#include "stm32f10x.h" #include #include #include #include #include "AT.h" #include "EC800M_UDP_Client5.h" #include "CoAP.h" #include "mbedtls_util.h" #include "cJSON.h" #include "sys.h" #include "ec800m.h" #include "pump_dicts.h" #include "INflash.h" // 流程 enum Step{ STEP_NONE, // 空闲状态,无操作 STEP_START, // 开始 STEP_EXIT_SLEEP, // 退出睡眠 STEP_ENTER_SLEEP, // 进入睡眠 STEP_WAIT, // 等待 STEP_STATE, // 查询状态 STEP_OPEN, // 打开 STEP_OPEN_WAIT_RESULT, // 等待打开结果 STEP_JUDGE_AUTH_OR_DATA, // 判断认证还是发送 STEP_JOIN_AUTH_MESSAGE, // 拼接认证报文 STEP_JOIN_DATA_MESSAGE, // 拼接数据报文 STEP_QUERY_SLEEP, // 查询休眠 STEP_SET_SLEEP, // 开启休眠 STEP_SET_QISDE_0, // 关闭发送回显 STEP_SEND, // 发送 STEP_RECV, // 等待发送结果 STEP_SET_CFUN_0, // 设置最小功能模式 STEP_WAIT_SET_CFUN_0, // 等待设置最小功能模式 STEP_SET_CFUN_1, // 设置全功能模式 STEP_WAIT_SET_CFUN_1, // 等待设置全功能模式结果 STEP_SET_CGREG_2, // 设置ps域允许上报网络注册和位置信息 STEP_QUERY_CGREG, // 查询网络注册状态 STEP_CLOSE, // 关闭 STEP_SUCCESS, // 成功 STEP_FAILURE, // 失败 STEP_FINISH, // 流程结束 }; // 当前 static enum Step step = STEP_NONE; // 下一步 static enum Step next_step = STEP_NONE; // 客户端5 struct EC800M_Client_Struct UDP_Client5 = { .status = Client_Status_None, }; // 注册后的参数 extern Coefficient_Data flashdata; // socket ID static uint8_t connectID = 5; /** 阿里云连接参数 **/ static char ProductKey[20] = "a1t3qlUNDcP"; static char DeviceName[20] = "LTEcat1ceshi001"; static char DeviceSecret[40] = "4929a78860f663ec72e2c313a4eee7ac"; static char ClientID[60]; static char Seq[10] = "666"; static uint16_t Port = 5682; static char Host[60]; static uint32_t SeqOffset; static char Random[20]; static char Token[50]; // payload缓存 //static uint8_t payload[256]; //static uint16_t payload_length; // coap报文 static uint8_t coap_message[512]; static uint16_t coap_message_length = 0; // aes cbc static uint8_t aes_key[16] = {0}; static char iv[] = "543yhjy97ae7fyfg"; // 泵参数 static struct Pump_Params pump_params; // 待发送数据的地址和长度 static uint8_t data[128]; static uint16_t data_length; // 计时相关的变量 uint8_t Client5_time_flag = 0; uint32_t Client5_timer_ms = 0; uint32_t Client5_wait_time = 10; // 初始化 void UDP_Client5_Init(void) { // 赋值三元组 strcpy(ProductKey, flashdata.productKey); strcpy(DeviceName, flashdata.deviceName); strcpy(DeviceSecret, flashdata.deviceSecret); // 设置host memset(Host, '\0', sizeof(Host)); strcat(Host, ProductKey); strcat(Host, ".coap.cn-shanghai.link.aliyuncs.com"); // 设置clientid memset(ClientID, '\0', sizeof(ClientID)); strcat(ClientID, ProductKey); strcat(ClientID, "&"); strcat(ClientID, DeviceName); } // 声明函数。步骤跳转 void goto_step(enum Step ns); // 发送流程 void UDP_Client5_Handle(void); // 发送数据 void UDP_Client5_Send(struct Pump_Params params) { if(step == STEP_NONE) { // 待发送数据的地址和长度 pump_params = params; // 初始化 UDP_Client5_Init(); // 正在发送 UDP_Client5.status = Client_Status_Sending; // 流程开始 goto_step(STEP_START); } } // 获取状态 enum Client_Status UDP_Client5_Status(void) { if(UDP_Client5.status == Client_Status_None) { return UDP_Client5.status; } else if(step == STEP_FINISH) { return UDP_Client5.status; } else { return Client_Status_Sending; } } // 清除 void UDP_Client5_Clear(void) { // 流程置空 goto_step(STEP_NONE); // 空闲 UDP_Client5.status = Client_Status_None; } // 直接跳转到下一步 static void goto_step(enum Step ns) { // 重置ec800m状态 ec800m.reset(); step = ns; } // 先等待再跳转到下一步 static void goto_step_wait(enum Step ns, uint32_t t) { goto_step(STEP_WAIT); // 等待 Client5_wait_time = t; next_step = ns; // 等待之后跳转 } // 只等待,等待之后返回原来的步骤 static void goto_wait(uint32_t t) { goto_step_wait(step, t); } // 失败 static void goto_failure(char * info) { Log_Printf_Debug("STEP: 数据发送失败,%s\r\n", info); UDP_Client5.status = Client_Status_Failure; strcpy(UDP_Client5.info, info); goto_step(STEP_FAILURE); } // 成功 static void goto_success(char * info) { Log_Printf_Debug("STEP: 数据发送成功,%s\r\n", info); UDP_Client5.status = Client_Status_Success; strcpy(UDP_Client5.info, info); goto_step(STEP_SUCCESS); } // 等待 static void wait(void) { if(Client5_time_flag == 0) { Client5_timer_ms = 0; Client5_time_flag = 1; } else if(Client5_timer_ms > Client5_wait_time) { goto_step(next_step); // 进入下一步 Client5_time_flag = 0; } } // 判断认证还是发送 static uint8_t judge_auth_or_data(void) { if(strlen(Token) > 0) // 已认证 { return 1; } else { return 0; } } // 拼接认证报文 static void join_auth_message(uint8_t * coap_message, uint16_t * coap_message_length) { SeqOffset=65535; Log_Printf_Debug("STEP: 拼接认证报文,seqOffset=%d\r\n", SeqOffset); // 先清除 // memset(coap_message, 0, sizeof(coap_message)); // coap_message_length = 0; // CoAP协议 CoAP_Init(); CoAP_Set_T(0); CoAP_Set_Code(2); CoAP_Set_MessageID(SeqOffset); // option // host CoAP_Set_Option_Str(3, Host); // port CoAP_Set_Option_Short(7, Port); // path CoAP_Set_Option_Str(11, "auth"); // content-format CoAP_Set_Option_Short(12, 50); // accept CoAP_Set_Option_Short(17, 50); // 待签名数据 // 签名相关 static char StrForSignature[100]; static char sign[50]; memset(StrForSignature, '\0', sizeof(StrForSignature)); sprintf((char * )StrForSignature, "clientId%sdeviceName%sproductKey%sseq%s", ClientID, DeviceName, ProductKey, Seq); // 签名 memset(sign, '\0', sizeof(sign)); utils_hmac_sha1_str(StrForSignature, strlen((char * )StrForSignature), sign, DeviceSecret, strlen(DeviceSecret)); // payload // memset(payload, '\0', sizeof(payload)); char payload[256] = {0}; sprintf((char * )payload, "{\"clientId\":\"%s\",\"signmethod\":\"hmacsha1\",\"sign\":\"%s\",\"productKey\":\"%s\",\"deviceName\":\"%s\",\"seq\":\"%s\"}", ClientID, sign, ProductKey, DeviceName, Seq); // 设置payload CoAP_Set_Payload_Str(payload); // 生成报文 * coap_message_length = CoAP_Get_Length(); memcpy(coap_message, CoAP_Get_Message(), * coap_message_length); } // 拼接数据报文 static void join_data_message(uint8_t * data, uint8_t data_length, uint8_t * coap_message, uint16_t * coap_message_length) { SeqOffset++; Log_Printf_Debug("STEP: 拼接数据报文,seqOffset=%d\r\n", SeqOffset); // 先清除 // memset(coap_message, 0, sizeof(coap_message)); // coap_message_length = 0; char out[80]={0}; char sha256_source[100] = {0}; snprintf(sha256_source, sizeof(sha256_source), "%s,%s" ,DeviceSecret ,Random); Log_Printf_Debug("sha256_source: %s\r\n", sha256_source); utils_sha256(sha256_source, strlen(sha256_source), out); memset(aes_key, 0, sizeof(aes_key)); memcpy(aes_key, out+8, 16); //获取key // CoAP协议 CoAP_Init(); CoAP_Set_T(0); CoAP_Set_Code(2); CoAP_Set_MessageID(SeqOffset); // option // host CoAP_Set_Option_Str(3, Host); // port CoAP_Set_Option_Short(7, Port); // path CoAP_Set_Option_Str(11, "topic"); CoAP_Set_Option_Str(11, "sys"); CoAP_Set_Option_Str(11, ProductKey); CoAP_Set_Option_Str(11, DeviceName); CoAP_Set_Option_Str(11, "thing"); CoAP_Set_Option_Str(11, "model"); CoAP_Set_Option_Str(11, "up_raw"); // content-format CoAP_Set_Option_Short(12, 50); // accept CoAP_Set_Option_Short(17, 50); // 2088 CoAP_Set_Option_Str(2088, Token); // 2089 char Rand2089[10] = {'\0'}; char Opt2089[20] = {'\0'}; my_itoa(SeqOffset, Rand2089, 10); int Opt2089_Length = utils_aes128_cbc_enc((char * )aes_key, iv, Rand2089, Opt2089); CoAP_Set_Option_Str(2089, Opt2089); // payload // memset(payload, '\0', sizeof(payload)); uint8_t payload[256] = {0}; // int payload_length = utils_aes128_cbc_enc_with_length((char * )aes_key, iv, data, data_length, payload); // payload_length = utils_aes128_cbc_enc((char * )aes_key, iv, (char * )Data_Buffer, (char * )payload); Log_Printf_Debug("payload_length: %d\r\n", payload_length); CoAP_Set_Payload(payload, payload_length); // 生成报文 * coap_message_length = CoAP_Get_Length(); memcpy(coap_message, CoAP_Get_Message(), * coap_message_length); } // 等待数据返回 static uint8_t recv_data_handle(uint8_t * coap_message, uint16_t coap_message_length) { uint16_t payload_length = CoAP_Get_Payload_Length(coap_message, coap_message_length); uint8_t payload[256] = {0}; CoAP_Get_Payload(coap_message, coap_message_length, payload); Log_Printf_Debug("payload长度: %d\r\n", payload_length); // 判断是认证返回,还是数据发送返回 if(payload_length == 0) // 无返回 { // 清空Token,重新认证 memset(Token, '\0', sizeof(Token)); return 0; } else if(payload[0] == '{' && payload[payload_length-1] == '}') // 认证返回 { // 解析json cJSON * cjson = cJSON_Parse((char * )payload); Log_Printf_Debug("plaintext(%d): %s\r\n",payload_length, payload); memset(Random, '\0', sizeof(Random)); memset(Token, '\0', sizeof(Token)); if(cJSON_HasObjectItem(cjson, "random")) { char * random = cJSON_GetObjectItem(cjson, "random")->valuestring; strcpy(Random, random); } if(cJSON_HasObjectItem(cjson, "seqOffset")) { uint16_t seqOffset = cJSON_GetObjectItem(cjson, "seqOffset")->valueint; SeqOffset = seqOffset; } if(cJSON_HasObjectItem(cjson, "token")) { char * token = cJSON_GetObjectItem(cjson, "token")->valuestring; strcpy(Token, token); } Log_Printf_Debug("\r\n(%s, %s, %d)\r\n", Random, Token, SeqOffset); cJSON_Delete(cjson);//清除结构体 return 1; } else { // 数据发送成功返回 uint8_t plaintext[256] = {0}; // 明文 uint16_t plaintext_length = utils_aes128_cbc_dec((char * )aes_key, iv, (char * )payload, payload_length, (char * )plaintext); Log_Printf_Debug("\r\nplaintext(%d): %s\r\n",plaintext_length, (char *)plaintext); return 2; } } // 发送数据的逻辑 static enum Result result = Result_None; static uint8_t cgreg_n; static uint8_t cgreg_stat; static uint16_t cgreg_lac; static uint32_t cgreg_ci; static uint8_t query_cgreg_times = 0; // 查询网络状态的次数 static uint8_t auth_times = 0; // 认证次数 static uint16_t socket_err = 0; static uint8_t auth_or_data = 0; void UDP_Client5_Handle(void) { // 流程 switch(step) { case STEP_NONE: // 空闲 break; case STEP_START: // 开始 query_cgreg_times = 0; // 查询网络状态的次数 auth_times = 0; // 认证次数 goto_step(STEP_EXIT_SLEEP); break; case STEP_EXIT_SLEEP: // 退出休眠 ec800m.exit_sleep(); goto_step_wait(STEP_SET_CFUN_1, 3); break; case STEP_SET_CFUN_1: // 设置全功能模式 result = ec800m.set_cfun(1); if(result == Result_Success) { goto_step(STEP_SET_CGREG_2); } else if(result == Result_Failed) { goto_failure("设置全功能模式失败"); } break; case STEP_SET_CGREG_2: // 设置ps域 result = ec800m.set_cgreg(2); if(result == Result_Success) { goto_step(STEP_QUERY_CGREG); } else if(result == Result_Failed) { goto_failure("设置ps域失败"); } break; case STEP_QUERY_CGREG: // 查询ps域 result = ec800m.query_cgreg(&cgreg_n, &cgreg_stat, &cgreg_lac, &cgreg_ci); if(result == Result_Success) { if(cgreg_stat == 1) { // 参数赋值 pump_params.lac = cgreg_lac; pump_params.ci = cgreg_ci; // 编码 business_protocol_encode(pump_params, data, &data_length); // 下一步 goto_step(STEP_CLOSE); } else if(query_cgreg_times > 10) // 最多查询20次 { goto_failure("查询ps域次数过多"); } else { goto_wait(400); query_cgreg_times++; } } else if(result == Result_Failed) { goto_failure("查询ps域失败"); } break; case STEP_CLOSE: // 关闭连接 result = ec800m.close_socket(connectID); if(result == Result_Success) { goto_step(STEP_OPEN); } else if(result == Result_Failed) { goto_failure("关闭连接失败"); } break; case STEP_OPEN: // 打开客户端 result = ec800m.open_socket(connectID, "UDP", Host, Port, 1, &socket_err); if(result == Result_Success) { if(socket_err == 0) { goto_step(STEP_JUDGE_AUTH_OR_DATA); } else { goto_failure("客户端打开错误"); } } else if(result == Result_Failed) { goto_failure("打开客户端失败"); } break; case STEP_JUDGE_AUTH_OR_DATA: // 判断认证还是发送 auth_or_data = judge_auth_or_data(); if(auth_or_data == 1) // 已认证 { goto_step(STEP_JOIN_DATA_MESSAGE); } else { goto_step(STEP_JOIN_AUTH_MESSAGE); } break; case STEP_JOIN_AUTH_MESSAGE: // 拼接认证报文 if(auth_times > 0) // 最多重新认证一次 { goto_failure("认证次数过多"); } else { join_auth_message(coap_message, &coap_message_length); goto_step(STEP_SET_QISDE_0); auth_times++; } break; case STEP_JOIN_DATA_MESSAGE: // 拼接数据报文 join_data_message(data, data_length, coap_message, &coap_message_length); goto_step(STEP_SET_QISDE_0); break; case STEP_SET_QISDE_0: // 关闭发送回显 result = ec800m.set_qisde(0); if(result == Result_Success) { goto_step(STEP_SEND); } else if(result == Result_Failed) { goto_failure("关闭发送回显失败"); } break; case STEP_SEND: // 发送send result = ec800m.send(connectID, coap_message, coap_message_length); if(result == Result_Success) { goto_step(STEP_RECV); } else if(result == Result_Failed) { goto_failure("发送send失败"); } break; case STEP_RECV: // 等待结果 result = ec800m.recv_with_time(connectID, coap_message, &coap_message_length, 10000); if(result == Result_Success) { uint8_t res = recv_data_handle(coap_message, coap_message_length); if(res == 0) // 发送失败 { goto_step(STEP_JUDGE_AUTH_OR_DATA); // 重新认证 } else if(res == 1) // 认证成功 { goto_step(STEP_JOIN_DATA_MESSAGE); } else if(res == 2) // 发送成功 { goto_success("发送成功"); } } else if(result == Result_Failed) { goto_failure("等待结果失败"); } break; case STEP_WAIT: // 等待 wait(); break; case STEP_SUCCESS: // 成功 goto_step(STEP_SET_SLEEP); break; case STEP_FAILURE: // 失败 goto_step(STEP_SET_SLEEP); break; case STEP_SET_SLEEP: // 设置休眠模式 result = ec800m.set_sleep(1); if(result != Result_None) { goto_step(STEP_SET_CFUN_0); } break; case STEP_SET_CFUN_0: // 设置最小功能模式 result = ec800m.set_cfun(0); if(result != Result_None) { goto_step(STEP_ENTER_SLEEP); } break; case STEP_ENTER_SLEEP: // 进入睡眠 ec800m.enter_sleep(); goto_step(STEP_FINISH); break; case STEP_FINISH: // 结束流程 break; default: break; } }