Using MySensors and openHAB2 MQTT2 binding

The example below is connecting MySensors with openHAB based on the new MQTT binding.

bridge.things

// bridge.things
 
// https://community.openhab.org/t/using-sonoff-power-switches-with-tasmota-firmware-and-openhab2-mqtt2-binding/59969
 
Bridge mqtt:broker:MqttOpenHAB75 "MQTT Broker Pandora" @ "MQTT Pandora" [ 
  host="192.168.1.123",
  port=1883,
  secure="AUTO",
  qos=0,
  retain=false,
  clientid="Oh2Mqtt2Thing",
  //certificate="",
  //certificatepin=false,
  //publickey="",
  //publickeypin=false,
  keep_alive_time=30000,
  reconnect_time=60000,
  //lastwill_message="",
  //lastwill_qos=1,
  //lastwill_topic="",
  username="mqttuser",
  password="mqttpw"
]

mysensors.things

// mysensors.things
// https://github.com/tobof/openhab2-addons/wiki/Configuration

// "MyS-Node"    // "mygateway1-out"	data received from your gateway
// "MyS-2Node"   // "mygateway1-in"		send data to your sensors
//                   				MY_MQTT_PUBLISH_TOPIC_PREFIX / FROM-NODE-ID / SENSOR-ID / CMD-TYPE / ACK-FLAG / SUB-TYPE

Thing mqtt:topic:MySBabylon_LED_1_th  "MQTT-MyS Thing: Babylon LED" (mqtt:broker:MqttOpenHAB75) @ "MQTT OpenHAB"
    {
    Channels:
        Type number : uptime    "LED Stripe uptime" [ stateTopic="MyS-Node/5/255/3/0/22" ]
        Type switch : lamp      "LED Stripe power"  [ stateTopic="MyS-Node/5/1/1/0/2",       commandTopic="MyS-2Node/5/1/2/0/2" ]
        Type number : dim       "LED Stripe dim"    [ stateTopic="MyS-Node/5/1/1/0/3",       commandTopic="MyS-2Node/5/1/2/0/3" ]
        Type number : fade      "LED Stripe fade"   [ stateTopic="MyS-Node/5/1/1/0/24",      commandTopic="MyS-2Node/5/1/2/0/24" ]
    }

Thing mqtt:topic:MySBabylon_DHT22_th  "MQTT-OneWire Thing: Gateway" (mqtt:broker:MqttOpenHAB75) @ "MQTT OpenHAB"
    {
    Channels:
        Type number : uptime      "DHT22 uptime"       [ stateTopic="MyS-Node/1/255/3/0/22" ]
        Type number : hummidity   "DHT22 hummidity"    [ stateTopic="MyS-Node/1/3/1/0/1" ]
        Type number : temperature "DHT22 temperature"  [ stateTopic="MyS-Node/1/4/1/0/0" ] 
        Type string : info        "DHT22 info"         [ stateTopic="MyS-Node/1/0/1/0/47" ] 
    }

Thing mqtt:topic:OneWireGW_th  "MQTT-OneWire Thing: Gateway" (mqtt:broker:MqttOpenHAB75) @ "MQTT OpenHAB"
    {
    Channels:
        Type number : uptime    "Gateway uptime"    [ stateTopic="MyS-Node/0/255/3/0/22" ]
    }


mysensors.items

// mysensors.items
//  itemname ["labeltext"] [<iconname>] [(group1, group2, ...)] [{bindingconfig}]
// https://github.com/tobof/openhab2-addons/wiki/Configuration
/************************************************** Gruppen ********************************************/
Group gMYSensors	// restore after power down
 
/************************************************** Items ********************************************/
//																				MY_MQTT_PUBLISH_TOPIC_PREFIX / FROM-NODE-ID/SENSOR-ID/CMD-TYPE/ACK-FLAG/SUB-TYPE

// "MyS-Node"    // "mygateway1-out"	data received from your gateway
// "MyS-2Node"   // "mygateway1-in"		send data to your sensors

Number  Gateway_uptime	  "Gateway uptime: [%d]"                <time>        (gMYSensors) { channel="mqtt:topic:OneWireGW_th:uptime" }

Number  MyS_DHT22_uptime	    "DHT22 uptime: [%d]"              <time>        (gMYSensors) { channel="mqtt:topic:MySBabylon_DHT22_th:uptime" }
Number  MyS_DHT22_humidity  	"DHT22 humidity: [%.0f %%]"       <humidity>    (gMYSensors) { channel="mqtt:topic:MySBabylon_DHT22_th:hummidity" }
Number  MyS_DHT22_temperature	"DHT22 temperature: [%.1f  °C] "  <temperature> (gMYSensors) { channel="mqtt:topic:MySBabylon_DHT22_th:temperature" }
String  MyS_DHT22_info      	"DHT22 info:"                     <error>       (gMYSensors) { channel="mqtt:topic:MySBabylon_DHT22_th:info" }

