support ota

This commit is contained in:
ethan.du 2021-05-17 13:20:56 +08:00
parent 47401c5a32
commit fdd5dc370a
21 changed files with 1827 additions and 54 deletions

View File

@ -11,6 +11,7 @@ option(ENABLE_LOG_DEBUG "是否打开DEBUG日志输出" OFF)
option(ENABLE_IOT_TRACE "是否打开函数跟踪" OFF) option(ENABLE_IOT_TRACE "是否打开函数跟踪" OFF)
option(ENABLE_FEATURE_MQTT_COMM "是否打开MQTT通道的总开关" ON) option(ENABLE_FEATURE_MQTT_COMM "是否打开MQTT通道的总开关" ON)
option(ENABLE_FEATURE_OTA "是否打开OTA固件升级总开关" ON)
option(ENABLE_FEATURE_AUTH_MODE_DYNAMIC "是否打开设备动态注册" ON) option(ENABLE_FEATURE_AUTH_MODE_DYNAMIC "是否打开设备动态注册" ON)
option(ENABLE_TLS_SUPPORT "是否打开TLS支持" ON) option(ENABLE_TLS_SUPPORT "是否打开TLS支持" ON)
option(ENABLE_SDK_TESTS "是否打开SDK测试用例编译" ON) option(ENABLE_SDK_TESTS "是否打开SDK测试用例编译" ON)
@ -77,6 +78,14 @@ else ()
message("FEATURE_AUTH_MODE_DYNAMIC = n") message("FEATURE_AUTH_MODE_DYNAMIC = n")
endif () endif ()
if (ENABLE_FEATURE_OTA)
message("ENABLE_FEATURE_OTA = y")
include_directories(src/ota/include)
AUX_SOURCE_DIRECTORY(src/ota/src OTA_SRC)
set(src_iot_sdk ${src_iot_sdk} ${OTA_SRC})
else ()
message("ENABLE_FEATURE_OTA = n")
endif ()
if (ENABLE_TLS_SUPPORT) if (ENABLE_TLS_SUPPORT)
message("FEATURE_SUPPORT_TLS = y") message("FEATURE_SUPPORT_TLS = y")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DSUPPORT_TLS") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DSUPPORT_TLS")

View File

@ -11,6 +11,7 @@ COMP_LIB_COMPONENTS := \
$(call CompLib_Map, MQTT_COMM_ENABLED, src/mqtt/src) $(call CompLib_Map, MQTT_COMM_ENABLED, src/mqtt/src)
$(call CompLib_Map, OTA_ENABLED, src/ota/src)
$(call CompLib_Map, SUPPORT_AT_CMD, src/at/src src/at/class/$(PLATFORM_MODULE) platform/module) $(call CompLib_Map, SUPPORT_AT_CMD, src/at/src src/at/class/$(PLATFORM_MODULE) platform/module)
IOTSDK_SRC_FILES := \ IOTSDK_SRC_FILES := \
@ -53,6 +54,9 @@ $(call CompInc_Map, MQTT_COMM_ENABLED, \
src/mqtt/include \ src/mqtt/include \
) )
$(call CompInc_Map, OTA_ENABLED, \
src/ota/include \
)
$(call CompInc_Map, SUPPORT_TLS, \ $(call CompInc_Map, SUPPORT_TLS, \
external_libs/mbedtls/include \ external_libs/mbedtls/include \
) )

View File

@ -15,6 +15,7 @@ PLATFORM_MODULE = m26
# PLATFORM_AR = armar # PLATFORM_AR = armar
FEATURE_MQTT_COMM_ENABLED = y # 是否打开MQTT连接云平台 FEATURE_MQTT_COMM_ENABLED = y # 是否打开MQTT连接云平台
FEATURE_OTA_ENABLED = y # 是否打开OTA固件升级
FEATURE_AUTH_MODE_DYNAMIC = y # 是否打开设备动态注册 FEATURE_AUTH_MODE_DYNAMIC = y # 是否打开设备动态注册
FEATURE_SUPPORT_TLS = y # 是否打开TLS支持 FEATURE_SUPPORT_TLS = y # 是否打开TLS支持
FEATURE_SUPPORT_AT_CMD = n # 是否打开AT命令支持 FEATURE_SUPPORT_AT_CMD = n # 是否打开AT命令支持

View File

@ -25,7 +25,7 @@ static int _utils_parse_name(const char *url, char *name) {
} }
host_ptr += 3; host_ptr += 3;
path_ptr = strchr(host_ptr, '/'); path_ptr = strrchr(host_ptr, '/');
if (NULL == path_ptr) { if (NULL == path_ptr) {
return -2; return -2;
} }
@ -39,6 +39,7 @@ static int _utils_parse_name(const char *url, char *name) {
memcpy(name, path_ptr + 1, name_len - 1); memcpy(name, path_ptr + 1, name_len - 1);
name[name_len] = '\0'; name[name_len] = '\0';
LOG_ERROR("file name:%s",name);
return SUCCESS_RET; return SUCCESS_RET;
} }

View File

@ -5,7 +5,16 @@ if (ENABLE_FEATURE_MQTT_COMM)
add_dependencies(mqtt_sample iot_sdk iot_platform) add_dependencies(mqtt_sample iot_sdk iot_platform)
endif () endif ()
if (ENABLE_FEATURE_OTA)
add_executable(ota_sample ota/ota_sample.c)
add_dependencies(ota_sample iot_sdk iot_platform)
endif ()
if (ENABLE_FEATURE_AUTH_MODE_DYNAMIC) if (ENABLE_FEATURE_AUTH_MODE_DYNAMIC)
add_executable(dynamic_auth_sample dynamic_auth/dynamic_auth_sample.c) add_executable(dynamic_auth_sample dynamic_auth/dynamic_auth_sample.c)
add_dependencies(dynamic_auth_sample iot_sdk iot_platform) add_dependencies(dynamic_auth_sample iot_sdk iot_platform)
endif () endif ()
if (ENABLE_FEATURE_OTA)
add_executable(ota_sample ota/ota_sample.c)
add_dependencies(ota_sample iot_sdk iot_platform)
endif ()

122
samples/ota/ota_sample.c Normal file
View File

