recover source code

This commit is contained in:
zogodo
2019-09-04 11:06:06 +08:00
parent 3c69d37089
commit 3065ffe5c7
37 changed files with 5016 additions and 22 deletions

View File

@@ -17,11 +17,9 @@
也可以发送邮件给我:zip_zhang@foxmail.com 也可以发送邮件给我:zip_zhang@foxmail.com
注意:所有咨询我文档已经写清楚的问题等等,都不再做任何回复 注意:
已经发现有人使用的我的固件在我未授权的情况下在pdd转转等上加价售卖,所以之后不再提供完整刷机包,仅提供ota包,需要完整包刷机的请加群索要,或是发送邮件给我并能够证明你不是店铺卖家也会单独提供给你完整固件
注意: 固件增加了激活码的功能,所以提供完整固件包 在武汉的可以来找我免费帮刷
已经发现有人使用的我的固件在我未授权的情况下在pdd转转等上加价售卖,~~所以之后不再提供完整刷机包,仅提供ota包,需要完整包刷机的请加群索要,或是发送邮件给我并能够证明你不是店铺卖家也会单独提供给你完整固件~~
~~在武汉的可以来找我免费帮刷~~
> ### 作者声明 > ### 作者声明
> >
@@ -33,11 +31,13 @@
~~不定时重启断电!!!~~ 已修复重启问题(0.10.3),此版本开始需要使用激活码才能使用,激活码原则上免费提供给个人使用.详细见[激活码](#激活码说明) ### 已知BUG
不定时重启断电!!!
定时任务偶尔无效
为防止商用,以上bug在公开版本不修复
@@ -55,13 +55,9 @@
- [x] 无服务器时使用UDP通信 - [x] 无服务器时使用UDP通信
- [x] MQTT服务器连接控制 - [x] MQTT服务器连接控制
- [x] 通过mqtt连入homeassistant - [x] 通过mqtt连入homeassistant
- [x] app实时显示功率 - [x] app实时显示功率(校准数据)
- [ ] ~~根据功率自动开关~~(未做此功能) - [ ] ~~根据功率自动开关~~(未做此功能)
后续计划及当期正在处理的见[TodoProject](https://github.com/a2633063/zTC1/projects/1)
<img src="https://raw.githubusercontent.com/wiki/a2633063/zTC1/image/Phicomm_TC1.png" width="540"> <img src="https://raw.githubusercontent.com/wiki/a2633063/zTC1/image/Phicomm_TC1.png" width="540">
@@ -76,8 +72,6 @@
[开始](#开始) [开始](#开始)
[激活码说明](#激活码说明)
[拆机接线及烧录固件相关](#拆机接线及烧录固件相关) [拆机接线及烧录固件相关](#拆机接线及烧录固件相关)
[开始使用/使用方法](#开始使用/使用方法) [开始使用/使用方法](#开始使用/使用方法)
@@ -131,14 +125,6 @@
## 激活码说明
为防止被不良商用,增加了必须使用激活码激活的功能.对于一般个人申请激活码限额免费获取
见[自助获取激活码](https://github.com/a2633063/SmartControl_Android_MQTT/wiki/激活码获取)
激活方式见[开始使用中的激活](https://github.com/a2633063/zTC1/wiki/开始使用#激活)
## 拆机接线及烧录固件相关 ## 拆机接线及烧录固件相关
见[固件烧录](https://github.com/a2633063/zTC1/wiki/固件烧录) 见[固件烧录](https://github.com/a2633063/zTC1/wiki/固件烧录)

Binary file not shown.

Binary file not shown.

46
TC1/TC1.mk Normal file
View File

@@ -0,0 +1,46 @@
###############################################################################
#
# The MIT License
# Copyright (c) 2016 MXCHIP Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is furnished
# to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
# IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
###############################################################################
NAME := App_TC1
$(NAME)_SOURCES := main.c\
cJSON/cJSON.c\
ota_server/ota_server.c\
user_wifi.c\
user_gpio.c\
user_udp.c\
user_sntp.c\
user_rtc.c\
user_mqtt_client.c\
user_ota.c\
user_power.c\
user_function.c\
http_server/app_httpd.c \
http_server/web_data.c
$(NAME)_COMPONENTS := protocols/SNTP\
protocols/mqtt\
utilities/url\
daemons/http_server

821
TC1/cJSON/cJSON.c Normal file
View File

@@ -0,0 +1,821 @@
/*
Copyright (c) 2009 Dave Gamble
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
/* cJSON */
/* JSON parser in C. */
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <float.h>
#include <limits.h>
#include <ctype.h>
#include "cJSON.h"
#include "mico.h"
static const char *ep;
const char *cJSON_GetErrorPtr(void) {return ep;}
static int cJSON_strcasecmp(const char *s1,const char *s2)
{
if (!s1) return (s1==s2)?0:1;if (!s2) return 1;
for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0) return 0;
return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2);
}
static void *(*cJSON_malloc)(size_t sz) = malloc;
static void (*cJSON_free)(void *ptr) = free;
static char* cJSON_strdup(const char* str)
{
size_t len;
char* copy;
len = strlen(str) + 1;
if (!(copy = (char*)cJSON_malloc(len))) return 0;
memcpy(copy,str,len);
return copy;
}
void cJSON_InitHooks(cJSON_Hooks* hooks)
{
if (!hooks) { /* Reset hooks */
cJSON_malloc = malloc;
cJSON_free = free;
return;
}
cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc;
cJSON_free = (hooks->free_fn)?hooks->free_fn:free;
}
/* Internal constructor. */
static cJSON *cJSON_New_Item(void)
{
cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON));
if (node) memset(node,0,sizeof(cJSON));
return node;
}
/* Delete a cJSON structure. */
void cJSON_Delete(cJSON *c)
{
cJSON *next;
while (c)
{
next=c->next;
if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child);
if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring);
if (!(c->type&cJSON_StringIsConst) && c->string) cJSON_free(c->string);
cJSON_free(c);
c=next;
}
}
/* Parse the input text to generate a number, and populate the result into item. */
static const char *parse_number(cJSON *item,const char *num)
{
double n=0,sign=1,scale=0;int subscale=0,signsubscale=1;
if (*num=='-') sign=-1,num++; /* Has sign? */
if (*num=='0') num++; /* is zero */
if (*num>='1' && *num<='9') do n=(n*10.0)+(*num++ -'0'); while (*num>='0' && *num<='9'); /* Number? */
if (*num=='.' && num[1]>='0' && num[1]<='9') {num++; do n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');} /* Fractional part? */
if (*num=='e' || *num=='E') /* Exponent? */
{ num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++; /* With sign? */
while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0'); /* Number? */
}
n=sign*n*pow(10.0,(scale+subscale*signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */
item->valuedouble=n;
item->valueint=(int)n;
item->type=cJSON_Number;
return num;
}
static int pow2gt (int x) { --x; x|=x>>1; x|=x>>2; x|=x>>4; x|=x>>8; x|=x>>16; return x+1; }
typedef struct {char *buffer; int length; int offset; } printbuffer;
static char* ensure(printbuffer *p,int needed)
{
char *newbuffer;int newsize;
if (!p || !p->buffer) return 0;
needed+=p->offset;
if (needed<=p->length) return p->buffer+p->offset;
newsize=pow2gt(needed);
newbuffer=(char*)cJSON_malloc(newsize);
if (!newbuffer) {cJSON_free(p->buffer);p->length=0,p->buffer=0;return 0;}
if (newbuffer) memcpy(newbuffer,p->buffer,p->length);
cJSON_free(p->buffer);
p->length=newsize;
p->buffer=newbuffer;
return newbuffer+p->offset;
}
static int update(printbuffer *p)
{
char *str;
if (!p || !p->buffer) return 0;
str=p->buffer+p->offset;
return p->offset+strlen(str);
}
/* Render the number nicely from the given item into a string. */
static char *print_number(cJSON *item,printbuffer *p)
{
char *str=0;
double d=item->valuedouble;
if (d==0)
{
if (p) str=ensure(p,2);
else str=(char*)cJSON_malloc(2); /* special case for 0. */
if (str) strcpy(str,"0");
}
else if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN)
{
if (p) str=ensure(p,21);
else str=(char*)cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */
if (str) sprintf(str,"%d",item->valueint);
}
else
{
if (p) str=ensure(p,64);
else str=(char*)cJSON_malloc(64); /* This is a nice tradeoff. */
if (str)
{
if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)sprintf(str,"%.0f",d);
else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d);
else sprintf(str,"%f",d);
}
}
return str;
}
static unsigned parse_hex4(const char *str)
{
unsigned h=0;
if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
h=h<<4;str++;
if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
h=h<<4;str++;
if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
h=h<<4;str++;
if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
return h;
}
/* Parse the input text into an unescaped cstring, and populate item. */
static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
static const char *parse_string(cJSON *item,const char *str)
{
const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2;
if (*str!='\"') {ep=str;return 0;} /* not a string! */
while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */
out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */
if (!out) return 0;
ptr=str+1;ptr2=out;
while (*ptr!='\"' && *ptr)
{
if (*ptr!='\\') *ptr2++=*ptr++;
else
{
ptr++;
switch (*ptr)
{
case 'b': *ptr2++='\b'; break;
case 'f': *ptr2++='\f'; break;
case 'n': *ptr2++='\n'; break;
case 'r': *ptr2++='\r'; break;
case 't': *ptr2++='\t'; break;
case 'u': /* transcode utf16 to utf8. */
uc=parse_hex4(ptr+1);ptr+=4; /* get the unicode char. */
if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) break; /* check for invalid. */
if (uc>=0xD800 && uc<=0xDBFF) /* UTF16 surrogate pairs. */
{
if (ptr[1]!='\\' || ptr[2]!='u') break; /* missing second-half of surrogate. */
uc2=parse_hex4(ptr+3);ptr+=6;
if (uc2<0xDC00 || uc2>0xDFFF) break; /* invalid second-half of surrogate. */
uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF));
}
len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len;
switch (len) {
case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
case 1: *--ptr2 =(uc | firstByteMark[len]);
}
ptr2+=len;
break;
default: *ptr2++=*ptr; break;
}
ptr++;
}
}
*ptr2=0;
if (*ptr=='\"') ptr++;
item->valuestring=out;
item->type=cJSON_String;
return ptr;
}
/* Render the cstring provided to an escaped version that can be printed. */
static char *print_string_ptr(const char *str,printbuffer *p)
{
const char *ptr;char *ptr2,*out;int len=0,flag=0;unsigned char token;
for (ptr=str;*ptr;ptr++) flag|=((*ptr>0 && *ptr<32)||(*ptr=='\"')||(*ptr=='\\'))?1:0;
if (!flag)
{
len=ptr-str;
if (p) out=ensure(p,len+3);
else out=(char*)cJSON_malloc(len+3);
if (!out) return 0;
ptr2=out;*ptr2++='\"';
strcpy(ptr2,str);
ptr2[len]='\"';
ptr2[len+1]=0;
return out;
}
if (!str)
{
if (p) out=ensure(p,3);
else out=(char*)cJSON_malloc(3);
if (!out) return 0;
strcpy(out,"\"\"");
return out;
}
ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;}
if (p) out=ensure(p,len+3);
else out=(char*)cJSON_malloc(len+3);
if (!out) return 0;
ptr2=out;ptr=str;
*ptr2++='\"';
while (*ptr)
{
if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++;
else
{
*ptr2++='\\';
switch (token=*ptr++)
{
case '\\': *ptr2++='\\'; break;
case '\"': *ptr2++='\"'; break;
case '\b': *ptr2++='b'; break;
case '\f': *ptr2++='f'; break;
case '\n': *ptr2++='n'; break;
case '\r': *ptr2++='r'; break;
case '\t': *ptr2++='t'; break;
default: sprintf(ptr2,"u%04x",token);ptr2+=5; break; /* escape and print */
}
}
}
*ptr2++='\"';*ptr2++=0;
return out;
}
/* Invote print_string_ptr (which is useful) on an item. */
static char *print_string(cJSON *item,printbuffer *p) {return print_string_ptr(item->valuestring,p);}
/* Predeclare these prototypes. */
static const char *parse_value(cJSON *item,const char *value);
static char *print_value(cJSON *item,int depth,int fmt,printbuffer *p);
static const char *parse_array(cJSON *item,const char *value);
static char *print_array(cJSON *item,int depth,int fmt,printbuffer *p);
static const char *parse_object(cJSON *item,const char *value);
static char *print_object(cJSON *item,int depth,int fmt,printbuffer *p);
/* Utility to jump whitespace and cr/lf */
static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;}
/* Parse an object - create a new root, and populate. */
cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated)
{
const char *end=0;
cJSON *c=cJSON_New_Item();
ep=0;
if (!c) return 0; /* memory fail */
end=parse_value(c,skip(value));
if (!end) {cJSON_Delete(c);return 0;} /* parse failure. ep is set. */
/* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
if (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);ep=end;return 0;}}
if (return_parse_end) *return_parse_end=end;
return c;
}
/* Default options for cJSON_Parse */
cJSON *cJSON_Parse(const char *value) {return cJSON_ParseWithOpts(value,0,0);}
/* Render a cJSON item/entity/structure to text. */
char *cJSON_Print(cJSON *item) {return print_value(item,0,1,0);}
char *cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0,0,0);}
char *cJSON_PrintBuffered(cJSON *item,int prebuffer,int fmt)
{
printbuffer p;
p.buffer=(char*)cJSON_malloc(prebuffer);
p.length=prebuffer;
p.offset=0;
return print_value(item,0,fmt,&p);
return p.buffer;
}
/* Parser core - when encountering text, process appropriately. */
static const char *parse_value(cJSON *item,const char *value)
{
if (!value) return 0; /* Fail on null. */
if (!strncmp(value,"null",4)) { item->type=cJSON_NULL; return value+4; }
if (!strncmp(value,"false",5)) { item->type=cJSON_False; return value+5; }
if (!strncmp(value,"true",4)) { item->type=cJSON_True; item->valueint=1; return value+4; }
if (*value=='\"') { return parse_string(item,value); }
if (*value=='-' || (*value>='0' && *value<='9')) { return parse_number(item,value); }
if (*value=='[') { return parse_array(item,value); }
if (*value=='{') { return parse_object(item,value); }
ep=value;return 0; /* failure. */
}
/* Render a value to text. */
static char *print_value(cJSON *item,int depth,int fmt,printbuffer *p)
{
char *out=0;
if (!item) return 0;
if (p)
{
switch ((item->type)&255)
{
case cJSON_NULL: {out=ensure(p,5); if (out) strcpy(out,"null"); break;}
case cJSON_False: {out=ensure(p,6); if (out) strcpy(out,"false"); break;}
case cJSON_True: {out=ensure(p,5); if (out) strcpy(out,"true"); break;}
case cJSON_Number: out=print_number(item,p);break;
case cJSON_String: out=print_string(item,p);break;
case cJSON_Array: out=print_array(item,depth,fmt,p);break;
case cJSON_Object: out=print_object(item,depth,fmt,p);break;
}
}
else
{
switch ((item->type)&255)
{
case cJSON_NULL: out=cJSON_strdup("null"); break;
case cJSON_False: out=cJSON_strdup("false");break;
case cJSON_True: out=cJSON_strdup("true"); break;
case cJSON_Number: out=print_number(item,0);break;
case cJSON_String: out=print_string(item,0);break;
case cJSON_Array: out=print_array(item,depth,fmt,0);break;
case cJSON_Object: out=print_object(item,depth,fmt,0);break;
}
}
return out;
}
/* Build an array from input text. */
static const char *parse_array(cJSON *item,const char *value)
{
cJSON *child;
if (*value!='[') {ep=value;return 0;} /* not an array! */
item->type=cJSON_Array;
value=skip(value+1);
if (*value==']') return value+1; /* empty array. */
item->child=child=cJSON_New_Item();
if (!item->child) return 0; /* memory fail */
value=skip(parse_value(child,skip(value))); /* skip any spacing, get the value. */
if (!value) return 0;
while (*value==',')
{
cJSON *new_item;
if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */
child->next=new_item;new_item->prev=child;child=new_item;
value=skip(parse_value(child,skip(value+1)));
if (!value) return 0; /* memory fail */
}
if (*value==']') return value+1; /* end of array */
ep=value;return 0; /* malformed. */
}
/* Render an array to text */
static char *print_array(cJSON *item,int depth,int fmt,printbuffer *p)
{
char **entries;
char *out=0,*ptr,*ret;int len=5;
cJSON *child=item->child;
int numentries=0,i=0,fail=0;
size_t tmplen=0;
/* How many entries in the array? */
while (child) numentries++,child=child->next;
/* Explicitly handle numentries==0 */
if (!numentries)
{
if (p) out=ensure(p,3);
else out=(char*)cJSON_malloc(3);
if (out) strcpy(out,"[]");
return out;
}
if (p)
{
/* Compose the output array. */
i=p->offset;
ptr=ensure(p,1);if (!ptr) return 0; *ptr='['; p->offset++;
child=item->child;
while (child && !fail)
{
print_value(child,depth+1,fmt,p);
p->offset=update(p);
if (child->next) {len=fmt?2:1;ptr=ensure(p,len+1);if (!ptr) return 0;*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;p->offset+=len;}
child=child->next;
}
ptr=ensure(p,2);if (!ptr) return 0; *ptr++=']';*ptr=0;
out=(p->buffer)+i;
}
else
{
/* Allocate an array to hold the values for each */
entries=(char**)cJSON_malloc(numentries*sizeof(char*));
if (!entries) return 0;
memset(entries,0,numentries*sizeof(char*));
/* Retrieve all the results: */
child=item->child;
while (child && !fail)
{
ret=print_value(child,depth+1,fmt,0);
entries[i++]=ret;
if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1;
child=child->next;
}
/* If we didn't fail, try to malloc the output string */
if (!fail) out=(char*)cJSON_malloc(len);
/* If that fails, we fail. */
if (!out) fail=1;
/* Handle failure. */
if (fail)
{
for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]);
cJSON_free(entries);
return 0;
}
/* Compose the output array. */
*out='[';
ptr=out+1;*ptr=0;
for (i=0;i<numentries;i++)
{
tmplen=strlen(entries[i]);memcpy(ptr,entries[i],tmplen);ptr+=tmplen;
if (i!=numentries-1) {*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;}
cJSON_free(entries[i]);
}
cJSON_free(entries);
*ptr++=']';*ptr++=0;
}
return out;
}
/* Build an object from the text. */
static const char *parse_object(cJSON *item,const char *value)
{
cJSON *child;
if (*value!='{') {ep=value;return 0;} /* not an object! */
item->type=cJSON_Object;
value=skip(value+1);
if (*value=='}') return value+1; /* empty array. */
item->child=child=cJSON_New_Item();
if (!item->child) return 0;
value=skip(parse_string(child,skip(value)));
if (!value) return 0;
child->string=child->valuestring;child->valuestring=0;
if (*value!=':') {ep=value;return 0;} /* fail! */
value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */
if (!value) return 0;
while (*value==',')
{
cJSON *new_item;
if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */
child->next=new_item;new_item->prev=child;child=new_item;
value=skip(parse_string(child,skip(value+1)));
if (!value) return 0;
child->string=child->valuestring;child->valuestring=0;
if (*value!=':') {ep=value;return 0;} /* fail! */
value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */
if (!value) return 0;
}
if (*value=='}') return value+1; /* end of array */
ep=value;return 0; /* malformed. */
}
/* Render an object to text. */
static char *print_object(cJSON *item,int depth,int fmt,printbuffer *p)
{
char **entries=0,**names=0;
char *out=0,*ptr,*ret,*str;int len=7,i=0,j;
cJSON *child=item->child;
int numentries=0,fail=0;
size_t tmplen=0;
/* Count the number of entries. */
while (child) numentries++,child=child->next;
/* Explicitly handle empty object case */
if (!numentries)
{
if (p) out=ensure(p,fmt?depth+4:3);
else out=(char*)cJSON_malloc(fmt?depth+4:3);
if (!out) return 0;
ptr=out;*ptr++='{';
if (fmt) {*ptr++='\n';for (i=0;i<depth-1;i++) *ptr++='\t';}
*ptr++='}';*ptr++=0;
return out;
}
if (p)
{
/* Compose the output: */
i=p->offset;
len=fmt?2:1; ptr=ensure(p,len+1); if (!ptr) return 0;
*ptr++='{'; if (fmt) *ptr++='\n'; *ptr=0; p->offset+=len;
child=item->child;depth++;
while (child)
{
if (fmt)
{
ptr=ensure(p,depth); if (!ptr) return 0;
for (j=0;j<depth;j++) *ptr++='\t';
p->offset+=depth;
}
print_string_ptr(child->string,p);
p->offset=update(p);
len=fmt?2:1;
ptr=ensure(p,len); if (!ptr) return 0;
*ptr++=':';if (fmt) *ptr++='\t';
p->offset+=len;
print_value(child,depth,fmt,p);
p->offset=update(p);
len=(fmt?1:0)+(child->next?1:0);
ptr=ensure(p,len+1); if (!ptr) return 0;
if (child->next) *ptr++=',';
if (fmt) *ptr++='\n';*ptr=0;
p->offset+=len;
child=child->next;
}
ptr=ensure(p,fmt?(depth+1):2); if (!ptr) return 0;
if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';
*ptr++='}';*ptr=0;
out=(p->buffer)+i;
}
else
{
/* Allocate space for the names and the objects */
entries=(char**)cJSON_malloc(numentries*sizeof(char*));
if (!entries) return 0;
names=(char**)cJSON_malloc(numentries*sizeof(char*));
if (!names) {cJSON_free(entries);return 0;}
memset(entries,0,sizeof(char*)*numentries);
memset(names,0,sizeof(char*)*numentries);
/* Collect all the results into our arrays: */
child=item->child;depth++;if (fmt) len+=depth;
while (child)
{
names[i]=str=print_string_ptr(child->string,0);
entries[i++]=ret=print_value(child,depth,fmt,0);
if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1;
child=child->next;
}
/* Try to allocate the output string */
if (!fail) out=(char*)cJSON_malloc(len);
if (!out) fail=1;
/* Handle failure */
if (fail)
{
for (i=0;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);}
cJSON_free(names);cJSON_free(entries);
return 0;
}
/* Compose the output: */
*out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0;
for (i=0;i<numentries;i++)
{
if (fmt) for (j=0;j<depth;j++) *ptr++='\t';
tmplen=strlen(names[i]);memcpy(ptr,names[i],tmplen);ptr+=tmplen;
*ptr++=':';if (fmt) *ptr++='\t';
strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
if (i!=numentries-1) *ptr++=',';
if (fmt) *ptr++='\n';*ptr=0;
cJSON_free(names[i]);cJSON_free(entries[i]);
}
cJSON_free(names);cJSON_free(entries);
if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';
*ptr++='}';*ptr++=0;
}
return out;
}
/* Get Array size/item / object item. */
int cJSON_GetArraySize(cJSON *array) {cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;}
cJSON *cJSON_GetArrayItem(cJSON *array,int item) {cJSON *c=array->child; while (c && item>0) item--,c=c->next; return c;}
cJSON *cJSON_GetObjectItem(cJSON *object,const char *string) {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;}
/* Utility for array list handling. */
static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;}
/* Utility for handling references. */
static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();if (!ref) return 0;memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;}
/* Add item to array/object. */
void cJSON_AddItemToArray(cJSON *array, cJSON *item) {cJSON *c=array->child;if (!item) return; if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}}
void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);}
void cJSON_AddItemToObjectCS(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (!(item->type&cJSON_StringIsConst) && item->string) cJSON_free(item->string);item->string=(char*)string;item->type|=cJSON_StringIsConst;cJSON_AddItemToArray(object,item);}
void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) {cJSON_AddItemToArray(array,create_reference(item));}
void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item) {cJSON_AddItemToObject(object,string,create_reference(item));}
cJSON *cJSON_DetachItemFromArray(cJSON *array,int which) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0;
if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;}
void cJSON_DeleteItemFromArray(cJSON *array,int which) {cJSON_Delete(cJSON_DetachItemFromArray(array,which));}
cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string) {int i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;}
void cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));}
/* Replace array/object items with new ones. */
void cJSON_InsertItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) {cJSON_AddItemToArray(array,newitem);return;}
newitem->next=c;newitem->prev=c->prev;c->prev=newitem;if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;}
void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return;
newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem;
if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);}
void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}}
/* Create basic types: */
cJSON *cJSON_CreateNull(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;}
cJSON *cJSON_CreateTrue(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;}
cJSON *cJSON_CreateFalse(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;}
cJSON *cJSON_CreateBool(int b) {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;}
cJSON *cJSON_CreateNumber(double num) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;}return item;}
cJSON *cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;}
cJSON *cJSON_CreateArray(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;}
cJSON *cJSON_CreateObject(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;}
/* Create Arrays: */
cJSON *cJSON_CreateIntArray(const int *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
cJSON *cJSON_CreateFloatArray(const float *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
cJSON *cJSON_CreateDoubleArray(const double *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
cJSON *cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateString(strings[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
/* Duplication */
cJSON *cJSON_Duplicate(cJSON *item,int recurse)
{
cJSON *newitem,*cptr,*nptr=0,*newchild;
/* Bail on bad ptr */
if (!item) return 0;
/* Create new item */
newitem=cJSON_New_Item();
if (!newitem) return 0;
/* Copy over all vars */
newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble;
if (item->valuestring) {newitem->valuestring=cJSON_strdup(item->valuestring); if (!newitem->valuestring) {cJSON_Delete(newitem);return 0;}}
if (item->string) {newitem->string=cJSON_strdup(item->string); if (!newitem->string) {cJSON_Delete(newitem);return 0;}}
/* If non-recursive, then we're done! */
if (!recurse) return newitem;
/* Walk the ->next chain for the child. */
cptr=item->child;
while (cptr)
{
newchild=cJSON_Duplicate(cptr,1); /* Duplicate (with recurse) each item in the ->next chain */
if (!newchild) {cJSON_Delete(newitem);return 0;}
if (nptr) {nptr->next=newchild,newchild->prev=nptr;nptr=newchild;} /* If newitem->child already set, then crosswire ->prev and ->next and move on */
else {newitem->child=newchild;nptr=newchild;} /* Set newitem->child and move to it */
cptr=cptr->next;
}
return newitem;
}
void cJSON_Minify(char *json)
{
char *into=json;
while (*json)
{
if (*json==' ') json++;
else if (*json=='\t') json++; /* Whitespace characters. */
else if (*json=='\r') json++;
else if (*json=='\n') json++;
else if (*json=='/' && json[1]=='/') while (*json && *json!='\n') json++; /* double-slash comments, to end of line. */
else if (*json=='/' && json[1]=='*') {while (*json && !(*json=='*' && json[1]=='/')) json++;json+=2;} /* multiline comments. */
else if (*json=='\"'){*into++=*json++;while (*json && *json!='\"'){if (*json=='\\') *into++=*json++;*into++=*json++;}*into++=*json++;} /* string literals, which are \" sensitive. */
else *into++=*json++; /* All other characters. */
}
*into=0; /* and null-terminate. */
}
/****************************************************************/
// isXXX Function
// <20>ж<EFBFBD>item<65><6D><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int cJSON_IsFalse(const cJSON * const item) {
if (item == NULL) {
return false;
}
return (item->type & 0xFF) == cJSON_False;
}
int cJSON_IsTrue(const cJSON * const item) {
if (item == NULL) {
return false;
}
return (item->type & 0xff) == cJSON_True;
}
int cJSON_IsBool(const cJSON * const item) {
if (item == NULL) {
return false;
}
return (item->type & (cJSON_True | cJSON_False)) != 0;
}
int cJSON_IsNull(const cJSON * const item) {
if (item == NULL) {
return false;
}
return (item->type & 0xFF) == cJSON_NULL;
}
int cJSON_IsNumber(const cJSON * const item) {
if (item == NULL) {
return false;
}
return (item->type & 0xFF) == cJSON_Number;
}
int cJSON_IsString(const cJSON * const item) {
if (item == NULL) {
return false;
}
return (item->type & 0xFF) == cJSON_String;
}
int cJSON_IsArray(const cJSON * const item) {
if (item == NULL) {
return false;
}
return (item->type & 0xFF) == cJSON_Array;
}
int cJSON_IsObject(const cJSON * const item) {
if (item == NULL) {
return false;
}
return (item->type & 0xFF) == cJSON_Object;
}

159
TC1/cJSON/cJSON.h Normal file
View File

@@ -0,0 +1,159 @@
/*
Copyright (c) 2009 Dave Gamble
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef cJSON__h
#define cJSON__h
#ifdef __cplusplus
extern "C"
{
#endif
/* cJSON Types: */
#define cJSON_False 0
#define cJSON_True 1
#define cJSON_NULL 2
#define cJSON_Number 3
#define cJSON_String 4
#define cJSON_Array 5
#define cJSON_Object 6
#define cJSON_IsReference 256
#define cJSON_StringIsConst 512
/* The cJSON structure: */
typedef struct cJSON {
struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
int type; /* The type of the item, as above. */
char *valuestring; /* The item's string, if type==cJSON_String */
int valueint; /* The item's number, if type==cJSON_Number */
double valuedouble; /* The item's number, if type==cJSON_Number */
char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
} cJSON;
typedef struct cJSON_Hooks {
void *(*malloc_fn)(size_t sz);
void (*free_fn)(void *ptr);
} cJSON_Hooks;
/* Supply malloc, realloc and free functions to cJSON */
extern void cJSON_InitHooks(cJSON_Hooks* hooks);
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */
extern cJSON *cJSON_Parse(const char *value);
/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */
extern char *cJSON_Print(cJSON *item);
/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */
extern char *cJSON_PrintUnformatted(cJSON *item);
/* 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 */
extern char *cJSON_PrintBuffered(cJSON *item,int prebuffer,int fmt);
/* Delete a cJSON entity and all subentities. */
extern void cJSON_Delete(cJSON *c);
/* Returns the number of items in an array (or object). */
extern int cJSON_GetArraySize(cJSON *array);
/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
extern cJSON *cJSON_GetArrayItem(cJSON *array,int item);
/* Get item "string" from object. Case insensitive. */
extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);
/* 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. */
extern const char *cJSON_GetErrorPtr(void);
/* These calls create a cJSON item of the appropriate type. */
extern cJSON *cJSON_CreateNull(void);
extern cJSON *cJSON_CreateTrue(void);
extern cJSON *cJSON_CreateFalse(void);
extern cJSON *cJSON_CreateBool(int b);
extern cJSON *cJSON_CreateNumber(double num);
extern cJSON *cJSON_CreateString(const char *string);
extern cJSON *cJSON_CreateArray(void);
extern cJSON *cJSON_CreateObject(void);
/* These utilities create an Array of count items. */
extern cJSON *cJSON_CreateIntArray(const int *numbers,int count);
extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count);
extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count);
extern cJSON *cJSON_CreateStringArray(const char **strings,int count);
/* Append item to the specified array/object. */
extern void cJSON_AddItemToArray(cJSON *array, cJSON *item);
extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item);
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 */
/* 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. */
extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
extern void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item);
/* Remove/Detatch items from Arrays/Objects. */
extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which);
extern void cJSON_DeleteItemFromArray(cJSON *array,int which);
extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string);
extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string);
/* Update array items. */
extern void cJSON_InsertItemInArray(cJSON *array,int which,cJSON *newitem); /* Shifts pre-existing items to the right. */
extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem);
extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
/* Duplicate a cJSON item */
extern cJSON *cJSON_Duplicate(cJSON *item,int recurse);
/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
need to be released. With recurse!=0, it will duplicate any children connected to the item.
The item->next and ->prev pointers are always zero on return from Duplicate. */
/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated);
extern void cJSON_Minify(char *json);
/* Macros for creating things quickly. */
#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull())
#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue())
#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse())
#define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b))
#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s))
/* When assigning an integer value, it needs to be propagated to valuedouble too. */
#define cJSON_SetIntValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val))
#define cJSON_SetNumberValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val))
/* These functions check the type of an item */
int cJSON_IsFalse(const cJSON * const item);
int cJSON_IsTrue(const cJSON * const item);
int cJSON_IsBool(const cJSON * const item);
int cJSON_IsNull(const cJSON * const item);
int cJSON_IsNumber(const cJSON * const item);
int cJSON_IsString(const cJSON * const item);
int cJSON_IsArray(const cJSON * const item);
int cJSON_IsObject(const cJSON * const item);
#ifdef __cplusplus
}
#endif
#endif