Number  Babylon_LED_uptime	"Babylon LED uptime: [%d]"          <time>        (gMYSensors) { channel="mqtt:topic:MySBabylon_LED_1_th:uptime" }
Switch 	Babylon_LED_SWITCH  "Babylon LED Switch"                              (gMYSensors) { channel="mqtt:topic:MySBabylon_LED_1_th:lamp" }
Number 	Babylon_LED_DIM     "Babylon LED DIM"                   <settings>    (gMYSensors) { channel="mqtt:topic:MySBabylon_LED_1_th:dim" }
Number 	Babylon_LED_FADE    "Babylon LED FADE"                  <settings>    (gMYSensors) { channel="mqtt:topic:MySBabylon_LED_1_th:fade" }

mysensors.sitemap

// mysensors.sitemap
// list of icons: https://github.com/eclipse/smarthome/tree/master/extensions/ui/iconset/org.eclipse.smarthome.ui.iconset.classic/icons

  sitemap mysensors label="My Sensors" { 

	Frame label="MQTT Gateway" {
		// Text item=Ardu1_433_Uptime	label="433 uptime"
		Text		item=Gateway_uptime
	} // end of Frame

	Frame label="MQTT DHT22" {
		Text		item=MyS_DHT22_uptime
		Text		item=MyS_DHT22_humidity
		Text		item=MyS_DHT22_temperature
		Text		item=MyS_DHT22_info
	} // end of Frame

	Frame label="MQTT LED" {
		Text		item=Babylon_LED_uptime
		Switch		item=Babylon_LED_SWITCH
		Slider 		item=Babylon_LED_DIM
		Slider 		item=Babylon_LED_FADE
		Colorpicker item=LEDStrip_1_Color
	} // end of Frame


} // end of sitemap
5 Likes

Below is the MySenor code using a DHT22

/**
 * MySensors Example
 * https://www.mysensors.org/download/sensor_api_20
 */
// Enable debug prints to serial monitor
#define MY_DEBUG

#define MY_RADIO_NRF24              //  define radio type to be used
#define MY_RF24_CHANNEL     76            // 76
#define MY_RF24_PA_LEVEL    RF24_PA_LOW    //RF24_PA_LOW, RF24_PA_HIGH,  RF24_PA_MAX 
#define MY_RF24_DATARATE    RF24_250KBPS
// #define MY_REPEATER_FEATURE            // turn a node into a repeater - but Node must be awake all the time, no sleep

#define MY_NODE_ID 1             // Node id defaults to AUTO (tries to fetch id from controller).
                                    // Specify a number (1-254) if you want to manually set your Node ID
#define SKETCH_NAME "DHT22 Babylon"                // Change to a fancy name you like
#define SKETCH_VERSION "1.1"
#define CHILD_ID_TXT  0
#define CHILD_ID_HUM  3
#define CHILD_ID_TEMP 4

#include "Arduino.h"
#include <SPI.h>  // DHT 22
#include <DHT.h>  // DHT 22
#include <MySensors.h>

//                                          // e.g. V_TEMP, V_HUM, V_LIGHT, V_DIMMER, V_PRESSURE, V_FORECAST, V_RAIN, ...
float     lastTemp;
float     lastHum;
uint8_t   nNoUpdatesTemp;
uint8_t   nNoUpdatesHum;
bool      metric = true;

MyMessage msgHum  (CHILD_ID_HUM,  V_HUM);
MyMessage msgTemp (CHILD_ID_TEMP, V_TEMP);
MyMessage msgText (CHILD_ID_TXT, V_TEXT);               // message for Sending Text to Controller

DHT dht;

#define   LED_PIN1            7  // Arduino Digital I/O pin number for relay 
#define   DHT_DATA_PIN        2 // DHT 22
#define   SENSOR_TEMP_OFFSET  0  // DHT22

// Sleep time between sensor updates (in milliseconds)
// Must be >1000ms for DHT22 and >2000ms for DHT11
static const uint64_t UPDATE_INTERVAL = 10000; // 60000;

// Force sending an update of the temperature after n sensor reads, so a controller showing the
// timestamp of the last update doesn't show something like 3 hours in the unlikely case, that
// the value didn't change since;
// i.e. the sensor would force sending an update every UPDATE_INTERVAL*FORCE_UPDATE_N_READS [ms]
static const uint8_t FORCE_UPDATE_N_READS = 10;

#define   HEARTBEAT_TIME  10000
uint32_t  last_heartbeat_time;

