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