Search in sources :

Example 1 with PairPingMsg

use of org.openhab.binding.maxcul.internal.messages.PairPingMsg 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();
}
Also used : PushButtonMsg(org.openhab.binding.maxcul.internal.messages.PushButtonMsg) SetTemperatureMsg(org.openhab.binding.maxcul.internal.messages.SetTemperatureMsg) MaxCulBindingProvider(org.openhab.binding.maxcul.MaxCulBindingProvider) WallThermostatControlMsg(org.openhab.binding.maxcul.internal.messages.WallThermostatControlMsg) WallThermostatStateMsg(org.openhab.binding.maxcul.internal.messages.WallThermostatStateMsg) PairPingMsg(org.openhab.binding.maxcul.internal.messages.PairPingMsg) ThermostatStateMsg(org.openhab.binding.maxcul.internal.messages.ThermostatStateMsg) WallThermostatStateMsg(org.openhab.binding.maxcul.internal.messages.WallThermostatStateMsg) TimeInfoMsg(org.openhab.binding.maxcul.internal.messages.TimeInfoMsg) DecimalType(org.openhab.core.library.types.DecimalType) TimeUpdateRequestSequence(org.openhab.binding.maxcul.internal.message.sequencers.TimeUpdateRequestSequence) PairingInitialisationSequence(org.openhab.binding.maxcul.internal.message.sequencers.PairingInitialisationSequence) ShutterContactStateMsg(org.openhab.binding.maxcul.internal.messages.ShutterContactStateMsg) MaxCulMsgType(org.openhab.binding.maxcul.internal.messages.MaxCulMsgType)

Example 2 with PairPingMsg

use of org.openhab.binding.maxcul.internal.messages.PairPingMsg in project openhab1-addons by openhab.

the class MaxCulMsgHandler method listenModeHandler.

private void listenModeHandler(String data) {
    switch(BaseMsg.getMsgType(data)) {
        case WALL_THERMOSTAT_CONTROL:
            new WallThermostatControlMsg(data).printMessage();
            break;
        case TIME_INFO:
            new TimeInfoMsg(data).printMessage();
            break;
        case SET_TEMPERATURE:
            new SetTemperatureMsg(data).printMessage();
            break;
        case ACK:
            new AckMsg(data).printMessage();
            break;
        case PAIR_PING:
            new PairPingMsg(data).printMessage();
            break;
        case PAIR_PONG:
            new PairPongMsg(data).printMessage();
            break;
        case THERMOSTAT_STATE:
            new ThermostatStateMsg(data).printMessage();
            break;
        case SET_GROUP_ID:
            new SetGroupIdMsg(data).printMessage();
            break;
        case WAKEUP:
            new WakeupMsg(data).printMessage();
            break;
        case WALL_THERMOSTAT_STATE:
            new WallThermostatStateMsg(data).printMessage();
            break;
        case ADD_LINK_PARTNER:
        case CONFIG_TEMPERATURES:
        case CONFIG_VALVE:
        case CONFIG_WEEK_PROFILE:
        case PUSH_BUTTON_STATE:
        case REMOVE_GROUP_ID:
        case REMOVE_LINK_PARTNER:
        case RESET:
        case SET_COMFORT_TEMPERATURE:
        case SET_DISPLAY_ACTUAL_TEMP:
        case SET_ECO_TEMPERATURE:
        case SHUTTER_CONTACT_STATE:
        case UNKNOWN:
        default:
            BaseMsg baseMsg = new BaseMsg(data);
            baseMsg.printMessage();
            break;
    }
}
Also used : WallThermostatStateMsg(org.openhab.binding.maxcul.internal.messages.WallThermostatStateMsg) PairPongMsg(org.openhab.binding.maxcul.internal.messages.PairPongMsg) PairPingMsg(org.openhab.binding.maxcul.internal.messages.PairPingMsg) BaseMsg(org.openhab.binding.maxcul.internal.messages.BaseMsg) SetTemperatureMsg(org.openhab.binding.maxcul.internal.messages.SetTemperatureMsg) ThermostatStateMsg(org.openhab.binding.maxcul.internal.messages.ThermostatStateMsg) WallThermostatStateMsg(org.openhab.binding.maxcul.internal.messages.WallThermostatStateMsg) TimeInfoMsg(org.openhab.binding.maxcul.internal.messages.TimeInfoMsg) AckMsg(org.openhab.binding.maxcul.internal.messages.AckMsg) WallThermostatControlMsg(org.openhab.binding.maxcul.internal.messages.WallThermostatControlMsg) SetGroupIdMsg(org.openhab.binding.maxcul.internal.messages.SetGroupIdMsg) WakeupMsg(org.openhab.binding.maxcul.internal.messages.WakeupMsg)

