Simulated product dispenser
Fork of mbed-cloud-workshop-connect-HTS221 by
m2mtlvdeserializer.cpp
00001 /* 00002 * Copyright (c) 2015 ARM Limited. All rights reserved. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * Licensed under the Apache License, Version 2.0 (the License); you may 00005 * not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an AS IS BASIS, WITHOUT 00012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 // Needed for PRIu64 on FreeRTOS 00017 #include <stdio.h> 00018 // Note: this macro is needed on armcc to get the the limit macros like UINT16_MAX 00019 #ifndef __STDC_LIMIT_MACROS 00020 #define __STDC_LIMIT_MACROS 00021 #endif 00022 00023 // Note: this macro is needed on armcc to get the the PRI*32 macros 00024 // from inttypes.h in a C++ code. 00025 #ifndef __STDC_FORMAT_MACROS 00026 #define __STDC_FORMAT_MACROS 00027 #endif 00028 00029 #include "include/m2mtlvdeserializer.h" 00030 #include "mbed-client/m2mconstants.h" 00031 #include "mbed-trace/mbed_trace.h" 00032 #include "common_functions.h" 00033 00034 #define TRACE_GROUP "mClt" 00035 #define BUFFER_SIZE 10 00036 00037 bool M2MTLVDeserializer::is_object_instance(const uint8_t *tlv) 00038 { 00039 return is_object_instance(tlv, 0); 00040 } 00041 00042 bool M2MTLVDeserializer::is_resource(const uint8_t *tlv) 00043 { 00044 return is_resource(tlv, 0); 00045 } 00046 00047 bool M2MTLVDeserializer::is_multiple_resource(const uint8_t *tlv) 00048 { 00049 return is_multiple_resource(tlv, 0); 00050 } 00051 00052 bool M2MTLVDeserializer::is_resource_instance(const uint8_t *tlv) 00053 { 00054 return is_resource_instance(tlv, 0); 00055 } 00056 00057 M2MTLVDeserializer::Error M2MTLVDeserializer::deserialise_object_instances(const uint8_t* tlv, 00058 uint32_t tlv_size, 00059 M2MObject &object, 00060 M2MTLVDeserializer::Operation operation) 00061 { 00062 M2MTLVDeserializer::Error error = M2MTLVDeserializer::None; 00063 if (is_object_instance(tlv) ) { 00064 tr_debug("M2MTLVDeserializer::deserialise_object_instances"); 00065 error = deserialize_object_instances(tlv, tlv_size, 0, object,operation,false); 00066 if(M2MTLVDeserializer::None == error) { 00067 error = deserialize_object_instances(tlv, tlv_size, 0, object,operation,true); 00068 } 00069 } else { 00070 tr_debug("M2MTLVDeserializer::deserialise_object_instances ::NotValid"); 00071 error = M2MTLVDeserializer::NotValid; 00072 } 00073 return error; 00074 } 00075 00076 M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_resources(const uint8_t *tlv, 00077 uint32_t tlv_size, 00078 M2MObjectInstance &object_instance, 00079 M2MTLVDeserializer::Operation operation) 00080 { 00081 M2MTLVDeserializer::Error error = M2MTLVDeserializer::None; 00082 if (!is_resource(tlv) && !is_multiple_resource(tlv)) { 00083 error = M2MTLVDeserializer::NotValid; 00084 } else { 00085 error = deserialize_resources(tlv, tlv_size, 0, object_instance, operation,false); 00086 if(M2MTLVDeserializer::None == error) { 00087 if (M2MTLVDeserializer::Put == operation) { 00088 remove_resources(tlv, tlv_size, object_instance, 0); 00089 } 00090 error = deserialize_resources(tlv, tlv_size, 0, object_instance, operation,true); 00091 } 00092 } 00093 return error; 00094 } 00095 00096 M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_resource_instances(const uint8_t *tlv, 00097 uint32_t tlv_size, 00098 M2MResource &resource, 00099 M2MTLVDeserializer::Operation operation) 00100 { 00101 M2MTLVDeserializer::Error error = M2MTLVDeserializer::None; 00102 if (!is_multiple_resource(tlv)) { 00103 error = M2MTLVDeserializer::NotValid; 00104 } else { 00105 tr_debug("M2MTLVDeserializer::deserialize_resource_instances()"); 00106 uint8_t offset = 2; 00107 00108 ((tlv[0] & 0x20) == 0) ? offset : offset++; 00109 00110 uint8_t length = tlv[0] & 0x18; 00111 if(length == 0x08) { 00112 offset += 1; 00113 } else if(length == 0x10) { 00114 offset += 2; 00115 } else if(length == 0x18) { 00116 offset += 3; 00117 } 00118 00119 tr_debug("M2MTLVDeserializer::deserialize_resource_instances() Offset %d", offset); 00120 error = deserialize_resource_instances(tlv, tlv_size, offset, resource, operation,false); 00121 if(M2MTLVDeserializer::None == error) { 00122 if (M2MTLVDeserializer::Put == operation) { 00123 remove_resource_instances(tlv, tlv_size, resource, offset); 00124 } 00125 error = deserialize_resource_instances(tlv, tlv_size, offset, resource, operation,true); 00126 } 00127 } 00128 return error; 00129 } 00130 00131 M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_object_instances(const uint8_t *tlv, 00132 uint32_t tlv_size, 00133 uint32_t offset, 00134 M2MObject &object, 00135 M2MTLVDeserializer::Operation operation, 00136 bool update_value) 00137 { 00138 tr_debug("M2MTLVDeserializer::deserialize_object_instances()"); 00139 M2MTLVDeserializer::Error error = M2MTLVDeserializer::None; 00140 TypeIdLength til(tlv, offset); 00141 til.deserialize(); 00142 offset = til._offset; 00143 00144 const M2MObjectInstanceList &list = object.instances(); 00145 M2MObjectInstanceList::const_iterator it; 00146 it = list.begin(); 00147 00148 if (TYPE_OBJECT_INSTANCE == til._type) { 00149 for (; it!=list.end(); it++) { 00150 if((*it)->instance_id() == til._id) { 00151 error = deserialize_resources(tlv, tlv_size, offset, (**it),operation, update_value); 00152 } 00153 } 00154 offset += til._length; 00155 00156 if(offset < tlv_size) { 00157 error = deserialize_object_instances(tlv, tlv_size, offset, object, operation, update_value); 00158 } 00159 } 00160 return error; 00161 } 00162 00163 M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_resources(const uint8_t *tlv, 00164 uint32_t tlv_size, 00165 uint32_t offset, 00166 M2MObjectInstance &object_instance, 00167 M2MTLVDeserializer::Operation operation, 00168 bool update_value) 00169 { 00170 tr_debug("M2MTLVDeserializer::deserialize_resources()"); 00171 M2MTLVDeserializer::Error error = M2MTLVDeserializer::None; 00172 TypeIdLength til(tlv, offset); 00173 til.deserialize(); 00174 offset = til._offset; 00175 00176 const M2MResourceList &list = object_instance.resources(); 00177 M2MResourceList::const_iterator it; 00178 it = list.begin(); 00179 00180 bool found = false; 00181 bool multi = false; 00182 if (TYPE_RESOURCE == til._type || TYPE_RESOURCE_INSTANCE == til._type) { 00183 multi = false; 00184 for (; it!=list.end(); it++) { 00185 if((*it)->name_id() == til._id){ 00186 tr_debug("M2MTLVDeserializer::deserialize_resources() - Resource ID %d ", til._id); 00187 found = true; 00188 if(update_value) { 00189 if(til._length > 0) { 00190 tr_debug("M2MTLVDeserializer::deserialize_resources() - Update value"); 00191 if (!set_resource_instance_value((*it), tlv+offset, til._length)) { 00192 error = M2MTLVDeserializer::OutOfMemory; 00193 break; 00194 } 00195 } else { 00196 tr_debug("M2MTLVDeserializer::deserialize_resources() - Clear Value"); 00197 (*it)->clear_value(); 00198 } 00199 break; 00200 } else if(0 == ((*it)->operation() & SN_GRS_PUT_ALLOWED)) { 00201 tr_debug("M2MTLVDeserializer::deserialize_resources() - NOT_ALLOWED"); 00202 error = M2MTLVDeserializer::NotAllowed; 00203 break; 00204 } 00205 } 00206 } 00207 } else if (TYPE_MULTIPLE_RESOURCE == til._type) { 00208 multi = true; 00209 for (; it!=list.end(); it++) { 00210 if((*it)->supports_multiple_instances() && 00211 (*it)->name_id() == til._id) { 00212 found = true; 00213 error = deserialize_resource_instances(tlv, tlv_size, offset, (**it), object_instance, operation, update_value); 00214 } 00215 } 00216 } else { 00217 error = M2MTLVDeserializer::NotValid; 00218 return error; 00219 } 00220 00221 if(!found) { 00222 if(M2MTLVDeserializer::Post == operation) { 00223 //Create a new Resource 00224 String id; 00225 id.append_int(til._id); 00226 M2MResource *resource = object_instance.create_dynamic_resource(id,"",M2MResourceInstance::OPAQUE,true,multi); 00227 if(resource) { 00228 resource->set_operation(M2MBase::GET_PUT_POST_DELETE_ALLOWED); 00229 } 00230 if( TYPE_MULTIPLE_RESOURCE == til._type ) { 00231 error = deserialize_resource_instances(tlv, tlv_size, offset, (*resource), object_instance, operation, update_value); 00232 } 00233 } else if(M2MTLVDeserializer::Put == operation) { 00234 error = M2MTLVDeserializer::NotFound; 00235 } 00236 } 00237 00238 00239 offset += til._length; 00240 00241 if(offset < tlv_size) { 00242 error = deserialize_resources(tlv, tlv_size, offset, object_instance, operation, update_value); 00243 } 00244 return error; 00245 } 00246 00247 M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_resource_instances(const uint8_t *tlv, 00248 uint32_t tlv_size, 00249 uint32_t offset, 00250 M2MResource &resource, 00251 M2MObjectInstance &object_instance, 00252 M2MTLVDeserializer::Operation operation, 00253 bool update_value) 00254 { 00255 M2MTLVDeserializer::Error error = M2MTLVDeserializer::None; 00256 TypeIdLength til(tlv, offset); 00257 til.deserialize(); 00258 offset = til._offset; 00259 00260 if (TYPE_MULTIPLE_RESOURCE == til._type || TYPE_RESOURCE_INSTANCE == til._type) { 00261 const M2MResourceInstanceList &list = resource.resource_instances(); 00262 M2MResourceInstanceList::const_iterator it; 00263 it = list.begin(); 00264 bool found = false; 00265 for (; it!=list.end(); it++) { 00266 if((*it)->instance_id() == til._id && TYPE_RESOURCE_INSTANCE == til._type) { 00267 found = true; 00268 if(update_value) { 00269 if(til._length > 0) { 00270 if (!set_resource_instance_value((*it), tlv+offset, til._length)) { 00271 error = M2MTLVDeserializer::OutOfMemory; 00272 break; 00273 } 00274 } else { 00275 (*it)->clear_value(); 00276 } 00277 break; 00278 } else if(0 == ((*it)->operation() & SN_GRS_PUT_ALLOWED)) { 00279 error = M2MTLVDeserializer::NotAllowed; 00280 break; 00281 } 00282 } 00283 } 00284 00285 if(!found) { 00286 if(M2MTLVDeserializer::Post == operation) { 00287 // Create a new Resource Instance 00288 M2MResourceInstance *res_instance = object_instance.create_dynamic_resource_instance(resource.name(),"", 00289 resource.resource_instance_type(), 00290 true, 00291 til._id); 00292 if(res_instance) { 00293 res_instance->set_operation(M2MBase::GET_PUT_POST_DELETE_ALLOWED); 00294 } 00295 } else if(M2MTLVDeserializer::Put == operation) { 00296 error = M2MTLVDeserializer::NotFound; 00297 } 00298 } 00299 } else { 00300 error = M2MTLVDeserializer::NotValid; 00301 return error; 00302 } 00303 00304 offset += til._length; 00305 00306 if(offset < tlv_size) { 00307 error = deserialize_resource_instances(tlv, tlv_size, offset, resource, object_instance, operation, update_value); 00308 } 00309 return error; 00310 } 00311 00312 M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_resource_instances(const uint8_t *tlv, 00313 uint32_t tlv_size, 00314 uint32_t offset, 00315 M2MResource &resource, 00316 M2MTLVDeserializer::Operation operation, 00317 bool update_value) 00318 { 00319 M2MTLVDeserializer::Error error = M2MTLVDeserializer::None; 00320 TypeIdLength til(tlv, offset); 00321 til.deserialize(); 00322 offset = til._offset; 00323 00324 if (TYPE_RESOURCE_INSTANCE == til._type) { 00325 const M2MResourceInstanceList &list = resource.resource_instances(); 00326 M2MResourceInstanceList::const_iterator it; 00327 it = list.begin(); 00328 bool found = false; 00329 for (; it!=list.end(); it++) { 00330 if((*it)->instance_id() == til._id) { 00331 found = true; 00332 if(update_value) { 00333 if(til._length > 0) { 00334 if (!set_resource_instance_value((*it),tlv+offset, til._length)) { 00335 error = M2MTLVDeserializer::OutOfMemory; 00336 break; 00337 } 00338 } else { 00339 (*it)->clear_value(); 00340 } 00341 break; 00342 } else if(0 == ((*it)->operation() & SN_GRS_PUT_ALLOWED)) { 00343 error = M2MTLVDeserializer::NotAllowed; 00344 break; 00345 } 00346 } 00347 } 00348 if(!found) { 00349 if(M2MTLVDeserializer::Post == operation) { 00350 error = M2MTLVDeserializer::NotAllowed; 00351 } else if(M2MTLVDeserializer::Put == operation) { 00352 error = M2MTLVDeserializer::NotFound; 00353 } 00354 } 00355 } else { 00356 error = M2MTLVDeserializer::NotValid; 00357 return error; 00358 } 00359 00360 offset += til._length; 00361 00362 if(offset < tlv_size) { 00363 error = deserialize_resource_instances(tlv, tlv_size, offset, resource, operation, update_value); 00364 } 00365 return error; 00366 } 00367 00368 bool M2MTLVDeserializer::is_object_instance(const uint8_t *tlv, uint32_t offset) 00369 { 00370 bool ret = false; 00371 if (tlv) { 00372 uint8_t value = tlv[offset]; 00373 ret = (TYPE_OBJECT_INSTANCE == (value & TYPE_RESOURCE)); 00374 } 00375 return ret; 00376 } 00377 00378 uint16_t M2MTLVDeserializer::instance_id(const uint8_t *tlv) 00379 { 00380 TypeIdLength til(tlv, 0); 00381 til.deserialize(); 00382 uint16_t id = til._id; 00383 return id; 00384 } 00385 00386 bool M2MTLVDeserializer::is_resource(const uint8_t *tlv, uint32_t offset) 00387 { 00388 bool ret = false; 00389 if (tlv) { 00390 ret = (TYPE_RESOURCE == (tlv[offset] & TYPE_RESOURCE)); 00391 } 00392 return ret; 00393 } 00394 00395 bool M2MTLVDeserializer::is_multiple_resource(const uint8_t *tlv, uint32_t offset) 00396 { 00397 bool ret = false; 00398 if (tlv) { 00399 ret = (TYPE_MULTIPLE_RESOURCE == (tlv[offset] & TYPE_RESOURCE)); 00400 } 00401 return ret; 00402 } 00403 00404 bool M2MTLVDeserializer::is_resource_instance(const uint8_t *tlv, uint32_t offset) 00405 { 00406 bool ret = false; 00407 if (tlv) { 00408 ret = (TYPE_RESOURCE_INSTANCE == (tlv[offset] & TYPE_RESOURCE)); 00409 } 00410 return ret; 00411 } 00412 00413 bool M2MTLVDeserializer::set_resource_instance_value(M2MResourceBase *res, const uint8_t *tlv, const uint32_t size) 00414 { 00415 bool success = true; 00416 switch (res->resource_instance_type()) { 00417 case M2MResourceBase::INTEGER: 00418 case M2MResourceBase::BOOLEAN: 00419 case M2MResourceBase::TIME: 00420 { 00421 int64_t value = String::convert_array_to_integer(tlv, size); 00422 if (!res->set_value(value)) { 00423 success = false; 00424 } 00425 break; 00426 // Todo! implement conversion for other types as well 00427 } 00428 case M2MResourceBase::STRING: 00429 case M2MResourceBase::OPAQUE: 00430 case M2MResourceBase::OBJLINK: 00431 if (!res->set_value(tlv, size)) { 00432 success = false; 00433 } 00434 break; 00435 case M2MResourceBase::FLOAT: 00436 { 00437 uint32_t value = common_read_32_bit(tlv); 00438 if (!res->set_value_float(*(float*)&value)) { 00439 success = false; 00440 } 00441 break; 00442 } 00443 default: 00444 success = false; 00445 break; 00446 } 00447 00448 return success; 00449 } 00450 00451 void M2MTLVDeserializer::remove_resources(const uint8_t *tlv, 00452 uint32_t tlv_size, 00453 M2MObjectInstance &object_instance, 00454 uint32_t offset_size) 00455 { 00456 tr_debug("M2MTLVDeserializer::remove_resources"); 00457 uint32_t offset = offset_size; 00458 const M2MResourceList &list = object_instance.resources(); 00459 M2MResourceList::const_iterator it; 00460 00461 it = list.begin(); 00462 for (; it!=list.end();) { 00463 bool found = false; 00464 while(offset < tlv_size) { 00465 TypeIdLength til(tlv, offset); 00466 til.deserialize(); 00467 offset = til._offset; 00468 offset += til._length; 00469 if((*it)->name_id() == til._id){ 00470 offset = offset_size; 00471 found = true; 00472 break; 00473 } 00474 } 00475 offset = offset_size; 00476 00477 // Remove resource if not part of the TLV message 00478 if (!found) { 00479 tr_debug("M2MTLVDeserializer::remove_resources - remove resource %" PRId32, (*it)->name_id()); 00480 object_instance.remove_resource((*it)->name()); 00481 } else { 00482 ++it; 00483 } 00484 } 00485 } 00486 00487 void M2MTLVDeserializer::remove_resource_instances(const uint8_t *tlv, 00488 uint32_t tlv_size, 00489 M2MResource &resource, 00490 uint32_t offset_size) 00491 { 00492 tr_debug("M2MTLVDeserializer::remove_resource_instances"); 00493 uint32_t offset = offset_size; 00494 const M2MResourceInstanceList &list = resource.resource_instances(); 00495 M2MResourceInstanceList::const_iterator it; 00496 it = list.begin(); 00497 00498 for (; it!=list.end();) { 00499 bool found = false; 00500 while (offset < tlv_size) { 00501 TypeIdLength til(tlv, offset); 00502 til.deserialize(); 00503 offset = til._offset; 00504 offset += til._length; 00505 if ((*it)->instance_id() == til._id){ 00506 offset = offset_size; 00507 found = true; 00508 break; 00509 } 00510 } 00511 offset = offset_size; 00512 00513 // Remove resource instance if not part of the TLV message 00514 if (!found) { 00515 tr_debug("M2MTLVDeserializer::remove_resource_instances - remove resource instance %d", (*it)->instance_id()); 00516 resource.remove_resource_instance((*it)->instance_id()); 00517 } else { 00518 ++it; 00519 } 00520 } 00521 } 00522 00523 TypeIdLength::TypeIdLength(const uint8_t *tlv, uint32_t offset) 00524 : _tlv(tlv), _offset(offset), _type(tlv[offset] & 0xC0), _id(0), _length(0) 00525 { 00526 } 00527 00528 void TypeIdLength::deserialize() 00529 { 00530 uint32_t idLength = _tlv[_offset] & ID16; 00531 uint32_t lengthType = _tlv[_offset] & LENGTH24; 00532 if (0 == lengthType) { 00533 _length = _tlv[_offset] & 0x07; 00534 } 00535 _offset++; 00536 00537 deserialiseID(idLength); 00538 deserialiseLength(lengthType); 00539 } 00540 00541 void TypeIdLength::deserialiseID(uint32_t idLength) 00542 { 00543 _id = _tlv[_offset++] & 0xFF; 00544 if (ID16 == idLength) { 00545 _id = (_id << 8) + (_tlv[_offset++] & 0xFF); 00546 } 00547 } 00548 00549 void TypeIdLength::deserialiseLength(uint32_t lengthType) 00550 { 00551 if (lengthType > 0) { 00552 _length = _tlv[_offset++] & 0xFF; 00553 } 00554 if (lengthType > LENGTH8) { 00555 _length = (_length << 8) + (_tlv[_offset++] & 0xFF); 00556 } 00557 if (lengthType > LENGTH16) { 00558 _length = (_length << 8) + (_tlv[_offset++] & 0xFF); 00559 } 00560 }
Generated on Tue Jul 12 2022 19:12:13 by 1.7.2