207
TC1/http_server/app_httpd.c Normal file
View File

@@ -0,0 +1,207 @@
/**
******************************************************************************
* @file app_https.c
* @author QQ DING
* @version V1.0.0
* @date 1-September-2015
* @brief The main HTTPD server initialization and wsgi handle.
******************************************************************************
*
* The MIT License
* Copyright (c) 2016 MXCHIP Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
* IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
******************************************************************************
*/
#include <httpd.h>
#include <http_parse.h>
#include <http-strings.h>
#include "mico.h"
#include "httpd_priv.h"
#include "app_httpd.h"
#include "main.h"
#define app_httpd_log(M, ...) custom_log("apphttpd", M, ##__VA_ARGS__)
#define HTTPD_HDR_DEFORT (HTTPD_HDR_ADD_SERVER|HTTPD_HDR_ADD_CONN_CLOSE|HTTPD_HDR_ADD_PRAGMA_NO_CACHE)
static bool is_http_init;
static bool is_handlers_registered;
struct httpd_wsgi_call g_app_handlers[];
static int web_send_wifisetting_page(httpd_request_t *req)
{
OSStatus err = kNoErr;
err = httpd_send_all_header(req, HTTP_RES_200, sizeof(wifisetting), HTTP_CONTENT_HTML_STR);
require_noerr_action( err, exit, app_httpd_log("ERROR: Unable to send http wifisetting headers.") );
err = httpd_send_body(req->sock, wifisetting, sizeof(wifisetting));
require_noerr_action( err, exit, app_httpd_log("ERROR: Unable to send http wifisetting body.") );
exit:
return err;
}
static int web_send_result_page(httpd_request_t *req)
{
OSStatus err = kNoErr;
bool para_succ = false;
int buf_size = 512;
char *buf;
char value_ssid[maxSsidLen];
char value_pass[maxKeyLen];
char value_user[maxNameLen];
mico_Context_t* context = NULL;
context = mico_system_context_get( );
buf = malloc(buf_size);
err = httpd_get_data(req, buf, buf_size);
require_noerr( err, Save_Out );
err = httpd_get_tag_from_post_data(buf, "SSID", value_ssid, maxSsidLen);
require_noerr( err, Save_Out );
err = httpd_get_tag_from_post_data(buf, "USER", value_user, maxNameLen);
require_noerr( err, Save_Out );
if(!strncmp(value_ssid, "\0", 1))
goto Save_Out;
if(!strncmp(value_user, "\0", 1))
goto Save_Out;
strncpy(context->micoSystemConfig.ssid, value_ssid, maxSsidLen);
strncpy(user_config->user, value_user, maxNameLen);
err = httpd_get_tag_from_post_data(buf, "PASS", value_pass, maxKeyLen);
require_noerr( err, Save_Out );
strncpy(context->micoSystemConfig.key, value_pass, maxKeyLen);
strncpy(context->micoSystemConfig.user_key, value_pass, maxKeyLen);
context->micoSystemConfig.keyLength = strlen(context->micoSystemConfig.key);
context->micoSystemConfig.user_keyLength = strlen(context->micoSystemConfig.key);
context->micoSystemConfig.channel = 0;
memset(context->micoSystemConfig.bssid, 0x0, 6);
context->micoSystemConfig.security = SECURITY_TYPE_AUTO;
context->micoSystemConfig.dhcpEnable = true;
para_succ = true;
Save_Out:
if(para_succ == true)
{
err = httpd_send_all_header(req, HTTP_RES_200, sizeof(wifisuccess), HTTP_CONTENT_HTML_STR);
require_noerr_action( err, exit, app_httpd_log("ERROR: Unable to send http wifisuccess headers.") );
err = httpd_send_body(req->sock, wifisuccess, sizeof(wifisuccess));
require_noerr_action( err, exit, app_httpd_log("ERROR: Unable to send http wifisuccess body.") );
context->micoSystemConfig.configured = allConfigured;
mico_system_context_update(context);
mico_system_power_perform( context, eState_Software_Reset );
}
else
{
err = httpd_send_all_header(req, HTTP_RES_200, sizeof(wififail), HTTP_CONTENT_HTML_STR);
require_noerr_action( err, exit, app_httpd_log("ERROR: Unable to send http wififail headers.") );
err = httpd_send_body(req->sock, wififail, sizeof(wififail));
require_noerr_action( err, exit, app_httpd_log("ERROR: Unable to send http wififail body.") );
}
exit:
if(buf) free(buf);
return err;
}
struct httpd_wsgi_call g_app_handlers[] = {
{"/", HTTPD_HDR_DEFORT, 0, web_send_wifisetting_page, NULL, NULL, NULL},
{"/result.htm", HTTPD_HDR_DEFORT, 0, NULL, web_send_result_page, NULL, NULL},
{"/setting.htm", HTTPD_HDR_DEFORT, 0, web_send_wifisetting_page, NULL, NULL, NULL},
};
static int g_app_handlers_no = sizeof(g_app_handlers)/sizeof(struct httpd_wsgi_call);
static void app_http_register_handlers()
{
int rc;
rc = httpd_register_wsgi_handlers(g_app_handlers, g_app_handlers_no);
if (rc) {
app_httpd_log("failed to register test web handler");
}
}
static int _app_httpd_start()
{
OSStatus err = kNoErr;
app_httpd_log("initializing web-services");
/*Initialize HTTPD*/
if(is_http_init == false) {
err = httpd_init();
require_noerr_action( err, exit, app_httpd_log("failed to initialize httpd") );
is_http_init = true;
}
/*Start http thread*/
err = httpd_start();
if(err != kNoErr) {
app_httpd_log("failed to start httpd thread");
httpd_shutdown();
}
exit:
return err;
}
int app_httpd_start( void )
{
OSStatus err = kNoErr;
err = _app_httpd_start();
require_noerr( err, exit );
if (is_handlers_registered == false) {
app_http_register_handlers();
is_handlers_registered = true;
}
exit:
return err;
}
int app_httpd_stop()
{
OSStatus err = kNoErr;
/* HTTPD and services */
app_httpd_log("stopping down httpd");
err = httpd_stop();
require_noerr_action( err, exit, app_httpd_log("failed to halt httpd") );
exit:
return err;
}

View File

@@ -0,0 +1,43 @@
/**
******************************************************************************
* @file app_httpd.h
* @author QQ DING
* @version V1.0.0
* @date 1-September-2015
* @brief This header contains function prototypes called by httpd protocol
* operations
******************************************************************************
*
* The MIT License
* Copyright (c) 2016 MXCHIP Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
* IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
******************************************************************************
*/
extern const unsigned char wififail[0xAC9];
extern const unsigned char wifisetting[3618];
extern const unsigned char wifisuccess[0x9BC];
int app_httpd_start( void );
int app_httpd_stop();

View File

@@ -0,0 +1,41 @@
/**
@page " http_sever " demo
@verbatim
******************** (C) COPYRIGHT 2016 MXCHIP MiCO SDK*******************
* @file http_sever/readme.txt
* @author MDWG (MiCO Documentation Working Group)
* @version v2.4.x
* @date 11-April-2016
* @brief Description of the "http_sever" demo.
******************************************************************************
@par Demo Description
This demo shows: how to start http sever to realize network configuration through webpage on PC or Mobile Phone.
@par Directory contents
- Demos/http/http_sever/http_sever.c HTTP server demo entrance
- Demos/http/http_sever/app_httpd.c HTTP server demo
- Demos/http/http_sever/web_data.c Webpage applicaiton program
- Demos/http/http_sever/mico_config.h MiCO function header file
- Demos/http/http_sever/app_httpd.h app_httpd.c header file
@par Hardware and Software environment
- This demo has been tested on MiCOKit-3165 board.
- This demo can be easily tailored to any other supported device and development board.
@par How to use it ?
In order to make the program work, you must do the following :
- Open your preferred toolchain,
- IDE: IAR 7.30.4 or Keil MDK 5.13.
- Debugging Tools: JLINK or STLINK
- Modify header file path of "mico_config.h". Please referring to "http://mico.io/wiki/doku.php?id=confighchange"
- Rebuild all files and load your image into target memory. Please referring to "http://mico.io/wiki/doku.php?id=debug"
- Run the demo.
- 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
**/

601
TC1/http_server/web_data.c Normal file
View File