@ -0,0 +1,122 @@
/*
* Copyright (C) 2012-2019 UCloud. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* or in the "license" file accompanying this file. This file 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 <unistd.h>
#include <limits.h>
#include <string.h>
#include "uiot_export.h"
#include "uiot_import.h"
#include "uiot_export_ota.h"
#define UIOT_MY_PRODUCT_SN "productSN"
#define UIOT_MY_DEVICE_SN "deviceSN"
#define UIOT_MY_DEVICE_SECRET "device_secret"
#define OTA_BUF_LEN (1024)
static void event_handler(void *pClient, void *handle_context, MQTTEventMsg *msg)
{
switch(msg->event_type) {
case MQTT_EVENT_UNDEF:
LOG_INFO("undefined event occur.\n");
break;
case MQTT_EVENT_DISCONNECT:
LOG_INFO("MQTT disconnect.\n");
break;
case MQTT_EVENT_RECONNECT:
LOG_INFO("MQTT reconnect.\n");
break;
case MQTT_EVENT_SUBSCRIBE_SUCCESS:
LOG_INFO("subscribe success.\n");
break;
case MQTT_EVENT_SUBSCRIBE_TIMEOUT:
LOG_INFO("subscribe wait ack timeout.\n");
break;
case MQTT_EVENT_SUBSCRIBE_NACK:
LOG_INFO("subscribe nack.\n");
break;
case MQTT_EVENT_PUBLISH_SUCCESS:
LOG_INFO("publish success.\n");
break;
case MQTT_EVENT_PUBLISH_TIMEOUT:
LOG_INFO("publish timeout.\n");
break;
case MQTT_EVENT_PUBLISH_NACK:
LOG_INFO("publish nack.\n");
break;
default:
LOG_INFO("Should NOT arrive here.\n");
break;
}
}
static int _setup_connect_init_params(MQTTInitParams* initParams)
{
initParams->device_sn = UIOT_MY_DEVICE_SN;
initParams->product_sn = UIOT_MY_PRODUCT_SN;
initParams->device_secret = UIOT_MY_DEVICE_SECRET;
initParams->command_timeout = UIOT_MQTT_COMMAND_TIMEOUT;
initParams->keep_alive_interval = UIOT_MQTT_KEEP_ALIVE_INTERNAL;
initParams->auto_connect_enable = 1;
initParams->event_handler.h_fp = event_handler;
return SUCCESS_RET;
}
int main(int argc, char **argv)
{
int rc;
MQTTInitParams init_params = DEFAULT_MQTT_INIT_PARAMS;
rc = _setup_connect_init_params(&init_params);
if (rc != SUCCESS_RET) {
return rc;
}
void *client = IOT_MQTT_Construct(&init_params);
if (client != NULL) {
LOG_INFO("MQTT Construct Success");
} else {
LOG_ERROR("MQTT Construct Failed");
return FAILURE_RET;
}
void *h_ota = IOT_OTA_Init(UIOT_MY_PRODUCT_SN, UIOT_MY_DEVICE_SN, client);
if (NULL == h_ota) {
IOT_MQTT_Destroy(&client);
LOG_ERROR("init OTA failed");
return FAILURE_RET;
}
while(1)
{
IOT_MQTT_Yield(client, 5000);
}
}

View File

@ -23,6 +23,15 @@ dynamic_auth_sample:
mv $@ $(FINAL_DIR)/bin mv $@ $(FINAL_DIR)/bin
endif endif
ifneq (,$(filter -DOTA_ENABLED,$(CFLAGS)))
ota_sample:
$(TOP_Q) \
$(PLATFORM_CC) $(CFLAGS) $(SAMPLE_DIR)/ota/$@.c $(LDFLAGS) -o $@
$(TOP_Q) \
mv $@ $(FINAL_DIR)/bin
endif
samples_final: samples_final:
$(TOP_Q) \ $(TOP_Q) \
cp -rf $(TOP_DIR)/src/sdk-impl/*port*.h $(FINAL_DIR)/include/ cp -rf $(TOP_DIR)/src/sdk-impl/*port*.h $(FINAL_DIR)/include/

View File

@ -25,25 +25,68 @@ extern "C" {
static const char *iot_ca_crt = \ static const char *iot_ca_crt = \
{ {
"-----BEGIN CERTIFICATE-----\r\n" "-----BEGIN CERTIFICATE-----\r\n"
"MIIDLDCCAhQCCQCnVOYTQCyIGjANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJD\r\n" "MIIErjCCA5agAwIBAgIQBYAmfwbylVM0jhwYWl7uLjANBgkqhkiG9w0BAQsFADBh\r\n"
"TjELMAkGA1UECAwCU0gxCzAJBgNVBAcMAlNIMQ8wDQYDVQQKDAZVQ0xPVUQxDTAL\r\n" "MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\r\n"
"BgNVBAsMBFBBQVMxDzANBgNVBAMMBlVDTE9VRDAeFw0yMDEyMTYwNTI2MzVaFw00\r\n" "d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD\r\n"
"MDEyMTEwNTI2MzVaMFgxCzAJBgNVBAYTAkNOMQswCQYDVQQIDAJTSDELMAkGA1UE\r\n" "QTAeFw0xNzEyMDgxMjI4MjZaFw0yNzEyMDgxMjI4MjZaMHIxCzAJBgNVBAYTAkNO\r\n"
"BwwCU0gxDzANBgNVBAoMBlVDTE9VRDENMAsGA1UECwwEUEFBUzEPMA0GA1UEAwwG\r\n" "MSUwIwYDVQQKExxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMuMR0wGwYDVQQL\r\n"
"VUNMT1VEMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA312YPHXmEEP/\r\n" "ExREb21haW4gVmFsaWRhdGVkIFNTTDEdMBsGA1UEAxMUVHJ1c3RBc2lhIFRMUyBS\r\n"
"PaPdSB4+jFQGHRE+BbOme5NOOL9AmFi+jxJb/4UHD6WBdl4nb0fOuw2dfbqv4Qrl\r\n" "U0EgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCgWa9X+ph+wAm8\r\n"
"Vh/ZwOQoQdzIZJTHMQNZoOd/5nwa/WPBAldNzWH/IqjFrhCD9tfA0rldH0QTE1s2\r\n" "Yh1Fk1MjKbQ5QwBOOKVaZR/OfCh+F6f93u7vZHGcUU/lvVGgUQnbzJhR1UV2epJa\r\n"
"vQ8WpNi5pyJJMGoBs7q1QY0GqIRJc3iTIqsNADZhNJ4zLRa05nBzXgKQRIz1Rumx\r\n" "e+m7cxnXIKdD0/VS9btAgwJszGFvwoqXeaCqFoP71wPmXjjUwLT70+qvX4hdyYfO\r\n"
"MpRNuKFz4EHLDkRUZCYqw5SmtpaW4ja/sSC4UzGfTEkXmNyN9UrteyvUMPbN6vTz\r\n" "JcjeTz5QKtg8zQwxaK9x4JT9CoOmoVdVhEBAiD3DwR5fFgOHDwwGxdJWVBvktnoA\r\n"
"igymgHyES3ygm+sEHJXFvpvZVfq8anwyNs0uUlHhWcx+MqF93vd+T1RRAq+s0BmK\r\n" "zjdTLXDdbSVC5jZ0u8oq9BiTDv7jAlsB5F8aZgvSZDOQeFrwaOTbKWSEInEhnchK\r\n"
"YobbIrhCuQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQBvvBmgA2IjcKca0mTZ9uvM\r\n" "ZTD1dz6aBlk1xGEI5PZWAnVAba/ofH33ktymaTDsE6xRDnW97pDkimCRak6CEbfe\r\n"
"EyskZMTnywGuYaSu0JrgY063RsoB/p9z86TqYzLxWR0en4S4VuBWERxuaYATHs6f\r\n" "3dXw6OV5AgMBAAGjggFPMIIBSzAdBgNVHQ4EFgQUf9OZ86BHDjEAVlYijrfMnt3K\r\n"
"sKhSq9W9RqRj8PAhjLbLPKbhp6hM/VdpcIgJNrqlmFrAcZvddiozb2U832qp65/M\r\n" "AYowHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDgYDVR0PAQH/BAQD\r\n"
"1m2Tq9i1/NosoIoolirCiK4iEotK0zYsUig1dgRTvSGVbkrmIaFesQGU503dYct/\r\n" "AgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjASBgNVHRMBAf8ECDAG\r\n"
"Uz2jEmg8o36cMk011PcbkcTV6Way2g0zXs5PJu3PsJkFgL9jsBFlF1/6sHRan2V9\r\n" "AQH/AgEAMDQGCCsGAQUFBwEBBCgwJjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3Au\r\n"
"7HFkvgolP7RSYFSJT2Hx1NQ71NoK18lnQpvjn2bZndGOACAadpWKvDAIouaB8v8w\r\n" "ZGlnaWNlcnQuY29tMEIGA1UdHwQ7MDkwN6A1oDOGMWh0dHA6Ly9jcmwzLmRpZ2lj\r\n"
"ZXJ0LmNvbS9EaWdpQ2VydEdsb2JhbFJvb3RDQS5jcmwwTAYDVR0gBEUwQzA3Bglg\r\n"
"hkgBhv1sAQIwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29t\r\n"
"L0NQUzAIBgZngQwBAgEwDQYJKoZIhvcNAQELBQADggEBAK3dVOj5dlv4MzK2i233\r\n"
"lDYvyJ3slFY2X2HKTYGte8nbK6i5/fsDImMYihAkp6VaNY/en8WZ5qcrQPVLuJrJ\r\n"
"DSXT04NnMeZOQDUoj/NHAmdfCBB/h1bZ5OGK6Sf1h5Yx/5wR4f3TUoPgGlnU7EuP\r\n"
"ISLNdMRiDrXntcImDAiRvkh5GJuH4YCVE6XEntqaNIgGkRwxKSgnU3Id3iuFbW9F\r\n"
"UQ9Qqtb1GX91AJ7i4153TikGgYCdwYkBURD8gSVe8OAco6IfZOYt/TEwii1Ivi1C\r\n"
"qnuUlWpsF1LdQNIdfbW3TSe0BhQa7ifbVIfvPWHYOu3rkg1ZeMo6XRU9B4n5VyJY\r\n"
"RmE=\r\n"
"-----END CERTIFICATE-----\r\n"
};
static const char *iot_https_ca_crt = \
{
"-----BEGIN CERTIFICATE-----\r\n"
"MIIErjCCA5agAwIBAgIQBYAmfwbylVM0jhwYWl7uLjANBgkqhkiG9w0BAQsFADBh\r\n"
"MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\r\n"
"d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD\r\n"
"QTAeFw0xNzEyMDgxMjI4MjZaFw0yNzEyMDgxMjI4MjZaMHIxCzAJBgNVBAYTAkNO\r\n"
"MSUwIwYDVQQKExxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMuMR0wGwYDVQQL\r\n"
"ExREb21haW4gVmFsaWRhdGVkIFNTTDEdMBsGA1UEAxMUVHJ1c3RBc2lhIFRMUyBS\r\n"
"U0EgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCgWa9X+ph+wAm8\r\n"
"Yh1Fk1MjKbQ5QwBOOKVaZR/OfCh+F6f93u7vZHGcUU/lvVGgUQnbzJhR1UV2epJa\r\n"
"e+m7cxnXIKdD0/VS9btAgwJszGFvwoqXeaCqFoP71wPmXjjUwLT70+qvX4hdyYfO\r\n"
"JcjeTz5QKtg8zQwxaK9x4JT9CoOmoVdVhEBAiD3DwR5fFgOHDwwGxdJWVBvktnoA\r\n"
"zjdTLXDdbSVC5jZ0u8oq9BiTDv7jAlsB5F8aZgvSZDOQeFrwaOTbKWSEInEhnchK\r\n"
"ZTD1dz6aBlk1xGEI5PZWAnVAba/ofH33ktymaTDsE6xRDnW97pDkimCRak6CEbfe\r\n"
"3dXw6OV5AgMBAAGjggFPMIIBSzAdBgNVHQ4EFgQUf9OZ86BHDjEAVlYijrfMnt3K\r\n"
"AYowHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDgYDVR0PAQH/BAQD\r\n"
"AgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjASBgNVHRMBAf8ECDAG\r\n"
"AQH/AgEAMDQGCCsGAQUFBwEBBCgwJjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3Au\r\n"
"ZGlnaWNlcnQuY29tMEIGA1UdHwQ7MDkwN6A1oDOGMWh0dHA6Ly9jcmwzLmRpZ2lj\r\n"
"ZXJ0LmNvbS9EaWdpQ2VydEdsb2JhbFJvb3RDQS5jcmwwTAYDVR0gBEUwQzA3Bglg\r\n"
"hkgBhv1sAQIwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29t\r\n"
"L0NQUzAIBgZngQwBAgEwDQYJKoZIhvcNAQELBQADggEBAK3dVOj5dlv4MzK2i233\r\n"
"lDYvyJ3slFY2X2HKTYGte8nbK6i5/fsDImMYihAkp6VaNY/en8WZ5qcrQPVLuJrJ\r\n"
"DSXT04NnMeZOQDUoj/NHAmdfCBB/h1bZ5OGK6Sf1h5Yx/5wR4f3TUoPgGlnU7EuP\r\n"
"ISLNdMRiDrXntcImDAiRvkh5GJuH4YCVE6XEntqaNIgGkRwxKSgnU3Id3iuFbW9F\r\n"
"UQ9Qqtb1GX91AJ7i4153TikGgYCdwYkBURD8gSVe8OAco6IfZOYt/TEwii1Ivi1C\r\n"
"qnuUlWpsF1LdQNIdfbW3TSe0BhQa7ifbVIfvPWHYOu3rkg1ZeMo6XRU9B4n5VyJY\r\n"
"RmE=\r\n"
"-----END CERTIFICATE-----\r\n" "-----END CERTIFICATE-----\r\n"
}; };
#endif #endif
const char *iot_ca_get() { const char *iot_ca_get() {
@ -54,6 +97,15 @@ const char *iot_ca_get() {
#endif #endif
} }
const char *iot_https_ca_get() {
#ifdef SUPPORT_TLS
return iot_https_ca_crt;
#else
return NULL;
#endif
}
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -21,6 +21,7 @@ extern "C" {
#endif #endif
const char *iot_ca_get(void); const char *iot_ca_get(void);
const char *iot_https_ca_get();
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -0,0 +1,50 @@
/*
* Copyright (C) 2012-2019 UCloud. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* or in the "license" file accompanying this file. This file 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.
*/
#ifndef C_SDK_OTA_CONFIG_H_
#define C_SDK_OTA_CONFIG_H_
#ifdef __cplusplus
extern "C" {
#endif
#define TYPE_FIELD "Method"
#define MD5_FIELD "Payload.MD5"
#define MODULE_FIELD "Payload.Module"
#define VERSION_FIELD "Payload.Version"
#define CURRENT_VERSION_FIELD "Payload.CurrentVersion"
#define URL_FIELD "Payload.URL"
#define SIZE_FIELD "Payload.Size"
#define TASKID_FILED "Payload.TaskID"
#define NOTIFY_METHOD "notify"
#define REPORT_VER_TEMPLATE "{\"Method\": \"report\", \"Payload\":{\"Module\":\"%s\", \"Version\":\"%s\"}}"
#define REPORT_SUCCESS_MSG_TEMPLATE "{\"Method\": \"success\", \"Payload\": {\"TaskID\": \"%s\"}}"
#define REPORT_FAIL_MSG_TEMPLATE "{\"Method\": \"fail\", \"Payload\": {\"TaskID\": %d, \"ErrMsg\":\"%s\"}}"
#define NOTIFY_MSG_TEMPLATE "{\"Method\": \"notify\", \"Payload\":{\"TaskID\":%d}}"
#define UPGRADING_MSG_TEMPLATE "{\"Method\": \"upgrading\", \"Payload\":{\"TaskID\":%d}}"
#define OTA_UPSTREAM_MSG_BUF_LEN (129)
#define OTA_TOPIC_BUF_LEN (129)
#define OTA_UPSTREAM_TOPIC_TYPE "upstream"
#define OTA_DOWNSTREAM_TOPIC_TYPE "downstream"
#define OTA_TOPIC_TEMPLATE "/$system/%s/%s/ota/%s"
#ifdef __cplusplus
}
#endif
#endif //C_SDK_OTA_CONFIG_H_

