#include "EC801E.h" #include "stdio.h" #include "usart.h" #include "string.h" #include "cJSON.h" #include "uart_dev.h" #include "anemometer_dev.h" #define USE_UTC 1 // ID uint8_t g_devic_id[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; // 客户端名字 char g_cilent_name[] = "Test_cilent"; // 连接用户名 char g_cilent_user_name[] = "12345"; // 连接密码 char g_cilent_paaword[] = "12345"; // 服务器IP char g_server_ip[] = "199.7.140.10,1883"; // 订阅主题名 char g_topic_name[] = "Test_Topic_1"; // 时间戳 uint32_t g_time_stamp; // 最新一条信息发送时的时间戳 uint32_t trans_time_stamp; // 打开客户端网络标志 int flag_open_net = 0; // 连接服务器标志 int flag_connect = 0; // 订阅成功网络标志 int flag_sub = 0; // 发布信息标志 int flag_pubex = 0; void parse_json(uint8_t *json_buff); //控制上电并开机 void EC801E_Power_ON() { // PWR_KEY_4G_Pin低电平,上电自动开机 HAL_GPIO_WritePin(GPIO_4G_PWR_KEY_GPIO_Port, GPIO_4G_PWR_KEY_Pin, GPIO_PIN_SET); //上电 HAL_GPIO_WritePin(GPIO_4G_PWR_CTRL_GPIO_Port, GPIO_4G_PWR_CTRL_Pin, GPIO_PIN_RESET); HAL_Delay(1000); HAL_GPIO_WritePin(GPIO_4G_PWR_CTRL_GPIO_Port, GPIO_4G_PWR_CTRL_Pin, GPIO_PIN_SET); } //开机状态检测 //HAL_OK:正常开机 uint8_t Read_Status() { uint8_t temp_status = HAL_ERROR; temp_status = HAL_GPIO_ReadPin(GPIO_4G_STATUS_GPIO_Port, GPIO_4G_STATUS_Pin) == GPIO_PIN_SET ? HAL_OK : HAL_ERROR; return temp_status; } //串口重定向打印 size_t __write(int handle, const unsigned char * buffer, size_t size) { if(HAL_OK == HAL_UART_Transmit(&huart1,(uint8_t *)buffer,size,100000)) { return size; } else { return -1; } } // MQTT打开客户端网络.连接MQTT服务器.订阅 // ip,端口,客户端ID(0-5),客户端名称,用户名,密码,订阅主题名 void MQTT_Config() { // 确保4G模块完全开机 osDelay(5000); // 打开客户端网络 while(!flag_open_net) { // uart_sendstr(g_ec801_uart_handle, "AT+QMTOPEN=0,199.7.140.10,1883\r\n"); uart_sendstr(g_ec801_uart_handle, "AT+QMTOPEN=0,"); uart_sendstr(g_ec801_uart_handle, g_server_ip); uart_sendstr(g_ec801_uart_handle, "\r\n"); osDelay(5000); }flag_open_net = 0; // 连接服务器 while(!flag_connect) { uart_sendstr(g_ec801_uart_handle, "AT+QMTCONN=0,"); uart_sendstr(g_ec801_uart_handle, g_cilent_name); uart_sendstr(g_ec801_uart_handle, ","); uart_sendstr(g_ec801_uart_handle, g_cilent_user_name); uart_sendstr(g_ec801_uart_handle, ","); uart_sendstr(g_ec801_uart_handle, g_cilent_paaword); uart_sendstr(g_ec801_uart_handle, "\r\n"); osDelay(5000); }flag_connect = 0; // 订阅主题 while(!flag_sub) { uart_sendstr(g_ec801_uart_handle, "AT+QMTSUB=0,0,"); uart_sendstr(g_ec801_uart_handle, g_topic_name); uart_sendstr(g_ec801_uart_handle, ",0\r\n"); osDelay(5000); }flag_sub = 0; } void EC801_start() { EC801E_Power_ON(); osDelay(5000); while(!EC801_GET_Time()); MQTT_Config(); } // MQTT发送数据 void MQTT_Trans_Data() { //字符串长度 uint8_t str_len = 0; char str_len_str[32]; //创建获取数据指针 float32_t *ptr = (float32_t *)&g_stMcs_Para; // 创建JSON数组及对象 char *cjson_str = NULL; cJSON * JsonRoot = cJSON_CreateObject(); cJSON * DataArray = cJSON_CreateArray(); //将uint8的ID存到字符串内 char deviId_str[15]; snprintf(deviId_str, sizeof(deviId_str), "%X%X%X%X%X%X%X", g_devic_id[0], \ g_devic_id[1], \ g_devic_id[2], \ g_devic_id[3], \ g_devic_id[4], \ g_devic_id[5], \ g_devic_id[6]); trans_time_stamp = g_time_stamp;// 将发送时时间戳存入最新发送时间时间戳 cJSON_AddStringToObject(JsonRoot, "deviId", deviId_str); cJSON_AddStringToObject(JsonRoot, "frameType", "item_type"); cJSON_AddNumberToObject(JsonRoot, "timeStamp", g_time_stamp); cJSON_AddNumberToObject(JsonRoot, "version", 10); cJSON_AddItemToObject(JsonRoot, "data", DataArray);//添加data数组 for(int i = 0; i < sizeof(mcs_para)/sizeof(float32_t) - 2; i++)// 雨量光辐射还是空气 { cJSON_AddItemToArray(DataArray, cJSON_CreateNumber(((float)((int )(ptr[i] * 100 + 0.5)))/100.0));// 四舍五入两位小数 } // 对象转字符串 cjson_str = cJSON_Print(JsonRoot); str_len = strlen(cjson_str) + 2 + 4; sprintf(str_len_str, "%d", str_len); while(!flag_pubex) { // 发送发数据包命令 uart_sendstr(g_ec801_uart_handle, "AT+QMTPUBEX=0,0,0,0,"); uart_sendstr(g_ec801_uart_handle, g_topic_name); uart_sendstr(g_ec801_uart_handle, ","); uart_sendstr(g_ec801_uart_handle, str_len_str); uart_sendstr(g_ec801_uart_handle, "\r\n"); //发送数据包 osDelay(2000); uart_sendstr(g_ec801_uart_handle, cjson_str); HAL_Delay(3000); }flag_pubex = 0; //释放 vPortFree(cjson_str); cJSON_Delete(JsonRoot); } // 判断闰年,1闰0平 uint16_t fml_leap_year(uint16_t year) { return (((year % 4 == 0)&&(year % 100 != 0)) || (year % 400 == 0)); } //日期转时间戳 uint32_t fml_time_to_stamp(int year, int month, int day, int hour, int minute, int second) { static uint32_t dax = 0; static uint32_t day_count = 0; uint16_t leap_year_count = 0; uint16_t i; // 计算闰年数 for (i = 1970; i < year; i++) { if (fml_leap_year(i)) { leap_year_count++; } } // 计算年的总天数 day_count = leap_year_count * 366 + (year - 1970 - leap_year_count) * 365; uint8_t mouthday[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; // 计算当年到当前月的所有天数 for (i = 1; i < month; i++) { day_count += mouthday[i]; } if(fml_leap_year(year)) { day_count += 1; } // 累加计算当月的天数 day_count += (day - 1); dax = (uint32_t)(day_count * 86400) + (uint32_t)((uint32_t)hour * 3600) + (uint32_t)((uint32_t)minute * 60) + (uint32_t)second; return dax; } //时间获取完成变量,用于控制是否开始MQTT信息接收 uint8_t time_get_ok = 0; // 生成时间戳 int EC801_GET_Time() { int year, month, day, hour, minute, second; if(USE_UTC) { uart_sendstr(g_ec801_uart_handle, "AT+QLTS=0\r\n"); }else { uart_sendstr(g_ec801_uart_handle, "AT+QLTS=2\r\n"); } osDelay(1000); char time[100] = {0};int index = 0; // 第一个“后是时间,前面不要 do{ time[index] = uart_dev_in_char(g_ec801_uart_handle); }while(time[index++] != '"' && uart_dev_char_present(g_ec801_uart_handle)); // 丢掉前面的 memcpy(time, time + index - 1, index); index = 1; // "前面是时间 do{ time[index] = uart_dev_in_char(g_ec801_uart_handle); }while(time[index++] != '"' && uart_dev_char_present(g_ec801_uart_handle)); // 字符提取成int sscanf(time, "\"%d/%d/%d,%d:%d:%d\"", &year, &month, &day, &hour, &minute, &second); if(year) { time_get_ok = 1; } // 生成时间戳 g_time_stamp = fml_time_to_stamp(year, month, day, hour, minute, second); return year; } #define JSON_BUFFER_SIZE 200 // 解析收到的4g模块数据 void parse_4g_receive_data() { if(uart_dev_char_present(g_ec801_uart_handle)){ int temp_5_index = 0; char temp_5_char[5] = {0}; int AT_Command_flag = 0; int Command_index = 0; char AT_Command[10] = {0}; int AT_Command_ok_flag = 0; int AT_data_ok_flag = 0; uint8_t temp_buff[JSON_BUFFER_SIZE]; int temp_buff_index = 0; // 索引 char c = 0; int inJson = 0; memset(temp_buff, '\0', sizeof(temp_buff));//每次接受前清空一下BUFF for(; uart_dev_char_present(g_ec801_uart_handle);) { // 思路:挨个解析,每次解析3个字符存入BUFFER,依次后移,检测到+后看前面两个 // 如果前面两个是AT,则继续解析 // 如果前面两个不是AT,则将从+开始到:的内容都存入命令BUFF // 根据 命令BUFF 处理后面的数据 c = uart_dev_in_char(g_ec801_uart_handle); temp_5_char[temp_5_index] = c; if(c == '+') { if(temp_5_char[(temp_5_index + 4)%5] == 'T' && temp_5_char[(temp_5_index + 3)%5] == 'A')// 判断 + 前是不是AT { } else { AT_Command_flag = 1; } } temp_5_index = (temp_5_index + 1)%5;//更新索引 // 读命令 if(AT_Command_flag){ AT_Command[Command_index] = c;// 存入命令Buff if(AT_Command[Command_index] == ':')// :后面是状态 { AT_Command_flag = 0;// 命令读完 AT_Command_ok_flag = 1; } Command_index ++; } // 命令读完,根据命令匹配反馈数据 if(AT_Command_ok_flag) { // term_printf(AT_Command); // 打开QMTT客户端反馈 if(strstr(AT_Command, "QMTOPEN")) { temp_buff[temp_buff_index] = c; if(temp_buff[temp_buff_index] == '\r'||temp_buff[temp_buff_index] == '\n') { // 处理完归零 AT_Command_ok_flag = 0; memset(AT_Command, 0, 10); // 处理读完之后的数据 int client_idx, result; sscanf(temp_buff, ": %d,%d", &client_idx, &result); // 打开完成 if(result == 0) { flag_open_net = 1; } return; } temp_buff_index ++; } // 连接服务器反馈 if(strstr(AT_Command, "QMTCONN")) { temp_buff[temp_buff_index] = c; if(temp_buff[temp_buff_index] == '\r'||temp_buff[temp_buff_index] == '\n') { // 处理完归零 AT_Command_ok_flag = 0; memset(AT_Command, 0, 10); // 处理读完之后的数据 int client_idx, result, ret_code; sscanf(temp_buff, ": %d,%d,%d", &client_idx, &result, &ret_code); // 连接完成 if(result == 0 && ret_code == 0) { flag_connect = 1; } return; } temp_buff_index ++; } // 订阅主题反馈 if(strstr(AT_Command, "QMTSUB")) { temp_buff[temp_buff_index] = c; if(temp_buff[temp_buff_index] == '\r'||temp_buff[temp_buff_index] == '\n') { // 处理完归零 AT_Command_ok_flag = 0; memset(AT_Command, 0, 10); // 处理读完之后的数据 int client_idx, msgID, result, value; sscanf(temp_buff, ": %d,%d,%d,%d", &client_idx, &msgID, &result, &value); // 连接完成 if(result == 0) { flag_sub = 1; } return; } temp_buff_index ++; } // 发布消息反馈 if(strstr(AT_Command, "QMTPUBEX")) { temp_buff[temp_buff_index] = c; if(temp_buff[temp_buff_index] == '\r'||temp_buff[temp_buff_index] == '\n') { // 处理完归零 AT_Command_ok_flag = 0; memset(AT_Command, 0, 10); // 处理读完之后的数据 int client_idx, msgID, result, value; sscanf(temp_buff, ": %d,%d,%d,%d", &client_idx, &msgID, &result, &value); // 连接完成 if(result == 0 || result == 1) { flag_pubex = 1; } return; } temp_buff_index ++; } // 收到消息反馈+++++收到json if(strstr(AT_Command, "QMTRECV")) { if (c == '{') { AT_data_ok_flag = 1; } if (AT_data_ok_flag == 1) { temp_buff[temp_buff_index] = c; if (temp_buff[temp_buff_index] == '}') { // 处理完归零 AT_data_ok_flag = 0; memset(AT_Command, 0, 10); // 接收完了 if(temp_buff[0] != '\0') { parse_json(temp_buff); } // term_printf(temp_buff); return; } temp_buff_index ++; } } } } } } extern int trans_4g_flag; // 收到json数据处理 void parse_json(uint8_t *json_buff) { cJSON* cjson_root = cJSON_Parse(json_buff); if(cjson_root == NULL) { term_printf("parse fail.\n"); return; } cJSON* cjson_id = cJSON_GetObjectItem(cjson_root, "deviId"); cJSON* cjson_type = cJSON_GetObjectItem(cjson_root, "frameType"); cJSON* cjson_version = cJSON_GetObjectItem(cjson_root, "version"); cJSON* cjson_response = cJSON_GetObjectItem(cjson_root, "response"); cJSON* cjson_time = cJSON_GetObjectItem(cjson_root, "timeStamp"); cJSON* cjson_cmd = cJSON_GetObjectItem(cjson_root, "cmd"); // 取出数据 char *temp_id = cjson_id -> valuestring; char *temp_type = cjson_type -> valuestring; int temp_version = cjson_version -> valueint; int temp_response = cjson_response -> valueint; int temp_time = cjson_time -> valueint; int temp_cmd = cjson_cmd -> valueint; term_printf("deviId=%s\n frameType=%s\n version=%d\n response=%d\n timeStamp=%d\n cmd=%d", temp_id, temp_type, temp_version, temp_response, temp_time, temp_cmd); cJSON_Delete(cjson_root); // 与发送时间不一样才处理 if(temp_time != trans_time_stamp) { term_printf("1111"); if(temp_cmd == 1) { trans_4g_flag = 1; } } // 数据处理 // if(abs(temp_time - g_time_stamp) >= 120) // { // g_time_stamp = temp_time; // } }