@@ -0,0 +1,601 @@
/**
******************************************************************************
* @file web_data.c
* @author QQ DING
* @version V1.0.0
* @date 1-September-2015
* @brief This header file contains some data page
******************************************************************************
*
* The MIT License
* Copyright (c) 2016 MXCHIP Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
* IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
******************************************************************************
*/
const unsigned char wififail[0xAC9] = {
0x3C, 0x21, 0x44, 0x4F, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20, 0x68, 0x74, 0x6D, 0x6C, 0x20, 0x50,
0x55, 0x42, 0x4C, 0x49, 0x43, 0x20, 0x22, 0x2D, 0x2F, 0x2F, 0x57, 0x33, 0x43, 0x2F, 0x2F, 0x44,
0x54, 0x44, 0x20, 0x58, 0x48, 0x54, 0x4D, 0x4C, 0x20, 0x31, 0x2E, 0x30, 0x20, 0x54, 0x72, 0x61,
0x6E, 0x73, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x61, 0x6C, 0x2F, 0x2F, 0x45, 0x4E, 0x22, 0x20, 0x22,
0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x33, 0x2E, 0x6F, 0x72,
0x67, 0x2F, 0x54, 0x52, 0x2F, 0x78, 0x68, 0x74, 0x6D, 0x6C, 0x31, 0x2F, 0x44, 0x54, 0x44, 0x2F,
0x78, 0x68, 0x74, 0x6D, 0x6C, 0x31, 0x2D, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x69, 0x74, 0x69, 0x6F,
0x6E, 0x61, 0x6C, 0x2E, 0x64, 0x74, 0x64, 0x22, 0x3E, 0x0D, 0x0A, 0x3C, 0x68, 0x74, 0x6D, 0x6C,
0x20, 0x78, 0x6D, 0x6C, 0x6E, 0x73, 0x3D, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x77,
0x77, 0x77, 0x2E, 0x77, 0x33, 0x2E, 0x6F, 0x72, 0x67, 0x2F, 0x31, 0x39, 0x39, 0x39, 0x2F, 0x78,
0x68, 0x74, 0x6D, 0x6C, 0x22, 0x3E, 0x0D, 0x0A, 0x3C, 0x68, 0x65, 0x61, 0x64, 0x3E, 0x0D, 0x0A,
0x3C, 0x6D, 0x65, 0x74, 0x61, 0x20, 0x68, 0x74, 0x74, 0x70, 0x2D, 0x65, 0x71, 0x75, 0x69, 0x76,
0x3D, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x2D, 0x74, 0x79, 0x70, 0x65, 0x22, 0x20,
0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x3D, 0x22, 0x74, 0x65, 0x78, 0x74, 0x2F, 0x68, 0x74,
0x6D, 0x6C, 0x22, 0x20, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3D, 0x22, 0x75, 0x74, 0x66,
0x2D, 0x38, 0x22, 0x3E, 0x0D, 0x0A, 0x3C, 0x6D, 0x65, 0x74, 0x61, 0x20, 0x63, 0x6F, 0x6E, 0x74,
0x65, 0x6E, 0x74, 0x3D, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3D, 0x64, 0x65, 0x76, 0x69, 0x63,
0x65, 0x2D, 0x77, 0x69, 0x64, 0x74, 0x68, 0x2C, 0x20, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x61, 0x6C,
0x2D, 0x73, 0x63, 0x61, 0x6C, 0x65, 0x3D, 0x31, 0x2E, 0x30, 0x2C, 0x20, 0x6D, 0x61, 0x78, 0x69,
0x6D, 0x75, 0x6D, 0x2D, 0x73, 0x63, 0x61, 0x6C, 0x65, 0x3D, 0x31, 0x2E, 0x30, 0x2C, 0x20, 0x75,
0x73, 0x65, 0x72, 0x2D, 0x73, 0x63, 0x61, 0x6C, 0x61, 0x62, 0x6C, 0x65, 0x3D, 0x30, 0x22, 0x20,
0x6E, 0x61, 0x6D, 0x65, 0x3D, 0x22, 0x76, 0x69, 0x65, 0x77, 0x70, 0x6F, 0x72, 0x74, 0x22, 0x3E,
0x0D, 0x0A, 0x3C, 0x74, 0x69, 0x74, 0x6C, 0x65, 0x3E, 0xE7, 0xBD, 0x91, 0xE5, 0x85, 0xB3, 0xE4,
0xB8, 0x8A, 0xE7, 0xBD, 0x91, 0xE8, 0xAE, 0xBE, 0xE7, 0xBD, 0xAE, 0x3C, 0x2F, 0x74, 0x69, 0x74,
0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x3C, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20, 0x62,
0x6F, 0x64, 0x79, 0x2C, 0x20, 0x70, 0x2C, 0x20, 0x68, 0x31, 0x2C, 0x20, 0x68, 0x32, 0x2C, 0x20,
0x68, 0x33, 0x2C, 0x20, 0x68, 0x34, 0x2C, 0x20, 0x68, 0x35, 0x2C, 0x20, 0x68, 0x36, 0x2C, 0x20,
0x75, 0x6C, 0x2C, 0x20, 0x6F, 0x6C, 0x2C, 0x20, 0x6C, 0x69, 0x2C, 0x20, 0x64, 0x6C, 0x2C, 0x20,
0x64, 0x74, 0x2C, 0x20, 0x64, 0x64, 0x2C, 0x20, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x2C, 0x20, 0x74,
0x68, 0x2C, 0x20, 0x74, 0x64, 0x2C, 0x20, 0x66, 0x6F, 0x72, 0x6D, 0x2C, 0x20, 0x66, 0x69, 0x65,
0x6C, 0x64, 0x73, 0x65, 0x74, 0x2C, 0x20, 0x6C, 0x65, 0x67, 0x65, 0x6E, 0x64, 0x2C, 0x20, 0x69,
0x6E, 0x70, 0x75, 0x74, 0x2C, 0x20, 0x74, 0x65, 0x78, 0x74, 0x61, 0x72, 0x65, 0x61, 0x2C, 0x20,
0x62, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x2C, 0x20, 0x73, 0x65, 0x6C, 0x65, 0x63, 0x74, 0x2C, 0x20,
0x69, 0x6D, 0x67, 0x2C, 0x20, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x71, 0x75, 0x6F, 0x74, 0x65, 0x20,
0x7B, 0x0D, 0x0A, 0x09, 0x6D, 0x61, 0x72, 0x67, 0x69, 0x6E, 0x3A, 0x20, 0x30, 0x3B, 0x0D, 0x0A,
0x09, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6E, 0x67, 0x3A, 0x20, 0x30, 0x3B, 0x0D, 0x0A, 0x09, 0x62,
0x6F, 0x72, 0x64, 0x65, 0x72, 0x3A, 0x20, 0x30, 0x3B, 0x0D, 0x0A, 0x09, 0x66, 0x6F, 0x6E, 0x74,
0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3B, 0x0D, 0x0A, 0x09, 0x76,
0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6C, 0x2D, 0x61, 0x6C, 0x69, 0x67, 0x6E, 0x3A, 0x20, 0x62,
0x61, 0x73, 0x65, 0x6C, 0x69, 0x6E, 0x65, 0x3B, 0x0D, 0x0A, 0x09, 0x66, 0x6F, 0x6E, 0x74, 0x2D,
0x66, 0x61, 0x6D, 0x69, 0x6C, 0x79, 0x3A, 0x20, 0x22, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F,
0x66, 0x74, 0x20, 0x59, 0x61, 0x48, 0x65, 0x69, 0x22, 0x2C, 0x22, 0x69, 0x63, 0x6F, 0x6E, 0x66,
0x6F, 0x6E, 0x74, 0x22, 0x2C, 0x22, 0x46, 0x6F, 0x6E, 0x74, 0x41, 0x77, 0x65, 0x73, 0x6F, 0x6D,
0x65, 0x22, 0x20, 0x20, 0x21, 0x69, 0x6D, 0x70, 0x6F, 0x72, 0x74, 0x61, 0x6E, 0x74, 0x3B, 0x0D,
0x0A, 0x7D, 0x0D, 0x0A, 0x68, 0x31, 0x2C, 0x20, 0x68, 0x32, 0x2C, 0x20, 0x68, 0x33, 0x2C, 0x20,
0x68, 0x34, 0x2C, 0x20, 0x68, 0x35, 0x2C, 0x20, 0x68, 0x36, 0x20, 0x7B, 0x0D, 0x0A, 0x09, 0x66,
0x6F, 0x6E, 0x74, 0x2D, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x20, 0x6E, 0x6F, 0x72, 0x6D,
0x61, 0x6C, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x62, 0x6F, 0x64, 0x79, 0x7B, 0x0D, 0x0A, 0x09,
0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x3A, 0x20, 0x23, 0x66, 0x35, 0x66,
0x35, 0x66, 0x35, 0x0D, 0x0A, 0x09, 0x7D, 0x0D, 0x0A, 0x62, 0x6F, 0x64, 0x79, 0x2C, 0x20, 0x68,
0x74, 0x6D, 0x6C, 0x20, 0x7B, 0x0D, 0x0A, 0x09, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x20,
0x31, 0x30, 0x30, 0x25, 0x3B, 0x0D, 0x0A, 0x09, 0x6D, 0x61, 0x78, 0x2D, 0x68, 0x65, 0x69, 0x67,
0x68, 0x74, 0x3A, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x68, 0x74,
0x6D, 0x6C, 0x7B, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x36, 0x32, 0x2E,
0x35, 0x25, 0x3B, 0x7D, 0x0D, 0x0A, 0x0D, 0x0A, 0x2E, 0x6D, 0x61, 0x69, 0x6E, 0x7B, 0x0D, 0x0A,
0x09, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3A, 0x31, 0x30, 0x30, 0x25, 0x3B, 0x0D, 0x0A, 0x09, 0x6D,
0x69, 0x6E, 0x2D, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x31, 0x30, 0x30, 0x25, 0x3B, 0x0D,
0x0A, 0x09, 0x70, 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x3A, 0x72, 0x65, 0x6C, 0x61, 0x74,
0x69, 0x76, 0x65, 0x3B, 0x0D, 0x0A, 0x09, 0x62, 0x6F, 0x78, 0x2D, 0x73, 0x69, 0x7A, 0x69, 0x6E,
0x67, 0x3A, 0x20, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x62, 0x6F, 0x78, 0x3B, 0x0D, 0x0A,
0x09, 0x2D, 0x77, 0x65, 0x62, 0x6B, 0x69, 0x74, 0x2D, 0x62, 0x6F, 0x78, 0x2D, 0x73, 0x69, 0x7A,
0x69, 0x6E, 0x67, 0x3A, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x62, 0x6F, 0x78, 0x3B, 0x0D,
0x0A, 0x09, 0x64, 0x69, 0x73, 0x70, 0x6C, 0x61, 0x79, 0x3A, 0x2D, 0x77, 0x65, 0x62, 0x6B, 0x69,
0x74, 0x2D, 0x62, 0x6F, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x2D, 0x77, 0x65, 0x62, 0x6B, 0x69, 0x74,
0x2D, 0x62, 0x6F, 0x78, 0x2D, 0x6F, 0x72, 0x69, 0x65, 0x6E, 0x74, 0x3A, 0x76, 0x65, 0x72, 0x74,
0x69, 0x63, 0x61, 0x6C, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x68, 0x65, 0x61, 0x64, 0x65,
0x72, 0x20, 0x7B, 0x0D, 0x0A, 0x09, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64,
0x3A, 0x20, 0x23, 0x66, 0x35, 0x36, 0x63, 0x36, 0x63, 0x3B, 0x0D, 0x0A, 0x09, 0x68, 0x65, 0x69,
0x67, 0x68, 0x74, 0x3A, 0x34, 0x38, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x6C, 0x69, 0x6E, 0x65,
0x2D, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x34, 0x38, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09,
0x6F, 0x76, 0x65, 0x72, 0x66, 0x6C, 0x6F, 0x77, 0x3A, 0x20, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6E,
0x3B, 0x0D, 0x0A, 0x09, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3A, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3B,
0x0D, 0x0A, 0x09, 0x62, 0x6F, 0x78, 0x2D, 0x73, 0x69, 0x7A, 0x69, 0x6E, 0x67, 0x3A, 0x20, 0x62,
0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x62, 0x6F, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x70, 0x6F, 0x73,
0x69, 0x74, 0x69, 0x6F, 0x6E, 0x3A, 0x20, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x69, 0x76, 0x65, 0x3B,
0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x68, 0x33, 0x20,
0x7B, 0x0D, 0x0A, 0x09, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x20, 0x31,
0x38, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 0x68, 0x65, 0x69, 0x67,
0x68, 0x74, 0x3A, 0x20, 0x34, 0x38, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x74, 0x65, 0x78, 0x74,
0x2D, 0x61, 0x6C, 0x69, 0x67, 0x6E, 0x3A, 0x20, 0x63, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x3B, 0x0D,
0x0A, 0x09, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x20, 0x23, 0x66, 0x66, 0x66, 0x3B, 0x0D, 0x0A,
0x7D, 0x0D, 0x0A, 0x2E, 0x62, 0x74, 0x6E, 0x2D, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x20, 0x7B,
0x0D, 0x0A, 0x09, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x3A, 0x20, 0x63,
0x65, 0x6E, 0x74, 0x65, 0x72, 0x20, 0x6E, 0x6F, 0x2D, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x3B,
0x0D, 0x0A, 0x09, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x2D, 0x73, 0x69,
0x7A, 0x65, 0x3A, 0x20, 0x31, 0x32, 0x70, 0x78, 0x20, 0x32, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A,
0x09, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3A, 0x20, 0x34, 0x34, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09,
0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x20, 0x34, 0x38, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09,
0x64, 0x69, 0x73, 0x70, 0x6C, 0x61, 0x79, 0x3A, 0x20, 0x69, 0x6E, 0x6C, 0x69, 0x6E, 0x65, 0x2D,
0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x3B, 0x0D, 0x0A, 0x09, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x73, 0x69,
0x7A, 0x65, 0x3A, 0x20, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x6C, 0x69, 0x6E, 0x65, 0x2D,
0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x20, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x6F,
0x76, 0x65, 0x72, 0x66, 0x6C, 0x6F, 0x77, 0x3A, 0x20, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6E, 0x3B,
0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x2E, 0x62, 0x74,
0x6E, 0x2D, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x20, 0x7B, 0x0D, 0x0A, 0x09, 0x70, 0x6F, 0x73,
0x69, 0x74, 0x69, 0x6F, 0x6E, 0x3A, 0x20, 0x61, 0x62, 0x73, 0x6F, 0x6C, 0x75, 0x74, 0x65, 0x3B,
0x0D, 0x0A, 0x09, 0x6C, 0x65, 0x66, 0x74, 0x3A, 0x20, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09,
0x74, 0x6F, 0x70, 0x3A, 0x20, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x77,
0x69, 0x66, 0x69, 0x2D, 0x66, 0x61, 0x69, 0x6C, 0x20, 0x2E, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E,
0x74, 0x7B, 0x0D, 0x0A, 0x09, 0x2D, 0x77, 0x65, 0x62, 0x6B, 0x69, 0x74, 0x2D, 0x62, 0x6F, 0x78,
0x2D, 0x66, 0x6C, 0x65, 0x78, 0x3A, 0x20, 0x31, 0x3B, 0x20, 0x20, 0x20, 0x20, 0x0D, 0x0A, 0x09,
0x2D, 0x6D, 0x6F, 0x7A, 0x2D, 0x62, 0x6F, 0x78, 0x2D, 0x66, 0x6C, 0x65, 0x78, 0x3A, 0x20, 0x31,
0x3B, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0D, 0x0A, 0x09, 0x2D, 0x77, 0x65, 0x62,
0x6B, 0x69, 0x74, 0x2D, 0x66, 0x6C, 0x65, 0x78, 0x3A, 0x20, 0x31, 0x3B, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x0D, 0x0A, 0x09, 0x2D, 0x6D, 0x73, 0x2D, 0x66, 0x6C, 0x65, 0x78, 0x3A, 0x20,
0x31, 0x3B, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0D, 0x0A,
0x09, 0x66, 0x6C, 0x65, 0x78, 0x3A, 0x20, 0x31, 0x3B, 0x20, 0x0D, 0x0A, 0x09, 0x70, 0x61, 0x64,
0x64, 0x69, 0x6E, 0x67, 0x3A, 0x31, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x62, 0x61, 0x63,
0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x2D, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x23, 0x46,
0x46, 0x46, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x77, 0x69, 0x66, 0x69, 0x2D, 0x66, 0x61,
0x69, 0x6C, 0x20, 0x68, 0x32, 0x7B, 0x0D, 0x0A, 0x09, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x20,
0x23, 0x66, 0x35, 0x36, 0x63, 0x36, 0x63, 0x3B, 0x0D, 0x0A, 0x09, 0x66, 0x6F, 0x6E, 0x74, 0x2D,
0x73, 0x69, 0x7A, 0x65, 0x3A, 0x33, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x74, 0x65, 0x78,
0x74, 0x2D, 0x61, 0x6C, 0x69, 0x67, 0x6E, 0x3A, 0x63, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x3B, 0x0D,
0x0A, 0x09, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6E, 0x67, 0x3A, 0x33, 0x30, 0x70, 0x78, 0x20, 0x30,
0x3B, 0x0D, 0x0A, 0x09, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A,
0x33, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x77, 0x69, 0x66, 0x69, 0x2D,
0x66, 0x61, 0x69, 0x6C, 0x20, 0x7B, 0x0D, 0x0A, 0x09, 0x74, 0x65, 0x78, 0x74, 0x2D, 0x69, 0x6E,
0x64, 0x65, 0x6E, 0x74, 0x3A, 0x32, 0x72, 0x65, 0x6D, 0x3B, 0x0D, 0x0A, 0x09, 0x66, 0x6F, 0x6E,
0x74, 0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x31, 0x36, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x6C,
0x69, 0x6E, 0x65, 0x2D, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x32, 0x38, 0x70, 0x78, 0x3B,
0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x62, 0x74, 0x6E, 0x7B, 0x0D, 0x0A, 0x09, 0x74, 0x65, 0x78,
0x74, 0x2D, 0x64, 0x65, 0x63, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x3A, 0x20, 0x6E, 0x6F,
0x6E, 0x65, 0x3B, 0x0D, 0x0A, 0x09, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x34, 0x30, 0x70,
0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74,
0x3A, 0x34, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x73, 0x69,
0x7A, 0x65, 0x3A, 0x31, 0x34, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x64, 0x69, 0x73, 0x70, 0x6C,
0x61, 0x79, 0x3A, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x3B, 0x0D, 0x0A, 0x09, 0x62, 0x6F, 0x72, 0x64,
0x65, 0x72, 0x3A, 0x20, 0x30, 0x20, 0x6E, 0x6F, 0x6E, 0x65, 0x3B, 0x0D, 0x0A, 0x09, 0x63, 0x6F,
0x6C, 0x6F, 0x72, 0x3A, 0x20, 0x23, 0x46, 0x46, 0x46, 0x3B, 0x0D, 0x0A, 0x09, 0x62, 0x6F, 0x72,
0x64, 0x65, 0x72, 0x2D, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3A, 0x20, 0x35, 0x70, 0x78, 0x3B,
0x0D, 0x0A, 0x09, 0x2D, 0x6D, 0x6F, 0x7A, 0x2D, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x72,
0x61, 0x64, 0x69, 0x75, 0x73, 0x3A, 0x20, 0x35, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x2D, 0x77,
0x65, 0x62, 0x6B, 0x69, 0x74, 0x2D, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x72, 0x61, 0x64,
0x69, 0x75, 0x73, 0x3A, 0x20, 0x35, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x6F, 0x75, 0x74, 0x6C,
0x69, 0x6E, 0x65, 0x3A, 0x20, 0x6E, 0x6F, 0x6E, 0x65, 0x3B, 0x0D, 0x0A, 0x09, 0x63, 0x75, 0x72,
0x73, 0x6F, 0x72, 0x3A, 0x20, 0x70, 0x6F, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x3B, 0x0D, 0x0A, 0x09,
0x74, 0x65, 0x78, 0x74, 0x2D, 0x61, 0x6C, 0x69, 0x67, 0x6E, 0x3A, 0x63, 0x65, 0x6E, 0x74, 0x65,
0x72, 0x3B, 0x0D, 0x0A, 0x09, 0x6D, 0x69, 0x6E, 0x2D, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3A, 0x37,
0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6E, 0x67, 0x3A, 0x30,
0x20, 0x31, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x62, 0x74, 0x6E, 0x2D,
0x72, 0x65, 0x64, 0x7B, 0x0D, 0x0A, 0x09, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E,
0x64, 0x2D, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x23, 0x66, 0x35, 0x36, 0x63, 0x36, 0x63, 0x3B,
0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x67, 0x65, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2D, 0x62, 0x74,
0x6E, 0x20, 0x62, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x20, 0x7B, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20,
0x77, 0x69, 0x64, 0x74, 0x68, 0x3A, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3B, 0x0D, 0x0A, 0x09, 0x6D,
0x61, 0x72, 0x67, 0x69, 0x6E, 0x3A, 0x33, 0x35, 0x70, 0x78, 0x20, 0x30, 0x3B, 0x0D, 0x0A, 0x7D,
0x0D, 0x0A, 0x3C, 0x2F, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x3C, 0x2F, 0x68, 0x65,
0x61, 0x64, 0x3E, 0x0D, 0x0A, 0x0D, 0x0A, 0x3C, 0x62, 0x6F, 0x64, 0x79, 0x3E, 0x0D, 0x0A, 0x3C,
0x64, 0x69, 0x76, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22, 0x6D, 0x61, 0x69, 0x6E, 0x20,
0x77, 0x69, 0x66, 0x69, 0x2D, 0x66, 0x61, 0x69, 0x6C, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x3C,
0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22, 0x68, 0x65,
0x61, 0x64, 0x65, 0x72, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x3C, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3D, 0x22, 0x23, 0x22, 0x20, 0x63, 0x6C, 0x61, 0x73,
0x73, 0x3D, 0x22, 0x62, 0x74, 0x6E, 0x2D, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x22, 0x3E, 0xE4,
0xB8, 0x8A, 0xE4, 0xB8, 0x80, 0xE9, 0xA1, 0xB5, 0x3C, 0x2F, 0x61, 0x3E, 0x0D, 0x0A, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x68, 0x33, 0x3E, 0xE7, 0xBD, 0x91, 0xE5, 0x85, 0xB3,
0xE4, 0xB8, 0x8A, 0xE7, 0xBD, 0x91, 0xE8, 0xAE, 0xBE, 0xE7, 0xBD, 0xAE, 0x3C, 0x2F, 0x68, 0x33,
0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x3E,
0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73,
0x3D, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x3C, 0x68, 0x32, 0x3E, 0xE8, 0xAE, 0xBE, 0xE7, 0xBD, 0xAE, 0xE5, 0xA4,
0xB1, 0xE8, 0xB4, 0xA5, 0xEF, 0xBC, 0x81, 0x3C, 0x2F, 0x68, 0x32, 0x3E, 0x0D, 0x0A, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x63, 0x6C,
0x61, 0x73, 0x73, 0x3D, 0x22, 0x67, 0x65, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2D, 0x62, 0x74, 0x6E,
0x22, 0x3E, 0x3C, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3D, 0x22, 0x2F, 0x73, 0x65, 0x74, 0x74,
0x69, 0x6E, 0x67, 0x2E, 0x68, 0x74, 0x6D, 0x22, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22,
0x62, 0x74, 0x6E, 0x20, 0x62, 0x74, 0x6E, 0x2D, 0x72, 0x65, 0x64, 0x20, 0x62, 0x74, 0x6E, 0x2D,
0x74, 0x72, 0x79, 0x22, 0x3E, 0xE5, 0x86, 0x8D, 0xE6, 0xAC, 0xA1, 0xE9, 0x87, 0x8D, 0xE8, 0xAF,
0x95, 0x3C, 0x2F, 0x61, 0x3E, 0x3C, 0x2F, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D,
0x0A, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x64, 0x69, 0x76, 0x3E, 0x0D, 0x0A, 0x3C, 0x2F, 0x64,
0x69, 0x76, 0x3E, 0x0D, 0x0A, 0x0D, 0x0A, 0x3C, 0x2F, 0x62, 0x6F, 0x64, 0x79, 0x3E, 0x0D, 0x0A,
0x3C, 0x2F, 0x68, 0x74, 0x6D, 0x6C, 0x3E, 0x0D, 0x0A
};
const unsigned char wifisetting[] = {
0x3C, 0x21, 0x64, 0x6F, 0x63, 0x74, 0x79, 0x70, 0x65, 0x20, 0x68, 0x74, 0x6D, 0x6C, 0x3E, 0x0D,
0x0A, 0x3C, 0x68, 0x74, 0x6D, 0x6C, 0x3E, 0x0D, 0x0A, 0x3C, 0x68, 0x65, 0x61, 0x64, 0x3E, 0x0D,
0x0A, 0x3C, 0x6D, 0x65, 0x74, 0x61, 0x20, 0x68, 0x74, 0x74, 0x70, 0x2D, 0x65, 0x71, 0x75, 0x69,
0x76, 0x3D, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x2D, 0x74, 0x79, 0x70, 0x65, 0x22,
0x20, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x3D, 0x22, 0x74, 0x65, 0x78, 0x74, 0x2F, 0x68,
0x74, 0x6D, 0x6C, 0x22, 0x20, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3D, 0x22, 0x75, 0x74,
0x66, 0x2D, 0x38, 0x22, 0x3E, 0x0D, 0x0A, 0x3C, 0x6D, 0x65, 0x74, 0x61, 0x20, 0x63, 0x6F, 0x6E,
0x74, 0x65, 0x6E, 0x74, 0x3D, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3D, 0x64, 0x65, 0x76, 0x69,
0x63, 0x65, 0x2D, 0x77, 0x69, 0x64, 0x74, 0x68, 0x2C, 0x20, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x61,
0x6C, 0x2D, 0x73, 0x63, 0x61, 0x6C, 0x65, 0x3D, 0x31, 0x2E, 0x30, 0x2C, 0x20, 0x6D, 0x61, 0x78,
0x69, 0x6D, 0x75, 0x6D, 0x2D, 0x73, 0x63, 0x61, 0x6C, 0x65, 0x3D, 0x31, 0x2E, 0x30, 0x2C, 0x20,
0x75, 0x73, 0x65, 0x72, 0x2D, 0x73, 0x63, 0x61, 0x6C, 0x61, 0x62, 0x6C, 0x65, 0x3D, 0x30, 0x22,
0x20, 0x6E, 0x61, 0x6D, 0x65, 0x3D, 0x22, 0x76, 0x69, 0x65, 0x77, 0x70, 0x6F, 0x72, 0x74, 0x22,
0x3E, 0x0D, 0x0A, 0x3C, 0x74, 0x69, 0x74, 0x6C, 0x65, 0x3E, 0xE7, 0xBD, 0x91, 0xE5, 0x85, 0xB3,
0xE4, 0xB8, 0x8A, 0xE7, 0xBD, 0x91, 0xE8, 0xAE, 0xBE, 0xE7, 0xBD, 0xAE, 0x3C, 0x2F, 0x74, 0x69,
0x74, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x3C, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20,
0x20, 0x62, 0x6F, 0x64, 0x79, 0x2C, 0x20, 0x70, 0x2C, 0x20, 0x68, 0x31, 0x2C, 0x20, 0x68, 0x32,
0x2C, 0x20, 0x68, 0x33, 0x2C, 0x20, 0x68, 0x34, 0x2C, 0x20, 0x68, 0x35, 0x2C, 0x20, 0x68, 0x36,
0x2C, 0x20, 0x75, 0x6C, 0x2C, 0x20, 0x6F, 0x6C, 0x2C, 0x20, 0x6C, 0x69, 0x2C, 0x20, 0x64, 0x6C,
0x2C, 0x20, 0x64, 0x74, 0x2C, 0x20, 0x64, 0x64, 0x2C, 0x20, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x2C,
0x20, 0x74, 0x68, 0x2C, 0x20, 0x74, 0x64, 0x2C, 0x20, 0x66, 0x6F, 0x72, 0x6D, 0x2C, 0x20, 0x66,
0x69, 0x65, 0x6C, 0x64, 0x73, 0x65, 0x74, 0x2C, 0x20, 0x6C, 0x65, 0x67, 0x65, 0x6E, 0x64, 0x2C,
0x20, 0x69, 0x6E, 0x70, 0x75, 0x74, 0x2C, 0x20, 0x74, 0x65, 0x78, 0x74, 0x61, 0x72, 0x65, 0x61,
0x2C, 0x20, 0x62, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x2C, 0x20, 0x73, 0x65, 0x6C, 0x65, 0x63, 0x74,
0x2C, 0x20, 0x69, 0x6D, 0x67, 0x2C, 0x20, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x71, 0x75, 0x6F, 0x74,
0x65, 0x20, 0x7B, 0x0D, 0x0A, 0x09, 0x6D, 0x61, 0x72, 0x67, 0x69, 0x6E, 0x3A, 0x20, 0x30, 0x3B,
0x0D, 0x0A, 0x09, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6E, 0x67, 0x3A, 0x20, 0x30, 0x3B, 0x0D, 0x0A,
0x09, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x3A, 0x20, 0x30, 0x3B, 0x0D, 0x0A, 0x09, 0x66, 0x6F,
0x6E, 0x74, 0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3B, 0x0D, 0x0A,
0x09, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6C, 0x2D, 0x61, 0x6C, 0x69, 0x67, 0x6E, 0x3A,
0x20, 0x62, 0x61, 0x73, 0x65, 0x6C, 0x69, 0x6E, 0x65, 0x3B, 0x0D, 0x0A, 0x09, 0x66, 0x6F, 0x6E,
0x74, 0x2D, 0x66, 0x61, 0x6D, 0x69, 0x6C, 0x79, 0x3A, 0x20, 0x22, 0x4D, 0x69, 0x63, 0x72, 0x6F,
0x73, 0x6F, 0x66, 0x74, 0x20, 0x59, 0x61, 0x48, 0x65, 0x69, 0x22, 0x2C, 0x22, 0x69, 0x63, 0x6F,
0x6E, 0x66, 0x6F, 0x6E, 0x74, 0x22, 0x2C, 0x22, 0x46, 0x6F, 0x6E, 0x74, 0x41, 0x77, 0x65, 0x73,
0x6F, 0x6D, 0x65, 0x22, 0x20, 0x20, 0x21, 0x69, 0x6D, 0x70, 0x6F, 0x72, 0x74, 0x61, 0x6E, 0x74,
0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x68, 0x31, 0x2C, 0x20, 0x68, 0x32, 0x2C, 0x20, 0x68, 0x33,
0x2C, 0x20, 0x68, 0x34, 0x2C, 0x20, 0x68, 0x35, 0x2C, 0x20, 0x68, 0x36, 0x20, 0x7B, 0x0D, 0x0A,
0x09, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x20, 0x6E, 0x6F,
0x72, 0x6D, 0x61, 0x6C, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x62, 0x6F, 0x64, 0x79, 0x7B, 0x0D,
0x0A, 0x09, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x3A, 0x20, 0x23, 0x66,
0x35, 0x66, 0x35, 0x66, 0x35, 0x0D, 0x0A, 0x09, 0x7D, 0x0D, 0x0A, 0x62, 0x6F, 0x64, 0x79, 0x2C,
0x20, 0x68, 0x74, 0x6D, 0x6C, 0x20, 0x7B, 0x0D, 0x0A, 0x09, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74,
0x3A, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3B, 0x0D, 0x0A, 0x09, 0x6D, 0x61, 0x78, 0x2D, 0x68, 0x65,
0x69, 0x67, 0x68, 0x74, 0x3A, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A,
0x68, 0x74, 0x6D, 0x6C, 0x7B, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x36,
0x32, 0x2E, 0x35, 0x25, 0x3B, 0x7D, 0x0D, 0x0A, 0x2E, 0x6D, 0x61, 0x69, 0x6E, 0x7B, 0x0D, 0x0A,
0x09, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3A, 0x31, 0x30, 0x30, 0x25, 0x3B, 0x0D, 0x0A, 0x09, 0x6D,
0x69, 0x6E, 0x2D, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x31, 0x30, 0x30, 0x25, 0x3B, 0x0D,
0x0A, 0x09, 0x70, 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x3A, 0x72, 0x65, 0x6C, 0x61, 0x74,
0x69, 0x76, 0x65, 0x3B, 0x0D, 0x0A, 0x09, 0x62, 0x6F, 0x78, 0x2D, 0x73, 0x69, 0x7A, 0x69, 0x6E,
0x67, 0x3A, 0x20, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x62, 0x6F, 0x78, 0x3B, 0x0D, 0x0A,
0x09, 0x2D, 0x77, 0x65, 0x62, 0x6B, 0x69, 0x74, 0x2D, 0x62, 0x6F, 0x78, 0x2D, 0x73, 0x69, 0x7A,
0x69, 0x6E, 0x67, 0x3A, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x62, 0x6F, 0x78, 0x3B, 0x0D,
0x0A, 0x09, 0x64, 0x69, 0x73, 0x70, 0x6C, 0x61, 0x79, 0x3A, 0x2D, 0x77, 0x65, 0x62, 0x6B, 0x69,
0x74, 0x2D, 0x62, 0x6F, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x2D, 0x77, 0x65, 0x62, 0x6B, 0x69, 0x74,
0x2D, 0x62, 0x6F, 0x78, 0x2D, 0x6F, 0x72, 0x69, 0x65, 0x6E, 0x74, 0x3A, 0x76, 0x65, 0x72, 0x74,
0x69, 0x63, 0x61, 0x6C, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x68, 0x65, 0x61, 0x64, 0x65,
0x72, 0x20, 0x7B, 0x0D, 0x0A, 0x09, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64,
0x3A, 0x20, 0x23, 0x66, 0x35, 0x36, 0x63, 0x36, 0x63, 0x3B, 0x0D, 0x0A, 0x09, 0x68, 0x65, 0x69,
0x67, 0x68, 0x74, 0x3A, 0x34, 0x38, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x6C, 0x69, 0x6E, 0x65,
0x2D, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x34, 0x38, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09,
0x6F, 0x76, 0x65, 0x72, 0x66, 0x6C, 0x6F, 0x77, 0x3A, 0x20, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6E,
0x3B, 0x0D, 0x0A, 0x09, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3A, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3B,
0x0D, 0x0A, 0x09, 0x62, 0x6F, 0x78, 0x2D, 0x73, 0x69, 0x7A, 0x69, 0x6E, 0x67, 0x3A, 0x20, 0x62,
0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x62, 0x6F, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x70, 0x6F, 0x73,
0x69, 0x74, 0x69, 0x6F, 0x6E, 0x3A, 0x20, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x69, 0x76, 0x65, 0x3B,
0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x68, 0x33, 0x20,
0x7B, 0x0D, 0x0A, 0x09, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x20, 0x31,
0x38, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 0x68, 0x65, 0x69, 0x67,
0x68, 0x74, 0x3A, 0x20, 0x34, 0x38, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x74, 0x65, 0x78, 0x74,
0x2D, 0x61, 0x6C, 0x69, 0x67, 0x6E, 0x3A, 0x20, 0x63, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x3B, 0x0D,
0x0A, 0x09, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x20, 0x23, 0x66, 0x66, 0x66, 0x3B, 0x0D, 0x0A,
0x7D, 0x0D, 0x0A, 0x2E, 0x62, 0x74, 0x6E, 0x2D, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x20, 0x7B,
0x0D, 0x0A, 0x09, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x3A, 0x20, 0x75,
0x72, 0x6C, 0x28, 0x2E, 0x2E, 0x2F, 0x69, 0x6D, 0x61, 0x67, 0x65, 0x73, 0x2F, 0x69, 0x63, 0x6F,
0x6E, 0x30, 0x34, 0x2E, 0x70, 0x6E, 0x67, 0x29, 0x20, 0x63, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x20,
0x6E, 0x6F, 0x2D, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x3B, 0x0D, 0x0A, 0x09, 0x62, 0x61, 0x63,
0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x20, 0x31, 0x32,
0x70, 0x78, 0x20, 0x32, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x77, 0x69, 0x64, 0x74, 0x68,
0x3A, 0x20, 0x34, 0x34, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74,
0x3A, 0x20, 0x34, 0x38, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x64, 0x69, 0x73, 0x70, 0x6C, 0x61,
0x79, 0x3A, 0x20, 0x69, 0x6E, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x3B,
0x0D, 0x0A, 0x09, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x20, 0x30, 0x70,
0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74,
0x3A, 0x20, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x6F, 0x76, 0x65, 0x72, 0x66, 0x6C, 0x6F,
0x77, 0x3A, 0x20, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6E, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E,
0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x2E, 0x62, 0x74, 0x6E, 0x2D, 0x72, 0x65, 0x74, 0x75,
0x72, 0x6E, 0x20, 0x7B, 0x0D, 0x0A, 0x09, 0x70, 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x3A,
0x20, 0x61, 0x62, 0x73, 0x6F, 0x6C, 0x75, 0x74, 0x65, 0x3B, 0x0D, 0x0A, 0x09, 0x6C, 0x65, 0x66,
0x74, 0x3A, 0x20, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x74, 0x6F, 0x70, 0x3A, 0x20, 0x30,
0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x77, 0x69, 0x66, 0x69, 0x2D, 0x73, 0x65,
0x74, 0x20, 0x2E, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x7B, 0x0D, 0x0A, 0x09, 0x6D, 0x61,
0x72, 0x67, 0x69, 0x6E, 0x3A, 0x31, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x2D, 0x77, 0x65,
0x62, 0x6B, 0x69, 0x74, 0x2D, 0x62, 0x6F, 0x78, 0x2D, 0x66, 0x6C, 0x65, 0x78, 0x3A, 0x20, 0x31,
0x3B, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x2D, 0x6D, 0x6F, 0x7A, 0x2D, 0x62, 0x6F, 0x78, 0x2D,
0x66, 0x6C, 0x65, 0x78, 0x3A, 0x20, 0x31, 0x3B, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x2D, 0x77,
0x65, 0x62, 0x6B, 0x69, 0x74, 0x2D, 0x66, 0x6C, 0x65, 0x78, 0x3A, 0x20, 0x31, 0x3B, 0x0D, 0x0A,
0x20, 0x20, 0x20, 0x20, 0x2D, 0x6D, 0x73, 0x2D, 0x66, 0x6C, 0x65, 0x78, 0x3A, 0x20, 0x31, 0x3B,
0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6C, 0x65, 0x78, 0x3A, 0x20, 0x31, 0x3B, 0x0D, 0x0A,
0x7D, 0x0D, 0x0A, 0x2E, 0x67, 0x65, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2D, 0x69, 0x6E, 0x66, 0x6F,
0x2D, 0x62, 0x6F, 0x78, 0x20, 0x2E, 0x69, 0x6E, 0x70, 0x75, 0x74, 0x2D, 0x66, 0x69, 0x65, 0x6C,
0x64, 0x7B, 0x0D, 0x0A, 0x09, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74,
0x3A, 0x32, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61,
0x6C, 0x2D, 0x61, 0x6C, 0x69, 0x67, 0x6E, 0x3A, 0x6D, 0x69, 0x64, 0x64, 0x6C, 0x65, 0x3B, 0x0D,
0x0A, 0x09, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x3A, 0x20, 0x31, 0x70, 0x78, 0x20, 0x73, 0x6F,
0x6C, 0x69, 0x64, 0x20, 0x23, 0x64, 0x37, 0x64, 0x37, 0x64, 0x37, 0x3B, 0x0D, 0x0A, 0x20, 0x20,
0x20, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x20, 0x35, 0x38, 0x70, 0x78, 0x3B, 0x0D,
0x0A, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x3A,
0x20, 0x23, 0x66, 0x66, 0x66, 0x3B, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6F, 0x78, 0x2D,
0x73, 0x69, 0x7A, 0x69, 0x6E, 0x67, 0x3A, 0x20, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x62,
0x6F, 0x78, 0x3B, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x70, 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F,
0x6E, 0x3A, 0x20, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x69, 0x76, 0x65, 0x3B, 0x0D, 0x0A, 0x20, 0x20,
0x20, 0x20, 0x6D, 0x61, 0x72, 0x67, 0x69, 0x6E, 0x2D, 0x62, 0x6F, 0x74, 0x74, 0x6F, 0x6D, 0x3A,
0x20, 0x2D, 0x31, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64,
0x69, 0x6E, 0x67, 0x3A, 0x20, 0x31, 0x39, 0x70, 0x78, 0x20, 0x31, 0x35, 0x70, 0x78, 0x20, 0x31,
0x39, 0x70, 0x78, 0x20, 0x31, 0x38, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x69,
0x6E, 0x70, 0x75, 0x74, 0x2D, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x69, 0x6E, 0x70, 0x75, 0x74,
0x20, 0x7B, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x20,
0x32, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x6C, 0x69, 0x6E, 0x65, 0x2D,
0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x20, 0x32, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x20,
0x20, 0x20, 0x20, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x20, 0x31, 0x34,
0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3A, 0x20,
0x31, 0x30, 0x30, 0x25, 0x3B, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6F, 0x72, 0x64, 0x65,
0x72, 0x3A, 0x20, 0x30, 0x20, 0x6E, 0x6F, 0x6E, 0x65, 0x3B, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20,
0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x3A, 0x20, 0x74, 0x72, 0x61, 0x6E,
0x73, 0x70, 0x61, 0x72, 0x65, 0x6E, 0x74, 0x3B, 0x0D, 0x0A, 0x09, 0x6F, 0x75, 0x74, 0x6C, 0x69,
0x6E, 0x65, 0x3A, 0x20, 0x6D, 0x65, 0x64, 0x69, 0x75, 0x6D, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A,
0x2E, 0x69, 0x6E, 0x70, 0x75, 0x74, 0x2D, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x3A, 0x66, 0x69, 0x72,
0x73, 0x74, 0x2D, 0x6F, 0x66, 0x2D, 0x74, 0x79, 0x70, 0x65, 0x20, 0x7B, 0x0D, 0x0A, 0x20, 0x20,
0x20, 0x20, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x74, 0x6F, 0x70, 0x2D, 0x6C, 0x65, 0x66,
0x74, 0x2D, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3A, 0x20, 0x35, 0x70, 0x78, 0x3B, 0x0D, 0x0A,
0x20, 0x20, 0x20, 0x20, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x74, 0x6F, 0x70, 0x2D, 0x72,
0x69, 0x67, 0x68, 0x74, 0x2D, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3A, 0x20, 0x35, 0x70, 0x78,
0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x69, 0x6E, 0x70, 0x75, 0x74, 0x2D, 0x66, 0x69, 0x65,
0x6C, 0x64, 0x3A, 0x6C, 0x61, 0x73, 0x74, 0x2D, 0x6F, 0x66, 0x2D, 0x74, 0x79, 0x70, 0x65, 0x20,
0x7B, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x62, 0x6F,
0x74, 0x74, 0x6F, 0x6D, 0x2D, 0x6C, 0x65, 0x66, 0x74, 0x2D, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73,
0x3A, 0x20, 0x35, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6F, 0x72, 0x64,
0x65, 0x72, 0x2D, 0x62, 0x6F, 0x74, 0x74, 0x6F, 0x6D, 0x2D, 0x72, 0x69, 0x67, 0x68, 0x74, 0x2D,
0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3A, 0x20, 0x35, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D,
0x0A, 0x2E, 0x62, 0x74, 0x6E, 0x7B, 0x0D, 0x0A, 0x09, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A,
0x34, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 0x68, 0x65, 0x69,
0x67, 0x68, 0x74, 0x3A, 0x34, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x66, 0x6F, 0x6E, 0x74,
0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x31, 0x34, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x64, 0x69,
0x73, 0x70, 0x6C, 0x61, 0x79, 0x3A, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x3B, 0x0D, 0x0A, 0x09, 0x62,
0x6F, 0x72, 0x64, 0x65, 0x72, 0x3A, 0x20, 0x30, 0x20, 0x6E, 0x6F, 0x6E, 0x65, 0x3B, 0x0D, 0x0A,
0x09, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x20, 0x23, 0x46, 0x46, 0x46, 0x3B, 0x0D, 0x0A, 0x09,
0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3A, 0x20, 0x35,
0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x2D, 0x6D, 0x6F, 0x7A, 0x2D, 0x62, 0x6F, 0x72, 0x64, 0x65,
0x72, 0x2D, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3A, 0x20, 0x35, 0x70, 0x78, 0x3B, 0x0D, 0x0A,
0x09, 0x2D, 0x77, 0x65, 0x62, 0x6B, 0x69, 0x74, 0x2D, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D,
0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3A, 0x20, 0x35, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x6F,
0x75, 0x74, 0x6C, 0x69, 0x6E, 0x65, 0x3A, 0x20, 0x6E, 0x6F, 0x6E, 0x65, 0x3B, 0x0D, 0x0A, 0x09,
0x63, 0x75, 0x72, 0x73, 0x6F, 0x72, 0x3A, 0x20, 0x70, 0x6F, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x3B,
0x0D, 0x0A, 0x09, 0x74, 0x65, 0x78, 0x74, 0x2D, 0x61, 0x6C, 0x69, 0x67, 0x6E, 0x3A, 0x63, 0x65,
0x6E, 0x74, 0x65, 0x72, 0x3B, 0x0D, 0x0A, 0x09, 0x6D, 0x69, 0x6E, 0x2D, 0x77, 0x69, 0x64, 0x74,
0x68, 0x3A, 0x37, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6E,
0x67, 0x3A, 0x30, 0x20, 0x31, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x62,
0x74, 0x6E, 0x2D, 0x72, 0x65, 0x64, 0x7B, 0x0D, 0x0A, 0x09, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72,
0x6F, 0x75, 0x6E, 0x64, 0x2D, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x23, 0x66, 0x35, 0x36, 0x63,
0x36, 0x63, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x67, 0x65, 0x74, 0x65, 0x77, 0x61, 0x79,
0x2D, 0x62, 0x74, 0x6E, 0x20, 0x62, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x20, 0x7B, 0x0D, 0x0A, 0x20,
0x20, 0x20, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3A, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3B, 0x0D,
0x0A, 0x09, 0x6D, 0x61, 0x72, 0x67, 0x69, 0x6E, 0x3A, 0x33, 0x35, 0x70, 0x78, 0x20, 0x30, 0x3B,
0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x3C, 0x2F, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x0D,
0x0A, 0x3C, 0x2F, 0x68, 0x65, 0x61, 0x64, 0x3E, 0x0D, 0x0A, 0x0D, 0x0A, 0x3C, 0x62, 0x6F, 0x64,
0x79, 0x3E, 0x0D, 0x0A, 0x3C, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22,
0x6D, 0x61, 0x69, 0x6E, 0x20, 0x77, 0x69, 0x66, 0x69, 0x2D, 0x73, 0x65, 0x74, 0x22, 0x3E, 0x0D,
0x0A, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x20, 0x63, 0x6C,
0x61, 0x73, 0x73, 0x3D, 0x22, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x22, 0x3E, 0x0D, 0x0A, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3D, 0x22,
0x23, 0x22, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22, 0x62, 0x74, 0x6E, 0x2D, 0x72, 0x65,
0x74, 0x75, 0x72, 0x6E, 0x22, 0x3E, 0xE4, 0xB8, 0x8A, 0xE4, 0xB8, 0x80, 0xE9, 0xA1, 0xB5, 0x3C,
0x2F, 0x61, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x68, 0x33,
0x3E, 0xE7, 0xBD, 0x91, 0xE5, 0x85, 0xB3, 0xE4, 0xB8, 0x8A, 0xE7, 0xBD, 0x91, 0xE8, 0xAE, 0xBE,
0xE7, 0xBD, 0xAE, 0x3C, 0x2F, 0x68, 0x33, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F,
0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69,
0x76, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74,
0x22, 0x3E, 0x0D, 0x0A, 0x09, 0x3C, 0x66, 0x6F, 0x72, 0x6D, 0x20, 0x61, 0x63, 0x74, 0x69, 0x6F,
0x6E, 0x3D, 0x22, 0x72, 0x65, 0x73, 0x75, 0x6C, 0x74, 0x2E, 0x68, 0x74, 0x6D, 0x22, 0x20, 0x6D,
0x65, 0x74, 0x68, 0x6F, 0x64, 0x3D, 0x22, 0x70, 0x6F, 0x73, 0x74, 0x22, 0x3E, 0x0D, 0x0A, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x63,
0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22, 0x67, 0x65, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2D, 0x69, 0x6E,
0x66, 0x6F, 0x2D, 0x62, 0x6F, 0x78, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22,
0x69, 0x6E, 0x70, 0x75, 0x74, 0x2D, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x22, 0x3E, 0x0D, 0x0A, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x69, 0x6E, 0x70,
0x75, 0x74, 0x20, 0x69, 0x64, 0x3D, 0x22, 0x73, 0x73, 0x69, 0x64, 0x22, 0x20, 0x74, 0x79, 0x70,
0x65, 0x3D, 0x22, 0x74, 0x65, 0x78, 0x74, 0x22, 0x20, 0x6E, 0x61, 0x6D, 0x65, 0x3D, 0x22, 0x53,
0x53, 0x49, 0x44, 0x22, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x3D, 0x22, 0x22, 0x20, 0x70, 0x6C,
0x61, 0x63, 0x65, 0x68, 0x6F, 0x6C, 0x64, 0x65, 0x72, 0x3D, 0x22, 0x57, 0x49, 0x46, 0x49, 0xE5,
0x90, 0x8D, 0xE7, 0xA7, 0xB0, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x3C, 0x2F, 0x64, 0x69, 0x76, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D,
0x22, 0x69, 0x6E, 0x70, 0x75, 0x74, 0x2D, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x22, 0x3E, 0x0D, 0x0A,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x69, 0x6E,
0x70, 0x75, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3D, 0x22, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6F,
0x72, 0x64, 0x22, 0x20, 0x6E, 0x61, 0x6D, 0x65, 0x3D, 0x22, 0x50, 0x41, 0x53, 0x53, 0x22, 0x20,
0x76, 0x61, 0x6C, 0x75, 0x65, 0x3D, 0x22, 0x22, 0x20, 0x70, 0x6C, 0x61, 0x63, 0x65, 0x68, 0x6F,
0x6C, 0x64, 0x65, 0x72, 0x3D, 0x22, 0xE8, 0xBE, 0x93, 0xE5, 0x85, 0xA5, 0xE5, 0xAF, 0x86, 0xE7,
0xA0, 0x81, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x3C, 0x2F, 0x64, 0x69, 0x76, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x3C, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22, 0x69, 0x6E,
0x70, 0x75, 0x74, 0x2D, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x69, 0x6E, 0x70, 0x75, 0x74,
0x20, 0x74, 0x79, 0x70, 0x65, 0x3D, 0x22, 0x75, 0x73, 0x65, 0x72, 0x22, 0x20, 0x6E, 0x61, 0x6D,
0x65, 0x3D, 0x22, 0x55, 0x53, 0x45, 0x52, 0x22, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x3D, 0x22,
0x22, 0x20, 0x70, 0x6C, 0x61, 0x63, 0x65, 0x68, 0x6F, 0x6C, 0x64, 0x65, 0x72, 0x3D, 0x22, 0xE8,
0xBE, 0x93, 0xE5, 0x85, 0xA5, 0xE7, 0x99, 0xBB, 0xE5, 0xBD, 0x95, 0xE9, 0x82, 0xAE, 0xE7, 0xAE,
0xB1, 0x2C, 0xE6, 0xB3, 0xA8, 0xE6, 0x84, 0x8F, 0xE7, 0x94, 0xA8, 0xE6, 0x88, 0xB7, 0xE8, 0xBE,
0x93, 0xE5, 0x85, 0xA5, 0xE9, 0x94, 0x99, 0xE8, 0xAF, 0xAF, 0xE5, 0xB0, 0x86, 0xE5, 0xAF, 0xBC,
0xE8, 0x87, 0xB4, 0xE6, 0x97, 0xA0, 0xE6, 0xB3, 0x95, 0xE7, 0xBB, 0x91, 0xE5, 0xAE, 0x9A, 0xE8,
0xAE, 0xBE, 0xE5, 0xA4, 0x87, 0x21, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x64, 0x69, 0x76, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20,
0x3C, 0x2F, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x3C, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x63, 0x6C, 0x61,
0x73, 0x73, 0x3D, 0x22, 0x67, 0x65, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2D, 0x62, 0x74, 0x6E, 0x22,
0x3E, 0x3C, 0x62, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3D, 0x22, 0x73,
0x75, 0x62, 0x6D, 0x69, 0x74, 0x22, 0x20, 0x6E, 0x61, 0x6D, 0x65, 0x3D, 0x22, 0x6E, 0x65, 0x78,
0x74, 0x22, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22, 0x62, 0x74, 0x6E, 0x20, 0x62, 0x74,
0x6E, 0x2D, 0x72, 0x65, 0x64, 0x20, 0x62, 0x74, 0x6E, 0x2D, 0x6E, 0x65, 0x78, 0x74, 0x22, 0x3E,
0xE4, 0xB8, 0x8B, 0xE4, 0xB8, 0x80, 0xE6, 0xAD, 0xA5, 0x3C, 0x2F, 0x62, 0x75, 0x74, 0x74, 0x6F,
0x6E, 0x3E, 0x3C, 0x2F, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x0D, 0x0A, 0x09, 0x3C,
0x2F, 0x66, 0x6F, 0x72, 0x6D, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x64, 0x69,
0x76, 0x3E, 0x0D, 0x0A, 0x3C, 0x2F, 0x64, 0x69, 0x76, 0x3E, 0x0D, 0x0A, 0x3C, 0x2F, 0x62, 0x6F,
0x64, 0x79, 0x3E, 0x0D, 0x0A, 0x3C, 0x2F, 0x68, 0x74, 0x6D, 0x6C, 0x3E, 0x0D, 0x0A
};
const unsigned char wifisuccess[0x9BC] = {
0x3C, 0x21, 0x64, 0x6F, 0x63, 0x74, 0x79, 0x70, 0x65, 0x20, 0x68, 0x74, 0x6D, 0x6C, 0x3E, 0x0D,
0x0A, 0x3C, 0x68, 0x74, 0x6D, 0x6C, 0x3E, 0x0D, 0x0A, 0x3C, 0x68, 0x65, 0x61, 0x64, 0x3E, 0x0D,
0x0A, 0x3C, 0x6D, 0x65, 0x74, 0x61, 0x20, 0x68, 0x74, 0x74, 0x70, 0x2D, 0x65, 0x71, 0x75, 0x69,
0x76, 0x3D, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x2D, 0x74, 0x79, 0x70, 0x65, 0x22,
0x20, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x3D, 0x22, 0x74, 0x65, 0x78, 0x74, 0x2F, 0x68,
0x74, 0x6D, 0x6C, 0x22, 0x20, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3D, 0x22, 0x75, 0x74,
0x66, 0x2D, 0x38, 0x22, 0x3E, 0x0D, 0x0A, 0x3C, 0x6D, 0x65, 0x74, 0x61, 0x20, 0x63, 0x6F, 0x6E,
0x74, 0x65, 0x6E, 0x74, 0x3D, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3D, 0x64, 0x65, 0x76, 0x69,
0x63, 0x65, 0x2D, 0x77, 0x69, 0x64, 0x74, 0x68, 0x2C, 0x20, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x61,
0x6C, 0x2D, 0x73, 0x63, 0x61, 0x6C, 0x65, 0x3D, 0x31, 0x2E, 0x30, 0x2C, 0x20, 0x6D, 0x61, 0x78,
0x69, 0x6D, 0x75, 0x6D, 0x2D, 0x73, 0x63, 0x61, 0x6C, 0x65, 0x3D, 0x31, 0x2E, 0x30, 0x2C, 0x20,
0x75, 0x73, 0x65, 0x72, 0x2D, 0x73, 0x63, 0x61, 0x6C, 0x61, 0x62, 0x6C, 0x65, 0x3D, 0x30, 0x22,
0x20, 0x6E, 0x61, 0x6D, 0x65, 0x3D, 0x22, 0x76, 0x69, 0x65, 0x77, 0x70, 0x6F, 0x72, 0x74, 0x22,
0x3E, 0x0D, 0x0A, 0x3C, 0x74, 0x69, 0x74, 0x6C, 0x65, 0x3E, 0xE7, 0xBD, 0x91, 0xE5, 0x85, 0xB3,
0xE4, 0xB8, 0x8A, 0xE7, 0xBD, 0x91, 0xE8, 0xAE, 0xBE, 0xE7, 0xBD, 0xAE, 0x3C, 0x2F, 0x74, 0x69,
0x74, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x3C, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x3E, 0x0D, 0x0A, 0x20,
0x62, 0x6F, 0x64, 0x79, 0x2C, 0x20, 0x70, 0x2C, 0x20, 0x68, 0x31, 0x2C, 0x20, 0x68, 0x32, 0x2C,
0x20, 0x68, 0x33, 0x2C, 0x20, 0x68, 0x34, 0x2C, 0x20, 0x68, 0x35, 0x2C, 0x20, 0x68, 0x36, 0x2C,
0x20, 0x75, 0x6C, 0x2C, 0x20, 0x6F, 0x6C, 0x2C, 0x20, 0x6C, 0x69, 0x2C, 0x20, 0x64, 0x6C, 0x2C,
0x20, 0x64, 0x74, 0x2C, 0x20, 0x64, 0x64, 0x2C, 0x20, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x2C, 0x20,
0x74, 0x68, 0x2C, 0x20, 0x74, 0x64, 0x2C, 0x20, 0x66, 0x6F, 0x72, 0x6D, 0x2C, 0x20, 0x66, 0x69,
0x65, 0x6C, 0x64, 0x73, 0x65, 0x74, 0x2C, 0x20, 0x6C, 0x65, 0x67, 0x65, 0x6E, 0x64, 0x2C, 0x20,
0x69, 0x6E, 0x70, 0x75, 0x74, 0x2C, 0x20, 0x74, 0x65, 0x78, 0x74, 0x61, 0x72, 0x65, 0x61, 0x2C,
0x20, 0x62, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x2C, 0x20, 0x73, 0x65, 0x6C, 0x65, 0x63, 0x74, 0x2C,
0x20, 0x69, 0x6D, 0x67, 0x2C, 0x20, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x71, 0x75, 0x6F, 0x74, 0x65,
0x20, 0x7B, 0x0D, 0x0A, 0x09, 0x6D, 0x61, 0x72, 0x67, 0x69, 0x6E, 0x3A, 0x20, 0x30, 0x3B, 0x0D,
0x0A, 0x09, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6E, 0x67, 0x3A, 0x20, 0x30, 0x3B, 0x0D, 0x0A, 0x09,
0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x3A, 0x20, 0x30, 0x3B, 0x0D, 0x0A, 0x09, 0x66, 0x6F, 0x6E,
0x74, 0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3B, 0x0D, 0x0A, 0x09,
0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6C, 0x2D, 0x61, 0x6C, 0x69, 0x67, 0x6E, 0x3A, 0x20,
0x62, 0x61, 0x73, 0x65, 0x6C, 0x69, 0x6E, 0x65, 0x3B, 0x0D, 0x0A, 0x09, 0x66, 0x6F, 0x6E, 0x74,
0x2D, 0x66, 0x61, 0x6D, 0x69, 0x6C, 0x79, 0x3A, 0x20, 0x22, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73,
0x6F, 0x66, 0x74, 0x20, 0x59, 0x61, 0x48, 0x65, 0x69, 0x22, 0x2C, 0x22, 0x69, 0x63, 0x6F, 0x6E,
0x66, 0x6F, 0x6E, 0x74, 0x22, 0x2C, 0x22, 0x46, 0x6F, 0x6E, 0x74, 0x41, 0x77, 0x65, 0x73, 0x6F,
0x6D, 0x65, 0x22, 0x20, 0x20, 0x21, 0x69, 0x6D, 0x70, 0x6F, 0x72, 0x74, 0x61, 0x6E, 0x74, 0x3B,
0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x68, 0x31, 0x2C, 0x20, 0x68, 0x32, 0x2C, 0x20, 0x68, 0x33, 0x2C,
0x20, 0x68, 0x34, 0x2C, 0x20, 0x68, 0x35, 0x2C, 0x20, 0x68, 0x36, 0x20, 0x7B, 0x0D, 0x0A, 0x09,
0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x20, 0x6E, 0x6F, 0x72,
0x6D, 0x61, 0x6C, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x62, 0x6F, 0x64, 0x79, 0x7B, 0x0D, 0x0A,
0x09, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x3A, 0x20, 0x23, 0x66, 0x35,
0x66, 0x35, 0x66, 0x35, 0x0D, 0x0A, 0x09, 0x7D, 0x0D, 0x0A, 0x62, 0x6F, 0x64, 0x79, 0x2C, 0x20,
0x68, 0x74, 0x6D, 0x6C, 0x20, 0x7B, 0x0D, 0x0A, 0x09, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A,
0x20, 0x31, 0x30, 0x30, 0x25, 0x3B, 0x0D, 0x0A, 0x09, 0x6D, 0x61, 0x78, 0x2D, 0x68, 0x65, 0x69,
0x67, 0x68, 0x74, 0x3A, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x68,
0x74, 0x6D, 0x6C, 0x7B, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x36, 0x32,
0x2E, 0x35, 0x25, 0x3B, 0x7D, 0x0D, 0x0A, 0x2E, 0x6D, 0x61, 0x69, 0x6E, 0x7B, 0x0D, 0x0A, 0x09,
0x77, 0x69, 0x64, 0x74, 0x68, 0x3A, 0x31, 0x30, 0x30, 0x25, 0x3B, 0x0D, 0x0A, 0x09, 0x6D, 0x69,
0x6E, 0x2D, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x31, 0x30, 0x30, 0x25, 0x3B, 0x0D, 0x0A,
0x09, 0x70, 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x3A, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x69,
0x76, 0x65, 0x3B, 0x0D, 0x0A, 0x09, 0x62, 0x6F, 0x78, 0x2D, 0x73, 0x69, 0x7A, 0x69, 0x6E, 0x67,
0x3A, 0x20, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x62, 0x6F, 0x78, 0x3B, 0x0D, 0x0A, 0x09,
0x2D, 0x77, 0x65, 0x62, 0x6B, 0x69, 0x74, 0x2D, 0x62, 0x6F, 0x78, 0x2D, 0x73, 0x69, 0x7A, 0x69,
0x6E, 0x67, 0x3A, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x62, 0x6F, 0x78, 0x3B, 0x0D, 0x0A,
0x09, 0x64, 0x69, 0x73, 0x70, 0x6C, 0x61, 0x79, 0x3A, 0x2D, 0x77, 0x65, 0x62, 0x6B, 0x69, 0x74,
0x2D, 0x62, 0x6F, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x2D, 0x77, 0x65, 0x62, 0x6B, 0x69, 0x74, 0x2D,
0x62, 0x6F, 0x78, 0x2D, 0x6F, 0x72, 0x69, 0x65, 0x6E, 0x74, 0x3A, 0x76, 0x65, 0x72, 0x74, 0x69,
0x63, 0x61, 0x6C, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72,
0x20, 0x7B, 0x0D, 0x0A, 0x09, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x3A,
0x20, 0x23, 0x66, 0x35, 0x36, 0x63, 0x36, 0x63, 0x3B, 0x0D, 0x0A, 0x09, 0x68, 0x65, 0x69, 0x67,
0x68, 0x74, 0x3A, 0x34, 0x38, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x6C, 0x69, 0x6E, 0x65, 0x2D,
0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x34, 0x38, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x6F,
0x76, 0x65, 0x72, 0x66, 0x6C, 0x6F, 0x77, 0x3A, 0x20, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6E, 0x3B,
0x0D, 0x0A, 0x09, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3A, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3B, 0x0D,
0x0A, 0x09, 0x62, 0x6F, 0x78, 0x2D, 0x73, 0x69, 0x7A, 0x69, 0x6E, 0x67, 0x3A, 0x20, 0x62, 0x6F,
0x72, 0x64, 0x65, 0x72, 0x2D, 0x62, 0x6F, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x70, 0x6F, 0x73, 0x69,
0x74, 0x69, 0x6F, 0x6E, 0x3A, 0x20, 0x72, 0x65, 0x6C, 0x61, 0x74, 0x69, 0x76, 0x65, 0x3B, 0x0D,
0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x68, 0x33, 0x20, 0x7B,
0x0D, 0x0A, 0x09, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x20, 0x31, 0x38,
0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 0x68, 0x65, 0x69, 0x67, 0x68,
0x74, 0x3A, 0x20, 0x34, 0x38, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x74, 0x65, 0x78, 0x74, 0x2D,
0x61, 0x6C, 0x69, 0x67, 0x6E, 0x3A, 0x20, 0x63, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x3B, 0x0D, 0x0A,
0x09, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x20, 0x23, 0x66, 0x66, 0x66, 0x3B, 0x0D, 0x0A, 0x7D,
0x0D, 0x0A, 0x2E, 0x62, 0x74, 0x6E, 0x2D, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x20, 0x7B, 0x0D,
0x0A, 0x09, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x3A, 0x20, 0x63, 0x65,
0x6E, 0x74, 0x65, 0x72, 0x20, 0x6E, 0x6F, 0x2D, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x3B, 0x0D,
0x0A, 0x09, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x2D, 0x73, 0x69, 0x7A,
0x65, 0x3A, 0x20, 0x31, 0x32, 0x70, 0x78, 0x20, 0x32, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09,
0x77, 0x69, 0x64, 0x74, 0x68, 0x3A, 0x20, 0x34, 0x34, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x68,
0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x20, 0x34, 0x38, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x64,
0x69, 0x73, 0x70, 0x6C, 0x61, 0x79, 0x3A, 0x20, 0x69, 0x6E, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 0x62,
0x6C, 0x6F, 0x63, 0x6B, 0x3B, 0x0D, 0x0A, 0x09, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x73, 0x69, 0x7A,
0x65, 0x3A, 0x20, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 0x68,
0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x20, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x6F, 0x76,
0x65, 0x72, 0x66, 0x6C, 0x6F, 0x77, 0x3A, 0x20, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6E, 0x3B, 0x0D,
0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x2E, 0x62, 0x74, 0x6E,
0x2D, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x20, 0x7B, 0x0D, 0x0A, 0x09, 0x70, 0x6F, 0x73, 0x69,
0x74, 0x69, 0x6F, 0x6E, 0x3A, 0x20, 0x61, 0x62, 0x73, 0x6F, 0x6C, 0x75, 0x74, 0x65, 0x3B, 0x0D,
0x0A, 0x09, 0x6C, 0x65, 0x66, 0x74, 0x3A, 0x20, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x74,
0x6F, 0x70, 0x3A, 0x20, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x77, 0x69,
0x66, 0x69, 0x2D, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x20, 0x2E, 0x63, 0x6F, 0x6E, 0x74,
0x65, 0x6E, 0x74, 0x7B, 0x0D, 0x0A, 0x09, 0x2D, 0x77, 0x65, 0x62, 0x6B, 0x69, 0x74, 0x2D, 0x62,
0x6F, 0x78, 0x2D, 0x66, 0x6C, 0x65, 0x78, 0x3A, 0x20, 0x31, 0x3B, 0x0D, 0x0A, 0x20, 0x20, 0x20,
0x20, 0x2D, 0x6D, 0x6F, 0x7A, 0x2D, 0x62, 0x6F, 0x78, 0x2D, 0x66, 0x6C, 0x65, 0x78, 0x3A, 0x20,
0x31, 0x3B, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x2D, 0x77, 0x65, 0x62, 0x6B, 0x69, 0x74, 0x2D,
0x66, 0x6C, 0x65, 0x78, 0x3A, 0x20, 0x31, 0x3B, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x2D, 0x6D,
0x73, 0x2D, 0x66, 0x6C, 0x65, 0x78, 0x3A, 0x20, 0x31, 0x3B, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20,
0x66, 0x6C, 0x65, 0x78, 0x3A, 0x20, 0x31, 0x3B, 0x0D, 0x0A, 0x09, 0x70, 0x61, 0x64, 0x64, 0x69,
0x6E, 0x67, 0x3A, 0x31, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x62, 0x61, 0x63, 0x6B, 0x67,
0x72, 0x6F, 0x75, 0x6E, 0x64, 0x2D, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x23, 0x46, 0x46, 0x46,
0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x77, 0x69, 0x66, 0x69, 0x2D, 0x73, 0x75, 0x63, 0x63,
0x65, 0x73, 0x73, 0x20, 0x68, 0x32, 0x7B, 0x0D, 0x0A, 0x09, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A,
0x20, 0x23, 0x66, 0x35, 0x36, 0x63, 0x36, 0x63, 0x3B, 0x0D, 0x0A, 0x09, 0x66, 0x6F, 0x6E, 0x74,
0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x33, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x74, 0x65,
0x78, 0x74, 0x2D, 0x61, 0x6C, 0x69, 0x67, 0x6E, 0x3A, 0x63, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x3B,
0x0D, 0x0A, 0x09, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6E, 0x67, 0x3A, 0x33, 0x30, 0x70, 0x78, 0x20,
0x30, 0x3B, 0x0D, 0x0A, 0x09, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74,
0x3A, 0x33, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x77, 0x69, 0x66, 0x69,
0x2D, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x20, 0x70, 0x7B, 0x0D, 0x0A, 0x09, 0x74, 0x65,
0x78, 0x74, 0x2D, 0x69, 0x6E, 0x64, 0x65, 0x6E, 0x74, 0x3A, 0x32, 0x72, 0x65, 0x6D, 0x3B, 0x0D,
0x0A, 0x09, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x31, 0x36, 0x70, 0x78,
0x3B, 0x0D, 0x0A, 0x09, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3A,
0x32, 0x38, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x62, 0x74, 0x6E, 0x7B, 0x0D,
0x0A, 0x09, 0x74, 0x65, 0x78, 0x74, 0x2D, 0x64, 0x65, 0x63, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F,
0x6E, 0x3A, 0x20, 0x6E, 0x6F, 0x6E, 0x65, 0x3B, 0x0D, 0x0A, 0x09, 0x68, 0x65, 0x69, 0x67, 0x68,
0x74, 0x3A, 0x34, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x6C, 0x69, 0x6E, 0x65, 0x2D, 0x68,
0x65, 0x69, 0x67, 0x68, 0x74, 0x3A, 0x34, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x66, 0x6F,
0x6E, 0x74, 0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x31, 0x34, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09,
0x64, 0x69, 0x73, 0x70, 0x6C, 0x61, 0x79, 0x3A, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x3B, 0x0D, 0x0A,
0x09, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x3A, 0x20, 0x30, 0x20, 0x6E, 0x6F, 0x6E, 0x65, 0x3B,
0x0D, 0x0A, 0x09, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x20, 0x23, 0x46, 0x46, 0x46, 0x3B, 0x0D,
0x0A, 0x09, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x2D, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3A,
0x20, 0x35, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x2D, 0x6D, 0x6F, 0x7A, 0x2D, 0x62, 0x6F, 0x72,
0x64, 0x65, 0x72, 0x2D, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3A, 0x20, 0x35, 0x70, 0x78, 0x3B,
0x0D, 0x0A, 0x09, 0x2D, 0x77, 0x65, 0x62, 0x6B, 0x69, 0x74, 0x2D, 0x62, 0x6F, 0x72, 0x64, 0x65,
0x72, 0x2D, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3A, 0x20, 0x35, 0x70, 0x78, 0x3B, 0x0D, 0x0A,
0x09, 0x6F, 0x75, 0x74, 0x6C, 0x69, 0x6E, 0x65, 0x3A, 0x20, 0x6E, 0x6F, 0x6E, 0x65, 0x3B, 0x0D,
0x0A, 0x09, 0x63, 0x75, 0x72, 0x73, 0x6F, 0x72, 0x3A, 0x20, 0x70, 0x6F, 0x69, 0x6E, 0x74, 0x65,
0x72, 0x3B, 0x0D, 0x0A, 0x09, 0x74, 0x65, 0x78, 0x74, 0x2D, 0x61, 0x6C, 0x69, 0x67, 0x6E, 0x3A,
0x63, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x3B, 0x0D, 0x0A, 0x09, 0x6D, 0x69, 0x6E, 0x2D, 0x77, 0x69,
0x64, 0x74, 0x68, 0x3A, 0x37, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x09, 0x70, 0x61, 0x64, 0x64,
0x69, 0x6E, 0x67, 0x3A, 0x30, 0x20, 0x31, 0x30, 0x70, 0x78, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A,
0x2E, 0x62, 0x74, 0x6E, 0x2D, 0x72, 0x65, 0x64, 0x7B, 0x0D, 0x0A, 0x09, 0x62, 0x61, 0x63, 0x6B,
0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x2D, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x3A, 0x23, 0x66, 0x35,
0x36, 0x63, 0x36, 0x63, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x2E, 0x67, 0x65, 0x74, 0x65, 0x77,
0x61, 0x79, 0x2D, 0x62, 0x74, 0x6E, 0x20, 0x62, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x20, 0x7B, 0x0D,
0x0A, 0x20, 0x20, 0x20, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3A, 0x20, 0x31, 0x30, 0x30, 0x25,
0x3B, 0x0D, 0x0A, 0x09, 0x6D, 0x61, 0x72, 0x67, 0x69, 0x6E, 0x3A, 0x33, 0x35, 0x70, 0x78, 0x20,
0x30, 0x3B, 0x0D, 0x0A, 0x7D, 0x0D, 0x0A, 0x3C, 0x2F, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x3E, 0x0D,
0x0A, 0x3C, 0x2F, 0x68, 0x65, 0x61, 0x64, 0x3E, 0x0D, 0x0A, 0x0D, 0x0A, 0x3C, 0x62, 0x6F, 0x64,
0x79, 0x3E, 0x0D, 0x0A, 0x3C, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22,
0x6D, 0x61, 0x69, 0x6E, 0x20, 0x77, 0x69, 0x66, 0x69, 0x2D, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73,
0x73, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x3C, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x63,
0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x22, 0x3E, 0x0D, 0x0A,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3D,
0x22, 0x23, 0x22, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22, 0x62, 0x74, 0x6E, 0x2D, 0x72,
0x65, 0x74, 0x75, 0x72, 0x6E, 0x22, 0x3E, 0xE4, 0xB8, 0x8A, 0xE4, 0xB8, 0x80, 0xE9, 0xA1, 0xB5,
0x3C, 0x2F, 0x61, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x68,
0x33, 0x3E, 0xE7, 0xBD, 0x91, 0xE5, 0x85, 0xB3, 0xE4, 0xB8, 0x8A, 0xE7, 0xBD, 0x91, 0xE8, 0xAE,
0xBE, 0xE7, 0xBD, 0xAE, 0x3C, 0x2F, 0x68, 0x33, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x3C,
0x2F, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x64,
0x69, 0x76, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E,
0x74, 0x22, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x68, 0x32, 0x3E,
0xE8, 0xAE, 0xBE, 0xE7, 0xBD, 0xAE, 0xE6, 0x88, 0x90, 0xE5, 0x8A, 0x9F, 0xEF, 0xBC, 0x81, 0x3C,
0x2F, 0x68, 0x32, 0x3E, 0x0D, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x3C, 0x2F, 0x64, 0x69, 0x76, 0x3E,
0x0D, 0x0A, 0x3C, 0x2F, 0x64, 0x69, 0x76, 0x3E, 0x0D, 0x0A, 0x3C, 0x2F, 0x62, 0x6F, 0x64, 0x79,
0x3E, 0x0D, 0x0A, 0x3C, 0x2F, 0x68, 0x74, 0x6D, 0x6C, 0x3E, 0x0D, 0x0A
};

