struct pando_buffer * FUNCTION_ATTRIBUTE construct_data_package_to_server(uint16_t *payload_type) { struct pando_buffer *gateway_data_buffer = NULL; struct sub_device_buffer *device_data_buffer = NULL; uint16_t buf_len = 0; //构建子设备数据包 device_data_buffer = construct_sub_device_data(); buf_len = GATE_HEADER_LEN - DEV_HEADER_LEN + device_data_buffer->buffer_length; gateway_data_buffer = pando_buffer_create(buf_len, GATE_HEADER_LEN - DEV_HEADER_LEN); if (gateway_data_buffer->buffer == NULL) { pd_printf("constuct_event_package_to_server malloc failed.\n"); return NULL; } printf("len %d, offset %d\n", gateway_data_buffer->buff_len, gateway_data_buffer->offset); //复制子设备事件包内容,并释放 pd_memcpy( gateway_data_buffer->buffer + gateway_data_buffer->offset, device_data_buffer->buffer, device_data_buffer->buffer_length); delete_device_package(device_data_buffer); if (pando_protocol_encode(gateway_data_buffer, payload_type)) { pd_printf("pando_protocol_encode error.\n"); } pando_protocol_set_sub_device_id(gateway_data_buffer, 112); show_package(gateway_data_buffer->buffer, gateway_data_buffer->buff_len); return gateway_data_buffer; }
int FUNCTION_ATTRIBUTE pando_protocol_encode(struct pando_buffer *pdbuf, uint16_t *payload_type) { uint8_t *position = pdbuf->buffer + pdbuf->offset; uint8_t *buffer_end = pdbuf->buffer + pdbuf->buff_len; struct mqtt_bin_header m_header; struct device_header sub_device_header; struct device_header *header = (struct device_header*)position; if ((position += DEV_HEADER_LEN) > buffer_end) { pd_printf("Incorrect encode buffer length.\n"); return -1; } pd_memcpy(&payload_type, &(header->payload_type), sizeof(header->payload_type)); *payload_type = net16_to_host(*payload_type); pd_memcpy(&(sub_device_header.flags), &(header->flags), sizeof(header->flags)); sub_device_header.flags = net16_to_host(sub_device_header.flags); if (init_pdbin_header(&m_header, &sub_device_header)) { pd_printf("Init pdbin header failed.\n"); return -1; } position -= GATE_HEADER_LEN; pd_memcpy(position, &m_header, GATE_HEADER_LEN); pdbuf->offset = pdbuf->offset + DEV_HEADER_LEN - GATE_HEADER_LEN; return 0; }
int pando_protocol_set_sub_device_id(struct pando_buffer *buf, uint16_t sub_device_id) { uint8_t *pos = buf->buffer + GATE_HEADER_LEN + buf->offset; if (pos == NULL) { pd_printf("subdevice null\n"); return -1; } else { pd_printf("set sub_device_id %d\n", sub_device_id); sub_device_id = host16_to_net(sub_device_id); pd_memcpy(pos, &sub_device_id, sizeof(sub_device_id)); return 0; } #if 0 uint8_t *pos = NULL; int rc = 0; uint16_t tmp_devid = sub_device_id; pos = buf->buffer + GATE_HEADER_LEN + buf->offset; if (buf == NULL || sub_device_id > 127*128) { pd_printf("subdevice null, subdevice id :%d\n", sub_device_id); return -1; } else { pd_printf("sub_device_id %d\n", sub_device_id); do { char d = tmp_devid % 128; tmp_devid /= 128; /* if there are more digits to encode, set the top bit of this digit */ if (tmp_devid > 0) d |= 0x80; pos[rc++] = d; } while (tmp_devid > 0); /* sub device using 2 bytes space.*/ if (rc == 1) { for(;pos >= buf->buffer; pos--) { *(pos + 1) = *pos; } buf->offset += 1; } return 0; } #endif }
// 创建事件包的步骤 // 1. 使用create_params_block添加第一个参数 // 2. add_next_param直到添加完全部参数 // 3. create_event_package创建数据包,并delete_params_block来释放params_block struct sub_device_buffer * FUNCTION_ATTRIBUTE construct_sub_device_event() { struct sub_device_buffer *event_buffer = NULL; struct TLVs *params_block = NULL; uint16_t event_num = 0x0911; uint16_t flag = 0x0011; uint32_t event_param1 = 0xa1b2c3d4; uint8_t event_param2 = 0xc1; char event_param3[] = "test data"; event_buffer = create_event_package(flag); if (NULL == event_buffer) { pd_printf("Create event package failed."); return NULL; } params_block = create_params_block(); if (params_block == NULL) { pd_printf("Create first tlv param failed.\n"); return NULL; } if (add_next_param(params_block, TLV_TYPE_UINT8, sizeof(event_param2), &event_param2)) { delete_params_block(params_block); pd_printf("Add next tlv param failed.\n"); return NULL; } if (add_next_param(params_block, TLV_TYPE_UINT32, sizeof(event_param1), &event_param1)) { delete_params_block(params_block); pd_printf("Add next tlv param failed.\n"); return NULL; } if (add_next_param(params_block, TLV_TYPE_BYTES, sizeof(event_param3), event_param3)) { delete_params_block(params_block); pd_printf("Add next tlv param failed.\n"); return NULL; } // 3. create event with flag, priority and tlv params add_event(event_buffer, event_num, 0, params_block); delete_params_block(params_block); finish_package(event_buffer); show_package(event_buffer->buffer, event_buffer->buffer_length); return event_buffer; }
void FUNCTION_ATTRIBUTE show_package(uint8_t *buffer, uint16_t length) { int i = 0; pd_printf("Package length: %d\ncontent is: \n", length); for (i = 0; i < length; i++) { pd_printf("%02x ",(uint8_t)buffer[i]); } pd_printf("\n"); }
/****************************************************************************** * FunctionName : pando_device_login * Description : try login device using pando cloud device register api. * Parameters : the specify login callback function * Returns : *******************************************************************************/ void FUNCTION_ATTRIBUTE pando_device_login(gateway_callback callback) { pd_printf("begin login device...\n"); if(callback != NULL) { device_login_callback = callback; } char * str_device_id = NULL; char * str_device_secret = NULL; str_device_id = pando_data_get(DATANAME_DEVICE_ID); str_device_secret = pando_data_get(DATANAME_DEVICE_SECRET); if(str_device_id == NULL || str_device_secret == NULL) { // has not registered pd_printf("login failed ! device has not been registerd...\n"); device_login_callback(PANDO_NOT_REGISTERED); return; } int device_id = atol(str_device_id); // try login via HTTP struct jsontree_int json_device_id = JSONTREE_INT(device_id); struct jsontree_string json_device_secret = JSONTREE_STRING(str_device_secret); struct jsontree_string json_protocol = JSONTREE_STRING("mqtt"); JSONTREE_OBJECT_EXT(device_info, JSONTREE_PAIR("device_id", &json_device_id), JSONTREE_PAIR("device_secret", &json_device_secret), JSONTREE_PAIR("protocol", &json_protocol)); request = (char *)pd_malloc(MAX_BUF_LEN); int ret = pando_json_print((struct jsontree_value*)(&device_info), request, MAX_BUF_LEN); pd_printf("device login request:::\n%s\n(end)\n", request); net_http_post(PANDO_API_URL "/v1/devices/authentication", request, http_callback_login); if(request != NULL) { pd_free(request); request = NULL; } }
int FUNCTION_ATTRIBUTE pando_protocol_decode(struct pando_buffer *pdbuf, uint16_t payload_type) { //get valid data position of buffer uint8_t *position = pdbuf->buffer + pdbuf->offset; uint8_t *pdbuf_end = pdbuf->buffer + pdbuf->buff_len; struct device_header sub_device_header; struct mqtt_bin_header *m_header = (struct mqtt_bin_header *)position; //check token if (check_pdbin_header(m_header)) { return -1; } position += GATE_HEADER_LEN; if (position > pdbuf_end) { pd_printf("Incorrect decode buffer length.\n"); return -1; } init_device_header(&sub_device_header, m_header, payload_type, pdbuf->buff_len - pdbuf->offset); //point to sub device packet header in the buffer position -= DEV_HEADER_LEN; pd_memcpy(position, &sub_device_header, DEV_HEADER_LEN); //now from offset to the end of buffer, is sub device packet to send pdbuf->offset = pdbuf->offset + GATE_HEADER_LEN - DEV_HEADER_LEN; return 0; }
static void save_data_to_flash() { pd_printf("saving data to flash...\n"); int32 magic = PANDO_CONFIG_MAGIC; STMFLASH_Write(PANDO_CONFIG_ADDRESS, (uint16 *)(&magic), sizeof(int32)); struct data_pair * cur; int32 cnt = 0; for(cur=head; cur!=NULL; cur=cur->next) { STMFLASH_Write(PANDO_CONFIG_ADDRESS + sizeof(int32) + sizeof(int32) + (cnt * sizeof(struct data_pair)), (uint16 *)cur, sizeof(struct data_pair)); cnt ++; } STMFLASH_Write(PANDO_CONFIG_ADDRESS + sizeof(int32), (uint16 *)&cnt, sizeof(int32)); pd_printf("done...\n"); }
void FUNCTION_ATTRIBUTE channel_send_to_device(PANDO_CHANNEL_NAME name, uint8_t * buffer, uint16_t length) { pd_printf("send package to device\n"); if(channels[name].device_cb != NULL ){ channels[name].device_cb(buffer, length); } }
int FUNCTION_ATTRIBUTE check_pdbin_header(struct mqtt_bin_header *bin_header) { if (pd_memcmp(bin_header->token, protocol_tool_base_params.token, sizeof(protocol_tool_base_params.token))) { pd_printf("Token error.\n"); return -1; } return 0; }
int FUNCTION_ATTRIBUTE pando_protocol_init(struct protocol_base init_params) { if ((struct protocol_base *)pd_memcpy(&protocol_tool_base_params, &init_params, sizeof(init_params)) == NULL) { pd_printf("pando_protocol_init failed.\n"); return -1; } return 0; }
/****************************************************************************** * FunctionName : zero_device_data_process. * Description : process the received data of zero device(zero device is the gateway itself). * Parameters : uint. * Returns : none. *******************************************************************************/ static void FUNCTION_ATTRIBUTE zero_device_data_process(uint8_t * buffer, uint16_t length) { struct pando_command cmd_body; uint16_t type = 0; uint16_t len = 0; struct sub_device_buffer * device_buffer = (struct sub_device_buffer *)pd_malloc(sizeof(struct sub_device_buffer)); if(device_buffer == NULL) { pd_printf("%s:malloc error!\n", __func__); return; } device_buffer->buffer = (uint8_t*)pd_malloc(length); if(device_buffer->buffer == NULL) { pd_printf("%s:malloc error!\n", __func__); pd_free(device_buffer); return; } pd_memcpy(device_buffer->buffer, buffer, length); device_buffer->buffer_length = length; struct TLVs *cmd_param = get_sub_device_command(device_buffer, &cmd_body); if(COMMON_COMMAND_SYN_TIME == cmd_body.command_num ) { pd_printf("PANDO: synchronize time\n"); uint64_t time = get_next_uint64(cmd_param); show_package((uint8_t*)(&time), sizeof(time)); // pando_set_system_time(time); } if( device_buffer->buffer != NULL) { pd_free( device_buffer->buffer); device_buffer->buffer = NULL; } if(device_buffer != NULL) { pd_free(device_buffer); device_buffer = NULL; } }
/****************************************************************************** * FunctionName : pando_data_set * Description : set the vale of the parameter stored, if the parameter is existing. Else creat the parameter, and save it. * Parameters : key -- the parameter; value -- the value of the parameter. * Returns : the save result *******************************************************************************/ SET_RESULT pando_data_set(char* key, char* value) { struct data_pair * p; p = find_pair_by_key(key); if(p != NULL) { // key exist, update value. pd_strncpy(p->val, value, DATAPAIR_VALUE_LEN); pd_printf("key %s updated...\n", key, p->val); } else { // key not exist, create a new pair. struct data_pair * p = (struct data_pair * )pd_malloc(sizeof(struct data_pair)); pd_strncpy(p->key, key, DATAPAIR_KEY_LEN); pd_strncpy(p->val, value, DATAPAIR_VALUE_LEN); p->next = head; head = p; pd_printf("key %s created..., value %s \n", key, p->val); } save_data_to_flash(); }
void load_data_from_flash() { pd_printf("loading config data from flash...\n"); int32 cnt, i; int32 magic = 0; pd_printf("loading config data from flash...\n"); //TODO: add system data storage interface. //STMFLASH_Read(PANDO_CONFIG_ADDRESS, (uint16 *)&magic, sizeof(int32)); pd_printf("read magic : %x\n", magic); if(magic != PANDO_CONFIG_MAGIC) { pd_printf("flash config data not initialized!\n"); return; } ////TODO: add system data storage interface. //STMFLASH_Read(PANDO_CONFIG_ADDRESS + sizeof(int32), (uint16 *)&cnt, sizeof(int32)); pd_printf("reading config from flash , key count : %d...\n", cnt); for(i=0; i<cnt; i++) { struct data_pair * p = (struct data_pair * )pd_malloc(sizeof(struct data_pair)); STMFLASH_Read(PANDO_CONFIG_ADDRESS + sizeof(int32) + sizeof(int32) + sizeof(struct data_pair)*i, (uint16 *)p, sizeof(struct data_pair)); p->next = head; head = p; } pd_printf("done...\n"); }
static void delete_files(const GEList *file_list) { GList *iter; char *temp_utf8; int count_deleted = 0; pd_start(_("Deleting Files")); for (iter = g_elist_first(file_list); iter; iter = g_list_next(iter)) { /* flush pending gtk operations so the UI doesn't freeze */ pd_scroll_to_bottom(); while (gtk_events_pending()) gtk_main_iteration(); if (pd_stop_requested()) { pd_printf(PD_ICON_WARN, _("Operation stopped at user's request")); break; } temp_utf8 = str_filename_to_utf8(iter->data, _("(UTF8 conversion error)")); if (unlink(iter->data) == 0) { count_deleted++; pd_printf(PD_ICON_OK, _("Deleted file \"%s\""), temp_utf8); } else { int save_errno = errno; pd_printf(PD_ICON_FAIL, _("Error deleting file \"%s\""), temp_utf8); pd_printf(PD_ICON_NONE, "%s (%d)", strerror(save_errno), save_errno); } free(temp_utf8); } pd_printf(PD_ICON_INFO, _("Done (deleted %d of %d files)"), count_deleted, file_list->length); pd_end(); if (count_deleted > 0) fl_refresh(TRUE); }
int OpenNetworkLink(char *name, unsigned short netid) { PRIV_SAVE_AREA int s, proto, ret; struct ifreq req; struct sockaddr_ll addr; if (config.vnet == VNET_TYPE_TAP) { receive_mode = 6; return tun_alloc(name); } proto = htons(netid); enter_priv_on(); s = socket(PF_PACKET, SOCK_RAW, proto); leave_priv_setting(); if (s < 0) { if (errno == EPERM) error("Must be root for direct NIC access\n"); return -1; } fcntl(s, F_SETFL, O_NDELAY); strcpy(req.ifr_name, name); if (ioctl(s, SIOCGIFINDEX, &req) < 0) { close(s); return -1; } addr.sll_family = AF_PACKET; addr.sll_protocol = proto; addr.sll_ifindex = req.ifr_ifindex; if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { pd_printf("OpenNetwork: could not bind socket: %s\n", strerror(errno)); close(s); return -1; } enter_priv_on(); ret = ioctl(s, SIOCGIFFLAGS, &req); leave_priv_setting(); if (ret < 0) { close(s); return -1; } receive_mode = (req.ifr_flags & IFF_PROMISC) ? 6 : ((req.ifr_flags & IFF_BROADCAST) ? 3 : 2); return s; }
int GetDeviceHardwareAddress(char *device, char *addr) { if (config.vnet == VNET_TYPE_DSN || config.vnet == VNET_TYPE_TAP) { /* This routine is totally local; doesn't make request to actual device. */ int i; memcpy(local_eth_addr, DOSNET_FAKED_ETH_ADDRESS, 6); *(unsigned short int *)&(local_eth_addr[2]) = DosnetID; memcpy(addr, local_eth_addr, 6); pd_printf("Assigned Ethernet Address = "); for (i=0; i < 6; i++) pd_printf("%02x:", local_eth_addr[i] & 0xff); pd_printf("\n"); } else { int s = socket(AF_INET, SOCK_DGRAM, 0); struct ifreq req; int err; strcpy(req.ifr_name, device); err = ioctl(s, SIOCGIFHWADDR, &req); close(s); if (err == -1) return err; #ifdef NET3 memcpy(addr, req.ifr_hwaddr.sa_data,8); #else memcpy(addr, req.ifr_hwaddr, 8); #endif } return 0; }
int pando_protocol_get_sub_device_id(struct pando_buffer *buf, uint16_t *sub_device_id) { uint8_t *pos = buf->buffer + GATE_HEADER_LEN + buf->offset; if (pos == NULL) { pd_printf("subdevice null\n"); return -1; } else { pd_memcpy(sub_device_id, pos, sizeof(*sub_device_id)); *sub_device_id = net16_to_host(*sub_device_id); return 0; } }
/* event exactly the same as command */ void FUNCTION_ATTRIBUTE decode_command(struct pando_buffer *buf, uint16_t payload_type) { // 网关解包 pando_protocol_decode(buf, payload_type); // 网关向子设备传递数据包,如果是向子设备发包,请用对应的设备send函数 struct sub_device_buffer *device_buffer = pd_malloc(sizeof(struct sub_device_buffer)); device_buffer->buffer_length = pando_get_package_length(buf); device_buffer->buffer = pd_malloc(device_buffer->buffer_length); // 从网关数据包中获取子设备数据包 pd_memcpy(device_buffer->buffer, pando_get_package_begin(buf), device_buffer->buffer_length); // 获取数据完成,释放网关缓冲区 pando_buffer_delete(buf); /* 以下是子设备解析代码 */ struct pando_command cmd_body; // 1.子设备解命令包, 返回参数区的起始位置 struct TLVs *cmd_params_block = get_sub_device_command(device_buffer, &cmd_body); pd_printf("sub id %02x, cmd num %02x, pri %02x, count: %d\n", cmd_body.sub_device_id, cmd_body.command_num, cmd_body.priority, cmd_body.params->count); // 2.子设备获取命令参数 uint16_t tlv_length; uint8_t *value = pd_malloc(100); uint8_t param1 = get_next_uint8(cmd_params_block); show_package(¶m1, sizeof(param1)); uint32_t param2 = get_next_uint32(cmd_params_block); show_package(¶m2, sizeof(param2)); char *param_bytes = get_next_bytes(cmd_params_block, &tlv_length); pd_memcpy(value, param_bytes, tlv_length); show_package(value, tlv_length); pd_free(value); // 3. 删除子设备缓冲区 delete_device_package(device_buffer); }
struct sub_device_buffer * FUNCTION_ATTRIBUTE create_data_package(uint16_t property_num, uint16_t flags, struct TLVs *data_params) { struct sub_device_buffer *data_buffer = NULL; struct pando_property *single_property = NULL; struct device_header *header = NULL; uint16_t payload_length; uint16_t payload_type = PAYLOAD_TYPE_DATA; if (data_params == NULL) { pd_printf("Must create data package with params.\n"); return NULL; } data_buffer = (struct sub_device_buffer *)pd_malloc(sizeof(struct sub_device_buffer)); payload_length = sizeof(struct pando_property) + current_tlv_block_size - sizeof(struct TLVs); //count 被重复包含了 data_buffer->buffer_length = payload_length + DEV_HEADER_LEN; data_buffer->buffer = (uint8_t *)pd_malloc(data_buffer->buffer_length); pd_memset(data_buffer->buffer, 0, data_buffer->buffer_length); header = (struct device_header *)data_buffer->buffer; single_property = (struct pando_property *)(data_buffer->buffer + DEV_HEADER_LEN); base_params.data_sequence++; header->crc = 0x11; header->flags = host16_to_net(flags); header->frame_seq = host32_to_net(base_params.data_sequence); header->magic = MAGIC_HEAD_SUB_DEVICE; header->payload_len = host16_to_net(payload_length); header->payload_type = host16_to_net(payload_type); single_property->property_num = host16_to_net(property_num); pd_memcpy(single_property->params, data_params, current_tlv_block_size); return data_buffer; }
struct sub_device_buffer * FUNCTION_ATTRIBUTE construct_sub_device_data() { struct sub_device_buffer *data_buffer = NULL; struct TLVs *params_block = NULL; int ret = 0; uint16_t property_num = 0x1516; uint16_t property_num2 = 0x1122; uint16_t flag = 0; uint32_t data_param1 = 0xa1b2c3d4; uint8_t data_param2 = 0xc1; char data_param3[] = "test data"; //create buffer, remember delete data_buffer = create_data_package(flag); if (data_buffer == NULL) { pd_printf("Create data package failed."); } params_block = create_params_block(); if (params_block == NULL) { pd_printf("Create first tlv param failed.\n"); return NULL; } if (add_next_uint32(params_block, data_param1)) { delete_params_block(params_block); pd_printf("Add next tlv param failed.\n"); return NULL; } if (add_next_uint8(params_block, data_param2)) { delete_params_block(params_block); pd_printf("Add next tlv param failed.\n"); return NULL; } if (add_next_bytes(params_block, strlen(data_param3), data_param3)) { delete_params_block(params_block); pd_printf("Add next tlv param failed.\n"); return NULL; } add_next_property(data_buffer, property_num, params_block); // once the params block has been added to data package //you must delete it even you are going to add another block to the package delete_params_block(params_block); //add different property params_block = create_params_block(); if (params_block == NULL) { pd_printf("Create first tlv param failed.\n"); return NULL; } if (add_next_uint8(params_block, data_param2)) { delete_params_block(params_block); pd_printf("Add next tlv param failed.\n"); return NULL; } if (add_next_bytes(params_block, strlen(data_param3), data_param3)) { delete_params_block(params_block); pd_printf("Add next tlv param failed.\n"); return NULL; } ret = add_next_property(data_buffer, property_num2, params_block); if (ret != 0) { delete_params_block(params_block); pd_printf("add_next_property failed."); return NULL; } //do not forget to delete params block again delete_params_block(params_block); finish_package(data_buffer); show_package(data_buffer->buffer, data_buffer->buffer_length); return data_buffer; }
void FUNCTION_ATTRIBUTE decode_data(struct pando_buffer *buf, uint16_t payload_type) { // 网关解包 pando_protocol_decode(buf, payload_type); // 网关向子设备传递数据包,如果是向子设备发包,请用对应的设备send函数 struct sub_device_buffer *device_buffer = pd_malloc(sizeof(struct sub_device_buffer)); device_buffer->buffer_length = pando_get_package_length(buf); device_buffer->buffer = pd_malloc(device_buffer->buffer_length); // 从网关数据包中获取子设备数据包 pd_memcpy(device_buffer->buffer, pando_get_package_begin(buf), device_buffer->buffer_length); // 获取数据完成,释放网关缓冲区 pando_buffer_delete(buf); show_package(device_buffer->buffer, device_buffer->buffer_length); /* 以下是子设备解析代码 */ struct pando_property data_body; uint8_t *buf_end = device_buffer->buffer + device_buffer->buffer_length; int i = 0; uint16_t tlv_type, tlv_length; uint8_t *value = pd_malloc(100); struct TLV *param = NULL; struct TLVs *property_block; // 2.子设备获取命令参数 uint32_t param1 = 0; uint8_t param2 = 0; char *param_bytes = NULL; while(1) { property_block = get_sub_device_property(device_buffer, &data_body); if (property_block == NULL) { pd_printf("reach end of buffer\n"); break; } pd_printf("count: %d\n", data_body.params->count); if (data_body.params->count == 3) { param1 = get_next_uint32(property_block); show_package(¶m1, sizeof(param1)); param2 = get_next_uint8(property_block); show_package(¶m2, sizeof(param2)); param_bytes = get_next_bytes(property_block, &tlv_length); pd_memcpy(value, param_bytes, tlv_length); show_package(value, tlv_length); } else if (data_body.params->count == 2) { param2 = get_next_uint8(property_block); show_package(¶m2, sizeof(param2)); param_bytes = get_next_bytes(property_block, &tlv_length); pd_memcpy(value, param_bytes, tlv_length); show_package(value, tlv_length); } } pd_free(value); // 3. 删除子设备缓冲区 delete_device_package(device_buffer); }
void GenerateDosnetID(void) { DosnetID = DOSNET_TYPE_BASE + (rand() & 0xff); pd_printf("Assigned DosnetID=%x\n", DosnetID); }
static void FUNCTION_ATTRIBUTE http_callback_login(char * response) { if(request != NULL) { pd_free(request); request = NULL; } if(response == NULL) { device_login_callback(PANDO_LOGIN_FAIL); return; } pd_printf("response=%s\n(end)\n", response); struct jsonparse_state json_state; jsonparse_setup(&json_state, response, pd_strlen(response)); int code; char message[MSG_BUF_LEN]; char access_token[ACCESS_TOKEN_LEN*2 + 16]; char access_addr[KEY_BUF_LEN]; access_token[ACCESS_TOKEN_LEN*2] = '\0'; int type; while ((type = jsonparse_next(&json_state)) != 0) { if (type == JSON_TYPE_PAIR_NAME) { if(jsonparse_strcmp_value(&json_state, "code") == 0) { jsonparse_next(&json_state); jsonparse_next(&json_state); code = jsonparse_get_value_as_int(&json_state); } else if(jsonparse_strcmp_value(&json_state, "message") == 0) { jsonparse_next(&json_state); jsonparse_next(&json_state); jsonparse_copy_value(&json_state, message, MSG_BUF_LEN); } else if(jsonparse_strcmp_value(&json_state, "data") == 0) { while((type = jsonparse_next(&json_state)) != 0 && json_state.depth > 1) { if(type == JSON_TYPE_PAIR_NAME) { if(jsonparse_strcmp_value(&json_state, "access_token") == 0) { jsonparse_next(&json_state); jsonparse_next(&json_state); jsonparse_copy_value(&json_state, access_token, ACCESS_TOKEN_LEN*2 + 16); } else if(jsonparse_strcmp_value(&json_state, "access_addr") == 0) { jsonparse_next(&json_state); jsonparse_next(&json_state); jsonparse_copy_value(&json_state, access_addr, KEY_BUF_LEN); } } } } } } if(code != 0) { pd_printf("device login failed: %s\n", message); if(device_login_callback != NULL) { device_login_callback(PANDO_LOGIN_FAIL); } return; } hex2bin(pando_device_token, access_token); pd_printf("device login success, access_addr : %s\n", access_addr); pando_data_set(DATANAME_ACCESS_ADDR, access_addr); pando_data_set(DATANAME_ACCESS_TOKEN, access_token); if(device_login_callback != NULL) { device_login_callback(PANDO_LOGIN_OK); } }