EC800(7149).c 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268
  1. //----------------------------说明
  2. // 程序使用hal库,数据传输使用的串口,串口设置为发送+dma,接收+dma+空闲中断的模式
  3. #include "EC800.h"
  4. //-----------------------------变量定义
  5. //---------
  6. typedef struct{
  7. // 为模块打开一个网络中
  8. char ip[20]; // IP
  9. uint16_t port; // port
  10. // 连接到mqtt服务器
  11. char clientid[20]; // clientid
  12. char username[20]; // username
  13. char password[20]; // password
  14. }ec800Date;
  15. ec800Date s_ec800Date = {
  16. .ip = "39.98.37.180",
  17. .port = 32449,
  18. .clientid = "NULL",
  19. .username = "hechun",
  20. .password = "admin123",
  21. };
  22. typedef struct{
  23. uint8_t drivDirection; // 行驶方向 单位 度 short类型
  24. uint8_t vehicleStatus; // 车辆状态 停驶:0 运行中:1 充电中:2 电池离仓:3 故障:4 离线:5
  25. uint8_t dailyDrivTime; // 当日行驶时长 单位 小时 short类型
  26. uint8_t dailyDrivMileage; // 当日行驶里程 单位 公里 short类型
  27. uint8_t runTime; // 运行时长
  28. uint8_t batCompartmentTemp; // 电池仓温度
  29. uint16_t vehicleSpeed; // 实时车速 单位 m/s short类型
  30. uint16_t accTotalDrivTime; // 累积行驶总时长 int
  31. uint16_t accTotalMileage; // 累积行驶总里程 int
  32. uint16_t demandCur; // 需求电流 0.1A
  33. uint16_t demandVol; // 需求电压 0.1V
  34. uint32_t latitude; //纬度 分扩大100000倍,实际要除以100000
  35. uint8_t nshemi; //北纬/南纬,N:北纬;S:南纬
  36. uint32_t longitude; //经度 分扩大100000倍,实际要除以100000
  37. uint8_t ewhemi; //东经/西经,E:东经;W:西经
  38. uint32_t Timestamp; // 时间戳
  39. char lat_long_data[40]; // 经纬度数据
  40. char VIN[40]; // 车架号
  41. char Vehicle_Num[27]; // 车辆编号
  42. char uploadTime[20]; // 上传时间
  43. char imsi[20]; // SIM卡的IMSI信息
  44. }messageDate;
  45. messageDate s_messageDate = {0};
  46. typedef struct{
  47. uint8_t maxSpeed; // 服务器下发的允许最大车速
  48. uint16_t year; // 上传时间 年
  49. uint8_t month; // 上传时间 月
  50. uint8_t day; // 上传时间 日
  51. uint8_t hour; // 上传时间 时
  52. uint8_t minute; // 上传时间 分
  53. uint8_t sec; // 上传时间 秒
  54. }recDate;
  55. recDate s_recDate = {0};
  56. nmea_msg s_nmea_msg = {0};
  57. nmea_utc_time s_nmea_utc_time = {0};
  58. // AT指令响应超时时间定义
  59. #define REC_TIMEOUT (10000) // 1ms
  60. /**
  61. * @brief 计算字符串的长度
  62. * @param str: 所需计算字符串的指针
  63. * @note
  64. * @retval 无
  65. */
  66. int EC800_calculateStringLength(const char* str) {
  67. int length = 0;
  68. while (str[length] != '\0') {
  69. length++;
  70. }
  71. return length;
  72. }
  73. /**
  74. * @brief 发送指令函数
  75. * @param command: 指令
  76. * @param enterNum: 进入函数次数,只有第一次的时候清除buff
  77. * @note
  78. * @retval 无
  79. */
  80. void EC800M_SendCommand(const char* command)
  81. {
  82. uint32_t stringLen = 0;
  83. stringLen = EC800_calculateStringLength(command);
  84. //等待发送状态OK
  85. while(HAL_DMA_GetState(&hdma_usart3_tx) == HAL_DMA_STATE_BUSY) osDelay(1);
  86. //发送数据
  87. HAL_UART_Transmit_DMA(&huart3, (uint8_t*)command, stringLen);
  88. }
  89. /**
  90. * @brief 接收指令回复函数
  91. * @param haystack: 接收的字符串数据
  92. * @param needle: 正确回复的数据
  93. * @note
  94. * @retval 无
  95. */
  96. char* EC800M_RecRespond(char *haystack, const char *needle ){
  97. char* p = NULL;
  98. HAL_UART_Receive_DMA(&huart3, (uint8_t*)g_usart3_rx_buf, USART3_REC_LEN); //设置接收缓冲区
  99. __HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE);
  100. while(g_usart3_rx_sta == 0) osDelay(1);
  101. __HAL_UART_DISABLE_IT(&huart3, UART_IT_IDLE); // 关闭空闲中断
  102. g_usart3_rx_sta= 0;
  103. p = strstr(haystack, needle);
  104. memset(haystack, 0, USART3_REC_LEN); // 清除数据buff
  105. return p;
  106. }
  107. // 自定义的搜索函数
  108. void* search_sequence(const void* haystack, size_t haystack_len, const void* needle, size_t needle_len) {
  109. const unsigned char* h = (const unsigned char*)haystack;
  110. const unsigned char* n = (const unsigned char*)needle;
  111. // 如果needle为空或haystack长度小于needle长度,则直接返回NULL
  112. if (needle_len == 0 || haystack_len < needle_len) {
  113. return NULL;
  114. }
  115. for (size_t i = 0; i <= haystack_len - needle_len; ++i) {
  116. size_t j;
  117. for (j = 0; j < needle_len; ++j) {
  118. if (h[i + j] != n[j]) {
  119. break; // 如果当前字符不匹配,则跳出内层循环
  120. }
  121. }
  122. if (j == needle_len) {
  123. return (void*)(h + i); // 找到匹配的序列,返回其在haystack中的位置
  124. }
  125. }
  126. // 如果遍历了整个haystack都没有找到匹配的序列,则返回NULL
  127. return NULL;
  128. }
  129. // 接收并比较响应字符串
  130. uint8_t Accept_and_Compare_Str(const char* needle){
  131. uint8_t temp = 0;
  132. static uint16_t timeOutCnt = 0; // 超时计数
  133. HAL_UART_Receive_DMA(&huart3, (uint8_t*)g_usart3_rx_buf, USART3_REC_LEN); //设置接收缓冲区
  134. __HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE);
  135. while(!temp) {
  136. osDelay(1);
  137. // if(strstr(g_usart3_rx_buf, needle)){
  138. if(search_sequence(g_usart3_rx_buf, USART3_REC_LEN, needle, strlen(needle))){
  139. temp = 1;
  140. }
  141. // if(strstr(g_usart3_rx_buf, "ERROR")){
  142. if(search_sequence(g_usart3_rx_buf, USART3_REC_LEN, "ERROR", strlen("ERROR"))){
  143. temp = 2;
  144. }
  145. if(timeOutCnt < REC_TIMEOUT){
  146. timeOutCnt++;
  147. }else{
  148. timeOutCnt = 0;
  149. temp = 3;
  150. }
  151. }
  152. g_usart3_rx_sta = 0;
  153. __HAL_UART_DISABLE_IT(&huart3, UART_IT_IDLE); // 关闭空闲中断
  154. return temp;
  155. }
  156. /**
  157. * @brief 接收使能函数
  158. * @note
  159. * @retval 无
  160. */
  161. void EC800_recEnable(void){
  162. HAL_UART_Receive_DMA(&huart3, (uint8_t*)g_usart3_rx_buf, USART3_REC_LEN); //设置接收缓冲区
  163. __HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE);
  164. while(g_usart3_rx_sta == 0) osDelay(1);
  165. }
  166. /**
  167. * @brief 提取检查信号响应字符串字段中的信号量并进行信号判断
  168. * @param data: 响应的信号量指针
  169. * @note
  170. * @retval 无
  171. */
  172. static uint8_t EC800_extractSignal(char *data){
  173. char *token;
  174. int field_1;
  175. // 使用strtok函数提取字段
  176. token = strtok(data, ":,");
  177. while (token != NULL) {
  178. field_1 = atoi(token); // 转换为整数类型
  179. token = strtok(NULL, ":,");
  180. memset(data, 0, USART3_REC_LEN); // 清除数据buff
  181. g_usart3_rx_sta = 0; // 清除接收状态
  182. if (field_1 < 31) {
  183. return 1;
  184. } else {
  185. return 0;
  186. }
  187. }
  188. return 0;
  189. }
  190. /**
  191. * @brief 获取IMSI号
  192. * @param 无
  193. * @note
  194. * @retval 1: imsi没有获取到 0;imsi获取到
  195. */
  196. uint8_t EC800_getIMSI(void){
  197. char* found = NULL;
  198. char number[16]; // 15 digits + 1 for null terminator
  199. int numberIndex = 0;
  200. int numberFound = 0;
  201. EC800M_SendCommand(AT_CIMI);
  202. EC800_recEnable();
  203. found = strstr(g_usart3_rx_buf, AT_RESP_OK);
  204. if (found != NULL) {
  205. printf("IMSI is get\r\n");
  206. }else{
  207. printf("IMSI is not get\r\n");
  208. return 1;
  209. }
  210. for (int i = 0; i < strlen(g_usart3_rx_buf); i++) {
  211. if (isdigit(g_usart3_rx_buf[i])) {
  212. number[numberIndex] = g_usart3_rx_buf[i];
  213. numberIndex++;
  214. if (numberIndex >= 15) {
  215. numberFound = 1;
  216. break;
  217. }
  218. }
  219. }
  220. number[numberIndex] = '\0';
  221. if (numberFound) {
  222. memcpy(s_messageDate.imsi, number, strlen(number));
  223. printf("IMSI is: %s\n", number);
  224. } else {
  225. printf("Error: Unable to extract the number\n");
  226. }
  227. return 0;
  228. }
  229. /**
  230. * @brief EC800M确认网络并链接MQTT服务器
  231. * @param NONE
  232. * @note
  233. * @retval 无
  234. */
  235. uint8_t linkStep = 0;
  236. void EC800M_link(void){
  237. uint8_t temp = 0;
  238. char command[100] = {0};
  239. char errrCnt = 0; // 错误计数
  240. char* found = NULL;
  241. switch(linkStep){
  242. case 0: // 基础配置
  243. EC800M_SendCommand(AT_CMD_TEST);
  244. found = EC800M_RecRespond(g_usart3_rx_buf, AT_RESP_OK);
  245. if (found != NULL) {
  246. printf("Module status normal\r\n");
  247. }else{
  248. errrCnt++;
  249. printf("Module status abnormal\r\n");
  250. }
  251. if(errrCnt == 0){
  252. linkStep = 1;
  253. }else{
  254. errrCnt = 0;
  255. }
  256. break;
  257. case 1: // 获取ISMI号
  258. errrCnt = EC800_getIMSI();
  259. if(errrCnt == 0){
  260. linkStep = 2;
  261. }else{
  262. errrCnt = 0;
  263. }
  264. break;
  265. case 2:
  266. EC800M_SendCommand(AT_CMD_ATE0);
  267. found = EC800M_RecRespond(g_usart3_rx_buf, AT_RESP_OK);
  268. if (found != NULL) {
  269. printf("Cancel module echo\r\n");
  270. }else{
  271. errrCnt++;
  272. printf("Failed to cancel module echo\r\n");
  273. }
  274. if(errrCnt == 0){
  275. linkStep = 3;
  276. }else{
  277. errrCnt = 0;
  278. }
  279. break;
  280. case 3:
  281. EC800M_SendCommand(AT_CMD_CPIN);
  282. found = EC800M_RecRespond(g_usart3_rx_buf, AT_RESP_CPIN_READY);
  283. if (found != NULL) {
  284. printf("SIM card normal\r\n");
  285. }else{
  286. errrCnt++;
  287. printf("SIM card abnormal\r\n");
  288. }
  289. if(errrCnt == 0){
  290. linkStep = 4;
  291. }else{
  292. errrCnt = 0;
  293. }
  294. break;
  295. case 4:
  296. EC800M_SendCommand(AT_CMD_CSQ);
  297. EC800_recEnable();
  298. temp = EC800_extractSignal(g_usart3_rx_buf);
  299. if (temp) {
  300. printf("signal normal\r\n");
  301. }else{
  302. errrCnt++;
  303. printf("signal abnormal\r\n");
  304. }
  305. if(errrCnt == 0){
  306. linkStep = 5;
  307. }else{
  308. errrCnt = 0;
  309. }
  310. break;
  311. case 5:
  312. EC800M_SendCommand(AT_CMD_CREG);
  313. EC800_recEnable();
  314. // 使用字符串处理函数判断是否为正常状态
  315. if (strstr(g_usart3_rx_buf, "1") != NULL || strstr(g_usart3_rx_buf, "5") != NULL) {
  316. printf("The module successfully registered on the GSM network\r\n");
  317. } else {
  318. errrCnt++;
  319. printf("The module failed to register on the GSM network\r\n");
  320. }
  321. memset(g_usart3_rx_buf, 0, USART3_REC_LEN); // 清除数据buff
  322. g_usart3_rx_sta = 0; // 清除接收状态
  323. if(errrCnt == 0){
  324. linkStep = 6;
  325. }else{
  326. errrCnt = 0;
  327. }
  328. break;
  329. case 6:
  330. EC800M_SendCommand(AT_CMD_QIDEACT);
  331. found = EC800M_RecRespond(g_usart3_rx_buf, AT_RESP_OK);
  332. if (found != NULL) {
  333. printf("Successfully disabled mobile scene\r\n");
  334. }else{
  335. errrCnt++;
  336. printf("Failed to disable mobile scene\r\n");
  337. }
  338. if(errrCnt == 0){
  339. linkStep = 7;
  340. }else{
  341. errrCnt = 0;
  342. }
  343. break;
  344. case 7:
  345. EC800M_SendCommand(AT_CMD_QIACT);
  346. found = EC800M_RecRespond(g_usart3_rx_buf, AT_RESP_OK);
  347. if (found != NULL) {
  348. printf("Successfully enabled mobile scene\r\n");
  349. }else{
  350. errrCnt++;
  351. printf("Failed to enable mobile scene\r\n");
  352. }
  353. if(errrCnt == 0){
  354. linkStep = 8;
  355. }else{
  356. errrCnt = 0;
  357. }
  358. break;
  359. case 8: // 连接mqtt服务器
  360. sprintf(command, "AT+QMTCFG=\"qmtping\",0,%d\r\n", 30);
  361. EC800M_SendCommand(command);
  362. found = EC800M_RecRespond(g_usart3_rx_buf, AT_RESP_OK);
  363. if (found != NULL) {
  364. printf("MQTT heartbeat set successfully\r\n");
  365. }else{
  366. errrCnt++;
  367. printf("Failed to set MQTT heartbeat\r\n");
  368. }
  369. if(errrCnt == 0){
  370. linkStep = 9;
  371. }else{
  372. errrCnt = 0;
  373. }
  374. break;
  375. case 9:
  376. EC800M_SendCommand(AT_CMD_QMTCFG_SET_DATA_MODE);
  377. found = EC800M_RecRespond(g_usart3_rx_buf, AT_RESP_OK);
  378. if (found != NULL) {
  379. printf("Data receiving mode set successfully.\r\n");
  380. }else{
  381. errrCnt++;
  382. printf("Failed to set data receiving mode\r\n");
  383. }
  384. if(errrCnt == 0){
  385. linkStep = 10;
  386. }else{
  387. errrCnt = 0;
  388. }
  389. break;
  390. case 10:
  391. sprintf(command,"AT+QMTOPEN=0,\"%s\",%d\r\n", s_ec800Date.ip, s_ec800Date.port);
  392. EC800M_SendCommand(command);
  393. found = EC800M_RecRespond(g_usart3_rx_buf, AT_RESP_OK);
  394. found = EC800M_RecRespond(g_usart3_rx_buf, AT_RESP_QMTOPEN);
  395. if (found != NULL) {
  396. printf("Successfully opened a network for the module\r\n");
  397. }else{
  398. errrCnt++;
  399. printf("Failed to open a network for the module\r\n");
  400. }
  401. if(errrCnt == 0){
  402. linkStep = 11;
  403. }else{
  404. errrCnt = 0;
  405. }
  406. break;
  407. case 11:
  408. sprintf(command,"AT+QMTCONN=0,%s,%s,%s\r\n",s_ec800Date.clientid, s_ec800Date.username, s_ec800Date.password);
  409. EC800M_SendCommand(command);
  410. found = EC800M_RecRespond(g_usart3_rx_buf, AT_RESP_OK);
  411. found = EC800M_RecRespond(g_usart3_rx_buf, AT_RESP_QMTCONN);
  412. if (found != NULL) {
  413. printf("Successfully connected to the MQTT server\r\n");
  414. }else{
  415. errrCnt++;
  416. printf("Failed to connect to the MQTT server\r\n");
  417. }
  418. if(errrCnt == 0){
  419. linkStep = 12;
  420. }else{
  421. errrCnt = 0;
  422. }
  423. break;
  424. default: break;
  425. }
  426. }
  427. /**
  428. * @brief EC800M初始化GNSS
  429. * @param NONE
  430. * @note
  431. * @retval 无
  432. */
  433. uint8_t gnssStep = 0;
  434. void EC800_gnss_init(void){
  435. char errrCnt = 0; // 错误计数
  436. char* found = NULL;
  437. switch(gnssStep){
  438. case 6:
  439. EC800M_SendCommand(AT_QGPS_0);
  440. found = EC800M_RecRespond(g_usart3_rx_buf, AT_RESP_OK);
  441. if (found != NULL) {
  442. printf("Turn off the GNSS module\r\n");
  443. }else{
  444. errrCnt++;
  445. printf("Failed to turn off the GNSS module\r\n");
  446. }
  447. if(errrCnt == 0){
  448. gnssStep = 7;
  449. }else{
  450. gnssStep = 7;
  451. }
  452. break;
  453. case 7:
  454. EC800M_SendCommand(AT_QGPS_1);
  455. found = EC800M_RecRespond(g_usart3_rx_buf, AT_RESP_OK);
  456. if (found != NULL) {
  457. printf("Turn on the GNSS module\r\n");
  458. }else{
  459. errrCnt++;
  460. printf("Failed to turn on the GNSS module\r\n");
  461. }
  462. if(errrCnt == 0){
  463. gnssStep = 8;
  464. }else{
  465. errrCnt = 0;
  466. }
  467. break;
  468. case 0:
  469. EC800M_SendCommand(AT_QGPSCFG_out_port);
  470. found = EC800M_RecRespond(g_usart3_rx_buf, AT_RESP_OK);
  471. if (found != NULL) {
  472. printf("Outputting NMEA Sentences via Serial Debugging\r\n");
  473. }else{
  474. errrCnt++;
  475. printf("The NMEA sentence output is set incorrectly\r\n");
  476. }
  477. if(errrCnt == 0){
  478. gnssStep = 1;
  479. }else{
  480. errrCnt = 0;
  481. }
  482. break;
  483. case 1:
  484. EC800M_SendCommand(AT_QGPSCFG_nmeasrc);
  485. found = EC800M_RecRespond(g_usart3_rx_buf, AT_RESP_OK);
  486. if (found != NULL) {
  487. printf("Enabling NMEA sentence retrieval via AT+QGPSGNMEA\r\n");
  488. }else{
  489. errrCnt++;
  490. printf("Failed to enable retrieving NMEA sentences via AT+QGPSGNMEA\r\n");
  491. }
  492. if(errrCnt == 0){
  493. gnssStep = 2;
  494. }else{
  495. errrCnt = 0;
  496. }
  497. break;
  498. case 2:
  499. EC800M_SendCommand(AT_QGPSCFG_gpsnmeatype);
  500. found = EC800M_RecRespond(g_usart3_rx_buf, AT_RESP_OK);
  501. if (found != NULL) {
  502. printf("Configuring the output type of NMEA sentences to all formats\r\n");
  503. }else{
  504. errrCnt++;
  505. printf("Failed to configure the output type of NMEA sentences to all formats\r\n");
  506. }
  507. if(errrCnt == 0){
  508. gnssStep = 3;
  509. }else{
  510. errrCnt = 0;
  511. }
  512. break;
  513. case 3:
  514. EC800M_SendCommand(AT_QGPSCFG_gnssconfig);
  515. found = EC800M_RecRespond(g_usart3_rx_buf, AT_RESP_OK);
  516. if (found != NULL) {
  517. printf("Configuring the supported GNSS satellite navigation systems to GPS+BeiDou\r\n");
  518. }else{
  519. errrCnt++;
  520. printf("Failed to configure the supported GNSS satellite navigation systems to GPS+BeiDou\r\n");
  521. }
  522. if(errrCnt == 0){
  523. gnssStep = 4;
  524. }else{
  525. errrCnt = 0;
  526. }
  527. break;
  528. case 4:
  529. EC800M_SendCommand(AT_QGPSCFG_autogps);
  530. found = EC800M_RecRespond(g_usart3_rx_buf, AT_RESP_OK);
  531. if (found != NULL) {
  532. printf("Disable GNSS auto-start\r\n");
  533. }else{
  534. errrCnt++;
  535. printf("Failed to disable GNSS auto-start\r\n");
  536. }
  537. if(errrCnt == 0){
  538. gnssStep = 5;
  539. }else{
  540. errrCnt = 0;
  541. }
  542. break;
  543. case 5:
  544. EC800M_SendCommand(AT_QGPSCFG_apflash);
  545. found = EC800M_RecRespond(g_usart3_rx_buf, AT_RESP_OK);
  546. if (found != NULL) {
  547. printf("Disable AP-Flash quick start function\r\n");
  548. }else{
  549. errrCnt++;
  550. printf("Failed to disable AP-Flash quick start function\r\n");
  551. }
  552. if(errrCnt == 0){
  553. gnssStep = 6;
  554. }else{
  555. errrCnt = 0;
  556. }
  557. break;
  558. default:
  559. break;
  560. }
  561. }
  562. //UTC时间转换为任意时区时间,如果是转换为北京时间,timezone传8即可
  563. void utc_to_local_time(nmea_utc_time* utc_time, int8_t timezone, nmea_utc_time* local_time)
  564. {
  565. int year,month,day,hour;
  566. int lastday = 0; //last day of this month 本月天数
  567. int lastlastday = 0; //last day of last month 上个月天数
  568. year = utc_time->year; //utc time
  569. month = utc_time->month;
  570. day = utc_time->date;
  571. hour = utc_time->hour + timezone;
  572. //1月大,2月小,3月大,4月小,5月大,6月小,7月大,8月大,9月小,10月大,11月小,12月大
  573. if(month==1 || month==3 || month==5 || month==7 || month==8 || month==10 || month==12)
  574. {
  575. lastday = 31;//本月天数
  576. lastlastday = 30;//这里应该补上上个月的天数
  577. if(month == 3)
  578. {
  579. if((year%400 == 0)||(year%4 == 0 && year%100 != 0))//if this is lunar year
  580. lastlastday = 29;
  581. else
  582. lastlastday = 28;
  583. }
  584. if(month == 8 || month == 1)//这里应该是8月和1月,因为8月和1月的上一个月(7月和12月)的天数是31天的
  585. lastlastday = 31;
  586. }
  587. else if(month == 4 || month == 6 || month == 9 || month == 11)
  588. {
  589. lastday = 30;
  590. lastlastday = 31;
  591. }
  592. else
  593. {
  594. lastlastday = 31;
  595. if((year%400 == 0)||(year%4 == 0 && year%100 != 0))
  596. lastday = 29;
  597. else
  598. lastday = 28;
  599. }
  600. if(hour >= 24)// if >24, day+1
  601. {
  602. hour -= 24;
  603. day += 1;
  604. if(day > lastday)// next month, day-lastday of this month
  605. {
  606. day -= lastday;
  607. month += 1;
  608. if(month > 12)// next year, month-12
  609. {
  610. month -= 12;
  611. year += 1;
  612. }
  613. }
  614. }
  615. if(hour < 0)// if <0, day-1
  616. {
  617. hour += 24;
  618. day -= 1;
  619. if(day < 1)// month-1, day=last day of last month
  620. {
  621. day = lastlastday;
  622. month -= 1;
  623. if(month < 1)// last year, month=12
  624. {
  625. month = 12;
  626. year -= 1;
  627. }
  628. }
  629. }
  630. // transfer value to local_time
  631. local_time->year = year;
  632. local_time->month = month;
  633. local_time->date = day;
  634. local_time->hour = hour;
  635. local_time->min = utc_time->min;
  636. local_time->sec = utc_time->sec;
  637. }
  638. /**
  639. * @brief 常用时间格式转时间戳
  640. * @param NONE
  641. * @note
  642. * @retval 无
  643. */
  644. uint32_t EC800_mktime (unsigned int year, unsigned int mon,
  645. unsigned int day, unsigned int hour,
  646. unsigned int min, unsigned int sec)
  647. {
  648. if (0 >= (int) (mon -= 2)){ /**//* 1..12 -> 11,12,1..10 */
  649. mon += 12; /**//* Puts Feb last since it has leap day */
  650. year -= 1;
  651. }
  652. return (((
  653. (unsigned long) (year/4 - year/100 + year/400 + 367*mon/12 + day) +
  654. year*365 - 719499
  655. )*24 + hour /**//* now have hours */
  656. )*60 + min /**//* now have minutes */
  657. )*60 + sec; /**//* finally seconds */
  658. }
  659. /**
  660. * @brief 读取GNSS的数据
  661. * @param NONE
  662. * @note
  663. * @retval 无
  664. */
  665. void EC800_readGnssDate(void){
  666. char* found = NULL;
  667. EC800M_SendCommand(AT_QGPSGNMEA_RMC);
  668. EC800_recEnable();
  669. found = strstr(g_usart3_rx_buf, AT_RESP_OK);
  670. if (found != NULL) {
  671. printf("Location information received successfully\r\n");
  672. }else{
  673. printf("Location information reception failed\r\n");
  674. return ;
  675. }
  676. printf("Location information:%s\r\n", g_usart3_rx_buf);
  677. NMEA_GNRMC_Analysis(&s_nmea_msg, (uint8_t*)g_usart3_rx_buf);
  678. utc_to_local_time(&(s_nmea_msg.utc), 8, &s_nmea_utc_time);
  679. printf("timer-%d/%d/%d %d:%d:%d\r\n",s_nmea_utc_time.year,s_nmea_utc_time.month,s_nmea_utc_time.date,s_nmea_utc_time.hour,s_nmea_utc_time.min,s_nmea_utc_time.sec);
  680. s_messageDate.Timestamp = EC800_mktime(s_nmea_utc_time.year,s_nmea_utc_time.month,s_nmea_utc_time.date,s_nmea_utc_time.hour,s_nmea_utc_time.min,s_nmea_utc_time.sec);
  681. g_usart3_rx_sta= 0;
  682. memset(g_usart3_rx_buf, 0, USART3_REC_LEN); // 清除数据buff
  683. printf("latitude:%d%d--longitude:%d%d\r\n", s_nmea_msg.latitude, s_nmea_msg.nshemi, s_nmea_msg.longitude, s_nmea_msg.ewhemi);
  684. s_messageDate.latitude = s_nmea_msg.latitude;
  685. s_messageDate.nshemi = s_nmea_msg.nshemi;
  686. s_messageDate.longitude = s_nmea_msg.longitude;
  687. s_messageDate.ewhemi = s_nmea_msg.ewhemi;
  688. }
  689. /**
  690. * @brief EC800M订阅主题
  691. * @param topic1: 订阅的主题名称1字符串形式
  692. * @param topic2: 订阅的主题名称2字符串形式
  693. * @note
  694. * @retval 无
  695. */
  696. uint8_t EC800_subscribeToTopic(const char* topic1){
  697. char command[100] = {0};
  698. char* found = NULL;
  699. sprintf(command, "AT+QMTSUB=0,1,\"%s\",0\r\n", topic1);
  700. EC800M_SendCommand(command);
  701. found = EC800M_RecRespond(g_usart3_rx_buf, AT_RESP_OK);
  702. found = EC800M_RecRespond(g_usart3_rx_buf, AT_RESP_QMTSUB);
  703. if (found != NULL) {
  704. printf("Subscription to the topic successful\r\n");
  705. return 1;
  706. }else{
  707. printf("Subscription to the topic failed\r\n");
  708. return 0;
  709. }
  710. }
  711. /**
  712. * @brief EC800M发布消息
  713. * @param topic: 消息发布的主题 字符串形式
  714. * @param message: 发布的消息 字符串形式
  715. * @param len: 发布消息的字节长度
  716. * @note
  717. * @retval 无
  718. */
  719. uint8_t EC800_publishMessage(const char* topic, const char* message, uint16_t len){
  720. char command[100] = {0};
  721. char* found = NULL;
  722. char* responseCmd = ">";
  723. static uint8_t publishStep = 0;
  724. switch(publishStep){
  725. case 0:
  726. sprintf(command,"AT+QMTPUBEX=0,0,0,0,\"%s\",%d\r\n",topic,len);
  727. EC800M_SendCommand(command);
  728. found = EC800M_RecRespond(g_usart3_rx_buf, responseCmd);
  729. if (found != NULL) {
  730. found = NULL; // 将found指针指向NULL处
  731. printf("The topic has been linked\r\n");
  732. publishStep = 1;
  733. }else{
  734. printf("The topic link failed\r\n");
  735. publishStep = 0;
  736. }
  737. // break;
  738. case 1:
  739. EC800M_SendCommand(message);
  740. found = EC800M_RecRespond(g_usart3_rx_buf, AT_RESP_OK);
  741. found = EC800M_RecRespond(g_usart3_rx_buf, AT_RESP_QMTPUBEX);
  742. if (found != NULL) {
  743. printf("The message has been successfully posted\r\n");
  744. publishStep = 0;
  745. }else{
  746. printf("Message publication failed\r\n");
  747. publishStep = 0;
  748. }
  749. break;
  750. default:
  751. break;
  752. }
  753. return 2;
  754. }
  755. /**
  756. * @brief EC800M与服务器进行时间对时
  757. * @note
  758. * @retval 无
  759. */
  760. uint8_t EC800_time_calibration(void){
  761. cJSON *root = NULL;
  762. char *jsonString = NULL;
  763. uint8_t temp = 0;
  764. // 定义对象 { }
  765. root = cJSON_CreateObject();
  766. // 插入元素,对应 键值对
  767. cJSON_AddItemToObject(root, "msgType", cJSON_CreateString("json"));
  768. cJSON_AddItemToObject(root, "imsi", cJSON_CreateString(s_messageDate.imsi));
  769. cJSON_AddItemToObject(root, "hardVersion", cJSON_CreateString(HARD_VERSION));
  770. cJSON_AddItemToObject(root, "softVersion", cJSON_CreateString(SOFT_VERSION));
  771. cJSON_AddItemToObject(root, "devId", cJSON_CreateString(DEV_ID));
  772. cJSON_AddItemToObject(root, "protocolVersion", cJSON_CreateString(PROTOCOL_VERSION));
  773. cJSON_AddItemToObject(root, "txnNo", cJSON_CreateNumber(s_messageDate.Timestamp));
  774. cJSON_AddItemToObject(root, "devType", cJSON_CreateNumber(DEV_TYPE));
  775. // 将 JSON 对象转换为字符串
  776. jsonString = cJSON_Print(root);
  777. cJSON_Delete(root);
  778. temp = EC800_publishMessage("ABCDEFG", jsonString, strlen(jsonString));
  779. free(jsonString);
  780. return temp;
  781. }
  782. /**
  783. * @brief 将服务器响应的字符串中的年月日进行分离
  784. * @note
  785. * @retval 无
  786. */
  787. void parseServerTime(char* str){
  788. char year[5];
  789. char month[3];
  790. char day[3];
  791. char hour[3];
  792. char minute[3];
  793. char second[3];
  794. strncpy(year, str, 4);
  795. year[4] = '\0';
  796. strncpy(month, str + 4, 2);
  797. month[2] = '\0';
  798. strncpy(day, str + 6, 2);
  799. day[2] = '\0';
  800. strncpy(hour, str + 8, 2);
  801. hour[2] = '\0';
  802. strncpy(minute, str + 10, 2);
  803. minute[2] = '\0';
  804. strncpy(second, str + 12, 2);
  805. second[2] = '\0';
  806. s_recDate.year = atoi(year);
  807. s_recDate.month = atoi(month);
  808. s_recDate.day = atoi(day);
  809. s_recDate.hour = atoi(hour);
  810. s_recDate.minute = atoi(minute);
  811. s_recDate.sec = atoi(second);
  812. s_messageDate.Timestamp = EC800_mktime(s_recDate.year,s_recDate.month,s_recDate.day,s_recDate.hour,s_recDate.minute,s_recDate.sec);
  813. printf("Year (int): %d\n", s_recDate.year);
  814. printf("Month (int): %d\n", s_recDate.month);
  815. printf("Day (int): %d\n", s_recDate.day);
  816. printf("Hour (int): %d\n", s_recDate.hour);
  817. printf("Minute (int): %d\n", s_recDate.minute);
  818. printf("Second (int): %d\n", s_recDate.sec);
  819. }
  820. /**
  821. * @brief 解析对时数据帧的响应
  822. * @note
  823. * @retval 无
  824. */
  825. void EC800_parseRespondTime(cJSON *root, cJSON *item){
  826. uint8_t temp = 0;
  827. // 获取"resultCode"字段的值
  828. item = cJSON_GetObjectItem(root, "resultCode");
  829. if (item == NULL) {
  830. printf("Field \"resultCode\" not found\n");
  831. }else{
  832. // 打印"resultCode"字段的值
  833. printf("resultCode: %d\n", item->valueint);
  834. if((item->valueint) == 1){
  835. printf("The upload of synchronized data was successful.\n");
  836. temp = 1; // 上传成功
  837. }else{
  838. printf("The upload of synchronized data has failed.\n");
  839. }
  840. }
  841. if(temp == 1){
  842. item = cJSON_GetObjectItem(root, "serverTime");
  843. if (item == NULL) {
  844. printf("Field \"serverTime\" not found\n");
  845. }else{
  846. // 打印"serverTime"字段的值
  847. printf("serverTime: %d\n", item->valuestring);
  848. parseServerTime(item->valuestring);
  849. }
  850. }
  851. }
  852. /**
  853. * @brief EC800M上传实时数据
  854. * @note
  855. * @retval 无
  856. */
  857. uint8_t EC800_uploadRealDate(void){
  858. cJSON *root = NULL;
  859. char *jsonString = NULL;
  860. cJSON *rt000 = NULL;
  861. cJSON *rt000Object1 = NULL;
  862. uint8_t temp = 0;
  863. // 定义对象 { }
  864. root = cJSON_CreateObject();
  865. //
  866. // 插入元素,对应 键值对
  867. cJSON_AddItemToObject(root, "msgType", cJSON_CreateString("json"));
  868. cJSON_AddItemToObject(root, "imsi", cJSON_CreateString(s_messageDate.imsi));
  869. cJSON_AddItemToObject(root, "hardVersion", cJSON_CreateString(HARD_VERSION));
  870. cJSON_AddItemToObject(root, "softVersion", cJSON_CreateString(SOFT_VERSION));
  871. cJSON_AddItemToObject(root, "devId", cJSON_CreateString(DEV_ID));
  872. cJSON_AddItemToObject(root, "protocolVersion", cJSON_CreateString(PROTOCOL_VERSION));
  873. cJSON_AddItemToObject(root, "txnNo", cJSON_CreateNumber(s_messageDate.Timestamp));
  874. cJSON_AddItemToObject(root, "devType", cJSON_CreateNumber(DEV_TYPE));
  875. // 定义 { } 对象
  876. rt000Object1 = cJSON_CreateObject();
  877. cJSON_AddItemToObject(rt000Object1, "rt003", cJSON_CreateNumber(s_messageDate.vehicleStatus));
  878. cJSON_AddItemToObject(rt000Object1, "rt025", cJSON_CreateNumber(s_messageDate.demandVol));
  879. cJSON_AddItemToObject(rt000Object1, "rt026", cJSON_CreateNumber(s_messageDate.demandCur));
  880. cJSON_AddItemToObject(rt000Object1, "rt027", cJSON_CreateString(s_messageDate.VIN));
  881. cJSON_AddItemToObject(rt000Object1, "rt028", cJSON_CreateString(s_messageDate.lat_long_data));
  882. cJSON_AddItemToObject(rt000Object1, "rt029", cJSON_CreateNumber(s_messageDate.drivDirection));
  883. cJSON_AddItemToObject(rt000Object1, "rt030", cJSON_CreateNumber(s_messageDate.vehicleSpeed));
  884. cJSON_AddItemToObject(rt000Object1, "rt031", cJSON_CreateNumber(s_messageDate.dailyDrivTime));
  885. cJSON_AddItemToObject(rt000Object1, "rt032", cJSON_CreateNumber(s_messageDate.dailyDrivMileage));
  886. cJSON_AddItemToObject(rt000Object1, "rt033", cJSON_CreateNumber(s_messageDate.accTotalDrivTime));
  887. cJSON_AddItemToObject(rt000Object1, "rt034", cJSON_CreateNumber(s_messageDate.accTotalMileage));
  888. cJSON_AddItemToObject(rt000Object1, "rt035", cJSON_CreateNumber(s_messageDate.runTime));
  889. // 定义 [ ] 数组
  890. rt000 = cJSON_CreateArray();
  891. // 往数组中添加元素
  892. cJSON_AddItemToArray(rt000, rt000Object1);
  893. // 将子项插入根项中
  894. cJSON_AddItemToObject(root, "rt000", rt000);
  895. //
  896. // 将 JSON 对象转换为字符串
  897. jsonString = cJSON_Print(root);
  898. cJSON_Delete(root);
  899. temp = EC800_publishMessage("ABCDEFG", jsonString, strlen(jsonString));
  900. free(jsonString);
  901. return temp;
  902. }
  903. /**
  904. * @brief 解析实时数据响应
  905. * @note
  906. * @retval 无
  907. */
  908. void EC800_respondRealDate(cJSON *root, cJSON *item){
  909. // 获取"name"字段的值
  910. item = cJSON_GetObjectItem(root, "resultCode");
  911. if (item == NULL) {
  912. printf("Field \"resultCode\" not found\n");
  913. }else{
  914. // 打印"name"字段的值
  915. printf("resultCode: %d\n", item->valueint);
  916. if((item->valueint) == 1){
  917. printf("Uploaded real-time data successfully\n");
  918. }else{
  919. printf("The upload of real-time data has failed\n");
  920. }
  921. }
  922. }
  923. /**
  924. * @brief 通信响应解析
  925. * @note
  926. * @return 当前的控制命令
  927. */
  928. short EC800_respondParse(void){
  929. cJSON *root = NULL;
  930. cJSON *item = NULL;
  931. short cmd = 0;
  932. // 找到JSON数据的起始位置
  933. const char* start = strchr(g_usart3_rx_buf, '{');
  934. if (start == NULL) {
  935. printf("JSON data not found\n");
  936. return 0;
  937. }
  938. // 解析JSON数据
  939. root = cJSON_Parse(start);
  940. if (root == NULL) {
  941. printf("Failed to parse JSON data\n");
  942. cJSON_Delete(root);
  943. return 0;
  944. }
  945. // 获取"controlCode"字段的值
  946. item = cJSON_GetObjectItem(root, "controlCode");
  947. if (item == NULL) {
  948. printf("Field \"controlCode\" not found\n");
  949. }else{
  950. // 打印"controlCode"字段的值
  951. printf("controlCode: %d\n", item->valueint);
  952. cmd = item->valueint;
  953. }
  954. // 解析对应命令的对应数据
  955. switch(cmd){
  956. case 106:
  957. EC800_parseRespondTime(root, item);
  958. break;
  959. case 202:
  960. EC800_respondRealDate(root, item);
  961. break;
  962. default :
  963. break;
  964. }
  965. cJSON_Delete(root);
  966. return (cmd);
  967. }
  968. /**
  969. * @brief EC800M状态转换与使用
  970. * @note
  971. * @retval 无
  972. */
  973. uint8_t stateStep = 0;
  974. void EC800_stateTransition_use(void){
  975. uint8_t right = 1; // 返回是否为正确
  976. static uint16_t timesCnt = 0;
  977. static uint8_t tudeErrcnt = 0; // 定位信息错误计数
  978. switch(stateStep){
  979. case 0: // 初始化模块
  980. EC800M_link();
  981. if(linkStep == 9){
  982. stateStep = 1;
  983. }
  984. break;
  985. case 1: // 初始化GNSS
  986. // EC800_gnss_init();
  987. EC800_FTP_OTA_Upgrade();
  988. if(gnssStep == 8){
  989. // stateStep = 2;
  990. }
  991. break;
  992. case 2: // 订阅主题
  993. right = EC800_subscribeToTopic("aabbcc");
  994. if(right != 1){ // 发布消息失败,可能断开链接
  995. // stateStep = 0; // 重新初始化
  996. }else{
  997. stateStep = 3;
  998. }
  999. break;
  1000. case 3:
  1001. // 获取定位信息
  1002. EC800_readGnssDate();
  1003. // 没有获取到定位信息 重复获取三次
  1004. if((s_messageDate.latitude == 0) && (s_messageDate.longitude == 0)){
  1005. tudeErrcnt++;
  1006. if(tudeErrcnt == 4){
  1007. tudeErrcnt = 0;
  1008. stateStep = 4;
  1009. }
  1010. }else{
  1011. tudeErrcnt = 0;
  1012. stateStep = 4;
  1013. }
  1014. break;
  1015. case 4: // 与服务器对时
  1016. right = EC800_time_calibration();
  1017. stateStep = 6; // 去步骤6等待对时响应 收到对时响应后,发布实时消息
  1018. break;
  1019. case 5: // 发布消息
  1020. right = EC800_uploadRealDate();
  1021. stateStep = 6;
  1022. // if(right == 0){ // 发布消息失败,可能断开链接
  1023. // stateStep = 0; // 重新初始化
  1024. // linkStep = 0;
  1025. // stateStep = 6;
  1026. // }else if(right == 1){
  1027. // stateStep = 6;
  1028. // }
  1029. break;
  1030. case 6: // 接收消息
  1031. HAL_UART_Receive_DMA(&huart3, (uint8_t*)g_usart3_rx_buf, USART3_REC_LEN); //设置接收缓冲区
  1032. __HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE);
  1033. if(g_usart3_rx_sta!=0){
  1034. HAL_UART_Transmit(&huart1, (uint8_t*)g_usart3_rx_buf, strlen(g_usart3_rx_buf), HAL_MAX_DELAY); // 打印数据除去URC
  1035. right = EC800_respondParse();
  1036. if(right == CTR_CODE_JUDETIME){ // 对时响应
  1037. stateStep = 5;
  1038. right = 0;
  1039. timesCnt = 0;
  1040. }
  1041. memset(g_usart3_rx_buf, 0, USART3_REC_LEN); // 清除数据buff,接收新的数据
  1042. g_usart3_rx_sta = 0; // 清除接收状态
  1043. }
  1044. // 转弯行驶中
  1045. if(turnFlag == 1){
  1046. if(timesCnt < TURN_INTERVAL_TIME_MS){
  1047. timesCnt++;
  1048. }else{
  1049. timesCnt= 0;
  1050. stateStep = 3;
  1051. HAL_UART_DMAStop(&huart3);
  1052. __HAL_UART_DISABLE_IT(&huart3, UART_IT_IDLE);
  1053. }
  1054. }else{ // 正常行驶中
  1055. if(timesCnt < PUBLISH_TIME_MS){
  1056. timesCnt++;
  1057. }else{
  1058. timesCnt= 0;
  1059. stateStep = 3;
  1060. HAL_UART_DMAStop(&huart3);
  1061. __HAL_UART_DISABLE_IT(&huart3, UART_IT_IDLE);
  1062. }
  1063. }
  1064. break;
  1065. default:
  1066. break;
  1067. }
  1068. }