From 4a963bd78cfc0f96b5ee83f3cc17123fde3d0481 Mon Sep 17 00:00:00 2001 From: "2584532475@qq.com" Date: Mon, 8 Apr 2024 20:38:35 +0800 Subject: [PATCH] 2024-05-31 --- Application/os-app.c | 6 +- Application/os-app.h | 17 +- Board/data.c | 208 ++- Board/data.h | 82 +- Board/di-board.c | 17 +- Board/di-board.h | 8 +- Board/do-board.c | 4 +- Board/do-board.h | 4 +- Board/network/cat1drv.c | 30 +- Board/network/jsonpacket.c | 24 +- Board/network/jsonunpack.c | 20 + Board/network/proto.c | 1 + Board/relay-board.c | 85 +- Board/relay-board.h | 30 +- Comm/networkthread.c | 2 + MDK-ARM/GB01VETx.uvguix.Memory | 48 +- .../RealThread_RTOS/components/device/alarm.c | 609 +++++++ .../RealThread_RTOS/components/device/rtc.c | 254 +++ .../RealThread_RTOS/components/device/rtc.h | 20 + .../components/device/soft_rtc.c | 109 ++ Project/g0b1vetx-sluice | 2 +- middleware/Util/util.c | 9 + middleware/Util/util.h | 7 + .../cjson-master/cjson-master/cJSON_Utils.c | 1481 +++++++++++++++++ .../cjson-master/cjson-master/cJSON_Utils.h | 88 + middleware/easyflash/inc/ef_cfg.h | 4 +- middleware/easyflash/port/ef_port.c | 16 +- 27 files changed, 2956 insertions(+), 229 deletions(-) create mode 100644 Middlewares/Third_Party/RealThread_RTOS/components/device/alarm.c create mode 100644 Middlewares/Third_Party/RealThread_RTOS/components/device/rtc.c create mode 100644 Middlewares/Third_Party/RealThread_RTOS/components/device/rtc.h create mode 100644 Middlewares/Third_Party/RealThread_RTOS/components/device/soft_rtc.c create mode 100644 middleware/cjson/cjson-master/cjson-master/cJSON_Utils.c create mode 100644 middleware/cjson/cjson-master/cjson-master/cJSON_Utils.h diff --git a/Application/os-app.c b/Application/os-app.c index 2092072..2d24595 100644 --- a/Application/os-app.c +++ b/Application/os-app.c @@ -12,6 +12,7 @@ #include #include #include "mqtt-board.h" +#include "relay-board.h" #include "data.h" uint32_t os_timer_count = 1; @@ -38,7 +39,7 @@ static rt_timer_t locktimer; static void locktimerouter (void* parameter) { // todo 关闭定时器 - HAL_GPIO_WritePin (LOCK_GPIO_Port, LOCK_Pin, GPIO_PIN_RESET); + MX_Relay_Push(RELAYDoor,RELAY_DISC); } static void thread_entry (void *parameter) @@ -68,6 +69,7 @@ static void thread_entry (void *parameter) //gCommEvents = rt_event_create ("gCommEvents", RT_IPC_FLAG_FIFO) ; locktimer = rt_timer_create ("locktimer", locktimerouter, RT_NULL, 1000, RT_TIMER_FLAG_ONE_SHOT); // 异常检测定时器 + RtcThreadStart (); SluiceThreadStart(); // 闸门控制线程 U4851ThreadStart(); // 4851采集线程 U4852ThreadStart(); // 4852采集线程 @@ -89,7 +91,7 @@ static void thread_entry (void *parameter) if (RT_EOK == rt_event_recv (gCtrlEvents, EVENT_CTRL_SET_UNLOCK, RT_EVENT_FLAG_AND | RT_EVENT_FLAG_CLEAR, 2000, RT_NULL)) // 数据接受失败,上报异常状态 { // todo: 打开继电器,开启定时器 - HAL_GPIO_WritePin (LOCK_GPIO_Port, LOCK_Pin, GPIO_PIN_SET); + MX_Relay_Push(RELAYDoor,RELAY_CONN); rt_timer_start (locktimer); } } diff --git a/Application/os-app.h b/Application/os-app.h index 0880b52..4c59c62 100644 --- a/Application/os-app.h +++ b/Application/os-app.h @@ -64,10 +64,14 @@ #define CFG_THREAD_PRIORITY 13 // 优先级 #define CFG_THREAD_TIMESLICE 5 -// UI线程 +// 升级 #define UPGRADE_THREAD_PRIORITY 12 // 优先级 #define UPGRADE_THREAD_TIMESLICE 5 +// RTC +#define RTC_THREAD_PRIORITY 11 // 优先级 +#define RTC_THREAD_TIMESLICE 5 + int ThreadNewOsApp (void); void SluiceThreadStart (void); @@ -84,6 +88,7 @@ void CAT1ThreadStart (void); void ZS001ThreadStart (void); void MJEth1ThreadStart (void); void UpgradeThreadStart (void); +void RtcThreadStart (void); #define EVENT_CTRL_SET_OPT_SLU (1U<< 0) // 发送开度控制到提闸线程 #define EVENT_CTRL_SET_STP_SLU (1U<< 1) // 发送停止控制到提闸线程 @@ -118,6 +123,7 @@ void UpgradeThreadStart (void); #define EVENT_TRIG_COMM_RX (1U << 6) // MQTT 接受到数据 #define EVENT_TRIG_COMM_RST (1U << 7) // MQTT 发送数据 #define EVENT_TRIG_UPGRADE_RX (1U << 8) // MQTT 接受到数据 +#define EVENT_TRIG_NETMODE_TX2 (1U << 9) // 通过网络模块向通道2发送数据 #define MAIL_COMM_HEART 0 @@ -127,6 +133,7 @@ void UpgradeThreadStart (void); #define MAIL_COMM_UPACK 4 // 提闸的ACK #define MAIL_COMM_SLACK 5 // 其他的ACK #define MAIL_COMM_READPARA 6 // 读取参数 +#define MAIL_COMM_ACK 7 // 读取参数 #define MAIL_SLUICE_OPT 0 #define MAIL_SLUICE_STP 1 @@ -134,10 +141,10 @@ void UpgradeThreadStart (void); #define MAIL_SLUICE_SDW 3 -#define MAIL_CT_OPT 0 -#define MAIL_CT_SUP 1 -#define MAIL_CT_SDW 2 -#define MAIL_CT_STP 3 +#define MAIL_CT_OPT 0 // 执行 +#define MAIL_CT_SUP 1 // 上升 +#define MAIL_CT_SDW 2 // 下降 +#define MAIL_CT_STP 3 // 停止 #define MAIL_VIEW_LOGIN 1 // 登录成功 需要跳转页面 #define MAIL_VIEW_FLUSH 2 // 刷新界面显示 diff --git a/Board/data.c b/Board/data.c index 90de6de..c2f2e9a 100644 --- a/Board/data.c +++ b/Board/data.c @@ -3,94 +3,116 @@ -const StrIndex_t cDownDataType[] = + +/****************************************** +* 版本信息 +******************************************/ +volatile const char _makeData[] = __DATE__; //12字节,编译日期 +volatile const char _makeTime[] = __TIME__; //9字节 +volatile const char cBootv[] = "Ver3.0.0"; //获取时添加上面两个时间信息,最大长度64字节 +char _versionTemp[64]; + + + +const StrIndex_t cDownDataType[] = { - {"run",DownRun} , - {"stop",DownStop} , - {"open",DownOpen} , - {"close",DownClose} , - {"reg_ans",DownRegistAns} , - {"heart_ans",DownHeartAns}, - {"update",DownUpdate}, - {"reboot",DownReboot}, - {"config",DownConfig}, - {"read",DownRead} + {"run", DownRun}, + {"stop", DownStop}, + {"open", DownOpen}, + {"close", DownClose}, + {"reg_ans", DownRegistAns}, + {"heart_ans", DownHeartAns}, + {"update", DownUpdate}, + {"reboot", DownReboot}, + {"config", DownConfig}, + {"read", DownRead}, + {"fact", DownFact} }; -const StrIndex_t cSiteType[] = +const StrIndex_t cSiteType[] = { - {"sluice",SiteSluice} , - {"flow",SiteFlow} , - {"press",SiteSee} , - {"auto",SiteColl} , - {"trans",SiteServer} , - {"level",SiteLevel} + {"sluice", SiteSluice}, + {"flow", SiteFlow}, + {"press", SiteSee}, + {"auto", SiteColl}, // 自动化采集站 + {"trans", SiteServer}, + {"level", SiteLevel}, + {"skew", SiteSkew} //测斜仪 }; -const StrIndex_t cMotorType[] = +const StrIndex_t cMotorType[] = { - {"mg1000",MT_MG_1000} , - {"qh100",MT_QH_V100} , - {"qh200",MT_QH_V200} , - {"zs100",MT_ZS_V100} , - {"dy100",MT_DY_V100} , - {"kg100",MT_KG_V100} + {"mg1000", MT_MG_1000}, + {"qh100", MT_QH_V100}, + {"qh200", MT_QH_V200}, + {"zs100", MT_ZS_V100}, + {"jz200", MT_JZ_V200}, // 金志 4-20 ma + {"dy100", MT_DY_V100}, // 大禹锥型阀 + {"kg100", MT_KG_V100}, // 开关量模块 + {"kr100", MT_KR_V100}, // 闸位计 + {"asca3", MT_ASC_A3}, // A3 驱动器 + {"ascws", MT_ASC_WS}, // A3 驱动器 }; -const StrIndex_t c4851Type[] = +const StrIndex_t c4851Type[] = { - {"mg1000",ST_MG_1000} , - {"qh100",ST_QH_V100} , - {"qh200",ST_QH_V200} , - {"dy100",ST_DY_V100} , - {"kg100",ST_KG_V100} , + {"mg1000", ST_MG_1000}, + {"qh100", ST_QH_V100}, + {"qh200", ST_QH_V200}, + {"zs100", ST_ZS_V100}, // 中盛4-20ma + {"dy100", ST_DY_V100}, + {"kg100", ST_KG_V100}, + {"at100", ST_AT_V100}, + {"kr100", ST_KR_V100}, }; -const StrIndex_t cU485Type[] = +const StrIndex_t cU485Type[] = { - {"modbus",0} + {"modbus", 0} }; -const StrIndex_t c4852Type[] = +// 485 2 通道 +const StrIndex_t c4852Type[] = { - {"rds600",ST_RDS_600} , - {"tds300",ST_TDS_300} , - {"ht100",ST_HT_V100} , - {"zkjszk",ST_ZK_JSZK}, - {"djx100",ST_DJX_100}, - {"rds300",ST_RDS_300} + {"rds600", ST_RDS_600}, + {"tds300", ST_TDS_300}, + {"ht100", ST_HT_V100}, + {"zkjszk", ST_ZK_JSZK}, + {"djx100", ST_DJX_100}, + {"rds300", ST_RDS_300}, + {"mi600", ST_MI_600} // 测斜仪 }; -const ParShallInfo_t ParShallTale[] = +const ParShallInfo_t ParShallTale[] = { - {.w = 0,.c = 0,.m = 0}, - {.w = 0.152, .c = 0.381, .m = 1.58 ,.minLeve = 0.03, .maxLeve = 0.45, .minFlow = 1.5/1000, .maxFlow = 100/1000}, - {.w = 0.25, .c = 0.561, .m = 1.513 ,.minLeve = 0.03, .maxLeve = 0.60, .minFlow = 3.0/1000, .maxFlow = 250/1000}, - {.w = 0.30, .c = 0.679, .m = 1.521 ,.minLeve = 0.03, .maxLeve = 0.75, .minFlow = 3.5/1000, .maxFlow = 400/1000}, - {.w = 0.45, .c = 1.038, .m = 1.537 ,.minLeve = 0.03, .maxLeve = 0.75, .minFlow = 4.5/1000, .maxFlow = 630/1000}, - {.w = 0.60, .c = 1.403, .m = 1.548 ,.minLeve = 0.05, .maxLeve = 0.75, .minFlow = 12.5/1000, .maxFlow = 850/1000}, - {.w = 0.75, .c = 1.772, .m = 1.557 ,.minLeve = 0.06, .maxLeve = 0.75, .minFlow = 25.0/1000, .maxFlow = 1100/1000}, - {.w = 0.90, .c = 2.147, .m = 1.565 ,.minLeve = 0.06, .maxLeve = 0.75, .minFlow = 30.0/1000, .maxFlow = 1250/1000}, - {.w = 1.00, .c = 2.397, .m = 1.569 ,.minLeve = 0.06, .maxLeve = 0.80, .minFlow = 30.0/1000, .maxFlow = 1500/1000}, - {.w = 1.20, .c = 2.904, .m = 1.577 ,.minLeve = 0.06, .maxLeve = 0.80, .minFlow = 35.0/1000, .maxFlow = 2000/1000}, - {.w = 1.50, .c = 3.668, .m = 1.586 ,.minLeve = 0.06, .maxLeve = 0.80, .minFlow = 45.0/1000, .maxFlow = 2500/1000}, - {.w = 1.80, .c = 4.440, .m = 1.593 ,.minLeve = 0.08, .maxLeve = 0.80, .minFlow = 80.0/1000, .maxFlow = 3000/1000}, - {.w = 2.10, .c = 5.222, .m = 1.599 ,.minLeve = 0.08, .maxLeve = 0.80, .minFlow = 95.0/1000, .maxFlow = 3600/1000}, - {.w = 2.40, .c = 6.004, .m = 1.605 ,.minLeve = 0.08, .maxLeve = 0.80, .minFlow = 100.0/1000, .maxFlow = 4000/1000}, - - {.w = 3.05, .c = 7.463, .m = 1.6 ,.minLeve = 0.09, .maxLeve = 1.07, .minFlow = 0.16, .maxFlow = 8.28}, - {.w = 3.66, .c = 8.859, .m = 1.6 ,.minLeve = 0.09, .maxLeve = 1.37, .minFlow = 0.19, .maxFlow = 14.68}, - {.w = 4.57, .c = 10.96, .m = 1.6 ,.minLeve = 0.09, .maxLeve = 1.67, .minFlow = 0.23, .maxFlow = 25.04}, - {.w = 6.10, .c = 14.45, .m = 1.6 ,.minLeve = 0.09, .maxLeve = 1.83, .minFlow = 0.31, .maxFlow = 37.97}, - - {.w = 7.62, .c = 17.94, .m = 1.6 ,.minLeve = 0.09, .maxLeve = 1.83, .minFlow = 0.38, .maxFlow = 47.16}, - {.w = 9.14, .c = 21.44, .m = 1.6 ,.minLeve = 0.09, .maxLeve = 1.83, .minFlow = 0.46, .maxFlow = 56.33}, - {.w = 12.19, .c = 28.43, .m = 1.6 ,.minLeve = 0.09, .maxLeve = 1.83, .minFlow = 0.60, .maxFlow = 74.70}, - {.w = 15.24, .c = 35.41, .m = 1.6 ,.minLeve = 0.09, .maxLeve = 1.83, .minFlow = 0.75, .maxFlow = 93.04}, + {.w = 0, .c = 0, .m = 0}, + {.w = 0.152, .c = 0.381, .m = 1.58 , .minLeve = 0.03, .maxLeve = 0.45, .minFlow = 1.5 / 1000, .maxFlow = 100 / 1000}, + {.w = 0.25, .c = 0.561, .m = 1.513 , .minLeve = 0.03, .maxLeve = 0.60, .minFlow = 3.0 / 1000, .maxFlow = 250 / 1000}, + {.w = 0.30, .c = 0.679, .m = 1.521 , .minLeve = 0.03, .maxLeve = 0.75, .minFlow = 3.5 / 1000, .maxFlow = 400 / 1000}, + {.w = 0.45, .c = 1.038, .m = 1.537 , .minLeve = 0.03, .maxLeve = 0.75, .minFlow = 4.5 / 1000, .maxFlow = 630 / 1000}, + {.w = 0.60, .c = 1.403, .m = 1.548 , .minLeve = 0.05, .maxLeve = 0.75, .minFlow = 12.5 / 1000, .maxFlow = 850 / 1000}, + {.w = 0.75, .c = 1.772, .m = 1.557 , .minLeve = 0.06, .maxLeve = 0.75, .minFlow = 25.0 / 1000, .maxFlow = 1100 / 1000}, + {.w = 0.90, .c = 2.147, .m = 1.565 , .minLeve = 0.06, .maxLeve = 0.75, .minFlow = 30.0 / 1000, .maxFlow = 1250 / 1000}, + {.w = 1.00, .c = 2.397, .m = 1.569 , .minLeve = 0.06, .maxLeve = 0.80, .minFlow = 30.0 / 1000, .maxFlow = 1500 / 1000}, + {.w = 1.20, .c = 2.904, .m = 1.577 , .minLeve = 0.06, .maxLeve = 0.80, .minFlow = 35.0 / 1000, .maxFlow = 2000 / 1000}, + {.w = 1.50, .c = 3.668, .m = 1.586 , .minLeve = 0.06, .maxLeve = 0.80, .minFlow = 45.0 / 1000, .maxFlow = 2500 / 1000}, + {.w = 1.80, .c = 4.440, .m = 1.593 , .minLeve = 0.08, .maxLeve = 0.80, .minFlow = 80.0 / 1000, .maxFlow = 3000 / 1000}, + {.w = 2.10, .c = 5.222, .m = 1.599 , .minLeve = 0.08, .maxLeve = 0.80, .minFlow = 95.0 / 1000, .maxFlow = 3600 / 1000}, + {.w = 2.40, .c = 6.004, .m = 1.605 , .minLeve = 0.08, .maxLeve = 0.80, .minFlow = 100.0 / 1000, .maxFlow = 4000 / 1000}, + + {.w = 3.05, .c = 7.463, .m = 1.6 , .minLeve = 0.09, .maxLeve = 1.07, .minFlow = 0.16, .maxFlow = 8.28}, + {.w = 3.66, .c = 8.859, .m = 1.6 , .minLeve = 0.09, .maxLeve = 1.37, .minFlow = 0.19, .maxFlow = 14.68}, + {.w = 4.57, .c = 10.96, .m = 1.6 , .minLeve = 0.09, .maxLeve = 1.67, .minFlow = 0.23, .maxFlow = 25.04}, + {.w = 6.10, .c = 14.45, .m = 1.6 , .minLeve = 0.09, .maxLeve = 1.83, .minFlow = 0.31, .maxFlow = 37.97}, + + {.w = 7.62, .c = 17.94, .m = 1.6 , .minLeve = 0.09, .maxLeve = 1.83, .minFlow = 0.38, .maxFlow = 47.16}, + {.w = 9.14, .c = 21.44, .m = 1.6 , .minLeve = 0.09, .maxLeve = 1.83, .minFlow = 0.46, .maxFlow = 56.33}, + {.w = 12.19, .c = 28.43, .m = 1.6 , .minLeve = 0.09, .maxLeve = 1.83, .minFlow = 0.60, .maxFlow = 74.70}, + {.w = 15.24, .c = 35.41, .m = 1.6 , .minLeve = 0.09, .maxLeve = 1.83, .minFlow = 0.75, .maxFlow = 93.04}, } ; @@ -98,7 +120,14 @@ const ParShallInfo_t ParShallTale[] = SluiceData_t SluiceData[SLUICE_COUTN]; WaterData_t WaterData[WATER_COUTN]; + +InclinometerData_t IncData[6]; // 测斜仪数据 + SysData_t SysData; +SOFTRTC_t g_SoftRtc = +{ + 23, 10, 1, 0, 0, 0 +}; uint32_t g_ifconfig = 0; uint32_t g_ifupdate = 0; @@ -106,9 +135,9 @@ uint32_t g_ifupdate = 0; int cMotorGetType (char * str) { - for (int i =0;i < sizeof(cMotorType)/sizeof(StrIndex_t);i++) + for (int i = 0; i < sizeof (cMotorType) / sizeof (StrIndex_t); i++) { - if (rt_memcmp(str,cMotorType[i].str,rt_strlen(str)) == 0) + if (rt_memcmp (str, cMotorType[i].str, rt_strlen (str)) == 0) { return cMotorType[i].index; } @@ -117,13 +146,13 @@ int cMotorGetType (char * str) } -int c4851GetType(char * str) +int c4851GetType (char * str) { - rt_kprintf("485 option count:%d\r\n",sizeof(c4851Type)/sizeof(StrIndex_t)) ; - for (int i =0;i < sizeof(c4851Type)/sizeof(StrIndex_t);i++) + rt_kprintf ("485 option count:%d\r\n", sizeof (c4851Type) / sizeof (StrIndex_t)) ; + for (int i = 0; i < sizeof (c4851Type) / sizeof (StrIndex_t); i++) { - rt_kprintf("%s,%s\r\n",str,c4851Type[i].str) ; - if (rt_memcmp(str,c4851Type[i].str,rt_strlen(str)) == 0) + rt_kprintf ("%s,%s\r\n", str, c4851Type[i].str) ; + if (rt_memcmp (str, c4851Type[i].str, rt_strlen (str)) == 0) { return c4851Type[i].index; } @@ -131,11 +160,11 @@ int c4851GetType(char * str) return -1; } -int c4852GetType(char * str) +int c4852GetType (char * str) { - for (int i =0;i < sizeof(c4852Type)/sizeof(StrIndex_t);i++) + for (int i = 0; i < sizeof (c4852Type) / sizeof (StrIndex_t); i++) { - if (rt_memcmp(str,c4852Type[i].str,rt_strlen(str)) == 0) + if (rt_memcmp (str, c4852Type[i].str, rt_strlen (str)) == 0) { return c4852Type[i].index; } @@ -144,11 +173,11 @@ int c4852GetType(char * str) } -int cU485GetType(char *str) +int cU485GetType (char *str) { - for (int i =0;i < sizeof(cU485Type)/sizeof(StrIndex_t);i++) + for (int i = 0; i < sizeof (cU485Type) / sizeof (StrIndex_t); i++) { - if (rt_memcmp(str,cU485Type[i].str,rt_strlen(str)) == 0) + if (rt_memcmp (str, cU485Type[i].str, rt_strlen (str)) == 0) { return cU485Type[i].index; } @@ -157,11 +186,11 @@ int cU485GetType(char *str) } -int cDownType2Index(char * str) +int cDownType2Index (char * str) { - for (int i =0;i < sizeof(cDownDataType)/sizeof(StrIndex_t);i++) + for (int i = 0; i < sizeof (cDownDataType) / sizeof (StrIndex_t); i++) { - if (rt_memcmp(str,cDownDataType[i].str,rt_strlen(str)) == 0) + if (rt_memcmp (str, cDownDataType[i].str, rt_strlen (str)) == 0) { return cDownDataType[i].index; } @@ -171,11 +200,11 @@ int cDownType2Index(char * str) -int cSiteType2Index(char * str) +int cSiteType2Index (char * str) { - for (int i =0;i < sizeof(cSiteType)/sizeof(StrIndex_t);i++) + for (int i = 0; i < sizeof (cSiteType) / sizeof (StrIndex_t); i++) { - if (rt_memcmp(str,cSiteType[i].str,rt_strlen(str)) == 0) + if (rt_memcmp (str, cSiteType[i].str, rt_strlen (str)) == 0) { return cSiteType[i].index; } @@ -186,6 +215,17 @@ int cSiteType2Index(char * str) +/********************************************** +获取boot版本信息 +**********************************************/ +void *GetVersion (void) +{ + int i = rt_sprintf (_versionTemp, "%s-%s %s", cBootv, _makeData, _makeTime); + _versionTemp[i] = 0; + return (void*) _versionTemp; +} + + diff --git a/Board/data.h b/Board/data.h index 927de34..1581b5b 100644 --- a/Board/data.h +++ b/Board/data.h @@ -3,13 +3,20 @@ #include + #define SLUICE_COUTN 1// 当前处理几口闸 #define WATER_COUTN 6// 当前接入n个流量计 + #define SUBTOPIC_COUNT 1 // 订阅topic 数量 #define SLUCIE_EXEC_COUNT 20// 闸门异常时间 -#define VERSION "V2.0.1" +#define VERSION "KRH-1.0.16" + // #define AI_AOVERSION "KRH-1.0.16" +//AIAO + + + @@ -20,7 +27,7 @@ typedef struct StrIndex_t { char str[10]; int index; -}StrIndex_t; +} StrIndex_t; // 巴歇尔槽流量计 @@ -33,7 +40,7 @@ typedef struct ParShallInfo_t double maxLeve; double minFlow; double maxFlow; -}ParShallInfo_t; +} ParShallInfo_t; @@ -41,13 +48,13 @@ typedef struct LeveInfo_t { uint16_t Y[100]; // 水位 uint16_t Key[100]; // 流量 -}LeveInfo_t; +} LeveInfo_t; // 水位流量关系表数据 typedef struct WaterLeveInfo_t { uint16_t X[100]; // 单位 mm LeveInfo_t Key[100]; -}WaterLeveInfo_t; +} WaterLeveInfo_t; @@ -78,18 +85,37 @@ typedef struct SysData_t int fileSize; // 文件大小 } SysData_t; +typedef struct SOFTRTC_t +{ + uint8_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t minutes; + uint8_t second; +} SOFTRTC_t; + // 水量参数 +typedef struct InclinometerData_t +{ + uint8_t dir; // 方向 + uint32_t data;// 数据 +} InclinometerData_t; + + +// 测斜数据 typedef struct WaterData_t { - int64_t ttWater; // 累计流量 单位 m3 - int32_t thisFlow; // 瞬时流量 单位 m3 - int32_t thisLevel; // 水位 - int32_t thisSpeed; // 流速 + int64_t ttWater; // 累计流量 单位 m3 + int32_t thisFlow; // 瞬时流量 单位 m3 + int32_t thisLevel; // 水位 + int32_t thisSpeed; // 流速 int32_t thisPress; // 压力 int32_t thisTemp; // 温度 + int retry ; // 重试次数 } WaterData_t; @@ -98,7 +124,7 @@ typedef enum Ctrl_Mode_t { CTRL_FOPEN = 0, CTRL_ZOPEN = 1 -}Ctrl_Mode_t; +} Ctrl_Mode_t; typedef enum MotorType_t @@ -106,11 +132,13 @@ typedef enum MotorType_t MT_MG_1000, // 米格1000 MT_QH_V100, // 强华 1.0 版本 MT_QH_V200, // 强华 2.0 版本 - MT_ZS_V100, // 中盛 4-20 ma + MT_ZS_V100, // 中盛 4-20 ma MT_JZ_V200, // 金志 4-20 ma MT_DY_V100, // 大禹锥型阀 MT_KG_V100, // 开关量模块 MT_KR_V100, // 徐州正天闸位计 + MT_ASC_A3, // A3驱动器 + MT_ASC_WS, // 金昌无刷电机 } MotorType_t; typedef enum S4851Type_t @@ -118,6 +146,7 @@ typedef enum S4851Type_t ST_MG_1000, // 米格1000 ST_QH_V100, // 强华 1.0 版本 ST_QH_V200, // 强华 2.0 版本 + ST_ZS_V100, // 中盛4-20ma ST_AT_V100, // 奥图编码器 ST_DY_V100, // 大禹锥形阀 ST_KG_V100, // 开关量模块 @@ -129,9 +158,10 @@ typedef enum S4852Type_t ST_RDS_600, // rds600 雷达流速一体机 ST_TDS_300, // tds300 超声波流量计 ST_HT_V100, // 华天液位计 - ST_ZK_JSZK, // 精水中科多普勒 + ST_ZK_JSZK, // 精水中科多普勒 ST_DJX_100, // 丁家峡闸门 读取开度 ST_RDS_300, // 雷达流量计 + ST_MI_600, // 鹦鸽嘴测斜仪 } S4852Type_t; @@ -140,7 +170,7 @@ typedef enum SOFTFLOWType_t NONE, WATER, PARSHALL// -}SOFTFLOWType_t; +} SOFTFLOWType_t; @@ -151,8 +181,9 @@ typedef enum SiteType_t SiteSee, // 渗流渗压站 SiteColl, // 采集站 SiteServer, // 串口服务器 - SiteLevel // 水位站 -}SiteType_t; + SiteLevel, // 水位站 + SiteSkew // 测斜仪 +} SiteType_t; typedef enum DownDataType_t @@ -167,7 +198,8 @@ typedef enum DownDataType_t DownReboot = 7, // 重启 DownConfig = 8, // 修改参数 DownRead = 9, // 读取参数 -}DownDataType_t; + DownFact = 10, // 读取参数 +} DownDataType_t; @@ -178,36 +210,40 @@ typedef struct TypeIndexMail_t { uint16_t Type; uint16_t index; -}TypeIndexMail_t; +} TypeIndexMail_t; extern SluiceData_t SluiceData[SLUICE_COUTN]; extern WaterData_t WaterData[WATER_COUTN]; +extern InclinometerData_t IncData[6]; extern SysData_t SysData; extern const WaterLeveInfo_t LeveInfo; extern const ParShallInfo_t ParShallTale[]; +extern SOFTRTC_t g_SoftRtc; int cMotorGetType (char * str); -int c4851GetType(char * str); +int c4851GetType (char * str); -int c4852GetType(char * str); +int c4852GetType (char * str); -int cU485GetType(char *str); +int cU485GetType (char *str); // 读取控制模式 -int cCtrlGetType(char * str); +int cCtrlGetType (char * str); -int cDownType2Index(char * str); +int cDownType2Index (char * str); -int cSiteType2Index(char * str); +int cSiteType2Index (char * str); +void *GetVersion (void); + #endif diff --git a/Board/di-board.c b/Board/di-board.c index db57117..1c797f6 100644 --- a/Board/di-board.c +++ b/Board/di-board.c @@ -1,39 +1,40 @@ #include "main.h" +#include "di-board.h" -int DiReadChann (int chann) +DIState_t MX_Din_Pull (int chann) { - int ret = -1; + DIState_t ret; switch (chann) { case 1: { - ret = HAL_GPIO_ReadPin (DI1_GPIO_Port, DI1_Pin); + ret = (DIState_t) HAL_GPIO_ReadPin (DI1_GPIO_Port, DI1_Pin); break; } case 2: { - ret = HAL_GPIO_ReadPin (DI2_GPIO_Port, DI2_Pin); + ret = (DIState_t) HAL_GPIO_ReadPin (DI2_GPIO_Port, DI2_Pin); break; } case 3: { - ret = HAL_GPIO_ReadPin (DI3_GPIO_Port, DI4_Pin); + ret = (DIState_t) HAL_GPIO_ReadPin (DI3_GPIO_Port, DI3_Pin); break; } case 4: { - ret = HAL_GPIO_ReadPin (DI4_GPIO_Port, DI4_Pin); + ret = (DIState_t) HAL_GPIO_ReadPin (DI4_GPIO_Port, DI4_Pin); break; } case 5: { - ret = HAL_GPIO_ReadPin (DI5_GPIO_Port, DI5_Pin); + ret = (DIState_t) HAL_GPIO_ReadPin (DI5_GPIO_Port, DI5_Pin); break; } case 6: { - ret = HAL_GPIO_ReadPin (DI6_GPIO_Port, DI6_Pin); + ret = (DIState_t) HAL_GPIO_ReadPin (DI6_GPIO_Port, DI6_Pin); break; } } diff --git a/Board/di-board.h b/Board/di-board.h index 355b92f..85a5867 100644 --- a/Board/di-board.h +++ b/Board/di-board.h @@ -1,8 +1,14 @@ #ifndef _DI_BOARD_H #define _DI_BOARD_H +typedef enum DIState_t +{ + DI_HIGH = 1, + DI_LOW = 0 +} DIState_t; + void DiInit (void); -int DiReadChann (int chann); +DIState_t MX_Din_Pull (int chann); #endif diff --git a/Board/do-board.c b/Board/do-board.c index ff412f8..b4abfd6 100644 --- a/Board/do-board.c +++ b/Board/do-board.c @@ -3,7 +3,7 @@ -void MX_Dout_Push(int index,int pwm) +void MX_Dout_Push (int index, int pwm) { - MX_TIM_SetDuty(index,pwm); + MX_TIM_SetDuty (index, pwm); } \ No newline at end of file diff --git a/Board/do-board.h b/Board/do-board.h index a8bbaa8..72fa7fc 100644 --- a/Board/do-board.h +++ b/Board/do-board.h @@ -1,6 +1,6 @@ #ifndef _DO_BOARD_HH #define _DO_BOARD_HH -void MX_Dout_Push(int index, int pwm); +void MX_Dout_Push (int index, int pwm); -#endif \ No newline at end of file +#endif \ No newline at end of file diff --git a/Board/network/cat1drv.c b/Board/network/cat1drv.c index db3677a..1acca24 100644 --- a/Board/network/cat1drv.c +++ b/Board/network/cat1drv.c @@ -165,7 +165,7 @@ static CommRet_T cat1_sendcmd_and_responce (int time, char * tx, int size, char { if (RT_EOK == rt_event_recv (gUartEvents, EVENT_UART_GSM_RX, RT_EVENT_FLAG_AND | RT_EVENT_FLAG_CLEAR, 0, RT_NULL)) { - // rt_kprintf ("[%.*s]", g_GSMDrv.rx_size, g_GSMDrv.rx_buffer) ; + //rt_kprintf ("[%.*s]", g_GSMDrv.rx_size, g_GSMDrv.rx_buffer) ; if (NULL != rt_strstr ( (char *) g_GSMDrv.rx_buffer, ack)) { if (call != NULL) @@ -278,6 +278,26 @@ CAT1RST: rt_kprintf ("NET:+CME:ERROR QIRD\r\n"); goto CAT1RST; } +// // 通过通道2上报数据 +// if (RT_EOK == rt_event_recv (gTrigEvents, EVENT_TRIG_NETMODE_TX2, RT_EVENT_FLAG_AND | RT_EVENT_FLAG_CLEAR, RT_WAITING_NO, RT_NULL)) // 需要发送数据 +// { +// if (g_cat1Drv.txbuff != NULL) +// { +// rt_sprintf (at_cmd, "AT+QISEND=0,%d\r\n", g_cat1Drv.tx_size); +// rt_thread_mdelay (10); +// if (cat1_sendcmd_and_responce (1000, at_cmd, strlen (at_cmd), ">", NULL) != RetSucc) +// { +// rt_kprintf ("NET:+CME:ERROR QISEND\r\n"); +// goto CAT1RST; +// } +// if (cat1_sendcmd_and_responce (3000, g_cat1Drv.txbuff, g_cat1Drv.tx_size, "SEND OK", NULL) != RetSucc) +// { +// rt_kprintf ("NET:+CME:ERROR QPUSH\r\n"); +// goto CAT1RST; +// } +// } +// } + } rt_thread_mdelay (3000); } @@ -292,6 +312,14 @@ void cat1_service_tx (char * buff, int size) rt_event_send (gTrigEvents, EVENT_TRIG_NETMODE_TX1) ; } +// 通过网络通道2发送数据 +void cat1_service2_tx (char * buff, int size) +{ + rt_memcpy (g_cat1Drv.txbuff, buff, size); + g_cat1Drv.tx_size = size; + rt_event_send (gTrigEvents, EVENT_TRIG_NETMODE_TX2) ; +} + void CAT1ThreadStart (void) { diff --git a/Board/network/jsonpacket.c b/Board/network/jsonpacket.c index f9d4011..a589779 100644 --- a/Board/network/jsonpacket.c +++ b/Board/network/jsonpacket.c @@ -26,15 +26,15 @@ int Json5MinFlowDataPacket (uint8_t * buffer) cJSON_AddItemToObject (root, "site_type", cJSON_CreateString (p)); // 表示流量计 cJSON_AddItemToObject (root, "pver", cJSON_CreateString (PROTO_VER)); // 表示流量计 cJSON_AddItemToObject (root, "iccid", cJSON_CreateString (SysData.iccid)); // 表示流量计 - cJSON_AddItemToObject (root, "ver", cJSON_CreateString (VERSION)); // 表示流量计 + cJSON_AddItemToObject (root, "ver", cJSON_CreateString (GetVersion())); // 表示流量计 cJSON_AddItemToObject (root, "vol", cJSON_CreateNumber (12.3)); // 表示电池电压 cJSON_AddItemToObject (root, "temp", cJSON_CreateNumber (32.5)); // 表示流量计 p = ef_get_env ("net_drv"); cJSON_AddItemToObject (root, "netdrv", cJSON_CreateString (p)); // 表示流量计 p = ef_get_env ("iap_app_filename"); - //uint32_t max_open = atoi (p); cJSON_AddItemToObject (root, "filename", cJSON_CreateString (p)); // 表示电池电压 - cJSON_AddItemToObject (root, "chancnt", cJSON_CreateNumber (1)); // 表示电池电压 + p = ef_get_env ("chancnt"); + cJSON_AddItemToObject (root, "chancnt", cJSON_CreateString (p)); // 表示电池电压 //cJSON_AddItemToObject (root, "chancnt", cJSON_CreateNumber (1)); // 表示电池电压 // 瞬时流速 for (int i = 0; i < 6; i++) @@ -63,7 +63,7 @@ int Json5MinFlowDataPacket (uint8_t * buffer) // 当前水位 for (int i = 0; i < 6; i++) { - dbl[i] = WaterData[i].thisLevel; + dbl[i] = (double)WaterData[i].thisLevel/100; } cJSON * ArrNumLeve = cJSON_CreateDoubleArray (dbl, 6); cJSON_AddItemToObject (root, "thisLeve", ArrNumLeve); @@ -82,6 +82,22 @@ int Json5MinFlowDataPacket (uint8_t * buffer) } cJSON * ArrNumTemp = cJSON_CreateDoubleArray (dbl, 6); cJSON_AddItemToObject (root, "thistemp", ArrNumTemp); + + // 当前测斜方向 + for (int i = 0; i < 6; i++) + { + dbl[i] = IncData[i].dir; + } + cJSON * ArrNumIncDir = cJSON_CreateDoubleArray (dbl, 6); + cJSON_AddItemToObject (root, "thisincdir", ArrNumIncDir); + + // 当前测斜数据 + for (int i = 0; i < 6; i++) + { + dbl[i] = IncData[i].data; + } + cJSON * ArrNumIncData = cJSON_CreateDoubleArray (dbl, 6); + cJSON_AddItemToObject (root, "thisincdata", ArrNumIncData); //---------------------------------------------以下不准修改 result = cJSON_PrintUnformatted (root); diff --git a/Board/network/jsonunpack.c b/Board/network/jsonunpack.c index 6f3d941..a052437 100644 --- a/Board/network/jsonunpack.c +++ b/Board/network/jsonunpack.c @@ -7,9 +7,13 @@ #include #include "data.h" #include "os-app.h" +#include "main.h" char config_list[16][32] = {NULL}; int config_list_size = 0; +// 用于远程出厂设置时保留配置 +char backdevice_id[12] = {0}; +char backnetdrv[12] = {0}; @@ -66,6 +70,7 @@ void JsonUnPacket (int index, char *buff) UpgradeThreadStart(); break; case DownReboot : + HAL_NVIC_SystemReset(); break; case DownConfig: // 设置参数 // 读取参数列表 @@ -80,6 +85,9 @@ void JsonUnPacket (int index, char *buff) ef_set_env (key, value); } } + mail.Type = MAIL_COMM_ACK; + mail.index = index + 1; // 0通道用来升级的通道 + rt_mb_send (gTCommMail, * ( (uint32_t*) &mail)); break; case DownRead: // 读取参数 list = cJSON_GetObjectItem (root, "list"); @@ -94,6 +102,18 @@ void JsonUnPacket (int index, char *buff) rt_mb_send (gTCommMail, * ( (uint32_t*) &mail)); // 读取参数列表 break; + case DownFact: + p = ef_get_env("device_id"); + rt_sprintf(backdevice_id,"%s",p); + p = ef_get_env("net_drv") ; + rt_sprintf(backnetdrv,"%s",p); + ef_env_set_default(); + ef_set_env("device_id",backdevice_id) ; + ef_set_env("net_drv",backnetdrv) ; + mail.Type = MAIL_COMM_ACK; + mail.index = index + 1; // 0通道用来升级的通道 + rt_mb_send (gTCommMail, * ( (uint32_t*) &mail)); + break; default: break; } diff --git a/Board/network/proto.c b/Board/network/proto.c index dea9e6f..5fe93f5 100644 --- a/Board/network/proto.c +++ b/Board/network/proto.c @@ -172,6 +172,7 @@ int PacketSluiceUp (int k, char * tx_data) tx_data[tx_size++] = 0x01; // // 闸门开度 intk.data = SluiceData[k].gopen * 10; + rt_kprintf("gopen:%d\r\n"); tx_data[tx_size++] = intk.byte[3]; tx_data[tx_size++] = intk.byte[2]; tx_data[tx_size++] = intk.byte[1]; diff --git a/Board/relay-board.c b/Board/relay-board.c index 370ecf6..d4405b5 100644 --- a/Board/relay-board.c +++ b/Board/relay-board.c @@ -1,54 +1,43 @@ #include "relay-board.h" +#include "main.h" -RelayInfo_t RelayInfo = + +void MX_Relay_Push (RelayIndex_t index, RelayState_t ste) { - {GPIOB, GPIO_PIN_8, GPIO_MODE_OUTPUT_PP, GPIO_PULLUP, GPIO_SPEED_FREQ_VERY_HIGH, NULL}, //PB5 - {GPIOB, GPIO_PIN_9, GPIO_MODE_OUTPUT_PP, GPIO_PULLUP, GPIO_SPEED_FREQ_VERY_HIGH, NULL}, //PB5 -}; -/******************************************** - 函数名称:UartInfoInit - 输入参数:串口句柄 - 输出参数:NULL - 功能描述:初始化一个串口 -********************************************/ -void RelayInfoInit (void) -{ - GPIO_InitTypeDef GPIO_InitStruct; - - GPIO_InitStruct.Mode = RelayInfo.Relay1.mode; - GPIO_InitStruct.Pull = RelayInfo.Relay1.Pull; - GPIO_InitStruct.Speed = RelayInfo.Relay1.Speed; - - GPIO_InitStruct.Pin = RelayInfo.Relay1.pin; - HAL_GPIO_Init (RelayInfo.Relay1.GPIOx, &GPIO_InitStruct); - HAL_GPIO_WritePin (RelayInfo.Relay1.GPIOx, RelayInfo.Relay1.pin, GPIO_PIN_RESET); - - - GPIO_InitStruct.Mode = RelayInfo.Relay2.mode; - GPIO_InitStruct.Pull = RelayInfo.Relay2.Pull; - GPIO_InitStruct.Speed = RelayInfo.Relay2.Speed; - - GPIO_InitStruct.Pin = RelayInfo.Relay2.pin; - HAL_GPIO_Init (RelayInfo.Relay2.GPIOx, &GPIO_InitStruct); - HAL_GPIO_WritePin (RelayInfo.Relay2.GPIOx, RelayInfo.Relay2.pin, GPIO_PIN_RESET); -} -void RelayOpenDoor (void) -{ - HAL_GPIO_WritePin (RelayInfo.Relay1.GPIOx, RelayInfo.Relay1.pin, GPIO_PIN_SET); -} -void RelayCloseDoor (void) -{ - HAL_GPIO_WritePin (RelayInfo.Relay1.GPIOx, RelayInfo.Relay1.pin, GPIO_PIN_RESET); -} - - -void RelayOpenK2 (void) -{ - HAL_GPIO_WritePin (RelayInfo.Relay2.GPIOx, RelayInfo.Relay2.pin, GPIO_PIN_SET); -} -void RelayCloseK2 (void) -{ - HAL_GPIO_WritePin (RelayInfo.Relay2.GPIOx, RelayInfo.Relay2.pin, GPIO_PIN_RESET); + if (ste == RELAY_CONN) + { + switch (index) + { + case RELAY1: + HAL_GPIO_WritePin (RELAY1_GPIO_Port, RELAY1_Pin, GPIO_PIN_SET); + break; + case RELAY2: + HAL_GPIO_WritePin (RELAY2_GPIO_Port, RELAY2_Pin, GPIO_PIN_SET); + break; + case RELAYDoor: + HAL_GPIO_WritePin (LOCK_GPIO_Port, LOCK_Pin, GPIO_PIN_SET); + break; + default: + break; + } + } + else + { + switch (index) + { + case RELAY1: + HAL_GPIO_WritePin (RELAY1_GPIO_Port, RELAY1_Pin, GPIO_PIN_RESET); + break; + case RELAY2: + HAL_GPIO_WritePin (RELAY2_GPIO_Port, RELAY2_Pin, GPIO_PIN_RESET); + break; + case RELAYDoor: + HAL_GPIO_WritePin (LOCK_GPIO_Port, LOCK_Pin, GPIO_PIN_RESET); + break; + default: + break; + } + } } diff --git a/Board/relay-board.h b/Board/relay-board.h index 7ac4330..6bbb956 100644 --- a/Board/relay-board.h +++ b/Board/relay-board.h @@ -1,25 +1,23 @@ #ifndef _RELAY_BOARD_H #define _RELAY_BOARD_H -#include "stm32l0xx_hal.h" -#include "stgpio.h" -typedef struct RelayInfo_t + + + +typedef enum RelayState_t { -// GpioInfo_t Tx; -// GpioInfo_t Rx; - - GpioInfo_t Relay1; // 用于控制485的收发 - GpioInfo_t Relay2; // 用于控制485的收发 - -} RelayInfo_t; - -void RelayInfoInit (void); -void RelayOpenDoor (void); -void RelayCloseDoor (void); -void RelayOpenK2 (void); -void RelayCloseK2 (void); + RELAY_CONN = 1, + RELAY_DISC = 0 +} RelayState_t; +typedef enum RelayIndex_t +{ + RELAY1 = 0, + RELAY2 = 1, + RELAYDoor = 2 +} RelayIndex_t; +void MX_Relay_Push (RelayIndex_t index, RelayState_t ste); #endif diff --git a/Comm/networkthread.c b/Comm/networkthread.c index 4d00b2b..94f2484 100644 --- a/Comm/networkthread.c +++ b/Comm/networkthread.c @@ -179,6 +179,8 @@ INIT: break; case SiteFlow: case SiteSee: + case SiteLevel: + case SiteSkew: gMqttDrv.tx_size = Json5MinFlowDataPacket ( (uint8_t *) gMqttDrv.txbuff); break; case SiteColl: diff --git a/MDK-ARM/GB01VETx.uvguix.Memory b/MDK-ARM/GB01VETx.uvguix.Memory index 650e83c..d2a5d89 100644 --- a/MDK-ARM/GB01VETx.uvguix.Memory +++ b/MDK-ARM/GB01VETx.uvguix.Memory @@ -97,17 +97,17 @@ -1 - 337 - 2503 - 3943 - 1096 + 306 + 2035 + 3475 + 1065 0 1394 - 010000000400000001000000010000000100000001000000000000000200000000000000010000000100000000000000280000002800000001000000090000000400000001000000834A3A5C6164645F62795F7A68616E6770656E675C50726F6A6563745C534C554943455C536C756963655C474230564554785C67306231766574782D626F6172645C4D6964646C6577617265735C54686972645F50617274795C5265616C5468726561645F52544F535C636F6D706F6E656E74735C6465766963655C6465766963652E6300000000086465766963652E6300000000C5D4F200FFFFFFFF554A3A5C6164645F62795F7A68616E6770656E675C50726F6A6563745C534C554943455C536C756963655C474230564554785C67306231766574782D626F6172645C52542D5468726561645C7274636F6E6669672E68000000000A7274636F6E6669672E6800000000FFDC7800FFFFFFFF8C4A3A5C6164645F62795F7A68616E6770656E675C50726F6A6563745C534C554943455C536C756963655C474230564554785C67306231766574782D626F6172645C4D6964646C6577617265735C54686972645F50617274795C5265616C5468726561645F52544F535C6273705C5F74656D706C6174655C637562656D785F636F6E6669675C626F6172642E630000000007626F6172642E6300000000BECEA100FFFFFFFF754A3A5C6164645F62795F7A68616E6770656E675C50726F6A6563745C534C554943455C536C756963655C474230564554785C67306231766574782D626F6172645C447269766572735C53544D3332473078785F48414C5F4472697665725C496E635C73746D3332673078785F68616C5F6465662E68000000001373746D3332673078785F68616C5F6465662E6800000000F0A0A100FFFFFFFF504A3A5C6164645F62795F7A68616E6770656E675C50726F6A6563745C534C554943455C536C756963655C474230564554785C67306231766574782D626F6172645C436F72655C5372635C6D61696E2E6300000000066D61696E2E6300000000BCA8E100FFFFFFFF5E4A3A5C6164645F62795F7A68616E6770656E675C50726F6A6563745C534C554943455C536C756963655C474230564554785C67306231766574782D626F6172645C4D444B2D41524D5C737461727475705F73746D33326730623178782E730000000015737461727475705F73746D33326730623178782E73000000009CC1B600FFFFFFFF794A3A5C6164645F62795F7A68616E6770656E675C50726F6A6563745C534C554943455C536C756963655C474230564554785C67306231766574782D626F6172645C4D6964646C6577617265735C54686972645F50617274795C5265616C5468726561645F52544F535C7372635C636F6D706F6E656E74732E63000000000C636F6D706F6E656E74732E6300000000F7B88600FFFFFFFF734A3A5C6164645F62795F7A68616E6770656E675C50726F6A6563745C534C554943455C536C756963655C474230564554785C67306231766574782D626F6172645C4D6964646C6577617265735C54686972645F50617274795C5265616C5468726561645F52544F535C7372635C69646C652E63000000000669646C652E6300000000D9ADC200FFFFFFFF514A3A5C6164645F62795F7A68616E6770656E675C50726F6A6563745C534C554943455C536C756963655C474230564554785C67306231766574782D626F6172645C436F72655C5372635C75736172742E63000000000775736172742E6300000000A5C2D700FFFFFFFF0100000010000000C5D4F200FFDC7800BECEA100F0A0A100BCA8E1009CC1B600F7B88600D9ADC200A5C2D700B3A6BE00EAD6A300F6FA7D00B5E99D005FC3CF00C1838300CACAD500010000000000000002000000C808000066000000000F0000D8020000 + 010000000400000001000000010000000100000001000000000000000200000000000000010000000100000000000000280000002800000001000000090000000400000001000000834A3A5C6164645F62795F7A68616E6770656E675C50726F6A6563745C534C554943455C536C756963655C474230564554785C67306231766574782D626F6172645C4D6964646C6577617265735C54686972645F50617274795C5265616C5468726561645F52544F535C636F6D706F6E656E74735C6465766963655C6465766963652E6300000000086465766963652E6300000000C5D4F200FFFFFFFF554A3A5C6164645F62795F7A68616E6770656E675C50726F6A6563745C534C554943455C536C756963655C474230564554785C67306231766574782D626F6172645C52542D5468726561645C7274636F6E6669672E68000000000A7274636F6E6669672E6800000000FFDC7800FFFFFFFF8C4A3A5C6164645F62795F7A68616E6770656E675C50726F6A6563745C534C554943455C536C756963655C474230564554785C67306231766574782D626F6172645C4D6964646C6577617265735C54686972645F50617274795C5265616C5468726561645F52544F535C6273705C5F74656D706C6174655C637562656D785F636F6E6669675C626F6172642E630000000007626F6172642E6300000000BECEA100FFFFFFFF754A3A5C6164645F62795F7A68616E6770656E675C50726F6A6563745C534C554943455C536C756963655C474230564554785C67306231766574782D626F6172645C447269766572735C53544D3332473078785F48414C5F4472697665725C496E635C73746D3332673078785F68616C5F6465662E68000000001373746D3332673078785F68616C5F6465662E6800000000F0A0A100FFFFFFFF504A3A5C6164645F62795F7A68616E6770656E675C50726F6A6563745C534C554943455C536C756963655C474230564554785C67306231766574782D626F6172645C436F72655C5372635C6D61696E2E6300000000066D61696E2E6300000000BCA8E100FFFFFFFF5E4A3A5C6164645F62795F7A68616E6770656E675C50726F6A6563745C534C554943455C536C756963655C474230564554785C67306231766574782D626F6172645C4D444B2D41524D5C737461727475705F73746D33326730623178782E730000000015737461727475705F73746D33326730623178782E73000000009CC1B600FFFFFFFF794A3A5C6164645F62795F7A68616E6770656E675C50726F6A6563745C534C554943455C536C756963655C474230564554785C67306231766574782D626F6172645C4D6964646C6577617265735C54686972645F50617274795C5265616C5468726561645F52544F535C7372635C636F6D706F6E656E74732E63000000000C636F6D706F6E656E74732E6300000000F7B88600FFFFFFFF734A3A5C6164645F62795F7A68616E6770656E675C50726F6A6563745C534C554943455C536C756963655C474230564554785C67306231766574782D626F6172645C4D6964646C6577617265735C54686972645F50617274795C5265616C5468726561645F52544F535C7372635C69646C652E63000000000669646C652E6300000000D9ADC200FFFFFFFF514A3A5C6164645F62795F7A68616E6770656E675C50726F6A6563745C534C554943455C536C756963655C474230564554785C67306231766574782D626F6172645C436F72655C5372635C75736172742E63000000000775736172742E6300000000A5C2D700FFFFFFFF0100000010000000C5D4F200FFDC7800BECEA100F0A0A100BCA8E1009CC1B600F7B88600D9ADC200A5C2D700B3A6BE00EAD6A300F6FA7D00B5E99D005FC3CF00C1838300CACAD500010000000000000002000000C808000066000000000F0000D0020000 @@ -146,7 +146,7 @@ 0 16 - 030000006600000041010000A8020000 + 030000006600000041010000A0020000 16 @@ -166,7 +166,7 @@ 0 16 - 030000006600000041010000A8020000 + 030000006600000041010000A0020000 16 @@ -446,7 +446,7 @@ 0 16 - 030000006600000041010000A8020000 + 030000006600000041010000A0020000 16 @@ -466,7 +466,7 @@ 0 16 - 030000006600000041010000A8020000 + 030000006600000041010000A0020000 16 @@ -486,7 +486,7 @@ 0 16 - 03000000DC0200007D070000CD030000 + 03000000D40200007D070000C5030000 16 @@ -526,7 +526,7 @@ 0 16 - 03000000DC0200007D070000CD030000 + 03000000D40200007D070000C5030000 16 @@ -1146,7 +1146,7 @@ 0 16 - 030000006600000041010000A8020000 + 030000006600000041010000A0020000 16 @@ -1166,7 +1166,7 @@ 0 16 - 03000000DC0200007D070000CD030000 + 03000000D40200007D070000C5030000 16 @@ -1186,7 +1186,7 @@ 0 16 - 03000000DC0200007D070000CD030000 + 03000000D40200007D070000C5030000 16 @@ -1246,7 +1246,7 @@ 0 16 - 03000000DC0200007D070000CD030000 + 03000000D40200007D070000C5030000 16 @@ -1266,7 +1266,7 @@ 0 16 - 03000000DC0200007D070000CD030000 + 03000000D40200007D070000C5030000 16 @@ -1726,7 +1726,7 @@ 0 16 - 00000000E603000080070000F9030000 + 00000000DE03000080070000F1030000 16 @@ -1795,14 +1795,14 @@ 3312 - 000000000B000000000000000020000000000000FFFFFFFFFFFFFFFFF4000000DF00000090050000E3000000000000000100000004000000010000000000000000000000FFFFFFFF08000000CB00000057010000CC000000F08B00005A01000079070000D601000045890000FFFF02000B004354616262656450616E6500200000000000007408000066000000100D0000F6000000F40000004F00000090050000DF0000000000000040280046080000000B446973617373656D626C7900000000CB00000001000000FFFFFFFFFFFFFFFF14506572666F726D616E636520416E616C797A6572000000005701000001000000FFFFFFFFFFFFFFFF14506572666F726D616E636520416E616C797A657200000000CC00000001000000FFFFFFFFFFFFFFFF0E4C6F67696320416E616C797A657200000000F08B000001000000FFFFFFFFFFFFFFFF0D436F646520436F766572616765000000005A01000001000000FFFFFFFFFFFFFFFF11496E737472756374696F6E205472616365000000007907000001000000FFFFFFFFFFFFFFFF0F53797374656D20416E616C797A657200000000D601000001000000FFFFFFFFFFFFFFFF104576656E742053746174697374696373000000004589000001000000FFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000000000000001000000FFFFFFFFCB00000001000000FFFFFFFFCB000000000000000040000000000000FFFFFFFFFFFFFFFF9C0400004F000000A004000029020000000000000200000004000000010000000000000000000000FFFFFFFF2B000000E2050000CA0900002D8C00002E8C00002F8C0000308C0000318C0000328C0000338C0000348C0000358C0000368C0000378C0000388C0000398C00003A8C00003B8C00003C8C00003D8C00003E8C00003F8C0000408C0000418C000050C3000051C3000052C3000053C3000054C3000055C3000056C3000057C3000058C3000059C300005AC300005BC300005CC300005DC300005EC300005FC3000060C3000061C3000062C3000063C3000001800040000000000000200C000066000000100D000040020000A00400004F000000900500002902000000000000404100462B0000000753796D626F6C7300000000E205000001000000FFFFFFFFFFFFFFFF0A5472616365204461746100000000CA09000001000000FFFFFFFFFFFFFFFF00000000002D8C000001000000FFFFFFFFFFFFFFFF00000000002E8C000001000000FFFFFFFFFFFFFFFF00000000002F8C000001000000FFFFFFFFFFFFFFFF0000000000308C000001000000FFFFFFFFFFFFFFFF0000000000318C000001000000FFFFFFFFFFFFFFFF0000000000328C000001000000FFFFFFFFFFFFFFFF0000000000338C000001000000FFFFFFFFFFFFFFFF0000000000348C000001000000FFFFFFFFFFFFFFFF0000000000358C000001000000FFFFFFFFFFFFFFFF0000000000368C000001000000FFFFFFFFFFFFFFFF0000000000378C000001000000FFFFFFFFFFFFFFFF0000000000388C000001000000FFFFFFFFFFFFFFFF0000000000398C000001000000FFFFFFFFFFFFFFFF00000000003A8C000001000000FFFFFFFFFFFFFFFF00000000003B8C000001000000FFFFFFFFFFFFFFFF00000000003C8C000001000000FFFFFFFFFFFFFFFF00000000003D8C000001000000FFFFFFFFFFFFFFFF00000000003E8C000001000000FFFFFFFFFFFFFFFF00000000003F8C000001000000FFFFFFFFFFFFFFFF0000000000408C000001000000FFFFFFFFFFFFFFFF0000000000418C000001000000FFFFFFFFFFFFFFFF000000000050C3000001000000FFFFFFFFFFFFFFFF000000000051C3000001000000FFFFFFFFFFFFFFFF000000000052C3000001000000FFFFFFFFFFFFFFFF000000000053C3000001000000FFFFFFFFFFFFFFFF000000000054C3000001000000FFFFFFFFFFFFFFFF000000000055C3000001000000FFFFFFFFFFFFFFFF000000000056C3000001000000FFFFFFFFFFFFFFFF000000000057C3000001000000FFFFFFFFFFFFFFFF000000000058C3000001000000FFFFFFFFFFFFFFFF000000000059C3000001000000FFFFFFFFFFFFFFFF00000000005AC3000001000000FFFFFFFFFFFFFFFF00000000005BC3000001000000FFFFFFFFFFFFFFFF00000000005CC3000001000000FFFFFFFFFFFFFFFF00000000005DC3000001000000FFFFFFFFFFFFFFFF00000000005EC3000001000000FFFFFFFFFFFFFFFF00000000005FC3000001000000FFFFFFFFFFFFFFFF000000000060C3000001000000FFFFFFFFFFFFFFFF000000000061C3000001000000FFFFFFFFFFFFFFFF000000000062C3000001000000FFFFFFFFFFFFFFFF000000000063C3000001000000FFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000000000000001000000FFFFFFFFE205000001000000FFFFFFFFE2050000000000000010000001000000FFFFFFFFFFFFFFFF440100004F00000048010000C102000001000000020000100400000001000000C7FEFFFF3C060000FFFFFFFF05000000ED0300006D000000C3000000C400000073940000018000100000010000008007000066000000C4080000D8020000000000004F00000044010000C10200000000000040410056050000000750726F6A65637401000000ED03000001000000FFFFFFFFFFFFFFFF05426F6F6B73010000006D00000001000000FFFFFFFFFFFFFFFF0946756E6374696F6E7301000000C300000001000000FFFFFFFFFFFFFFFF0954656D706C6174657301000000C400000001000000FFFFFFFFFFFFFFFF09526567697374657273000000007394000001000000FFFFFFFFFFFFFFFF00000000000000000000000000000000000000000000000001000000FFFFFFFFED03000001000000FFFFFFFFED030000000000000080000000000000FFFFFFFFFFFFFFFF0000000015020000900500001902000000000000010000000400000001000000000000000000000000000000000000000000000001000000C6000000FFFFFFFF0F0000008F070000930700009407000095070000960700009007000091070000B5010000B801000038030000B9050000BA050000BB050000BC050000CB090000018000800000000000008007000030020000100D0000D4020000000000001902000090050000BD02000000000000404100460F0000001343616C6C20537461636B202B204C6F63616C73000000008F07000001000000FFFFFFFFFFFFFFFF0755415254202331000000009307000001000000FFFFFFFFFFFFFFFF0755415254202332000000009407000001000000FFFFFFFFFFFFFFFF0755415254202333000000009507000001000000FFFFFFFFFFFFFFFF15446562756720287072696E74662920566965776572000000009607000001000000FFFFFFFFFFFFFFFF0757617463682031000000009007000001000000FFFFFFFFFFFFFFFF0757617463682032000000009107000001000000FFFFFFFFFFFFFFFF10547261636520457863657074696F6E7300000000B501000001000000FFFFFFFFFFFFFFFF0E4576656E7420436F756E7465727300000000B801000001000000FFFFFFFFFFFFFFFF09554C494E4B706C7573000000003803000001000000FFFFFFFFFFFFFFFF084D656D6F7279203100000000B905000001000000FFFFFFFFFFFFFFFF084D656D6F7279203200000000BA05000001000000FFFFFFFFFFFFFFFF084D656D6F7279203300000000BB05000001000000FFFFFFFFFFFFFFFF084D656D6F7279203400000000BC05000001000000FFFFFFFFFFFFFFFF105472616365204E617669676174696F6E00000000CB09000001000000FFFFFFFFFFFFFFFFFFFFFFFF0000000001000000000000000000000001000000FFFFFFFFC802000019020000CC020000BD02000000000000020000000400000000000000000000000000000000000000000000000000000002000000C6000000FFFFFFFF8F07000001000000FFFFFFFF8F07000001000000C6000000000000000080000001000000FFFFFFFFFFFFFFFF00000000C102000080070000C5020000010000000100001004000000010000004CFDFFFF8E000000FFFFFFFF06000000C5000000C7000000B4010000D2010000CF010000779400000180008000000100000080070000DC020000000F0000FD03000000000000C502000080070000E60300000000000040820056060000000C4275696C64204F757470757401000000C500000001000000FFFFFFFFFFFFFFFF0D46696E6420496E2046696C657301000000C700000001000000FFFFFFFFFFFFFFFF0A4572726F72204C69737400000000B401000001000000FFFFFFFFFFFFFFFF0E536F757263652042726F7773657200000000D201000001000000FFFFFFFFFFFFFFFF0E416C6C205265666572656E63657300000000CF01000001000000FFFFFFFFFFFFFFFF0742726F77736572010000007794000001000000FFFFFFFFFFFFFFFF00000000000000000000000000000000000000000000000001000000FFFFFFFFC500000001000000FFFFFFFFC5000000000000000000000000000000 + 000000000B000000000000000020000000000000FFFFFFFFFFFFFFFFF4000000DF00000090050000E3000000000000000100000004000000010000000000000000000000FFFFFFFF08000000CB00000057010000CC000000F08B00005A01000079070000D601000045890000FFFF02000B004354616262656450616E6500200000000000007408000066000000100D0000F6000000F40000004F00000090050000DF0000000000000040280046080000000B446973617373656D626C7900000000CB00000001000000FFFFFFFFFFFFFFFF14506572666F726D616E636520416E616C797A6572000000005701000001000000FFFFFFFFFFFFFFFF14506572666F726D616E636520416E616C797A657200000000CC00000001000000FFFFFFFFFFFFFFFF0E4C6F67696320416E616C797A657200000000F08B000001000000FFFFFFFFFFFFFFFF0D436F646520436F766572616765000000005A01000001000000FFFFFFFFFFFFFFFF11496E737472756374696F6E205472616365000000007907000001000000FFFFFFFFFFFFFFFF0F53797374656D20416E616C797A657200000000D601000001000000FFFFFFFFFFFFFFFF104576656E742053746174697374696373000000004589000001000000FFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000000000000001000000FFFFFFFFCB00000001000000FFFFFFFFCB000000000000000040000000000000FFFFFFFFFFFFFFFF9C0400004F000000A004000029020000000000000200000004000000010000000000000000000000FFFFFFFF2B000000E2050000CA0900002D8C00002E8C00002F8C0000308C0000318C0000328C0000338C0000348C0000358C0000368C0000378C0000388C0000398C00003A8C00003B8C00003C8C00003D8C00003E8C00003F8C0000408C0000418C000050C3000051C3000052C3000053C3000054C3000055C3000056C3000057C3000058C3000059C300005AC300005BC300005CC300005DC300005EC300005FC3000060C3000061C3000062C3000063C3000001800040000000000000200C000066000000100D000040020000A00400004F000000900500002902000000000000404100462B0000000753796D626F6C7300000000E205000001000000FFFFFFFFFFFFFFFF0A5472616365204461746100000000CA09000001000000FFFFFFFFFFFFFFFF00000000002D8C000001000000FFFFFFFFFFFFFFFF00000000002E8C000001000000FFFFFFFFFFFFFFFF00000000002F8C000001000000FFFFFFFFFFFFFFFF0000000000308C000001000000FFFFFFFFFFFFFFFF0000000000318C000001000000FFFFFFFFFFFFFFFF0000000000328C000001000000FFFFFFFFFFFFFFFF0000000000338C000001000000FFFFFFFFFFFFFFFF0000000000348C000001000000FFFFFFFFFFFFFFFF0000000000358C000001000000FFFFFFFFFFFFFFFF0000000000368C000001000000FFFFFFFFFFFFFFFF0000000000378C000001000000FFFFFFFFFFFFFFFF0000000000388C000001000000FFFFFFFFFFFFFFFF0000000000398C000001000000FFFFFFFFFFFFFFFF00000000003A8C000001000000FFFFFFFFFFFFFFFF00000000003B8C000001000000FFFFFFFFFFFFFFFF00000000003C8C000001000000FFFFFFFFFFFFFFFF00000000003D8C000001000000FFFFFFFFFFFFFFFF00000000003E8C000001000000FFFFFFFFFFFFFFFF00000000003F8C000001000000FFFFFFFFFFFFFFFF0000000000408C000001000000FFFFFFFFFFFFFFFF0000000000418C000001000000FFFFFFFFFFFFFFFF000000000050C3000001000000FFFFFFFFFFFFFFFF000000000051C3000001000000FFFFFFFFFFFFFFFF000000000052C3000001000000FFFFFFFFFFFFFFFF000000000053C3000001000000FFFFFFFFFFFFFFFF000000000054C3000001000000FFFFFFFFFFFFFFFF000000000055C3000001000000FFFFFFFFFFFFFFFF000000000056C3000001000000FFFFFFFFFFFFFFFF000000000057C3000001000000FFFFFFFFFFFFFFFF000000000058C3000001000000FFFFFFFFFFFFFFFF000000000059C3000001000000FFFFFFFFFFFFFFFF00000000005AC3000001000000FFFFFFFFFFFFFFFF00000000005BC3000001000000FFFFFFFFFFFFFFFF00000000005CC3000001000000FFFFFFFFFFFFFFFF00000000005DC3000001000000FFFFFFFFFFFFFFFF00000000005EC3000001000000FFFFFFFFFFFFFFFF00000000005FC3000001000000FFFFFFFFFFFFFFFF000000000060C3000001000000FFFFFFFFFFFFFFFF000000000061C3000001000000FFFFFFFFFFFFFFFF000000000062C3000001000000FFFFFFFFFFFFFFFF000000000063C3000001000000FFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000000000000001000000FFFFFFFFE205000001000000FFFFFFFFE2050000000000000010000001000000FFFFFFFFFFFFFFFF440100004F00000048010000B902000001000000020000100400000001000000C7FEFFFF3C060000FFFFFFFF05000000ED0300006D000000C3000000C400000073940000018000100000010000008007000066000000C4080000D0020000000000004F00000044010000B90200000000000040410056050000000750726F6A65637401000000ED03000001000000FFFFFFFFFFFFFFFF05426F6F6B73010000006D00000001000000FFFFFFFFFFFFFFFF0946756E6374696F6E7301000000C300000001000000FFFFFFFFFFFFFFFF0954656D706C6174657301000000C400000001000000FFFFFFFFFFFFFFFF09526567697374657273000000007394000001000000FFFFFFFFFFFFFFFF00000000000000000000000000000000000000000000000001000000FFFFFFFFED03000001000000FFFFFFFFED030000000000000080000000000000FFFFFFFFFFFFFFFF0000000015020000900500001902000000000000010000000400000001000000000000000000000000000000000000000000000001000000C6000000FFFFFFFF0F0000008F070000930700009407000095070000960700009007000091070000B5010000B801000038030000B9050000BA050000BB050000BC050000CB090000018000800000000000008007000030020000100D0000D4020000000000001902000090050000BD02000000000000404100460F0000001343616C6C20537461636B202B204C6F63616C73000000008F07000001000000FFFFFFFFFFFFFFFF0755415254202331000000009307000001000000FFFFFFFFFFFFFFFF0755415254202332000000009407000001000000FFFFFFFFFFFFFFFF0755415254202333000000009507000001000000FFFFFFFFFFFFFFFF15446562756720287072696E74662920566965776572000000009607000001000000FFFFFFFFFFFFFFFF0757617463682031000000009007000001000000FFFFFFFFFFFFFFFF0757617463682032000000009107000001000000FFFFFFFFFFFFFFFF10547261636520457863657074696F6E7300000000B501000001000000FFFFFFFFFFFFFFFF0E4576656E7420436F756E7465727300000000B801000001000000FFFFFFFFFFFFFFFF09554C494E4B706C7573000000003803000001000000FFFFFFFFFFFFFFFF084D656D6F7279203100000000B905000001000000FFFFFFFFFFFFFFFF084D656D6F7279203200000000BA05000001000000FFFFFFFFFFFFFFFF084D656D6F7279203300000000BB05000001000000FFFFFFFFFFFFFFFF084D656D6F7279203400000000BC05000001000000FFFFFFFFFFFFFFFF105472616365204E617669676174696F6E00000000CB09000001000000FFFFFFFFFFFFFFFFFFFFFFFF0000000001000000000000000000000001000000FFFFFFFFC802000019020000CC020000BD02000000000000020000000400000000000000000000000000000000000000000000000000000002000000C6000000FFFFFFFF8F07000001000000FFFFFFFF8F07000001000000C6000000000000000080000001000000FFFFFFFFFFFFFFFF00000000B902000080070000BD020000010000000100001004000000010000004CFDFFFF8E000000FFFFFFFF06000000C5000000C7000000B4010000D2010000CF010000779400000180008000000100000080070000D4020000000F0000F503000000000000BD02000080070000DE0300000000000040820056060000000C4275696C64204F757470757401000000C500000001000000FFFFFFFFFFFFFFFF0D46696E6420496E2046696C657301000000C700000001000000FFFFFFFFFFFFFFFF0A4572726F72204C69737400000000B401000001000000FFFFFFFFFFFFFFFF0E536F757263652042726F7773657200000000D201000001000000FFFFFFFFFFFFFFFF0E416C6C205265666572656E63657300000000CF01000001000000FFFFFFFFFFFFFFFF0742726F77736572010000007794000001000000FFFFFFFFFFFFFFFF00000000000000000000000000000000000000000000000001000000FFFFFFFFC500000001000000FFFFFFFFC5000000000000000000000000000000 59392 File - 2878 - 00200000010000002800FFFF01001100434D4643546F6F6C426172427574746F6E00E100000000000000000000000000000000000000000000000100000001000000018001E100000000000001000000000000000000000000000000000100000001000000018003E1000000000000020000000000000000000000000000000001000000010000000180CD7F0000000000000300000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018023E100000000040004000000000000000000000000000000000100000001000000018022E100000000040005000000000000000000000000000000000100000001000000018025E10000000000000600000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001802BE10000000004000700000000000000000000000000000000010000000100000001802CE10000000004000800000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001807A8A0000000000000900000000000000000000000000000000010000000100000001807B8A0000000004000A00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180D3B00000000000000B000000000000000000000000000000000100000001000000018015B10000000004000C0000000000000000000000000000000001000000010000000180F4B00000000004000D000000000000000000000000000000000100000001000000018036B10000000004000E00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180FF88000000000400460000000000000000000000000000000001000000010000000180FE880000000004004500000000000000000000000000000000010000000100000001800B810000000004001300000000000000000000000000000000010000000100000001800C810000000004001400000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180F0880000020000000F000000000000000000000000000000000100000001000000FFFF0100120043555646696E64436F6D626F427574746F6EE803000000000000000000000000000000000000000000000001000000010000009600000002002050000000000A4465766963654C696E6B960000000000000013000A4465766963654C696E6B096C696E6B54696D657204D0C4CCF80A6754436F6D6D4D61696C0D50616B63657454696D657255700F4D41494C5F534C554943455F4F50540C75343835325F7468726561641445465F454E565F5553494E475F574C5F4D4F44450F534655445F44454255475F4D4F44450557617465720F6F6E6C696E655F6961705F7461736B0D6961705F66696C655F73697A650B6961705F66696C656E616D074949435F53434C1065665F65726173655F62616B5F6170701172745F656E7465725F637269746963616C0C4D585F554152545F496E6974164F535F4941505F5448524541445F5052494F524954590A675F6966636F6E66696700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018024E10000000000001100000000000000000000000000000000010000000100000001800A810000000000001200000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000FFFF01001500434D4643546F6F6C4261724D656E75427574746F6E2280000002000000150000002153746172742F53746F70202644656275672053657373696F6E094374726C2B46350000000000000000000000000100000001000000000000000000000001000000020021802280000000000000150000002153746172742F53746F70202644656275672053657373696F6E094374726C2B4635000000000000000000000000010000000100000000000000000000000100000000002180E0010000000000007500000021456E65726779204D6561737572656D656E742026776974686F75742044656275670000000000000000000000000100000001000000000000000000000001000000000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180C488000000000000160000000000000000000000000000000001000000010000000180C988000000000400180000000000000000000000000000000001000000010000000180C788000000000000190000000000000000000000000000000001000000010000002180C8880000000000001700000027264B696C6C20416C6C20427265616B706F696E747320696E2043757272656E7420546172676574000000000000000000000000010000000100000000000000000000000100000003002180C8880000000000001700000027264B696C6C20416C6C20427265616B706F696E747320696E2043757272656E7420546172676574000000000000000000000000010000000100000000000000000000000100000000002180E50100000000000078000000264B696C6C20416C6C20427265616B706F696E747320696E204163746976652050726F6A656374000000000000000000000000010000000100000000000000000000000100000000002180E601000000000000790000002F4B696C6C20416C6C20427265616B706F696E747320696E204D756C74692D50726F6A65637420576F726B73706163650000000000000000000000000100000001000000000000000000000001000000000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000021804C010000020001001A0000000F2650726F6A6563742057696E646F77000000000000000000000000010000000100000000000000000000000100000008002180DD880000000000001A0000000750726F6A656374000000000000000000000000010000000100000000000000000000000100000000002180DC8B0000000000003A00000005426F6F6B73000000000000000000000000010000000100000000000000000000000100000000002180E18B0000000000003B0000000946756E6374696F6E73000000000000000000000000010000000100000000000000000000000100000000002180E28B000000000000400000000954656D706C6174657300000000000000000000000001000000010000000000000000000000010000000000218018890000000000003D0000000E536F757263652042726F777365720000000000000000000000000100000001000000000000000000000001000000000021800000000000000400FFFFFFFF00000000000000000001000000000000000100000000000000000000000100000000002180D988000000000000390000000C4275696C64204F7574707574000000000000000000000000010000000100000000000000000000000100000000002180E38B000000000000410000000B46696E64204F75747075740000000000000000000000000100000001000000000000000000000001000000000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180FB7F0000000000001B000000000000000000000000000000000100000001000000000000000446696C65EE010000 + 2873 + 00200000010000002800FFFF01001100434D4643546F6F6C426172427574746F6E00E100000000000000000000000000000000000000000000000100000001000000018001E100000000000001000000000000000000000000000000000100000001000000018003E1000000000000020000000000000000000000000000000001000000010000000180CD7F0000000000000300000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018023E100000000040004000000000000000000000000000000000100000001000000018022E100000000040005000000000000000000000000000000000100000001000000018025E10000000000000600000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001802BE10000000004000700000000000000000000000000000000010000000100000001802CE10000000004000800000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001807A8A0000000004000900000000000000000000000000000000010000000100000001807B8A0000000004000A00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180D3B00000000000000B000000000000000000000000000000000100000001000000018015B10000000004000C0000000000000000000000000000000001000000010000000180F4B00000000004000D000000000000000000000000000000000100000001000000018036B10000000004000E00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180FF88000000000400460000000000000000000000000000000001000000010000000180FE880000000004004500000000000000000000000000000000010000000100000001800B810000000004001300000000000000000000000000000000010000000100000001800C810000000004001400000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180F0880000020000000F000000000000000000000000000000000100000001000000FFFF0100120043555646696E64436F6D626F427574746F6EE8030000000000000000000000000000000000000000000000010000000100000096000000020020500000000007436865636B52549600000000000000140007436865636B525401420B4669785F52616D2E4B76320B4669785F52616D2E4B7630074669785F52616D0646697852616D0B57617465725F77726974651373765F656570726F6D5F6F7065726174696F6E1943756D756C61746976655F57617465725F4261636B776172640C4170704D6F64654465627567165343422D3E56544F52203D20464C4153485F4241534510434F4C4C454354494F4E5F54494D45520C464C4F575F53554D5F4D415804393939390973343835327479706504594731390B4D41494C5F43545F4F50540B736C756963655F6F70656E10555345525F4A534F4E5F5041434B45540E5061636B657455705265676973740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018024E10000000000001100000000000000000000000000000000010000000100000001800A810000000000001200000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000FFFF01001500434D4643546F6F6C4261724D656E75427574746F6E2280000002000000150000002153746172742F53746F70202644656275672053657373696F6E094374726C2B46350000000000000000000000000100000001000000000000000000000001000000020021802280000000000000150000002153746172742F53746F70202644656275672053657373696F6E094374726C2B4635000000000000000000000000010000000100000000000000000000000100000000002180E0010000000000007500000021456E65726779204D6561737572656D656E742026776974686F75742044656275670000000000000000000000000100000001000000000000000000000001000000000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180C488000000000000160000000000000000000000000000000001000000010000000180C988000000000400180000000000000000000000000000000001000000010000000180C788000000000000190000000000000000000000000000000001000000010000002180C8880000000000001700000027264B696C6C20416C6C20427265616B706F696E747320696E2043757272656E7420546172676574000000000000000000000000010000000100000000000000000000000100000003002180C8880000000000001700000027264B696C6C20416C6C20427265616B706F696E747320696E2043757272656E7420546172676574000000000000000000000000010000000100000000000000000000000100000000002180E50100000000000078000000264B696C6C20416C6C20427265616B706F696E747320696E204163746976652050726F6A656374000000000000000000000000010000000100000000000000000000000100000000002180E601000000000000790000002F4B696C6C20416C6C20427265616B706F696E747320696E204D756C74692D50726F6A65637420576F726B73706163650000000000000000000000000100000001000000000000000000000001000000000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000021804C010000020001001A0000000F2650726F6A6563742057696E646F77000000000000000000000000010000000100000000000000000000000100000008002180DD880000000000001A0000000750726F6A656374000000000000000000000000010000000100000000000000000000000100000000002180DC8B0000000000003A00000005426F6F6B73000000000000000000000000010000000100000000000000000000000100000000002180E18B0000000000003B0000000946756E6374696F6E73000000000000000000000000010000000100000000000000000000000100000000002180E28B000000000000400000000954656D706C6174657300000000000000000000000001000000010000000000000000000000010000000000218018890000000000003D0000000E536F757263652042726F777365720000000000000000000000000100000001000000000000000000000001000000000021800000000000000400FFFFFFFF00000000000000000001000000000000000100000000000000000000000100000000002180D988000000000000390000000C4275696C64204F7574707574000000000000000000000000010000000100000000000000000000000100000000002180E38B000000000000410000000B46696E64204F75747075740000000000000000000000000100000001000000000000000000000001000000000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180FB7F0000000000001B000000000000000000000000000000000100000001000000000000000446696C65EE010000 1423 @@ -3638,9 +3638,9 @@ ../Core/Src/main.c - 25 - 199 - 207 + 1 + 178 + 190 1 0 @@ -3674,7 +3674,7 @@ ../Core/Src/usart.c - 4 + 22 97 98 1 diff --git a/Middlewares/Third_Party/RealThread_RTOS/components/device/alarm.c b/Middlewares/Third_Party/RealThread_RTOS/components/device/alarm.c new file mode 100644 index 0000000..4fa53db --- /dev/null +++ b/Middlewares/Third_Party/RealThread_RTOS/components/device/alarm.c @@ -0,0 +1,609 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2012-10-27 heyuanjie87 first version. + * 2013-05-17 aozima initial alarm event & mutex in system init. + */ + +#include +#include + +#define RT_RTC_YEARS_MAX 137 +#define RT_ALARM_DELAY 2 +#define RT_ALARM_STATE_INITED 0x02 +#define RT_ALARM_STATE_START 0x01 +#define RT_ALARM_STATE_STOP 0x00 + +#if (defined(RT_USING_RTC) && defined(RT_USING_ALARM)) +static struct rt_alarm_container _container; + +rt_inline rt_uint32_t alarm_mkdaysec(struct tm *time) +{ + rt_uint32_t sec; + + sec = time->tm_sec; + sec += time->tm_min * 60; + sec += time->tm_hour * 3600; + + return (sec); +} + +static rt_err_t alarm_set(struct rt_alarm *alarm) +{ + rt_device_t device; + struct rt_rtc_wkalarm wkalarm; + rt_err_t ret; + + device = rt_device_find("rtc"); + if (device == RT_NULL) + { + return (RT_ERROR); + } + if (alarm->flag & RT_ALARM_STATE_START) + wkalarm.enable = RT_TRUE; + else + wkalarm.enable = RT_FALSE; + + wkalarm.tm_sec = alarm->wktime.tm_sec; + wkalarm.tm_min = alarm->wktime.tm_min; + wkalarm.tm_hour = alarm->wktime.tm_hour; + + ret = rt_device_control(device, RT_DEVICE_CTRL_RTC_SET_ALARM, &wkalarm); + if ((ret == RT_EOK) && wkalarm.enable) + { + ret = rt_device_control(device, RT_DEVICE_CTRL_RTC_GET_ALARM, &wkalarm); + if (ret == RT_EOK) + { + /* + some RTC device like RX8025,it's alarms precision is 1 minute. + in this case,low level RTC driver should set wkalarm->tm_sec to 0. + */ + alarm->wktime.tm_sec = wkalarm.tm_sec; + alarm->wktime.tm_min = wkalarm.tm_min; + alarm->wktime.tm_hour = wkalarm.tm_hour; + } + } + + return (ret); +} + +static void alarm_wakeup(struct rt_alarm *alarm, struct tm *now) +{ + rt_uint32_t sec_alarm, sec_now; + rt_bool_t wakeup = RT_FALSE; + time_t timestamp; + + sec_alarm = alarm_mkdaysec(&alarm->wktime); + sec_now = alarm_mkdaysec(now); + + if (alarm->flag & RT_ALARM_STATE_START) + { + switch (alarm->flag & 0xFF00) + { + case RT_ALARM_ONESHOT: + { + sec_alarm = mktime(&alarm->wktime); + sec_now = mktime(now); + if (((sec_now - sec_alarm) <= RT_ALARM_DELAY) && (sec_now >= sec_alarm)) + { + /* stop alarm */ + alarm->flag &= ~RT_ALARM_STATE_START; + alarm_set(alarm); + wakeup = RT_TRUE; + } + } + break; + case RT_ALARM_DAILY: + { + if (((sec_now - sec_alarm) <= RT_ALARM_DELAY) && (sec_now >= sec_alarm)) + wakeup = RT_TRUE; + } + break; + case RT_ALARM_WEEKLY: + { + /* alarm at wday */ + sec_alarm += alarm->wktime.tm_wday * 24 * 3600; + sec_now += now->tm_wday * 24 * 3600; + + if (((sec_now - sec_alarm) <= RT_ALARM_DELAY) && (sec_now >= sec_alarm)) + wakeup = RT_TRUE; + } + break; + case RT_ALARM_MONTHLY: + { + /* monthly someday generate alarm signals */ + if (alarm->wktime.tm_mday == now->tm_mday) + { + if ((sec_now - sec_alarm) <= RT_ALARM_DELAY) + wakeup = RT_TRUE; + } + } + break; + case RT_ALARM_YAERLY: + { + if ((alarm->wktime.tm_mday == now->tm_mday) && \ + (alarm->wktime.tm_mon == now->tm_mon)) + { + if ((sec_now - sec_alarm) <= RT_ALARM_DELAY) + wakeup = RT_TRUE; + } + } + break; + } + + if ((wakeup == RT_TRUE) && (alarm->callback != RT_NULL)) + { + timestamp = time(RT_NULL); + alarm->callback(alarm, timestamp); + } + } +} + +static void alarm_update(rt_uint32_t event) +{ + struct rt_alarm *alm_prev = RT_NULL, *alm_next = RT_NULL; + struct rt_alarm *alarm; + rt_int32_t sec_now, sec_alarm, sec_tmp; + rt_int32_t sec_next = 24 * 3600, sec_prev = 0; + time_t timestamp; + struct tm now; + rt_list_t *next; + + rt_mutex_take(&_container.mutex, RT_WAITING_FOREVER); + if (!rt_list_isempty(&_container.head)) + { + /* get time of now */ + timestamp = time(RT_NULL); + localtime_r(×tamp, &now); + + for (next = _container.head.next; next != &_container.head; next = next->next) + { + alarm = rt_list_entry(next, struct rt_alarm, list); + /* check the overtime alarm */ + alarm_wakeup(alarm, &now); + } + + timestamp = time(RT_NULL); + localtime_r(×tamp, &now); + sec_now = alarm_mkdaysec(&now); + + for (next = _container.head.next; next != &_container.head; next = next->next) + { + alarm = rt_list_entry(next, struct rt_alarm, list); + /* calculate seconds from 00:00:00 */ + sec_alarm = alarm_mkdaysec(&alarm->wktime); + + if ((alarm->flag & RT_ALARM_STATE_START) && (alarm != _container.current)) + { + sec_tmp = sec_alarm - sec_now; + if (sec_tmp > 0) + { + /* find alarm after now(now to 23:59:59) and the most recent */ + if (sec_tmp < sec_next) + { + sec_next = sec_tmp; + alm_next = alarm; + } + } + else + { + /* find alarm before now(00:00:00 to now) and furthest from now */ + if (sec_tmp < sec_prev) + { + sec_prev = sec_tmp; + alm_prev = alarm; + } + } + } + } + /* enable the alarm after now first */ + if (sec_next < 24 * 3600) + { + if (alarm_set(alm_next) == RT_EOK) + _container.current = alm_next; + } + else if (sec_prev < 0) + { + /* enable the alarm before now */ + if (alarm_set(alm_prev) == RT_EOK) + _container.current = alm_prev; + } + } + rt_mutex_release(&_container.mutex); +} + +static rt_uint32_t days_of_year_month(int tm_year, int tm_mon) +{ + rt_uint32_t ret, year; + + year = tm_year + 1900; + if (tm_mon == 1) + { + ret = 28 + ((!(year % 4) && (year % 100)) || !(year % 400)); + } + else if (((tm_mon <= 6) && (tm_mon % 2 == 0)) || ((tm_mon > 6) && (tm_mon % 2 == 1))) + { + ret = 31; + } + else + { + ret = 30; + } + + return (ret); +} + +static rt_bool_t is_valid_date(struct tm *date) +{ + if ((date->tm_year < 0) || (date->tm_year > RT_RTC_YEARS_MAX)) + { + return (RT_FALSE); + } + + if ((date->tm_mon < 0) || (date->tm_mon > 11)) + { + return (RT_FALSE); + } + + if ((date->tm_mday < 1) || \ + (date->tm_mday > days_of_year_month(date->tm_year, date->tm_mon))) + { + return (RT_FALSE); + } + + return (RT_TRUE); +} + +static rt_err_t alarm_setup(rt_alarm_t alarm, struct tm *wktime) +{ + rt_err_t ret = RT_ERROR; + time_t timestamp; + struct tm *setup, now; + + setup = &alarm->wktime; + *setup = *wktime; + timestamp = time(RT_NULL); + localtime_r(×tamp, &now); + + /* if these are a "don't care" value,we set them to now*/ + if ((setup->tm_sec > 59) || (setup->tm_sec < 0)) + setup->tm_sec = now.tm_sec; + if ((setup->tm_min > 59) || (setup->tm_min < 0)) + setup->tm_min = now.tm_min; + if ((setup->tm_hour > 23) || (setup->tm_hour < 0)) + setup->tm_hour = now.tm_hour; + + switch (alarm->flag & 0xFF00) + { + case RT_ALARM_DAILY: + { + /* do nothing but needed */ + } + break; + case RT_ALARM_ONESHOT: + { + /* if these are "don't care" value we set them to now */ + if (setup->tm_year == RT_ALARM_TM_NOW) + setup->tm_year = now.tm_year; + if (setup->tm_mon == RT_ALARM_TM_NOW) + setup->tm_mon = now.tm_mon; + if (setup->tm_mday == RT_ALARM_TM_NOW) + setup->tm_mday = now.tm_mday; + /* make sure the setup is valid */ + if (!is_valid_date(setup)) + goto _exit; + } + break; + case RT_ALARM_WEEKLY: + { + /* if tm_wday is a "don't care" value we set it to now */ + if ((setup->tm_wday < 0) || (setup->tm_wday > 6)) + setup->tm_wday = now.tm_wday; + } + break; + case RT_ALARM_MONTHLY: + { + /* if tm_mday is a "don't care" value we set it to now */ + if ((setup->tm_mday < 1) || (setup->tm_mday > 31)) + setup->tm_mday = now.tm_mday; + } + break; + case RT_ALARM_YAERLY: + { + /* if tm_mon is a "don't care" value we set it to now */ + if ((setup->tm_mon < 0) || (setup->tm_mon > 11)) + setup->tm_mon = now.tm_mon; + + if (setup->tm_mon == 1) + { + /* tm_mon is February */ + + /* tm_mday should be 1~29.otherwise,it's a "don't care" value */ + if ((setup->tm_mday < 1) || (setup->tm_mday > 29)) + setup->tm_mday = now.tm_mday; + } + else if (((setup->tm_mon <= 6) && (setup->tm_mon % 2 == 0)) || \ + ((setup->tm_mon > 6) && (setup->tm_mon % 2 == 1))) + { + /* Jan,Mar,May,Jul,Aug,Oct,Dec */ + + /* tm_mday should be 1~31.otherwise,it's a "don't care" value */ + if ((setup->tm_mday < 1) || (setup->tm_mday > 31)) + setup->tm_mday = now.tm_mday; + } + else + { + /* tm_mday should be 1~30.otherwise,it's a "don't care" value */ + if ((setup->tm_mday < 1) || (setup->tm_mday > 30)) + setup->tm_mday = now.tm_mday; + } + } + break; + default: + { + goto _exit; + } + } + + if ((setup->tm_hour == 23) && (setup->tm_min == 59) && (setup->tm_sec == 59)) + { + /* + for insurance purposes, we will generate an alarm + signal two seconds ahead of. + */ + setup->tm_sec = 60 - RT_ALARM_DELAY; + } + /* set initialized state */ + alarm->flag |= RT_ALARM_STATE_INITED; + ret = RT_EOK; + +_exit: + + return (ret); +} + +/** \brief send a rtc alarm event + * + * \param dev pointer to RTC device(currently unused,you can ignore it) + * \param event RTC event(currently unused) + * \return none + */ +void rt_alarm_update(rt_device_t dev, rt_uint32_t event) +{ + rt_event_send(&_container.event, 1); +} + +/** \brief modify the alarm setup + * + * \param alarm pointer to alarm + * \param cmd control command + * \param arg argument + */ +rt_err_t rt_alarm_control(rt_alarm_t alarm, int cmd, void *arg) +{ + rt_err_t ret = RT_ERROR; + + RT_ASSERT(alarm != RT_NULL); + + rt_mutex_take(&_container.mutex, RT_WAITING_FOREVER); + switch (cmd) + { + case RT_ALARM_CTRL_MODIFY: + { + struct rt_alarm_setup *setup; + + RT_ASSERT(arg != RT_NULL); + setup = arg; + rt_alarm_stop(alarm); + alarm->flag = setup->flag & 0xFF00; + alarm->wktime = setup->wktime; + ret = alarm_setup(alarm, &alarm->wktime); + } + break; + } + + rt_mutex_release(&_container.mutex); + + return (ret); +} + +/** \brief start an alarm + * + * \param alarm pointer to alarm + * \return RT_EOK + */ +rt_err_t rt_alarm_start(rt_alarm_t alarm) +{ + rt_int32_t sec_now, sec_old, sec_new; + rt_err_t ret = RT_ERROR; + time_t timestamp; + struct tm now; + + if (alarm == RT_NULL) + return (ret); + rt_mutex_take(&_container.mutex, RT_WAITING_FOREVER); + if (!(alarm->flag & RT_ALARM_STATE_INITED)) + { + if (alarm_setup(alarm, &alarm->wktime) != RT_EOK) + goto _exit; + } + if ((alarm->flag & 0x01) == RT_ALARM_STATE_STOP) + { + timestamp = time(RT_NULL); + localtime_r(×tamp, &now); + + alarm->flag |= RT_ALARM_STATE_START; + /* set alarm */ + if (_container.current == RT_NULL) + { + ret = alarm_set(alarm); + } + else + { + sec_now = alarm_mkdaysec(&now); + sec_old = alarm_mkdaysec(&_container.current->wktime); + sec_new = alarm_mkdaysec(&alarm->wktime); + + if ((sec_new < sec_old) && (sec_new > sec_now)) + { + ret = alarm_set(alarm); + } + else if ((sec_new > sec_now) && (sec_old < sec_now)) + { + ret = alarm_set(alarm); + } + else if ((sec_new < sec_old) && (sec_old < sec_now)) + { + ret = alarm_set(alarm); + } + else + { + ret = RT_EOK; + goto _exit; + } + } + + if (ret == RT_EOK) + { + _container.current = alarm; + } + } + +_exit: + rt_mutex_release(&_container.mutex); + + return (ret); +} + +/** \brief stop an alarm + * + * \param alarm pointer to alarm + * \return RT_EOK + */ +rt_err_t rt_alarm_stop(rt_alarm_t alarm) +{ + rt_err_t ret = RT_ERROR; + + if (alarm == RT_NULL) + return (ret); + rt_mutex_take(&_container.mutex, RT_WAITING_FOREVER); + if (!(alarm->flag & RT_ALARM_STATE_START)) + goto _exit; + /* stop alarm */ + alarm->flag &= ~RT_ALARM_STATE_START; + + if (_container.current == alarm) + { + ret = alarm_set(alarm); + _container.current = RT_NULL; + } + + if (ret == RT_EOK) + alarm_update(0); + +_exit: + rt_mutex_release(&_container.mutex); + + return (ret); +} + +/** \brief delete an alarm + * + * \param alarm pointer to alarm + * \return RT_EOK + */ +rt_err_t rt_alarm_delete(rt_alarm_t alarm) +{ + rt_err_t ret = RT_ERROR; + + if (alarm == RT_NULL) + return (ret); + rt_mutex_take(&_container.mutex, RT_WAITING_FOREVER); + /* stop the alarm */ + alarm->flag &= ~RT_ALARM_STATE_START; + if (_container.current == alarm) + { + ret = alarm_set(alarm); + _container.current = RT_NULL; + /* set new alarm if necessary */ + alarm_update(0); + } + rt_list_remove(&alarm->list); + rt_free(alarm); + + rt_mutex_release(&_container.mutex); + + return (ret); +} + +/** \brief create an alarm + * + * \param flag set alarm mode e.g: RT_ALARM_DAILY + * \param setup pointer to setup infomation + */ +rt_alarm_t rt_alarm_create(rt_alarm_callback_t callback, struct rt_alarm_setup *setup) +{ + struct rt_alarm *alarm; + + if (setup == RT_NULL) + return (RT_NULL); + alarm = rt_malloc(sizeof(struct rt_alarm)); + if (alarm == RT_NULL) + return (RT_NULL); + rt_list_init(&alarm->list); + + alarm->wktime = setup->wktime; + alarm->flag = setup->flag & 0xFF00; + alarm->callback = callback; + rt_mutex_take(&_container.mutex, RT_WAITING_FOREVER); + rt_list_insert_after(&_container.head, &alarm->list); + rt_mutex_release(&_container.mutex); + + return (alarm); +} + +/** \brief rtc alarm service thread entry + * + */ +static void rt_alarmsvc_thread_init(void *param) +{ + rt_uint32_t recv; + + _container.current = RT_NULL; + + while (1) + { + if (rt_event_recv(&_container.event, 0xFFFF, + RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, + RT_WAITING_FOREVER, &recv) == RT_EOK) + { + alarm_update(recv); + } + } +} + + +/** \brief initialize alarm service system + * + * \param none + * \return none + */ +void rt_alarm_system_init(void) +{ + rt_thread_t tid; + + rt_list_init(&_container.head); + rt_event_init(&_container.event, "alarmsvc", RT_IPC_FLAG_FIFO); + rt_mutex_init(&_container.mutex, "alarmsvc", RT_IPC_FLAG_FIFO); + + tid = rt_thread_create("alarmsvc", + rt_alarmsvc_thread_init, RT_NULL, + 512, 8, 1); + if (tid != RT_NULL) + rt_thread_startup(tid); +} +#endif diff --git a/Middlewares/Third_Party/RealThread_RTOS/components/device/rtc.c b/Middlewares/Third_Party/RealThread_RTOS/components/device/rtc.c new file mode 100644 index 0000000..3468bcd --- /dev/null +++ b/Middlewares/Third_Party/RealThread_RTOS/components/device/rtc.c @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2012-01-29 aozima first version. + * 2012-04-12 aozima optimization: find rtc device only first. + * 2012-04-16 aozima add scheduler lock for set_date and set_time. + * 2018-02-16 armink add auto sync time by NTP + */ + +#include +#include +#include + +#ifdef RT_USING_RTC + +/* Using NTP auto sync RTC time */ +#ifdef RTC_SYNC_USING_NTP +/* NTP first sync delay time for network connect, unit: second */ +#ifndef RTC_NTP_FIRST_SYNC_DELAY +#define RTC_NTP_FIRST_SYNC_DELAY (30) +#endif +/* NTP sync period, unit: second */ +#ifndef RTC_NTP_SYNC_PERIOD +#define RTC_NTP_SYNC_PERIOD (1L*60L*60L) +#endif +#endif /* RTC_SYNC_USING_NTP */ + +/** + * Set system date(time not modify). + * + * @param rt_uint32_t year e.g: 2012. + * @param rt_uint32_t month e.g: 12 (1~12). + * @param rt_uint32_t day e.g: 31. + * + * @return rt_err_t if set success, return RT_EOK. + * + */ +rt_err_t set_date(rt_uint32_t year, rt_uint32_t month, rt_uint32_t day) +{ + time_t now; + struct tm *p_tm; + struct tm tm_new; + rt_device_t device; + rt_err_t ret = -RT_ERROR; + + /* get current time */ + now = time(RT_NULL); + + /* lock scheduler. */ + rt_enter_critical(); + /* converts calendar time time into local time. */ + p_tm = localtime(&now); + /* copy the statically located variable */ + memcpy(&tm_new, p_tm, sizeof(struct tm)); + /* unlock scheduler. */ + rt_exit_critical(); + + /* update date. */ + tm_new.tm_year = year - 1900; + tm_new.tm_mon = month - 1; /* tm_mon: 0~11 */ + tm_new.tm_mday = day; + + /* converts the local time in time to calendar time. */ + now = mktime(&tm_new); + + device = rt_device_find("rtc"); + if (device == RT_NULL) + { + return -RT_ERROR; + } + + /* update to RTC device. */ + ret = rt_device_control(device, RT_DEVICE_CTRL_RTC_SET_TIME, &now); + + return ret; +} + +/** + * Set system time(date not modify). + * + * @param rt_uint32_t hour e.g: 0~23. + * @param rt_uint32_t minute e.g: 0~59. + * @param rt_uint32_t second e.g: 0~59. + * + * @return rt_err_t if set success, return RT_EOK. + * + */ +rt_err_t set_time(rt_uint32_t hour, rt_uint32_t minute, rt_uint32_t second) +{ + time_t now; + struct tm *p_tm; + struct tm tm_new; + rt_device_t device; + rt_err_t ret = -RT_ERROR; + + /* get current time */ + now = time(RT_NULL); + + /* lock scheduler. */ + rt_enter_critical(); + /* converts calendar time time into local time. */ + p_tm = localtime(&now); + /* copy the statically located variable */ + memcpy(&tm_new, p_tm, sizeof(struct tm)); + /* unlock scheduler. */ + rt_exit_critical(); + + /* update time. */ + tm_new.tm_hour = hour; + tm_new.tm_min = minute; + tm_new.tm_sec = second; + + /* converts the local time in time to calendar time. */ + now = mktime(&tm_new); + + device = rt_device_find("rtc"); + if (device == RT_NULL) + { + return -RT_ERROR; + } + + /* update to RTC device. */ + ret = rt_device_control(device, RT_DEVICE_CTRL_RTC_SET_TIME, &now); + + return ret; +} + +#ifdef RTC_SYNC_USING_NTP +static void ntp_sync_thread_enrty(void *param) +{ + extern time_t ntp_sync_to_rtc(const char *host_name); + /* first sync delay for network connect */ + rt_thread_delay(RTC_NTP_FIRST_SYNC_DELAY * RT_TICK_PER_SECOND); + + while (1) + { + ntp_sync_to_rtc(NULL); + rt_thread_delay(RTC_NTP_SYNC_PERIOD * RT_TICK_PER_SECOND); + } +} + +int rt_rtc_ntp_sync_init(void) +{ + static rt_bool_t init_ok = RT_FALSE; + rt_thread_t thread; + + if (init_ok) + { + return 0; + } + + thread = rt_thread_create("ntp_sync", ntp_sync_thread_enrty, RT_NULL, 1536, 26, 2); + if (thread) + { + rt_thread_startup(thread); + } + else + { + return -RT_ENOMEM; + } + + init_ok = RT_TRUE; + + return RT_EOK; +} +INIT_COMPONENT_EXPORT(rt_rtc_ntp_sync_init); +#endif /* RTC_SYNC_USING_NTP */ + +#ifdef RT_USING_FINSH +#include +#include + +void list_date(void) +{ + time_t now; + + now = time(RT_NULL); + rt_kprintf("%s\n", ctime(&now)); +} +FINSH_FUNCTION_EXPORT(list_date, show date and time.) + +FINSH_FUNCTION_EXPORT(set_date, set date. e.g: set_date(2010,2,28)) +FINSH_FUNCTION_EXPORT(set_time, set time. e.g: set_time(23,59,59)) + +#if defined(RT_USING_FINSH) && defined(FINSH_USING_MSH) +static void date(uint8_t argc, char **argv) +{ + if (argc == 1) + { + time_t now; + /* output current time */ + now = time(RT_NULL); + rt_kprintf("%s", ctime(&now)); + } + else if (argc >= 7) + { + /* set time and date */ + uint16_t year; + uint8_t month, day, hour, min, sec; + year = atoi(argv[1]); + month = atoi(argv[2]); + day = atoi(argv[3]); + hour = atoi(argv[4]); + min = atoi(argv[5]); + sec = atoi(argv[6]); + if (year > 2099 || year < 2000) + { + rt_kprintf("year is out of range [2000-2099]\n"); + return; + } + if (month == 0 || month > 12) + { + rt_kprintf("month is out of range [1-12]\n"); + return; + } + if (day == 0 || day > 31) + { + rt_kprintf("day is out of range [1-31]\n"); + return; + } + if (hour > 23) + { + rt_kprintf("hour is out of range [0-23]\n"); + return; + } + if (min > 59) + { + rt_kprintf("minute is out of range [0-59]\n"); + return; + } + if (sec > 59) + { + rt_kprintf("second is out of range [0-59]\n"); + return; + } + set_time(hour, min, sec); + set_date(year, month, day); + } + else + { + rt_kprintf("please input: date [year month day hour min sec] or date\n"); + rt_kprintf("e.g: date 2018 01 01 23 59 59 or date\n"); + } +} +MSH_CMD_EXPORT(date, get date and time or set [year month day hour min sec]); +#endif /* defined(RT_USING_FINSH) && defined(FINSH_USING_MSH) */ + +#endif /* RT_USING_FINSH */ + +#endif /* RT_USING_RTC */ diff --git a/Middlewares/Third_Party/RealThread_RTOS/components/device/rtc.h b/Middlewares/Third_Party/RealThread_RTOS/components/device/rtc.h new file mode 100644 index 0000000..4845937 --- /dev/null +++ b/Middlewares/Third_Party/RealThread_RTOS/components/device/rtc.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2012-10-10 aozima first version. + */ + +#ifndef __RTC_H__ +#define __RTC_H__ + +rt_err_t set_date(rt_uint32_t year, rt_uint32_t month, rt_uint32_t day); +rt_err_t set_time(rt_uint32_t hour, rt_uint32_t minute, rt_uint32_t second); + +int rt_soft_rtc_init(void); +int rt_rtc_ntp_sync_init(void); + +#endif /* __RTC_H__ */ diff --git a/Middlewares/Third_Party/RealThread_RTOS/components/device/soft_rtc.c b/Middlewares/Third_Party/RealThread_RTOS/components/device/soft_rtc.c new file mode 100644 index 0000000..2d10bc5 --- /dev/null +++ b/Middlewares/Third_Party/RealThread_RTOS/components/device/soft_rtc.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-01-30 armink the first version + */ + +#include +#include +#include + +#include + +#ifdef RT_USING_SOFT_RTC + +/* 2018-01-30 14:44:50 = RTC_TIME_INIT(2018, 1, 30, 14, 44, 50) */ +#define RTC_TIME_INIT(year, month, day, hour, minute, second) \ + {.tm_year = year - 1900, .tm_mon = month - 1, .tm_mday = day, .tm_hour = hour, .tm_min = minute, .tm_sec = second} + +#ifndef SOFT_RTC_TIME_DEFAULT +#define SOFT_RTC_TIME_DEFAULT RTC_TIME_INIT(2018, 1, 1, 0, 0 ,0) +#endif + +static struct rt_device soft_rtc_dev; +static rt_tick_t init_tick; +static time_t init_time; + +static rt_err_t soft_rtc_control(rt_device_t dev, int cmd, void *args) +{ + time_t *time; + struct tm time_temp; + + RT_ASSERT(dev != RT_NULL); + memset(&time_temp, 0, sizeof(struct tm)); + + switch (cmd) + { + case RT_DEVICE_CTRL_RTC_GET_TIME: + time = (time_t *) args; + *time = init_time + (rt_tick_get() - init_tick) / RT_TICK_PER_SECOND; + break; + + case RT_DEVICE_CTRL_RTC_SET_TIME: + { + time = (time_t *) args; + init_time = *time - (rt_tick_get() - init_tick) / RT_TICK_PER_SECOND; + break; + } + } + + return RT_EOK; +} + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops soft_rtc_ops = +{ + RT_NULL, + RT_NULL, + RT_NULL, + RT_NULL, + RT_NULL, + soft_rtc_control +}; +#endif + +int rt_soft_rtc_init(void) +{ + static rt_bool_t init_ok = RT_FALSE; + struct tm time_new = SOFT_RTC_TIME_DEFAULT; + + if (init_ok) + { + return 0; + } + /* make sure only one 'rtc' device */ + RT_ASSERT(!rt_device_find("rtc")); + + init_tick = rt_tick_get(); + init_time = mktime(&time_new); + + soft_rtc_dev.type = RT_Device_Class_RTC; + + /* register rtc device */ +#ifdef RT_USING_DEVICE_OPS + soft_rtc_dev.ops = &soft_rtc_ops; +#else + soft_rtc_dev.init = RT_NULL; + soft_rtc_dev.open = RT_NULL; + soft_rtc_dev.close = RT_NULL; + soft_rtc_dev.read = RT_NULL; + soft_rtc_dev.write = RT_NULL; + soft_rtc_dev.control = soft_rtc_control; +#endif + + /* no private */ + soft_rtc_dev.user_data = RT_NULL; + + rt_device_register(&soft_rtc_dev, "rtc", RT_DEVICE_FLAG_RDWR); + + init_ok = RT_TRUE; + + return 0; +} +INIT_DEVICE_EXPORT(rt_soft_rtc_init); + +#endif /* RT_USING_SOFT_RTC */ diff --git a/Project/g0b1vetx-sluice b/Project/g0b1vetx-sluice index 38d2e6b..2c9ad35 160000 --- a/Project/g0b1vetx-sluice +++ b/Project/g0b1vetx-sluice @@ -1 +1 @@ -Subproject commit 38d2e6b239cf12f35cc10a3b03de211c06d34aad +Subproject commit 2c9ad35632dd794514b6f54860f2b2c8d4605cb2 diff --git a/middleware/Util/util.c b/middleware/Util/util.c index 812476f..be3d9dc 100644 --- a/middleware/Util/util.c +++ b/middleware/Util/util.c @@ -21,6 +21,15 @@ uint32_t Bytes2Int (char * data) return I.data; } +int16_t Bytes2Int16 (char * data) +{ + Int16Tobyte int16_byte; + int16_byte.byte[0] = data[1]; + int16_byte.byte[1] = data[0]; + return int16_byte.value; +} + + // ----------------------------------------------------------------- // 函数功能: hex字符串转byte数组 diff --git a/middleware/Util/util.h b/middleware/Util/util.h index 4b1a5d1..326fb7a 100644 --- a/middleware/Util/util.h +++ b/middleware/Util/util.h @@ -15,6 +15,11 @@ typedef union } Float; +typedef union{ + int16_t value; + char byte[2]; +}Int16Tobyte; + float Bytes2Float (char * data); uint32_t Bytes2Int (char * data); int hexstr_to_hexbyte (char *src, char *obj, uint16_t length); @@ -23,6 +28,8 @@ uint32_t byte_to_Inverse(char * data); // 754 转float float float_to_iee754 (float ff1,char * data); +int16_t Bytes2Int16 (char * data); + #endif diff --git a/middleware/cjson/cjson-master/cjson-master/cJSON_Utils.c b/middleware/cjson/cjson-master/cjson-master/cJSON_Utils.c new file mode 100644 index 0000000..63651df --- /dev/null +++ b/middleware/cjson/cjson-master/cjson-master/cJSON_Utils.c @@ -0,0 +1,1481 @@ +/* + Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + + 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. +*/ + +/* disable warnings about old C89 functions in MSVC */ +#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) +#define _CRT_SECURE_NO_DEPRECATE +#endif + +#ifdef __GNUCC__ +#pragma GCC visibility push(default) +#endif +#if defined(_MSC_VER) +#pragma warning (push) +/* disable warning about single line comments in system headers */ +#pragma warning (disable : 4001) +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(_MSC_VER) +#pragma warning (pop) +#endif +#ifdef __GNUCC__ +#pragma GCC visibility pop +#endif + +#include "cJSON_Utils.h" + +/* define our own boolean type */ +#ifdef true +#undef true +#endif +#define true ((cJSON_bool)1) + +#ifdef false +#undef false +#endif +#define false ((cJSON_bool)0) + +static unsigned char* cJSONUtils_strdup(const unsigned char* const string) +{ + size_t length = 0; + unsigned char *copy = NULL; + + length = strlen((const char*)string) + sizeof(""); + copy = (unsigned char*) cJSON_malloc(length); + if (copy == NULL) + { + return NULL; + } + memcpy(copy, string, length); + + return copy; +} + +/* string comparison which doesn't consider NULL pointers equal */ +static int compare_strings(const unsigned char *string1, const unsigned char *string2, const cJSON_bool case_sensitive) +{ + if ((string1 == NULL) || (string2 == NULL)) + { + return 1; + } + + if (string1 == string2) + { + return 0; + } + + if (case_sensitive) + { + return strcmp((const char*)string1, (const char*)string2); + } + + for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++) + { + if (*string1 == '\0') + { + return 0; + } + } + + return tolower(*string1) - tolower(*string2); +} + +/* securely comparison of floating-point variables */ +static cJSON_bool compare_double(double a, double b) +{ + double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b); + return (fabs(a - b) <= maxVal * DBL_EPSILON); +} + + +/* Compare the next path element of two JSON pointers, two NULL pointers are considered unequal: */ +static cJSON_bool compare_pointers(const unsigned char *name, const unsigned char *pointer, const cJSON_bool case_sensitive) +{ + if ((name == NULL) || (pointer == NULL)) + { + return false; + } + + for (; (*name != '\0') && (*pointer != '\0') && (*pointer != '/'); (void)name++, pointer++) /* compare until next '/' */ + { + if (*pointer == '~') + { + /* check for escaped '~' (~0) and '/' (~1) */ + if (((pointer[1] != '0') || (*name != '~')) && ((pointer[1] != '1') || (*name != '/'))) + { + /* invalid escape sequence or wrong character in *name */ + return false; + } + else + { + pointer++; + } + } + else if ((!case_sensitive && (tolower(*name) != tolower(*pointer))) || (case_sensitive && (*name != *pointer))) + { + return false; + } + } + if (((*pointer != 0) && (*pointer != '/')) != (*name != 0)) + { + /* one string has ended, the other not */ + return false;; + } + + return true; +} + +/* calculate the length of a string if encoded as JSON pointer with ~0 and ~1 escape sequences */ +static size_t pointer_encoded_length(const unsigned char *string) +{ + size_t length; + for (length = 0; *string != '\0'; (void)string++, length++) + { + /* character needs to be escaped? */ + if ((*string == '~') || (*string == '/')) + { + length++; + } + } + + return length; +} + +/* copy a string while escaping '~' and '/' with ~0 and ~1 JSON pointer escape codes */ +static void encode_string_as_pointer(unsigned char *destination, const unsigned char *source) +{ + for (; source[0] != '\0'; (void)source++, destination++) + { + if (source[0] == '/') + { + destination[0] = '~'; + destination[1] = '1'; + destination++; + } + else if (source[0] == '~') + { + destination[0] = '~'; + destination[1] = '0'; + destination++; + } + else + { + destination[0] = source[0]; + } + } + + destination[0] = '\0'; +} + +CJSON_PUBLIC(char *) cJSONUtils_FindPointerFromObjectTo(const cJSON * const object, const cJSON * const target) +{ + size_t child_index = 0; + cJSON *current_child = 0; + + if ((object == NULL) || (target == NULL)) + { + return NULL; + } + + if (object == target) + { + /* found */ + return (char*)cJSONUtils_strdup((const unsigned char*)""); + } + + /* recursively search all children of the object or array */ + for (current_child = object->child; current_child != NULL; (void)(current_child = current_child->next), child_index++) + { + unsigned char *target_pointer = (unsigned char*)cJSONUtils_FindPointerFromObjectTo(current_child, target); + /* found the target? */ + if (target_pointer != NULL) + { + if (cJSON_IsArray(object)) + { + /* reserve enough memory for a 64 bit integer + '/' and '\0' */ + unsigned char *full_pointer = (unsigned char*)cJSON_malloc(strlen((char*)target_pointer) + 20 + sizeof("/")); + /* check if conversion to unsigned long is valid + * This should be eliminated at compile time by dead code elimination + * if size_t is an alias of unsigned long, or if it is bigger */ + if (child_index > ULONG_MAX) + { + cJSON_free(target_pointer); + cJSON_free(full_pointer); + return NULL; + } + sprintf((char*)full_pointer, "/%lu%s", (unsigned long)child_index, target_pointer); /* / */ + cJSON_free(target_pointer); + + return (char*)full_pointer; + } + + if (cJSON_IsObject(object)) + { + unsigned char *full_pointer = (unsigned char*)cJSON_malloc(strlen((char*)target_pointer) + pointer_encoded_length((unsigned char*)current_child->string) + 2); + full_pointer[0] = '/'; + encode_string_as_pointer(full_pointer + 1, (unsigned char*)current_child->string); + strcat((char*)full_pointer, (char*)target_pointer); + cJSON_free(target_pointer); + + return (char*)full_pointer; + } + + /* reached leaf of the tree, found nothing */ + cJSON_free(target_pointer); + return NULL; + } + } + + /* not found */ + return NULL; +} + +/* non broken version of cJSON_GetArrayItem */ +static cJSON *get_array_item(const cJSON *array, size_t item) +{ + cJSON *child = array ? array->child : NULL; + while ((child != NULL) && (item > 0)) + { + item--; + child = child->next; + } + + return child; +} + +static cJSON_bool decode_array_index_from_pointer(const unsigned char * const pointer, size_t * const index) +{ + size_t parsed_index = 0; + size_t position = 0; + + if ((pointer[0] == '0') && ((pointer[1] != '\0') && (pointer[1] != '/'))) + { + /* leading zeroes are not permitted */ + return 0; + } + + for (position = 0; (pointer[position] >= '0') && (pointer[0] <= '9'); position++) + { + parsed_index = (10 * parsed_index) + (size_t)(pointer[position] - '0'); + + } + + if ((pointer[position] != '\0') && (pointer[position] != '/')) + { + return 0; + } + + *index = parsed_index; + + return 1; +} + +static cJSON *get_item_from_pointer(cJSON * const object, const char * pointer, const cJSON_bool case_sensitive) +{ + cJSON *current_element = object; + + if (pointer == NULL) + { + return NULL; + } + + /* follow path of the pointer */ + while ((pointer[0] == '/') && (current_element != NULL)) + { + pointer++; + if (cJSON_IsArray(current_element)) + { + size_t index = 0; + if (!decode_array_index_from_pointer((const unsigned char*)pointer, &index)) + { + return NULL; + } + + current_element = get_array_item(current_element, index); + } + else if (cJSON_IsObject(current_element)) + { + current_element = current_element->child; + /* GetObjectItem. */ + while ((current_element != NULL) && !compare_pointers((unsigned char*)current_element->string, (const unsigned char*)pointer, case_sensitive)) + { + current_element = current_element->next; + } + } + else + { + return NULL; + } + + /* skip to the next path token or end of string */ + while ((pointer[0] != '\0') && (pointer[0] != '/')) + { + pointer++; + } + } + + return current_element; +} + +CJSON_PUBLIC(cJSON *) cJSONUtils_GetPointer(cJSON * const object, const char *pointer) +{ + return get_item_from_pointer(object, pointer, false); +} + +CJSON_PUBLIC(cJSON *) cJSONUtils_GetPointerCaseSensitive(cJSON * const object, const char *pointer) +{ + return get_item_from_pointer(object, pointer, true); +} + +/* JSON Patch implementation. */ +static void decode_pointer_inplace(unsigned char *string) +{ + unsigned char *decoded_string = string; + + if (string == NULL) { + return; + } + + for (; *string; (void)decoded_string++, string++) + { + if (string[0] == '~') + { + if (string[1] == '0') + { + decoded_string[0] = '~'; + } + else if (string[1] == '1') + { + decoded_string[1] = '/'; + } + else + { + /* invalid escape sequence */ + return; + } + + string++; + } + } + + decoded_string[0] = '\0'; +} + +/* non-broken cJSON_DetachItemFromArray */ +static cJSON *detach_item_from_array(cJSON *array, size_t which) +{ + cJSON *c = array->child; + while (c && (which > 0)) + { + c = c->next; + which--; + } + if (!c) + { + /* item doesn't exist */ + return NULL; + } + if (c != array->child) + { + /* not the first element */ + c->prev->next = c->next; + } + if (c->next) + { + c->next->prev = c->prev; + } + if (c == array->child) + { + array->child = c->next; + } + else if (c->next == NULL) + { + array->child->prev = c->prev; + } + /* make sure the detached item doesn't point anywhere anymore */ + c->prev = c->next = NULL; + + return c; +} + +/* detach an item at the given path */ +static cJSON *detach_path(cJSON *object, const unsigned char *path, const cJSON_bool case_sensitive) +{ + unsigned char *parent_pointer = NULL; + unsigned char *child_pointer = NULL; + cJSON *parent = NULL; + cJSON *detached_item = NULL; + + /* copy path and split it in parent and child */ + parent_pointer = cJSONUtils_strdup(path); + if (parent_pointer == NULL) { + goto cleanup; + } + + child_pointer = (unsigned char*)strrchr((char*)parent_pointer, '/'); /* last '/' */ + if (child_pointer == NULL) + { + goto cleanup; + } + /* split strings */ + child_pointer[0] = '\0'; + child_pointer++; + + parent = get_item_from_pointer(object, (char*)parent_pointer, case_sensitive); + decode_pointer_inplace(child_pointer); + + if (cJSON_IsArray(parent)) + { + size_t index = 0; + if (!decode_array_index_from_pointer(child_pointer, &index)) + { + goto cleanup; + } + detached_item = detach_item_from_array(parent, index); + } + else if (cJSON_IsObject(parent)) + { + detached_item = cJSON_DetachItemFromObject(parent, (char*)child_pointer); + } + else + { + /* Couldn't find object to remove child from. */ + goto cleanup; + } + +cleanup: + if (parent_pointer != NULL) + { + cJSON_free(parent_pointer); + } + + return detached_item; +} + +/* sort lists using mergesort */ +static cJSON *sort_list(cJSON *list, const cJSON_bool case_sensitive) +{ + cJSON *first = list; + cJSON *second = list; + cJSON *current_item = list; + cJSON *result = list; + cJSON *result_tail = NULL; + + if ((list == NULL) || (list->next == NULL)) + { + /* One entry is sorted already. */ + return result; + } + + while ((current_item != NULL) && (current_item->next != NULL) && (compare_strings((unsigned char*)current_item->string, (unsigned char*)current_item->next->string, case_sensitive) < 0)) + { + /* Test for list sorted. */ + current_item = current_item->next; + } + if ((current_item == NULL) || (current_item->next == NULL)) + { + /* Leave sorted lists unmodified. */ + return result; + } + + /* reset pointer to the beginning */ + current_item = list; + while (current_item != NULL) + { + /* Walk two pointers to find the middle. */ + second = second->next; + current_item = current_item->next; + /* advances current_item two steps at a time */ + if (current_item != NULL) + { + current_item = current_item->next; + } + } + if ((second != NULL) && (second->prev != NULL)) + { + /* Split the lists */ + second->prev->next = NULL; + second->prev = NULL; + } + + /* Recursively sort the sub-lists. */ + first = sort_list(first, case_sensitive); + second = sort_list(second, case_sensitive); + result = NULL; + + /* Merge the sub-lists */ + while ((first != NULL) && (second != NULL)) + { + cJSON *smaller = NULL; + if (compare_strings((unsigned char*)first->string, (unsigned char*)second->string, case_sensitive) < 0) + { + smaller = first; + } + else + { + smaller = second; + } + + if (result == NULL) + { + /* start merged list with the smaller element */ + result_tail = smaller; + result = smaller; + } + else + { + /* add smaller element to the list */ + result_tail->next = smaller; + smaller->prev = result_tail; + result_tail = smaller; + } + + if (first == smaller) + { + first = first->next; + } + else + { + second = second->next; + } + } + + if (first != NULL) + { + /* Append rest of first list. */ + if (result == NULL) + { + return first; + } + result_tail->next = first; + first->prev = result_tail; + } + if (second != NULL) + { + /* Append rest of second list */ + if (result == NULL) + { + return second; + } + result_tail->next = second; + second->prev = result_tail; + } + + return result; +} + +static void sort_object(cJSON * const object, const cJSON_bool case_sensitive) +{ + if (object == NULL) + { + return; + } + object->child = sort_list(object->child, case_sensitive); +} + +static cJSON_bool compare_json(cJSON *a, cJSON *b, const cJSON_bool case_sensitive) +{ + if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF))) + { + /* mismatched type. */ + return false; + } + switch (a->type & 0xFF) + { + case cJSON_Number: + /* numeric mismatch. */ + if ((a->valueint != b->valueint) || (!compare_double(a->valuedouble, b->valuedouble))) + { + return false; + } + else + { + return true; + } + + case cJSON_String: + /* string mismatch. */ + if (strcmp(a->valuestring, b->valuestring) != 0) + { + return false; + } + else + { + return true; + } + + case cJSON_Array: + for ((void)(a = a->child), b = b->child; (a != NULL) && (b != NULL); (void)(a = a->next), b = b->next) + { + cJSON_bool identical = compare_json(a, b, case_sensitive); + if (!identical) + { + return false; + } + } + + /* array size mismatch? (one of both children is not NULL) */ + if ((a != NULL) || (b != NULL)) + { + return false; + } + else + { + return true; + } + + case cJSON_Object: + sort_object(a, case_sensitive); + sort_object(b, case_sensitive); + for ((void)(a = a->child), b = b->child; (a != NULL) && (b != NULL); (void)(a = a->next), b = b->next) + { + cJSON_bool identical = false; + /* compare object keys */ + if (compare_strings((unsigned char*)a->string, (unsigned char*)b->string, case_sensitive)) + { + /* missing member */ + return false; + } + identical = compare_json(a, b, case_sensitive); + if (!identical) + { + return false; + } + } + + /* object length mismatch (one of both children is not null) */ + if ((a != NULL) || (b != NULL)) + { + return false; + } + else + { + return true; + } + + default: + break; + } + + /* null, true or false */ + return true; +} + +/* non broken version of cJSON_InsertItemInArray */ +static cJSON_bool insert_item_in_array(cJSON *array, size_t which, cJSON *newitem) +{ + cJSON *child = array->child; + while (child && (which > 0)) + { + child = child->next; + which--; + } + if (which > 0) + { + /* item is after the end of the array */ + return 0; + } + if (child == NULL) + { + cJSON_AddItemToArray(array, newitem); + return 1; + } + + /* insert into the linked list */ + newitem->next = child; + newitem->prev = child->prev; + child->prev = newitem; + + /* was it at the beginning */ + if (child == array->child) + { + array->child = newitem; + } + else + { + newitem->prev->next = newitem; + } + + return 1; +} + +static cJSON *get_object_item(const cJSON * const object, const char* name, const cJSON_bool case_sensitive) +{ + if (case_sensitive) + { + return cJSON_GetObjectItemCaseSensitive(object, name); + } + + return cJSON_GetObjectItem(object, name); +} + +enum patch_operation { INVALID, ADD, REMOVE, REPLACE, MOVE, COPY, TEST }; + +static enum patch_operation decode_patch_operation(const cJSON * const patch, const cJSON_bool case_sensitive) +{ + cJSON *operation = get_object_item(patch, "op", case_sensitive); + if (!cJSON_IsString(operation)) + { + return INVALID; + } + + if (strcmp(operation->valuestring, "add") == 0) + { + return ADD; + } + + if (strcmp(operation->valuestring, "remove") == 0) + { + return REMOVE; + } + + if (strcmp(operation->valuestring, "replace") == 0) + { + return REPLACE; + } + + if (strcmp(operation->valuestring, "move") == 0) + { + return MOVE; + } + + if (strcmp(operation->valuestring, "copy") == 0) + { + return COPY; + } + + if (strcmp(operation->valuestring, "test") == 0) + { + return TEST; + } + + return INVALID; +} + +/* overwrite and existing item with another one and free resources on the way */ +static void overwrite_item(cJSON * const root, const cJSON replacement) +{ + if (root == NULL) + { + return; + } + + if (root->string != NULL) + { + cJSON_free(root->string); + } + if (root->valuestring != NULL) + { + cJSON_free(root->valuestring); + } + if (root->child != NULL) + { + cJSON_Delete(root->child); + } + + memcpy(root, &replacement, sizeof(cJSON)); +} + +static int apply_patch(cJSON *object, const cJSON *patch, const cJSON_bool case_sensitive) +{ + cJSON *path = NULL; + cJSON *value = NULL; + cJSON *parent = NULL; + enum patch_operation opcode = INVALID; + unsigned char *parent_pointer = NULL; + unsigned char *child_pointer = NULL; + int status = 0; + + path = get_object_item(patch, "path", case_sensitive); + if (!cJSON_IsString(path)) + { + /* malformed patch. */ + status = 2; + goto cleanup; + } + + opcode = decode_patch_operation(patch, case_sensitive); + if (opcode == INVALID) + { + status = 3; + goto cleanup; + } + else if (opcode == TEST) + { + /* compare value: {...} with the given path */ + status = !compare_json(get_item_from_pointer(object, path->valuestring, case_sensitive), get_object_item(patch, "value", case_sensitive), case_sensitive); + goto cleanup; + } + + /* special case for replacing the root */ + if (path->valuestring[0] == '\0') + { + if (opcode == REMOVE) + { + static const cJSON invalid = { NULL, NULL, NULL, cJSON_Invalid, NULL, 0, 0, NULL}; + + overwrite_item(object, invalid); + + status = 0; + goto cleanup; + } + + if ((opcode == REPLACE) || (opcode == ADD)) + { + value = get_object_item(patch, "value", case_sensitive); + if (value == NULL) + { + /* missing "value" for add/replace. */ + status = 7; + goto cleanup; + } + + value = cJSON_Duplicate(value, 1); + if (value == NULL) + { + /* out of memory for add/replace. */ + status = 8; + goto cleanup; + } + + overwrite_item(object, *value); + + /* delete the duplicated value */ + cJSON_free(value); + value = NULL; + + /* the string "value" isn't needed */ + if (object->string != NULL) + { + cJSON_free(object->string); + object->string = NULL; + } + + status = 0; + goto cleanup; + } + } + + if ((opcode == REMOVE) || (opcode == REPLACE)) + { + /* Get rid of old. */ + cJSON *old_item = detach_path(object, (unsigned char*)path->valuestring, case_sensitive); + if (old_item == NULL) + { + status = 13; + goto cleanup; + } + cJSON_Delete(old_item); + if (opcode == REMOVE) + { + /* For Remove, this job is done. */ + status = 0; + goto cleanup; + } + } + + /* Copy/Move uses "from". */ + if ((opcode == MOVE) || (opcode == COPY)) + { + cJSON *from = get_object_item(patch, "from", case_sensitive); + if (from == NULL) + { + /* missing "from" for copy/move. */ + status = 4; + goto cleanup; + } + + if (opcode == MOVE) + { + value = detach_path(object, (unsigned char*)from->valuestring, case_sensitive); + } + if (opcode == COPY) + { + value = get_item_from_pointer(object, from->valuestring, case_sensitive); + } + if (value == NULL) + { + /* missing "from" for copy/move. */ + status = 5; + goto cleanup; + } + if (opcode == COPY) + { + value = cJSON_Duplicate(value, 1); + } + if (value == NULL) + { + /* out of memory for copy/move. */ + status = 6; + goto cleanup; + } + } + else /* Add/Replace uses "value". */ + { + value = get_object_item(patch, "value", case_sensitive); + if (value == NULL) + { + /* missing "value" for add/replace. */ + status = 7; + goto cleanup; + } + value = cJSON_Duplicate(value, 1); + if (value == NULL) + { + /* out of memory for add/replace. */ + status = 8; + goto cleanup; + } + } + + /* Now, just add "value" to "path". */ + + /* split pointer in parent and child */ + parent_pointer = cJSONUtils_strdup((unsigned char*)path->valuestring); + if (parent_pointer) { + child_pointer = (unsigned char*)strrchr((char*)parent_pointer, '/'); + } + if (child_pointer != NULL) + { + child_pointer[0] = '\0'; + child_pointer++; + } + parent = get_item_from_pointer(object, (char*)parent_pointer, case_sensitive); + decode_pointer_inplace(child_pointer); + + /* add, remove, replace, move, copy, test. */ + if ((parent == NULL) || (child_pointer == NULL)) + { + /* Couldn't find object to add to. */ + status = 9; + goto cleanup; + } + else if (cJSON_IsArray(parent)) + { + if (strcmp((char*)child_pointer, "-") == 0) + { + cJSON_AddItemToArray(parent, value); + value = NULL; + } + else + { + size_t index = 0; + if (!decode_array_index_from_pointer(child_pointer, &index)) + { + status = 11; + goto cleanup; + } + + if (!insert_item_in_array(parent, index, value)) + { + status = 10; + goto cleanup; + } + value = NULL; + } + } + else if (cJSON_IsObject(parent)) + { + if (case_sensitive) + { + cJSON_DeleteItemFromObjectCaseSensitive(parent, (char*)child_pointer); + } + else + { + cJSON_DeleteItemFromObject(parent, (char*)child_pointer); + } + cJSON_AddItemToObject(parent, (char*)child_pointer, value); + value = NULL; + } + else /* parent is not an object */ + { + /* Couldn't find object to add to. */ + status = 9; + goto cleanup; + } + +cleanup: + if (value != NULL) + { + cJSON_Delete(value); + } + if (parent_pointer != NULL) + { + cJSON_free(parent_pointer); + } + + return status; +} + +CJSON_PUBLIC(int) cJSONUtils_ApplyPatches(cJSON * const object, const cJSON * const patches) +{ + const cJSON *current_patch = NULL; + int status = 0; + + if (!cJSON_IsArray(patches)) + { + /* malformed patches. */ + return 1; + } + + if (patches != NULL) + { + current_patch = patches->child; + } + + while (current_patch != NULL) + { + status = apply_patch(object, current_patch, false); + if (status != 0) + { + return status; + } + current_patch = current_patch->next; + } + + return 0; +} + +CJSON_PUBLIC(int) cJSONUtils_ApplyPatchesCaseSensitive(cJSON * const object, const cJSON * const patches) +{ + const cJSON *current_patch = NULL; + int status = 0; + + if (!cJSON_IsArray(patches)) + { + /* malformed patches. */ + return 1; + } + + if (patches != NULL) + { + current_patch = patches->child; + } + + while (current_patch != NULL) + { + status = apply_patch(object, current_patch, true); + if (status != 0) + { + return status; + } + current_patch = current_patch->next; + } + + return 0; +} + +static void compose_patch(cJSON * const patches, const unsigned char * const operation, const unsigned char * const path, const unsigned char *suffix, const cJSON * const value) +{ + cJSON *patch = NULL; + + if ((patches == NULL) || (operation == NULL) || (path == NULL)) + { + return; + } + + patch = cJSON_CreateObject(); + if (patch == NULL) + { + return; + } + cJSON_AddItemToObject(patch, "op", cJSON_CreateString((const char*)operation)); + + if (suffix == NULL) + { + cJSON_AddItemToObject(patch, "path", cJSON_CreateString((const char*)path)); + } + else + { + size_t suffix_length = pointer_encoded_length(suffix); + size_t path_length = strlen((const char*)path); + unsigned char *full_path = (unsigned char*)cJSON_malloc(path_length + suffix_length + sizeof("/")); + + sprintf((char*)full_path, "%s/", (const char*)path); + encode_string_as_pointer(full_path + path_length + 1, suffix); + + cJSON_AddItemToObject(patch, "path", cJSON_CreateString((const char*)full_path)); + cJSON_free(full_path); + } + + if (value != NULL) + { + cJSON_AddItemToObject(patch, "value", cJSON_Duplicate(value, 1)); + } + cJSON_AddItemToArray(patches, patch); +} + +CJSON_PUBLIC(void) cJSONUtils_AddPatchToArray(cJSON * const array, const char * const operation, const char * const path, const cJSON * const value) +{ + compose_patch(array, (const unsigned char*)operation, (const unsigned char*)path, NULL, value); +} + +static void create_patches(cJSON * const patches, const unsigned char * const path, cJSON * const from, cJSON * const to, const cJSON_bool case_sensitive) +{ + if ((from == NULL) || (to == NULL)) + { + return; + } + + if ((from->type & 0xFF) != (to->type & 0xFF)) + { + compose_patch(patches, (const unsigned char*)"replace", path, 0, to); + return; + } + + switch (from->type & 0xFF) + { + case cJSON_Number: + if ((from->valueint != to->valueint) || !compare_double(from->valuedouble, to->valuedouble)) + { + compose_patch(patches, (const unsigned char*)"replace", path, NULL, to); + } + return; + + case cJSON_String: + if (strcmp(from->valuestring, to->valuestring) != 0) + { + compose_patch(patches, (const unsigned char*)"replace", path, NULL, to); + } + return; + + case cJSON_Array: + { + size_t index = 0; + cJSON *from_child = from->child; + cJSON *to_child = to->child; + unsigned char *new_path = (unsigned char*)cJSON_malloc(strlen((const char*)path) + 20 + sizeof("/")); /* Allow space for 64bit int. log10(2^64) = 20 */ + + /* generate patches for all array elements that exist in both "from" and "to" */ + for (index = 0; (from_child != NULL) && (to_child != NULL); (void)(from_child = from_child->next), (void)(to_child = to_child->next), index++) + { + /* check if conversion to unsigned long is valid + * This should be eliminated at compile time by dead code elimination + * if size_t is an alias of unsigned long, or if it is bigger */ + if (index > ULONG_MAX) + { + cJSON_free(new_path); + return; + } + sprintf((char*)new_path, "%s/%lu", path, (unsigned long)index); /* path of the current array element */ + create_patches(patches, new_path, from_child, to_child, case_sensitive); + } + + /* remove leftover elements from 'from' that are not in 'to' */ + for (; (from_child != NULL); (void)(from_child = from_child->next)) + { + /* check if conversion to unsigned long is valid + * This should be eliminated at compile time by dead code elimination + * if size_t is an alias of unsigned long, or if it is bigger */ + if (index > ULONG_MAX) + { + cJSON_free(new_path); + return; + } + sprintf((char*)new_path, "%lu", (unsigned long)index); + compose_patch(patches, (const unsigned char*)"remove", path, new_path, NULL); + } + /* add new elements in 'to' that were not in 'from' */ + for (; (to_child != NULL); (void)(to_child = to_child->next), index++) + { + compose_patch(patches, (const unsigned char*)"add", path, (const unsigned char*)"-", to_child); + } + cJSON_free(new_path); + return; + } + + case cJSON_Object: + { + cJSON *from_child = NULL; + cJSON *to_child = NULL; + sort_object(from, case_sensitive); + sort_object(to, case_sensitive); + + from_child = from->child; + to_child = to->child; + /* for all object values in the object with more of them */ + while ((from_child != NULL) || (to_child != NULL)) + { + int diff; + if (from_child == NULL) + { + diff = 1; + } + else if (to_child == NULL) + { + diff = -1; + } + else + { + diff = compare_strings((unsigned char*)from_child->string, (unsigned char*)to_child->string, case_sensitive); + } + + if (diff == 0) + { + /* both object keys are the same */ + size_t path_length = strlen((const char*)path); + size_t from_child_name_length = pointer_encoded_length((unsigned char*)from_child->string); + unsigned char *new_path = (unsigned char*)cJSON_malloc(path_length + from_child_name_length + sizeof("/")); + + sprintf((char*)new_path, "%s/", path); + encode_string_as_pointer(new_path + path_length + 1, (unsigned char*)from_child->string); + + /* create a patch for the element */ + create_patches(patches, new_path, from_child, to_child, case_sensitive); + cJSON_free(new_path); + + from_child = from_child->next; + to_child = to_child->next; + } + else if (diff < 0) + { + /* object element doesn't exist in 'to' --> remove it */ + compose_patch(patches, (const unsigned char*)"remove", path, (unsigned char*)from_child->string, NULL); + + from_child = from_child->next; + } + else + { + /* object element doesn't exist in 'from' --> add it */ + compose_patch(patches, (const unsigned char*)"add", path, (unsigned char*)to_child->string, to_child); + + to_child = to_child->next; + } + } + return; + } + + default: + break; + } +} + +CJSON_PUBLIC(cJSON *) cJSONUtils_GeneratePatches(cJSON * const from, cJSON * const to) +{ + cJSON *patches = NULL; + + if ((from == NULL) || (to == NULL)) + { + return NULL; + } + + patches = cJSON_CreateArray(); + create_patches(patches, (const unsigned char*)"", from, to, false); + + return patches; +} + +CJSON_PUBLIC(cJSON *) cJSONUtils_GeneratePatchesCaseSensitive(cJSON * const from, cJSON * const to) +{ + cJSON *patches = NULL; + + if ((from == NULL) || (to == NULL)) + { + return NULL; + } + + patches = cJSON_CreateArray(); + create_patches(patches, (const unsigned char*)"", from, to, true); + + return patches; +} + +CJSON_PUBLIC(void) cJSONUtils_SortObject(cJSON * const object) +{ + sort_object(object, false); +} + +CJSON_PUBLIC(void) cJSONUtils_SortObjectCaseSensitive(cJSON * const object) +{ + sort_object(object, true); +} + +static cJSON *merge_patch(cJSON *target, const cJSON * const patch, const cJSON_bool case_sensitive) +{ + cJSON *patch_child = NULL; + + if (!cJSON_IsObject(patch)) + { + /* scalar value, array or NULL, just duplicate */ + cJSON_Delete(target); + return cJSON_Duplicate(patch, 1); + } + + if (!cJSON_IsObject(target)) + { + cJSON_Delete(target); + target = cJSON_CreateObject(); + } + + patch_child = patch->child; + while (patch_child != NULL) + { + if (cJSON_IsNull(patch_child)) + { + /* NULL is the indicator to remove a value, see RFC7396 */ + if (case_sensitive) + { + cJSON_DeleteItemFromObjectCaseSensitive(target, patch_child->string); + } + else + { + cJSON_DeleteItemFromObject(target, patch_child->string); + } + } + else + { + cJSON *replace_me = NULL; + cJSON *replacement = NULL; + + if (case_sensitive) + { + replace_me = cJSON_DetachItemFromObjectCaseSensitive(target, patch_child->string); + } + else + { + replace_me = cJSON_DetachItemFromObject(target, patch_child->string); + } + + replacement = merge_patch(replace_me, patch_child, case_sensitive); + if (replacement == NULL) + { + cJSON_Delete(target); + return NULL; + } + + cJSON_AddItemToObject(target, patch_child->string, replacement); + } + patch_child = patch_child->next; + } + return target; +} + +CJSON_PUBLIC(cJSON *) cJSONUtils_MergePatch(cJSON *target, const cJSON * const patch) +{ + return merge_patch(target, patch, false); +} + +CJSON_PUBLIC(cJSON *) cJSONUtils_MergePatchCaseSensitive(cJSON *target, const cJSON * const patch) +{ + return merge_patch(target, patch, true); +} + +static cJSON *generate_merge_patch(cJSON * const from, cJSON * const to, const cJSON_bool case_sensitive) +{ + cJSON *from_child = NULL; + cJSON *to_child = NULL; + cJSON *patch = NULL; + if (to == NULL) + { + /* patch to delete everything */ + return cJSON_CreateNull(); + } + if (!cJSON_IsObject(to) || !cJSON_IsObject(from)) + { + return cJSON_Duplicate(to, 1); + } + + sort_object(from, case_sensitive); + sort_object(to, case_sensitive); + + from_child = from->child; + to_child = to->child; + patch = cJSON_CreateObject(); + if (patch == NULL) + { + return NULL; + } + while (from_child || to_child) + { + int diff; + if (from_child != NULL) + { + if (to_child != NULL) + { + diff = strcmp(from_child->string, to_child->string); + } + else + { + diff = -1; + } + } + else + { + diff = 1; + } + + if (diff < 0) + { + /* from has a value that to doesn't have -> remove */ + cJSON_AddItemToObject(patch, from_child->string, cJSON_CreateNull()); + + from_child = from_child->next; + } + else if (diff > 0) + { + /* to has a value that from doesn't have -> add to patch */ + cJSON_AddItemToObject(patch, to_child->string, cJSON_Duplicate(to_child, 1)); + + to_child = to_child->next; + } + else + { + /* object key exists in both objects */ + if (!compare_json(from_child, to_child, case_sensitive)) + { + /* not identical --> generate a patch */ + cJSON_AddItemToObject(patch, to_child->string, cJSONUtils_GenerateMergePatch(from_child, to_child)); + } + + /* next key in the object */ + from_child = from_child->next; + to_child = to_child->next; + } + } + if (patch->child == NULL) + { + /* no patch generated */ + cJSON_Delete(patch); + return NULL; + } + + return patch; +} + +CJSON_PUBLIC(cJSON *) cJSONUtils_GenerateMergePatch(cJSON * const from, cJSON * const to) +{ + return generate_merge_patch(from, to, false); +} + +CJSON_PUBLIC(cJSON *) cJSONUtils_GenerateMergePatchCaseSensitive(cJSON * const from, cJSON * const to) +{ + return generate_merge_patch(from, to, true); +} diff --git a/middleware/cjson/cjson-master/cjson-master/cJSON_Utils.h b/middleware/cjson/cjson-master/cjson-master/cJSON_Utils.h new file mode 100644 index 0000000..a970c65 --- /dev/null +++ b/middleware/cjson/cjson-master/cjson-master/cJSON_Utils.h @@ -0,0 +1,88 @@ +/* + Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + + 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_Utils__h +#define cJSON_Utils__h + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "cJSON.h" + +/* Implement RFC6901 (https://tools.ietf.org/html/rfc6901) JSON Pointer spec. */ +CJSON_PUBLIC(cJSON *) cJSONUtils_GetPointer(cJSON * const object, const char *pointer); +CJSON_PUBLIC(cJSON *) cJSONUtils_GetPointerCaseSensitive(cJSON * const object, const char *pointer); + +/* Implement RFC6902 (https://tools.ietf.org/html/rfc6902) JSON Patch spec. */ +/* NOTE: This modifies objects in 'from' and 'to' by sorting the elements by their key */ +CJSON_PUBLIC(cJSON *) cJSONUtils_GeneratePatches(cJSON * const from, cJSON * const to); +CJSON_PUBLIC(cJSON *) cJSONUtils_GeneratePatchesCaseSensitive(cJSON * const from, cJSON * const to); +/* Utility for generating patch array entries. */ +CJSON_PUBLIC(void) cJSONUtils_AddPatchToArray(cJSON * const array, const char * const operation, const char * const path, const cJSON * const value); +/* Returns 0 for success. */ +CJSON_PUBLIC(int) cJSONUtils_ApplyPatches(cJSON * const object, const cJSON * const patches); +CJSON_PUBLIC(int) cJSONUtils_ApplyPatchesCaseSensitive(cJSON * const object, const cJSON * const patches); + +/* +// Note that ApplyPatches is NOT atomic on failure. To implement an atomic ApplyPatches, use: +//int cJSONUtils_AtomicApplyPatches(cJSON **object, cJSON *patches) +//{ +// cJSON *modme = cJSON_Duplicate(*object, 1); +// int error = cJSONUtils_ApplyPatches(modme, patches); +// if (!error) +// { +// cJSON_Delete(*object); +// *object = modme; +// } +// else +// { +// cJSON_Delete(modme); +// } +// +// return error; +//} +// Code not added to library since this strategy is a LOT slower. +*/ + +/* Implement RFC7386 (https://tools.ietf.org/html/rfc7396) JSON Merge Patch spec. */ +/* target will be modified by patch. return value is new ptr for target. */ +CJSON_PUBLIC(cJSON *) cJSONUtils_MergePatch(cJSON *target, const cJSON * const patch); +CJSON_PUBLIC(cJSON *) cJSONUtils_MergePatchCaseSensitive(cJSON *target, const cJSON * const patch); +/* generates a patch to move from -> to */ +/* NOTE: This modifies objects in 'from' and 'to' by sorting the elements by their key */ +CJSON_PUBLIC(cJSON *) cJSONUtils_GenerateMergePatch(cJSON * const from, cJSON * const to); +CJSON_PUBLIC(cJSON *) cJSONUtils_GenerateMergePatchCaseSensitive(cJSON * const from, cJSON * const to); + +/* Given a root object and a target object, construct a pointer from one to the other. */ +CJSON_PUBLIC(char *) cJSONUtils_FindPointerFromObjectTo(const cJSON * const object, const cJSON * const target); + +/* Sorts the members of the object into alphabetical order. */ +CJSON_PUBLIC(void) cJSONUtils_SortObject(cJSON * const object); +CJSON_PUBLIC(void) cJSONUtils_SortObjectCaseSensitive(cJSON * const object); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/middleware/easyflash/inc/ef_cfg.h b/middleware/easyflash/inc/ef_cfg.h index 919b2c3..e9db4eb 100644 --- a/middleware/easyflash/inc/ef_cfg.h +++ b/middleware/easyflash/inc/ef_cfg.h @@ -34,12 +34,12 @@ #ifdef EF_USING_ENV /* Auto update ENV to latest default when current ENV version number is changed. */ -/* #define EF_ENV_AUTO_UPDATE */ +#define EF_ENV_AUTO_UPDATE /** * ENV version number defined by user. * Please change it when your firmware add a new ENV to default_env_set. */ -#define EF_ENV_VER_NUM 0 /* @note you must define it for a value, such as 0 */ +#define EF_ENV_VER_NUM 3 /* @note you must define it for a value, such as 0 */ /* MCU Endian Configuration, default is Little Endian Order. */ /* #define EF_BIG_ENDIAN */ diff --git a/middleware/easyflash/port/ef_port.c b/middleware/easyflash/port/ef_port.c index bf4450f..2b8db12 100644 --- a/middleware/easyflash/port/ef_port.c +++ b/middleware/easyflash/port/ef_port.c @@ -43,7 +43,7 @@ static const ef_env default_env_set[] = { {"boot_times", "0"}, {"jump_boot_time", "10"}, // BOOT 等待时间 10s // 基础参数设置 - {"device_id", "0000000003"}, + {"device_id", "7322070012"}, {"app_id", "220000"}, // 业务ID {"user_pass", "123456"}, {"sys_pass", "898909"}, @@ -51,7 +51,7 @@ static const ef_env default_env_set[] = { {"mqtt_pass", "admin"}, {"mqtt_addr", "mqtt.zyjzjs.cn"}, {"mqtt_port", "1883"}, - {"mqtt_topic", "sluice"}, //订阅topic + {"mqtt_topic", "syksk"}, //订阅topic {"net_drv", "dtu"}, // mqtt dtu ec200 eth {"eth2_chann", "0"}, //以太网通道2 支持modbus @@ -82,9 +82,9 @@ static const ef_env default_env_set[] = { {"pwm4", "0"}, // PWM4功能 // 闸门参数设置 - {"max_open", "1400"}, // 最大开度 - {"max_ecode", "31241"}, // 编码器最大编码 - {"min_ecode", "32828"}, // 编码器最小编码 + {"max_open", "1600"}, // 最大开度 + {"max_ecode", "25712"}, // 编码器最大编码 + {"min_ecode", "31770"}, // 编码器最小编码 {"exec_time", "50"}, // 异常检测时间 单位100ms 50 就是 5s // 闸门参数设置 @@ -98,7 +98,11 @@ static const ef_env default_env_set[] = { {"site_type", "sluice"}, // 0,闸门站,1,流量站,2,渗流渗压站,3,自动化采集站,4,串口服务器 {"level","[0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0]"}, {"flow", "[0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0]"}, - {"wsid","[128,2,3,4,5,6]"}, + {"wsid","[1,2,3,4,5,6]"}, + {"sl427ip","116.176.77.72"}, + {"sl427port","6200"}, + {"sl427code","0000000002"}, + // 水位流量关系表 配置10 个点