IoT sensor/controller using STM32, W5500 ethernet, MQTT

Dependencies:   mbed WIZnet_Library Watchdog DHT MQTT DS1820

main.cpp

Committer:
Geekshow
Date:
2020-02-24
Revision:
5:b2ae1ed8a30e
Parent:
4:ebaf1973d008
Child:
6:4d30bc5a8076

File content as of revision 5:b2ae1ed8a30e:

#include "mbed.h"
//#include "rtos.h"
//#include "pins.h"
#include "WIZnetInterface.h"
#include "MQTTSocket.h"
#include "MQTTClient.h"

// ========== PIN DEFINITIONS ============
#define NUM_OF_OUTPUTS 11
#define NUM_OF_INPUTS 12

#define LED_GREEN PA_5
#define LED_ORANGE PA_1 // Don't use! Shared with D3
#define BUTTON PC_9

#define ANALOGPIN0 PC_0  // Analogue Input 0
#define ANALOGPIN1 PC_1  // Analogue Input 1
#define ANALOGPIN2 PC_2  // Analogue Input 2
#define ANALOGPIN3 PC_3  // Analogue Input 3
#define ANALOGPIN4 PC_4  // Analogue Input 4
#define ANALOGPIN5 PC_5  // Analogue Input 5

//#define INPUTPINx PC_15     // Don't use D23
#define INPUTPIN0 PB_9     // DHT22 digital pin (D24)
#define INPUTPIN1 PD_2     // DHT22 digital pin (D25)
#define INPUTPIN2 PC_10     // DHT22 digital pin (D26)
//#define INPUTPINx PB_0     // Don't use D27
//#define INPUTPINx PB_1     // Don't use D28
#define INPUTPIN3 PB_10     //  digital pin (D29)
#define INPUTPIN4 PB_11     //  digital pin (D30)
#define INPUTPIN5 PB_12     //  digital pin (D31)
#define INPUTPIN6 PB_13     //  digital pin (D32)
#define INPUTPIN7 PB_14     //  digital pin (D33)
#define INPUTPIN8 PB_15     //  digital pin (D34)
#define INPUTPIN9 PC_6      //  digital pin (D35)
#define INPUTPIN10 PC_7     //  digital pin (D36)
#define INPUTPIN11 PC_8     //  digital pin (D37)

#define OUTPUTPIN0 PA_3  // digital output D0
#define OUTPUTPIN1 PA_2  // digital output D1
#define OUTPUTPIN2 PA_0  // digital output D2
#define OUTPUTPIN3 PA_1  // digital output D3
#define OUTPUTPIN4 PB_5  // digital output D4
#define OUTPUTPIN5 PB_6  // digital output D5
#define OUTPUTPIN6 PA_8  // digital output D6
#define OUTPUTPIN7 PA_9  // digital output D7
#define OUTPUTPIN8 PA_10  // digital output D8
#define OUTPUTPIN9 PB_7  // digital output D9
//#define OUTPUTPINx PA_4  // digital output D10 - SPI1 SS
//#define OUTPUTPINx PA_4  // digital output D11 - SPI1 MOSI
//#define OUTPUTPINx PA_4  // digital output D12 - SPI1 MISO
//#define OUTPUTPINx PA_4  // digital output D13 - SPI1 CLK
#define OUTPUTPIN10 PB_8  // digital output D14
// ================= *************** ==================
#define USART3_TX PC_10
// ================= *************** ==================
#define NODE_NAME "controller03" // TODO just define node number

Ticker tick_5sec;
Ticker tick_1sec;

typedef MQTT::Client<MQTTSocket,Countdown> MClient;

const char* ONOFF[] = {"OFF", "ON"};
const char* OPENCLOSED[] = {"CLOSED", "OPEN"};

Serial pc(USART3_TX, NC); // serial debug output on D26 (pin 4 of Extension)

DigitalIn button(BUTTON);
DigitalOut led(LED_GREEN);
DigitalOut output0(OUTPUTPIN0);

