app_nb.c 79 KB

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