blob: 7e3ac6976dfad646c86ae39118e0a6d5dea34636 [file] [log] [blame]
zongqiang.zhang0c6a0882019-08-07 14:48:21 +08001#include "sp_communicate.h"
2#include "sp_util.h"
3#include "sp_flash.h"
4#include "sp_constant.h"
5#include "sp_data.h"
6#include "sp_msgpack.h"
7#include "sp_display.h"
8#include "../sys_hw/drv_usart.h"
9
10static void sp_usart_send(sp_pos_t* pos, sp_protocol_request_t* req)
11{
12 uint8 sendBuff[264];
13 MEMCLEAR(sendBuff, sizeof(sendBuff));
14
15 pos->last_comm_status.command = req->excmd;
16 pos->last_comm_status.sendtime = sp_get_ticker();
17
18 sp_protocol_crc((uint8*)req +2, req->datalen, (uint8*)req +2 +req->datalen);
19 req->datalen += 2;
20 MEMCPY(sendBuff, req, req->datalen+2);
21 usart_send(sendBuff, req->datalen+2);
22}
23
24static uint8 sp_usart_recv(sp_pos_t* pos, sp_protocol_response_t* resp, int32 timeout_ms)
25{
26 uint32 tick = 0;
27 tick = sp_get_ticker();
28 while(1)
29 {
30 MEMCLEAR(resp, sizeof(sp_protocol_response_t));
31 usart_read((u8*)resp, sizeof(sp_protocol_response_t));
32 if(pos->last_comm_status.command == resp->excmd)
33 {
34 MEMCLEAR(&(pos->last_comm_status), sizeof(sp_comm_status_t));
35 return resp->retcode;
36 }
37 if((sp_get_ticker() - tick) >= timeout_ms)
38 {
39 return 1;
40 }
41 }
42}
43uint8 sp_comm_call(sp_pos_t* pos, sp_protocol_request_t* req,
44 sp_protocol_response_t* resp, int32 timeout_ms)
45{
46 sp_usart_send(pos, req);
47 return sp_usart_recv(pos, resp, timeout_ms);
48}
49
50void sp_protocol_req_init(sp_protocol_request_t* req, uint8 command)
51{
52 MEMCLEAR(req,sizeof(sp_protocol_request_t));
53 req->command = PROTOCOL_COMMAND_V2;
54 req->excmd = command;
55 req->flag = PROTOCOL_FLAG_PACK(req->flag);
56 req->flag = PROTOCOL_WITHOUT_MAC(req->flag);
57 req->datalen = 3;
58}
59
60static uint16 sp_confirm_card_authentication(sp_pos_t* pos, sp_card_t* card)
61{
62 uint8 size;
63 uint16 ret;
64 int32 timeout_ms = COMM_WAIT_TIME;
65 cw_unpack_context unpack;
66 unpack_field_t field;
67 sp_protocol_response_t resp;
68
69 disp_hint_info(pos,"ÕýÔÚÉí·ÝÈÏÖ¤ÖÐ",DELAY_TIME2s);
70 ret = sp_usart_recv(pos, &resp, timeout_ms);
71 if(ret)
72 {
73 ret = RC_CARD_AUTHENTICATION;
74 return ret;
75 }
76
77 sp_unpack_init(&unpack,resp.data,resp.datalen);
78 size = sp_unpack_map_size(&unpack);
79 while(size-- > 0)
80 {
81 sp_unpack_value(&unpack,&field);
82 if(IS_KEY(PK_INT_WATERLIMIT,field.key))
83 {
84 card->waterlimit = field.val.intval;
85 }
86 else if(IS_KEY(PK_BIN_BILLNO,field.key))
87 {
88 MEMCPY(card->billno, field.val.binval, field.strlen);
89 }
90 else if(IS_KEY(PK_INT_FEEAMOUNT,field.key))
91 {
92 card->feepara.fee_amt = field.val.intval;
93 }
94 else if(IS_KEY(PK_INT_FEEUNIT, field.key))
95 {
96 card->feepara.fee_unit = field.val.intval;
97 }
98 else if(IS_KEY(PK_INT_FEESTART, field.key))
99 {
100 card->feepara.fee_start = field.val.intval;
101 }
102 }
103 disp_hint_info(pos,"Éí·ÝÈÏÖ¤³É¹¦",DELAY_TIME1s);
104 return 0;
105}
106
107//ºǫ́¶Ô¿¨µÄÉí·ÝÈÏÖ¤
108uint16 sp_card_authentication(sp_pos_t* pos, sp_card_t* card)
109{
110 uint8 ctime[6];
111 sp_protocol_request_t req;
112 cw_pack_context pack;
113 MEMCLEAR(&req, sizeof(req));
114 MEMCLEAR(&pack, sizeof(req));
115 MEMCLEAR(ctime, sizeof ctime);
116
117 sp_get_bcdtime(ctime);
118 sp_protocol_req_init(&req, SP_CMD_CARD_AUTHENTICATION);
119 sp_pack_init(&pack, req.data, sizeof(req.data));
120 cw_pack_map_size(&pack,4);
121
122 sp_pack_put_bin(&pack, PK_BIN_CARDPHYID, card->cardphyid, 4);
123 sp_pack_put_bin(&pack, PK_BIN_CITIZEN_CARDNO, card->citizen_cardno, 12);
124 sp_pack_put_bin(&pack, PK_BIN_DEVPHYID, pos->devphyid, 4);
125 sp_pack_put_bin(&pack, PK_BIN_DEVTIME, ctime, 6);
126
127 req.datalen += sp_pack_length(&pack);
128 sp_usart_send(pos, &req);
129 return sp_confirm_card_authentication(pos, card);
130}
131
132//É豸ǩµ½
133uint16 sp_async_equipment_login(sp_pos_t* pos)
134{
135 sp_protocol_request_t req;
136 cw_pack_context pack;
137 uint8 ctime[6];
138 MEMCLEAR(ctime, sizeof(ctime));
139 pos->heartbeat.heart_status = HEART_SEND;
140
141 sp_get_bcdtime(ctime);
142 sp_protocol_req_init(&req, SP_CMD_LOGIN);
143 sp_pack_init(&pack, req.data, sizeof(req.data));
144 cw_pack_map_size(&pack, 5);
145
146 sp_pack_put_bin(&pack, PK_BIN_DEVPHYID, pos->devphyid, 4);
147 sp_pack_put_bin(&pack, PK_BIN_DEVTIME, ctime, 6);
148 sp_pack_put_str(&pack, PK_STR_DEVTYPE, DEV_TYPE);
149 sp_pack_put_str(&pack, PK_STR_VERSION, PRO_VERSION);
150 sp_pack_put_bin(&pack, PK_BIN_DEVICEKEY, (pos->sysconf.deviceKey), 8);
151
152 req.datalen += sp_pack_length(&pack);
153 sp_usart_send(pos, &req);
154 return 0;
155}
156
157//ÐÄÌøÈ·ÈÏ£¬¼ì²âÍøÂçÊÇ·ñÕý³£
158uint16 sp_async_heartbeat(sp_pos_t* pos)
159{
160 uint8 ctime[6];
161 uint8 unconfirm_transnum = 0;
162 sp_protocol_request_t req;
163 cw_pack_context pack;
164
165 pos->heartbeat.heart_status = HEART_SEND;
166 if(pos->unconfirm_transdtl.transaddr <= pos->last_transdtl.transaddr)
167 {
168 unconfirm_transnum = ((pos->last_transdtl.transaddr - pos->unconfirm_transdtl.transaddr) /
169 sizeof(sp_transdtl_t)) + 1;
170 }
171 else
172 {
173 unconfirm_transnum = 0;
174 }
175 sp_protocol_req_init(&req, SP_CMD_HEARTBEAT);
176 sp_pack_init(&pack, req.data, sizeof(req.data));
177 cw_pack_map_size(&pack, 6);
178
179 sp_get_bcdtime(ctime);
180 sp_pack_put_bin(&pack, PK_BIN_DEVPHYID, pos->devphyid, 4);
181 sp_pack_put_bin(&pack, PK_BIN_DEVTIME, ctime, 6);
182 sp_pack_put_str(&pack, PK_STR_DEVTYPE, DEV_TYPE);
183 sp_pack_put_str(&pack, PK_STR_VERSION, PRO_VERSION);
184 sp_pack_put_int(&pack, PK_INT_UNTRANSCONST, unconfirm_transnum);
185 sp_pack_put_int(&pack, PK_INT_WORKMODE, pos->sysconf.work_mode);
186
187 req.datalen += sp_pack_length(&pack);
188 sp_usart_send(pos, &req);
189 return 0;
190}
191
192static uint16 sp_confirm_qrcode_init(sp_pos_t* pos, sp_card_t* card)
193{
194 uint8 size;
195 uint16 ret;
196 int32 timeout_ms = COMM_WAIT_TIME;
197 cw_unpack_context unpack;
198 unpack_field_t field;
199 sp_protocol_response_t resp;
200
201 ret = sp_usart_recv(pos, &resp, timeout_ms);
202 if(ret)
203 {
204 ret = RC_QRCODE_FAILURE;
205 return ret;
206 }
207
208 sp_unpack_init(&unpack,resp.data,resp.datalen);
209 size = sp_unpack_map_size(&unpack);
210 while(size-- > 0)
211 {
212 sp_unpack_value(&unpack,&field);
213 if(IS_KEY(PK_STR_SHORT_URL, field.key))
214 {
215 MEMCPY(card->qrcode.qrcode_url, field.val.strval, field.strlen);
216 }
217 else if(IS_KEY(PK_BIN_BILLNO, field.key))
218 {
219 MEMCPY(card->billno, field.val.binval, field.strlen);
220 }
221 else if(IS_KEY(PK_INT_VAILDTIME, field.key))
222 {
223 card->qrcode.validtime = field.val.intval;
224 }
225 }
226 card->qrcode.starttime = sp_get_ticker();
227 return 0;
228}
229
230//¶þάÂë»ñÈ¡
231uint16 sp_qrcode_init(sp_pos_t* pos, sp_card_t* card)
232{
233 uint8 ctime[6];
234 sp_protocol_request_t req;
235 cw_pack_context pack;
236
237 sp_get_bcdtime(ctime);
238 sp_protocol_req_init(&req, SP_CMD_SHORTURL);
239 sp_pack_init(&pack, req.data, sizeof(req.data));
240 cw_pack_map_size(&pack, 2);
241
242 sp_pack_put_bin(&pack, PK_BIN_DEVPHYID, pos->devphyid, 4);
243 sp_pack_put_bin(&pack, PK_BIN_DEVTIME, ctime, 6);
244
245 req.datalen += sp_pack_length(&pack);
246 sp_usart_send(pos, &req);
247 return sp_confirm_qrcode_init(pos, card);
248}
249
250//¶þάÂëÈ·ÈÏ£¬»ñȡ֧¸¶×´Ì¬
251static uint16 sp_confirm_qrcode_query(sp_pos_t* pos, sp_card_t* card)
252{
253 uint8 size;
254 uint16 ret;
255 int32 timeout_ms = COMM_WAIT_TIME;
256 cw_unpack_context unpack;
257 unpack_field_t field;
258 sp_protocol_response_t resp;
259
260 ret = sp_usart_recv(pos, &resp, timeout_ms);
261 if(ret)
262 {
263 ret = RC_QRCODE_QUERY_FAIL;
264 return ret;
265 }
266
267 sp_unpack_init(&unpack,resp.data,resp.datalen);
268 size = sp_unpack_map_size(&unpack);
269 while(size-- > 0)
270 {
271 sp_unpack_value(&unpack,&field);
272 if(IS_KEY(PK_BIN_BILLNO, field.key))
273 {
274 MEMCPY(card->billno, field.val.binval, field.strlen);
275 }
276 else if(IS_KEY(PK_INT_AUTHSTATUS, field.key))
277 {
278 card->qrcode.authstatus = field.val.intval;
279 }
280 else if(IS_KEY(PK_INT_PAYSTATUS, field.key))
281 {
282 card->qrcode.paystatus = field.val.intval;
283 }
284 else if(IS_KEY(PK_INT_PAYAMT, field.key))
285 {
286 card->qrcode.paidAmount = field.val.intval;
287 }
288 else if(IS_KEY(PK_INT_FEEAMOUNT,field.key))
289 {
290 card->feepara.fee_amt = field.val.intval;
291 }
292 else if(IS_KEY(PK_INT_FEEUNIT, field.key))
293 {
294 card->feepara.fee_unit = field.val.intval;
295 }
296 }
297 return resp.retcode;
298}
299
300uint16 sp_qrcode_query(sp_pos_t* pos, sp_card_t* card)
301{
302 uint8 ctime[6];
303 sp_protocol_request_t req;
304 cw_pack_context pack;
305
306 sp_get_bcdtime(ctime);
307 sp_protocol_req_init(&req, SP_CMD_QRCODE_PAY_QUERY);
308 sp_pack_init(&pack, req.data, sizeof(req.data));
309 cw_pack_map_size(&pack, 2);
310
311 sp_pack_put_bin(&pack, PK_BIN_DEVPHYID, pos->devphyid, 4);
312 sp_pack_put_bin(&pack, PK_BIN_BILLNO, card->billno, sizeof(card->billno));
313
314 req.datalen += sp_pack_length(&pack);
315 sp_usart_send(pos, &req);
316 return sp_confirm_qrcode_query(pos, card);
317}
318
319//Á÷Ë®ÉÏ´«
320static uint8 transdtl_account_bilLno[10];
321static uint16 sp_async_upload_transdtl(sp_pos_t* pos, sp_transdtl_t* transdtl)
322{
323 uint8 crc[2];
324 cw_pack_context pack;
325 sp_protocol_request_t req;
326
327 MEMCPY(transdtl_account_bilLno, transdtl->billno, sizeof(transdtl->billno));
328 sp_protocol_req_init(&req, SP_CMD_TRANSDTL_ACCOUNT);
329 sp_pack_init(&pack,req.data,sizeof(req.data));
330 cw_pack_map_size(&pack,10);
331
332 sp_pack_put_bin(&pack, PK_BIN_DEVPHYID, transdtl->devphyid,4);
333 sp_pack_put_bin(&pack, PK_BIN_TRANSDATE, transdtl->transdate,3);
334 sp_pack_put_bin(&pack, PK_BIN_TRANSTIME, transdtl->transtime,3);
335 sp_pack_put_bin(&pack, PK_BIN_BILLNO, transdtl->billno, sizeof(transdtl->billno));
336 sp_pack_put_bin(&pack, PK_BIN_CARDPHYID, transdtl->cardphyid,
337 sizeof(transdtl->cardphyid));
338 sp_pack_put_int(&pack, PK_INT_TRANSWAY, transdtl->transway);
339 sp_pack_put_int(&pack, PK_INT_AMOUNT, transdtl->amount);
340 sp_pack_put_int(&pack, PK_INT_PAYAMT, transdtl->paidAmount);
341 sp_pack_put_int(&pack, PK_INT_FLOWSENSORS, transdtl->flowsensors);
342 sp_pack_put_int(&pack, PK_INT_FLAG, transdtl->transtatus);
343
344 sp_protocol_crc((uint8*)transdtl, sizeof(sp_transdtl_t)-2,crc);
345 req.datalen += sp_pack_length(&pack);
346 sp_usart_send(pos, &req);
347 return 0;
348}
349
350//È·ÈÏÁ÷ˮ״̬
351static uint8 sp_confirm_transdtl_account(sp_protocol_response_t* resp, sp_pos_t* pos)
352{
353 uint8 size;
354 cw_unpack_context unpack;
355 unpack_field_t field;
356
357 if(!resp->retcode)
358 {
359 sp_unpack_init(&unpack, resp->data, resp->datalen);
360 size = sp_unpack_map_size(&unpack);
361 while(size-- > 0)
362 {
363 sp_unpack_value(&unpack,&field);
364 if(IS_KEY(PK_BIN_BILLNO,field.key))
365 {
366 if(MEMCMP(field.val.binval, transdtl_account_bilLno,
367 sizeof(transdtl_account_bilLno)) == 0)
368 {
369 pos->unconfirm_transdtl.transaddr+= sizeof(sp_transdtl_t);
370 if(ADDR_TRANSDTL_END <= pos->unconfirm_transdtl.transaddr)
371 {
372 pos->unconfirm_transdtl.transaddr= ADDR_TRANSDTL_BEGIN;
373 }
374 return sp_write_unconfirm_record(pos);
375 }
376 }
377 }
378 }
379 return resp->retcode;
380
381}
382
383static uint8 sp_confirm_heartbeat(sp_protocol_response_t* resp, sp_pos_t* pos)
384{
385 uint8 size;
386 uint8 ctime[6];
387 uint8 systime[7];
388 uint8 login_flag = 0;
389 cw_unpack_context unpack;
390 unpack_field_t field;
391
392 if(resp->retcode)
393 {
394 return resp->retcode;
395 }
396 pos->heartbeat.heart_status = HEART_RECV;
397
398 sp_unpack_init(&unpack,resp->data,resp->datalen);
399 size = sp_unpack_map_size(&unpack);
400 while(size-- > 0)
401 {
402 sp_unpack_value(&unpack,&field);
403 if(IS_KEY(PK_BIN_SYSTIME, field.key))
404 {
405 if(field.strlen == 7)
406 {
407 MEMCPY(systime,field.val.binval,7);
408 sp_get_bcdtime(ctime);
409 if(MEMCMP(ctime,systime +1,5) != 0)
410 {
411 if(!sp_check_time_valid(systime +1))
412 {
413 sp_set_bcdtime(systime +1);
414 }
415 }
416 }
417 }
418 else if(IS_KEY(PK_STR_STATUS, field.key))
419 {
420 if(MEMCMP(field.val.strval, "normal", field.strlen) == 0)
421 {
422 login_flag = 1;
423 }
424 else if(MEMCMP(field.val.strval, "logout", field.strlen) == 0)
425 {
426 login_flag = 0;
427 }
428 else if(MEMCMP(field.val.strval, "closed", field.strlen) == 0)
429 {
430 login_flag = 2;
431 }
432 }
433 }
434 sp_save_heartbeat_info(pos, login_flag);
435 return resp->retcode;
436}
437
438uint8 sp_confirm_login(sp_protocol_response_t* resp, sp_pos_t* pos)
439{
440 uint8 size;
441 uint8 ctime[6];
442 uint8 systime[7];
443 uint8 login_flag = 0;
444 uint8 unit = 0;
445 uint8 offline_maxhour = 0;
446 cw_unpack_context unpack;
447 unpack_field_t field;
448
449 MEMCLEAR(ctime, sizeof(ctime));
450 MEMCLEAR(systime, sizeof(systime));
451 if(resp->retcode)
452 {
453 return resp->retcode;
454 }
455 pos->heartbeat.heart_status = HEART_RECV;
456
457 sp_unpack_init(&unpack,resp->data,resp->datalen);
458 size = sp_unpack_map_size(&unpack);
459 while(size-- > 0)
460 {
461 sp_unpack_value(&unpack,&field);
462 if(IS_KEY(PK_INT_OFFLINEMAXHOUR, field.key))
463 {
464 offline_maxhour = field.val.intval;
465 }
466 else if(IS_KEY(PK_INT_PULSEINHML, field.key))
467 {
468 unit = field.val.intval;
469 }
470 else if(IS_KEY(PK_BIN_SYSTIME, field.key))
471 {
472 if(field.strlen == 7)
473 {
474 MEMCPY(systime,field.val.binval,7);
475 sp_get_bcdtime(ctime);
476 if(MEMCMP(ctime,systime +1,5) != 0)
477 {
478 if(!sp_check_time_valid(systime +1))
479 {
480 sp_set_bcdtime(systime +1);
481 }
482 }
483 }
484 }
485 }
486
487 login_flag = 1;
488 sp_save_login_info(pos, login_flag, unit, offline_maxhour);
489 return resp->retcode;
490}
491
492static protocol_cmd_t protocol_cmds[] =
493{
494 {SP_CMD_TRANSDTL_ACCOUNT, sp_confirm_transdtl_account},
495 {SP_CMD_HEARTBEAT, sp_confirm_heartbeat},
496 {SP_CMD_LOGIN, sp_confirm_login},
497 {0, NULL}
498};
499
500static uint16 sp_async_confirm_process(sp_pos_t* pos)
501{
502 uint8 ret = 0;
503 uint8 i = 0;
504 int32 timeout_ms = COMM_WAIT_TIME;
505 sp_protocol_response_t resp;
506
507 ret = sp_usart_recv(pos, &resp, timeout_ms);
508 if(ret)
509 {
510 return ret;
511 }
512 while(protocol_cmds[i].func != NULL && protocol_cmds[i].cmd != 0)
513 {
514 if(protocol_cmds[i].cmd == resp.excmd)
515 {
516 return protocol_cmds[i].func(&resp, pos);
517 }
518 ++i;
519 }
520 return 1;
521}
522
523//¼ì²âÉ豸ͨѶ״̬£¬¿ÕÏÐʱ¼ä½øÐÐÁ÷Ë®´¦ÀíµÈ¹¤×÷
524static void sp_check_and_switch_linkstat(sp_pos_t* pos)
525{
526 if(pos->heartbeat.heart_status == HEART_SEND)
527 {
528 //ÒÑ·¢ËÍÐÄÌø£¬Î´ÊÕµ½Ó¦´ð
529 pos->link_stat = 0;
530 pos->heartbeat.heart_status = HEART_INIT;
531 }
532 else if(pos->heartbeat.heart_status == HEART_RECV)
533 {
534 //ÒÑ·¢ËÍÐÄÌø£¬ÊÕµ½Ó¦´ð
535 pos->link_stat = 1;
536 pos->heartbeat.heart_status = HEART_INIT;
537 }
538}
539
540void sp_communicate(sp_pos_t* pos)
541{
542 uint16 ret = 0;
543 uint32 ticker = 0;
544 sp_transdtl_t transdtl;
545
546 if(pos->deviceno == 0)
547 {
548 return;
549 }
550 ticker = sp_get_ticker();
551 if(ticker - pos->last_comm_status.sendtime > COMM_WAIT_TIME)
552 {
553 if(pos->devlogin.last_login_ticker == 0 || pos->devlogin.login_flag == 0
554 || (ticker - pos->devlogin.last_login_ticker) > DELAY_TIME60s*60*24)
555 {
556 pos->devlogin.last_login_ticker = ticker;
557 sp_async_equipment_login(pos);
558 }
559 else if(ticker < pos->heartbeat.last_heartbeat_ticker
560 || pos->heartbeat.last_heartbeat_ticker == 0
561 || (ticker - pos->heartbeat.last_heartbeat_ticker) > DELAY_TIME60s*2)
562 {
563 pos->heartbeat.last_heartbeat_ticker = ticker;
564 sp_async_heartbeat(pos);
565 }
566 else
567 {
568 sp_check_and_switch_linkstat(pos);
569 if(pos->link_stat)
570 {
571 //¼ì²âµ±Ç°ÊÇ·ñÓÐδÉÏ´«µÄÁ÷Ë®
572 if(pos->unconfirm_transdtl.transaddr <= pos->last_transdtl.transaddr)
573 {
574 ret = sp_flash_read((uint32)pos->unconfirm_transdtl.transaddr, (uint8*)&transdtl,
575 sizeof(transdtl));
576 if(!ret)
577 {
578 if(!pos->sysconf.work_mode)
579 {
580 pos->heartbeat.last_heartbeat_ticker = ticker;
581 sp_async_upload_transdtl(pos, &transdtl);
582 }
583 }
584 }
585 }
586 }
587 }
588
589 sp_async_confirm_process(pos);
590}