| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447 |
- /*
- * YM310 Protocol Handler - v1.1 (Optimized)
- *
- * 功能:处理 MQTT 接收到的 JSON 协议,执行相应操作并回复。
- * 依赖:cJSON, EasyFlash, RT-Thread, YM310 MQTT 驱动。
- *
- * Version: 1.1.0
- */
- /*********************↓ define ↓************************/
- #define DBG_TAG "Y-RPT"
- #define DBG_LVL DBG_INFO
- /*********************↑ define ↑************************/
- /*********************↓ include ↓************************/
- #include <rtdbg.h>
- #include <rtthread.h>
- #include <easyflash.h>
- #include <cJSON.h>
- #include <board.h>
- #include <string.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include "ym310_mqtt.h"
- #include "ym310_protecl.h"
- #include "main.h"
- #include "ecode.h"
- /*********************↑ include ↑************************/
- /*********************↓ extern ↓************************/
- extern struct rtc_time time_now;
- extern char update_res;
- extern char upload_res;
- typedef struct
- {
- char username[32];
- char password[32];
- char host[64];
- rt_uint16_t port;
- char filename[128];
- } ftp_url_info_t;
- extern int ym310_ftp_parse_url(const char *url, ftp_url_info_t *info);
- extern void once_test_tig(void);
- extern rt_bool_t gpio_lamp_get_status(void);
- extern uint8_t read_platform_flag(void);
- extern void hv_save(uint32_t c);
- extern uint32_t hv_read(void);
- extern void RESET_ALL_PARA(void);
- /*********************↑ extern ↑************************/
- /********************↓ declaration ↓***********************/
- typedef enum
- {
- WORK_STATE_IDLE = 0,
- WORK_STATE_WORKING,
- WORK_STATE_LIGHT_PRT,
- WORK_STATE_COOLDOWN,
- WORK_STATE_WAIT_DAY,
- WORK_STATE_OTHER_PRT
- } Work_status;
- static void format_time(char *buf, size_t size, const struct rtc_time *tm);
- void ym310_data_report(rt_uint8_t client_idx);
- int ym310_warn_report(const char *detail);
- static cJSON *build_devinfo_report(void);
- static cJSON *build_data_report(void);
- static cJSON *build_paramconf_response(void);
- static cJSON *build_serverconf_response(void);
- static cJSON *build_simple_response(const char *cmd, int result);
- static void send_response(rt_uint8_t client_idx, cJSON *resp);
- static void handle_read(rt_uint8_t client_idx, cJSON *root);
- static void handle_set_scdparam(rt_uint8_t client_idx, cJSON *root);
- static void handle_thirdserverconf(rt_uint8_t client_idx, cJSON *root);
- static void handle_paramconf(rt_uint8_t client_idx, cJSON *root);
- static void handle_test(rt_uint8_t client_idx, cJSON *root);
- static void handle_reboot(rt_uint8_t client_idx, cJSON *root);
- static void handle_update_stm32(rt_uint8_t client_idx, cJSON *root);
- static void process_json(rt_uint8_t client_idx, const char *payload);
- static void handle_platform(rt_uint8_t client_idx, cJSON *root);
- static void handle_read_ecode(rt_uint8_t client_idx, cJSON *root);
- static void handle_read_update_url(rt_uint8_t client_idx, cJSON *root);
- static void handle_set_update_url(rt_uint8_t client_idx, cJSON *root);
- static void handle_sensor(rt_uint8_t client_idx, cJSON *root);
- static void handle_read_sensor(rt_uint8_t client_idx, cJSON *root);
- static void handle_read_status(rt_uint8_t client_idx, cJSON *root);
- static void handle_chg_light_type(rt_uint8_t client_idx, cJSON *root);
- static void handle_location(rt_uint8_t client_idx, cJSON *root);
- static void handle_upload_ecode(rt_uint8_t client_idx, cJSON *root);
- static void handle_get_devinfo(rt_uint8_t client_idx, cJSON *root);
- static void handle_FORCE_RESET(rt_uint8_t client_idx, cJSON *root);
- static void handle_lamp_proc_on(rt_uint8_t client_idx, cJSON *root);
- static void handle_lamp_proc_off(rt_uint8_t client_idx, cJSON *root);
- static void handle_SCDV3_UP_FIRMWARE(rt_uint8_t client_idx, cJSON *root);
- /********************↑ declaration ↑***********************/
- /*********************↓ global variables ↓************************/
- SYS_INFO sys_info = {0};
- DEV_INFO dev_info = {0};
- LIMIT limit = {0};
- sensor_t sensor = {0};
- SYS_STATUS sys_sta = {0}; // 不保存
- uint8_t g_work_state = 0;
- uint8_t g_work_mode = 0;
- uint32_t g_work_elapsed_sec = 0;
- uint32_t g_work_total_sec = 0;
- uint8_t g_work_progress = 0;
- uint32_t g_cooldown_sec = 0;
- uint8_t g_work_start_hour = 0;
- uint8_t g_work_start_minute = 0;
- /*********************↑ global variables ↑************************/
- /*********************↓ function definitions ↓***********************/
- static void format_time(char *buf, size_t size, const struct rtc_time *tm)
- {
- rt_snprintf(buf, size, "%04d%02d%02d%02d%02d%02d",
- tm->year, tm->month, tm->date,
- tm->hour, tm->minute, tm->second);
- }
- char *version_with_time(void)
- {
- static char version[40];
- char *MonthTable[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
- uint8_t i;
- char time[40];
- char month_s[10];
- int month_v = 0;
- int day_v;
- int year_v;
- int hour_v;
- int min_v;
- int sec_v;
- rt_sprintf((char *)time, "%s %s\r\n", __DATE__, __TIME__);
- sscanf(time, "%s %d %d %d:%d:%d", month_s, &day_v, &year_v, &hour_v, &min_v, &sec_v);
- for (i = 0; i < sizeof(MonthTable) / sizeof(MonthTable[0]); i++)
- {
- if (rt_strstr(month_s, (char *)MonthTable[i]))
- {
- month_v = i + 1;
- break;
- }
- }
- rt_sprintf(version, "%d.%d.%d-%04d/%02d/%02d/%02d/%02d", SCD_VERSION / 100, SCD_VERSION % 100 / 10, SCD_VERSION % 10, year_v, month_v, day_v, hour_v, min_v);
- return version;
- }
- /**
- * @brief 处理读取 update_url 指令
- * JSON格式: {"cmd":"read_update_url"}
- */
- static void handle_read_update_url(rt_uint8_t client_idx, cJSON *root)
- {
- (void)root; /* 不需要解析ext */
- cJSON *resp = cJSON_CreateObject();
- if (!resp)
- {
- LOG_E("read_update_url: Failed to create response");
- return;
- }
- cJSON_AddStringToObject(resp, "cmd", "read_update_url");
- cJSON *ext = cJSON_CreateObject();
- if (!ext)
- {
- cJSON_Delete(resp);
- LOG_E("read_update_url: Failed to create ext object");
- return;
- }
- cJSON_AddItemToObject(resp, "ext", ext);
- cJSON_AddStringToObject(ext, "url", sys_info.update_url);
- cJSON_AddNumberToObject(ext, "len", strlen(sys_info.update_url));
- LOG_I("read_update_url: url=%s", sys_info.update_url);
- send_response(client_idx, resp);
- }
- /**
- * @brief 处理设置 update_url 指令
- * JSON格式: {"cmd":"set_update_url","ext":{"url":"ftp://..."}}
- */
- static void handle_set_update_url(rt_uint8_t client_idx, cJSON *root)
- {
- cJSON *ext = cJSON_GetObjectItem(root, "ext");
- if (!ext || !cJSON_IsObject(ext))
- {
- LOG_E("set_update_url: missing ext object");
- cJSON *resp = build_simple_response("设置失败:缺少 ext对象", -1);
- if (resp)
- send_response(client_idx, resp);
- return;
- }
- cJSON *url_json = cJSON_GetObjectItem(ext, "url");
- if (!url_json || !cJSON_IsString(url_json))
- {
- LOG_E("set_update_url: missing or invalid url string");
- cJSON *resp = build_simple_response("设置失败:缺少url字段", -1);
- if (resp)
- send_response(client_idx, resp);
- return;
- }
- const char *new_url = url_json->valuestring;
- if (!new_url || strlen(new_url) == 0)
- {
- LOG_E("set_update_url: url is empty");
- cJSON *resp = build_simple_response("设置失败:URL 为空字符串", -2);
- if (resp)
- send_response(client_idx, resp);
- return;
- }
- if (strlen(new_url) >= sizeof(sys_info.update_url))
- {
- LOG_E("set_update_url: url too long (%d >= %d)",
- strlen(new_url), sizeof(sys_info.update_url));
- cJSON *resp = build_simple_response("设置失败:URL太长 (128B MAX)", -3);
- if (resp)
- send_response(client_idx, resp);
- return;
- }
- ftp_url_info_t url_info;
- if (ym310_ftp_parse_url(new_url, &url_info) != RT_EOK)
- {
- LOG_E("set_update_url: invalid FTP URL format");
- cJSON *resp = build_simple_response("设置失败:URL格式无效", -4);
- if (resp)
- send_response(client_idx, resp);
- return;
- }
- if (strlen(url_info.host) == 0 || strlen(url_info.filename) == 0)
- {
- LOG_E("set_update_url: parsed host or filename empty");
- cJSON *resp = build_simple_response("设置失败:解析后关键字段为空", -5);
- if (resp)
- send_response(client_idx, resp);
- return;
- }
- memset(sys_info.update_url, 0, sizeof(sys_info.update_url));
- strncpy(sys_info.update_url, new_url, sizeof(sys_info.update_url) - 1);
- sys_info.update_url[sizeof(sys_info.update_url) - 1] = '\0';
- save_sys_info();
- LOG_I("set_update_url: URL updated and saved: %s", sys_info.update_url);
- LOG_I(" parsed: host=%s, port=%d, file=%s",
- url_info.host, url_info.port, url_info.filename);
- cJSON *resp = cJSON_CreateObject();
- if (resp)
- {
- cJSON_AddStringToObject(resp, "cmd", "set_update_url");
- cJSON_AddStringToObject(resp, "result", "OK");
- cJSON *resp_ext = cJSON_CreateObject();
- if (resp_ext)
- {
- cJSON_AddStringToObject(resp_ext, "url", sys_info.update_url);
- cJSON_AddStringToObject(resp_ext, "host", url_info.host);
- cJSON_AddNumberToObject(resp_ext, "port", url_info.port);
- cJSON_AddStringToObject(resp_ext, "filename", url_info.filename);
- cJSON_AddItemToObject(resp, "ext", resp_ext);
- }
- send_response(client_idx, resp);
- }
- }
- static cJSON *build_data_report(void)
- {
- cJSON *root = cJSON_CreateObject();
- if (!root)
- return NULL;
- cJSON_AddStringToObject(root, "cmd", "data");
- cJSON *ext = cJSON_CreateObject();
- if (!ext)
- {
- cJSON_Delete(root);
- return NULL;
- }
- cJSON_AddItemToObject(root, "ext", ext);
- char stamp[15];
- format_time(stamp, sizeof(stamp), &time_now);
- cJSON_AddStringToObject(ext, "stamp", stamp);
- uint32_t start_time = 0;
- ef_get_env_blob("start_time", &start_time, sizeof(start_time), NULL);
- cJSON_AddStringToObject(ext, "imei", sys_info.imei);
- cJSON_AddStringToObject(ext, "iccid", sys_info.iccid);
- cJSON_AddStringToObject(ext, "stm8vs", version_with_time());
- cJSON_AddStringToObject(ext, "dver", version_with_time());
- char num_buf[16];
- // csq
- rt_snprintf(num_buf, sizeof(num_buf), "%u", sys_info.csq);
- cJSON_AddStringToObject(ext, "csq", num_buf);
- // dtype
- rt_snprintf(num_buf, sizeof(num_buf), "%u", DEVICE_TYPE);
- cJSON_AddStringToObject(ext, "dtype", num_buf);
- // rcnt
- rt_snprintf(num_buf, sizeof(num_buf), "%u", start_time);
- cJSON_AddStringToObject(ext, "rcnt", num_buf);
- // ws
- rt_snprintf(num_buf, sizeof(num_buf), "%u", sys_sta.work_state);
- cJSON_AddStringToObject(ext, "ws", num_buf);
- // ds
- rt_snprintf(num_buf, sizeof(num_buf), "%u", dev_info.power_state);
- cJSON_AddStringToObject(ext, "ds", num_buf);
- // tt
- rt_snprintf(num_buf, sizeof(num_buf), "%u", dev_info.light_work_duration);
- cJSON_AddStringToObject(ext, "tt", num_buf);
- // ts
- rt_snprintf(num_buf, sizeof(num_buf), "%u", dev_info.time_ctrl_enable);
- cJSON_AddStringToObject(ext, "ts", num_buf);
- // st
- rt_snprintf(num_buf, sizeof(num_buf), "%u", dev_info.time_start);
- cJSON_AddStringToObject(ext, "st", num_buf);
- // et
- rt_snprintf(num_buf, sizeof(num_buf), "%u", dev_info.time_end);
- cJSON_AddStringToObject(ext, "et", num_buf);
- // vps
- if (sys_sta.undervolt_protect == VALID)
- {
- cJSON_AddStringToObject(ext, "vps", "1");
- }
- else
- {
- cJSON_AddStringToObject(ext, "vps", "0");
- }
- // tps
- if (sys_sta.temp_protect == 0x7A)
- {
- cJSON_AddStringToObject(ext, "tps", "1");
- }
- else if (sys_sta.temp_protect == VALID)
- {
- cJSON_AddStringToObject(ext, "tps", "2");
- }
- else
- {
- cJSON_AddStringToObject(ext, "tps", "0");
- }
- // dps
- if (sys_sta.tilt_protect == VALID)
- {
- cJSON_AddStringToObject(ext, "dps", "1");
- }
- else
- {
- cJSON_AddStringToObject(ext, "dps", "0");
- }
- // rps
- if (sys_sta.rain_protect == VALID)
- {
- cJSON_AddStringToObject(ext, "rps", "1");
- }
- else
- {
- cJSON_AddStringToObject(ext, "rps", "0");
- }
- if (sys_sta.light_protect == VALID)
- {
- cJSON_AddStringToObject(ext, "lps", "1");
- }
- else
- {
- cJSON_AddStringToObject(ext, "lps", "0");
- }
- // ct
- rt_snprintf(num_buf, sizeof(num_buf), "%u", sys_sta.hv_count);
- cJSON_AddStringToObject(ext, "ct", num_buf);
- // 电压部分
- char buf[16];
- // 充电电压
- int cv_int = sys_sta.charge_voltage / 1000;
- int cv_dec = sys_sta.charge_voltage % 1000;
- rt_snprintf(buf, sizeof(buf), "%d.%03d", cv_int, cv_dec);
- cJSON_AddStringToObject(ext, "cv", buf);
- // 电池电压
- int bv_int = sys_sta.battery_voltage / 1000;
- int bv_dec = sys_sta.battery_voltage % 1000;
- rt_snprintf(buf, sizeof(buf), "%d.%03d", bv_int, bv_dec);
- cJSON_AddStringToObject(ext, "bv", buf);
- // 主板温度
- int bt_int = sys_sta.board_temp / 10;
- rt_snprintf(buf, sizeof(buf), "%d", bt_int);
- cJSON_AddStringToObject(ext, "bt", buf);
- /* ========== 传感器数据联动逻辑 ==========
- * 优先级:SHT30 > (NTC温度 + PLAT湿度) > PLAT > 默认值
- * - 温度:SHT30 > NTC > PLAT > 22.0
- * - 湿度:SHT30 > PLAT > 33.0
- */
- uint8_t temp_source = 0; /* 温度来源:1=SHT,2=NTC,3=PLAT,4=默认 */
- uint8_t humi_source = 0; /* 湿度来源:1=SHT,2=PLAT,3=默认 */
- /* 1. 优先使用 SHT30 数据 */
- if (sensor.valid_sht == VALID)
- {
- temp_source = 1;
- humi_source = 1;
- LOG_D("Sensor: using SHT30 data (temp=%d.%d°C, humi=%d.%d%%)",
- sensor.temp_sht / 10, sensor.temp_sht % 10,
- sensor.humi_sht / 10, sensor.humi_sht % 10);
- }
- /* 2. SHT30 不可用,尝试组合:NTC温度 + PLAT湿度 */
- else if (sensor.valid_ntc == VALID && sensor.valid_plat == VALID)
- {
- temp_source = 2;
- humi_source = 2;
- LOG_D("Sensor: using NTC temp + PLAT humi (temp=%d.%d°C, humi=%d.%d%%)",
- sensor.temp_ntc / 10, sensor.temp_ntc % 10,
- sensor.humi_plat / 10, sensor.humi_plat % 10);
- }
- /* 4. 使用 NTC 温度,湿度使用默认值 */
- else if (sensor.valid_ntc == VALID)
- {
- temp_source = 2;
- humi_source = 3;
- LOG_D("Sensor: using NTC temp only (temp=%d.%d°C), humidity default 33.0%%",
- sensor.temp_ntc / 10, sensor.temp_ntc % 10);
- }
- /* 3. 使用 PLAT 数据 */
- else if (sensor.valid_plat == VALID)
- {
- temp_source = 3;
- humi_source = 2;
- LOG_D("Sensor: using PLAT data (temp=%d.%d°C, humi=%d.%d%%)",
- sensor.temp_plat / 10, sensor.temp_plat % 10,
- sensor.humi_plat / 10, sensor.humi_plat % 10);
- }
- /* 5. 所有传感器都无效,使用默认值 */
- else
- {
- temp_source = 4;
- humi_source = 3;
- LOG_W("Sensor: ALL sensors invalid, using default values (temp=22.0°C, humi=33.0%%)");
- }
- switch (temp_source)
- {
- case 1:
- cJSON_AddStringToObject(ext, "at_source", "SHT30");
- rt_snprintf(buf, sizeof(buf), "%d.%d", sensor.temp_sht / 10, sensor.temp_sht % 10);
- cJSON_AddStringToObject(ext, "at", buf);
- break;
- case 2:
- cJSON_AddStringToObject(ext, "at_source", "NTC");
- rt_snprintf(buf, sizeof(buf), "%d.%d", sensor.temp_ntc / 10, sensor.temp_ntc % 10);
- cJSON_AddStringToObject(ext, "at", buf);
- break;
- case 3:
- cJSON_AddStringToObject(ext, "at_source", "PLAT");
- rt_snprintf(buf, sizeof(buf), "%d.%d", sensor.temp_plat / 10, sensor.temp_plat % 10);
- cJSON_AddStringToObject(ext, "at", buf);
- break;
- case 4:
- cJSON_AddStringToObject(ext, "at_source", "default");
- rt_snprintf(buf, sizeof(buf), "%d.%d", 22 / 10, 22 % 10);
- cJSON_AddStringToObject(ext, "at", buf);
- break;
- default:
- break;
- }
- switch (humi_source)
- {
- case 1:
- cJSON_AddStringToObject(ext, "ah_source", "SHT30");
- rt_snprintf(buf, sizeof(buf), "%d.%d", sensor.humi_sht / 10, sensor.humi_sht % 10);
- cJSON_AddStringToObject(ext, "ah", buf);
- break;
- case 2:
- cJSON_AddStringToObject(ext, "ah_source", "PLAT");
- rt_snprintf(buf, sizeof(buf), "%d.%d", sensor.humi_plat / 10, sensor.humi_plat % 10);
- cJSON_AddStringToObject(ext, "ah", buf);
- break;
- case 3:
- cJSON_AddStringToObject(ext, "ah_source", "default");
- rt_snprintf(buf, sizeof(buf), "%d.%d", 33 / 10, 33 % 10);
- cJSON_AddStringToObject(ext, "ah", buf);
- break;
- default:
- break;
- }
- if (sys_sta.lamp_fault == VALID) // 短路
- {
- cJSON_AddStringToObject(ext, "voltval", "2");
- }
- else if (sys_sta.lamp_fault == 0x7A) // 开路
- {
- cJSON_AddStringToObject(ext, "voltval", "3");
- }
- else if (gpio_lamp_get_status()) // 开
- {
- cJSON_AddStringToObject(ext, "voltval", "1");
- }
- else // 关
- {
- cJSON_AddStringToObject(ext, "voltval", "0");
- }
- /* 灯管故障 */
- // cycle_off
- rt_snprintf(num_buf, sizeof(num_buf), "%u", sys_sta.idle_flag);
- cJSON_AddStringToObject(ext, "cycle_off", num_buf);
- // dat_f
- rt_snprintf(num_buf, sizeof(num_buf), "%u", dev_info.data_interval);
- cJSON_AddStringToObject(ext, "dat_f", num_buf);
- // clt_t
- rt_snprintf(num_buf, sizeof(num_buf), "%u", dev_info.clean_interval);
- cJSON_AddStringToObject(ext, "clt_t", num_buf);
- // clear_on
- rt_snprintf(num_buf, sizeof(num_buf), "%u", dev_info.clean_enable);
- cJSON_AddStringToObject(ext, "clear_on", num_buf);
- // gps
- rt_snprintf(num_buf, sizeof(num_buf), "%u", dev_info.GPS_MODE);
- cJSON_AddStringToObject(ext, "gps", num_buf);
- if (dev_info.GPS_MODE == 0)
- {
- cJSON_AddStringToObject(ext, "lat", dev_info.latitude_FORCE);
- cJSON_AddStringToObject(ext, "lng", dev_info.longitude_FORCE);
- }
- else if (dev_info.GPS_MODE == 1)
- {
- cJSON_AddStringToObject(ext, "lat", dev_info.latitude);
- cJSON_AddStringToObject(ext, "lng", dev_info.longitude);
- }
- cJSON_AddNumberToObject(ext, "light_pct", sys_sta.light_percent / 10 + (sys_sta.light_percent % 10 / 5));
- cJSON_AddNumberToObject(ext, "lamp_current", sys_sta.lamp_current);
- if (dev_info.light_flag == 0)
- {
- cJSON_AddStringToObject(ext, "light_source", "太阳能板");
- }
- else if (dev_info.light_flag == 1)
- {
- cJSON_AddStringToObject(ext, "light_source", "光敏管");
- }
- cJSON_AddStringToObject(ext, "scd_ver", "3");
- return root;
- }
- /**
- * @brief 构建数据上报响应(副平台格式)
- * JSON格式: {"cmd":"data","ext":{...}}
- * 对应查询指令: {"cmd":"read","ext":"data"}
- */
- static cJSON *build_data_report_vice(void)
- {
- cJSON *root = cJSON_CreateObject();
- if (!root)
- {
- LOG_E("build_data_report_vice: failed to create root");
- return NULL;
- }
- cJSON_AddStringToObject(root, "cmd", "data");
- cJSON *ext = cJSON_CreateObject();
- if (!ext)
- {
- LOG_E("build_data_report_vice: failed to create ext");
- cJSON_Delete(root);
- return NULL;
- }
- cJSON_AddItemToObject(root, "ext", ext);
- /* 时间戳 */
- char stamp[15] = {0};
- format_time(stamp, sizeof(stamp), &time_now);
- cJSON_AddStringToObject(ext, "stamp", stamp);
- /* 设备标识 */
- cJSON_AddStringToObject(ext, "imei", sys_info.imei);
- cJSON_AddStringToObject(ext, "stm8vs", version_with_time());
- /* 开关机状态 ds */
- cJSON_AddNumberToObject(ext, "ds", dev_info.power_state);
- /* 时控切换标志位 tcs (等同于timctrl) */
- cJSON_AddNumberToObject(ext, "tcs", dev_info.time_ctrl_enable);
- cJSON_AddNumberToObject(ext, "tbs", 0); // 备用字段,暂时为0
- /* 充电电压 cv (mV -> V,保留整数) */
- cJSON_AddNumberToObject(ext, "cv", sys_sta.charge_voltage / 1000);
- /* 高压计数 ct */
- cJSON_AddNumberToObject(ext, "ct", sys_sta.hv_count);
- /* 欠压状态 vps */
- cJSON_AddNumberToObject(ext, "vps", sys_sta.undervolt_protect == VALID ? 1 : 0);
- /* 自清虫标记位 lcm (默认0,暂未实现) */
- cJSON_AddNumberToObject(ext, "lcm", 0);
- /* 清虫时间间隔 clt (分钟) */
- cJSON_AddNumberToObject(ext, "clt", dev_info.clean_interval);
- /* GPS源 gps */
- cJSON_AddNumberToObject(ext, "gps", dev_info.GPS_MODE);
- /* 重启次数 rcnt */
- uint32_t start_time = 0;
- ef_get_env_blob("start_time", &start_time, sizeof(start_time), NULL);
- cJSON_AddNumberToObject(ext, "rcnt", start_time);
- /* 工作状态 ws */
- cJSON_AddNumberToObject(ext, "ws", sys_sta.work_state);
- /* 经纬度 */
- if (dev_info.GPS_MODE == 0)
- {
- cJSON_AddStringToObject(ext, "lat", dev_info.latitude_FORCE);
- cJSON_AddStringToObject(ext, "lng", dev_info.longitude_FORCE);
- }
- else if (dev_info.GPS_MODE == 1)
- {
- cJSON_AddStringToObject(ext, "lat", dev_info.latitude);
- cJSON_AddStringToObject(ext, "lng", dev_info.longitude);
- }
- /* 时控时间 */
- cJSON_AddNumberToObject(ext, "st", dev_info.time_start);
- cJSON_AddNumberToObject(ext, "et", dev_info.time_end);
- cJSON_AddNumberToObject(ext, "tt", dev_info.light_work_duration);
- /* ========== 环境温度 at (浮点数转字符串) ========== */
- int16_t temp_value = 0;
- if (sensor.valid_sht == VALID)
- temp_value = sensor.temp_sht;
- else if (sensor.valid_ntc == VALID)
- temp_value = sensor.temp_ntc;
- else if (sensor.valid_plat == VALID)
- temp_value = sensor.temp_plat;
- else
- temp_value = 220; // 默认22.0°C
- cJSON_AddNumberToObject(ext, "at", temp_value); // 直接添加整数,如 302 表示 30.2°C
- /* ========== 环境湿度 ah (浮点数转字符串) ========== */
- int16_t humi_value = 0;
- if (sensor.valid_sht == VALID)
- humi_value = sensor.humi_sht;
- else if (sensor.valid_plat == VALID)
- humi_value = sensor.humi_plat;
- else
- humi_value = 330; // 默认33.0%
- cJSON_AddNumberToObject(ext, "ah", humi_value); // 直接添加整数,如 183 表示 18.3%
- /* 温控状态 tps */
- if (sys_sta.temp_protect == 0x7A)
- cJSON_AddNumberToObject(ext, "tps", 2); // 过温保护
- else if (sys_sta.temp_protect == VALID)
- cJSON_AddNumberToObject(ext, "tps", 1); // 低温保护
- else
- cJSON_AddNumberToObject(ext, "tps", 0); // 正常
- /* 雨控保护状态 rps */
- cJSON_AddNumberToObject(ext, "rps", sys_sta.rain_protect == VALID ? 1 : 0);
- /* 倾倒保护状态 dps */
- cJSON_AddNumberToObject(ext, "dps", sys_sta.tilt_protect == VALID ? 1 : 0);
- /* 光控保护状态 lps */
- cJSON_AddNumberToObject(ext, "lps", sys_sta.light_protect == VALID ? 1 : 0);
- /* 电池电压 bv (mV) */
- cJSON_AddNumberToObject(ext, "bv", sys_sta.battery_voltage);
- LOG_D("build_data_report_vice: temp=%d.%d, humi=%d.%d",
- temp_int, temp_dec, humi_int, humi_dec);
- return root;
- }
- /**
- * @brief 构建设备状态上报响应(副平台格式)
- * JSON格式: {"cmd":"status","ext":{...}}
- * 对应查询指令: {"cmd":"read","ext":"status"}
- */
- static cJSON *build_status_report_vice(void)
- {
- cJSON *root = cJSON_CreateObject();
- if (!root)
- return NULL;
- cJSON_AddStringToObject(root, "cmd", "status");
- cJSON *ext = cJSON_CreateObject();
- if (!ext)
- {
- cJSON_Delete(root);
- return NULL;
- }
- cJSON_AddItemToObject(root, "ext", ext);
- char stamp[15];
- format_time(stamp, sizeof(stamp), &time_now);
- cJSON_AddStringToObject(ext, "stamp", stamp);
- cJSON_AddStringToObject(ext, "stm8vs", version_with_time());
- cJSON_AddStringToObject(ext, "dver", version_with_time());
- cJSON_AddStringToObject(ext, "imei", sys_info.imei);
- cJSON_AddStringToObject(ext, "iccid", sys_info.iccid);
- /* 设备类型 dtype */
- cJSON_AddNumberToObject(ext, "dtype", DEVICE_TYPE);
- /* 信号强度 csq */
- cJSON_AddNumberToObject(ext, "csq", sys_info.csq);
- /* 开关机状态 ds */
- cJSON_AddNumberToObject(ext, "ds", dev_info.power_state);
- /* 时控相关 */
- cJSON_AddNumberToObject(ext, "tcs", dev_info.time_ctrl_enable);
- cJSON_AddNumberToObject(ext, "tbs", 0);
- cJSON_AddNumberToObject(ext, "st", dev_info.time_start);
- cJSON_AddNumberToObject(ext, "et", dev_info.time_end);
- cJSON_AddNumberToObject(ext, "tt", dev_info.light_work_duration);
- /* 上报间隔 dattim (分钟) */
- cJSON_AddNumberToObject(ext, "dattim", dev_info.data_interval);
- /* 清虫时间间隔 clt */
- cJSON_AddNumberToObject(ext, "clt", dev_info.clean_interval);
- cJSON_AddNumberToObject(ext, "lcm", 0);
- /* 工作状态 ws */
- cJSON_AddNumberToObject(ext, "ws", sys_sta.work_state);
- /* 保护状态 */
- cJSON_AddNumberToObject(ext, "vps", sys_sta.undervolt_protect == VALID ? 1 : 0);
- cJSON_AddNumberToObject(ext, "tps", sys_sta.temp_protect == VALID ? 1 : 0);
- cJSON_AddNumberToObject(ext, "dps", sys_sta.tilt_protect == VALID ? 1 : 0);
- cJSON_AddNumberToObject(ext, "rps", sys_sta.rain_protect == VALID ? 1 : 0);
- cJSON_AddNumberToObject(ext, "lps", sys_sta.light_protect == VALID ? 1 : 0);
- /* GPS相关 */
- cJSON_AddNumberToObject(ext, "gps", dev_info.GPS_MODE);
- cJSON_AddStringToObject(ext, "lat", dev_info.latitude);
- cJSON_AddStringToObject(ext, "lng", dev_info.longitude);
- /* 电池电压 voltval (mV,整数) */
- cJSON_AddNumberToObject(ext, "voltval", sys_sta.battery_voltage);
- /* ========== 主板温度 bt (浮点数转字符串) ========== */
- cJSON_AddNumberToObject(ext, "bt", sys_sta.board_temp); // board_temp 本来就是 *10 的值
- return root;
- }
- static cJSON *build_paramconf_response(void)
- {
- cJSON *root = cJSON_CreateObject();
- if (!root)
- return NULL;
- cJSON_AddStringToObject(root, "cmd", "Set_scdparam");
- cJSON *ext = cJSON_CreateObject();
- if (!ext)
- {
- cJSON_Delete(root);
- return NULL;
- }
- cJSON_AddItemToObject(root, "ext", ext);
- cJSON_AddNumberToObject(ext, "lcm", 0);
- cJSON_AddNumberToObject(ext, "clear_on", 0);
- cJSON_AddNumberToObject(ext, "vsunrise", limit.vsunrise);
- cJSON_AddNumberToObject(ext, "vsunset", limit.vsunset);
- cJSON_AddNumberToObject(ext, "vcutof", limit.vcutof);
- cJSON_AddNumberToObject(ext, "vfloat", limit.vfloat);
- cJSON_AddNumberToObject(ext, "vrecharge", limit.vrecharge);
- cJSON_AddNumberToObject(ext, "uvstart", limit.uvstart);
- cJSON_AddNumberToObject(ext, "uvoff", limit.uvoff);
- cJSON_AddNumberToObject(ext, "uvon", limit.uvon);
- cJSON_AddNumberToObject(ext, "overtemp", limit.overtemp);
- cJSON_AddNumberToObject(ext, "lowtemp", limit.lowtemp);
- cJSON_AddNumberToObject(ext, "unovert", limit.unovert);
- cJSON_AddNumberToObject(ext, "unlowt", limit.unlowt);
- cJSON_AddNumberToObject(ext, "battype", limit.battype);
- cJSON_AddNumberToObject(ext, "vstart", 0);
- cJSON_AddNumberToObject(ext, "version", 0);
- return root;
- }
- static cJSON *build_serverconf_response(void)
- {
- cJSON *root = cJSON_CreateObject();
- if (!root)
- return NULL;
- cJSON_AddStringToObject(root, "cmd", "serverconf");
- cJSON *ext = cJSON_CreateObject();
- if (!ext)
- {
- cJSON_Delete(root);
- return NULL;
- }
- cJSON_AddItemToObject(root, "ext", ext);
- const SERVER_CFG *cfg = &sys_info.customer_cfg;
- cJSON_AddStringToObject(ext, "sub", cfg->sub_topic);
- cJSON_AddStringToObject(ext, "pub", cfg->pub_topic);
- cJSON_AddStringToObject(ext, "ip", cfg->host);
- cJSON_AddNumberToObject(ext, "port", cfg->port);
- cJSON_AddNumberToObject(ext, "qos", cfg->qos);
- cJSON_AddStringToObject(ext, "lastwill", cfg->lastwill);
- cJSON_AddStringToObject(ext, "uid", cfg->username);
- cJSON_AddStringToObject(ext, "pwd", cfg->password);
- cJSON_AddStringToObject(ext, "cid", cfg->client_id);
- cJSON_AddNumberToObject(ext, "enable", (cfg->enable == VALID) ? 1 : 0);
- return root;
- }
- static cJSON *build_simple_response(const char *cmd, int result)
- {
- cJSON *root = cJSON_CreateObject();
- if (!root)
- return NULL;
- cJSON_AddStringToObject(root, "cmd", cmd);
- cJSON_AddStringToObject(root, "result", result == 0 ? "ok" : "error");
- return root;
- }
- static void send_response(rt_uint8_t client_idx, cJSON *resp)
- {
- if (!resp)
- return;
- char *json_str = cJSON_PrintUnformatted(resp);
- if (json_str)
- {
- LOG_D("Send response: %s", json_str);
- const char *pub_topic = g_mqtt_instances[client_idx].config.pub_topic;
- ym310_mqtt_send_to(client_idx, pub_topic, json_str, rt_strlen(json_str),
- g_mqtt_instances[client_idx].config.qos);
- cJSON_free(json_str);
- }
- cJSON_Delete(resp);
- }
- static void handle_platform(rt_uint8_t client_idx, cJSON *root)
- {
- cJSON *ext = cJSON_GetObjectItem(root, "ext");
- if (!ext || !cJSON_IsObject(ext))
- {
- LOG_E("platform missing ext object");
- return;
- }
- cJSON *type = cJSON_GetObjectItem(ext, "type");
- if (!type || !cJSON_IsString(type))
- {
- LOG_E("platform missing type string");
- return;
- }
- const char *type_str = type->valuestring;
- uint8_t new_flag;
- if (strcmp(type_str, "MAIN") == 0)
- {
- new_flag = 0x00; /* 主平台标志(非VALID) */
- Recode_e_code(e_platform_chg, 0, "指令切换->主平台");
- }
- else if (strcmp(type_str, "VICE") == 0)
- {
- new_flag = PLATFORM_VICE_MAGIC; /* VALID */
- Recode_e_code(e_platform_chg, 1, "指令切换->副平台");
- }
- else if (strcmp(type_str, "120.27.222.26") == 0)
- {
- new_flag = PLATFORM_VICE_MAGIC; /* VALID */
- Recode_e_code(e_platform_chg, 2, "平台切换->副平台");
- }
- else
- {
- LOG_W("Unknown platform type: %s", type_str);
- return;
- }
- ef_set_env_blob(EF_PLATFORM_FLAG, &new_flag, sizeof(new_flag));
- LOG_I("Platform flag set to %s, will reboot to take effect", type_str);
- cJSON *resp = build_simple_response("platform", 0);
- if (resp)
- send_response(client_idx, resp);
- rt_thread_mdelay(1000);
- rt_hw_cpu_reset();
- }
- static void handle_read(rt_uint8_t client_idx, cJSON *root)
- {
- cJSON *ext = cJSON_GetObjectItem(root, "ext");
- if (!ext || !cJSON_IsString(ext))
- {
- LOG_E("read cmd missing ext string");
- return;
- }
- const char *ext_str = ext->valuestring;
- if (strcmp(ext_str, "data") == 0)
- {
- cJSON *resp = NULL;
- if (read_platform_flag() == 0)
- {
- resp = build_data_report();
- }
- else
- {
- resp = build_data_report_vice();
- }
- if (resp)
- {
- send_response(client_idx, resp);
- }
- }
- else if (strcmp(ext_str, "status") == 0 && (read_platform_flag() == 1))
- {
- cJSON *resp = build_status_report_vice(); // 新函数
- if (resp)
- send_response(client_idx, resp);
- }
- else if (strcmp(ext_str, "paramconf") == 0)
- {
- cJSON *resp = build_paramconf_response();
- if (resp)
- send_response(client_idx, resp);
- }
- else if (strcmp(ext_str, "thirdserverconf") == 0)
- {
- cJSON *resp = build_serverconf_response();
- if (resp)
- send_response(client_idx, resp);
- }
- else
- {
- LOG_W("Unknown read ext: %s", ext_str);
- }
- }
- static void handle_set_scdparam(rt_uint8_t client_idx, cJSON *root)
- {
- cJSON *ext = cJSON_GetObjectItem(root, "ext");
- if (!ext || !cJSON_IsObject(ext))
- {
- LOG_E("Set_scdparam missing ext object");
- return;
- }
- cJSON *item;
- char need_save = 0;
- // vsunrise: 日出电压
- item = cJSON_GetObjectItem(ext, "vsunrise");
- if (item && cJSON_IsNumber(item))
- {
- int val = item->valueint;
- if (val >= 1000 && val <= 5000) // 1-5V
- {
- limit.vsunrise = val;
- need_save = 1;
- }
- else
- {
- LOG_W("vsunrise value %d out of range[1000,5000]", val);
- }
- }
- // vsunset: 日落电压
- item = cJSON_GetObjectItem(ext, "vsunset");
- if (item && cJSON_IsNumber(item))
- {
- int val = item->valueint;
- if (val >= 1000 && val <= 5000) // 1-5V
- {
- limit.vsunset = val;
- need_save = 1;
- }
- else
- {
- LOG_W("vsunset value %d out of range[1000,5000]", val);
- }
- }
- // vcutof: 截止电压
- item = cJSON_GetObjectItem(ext, "vcutof");
- if (item && cJSON_IsNumber(item))
- {
- int val = item->valueint;
- if (val >= 1000 && val <= 5000) // 1-5V
- {
- limit.vcutof = val;
- need_save = 1;
- }
- else
- {
- LOG_W("vcutof value %d out of range [1000,5000]", val);
- }
- }
- // vfloat: 浮充电压
- item = cJSON_GetObjectItem(ext, "vfloat");
- if (item && cJSON_IsNumber(item))
- {
- int val = item->valueint;
- if (val >= 1000 && val <= 5000) // 1-5V
- {
- limit.vfloat = val;
- need_save = 1;
- }
- else
- {
- LOG_W("vfloat value %d out of range [1000,5000]", val);
- }
- }
- // vrecharge: 再次开启充电电压
- item = cJSON_GetObjectItem(ext, "vrecharge");
- if (item && cJSON_IsNumber(item))
- {
- int val = item->valueint;
- if (val >= 1000 && val <= 5000) // 1-5V
- {
- limit.vrecharge = val;
- need_save = 1;
- }
- else
- {
- LOG_W("vrecharge value %d out of range[1000,5000]", val);
- }
- }
- item = cJSON_GetObjectItem(ext, "uvstart");
- if (item && cJSON_IsNumber(item))
- {
- int val = item->valueint;
- if (val >= 1000 && val <= 5000) // 1-5V
- {
- limit.uvstart = val;
- need_save = 1;
- }
- else
- {
- LOG_W("uvstart value %d out of range[1000,5000]", val);
- }
- }
- // uvoff: 欠压关闭电压
- item = cJSON_GetObjectItem(ext, "uvoff");
- if (item && cJSON_IsNumber(item))
- {
- int val = item->valueint;
- if (val >= 1000 && val <= 5000) // 1-5V
- {
- limit.uvoff = val;
- need_save = 1;
- }
- else
- {
- LOG_W("uvoff value %d out of range[1000,5000]", val);
- }
- }
- // uvon: 欠压开始电压
- item = cJSON_GetObjectItem(ext, "uvon");
- if (item && cJSON_IsNumber(item))
- {
- int val = item->valueint;
- if (val >= 1000 && val <= 5000) // 1-5V
- {
- limit.uvon = val;
- need_save = 1;
- }
- else
- {
- LOG_W("uvon value %d out of range[1000,5000]", val);
- }
- }
- // overtemp: 过温保护温度
- item = cJSON_GetObjectItem(ext, "overtemp");
- if (item && cJSON_IsNumber(item))
- {
- int val = item->valueint;
- if (val >= 30 && val <= 80)
- {
- limit.overtemp = val * 10;
- need_save = 1;
- }
- else
- {
- LOG_W("overtemp value %d out of range[30,80]", val);
- }
- }
- // lowtemp: 低温保护温度,范围 -20°C - 5°C
- item = cJSON_GetObjectItem(ext, "lowtemp");
- if (item && cJSON_IsNumber(item))
- {
- int val = item->valueint;
- if (val >= -20 && val <= 10)
- {
- limit.lowtemp = val * 10;
- need_save = 1;
- }
- else
- {
- LOG_W("lowtemp value %d out of range [-20,10]", val);
- }
- }
- // unovert: 过温恢复温度
- item = cJSON_GetObjectItem(ext, "unovert");
- if (item && cJSON_IsNumber(item))
- {
- int val = item->valueint;
- if (val >= 20 && val <= 70)
- {
- limit.unovert = val * 10;
- need_save = 1;
- }
- else
- {
- LOG_W("unovert value %d out of range [20,70]", val);
- }
- }
- // unlowt: 低温恢复温度
- item = cJSON_GetObjectItem(ext, "unlowt");
- if (item && cJSON_IsNumber(item))
- {
- int val = item->valueint;
- if (val >= -15 && val <= 15)
- {
- limit.unlowt = val * 10;
- need_save = 1;
- }
- else
- {
- LOG_W("unlowt value %d out of range [-15,15]", val);
- }
- }
- // battype: 电池类型,0-铅酸,1-锂电池,2-胶体电池等
- item = cJSON_GetObjectItem(ext, "battype");
- if (item && cJSON_IsNumber(item))
- {
- int val = item->valueint;
- if (val >= 0 && val <= 5) // 假设支持0-5种电池类型
- {
- limit.battype = val;
- need_save = 1;
- }
- else
- {
- LOG_W("battype value %d out of range [0,5]", val);
- }
- }
- if (need_save)
- {
- save_limit();
- LOG_I("Limit params updated");
- cJSON *resp = build_simple_response("Set_scdparam", 0);
- if (resp)
- send_response(client_idx, resp);
- }
- else
- {
- LOG_W("No valid parameters to update");
- cJSON *resp = build_simple_response("Set_scdparam", -1); // -1 表示参数无效
- if (resp)
- send_response(client_idx, resp);
- }
- }
- static void handle_thirdserverconf(rt_uint8_t client_idx, cJSON *root)
- {
- cJSON *ext = cJSON_GetObjectItem(root, "ext");
- if (!ext || !cJSON_IsObject(ext))
- {
- LOG_E("thirdserverconf missing ext object");
- return;
- }
- SERVER_CFG *cfg = &sys_info.customer_cfg;
- cJSON *item;
- #define UPDATE_STR(json_field, member) \
- do \
- { \
- item = cJSON_GetObjectItem(ext, json_field); \
- if (item && cJSON_IsString(item)) \
- rt_strncpy(cfg->member, item->valuestring, sizeof(cfg->member) - 1); \
- } while (0)
- #define UPDATE_INT(json_field, member) \
- do \
- { \
- item = cJSON_GetObjectItem(ext, json_field); \
- if (item && cJSON_IsNumber(item)) \
- cfg->member = item->valueint; \
- } while (0)
- UPDATE_STR("sub", sub_topic);
- UPDATE_STR("pub", pub_topic);
- UPDATE_STR("ip", host);
- UPDATE_INT("port", port);
- UPDATE_INT("qos", qos);
- UPDATE_STR("lastwill", lastwill);
- UPDATE_STR("uid", username);
- UPDATE_STR("pwd", password);
- UPDATE_STR("cid", client_id);
- #undef UPDATE_STR
- #undef UPDATE_INT
- cfg->enable = VALID;
- save_sys_info();
- LOG_I("Server config updated, enable set to VALID (will take effect after reboot)");
- Recode_e_code(e_mqtt_cmd, 2, "平台指令:修改对接服务器信息");
- cJSON *resp = build_simple_response("thirdserverconf", 0);
- if (resp)
- send_response(client_idx, resp);
- }
- static void handle_paramconf(rt_uint8_t client_idx, cJSON *root)
- {
- cJSON *ext = cJSON_GetObjectItem(root, "ext");
- if (!ext || !cJSON_IsObject(ext))
- {
- LOG_E("paramconf missing ext object");
- return;
- }
- cJSON *item;
- char need_save = 0;
- char need_restart = 0;
- item = cJSON_GetObjectItem(ext, "timctrl");
- if (item && cJSON_IsString(item))
- {
- if (atoi(item->valuestring) == 0 || atoi(item->valuestring) == 1)
- {
- if (dev_info.time_ctrl_enable != atoi(item->valuestring))
- {
- dev_info.time_ctrl_enable = atoi(item->valuestring);
- need_save = 1;
- need_restart = 1;
- if (atoi(item->valuestring))
- {
- Recode_e_code(e_mqtt_cmd, 9, "平台指令:改为时控模式");
- }
- else
- {
- Recode_e_code(e_mqtt_cmd, 9, "平台指令:改为光控模式");
- }
- }
- }
- }
- item = cJSON_GetObjectItem(ext, "st");
- if (item && cJSON_IsString(item))
- {
- if (atoi(item->valuestring) >= 0 && atoi(item->valuestring) <= 23)
- {
- if (dev_info.time_start != atoi(item->valuestring))
- {
- dev_info.time_start = atoi(item->valuestring);
- need_save = 1;
- need_restart = 1;
- Recode_e_code(e_mqtt_cmd, 3, "平台指令:修改时控开启时间");
- }
- }
- }
- item = cJSON_GetObjectItem(ext, "et");
- if (item && cJSON_IsString(item))
- {
- if (atoi(item->valuestring) >= 0 && atoi(item->valuestring) <= 23)
- {
- if (dev_info.time_end != atoi(item->valuestring))
- {
- dev_info.time_end = atoi(item->valuestring);
- need_save = 1;
- need_restart = 1;
- Recode_e_code(e_mqtt_cmd, 4, "平台指令:修改时控结束时间");
- }
- }
- }
- item = cJSON_GetObjectItem(ext, "dattim");
- if (item && cJSON_IsString(item))
- {
- if (atoi(item->valuestring) >= 5 && atoi(item->valuestring) <= 180)
- {
- if (dev_info.data_interval != atoi(item->valuestring))
- {
- dev_info.data_interval = atoi(item->valuestring);
- need_save = 1;
- Recode_e_code(e_mqtt_cmd, 7, "平台指令:修改上报间隔");
- }
- }
- }
- item = cJSON_GetObjectItem(ext, "clt");
- if (item && cJSON_IsString(item))
- dev_info.clean_interval = atoi(item->valuestring);
- item = cJSON_GetObjectItem(ext, "tt");
- if (item && cJSON_IsString(item))
- {
- if (atoi(item->valuestring) >= 0 && atoi(item->valuestring) <= 10)
- {
- if (dev_info.light_work_duration != atoi(item->valuestring))
- {
- dev_info.light_work_duration = atoi(item->valuestring);
- need_save = 1;
- need_restart = 1;
- Recode_e_code(e_mqtt_cmd, 5, "平台指令:修改光控时长");
- }
- }
- }
- item = cJSON_GetObjectItem(ext, "ts");
- if (item && cJSON_IsString(item))
- {
- if (atoi(item->valuestring) >= 0 && atoi(item->valuestring) <= 1)
- {
- if (dev_info.time_ctrl_enable != atoi(item->valuestring))
- {
- dev_info.time_ctrl_enable = atoi(item->valuestring);
- need_save = 1;
- need_restart = 1;
- if (atoi(item->valuestring))
- {
- Recode_e_code(e_mqtt_cmd, 9, "平台指令:改为时控模式");
- }
- else
- {
- Recode_e_code(e_mqtt_cmd, 9, "平台指令:改为光控模式");
- }
- }
- }
- }
- item = cJSON_GetObjectItem(ext, "ds");
- if (item && cJSON_IsString(item))
- {
- if (atoi(item->valuestring) == 0 || atoi(item->valuestring) == 1)
- {
- if (dev_info.power_state != atoi(item->valuestring))
- {
- dev_info.power_state = atoi(item->valuestring);
- need_save = 1;
- if (dev_info.power_state)
- {
- Recode_e_code(e_mqtt_cmd, 6, "平台指令:开机");
- }
- else
- {
- Recode_e_code(e_mqtt_cmd, 0, "平台指令:关机");
- }
- }
- }
- }
- /* 新增:解析 lng 和 lat 字符串 */
- item = cJSON_GetObjectItem(ext, "lng");
- if (item && cJSON_IsString(item))
- {
- rt_strncpy(dev_info.longitude, item->valuestring, sizeof(dev_info.longitude) - 1);
- }
- item = cJSON_GetObjectItem(ext, "lat");
- if (item && cJSON_IsString(item))
- {
- rt_strncpy(dev_info.latitude, item->valuestring, sizeof(dev_info.latitude) - 1);
- }
- if (need_restart)
- {
- if ((dev_info.power_state == 1) && (g_work_state != 0))
- {
- dev_info.power_state = 0;
- rt_thread_mdelay(300);
- dev_info.power_state = 1;
- Recode_e_code(e_CMD_restartwork, 0, "平台指令生效:复位工作状态");
- }
- }
- if (need_save)
- {
- save_dev_info();
- LOG_I("Device params updated");
- cJSON *resp = build_simple_response("paramconf", 0);
- if (resp)
- {
- send_response(client_idx, resp);
- }
- ym310_data_report(0);
- }
- else
- {
- LOG_W("No valid parameters to update");
- cJSON *resp = build_simple_response("paramconf", -1); // -1 表示参数无效
- if (resp)
- {
- send_response(client_idx, resp);
- }
- }
- }
- static void handle_test(rt_uint8_t client_idx, cJSON *root)
- {
- (void)root;
- LOG_I("Test command received");
- once_test_tig();
- cJSON *resp = build_simple_response("test", 0);
- if (resp)
- send_response(client_idx, resp);
- }
- static void handle_chg_light_type(rt_uint8_t client_idx, cJSON *root)
- {
- (void)root;
- LOG_I("handle_chg_light_type");
- cJSON *resp = NULL;
- resp = NULL;
- if (dev_info.light_flag == 0)
- {
- dev_info.light_flag = 1;
- cJSON *resp = build_simple_response("切换光控源=光敏二极管", 0);
- Recode_e_code(e_mqtt_cmd, 8, "平台指令:切换光控源=光敏二极管");
- }
- else
- {
- dev_info.light_flag = 0;
- cJSON *resp = build_simple_response("切换光控源=太阳能板", 0);
- Recode_e_code(e_mqtt_cmd, 9, "平台指令:切换光控源=太阳能板");
- }
- save_dev_info();
- if (resp)
- {
- send_response(client_idx, resp);
- }
- }
- static void handle_reboot(rt_uint8_t client_idx, cJSON *root)
- {
- (void)root;
- LOG_I("Reboot command received, will restart in 1 second");
- cJSON *resp = build_simple_response("reboot", 0);
- if (resp)
- send_response(client_idx, resp);
- rt_thread_mdelay(1000);
- rt_hw_cpu_reset();
- }
- static void handle_update_stm32(rt_uint8_t client_idx, cJSON *root)
- {
- (void)root;
- LOG_I("STM32 update command received");
- cJSON *resp = build_simple_response("update_stm32", 0);
- if (resp)
- {
- send_response(client_idx, resp);
- }
- char up_flag = VALID;
- ef_set_env_blob("up_flag", &up_flag, sizeof(up_flag));
- rt_thread_mdelay(500);
- Recode_e_code(e_update, 0, "升级:接收到下发的指令");
- rt_thread_mdelay(500);
- rt_hw_cpu_reset();
- }
- static void handle_SCDV3_UP_FIRMWARE(rt_uint8_t client_idx, cJSON *root)
- {
- (void)root;
- LOG_I("handle_SCDV3_UP_FIRMWARE");
- cJSON *resp = build_simple_response("SCDV3_UP_FIRMWARE", 0);
- if (resp)
- {
- send_response(client_idx, resp);
- }
- char up_flag = VALID;
- ef_set_env_blob("up_flag", &up_flag, sizeof(up_flag));
- rt_thread_mdelay(500);
- Recode_e_code(e_update, 0, "升级:接收到下发的专用指令");
- rt_thread_mdelay(500);
- rt_hw_cpu_reset();
- }
- /* 开启客户MQTT(仅修改标志,下次重启生效) */
- static void handle_enable_customer(rt_uint8_t client_idx, cJSON *root)
- {
- (void)root;
- sys_info.customer_cfg.enable = VALID;
- save_sys_info();
- LOG_I("Customer MQTT enable flag set to VALID (will take effect after reboot)");
- cJSON *resp = build_simple_response("enable_customer", 0);
- if (resp)
- send_response(client_idx, resp);
- }
- /* 关闭客户MQTT */
- static void handle_disable_customer(rt_uint8_t client_idx, cJSON *root)
- {
- (void)root;
- sys_info.customer_cfg.enable = 0;
- save_sys_info();
- LOG_I("Customer MQTT enable flag set to 0 (will take effect after reboot)");
- cJSON *resp = build_simple_response("disable_customer", 0);
- if (resp)
- send_response(client_idx, resp);
- }
- /* 字符串转整数(支持小数)例如 "2.5" -> 25, "30" -> 300 */
- static int16_t str_to_temp_humi(const char *str)
- {
- int integer = 0;
- int decimal = 0;
- int dot_pos = -1;
- int len = strlen(str);
- /* 查找小数点位置 */
- for (int i = 0; i < len; i++)
- {
- if (str[i] == '.')
- {
- dot_pos = i;
- break;
- }
- }
- if (dot_pos == -1)
- {
- /* 无小数点,如 "30" -> 300 */
- integer = atoi(str);
- return (int16_t)(integer * 10);
- }
- else
- {
- /* 有小数点,如 "2.5" -> 25 */
- char int_part[16] = {0};
- char dec_part[16] = {0};
- /* 提取整数部分 */
- strncpy(int_part, str, dot_pos);
- integer = atoi(int_part);
- /* 提取小数部分(只取第一位) */
- if (dot_pos + 1 < len)
- {
- dec_part[0] = str[dot_pos + 1];
- decimal = atoi(dec_part);
- }
- return (int16_t)(integer * 10 + decimal);
- }
- }
- /* 实现sensor处理函数 */
- static void handle_sensor(rt_uint8_t client_idx, cJSON *root)
- {
- (void)client_idx; /* 无需回复 */
- cJSON *ext = cJSON_GetObjectItem(root, "ext");
- if (!ext || !cJSON_IsObject(ext))
- {
- LOG_E("sensor missing ext object");
- return;
- }
- cJSON *temp_json = cJSON_GetObjectItem(ext, "new_tem");
- cJSON *humi_json = cJSON_GetObjectItem(ext, "new_hum");
- if (!temp_json || !cJSON_IsString(temp_json))
- {
- LOG_E("sensor missing or invalid new_tem");
- return;
- }
- if (!humi_json || !cJSON_IsString(humi_json))
- {
- LOG_E("sensor missing or invalid new_hum");
- return;
- }
- /* 解析温度字符串,直接转换为整数存储(如"2.5" -> 25)*/
- sensor.temp_plat = str_to_temp_humi(temp_json->valuestring);
- /* 解析湿度字符串,直接转换为整数存储(如"30" -> 300)*/
- sensor.humi_plat = str_to_temp_humi(humi_json->valuestring);
- /* 设置有效标志 */
- sensor.valid_plat = VALID;
- LOG_D("sensor[PLATFORM]: temp=%d.%d°C, humi=%d.%d%%",
- sensor.temp_plat / 10, sensor.temp_plat % 10,
- sensor.humi_plat / 10, sensor.humi_plat % 10);
- }
- /**
- * @brief 处理读取传感器数据指令
- * JSON格式: {"cmd":"read_sensor"}
- */
- static void handle_read_sensor(rt_uint8_t client_idx, cJSON *root)
- {
- (void)root; /* 不需要解析ext */
- cJSON *resp = cJSON_CreateObject();
- if (!resp)
- {
- LOG_E("read_sensor: Failed to create response");
- return;
- }
- cJSON_AddStringToObject(resp, "cmd", "read_sensor");
- cJSON *ext = cJSON_CreateObject();
- if (!ext)
- {
- cJSON_Delete(resp);
- LOG_E("read_sensor: Failed to create ext object");
- return;
- }
- cJSON_AddItemToObject(resp, "ext", ext);
- /* ========== 平台下发数据 ========== */
- cJSON *platform = cJSON_CreateObject();
- if (platform)
- {
- if (sensor.valid_plat == VALID)
- {
- char temp_str[16], humi_str[16];
- rt_snprintf(temp_str, sizeof(temp_str), "%d.%d",
- sensor.temp_plat / 10, sensor.temp_plat % 10);
- rt_snprintf(humi_str, sizeof(humi_str), "%d.%d",
- sensor.humi_plat / 10, sensor.humi_plat % 10);
- cJSON_AddStringToObject(platform, "temp", temp_str);
- cJSON_AddStringToObject(platform, "humi", humi_str);
- cJSON_AddStringToObject(platform, "status", "valid");
- }
- else
- {
- cJSON_AddStringToObject(platform, "temp", "0.0");
- cJSON_AddStringToObject(platform, "humi", "0.0");
- cJSON_AddStringToObject(platform, "status", "invalid");
- }
- cJSON_AddItemToObject(ext, "platform", platform);
- }
- /* ========== SHT30传感器数据 ========== */
- cJSON *sht30 = cJSON_CreateObject();
- if (sht30)
- {
- if (sensor.valid_sht == VALID)
- {
- char temp_str[16], humi_str[16];
- rt_snprintf(temp_str, sizeof(temp_str), "%d.%d",
- sensor.temp_sht / 10, sensor.temp_sht % 10);
- rt_snprintf(humi_str, sizeof(humi_str), "%d.%d",
- sensor.humi_sht / 10, sensor.humi_sht % 10);
- cJSON_AddStringToObject(sht30, "temp", temp_str);
- cJSON_AddStringToObject(sht30, "humi", humi_str);
- cJSON_AddStringToObject(sht30, "status", "valid");
- }
- else
- {
- cJSON_AddStringToObject(sht30, "temp", "0.0");
- cJSON_AddStringToObject(sht30, "humi", "0.0");
- cJSON_AddStringToObject(sht30, "status", "invalid");
- }
- cJSON_AddItemToObject(ext, "sht30", sht30);
- }
- /* ========== NTC温度传感器数据 ========== */
- cJSON *ntc = cJSON_CreateObject();
- if (ntc)
- {
- if (sensor.valid_ntc == VALID)
- {
- char temp_str[16];
- rt_snprintf(temp_str, sizeof(temp_str), "%d.%d",
- sensor.temp_ntc / 10, sensor.temp_ntc % 10);
- cJSON_AddStringToObject(ntc, "temp", temp_str);
- cJSON_AddStringToObject(ntc, "status", "valid");
- }
- else
- {
- cJSON_AddStringToObject(ntc, "temp", "0.0");
- cJSON_AddStringToObject(ntc, "status", "invalid");
- }
- cJSON_AddItemToObject(ext, "ntc", ntc);
- }
- /* 添加时间戳 */
- char stamp[20];
- format_time(stamp, sizeof(stamp), &time_now);
- cJSON_AddStringToObject(ext, "timestamp", stamp);
- LOG_I("read_sensor: platform=%s, sht30=%s, ntc=%s",
- sensor.valid_plat == VALID ? "valid" : "invalid",
- sensor.valid_sht == VALID ? "valid" : "invalid",
- sensor.valid_ntc == VALID ? "valid" : "invalid");
- send_response(client_idx, resp);
- }
- /* 静态JSON缓冲区(全局或线程局部) */
- static char s_warn_json_buf[256];
- static uint8_t s_warn_busy = 0; /* 占用标志,防止重入 */
- /**
- * @brief 通用预警消息上报函数(栈空间优化版 - 使用静态缓冲区)
- * @param detail 预警详细信息(字符串)
- * @return int 0-成功,-1-失败,-2-缓冲区忙
- */
- int ym310_warn_report(const char *detail)
- {
- char stamp[15];
- int len;
- int ret = -1;
- char *real_detail = NULL;
- char buf[48] = {0};
- sprintf(buf, "成功升级至:%s", version_with_time());
- if (strstr(detail, "UPDATE_SUCC") != NULL)
- {
- real_detail = buf;
- }
- else
- {
- real_detail = detail;
- }
- /* 记录错误码 */
- Recode_e_code(e_WARN, 0, (char *)real_detail);
- /* ========== 1. 参数校验 ========== */
- if (!real_detail || (real_detail) == 0)
- {
- LOG_E("warn_report: detail is empty");
- return -1;
- }
- /* ========== 2. 检查缓冲区是否被占用(防止重入) ========== */
- if (s_warn_busy)
- {
- LOG_W("warn_report: buffer busy, skip: %s", real_detail);
- return -2;
- }
- /* ========== 3. 检查MQTT连接 ========== */
- if (!ym310_mqtt_is_connected(0))
- {
- LOG_W("warn_report: MQTT not connected, skip: %s", real_detail);
- return -1;
- }
- /* ========== 4. 检查IMEI ========== */
- if (strlen(sys_info.imei) == 0)
- {
- LOG_W("warn_report: IMEI not ready, skip: %s", real_detail);
- return -1;
- }
- /* ========== 5. 占用缓冲区 ========== */
- s_warn_busy = 1;
- /* ========== 6. 获取时间戳 ========== */
- format_time(stamp, sizeof(stamp), &time_now);
- /* ========== 7. 手动构建JSON(避免cJSON栈开销) ========== */
- len = rt_snprintf(s_warn_json_buf, sizeof(s_warn_json_buf),
- "{\"cmd\":\"warn\",\"ext\":{\"detail\":\"%s\"}}", real_detail);
- /* ========== 8. 检查JSON长度 ========== */
- if (len > 0 && len < sizeof(s_warn_json_buf))
- {
- // /* 打印日志 */
- // LOG_I("WARN: %s", detail);
- // LOG_D("WARN payload: %s", s_warn_json_buf);
- /* 发送MQTT消息 */
- if (ym310_mqtt_send_primary(s_warn_json_buf, len) == RT_EOK)
- {
- ret = 0;
- }
- else
- {
- LOG_E("warn_report: send failed");
- ret = -3;
- }
- }
- else
- {
- LOG_E("warn_report: JSON too long or failed, len=%d", len);
- ret = -4;
- }
- /* ========== 9. 释放缓冲区 ========== */
- s_warn_busy = 0;
- return ret;
- }
- /* 调试命令查看sensor状态 */
- static void show_sensor(int argc, char **argv)
- {
- rt_kprintf("\n========== SENSOR STATUS ==========\n");
- /* 平台数据 */
- rt_kprintf("[PLAT] ");
- if (sensor.valid_plat == VALID)
- {
- rt_kprintf("temp=%d.%d°C, humi=%d.%d%%\n",
- sensor.temp_plat / 10, sensor.temp_plat % 10,
- sensor.humi_plat / 10, sensor.humi_plat % 10);
- }
- else
- {
- rt_kprintf("invalid\n");
- }
- /* SHT30数据 */
- rt_kprintf("[SHT ] ");
- if (sensor.valid_sht == VALID)
- {
- rt_kprintf("temp=%d.%d°C, humi=%d.%d%%\n",
- sensor.temp_sht / 10, sensor.temp_sht % 10,
- sensor.humi_sht / 10, sensor.humi_sht % 10);
- }
- else
- {
- rt_kprintf("invalid\n");
- }
- /* NTC数据 */
- rt_kprintf("[NTC ] ");
- if (sensor.valid_ntc == VALID)
- {
- rt_kprintf("temp=%d.%d°C\n",
- sensor.temp_ntc / 10, sensor.temp_ntc % 10);
- }
- else
- {
- rt_kprintf("invalid\n");
- }
- rt_kprintf("==================================\n");
- }
- MSH_CMD_EXPORT(show_sensor, show sensor data);
- static void process_json(rt_uint8_t client_idx, const char *payload)
- {
- cJSON *root = cJSON_Parse(payload);
- if (!root)
- {
- LOG_E("JSON parse error: %s", payload);
- return;
- }
- cJSON *cmd_json = cJSON_GetObjectItem(root, "cmd");
- if (!cmd_json || !cJSON_IsString(cmd_json))
- {
- LOG_E("No cmd field or invalid");
- cJSON_Delete(root);
- return;
- }
- const char *cmd = cmd_json->valuestring;
- LOG_D("Received cmd: %s", cmd);
- if (strcmp(cmd, "read") == 0)
- {
- handle_read(client_idx, root);
- }
- else if (strcmp(cmd, "Set_scdparam") == 0)
- {
- handle_set_scdparam(client_idx, root);
- }
- else if (strcmp(cmd, "thirdserverconf") == 0)
- {
- handle_thirdserverconf(client_idx, root);
- }
- else if (strcmp(cmd, "paramconf") == 0)
- {
- handle_paramconf(client_idx, root);
- }
- else if (strcmp(cmd, "test") == 0)
- {
- handle_test(client_idx, root);
- }
- else if (strcmp(cmd, "reboot") == 0)
- {
- handle_reboot(client_idx, root);
- }
- else if (strcmp(cmd, "update_stm32") == 0)
- {
- handle_update_stm32(client_idx, root);
- }
- else if (strcmp(cmd, "platform") == 0)
- {
- handle_platform(client_idx, root);
- }
- else if (strcmp(cmd, "enable_customer") == 0)
- {
- handle_enable_customer(client_idx, root);
- }
- else if (strcmp(cmd, "disable_customer") == 0)
- {
- handle_disable_customer(client_idx, root);
- }
- else if (strcmp(cmd, "read_ecode") == 0)
- {
- handle_read_ecode(client_idx, root);
- }
- else if (strcmp(cmd, "read_update_url") == 0)
- {
- handle_read_update_url(client_idx, root);
- }
- else if (strcmp(cmd, "set_update_url") == 0)
- {
- handle_set_update_url(client_idx, root);
- }
- else if (strcmp(cmd, "sensor") == 0)
- {
- handle_sensor(client_idx, root);
- }
- else if (strcmp(cmd, "read_sensor") == 0)
- {
- handle_read_sensor(client_idx, root);
- }
- else if (strcmp(cmd, "read_status") == 0)
- {
- handle_read_status(client_idx, root);
- }
- else if (strcmp(cmd, "Light_control_handoff") == 0)
- {
- handle_chg_light_type(client_idx, root);
- }
- else if (strcmp(cmd, "location") == 0)
- {
- handle_location(client_idx, root);
- }
- else if (strcmp(cmd, "upload_ecode") == 0)
- {
- handle_upload_ecode(client_idx, root);
- }
- else if (strcmp(cmd, "get_devinfo") == 0)
- {
- handle_get_devinfo(client_idx, root);
- }
- else if (strcmp(cmd, "FORCE_RESET") == 0)
- {
- handle_FORCE_RESET(client_idx, root);
- }
- else if (strcmp(cmd, "lamp_proc_on") == 0)
- {
- handle_lamp_proc_on(client_idx, root);
- }
- else if (strcmp(cmd, "lamp_proc_off") == 0)
- {
- handle_lamp_proc_off(client_idx, root);
- }
- else if (strcmp(cmd, "SCDV3_UP_FIRMWARE") == 0)
- {
- handle_SCDV3_UP_FIRMWARE(client_idx, root);
- }
- else
- {
- LOG_W("Unknown cmd: %s", cmd);
- }
- cJSON_Delete(root);
- }
- #include <ctype.h>
- void ym310_protocol_process(rt_uint8_t client_idx, const char *topic,
- const char *payload, rt_uint16_t len)
- {
- (void)topic;
- if (!payload || len == 0)
- {
- LOG_E("Empty payload");
- return;
- }
- char *buf = rt_malloc(len + 1);
- if (!buf)
- {
- LOG_E("Out of memory");
- return;
- }
- rt_memcpy(buf, payload, len);
- buf[len] = '\0';
- LOG_D("Processing payload (%d): %s", len, buf);
- process_json(client_idx, buf);
- rt_free(buf);
- }
- void ym310_data_report(rt_uint8_t client_idx)
- {
- char res = 1;
- if (client_idx == 1 && sys_info.customer_cfg.enable != VALID)
- {
- return;
- }
- cJSON *root = NULL;
- if (read_platform_flag())
- {
- root = build_data_report_vice();
- }
- else
- {
- root = build_data_report();
- }
- if (!root)
- {
- LOG_E("Failed to build data report");
- return;
- }
- char *json_str = cJSON_PrintUnformatted(root);
- if (json_str)
- {
- LOG_D("Data report to MQTT[%d]: %s", client_idx, json_str);
- if (client_idx == 0)
- {
- if (ym310_mqtt_send_primary(json_str, rt_strlen(json_str)) != RT_EOK)
- {
- res = 0;
- }
- }
- else if (client_idx == 1)
- {
- if (ym310_mqtt_send_secondary(json_str, rt_strlen(json_str)) != RT_EOK)
- {
- res = 0;
- }
- }
- else
- {
- LOG_E("Invalid client_idx: %d", client_idx);
- res = 0;
- }
- cJSON_free(json_str);
- }
- cJSON_Delete(root);
- // rt_memory_info(&total, &used, &max_used);
- // LOG_W("After report: total=%d, used=%d, max=%d", total, used, max_used);
- if (read_platform_flag()) // 上报status
- {
- root = build_status_report_vice();
- if (root)
- {
- char *json_str = cJSON_PrintUnformatted(root);
- if (json_str)
- {
- LOG_D("Status report to MQTT[%d]: %s", client_idx, json_str);
- ym310_mqtt_send_primary(json_str, rt_strlen(json_str));
- cJSON_free(json_str);
- }
- cJSON_Delete(root);
- }
- }
- if (res)
- {
- hv_save(0);
- }
- }
- /**
- * @brief 发送升级结果到 MQTT
- * @param client_idx MQTT 实例索引(通常使用主 MQTT,即 0)
- * @param update_res 升级结果标志(VALID 成功,0x9E 写入失败,0x9F 校验失败)
- */
- static void report_update_result(rt_uint8_t client_idx)
- {
- if (update_res < 0x9A || update_res > 0x9F)
- {
- return;
- }
- cJSON *root = cJSON_CreateObject();
- if (root == RT_NULL)
- return;
- cJSON_AddStringToObject(root, "cmd", "update_result");
- const char *status = "unknown";
- const char *desc = "";
- switch (update_res)
- {
- case 0x9A:
- status = "fail";
- desc = "firmware download fail";
- break;
- case VALID:
- status = "ok";
- desc = "FIRMWARE UPDATE SUCCESS";
- // Recode_e_code(e_update_WSUCC, 0, "升级写入固件成功");
- break;
- case 0x9E:
- status = "error";
- desc = "firmware release failed";
- // Recode_e_code(e_update_WFAIL, 1, "升级写入固件失败");
- break;
- case 0x9F:
- status = "error";
- desc = "verification failed";
- // Recode_e_code(e_update_WFAIL, 2, "升级写入固件失败(校验未通过)");
- break;
- default:
- cJSON_Delete(root);
- return;
- break;
- }
- cJSON_AddStringToObject(root, "result", status);
- cJSON_AddStringToObject(root, "desc", desc);
- cJSON_AddNumberToObject(root, "code", update_res);
- cJSON_AddStringToObject(root, "version", version_with_time());
- send_response(client_idx, root);
- update_res = 0;
- ef_set_env_blob("update_res", &update_res, sizeof(update_res));
- ym310_warn_report("UPDATE_SUCC");
- }
- static void report_upload_result(rt_uint8_t client_idx)
- {
- if (upload_res < 0x9A || upload_res > 0x9F)
- {
- return;
- }
- cJSON *root = cJSON_CreateObject();
- if (root == RT_NULL)
- return;
- cJSON_AddStringToObject(root, "cmd", "upload_result");
- const char *status = "unknown";
- const char *desc = "";
- switch (upload_res)
- {
- case 0x9A:
- status = "error";
- desc = "LOG UPLOAD FAIL";
- break;
- case VALID:
- status = "ok";
- desc = "LOG UPLOAD SUCCESS";
- break;
- default:
- cJSON_Delete(root);
- return;
- break;
- }
- cJSON_AddStringToObject(root, "result", status);
- cJSON_AddStringToObject(root, "desc", desc);
- cJSON_AddNumberToObject(root, "upload_res", upload_res);
- send_response(client_idx, root);
- upload_res = 0;
- ef_set_env_blob("upload_res", &upload_res, sizeof(upload_res));
- }
- /*********************↑ function definitions ↑***********************/
- /*********************↓ data report ↓***********************/
- static char report_once = 0; // 触发一次上报
- #define MAX_WAIT_SEC 30 * 60 // half an hour
- /* 数据上报线程入口 */
- static void data_report_thread_entry(void *param)
- {
- uint16_t interval_min;
- // LOG_I("Data report thread started");
- uint16_t wait = 0;
- uint32_t used_sec = 0;
- /* 等待 MQTT0 连接成功 */
- while (1)
- {
- if (ym310_mqtt_is_connected(0))
- {
- break;
- }
- // rt_kprintf("ym310_mqtt_is_connected = %d \n", ym310_mqtt_is_connected(0));
- if (wait++ > 0 && wait % 15 == 0)
- {
- LOG_I("Waiting for MQTT0 connection...");
- if (wait >= MAX_WAIT_SEC)
- {
- Recode_e_code(e_mqtt0_outtime, wait, "MQTT0 超时未连接");
- rt_hw_cpu_reset();
- }
- }
- rt_thread_mdelay(1000);
- }
- rt_thread_mdelay(10000);
- //rt_thread_mdelay(33000);
- LOG_D("MQTT0 connected, start reporting");
- /* 开机立即上报一次 */
- ym310_data_report(0);
- ym310_data_report(1);
- report_update_result(0);
- report_upload_result(0);
- while (1)
- {
- /* 读取当前上报间隔 */
- interval_min = dev_info.data_interval;
- if (interval_min == 0)
- {
- interval_min = 10; /* 默认10分钟 */
- LOG_D("data_interval is 0, use default %d minutes", interval_min);
- }
- if (used_sec >= interval_min * 60)
- {
- LOG_D("Reporting data (interval=%d min)", interval_min);
- ym310_data_report(0);
- ym310_data_report(1);
- used_sec = 1;
- }
- else
- {
- used_sec++;
- }
- if (used_sec > 0 && used_sec % 60 == 0)
- {
- // rt_kprintf("ready for report %d/%d min \n", used_sec / 60, interval_min);
- // rt_memory_info(&total, &used, &max_used);
- // LOG_I("NOW MEM: total=%d, used=%d, max=%d", total, used, max_used);
- }
- rt_thread_mdelay(1000);
- if (report_once)
- {
- report_once = 0;
- LOG_I("Manual report triggered for MQTT");
- ym310_data_report(0);
- ym310_data_report(1);
- rt_thread_mdelay(3000);
- }
- }
- }
- static int start_datarpt(void)
- {
- rt_thread_t s_report_thread = RT_NULL;
- /* 创建数据上报线程 */
- s_report_thread = rt_thread_create("data_rpt",
- data_report_thread_entry,
- RT_NULL,
- 2048, /* 栈大小,根据需要调整 */
- 19, /* 优先级,低于MQTT线程 */
- 10);
- if (s_report_thread != RT_NULL)
- {
- rt_thread_startup(s_report_thread);
- }
- else
- {
- LOG_E("Failed to create data report thread");
- }
- return 0;
- }
- INIT_APP_EXPORT(start_datarpt);
- /*********************↑ data report ↑***********************/
- void report_now(void)
- {
- report_once = 1;
- }
- MSH_CMD_EXPORT(report_now, Trigger a data report immediately);
- static void handle_read_ecode(rt_uint8_t client_idx, cJSON *root)
- {
- cJSON *ext = cJSON_GetObjectItem(root, "ext");
- if (!ext || !cJSON_IsObject(ext))
- {
- LOG_E("read_ecode missing ext object");
- return;
- }
- cJSON *start_json = cJSON_GetObjectItem(ext, "start");
- cJSON *count_json = cJSON_GetObjectItem(ext, "count");
- if (!start_json || !cJSON_IsNumber(start_json) ||
- !count_json || !cJSON_IsNumber(count_json))
- {
- LOG_E("read_ecode missing or invalid start/count");
- return;
- }
- int start = start_json->valueint;
- int count = count_json->valueint;
- int total = ecode_get_count();
- /* ========== 指令1: 读取当前存储条数 (start=0, count=0) ========== */
- if (start == 0 && count == 0)
- {
- cJSON *resp = cJSON_CreateObject();
- cJSON_AddStringToObject(resp, "cmd", "read_ecode");
- cJSON_AddNumberToObject(resp, "total", total);
- cJSON_AddStringToObject(resp, "status", "count_only");
- cJSON_AddStringToObject(resp, "msg", "current stored records count");
- send_response(client_idx, resp);
- LOG_I("read_ecode count_only: total=%d", total);
- return;
- }
- /* ========== 指令2: 读取所有存储的ecode (start=99, count=99) ========== */
- if (start == 99 && count == 99)
- {
- start = 0;
- count = total;
- LOG_I("read_ecode read_all mode: total=%d, will packet automatically", total);
- }
- /* ========== 指令3: 按起始位置和条数读取 (正常逻辑) ========== */
- /* 参数校验 */
- if (start < 0 || (total > 0 && start >= total))
- {
- cJSON *err = cJSON_CreateObject();
- cJSON_AddStringToObject(err, "cmd", "read_ecode");
- cJSON_AddStringToObject(err, "error", "start out of range");
- cJSON_AddNumberToObject(err, "total", total);
- send_response(client_idx, err);
- return;
- }
- if (count <= 0)
- {
- cJSON *err = cJSON_CreateObject();
- cJSON_AddStringToObject(err, "cmd", "read_ecode");
- cJSON_AddStringToObject(err, "error", "count must be positive");
- cJSON_AddNumberToObject(err, "total", total);
- send_response(client_idx, err);
- return;
- }
- /* MQTT分包参数配置 */
- #define MQTT_MAX_PAYLOAD_SIZE_USE 950 /* MQTT最大负载,留有余量 */
- #define REPORT_INTERVAL_MS 2000 /* 分包间隔2秒 */
- #define JSON_OVERHEAD_PER_RECORD 50 /* 每条记录JSON格式开销(字段名、括号、逗号等) */
- #define JSON_BASE_OVERHEAD 50 /* 基础JSON开销(cmd、start等字段) */
- /* 计算实际需要读取的数量 */
- int remaining = (start + count > total) ? (total - start) : count;
- int current_start = start;
- int packet_seq = 0;
- LOG_I("read_ecode start=%d, request_count=%d, actual_remaining=%d, total=%d",
- start, count, remaining, total);
- /* 动态分包上报 - 根据实际记录大小决定每包数量 */
- while (remaining > 0)
- {
- packet_seq++;
- /* 预估本包可以容纳的记录数 */
- int records_this_packet = 0;
- int estimated_size = JSON_BASE_OVERHEAD;
- /* 逐条检查,直到接近限制 */
- for (int i = 0; i < remaining; i++)
- {
- ecode_record_t rec;
- if (ecode_read(current_start + i, &rec) != 0)
- {
- /* 读取失败,跳过这条 */
- continue;
- }
- /* 计算这条记录的实际大小:
- - detail字符串长度
- - 时间字符串固定17字节 (YY/MM/DD HH:MM:SS)
- - 数字字段约10字节
- - JSON格式开销50字节
- */
- int detail_len = strlen(rec.detail);
- int record_size = JSON_OVERHEAD_PER_RECORD + detail_len + 17 + 20;
- /* 检查加上这条是否会超出限制 */
- if (estimated_size + record_size > MQTT_MAX_PAYLOAD_SIZE_USE && records_this_packet > 0)
- {
- /* 这条放不下了,且已经有记录,停止添加 */
- break;
- }
- estimated_size += record_size;
- records_this_packet++;
- /* 至少放一条,防止死循环 */
- if (records_this_packet == 1 && estimated_size > MQTT_MAX_PAYLOAD_SIZE_USE)
- {
- LOG_W("single record too large: %d bytes, will send anyway", estimated_size);
- break;
- }
- }
- /* 确保至少有一条 */
- if (records_this_packet == 0)
- records_this_packet = 1;
- /* 限制不超过剩余数量 */
- if (records_this_packet > remaining)
- records_this_packet = remaining;
- cJSON *resp = cJSON_CreateObject();
- cJSON_AddStringToObject(resp, "cmd", "read_ecode");
- cJSON_AddNumberToObject(resp, "start", current_start);
- cJSON_AddNumberToObject(resp, "total", total);
- cJSON_AddNumberToObject(resp, "packet_seq", packet_seq);
- cJSON_AddBoolToObject(resp, "has_more", remaining > records_this_packet);
- cJSON *records = cJSON_CreateArray();
- int actual_read = 0;
- for (int i = 0; i < records_this_packet; i++)
- {
- ecode_record_t rec;
- if (ecode_read(current_start + i, &rec) == 0)
- {
- cJSON *item = cJSON_CreateObject();
- cJSON_AddNumberToObject(item, "num", rec.num);
- /* 使用缓冲区接收时间字符串 */
- char time_str[32];
- rt_snprintf(time_str, sizeof(time_str), "%02d/%02d/%02d %02d:%02d:%02d",
- rec.time_stamp.tm_year, rec.time_stamp.tm_mon,
- rec.time_stamp.tm_mday, rec.time_stamp.tm_hour,
- rec.time_stamp.tm_min, rec.time_stamp.tm_sec);
- cJSON_AddStringToObject(item, "time", time_str);
- cJSON_AddNumberToObject(item, "code", rec.code);
- cJSON_AddNumberToObject(item, "para", rec.para);
- cJSON_AddStringToObject(item, "detail", rec.detail);
- cJSON_AddItemToArray(records, item);
- actual_read++;
- }
- else
- {
- LOG_W("failed to read ecode at index %d", current_start + i);
- }
- }
- cJSON_AddNumberToObject(resp, "count", actual_read);
- cJSON_AddItemToObject(resp, "records", records);
- /* 发送本包数据 */
- send_response(client_idx, resp);
- LOG_I("read_ecode sent packet %d: start=%d, count=%d/%d, remaining=%d",
- packet_seq, current_start, actual_read, records_this_packet, remaining - records_this_packet);
- /* 更新计数器 */
- current_start += records_this_packet;
- remaining -= records_this_packet;
- /* 如果还有数据,等待2秒后发送下一包 */
- if (remaining > 0)
- {
- rt_thread_mdelay(REPORT_INTERVAL_MS);
- }
- }
- LOG_I("read_ecode completed: %d packets sent", packet_seq);
- }
- /**
- * @brief 格式化时长字符串(自动选择分钟或小时)
- * @param seconds 秒数
- * @param buf 输出缓冲区
- * @param size 缓冲区大小
- */
- static void format_duration_str(uint32_t seconds, char *buf, size_t size)
- {
- if (seconds >= 3600)
- {
- /* 大于等于1小时,显示小时和分钟 */
- uint32_t hours = seconds / 3600;
- uint32_t minutes = (seconds % 3600) / 60;
- if (minutes > 0)
- rt_snprintf(buf, size, "%u小时%u分钟", hours, minutes);
- else
- rt_snprintf(buf, size, "%u小时", hours);
- }
- else if (seconds >= 60)
- {
- /* 大于等于1分钟,显示分钟 */
- uint32_t minutes = seconds / 60;
- uint32_t secs = seconds % 60;
- if (secs > 0)
- rt_snprintf(buf, size, "%u分钟%u秒", minutes, secs);
- else
- rt_snprintf(buf, size, "%u分钟", minutes);
- }
- else
- {
- /* 小于1分钟,显示秒 */
- rt_snprintf(buf, size, "%u秒", seconds);
- }
- }
- /**
- * @brief 处理读取系统状态指令
- */
- static void handle_read_status(rt_uint8_t client_idx, cJSON *root)
- {
- (void)root;
- cJSON *resp = cJSON_CreateObject();
- if (!resp)
- return;
- cJSON_AddStringToObject(resp, "cmd", "read_status");
- cJSON *ext = cJSON_CreateObject();
- if (!ext)
- {
- cJSON_Delete(resp);
- return;
- }
- cJSON_AddItemToObject(resp, "ext", ext);
- /* 开关机状态 */
- cJSON_AddStringToObject(ext, "开关机状态", dev_info.power_state ? "开机" : "关机");
- const char *state_str = "";
- switch (g_work_state)
- {
- case WORK_STATE_IDLE:
- state_str = "空闲中";
- break;
- case WORK_STATE_WORKING:
- state_str = "工作中";
- break;
- case WORK_STATE_LIGHT_PRT:
- state_str = "光控中";
- break;
- case WORK_STATE_COOLDOWN:
- state_str = "冷却中";
- break;
- case WORK_STATE_WAIT_DAY:
- state_str = "工作结束等待天亮";
- break;
- case WORK_STATE_OTHER_PRT:
- state_str = "保护中";
- break;
- default:
- break;
- }
- cJSON_AddStringToObject(ext, "工作状态", state_str);
- /* 工作模式 */
- if (g_work_state == 1)
- {
- cJSON_AddStringToObject(ext, "工作模式", g_work_mode == 1 ? "光控模式" : "时控模式");
- /* 开始时间 */
- char start_time[16];
- rt_snprintf(start_time, sizeof(start_time), "%02d:%02d",
- g_work_start_hour, g_work_start_minute);
- cJSON_AddStringToObject(ext, "开始时间", start_time);
- /* 已工作时长(分钟) */
- uint32_t elapsed_min = g_work_elapsed_sec / 60;
- cJSON_AddNumberToObject(ext, "已工作时长(分钟)", elapsed_min);
- /* 进度百分比 */
- cJSON_AddNumberToObject(ext, "进度百分比", g_work_progress);
- if (g_work_total_sec > 0)
- {
- uint32_t remain_min = (g_work_total_sec - g_work_elapsed_sec) / 60;
- cJSON_AddNumberToObject(ext, "剩余时长(分钟)", remain_min);
- }
- else
- {
- cJSON_AddStringToObject(ext, "工作模式类型", "自动模式(天亮结束)");
- }
- if (dev_info.time_ctrl_enable == 0)
- {
- if (dev_info.light_work_duration > 0)
- {
- char duration[32];
- rt_snprintf(duration, sizeof(duration), "%d小时(光控)", dev_info.light_work_duration);
- cJSON_AddStringToObject(ext, "配置工作时长", duration);
- }
- else
- {
- cJSON_AddStringToObject(ext, "配置工作时长", "自动模式");
- }
- }
- else
- {
- char duration[32];
- rt_snprintf(duration, sizeof(duration), "%d小时(时控)", calculate_hours_diff(dev_info.time_start, dev_info.time_end));
- cJSON_AddStringToObject(ext, "配置工作时长", duration);
- }
- }
- /* 冷却状态 */
- if (g_work_state == 2 && g_cooldown_sec > 0)
- {
- cJSON_AddNumberToObject(ext, "冷却剩余秒数", g_cooldown_sec);
- }
- /* 控制模式 */
- cJSON_AddStringToObject(ext, "控制模式", dev_info.time_ctrl_enable ? "时控模式" : "光控模式");
- if (dev_info.time_ctrl_enable == 0)
- {
- /* 光控模式详情 */
- cJSON_AddStringToObject(ext, "光控来源", dev_info.light_flag == 0 ? "太阳能板" : "光敏二极管");
- /* 亮度值(整数,0-1000表示0.0%-100.0%) */
- cJSON_AddNumberToObject(ext, "亮度值(%)", sys_sta.light_percent / 10);
- /* 充电电压(mV) */
- cJSON_AddNumberToObject(ext, "充电电压(mV)", sys_sta.charge_voltage);
- /* 光控保护状态 */
- cJSON_AddStringToObject(ext, "光控保护",
- sys_sta.light_protect == VALID ? "激活(白天)" : "未激活(夜晚)");
- }
- else
- {
- /* 时控模式详情 */
- char time_range[32];
- rt_snprintf(time_range, sizeof(time_range), "%02d:00 - %02d:00",
- dev_info.time_start, dev_info.time_end);
- cJSON_AddStringToObject(ext, "时控时段", time_range);
- cJSON_AddNumberToObject(ext, "当前小时", time_now.hour);
- /* 内联判断是否在时段内 */
- int in_range;
- if (dev_info.time_start <= dev_info.time_end)
- {
- in_range = (time_now.hour >= dev_info.time_start && time_now.hour < dev_info.time_end);
- }
- else
- {
- in_range = (time_now.hour >= dev_info.time_start || time_now.hour < dev_info.time_end);
- }
- cJSON_AddStringToObject(ext, "是否在时段内", in_range ? "是" : "否");
- }
- char off_lamp_proc = 0;
- ef_get_env_blob("off_lamp_proc", &off_lamp_proc, sizeof(off_lamp_proc), NULL);
- /* 保护状态 */
- cJSON *protect = cJSON_CreateObject();
- if (protect)
- {
- cJSON_AddStringToObject(protect, "光控保护", sys_sta.light_protect == VALID ? "激活" : "正常");
- cJSON_AddStringToObject(protect, "欠压保护", sys_sta.undervolt_protect == VALID ? "激活" : "正常");
- cJSON_AddStringToObject(protect, "高温保护", sys_sta.temp_protect == VALID ? "激活" : "正常");
- cJSON_AddStringToObject(protect, "低温保护", sys_sta.temp_protect == 0x7A ? "激活" : "正常");
- cJSON_AddStringToObject(protect, "倾倒保护", sys_sta.tilt_protect == VALID ? "激活" : "正常");
- cJSON_AddStringToObject(protect, "雨控保护", sys_sta.rain_protect == VALID ? "激活" : "正常");
- cJSON_AddStringToObject(protect, "灯管保护功能", off_lamp_proc == VALID ? "关闭" : "开启");
- switch (sys_sta.lamp_fault)
- {
- case 0x7A:
- cJSON_AddStringToObject(protect, "灯管状态", "开路");
- break;
- case VALID:
- cJSON_AddStringToObject(protect, "灯管状态", "短路");
- break;
- default:
- cJSON_AddStringToObject(protect, "灯管状态", "正常");
- break;
- }
- cJSON_AddItemToObject(ext, "保护状态", protect);
- }
- /* 电气参数 */
- cJSON_AddNumberToObject(ext, "电池电压(mV)", sys_sta.battery_voltage);
- cJSON_AddNumberToObject(ext, "SHT温度(℃)", sensor.temp_sht / 10);
- cJSON_AddNumberToObject(ext, "NTC温度(℃)", sensor.temp_ntc / 10);
- cJSON_AddNumberToObject(ext, "气象温度(℃)", sensor.temp_plat / 10);
- cJSON_AddNumberToObject(ext, "主板温度(℃)", sys_sta.board_temp / 10);
- cJSON_AddNumberToObject(ext, "灯管电流", sys_sta.lamp_current);
- cJSON_AddNumberToObject(ext, "高压次数", sys_sta.hv_count);
- /* 时间戳 */
- char stamp[20];
- rt_snprintf(stamp, sizeof(stamp), "%04d-%02d-%02d %02d:%02d:%02d",
- time_now.year, time_now.month, time_now.date,
- time_now.hour, time_now.minute, time_now.second);
- cJSON_AddStringToObject(ext, "上报时间", stamp);
- send_response(client_idx, resp);
- }
- /**
- * @brief 处理手动下发定位指令
- * JSON格式: {"cmd":"location","ext":{"lat": "34.4861845","lng": "113.3963165","type": "1"}}
- *
- * 功能:当GPS定位失效时,手动下发当前位置
- * - 将经纬度字符串存储到 longitude_FORCE 和 latitude_FORCE
- * - 设置 GPS_MODE = 0(手动模式)
- * - 保存设备信息到 Flash
- */
- static void handle_location(rt_uint8_t client_idx, cJSON *root)
- {
- cJSON *ext = cJSON_GetObjectItem(root, "ext");
- if (!ext || !cJSON_IsObject(ext))
- {
- LOG_E("location: missing ext object");
- cJSON *resp = build_simple_response("location", -1);
- if (resp)
- send_response(client_idx, resp);
- return;
- }
- cJSON *type = cJSON_GetObjectItem(ext, "type");
- if (!type || !cJSON_IsString(type))
- {
- LOG_E("location: missing or invalid type field");
- cJSON *resp = build_simple_response("location", -6);
- if (resp)
- send_response(client_idx, resp);
- return;
- }
- if (type->valuestring[0] == '0')
- {
- cJSON *lat_json = cJSON_GetObjectItem(ext, "lat");
- cJSON *lng_json = cJSON_GetObjectItem(ext, "lng");
- if (!lat_json || !cJSON_IsString(lat_json))
- {
- LOG_E("location: missing or invalid lat field");
- cJSON *resp = build_simple_response("location", -2);
- if (resp)
- send_response(client_idx, resp);
- return;
- }
- if (!lng_json || !cJSON_IsString(lng_json))
- {
- LOG_E("location: missing or invalid lng field");
- cJSON *resp = build_simple_response("location", -3);
- if (resp)
- send_response(client_idx, resp);
- return;
- }
- const char *lat_str = lat_json->valuestring;
- const char *lng_str = lng_json->valuestring;
- /* 验证经纬度字符串长度 */
- if (strlen(lat_str) >= sizeof(dev_info.latitude_FORCE))
- {
- LOG_E("location: lat string too long (%d >= %d)", strlen(lat_str), sizeof(dev_info.latitude_FORCE));
- cJSON *resp = build_simple_response("location", -4);
- if (resp)
- send_response(client_idx, resp);
- return;
- }
- if (strlen(lng_str) >= sizeof(dev_info.longitude_FORCE))
- {
- LOG_E("location: lng string too long (%d >= %d)", strlen(lng_str), sizeof(dev_info.longitude_FORCE));
- cJSON *resp = build_simple_response("location", -5);
- if (resp)
- send_response(client_idx, resp);
- return;
- }
- /* 清空原有数据 */
- memset(dev_info.latitude_FORCE, 0, sizeof(dev_info.latitude_FORCE));
- memset(dev_info.longitude_FORCE, 0, sizeof(dev_info.longitude_FORCE));
- /* 复制经纬度字符串 */
- strncpy(dev_info.latitude_FORCE, lat_str, sizeof(dev_info.latitude_FORCE) - 1);
- strncpy(dev_info.longitude_FORCE, lng_str, sizeof(dev_info.longitude_FORCE) - 1);
- /* 设置GPS模式为手动模式 */
- dev_info.GPS_MODE = 0;
- /* 保存设备信息到 Flash */
- save_dev_info();
- LOG_I("location: force location saved - lat=%s, lng=%s, GPS_MODE=0",
- dev_info.latitude_FORCE, dev_info.longitude_FORCE);
- /* 构建成功响应 */
- cJSON *resp = cJSON_CreateObject();
- if (resp)
- {
- cJSON_AddStringToObject(resp, "cmd", "location");
- cJSON_AddStringToObject(resp, "result", "ok");
- cJSON *resp_ext = cJSON_CreateObject();
- if (resp_ext)
- {
- cJSON_AddStringToObject(resp_ext, "lat", dev_info.latitude_FORCE);
- cJSON_AddStringToObject(resp_ext, "lng", dev_info.longitude_FORCE);
- cJSON_AddNumberToObject(resp_ext, "gps_mode", dev_info.GPS_MODE);
- cJSON_AddItemToObject(resp, "ext", resp_ext);
- }
- send_response(client_idx, resp);
- }
- }
- if (type->valuestring[0] == '1')
- {
- /* 设置GPS模式为自动模式 */
- dev_info.GPS_MODE = 1;
- /* 保存设备信息到 Flash */
- save_dev_info();
- /* 构建成功响应 */
- cJSON *resp = cJSON_CreateObject();
- if (resp)
- {
- cJSON_AddStringToObject(resp, "cmd", "location");
- cJSON_AddStringToObject(resp, "result", "ok");
- cJSON *resp_ext = cJSON_CreateObject();
- if (resp_ext)
- {
- cJSON_AddNumberToObject(resp_ext, "gps_mode", dev_info.GPS_MODE);
- cJSON_AddItemToObject(resp, "ext", resp_ext);
- }
- send_response(client_idx, resp);
- }
- }
- }
- static void handle_upload_ecode(rt_uint8_t client_idx, cJSON *root)
- {
- (void)root;
- uint8_t flag = 0x9D;
- ef_set_env_blob("upload_ecode", &flag, sizeof(flag));
- LOG_I("upload_ecode flag set, will upload on next reboot");
- Recode_e_code(e_upload_ecode, 0, "收到上传EC日志指令");
- cJSON *resp = build_simple_response("upload_ecode", 0);
- if (resp)
- {
- send_response(client_idx, resp);
- }
- rt_thread_mdelay(300);
- rt_hw_cpu_reset();
- }
- static cJSON *build_devinfo_report(void)
- {
- cJSON *root = cJSON_CreateObject();
- if (!root)
- return NULL;
- cJSON_AddStringToObject(root, "cmd", "devinfo");
- cJSON *ext = cJSON_CreateObject();
- if (!ext)
- {
- cJSON_Delete(root);
- return NULL;
- }
- cJSON_AddItemToObject(root, "ext", ext);
- cJSON *mqtt_vice = cJSON_CreateObject();
- if (!mqtt_vice)
- {
- cJSON_Delete(root);
- return NULL;
- }
- cJSON_AddItemToObject(ext, "mqtt_vice", mqtt_vice);
- // cJSON *range = cJSON_CreateObject();
- // if (!range)
- // {
- // cJSON_Delete(root);
- // return NULL;
- // }
- // cJSON_AddItemToObject(ext, "range", range);
- cJSON *work = cJSON_CreateObject();
- if (!work)
- {
- cJSON_Delete(work);
- return NULL;
- }
- cJSON_AddItemToObject(ext, "work", work);
- cJSON *cjson_limit = cJSON_CreateObject();
- if (!cjson_limit)
- {
- cJSON_Delete(cjson_limit);
- return NULL;
- }
- cJSON_AddItemToObject(ext, "limit", cjson_limit);
- cJSON *info = cJSON_CreateObject();
- if (!info)
- {
- cJSON_Delete(info);
- return NULL;
- }
- cJSON_AddItemToObject(ext, "info", info);
- char stamp[15];
- format_time(stamp, sizeof(stamp), &time_now);
- cJSON_AddStringToObject(ext, "stamp", stamp);
- uint32_t start_time = 0;
- ef_get_env_blob("start_time", &start_time, sizeof(start_time), NULL);
- cJSON_AddStringToObject(info, "IMEI", sys_info.imei);
- cJSON_AddStringToObject(info, "ICCID", sys_info.iccid);
- cJSON_AddStringToObject(info, "VERSION", version_with_time());
- char num_buf[16];
- // 信号强度
- rt_snprintf(num_buf, sizeof(num_buf), "%u", sys_info.csq);
- cJSON_AddStringToObject(info, "CSQ", num_buf);
- // 开机次数
- rt_snprintf(num_buf, sizeof(num_buf), "%u", start_time);
- cJSON_AddStringToObject(ext, "START_TIMES", num_buf);
- // 设备状态
- rt_snprintf(num_buf, sizeof(num_buf), "%u", sys_sta.work_state);
- cJSON_AddStringToObject(ext, "DEV_STATUS", num_buf);
- // 开关机状态
- rt_snprintf(num_buf, sizeof(num_buf), "%u", dev_info.power_state);
- cJSON_AddStringToObject(work, "DEV_IS_ON", num_buf);
- // 光控工作时长
- rt_snprintf(num_buf, sizeof(num_buf), "%u", dev_info.light_work_duration);
- cJSON_AddStringToObject(work, "LIGHT_WORK_HOUR", num_buf);
- // 工作模式
- rt_snprintf(num_buf, sizeof(num_buf), "%u", dev_info.time_ctrl_enable);
- cJSON_AddStringToObject(work, "WORK_MODE", num_buf);
- // 时控开始
- rt_snprintf(num_buf, sizeof(num_buf), "%u", dev_info.time_start);
- cJSON_AddStringToObject(work, "TIME_CTL_START", num_buf);
- // 时控结束
- rt_snprintf(num_buf, sizeof(num_buf), "%u", dev_info.time_end);
- cJSON_AddStringToObject(work, "TIME_CTL_END", num_buf);
- // 欠压保护
- if (sys_sta.undervolt_protect == VALID)
- {
- cJSON_AddStringToObject(ext, "UV_PROT", "1"); // 欠压
- }
- else
- {
- cJSON_AddStringToObject(ext, "UV_PROT", "0"); // 正常
- }
- // 温控保护
- if (sys_sta.temp_protect == 0x7A) // 低温
- {
- cJSON_AddStringToObject(ext, "TEMP_PROT", "1");
- }
- else if (sys_sta.temp_protect == VALID) // 高温
- {
- cJSON_AddStringToObject(ext, "TEMP_PROT", "2");
- }
- else // 正常
- {
- cJSON_AddStringToObject(ext, "TEMP_PROT", "0");
- }
- // 倾倒保护
- if (sys_sta.tilt_protect == VALID)
- {
- cJSON_AddStringToObject(ext, "Tilt_PROT", "1");
- }
- else
- {
- cJSON_AddStringToObject(ext, "Tilt_PROT", "0");
- }
- // 雨控保护
- if (sys_sta.rain_protect == VALID)
- {
- cJSON_AddStringToObject(ext, "Rain_PROT", "1");
- }
- else
- {
- cJSON_AddStringToObject(ext, "Rain_PROT", "0");
- }
- // 光控保护
- if (sys_sta.light_protect == VALID)
- {
- cJSON_AddStringToObject(ext, "Light_PROT", "1");
- }
- else
- {
- cJSON_AddStringToObject(ext, "Light_PROT", "0");
- }
- // 高压计数
- // ct
- rt_snprintf(num_buf, sizeof(num_buf), "%u", sys_sta.hv_count);
- cJSON_AddStringToObject(work, "HV_CNT", num_buf);
- // 电压部分
- char buf[16];
- // 充电电压
- int cv_int = sys_sta.charge_voltage / 1000;
- int cv_dec = sys_sta.charge_voltage % 1000;
- rt_snprintf(buf, sizeof(buf), "%d.%03d", cv_int, cv_dec);
- cJSON_AddStringToObject(ext, "V_CHG", buf);
- // 电池电压
- int bv_int = sys_sta.battery_voltage / 1000;
- int bv_dec = sys_sta.battery_voltage % 1000;
- rt_snprintf(buf, sizeof(buf), "%d.%03d", bv_int, bv_dec);
- cJSON_AddStringToObject(ext, "V_BAT", buf);
- // 主板温度
- int bt_int = sys_sta.board_temp / 10;
- rt_snprintf(buf, sizeof(buf), "%d", bt_int);
- cJSON_AddStringToObject(ext, "T_BOARD", buf);
- /* ========== 传感器数据联动逻辑 ==========
- * 优先级:SHT30 > (NTC温度 + PLAT湿度) > PLAT > 默认值
- * - 温度:SHT30 > NTC > PLAT > 22.0
- * - 湿度:SHT30 > PLAT > 33.0
- */
- uint8_t temp_source = 0; /* 温度来源:1=SHT,2=NTC,3=PLAT,4=默认 */
- uint8_t humi_source = 0; /* 湿度来源:1=SHT,2=PLAT,3=默认 */
- /* 1. 优先使用 SHT30 数据 */
- if (sensor.valid_sht == VALID)
- {
- temp_source = 1;
- humi_source = 1;
- LOG_D("Sensor: using SHT30 data (temp=%d.%d°C, humi=%d.%d%%)",
- sensor.temp_sht / 10, sensor.temp_sht % 10,
- sensor.humi_sht / 10, sensor.humi_sht % 10);
- }
- /* 2. SHT30 不可用,尝试组合:NTC温度 + PLAT湿度 */
- else if (sensor.valid_ntc == VALID && sensor.valid_plat == VALID)
- {
- temp_source = 2;
- humi_source = 2;
- LOG_D("Sensor: using NTC temp + PLAT humi (temp=%d.%d°C, humi=%d.%d%%)",
- sensor.temp_ntc / 10, sensor.temp_ntc % 10,
- sensor.humi_plat / 10, sensor.humi_plat % 10);
- }
- /* 3. 使用 PLAT 数据 */
- else if (sensor.valid_plat == VALID)
- {
- temp_source = 3;
- humi_source = 2;
- LOG_D("Sensor: using PLAT data (temp=%d.%d°C, humi=%d.%d%%)",
- sensor.temp_plat / 10, sensor.temp_plat % 10,
- sensor.humi_plat / 10, sensor.humi_plat % 10);
- }
- /* 4. 使用 NTC 温度,湿度使用默认值 */
- else if (sensor.valid_ntc == VALID)
- {
- temp_source = 2;
- humi_source = 3;
- LOG_D("Sensor: using NTC temp only (temp=%d.%d°C), humidity default 33.0%%",
- sensor.temp_ntc / 10, sensor.temp_ntc % 10);
- }
- /* 5. 所有传感器都无效,使用默认值 */
- else
- {
- temp_source = 4;
- humi_source = 3;
- LOG_W("Sensor: ALL sensors invalid, using default values (temp=22.0°C, humi=33.0%%)");
- }
- switch (temp_source)
- {
- case 1:
- cJSON_AddStringToObject(ext, "temp_source", "SHT30");
- rt_snprintf(buf, sizeof(buf), "%d.%d", sensor.temp_sht / 10, sensor.temp_sht % 10);
- cJSON_AddStringToObject(ext, "TEMP", buf);
- break;
- case 2:
- cJSON_AddStringToObject(ext, "temp_source", "NTC");
- rt_snprintf(buf, sizeof(buf), "%d.%d", sensor.temp_ntc / 10, sensor.temp_ntc % 10);
- cJSON_AddStringToObject(ext, "TEMP", buf);
- break;
- case 3:
- cJSON_AddStringToObject(ext, "temp_source", "PLAT");
- rt_snprintf(buf, sizeof(buf), "%d.%d", sensor.temp_plat / 10, sensor.temp_plat % 10);
- cJSON_AddStringToObject(ext, "TEMP", buf);
- break;
- case 4:
- cJSON_AddStringToObject(ext, "temp_source", "default");
- rt_snprintf(buf, sizeof(buf), "%d.%d", 22 / 10, 22 % 10);
- cJSON_AddStringToObject(ext, "TEMP", buf);
- break;
- default:
- break;
- }
- switch (humi_source)
- {
- case 1:
- cJSON_AddStringToObject(ext, "humi_source", "SHT30");
- rt_snprintf(buf, sizeof(buf), "%d.%d", sensor.humi_sht / 10, sensor.humi_sht % 10);
- cJSON_AddStringToObject(ext, "HUMI", buf);
- break;
- case 2:
- cJSON_AddStringToObject(ext, "humi_source", "PLAT");
- rt_snprintf(buf, sizeof(buf), "%d.%d", sensor.humi_plat / 10, sensor.humi_plat % 10);
- cJSON_AddStringToObject(ext, "HUMI", buf);
- break;
- case 3:
- cJSON_AddStringToObject(ext, "humi_source", "default");
- rt_snprintf(buf, sizeof(buf), "%d.%d", 33 / 10, 33 % 10);
- cJSON_AddStringToObject(ext, "HUMI", buf);
- break;
- default:
- break;
- }
- // 灯管状态
- if (sys_sta.lamp_fault == VALID) // 短路
- {
- cJSON_AddStringToObject(ext, "LAMP_STA", "2");
- }
- else if (sys_sta.lamp_fault == 0x7A) // 开路
- {
- cJSON_AddStringToObject(ext, "LAMP_STA", "3");
- }
- else if (gpio_lamp_get_status()) // 开
- {
- cJSON_AddStringToObject(ext, "LAMP_STA", "1");
- }
- else // 关
- {
- cJSON_AddStringToObject(ext, "LAMP_STA", "0");
- }
- /* 灯管故障 */
- // 数据间隔
- rt_snprintf(num_buf, sizeof(num_buf), "%u", dev_info.data_interval);
- cJSON_AddStringToObject(info, "DATA_INR", num_buf);
- // GPS模式
- rt_snprintf(num_buf, sizeof(num_buf), "%u", dev_info.GPS_MODE);
- cJSON_AddStringToObject(info, "GPS_MODE", num_buf);
- if (dev_info.GPS_MODE == 0)
- {
- cJSON_AddStringToObject(info, "LAT", dev_info.latitude_FORCE);
- cJSON_AddStringToObject(info, "LON", dev_info.longitude_FORCE);
- }
- else if (dev_info.GPS_MODE == 1)
- {
- cJSON_AddStringToObject(info, "LAT", dev_info.latitude);
- cJSON_AddStringToObject(info, "LON", dev_info.longitude);
- }
- cJSON_AddNumberToObject(ext, "Light_Percent", sys_sta.light_percent / 10 + (sys_sta.light_percent % 10 / 5));
- cJSON_AddNumberToObject(ext, "Lamp_Current", sys_sta.lamp_current);
- if (dev_info.light_flag == 0)
- {
- cJSON_AddStringToObject(work, "Light_Source", "太阳能板");
- }
- else if (dev_info.light_flag == 1)
- {
- cJSON_AddStringToObject(work, "Light_Source", "光敏管");
- }
- /**
- * @brief 下面是新增的第一部分 设备工作状态
- *
- */
- const char *state_str = "";
- switch (g_work_state)
- {
- case WORK_STATE_IDLE:
- state_str = "空闲中";
- break;
- case WORK_STATE_WORKING:
- state_str = "工作中";
- break;
- case WORK_STATE_LIGHT_PRT:
- state_str = "光控中";
- break;
- case WORK_STATE_COOLDOWN:
- state_str = "冷却中";
- break;
- case WORK_STATE_WAIT_DAY:
- state_str = "工作结束等待天亮(光控)";
- break;
- case WORK_STATE_OTHER_PRT:
- state_str = "保护中";
- break;
- default:
- break;
- }
- cJSON_AddStringToObject(work, "WORK_STATUS", state_str);
- /* 工作模式 */
- if (g_work_state == 1)
- {
- /* 进度百分比 */
- cJSON_AddNumberToObject(work, "WORK_PERCENT", g_work_progress);
- if (g_work_total_sec > 0)
- {
- uint32_t remain_min = (g_work_total_sec - g_work_elapsed_sec) / 60;
- cJSON_AddNumberToObject(work, "Remaining_Min", remain_min);
- }
- }
- cJSON_AddNumberToObject(ext, "TEMP_SHT", sensor.temp_sht / 10);
- cJSON_AddNumberToObject(ext, "TEMP_NTC", sensor.temp_ntc / 10);
- cJSON_AddNumberToObject(ext, "TEMP_PLAT", sensor.temp_plat / 10);
- /**
- * @brief 下面是保护阈值
- *
- */
- cJSON_AddNumberToObject(cjson_limit, "V-SunRise", limit.vsunrise);
- cJSON_AddNumberToObject(cjson_limit, "V-SunSet", limit.vsunset);
- cJSON_AddNumberToObject(cjson_limit, "UV-OFF", limit.uvoff);
- cJSON_AddNumberToObject(cjson_limit, "UV-ON", limit.uvon);
- cJSON_AddNumberToObject(cjson_limit, "TEMP-OVER", limit.overtemp / 10);
- cJSON_AddNumberToObject(cjson_limit, "TEMP-UNOVER", limit.unovert / 10);
- cJSON_AddNumberToObject(cjson_limit, "TEMP-LOW", limit.lowtemp / 10);
- cJSON_AddNumberToObject(cjson_limit, "TEMP-UNLOW", limit.unlowt / 10);
- // /**
- // * @brief 以下是控制类的信息(上下限)
- // *
- // */
- // cJSON_AddNumberToObject(range, "DATA_INR_MIN", 5);
- // cJSON_AddNumberToObject(range, "DATA_INR_MAX", 180);
- // cJSON_AddNumberToObject(range, "DEV_IS_ON_MIN", 0);
- // cJSON_AddNumberToObject(range, "DEV_IS_ON_MAX", 1);
- // cJSON_AddNumberToObject(range, "GPS_MODE_MIN", 0);
- // cJSON_AddNumberToObject(range, "GPS_MODE_MAX", 1);
- // cJSON_AddNumberToObject(range, "LIGHT_WORK_HOUR_MIN", 0);
- // cJSON_AddNumberToObject(range, "LIGHT_WORK_HOUR_MAX", 10);
- // cJSON_AddNumberToObject(range, "TIME_CTL_END_MIN", 0);
- // cJSON_AddNumberToObject(range, "TIME_CTL_END_MAX", 23);
- // cJSON_AddNumberToObject(range, "TIME_CTL_START_MIN", 0);
- // cJSON_AddNumberToObject(range, "TIME_CTL_START_MAX", 23);
- // cJSON_AddNumberToObject(range, "WORK_MODE_MIN", 0);
- // cJSON_AddNumberToObject(range, "WORK_MODE_MAX", 1);
- // cJSON_AddNumberToObject(range, "V-SunRise_MIN", 1000);
- // cJSON_AddNumberToObject(range, "V-SunRise_MAX", 5000);
- // cJSON_AddNumberToObject(range, "V-SunSet_MIN", 1000);
- // cJSON_AddNumberToObject(range, "V-SunSet_MAX", 5000);
- // cJSON_AddNumberToObject(range, "UV-OFF_MIN", 1000);
- // cJSON_AddNumberToObject(range, "UV-OFF_MAX", 5000);
- // cJSON_AddNumberToObject(range, "UV-ON_MIN", 1000);
- // cJSON_AddNumberToObject(range, "UV-ON_MAX", 5000);
- // cJSON_AddNumberToObject(range, "TEMP-OVER_MIN", 300);
- // cJSON_AddNumberToObject(range, "TEMP-OVER_MAX", 800);
- // cJSON_AddNumberToObject(range, "TEMP-UNOVER_MIN", 200);
- // cJSON_AddNumberToObject(range, "TEMP-UNOVER_MAX", 700);
- // cJSON_AddNumberToObject(range, "TEMP-LOW_MIN", -20);
- // cJSON_AddNumberToObject(range, "TEMP-LOW_MAX", 10);
- // cJSON_AddNumberToObject(range, "TEMP-UNLOW_MIN", -15);
- // cJSON_AddNumberToObject(range, "TEMP-UNLOW_MAX", 15);
- // LOG_I(" sub_topic : %s", sys_info.customer_cfg.sub_topic[0] ? sys_info.customer_cfg.sub_topic : "(empty)");
- // LOG_I(" pub_topic : %s", sys_info.customer_cfg.pub_topic[0] ? sys_info.customer_cfg.pub_topic : "(empty)");
- // LOG_I(" host : %s", sys_info.customer_cfg.host[0] ? sys_info.customer_cfg.host : "(empty)");
- // LOG_I(" port : %u", sys_info.customer_cfg.port);
- // LOG_I(" qos : %u", sys_info.customer_cfg.qos);
- // LOG_I(" enable : 0x%02X %s", sys_info.customer_cfg.enable,
- cJSON_AddStringToObject(mqtt_vice, "HOST", sys_info.customer_cfg.host);
- cJSON_AddNumberToObject(mqtt_vice, "PORT", sys_info.customer_cfg.port);
- cJSON_AddStringToObject(mqtt_vice, "USER", sys_info.customer_cfg.username);
- cJSON_AddStringToObject(mqtt_vice, "PWD", sys_info.customer_cfg.password);
- cJSON_AddStringToObject(mqtt_vice, "CID", sys_info.customer_cfg.client_id);
- cJSON_AddStringToObject(mqtt_vice, "PUB_T", sys_info.customer_cfg.pub_topic);
- cJSON_AddStringToObject(mqtt_vice, "SUB_T", sys_info.customer_cfg.sub_topic);
- if (sys_info.customer_cfg.enable == VALID)
- {
- cJSON_AddStringToObject(mqtt_vice, "ENABLE", "ON");
- }
- else
- {
- cJSON_AddStringToObject(mqtt_vice, "ENABLE", "OFF");
- }
- return root;
- }
- static void handle_get_devinfo(rt_uint8_t client_idx, cJSON *root)
- {
- (void)root;
- LOG_I("handle_get_devinfo EXE");
- // Recode_e_code(e_mqtt_cmd, 10, "执行上传设备信息命令");
- cJSON *resp = build_devinfo_report();
- if (resp)
- {
- send_response(client_idx, resp);
- }
- }
- static void handle_FORCE_RESET(rt_uint8_t client_idx, cJSON *root)
- {
- (void)root;
- LOG_I("handle_FORCE_RESET EXE");
- RESET_ALL_PARA();
- cJSON *resp = build_simple_response("FORCE_RESET", 0);
- if (resp)
- {
- send_response(client_idx, resp);
- }
- rt_thread_mdelay(300);
- rt_hw_cpu_reset();
- }
- static void handle_lamp_proc_on(rt_uint8_t client_idx, cJSON *root)
- {
- (void)root;
- char off_lamp_proc = 0;
- ef_set_env_blob("off_lamp_proc", &off_lamp_proc, sizeof(off_lamp_proc));
- cJSON *resp = build_simple_response("lamp_proc_on", 0);
- if (resp)
- {
- send_response(client_idx, resp);
- }
- }
- static void handle_lamp_proc_off(rt_uint8_t client_idx, cJSON *root)
- {
- (void)root;
- char off_lamp_proc = VALID;
- ef_set_env_blob("off_lamp_proc", &off_lamp_proc, sizeof(off_lamp_proc));
- cJSON *resp = build_simple_response("lamp_proc_off", 0);
- if (resp)
- {
- send_response(client_idx, resp);
- }
- }
|