// ------------------------------------------------------------------------------------------------------
void before()                 // 
{
  pinMode (LED_PIN1,  OUTPUT);
} // end of function

// ------------------------------------------------------------------------------------------------------
void presentation()                 // sensor must first present itself to the controller
{
  sendSketchInfo(SKETCH_NAME, SKETCH_VERSION);
  // Register all sensors to gw (they will be created as child devices)
  present(CHILD_ID_HUM, S_HUM);
  present(CHILD_ID_TEMP, S_TEMP);

  metric = getControllerConfig().isMetric;

} // end of function

// ------------------------------------------------------------------------------------------------------
void my_blink() {
  digitalWrite(LED_PIN1, HIGH);
  delay(200);
  digitalWrite(LED_PIN1, LOW);
  delay(200);
  Serial.println("blink..");
} // end of function

// ------------------------------------------------------------------------------------------------------
void setup() {  

  my_blink();
  my_blink();

  dht.setup(DHT_DATA_PIN); // set data pin of DHT sensor
  if (UPDATE_INTERVAL <= dht.getMinimumSamplingPeriod()) {
    Serial.println("Warning: UPDATE_INTERVAL is smaller than supported by the sensor!");
  }
  // Sleep for the time of the minimum sampling period to give the sensor time to power up
  // (otherwise, timeout errors might occure for the first reading)
  sleep(dht.getMinimumSamplingPeriod());

  last_heartbeat_time = millis();
} // end of function


// ------------------------------------------------------------------------------------------------------
void timer_heartbeat()
{
    if ((millis() - last_heartbeat_time) > HEARTBEAT_TIME) {
    // If it exceeds the heartbeat time then send a heartbeat
    sendHeartbeat();
    last_heartbeat_time = millis();
  
    #ifdef MY_DEBUG
      Serial.println("-----> Sent heartbeat: Node " + (String)MY_NODE_ID + " is alive");
    #endif
  }
} // end of function



// ------------------------------------------------------------------------------------------------------
void read_DHT22_temperature()
{

  // Force reading sensor, so it works also after sleep()
  //  dht.readSensor(true); 

  // Get temperature from DHT library
  float temperature = dht.getTemperature();
  if (isnan(temperature)) {
    Serial.println("Failed reading temperature from DHT!");
    send(msgText.set("ERROR DHT22"));  // Send tripped value to gw
  } else if (temperature != lastTemp || nNoUpdatesTemp == FORCE_UPDATE_N_READS) {
    // Only send temperature if it changed since the last measurement or if we didn't send an update for n times
    lastTemp = temperature;

    // apply the offset before converting to something different than Celsius degrees
    temperature += SENSOR_TEMP_OFFSET;

    if (!metric) {
      temperature = dht.toFahrenheit(temperature);
    }
    // Reset no updates counter
    nNoUpdatesTemp = 0;
    send(msgText.set("ok"));
    send(msgTemp.set(temperature, 1));

    #ifdef MY_DEBUG
    Serial.print("CHILD ");
    Serial.print(CHILD_ID_TEMP);
    Serial.print("/ DHT22 Temp> ");
    Serial.println(temperature);
    #endif
  } else {
    // Increase no update counter if the temperature stayed the same
    nNoUpdatesTemp++;
  }

}// end of function

// ------------------------------------------------------------------------------------------------------
void read_DHT22_hummidity()
{
  // Get humidity from DHT library
  float humidity = dht.getHumidity();
  if (isnan(humidity)) {
    Serial.println("Failed reading humidity from DHT");
    send(msgText.set("ERROR DHT22"));  // Send tripped value to gw
  } else if (humidity != lastHum || nNoUpdatesHum == FORCE_UPDATE_N_READS) {
    // Only send humidity if it changed since the last measurement or if we didn't send an update for n times
    lastHum = humidity;
    // Reset no updates counter
    nNoUpdatesHum = 0;
    send(msgText.set("ok"));
    send(msgHum.set(humidity, 1));

    #ifdef MY_DEBUG
    Serial.print("CHILD ");
    Serial.print(CHILD_ID_HUM);
    Serial.print(" / DHT22 Hum> ");
    Serial.println(humidity);
    #endif
  } else {
    // Increase no update counter if the humidity stayed the same
    nNoUpdatesHum++;
  }

}// end of function


// ------------------------------------------------------------------------------------------------------
void loop()
{

  timer_heartbeat();
  read_DHT22_temperature();
  my_blink(); my_blink();
  sleep(200);
  read_DHT22_hummidity();
  sleep(UPDATE_INTERVAL); // Sleep for a while to save energy

} // end of function

1 Like

I also got in contact with the MySensor developers and they seem to be interested in mqtt conventions like Homie, so that auto discovery can maybe done in the future.

3 Likes