View File

@ -0,0 +1,96 @@
/*
* Copyright (C) 2012-2019 UCloud. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* or in the "license" file accompanying this file. This file 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.
*/
#ifndef C_SDK_OTA_INTERNAL_H_
#define C_SDK_OTA_INTERNAL_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include "ota_config.h"
#include "uiot_export_ota.h"
#include "utils_httpc.h"
#include "utils_list.h"
// OTA Signal Channel
typedef void (*OnOTAMessageCallback)(void *pContext, const char *msg, uint32_t msgLen);
typedef struct{
char *payload; // MQTT 消息负载
size_t payload_len; // MQTT 消息负载长度
}OTA_UPLOAD_Msg;
typedef struct {
const char *url;
http_client_t http; /* http client */
http_client_data_t http_data; /* http client data */
} OTA_Http_Client;
void *osc_init(const char *product_sn, const char *device_sn, void *channel, OnOTAMessageCallback callback,
void *context);
/* OSC, OTA signal channel */
typedef struct {
void *mqtt;
const char *product_sn;
const char *device_sn;
char topic_upgrade[OTA_TOPIC_BUF_LEN];
OnOTAMessageCallback msg_callback;
List *msg_list; /* recv update msg */
void *msg_mutex; /* mutex for msg list */
void *context;
} OTA_MQTT_Struct_t;
int osc_deinit(void *handle);
int osc_report_progress(void *handle, const char *msg);
int osc_upstream_publish(void *handle, const char *msg);
// OTA Fetch Channel
void *ofc_init(const char *url);
int32_t ofc_connect(void *handle);
int32_t ofc_fetch(void *handle, uint32_t size_fetched, char *buf, uint32_t buf_len, size_t range_len, uint32_t timeout_s);
int ofc_deinit(void *handle);
// ota_lib
void *ota_lib_md5_init(void);
void ota_lib_md5_update(void *md5, const char *buf, size_t buf_len);
void ota_lib_md5_finalize(void *md5, char *output_str);
void ota_lib_md5_deinit(void *md5);
int ota_lib_get_msg_type(char *json, char **type);
int ota_lib_get_params(char *json, char **url, char **module, char **download_name, char **version, char **current_version, char **md5,
char **taskID, uint32_t *fileSize);
int ota_lib_gen_upstream_msg(char *buf, size_t bufLen, const char *module, const char *version, char *taskID,
IOT_OTA_UpstreamMsgType reportType);
#ifdef __cplusplus
}
#endif
#endif //C_SDK_OTA_INTERNAL_H_

700
src/ota/src/ota_client.c Normal file
View File

