Eric Micallef / Mbed OS smat_controller

Dependencies:   MQTT

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers mqtt.cpp Source File

mqtt.cpp

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2018 ARM Limited
00003  * SPDX-License-Identifier: Apache-2.0
00004  */
00005 
00006 #include "mbed.h"
00007 #include "MQTTNetwork.h"
00008 #include "MQTTClient.h"
00009 #include "MQTTmbed.h"
00010 #include "mqtt.h"
00011 #include <assert.h>
00012 #include "AccCar.h"
00013 
00014 // topics interested in 
00015 #define POSITION_TOPIC "MQTT_Position0x25"
00016 #define CONTROL_TOPIC "MQTT_Control0x25"
00017 
00018 #define DEBUG_MQTT
00019  
00020 Serial mqtt_pc (USBTX, USBRX);
00021 
00022 
00023 // empty constructor
00024 mqtt::mqtt()
00025 {
00026     
00027 }
00028 
00029 /*
00030     This function sets up the wifi module and connects it to the SSID 
00031     configured in the configuration file. It also prints out the MAC address 
00032     of the module, which is needed if you are trying to use campus wifi.
00033     This function returns NULL if there are any issues.
00034 */
00035 WiFiInterface* mqtt::setup_wifi() {
00036     // Get a handle to the WiFi module
00037     WiFiInterface* wifi = WiFiInterface::get_default_instance();
00038     
00039     // Connect the module to the wifi, based on the SSID and password 
00040     // specified in the mbed_app.json configuration file
00041     // If you are using AirPennNet-Device, this will not succeed until the MAC
00042     // address (printed shortly after this) is registered
00043     mqtt_pc.printf("Connecting to wifi\r\n");
00044     int rc = wifi->connect(MBED_CONF_APP_WIFI_SSID, MBED_CONF_APP_WIFI_PASSWORD, NSAPI_SECURITY_WPA_WPA2);
00045     
00046     // Print out the MAC address of the wifi module. The MAC address is 
00047     // needed to register the device with AirPennNet-Device, so that you
00048     // can use the campus wifi
00049     mqtt_pc.printf("MAC Address: ");
00050     mqtt_pc.printf(wifi->get_mac_address());
00051     mqtt_pc.printf("\r\n");
00052     
00053     if (rc != 0) {
00054         mqtt_pc.printf("Problem connecting to wifi\r\n");   
00055         return NULL;
00056     } else {
00057         mqtt_pc.printf("Wifi connected\r\n");  
00058     }
00059       
00060     return wifi;
00061 }
00062 
00063 /*
00064     This function creates the MQTT client and connects it to the MQTT broker
00065     that we have setup for the course. If there are any errors with the 
00066     connection, it will return NULL
00067 */
00068 MQTT::Client<MQTTNetwork, Countdown>* mqtt::setup_mqtt(MQTTNetwork& network) {
00069     // the hostname and port point to a Google Cloud MQTT server we setup for
00070     // this project
00071     const char* hostname = "34.68.206.11";
00072     int port = 1883;
00073     
00074     // Create the underlying network connection to the MQTT server
00075     mqtt_pc.printf("Connecting to %s:%d\r\n", hostname, port);
00076     int rc = network.connect(hostname, port);
00077     if (rc != 0) {
00078         mqtt_pc.printf("There was an error with the TCP connect: %d\r\n", rc);
00079         return NULL;
00080     }
00081     
00082     mqtt_pc.printf("Connected to %s:%d\r\n", hostname, port);
00083         
00084     // Connect the MQTT client to the server
00085     MQTT::Client<MQTTNetwork, Countdown>* temp_client = new MQTT::Client<MQTTNetwork, Countdown>(network);
00086     rc = temp_client->connect();
00087     if (rc != 0) {
00088         mqtt_pc.printf("There was an error with the MQTT connect: %d\r\n", rc);
00089         return NULL;
00090     }
00091     
00092     mqtt_pc.printf("MQTT connect successful!\r\n");
00093     
00094     return temp_client;
00095 }
00096 
00097 /*
00098     This function is the callback for when a message is received from the 
00099     MQTT broker. You register different callback functions with different
00100     topic subscriptions
00101 */
00102 void mqtt::control_message_arrived(MQTT::MessageData& md)
00103 {
00104     MQTT::Message &message = md.message;
00105     // make message
00106     control_msg_t* msg = new control_msg_t;
00107     assert(msg != NULL && message.payloadlen == sizeof(control_msg_t));
00108     
00109     // copy to our new pointer for some reason just taking the payload ptr is bad for mbed?
00110     memcpy(msg,message.payload,message.payloadlen);
00111 
00112 #ifdef DEBUG_MQTT  
00113     //mqtt_pc.printf("Message arrived: qos %d, retained %d, dup %d, packetid %d\r\n", message.qos, message.retained, message.dup, message.id);
00114     mqtt_pc.printf("speed %d id %d \r\n", msg->speed, msg->car_id);
00115 #endif 
00116 
00117     // add our message to the queue no fucking clue what happens internally to
00118     // the message memory
00119     mqtt::instance()->add_to_control_queue(msg->car_id,msg);
00120     
00121     // free message
00122     delete msg;
00123 }
00124 
00125 /*
00126     This function sends a message to the test topic.
00127 */
00128 int mqtt::send_position_msg( position_msg_t* msg ) 
00129 {
00130     assert(msg != NULL && client != NULL);
00131     
00132     MQTT::Message message;
00133 
00134     // might be safest to memcopy thius seems to work
00135     //memcpy(message.payload,msg,sizeof(position_msg_t));
00136     message.payload = (void*)msg;
00137     message.payloadlen = sizeof(position_msg_t); 
00138     message.qos = MQTT::QOS1;
00139 
00140 #ifdef DEBUG_MQTT
00141     mqtt_pc.printf("Sending a message!\r\n");
00142 #endif
00143 
00144     int rc = client->publish(POSITION_TOPIC,message);
00145     assert(rc == 0);  
00146 
00147     client->yield(1000);
00148     return 0;
00149 }
00150 
00151 void mqtt::bringup_network() {
00152     
00153     // 
00154     WiFiInterface* wifi = setup_wifi();
00155     assert(wifi != NULL);
00156     
00157     // Create the network object needed by the MQTT client
00158     new_network = new MQTTNetwork(wifi);
00159     
00160     // get client
00161     client = setup_mqtt(*new_network);
00162     assert(client != NULL);
00163 
00164     // Subscribe to a topic / register a callback  
00165     mqtt_pc.printf("Subscribing to topic %s\r\n", CONTROL_TOPIC);
00166     int rc = client->subscribe(CONTROL_TOPIC, MQTT::QOS1, control_message_arrived);
00167     assert(rc == 0);
00168     
00169     // make a road based of mqtt id
00170     mqtt_id = 0;
00171     if(strcmp(wifi->get_mac_address(),"2c:3a:e8:0b:75:06") == 0){
00172         mqtt_id = 0;
00173     }
00174     else{
00175         mqtt_id = 1;
00176     }
00177     
00178     mqtt_pc.printf("Subscribed, Setup complete!\r\n");
00179 }
00180 
00181 
00182 // manage callbacks from mqtt
00183 void mqtt::manage_network()
00184 {
00185     while(true)
00186     {
00187         //
00188         osEvent evt = position_queue.get();
00189         assert(evt.status == osEventMessage);
00190         
00191         //
00192         position_msg_t *message = (position_msg_t*)evt.value.p;
00193         send_position_msg(message);
00194 
00195 //      client->yield(100);
00196     }
00197 }
00198 
00199 //
00200 // clean up goes here
00201 void mqtt::shutdown_network()
00202 {    
00203     //
00204     mqtt_pc.printf("shutting down mbed\r\n");
00205     
00206     //
00207     client->disconnect();
00208     delete new_network;
00209     
00210     //
00211     thread->terminate();
00212     delete thread;
00213 }
00214 
00215 // launch network manager thread
00216 // responsible for pub sub 
00217 void mqtt::setup_network()
00218 {
00219     // bring up network if anything bad happens we will assert and crash
00220     bringup_network();
00221     
00222     // create a new thread thats sole purpose in life is to call client yield
00223     // what a sad life for a thread
00224     // calling yield is necessary as we will not get any messages for the mqtt 
00225     // serverwithout it
00226     thread = new Thread();
00227     assert(thread != NULL);
00228     thread->start( callback(this,&mqtt::manage_network) );
00229     
00230 }