├── README.md ├── TC1 ├── MiCOKit_EXT.h ├── TC1.mk ├── cJSON │ ├── cJSON.c │ └── cJSON.h ├── http_server │ ├── app_httpd.c │ ├── app_httpd.h │ ├── readme.txt │ └── web_data.c ├── main.c ├── main.h ├── mico_config.h ├── ota_server │ ├── ota_server.c │ └── ota_server.h ├── user_function.c ├── user_function.h ├── user_gpio.c ├── user_gpio.h ├── user_mqtt_client.c ├── user_mqtt_client.h ├── user_ota.c ├── user_ota.h ├── user_power.c ├── user_power.h ├── user_sntp.c ├── user_sntp.h ├── user_wifi.c └── user_wifi.h └── mico-os └── libraries └── protocols └── SNTP └── sntp.c /README.md: -------------------------------------------------------------------------------- 1 | ## 高能预警 ## 2 | fork的版本号较低,可能存在不少bug,请充分测试后再用于实际场景。 3 | 4 | ## 说明 ## 5 | 基于[斐讯TC1智能排插固件zTC1(v0.10)](https://github.com/a2633063/zTC1/)进行精简的固件,详细说明[传送门](https://ljr.im/articles/streamline-the-fixon-tc1-firmware/)。 6 | -------------------------------------------------------------------------------- /TC1/MiCOKit_EXT.h: -------------------------------------------------------------------------------- 1 | #include "sntp.h" -------------------------------------------------------------------------------- /TC1/TC1.mk: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # 3 | # The MIT License 4 | # Copyright (c) 2016 MXCHIP Inc. 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is furnished 11 | # to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 21 | # IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | ############################################################################### 23 | 24 | 25 | NAME := App_TC1 26 | 27 | $(NAME)_SOURCES := main.c\ 28 | cJSON/cJSON.c\ 29 | ota_server/ota_server.c\ 30 | user_wifi.c\ 31 | user_gpio.c\ 32 | user_sntp.c\ 33 | user_mqtt_client.c\ 34 | user_ota.c\ 35 | user_power.c\ 36 | user_function.c\ 37 | http_server/app_httpd.c \ 38 | http_server/web_data.c 39 | 40 | $(NAME)_COMPONENTS := protocols/SNTP\ 41 | protocols/mqtt\ 42 | utilities/url\ 43 | daemons/http_server 44 | -------------------------------------------------------------------------------- /TC1/cJSON/cJSON.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cnk700i/tc1_mqtt/3264db3894c0e3323ecc1050b546f51cc19f1c23/TC1/cJSON/cJSON.c -------------------------------------------------------------------------------- /TC1/cJSON/cJSON.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Dave Gamble 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | */ 22 | 23 | #ifndef cJSON__h 24 | #define cJSON__h 25 | 26 | #ifdef __cplusplus 27 | extern "C" 28 | { 29 | #endif 30 | 31 | /* cJSON Types: */ 32 | #define cJSON_False 0 33 | #define cJSON_True 1 34 | #define cJSON_NULL 2 35 | #define cJSON_Number 3 36 | #define cJSON_String 4 37 | #define cJSON_Array 5 38 | #define cJSON_Object 6 39 | 40 | #define cJSON_IsReference 256 41 | #define cJSON_StringIsConst 512 42 | 43 | /* The cJSON structure: */ 44 | typedef struct cJSON { 45 | struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ 46 | struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ 47 | 48 | int type; /* The type of the item, as above. */ 49 | 50 | char *valuestring; /* The item's string, if type==cJSON_String */ 51 | int valueint; /* The item's number, if type==cJSON_Number */ 52 | double valuedouble; /* The item's number, if type==cJSON_Number */ 53 | 54 | char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ 55 | } cJSON; 56 | 57 | typedef struct cJSON_Hooks { 58 | void *(*malloc_fn)(size_t sz); 59 | void (*free_fn)(void *ptr); 60 | } cJSON_Hooks; 61 | 62 | /* Supply malloc, realloc and free functions to cJSON */ 63 | extern void cJSON_InitHooks(cJSON_Hooks* hooks); 64 | 65 | 66 | /* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */ 67 | extern cJSON *cJSON_Parse(const char *value); 68 | /* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */ 69 | extern char *cJSON_Print(cJSON *item); 70 | /* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */ 71 | extern char *cJSON_PrintUnformatted(cJSON *item); 72 | /* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */ 73 | extern char *cJSON_PrintBuffered(cJSON *item,int prebuffer,int fmt); 74 | /* Delete a cJSON entity and all subentities. */ 75 | extern void cJSON_Delete(cJSON *c); 76 | 77 | /* Returns the number of items in an array (or object). */ 78 | extern int cJSON_GetArraySize(cJSON *array); 79 | /* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */ 80 | extern cJSON *cJSON_GetArrayItem(cJSON *array,int item); 81 | /* Get item "string" from object. Case insensitive. */ 82 | extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string); 83 | 84 | /* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ 85 | extern const char *cJSON_GetErrorPtr(void); 86 | 87 | /* These calls create a cJSON item of the appropriate type. */ 88 | extern cJSON *cJSON_CreateNull(void); 89 | extern cJSON *cJSON_CreateTrue(void); 90 | extern cJSON *cJSON_CreateFalse(void); 91 | extern cJSON *cJSON_CreateBool(int b); 92 | extern cJSON *cJSON_CreateNumber(double num); 93 | extern cJSON *cJSON_CreateString(const char *string); 94 | extern cJSON *cJSON_CreateArray(void); 95 | extern cJSON *cJSON_CreateObject(void); 96 | 97 | /* These utilities create an Array of count items. */ 98 | extern cJSON *cJSON_CreateIntArray(const int *numbers,int count); 99 | extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count); 100 | extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count); 101 | extern cJSON *cJSON_CreateStringArray(const char **strings,int count); 102 | 103 | /* Append item to the specified array/object. */ 104 | extern void cJSON_AddItemToArray(cJSON *array, cJSON *item); 105 | extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item); 106 | extern void cJSON_AddItemToObjectCS(cJSON *object,const char *string,cJSON *item); /* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object */ 107 | /* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */ 108 | extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); 109 | extern void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item); 110 | 111 | /* Remove/Detatch items from Arrays/Objects. */ 112 | extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which); 113 | extern void cJSON_DeleteItemFromArray(cJSON *array,int which); 114 | extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string); 115 | extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string); 116 | 117 | /* Update array items. */ 118 | extern void cJSON_InsertItemInArray(cJSON *array,int which,cJSON *newitem); /* Shifts pre-existing items to the right. */ 119 | extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem); 120 | extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); 121 | 122 | /* Duplicate a cJSON item */ 123 | extern cJSON *cJSON_Duplicate(cJSON *item,int recurse); 124 | /* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will 125 | need to be released. With recurse!=0, it will duplicate any children connected to the item. 126 | The item->next and ->prev pointers are always zero on return from Duplicate. */ 127 | 128 | /* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ 129 | extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated); 130 | 131 | extern void cJSON_Minify(char *json); 132 | 133 | /* Macros for creating things quickly. */ 134 | #define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull()) 135 | #define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue()) 136 | #define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse()) 137 | #define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b)) 138 | #define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n)) 139 | #define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s)) 140 | 141 | /* When assigning an integer value, it needs to be propagated to valuedouble too. */ 142 | #define cJSON_SetIntValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val)) 143 | #define cJSON_SetNumberValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val)) 144 | 145 | /* These functions check the type of an item */ 146 | int cJSON_IsFalse(const cJSON * const item); 147 | int cJSON_IsTrue(const cJSON * const item); 148 | int cJSON_IsBool(const cJSON * const item); 149 | int cJSON_IsNull(const cJSON * const item); 150 | int cJSON_IsNumber(const cJSON * const item); 151 | int cJSON_IsString(const cJSON * const item); 152 | int cJSON_IsArray(const cJSON * const item); 153 | int cJSON_IsObject(const cJSON * const item); 154 | 155 | #ifdef __cplusplus 156 | } 157 | #endif 158 | 159 | #endif 160 | -------------------------------------------------------------------------------- /TC1/http_server/app_httpd.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file app_https.c 4 | * @author QQ DING 5 | * @version V1.0.0 6 | * @date 1-September-2015 7 | * @brief The main HTTPD server initialization and wsgi handle. 8 | ****************************************************************************** 9 | * 10 | * The MIT License 11 | * Copyright (c) 2016 MXCHIP Inc. 12 | * 13 | * Permission is hereby granted, free of charge, to any person obtaining a copy 14 | * of this software and associated documentation files (the "Software"), to deal 15 | * in the Software without restriction, including without limitation the rights 16 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | * copies of the Software, and to permit persons to whom the Software is furnished 18 | * to do so, subject to the following conditions: 19 | * 20 | * The above copyright notice and this permission notice shall be included in 21 | * all copies or substantial portions of the Software. 22 | * 23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 27 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 28 | * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 29 | * 30 | ****************************************************************************** 31 | */ 32 | 33 | #include 34 | #include 35 | #include 36 | 37 | #include "mico.h" 38 | #include "httpd_priv.h" 39 | #include "app_httpd.h" 40 | 41 | #include "main.h" 42 | 43 | #define app_httpd_log(M, ...) custom_log("apphttpd", M, ##__VA_ARGS__) 44 | 45 | #define HTTPD_HDR_DEFORT (HTTPD_HDR_ADD_SERVER|HTTPD_HDR_ADD_CONN_CLOSE|HTTPD_HDR_ADD_PRAGMA_NO_CACHE) 46 | static bool is_http_init; 47 | static bool is_handlers_registered; 48 | struct httpd_wsgi_call g_app_handlers[]; 49 | 50 | static int web_send_wifisetting_page(httpd_request_t *req) 51 | { 52 | OSStatus err = kNoErr; 53 | 54 | err = httpd_send_all_header(req, HTTP_RES_200, sizeof(wifisetting), HTTP_CONTENT_HTML_STR); 55 | require_noerr_action( err, exit, app_httpd_log("ERROR: Unable to send http wifisetting headers.") ); 56 | 57 | err = httpd_send_body(req->sock, wifisetting, sizeof(wifisetting)); 58 | require_noerr_action( err, exit, app_httpd_log("ERROR: Unable to send http wifisetting body.") ); 59 | 60 | exit: 61 | return err; 62 | } 63 | 64 | static int web_send_result_page(httpd_request_t *req) 65 | { 66 | OSStatus err = kNoErr; 67 | bool para_succ = false; 68 | int buf_size = 512; 69 | char *buf; 70 | char value_ssid[maxSsidLen]; 71 | char value_pass[maxKeyLen]; 72 | char value_user[maxNameLen]; 73 | mico_Context_t* context = NULL; 74 | 75 | context = mico_system_context_get( ); 76 | 77 | buf = malloc(buf_size); 78 | 79 | err = httpd_get_data(req, buf, buf_size); 80 | require_noerr( err, Save_Out ); 81 | 82 | err = httpd_get_tag_from_post_data(buf, "SSID", value_ssid, maxSsidLen); 83 | require_noerr( err, Save_Out ); 84 | 85 | err = httpd_get_tag_from_post_data(buf, "USER", value_user, maxNameLen); 86 | require_noerr( err, Save_Out ); 87 | 88 | if(!strncmp(value_ssid, "\0", 1)) 89 | goto Save_Out; 90 | if(!strncmp(value_user, "\0", 1)) 91 | goto Save_Out; 92 | 93 | strncpy(context->micoSystemConfig.ssid, value_ssid, maxSsidLen); 94 | strncpy(user_config->user, value_user, maxNameLen); 95 | 96 | err = httpd_get_tag_from_post_data(buf, "PASS", value_pass, maxKeyLen); 97 | require_noerr( err, Save_Out ); 98 | 99 | strncpy(context->micoSystemConfig.key, value_pass, maxKeyLen); 100 | strncpy(context->micoSystemConfig.user_key, value_pass, maxKeyLen); 101 | context->micoSystemConfig.keyLength = strlen(context->micoSystemConfig.key); 102 | context->micoSystemConfig.user_keyLength = strlen(context->micoSystemConfig.key); 103 | 104 | context->micoSystemConfig.channel = 0; 105 | memset(context->micoSystemConfig.bssid, 0x0, 6); 106 | context->micoSystemConfig.security = SECURITY_TYPE_AUTO; 107 | context->micoSystemConfig.dhcpEnable = true; 108 | 109 | para_succ = true; 110 | 111 | Save_Out: 112 | 113 | if(para_succ == true) 114 | { 115 | err = httpd_send_all_header(req, HTTP_RES_200, sizeof(wifisuccess), HTTP_CONTENT_HTML_STR); 116 | require_noerr_action( err, exit, app_httpd_log("ERROR: Unable to send http wifisuccess headers.") ); 117 | 118 | err = httpd_send_body(req->sock, wifisuccess, sizeof(wifisuccess)); 119 | require_noerr_action( err, exit, app_httpd_log("ERROR: Unable to send http wifisuccess body.") ); 120 | 121 | context->micoSystemConfig.configured = allConfigured; 122 | 123 | mico_system_context_update(context); 124 | 125 | mico_system_power_perform( context, eState_Software_Reset ); 126 | } 127 | else 128 | { 129 | err = httpd_send_all_header(req, HTTP_RES_200, sizeof(wififail), HTTP_CONTENT_HTML_STR); 130 | require_noerr_action( err, exit, app_httpd_log("ERROR: Unable to send http wififail headers.") ); 131 | 132 | err = httpd_send_body(req->sock, wififail, sizeof(wififail)); 133 | require_noerr_action( err, exit, app_httpd_log("ERROR: Unable to send http wififail body.") ); 134 | } 135 | 136 | exit: 137 | if(buf) free(buf); 138 | return err; 139 | } 140 | 141 | struct httpd_wsgi_call g_app_handlers[] = { 142 | {"/", HTTPD_HDR_DEFORT, 0, web_send_wifisetting_page, NULL, NULL, NULL}, 143 | {"/result.htm", HTTPD_HDR_DEFORT, 0, NULL, web_send_result_page, NULL, NULL}, 144 | {"/setting.htm", HTTPD_HDR_DEFORT, 0, web_send_wifisetting_page, NULL, NULL, NULL}, 145 | }; 146 | 147 | static int g_app_handlers_no = sizeof(g_app_handlers)/sizeof(struct httpd_wsgi_call); 148 | 149 | static void app_http_register_handlers() 150 | { 151 | int rc; 152 | rc = httpd_register_wsgi_handlers(g_app_handlers, g_app_handlers_no); 153 | if (rc) { 154 | app_httpd_log("failed to register test web handler"); 155 | } 156 | } 157 | 158 | static int _app_httpd_start() 159 | { 160 | OSStatus err = kNoErr; 161 | app_httpd_log("initializing web-services"); 162 | 163 | /*Initialize HTTPD*/ 164 | if(is_http_init == false) { 165 | err = httpd_init(); 166 | require_noerr_action( err, exit, app_httpd_log("failed to initialize httpd") ); 167 | is_http_init = true; 168 | } 169 | 170 | /*Start http thread*/ 171 | err = httpd_start(); 172 | if(err != kNoErr) { 173 | app_httpd_log("failed to start httpd thread"); 174 | httpd_shutdown(); 175 | } 176 | exit: 177 | return err; 178 | } 179 | 180 | int app_httpd_start( void ) 181 | { 182 | OSStatus err = kNoErr; 183 | 184 | err = _app_httpd_start(); 185 | require_noerr( err, exit ); 186 | 187 | if (is_handlers_registered == false) { 188 | app_http_register_handlers(); 189 | is_handlers_registered = true; 190 | } 191 | 192 | exit: 193 | return err; 194 | } 195 | 196 | int app_httpd_stop() 197 | { 198 | OSStatus err = kNoErr; 199 | 200 | /* HTTPD and services */ 201 | app_httpd_log("stopping down httpd"); 202 | err = httpd_stop(); 203 | require_noerr_action( err, exit, app_httpd_log("failed to halt httpd") ); 204 | 205 | exit: 206 | return err; 207 | } 208 | -------------------------------------------------------------------------------- /TC1/http_server/app_httpd.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file app_httpd.h 4 | * @author QQ DING 5 | * @version V1.0.0 6 | * @date 1-September-2015 7 | * @brief This header contains function prototypes called by httpd protocol 8 | * operations 9 | ****************************************************************************** 10 | * 11 | * The MIT License 12 | * Copyright (c) 2016 MXCHIP Inc. 13 | * 14 | * Permission is hereby granted, free of charge, to any person obtaining a copy 15 | * of this software and associated documentation files (the "Software"), to deal 16 | * in the Software without restriction, including without limitation the rights 17 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | * copies of the Software, and to permit persons to whom the Software is furnished 19 | * to do so, subject to the following conditions: 20 | * 21 | * The above copyright notice and this permission notice shall be included in 22 | * all copies or substantial portions of the Software. 23 | * 24 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 28 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 29 | * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 | * 31 | ****************************************************************************** 32 | */ 33 | 34 | extern const unsigned char wififail[0xAC9]; 35 | 36 | extern const unsigned char wifisetting[3618]; 37 | 38 | extern const unsigned char wifisuccess[0x9BC]; 39 | 40 | int app_httpd_start( void ); 41 | 42 | int app_httpd_stop(); 43 | 44 | -------------------------------------------------------------------------------- /TC1/http_server/readme.txt: -------------------------------------------------------------------------------- 1 | /** 2 | @page " http_sever " demo 3 | 4 | @verbatim 5 | ******************** (C) COPYRIGHT 2016 MXCHIP MiCO SDK******************* 6 | * @file http_sever/readme.txt 7 | * @author MDWG (MiCO Documentation Working Group) 8 | * @version v2.4.x 9 | * @date 11-April-2016 10 | * @brief Description of the "http_sever" demo. 11 | ****************************************************************************** 12 | 13 | @par Demo Description 14 | This demo shows: how to start http sever to realize network configuration through webpage on PC or Mobile Phone. 15 | 16 | 17 | @par Directory contents 18 | - Demos/http/http_sever/http_sever.c HTTP server demo entrance 19 | - Demos/http/http_sever/app_httpd.c HTTP server demo 20 | - Demos/http/http_sever/web_data.c Webpage applicaiton program 21 | - Demos/http/http_sever/mico_config.h MiCO function header file 22 | - Demos/http/http_sever/app_httpd.h app_httpd.c header file 23 | 24 | 25 | @par Hardware and Software environment 26 | - This demo has been tested on MiCOKit-3165 board. 27 | - This demo can be easily tailored to any other supported device and development board. 28 | 29 | 30 | @par How to use it ? 31 | In order to make the program work, you must do the following : 32 | - Open your preferred toolchain, 33 | - IDE: IAR 7.30.4 or Keil MDK 5.13. 34 | - Debugging Tools: JLINK or STLINK 35 | - Modify header file path of "mico_config.h". Please referring to "http://mico.io/wiki/doku.php?id=confighchange" 36 | - Rebuild all files and load your image into target memory. Please referring to "http://mico.io/wiki/doku.php?id=debug" 37 | - Run the demo. 38 | - View operating results and system serial log (Serial port: Baud rate: 115200, data bits: 8bit, parity: No, stop bits: 1). Please referring to http://mico.io/wiki/doku.php?id=com.mxchip.basic 39 | 40 | **/ 41 | 42 | -------------------------------------------------------------------------------- /TC1/http_server/web_data.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file web_data.c 4 | * @author QQ DING 5 | * @version V1.0.0 6 | * @date 1-September-2015 7 | * @brief This header file contains some data page 8 | ****************************************************************************** 9 | * 10 | * The MIT License 11 | * Copyright (c) 2016 MXCHIP Inc. 12 | * 13 | * Permission is hereby granted, free of charge, to any person obtaining a copy 14 | * of this software and associated documentation files (the "Software"), to deal 15 | * in the Software without restriction, including without limitation the rights 16 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | * copies of the Software, and to permit persons to whom the Software is furnished 18 | * to do so, subject to the following conditions: 19 | * 20 | * The above copyright notice and this permission notice shall be included in 21 | * all copies or substantial portions of the Software. 22 | * 23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 27 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 28 | * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 29 | * 30 | ****************************************************************************** 31 | */ 32 | 33 | 34 | const unsigned char wififail[0xAC9] = { 35 | 0x3C, 0x21, 0x44, 0x4F, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20, 0x68, 0x74, 0x6D, 0x6C, 0x20, 0x50, 36 | 0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x22, 0x2D, 0x2F, 0x2F, 0x57, 0x33, 0x43, 0x2F, 0x2F, 0x44, 37 | 0x54, 0x44, 0x20, 0x58, 0x48, 0x54, 0x4D, 0x4C, 0x20, 0x31, 0x2E, 0x30, 0x20, 0x54, 0x72, 0x61, 38 | 0x6E, 0x73, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x61, 0x6C, 0x2F, 0x2F, 0x45, 0x4E, 0x22, 0x20, 0x22, 39 | 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x33, 0x2E, 0x6F, 0x72, 40 | 0x67, 0x2F, 0x54, 0x52, 0x2F, 0x78, 0x68, 0x74, 0x6D, 0x6C, 0x31, 0x2F, 0x44, 0x54, 0x44, 0x2F, 41 | 0x78, 0x68, 0x74, 0x6D, 0x6C, 0x31, 0x2D, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x69, 0x74, 0x69, 0x6F, 42 | 0x6E, 0x61, 0x6C, 0x2E, 0x64, 0x74, 0x64, 0x22, 0x3E, 0x0D, 0x0A, 0x3C, 0x68, 0x74, 0x6D, 0x6C, 43 | 0x20, 0x78, 0x6D, 0x6C, 0x6E, 0x73, 0x3D, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x77, 44 | 0x77, 0x77, 0x2E, 0x77, 0x33, 0x2E, 0x6F, 0x72, 0x67, 0x2F, 0x31, 0x39, 0x39, 0x39, 0x2F, 0x78, 45 | 0x68, 0x74, 0x6D, 0x6C, 0x22, 0x3E, 0x0D, 0x0A, 0x3C, 0x68, 0x65, 0x61, 0x64, 0x3E, 0x0D, 0x0A, 46 | 0x3C, 0x6D, 0x65, 0x74, 0x61, 0x20, 0x68, 0x74, 0x74, 0x70, 0x2D, 0x65, 0x71, 0x75, 0x69, 0x76, 47 | 0x3D, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x2D, 0x74, 0x79, 0x70, 0x65, 0x22, 0x20, 48 | 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x3D, 0x22, 0x74, 0x65, 0x78, 0x74, 0x2F, 0x68, 0x74, 49 | 0x6D, 0x6C, 0x22, 0x20, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3D, 0x22, 0x75, 0x74, 0x66, 50 | 0x2D, 0x38, 0x22, 0x3E, 0x0D, 0x0A, 0x3C, 0x6D, 0x65, 0x74, 0x61, 0x20, 0x63, 0x6F, 0x6E, 0x74, 51 | 0x65, 0x6E, 0x74, 0x3D, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3D, 0x64, 0x65, 0x76, 0x69, 0x63, 52 | 0x65, 0x2D, 0x77, 0x69, 0x64, 0x74, 0x68, 0x2C, 0x20, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x61, 0x6C, 53 | 0x2D, 0x73, 0x63, 0x61, 0x6C, 0x65, 0x3D, 0x31, 0x2E, 0x30, 0x2C, 0x20, 0x6D, 0x61, 0x78, 0x69, 54 | 0x6D, 0x75, 0x6D, 0x2D, 0x73, 0x63, 0x61, 0x6C, 0x65, 0x3D, 0x31, 0x2E, 0x30, 0x2C, 0x20, 0x75, 55 | 0x73, 0x65, 0x72, 0x2D, 0x73, 0x63, 0x61, 0x6C, 0x61, 0x62, 0x6C, 0x65, 0x3D, 0x30, 0x22, 0x20, 56 | 0x6E, 0x61, 0x6D, 0x65, 0x3D, 0x22, 0x76, 0x69, 0x65, 0x77, 0x70, 0x6F, 0x72, 0x74, 0x22, 0x3E, 57 | 0x0D, 0x0A, 0x3C, 0x74, 0x69, 0x74, 0x6C, 0x65, 0x3E, 0xE7, 0xBD, 0x91, 0xE5, 0x85, 0xB3, 0xE4, 58 | 0xB8, 0x8A, 0xE7, 0xBD, 0x91, 0xE8, 0xAE, 0xBE, 0xE7, 0xBD, 0xAE, 0x3C, 0x2F, 0x74, 0x69, 0x74, 59 | 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x3C, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x62, 60 | 0x6F, 0x64, 0x79, 0x2C, 0x20, 0x70, 0x2C, 0x20, 0x68, 0x31, 0x2C, 0x20, 0x68, 0x32, 0x2C, 0x20, 61 | 0x68, 0x33, 0x2C, 0x20, 0x68, 0x34, 0x2C, 0x20, 0x68, 0x35, 0x2C, 0x20, 0x68, 0x36, 0x2C, 0x20, 62 | 0x75, 0x6C, 0x2C, 0x20, 0x6F, 0x6C, 0x2C, 0x20, 0x6C, 0x69, 0x2C, 0x20, 0x64, 0x6C, 0x2C, 0x20, 63 | 0x64, 0x74, 0x2C, 0x20, 0x64, 0x64, 0x2C, 0x20, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x2C, 0x20, 0x74, 64 | 0x68, 0x2C, 0x20, 0x74, 0x64, 0x2C, 0x20, 0x66, 0x6F, 0x72, 0x6D, 0x2C, 0x20, 0x66, 0x69, 0x65, 65 | 0x6C, 0x64, 0x73, 0x65, 0x74, 0x2C, 0x20, 0x6C, 0x65, 0x67, 0x65, 0x6E, 0x64, 0x2C, 0x20, 0x69, 66 | 0x6E, 0x70, 0x75, 0x74, 0x2C, 0x20, 0x74, 0x65, 0x78, 0x74, 0x61, 0x72, 0x65, 0x61, 0x2C, 0x20, 67 | 0x62, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x2C, 0x20, 0x73, 0x65, 0x6C, 0x65, 0x63, 0x74, 0x2C, 0x20, 68 | 0x69, 0x6D, 0x67, 0x2C, 0x20, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x71, 0x75, 0x6F, 0x74, 0x65, 0x20, 69 | 0x7B, 0x0D, 0x0A, 0x09, 0x6D, 0x61, 0x72, 0x67, 0x69, 0x6E, 0x3A, 0x20, 0x30, 0x3B, 0x0D, 0x0A, 70 | 0x09, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6E, 0x67, 0x3A, 0x20, 0x30, 0x3B, 0x0D, 0x0A, 0x09, 0x62, 71 | 0x6F, 0x72, 0x64, 0x65, 0x72, 0x3A, 0x20, 0x30, 0x3B, 0x0D, 0x0A, 0x09, 0x66, 0x6F, 0x6E, 0x74, 72 | 0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3B, 0x0D, 0x0A, 0x09, 0x76, 73 | 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6C, 0x2D, 0x61, 0x6C, 0x69, 0x67, 0x6E, 0x3A, 0x20, 0x62, 74 | 0x61, 0x73, 0x65, 0x6C, 0x69, 0x6E, 0x65, 0x3B, 0x0D, 0x0A, 0x09, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 75 | 0x66, 0x61, 0x6D, 0x69, 0x6C, 0x79, 0x3A, 0x20, 0x22, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 76 | 0x66, 0x74, 0x20, 0x59, 0x61, 0x48, 0x65, 0x69, 0x22, 0x2C, 0x22, 0x69, 0x63, 0x6F, 0x6E, 0x66, 77 | 0x6F, 0x6E, 0x74, 0x22, 0x2C, 0x22, 0x46, 0x6F, 0x6E, 0x74, 0x41, 0x77, 0x65, 0x73, 0x6F, 0x6D, 78 | 0x65, 0x22, 0x20, 0x20, 0x21, 0x69, 0x6D, 0x70, 0x6F, 0x72, 0x74, 0x61, 0x6E, 0x74, 0x3B, 0x0D, 79 | 0x0A, 0x7D, 0x0D, 0x0A, 0x68, 0x31, 0x2C, 0x20, 0x68, 0x32, 0x2C, 0x20, 0x68, 0x33, 0x2C, 0x20, 80 | 0x68, 0x34, 0x2C, 0x20, 0x68, 0x35, 0x2C, 0x20, 0x68, 0x36, 0x20, 0x7B, 0x0D, 0x0A, 0x09, 0x66, 81 | 0x6F, 0x6E, 0x74, 0x2D, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x20, 0x6E, 0x6F, 0x72, 0x6D, 82 | 0x61, 0x6C, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x62, 0x6F, 0x64, 0x79, 0x7B, 0x0D, 0x0A, 0x09, 83 | 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x3A, 0x20, 0x23, 0x66, 0x35, 0x66, 84 | 0x35, 0x66, 0x35, 0x0D, 0x0A, 0x09, 0x7D, 0x0D, 0x0A, 0x62, 0x6F, 0x64, 0x79, 0x2C, 0x20, 0x68, 85 | 0x74, 0x6D, 0x6C, 0x20, 0x7B, 0x0D, 0x0A, 0x09, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x20, 86 | 0x31, 0x30, 0x30, 0x25, 0x3B, 0x0D, 0x0A, 0x09, 0x6D, 0x61, 0x78, 0x2D, 0x68, 0x65, 0x69, 0x67, 87 | 0x68, 0x74, 0x3A, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x68, 0x74, 88 | 0x6D, 0x6C, 0x7B, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x36, 0x32, 0x2E, 89 | 0x35, 0x25, 0x3B, 0x7D, 0x0D, 0x0A, 0x0D, 0x0A, 0x2E, 0x6D, 0x61, 0x69, 0x6E, 0x7B, 0x0D, 0x0A, 90 | 0x09, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3A, 0x31, 0x30, 0x30, 0x25, 0x3B, 0x0D, 0x0A, 0x09, 0x6D, 91 | 0x69, 0x6E, 0x2D, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x31, 0x30, 0x30, 0x25, 0x3B, 0x0D, 92 | 0x0A, 0x09, 0x70, 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x3A, 0x72, 0x65, 0x6C, 0x61, 0x74, 93 | 0x69, 0x76, 0x65, 0x3B, 0x0D, 0x0A, 0x09, 0x62, 0x6F, 0x78, 0x2D, 0x73, 0x69, 0x7A, 0x69, 0x6E, 94 | 0x67, 0x3A, 0x20, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x62, 0x6F, 0x78, 0x3B, 0x0D, 0x0A, 95 | 0x09, 0x2D, 0x77, 0x65, 0x62, 0x6B, 0x69, 0x74, 0x2D, 0x62, 0x6F, 0x78, 0x2D, 0x73, 0x69, 0x7A, 96 | 0x69, 0x6E, 0x67, 0x3A, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x62, 0x6F, 0x78, 0x3B, 0x0D, 97 | 0x0A, 0x09, 0x64, 0x69, 0x73, 0x70, 0x6C, 0x61, 0x79, 0x3A, 0x2D, 0x77, 0x65, 0x62, 0x6B, 0x69, 98 | 0x74, 0x2D, 0x62, 0x6F, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x2D, 0x77, 0x65, 0x62, 0x6B, 0x69, 0x74, 99 | 0x2D, 0x62, 0x6F, 0x78, 0x2D, 0x6F, 0x72, 0x69, 0x65, 0x6E, 0x74, 0x3A, 0x76, 0x65, 0x72, 0x74, 100 | 0x69, 0x63, 0x61, 0x6C, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x68, 0x65, 0x61, 0x64, 0x65, 101 | 0x72, 0x20, 0x7B, 0x0D, 0x0A, 0x09, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 102 | 0x3A, 0x20, 0x23, 0x66, 0x35, 0x36, 0x63, 0x36, 0x63, 0x3B, 0x0D, 0x0A, 0x09, 0x68, 0x65, 0x69, 103 | 0x67, 0x68, 0x74, 0x3A, 0x34, 0x38, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x6C, 0x69, 0x6E, 0x65, 104 | 0x2D, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x34, 0x38, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 105 | 0x6F, 0x76, 0x65, 0x72, 0x66, 0x6C, 0x6F, 0x77, 0x3A, 0x20, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6E, 106 | 0x3B, 0x0D, 0x0A, 0x09, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3A, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3B, 107 | 0x0D, 0x0A, 0x09, 0x62, 0x6F, 0x78, 0x2D, 0x73, 0x69, 0x7A, 0x69, 0x6E, 0x67, 0x3A, 0x20, 0x62, 108 | 0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x62, 0x6F, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x70, 0x6F, 0x73, 109 | 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x3A, 0x20, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x69, 0x76, 0x65, 0x3B, 110 | 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x68, 0x33, 0x20, 111 | 0x7B, 0x0D, 0x0A, 0x09, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x20, 0x31, 112 | 0x38, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 0x68, 0x65, 0x69, 0x67, 113 | 0x68, 0x74, 0x3A, 0x20, 0x34, 0x38, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x74, 0x65, 0x78, 0x74, 114 | 0x2D, 0x61, 0x6C, 0x69, 0x67, 0x6E, 0x3A, 0x20, 0x63, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x3B, 0x0D, 115 | 0x0A, 0x09, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x20, 0x23, 0x66, 0x66, 0x66, 0x3B, 0x0D, 0x0A, 116 | 0x7D, 0x0D, 0x0A, 0x2E, 0x62, 0x74, 0x6E, 0x2D, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x20, 0x7B, 117 | 0x0D, 0x0A, 0x09, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x3A, 0x20, 0x63, 118 | 0x65, 0x6E, 0x74, 0x65, 0x72, 0x20, 0x6E, 0x6F, 0x2D, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x3B, 119 | 0x0D, 0x0A, 0x09, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x2D, 0x73, 0x69, 120 | 0x7A, 0x65, 0x3A, 0x20, 0x31, 0x32, 0x70, 0x78, 0x20, 0x32, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 121 | 0x09, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3A, 0x20, 0x34, 0x34, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 122 | 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x20, 0x34, 0x38, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 123 | 0x64, 0x69, 0x73, 0x70, 0x6C, 0x61, 0x79, 0x3A, 0x20, 0x69, 0x6E, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 124 | 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x3B, 0x0D, 0x0A, 0x09, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x73, 0x69, 125 | 0x7A, 0x65, 0x3A, 0x20, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 126 | 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x20, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x6F, 127 | 0x76, 0x65, 0x72, 0x66, 0x6C, 0x6F, 0x77, 0x3A, 0x20, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6E, 0x3B, 128 | 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x2E, 0x62, 0x74, 129 | 0x6E, 0x2D, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x20, 0x7B, 0x0D, 0x0A, 0x09, 0x70, 0x6F, 0x73, 130 | 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x3A, 0x20, 0x61, 0x62, 0x73, 0x6F, 0x6C, 0x75, 0x74, 0x65, 0x3B, 131 | 0x0D, 0x0A, 0x09, 0x6C, 0x65, 0x66, 0x74, 0x3A, 0x20, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 132 | 0x74, 0x6F, 0x70, 0x3A, 0x20, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x77, 133 | 0x69, 0x66, 0x69, 0x2D, 0x66, 0x61, 0x69, 0x6C, 0x20, 0x2E, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 134 | 0x74, 0x7B, 0x0D, 0x0A, 0x09, 0x2D, 0x77, 0x65, 0x62, 0x6B, 0x69, 0x74, 0x2D, 0x62, 0x6F, 0x78, 135 | 0x2D, 0x66, 0x6C, 0x65, 0x78, 0x3A, 0x20, 0x31, 0x3B, 0x20, 0x20, 0x20, 0x20, 0x0D, 0x0A, 0x09, 136 | 0x2D, 0x6D, 0x6F, 0x7A, 0x2D, 0x62, 0x6F, 0x78, 0x2D, 0x66, 0x6C, 0x65, 0x78, 0x3A, 0x20, 0x31, 137 | 0x3B, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0D, 0x0A, 0x09, 0x2D, 0x77, 0x65, 0x62, 138 | 0x6B, 0x69, 0x74, 0x2D, 0x66, 0x6C, 0x65, 0x78, 0x3A, 0x20, 0x31, 0x3B, 0x20, 0x20, 0x20, 0x20, 139 | 0x20, 0x20, 0x20, 0x0D, 0x0A, 0x09, 0x2D, 0x6D, 0x73, 0x2D, 0x66, 0x6C, 0x65, 0x78, 0x3A, 0x20, 140 | 0x31, 0x3B, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0D, 0x0A, 141 | 0x09, 0x66, 0x6C, 0x65, 0x78, 0x3A, 0x20, 0x31, 0x3B, 0x20, 0x0D, 0x0A, 0x09, 0x70, 0x61, 0x64, 142 | 0x64, 0x69, 0x6E, 0x67, 0x3A, 0x31, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x62, 0x61, 0x63, 143 | 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x2D, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x23, 0x46, 144 | 0x46, 0x46, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x77, 0x69, 0x66, 0x69, 0x2D, 0x66, 0x61, 145 | 0x69, 0x6C, 0x20, 0x68, 0x32, 0x7B, 0x0D, 0x0A, 0x09, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x20, 146 | 0x23, 0x66, 0x35, 0x36, 0x63, 0x36, 0x63, 0x3B, 0x0D, 0x0A, 0x09, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 147 | 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x33, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x74, 0x65, 0x78, 148 | 0x74, 0x2D, 0x61, 0x6C, 0x69, 0x67, 0x6E, 0x3A, 0x63, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x3B, 0x0D, 149 | 0x0A, 0x09, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6E, 0x67, 0x3A, 0x33, 0x30, 0x70, 0x78, 0x20, 0x30, 150 | 0x3B, 0x0D, 0x0A, 0x09, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 151 | 0x33, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x77, 0x69, 0x66, 0x69, 0x2D, 152 | 0x66, 0x61, 0x69, 0x6C, 0x20, 0x7B, 0x0D, 0x0A, 0x09, 0x74, 0x65, 0x78, 0x74, 0x2D, 0x69, 0x6E, 153 | 0x64, 0x65, 0x6E, 0x74, 0x3A, 0x32, 0x72, 0x65, 0x6D, 0x3B, 0x0D, 0x0A, 0x09, 0x66, 0x6F, 0x6E, 154 | 0x74, 0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x31, 0x36, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x6C, 155 | 0x69, 0x6E, 0x65, 0x2D, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x32, 0x38, 0x70, 0x78, 0x3B, 156 | 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x62, 0x74, 0x6E, 0x7B, 0x0D, 0x0A, 0x09, 0x74, 0x65, 0x78, 157 | 0x74, 0x2D, 0x64, 0x65, 0x63, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x3A, 0x20, 0x6E, 0x6F, 158 | 0x6E, 0x65, 0x3B, 0x0D, 0x0A, 0x09, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x34, 0x30, 0x70, 159 | 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 160 | 0x3A, 0x34, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x73, 0x69, 161 | 0x7A, 0x65, 0x3A, 0x31, 0x34, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x64, 0x69, 0x73, 0x70, 0x6C, 162 | 0x61, 0x79, 0x3A, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x3B, 0x0D, 0x0A, 0x09, 0x62, 0x6F, 0x72, 0x64, 163 | 0x65, 0x72, 0x3A, 0x20, 0x30, 0x20, 0x6E, 0x6F, 0x6E, 0x65, 0x3B, 0x0D, 0x0A, 0x09, 0x63, 0x6F, 164 | 0x6C, 0x6F, 0x72, 0x3A, 0x20, 0x23, 0x46, 0x46, 0x46, 0x3B, 0x0D, 0x0A, 0x09, 0x62, 0x6F, 0x72, 165 | 0x64, 0x65, 0x72, 0x2D, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3A, 0x20, 0x35, 0x70, 0x78, 0x3B, 166 | 0x0D, 0x0A, 0x09, 0x2D, 0x6D, 0x6F, 0x7A, 0x2D, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x72, 167 | 0x61, 0x64, 0x69, 0x75, 0x73, 0x3A, 0x20, 0x35, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x2D, 0x77, 168 | 0x65, 0x62, 0x6B, 0x69, 0x74, 0x2D, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x72, 0x61, 0x64, 169 | 0x69, 0x75, 0x73, 0x3A, 0x20, 0x35, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x6F, 0x75, 0x74, 0x6C, 170 | 0x69, 0x6E, 0x65, 0x3A, 0x20, 0x6E, 0x6F, 0x6E, 0x65, 0x3B, 0x0D, 0x0A, 0x09, 0x63, 0x75, 0x72, 171 | 0x73, 0x6F, 0x72, 0x3A, 0x20, 0x70, 0x6F, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x3B, 0x0D, 0x0A, 0x09, 172 | 0x74, 0x65, 0x78, 0x74, 0x2D, 0x61, 0x6C, 0x69, 0x67, 0x6E, 0x3A, 0x63, 0x65, 0x6E, 0x74, 0x65, 173 | 0x72, 0x3B, 0x0D, 0x0A, 0x09, 0x6D, 0x69, 0x6E, 0x2D, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3A, 0x37, 174 | 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6E, 0x67, 0x3A, 0x30, 175 | 0x20, 0x31, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x62, 0x74, 0x6E, 0x2D, 176 | 0x72, 0x65, 0x64, 0x7B, 0x0D, 0x0A, 0x09, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 177 | 0x64, 0x2D, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x23, 0x66, 0x35, 0x36, 0x63, 0x36, 0x63, 0x3B, 178 | 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x67, 0x65, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2D, 0x62, 0x74, 179 | 0x6E, 0x20, 0x62, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x20, 0x7B, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 180 | 0x77, 0x69, 0x64, 0x74, 0x68, 0x3A, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3B, 0x0D, 0x0A, 0x09, 0x6D, 181 | 0x61, 0x72, 0x67, 0x69, 0x6E, 0x3A, 0x33, 0x35, 0x70, 0x78, 0x20, 0x30, 0x3B, 0x0D, 0x0A, 0x7D, 182 | 0x0D, 0x0A, 0x3C, 0x2F, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x3C, 0x2F, 0x68, 0x65, 183 | 0x61, 0x64, 0x3E, 0x0D, 0x0A, 0x0D, 0x0A, 0x3C, 0x62, 0x6F, 0x64, 0x79, 0x3E, 0x0D, 0x0A, 0x3C, 184 | 0x64, 0x69, 0x76, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22, 0x6D, 0x61, 0x69, 0x6E, 0x20, 185 | 0x77, 0x69, 0x66, 0x69, 0x2D, 0x66, 0x61, 0x69, 0x6C, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x3C, 186 | 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22, 0x68, 0x65, 187 | 0x61, 0x64, 0x65, 0x72, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 188 | 0x3C, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3D, 0x22, 0x23, 0x22, 0x20, 0x63, 0x6C, 0x61, 0x73, 189 | 0x73, 0x3D, 0x22, 0x62, 0x74, 0x6E, 0x2D, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x22, 0x3E, 0xE4, 190 | 0xB8, 0x8A, 0xE4, 0xB8, 0x80, 0xE9, 0xA1, 0xB5, 0x3C, 0x2F, 0x61, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 191 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x68, 0x33, 0x3E, 0xE7, 0xBD, 0x91, 0xE5, 0x85, 0xB3, 192 | 0xE4, 0xB8, 0x8A, 0xE7, 0xBD, 0x91, 0xE8, 0xAE, 0xBE, 0xE7, 0xBD, 0xAE, 0x3C, 0x2F, 0x68, 0x33, 193 | 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x3E, 194 | 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 195 | 0x3D, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 196 | 0x20, 0x20, 0x20, 0x20, 0x3C, 0x68, 0x32, 0x3E, 0xE8, 0xAE, 0xBE, 0xE7, 0xBD, 0xAE, 0xE5, 0xA4, 197 | 0xB1, 0xE8, 0xB4, 0xA5, 0xEF, 0xBC, 0x81, 0x3C, 0x2F, 0x68, 0x32, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 198 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x63, 0x6C, 199 | 0x61, 0x73, 0x73, 0x3D, 0x22, 0x67, 0x65, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2D, 0x62, 0x74, 0x6E, 200 | 0x22, 0x3E, 0x3C, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3D, 0x22, 0x2F, 0x73, 0x65, 0x74, 0x74, 201 | 0x69, 0x6E, 0x67, 0x2E, 0x68, 0x74, 0x6D, 0x22, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22, 202 | 0x62, 0x74, 0x6E, 0x20, 0x62, 0x74, 0x6E, 0x2D, 0x72, 0x65, 0x64, 0x20, 0x62, 0x74, 0x6E, 0x2D, 203 | 0x74, 0x72, 0x79, 0x22, 0x3E, 0xE5, 0x86, 0x8D, 0xE6, 0xAC, 0xA1, 0xE9, 0x87, 0x8D, 0xE8, 0xAF, 204 | 0x95, 0x3C, 0x2F, 0x61, 0x3E, 0x3C, 0x2F, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 205 | 0x0A, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x64, 0x69, 0x76, 0x3E, 0x0D, 0x0A, 0x3C, 0x2F, 0x64, 206 | 0x69, 0x76, 0x3E, 0x0D, 0x0A, 0x0D, 0x0A, 0x3C, 0x2F, 0x62, 0x6F, 0x64, 0x79, 0x3E, 0x0D, 0x0A, 207 | 0x3C, 0x2F, 0x68, 0x74, 0x6D, 0x6C, 0x3E, 0x0D, 0x0A 208 | }; 209 | 210 | 211 | const unsigned char wifisetting[] = { 212 | 0x3C, 0x21, 0x64, 0x6F, 0x63, 0x74, 0x79, 0x70, 0x65, 0x20, 0x68, 0x74, 0x6D, 0x6C, 0x3E, 0x0D, 213 | 0x0A, 0x3C, 0x68, 0x74, 0x6D, 0x6C, 0x3E, 0x0D, 0x0A, 0x3C, 0x68, 0x65, 0x61, 0x64, 0x3E, 0x0D, 214 | 0x0A, 0x3C, 0x6D, 0x65, 0x74, 0x61, 0x20, 0x68, 0x74, 0x74, 0x70, 0x2D, 0x65, 0x71, 0x75, 0x69, 215 | 0x76, 0x3D, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x2D, 0x74, 0x79, 0x70, 0x65, 0x22, 216 | 0x20, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x3D, 0x22, 0x74, 0x65, 0x78, 0x74, 0x2F, 0x68, 217 | 0x74, 0x6D, 0x6C, 0x22, 0x20, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3D, 0x22, 0x75, 0x74, 218 | 0x66, 0x2D, 0x38, 0x22, 0x3E, 0x0D, 0x0A, 0x3C, 0x6D, 0x65, 0x74, 0x61, 0x20, 0x63, 0x6F, 0x6E, 219 | 0x74, 0x65, 0x6E, 0x74, 0x3D, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3D, 0x64, 0x65, 0x76, 0x69, 220 | 0x63, 0x65, 0x2D, 0x77, 0x69, 0x64, 0x74, 0x68, 0x2C, 0x20, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x61, 221 | 0x6C, 0x2D, 0x73, 0x63, 0x61, 0x6C, 0x65, 0x3D, 0x31, 0x2E, 0x30, 0x2C, 0x20, 0x6D, 0x61, 0x78, 222 | 0x69, 0x6D, 0x75, 0x6D, 0x2D, 0x73, 0x63, 0x61, 0x6C, 0x65, 0x3D, 0x31, 0x2E, 0x30, 0x2C, 0x20, 223 | 0x75, 0x73, 0x65, 0x72, 0x2D, 0x73, 0x63, 0x61, 0x6C, 0x61, 0x62, 0x6C, 0x65, 0x3D, 0x30, 0x22, 224 | 0x20, 0x6E, 0x61, 0x6D, 0x65, 0x3D, 0x22, 0x76, 0x69, 0x65, 0x77, 0x70, 0x6F, 0x72, 0x74, 0x22, 225 | 0x3E, 0x0D, 0x0A, 0x3C, 0x74, 0x69, 0x74, 0x6C, 0x65, 0x3E, 0xE7, 0xBD, 0x91, 0xE5, 0x85, 0xB3, 226 | 0xE4, 0xB8, 0x8A, 0xE7, 0xBD, 0x91, 0xE8, 0xAE, 0xBE, 0xE7, 0xBD, 0xAE, 0x3C, 0x2F, 0x74, 0x69, 227 | 0x74, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x3C, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 228 | 0x20, 0x62, 0x6F, 0x64, 0x79, 0x2C, 0x20, 0x70, 0x2C, 0x20, 0x68, 0x31, 0x2C, 0x20, 0x68, 0x32, 229 | 0x2C, 0x20, 0x68, 0x33, 0x2C, 0x20, 0x68, 0x34, 0x2C, 0x20, 0x68, 0x35, 0x2C, 0x20, 0x68, 0x36, 230 | 0x2C, 0x20, 0x75, 0x6C, 0x2C, 0x20, 0x6F, 0x6C, 0x2C, 0x20, 0x6C, 0x69, 0x2C, 0x20, 0x64, 0x6C, 231 | 0x2C, 0x20, 0x64, 0x74, 0x2C, 0x20, 0x64, 0x64, 0x2C, 0x20, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x2C, 232 | 0x20, 0x74, 0x68, 0x2C, 0x20, 0x74, 0x64, 0x2C, 0x20, 0x66, 0x6F, 0x72, 0x6D, 0x2C, 0x20, 0x66, 233 | 0x69, 0x65, 0x6C, 0x64, 0x73, 0x65, 0x74, 0x2C, 0x20, 0x6C, 0x65, 0x67, 0x65, 0x6E, 0x64, 0x2C, 234 | 0x20, 0x69, 0x6E, 0x70, 0x75, 0x74, 0x2C, 0x20, 0x74, 0x65, 0x78, 0x74, 0x61, 0x72, 0x65, 0x61, 235 | 0x2C, 0x20, 0x62, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x2C, 0x20, 0x73, 0x65, 0x6C, 0x65, 0x63, 0x74, 236 | 0x2C, 0x20, 0x69, 0x6D, 0x67, 0x2C, 0x20, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x71, 0x75, 0x6F, 0x74, 237 | 0x65, 0x20, 0x7B, 0x0D, 0x0A, 0x09, 0x6D, 0x61, 0x72, 0x67, 0x69, 0x6E, 0x3A, 0x20, 0x30, 0x3B, 238 | 0x0D, 0x0A, 0x09, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6E, 0x67, 0x3A, 0x20, 0x30, 0x3B, 0x0D, 0x0A, 239 | 0x09, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x3A, 0x20, 0x30, 0x3B, 0x0D, 0x0A, 0x09, 0x66, 0x6F, 240 | 0x6E, 0x74, 0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3B, 0x0D, 0x0A, 241 | 0x09, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6C, 0x2D, 0x61, 0x6C, 0x69, 0x67, 0x6E, 0x3A, 242 | 0x20, 0x62, 0x61, 0x73, 0x65, 0x6C, 0x69, 0x6E, 0x65, 0x3B, 0x0D, 0x0A, 0x09, 0x66, 0x6F, 0x6E, 243 | 0x74, 0x2D, 0x66, 0x61, 0x6D, 0x69, 0x6C, 0x79, 0x3A, 0x20, 0x22, 0x4D, 0x69, 0x63, 0x72, 0x6F, 244 | 0x73, 0x6F, 0x66, 0x74, 0x20, 0x59, 0x61, 0x48, 0x65, 0x69, 0x22, 0x2C, 0x22, 0x69, 0x63, 0x6F, 245 | 0x6E, 0x66, 0x6F, 0x6E, 0x74, 0x22, 0x2C, 0x22, 0x46, 0x6F, 0x6E, 0x74, 0x41, 0x77, 0x65, 0x73, 246 | 0x6F, 0x6D, 0x65, 0x22, 0x20, 0x20, 0x21, 0x69, 0x6D, 0x70, 0x6F, 0x72, 0x74, 0x61, 0x6E, 0x74, 247 | 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x68, 0x31, 0x2C, 0x20, 0x68, 0x32, 0x2C, 0x20, 0x68, 0x33, 248 | 0x2C, 0x20, 0x68, 0x34, 0x2C, 0x20, 0x68, 0x35, 0x2C, 0x20, 0x68, 0x36, 0x20, 0x7B, 0x0D, 0x0A, 249 | 0x09, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x20, 0x6E, 0x6F, 250 | 0x72, 0x6D, 0x61, 0x6C, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x62, 0x6F, 0x64, 0x79, 0x7B, 0x0D, 251 | 0x0A, 0x09, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x3A, 0x20, 0x23, 0x66, 252 | 0x35, 0x66, 0x35, 0x66, 0x35, 0x0D, 0x0A, 0x09, 0x7D, 0x0D, 0x0A, 0x62, 0x6F, 0x64, 0x79, 0x2C, 253 | 0x20, 0x68, 0x74, 0x6D, 0x6C, 0x20, 0x7B, 0x0D, 0x0A, 0x09, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 254 | 0x3A, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3B, 0x0D, 0x0A, 0x09, 0x6D, 0x61, 0x78, 0x2D, 0x68, 0x65, 255 | 0x69, 0x67, 0x68, 0x74, 0x3A, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 256 | 0x68, 0x74, 0x6D, 0x6C, 0x7B, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x36, 257 | 0x32, 0x2E, 0x35, 0x25, 0x3B, 0x7D, 0x0D, 0x0A, 0x2E, 0x6D, 0x61, 0x69, 0x6E, 0x7B, 0x0D, 0x0A, 258 | 0x09, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3A, 0x31, 0x30, 0x30, 0x25, 0x3B, 0x0D, 0x0A, 0x09, 0x6D, 259 | 0x69, 0x6E, 0x2D, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x31, 0x30, 0x30, 0x25, 0x3B, 0x0D, 260 | 0x0A, 0x09, 0x70, 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x3A, 0x72, 0x65, 0x6C, 0x61, 0x74, 261 | 0x69, 0x76, 0x65, 0x3B, 0x0D, 0x0A, 0x09, 0x62, 0x6F, 0x78, 0x2D, 0x73, 0x69, 0x7A, 0x69, 0x6E, 262 | 0x67, 0x3A, 0x20, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x62, 0x6F, 0x78, 0x3B, 0x0D, 0x0A, 263 | 0x09, 0x2D, 0x77, 0x65, 0x62, 0x6B, 0x69, 0x74, 0x2D, 0x62, 0x6F, 0x78, 0x2D, 0x73, 0x69, 0x7A, 264 | 0x69, 0x6E, 0x67, 0x3A, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x62, 0x6F, 0x78, 0x3B, 0x0D, 265 | 0x0A, 0x09, 0x64, 0x69, 0x73, 0x70, 0x6C, 0x61, 0x79, 0x3A, 0x2D, 0x77, 0x65, 0x62, 0x6B, 0x69, 266 | 0x74, 0x2D, 0x62, 0x6F, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x2D, 0x77, 0x65, 0x62, 0x6B, 0x69, 0x74, 267 | 0x2D, 0x62, 0x6F, 0x78, 0x2D, 0x6F, 0x72, 0x69, 0x65, 0x6E, 0x74, 0x3A, 0x76, 0x65, 0x72, 0x74, 268 | 0x69, 0x63, 0x61, 0x6C, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x68, 0x65, 0x61, 0x64, 0x65, 269 | 0x72, 0x20, 0x7B, 0x0D, 0x0A, 0x09, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 270 | 0x3A, 0x20, 0x23, 0x66, 0x35, 0x36, 0x63, 0x36, 0x63, 0x3B, 0x0D, 0x0A, 0x09, 0x68, 0x65, 0x69, 271 | 0x67, 0x68, 0x74, 0x3A, 0x34, 0x38, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x6C, 0x69, 0x6E, 0x65, 272 | 0x2D, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x34, 0x38, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 273 | 0x6F, 0x76, 0x65, 0x72, 0x66, 0x6C, 0x6F, 0x77, 0x3A, 0x20, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6E, 274 | 0x3B, 0x0D, 0x0A, 0x09, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3A, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3B, 275 | 0x0D, 0x0A, 0x09, 0x62, 0x6F, 0x78, 0x2D, 0x73, 0x69, 0x7A, 0x69, 0x6E, 0x67, 0x3A, 0x20, 0x62, 276 | 0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x62, 0x6F, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x70, 0x6F, 0x73, 277 | 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x3A, 0x20, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x69, 0x76, 0x65, 0x3B, 278 | 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x68, 0x33, 0x20, 279 | 0x7B, 0x0D, 0x0A, 0x09, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x20, 0x31, 280 | 0x38, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 0x68, 0x65, 0x69, 0x67, 281 | 0x68, 0x74, 0x3A, 0x20, 0x34, 0x38, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x74, 0x65, 0x78, 0x74, 282 | 0x2D, 0x61, 0x6C, 0x69, 0x67, 0x6E, 0x3A, 0x20, 0x63, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x3B, 0x0D, 283 | 0x0A, 0x09, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x20, 0x23, 0x66, 0x66, 0x66, 0x3B, 0x0D, 0x0A, 284 | 0x7D, 0x0D, 0x0A, 0x2E, 0x62, 0x74, 0x6E, 0x2D, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x20, 0x7B, 285 | 0x0D, 0x0A, 0x09, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x3A, 0x20, 0x75, 286 | 0x72, 0x6C, 0x28, 0x2E, 0x2E, 0x2F, 0x69, 0x6D, 0x61, 0x67, 0x65, 0x73, 0x2F, 0x69, 0x63, 0x6F, 287 | 0x6E, 0x30, 0x34, 0x2E, 0x70, 0x6E, 0x67, 0x29, 0x20, 0x63, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x20, 288 | 0x6E, 0x6F, 0x2D, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x3B, 0x0D, 0x0A, 0x09, 0x62, 0x61, 0x63, 289 | 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x20, 0x31, 0x32, 290 | 0x70, 0x78, 0x20, 0x32, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x77, 0x69, 0x64, 0x74, 0x68, 291 | 0x3A, 0x20, 0x34, 0x34, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 292 | 0x3A, 0x20, 0x34, 0x38, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x64, 0x69, 0x73, 0x70, 0x6C, 0x61, 293 | 0x79, 0x3A, 0x20, 0x69, 0x6E, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x3B, 294 | 0x0D, 0x0A, 0x09, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x20, 0x30, 0x70, 295 | 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 296 | 0x3A, 0x20, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x6F, 0x76, 0x65, 0x72, 0x66, 0x6C, 0x6F, 297 | 0x77, 0x3A, 0x20, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6E, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 298 | 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x2E, 0x62, 0x74, 0x6E, 0x2D, 0x72, 0x65, 0x74, 0x75, 299 | 0x72, 0x6E, 0x20, 0x7B, 0x0D, 0x0A, 0x09, 0x70, 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x3A, 300 | 0x20, 0x61, 0x62, 0x73, 0x6F, 0x6C, 0x75, 0x74, 0x65, 0x3B, 0x0D, 0x0A, 0x09, 0x6C, 0x65, 0x66, 301 | 0x74, 0x3A, 0x20, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x74, 0x6F, 0x70, 0x3A, 0x20, 0x30, 302 | 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x77, 0x69, 0x66, 0x69, 0x2D, 0x73, 0x65, 303 | 0x74, 0x20, 0x2E, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x7B, 0x0D, 0x0A, 0x09, 0x6D, 0x61, 304 | 0x72, 0x67, 0x69, 0x6E, 0x3A, 0x31, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x2D, 0x77, 0x65, 305 | 0x62, 0x6B, 0x69, 0x74, 0x2D, 0x62, 0x6F, 0x78, 0x2D, 0x66, 0x6C, 0x65, 0x78, 0x3A, 0x20, 0x31, 306 | 0x3B, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x2D, 0x6D, 0x6F, 0x7A, 0x2D, 0x62, 0x6F, 0x78, 0x2D, 307 | 0x66, 0x6C, 0x65, 0x78, 0x3A, 0x20, 0x31, 0x3B, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x2D, 0x77, 308 | 0x65, 0x62, 0x6B, 0x69, 0x74, 0x2D, 0x66, 0x6C, 0x65, 0x78, 0x3A, 0x20, 0x31, 0x3B, 0x0D, 0x0A, 309 | 0x20, 0x20, 0x20, 0x20, 0x2D, 0x6D, 0x73, 0x2D, 0x66, 0x6C, 0x65, 0x78, 0x3A, 0x20, 0x31, 0x3B, 310 | 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6C, 0x65, 0x78, 0x3A, 0x20, 0x31, 0x3B, 0x0D, 0x0A, 311 | 0x7D, 0x0D, 0x0A, 0x2E, 0x67, 0x65, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2D, 0x69, 0x6E, 0x66, 0x6F, 312 | 0x2D, 0x62, 0x6F, 0x78, 0x20, 0x2E, 0x69, 0x6E, 0x70, 0x75, 0x74, 0x2D, 0x66, 0x69, 0x65, 0x6C, 313 | 0x64, 0x7B, 0x0D, 0x0A, 0x09, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 314 | 0x3A, 0x32, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 315 | 0x6C, 0x2D, 0x61, 0x6C, 0x69, 0x67, 0x6E, 0x3A, 0x6D, 0x69, 0x64, 0x64, 0x6C, 0x65, 0x3B, 0x0D, 316 | 0x0A, 0x09, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x3A, 0x20, 0x31, 0x70, 0x78, 0x20, 0x73, 0x6F, 317 | 0x6C, 0x69, 0x64, 0x20, 0x23, 0x64, 0x37, 0x64, 0x37, 0x64, 0x37, 0x3B, 0x0D, 0x0A, 0x20, 0x20, 318 | 0x20, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x20, 0x35, 0x38, 0x70, 0x78, 0x3B, 0x0D, 319 | 0x0A, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x3A, 320 | 0x20, 0x23, 0x66, 0x66, 0x66, 0x3B, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6F, 0x78, 0x2D, 321 | 0x73, 0x69, 0x7A, 0x69, 0x6E, 0x67, 0x3A, 0x20, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x62, 322 | 0x6F, 0x78, 0x3B, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x70, 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F, 323 | 0x6E, 0x3A, 0x20, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x69, 0x76, 0x65, 0x3B, 0x0D, 0x0A, 0x20, 0x20, 324 | 0x20, 0x20, 0x6D, 0x61, 0x72, 0x67, 0x69, 0x6E, 0x2D, 0x62, 0x6F, 0x74, 0x74, 0x6F, 0x6D, 0x3A, 325 | 0x20, 0x2D, 0x31, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 326 | 0x69, 0x6E, 0x67, 0x3A, 0x20, 0x31, 0x39, 0x70, 0x78, 0x20, 0x31, 0x35, 0x70, 0x78, 0x20, 0x31, 327 | 0x39, 0x70, 0x78, 0x20, 0x31, 0x38, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x69, 328 | 0x6E, 0x70, 0x75, 0x74, 0x2D, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x69, 0x6E, 0x70, 0x75, 0x74, 329 | 0x20, 0x7B, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x20, 330 | 0x32, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 331 | 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x20, 0x32, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x20, 332 | 0x20, 0x20, 0x20, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x20, 0x31, 0x34, 333 | 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3A, 0x20, 334 | 0x31, 0x30, 0x30, 0x25, 0x3B, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6F, 0x72, 0x64, 0x65, 335 | 0x72, 0x3A, 0x20, 0x30, 0x20, 0x6E, 0x6F, 0x6E, 0x65, 0x3B, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 336 | 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x3A, 0x20, 0x74, 0x72, 0x61, 0x6E, 337 | 0x73, 0x70, 0x61, 0x72, 0x65, 0x6E, 0x74, 0x3B, 0x0D, 0x0A, 0x09, 0x6F, 0x75, 0x74, 0x6C, 0x69, 338 | 0x6E, 0x65, 0x3A, 0x20, 0x6D, 0x65, 0x64, 0x69, 0x75, 0x6D, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 339 | 0x2E, 0x69, 0x6E, 0x70, 0x75, 0x74, 0x2D, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x3A, 0x66, 0x69, 0x72, 340 | 0x73, 0x74, 0x2D, 0x6F, 0x66, 0x2D, 0x74, 0x79, 0x70, 0x65, 0x20, 0x7B, 0x0D, 0x0A, 0x20, 0x20, 341 | 0x20, 0x20, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x74, 0x6F, 0x70, 0x2D, 0x6C, 0x65, 0x66, 342 | 0x74, 0x2D, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3A, 0x20, 0x35, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 343 | 0x20, 0x20, 0x20, 0x20, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x74, 0x6F, 0x70, 0x2D, 0x72, 344 | 0x69, 0x67, 0x68, 0x74, 0x2D, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3A, 0x20, 0x35, 0x70, 0x78, 345 | 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x69, 0x6E, 0x70, 0x75, 0x74, 0x2D, 0x66, 0x69, 0x65, 346 | 0x6C, 0x64, 0x3A, 0x6C, 0x61, 0x73, 0x74, 0x2D, 0x6F, 0x66, 0x2D, 0x74, 0x79, 0x70, 0x65, 0x20, 347 | 0x7B, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x62, 0x6F, 348 | 0x74, 0x74, 0x6F, 0x6D, 0x2D, 0x6C, 0x65, 0x66, 0x74, 0x2D, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 349 | 0x3A, 0x20, 0x35, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6F, 0x72, 0x64, 350 | 0x65, 0x72, 0x2D, 0x62, 0x6F, 0x74, 0x74, 0x6F, 0x6D, 0x2D, 0x72, 0x69, 0x67, 0x68, 0x74, 0x2D, 351 | 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3A, 0x20, 0x35, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 352 | 0x0A, 0x2E, 0x62, 0x74, 0x6E, 0x7B, 0x0D, 0x0A, 0x09, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 353 | 0x34, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 0x68, 0x65, 0x69, 354 | 0x67, 0x68, 0x74, 0x3A, 0x34, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x66, 0x6F, 0x6E, 0x74, 355 | 0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x31, 0x34, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x64, 0x69, 356 | 0x73, 0x70, 0x6C, 0x61, 0x79, 0x3A, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x3B, 0x0D, 0x0A, 0x09, 0x62, 357 | 0x6F, 0x72, 0x64, 0x65, 0x72, 0x3A, 0x20, 0x30, 0x20, 0x6E, 0x6F, 0x6E, 0x65, 0x3B, 0x0D, 0x0A, 358 | 0x09, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x20, 0x23, 0x46, 0x46, 0x46, 0x3B, 0x0D, 0x0A, 0x09, 359 | 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3A, 0x20, 0x35, 360 | 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x2D, 0x6D, 0x6F, 0x7A, 0x2D, 0x62, 0x6F, 0x72, 0x64, 0x65, 361 | 0x72, 0x2D, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3A, 0x20, 0x35, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 362 | 0x09, 0x2D, 0x77, 0x65, 0x62, 0x6B, 0x69, 0x74, 0x2D, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 363 | 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3A, 0x20, 0x35, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x6F, 364 | 0x75, 0x74, 0x6C, 0x69, 0x6E, 0x65, 0x3A, 0x20, 0x6E, 0x6F, 0x6E, 0x65, 0x3B, 0x0D, 0x0A, 0x09, 365 | 0x63, 0x75, 0x72, 0x73, 0x6F, 0x72, 0x3A, 0x20, 0x70, 0x6F, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x3B, 366 | 0x0D, 0x0A, 0x09, 0x74, 0x65, 0x78, 0x74, 0x2D, 0x61, 0x6C, 0x69, 0x67, 0x6E, 0x3A, 0x63, 0x65, 367 | 0x6E, 0x74, 0x65, 0x72, 0x3B, 0x0D, 0x0A, 0x09, 0x6D, 0x69, 0x6E, 0x2D, 0x77, 0x69, 0x64, 0x74, 368 | 0x68, 0x3A, 0x37, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6E, 369 | 0x67, 0x3A, 0x30, 0x20, 0x31, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x62, 370 | 0x74, 0x6E, 0x2D, 0x72, 0x65, 0x64, 0x7B, 0x0D, 0x0A, 0x09, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 371 | 0x6F, 0x75, 0x6E, 0x64, 0x2D, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x23, 0x66, 0x35, 0x36, 0x63, 372 | 0x36, 0x63, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x67, 0x65, 0x74, 0x65, 0x77, 0x61, 0x79, 373 | 0x2D, 0x62, 0x74, 0x6E, 0x20, 0x62, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x20, 0x7B, 0x0D, 0x0A, 0x20, 374 | 0x20, 0x20, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3A, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3B, 0x0D, 375 | 0x0A, 0x09, 0x6D, 0x61, 0x72, 0x67, 0x69, 0x6E, 0x3A, 0x33, 0x35, 0x70, 0x78, 0x20, 0x30, 0x3B, 376 | 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x3C, 0x2F, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x0D, 377 | 0x0A, 0x3C, 0x2F, 0x68, 0x65, 0x61, 0x64, 0x3E, 0x0D, 0x0A, 0x0D, 0x0A, 0x3C, 0x62, 0x6F, 0x64, 378 | 0x79, 0x3E, 0x0D, 0x0A, 0x3C, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22, 379 | 0x6D, 0x61, 0x69, 0x6E, 0x20, 0x77, 0x69, 0x66, 0x69, 0x2D, 0x73, 0x65, 0x74, 0x22, 0x3E, 0x0D, 380 | 0x0A, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x20, 0x63, 0x6C, 381 | 0x61, 0x73, 0x73, 0x3D, 0x22, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 382 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3D, 0x22, 383 | 0x23, 0x22, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22, 0x62, 0x74, 0x6E, 0x2D, 0x72, 0x65, 384 | 0x74, 0x75, 0x72, 0x6E, 0x22, 0x3E, 0xE4, 0xB8, 0x8A, 0xE4, 0xB8, 0x80, 0xE9, 0xA1, 0xB5, 0x3C, 385 | 0x2F, 0x61, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x68, 0x33, 386 | 0x3E, 0xE7, 0xBD, 0x91, 0xE5, 0x85, 0xB3, 0xE4, 0xB8, 0x8A, 0xE7, 0xBD, 0x91, 0xE8, 0xAE, 0xBE, 387 | 0xE7, 0xBD, 0xAE, 0x3C, 0x2F, 0x68, 0x33, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 388 | 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 389 | 0x76, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 390 | 0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x3C, 0x66, 0x6F, 0x72, 0x6D, 0x20, 0x61, 0x63, 0x74, 0x69, 0x6F, 391 | 0x6E, 0x3D, 0x22, 0x72, 0x65, 0x73, 0x75, 0x6C, 0x74, 0x2E, 0x68, 0x74, 0x6D, 0x22, 0x20, 0x6D, 392 | 0x65, 0x74, 0x68, 0x6F, 0x64, 0x3D, 0x22, 0x70, 0x6F, 0x73, 0x74, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 393 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x63, 394 | 0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22, 0x67, 0x65, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2D, 0x69, 0x6E, 395 | 0x66, 0x6F, 0x2D, 0x62, 0x6F, 0x78, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 396 | 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22, 397 | 0x69, 0x6E, 0x70, 0x75, 0x74, 0x2D, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 398 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x69, 0x6E, 0x70, 399 | 0x75, 0x74, 0x20, 0x69, 0x64, 0x3D, 0x22, 0x73, 0x73, 0x69, 0x64, 0x22, 0x20, 0x74, 0x79, 0x70, 400 | 0x65, 0x3D, 0x22, 0x74, 0x65, 0x78, 0x74, 0x22, 0x20, 0x6E, 0x61, 0x6D, 0x65, 0x3D, 0x22, 0x53, 401 | 0x53, 0x49, 0x44, 0x22, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x3D, 0x22, 0x22, 0x20, 0x70, 0x6C, 402 | 0x61, 0x63, 0x65, 0x68, 0x6F, 0x6C, 0x64, 0x65, 0x72, 0x3D, 0x22, 0x57, 0x49, 0x46, 0x49, 0xE5, 403 | 0x90, 0x8D, 0xE7, 0xA7, 0xB0, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 404 | 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x64, 0x69, 0x76, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 405 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, 406 | 0x22, 0x69, 0x6E, 0x70, 0x75, 0x74, 0x2D, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x22, 0x3E, 0x0D, 0x0A, 407 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x69, 0x6E, 408 | 0x70, 0x75, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3D, 0x22, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6F, 409 | 0x72, 0x64, 0x22, 0x20, 0x6E, 0x61, 0x6D, 0x65, 0x3D, 0x22, 0x50, 0x41, 0x53, 0x53, 0x22, 0x20, 410 | 0x76, 0x61, 0x6C, 0x75, 0x65, 0x3D, 0x22, 0x22, 0x20, 0x70, 0x6C, 0x61, 0x63, 0x65, 0x68, 0x6F, 411 | 0x6C, 0x64, 0x65, 0x72, 0x3D, 0x22, 0xE8, 0xBE, 0x93, 0xE5, 0x85, 0xA5, 0xE5, 0xAF, 0x86, 0xE7, 412 | 0xA0, 0x81, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 413 | 0x3C, 0x2F, 0x64, 0x69, 0x76, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 414 | 415 | 0x20, 0x20, 0x3C, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22, 0x69, 0x6E, 416 | 0x70, 0x75, 0x74, 0x2D, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 417 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x69, 0x6E, 0x70, 0x75, 0x74, 418 | 0x20, 0x74, 0x79, 0x70, 0x65, 0x3D, 0x22, 0x75, 0x73, 0x65, 0x72, 0x22, 0x20, 0x6E, 0x61, 0x6D, 419 | 0x65, 0x3D, 0x22, 0x55, 0x53, 0x45, 0x52, 0x22, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x3D, 0x22, 420 | 0x22, 0x20, 0x70, 0x6C, 0x61, 0x63, 0x65, 0x68, 0x6F, 0x6C, 0x64, 0x65, 0x72, 0x3D, 0x22, 0xE8, 421 | 0xBE, 0x93, 0xE5, 0x85, 0xA5, 0xE7, 0x99, 0xBB, 0xE5, 0xBD, 0x95, 0xE9, 0x82, 0xAE, 0xE7, 0xAE, 422 | 0xB1, 0x2C, 0xE6, 0xB3, 0xA8, 0xE6, 0x84, 0x8F, 0xE7, 0x94, 0xA8, 0xE6, 0x88, 0xB7, 0xE8, 0xBE, 423 | 0x93, 0xE5, 0x85, 0xA5, 0xE9, 0x94, 0x99, 0xE8, 0xAF, 0xAF, 0xE5, 0xB0, 0x86, 0xE5, 0xAF, 0xBC, 424 | 0xE8, 0x87, 0xB4, 0xE6, 0x97, 0xA0, 0xE6, 0xB3, 0x95, 0xE7, 0xBB, 0x91, 0xE5, 0xAE, 0x9A, 0xE8, 425 | 0xAE, 0xBE, 0xE5, 0xA4, 0x87, 0x21, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 426 | 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x64, 0x69, 0x76, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 427 | 0x20, 0x20, 0x20, 0x20, 428 | 429 | 0x3C, 0x2F, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 430 | 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x63, 0x6C, 0x61, 431 | 0x73, 0x73, 0x3D, 0x22, 0x67, 0x65, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2D, 0x62, 0x74, 0x6E, 0x22, 432 | 0x3E, 0x3C, 0x62, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3D, 0x22, 0x73, 433 | 0x75, 0x62, 0x6D, 0x69, 0x74, 0x22, 0x20, 0x6E, 0x61, 0x6D, 0x65, 0x3D, 0x22, 0x6E, 0x65, 0x78, 434 | 0x74, 0x22, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22, 0x62, 0x74, 0x6E, 0x20, 0x62, 0x74, 435 | 0x6E, 0x2D, 0x72, 0x65, 0x64, 0x20, 0x62, 0x74, 0x6E, 0x2D, 0x6E, 0x65, 0x78, 0x74, 0x22, 0x3E, 436 | 0xE4, 0xB8, 0x8B, 0xE4, 0xB8, 0x80, 0xE6, 0xAD, 0xA5, 0x3C, 0x2F, 0x62, 0x75, 0x74, 0x74, 0x6F, 437 | 0x6E, 0x3E, 0x3C, 0x2F, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x3C, 438 | 0x2F, 0x66, 0x6F, 0x72, 0x6D, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x64, 0x69, 439 | 0x76, 0x3E, 0x0D, 0x0A, 0x3C, 0x2F, 0x64, 0x69, 0x76, 0x3E, 0x0D, 0x0A, 0x3C, 0x2F, 0x62, 0x6F, 440 | 0x64, 0x79, 0x3E, 0x0D, 0x0A, 0x3C, 0x2F, 0x68, 0x74, 0x6D, 0x6C, 0x3E, 0x0D, 0x0A 441 | }; 442 | 443 | const unsigned char wifisuccess[0x9BC] = { 444 | 0x3C, 0x21, 0x64, 0x6F, 0x63, 0x74, 0x79, 0x70, 0x65, 0x20, 0x68, 0x74, 0x6D, 0x6C, 0x3E, 0x0D, 445 | 0x0A, 0x3C, 0x68, 0x74, 0x6D, 0x6C, 0x3E, 0x0D, 0x0A, 0x3C, 0x68, 0x65, 0x61, 0x64, 0x3E, 0x0D, 446 | 0x0A, 0x3C, 0x6D, 0x65, 0x74, 0x61, 0x20, 0x68, 0x74, 0x74, 0x70, 0x2D, 0x65, 0x71, 0x75, 0x69, 447 | 0x76, 0x3D, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x2D, 0x74, 0x79, 0x70, 0x65, 0x22, 448 | 0x20, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x3D, 0x22, 0x74, 0x65, 0x78, 0x74, 0x2F, 0x68, 449 | 0x74, 0x6D, 0x6C, 0x22, 0x20, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3D, 0x22, 0x75, 0x74, 450 | 0x66, 0x2D, 0x38, 0x22, 0x3E, 0x0D, 0x0A, 0x3C, 0x6D, 0x65, 0x74, 0x61, 0x20, 0x63, 0x6F, 0x6E, 451 | 0x74, 0x65, 0x6E, 0x74, 0x3D, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3D, 0x64, 0x65, 0x76, 0x69, 452 | 0x63, 0x65, 0x2D, 0x77, 0x69, 0x64, 0x74, 0x68, 0x2C, 0x20, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x61, 453 | 0x6C, 0x2D, 0x73, 0x63, 0x61, 0x6C, 0x65, 0x3D, 0x31, 0x2E, 0x30, 0x2C, 0x20, 0x6D, 0x61, 0x78, 454 | 0x69, 0x6D, 0x75, 0x6D, 0x2D, 0x73, 0x63, 0x61, 0x6C, 0x65, 0x3D, 0x31, 0x2E, 0x30, 0x2C, 0x20, 455 | 0x75, 0x73, 0x65, 0x72, 0x2D, 0x73, 0x63, 0x61, 0x6C, 0x61, 0x62, 0x6C, 0x65, 0x3D, 0x30, 0x22, 456 | 0x20, 0x6E, 0x61, 0x6D, 0x65, 0x3D, 0x22, 0x76, 0x69, 0x65, 0x77, 0x70, 0x6F, 0x72, 0x74, 0x22, 457 | 0x3E, 0x0D, 0x0A, 0x3C, 0x74, 0x69, 0x74, 0x6C, 0x65, 0x3E, 0xE7, 0xBD, 0x91, 0xE5, 0x85, 0xB3, 458 | 0xE4, 0xB8, 0x8A, 0xE7, 0xBD, 0x91, 0xE8, 0xAE, 0xBE, 0xE7, 0xBD, 0xAE, 0x3C, 0x2F, 0x74, 0x69, 459 | 0x74, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x3C, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 460 | 0x62, 0x6F, 0x64, 0x79, 0x2C, 0x20, 0x70, 0x2C, 0x20, 0x68, 0x31, 0x2C, 0x20, 0x68, 0x32, 0x2C, 461 | 0x20, 0x68, 0x33, 0x2C, 0x20, 0x68, 0x34, 0x2C, 0x20, 0x68, 0x35, 0x2C, 0x20, 0x68, 0x36, 0x2C, 462 | 0x20, 0x75, 0x6C, 0x2C, 0x20, 0x6F, 0x6C, 0x2C, 0x20, 0x6C, 0x69, 0x2C, 0x20, 0x64, 0x6C, 0x2C, 463 | 0x20, 0x64, 0x74, 0x2C, 0x20, 0x64, 0x64, 0x2C, 0x20, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x2C, 0x20, 464 | 0x74, 0x68, 0x2C, 0x20, 0x74, 0x64, 0x2C, 0x20, 0x66, 0x6F, 0x72, 0x6D, 0x2C, 0x20, 0x66, 0x69, 465 | 0x65, 0x6C, 0x64, 0x73, 0x65, 0x74, 0x2C, 0x20, 0x6C, 0x65, 0x67, 0x65, 0x6E, 0x64, 0x2C, 0x20, 466 | 0x69, 0x6E, 0x70, 0x75, 0x74, 0x2C, 0x20, 0x74, 0x65, 0x78, 0x74, 0x61, 0x72, 0x65, 0x61, 0x2C, 467 | 0x20, 0x62, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x2C, 0x20, 0x73, 0x65, 0x6C, 0x65, 0x63, 0x74, 0x2C, 468 | 0x20, 0x69, 0x6D, 0x67, 0x2C, 0x20, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x71, 0x75, 0x6F, 0x74, 0x65, 469 | 0x20, 0x7B, 0x0D, 0x0A, 0x09, 0x6D, 0x61, 0x72, 0x67, 0x69, 0x6E, 0x3A, 0x20, 0x30, 0x3B, 0x0D, 470 | 0x0A, 0x09, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6E, 0x67, 0x3A, 0x20, 0x30, 0x3B, 0x0D, 0x0A, 0x09, 471 | 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x3A, 0x20, 0x30, 0x3B, 0x0D, 0x0A, 0x09, 0x66, 0x6F, 0x6E, 472 | 0x74, 0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3B, 0x0D, 0x0A, 0x09, 473 | 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6C, 0x2D, 0x61, 0x6C, 0x69, 0x67, 0x6E, 0x3A, 0x20, 474 | 0x62, 0x61, 0x73, 0x65, 0x6C, 0x69, 0x6E, 0x65, 0x3B, 0x0D, 0x0A, 0x09, 0x66, 0x6F, 0x6E, 0x74, 475 | 0x2D, 0x66, 0x61, 0x6D, 0x69, 0x6C, 0x79, 0x3A, 0x20, 0x22, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 476 | 0x6F, 0x66, 0x74, 0x20, 0x59, 0x61, 0x48, 0x65, 0x69, 0x22, 0x2C, 0x22, 0x69, 0x63, 0x6F, 0x6E, 477 | 0x66, 0x6F, 0x6E, 0x74, 0x22, 0x2C, 0x22, 0x46, 0x6F, 0x6E, 0x74, 0x41, 0x77, 0x65, 0x73, 0x6F, 478 | 0x6D, 0x65, 0x22, 0x20, 0x20, 0x21, 0x69, 0x6D, 0x70, 0x6F, 0x72, 0x74, 0x61, 0x6E, 0x74, 0x3B, 479 | 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x68, 0x31, 0x2C, 0x20, 0x68, 0x32, 0x2C, 0x20, 0x68, 0x33, 0x2C, 480 | 0x20, 0x68, 0x34, 0x2C, 0x20, 0x68, 0x35, 0x2C, 0x20, 0x68, 0x36, 0x20, 0x7B, 0x0D, 0x0A, 0x09, 481 | 0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x20, 0x6E, 0x6F, 0x72, 482 | 0x6D, 0x61, 0x6C, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x62, 0x6F, 0x64, 0x79, 0x7B, 0x0D, 0x0A, 483 | 0x09, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x3A, 0x20, 0x23, 0x66, 0x35, 484 | 0x66, 0x35, 0x66, 0x35, 0x0D, 0x0A, 0x09, 0x7D, 0x0D, 0x0A, 0x62, 0x6F, 0x64, 0x79, 0x2C, 0x20, 485 | 0x68, 0x74, 0x6D, 0x6C, 0x20, 0x7B, 0x0D, 0x0A, 0x09, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 486 | 0x20, 0x31, 0x30, 0x30, 0x25, 0x3B, 0x0D, 0x0A, 0x09, 0x6D, 0x61, 0x78, 0x2D, 0x68, 0x65, 0x69, 487 | 0x67, 0x68, 0x74, 0x3A, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x68, 488 | 0x74, 0x6D, 0x6C, 0x7B, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x36, 0x32, 489 | 0x2E, 0x35, 0x25, 0x3B, 0x7D, 0x0D, 0x0A, 0x2E, 0x6D, 0x61, 0x69, 0x6E, 0x7B, 0x0D, 0x0A, 0x09, 490 | 0x77, 0x69, 0x64, 0x74, 0x68, 0x3A, 0x31, 0x30, 0x30, 0x25, 0x3B, 0x0D, 0x0A, 0x09, 0x6D, 0x69, 491 | 0x6E, 0x2D, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x31, 0x30, 0x30, 0x25, 0x3B, 0x0D, 0x0A, 492 | 0x09, 0x70, 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x3A, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x69, 493 | 0x76, 0x65, 0x3B, 0x0D, 0x0A, 0x09, 0x62, 0x6F, 0x78, 0x2D, 0x73, 0x69, 0x7A, 0x69, 0x6E, 0x67, 494 | 0x3A, 0x20, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x62, 0x6F, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 495 | 0x2D, 0x77, 0x65, 0x62, 0x6B, 0x69, 0x74, 0x2D, 0x62, 0x6F, 0x78, 0x2D, 0x73, 0x69, 0x7A, 0x69, 496 | 0x6E, 0x67, 0x3A, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x62, 0x6F, 0x78, 0x3B, 0x0D, 0x0A, 497 | 0x09, 0x64, 0x69, 0x73, 0x70, 0x6C, 0x61, 0x79, 0x3A, 0x2D, 0x77, 0x65, 0x62, 0x6B, 0x69, 0x74, 498 | 0x2D, 0x62, 0x6F, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x2D, 0x77, 0x65, 0x62, 0x6B, 0x69, 0x74, 0x2D, 499 | 0x62, 0x6F, 0x78, 0x2D, 0x6F, 0x72, 0x69, 0x65, 0x6E, 0x74, 0x3A, 0x76, 0x65, 0x72, 0x74, 0x69, 500 | 0x63, 0x61, 0x6C, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 501 | 0x20, 0x7B, 0x0D, 0x0A, 0x09, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x3A, 502 | 0x20, 0x23, 0x66, 0x35, 0x36, 0x63, 0x36, 0x63, 0x3B, 0x0D, 0x0A, 0x09, 0x68, 0x65, 0x69, 0x67, 503 | 0x68, 0x74, 0x3A, 0x34, 0x38, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 504 | 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x34, 0x38, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x6F, 505 | 0x76, 0x65, 0x72, 0x66, 0x6C, 0x6F, 0x77, 0x3A, 0x20, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6E, 0x3B, 506 | 0x0D, 0x0A, 0x09, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3A, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3B, 0x0D, 507 | 0x0A, 0x09, 0x62, 0x6F, 0x78, 0x2D, 0x73, 0x69, 0x7A, 0x69, 0x6E, 0x67, 0x3A, 0x20, 0x62, 0x6F, 508 | 0x72, 0x64, 0x65, 0x72, 0x2D, 0x62, 0x6F, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x70, 0x6F, 0x73, 0x69, 509 | 0x74, 0x69, 0x6F, 0x6E, 0x3A, 0x20, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x69, 0x76, 0x65, 0x3B, 0x0D, 510 | 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x68, 0x33, 0x20, 0x7B, 511 | 0x0D, 0x0A, 0x09, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x20, 0x31, 0x38, 512 | 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 0x68, 0x65, 0x69, 0x67, 0x68, 513 | 0x74, 0x3A, 0x20, 0x34, 0x38, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x74, 0x65, 0x78, 0x74, 0x2D, 514 | 0x61, 0x6C, 0x69, 0x67, 0x6E, 0x3A, 0x20, 0x63, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x3B, 0x0D, 0x0A, 515 | 0x09, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x20, 0x23, 0x66, 0x66, 0x66, 0x3B, 0x0D, 0x0A, 0x7D, 516 | 0x0D, 0x0A, 0x2E, 0x62, 0x74, 0x6E, 0x2D, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x20, 0x7B, 0x0D, 517 | 0x0A, 0x09, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x3A, 0x20, 0x63, 0x65, 518 | 0x6E, 0x74, 0x65, 0x72, 0x20, 0x6E, 0x6F, 0x2D, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x3B, 0x0D, 519 | 0x0A, 0x09, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x2D, 0x73, 0x69, 0x7A, 520 | 0x65, 0x3A, 0x20, 0x31, 0x32, 0x70, 0x78, 0x20, 0x32, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 521 | 0x77, 0x69, 0x64, 0x74, 0x68, 0x3A, 0x20, 0x34, 0x34, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x68, 522 | 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x20, 0x34, 0x38, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x64, 523 | 0x69, 0x73, 0x70, 0x6C, 0x61, 0x79, 0x3A, 0x20, 0x69, 0x6E, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 0x62, 524 | 0x6C, 0x6F, 0x63, 0x6B, 0x3B, 0x0D, 0x0A, 0x09, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x73, 0x69, 0x7A, 525 | 0x65, 0x3A, 0x20, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 0x68, 526 | 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x20, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x6F, 0x76, 527 | 0x65, 0x72, 0x66, 0x6C, 0x6F, 0x77, 0x3A, 0x20, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6E, 0x3B, 0x0D, 528 | 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x2E, 0x62, 0x74, 0x6E, 529 | 0x2D, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x20, 0x7B, 0x0D, 0x0A, 0x09, 0x70, 0x6F, 0x73, 0x69, 530 | 0x74, 0x69, 0x6F, 0x6E, 0x3A, 0x20, 0x61, 0x62, 0x73, 0x6F, 0x6C, 0x75, 0x74, 0x65, 0x3B, 0x0D, 531 | 0x0A, 0x09, 0x6C, 0x65, 0x66, 0x74, 0x3A, 0x20, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x74, 532 | 0x6F, 0x70, 0x3A, 0x20, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x77, 0x69, 533 | 0x66, 0x69, 0x2D, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x20, 0x2E, 0x63, 0x6F, 0x6E, 0x74, 534 | 0x65, 0x6E, 0x74, 0x7B, 0x0D, 0x0A, 0x09, 0x2D, 0x77, 0x65, 0x62, 0x6B, 0x69, 0x74, 0x2D, 0x62, 535 | 0x6F, 0x78, 0x2D, 0x66, 0x6C, 0x65, 0x78, 0x3A, 0x20, 0x31, 0x3B, 0x0D, 0x0A, 0x20, 0x20, 0x20, 536 | 0x20, 0x2D, 0x6D, 0x6F, 0x7A, 0x2D, 0x62, 0x6F, 0x78, 0x2D, 0x66, 0x6C, 0x65, 0x78, 0x3A, 0x20, 537 | 0x31, 0x3B, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x2D, 0x77, 0x65, 0x62, 0x6B, 0x69, 0x74, 0x2D, 538 | 0x66, 0x6C, 0x65, 0x78, 0x3A, 0x20, 0x31, 0x3B, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x2D, 0x6D, 539 | 0x73, 0x2D, 0x66, 0x6C, 0x65, 0x78, 0x3A, 0x20, 0x31, 0x3B, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 540 | 0x66, 0x6C, 0x65, 0x78, 0x3A, 0x20, 0x31, 0x3B, 0x0D, 0x0A, 0x09, 0x70, 0x61, 0x64, 0x64, 0x69, 541 | 0x6E, 0x67, 0x3A, 0x31, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x62, 0x61, 0x63, 0x6B, 0x67, 542 | 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x2D, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x23, 0x46, 0x46, 0x46, 543 | 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x77, 0x69, 0x66, 0x69, 0x2D, 0x73, 0x75, 0x63, 0x63, 544 | 0x65, 0x73, 0x73, 0x20, 0x68, 0x32, 0x7B, 0x0D, 0x0A, 0x09, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 545 | 0x20, 0x23, 0x66, 0x35, 0x36, 0x63, 0x36, 0x63, 0x3B, 0x0D, 0x0A, 0x09, 0x66, 0x6F, 0x6E, 0x74, 546 | 0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x33, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x74, 0x65, 547 | 0x78, 0x74, 0x2D, 0x61, 0x6C, 0x69, 0x67, 0x6E, 0x3A, 0x63, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x3B, 548 | 0x0D, 0x0A, 0x09, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6E, 0x67, 0x3A, 0x33, 0x30, 0x70, 0x78, 0x20, 549 | 0x30, 0x3B, 0x0D, 0x0A, 0x09, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 550 | 0x3A, 0x33, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x77, 0x69, 0x66, 0x69, 551 | 0x2D, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x20, 0x70, 0x7B, 0x0D, 0x0A, 0x09, 0x74, 0x65, 552 | 0x78, 0x74, 0x2D, 0x69, 0x6E, 0x64, 0x65, 0x6E, 0x74, 0x3A, 0x32, 0x72, 0x65, 0x6D, 0x3B, 0x0D, 553 | 0x0A, 0x09, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x31, 0x36, 0x70, 0x78, 554 | 0x3B, 0x0D, 0x0A, 0x09, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 555 | 0x32, 0x38, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x62, 0x74, 0x6E, 0x7B, 0x0D, 556 | 0x0A, 0x09, 0x74, 0x65, 0x78, 0x74, 0x2D, 0x64, 0x65, 0x63, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 557 | 0x6E, 0x3A, 0x20, 0x6E, 0x6F, 0x6E, 0x65, 0x3B, 0x0D, 0x0A, 0x09, 0x68, 0x65, 0x69, 0x67, 0x68, 558 | 0x74, 0x3A, 0x34, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 0x68, 559 | 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x34, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x66, 0x6F, 560 | 0x6E, 0x74, 0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x31, 0x34, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 561 | 0x64, 0x69, 0x73, 0x70, 0x6C, 0x61, 0x79, 0x3A, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x3B, 0x0D, 0x0A, 562 | 0x09, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x3A, 0x20, 0x30, 0x20, 0x6E, 0x6F, 0x6E, 0x65, 0x3B, 563 | 0x0D, 0x0A, 0x09, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x20, 0x23, 0x46, 0x46, 0x46, 0x3B, 0x0D, 564 | 0x0A, 0x09, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3A, 565 | 0x20, 0x35, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x2D, 0x6D, 0x6F, 0x7A, 0x2D, 0x62, 0x6F, 0x72, 566 | 0x64, 0x65, 0x72, 0x2D, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3A, 0x20, 0x35, 0x70, 0x78, 0x3B, 567 | 0x0D, 0x0A, 0x09, 0x2D, 0x77, 0x65, 0x62, 0x6B, 0x69, 0x74, 0x2D, 0x62, 0x6F, 0x72, 0x64, 0x65, 568 | 0x72, 0x2D, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3A, 0x20, 0x35, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 569 | 0x09, 0x6F, 0x75, 0x74, 0x6C, 0x69, 0x6E, 0x65, 0x3A, 0x20, 0x6E, 0x6F, 0x6E, 0x65, 0x3B, 0x0D, 570 | 0x0A, 0x09, 0x63, 0x75, 0x72, 0x73, 0x6F, 0x72, 0x3A, 0x20, 0x70, 0x6F, 0x69, 0x6E, 0x74, 0x65, 571 | 0x72, 0x3B, 0x0D, 0x0A, 0x09, 0x74, 0x65, 0x78, 0x74, 0x2D, 0x61, 0x6C, 0x69, 0x67, 0x6E, 0x3A, 572 | 0x63, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x3B, 0x0D, 0x0A, 0x09, 0x6D, 0x69, 0x6E, 0x2D, 0x77, 0x69, 573 | 0x64, 0x74, 0x68, 0x3A, 0x37, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x70, 0x61, 0x64, 0x64, 574 | 0x69, 0x6E, 0x67, 0x3A, 0x30, 0x20, 0x31, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 575 | 0x2E, 0x62, 0x74, 0x6E, 0x2D, 0x72, 0x65, 0x64, 0x7B, 0x0D, 0x0A, 0x09, 0x62, 0x61, 0x63, 0x6B, 576 | 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x2D, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x23, 0x66, 0x35, 577 | 0x36, 0x63, 0x36, 0x63, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x67, 0x65, 0x74, 0x65, 0x77, 578 | 0x61, 0x79, 0x2D, 0x62, 0x74, 0x6E, 0x20, 0x62, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x20, 0x7B, 0x0D, 579 | 0x0A, 0x20, 0x20, 0x20, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3A, 0x20, 0x31, 0x30, 0x30, 0x25, 580 | 0x3B, 0x0D, 0x0A, 0x09, 0x6D, 0x61, 0x72, 0x67, 0x69, 0x6E, 0x3A, 0x33, 0x35, 0x70, 0x78, 0x20, 581 | 0x30, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x3C, 0x2F, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x3E, 0x0D, 582 | 0x0A, 0x3C, 0x2F, 0x68, 0x65, 0x61, 0x64, 0x3E, 0x0D, 0x0A, 0x0D, 0x0A, 0x3C, 0x62, 0x6F, 0x64, 583 | 0x79, 0x3E, 0x0D, 0x0A, 0x3C, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22, 584 | 0x6D, 0x61, 0x69, 0x6E, 0x20, 0x77, 0x69, 0x66, 0x69, 0x2D, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 585 | 0x73, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x3C, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x63, 586 | 0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x22, 0x3E, 0x0D, 0x0A, 587 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3D, 588 | 0x22, 0x23, 0x22, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22, 0x62, 0x74, 0x6E, 0x2D, 0x72, 589 | 0x65, 0x74, 0x75, 0x72, 0x6E, 0x22, 0x3E, 0xE4, 0xB8, 0x8A, 0xE4, 0xB8, 0x80, 0xE9, 0xA1, 0xB5, 590 | 0x3C, 0x2F, 0x61, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x68, 591 | 0x33, 0x3E, 0xE7, 0xBD, 0x91, 0xE5, 0x85, 0xB3, 0xE4, 0xB8, 0x8A, 0xE7, 0xBD, 0x91, 0xE8, 0xAE, 592 | 0xBE, 0xE7, 0xBD, 0xAE, 0x3C, 0x2F, 0x68, 0x33, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x3C, 593 | 0x2F, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 594 | 0x69, 0x76, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 595 | 0x74, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x68, 0x32, 0x3E, 596 | 0xE8, 0xAE, 0xBE, 0xE7, 0xBD, 0xAE, 0xE6, 0x88, 0x90, 0xE5, 0x8A, 0x9F, 0xEF, 0xBC, 0x81, 0x3C, 597 | 0x2F, 0x68, 0x32, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x64, 0x69, 0x76, 0x3E, 598 | 0x0D, 0x0A, 0x3C, 0x2F, 0x64, 0x69, 0x76, 0x3E, 0x0D, 0x0A, 0x3C, 0x2F, 0x62, 0x6F, 0x64, 0x79, 599 | 0x3E, 0x0D, 0x0A, 0x3C, 0x2F, 0x68, 0x74, 0x6D, 0x6C, 0x3E, 0x0D, 0x0A 600 | }; 601 | 602 | -------------------------------------------------------------------------------- /TC1/main.c: -------------------------------------------------------------------------------- 1 | #include "main.h" 2 | 3 | #include "user_gpio.h" 4 | #include "user_wifi.h" 5 | #include "user_sntp.h" 6 | #include "user_power.h" 7 | #include "user_mqtt_client.h" 8 | #include "user_function.h" 9 | #include "http_server/app_httpd.h" 10 | 11 | #define os_log(format, ...) custom_log("TC1", format, ##__VA_ARGS__) 12 | 13 | 14 | 15 | char first_sntp = 0; //sntp校时成功标志位 16 | uint32_t sntp_count=0; 17 | uint32_t run_time=0; 18 | char strMac[16] = { 0 }; 19 | uint32_t power=0; 20 | 21 | system_config_t * sys_config; 22 | user_config_t * user_config; 23 | 24 | mico_gpio_t Relay[Relay_NUM] = { Relay_0, Relay_1, Relay_2, Relay_3, Relay_4, Relay_5 }; 25 | 26 | /* MICO system callback: Restore default configuration provided by application */ 27 | void appRestoreDefault_callback( void * const user_config_data, uint32_t size ) 28 | { 29 | int i; 30 | UNUSED_PARAMETER( size ); 31 | 32 | mico_system_context_get( )->micoSystemConfig.name[0] = 1; //在下次重启时使用默认名称 33 | mico_system_context_get( )->micoSystemConfig.name[1] = 0; 34 | 35 | user_config_t* userConfigDefault = user_config_data; 36 | 37 | // userConfigDefault->user[0] = 0; 38 | // userConfigDefault->mqtt_ip[0] = 0; 39 | // userConfigDefault->mqtt_port = 0; 40 | // userConfigDefault->mqtt_user[0] = 0; 41 | // userConfigDefault->mqtt_password[0] = 0; 42 | 43 | sprintf(userConfigDefault->mqtt_ip, CONFIG_MQTT_IP); 44 | userConfigDefault->mqtt_port = CONFIG_MQTT_PORT; 45 | sprintf(userConfigDefault->mqtt_user, CONFIG_MQTT_USER); 46 | sprintf(userConfigDefault->mqtt_password, CONFIG_MQTT_PASSWORD); 47 | //初始化wifi及密码 48 | strcpy( mico_system_context_get( )->micoSystemConfig.ssid, CONFIG_SSID ); 49 | strcpy( mico_system_context_get( )->micoSystemConfig.user_key, CONFIG_USER_KEY ); 50 | mico_system_context_get( )->micoSystemConfig.user_keyLength = strlen( CONFIG_USER_KEY ); 51 | 52 | userConfigDefault->version = USER_CONFIG_VERSION; 53 | for ( i = 0; i < SLOT_NUM; i++ ) 54 | { 55 | userConfigDefault->slot[i] = 1; 56 | 57 | } 58 | // mico_system_context_update( sys_config ); 59 | 60 | } 61 | 62 | int application_start( void ) 63 | { 64 | int i; 65 | os_log( "Start %s",VERSION ); 66 | 67 | uint8_t main_num=0; 68 | uint32_t power_last = 0xffffffff; 69 | OSStatus err = kNoErr; 70 | 71 | // for ( i = 0; i < Relay_NUM; i++ ) 72 | // { 73 | // MicoGpioOutputLow( Relay[(i)] ); 74 | // MicoGpioInitialize( Relay[i], OUTPUT_PUSH_PULL ); 75 | // MicoGpioOutputLow( Relay[(i)] ); 76 | // //MicoGpioOutputHigh(Relay[i]); 77 | // } 78 | /* Create mico system context and read application's config data from flash */ 79 | sys_config = mico_system_context_init( sizeof(user_config_t) ); 80 | user_config = ((system_context_t *) sys_config)->user_config_data; 81 | require_action( user_config, exit, err = kNoMemoryErr ); 82 | 83 | err = mico_system_init( sys_config ); 84 | require_noerr( err, exit ); 85 | 86 | MicoGpioInitialize( (mico_gpio_t) Button, INPUT_PULL_UP ); 87 | if ( !MicoGpioInputGet( Button ) ) 88 | { //开机时按钮状态 89 | os_log( "wifi_start_easylink" ); 90 | wifi_status = WIFI_STATE_NOEASYLINK; //wifi_init中启动easylink 91 | } 92 | 93 | MicoGpioInitialize( (mico_gpio_t) Led, OUTPUT_PUSH_PULL ); 94 | for ( i = 0; i < Relay_NUM; i++ ) 95 | { 96 | MicoGpioInitialize( Relay[i], OUTPUT_PUSH_PULL ); 97 | user_relay_set( i, user_config->slot[i] ); 98 | } 99 | MicoSysLed( 0 ); 100 | 101 | if ( user_config->version != USER_CONFIG_VERSION) 102 | { 103 | os_log( "WARNGIN: user params restored!" ); 104 | err = mico_system_context_restore( sys_config ); 105 | require_noerr( err, exit ); 106 | } 107 | 108 | wifi_init( ); 109 | mico_thread_msleep(1000); 110 | 111 | IPStatusTypedef para; 112 | micoWlanGetIPStatus( ¶, Station ); 113 | os_log( "micoWlanGetIPStatus:%d", micoWlanGetIPStatus( ¶, Station )); //mac读出来全部是0??!!! 114 | strcpy( strMac, para.mac ); 115 | os_log( "result:%s",strMac ); 116 | os_log( "result:%s",para.mac ); 117 | 118 | if ( sys_config->micoSystemConfig.name[0] == 1 ) 119 | { 120 | sprintf( sys_config->micoSystemConfig.name, ZTC_NAME, strMac ); 121 | } 122 | 123 | os_log( "user:%s",user_config->user ); 124 | os_log( "device name:%s",sys_config->micoSystemConfig.name ); 125 | os_log( "mqtt_ip:%s",user_config->mqtt_ip ); 126 | os_log( "mqtt_port:%d",user_config->mqtt_port ); 127 | os_log( "mqtt_user:%s",user_config->mqtt_user ); 128 | os_log( "mqtt_password:%s",user_config->mqtt_password ); 129 | 130 | os_log( "version:%d",user_config->version ); 131 | // for ( i = 0; i < SLOT_NUM; i++ ) 132 | // { 133 | // os_log("slot_%d:",i); 134 | // os_log("\tname:%s:",user_config->slot[i].name); 135 | // for ( j = 0; j < SLOT_TIME_TASK_NUM; j++ ) 136 | // { 137 | // os_log("\t\ton:%d\t %02d:%02d repeat:0x%X",user_config->slot[i].task[j].on, 138 | // user_config->slot[i].task[j].hour,user_config->slot[i].task[j].minute, 139 | // user_config->slot[i].task[j].repeat); 140 | // } 141 | // } 142 | 143 | 144 | // user_udp_init( ); 145 | key_init( ); 146 | err = user_mqtt_init( ); 147 | require_noerr( err, exit ); 148 | sntp_init(); 149 | user_power_init(); 150 | 151 | /* start http server thread */ 152 | // app_httpd_start(); 153 | while ( 1 ) 154 | { 155 | main_num++; 156 | //发送功率数据 157 | if ( power_last != power || main_num>4 ) 158 | { 159 | power_last = power; 160 | main_num =0; 161 | // uint8_t *power_buf = NULL; 162 | // power_buf = malloc( 128 ); 163 | // if ( power_buf != NULL ) 164 | // { 165 | // sprintf( power_buf, "{\"power\":\"%d.%d\",\"run_time\":%d}", power / 10, power % 10, run_time ); 166 | // user_mqtt_send( power_buf ); 167 | // free( power_buf ); 168 | // } 169 | user_mqtt_hass_power( ); 170 | } 171 | mico_thread_msleep(STATE_UPDATE_INTERVAL); 172 | } 173 | exit: 174 | os_log("application_start ERROR!"); 175 | return 0; 176 | } 177 | 178 | -------------------------------------------------------------------------------- /TC1/main.h: -------------------------------------------------------------------------------- 1 | #ifndef __MAIN_H_ 2 | #define __MAIN_H_ 3 | 4 | #include "mico.h" 5 | #include "MiCOKit_EXT.h" 6 | 7 | #define VERSION "v0.0.0" 8 | 9 | #define TYPE 1 10 | #define TYPE_NAME "tc1" 11 | 12 | #define SETTING_MQTT_STRING_LENGTH_MAX 32 //必须 4 字节对齐。 13 | 14 | #define SLOT_NAME_LENGTH 32 15 | #define SLOT_NUM 6 //插座数量 16 | #define SLOT_TIME_TASK_NUM 5 //每个插座最多5组定时任务 17 | 18 | #define Led MICO_GPIO_5 19 | #define Button MICO_GPIO_23 20 | #define POWER MICO_GPIO_15 21 | 22 | #define Relay_ON 1 23 | #define Relay_OFF 0 24 | 25 | #define Relay_0 MICO_GPIO_6 26 | #define Relay_1 MICO_GPIO_8 27 | #define Relay_2 MICO_GPIO_10 28 | #define Relay_3 MICO_GPIO_7 29 | #define Relay_4 MICO_GPIO_9 30 | #define Relay_5 MICO_GPIO_18 31 | #define Relay_NUM SLOT_NUM 32 | 33 | //自定义 34 | #define ZTC_NAME "tc1_%s" //设备名称模板,默认生成的设备名称为tc1_{{MAC地址}},PS:如修改要保留%s,将填充MAC地址 35 | #define CONFIG_SSID "ssid" //WiFi名称 36 | #define CONFIG_USER_KEY "password" //WiFi密码 37 | #define CONFIG_MQTT_IP "mqtt_ip" //MQTT服务器IP 38 | #define CONFIG_MQTT_PORT 1883 //MQTT服务器端口,数值 39 | #define CONFIG_MQTT_USER "mqtt_user" //MQTT用户名 40 | #define CONFIG_MQTT_PASSWORD "mqtt_password" //MQTT密码 41 | #define STATE_UPDATE_INTERVAL 10000 //功率上报间隔,单位ms,数值 42 | #define MQTT_CLIENT_SUB_TOPIC "cmnd/%s" //命令控制接收topic模板,%s取ZTC_NAME(默认tc1_{{MAC地址}}),PS:请勿修改此处,可修改ZTC_NAME 43 | #define MQTT_CLIENT_PUB_TOPIC "stat/%s" //状态信息topic模板,%s取ZTC_NAME(默认tc1_{{MAC地址}}),PS:请勿修改此处,可修改ZTC_NAME 44 | #define USER_CONFIG_VERSION 2 //OTA注意修改为与上次固件不同,触发重载wifi、mqtt等配置信息 45 | 46 | //用户保存参数结构体 47 | typedef struct 48 | { 49 | char mqtt_ip[SETTING_MQTT_STRING_LENGTH_MAX]; //mqtt service ip 50 | int mqtt_port; //mqtt service port 51 | char mqtt_user[SETTING_MQTT_STRING_LENGTH_MAX]; //mqtt service user 52 | char mqtt_password[SETTING_MQTT_STRING_LENGTH_MAX]; //mqtt service user 53 | // char mqtt_device_id[SETTING_MQTT_STRING_LENGTH_MAX]; //mqtt service user device name 54 | 55 | char version; 56 | char slot[SLOT_NUM]; 57 | char user[maxNameLen]; 58 | } user_config_t; 59 | 60 | extern char first_sntp; 61 | extern uint32_t sntp_count; 62 | 63 | extern uint32_t run_time; 64 | extern char strMac[16]; 65 | extern uint32_t power; 66 | extern system_config_t * sys_config; 67 | extern user_config_t * user_config; 68 | 69 | extern mico_gpio_t Relay[Relay_NUM]; 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /TC1/mico_config.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file mico_config.h 4 | * @author 5 | * @version V1.0.0 6 | * @date 7 | * @brief This file provide constant definition and type declaration for MICO 8 | * running. 9 | ****************************************************************************** 10 | * 11 | * The MIT License 12 | * Copyright (c) 2016 MXCHIP Inc. 13 | * 14 | * Permission is hereby granted, free of charge, to any person obtaining a copy 15 | * of this software and associated documentation files (the "Software"), to deal 16 | * in the Software without restriction, including without limitation the rights 17 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | * copies of the Software, and to permit persons to whom the Software is furnished 19 | * to do so, subject to the following conditions: 20 | * 21 | * The above copyright notice and this permission notice shall be included in 22 | * all copies or substantial portions of the Software. 23 | * 24 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 28 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 29 | * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 | * 31 | ****************************************************************************** 32 | */ 33 | 34 | #pragma once 35 | 36 | #define APP_INFO "MiCO BASIC Demo" 37 | 38 | #define FIRMWARE_REVISION "ZYC_BASIC_1_0" 39 | #define MANUFACTURER "ZYC Inc." 40 | #define SERIAL_NUMBER "20190105" 41 | #define PROTOCOL "com.zyc.basic" 42 | 43 | /************************************************************************ 44 | * Application thread stack size */ 45 | #define MICO_DEFAULT_APPLICATION_STACK_SIZE (2000) 46 | 47 | /************************************************************************ 48 | * Enable wlan connection, start easylink configuration if no wlan settings are existed */ 49 | //#define MICO_WLAN_CONNECTION_ENABLE 50 | 51 | #define MICO_WLAN_CONFIG_MODE CONFIG_MODE_AWS 52 | 53 | #define EasyLink_TimeOut 60000 /**< EasyLink timeout 60 seconds. */ 54 | 55 | #define EasyLink_ConnectWlan_Timeout 20000 /**< Connect to wlan after configured by easylink. 56 | Restart easylink after timeout: 20 seconds. */ 57 | 58 | /************************************************************************ 59 | * Device enter MFG mode if MICO settings are erased. */ 60 | //#define MFG_MODE_AUTO 61 | 62 | /************************************************************************ 63 | * Command line interface */ 64 | #define MICO_CLI_ENABLE 65 | 66 | /************************************************************************ 67 | * Start a system monitor daemon, application can register some monitor 68 | * points, If one of these points is not executed in a predefined period, 69 | * a watchdog reset will occur. */ 70 | #define MICO_SYSTEM_MONITOR_ENABLE 71 | 72 | /************************************************************************ 73 | * Add service _easylink._tcp._local. for discovery */ 74 | #define MICO_SYSTEM_DISCOVERY_ENABLE 75 | 76 | /************************************************************************ 77 | * MiCO TCP server used for configuration and ota. */ 78 | #define MICO_CONFIG_SERVER_ENABLE 79 | #define MICO_CONFIG_SERVER_PORT 8000 80 | 81 | -------------------------------------------------------------------------------- /TC1/ota_server/ota_server.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file ota_server.c 4 | * @author QQ ding 5 | * @version V1.0.0 6 | * @date 19-Oct-2016 7 | * @brief Create a OTA server thread, download update bin file. Reboot system 8 | * if download success. 9 | ****************************************************************************** 10 | * 11 | * The MIT License 12 | * Copyright (c) 2016 MXCHIP Inc. 13 | * 14 | * Permission is hereby granted, free of charge, to any person obtaining a copy 15 | * of this software and associated documentation files (the "Software"), to deal 16 | * in the Software without restriction, including without limitation the rights 17 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | * copies of the Software, and to permit persons to whom the Software is furnished 19 | * to do so, subject to the following conditions: 20 | * 21 | * The above copyright notice and this permission notice shall be included in 22 | * all copies or substantial portions of the Software. 23 | * 24 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 28 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 29 | * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 | ****************************************************************************** 31 | */ 32 | #include "mico.h" 33 | #include "HTTPUtils.h" 34 | #include "SocketUtils.h" 35 | #include "ota_server.h" 36 | #include "url.h" 37 | 38 | #if OTA_DEBUG 39 | #define ota_server_log(M, ...) custom_log("OTA", M, ##__VA_ARGS__) 40 | #else 41 | #define ota_server_log(M, ...) 42 | #endif 43 | 44 | static ota_server_context_t *ota_server_context = NULL; 45 | static HTTPHeader_t *httpHeader = NULL; 46 | 47 | static CRC16_Context crc_context; 48 | static md5_context md5; 49 | static uint32_t offset = 0; 50 | 51 | static OSStatus onReceivedData( struct _HTTPHeader_t * httpHeader, 52 | uint32_t pos, 53 | uint8_t *data, 54 | size_t len, 55 | void * userContext ); 56 | 57 | static void hex2str(uint8_t *hex, int hex_len, char *str) 58 | { 59 | int i = 0; 60 | for(i=0; i= 'A') && (*(str+i) <= 'Z') ){ 71 | *(str+i) += 32; 72 | } 73 | } 74 | } 75 | 76 | static int ota_server_send( uint8_t *data, int datalen ) 77 | { 78 | int res = 0; 79 | if( ota_server_context->download_url.HTTP_SECURITY == HTTP_SECURITY_HTTP ){ 80 | res = send( ota_server_context->download_url.ota_fd, data, datalen, 0 ); 81 | } 82 | #if OTA_USE_HTTPS 83 | if( ota_server_context->download_url.HTTP_SECURITY == HTTP_SECURITY_HTTPS ){ 84 | res = ssl_send( ota_server_context->download_url.ota_ssl, data, datalen); 85 | } 86 | #endif 87 | return res; 88 | } 89 | 90 | static OSStatus ota_server_connect( struct sockaddr_in *addr, socklen_t addrlen ) 91 | { 92 | OSStatus err = kNoErr; 93 | #if OTA_USE_HTTPS 94 | int ssl_errno = 0; 95 | #endif 96 | 97 | err = connect( ota_server_context->download_url.ota_fd, (struct sockaddr *)addr, addrlen ); 98 | require_noerr_string( err, exit, "ERROR: connect ota server failed" ); 99 | 100 | #if OTA_USE_HTTPS 101 | if( ota_server_context->download_url.HTTP_SECURITY == HTTP_SECURITY_HTTPS ){ 102 | ota_server_context->download_url.ota_ssl = ssl_connect( ota_server_context->download_url.ota_fd, 0, NULL, &ssl_errno ); 103 | require_action_string( ota_server_context->download_url.ota_ssl != NULL, exit, err = kConnectionErr,"ERROR: ssl disconnect" ); 104 | } 105 | #endif 106 | 107 | exit: 108 | return err; 109 | } 110 | 111 | static int ota_server_read_header( HTTPHeader_t *httpHeader ) 112 | { 113 | int res = 0; 114 | if( ota_server_context->download_url.HTTP_SECURITY == HTTP_SECURITY_HTTP ){ 115 | res = SocketReadHTTPHeader( ota_server_context->download_url.ota_fd, httpHeader ); 116 | } 117 | if( ota_server_context->download_url.HTTP_SECURITY == HTTP_SECURITY_HTTPS ){ 118 | #if OTA_USE_HTTPS 119 | res = SocketReadHTTPSHeader( ota_server_context->download_url.ota_ssl, httpHeader ); 120 | #endif 121 | } 122 | 123 | return res; 124 | } 125 | 126 | static int ota_server_read_body( HTTPHeader_t *httpHeader ) 127 | { 128 | int res = 0; 129 | if( ota_server_context->download_url.HTTP_SECURITY == HTTP_SECURITY_HTTP ){ 130 | res = SocketReadHTTPBody( ota_server_context->download_url.ota_fd, httpHeader ); 131 | } 132 | if( ota_server_context->download_url.HTTP_SECURITY == HTTP_SECURITY_HTTPS ){ 133 | #if OTA_USE_HTTPS 134 | res = SocketReadHTTPSBody( ota_server_context->download_url.ota_ssl, httpHeader ); 135 | #endif 136 | } 137 | return res; 138 | } 139 | 140 | static int ota_server_send_header( void ) 141 | { 142 | char *header = NULL; 143 | int j = 0; 144 | int ret = 0; 145 | header = malloc( OTA_SEND_HEAD_SIZE ); 146 | memset( header, 0x00, OTA_SEND_HEAD_SIZE ); 147 | 148 | j = sprintf( header, "GET " ); 149 | j += sprintf( header + j, "/%s HTTP/1.1\r\n", ota_server_context->download_url.url ); 150 | 151 | if ( ota_server_context->download_url.port == 0 ) 152 | { 153 | j += sprintf( header + j, "Host: %s\r\n", ota_server_context->download_url.host ); 154 | } else 155 | { 156 | j += sprintf( header + j, "Host: %s:%d\r\n", ota_server_context->download_url.host, ota_server_context->download_url.port ); 157 | } 158 | 159 | j += sprintf( header + j, "Connection: close\r\n" ); //Keep-Alive close 160 | 161 | //Range: bytes=start-end 162 | if ( ota_server_context->download_state.download_begin_pos > 0 ) 163 | { 164 | if ( ota_server_context->download_state.download_end_pos > 0 ) 165 | { 166 | j += sprintf( header + j, "Range: bytes=%d-%d\r\n", ota_server_context->download_state.download_begin_pos, 167 | ota_server_context->download_state.download_end_pos ); 168 | } else 169 | { 170 | j += sprintf( header + j, "Range: bytes=%d-\r\n", ota_server_context->download_state.download_begin_pos ); 171 | } 172 | } 173 | 174 | j += sprintf( header + j, "\r\n" ); 175 | 176 | ret = ota_server_send( (uint8_t *) header, strlen( header ) ); 177 | 178 | // ota_server_log("send: %d\r\n%s", strlen(header), header); 179 | if ( header != NULL ) free( header ); 180 | return ret; 181 | } 182 | 183 | static void ota_server_socket_close( void ) 184 | { 185 | #if OTA_USE_HTTPS 186 | if ( ota_server_context->download_url.ota_ssl ) ssl_close( ota_server_context->download_url.ota_ssl ); 187 | #endif 188 | SocketClose( &(ota_server_context->download_url.ota_fd) ); 189 | ota_server_context->download_url.ota_fd = -1; 190 | } 191 | 192 | static int ota_server_connect_server( struct in_addr in_addr ) 193 | { 194 | int err = 0; 195 | struct sockaddr_in server_address; 196 | 197 | if ( ota_server_context->download_url.port == 0 ) 198 | { 199 | if ( ota_server_context->download_url.HTTP_SECURITY == HTTP_SECURITY_HTTP ) 200 | { 201 | server_address.sin_port = htons(80); 202 | } else 203 | { 204 | server_address.sin_port = htons(443); 205 | } 206 | } else 207 | { 208 | server_address.sin_port = htons(ota_server_context->download_url.port); 209 | } 210 | 211 | server_address.sin_family = AF_INET; 212 | server_address.sin_addr = in_addr; 213 | 214 | err = ota_server_connect( &server_address, sizeof(server_address) ); 215 | if ( err != 0 ) 216 | { 217 | mico_thread_sleep( 1 ); 218 | return -1; 219 | } 220 | 221 | ota_server_log("ota server connected!"); 222 | return 0; 223 | } 224 | 225 | static void ota_server_progress_set( OTA_STATE_E state ) 226 | { 227 | float progress = 0.00; 228 | 229 | progress =(float) ota_server_context->download_state.download_begin_pos / ota_server_context->download_state.download_len; 230 | progress = progress*100; 231 | if( ota_server_context->ota_server_cb != NULL ) 232 | ota_server_context->ota_server_cb(state, progress); 233 | } 234 | 235 | static void ota_server_thread( mico_thread_arg_t arg ) 236 | { 237 | OSStatus err; 238 | uint16_t crc16 = 0; 239 | char md5_value[16] = {0}; 240 | char md5_value_string[33] = {0}; 241 | fd_set readfds; 242 | struct hostent* hostent_content = NULL; 243 | char **pptr = NULL; 244 | struct in_addr in_addr; 245 | 246 | mico_logic_partition_t* ota_partition = MicoFlashGetInfo( MICO_PARTITION_OTA_TEMP ); 247 | 248 | ota_server_context->ota_control = OTA_CONTROL_START; 249 | 250 | hostent_content = gethostbyname( ota_server_context->download_url.host ); 251 | require_action_quiet( hostent_content != NULL, DELETE, ota_server_progress_set(OTA_FAIL)); 252 | pptr=hostent_content->h_addr_list; 253 | in_addr.s_addr = *(uint32_t *)(*pptr); 254 | strcpy( ota_server_context->download_url.ip, inet_ntoa(in_addr)); 255 | ota_server_log("OTA server address: %s, host ip: %s", ota_server_context->download_url.host, ota_server_context->download_url.ip); 256 | 257 | offset = 0; 258 | MicoFlashErase( MICO_PARTITION_OTA_TEMP, 0x0, ota_partition->partition_length ); 259 | 260 | CRC16_Init( &crc_context ); 261 | if( ota_server_context->ota_check.is_md5 == true ){ 262 | InitMd5( &md5 ); 263 | } 264 | 265 | httpHeader = HTTPHeaderCreateWithCallback( 1024, onReceivedData, NULL, NULL ); 266 | require_action( httpHeader, DELETE, ota_server_progress_set(OTA_FAIL) ); 267 | 268 | while ( 1 ) 269 | { 270 | if ( ota_server_context->ota_control == OTA_CONTROL_PAUSE ){ 271 | mico_thread_sleep( 1 ); 272 | continue; 273 | }else if( ota_server_context->ota_control == OTA_CONTROL_STOP ){ 274 | goto DELETE; 275 | } 276 | 277 | ota_server_context->download_url.ota_fd = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); 278 | err = ota_server_connect_server( in_addr ); 279 | require_noerr_action( err, RECONNECTED, ota_server_progress_set(OTA_FAIL)); 280 | 281 | /* Send HTTP Request */ 282 | ota_server_send_header( ); 283 | 284 | FD_ZERO( &readfds ); 285 | FD_SET( ota_server_context->download_url.ota_fd, &readfds ); 286 | 287 | select( ota_server_context->download_url.ota_fd + 1, &readfds, NULL, NULL, NULL ); 288 | if ( FD_ISSET( ota_server_context->download_url.ota_fd, &readfds ) ) 289 | { 290 | /*parse header*/ 291 | err = ota_server_read_header( httpHeader ); 292 | if ( ota_server_context->ota_control == OTA_CONTROL_START ) 293 | { 294 | ota_server_context->download_state.download_len = httpHeader->contentLength; 295 | ota_server_context->ota_control = OTA_CONTROL_CONTINUE; 296 | } 297 | switch ( err ) 298 | { 299 | case kNoErr: 300 | #if OTA_DEBUG 301 | PrintHTTPHeader( httpHeader ); 302 | #endif 303 | err = ota_server_read_body( httpHeader );/*get body data*/ 304 | require_noerr( err, RECONNECTED ); 305 | /*get data and print*/ 306 | break; 307 | case EWOULDBLOCK: 308 | case kNoSpaceErr: 309 | case kConnectionErr: 310 | default: 311 | ota_server_log("ERROR: HTTP Header parse error: %d", err); 312 | break; 313 | } 314 | } 315 | 316 | if ( ota_server_context->download_state.download_len == ota_server_context->download_state.download_begin_pos ) 317 | { 318 | if( httpHeader->statusCode != 200 ){ 319 | ota_server_progress_set(OTA_FAIL); 320 | goto DELETE; 321 | } 322 | CRC16_Final( &crc_context, &crc16 ); 323 | if( ota_server_context->ota_check.is_md5 == true ){ 324 | Md5Final( &md5, (unsigned char *) md5_value ); 325 | hex2str((uint8_t *)md5_value, 16, md5_value_string); 326 | } 327 | if ( memcmp( md5_value_string, ota_server_context->ota_check.md5, OTA_MD5_LENTH ) == 0 ){ 328 | ota_server_progress_set(OTA_SUCCE); 329 | mico_ota_switch_to_new_fw( ota_server_context->download_state.download_len, crc16 ); 330 | mico_system_power_perform( mico_system_context_get( ), eState_Software_Reset ); 331 | }else{ 332 | ota_server_log("OTA md5 check err, Calculation:%s, Get:%s", md5_value_string, ota_server_context->ota_check.md5); 333 | ota_server_progress_set(OTA_FAIL); 334 | } 335 | goto DELETE; 336 | } 337 | 338 | RECONNECTED: 339 | ota_server_socket_close( ); 340 | mico_thread_sleep(2); 341 | continue; 342 | 343 | } 344 | DELETE: 345 | HTTPHeaderDestory( &httpHeader ); 346 | ota_server_socket_close( ); 347 | if( ota_server_context != NULL ){ 348 | if( ota_server_context->download_url.url != NULL ){ 349 | free(ota_server_context->download_url.url); 350 | ota_server_context->download_url.url = NULL; 351 | } 352 | free(ota_server_context); 353 | ota_server_context = NULL; 354 | } 355 | 356 | ota_server_log("ota server thread will delete"); 357 | mico_rtos_delete_thread(NULL); 358 | } 359 | 360 | /*one request may receive multi reply*/ 361 | static OSStatus onReceivedData( struct _HTTPHeader_t * inHeader, uint32_t inPos, uint8_t * inData, 362 | size_t inLen, void * inUserContext ) 363 | { 364 | OSStatus err = kNoErr; 365 | 366 | if ( inLen == 0 ) 367 | return err; 368 | 369 | ota_server_context->download_state.download_begin_pos += inLen; 370 | 371 | CRC16_Update( &crc_context, inData, inLen ); 372 | if( ota_server_context->ota_check.is_md5 == true ){ 373 | Md5Update( &md5, inData, inLen ); 374 | } 375 | 376 | MicoFlashWrite( MICO_PARTITION_OTA_TEMP, &offset, (uint8_t *) inData, inLen ); 377 | 378 | ota_server_progress_set(OTA_LOADING); 379 | 380 | if( ota_server_context->ota_control == OTA_CONTROL_PAUSE ){ 381 | while( 1 ){ 382 | if( ota_server_context->ota_control != OTA_CONTROL_PAUSE ) 383 | break; 384 | mico_thread_msleep(100); 385 | } 386 | } 387 | 388 | if( ota_server_context->ota_control == OTA_CONTROL_STOP ){ 389 | err = kUnsupportedErr; 390 | } 391 | 392 | return err; 393 | } 394 | 395 | static OSStatus ota_server_set_url( char *url ) 396 | { 397 | OSStatus err = kNoErr; 398 | url_field_t *url_t; 399 | char *pos = NULL; 400 | 401 | url_t = url_parse( url ); 402 | require_action(url, exit, err = kParamErr); 403 | #if OTA_DEBUG 404 | url_field_print( url_t ); 405 | #endif 406 | if ( !strcmp( url_t->schema, "https" ) ) 407 | { 408 | ota_server_context->download_url.HTTP_SECURITY = HTTP_SECURITY_HTTPS; 409 | } else 410 | { 411 | ota_server_context->download_url.HTTP_SECURITY = HTTP_SECURITY_HTTP; 412 | } 413 | 414 | strcpy( ota_server_context->download_url.host, url_t->host ); 415 | ota_server_context->download_url.port = atoi( url_t->port ); 416 | pos = strstr( url, url_t->path ); 417 | if ( pos == NULL ) 418 | { 419 | strcpy( ota_server_context->download_url.url, "" ); 420 | } else 421 | { 422 | strcpy( ota_server_context->download_url.url, pos ); 423 | } 424 | 425 | exit: 426 | url_free( url_t ); 427 | return err; 428 | } 429 | 430 | OSStatus ota_server_start( char *url, char *md5, ota_server_cb_fn call_back ) 431 | { 432 | OSStatus err = kNoErr; 433 | 434 | require_action(url, exit, err = kParamErr); 435 | 436 | if( ota_server_context != NULL ){ 437 | if( ota_server_context->download_url.url != NULL ){ 438 | free(ota_server_context->download_url.url); 439 | ota_server_context->download_url.url = NULL; 440 | } 441 | free(ota_server_context); 442 | ota_server_context = NULL; 443 | } 444 | 445 | ota_server_context = malloc(sizeof(ota_server_context_t)); 446 | require_action(ota_server_context, exit, err = kNoMemoryErr); 447 | memset(ota_server_context, 0x00, sizeof(ota_server_context_t)); 448 | 449 | ota_server_context->download_url.url = malloc(strlen(url)); 450 | require_action(ota_server_context->download_url.url, exit, err = kNoMemoryErr); 451 | memset(ota_server_context->download_url.url, 0x00, strlen(url)); 452 | 453 | err = ota_server_set_url(url); 454 | require_noerr(err, exit); 455 | 456 | if( md5 != NULL ){ 457 | ota_server_context->ota_check.is_md5 = true; 458 | memcpy(ota_server_context->ota_check.md5, md5, OTA_MD5_LENTH); 459 | upper2lower(ota_server_context->ota_check.md5, OTA_MD5_LENTH); 460 | } 461 | 462 | ota_server_context->ota_server_cb = call_back; 463 | 464 | err = mico_rtos_create_thread( NULL, MICO_APPLICATION_PRIORITY, "OTA", ota_server_thread, OTA_SERVER_THREAD_STACK_SIZE, 0 ); 465 | exit: 466 | return err; 467 | } 468 | 469 | void ota_server_pause( void ) 470 | { 471 | ota_server_context->ota_control = OTA_CONTROL_PAUSE; 472 | } 473 | 474 | void ota_server_continue( void ) 475 | { 476 | ota_server_context->ota_control = OTA_CONTROL_CONTINUE; 477 | } 478 | 479 | void ota_server_stop( void ) 480 | { 481 | ota_server_context->ota_control = OTA_CONTROL_STOP; 482 | } 483 | 484 | OTA_CONTROL_E ota_server_get( void ) 485 | { 486 | return ota_server_context->ota_control; 487 | } 488 | -------------------------------------------------------------------------------- /TC1/ota_server/ota_server.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file ota_sever.h 4 | * @author QQ ding 5 | * @version V1.0.0 6 | * @date 19-Oct-2016 7 | * @brief Provide ota server header files. 8 | ****************************************************************************** 9 | * 10 | * The MIT License 11 | * Copyright (c) 2014 MXCHIP Inc. 12 | * 13 | * Permission is hereby granted, free of charge, to any person obtaining a copy 14 | * of this software and associated documentation files (the "Software"), to deal 15 | * in the Software without restriction, including without limitation the rights 16 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | * copies of the Software, and to permit persons to whom the Software is furnished 18 | * to do so, subject to the following conditions: 19 | * 20 | * The above copyright notice and this permission notice shall be included in 21 | * all copies or substantial portions of the Software. 22 | * 23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 27 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 28 | * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 29 | ****************************************************************************** 30 | */ 31 | #ifndef __ota_server_H 32 | #define __ota_server_H 33 | 34 | #define OTA_DEBUG (1) 35 | #define OTA_USE_HTTPS (0) 36 | 37 | #define OTA_MD5_LENTH 32 38 | #define OTA_SEND_HEAD_SIZE 256 39 | #if OTA_USE_HTTPS 40 | #define OTA_SERVER_THREAD_STACK_SIZE 0x2000 41 | #else 42 | #define OTA_SERVER_THREAD_STACK_SIZE 0x800 43 | #endif 44 | 45 | typedef enum _OTA_STATE_E{ 46 | OTA_LOADING, 47 | OTA_SUCCE, 48 | OTA_FAIL 49 | }OTA_STATE_E; 50 | 51 | typedef enum _HTTP_SECURITY_E{ 52 | HTTP_SECURITY_HTTP, 53 | HTTP_SECURITY_HTTPS 54 | } HTTP_SECURITY_E; 55 | 56 | typedef enum _OTA_CONTROL_E{ 57 | OTA_CONTROL_IDLE, 58 | OTA_CONTROL_START, 59 | OTA_CONTROL_PAUSE, 60 | OTA_CONTROL_CONTINUE, 61 | OTA_CONTROL_STOP, 62 | } OTA_CONTROL_E; 63 | 64 | typedef struct _download_url_t{ 65 | char *url; 66 | HTTP_SECURITY_E HTTP_SECURITY; 67 | char host[30]; 68 | char ip[16]; 69 | int port; 70 | int ota_fd; 71 | #if OTA_USE_HTTPS 72 | mico_ssl_t ota_ssl; 73 | #endif 74 | } download_url_t; 75 | 76 | typedef struct _download_state_t{ 77 | int download_len; 78 | int download_begin_pos; 79 | int download_end_pos; 80 | } download_state_t; 81 | 82 | typedef struct _ota_check_t{ 83 | bool is_md5; 84 | char md5[OTA_MD5_LENTH + 1]; 85 | } ota_check_t; 86 | 87 | typedef void (*ota_server_cb_fn) (OTA_STATE_E state, float progress); 88 | 89 | typedef struct _ota_server_context_t{ 90 | download_url_t download_url; 91 | download_state_t download_state; 92 | ota_check_t ota_check; 93 | OTA_CONTROL_E ota_control; 94 | ota_server_cb_fn ota_server_cb; 95 | } ota_server_context_t; 96 | 97 | 98 | /** @addtogroup OTA_SERVER_DAEMONS_APIs 99 | * @{ 100 | */ 101 | 102 | 103 | /** @brief Start OTA server, Support resume from break point, MD5 check 104 | * 105 | * @param url : Download address, URL breakdown from RFC 3986 106 | * @param md5 : MD5 checksum result, must sting type, can be NULL 107 | * @param call_back : call back function, can be NULL 108 | * 109 | * @return kNoErr : on success. 110 | * @return kGeneralErr : if an error occurred 111 | */ 112 | OSStatus ota_server_start( char *url, char *md5, ota_server_cb_fn call_back ); 113 | 114 | 115 | /** @brief Get OTA server state 116 | * 117 | * @return OTA_CONTROL_E : state 118 | */ 119 | OTA_CONTROL_E ota_server_state_get( void ); 120 | 121 | 122 | /** @brief Pause OTA server daemons 123 | * 124 | * @return No 125 | */ 126 | void ota_server_pause( void ); 127 | 128 | 129 | /** @brief Continue OTA server daemons 130 | * 131 | * @return No 132 | */ 133 | void ota_server_continue( void ); 134 | 135 | 136 | /** @brief Stop OTA server daemons 137 | * 138 | * @return No 139 | */ 140 | void ota_server_stop( void ); 141 | 142 | #endif 143 | -------------------------------------------------------------------------------- /TC1/user_function.c: -------------------------------------------------------------------------------- 1 | #define os_log(format, ...) custom_log("FUNCTION", format, ##__VA_ARGS__) 2 | 3 | #include "TimeUtils.h" 4 | 5 | #include "main.h" 6 | #include "user_gpio.h" 7 | #include "cJSON/cJSON.h" 8 | #include "user_ota.h" 9 | #include "user_mqtt_client.h" 10 | 11 | bool json_slot_analysis( unsigned char x, cJSON * pJsonRoot, cJSON * pJsonSend ); 12 | bool json_slot_task_analysis( unsigned char x, unsigned char y, cJSON * pJsonRoot, cJSON * pJsonSend ); 13 | 14 | void user_function_cmd_received( char *mqtt_topic , char *mqtt_data ) 15 | { 16 | 17 | unsigned char i; 18 | bool update_user_config_flag = false; //标志位,记录最后是否需要更新储存的数据 19 | bool return_flag = true; //为true时返回json结果,否则不返回 20 | 21 | cJSON * pJsonRoot = cJSON_Parse( mqtt_data ); 22 | if ( !pJsonRoot ) 23 | { 24 | os_log( "this is not a json mqtt_data:\r\n%s\r\n", mqtt_data ); 25 | return; 26 | } 27 | 28 | //解析UDP命令device report(MQTT同样回复命令) 29 | cJSON *p_cmd = cJSON_GetObjectItem( pJsonRoot, "cmd" ); 30 | if ( p_cmd && cJSON_IsString( p_cmd ) && strcmp( p_cmd->valuestring, "device report" ) == 0 ) 31 | { 32 | cJSON *pRoot = cJSON_CreateObject( ); 33 | cJSON_AddStringToObject( pRoot, "name", sys_config->micoSystemConfig.name ); 34 | cJSON_AddNumberToObject( pRoot, "type", TYPE ); 35 | cJSON_AddStringToObject( pRoot, "type_name", TYPE_NAME ); 36 | uint32_t run_time = UpTicks( ); // get time in miiliseconds since RTOS start, roll over every 49 days, 17 hours. 37 | cJSON_AddNumberToObject( pRoot, "run_time", run_time/1000 ); 38 | //IP、mac 39 | IPStatusTypedef para; 40 | micoWlanGetIPStatus( ¶, Station ); 41 | cJSON_AddStringToObject( pRoot, "ip", para.ip ); 42 | cJSON_AddStringToObject( pRoot, "mac", strMac ); 43 | //时间 44 | iso8601_time_t iso8601_time; 45 | mico_time_get_iso8601_time( &iso8601_time ); 46 | char time_str[26]; 47 | sprintf(time_str, "%.27s", (char*)&iso8601_time); 48 | cJSON_AddStringToObject( pRoot, "time", time_str ); 49 | cJSON_AddNumberToObject( pRoot, "sntp_count", sntp_count ); 50 | 51 | char *s = cJSON_Print( pRoot ); 52 | // os_log( "pRoot: %s\r\n", s ); 53 | user_mqtt_send( s ); //发送数据 54 | free( (void *) s ); 55 | cJSON_Delete( pRoot ); 56 | // cJSON_Delete(p_cmd); 57 | return; 58 | } 59 | 60 | //以下为解析命令部分 61 | // cJSON *p_name = cJSON_GetObjectItem( pJsonRoot, "name" ); 62 | // cJSON *p_mac = cJSON_GetObjectItem( pJsonRoot, "mac" ); 63 | 64 | //开始正式处理所有命令 65 | cJSON *json_send = cJSON_CreateObject( ); 66 | // cJSON_AddStringToObject( json_send, "mac", strMac ); 67 | 68 | //解析版本 69 | cJSON *p_version = cJSON_GetObjectItem( pJsonRoot, "version" ); 70 | if ( p_version ) 71 | { 72 | os_log("version:%s",VERSION); 73 | cJSON_AddStringToObject( json_send, "version", VERSION ); 74 | } 75 | //解析运行时间 76 | cJSON *p_run_time = cJSON_GetObjectItem( pJsonRoot, "run_time" ); 77 | if ( p_run_time ) 78 | { 79 | cJSON_AddNumberToObject( json_send, "run_time", run_time ); 80 | } 81 | //解析功率 82 | cJSON *p_power = cJSON_GetObjectItem( pJsonRoot, "power" ); 83 | if ( p_power ) 84 | { 85 | char *temp_buf = malloc( 16 ); 86 | if ( temp_buf != NULL ) 87 | { 88 | sprintf( temp_buf, "%ld.%ld", power / 10, power % 10 ); 89 | cJSON_AddStringToObject( json_send, "power", temp_buf ); 90 | free( temp_buf ); 91 | } 92 | os_log("power:%ld",power); 93 | } 94 | //解析主机setting----------------------------------------------------------------- 95 | cJSON *p_setting = cJSON_GetObjectItem( pJsonRoot, "setting" ); 96 | if ( p_setting ) 97 | { 98 | //解析ota 99 | cJSON *p_ota = cJSON_GetObjectItem( p_setting, "ota" ); 100 | if ( p_ota ) 101 | { 102 | if ( cJSON_IsString( p_ota ) ) 103 | user_ota_start( p_ota->valuestring, NULL ); 104 | } 105 | 106 | cJSON *json_setting_send = cJSON_CreateObject( ); 107 | //设置设备名称/deviceid 108 | cJSON *p_setting_name = cJSON_GetObjectItem( p_setting, "name" ); 109 | if ( p_setting_name && cJSON_IsString( p_setting_name ) ) 110 | { 111 | update_user_config_flag = true; 112 | sprintf( sys_config->micoSystemConfig.name, p_setting_name->valuestring ); 113 | } 114 | 115 | //设置mqtt ip 116 | cJSON *p_mqtt_ip = cJSON_GetObjectItem( p_setting, "mqtt_uri" ); 117 | if ( p_mqtt_ip && cJSON_IsString( p_mqtt_ip ) ) 118 | { 119 | update_user_config_flag = true; 120 | sprintf( user_config->mqtt_ip, p_mqtt_ip->valuestring ); 121 | } 122 | 123 | //设置mqtt port 124 | cJSON *p_mqtt_port = cJSON_GetObjectItem( p_setting, "mqtt_port" ); 125 | if ( p_mqtt_port && cJSON_IsNumber( p_mqtt_port ) ) 126 | { 127 | update_user_config_flag = true; 128 | user_config->mqtt_port = p_mqtt_port->valueint; 129 | } 130 | 131 | //设置mqtt user 132 | cJSON *p_mqtt_user = cJSON_GetObjectItem( p_setting, "mqtt_user" ); 133 | if ( p_mqtt_user && cJSON_IsString( p_mqtt_user ) ) 134 | { 135 | update_user_config_flag = true; 136 | sprintf( user_config->mqtt_user, p_mqtt_user->valuestring ); 137 | } 138 | 139 | //设置mqtt password 140 | cJSON *p_mqtt_password = cJSON_GetObjectItem( p_setting, "mqtt_password" ); 141 | if ( p_mqtt_password && cJSON_IsString( p_mqtt_password ) ) 142 | { 143 | update_user_config_flag = true; 144 | sprintf( user_config->mqtt_password, p_mqtt_password->valuestring ); 145 | } 146 | 147 | //开发返回数据 148 | //返回设备ota 149 | if ( p_ota ) cJSON_AddStringToObject( json_setting_send, "ota", p_ota->valuestring ); 150 | 151 | //返回设备名称/deviceid 152 | if ( p_setting_name ) cJSON_AddStringToObject( json_setting_send, "name", sys_config->micoSystemConfig.name ); 153 | //返回mqtt ip 154 | if ( p_mqtt_ip ) cJSON_AddStringToObject( json_setting_send, "mqtt_uri", user_config->mqtt_ip ); 155 | //返回mqtt port 156 | if ( p_mqtt_port ) cJSON_AddNumberToObject( json_setting_send, "mqtt_port", user_config->mqtt_port ); 157 | //返回mqtt user 158 | if ( p_mqtt_user ) cJSON_AddStringToObject( json_setting_send, "mqtt_user", user_config->mqtt_user ); 159 | //返回mqtt password 160 | if ( p_mqtt_password ) cJSON_AddStringToObject( json_setting_send, "mqtt_password", user_config->mqtt_password ); 161 | 162 | cJSON_AddItemToObject( json_send, "setting", json_setting_send ); 163 | } 164 | 165 | //解析slot----------------------------------------------------------------- 166 | for ( i = 0; i < SLOT_NUM; i++ ) 167 | { 168 | if ( json_slot_analysis( i, pJsonRoot, json_send ) ) 169 | update_user_config_flag = true; 170 | } 171 | 172 | cJSON_AddStringToObject( json_send, "name", sys_config->micoSystemConfig.name ); 173 | 174 | if ( return_flag == true ) 175 | { 176 | char *json_str = cJSON_Print( json_send ); 177 | // os_log( "pRoot: %s\r\n", json_str ); 178 | user_mqtt_send( json_str ); //发送数据 179 | free( (void *) json_str ); 180 | } 181 | cJSON_Delete( json_send ); 182 | 183 | if ( update_user_config_flag ) 184 | { 185 | mico_system_context_update( sys_config ); 186 | update_user_config_flag = false; 187 | } 188 | 189 | cJSON_Delete( pJsonRoot ); 190 | 191 | } 192 | 193 | /* 194 | *解析处理定时任务json 195 | *udp_flag:发送udp/mqtt标志位,此处修改插座开关状态时,需要实时更新给domoticz 196 | *x:插座编号 197 | */ 198 | bool json_slot_analysis( unsigned char x, cJSON * pJsonRoot, cJSON * pJsonSend ) 199 | { 200 | if ( !pJsonRoot ) return false; 201 | if ( !pJsonSend ) return false; 202 | 203 | bool return_flag = false; 204 | char slot_str[] = "slotX"; 205 | slot_str[4] = x + '0'; 206 | 207 | cJSON *p_slot = cJSON_GetObjectItem( pJsonRoot, slot_str ); 208 | 209 | //解析slot on------------------------------------------------------ 210 | if ( p_slot ) 211 | { 212 | if ( cJSON_IsNumber( p_slot ) ) 213 | { 214 | user_relay_set( x, p_slot->valueint ); 215 | return_flag = true; 216 | } 217 | user_mqtt_send_slot_state( x ); 218 | } 219 | cJSON_AddNumberToObject( pJsonSend, slot_str, user_config->slot[x] ); 220 | 221 | return return_flag; 222 | } 223 | 224 | 225 | unsigned char strtohex( char a, char b ) 226 | { 227 | if ( a >= 0x30 && a <= 0x39 ) 228 | a -= 0x30; 229 | else if ( a >= 0x41 && a <= 0x46 ) 230 | { 231 | a = a + 10 - 0x41; 232 | } else if ( a >= 0x61 && a <= 0x66 ) 233 | { 234 | a = a + 10 - 0x61; 235 | } 236 | 237 | if ( b >= 0x30 && b <= 0x39 ) 238 | b -= 0x30; 239 | else if ( b >= 0x41 && b <= 0x46 ) 240 | { 241 | b = b + 10 - 0x41; 242 | } else if ( b >= 0x61 && b <= 0x66 ) 243 | { 244 | b = b + 10 - 0x61; 245 | } 246 | 247 | return a * 16 + b; 248 | } 249 | -------------------------------------------------------------------------------- /TC1/user_function.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __USER_FUNCTION_H_ 3 | #define __USER_FUNCTION_H_ 4 | 5 | 6 | #include "mico.h" 7 | #include "MiCOKit_EXT.h" 8 | 9 | void user_send( int udp_flag, char *s ); 10 | void user_function_cmd_received(char *mqtt_topic , char *mqtt_data); 11 | unsigned char strtohex(char a, char b); 12 | 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /TC1/user_gpio.c: -------------------------------------------------------------------------------- 1 | #define os_log(format, ...) custom_log("KEY", format, ##__VA_ARGS__) 2 | 3 | #include "main.h" 4 | #include "user_gpio.h" 5 | #include "user_mqtt_client.h" 6 | #include "cJSON/cJSON.h" 7 | 8 | mico_gpio_t relay[Relay_NUM] = { Relay_0, Relay_1, Relay_2, Relay_3, Relay_4, Relay_5 }; 9 | 10 | void user_led_set( char x ) 11 | { 12 | if ( x == -1 ) 13 | MicoGpioOutputTrigger( Led ); 14 | else if ( x ) 15 | MicoGpioOutputHigh( Led ); 16 | else 17 | MicoGpioOutputLow( Led ); 18 | } 19 | 20 | bool relay_out( void ) 21 | { 22 | unsigned char i; 23 | for ( i = 0; i < SLOT_NUM; i++ ) 24 | { 25 | if ( user_config->slot[i] != 0 ) 26 | { 27 | return true; 28 | } 29 | } 30 | return false; 31 | } 32 | 33 | /*user_relay_set 34 | * 设置继电器开关 35 | * x:编号 0-5 36 | * y:开关 0:关 1:开 37 | */ 38 | void user_relay_set(unsigned char x,unsigned char y ) 39 | { 40 | if (x >= SLOT_NUM ) return; 41 | 42 | if((y == 1) ? Relay_ON : Relay_OFF) MicoGpioOutputHigh( relay[x] );else MicoGpioOutputLow( relay[x] ); 43 | 44 | user_config->slot[x] = y; 45 | 46 | if ( relay_out( ) ) 47 | user_led_set( 1 ); 48 | else 49 | user_led_set( 0 ); 50 | } 51 | 52 | /* 53 | * 设置所有继电器开关 54 | * y:0:全部关 1:根据记录状态开关所有 55 | * 56 | */ 57 | void user_relay_set_all( char y ) 58 | { 59 | char i; 60 | for ( i = 0; i < SLOT_NUM; i++ ) 61 | user_relay_set( i, y ); 62 | } 63 | 64 | static void key_long_press( void ) 65 | { 66 | // os_log("key_long_press"); 67 | // user_led_set( 1 ); 68 | // user_mqtt_send( "mqtt test" ); 69 | } 70 | 71 | static void key_long_10s_press( void ) 72 | { 73 | // OSStatus err; 74 | // char i = 0; 75 | os_log( "WARNGIN: user params restored!" ); 76 | // for ( i = 0; i < 3; i++ ) 77 | // { 78 | // user_led_set( 1 ); 79 | // mico_rtos_thread_msleep( 100 ); 80 | // user_led_set( 0 ); 81 | // } 82 | // 83 | appRestoreDefault_callback( user_config, sizeof(user_config_t) ); 84 | sys_config->micoSystemConfig.ssid[0] = 0; 85 | mico_system_context_update( mico_system_context_get( ) ); 86 | } 87 | static void key_short_press( void ) 88 | { 89 | char i; 90 | // OSStatus err; 91 | 92 | if ( relay_out() ) 93 | { 94 | user_relay_set_all( 0 ); 95 | } 96 | else 97 | { 98 | user_relay_set_all( 1 ); 99 | } 100 | 101 | for ( i = 0; i < SLOT_NUM; i++ ) 102 | { 103 | user_mqtt_send_slot_state(i); 104 | } 105 | 106 | 107 | 108 | } 109 | mico_timer_t user_key_timer; 110 | uint16_t key_time = 0; 111 | #define BUTTON_LONG_PRESS_TIME 10 //100ms*10=1s 112 | 113 | static void key_timeout_handler( void* arg ) 114 | { 115 | 116 | static uint8_t key_trigger, key_continue; 117 | static uint8_t key_last; 118 | //按键扫描程序 119 | uint8_t tmp = ~(0xfe | MicoGpioInputGet( Button )); 120 | key_trigger = tmp & (tmp ^ key_continue); 121 | key_continue = tmp; 122 | // os_log("button scan:%02x %02x",key_trigger,key_continue); 123 | if ( key_trigger != 0 ) key_time = 0; //新按键按下时,重新开始按键计时 124 | if ( key_continue != 0 ) 125 | { 126 | //any button pressed 127 | key_time++; 128 | if ( key_time < BUTTON_LONG_PRESS_TIME ) 129 | key_last = key_continue; 130 | else 131 | { 132 | os_log("button long pressed:%d",key_time); 133 | 134 | if ( key_time == 30 ) 135 | { 136 | key_long_press( ); 137 | } 138 | else if ( key_time == 100 ) 139 | { 140 | key_long_10s_press( ); 141 | } 142 | else if ( key_time == 102 ) 143 | { 144 | user_led_set( 1 ); 145 | } 146 | else if ( key_time == 103 ) 147 | { 148 | user_led_set( 0 ); 149 | key_time = 101; 150 | } 151 | } 152 | 153 | } else 154 | { 155 | //button released 156 | if ( key_time < BUTTON_LONG_PRESS_TIME ) 157 | { //100ms*10=1s 大于1s为长按 158 | key_time = 0; 159 | os_log("button short pressed:%d",key_time); 160 | key_short_press( ); 161 | } else if ( key_time > 100 ) 162 | { 163 | MicoSystemReboot( ); 164 | } 165 | key_last = 0; 166 | mico_rtos_stop_timer( &user_key_timer ); 167 | } 168 | } 169 | 170 | static void key_falling_irq_handler( void* arg ) 171 | { 172 | mico_rtos_start_timer( &user_key_timer ); 173 | } 174 | void key_init( void ) 175 | { 176 | // MicoGpioInitialize( Button, INPUT_PULL_UP ); 177 | mico_rtos_init_timer( &user_key_timer, 100, key_timeout_handler, NULL ); 178 | 179 | MicoGpioEnableIRQ( Button, IRQ_TRIGGER_FALLING_EDGE, key_falling_irq_handler, NULL ); 180 | 181 | } 182 | 183 | -------------------------------------------------------------------------------- /TC1/user_gpio.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __USER_KEY_H_ 3 | #define __USER_KEY_H_ 4 | 5 | 6 | #include "mico.h" 7 | #include "MiCOKit_EXT.h" 8 | 9 | extern void user_led_set(char x); 10 | extern void key_init(void); 11 | extern void user_relay_set(unsigned char x,unsigned char y ); 12 | extern void user_relay_set_all( char y ); 13 | extern bool relay_out( void ); 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /TC1/user_mqtt_client.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file mqtt_client.c 4 | * @author Eshen Wang 5 | * @version V1.0.0 6 | * @date 16-Nov-2015 7 | * @brief MiCO application demonstrate a MQTT client. 8 | ****************************************************************************** 9 | * @attention 10 | * 11 | * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS 12 | * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE 13 | * TIME. AS A RESULT, MXCHIP Inc. SHALL NOT BE HELD LIABLE FOR ANY 14 | * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING 15 | * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE 16 | * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. 17 | * 18 | *