Example 3 with PairPingMsg

use of org.openhab.binding.maxcul.internal.messages.PairPingMsg in project openhab1-addons by openhab.

the class PairingInitialisationSequence method runSequencer.

@Override
public void runSequencer(BaseMsg msg) {
    /*
         * This sequence is taken from observations of activity between the MAX!
         * Cube and a wall thermostat and refined using some experimentation :)
         */
    if (state != PairingInitialisationState.RETX_WAKEUP_ACK) {
        // reset counter - ack received
        pktLostCount = 0;
    }
    logger.debug("Sequence State: " + state);
    switch(state) {
        case INITIAL_PING:
            /* get device type */
            PairPingMsg ppMsg = new PairPingMsg(msg.rawMsg);
            this.deviceType = MaxCulDevice.getDeviceTypeFromInt(ppMsg.type);
            /* Send PONG - assumes PING is checked */
            logger.debug("Sending PONG");
            this.devAddr = msg.srcAddrStr;
            messageHandler.sendPairPong(devAddr, this);
            state = PairingInitialisationState.PONG_ACKED;
            break;
        case PONG_ACKED:
            if (msg.msgType == MaxCulMsgType.ACK) {
                AckMsg ack = new AckMsg(msg.rawMsg);
                if (!ack.getIsNack()) {
                    if (this.deviceType == MaxCulDevice.PUSH_BUTTON) {
                        /* for a push button we're done now */
                        state = PairingInitialisationState.FINISHED;
                    } else {
                        /* send group id information */
                        logger.debug("Sending GROUP_ID");
                        messageHandler.sendSetGroupId(devAddr, group_id, this);
                        state = PairingInitialisationState.GROUP_ID_ACKED;
                    }
                } else {
                    logger.error("PAIR_PONG was nacked. Ending sequence");
                    state = PairingInitialisationState.FINISHED;
                }
            } else {
                logger.error("Received " + msg.msgType + " when expecting ACK");
            }
            break;
        case GROUP_ID_ACKED:
            if (msg.msgType == MaxCulMsgType.ACK) {
                AckMsg ack = new AckMsg(msg.rawMsg);
                if (!ack.getIsNack() && (this.deviceType == MaxCulDevice.RADIATOR_THERMOSTAT || this.deviceType == MaxCulDevice.WALL_THERMOSTAT || this.deviceType == MaxCulDevice.RADIATOR_THERMOSTAT_PLUS)) {
                    // send temps for comfort/eco etc
                    messageHandler.sendConfigTemperatures(devAddr, this, config.getComfortTemp(), config.getEcoTemp(), config.getMaxTemp(), config.getMinTemp(), config.getMeasurementOffset(), config.getWindowOpenTemperature(), config.getWindowOpenDuration());
                    state = PairingInitialisationState.CONFIG_TEMPS_ACKED;
                } else {
                    logger.error("SET_GROUP_ID was nacked. Ending sequence");
                    state = PairingInitialisationState.FINISHED;
                }
            } else {
                logger.error("Received " + msg.msgType + " when expecting ACK");
            }
            break;
        case CONFIG_TEMPS_ACKED:
            if (msg.msgType == MaxCulMsgType.ACK) {
                AckMsg ack = new AckMsg(msg.rawMsg);
                if (!ack.getIsNack()) {
                    /*
                         * associate device with us so we get updates - we pretend
                         * to be the MAX! Cube
                         */
                    messageHandler.sendAddLinkPartner(devAddr, this, msg.dstAddrStr, MaxCulDevice.CUBE);
                    /*
                         * if there are more associations to come then set up
                         * iterator and goto state to transmit more associations
                         */
                    if (associations != null && associations.isEmpty() == false) {
                        assocIter = associations.iterator();
                        state = PairingInitialisationState.SENDING_ASSOCIATIONS;
                    } else {
                        logger.debug("No user configured associations");
                        state = PairingInitialisationState.SENDING_ASSOCIATIONS_ACKED;
                    }
                } else {
                    logger.error("CONFIG_TEMPERATURES was nacked. Ending sequence");
                    state = PairingInitialisationState.FINISHED;
                }
            } else {
                logger.error("Received " + msg.msgType + " when expecting ACK");
            }
            break;
        case SENDING_ASSOCIATIONS:
            if (msg.msgType == MaxCulMsgType.ACK) {
                AckMsg ack = new AckMsg(msg.rawMsg);
                if (!ack.getIsNack()) {
                    if (assocIter.hasNext()) /*
                                                  * this should always be true, but
                                                  * good to check
                                                  */
                    {
                        MaxCulBindingConfig partnerCfg = assocIter.next();
                        messageHandler.sendAddLinkPartner(this.devAddr, this, partnerCfg.getDevAddr(), partnerCfg.getDeviceType());
                        /*
                             * if it's the last association message then wait for
                             * last ACK
                             */
                        if (assocIter.hasNext()) {
                            state = PairingInitialisationState.SENDING_ASSOCIATIONS;
                        } else {
                            state = PairingInitialisationState.SENDING_ASSOCIATIONS_ACKED;
                        }
                    } else {
                        // TODO NOTE: if further states are added then ensure
                        // you go to the right state. I.e. when all associations
                        // are done
                        state = PairingInitialisationState.FINISHED;
                    }
                } else {
                    logger.error("SENDING_ASSOCIATIONS was nacked. Ending sequence");
                    state = PairingInitialisationState.FINISHED;
                }
            } else {
                logger.error("Received " + msg.msgType + " when expecting ACK");
            }
            break;
        case SENDING_ASSOCIATIONS_ACKED:
            state = PairingInitialisationState.FINISHED;
            break;
        case SENDING_WEEK_PROFILE:
            // TODO implement this - but where to get a week profile from.
            // Meaningless at the moment!
            state = PairingInitialisationState.FINISHED;
            break;
        case FINISHED:
            /* done, do nothing */
            break;
        case RETX_WAKEUP_ACK:
            /* here are waiting for an ACK after sending a wakeup message */
            if (msg.msgType == MaxCulMsgType.ACK) {
                AckMsg ack = new AckMsg(msg.rawMsg);
                if (!ack.getIsNack()) {
                    logger.debug("Attempt retransmission - resuming");
                    this.useFast = true;
                    messageHandler.sendMessage(reTxMsg);
                    // resume back to previous state
                    state = reTxState;
                } else {
                    logger.error("WAKEUP for ReTx was nacked. Ending sequence");
                    state = PairingInitialisationState.FINISHED;
                }
            } else {
                logger.error("Received " + msg.msgType + " when expecting ACK");
            }
            break;
        default:
            logger.error("Invalid state for PairingInitialisation Message Sequence!");
            break;
    }
}
Also used : PairPingMsg(org.openhab.binding.maxcul.internal.messages.PairPingMsg) AckMsg(org.openhab.binding.maxcul.internal.messages.AckMsg) MaxCulBindingConfig(org.openhab.binding.maxcul.internal.MaxCulBindingConfig)

