1 /*
2 * Copyright (C) 2015-2019 Alibaba Group Holding Limited
3 */
4
5 #include "app_message.h"
6
7 #include "aiot_mqtt_api.h"
8 #include "aiot_state_api.h"
9 #include "aiot_sysdep_api.h"
10 #include "amp_platform.h"
11 #include "aos/kv.h"
12 #include "aos_network.h"
13 #include "aos_system.h"
14 #include "py_defines.h"
15 //#include "aiot_das_api.h"
16 #include "aiot_devinfo_api.h"
17 #include "aiot_dm_api.h"
18 #include "aiot_ntp_api.h"
19 #include "app_mgr.h"
20 #include "cJSON.h"
21
22 #define MOD_STR "APP_MESSAGE"
23
24 int pyamp_upgrading = 0;
25 int pyamp_device_token_verify_rejected = 0;
26 char pyamp_file_url[300] = { 0 };
27
28 /* ntp timestamp */
29 // int64_t pyamp_g_ntp_time = 0;
30 // int64_t pyamp_g_up_time = 0;
31
pyamp_update_file(const char * payload)32 int32_t pyamp_update_file(const char *payload)
33 {
34 int32_t ret = -1;
35 cJSON *root = NULL, *params = NULL, *url = NULL;
36
37 root = cJSON_Parse(payload);
38 if (root == NULL || !cJSON_IsObject(root)) {
39 amp_debug(MOD_STR, "JSON Parse Error");
40 return ret;
41 }
42 params = cJSON_GetObjectItem(root, "params");
43 if (params == NULL || !cJSON_IsObject(params)) {
44 amp_debug(MOD_STR, "JSON Parse Error");
45 cJSON_Delete(root);
46 return ret;
47 }
48 do {
49 url = cJSON_GetObjectItem(params, "url");
50 if (url == NULL || !cJSON_IsString(url)) {
51 amp_debug(MOD_STR, "JSON Parse Error");
52 cJSON_Delete(root);
53 return ret;
54 }
55
56 strcpy(pyamp_file_url, url->valuestring);
57 // amp_debug(MOD_STR, "get url: %s", url->valuestring);
58 if (pyamp_upgrading) {
59 amp_debug(MOD_STR, "pyamp_upgrading.........");
60 return ret;
61 }
62 pyamp_apppack_upgrade(pyamp_file_url);
63 } while (0);
64
65 cJSON_Delete(root);
66
67 return STATE_SUCCESS;
68 }
69
pyamptoken_verify(const char * payload)70 int32_t pyamptoken_verify(const char *payload)
71 {
72 int32_t ret = -1;
73 char token_flag[AMP_DEVICE_TOKEN_LENGTH] = { 0 };
74 int token_len = AMP_DEVICE_TOKEN_LENGTH;
75 cJSON *root = NULL, *params = NULL, *token = NULL;
76
77 root = cJSON_Parse(payload);
78 if (root == NULL || !cJSON_IsObject(root)) {
79 amp_debug(MOD_STR, "JSON Parse Error");
80 return ret;
81 }
82 params = cJSON_GetObjectItem(root, "params");
83 if (params == NULL || !cJSON_IsObject(params)) {
84 amp_debug(MOD_STR, "JSON Parse Error");
85 cJSON_Delete(root);
86 return ret;
87 }
88
89 token = cJSON_GetObjectItem(params, "token");
90 if (token == NULL || !cJSON_IsString(token)) {
91 amp_debug(MOD_STR, "JSON Parse Error");
92 cJSON_Delete(root);
93 return ret;
94 }
95 // strcpy(pyamp_file_url, token->valuestring);
96 amp_debug(MOD_STR, "get token flag is: %s", token->valuestring);
97 aos_kv_set(AMP_DEVICE_TOKEN_VERIFY_FLAG, token->valuestring, strlen(token->valuestring), 1);
98 if (strcmp(token->valuestring, "rejected") == 0) {
99 amp_debug(MOD_STR, "token verify failed, destroy pclient");
100 pyamp_device_token_verify_rejected = 1;
101 }
102
103 cJSON_Delete(root);
104
105 return STATE_SUCCESS;
106 }
107
pyamp_putfile_message_handler(void * handle,const aiot_mqtt_recv_t * packet,void * userdata)108 void pyamp_putfile_message_handler(void *handle, const aiot_mqtt_recv_t *packet, void *userdata)
109 {
110 switch (packet->type) {
111 case AIOT_MQTTRECV_PUB:
112 /* print topic name and topic message */
113 amp_debug(MOD_STR, "pub, qos: %d, len: %d, topic: %s \r\n", packet->data.pub.qos, packet->data.pub.topic_len,
114 packet->data.pub.topic);
115 amp_debug(MOD_STR, "pub, len: %d, payload: %s \r\n", packet->data.pub.payload_len, packet->data.pub.payload);
116 pyamp_update_file(packet->data.pub.payload);
117 break;
118 default:
119 break;
120 }
121 }
122
pyamp_verify_message_handler(void * handle,const aiot_mqtt_recv_t * packet,void * userdata)123 void pyamp_verify_message_handler(void *handle, const aiot_mqtt_recv_t *packet, void *userdata)
124 {
125 switch (packet->type) {
126 case AIOT_MQTTRECV_PUB:
127 /* print topic name and topic message */
128 amp_debug(MOD_STR, "pub, qos: %d, len: %d, topic: %.*s", packet->data.pub.qos, packet->data.pub.topic_len,
129 packet->data.pub.topic);
130 amp_debug(MOD_STR, "pub, len: %d, payload: %.*s", packet->data.pub.payload_len, packet->data.pub.payload);
131 pyamptoken_verify(packet->data.pub.payload);
132 break;
133 default:
134 break;
135 }
136 }
137
topic_subscribe(void * mqtt_handle,const char * fmt,void * callback)138 static int32_t topic_subscribe(void *mqtt_handle, const char *fmt, void *callback)
139 {
140 int res = STATE_SUCCESS;
141 int topic_len = 0;
142 char *topic = NULL;
143 char amp_internal_productkey[IOTX_PRODUCT_KEY_LEN] = { 0 };
144 char amp_internal_devicename[IOTX_DEVICE_NAME_LEN] = { 0 };
145 int productkey_len = IOTX_PRODUCT_KEY_LEN;
146 int devicename_len = IOTX_DEVICE_NAME_LEN;
147
148 aos_kv_get(AMP_INTERNAL_PRODUCTKEY, amp_internal_productkey, &productkey_len);
149 aos_kv_get(AMP_INTERNAL_DEVICENAME, amp_internal_devicename, &devicename_len);
150
151 topic_len = strlen(fmt) + strlen(amp_internal_productkey) + strlen(amp_internal_devicename) + 1;
152 topic = aos_malloc(topic_len);
153 if (topic == NULL) {
154 amp_debug(MOD_STR, "memory not enough");
155 return -1;
156 }
157 memset(topic, 0, topic_len);
158 aos_snprintf(topic, topic_len, fmt, amp_internal_productkey, amp_internal_devicename);
159
160 res = aiot_mqtt_sub(mqtt_handle, topic, callback, 0, NULL);
161 if (res < STATE_SUCCESS) {
162 amp_debug(MOD_STR, "subscribe failed");
163 aos_free(topic);
164 return -1;
165 }
166
167 aos_free(topic);
168 return 0;
169 }
170
topic_publish(void * handle,const char * fmt,char * payload)171 static int32_t topic_publish(void *handle, const char *fmt, char *payload)
172 {
173 int res = STATE_SUCCESS;
174 char *topic = NULL;
175 int topic_len = 0;
176 char amp_internal_productkey[IOTX_PRODUCT_KEY_LEN] = { 0 };
177 char amp_internal_devicename[IOTX_DEVICE_NAME_LEN] = { 0 };
178 int productkey_len = IOTX_PRODUCT_KEY_LEN;
179 int devicename_len = IOTX_DEVICE_NAME_LEN;
180
181 aos_kv_get(AMP_INTERNAL_PRODUCTKEY, amp_internal_productkey, &productkey_len);
182 aos_kv_get(AMP_INTERNAL_DEVICENAME, amp_internal_devicename, &devicename_len);
183
184 topic_len = strlen(fmt) + strlen(amp_internal_productkey) + strlen(amp_internal_devicename) + 1;
185 topic = aos_malloc(topic_len);
186 if (topic == NULL) {
187 amp_debug(MOD_STR, "memory not enough");
188 return -1;
189 }
190 memset(topic, 0, topic_len);
191 aos_snprintf(topic, topic_len, fmt, amp_internal_productkey, amp_internal_devicename);
192
193 res = aiot_mqtt_pub(handle, topic, payload, strlen(payload), 0);
194 if (res < STATE_SUCCESS) {
195 amp_debug(MOD_STR, "publish failed, res = %d", res);
196 aos_free(topic);
197 return -1;
198 }
199
200 aos_free(topic);
201 return 0;
202 }
203
pyamp_internal_service_subscribe(void * mqtt_handle)204 int32_t pyamp_internal_service_subscribe(void *mqtt_handle)
205 {
206 int res = STATE_SUCCESS;
207
208 const char *update_fmt = "/sys/%s/%s/thing/service/putfile";
209 const char *verify_fmt = "/sys/%s/%s/thing/service/verify";
210
211 res = topic_subscribe(mqtt_handle, update_fmt, pyamp_putfile_message_handler);
212 if (res < STATE_SUCCESS) {
213 amp_debug(MOD_STR, "subscribe update topic failed");
214 return -1;
215 }
216
217 res = topic_subscribe(mqtt_handle, verify_fmt, pyamp_verify_message_handler);
218 if (res < STATE_SUCCESS) {
219 amp_debug(MOD_STR, "subscribe update topic failed");
220 return -1;
221 }
222
223 return res;
224 }
225
226 #define PROP_POST_FORMAT_TOKEN "{\"params\":{\"token\":\"%s\"}}"
pyamp_internal_service_publish(void * mqtt_handle)227 int32_t pyamp_internal_service_publish(void *mqtt_handle)
228 {
229 int res = 0;
230 char token_content[AMP_DEVICE_TOKEN_LENGTH] = { 0 };
231 int token_len = AMP_DEVICE_TOKEN_LENGTH;
232 const char *verify_fmt = "/sys/%s/%s/thing/event/property/post";
233 char *payload = NULL;
234
235 payload = aos_malloc(128);
236 if (payload == NULL) {
237 amp_debug(MOD_STR, "memory not enough");
238 return -1;
239 }
240 memset(payload, 0, 128);
241 aos_kv_get(AMP_DEVICE_TOKEN, token_content, &token_len);
242 aos_snprintf(payload, 128, PROP_POST_FORMAT_TOKEN, token_content);
243
244 res = topic_publish(mqtt_handle, verify_fmt, payload);
245 if (res < STATE_SUCCESS) {
246 amp_debug(MOD_STR, "publish failed");
247 aos_free(payload);
248 return -1;
249 }
250
251 aos_free(payload);
252 return res;
253 }
254
255 #if 0
256 /* das service */
257 int32_t amp_das_service(void *mqtt_handle)
258 {
259 int32_t res = STATE_SUCCESS;
260 void *das_handle = NULL;
261
262 das_handle = aiot_das_init();
263 if (das_handle == NULL) {
264 amp_debug(MOD_STR, "das service init failed");
265 return -1;
266 }
267
268 res = aiot_das_setopt(das_handle, AIOT_DASOPT_MQTT_HANDLE, mqtt_handle);
269 if (res < STATE_SUCCESS) {
270 amp_debug(MOD_STR, "das set option failed");
271 aiot_das_deinit(&das_handle);
272 return -1;
273 }
274
275 res = aiot_das_stepping(das_handle);
276 if (res < STATE_SUCCESS) {
277 amp_debug(MOD_STR, "das stepping failed");
278 aiot_das_deinit(&das_handle);
279 return -1;
280 }
281
282 return res;
283 }
284 #endif
285
aiot_ntp_recv_handler(void * handle,const aiot_ntp_recv_t * packet,void * userdata)286 static void aiot_ntp_recv_handler(void *handle, const aiot_ntp_recv_t *packet, void *userdata)
287 {
288 switch (packet->type) {
289 case AIOT_NTPRECV_LOCAL_TIME:
290 /* print topic name and topic message */
291 amp_debug(MOD_STR,
292 "year: %d, month: %d, day: %d, hour: %d, min: %d, sec: "
293 "%d, msec: %d, timestamp: %d",
294 packet->data.local_time.year, packet->data.local_time.mon, packet->data.local_time.day,
295 packet->data.local_time.hour, packet->data.local_time.min, packet->data.local_time.sec,
296 packet->data.local_time.msec, packet->data.local_time.timestamp);
297
298 // pyamp_g_ntp_time = packet->data.local_time.timestamp;
299 // pyamp_g_up_time = aos_now_ms();
300
301 break;
302 default:
303 break;
304 }
305 }
306
aiot_ntp_event_handler(void * handle,const aiot_ntp_event_t * event,void * userdata)307 static void aiot_ntp_event_handler(void *handle, const aiot_ntp_event_t *event, void *userdata)
308 {
309 switch (event->type) {
310 case AIOT_NTPEVT_INVALID_RESPONSE:
311 /* print topic name and topic message */
312 amp_debug(MOD_STR, "ntp receive data invalid");
313 break;
314 case AIOT_NTPEVT_INVALID_TIME_FORMAT:
315 amp_debug(MOD_STR, "ntp receive data error");
316 break;
317 default:
318 break;
319 }
320 }
321
322 /* ntp service */
pyamp_ntp_service(void * mqtt_handle)323 int32_t pyamp_ntp_service(void *mqtt_handle)
324 {
325 int32_t res = STATE_SUCCESS;
326 int32_t time_zone = 8;
327 void *ntp_handle = NULL;
328
329 static int ntp_enable = 0;
330
331 if (ntp_enable) {
332 return res;
333 }
334
335 ntp_handle = aiot_ntp_init();
336 if (ntp_handle == NULL) {
337 amp_debug(MOD_STR, "ntp service init failed");
338 return -1;
339 }
340
341 res = aiot_ntp_setopt(ntp_handle, AIOT_NTPOPT_MQTT_HANDLE, (void *)mqtt_handle);
342 if (res < STATE_SUCCESS) {
343 amp_debug(MOD_STR, "ntp set mqtt handle failed");
344 aiot_ntp_deinit(&ntp_handle);
345 return -1;
346 }
347
348 res = aiot_ntp_setopt(ntp_handle, AIOT_NTPOPT_TIME_ZONE, (void *)&time_zone);
349 if (res < STATE_SUCCESS) {
350 amp_debug(MOD_STR, "ntp set time zone failed");
351 aiot_ntp_deinit(&ntp_handle);
352 return -1;
353 }
354
355 res = aiot_ntp_setopt(ntp_handle, AIOT_NTPOPT_RECV_HANDLER, (void *)aiot_ntp_recv_handler);
356 if (res < STATE_SUCCESS) {
357 amp_debug(MOD_STR, "ntp set receive handler failed");
358 aiot_ntp_deinit(&ntp_handle);
359 return -1;
360 }
361
362 res = aiot_ntp_setopt(ntp_handle, AIOT_NTPOPT_EVENT_HANDLER, (void *)aiot_ntp_event_handler);
363 if (res < STATE_SUCCESS) {
364 amp_debug(MOD_STR, "das set event handler failed");
365 aiot_ntp_deinit(&ntp_handle);
366 return -1;
367 }
368
369 res = aiot_ntp_send_request(ntp_handle);
370 if (res < STATE_SUCCESS) {
371 amp_debug(MOD_STR, "das stepping failed");
372 aiot_ntp_deinit(&ntp_handle);
373 return -1;
374 }
375
376 ntp_enable = 1;
377 return res;
378 }
379
380 /* 定位事件上报 */
location_event_post(void * dm_handle,char * event_id,char * params)381 static int32_t location_event_post(void *dm_handle, char *event_id, char *params)
382 {
383 aiot_dm_msg_t msg;
384
385 memset(&msg, 0, sizeof(aiot_dm_msg_t));
386 msg.type = AIOT_DMMSG_EVENT_POST;
387 msg.data.event_post.event_id = event_id;
388 msg.data.event_post.params = params;
389
390 return aiot_dm_send(dm_handle, &msg);
391 }
392
pyamp_location_service(void * mqtt_handle)393 int32_t pyamp_location_service(void *mqtt_handle)
394 {
395 int32_t res = STATE_SUCCESS;
396 void *dm_handle = NULL;
397 aos_locator_info_t locator_info;
398 char *bts = NULL;
399 char *lbs_info = NULL;
400
401 res = aos_get_locator_info(&locator_info);
402 if (res != STATE_SUCCESS) {
403 amp_debug(MOD_STR, "get network info failed");
404 return -1;
405 }
406
407 bts = (char *)aos_malloc(64);
408 if (bts == NULL) {
409 amp_debug(MOD_STR, "network info malloc failed");
410 return -1;
411 }
412
413 /* bts info format */
414 res = snprintf(bts, 64, "%s,%s,%d,%d,%d", locator_info.mcc, locator_info.mnc, locator_info.lac, locator_info.cellid,
415 locator_info.signal);
416 if (res < STATE_SUCCESS) {
417 amp_debug(MOD_STR, "lbs info generate failed");
418 aos_free(bts);
419 return -1;
420 }
421
422 amp_debug(MOD_STR, "lbs info is: %s", bts);
423
424 lbs_info = (char *)aos_malloc(256);
425 if (lbs_info == NULL) {
426 amp_debug(MOD_STR, "network info malloc failed");
427 return -1;
428 }
429
430 /* lbs info format */
431 res = snprintf(lbs_info, 64, LBS_INFO_FMT, bts, bts);
432 if (res < STATE_SUCCESS) {
433 amp_debug(MOD_STR, "lbs info generate failed");
434 aos_free(lbs_info);
435 return -1;
436 }
437
438 /* 创建DATA-MODEL实例 */
439 dm_handle = aiot_dm_init();
440 if (dm_handle == NULL) {
441 amp_debug(MOD_STR, "dm handle init failed");
442 return -1;
443 }
444
445 /* 配置MQTT实例句柄 */
446 aiot_dm_setopt(dm_handle, AIOT_DMOPT_MQTT_HANDLE, mqtt_handle);
447
448 char *lbs_event_id = "LocationInfo";
449
450 location_event_post(dm_handle, lbs_event_id, "{\"ErrorCode\": 0}");
451
452 aos_free(bts);
453 aos_free(lbs_info);
454
455 return res;
456 }
457
458 /* device activition info report */
pyamp_devinfo_report_service(void * mqtt_handle)459 int32_t pyamp_devinfo_report_service(void *mqtt_handle)
460 {
461 int32_t res = STATE_SUCCESS;
462 void *devinfo_handle = NULL;
463 aiot_devinfo_msg_t *devinfo = NULL;
464 char *msg = NULL;
465 int32_t msg_len = 0;
466 char product_key[IOTX_PRODUCT_KEY_LEN] = { 0 };
467 char device_name[IOTX_DEVICE_NAME_LEN] = { 0 };
468 int productkey_len = IOTX_PRODUCT_KEY_LEN;
469 int devicename_len = IOTX_DEVICE_NAME_LEN;
470
471 devinfo_handle = aiot_devinfo_init();
472 if (devinfo_handle == NULL) {
473 amp_debug(MOD_STR, "ntp service init failed");
474 return -1;
475 }
476
477 res = aiot_devinfo_setopt(devinfo_handle, AIOT_DEVINFOOPT_MQTT_HANDLE, (void *)mqtt_handle);
478 if (res < STATE_SUCCESS) {
479 amp_debug(MOD_STR, "devinfo set mqtt handle failed");
480 aiot_devinfo_deinit(&devinfo_handle);
481 return -1;
482 }
483
484 aos_kv_get(AMP_INTERNAL_PRODUCTKEY, product_key, &productkey_len);
485 aos_kv_get(AMP_INTERNAL_DEVICENAME, device_name, &devicename_len);
486
487 msg_len = strlen(DEVICE_INFO_UPDATE_FMT) + 32;
488 msg = (char *)aos_malloc(msg_len);
489 if (msg == NULL) {
490 amp_debug(MOD_STR, "malloc msg err");
491 return -1;
492 }
493 memset(msg, 0, msg_len);
494
495 /* devinfo update message */
496 res = snprintf(msg, msg_len, DEVICE_INFO_UPDATE_FMT, APPLICATION, MODULE_NAME);
497 if (res <= 0) {
498 amp_debug(MOD_STR, "topic msg generate err");
499 aos_free(msg);
500 return -1;
501 }
502
503 devinfo = aos_malloc(sizeof(aiot_devinfo_msg_t));
504 if (devinfo == NULL) {
505 amp_debug(MOD_STR, "device update info malloc failed");
506 aos_free(msg);
507 return -1;
508 }
509 memset(devinfo, 0, sizeof(aiot_devinfo_msg_t));
510
511 devinfo->product_key = aos_malloc(IOTX_PRODUCT_KEY_LEN);
512 if (devinfo->product_key == NULL) {
513 amp_debug(MOD_STR, "device update info malloc failed");
514 aos_free(msg);
515 aos_free(devinfo);
516 return -1;
517 }
518 memset(devinfo->product_key, 0, IOTX_PRODUCT_KEY_LEN);
519
520 devinfo->device_name = aos_malloc(IOTX_DEVICE_NAME_LEN);
521 if (devinfo->device_name == NULL) {
522 amp_debug(MOD_STR, "device update info malloc failed");
523 aos_free(msg);
524 aos_free(devinfo);
525 return -1;
526 }
527 memset(devinfo->device_name, 0, IOTX_DEVICE_NAME_LEN);
528
529 devinfo->data.update.params = aos_malloc(msg_len);
530 if (devinfo == NULL) {
531 amp_debug(MOD_STR, "device update info malloc failed");
532 aos_free(msg);
533 aos_free(devinfo);
534 return -1;
535 }
536 memset(devinfo->data.update.params, 0, msg_len);
537
538 devinfo->type = AIOT_DEVINFO_MSG_UPDATE;
539 memcpy(devinfo->product_key, product_key, strlen(product_key));
540 memcpy(devinfo->device_name, device_name, strlen(device_name));
541 memcpy(devinfo->data.update.params, msg, msg_len);
542
543 res = aiot_devinfo_send(devinfo_handle, devinfo);
544 if (res < STATE_SUCCESS) {
545 amp_debug(MOD_STR, "das stepping failed");
546 aos_free(msg);
547 aos_free(devinfo->product_key);
548 aos_free(devinfo->device_name);
549 aos_free(devinfo->data.update.params);
550 aos_free(devinfo);
551 aiot_devinfo_deinit(&devinfo_handle);
552 return -1;
553 }
554
555 aos_free(msg);
556 aos_free(devinfo->product_key);
557 aos_free(devinfo->device_name);
558 aos_free(devinfo->data.update.params);
559 aos_free(devinfo);
560
561 return res;
562 }
563