initial release

Dependencies:   BSP_B-L475E-IOT01 MQTT

Fork of Multiprotocol by Farnell-Element14 Bologna IOT Team

main.cpp

Committer:
fabio_gatti
Date:
2018-08-22
Revision:
5:69b70c8fc368
Parent:
4:591b0f33f8b0

File content as of revision 5:69b70c8fc368:

// main.cpp
#include <string>

#include "mbed.h"
#include "ISM43362Interface.h"
#include "TCPSocket.h"
//#include "HTS221Sensor.h"

#include "thingsboard_account.h"
// Sensors drivers present in the BSP library
#include "stm32l475e_iot01_tsensor.h"
#include "stm32l475e_iot01_hsensor.h"
#include "stm32l475e_iot01_psensor.h"
#include "stm32l475e_iot01_magneto.h"
#include "stm32l475e_iot01_gyro.h"
#include "stm32l475e_iot01_accelero.h"

// laser driver
//#include "lis3mdl_class.h"
#include "VL53L0X.h"

// H file per MQTT
#include "MQTTmbed.h"
#include "MQTTClient.h"

// H file per COAP
#include "sn_nsdl.h"
#include "sn_coap_protocol.h"
#include "sn_coap_header.h"

// Definitions ---------------------------------------------------------

// Change it with your WiFi network name
//#define WIFI_NETWORK_NAME       "farnell_iot_lab"
#define WIFI_NETWORK_NAME         "rucola"
// Change it with your WiFi password name
//#define WIFI_NETWORK_PASSWORD   "smartlab"
#define WIFI_NETWORK_PASSWORD     "Rosmarino_10"

#define WIFI_SECURITY             NSAPI_SECURITY_WPA_WPA2

#define COMM_PROTO                2

// scegliere il protocollo di trasporto dati
// COMM_PROTO = 0 -> accesso MQTT (default);
// COMM_PROTO = 1 -> access  HTTP;
// COMM_PROTO = 2 -> accesso COAP;
#ifndef COMM_PROTO
#define COMM_PROTO 0
#endif

// scegliere il token al device
#define DEVICE_ID                 1
#define DEVICE_ACCESS_TOKEN       SMART_BIN_1_DEVICE_ACCESS_TOKEN

//parametri rilevamento laser
#define MIN_DISTANCE_OBSTACLE     80 //distanza di rilevamento in mm
#define NUMBER_OF_OBSTACLE_FULL   3 //numero di letture per dichiarare il cestino pieno
#define TILT_THRESHOLD            700 //valore di soglia per ribaltamento pari a sin(angolo)*1000

// ciclo di frequenza lettura
#define SENSOR_READING_PERIOD     5000 //in ms

#if COMM_PROTO==0    //MQTT protocol

  #define MQTT_HOST               "demo.thingsboard.io"
  #define MQTT_PORT               1883
  #define MQTT_TOPIC              "v1/devices/me/telemetry"
  #define MQTT_MAX_MSG_LENGHT     500 //max mqtt lenght in byte

#elif COMM_PROTO==1  //HTTP protocol
  #define HTTP_HOST               "demo.thingsboard.io"
  #define HTTP_PORT               80
  #define HTTP_STR_1              "/api/v1/"
  #define HTTP_STR_2              "/telemetry"

#elif COMM_PROTO==2  //COAP protocol
  #define COAP_HOST               "demo.thingsboard.io"
  #define COAP_PORT               5683
  #define COAP_STR_1              "/api/v1/"
  #define COAP_STR_2              "/telemetry"
  
  #define SHOW_COAP_RESPONSE      false

#endif              //end protocol

// strutture comuni

#if COMM_PROTO == 0
class MQTTNetwork
{
public:
    MQTTNetwork(NetworkInterface* aNetwork) : network(aNetwork) {
        socket = new TCPSocket();
    }

    ~MQTTNetwork() {
        delete socket;
    }

    int read(unsigned char* buffer, int len, int timeout) {
        return socket->recv(buffer, len);
    }

    int write(unsigned char* buffer, int len, int timeout) {
        return socket->send(buffer, len);
    }

