Simulated product dispenser
Fork of mbed-cloud-workshop-connect-HTS221 by
FirmwareUpdateResource.cpp
00001 // ---------------------------------------------------------------------------- 00002 // Copyright 2016-2017 ARM Ltd. 00003 // 00004 // SPDX-License-Identifier: Apache-2.0 00005 // 00006 // Licensed under the Apache License, Version 2.0 (the "License"); 00007 // you may not use this file except in compliance with the License. 00008 // You may obtain a copy of the License at 00009 // 00010 // http://www.apache.org/licenses/LICENSE-2.0 00011 // 00012 // Unless required by applicable law or agreed to in writing, software 00013 // distributed under the License is distributed on an "AS IS" BASIS, 00014 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00015 // See the License for the specific language governing permissions and 00016 // limitations under the License. 00017 // ---------------------------------------------------------------------------- 00018 00019 #include "update-client-lwm2m/FirmwareUpdateResource.h" 00020 00021 #include "update-client-common/arm_uc_common.h" 00022 #include "source/update_client_hub_state_machine.h" 00023 #include "source/update_client_hub_error_handler.h" 00024 00025 #include <stdio.h> 00026 00027 #define ARM_UCS_LWM2M_INTERNAL_ERROR (-1) 00028 #define ARM_UCS_LWM2M_INTERNAL_SUCCESS (0) 00029 00030 namespace FirmwareUpdateResource { 00031 00032 /* send delayed response */ 00033 enum { 00034 ResourcePackage, 00035 ResourcePackageURI, 00036 ResourceUpdate 00037 }; 00038 00039 static void packageCallback(void* _parameters); 00040 static void packageURICallback(void* _parameters); 00041 static void updateCallback(void*); 00042 static void notificationCallback(const M2MBase& object, NotificationDeliveryStatus delivery_status, void* client_args); 00043 static void sendDelayedResponseTask(uint32_t parameter); 00044 00045 /* LWM2M Firmware Update Object */ 00046 static M2MObject* updateObject; 00047 00048 /* LWM2M Firmware Update Object resources */ 00049 static M2MResource* resourcePackage = NULL; 00050 static M2MResource* resourcePackageURI = NULL; 00051 static M2MResource* resourceUpdate = NULL; 00052 static M2MResource* resourceState = NULL; 00053 static M2MResource* resourceResult = NULL; 00054 static M2MResource* resourceName = NULL; 00055 static M2MResource* resourceVersion = NULL; 00056 00057 /* function pointers to callback functions */ 00058 static void (*externalPackageCallback)(const uint8_t* buffer, uint16_t length) = NULL; 00059 static void (*externalPackageURICallback)(const uint8_t* buffer, uint16_t length) = NULL; 00060 static void (*externalUpdateCallback)(void) = NULL; 00061 static void (*externalNotificationCallback)(void) = NULL; 00062 00063 /* Callback structs for delayed response. 00064 * 00065 * There needs to be one per callback type to avoid collisions between different operations. 00066 */ 00067 static arm_uc_callback_t callbackNodePackage = { NULL, 0, NULL, 0 }; 00068 static arm_uc_callback_t callbackNodePackageURI = { NULL, 0, NULL, 0 }; 00069 static arm_uc_callback_t callbackNodeResourceUpdate = { NULL, 0, NULL, 0 }; 00070 } 00071 00072 /** 00073 * @brief Initialize LWM2M Firmware Update Object 00074 * @details Sets up LWM2M object with accompanying resources. 00075 */ 00076 void FirmwareUpdateResource::Initialize(void) 00077 { 00078 static bool initialized = false; 00079 00080 if (!initialized) 00081 { 00082 initialized = true; 00083 00084 /* The LWM2M Firmware Update Object is at /5 */ 00085 updateObject = M2MInterfaceFactory::create_object("5"); 00086 00087 if (updateObject) 00088 { 00089 /* Create first (and only) instance /5/0 */ 00090 M2MObjectInstance* updateInstance = updateObject->create_object_instance(); 00091 00092 if (updateInstance) 00093 { 00094 /* Set observable so the Portal can read it */ 00095 updateInstance->set_observable(true); 00096 00097 /* Default values are non-standard, but the standard has no 00098 values for indicating that the device is initializing. 00099 To address this, Service ignores -1 and/or 255 values coming through, 00100 so for our purposes this is the correct form of initialization. 00101 */ 00102 uint8_t defaultValue[] = {"-1"}; 00103 uint8_t defaultVersion[] = {"-1"}; 00104 00105 /* Create Package resource /5/0/0 */ 00106 resourcePackage = updateInstance->create_dynamic_resource( 00107 "0", "Package", M2MResourceInstance::OPAQUE, false); 00108 if (resourcePackage) 00109 { 00110 /* This should be PUT according to the standard but 00111 Connector client doesn't support callbacks for PUT. 00112 */ 00113 resourcePackage->set_operation(M2MBase::POST_ALLOWED); 00114 resourcePackage->set_execute_function(packageCallback); 00115 00116 /* The delayed response if for processing heavier loads */ 00117 resourcePackage->set_delayed_response(true); 00118 } 00119 00120 /* Create Package URI resource /5/0/1 */ 00121 resourcePackageURI = updateInstance->create_dynamic_resource( 00122 "1", "PackageURI", M2MResourceInstance::STRING, false); 00123 if (resourcePackageURI) 00124 { 00125 resourcePackageURI->set_operation(M2MBase::POST_ALLOWED); 00126 resourcePackageURI->set_execute_function(packageURICallback); 00127 resourcePackageURI->set_delayed_response(true); 00128 } 00129 00130 /* Create Update resource /5/0/2 */ 00131 resourceUpdate = updateInstance->create_dynamic_resource( 00132 "2", "Update", M2MResourceInstance::BOOLEAN, false); 00133 if (resourceUpdate) 00134 { 00135 resourceUpdate->set_operation(M2MBase::POST_ALLOWED); 00136 resourceUpdate->set_execute_function(updateCallback); 00137 resourceUpdate->set_delayed_response(true); 00138 } 00139 00140 /* Create State resource /5/0/3 */ 00141 resourceState = updateInstance->create_dynamic_resource( 00142 "3", "State", M2MResourceInstance::INTEGER, true); 00143 if (resourceState) 00144 { 00145 resourceState->set_operation(M2MBase::GET_ALLOWED); 00146 resourceState->set_notification_delivery_status_cb(notificationCallback, NULL); 00147 resourceState->set_value(defaultValue, sizeof(defaultValue) - 1); 00148 } 00149 00150 /* Create Update Result resource /5/0/5 */ 00151 resourceResult = updateInstance->create_dynamic_resource( 00152 "5", "UpdateResult", M2MResourceInstance::INTEGER, true); 00153 if (resourceResult) 00154 { 00155 resourceResult->set_operation(M2MBase::GET_ALLOWED); 00156 resourceResult->set_notification_delivery_status_cb(notificationCallback, NULL); 00157 resourceResult->set_value(defaultValue, sizeof(defaultValue) - 1); 00158 } 00159 00160 /* Create PkgName resource /5/0/6 */ 00161 resourceName = updateInstance->create_dynamic_resource( 00162 "6", "PkgName", M2MResourceInstance::STRING, true); 00163 if (resourceName) 00164 { 00165 resourceName->set_operation(M2MBase::GET_ALLOWED); 00166 resourceName->set_value(defaultVersion, sizeof(defaultVersion) - 1); 00167 } 00168 00169 /* Create PkgVersion resource /5/0/7 */ 00170 resourceVersion = updateInstance->create_dynamic_resource( 00171 "7", "PkgVersion", M2MResourceInstance::STRING, true); 00172 if (resourceVersion) 00173 { 00174 resourceVersion->set_operation(M2MBase::GET_ALLOWED); 00175 resourceVersion->set_value(defaultVersion, sizeof(defaultVersion) - 1); 00176 } 00177 } 00178 } 00179 } 00180 } 00181 00182 M2MObject* FirmwareUpdateResource::getObject() 00183 { 00184 Initialize(); 00185 00186 return updateObject; 00187 } 00188 00189 void FirmwareUpdateResource::packageCallback(void* _parameters) 00190 { 00191 UC_SRCE_TRACE("FirmwareUpdateResource::packageCallback"); 00192 00193 if (_parameters && externalPackageCallback) 00194 { 00195 /* recast parameter */ 00196 M2MResource::M2MExecuteParameter* parameters = 00197 static_cast<M2MResource::M2MExecuteParameter*>(_parameters); 00198 00199 /* read payload */ 00200 const uint8_t* buffer = parameters->get_argument_value(); 00201 uint16_t length = parameters->get_argument_value_length(); 00202 00203 /* invoke external callback function */ 00204 externalPackageCallback(buffer, length); 00205 00206 /* schedule delayed response */ 00207 ARM_UC_PostCallback(&callbackNodePackage, 00208 FirmwareUpdateResource::sendDelayedResponseTask, 00209 FirmwareUpdateResource::ResourcePackage); 00210 } 00211 } 00212 00213 void FirmwareUpdateResource::packageURICallback(void* _parameters) 00214 { 00215 UC_SRCE_TRACE("FirmwareUpdateResource::packageURICallback"); 00216 00217 if (_parameters && externalPackageURICallback) 00218 { 00219 /* recast parameter */ 00220 M2MResource::M2MExecuteParameter* parameters = 00221 static_cast<M2MResource::M2MExecuteParameter*>(_parameters); 00222 00223 /* read payload */ 00224 const uint8_t* buffer = parameters->get_argument_value(); 00225 uint16_t length = parameters->get_argument_value_length(); 00226 00227 /* invoke external callback function */ 00228 externalPackageURICallback(buffer, length); 00229 00230 /* schedule delayed response */ 00231 ARM_UC_PostCallback(&callbackNodePackageURI, 00232 FirmwareUpdateResource::sendDelayedResponseTask, 00233 FirmwareUpdateResource::ResourcePackageURI); 00234 } 00235 } 00236 00237 void FirmwareUpdateResource::updateCallback(void* _parameters) 00238 { 00239 UC_SRCE_TRACE("FirmwareUpdateResource::updateCallback"); 00240 00241 (void) _parameters; 00242 00243 if (externalUpdateCallback) 00244 { 00245 /* invoke external callback function */ 00246 externalUpdateCallback(); 00247 00248 /* schedule delayed response */ 00249 ARM_UC_PostCallback(&callbackNodeResourceUpdate, 00250 FirmwareUpdateResource::sendDelayedResponseTask, 00251 FirmwareUpdateResource::ResourceUpdate); 00252 } 00253 } 00254 00255 void FirmwareUpdateResource::notificationCallback(const M2MBase& base, 00256 const NotificationDeliveryStatus delivery_status, 00257 void *client_args) 00258 { 00259 UC_SRCE_TRACE("FirmwareUpdateResource::notificationCallback status: %d", delivery_status); 00260 00261 if (delivery_status == NOTIFICATION_STATUS_DELIVERED) { 00262 // Notification has been ACKed by server, complete to callback 00263 UC_SRCE_TRACE("FirmwareUpdateResource::notificationCallback DELIVERED"); 00264 00265 if (externalNotificationCallback) { 00266 externalNotificationCallback(); 00267 } 00268 00269 } 00270 else if (delivery_status == NOTIFICATION_STATUS_BUILD_ERROR || 00271 delivery_status == NOTIFICATION_STATUS_RESEND_QUEUE_FULL || 00272 delivery_status == NOTIFICATION_STATUS_SEND_FAILED || 00273 delivery_status == NOTIFICATION_STATUS_UNSUBSCRIBED) { 00274 // Error case, notification not reaching service 00275 // We are sending out error because we cannot rely connection is 00276 // anymore up and the service and client are not in sync anymore. 00277 // Also sending new notifications after this might lock event 00278 // machine because comms cannot service us anymore. 00279 UC_SRCE_ERR_MSG("Received Notification delivery status: %d - ERROR!", delivery_status); 00280 ARM_UC_HUB_ErrorHandler(HUB_ERR_CONNECTION, ARM_UC_HUB_getState()); 00281 00282 } 00283 else { 00284 // NOTIFICATION_STATUS_INIT 00285 // NOTIFICATION_STATUS_SENT 00286 // NOTIFICATION_STATUS_SUBSCRIBED 00287 UC_SRCE_TRACE("FirmwareUpdateResource::notificationCallback Status ignored, waiting delivery..."); 00288 } 00289 } 00290 00291 void FirmwareUpdateResource::sendDelayedResponseTask(uint32_t parameter) 00292 { 00293 UC_SRCE_TRACE("FirmwareUpdateResource::sendDelayedResponseTask"); 00294 00295 switch (parameter) 00296 { 00297 case FirmwareUpdateResource::ResourcePackage: 00298 UC_SRCE_TRACE("resourcePackage->send_delayed_post_response"); 00299 resourcePackage->send_delayed_post_response(); 00300 break; 00301 case FirmwareUpdateResource::ResourcePackageURI: 00302 UC_SRCE_TRACE("resourcePackageURI->send_delayed_post_response"); 00303 resourcePackageURI->send_delayed_post_response(); 00304 break; 00305 case FirmwareUpdateResource::ResourceUpdate: 00306 UC_SRCE_TRACE("resourceUpdate->send_delayed_post_response"); 00307 resourceUpdate->send_delayed_post_response(); 00308 break; 00309 default: 00310 UC_SRCE_ERR_MSG("unsupported resource"); 00311 break; 00312 } 00313 } 00314 00315 /*****************************************************************************/ 00316 /* Update Client Source */ 00317 /*****************************************************************************/ 00318 00319 /* Add callback for resource /5/0/0, Package */ 00320 int32_t FirmwareUpdateResource::addPackageCallback(void (*cb)(const uint8_t* buffer, uint16_t length)) 00321 { 00322 UC_SRCE_TRACE("FirmwareUpdateResource::addPackageCallback: %p", cb); 00323 00324 externalPackageCallback = cb; 00325 00326 return ARM_UCS_LWM2M_INTERNAL_SUCCESS; 00327 } 00328 00329 /* Add callback for resource /5/0/1, Package URI */ 00330 int32_t FirmwareUpdateResource::addPackageURICallback(void (*cb)(const uint8_t* buffer, uint16_t length)) 00331 { 00332 UC_SRCE_TRACE("FirmwareUpdateResource::addPackageURICallback: %p", cb); 00333 00334 externalPackageURICallback = cb; 00335 00336 return ARM_UCS_LWM2M_INTERNAL_SUCCESS; 00337 } 00338 00339 /* Add callback for resource /5/0/2, Update */ 00340 int32_t FirmwareUpdateResource::addUpdateCallback(void (*cb)(void)) 00341 { 00342 UC_SRCE_TRACE("FirmwareUpdateResource::addUpdateCallback: %p", cb); 00343 00344 externalUpdateCallback = cb; 00345 00346 return ARM_UCS_LWM2M_INTERNAL_SUCCESS; 00347 } 00348 00349 /* Add callback for when send{State, UpdateResult} is done */ 00350 int32_t FirmwareUpdateResource::addNotificationCallback(void (*cb)(void)) 00351 { 00352 UC_SRCE_TRACE("FirmwareUpdateResource::addNotificationCallback: %p", cb); 00353 00354 externalNotificationCallback = cb; 00355 00356 return ARM_UCS_LWM2M_INTERNAL_SUCCESS; 00357 } 00358 00359 /*****************************************************************************/ 00360 /* Update Client Status */ 00361 /*****************************************************************************/ 00362 00363 /* Send state for resource /5/0/3, State */ 00364 int32_t FirmwareUpdateResource::sendState(arm_ucs_lwm2m_state_t state) 00365 { 00366 UC_SRCE_TRACE("FirmwareUpdateResource::sendState"); 00367 00368 int32_t result = ARM_UCS_LWM2M_INTERNAL_ERROR; 00369 00370 if (state <= ARM_UCS_LWM2M_STATE_LAST) 00371 { 00372 /* valid states: 0-3 */ 00373 uint8_t value[2]; 00374 snprintf((char*)value, 2, "%d", state); 00375 resourceState->set_value(value, 1); 00376 00377 result = ARM_UCS_LWM2M_INTERNAL_SUCCESS; 00378 } 00379 00380 return result; 00381 } 00382 00383 /* Send result for resource /5/0/5, Update Result */ 00384 int32_t FirmwareUpdateResource::sendUpdateResult(arm_ucs_lwm2m_result_t updateResult) 00385 { 00386 UC_SRCE_TRACE("FirmwareUpdateResource::sendUpdateResult"); 00387 00388 int32_t result = ARM_UCS_LWM2M_INTERNAL_ERROR; 00389 00390 if (updateResult <= ARM_UCS_LWM2M_RESULT_LAST) 00391 { 00392 /* valid results: 0-8 */ 00393 uint8_t value[2]; 00394 snprintf((char*)value, 2, "%d", updateResult); 00395 resourceResult->set_value(value, 1); 00396 00397 result = ARM_UCS_LWM2M_INTERNAL_SUCCESS; 00398 } 00399 00400 return result; 00401 } 00402 00403 /* Send name for resource /5/0/6 PkgName */ 00404 int32_t FirmwareUpdateResource::sendPkgName(const uint8_t* name, uint16_t length) 00405 { 00406 UC_SRCE_TRACE("FirmwareUpdateResource::sendPkgName"); 00407 00408 int32_t result = ARM_UCS_LWM2M_INTERNAL_ERROR; 00409 00410 /* the maximum length is defined in the OMA LWM2M standard. */ 00411 if ((name != NULL) && (length <= 255)) 00412 { 00413 uint8_t value[64] = { 0 }; 00414 uint8_t index = 0; 00415 00416 /* convert to printable characters using lookup table */ 00417 for ( ; (index < 32) && (index < length); index++) 00418 { 00419 value[2 * index ] = arm_uc_hex_table[name[index] >> 4]; 00420 value[2 * index + 1] = arm_uc_hex_table[name[index] & 0x0F]; 00421 } 00422 00423 resourceName->set_value(value, 2 * index); 00424 00425 result = ARM_UCS_LWM2M_INTERNAL_SUCCESS; 00426 } 00427 00428 return result; 00429 } 00430 00431 /* Send version for resource /5/0/7, PkgVersion */ 00432 int32_t FirmwareUpdateResource::sendPkgVersion(uint64_t version) 00433 { 00434 UC_SRCE_TRACE("FirmwareUpdateResource::sendPkgVersion"); 00435 00436 uint8_t value[21] = { 0 }; 00437 uint8_t length = snprintf((char*) value, 21, "%llu" , version); 00438 resourceVersion->set_value(value, length); 00439 00440 return ARM_UCS_LWM2M_INTERNAL_SUCCESS; 00441 } 00442 00443 void FirmwareUpdateResource::Uninitialize(void) 00444 { 00445 UC_SRCE_TRACE("FirmwareUpdateResource::Uninitialize"); 00446 delete updateObject; 00447 updateObject = NULL; 00448 }
Generated on Tue Jul 12 2022 19:12:12 by 1.7.2