Aggregations

PairPingMsg (org.openhab.binding.maxcul.internal.messages.PairPingMsg)3 AckMsg (org.openhab.binding.maxcul.internal.messages.AckMsg)2 SetTemperatureMsg (org.openhab.binding.maxcul.internal.messages.SetTemperatureMsg)2 ThermostatStateMsg (org.openhab.binding.maxcul.internal.messages.ThermostatStateMsg)2 TimeInfoMsg (org.openhab.binding.maxcul.internal.messages.TimeInfoMsg)2 WallThermostatControlMsg (org.openhab.binding.maxcul.internal.messages.WallThermostatControlMsg)2 WallThermostatStateMsg (org.openhab.binding.maxcul.internal.messages.WallThermostatStateMsg)2 MaxCulBindingProvider (org.openhab.binding.maxcul.MaxCulBindingProvider)1 MaxCulBindingConfig (org.openhab.binding.maxcul.internal.MaxCulBindingConfig)1 PairingInitialisationSequence (org.openhab.binding.maxcul.internal.message.sequencers.PairingInitialisationSequence)1 TimeUpdateRequestSequence (org.openhab.binding.maxcul.internal.message.sequencers.TimeUpdateRequestSequence)1 BaseMsg (org.openhab.binding.maxcul.internal.messages.BaseMsg)1 MaxCulMsgType (org.openhab.binding.maxcul.internal.messages.MaxCulMsgType)1 PairPongMsg (org.openhab.binding.maxcul.internal.messages.PairPongMsg)1 PushButtonMsg (org.openhab.binding.maxcul.internal.messages.PushButtonMsg)1 SetGroupIdMsg (org.openhab.binding.maxcul.internal.messages.SetGroupIdMsg)1 ShutterContactStateMsg (org.openhab.binding.maxcul.internal.messages.ShutterContactStateMsg)1 WakeupMsg (org.openhab.binding.maxcul.internal.messages.WakeupMsg)1 DecimalType (org.openhab.core.library.types.DecimalType)1