    int connect(const char* hostname, int port) {
        socket->open(network);
        return socket->connect(hostname, port);
    }

    int disconnect() {
        return socket->close();
    }

private:
    NetworkInterface* network;
    TCPSocket* socket;
};

#elif COMM_PROTO==2  //COAP protocol
UDPSocket socket;           // Socket to talk CoAP over
Thread recvfromThread;      // Thread to receive messages over CoAP
struct coap_s* coapHandle;
coap_version_e coapVersion = COAP_VERSION_1;

// CoAP HAL
void* coap_malloc(uint16_t size) {
    return malloc(size);
}

void coap_free(void* addr) {
    free(addr);
}

// tx_cb and rx_cb are not used in this program
uint8_t coap_tx_cb(uint8_t *a, uint16_t b, sn_nsdl_addr_s *c, void *d) {
    printf("coap tx cb\n");
    return 0;
}

int8_t coap_rx_cb(sn_coap_hdr_s *a, sn_nsdl_addr_s *b, void *c) {
    printf("coap rx cb\n");
    return 0;
}


#endif

#ifdef TARGET_DISCO_L475VG_IOT01A

static DevI2C devI2c(PB_11,PB_10);
static DigitalOut shutdown_pin(PC_6);
static VL53L0X range(&devI2c, &shutdown_pin, PC_7);

#endif

