use of org.openhab.binding.maxcul.MaxCulBindingProvider in project openhab1-addons by openhab.
the class MaxCulBinding method internalReceiveCommand.
/**
* @{inheritDoc
*/
@Override
protected void internalReceiveCommand(final String itemName, Command command) {
Timer pairModeTimer = null;
MaxCulBindingConfig bindingConfig = null;
for (MaxCulBindingProvider provider : super.providers) {
bindingConfig = provider.getConfigForItemName(itemName);
if (bindingConfig != null) {
break;
}
}
logger.debug("Received command " + command.toString() + " for item " + itemName);
if (bindingConfig != null) {
logger.debug("Found config for " + itemName);
switch(bindingConfig.getDeviceType()) {
case PAIR_MODE:
if ((command instanceof OnOffType)) {
switch((OnOffType) command) {
case ON:
/*
* turn on pair mode and schedule disabling of pairing
* mode
*/
pairMode = true;
TimerTask task = new TimerTask() {
@Override
public void run() {
logger.debug(itemName + " pairMode timeout executed");
pairMode = false;
eventPublisher.postUpdate(itemName, OnOffType.OFF);
}
};
pairModeTimer = timers.get(itemName);
if (pairModeTimer != null) {
pairModeTimer.cancel();
timers.remove(itemName);
}
pairModeTimer = new Timer();
timers.put(itemName, pairModeTimer);
pairModeTimer.schedule(task, pairModeTimeout);
logger.debug(itemName + " pairMode enabled & timeout scheduled");
break;
case OFF:
/*
* we are manually disabling, so clear the timer and the
* flag
*/
pairMode = false;
pairModeTimer = timers.get(itemName);
if (pairModeTimer != null) {
logger.debug(itemName + " pairMode timer cancelled");
pairModeTimer.cancel();
timers.remove(itemName);
}
logger.debug(itemName + " pairMode cleared");
break;
}
} else {
logger.warn("Command not handled for " + bindingConfig.getDeviceType() + " that is not OnOffType");
}
break;
case LISTEN_MODE:
if (command instanceof OnOffType) {
this.messageHandler.setListenMode(((OnOffType) command == OnOffType.ON));
} else {
logger.warn("Command not handled for " + bindingConfig.getDeviceType() + " that is not OnOffType");
}
break;
case LED_MODE:
if (command instanceof OnOffType) {
this.messageHandler.setLedMode(((OnOffType) command == OnOffType.ON));
} else {
logger.warn("Command not handled for " + bindingConfig.getDeviceType() + " that is not OnOffType");
}
break;
case RADIATOR_THERMOSTAT:
case RADIATOR_THERMOSTAT_PLUS:
case WALL_THERMOSTAT:
if (bindingConfig.getFeature() == MaxCulFeature.THERMOSTAT) {
/* clear out old pacing timer */
if (pacedBindingTransmitTimers.containsKey(bindingConfig)) {
pacedBindingTransmitTimers.get(bindingConfig).cancel();
pacedBindingTransmitTimers.remove(bindingConfig);
}
/* schedule new timer */
Timer pacingTimer = new Timer();
pacedBindingTransmitTimers.put(bindingConfig, pacingTimer);
pacingTimer.schedule(new MaxCulPacedThermostatTransmitTask(command, bindingConfig, messageHandler, super.providers), PACED_TRANSMIT_TIME);
} else if (bindingConfig.getFeature() == MaxCulFeature.DISPLAYSETTING) {
messageHandler.sendSetDisplayActualTemp(bindingConfig.getDevAddr(), ((OnOffType) command == OnOffType.ON));
} else if (bindingConfig.getFeature() == MaxCulFeature.RESET) {
messageHandler.sendReset(bindingConfig.getDevAddr());
} else {
logger.warn("Command not handled for " + bindingConfig.getDeviceType() + " that is not OnOffType or DecimalType");
}
break;
case SHUTTER_CONTACT:
if (bindingConfig.getFeature() == MaxCulFeature.RESET) {
messageHandler.sendReset(bindingConfig.getDevAddr());
}
break;
default:
logger.warn("Command not handled for " + bindingConfig.getDeviceType());
break;
}
}
updateCreditMonitors();
}
use of org.openhab.binding.maxcul.MaxCulBindingProvider in project openhab1-addons by openhab.
the class MaxCulBinding method updateCreditMonitors.
private void updateCreditMonitors() {
/* find and update credit monitor binding if it exists */
int credit10ms = messageHandler.getCreditStatus();
for (MaxCulBindingProvider provider : super.providers) {
Collection<MaxCulBindingConfig> bindingConfigs = provider.getCreditMonitorBindings();
for (MaxCulBindingConfig bc : bindingConfigs) {
String itemName = provider.getItemNameForConfig(bc);
eventPublisher.postUpdate(itemName, new DecimalType(credit10ms));
}
}
}
use of org.openhab.binding.maxcul.MaxCulBindingProvider in project openhab1-addons by openhab.
the class MaxCulMsgHandler method dataReceived.
@Override
public void dataReceived(String data) {
logger.debug("MaxCulSender Received " + data);
if (data.startsWith("Z")) {
if (listenMode) {
listenModeHandler(data);
return;
}
/* Check message is destined for us */
if (BaseMsg.isForUs(data, srcAddr)) {
boolean passToBinding = true;
/* Handle Internal Messages */
MaxCulMsgType msgType = BaseMsg.getMsgType(data);
if (msgType == MaxCulMsgType.ACK) {
passToBinding = false;
AckMsg msg = new AckMsg(data);
if (pendingAckQueue.containsKey(msg.msgCount) && msg.dstAddrStr.compareTo(srcAddr) == 0) {
SenderQueueItem qi = pendingAckQueue.remove(msg.msgCount);
/* verify ACK */
if ((qi.msg.dstAddrStr.equalsIgnoreCase(msg.srcAddrStr)) && (qi.msg.srcAddrStr.equalsIgnoreCase(msg.dstAddrStr))) {
if (msg.getIsNack()) {
/* NAK'd! */
// TODO resend?
logger.error("Message was NAK'd, packet lost");
} else {
logger.debug("Message " + msg.msgCount + " ACK'd ok!");
}
}
} else {
logger.info("Got ACK for message " + msg.msgCount + " but it wasn't in the queue");
}
}
if (sequenceRegister.containsKey(new BaseMsg(data).msgCount)) {
passToBinding = false;
/*
* message found in sequence register, so it will be handled
* by the sequence
*/
BaseMsg bMsg = new BaseMsg(data);
logger.debug("Message " + bMsg.msgCount + " is part of sequence. Running next step in sequence.");
sequenceRegister.get(bMsg.msgCount).runSequencer(bMsg);
sequenceRegister.remove(bMsg.msgCount);
}
if (passToBinding) {
/* pass data to binding for processing */
this.mcbmp.maxCulMsgReceived(data, false);
}
} else if (BaseMsg.isForUs(data, "000000")) {
switch(BaseMsg.getMsgType(data)) {
case PAIR_PING:
case WALL_THERMOSTAT_CONTROL:
case THERMOSTAT_STATE:
case WALL_THERMOSTAT_STATE:
this.mcbmp.maxCulMsgReceived(data, true);
break;
default:
/* TODO handle other broadcast */
logger.debug("Unhandled broadcast message of type " + BaseMsg.getMsgType(data).toString());
break;
}
} else {
// Associated devices send messages that tell of their status to
// the associated
// device. We need to spy on devices we know about to extract
// useful data
boolean passToBinding = false;
BaseMsg bMsg = new BaseMsg(data);
for (MaxCulBindingProvider provider : providers) {
// look up source device configs
List<MaxCulBindingConfig> configs = provider.getConfigsForRadioAddr(bMsg.srcAddrStr);
if (!configs.isEmpty()) {
// get asssociated devices with source device
String serialNum = configs.get(0).getSerialNumber();
HashSet<MaxCulBindingConfig> assocDevs = provider.getAssociations(serialNum);
if (!assocDevs.isEmpty()) {
// message dest
for (MaxCulBindingConfig device : assocDevs) {
if (device.getDevAddr().equalsIgnoreCase(bMsg.dstAddrStr)) {
passToBinding = true;
break;
}
}
}
}
}
if (passToBinding && (BaseMsg.getMsgType(data) != MaxCulMsgType.PAIR_PING && BaseMsg.getMsgType(data) != MaxCulMsgType.ACK)) {
/*
* pass data to binding for processing - pretend it is
* broadcast so as not to ACK
*/
this.mcbmp.maxCulMsgReceived(data, true);
}
}
}
}
use of org.openhab.binding.maxcul.MaxCulBindingProvider in project openhab1-addons by openhab.
the class MaxCulBinding method maxCulMsgReceived.
@Override
public void maxCulMsgReceived(String data, boolean isBroadcast) {
logger.debug("Received data from CUL: " + data);
MaxCulMsgType msgType = BaseMsg.getMsgType(data);
/*
* Check if it's broadcast and we're in pair mode or a PAIR_PING message
* directly for us
*/
if (((pairMode && isBroadcast) || !isBroadcast) && msgType == MaxCulMsgType.PAIR_PING) {
logger.debug("Got PAIR_PING message");
MaxCulBindingConfig configWithTempsConfig = null;
/* process packet */
PairPingMsg pkt = new PairPingMsg(data);
/* Match serial number to binding configuration */
Collection<MaxCulBindingConfig> bindingConfigs = getBindingsBySerial(pkt.serial);
/*
* only respond and set pairing info if we found at least one
* binding config
*/
if (bindingConfigs != null) {
logger.debug("Found " + bindingConfigs.size() + " configs for " + pkt.serial);
for (MaxCulBindingConfig bc : bindingConfigs) {
/* Set pairing information */
bc.setPairedInfo(pkt.srcAddrStr);
/*
* where it came from gives
* the addr of the device
*/
if (bc.isTemperatureConfigSet() && configWithTempsConfig == null) {
configWithTempsConfig = bc;
}
}
/* if none have values set then send default from first config */
if (configWithTempsConfig == null) {
logger.debug("Using default temperature configuration from config 0");
configWithTempsConfig = (MaxCulBindingConfig) bindingConfigs.toArray()[0];
}
/* get device associations */
HashSet<MaxCulBindingConfig> associations = null;
for (MaxCulBindingProvider provider : super.providers) {
associations = provider.getAssociations(configWithTempsConfig.getSerialNumber());
if (associations != null && associations.isEmpty() == false) {
logger.debug("Found associations");
break;
}
}
/* start the initialisation sequence */
logger.debug("Creating pairing sequencer");
PairingInitialisationSequence ps = new PairingInitialisationSequence(this.DEFAULT_GROUP_ID, messageHandler, configWithTempsConfig, associations);
messageHandler.startSequence(ps, pkt);
} else {
logger.error("Pairing failed: Unable to find binding config for device " + pkt.serial);
}
} else {
switch(msgType) {
/*
* TODO there are other incoming messages that aren't handled that
* could be
*/
case WALL_THERMOSTAT_CONTROL:
WallThermostatControlMsg wallThermCtrlMsg = new WallThermostatControlMsg(data);
wallThermCtrlMsg.printMessage();
for (MaxCulBindingProvider provider : super.providers) {
Collection<MaxCulBindingConfig> bindingConfigs = provider.getConfigsForRadioAddr(wallThermCtrlMsg.srcAddrStr);
for (MaxCulBindingConfig bc : bindingConfigs) {
if (bc.getFeature() == MaxCulFeature.THERMOSTAT && wallThermCtrlMsg.getDesiredTemperature() != null) {
String itemName = provider.getItemNameForConfig(bc);
eventPublisher.postUpdate(itemName, new DecimalType(wallThermCtrlMsg.getDesiredTemperature()));
} else if (bc.getFeature() == MaxCulFeature.TEMPERATURE && wallThermCtrlMsg.getMeasuredTemperature() != null) {
String itemName = provider.getItemNameForConfig(bc);
eventPublisher.postUpdate(itemName, new DecimalType(wallThermCtrlMsg.getMeasuredTemperature()));
}
// TODO switch mode between manual/automatic?
}
}
/* reply only if not broadcast */
if (isBroadcast == false) {
this.messageHandler.sendAck(wallThermCtrlMsg);
}
break;
case SET_TEMPERATURE:
SetTemperatureMsg setTempMsg = new SetTemperatureMsg(data);
setTempMsg.printMessage();
for (MaxCulBindingProvider provider : super.providers) {
Collection<MaxCulBindingConfig> bindingConfigs = provider.getConfigsForRadioAddr(setTempMsg.srcAddrStr);
for (MaxCulBindingConfig bc : bindingConfigs) {
if (bc.getFeature() == MaxCulFeature.THERMOSTAT) {
String itemName = provider.getItemNameForConfig(bc);
eventPublisher.postUpdate(itemName, new DecimalType(setTempMsg.getDesiredTemperature()));
}
// TODO switch mode between manual/automatic?
}
}
/* respond to device */
if (isBroadcast == false) {
this.messageHandler.sendAck(setTempMsg);
}
break;
case THERMOSTAT_STATE:
ThermostatStateMsg thermStateMsg = new ThermostatStateMsg(data);
thermStateMsg.printMessage();
for (MaxCulBindingProvider provider : super.providers) {
Collection<MaxCulBindingConfig> bindingConfigs = provider.getConfigsForRadioAddr(thermStateMsg.srcAddrStr);
for (MaxCulBindingConfig bc : bindingConfigs) {
String itemName = provider.getItemNameForConfig(bc);
if (bc.getFeature() == MaxCulFeature.THERMOSTAT && thermStateMsg.getDesiredTemperature() != null) {
eventPublisher.postUpdate(itemName, new DecimalType(thermStateMsg.getDesiredTemperature()));
} else if (bc.getFeature() == MaxCulFeature.TEMPERATURE && thermStateMsg.getMeasuredTemperature() != null) {
eventPublisher.postUpdate(itemName, new DecimalType(thermStateMsg.getMeasuredTemperature()));
} else if (bc.getFeature() == MaxCulFeature.BATTERY) {
eventPublisher.postUpdate(itemName, thermStateMsg.getBatteryLow() ? OnOffType.ON : OnOffType.OFF);
} else if (bc.getFeature() == MaxCulFeature.MODE) {
eventPublisher.postUpdate(itemName, new DecimalType(thermStateMsg.getControlMode().toInt()));
} else if (bc.getFeature() == MaxCulFeature.VALVE_POS) {
eventPublisher.postUpdate(itemName, new DecimalType(thermStateMsg.getValvePos()));
}
// TODO switch mode between manual/automatic?
}
}
/* respond to device */
if (isBroadcast == false) {
this.messageHandler.sendAck(thermStateMsg);
}
break;
case WALL_THERMOSTAT_STATE:
WallThermostatStateMsg wallThermStateMsg = new WallThermostatStateMsg(data);
wallThermStateMsg.printMessage();
for (MaxCulBindingProvider provider : super.providers) {
Collection<MaxCulBindingConfig> bindingConfigs = provider.getConfigsForRadioAddr(wallThermStateMsg.srcAddrStr);
for (MaxCulBindingConfig bc : bindingConfigs) {
String itemName = provider.getItemNameForConfig(bc);
if (bc.getFeature() == MaxCulFeature.THERMOSTAT && wallThermStateMsg.getDesiredTemperature() != null) {
eventPublisher.postUpdate(itemName, new DecimalType(wallThermStateMsg.getDesiredTemperature()));
} else if (bc.getFeature() == MaxCulFeature.TEMPERATURE && wallThermStateMsg.getMeasuredTemperature() != null) {
eventPublisher.postUpdate(itemName, new DecimalType(wallThermStateMsg.getMeasuredTemperature()));
} else if (bc.getFeature() == MaxCulFeature.BATTERY) {
eventPublisher.postUpdate(itemName, wallThermStateMsg.getBatteryLow() ? OnOffType.ON : OnOffType.OFF);
} else if (bc.getFeature() == MaxCulFeature.MODE) {
eventPublisher.postUpdate(itemName, new DecimalType(wallThermStateMsg.getControlMode().toInt()));
}
}
}
/* respond to device */
if (isBroadcast == false) {
this.messageHandler.sendAck(wallThermStateMsg);
}
break;
case TIME_INFO:
TimeInfoMsg timeMsg = new TimeInfoMsg(data);
timeMsg.printMessage();
TimeUpdateRequestSequence timeSeq = new TimeUpdateRequestSequence(this.tzStr, messageHandler);
messageHandler.startSequence(timeSeq, timeMsg);
break;
case PUSH_BUTTON_STATE:
PushButtonMsg pbMsg = new PushButtonMsg(data);
pbMsg.printMessage();
for (MaxCulBindingProvider provider : super.providers) {
Collection<MaxCulBindingConfig> bindingConfigs = provider.getConfigsForRadioAddr(pbMsg.srcAddrStr);
for (MaxCulBindingConfig bc : bindingConfigs) {
String itemName = provider.getItemNameForConfig(bc);
if (bc.getFeature() == MaxCulFeature.SWITCH) {
// 'AUTO' maps to 'ON' and 'ECO' maps to 'OFF'
eventPublisher.postUpdate(itemName, pbMsg.getMode() == PushButtonMode.AUTO ? OnOffType.ON : OnOffType.OFF);
} else if (bc.getFeature() == MaxCulFeature.BATTERY) {
eventPublisher.postUpdate(itemName, pbMsg.getBatteryLow() ? OnOffType.ON : OnOffType.OFF);
}
}
}
if (isBroadcast == false) {
this.messageHandler.sendAck(pbMsg);
}
break;
case SHUTTER_CONTACT_STATE:
ShutterContactStateMsg shutterContactStateMsg = new ShutterContactStateMsg(data);
shutterContactStateMsg.printMessage();
for (MaxCulBindingProvider provider : super.providers) {
Collection<MaxCulBindingConfig> bindingConfigs = provider.getConfigsForRadioAddr(shutterContactStateMsg.srcAddrStr);
for (MaxCulBindingConfig bc : bindingConfigs) {
String itemName = provider.getItemNameForConfig(bc);
if (bc.getFeature() == MaxCulFeature.CONTACT) {
if (shutterContactStateMsg.getState() == ShutterContactState.CLOSED) {
eventPublisher.postUpdate(itemName, OpenClosedType.CLOSED);
} else if (shutterContactStateMsg.getState() == ShutterContactState.OPEN) {
eventPublisher.postUpdate(itemName, OpenClosedType.OPEN);
}
} else if (bc.getFeature() == MaxCulFeature.BATTERY) {
eventPublisher.postUpdate(itemName, shutterContactStateMsg.getBatteryLow() ? OnOffType.ON : OnOffType.OFF);
}
}
}
/* respond to device */
if (isBroadcast == false) {
this.messageHandler.sendAck(shutterContactStateMsg);
}
break;
default:
logger.debug("Unhandled message type " + msgType.toString());
break;
}
}
updateCreditMonitors();
}
Aggregations