IoT sensor/controller using STM32, W5500 ethernet, MQTT

Dependencies:   mbed WIZnet_Library Watchdog DHT MQTT DS1820

main.cpp

Committer:
Geekshow
Date:
2020-02-23
Revision:
4:ebaf1973d008
Parent:
3:de9611d75590
Child:
5:b2ae1ed8a30e

File content as of revision 4:ebaf1973d008:

#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

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;
static Timer g_timer;   // TODO remove me

WIZnetInterface wiz(PA_7, PA_6, PA_5, PA_4, PB_10); // SPI1 with D29 (reset)
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);

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);
}

 
int networking_init(MQTTSocket &sock, MClient &client) {
    int ret = 0;
    g_timer.start();
    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());
    
    srand(rand()^g_timer.read_us()); // what is this doing?
    
    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);
    
    srand(rand()^g_timer.read_us()); // what is this doing?
    
    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(client, "stat","online");
    pc.printf("Initialization done.\r\n");
    
    return 0;
}


int main()
{
    MQTTSocket sock;
    MClient client(sock);

    int connected = networking_init(sock, client);

    bool btn = 0;

    while(1) {
        set_outputs();
        read_inputs();
        
        // replace this hacky mess with read_inputs!
        bool newBTN = button;
        if(newBTN != btn) {
            publish_value(client,"input0",OPENCLOSED[newBTN]);
            btn = newBTN;
        } else {
            client.yield(1000);
            connected = publish_value(client,"stat","hello world");
            if(connected != 0) {
                pc.printf("Restarting network....\r\n");
                networking_init(sock, client);
            }
        }
    }
}