/** {@inheritDoc} */ @Override public void internalReceiveCommand(String itemName, Command command) { logger.debug("Received command from {}", itemName); // resolve serial number for item String serialNumber = null; for (MaxCubeBindingProvider provider : providers) { serialNumber = provider.getSerialNumber(itemName); if (StringUtils.isBlank(serialNumber)) { continue; } // send command to MAX!Cube LAN Gateway Device device = findDevice(serialNumber, devices); if (device == null) { logger.debug( "Cannot send command to device with serial number {}, device not listed.", serialNumber); continue; } String rfAddress = device.getRFAddress(); String commandString = null; if (command instanceof DecimalType || command instanceof OnOffType) { DecimalType decimalType = DEFAULT_OFF_TEMPERATURE; if (command instanceof DecimalType) { decimalType = (DecimalType) command; } else if (command instanceof OnOffType) { decimalType = OnOffType.ON.equals(command) ? DEFAULT_ON_TEMPERATURE : DEFAULT_OFF_TEMPERATURE; } S_Command cmd = new S_Command( rfAddress, device.getRoomId(), ((HeatingThermostat) device).getMode(), decimalType.doubleValue()); commandString = cmd.getCommandString(); } else if (command instanceof StringType) { String commandContent = command.toString().trim().toUpperCase(); S_Command cmd = null; ThermostatModeType commandThermoType = null; if (commandContent.contentEquals(ThermostatModeType.AUTOMATIC.toString())) { commandThermoType = ThermostatModeType.AUTOMATIC; cmd = new S_Command(rfAddress, device.getRoomId(), commandThermoType); } else if (commandContent.contentEquals(ThermostatModeType.BOOST.toString())) { commandThermoType = ThermostatModeType.BOOST; Double setTemp = Double.parseDouble(((HeatingThermostat) device).getTemperatureSetpoint().toString()); cmd = new S_Command(rfAddress, device.getRoomId(), commandThermoType, setTemp); } else if (commandContent.contentEquals(ThermostatModeType.MANUAL.toString())) { commandThermoType = ThermostatModeType.MANUAL; Double setTemp = Double.parseDouble(((HeatingThermostat) device).getTemperatureSetpoint().toString()); cmd = new S_Command(rfAddress, device.getRoomId(), commandThermoType, setTemp); logger.debug("updates to MANUAL mode with temperature '{}'", setTemp); } else { logger.debug( "Only updates to AUTOMATIC, MANUAL & BOOST supported, received value ;'{}'", commandContent); continue; } commandString = cmd.getCommandString(); } if (commandString != null) { try { if (socket == null) { this.socketConnect(); } writer.write(commandString); logger.debug(commandString); writer.flush(); Message message = null; String raw = reader.readLine(); try { while (!this.messageProcessor.isMessageAvailable()) { this.messageProcessor.addReceivedLine(raw); raw = reader.readLine(); } message = this.messageProcessor.pull(); } catch (Exception e) { logger.info("Error while handling response from MAX! Cube lan gateway!"); logger.debug(Utils.getStackTrace(e)); this.messageProcessor.reset(); } if (message != null) { if (message.getType() == MessageType.S) { sMessageProcessing((S_Message) message); } } if (!exclusive) { socket.close(); socket = null; } } catch (UnknownHostException e) { logger.info( "Host error occurred while connecting to MAX! Cube lan gateway '{}': {}", ip, e.getMessage()); socketClose(); } catch (IOException e) { logger.info( "IO error occurred while writing to MAX! Cube lan gateway '{}': {}", ip, e.getMessage()); socketClose(); // reconnect on next execution } catch (Exception e) { logger.info( "Error occurred while writing to MAX! Cube lan gateway '{}': {}", ip, e.getMessage()); logger.info(Utils.getStackTrace(e)); socketClose(); // reconnect on next execution } logger.debug("Command Sent to {}", ip); } else { logger.debug("Null Command not sent to {}", ip); } } }
/** {@inheritDoc} */ @Override public synchronized void execute() { if (ip == null) { logger.debug("Update prior to completion of interface IP configuration"); return; } try { String raw = null; if (maxRequestsPerConnection > 0 && requestCount >= maxRequestsPerConnection) { logger.debug("maxRequestsPerConnection reached, reconnecting."); socket.close(); this.socketConnect(); } if (socket == null) { this.socketConnect(); } else { /* * if the connection is already open (this happens in exclusive mode), just send a "l:\r\n" to get the * latest live informations * note that "L:\r\n" or "l:\n" would not work. */ logger.debug("Sending state request #" + this.requestCount + " to Maxcube"); writer.write("l:" + '\r' + '\n'); writer.flush(); requestCount++; } boolean cont = true; while (cont) { raw = reader.readLine(); if (raw == null) { cont = false; continue; } Message message = null; try { this.messageProcessor.addReceivedLine(raw); if (this.messageProcessor.isMessageAvailable()) { message = this.messageProcessor.pull(); } else { continue; } message.debug(logger); if (message != null) { message.debug(logger); if (message.getType() == MessageType.M) { M_Message msg = (M_Message) message; for (DeviceInformation di : msg.devices) { Configuration c = null; for (Configuration conf : configurations) { if (conf.getSerialNumber().equalsIgnoreCase(di.getSerialNumber())) { c = conf; break; } } if (c != null) { configurations.remove(c); } c = Configuration.create(di); configurations.add(c); c.setRoomId(di.getRoomId()); } } else if (message.getType() == MessageType.C) { Configuration c = null; for (Configuration conf : configurations) { if (conf.getSerialNumber() .equalsIgnoreCase(((C_Message) message).getSerialNumber())) { c = conf; break; } } if (c == null) { configurations.add(Configuration.create(message)); } else { c.setValues((C_Message) message); } } else if (message.getType() == MessageType.S) { sMessageProcessing((S_Message) message); cont = false; } else if (message.getType() == MessageType.L) { ((L_Message) message).updateDevices(devices, configurations); logger.debug("{} devices found.", devices.size()); // the L message is the last one, while the reader // would hang trying to read a new line and // eventually the // cube will fail to establish // new connections for some time cont = false; } } } catch (IncorrectMultilineIndexException ex) { logger.info( "Incorrect MAX!Cube multiline message detected. Stopping processing and continue with next Line."); this.messageProcessor.reset(); } catch (NoMessageAvailableException ex) { logger.info( "Could not process MAX!Cube message. Stopping processing and continue with next Line."); this.messageProcessor.reset(); } catch (IncompleteMessageException ex) { logger.info( "Error while parsing MAX!Cube multiline message. Stopping processing, and continue with next Line."); this.messageProcessor.reset(); } catch (UnprocessableMessageException ex) { logger.info( "Error while parsing MAX!Cube message. Stopping processing, and continue with next Line."); this.messageProcessor.reset(); } catch (UnsupportedMessageTypeException ex) { logger.info( "Unsupported MAX!Cube message detected. Ignoring and continue with next Line."); this.messageProcessor.reset(); } catch (MessageIsWaitingException ex) { logger.info( "There was and unhandled message waiting. Ignoring and continue with next Line."); this.messageProcessor.reset(); } catch (Exception e) { logger.info("Failed to process message received by MAX! protocol."); logger.debug(Utils.getStackTrace(e)); this.messageProcessor.reset(); } } if (!exclusive) { socketClose(); } for (MaxCubeBindingProvider provider : providers) { for (String itemName : provider.getItemNames()) { String serialNumber = provider.getSerialNumber(itemName); Device device = findDevice(serialNumber, devices); if (device == null) { logger.info("Cannot find MAX!cube device with serial number '{}'", serialNumber); logAvailableMaxDevices(); continue; } // all devices have a battery state, so this is type-independent if (provider.getBindingType(itemName) == BindingType.BATTERY) { if (device.battery().isChargeUpdated()) { eventPublisher.postUpdate(itemName, device.battery().getCharge()); } } else if (provider.getBindingType(itemName) == BindingType.CONNECTION_ERROR) { if (device.isErrorUpdated()) { OnOffType connectionError = device.isError() ? OnOffType.ON : OnOffType.OFF; eventPublisher.postUpdate(itemName, connectionError); } } else { switch (device.getType()) { case HeatingThermostatPlus: case HeatingThermostat: if (provider.getBindingType(itemName) == BindingType.VALVE && ((HeatingThermostat) device).isValvePositionUpdated()) { eventPublisher.postUpdate( itemName, ((HeatingThermostat) device).getValvePosition()); break; } // omitted break, fall through case WallMountedThermostat: // and also HeatingThermostat if (provider.getBindingType(itemName) == BindingType.MODE && ((HeatingThermostat) device).isModeUpdated()) { eventPublisher.postUpdate(itemName, ((HeatingThermostat) device).getModeString()); } else if (provider.getBindingType(itemName) == BindingType.ACTUAL && ((HeatingThermostat) device).isTemperatureActualUpdated()) { eventPublisher.postUpdate( itemName, ((HeatingThermostat) device).getTemperatureActual()); } else if (((HeatingThermostat) device).isTemperatureSetpointUpdated() && provider.getBindingType(itemName) == null) { eventPublisher.postUpdate( itemName, ((HeatingThermostat) device).getTemperatureSetpoint()); } break; case ShutterContact: if (((ShutterContact) device).isShutterStateUpdated()) { eventPublisher.postUpdate(itemName, ((ShutterContact) device).getShutterState()); } break; default: // no further devices supported yet } } } } } catch (UnknownHostException e) { logger.info( "Host error occurred while connecting to MAX! Cube lan gateway '{}': {}", ip, e.getMessage()); socketClose(); } catch (IOException e) { logger.info( "IO error occurred while connecting to MAX! Cube lan gateway '{}': {}", ip, e.getMessage()); socketClose(); // reconnect on next execution } catch (Exception e) { logger.info( "Error occurred while connecting to MAX! Cube lan gateway '{}': {}", ip, e.getMessage()); logger.info(Utils.getStackTrace(e)); socketClose(); // reconnect on next execution } }