uint8_t mac_addr[6]={0x00, 0x00, 0x00, 0xBE, 0xEF, 0x03}; // TODO make last byte dynamic
const char* mqtt_broker = "192.168.1.99";
const int mqtt_port = 1883;
unsigned long uptime_sec = 0;


const char* inputs[2] = {
    "button",
    NULL
};

const char* outputs[2] = {
    "output0",
    NULL
};


void on_control_cmd(const char* actuator_name, const char* control_value)
{
    int new_state = 0;
    pc.printf("Received CMD %s %s\r\n", actuator_name, control_value);
    if(strcmp(control_value, "ON") == 0) {
        pc.printf("ON value requested!\r\n");
        new_state = 1;
    }
    else if(strcmp(control_value, "OFF") == 0) {
        pc.printf("OFF value requested!\r\n");
        new_state = 0;
    }
    else {
        pc.printf("No value specified! In future return the current value...\r\n");
        return;
    }
    
    if(strcmp(actuator_name, "output0") == 0) {
        pc.printf("Output: %s updated to %d\r\n", actuator_name, new_state);
        led = new_state;
        output0 = new_state;
    }
}

void read_inputs()
{
    
}


void set_outputs()
{
}


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);
    if(ret == -1) {
        pc.printf("ERROR during client.publish() = %d\r\n",ret);
    }
    return ret;
}


void messageArrived(MQTT::MessageData& md)
{
    MQTT::Message &message = md.message;

    // copy message payload into local char array IMPROVE ME!
    char* payload = new char[message.payloadlen+1];
    if(!payload)
        return;
    memcpy(payload, message.payload, message.payloadlen);
    payload[message.payloadlen]='\0';
    
    // copy topic payload into local char array IMPROVE ME!
    char* topic = new char[md.topicName.lenstring.len+1];
    if(!topic){
        delete[] payload;
        return;
    }
    memcpy(topic, md.topicName.lenstring.data, md.topicName.lenstring.len);
    topic[md.topicName.lenstring.len]='\0';
    
    pc.printf("Rcvd: %s : %s\r\n", topic, payload);
    
    // split up topic string
    char *topics = strtok (topic,"/");
    for (int tok=0; tok<2 && topics != NULL; tok++)  // WARNING! hard coded 2 layer topic!
    {
//        pc.printf ("%s\r\n",topics);
        topics = strtok (NULL, "/");
    }
    on_control_cmd(topics, payload);
    delete[] topic;
    delete[] payload;
}


int publish_value(MClient &client, const char *topic, const char *buf)
{
    return publish(client, "stat", topic, buf, strlen(buf), true);
}

WIZnetInterface wiz(PA_7, PA_6, PA_5, PA_4, PB_10); // SPI1 with D29 (reset)
MQTTSocket sock;
MClient client(sock);
int connected = -1;

int networking_init(MQTTSocket &sock, MClient &client, WIZnetInterface &wiz) {
    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");
    }
    
    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;
    }
    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);

    // Node online message
    publish_value(client, "alive","ON");
    publish_value(client, "IPAddress", wiz.getIPAddress());
    pc.printf("Initialization done.\r\n");
    
    return 0;
} 

void periodic_announcement() {
    // announce statuses
    char uptime_sec_str[12];
    sprintf(uptime_sec_str, "%d", uptime_sec);
    connected = publish_value(client,"uptime",uptime_sec_str);
}

void every_second() {
    uptime_sec++;
}

int main()
{
    tick_1sec.attach(&every_second, 1.0);
    pc.printf("\n\nNode: %s\r\n", NODE_NAME);

    connected = networking_init(sock, client, wiz);
    
    tick_5sec.attach(&periodic_announcement, 5.0);

    while(1) {
        set_outputs();
        read_inputs();
        
        
        if(connected != 0) {
            pc.printf("Restarting network....\r\n");
            networking_init(sock, client, wiz);
        }
        // pause a while, yawn......
//        client.yield(1000);
    }
}