IoT sensor/controller using STM32, W5500 ethernet, MQTT

Dependencies:   mbed WIZnet_Library Watchdog DHT MQTT DS1820

Revision:
13:5f6508dbaa2d
Parent:
12:bcb38c1af703
--- a/main.cpp	Tue Mar 03 00:22:19 2020 +0000
+++ b/main.cpp	Tue Mar 03 18:56:49 2020 +0000
@@ -2,9 +2,8 @@
 #include "Watchdog.h"
 //#include "rtos.h"
 //#include "pins.h"
-#include "WIZnetInterface.h"
-#include "MQTTSocket.h"
 #include "MQTTClient.h"
+#include "MQTTEthernet.h"
 
 // ========== PIN DEFINITIONS ============
 // TODO move pin definitions into separate file
@@ -52,6 +51,8 @@
 // ================= *************** ==================
 #define NODE_NAME "controller03" // TODO just define node number
 
+#define MQTT_MAX_PACKET_SIZE 250
+
 #define NUM_OUTPUTS 8
 DigitalOut outputs[NUM_OUTPUTS] = {D_0, D_1, D_2, D_3, D_4, D_5, D_6, D_7};
 #define NUM_INPUTS 6
@@ -70,7 +71,7 @@
 float humidity[1];
 
 Watchdog wd;
-Ticker tick_60sec;
+Ticker tick_30sec;
 Ticker tick_5sec;
 Ticker tick_1sec;
 Ticker tick_500ms;
@@ -79,15 +80,15 @@
 bool flag_read_dht;
 bool flag_read_ds18b20;
 
-typedef MQTT::Client<MQTTSocket,Countdown> MClient;
+//typedef MQTT::Client<MQTTSocket,Countdown> MClient;
 
 const char* ONOFF[] = {"ON", "OFF"};
 const char* OPENCLOSED[] = {"CLOSED", "OPEN"};
 enum IO_STATE{IO_ON, IO_OFF};
 
 uint8_t mac_addr[6]={0x00, 0x00, 0x00, 0xBE, 0xEF, 0x03}; // TODO make last byte dynamic
-//const char* mqtt_broker = "192.168.10.4";
-const char* mqtt_broker = "192.168.1.99";
+//char* mqtt_broker = "192.168.10.4";
+char* mqtt_broker = "192.168.1.99";
 const int mqtt_port = 1883;
 unsigned long uptime_sec = 0;
 int connected = -1;
@@ -123,7 +124,7 @@
             pc.printf("Output: %d updated to %s\r\n", output_num, ONOFF[new_state]);
             outputs[output_num] = new_state;
             flag_publish = 1;  // workaround for below
-//            publish_value(client, topic, ONOFF[new_state], false);  // needs to access client :-/
+//            publish_value(client, ipstack, topic, ONOFF[new_state], false);  // needs to access client :-/
         }
     }
     else {
@@ -131,12 +132,20 @@
     }
 }
 