191
TC1/main.c Normal file
View File

@@ -0,0 +1,191 @@
#include "main.h"
#include "user_gpio.h"
#include "user_wifi.h"
#include "user_rtc.h"
#include "user_udp.h"
#include "user_power.h"
#include "user_mqtt_client.h"
#include "user_function.h"
#include "http_server/app_httpd.h"
#define os_log(format, ...) custom_log("TC1", format, ##__VA_ARGS__)
char rtc_init = 0; //sntpУʱ<D0A3>ɹ<EFBFBD><C9B9><EFBFBD>־λ
uint32_t total_time=0;
char strMac[16] = { 0 };
uint32_t power=0;
system_config_t * sys_config;
user_config_t * user_config;
mico_gpio_t Relay[Relay_NUM] = { Relay_0, Relay_1, Relay_2, Relay_3, Relay_4, Relay_5 };
/* MICO system callback: Restore default configuration provided by application */
void appRestoreDefault_callback( void * const user_config_data, uint32_t size )
{
int i, j;
UNUSED_PARAMETER( size );
mico_system_context_get( )->micoSystemConfig.name[0] = 1; //<2F><><EFBFBD>´<EFBFBD><C2B4><EFBFBD><EFBFBD><EFBFBD>ʱʹ<CAB1><CAB9>Ĭ<EFBFBD><C4AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
mico_system_context_get( )->micoSystemConfig.name[1] = 0;
user_config_t* userConfigDefault = user_config_data;
userConfigDefault->user[0] = 0;
userConfigDefault->mqtt_ip[0] = 0;
userConfigDefault->mqtt_port = 0;
userConfigDefault->mqtt_user[0] = 0;
userConfigDefault->mqtt_password[0] = 0;
userConfigDefault->version = USER_CONFIG_VERSION;
for ( i = 0; i < PLUG_NUM; i++ )
{
userConfigDefault->plug[i].on = 1;
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>1-6
userConfigDefault->plug[i].name[0] = 0xe6;
userConfigDefault->plug[i].name[1] = 0x8f;
userConfigDefault->plug[i].name[2] = 0x92;
userConfigDefault->plug[i].name[3] = 0xe5;
userConfigDefault->plug[i].name[4] = 0x8f;
userConfigDefault->plug[i].name[5] = 0xa3;
userConfigDefault->plug[i].name[6] = i + '1';
userConfigDefault->plug[i].name[7] = 0;
// sprintf( userConfigDefault->plug[i].name, "<22><><EFBFBD><EFBFBD>%d", i );//<2F><><EFBFBD><EFBFBD><EFBFBD>
for ( j = 0; j < PLUG_TIME_TASK_NUM; j++ )
{
userConfigDefault->plug[i].task[j].hour = 0;
userConfigDefault->plug[i].task[j].minute = 0;
userConfigDefault->plug[i].task[j].repeat = 0x00;
userConfigDefault->plug[i].task[j].on = 0;
userConfigDefault->plug[i].task[j].action = 1;
}
}
// mico_system_context_update( sys_config );
}
int application_start( void )
{
int i;
os_log( "Start %s",VERSION );
uint8_t main_num=0;
uint32_t power_last = 0xffffffff;
OSStatus err = kNoErr;
// for ( i = 0; i < Relay_NUM; i++ )
// {
// MicoGpioOutputLow( Relay[(i)] );
// MicoGpioInitialize( Relay[i], OUTPUT_PUSH_PULL );
// MicoGpioOutputLow( Relay[(i)] );
// //MicoGpioOutputHigh(Relay[i]);
// }
/* Create mico system context and read application's config data from flash */
sys_config = mico_system_context_init( sizeof(user_config_t) );
user_config = ((system_context_t *) sys_config)->user_config_data;
require_action( user_config, exit, err = kNoMemoryErr );
err = mico_system_init( sys_config );
require_noerr( err, exit );
MicoGpioInitialize( (mico_gpio_t) Button, INPUT_PULL_UP );
if ( !MicoGpioInputGet( Button ) )
{ //<2F><><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>ť״̬
os_log( "wifi_start_easylink" );
wifi_status = WIFI_STATE_NOEASYLINK; //wifi_init<69><74><EFBFBD><EFBFBD><EFBFBD><EFBFBD>easylink
}
MicoGpioInitialize( (mico_gpio_t) Led, OUTPUT_PUSH_PULL );
for ( i = 0; i < Relay_NUM; i++ )
{
MicoGpioInitialize( Relay[i], OUTPUT_PUSH_PULL );
user_relay_set( i, user_config->plug[i].on );
}
MicoSysLed( 0 );
if ( user_config->version != USER_CONFIG_VERSION || user_config->plug[0].task[0].hour < 0 || user_config->plug[0].task[0].hour > 23 )
{
os_log( "WARNGIN: user params restored!" );
err = mico_system_context_restore( sys_config );
require_noerr( err, exit );
}
if ( sys_config->micoSystemConfig.name[0] == 1 )
{
IPStatusTypedef para;
os_log( "micoWlanGetIPStatus:%d", micoWlanGetIPStatus( &para, Station )); //mac<61><63><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><C8AB><EFBFBD><EFBFBD>0??!!!
strcpy( strMac, para.mac );
os_log( "result:%s",strMac );
os_log( "result:%s",para.mac );
unsigned char mac1, mac2;
mac1 = strtohex( strMac[8], strMac[9] );
mac2 = strtohex( strMac[10], strMac[11] );
os_log( "strtohex:0x%02x%02x",mac1,mac2 );
sprintf( sys_config->micoSystemConfig.name, ZTC1_NAME, mac1, mac2 );
}
os_log( "user:%s",user_config->user );
os_log( "device name:%s",sys_config->micoSystemConfig.name );
os_log( "mqtt_ip:%s",user_config->mqtt_ip );
os_log( "mqtt_port:%d",user_config->mqtt_port );
os_log( "mqtt_user:%s",user_config->mqtt_user );
os_log( "mqtt_password:%s",user_config->mqtt_password );
os_log( "version:%d",user_config->version );
// for ( i = 0; i < PLUG_NUM; i++ )
// {
// os_log("plug_%d:",i);
// os_log("\tname:%s:",user_config->plug[i].name);
// for ( j = 0; j < PLUG_TIME_TASK_NUM; j++ )
// {
// os_log("\t\ton:%d\t %02d:%02d repeat:0x%X",user_config->plug[i].task[j].on,
// user_config->plug[i].task[j].hour,user_config->plug[i].task[j].minute,
// user_config->plug[i].task[j].repeat);
// }
// }
wifi_init( );
user_udp_init( );
key_init( );
err = user_mqtt_init( );
require_noerr( err, exit );
err = user_rtc_init( );
require_noerr( err, exit );
user_power_init();
/* start http server thread */
// app_httpd_start();
while ( 1 )
{
main_num++;
//<2F><><EFBFBD>͹<EFBFBD><CDB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if ( power_last != power || main_num>4 )
{
power_last = power;
main_num =0;
uint8_t *power_buf = NULL;
power_buf = malloc( 128 );
if ( power_buf != NULL )
{
sprintf( power_buf, "{\"mac\":\"%s\",\"power\":\"%d.%d\",\"total_time\":%d}", strMac, power / 10, power % 10, total_time );
user_send( 0, power_buf );
free( power_buf );
}
user_mqtt_hass_power( );
}
mico_thread_msleep(1000);
}
exit:
os_log("application_start ERROR!");
return 0;
}