© COPYRIGHT 2014 MXCHIP Inc.

19 | ****************************************************************************** 20 | */ 21 | #define app_log(M, ...) custom_log("APP", M, ##__VA_ARGS__) 22 | #define mqtt_log(M, ...) custom_log("MQTT", M, ##__VA_ARGS__) 23 | 24 | #include "main.h" 25 | #include "mico.h" 26 | #include "MQTTClient.h" 27 | #include "user_function.h" 28 | #include "user_gpio.h" 29 | #include "user_mqtt_client.h" 30 | #include "cJSON/cJSON.h" 31 | 32 | //#define MQTT_CLIENT_SSL_ENABLE // ssl 33 | 34 | #define MAX_MQTT_TOPIC_SIZE (256) 35 | #define MAX_MQTT_DATA_SIZE (1024) 36 | #define MAX_MQTT_SEND_QUEUE_SIZE (10) 37 | 38 | #ifdef MQTT_CLIENT_SSL_ENABLE 39 | 40 | #define MQTT_SERVER "test.mosquitto.org" 41 | #define MQTT_SERVER_PORT 8883 42 | char* mqtt_server_ssl_cert_str = 43 | "-----BEGIN CERTIFICATE-----\r\n\ 44 | MIIC8DCCAlmgAwIBAgIJAOD63PlXjJi8MA0GCSqGSIb3DQEBBQUAMIGQMQswCQYD\r\n\ 45 | VQQGEwJHQjEXMBUGA1UECAwOVW5pdGVkIEtpbmdkb20xDjAMBgNVBAcMBURlcmJ5\r\n\ 46 | MRIwEAYDVQQKDAlNb3NxdWl0dG8xCzAJBgNVBAsMAkNBMRYwFAYDVQQDDA1tb3Nx\r\n\ 47 | dWl0dG8ub3JnMR8wHQYJKoZIhvcNAQkBFhByb2dlckBhdGNob28ub3JnMB4XDTEy\r\n\ 48 | MDYyOTIyMTE1OVoXDTIyMDYyNzIyMTE1OVowgZAxCzAJBgNVBAYTAkdCMRcwFQYD\r\n\ 49 | VQQIDA5Vbml0ZWQgS2luZ2RvbTEOMAwGA1UEBwwFRGVyYnkxEjAQBgNVBAoMCU1v\r\n\ 50 | c3F1aXR0bzELMAkGA1UECwwCQ0ExFjAUBgNVBAMMDW1vc3F1aXR0by5vcmcxHzAd\r\n\ 51 | BgkqhkiG9w0BCQEWEHJvZ2VyQGF0Y2hvby5vcmcwgZ8wDQYJKoZIhvcNAQEBBQAD\r\n\ 52 | gY0AMIGJAoGBAMYkLmX7SqOT/jJCZoQ1NWdCrr/pq47m3xxyXcI+FLEmwbE3R9vM\r\n\ 53 | rE6sRbP2S89pfrCt7iuITXPKycpUcIU0mtcT1OqxGBV2lb6RaOT2gC5pxyGaFJ+h\r\n\ 54 | A+GIbdYKO3JprPxSBoRponZJvDGEZuM3N7p3S/lRoi7G5wG5mvUmaE5RAgMBAAGj\r\n\ 55 | UDBOMB0GA1UdDgQWBBTad2QneVztIPQzRRGj6ZHKqJTv5jAfBgNVHSMEGDAWgBTa\r\n\ 56 | d2QneVztIPQzRRGj6ZHKqJTv5jAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUA\r\n\ 57 | A4GBAAqw1rK4NlRUCUBLhEFUQasjP7xfFqlVbE2cRy0Rs4o3KS0JwzQVBwG85xge\r\n\ 58 | REyPOFdGdhBY2P1FNRy0MDr6xr+D2ZOwxs63dG1nnAnWZg7qwoLgpZ4fESPD3PkA\r\n\ 59 | 1ZgKJc2zbSQ9fCPxt2W3mdVav66c6fsb7els2W2Iz7gERJSX\r\n\ 60 | -----END CERTIFICATE-----"; 61 | 62 | #else // ! MQTT_CLIENT_SSL_ENABLE 63 | 64 | #define MQTT_SERVER user_config->mqtt_ip 65 | #define MQTT_SERVER_PORT user_config->mqtt_port 66 | 67 | #endif // MQTT_CLIENT_SSL_ENABLE 68 | 69 | typedef struct 70 | { 71 | char topic[MAX_MQTT_TOPIC_SIZE]; 72 | char qos; 73 | char retained; 74 | 75 | uint8_t data[MAX_MQTT_DATA_SIZE]; 76 | uint32_t datalen; 77 | } mqtt_recv_msg_t, *p_mqtt_recv_msg_t, mqtt_send_msg_t, *p_mqtt_send_msg_t; 78 | 79 | static void mqtt_client_thread( mico_thread_arg_t arg ); 80 | static void messageArrived( MessageData* md ); 81 | static OSStatus mqtt_msg_publish( Client *c, const char* topic, char qos, char retained, const unsigned char* msg, uint32_t msg_len ); 82 | 83 | OSStatus user_recv_handler( void *arg ); 84 | // OSStatus user_mqtt_send_slot_state(unsigned char slot_id ); 85 | // OSStatus user_mqtt_send_tc1_state(void); 86 | // OSStatus user_mqtt_hass_auto_slot( char slot_id ); 87 | // OSStatus user_mqtt_hass_auto_power( void ); 88 | 89 | bool isconnect = false; 90 | mico_queue_t mqtt_msg_send_queue = NULL; 91 | 92 | Client c; // mqtt client object 93 | Network n; // socket network for mqtt client 94 | 95 | static mico_worker_thread_t mqtt_client_worker_thread; /* Worker thread to manage send/recv events */ 96 | // static mico_timed_event_t mqtt_client_send_event; 97 | 98 | char topic_state[MAX_MQTT_TOPIC_SIZE]; 99 | char topic_set[MAX_MQTT_TOPIC_SIZE]; 100 | 101 | mico_timer_t timer_handle; 102 | static uint8_t timer_status = 0; 103 | void user_mqtt_timer_func( void *arg ) 104 | { 105 | char *buf1 = NULL; 106 | if ( mico_rtos_is_queue_empty( &mqtt_msg_send_queue ) == true ) 107 | { 108 | timer_status++; 109 | switch ( timer_status ) 110 | { 111 | case 1: 112 | user_mqtt_hass_auto_power( ); 113 | break; 114 | case 2: 115 | user_mqtt_hass_auto_slot( 0 ); 116 | break; 117 | case 3: 118 | user_mqtt_hass_auto_slot( 1 ); 119 | break; 120 | case 4: 121 | user_mqtt_hass_auto_slot( 2 ); 122 | break; 123 | case 5: 124 | user_mqtt_hass_auto_slot( 3 ); 125 | break; 126 | case 6: 127 | user_mqtt_hass_auto_slot( 4 ); 128 | break; 129 | case 7: 130 | user_mqtt_hass_auto_slot( 5 ); 131 | break; 132 | case 8: 133 | user_mqtt_send_tc1_state(); 134 | break; 135 | case 9: 136 | buf1 = malloc( 256 ); //idx为1位时长度为24 137 | if ( buf1 != NULL ) 138 | { 139 | sprintf( 140 | buf1, 141 | "{\"mac\":\"%s\",\"version\":null,\"slot0\":null,\"slot1\":null,\"slot2\":null,\"slot3\":null,\"slot4\":null,\"slot5\":null}", 142 | strMac ); //触发上报 143 | user_function_cmd_received( NULL, buf1 ); 144 | free( buf1 ); 145 | } 146 | break; 147 | case 10: 148 | buf1 = malloc( 32 ); //idx为1位时长度为24 149 | if ( buf1 != NULL ) 150 | { 151 | sprintf( buf1,"{\"cmd\":\"device report\"}"); 152 | user_function_cmd_received( NULL, buf1 ); 153 | free( buf1 ); 154 | } 155 | break; 156 | default: 157 | mico_stop_timer( &timer_handle ); 158 | // mico_deinit_timer( &timer_handle ); 159 | break; 160 | } 161 | } 162 | } 163 | 164 | /* Application entrance */ 165 | OSStatus user_mqtt_init( void ) 166 | { 167 | OSStatus err = kNoErr; 168 | 169 | sprintf( topic_set, MQTT_CLIENT_SUB_TOPIC, sys_config->micoSystemConfig.name); 170 | sprintf( topic_state, MQTT_CLIENT_PUB_TOPIC, sys_config->micoSystemConfig.name ); 171 | 172 | #ifdef MQTT_CLIENT_SSL_ENABLE 173 | int mqtt_thread_stack_size = 0x3000; 174 | #else 175 | //TODO size:0x800 176 | int mqtt_thread_stack_size = 0x2000; 177 | #endif 178 | uint32_t mqtt_lib_version = MQTTClientLibVersion( ); 179 | app_log( "MQTT client version: [%ld.%ld.%ld]", 180 | 0xFF & (mqtt_lib_version >> 16), 0xFF & (mqtt_lib_version >> 8), 0xFF & mqtt_lib_version); 181 | 182 | /* create mqtt msg send queue */ 183 | err = mico_rtos_init_queue( &mqtt_msg_send_queue, "mqtt_msg_send_queue", sizeof(p_mqtt_send_msg_t), 184 | MAX_MQTT_SEND_QUEUE_SIZE ); 185 | require_noerr_action( err, exit, app_log("ERROR: create mqtt msg send queue err=%d.", err) ); 186 | 187 | /* start mqtt client */ 188 | err = mico_rtos_create_thread( NULL, MICO_APPLICATION_PRIORITY, "mqtt_client", 189 | (mico_thread_function_t) mqtt_client_thread, 190 | mqtt_thread_stack_size, 0 ); 191 | require_noerr_string( err, exit, "ERROR: Unable to start the mqtt client thread." ); 192 | 193 | /* Create a worker thread for user handling MQTT data event */ 194 | err = mico_rtos_create_worker_thread( &mqtt_client_worker_thread, MICO_APPLICATION_PRIORITY, 0x800, 5 ); 195 | require_noerr_string( err, exit, "ERROR: Unable to start the mqtt client worker thread." ); 196 | 197 | exit: 198 | if ( kNoErr != err ) app_log("ERROR, app thread exit err: %d", err); 199 | return err; 200 | } 201 | 202 | static OSStatus mqtt_client_release( Client *c, Network *n ) 203 | { 204 | OSStatus err = kNoErr; 205 | 206 | if ( c->isconnected ) MQTTDisconnect( c ); 207 | 208 | n->disconnect( n ); // close connection 209 | 210 | if ( MQTT_SUCCESS != MQTTClientDeinit( c ) ) 211 | { 212 | app_log("MQTTClientDeinit failed!"); 213 | err = kDeletedErr; 214 | } 215 | return err; 216 | } 217 | 218 | // publish msg to mqtt server 219 | static OSStatus mqtt_msg_publish( Client *c, const char* topic, char qos, char retained, 220 | const unsigned char* msg, 221 | uint32_t msg_len ) 222 | { 223 | OSStatus err = kUnknownErr; 224 | int ret = 0; 225 | MQTTMessage publishData = MQTTMessage_publishData_initializer; 226 | 227 | require( topic && msg_len && msg, exit ); 228 | 229 | // upload data qos0 230 | publishData.qos = (enum QoS) qos; 231 | publishData.retained = retained; 232 | publishData.payload = (void*) msg; 233 | publishData.payloadlen = msg_len; 234 | 235 | ret = MQTTPublish( c, topic, &publishData ); 236 | 237 | if ( MQTT_SUCCESS == ret ) 238 | { 239 | err = kNoErr; 240 | } else if ( MQTT_SOCKET_ERR == ret ) 241 | { 242 | err = kConnectionErr; 243 | } else 244 | { 245 | err = kUnknownErr; 246 | } 247 | 248 | exit: 249 | return err; 250 | } 251 | 252 | void mqtt_client_thread( mico_thread_arg_t arg ) 253 | { 254 | OSStatus err = kUnknownErr; 255 | 256 | int rc = -1; 257 | fd_set readfds; 258 | struct timeval t = { 0, MQTT_YIELD_TMIE * 1000 }; 259 | 260 | ssl_opts ssl_settings; 261 | MQTTPacket_connectData connectData = MQTTPacket_connectData_initializer; 262 | 263 | p_mqtt_send_msg_t p_send_msg = NULL; 264 | int msg_send_event_fd = -1; 265 | bool no_mqtt_msg_exchange = true; 266 | 267 | mqtt_log("MQTT client thread started..."); 268 | 269 | memset( &c, 0, sizeof(c) ); 270 | memset( &n, 0, sizeof(n) ); 271 | 272 | /* create msg send queue event fd */ 273 | msg_send_event_fd = mico_create_event_fd( mqtt_msg_send_queue ); 274 | require_action( msg_send_event_fd >= 0, exit, mqtt_log("ERROR: create msg send queue event fd failed!!!") ); 275 | 276 | MQTT_start: 277 | 278 | isconnect = false; 279 | /* 1. create network connection */ 280 | #ifdef MQTT_CLIENT_SSL_ENABLE 281 | ssl_settings.ssl_enable = true; 282 | ssl_settings.ssl_debug_enable = false; // ssl debug log 283 | ssl_settings.ssl_version = TLS_V1_2_MODE; 284 | ssl_settings.ca_str_len = strlen(mqtt_server_ssl_cert_str); 285 | ssl_settings.ca_str = mqtt_server_ssl_cert_str; 286 | #else 287 | ssl_settings.ssl_enable = false; 288 | #endif 289 | LinkStatusTypeDef LinkStatus; 290 | while ( 1 ) 291 | { 292 | isconnect = false; 293 | mico_rtos_thread_sleep( 3 ); 294 | if ( MQTT_SERVER[0] < 0x20 || MQTT_SERVER[0] > 0x7f || MQTT_SERVER_PORT < 1 ) continue; //未配置mqtt服务器时不连接 295 | 296 | micoWlanGetLinkStatus( &LinkStatus ); 297 | if ( LinkStatus.is_connected != 1 ) 298 | { 299 | mqtt_log("ERROR: WIFI not connection err=%d, waiting 3s for connecting and then connecting MQTT.", rc); 300 | mico_rtos_thread_sleep( 3 ); 301 | continue; 302 | } 303 | 304 | rc = NewNetwork( &n, MQTT_SERVER, MQTT_SERVER_PORT, ssl_settings ); 305 | if ( rc == MQTT_SUCCESS ) break; 306 | mqtt_log("ERROR: MQTT network connection err=%d, reconnect after 3s...", rc); 307 | 308 | } 309 | mqtt_log("MQTT network connection success!"); 310 | 311 | /* 2. init mqtt client */ 312 | //c.heartbeat_retry_max = 2; 313 | rc = MQTTClientInit( &c, &n, MQTT_CMD_TIMEOUT ); 314 | require_noerr_string( rc, MQTT_reconnect, "ERROR: MQTT client init err." ); 315 | 316 | mqtt_log("MQTT client init success!"); 317 | 318 | /* 3. create mqtt client connection */ 319 | // connectData.willFlag = 0; 320 | connectData.MQTTVersion = 4; // 3: 3.1, 4: v3.1.1 321 | connectData.clientID.cstring = sys_config->micoSystemConfig.name; 322 | connectData.username.cstring = user_config->mqtt_user; 323 | connectData.password.cstring = user_config->mqtt_password; 324 | connectData.keepAliveInterval = MQTT_CLIENT_KEEPALIVE; 325 | connectData.cleansession = 1; 326 | 327 | connectData.willFlag = 1; 328 | connectData.will.topicName.cstring = topic_state; 329 | connectData.will.message.cstring = "offline"; 330 | connectData.will.retained = 1; 331 | connectData.will.qos = 1; 332 | 333 | rc = MQTTConnect( &c, &connectData ); 334 | require_noerr_string( rc, MQTT_reconnect, "ERROR: MQTT client connect err." ); 335 | 336 | mqtt_log("MQTT client connect success!"); 337 | 338 | /* 4. mqtt client subscribe */ 339 | rc = MQTTSubscribe( &c, topic_set, QOS0, messageArrived ); 340 | require_noerr_string( rc, MQTT_reconnect, "ERROR: MQTT client subscribe err." ); 341 | mqtt_log("MQTT client subscribe success! recv_topic=[%s].", topic_set); 342 | /*4.1 连接成功后先更新发送一次数据*/ 343 | isconnect = true; 344 | timer_status = 0; 345 | mico_init_timer( &timer_handle, 150, user_mqtt_timer_func, &arg ); 346 | mico_start_timer( &timer_handle ); 347 | /* 5. client loop for recv msg && keepalive */ 348 | while ( 1 ) 349 | { 350 | isconnect = true; 351 | no_mqtt_msg_exchange = true; 352 | FD_ZERO( &readfds ); 353 | FD_SET( c.ipstack->my_socket, &readfds ); 354 | FD_SET( msg_send_event_fd, &readfds ); 355 | select( msg_send_event_fd + 1, &readfds, NULL, NULL, &t ); 356 | 357 | /* recv msg from server */ 358 | if ( FD_ISSET( c.ipstack->my_socket, &readfds ) ) 359 | { 360 | rc = MQTTYield( &c, (int) MQTT_YIELD_TMIE ); 361 | require_noerr( rc, MQTT_reconnect ); 362 | no_mqtt_msg_exchange = false; 363 | } 364 | 365 | /* recv msg from user worker thread to be sent to server */ 366 | if ( FD_ISSET( msg_send_event_fd, &readfds ) ) 367 | { 368 | while ( mico_rtos_is_queue_empty( &mqtt_msg_send_queue ) == false ) 369 | { 370 | // get msg from send queue 371 | mico_rtos_pop_from_queue( &mqtt_msg_send_queue, &p_send_msg, 0 ); 372 | // require_string( p_send_msg, exit, "Wrong data point" ); 373 | 374 | // send message to server 375 | err = mqtt_msg_publish( &c, p_send_msg->topic, p_send_msg->qos, p_send_msg->retained, 376 | p_send_msg->data, 377 | p_send_msg->datalen ); 378 | 379 | require_noerr_string( err, MQTT_reconnect, "ERROR: MQTT publish data err" ); 380 | 381 | mqtt_log("MQTT publish data success! send_topic=[%s], msg=[%ld].\r\n", p_send_msg->topic, p_send_msg->datalen); 382 | no_mqtt_msg_exchange = false; 383 | free( p_send_msg ); 384 | p_send_msg = NULL; 385 | } 386 | } 387 | 388 | /* if no msg exchange, we need to check ping msg to keep alive. */ 389 | if ( no_mqtt_msg_exchange ) 390 | { 391 | rc = keepalive( &c ); 392 | require_noerr_string( rc, MQTT_reconnect, "ERROR: keepalive err" ); 393 | } 394 | } 395 | 396 | MQTT_reconnect: 397 | 398 | mqtt_log("Disconnect MQTT client, and reconnect after 5s, reason: mqtt_rc = %d, err = %d", rc, err ); 399 | 400 | timer_status=100; 401 | 402 | mqtt_client_release( &c, &n ); 403 | isconnect = false; 404 | user_led_set( -1 ); 405 | mico_rtos_thread_msleep( 100 ); 406 | user_led_set( -1 ); 407 | mico_rtos_thread_sleep( 5 ); 408 | goto MQTT_start; 409 | 410 | exit: 411 | isconnect = false; 412 | mqtt_log("EXIT: MQTT client exit with err = %d.", err); 413 | mqtt_client_release( &c, &n ); 414 | mico_rtos_delete_thread( NULL ); 415 | } 416 | 417 | // callback, msg received from mqtt server 418 | static void messageArrived( MessageData* md ) 419 | { 420 | OSStatus err = kUnknownErr; 421 | p_mqtt_recv_msg_t p_recv_msg = NULL; 422 | MQTTMessage* message = md->message; 423 | /* 424 | app_log("MQTT messageArrived callback: topiclen=[%d][%s],\t payloadlen=[%d][%s]",md->topicName->lenstring.len, 425 | md->topicName->lenstring.data,(int)message->payloadlen,(char*)message->payload); 426 | */ 427 | // mqtt_log("======MQTT received callback ![%d]======", MicoGetMemoryInfo()->free_memory ); 428 | p_recv_msg = (p_mqtt_recv_msg_t) calloc( 1, sizeof(mqtt_recv_msg_t) ); 429 | require_action( p_recv_msg, exit, err = kNoMemoryErr ); 430 | 431 | p_recv_msg->datalen = message->payloadlen; 432 | p_recv_msg->qos = (char) (message->qos); 433 | p_recv_msg->retained = message->retained; 434 | strncpy( p_recv_msg->topic, md->topicName->lenstring.data, md->topicName->lenstring.len ); 435 | memcpy( p_recv_msg->data, message->payload, message->payloadlen ); 436 | 437 | err = mico_rtos_send_asynchronous_event( &mqtt_client_worker_thread, user_recv_handler, p_recv_msg ); 438 | require_noerr( err, exit ); 439 | 440 | exit: 441 | if ( err != kNoErr ) 442 | { 443 | app_log("ERROR: Recv data err = %d", err); 444 | if ( p_recv_msg ) free( p_recv_msg ); 445 | } 446 | return; 447 | } 448 | 449 | /* Application process MQTT received data */ 450 | OSStatus user_recv_handler( void *arg ) 451 | { 452 | OSStatus err = kUnknownErr; 453 | p_mqtt_recv_msg_t p_recv_msg = arg; 454 | require( p_recv_msg, exit ); 455 | 456 | app_log("user get data success! from_topic=[%s], msg=[%ld].\r\n", p_recv_msg->topic, p_recv_msg->datalen); 457 | user_function_cmd_received( p_recv_msg->topic, (char *)p_recv_msg->data ); 458 | free( p_recv_msg ); 459 | 460 | exit: 461 | return err; 462 | } 463 | 464 | OSStatus user_mqtt_send_topic( char *topic, char *arg, char retained,char qos ) 465 | { 466 | OSStatus err = kUnknownErr; 467 | p_mqtt_send_msg_t p_send_msg = NULL; 468 | 469 | // app_log("======App prepare to send ![%d]======", MicoGetMemoryInfo()->free_memory); 470 | 471 | /* Send queue is full, pop the oldest */ 472 | if ( mico_rtos_is_queue_full( &mqtt_msg_send_queue ) == true ) 473 | { 474 | mico_rtos_pop_from_queue( &mqtt_msg_send_queue, &p_send_msg, 0 ); 475 | free( p_send_msg ); 476 | p_send_msg = NULL; 477 | } 478 | 479 | /* Push the latest data into send queue*/ 480 | p_send_msg = (p_mqtt_send_msg_t) calloc( 1, sizeof(mqtt_send_msg_t) ); 481 | require_action( p_send_msg, exit, err = kNoMemoryErr ); 482 | 483 | p_send_msg->qos = qos; 484 | p_send_msg->retained = retained; 485 | p_send_msg->datalen = strlen( arg ); 486 | memcpy( p_send_msg->data, arg, p_send_msg->datalen ); 487 | strncpy( p_send_msg->topic, topic, MAX_MQTT_TOPIC_SIZE ); 488 | 489 | err = mico_rtos_push_to_queue( &mqtt_msg_send_queue, &p_send_msg, 0 ); 490 | require_noerr( err, exit ); 491 | 492 | //app_log("Push user msg into send queue success!"); 493 | 494 | exit: 495 | if ( err != kNoErr && p_send_msg ) free( p_send_msg ); 496 | return err; 497 | } 498 | 499 | /* Application collect data and seng them to MQTT send queue */ 500 | OSStatus user_mqtt_send( char *arg ) 501 | { 502 | return user_mqtt_send_topic( topic_state, arg, 0, 0 ); 503 | } 504 | 505 | //更新ha开关状态 506 | OSStatus user_mqtt_send_slot_state(unsigned char slot_id ) 507 | { 508 | OSStatus err = kUnknownErr; 509 | if (isconnect == false) 510 | { 511 | return err; 512 | } 513 | char *send_buf = NULL; 514 | char *topic_buf = NULL; 515 | send_buf = malloc( 64 ); // 516 | topic_buf = malloc( 64 ); // 517 | if ( send_buf != NULL && topic_buf != NULL ) 518 | { 519 | sprintf( topic_buf, "stat/%s/slot%d", sys_config->micoSystemConfig.name, slot_id ); 520 | sprintf( send_buf, "{\"slot%d\":%d}", slot_id, user_config->slot[slot_id] ); 521 | err = user_mqtt_send_topic( topic_buf, send_buf, 1, 1 ); 522 | } 523 | if ( send_buf ) free( send_buf ); 524 | if ( topic_buf ) free( topic_buf ); 525 | return err; 526 | } 527 | 528 | //更新状态 529 | OSStatus user_mqtt_send_tc1_state(void) 530 | { 531 | OSStatus err = kUnknownErr; 532 | if (isconnect == false) 533 | { 534 | return err; 535 | } 536 | char *send_buf = NULL; 537 | send_buf = malloc( 32 ); 538 | if ( send_buf != NULL) 539 | { 540 | sprintf( send_buf, "online"); 541 | err = user_mqtt_send_topic( topic_state, send_buf, 1, 1 ); 542 | } 543 | if ( send_buf ) free( send_buf ); 544 | return err; 545 | } 546 | 547 | //hass mqtt自动发现数据开关发送 548 | OSStatus user_mqtt_hass_auto_slot( char slot_id ) 549 | { 550 | OSStatus err = kUnknownErr; 551 | if (isconnect == false) 552 | { 553 | return err; 554 | } 555 | char *send_buf = NULL; 556 | char *topic_buf = NULL; 557 | send_buf = malloc( 512 ); // 558 | topic_buf = malloc( 128 ); // 559 | if ( send_buf != NULL && topic_buf != NULL ) 560 | { 561 | sprintf( topic_buf, "homeassistant/switch/%s/slot%d/config", sys_config->micoSystemConfig.name, slot_id ); 562 | sprintf( send_buf, "{" 563 | "\"name\":\"%s_slot%d\"," 564 | "\"state_topic\":\"stat/%s/slot%d\"," 565 | "\"command_topic\":\"cmnd/%s\"," 566 | "\"payload_on\":\"{\\\"slot%d\\\":1}\"," 567 | "\"payload_off\":\"{\\\"slot%d\\\":0}\"," 568 | "\"availability_topic\":\"stat/%s\"" 569 | "}", 570 | sys_config->micoSystemConfig.name, slot_id, sys_config->micoSystemConfig.name, slot_id, sys_config->micoSystemConfig.name, slot_id, slot_id, sys_config->micoSystemConfig.name ); 571 | err = user_mqtt_send_topic( topic_buf, send_buf, 1, 1 ); 572 | } 573 | if ( send_buf ) free( send_buf ); 574 | if ( topic_buf ) free( topic_buf ); 575 | return err; 576 | } 577 | 578 | //hass mqtt自动发现数据功率发送 579 | OSStatus user_mqtt_hass_auto_power( void ) 580 | { 581 | OSStatus err = kUnknownErr; 582 | if (isconnect == false) 583 | { 584 | return err; 585 | } 586 | char *send_buf = NULL; 587 | char *topic_buf = NULL; 588 | send_buf = malloc( 512 ); // 589 | topic_buf = malloc( 128 ); // 590 | if ( send_buf != NULL && topic_buf != NULL ) 591 | { 592 | sprintf( topic_buf, "homeassistant/sensor/%s/power/config", sys_config->micoSystemConfig.name ); 593 | sprintf( send_buf, "{" 594 | "\"name\":\"%s_power\"," 595 | "\"state_topic\":\"stat/%s/power\"," 596 | "\"unit_of_measurement\":\"W\"," 597 | "\"icon\":\"mdi:gauge\"," 598 | "\"availability_topic\":\"stat/%s\"" 599 | "}", 600 | sys_config->micoSystemConfig.name, sys_config->micoSystemConfig.name, sys_config->micoSystemConfig.name ); 601 | 602 | err = user_mqtt_send_topic( topic_buf, send_buf, 1, 1 ); 603 | } 604 | if ( send_buf ) free( send_buf ); 605 | if ( topic_buf ) free( topic_buf ); 606 | return err; 607 | } 608 | 609 | OSStatus user_mqtt_hass_power( void ) 610 | { 611 | OSStatus err = kUnknownErr; 612 | if (isconnect == false) 613 | { 614 | return err; 615 | } 616 | char *send_buf = NULL; 617 | char *topic_buf = NULL; 618 | send_buf = malloc( 512 ); // 619 | topic_buf = malloc( 128 ); // 620 | if ( send_buf != NULL && topic_buf != NULL ) 621 | { 622 | sprintf( topic_buf, "stat/%s/power", sys_config->micoSystemConfig.name ); 623 | sprintf( send_buf, "%ld.%ld", power / 10, power % 10 ); 624 | err = user_mqtt_send_topic( topic_buf, send_buf, 0, 0 ); 625 | } 626 | if ( send_buf ) free( send_buf ); 627 | if ( topic_buf ) free( topic_buf ); 628 | return err; 629 | } 630 | 631 | bool user_mqtt_isconnect( ) 632 | { 633 | return isconnect; 634 | } 635 | -------------------------------------------------------------------------------- /TC1/user_mqtt_client.h: -------------------------------------------------------------------------------- 1 | #ifndef __USER_MQTT_CLIENT_H_ 2 | #define __USER_MQTT_CLIENT_H_ 3 | 4 | 5 | #include "mico.h" 6 | 7 | #define MQTT_CLIENT_KEEPALIVE 30 8 | 9 | #define MQTT_CMD_TIMEOUT 5000 // 5s 10 | #define MQTT_YIELD_TMIE 5000 // 5s 11 | 12 | 13 | extern OSStatus user_mqtt_init(void); 14 | extern OSStatus user_mqtt_send( char *arg ); 15 | extern bool user_mqtt_isconnect(void); 16 | extern OSStatus user_mqtt_send_slot_state(unsigned char slot_id ); 17 | extern OSStatus user_mqtt_send_tc1_state(void); 18 | extern OSStatus user_mqtt_hass_auto_slot( char slot_id ); 19 | extern OSStatus user_mqtt_hass_power( void ); 20 | extern OSStatus user_mqtt_hass_auto_power( void ); 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /TC1/user_ota.c: -------------------------------------------------------------------------------- 1 | #define os_log(format, ...) custom_log("OTA", format, ##__VA_ARGS__) 2 | 3 | #include "mico.h" 4 | #include "ota_server/ota_server.h" 5 | #include "main.h" 6 | #include "user_mqtt_client.h" 7 | #include "user_function.h" 8 | 9 | static int8_t step_progress = 0; 10 | static int8_t last_progress = 0; 11 | 12 | static void ota_server_status_handler( OTA_STATE_E state, float progress ) 13 | { 14 | int8_t int_progress = (int) progress; 15 | step_progress = int_progress / 5; 16 | char str[64] = { 0 }; 17 | switch ( state ) 18 | { 19 | case OTA_LOADING: 20 | os_log("ota server is loading, progress %.2f%%", progress); 21 | if ( step_progress != last_progress){ 22 | last_progress = step_progress; 23 | sprintf( str, "{\"mac\":\"%s\",\"ota_progress\":%i}", strMac, step_progress*5 ); 24 | } 25 | break; 26 | case OTA_SUCCE: 27 | os_log("ota server daemons success"); 28 | sprintf( str, "{\"mac\":\"%s\",\"ota_progress\":success}", strMac ); 29 | last_progress = 0; 30 | step_progress = 0; 31 | break; 32 | case OTA_FAIL: 33 | os_log("ota server daemons failed"); 34 | sprintf( str, "{\"mac\":\"%s\",\"ota_progress\":-1}", strMac ); 35 | last_progress = 0; 36 | step_progress = 0; 37 | break; 38 | default: 39 | break; 40 | } 41 | if ( str[0] > 0 ) 42 | { 43 | user_mqtt_send( str ); 44 | str[0] = 0; 45 | } 46 | } 47 | 48 | void user_ota_start( char *url, char *md5 ) 49 | { 50 | os_log("ready to ota:%s",url); 51 | ota_server_start( url, md5, ota_server_status_handler ); 52 | } -------------------------------------------------------------------------------- /TC1/user_ota.h: -------------------------------------------------------------------------------- 1 | #ifndef __USER_OTA_H_ 2 | #define __USER_OTA_H_ 3 | 4 | 5 | void user_ota_start(char *url, char *md5); 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /TC1/user_power.c: -------------------------------------------------------------------------------- 1 | #define os_log(format, ...) custom_log("OTA", format, ##__VA_ARGS__) 2 | #include "TimeUtils.h" 3 | 4 | #include "mico.h" 5 | #include "main.h" 6 | #include "user_mqtt_client.h" 7 | #include "user_function.h" 8 | 9 | mico_timer_t power_timer; 10 | 11 | static uint32_t clock_count_last = 0; 12 | static uint32_t clock_count = 0; 13 | static uint32_t timer_count = 0; 14 | static uint32_t timer_irq_count = 0; 15 | 16 | static void power_timer_handler( void* arg ) 17 | { 18 | 19 | // uint8_t pin_input = MicoGpioInputGet( POWER ); 20 | uint32_t timer = 0; 21 | 22 | if ( timer_irq_count > 1 ) 23 | { 24 | timer = (clock_count - clock_count_last); 25 | 26 | os_log("power_irq_handler:%09lu %lu %lu",timer,timer_irq_count,timer_count); 27 | if ( timer_count > 3 ) 28 | { 29 | timer /= 1000; 30 | timer += 4294967; //0xffffffff/1000; 31 | } else if ( clock_count < clock_count_last ) 32 | { 33 | timer += 0xffffffff; 34 | timer /= 1000; 35 | }else timer/=1000; 36 | power = 17100000 * (timer_irq_count - 1) / timer; 37 | timer_count = 0; 38 | timer_irq_count = 0; 39 | } else 40 | { 41 | timer_count++; 42 | } 43 | 44 | // if ( clock_count_last != timer_count ) 45 | // { 46 | //// os_log("power_irq_handler:%u-%u=%u",timer_count,clock_count_last,timer); 47 | // timer = (timer_count - clock_count_last); 48 | // if ( timer_count < clock_count_last ) timer += 0xffffffff; 49 | // 50 | // timer = timer / 1000; 51 | // power = 15200000 / timer; 52 | // os_log("power_irq_handler:%u,%07u",power,timer); 53 | // clock_count_last = timer_count; 54 | // } 55 | // if(timer_count==0) os_log("power_timer_handler Hight:%d",clock_count_last); 56 | // timer_count++; 57 | // clock_count_last=timer_count; 58 | } 59 | 60 | static void power_irq_handler( void* arg ) 61 | { 62 | clock_count = mico_nanosecond_clock_value( ); 63 | if ( timer_irq_count == 0 ) clock_count_last = clock_count; 64 | timer_irq_count++; 65 | } 66 | 67 | void user_power_init( void ) 68 | { 69 | os_log("user_power_init"); 70 | 71 | MicoGpioInitialize( POWER, INPUT_PULL_UP ); 72 | mico_rtos_init_timer( &power_timer, 1000, power_timer_handler, NULL ); 73 | mico_rtos_start_timer( &power_timer ); 74 | 75 | MicoGpioEnableIRQ( POWER, IRQ_TRIGGER_FALLING_EDGE, power_irq_handler, NULL ); 76 | } 77 | 78 | -------------------------------------------------------------------------------- /TC1/user_power.h: -------------------------------------------------------------------------------- 1 | #ifndef __USER_POWER_H_ 2 | #define __USER_POWER_H_ 3 | 4 | void user_power_init( void ); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /TC1/user_sntp.c: -------------------------------------------------------------------------------- 1 | 2 | #define os_log(format, ...) custom_log("SNTP", format, ##__VA_ARGS__) 3 | 4 | #include "main.h" 5 | //#include "user_gpio.h" 6 | #include "user_sntp.h" 7 | 8 | /* Callback function when MiCO UTC time in sync to NTP server */ 9 | 10 | static void sntp_time_call_back( void ) 11 | { 12 | sntp_count++ ; 13 | mico_rtc_time_t rtc_time; 14 | MicoRtcGetTime(&rtc_time); 15 | os_log("time:20%d/%d/%d %d %d:%d:%d",rtc_time.year,rtc_time.month,rtc_time.date,rtc_time.weekday,rtc_time.hr,rtc_time.min,rtc_time.sec); 16 | if (first_sntp == 0){ 17 | sntp_stop_auto_time_sync(); 18 | sntp_start_auto_time_sync(3600 * 1000, sntp_time_call_back); //1小时校准一次 19 | first_sntp = 1; 20 | } 21 | } 22 | 23 | 24 | void sntp_init(void) 25 | { 26 | sntp_start_auto_time_sync(60 * 1000, sntp_time_call_back); //首次每1分钟时校准一次 27 | } 28 | -------------------------------------------------------------------------------- /TC1/user_sntp.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __USER_SNTP_H_ 3 | #define __USER_SNTP_H_ 4 | 5 | #include "MiCOKit_EXT.h" 6 | 7 | extern void sntp_init(void); 8 | 9 | 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /TC1/user_wifi.c: -------------------------------------------------------------------------------- 1 | #include "user_wifi.h" 2 | 3 | #include "main.h" 4 | #include "mico_socket.h" 5 | #include "user_gpio.h" 6 | 7 | #include "user_function.h" 8 | #define os_log(format, ...) custom_log("WIFI", format, ##__VA_ARGS__) 9 | 10 | char wifi_status = WIFI_STATE_NOCONNECT; 11 | 12 | mico_timer_t wifi_led_timer; 13 | 14 | static void wifi_connect_sys_config( void ) 15 | { 16 | if ( strlen( sys_config->micoSystemConfig.ssid ) > 0 ) 17 | { 18 | os_log("connect ssid:%s key:%s",sys_config->micoSystemConfig.ssid,sys_config->micoSystemConfig.user_key); 19 | network_InitTypeDef_st wNetConfig; 20 | memset( &wNetConfig, 0, sizeof(network_InitTypeDef_st) ); 21 | strcpy( wNetConfig.wifi_ssid, sys_config->micoSystemConfig.ssid ); 22 | strcpy( wNetConfig.wifi_key, sys_config->micoSystemConfig.user_key ); 23 | wNetConfig.wifi_mode = Station; 24 | wNetConfig.dhcpMode = DHCP_Client; 25 | wNetConfig.wifi_retry_interval = 6000; 26 | micoWlanStart( &wNetConfig ); 27 | wifi_status = WIFI_STATE_CONNECTING; 28 | } else 29 | wifi_status = WIFI_STATE_FAIL; 30 | } 31 | void wifi_start_easylink( ) 32 | { 33 | wifi_status = WIFI_STATE_EASYLINK; 34 | micoWlanStartEasyLink( 20000 ); 35 | user_led_set( 1 ); 36 | } 37 | 38 | //easylink 完成回调 39 | void wifi_easylink_completed_handle( network_InitTypeDef_st *nwkpara, void * arg ) 40 | { 41 | os_log("wifi_easylink_wps_completed_handle:"); 42 | if ( nwkpara == NULL ) 43 | { 44 | os_log("EasyLink fail"); 45 | micoWlanStopEasyLink( ); 46 | return; 47 | } 48 | 49 | os_log("ssid:\"%s\",\"%s\"",nwkpara->wifi_ssid,nwkpara->wifi_key); 50 | 51 | //保存wifi及密码 52 | strcpy( sys_config->micoSystemConfig.ssid, nwkpara->wifi_ssid ); 53 | strcpy( sys_config->micoSystemConfig.user_key, nwkpara->wifi_key ); 54 | sys_config->micoSystemConfig.user_keyLength = strlen( nwkpara->wifi_key ); 55 | mico_system_context_update( sys_config ); 56 | 57 | wifi_status = WIFI_STATE_NOCONNECT; 58 | os_log("EasyLink stop"); 59 | micoWlanStopEasyLink( ); 60 | } 61 | 62 | //wifi已连接获取到IP地址 回调 63 | static void wifi_get_ip_callback( IPStatusTypedef *pnet, void * arg ) 64 | { 65 | os_log("got IP:%s", pnet->ip); 66 | wifi_status = WIFI_STATE_CONNECTED; 67 | } 68 | //wifi连接状态改变回调 69 | static void wifi_status_callback( WiFiEvent status, void *arg ) 70 | { 71 | if ( status == NOTIFY_STATION_UP ) //wifi连接成功 72 | { 73 | //wifi_status = WIFI_STATE_CONNECTED; 74 | } else if ( status == NOTIFY_STATION_DOWN ) //wifi断开 75 | { 76 | wifi_status = WIFI_STATE_NOCONNECT; 77 | if ( !mico_rtos_is_timer_running( &wifi_led_timer ) ) mico_rtos_start_timer( &wifi_led_timer ); 78 | } 79 | } 80 | //100ms定时器回调 81 | static void wifi_led_timer_callback( void* arg ) 82 | { 83 | static unsigned int num = 0; 84 | num++; 85 | 86 | switch ( wifi_status ) 87 | { 88 | case WIFI_STATE_FAIL: 89 | os_log("wifi connect fail"); 90 | user_led_set( 0 ); 91 | mico_rtos_stop_timer( &wifi_led_timer ); 92 | break; 93 | case WIFI_STATE_NOCONNECT: 94 | wifi_connect_sys_config( ); 95 | break; 96 | 97 | case WIFI_STATE_CONNECTING: 98 | //if ( num > 1 ) 99 | { 100 | num = 0; 101 | user_led_set( -1 ); 102 | } 103 | break; 104 | case WIFI_STATE_NOEASYLINK: 105 | wifi_start_easylink( ); 106 | break; 107 | case WIFI_STATE_EASYLINK: 108 | user_led_set( 1 ); 109 | break; 110 | case WIFI_STATE_CONNECTED: 111 | user_led_set( 0 ); 112 | mico_rtos_stop_timer( &wifi_led_timer ); 113 | if ( relay_out( ) ) 114 | user_led_set( 1 ); 115 | else 116 | user_led_set( 0 ); 117 | break; 118 | } 119 | } 120 | 121 | void wifi_init( void ) 122 | { 123 | //wifi配置初始化 124 | // network_InitTypeDef_st wNetConfig; 125 | 126 | // memset(&wNetConfig, 0, sizeof(network_InitTypeDef_st)); 127 | // wNetConfig.wifi_mode = Station; 128 | // snprintf(wNetConfig.wifi_ssid, 32, "Honor 9" ); 129 | // strcpy((char*)wNetConfig.wifi_key, "19910911"); 130 | // wNetConfig.dhcpMode = DHCP_Client; 131 | // wNetConfig.wifi_retry_interval=6000; 132 | // micoWlanStart(&wNetConfig); 133 | 134 | //wifi状态下led闪烁定时器初始化 135 | mico_rtos_init_timer( &wifi_led_timer, 1000, (void *) wifi_led_timer_callback, NULL ); 136 | //easylink 完成回调 137 | mico_system_notify_register( mico_notify_EASYLINK_WPS_COMPLETED, (void *) wifi_easylink_completed_handle, NULL ); 138 | //wifi已连接获取到IP地址 回调 139 | mico_system_notify_register( mico_notify_DHCP_COMPLETED, (void *) wifi_get_ip_callback, NULL ); 140 | //wifi连接状态改变回调 141 | mico_system_notify_register( mico_notify_WIFI_STATUS_CHANGED, (void*) wifi_status_callback, NULL ); 142 | 143 | //启动定时器开始进行wifi连接 144 | if ( !mico_rtos_is_timer_running( &wifi_led_timer ) ) mico_rtos_start_timer( &wifi_led_timer ); 145 | 146 | } 147 | 148 | -------------------------------------------------------------------------------- /TC1/user_wifi.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __USER_WIFI_H_ 3 | #define __USER_WIFI_H_ 4 | 5 | 6 | #include "mico.h" 7 | #include "MiCOKit_EXT.h" 8 | 9 | 10 | enum { 11 | WIFI_STATE_FAIL, 12 | WIFI_STATE_NOCONNECT, 13 | WIFI_STATE_CONNECTING, 14 | WIFI_STATE_CONNECTED, 15 | WIFI_STATE_NOEASYLINK, 16 | WIFI_STATE_EASYLINK, 17 | WIFI_STATE_EASYLINKING, 18 | }; 19 | 20 | 21 | 22 | extern char wifi_status; 23 | extern void wifi_init(void); 24 | extern void wifi_start_easylink(void); 25 | 26 | 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /mico-os/libraries/protocols/SNTP/sntp.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file sntp.c 4 | * @author William Xu 5 | * @version V1.0.0 6 | * @date 05-May-2014 7 | * @brief Create a NTP client timed enent, and synchronize with NTP server, 8 | * generate callback when synced. 9 | ****************************************************************************** 10 | * 11 | * The MIT License 12 | * Copyright (c) 2016 MXCHIP Inc. 13 | * 14 | * Permission is hereby granted, free of charge, to any person obtaining a copy 15 | * of this software and associated documentation files (the "Software"), to deal 16 | * in the Software without restriction, including without limitation the rights 17 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | * copies of the Software, and to permit persons to whom the Software is furnished 19 | * to do so, subject to the following conditions: 20 | * 21 | * The above copyright notice and this permission notice shall be included in 22 | * all copies or substantial portions of the Software. 23 | * 24 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 28 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 29 | * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 | ****************************************************************************** 31 | */ 32 | 33 | #include 34 | 35 | #include "mico.h" 36 | #include "sntp.h" 37 | #include "TimeUtils.h" 38 | #include "SocketUtils.h" 39 | 40 | #ifdef DEBUG 41 | #define ntp_log(M, ...) custom_log("SNTP", M, ##__VA_ARGS__) 42 | #define ntp_log_trace() custom_log_trace("SNTP") 43 | #else 44 | #define ntp_log(M, ...) 45 | #define ntp_log_trace() 46 | #endif 47 | 48 | /****************************************************** 49 | * Macros 50 | ******************************************************/ 51 | 52 | /****************************************************** 53 | * Constants 54 | ******************************************************/ 55 | 56 | #define NTP_EPOCH (86400U * (365U * 70U + 17U)) 57 | #define NTP_PORT 123 58 | 59 | #ifndef MICO_NTP_REPLY_TIMEOUT 60 | #define MICO_NTP_REPLY_TIMEOUT 300 61 | #endif 62 | 63 | #define MAX_NTP_ATTEMPTS 3 64 | #define TIME_BTW_ATTEMPTS 5000 65 | /* RFC4330 recommends min 15s between polls */ 66 | #define MIN_POLL_INTERVAL 15 * 1000 67 | 68 | /****************************************************** 69 | * Enumerations 70 | ******************************************************/ 71 | 72 | /****************************************************** 73 | * Type Definitions 74 | ******************************************************/ 75 | 76 | /****************************************************** 77 | * Structures 78 | ******************************************************/ 79 | 80 | /* 81 | * Taken from RFC 1305 82 | * http://www.ietf.org/rfc/rfc1305.txt 83 | */ 84 | typedef struct 85 | { 86 | unsigned int mode : 3; 87 | unsigned int vn : 3; 88 | unsigned int li : 2; 89 | uint8_t stratum; 90 | int8_t poll; 91 | uint32_t root_delay; 92 | uint32_t root_dispersion; 93 | uint32_t reference_identifier; 94 | uint32_t reference_timestamp_seconds; 95 | uint32_t reference_timestamp_fraction; 96 | uint32_t originate_timestamp_seconds; 97 | uint32_t originate_timestamp_fraction; 98 | uint32_t receive_timestamp_seconds; 99 | uint32_t receive_timestamp_fraction; 100 | uint32_t transmit_timestamp_seconds; 101 | uint32_t transmit_timestamp_fraction; 102 | } ntp_packet_t; 103 | 104 | /****************************************************** 105 | * Static Function Declarations 106 | ******************************************************/ 107 | 108 | static OSStatus sync_ntp_time( void* arg ); 109 | 110 | /****************************************************** 111 | * Variable Definitions 112 | ******************************************************/ 113 | 114 | static time_synced_fun time_synced_call_back = NULL; 115 | static mico_timed_event_t sync_ntp_time_event; 116 | /* Only support primary and secondary servers */ 117 | static struct in_addr ntp_server[2]; 118 | static const char ntp_dns_name[3][32] = 119 | {"ntp1.aliyun.com", "cn.pool.ntp.org", "time.asia.apple.com"}; 120 | /****************************************************** 121 | * Function Definitions 122 | ******************************************************/ 123 | 124 | OSStatus sntp_start_auto_time_sync( uint32_t interval_ms, time_synced_fun call_back ) 125 | { 126 | OSStatus err = kNoErr; 127 | uint8_t random_initial; 128 | 129 | time_synced_call_back = call_back; 130 | /* Synchronize time with NTP server and schedule for re-sync every one day */ 131 | MicoRandomNumberRead( &random_initial, 1 ); 132 | /* prevent thundering herd scenarios by randomizing per RFC4330 */ 133 | //mico_rtos_delay_milliseconds(300 * (unsigned int)random_initial); 134 | mico_rtos_send_asynchronous_event( MICO_NETWORKING_WORKER_THREAD, sync_ntp_time, 0 ); 135 | if ( interval_ms < MIN_POLL_INTERVAL ) 136 | interval_ms = MIN_POLL_INTERVAL; 137 | mico_rtos_register_timed_event( &sync_ntp_time_event, MICO_NETWORKING_WORKER_THREAD, sync_ntp_time, interval_ms, 138 | 0 ); 139 | return err; 140 | } 141 | 142 | OSStatus sntp_set_server_ip_address( uint32_t index, struct in_addr address ) 143 | { 144 | if ( (index != 0) && (index != 1) ) 145 | return kParamErr; 146 | 147 | ntp_server[index] = address; 148 | return kNoErr; 149 | } 150 | 151 | OSStatus sntp_clr_server_ip_address( uint32_t index ) 152 | { 153 | if ( index > 1 ) 154 | return kParamErr; 155 | 156 | ntp_server[index].s_addr = 0; 157 | return kNoErr; 158 | } 159 | 160 | OSStatus sntp_stop_auto_time_sync( void ) 161 | { 162 | return mico_rtos_deregister_timed_event( &sync_ntp_time_event ); 163 | } 164 | 165 | OSStatus sntp_get_time( const struct in_addr *ntp_server_ip, ntp_timestamp_t* timestamp) 166 | { 167 | int Ntp_fd = -1; 168 | OSStatus err; 169 | ntp_packet_t data; 170 | mico_utc_time_t utc_time; 171 | fd_set readfds; 172 | struct timeval t; 173 | struct sockaddr_in self_addr, remote_addr; 174 | socklen_t remote_addr_len; 175 | uint32_t client_sent_timestamp; 176 | 177 | Ntp_fd = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ); 178 | require_action( IsValidSocket( Ntp_fd ), exit, err = kNoResourcesErr ); 179 | 180 | self_addr.sin_family = AF_INET; 181 | self_addr.sin_addr.s_addr = INADDR_ANY; 182 | self_addr.sin_port = htons(NTP_PORT); 183 | 184 | err = bind( Ntp_fd, (struct sockaddr *)&self_addr, sizeof(struct sockaddr_in) ); 185 | require_noerr( err, exit ); 186 | 187 | t.tv_sec = 3; 188 | t.tv_usec = 0; 189 | 190 | /* Fill packet contents */ 191 | mico_time_get_utc_time( &utc_time ); 192 | memset( &data, 0, sizeof(ntp_packet_t) ); 193 | data.li = 3; 194 | data.vn = 3; 195 | data.mode = 3; 196 | data.poll = 17; 197 | data.transmit_timestamp_seconds = Swap32( utc_time + NTP_EPOCH ); 198 | client_sent_timestamp = data.transmit_timestamp_seconds; 199 | 200 | remote_addr.sin_family = AF_INET; 201 | remote_addr.sin_addr.s_addr = ntp_server_ip->s_addr; 202 | remote_addr.sin_port = htons(NTP_PORT); 203 | 204 | require_action( 205 | sendto( Ntp_fd, &data, sizeof(ntp_packet_t), 0, (struct sockaddr *)&remote_addr, sizeof(struct sockaddr) ), 206 | exit, err = kNotWritableErr ); 207 | 208 | FD_ZERO( &readfds ); 209 | FD_SET( Ntp_fd, &readfds ); 210 | 211 | require_action( select( Ntp_fd + 1, &readfds, NULL, NULL, &t ) >= 0, exit, err = kUnexpectedErr ); 212 | 213 | require_action( FD_ISSET( Ntp_fd, &readfds ), exit, err = kTimeoutErr ); 214 | 215 | require_action( 216 | recvfrom( Ntp_fd, &data, sizeof(ntp_packet_t), 0, (struct sockaddr *)&remote_addr, &remote_addr_len ), exit, 217 | err = kNotReadableErr ); 218 | 219 | require_action_string( client_sent_timestamp == data.originate_timestamp_seconds, exit, 220 | err = kResponseErr, 221 | "Server Returned Bad Originate TimeStamp" ); 222 | 223 | require_action_string( data.li <= 2 && data.vn == 3 && data.stratum != 0 && data.stratum <= 15 224 | && data.transmit_timestamp_seconds != 0 225 | && data.mode == 4, 226 | exit, err = kResponseErr, "Invalid Protocol Parameters returned" ); 227 | 228 | timestamp->seconds = Swap32( data.transmit_timestamp_seconds ) - NTP_EPOCH; 229 | timestamp->microseconds = Swap32( data.transmit_timestamp_fraction ) / 4295; /* 4295 = 2^32 / 10^6 */ 230 | 231 | ntp_log("Time Synchronized, %s",asctime(localtime((const time_t *)×tamp->seconds))); 232 | 233 | exit: 234 | if ( err != kNoErr ) ntp_log("Exit: NTP client exit with err = %d", err); 235 | SocketClose( &Ntp_fd ); 236 | return err; 237 | } 238 | 239 | static OSStatus sync_ntp_time( void* arg ) 240 | { 241 | OSStatus err = kGeneralErr; 242 | ntp_timestamp_t current_time; 243 | struct hostent * hostent_content = NULL; 244 | struct in_addr ntp_server_ip; 245 | char ** pptr = NULL; 246 | uint32_t i, j; 247 | 248 | UNUSED_PARAMETER( arg ); 249 | 250 | /* Get the time */ 251 | ntp_log( "Getting NTP time... "); 252 | 253 | for ( i = 0; i < MAX_NTP_ATTEMPTS; i++ ) 254 | { 255 | /* First check if there are local servers to use */ 256 | if ( ntp_server[0].s_addr != 0 ) 257 | { 258 | ntp_log( "Sending request primary ..." ); 259 | err = sntp_get_time( &ntp_server[0], ¤t_time ); 260 | } 261 | if ( err != kNoErr && (ntp_server[1].s_addr != 0) ) 262 | { 263 | ntp_log( "Sending request secondary ..."); 264 | err = sntp_get_time( &ntp_server[1], ¤t_time ); 265 | } 266 | /* only fall back to global servers if we can't get local */ 267 | if ( err != kNoErr ) 268 | { 269 | for(j=0; j<3; j++) { 270 | ntp_log("Resolving SNTP server address %s...", ntp_dns_name[j]); 271 | hostent_content = gethostbyname( ntp_dns_name[j] ); 272 | if( hostent_content == NULL ) 273 | { 274 | ntp_log("SNTP server address can not be resolved"); 275 | continue; 276 | } 277 | pptr=hostent_content->h_addr_list; 278 | ntp_server_ip.s_addr = *(uint32_t *)(*pptr); 279 | ntp_log("SNTP server address: %s, host ip: %s", ntp_dns_name[j], inet_ntoa(ntp_server_ip)); 280 | err = sntp_get_time( &ntp_server_ip, ¤t_time ); 281 | if ( err == kNoErr ) 282 | break; 283 | } 284 | } 285 | 286 | if ( err == kNoErr ) 287 | { 288 | ntp_log( "success" ); 289 | break; 290 | } 291 | else 292 | { 293 | mico_rtos_delay_milliseconds( TIME_BTW_ATTEMPTS ); 294 | ntp_log( "failed, trying again..." ); 295 | } 296 | } 297 | 298 | if ( i >= MAX_NTP_ATTEMPTS ) 299 | { 300 | ntp_log( "Give up getting NTP time\n" ); 301 | memset( ¤t_time, 0, sizeof(current_time) ); 302 | return kTimeoutErr; 303 | } 304 | else 305 | { 306 | mico_utc_time_ms_t utc_time_ms = (uint64_t) current_time.seconds * (uint64_t) 1000 307 | + (current_time.microseconds / 1000); 308 | 309 | /* Set & Print the time */ 310 | mico_time_set_utc_time_ms( &utc_time_ms ); 311 | } 312 | 313 | if ( time_synced_call_back ) time_synced_call_back( ); 314 | #ifdef DEBUG 315 | iso8601_time_t iso8601_time; 316 | mico_time_get_iso8601_time( &iso8601_time ); 317 | ntp_log("Current time is: %.26s\n", (char*)&iso8601_time); 318 | #endif 319 | return kNoErr; 320 | } --------------------------------------------------------------------------------