DigitalOut led(LED1);
Serial pc(USBTX, USBRX); //use these pins for serial coms.
int main()
{
    
    bool blnTilted = false; // variabile per l'assetto del cestino
    bool blnIsFull=false;   // variabile per lo stato (pieno/vuoto) del cestino
    int LaserCountObstacle=0; //contatore di ostacoli rilevati dal laser
  
    int count = 0;
    pc.baud(115200);

    
//initing sensori   
    float sensor_pressure_value = 0;
    float sensor_temperature_value = 0;
    float sensor_humidity_value = 0;
 
    int16_t pDataXYZ[3] = {0};
    //float pGyroDataXYZ[3] = {0};
  
    range.init_sensor(VL53L0X_DEFAULT_ADDRESS);
     
    BSP_TSENSOR_Init();
    BSP_HSENSOR_Init();
    BSP_PSENSOR_Init();

    //BSP_MAGNETO_Init();
    //BSP_GYRO_Init();
    BSP_ACCELERO_Init(); 

//initing sensori   
    
    
    printf(" --- START SESSION ---\n");
    ISM43362Interface wifi(MBED_CONF_APP_WIFI_SPI_MOSI,
            MBED_CONF_APP_WIFI_SPI_MISO,
            MBED_CONF_APP_WIFI_SPI_SCLK,
            MBED_CONF_APP_WIFI_SPI_NSS,
            MBED_CONF_APP_WIFI_RESET,
            MBED_CONF_APP_WIFI_DATAREADY,
            MBED_CONF_APP_WIFI_WAKEUP, false);

    // Scanning WiFi networks ------------------------------------------

    WiFiAccessPoint *ap;

    count = wifi.scan(NULL, 0);
    printf("%d networks available.\n", count);

    /* Limit number of network arbitrary to 15 */
    count = count < 15 ? count : 15;

    ap = new WiFiAccessPoint[count];
    count = wifi.scan(ap, count);
    for (int i = 0; i < count; i++) {
        printf("Network: %s RSSI: %hhd\n", ap[i].get_ssid(), ap[i].get_rssi());
    }

    delete[] ap;

    // Connecting to WiFi network --------------------------------------

    printf("\nConnecting to %s...\n", WIFI_NETWORK_NAME);
    int ret = wifi.connect(WIFI_NETWORK_NAME, WIFI_NETWORK_PASSWORD, WIFI_SECURITY);
    if (ret != 0) {
        printf("\nConnection error\n");
        return -1;
    }

    printf("Success\n\n");
    printf("MAC: %s\n", wifi.get_mac_address());
    printf("IP: %s\n", wifi.get_ip_address());
    printf("Netmask: %s\n", wifi.get_netmask());
    printf("Gateway: %s\n", wifi.get_gateway());
    printf("RSSI: %d\n\n", wifi.get_rssi());

#if COMM_PROTO == 0  //MQTT
    printf("Collegamento MQTT server: " MQTT_HOST  "\n");

    MQTTNetwork network(&wifi);
    MQTT::Client<MQTTNetwork, Countdown,MQTT_MAX_MSG_LENGHT> client(network); // attenzione alla MAX DIM MSG MQTT

    char assess_token[] = DEVICE_ACCESS_TOKEN;

    MQTTPacket_connectData conn_data = MQTTPacket_connectData_initializer;
    conn_data.username.cstring = assess_token;

    if (network.connect(MQTT_HOST, MQTT_PORT) < 0) {
      printf("failed to connect to " MQTT_HOST  "\n");
      return -1;
    }

    if (client.connect(conn_data) < 0) {
      printf("failed to send MQTT connect message\n");
      return -1;
    }

    printf("successfully connect to MQTT server!\n");

#elif COMM_PROTO == 1  //HTTP

    printf("Collegamento HTTP server: " HTTP_HOST  "\n");
    TCPSocket socket;
    nsapi_error_t response;

    // Open a socket on the network interface, and create a TCP connection 
    socket.open(&wifi);
    response = socket.connect(HTTP_HOST, HTTP_PORT);
    if(0 != response) {
        printf("Error connecting: %d\n", response);
        socket.close();
        return -1;
    }
    socket.close();
#elif COMM_PROTO == 2 // COAP
    
    //inserire un test di invio dati al server coap


#endif

// Initialize sensors --------------------------------------------------
/*
    DevI2C i2c_2(PB_11, PB_10);
    HTS221Sensor hum_temp(&i2c_2);

    hum_temp.init(NULL);
    hum_temp.enable();
    hum_temp.read_id(&id);
    printf("HTS221  humidity & temperature sensor = 0x%X\r\n", id);
*/
// Variabili di appoggio  -----------------------------------------------
#if COMM_PROTO == 1
    uint8_t http_request[1024];   
    char request_body[256];
    static   uint8_t http_resp[512];
    uint16_t reqLen;
    uint16_t respLen;

#elif COMM_PROTO == 2 // COAP
    char coap_body[256];
    char coap_uri_path[256];
    uint16_t coap_message_id;
    coap_message_id=0;
    

#endif




// ciclo di lettura sensori e caricamento su cloud       
for (;;) {
/*   
   
    float temp, humid;

    hum_temp.get_temperature(&temp);
    hum_temp.get_humidity(&humid);
    
    printf("ID: %d HTS221:  [temp] %.2f C, [hum]   %.2f%%\r\n", DEVICE_ID,temp, humid);
*/

    sensor_temperature_value = BSP_TSENSOR_ReadTemp();
    printf("TEMPERATURE: %.2f degC\n", sensor_temperature_value);

    sensor_humidity_value = BSP_HSENSOR_ReadHumidity();
    printf("HUMIDITY   : %.2f %%\n", sensor_humidity_value);

    sensor_pressure_value = BSP_PSENSOR_ReadPressure();
    printf("PRESSURE   : %.2f mBar\n", sensor_pressure_value);
    
    BSP_ACCELERO_AccGetXYZ(pDataXYZ);
    printf("ACCELERO_X : %d\n", pDataXYZ[0]);
    //printf("ACCELERO_Y = %d\n", pDataXYZ[1]);
    //printf("ACCELERO_Z = %d\n", pDataXYZ[2]);

    uint32_t distance;

    int status = range.get_distance(&distance);
    if (status == VL53L0X_ERROR_NONE) {
        printf("VL53L0X [mm]: %6ld\n", distance);
    } else {
        printf("VL53L0X [mm]: --\n");
    }
    if (abs(pDataXYZ[0]) < TILT_THRESHOLD)  {
        blnTilted = true;
    }  else {
        blnTilted = false;
    } //controllo inclinazione

    if (status == VL53L0X_ERROR_NONE && distance<=MIN_DISTANCE_OBSTACLE && LaserCountObstacle < NUMBER_OF_OBSTACLE_FULL){
        LaserCountObstacle++;
    } else if (status == VL53L0X_ERROR_NONE && distance>MIN_DISTANCE_OBSTACLE && LaserCountObstacle>0){
        LaserCountObstacle--;
    } //controllo distanza ostacolo
    
    if (LaserCountObstacle>=NUMBER_OF_OBSTACLE_FULL){
        blnIsFull = true;
    } else if (LaserCountObstacle == 0) {
        blnIsFull = false;
    }
    printf("laser counter: %d\n",LaserCountObstacle);

   
#if COMM_PROTO == 0
    char msg[256];  


    int n = snprintf(msg, sizeof(msg),
        "{\"ID\":%d,\"temperature\":%f, \"humidity\":%f, \"pressure\":%f, \"IsTilted\":%d, \"IsFull\":%d}",
        DEVICE_ID,sensor_temperature_value, sensor_humidity_value,sensor_pressure_value,blnTilted,blnIsFull);
    printf("messaggio: %s\n",msg);

    void *payload = reinterpret_cast<void*>(msg);
    size_t payload_len = n;
    printf("Message payload lenght: %d\r\n",payload_len);
    printf("publish to: %s %d %s\r\n", MQTT_HOST, MQTT_PORT, MQTT_TOPIC);
    if (client.publish(MQTT_TOPIC, payload, n) < 0) {
        printf("-- ERROR -- :failed to publish MQTT message\n");
    }
  
#elif COMM_PROTO == 1
    // ciclo di scrittura su socket
    // - open
    // - connect
    // - send 
    // - close
   
    socket.open(&wifi);
    response = socket.connect(HTTP_HOST, HTTP_PORT);
    if(0 != response) {
        printf("Error connecting: %d\n", response);
        socket.close();
        return -1;
    }
        
        
    // body of the request

    sprintf(request_body, "{\"ID\":%d,\"temperature\":%f, \"humidity\":%f, \"pressure\":%f, \"IsTilted\":%d, \"IsFull\":%d}",
        DEVICE_ID,sensor_temperature_value, sensor_humidity_value,sensor_pressure_value,blnTilted,blnIsFull);

    printf("messaggio: %s\r\n",request_body);


    // build header of the request
    sprintf((char *)http_request, "POST %s%s%s HTTP/1.1\r\nHost: %s \r\n", HTTP_STR_1,DEVICE_ACCESS_TOKEN,HTTP_STR_2, HTTP_HOST);
    strcat((char *)http_request, "Accept: */*\r\n");
    strcat((char *)http_request, "User-agent: ST-475-IOT\r\n");
    strcat((char *)http_request, "Connection: Close\r\n"); 
    char buffer[64];
    strcat((char *)http_request, "Content-Type: application/json\r\n");
    sprintf(buffer, "Content-Length: %d \r\n", strlen(request_body));
    strcat((char *)http_request, buffer);

    // append body to the header of the request
    strcat((char *)http_request, request_body);
    reqLen = strlen((char *)http_request);
    printf((char *)http_request);

    // Send a simple http request
    
    nsapi_size_t size = strlen((char *)http_request);
    response = 0;
    
    while(size)
    {
        response = socket.send(((char *)http_request)+response, size);
        
        if (response < 0) {
            printf("Error sending data: %d\n", response);
            socket.close();
            return -1;
        } else {
            size -= response;
            // Check if entire message was sent or not
            printf("sent %d [%.*s]\n", response, strstr((char *)http_request, "\r\n")-(char *)http_request, (char *)http_request);
        }
    }
    // pulizia risorse della socket
    socket.close();        
        
#elif COMM_PROTO == 2 //COAP              
   

    // Open a socket on the network interface
    socket.open(&wifi);

    // Initialize the CoAP protocol handle, pointing to local implementations on malloc/free/tx/rx functions
    coapHandle = sn_coap_protocol_init(&coap_malloc, &coap_free, &coap_tx_cb, &coap_rx_cb);


    // Path to the resource we want to retrieve
    sprintf(coap_uri_path, "%s%s%s", COAP_STR_1,DEVICE_ACCESS_TOKEN,COAP_STR_2);
    sprintf(coap_body, "{\"ID\":%d,\"temperature\":%f, \"humidity\":%f, \"pressure\":%f, \"IsTilted\":%d, \"IsFull\":%d}",
        DEVICE_ID,sensor_temperature_value, sensor_humidity_value,sensor_pressure_value,blnTilted,blnIsFull);

    printf ("URI PATH: %s\n",coap_uri_path);
    printf ("BODY: %s\n",coap_body);
    printf ("id: %d\n",coap_message_id);

    // See ns_coap_header.h
    sn_coap_hdr_s *coap_res_ptr = (sn_coap_hdr_s*)calloc(sizeof(sn_coap_hdr_s), 1);
    coap_res_ptr->uri_path_ptr = (uint8_t*)coap_uri_path;       // Path
    coap_res_ptr->uri_path_len = strlen(coap_uri_path);
    coap_res_ptr->msg_type = COAP_MSG_TYPE_NON_CONFIRMABLE;
    coap_res_ptr->msg_code = COAP_MSG_CODE_REQUEST_POST;         // CoAP method
    coap_res_ptr->content_format = COAP_CT_JSON;          // CoAP content type
    coap_res_ptr->payload_len = strlen(coap_body);                              // Body length
    coap_res_ptr->payload_ptr = (uint8_t*)coap_body;                              // Body pointer
    coap_res_ptr->options_list_ptr = 0;                         // Optional: options list
    coap_res_ptr->msg_id = coap_message_id;  //msg ID, don't forget to increase it
    coap_message_id++;
    
    // Calculate the CoAP message size, allocate the memory and build the message
    uint16_t message_len = sn_coap_builder_calc_needed_packet_data_size(coap_res_ptr);
    printf("Calculated message length: %d bytes\n", message_len);

    uint8_t* message_ptr = (uint8_t*)malloc(message_len);
    sn_coap_builder(message_ptr, coap_res_ptr);

    // Uncomment to see the raw buffer that will be sent...
     printf("Message is: ");
     for (size_t ix = 0; ix < message_len; ix++) {
         printf("%02x ", message_ptr[ix]);
     }
     printf("\n");

    int scount = socket.sendto(COAP_HOST, COAP_PORT, message_ptr, message_len);
    printf("Sent %d bytes to coap://%s:%d\n", scount,COAP_HOST, COAP_PORT);

// routine di ricezione    
#if SHOW_COAP_RESPONSE == true
    SocketAddress addr;
    uint8_t* recv_buffer = (uint8_t*)malloc(1280); // Suggested is to keep packet size under 1280 bytes
    
    if ((ret = socket.recvfrom(&addr, recv_buffer, 1280)) >= 0) {
        // to see where the message came from, inspect addr.get_addr() and addr.get_port()
  
        printf("Received packets from (%s,%d)\n", addr.get_ip_address(),addr.get_port());

        sn_coap_hdr_s* parsed = sn_coap_parser(coapHandle, ret, recv_buffer, &coapVersion);

        // We know the payload is going to be a string
        std::string payload((const char*)parsed->payload_ptr, parsed->payload_len);

        printf("\tmsg_id:           %d\n", parsed->msg_id);
        printf("\tmsg_code:         %d\n", parsed->msg_code);
        printf("\tcontent_format:   %d\n", parsed->content_format);
        printf("\tpayload_len:      %d\n", parsed->payload_len);
        printf("\tpayload:          %s\n", payload.c_str());
        printf("\toptions_list_ptr: %p\n", parsed->options_list_ptr);
    }

    free(recv_buffer);  
 

#endif //end SHOW_COAP_RESPONSE   
    socket.close();
    sn_coap_protocol_destroy(coapHandle);
    free(coap_res_ptr);
    free(message_ptr);

     
#endif //end protocol selection


    wait_ms(SENSOR_READING_PERIOD);
}

//le disconnect non vengono raggiunte perche' rimaniamo all'interno del ciclo
//client.disconnect();
//wifi.disconnect();

//printf("\ndone\n");
//return 0;

}