@ -0,0 +1,700 @@
/*
* Copyright (C) 2012-2019 UCloud. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* or in the "license" file accompanying this file. This file 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 "uiot_defs.h"
#include "uiot_export_ota.h"
#include "uiot_internal.h"
#include "ota_config.h"
#include "ota_internal.h"
#include "utils_timer.h"
#define HTTP_OTA_BUFF_LEN 1024
/* http slice len config HTTP_OTA_BUFF_LEN > HTTP_OTA_RANGE_LEN*/
#define HTTP_OTA_RANGE_LEN 1000
static void print_progress(uint32_t percent)
{
static unsigned char progress_sign[100 + 1];
uint8_t i;
if (percent > 100)
{
percent = 100;
}
for (i = 0; i < 100; i++)
{
if (i < percent)
{
progress_sign[i] = '=';
}
else if (percent == i)
{
progress_sign[i] = '>';
}
else
{
progress_sign[i] = ' ';
}
}
progress_sign[sizeof(progress_sign) - 1] = '\0';
LOG_INFO("Download: [%s] %d%%\r\n", progress_sign, percent);
}
static int send_upstream_msg_with_version(void *handle, const char *module, const char *version, char *taskID, IOT_OTA_UpstreamMsgType reportType)
{
POINTER_VALID_CHECK(handle, ERR_OTA_INVALID_PARAM);
int ret;
char *msg_upstream;
OTA_Struct_t *h_ota = (OTA_Struct_t *)handle;
if (OTA_STATE_UNINITED == h_ota->state) {
LOG_ERROR("handle is uninitialized");
h_ota->err = ERR_OTA_INVALID_STATE;
return ERR_OTA_INVALID_STATE;
}
if (NULL == (msg_upstream = HAL_Malloc(OTA_UPSTREAM_MSG_BUF_LEN))) {
LOG_ERROR("allocate for msg_informed failed");
h_ota->err = ERR_OTA_NO_MEMORY;
return ERR_OTA_NO_MEMORY;
}
ret = ota_lib_gen_upstream_msg(msg_upstream, OTA_UPSTREAM_MSG_BUF_LEN, module, version, taskID, reportType);
if (SUCCESS_RET != ret) {
LOG_ERROR("generate upstream message failed");
h_ota->err = ret;
goto do_exit;
}
ret = osc_upstream_publish(h_ota->ch_signal, msg_upstream);
if (ret < 0) {
LOG_ERROR("Report result failed");
h_ota->err = ret;
goto do_exit;
}
do_exit:
if (NULL != msg_upstream) {
HAL_Free(msg_upstream);
}
return ret;
}
static void _ota_push_upload_msg(void *handle, const char *msg, uint32_t msg_len)
{
OTA_Struct_t *h_ota = (OTA_Struct_t *) handle;
OTA_MQTT_Struct_t *h_osc = h_ota->ch_signal;
OTA_UPLOAD_Msg *push_msg = (OTA_UPLOAD_Msg *)HAL_Malloc(sizeof(OTA_UPLOAD_Msg));
if (NULL == (push_msg->payload = HAL_Malloc(msg_len + 1))) {
LOG_ERROR("HAL_Malloc failed!");
return;
}
HAL_Snprintf(push_msg->payload, msg_len + 1, "%s", msg);
push_msg->payload_len = msg_len;
ListNode *node = list_node_new((void *)push_msg);
if (NULL == node)
{
LOG_ERROR("run list_node_new is error!\n");
HAL_Free(push_msg->payload);
HAL_Free(push_msg);
return;
}
HAL_MutexLock(h_osc->msg_mutex);
list_rpush(h_osc->msg_list, node);
HAL_MutexUnlock(h_osc->msg_mutex);
return;
}
static void _ota_pop_upload_msg(void *handle)
{
OTA_Struct_t *h_ota = (OTA_Struct_t *) handle;
OTA_MQTT_Struct_t *h_osc = h_ota->ch_signal;
if(h_osc->msg_list->len > 0)
{
HAL_MutexLock(h_osc->msg_mutex);
ListNode *node = list_lpop(h_osc->msg_list);
HAL_MutexUnlock(h_osc->msg_mutex);
OTA_UPLOAD_Msg *pop_msg = node->val;
h_osc->msg_callback(h_ota, pop_msg->payload, pop_msg->payload_len);
HAL_Free(pop_msg->payload);
HAL_Free(pop_msg);
HAL_Free(node);
return;
}
return;
}
static void _ota_callback(void *pContext, const char *msg, uint32_t msg_len)
{
char *msg_method = NULL;
char *msg_str = NULL;
OTA_Struct_t *h_ota = (OTA_Struct_t *) pContext;
if (h_ota == NULL || msg == NULL) {
LOG_ERROR("pointer is NULL");
return;
}
if (NULL == (msg_str = HAL_Malloc(msg_len + 1))) {
LOG_ERROR("HAL_Malloc failed!");
return;
}
HAL_Snprintf(msg_str, msg_len + 1, "%s", msg);
if (SUCCESS_RET != ota_lib_get_msg_type(msg_str, &msg_method)) {
LOG_ERROR("Get message type failed!");
goto do_exit;
}
if (0 == strcmp(msg_method, NOTIFY_METHOD))
{
/* downloading, push update msg to list */
if (h_ota->state == OTA_STATE_FETCHING) {
LOG_INFO("In OTA_STATE_FETCHING state");
_ota_push_upload_msg(h_ota, msg_str, msg_len);
goto do_exit;
}
if (SUCCESS_RET != ota_lib_get_params(msg_str, &h_ota->url, &h_ota->module, &h_ota->download_name,
&h_ota->version, &h_ota->current_version, &h_ota->md5sum, &h_ota->taskID, &h_ota->size_file)) {
LOG_ERROR("Get firmware parameter failed");
goto do_exit;
}
/* received updating msg */
send_upstream_msg_with_version(h_ota, "", "", h_ota->taskID, OTA_REPORT_START);
if (NULL == (h_ota->ch_fetch = ofc_init(h_ota->url))) {
LOG_ERROR("Initialize fetch module failed");
goto do_exit;
}
if (SUCCESS_RET != ofc_connect(h_ota->ch_fetch)) {
LOG_ERROR("Connect fetch module failed");
h_ota->state = OTA_STATE_DISCONNECTED;
goto do_exit;
}
h_ota->state = OTA_STATE_FETCHING;
if(SUCCESS_RET != IOT_OTA_fw_download(h_ota)) {
LOG_ERROR("download file failed");
h_ota->state = OTA_STATE_DISCONNECTED;
}
/* download over, pop first pushed msg to download */
_ota_pop_upload_msg(h_ota);
}
do_exit:
HAL_Free(msg_str);
HAL_Free(msg_method);
return;
}
void *IOT_OTA_Init(const char *product_sn, const char *device_sn, void *ch_signal)
{
POINTER_VALID_CHECK(product_sn, NULL);
POINTER_VALID_CHECK(device_sn, NULL);
POINTER_VALID_CHECK(ch_signal, NULL);
OTA_Struct_t *h_ota = NULL;
if (NULL == (h_ota = HAL_Malloc(sizeof(OTA_Struct_t)))) {
LOG_ERROR("allocate failed");
return NULL;
}
memset(h_ota, 0, sizeof(OTA_Struct_t));
h_ota->state = OTA_STATE_UNINITED;
h_ota->ch_signal = osc_init(product_sn, device_sn, ch_signal, _ota_callback, h_ota);
if (NULL == h_ota->ch_signal) {
LOG_ERROR("initialize signal channel failed");
goto do_exit;
}
h_ota->md5 = ota_lib_md5_init();
if (NULL == h_ota->md5) {
LOG_ERROR("initialize md5 failed");
goto do_exit;
}
h_ota->state = OTA_STATE_INITED;
return h_ota;
do_exit:
if (NULL != h_ota->ch_signal) {
osc_deinit(h_ota->ch_signal);
}
if (NULL != h_ota->md5) {
ota_lib_md5_deinit(h_ota->md5);
}
if (NULL != h_ota) {
HAL_Free(h_ota);
}
return NULL;
}
int IOT_OTA_Destroy(void *handle)
{
POINTER_VALID_CHECK(handle, ERR_OTA_INVALID_PARAM);
OTA_Struct_t *h_ota = (OTA_Struct_t*) handle;
if (OTA_STATE_UNINITED == h_ota->state) {
LOG_ERROR("handle is uninitialized");
return FAILURE_RET;
}
osc_deinit(h_ota->ch_signal);
ofc_deinit(h_ota->ch_fetch);
ota_lib_md5_deinit(h_ota->md5);
if (NULL != h_ota->url) {
HAL_Free(h_ota->url);
}
if (NULL != h_ota->module) {
HAL_Free(h_ota->module);
}
if (NULL != h_ota->version) {
HAL_Free(h_ota->version);
}
if (NULL != h_ota->md5sum) {
HAL_Free(h_ota->md5sum);
}
if (NULL != h_ota->download_name) {
HAL_Free(h_ota->download_name);
}
HAL_Free(h_ota);
return SUCCESS_RET;
}
void IOT_OTA_Clear(void *handle)
{
OTA_Struct_t *h_ota = (OTA_Struct_t *)handle;
ofc_deinit(h_ota->ch_fetch);
if (NULL != h_ota->url) {
memset(h_ota->url, 0, strlen(h_ota->url));
}
if (NULL != h_ota->module) {
memset(h_ota->module, 0, strlen(h_ota->module));
}
if(NULL != h_ota->download_name){
memset(h_ota->download_name, 0, strlen(h_ota->download_name));
}
if (NULL != h_ota->version) {
memset(h_ota->version, 0, strlen(h_ota->version));
}
if (NULL != h_ota->md5sum) {
memset(h_ota->md5sum, 0, strlen(h_ota->md5sum));
}
h_ota->size_last_fetched = 0;
h_ota->size_fetched = 0;
h_ota->size_file = 0;
ota_lib_md5_deinit(h_ota->md5);
h_ota->md5 = ota_lib_md5_init();
h_ota->state = OTA_STATE_INITED;
return;
}
int IOT_OTA_ReportVersion(void *handle, const char *module, const char *version)
{
return send_upstream_msg_with_version(handle, module, version, 0, OTA_REPORT_VERSION);
}
int IOT_OTA_ReportSuccess(void *handle)
{
OTA_Struct_t *h_ota = (OTA_Struct_t *)handle;
if(h_ota->fetch_callback_func != NULL)
{
h_ota->fetch_callback_func(handle, OTA_REPORT_SUCCESS);
}
h_ota->current_version = h_ota->version;
return send_upstream_msg_with_version(handle, "", "", h_ota->taskID, OTA_REPORT_SUCCESS);
}
int IOT_OTA_ReportUpgrading(void *handle)
{
OTA_Struct_t *h_ota = (OTA_Struct_t *)handle;
return send_upstream_msg_with_version(handle, "", "", h_ota->taskID, OTA_REPORT_UPGRADING);
}
int IOT_OTA_ReportFail(void *handle, IOT_OTA_ReportErrCode err_code)
{
POINTER_VALID_CHECK(handle, ERR_OTA_INVALID_PARAM);
int ret;
char *msg_upstream;
OTA_Struct_t *h_ota = (OTA_Struct_t *)handle;
if (OTA_STATE_UNINITED == h_ota->state) {
LOG_ERROR("handle is uninitialized");
h_ota->err = ERR_OTA_INVALID_STATE;
return ERR_OTA_INVALID_STATE;
}
if (NULL == (msg_upstream = HAL_Malloc(OTA_UPSTREAM_MSG_BUF_LEN))) {
LOG_ERROR("allocate for msg_informed failed");
h_ota->err = ERR_OTA_NO_MEMORY;
return ERR_OTA_NO_MEMORY;
}
ret = ota_lib_gen_upstream_msg(msg_upstream, OTA_UPSTREAM_MSG_BUF_LEN, "", "", h_ota->taskID, (IOT_OTA_UpstreamMsgType)err_code);
if (SUCCESS_RET != ret) {
LOG_ERROR("generate upstream message failed");
h_ota->err = ret;
goto do_exit;
}
ret = osc_upstream_publish(h_ota->ch_signal, msg_upstream);
if (ret < 0) {
LOG_ERROR("Report result failed");
h_ota->err = ret;
goto do_exit;
}
if(h_ota->fetch_callback_func != NULL)
h_ota->fetch_callback_func(handle, (IOT_OTA_UpstreamMsgType)err_code);
do_exit:
if (NULL != msg_upstream) {
HAL_Free(msg_upstream);
}
return ret;
}
int IOT_OTA_IsFetching(void *handle)
{
OTA_Struct_t *h_ota = (OTA_Struct_t *)handle;
if (NULL == handle) {
LOG_ERROR("handle is NULL");
return 0;
}
if (OTA_STATE_UNINITED == h_ota->state) {
LOG_ERROR("handle is uninitialized");
h_ota->err = ERR_OTA_INVALID_STATE;
return 0;
}
return (OTA_STATE_FETCHING == h_ota->state);
}
int IOT_OTA_IsFetchFinish(void *handle)
{
OTA_Struct_t *h_ota = (OTA_Struct_t *) handle;
if (NULL == handle) {
LOG_ERROR("handle is NULL");
return 0;
}
if (OTA_STATE_UNINITED == h_ota->state) {
LOG_ERROR("handle is uninitialized");
h_ota->err = ERR_OTA_INVALID_STATE;
return 0;
}
return (OTA_STATE_FETCHED == h_ota->state);
}
int IOT_OTA_Yield(void *handle, uint32_t timeout_ms)
{
POINTER_VALID_CHECK(handle, FAILURE_RET);
OTA_Struct_t *h_ota = (OTA_Struct_t*) handle;
return IOT_MQTT_Yield(((OTA_MQTT_Struct_t *)h_ota->ch_signal)->mqtt, timeout_ms);
}
int IOT_OTA_FetchYield(void *handle, char *buf, size_t buf_len, size_t range_len, uint32_t timeout_s)
{
int ret;
OTA_Struct_t *h_ota = (OTA_Struct_t *) handle;
int retry_time = 0;
POINTER_VALID_CHECK(handle, ERR_OTA_INVALID_PARAM);
POINTER_VALID_CHECK(buf, ERR_OTA_INVALID_PARAM);
NUMERIC_VALID_CHECK(buf_len, ERR_OTA_INVALID_PARAM);
if (OTA_STATE_FETCHING != h_ota->state) {
h_ota->err = ERR_OTA_INVALID_STATE;
return ERR_OTA_INVALID_STATE;
}
for(retry_time = 0; retry_time < 5; retry_time++)
{
/* fetch fail,try again utill 5 time */
ret = ofc_fetch(h_ota->ch_fetch, h_ota->size_fetched ,buf, buf_len, range_len, timeout_s);
/* range download send request too often maybe cutdown by server, need reconnect and continue to download. */
if((ret == ERR_HTTP_CONN_ERROR) && (h_ota->state != OTA_STATE_DISCONNECTED)) {
ofc_deinit(h_ota->ch_fetch);
h_ota->ch_fetch = ofc_init(h_ota->url);
ofc_connect(h_ota->ch_fetch);
h_ota->state = OTA_STATE_FETCHING;
continue;
}
if (ret < 0) {
LOG_ERROR("Fetch firmware failed");
h_ota->state = OTA_STATE_FETCHED;
h_ota->err = ret;
if (ret == ERR_OTA_FETCH_AUTH_FAIL) { // 上报签名过期
IOT_OTA_ReportFail(h_ota, OTA_ERRCODE_SIGNATURE_EXPIRED);
} else if (ret == ERR_OTA_FILE_NOT_EXIST) { // 上报文件不存在
IOT_OTA_ReportFail(h_ota, OTA_ERRCODE_FIRMWARE_NOT_EXIST);
} else if (ret == ERR_OTA_FETCH_TIMEOUT) { // 上报下载超时
IOT_OTA_ReportFail(h_ota, OTA_ERRCODE_DOWNLOAD_TIMEOUT);
} else {
h_ota->err = ERR_OTA_FETCH_FAILED;
}
HAL_SleepMs(1000);
} else{
break;
}
}
if (ret > 0) {
ota_lib_md5_update(h_ota->md5, buf, ret);
h_ota->size_last_fetched = ret;
h_ota->size_fetched += ret;
}
else
{
return ret;
}
/* report percent every second. */
uint32_t percent = (h_ota->size_fetched * 100) / h_ota->size_file;
print_progress(percent);
if (h_ota->size_fetched >= h_ota->size_file) {
h_ota->state = OTA_STATE_FETCHED;
}
return ret;
}
int IOT_OTA_Ioctl(void *handle, IOT_OTA_CmdType type, void *buf, size_t buf_len)
{
OTA_Struct_t * h_ota = (OTA_Struct_t *) handle;
POINTER_VALID_CHECK(handle, ERR_OTA_INVALID_PARAM);
POINTER_VALID_CHECK(buf, ERR_OTA_INVALID_PARAM);
NUMERIC_VALID_CHECK(buf_len, ERR_OTA_INVALID_PARAM);
if (h_ota->state < OTA_STATE_FETCHING) {
h_ota->err = ERR_OTA_INVALID_STATE;
return ERR_OTA_INVALID_STATE;
}
switch (type) {
case OTA_IOCTL_FETCHED_SIZE:
if ((4 != buf_len) || (0 != ((unsigned long)buf & 0x3))) {
LOG_ERROR("Invalid parameter");
h_ota->err = ERR_OTA_INVALID_PARAM;
return FAILURE_RET;
} else {
*((uint32_t *)buf) = h_ota->size_fetched;
return SUCCESS_RET;
}
case OTA_IOCTL_FILE_SIZE:
if ((4 != buf_len) || (0 != ((unsigned long)buf & 0x3))) {
LOG_ERROR("Invalid parameter");
h_ota->err = ERR_OTA_INVALID_PARAM;
return FAILURE_RET;
} else {
*((uint32_t *)buf) = h_ota->size_file;
return SUCCESS_RET;
}
case OTA_IOCTL_VERSION:
strncpy(buf, h_ota->version, buf_len);
((char *)buf)[buf_len - 1] = '\0';
break;
case OTA_IOCTL_MD5SUM:
strncpy(buf, h_ota->md5sum, buf_len);
((char *)buf)[buf_len - 1] = '\0';
break;
case OTA_IOCTL_CHECK_FIRMWARE:
if ((4 != buf_len) || (0 != ((unsigned long)buf & 0x3))) {
LOG_ERROR("Invalid parameter");
h_ota->err = ERR_OTA_INVALID_PARAM;
return FAILURE_RET;
} else if (h_ota->state != OTA_STATE_FETCHED) {
h_ota->err = ERR_OTA_INVALID_STATE;
LOG_ERROR("Firmware can be checked in OTA_STATE_FETCHED state only");
return FAILURE_RET;
} else {
char md5_str[33];
ota_lib_md5_finalize(h_ota->md5, md5_str);
LOG_DEBUG("origin=%s, now=%s", h_ota->md5sum, md5_str);
if (0 == strcmp(h_ota->md5sum, md5_str)) {
*((uint32_t *)buf) = 1;
} else {
*((uint32_t *)buf) = 0;
// 上报MD5不匹配
h_ota->err = ERR_OTA_MD5_MISMATCH;
IOT_OTA_ReportFail(h_ota, OTA_ERRCODE_MD5_MISMATCH);
}
return SUCCESS_RET;
}
default:
LOG_ERROR("invalid cmd type");
h_ota->err = ERR_OTA_INVALID_PARAM;
return FAILURE_RET;
}
return SUCCESS_RET;
}
int IOT_OTA_GetLastError(void *handle)
{
OTA_Struct_t * h_ota = (OTA_Struct_t *) handle;
if (NULL == handle) {
LOG_ERROR("handle is NULL");
return ERR_OTA_INVALID_PARAM;
}
return h_ota->err;
}
int IOT_OTA_fw_download(void *handle)
{
int ret = 0;
int file_size = 0, length, firmware_valid, total_length = 0;
char *buffer_read = NULL;
OTA_Struct_t * h_ota = (OTA_Struct_t *) handle;
void * download_handle = NULL;
IOT_OTA_Ioctl(h_ota, OTA_IOCTL_FILE_SIZE, &file_size, 4);
download_handle = HAL_Download_Init(h_ota->download_name);
if(download_handle == NULL)
{
ret = FAILURE_RET;
goto __exit;
}
buffer_read = (char *)HAL_Malloc(HTTP_OTA_BUFF_LEN);
if (buffer_read == NULL)
{
LOG_ERROR("No memory for http ota!");
ret = FAILURE_RET;
goto __exit;
}
memset(buffer_read, 0x00, HTTP_OTA_BUFF_LEN);
IOT_OTA_ReportUpgrading(h_ota);
LOG_INFO("OTA file size is (%d)", file_size);
do
{
length = IOT_OTA_FetchYield(h_ota, buffer_read, HTTP_OTA_BUFF_LEN, HTTP_OTA_RANGE_LEN, 10);
if (length > 0)
{
/* Write the data to the corresponding partition address */
if(HAL_Download_Write(download_handle, total_length, buffer_read, length) == FAILURE_RET){
ret = FAILURE_RET;
goto __exit;
}
total_length += length;
//wait cancel cmd
IOT_OTA_Yield(handle, 100);
}
else
{
LOG_ERROR("Exit: server return err (%d)!", length);
ret = ERR_OTA_FETCH_FAILED;
goto __exit;
}
} while (!IOT_OTA_IsFetchFinish(h_ota));
if (total_length == file_size)
{
ret = SUCCESS_RET;
IOT_OTA_Ioctl(h_ota, OTA_IOCTL_CHECK_FIRMWARE, &firmware_valid, 4);
if (0 == firmware_valid) {
LOG_ERROR("The firmware is invalid");
ret = IOT_OTA_GetLastError(h_ota);
goto __exit;
} else {
LOG_INFO("The firmware is valid");
IOT_OTA_ReportSuccess(h_ota);
}
if(HAL_Download_End(download_handle))
ret = FAILURE_RET;
LOG_INFO("Download firmware to flash success.");
}
__exit:
if (buffer_read != NULL)
HAL_Free(buffer_read);
IOT_OTA_Clear(h_ota);
return ret;
}

