EC800M_UDP_Client5.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618
  1. #include "stm32f10x.h"
  2. #include <stdio.h>
  3. #include <stdarg.h>
  4. #include <string.h>
  5. #include <stdlib.h>
  6. #include "AT.h"
  7. #include "EC800M_UDP_Client5.h"
  8. #include "CoAP.h"
  9. #include "mbedtls_util.h"
  10. #include "cJSON.h"
  11. #include "sys.h"
  12. #include "ec800m.h"
  13. #include "pump_dicts.h"
  14. #include "INflash.h"
  15. // 流程
  16. enum Step{
  17. STEP_NONE, // 空闲状态,无操作
  18. STEP_START, // 开始
  19. STEP_EXIT_SLEEP, // 退出睡眠
  20. STEP_ENTER_SLEEP, // 进入睡眠
  21. STEP_WAIT, // 等待
  22. STEP_STATE, // 查询状态
  23. STEP_OPEN, // 打开
  24. STEP_OPEN_WAIT_RESULT, // 等待打开结果
  25. STEP_JUDGE_AUTH_OR_DATA, // 判断认证还是发送
  26. STEP_JOIN_AUTH_MESSAGE, // 拼接认证报文
  27. STEP_JOIN_DATA_MESSAGE, // 拼接数据报文
  28. STEP_QUERY_SLEEP, // 查询休眠
  29. STEP_SET_SLEEP, // 开启休眠
  30. STEP_SET_QISDE_0, // 关闭发送回显
  31. STEP_SEND, // 发送
  32. STEP_RECV, // 等待发送结果
  33. STEP_SET_CFUN_0, // 设置最小功能模式
  34. STEP_WAIT_SET_CFUN_0, // 等待设置最小功能模式
  35. STEP_SET_CFUN_1, // 设置全功能模式
  36. STEP_WAIT_SET_CFUN_1, // 等待设置全功能模式结果
  37. STEP_SET_CGREG_2, // 设置ps域允许上报网络注册和位置信息
  38. STEP_QUERY_CGREG, // 查询网络注册状态
  39. STEP_CLOSE, // 关闭
  40. STEP_SUCCESS, // 成功
  41. STEP_FAILURE, // 失败
  42. STEP_FINISH, // 流程结束
  43. };
  44. // 当前
  45. static enum Step step = STEP_NONE;
  46. // 下一步
  47. static enum Step next_step = STEP_NONE;
  48. // 客户端5
  49. struct EC800M_Client_Struct UDP_Client5 = {
  50. .status = Client_Status_None,
  51. };
  52. // 注册后的参数
  53. extern Coefficient_Data flashdata;
  54. // socket ID
  55. static uint8_t connectID = 5;
  56. /** 阿里云连接参数 **/
  57. static char ProductKey[20] = "a1t3qlUNDcP";
  58. static char DeviceName[20] = "LTEcat1ceshi001";
  59. static char DeviceSecret[40] = "4929a78860f663ec72e2c313a4eee7ac";
  60. static char ClientID[60];
  61. static char Seq[10] = "666";
  62. static uint16_t Port = 5682;
  63. static char Host[60];
  64. static uint32_t SeqOffset;
  65. static char Random[20];
  66. static char Token[50];
  67. // payload缓存
  68. //static uint8_t payload[256];
  69. //static uint16_t payload_length;
  70. // coap报文
  71. static uint8_t coap_message[512];
  72. static uint16_t coap_message_length = 0;
  73. // aes cbc
  74. static uint8_t aes_key[16] = {0};
  75. static char iv[] = "543yhjy97ae7fyfg";
  76. // 泵参数
  77. static struct Pump_Params pump_params;
  78. // 待发送数据的地址和长度
  79. static uint8_t data[128];
  80. static uint16_t data_length;
  81. // 计时相关的变量
  82. uint8_t Client5_time_flag = 0;
  83. uint32_t Client5_timer_ms = 0;
  84. uint32_t Client5_wait_time = 10;
  85. // 初始化
  86. void UDP_Client5_Init(void)
  87. {
  88. // 赋值三元组
  89. strcpy(ProductKey, flashdata.productKey);
  90. strcpy(DeviceName, flashdata.deviceName);
  91. strcpy(DeviceSecret, flashdata.deviceSecret);
  92. // 设置host
  93. memset(Host, '\0', sizeof(Host));
  94. strcat(Host, ProductKey);
  95. strcat(Host, ".coap.cn-shanghai.link.aliyuncs.com");
  96. // 设置clientid
  97. memset(ClientID, '\0', sizeof(ClientID));
  98. strcat(ClientID, ProductKey);
  99. strcat(ClientID, "&");
  100. strcat(ClientID, DeviceName);
  101. }
  102. // 声明函数。步骤跳转
  103. void goto_step(enum Step ns);
  104. // 发送流程
  105. void UDP_Client5_Handle(void);
  106. // 发送数据
  107. void UDP_Client5_Send(struct Pump_Params params)
  108. {
  109. if(step == STEP_NONE)
  110. {
  111. // 待发送数据的地址和长度
  112. pump_params = params;
  113. // 初始化
  114. UDP_Client5_Init();
  115. // 正在发送
  116. UDP_Client5.status = Client_Status_Sending;
  117. // 流程开始
  118. goto_step(STEP_START);
  119. }
  120. }
  121. // 获取状态
  122. enum Client_Status UDP_Client5_Status(void)
  123. {
  124. if(UDP_Client5.status == Client_Status_None)
  125. {
  126. return UDP_Client5.status;
  127. }
  128. else if(step == STEP_FINISH)
  129. {
  130. return UDP_Client5.status;
  131. }
  132. else
  133. {
  134. return Client_Status_Sending;
  135. }
  136. }
  137. // 清除
  138. void UDP_Client5_Clear(void)
  139. {
  140. // 流程置空
  141. goto_step(STEP_NONE);
  142. // 空闲
  143. UDP_Client5.status = Client_Status_None;
  144. }
  145. // 直接跳转到下一步
  146. static void goto_step(enum Step ns)
  147. {
  148. // 重置ec800m状态
  149. ec800m.reset();
  150. step = ns;
  151. }
  152. // 先等待再跳转到下一步
  153. static void goto_step_wait(enum Step ns, uint32_t t)
  154. {
  155. goto_step(STEP_WAIT); // 等待
  156. Client5_wait_time = t;
  157. next_step = ns; // 等待之后跳转
  158. }
  159. // 只等待,等待之后返回原来的步骤
  160. static void goto_wait(uint32_t t)
  161. {
  162. goto_step_wait(step, t);
  163. }
  164. // 失败
  165. static void goto_failure(char * info)
  166. {
  167. Log_Printf_Debug("STEP: 数据发送失败,%s\r\n", info);
  168. UDP_Client5.status = Client_Status_Failure;
  169. strcpy(UDP_Client5.info, info);
  170. goto_step(STEP_FAILURE);
  171. }
  172. // 成功
  173. static void goto_success(char * info)
  174. {
  175. Log_Printf_Debug("STEP: 数据发送成功,%s\r\n", info);
  176. UDP_Client5.status = Client_Status_Success;
  177. strcpy(UDP_Client5.info, info);
  178. goto_step(STEP_SUCCESS);
  179. }
  180. // 等待
  181. static void wait(void)
  182. {
  183. if(Client5_time_flag == 0)
  184. {
  185. Client5_timer_ms = 0;
  186. Client5_time_flag = 1;
  187. }
  188. else if(Client5_timer_ms > Client5_wait_time)
  189. {
  190. goto_step(next_step); // 进入下一步
  191. Client5_time_flag = 0;
  192. }
  193. }
  194. // 判断认证还是发送
  195. static uint8_t judge_auth_or_data(void)
  196. {
  197. if(strlen(Token) > 0) // 已认证
  198. {
  199. return 1;
  200. }
  201. else
  202. {
  203. return 0;
  204. }
  205. }
  206. // 拼接认证报文
  207. static void join_auth_message(uint8_t * coap_message, uint16_t * coap_message_length)
  208. {
  209. SeqOffset=65535;
  210. Log_Printf_Debug("STEP: 拼接认证报文,seqOffset=%d\r\n", SeqOffset);
  211. // 先清除
  212. // memset(coap_message, 0, sizeof(coap_message));
  213. // coap_message_length = 0;
  214. // CoAP协议
  215. CoAP_Init();
  216. CoAP_Set_T(0);
  217. CoAP_Set_Code(2);
  218. CoAP_Set_MessageID(SeqOffset);
  219. // option
  220. // host
  221. CoAP_Set_Option_Str(3, Host);
  222. // port
  223. CoAP_Set_Option_Short(7, Port);
  224. // path
  225. CoAP_Set_Option_Str(11, "auth");
  226. // content-format
  227. CoAP_Set_Option_Short(12, 50);
  228. // accept
  229. CoAP_Set_Option_Short(17, 50);
  230. // 待签名数据
  231. // 签名相关
  232. static char StrForSignature[100];
  233. static char sign[50];
  234. memset(StrForSignature, '\0', sizeof(StrForSignature));
  235. sprintf((char * )StrForSignature, "clientId%sdeviceName%sproductKey%sseq%s", ClientID, DeviceName, ProductKey, Seq);
  236. // 签名
  237. memset(sign, '\0', sizeof(sign));
  238. utils_hmac_sha1_str(StrForSignature, strlen((char * )StrForSignature), sign, DeviceSecret, strlen(DeviceSecret));
  239. // payload
  240. // memset(payload, '\0', sizeof(payload));
  241. char payload[256] = {0};
  242. sprintf((char * )payload, "{\"clientId\":\"%s\",\"signmethod\":\"hmacsha1\",\"sign\":\"%s\",\"productKey\":\"%s\",\"deviceName\":\"%s\",\"seq\":\"%s\"}", ClientID, sign, ProductKey, DeviceName, Seq);
  243. // 设置payload
  244. CoAP_Set_Payload_Str(payload);
  245. // 生成报文
  246. * coap_message_length = CoAP_Get_Length();
  247. memcpy(coap_message, CoAP_Get_Message(), * coap_message_length);
  248. }
  249. // 拼接数据报文
  250. static void join_data_message(uint8_t * data, uint8_t data_length, uint8_t * coap_message, uint16_t * coap_message_length)
  251. {
  252. SeqOffset++;
  253. Log_Printf_Debug("STEP: 拼接数据报文,seqOffset=%d\r\n", SeqOffset);
  254. // 先清除
  255. // memset(coap_message, 0, sizeof(coap_message));
  256. // coap_message_length = 0;
  257. char out[80]={0};
  258. char sha256_source[100] = {0};
  259. snprintf(sha256_source, sizeof(sha256_source), "%s,%s" ,DeviceSecret ,Random);
  260. Log_Printf_Debug("sha256_source: %s\r\n", sha256_source);
  261. utils_sha256(sha256_source, strlen(sha256_source), out);
  262. memset(aes_key, 0, sizeof(aes_key));
  263. memcpy(aes_key, out+8, 16); //获取key
  264. // CoAP协议
  265. CoAP_Init();
  266. CoAP_Set_T(0);
  267. CoAP_Set_Code(2);
  268. CoAP_Set_MessageID(SeqOffset);
  269. // option
  270. // host
  271. CoAP_Set_Option_Str(3, Host);
  272. // port
  273. CoAP_Set_Option_Short(7, Port);
  274. // path
  275. CoAP_Set_Option_Str(11, "topic");
  276. CoAP_Set_Option_Str(11, "sys");
  277. CoAP_Set_Option_Str(11, ProductKey);
  278. CoAP_Set_Option_Str(11, DeviceName);
  279. CoAP_Set_Option_Str(11, "thing");
  280. CoAP_Set_Option_Str(11, "model");
  281. CoAP_Set_Option_Str(11, "up_raw");
  282. // content-format
  283. CoAP_Set_Option_Short(12, 50);
  284. // accept
  285. CoAP_Set_Option_Short(17, 50);
  286. // 2088
  287. CoAP_Set_Option_Str(2088, Token);
  288. // 2089
  289. char Rand2089[10] = {'\0'};
  290. char Opt2089[20] = {'\0'};
  291. my_itoa(SeqOffset, Rand2089, 10);
  292. int Opt2089_Length = utils_aes128_cbc_enc((char * )aes_key, iv, Rand2089, Opt2089);
  293. CoAP_Set_Option_Str(2089, Opt2089);
  294. // payload
  295. // memset(payload, '\0', sizeof(payload));
  296. uint8_t payload[256] = {0};
  297. //
  298. int payload_length = utils_aes128_cbc_enc_with_length((char * )aes_key, iv, data, data_length, payload);
  299. // payload_length = utils_aes128_cbc_enc((char * )aes_key, iv, (char * )Data_Buffer, (char * )payload);
  300. Log_Printf_Debug("payload_length: %d\r\n", payload_length);
  301. CoAP_Set_Payload(payload, payload_length);
  302. // 生成报文
  303. * coap_message_length = CoAP_Get_Length();
  304. memcpy(coap_message, CoAP_Get_Message(), * coap_message_length);
  305. }
  306. // 等待数据返回
  307. static uint8_t recv_data_handle(uint8_t * coap_message, uint16_t coap_message_length)
  308. {
  309. uint16_t payload_length = CoAP_Get_Payload_Length(coap_message, coap_message_length);
  310. uint8_t payload[256] = {0};
  311. CoAP_Get_Payload(coap_message, coap_message_length, payload);
  312. Log_Printf_Debug("payload长度: %d\r\n", payload_length);
  313. // 判断是认证返回,还是数据发送返回
  314. if(payload_length == 0) // 无返回
  315. {
  316. // 清空Token,重新认证
  317. memset(Token, '\0', sizeof(Token));
  318. return 0;
  319. }
  320. else if(payload[0] == '{' && payload[payload_length-1] == '}') // 认证返回
  321. {
  322. // 解析json
  323. cJSON * cjson = cJSON_Parse((char * )payload);
  324. Log_Printf_Debug("plaintext(%d): %s\r\n",payload_length, payload);
  325. memset(Random, '\0', sizeof(Random));
  326. memset(Token, '\0', sizeof(Token));
  327. if(cJSON_HasObjectItem(cjson, "random"))
  328. {
  329. char * random = cJSON_GetObjectItem(cjson, "random")->valuestring;
  330. strcpy(Random, random);
  331. }
  332. if(cJSON_HasObjectItem(cjson, "seqOffset"))
  333. {
  334. uint16_t seqOffset = cJSON_GetObjectItem(cjson, "seqOffset")->valueint;
  335. SeqOffset = seqOffset;
  336. }
  337. if(cJSON_HasObjectItem(cjson, "token"))
  338. {
  339. char * token = cJSON_GetObjectItem(cjson, "token")->valuestring;
  340. strcpy(Token, token);
  341. }
  342. Log_Printf_Debug("\r\n(%s, %s, %d)\r\n", Random, Token, SeqOffset);
  343. cJSON_Delete(cjson);//清除结构体
  344. return 1;
  345. }
  346. else
  347. {
  348. // 数据发送成功返回
  349. uint8_t plaintext[256] = {0}; // 明文
  350. uint16_t plaintext_length = utils_aes128_cbc_dec((char * )aes_key, iv, (char * )payload, payload_length, (char * )plaintext);
  351. Log_Printf_Debug("\r\nplaintext(%d): %s\r\n",plaintext_length, (char *)plaintext);
  352. return 2;
  353. }
  354. }
  355. // 发送数据的逻辑
  356. static enum Result result = Result_None;
  357. static uint8_t cgreg_n;
  358. static uint8_t cgreg_stat;
  359. static uint16_t cgreg_lac;
  360. static uint32_t cgreg_ci;
  361. static uint8_t query_cgreg_times = 0; // 查询网络状态的次数
  362. static uint8_t auth_times = 0; // 认证次数
  363. static uint16_t socket_err = 0;
  364. static uint8_t auth_or_data = 0;
  365. void UDP_Client5_Handle(void)
  366. {
  367. // 流程
  368. switch(step)
  369. {
  370. case STEP_NONE: // 空闲
  371. break;
  372. case STEP_START: // 开始
  373. query_cgreg_times = 0; // 查询网络状态的次数
  374. auth_times = 0; // 认证次数
  375. goto_step(STEP_EXIT_SLEEP);
  376. break;
  377. case STEP_EXIT_SLEEP: // 退出休眠
  378. ec800m.exit_sleep();
  379. goto_step_wait(STEP_SET_CFUN_1, 3);
  380. break;
  381. case STEP_SET_CFUN_1: // 设置全功能模式
  382. result = ec800m.set_cfun(1);
  383. if(result == Result_Success)
  384. {
  385. goto_step(STEP_SET_CGREG_2);
  386. }
  387. else if(result == Result_Failed)
  388. {
  389. goto_failure("设置全功能模式失败");
  390. }
  391. break;
  392. case STEP_SET_CGREG_2: // 设置ps域
  393. result = ec800m.set_cgreg(2);
  394. if(result == Result_Success)
  395. {
  396. goto_step(STEP_QUERY_CGREG);
  397. }
  398. else if(result == Result_Failed)
  399. {
  400. goto_failure("设置ps域失败");
  401. }
  402. break;
  403. case STEP_QUERY_CGREG: // 查询ps域
  404. result = ec800m.query_cgreg(&cgreg_n, &cgreg_stat, &cgreg_lac, &cgreg_ci);
  405. if(result == Result_Success)
  406. {
  407. if(cgreg_stat == 1)
  408. {
  409. // 参数赋值
  410. pump_params.lac = cgreg_lac;
  411. pump_params.ci = cgreg_ci;
  412. // 编码
  413. business_protocol_encode(pump_params, data, &data_length);
  414. // 下一步
  415. goto_step(STEP_CLOSE);
  416. }
  417. else if(query_cgreg_times > 10) // 最多查询20次
  418. {
  419. goto_failure("查询ps域次数过多");
  420. }
  421. else
  422. {
  423. goto_wait(400);
  424. query_cgreg_times++;
  425. }
  426. }
  427. else if(result == Result_Failed)
  428. {
  429. goto_failure("查询ps域失败");
  430. }
  431. break;
  432. case STEP_CLOSE: // 关闭连接
  433. result = ec800m.close_socket(connectID);
  434. if(result == Result_Success)
  435. {
  436. goto_step(STEP_OPEN);
  437. }
  438. else if(result == Result_Failed)
  439. {
  440. goto_failure("关闭连接失败");
  441. }
  442. break;
  443. case STEP_OPEN: // 打开客户端
  444. result = ec800m.open_socket(connectID, "UDP", Host, Port, 1, &socket_err);
  445. if(result == Result_Success)
  446. {
  447. if(socket_err == 0)
  448. {
  449. goto_step(STEP_JUDGE_AUTH_OR_DATA);
  450. }
  451. else
  452. {
  453. goto_failure("客户端打开错误");
  454. }
  455. }
  456. else if(result == Result_Failed)
  457. {
  458. goto_failure("打开客户端失败");
  459. }
  460. break;
  461. case STEP_JUDGE_AUTH_OR_DATA: // 判断认证还是发送
  462. auth_or_data = judge_auth_or_data();
  463. if(auth_or_data == 1) // 已认证
  464. {
  465. goto_step(STEP_JOIN_DATA_MESSAGE);
  466. }
  467. else
  468. {
  469. goto_step(STEP_JOIN_AUTH_MESSAGE);
  470. }
  471. break;
  472. case STEP_JOIN_AUTH_MESSAGE: // 拼接认证报文
  473. if(auth_times > 0) // 最多重新认证一次
  474. {
  475. goto_failure("认证次数过多");
  476. }
  477. else
  478. {
  479. join_auth_message(coap_message, &coap_message_length);
  480. goto_step(STEP_SET_QISDE_0);
  481. auth_times++;
  482. }
  483. break;
  484. case STEP_JOIN_DATA_MESSAGE: // 拼接数据报文
  485. join_data_message(data, data_length, coap_message, &coap_message_length);
  486. goto_step(STEP_SET_QISDE_0);
  487. break;
  488. case STEP_SET_QISDE_0: // 关闭发送回显
  489. result = ec800m.set_qisde(0);
  490. if(result == Result_Success)
  491. {
  492. goto_step(STEP_SEND);
  493. }
  494. else if(result == Result_Failed)
  495. {
  496. goto_failure("关闭发送回显失败");
  497. }
  498. break;
  499. case STEP_SEND: // 发送send
  500. result = ec800m.send(connectID, coap_message, coap_message_length);
  501. if(result == Result_Success)
  502. {
  503. goto_step(STEP_RECV);
  504. }
  505. else if(result == Result_Failed)
  506. {
  507. goto_failure("发送send失败");
  508. }
  509. break;
  510. case STEP_RECV: // 等待结果
  511. result = ec800m.recv_with_time(connectID, coap_message, &coap_message_length, 10000);
  512. if(result == Result_Success)
  513. {
  514. uint8_t res = recv_data_handle(coap_message, coap_message_length);
  515. if(res == 0) // 发送失败
  516. {
  517. goto_step(STEP_JUDGE_AUTH_OR_DATA); // 重新认证
  518. }
  519. else if(res == 1) // 认证成功
  520. {
  521. goto_step(STEP_JOIN_DATA_MESSAGE);
  522. }
  523. else if(res == 2) // 发送成功
  524. {
  525. goto_success("发送成功");
  526. }
  527. }
  528. else if(result == Result_Failed)
  529. {
  530. goto_failure("等待结果失败");
  531. }
  532. break;
  533. case STEP_WAIT: // 等待
  534. wait();
  535. break;
  536. case STEP_SUCCESS: // 成功
  537. goto_step(STEP_SET_SLEEP);
  538. break;
  539. case STEP_FAILURE: // 失败
  540. goto_step(STEP_SET_SLEEP);
  541. break;
  542. case STEP_SET_SLEEP: // 设置休眠模式
  543. result = ec800m.set_sleep(1);
  544. if(result != Result_None)
  545. {
  546. goto_step(STEP_SET_CFUN_0);
  547. }
  548. break;
  549. case STEP_SET_CFUN_0: // 设置最小功能模式
  550. result = ec800m.set_cfun(0);
  551. if(result != Result_None)
  552. {
  553. goto_step(STEP_ENTER_SLEEP);
  554. }
  555. break;
  556. case STEP_ENTER_SLEEP: // 进入睡眠
  557. ec800m.enter_sleep();
  558. goto_step(STEP_FINISH);
  559. break;
  560. case STEP_FINISH: // 结束流程
  561. break;
  562. default:
  563. break;
  564. }
  565. }