Example program that shows how to use the Secure (TLS) SharkMQ library included in SharkSSL-Lite
Dependencies: EthernetInterface SharkSSL-Lite mbed-rtos mbed
Introduction
The SMQ Architecture is an Internet of Things (IoT) publish subscribe end-to-end solution that is optimized for embedded systems to provide instantaneous Device Edge Node connectivity, 1 to 1 Communications, and Ease of Transcending Firewalls. The solution is ideal for resource constrained devices that require real-time dynamic control, analytic information, and firmware updates in both LAN and WAN environments.
Architecture Component List
- SMQ C Client (Non-secure)
- SharkMQ Secure C Client (this mbed example)
- SMQjs (Javascript)
- SMQ JAVA
- SMQ Broker
SharkMQ-LED-Demo
An example of (Secure) device control via a Browser interface. It includes the LED demonstration example code, SharkMQ, and SharkSSL SSL|TLS stack for authentication and encryption.
- Code Size: 21kB ROM | 4kB RAM.
- Requires: SharkSSL-Lite
Video Tutorials
How to setup your own secure SMQ IoT cloud server
Most IoT cloud server solutions, whether they provide ready-to-use hosted services or not, are based on a standard Virtual Private Server (VPS). Most developers probably think of Amazon or Microsoft Azure's services when considering the server side of their IoT solution. These high-end services are great if you need to scale up to millions of connected devices. However, for most small-scale operations and DIY projects, a low-cost VPS is more than adequate.
SMQ LED Demo
See Also
- SMQ Client-Example (NonSecure) SMQ Client LED Demonstration.
- SMQ LED Demonstration Tutorial
- SMQ Documentation
- Real Time Logic LLC public SMQ Broker access.
- How to set up your own low cost SMQ Broker cloud server solution Tutorial.
main.cpp@3:1bd18e82d943, 2016-04-08 (annotated)
- Committer:
- wini
- Date:
- Fri Apr 08 15:38:20 2016 +0000
- Revision:
- 3:1bd18e82d943
- Parent:
- 2:fd1c5fac2380
More code comments in main.cpp
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
wini | 0:10b4212318d4 | 1 | #include "mbed.h" |
wini | 0:10b4212318d4 | 2 | #include "ledctrl.h" |
wini | 0:10b4212318d4 | 3 | #include "EthernetInterface.h" |
wini | 0:10b4212318d4 | 4 | |
wini | 0:10b4212318d4 | 5 | DigitalOut led1(LED1); |
wini | 0:10b4212318d4 | 6 | DigitalOut led2(LED2); |
wini | 0:10b4212318d4 | 7 | DigitalOut led3(LED3); |
wini | 0:10b4212318d4 | 8 | DigitalOut led4(LED4); |
wini | 0:10b4212318d4 | 9 | |
wini | 0:10b4212318d4 | 10 | static const LedInfo ledInfo[] = { |
wini | 0:10b4212318d4 | 11 | { |
wini | 0:10b4212318d4 | 12 | "LED 1", |
wini | 0:10b4212318d4 | 13 | LedColor_yellow, |
wini | 0:10b4212318d4 | 14 | 1 |
wini | 0:10b4212318d4 | 15 | }, |
wini | 0:10b4212318d4 | 16 | { |
wini | 0:10b4212318d4 | 17 | "LED 2", |
wini | 0:10b4212318d4 | 18 | LedColor_red, |
wini | 0:10b4212318d4 | 19 | 2 |
wini | 0:10b4212318d4 | 20 | }, |
wini | 0:10b4212318d4 | 21 | { |
wini | 0:10b4212318d4 | 22 | "LED 3", |
wini | 0:10b4212318d4 | 23 | LedColor_blue, |
wini | 0:10b4212318d4 | 24 | 3 |
wini | 0:10b4212318d4 | 25 | }, |
wini | 0:10b4212318d4 | 26 | { |
wini | 0:10b4212318d4 | 27 | "LED 4", |
wini | 0:10b4212318d4 | 28 | LedColor_yellow, |
wini | 0:10b4212318d4 | 29 | 4 |
wini | 0:10b4212318d4 | 30 | } |
wini | 0:10b4212318d4 | 31 | }; |
wini | 0:10b4212318d4 | 32 | |
wini | 1:7099d4432b41 | 33 | #define LEDSLEN (sizeof(ledInfo) / sizeof(ledInfo[0])) |
wini | 1:7099d4432b41 | 34 | |
wini | 1:7099d4432b41 | 35 | static int leds[LEDSLEN]; |
wini | 0:10b4212318d4 | 36 | |
wini | 0:10b4212318d4 | 37 | /* Returns the LED on/off state for led with ID 'ledId'. |
wini | 0:10b4212318d4 | 38 | */ |
wini | 0:10b4212318d4 | 39 | int getLedState(int ledId) |
wini | 0:10b4212318d4 | 40 | { |
wini | 1:7099d4432b41 | 41 | if(ledId >= 1 && ledId <= LEDSLEN) |
wini | 1:7099d4432b41 | 42 | return leds[ledId-1]; |
wini | 1:7099d4432b41 | 43 | return 0; |
wini | 0:10b4212318d4 | 44 | } |
wini | 0:10b4212318d4 | 45 | |
wini | 0:10b4212318d4 | 46 | /* |
wini | 0:10b4212318d4 | 47 | Return an array of LedInfo (struct). Each element in the array |
wini | 0:10b4212318d4 | 48 | provides information for one LED. The 'len' argument must be set by |
wini | 0:10b4212318d4 | 49 | function getLedInfo. The out argument 'en' specifies the length of |
wini | 0:10b4212318d4 | 50 | the returned array, that is, number of LEDs in the device. Each LED |
wini | 0:10b4212318d4 | 51 | has a name, color, and ID. The ID, which provides information about |
wini | 0:10b4212318d4 | 52 | which LED to turn on/off, is used by control messages sent between |
wini | 0:10b4212318d4 | 53 | device code and UI clients. The IDs for a four LED device can for |
wini | 0:10b4212318d4 | 54 | example be 1,2,3,4. |
wini | 0:10b4212318d4 | 55 | */ |
wini | 0:10b4212318d4 | 56 | const LedInfo* getLedInfo(int* len) |
wini | 0:10b4212318d4 | 57 | { |
wini | 1:7099d4432b41 | 58 | *len = LEDSLEN; |
wini | 0:10b4212318d4 | 59 | return ledInfo; |
wini | 0:10b4212318d4 | 60 | } |
wini | 0:10b4212318d4 | 61 | |
wini | 0:10b4212318d4 | 62 | |
wini | 0:10b4212318d4 | 63 | /* Returns the name of this device. The name is presented by UI |
wini | 0:10b4212318d4 | 64 | clients such as browsers. |
wini | 0:10b4212318d4 | 65 | */ |
wini | 0:10b4212318d4 | 66 | extern "C" const char* getDevName(void) |
wini | 0:10b4212318d4 | 67 | { |
wini | 1:7099d4432b41 | 68 | return "mbed: Arch Pro : SharkSSL-Lite"; |
wini | 0:10b4212318d4 | 69 | } |
wini | 0:10b4212318d4 | 70 | |
wini | 3:1bd18e82d943 | 71 | /* Blink all LEDs |
wini | 3:1bd18e82d943 | 72 | */ |
wini | 0:10b4212318d4 | 73 | static void blinkAll(int fast) |
wini | 0:10b4212318d4 | 74 | { |
wini | 0:10b4212318d4 | 75 | int i; |
wini | 1:7099d4432b41 | 76 | for(i = 0 ; i < LEDSLEN ; i++) setLed(ledInfo[i].id, FALSE); |
wini | 1:7099d4432b41 | 77 | for(i = 0 ; i < LEDSLEN ; i++) |
wini | 0:10b4212318d4 | 78 | { |
wini | 1:7099d4432b41 | 79 | setLed(ledInfo[i].id, TRUE); |
wini | 0:10b4212318d4 | 80 | wait_ms(fast ? 120: 400); |
wini | 0:10b4212318d4 | 81 | } |
wini | 1:7099d4432b41 | 82 | for(i = 0 ; i < LEDSLEN ; i++) |
wini | 0:10b4212318d4 | 83 | { |
wini | 1:7099d4432b41 | 84 | setLed(ledInfo[i].id, FALSE); |
wini | 0:10b4212318d4 | 85 | wait_ms(fast ? 120: 400); |
wini | 0:10b4212318d4 | 86 | } |
wini | 0:10b4212318d4 | 87 | } |
wini | 0:10b4212318d4 | 88 | |
wini | 3:1bd18e82d943 | 89 | /* Blink LED with ID 'led' |
wini | 3:1bd18e82d943 | 90 | */ |
wini | 0:10b4212318d4 | 91 | static void blink(int led) |
wini | 0:10b4212318d4 | 92 | { |
wini | 0:10b4212318d4 | 93 | int i; |
wini | 0:10b4212318d4 | 94 | for(i = 0 ; i < 30; i++) |
wini | 0:10b4212318d4 | 95 | { |
wini | 0:10b4212318d4 | 96 | setLed(led, 1); |
wini | 0:10b4212318d4 | 97 | wait_ms(120); |
wini | 0:10b4212318d4 | 98 | setLed(led, 0); |
wini | 0:10b4212318d4 | 99 | wait_ms(120); |
wini | 0:10b4212318d4 | 100 | } |
wini | 0:10b4212318d4 | 101 | } |
wini | 0:10b4212318d4 | 102 | |
wini | 0:10b4212318d4 | 103 | /* Command sent by UI client to turn LED with ID on or off. This |
wini | 0:10b4212318d4 | 104 | function must set the LED to on if 'on' is TRUE and off if 'on' is FALSE. |
wini | 0:10b4212318d4 | 105 | */ |
wini | 0:10b4212318d4 | 106 | extern "C" int setLed(int ledId, int on) |
wini | 0:10b4212318d4 | 107 | { |
wini | 1:7099d4432b41 | 108 | if(ledId >= 1 && ledId <= LEDSLEN) |
wini | 0:10b4212318d4 | 109 | { |
wini | 1:7099d4432b41 | 110 | leds[ledId-1] = on; |
wini | 1:7099d4432b41 | 111 | on = on ? 0 : 1; /* Invert */ |
wini | 1:7099d4432b41 | 112 | switch(ledId) |
wini | 1:7099d4432b41 | 113 | { |
wini | 1:7099d4432b41 | 114 | case 1: led1 = on; break; |
wini | 1:7099d4432b41 | 115 | case 2: led2 = on; break; |
wini | 1:7099d4432b41 | 116 | case 3: led3 = on; break; |
wini | 1:7099d4432b41 | 117 | case 4: led4 = on; break; |
wini | 1:7099d4432b41 | 118 | } |
wini | 1:7099d4432b41 | 119 | return 0; |
wini | 0:10b4212318d4 | 120 | } |
wini | 1:7099d4432b41 | 121 | return -1; |
wini | 0:10b4212318d4 | 122 | } |
wini | 0:10b4212318d4 | 123 | |
wini | 0:10b4212318d4 | 124 | |
wini | 0:10b4212318d4 | 125 | /* |
wini | 0:10b4212318d4 | 126 | An optional function that enables LEDs to be set directly by the |
wini | 0:10b4212318d4 | 127 | device. This function is typically used by devices that include one |
wini | 0:10b4212318d4 | 128 | or more buttons. A button click may for example turn on a specific |
wini | 0:10b4212318d4 | 129 | LED. The function is called at intervals (polled) by the LED device |
wini | 0:10b4212318d4 | 130 | code. The function may for example detect a button click and return |
wini | 0:10b4212318d4 | 131 | the information to the caller. Arguments 'ledId' and 'on' are out |
wini | 0:10b4212318d4 | 132 | arguments, where 'ledId' is set to the LED ID and 'on' is set to |
wini | 0:10b4212318d4 | 133 | TRUE for on and FALSE for off. The function must return TRUE (a non |
wini | 0:10b4212318d4 | 134 | zero value) if the LED is to be set on/off and zero on no |
wini | 0:10b4212318d4 | 135 | change. Create an empty function returning zero if you do not plan |
wini | 0:10b4212318d4 | 136 | on implementing this feature. |
wini | 0:10b4212318d4 | 137 | */ |
wini | 0:10b4212318d4 | 138 | extern "C" int setLedFromDevice(int* ledId, int* on) |
wini | 0:10b4212318d4 | 139 | { |
wini | 0:10b4212318d4 | 140 | return FALSE; |
wini | 0:10b4212318d4 | 141 | } |
wini | 0:10b4212318d4 | 142 | |
wini | 0:10b4212318d4 | 143 | extern "C" void setProgramStatus(ProgramStatus s) |
wini | 0:10b4212318d4 | 144 | { |
wini | 1:7099d4432b41 | 145 | int i; |
wini | 1:7099d4432b41 | 146 | for(i = 0 ; i < LEDSLEN ; i++) setLed(ledInfo[i].id, FALSE); |
wini | 0:10b4212318d4 | 147 | switch(s) |
wini | 0:10b4212318d4 | 148 | { |
wini | 0:10b4212318d4 | 149 | case ProgramStatus_Restarting: |
wini | 0:10b4212318d4 | 150 | blinkAll(FALSE); |
wini | 0:10b4212318d4 | 151 | case ProgramStatus_Starting: |
wini | 0:10b4212318d4 | 152 | blinkAll(TRUE); |
wini | 0:10b4212318d4 | 153 | break; |
wini | 0:10b4212318d4 | 154 | |
wini | 0:10b4212318d4 | 155 | case ProgramStatus_Connecting: |
wini | 1:7099d4432b41 | 156 | setLed(ledInfo[1].id, TRUE); |
wini | 0:10b4212318d4 | 157 | break; |
wini | 0:10b4212318d4 | 158 | |
wini | 0:10b4212318d4 | 159 | case ProgramStatus_SslHandshake: |
wini | 1:7099d4432b41 | 160 | setLed(ledInfo[2].id, TRUE); |
wini | 0:10b4212318d4 | 161 | break; |
wini | 0:10b4212318d4 | 162 | |
wini | 0:10b4212318d4 | 163 | case ProgramStatus_DeviceReady: |
wini | 1:7099d4432b41 | 164 | for(i = 0 ; i < LEDSLEN ; i++) setLed(ledInfo[i].id, TRUE); |
wini | 0:10b4212318d4 | 165 | wait(1); |
wini | 1:7099d4432b41 | 166 | for(i = 0 ; i < LEDSLEN ; i++) setLed(ledInfo[i].id, FALSE); |
wini | 0:10b4212318d4 | 167 | break; |
wini | 0:10b4212318d4 | 168 | |
wini | 0:10b4212318d4 | 169 | case ProgramStatus_CloseCommandReceived: |
wini | 1:7099d4432b41 | 170 | blink(ledInfo[3].id); |
wini | 0:10b4212318d4 | 171 | break; |
wini | 0:10b4212318d4 | 172 | |
wini | 0:10b4212318d4 | 173 | default: |
wini | 0:10b4212318d4 | 174 | blinkAll(FALSE); |
wini | 0:10b4212318d4 | 175 | switch(s) |
wini | 0:10b4212318d4 | 176 | { |
wini | 0:10b4212318d4 | 177 | case ProgramStatus_SocketError: |
wini | 0:10b4212318d4 | 178 | case ProgramStatus_DnsError: |
wini | 0:10b4212318d4 | 179 | case ProgramStatus_WebServiceNotAvailError: |
wini | 0:10b4212318d4 | 180 | case ProgramStatus_InvalidCommandError: |
wini | 0:10b4212318d4 | 181 | case ProgramStatus_PongResponseError: |
wini | 1:7099d4432b41 | 182 | blink(ledInfo[1].id); |
wini | 0:10b4212318d4 | 183 | break; |
wini | 0:10b4212318d4 | 184 | |
wini | 0:10b4212318d4 | 185 | case ProgramStatus_ConnectionError: |
wini | 1:7099d4432b41 | 186 | blink(ledInfo[2].id); |
wini | 0:10b4212318d4 | 187 | break; |
wini | 0:10b4212318d4 | 188 | |
wini | 0:10b4212318d4 | 189 | case ProgramStatus_CertificateNotTrustedError: |
wini | 0:10b4212318d4 | 190 | case ProgramStatus_SslHandshakeError: |
wini | 1:7099d4432b41 | 191 | blink(ledInfo[3].id); |
wini | 0:10b4212318d4 | 192 | break; |
wini | 0:10b4212318d4 | 193 | |
wini | 0:10b4212318d4 | 194 | case ProgramStatus_MemoryError: |
wini | 1:7099d4432b41 | 195 | for(i = 0 ; i < LEDSLEN ; i++) blink(ledInfo[i].id); |
wini | 0:10b4212318d4 | 196 | break; |
wini | 0:10b4212318d4 | 197 | } |
wini | 0:10b4212318d4 | 198 | } |
wini | 0:10b4212318d4 | 199 | } |
wini | 0:10b4212318d4 | 200 | |
wini | 0:10b4212318d4 | 201 | |
wini | 0:10b4212318d4 | 202 | static EthernetInterface eth; |
wini | 0:10b4212318d4 | 203 | |
wini | 0:10b4212318d4 | 204 | |
wini | 0:10b4212318d4 | 205 | /* Required by SMQ examples. |
wini | 0:10b4212318d4 | 206 | The unique ID is used when calling the SMQ constructor. The |
wini | 0:10b4212318d4 | 207 | unique ID is typically set to the MAC address. See the SMQ |
wini | 0:10b4212318d4 | 208 | documentation for details: |
wini | 0:10b4212318d4 | 209 | https://realtimelogic.com/ba/doc/en/C/shark/structSharkMQ.html |
wini | 0:10b4212318d4 | 210 | */ |
wini | 0:10b4212318d4 | 211 | int getUniqueId(const char** id) |
wini | 0:10b4212318d4 | 212 | { |
wini | 0:10b4212318d4 | 213 | *id=eth.getMACAddress(); |
wini | 0:10b4212318d4 | 214 | return strlen(*id); |
wini | 0:10b4212318d4 | 215 | } |
wini | 0:10b4212318d4 | 216 | |
wini | 0:10b4212318d4 | 217 | int main() |
wini | 0:10b4212318d4 | 218 | { |
wini | 0:10b4212318d4 | 219 | xprintf(("\n\n\nIn main\n")); |
wini | 0:10b4212318d4 | 220 | eth.init(); //Use DHCP |
wini | 0:10b4212318d4 | 221 | xprintf(("EthernetInterface connect\n")); |
wini | 0:10b4212318d4 | 222 | blinkAll(FALSE); |
wini | 0:10b4212318d4 | 223 | eth.connect(); |
wini | 0:10b4212318d4 | 224 | xprintf(("IP Address is %s\n", eth.getIPAddress())); |
wini | 0:10b4212318d4 | 225 | mainTask(0); |
wini | 0:10b4212318d4 | 226 | error("mainTask returned"); |
wini | 0:10b4212318d4 | 227 | } |