119
src/ota/src/ota_fetch.c Normal file
View File

@ -0,0 +1,119 @@
/*
* Copyright (C) 2012-2019 UCloud. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* or in the "license" file accompanying this file. This file 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 <string.h>
#include "uiot_export_ota.h"
#include "uiot_import.h"
#include "ota_internal.h"
#include "ca.h"
#include "utils_httpc.h"
void *ofc_init(const char *url)
{
FUNC_ENTRY;
OTA_Http_Client *h_ofc;
if (NULL == (h_ofc = HAL_Malloc(sizeof(OTA_Http_Client)))) {
LOG_ERROR("allocate for h_odc failed");
FUNC_EXIT_RC(NULL);
}
memset(h_ofc, 0, sizeof(OTA_Http_Client));
/* set http request-header parameter */
h_ofc->http.header = "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" \
"Accept-Encoding: gzip, deflate\r\n";
h_ofc->url = url;
FUNC_EXIT_RC(h_ofc);
}
int32_t ofc_connect(void *handle)
{
FUNC_ENTRY;
OTA_Http_Client * h_ofc = (OTA_Http_Client *)handle;
#ifdef SUPPORT_TLS
const char *ca_crt = iot_https_ca_get();
#else
const char *ca_crt = NULL;
#endif
int32_t rc = http_client_connect(&h_ofc->http, h_ofc->url, ca_crt);
FUNC_EXIT_RC(rc);
}
int32_t ofc_fetch(void *handle, uint32_t size_fetched, char *buf, uint32_t buf_len, size_t range_len, uint32_t timeout_s)
{
FUNC_ENTRY;
int diff;
OTA_Http_Client * h_ofc = (OTA_Http_Client *)handle;
/* 分片请求 */
int rc = _http_send_request(&h_ofc->http, h_ofc->url, HTTP_GET, size_fetched, range_len, &h_ofc->http_data, 5000);
if (rc != SUCCESS_RET) {
LOG_ERROR("http_send_request error, rc = %d, size_fetched = %d\r\n", rc, size_fetched);
FUNC_EXIT_RC(rc);
}
#ifdef SUPPORT_AT_CMD
/* wait at module recv data */
HAL_SleepMs(5000);
#endif
h_ofc->http_data.response_buf = buf;
h_ofc->http_data.response_buf_len = buf_len;
h_ofc->http_data.response_content_len = 0;
h_ofc->http_data.response_received_len = 0;
diff = h_ofc->http_data.response_content_len - h_ofc->http_data.retrieve_len;
rc = http_client_recv_data(&h_ofc->http, timeout_s * 1000, &h_ofc->http_data);
if (SUCCESS_RET != rc) {
if (rc == ERR_HTTP_NOT_FOUND)
FUNC_EXIT_RC(ERR_OTA_FILE_NOT_EXIST);
if (rc == ERR_HTTP_AUTH_ERROR)
FUNC_EXIT_RC(ERR_OTA_FETCH_AUTH_FAIL);
if (rc == ERR_HTTP_TIMEOUT)
FUNC_EXIT_RC(ERR_OTA_FETCH_TIMEOUT);
FUNC_EXIT_RC(rc);
}
FUNC_EXIT_RC(h_ofc->http_data.response_content_len - h_ofc->http_data.retrieve_len - diff);
}
int ofc_deinit(void *handle)
{
FUNC_ENTRY;
OTA_Http_Client *h_ofc = (OTA_Http_Client *)handle;
http_client_close(&h_ofc->http);
if (NULL != handle) {
HAL_Free(handle);
}
FUNC_EXIT_RC(SUCCESS_RET);
}

