Official reference client implementation for Cumulocity SmartREST on u-blox C027.

Dependencies:   C027_Support C12832 LM75B MMA7660 MbedSmartRest mbed-rtos mbed

Fork of MbedSmartRestMain by Vincent Wochnik

Committer:
vwochnik
Date:
Tue Feb 10 20:52:13 2015 +0000
Revision:
70:f489ca11f254
Parent:
68:0dc778a16d0d
Child:
77:f6717e4eccc4
realtime running and functional test

Who changed what in which revision?

UserRevisionLine numberNew contents of line
vwochnik 57:4af5f1bec3a6 1 #include "OperationSupport.h"
vwochnik 59:f96be79feccd 2 #include <string.h>
vwochnik 63:010bbbb4732a 3 #include "Aggregator.h"
vwochnik 57:4af5f1bec3a6 4 #include "ComposedRecord.h"
vwochnik 57:4af5f1bec3a6 5 #include "CharValue.h"
vwochnik 57:4af5f1bec3a6 6 #include "IntegerValue.h"
vwochnik 57:4af5f1bec3a6 7
vwochnik 59:f96be79feccd 8 CharValue aOperationStatePending("PENDING");
vwochnik 59:f96be79feccd 9 CharValue aOperationStateExecuting("EXECUTING");
vwochnik 59:f96be79feccd 10 CharValue aOperationStateSuccessful("SUCCESSFUL");
vwochnik 59:f96be79feccd 11 CharValue aOperationStateFailed("FAILED");
vwochnik 59:f96be79feccd 12
vwochnik 68:0dc778a16d0d 13 OperationSupport::OperationSupport(AbstractSmartRest& client, SmartRestTemplate& tpl, long& deviceId, ConfigurationSynchronization& configurationSynchronization, DeviceIO& io) :
vwochnik 57:4af5f1bec3a6 14 _client(client),
vwochnik 57:4af5f1bec3a6 15 _tpl(tpl),
vwochnik 60:3c822f97fc73 16 _deviceId(deviceId),
vwochnik 68:0dc778a16d0d 17 _executor(client, tpl, deviceId, configurationSynchronization, io),
vwochnik 63:010bbbb4732a 18 _thread1(OperationSupport::thread1_func, this),
vwochnik 67:c360a2b2c948 19 _thread2(OperationSupport::thread2_func, this),
vwochnik 67:c360a2b2c948 20 _thread3(OperationSupport::thread3_func, this)
vwochnik 57:4af5f1bec3a6 21 {
vwochnik 57:4af5f1bec3a6 22 _init = false;
vwochnik 67:c360a2b2c948 23 _firstRun = true;
vwochnik 57:4af5f1bec3a6 24 }
vwochnik 57:4af5f1bec3a6 25
vwochnik 57:4af5f1bec3a6 26 bool OperationSupport::init()
vwochnik 57:4af5f1bec3a6 27 {
vwochnik 57:4af5f1bec3a6 28 if (_init)
vwochnik 57:4af5f1bec3a6 29 return false;
vwochnik 57:4af5f1bec3a6 30
vwochnik 57:4af5f1bec3a6 31 // Get pending operations
vwochnik 57:4af5f1bec3a6 32 // USAGE: 110,<DEVICE/ID>
vwochnik 57:4af5f1bec3a6 33 if (!_tpl.add("10,110,GET,/devicecontrol/operations?status=PENDING&deviceId=%%&pageSize=100,,application/vnd.com.nsn.cumulocity.operationCollection+json,%%,UNSIGNED,\r\n"))
vwochnik 57:4af5f1bec3a6 34 return false;
vwochnik 57:4af5f1bec3a6 35
vwochnik 57:4af5f1bec3a6 36 // Set operation state
vwochnik 57:4af5f1bec3a6 37 // USAGE: 110,<OPERATION/ID>,<STATE>
vwochnik 58:4cc0ae5a7058 38 if (!_tpl.add("10,111,PUT,/devicecontrol/operations/%%,application/vnd.com.nsn.cumulocity.operation+json,application/vnd.com.nsn.cumulocity.operation+json,%%,UNSIGNED STRING,\"{\"\"status\"\":\"\"%%\"\"}\"\r\n"))
vwochnik 57:4af5f1bec3a6 39 return false;
vwochnik 57:4af5f1bec3a6 40
vwochnik 57:4af5f1bec3a6 41 // Get operations
vwochnik 57:4af5f1bec3a6 42 // Response: 210,<OPERATION/ID>,<STATUS>
vwochnik 57:4af5f1bec3a6 43 if (!_tpl.add("11,210,\"$.operations\",,\"$.id\",\"$.status\"\r\n"))
vwochnik 57:4af5f1bec3a6 44 return false;
vwochnik 57:4af5f1bec3a6 45
vwochnik 57:4af5f1bec3a6 46 // Get operation
vwochnik 57:4af5f1bec3a6 47 // Response: 211,<OPERATION/ID>,<STATUS>
vwochnik 57:4af5f1bec3a6 48 if (!_tpl.add("11,211,,\"$.deviceId\",\"$.id\",\"$.status\"\r\n"))
vwochnik 57:4af5f1bec3a6 49 return false;
vwochnik 63:010bbbb4732a 50
vwochnik 63:010bbbb4732a 51 if (!_executor.init())
vwochnik 63:010bbbb4732a 52 return false;
vwochnik 57:4af5f1bec3a6 53
vwochnik 57:4af5f1bec3a6 54 _init = true;
vwochnik 57:4af5f1bec3a6 55 return true;
vwochnik 57:4af5f1bec3a6 56 }
vwochnik 57:4af5f1bec3a6 57
vwochnik 57:4af5f1bec3a6 58 bool OperationSupport::run()
vwochnik 57:4af5f1bec3a6 59 {
vwochnik 67:c360a2b2c948 60 if (_firstRun) {
vwochnik 67:c360a2b2c948 61 _firstRun = false;
vwochnik 70:f489ca11f254 62 if (!requestPendingOperations())
vwochnik 70:f489ca11f254 63 return false;
vwochnik 63:010bbbb4732a 64 }
vwochnik 63:010bbbb4732a 65
vwochnik 63:010bbbb4732a 66 return true;
vwochnik 63:010bbbb4732a 67 }
vwochnik 63:010bbbb4732a 68
vwochnik 63:010bbbb4732a 69 bool OperationSupport::requestPendingOperations()
vwochnik 63:010bbbb4732a 70 {
vwochnik 60:3c822f97fc73 71 uint8_t ret;
vwochnik 63:010bbbb4732a 72 OperationStore::Operation op;
vwochnik 60:3c822f97fc73 73
vwochnik 59:f96be79feccd 74 ComposedRecord record;
vwochnik 59:f96be79feccd 75 ParsedRecord received;
vwochnik 59:f96be79feccd 76
vwochnik 59:f96be79feccd 77 IntegerValue msgId(110);
vwochnik 59:f96be79feccd 78 IntegerValue deviceId(_deviceId);
vwochnik 59:f96be79feccd 79 if ((!record.add(msgId)) || (!record.add(deviceId)))
vwochnik 59:f96be79feccd 80 return false;
vwochnik 60:3c822f97fc73 81
vwochnik 59:f96be79feccd 82 if (_client.send(record) != SMARTREST_SUCCESS) {
vwochnik 59:f96be79feccd 83 _client.stop();
vwochnik 59:f96be79feccd 84 return false;
vwochnik 59:f96be79feccd 85 }
vwochnik 60:3c822f97fc73 86
vwochnik 60:3c822f97fc73 87 while ((ret = _client.receive(received)) == SMARTREST_SUCCESS) {
vwochnik 65:a62dbef2f924 88 if (!operationFromRecord(received, op))
vwochnik 63:010bbbb4732a 89 continue;
vwochnik 70:f489ca11f254 90 _store.enqueue(op);
vwochnik 60:3c822f97fc73 91 }
vwochnik 59:f96be79feccd 92 _client.stop();
vwochnik 60:3c822f97fc73 93
vwochnik 60:3c822f97fc73 94 if ((ret != SMARTREST_END_OF_RESPONSE) &&
vwochnik 60:3c822f97fc73 95 (ret != SMARTREST_CONNECTION_CLOSED)) {
vwochnik 60:3c822f97fc73 96 return false;
vwochnik 60:3c822f97fc73 97 }
vwochnik 59:f96be79feccd 98
vwochnik 60:3c822f97fc73 99 return true;
vwochnik 57:4af5f1bec3a6 100 }
vwochnik 59:f96be79feccd 101
vwochnik 60:3c822f97fc73 102 bool OperationSupport::operationFromRecord(ParsedRecord& received, OperationStore::Operation& op)
vwochnik 59:f96be79feccd 103 {
vwochnik 59:f96be79feccd 104 const char *tmp;
vwochnik 59:f96be79feccd 105
vwochnik 59:f96be79feccd 106 if ((received.values() < 4) ||
vwochnik 59:f96be79feccd 107 (received.value(0).valueType() != VALUE_INTEGER) ||
vwochnik 70:f489ca11f254 108 //TODO: error here since streaming op does not have 210 msg id
vwochnik 70:f489ca11f254 109 // (received.value(0).integerValue() != 210) ||
vwochnik 59:f96be79feccd 110 (received.value(2).valueType() != VALUE_INTEGER) ||
vwochnik 59:f96be79feccd 111 (received.value(3).valueType() != VALUE_CHARACTER))
vwochnik 59:f96be79feccd 112 return false;
vwochnik 59:f96be79feccd 113
vwochnik 60:3c822f97fc73 114 op.identifier = received.value(2).integerValue();
vwochnik 59:f96be79feccd 115 tmp = received.value(3).characterValue();
vwochnik 59:f96be79feccd 116 if (strcmp(tmp, "EXECUTING") == 0)
vwochnik 62:86a04c5bda18 117 op.state = OPERATION_EXECUTING;
vwochnik 59:f96be79feccd 118 else if (strcmp(tmp, "SUCCESSFUL") == 0)
vwochnik 62:86a04c5bda18 119 op.state = OPERATION_SUCCESSFUL;
vwochnik 59:f96be79feccd 120 else if (strcmp(tmp, "FAILED") == 0)
vwochnik 62:86a04c5bda18 121 op.state = OPERATION_FAILED;
vwochnik 70:f489ca11f254 122 else if (strcmp(tmp, "PENDING") == 0)
vwochnik 70:f489ca11f254 123 op.state = OPERATION_PENDING;
vwochnik 59:f96be79feccd 124 else
vwochnik 70:f489ca11f254 125 return false;
vwochnik 59:f96be79feccd 126
vwochnik 59:f96be79feccd 127 return true;
vwochnik 59:f96be79feccd 128 }
vwochnik 59:f96be79feccd 129
vwochnik 59:f96be79feccd 130 bool OperationSupport::updateOperation(OperationStore::Operation& op)
vwochnik 59:f96be79feccd 131 {
vwochnik 61:15719dbe8820 132 uint8_t ret; bool found;
vwochnik 59:f96be79feccd 133 ComposedRecord record;
vwochnik 59:f96be79feccd 134 ParsedRecord received;
vwochnik 59:f96be79feccd 135
vwochnik 59:f96be79feccd 136 IntegerValue msgId(111);
vwochnik 59:f96be79feccd 137 IntegerValue operationId(op.identifier);
vwochnik 59:f96be79feccd 138 if ((!record.add(msgId)) || (!record.add(operationId)) ||
vwochnik 59:f96be79feccd 139 (!record.add(operationStateValue(op))))
vwochnik 59:f96be79feccd 140 return false;
vwochnik 59:f96be79feccd 141
vwochnik 59:f96be79feccd 142 if (_client.send(record) != SMARTREST_SUCCESS) {
vwochnik 59:f96be79feccd 143 _client.stop();
vwochnik 59:f96be79feccd 144 return false;
vwochnik 59:f96be79feccd 145 }
vwochnik 59:f96be79feccd 146
vwochnik 61:15719dbe8820 147 found = false;
vwochnik 61:15719dbe8820 148 while ((ret = _client.receive(received)) == SMARTREST_SUCCESS) {
vwochnik 61:15719dbe8820 149 if ((received.values() == 4) &&
vwochnik 61:15719dbe8820 150 (received.value(0).valueType() == VALUE_INTEGER) &&
vwochnik 61:15719dbe8820 151 (received.value(0).integerValue() == 211) &&
vwochnik 61:15719dbe8820 152 (received.value(2).valueType() == VALUE_INTEGER) &&
vwochnik 61:15719dbe8820 153 (received.value(2).integerValue() == op.identifier)) {
vwochnik 61:15719dbe8820 154 found = true;
vwochnik 61:15719dbe8820 155 break;
vwochnik 61:15719dbe8820 156 }
vwochnik 59:f96be79feccd 157 }
vwochnik 59:f96be79feccd 158 _client.stop();
vwochnik 61:15719dbe8820 159
vwochnik 61:15719dbe8820 160 return found;
vwochnik 59:f96be79feccd 161 }
vwochnik 59:f96be79feccd 162
vwochnik 59:f96be79feccd 163 CharValue& OperationSupport::operationStateValue(OperationStore::Operation& op)
vwochnik 59:f96be79feccd 164 {
vwochnik 59:f96be79feccd 165 switch (op.state) {
vwochnik 62:86a04c5bda18 166 case OPERATION_EXECUTING:
vwochnik 59:f96be79feccd 167 return aOperationStateExecuting;
vwochnik 62:86a04c5bda18 168 case OPERATION_SUCCESSFUL:
vwochnik 59:f96be79feccd 169 return aOperationStateSuccessful;
vwochnik 62:86a04c5bda18 170 case OPERATION_FAILED:
vwochnik 59:f96be79feccd 171 return aOperationStateFailed;
vwochnik 59:f96be79feccd 172 default:
vwochnik 59:f96be79feccd 173 return aOperationStatePending;
vwochnik 59:f96be79feccd 174 }
vwochnik 59:f96be79feccd 175 }
vwochnik 60:3c822f97fc73 176
vwochnik 63:010bbbb4732a 177 void OperationSupport::thread1()
vwochnik 60:3c822f97fc73 178 {
vwochnik 63:010bbbb4732a 179 OperationStore::Operation op;
vwochnik 63:010bbbb4732a 180 bool ret;
vwochnik 63:010bbbb4732a 181
vwochnik 63:010bbbb4732a 182 while (!_init)
vwochnik 63:010bbbb4732a 183 Thread::yield();
vwochnik 63:010bbbb4732a 184
vwochnik 63:010bbbb4732a 185 while (true) {
vwochnik 63:010bbbb4732a 186 if (!_store.takePending(op)) {
vwochnik 63:010bbbb4732a 187 Thread::yield();
vwochnik 63:010bbbb4732a 188 continue;
vwochnik 63:010bbbb4732a 189 }
vwochnik 63:010bbbb4732a 190
vwochnik 63:010bbbb4732a 191 updateOperation(op);
vwochnik 63:010bbbb4732a 192 ret = _executor.executeOperation(op);
vwochnik 63:010bbbb4732a 193 _store.markAsDone(op, ret);
vwochnik 63:010bbbb4732a 194 }
vwochnik 63:010bbbb4732a 195 }
vwochnik 63:010bbbb4732a 196
vwochnik 63:010bbbb4732a 197 void OperationSupport::thread2()
vwochnik 63:010bbbb4732a 198 {
vwochnik 63:010bbbb4732a 199 OperationStore::Operation op;
vwochnik 63:010bbbb4732a 200 Aggregator aggr(true);
vwochnik 63:010bbbb4732a 201
vwochnik 60:3c822f97fc73 202 while (!_init)
vwochnik 60:3c822f97fc73 203 Thread::yield();
vwochnik 60:3c822f97fc73 204
vwochnik 63:010bbbb4732a 205 while (true) {
vwochnik 63:010bbbb4732a 206 while ((!aggr.full()) && (_store.takeDone(op))) {
vwochnik 63:010bbbb4732a 207 ComposedRecord record;
vwochnik 60:3c822f97fc73 208
vwochnik 63:010bbbb4732a 209 IntegerValue msgId(111);
vwochnik 63:010bbbb4732a 210 IntegerValue operationId(op.identifier);
vwochnik 63:010bbbb4732a 211 if ((!record.add(msgId)) || (!record.add(operationId)) ||
vwochnik 63:010bbbb4732a 212 (!record.add(operationStateValue(op))))
vwochnik 63:010bbbb4732a 213 break;
vwochnik 63:010bbbb4732a 214
vwochnik 63:010bbbb4732a 215 if (!aggr.add(record))
vwochnik 63:010bbbb4732a 216 break;
vwochnik 63:010bbbb4732a 217 }
vwochnik 63:010bbbb4732a 218
vwochnik 63:010bbbb4732a 219 if (aggr.length() == 0) {
vwochnik 63:010bbbb4732a 220 Thread::yield();
vwochnik 63:010bbbb4732a 221 continue;
vwochnik 63:010bbbb4732a 222 }
vwochnik 63:010bbbb4732a 223
vwochnik 65:a62dbef2f924 224 if (_client.send(aggr) != SMARTREST_SUCCESS) { }
vwochnik 63:010bbbb4732a 225 _client.stop();
vwochnik 63:010bbbb4732a 226 aggr.clear();
vwochnik 63:010bbbb4732a 227 }
vwochnik 60:3c822f97fc73 228 }
vwochnik 60:3c822f97fc73 229
vwochnik 67:c360a2b2c948 230 void OperationSupport::thread3()
vwochnik 67:c360a2b2c948 231 {
vwochnik 70:f489ca11f254 232 char bayeuxId[33];
vwochnik 67:c360a2b2c948 233
vwochnik 67:c360a2b2c948 234 ComposedRecord record;
vwochnik 67:c360a2b2c948 235 ParsedRecord received;
vwochnik 70:f489ca11f254 236 OperationStore::Operation op;
vwochnik 67:c360a2b2c948 237
vwochnik 67:c360a2b2c948 238 while ((!_init) || (_firstRun))
vwochnik 67:c360a2b2c948 239 Thread::yield();
vwochnik 67:c360a2b2c948 240
vwochnik 67:c360a2b2c948 241 // request Bayeux ID
vwochnik 67:c360a2b2c948 242 {
vwochnik 70:f489ca11f254 243 const char *str;
vwochnik 70:f489ca11f254 244
vwochnik 67:c360a2b2c948 245 IntegerValue msgId(80);
vwochnik 67:c360a2b2c948 246 if (!record.add(msgId))
vwochnik 67:c360a2b2c948 247 return;
vwochnik 67:c360a2b2c948 248
vwochnik 70:f489ca11f254 249 if ((_client.stream("/devicecontrol/notifications", record) != SMARTREST_SUCCESS) ||
vwochnik 70:f489ca11f254 250 (_client.receive(received) != SMARTREST_SUCCESS)) {
vwochnik 67:c360a2b2c948 251 _client.stop();
vwochnik 67:c360a2b2c948 252 return;
vwochnik 67:c360a2b2c948 253 }
vwochnik 70:f489ca11f254 254
vwochnik 70:f489ca11f254 255 _client.stop();
vwochnik 70:f489ca11f254 256
vwochnik 70:f489ca11f254 257 str = received.value(0).characterValue();
vwochnik 70:f489ca11f254 258 if ((str == NULL) || (strlen(str) > sizeof(bayeuxId)))
vwochnik 70:f489ca11f254 259 return;
vwochnik 70:f489ca11f254 260
vwochnik 70:f489ca11f254 261 strcpy(bayeuxId, str);
vwochnik 70:f489ca11f254 262 record.clear();
vwochnik 70:f489ca11f254 263 }
vwochnik 70:f489ca11f254 264
vwochnik 70:f489ca11f254 265 // set channel
vwochnik 70:f489ca11f254 266 {
vwochnik 70:f489ca11f254 267 char chn[16]; int len;
vwochnik 70:f489ca11f254 268
vwochnik 70:f489ca11f254 269 len = 0;
vwochnik 70:f489ca11f254 270 snprintf(chn, sizeof(chn), "/%ld%n", _deviceId, &len);
vwochnik 70:f489ca11f254 271 if ((len == 0) || (len == sizeof(chn)))
vwochnik 70:f489ca11f254 272 return;
vwochnik 70:f489ca11f254 273
vwochnik 70:f489ca11f254 274 IntegerValue msgId(81);
vwochnik 70:f489ca11f254 275 CharValue bid(bayeuxId);
vwochnik 70:f489ca11f254 276 CharValue channel(chn);
vwochnik 70:f489ca11f254 277 if ((!record.add(msgId)) || (!record.add(bid)) || (!record.add(channel)))
vwochnik 70:f489ca11f254 278 return;
vwochnik 70:f489ca11f254 279
vwochnik 70:f489ca11f254 280 if ((_client.stream("/devicecontrol/notifications", record) != SMARTREST_SUCCESS) ||
vwochnik 70:f489ca11f254 281 (_client.receive(received) != SMARTREST_END_OF_RESPONSE)) {
vwochnik 67:c360a2b2c948 282 _client.stop();
vwochnik 70:f489ca11f254 283 return;
vwochnik 67:c360a2b2c948 284 }
vwochnik 70:f489ca11f254 285
vwochnik 67:c360a2b2c948 286 _client.stop();
vwochnik 70:f489ca11f254 287 record.clear();
vwochnik 70:f489ca11f254 288 }
vwochnik 70:f489ca11f254 289
vwochnik 70:f489ca11f254 290 {
vwochnik 70:f489ca11f254 291 IntegerValue msgId(83);
vwochnik 70:f489ca11f254 292 CharValue bid(bayeuxId);
vwochnik 70:f489ca11f254 293 if ((!record.add(msgId)) || (!record.add(bid)))
vwochnik 70:f489ca11f254 294 return;
vwochnik 67:c360a2b2c948 295 }
vwochnik 67:c360a2b2c948 296
vwochnik 67:c360a2b2c948 297 while (true) {
vwochnik 70:f489ca11f254 298 if (_client.stream("/devicecontrol/notifications", record) != SMARTREST_SUCCESS) {
vwochnik 70:f489ca11f254 299 _client.stop();
vwochnik 70:f489ca11f254 300 continue;
vwochnik 70:f489ca11f254 301 }
vwochnik 70:f489ca11f254 302
vwochnik 70:f489ca11f254 303 while (_client.receive(received) == SMARTREST_SUCCESS) {
vwochnik 70:f489ca11f254 304 if (!operationFromRecord(received, op))
vwochnik 70:f489ca11f254 305 continue;
vwochnik 70:f489ca11f254 306 _store.enqueue(op);
vwochnik 70:f489ca11f254 307 }
vwochnik 70:f489ca11f254 308
vwochnik 70:f489ca11f254 309 //TODO: error checking
vwochnik 70:f489ca11f254 310 _client.stop();
vwochnik 70:f489ca11f254 311 }
vwochnik 67:c360a2b2c948 312 }
vwochnik 67:c360a2b2c948 313
vwochnik 63:010bbbb4732a 314 void OperationSupport::thread1_func(void const *arg)
vwochnik 60:3c822f97fc73 315 {
vwochnik 60:3c822f97fc73 316 OperationSupport *that;
vwochnik 60:3c822f97fc73 317 that = (OperationSupport*)arg;
vwochnik 63:010bbbb4732a 318 that->thread1();
vwochnik 60:3c822f97fc73 319 }
vwochnik 63:010bbbb4732a 320
vwochnik 63:010bbbb4732a 321 void OperationSupport::thread2_func(void const *arg)
vwochnik 63:010bbbb4732a 322 {
vwochnik 63:010bbbb4732a 323 OperationSupport *that;
vwochnik 63:010bbbb4732a 324 that = (OperationSupport*)arg;
vwochnik 63:010bbbb4732a 325 that->thread2();
vwochnik 63:010bbbb4732a 326 }
vwochnik 67:c360a2b2c948 327
vwochnik 67:c360a2b2c948 328 void OperationSupport::thread3_func(void const *arg)
vwochnik 67:c360a2b2c948 329 {
vwochnik 67:c360a2b2c948 330 OperationSupport *that;
vwochnik 67:c360a2b2c948 331 that = (OperationSupport*)arg;
vwochnik 67:c360a2b2c948 332 that->thread3();
vwochnik 67:c360a2b2c948 333 }