IoT sensor/controller using STM32, W5500 ethernet, MQTT
Dependencies: mbed WIZnet_Library Watchdog DHT MQTT DS1820
Diff: main.cpp
- 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; } }