[solarmax] Support configurable Device Address (#14366)
Signed-off-by: Jamie Townsend <jamie_townsend@hotmail.com>
This commit is contained in:
@@ -23,6 +23,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
public class SolarMaxConfiguration {
|
||||
public String host = ""; // this will always need to be overridden
|
||||
public int portNumber = 12345; // default value is 12345
|
||||
public int deviceAddress = 1; // default value is 1
|
||||
|
||||
public int refreshInterval = 15; // default value is 15
|
||||
}
|
||||
|
||||
@@ -72,8 +72,8 @@ public class SolarMaxHandler extends BaseThingHandler {
|
||||
* This is called to start the refresh job and also to reset that refresh job when a config change is done.
|
||||
*/
|
||||
private void configurePolling() {
|
||||
logger.debug("Polling data from {} at {}:{} every {} seconds ", getThing().getUID(), this.config.host,
|
||||
this.config.portNumber, this.config.refreshInterval);
|
||||
logger.debug("Polling data from {} at {}:{} (Device Address {}) every {} seconds ", getThing().getUID(),
|
||||
this.config.host, this.config.portNumber, this.config.deviceAddress, this.config.refreshInterval);
|
||||
if (this.config.refreshInterval > 0) {
|
||||
if (pollingJob == null || pollingJob.isCancelled()) {
|
||||
pollingJob = scheduler.scheduleWithFixedDelay(pollingRunnable, 0, this.config.refreshInterval,
|
||||
@@ -98,10 +98,12 @@ public class SolarMaxHandler extends BaseThingHandler {
|
||||
};
|
||||
|
||||
private synchronized void updateValuesFromDevice() {
|
||||
logger.debug("Updating data from {} at {}:{} ", getThing().getUID(), this.config.host, this.config.portNumber);
|
||||
logger.debug("Updating data from {} at {}:{} (Device Address {}) ", getThing().getUID(), this.config.host,
|
||||
this.config.portNumber, this.config.deviceAddress);
|
||||
// get the data from the SolarMax device
|
||||
try {
|
||||
SolarMaxData solarMaxData = SolarMaxConnector.getAllValuesFromSolarMax(config.host, config.portNumber);
|
||||
SolarMaxData solarMaxData = SolarMaxConnector.getAllValuesFromSolarMax(config.host, config.portNumber,
|
||||
this.config.deviceAddress);
|
||||
|
||||
if (solarMaxData.wasCommunicationSuccessful()) {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
|
||||
@@ -58,16 +58,17 @@ public class SolarMaxConnector {
|
||||
private static int responseTimeout = 10000;
|
||||
|
||||
/**
|
||||
* gets all known values from the SolarMax device addressable at host:port
|
||||
* gets all known values from the SolarMax device addressable at host:portNumber
|
||||
*
|
||||
* @param host hostname or ip address of the SolarMax device to be contacted
|
||||
* @param port port the SolarMax is listening on (default is 12345)
|
||||
* @param portNumber portNumber the SolarMax is listening on (default is 12345)
|
||||
* @param commandList a list of commands to be sent to the SolarMax device
|
||||
* @return
|
||||
* @throws UnknownHostException if the host is unknown
|
||||
* @throws SolarMaxException if some other exception occurs
|
||||
*/
|
||||
public static SolarMaxData getAllValuesFromSolarMax(final String host, int port) throws SolarMaxException {
|
||||
public static SolarMaxData getAllValuesFromSolarMax(final String host, final int portNumber,
|
||||
final int deviceAddress) throws SolarMaxException {
|
||||
List<SolarMaxCommandKey> commandList = new ArrayList<>();
|
||||
|
||||
for (SolarMaxCommandKey solarMaxCommandKey : SolarMaxCommandKey.values()) {
|
||||
@@ -81,7 +82,8 @@ public class SolarMaxConnector {
|
||||
// get the data from the SolarMax device. If we didn't get as many values back as we asked for, there were
|
||||
// communications problems, so set communicationSuccessful appropriately
|
||||
|
||||
Map<SolarMaxCommandKey, @Nullable String> valuesFromSolarMax = getValuesFromSolarMax(host, port, commandList);
|
||||
Map<SolarMaxCommandKey, @Nullable String> valuesFromSolarMax = getValuesFromSolarMax(host, portNumber,
|
||||
deviceAddress, commandList);
|
||||
boolean allCommandsAnswered = true;
|
||||
for (SolarMaxCommandKey solarMaxCommandKey : commandList) {
|
||||
if (!valuesFromSolarMax.containsKey(solarMaxCommandKey)) {
|
||||
@@ -97,17 +99,18 @@ public class SolarMaxConnector {
|
||||
}
|
||||
|
||||
/**
|
||||
* gets values from the SolarMax device addressable at host:port
|
||||
* gets values from the SolarMax device addressable at host:portNumber
|
||||
*
|
||||
* @param host hostname or ip address of the SolarMax device to be contacted
|
||||
* @param port port the SolarMax is listening on (default is 12345)
|
||||
* @param portNumber portNumber the SolarMax is listening on (default is 12345)
|
||||
* @param commandList a list of commands to be sent to the SolarMax device
|
||||
* @return
|
||||
* @throws UnknownHostException if the host is unknown
|
||||
* @throws SolarMaxException if some other exception occurs
|
||||
*/
|
||||
private static Map<SolarMaxCommandKey, @Nullable String> getValuesFromSolarMax(final String host, int port,
|
||||
final List<SolarMaxCommandKey> commandList) throws SolarMaxException {
|
||||
private static Map<SolarMaxCommandKey, @Nullable String> getValuesFromSolarMax(final String host,
|
||||
final int portNumber, final int deviceAddress, final List<SolarMaxCommandKey> commandList)
|
||||
throws SolarMaxException {
|
||||
Socket socket;
|
||||
|
||||
Map<SolarMaxCommandKey, @Nullable String> returnMap = new HashMap<>();
|
||||
@@ -120,7 +123,8 @@ public class SolarMaxConnector {
|
||||
requestsRequired = requestsRequired + 1;
|
||||
}
|
||||
for (int requestNumber = 0; requestNumber < requestsRequired; requestNumber++) {
|
||||
LOGGER.debug(" Requesting data from {}:{} with timeout of {}ms", host, port, responseTimeout);
|
||||
LOGGER.debug(" Requesting data from {}:{} (Device Address {}) with timeout of {}ms", host, portNumber,
|
||||
deviceAddress, responseTimeout);
|
||||
|
||||
int firstCommandNumber = requestNumber * maxConcurrentCommands;
|
||||
int lastCommandNumber = (requestNumber + 1) * maxConcurrentCommands;
|
||||
@@ -130,11 +134,11 @@ public class SolarMaxConnector {
|
||||
List<SolarMaxCommandKey> commandsToSend = commandList.subList(firstCommandNumber, lastCommandNumber);
|
||||
|
||||
try {
|
||||
socket = getSocketConnection(host, port);
|
||||
socket = getSocketConnection(host, portNumber);
|
||||
} catch (UnknownHostException e) {
|
||||
throw new SolarMaxConnectionException(e);
|
||||
}
|
||||
returnMap.putAll(getValuesFromSolarMax(socket, commandsToSend));
|
||||
returnMap.putAll(getValuesFromSolarMax(socket, deviceAddress, commandsToSend));
|
||||
|
||||
// SolarMax can't deal with requests too close to one another, so just wait a moment
|
||||
try {
|
||||
@@ -158,14 +162,14 @@ public class SolarMaxConnector {
|
||||
}
|
||||
|
||||
private static Map<SolarMaxCommandKey, @Nullable String> getValuesFromSolarMax(final Socket socket,
|
||||
final List<SolarMaxCommandKey> commandList) throws SolarMaxException {
|
||||
final int deviceAddress, final List<SolarMaxCommandKey> commandList) throws SolarMaxException {
|
||||
OutputStream outputStream = null;
|
||||
InputStream inputStream = null;
|
||||
try {
|
||||
outputStream = socket.getOutputStream();
|
||||
inputStream = socket.getInputStream();
|
||||
|
||||
return getValuesFromSolarMax(outputStream, inputStream, commandList);
|
||||
return getValuesFromSolarMax(outputStream, inputStream, deviceAddress, commandList);
|
||||
} catch (final SolarMaxException | IOException e) {
|
||||
throw new SolarMaxException("Error getting input/output streams from socket", e);
|
||||
} finally {
|
||||
@@ -184,10 +188,11 @@ public class SolarMaxConnector {
|
||||
}
|
||||
|
||||
private static Map<SolarMaxCommandKey, @Nullable String> getValuesFromSolarMax(final OutputStream outputStream,
|
||||
final InputStream inputStream, final List<SolarMaxCommandKey> commandList) throws SolarMaxException {
|
||||
final InputStream inputStream, final int deviceAddress, final List<SolarMaxCommandKey> commandList)
|
||||
throws SolarMaxException {
|
||||
Map<SolarMaxCommandKey, @Nullable String> returnedValues;
|
||||
String commandString = getCommandString(commandList);
|
||||
String request = contructRequest(commandString);
|
||||
String request = contructRequest(deviceAddress, commandString);
|
||||
try {
|
||||
LOGGER.trace(" ==>: {}", request);
|
||||
|
||||
@@ -273,30 +278,31 @@ public class SolarMaxConnector {
|
||||
return responseMap;
|
||||
}
|
||||
|
||||
private static Socket getSocketConnection(final String host, int port)
|
||||
private static Socket getSocketConnection(final String host, int portNumber)
|
||||
throws SolarMaxConnectionException, UnknownHostException {
|
||||
port = (port == 0) ? DEFAULT_PORT : port;
|
||||
portNumber = (portNumber == 0) ? DEFAULT_PORT : portNumber;
|
||||
|
||||
Socket socket;
|
||||
|
||||
try {
|
||||
socket = new Socket();
|
||||
socket.connect(new InetSocketAddress(host, port), CONNECTION_TIMEOUT);
|
||||
socket.connect(new InetSocketAddress(host, portNumber), CONNECTION_TIMEOUT);
|
||||
socket.setSoTimeout(responseTimeout);
|
||||
} catch (final UnknownHostException e) {
|
||||
throw e;
|
||||
} catch (final IOException e) {
|
||||
throw new SolarMaxConnectionException("Error connecting to port '" + port + "' on host '" + host + "'", e);
|
||||
throw new SolarMaxConnectionException(
|
||||
"Error connecting to portNumber '" + portNumber + "' on host '" + host + "'", e);
|
||||
}
|
||||
|
||||
return socket;
|
||||
}
|
||||
|
||||
public static boolean connectionTest(final String host, int port) throws UnknownHostException {
|
||||
public static boolean connectionTest(final String host, final int portNumber) throws UnknownHostException {
|
||||
Socket socket = null;
|
||||
|
||||
try {
|
||||
socket = getSocketConnection(host, port);
|
||||
socket = getSocketConnection(host, portNumber);
|
||||
} catch (SolarMaxConnectionException e) {
|
||||
return false;
|
||||
} finally {
|
||||
@@ -331,9 +337,9 @@ public class SolarMaxConnector {
|
||||
* @param questions appears to be able to handle multiple commands. For now, one at a time is good fishing
|
||||
* @return the request to be sent to the SolarMax device
|
||||
*/
|
||||
static String contructRequest(final String questions) {
|
||||
static String contructRequest(final int deviceAddress, final String questions) {
|
||||
String src = "FB";
|
||||
String dstHex = String.format("%02X", 1); // destinationDevice defaults to 1 and is ignored with TCP/IP
|
||||
String dstHex = String.format("%02X", deviceAddress); // destinationDevice defaults to 1
|
||||
String len = "00";
|
||||
String cs = "0000";
|
||||
String msg = "64:" + questions;
|
||||
|
||||
@@ -10,9 +10,11 @@ thing-type.solarmax.inverter.description = Basic thing for the SolarMax Power In
|
||||
|
||||
# thing types config
|
||||
|
||||
thing-type.config.solarmax.inverter.deviceAddress.label = Device Address
|
||||
thing-type.config.solarmax.inverter.deviceAddress.description = Device address for devices connected serially (defaults to 1)
|
||||
thing-type.config.solarmax.inverter.host.label = Host
|
||||
thing-type.config.solarmax.inverter.host.description = Hostname or IP Address
|
||||
thing-type.config.solarmax.inverter.portNumber.label = Port
|
||||
thing-type.config.solarmax.inverter.portNumber.label = Port Number
|
||||
thing-type.config.solarmax.inverter.portNumber.description = Port Number (defaults to 12345)
|
||||
thing-type.config.solarmax.inverter.refreshInterval.label = Refresh Interval
|
||||
thing-type.config.solarmax.inverter.refreshInterval.description = Refresh Interval in seconds (defaults to 15)
|
||||
|
||||
@@ -37,10 +37,15 @@
|
||||
<description>Hostname or IP Address</description>
|
||||
</parameter>
|
||||
<parameter name="portNumber" type="integer" required="false">
|
||||
<label>Port</label>
|
||||
<label>Port Number</label>
|
||||
<description>Port Number (defaults to 12345)</description>
|
||||
<default>12345</default>
|
||||
</parameter>
|
||||
<parameter name="deviceAddress" type="integer" required="false">
|
||||
<label>Device Address</label>
|
||||
<description>Device address for devices connected serially (defaults to 1)</description>
|
||||
<default>1</default>
|
||||
</parameter>
|
||||
<parameter name="refreshInterval" type="integer" required="false">
|
||||
<label>Refresh Interval</label>
|
||||
<description>Refresh Interval in seconds (defaults to 15)</description>
|
||||
|
||||
@@ -42,6 +42,7 @@ public class SolarmaxConnectorFindCommands {
|
||||
|
||||
private static final String HOST = "192.168.1.151";
|
||||
private static final int PORT = 12345;
|
||||
private static final int DEVICE_ADDRESS = 1;
|
||||
private static final int CONNECTION_TIMEOUT = 1000; // ms
|
||||
|
||||
@Test
|
||||
@@ -127,7 +128,7 @@ public class SolarmaxConnectorFindCommands {
|
||||
|
||||
Map<String, @Nullable String> responseMap = null;
|
||||
|
||||
responseMap = getValuesFromSolarMax(HOST, PORT, commands);
|
||||
responseMap = getValuesFromSolarMax(HOST, PORT, DEVICE_ADDRESS, commands);
|
||||
|
||||
if (responseMap.containsKey(command)) {
|
||||
LOGGER.debug("Request: " + command + " Valid Response: " + responseMap.get(command));
|
||||
@@ -139,8 +140,8 @@ public class SolarmaxConnectorFindCommands {
|
||||
/**
|
||||
* based on SolarMaxConnector.getValuesFromSolarMax
|
||||
*/
|
||||
private static Map<String, @Nullable String> getValuesFromSolarMax(final String host, int port,
|
||||
final List<String> commandList) throws SolarMaxException {
|
||||
private static Map<String, @Nullable String> getValuesFromSolarMax(final String host, final int portNumber,
|
||||
final int deviceAddress, final List<String> commandList) throws SolarMaxException {
|
||||
Socket socket;
|
||||
|
||||
Map<String, @Nullable String> returnMap = new HashMap<>();
|
||||
@@ -153,7 +154,7 @@ public class SolarmaxConnectorFindCommands {
|
||||
requestsRequired = requestsRequired + 1;
|
||||
}
|
||||
for (int requestNumber = 0; requestNumber < requestsRequired; requestNumber++) {
|
||||
LOGGER.debug(" Requesting data from {}:{} with timeout of {}ms", host, port, CONNECTION_TIMEOUT);
|
||||
LOGGER.debug(" Requesting data from {}:{} with timeout of {}ms", host, portNumber, CONNECTION_TIMEOUT);
|
||||
|
||||
int firstCommandNumber = requestNumber * maxConcurrentCommands;
|
||||
int lastCommandNumber = (requestNumber + 1) * maxConcurrentCommands;
|
||||
@@ -163,11 +164,11 @@ public class SolarmaxConnectorFindCommands {
|
||||
List<String> commandsToSend = commandList.subList(firstCommandNumber, lastCommandNumber);
|
||||
|
||||
try {
|
||||
socket = getSocketConnection(host, port);
|
||||
socket = getSocketConnection(host, portNumber);
|
||||
} catch (UnknownHostException e) {
|
||||
throw new SolarMaxConnectionException(e);
|
||||
}
|
||||
returnMap.putAll(getValuesFromSolarMax(socket, commandsToSend));
|
||||
returnMap.putAll(getValuesFromSolarMax(socket, deviceAddress, commandsToSend));
|
||||
|
||||
// SolarMax can't deal with requests too close to one another, so just wait a moment
|
||||
try {
|
||||
@@ -179,7 +180,7 @@ public class SolarmaxConnectorFindCommands {
|
||||
return returnMap;
|
||||
}
|
||||
|
||||
private static Map<String, @Nullable String> getValuesFromSolarMax(final Socket socket,
|
||||
private static Map<String, @Nullable String> getValuesFromSolarMax(final Socket socket, final int deviceAddress,
|
||||
final List<String> commandList) throws SolarMaxException {
|
||||
OutputStream outputStream = null;
|
||||
InputStream inputStream = null;
|
||||
@@ -187,7 +188,7 @@ public class SolarmaxConnectorFindCommands {
|
||||
outputStream = socket.getOutputStream();
|
||||
inputStream = socket.getInputStream();
|
||||
|
||||
return getValuesFromSolarMax(outputStream, inputStream, commandList);
|
||||
return getValuesFromSolarMax(outputStream, inputStream, deviceAddress, commandList);
|
||||
} catch (final SolarMaxException | IOException e) {
|
||||
throw new SolarMaxException("Error getting input/output streams from socket", e);
|
||||
} finally {
|
||||
@@ -231,32 +232,34 @@ public class SolarmaxConnectorFindCommands {
|
||||
return characters;
|
||||
}
|
||||
|
||||
private static Socket getSocketConnection(final String host, int port)
|
||||
private static Socket getSocketConnection(final String host, int portNumber)
|
||||
throws SolarMaxConnectionException, UnknownHostException {
|
||||
port = (port == 0) ? SolarmaxConnectorFindCommands.PORT : port;
|
||||
portNumber = (portNumber == 0) ? PORT : portNumber;
|
||||
|
||||
Socket socket;
|
||||
|
||||
try {
|
||||
socket = new Socket();
|
||||
LOGGER.debug(" Connecting to " + host + ":" + port + " with a timeout of " + CONNECTION_TIMEOUT);
|
||||
socket.connect(new InetSocketAddress(host, port), CONNECTION_TIMEOUT);
|
||||
LOGGER.debug(" Connecting to " + host + ":" + portNumber + " with a timeout of " + CONNECTION_TIMEOUT);
|
||||
socket.connect(new InetSocketAddress(host, portNumber), CONNECTION_TIMEOUT);
|
||||
LOGGER.debug(" Connected.");
|
||||
socket.setSoTimeout(CONNECTION_TIMEOUT);
|
||||
} catch (final UnknownHostException e) {
|
||||
throw e;
|
||||
} catch (final IOException e) {
|
||||
throw new SolarMaxConnectionException("Error connecting to port '" + port + "' on host '" + host + "'", e);
|
||||
throw new SolarMaxConnectionException(
|
||||
"Error connecting to port '" + portNumber + "' on host '" + host + "'", e);
|
||||
}
|
||||
|
||||
return socket;
|
||||
}
|
||||
|
||||
private static Map<String, @Nullable String> getValuesFromSolarMax(final OutputStream outputStream,
|
||||
final InputStream inputStream, final List<String> commandList) throws SolarMaxException {
|
||||
final InputStream inputStream, final int deviceAddress, final List<String> commandList)
|
||||
throws SolarMaxException {
|
||||
Map<String, @Nullable String> returnedValues;
|
||||
String commandString = getCommandString(commandList);
|
||||
String request = SolarMaxConnector.contructRequest(commandString);
|
||||
String request = SolarMaxConnector.contructRequest(deviceAddress, commandString);
|
||||
try {
|
||||
LOGGER.trace(" ==>: {}", request);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user