app_nb.c 77 KB

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