78
TC1/main.h Normal file
View File

@@ -0,0 +1,78 @@
#ifndef __MAIN_H_
#define __MAIN_H_
#include "mico.h"
#include "MiCOKit_EXT.h"
#define VERSION "v0.10.1"
#define TYPE 1
#define TYPE_NAME "zTC1"
#define ZTC1_NAME "zTC1_%02X%02X"
#define USER_CONFIG_VERSION 2
#define SETTING_MQTT_STRING_LENGTH_MAX 32 //<2F><><EFBFBD><EFBFBD> 4 <20>ֽڶ<D6BD><DAB6>
#define PLUG_NAME_LENGTH 32
#define PLUG_NUM 6 //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#define PLUG_TIME_TASK_NUM 5 //ÿ<><C3BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>5<EFBFBD>鶨ʱ<E9B6A8><CAB1><EFBFBD><EFBFBD>
#define Led MICO_GPIO_5
#define Button MICO_GPIO_23
#define POWER MICO_GPIO_15
#define Relay_ON 1
#define Relay_OFF 0
#define Relay_0 MICO_GPIO_6
#define Relay_1 MICO_GPIO_8
#define Relay_2 MICO_GPIO_10
#define Relay_3 MICO_GPIO_7
#define Relay_4 MICO_GPIO_9
#define Relay_5 MICO_GPIO_18
#define Relay_NUM PLUG_NUM
typedef struct
{
char hour; //Сʱ
char minute; //<2F><><EFBFBD><EFBFBD>
uint8_t repeat; //bit7:һ<><D2BB> bit6-0:<3A><><EFBFBD><EFBFBD>-<2D><>һ
char action; //<2F><><EFBFBD><EFBFBD>
char on; //<2F><><EFBFBD><EFBFBD>
} user_plug_task_config_t;
typedef struct
{
char name[PLUG_NAME_LENGTH];
char on; //<2F><>¼<EFBFBD><C2BC>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD>
user_plug_task_config_t task[PLUG_TIME_TASK_NUM];
} user_plug_config_t;
//<2F>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E1B9B9>
typedef struct
{
char mqtt_ip[SETTING_MQTT_STRING_LENGTH_MAX]; //mqtt service ip
int mqtt_port; //mqtt service port
char mqtt_user[SETTING_MQTT_STRING_LENGTH_MAX]; //mqtt service user
char mqtt_password[SETTING_MQTT_STRING_LENGTH_MAX]; //mqtt service user
// char mqtt_device_id[SETTING_MQTT_STRING_LENGTH_MAX]; //mqtt service user device name
char version;
user_plug_config_t plug[PLUG_NUM];
char user[maxNameLen];
} user_config_t;
extern char rtc_init;
extern uint32_t total_time;
extern char strMac[16];
extern uint32_t power;
extern system_config_t * sys_config;
extern user_config_t * user_config;
extern mico_gpio_t Relay[Relay_NUM];
#endif

80
TC1/mico_config.h Normal file
View File

@@ -0,0 +1,80 @@
/**
******************************************************************************
* @file mico_config.h
* @author
* @version V1.0.0
* @date
* @brief This file provide constant definition and type declaration for MICO
* running.
******************************************************************************
*
* The MIT License
* Copyright (c) 2016 MXCHIP Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
* IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
******************************************************************************
*/
#pragma once
#define APP_INFO "MiCO BASIC Demo"
#define FIRMWARE_REVISION "ZYC_BASIC_1_0"
#define MANUFACTURER "ZYC Inc."
#define SERIAL_NUMBER "20190105"
#define PROTOCOL "com.zyc.basic"
/************************************************************************
* Application thread stack size */
#define MICO_DEFAULT_APPLICATION_STACK_SIZE (2000)
/************************************************************************
* Enable wlan connection, start easylink configuration if no wlan settings are existed */
//#define MICO_WLAN_CONNECTION_ENABLE
#define MICO_WLAN_CONFIG_MODE CONFIG_MODE_AWS
#define EasyLink_TimeOut 60000 /**< EasyLink timeout 60 seconds. */
#define EasyLink_ConnectWlan_Timeout 20000 /**< Connect to wlan after configured by easylink.
Restart easylink after timeout: 20 seconds. */
/************************************************************************
* Device enter MFG mode if MICO settings are erased. */
//#define MFG_MODE_AUTO
/************************************************************************
* Command line interface */
#define MICO_CLI_ENABLE
/************************************************************************
* Start a system monitor daemon, application can register some monitor
* points, If one of these points is not executed in a predefined period,
* a watchdog reset will occur. */
#define MICO_SYSTEM_MONITOR_ENABLE
/************************************************************************
* Add service _easylink._tcp._local. for discovery */
#define MICO_SYSTEM_DISCOVERY_ENABLE
/************************************************************************
* MiCO TCP server used for configuration and ota. */
#define MICO_CONFIG_SERVER_ENABLE
#define MICO_CONFIG_SERVER_PORT 8000

487
TC1/ota_server/ota_server.c Normal file
View File

@@ -0,0 +1,487 @@
/**
******************************************************************************
* @file ota_server.c
* @author QQ ding
* @version V1.0.0
* @date 19-Oct-2016
* @brief Create a OTA server thread, download update bin file. Reboot system
* if download success.
******************************************************************************
*
* The MIT License
* Copyright (c) 2016 MXCHIP Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
* IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
******************************************************************************
*/
#include "mico.h"
#include "HTTPUtils.h"
#include "SocketUtils.h"
#include "ota_server.h"
#include "url.h"
#if OTA_DEBUG
#define ota_server_log(M, ...) custom_log("OTA", M, ##__VA_ARGS__)
#else
#define ota_server_log(M, ...)
#endif
static ota_server_context_t *ota_server_context = NULL;
static HTTPHeader_t *httpHeader = NULL;
static CRC16_Context crc_context;
static md5_context md5;
static uint32_t offset = 0;
static OSStatus onReceivedData( struct _HTTPHeader_t * httpHeader,
uint32_t pos,
uint8_t *data,
size_t len,
void * userContext );
static void hex2str(uint8_t *hex, int hex_len, char *str)
{
int i = 0;
for(i=0; i<hex_len; i++){
sprintf(str+i*2, "%02x", hex[i]);
}
}
static void upper2lower(char *str, int len)
{
int i = 0;
for(i=0; i<len; i++)
{
if( (*(str+i) >= 'A') && (*(str+i) <= 'Z') ){
*(str+i) += 32;
}
}
}
static int ota_server_send( uint8_t *data, int datalen )
{
int res = 0;
if( ota_server_context->download_url.HTTP_SECURITY == HTTP_SECURITY_HTTP ){
res = send( ota_server_context->download_url.ota_fd, data, datalen, 0 );
}
#if OTA_USE_HTTPS
if( ota_server_context->download_url.HTTP_SECURITY == HTTP_SECURITY_HTTPS ){
res = ssl_send( ota_server_context->download_url.ota_ssl, data, datalen);
}
#endif
return res;
}
static OSStatus ota_server_connect( struct sockaddr_in *addr, socklen_t addrlen )
{
OSStatus err = kNoErr;
#if OTA_USE_HTTPS
int ssl_errno = 0;
#endif
err = connect( ota_server_context->download_url.ota_fd, (struct sockaddr *)addr, addrlen );
require_noerr_string( err, exit, "ERROR: connect ota server failed" );
#if OTA_USE_HTTPS
if( ota_server_context->download_url.HTTP_SECURITY == HTTP_SECURITY_HTTPS ){
ota_server_context->download_url.ota_ssl = ssl_connect( ota_server_context->download_url.ota_fd, 0, NULL, &ssl_errno );
require_action_string( ota_server_context->download_url.ota_ssl != NULL, exit, err = kConnectionErr,"ERROR: ssl disconnect" );
}
#endif
exit:
return err;
}
static int ota_server_read_header( HTTPHeader_t *httpHeader )
{
int res = 0;
if( ota_server_context->download_url.HTTP_SECURITY == HTTP_SECURITY_HTTP ){
res = SocketReadHTTPHeader( ota_server_context->download_url.ota_fd, httpHeader );
}
if( ota_server_context->download_url.HTTP_SECURITY == HTTP_SECURITY_HTTPS ){
#if OTA_USE_HTTPS
res = SocketReadHTTPSHeader( ota_server_context->download_url.ota_ssl, httpHeader );
#endif
}
return res;
}
static int ota_server_read_body( HTTPHeader_t *httpHeader )
{
int res = 0;
if( ota_server_context->download_url.HTTP_SECURITY == HTTP_SECURITY_HTTP ){
res = SocketReadHTTPBody( ota_server_context->download_url.ota_fd, httpHeader );
}
if( ota_server_context->download_url.HTTP_SECURITY == HTTP_SECURITY_HTTPS ){
#if OTA_USE_HTTPS
res = SocketReadHTTPSBody( ota_server_context->download_url.ota_ssl, httpHeader );
#endif
}
return res;
}
static int ota_server_send_header( void )
{
char *header = NULL;
int j = 0;
int ret = 0;
header = malloc( OTA_SEND_HEAD_SIZE );
memset( header, 0x00, OTA_SEND_HEAD_SIZE );
j = sprintf( header, "GET " );
j += sprintf( header + j, "/%s HTTP/1.1\r\n", ota_server_context->download_url.url );
if ( ota_server_context->download_url.port == 0 )
{
j += sprintf( header + j, "Host: %s\r\n", ota_server_context->download_url.host );
} else
{
j += sprintf( header + j, "Host: %s:%d\r\n", ota_server_context->download_url.host, ota_server_context->download_url.port );
}
j += sprintf( header + j, "Connection: close\r\n" ); //Keep-Alive close
//Range: bytes=start-end
if ( ota_server_context->download_state.download_begin_pos > 0 )
{
if ( ota_server_context->download_state.download_end_pos > 0 )
{
j += sprintf( header + j, "Range: bytes=%d-%d\r\n", ota_server_context->download_state.download_begin_pos,
ota_server_context->download_state.download_end_pos );
} else
{
j += sprintf( header + j, "Range: bytes=%d-\r\n", ota_server_context->download_state.download_begin_pos );
}
}
j += sprintf( header + j, "\r\n" );
ret = ota_server_send( (uint8_t *) header, strlen( header ) );
// ota_server_log("send: %d\r\n%s", strlen(header), header);
if ( header != NULL ) free( header );
return ret;
}
static void ota_server_socket_close( void )
{
#if OTA_USE_HTTPS
if ( ota_server_context->download_url.ota_ssl ) ssl_close( ota_server_context->download_url.ota_ssl );
#endif
SocketClose( &(ota_server_context->download_url.ota_fd) );
ota_server_context->download_url.ota_fd = -1;
}
static int ota_server_connect_server( struct in_addr in_addr )
{
int err = 0;
struct sockaddr_in server_address;
if ( ota_server_context->download_url.port == 0 )
{
if ( ota_server_context->download_url.HTTP_SECURITY == HTTP_SECURITY_HTTP )
{
server_address.sin_port = htons(80);
} else
{
server_address.sin_port = htons(443);
}
} else
{
server_address.sin_port = htons(ota_server_context->download_url.port);
}
server_address.sin_family = AF_INET;
server_address.sin_addr = in_addr;
err = ota_server_connect( &server_address, sizeof(server_address) );
if ( err != 0 )
{
mico_thread_sleep( 1 );
return -1;
}
ota_server_log("ota server connected!");
return 0;
}
static void ota_server_progress_set( OTA_STATE_E state )
{
float progress = 0.00;
progress =(float) ota_server_context->download_state.download_begin_pos / ota_server_context->download_state.download_len;
progress = progress*100;
if( ota_server_context->ota_server_cb != NULL )
ota_server_context->ota_server_cb(state, progress);
}
static void ota_server_thread( mico_thread_arg_t arg )
{
OSStatus err;
uint16_t crc16 = 0;
char md5_value[16] = {0};
char md5_value_string[33] = {0};
fd_set readfds;
struct hostent* hostent_content = NULL;
char **pptr = NULL;
struct in_addr in_addr;
mico_logic_partition_t* ota_partition = MicoFlashGetInfo( MICO_PARTITION_OTA_TEMP );
ota_server_context->ota_control = OTA_CONTROL_START;
hostent_content = gethostbyname( ota_server_context->download_url.host );
require_action_quiet( hostent_content != NULL, DELETE, ota_server_progress_set(OTA_FAIL));
pptr=hostent_content->h_addr_list;
in_addr.s_addr = *(uint32_t *)(*pptr);
strcpy( ota_server_context->download_url.ip, inet_ntoa(in_addr));
ota_server_log("OTA server address: %s, host ip: %s", ota_server_context->download_url.host, ota_server_context->download_url.ip);
offset = 0;
MicoFlashErase( MICO_PARTITION_OTA_TEMP, 0x0, ota_partition->partition_length );
CRC16_Init( &crc_context );
if( ota_server_context->ota_check.is_md5 == true ){
InitMd5( &md5 );
}
httpHeader = HTTPHeaderCreateWithCallback( 1024, onReceivedData, NULL, NULL );
require_action( httpHeader, DELETE, ota_server_progress_set(OTA_FAIL) );
while ( 1 )
{
if ( ota_server_context->ota_control == OTA_CONTROL_PAUSE ){
mico_thread_sleep( 1 );
continue;
}else if( ota_server_context->ota_control == OTA_CONTROL_STOP ){
goto DELETE;
}
ota_server_context->download_url.ota_fd = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
err = ota_server_connect_server( in_addr );
require_noerr_action( err, RECONNECTED, ota_server_progress_set(OTA_FAIL));
/* Send HTTP Request */
ota_server_send_header( );
FD_ZERO( &readfds );
FD_SET( ota_server_context->download_url.ota_fd, &readfds );
select( ota_server_context->download_url.ota_fd + 1, &readfds, NULL, NULL, NULL );
if ( FD_ISSET( ota_server_context->download_url.ota_fd, &readfds ) )
{
/*parse header*/
err = ota_server_read_header( httpHeader );
if ( ota_server_context->ota_control == OTA_CONTROL_START )
{
ota_server_context->download_state.download_len = httpHeader->contentLength;
ota_server_context->ota_control = OTA_CONTROL_CONTINUE;
}
switch ( err )
{
case kNoErr:
#if OTA_DEBUG
PrintHTTPHeader( httpHeader );
#endif
err = ota_server_read_body( httpHeader );/*get body data*/
require_noerr( err, RECONNECTED );
/*get data and print*/
break;
case EWOULDBLOCK:
case kNoSpaceErr:
case kConnectionErr:
default:
ota_server_log("ERROR: HTTP Header parse error: %d", err);
break;
}
}
if ( ota_server_context->download_state.download_len == ota_server_context->download_state.download_begin_pos )
{
if( httpHeader->statusCode != 200 ){
ota_server_progress_set(OTA_FAIL);
goto DELETE;
}
CRC16_Final( &crc_context, &crc16 );
if( ota_server_context->ota_check.is_md5 == true ){
Md5Final( &md5, (unsigned char *) md5_value );
hex2str((uint8_t *)md5_value, 16, md5_value_string);
}
if ( memcmp( md5_value_string, ota_server_context->ota_check.md5, OTA_MD5_LENTH ) == 0 ){
ota_server_progress_set(OTA_SUCCE);
mico_ota_switch_to_new_fw( ota_server_context->download_state.download_len, crc16 );
mico_system_power_perform( mico_system_context_get( ), eState_Software_Reset );
}else{
ota_server_log("OTA md5 check err, Calculation:%s, Get:%s", md5_value_string, ota_server_context->ota_check.md5);
ota_server_progress_set(OTA_FAIL);
}
goto DELETE;
}
RECONNECTED:
ota_server_socket_close( );
mico_thread_sleep(2);
continue;
}
DELETE:
HTTPHeaderDestory( &httpHeader );
ota_server_socket_close( );
if( ota_server_context != NULL ){
if( ota_server_context->download_url.url != NULL ){
free(ota_server_context->download_url.url);
ota_server_context->download_url.url = NULL;
}
free(ota_server_context);
ota_server_context = NULL;
}
ota_server_log("ota server thread will delete");
mico_rtos_delete_thread(NULL);
}
/*one request may receive multi reply*/
static OSStatus onReceivedData( struct _HTTPHeader_t * inHeader, uint32_t inPos, uint8_t * inData,
size_t inLen, void * inUserContext )
{
OSStatus err = kNoErr;
if ( inLen == 0 )
return err;
ota_server_context->download_state.download_begin_pos += inLen;
CRC16_Update( &crc_context, inData, inLen );
if( ota_server_context->ota_check.is_md5 == true ){
Md5Update( &md5, inData, inLen );
}
MicoFlashWrite( MICO_PARTITION_OTA_TEMP, &offset, (uint8_t *) inData, inLen );
ota_server_progress_set(OTA_LOADING);
if( ota_server_context->ota_control == OTA_CONTROL_PAUSE ){
while( 1 ){
if( ota_server_context->ota_control != OTA_CONTROL_PAUSE )
break;
mico_thread_msleep(100);
}
}
if( ota_server_context->ota_control == OTA_CONTROL_STOP ){
err = kUnsupportedErr;
}
return err;
}
static OSStatus ota_server_set_url( char *url )
{
OSStatus err = kNoErr;
url_field_t *url_t;
char *pos = NULL;
url_t = url_parse( url );
require_action(url, exit, err = kParamErr);
#if OTA_DEBUG
url_field_print( url_t );
#endif
if ( !strcmp( url_t->schema, "https" ) )
{
ota_server_context->download_url.HTTP_SECURITY = HTTP_SECURITY_HTTPS;
} else
{
ota_server_context->download_url.HTTP_SECURITY = HTTP_SECURITY_HTTP;
}
strcpy( ota_server_context->download_url.host, url_t->host );
ota_server_context->download_url.port = atoi( url_t->port );
pos = strstr( url, url_t->path );
if ( pos == NULL )
{
strcpy( ota_server_context->download_url.url, "" );
} else
{
strcpy( ota_server_context->download_url.url, pos );
}
exit:
url_free( url_t );
return err;
}
OSStatus ota_server_start( char *url, char *md5, ota_server_cb_fn call_back )
{
OSStatus err = kNoErr;
require_action(url, exit, err = kParamErr);
if( ota_server_context != NULL ){
if( ota_server_context->download_url.url != NULL ){
free(ota_server_context->download_url.url);
ota_server_context->download_url.url = NULL;
}
free(ota_server_context);
ota_server_context = NULL;
}
ota_server_context = malloc(sizeof(ota_server_context_t));
require_action(ota_server_context, exit, err = kNoMemoryErr);
memset(ota_server_context, 0x00, sizeof(ota_server_context_t));
ota_server_context->download_url.url = malloc(strlen(url));
require_action(ota_server_context->download_url.url, exit, err = kNoMemoryErr);
memset(ota_server_context->download_url.url, 0x00, strlen(url));
err = ota_server_set_url(url);
require_noerr(err, exit);
if( md5 != NULL ){
ota_server_context->ota_check.is_md5 = true;
memcpy(ota_server_context->ota_check.md5, md5, OTA_MD5_LENTH);
upper2lower(ota_server_context->ota_check.md5, OTA_MD5_LENTH);
}
ota_server_context->ota_server_cb = call_back;
err = mico_rtos_create_thread( NULL, MICO_APPLICATION_PRIORITY, "OTA", ota_server_thread, OTA_SERVER_THREAD_STACK_SIZE, 0 );
exit:
return err;
}
void ota_server_pause( void )
{
ota_server_context->ota_control = OTA_CONTROL_PAUSE;
}
void ota_server_continue( void )
{
ota_server_context->ota_control = OTA_CONTROL_CONTINUE;
}
void ota_server_stop( void )
{
ota_server_context->ota_control = OTA_CONTROL_STOP;
}
OTA_CONTROL_E ota_server_get( void )
{
return ota_server_context->ota_control;
}

