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:
Tue Mar 03 14:10:09 2015 +0000
Revision:
77:f6717e4eccc4
Parent:
70:f489ca11f254
Child:
81:4a7761914901
Working device push, DNS caching, change logging level when running and more.

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
vwochnik 63:010bbbb4732a 188 updateOperation(op);
vwochnik 63:010bbbb4732a 189 ret = _executor.executeOperation(op);
vwochnik 63:010bbbb4732a 190 _store.markAsDone(op, ret);
vwochnik 63:010bbbb4732a 191 }
vwochnik 63:010bbbb4732a 192 }
vwochnik 63:010bbbb4732a 193
vwochnik 63:010bbbb4732a 194 void OperationSupport::thread2()
vwochnik 63:010bbbb4732a 195 {
vwochnik 63:010bbbb4732a 196 OperationStore::Operation op;
vwochnik 63:010bbbb4732a 197 Aggregator aggr(true);
vwochnik 63:010bbbb4732a 198
vwochnik 60:3c822f97fc73 199 while (!_init)
vwochnik 60:3c822f97fc73 200 Thread::yield();
vwochnik 60:3c822f97fc73 201
vwochnik 63:010bbbb4732a 202 while (true) {
vwochnik 63:010bbbb4732a 203 while ((!aggr.full()) && (_store.takeDone(op))) {
vwochnik 63:010bbbb4732a 204 ComposedRecord record;
vwochnik 60:3c822f97fc73 205
vwochnik 63:010bbbb4732a 206 IntegerValue msgId(111);
vwochnik 63:010bbbb4732a 207 IntegerValue operationId(op.identifier);
vwochnik 63:010bbbb4732a 208 if ((!record.add(msgId)) || (!record.add(operationId)) ||
vwochnik 63:010bbbb4732a 209 (!record.add(operationStateValue(op))))
vwochnik 63:010bbbb4732a 210 break;
vwochnik 63:010bbbb4732a 211
vwochnik 63:010bbbb4732a 212 if (!aggr.add(record))
vwochnik 63:010bbbb4732a 213 break;
vwochnik 63:010bbbb4732a 214 }
vwochnik 63:010bbbb4732a 215
vwochnik 63:010bbbb4732a 216 if (aggr.length() == 0) {
vwochnik 63:010bbbb4732a 217 Thread::yield();
vwochnik 63:010bbbb4732a 218 continue;
vwochnik 63:010bbbb4732a 219 }
vwochnik 63:010bbbb4732a 220
vwochnik 65:a62dbef2f924 221 if (_client.send(aggr) != SMARTREST_SUCCESS) { }
vwochnik 63:010bbbb4732a 222 _client.stop();
vwochnik 63:010bbbb4732a 223 aggr.clear();
vwochnik 63:010bbbb4732a 224 }
vwochnik 60:3c822f97fc73 225 }
vwochnik 60:3c822f97fc73 226
vwochnik 67:c360a2b2c948 227 void OperationSupport::thread3()
vwochnik 67:c360a2b2c948 228 {
vwochnik 70:f489ca11f254 229 char bayeuxId[33];
vwochnik 67:c360a2b2c948 230 ComposedRecord record;
vwochnik 67:c360a2b2c948 231 ParsedRecord received;
vwochnik 70:f489ca11f254 232 OperationStore::Operation op;
vwochnik 67:c360a2b2c948 233
vwochnik 67:c360a2b2c948 234 while ((!_init) || (_firstRun))
vwochnik 67:c360a2b2c948 235 Thread::yield();
vwochnik 67:c360a2b2c948 236
vwochnik 67:c360a2b2c948 237 // request Bayeux ID
vwochnik 67:c360a2b2c948 238 {
vwochnik 70:f489ca11f254 239 const char *str;
vwochnik 67:c360a2b2c948 240 IntegerValue msgId(80);
vwochnik 67:c360a2b2c948 241 if (!record.add(msgId))
vwochnik 67:c360a2b2c948 242 return;
vwochnik 67:c360a2b2c948 243
vwochnik 70:f489ca11f254 244 if ((_client.stream("/devicecontrol/notifications", record) != SMARTREST_SUCCESS) ||
vwochnik 70:f489ca11f254 245 (_client.receive(received) != SMARTREST_SUCCESS)) {
vwochnik 67:c360a2b2c948 246 _client.stop();
vwochnik 67:c360a2b2c948 247 return;
vwochnik 67:c360a2b2c948 248 }
vwochnik 70:f489ca11f254 249 _client.stop();
vwochnik 70:f489ca11f254 250
vwochnik 70:f489ca11f254 251 str = received.value(0).characterValue();
vwochnik 70:f489ca11f254 252 if ((str == NULL) || (strlen(str) > sizeof(bayeuxId)))
vwochnik 70:f489ca11f254 253 return;
vwochnik 70:f489ca11f254 254
vwochnik 70:f489ca11f254 255 strcpy(bayeuxId, str);
vwochnik 70:f489ca11f254 256 record.clear();
vwochnik 70:f489ca11f254 257 }
vwochnik 70:f489ca11f254 258
vwochnik 70:f489ca11f254 259 // set channel
vwochnik 70:f489ca11f254 260 {
xinlei 77:f6717e4eccc4 261 char chn[16];
xinlei 77:f6717e4eccc4 262 int len = 0;
vwochnik 70:f489ca11f254 263 snprintf(chn, sizeof(chn), "/%ld%n", _deviceId, &len);
vwochnik 70:f489ca11f254 264 if ((len == 0) || (len == sizeof(chn)))
vwochnik 70:f489ca11f254 265 return;
vwochnik 70:f489ca11f254 266
vwochnik 70:f489ca11f254 267 IntegerValue msgId(81);
vwochnik 70:f489ca11f254 268 CharValue bid(bayeuxId);
vwochnik 70:f489ca11f254 269 CharValue channel(chn);
vwochnik 70:f489ca11f254 270 if ((!record.add(msgId)) || (!record.add(bid)) || (!record.add(channel)))
vwochnik 70:f489ca11f254 271 return;
vwochnik 70:f489ca11f254 272
vwochnik 70:f489ca11f254 273 if ((_client.stream("/devicecontrol/notifications", record) != SMARTREST_SUCCESS) ||
vwochnik 70:f489ca11f254 274 (_client.receive(received) != SMARTREST_END_OF_RESPONSE)) {
vwochnik 67:c360a2b2c948 275 _client.stop();
vwochnik 70:f489ca11f254 276 return;
vwochnik 67:c360a2b2c948 277 }
vwochnik 70:f489ca11f254 278
vwochnik 67:c360a2b2c948 279 _client.stop();
vwochnik 70:f489ca11f254 280 record.clear();
vwochnik 70:f489ca11f254 281 }
vwochnik 70:f489ca11f254 282
vwochnik 70:f489ca11f254 283 {
vwochnik 70:f489ca11f254 284 IntegerValue msgId(83);
vwochnik 70:f489ca11f254 285 CharValue bid(bayeuxId);
vwochnik 70:f489ca11f254 286 if ((!record.add(msgId)) || (!record.add(bid)))
vwochnik 70:f489ca11f254 287 return;
vwochnik 67:c360a2b2c948 288 }
vwochnik 67:c360a2b2c948 289
vwochnik 67:c360a2b2c948 290 while (true) {
vwochnik 70:f489ca11f254 291 if (_client.stream("/devicecontrol/notifications", record) != SMARTREST_SUCCESS) {
vwochnik 70:f489ca11f254 292 _client.stop();
vwochnik 70:f489ca11f254 293 continue;
vwochnik 70:f489ca11f254 294 }
vwochnik 70:f489ca11f254 295
vwochnik 70:f489ca11f254 296 while (_client.receive(received) == SMARTREST_SUCCESS) {
vwochnik 70:f489ca11f254 297 if (!operationFromRecord(received, op))
vwochnik 70:f489ca11f254 298 continue;
vwochnik 70:f489ca11f254 299 _store.enqueue(op);
vwochnik 70:f489ca11f254 300 }
vwochnik 70:f489ca11f254 301
vwochnik 70:f489ca11f254 302 //TODO: error checking
vwochnik 70:f489ca11f254 303 _client.stop();
vwochnik 70:f489ca11f254 304 }
vwochnik 67:c360a2b2c948 305 }
vwochnik 67:c360a2b2c948 306
vwochnik 63:010bbbb4732a 307 void OperationSupport::thread1_func(void const *arg)
vwochnik 60:3c822f97fc73 308 {
vwochnik 60:3c822f97fc73 309 OperationSupport *that;
vwochnik 60:3c822f97fc73 310 that = (OperationSupport*)arg;
vwochnik 63:010bbbb4732a 311 that->thread1();
vwochnik 60:3c822f97fc73 312 }
vwochnik 63:010bbbb4732a 313
vwochnik 63:010bbbb4732a 314 void OperationSupport::thread2_func(void const *arg)
vwochnik 63:010bbbb4732a 315 {
vwochnik 63:010bbbb4732a 316 OperationSupport *that;
vwochnik 63:010bbbb4732a 317 that = (OperationSupport*)arg;
vwochnik 63:010bbbb4732a 318 that->thread2();
vwochnik 63:010bbbb4732a 319 }
vwochnik 67:c360a2b2c948 320
vwochnik 67:c360a2b2c948 321 void OperationSupport::thread3_func(void const *arg)
vwochnik 67:c360a2b2c948 322 {
vwochnik 67:c360a2b2c948 323 OperationSupport *that;
vwochnik 67:c360a2b2c948 324 that = (OperationSupport*)arg;
vwochnik 67:c360a2b2c948 325 that->thread3();
vwochnik 67:c360a2b2c948 326 }