Masa Kovacevic 2020/0229

Dependencies:   19E042PIM_MB_PINS

Committer:
tzwell
Date:
Sat Nov 27 20:33:49 2021 +0000
Revision:
1:c994530bdb3d
Parent:
0:6380a1c94d6c
Child:
2:c7fcce20f023
Commented in more detail

Who changed what in which revision?

UserRevisionLine numberNew contents of line
tzwell 0:6380a1c94d6c 1 /*
tzwell 0:6380a1c94d6c 2 * Program implements MQTT client on a NUCLEO-L476RG board
tzwell 0:6380a1c94d6c 3 * using arm mbed-mqtt library and ESP-WROOM-02 WiFi modem.
tzwell 0:6380a1c94d6c 4 *
tzwell 0:6380a1c94d6c 5 * University of Belgrade - School of Electrical Engineering
tzwell 0:6380a1c94d6c 6 * Department of Electronics
tzwell 0:6380a1c94d6c 7 * Bulevar Kralja Aleksandra 73, 11120 Belgrade, Serbia
tzwell 0:6380a1c94d6c 8 *
tzwell 0:6380a1c94d6c 9 * November 2021.
tzwell 0:6380a1c94d6c 10 *
tzwell 0:6380a1c94d6c 11 */
tzwell 0:6380a1c94d6c 12
tzwell 0:6380a1c94d6c 13 #include "mbed.h"
tzwell 0:6380a1c94d6c 14 #include "mb_pins.h"
tzwell 0:6380a1c94d6c 15 #include "platform/mbed_thread.h"
tzwell 0:6380a1c94d6c 16 #include "MQTTClientMbedOs.h"
tzwell 0:6380a1c94d6c 17
tzwell 0:6380a1c94d6c 18
tzwell 0:6380a1c94d6c 19 // LED2 blinking rate:
tzwell 0:6380a1c94d6c 20 #define BLINKING_RATE_MS 250
tzwell 0:6380a1c94d6c 21 // Scaler to 3v3L
tzwell 0:6380a1c94d6c 22 #define VOLTAGE_SCALER 3.3f
tzwell 0:6380a1c94d6c 23 // Client yield timeout in miliseconds:
tzwell 0:6380a1c94d6c 24 #define YIELD_TIMEOUT_MS 1000
tzwell 0:6380a1c94d6c 25 // Maximum number of networks to scan for:
tzwell 0:6380a1c94d6c 26 #define MAX_NETWORKS 15
tzwell 0:6380a1c94d6c 27 // Small delay for network information printing:
tzwell 0:6380a1c94d6c 28 #define PRINTF_DELAY_MS 10
tzwell 0:6380a1c94d6c 29
tzwell 0:6380a1c94d6c 30
tzwell 0:6380a1c94d6c 31 // Left potentiometer:
tzwell 0:6380a1c94d6c 32 AnalogIn pot1(MB_POT1);
tzwell 0:6380a1c94d6c 33 // Left button on the motherboard:
tzwell 0:6380a1c94d6c 34 InterruptIn sw1(MB_SW1);
tzwell 0:6380a1c94d6c 35 // Right LED on the motherboard:
tzwell 0:6380a1c94d6c 36 DigitalOut led2(MB_LED2);
tzwell 1:c994530bdb3d 37 // Pointer to a WiFi network object:
tzwell 0:6380a1c94d6c 38 WiFiInterface *wifi;
tzwell 0:6380a1c94d6c 39 // Creating TCP socket:
tzwell 0:6380a1c94d6c 40 TCPSocket socket;
tzwell 0:6380a1c94d6c 41 // Creating MQTT client using the TCP socket;
tzwell 0:6380a1c94d6c 42 MQTTClient client(&socket);
tzwell 0:6380a1c94d6c 43 // Message handler:
tzwell 0:6380a1c94d6c 44 MQTT::Message message;
tzwell 0:6380a1c94d6c 45
tzwell 0:6380a1c94d6c 46 char* topic = "mbed-sample-pub";
tzwell 0:6380a1c94d6c 47 char* topic_sub = "mbed-sample-sub";
tzwell 0:6380a1c94d6c 48 // Counter of arrived messages:
tzwell 0:6380a1c94d6c 49 int arrivedcount = 0;
tzwell 0:6380a1c94d6c 50 // Flag indicating that button is not pressed:
tzwell 0:6380a1c94d6c 51 int button_pressed=0;
tzwell 1:c994530bdb3d 52 // HiveMQ broker connectivity information:
tzwell 1:c994530bdb3d 53 const char* hostname = "broker.hivemq.com";
tzwell 1:c994530bdb3d 54 int port = 1883;
tzwell 0:6380a1c94d6c 55 // Returning a string for a provided network encryption:
tzwell 0:6380a1c94d6c 56 const char *sec2str(nsapi_security_t sec)
tzwell 0:6380a1c94d6c 57 {
tzwell 0:6380a1c94d6c 58 switch (sec)
tzwell 0:6380a1c94d6c 59 {
tzwell 0:6380a1c94d6c 60 case NSAPI_SECURITY_NONE:
tzwell 0:6380a1c94d6c 61 return "None";
tzwell 0:6380a1c94d6c 62 case NSAPI_SECURITY_WEP:
tzwell 0:6380a1c94d6c 63 return "WEP";
tzwell 0:6380a1c94d6c 64 case NSAPI_SECURITY_WPA:
tzwell 0:6380a1c94d6c 65 return "WPA";
tzwell 0:6380a1c94d6c 66 case NSAPI_SECURITY_WPA2:
tzwell 0:6380a1c94d6c 67 return "WPA2";
tzwell 0:6380a1c94d6c 68 case NSAPI_SECURITY_WPA_WPA2:
tzwell 0:6380a1c94d6c 69 return "WPA/WPA2";
tzwell 0:6380a1c94d6c 70 case NSAPI_SECURITY_UNKNOWN:
tzwell 0:6380a1c94d6c 71 default:
tzwell 0:6380a1c94d6c 72 return "Unknown";
tzwell 0:6380a1c94d6c 73 }
tzwell 0:6380a1c94d6c 74 }
tzwell 0:6380a1c94d6c 75
tzwell 1:c994530bdb3d 76 int scan_networks(WiFiInterface *wifi)
tzwell 0:6380a1c94d6c 77 {
tzwell 0:6380a1c94d6c 78 printf("Scan:\n");
tzwell 1:c994530bdb3d 79
tzwell 1:c994530bdb3d 80 // Scan only for the number of networks, first parameter is NULL:
tzwell 1:c994530bdb3d 81 int count = wifi->scan(NULL, 0);
tzwell 1:c994530bdb3d 82 // If there are no networks, count == 0, if there is an error, counter < 0:
tzwell 0:6380a1c94d6c 83 if (count <= 0)
tzwell 0:6380a1c94d6c 84 {
tzwell 0:6380a1c94d6c 85 printf("scan() failed with return value: %d\n", count);
tzwell 0:6380a1c94d6c 86 return 0;
tzwell 0:6380a1c94d6c 87 }
tzwell 0:6380a1c94d6c 88
tzwell 1:c994530bdb3d 89 // Limit number of network arbitrary to some reasonable number:
tzwell 0:6380a1c94d6c 90 count = count < MAX_NETWORKS ? count : MAX_NETWORKS;
tzwell 0:6380a1c94d6c 91
tzwell 1:c994530bdb3d 92 // Create a local pointer to an object, which is an array of WiFi APs:
tzwell 1:c994530bdb3d 93 WiFiAccessPoint *ap = new WiFiAccessPoint[count];
tzwell 1:c994530bdb3d 94 // Now scan again for 'count' networks and populate the array of APs:
tzwell 0:6380a1c94d6c 95 count = wifi->scan(ap, count);
tzwell 1:c994530bdb3d 96
tzwell 1:c994530bdb3d 97 // This time, the number of entries to 'ap' is returned:
tzwell 0:6380a1c94d6c 98 if (count <= 0)
tzwell 0:6380a1c94d6c 99 {
tzwell 0:6380a1c94d6c 100 printf("scan() failed with return value: %d\n", count);
tzwell 0:6380a1c94d6c 101 return 0;
tzwell 0:6380a1c94d6c 102 }
tzwell 0:6380a1c94d6c 103
tzwell 1:c994530bdb3d 104 // Print out the parameters of each AP:
tzwell 0:6380a1c94d6c 105 for (int i = 0; i < count; i++)
tzwell 0:6380a1c94d6c 106 {
tzwell 0:6380a1c94d6c 107 printf("Network: %s secured: %s BSSID: %hhX:%hhX:%hhX:%hhx:%hhx:%hhx RSSI: %hhd Ch: %hhd\n", ap[i].get_ssid(),
tzwell 0:6380a1c94d6c 108 sec2str(ap[i].get_security()), ap[i].get_bssid()[0], ap[i].get_bssid()[1], ap[i].get_bssid()[2],
tzwell 0:6380a1c94d6c 109 ap[i].get_bssid()[3], ap[i].get_bssid()[4], ap[i].get_bssid()[5], ap[i].get_rssi(), ap[i].get_channel());
tzwell 0:6380a1c94d6c 110 thread_sleep_for(PRINTF_DELAY_MS);
tzwell 0:6380a1c94d6c 111 }
tzwell 0:6380a1c94d6c 112 printf("%d networks available.\n", count);
tzwell 1:c994530bdb3d 113
tzwell 1:c994530bdb3d 114 // Since 'ap' is dynamically allocated pointer to the array of objects, it
tzwell 1:c994530bdb3d 115 // needs to be deleted:
tzwell 0:6380a1c94d6c 116 delete[] ap;
tzwell 0:6380a1c94d6c 117 return count;
tzwell 0:6380a1c94d6c 118 }
tzwell 0:6380a1c94d6c 119
tzwell 0:6380a1c94d6c 120 void messageArrived(MQTT::MessageData& md)
tzwell 0:6380a1c94d6c 121 {
tzwell 0:6380a1c94d6c 122 MQTT::Message &message = md.message;
tzwell 0:6380a1c94d6c 123 //printf("Message arrived: qos %d, retained %d, dup %d, packetid %d\r\n", message.qos, message.retained, message.dup, message.id);
tzwell 0:6380a1c94d6c 124 printf("Message from the browser: %.*s\r\n", message.payloadlen, (char*)message.payload);
tzwell 0:6380a1c94d6c 125 ++arrivedcount;
tzwell 0:6380a1c94d6c 126 }
tzwell 0:6380a1c94d6c 127
tzwell 0:6380a1c94d6c 128 void buttonFunction() {
tzwell 0:6380a1c94d6c 129
tzwell 0:6380a1c94d6c 130 button_pressed=1;
tzwell 0:6380a1c94d6c 131
tzwell 0:6380a1c94d6c 132 }
tzwell 0:6380a1c94d6c 133
tzwell 0:6380a1c94d6c 134 int main()
tzwell 0:6380a1c94d6c 135 {
tzwell 1:c994530bdb3d 136 // Set the interrupt event:
tzwell 1:c994530bdb3d 137 sw1.fall(&buttonFunction);
tzwell 0:6380a1c94d6c 138
tzwell 1:c994530bdb3d 139 // Create a default network interface:
tzwell 0:6380a1c94d6c 140 wifi = WiFiInterface::get_default_instance();
tzwell 0:6380a1c94d6c 141 if (!wifi) {
tzwell 0:6380a1c94d6c 142 printf("ERROR: No WiFiInterface found.\n");
tzwell 0:6380a1c94d6c 143 return -1;
tzwell 0:6380a1c94d6c 144 }
tzwell 1:c994530bdb3d 145
tzwell 1:c994530bdb3d 146 // Scan for available networks and aquire information about Access Points:
tzwell 1:c994530bdb3d 147 int count = scan_networks(wifi);
tzwell 0:6380a1c94d6c 148 if (count == 0) {
tzwell 0:6380a1c94d6c 149 printf("No WIFI APs found - can't continue further.\n");
tzwell 0:6380a1c94d6c 150 return -1;
tzwell 0:6380a1c94d6c 151 }
tzwell 1:c994530bdb3d 152
tzwell 1:c994530bdb3d 153 // Connect to the network with the parameters specified in 'mbed_app.json':
tzwell 0:6380a1c94d6c 154 printf("\nConnecting to %s...\n", MBED_CONF_APP_WIFI_SSID);
tzwell 0:6380a1c94d6c 155 int ret = wifi->connect(MBED_CONF_APP_WIFI_SSID, MBED_CONF_APP_WIFI_PASSWORD, NSAPI_SECURITY_WPA_WPA2);
tzwell 0:6380a1c94d6c 156 if (ret != 0) {
tzwell 0:6380a1c94d6c 157 printf("\nConnection error: %d\n", ret);
tzwell 0:6380a1c94d6c 158 return -1;
tzwell 0:6380a1c94d6c 159 }
tzwell 1:c994530bdb3d 160
tzwell 1:c994530bdb3d 161 // Print out the information aquired:
tzwell 0:6380a1c94d6c 162 printf("Success\n\n");
tzwell 0:6380a1c94d6c 163 printf("MAC: %s\n", wifi->get_mac_address());
tzwell 0:6380a1c94d6c 164 printf("IP: %s\n", wifi->get_ip_address());
tzwell 0:6380a1c94d6c 165 printf("Netmask: %s\n", wifi->get_netmask());
tzwell 0:6380a1c94d6c 166 printf("Gateway: %s\n", wifi->get_gateway());
tzwell 0:6380a1c94d6c 167 printf("RSSI: %d\n\n", wifi->get_rssi());
tzwell 1:c994530bdb3d 168
tzwell 1:c994530bdb3d 169 // Open TCP socket using WiFi network interface:
tzwell 0:6380a1c94d6c 170 socket.open(wifi);
tzwell 1:c994530bdb3d 171 // Connect to the HiveMQ broker:
tzwell 0:6380a1c94d6c 172 socket.connect(hostname, port);
tzwell 1:c994530bdb3d 173 // Fill connect data with default values:
tzwell 0:6380a1c94d6c 174 MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
tzwell 1:c994530bdb3d 175 // Change only ID and protocol version:
tzwell 0:6380a1c94d6c 176 data.MQTTVersion = 3;
tzwell 0:6380a1c94d6c 177 data.clientID.cstring = "NUCLEO-L476RG-60";
tzwell 0:6380a1c94d6c 178
tzwell 1:c994530bdb3d 179 // Connect the
tzwell 1:c994530bdb3d 180 int rc = 0;
tzwell 0:6380a1c94d6c 181 if ((rc = client.connect(data)) != 0)
tzwell 0:6380a1c94d6c 182 printf("rc from MQTT connect is %d\r\n", rc);
tzwell 0:6380a1c94d6c 183
tzwell 0:6380a1c94d6c 184 if ((rc = client.subscribe(topic_sub, MQTT::QOS2, messageArrived)) != 0)
tzwell 0:6380a1c94d6c 185 printf("rc from MQTT subscribe is %d\r\n", rc);
tzwell 0:6380a1c94d6c 186
tzwell 0:6380a1c94d6c 187 while (true) {
tzwell 0:6380a1c94d6c 188 // Show that the loop is running by switching motherboard LED2:
tzwell 0:6380a1c94d6c 189 led2 = !led2;
tzwell 0:6380a1c94d6c 190 thread_sleep_for(BLINKING_RATE_MS);
tzwell 0:6380a1c94d6c 191 if (button_pressed==1) {
tzwell 0:6380a1c94d6c 192 button_pressed=0;
tzwell 0:6380a1c94d6c 193 // QoS 0
tzwell 0:6380a1c94d6c 194 char buf[100];
tzwell 0:6380a1c94d6c 195 sprintf(buf, "V(POT1) = %1.2f\r\n", pot1*VOLTAGE_SCALER);
tzwell 0:6380a1c94d6c 196 message.qos = MQTT::QOS0;
tzwell 0:6380a1c94d6c 197 message.retained = false;
tzwell 0:6380a1c94d6c 198 message.dup = false;
tzwell 0:6380a1c94d6c 199 message.payload = (void*)buf;
tzwell 0:6380a1c94d6c 200 message.payloadlen = strlen(buf)+1;
tzwell 0:6380a1c94d6c 201 client.publish(topic, message);
tzwell 0:6380a1c94d6c 202 }
tzwell 0:6380a1c94d6c 203 // Need to call yield API to maintain connection:
tzwell 0:6380a1c94d6c 204 client.yield(YIELD_TIMEOUT_MS);
tzwell 0:6380a1c94d6c 205 }
tzwell 0:6380a1c94d6c 206 }