Skip to content
  • MySensors
  • OpenHardware.io
  • Categories
  • Recent
  • Tags
  • Popular
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo
  1. Home
  2. Controllers
  3. OpenHAB
  4. MQTT/OpenHab gw.request reply

MQTT/OpenHab gw.request reply

Scheduled Pinned Locked Moved OpenHAB
mqtt openhab
3 Posts 2 Posters 3.5k Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Offline
    A Offline
    adi32k
    wrote on last edited by
    #1

    How can I make OpenHab respod to gw.request(sensor, V_HEATER_SW,0);

    I have a relay actuator sketch and in setup() I have this

    for (int sensor=1 ; sensor<=NUMBER_OF_RELAYS;sensor++)
    {
    gw.present(sensor, S_HEATER);
    gw.request(sensor, V_HEATER_SW,0);
    }

    practically I would like OpenHab to respond to the gw.request with the last state of the relay that OpenHab knows.

    My item definition is the follwing. I am able to ON and OFF the relay, but I need to find a way to get the values from OpenHab of the relays when the relay actuator arduino reboots.

    Switch Incalzire_Releu_GF_Living2 "Incalzire Releu Living 2" <heating> (Incalzire) {mqtt=">[mysensor:MyMQTT/3/2/V_HEATER_SW:command:ON:1],>[mysensor:MyMQTT/3/2/V_HEATER_SW:command:OFF:0]"}

    1 Reply Last reply
    0
    • B Offline
      B Offline
      binladin
      wrote on last edited by
      #2

      To work with actuators, suggests implementation of an RPC interface over the MQTT, such as here - mqtt-rpc for node.js. In other words - it requires special design of topic structure, as a very simple example, you could publish to MyMQTT/20/0/V_LIGHT/REQUEST and subscribe to MyMQTT/20/0/V_LIGHT/RESPONSE. Here your can read how it works in Gadgetkeeper - JSON-RPC over MQTT.

      Even better would be to have implemented the protocol WAMP - WAMP Router diagram

      But there is a trick for our situation - we can use V_VAR2 for requesting controller and V_VAR1 for getting response. For example:
      MyMQTT/20/1/V_VAR1 - (incomingMessage)
      MyMQTT/20/1/V_VAR2 - (send request).
      Below you can see sketch of Natural Gas Meter from Majordomo forum (russian - you can use translate.google.com), which used this trick. This sketch derrived from MySensors Power Meter Pulse Sensor.

      But you have to adapt the settings of OpenHub like settings in Majordomo.

      // Use this sensor to measure KWH and Watt of your house meeter
      // You need to set the correct pulsefactor of your meeter (blinks per KWH).
      // The sensor starts by fetching current KWH value from gateway.
      // Reports both KWH and Watt back to gateway.
      //
      // Unfortunately millis() won't increment when the Arduino is in 
      // sleepmode. So we cannot make this sensor sleep if we also want 
      // to calculate/report watt-number.
      
      #include <SPI.h>
      #include <MySensor.h>  
      
      #define DIGITAL_INPUT_SENSOR 3  // The digital input you attached your light sensor.  (Only 2 and 3 generates interrupt!)
      #define PULSE_FACTOR 1000       // Nummber of blinks per KWH of your meeter
      #define SLEEP_MODE true        // Watt-value can only be reported when sleep mode is false.
      #define MAX_WATT 10000          // Max watt value to report. This filetrs outliers.
      #define INTERRUPT DIGITAL_INPUT_SENSOR-2 // Usually the interrupt = pin -2 (on uno/nano anyway)
      
      // Id of the sensor child
      #define CHILD_ID_CNT 1
      #define CHILD_ID_DEV 254
      
       unsigned long SEND_FREQUENCY = 300000; // Minimum time between send (in milliseconds). We don't wnat to spam the gateway.
       MySensor gw;
       double ppwh = ((double)PULSE_FACTOR)/1000; // Pulses per watt hour
       boolean pcReceived = false;
       volatile unsigned long pulseCount = 0;   
       volatile unsigned long lastBlink = 0;
       volatile unsigned long watt = 0;
       unsigned long oldPulseCount = 0;   
       unsigned long oldWatt = 0;
       double oldKwh;
       double oldTemp = 0;
       float oldBatteryV = 0;
       unsigned long lastSend;
      
       MyMessage CntWattMsg(CHILD_ID_CNT, V_WATT);
       MyMessage CntKwhMsg(CHILD_ID_CNT,  V_KWH);
       MyMessage pcMsg(CHILD_ID_CNT,      V_VAR1);
       MyMessage pcReqMsg(CHILD_ID_CNT,   V_VAR2);
      
       MyMessage BattMsg(CHILD_ID_DEV, V_VOLTAGE);
      
      long readVcc() {
       long result;
       // Read 1.1V reference against AVcc
       ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
       delay(2); // Wait for Vref to settle
       ADCSRA |= _BV(ADSC); // Convert
       while (bit_is_set(ADCSRA,ADSC));
       result = ADCL;
       result |= ADCH<<8;
       result = 1126400L / result; // Back-calculate AVcc in mV
       return result;
      }
      
      void SendDevInfo()
      {
        //========= Battery =============  
        float batteryV  = readVcc() * 0.001;
      
        Serial.print("BatV:");
        Serial.println(batteryV);
      
        gw.send(BattMsg.set(batteryV, 2));
      }
      
      void setup()  
      {  
        wdt_disable();
      
        // Disable the ADC by setting the ADEN bit (bit 7) to zero.
        ADCSRA = ADCSRA & B01111111;
      
         // Disable the analog comparator by setting the ACD bit
        // (bit 7) to one.
        ACSR = B10000000;   
      
        gw.begin(incomingMessage);
      
        // Send the sketch version information to the gateway and Controller
        gw.sendSketchInfo("Natural GAS Meter", "1.0");
      
        // Register this device as power sensor
        gw.present(CHILD_ID_CNT, S_POWER);
        gw.present(CHILD_ID_DEV, V_VOLTAGE);  
      
        // Fetch last known pulse count value from gw
        //gw.request(CHILD_ID_CNT, V_VAR1);
        gw.send(pcReqMsg.set("REQ"));
      
        attachInterrupt(INTERRUPT, onPulse, RISING);
      
        wdt_enable(WDTO_8S);  
      
        lastSend=millis();
      }
      
      void loop()     
      { 
       wdt_reset();
      
       // By calling process() you route messages in the background
       gw.process();
      
       // Send feq
       // Only send values at a maximum frequency or woken up from sleep
       unsigned long now = millis();
       bool sendTime = now - lastSend > SEND_FREQUENCY;
      
       //========= Cnt =============   
       if (pcReceived && (SLEEP_MODE || sendTime)) {
         SendDevInfo();
      
      // New watt value has been calculated  
      if (!SLEEP_MODE && watt != oldWatt) {
        // Check that we dont get unresonable large watt value. 
        // could hapen when long wraps or false interrupt triggered
        if (watt<((unsigned long)MAX_WATT)) {
          gw.send(CntWattMsg.set(watt));  // Send watt value to gw 
        }  
        Serial.print("Watt:");
        Serial.println(watt);
        oldWatt = watt;
      }
      
      // Pulse cout has changed
      if (pulseCount != oldPulseCount) {
        gw.send(pcMsg.set(pulseCount));  // Send pulse count value to gw 
        double kwh = ((double)pulseCount/((double)PULSE_FACTOR));     
        oldPulseCount = pulseCount;
        if (kwh != oldKwh) {
          gw.send(CntKwhMsg.set(kwh, 4));  // Send kwh value to gw 
          oldKwh = kwh;
        }
      }       
      
      lastSend = now;    
       } else if (sendTime && !pcReceived) {
      // No count received. Try requesting it again
      //gw.request(CHILD_ID_CNT, V_VAR1);
      gw.send(pcReqMsg.set("REQ"));
      
      lastSend=now;       
      }
      
       //========= Sleep ================
       if (SLEEP_MODE && pcReceived) {
       Serial.println("sleep");
       gw.sleep(SEND_FREQUENCY);
       }
      }
      
       void incomingMessage(const MyMessage &message) {
        if (message.type==V_VAR1) {  
        pulseCount = oldPulseCount = message.getLong();
        Serial.print("Received last pulse count from gw:");
        Serial.println(pulseCount);
        pcReceived = true;
        }
       }
      
      void onPulse()     
      { 
       if (!SLEEP_MODE) {
       unsigned long newBlink = micros();  
       unsigned long interval = newBlink-lastBlink;
       if (interval<10000L) { // Sometimes we get interrupt on RISING
       return;
       }
      watt = (3600000000.0 /interval) / ppwh;
      lastBlink = newBlink;
      } 
       pulseCount++;
      }
      
      1 Reply Last reply
      0
      • A Offline
        A Offline
        adi32k
        wrote on last edited by
        #3

        Thanks for the suggestion. I found another solution.

        I have the item like this:

        Switch Incalzire_Releu_GF_Living1 "Incalzire Releu Living 1" <heating> (Incalzire) {mqtt=">[mysensor:MyMQTT/3/1/V_HEATER_SW:command:ON:1],>[mysensor:MyMQTT/3/1/V_HEATER_SW:command:OFF:0],<[mysensor:MyMQTT/3/1/V_HEATER_SW:command:MAP(1on0off.map)]"}

        and in 1onoff.map i have:

        **1=ON
        0=OFF
        1.4.1=REQUEST
        **

        And then I have a rule:

        rule "SW1 Persist"
        when
        Item Incalzire_Releu_GF_Living1 received command
        then
        if (receivedCommand == "REQUEST")
        {
        sendCommand(Incalzire_Releu_GF_Living1 , Incalzire_Releu_GF_Living1.state);
        }
        end

        In the arduino code for the relay I have in the setu() this code.

        **void setup()
        {

        gw.begin(incomingMessage, AUTO, true);

        gw.sendSketchInfo("Relay Control", "1.0");

        for (int sensor=1 ; sensor<=NUMBER_OF_RELAYS;sensor++)
        {
        gw.present(sensor, S_HEATER);
        gw.request(sensor, V_HEATER_SW,0);
        }
        }**

        So whenever gw.request is called the idem receives an update with 1.4.1 that is resolved by the rule to the actual state of the switch in openhab.

        Like this, when arduino starts, the relays will be swiched ON as per the actual state of the switch.

        1 Reply Last reply
        1
        Reply
        • Reply as topic
        Log in to reply
        • Oldest to Newest
        • Newest to Oldest
        • Most Votes


        9

        Online

        11.7k

        Users

        11.2k

        Topics

        113.0k

        Posts


        Copyright 2019 TBD   |   Forum Guidelines   |   Privacy Policy   |   Terms of Service
        • Login

        • Don't have an account? Register

        • Login or register to search.
        • First post
          Last post
        0
        • MySensors
        • OpenHardware.io
        • Categories
        • Recent
        • Tags
        • Popular