142
TC1/ota_server/ota_server.h Normal file
View File

@@ -0,0 +1,142 @@
/**
******************************************************************************
* @file ota_sever.h
* @author QQ ding
* @version V1.0.0
* @date 19-Oct-2016
* @brief Provide ota server header files.
******************************************************************************
*
* The MIT License
* Copyright (c) 2014 MXCHIP Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
* IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
******************************************************************************
*/
#ifndef __ota_server_H
#define __ota_server_H
#define OTA_DEBUG (1)
#define OTA_USE_HTTPS (0)
#define OTA_MD5_LENTH 32
#define OTA_SEND_HEAD_SIZE 256
#if OTA_USE_HTTPS
#define OTA_SERVER_THREAD_STACK_SIZE 0x2000
#else
#define OTA_SERVER_THREAD_STACK_SIZE 0x800
#endif
typedef enum _OTA_STATE_E{
OTA_LOADING,
OTA_SUCCE,
OTA_FAIL
}OTA_STATE_E;
typedef enum _HTTP_SECURITY_E{
HTTP_SECURITY_HTTP,
HTTP_SECURITY_HTTPS
} HTTP_SECURITY_E;
typedef enum _OTA_CONTROL_E{
OTA_CONTROL_IDLE,
OTA_CONTROL_START,
OTA_CONTROL_PAUSE,
OTA_CONTROL_CONTINUE,
OTA_CONTROL_STOP,
} OTA_CONTROL_E;
typedef struct _download_url_t{
char *url;
HTTP_SECURITY_E HTTP_SECURITY;
char host[30];
char ip[16];
int port;
int ota_fd;
#if OTA_USE_HTTPS
mico_ssl_t ota_ssl;
#endif
} download_url_t;
typedef struct _download_state_t{
int download_len;
int download_begin_pos;
int download_end_pos;
} download_state_t;
typedef struct _ota_check_t{
bool is_md5;
char md5[OTA_MD5_LENTH + 1];
} ota_check_t;
typedef void (*ota_server_cb_fn) (OTA_STATE_E state, float progress);
typedef struct _ota_server_context_t{
download_url_t download_url;
download_state_t download_state;
ota_check_t ota_check;
OTA_CONTROL_E ota_control;
ota_server_cb_fn ota_server_cb;
} ota_server_context_t;
/** @addtogroup OTA_SERVER_DAEMONS_APIs
* @{
*/
/** @brief Start OTA server, Support resume from break point, MD5 check
*
* @param url : Download address, URL breakdown from RFC 3986
* @param md5 : MD5 checksum result, must sting type, can be NULL
* @param call_back : call back function, can be NULL
*
* @return kNoErr : on success.
* @return kGeneralErr : if an error occurred
*/
OSStatus ota_server_start( char *url, char *md5, ota_server_cb_fn call_back );
/** @brief Get OTA server state
*
* @return OTA_CONTROL_E : state
*/
OTA_CONTROL_E ota_server_state_get( void );
/** @brief Pause OTA server daemons
*
* @return No
*/
void ota_server_pause( void );
/** @brief Continue OTA server daemons
*
* @return No
*/
void ota_server_continue( void );
/** @brief Stop OTA server daemons
*
* @return No
*/
void ota_server_stop( void );
#endif

358
TC1/user_function.c Normal file
View File

@@ -0,0 +1,358 @@
#define os_log(format, ...) custom_log("FUNCTION", format, ##__VA_ARGS__)
#include "TimeUtils.h"
#include "main.h"
#include "user_gpio.h"
#include "cJSON/cJSON.h"
#include "user_ota.h"
#include "user_mqtt_client.h"
#include "user_udp.h"
uint32_t last_time = 0;
void user_function_set_last_time( )
{
last_time = UpTicks( );
}
bool json_plug_analysis( int udp_flag, unsigned char x, cJSON * pJsonRoot, cJSON * pJsonSend );
bool json_plug_task_analysis( unsigned char x, unsigned char y, cJSON * pJsonRoot, cJSON * pJsonSend );
void user_send( int udp_flag, char *s )
{
if ( udp_flag || !user_mqtt_isconnect( ) )
user_udp_send( s ); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
else
user_mqtt_send( s );
}
void user_function_cmd_received( int udp_flag, uint8_t *pusrdata )
{
unsigned char i;
bool update_user_config_flag = false; //<2F><>־λ,<2C><>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD>´<EFBFBD><C2B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
bool return_flag = true; //Ϊtrueʱ<65><CAB1><EFBFBD><EFBFBD>json<6F><6E><EFBFBD><EFBFBD>,<2C><><EFBFBD>򲻷<EFBFBD><F2B2BBB7><EFBFBD>
cJSON * pJsonRoot = cJSON_Parse( pusrdata );
if ( !pJsonRoot )
{
os_log( "this is not a json data:\r\n%s\r\n", pusrdata );
return;
}
//<2F><><EFBFBD><EFBFBD>UDP<44><50><EFBFBD><EFBFBD>device report(MQTTͬ<54><CDAC><EFBFBD>ظ<EFBFBD><D8B8><EFBFBD><EFBFBD><EFBFBD>)
cJSON *p_cmd = cJSON_GetObjectItem( pJsonRoot, "cmd" );
if ( p_cmd && cJSON_IsString( p_cmd ) && strcmp( p_cmd->valuestring, "device report" ) == 0 )
{
cJSON *pRoot = cJSON_CreateObject( );
cJSON_AddStringToObject( pRoot, "name", sys_config->micoSystemConfig.name );
cJSON_AddStringToObject( pRoot, "mac", strMac );
cJSON_AddNumberToObject( pRoot, "type", TYPE );
cJSON_AddStringToObject( pRoot, "type_name", TYPE_NAME );
IPStatusTypedef para;
micoWlanGetIPStatus( &para, Station );
cJSON_AddStringToObject( pRoot, "ip", para.ip );
char *s = cJSON_Print( pRoot );
// os_log( "pRoot: %s\r\n", s );
user_send( udp_flag, s ); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
free( (void *) s );
cJSON_Delete( pRoot );
// cJSON_Delete(p_cmd);
}
//<2F><><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EEB2BF>
cJSON *p_name = cJSON_GetObjectItem( pJsonRoot, "name" );
cJSON *p_mac = cJSON_GetObjectItem( pJsonRoot, "mac" );
//<2F><>ʼ<EFBFBD><CABC>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if ( (p_name && cJSON_IsString( p_name ) && strcmp( p_name->valuestring, sys_config->micoSystemConfig.name ) == 0) //name
|| (p_mac && cJSON_IsString( p_mac ) && strcmp( p_mac->valuestring, strMac ) == 0) //mac
)
{
cJSON *json_send = cJSON_CreateObject( );
cJSON_AddStringToObject( json_send, "mac", strMac );
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// cJSON *p_cmd = cJSON_GetObjectItem( pJsonRoot, "name" );
if(p_cmd && cJSON_IsString( p_cmd ) && strcmp( p_cmd->valuestring, "restart" ) == 0)
{
os_log("cmd:restart");
mico_system_power_perform( mico_system_context_get( ), eState_Software_Reset );
}
//<2F><><EFBFBD><EFBFBD><EFBFBD>
cJSON *p_version = cJSON_GetObjectItem( pJsonRoot, "version" );
if ( p_version )
{
os_log("version:%s",VERSION);
cJSON_AddStringToObject( json_send, "version", VERSION );
}
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>
cJSON *p_total_time = cJSON_GetObjectItem( pJsonRoot, "total_time" );
if ( p_total_time )
{
cJSON_AddNumberToObject( json_send, "total_time", total_time );
}
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
cJSON *p_power = cJSON_GetObjectItem( pJsonRoot, "power" );
if ( p_power )
{
uint8_t *temp_buf = malloc( 16 );
if ( temp_buf != NULL )
{
sprintf( temp_buf, "%d.%d", power / 10, power % 10 );
cJSON_AddStringToObject( json_send, "power", temp_buf );
free( temp_buf );
}
os_log("power:%d",power);
}
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>setting-----------------------------------------------------------------
cJSON *p_setting = cJSON_GetObjectItem( pJsonRoot, "setting" );
if ( p_setting )
{
//<2F><><EFBFBD><EFBFBD>ota
cJSON *p_ota = cJSON_GetObjectItem( p_setting, "ota" );
if ( p_ota )
{
if ( cJSON_IsString( p_ota ) )
user_ota_start( p_ota->valuestring, NULL );
}
cJSON *json_setting_send = cJSON_CreateObject( );
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E8B1B8><EFBFBD><EFBFBD>/deviceid
cJSON *p_setting_name = cJSON_GetObjectItem( p_setting, "name" );
if ( p_setting_name && cJSON_IsString( p_setting_name ) )
{
update_user_config_flag = true;
sprintf( sys_config->micoSystemConfig.name, p_setting_name->valuestring );
}
//<2F><><EFBFBD><EFBFBD>mqtt ip
cJSON *p_mqtt_ip = cJSON_GetObjectItem( p_setting, "mqtt_uri" );
if ( p_mqtt_ip && cJSON_IsString( p_mqtt_ip ) )
{
update_user_config_flag = true;
sprintf( user_config->mqtt_ip, p_mqtt_ip->valuestring );
}
//<2F><><EFBFBD><EFBFBD>mqtt port
cJSON *p_mqtt_port = cJSON_GetObjectItem( p_setting, "mqtt_port" );
if ( p_mqtt_port && cJSON_IsNumber( p_mqtt_port ) )
{
update_user_config_flag = true;
user_config->mqtt_port = p_mqtt_port->valueint;
}
//<2F><><EFBFBD><EFBFBD>mqtt user
cJSON *p_mqtt_user = cJSON_GetObjectItem( p_setting, "mqtt_user" );
if ( p_mqtt_user && cJSON_IsString( p_mqtt_user ) )
{
update_user_config_flag = true;
sprintf( user_config->mqtt_user, p_mqtt_user->valuestring );
}
//<2F><><EFBFBD><EFBFBD>mqtt password
cJSON *p_mqtt_password = cJSON_GetObjectItem( p_setting, "mqtt_password" );
if ( p_mqtt_password && cJSON_IsString( p_mqtt_password ) )
{
update_user_config_flag = true;
sprintf( user_config->mqtt_password, p_mqtt_password->valuestring );
}
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//<2F><><EFBFBD><EFBFBD><EFBFBD>豸ota
if ( p_ota ) cJSON_AddStringToObject( json_setting_send, "ota", p_ota->valuestring );
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E8B1B8><EFBFBD><EFBFBD>/deviceid
if ( p_setting_name ) cJSON_AddStringToObject( json_setting_send, "name", sys_config->micoSystemConfig.name );
//<2F><><EFBFBD><EFBFBD>mqtt ip
if ( p_mqtt_ip ) cJSON_AddStringToObject( json_setting_send, "mqtt_uri", user_config->mqtt_ip );
//<2F><><EFBFBD><EFBFBD>mqtt port
if ( p_mqtt_port ) cJSON_AddNumberToObject( json_setting_send, "mqtt_port", user_config->mqtt_port );
//<2F><><EFBFBD><EFBFBD>mqtt user
if ( p_mqtt_user ) cJSON_AddStringToObject( json_setting_send, "mqtt_user", user_config->mqtt_user );
//<2F><><EFBFBD><EFBFBD>mqtt password
if ( p_mqtt_password ) cJSON_AddStringToObject( json_setting_send, "mqtt_password", user_config->mqtt_password );
cJSON_AddItemToObject( json_send, "setting", json_setting_send );
}
//<2F><><EFBFBD><EFBFBD>plug-----------------------------------------------------------------
for ( i = 0; i < PLUG_NUM; i++ )
{
if ( json_plug_analysis( udp_flag, i, pJsonRoot, json_send ) )
update_user_config_flag = true;
}
cJSON_AddStringToObject( json_send, "name", sys_config->micoSystemConfig.name );
if ( return_flag == true )
{
char *json_str = cJSON_Print( json_send );
// os_log( "pRoot: %s\r\n", json_str );
user_send( udp_flag, json_str ); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
free( (void *) json_str );
}
cJSON_Delete( json_send );
}
if ( update_user_config_flag )
{
mico_system_context_update( sys_config );
update_user_config_flag = false;
}
cJSON_Delete( pJsonRoot );
}
/*
*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>json
*udp_flag:<3A><><EFBFBD><EFBFBD>udp/mqtt<74><74>־λ,<2C>˴<EFBFBD><CBB4>޸IJ<DEB8><C4B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬ʱ,<2C><>Ҫʵʱ<CAB5><CAB1><EFBFBD>¸<EFBFBD>domoticz
*x:<3A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
bool json_plug_analysis( int udp_flag, unsigned char x, cJSON * pJsonRoot, cJSON * pJsonSend )
{
if ( !pJsonRoot ) return false;
if ( !pJsonSend ) return false;
char i;
bool return_flag = false;
char plug_str[] = "plug_X";
plug_str[5] = x + '0';
cJSON *p_plug = cJSON_GetObjectItem( pJsonRoot, plug_str );
if ( !p_plug ) return_flag = false;
cJSON *json_plug_send = cJSON_CreateObject( );
//<2F><><EFBFBD><EFBFBD>plug on------------------------------------------------------
if ( p_plug )
{
cJSON *p_plug_on = cJSON_GetObjectItem( p_plug, "on" );
if ( p_plug_on )
{
if ( cJSON_IsNumber( p_plug_on ) )
{
user_relay_set( x, p_plug_on->valueint );
return_flag = true;
}
user_mqtt_send_plug_state( x );
}
//<2F><><EFBFBD><EFBFBD>plug<75><67>setting<6E><67>Ŀ----------------------------------------------
cJSON *p_plug_setting = cJSON_GetObjectItem( p_plug, "setting" );
if ( p_plug_setting )
{
cJSON *json_plug_setting_send = cJSON_CreateObject( );
//<2F><><EFBFBD><EFBFBD>plug<75><67>setting<6E><67>name----------------------------------------
cJSON *p_plug_setting_name = cJSON_GetObjectItem( p_plug_setting, "name" );
if ( p_plug_setting_name )
{
if ( cJSON_IsString( p_plug_setting_name ) )
{
return_flag = true;
sprintf( user_config->plug[x].name, p_plug_setting_name->valuestring );
user_mqtt_hass_auto_name( x );
}
cJSON_AddStringToObject( json_plug_setting_send, "name", user_config->plug[x].name );
}
//<2F><><EFBFBD><EFBFBD>plug<75><67>setting<6E><67>task----------------------------------------
for ( i = 0; i < PLUG_TIME_TASK_NUM; i++ )
{
if ( json_plug_task_analysis( x, i, p_plug_setting, json_plug_setting_send ) )
return_flag = true;
}
cJSON_AddItemToObject( json_plug_send, "setting", json_plug_setting_send );
}
}
// cJSON *p_nvalue = cJSON_GetObjectItem( pJsonRoot, "nvalue" );
// if ( p_plug || p_nvalue )
cJSON_AddNumberToObject( json_plug_send, "on", user_config->plug[x].on );
cJSON_AddItemToObject( pJsonSend, plug_str, json_plug_send );
return return_flag;
}
/*
*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>json
*x:<3A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> y:<3A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
bool json_plug_task_analysis( unsigned char x, unsigned char y, cJSON * pJsonRoot, cJSON * pJsonSend )
{
if ( !pJsonRoot ) return false;
bool return_flag = false;
char plug_task_str[] = "task_X";
plug_task_str[5] = y + '0';
cJSON *p_plug_task = cJSON_GetObjectItem( pJsonRoot, plug_task_str );
if ( !p_plug_task ) return false;
cJSON *json_plug_task_send = cJSON_CreateObject( );
cJSON *p_plug_task_hour = cJSON_GetObjectItem( p_plug_task, "hour" );
cJSON *p_plug_task_minute = cJSON_GetObjectItem( p_plug_task, "minute" );
cJSON *p_plug_task_repeat = cJSON_GetObjectItem( p_plug_task, "repeat" );
cJSON *p_plug_task_action = cJSON_GetObjectItem( p_plug_task, "action" );
cJSON *p_plug_task_on = cJSON_GetObjectItem( p_plug_task, "on" );
if ( p_plug_task_hour && p_plug_task_minute && p_plug_task_repeat &&
p_plug_task_action
&& p_plug_task_on )
{
if ( cJSON_IsNumber( p_plug_task_hour )
&& cJSON_IsNumber( p_plug_task_minute )
&& cJSON_IsNumber( p_plug_task_repeat )
&& cJSON_IsNumber( p_plug_task_action )
&& cJSON_IsNumber( p_plug_task_on )
)
{
return_flag = true;
user_config->plug[x].task[y].hour = p_plug_task_hour->valueint;
user_config->plug[x].task[y].minute = p_plug_task_minute->valueint;
user_config->plug[x].task[y].repeat = p_plug_task_repeat->valueint;
user_config->plug[x].task[y].action = p_plug_task_action->valueint;
user_config->plug[x].task[y].on = p_plug_task_on->valueint;
}
}
cJSON_AddNumberToObject( json_plug_task_send, "hour", user_config->plug[x].task[y].hour );
cJSON_AddNumberToObject( json_plug_task_send, "minute", user_config->plug[x].task[y].minute );
cJSON_AddNumberToObject( json_plug_task_send, "repeat", user_config->plug[x].task[y].repeat );
cJSON_AddNumberToObject( json_plug_task_send, "action", user_config->plug[x].task[y].action );
cJSON_AddNumberToObject( json_plug_task_send, "on", user_config->plug[x].task[y].on );
cJSON_AddItemToObject( pJsonSend, plug_task_str, json_plug_task_send );
return return_flag;
}
unsigned char strtohex( char a, char b )
{
if ( a >= 0x30 && a <= 0x39 )
a -= 0x30;
else if ( a >= 0x41 && a <= 0x46 )
{
a = a + 10 - 0x41;
} else if ( a >= 0x61 && a <= 0x66 )
{
a = a + 10 - 0x61;
}
if ( b >= 0x30 && b <= 0x39 )
b -= 0x30;
else if ( b >= 0x41 && b <= 0x46 )
{
b = b + 10 - 0x41;
} else if ( b >= 0x61 && b <= 0x66 )
{
b = b + 10 - 0x61;
}
return a * 16 + b;
}

14
TC1/user_function.h Normal file
View File

@@ -0,0 +1,14 @@
#ifndef __USER_FUNCTION_H_
#define __USER_FUNCTION_H_
#include "mico.h"
#include "MiCOKit_EXT.h"
void user_send( int udp_flag, char *s );
void user_function_cmd_received(int udp_flag,uint8_t *pusrdata);
unsigned char strtohex(char a, char b);
#endif

183
TC1/user_gpio.c Normal file
View File

@@ -0,0 +1,183 @@
#define os_log(format, ...) custom_log("KEY", format, ##__VA_ARGS__)
#include "main.h"
#include "user_gpio.h"
#include "user_mqtt_client.h"
#include "user_udp.h"
#include "cJSON/cJSON.h"
mico_gpio_t relay[Relay_NUM] = { Relay_0, Relay_1, Relay_2, Relay_3, Relay_4, Relay_5 };
void user_led_set( char x )
{
if ( x == -1 )
MicoGpioOutputTrigger( Led );
else if ( x )
MicoGpioOutputHigh( Led );
else
MicoGpioOutputLow( Led );
}
bool relay_out( void )
{
unsigned char i;
for ( i = 0; i < PLUG_NUM; i++ )
{
if ( user_config->plug[i].on != 0 )
{
return true;
}
}
return false;
}
/*user_relay_set
* <20><><EFBFBD>ü̵<C3BC><CCB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* x:<3A><><EFBFBD><EFBFBD> 0-5
* y:<3A><><EFBFBD><EFBFBD> 0:<3A><> 1:<3A><>
*/
void user_relay_set(unsigned char x,unsigned char y )
{
if (x >= PLUG_NUM ) return;
if((y == 1) ? Relay_ON : Relay_OFF) MicoGpioOutputHigh( relay[x] );else MicoGpioOutputLow( relay[x] );
user_config->plug[x].on = y;
if ( relay_out( ) )
user_led_set( 1 );
else
user_led_set( 0 );
}
/*
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>м̵<D0BC><CCB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* y:0:ȫ<><C8AB><EFBFBD><EFBFBD> 1:<3A><><EFBFBD>ݼ<EFBFBD>¼״̬<D7B4><CCAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
*/
void user_relay_set_all( char y )
{
char i;
for ( i = 0; i < PLUG_NUM; i++ )
user_relay_set( i, y );
}
static void key_long_press( void )
{
// os_log("key_long_press");
// user_led_set( 1 );
// user_mqtt_send( "mqtt test" );
}
static void key_long_10s_press( void )
{
OSStatus err;
char i = 0;
os_log( "WARNGIN: user params restored!" );
// for ( i = 0; i < 3; i++ )
// {
// user_led_set( 1 );
// mico_rtos_thread_msleep( 100 );
// user_led_set( 0 );
// }
//
appRestoreDefault_callback( user_config, sizeof(user_config_t) );
sys_config->micoSystemConfig.ssid[0] = 0;
mico_system_context_update( mico_system_context_get( ) );
}
static void key_short_press( void )
{
char i;
OSStatus err;
if ( relay_out() )
{
user_relay_set_all( 0 );
}
else
{
user_relay_set_all( 1 );
}
for ( i = 0; i < PLUG_NUM; i++ )
{
user_mqtt_send_plug_state(i);
}
}
mico_timer_t user_key_timer;
uint16_t key_time = 0;
#define BUTTON_LONG_PRESS_TIME 10 //100ms*10=1s
static void key_timeout_handler( void* arg )
{
static uint8_t key_trigger, key_continue;
static uint8_t key_last;
//<2F><><EFBFBD><EFBFBD>ɨ<EFBFBD><C9A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
uint8_t tmp = ~(0xfe | MicoGpioInputGet( Button ));
key_trigger = tmp & (tmp ^ key_continue);
key_continue = tmp;
// os_log("button scan:%02x %02x",key_trigger,key_continue);
if ( key_trigger != 0 ) key_time = 0; //<2F>°<EFBFBD><C2B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ,<2C><><EFBFBD>¿<EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ
if ( key_continue != 0 )
{
//any button pressed
key_time++;
if ( key_time < BUTTON_LONG_PRESS_TIME )
key_last = key_continue;
else
{
os_log("button long pressed:%d",key_time);
if ( key_time == 30 )
{
key_long_press( );
}
else if ( key_time == 100 )
{
key_long_10s_press( );
}
else if ( key_time == 102 )
{
user_led_set( 1 );
}
else if ( key_time == 103 )
{
user_led_set( 0 );
key_time = 101;
}
}
} else
{
//button released
if ( key_time < BUTTON_LONG_PRESS_TIME )
{ //100ms*10=1s <20><><EFBFBD><EFBFBD>1sΪ<73><CEAA><EFBFBD><EFBFBD>
key_time = 0;
os_log("button short pressed:%d",key_time);
key_short_press( );
} else if ( key_time > 100 )
{
MicoSystemReboot( );
}
key_last = 0;
mico_rtos_stop_timer( &user_key_timer );
}
}
static void key_falling_irq_handler( void* arg )
{
mico_rtos_start_timer( &user_key_timer );
}
void key_init( void )
{
MicoGpioInitialize( Button, INPUT_PULL_UP );
mico_rtos_init_timer( &user_key_timer, 100, key_timeout_handler, NULL );
MicoGpioEnableIRQ( Button, IRQ_TRIGGER_FALLING_EDGE, key_falling_irq_handler, NULL );
}

15
TC1/user_gpio.h Normal file
View File

@@ -0,0 +1,15 @@
#ifndef __USER_KEY_H_
#define __USER_KEY_H_
#include "mico.h"
#include "MiCOKit_EXT.h"
extern void user_led_set(char x);
extern void key_init(void);
extern void user_relay_set(unsigned char x,unsigned char y );
extern void user_relay_set_all( char y );
extern bool relay_out( void );
#endif

656
TC1/user_mqtt_client.c Normal file
View File

