app_nb.c 77 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784
  1. #include "board.h"
  2. #include "app_nb.h"
  3. #include "prj_com.h"
  4. #include "param.h"
  5. #include "rtc_run.h"
  6. #include "board.h"
  7. #include "tdc_tof.h"
  8. #include "bill.h"
  9. #include "alarm.h"
  10. #include "stat.h"
  11. #include "ymodem.h"
  12. Nb_Run_t NbRun;
  13. uint8_t NB_CHECK_TDC_COMPLETE_FLAG = 0;
  14. uint8_t NbIntStep = 0xFFu;
  15. rt_sem_t Nb_thread_run_sem = RT_NULL; // NB线程运行信号量
  16. // 补报相关信息
  17. NbAppFrame_t __attribute__((aligned(4))) NbAppFrame;
  18. uint8_t Nb_rx_data(void);
  19. void nb_run_init(void)
  20. {
  21. lpuart0_set_rx_itf(NbRxCh); // nb串口中断
  22. // NbRun.rx_flag = FALSE;
  23. NbRun.rx_over_time = 0;
  24. NbRun.rx_idx = 0;
  25. memset(NbRun.rx_buf, 0, sizeof(NbRun.rx_buf));
  26. memset(NbRun.tx_buf, 0, sizeof(NbRun.tx_buf));
  27. NbRun.cur_at = at_end;
  28. NbRun.rsrp = 0;
  29. NbRun.rsrq = 0;
  30. NbRun.rssi = 0;
  31. NbRun.snr = 0;
  32. memset(NbRun.imei, 0, sizeof(NbRun.imei));
  33. memset(NbRun.imsi, 0, sizeof(NbRun.imsi));
  34. memset(NbRun.ccid, 0, sizeof(NbRun.ccid));
  35. NbRun.task.count = 0;
  36. // NbRun.open_time_out = 0;
  37. memset(&NbAppFrame, 0, sizeof(NbAppFrame));
  38. NbRun.status = 0;
  39. Nb_thread_run_sem = rt_sem_create("nb_thread_run", 0, RT_IPC_FLAG_FIFO); // 创建nb运行信号量
  40. NbRun.get_imei_flag = 0;
  41. NbRun.get_imsi_flag = 0;
  42. NbRun.get_ccid_flag = 0;
  43. }
  44. static void NbBuildDataHeader(uint16_t data_len)
  45. {
  46. Param_t *param;
  47. GetParam(&param);
  48. NbAppFrame.prefix[0] = 0xFE;
  49. NbAppFrame.prefix[1] = 0xFE;
  50. NbAppFrame.head = 0x68;
  51. NbAppFrame.type = 0x10;
  52. // memcpy(NbAppFrame.addr, param->dev_id, sizeof(param->dev_id));
  53. NbAppFrame.addr[0] = param->dev_id[5];
  54. NbAppFrame.addr[1] = param->dev_id[4];
  55. NbAppFrame.addr[2] = param->dev_id[3];
  56. NbAppFrame.addr[3] = param->dev_id[2];
  57. NbAppFrame.addr[4] = param->dev_id[1];
  58. NbAppFrame.addr[5] = param->dev_id[0];
  59. // NbAppFrame.addr[6] = param->dev_id[0];
  60. NbAppFrame.addr[6] = 0x00;
  61. NbAppFrame.ctrl = 0xA0;
  62. NbAppFrame.len[0] = (unsigned char)(data_len);
  63. NbAppFrame.len[1] = (unsigned char)(data_len >> 8);
  64. }
  65. static void NbBuildDataTail(uint16_t data_len)
  66. {
  67. uint8_t cs = 0;
  68. // cs
  69. cs = check_sum((uint8_t *)&NbAppFrame.head, 12);
  70. cs += check_sum(NbAppFrame.data, data_len);
  71. NbAppFrame.data[data_len] = cs; // 8位累加和
  72. NbAppFrame.data[data_len + 1] = 0x16; // 结束位
  73. }
  74. /*
  75. int NbRcvDataValid(void)
  76. {
  77. char *p = NULL;
  78. int16_t index1 = 0;
  79. uint16_t index2 = 0;
  80. char data[5] = {0};
  81. uint32_t len;
  82. uint8_t cs;
  83. uint16_t data_len;
  84. if (Nb_rx_data() == 0)
  85. return 0;
  86. p = strstr((char *)NbRun.rx_buf, ",");
  87. if (p == NULL)
  88. {
  89. // LOG("no data recv flag\n");
  90. NbClrRxBuf();
  91. return 2;
  92. }
  93. index1 = 2; // strnchar((char *)NbRun.rx_buf, ':', 0);
  94. index2 = strnchar((char *)NbRun.rx_buf, ',', 0);
  95. // index1 = strnchar((char *)NbRun.rx_buf, ',', 0);
  96. // index2 = strnchar((char *)NbRun.rx_buf, ',', 1);
  97. if (index1 > index2 || index2 < 1 || (index2 - index1) > sizeof(data))
  98. {
  99. NbClrRxBuf();
  100. return 3;
  101. }
  102. memcpy(data, NbRun.rx_buf + index1, index2 - index1);
  103. str2int(data, &len); // 已发送数据长度
  104. if (len < 14)
  105. {
  106. NbClrRxBuf();
  107. return 4;
  108. }
  109. StrToHexBuf((char *)&NbAppFrame.head, (char *)(NbRun.rx_buf + index2 + 1), len);
  110. NbClrRxBuf();
  111. if (NbAppFrame.head != 0x68)
  112. { // 帧头不正确
  113. return 5;
  114. }
  115. data_len = (NbAppFrame.len[1] << 8) | NbAppFrame.len[0];
  116. if (len != 14 + data_len)
  117. { // 已发送长度不正确
  118. return 6;
  119. }
  120. cs = check_sum((uint8_t *)&NbAppFrame.head, len - 2);
  121. if (cs != NbAppFrame.data[data_len])
  122. { // crc校验不正确
  123. return 7;
  124. }
  125. if (NbAppFrame.data[data_len + 1] != 0x16)
  126. { // 结束符不正确
  127. return 8;
  128. }
  129. return 1;
  130. }*/
  131. char *get_frame_start(char *buf, uint16_t len)
  132. {
  133. if (buf == NULL || len < 2)
  134. {
  135. return NULL;
  136. }
  137. for (uint16_t i = 0; i <= len - 2; i++)
  138. {
  139. if ((uint8_t)buf[i] == 0x68 && (uint8_t)buf[i + 1] == 0x10)
  140. {
  141. return &buf[i];
  142. }
  143. }
  144. return NULL;
  145. }
  146. int NbRcvDataValid(void)
  147. {
  148. char *p_comma = NULL;
  149. char *p_start = NULL;
  150. char len_str[8] = {0};
  151. uint32_t total_frame_len = 0;
  152. uint8_t cs;
  153. uint8_t head_len = 0;
  154. uint16_t data_len;
  155. // 1. 检查是否有数据接收完成标志
  156. if (Nb_rx_data() == 0)
  157. return 0; // 无数据,继续等待
  158. // 2. 接收数据关键字
  159. p_comma = strstr((char *)NbRun.rx_buf, "+QIRD: ");
  160. if (p_comma == NULL)
  161. {
  162. // 没有逗号,检查是否全是空白或OK,如果是则清除
  163. if (strstr((char *)NbRun.rx_buf, "OK") != NULL || NbRun.rx_idx > 50)
  164. {
  165. NbClrRxBuf();
  166. }
  167. return 0; // 数据可能不完整,继续等待
  168. }
  169. p_start = p_comma + 7; //+QIRD:后的数据开始位置
  170. while (*p_start >= '0' && *p_start <= '9')
  171. {
  172. len_str[head_len++] = *p_start++;
  173. }
  174. len_str[head_len] = '\0';
  175. total_frame_len = atoi(len_str); // 数据总长度
  176. if (total_frame_len < 14)
  177. {
  178. NbClrRxBuf();
  179. return 4;
  180. }
  181. // 6. 检查 Hex 数据完整性
  182. // char *p_hex_start = p_start + head_len + 2; // 包含关键字+ 长度域+ 回车换行符
  183. char *p_hex_start = get_frame_start(p_start + 2, NbRun.rx_idx - (p_start + 2 - (char *)NbRun.rx_buf));
  184. if (p_hex_start == NULL)
  185. {
  186. return 0; // 数据不完整,继续等待
  187. }
  188. // 6.2 检查校验和
  189. cs = 0;
  190. uint16_t available_chars = NbRun.rx_idx - (p_hex_start - (char *)NbRun.rx_buf);
  191. if (available_chars < total_frame_len) // 这里可能要改为接收二进制数据,(去掉*2)
  192. {
  193. return 0; // 数据不完整,继续等待
  194. }
  195. // 7. Hex 转 Binary
  196. // StrToHexBuf((char *)&NbAppFrame.head, p_hex_start, total_frame_len);//如果是二进制数据,则不需要转换
  197. memcpy((char *)&NbAppFrame.head, p_hex_start, total_frame_len);
  198. NbClrRxBuf();
  199. // 8. 校验帧头
  200. if (NbAppFrame.head != 0x68)
  201. return 5;
  202. // 9. 校验长度一致性
  203. data_len = (NbAppFrame.len[1] << 8) | NbAppFrame.len[0];
  204. if (total_frame_len != (14 + data_len))
  205. return 6;
  206. // 10. 校验 Check Sum
  207. cs = check_sum((uint8_t *)&NbAppFrame.head, total_frame_len - 2);
  208. if (cs != NbAppFrame.data[data_len])
  209. return 7;
  210. // 11. 校验帧尾
  211. if (NbAppFrame.data[data_len + 1] != 0x16)
  212. return 8;
  213. return 1; // 验证成功
  214. }
  215. void GetNbRun(Nb_Run_t **nb_run)
  216. {
  217. *nb_run = &NbRun;
  218. }
  219. void NbRxCh(uint8_t ch)
  220. {
  221. if (NbRun.rx_idx >= NB_RXLEN_MAX - 1)
  222. {
  223. return;
  224. }
  225. NbRun.rx_buf[NbRun.rx_idx++] = ch;
  226. NbRun.rx_over_time = 4;
  227. #ifdef DEBUG_NB
  228. // LOG("%c",ch);
  229. #endif
  230. }
  231. // void NbRxTimeout(void)
  232. //{
  233. // if (NbRun.rx_over_time >= 2) {
  234. // NbRun.rx_over_time--;
  235. // } else if (NbRun.rx_over_time == 1) {
  236. // NbRun.rx_flag = TRUE;
  237. // NbRun.rx_over_time--;
  238. // }
  239. // }
  240. uint8_t Nb_rx_data(void)
  241. {
  242. if (NbRun.rx_over_time != 0)
  243. {
  244. NbRun.rx_over_time--;
  245. }
  246. if (NbRun.rx_over_time == 1)
  247. {
  248. #ifdef DEBUG_NB
  249. /////////////////////
  250. unsigned short i;
  251. for (i = 0; i < NbRun.rx_idx; i++)
  252. LOG("%c", NbRun.rx_buf[i]);
  253. // LOG("%s\r\n",NbRun.rx_buf);
  254. ///////////////////
  255. #endif
  256. return 1; // 已收到数据
  257. // }
  258. }
  259. return 0;
  260. }
  261. void NbClrRxBuf(void)
  262. {
  263. NbRun.rx_idx = 0;
  264. memset(NbRun.rx_buf, 0, sizeof(NbRun.rx_buf));
  265. }
  266. int8_t get_nb_imsi_code(void)
  267. {
  268. char *p = NULL;
  269. char *q = NULL;
  270. uint8_t i, flag;
  271. p = strstr((char *)NbRun.rx_buf, "OK");
  272. if (p == NULL)
  273. {
  274. return -1;
  275. }
  276. p = strstr((char *)NbRun.rx_buf, "\r\n"); // 找到第一个回车符
  277. if (p != NULL && strlen(p) > 2)
  278. {
  279. q = strstr(p + 2, "\r\n"); // 第二个回车符,id在两个回车符之间
  280. if (q != NULL && (q - p - 2) > 0 && (q - p - 2) < 16)
  281. { // 长度大于2小于15
  282. *q = 0;
  283. strcpy(NbRun.imsi, p + 2);
  284. /// LOG("imsi = %s\n", NbRun.imsi);
  285. }
  286. }
  287. flag = 0;
  288. for (i = 0; NbRun.imsi[i] != 0; i++)
  289. {
  290. if (NbRun.imsi[i] < '0' || NbRun.imsi[i] > '9')
  291. {
  292. flag = 1;
  293. break;
  294. }
  295. }
  296. if (flag == 1 || i != 15)
  297. return -1;
  298. NbRun.get_imsi_flag = 1; // 已获取IMEI号标志
  299. return 0;
  300. }
  301. int8_t get_nb_imei_code(void)
  302. {
  303. char *p = NULL;
  304. char *q = NULL;
  305. uint8_t i, flag;
  306. p = strstr((char *)NbRun.rx_buf, "OK");
  307. if (p == NULL)
  308. {
  309. return -1;
  310. }
  311. p = strstr((char *)NbRun.rx_buf, "+CGSN:");
  312. if (p != NULL)
  313. {
  314. p = strstr((char *)NbRun.rx_buf, "\""); // 找到第一个"所在位置
  315. if (p != NULL && strlen(p + 1) > 1)
  316. {
  317. q = strstr(p + 1, "\"\r\n"); // 回车换行符所在位置
  318. if (q != NULL && (q - p - 1) > 0 && (q - p - 1) < 16)
  319. { // 存在回车换行符,且:到换行符之间有信息,且长度小于16
  320. *q = 0; // 把第二个"置0,作为字符串结束位置
  321. strcpy(NbRun.imei, p + 1);
  322. }
  323. }
  324. }
  325. flag = 0;
  326. for (i = 0; NbRun.imei[i] != 0; i++)
  327. {
  328. if (NbRun.imei[i] < '0' || NbRun.imei[i] > '9')
  329. {
  330. flag = 1;
  331. break;
  332. }
  333. }
  334. if (flag == 1 || i != 15)
  335. return -1;
  336. NbRun.get_imei_flag = 1; // 已获取IMEI号标志
  337. #ifdef APP_DEBUG_PRINT
  338. LOG("imei=%s\r\n", NbRun.imei);
  339. #endif
  340. return 0;
  341. }
  342. int8_t get_nb_ccid_code(void)
  343. {
  344. char *p = NULL;
  345. char *q = NULL;
  346. uint8_t i, flag;
  347. p = strstr((char *)NbRun.rx_buf, "OK");
  348. if (p == NULL)
  349. {
  350. return -1;
  351. }
  352. p = strstr((char *)NbRun.rx_buf, ":");
  353. p++;
  354. if (p != NULL && strlen(p) > 1)
  355. {
  356. q = strstr(p + 1, "\r\n");
  357. if (q != NULL && (q - p - 1) > 0 && (q - p - 1) < 21)
  358. {
  359. *q = 0;
  360. strcpy(NbRun.ccid, p + 1);
  361. }
  362. }
  363. flag = 0;
  364. for (i = 0; NbRun.ccid[i] != 0; i++)
  365. {
  366. if (NbRun.ccid[i] < '0' || NbRun.ccid[i] > '9')
  367. {
  368. flag = 1;
  369. break;
  370. }
  371. }
  372. if (flag == 1 || i != 20)
  373. return -1;
  374. NbRun.get_ccid_flag = 1; // 已获取IMEI号标志
  375. #ifdef APP_DEBUG_PRINT
  376. LOG("iccid=%s\r\n", NbRun.ccid);
  377. #endif
  378. return 0;
  379. }
  380. // NUESTATS:CELL,<earfcn>,<physical_cell_id>,<primarycell>,<RSRP>,<RSRQ>,<RSSI>,<SNR>
  381. // NUESTATS:CELL,2401,476,1,-920,-41,-879,144
  382. // 在 app_nb.c 中找到 NbSetUploadMode 函数并替换
  383. void NbSetUploadMode(uint8_t mode)
  384. {
  385. // 【修改点】:始终更新 mode,使用 |= 确保不覆盖已有的触发原因
  386. // 例如:如果之前是定时上报(0x02),现在发生了错误报警(0x10),mode 将变为 0x12
  387. NbRun.upload.mode |= mode;
  388. // 只有在尚未标记上传任务时,才设置 flag 并唤醒线程
  389. if (NbRun.upload.flag == FALSE)
  390. {
  391. NbRun.upload.flag = TRUE;
  392. NbRun.task.flag = 1;
  393. NbRun.cur_afn = 0x0010;
  394. rt_sem_release(Nb_thread_run_sem); // 触发nb线程
  395. }
  396. }
  397. /////////////////等待接收指定的回复///////////////////////
  398. // ack:回复的字符串
  399. // timeout:等待超时时间 秒单位
  400. //: 返回0:成功, -1:等待超时
  401. /////////////////////////////////////
  402. int8_t Nb_check_rec_valid(uint8_t state, char *ack)
  403. {
  404. // if(state == COAP_WAIT_REG){
  405. // if(strstr((const char *)NbRun.rx_buf, ack) != NULL )
  406. // }
  407. // else
  408. if (strstr((const char *)NbRun.rx_buf, ack) != NULL)
  409. { // 收到要求的回复
  410. return 1; // 收到正确回复,进行下一步
  411. }
  412. if (strstr((char *)&NbRun.rx_buf[0], "\r\nOK\r\n") != NULL || strstr((char *)&NbRun.rx_buf[0], "\r\nERROR\r\n") != NULL)
  413. {
  414. return -1; // 错误回复,重新发送
  415. }
  416. return 0; // 其他需要继续等待
  417. }
  418. void nb_send_data_route(unsigned char *data, uint16_t len) // 发送数据 TCP
  419. {
  420. char tmp[16] = {0};
  421. memset(NbRun.tx_buf, 0, sizeof(NbRun.tx_buf));
  422. strcpy((char *)NbRun.tx_buf, "AT+QISENDEX=0,"); // at指令 发送数据
  423. // int2str(len, tmp); // 转换成字符串
  424. strcat((char *)NbRun.tx_buf, "\"");
  425. HexBufToStr((char *)NbRun.tx_buf + strlen((char *)NbRun.tx_buf), data, len); // 不加前面的指令部分,只发送数据部分
  426. strcat((char *)NbRun.tx_buf, "\"");
  427. strcat((char *)NbRun.tx_buf, "\r\n\0"); // 末尾回车换行符
  428. // NbRoutineEventPro((char *)NbRun.tx_buf, (char *)NB_NMGS_ACK, 3, 60);
  429. }
  430. UPLOAD_DEF upload_dat;
  431. const uint8_t monthday[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  432. ///////////////////////////////////////////
  433. /////////////////////////////////main.c中运行,判断是否应该触发nb线程//////////////////////////////////////////////
  434. // 参数 无
  435. // 返回 无
  436. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  437. uint8_t settlement_day_upload_check(void)
  438. { // 结算日上报
  439. if (Paramx.settlement_day == 0)
  440. return 0;
  441. rtc_run_t *rr;
  442. get_rtc_run(&rr);
  443. uint8_t days, setday;
  444. days = monthday[rr->month - 1];
  445. if (rr->year % 4 == 0 && rr->month == 2)
  446. {
  447. days++;
  448. } // 计算当月天数
  449. //////////////////////确定当天上报是否是结算日上报/////////////////////////////////////
  450. int32_t now, start;
  451. now = (int32_t)(3600 * rr->hour + 60 * rr->minute + rr->second);
  452. start = (int32_t)(Paramx.report_base_hour * 3600 + Paramx.report_base_min * 60 + (Paramx.report_base_sec & 0xfe));
  453. if (Paramx.settlement_day == 0)
  454. {
  455. return 0;
  456. }
  457. if (Paramx.settlement_day > days)
  458. {
  459. setday = days;
  460. }
  461. else
  462. {
  463. setday = Paramx.settlement_day;
  464. }
  465. if (now < start)
  466. return 0;
  467. if (setday == rr->day && now - start <= 5)
  468. {
  469. return NB_UPLOAD_SETTLE_DAY;
  470. }
  471. return 0;
  472. }
  473. uint8_t regular_upload_check(void)
  474. { // 定时上报
  475. uint32_t *alarmbit;
  476. all_alarm_status(&alarmbit);
  477. if ((*alarmbit & ERR_LOW_POWER) != 0)
  478. return 0; // 低电压不上报
  479. uint8_t i;
  480. rtc_run_t *rr;
  481. get_rtc_run(&rr);
  482. int32_t now, start;
  483. now = (int32_t)(3600 * rr->hour + 60 * rr->minute + rr->second);
  484. start = (int32_t)(Paramx.report_base_hour * 3600 + Paramx.report_base_min * 60 + (Paramx.report_base_sec & 0xfe));
  485. if (now < start)
  486. return 0; // 未到上报时间
  487. if (((now - start) % (Paramx.report_interval * 60)) <= 5)
  488. return NB_UPLOAD_TIMER;
  489. return 0;
  490. }
  491. uint8_t dma_upload_check(void)
  492. {
  493. uint32_t *alarmbit;
  494. all_alarm_status(&alarmbit);
  495. if ((*alarmbit & ERR_LOW_POWER) != 0)
  496. return 0; // 低电压DMA不上报
  497. if (Paramx.dma_interval == 0)
  498. return 0; // 无dma上报
  499. int32_t start_sec, end_sec, now_sec;
  500. rtc_run_t *rr;
  501. get_rtc_run(&rr);
  502. start_sec = (int32_t)(3600 * Paramx.dma_report_start[0] + 60 * Paramx.dma_report_start[1] + Paramx.dma_report_start[2]);
  503. end_sec = (int32_t)(3600 * Paramx.dma_report_end[0] + 60 * Paramx.dma_report_end[1] + Paramx.dma_report_end[2]);
  504. now_sec = (int32_t)(3600 * rr->hour + 60 * rr->minute + rr->second);
  505. if (now_sec < start_sec || now_sec > end_sec + 3)
  506. return 0; // 不在dma时间范围内
  507. if (((now_sec - start_sec) % (Paramx.dma_interval * 60)) <= 5)
  508. {
  509. return NB_UPLOAD_DMA;
  510. }
  511. return 0;
  512. }
  513. ////////////////故障上报监测///////////////////////
  514. // 参数:无
  515. // 返回:有故障NB_UPLOAD_ERR 无故障:0
  516. ///////////////////////////////////////////////
  517. uint8_t err_upload_check(void)
  518. {
  519. uint32_t *alarmbit;
  520. uint32_t temp;
  521. if (StartUp < 15)
  522. return 0;
  523. all_alarm_status(&alarmbit);
  524. temp = (upload_dat.err_mem_dat & (*alarmbit)) ^ (*alarmbit); // 检查是否有异常bit被置位
  525. if (temp != 0)
  526. {
  527. upload_dat.err_mem_dat = *alarmbit;
  528. return NB_UPLOAD_ERR;
  529. }
  530. return 0;
  531. }
  532. uint8_t rept_upload_check(void)
  533. { // 重复上报监测
  534. uint8_t i;
  535. rtc_run_t *rr;
  536. get_rtc_run(&rr);
  537. tm_t now_time;
  538. now_time.year = rr->year;
  539. now_time.month = rr->month;
  540. now_time.day = rr->day;
  541. now_time.hour = rr->hour;
  542. now_time.min = rr->minute;
  543. now_time.sec = rr->second;
  544. uint32_t now_sec = (uint32_t)(now_time.hour * 3600 + now_time.min * 60 + now_time.sec);
  545. uint32_t start_sec = (uint32_t)(upload_dat.rept_time.hour * 3600 + upload_dat.rept_time.min * 60 + (upload_dat.rept_time.sec & 0xfc));
  546. uint8_t ret = 0;
  547. if (upload_dat.rept_runflag != 0)
  548. {
  549. // if (datecmp(now_time, upload_dat.rept_time) >= 0)
  550. if (now_sec >= start_sec && now_sec <= start_sec + 3)
  551. {
  552. upload_dat.rept_runflag = 0;
  553. return NB_UPLOAD_REPT;
  554. }
  555. }
  556. return 0;
  557. }
  558. // 手动上报
  559. uint8_t manual_upload_check(void)
  560. {
  561. if (upload_dat.manual_runflag == 1)
  562. {
  563. upload_dat.manual_runflag = 0;
  564. return NB_UPLOAD_MANUAL;
  565. }
  566. return 0;
  567. }
  568. short up_signal_cnt = -100; // 用于上报过程中动态显示信号强度
  569. /////////////////////////////////main.c中运行,判断是否应该触发nb线程,1秒1一次//////////////////////////////////////////////
  570. // 参数 无
  571. // 返回 无
  572. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  573. // 在 app_nb.c 中找到 nb_task_run_check 函数并替换
  574. void nb_task_run_check(void)
  575. {
  576. uint8_t trik_flag = 0;
  577. extern const int16_t rsrp_level[5];
  578. // 信号强度动态显示逻辑保持不变
  579. if (NbRun.upload.flag != 0)
  580. {
  581. up_signal_cnt = (up_signal_cnt + 1) % 5;
  582. NbRun.rsrp = rsrp_level[up_signal_cnt];
  583. }
  584. else
  585. NbRun.rsrp = NbRun.rsrp_bak;
  586. #ifdef debug_dog
  587. if (StartUp == 5)
  588. {
  589. rt_enter_critical();
  590. McuFlash_EraseSegment(DIFF_PATCH_PACKET_START, DIFF_PATCH_PACKET_SIZE);
  591. rt_exit_critical();
  592. rt_enter_critical();
  593. uint8_t i;
  594. for (i = 0; i < 16; i++)
  595. xx[i] = i + 1;
  596. write_flash_memory(xx, DIFF_PATCH_PACKET_START, 16);
  597. rt_exit_critical();
  598. while (1)
  599. ;
  600. }
  601. #endif
  602. if (NbRun.reset_mcu_cnt != 0)
  603. {
  604. NbRun.reset_mcu_cnt--;
  605. if (NbRun.reset_mcu_cnt == 2)
  606. LOG("ready to reset mcu\r\n");
  607. if (NbRun.reset_mcu_cnt == 1)
  608. {
  609. // watchdog_init(WdtResetEn, WdtT3s28);
  610. // feed_dog();
  611. NVIC_SystemReset();
  612. // while (1);
  613. // {
  614. // }
  615. }
  616. // NVIC_SystemReset();
  617. }
  618. // 【修改点】:不再因为 NbRun.upload.flag 为真而直接 return
  619. // 即使正在上传,我们也要检查是否有新的触发原因(如错误报警),并将其加入 mode
  620. trik_flag = settlement_day_upload_check();
  621. trik_flag |= regular_upload_check();
  622. trik_flag |= dma_upload_check();
  623. trik_flag |= err_upload_check(); // 错误报警通常优先级最高,但也作为位之一
  624. trik_flag |= rept_upload_check();
  625. trik_flag |= manual_upload_check();
  626. if (trik_flag != 0)
  627. {
  628. // 调用 NbSetUploadMode,它内部会处理 |= 逻辑和线程唤醒逻辑
  629. NbSetUploadMode(trik_flag);
  630. }
  631. // 注意:如果上传已经完成或失败,NbRun.upload.flag 会在 NbTread 末尾清零
  632. // 此时下一次 nb_task_run_check 运行时会正常触发新的上传任务
  633. }
  634. // 上报数据准备,在tx_buf中
  635. void nb_upload_data_ready(void)
  636. {
  637. NbBuildDataReport(); // 组织上报数据,在NbAppFrame中
  638. uint16_t len = ((NbAppFrame.len[1] << 8) | NbAppFrame.len[0]) + 16; // 数据总长度
  639. nb_send_data_route((uint8_t *)&NbAppFrame, len);
  640. }
  641. void nb_set_ip_para_ack(void)
  642. {
  643. // NbBuildSetIpAndPortRsp();
  644. nb_set_para_rept(5, 0x20, 1);
  645. uint16_t len = ((NbAppFrame.len[1] << 8) | NbAppFrame.len[0]) + 16;
  646. nb_send_data_route((uint8_t *)&NbAppFrame, len);
  647. }
  648. void nb_set_regular_report_para_ack(int8_t ret)
  649. {
  650. // NbBuildSetReportPointRsp(ret);
  651. nb_set_para_rept(5, 0x21, ret);
  652. uint16_t len = ((NbAppFrame.len[1] << 8) | NbAppFrame.len[0]) + 16;
  653. nb_send_data_route((uint8_t *)&NbAppFrame, len);
  654. }
  655. void nb_set_dma_report_para_ack(int8_t ret)
  656. {
  657. /// NbBuildSetDmaReportPointRsp(ret);
  658. nb_set_para_rept(5, 0x22, ret);
  659. uint16_t len = ((NbAppFrame.len[1] << 8) | NbAppFrame.len[0]) + 16;
  660. nb_send_data_route((uint8_t *)&NbAppFrame, len);
  661. }
  662. void nb_set_rtc_data_ack(int8_t ret)
  663. {
  664. // NbBuildSetDateTimeRsp(ret);
  665. nb_set_para_rept(5, 0x23, ret);
  666. }
  667. void nb_set_flow_alarm_para_ack(int8_t ret)
  668. {
  669. // NbBuildSetFlowAlarmThresRsp(ret);
  670. nb_set_para_rept(5, 0x24, ret);
  671. uint16_t len = ((NbAppFrame.len[1] << 8) | NbAppFrame.len[0]) + 16;
  672. nb_send_data_route((uint8_t *)&NbAppFrame, len);
  673. }
  674. void nb_set_pressure_alarm_para_ack(int8_t ret)
  675. {
  676. // NbBuildSetPressureAlarmThresRsp(ret);
  677. nb_set_para_rept(5, 0x25, ret);
  678. }
  679. void nb_set_temp_alarm_para_ack(int8_t ret)
  680. {
  681. // NbBuildSetTempAlarmThresRsp(ret);
  682. nb_set_para_rept(5, 0x26, ret);
  683. }
  684. void nb_set_settlment_day_para_ack(int8_t ret)
  685. {
  686. // NbBuildSetSettleRsp(ret);
  687. nb_set_para_rept(5, 0x27, ret);
  688. }
  689. void nb_set_meter_bottom_data_ack(int8_t ret)
  690. {
  691. // NbBuildSetBaseReadingRsp(ret);
  692. nb_set_para_rept(5, 0x28, ret);
  693. }
  694. void nb_read_month_record_ack(void)
  695. {
  696. NbBuildReportMonthRecord();
  697. }
  698. void nb_read_day_record_ack(void)
  699. {
  700. NbBuildReportDayRecord();
  701. }
  702. int8_t nb_read_hour_record_ack(void)
  703. {
  704. uint32_t start, end, ndate;
  705. uint8_t loop_count = 0; // 用于限制循环次数
  706. start = (NbAppFrame.data[5] << 16) | (NbAppFrame.data[6] << 8) | NbAppFrame.data[7];
  707. end = (NbAppFrame.data[9] << 16) | (NbAppFrame.data[10] << 8) | NbAppFrame.data[11];
  708. rtc_run_t *rr;
  709. get_rtc_run(&rr); // 获取当前时间
  710. ndate = (rr->year << 16) | (rr->month << 8) | rr->day;
  711. // 计算30天前的日期边界
  712. uint32_t b30date = ndate;
  713. for (uint8_t i = 0; i < 30; i++)
  714. b30date = prev_day(b30date);
  715. // --- 修改部分开始 ---
  716. // 原逻辑:如果时间不合法,直接返回 -1
  717. // 新逻辑:如果时间不合法,构建一个长度为248且数据全为0的帧发送一次
  718. // 检查合法性
  719. uint8_t is_invalid = 0;
  720. if (start > ndate || end < b30date || start > end)
  721. {
  722. is_invalid = 1;
  723. }
  724. // 校正 start
  725. if (start < b30date)
  726. start = b30date;
  727. // 校正 end
  728. if (end > ndate)
  729. end = ndate;
  730. // 再次检查校正后是否合法
  731. if (start > end)
  732. {
  733. is_invalid = 1;
  734. }
  735. if (is_invalid)
  736. {
  737. uint16_t mid = (NbAppFrame.data[3] << 8) | NbAppFrame.data[2];
  738. // 定义正常的数据长度 (参考 NbBuildReportHourRecord)
  739. uint16_t data_len = 248;
  740. // 构建帧头
  741. NbBuildDataHeader(data_len);
  742. // 设置 AFN 为 0x34 (Read Hour Record Response)
  743. NbAppFrame.data[0] = 0x34;
  744. NbAppFrame.data[1] = 0x00;
  745. // 设置 MID
  746. NbAppFrame.data[2] = (uint8_t)(mid);
  747. NbAppFrame.data[3] = (uint8_t)(mid >> 8);
  748. // 将数据区域全部清零 (NbBuildDataHeader 不会自动清零 data 区域,需手动处理)
  749. // 注意:NbAppFrame.data 的大小通常足够容纳 248 字节
  750. memset(&NbAppFrame.data[4], 0, data_len);
  751. // 构建帧尾 (包含校验和)
  752. NbBuildDataTail(data_len);
  753. uint16_t len = ((NbAppFrame.len[1] << 8) | NbAppFrame.len[0]) + 16;
  754. nb_send_data_route((uint8_t *)&NbAppFrame, len);
  755. // 发送 AT 命令
  756. if (at_cmd_send(COAP_QLWDATASEND, (char *)NbRun.tx_buf, NB_AT_ACK, 3, 60) == -1)
  757. return -1;
  758. return 0; // 返回成功,表示已处理本次请求
  759. }
  760. // --- 修改部分结束 ---
  761. ndate = start;
  762. uint16_t len;
  763. // 无限循环处理所有有效日期,但限制 loop_count < 12 以防死循环或数据过多
  764. while (ndate <= end && loop_count < 12)
  765. {
  766. NbBuildReportHourRecord((uint8_t)(ndate >> 16), (uint8_t)(ndate >> 8), (uint8_t)(ndate));
  767. len = ((NbAppFrame.len[1] << 8) | NbAppFrame.len[0]) + 16;
  768. nb_send_data_route((uint8_t *)&NbAppFrame, len);
  769. if (at_cmd_send(COAP_QLWDATASEND, (char *)NbRun.tx_buf, NB_AT_ACK, 3, 60) == -1)
  770. return -1;
  771. ndate = next_day(ndate);
  772. loop_count++; // 增加计数器
  773. }
  774. return 0;
  775. }
  776. int8_t nb_read_5min_record_ack(void)
  777. {
  778. // 将大型局部变量改为静态变量,以减少栈使用
  779. static tm_t start, end, cur;
  780. static tm_t now_tm, limit_start_tm;
  781. uint16_t len;
  782. uint8_t loop_count = 0; // ?
  783. // 1. е????
  784. start.year = NbAppFrame.data[5];
  785. start.month = NbAppFrame.data[6];
  786. start.day = NbAppFrame.data[7];
  787. start.hour = NbAppFrame.data[8];
  788. start.min = NbAppFrame.data[9];
  789. start.sec = 0;
  790. end.year = NbAppFrame.data[11];
  791. end.month = NbAppFrame.data[12];
  792. end.day = NbAppFrame.data[13];
  793. end.hour = NbAppFrame.data[14];
  794. end.min = NbAppFrame.data[15];
  795. end.sec = 0;
  796. // 2. ????15??
  797. rtc_run_t *rr;
  798. get_rtc_run(&rr);
  799. // ?? tm_t (??)
  800. now_tm.year = rr->year;
  801. now_tm.month = rr->month;
  802. now_tm.day = rr->day;
  803. now_tm.hour = rr->hour;
  804. now_tm.min = rr->minute;
  805. now_tm.sec = rr->second;
  806. // 15???
  807. uint32_t date32 = (rr->year << 16) | (rr->month << 8) | rr->day;
  808. for (uint8_t i = 0; i < 15; i++)
  809. {
  810. date32 = prev_day(date32);
  811. }
  812. limit_start_tm.year = (date32 >> 16) & 0xFF;
  813. limit_start_tm.month = (date32 >> 8) & 0xFF;
  814. limit_start_tm.day = date32 & 0xFF;
  815. limit_start_tm.hour = 0;
  816. limit_start_tm.min = 0;
  817. limit_start_tm.sec = 0;
  818. // 3. ??: start ? end
  819. uint8_t is_invalid = 0;
  820. if (datecmp(start, end) > 0)
  821. {
  822. is_invalid = 1;
  823. }
  824. // 4. ?Ч??Χ
  825. // ЧΧ: [limit_start_tm, now_tm]
  826. if (datecmp(end, limit_start_tm) < 0) // ?15?
  827. {
  828. is_invalid = 1;
  829. }
  830. if (datecmp(start, now_tm) > 0) // ?????
  831. {
  832. is_invalid = 1;
  833. }
  834. // 5. У start end ЧΧ
  835. if (datecmp(start, limit_start_tm) < 0)
  836. {
  837. start = limit_start_tm;
  838. }
  839. if (datecmp(end, now_tm) > 0)
  840. {
  841. end = now_tm;
  842. }
  843. // ?μУ?
  844. if (datecmp(start, end) > 0)
  845. {
  846. is_invalid = 1;
  847. }
  848. // --- ???? ---
  849. // ????388??0??
  850. if (is_invalid)
  851. {
  852. uint16_t mid = (NbAppFrame.data[3] << 8) | NbAppFrame.data[2];
  853. //
  854. uint16_t data_len = 388;
  855. // ??
  856. NbBuildDataHeader(data_len);
  857. // AFN ? 0x37 (Read 5Min Record Response)
  858. NbAppFrame.data[0] = 0x37;
  859. NbAppFrame.data[1] = 0x00;
  860. // MID
  861. NbAppFrame.data[2] = (uint8_t)(mid);
  862. NbAppFrame.data[3] = (uint8_t)(mid >> 8);
  863. // ? (NbBuildDataHeader ? data ?)
  864. // ??NbAppFrame.data ?С? 388 ?
  865. memset(&NbAppFrame.data[4], 0, data_len);
  866. // ?β (У)
  867. NbBuildDataTail(data_len);
  868. len = ((NbAppFrame.len[1] << 8) | NbAppFrame.len[0]) + 16;
  869. nb_send_data_route((uint8_t *)&NbAppFrame, len);
  870. // AT
  871. if (at_cmd_send(COAP_QLWDATASEND, (char *)NbRun.tx_buf, NB_AT_ACK, 3, 60) == -1)
  872. return -1;
  873. return 0; // ????
  874. }
  875. // --- ??? ---
  876. // 6. ??12
  877. cur = start; // 初始化 cur
  878. while (datecmp(cur, end) < 0) // ? while ???м
  879. {
  880. // ?
  881. if (loop_count >= 12)
  882. {
  883. break;
  884. }
  885. NbBuildReport5MinRecord(&cur);
  886. len = ((NbAppFrame.len[1] << 8) | NbAppFrame.len[0]) + 16;
  887. nb_send_data_route((uint8_t *)&NbAppFrame, len);
  888. if (at_cmd_send(COAP_QLWDATASEND, (char *)NbRun.tx_buf, NB_AT_ACK, 3, 60) == -1)
  889. return -1;
  890. // 2С?
  891. time_add_secs(&cur, &cur, 2 * 60 * 60);
  892. loop_count++; // ?
  893. }
  894. return 0;
  895. }
  896. void nb_read_log_record_ack(void)
  897. {
  898. NbBuildReportLogRecord();
  899. }
  900. /////// 设置开始升级信息/////////////////////
  901. /// 返回 1:成功 2:版本号不对 3:长度超限
  902. int8_t nb_set_patch_info(void)
  903. {
  904. PATCH_INFO_DEF dat;
  905. uint8_t *src = &NbAppFrame.data[4];
  906. memcpy(dat.cur_ver, src, 5);
  907. memcpy(dat.new_ver, src + 5, 5);
  908. dat.patch_len = src[10] + ((uint16_t)src[11] << 8) + ((uint32_t)src[12] << 16) + ((uint32_t)src[13] << 24);
  909. dat.per_packet_len = src[14] + 256 * src[15];
  910. dat.packet_crc = src[16] + 256 * src[17];
  911. uint8_t ret = set_patch_info(&dat); // 返回1,2,3 //1成功
  912. // if(ret != 0)return -1;
  913. // else return 0;
  914. return ret;
  915. }
  916. ////////////////////////////////////
  917. // 1.升级成功结束
  918. // 2:升级失败,crc校验失败
  919. // 3.升级失败,多次尝试未获得升级包
  920. // 4.失败,未能成功运行
  921. // 5.失败版本不匹配
  922. // 0x10:重新读取本包数据
  923. // 0x20:获取下一包
  924. ///////////////////////////////////
  925. void nb_set_patch_info_ack(int8_t stat)
  926. {
  927. // if(stat>=1 && stat <= 6 ){
  928. if (stat <= 3)
  929. NbBuildReportUpdateStatus(stat);
  930. //}
  931. else // if(stat == 0x10){
  932. NbBuildGetPackage();
  933. //}
  934. // else if(stat == 0x20){
  935. // NbBuildGetPackage();
  936. // }
  937. }
  938. /////////////在采样中断结束,刚好允许进入低功耗时发送指令,避免接收失败//////////////////////
  939. // dat:要发送的数据
  940. ////////////////////////////////////
  941. // uint8_t NB_CHECK_TDC_COMPLETE_FLAG
  942. // check G_TDC_CAN_DEEP_SLEEP 0->1
  943. void send_nb_data_after_sample(char *dat)
  944. {
  945. extern uint8_t rtc_1s_flag;
  946. if (NB_CHECK_TDC_COMPLETE_FLAG == 1 && rtc_1s_flag == 1)
  947. {
  948. nb_tx_str(dat);
  949. rtc_1s_flag = 0;
  950. }
  951. NB_CHECK_TDC_COMPLETE_FLAG = 0;
  952. }
  953. int8_t rec_data_check(void)
  954. {
  955. // 1. 主动请求数据
  956. send_nb_data_after_sample("AT+QIRD=0,1500\r\n"); // 读取数据,最长1500 tcp限制
  957. // 2. 尝试解析数据
  958. uint8_t result = NbRcvDataValid();
  959. // --- 情况 A: 没有收到完整数据或正在等待 ---
  960. if (result == 0)
  961. {
  962. // 如果是 OTA 过程,允许较长的等待时间
  963. if (NbRun.cur_afn == 0x50 || NbRun.cur_afn == 0x51)
  964. {
  965. NbRun.get_patch_time_out++;
  966. if (NbRun.get_patch_time_out < 120) // 约 5-10秒
  967. return 1; // 继续等待
  968. else
  969. return -1; // OTA 超时
  970. }
  971. return 1; // 普通命令继续等待
  972. }
  973. // --- 情况 B: 数据校验失败 (格式错误、CS错误等) ---
  974. if (result > 1)
  975. {
  976. #ifdef DEBUG_NB
  977. LOG("Rcv Err: %d\r\n", result);
  978. #endif
  979. // 收到垃圾数据,清除状态,让上层循环重试 AT+NMGR
  980. // 返回 1 表示“本次尝试失败,请重试”,而不是“继续等待当前缓冲”
  981. return 1;
  982. }
  983. // --- 情况 C: 数据校验成功 (result == 1) ---
  984. NbRun.get_patch_time_out = 0; // 重置 OTA 超时计数
  985. uint16_t afn = (NbAppFrame.data[1] << 8) | NbAppFrame.data[0];
  986. uint16_t data_len = (NbAppFrame.len[1] << 8) | NbAppFrame.len[0];
  987. // 更新当前 AFN 状态,用于后续多包交互(如 OTA)
  988. if (afn != 0x51)
  989. { // 数据包通常不改变 cur_afn,除非是第一个包
  990. NbRun.cur_afn = afn;
  991. }
  992. int8_t ret = 0;
  993. uint8_t need_reply = 0; // 标记是否需要发送应用层回复
  994. uint8_t update_status = 0;
  995. #ifdef DEBUG_NB
  996. LOG("Rec OK, AFN=0x%04X, Len=%d\r\n", afn, data_len);
  997. #endif
  998. // --- 业务逻辑分发 ---
  999. switch (afn)
  1000. {
  1001. case 0x20: // Set IP/Port
  1002. if (data_len != 16)
  1003. return 1;
  1004. ret = set_server_ip_port_para((SERVER_IP_PORT_DEF *)&NbAppFrame.data[4]);
  1005. nb_set_ip_para_ack();
  1006. need_reply = 1;
  1007. break;
  1008. case 0x21: // Set Regular Report
  1009. if (data_len != 9)
  1010. return 1;
  1011. {
  1012. REGULAR_REPORT_DEF dat;
  1013. dat.report_base_hour = NbAppFrame.data[4];
  1014. dat.report_base_min = NbAppFrame.data[5];
  1015. dat.report_base_sec = NbAppFrame.data[6];
  1016. dat.report_interval = NbAppFrame.data[7] + 256 * NbAppFrame.data[8];
  1017. ret = set_regular_report_para(&dat);
  1018. }
  1019. nb_set_regular_report_para_ack(ret == 0 ? 1 : ret);
  1020. need_reply = 1;
  1021. break;
  1022. case 0x22: // Set DMA Report
  1023. if (data_len != 11)
  1024. return 1;
  1025. {
  1026. DMA_REGULAR_REPORT_DEF dat;
  1027. dat.dma_report_start_hour = NbAppFrame.data[4];
  1028. dat.dma_report_start_min = NbAppFrame.data[5];
  1029. dat.dma_report_start_sec = NbAppFrame.data[6];
  1030. dat.dma_report_end_hour = NbAppFrame.data[7];
  1031. dat.dma_report_end_min = NbAppFrame.data[8];
  1032. dat.dma_report_end_sec = NbAppFrame.data[9];
  1033. dat.dma_interval = NbAppFrame.data[10];
  1034. ret = set_dma_regular_report_para(&dat);
  1035. }
  1036. nb_set_dma_report_para_ack(ret == 0 ? 1 : ret);
  1037. need_reply = 1;
  1038. break;
  1039. case 0x23: // Set RTC
  1040. if (data_len != 11)
  1041. return 1;
  1042. {
  1043. tm_t tm;
  1044. // tm.year = ((NbAppFrame.data[4] << 8) | NbAppFrame.data[5]) % 2000;
  1045. tm.year = NbAppFrame.data[5];
  1046. tm.month = NbAppFrame.data[6];
  1047. tm.day = NbAppFrame.data[7];
  1048. tm.hour = NbAppFrame.data[8];
  1049. tm.min = NbAppFrame.data[9];
  1050. tm.sec = NbAppFrame.data[10];
  1051. ret = SetRtcTime(&tm);
  1052. }
  1053. save_cur_flow_flag = 1;
  1054. nb_set_rtc_data_ack(ret);
  1055. need_reply = 1;
  1056. break;
  1057. case 0x24: // Set Flow Alarm
  1058. if (data_len != 18)
  1059. return 1;
  1060. {
  1061. FLOW_ALARM_PARA_DEF flow_alarm_para;
  1062. flow_alarm_para.large_flow_alarm_thres = (NbAppFrame.data[7] << 24) | (NbAppFrame.data[6] << 16) | (NbAppFrame.data[5] << 8) | NbAppFrame.data[4];
  1063. flow_alarm_para.large_flow_cnti_moni_time = (NbAppFrame.data[9] << 8) | NbAppFrame.data[8];
  1064. flow_alarm_para.cnti_flow_cnti_moni_time = (NbAppFrame.data[11] << 8) | NbAppFrame.data[10];
  1065. flow_alarm_para.leak_flow_alarm_thres = (NbAppFrame.data[15] << 24) | (NbAppFrame.data[14] << 16) | (NbAppFrame.data[13] << 8) | NbAppFrame.data[12];
  1066. flow_alarm_para.leak_flow_cnti_moni_time = (NbAppFrame.data[17] << 8) | NbAppFrame.data[16];
  1067. ret = set_flow_alarm_para(&flow_alarm_para);
  1068. }
  1069. nb_set_flow_alarm_para_ack(ret == 0 ? 1 : ret);
  1070. need_reply = 1;
  1071. break;
  1072. case 0x25: // Set Press Alarm
  1073. if (data_len != 6)
  1074. return 1;
  1075. ret = set_press_alarm_para((PRESS_ALARM_PARA_DEF *)&NbAppFrame.data[4]);
  1076. nb_set_pressure_alarm_para_ack(ret == 0 ? 1 : ret);
  1077. need_reply = 1;
  1078. break;
  1079. case 0x26: // Set Temp Alarm
  1080. if (data_len != 8)
  1081. return 1;
  1082. ret = set_temp_alarm_para((TEMP_ALARM_PARA_DEF *)&NbAppFrame.data[4]);
  1083. nb_set_temp_alarm_para_ack(ret == 0 ? 1 : ret);
  1084. need_reply = 1;
  1085. break;
  1086. case 0x27: // Set Settlement Day
  1087. if (data_len != 5)
  1088. return 1;
  1089. ret = set_settlement_day_para((SETTLEMENT_DAY_DEF *)&NbAppFrame.data[4]);
  1090. nb_set_settlment_day_para_ack(ret == 0 ? 1 : ret);
  1091. need_reply = 1;
  1092. break;
  1093. case 0x28: // Set Bottom Data
  1094. if (data_len != 12)
  1095. return 1;
  1096. ret = set_meter_bottom_data((METER_BOTTOM_DEF *)&NbAppFrame.data[4]);
  1097. nb_set_meter_bottom_data_ack(ret == 0 ? 1 : ret);
  1098. need_reply = 1;
  1099. break;
  1100. case 0x30: // Read Month Record
  1101. nb_read_month_record_ack();
  1102. need_reply = 1;
  1103. break;
  1104. case 0x32: // Read Day Record
  1105. nb_read_day_record_ack();
  1106. need_reply = 1;
  1107. break;
  1108. case 0x34: // Read Hour Record
  1109. // 注意:nb_read_hour_record_ack 内部已经完成了所有分包发送和 AT 交互
  1110. ret = nb_read_hour_record_ack();
  1111. if (ret == -1)
  1112. {
  1113. LOG("Read Hour Err\r\n");
  1114. return -1; // 严重错误,退出上传会话
  1115. }
  1116. // 内部已处理完毕,不需要再执行底部的通用回复逻辑
  1117. return 0;
  1118. case 0x36: // Read 5Min Record
  1119. ret = nb_read_5min_record_ack();
  1120. if (ret == -1)
  1121. {
  1122. LOG("Read 5Min Err\r\n");
  1123. return -1;
  1124. }
  1125. // 内部已处理完毕
  1126. return 0;
  1127. case 0x38: // Read Log
  1128. nb_read_log_record_ack();
  1129. need_reply = 1;
  1130. break;
  1131. case 0x40: // Close Link
  1132. LOG("Close Link\r\n");
  1133. return 2; // 特殊返回码,指示关闭链接
  1134. case 0x50: // OTA Start
  1135. if (data_len != 22)
  1136. return 1;
  1137. ret = nb_set_patch_info();
  1138. if (ret != 1)
  1139. {
  1140. nb_set_patch_info_ack(ret);
  1141. need_reply = 1;
  1142. }
  1143. else
  1144. {
  1145. NbRun.mid = (NbAppFrame.data[3] << 8) | NbAppFrame.data[2];
  1146. nb_set_patch_info_ack(0x10); // Request first package
  1147. need_reply = 1;
  1148. }
  1149. NbRun.get_patch_retry_cnt = 0;
  1150. break;
  1151. case 0x51: // OTA Data Package
  1152. // 检查数据长度是否匹配预期
  1153. if (data_len != (8 + PatchInfo.per_packet_len))
  1154. {
  1155. update_status = 0x20; // Resend request
  1156. }
  1157. else
  1158. {
  1159. DIFF_PACKET_DEF *dat = (DIFF_PACKET_DEF *)&NbAppFrame.data[4];
  1160. ret = write_diff_patch_to_flash(dat);
  1161. if (ret == 1)
  1162. { // Success
  1163. NbRun.get_patch_retry_cnt = 0;
  1164. if (PatchInfo.update_status == 1)
  1165. {
  1166. update_status = 0x10; // Request next
  1167. }
  1168. else
  1169. {
  1170. update_status = 1; // Finish
  1171. }
  1172. }
  1173. else
  1174. {
  1175. update_status = ret; // Error code
  1176. }
  1177. }
  1178. // 重试计数逻辑
  1179. if (update_status == 0x10 || update_status == 1)
  1180. {
  1181. NbRun.get_patch_retry_cnt = 0;
  1182. }
  1183. else
  1184. {
  1185. NbRun.get_patch_retry_cnt++;
  1186. }
  1187. if (NbRun.get_patch_retry_cnt > 20)
  1188. {
  1189. update_status = 3; // Fail
  1190. }
  1191. if (update_status <= 3)
  1192. {
  1193. NbRun.cur_afn = 0; // Reset AFN after handling packet
  1194. }
  1195. nb_set_patch_info_ack(update_status);
  1196. need_reply = 1;
  1197. if (update_status >= 1 && update_status <= 6)
  1198. {
  1199. // OTA finished or failed, will return 2 later
  1200. }
  1201. break;
  1202. default:
  1203. LOG("Unknown AFN: 0x%04X\r\n", afn);
  1204. return 1; // Ignore unknown, wait for next
  1205. }
  1206. // --- 发送应用层回复 ---
  1207. if (need_reply == 1)
  1208. {
  1209. uint16_t len = ((NbAppFrame.len[1] << 8) | NbAppFrame.len[0]) + 16;
  1210. nb_send_data_route((uint8_t *)&NbAppFrame, len);
  1211. // 发送 AT 指令并将数据发往网络
  1212. ret = at_cmd_send(55, (char *)NbRun.tx_buf, NB_AT_ACK, 6, 5);
  1213. if (ret == -1)
  1214. {
  1215. return -1; // Send failed
  1216. }
  1217. // 如果是 OTA 结束状态,返回 2 以退出循环
  1218. if (afn == 0x51 && (update_status >= 1 && update_status <= 6))
  1219. {
  1220. return 2;
  1221. }
  1222. return 0; // Success
  1223. }
  1224. return 1; // Should not reach here if logic is correct
  1225. }
  1226. void rtc_add_secs(TIME_DEF *dest, rtc_run_t *src, unsigned short secs)
  1227. {
  1228. unsigned short dat;
  1229. // dat=secs;
  1230. dest->second = (src->second + dat) % 60;
  1231. dat = (src->second + dat) / 60;
  1232. dest->minute = (src->minute + dat) % 60;
  1233. dat = (src->minute + dat) / 60;
  1234. dest->hour = (dat + src->hour) % 24;
  1235. }
  1236. int8_t connected_flag;
  1237. void NbTread(void)
  1238. {
  1239. uint32_t retry_time;
  1240. uint8_t vflag = 0;
  1241. uint16_t len;
  1242. uint8_t ncnt;
  1243. char ncdp_str[64];
  1244. uint8_t npos;
  1245. //////////////读取ID等初始化流程/////////////////////////////////////////
  1246. G_NB_CAN_DEEP_SLEEP = 0; // 不允许休眠
  1247. nb_power_on(0);
  1248. rt_thread_mdelay(2000);
  1249. do
  1250. {
  1251. npos = 0;
  1252. if (at_cmd_send(npos++, NB_AT, NB_AT_ACK, 10, 2) == -1)
  1253. break; //
  1254. if (at_cmd_send(npos++, NB_ATE0, NB_ATE0_ACK, 3, 2) == -1) // 关闭回显
  1255. break;
  1256. /////////////设置频段//////////////////////////
  1257. if(Paramx.nb_band_flag!=0)
  1258. {if (at_cmd_send(npos++, "AT+QCFG=\"band\",0,0x10,0,1\r\n", NB_AT_ACK, 3, 5) == -1)
  1259. break;
  1260. set_nb_band();
  1261. if (at_cmd_send(1, NB_CFUN0, NB_AT_ACK, 3, 3) == -1)
  1262. break;
  1263. rt_thread_mdelay(1000);
  1264. if (at_cmd_send(1, NB_CFUN1, NB_AT_ACK, 3, 3) == -1)
  1265. break;
  1266. rt_thread_mdelay(1200);
  1267. }
  1268. //////////////////////////////////////////
  1269. // if (at_cmd_send(1, NB_CFUN0, NB_AT_ACK, 3, 2) == -1)
  1270. // break;
  1271. // rt_thread_mdelay(1000);
  1272. // if (at_cmd_send(1, NB_CFUN1, NB_AT_ACK, 3, 3) == -1)
  1273. // break;
  1274. // rt_thread_mdelay(1200);
  1275. if (at_cmd_send(npos++, NB_CGSN, NB_CGSN_ACK, 3, 2) == -1)
  1276. break;
  1277. get_nb_imei_code();
  1278. if (at_cmd_send(npos++, NB_CIMI, NB_AT_ACK, 3, 2) == -1)
  1279. break;
  1280. get_nb_imsi_code();
  1281. if (at_cmd_send(npos++, NB_NCCID, NB_NCCID_ACK, 3, 2) == -1) // different from BC28
  1282. break;
  1283. get_nb_ccid_code();
  1284. } while (0);
  1285. nb_power_off();
  1286. //////////////////////////////////////////////////////////////////
  1287. // G_NB_CAN_DEEP_SLEEP = 1;//允许休眠
  1288. while (1)
  1289. {
  1290. G_NB_CAN_DEEP_SLEEP = 1; // 允许休眠
  1291. rt_sem_take(Nb_thread_run_sem, RT_WAITING_FOREVER); // 等信号量
  1292. npos = 0;
  1293. // #ifdef DEBUG_NB
  1294. #ifdef APP_DEBUG_PRINT
  1295. LOG("upload_begin type: %s\r\n", get_upload_type_str(NbRun.upload.mode));
  1296. if (NbRun.upload.mode & 0x10)
  1297. LOG("error_code = %X\r\n", upload_dat.err_mem_dat);
  1298. #endif
  1299. // #endif
  1300. // 既不是定时上报,也不是重复上报,并且没有子服务,也没有主服务,则跳过
  1301. if ((NbRun.upload.mode & (NB_UPLOAD_TIMER | NB_UPLOAD_REPT)) == 0 && check_sub_service_flag() == 0 && check_main_service_flag() == 0)
  1302. {
  1303. NbRun.upload.flag = 0;
  1304. NbRun.upload.mode = 0; // 本次上传结束后清零
  1305. LOG("no service upload!\r\n");
  1306. continue;
  1307. }
  1308. G_NB_CAN_DEEP_SLEEP = 0; // 不允许休眠
  1309. nb_power_on(0);
  1310. rt_thread_mdelay(1000);
  1311. do
  1312. {
  1313. if (at_cmd_send(npos++, NB_AT, NB_AT_ACK, 10, 2) == -1) // at测试
  1314. break;
  1315. if (at_cmd_send(npos++, NB_ATE0, NB_ATE0_ACK, 3, 2) == -1) // 关闭回显
  1316. break;
  1317. if (at_cmd_send(npos++, "AT+IPR=9600\r\n", NB_AT_ACK, 3, 2) == -1)
  1318. break;
  1319. nb_power_on(3);
  1320. rt_thread_mdelay(500);
  1321. if (NbRun.get_imei_flag == 0) // 读取imei号
  1322. { // 读取IMEI号
  1323. if (at_cmd_send(npos++, NB_CGSN, NB_CGSN_ACK, 3, 2) == -1)
  1324. break;
  1325. get_nb_imei_code();
  1326. }
  1327. npos = 5;
  1328. if (at_cmd_send(npos++, NB_CMEE1, NB_CMEE_ACK, 3, 2) == -1) // 错误上报方式 BC800需要
  1329. break;
  1330. retry_time = 0;
  1331. vflag = 1;
  1332. while (at_cmd_send(npos, "AT+CPIN?\r\n", "+CPIN: READY", 3, 3) == -1)
  1333. {
  1334. retry_time++;
  1335. if (retry_time > 3)
  1336. {
  1337. vflag = 0;
  1338. break;
  1339. }
  1340. if (at_cmd_send(npos + 1, NB_CFUN0, NB_AT_ACK, 3, 2) == -1)
  1341. {
  1342. vflag = 0;
  1343. break;
  1344. } // FUN0格式
  1345. rt_thread_mdelay(1000);
  1346. if (at_cmd_send(npos + 2, NB_CFUN1, NB_AT_ACK, 3, 3) == -1) // 设置最大模式,开始搜网
  1347. {
  1348. vflag = 0;
  1349. break;
  1350. }
  1351. rt_thread_mdelay(1200);
  1352. }
  1353. npos += 3;
  1354. if (vflag == 0)
  1355. break;
  1356. if (NbRun.get_ccid_flag == 0) // 读取ccid号
  1357. { // 读取ccid号
  1358. ncnt = 0;
  1359. if (at_cmd_send(npos, NB_NCCID, NB_NCCID_ACK, 3, 2) == -1)
  1360. {
  1361. break;
  1362. }
  1363. get_nb_ccid_code();
  1364. }
  1365. npos++;
  1366. if (NbRun.get_imsi_flag == 0) // 读取imsi号
  1367. { // 读取imsi号
  1368. if (at_cmd_send(npos, NB_CIMI, NB_AT_ACK, 3, 2) == -1)
  1369. break;
  1370. get_nb_imsi_code();
  1371. }
  1372. npos++;
  1373. if (at_cmd_send(npos++, "AT+COPS=0\r\n", NB_AT_ACK, 3, 2) == -1) // 自动选择网络
  1374. break;
  1375. rt_thread_mdelay(500);
  1376. retry_time = 0;
  1377. while (1)
  1378. { // 内循环判断
  1379. if (retry_time >= 3) // 已经3个循环结束
  1380. {
  1381. vflag = 0;
  1382. break;
  1383. }
  1384. else if (retry_time != 0) // 首次进入不复位
  1385. {
  1386. if (at_cmd_send(npos, NB_CFUN0, NB_AT_ACK, 3, 2) == -1)
  1387. break; // FUN0格式
  1388. rt_thread_mdelay(1000);
  1389. if (at_cmd_send(npos + 1, NB_CFUN1, NB_AT_ACK, 3, 3) == -1) // 设置最大模式,开始搜网
  1390. break;
  1391. rt_thread_mdelay(1200);
  1392. }
  1393. if (at_cmd_send2(npos + 2, "AT+CEREG?\r\n", "+CEREG: 0,1", "+CREG: 0,5", 30, 2) == -1) // 查询网络注册状态TT_ACK, 3, 2) == -1) // PS域附着
  1394. {
  1395. retry_time++; // 重试次数
  1396. continue;
  1397. } // 状态值1/5都属于正常
  1398. if (at_cmd_send(npos + 3, NB_CGATT, NB_CGATT_ACK, 3, 2) == -1) // PS域附着
  1399. break;
  1400. // retry_time = 0;
  1401. if (at_cmd_send(npos + 4, NB_CGATT_QUERY, NB_CGATT_QUERY_ACK, 20, 2) == -1)
  1402. { // 查询附着状态
  1403. retry_time++; // 重试次数
  1404. continue; // 重新注册
  1405. }
  1406. vflag = 1;
  1407. break;
  1408. }
  1409. npos += 5;
  1410. if (vflag == 0)
  1411. break; // 失败后退出的循环
  1412. vflag = 0;
  1413. // if (at_cmd_send(14, NB_CSQ, NB_CSQ_ACK, 3, 2) == -1) // 查询无线信号强度 BC800有
  1414. // break;
  1415. // get_nb_csq();
  1416. ncnt = 5;
  1417. vflag = 1;
  1418. while (ncnt--) // 查询无线信号强度 BC800有
  1419. {
  1420. if (at_cmd_send(npos++, "AT+QENG=\"servingcell\"\r\n", "+QENG: \"servingcell\"", 3, 2) == -1)
  1421. {
  1422. vflag = 0;
  1423. break;
  1424. }
  1425. if (get_nb_signal(NbRun.rx_buf, NbRun.rx_idx) == 1)
  1426. break;
  1427. rt_thread_mdelay(1000);
  1428. }
  1429. if (vflag == 0)
  1430. break;
  1431. vflag = 0;
  1432. if (at_cmd_send(npos++, "AT+QICSGP=1,1,\"CTNET\",\"\",\"\",1\r\n", NB_AT_ACK, 3, 2) == -1) // 配置场景
  1433. break;
  1434. if (at_cmd_send(npos++, "AT+QIACT=1\r\n", NB_AT_ACK, 3, 3) == -1) // 激活场景
  1435. break;
  1436. if (at_cmd_send(npos++, "AT+QIACT?\r\n", "+QIACT: 1,1", 3, 3) == -1) // 查询场景激活状态
  1437. break;
  1438. if ((NbRun.upload.mode & NB_UPLOAD_TIMER) != 0)
  1439. {
  1440. if (at_cmd_send(npos, "AT+QNTP=1,\"202.112.10.36\",123\r\n", "+QNTP: 0,", 1, 15) == 0)
  1441. {
  1442. save_datetime_from_at(NbRun.rx_buf, NbRun.rx_idx);
  1443. LOG("get net time!\t\n");
  1444. }
  1445. }
  1446. npos++;
  1447. int16_t link_code;
  1448. vflag = 0x80;
  1449. //////////////////////////////////tcp主连接与发送数据////////////////////////////////////////
  1450. if (((upload_dat.rept_addr & BIT0) != 0 || NbRun.upload.mode != NB_UPLOAD_REPT) && check_main_service_flag() == 1)
  1451. {
  1452. vflag &= 0x0f;
  1453. do
  1454. {
  1455. #ifdef APP_DEBUG_PRINT
  1456. LOG("main service upload\r\n");
  1457. #endif
  1458. vflag = 0;
  1459. sprintf(ncdp_str, "AT+QIOPEN=1,0,\"TCP\",\"%d.%d.%d.%d\",%d,0,0\r\n", // 倒数第二个0:本地ip自动 最后一个0: 缓存模式
  1460. Paramx.main_server_ip[0],
  1461. Paramx.main_server_ip[1],
  1462. Paramx.main_server_ip[2],
  1463. Paramx.main_server_ip[3],
  1464. Paramx.main_server_port);
  1465. if (at_cmd_send(npos, ncdp_str, "+QIOPEN: 0,", 2, 10) == -1) // 建立TCP连接,等待连接成功
  1466. break;
  1467. if (get_code(NbRun.rx_buf, "+QIOPEN: 0,", NbRun.rx_idx, &link_code) == -1)
  1468. break;
  1469. if (link_code != 0)
  1470. break;
  1471. // 发送数据,等待接收指令,收到指令后执行,超时退出
  1472. nb_upload_data_ready();
  1473. rt_thread_mdelay(100); // 准备上报数据
  1474. if (at_cmd_send(npos + 1, (char *)NbRun.tx_buf, "SEND OK", 3, 3) == -1) // 发送上报数据
  1475. break;
  1476. vflag = 1; // 上报成功标志
  1477. int8_t ret;
  1478. retry_time = 50; // 12秒
  1479. NbRun.cur_afn = 0;
  1480. //////////////////////////////////////
  1481. while (retry_time--)
  1482. {
  1483. ret = rec_data_check();
  1484. rt_thread_mdelay(100);
  1485. if (ret == 0)
  1486. retry_time = 150; // 判断接收数据是否合法,以及读取协议层afn和长度,并回复
  1487. else if (ret == -1 || ret == 2)
  1488. break;
  1489. }
  1490. } while (0);
  1491. at_cmd_send(npos + 2, "AT+QICLOSE=0\r\n", NB_AT_ACK, 3, 3); // 关闭tcpLINK
  1492. }
  1493. npos += 3;
  1494. ////////////////////////////备用连接/////////////////////////////////////////////////////
  1495. if (((upload_dat.rept_addr & BIT1) != 0 || NbRun.upload.mode != NB_UPLOAD_REPT) && check_sub_service_flag() == 1)
  1496. {
  1497. vflag &= 0x0f;
  1498. do
  1499. {
  1500. #ifdef APP_DEBUG_PRINT
  1501. LOG("sub service upload\r\n");
  1502. #endif
  1503. sprintf(ncdp_str, "AT+QIOPEN=1,0,\"TCP\",\"%d.%d.%d.%d\",%d,0,0\r\n", // 倒数第二个0:本地ip自动 最后一个0: 缓存模式
  1504. Paramx.sub_server_ip[0],
  1505. Paramx.sub_server_ip[1],
  1506. Paramx.sub_server_ip[2],
  1507. Paramx.sub_server_ip[3],
  1508. Paramx.sub_server_port);
  1509. if (at_cmd_send(npos, ncdp_str, "+QIOPEN: 0,", 2, 10) == -1) // 建立TCP连接,等待连接成功
  1510. break;
  1511. if (get_code(NbRun.rx_buf, "+QIOPEN: 0,", NbRun.rx_idx, &link_code) == -1)
  1512. break;
  1513. if (link_code != 0)
  1514. break;
  1515. // 发送数据,等待接收指令,收到指令后执行,超时退出
  1516. nb_upload_data_ready();
  1517. rt_thread_mdelay(100); // 准备上报数据
  1518. if (at_cmd_send(npos + 1, (char *)NbRun.tx_buf, "SEND OK", 3, 3) == -1) // 发送上报数据
  1519. break;
  1520. vflag |= 2; // 上报成功标志
  1521. int8_t ret;
  1522. retry_time = 50; // 12秒
  1523. NbRun.cur_afn = 0;
  1524. //////////////////////////////////////
  1525. while (retry_time--)
  1526. {
  1527. ret = rec_data_check();
  1528. rt_thread_mdelay(100);
  1529. if (ret == 0)
  1530. retry_time = 50; // 判断接收数据是否合法,以及读取协议层afn和长度,并回复
  1531. else if (ret == -1 || ret == 2)
  1532. break;
  1533. }
  1534. } while (0);
  1535. at_cmd_send(npos + 2, "AT+QICLOSE=0\r\n", NB_AT_ACK, 3, 2); // 关闭tcpLINK
  1536. }
  1537. } while (0); // 主循环
  1538. // NB_RUN_UPDATE_FLAG = 0;
  1539. nb_power_off();
  1540. if (vflag & 0x80)
  1541. LOG("no service upload!\r\n");
  1542. else if ((vflag & 3) != 0)
  1543. {
  1544. if ((vflag & BIT0) != 0)
  1545. LOG("MAIN upload ok!\r\n");
  1546. if ((vflag & BIT1) != 0)
  1547. LOG("SUB upload ok!\r\n");
  1548. }
  1549. else if (vflag == 0)
  1550. LOG("upload fail\r\n");
  1551. if ((vflag & 3) != 3 && vflag != 0x80) // 有失败的情况
  1552. { // 上报失败,补报判别
  1553. if (NbRun.upload.mode & ~(NB_UPLOAD_REPT | NB_UPLOAD_DMA | NB_UPLOAD_MANUAL))
  1554. { // 除补报,DMA,手动上报之外,其他需要补报
  1555. upload_dat.rept_runflag = ((~vflag) & 0x3); // 补报
  1556. upload_dat.rept_addr = upload_dat.rept_runflag;
  1557. rtc_run_t *rr;
  1558. get_rtc_run(&rr);
  1559. tm_t ntm;
  1560. ntm.year = rr->year;
  1561. ntm.month = rr->month;
  1562. ntm.day = rr->day;
  1563. ntm.hour = rr->hour;
  1564. ntm.min = rr->minute;
  1565. ntm.sec = rr->second;
  1566. time_add_secs(&upload_dat.rept_time, &ntm, 3600);
  1567. }
  1568. }
  1569. // NbRun.void_load_timout = NB_VOID_UPLOAD_TIME;//这段时间不能上报60s
  1570. NbRun.upload.flag = 0;
  1571. NbRun.upload.mode = 0; // 本次上传结束后清零
  1572. } // while(1)
  1573. }
  1574. /////////////添加上报过程中动态显示信号/////////////////////
  1575. ////////////////////发送at指令并等待处理接收数据//////////////////////////////////////////////////////
  1576. // stat:当前所在流程位置,和每个指令一一对应
  1577. // cmd_str:at指令字符串
  1578. // ack:要求本次回复的字符串
  1579. // retry_time: 重试次数
  1580. // time_out: 超时时间 秒单位
  1581. // 成功:返回0 失败返回-1
  1582. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  1583. int8_t at_cmd_send(uint8_t stat, char *cmd_str, char *ack, uint16_t retry_time, uint8_t time_out)
  1584. {
  1585. uint16_t retry = retry_time;
  1586. uint16_t time_cnt;
  1587. int8_t ret = 0;
  1588. NbRun.cur_state = stat;
  1589. NbRun.ack = ack;
  1590. if (time_out > 250)
  1591. time_out = 250; // 最大不超过25秒
  1592. time_cnt = time_out * 10;
  1593. ////////////
  1594. // retry=250;
  1595. //////////////
  1596. // LOG("nbstat=%d\r\n",stat);
  1597. while (retry--)
  1598. {
  1599. NbClrRxBuf();
  1600. time_cnt = time_out * 10;
  1601. nb_tx_str(cmd_str);
  1602. while (--time_cnt)
  1603. {
  1604. if (Nb_rx_data() == 1)
  1605. {
  1606. // if (stat > COAP_CGATT_QUERY && stat < COAP_WAIT_REG)//EC800 不再需要了
  1607. // {
  1608. // if (memstr_exist(NbRun.rx_buf, NbRun.rx_idx, "+QLWEVTIND:3", 12) == 1)
  1609. // {
  1610. // connected_flag = 1;
  1611. // }
  1612. // }
  1613. //////////////////////////////////////////////
  1614. ret = Nb_check_rec_valid(stat, ack);
  1615. if (ret == 1)
  1616. {
  1617. LOG(".");
  1618. return 0;
  1619. } // 收到正确的回复}
  1620. else if (ret == -1)
  1621. break;
  1622. // else if(ret == 0)continue;
  1623. }
  1624. rt_thread_mdelay(NB_REC_DELAY_TICK); // 等100ms
  1625. }
  1626. if (time_cnt == 0)
  1627. { // 超时未收到数据
  1628. continue;
  1629. }
  1630. if (Nb_check_rec_valid(stat, ack) == TRUE)
  1631. { // 检查是否收到正确回复
  1632. return 0;
  1633. }
  1634. }
  1635. return -1;
  1636. }
  1637. int8_t at_cmd_send2(uint8_t stat, char *cmd_str, char *ack1, char *ack2, uint16_t retry_time, uint8_t time_out)
  1638. {
  1639. uint16_t retry = retry_time;
  1640. uint16_t time_cnt;
  1641. int8_t ret1, ret2;
  1642. NbRun.cur_state = stat;
  1643. NbRun.ack = ack1;
  1644. if (time_out > 250)
  1645. time_out = 250; // 最大不超过25秒
  1646. time_cnt = time_out * 10;
  1647. ////////////
  1648. // retry=250;
  1649. //////////////
  1650. // LOG("nbstat=%d\r\n",stat);
  1651. while (retry--)
  1652. {
  1653. NbClrRxBuf();
  1654. time_cnt = time_out * 10;
  1655. nb_tx_str(cmd_str);
  1656. while (--time_cnt)
  1657. {
  1658. if (Nb_rx_data() == 1)
  1659. {
  1660. ret1 = Nb_check_rec_valid(stat, ack1);
  1661. if (ret1 == 1)
  1662. {
  1663. LOG(".");
  1664. return 0;
  1665. } // 收到正确的回复}
  1666. ret2 = Nb_check_rec_valid(stat, ack2);
  1667. if (ret2 == 1)
  1668. {
  1669. LOG(".");
  1670. return 0;
  1671. } // 收到正确的回复
  1672. if (ret1 == -1 || ret2 == -1)
  1673. break;
  1674. // else if(ret == 0)continue;
  1675. }
  1676. rt_thread_mdelay(NB_REC_DELAY_TICK); // 等100ms
  1677. }
  1678. if (time_cnt == 0)
  1679. { // 超时未收到数据
  1680. continue;
  1681. }
  1682. if (Nb_check_rec_valid(stat, ack1) == TRUE)
  1683. { // 检查是否收到正确回复
  1684. return 0;
  1685. }
  1686. if (Nb_check_rec_valid(stat, ack2) == TRUE)
  1687. { // 检查是否收到正确回复
  1688. return 0;
  1689. }
  1690. }
  1691. return -1;
  1692. }
  1693. static void BuildDataReportMeter(rtc_run_t *rr, uint8_t *data)
  1694. {
  1695. rtc_run_t *max_fr_rr;
  1696. // total positive water
  1697. uint32_t temp = (uint32_t)(FwCumFlow * 0.0001 + 0.5); // unit: 0.01m^3
  1698. data[0] = (uint8_t)temp;
  1699. data[1] = (uint8_t)(temp >> 8);
  1700. data[2] = (uint8_t)(temp >> 16);
  1701. data[3] = (uint8_t)(temp >> 24);
  1702. // total reverse water
  1703. temp = (uint32_t)(BwCumFlow * 0.0001 + 0.5); // unit: 0.01m^3
  1704. data[4] = (uint8_t)temp;
  1705. data[5] = (uint8_t)(temp >> 8);
  1706. data[6] = (uint8_t)(temp >> 16);
  1707. data[7] = (uint8_t)(temp >> 24);
  1708. // Daily maximum flow rate
  1709. temp = (uint32_t)(get_max_flow_rate() * 1000); // 3位小数点
  1710. #ifdef DEBUG_NB
  1711. // temp = 12345;
  1712. #endif
  1713. data[8] = (uint8_t)(temp);
  1714. data[9] = (uint8_t)(temp >> 8);
  1715. data[10] = (uint8_t)(temp >> 16);
  1716. data[11] = (uint8_t)(temp >> 24);
  1717. // Daily maximum flow rate time
  1718. get_max_flow_rate_time(&max_fr_rr);
  1719. if (max_fr_rr == NULL || max_fr_rr->year == 0 || max_fr_rr->month == 0 || max_fr_rr->day == 0)
  1720. memset(&data[12], 0, 7);
  1721. else
  1722. {
  1723. data[12] = 0x14;
  1724. data[13] = max_fr_rr->year;
  1725. data[14] = max_fr_rr->month;
  1726. data[15] = max_fr_rr->day;
  1727. data[16] = max_fr_rr->hour;
  1728. data[17] = max_fr_rr->minute;
  1729. data[18] = max_fr_rr->second;
  1730. }
  1731. #ifdef DEBUG_NB
  1732. // data[13] = 26;
  1733. // data[14] = 3;
  1734. // data[15] = 31;
  1735. // data[16] = 9;
  1736. // data[17] = 30;
  1737. // data[18] = 45;
  1738. #endif
  1739. // water temperature
  1740. if (WaterTemp > 100.0f || WaterTemp < 0.0f)
  1741. temp = -1;
  1742. else
  1743. temp = (uint32_t)(WaterTemp * 10 + 0.5);
  1744. #ifdef DEBUG_NB
  1745. // temp = -300;
  1746. #endif
  1747. data[19] = (uint8_t)(temp);
  1748. data[20] = (uint8_t)(temp >> 8);
  1749. // water pressure
  1750. if (Paramx.pressure_sensor == 1)
  1751. {
  1752. data[21] = (uint8_t)(WaterPressure * 100);
  1753. }
  1754. else
  1755. data[21] = 0x00; // 无压力传感器,修改为0
  1756. #ifdef DEBUG_NB
  1757. // data[21]=213;
  1758. #endif
  1759. // battery voltage unit: 0.1V
  1760. /* if (McuVbat > McuVTxbat)
  1761. { // 判断哪个电池低就上传哪个数据
  1762. temp = McuVTxbat / 100;
  1763. }
  1764. else
  1765. temp = McuVbat / 100;
  1766. */
  1767. temp = McuVbat / 100; // wxl2026-6-2
  1768. data[22] = (unsigned char)temp;
  1769. data[23] = 0x14;
  1770. data[24] = rr->year;
  1771. data[25] = rr->month;
  1772. data[26] = rr->day;
  1773. data[27] = rr->hour;
  1774. data[28] = rr->minute;
  1775. data[29] = rr->second;
  1776. }
  1777. static void BuildDataReportParam(uint8_t *data)
  1778. {
  1779. Param_t *param;
  1780. Nb_Run_t *nb_run;
  1781. GetParam(&param);
  1782. GetNbRun(&nb_run);
  1783. // version
  1784. data[0] = 'V';
  1785. data[1] = VER_TYPE;
  1786. data[2] = VER_OPERATOR;
  1787. data[3] = VER_MODULE;
  1788. data[4] = VER_FIRMWARE;
  1789. // diameter
  1790. data[5] = (unsigned char)(param->diameter);
  1791. data[6] = (unsigned char)(param->diameter >> 8);
  1792. // channel number
  1793. data[7] = param->chan_num;
  1794. // main server ip
  1795. data[8] = param->main_server_ip[0];
  1796. data[9] = param->main_server_ip[1];
  1797. data[10] = param->main_server_ip[2];
  1798. data[11] = param->main_server_ip[3];
  1799. // main server port
  1800. data[12] = (unsigned char)(param->main_server_port);
  1801. data[13] = (unsigned char)(param->main_server_port >> 8);
  1802. // sub server ip
  1803. data[14] = param->sub_server_ip[0];
  1804. data[15] = param->sub_server_ip[1];
  1805. data[16] = param->sub_server_ip[2];
  1806. data[17] = param->sub_server_ip[3];
  1807. // sub server port
  1808. data[18] = (unsigned char)(param->sub_server_port);
  1809. data[19] = (unsigned char)(param->sub_server_port >> 8);
  1810. // report base time
  1811. data[20] = param->report_base_hour;
  1812. data[21] = param->report_base_min;
  1813. data[22] = param->report_base_sec;
  1814. // report interval minutes
  1815. data[23] = (unsigned char)(param->report_interval);
  1816. data[24] = (unsigned char)(param->report_interval >> 8);
  1817. // DMA report start time
  1818. data[25] = param->dma_report_start[0];
  1819. data[26] = param->dma_report_start[1];
  1820. data[27] = param->dma_report_start[2];
  1821. // DMA report end time
  1822. data[28] = param->dma_report_end[0];
  1823. data[29] = param->dma_report_end[1];
  1824. data[30] = param->dma_report_end[2];
  1825. // DMA report interval time
  1826. data[31] = param->dma_interval;
  1827. // settlement day
  1828. data[32] = param->settlement_day;
  1829. // high temperature alarm threshold
  1830. data[33] = (unsigned char)(param->high_temp_alarm_thres);
  1831. data[34] = (unsigned char)(param->high_temp_alarm_thres >> 8);
  1832. // low temperature alarm threshold
  1833. data[35] = (unsigned char)(param->low_temp_alarm_thres);
  1834. data[36] = (unsigned char)(param->low_temp_alarm_thres >> 8);
  1835. // large flow alarm threshold
  1836. data[37] = (unsigned char)(param->large_flow_alarm_thres);
  1837. data[38] = (unsigned char)(param->large_flow_alarm_thres >> 8);
  1838. data[39] = (unsigned char)(param->large_flow_alarm_thres >> 16);
  1839. data[40] = (unsigned char)(param->large_flow_alarm_thres >> 24);
  1840. // large flow continue monitor time
  1841. data[41] = (unsigned char)(param->large_flow_cnti_moni_time);
  1842. data[42] = (unsigned char)(param->large_flow_cnti_moni_time >> 8);
  1843. // continue flow continue monitor time
  1844. data[43] = (unsigned char)(param->cnti_flow_cnti_moni_time);
  1845. data[44] = (unsigned char)(param->cnti_flow_cnti_moni_time >> 8);
  1846. // leak flow alarm threshold
  1847. data[45] = (unsigned char)(param->leak_flow_alarm_thres);
  1848. data[46] = (unsigned char)(param->leak_flow_alarm_thres >> 8);
  1849. data[47] = (unsigned char)(param->leak_flow_alarm_thres >> 16);
  1850. data[48] = (unsigned char)(param->leak_flow_alarm_thres >> 24);
  1851. // leak flow continue monitor time
  1852. data[49] = (unsigned char)(param->leak_flow_cnti_moni_time);
  1853. data[50] = (unsigned char)(param->leak_flow_cnti_moni_time >> 8);
  1854. // high press alarm threshold
  1855. data[51] = (unsigned char)(param->high_press_alarm_thres);
  1856. // low press alarm threshold
  1857. data[52] = (unsigned char)(param->low_press_alarm_thres);
  1858. // pressure sensor
  1859. data[53] = param->pressure_sensor;
  1860. }
  1861. static void BuildDataReportNb(uint8_t *data)
  1862. {
  1863. Nb_Run_t *nb_run;
  1864. char tmp[3];
  1865. uint16_t i;
  1866. GetNbRun(&nb_run);
  1867. // IMEI len = 8
  1868. if (strlen(nb_run->imei) == 15)
  1869. {
  1870. tmp[0] = '0';
  1871. tmp[1] = nb_run->imei[0];
  1872. tmp[2] = 0;
  1873. StrToHexBuf((char *)&data[0], tmp, 2);
  1874. StrToHexBuf((char *)&data[1], &(nb_run->imei[1]), 14);
  1875. }
  1876. else
  1877. {
  1878. StrToHexBuf((char *)&data[0], tmp, 16);
  1879. }
  1880. // cell id in AT+NUESTATS response
  1881. data[8] = (unsigned char)(nb_run->bts_id);
  1882. data[9] = (unsigned char)(nb_run->bts_id >> 8);
  1883. data[10] = 0x00;
  1884. data[11] = 0x00;
  1885. // physical cell id
  1886. data[12] = (unsigned char)(nb_run->physical_cell_id);
  1887. data[13] = (unsigned char)(nb_run->physical_cell_id >> 8);
  1888. // rsrp
  1889. data[14] = (unsigned char)(nb_run->rsrp);
  1890. data[15] = (unsigned char)(nb_run->rsrp >> 8);
  1891. // snr
  1892. data[16] = (unsigned char)(nb_run->snr);
  1893. data[17] = (unsigned char)(nb_run->snr >> 8);
  1894. // csq
  1895. data[18] = nb_run->rssi;
  1896. // iccid len = 10
  1897. for (i = 0; i < 10; i++)
  1898. { // 这里是不是错了
  1899. data[19 + i] = (unsigned char)(((nb_run->ccid[2 * i] - '0') << 4) | (nb_run->ccid[2 * i + 1] - '0'));
  1900. }
  1901. }
  1902. static void BuildMonthRecord(rtc_run_t *rr, uint8_t *data)
  1903. {
  1904. uint32_t date = ((rr->year << 16) | (rr->month << 8));
  1905. uint16_t i;
  1906. bill_t bill;
  1907. uint8_t vflag;
  1908. for (i = 0; i < 2; i++)
  1909. {
  1910. date = prev_month(date);
  1911. vflag = read_month_bill((uint8_t)(date >> 16), (uint8_t)(date >> 8), &bill);
  1912. if (vflag != 0)
  1913. continue; // no data
  1914. if (bill.date[0] != (uint8_t)(date >> 16) || bill.date[1] != (uint8_t)(date >> 8))
  1915. continue; // 不是当月数据
  1916. data[i * 11] = 0x14;
  1917. data[i * 11 + 1] = bill.date[0];
  1918. data[i * 11 + 2] = bill.date[1];
  1919. data[i * 11] = 0x14;
  1920. data[i * 11 + 1] = bill.date[0];
  1921. data[i * 11 + 2] = bill.date[1];
  1922. data[i * 11 + 3] = (unsigned char)(bill.fw_used);
  1923. data[i * 11 + 4] = (unsigned char)(bill.fw_used >> 8);
  1924. data[i * 11 + 5] = (unsigned char)(bill.fw_used >> 16);
  1925. data[i * 11 + 6] = (unsigned char)(bill.fw_used >> 24);
  1926. data[i * 11 + 7] = (unsigned char)(bill.bw_used);
  1927. data[i * 11 + 8] = (unsigned char)(bill.bw_used >> 8);
  1928. data[i * 11 + 9] = (unsigned char)(bill.bw_used >> 16);
  1929. data[i * 11 + 10] = (unsigned char)(bill.bw_used >> 24);
  1930. }
  1931. }
  1932. static void BuildDayRecord(rtc_run_t *rr, uint8_t *data)
  1933. {
  1934. uint16_t i;
  1935. bill_t bill;
  1936. uint32_t date = ((rr->year << 16) | (rr->month << 8) | rr->day);
  1937. uint8_t vflag;
  1938. for (i = 0; i < 5; i++)
  1939. {
  1940. date = prev_day(date);
  1941. vflag = read_day_bill((uint8_t)(date >> 8), (uint8_t)date, &bill);
  1942. if (vflag != 0)
  1943. continue; // no data
  1944. if (bill.date[0] != (uint8_t)(date >> 16) || bill.date[1] != (uint8_t)(date >> 8) || bill.date[2] != (uint8_t)date)
  1945. continue; // 不是当天的数据
  1946. data[i * 12] = 0x14;
  1947. data[i * 12 + 1] = bill.date[0];
  1948. data[i * 12 + 2] = bill.date[1];
  1949. data[i * 12 + 3] = bill.date[2];
  1950. data[i * 12 + 4] = (unsigned char)(bill.fw_used);
  1951. data[i * 12 + 5] = (unsigned char)(bill.fw_used >> 8);
  1952. data[i * 12 + 6] = (unsigned char)(bill.fw_used >> 16);
  1953. data[i * 12 + 7] = (unsigned char)(bill.fw_used >> 24);
  1954. data[i * 12 + 8] = (unsigned char)(bill.bw_used);
  1955. data[i * 12 + 9] = (unsigned char)(bill.bw_used >> 8);
  1956. data[i * 12 + 10] = (unsigned char)(bill.bw_used >> 16);
  1957. data[i * 12 + 11] = (unsigned char)(bill.bw_used >> 24);
  1958. }
  1959. }
  1960. static void BuildHourRecord(rtc_run_t *rr, uint8_t *data)
  1961. {
  1962. uint8_t i;
  1963. hour_bill_t bill;
  1964. uint8_t vflag;
  1965. uint32_t date = ((rr->year << 16) | (rr->month << 8) | rr->day);
  1966. date = prev_day(date);
  1967. data[0] = 0x14;
  1968. data[1] = (unsigned char)(date >> 16);
  1969. data[2] = (unsigned char)(date >> 8);
  1970. data[3] = (unsigned char)(date);
  1971. for (i = 0; i < 24; i++)
  1972. {
  1973. vflag = read_hour_bill((uint8_t)date, i, &bill);
  1974. if (vflag != 0) // 数据不合法,放弃
  1975. continue;
  1976. if ((bill.date[0] != data[1]) || (bill.date[1] != data[2]) || (bill.date[2] != data[3]))
  1977. {
  1978. continue;
  1979. } // 不是当前日期数据,丢弃
  1980. memcpy(&data[4 + i * 3], bill.fw_used, 3);
  1981. memcpy(&data[4 + 72 + i * 3], bill.bw_used, 3);
  1982. data[4 + 144 + i] = bill.pressure;
  1983. memcpy(&data[4 + 168 + i * 3], bill.flow_rate, 3);
  1984. }
  1985. }
  1986. void NbBuildDataReport(void)
  1987. {
  1988. rtc_run_t *rr;
  1989. Nb_Run_t *nb_run;
  1990. uint16_t data_len = 448;
  1991. uint32_t *err_no;
  1992. // current date time
  1993. get_rtc_run(&rr);
  1994. GetNbRun(&nb_run);
  1995. NbBuildDataHeader(data_len);
  1996. // AFN
  1997. NbAppFrame.data[0] = 0x10;
  1998. NbAppFrame.data[1] = 0x00;
  1999. // MID
  2000. NbAppFrame.data[2] = 0x00;
  2001. NbAppFrame.data[3] = 0x00;
  2002. // DC
  2003. // report trigger mode
  2004. NbAppFrame.data[4] = nb_run->upload.mode;
  2005. BuildDataReportMeter(rr, &NbAppFrame.data[5]); // meter part len 30
  2006. BuildDataReportParam(&NbAppFrame.data[35]); // param part len 54
  2007. BuildDataReportNb(&NbAppFrame.data[89]); // nb part len 29
  2008. BuildMonthRecord(rr, &NbAppFrame.data[118]); // month record part len 22
  2009. BuildDayRecord(rr, &NbAppFrame.data[140]); // day record part len 60
  2010. BuildHourRecord(rr, &NbAppFrame.data[200]); // day record part len 244
  2011. // error no
  2012. all_alarm_status(&err_no);
  2013. //(*err_no) &= 0xffff0fff;
  2014. NbAppFrame.data[444] = (uint8_t)(*err_no);
  2015. NbAppFrame.data[445] = (uint8_t)(*err_no >> 8);
  2016. NbAppFrame.data[446] = (uint8_t)(*err_no >> 16);
  2017. NbAppFrame.data[447] = (uint8_t)(*err_no >> 24);
  2018. NbBuildDataTail(data_len);
  2019. }
  2020. void nb_set_para_rept(uint16_t dat_len, uint16_t afn, int8_t ret)
  2021. {
  2022. // uint16_t data_len = 5;
  2023. // uint16_t mid = (NbAppFrame.data[3] << 8) | NbAppFrame.data[2];
  2024. NbBuildDataHeader(dat_len);
  2025. // AFN
  2026. NbAppFrame.data[0] = (uint8_t)afn;
  2027. NbAppFrame.data[1] = (uint8_t)(afn >> 8);
  2028. // MID
  2029. // NbAppFrame.data[2] = (uint8_t)(mid);
  2030. // NbAppFrame.data[3] = (uint8_t)(mid >> 8);
  2031. NbAppFrame.data[4] = ret; // set success
  2032. NbBuildDataTail(dat_len);
  2033. }
  2034. void NbBuildReportMonthRecord(void)
  2035. {
  2036. uint16_t data_len = 202;
  2037. uint16_t mid = (NbAppFrame.data[3] << 8) | NbAppFrame.data[2];
  2038. uint8_t ret;
  2039. // rtc_run_t *rr;
  2040. // get_rtc_run(&rr);
  2041. NbBuildDataHeader(data_len);
  2042. // AFN
  2043. NbAppFrame.data[0] = 0x31;
  2044. NbAppFrame.data[1] = 0x00;
  2045. // MID
  2046. NbAppFrame.data[2] = (uint8_t)(mid);
  2047. NbAppFrame.data[3] = (uint8_t)(mid >> 8);
  2048. uint8_t *data = &NbAppFrame.data[4];
  2049. get_18month_record_data(data);
  2050. NbBuildDataTail(data_len);
  2051. }
  2052. void NbBuildReportDayRecord(void)
  2053. {
  2054. uint16_t data_len = 364;
  2055. uint16_t mid = (NbAppFrame.data[3] << 8) | NbAppFrame.data[2];
  2056. uint8_t ret;
  2057. NbBuildDataHeader(data_len);
  2058. // AFN
  2059. NbAppFrame.data[0] = 0x33;
  2060. NbAppFrame.data[1] = 0x00;
  2061. // MID
  2062. NbAppFrame.data[2] = (uint8_t)(mid);
  2063. NbAppFrame.data[3] = (uint8_t)(mid >> 8);
  2064. uint8_t *data = &NbAppFrame.data[4];
  2065. get_30day_record_data(data);
  2066. NbBuildDataTail(data_len);
  2067. }
  2068. void NbBuildReportHourRecord(uint8_t year, uint8_t month, uint8_t day)
  2069. {
  2070. uint16_t data_len = 248;
  2071. uint16_t mid = (NbAppFrame.data[3] << 8) | NbAppFrame.data[2];
  2072. // rtc_run_t *rr;
  2073. // get_rtc_run(&rr);
  2074. NbBuildDataHeader(data_len);
  2075. // AFN
  2076. NbAppFrame.data[0] = 0x35;
  2077. NbAppFrame.data[1] = 0x00;
  2078. // MID
  2079. NbAppFrame.data[2] = (uint8_t)(mid);
  2080. NbAppFrame.data[3] = (uint8_t)(mid >> 8);
  2081. uint8_t *data = &NbAppFrame.data[4];
  2082. get_hour_record_data(year, month, day, data);
  2083. NbBuildDataTail(data_len);
  2084. }
  2085. void NbBuildReport5MinRecord(tm_t *date)
  2086. { // 年月日时分
  2087. uint16_t data_len = 388;
  2088. uint16_t mid = (NbAppFrame.data[3] << 8) | NbAppFrame.data[2];
  2089. uint32_t i = 0;
  2090. uint8_t ret;
  2091. hour_bill_t bill;
  2092. tm_t src;
  2093. tm_t dest;
  2094. NbBuildDataHeader(data_len);
  2095. memset(NbAppFrame.data, 0, sizeof(NbAppFrame.data));
  2096. // AFN
  2097. NbAppFrame.data[0] = 0x37;
  2098. NbAppFrame.data[1] = 0x00;
  2099. // MID
  2100. NbAppFrame.data[2] = (uint8_t)(mid);
  2101. NbAppFrame.data[3] = (uint8_t)(mid >> 8);
  2102. uint8_t *data = &NbAppFrame.data[4];
  2103. GET_5MIN_REOCORD_DEF mdate;
  2104. mdate.start_time[0] = date->year;
  2105. mdate.start_time[1] = date->month;
  2106. mdate.start_time[2] = date->day;
  2107. mdate.start_time[3] = date->hour;
  2108. mdate.start_time[4] = date->min;
  2109. mdate.start_time[5] = date->sec;
  2110. time_add_secs(&dest, date, 2 * 3600);
  2111. mdate.end_time[0] = dest.year;
  2112. mdate.end_time[1] = dest.month;
  2113. mdate.end_time[2] = dest.day;
  2114. mdate.end_time[3] = dest.hour;
  2115. mdate.end_time[4] = dest.min;
  2116. mdate.end_time[5] = dest.sec;
  2117. get_5min_record_data(&mdate, 0, data);
  2118. NbBuildDataTail(data_len);
  2119. }
  2120. void NbBuildReportLogRecord(void)
  2121. {
  2122. uint16_t data_len = 394;
  2123. uint16_t mid = (NbAppFrame.data[3] << 8) | NbAppFrame.data[2];
  2124. uint8_t i;
  2125. int8_t j;
  2126. uint8_t num = 0;
  2127. alarm_t alarm;
  2128. uint8_t rec_len = 13;
  2129. NbBuildDataHeader(data_len);
  2130. // AFN
  2131. NbAppFrame.data[0] = 0x39;
  2132. NbAppFrame.data[1] = 0x00;
  2133. // MID
  2134. NbAppFrame.data[2] = (uint8_t)(mid);
  2135. NbAppFrame.data[3] = (uint8_t)(mid >> 8);
  2136. uint8_t *data = &NbAppFrame.data[4];
  2137. num = get_alarm_num();
  2138. if (num > 30)
  2139. {
  2140. num = 30;
  2141. }
  2142. get_log_record(0, num, data);
  2143. NbBuildDataTail(data_len);
  2144. }
  2145. void NbBuildGetPackage(void)
  2146. {
  2147. uint16_t data_len = 21;
  2148. uint16_t mid = (NbAppFrame.data[3] << 8) | NbAppFrame.data[2];
  2149. Param_t *param;
  2150. NbBuildDataHeader(data_len);
  2151. // AFN
  2152. NbAppFrame.data[0] = 0x51;
  2153. NbAppFrame.data[1] = 0x00;
  2154. // MID
  2155. NbAppFrame.data[2] = (uint8_t)(mid);
  2156. NbAppFrame.data[3] = (uint8_t)(mid >> 8);
  2157. GetParam(&param);
  2158. uint8_t *data = &NbAppFrame.data[4];
  2159. data[0] = 'V';
  2160. data[1] = VER_TYPE;
  2161. data[2] = VER_OPERATOR;
  2162. data[3] = VER_MODULE;
  2163. data[4] = VER_FIRMWARE;
  2164. data[5] = 'V';
  2165. data[6] = VER_TYPE;
  2166. data[7] = VER_OPERATOR;
  2167. data[8] = VER_MODULE;
  2168. data[9] = VER_FIRMWARE + 1;
  2169. data[10] = (uint8_t)(PatchInfo.per_packet_len);
  2170. data[11] = (uint8_t)(PatchInfo.per_packet_len >> 8);
  2171. data[12] = (uint8_t)(PatchInfo.cur_num);
  2172. data[13] = (uint8_t)(PatchInfo.cur_num >> 8);
  2173. data[14] = (uint8_t)(PatchInfo.packet_crc);
  2174. data[15] = (uint8_t)(PatchInfo.packet_crc >> 8);
  2175. data[16] = 1;
  2176. NbBuildDataTail(data_len);
  2177. }
  2178. void NbBuildReportUpdateStatus(int8_t stat)
  2179. {
  2180. uint16_t data_len = 5;
  2181. uint16_t mid = NbRun.mid; //(NbAppFrame.data[3] << 8) | NbAppFrame.data[2];
  2182. Param_t *param;
  2183. NbBuildDataHeader(data_len);
  2184. // AFN
  2185. NbAppFrame.data[0] = 0x52;
  2186. NbAppFrame.data[1] = 0x00;
  2187. // MID
  2188. NbAppFrame.data[2] = (uint8_t)(mid);
  2189. NbAppFrame.data[3] = (uint8_t)(mid >> 8);
  2190. NbAppFrame.data[4] = stat;
  2191. NbBuildDataTail(data_len);
  2192. }
  2193. #ifdef DEBUG_LOG_WARM
  2194. void Debug_log(void)
  2195. {
  2196. // #ifdef DEBUG_NB
  2197. uint8_t i;
  2198. for (i = 0; i < 32; i++)
  2199. {
  2200. write_alarm(i / 2, i % 2, i * 10 + 10);
  2201. }
  2202. // #endif
  2203. }
  2204. #endif
  2205. #ifdef APP_DEBUG_PRINT
  2206. static char str[50];
  2207. char *get_upload_type_str(uint8_t type)
  2208. {
  2209. char cnt = 0;
  2210. memset(str, 0, 50);
  2211. if (type & 0x1)
  2212. strcat(str, "manual,");
  2213. if (type & 0x2)
  2214. strcat(str, "regular,");
  2215. if (type & 0x4)
  2216. strcat(str, "rept,");
  2217. if (type & 0x8)
  2218. strcat(str, "settlement,");
  2219. if (type & 0x10)
  2220. strcat(str, "error,");
  2221. if (type & 0x20)
  2222. strcat(str, "dma");
  2223. return str;
  2224. }
  2225. #endif
  2226. uint8_t memstr_exist(uint8_t *hay, size_t hay_len, const char *sub, size_t sub_len)
  2227. {
  2228. if (sub_len == 0)
  2229. return 1;
  2230. if (sub_len > hay_len)
  2231. return 0;
  2232. for (size_t i = 0; i <= hay_len - sub_len; i++)
  2233. {
  2234. if (memcmp(hay + i, sub, sub_len) == 0)
  2235. {
  2236. return 1;
  2237. }
  2238. }
  2239. return 0;
  2240. }
  2241. int8_t get_code(uint8_t *buf, const char *keyword, uint16_t dat_len, int16_t *ret)
  2242. {
  2243. char *pos;
  2244. buf[dat_len] = 0;
  2245. pos = strstr((char *)buf, keyword);
  2246. if (pos == NULL)
  2247. return -1;
  2248. uint16_t dat = 0;
  2249. uint16_t i;
  2250. char vflag;
  2251. pos = pos + strlen(keyword);
  2252. vflag = 0;
  2253. uint8_t flag = 0;
  2254. if (*pos == '+' || *pos == '-')
  2255. {
  2256. if (*pos == '-')
  2257. flag = 1;
  2258. pos++;
  2259. }
  2260. while (*pos >= '0' && *pos <= '9')
  2261. {
  2262. dat *= 10;
  2263. dat += *pos - '0';
  2264. pos++;
  2265. vflag = 1;
  2266. }
  2267. if (vflag == 0)
  2268. return -1;
  2269. if (flag == 1)
  2270. dat = -dat;
  2271. *ret = dat;
  2272. return 1;
  2273. }
  2274. //+QNTP: 0,"2019/09/09,01:32:42+32"
  2275. void save_datetime_from_at(uint8_t *buf, uint16_t dat_len)
  2276. {
  2277. tm_t tm;
  2278. int16_t zone = 0;
  2279. char *p;
  2280. buf[dat_len] = 0; // 确保字符串终止
  2281. p = strstr((char *)buf, "\""); // 定位到双引号开始处
  2282. if (p == NULL)
  2283. return;
  2284. // 利用 sscanf 直接格式化提取年月日时分秒和时区
  2285. // 格式: 2019/09/09,01:32:42+32
  2286. if (sscanf(p + 1, "%hu/%hu/%hu,%u:%u:%u%hd",
  2287. &tm.year, &tm.month, &tm.day,
  2288. &tm.hour, &tm.min, &tm.sec, &zone) != 7)
  2289. {
  2290. return; // 解析失败或格式不匹配
  2291. }
  2292. // 合法性检查
  2293. if (tm.year < 26 || tm.month == 0 || tm.month > 12 ||
  2294. tm.day == 0 || tm.day > 31 || tm.hour > 23 || tm.min > 59 || tm.sec > 59)
  2295. return;
  2296. // 时区转换 (保留原逻辑:正负时区分别调用不同的时间计算函数)
  2297. if (zone > 0)
  2298. {
  2299. time_add_secs(&tm, &tm, zone * 15 * 60);
  2300. }
  2301. else if (zone < 0) // 增加非零判断,避免对0进行无意义的减法
  2302. {
  2303. time_sub_secs(&tm, &tm, -zone * 15 * 60); // 传入正数
  2304. }
  2305. tm.year %= 100;
  2306. SetRtcTime(&tm);
  2307. }
  2308. //+QENG: "servingcell","NOCONN","LTE","FDD",460,11,EA6CE03,77,100,1,5,5,EA15,-94,-8,-66,24,26
  2309. // rsrp rwrq rssi sinr
  2310. uint8_t get_nb_signal(uint8_t *buf, uint16_t dat_len)
  2311. {
  2312. char temp[8];
  2313. char *p;
  2314. int8_t index1 = 0, index2 = 0;
  2315. int16_t *out_val = NULL;
  2316. uint8_t ret = 0;
  2317. buf[dat_len] = 0; // 确保终止位
  2318. p = strstr((char *)buf, "servingcell");
  2319. if (p == NULL)
  2320. return 0;
  2321. index1 = strnchar(p, ',', 12);
  2322. // 依次提取 rsrp_bak, rsrq, rssi, snr
  2323. for (uint8_t i = 0; i < 4; i++)
  2324. {
  2325. if (index1 == -1)
  2326. break; // 上一次查找失败,直接退出
  2327. index2 = strnchar(p, ',', 13 + i);
  2328. if (index2 != -1 && index1 < index2)
  2329. {
  2330. memset(temp, 0, sizeof(temp));
  2331. memcpy(temp, p + index1 + 1, index2 - index1 - 1);
  2332. int16_t val = atoi(temp);
  2333. switch (i)
  2334. {
  2335. case 0:
  2336. NbRun.rsrp_bak = val;
  2337. break;
  2338. case 1:
  2339. NbRun.rsrq = val;
  2340. break;
  2341. case 2:
  2342. NbRun.rssi = val;
  2343. ret = 1;
  2344. break;
  2345. }
  2346. }
  2347. index1 = index2; // 将当前的右边界作为下一次的左边界
  2348. }
  2349. return ret;
  2350. }
  2351. uint8_t check_sub_service_flag(void)
  2352. {
  2353. uint8_t vflag;
  2354. vflag = 1;
  2355. if (Paramx.main_server_ip[0] == Paramx.sub_server_ip[0] && Paramx.main_server_ip[1] == Paramx.sub_server_ip[1] && Paramx.main_server_ip[2] == Paramx.sub_server_ip[2] && Paramx.main_server_ip[3] == Paramx.sub_server_ip[3] && Paramx.main_server_port == Paramx.sub_server_port)
  2356. {
  2357. vflag = 0;
  2358. } // 主从ip相同,端口号相同
  2359. if (Paramx.sub_server_ip[0] == 0 || Paramx.sub_server_port == 0) // 从ip为空,端口号为空
  2360. {
  2361. vflag = 0;
  2362. }
  2363. return vflag;
  2364. }
  2365. uint8_t check_main_service_flag(void)
  2366. {
  2367. uint8_t vflag;
  2368. vflag = 1;
  2369. if (Paramx.main_server_ip[0] == 0 || Paramx.main_server_port == 0) // 从ip为空,端口号为空
  2370. {
  2371. vflag = 0;
  2372. }
  2373. return vflag;
  2374. }