541 smart traffic controller

Dependencies:   MQTT

mqtt.h

Committer:
micallef25
Date:
2019-12-12
Revision:
7:fd8e0604faaa
Parent:
6:6cb13ac483e0

File content as of revision 7:fd8e0604faaa:

#ifndef _MQTT_H_
#define _MQTT_H_

#include "mbed.h"
#include "MQTTNetwork.h"
#include "MQTTClient.h"
#include "MQTTmbed.h"
#include <assert.h>

#define MAX_CARS_ON_ROAD 5

//#define WINDOWS

#ifdef WINDOWS
#define DELIM "\r\n"
#else
#define DELIM "\n"
#endif

//#define PUBLISH_ONLY
//#define SAFE_CRITICAL
enum drive_state_t{
 NORMAL_STATE = 0,
 STOPPED_STATE,
 CROSSING_STATE
};

typedef struct position_msg{
    int position;
    int speed;
    int car_id;
    int road_id; 
    int counter; // for debugging and ensuring everyone is synchronized
    //drive_state_t state; // for debugging
}position_msg_t;

typedef struct road_msg{
    int road_id;
    int road_clock;
    int simulating;
}road_msg_t;

typedef struct control_msg{
    int speed;
    int car_id;
    int road_id;
    int counter; // for debugging synchronization
}control_msg_t;


class mqtt{

private:
    // static functions for control message callbacks
    static void control_message_arrived(MQTT::MessageData& md);
    static void road_message_arrived(MQTT::MessageData& md);
    
    // functions for creatin of mqtt and wifi bring up
    WiFiInterface* setup_wifi();
    int send_position_msg(MQTT::Message& message,position_msg_t* msg);
    int send_road_msg(MQTT::Message& message,road_msg_t* msg);
    void manage_network();
    void bringup_network();
    
    // data structures needed for creation of network
    MQTT::Client<MQTTNetwork, Countdown>* client;
    MQTT::Client<MQTTNetwork, Countdown>* setup_mqtt(MQTTNetwork& network); 
    MQTTNetwork* new_network;
    
    // thread that will manage the mqtt network status
    Thread* thread;
    
    // queue for sending position msessages
    Queue<position_msg_t, 15> position_queue;
    
    // queue for sending road msessages
    Queue<road_msg_t, 3> road_to_network_queue;
    
    // queue for sending road msessages
    Queue<road_msg_t, 3> network_to_road_queue;
    
    // queue for control message passsing between mqtt and car threads
    Queue<control_msg_t, 3> control_queue[MAX_CARS_ON_ROAD];

    
public:
    // singleton instance for managing network
    // we can only have one network so this should prohibit accidental
    // creations of multiple objects
    static mqtt* mqtt_singleton;
    
    //
    int mqtt_id;
    
    // empty constructor
    mqtt();
    
    // setup and tear down API's
    void setup_network();
    void shutdown_network();
    void clear_queues();
    
    static mqtt *instance()
    {
        if (!mqtt_singleton)
          mqtt_singleton = new mqtt;
        return mqtt_singleton;
    }
    
    // adding to a queue to be sent on mqtt network
    inline void add_to_position_queue(position_msg_t* msg)
    {
        position_queue.put(msg,osWaitForever);
    }
    
    // adding to road queue to be sent on mqtt network
    inline void add_to_road_to_network_queue(road_msg_t* msg)
    {
        road_to_network_queue.put(msg,osWaitForever);
    }
    
    // adding to road queue to be sent on mqtt network
    inline void add_to_network_to_road_queue(road_msg_t* msg)
    {
        network_to_road_queue.put(msg,osWaitForever);
    }
    

    // adding to a queue to be sent on mqtt network
    inline void add_to_control_queue(int car_id,control_msg_t* msg)
    {
        control_queue[car_id].put(msg,osWaitForever);
    }
    
    // adding to a queue to be sent on mqtt network
    inline control_msg_t* get_control_msg(int car_id)
    {
        // handle the case if no message was received in time
#ifdef SAFETY_CRITICAL
        if(control_queue[car_id].empty())
        {
            return NULL;   
        }
#endif
        osEvent evt = control_queue[car_id].get(osWaitForever);
        assert(evt.status == osEventMessage);
        control_msg_t *message = (control_msg_t*)evt.value.p;
        return message;
    }
    
    // we are publishing and subscring to the road message
    // thus we need to ensure we are not grabbing our own
    inline road_msg_t* get_network_to_road_msg()
    {
        // get message from queue
        osEvent evt = network_to_road_queue.get(osWaitForever);
        assert(evt.status == osEventMessage);
        road_msg_t *message = (road_msg_t*)evt.value.p;
        // we handle ignoring messages in callback
        // delete the message and let the cars go 
        assert(mqtt_id != message->road_id );
        return message;
    }
    
};


#endif