SMQ is an easy to use machine-to-machine (M2M)/"Internet of Things" connectivity protocol that follows the publish subscribe design pattern.

Dependencies:   EthernetInterface 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
  • SMQjs (Javascript)
  • SMQ JAVA
  • SMQ Broker

/media/uploads/wini/smq_architecture.png

SMQ Client-example

A (non-secure) C Client implementation of the SMQ protocol demonstrating device control over the on board LEDs via any modern (WebSocket enabled) Browser interface.

  • Code Size: 3kB

See Also

How to setup your own 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.

Committer:
wini
Date:
Fri Mar 25 23:07:22 2016 +0000
Revision:
2:bac2873dbd15
Parent:
1:734fa1459f69
Updated to latest SMQ source base

Who changed what in which revision?

UserRevisionLine numberNew contents of line
wini 0:bd3aeb15634e 1
wini 0:bd3aeb15634e 2 #include "mbed.h"
wini 0:bd3aeb15634e 3 #include "ledctrl.h"
wini 0:bd3aeb15634e 4 #include "EthernetInterface.h"
wini 0:bd3aeb15634e 5
wini 0:bd3aeb15634e 6 DigitalOut led1(LED1);
wini 1:734fa1459f69 7 DigitalOut led2(LED2);
wini 1:734fa1459f69 8 DigitalOut led3(LED3);
wini 1:734fa1459f69 9 DigitalOut led4(LED4);
wini 0:bd3aeb15634e 10
wini 0:bd3aeb15634e 11 static const LedInfo ledInfo[] = {
wini 0:bd3aeb15634e 12 {
wini 0:bd3aeb15634e 13 "LED 1",
wini 1:734fa1459f69 14 LedColor_yellow,
wini 0:bd3aeb15634e 15 1
wini 1:734fa1459f69 16 },
wini 1:734fa1459f69 17 {
wini 1:734fa1459f69 18 "LED 2",
wini 1:734fa1459f69 19 LedColor_red,
wini 1:734fa1459f69 20 2
wini 1:734fa1459f69 21 },
wini 1:734fa1459f69 22 {
wini 1:734fa1459f69 23 "LED 3",
wini 1:734fa1459f69 24 LedColor_blue,
wini 1:734fa1459f69 25 3
wini 1:734fa1459f69 26 },
wini 1:734fa1459f69 27 {
wini 1:734fa1459f69 28 "LED 4",
wini 1:734fa1459f69 29 LedColor_yellow,
wini 1:734fa1459f69 30 4
wini 0:bd3aeb15634e 31 }
wini 0:bd3aeb15634e 32 };
wini 0:bd3aeb15634e 33
wini 2:bac2873dbd15 34 static int leds[sizeof(ledInfo)/sizeof(ledInfo[1])];
wini 0:bd3aeb15634e 35
wini 2:bac2873dbd15 36 /* Returns the LED on/off state for led with ID 'ledId'.
wini 2:bac2873dbd15 37 */
wini 2:bac2873dbd15 38 int getLedState(int ledId)
wini 0:bd3aeb15634e 39 {
wini 0:bd3aeb15634e 40 baAssert(ledId >= 1 && ledId <= sizeof(ledInfo)/sizeof(ledInfo[1]));
wini 0:bd3aeb15634e 41 return leds[ledId-1];
wini 0:bd3aeb15634e 42 }
wini 0:bd3aeb15634e 43
wini 0:bd3aeb15634e 44
wini 2:bac2873dbd15 45 /*
wini 2:bac2873dbd15 46 Return an array of LedInfo (struct). Each element in the array
wini 2:bac2873dbd15 47 provides information for one LED. The 'len' argument must be set by
wini 2:bac2873dbd15 48 function getLedInfo. The out argument 'en' specifies the length of
wini 2:bac2873dbd15 49 the returned array, that is, number of LEDs in the device. Each LED
wini 2:bac2873dbd15 50 has a name, color, and ID. The ID, which provides information about
wini 2:bac2873dbd15 51 which LED to turn on/off, is used by control messages sent between
wini 2:bac2873dbd15 52 device code and UI clients. The IDs for a four LED device can for
wini 2:bac2873dbd15 53 example be 1,2,3,4.
wini 2:bac2873dbd15 54 */
wini 0:bd3aeb15634e 55 const LedInfo* getLedInfo(int* len)
wini 0:bd3aeb15634e 56 {
wini 0:bd3aeb15634e 57 *len = sizeof(ledInfo) / sizeof(ledInfo[0]);
wini 0:bd3aeb15634e 58 return ledInfo;
wini 0:bd3aeb15634e 59 }
wini 0:bd3aeb15634e 60
wini 2:bac2873dbd15 61
wini 2:bac2873dbd15 62 /* Returns the name of this device. The name is presented by UI
wini 2:bac2873dbd15 63 clients such as browsers.
wini 2:bac2873dbd15 64 */
wini 0:bd3aeb15634e 65 extern "C" const char* getDevName(void)
wini 0:bd3aeb15634e 66 {
wini 0:bd3aeb15634e 67 return "mbed: Arch Pro";
wini 0:bd3aeb15634e 68 }
wini 0:bd3aeb15634e 69
wini 1:734fa1459f69 70 static void blinkAll(int fast)
wini 1:734fa1459f69 71 {
wini 1:734fa1459f69 72 int i;
wini 1:734fa1459f69 73 for(i = 1 ; i <= 4 ; i++) setLed(i, FALSE);
wini 1:734fa1459f69 74 for(i = 1 ; i <= 4 ; i++)
wini 1:734fa1459f69 75 {
wini 1:734fa1459f69 76 setLed(i, TRUE);
wini 1:734fa1459f69 77 wait_ms(fast ? 120: 400);
wini 1:734fa1459f69 78 }
wini 1:734fa1459f69 79 for(i = 1 ; i <= 4 ; i++)
wini 1:734fa1459f69 80 {
wini 1:734fa1459f69 81 setLed(i, FALSE);
wini 1:734fa1459f69 82 wait_ms(fast ? 120: 400);
wini 1:734fa1459f69 83 }
wini 1:734fa1459f69 84 }
wini 1:734fa1459f69 85
wini 1:734fa1459f69 86
wini 1:734fa1459f69 87 static void blink(int led)
wini 1:734fa1459f69 88 {
wini 1:734fa1459f69 89 int i;
wini 1:734fa1459f69 90 for(i = 0 ; i < 30; i++)
wini 1:734fa1459f69 91 {
wini 1:734fa1459f69 92 setLed(led, 1);
wini 1:734fa1459f69 93 wait_ms(120);
wini 1:734fa1459f69 94 setLed(led, 0);
wini 1:734fa1459f69 95 wait_ms(120);
wini 1:734fa1459f69 96 }
wini 1:734fa1459f69 97 }
wini 1:734fa1459f69 98
wini 2:bac2873dbd15 99 /* Command sent by UI client to turn LED with ID on or off. This
wini 2:bac2873dbd15 100 function must set the LED to on if 'on' is TRUE and off if 'on' is FALSE.
wini 2:bac2873dbd15 101 */
wini 0:bd3aeb15634e 102 extern "C" int setLed(int ledId, int on)
wini 0:bd3aeb15634e 103 {
wini 2:bac2873dbd15 104 baAssert(ledId >= 1 && ledId <= sizeof(ledInfo)/sizeof(ledInfo[1]));
wini 2:bac2873dbd15 105 leds[ledId-1] = on;
wini 2:bac2873dbd15 106 on = on ? 0 : 1; /* Invert */
wini 1:734fa1459f69 107 switch(ledId)
wini 1:734fa1459f69 108 {
wini 1:734fa1459f69 109 case 1: led1 = on; break;
wini 1:734fa1459f69 110 case 2: led2 = on; break;
wini 1:734fa1459f69 111 case 3: led3 = on; break;
wini 1:734fa1459f69 112 case 4: led4 = on; break;
wini 1:734fa1459f69 113 }
wini 0:bd3aeb15634e 114 return 0;
wini 0:bd3aeb15634e 115 }
wini 0:bd3aeb15634e 116
wini 0:bd3aeb15634e 117
wini 2:bac2873dbd15 118 /*
wini 2:bac2873dbd15 119 An optional function that enables LEDs to be set directly by the
wini 2:bac2873dbd15 120 device. This function is typically used by devices that include one
wini 2:bac2873dbd15 121 or more buttons. A button click may for example turn on a specific
wini 2:bac2873dbd15 122 LED. The function is called at intervals (polled) by the LED device
wini 2:bac2873dbd15 123 code. The function may for example detect a button click and return
wini 2:bac2873dbd15 124 the information to the caller. Arguments 'ledId' and 'on' are out
wini 2:bac2873dbd15 125 arguments, where 'ledId' is set to the LED ID and 'on' is set to
wini 2:bac2873dbd15 126 TRUE for on and FALSE for off. The function must return TRUE (a non
wini 2:bac2873dbd15 127 zero value) if the LED is to be set on/off and zero on no
wini 2:bac2873dbd15 128 change. Create an empty function returning zero if you do not plan
wini 2:bac2873dbd15 129 on implementing this feature.
wini 2:bac2873dbd15 130 */
wini 0:bd3aeb15634e 131 extern "C" int setLedFromDevice(int* ledId, int* on)
wini 0:bd3aeb15634e 132 {
wini 0:bd3aeb15634e 133 return FALSE;
wini 0:bd3aeb15634e 134 }
wini 0:bd3aeb15634e 135
wini 0:bd3aeb15634e 136 extern "C" void setProgramStatus(ProgramStatus s)
wini 0:bd3aeb15634e 137 {
wini 1:734fa1459f69 138 int i;
wini 1:734fa1459f69 139 for(i = 1 ; i <= 4 ; i++) setLed(i, FALSE);
wini 1:734fa1459f69 140 switch(s)
wini 1:734fa1459f69 141 {
wini 1:734fa1459f69 142 case ProgramStatus_Restarting:
wini 1:734fa1459f69 143 blinkAll(FALSE);
wini 1:734fa1459f69 144 case ProgramStatus_Starting:
wini 1:734fa1459f69 145 blinkAll(TRUE);
wini 1:734fa1459f69 146 break;
wini 1:734fa1459f69 147
wini 1:734fa1459f69 148 case ProgramStatus_Connecting:
wini 1:734fa1459f69 149 setLed(1, TRUE);
wini 1:734fa1459f69 150 break;
wini 1:734fa1459f69 151
wini 1:734fa1459f69 152 case ProgramStatus_SslHandshake:
wini 1:734fa1459f69 153 setLed(2, TRUE);
wini 1:734fa1459f69 154 break;
wini 1:734fa1459f69 155
wini 1:734fa1459f69 156 case ProgramStatus_DeviceReady:
wini 1:734fa1459f69 157 for(i = 1 ; i <= 4 ; i++) setLed(i, TRUE);
wini 1:734fa1459f69 158 wait(1);
wini 1:734fa1459f69 159 for(i = 1 ; i <= 4 ; i++) setLed(i, FALSE);
wini 1:734fa1459f69 160 break;
wini 1:734fa1459f69 161
wini 1:734fa1459f69 162 case ProgramStatus_CloseCommandReceived:
wini 1:734fa1459f69 163 blink(3);
wini 1:734fa1459f69 164 break;
wini 1:734fa1459f69 165
wini 1:734fa1459f69 166 default:
wini 1:734fa1459f69 167 blinkAll(FALSE);
wini 1:734fa1459f69 168 switch(s)
wini 1:734fa1459f69 169 {
wini 1:734fa1459f69 170 case ProgramStatus_SocketError:
wini 1:734fa1459f69 171 case ProgramStatus_DnsError:
wini 1:734fa1459f69 172 case ProgramStatus_WebServiceNotAvailError:
wini 1:734fa1459f69 173 case ProgramStatus_InvalidCommandError:
wini 1:734fa1459f69 174 case ProgramStatus_PongResponseError:
wini 1:734fa1459f69 175 blink(1);
wini 1:734fa1459f69 176 break;
wini 1:734fa1459f69 177
wini 1:734fa1459f69 178 case ProgramStatus_ConnectionError:
wini 1:734fa1459f69 179 blink(2);
wini 1:734fa1459f69 180 break;
wini 1:734fa1459f69 181
wini 1:734fa1459f69 182 case ProgramStatus_CertificateNotTrustedError:
wini 1:734fa1459f69 183 case ProgramStatus_SslHandshakeError:
wini 1:734fa1459f69 184 blink(3);
wini 1:734fa1459f69 185 break;
wini 1:734fa1459f69 186
wini 1:734fa1459f69 187 case ProgramStatus_MemoryError:
wini 1:734fa1459f69 188 for(i = 1 ; i <= 4 ; i++) blink(i);
wini 1:734fa1459f69 189 break;
wini 1:734fa1459f69 190 }
wini 1:734fa1459f69 191 }
wini 0:bd3aeb15634e 192 }
wini 0:bd3aeb15634e 193
wini 2:bac2873dbd15 194
wini 2:bac2873dbd15 195 static EthernetInterface eth;
wini 2:bac2873dbd15 196
wini 2:bac2873dbd15 197
wini 2:bac2873dbd15 198 /* Required by SMQ examples.
wini 2:bac2873dbd15 199 The unique ID is used when calling the SMQ constructor. The
wini 2:bac2873dbd15 200 unique ID is typically set to the MAC address. See the SMQ
wini 2:bac2873dbd15 201 documentation for details:
wini 2:bac2873dbd15 202 https://realtimelogic.com/ba/doc/en/C/shark/structSharkMQ.html
wini 2:bac2873dbd15 203 */
wini 2:bac2873dbd15 204 int getUniqueId(const char** id)
wini 2:bac2873dbd15 205 {
wini 2:bac2873dbd15 206 *id=eth.getMACAddress();
wini 2:bac2873dbd15 207 return strlen(*id);
wini 1:734fa1459f69 208 }
wini 0:bd3aeb15634e 209
wini 0:bd3aeb15634e 210 int main()
wini 0:bd3aeb15634e 211 {
wini 1:734fa1459f69 212 xprintf(("\n\n\nIn main\n"));
wini 1:734fa1459f69 213 eth.init(); //Use DHCP
wini 1:734fa1459f69 214 xprintf(("EthernetInterface connect\n"));
wini 1:734fa1459f69 215 blinkAll(FALSE);
wini 1:734fa1459f69 216 eth.connect();
wini 1:734fa1459f69 217 xprintf(("IP Address is %s\n", eth.getIPAddress()));
wini 1:734fa1459f69 218 mainTask(0);
wini 0:bd3aeb15634e 219 error("mainTask returned");
wini 0:bd3aeb15634e 220 }