123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119 |
- #include "ML307A.h"
- #include "usart.h"
- #include "circle_buffer.h"
- #include "rtc.h"
- #include <stdio.h> //printf
- #include <string.h>
- #include <stdbool.h> // bool
- #include "cmsis_os.h"
- #include "main.h"
- #include "queue.h"
- #include "uType.h"
- #include "remote.h"
- extern circle_buf_t uart3CircleBuf; // 环形缓冲区管理结构体
- //extern circle_buf_t_2 uart3CircleBuf_2; // 环形缓冲区管理结构体
- #define BUFFER_SIZE4G 512
- extern uint8_t receiveBuff4G[BUFFER_SIZE4G];
- char responseBuf[256]; // AT指令应答的局部缓冲区
- char responseBuf_2[256]; // AT指令应答的局部缓冲区
- //static uint8_t uart3ParseBuf[BUFFER_SIZE4G]; // 解析+MIPURC: "rtcp"的缓冲区
- //static uint16_t parseIndex = 0; // 解析+MIPURC: "rtcp"的缓冲区指针
- extern uint8_t receiveBuff4G_MIPURC[BUFFER_SIZE4G];
- extern osMessageQueueId_t uart3rxqueueHandle;
- bool MgnssFlag = false;// GNSS定位信息上报成功标志位
- uint8_t Reset4G_flag = 0;
- #define MAX_HEX_DATA_LEN 256 // 假设最多解析 256 字节的 HEX 数据
- uint8_t parsed_4GMIPURC_Data[MAX_HEX_DATA_LEN];
- extern bool flash_save_parameter_flag;
- uint16_t msg_serial = 0;
- extern volatile bool heartbeat_reply_received;
- extern volatile bool unixtime_reply_received;
- /**
- * @breaf 封装串口发送4G AT命令函数
- */
- void USART_SendString(UART_HandleTypeDef *huart,char *str)
- {
- // HAL_UART_Transmit(huart, (uint8_t*)str, strlen(str), 0xFFFF);
- HAL_UART_Transmit_DMA(huart, (uint8_t*)str, strlen(str));
- }
- /**
- * @breaf 发送4G串口命令
- */
- /*
- uint8_t sendCmd_4G(char *pCmd, char *pRes, uint32_t timeOut, uint8_t sendNum)
- {
- uint8_t i = 0;
- uint32_t time;
- // uint8_t found = 0;
-
- for (i = 0; i < sendNum; i++)
- {
- time = timeOut * 10; // 将超时时间转换为循环次数
- memset(receiveBuff4G, 0, sizeof(receiveBuff4G)); // 清空接收缓冲区
- USART_SendString(&huart3, pCmd); // 发送命令字符串
- // HAL_Delay(100);
- osDelay(100);
- while (time--)
- {
- if (strstr((const char *)receiveBuff4G, pRes) != NULL)
- {
- printf("-- %s\n", receiveBuff4G); // 打印接收到的内容
- //如果接收缓冲区包含预期的响应
- return 1;
- }
- // HAL_Delay(100);
- osDelay(100);
- }
- printf("! %s\n", receiveBuff4G);
- }
- return 0;
- }
- */
- uint8_t sendCmd_4G(char *pCmd, char *pRes1, uint32_t timeOut, uint8_t sendNum)
- {
- uint8_t i;
- uint32_t time;
- uint8_t receivedByte;
- memset(responseBuf, 0, sizeof(responseBuf)); // 清空临时缓冲区
- for (i = 0; i < sendNum; i++)
- {
- time = timeOut * 10; // 计算超时时间
- // ★ 发送前丢弃旧数据 ★
- __HAL_UART_DISABLE_IT(&huart3, UART_IT_IDLE); // 可选:保护指针修改
- uart3CircleBuf.r = uart3CircleBuf.w; // 丢弃旧数据
- __HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE);
- //printf("send command: %s\r\n", pCmd);
-
- USART_SendString(&huart3, pCmd); // 发送 AT 指令
- osDelay(100); // 等待模块返回(短暂延时)
- while (time--)
- {
- uint8_t gotNewData = 0;
- // 读取环形缓冲区内的新数据
- while (circle_buf_read(&uart3CircleBuf, &receivedByte) == 0)
- {
- gotNewData = 1;
- uint16_t len = strlen(responseBuf);
- if (len < sizeof(responseBuf) - 1)
- {
- responseBuf[len] = receivedByte;
- responseBuf[len + 1] = '\0'; // 字符串结束符
- }
- }
- if (gotNewData)
- {
- // ★ 判断是否匹配 ★
- if (pRes1 && strstr(responseBuf, pRes1) != NULL)
- {
- // printf("-: %s\n", responseBuf);
- return 1; // 任意一个匹配成功
- }
- }
- osDelay(10);
- }
- printf("Timeout_!: %s\n", responseBuf); // 超时打印
- }
- return 0;
- }
- uint8_t sendCmd_4G_2(char *pCmd, char *pRes1, char *pRes2, uint32_t timeOut, uint8_t sendNum)
- {
- uint8_t i;
- uint32_t time;
- uint8_t receivedByte;
- memset(responseBuf_2, 0, sizeof(responseBuf_2)); // 清空临时缓冲区
- for (i = 0; i < sendNum; i++)
- {
- time = timeOut * 10; // 计算超时时间
- // ★ 发送前丢弃旧数据 ★
- __HAL_UART_DISABLE_IT(&huart3, UART_IT_IDLE); // 可选:保护指针修改
- uart3CircleBuf.r = uart3CircleBuf.w; // 丢弃旧数据
- __HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE);
- //printf("send command: %s\r\n", pCmd);
-
- USART_SendString(&huart3, pCmd); // 发送 AT 指令
- osDelay(100); // 等待模块返回(短暂延时)
- while (time--)
- {
- uint8_t gotNewData = 0;
- // 读取环形缓冲区内的新数据
- while (circle_buf_read(&uart3CircleBuf, &receivedByte) == 0)
- {
- gotNewData = 1;
- uint16_t len = strlen(responseBuf_2);
- if (len < sizeof(responseBuf_2) - 1)
- {
- responseBuf_2[len] = receivedByte;
- responseBuf_2[len + 1] = '\0'; // 字符串结束符
- }
- }
- if (gotNewData)
- {
- // ★ 判断是否匹配 ★
- if ((pRes1 && strstr(responseBuf_2, pRes1) != NULL) ||
- (pRes2 && strstr(responseBuf_2, pRes2) != NULL))
-
- {
- // printf("-: %s\n", responseBuf_2);
- return 1; // 任意一个匹配成功
- }
- }
- osDelay(10);
- }
- printf("Timeout_!: %s\n", responseBuf_2); // 超时打印
- }
- return 0;
- }
- uint8_t sendCmd_4G_3(char *pCmd, char *pRes1, char *pRes2, uint32_t timeOut, uint8_t sendNum)
- {
- uint8_t i;
- uint32_t time;
- uint8_t receivedByte;
- memset(responseBuf_2, 0, sizeof(responseBuf_2)); // 清空临时缓冲区
- for (i = 0; i < sendNum; i++)
- {
- time = timeOut * 10; // 计算超时时间
- // ★ 发送前丢弃旧数据 ★
- __HAL_UART_DISABLE_IT(&huart3, UART_IT_IDLE); // 可选:保护指针修改
- uart3CircleBuf.r = uart3CircleBuf.w; // 丢弃旧数据
- __HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE);
- USART_SendString(&huart3, pCmd); // 发送 AT 指令
- osDelay(100); // 等待模块返回(短暂延时)
- uint8_t matchFlag = 0;
- while (time--)
- {
- uint8_t gotNewData = 0;
- // 读取环形缓冲区内的新数据
- while (circle_buf_read(&uart3CircleBuf, &receivedByte) == 0)
- {
- gotNewData = 1;
- uint16_t len = strlen(responseBuf_2);
- if (len < sizeof(responseBuf_2) - 1)
- {
- responseBuf_2[len] = receivedByte;
- responseBuf_2[len + 1] = '\0'; // 字符串结束符
- }
- }
- if (gotNewData)
- {
- // 每次有新数据都检测是否有完整的行
- char *lineStart = responseBuf_2;
- while (1)
- {
- // 查找是否有一行结束符
- char *lineEnd = strstr(lineStart, "\r\n");
- if (lineEnd == NULL)
- break; // 没有完整行,等待更多数据
- // 截断这一行,形成完整字符串
- *lineEnd = '\0';
- // 打印完整行
- // printf("%s\n", lineStart);
- // // 重点:如果是+MIPURC开头的数据
- // if (strstr(lineStart, "+MIPURC: \"rtcp\"") != NULL)
- // {
- // printf("MIPURC Data: %s\n", lineStart);
- // }
- // 判断是否有匹配到成功应答
- if ((pRes1 && strstr(lineStart, pRes1) != NULL) ||
- (pRes2 && strstr(lineStart, pRes2) != NULL))
- {
- matchFlag = 1;
- }
- // 移动到下一行
- lineStart = lineEnd + 2;
- }
- // 剩下的内容移动到buffer头部(继续拼接未完整行)
- uint16_t remainLen = strlen(lineStart);
- memmove(responseBuf_2, lineStart, remainLen + 1); // +1 包含结束符
- }
- osDelay(10);
- }
- if (matchFlag)
- {
- // printf("%s\n", responseBuf_2); // 打印剩余数据
- return 1; // 任意一个匹配成功
- }
- printf("Timeout_!: %s\n", responseBuf_2); // 超时打印
- }
- return 0;
- }
- void process_uart3_buffer(void)
- {
- Uart3Rx_msg uart3_msg;
-
- if (xQueueReceive(uart3rxqueueHandle, &uart3_msg, (TickType_t)500) == pdPASS) // portMAX_DELAY (TickType_t)0
- {
- uint16_t len = (uart3_msg.length < sizeof(receiveBuff4G_MIPURC)) ? uart3_msg.length : (sizeof(receiveBuff4G_MIPURC) - 1);
- memcpy(receiveBuff4G_MIPURC, uart3_msg.data, len);
- receiveBuff4G_MIPURC[len] = '\0'; // 确保字符串结尾
- printf("Queue Data: %s\n", receiveBuff4G_MIPURC);
- if(system_cloud_mode == Cloud_4G_MODE)
- {
- process_MIPURC_data(receiveBuff4G_MIPURC, len);
- }
- }
- }
- void process_MIPURC_data(uint8_t *buf, uint16_t len)
- {
- const char *mipurcStr = "+MIPURC: \"rtcp\",0,";
- uint16_t mipurcLen = strlen(mipurcStr);
- int mipurcPos = -1;
- // **查找 "+MIPURC: \"rtcp\",0," 位置**
- for (uint16_t i = 0; i <= len - mipurcLen; i++) {
- if (memcmp(buf + i, mipurcStr, mipurcLen) == 0) {
- mipurcPos = i;
- break;
- }
- }
- // **如果找到 "+MIPURC: \"rtcp\",0,"**
- if (mipurcPos != -1)
- {
- uint8_t *dataStart = buf + mipurcPos + mipurcLen; // `+MIPURC: "rtcp",0,` 后的数据
- // **提取数据长度**
- char *commaPos = strchr((char *)dataStart, ',');
- if (commaPos == NULL) {
- printf("Invalid MIPURC format (missing length)\n");
- return;
- }
- int expectedDataLen = 0;
- if (sscanf(commaPos - 2, "%d,", &expectedDataLen) != 1) { // **修正解析**
- printf("Invalid MIPURC format (length parse error)\n");
- return;
- }
- // 找到实际数据部分(跳过逗号后面的空格)
- char *hexDataStr = commaPos + 3; // 这里 +3 是跳过 ", ",确保指向 HEX 数据
- // **转换 HEX 字符串到二进制**
- int actualDataLen = hexStringToBytes(hexDataStr-2, parsed_4GMIPURC_Data, MAX_HEX_DATA_LEN);
- if (actualDataLen < 0) {
- printf("HEX Data parse error! Code: %d\n", actualDataLen);
- return;
- }
- // **检查长度是否匹配**
- if (expectedDataLen == actualDataLen-1)
- {
- // printf("Extracted JT808 Data (%d bytes): ", expectedDataLen);
- // for (int i = 0; i < expectedDataLen; i++) {
- // printf("%02X ", parsed_4GMIPURC_Data[i]);
- // }
- // printf("\n");
- // 直接解析 JT808 数据
- parse_JT808_frame(parsed_4GMIPURC_Data, expectedDataLen);
- } else {
- printf("Length mismatch: expected %d, got %d. Ignoring.\n", expectedDataLen, actualDataLen);
- }
- }
- }
- /**
- * @brief 等待UART3接收预期字符串中的任意一个 WIFI用
- * @param keywords 关键词数组(多个字符串)
- * @param keyword_count 关键词数量
- * @param buffer 存储接收数据的缓冲区
- * @param buffer_len 缓冲区长度
- * @param timeout_ms 等待超时时间(毫秒)
- * @return 匹配到的关键词索引(0 ~ keyword_count-1),否则返回 -1
- */
- int wait_uart3_multi_response(const char* keywords[], int keyword_count, char* buffer, uint16_t buffer_len, uint32_t timeout_ms)
- {
- TickType_t start_tick = xTaskGetTickCount();
- uint16_t total_len = 0;
- Uart3Rx_msg uart3_msg;
- while ((xTaskGetTickCount() - start_tick) < pdMS_TO_TICKS(timeout_ms))
- {
- if (xQueueReceive(uart3rxqueueHandle, &uart3_msg, pdMS_TO_TICKS(300)) == pdPASS)
- {
- uint16_t copy_len = (uart3_msg.length < (buffer_len - total_len - 1)) ? uart3_msg.length : (buffer_len - total_len - 1);
- memcpy(buffer + total_len, uart3_msg.data, copy_len);
- total_len += copy_len;
- buffer[total_len] = '\0';
- printf("Recv: %s\r\n", buffer);
- // 检查并提取 +TRDTC: 数据
- extract_and_parse_trdtc(buffer);
- for (int i = 0; i < keyword_count; ++i)
- {
- if (strstr(buffer, keywords[i]) != NULL)
- {
- // printf("Matched keyword[%d]: %s\r\n", i, keywords[i]);
- return i;
- }
- }
-
- }
- }
- printf("Timeout\r\n");
- return -1;
- }
- /**
- * @brief 从 UART 数据中提取并解析 +TRDTC: 开头的 JT808 帧数据
- * @param buffer 接收到的完整字符串(含 +TRDTC:)
- */
- void extract_and_parse_trdtc(const char* buffer)
- {
-
- const char* trdtc_start = strstr(buffer, "+TRDTC:");
- if (!trdtc_start)
- return;
- // 查找第一个 "7E" 作为帧起始
- const char* frame_start = strstr(trdtc_start, "7E");
- if (!frame_start)
- return;
- // printf("first 7E \r\n");
- const char* frame_end = strstr(frame_start + 2, "7E"); // 查找第二个 7E
- if (frame_end)
- {
- frame_end += 2; // 包含结束 7E
- }
- else
- {
- // 如果没找到第二个7E,尝试查找\r\n作为帧尾
- frame_end = strstr(frame_start, "\r\n");
- if (!frame_end)
- return; // 没有找到帧尾,退出
- // 不包括 \r\n,只处理到前面为止
- }
- // printf("frame_end 7E \r\n");
- int hex_len = frame_end - frame_start;
- if (hex_len <= 0 || hex_len > 512)
- return;
- uint8_t jt808_frame[256];
- int byte_len = 0;
- char byte_str[3] = {0};
- for (int i = 0; i < hex_len; i += 2)
- {
- if (frame_start[i] == '\0' || frame_start[i + 1] == '\0')
- break;
- byte_str[0] = frame_start[i];
- byte_str[1] = frame_start[i + 1];
- jt808_frame[byte_len++] = (uint8_t)strtol(byte_str, NULL, 16);
- }
- if (byte_len > 0)
- parse_JT808_frame(jt808_frame, byte_len);
- }
- void parse_JT808_frame(uint8_t *frame, uint16_t length)
- {
- // printf("JT808 Frame Received (Len: %d): ", length);
- // for (uint16_t i = 0; i < length; i++)
- // {
- // printf("%02X ", frame[i]);
- // }
- // printf("\n");
-
- uint16_t msg_id = (frame[1] << 8) | frame[2]; // 消息 ID
- // uint16_t msg_length = (frame[3] << 8) | frame[4]; // 消息体长度
- // uint8_t *phone_number = &frame[5]; // 手机号 (BCD 编码)
- msg_serial = (frame[11] << 8) | frame[12]; // 消息流水号
- uint8_t *payload = &frame[13]; // 消息体数据
- uint8_t received_checksum = frame[length - 2]; // 校验码
-
- uint8_t calculated_checksum = Calculate_Checksum(&frame[1], length - 3);
- if (calculated_checksum != received_checksum )
- {
- printf("Checksum Mismatch! Expected: %02X, Received: %02X\n", calculated_checksum, received_checksum);
- return;
- }
-
- // printf("JT808 Frame Received (Len: %d)\n", length);
- // printf("Message ID: 0x%04X, Length: %d, Serial: %d\n", msg_id, msg_length, msg_serial);
- switch (msg_id)
- {
- case 0x80FF: // 服务器下发unix时间
- if ((length - 13) >= 4) // 数据体长度至少 4 字节
- {
- // 从 payload 中提取 4 字节,转成 uint32_t
- uint32_t timestamp =
- ((uint32_t)payload[0] << 24) |
- ((uint32_t)payload[1] << 16) |
- ((uint32_t)payload[2] << 8) |
- ((uint32_t)payload[3]);
- // printf("Received UNIX Timestamp: %lu\r\n", timestamp);
- // 设置 RTC 时间
- Set_RTC_Time((time_t)timestamp);
- unixtime_reply_received = true;
- }
- else
- {
- printf("Invalid 0x80FF payload length: %d\r\n", length - 13);
- }
- break;
-
- case 0x8001: // 终端通用应答
- if (length > 18 && frame[17] == 0)
- printf("Heart_callback_OK\n");
- heartbeat_reply_received = true;
- break;
- case 0x8100: // 终端注册应答
- if (length > 14 && frame[13] == 0)
- printf("Cloud_Register_callback_OK\n");
- break;
- case 0x8103: // 终端参数设置
- parse_JT808_8103(payload, length);
- Send_General_response();
- break;
- default:
- printf("Unknown Message ID: 0x%04X\n", msg_id);
- break;
- }
-
-
- }
- // 解析 JT808 0x8103 终端参数设置
- void parse_JT808_8103(uint8_t *payload, uint16_t length)
- {
- printf("Terminal Parameter Settings Received:\n");
- for (uint16_t i = 1; i < length;)
- {
-
- uint16_t param_id = (payload[i] << 8) | payload[i + 1]; // 参数 ID
- uint8_t param_length = payload[i + 2]; // 参数长度
- uint8_t param_value = payload[i + 3]; // 只支持 1 字节参数
- printf("Param ID: 0x%04X, Length: %d, Value: %d\n", param_id, param_length, param_value);
- switch (param_id)
- {
- case 0xF101: flash_data.controltransmit_flag = param_value; break;
- case 0xF102: flash_data.temp_first_threshold = param_value; break;
- case 0xF103: flash_data.temp_second_threshold = param_value; break;
- case 0xF104: flash_data.pressure_threshold = param_value; break;
- case 0xF105: flash_data.co_threshold = param_value; break;
- case 0xF106: flash_data.h2_threshold = param_value; break;
- case 0xF107: flash_data.smallboard_upload_frequency = param_value; break;
- case 0xF108: flash_data.heart_upload_frequency = param_value; break;
- case 0xF109: flash_data.mainboard_upload_frequency = param_value; break;
- default:
- printf("Unknown Parameter ID: 0x%04X\n", param_id);
- break;
- }
- i += (3 + param_length); // 跳过已解析的参数
- }
- CAN_Send_Parameter(0x00110000, &flash_data, 8);
- flash_save_parameter_flag = true;
- printf("Updated flash_data:\n");
- printf("Control Transmit Flag: %d\n", flash_data.controltransmit_flag);
- printf("Temp First Threshold: %d°C\n", flash_data.temp_first_threshold);
- printf("Temp Second Threshold: %d°C\n", flash_data.temp_second_threshold);
- printf("Pressure Threshold: %d Pa\n", flash_data.pressure_threshold);
- printf("CO Threshold: %d ppm\n", flash_data.co_threshold);
- printf("H2 Threshold: %d ppm\n", flash_data.h2_threshold);
- printf("Smallboard Upload Frequency: %d s\n", flash_data.smallboard_upload_frequency);
- printf("Heart Upload Frequency: %d s\n", flash_data.heart_upload_frequency);
- printf("Mainboard Upload Frequency: %d s\n", flash_data.mainboard_upload_frequency);
- }
- // HEX 字符串转换为二进制数据
- int hexStringToBytes(const char *hexStr, uint8_t *outBytes, int maxLen)
- {
- int hexStrLen = strlen(hexStr);
- if (hexStrLen % 2 != 0) {
- return -1; // HEX 字符串长度必须是偶数
- }
-
- int byteLen = hexStrLen / 2;
- if (byteLen > maxLen) {
- return -2; // 数据超出缓冲区
- }
- for (int i = 0; i < byteLen; i++) {
- sscanf(hexStr + 2 * i, "%2hhx", &outBytes[i]); // 每两个字符转换成 1 个字节
- }
-
- return byteLen;
- }
- /**
- * @breaf MQTT连接至MQTT服务器,订阅,发布消息
- */
- // 封装MQTT连接至MQTT服务器
- uint8_t mqttconn(char *IpAddr, uint16_t port, char *ID, char *User, char *Passwd, char* pRes)
- {
-
- char MQTT_Sendbuf[128];
- sprintf((char *)MQTT_Sendbuf,"AT+MQTTCONN=0,\"%s\",\"%d\",\"%s\",\"%s\",\"%s\"\r\n",IpAddr, port, ID,User, Passwd);
- sendCmd_4G(MQTT_Sendbuf,pRes,1,1);
- if(sendCmd_4G(MQTT_Sendbuf,pRes,1,1))
- {
- return 1;
- }
- return 0;
- }
- // 连接至MQTT服务器,订阅
- void MQTTCONN(void)
- {
- char MQTT_SUBbuf[50]; // 订阅字符缓冲区
- char topicb[50];//*服务器发布主题B
-
- // 连接至MQTT服务器
- mqttconn((char*)MQTTADDR,MQTTPORT,"DCCJC",(char*)MQTTUSER,(char*)MQTTPSWD,"+MQTTURC: \"conn\",0,0");// printf("#连接MQTT成功\r\n");
-
- // 订阅主题
- snprintf(MQTT_SUBbuf, 50, "AT+MQTTSUB=0,\"%s\",1\r\n", topicb);
- // 发送订阅指令并检查结果
- sendCmd_4G(MQTT_SUBbuf, "+MQTTURC: \"suback\"", 1, 1);// printf("#订阅成功\r\n");
-
- }
- // 发布消息QoS=0;
- uint8_t MQTT_PUB(uint8_t connect_id, char *topic, char *mesg, char* pRes)
- {
- char MQTT_Sendbuf[200];
- uint8_t length = strlen(mesg);
- sprintf((char *)MQTT_Sendbuf,"AT+MQTTPUB=%d,\"%s\",0,0,0,%d,\"%s\"\r\n",connect_id, topic, length, mesg);
- sendCmd_4G(MQTT_Sendbuf,pRes,1,1);
- // if(sendCmd_4G(MQTT_Sendbuf,pRes,1,1)){// printf("#发布心跳成功\r\n");
- // return 1;
- // }
- return 1;
- }
- // 断开MQTT连接
- void MQTTDISCONN(void)
- {
- sendCmd_4G("AT+MQTTDISC=0\r\n", "OK", 1, 1);// printf("#断开MQTT连接成功\r\n");
- }
- /**
- * @breaf 建立TCP连接
- */
- // 封装建立TCP连接函数
- void tcpconn(char *value, uint8_t cid, char *IPaddr, uint16_t port, uint8_t tcpConnmode)
- {
- char *ptr = value;
- ptr += sprintf(ptr, "AT+MIPOPEN=%d,\"TCP\",\"%s\",%d,60,%d\r\n",cid,IPaddr,port,tcpConnmode);
- }
- // 建立TCP连接平台端IP及端口号
- void TCPCONN(void)
- {
- char TCPconnvalue[100];
- tcpconn(TCPconnvalue, 1, JIALONGip, JIALONGport,0); //cid=1 tcpConnmode=0 普通模式
- }
- /**
- * @breaf 连续定位信息上报
- */
- void GNSSLOC(void)
- {
- // sendCmd_4G("AT+MIPCFG=\"encoding\",1,1,1\r\n", "OK", 1, 1);//默认输入输出为ASCII,0 发16,1 接16,1
-
- sendCmd_4G("AT+MGNSSCFG=\"nmea/mask\",0\r\n", "OK", 1, 1);
- sendCmd_4G("AT+MGNSSLOC=0\r\n", "OK", 1, 1);
- sendCmd_4G("AT+MGNSS=1\r\n", "OK", 1, 1);
- if(sendCmd_4G("AT+MGNSSCFG=\"nmea/mask\",0\r\n", "OK", 1, 1))
- { // printf("#使能NMEA信息\r\n");
- if(sendCmd_4G("AT+MGNSSLOC=0\r\n", "OK", 1, 1))
- {// printf("#关闭自动定位上报\r\n");
- if(sendCmd_4G("AT+MGNSS=1\r\n", "OK", 1, 1))
- {// printf("开启MGNSS\r\n");
- MgnssFlag=true;
- }
- }
- }
- }
- /**
- * @breaf 4G模块初始化
- */
- void ML307A_INIT(void)
- {
-
- if (sendCmd_4G("AT\r\n", "OK", 1, 5))
- {
- printf("AT_OK\r\n");
- }else
- {
- printf("AT_fail\r\n");
- ML307AReset();
- }
- if (sendCmd_4G("AT+CPIN?\r\n", "+CPIN: READY", 1, 5))
- {
- printf("CPIN_OK\r\n");
- }
- if (sendCmd_4G("AT+CEREG?\r\n", "+CEREG: 0,1", 1, 5))
- {
- printf("CEREG_OK\r\n");
- }
- if(sendCmd_4G("AT+MIPCLOSE=1\r\n", "+MIPSEND:", 1, 1))//关闭TCP连接
- {
- printf("MIPCLOSE_OK\r\n");
- }
- ML307A_MQTT_Init();
- }
- void ML307A_Init(void)
- {
-
- for (int attempt_count = 0; attempt_count < 3; attempt_count++)
- {
- sendCmd_4G("AT\r\n", "OK", 1, 5);
- HAL_Delay(10);
- sendCmd_4G("AT+CPIN?\r\n", "+CPIN: READY", 1, 5);
- printf("CPIN_OK\r\n");
- HAL_Delay(10);
- sendCmd_4G("AT+CEREG?\r\n", "+CEREG: 0,1", 1, 5);
- printf("Network ing...\r\n");
- if (sendCmd_4G("AT+CPIN?\r\n", "+CPIN: READY", 1, 5))
- {
- printf("PIN认证成功\r\n");
- if (sendCmd_4G("AT+CEREG?\r\n", "+CEREG: 0,1", 1, 5))
- {
- printf("驻网成功\r\n");
- break;
- }
- } else {
- ML307AReset();
- }
-
- break;
- }
- }
- /*
- char TCPconnvalue[100];// TCP的IP地址端口号缓冲区
- case 2:
- // tcpconn(TCPconnvalue, 1, JIALONGip, JIALONGport,0); //cid=1 tcpConnmode=0 普通模式
- // if (sendCmd_4G(TCPconnvalue, "+MIPOPEN: 1,0", 1, 1)) {
- // step4g++;
- // }
- step4g=3;
- break;
- case 3:
- sendCmd_4G("AT+MIPCFG=\"encoding\",0,2,0\r\n", "OK", 1, 1);////输入配置为转义字符模式
- if (!reset4Gmodule) {
- if (sendCmd_4G("AT+MGNSSCFG=\"nmea/mask\",0\r\n", "OK", 1, 1)) {
- printf("#使能NMEA信息\r\n");
- if (sendCmd_4G("AT+MGNSSLOC=0\r\n", "OK", 1, 1)) {
- printf("#关闭自动定位上报\r\n");
- if (sendCmd_4G("AT+MGNSS=1\r\n", "OK", 1, 1)) {
- printf("#开启MGNSS\r\n");
- MgnssFlag = true;
- }
- }
- }
- step4g++;
- } else {
- reset4Gmodule = false;
- }
- break;
- case 4:
- MQTTCONN();
- char data_buff[256]; //组合JSON报文数据
- uint8_t run_state = 0;
- sprintf((char *)data_buff,"{\"temperature\":{\"ID\":180}}");
- run_state=MQTT_PUB(0,Publish_Topic,data_buff,"+MQTTURC: \"puback\"");//上报
- if(run_state==1)
- {
- printf("4G模块发布数据至MQTT成功\r\n");
- run_state = 0;
- }
- */
- void Send_AT_Command(char *command)
- {
- // 发送AT指令时添加换行符
- char command_with_newline[256];
- snprintf(command_with_newline, sizeof(command_with_newline), "%s\r\n", command);
- // 发送指令
- HAL_UART_Transmit(&huart3, (uint8_t *)command_with_newline, strlen(command_with_newline),1000);
- }
- void Receive_Response(char *buffer, uint16_t size)
- {
-
-
- // 接收数据
- HAL_UART_Receive_DMA(&huart3, (uint8_t *)buffer, size - 1);
-
- // 添加字符串结束符
- buffer[size - 1] = '\0';
- memset(buffer, 0, size); // 清空接收缓冲区
- }
- int Check_Response(char *buffer, uint16_t size)
- {
- Receive_Response(buffer, size);
-
- // 判断是否为错误响应
- if (strstr(buffer, "+CME ERROR") != NULL) {
- return 0; // 失败
- }
- // 判断是否为特定成功响应
- if (strstr(buffer, "+MQTTREAD") != NULL ||
- strstr(buffer, "+MQTTPUB") != NULL ||
- strstr(buffer, "+MQTTSUB") != NULL ||
- strstr(buffer, "+MQTTURC") != NULL ||
- strstr(buffer, "+CEREG:0,1") != NULL
- ) {
- return 1; // 成功
- }
- // 判断是否为OK响应
- if (strstr(buffer, "OK") != NULL) {
- return 1; // 成功
- }
- return 0; // 其他情况视为失败
- }
- int Send_Command_Check_Response(char *command, char *response_buffer, uint16_t buffer_size)
- {
- Send_AT_Command(command);
- return Check_Response(response_buffer, buffer_size);
- }
- void MQTT_Process(void)
- {
- char response[256]; // 存放接收的响应数据
- int total_attempt = 0; // 总共跳回清除会话模式的次数
- int attempt = 0; // 每个步骤的重试次数
- int success = 0; // 是否成功标志位
- while (total_attempt < 5) { // 最多尝试5次清除会话模式
- total_attempt++; // 每次从头开始都计为一次清除会话模式的执行
- // 1. 清除会话模式
- attempt = 0; // 重置步骤重试计数
- while (attempt < 3) { // 每个步骤最多重试3次
- success = Send_Command_Check_Response("AT+MQTTCFG=\"clean\",0,1", response, sizeof(response));
- if (success)
- // printf("清除会话模式成功\n");
- break; // 成功则继续下一个步骤
- attempt++;
-
- }
- if (!success) continue; // 如果重试3次仍然失败,则重新开始整个流程
- HAL_Delay(1);
- // 2. 配置为接收缓存模式
- attempt = 0; // 重置步骤重试计数
- while (attempt < 3) {
- success = Send_Command_Check_Response("AT+MQTTCFG=\"cached\",0,1", response, sizeof(response));
- if (success) {
- printf("配置为接收缓存模式成功\n");
- break;
- }
- attempt++;
- }
- if (!success) continue; // 如果失败则重新开始整个流程
- HAL_Delay(1);
- // 3. 连接至MQTT服务器
- attempt = 0;
- while (attempt < 3) {
- success = Send_Command_Check_Response("AT+MQTTCONN=0,\"183.230.40.96\",1883,\"test0923_1\",\"0w8A8Kloxm\",\"version=2018-10-31&res=products%2F0w8A8Kloxm%2Fdevices%2Ftest0923_1&et=1853416411&method=md5&sign=VBoBVpruRrjQA6LjW2KEXw%3D%3D\"", response, sizeof(response));
- if (success) {
- printf("连接至MQTT服务器成功\n");
- break;
- }
- attempt++;
- }
- if (!success) continue;
- HAL_Delay(1);
- // 4. 订阅主题
- attempt = 0;
- while (attempt < 3) {
- success = Send_Command_Check_Response("AT+MQTTSUB=0,\"$sys/0w8A8Kloxm/test0923_1/#\",1", response, sizeof(response));
- if (success) {
- printf("订阅主题成功\n");
- break;
- }
- attempt++;
- }
- if (!success) continue;
- HAL_Delay(1);
- // 5. 发布消息
- attempt = 0;
- while (attempt < 3) {
- success = Send_Command_Check_Response("AT+MQTTPUB=0,\"$sys/0w8A8Kloxm/test0923_1/dp/post/json\",0,0,0,65,\"{\"id\":123,\"dp\":{\"gps\":[{\"v\":{\"lon\":20.898888,\"lat\":15.268888}}]}}\"", response, sizeof(response));
- if (success){
- printf("发布消息成功\n");
- break;
- }
- attempt++;
- }
- if (!success) continue;
- // // 6. 读取缓存数据
- // attempt = 0;
- // while (attempt < 3) {
- // success = Send_Command_Check_Response("AT+MQTTREAD=0,1", response, sizeof(response));
- // if (success) {
- // printf("读取缓存数据成功");
- // break;
- // }
- // attempt++;
- // }
- // if (!success) continue;
- // // 7. 断开连接
- // attempt = 0;
- // while (attempt < 3) {
- // success = Send_Command_Check_Response("AT+MQTTDISC=0", response, sizeof(response));
- // if (success) {
- // printf("断开连接成功");
- // break;
- // }
- // attempt++;
- // }
- // if (!success) continue;
- // 如果所有步骤都成功,则退出函数
- break;
- }
- // 如果达到5次还不成功,可以输出日志或执行其他错误处理
- if (total_attempt >= 5) {
- // 错误处理
- printf("MQTT连接失败,达到最大重试次数。\n");
- }
- }
- void ML307A_MQTT_Init(void)
- {
- // check_network_connection();
- char response[256]; // 存放接收的响应数据
- Send_Command_Check_Response("AT+MQTTDISC=0", response, sizeof(response));
- HAL_Delay(100);
- Send_Command_Check_Response("AT+MQTTCFG=\"clean\",0,1", response, sizeof(response));
- HAL_Delay(100);
- Send_Command_Check_Response("AT+MQTTCFG=\"cached\",0,1", response, sizeof(response));
- HAL_Delay(100);
- Send_Command_Check_Response("AT+MQTTCONN=0,\"106.14.207.159\",1883,\"BATT|securemode=2,signmethod=hmacsha1,timestamp=1729351701003|\",\"BATT&k1vccLJvsUy\",\"E664F110C5752BDB294C14ADC5594A673C6552B8\"", response, sizeof(response));
- HAL_Delay(100);
- Send_Command_Check_Response("AT+MQTTSUB=0,\"/sys/k1vccLJvsUy/BATT/thing/service/property/set\",1", response, sizeof(response));
- }
- int cpin_attempts = 0; // AT+CPIN计数3次的计数器
- void ML307A_NET_Init(void)
- {
- HAL_Delay(100);
- uint8_t step4g = 0;// 模组4G初始化步骤标志位
- char response[256]; // 存放接收的响应数据
- // if(Reset4G_flag)
- // {
- // Reset4G_flag = 0;
- // step4g = 0;
- // }
- switch(step4g)
- {
- case 0:
- {
- // if (sendCmd_4G("AT\r\n", "OK", 1, 4))
- HAL_Delay(10);
- if (Send_Command_Check_Response("AT", response, sizeof(response)))
- {
- printf("AT_OK\r\n");
- step4g++; // 进入下一步
- }else
- {
- printf("AT_fail\r\n");
- step4g++;
- }
- }
- case 1:
- {
- HAL_Delay(10);
- // if (sendCmd_4G("AT+CEREG?\r\n", "+CEREG:0,1", 1, 5))
- if (Send_Command_Check_Response("AT+CEREG?", response, sizeof(response)))
- {
- printf("CEREG_OK\r\n");
- HAL_Delay(500);
- step4g++; // 进入下一步
- cpin_attempts = 0; // 重置计数器
- }
- else
- {
- // cpin_attempts++; // 增加计数
- // if (cpin_attempts >= 3) // 如果已经发送了3次
- // {
- //// sendCmd_4G("AT+CGATT=1\r\n", "OK", 1, 5); // 手动驻网
- // Send_Command_Check_Response("AT+CGATT=1", response, sizeof(response));
- // HAL_Delay(100);
- // printf("CEREG_fail\r\n");
- // cpin_attempts = 0; // 重置计数器
- // }
- // Send_Command_Check_Response("AT+CGATT=1", response, sizeof(response));
- HAL_Delay(100);
- printf("CEREG_fail\r\n");
- step4g ++;
- }
- }
- case 2:
- {
- HAL_Delay(10);
- // sendCmd_4G("AT+CFUN=1\r\n", "OK", 1, 5); // 确保CFUN为1
- // if(Send_Command_Check_Response("AT+CFUN=1", response, sizeof(response)))
- // {
- // HAL_Delay(100);
- // step4g++; // 进入下一步
- // printf("AT+CFUN_ok\r\n");
- // }
- step4g++; // 进入下一步
- // else
- // {
- // step4g++; // 进入下一步
- // printf("AT+CFUN_fail\r\n");
- // }
- }
- case 3:
- {
- HAL_Delay(10);
- // 配置为自动连网(模组应用层网络)
- if(Send_Command_Check_Response("AT+MUECONFIG=\"autoconn\",1", response, sizeof(response)))
- {
- HAL_Delay(100);
- printf("AT+MUECONFIG_ok\r\n");
- step4g++; // 进入下一步
- }
- else
- {
- step4g++; // 进入下一步
- printf("AT+MUECONFIG_fail\r\n");
- }
- }
- case 4:
- {
- HAL_Delay(10);
- // 配置为自动拨号(上位机网卡拨号)
- if(Send_Command_Check_Response("AT+MDIALUPCFG=\"auto\",1", response, sizeof(response)))
- {
- HAL_Delay(100);
- step4g++; // 进入下一步
- printf("AT+MDIALUPCFG_ok\r\n");
- }
- else
- {
- step4g++; // 进入下一步
- printf("AT+MDIALUPCFG_fail\r\n");
- }
- }
- case 5:
- {
- HAL_Delay(10);
- ML307A_MQTT_Init(); // 初始化MQTT
- break;
- }
- case 7:
- {
- break;
- }
- }
- }
- /**
- * @breaf 重启模块
- */
- void ML307AReset(void)
- {
- HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET);
- HAL_Delay(500);
- HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_SET);
- HAL_Delay(2000);
- Reset4G_flag = 1;
- printf("Reset_4G\n");
- }
- void check_network_connection(void)
- {
- char response[100];
- // 发送 AT+CREG? 查询网络注册状态
- Send_Command_Check_Response("AT+CREG?", response, sizeof(response));
- HAL_Delay(10);
- // 检查是否已注册到网络,通常返回 0,1 或 0,5 代表已连接
- if (strstr(response, "0,1") == NULL && strstr(response, "0,5") == NULL) {
- // 如果未联网,执行联网操作
- Send_Command_Check_Response("AT+CGATT=1", response, sizeof(response));
- HAL_Delay(10);
- // 检查联网是否成功
- Send_Command_Check_Response("AT+CGATT?", response, sizeof(response));
- HAL_Delay(10);
- }else
- {
- ML307A_MQTT_Init();
- }
-
- }
- void ML307A_GNSS(void)
- {
- sendCmd_4G("AT+CPIN?\r\n", "+CPIN: READY", 1, 5);
- }
|