@@ -0,0 +1,656 @@
/**
******************************************************************************
* @file mqtt_client.c
* @author Eshen Wang
* @version V1.0.0
* @date 16-Nov-2015
* @brief MiCO application demonstrate a MQTT client.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, MXCHIP Inc. SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2014 MXCHIP Inc.</center></h2>
******************************************************************************
*/
#define app_log(M, ...) custom_log("APP", M, ##__VA_ARGS__)
#define mqtt_log(M, ...) custom_log("MQTT", M, ##__VA_ARGS__)
#include "main.h"
#include "mico.h"
#include "MQTTClient.h"
#include "user_function.h"
#include "user_gpio.h"
#include "user_mqtt_client.h"
#include "cJSON/cJSON.h"
//#define MQTT_CLIENT_SSL_ENABLE // ssl
#define MAX_MQTT_TOPIC_SIZE (256)
#define MAX_MQTT_DATA_SIZE (1024)
#define MAX_MQTT_SEND_QUEUE_SIZE (10)
#ifdef MQTT_CLIENT_SSL_ENABLE
#define MQTT_SERVER "test.mosquitto.org"
#define MQTT_SERVER_PORT 8883
char* mqtt_server_ssl_cert_str =
"-----BEGIN CERTIFICATE-----\r\n\
MIIC8DCCAlmgAwIBAgIJAOD63PlXjJi8MA0GCSqGSIb3DQEBBQUAMIGQMQswCQYD\r\n\
VQQGEwJHQjEXMBUGA1UECAwOVW5pdGVkIEtpbmdkb20xDjAMBgNVBAcMBURlcmJ5\r\n\
MRIwEAYDVQQKDAlNb3NxdWl0dG8xCzAJBgNVBAsMAkNBMRYwFAYDVQQDDA1tb3Nx\r\n\
dWl0dG8ub3JnMR8wHQYJKoZIhvcNAQkBFhByb2dlckBhdGNob28ub3JnMB4XDTEy\r\n\
MDYyOTIyMTE1OVoXDTIyMDYyNzIyMTE1OVowgZAxCzAJBgNVBAYTAkdCMRcwFQYD\r\n\
VQQIDA5Vbml0ZWQgS2luZ2RvbTEOMAwGA1UEBwwFRGVyYnkxEjAQBgNVBAoMCU1v\r\n\
c3F1aXR0bzELMAkGA1UECwwCQ0ExFjAUBgNVBAMMDW1vc3F1aXR0by5vcmcxHzAd\r\n\
BgkqhkiG9w0BCQEWEHJvZ2VyQGF0Y2hvby5vcmcwgZ8wDQYJKoZIhvcNAQEBBQAD\r\n\
gY0AMIGJAoGBAMYkLmX7SqOT/jJCZoQ1NWdCrr/pq47m3xxyXcI+FLEmwbE3R9vM\r\n\
rE6sRbP2S89pfrCt7iuITXPKycpUcIU0mtcT1OqxGBV2lb6RaOT2gC5pxyGaFJ+h\r\n\
A+GIbdYKO3JprPxSBoRponZJvDGEZuM3N7p3S/lRoi7G5wG5mvUmaE5RAgMBAAGj\r\n\
UDBOMB0GA1UdDgQWBBTad2QneVztIPQzRRGj6ZHKqJTv5jAfBgNVHSMEGDAWgBTa\r\n\
d2QneVztIPQzRRGj6ZHKqJTv5jAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUA\r\n\
A4GBAAqw1rK4NlRUCUBLhEFUQasjP7xfFqlVbE2cRy0Rs4o3KS0JwzQVBwG85xge\r\n\
REyPOFdGdhBY2P1FNRy0MDr6xr+D2ZOwxs63dG1nnAnWZg7qwoLgpZ4fESPD3PkA\r\n\
1ZgKJc2zbSQ9fCPxt2W3mdVav66c6fsb7els2W2Iz7gERJSX\r\n\
-----END CERTIFICATE-----";
#else // ! MQTT_CLIENT_SSL_ENABLE
#define MQTT_SERVER user_config->mqtt_ip
#define MQTT_SERVER_PORT user_config->mqtt_port
#endif // MQTT_CLIENT_SSL_ENABLE
typedef struct
{
char topic[MAX_MQTT_TOPIC_SIZE];
char qos;
char retained;
uint8_t data[MAX_MQTT_DATA_SIZE];
uint32_t datalen;
} mqtt_recv_msg_t, *p_mqtt_recv_msg_t, mqtt_send_msg_t, *p_mqtt_send_msg_t;
static void mqtt_client_thread( mico_thread_arg_t arg );
static void messageArrived( MessageData* md );
static OSStatus mqtt_msg_publish( Client *c, const char* topic, char qos, char retained, const unsigned char* msg, uint32_t msg_len );
OSStatus user_recv_handler( void *arg );
OSStatus user_mqtt_send_plug_state( char plug_id );
void user_mqtt_hass_auto( char plug_id );
void user_mqtt_hass_auto_power( void );
bool isconnect = false;
mico_queue_t mqtt_msg_send_queue = NULL;
Client c; // mqtt client object
Network n; // socket network for mqtt client
static mico_worker_thread_t mqtt_client_worker_thread; /* Worker thread to manage send/recv events */
static mico_timed_event_t mqtt_client_send_event;
char topic_state[MAX_MQTT_TOPIC_SIZE];
char topic_set[MAX_MQTT_TOPIC_SIZE];
mico_timer_t timer_handle;
static uint8_t timer_status = 0;
void user_mqtt_timer_func( void *arg )
{
uint8_t *buf1 = NULL;
LinkStatusTypeDef LinkStatus;
micoWlanGetLinkStatus( &LinkStatus );
if ( LinkStatus.is_connected != 1 )
{
mico_stop_timer( &timer_handle );
return;
}
if ( mico_rtos_is_queue_empty( &mqtt_msg_send_queue ) == true )
{
timer_status++;
switch ( timer_status )
{
case 1:
user_mqtt_hass_auto_power( );
break;
case 2:
user_mqtt_hass_auto( 0 );
break;
case 3:
user_mqtt_hass_auto( 1 );
break;
case 4:
user_mqtt_hass_auto( 2 );
break;
case 5:
user_mqtt_hass_auto( 3 );
break;
case 6:
user_mqtt_hass_auto( 4 );
break;
case 7:
user_mqtt_hass_auto( 5 );
break;
case 8:
user_mqtt_hass_auto_name( 0 );
break;
case 9:
user_mqtt_hass_auto_name( 1 );
break;
case 10:
user_mqtt_hass_auto_name( 2 );
break;
case 11:
user_mqtt_hass_auto_name( 3 );
break;
case 12:
user_mqtt_hass_auto_name( 4 );
break;
case 13:
user_mqtt_hass_auto_name( 5 );
break;
case 14:
user_mqtt_hass_auto_power_name( );
break;
case 15:
buf1 = malloc( 1024 ); //idx为1位时长度为24
if ( buf1 != NULL )
{
sprintf(
buf1,
"{\"mac\":\"%s\",\"version\":null,\"plug_0\":{\"on\":null,\"setting\":{\"name\":null}},\"plug_1\":{\"on\":null,\"setting\":{\"name\":null}},\"plug_2\":{\"on\":null,\"setting\":{\"name\":null}},\"plug_3\":{\"on\":null,\"setting\":{\"name\":null}},\"plug_4\":{\"on\":null,\"setting\":{\"name\":null}},\"plug_5\":{\"on\":null,\"setting\":{\"name\":null}}}",
strMac );
user_function_cmd_received( 0, buf1 );
free( buf1 );
}
break;
default:
mico_stop_timer( &timer_handle );
// mico_deinit_timer( &timer_handle );
break;
}
}
}
/* Application entrance */
OSStatus user_mqtt_init( void )
{
OSStatus err = kNoErr;
sprintf( topic_set, MQTT_CLIENT_SUB_TOPIC1 );
sprintf( topic_state, MQTT_CLIENT_PUB_TOPIC, strMac );
#ifdef MQTT_CLIENT_SSL_ENABLE
int mqtt_thread_stack_size = 0x3000;
#else
//TODO size:0x800
int mqtt_thread_stack_size = 0x2000;
#endif
uint32_t mqtt_lib_version = MQTTClientLibVersion( );
app_log( "MQTT client version: [%ld.%ld.%ld]",
0xFF & (mqtt_lib_version >> 16), 0xFF & (mqtt_lib_version >> 8), 0xFF & mqtt_lib_version);
/* create mqtt msg send queue */
err = mico_rtos_init_queue( &mqtt_msg_send_queue, "mqtt_msg_send_queue", sizeof(p_mqtt_send_msg_t),
MAX_MQTT_SEND_QUEUE_SIZE );
require_noerr_action( err, exit, app_log("ERROR: create mqtt msg send queue err=%d.", err) );
/* start mqtt client */
err = mico_rtos_create_thread( NULL, MICO_APPLICATION_PRIORITY, "mqtt_client",
(mico_thread_function_t) mqtt_client_thread,
mqtt_thread_stack_size, 0 );
require_noerr_string( err, exit, "ERROR: Unable to start the mqtt client thread." );
/* Create a worker thread for user handling MQTT data event */
err = mico_rtos_create_worker_thread( &mqtt_client_worker_thread, MICO_APPLICATION_PRIORITY, 0x800, 5 );
require_noerr_string( err, exit, "ERROR: Unable to start the mqtt client worker thread." );
exit:
if ( kNoErr != err ) app_log("ERROR, app thread exit err: %d", err);
return err;
}
static OSStatus mqtt_client_release( Client *c, Network *n )
{
OSStatus err = kNoErr;
if ( c->isconnected ) MQTTDisconnect( c );
n->disconnect( n ); // close connection
if ( MQTT_SUCCESS != MQTTClientDeinit( c ) )
{
app_log("MQTTClientDeinit failed!");
err = kDeletedErr;
}
return err;
}
// publish msg to mqtt server
static OSStatus mqtt_msg_publish( Client *c, const char* topic, char qos, char retained,
const unsigned char* msg,
uint32_t msg_len )
{
OSStatus err = kUnknownErr;
int ret = 0;
MQTTMessage publishData = MQTTMessage_publishData_initializer;
require( topic && msg_len && msg, exit );
// upload data qos0
publishData.qos = (enum QoS) qos;
publishData.retained = retained;
publishData.payload = (void*) msg;
publishData.payloadlen = msg_len;
ret = MQTTPublish( c, topic, &publishData );
if ( MQTT_SUCCESS == ret )
{
err = kNoErr;
} else if ( MQTT_SOCKET_ERR == ret )
{
err = kConnectionErr;
} else
{
err = kUnknownErr;
}
exit:
return err;
}
void mqtt_client_thread( mico_thread_arg_t arg )
{
OSStatus err = kUnknownErr;
int i, rc = -1;
fd_set readfds;
struct timeval t = { 0, MQTT_YIELD_TMIE * 1000 };
ssl_opts ssl_settings;
MQTTPacket_connectData connectData = MQTTPacket_connectData_initializer;
p_mqtt_send_msg_t p_send_msg = NULL;
int msg_send_event_fd = -1;
bool no_mqtt_msg_exchange = true;
mqtt_log("MQTT client thread started...");
memset( &c, 0, sizeof(c) );
memset( &n, 0, sizeof(n) );
/* create msg send queue event fd */
msg_send_event_fd = mico_create_event_fd( mqtt_msg_send_queue );
require_action( msg_send_event_fd >= 0, exit, mqtt_log("ERROR: create msg send queue event fd failed!!!") );
MQTT_start:
isconnect = false;
/* 1. create network connection */
#ifdef MQTT_CLIENT_SSL_ENABLE
ssl_settings.ssl_enable = true;
ssl_settings.ssl_debug_enable = false; // ssl debug log
ssl_settings.ssl_version = TLS_V1_2_MODE;
ssl_settings.ca_str_len = strlen(mqtt_server_ssl_cert_str);
ssl_settings.ca_str = mqtt_server_ssl_cert_str;
#else
ssl_settings.ssl_enable = false;
#endif
LinkStatusTypeDef LinkStatus;
while ( 1 )
{
isconnect = false;
mico_rtos_thread_sleep( 3 );
if ( MQTT_SERVER[0] < 0x20 || MQTT_SERVER[0] > 0x7f || MQTT_SERVER_PORT < 1 ) continue; //未配置mqtt服务器时不连接
micoWlanGetLinkStatus( &LinkStatus );
if ( LinkStatus.is_connected != 1 )
{
mqtt_log("ERROR:WIFI not connection , waiting 3s for connecting and then connecting MQTT ", rc);
mico_rtos_thread_sleep( 3 );
continue;
}
rc = NewNetwork( &n, MQTT_SERVER, MQTT_SERVER_PORT, ssl_settings );
if ( rc == MQTT_SUCCESS ) break;
mqtt_log("ERROR: MQTT network connection err=%d, reconnect after 3s...", rc);
}
mqtt_log("MQTT network connection success!");
/* 2. init mqtt client */
//c.heartbeat_retry_max = 2;
rc = MQTTClientInit( &c, &n, MQTT_CMD_TIMEOUT );
require_noerr_string( rc, MQTT_reconnect, "ERROR: MQTT client init err." );
mqtt_log("MQTT client init success!");
/* 3. create mqtt client connection */
connectData.willFlag = 0;
connectData.MQTTVersion = 4; // 3: 3.1, 4: v3.1.1
connectData.clientID.cstring = strMac;
connectData.username.cstring = user_config->mqtt_user;
connectData.password.cstring = user_config->mqtt_password;
connectData.keepAliveInterval = MQTT_CLIENT_KEEPALIVE;
connectData.cleansession = 1;
rc = MQTTConnect( &c, &connectData );
require_noerr_string( rc, MQTT_reconnect, "ERROR: MQTT client connect err." );
mqtt_log("MQTT client connect success!");
/* 4. mqtt client subscribe */
rc = MQTTSubscribe( &c, topic_set, QOS0, messageArrived );
require_noerr_string( rc, MQTT_reconnect, "ERROR: MQTT client subscribe err." );
mqtt_log("MQTT client subscribe success! recv_topic=[%s].", topic_set);
/*4.1 连接成功后先更新发送一次数据*/
isconnect = true;
mico_init_timer( &timer_handle, 150, user_mqtt_timer_func, &arg );
mico_start_timer( &timer_handle );
/* 5. client loop for recv msg && keepalive */
while ( 1 )
{
isconnect = true;
no_mqtt_msg_exchange = true;
FD_ZERO( &readfds );
FD_SET( c.ipstack->my_socket, &readfds );
FD_SET( msg_send_event_fd, &readfds );
select( msg_send_event_fd + 1, &readfds, NULL, NULL, &t );
/* recv msg from server */
if ( FD_ISSET( c.ipstack->my_socket, &readfds ) )
{
rc = MQTTYield( &c, (int) MQTT_YIELD_TMIE );
require_noerr( rc, MQTT_reconnect );
no_mqtt_msg_exchange = false;
}
/* recv msg from user worker thread to be sent to server */
if ( FD_ISSET( msg_send_event_fd, &readfds ) )
{
while ( mico_rtos_is_queue_empty( &mqtt_msg_send_queue ) == false )
{
// get msg from send queue
mico_rtos_pop_from_queue( &mqtt_msg_send_queue, &p_send_msg, 0 );
require_string( p_send_msg, exit, "Wrong data point" );
// send message to server
err = mqtt_msg_publish( &c, p_send_msg->topic, p_send_msg->qos, p_send_msg->retained,
p_send_msg->data,
p_send_msg->datalen );
require_noerr_string( err, MQTT_reconnect, "ERROR: MQTT publish data err" );
mqtt_log("MQTT publish data success! send_topic=[%s], msg=[%ld].\r\n", p_send_msg->topic, p_send_msg->datalen);
no_mqtt_msg_exchange = false;
free( p_send_msg );
p_send_msg = NULL;
}
}
/* if no msg exchange, we need to check ping msg to keep alive. */
if ( no_mqtt_msg_exchange )
{
rc = keepalive( &c );
require_noerr_string( rc, MQTT_reconnect, "ERROR: keepalive err" );
}
}
MQTT_reconnect:
mqtt_log("Disconnect MQTT client, and reconnect after 5s, reason: mqtt_rc = %d, err = %d", rc, err );
timer_status=100;
mqtt_client_release( &c, &n );
isconnect = false;
user_led_set( -1 );
mico_rtos_thread_msleep( 100 );
user_led_set( -1 );
mico_rtos_thread_sleep( 5 );
goto MQTT_start;
exit:
isconnect = false;
mqtt_log("EXIT: MQTT client exit with err = %d.", err);
mqtt_client_release( &c, &n );
mico_rtos_delete_thread( NULL );
}
// callback, msg received from mqtt server
static void messageArrived( MessageData* md )
{
OSStatus err = kUnknownErr;
p_mqtt_recv_msg_t p_recv_msg = NULL;
MQTTMessage* message = md->message;
p_recv_msg = (p_mqtt_recv_msg_t) calloc( 1, sizeof(mqtt_recv_msg_t) );
require_action( p_recv_msg, exit, err = kNoMemoryErr );
p_recv_msg->datalen = message->payloadlen;
p_recv_msg->qos = (char) (message->qos);
p_recv_msg->retained = message->retained;
strncpy( p_recv_msg->topic, md->topicName->lenstring.data, md->topicName->lenstring.len );
memcpy( p_recv_msg->data, message->payload, message->payloadlen );
err = mico_rtos_send_asynchronous_event( &mqtt_client_worker_thread, user_recv_handler, p_recv_msg );
require_noerr( err, exit );
exit:
if ( err != kNoErr )
{
app_log("ERROR: Recv data err = %d", err);
if ( p_recv_msg ) free( p_recv_msg );
}
return;
}
/* Application process MQTT received data */
OSStatus user_recv_handler( void *arg )
{
OSStatus err = kUnknownErr;
p_mqtt_recv_msg_t p_recv_msg = arg;
require( p_recv_msg, exit );
app_log("user get data success! from_topic=[%s], msg=[%ld].\r\n", p_recv_msg->topic, p_recv_msg->datalen);
user_function_cmd_received( 0, p_recv_msg->data );
free( p_recv_msg );
exit:
return err;
}
OSStatus user_mqtt_send_topic( char *topic, char *arg, char retained )
{
OSStatus err = kUnknownErr;
p_mqtt_send_msg_t p_send_msg = NULL;
// app_log("======App prepare to send ![%d]======", MicoGetMemoryInfo()->free_memory);
/* Send queue is full, pop the oldest */
if ( mico_rtos_is_queue_full( &mqtt_msg_send_queue ) == true )
{
mico_rtos_pop_from_queue( &mqtt_msg_send_queue, &p_send_msg, 0 );
free( p_send_msg );
p_send_msg = NULL;
}
/* Push the latest data into send queue*/
p_send_msg = (p_mqtt_send_msg_t) calloc( 1, sizeof(mqtt_send_msg_t) );
require_action( p_send_msg, exit, err = kNoMemoryErr );
p_send_msg->qos = 0;
p_send_msg->retained = retained;
p_send_msg->datalen = strlen( arg );
memcpy( p_send_msg->data, arg, p_send_msg->datalen );
strncpy( p_send_msg->topic, topic, MAX_MQTT_TOPIC_SIZE );
err = mico_rtos_push_to_queue( &mqtt_msg_send_queue, &p_send_msg, 0 );
require_noerr( err, exit );
//app_log("Push user msg into send queue success!");
exit:
if ( err != kNoErr && p_send_msg ) free( p_send_msg );
return err;
}
/* Application collect data and seng them to MQTT send queue */
OSStatus user_mqtt_send( char *arg )
{
return user_mqtt_send_topic( topic_state, arg, 0 );
}
//更新ha开关状态
OSStatus user_mqtt_send_plug_state( char plug_id )
{
uint8_t *send_buf = NULL;
uint8_t *topic_buf = NULL;
send_buf = malloc( 64 ); //
topic_buf = malloc( 64 ); //
if ( send_buf != NULL && topic_buf != NULL )
{
sprintf( topic_buf, "homeassistant/switch/%s/plug_%d/state", strMac, plug_id );
sprintf( send_buf, "{\"mac\":\"%s\",\"plug_%d\":{\"on\":%d}}", strMac, plug_id, user_config->plug[plug_id].on );
user_mqtt_send_topic( topic_buf, send_buf, 1 );
}
if ( send_buf ) free( send_buf );
if ( topic_buf ) free( topic_buf );
}
//hass mqtt自动发现数据开关发送
void user_mqtt_hass_auto( char plug_id )
{
uint8_t i;
uint8_t *send_buf = NULL;
uint8_t *topic_buf = NULL;
send_buf = malloc( 512 ); //
topic_buf = malloc( 128 ); //
if ( send_buf != NULL && topic_buf != NULL )
{
sprintf( topic_buf, "homeassistant/switch/%s/plug_%d/config", strMac, plug_id );
sprintf( send_buf, "{"
"\"name\":\"zTC1_plug%d_%s\","
"\"stat_t\":\"homeassistant/switch/%s/plug_%d/state\","
"\"cmd_t\":\"device/ztc1/set\","
"\"pl_on\":\"{\\\"mac\\\":\\\"%s\\\",\\\"plug_%d\\\":{\\\"on\\\":1}}\","
"\"pl_off\":\"{\\\"mac\\\":\\\"%s\\\",\\\"plug_%d\\\":{\\\"on\\\":0}}\""
"}\0",
plug_id, strMac + 8, strMac, plug_id, strMac, plug_id, strMac, plug_id );
user_mqtt_send_topic( topic_buf, send_buf, 1 );
}
if ( send_buf ) free( send_buf );
if ( topic_buf ) free( topic_buf );
}
void user_mqtt_hass_auto_name( char plug_id )
{
uint8_t *send_buf = NULL;
uint8_t *topic_buf = NULL;
send_buf = (uint8_t *) malloc( 300 );
topic_buf = (uint8_t *) malloc( 64 );
if ( send_buf != NULL && topic_buf != NULL )
{
sprintf( topic_buf, "homeassistant/switch/%s/plug_%d/config", strMac, plug_id );
sprintf( send_buf, "{"
"\"name\":\"%s\","
"\"stat_t\":\"homeassistant/switch/%s/plug_%d/state\","
"\"cmd_t\":\"device/ztc1/set\","
"\"pl_on\":\"{\\\"mac\\\":\\\"%s\\\",\\\"plug_%d\\\":{\\\"on\\\":1}}\","
"\"pl_off\":\"{\\\"mac\\\":\\\"%s\\\",\\\"plug_%d\\\":{\\\"on\\\":0}}\""
"}\0",
user_config->plug[plug_id].name, strMac, plug_id, strMac, plug_id, strMac, plug_id );
user_mqtt_send_topic( topic_buf, send_buf, 0 );
}
if ( send_buf )
free( send_buf );
if ( topic_buf )
free( topic_buf );
}
//hass mqtt自动发现数据功率发送
void user_mqtt_hass_auto_power( void )
{
uint8_t i;
uint8_t *send_buf = NULL;
uint8_t *topic_buf = NULL;
send_buf = malloc( 512 ); //
topic_buf = malloc( 128 ); //
if ( send_buf != NULL && topic_buf != NULL )
{
sprintf( topic_buf, "homeassistant/sensor/%s/power/config", strMac );
sprintf( send_buf, "{"
"\"name\":\"zTC1_power_%s\","
"\"state_topic\":\"homeassistant/sensor/%s/power/state\","
"\"unit_of_measurement\":\"W\","
"\"icon\":\"mdi:gauge\","
"\"value_template\":\"{{ value_json.power }}\""
"}",
strMac + 8, strMac );
user_mqtt_send_topic( topic_buf, send_buf, 1 );
}
if ( send_buf ) free( send_buf );
if ( topic_buf ) free( topic_buf );
}
void user_mqtt_hass_auto_power_name( void )
{
uint8_t *send_buf = NULL;
uint8_t *topic_buf = NULL;
send_buf = (uint8_t *) malloc( 300 ); //
topic_buf = (uint8_t *) malloc( 64 ); //
if ( send_buf != NULL && topic_buf != NULL )
{
sprintf( topic_buf, "homeassistant/sensor/%s/power/config", strMac );
sprintf( send_buf, "{"
"\"name\":\"zTC1xxxxxx\","
"\"state_topic\":\"homeassistant/sensor/%s/power/state\","
"\"unit_of_measurement\":\"W\","
"\"icon\":\"mdi:gauge\","
"\"value_template\":\"{{ value_json.power }}\""
"}",
strMac );
send_buf[13] = 0xe5;
send_buf[14] = 0x8a;
send_buf[15] = 0x9f;
send_buf[16] = 0xe7;
send_buf[17] = 0x8e;
send_buf[18] = 0x87;
user_mqtt_send_topic( topic_buf, send_buf, 0 );
}
if ( send_buf )
free( send_buf );
if ( topic_buf )
free( topic_buf );
}
void user_mqtt_hass_power( void )
{
uint8_t i;
uint8_t *send_buf = NULL;
uint8_t *topic_buf = NULL;
send_buf = malloc( 512 ); //
topic_buf = malloc( 128 ); //
if ( send_buf != NULL && topic_buf != NULL )
{
sprintf( topic_buf, "homeassistant/sensor/%s/power/state", strMac );
sprintf( send_buf, "{\"power\":\"%d.%d\"}", power / 10, power % 10 );
user_mqtt_send_topic( topic_buf, send_buf, 0 );
}
if ( send_buf ) free( send_buf );
if ( topic_buf ) free( topic_buf );
}
bool user_mqtt_isconnect( )
{
return isconnect;
}

23
TC1/user_mqtt_client.h Normal file
View File

@@ -0,0 +1,23 @@
#ifndef __USER_MQTT_CLIENT_H_
#define __USER_MQTT_CLIENT_H_
#include "mico.h"
#define MQTT_CLIENT_KEEPALIVE 30
#define MQTT_CLIENT_SUB_TOPIC1 "device/ztc1/set"
#define MQTT_CLIENT_PUB_TOPIC "device/ztc1/%s/state"
#define MQTT_CMD_TIMEOUT 5000 // 5s
#define MQTT_YIELD_TMIE 5000 // 5s
extern OSStatus user_mqtt_init(void);
extern OSStatus user_mqtt_send( char *arg );
extern bool user_mqtt_isconnect(void);
extern OSStatus user_mqtt_send_plug_state( char plug_id );
extern void user_mqtt_hass_auto( char plug_id );
extern void user_mqtt_hass_auto_name(char plug_id);
extern void user_mqtt_hass_power( void );
extern void user_mqtt_hass_auto_power( void );
extern void user_mqtt_hass_auto_power_name(void);
#endif

42
TC1/user_ota.c Normal file
View File

@@ -0,0 +1,42 @@
#define os_log(format, ...) custom_log("OTA", format, ##__VA_ARGS__)
#include "mico.h"
#include "ota_server/ota_server.h"
#include "main.h"
#include "user_udp.h"
#include "user_mqtt_client.h"
#include "user_function.h"
static void ota_server_status_handler( OTA_STATE_E state, float progress )
{
char str[64] = { 0 };
switch ( state )
{
case OTA_LOADING:
os_log("ota server is loading, progress %.2f%%", progress);
if ( ((int) progress)%10 == 1 )
sprintf( str, "{\"mac\":\"%s\",\"ota_progress\":%d}", strMac,((int) progress) );
break;
case OTA_SUCCE:
os_log("ota server daemons success");
sprintf( str, "{\"mac\":\"%s\",\"ota_progress\":100}", strMac );
break;
case OTA_FAIL:
os_log("ota server daemons failed");
sprintf( str, "{\"mac\":\"%s\",\"ota_progress\":-1}", strMac );
break;
default:
break;
}
if ( str[0] > 0 )
{
user_send( true, str );
}
}
void user_ota_start( char *url, char *md5 )
{
os_log("ready to ota:%s",url);
ota_server_start( url, md5, ota_server_status_handler );
}

7
TC1/user_ota.h Normal file
View File

@@ -0,0 +1,7 @@
#ifndef __USER_OTA_H_
#define __USER_OTA_H_
void user_ota_start(char *url, char *md5);
#endif

78
TC1/user_power.c Normal file
View File