201
src/ota/src/ota_lib.c Normal file
View File

@ -0,0 +1,201 @@
/*
* Copyright (C) 2012-2019 UCloud. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* or in the "license" file accompanying this file. This file 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 <string.h>
#include <stdio.h>
#include "ota_config.h"
#include "ota_internal.h"
#include "utils_md5.h"
#include "lite-utils.h"
void *ota_lib_md5_init(void) {
iot_md5_context *ctx = HAL_Malloc(sizeof(iot_md5_context));
if (NULL == ctx) {
return NULL;
}
utils_md5_init(ctx);
utils_md5_starts(ctx);
return ctx;
}
void ota_lib_md5_update(void *md5, const char *buf, size_t buf_len) {
utils_md5_update(md5, (unsigned char *) buf, buf_len);
}
void ota_lib_md5_finalize(void *md5, char *output_str) {
utils_md5_finish_hb2hex(md5, output_str);
}
void ota_lib_md5_deinit(void *md5) {
if (NULL != md5) {
HAL_Free(md5);
}
}
int ota_lib_get_msg_type(char *json, char **type) {
FUNC_ENTRY;
if (NULL == (*type = LITE_json_value_of(TYPE_FIELD, json))) {
LOG_ERROR("get value of type key failed");
FUNC_EXIT_RC(ERR_OTA_GENERAL_FAILURE);
}
FUNC_EXIT_RC(SUCCESS_RET);
}
int ota_lib_get_params(char *json, char **url, char **module, char **download_name, char **version, char **current_version, char **md5, char **taskID,
uint32_t *fileSize) {
FUNC_ENTRY;
char *module_str;
char *file_size_str;
char *version_str;
char *current_version_str;
char *url_str;
char *md5_str;
char *taskID_str;
/* get module */
if (NULL == (module_str = LITE_json_value_of(MODULE_FIELD, json))) {
LOG_ERROR("get value of module key failed");
FUNC_EXIT_RC(ERR_OTA_GENERAL_FAILURE);
}
if (NULL != *module) {
HAL_Free(*module);
}
*module = module_str;
/* get version */
if (NULL == (version_str = LITE_json_value_of(VERSION_FIELD, json))) {
LOG_ERROR("get value of version key failed");
FUNC_EXIT_RC(ERR_OTA_GENERAL_FAILURE);
}
if (NULL != *version) {
HAL_Free(*version);
}
*version = version_str;
/* get current version */
if (NULL == (current_version_str = LITE_json_value_of(CURRENT_VERSION_FIELD, json))) {
LOG_ERROR("get value of current version key failed");
FUNC_EXIT_RC(ERR_OTA_GENERAL_FAILURE);
}
if (NULL != *current_version) {
HAL_Free(*current_version);
}
*current_version = current_version_str;
/* get URL */
if (NULL == (url_str = LITE_json_value_of(URL_FIELD, json))) {
LOG_ERROR("get value of url key failed");
FUNC_EXIT_RC(ERR_OTA_GENERAL_FAILURE);
}
if (NULL != *url) {
HAL_Free(*url);
}
*url = url_str;
*download_name = HAL_Download_Name_Set((void*)url_str);
/* get md5 */
if (NULL == (md5_str = LITE_json_value_of(MD5_FIELD, json))) {
LOG_ERROR("get value of md5 failed");
FUNC_EXIT_RC(ERR_OTA_GENERAL_FAILURE);
}
if (NULL != *md5) {
HAL_Free(*md5);
}
*md5 = md5_str;
/* get md5 */
if (NULL == (taskID_str = LITE_json_value_of(TASKID_FILED, json))) {
LOG_ERROR("get value of taskID failed");
FUNC_EXIT_RC(ERR_OTA_GENERAL_FAILURE);
}
if (NULL != *taskID) {
HAL_Free(*taskID);
}
*taskID = taskID_str;
/* get file size */
if (NULL == (file_size_str = LITE_json_value_of(SIZE_FIELD, json))) {
LOG_ERROR("get value of file size failed");
FUNC_EXIT_RC(ERR_OTA_GENERAL_FAILURE);
}
if (SUCCESS_RET != LITE_get_uint32(fileSize, file_size_str)) {
LOG_ERROR("get uint32 failed");
HAL_Free(file_size_str);
FUNC_EXIT_RC(ERR_OTA_GENERAL_FAILURE);
}
HAL_Free(file_size_str);
FUNC_EXIT_RC(SUCCESS_RET);
}
int ota_lib_gen_upstream_msg(char *buf, size_t bufLen, const char *module, const char *version, char *taskID,
IOT_OTA_UpstreamMsgType reportType) {
FUNC_ENTRY;
int ret;
switch (reportType) {
case OTA_REPORT_DOWNLOAD_TIMEOUT:
case OTA_REPORT_FIRMWARE_NOT_EXIST:
case OTA_REPORT_MD5_MISMATCH:
case OTA_REPORT_SIGNATURE_EXPIRED:
case OTA_REPORT_FIRMWARE_BURN_FAILED:
case OTA_REPORT_UNDEFINED_ERROR:
ret = HAL_Snprintf(buf, bufLen, REPORT_FAIL_MSG_TEMPLATE, reportType);
break;
case OTA_REPORT_START:
ret = HAL_Snprintf(buf, bufLen, NOTIFY_MSG_TEMPLATE, taskID);
break;
case OTA_REPORT_UPGRADING:
ret = HAL_Snprintf(buf, bufLen, UPGRADING_MSG_TEMPLATE, taskID);
break;
case OTA_REPORT_SUCCESS:
ret = HAL_Snprintf(buf, bufLen, REPORT_SUCCESS_MSG_TEMPLATE, taskID);
break;
case OTA_REPORT_VERSION:
ret = HAL_Snprintf(buf, bufLen, REPORT_VER_TEMPLATE, module, version);
break;
default: FUNC_EXIT_RC(ERR_OTA_GENERAL_FAILURE);
}
if (ret < 0) {
LOG_ERROR("HAL_Snprintf failed");
FUNC_EXIT_RC(ERR_OTA_GENERAL_FAILURE);
} else if (ret >= bufLen) {
LOG_ERROR("msg is too long");
FUNC_EXIT_RC(ERR_OTA_STR_TOO_LONG);
}
FUNC_EXIT_RC(SUCCESS_RET);
}

172
src/ota/src/ota_mqtt.c Normal file
View File