-int publish(MClient& client, const char* msg_type, const char* point, 
-                    const char* payload = NULL, size_t payload_len = 0, 
-                    bool retain = false, MQTT::QoS qos = MQTT::QOS1){
-    char topic[64];
-    sprintf(topic, "%s/" NODE_NAME "/%s", msg_type, point);
-    int ret = client.publish(topic, (void*)payload, payload_len, qos, retain);
+int publish(MQTT::Client<MQTTEthernet, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTEthernet* ipstack, 
+                    const char* msg_type, const char* point, const char* payload = NULL, size_t payload_len = 0, 
+                    bool retain = false) {
+    MQTT::Message message;
+    message.qos = MQTT::QOS0;
+    message.retained = retain;
+    message.dup = false;
+    message.payload = (void*)payload;
+    message.payloadlen = payload_len;
+    
+    char topic_str[64];
+    sprintf(topic_str, "%s/" NODE_NAME "/%s", msg_type, point);
+    
+    int ret = client->publish(topic_str, &message);
     if(ret == -1) {
         pc.printf("ERROR during client.publish() = %d\r\n",ret);
     }
@@ -180,43 +189,43 @@
 }
 
 
-int publish_value(MClient &client, const char *topic, const char *buf, bool retain = false)
+int publish_value(MQTT::Client<MQTTEthernet, Countdown, MQTT_MAX_PACKET_SIZE>* &client, MQTTEthernet* &ipstack, const char *topic, const char *buf, bool retain = false)
 {
-    return publish(client, "stat", topic, buf, strlen(buf), retain);
+    return publish(client, ipstack, "stat", topic, buf, strlen(buf), retain);
 }
 
 
-void publish_outputs(MClient &client) {
+void publish_outputs(MQTT::Client<MQTTEthernet, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTEthernet* ipstack) {
     for(int i=0; i<NUM_OUTPUTS; i++) {
         bool output_state = outputs[i];
         char topic[] = "outputx";
         topic[6] = i+48;
         pc.printf("Output: %s is %s\r\n", topic, ONOFF[output_state]);
-        connected = publish_value(client, topic, ONOFF[output_state], false);
+        connected = publish_value(client, ipstack, topic, ONOFF[output_state], false);
     }
 }
 
-void publish_inputs(MClient &client) {
+void publish_inputs(MQTT::Client<MQTTEthernet, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTEthernet* ipstack) {
     for(int i=0; i<NUM_INPUTS; i++) {
         char topic_str[8]; // long enough string for inputx
         sprintf(topic_str, "input%d", i);
-        publish_value(client,topic_str,OPENCLOSED[input_state[i]], false);
+        publish_value(client, ipstack,topic_str,OPENCLOSED[input_state[i]], false);
     }
 }
 
 
-void publish_info(MClient &client) {
+void publish_info(MQTT::Client<MQTTEthernet, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTEthernet* ipstack) {
     // uptime
     pc.printf("Uptime %d\r\n", uptime_sec);
     char uptime_sec_str[12]; // long enough string for a long int
     sprintf(uptime_sec_str, "%d", uptime_sec);
-    publish_value(client,"uptime",uptime_sec_str, false);
+    publish_value(client, ipstack,"uptime",uptime_sec_str, false);
     // alive
-    publish_value(client, "alive","ON", false);
+    publish_value(client, ipstack, "alive","ON", false);
 }
 
 
-void read_inputs(MClient &client) {
+void read_inputs(MQTT::Client<MQTTEthernet, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTEthernet* ipstack) {
     for(int i=0; i<NUM_INPUTS; i++) {
         bool old_state = input_state[i];    // save old state
         input_state[i] = inputs[i];         // read new value
@@ -226,13 +235,13 @@
             pc.printf("Input %d changed to %s\r\n", i, OPENCLOSED[input_state[i]]);
             char topic_str[8]; // long enough string for inputx
             sprintf(topic_str, "input%d", i);
-            publish_value(client,topic_str,OPENCLOSED[input_state[i]], false);
+            publish_value(client, ipstack,topic_str,OPENCLOSED[input_state[i]], false);
         }
     }
 }
 
 
-void read_dht(MClient &client) {
+void read_dht(MQTT::Client<MQTTEthernet, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTEthernet* ipstack) {
     int error = dht0.readData();
     if (0 == error) {
         temp[0]      = dht0.ReadTemperature(CELCIUS);
@@ -245,19 +254,19 @@
     // convert to string and publish
     char temp_str[6];
     sprintf(temp_str, "%3.1f", temp[0]);
-    publish_value(client,"temp0",temp_str, false);
+    publish_value(client, ipstack,"temp0",temp_str, false);
     char humidity_str[6];
     sprintf(humidity_str, "%3.1f", humidity[0]);
-    publish_value(client,"humidity0",humidity_str, false);
+    publish_value(client, ipstack,"humidity0",humidity_str, false);
 }
     
     
-void read_ds18b20(MClient &client, int num_ds18b20) {
+void read_ds18b20(MQTT::Client<MQTTEthernet, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTEthernet* ipstack, int num_ds18b20) {
     // Announce num of DS18B20 found
     char temp_str[6];
     char topic_str[6];
     sprintf(temp_str, "%d", num_ds18b20);
-    publish_value(client,"num_ds18b20",temp_str, false);
+    publish_value(client, ipstack,"num_ds18b20",temp_str, false);
     //Start temperature conversion, wait until ready
     probe[0]->convertTemperature(true, DS1820::all_devices);     
     for (int i = 0; i<num_ds18b20; i++) {
@@ -266,48 +275,45 @@
         // convert to string and publish
         sprintf(temp_str, "%3.3f", temp);
         sprintf(topic_str, "probetemp%d", i);
-        publish_value(client,topic_str,temp_str, false);
+        publish_value(client, ipstack,topic_str,temp_str, false);
     }
 }
 
 
-int networking_init(MQTTSocket &sock, MClient &client, WIZnetInterface &wiz) {
+int networking_init(MQTT::Client<MQTTEthernet, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTEthernet* ipstack) {
     int ret = 0;
     pc.printf("\n\nNode: %s\r\n", NODE_NAME);
     pc.printf("%s attempting ethernet connection...\r\n", NODE_NAME);
-    wiz.init(mac_addr); // resets the w5500
-    if (wiz.connect() == (-1)) {
-        pc.printf("Error getting DHCP address!!\r\n");
+    ret = ipstack->connect(mqtt_broker,mqtt_port);
+    if (ret != 0) {
+        pc.printf("Error connecting to MQTT broker!!\r\n");
+        return ret;
     }
     
-    pc.printf("IP: %s\r\n", wiz.getIPAddress());
-        
-    ret = sock.connect((char*)mqtt_broker,mqtt_port);
-    if(ret != 0){
-        pc.printf("failed to connect to TCP server\r\n");
-        return 1;
-    }
-    pc.printf("sock.connect()=%d\r\n",ret);
-        
-    if(client.connect() != 0){
-        pc.printf("MQTT connect failed\r\n");
-        return -1;
+    // MQTT Connect
+    MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
+    data.MQTTVersion = 3;
+    data.clientID.cstring = NODE_NAME;
+    
+    ret = client->connect(&data);
+    if (ret != 0) {
+        pc.printf("Error connecting to MQTT broker!!\r\n");
+        return ret;
+    }    
+
+    if ((ret = client->subscribe("cmnd/" NODE_NAME "/+", MQTT::QOS1, messageArrived)) == 0) {
+        // Node online message
+        publish_value(client, ipstack, "alive","ON", false);
+//        publish_value(client, ipstack, "IPAddress", ipstack.getip?, true);
+        pc.printf("Initialization done.\r\n");
+        return 0;
     }
-    pc.printf("client.connect()=%d\r\n",ret);
-    
-    ret = client.subscribe("cmnd/" NODE_NAME "/+", MQTT::QOS1, messageArrived);    
-    pc.printf("client.subscribe()=%d\r\n", ret);
-    // TODO add client ID when subscribing
-
-    // Node online message
-    publish_value(client, "alive","ON", false);
-    publish_value(client, "IPAddress", wiz.getIPAddress(), true);
-    pc.printf("Initialization done.\r\n");
-    
-    return 0;
+    else {    
+        return ret;
+    }
 } 
 
-void every_60sec() {
+void every_30sec() {
     // no waits or blocking routines here please!
     flag_read_dht = 1;
     flag_read_ds18b20 = 1;
@@ -315,6 +321,8 @@
 
 void every_5sec() {
     // no waits or blocking routines here please!
+//    flag_read_dht = 1;
+//    flag_read_ds18b20 = 1;
     flag_publish = 1;
 }
 
@@ -336,16 +344,17 @@
 
 int main()
 {
-    wd.Configure(20.0);
+    wd.Configure(30.0);
 //    WIZnetInterface wiz(PA_7, PA_6, PA_5, PA_4, NC); // SPI1 with no reset
-    WIZnetInterface wiz(PB_15, PB_14, PB_13, PB_12, PC_6); // SPI2 with D35 reset
-    MQTTSocket sock;
-    MClient client(sock);
+//    WIZnetInterface wiz(PB_15, PB_14, PB_13, PB_12, PC_6); // SPI2 with D35 reset
+    SPI spi(PB_15, PB_14, PB_13); // mosi, miso, sclk
+    MQTTEthernet ipstack(&spi, PB_12, PC_6);
+    MQTT::Client<MQTTEthernet, Countdown, MQTT_MAX_PACKET_SIZE> client(ipstack);
     
     tick_500ms.attach(&every_500ms, 0.5);
     tick_1sec.attach(&every_second, 1.0);
-    tick_5sec.attach(&every_5sec, 5.1);
-    tick_60sec.attach(&every_60sec, 59);
+    tick_5sec.attach(&every_5sec, 6.1);
+    tick_30sec.attach(&every_30sec, 29);
     
     //pulse all outputs
     for(int i=0; i<NUM_OUTPUTS; i++) {
@@ -356,7 +365,7 @@
     pc.printf("\n\nNode: %s\r\n", NODE_NAME);
     
     wd.Service();       // kick the dog before the timeout
-    connected = networking_init(sock, client, wiz);
+    connected = networking_init(&client, &ipstack);
 
     // Initialize DS18B20 probe array to DS1820 objects
     int num_ds18b20 = 0;
@@ -369,26 +378,26 @@
     pc.printf("DS18B20: Found %d device(s)\r\n", num_ds18b20);
     
     while(1) {
-        read_inputs(client);
+        read_inputs(&client, &ipstack);
         
         if(connected != 0) {
             pc.printf("Restarting network....\r\n");
-            connected = networking_init(sock, client, wiz);
+            connected = networking_init(&client, &ipstack);
         }
         else {
             // we're connected, do stuff!
             if(flag_publish) {
-                publish_outputs(client);
-                publish_inputs(client);
-                publish_info(client);
+                publish_outputs(&client, &ipstack);
+                publish_inputs(&client, &ipstack);
+                publish_info(&client, &ipstack);
                 flag_publish = 0;
             }
             else if(flag_read_dht) {
-                read_dht(client);
+                read_dht(&client, &ipstack);
                 flag_read_dht = 0;
             }
             else if(flag_read_ds18b20) {
-                read_ds18b20(client, num_ds18b20);
+                read_ds18b20(&client, &ipstack, num_ds18b20);
                 flag_read_ds18b20 = 0;
             }
         }