@@ -0,0 +1,78 @@
#define os_log(format, ...) custom_log("OTA", format, ##__VA_ARGS__)
#include "TimeUtils.h"
#include "mico.h"
#include "main.h"
#include "user_udp.h"
#include "user_mqtt_client.h"
#include "user_function.h"
mico_timer_t power_timer;
static uint32_t clock_count_last = 0;
static uint32_t clock_count = 0;
static uint32_t timer_count = 0;
static uint32_t timer_irq_count = 0;
static void power_timer_handler( void* arg )
{
// uint8_t pin_input = MicoGpioInputGet( POWER );
uint32_t timer = 0;
if ( timer_irq_count > 1 )
{
timer = (clock_count - clock_count_last);
// os_log("power_irq_handler:%09u %u %u",timer,timer_irq_count,timer_count);
if ( timer_count > 3 )
{
timer /= 1000;
timer += 4294967; //0xffffffff/1000;
} else if ( clock_count < clock_count_last )
{
timer += 0xffffffff;
timer /= 1000;
}else timer/=1000;
power = 17100000 * (timer_irq_count - 1) / timer;
timer_count = 0;
timer_irq_count = 0;
} else
{
timer_count++;
}
// if ( clock_count_last != timer_count )
// {
//// os_log("power_irq_handler:%u-%u=%u",timer_count,clock_count_last,timer);
// timer = (timer_count - clock_count_last);
// if ( timer_count < clock_count_last ) timer += 0xffffffff;
//
// timer = timer / 1000;
// power = 15200000 / timer;
// os_log("power_irq_handler:%u,%07u",power,timer);
// clock_count_last = timer_count;
// }
// if(timer_count==0) os_log("power_timer_handler Hight:%d",clock_count_last);
// timer_count++;
// clock_count_last=timer_count;
}
static void power_irq_handler( void* arg )
{
clock_count = mico_nanosecond_clock_value( );
if ( timer_irq_count == 0 ) clock_count_last = clock_count;
timer_irq_count++;
}
void user_power_init( void )
{
os_log("user_power_init");
MicoGpioInitialize( POWER, INPUT_PULL_UP );
mico_rtos_init_timer( &power_timer, 1000, power_timer_handler, NULL );
mico_rtos_start_timer( &power_timer );
MicoGpioEnableIRQ( POWER, IRQ_TRIGGER_FALLING_EDGE, power_irq_handler, NULL );
}

6
TC1/user_power.h Normal file
View File

@@ -0,0 +1,6 @@
#ifndef __USER_POWER_H_
#define __USER_POWER_H_
void user_power_init( void );
#endif

280
TC1/user_rtc.c Normal file
View File

@@ -0,0 +1,280 @@
#define os_log(format, ...) custom_log("RTC", format, ##__VA_ARGS__)
#include "main.h"
#include "user_gpio.h"
#include "sntp.h"
#include "user_sntp.h"
#include "cJSON/cJSON.h"
#include "user_mqtt_client.h"
#include "user_function.h"
void rtc_thread( mico_thread_arg_t arg );
OSStatus user_sntp_get_time( )
{
OSStatus err = kNoErr;
ntp_timestamp_t current_time;
struct hostent * hostent_content = NULL;
char ** pptr = NULL;
struct in_addr ipp;
// mico_rtc_time_t rtc_time;
hostent_content = gethostbyname( "pool.ntp.org" );
pptr = hostent_content->h_addr_list;
ipp.s_addr = 0xd248912c;
err = sntp_get_time( &ipp, &current_time );
if ( err != kNoErr )
{
os_log("sntp_get_time err = %d.", err);
ipp.s_addr = *(uint32_t *) (*pptr);
err = sntp_get_time( &ipp, &current_time );
}
if ( err != kNoErr )
{
os_log("sntp_get_time0 err = %d.", err);
hostent_content = gethostbyname( "cn.ntp.org.cn" );
pptr = hostent_content->h_addr_list;
ipp.s_addr = *(uint32_t *) (*pptr);
err = sntp_get_time( &ipp, &current_time );
}
if ( err != kNoErr )
{
os_log("sntp_get_time1 err = %d.", err);
hostent_content = gethostbyname( "cn.pool.ntp.org" );
pptr = hostent_content->h_addr_list;
ipp.s_addr = *(uint32_t *) (*pptr);
err = sntp_get_time( &ipp, &current_time );
}
if ( err != kNoErr )
{
os_log("sntp_get_time2 err = %d.", err);
hostent_content = gethostbyname( "s1a.time.edu.cn" );
pptr = hostent_content->h_addr_list;
ipp.s_addr = *(uint32_t *) (*pptr);
err = sntp_get_time( &ipp, &current_time );
}
if ( err != kNoErr )
{
os_log("sntp_get_time3 err = %d.", err);
hostent_content = gethostbyname( "ntp.sjtu.edu.cn" );
pptr = hostent_content->h_addr_list;
ipp.s_addr = *(uint32_t *) (*pptr);
err = sntp_get_time( &ipp, &current_time );
}
if ( err == kNoErr )
{
mico_utc_time_ms_t utc_time_ms = (uint64_t) current_time.seconds * (uint64_t) 1000
+ (current_time.microseconds / 1000);
mico_time_set_utc_time_ms( &utc_time_ms );
// mico_utc_time_t utc_time = utc_time_ms / 1000 + 28800; //+8:00
// struct tm * currentTime = localtime( (const time_t *) &utc_time );
// rtc_time.sec = currentTime->tm_sec;
// rtc_time.min = currentTime->tm_min;
// rtc_time.hr = currentTime->tm_hour;
// rtc_time.date = currentTime->tm_mday;
// rtc_time.weekday = currentTime->tm_wday;
// rtc_time.month = currentTime->tm_mon + 1;
// rtc_time.year = (currentTime->tm_year + 1900) % 100;
// MicoRtcSetTime( &rtc_time );
}
else
{
os_log("sntp_get_time4 err = %d.", err);
return err;
}
return kNoErr;
}
OSStatus user_rtc_init( void )
{
OSStatus err = kNoErr;
// mico_rtc_time_t rtc_time;
// rtc_time.sec = 0;
// rtc_time.min = 0;
// rtc_time.hr = 0;
//
// rtc_time.date = 1;
// rtc_time.weekday = 1;
// rtc_time.month = 1;
// rtc_time.year = 1;
//
// MicoRtcSetTime( &rtc_time );
// /* create mqtt msg send queue */
// err = mico_rtos_init_queue( &mqtt_msg_send_queue, "mqtt_msg_send_queue", sizeof(p_mqtt_send_msg_t),
// MAX_MQTT_SEND_QUEUE_SIZE );
// require_noerr_action( err, exit, app_log("ERROR: create mqtt msg send queue err=%d.", err) );
/* start rtc client */
err = mico_rtos_create_thread( NULL, MICO_APPLICATION_PRIORITY, "rtc",
(mico_thread_function_t) rtc_thread,
0x1000, 0 );
require_noerr_string( err, exit, "ERROR: Unable to start the rtc thread." );
if ( kNoErr != err ) os_log("ERROR, app thread exit err: %d", err);
exit:
return err;
}
void rtc_thread( mico_thread_arg_t arg )
{
int i, j;
char task_flag[PLUG_NUM] = { -1, -1, -1, -1, -1, -1 }; //<2F><>¼ÿ<C2BC><C3BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><C4B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
OSStatus err = kUnknownErr;
LinkStatusTypeDef LinkStatus;
mico_rtc_time_t rtc_time;
mico_utc_time_t utc_time;
mico_utc_time_t utc_time_last;
while ( 1 )
{ //<2F>ϵ<EFBFBD><CFB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>wifi<66>ſ<EFBFBD>ʼ<EFBFBD><CABC>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD>ȴ<EFBFBD><C8B4><EFBFBD><EFBFBD><EFBFBD>
micoWlanGetLinkStatus( &LinkStatus );
if ( LinkStatus.is_connected == 1 )
{
err = user_sntp_get_time( );
if ( err == kNoErr )
{
os_log("sntp success!");
rtc_init = 1;
break;
}
}
mico_rtos_thread_sleep( 3 );
}
while ( 1 )
{
mico_time_get_utc_time( &utc_time );
utc_time += 28800;
if ( utc_time_last != utc_time )
{
utc_time_last == utc_time;
total_time++;
}
struct tm * currentTime = localtime( (const time_t *) &utc_time );
rtc_time.sec = currentTime->tm_sec;
rtc_time.min = currentTime->tm_min;
rtc_time.hr = currentTime->tm_hour;
rtc_time.date = currentTime->tm_mday;
rtc_time.weekday = currentTime->tm_wday;
rtc_time.month = currentTime->tm_mon + 1;
rtc_time.year = (currentTime->tm_year + 1900) % 100;
// MicoRtcSetTime( &rtc_time ); //MicoRtc<74><63><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD>ʱ!
if ( rtc_time.sec == 0 )
os_log("time:20%02d/%02d/%02d %d %02d:%02d:%02d",rtc_time.year,rtc_time.month,rtc_time.date,rtc_time.weekday,rtc_time.hr,rtc_time.min,rtc_time.sec);
char update_user_config_flag = 0;
for ( i = 0; i < PLUG_NUM; i++ )
{
for ( j = 0; j < PLUG_TIME_TASK_NUM; j++ )
{
if ( user_config->plug[i].task[j].on != 0 )
{
uint8_t repeat = user_config->plug[i].task[j].repeat;
if ( //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD><C4B1>̵<EFBFBD><CCB5><EFBFBD>״̬: <20><>Ϊ0 ʱ<>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD>趨ֵ, <20>ظ<EFBFBD><D8B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>趨ֵ
rtc_time.sec == 0 && rtc_time.min == user_config->plug[i].task[j].minute
&& rtc_time.hr == user_config->plug[i].task[j].hour
&& ((repeat == 0x00) || repeat & (1 << (rtc_time.weekday - 1)))
)
{
if ( user_config->plug[i].on != user_config->plug[i].task[j].action )
{
user_relay_set( i, user_config->plug[i].task[j].action );
update_user_config_flag = 1;
user_mqtt_send_plug_state( i );
}
if ( repeat == 0x00 )
{
task_flag[i] = j;
user_config->plug[i].task[j].on = 0;
update_user_config_flag = 1;
}
}
}
}
}
//<2F><><EFBFBD>´<EFBFBD><C2B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if ( update_user_config_flag == 1 )
{
os_log("update_user_config_flag");
mico_system_context_update( sys_config );
update_user_config_flag = 0;
cJSON *json_send = cJSON_CreateObject( );
cJSON_AddStringToObject( json_send, "mac", strMac );
for ( i = 0; i < PLUG_NUM; i++ )
{
char strTemp1[] = "plug_X";
strTemp1[5] = i + '0';
cJSON *json_send_plug = cJSON_CreateObject( );
cJSON_AddNumberToObject( json_send_plug, "on", user_config->plug[i].on );
if ( task_flag[i] >= 0 )
{
cJSON *json_send_plug_setting = cJSON_CreateObject( );
j = task_flag[i];
char strTemp2[] = "task_X";
strTemp2[5] = j + '0';
cJSON *json_send_plug_task = cJSON_CreateObject( );
cJSON_AddNumberToObject( json_send_plug_task, "hour", user_config->plug[i].task[j].hour );
cJSON_AddNumberToObject( json_send_plug_task, "minute", user_config->plug[i].task[j].minute );
cJSON_AddNumberToObject( json_send_plug_task, "repeat", user_config->plug[i].task[j].repeat );
cJSON_AddNumberToObject( json_send_plug_task, "action", user_config->plug[i].task[j].action );
cJSON_AddNumberToObject( json_send_plug_task, "on", user_config->plug[i].task[j].on );
cJSON_AddItemToObject( json_send_plug_setting, strTemp2, json_send_plug_task );
cJSON_AddItemToObject( json_send_plug, "setting", json_send_plug_setting );
task_flag[i] = -1;
}
cJSON_AddItemToObject( json_send, strTemp1, json_send_plug );
}
char *json_str = cJSON_Print( json_send );
user_send( false, json_str ); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
free( json_str );
cJSON_Delete( json_send );
// os_log("cJSON_Delete");
}
//SNTP<54><50><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿСʱУ׼һ<D7BC><D2BB>
if ( rtc_init != 1 || (rtc_time.sec == 0 && rtc_time.min == 0) )
{
micoWlanGetLinkStatus( &LinkStatus );
if ( LinkStatus.is_connected == 1 )
{
err = user_sntp_get_time( );
if ( err == kNoErr )
rtc_init = 1;
else
rtc_init = 2;
}
}
mico_rtos_thread_msleep( 900 );
}
// exit:
os_log("EXIT: rtc exit with err = %d.", err);
mico_rtos_delete_thread( NULL );
}

13
TC1/user_rtc.h Normal file
View File

@@ -0,0 +1,13 @@
#ifndef __USER_RTC_H_
#define __USER_RTC_H_
#include "mico.h"
#include "MiCOKit_EXT.h"
extern OSStatus user_rtc_init(void);
#endif

50
TC1/user_sntp.c Normal file
View File

@@ -0,0 +1,50 @@
#define os_log(format, ...) custom_log("SNTP", format, ##__VA_ARGS__)
#include "main.h"
//#include "user_gpio.h"
#include "user_sntp.h"
/* Callback function when MiCO UTC time in sync to NTP server */
static void sntp_time_call_back( void )
{
struct tm * currentTime;
// iso8601_time_t iso8601_time;
mico_utc_time_t utc_time;
mico_rtc_time_t rtc_time;
// mico_time_get_iso8601_time( &iso8601_time );
// os_log("sntp_time_synced: %.26s", (char*)&iso8601_time);
mico_time_get_utc_time( &utc_time );
utc_time+=28800; //+8:00
currentTime = localtime( (const time_t *)&utc_time );
rtc_time.sec = currentTime->tm_sec;
rtc_time.min = currentTime->tm_min;
rtc_time.hr = currentTime->tm_hour;
rtc_time.date = currentTime->tm_mday;
rtc_time.weekday = currentTime->tm_wday;
rtc_time.month = currentTime->tm_mon + 1;
rtc_time.year = (currentTime->tm_year + 1900) % 100;
MicoRtcSetTime( &rtc_time );
MicoRtcGetTime(&rtc_time);
os_log("SNTP 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);
}
void sntp_init(void)
{
struct in_addr ipp;ipp.s_addr=0xd248912c;
sntp_set_server_ip_address (0,ipp);
sntp_start_auto_time_sync (15000, sntp_time_call_back); //ÿСʱУ׼һ<D7BC><D2BB>
mico_rtc_time_t rtc_time;
MicoRtcGetTime(&rtc_time);
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);
}

13
TC1/user_sntp.h Normal file
View File

@@ -0,0 +1,13 @@
#ifndef __USER_SNTP_H_
#define __USER_SNTP_H_
#include "mico.h"
#include "MiCOKit_EXT.h"
extern void sntp_init(void);
#endif

178
TC1/user_udp.c Normal file
View File

@@ -0,0 +1,178 @@
#define os_log(format, ...) custom_log("UDP", format, ##__VA_ARGS__)
#include "main.h"
#include "user_function.h"
#define LOCAL_UDP_PORT 10182
#define REMOTE_UDP_PORT 10181
#define MAX_UDP_DATA_SIZE (1024)
#define MAX_UDP_SEND_QUEUE_SIZE (5)
mico_queue_t udp_msg_send_queue = NULL;
typedef struct
{
uint32_t datalen;
uint8_t data[MAX_UDP_DATA_SIZE];
} udp_send_msg_t, *p_udp_send_msg_t;
static OSStatus udp_msg_send( int socket, const unsigned char* msg, uint32_t msg_len );
void udp_thread( void *arg );
OSStatus user_udp_init( void )
{
OSStatus err = kNoErr;
/* start udp client */
err = mico_rtos_create_thread( NULL, MICO_APPLICATION_PRIORITY, "udp",
(mico_thread_function_t) udp_thread,
0x1000, 0 );
require_noerr_string( err, exit, "ERROR: Unable to start the rtc thread." );
if ( kNoErr != err ) os_log("ERROR, app thread exit err: %d", err);
exit:
return err;
}
/*create udp socket*/
void udp_thread( void *arg )
{
UNUSED_PARAMETER( arg );
OSStatus err;
struct sockaddr_in addr;
fd_set readfds;
socklen_t addrLen = sizeof(addr);
int udp_fd = -1, len;
p_udp_send_msg_t p_send_msg = NULL;
int msg_send_event_fd = -1;
char ip_address[16];
uint8_t *buf = NULL;
/* create udp msg send queue */
err = mico_rtos_init_queue( &udp_msg_send_queue, "uqp_msg_send_queue", sizeof(p_udp_send_msg_t),
MAX_UDP_SEND_QUEUE_SIZE );
require_noerr_action( err, exit, os_log( "ERROR: create udp msg send queue err=%d.", err ) );
/* create msg send queue event fd */
msg_send_event_fd = mico_create_event_fd( udp_msg_send_queue );
require_action( msg_send_event_fd >= 0, exit, os_log( "ERROR: create msg send queue event fd failed!!!" ) );
buf = malloc( 1024 );
require_action( buf, exit, err = kNoMemoryErr );
/*Establish a UDP port to receive any data sent to this port*/
udp_fd = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
require_action( IsValidSocket( udp_fd ), exit, err = kNoResourcesErr );
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons( LOCAL_UDP_PORT );
err = bind( udp_fd, (struct sockaddr *) &addr, sizeof(addr) );
require_noerr( err, exit );
os_log("Open local UDP port %d", LOCAL_UDP_PORT);
while ( 1 )
{
FD_ZERO( &readfds );
FD_SET( msg_send_event_fd, &readfds );
FD_SET( udp_fd, &readfds );
select( udp_fd + 1, &readfds, NULL, NULL, NULL );
/*Read data from udp and send data back */
if ( FD_ISSET( udp_fd, &readfds ) )
{
len = recvfrom( udp_fd, buf, 1024, 0, (struct sockaddr *) &addr, &addrLen );
require_action( len >= 0, exit, err = kConnectionErr );
strcpy( ip_address, inet_ntoa( addr.sin_addr ) );
if(len<1024) buf[len]=0;
os_log( "udp recv from %s:%d, len:%d ", ip_address,addr.sin_port, len );
user_function_cmd_received(1,buf);
// sendto( udp_fd, buf, len, 0, (struct sockaddr *) &addr, sizeof(struct sockaddr_in) );
}
/* recv msg from user worker thread to be sent to server */
if ( FD_ISSET( msg_send_event_fd, &readfds ) )
{
while ( mico_rtos_is_queue_empty( &udp_msg_send_queue ) == false )
{
// get msg from send queue
mico_rtos_pop_from_queue( &udp_msg_send_queue, &p_send_msg, 0 );
require_string( p_send_msg, exit, "Wrong data point" );
// send message to server
err = udp_msg_send( udp_fd, p_send_msg->data, p_send_msg->datalen );
// require_noerr_string( err, MQTT_reconnect, "ERROR: udp publish data err" );
os_log( "udp send data success! msg=[%ld].\r\n", p_send_msg->datalen);
free( p_send_msg );
p_send_msg = NULL;
}
}
}
exit:
if ( err != kNoErr )
os_log("UDP thread exit with err: %d", err);
if ( buf != NULL ) free( buf );
mico_rtos_delete_thread( NULL );
}
// send msg to udp
static OSStatus udp_msg_send( int socket, const unsigned char* msg, uint32_t msg_len )
{
OSStatus err = kUnknownErr;
int ret = 0;
require( msg_len && msg, exit );
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons( LOCAL_UDP_PORT );
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_BROADCAST;
addr.sin_port = htons( REMOTE_UDP_PORT );
/*the receiver should bind at port=20000*/
sendto( socket, msg, msg_len, 0, (struct sockaddr *) &addr, sizeof(addr) );
exit:
return err;
}
/* Application collect data and seng them to udp send queue */
OSStatus user_udp_send( char *arg )
{
OSStatus err = kUnknownErr;
p_udp_send_msg_t p_send_msg = NULL;
// app_log("======App prepare to send ![%d]======", MicoGetMemoryInfo()->free_memory);
/* Send queue is full, pop the oldest */
if ( mico_rtos_is_queue_full( &udp_msg_send_queue ) == true )
{
mico_rtos_pop_from_queue( &udp_msg_send_queue, &p_send_msg, 0 );
free( p_send_msg );
p_send_msg = NULL;
}
/* Push the latest data into send queue*/
p_send_msg = calloc( 1, sizeof(udp_send_msg_t) );
require_action( p_send_msg, exit, err = kNoMemoryErr );
p_send_msg->datalen = strlen( arg );
memcpy( p_send_msg->data, arg, p_send_msg->datalen );
err = mico_rtos_push_to_queue( &udp_msg_send_queue, &p_send_msg, 0 );
require_noerr( err, exit );
//app_log("Push user msg into send queue success!");
exit:
if ( err != kNoErr && p_send_msg ) free( p_send_msg );
return err;
}

14
TC1/user_udp.h Normal file
View File

@@ -0,0 +1,14 @@
#ifndef __USER_UDP_H_
#define __USER_UDP_H_
#include "mico.h"
#include "MiCOKit_EXT.h"
OSStatus user_udp_init( void );
OSStatus user_udp_send( char *arg );
#endif

152
TC1/user_wifi.c Normal file
View File

@@ -0,0 +1,152 @@
#include "user_wifi.h"
#include "main.h"
#include "mico_socket.h"
#include "user_gpio.h"
#include "user_sntp.h"
#define os_log(format, ...) custom_log("WIFI", format, ##__VA_ARGS__)
char wifi_status = WIFI_STATE_NOCONNECT;
mico_timer_t wifi_led_timer;
static void wifi_connect_sys_config( void )
{
if ( strlen( sys_config->micoSystemConfig.ssid ) > 0 )
{
os_log("connect ssid:%s key:%s",sys_config->micoSystemConfig.ssid,sys_config->micoSystemConfig.user_key);
network_InitTypeDef_st wNetConfig;
memset( &wNetConfig, 0, sizeof(network_InitTypeDef_st) );
strcpy( wNetConfig.wifi_ssid, sys_config->micoSystemConfig.ssid );
strcpy( wNetConfig.wifi_key, sys_config->micoSystemConfig.user_key );
wNetConfig.wifi_mode = Station;
wNetConfig.dhcpMode = DHCP_Client;
wNetConfig.wifi_retry_interval = 6000;
micoWlanStart( &wNetConfig );
wifi_status = WIFI_STATE_CONNECTING;
} else
wifi_status = WIFI_STATE_FAIL;
}
void wifi_start_easylink( )
{
wifi_status = WIFI_STATE_EASYLINK;
micoWlanStartEasyLink( 20000 );
user_led_set( 1 );
}
//easylink <20><><EFBFBD>ɻص<C9BB>
void wifi_easylink_completed_handle( network_InitTypeDef_st *nwkpara, void * arg )
{
os_log("wifi_easylink_wps_completed_handle:");
if ( nwkpara == NULL )
{
os_log("EasyLink fail");
micoWlanStopEasyLink( );
return;
}
os_log("ssid:\"%s\",\"%s\"",nwkpara->wifi_ssid,nwkpara->wifi_key);
//<2F><><EFBFBD><EFBFBD>wifi<66><69><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
strcpy( sys_config->micoSystemConfig.ssid, nwkpara->wifi_ssid );
strcpy( sys_config->micoSystemConfig.user_key, nwkpara->wifi_key );
sys_config->micoSystemConfig.user_keyLength = strlen( nwkpara->wifi_key );
mico_system_context_update( sys_config );
wifi_status = WIFI_STATE_NOCONNECT;
os_log("EasyLink stop");
micoWlanStopEasyLink( );
}
//wifi<66><69><EFBFBD><EFBFBD><EFBFBD>ӻ<EFBFBD>ȡ<EFBFBD><C8A1>IP<49><50>ַ <20>ص<EFBFBD>
static void wifi_get_ip_callback( IPStatusTypedef *pnet, void * arg )
{
os_log("got IP:%s", pnet->ip);
wifi_status = WIFI_STATE_CONNECTED;
user_function_cmd_received(1,"{\"cmd\":\"device report\"}");
}
//wifi<66><69><EFBFBD><EFBFBD>״̬<D7B4>ı<EFBFBD><C4B1>ص<EFBFBD>
static void wifi_status_callback( WiFiEvent status, void *arg )
{
if ( status == NOTIFY_STATION_UP ) //wifi<66><69><EFBFBD>ӳɹ<D3B3>
{
//wifi_status = WIFI_STATE_CONNECTED;
} else if ( status == NOTIFY_STATION_DOWN ) //wifi<66>Ͽ<EFBFBD>
{
wifi_status = WIFI_STATE_NOCONNECT;
if ( !mico_rtos_is_timer_running( &wifi_led_timer ) ) mico_rtos_start_timer( &wifi_led_timer );
}
}
//100ms<6D><73>ʱ<EFBFBD><CAB1><EFBFBD>ص<EFBFBD>
static void wifi_led_timer_callback( void* arg )
{
static unsigned int num = 0;
num++;
switch ( wifi_status )
{
case WIFI_STATE_FAIL:
os_log("wifi connect fail");
user_led_set( 0 );
mico_rtos_stop_timer( &wifi_led_timer );
break;
case WIFI_STATE_NOCONNECT:
wifi_connect_sys_config( );
break;
case WIFI_STATE_CONNECTING:
//if ( num > 1 )
{
num = 0;
user_led_set( -1 );
}
break;
case WIFI_STATE_NOEASYLINK:
wifi_start_easylink( );
break;
case WIFI_STATE_EASYLINK:
user_led_set( 1 );
break;
case WIFI_STATE_CONNECTED:
user_led_set( 0 );
mico_rtos_stop_timer( &wifi_led_timer );
if ( relay_out( ) )
user_led_set( 1 );
else
user_led_set( 0 );
break;
}
}
void wifi_init( void )
{
//wifi<66><69><EFBFBD>ó<EFBFBD>ʼ<EFBFBD><CABC>
// network_InitTypeDef_st wNetConfig;
// memset(&wNetConfig, 0, sizeof(network_InitTypeDef_st));
// wNetConfig.wifi_mode = Station;
// snprintf(wNetConfig.wifi_ssid, 32, "Honor 9" );
// strcpy((char*)wNetConfig.wifi_key, "19910911");
// wNetConfig.dhcpMode = DHCP_Client;
// wNetConfig.wifi_retry_interval=6000;
// micoWlanStart(&wNetConfig);
//wifi״̬<D7B4><CCAC>led<65><64>˸<EFBFBD><CBB8>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>
mico_rtos_init_timer( &wifi_led_timer, 100, (void *) wifi_led_timer_callback, NULL );
//easylink <20><><EFBFBD>ɻص<C9BB>
mico_system_notify_register( mico_notify_EASYLINK_WPS_COMPLETED, (void *) wifi_easylink_completed_handle, NULL );
//wifi<66><69><EFBFBD><EFBFBD><EFBFBD>ӻ<EFBFBD>ȡ<EFBFBD><C8A1>IP<49><50>ַ <20>ص<EFBFBD>
mico_system_notify_register( mico_notify_DHCP_COMPLETED, (void *) wifi_get_ip_callback, NULL );
//wifi<66><69><EFBFBD><EFBFBD>״̬<D7B4>ı<EFBFBD><C4B1>ص<EFBFBD>
mico_system_notify_register( mico_notify_WIFI_STATUS_CHANGED, (void*) wifi_status_callback, NULL );
//sntp_init();
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>wifi<66><69><EFBFBD><EFBFBD>
if ( !mico_rtos_is_timer_running( &wifi_led_timer ) ) mico_rtos_start_timer( &wifi_led_timer );
IPStatusTypedef para;
micoWlanGetIPStatus( &para, Station );
strcpy( strMac, para.mac );
}

28
TC1/user_wifi.h Normal file
View File

@@ -0,0 +1,28 @@
#ifndef __USER_WIFI_H_
#define __USER_WIFI_H_
#include "mico.h"
#include "MiCOKit_EXT.h"
enum {
WIFI_STATE_FAIL,
WIFI_STATE_NOCONNECT,
WIFI_STATE_CONNECTING,
WIFI_STATE_CONNECTED,
WIFI_STATE_NOEASYLINK,
WIFI_STATE_EASYLINK,
WIFI_STATE_EASYLINKING,
};
extern char wifi_status;
extern void wifi_init(void);
extern void wifi_start_easylink(void);
#endif

1
_config.yml Normal file
View File

@@ -0,0 +1 @@
theme: jekyll-theme-cayman

Binary file not shown.

Binary file not shown.

1
mico-os.component Normal file
View File

@@ -0,0 +1 @@
https://code.aliyun.com/mico/mico-os.git/#6c465211d3ff8797cd835e400ec54a06530dd476