Arduino's IP-address send to OpenHAB and a LWT solution

Device: Arduino UNO with MQTT
Objectives : let OpenHAB know that the Arduino UNO decive is alive and kicking
MQTT LWT: Status reachability of this external device

How it started: I was charmed of the Last Will and Testament used in the TasmOTA-sketch for the SonOff devices. But reading these sketches is reading some hocus pocus abracadabra (not always but…)

So when I tried to implement this in an Arduino UNO sketch I had some problem to find a simplified example. The MQTT essentials (part 9) about this subject are helpful but did not bring me closer the required (preferred cut & paste) Arduino statement. Luckily (for me) I found more straightforward examples at this [place].

So in the end the statement is rather simple replace:
if (client.connect(MQTT_CLIENTID, MQTT_SERVER_UID, MQTT_SERVER_PWD))
with
if (client.connect(MQTT_CLIENTID, MQTT_SERVER_UID, MQTT_SERVER_PWD, MQTT_LWT_TOPIC, 0, true, “Offline”, true))
and add an extra line
client.publish(MQTT_LWT_TOPIC, “Online”, true);

The other problem I wanted to tackle was to show the IP-address of an Arduino UNO in OpenHAB. After several attempt I found somewhere (sorry lost the link) how to do this part:

// convert IP-address to a string for in this case MQTT
char* ip2CharArray(IPAddress IP) {
  static char a[16];
  sprintf(a, "%d.%d.%d.%d", IP[0], IP[1], IP[2], IP[3]);
  return a;
}

In combination with a common sensor the DHT22 the full sketch is:

/*
 Starting Sketch from: PubSubClient and surfing the internet by WJ4IoT
 Attached sensor DHT22 on D5
*/
#include <SPI.h>
#include <Ethernet.h>
/************************* Ethernet Client Setup *****************************/
// Update these with values suitable for your network.
byte mac[] = {0x00, 0x00, 0x00, 0x00, 0xF00, 0x01};
//Uncomment the following, and set to a valid ip if you don't have dhcp available.
//#include <Dhcp.h>
//IPAddress iotIP (192, 168, 0, 235);
//Uncomment the following, and set to your preference if you don't have automatic dns.
//#include <Dns.h>
//IPAddress dnsIP (8, 8, 8, 8);
//If you uncommented either of the above lines, make sure to change "Ethernet.begin(mac)" to "Ethernet.begin(mac, iotIP)" 
//or "Ethernet.begin(mac, iotIP, dnsIP)"

/*************************** MQTT Setup **************************************/
#include <PubSubClient.h>
const char* MQTT_SERVER      = "192.168.x.y"; //shaky part not sure why i need both ip as name
const char* MQTT_SERVER_UID  = "openhabian";
const char* MQTT_SERVER_PWD  = "password";
#define MQTT_SERVERPORT      1883

const char* MQTT_LWT_TOPIC  = "unoDHT/LWT";            // <- sync with deviceID !!! 
const char* MQTT_IN_TOPIC   = "unoDHT/in/#";
const char* MQTT_OUT_TOPIC  = "unoDHT/out";
const char* MQTT_CLIENTID   = "unoDHT";

EthernetClient ethClient;
PubSubClient client(MQTT_SERVER, MQTT_SERVERPORT, ethClient);

/*************************** LIBRARY Setup **************************************/
// DHT Temperature & Humidity Sensor
// Unified Sensor Library Example
// Written by Tony DiCola for Adafruit Industries
// Released under an MIT license.
// Depends on the following Arduino libraries:
// - Adafruit Unified Sensor Library: https://github.com/adafruit/Adafruit_Sensor
// - DHT Sensor Library: https://github.com/adafruit/DHT-sensor-library
// - See guide for details on sensor wiring and usage:
//   https://learn.adafruit.com/dht/overview

//#include <Adafruit_Sensor.h>
#include <DHT.h>
//#include <DHT_U.h>
#define DHTPIN   5         // Pin which is connected to the DHT sensor.
// Uncomment the type of sensor in use:
// #define DHTTYPE           DHT11     // DHT 11 
#define DHTTYPE           DHT22     // DHT 22 (AM2302)
// #define DHTTYPE           DHT21     // DHT 21 (AM2301)
//DHT_Unified dht(DHTPIN, DHTTYPE);
DHT dht(DHTPIN, DHTTYPE);
uint32_t delayMS;
double t, h;

/*************************** Variables **************************************/
String returnmsg;
int reconnects = 0;
long now, lastMsg = 0;
long timeBetweenMessages = 60000;  // sec x 1000

/*************************************************************************/
void setup()
{
  Ethernet.begin(mac);           // with IP based upon DSN-server  
  Serial.begin(115200);
  while (!Serial) {
    Serial.print("."); // wait for serial port to connect. Needed for native USB port only
  }
  /*
  Serial.println("sketch: MQTT_UNO_DHT22");
  Serial.print("compiled: ");
  Serial.print(__DATE__);
  Serial.print(" ");
  Serial.println(__TIME__);
  Serial.println("Following sensors are/should be connected");
  Serial.println("-> Digital D5 = DHT22");
  Serial.println("-----------------------------------------");
  */
  //pinMode(LED_BUILTIN, OUTPUT);

  reconnect();
  
  Serial.println("DHTxx test!");
  dht.begin();
  Serial.println("Begin with loop.....");
}
/*************************************************************************/

void loop()
{
  now = millis();
  //client.loop();
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  // Read temperature as Celsius (the default)
  float t = dht.readTemperature();
  // Read temperature as Fahrenheit (isFahrenheit = true)
  float f = dht.readTemperature(true);

  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t) || isnan(f)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }
  if (!client.connected()) {
    reconnect();
  }

  if (now - lastMsg > timeBetweenMessages ) {
    lastMsg = now;
    returnmsg = "{\"reconnects\":";
    returnmsg += reconnects;
    returnmsg += ",\"IP\":";
    returnmsg += ip2CharArray(Ethernet.localIP());
    returnmsg += ",\"temp\":";
    returnmsg += t;
    returnmsg += ",\"hum\":";
    returnmsg += h;
    returnmsg += "}";
    client.publish( MQTT_OUT_TOPIC , (char*) returnmsg.c_str(), true );
    client.subscribe(MQTT_IN_TOPIC);
    Serial.println(returnmsg);
  }
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

void reconnect() {
//  Loop until we're reconnected

  while (!client.connected()) {
    ++reconnects;
    Serial.println("Attempting MQTT connection...");
    //connect (clientID, username, password, willTopic, willQoS, willRetain, willMessage) https://pubsubclient.knolleary.net/api.html#connect4
    if (client.connect(MQTT_CLIENTID, MQTT_SERVER_UID, MQTT_SERVER_PWD, MQTT_LWT_TOPIC, 0, true, "Offline", true)) {
    //if (client.connect(MQTT_CLIENTID, MQTT_SERVER_UID, MQTT_SERVER_PWD)) {
      //Serial.println("....connected");
      //publish ready
      client.publish(MQTT_LWT_TOPIC, "Online", true);
      //subscribe in topic
      client.subscribe(MQTT_IN_TOPIC);
    } else {
      //Serial.print("failed, rc=");
      //Serial.print(client.state());
      //Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

// convert IP-address to a string for in this case MQTT

char* ip2CharArray(IPAddress IP) {
  static char a[16];
  sprintf(a, "%d.%d.%d.%d", IP[0], IP[1], IP[2], IP[3]);
  return a;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

How it looks in OpenHAB:

2 Likes

Nice, thank you for your contribution.
Please correct your code fences, thanks