| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882 |
- #include "board.h"
- #include "app_nb.h"
- #include "prj_com.h"
- #include "param.h"
- #include "rtc_run.h"
- #include "board.h"
- #include "tdc_tof.h"
- #include "bill.h"
- #include "alarm.h"
- #include "stat.h"
- #include "ymodem.h"
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdint.h>
- #include <string.h>
- Nb_Run_t NbRun;
- uint8_t NB_CHECK_TDC_COMPLETE_FLAG = 0;
- uint8_t NbIntStep = 0xFFu;
- rt_sem_t Nb_thread_run_sem = RT_NULL; // NB线程运行信号量
- // 补报相关信息
- NbAppFrame_t __attribute__((aligned(4))) NbAppFrame;
- uint8_t Nb_rx_data(void);
- void nb_run_init(void)
- {
- nb_power_off();
- lpuart0_set_rx_itf(NbRxCh); // nb串口中断
- // NbRun.rx_flag = FALSE;
- NbRun.rx_over_time = 0;
- NbRun.rx_idx = 0;
- memset(NbRun.rx_buf, 0, sizeof(NbRun.rx_buf));
- memset(NbRun.tx_buf, 0, sizeof(NbRun.tx_buf));
- NbRun.cur_at = at_end;
- NbRun.rsrp = 0;
- NbRun.rsrq = 0;
- NbRun.rssi = 0;
- NbRun.snr = 0;
- memset(NbRun.imei, 0, sizeof(NbRun.imei));
- memset(NbRun.imsi, 0, sizeof(NbRun.imsi));
- memset(NbRun.ccid, 0, sizeof(NbRun.ccid));
- NbRun.task.count = 0;
- // NbRun.open_time_out = 0;
- memset(&NbAppFrame, 0, sizeof(NbAppFrame));
- NbRun.status = 0;
- Nb_thread_run_sem = rt_sem_create("nb_thread_run", 0, RT_IPC_FLAG_FIFO); // 创建nb运行信号量
- NbRun.get_imei_flag = 0;
- NbRun.get_imsi_flag = 0;
- NbRun.get_ccid_flag = 0;
- }
- static void NbBuildDataHeader(uint16_t data_len)
- {
- Param_t *param;
- GetParam(¶m);
- NbAppFrame.prefix[0] = 0xFE;
- NbAppFrame.prefix[1] = 0xFE;
- NbAppFrame.head = 0x68;
- NbAppFrame.type = 0x10;
- // memcpy(NbAppFrame.addr, param->dev_id, sizeof(param->dev_id));
- NbAppFrame.addr[0] = param->dev_id[5];
- NbAppFrame.addr[1] = param->dev_id[4];
- NbAppFrame.addr[2] = param->dev_id[3];
- NbAppFrame.addr[3] = param->dev_id[2];
- NbAppFrame.addr[4] = param->dev_id[1];
- NbAppFrame.addr[5] = param->dev_id[0];
- // NbAppFrame.addr[6] = param->dev_id[0];
- NbAppFrame.addr[6] = 0x00;
- NbAppFrame.ctrl = 0xA0;
- NbAppFrame.len[0] = (unsigned char)(data_len);
- NbAppFrame.len[1] = (unsigned char)(data_len >> 8);
- }
- static void NbBuildDataTail(uint16_t data_len)
- {
- uint8_t cs = 0;
- // cs
- cs = check_sum((uint8_t *)&NbAppFrame.head, 12);
- cs += check_sum(NbAppFrame.data, data_len);
- NbAppFrame.data[data_len] = cs; // 8位累加和
- NbAppFrame.data[data_len + 1] = 0x16; // 结束位
- }
- /*
- int NbRcvDataValid(void)
- {
- char *p = NULL;
- int16_t index1 = 0;
- uint16_t index2 = 0;
- char data[5] = {0};
- uint32_t len;
- uint8_t cs;
- uint16_t data_len;
- if (Nb_rx_data() == 0)
- return 0;
- p = strstr((char *)NbRun.rx_buf, ",");
- if (p == NULL)
- {
- // LOG("no data recv flag\n");
- NbClrRxBuf();
- return 2;
- }
- index1 = 2; // strnchar((char *)NbRun.rx_buf, ':', 0);
- index2 = strnchar((char *)NbRun.rx_buf, ',', 0);
- // index1 = strnchar((char *)NbRun.rx_buf, ',', 0);
- // index2 = strnchar((char *)NbRun.rx_buf, ',', 1);
- if (index1 > index2 || index2 < 1 || (index2 - index1) > sizeof(data))
- {
- NbClrRxBuf();
- return 3;
- }
- memcpy(data, NbRun.rx_buf + index1, index2 - index1);
- str2int(data, &len); // 已发送数据长度
- if (len < 14)
- {
- NbClrRxBuf();
- return 4;
- }
- StrToHexBuf((char *)&NbAppFrame.head, (char *)(NbRun.rx_buf + index2 + 1), len);
- NbClrRxBuf();
- if (NbAppFrame.head != 0x68)
- { // 帧头不正确
- return 5;
- }
- data_len = (NbAppFrame.len[1] << 8) | NbAppFrame.len[0];
- if (len != 14 + data_len)
- { // 已发送长度不正确
- return 6;
- }
- cs = check_sum((uint8_t *)&NbAppFrame.head, len - 2);
- if (cs != NbAppFrame.data[data_len])
- { // crc校验不正确
- return 7;
- }
- if (NbAppFrame.data[data_len + 1] != 0x16)
- { // 结束符不正确
- return 8;
- }
- return 1;
- }*/
- char *get_frame_start(char *buf, uint16_t len)
- {
- if (buf == NULL || len < 2)
- {
- return NULL;
- }
- for (uint16_t i = 0; i <= len - 2; i++)
- {
- if ((uint8_t)buf[i] == 0x68 && (uint8_t)buf[i + 1] == 0x10)
- {
- return &buf[i];
- }
- }
- return NULL;
- }
- int NbRcvDataValid(void)
- {
- char *p_comma = NULL;
- char *p_start = NULL;
- char len_str[8] = {0};
- uint32_t total_frame_len = 0;
- uint8_t cs;
- uint8_t head_len = 0;
- uint16_t data_len;
- // 1. 检查是否有数据接收完成标志
- if (Nb_rx_data() == 0)
- return 0; // 无数据,继续等待
- // 2. 接收数据关键字
- p_comma = strstr((char *)NbRun.rx_buf, "+QIRD: ");
- if (p_comma == NULL)
- {
- // 没有逗号,检查是否全是空白或OK,如果是则清除
- if (strstr((char *)NbRun.rx_buf, "OK") != NULL || NbRun.rx_idx > 50)
- {
- NbClrRxBuf();
- }
- return 0; // 数据可能不完整,继续等待
- }
- p_start = p_comma + 7; //+QIRD:后的数据开始位置
- while (*p_start >= '0' && *p_start <= '9')
- {
- len_str[head_len++] = *p_start++;
- }
- len_str[head_len] = '\0';
- total_frame_len = atoi(len_str); // 数据总长度
- if (total_frame_len < 14)
- {
- NbClrRxBuf();
- return 4;
- }
- // 6. 检查 Hex 数据完整性
- // char *p_hex_start = p_start + head_len + 2; // 包含关键字+ 长度域+ 回车换行符
- char *p_hex_start = get_frame_start(p_start + 2, NbRun.rx_idx - (p_start + 2 - (char *)NbRun.rx_buf));
- if (p_hex_start == NULL)
- {
- return 0; // 数据不完整,继续等待
- }
- // 6.2 检查校验和
- cs = 0;
- uint16_t available_chars = NbRun.rx_idx - (p_hex_start - (char *)NbRun.rx_buf);
- if (available_chars < total_frame_len) // 这里可能要改为接收二进制数据,(去掉*2)
- {
- return 0; // 数据不完整,继续等待
- }
- // 7. Hex 转 Binary
- // StrToHexBuf((char *)&NbAppFrame.head, p_hex_start, total_frame_len);//如果是二进制数据,则不需要转换
- memcpy((char *)&NbAppFrame.head, p_hex_start, total_frame_len);
- NbClrRxBuf();
- // 8. 校验帧头
- if (NbAppFrame.head != 0x68)
- return 5;
- // 9. 校验长度一致性
- data_len = (NbAppFrame.len[1] << 8) | NbAppFrame.len[0];
- if (total_frame_len != (14 + data_len))
- return 6;
- // 10. 校验 Check Sum
- cs = check_sum((uint8_t *)&NbAppFrame.head, total_frame_len - 2);
- if (cs != NbAppFrame.data[data_len])
- return 7;
- // 11. 校验帧尾
- if (NbAppFrame.data[data_len + 1] != 0x16)
- return 8;
- return 1; // 验证成功
- }
- void GetNbRun(Nb_Run_t **nb_run)
- {
- *nb_run = &NbRun;
- }
- void NbRxCh(uint8_t ch)
- {
- if (NbRun.rx_idx >= NB_RXLEN_MAX - 1)
- {
- return;
- }
- NbRun.rx_buf[NbRun.rx_idx++] = ch;
- NbRun.rx_over_time = 4;
- #ifdef DEBUG_NB
- // LOG("%c",ch);
- #endif
- }
- // void NbRxTimeout(void)
- //{
- // if (NbRun.rx_over_time >= 2) {
- // NbRun.rx_over_time--;
- // } else if (NbRun.rx_over_time == 1) {
- // NbRun.rx_flag = TRUE;
- // NbRun.rx_over_time--;
- // }
- // }
- uint8_t Nb_rx_data(void)
- {
- if (NbRun.rx_over_time != 0)
- {
- NbRun.rx_over_time--;
- }
- if (NbRun.rx_over_time == 1)
- {
- #ifdef DEBUG_NB
- /////////////////////
- unsigned short i;
- for (i = 0; i < NbRun.rx_idx; i++)
- LOG("%c", NbRun.rx_buf[i]);
- // LOG("%s\r\n",NbRun.rx_buf);
- ///////////////////
- #endif
- return 1; // 已收到数据
- // }
- }
- return 0;
- }
- void NbClrRxBuf(void)
- {
- NbRun.rx_idx = 0;
- memset(NbRun.rx_buf, 0, sizeof(NbRun.rx_buf));
- }
- int8_t get_nb_imsi_code(void)
- {
- char *p = NULL;
- char *q = NULL;
- uint8_t i, flag;
- p = strstr((char *)NbRun.rx_buf, "OK");
- if (p == NULL)
- {
- return -1;
- }
- p = strstr((char *)NbRun.rx_buf, "\r\n"); // 找到第一个回车符
- if (p != NULL && strlen(p) > 2)
- {
- q = strstr(p + 2, "\r\n"); // 第二个回车符,id在两个回车符之间
- if (q != NULL && (q - p - 2) > 0 && (q - p - 2) < 16)
- { // 长度大于2小于15
- *q = 0;
- strcpy(NbRun.imsi, p + 2);
- /// LOG("imsi = %s\n", NbRun.imsi);
- }
- }
- flag = 0;
- for (i = 0; NbRun.imsi[i] != 0; i++)
- {
- if (NbRun.imsi[i] < '0' || NbRun.imsi[i] > '9')
- {
- flag = 1;
- break;
- }
- }
- if (flag == 1 || i != 15)
- return -1;
- NbRun.get_imsi_flag = 1; // 已获取IMEI号标志
- return 0;
- }
- int8_t get_nb_imei_code(void)
- {
- char *p = NULL;
- char *q = NULL;
- uint8_t i, flag;
- p = strstr((char *)NbRun.rx_buf, "OK");
- if (p == NULL)
- {
- return -1;
- }
- p = strstr((char *)NbRun.rx_buf, "+CGSN:");
- if (p != NULL)
- {
- p = strstr((char *)NbRun.rx_buf, "\""); // 找到第一个"所在位置
- if (p != NULL && strlen(p + 1) > 1)
- {
- q = strstr(p + 1, "\"\r\n"); // 回车换行符所在位置
- if (q != NULL && (q - p - 1) > 0 && (q - p - 1) < 16)
- { // 存在回车换行符,且:到换行符之间有信息,且长度小于16
- *q = 0; // 把第二个"置0,作为字符串结束位置
- strcpy(NbRun.imei, p + 1);
- }
- }
- }
- flag = 0;
- for (i = 0; NbRun.imei[i] != 0; i++)
- {
- if (NbRun.imei[i] < '0' || NbRun.imei[i] > '9')
- {
- flag = 1;
- break;
- }
- }
- if (flag == 1 || i != 15)
- return -1;
- NbRun.get_imei_flag = 1; // 已获取IMEI号标志
- #ifdef APP_DEBUG_PRINT
- LOG("imei=%s\r\n", NbRun.imei);
- #endif
- return 0;
- }
- int8_t get_nb_ccid_code(void)
- {
- char *p = NULL;
- char *q = NULL;
- uint8_t i, flag;
- p = strstr((char *)NbRun.rx_buf, "OK");
- if (p == NULL)
- {
- return -1;
- }
- p = strstr((char *)NbRun.rx_buf, ":");
- p++;
- if (p != NULL && strlen(p) > 1)
- {
- q = strstr(p + 1, "\r\n");
- if (q != NULL && (q - p - 1) > 0 && (q - p - 1) < 21)
- {
- *q = 0;
- strcpy(NbRun.ccid, p + 1);
- }
- }
- flag = 0;
- for (i = 0; NbRun.ccid[i] != 0; i++)
- {
- if (NbRun.ccid[i] < '0' || NbRun.ccid[i] > '9')
- {
- flag = 1;
- break;
- }
- }
- if (flag == 1 || i != 20)
- return -1;
- NbRun.get_ccid_flag = 1; // 已获取IMEI号标志
- #ifdef APP_DEBUG_PRINT
- LOG("iccid=%s\r\n", NbRun.ccid);
- #endif
- return 0;
- }
- // NUESTATS:CELL,<earfcn>,<physical_cell_id>,<primarycell>,<RSRP>,<RSRQ>,<RSSI>,<SNR>
- // NUESTATS:CELL,2401,476,1,-920,-41,-879,144
- // 在 app_nb.c 中找到 NbSetUploadMode 函数并替换
- void NbSetUploadMode(uint8_t mode)
- {
- // 【修改点】:始终更新 mode,使用 |= 确保不覆盖已有的触发原因
- // 例如:如果之前是定时上报(0x02),现在发生了错误报警(0x10),mode 将变为 0x12
- NbRun.upload.mode |= mode;
- // 只有在尚未标记上传任务时,才设置 flag 并唤醒线程
- if (NbRun.upload.flag == FALSE)
- {
- NbRun.upload.flag = TRUE;
- NbRun.task.flag = 1;
- NbRun.cur_afn = 0x0010;
- rt_sem_release(Nb_thread_run_sem); // 触发nb线程
- }
- }
- /////////////////等待接收指定的回复///////////////////////
- // ack:回复的字符串
- // timeout:等待超时时间 秒单位
- //: 返回0:成功, -1:等待超时
- /////////////////////////////////////
- int8_t Nb_check_rec_valid(uint8_t state, char *ack)
- {
- // if(state == COAP_WAIT_REG){
- // if(strstr((const char *)NbRun.rx_buf, ack) != NULL )
- // }
- // else
- if (strstr((const char *)NbRun.rx_buf, ack) != NULL)
- { // 收到要求的回复
- return 1; // 收到正确回复,进行下一步
- }
- // if (strstr((char *)&NbRun.rx_buf[0], "\r\nOK\r\n") != NULL || strstr((char *)&NbRun.rx_buf[0], "\r\nERROR\r\n") != NULL)
- if (strstr((char *)&NbRun.rx_buf[0], "\r\nERROR\r\n") != NULL)
- {
- return -1; // 错误回复,重新发送
- }
- return 0; // 其他需要继续等待
- }
- void nb_send_data_route(unsigned char *data, uint16_t len) // 发送数据 TCP
- {
- char tmp[16] = {0};
- memset(NbRun.tx_buf, 0, sizeof(NbRun.tx_buf));
- strcpy((char *)NbRun.tx_buf, "AT+QISENDEX=0,"); // at指令 发送数据
- // int2str(len, tmp); // 转换成字符串
- strcat((char *)NbRun.tx_buf, "\"");
- HexBufToStr((char *)NbRun.tx_buf + strlen((char *)NbRun.tx_buf), data, len); // 不加前面的指令部分,只发送数据部分
- strcat((char *)NbRun.tx_buf, "\"");
- strcat((char *)NbRun.tx_buf, "\r\n\0"); // 末尾回车换行符
- // NbRoutineEventPro((char *)NbRun.tx_buf, (char *)NB_NMGS_ACK, 3, 60);
- }
- UPLOAD_DEF upload_dat;
- const uint8_t monthday[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
- ///////////////////////////////////////////
- /////////////////////////////////main.c中运行,判断是否应该触发nb线程//////////////////////////////////////////////
- // 参数 无
- // 返回 无
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- uint8_t settlement_day_upload_check(void)
- { // 结算日上报
- if (Paramx.settlement_day == 0)
- return 0;
- rtc_run_t *rr;
- get_rtc_run(&rr);
- uint8_t days, setday;
- days = monthday[rr->month - 1];
- if (rr->year % 4 == 0 && rr->month == 2)
- {
- days++;
- } // 计算当月天数
- //////////////////////确定当天上报是否是结算日上报/////////////////////////////////////
- int32_t now, start;
- now = (int32_t)(3600 * rr->hour + 60 * rr->minute + rr->second);
- start = (int32_t)(Paramx.report_base_hour * 3600 + Paramx.report_base_min * 60 + (Paramx.report_base_sec & 0xfc));
- if (Paramx.settlement_day == 0)
- {
- return 0;
- }
- if (Paramx.settlement_day > days)
- {
- setday = days;
- }
- else
- {
- setday = Paramx.settlement_day;
- }
- if (now < start)
- return 0;
- if (setday == rr->day && now - start <= 5)
- {
- return NB_UPLOAD_SETTLE_DAY;
- }
- return 0;
- }
- uint8_t regular_upload_check(void)
- { // 定时上报
- uint32_t *alarmbit;
- all_alarm_status(&alarmbit);
- if ((*alarmbit & ERR_LOW_POWER) != 0)
- return 0; // 低电压不上报
- uint8_t i;
- rtc_run_t *rr;
- get_rtc_run(&rr);
- int32_t now, start;
- now = (int32_t)(3600 * rr->hour + 60 * rr->minute + rr->second);
- start = (int32_t)(Paramx.report_base_hour * 3600 + Paramx.report_base_min * 60 + (Paramx.report_base_sec & 0xfc));
- if (now < start)
- return 0; // 未到上报时间
- if (((now - start) % (Paramx.report_interval * 60)) <= 5)
- return NB_UPLOAD_TIMER;
- return 0;
- }
- uint8_t dma_upload_check(void)
- {
- uint32_t *alarmbit;
- all_alarm_status(&alarmbit);
- if ((*alarmbit & ERR_LOW_POWER) != 0)
- return 0; // 低电压DMA不上报
- if (Paramx.dma_interval == 0)
- return 0; // 无dma上报
- int32_t start_sec, end_sec, now_sec;
- rtc_run_t *rr;
- get_rtc_run(&rr);
- start_sec = (int32_t)(3600 * Paramx.dma_report_start[0] + 60 * Paramx.dma_report_start[1] + (Paramx.dma_report_start[2] & 0xfc));
- end_sec = (int32_t)(3600 * Paramx.dma_report_end[0] + 60 * Paramx.dma_report_end[1] + (Paramx.dma_report_end[2] & 0xfc));
- now_sec = (int32_t)(3600 * rr->hour + 60 * rr->minute + rr->second);
- if (now_sec < start_sec || now_sec > end_sec + 3)
- return 0; // 不在dma时间范围内
- if (((now_sec - start_sec) % (Paramx.dma_interval * 60)) <= 5)
- {
- return NB_UPLOAD_DMA;
- }
- return 0;
- }
- ////////////////故障上报监测///////////////////////
- // 参数:无
- // 返回:有故障NB_UPLOAD_ERR 无故障:0
- ///////////////////////////////////////////////
- uint8_t err_upload_check(void)
- {
- uint32_t *alarmbit;
- uint32_t temp;
- if (StartUp < 15)
- return 0;
- all_alarm_status(&alarmbit);
- temp = (upload_dat.err_mem_dat & (*alarmbit)) ^ (*alarmbit); // 检查是否有异常bit被置位
- if (temp != 0)
- {
- upload_dat.err_mem_dat = *alarmbit;
- return NB_UPLOAD_ERR;
- }
- return 0;
- }
- uint8_t rept_upload_check(void)
- { // 重复上报监测
- uint8_t i;
- rtc_run_t *rr;
- get_rtc_run(&rr);
- tm_t now_time;
- now_time.year = rr->year;
- now_time.month = rr->month;
- now_time.day = rr->day;
- now_time.hour = rr->hour;
- now_time.min = rr->minute;
- now_time.sec = rr->second;
- uint32_t now_sec = (uint32_t)(now_time.hour * 3600 + now_time.min * 60 + now_time.sec);
- uint32_t start_sec = (uint32_t)(upload_dat.rept_time.hour * 3600 + upload_dat.rept_time.min * 60 + (upload_dat.rept_time.sec & 0xfc));
- uint8_t ret = 0;
- if (upload_dat.rept_runflag != 0)
- {
- // if (datecmp(now_time, upload_dat.rept_time) >= 0)
- if (now_sec >= start_sec && now_sec <= start_sec + 3)
- {
- upload_dat.rept_runflag = 0;
- return NB_UPLOAD_REPT;
- }
- }
- return 0;
- }
- // 手动上报
- uint8_t manual_upload_check(void)
- {
- if (upload_dat.manual_runflag == 1)
- {
- upload_dat.manual_runflag = 0;
- return NB_UPLOAD_MANUAL;
- }
- return 0;
- }
- short up_signal_cnt = -100; // 用于上报过程中动态显示信号强度
- /////////////////////////////////main.c中运行,判断是否应该触发nb线程,1秒1一次//////////////////////////////////////////////
- // 参数 无
- // 返回 无
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // 在 app_nb.c 中找到 nb_task_run_check 函数并替换
- void nb_task_run_check(void)
- {
- uint8_t trik_flag = 0;
- extern const int16_t rsrp_level[5];
- // 信号强度动态显示逻辑保持不变
- if (NbRun.upload.flag != 0)
- {
- up_signal_cnt = (up_signal_cnt + 1) % 5;
- NbRun.rsrp = rsrp_level[up_signal_cnt];
- }
- else
- NbRun.rsrp = NbRun.rsrp_bak;
- #ifdef debug_dog
- if (StartUp == 5)
- {
- rt_enter_critical();
- McuFlash_EraseSegment(DIFF_PATCH_PACKET_START, DIFF_PATCH_PACKET_SIZE);
- rt_exit_critical();
- rt_enter_critical();
- uint8_t i;
- for (i = 0; i < 16; i++)
- xx[i] = i + 1;
- write_flash_memory(xx, DIFF_PATCH_PACKET_START, 16);
- rt_exit_critical();
- while (1)
- ;
- }
- #endif
- if (NbRun.reset_mcu_cnt != 0)
- {
- NbRun.reset_mcu_cnt--;
- if (NbRun.reset_mcu_cnt == 2)
- LOG("ready to reset mcu\r\n");
- if (NbRun.reset_mcu_cnt == 1)
- {
- // watchdog_init(WdtResetEn, WdtT3s28);
- // feed_dog();
- NVIC_SystemReset();
- // while (1);
- // {
- // }
- }
- // NVIC_SystemReset();
- }
- // 【修改点】:不再因为 NbRun.upload.flag 为真而直接 return
- // 即使正在上传,我们也要检查是否有新的触发原因(如错误报警),并将其加入 mode
- trik_flag = settlement_day_upload_check();
- trik_flag |= regular_upload_check();
- trik_flag |= dma_upload_check();
- trik_flag |= err_upload_check(); // 错误报警通常优先级最高,但也作为位之一
- trik_flag |= rept_upload_check();
- trik_flag |= manual_upload_check();
- if (trik_flag != 0)
- {
- // 调用 NbSetUploadMode,它内部会处理 |= 逻辑和线程唤醒逻辑
- NbSetUploadMode(trik_flag);
- }
- // 注意:如果上传已经完成或失败,NbRun.upload.flag 会在 NbTread 末尾清零
- // 此时下一次 nb_task_run_check 运行时会正常触发新的上传任务
- }
- // 上报数据准备,在tx_buf中
- void nb_upload_data_ready(void)
- {
- NbBuildDataReport(); // 组织上报数据,在NbAppFrame中
- uint16_t len = ((NbAppFrame.len[1] << 8) | NbAppFrame.len[0]) + 16; // 数据总长度
- nb_send_data_route((uint8_t *)&NbAppFrame, len);
- }
- void nb_set_ip_para_ack(void)
- {
- // NbBuildSetIpAndPortRsp();
- nb_set_para_rept(5, 0x20, 1);
- uint16_t len = ((NbAppFrame.len[1] << 8) | NbAppFrame.len[0]) + 16;
- nb_send_data_route((uint8_t *)&NbAppFrame, len);
- }
- void nb_set_regular_report_para_ack(int8_t ret)
- {
- // NbBuildSetReportPointRsp(ret);
- nb_set_para_rept(5, 0x21, ret);
- uint16_t len = ((NbAppFrame.len[1] << 8) | NbAppFrame.len[0]) + 16;
- nb_send_data_route((uint8_t *)&NbAppFrame, len);
- }
- void nb_set_dma_report_para_ack(int8_t ret)
- {
- /// NbBuildSetDmaReportPointRsp(ret);
- nb_set_para_rept(5, 0x22, ret);
- uint16_t len = ((NbAppFrame.len[1] << 8) | NbAppFrame.len[0]) + 16;
- nb_send_data_route((uint8_t *)&NbAppFrame, len);
- }
- void nb_set_rtc_data_ack(int8_t ret)
- {
- // NbBuildSetDateTimeRsp(ret);
- nb_set_para_rept(5, 0x23, ret);
- }
- void nb_set_flow_alarm_para_ack(int8_t ret)
- {
- // NbBuildSetFlowAlarmThresRsp(ret);
- nb_set_para_rept(5, 0x24, ret);
- uint16_t len = ((NbAppFrame.len[1] << 8) | NbAppFrame.len[0]) + 16;
- nb_send_data_route((uint8_t *)&NbAppFrame, len);
- }
- void nb_set_pressure_alarm_para_ack(int8_t ret)
- {
- // NbBuildSetPressureAlarmThresRsp(ret);
- nb_set_para_rept(5, 0x25, ret);
- }
- void nb_set_temp_alarm_para_ack(int8_t ret)
- {
- // NbBuildSetTempAlarmThresRsp(ret);
- nb_set_para_rept(5, 0x26, ret);
- }
- void nb_set_settlment_day_para_ack(int8_t ret)
- {
- // NbBuildSetSettleRsp(ret);
- nb_set_para_rept(5, 0x27, ret);
- }
- void nb_set_meter_bottom_data_ack(int8_t ret)
- {
- // NbBuildSetBaseReadingRsp(ret);
- nb_set_para_rept(5, 0x28, ret);
- }
- void nb_read_month_record_ack(void)
- {
- NbBuildReportMonthRecord();
- }
- void nb_read_day_record_ack(void)
- {
- NbBuildReportDayRecord();
- }
- int8_t nb_read_hour_record_ack(void)
- {
- uint32_t start, end, ndate;
- uint8_t loop_count = 0; // 用于限制循环次数
- start = (NbAppFrame.data[5] << 16) | (NbAppFrame.data[6] << 8) | NbAppFrame.data[7];
- end = (NbAppFrame.data[9] << 16) | (NbAppFrame.data[10] << 8) | NbAppFrame.data[11];
- rtc_run_t *rr;
- get_rtc_run(&rr); // 获取当前时间
- ndate = (rr->year << 16) | (rr->month << 8) | rr->day;
- // 计算30天前的日期边界
- uint32_t b30date = ndate;
- for (uint8_t i = 0; i < 30; i++)
- b30date = prev_day(b30date);
- // --- 修改部分开始 ---
- // 原逻辑:如果时间不合法,直接返回 -1
- // 新逻辑:如果时间不合法,构建一个长度为248且数据全为0的帧发送一次
- // 检查合法性
- uint8_t is_invalid = 0;
- if (start > ndate || end < b30date || start > end)
- {
- is_invalid = 1;
- }
- // 校正 start
- if (start < b30date)
- start = b30date;
- // 校正 end
- if (end > ndate)
- end = ndate;
- // 再次检查校正后是否合法
- if (start > end)
- {
- is_invalid = 1;
- }
- if (is_invalid)
- {
- uint16_t mid = (NbAppFrame.data[3] << 8) | NbAppFrame.data[2];
- // 定义正常的数据长度 (参考 NbBuildReportHourRecord)
- uint16_t data_len = 248;
- // 构建帧头
- NbBuildDataHeader(data_len);
- // 设置 AFN 为 0x34 (Read Hour Record Response)
- NbAppFrame.data[0] = 0x34;
- NbAppFrame.data[1] = 0x00;
- // 设置 MID
- NbAppFrame.data[2] = (uint8_t)(mid);
- NbAppFrame.data[3] = (uint8_t)(mid >> 8);
- // 将数据区域全部清零 (NbBuildDataHeader 不会自动清零 data 区域,需手动处理)
- // 注意:NbAppFrame.data 的大小通常足够容纳 248 字节
- memset(&NbAppFrame.data[4], 0, data_len);
- // 构建帧尾 (包含校验和)
- NbBuildDataTail(data_len);
- uint16_t len = ((NbAppFrame.len[1] << 8) | NbAppFrame.len[0]) + 16;
- nb_send_data_route((uint8_t *)&NbAppFrame, len);
- // 发送 AT 命令
- if (at_cmd_send(COAP_QLWDATASEND, (char *)NbRun.tx_buf, NB_AT_ACK, 3, 60) == -1)
- return -1;
- return 0; // 返回成功,表示已处理本次请求
- }
- // --- 修改部分结束 ---
- ndate = start;
- uint16_t len;
- // 无限循环处理所有有效日期,但限制 loop_count < 12 以防死循环或数据过多
- while (ndate <= end && loop_count < 12)
- {
- NbBuildReportHourRecord((uint8_t)(ndate >> 16), (uint8_t)(ndate >> 8), (uint8_t)(ndate));
- len = ((NbAppFrame.len[1] << 8) | NbAppFrame.len[0]) + 16;
- nb_send_data_route((uint8_t *)&NbAppFrame, len);
- if (at_cmd_send(COAP_QLWDATASEND, (char *)NbRun.tx_buf, NB_AT_ACK, 3, 60) == -1)
- return -1;
- ndate = next_day(ndate);
- loop_count++; // 增加计数器
- }
- return 0;
- }
- int8_t nb_read_5min_record_ack(void)
- {
- // 将大型局部变量改为静态变量,以减少栈使用
- static tm_t start, end, cur;
- static tm_t now_tm, limit_start_tm;
- uint16_t len;
- uint8_t loop_count = 0; // ?
- // 1. е????
- start.year = NbAppFrame.data[5];
- start.month = NbAppFrame.data[6];
- start.day = NbAppFrame.data[7];
- start.hour = NbAppFrame.data[8];
- start.min = NbAppFrame.data[9];
- start.sec = 0;
- end.year = NbAppFrame.data[11];
- end.month = NbAppFrame.data[12];
- end.day = NbAppFrame.data[13];
- end.hour = NbAppFrame.data[14];
- end.min = NbAppFrame.data[15];
- end.sec = 0;
- // 2. ????15??
- rtc_run_t *rr;
- get_rtc_run(&rr);
- // ?? tm_t (??)
- now_tm.year = rr->year;
- now_tm.month = rr->month;
- now_tm.day = rr->day;
- now_tm.hour = rr->hour;
- now_tm.min = rr->minute;
- now_tm.sec = rr->second;
- // 15???
- uint32_t date32 = (rr->year << 16) | (rr->month << 8) | rr->day;
- for (uint8_t i = 0; i < 15; i++)
- {
- date32 = prev_day(date32);
- }
- limit_start_tm.year = (date32 >> 16) & 0xFF;
- limit_start_tm.month = (date32 >> 8) & 0xFF;
- limit_start_tm.day = date32 & 0xFF;
- limit_start_tm.hour = 0;
- limit_start_tm.min = 0;
- limit_start_tm.sec = 0;
- // 3. ??: start ? end
- uint8_t is_invalid = 0;
- if (datecmp(start, end) > 0)
- {
- is_invalid = 1;
- }
- // 4. ?Ч??Χ
- // ЧΧ: [limit_start_tm, now_tm]
- if (datecmp(end, limit_start_tm) < 0) // ?15?
- {
- is_invalid = 1;
- }
- if (datecmp(start, now_tm) > 0) // ?????
- {
- is_invalid = 1;
- }
- // 5. У start end ЧΧ
- if (datecmp(start, limit_start_tm) < 0)
- {
- start = limit_start_tm;
- }
- // if (datecmp(end, now_tm) > 0)//允许终止时间大于当前时间
- //{
- // end = now_tm;
- // }
- // ?μУ?
- if (datecmp(start, end) > 0)
- {
- is_invalid = 1;
- }
- // --- ???? ---
- // ????388??0??
- if (is_invalid)
- {
- uint16_t mid = (NbAppFrame.data[3] << 8) | NbAppFrame.data[2];
- //
- uint16_t data_len = 388;
- // ??
- NbBuildDataHeader(data_len);
- // AFN ? 0x37 (Read 5Min Record Response)
- NbAppFrame.data[0] = 0x37;
- NbAppFrame.data[1] = 0x00;
- // MID
- NbAppFrame.data[2] = (uint8_t)(mid);
- NbAppFrame.data[3] = (uint8_t)(mid >> 8);
- // ? (NbBuildDataHeader ? data ?)
- // ??NbAppFrame.data ?С? 388 ?
- memset(&NbAppFrame.data[4], 0, data_len);
- // ?β (У)
- NbBuildDataTail(data_len);
- len = ((NbAppFrame.len[1] << 8) | NbAppFrame.len[0]) + 16;
- nb_send_data_route((uint8_t *)&NbAppFrame, len);
- // AT
- if (at_cmd_send(COAP_QLWDATASEND, (char *)NbRun.tx_buf, NB_AT_ACK, 3, 60) == -1)
- return -1;
- return 0; // ????
- }
- // --- ??? ---
- // 6. ??12
- cur = start; // 初始化 cur
- while (datecmp(cur, end) < 0) // ? while ???м
- {
- // ?
- if (loop_count >= 12)
- {
- break;
- }
- NbBuildReport5MinRecord(&cur);
- len = ((NbAppFrame.len[1] << 8) | NbAppFrame.len[0]) + 16;
- nb_send_data_route((uint8_t *)&NbAppFrame, len);
- if (at_cmd_send(COAP_QLWDATASEND, (char *)NbRun.tx_buf, NB_AT_ACK, 3, 60) == -1)
- return -1;
- // 2С?
- time_add_secs(&cur, &cur, 2 * 60 * 60);
- loop_count++; // ?
- }
- return 0;
- }
- void nb_read_log_record_ack(void)
- {
- NbBuildReportLogRecord();
- }
- /////// 设置开始升级信息/////////////////////
- /// 返回 1:成功 2:版本号不对 3:长度超限
- int8_t nb_set_patch_info(void)
- {
- PATCH_INFO_DEF dat;
- uint8_t *src = &NbAppFrame.data[4];
- memcpy(dat.cur_ver, src, 5);
- memcpy(dat.new_ver, src + 5, 5);
- dat.patch_len = src[10] + ((uint16_t)src[11] << 8) + ((uint32_t)src[12] << 16) + ((uint32_t)src[13] << 24);
- dat.per_packet_len = src[14] + 256 * src[15];
- dat.packet_crc = src[16] + 256 * src[17];
- uint8_t ret = set_patch_info(&dat); // 返回1,2,3 //1成功
- // if(ret != 0)return -1;
- // else return 0;
- return ret;
- }
- ////////////////////////////////////
- // 1.升级成功结束
- // 2:升级失败,crc校验失败
- // 3.升级失败,多次尝试未获得升级包
- // 4.失败,未能成功运行
- // 5.失败版本不匹配
- // 0x10:重新读取本包数据
- // 0x20:获取下一包
- ///////////////////////////////////
- void nb_set_patch_info_ack(int8_t stat)
- {
- // if(stat>=1 && stat <= 6 ){
- if (stat <= 3)
- NbBuildReportUpdateStatus(stat);
- //}
- else // if(stat == 0x10){
- NbBuildGetPackage();
- //}
- // else if(stat == 0x20){
- // NbBuildGetPackage();
- // }
- }
- /////////////在采样中断结束,刚好允许进入低功耗时发送指令,避免接收失败//////////////////////
- // dat:要发送的数据
- ////////////////////////////////////
- // uint8_t NB_CHECK_TDC_COMPLETE_FLAG
- // check G_TDC_CAN_DEEP_SLEEP 0->1
- void send_nb_data_after_sample(char *dat)
- {
- extern uint8_t rtc_1s_flag;
- if (NB_CHECK_TDC_COMPLETE_FLAG == 1 && rtc_1s_flag == 1)
- {
- nb_tx_str(dat);
- rtc_1s_flag = 0;
- }
- NB_CHECK_TDC_COMPLETE_FLAG = 0;
- }
- int8_t rec_data_check(void)
- {
- // 1. 主动请求数据
- send_nb_data_after_sample("AT+QIRD=0,1500\r\n"); // 读取数据,最长1500 tcp限制
- // 2. 尝试解析数据
- uint8_t result = NbRcvDataValid();
- // --- 情况 A: 没有收到完整数据或正在等待 ---
- if (result == 0)
- {
- // 如果是 OTA 过程,允许较长的等待时间
- if (NbRun.cur_afn == 0x50 || NbRun.cur_afn == 0x51)
- {
- NbRun.get_patch_time_out++;
- if (NbRun.get_patch_time_out < 120) // 约 5-10秒
- return 1; // 继续等待
- else
- return -1; // OTA 超时
- }
- return 1; // 普通命令继续等待
- }
- // --- 情况 B: 数据校验失败 (格式错误、CS错误等) ---
- if (result > 1)
- {
- #ifdef DEBUG_NB
- LOG("Rcv Err: %d\r\n", result);
- #endif
- // 收到垃圾数据,清除状态,让上层循环重试 AT+NMGR
- // 返回 1 表示“本次尝试失败,请重试”,而不是“继续等待当前缓冲”
- return 1;
- }
- // --- 情况 C: 数据校验成功 (result == 1) ---
- NbRun.get_patch_time_out = 0; // 重置 OTA 超时计数
- uint16_t afn = (NbAppFrame.data[1] << 8) | NbAppFrame.data[0];
- uint16_t data_len = (NbAppFrame.len[1] << 8) | NbAppFrame.len[0];
- // 更新当前 AFN 状态,用于后续多包交互(如 OTA)
- if (afn != 0x51)
- { // 数据包通常不改变 cur_afn,除非是第一个包
- NbRun.cur_afn = afn;
- }
- int8_t ret = 0;
- uint8_t need_reply = 0; // 标记是否需要发送应用层回复
- uint8_t update_status = 0;
- #ifdef DEBUG_NB
- LOG("Rec OK, AFN=0x%04X, Len=%d\r\n", afn, data_len);
- #endif
- // --- 业务逻辑分发 ---
- switch (afn)
- {
- case 0x20: // Set IP/Port
- if (data_len != 16)
- return 1;
- ret = set_server_ip_port_para((SERVER_IP_PORT_DEF *)&NbAppFrame.data[4]);
- nb_set_ip_para_ack();
- need_reply = 1;
- break;
- case 0x21: // Set Regular Report
- if (data_len != 9)
- return 1;
- {
- REGULAR_REPORT_DEF dat;
- dat.report_base_hour = NbAppFrame.data[4];
- dat.report_base_min = NbAppFrame.data[5];
- dat.report_base_sec = NbAppFrame.data[6];
- dat.report_interval = NbAppFrame.data[7] + 256 * NbAppFrame.data[8];
- ret = set_regular_report_para(&dat);
- }
- nb_set_regular_report_para_ack(ret == 0 ? 1 : ret);
- need_reply = 1;
- break;
- case 0x22: // Set DMA Report
- if (data_len != 11)
- return 1;
- {
- DMA_REGULAR_REPORT_DEF dat;
- dat.dma_report_start_hour = NbAppFrame.data[4];
- dat.dma_report_start_min = NbAppFrame.data[5];
- dat.dma_report_start_sec = NbAppFrame.data[6];
- dat.dma_report_end_hour = NbAppFrame.data[7];
- dat.dma_report_end_min = NbAppFrame.data[8];
- dat.dma_report_end_sec = NbAppFrame.data[9];
- dat.dma_interval = NbAppFrame.data[10];
- ret = set_dma_regular_report_para(&dat);
- }
- nb_set_dma_report_para_ack(ret == 0 ? 1 : ret);
- need_reply = 1;
- break;
- case 0x23: // Set RTC
- if (data_len != 11)
- return 1;
- {
- tm_t tm;
- // tm.year = ((NbAppFrame.data[4] << 8) | NbAppFrame.data[5]) % 2000;
- tm.year = NbAppFrame.data[5];
- tm.month = NbAppFrame.data[6];
- tm.day = NbAppFrame.data[7];
- tm.hour = NbAppFrame.data[8];
- tm.min = NbAppFrame.data[9];
- tm.sec = NbAppFrame.data[10];
- ret = SetRtcTime(&tm);
- }
- save_cur_flow_flag = 1;
- nb_set_rtc_data_ack(ret);
- need_reply = 1;
- break;
- case 0x24: // Set Flow Alarm
- if (data_len != 18)
- return 1;
- {
- FLOW_ALARM_PARA_DEF flow_alarm_para;
- flow_alarm_para.large_flow_alarm_thres = (NbAppFrame.data[7] << 24) | (NbAppFrame.data[6] << 16) | (NbAppFrame.data[5] << 8) | NbAppFrame.data[4];
- flow_alarm_para.large_flow_cnti_moni_time = (NbAppFrame.data[9] << 8) | NbAppFrame.data[8];
- flow_alarm_para.cnti_flow_cnti_moni_time = (NbAppFrame.data[11] << 8) | NbAppFrame.data[10];
- flow_alarm_para.leak_flow_alarm_thres = (NbAppFrame.data[15] << 24) | (NbAppFrame.data[14] << 16) | (NbAppFrame.data[13] << 8) | NbAppFrame.data[12];
- flow_alarm_para.leak_flow_cnti_moni_time = (NbAppFrame.data[17] << 8) | NbAppFrame.data[16];
- ret = set_flow_alarm_para(&flow_alarm_para);
- }
- nb_set_flow_alarm_para_ack(ret == 0 ? 1 : ret);
- need_reply = 1;
- break;
- case 0x25: // Set Press Alarm
- if (data_len != 6)
- return 1;
- ret = set_press_alarm_para((PRESS_ALARM_PARA_DEF *)&NbAppFrame.data[4]);
- nb_set_pressure_alarm_para_ack(ret == 0 ? 1 : ret);
- need_reply = 1;
- break;
- case 0x26: // Set Temp Alarm
- if (data_len != 8)
- return 1;
- ret = set_temp_alarm_para((TEMP_ALARM_PARA_DEF *)&NbAppFrame.data[4]);
- nb_set_temp_alarm_para_ack(ret == 0 ? 1 : ret);
- need_reply = 1;
- break;
- case 0x27: // Set Settlement Day
- if (data_len != 5)
- return 1;
- ret = set_settlement_day_para((SETTLEMENT_DAY_DEF *)&NbAppFrame.data[4]);
- nb_set_settlment_day_para_ack(ret == 0 ? 1 : ret);
- need_reply = 1;
- break;
- case 0x28: // Set Bottom Data
- if (data_len != 12)
- return 1;
- ret = set_meter_bottom_data((METER_BOTTOM_DEF *)&NbAppFrame.data[4]);
- nb_set_meter_bottom_data_ack(ret == 0 ? 1 : ret);
- need_reply = 1;
- break;
- case 0x30: // Read Month Record
- nb_read_month_record_ack();
- need_reply = 1;
- break;
- case 0x32: // Read Day Record
- nb_read_day_record_ack();
- need_reply = 1;
- break;
- case 0x34: // Read Hour Record
- // 注意:nb_read_hour_record_ack 内部已经完成了所有分包发送和 AT 交互
- ret = nb_read_hour_record_ack();
- if (ret == -1)
- {
- LOG("Read Hour Err\r\n");
- return -1; // 严重错误,退出上传会话
- }
- // 内部已处理完毕,不需要再执行底部的通用回复逻辑
- return 0;
- case 0x36: // Read 5Min Record
- ret = nb_read_5min_record_ack();
- if (ret == -1)
- {
- LOG("Read 5Min Err\r\n");
- return -1;
- }
- // 内部已处理完毕
- return 0;
- case 0x38: // Read Log
- nb_read_log_record_ack();
- need_reply = 1;
- break;
- case 0x40: // Close Link
- LOG("Close Link\r\n");
- return 2; // 特殊返回码,指示关闭链接
- case 0x50: // OTA Start
- if (data_len != 22)
- return 1;
- ret = nb_set_patch_info();
- if (ret != 1)
- {
- nb_set_patch_info_ack(ret);
- need_reply = 1;
- }
- else
- {
- NbRun.mid = (NbAppFrame.data[3] << 8) | NbAppFrame.data[2];
- nb_set_patch_info_ack(0x10); // Request first package
- need_reply = 1;
- }
- NbRun.get_patch_retry_cnt = 0;
- break;
- case 0x51: // OTA Data Package
- // 检查数据长度是否匹配预期
- if (data_len != (8 + PatchInfo.per_packet_len))
- {
- update_status = 0x20; // Resend request
- }
- else
- {
- DIFF_PACKET_DEF *dat = (DIFF_PACKET_DEF *)&NbAppFrame.data[4];
- ret = write_diff_patch_to_flash(dat);
- if (ret == 1)
- { // Success
- NbRun.get_patch_retry_cnt = 0;
- if (PatchInfo.update_status == 1)
- {
- update_status = 0x10; // Request next
- }
- else
- {
- update_status = 1; // Finish
- }
- }
- else
- {
- update_status = ret; // Error code
- }
- }
- // 重试计数逻辑
- if (update_status == 0x10 || update_status == 1)
- {
- NbRun.get_patch_retry_cnt = 0;
- }
- else
- {
- NbRun.get_patch_retry_cnt++;
- }
- if (NbRun.get_patch_retry_cnt > 20)
- {
- update_status = 3; // Fail
- }
- if (update_status <= 3)
- {
- NbRun.cur_afn = 0; // Reset AFN after handling packet
- }
- nb_set_patch_info_ack(update_status);
- need_reply = 1;
- if (update_status >= 1 && update_status <= 6)
- {
- // OTA finished or failed, will return 2 later
- }
- break;
- default:
- LOG("Unknown AFN: 0x%04X\r\n", afn);
- return 1; // Ignore unknown, wait for next
- }
- // --- 发送应用层回复 ---
- if (need_reply == 1)
- {
- uint16_t len = ((NbAppFrame.len[1] << 8) | NbAppFrame.len[0]) + 16;
- nb_send_data_route((uint8_t *)&NbAppFrame, len);
- // 发送 AT 指令并将数据发往网络
- ret = at_cmd_send(55, (char *)NbRun.tx_buf, NB_AT_ACK, 6, 5);
- if (ret == -1)
- {
- return -1; // Send failed
- }
- // 如果是 OTA 结束状态,返回 2 以退出循环
- if (afn == 0x51 && (update_status >= 1 && update_status <= 6))
- {
- return 2;
- }
- return 0; // Success
- }
- return 1; // Should not reach here if logic is correct
- }
- void rtc_add_secs(TIME_DEF *dest, rtc_run_t *src, unsigned short secs)
- {
- unsigned short dat;
- // dat=secs;
- dest->second = (src->second + dat) % 60;
- dat = (src->second + dat) / 60;
- dest->minute = (src->minute + dat) % 60;
- dat = (src->minute + dat) / 60;
- dest->hour = (dat + src->hour) % 24;
- }
- uint8_t connected_flag;
- void NbTread(void)
- {
- uint32_t retry_time;
- uint8_t vflag = 0;
- uint16_t len;
- uint8_t ncnt;
- char ncdp_str[64];
- uint8_t npos;
- //////////////读取ID等初始化流程/////////////////////////////////////////
- G_NB_CAN_DEEP_SLEEP = 0; // 不允许休眠
- nb_power_on(0);
- rt_thread_mdelay(2000);
- do
- {
- npos = 0;
- if (at_cmd_send(npos++, NB_AT, NB_AT_ACK, 10, 2) == -1)
- break; //
- if (at_cmd_send(npos++, NB_ATE0, NB_ATE0_ACK, 3, 2) == -1) // 关闭回显
- break;
- /////////////设置频段//////////////////////////
- ncnt = Paramx.nb_band_flag;
- /////////////设置频段//////////////////////////
- if (ncnt != 2)
- {
- if (ncnt > 2)
- {
- ncnt = 0;
- }
- if (ncnt == 0)
- {
- if (at_cmd_send(npos++, "AT+QCFG=\"band\",0,0x10,0,1\r\n", NB_AT_ACK, 3, 5) == -1)
- break;
- }
- if (ncnt == 1)
- {
- if (at_cmd_send(npos++, "AT+QCFG=\"band\",0,0x008800D5,0,1\r\n", NB_AT_ACK, 3, 5) == -1)
- break;
- }
- ncnt++;
- set_nb_band(ncnt);
- if (at_cmd_send(1, NB_CFUN0, NB_AT_ACK, 3, 3) == -1)
- break;
- rt_thread_mdelay(1000);
- if (at_cmd_send(1, NB_CFUN1, NB_AT_ACK, 3, 3) == -1)
- break;
- rt_thread_mdelay(1200);
- }
- //////////////////////////////////////////
- // if (at_cmd_send(1, NB_CFUN0, NB_AT_ACK, 3, 2) == -1)
- // break;
- // rt_thread_mdelay(1000);
- // if (at_cmd_send(1, NB_CFUN1, NB_AT_ACK, 3, 3) == -1)
- // break;
- // rt_thread_mdelay(1200);
- if (at_cmd_send(npos++, NB_CGSN, NB_CGSN_ACK, 3, 2) == -1)
- break;
- get_nb_imei_code();
- if (at_cmd_send(npos++, NB_CIMI, NB_AT_ACK, 3, 2) == -1)
- break;
- get_nb_imsi_code();
- if (at_cmd_send(npos++, NB_NCCID, NB_NCCID_ACK, 3, 2) == -1) // different from BC28
- break;
- get_nb_ccid_code();
- } while (0);
- nb_power_off();
- //////////////////////////////////////////////////////////////////
- // G_NB_CAN_DEEP_SLEEP = 1;//允许休眠
- while (1)
- {
- G_NB_CAN_DEEP_SLEEP = 1; // 允许休眠
- rt_sem_take(Nb_thread_run_sem, RT_WAITING_FOREVER); // 等信号量
- npos = 0;
- // #ifdef DEBUG_NB
- #ifdef APP_DEBUG_PRINT
- LOG("upload_begin type: %s\r\n", get_upload_type_str(NbRun.upload.mode));
- if (NbRun.upload.mode & 0x10)
- LOG("error_code = %X\r\n", upload_dat.err_mem_dat);
- #endif
- // #endif
- // 既不是定时上报,也不是重复上报,并且没有子服务,也没有主服务,则跳过
- if ((NbRun.upload.mode & (NB_UPLOAD_TIMER | NB_UPLOAD_REPT)) == 0 && check_sub_service_flag() == 0 && check_main_service_flag() == 0)
- {
- NbRun.upload.flag = 0;
- NbRun.upload.mode = 0; // 本次上传结束后清零
- LOG("no service upload!\r\n");
- continue;
- }
- G_NB_CAN_DEEP_SLEEP = 0; // 不允许休眠
- nb_power_on(0);
- rt_thread_mdelay(1000);
- do
- {
- if (at_cmd_send(npos++, NB_AT, NB_AT_ACK, 10, 2) == -1) // at测试
- break;
- if (at_cmd_send(npos++, NB_ATE0, NB_ATE0_ACK, 3, 2) == -1) // 关闭回显
- break;
- if (at_cmd_send(npos++, "AT+IPR=9600\r\n", NB_AT_ACK, 3, 2) == -1)
- break;
- nb_power_on(3);
- rt_thread_mdelay(500);
- if (NbRun.get_imei_flag == 0) // 读取imei号
- { // 读取IMEI号
- if (at_cmd_send(npos++, NB_CGSN, NB_CGSN_ACK, 3, 2) == -1)
- break;
- get_nb_imei_code();
- }
- npos = 5;
- if (at_cmd_send(npos++, NB_CMEE1, NB_CMEE_ACK, 3, 2) == -1) // 错误上报方式 BC800需要
- break;
- retry_time = 0;
- vflag = 1;
- while (at_cmd_send(npos, "AT+CPIN?\r\n", "+CPIN: READY", 3, 3) == -1)
- {
- retry_time++;
- if (retry_time > 3)
- {
- vflag = 0;
- break;
- }
- if (at_cmd_send(npos + 1, NB_CFUN0, NB_AT_ACK, 3, 2) == -1)
- {
- vflag = 0;
- break;
- } // FUN0格式
- rt_thread_mdelay(1000);
- if (at_cmd_send(npos + 2, NB_CFUN1, NB_AT_ACK, 3, 3) == -1) // 设置最大模式,开始搜网
- {
- vflag = 0;
- break;
- }
- rt_thread_mdelay(1200);
- }
- npos += 3;
- if (vflag == 0)
- break;
- if (NbRun.get_ccid_flag == 0) // 读取ccid号
- { // 读取ccid号
- ncnt = 0;
- if (at_cmd_send(npos, NB_NCCID, NB_NCCID_ACK, 3, 2) == -1)
- {
- break;
- }
- get_nb_ccid_code();
- }
- npos++;
- if (NbRun.get_imsi_flag == 0) // 读取imsi号
- { // 读取imsi号
- if (at_cmd_send(npos, NB_CIMI, NB_AT_ACK, 3, 2) == -1)
- break;
- get_nb_imsi_code();
- }
- npos++;
- if (at_cmd_send(npos++, "AT+COPS=0\r\n", NB_AT_ACK, 3, 2) == -1) // 自动选择网络
- break;
- rt_thread_mdelay(500);
- retry_time = 0;
- while (1)
- { // 内循环判断
- if (retry_time >= 3) // 已经3个循环结束
- {
- vflag = 0;
- break;
- }
- else if (retry_time != 0) // 首次进入不复位
- {
- if (at_cmd_send(npos, NB_CFUN0, NB_AT_ACK, 3, 2) == -1)
- break; // FUN0格式
- rt_thread_mdelay(1000);
- if (at_cmd_send(npos + 1, NB_CFUN1, NB_AT_ACK, 3, 3) == -1) // 设置最大模式,开始搜网
- break;
- rt_thread_mdelay(1200);
- }
- 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域附着
- {
- retry_time++; // 重试次数
- continue;
- } // 状态值1/5都属于正常
- if (at_cmd_send(npos + 3, NB_CGATT, NB_CGATT_ACK, 3, 2) == -1) // PS域附着
- break;
- // retry_time = 0;
- if (at_cmd_send(npos + 4, NB_CGATT_QUERY, NB_CGATT_QUERY_ACK, 20, 2) == -1)
- { // 查询附着状态
- retry_time++; // 重试次数
- continue; // 重新注册
- }
- vflag = 1;
- break;
- }
- npos += 5;
- if (vflag == 0)
- break; // 失败后退出的循环
- vflag = 0;
- // if (at_cmd_send(14, NB_CSQ, NB_CSQ_ACK, 3, 2) == -1) // 查询无线信号强度 BC800有
- // break;
- // get_nb_csq();
- ncnt = 5;
- vflag = 1;
- while (ncnt--) // 查询无线信号强度 EC800有
- {
- if (at_cmd_send(npos++, "AT+QENG=\"servingcell\"\r\n", "+QENG: \"servingcell\"", 3, 2) == -1)
- {
- vflag = 0;
- break;
- }
- if (get_nb_signal(NbRun.rx_buf, NbRun.rx_idx) == 1)
- break;
- rt_thread_mdelay(1000);
- }
- if (vflag == 0)
- break;
- vflag = 0;
- if (at_cmd_send(npos++, "AT+QICSGP=1,1,\"CTNET\",\"\",\"\",1\r\n", NB_AT_ACK, 3, 2) == -1) // 配置场景
- break;
- if (at_cmd_send(npos++, "AT+QIACT=1\r\n", NB_AT_ACK, 3, 3) == -1) // 激活场景
- break;
- if (at_cmd_send(npos++, "AT+QIACT?\r\n", "+QIACT: 1,1", 3, 3) == -1) // 查询场景激活状态
- break;
- #ifdef NB_AUTO_GET_NET_TIME
- if ((NbRun.upload.mode & NB_UPLOAD_TIMER) != 0)
- {
- if (at_cmd_send(npos, "AT+QNTP=1,\"202.112.10.36\",123\r\n", "+QNTP: 0,", 1, 15) == 0)
- {
- save_datetime_from_at(NbRun.rx_buf, NbRun.rx_idx);
- LOG("get net time!\t\n");
- }
- }
- #endif
- npos++;
- int16_t link_code;
- vflag = 0x80;
- //////////////////////////////////tcp主连接与发送数据////////////////////////////////////////
- if (((upload_dat.rept_addr & BIT0) != 0 || NbRun.upload.mode != NB_UPLOAD_REPT) && check_main_service_flag() == 1)
- {
- vflag &= 0x0f;
- do
- {
- #ifdef APP_DEBUG_PRINT
- LOG("main service upload\r\n");
- #endif
- vflag = 0;
- build_tcp_open_cmd(ncdp_str, //"AT+QIOPEN=1,0,\"TCP\",\"%d.%d.%d.%d\",%d,0,0\r\n", // 倒数第二个0:本地ip自动 最后一个0: 缓存模式
- Paramx.main_server_ip,
- // Paramx.main_server_ip[1],
- // Paramx.main_server_ip[2],
- // Paramx.main_server_ip[3],
- Paramx.main_server_port);
- if (at_cmd_send(npos, ncdp_str, "+QIOPEN: 0,", 2, 10) == -1) // 建立TCP连接,等待连接成功
- break;
- if (get_code(NbRun.rx_buf, "+QIOPEN: 0,", NbRun.rx_idx, &link_code) == -1)
- break;
- if (link_code != 0)
- break;
- // 发送数据,等待接收指令,收到指令后执行,超时退出
- nb_upload_data_ready();
- rt_thread_mdelay(100); // 准备上报数据
- if (at_cmd_send(npos + 1, (char *)NbRun.tx_buf, "SEND OK", 3, 3) == -1) // 发送上报数据
- break;
- vflag = 1; // 上报成功标志
- int8_t ret;
- retry_time = 120; // 12秒
- NbRun.cur_afn = 0;
- //////////////////////////////////////
- while (retry_time--)
- {
- ret = rec_data_check();
- rt_thread_mdelay(100);
- if (ret == 0)
- retry_time = 120; // 判断接收数据是否合法,以及读取协议层afn和长度,并回复
- else if (ret == -1 || ret == 2)
- break;
- }
- } while (0);
- at_cmd_send(npos + 2, "AT+QICLOSE=0\r\n", NB_AT_ACK, 3, 3); // 关闭tcpLINK
- }
- npos += 3;
- ////////////////////////////备用连接/////////////////////////////////////////////////////
- if (((upload_dat.rept_addr & BIT1) != 0 || NbRun.upload.mode != NB_UPLOAD_REPT) && check_sub_service_flag() == 1)
- {
- vflag &= 0x0f;
- do
- {
- #ifdef APP_DEBUG_PRINT
- LOG("sub service upload\r\n");
- #endif
- build_tcp_open_cmd(ncdp_str, //"AT+QIOPEN=1,0,\"TCP\",\"%d.%d.%d.%d\",%d,0,0\r\n", // 倒数第二个0:本地ip自动 最后一个0: 缓存模式
- Paramx.sub_server_ip, //[0],
- // Paramx.sub_server_ip[1],
- // Paramx.sub_server_ip[2],
- // Paramx.sub_server_ip[3],
- Paramx.sub_server_port);
- if (at_cmd_send(npos, ncdp_str, "+QIOPEN: 0,", 2, 10) == -1) // 建立TCP连接,等待连接成功
- break;
- if (get_code(NbRun.rx_buf, "+QIOPEN: 0,", NbRun.rx_idx, &link_code) == -1)
- break;
- if (link_code != 0)
- break;
- // 发送数据,等待接收指令,收到指令后执行,超时退出
- nb_upload_data_ready();
- rt_thread_mdelay(100); // 准备上报数据
- if (at_cmd_send(npos + 1, (char *)NbRun.tx_buf, "SEND OK", 3, 3) == -1) // 发送上报数据
- break;
- vflag |= 2; // 上报成功标志
- int8_t ret;
- retry_time = 120; // 12秒
- NbRun.cur_afn = 0;
- //////////////////////////////////////
- while (retry_time--)
- {
- ret = rec_data_check();
- rt_thread_mdelay(100);
- if (ret == 0)
- retry_time = 120; // 判断接收数据是否合法,以及读取协议层afn和长度,并回复
- else if (ret == -1 || ret == 2)
- break;
- }
- } while (0);
- at_cmd_send(npos + 2, "AT+QICLOSE=0\r\n", NB_AT_ACK, 3, 2); // 关闭tcpLINK
- }
- } while (0); // 主循环
- // NB_RUN_UPDATE_FLAG = 0;
- nb_power_off();
- if (vflag & 0x80)
- LOG("no service upload!\r\n");
- else if ((vflag & 3) != 0)
- {
- if ((vflag & BIT0) != 0)
- LOG("MAIN upload ok!\r\n");
- if ((vflag & BIT1) != 0)
- LOG("SUB upload ok!\r\n");
- }
- else if (vflag == 0)
- LOG("upload fail\r\n");
- if ((vflag & 3) != 3 && vflag != 0x80) // 有失败的情况
- { // 上报失败,补报判别
- if (NbRun.upload.mode & ~(NB_UPLOAD_REPT | NB_UPLOAD_DMA | NB_UPLOAD_MANUAL))
- { // 除补报,DMA,手动上报之外,其他需要补报
- upload_dat.rept_runflag = ((~vflag) & 0x3); // 补报
- upload_dat.rept_addr = upload_dat.rept_runflag;
- rtc_run_t *rr;
- get_rtc_run(&rr);
- tm_t ntm;
- ntm.year = rr->year;
- ntm.month = rr->month;
- ntm.day = rr->day;
- ntm.hour = rr->hour;
- ntm.min = rr->minute;
- ntm.sec = rr->second;
- time_add_secs(&upload_dat.rept_time, &ntm, 3600);
- }
- }
- // NbRun.void_load_timout = NB_VOID_UPLOAD_TIME;//这段时间不能上报60s
- NbRun.upload.flag = 0;
- NbRun.upload.mode = 0; // 本次上传结束后清零
- } // while(1)
- }
- /////////////添加上报过程中动态显示信号/////////////////////
- ////////////////////发送at指令并等待处理接收数据//////////////////////////////////////////////////////
- // stat:当前所在流程位置,和每个指令一一对应
- // cmd_str:at指令字符串
- // ack:要求本次回复的字符串
- // retry_time: 重试次数
- // time_out: 超时时间 秒单位
- // 成功:返回0 失败返回-1
- ///////////////////////////////////////////////////////////////////////////////////////////////////////
- int8_t at_cmd_send(uint8_t stat, char *cmd_str, char *ack, uint16_t retry_time, uint8_t time_out)
- {
- uint16_t retry = retry_time;
- uint16_t time_cnt;
- int8_t ret = 0;
- NbRun.cur_state = stat;
- NbRun.ack = ack;
- if (time_out > 250)
- time_out = 250; // 最大不超过25秒
- time_cnt = time_out * 10;
- ////////////
- // retry=250;
- //////////////
- // LOG("nbstat=%d\r\n",stat);
- while (retry--)
- {
- NbClrRxBuf();
- time_cnt = time_out * 10;
- nb_tx_str(cmd_str);
- while (--time_cnt)
- {
- if (Nb_rx_data() == 1)
- {
- // if (stat > COAP_CGATT_QUERY && stat < COAP_WAIT_REG)//EC800 不再需要了
- // {
- // if (memstr_exist(NbRun.rx_buf, NbRun.rx_idx, "+QLWEVTIND:3", 12) == 1)
- // {
- // connected_flag = 1;
- // }
- // }
- //////////////////////////////////////////////
- ret = Nb_check_rec_valid(stat, ack);
- if (ret == 1)
- {
- LOG(".");
- return 0;
- } // 收到正确的回复}
- else if (ret == -1)
- break;
- // else if(ret == 0)continue;
- }
- rt_thread_mdelay(NB_REC_DELAY_TICK); // 等100ms
- }
- if (time_cnt == 0)
- { // 超时未收到数据
- continue;
- }
- if (Nb_check_rec_valid(stat, ack) == TRUE)
- { // 检查是否收到正确回复
- return 0;
- }
- }
- return -1;
- }
- int8_t at_cmd_send2(uint8_t stat, char *cmd_str, char *ack1, char *ack2, uint16_t retry_time, uint8_t time_out)
- {
- uint16_t retry = retry_time;
- uint16_t time_cnt;
- int8_t ret1, ret2;
- NbRun.cur_state = stat;
- NbRun.ack = ack1;
- if (time_out > 250)
- time_out = 250; // 最大不超过25秒
- time_cnt = time_out * 10;
- ////////////
- // retry=250;
- //////////////
- // LOG("nbstat=%d\r\n",stat);
- while (retry--)
- {
- NbClrRxBuf();
- time_cnt = time_out * 10;
- nb_tx_str(cmd_str);
- while (--time_cnt)
- {
- if (Nb_rx_data() == 1)
- {
- ret1 = Nb_check_rec_valid(stat, ack1);
- if (ret1 == 1)
- {
- LOG(".");
- return 0;
- } // 收到正确的回复}
- ret2 = Nb_check_rec_valid(stat, ack2);
- if (ret2 == 1)
- {
- LOG(".");
- return 0;
- } // 收到正确的回复
- if (ret1 == -1 || ret2 == -1)
- break;
- // else if(ret == 0)continue;
- }
- rt_thread_mdelay(NB_REC_DELAY_TICK); // 等100ms
- }
- if (time_cnt == 0)
- { // 超时未收到数据
- continue;
- }
- if (Nb_check_rec_valid(stat, ack1) == TRUE)
- { // 检查是否收到正确回复
- return 0;
- }
- if (Nb_check_rec_valid(stat, ack2) == TRUE)
- { // 检查是否收到正确回复
- return 0;
- }
- }
- return -1;
- }
- static void BuildDataReportMeter(rtc_run_t *rr, uint8_t *data)
- {
- rtc_run_t *max_fr_rr;
- // total positive water
- uint32_t temp = (uint32_t)(FwCumFlow * 0.0001 + 0.5); // unit: 0.01m^3
- data[0] = (uint8_t)temp;
- data[1] = (uint8_t)(temp >> 8);
- data[2] = (uint8_t)(temp >> 16);
- data[3] = (uint8_t)(temp >> 24);
- // total reverse water
- temp = (uint32_t)(BwCumFlow * 0.0001 + 0.5); // unit: 0.01m^3
- data[4] = (uint8_t)temp;
- data[5] = (uint8_t)(temp >> 8);
- data[6] = (uint8_t)(temp >> 16);
- data[7] = (uint8_t)(temp >> 24);
- // Daily maximum flow rate
- temp = (uint32_t)(get_max_flow_rate() * 1000); // 3位小数点
- #ifdef DEBUG_NB
- // temp = 12345;
- #endif
- data[8] = (uint8_t)(temp);
- data[9] = (uint8_t)(temp >> 8);
- data[10] = (uint8_t)(temp >> 16);
- data[11] = (uint8_t)(temp >> 24);
- // Daily maximum flow rate time
- get_max_flow_rate_time(&max_fr_rr);
- if (max_fr_rr == NULL || max_fr_rr->year == 0 || max_fr_rr->month == 0 || max_fr_rr->day == 0)
- memset(&data[12], 0, 7);
- else
- {
- data[12] = 0x14;
- data[13] = max_fr_rr->year;
- data[14] = max_fr_rr->month;
- data[15] = max_fr_rr->day;
- data[16] = max_fr_rr->hour;
- data[17] = max_fr_rr->minute;
- data[18] = max_fr_rr->second;
- }
- #ifdef DEBUG_NB
- // data[13] = 26;
- // data[14] = 3;
- // data[15] = 31;
- // data[16] = 9;
- // data[17] = 30;
- // data[18] = 45;
- #endif
- // water temperature
- if (WaterTemp > 100.0f || WaterTemp < 0.0f)
- temp = 0x8000; // wxl 2026-5-22
- else
- temp = (uint32_t)(WaterTemp * 10 + 0.5);
- #ifdef DEBUG_NB
- // temp = -300;
- #endif
- data[19] = (uint8_t)(temp);
- data[20] = (uint8_t)(temp >> 8);
- // water pressure
- if (Paramx.pressure_sensor == 1)
- {
- data[21] = (uint8_t)(WaterPressure * 100);
- }
- else
- data[21] = 0;
- #ifdef DEBUG_NB
- // data[21]=213;
- #endif
- // battery voltage unit: 0.1V
- #if VER_MODULE == 3
- if (McuVbat > McuVTxbat)
- { // 判断哪个电池低就上传哪个数据
- temp = McuVTxbat / 100;
- }
- else
- temp = McuVbat / 100;
- #else
- temp = McuVbat / 100;
- #endif
- data[22] = (unsigned char)temp;
- data[23] = 0x14;
- data[24] = rr->year;
- data[25] = rr->month;
- data[26] = rr->day;
- data[27] = rr->hour;
- data[28] = rr->minute;
- data[29] = rr->second;
- }
- static void BuildDataReportParam(uint8_t *data)
- {
- Param_t *param;
- Nb_Run_t *nb_run;
- GetParam(¶m);
- GetNbRun(&nb_run);
- // version
- data[0] = 'V';
- data[1] = VER_TYPE;
- data[2] = VER_OPERATOR;
- data[3] = VER_MODULE;
- data[4] = VER_FIRMWARE;
- // diameter
- data[5] = (unsigned char)(param->diameter);
- data[6] = (unsigned char)(param->diameter >> 8);
- // channel number
- data[7] = param->chan_num;
- // main server ip
- data[8] = param->main_server_ip[0];
- data[9] = param->main_server_ip[1];
- data[10] = param->main_server_ip[2];
- data[11] = param->main_server_ip[3];
- // main server port
- data[12] = (unsigned char)(param->main_server_port);
- data[13] = (unsigned char)(param->main_server_port >> 8);
- // sub server ip
- data[14] = param->sub_server_ip[0];
- data[15] = param->sub_server_ip[1];
- data[16] = param->sub_server_ip[2];
- data[17] = param->sub_server_ip[3];
- // sub server port
- data[18] = (unsigned char)(param->sub_server_port);
- data[19] = (unsigned char)(param->sub_server_port >> 8);
- // report base time
- data[20] = param->report_base_hour;
- data[21] = param->report_base_min;
- data[22] = param->report_base_sec;
- // report interval minutes
- data[23] = (unsigned char)(param->report_interval);
- data[24] = (unsigned char)(param->report_interval >> 8);
- // DMA report start time
- data[25] = param->dma_report_start[0];
- data[26] = param->dma_report_start[1];
- data[27] = param->dma_report_start[2];
- // DMA report end time
- data[28] = param->dma_report_end[0];
- data[29] = param->dma_report_end[1];
- data[30] = param->dma_report_end[2];
- // DMA report interval time
- data[31] = param->dma_interval;
- // settlement day
- data[32] = param->settlement_day;
- // high temperature alarm threshold
- data[33] = (unsigned char)(param->high_temp_alarm_thres);
- data[34] = (unsigned char)(param->high_temp_alarm_thres >> 8);
- // low temperature alarm threshold
- data[35] = (unsigned char)(param->low_temp_alarm_thres);
- data[36] = (unsigned char)(param->low_temp_alarm_thres >> 8);
- // large flow alarm threshold
- data[37] = (unsigned char)(param->large_flow_alarm_thres);
- data[38] = (unsigned char)(param->large_flow_alarm_thres >> 8);
- data[39] = (unsigned char)(param->large_flow_alarm_thres >> 16);
- data[40] = (unsigned char)(param->large_flow_alarm_thres >> 24);
- // large flow continue monitor time
- data[41] = (unsigned char)(param->large_flow_cnti_moni_time);
- data[42] = (unsigned char)(param->large_flow_cnti_moni_time >> 8);
- // continue flow continue monitor time
- data[43] = (unsigned char)(param->cnti_flow_cnti_moni_time);
- data[44] = (unsigned char)(param->cnti_flow_cnti_moni_time >> 8);
- // leak flow alarm threshold
- data[45] = (unsigned char)(param->leak_flow_alarm_thres);
- data[46] = (unsigned char)(param->leak_flow_alarm_thres >> 8);
- data[47] = (unsigned char)(param->leak_flow_alarm_thres >> 16);
- data[48] = (unsigned char)(param->leak_flow_alarm_thres >> 24);
- // leak flow continue monitor time
- data[49] = (unsigned char)(param->leak_flow_cnti_moni_time);
- data[50] = (unsigned char)(param->leak_flow_cnti_moni_time >> 8);
- // high press alarm threshold
- data[51] = (unsigned char)(param->high_press_alarm_thres);
- // low press alarm threshold
- data[52] = (unsigned char)(param->low_press_alarm_thres);
- // pressure sensor
- data[53] = param->pressure_sensor;
- }
- static void BuildDataReportNb(uint8_t *data)
- {
- Nb_Run_t *nb_run;
- char tmp[3];
- uint16_t i;
- GetNbRun(&nb_run);
- // IMEI len = 8
- if (strlen(nb_run->imei) == 15)
- {
- tmp[0] = '0';
- tmp[1] = nb_run->imei[0];
- tmp[2] = 0;
- StrToHexBuf((char *)&data[0], tmp, 2);
- StrToHexBuf((char *)&data[1], &(nb_run->imei[1]), 14);
- }
- else
- {
- StrToHexBuf((char *)&data[0], tmp, 16);
- }
- // cell id in AT+NUESTATS response
- data[8] = (unsigned char)(nb_run->bts_id);
- data[9] = (unsigned char)(nb_run->bts_id >> 8);
- data[10] = (unsigned char)(nb_run->bts_id >> 16);
- data[11] = (unsigned char)(nb_run->bts_id >> 24);
- // physical cell id
- data[12] = (unsigned char)(nb_run->physical_cell_id);
- data[13] = (unsigned char)(nb_run->physical_cell_id >> 8);
- // rsrp
- data[14] = (unsigned char)(nb_run->rsrp_bak);
- data[15] = (unsigned char)(nb_run->rsrp_bak >> 8);
- // snr
- data[16] = (unsigned char)(nb_run->snr);
- data[17] = (unsigned char)(nb_run->snr >> 8);
- // csq
- data[18] = nb_run->rssi;
- // iccid len = 10
- for (i = 0; i < 10; i++)
- { // 这里是不是错了
- data[19 + i] = (unsigned char)(((nb_run->ccid[2 * i] - '0') << 4) | (nb_run->ccid[2 * i + 1] - '0'));
- }
- }
- static void BuildMonthRecord(rtc_run_t *rr, uint8_t *data)
- {
- uint32_t date = ((rr->year << 16) | (rr->month << 8));
- uint16_t i;
- bill_t bill;
- uint8_t vflag;
- for (i = 0; i < 2; i++)
- {
- date = prev_month(date);
- vflag = get_month_used_bill((uint8_t)(date >> 16), (uint8_t)(date >> 8), &bill);
- if (vflag != 0)
- continue; // no data
- data[i * 11] = 0x14;
- data[i * 11 + 1] = bill.date[0];
- data[i * 11 + 2] = bill.date[1];
- data[i * 11 + 3] = (unsigned char)(bill.fw_used);
- data[i * 11 + 4] = (unsigned char)(bill.fw_used >> 8);
- data[i * 11 + 5] = (unsigned char)(bill.fw_used >> 16);
- data[i * 11 + 6] = (unsigned char)(bill.fw_used >> 24);
- data[i * 11 + 7] = (unsigned char)(bill.bw_used);
- data[i * 11 + 8] = (unsigned char)(bill.bw_used >> 8);
- data[i * 11 + 9] = (unsigned char)(bill.bw_used >> 16);
- data[i * 11 + 10] = (unsigned char)(bill.bw_used >> 24);
- }
- }
- static void BuildDayRecord(rtc_run_t *rr, uint8_t *data)
- {
- uint16_t i;
- bill_t bill;
- uint32_t date = ((rr->year << 16) | (rr->month << 8) | rr->day);
- uint8_t vflag;
- for (i = 0; i < 5; i++)
- {
- date = prev_day(date);
- vflag = get_day_used_bill((uint8_t)(date >> 16), (uint8_t)(date >> 8), (uint8_t)date, &bill);
- if (vflag != 0)
- continue; // no data
- // if (bill.date[0] != (uint8_t)(date >> 16) || bill.date[1] != (uint8_t)(date >> 8) || bill.date[2] != (uint8_t)date)
- // continue; // 不是当天的数据
- data[i * 12] = 0x14;
- data[i * 12 + 1] = bill.date[0];
- data[i * 12 + 2] = bill.date[1];
- data[i * 12 + 3] = bill.date[2];
- data[i * 12 + 4] = (unsigned char)(bill.fw_used);
- data[i * 12 + 5] = (unsigned char)(bill.fw_used >> 8);
- data[i * 12 + 6] = (unsigned char)(bill.fw_used >> 16);
- data[i * 12 + 7] = (unsigned char)(bill.fw_used >> 24);
- data[i * 12 + 8] = (unsigned char)(bill.bw_used);
- data[i * 12 + 9] = (unsigned char)(bill.bw_used >> 8);
- data[i * 12 + 10] = (unsigned char)(bill.bw_used >> 16);
- data[i * 12 + 11] = (unsigned char)(bill.bw_used >> 24);
- }
- }
- static void BuildHourRecord(rtc_run_t *rr, uint8_t *data)
- {
- uint8_t i;
- hour_bill_t bill;
- uint8_t vflag;
- uint32_t date = ((rr->year << 16) | (rr->month << 8) | rr->day);
- date = prev_day(date);
- data[0] = 0x14;
- data[1] = (unsigned char)(date >> 16);
- data[2] = (unsigned char)(date >> 8);
- data[3] = (unsigned char)(date);
- for (i = 0; i < 24; i++)
- {
- vflag = get_hour_used_bill(data[1], data[2], data[3], i, &bill);
- if (vflag != 0) // 数据不合法,放弃
- continue;
- memcpy(&data[4 + i * 3], bill.fw_used, 3);
- memcpy(&data[4 + 72 + i * 3], bill.bw_used, 3);
- data[4 + 144 + i] = bill.pressure;
- memcpy(&data[4 + 168 + i * 3], bill.flow_rate, 3);
- }
- }
- void NbBuildDataReport(void)
- {
- rtc_run_t *rr;
- Nb_Run_t *nb_run;
- uint16_t data_len = 448;
- uint32_t *err_no;
- // current date time
- get_rtc_run(&rr);
- GetNbRun(&nb_run);
- NbBuildDataHeader(data_len);
- // AFN
- NbAppFrame.data[0] = 0x10;
- NbAppFrame.data[1] = 0x00;
- // MID
- NbAppFrame.data[2] = 0x00;
- NbAppFrame.data[3] = 0x00;
- // DC
- // report trigger mode
- NbAppFrame.data[4] = nb_run->upload.mode;
- BuildDataReportMeter(rr, &NbAppFrame.data[5]); // meter part len 30
- BuildDataReportParam(&NbAppFrame.data[35]); // param part len 54
- BuildDataReportNb(&NbAppFrame.data[89]); // nb part len 29
- BuildMonthRecord(rr, &NbAppFrame.data[118]); // month record part len 22
- BuildDayRecord(rr, &NbAppFrame.data[140]); // day record part len 60
- BuildHourRecord(rr, &NbAppFrame.data[200]); // day record part len 244
- // error no
- all_alarm_status(&err_no);
- //(*err_no) &= 0xffff0fff;
- NbAppFrame.data[444] = (uint8_t)(*err_no);
- NbAppFrame.data[445] = (uint8_t)(*err_no >> 8);
- NbAppFrame.data[446] = (uint8_t)(*err_no >> 16);
- NbAppFrame.data[447] = (uint8_t)(*err_no >> 24);
- NbBuildDataTail(data_len);
- }
- void nb_set_para_rept(uint16_t dat_len, uint16_t afn, int8_t ret)
- {
- // uint16_t data_len = 5;
- // uint16_t mid = (NbAppFrame.data[3] << 8) | NbAppFrame.data[2];
- NbBuildDataHeader(dat_len);
- // AFN
- NbAppFrame.data[0] = (uint8_t)afn;
- NbAppFrame.data[1] = (uint8_t)(afn >> 8);
- // MID
- // NbAppFrame.data[2] = (uint8_t)(mid);
- // NbAppFrame.data[3] = (uint8_t)(mid >> 8);
- NbAppFrame.data[4] = ret; // set success
- NbBuildDataTail(dat_len);
- }
- void NbBuildReportMonthRecord(void)
- {
- uint16_t data_len = 202;
- uint16_t mid = (NbAppFrame.data[3] << 8) | NbAppFrame.data[2];
- uint8_t ret;
- // rtc_run_t *rr;
- // get_rtc_run(&rr);
- NbBuildDataHeader(data_len);
- // AFN
- NbAppFrame.data[0] = 0x31;
- NbAppFrame.data[1] = 0x00;
- // MID
- NbAppFrame.data[2] = (uint8_t)(mid);
- NbAppFrame.data[3] = (uint8_t)(mid >> 8);
- uint8_t *data = &NbAppFrame.data[4];
- get_18month_record_data(data);
- NbBuildDataTail(data_len);
- }
- void NbBuildReportDayRecord(void)
- {
- uint16_t data_len = 364;
- uint16_t mid = (NbAppFrame.data[3] << 8) | NbAppFrame.data[2];
- uint8_t ret;
- NbBuildDataHeader(data_len);
- // AFN
- NbAppFrame.data[0] = 0x33;
- NbAppFrame.data[1] = 0x00;
- // MID
- NbAppFrame.data[2] = (uint8_t)(mid);
- NbAppFrame.data[3] = (uint8_t)(mid >> 8);
- uint8_t *data = &NbAppFrame.data[4];
- get_30day_record_data(data);
- NbBuildDataTail(data_len);
- }
- void NbBuildReportHourRecord(uint8_t year, uint8_t month, uint8_t day)
- {
- uint16_t data_len = 248;
- uint16_t mid = (NbAppFrame.data[3] << 8) | NbAppFrame.data[2];
- // rtc_run_t *rr;
- // get_rtc_run(&rr);
- NbBuildDataHeader(data_len);
- // AFN
- NbAppFrame.data[0] = 0x35;
- NbAppFrame.data[1] = 0x00;
- // MID
- NbAppFrame.data[2] = (uint8_t)(mid);
- NbAppFrame.data[3] = (uint8_t)(mid >> 8);
- uint8_t *data = &NbAppFrame.data[4];
- get_hour_record_data(year, month, day, data);
- NbBuildDataTail(data_len);
- }
- void NbBuildReport5MinRecord(tm_t *date)
- { // 年月日时分
- uint16_t data_len = 388;
- uint16_t mid = (NbAppFrame.data[3] << 8) | NbAppFrame.data[2];
- uint32_t i = 0;
- uint8_t ret;
- hour_bill_t bill;
- tm_t src;
- tm_t dest;
- NbBuildDataHeader(data_len);
- memset(NbAppFrame.data, 0, sizeof(NbAppFrame.data));
- // AFN
- NbAppFrame.data[0] = 0x37;
- NbAppFrame.data[1] = 0x00;
- // MID
- NbAppFrame.data[2] = (uint8_t)(mid);
- NbAppFrame.data[3] = (uint8_t)(mid >> 8);
- uint8_t *data = &NbAppFrame.data[4];
- GET_5MIN_REOCORD_DEF mdate;
- mdate.start_time[0] = date->year;
- mdate.start_time[1] = date->month;
- mdate.start_time[2] = date->day;
- mdate.start_time[3] = date->hour;
- mdate.start_time[4] = date->min;
- mdate.start_time[5] = date->sec;
- time_add_secs(&dest, date, 2 * 3600);
- mdate.end_time[0] = dest.year;
- mdate.end_time[1] = dest.month;
- mdate.end_time[2] = dest.day;
- mdate.end_time[3] = dest.hour;
- mdate.end_time[4] = dest.min;
- mdate.end_time[5] = dest.sec;
- get_5min_record_data(&mdate, 0, data);
- NbBuildDataTail(data_len);
- }
- void NbBuildReportLogRecord(void)
- {
- uint16_t data_len = 394;
- uint16_t mid = (NbAppFrame.data[3] << 8) | NbAppFrame.data[2];
- uint8_t i;
- int8_t j;
- uint8_t num = 0;
- alarm_t alarm;
- uint8_t rec_len = 13;
- NbBuildDataHeader(data_len);
- // AFN
- NbAppFrame.data[0] = 0x39;
- NbAppFrame.data[1] = 0x00;
- // MID
- NbAppFrame.data[2] = (uint8_t)(mid);
- NbAppFrame.data[3] = (uint8_t)(mid >> 8);
- uint8_t *data = &NbAppFrame.data[4];
- num = get_alarm_num();
- if (num > 30)
- {
- num = 30;
- }
- get_log_record(0, num, data);
- NbBuildDataTail(data_len);
- }
- void NbBuildGetPackage(void)
- {
- uint16_t data_len = 21;
- uint16_t mid = (NbAppFrame.data[3] << 8) | NbAppFrame.data[2];
- Param_t *param;
- NbBuildDataHeader(data_len);
- // AFN
- NbAppFrame.data[0] = 0x51;
- NbAppFrame.data[1] = 0x00;
- // MID
- NbAppFrame.data[2] = (uint8_t)(mid);
- NbAppFrame.data[3] = (uint8_t)(mid >> 8);
- GetParam(¶m);
- uint8_t *data = &NbAppFrame.data[4];
- data[0] = 'V';
- data[1] = VER_TYPE;
- data[2] = VER_OPERATOR;
- data[3] = VER_MODULE;
- data[4] = VER_FIRMWARE;
- data[5] = 'V';
- data[6] = VER_TYPE;
- data[7] = VER_OPERATOR;
- data[8] = VER_MODULE;
- data[9] = VER_FIRMWARE + 1;
- data[10] = (uint8_t)(PatchInfo.per_packet_len);
- data[11] = (uint8_t)(PatchInfo.per_packet_len >> 8);
- data[12] = (uint8_t)(PatchInfo.cur_num);
- data[13] = (uint8_t)(PatchInfo.cur_num >> 8);
- data[14] = (uint8_t)(PatchInfo.packet_crc);
- data[15] = (uint8_t)(PatchInfo.packet_crc >> 8);
- data[16] = 1;
- NbBuildDataTail(data_len);
- }
- void NbBuildReportUpdateStatus(int8_t stat)
- {
- uint16_t data_len = 5;
- uint16_t mid = NbRun.mid; //(NbAppFrame.data[3] << 8) | NbAppFrame.data[2];
- Param_t *param;
- NbBuildDataHeader(data_len);
- // AFN
- NbAppFrame.data[0] = 0x52;
- NbAppFrame.data[1] = 0x00;
- // MID
- NbAppFrame.data[2] = (uint8_t)(mid);
- NbAppFrame.data[3] = (uint8_t)(mid >> 8);
- NbAppFrame.data[4] = stat;
- NbBuildDataTail(data_len);
- }
- #ifdef DEBUG_LOG_WARM
- void Debug_log(void)
- {
- // #ifdef DEBUG_NB
- uint8_t i;
- for (i = 0; i < 32; i++)
- {
- write_alarm(i / 2, i % 2, i * 10 + 10);
- }
- // #endif
- }
- #endif
- #ifdef APP_DEBUG_PRINT
- static char str[50];
- char *get_upload_type_str(uint8_t type)
- {
- char cnt = 0;
- memset(str, 0, 50);
- if (type & 0x1)
- strcat(str, "manual,");
- if (type & 0x2)
- strcat(str, "regular,");
- if (type & 0x4)
- strcat(str, "rept,");
- if (type & 0x8)
- strcat(str, "settlement,");
- if (type & 0x10)
- strcat(str, "error,");
- if (type & 0x20)
- strcat(str, "dma");
- return str;
- }
- #endif
- uint8_t memstr_exist(uint8_t *hay, size_t hay_len, const char *sub, size_t sub_len)
- {
- if (sub_len == 0)
- return 1;
- if (sub_len > hay_len)
- return 0;
- for (size_t i = 0; i <= hay_len - sub_len; i++)
- {
- if (memcmp(hay + i, sub, sub_len) == 0)
- {
- return 1;
- }
- }
- return 0;
- }
- int8_t get_code(uint8_t *buf, const char *keyword, uint16_t dat_len, int16_t *ret)
- {
- char *pos;
- buf[dat_len] = 0;
- pos = strstr((char *)buf, keyword);
- if (pos == NULL)
- return -1;
- uint16_t dat = 0;
- uint16_t i;
- char vflag;
- pos = pos + strlen(keyword);
- vflag = 0;
- uint8_t flag = 0;
- if (*pos == '+' || *pos == '-')
- {
- if (*pos == '-')
- flag = 1;
- pos++;
- }
- while (*pos >= '0' && *pos <= '9')
- {
- dat *= 10;
- dat += *pos - '0';
- pos++;
- vflag = 1;
- }
- if (vflag == 0)
- return -1;
- if (flag == 1)
- dat = -dat;
- *ret = dat;
- return 1;
- }
- #ifdef NB_AUTO_GET_NET_TIME // 自动获取网络时间
- //+QNTP: 0,"2019/09/09,01:32:42+32"
- void save_datetime_from_at(uint8_t *buf, uint16_t dat_len)
- {
- tm_t tm;
- int16_t zone = 0;
- char *p;
- buf[dat_len] = 0; // 确保字符串终止
- p = strstr((char *)buf, "\""); // 定位到双引号开始处
- if (p == NULL)
- return;
- // 利用 sscanf 直接格式化提取年月日时分秒和时区
- // 格式: 2019/09/09,01:32:42+32
- if (sscanf(p + 1, "%hu/%hu/%hu,%u:%u:%u%hd",
- &tm.year, &tm.month, &tm.day,
- &tm.hour, &tm.min, &tm.sec, &zone) != 7)
- {
- return; // 解析失败或格式不匹配
- }
- // 合法性检查
- if (tm.year < 26 || tm.month == 0 || tm.month > 12 ||
- tm.day == 0 || tm.day > 31 || tm.hour > 23 || tm.min > 59 || tm.sec > 59)
- return;
- // 时区转换 (保留原逻辑:正负时区分别调用不同的时间计算函数)
- if (zone > 0)
- {
- time_add_secs(&tm, &tm, zone * 15 * 60);
- }
- else if (zone < 0) // 增加非零判断,避免对0进行无意义的减法
- {
- time_sub_secs(&tm, &tm, -zone * 15 * 60); // 传入正数
- }
- tm.year %= 100;
- SetRtcTime(&tm);
- save_cur_flow_flag = 1;
- }
- #endif
- //+QENG: "servingcell","NOCONN","LTE","FDD",460,11,EA6CE03,77,100,1,5,5,EA15,-94,-8,-66,24,26
- // rsrp rwrq rssi sinr
- uint8_t get_nb_signal(uint8_t *buf, uint16_t dat_len)
- {
- // 确保数据包含预期的关键字
- if (buf == NULL || strstr((char *)buf, "+QENG: \"servingcell\"") == NULL)
- {
- return 0;
- }
- if (dat_len > 200)
- return 0;
- char temp[200] = {0};
- memcpy(temp, buf, dat_len);
- char *token = NULL;
- char *tokens[20]; // 足足够容纳所有分割的子字符串
- int count = 0;
- // 使用 strtok 按逗号分割字符串
- token = strtok(temp, ",");
- while (token != NULL && count < 20)
- {
- tokens[count++] = token;
- token = strtok(NULL, ",");
- }
- // 根据您提供的格式,各字段在分割后的索引如下:
- // [0] +QENG: "servingcell"
- // [1] "NOCONN"
- // [2] "LTE"
- // [3] "FDD"
- // [4] 460
- // [5] 11
- // [6] 9C8C712 -> 基站id (需转为uint32_t)
- // [7] 119 -> 物理小区id
- // [8] 2452
- // [9] 5
- // [10] 3
- // [11] 3
- // [12] EA15
- // [13] -85 -> 参考信号接收功率
- // [14] -15 -> 参考信号接收质量
- // [15] -53 -> 接收信号强度指示
- // [16] 0 -> SINR (有效范围 -20~40)
- // 确保分割出的字段数量足够
- if (count > 16)
- {
- // 基站id是16进制字符串,使用 strtoul 转换为 32位无符号数
- NbRun.bts_id = (uint32_t)strtoul(tokens[6], NULL, 16);
- // 物理小区id是10进制数
- NbRun.physical_cell_id = (uint32_t)atoi(tokens[7]);
- // 参考信号接收功率
- NbRun.rsrp_bak = atoi(tokens[13]);
- // 参考信号接收质量
- NbRun.rsrq = atoi(tokens[14]);
- // 接收信号强度指示
- NbRun.rssi = atoi(tokens[15]);
- // SINR
- NbRun.snr = atoi(tokens[16]);
- return 1;
- }
- return 0;
- }
- uint8_t check_sub_service_flag(void)
- {
- uint8_t vflag;
- vflag = 1;
- 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)
- {
- vflag = 0;
- } // 主从ip相同,端口号相同
- if (Paramx.sub_server_ip[0] == 0 || Paramx.sub_server_port == 0) // 从ip为空,端口号为空
- {
- vflag = 0;
- }
- return vflag;
- }
- uint8_t check_main_service_flag(void)
- {
- uint8_t vflag;
- vflag = 1;
- if (Paramx.main_server_ip[0] == 0 || Paramx.main_server_port == 0) // 从ip为空,端口号为空
- {
- vflag = 0;
- }
- return vflag;
- }
- /**
- * @brief 极简的无符号整型转字符串函数 (替代 itoa,减少对 stdlib 的依赖)
- * @param value 待转换的数值
- * @param str 转换后的字符串缓冲区 (需保证至少6字节空间)
- * @return 指向字符串缓冲区的指针
- */
- static char *uint_to_str(uint16_t value, char *str)
- {
- char buf[6];
- uint8_t i = 0;
- if (value == 0)
- {
- str[0] = '0';
- str[1] = '\0';
- return str;
- }
- while (value > 0)
- {
- buf[i++] = (value % 10) + '0';
- value /= 10;
- }
- uint8_t len = i;
- for (uint8_t j = 0; j < len; j++)
- {
- str[j] = buf[len - 1 - j];
- }
- str[len] = '\0';
- return str;
- }
- /**
- * @brief 构建 NB-IoT TCP 连接的 AT 指令 (替代 sprintf,大幅减少代码量)
- * @param out_str 输出的指令字符串缓冲区
- * @param ip 4字节IP地址数组
- * @param port 端口号
- */
- void build_tcp_open_cmd(char *out_str, uint8_t *ip, uint16_t port)
- {
- char num_buf[6];
- strcpy(out_str, "AT+QIOPEN=1,0,\"TCP\",\"");
- uint_to_str(ip[0], num_buf);
- strcat(out_str, num_buf);
- strcat(out_str, ".");
- uint_to_str(ip[1], num_buf);
- strcat(out_str, num_buf);
- strcat(out_str, ".");
- uint_to_str(ip[2], num_buf);
- strcat(out_str, num_buf);
- strcat(out_str, ".");
- uint_to_str(ip[3], num_buf);
- strcat(out_str, num_buf);
- strcat(out_str, "\",");
- uint_to_str(port, num_buf);
- strcat(out_str, num_buf);
- strcat(out_str, ",0,0\r\n");
- }
|