@ -0,0 +1,172 @@
/*
* Copyright (C) 2012-2019 UCloud. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* or in the "license" file accompanying this file. This file 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 <string.h>
#include "uiot_defs.h"
#include "uiot_export_mqtt.h"
#include "uiot_export_ota.h"
#include "uiot_import.h"
#include "ota_config.h"
#include "ota_internal.h"
static int _ota_mqtt_gen_topic_name(char *buf, size_t buf_len, const char *ota_topic_type, const char *product_sn,
const char *device_sn)
{
FUNC_ENTRY;
int ret;
ret = HAL_Snprintf(buf, buf_len, OTA_TOPIC_TEMPLATE, product_sn, device_sn, ota_topic_type);
if(ret >= buf_len) {
FUNC_EXIT_RC(ERR_OTA_GENERAL_FAILURE);
}
if (ret < 0) {
LOG_ERROR("HAL_Snprintf failed");
FUNC_EXIT_RC(ERR_OTA_GENERAL_FAILURE);
}
FUNC_EXIT_RC(SUCCESS_RET);
}
static int _ota_mqtt_publish(OTA_MQTT_Struct_t *handle, const char *topic_type, int qos, const char *msg)
{
FUNC_ENTRY;
int ret;
char topic_name[OTA_TOPIC_BUF_LEN];
PublishParams pub_params = DEFAULT_PUB_PARAMS;
//暂不支持QOS2
if (0 == qos) {
pub_params.qos = QOS0;
} else {
pub_params.qos = QOS1;
}
pub_params.payload = (void *)msg;
pub_params.payload_len = strlen(msg);
ret = _ota_mqtt_gen_topic_name(topic_name, OTA_TOPIC_BUF_LEN, topic_type, handle->product_sn, handle->device_sn);
if (ret < 0) {
LOG_ERROR("generate topic name of info failed");
FUNC_EXIT_RC(ERR_OTA_GENERAL_FAILURE);
}
ret = IOT_MQTT_Publish(handle->mqtt, topic_name, &pub_params);
if (ret < 0) {
LOG_ERROR("publish to topic: %s failed", topic_name);
FUNC_EXIT_RC(ERR_OTA_OSC_FAILED);
}
FUNC_EXIT_RC(ret);
}
static void _ota_mqtt_upgrade_cb(void *pClient, MQTTMessage *message, void *pContext)
{
FUNC_ENTRY;
OTA_MQTT_Struct_t *handle = (OTA_MQTT_Struct_t *) pContext;
LOG_DEBUG("topic=%s", message->topic);
LOG_INFO("len=%u, topic_msg=%.*s", message->payload_len, message->payload_len, (char *)message->payload);
if (NULL != handle->msg_callback) {
handle->msg_callback(handle->context, message->payload, message->payload_len);
}
FUNC_EXIT;
}
void *osc_init(const char *product_sn, const char *device_sn, void *channel, OnOTAMessageCallback callback,
void *context)
{
int ret;
OTA_MQTT_Struct_t *h_osc = NULL;
if (NULL == (h_osc = HAL_Malloc(sizeof(OTA_MQTT_Struct_t)))) {
LOG_ERROR("allocate for h_osc failed");
goto do_exit;
}
memset(h_osc, 0, sizeof(OTA_MQTT_Struct_t));
h_osc->mqtt = channel;
h_osc->product_sn = product_sn;
h_osc->device_sn = device_sn;
h_osc->msg_callback = callback;
h_osc->context = context;
h_osc->msg_list = list_new();
h_osc->msg_mutex = HAL_MutexCreate();
if (h_osc->msg_mutex == NULL)
goto do_exit;
/* subscribe the OTA topic: "/$system/$(product_sn)/$(device_sn)/ota/downstream" */
ret = _ota_mqtt_gen_topic_name(h_osc->topic_upgrade, OTA_TOPIC_BUF_LEN, OTA_DOWNSTREAM_TOPIC_TYPE, product_sn,
device_sn);
if (ret < 0) {
LOG_ERROR("generate topic name of upgrade failed");
goto do_exit;
}
SubscribeParams sub_params = DEFAULT_SUB_PARAMS;
sub_params.on_message_handler = _ota_mqtt_upgrade_cb;
sub_params.qos = QOS1;
sub_params.user_data = h_osc;
ret = IOT_MQTT_Subscribe(channel, h_osc->topic_upgrade, &sub_params);
if (ret < 0) {
LOG_ERROR("ota mqtt subscribe failed!");
goto do_exit;
}
return h_osc;
do_exit:
if (NULL != h_osc) {
HAL_Free(h_osc);
}
return NULL;
}
int osc_deinit(void *handle)
{
FUNC_ENTRY;
OTA_MQTT_Struct_t *h_osc = handle;
list_destroy(h_osc->msg_list);
HAL_MutexDestroy(h_osc->msg_mutex);
if (NULL != handle) {
HAL_Free(handle);
}
FUNC_EXIT_RC(SUCCESS_RET);
}
/* report progress of OTA */
int osc_report_progress(void *handle, const char *msg)
{
return _ota_mqtt_publish(handle, OTA_UPSTREAM_TOPIC_TYPE, QOS0, msg);
}
/* report version of firmware */
int osc_upstream_publish(void *handle, const char *msg)
{
return _ota_mqtt_publish(handle, OTA_UPSTREAM_TOPIC_TYPE, QOS1, msg);
}

View File

@ -0,0 +1,232 @@
/*
* Copyright (C) 2012-2019 UCloud. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* or in the "license" file accompanying this file. This file 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.
*/
#ifndef C_SDK_UIOT_EXPORT_OTA_H_
#define C_SDK_UIOT_EXPORT_OTA_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "uiot_import.h"
typedef enum {
OTA_IOCTL_FETCHED_SIZE, /* 固件已经下载的大小 */
OTA_IOCTL_FILE_SIZE, /* 固件总大小 */
OTA_IOCTL_MD5SUM, /* md5(字符串类型) */
OTA_IOCTL_VERSION, /* 版本号(字符串类型)t */
OTA_IOCTL_CHECK_FIRMWARE /* 对固件进行校验 */
} IOT_OTA_CmdType;
typedef enum {
OTA_ERRCODE_FIRMWARE_NOT_EXIST = -1, /* 固件文件不存在(URL无法访问) */
OTA_ERRCODE_SIGNATURE_EXPIRED = -2, /* URL签名过期 */
OTA_ERRCODE_DOWNLOAD_TIMEOUT = -3, /* 下载超时 */
OTA_ERRCODE_MD5_MISMATCH = -4, /* MD5不匹配 */
OTA_ERRCODE_FIRMWARE_BURN_FAILED = -5, /* 固件烧录失败 */
OTA_ERRCODE_UNDEFINED_ERROR = -6 /* 未定义错误 */
} IOT_OTA_ReportErrCode;
typedef enum {
OTA_REPORT_UNDEFINED_ERROR = -6,
OTA_REPORT_FIRMWARE_BURN_FAILED = -5,
OTA_REPORT_MD5_MISMATCH = -4,
OTA_REPORT_DOWNLOAD_TIMEOUT = -3,
OTA_REPORT_SIGNATURE_EXPIRED = -2,
OTA_REPORT_FIRMWARE_NOT_EXIST = -1,
OTA_REPORT_NONE = 0,
OTA_REPORT_START = 1,
OTA_REPORT_UPGRADING = 2,
OTA_REPORT_SUCCESS = 3,
OTA_REPORT_VERSION = 4,
} IOT_OTA_UpstreamMsgType;
typedef int (*IOT_OTA_FetchCallback)(void *handle, IOT_OTA_UpstreamMsgType state);
/* OTA状态 */
typedef enum {
OTA_STATE_UNINITED = 0, /* 未初始化 */
OTA_STATE_INITED, /* 初始化完成 */
OTA_STATE_FETCHING, /* 正在下载固件 */
OTA_STATE_FETCHED, /* 固件下载完成 */
OTA_STATE_DISCONNECTED /* 连接已经断开 */
} IOT_OTA_State;
typedef struct {
uint32_t id; /* message id */
IOT_OTA_State state; /* OTA state */
uint32_t size_last_fetched; /* size of last downloaded */
uint32_t size_fetched; /* size of already downloaded */
uint32_t size_file; /* size of file */
char *taskID; /* point to taskID */
char *url; /* point to URL */
char *download_name; /* download partition name */
char *module; /* download module name */
char *version; /* point to version */
char *current_version; /* point to current version */
char *md5sum; /* MD5 string */
void *md5; /* MD5 handle */
void *ch_signal; /* channel handle of signal exchanged with OTA server */
void *ch_fetch; /* channel handle of download */
int err; /* last error code */
Timer report_timer;
IOT_OTA_FetchCallback fetch_callback_func;
} OTA_Struct_t;
/**
* @brief OTA模块和返回句柄
* MQTT客户端必须在调用此接口之前进行初始化
*
* @param product_sn:
* @param device_sn:
* @param ch_signal: .
*
* @retval : NULL
*/
void *IOT_OTA_Init(const char *product_sn, const char *device_sn, void *ch_signal);
/**
* @brief OTA相关的资源
*
*
* @param handle: OTA模块
*
* @retval 0 :
* @retval < 0 :
*/
int IOT_OTA_Destroy(void *handle);
/**
* @brief OTA服务器报告固件版本信息
* NOTE: OTA前请保证先上报一次本地固件的版本信息便
*
* @param handle: OTA模块
* @param module:
* @param version:
*
* @retval > 0 : publish的packet id
* @retval < 0 :
*/
int IOT_OTA_ReportVersion(void *handle, const char *module, const char *version);
/**
* @brief OTA服务器上报升级成功
*
* @param handle: OTA模块
*
* @retval > 0 : publish的packet id
* @retval < 0 :
*/
int IOT_OTA_ReportSuccess(void *handle);
/**
* @brief OTA服务器上报失败信息
*
* @param handle: OTA模块
* @param err_code:
*
* @retval > 0 : publish的packet id
* @retval < 0 :
*/
int IOT_OTA_ReportFail(void *handle, IOT_OTA_ReportErrCode err_code);
/**
* @brief
*
* @param handle: OTA模块
*
* @retval 1 : Yes.
* @retval 0 : No.
*/
int IOT_OTA_IsFetchFinish(void *handle);
/**
* @brief
* :buf
*
* @param handle: OTA模块
* @param buf:
* @param buf_len: buf
* @param range_len:
* @param timeout_s:
*
* @retval < 0 :
* @retval 0 : timeout_s
* @retval (0, len] : timeout_s
*/
int IOT_OTA_FetchYield(void *handle, char *buf, size_t buf_len, size_t range_len, uint32_t timeout_s);
/**
* @brief OTA信息
* md5等信息
*
* @param handle: OTA模块
* @param type: IOT_OTA_CmdType
* @param buf:
* @param buf_len: buf
* @return
NOTE:
1) type==OTA_IOCTL_FETCHED_SIZE, 'buf' uint32_t , 'buf_len' 4
2) type==OTA_IOCTL_FILE_SIZE, 'buf' uint32_t , 'buf_len' 4
3) type==OTA_IOCTL_MD5SUM, 'buf' buffer, 'buf_len' 33
4) type==OTA_IOCTL_VERSION, 'buf' buffer, 'buf_len' OTA_VERSION_LEN_MAX
5) type==OTA_IOCTL_CHECK_FIRMWARE, 'buf' uint32_t , 'buf_len' 4
0, MD5校验不通过, ; 1, .
*
* @retval 0 :
* @retval < 0 :
*/
int IOT_OTA_Ioctl(void *handle, IOT_OTA_CmdType type, void *buf, size_t buf_len);
/**
* @brief
*
* @param handle: OTA模块
*
* @return .
*/
int IOT_OTA_GetLastError(void *handle);
/**
* @brief
*
* @param handle: OTA模块
*
* @return .
*/
int IOT_OTA_fw_download(void *handle);
#ifdef __cplusplus
}
#endif
#endif //C_SDK_UIOT_EXPORT_OTA_H_

