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:
xinlei
Date:
Wed Mar 04 14:02:39 2015 +0000
Revision:
81:4a7761914901
Parent:
77:f6717e4eccc4
Child:
82:ca7430f50b2b
Express mode: walk-around for stability issue.

Who changed what in which revision?

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