完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
从RVB2601的SDK看,已经实现了基于W800 AT命令的Socket抽象设备,本文中将尝试在现有功能基础上,实现和测试验证阿里云平台接入的等相关功能,同时去了解YoC中网络设备和AT解析器框架。 AT指令解析器 AT指令解析器 主要用于发送命令、等待响应,用户可通过atparser_response_recv()获取并解析该应答数据,对于对端主动发送的数据(数据即为带外数据),则传入对应的带外处理函数中。 AT指令解析器 · GitBook (t-head.cn) 接口详细说明 初始化一个AT指令解析器 atparser_uservice_t *atparser_init(utask_t *task, const char *name, uart_config_t *config) 根据指定的微服务任务,串口名以及串口配置信息创建一个AT 指令解析器,成功则返回atparser_uservice_t指针,失败返回NULL · 参数: · task:微服务任务 · name: 串口名 · config: 串口配置信息 · 返回值: · 成功则返回atparser_uservice_t指针,失败返回NULL · 初始化一个用户自定义的AT指令解析器 atparser_uservice_t *atparser_channel_init(utask_t *task, const char *name, void *config, at_channel_t *channel); 根据指定的微服务任务,串口名以及串口配置信息创建一个AT 指令解析器,成功则返回atparser_uservice_t指针,失败返回NULL · 参数: · task:微服务任务 · name: 设备名 · config: 设备配置信息 · channel:at指令解析器的channel · 返回值: · 成功则返回atparser_uservice_t指针,失败返回NUL at_channel是具体执行AT命令内容收发的通道,比如串口、SPI接口等,RVB2601开发板上使用SPI接口;atparse负责对命令内容的解析和格式化拼装。 带外数据处理函数的格式 typedef int (*oob_callback)(atparser_uservice_t *at, void *pive, oob_data_t *oob_data); 用户根据传入的数据,做相关的处理,若处理完成则返回0;若处理未完成则返回-1 · 参数: · at: AT 指令解析器 · pive:用户自定义数据 · oob_data: 带外数据结构体 · 返回值: · 0表示处理完成并退出本次OOB,-1表示处理未完成,需要继续执行OOB 创建一个带外数据服务 int atparser_oob_create(atparser_uservice_t *at, const char *prefix, oob_callback cb, void *context); 根据指定的AT 指令解析器,带外数据匹配字符串,带外数据处理函数,以及用户自定义的上下文创建一个带外数据处理服务,成功则返回0,失败则返回负值 带外数据服务相当于在AT通道上注册一个对特定格式内容的监听,当收到匹配的内容时,自动触发注册的oob_callback; 带外数据服务相当于在AT通道上注册一个对特定格式内容的监听,当收到匹配的内容时,自动触发注册的oob_callback; 代码实现 cli中注册一个命令去触发连接云等动作,在获取到IP后去给w800发AT命令,开始连接云。 //应用层,添加cli命令 extern int set_aliyun_key( ); extern int set_aliyun_smartconf( ); extern int cloud_connect(); static void do_yun_cmd(char *wbuf, int wbuf_len, int argc, char **argv) { if (argc > 1) { if (0 == strcmp(argv[1], "config")) { printf("do smart confgrn"); set_aliyun_smartconf( ); return; } else if (0 == strcmp(argv[1], "conn")) { printf("do cloud_connectrn"); cloud_connect(); return; } else if (0 == strcmp(argv[1], "set")) { printf("do set_aliyun_keyrn"); set_aliyun_key( ); return; } } } void cli_reg_cmd_user(void) { static const struct cli_command cmd_yun = { "yun", "yun comand", do_yun_cmd, }; aos_cli_register_command(&cmd_yun); } W800的AT解析器实现中增加对云连接状态和属性设置下发的处理 extern at_channel_t spi_channel; int w800_module_init(utask_t *task, w800_wifi_param_t *param) { if (w800_module_inited) { return 0; } if (task == NULL) { task = utask_new("w800", 7 * 1024, QUEUE_MSG_COUNT, AOS_DEFAULT_APP_PRI + 4); } if (task == NULL) { return -1; } if (param->reset_pin) { csi_gpio_pin_init(&g_reset_pin, param->reset_pin); csi_gpio_pin_mode(&g_reset_pin,GPIO_MODE_PULLUP); csi_gpio_pin_dir(&g_reset_pin,GPIO_DIRECTION_OUTPUT); csi_gpio_pin_write(&g_reset_pin, GPIO_PIN_LOW); aos_msleep(200); csi_gpio_pin_write(&g_reset_pin, GPIO_PIN_HIGH); aos_msleep(1000); LOGD(TAG, "hard reset"); } g_atparser_uservice_t = atparser_channel_init(task, NULL, param, &spi_channel); aos_mutex_new(&g_cmd_mutex); atparser_debug_control(g_atparser_uservice_t, 1); atparser_oob_create(g_atparser_uservice_t, "2,CLOSED", _closed2_handler, NULL); atparser_oob_create(g_atparser_uservice_t, "1,CLOSED", _closed1_handler, NULL); atparser_oob_create(g_atparser_uservice_t, "0,CLOSED", _closed0_handler, NULL); atparser_oob_create(g_atparser_uservice_t, "+EVENT=NET,LINK_UP", _gotip_handler, NULL); atparser_oob_create(g_atparser_uservice_t, "+EVENT=NET,LINK_DOWN", _disconnect_handler, NULL); atparser_oob_create(g_atparser_uservice_t, "+EVENT=RECV,", _recv_data_handler, NULL); atparser_oob_create(g_atparser_uservice_t, "+EVENT=DISCONNECT,0", _closed0_handler, NULL); atparser_oob_create(g_atparser_uservice_t, "+EVENT=DISCONNECT,1", _closed1_handler, NULL); atparser_oob_create(g_atparser_uservice_t, "+EVENT=DISCONNECT,2", _closed2_handler, NULL); atparser_oob_create(g_atparser_uservice_t, "+IDMSTA:", cloud_connsta_handler, NULL); //连接状态OOB注册 atparser_oob_create(g_atparser_uservice_t, "+IDMPS:", cloud_recv_handler, NULL); //属性设置OOB注册 w800_module_inited = 1; return 0; } /* 接收到云端下发的属性设置 */ /* oob_data->buf和oob_data->len为AT通道上接收到的"+IDMPS:"之后的内容和长度 */ static int cloud_recv_handler(atparser_uservice_t *at, void *priv, oob_data_t *oob_data) { //+IDMPS: int id = 0; int len = 0; char data[128] = {0}; LOGI(TAG,"%s(%d)",oob_data->buf,oob_data->len); char *str = strchr(oob_data->buf, ':'); if (str != NULL) { sscanf(oob_data->buf, "%d,%d,%srn", &id, &len, data); LOGI(TAG,"==>cloud_recv %d(%d):%srn",id, len, data); oob_data->used_len += (str - oob_data->buf+1); } /* recv data is not enough need recv more */ return 0; } /*云连接状态上报OOB处理*/ static int cloud_connsta_handler(atparser_uservice_t *at, void *priv, oob_data_t *oob_data) { LOGI(TAG,"==>cloud_conn: %s(%d)",oob_data->buf,oob_data->len); /* recv data is not enough need recv more */ return 0; } 实现云连接等功能的AT命令收发 int cloud_connect() { int ret = -1; g_net_status = NET_STATUS_READY; aos_mutex_lock(&g_cmd_mutex, AOS_WAIT_FOREVER); atparser_set_timeout(g_atparser_uservice_t, 30 * 1000); atparser_clr_buf(g_atparser_uservice_t); if (atparser_send(g_atparser_uservice_t, "AT+IDMCON") == 0) { if (atparser_recv(g_atparser_uservice_t, "OK") == 0) { ret = 0; LOGI(TAG,"===>IDMCON OK"); } } atparser_set_timeout(g_atparser_uservice_t, 8 * 1000); atparser_cmd_exit(g_atparser_uservice_t); aos_mutex_unlock(&g_cmd_mutex); return ret; } int set_aliyun_key( ) { int ret = -1; g_net_status = NET_STATUS_READY; aos_mutex_lock(&g_cmd_mutex, AOS_WAIT_FOREVER); atparser_set_timeout(g_atparser_uservice_t, 30 * 1000); atparser_clr_buf(g_atparser_uservice_t); if (atparser_send(g_atparser_uservice_t, "AT+IDMAU="%s","%s","%s","%s"", PRODUCT_KEY, DEVICE_NAME, DEVICE_SECRET, PRODUCT_SECRET) == 0) { if (atparser_recv(g_atparser_uservice_t, "OK") == 0) { ret = 0; LOGI(TAG,"===>IDMAU OK"); } } atparser_set_timeout(g_atparser_uservice_t, 30 * 1000); atparser_clr_buf(g_atparser_uservice_t); if (atparser_send(g_atparser_uservice_t, "AT+IDMPID=%ld", PRODUCT_ID) == 0) { if (atparser_recv(g_atparser_uservice_t, "OK") == 0) { ret = 0; LOGI(TAG,"===>IDMPID OK"); } } atparser_set_timeout(g_atparser_uservice_t, 8 * 1000); atparser_cmd_exit(g_atparser_uservice_t); aos_mutex_unlock(&g_cmd_mutex); return ret; } int set_aliyun_smartconf( ) { int ret = -1; g_net_status = NET_STATUS_READY; aos_mutex_lock(&g_cmd_mutex, AOS_WAIT_FOREVER); atparser_set_timeout(g_atparser_uservice_t, 30 * 1000); atparser_clr_buf(g_atparser_uservice_t); if (atparser_send(g_atparser_uservice_t, "AT+IDMCLS") == 0) { if (atparser_recv(g_atparser_uservice_t, "OK") == 0) { ret = 0; LOGI(TAG,"===>IDMCLS OK"); } } atparser_set_timeout(g_atparser_uservice_t, 30 * 1000); atparser_clr_buf(g_atparser_uservice_t); if (atparser_send(g_atparser_uservice_t, "AT+IWSSTART=0") == 0) { if (atparser_recv(g_atparser_uservice_t, "OK") == 0) { ret = 0; LOGI(TAG,"===>IWSSTART OK"); } } atparser_set_timeout(g_atparser_uservice_t, 8 * 1000); atparser_cmd_exit(g_atparser_uservice_t); aos_mutex_unlock(&g_cmd_mutex); return ret; } 在阿里云物联网平台创建产品并定义功能 为w800模块配网和配置五元组 手机app配网没有调通,后续再调,先用手动配网; 调用set_aliyun_key( )配置五元组后,重启,w800将会自动连接路由器; 在连上路由器获取到IP后,调用cloud_connect(),待手动连接状态OOB回调时,“+IDMSTA:2“”说明已经连上阿里云了,在阿里云后台可以看到设备已在线; 通过在阿里云后台的设备调试页面,可进行在线调试,对设备属性进行设置,开发板上将收到对应的属性值,如下图: 到此,阿里云接入和属性设置功能验证通过了,后续将继续完善功能,基于在阿里云上定义的产品功能,做进一步的开发实现更多的应用功能。 文章转载自:平头哥芯片开放社区 作者:niu |
|
相关推荐
|
|
只有小组成员才能发言,加入小组>>
【平头哥Sipeed LicheeRV 86开发板试用体验】Waft初体验
15655 浏览 1 评论
13703 浏览 4 评论
【平头哥Sipeed LicheeRV 86开发板试用体验】四、烧写waft系统&搭建waft测试环境
19620 浏览 2 评论
59026 浏览 19 评论
【限时福利】加入芯片开发社区,领100G电子工程师资料大礼包
87687 浏览 121 评论
邀请函 | 3月2日 来上海参加平头哥“玄铁RISC-V生态大会”
742浏览 0评论
读书分享会 | 玄铁RISC-V处理器入门与实战电子书免费下载!
631浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 05:14 , Processed in 0.726184 second(s), Total 66, Slave 50 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号