286 lines
9.9 KiB
C
286 lines
9.9 KiB
C
/*
|
|
* Tencent is pleased to support the open source community by making IoT Hub available.
|
|
* Copyright (C) 2018-2020 THL A29 Limited, a Tencent company. All rights reserved.
|
|
|
|
* Licensed under the MIT License (the "License"); you may not use this file except in
|
|
* compliance with the License. You may obtain a copy of the License at
|
|
* http://opensource.org/licenses/MIT
|
|
|
|
* Unless required by applicable law or agreed to in writing, software distributed under the License is
|
|
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
|
* either express or implied. See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "qcloud_iot_export.h"
|
|
#include "qcloud_iot_import.h"
|
|
|
|
#define OTA_BUF_LEN (5000)
|
|
|
|
static bool sg_pub_ack = false;
|
|
static int sg_packet_id = 0;
|
|
|
|
void response_message_callback(void *coap_message, void *userContext)
|
|
{
|
|
int ret_code = IOT_COAP_GetMessageCode(coap_message);
|
|
switch (ret_code) {
|
|
case COAP_EVENT_RECEIVE_ACK:
|
|
Log_i("message received ACK, msgid: %d", IOT_COAP_GetMessageId(coap_message));
|
|
break;
|
|
case COAP_EVENT_RECEIVE_RESPCONTENT: {
|
|
char *payload = NULL;
|
|
int payload_len = 0;
|
|
int ret = -1;
|
|
ret = IOT_COAP_GetMessagePayload(coap_message, &payload, &payload_len);
|
|
if (ret == QCLOUD_RET_SUCCESS) {
|
|
Log_i("message received response, content: %s", payload);
|
|
} else {
|
|
Log_e("message received response, content error.");
|
|
}
|
|
}
|
|
|
|
break;
|
|
case COAP_EVENT_UNAUTHORIZED:
|
|
Log_i("coap client auth token expired or invalid, msgid: %d", IOT_COAP_GetMessageId(coap_message));
|
|
break;
|
|
case COAP_EVENT_FORBIDDEN:
|
|
Log_i("coap URI is invalid for this device, msgid: %d", IOT_COAP_GetMessageId(coap_message));
|
|
break;
|
|
case COAP_EVENT_INTERNAL_SERVER_ERROR:
|
|
Log_i("coap server internal error, msgid: %d", IOT_COAP_GetMessageId(coap_message));
|
|
break;
|
|
case COAP_EVENT_ACK_TIMEOUT:
|
|
Log_i("message receive ACK timeout, msgid: %d", IOT_COAP_GetMessageId(coap_message));
|
|
break;
|
|
case COAP_EVENT_SEPRESP_TIMEOUT:
|
|
Log_i("message received ACK but receive response timeout, msgid: %d", IOT_COAP_GetMessageId(coap_message));
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void event_handler(void *pcontext, CoAPEventMessage *message)
|
|
{
|
|
switch (message->event_type) {
|
|
case COAP_EVENT_RECEIVE_ACK:
|
|
if (sg_packet_id == (unsigned)(uintptr_t)message->message) {
|
|
sg_pub_ack = true;
|
|
}
|
|
Log_i("message received ACK, msgid: %d", sg_packet_id);
|
|
break;
|
|
case COAP_EVENT_RECEIVE_RESPCONTENT:
|
|
Log_i("message received response, content: %s", IOT_COAP_GetMessageId(message->message));
|
|
break;
|
|
case COAP_EVENT_UNAUTHORIZED:
|
|
Log_i("coap client auth token expired or invalid, msgid: %d", (unsigned)(uintptr_t)message->message);
|
|
break;
|
|
case COAP_EVENT_FORBIDDEN:
|
|
Log_i("coap URI is invalid for this device, msgid: %d", (unsigned)(uintptr_t)message->message);
|
|
break;
|
|
case COAP_EVENT_INTERNAL_SERVER_ERROR:
|
|
Log_i("coap server internal error, msgid: %d", (unsigned)(uintptr_t)message->message);
|
|
break;
|
|
case COAP_EVENT_ACK_TIMEOUT:
|
|
Log_i("message receive ACK timeout, msgid: %d", (unsigned)(uintptr_t)message->message);
|
|
break;
|
|
case COAP_EVENT_SEPRESP_TIMEOUT:
|
|
Log_i("message received ACK but receive response timeout, msgid: %d",
|
|
(unsigned)(uintptr_t)message->message);
|
|
break;
|
|
default:
|
|
Log_e("unrecogonized event type: %d", message->event_type);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static int _setup_connect_init_params(CoAPInitParams *initParams, DeviceInfo *device_info)
|
|
{
|
|
initParams->product_id = device_info->product_id;
|
|
initParams->device_name = device_info->device_name;
|
|
|
|
#ifdef AUTH_MODE_CERT
|
|
char certs_dir[16] = "certs";
|
|
char current_path[128];
|
|
char *cwd = getcwd(current_path, sizeof(current_path));
|
|
|
|
if (cwd == NULL) {
|
|
Log_e("getcwd return NULL");
|
|
return QCLOUD_ERR_FAILURE;
|
|
}
|
|
|
|
#ifdef WIN32
|
|
HAL_Snprintf(initParams->cert_file, FILE_PATH_MAX_LEN, "%s\\%s\\%s", current_path, certs_dir,
|
|
device_info->dev_cert_file_name);
|
|
HAL_Snprintf(initParams->key_file, FILE_PATH_MAX_LEN, "%s\\%s\\%s", current_path, certs_dir,
|
|
device_info->dev_key_file_name);
|
|
#else
|
|
HAL_Snprintf(initParams->cert_file, FILE_PATH_MAX_LEN, "%s/%s/%s", current_path, certs_dir,
|
|
device_info->dev_cert_file_name);
|
|
HAL_Snprintf(initParams->key_file, FILE_PATH_MAX_LEN, "%s/%s/%s", current_path, certs_dir,
|
|
device_info->dev_key_file_name);
|
|
#endif
|
|
|
|
#else
|
|
initParams->device_secret = device_info->device_secret;
|
|
#endif
|
|
|
|
initParams->command_timeout = QCLOUD_IOT_MQTT_COMMAND_TIMEOUT;
|
|
initParams->event_handle.h_fp = event_handler;
|
|
initParams->max_retry_count = 3;
|
|
|
|
return QCLOUD_RET_SUCCESS;
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
IOT_Log_Set_Level(eLOG_DEBUG);
|
|
int rc;
|
|
|
|
DeviceInfo device_info = {0};
|
|
rc = HAL_GetDevInfo((void *)&device_info);
|
|
if (QCLOUD_RET_SUCCESS != rc) {
|
|
Log_e("get device info failed: %d", rc);
|
|
return rc;
|
|
}
|
|
|
|
CoAPInitParams init_params = DEFAULT_COAPINIT_PARAMS;
|
|
rc = _setup_connect_init_params(&init_params, &device_info);
|
|
if (rc != QCLOUD_RET_SUCCESS) {
|
|
return rc;
|
|
}
|
|
|
|
void *client = IOT_COAP_Construct(&init_params);
|
|
if (client != NULL) {
|
|
Log_i("Cloud Device Construct Success");
|
|
} else {
|
|
Log_e("Cloud Device Construct Failed");
|
|
return QCLOUD_ERR_FAILURE;
|
|
}
|
|
|
|
DeviceInfo *dev_info = IOT_COAP_GetDeviceInfo(client);
|
|
void * h_ota = IOT_OTA_Init(dev_info->product_id, dev_info->device_name, client);
|
|
if (NULL == h_ota) {
|
|
Log_e("initialize OTA failed");
|
|
return QCLOUD_ERR_FAILURE;
|
|
}
|
|
|
|
if (0 > IOT_OTA_ReportVersion(h_ota, "1.0.0")) {
|
|
Log_e("report OTA version failed");
|
|
return QCLOUD_ERR_FAILURE;
|
|
}
|
|
HAL_SleepMs(2000);
|
|
|
|
int ota_over = 0;
|
|
bool upgrade_fetch_success = true;
|
|
FILE *fp;
|
|
char buf_ota[OTA_BUF_LEN];
|
|
if (NULL == (fp = fopen("ota.bin", "wb+"))) {
|
|
Log_e("open file failed");
|
|
return QCLOUD_ERR_FAILURE;
|
|
}
|
|
|
|
do {
|
|
uint32_t firmware_valid;
|
|
Log_i("wait for ota upgrade command...");
|
|
|
|
IOT_COAP_Yield(client, 200);
|
|
|
|
if (IOT_OTA_IsFetching(h_ota)) {
|
|
char version[128], md5sum[33];
|
|
uint32_t len, size_downloaded, size_file;
|
|
do {
|
|
len = IOT_OTA_FetchYield(h_ota, buf_ota, OTA_BUF_LEN, 1);
|
|
if (len > 0) {
|
|
if (1 != fwrite(buf_ota, len, 1, fp)) {
|
|
Log_e("write data to file failed");
|
|
upgrade_fetch_success = false;
|
|
break;
|
|
}
|
|
} else if (len < 0) {
|
|
Log_e("download fail rc=%d", len);
|
|
upgrade_fetch_success = false;
|
|
break;
|
|
}
|
|
|
|
/* get OTA information */
|
|
IOT_OTA_Ioctl(h_ota, IOT_OTAG_FETCHED_SIZE, &size_downloaded, 4);
|
|
IOT_OTA_Ioctl(h_ota, IOT_OTAG_FILE_SIZE, &size_file, 4);
|
|
IOT_OTA_Ioctl(h_ota, IOT_OTAG_MD5SUM, md5sum, 33);
|
|
IOT_OTA_Ioctl(h_ota, IOT_OTAG_VERSION, version, 128);
|
|
|
|
IOT_COAP_Yield(client, 100);
|
|
} while (!IOT_OTA_IsFetchFinish(h_ota));
|
|
|
|
/* Must check MD5 match or not */
|
|
if (upgrade_fetch_success) {
|
|
IOT_OTA_Ioctl(h_ota, IOT_OTAG_CHECK_FIRMWARE, &firmware_valid, 4);
|
|
if (0 == firmware_valid) {
|
|
Log_e("The firmware is invalid");
|
|
upgrade_fetch_success = false;
|
|
} else {
|
|
Log_e("The firmware is valid");
|
|
upgrade_fetch_success = true;
|
|
}
|
|
}
|
|
|
|
ota_over = 1;
|
|
}
|
|
|
|
HAL_SleepMs(2000);
|
|
|
|
} while (!ota_over);
|
|
|
|
if (upgrade_fetch_success) {
|
|
/* begin execute OTA files, should report upgrade begin */
|
|
// sg_packet_id = IOT_OTA_ReportUpgradeBegin(h_ota);
|
|
// if (0 > sg_packet_id) {
|
|
// Log_e("report OTA begin failed error:%d", sg_packet_id);
|
|
// return QCLOUD_ERR_FAILURE;
|
|
// }
|
|
|
|
// while (!sg_pub_ack) {
|
|
// HAL_SleepMs(1000);
|
|
// IOT_COAP_Yield(client, 200);
|
|
// }
|
|
// sg_pub_ack = false;
|
|
|
|
/* if upgrade success */
|
|
/* after execute OTA files, should report upgrade result */
|
|
// sg_packet_id = IOT_OTA_ReportUpgradeSuccess(h_ota, "1.0.1");
|
|
// if (0 > sg_packet_id) {
|
|
// Log_e("report OTA result failed error:%d", sg_packet_id);
|
|
// return QCLOUD_ERR_FAILURE;
|
|
// }
|
|
|
|
// while (!sg_pub_ack) {
|
|
// HAL_SleepMs(1000);
|
|
// IOT_COAP_Yield(client, 200);
|
|
// }
|
|
// sg_pub_ack = false;
|
|
|
|
/* if upgrade fail */
|
|
// sg_packet_id = IOT_OTA_ReportUpgradeFail(h_ota, "1.0.1");
|
|
// if (0 > sg_packet_id) {
|
|
// Log_e("report OTA result failed error:%d", sg_packet_id);
|
|
// return QCLOUD_ERR_FAILURE;
|
|
// }
|
|
// while (!sg_pub_ack) {
|
|
// HAL_SleepMs(1000);
|
|
// IOT_COAP_Yield(client, 200);
|
|
// }
|
|
// sg_pub_ack = false;
|
|
}
|
|
|
|
IOT_OTA_Destroy(h_ota);
|
|
|
|
IOT_COAP_Destroy(&client);
|
|
|
|
return 0;
|
|
}
|