Masa Kovacevic 2020/0229
Dependencies: 19E042PIM_MB_PINS
main.cpp@0:6380a1c94d6c, 2021-11-25 (annotated)
- Committer:
- tzwell
- Date:
- Thu Nov 25 18:58:24 2021 +0000
- Revision:
- 0:6380a1c94d6c
- Child:
- 1:c994530bdb3d
first publish first commit
Who changed what in which revision?
User | Revision | Line number | New 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 | 0:6380a1c94d6c | 37 | // WiFi network handler: |
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 | 0:6380a1c94d6c | 52 | |
tzwell | 0:6380a1c94d6c | 53 | // Returning a string for a provided network encryption: |
tzwell | 0:6380a1c94d6c | 54 | const char *sec2str(nsapi_security_t sec) |
tzwell | 0:6380a1c94d6c | 55 | { |
tzwell | 0:6380a1c94d6c | 56 | switch (sec) |
tzwell | 0:6380a1c94d6c | 57 | { |
tzwell | 0:6380a1c94d6c | 58 | case NSAPI_SECURITY_NONE: |
tzwell | 0:6380a1c94d6c | 59 | return "None"; |
tzwell | 0:6380a1c94d6c | 60 | case NSAPI_SECURITY_WEP: |
tzwell | 0:6380a1c94d6c | 61 | return "WEP"; |
tzwell | 0:6380a1c94d6c | 62 | case NSAPI_SECURITY_WPA: |
tzwell | 0:6380a1c94d6c | 63 | return "WPA"; |
tzwell | 0:6380a1c94d6c | 64 | case NSAPI_SECURITY_WPA2: |
tzwell | 0:6380a1c94d6c | 65 | return "WPA2"; |
tzwell | 0:6380a1c94d6c | 66 | case NSAPI_SECURITY_WPA_WPA2: |
tzwell | 0:6380a1c94d6c | 67 | return "WPA/WPA2"; |
tzwell | 0:6380a1c94d6c | 68 | case NSAPI_SECURITY_UNKNOWN: |
tzwell | 0:6380a1c94d6c | 69 | default: |
tzwell | 0:6380a1c94d6c | 70 | return "Unknown"; |
tzwell | 0:6380a1c94d6c | 71 | } |
tzwell | 0:6380a1c94d6c | 72 | } |
tzwell | 0:6380a1c94d6c | 73 | |
tzwell | 0:6380a1c94d6c | 74 | int scan_demo(WiFiInterface *wifi) |
tzwell | 0:6380a1c94d6c | 75 | { |
tzwell | 0:6380a1c94d6c | 76 | // Creating an access point |
tzwell | 0:6380a1c94d6c | 77 | WiFiAccessPoint *ap; |
tzwell | 0:6380a1c94d6c | 78 | |
tzwell | 0:6380a1c94d6c | 79 | printf("Scan:\n"); |
tzwell | 0:6380a1c94d6c | 80 | |
tzwell | 0:6380a1c94d6c | 81 | int count = wifi->scan(NULL,0); |
tzwell | 0:6380a1c94d6c | 82 | |
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 | 0:6380a1c94d6c | 89 | // Limit number of network arbitrary to 15 |
tzwell | 0:6380a1c94d6c | 90 | count = count < MAX_NETWORKS ? count : MAX_NETWORKS; |
tzwell | 0:6380a1c94d6c | 91 | |
tzwell | 0:6380a1c94d6c | 92 | // Create a new object, array of WiFi APs, and assign it to ap variable: |
tzwell | 0:6380a1c94d6c | 93 | ap = new WiFiAccessPoint[count]; |
tzwell | 0:6380a1c94d6c | 94 | count = wifi->scan(ap, count); |
tzwell | 0:6380a1c94d6c | 95 | |
tzwell | 0:6380a1c94d6c | 96 | if (count <= 0) |
tzwell | 0:6380a1c94d6c | 97 | { |
tzwell | 0:6380a1c94d6c | 98 | printf("scan() failed with return value: %d\n", count); |
tzwell | 0:6380a1c94d6c | 99 | return 0; |
tzwell | 0:6380a1c94d6c | 100 | } |
tzwell | 0:6380a1c94d6c | 101 | |
tzwell | 0:6380a1c94d6c | 102 | // Print network information: |
tzwell | 0:6380a1c94d6c | 103 | for (int i = 0; i < count; i++) |
tzwell | 0:6380a1c94d6c | 104 | { |
tzwell | 0:6380a1c94d6c | 105 | printf("Network: %s secured: %s BSSID: %hhX:%hhX:%hhX:%hhx:%hhx:%hhx RSSI: %hhd Ch: %hhd\n", ap[i].get_ssid(), |
tzwell | 0:6380a1c94d6c | 106 | sec2str(ap[i].get_security()), ap[i].get_bssid()[0], ap[i].get_bssid()[1], ap[i].get_bssid()[2], |
tzwell | 0:6380a1c94d6c | 107 | 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 | 108 | thread_sleep_for(PRINTF_DELAY_MS); |
tzwell | 0:6380a1c94d6c | 109 | } |
tzwell | 0:6380a1c94d6c | 110 | printf("%d networks available.\n", count); |
tzwell | 0:6380a1c94d6c | 111 | |
tzwell | 0:6380a1c94d6c | 112 | delete[] ap; |
tzwell | 0:6380a1c94d6c | 113 | return count; |
tzwell | 0:6380a1c94d6c | 114 | } |
tzwell | 0:6380a1c94d6c | 115 | |
tzwell | 0:6380a1c94d6c | 116 | void messageArrived(MQTT::MessageData& md) |
tzwell | 0:6380a1c94d6c | 117 | { |
tzwell | 0:6380a1c94d6c | 118 | MQTT::Message &message = md.message; |
tzwell | 0:6380a1c94d6c | 119 | //printf("Message arrived: qos %d, retained %d, dup %d, packetid %d\r\n", message.qos, message.retained, message.dup, message.id); |
tzwell | 0:6380a1c94d6c | 120 | printf("Message from the browser: %.*s\r\n", message.payloadlen, (char*)message.payload); |
tzwell | 0:6380a1c94d6c | 121 | ++arrivedcount; |
tzwell | 0:6380a1c94d6c | 122 | } |
tzwell | 0:6380a1c94d6c | 123 | |
tzwell | 0:6380a1c94d6c | 124 | void buttonFunction() { |
tzwell | 0:6380a1c94d6c | 125 | |
tzwell | 0:6380a1c94d6c | 126 | button_pressed=1; |
tzwell | 0:6380a1c94d6c | 127 | |
tzwell | 0:6380a1c94d6c | 128 | } |
tzwell | 0:6380a1c94d6c | 129 | |
tzwell | 0:6380a1c94d6c | 130 | int main() |
tzwell | 0:6380a1c94d6c | 131 | { |
tzwell | 0:6380a1c94d6c | 132 | sw1.fall(&buttonFunction); |
tzwell | 0:6380a1c94d6c | 133 | const char* hostname = "broker.hivemq.com"; |
tzwell | 0:6380a1c94d6c | 134 | int port = 1883; |
tzwell | 0:6380a1c94d6c | 135 | // Network interface |
tzwell | 0:6380a1c94d6c | 136 | |
tzwell | 0:6380a1c94d6c | 137 | wifi = WiFiInterface::get_default_instance(); |
tzwell | 0:6380a1c94d6c | 138 | if (!wifi) { |
tzwell | 0:6380a1c94d6c | 139 | printf("ERROR: No WiFiInterface found.\n"); |
tzwell | 0:6380a1c94d6c | 140 | return -1; |
tzwell | 0:6380a1c94d6c | 141 | } |
tzwell | 0:6380a1c94d6c | 142 | |
tzwell | 0:6380a1c94d6c | 143 | int count = scan_demo(wifi); |
tzwell | 0:6380a1c94d6c | 144 | if (count == 0) { |
tzwell | 0:6380a1c94d6c | 145 | printf("No WIFI APs found - can't continue further.\n"); |
tzwell | 0:6380a1c94d6c | 146 | return -1; |
tzwell | 0:6380a1c94d6c | 147 | } |
tzwell | 0:6380a1c94d6c | 148 | |
tzwell | 0:6380a1c94d6c | 149 | printf("\nConnecting to %s...\n", MBED_CONF_APP_WIFI_SSID); |
tzwell | 0:6380a1c94d6c | 150 | int ret = wifi->connect(MBED_CONF_APP_WIFI_SSID, MBED_CONF_APP_WIFI_PASSWORD, NSAPI_SECURITY_WPA_WPA2); |
tzwell | 0:6380a1c94d6c | 151 | if (ret != 0) { |
tzwell | 0:6380a1c94d6c | 152 | printf("\nConnection error: %d\n", ret); |
tzwell | 0:6380a1c94d6c | 153 | return -1; |
tzwell | 0:6380a1c94d6c | 154 | } |
tzwell | 0:6380a1c94d6c | 155 | |
tzwell | 0:6380a1c94d6c | 156 | printf("Success\n\n"); |
tzwell | 0:6380a1c94d6c | 157 | printf("MAC: %s\n", wifi->get_mac_address()); |
tzwell | 0:6380a1c94d6c | 158 | printf("IP: %s\n", wifi->get_ip_address()); |
tzwell | 0:6380a1c94d6c | 159 | printf("Netmask: %s\n", wifi->get_netmask()); |
tzwell | 0:6380a1c94d6c | 160 | printf("Gateway: %s\n", wifi->get_gateway()); |
tzwell | 0:6380a1c94d6c | 161 | printf("RSSI: %d\n\n", wifi->get_rssi()); |
tzwell | 0:6380a1c94d6c | 162 | |
tzwell | 0:6380a1c94d6c | 163 | socket.open(wifi); |
tzwell | 0:6380a1c94d6c | 164 | socket.connect(hostname, port); |
tzwell | 0:6380a1c94d6c | 165 | |
tzwell | 0:6380a1c94d6c | 166 | MQTTPacket_connectData data = MQTTPacket_connectData_initializer; |
tzwell | 0:6380a1c94d6c | 167 | data.MQTTVersion = 3; |
tzwell | 0:6380a1c94d6c | 168 | data.clientID.cstring = "NUCLEO-L476RG-60"; |
tzwell | 0:6380a1c94d6c | 169 | |
tzwell | 0:6380a1c94d6c | 170 | int rc=0; |
tzwell | 0:6380a1c94d6c | 171 | if ((rc = client.connect(data)) != 0) |
tzwell | 0:6380a1c94d6c | 172 | printf("rc from MQTT connect is %d\r\n", rc); |
tzwell | 0:6380a1c94d6c | 173 | |
tzwell | 0:6380a1c94d6c | 174 | if ((rc = client.subscribe(topic_sub, MQTT::QOS2, messageArrived)) != 0) |
tzwell | 0:6380a1c94d6c | 175 | printf("rc from MQTT subscribe is %d\r\n", rc); |
tzwell | 0:6380a1c94d6c | 176 | |
tzwell | 0:6380a1c94d6c | 177 | while (true) { |
tzwell | 0:6380a1c94d6c | 178 | // Show that the loop is running by switching motherboard LED2: |
tzwell | 0:6380a1c94d6c | 179 | led2 = !led2; |
tzwell | 0:6380a1c94d6c | 180 | thread_sleep_for(BLINKING_RATE_MS); |
tzwell | 0:6380a1c94d6c | 181 | if (button_pressed==1) { |
tzwell | 0:6380a1c94d6c | 182 | button_pressed=0; |
tzwell | 0:6380a1c94d6c | 183 | // QoS 0 |
tzwell | 0:6380a1c94d6c | 184 | char buf[100]; |
tzwell | 0:6380a1c94d6c | 185 | sprintf(buf, "V(POT1) = %1.2f\r\n", pot1*VOLTAGE_SCALER); |
tzwell | 0:6380a1c94d6c | 186 | message.qos = MQTT::QOS0; |
tzwell | 0:6380a1c94d6c | 187 | message.retained = false; |
tzwell | 0:6380a1c94d6c | 188 | message.dup = false; |
tzwell | 0:6380a1c94d6c | 189 | message.payload = (void*)buf; |
tzwell | 0:6380a1c94d6c | 190 | message.payloadlen = strlen(buf)+1; |
tzwell | 0:6380a1c94d6c | 191 | client.publish(topic, message); |
tzwell | 0:6380a1c94d6c | 192 | } |
tzwell | 0:6380a1c94d6c | 193 | // Need to call yield API to maintain connection: |
tzwell | 0:6380a1c94d6c | 194 | client.yield(YIELD_TIMEOUT_MS); |
tzwell | 0:6380a1c94d6c | 195 | } |
tzwell | 0:6380a1c94d6c | 196 | } |