View File

@ -20,6 +20,7 @@ extern "C" {
#include <string.h> #include <string.h>
#include <stddef.h> #include <stddef.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
#include "uiot_defs.h" #include "uiot_defs.h"
#include "utils_httpc.h" #include "utils_httpc.h"
@ -33,17 +34,20 @@ extern "C" {
#define HTTP_CLIENT_READ_BUF_SIZE (1024) /* read payload */ #define HTTP_CLIENT_READ_BUF_SIZE (1024) /* read payload */
#define HTTP_CLIENT_READ_HEAD_SIZE (32) /* read header */ #define HTTP_CLIENT_READ_HEAD_SIZE (32) /* read header */
#define HTTP_CLIENT_SEND_BUF_SIZE (1024) /* send */ #define HTTP_CLIENT_SEND_BUF_SIZE (1024) /* send */
#define HTTP_CLIENT_REQUEST_BUF_SIZE (300) /* send */ #define HTTP_CLIENT_REQUEST_BUF_SIZE (1024) /* send */
#define HTTP_CLIENT_MAX_URL_LEN (256) #define HTTP_CLIENT_MAX_URL_LEN (512)
#define HTTP_RETRIEVE_MORE_DATA (1) /**< More data needs to be retrieved. */ #define HTTP_RETRIEVE_MORE_DATA (1) /**< More data needs to be retrieved. */
#define HTTP_CLIENT_CHUNK_SIZE (1024) #define HTTP_CLIENT_CHUNK_SIZE (1024)
static int _utils_parse_url(const char *url, char *host, char *path) { static int _utils_parse_url(const char *url, char *host, char *path, int *port) {
char *host_ptr = (char *) strstr(url, "://"); char *host_ptr = (char *) strstr(url, "://");
uint32_t host_len = 0; uint32_t host_len = 0;
uint32_t path_len; uint32_t path_len;
uint32_t port_len;
/* char *port_ptr; */ /* char *port_ptr; */
char *path_ptr; char *path_ptr;
char *fragment_ptr; char *fragment_ptr;
char port_str[HTTP_CLIENT_MAX_URL_LEN] = {0};
char *port_ptr;
if (host_ptr == NULL) { if (host_ptr == NULL) {
return ERR_PARAM_INVALID; /* URL is invalid */ return ERR_PARAM_INVALID; /* URL is invalid */
@ -69,6 +73,17 @@ static int _utils_parse_url(const char *url, char *host, char *path) {
memcpy(path, path_ptr, path_len); memcpy(path, path_ptr, path_len);
path[path_len] = '\0'; path[path_len] = '\0';
port_ptr = strchr(host, ':');
if (NULL == port_ptr) {
return SUCCESS_RET;
}else{
port_len = port_ptr - host;
memcpy(port_str, port_ptr+1, strlen(port_ptr)-1);
port_str[strlen(port_ptr)-1] = '\0';
if(port_str != NULL)
*port = atoi(port_str);
host[port_len] = '\0';
}
return SUCCESS_RET; return SUCCESS_RET;
} }
@ -355,7 +370,7 @@ static int _http_parse_response_header(http_client_t *client, char *data, int le
client_data->response_content_len = atoi(tmp_ptr + strlen("Content-Length: ")); client_data->response_content_len = atoi(tmp_ptr + strlen("Content-Length: "));
client_data->retrieve_len = client_data->response_content_len; client_data->retrieve_len = client_data->response_content_len;
} else { } else {
LOG_ERROR("Could not parse header"); LOG_ERROR("Could not parse header data:%s",data);
return ERR_HTTP_CONN_ERROR; return ERR_HTTP_CONN_ERROR;
} }
@ -405,8 +420,9 @@ int _http_send_request(http_client_t *client, const char *url, HTTP_Request_Meth
int rc; int rc;
char host[HTTP_CLIENT_MAX_URL_LEN] = {0}; char host[HTTP_CLIENT_MAX_URL_LEN] = {0};
char path[HTTP_CLIENT_MAX_URL_LEN] = {0}; char path[HTTP_CLIENT_MAX_URL_LEN] = {0};
int port;
rc = _utils_parse_url(url, host, path); rc = _utils_parse_url(url, host, path, &port);
if (rc != SUCCESS_RET) { if (rc != SUCCESS_RET) {
return rc; return rc;
} }
@ -456,17 +472,18 @@ static int _http_client_recv_response(http_client_t *client, uint32_t timeout_ms
return ret; return ret;
} }
int http_client_connect(http_client_t *client, const char *url, int port, const char *ca_crt) { int http_client_connect(http_client_t *client, const char *url, const char *ca_crt) {
if (client->net.handle != 0) { if (client->net.handle != 0) {
LOG_ERROR("http client has connected to host!"); LOG_ERROR("http client has connected to host!");
return ERR_HTTP_CONN_ERROR; return ERR_HTTP_CONN_ERROR;
} }
int rc; int rc;
int port;
char host[HTTP_CLIENT_MAX_URL_LEN] = {0}; char host[HTTP_CLIENT_MAX_URL_LEN] = {0};
char path[HTTP_CLIENT_MAX_URL_LEN] = {0}; char path[HTTP_CLIENT_MAX_URL_LEN] = {0};
rc = _utils_parse_url(url, host, path); rc = _utils_parse_url(url, host, path, &port);
if (rc != SUCCESS_RET) { if (rc != SUCCESS_RET) {
return rc; return rc;
} }
@ -486,27 +503,6 @@ int http_client_connect(http_client_t *client, const char *url, int port, const
return rc; return rc;
} }
int http_client_common(http_client_t *client, const char *url, int port, const char *ca_crt,
HTTP_Request_Method method, http_client_data_t *client_data, uint32_t timeout_ms) {
int rc;
if (client->net.handle == 0) {
rc = http_client_connect(client, url, port, ca_crt);
if (rc != SUCCESS_RET) {
return rc;
}
}
rc = _http_send_request(client, url, method, 0, 0, client_data, timeout_ms);
if (rc != SUCCESS_RET) {
LOG_ERROR("http_send_request error, rc = %d", rc);
http_client_close(client);
return rc;
}
return SUCCESS_RET;
}
int http_client_recv_data(http_client_t *client, uint32_t timeout_ms, http_client_data_t *client_data) { int http_client_recv_data(http_client_t *client, uint32_t timeout_ms, http_client_data_t *client_data) {
int rc; int rc;

View File

@ -57,10 +57,7 @@ typedef struct {
} http_client_data_t; } http_client_data_t;
int http_client_connect(http_client_t *client, const char *url, int port, const char *ca_crt); int http_client_connect(http_client_t *client, const char *url, const char *ca_crt);
int http_client_common(http_client_t *client, const char *url, int port, const char *ca_crt,
HTTP_Request_Method method, http_client_data_t *client_data, uint32_t timeout_ms);
int http_client_recv_data(http_client_t *client, uint32_t timeout_ms, http_client_data_t *client_data); int http_client_recv_data(http_client_t *client, uint32_t timeout_ms, http_client_data_t *client_data);

View File

@ -4,6 +4,7 @@ PLATFORM_OS ?= linux
PLATFORM_MODULE ?= esp8266 PLATFORM_MODULE ?= esp8266
FEATURE_MQTT_COMM_ENABLED ?= y FEATURE_MQTT_COMM_ENABLED ?= y
FEATURE_OTA_ENABLED ?= n
FEATURE_AUTH_MODE_DYNAMIC ?= n FEATURE_AUTH_MODE_DYNAMIC ?= n
FEATURE_SUPPORT_TLS ?= n FEATURE_SUPPORT_TLS ?= n
FEATURE_SUPPORT_AT_CMD ?= n FEATURE_SUPPORT_AT_CMD ?= n

View File

@ -9,6 +9,7 @@ SETTING_VARS := \
SWITCH_VARS := \ SWITCH_VARS := \
FEATURE_MQTT_COMM_ENABLED \ FEATURE_MQTT_COMM_ENABLED \
FEATURE_OTA_ENABLED \
FEATURE_SUPPORT_TLS \ FEATURE_SUPPORT_TLS \
FEATURE_MQTT_RMDUP_MSG_ENABLED \ FEATURE_MQTT_RMDUP_MSG_ENABLED \
FEATURE_AUTH_MODE_DYNAMIC \ FEATURE_AUTH_MODE_DYNAMIC \

View File

@ -16,6 +16,6 @@ endif
$(TOP_Q) \ $(TOP_Q) \
rm -rf ${TEMP_DIR} rm -rf ${TEMP_DIR}
.PHONY: mqtt_sample dynamic_auth_sample .PHONY: mqtt_sample dynamic_auth_sample ota_sample
final : mqtt_sample dynamic_auth_sample final : mqtt_sample dynamic_auth_sample ota_sample