Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
网络学习营
【网络编程学习】+Mculover666+基于OneNET的智能家居
发布于 2018-08-19 09:44:53 浏览:2083
订阅该版
* 本帖最后由 Mculover666 于 2018-8-19 09:51 编辑 * 1. 第三周学习任务 * 通过 OneNet 页面控制灯的开关; * 通过 OneNet 页面控制灯的亮度; * 家里的温湿度信息实时展示; * 通过传感器监测,当监测到事件,向云端发送信息; 2.任务实现及所遇到的问题 2.1 基于onenet package的实现 2.1.1. ENV工具中开启onenet package [align=center]![1.png](/uploads/201808/18/131014cuujuj5cgcqdzuj5.png) 2.1.2. 代码实现 ![onenet_homework.c](/uploads/201808/19/094915ocems2dzzvyzoj8o.attach) ```/** * @File onenet_homework.c * @brief 利用onenet软件包完成以下功能: * 1.通过OneNET页面控制灯的开关; * 2.温湿度信息在onenet页面实时展示; * 3.温湿度信息超过阈值报警; * @author Mculover666 * @data 2018-08-17 */ #include
#include
#ifdef FINSH_USING_MSH #include
static void onenet_cmd_rsp_cb(uint8_t *recv_data, size_t recv_size, uint8_t **resp_data, size_t *resp_size); /* 上传温度数据、湿度数据、报警数据 */ static void onenet_homework_entry(void *parameter) { onenet_mqtt_init(); rt_thread_delay(rt_tick_from_millisecond(1 * 1000)); onenet_set_cmd_rsp_cb(onenet_cmd_rsp_cb); //temperature为10.0到40.0之间的随机数 //humidity为30.0%到60.0%之间随机数 int temperature = 0,humidity = 0; while(1) { /* 获取温度值和湿度值 */ while(1) { temperature = rand()%40; humidity = rand()%60; if(temperature > 10 && humidity >30) break; } if(temperature < 20) { if (onenet_mqtt_upload_string("temperature_alarm", "low temperature") < 0) { log_e("temperature_alarm upload has an error, stop uploading"); break; } } else if(temperature >30) { if (onenet_mqtt_upload_string("temperature_alarm", "high temperature") < 0) { log_e("temperature_alarm upload has an error, stop uploading"); break; } } else { if (onenet_mqtt_upload_string("temperature_alarm", "normal temperature") < 0) { log_e("temperature_alarm upload has an error, stop uploading"); break; } } rt_thread_delay(rt_tick_from_millisecond(1 * 500)); /* 发送温度值 */ if (onenet_mqtt_upload_digit("temperature_value", temperature) < 0) { log_e("temperature upload has an error, stop uploading"); break; } rt_thread_delay(rt_tick_from_millisecond(1 * 500)); if(humidity < 40) { if (onenet_mqtt_upload_string("humidity_alarm", "low humidity") < 0) { log_e("humidity_alarm upload has an error, stop uploading"); break; } } else if(humidity >50) { if (onenet_mqtt_upload_string("humidity_alarm", "high humidity") < 0) { log_e("humidity_alarm upload has an error, stop uploading"); break; } } else { if (onenet_mqtt_upload_string("humidity_alarm", "normal humidity") < 0) { log_e("humidity_alarm upload has an error, stop uploading"); break; } } rt_thread_delay(rt_tick_from_millisecond(1 * 500)); /* 发送湿度值 */ if (onenet_mqtt_upload_digit("humidity_value", humidity) < 0) { log_e("humidity upload has an error, stop uploading"); break; } rt_thread_delay(rt_tick_from_millisecond(5 * 1000)); } } int onenet_homework(void) { /* 创建一个动态线程 */ rt_thread_t tid; tid = rt_thread_create("onenet_homework", onenet_homework_entry, RT_NULL, 2 * 1024, RT_THREAD_PRIORITY_MAX / 3 - 1, 5); if(tid) { rt_thread_startup(tid); } return 0; } MSH_CMD_EXPORT(onenet_homework, send data to OneNET cloud cycle); /* 接收到数据后的回调函数 */ static void onenet_cmd_rsp_cb(uint8_t *recv_data, size_t recv_size, uint8_t **resp_data, size_t *resp_size) { if(*recv_data == 'i') { rt_kprintf("led state is on!
"); } else if(*recv_data == 'o') { rt_kprintf("led state is off!
"); } else { rt_kprintf("led luminance is %.*s
", recv_size, recv_data); } } #endif /* FINSH_USING_MSH */ ```2.2 基于onenet 应用平台的实现 2.3 任务完成结果 [align=center]![result2.png](/uploads/201808/18/204624fzy4oq6i4r5hp6ri.png) [align=center]![result1.png](/uploads/201808/18/204624qk7626gkci67ei33.png) [align=center]![result3.png](/uploads/201808/18/204624rnxk1okvemynv1oo.png) 2.4 任务完成需要注意的问题 整个任务中有5个数据流需要需要连续发送,如果不加延时会导致应用每次只更新一个值,数据丢失严重,所以在调用初始化命令onenet_mqtt_init后,在每次发送数据之后都加了延时语句: ``` rt_thread_delay(rt_tick_from_millisecond(1 * 500));``` 3.百度AI平台的应用 3.1. 任务要求 * 通过百度 TTS 语音合成功能,通过 http 接口上传一段文字,能够从百度获取相应的语音数据; 3.2. 任务实现 3.2.1. 参考文档 [list] (*)[webclient package](https://github.com/RT-Thread-packages/webclient) (*)[示例代码-利用http client 获取天气](https://github.com/RT-Thread-packages/samples/tree/master/network/httpclient) (*)[百度语音合成REST API文档](http://ai.baidu.com/docs#/TTS-API/top) [/list]3.2.2. urlencode实现 参考博客:[C语言实现urlcode和decode](http://www.cppblog.com/izualzhy/archive/2012/07/09/182456.html) ![url_encode.c](/uploads/201808/19/094939bzld829bkd4989d2.attach) ```/* * ===================================================================================== * Filename: url_encode.c * Description: url encode * * Created: 07/04/2012 08:32:24 PM * * Author: zhy (), izualzhy@163.com * ===================================================================================== */ #include
#include
/** * @brief URLEncode 对字符串URL编码 * * @param str 原字符串 * @param strSize 原字符串长度(不包括最后的\0) * @param result 结果缓冲区的地址 * @param resultSize 结果缓冲区的大小(包括最后的\0) * * @return: >0:resultstring 里实际有效的长度 * 0: 解码失败. */ int URLEncode(const char* str, const int strSize, char* result, const int resultSize) { int i; int j = 0;//for result index char ch; if ((str==NULL) || (result==NULL) || (strSize<=0) || (resultSize<=0)) { return 0; } for ( i=0; (i
='A') && (ch<'Z')) || ((ch>='a') && (ch<'z')) || ((ch>='0') && (ch<'9'))) { result[j++] = ch; } else if (ch == ' ') { result[j++] = '+'; } else if (ch == '.' || ch == '-' || ch == '_' || ch == '*') { result[j++] = ch; } else { if (j+3 < resultSize) { sprintf(result+j, "%%%02X", (unsigned char)ch); j += 3; } else { return 0; } } } result[j] = '\0'; return j; } ```3.2.3. 代码实现 ![http_speak.c](/uploads/201808/19/094952sx0oosxohozz7a2t.attach) ```/** * @File http_speak.c * @brief 通过百度 TTS 语音合成功能,通过 http 接口上传一段文字,能够从百度获取相应的语音数据; * @author Mculover666 * @data 2018-08-17 */ #include
/* 使用 HTTP 协议与服务器通信需要包含此头文件 */ #include
/* 使用BSD socket,需要包含socket.h头文件 */ #include
#include
#include
#define BUF_SZ 4096 //缓冲区大小 #define URL_LEN_MAX 256 //网址最大长度 #define TOKEN_LEN_MAX 100 //TOKEN最大长度 #define ApiKey "UwDz6lXM3dsPoQht5nGsgp3e" //应用ApiKey #define SecretKey "ZPKhskmNZeTfrsPTZ7it7ke5QTOrSCrR" //应用SecretKey #define lan "zh" //固定值zh,中英文混合模式 #define ctp "1" //客户端类型选择,web端填写固定值1 #define cuid "1c3269ef0b42447e857cc46b3bee2d6b" //用户唯一标识 #define vol "9" //音量,取值0-15,默认5为中音量 #define per "4" //发音人选择,0-普通女生,1为普通男生,3为情感合成-度逍遥,4为情感合成-度丫丫,默认为普通女声 #define spd "5" //语速,取值0-15,默认为5中语速 #define pit "5" //音调,取值0-15,默认为5中语调 #define aue "3" //3为mp3格式(默认); 4为pcm-16k;5为pcm-8k;6为wav(内容同pcm-16k) char token[100] ={0}; //获取到的token值 /* URLEncode 对字符串URL编码 */ extern int URLEncode(const char* str, const int strSize, char* result, const int resultSize); extern int webclient_get_file(const char* URI, const char* filename); /* 数据解析 */ void acquire_data_parse(rt_uint8_t *data) { cJSON *root = RT_NULL, *item = RT_NULL; root = cJSON_Parse((const char *)data); if (!root) { rt_kprintf("No memory for cJSON root!
"); return; } item = cJSON_GetObjectItem(root, "access_token"); rt_kprintf("
access_token:
%s", item->valuestring); strncpy(token, item->valuestring, strlen(item->valuestring)); item = cJSON_GetObjectItem(root, "scope"); rt_kprintf("
scope:
%s ", item->valuestring); item = cJSON_GetObjectItem(root, "expires_in"); rt_kprintf("
expires_in:%ld
", item->valueint); if (root != RT_NULL) cJSON_Delete(root); } /** * @brief 用Api Key 和 SecretKey访问网站换取token */ void acquire_token(int argc, char **argv) { rt_uint8_t *ptr = RT_NULL; int length = 0, result; struct webclient_session *session = RT_NULL; char *acquire_url = RT_NULL; /* 为 acquire_url 分配空间 */ acquire_url = rt_calloc(1, URL_LEN_MAX); if (!acquire_url) { rt_kprintf("No memory for acquire_url!
"); goto __exit; } /* 拼接 GET 网址 */ rt_snprintf(acquire_url, URL_LEN_MAX, "http://openapi.baidu.com/oauth/2.0/token?grant_type=client_credentials&client_id=%s&client_secret=%s",ApiKey,SecretKey); /* 为结构体 webclient_session 分配空间 */ session = (struct webclient_session *)rt_calloc(1, sizeof(struct webclient_session)); if (!session) { rt_kprintf("No memory for session structure!
"); goto __exit; } /* 连接网站 */ result = webclient_connect(session, acquire_url); if (result < 0) { rt_kprintf("Webclient connect URI(%s) failed!
", acquire_url); goto __exit; } /* 发送官方标准 header */ result = webclient_send_header(session, WEBCLIENT_GET, RT_NULL, RT_NULL); if (result < 0) { rt_kprintf("Webclient send header buffer failed return %d!", result); goto __exit; } /* 检查响应 */ if (webclient_handle_response(session)) { if (session->response != 200) { rt_kprintf("webclient handle response(%d) error!", session->response); goto __exit; } } /* 分配用于存放接收数据的缓冲 */ ptr = rt_calloc(1, BUF_SZ); if(!ptr) { rt_kprintf("No memory for data receive buffer!
"); goto __exit; } length = webclient_read(session, ptr, BUF_SZ); ptr[length] = '\0'; /* 获取到的数据解析 */ acquire_data_parse(ptr); __exit: /* 释放网址空间 */ if (acquire_url != RT_NULL) rt_free(acquire_url); /* 关闭会话 */ if (session != RT_NULL) webclient_close(session); /* 释放缓冲区空间 */ if (ptr != RT_NULL) rt_free(ptr); } /** * @brief 获取语音文件 */ int baidu_ai_speak(int argc, char **argv) { char* src = argv[1]; char obj[100] = {0}; unsigned int srclength = strlen(src); char *speak_url = RT_NULL; /* 将用户输入的字符串进行urlencode编码 */ rt_kprintf("src length: %d
", strlen(src)); URLEncode(src, srclength, obj, 100); rt_kprintf("obj: %s
", obj); rt_kprintf("obj: %d
", strlen(obj)); /* 为 speak_url 分配空间 */ speak_url = rt_calloc(1, URL_LEN_MAX); if (!speak_url) { rt_kprintf("No memory for weather_url!
"); goto __exit; } /* 拼接 wget 网址 */ rt_snprintf(speak_url, URL_LEN_MAX, "http://tsn.baidu.com/text2audio?tex=%s&lan=%s&ctp=%s&cuid=%s&tok=%s&vol=%s&per=%s&spd=%s&pit=%s&aue=%s",obj,lan,ctp,cuid,token,vol,per,spd,pit,aue); /* 获取音频文件*/ rt_kprintf("
%s
",speak_url); webclient_get_file(speak_url,"baidu-ai.mp3"); __exit: /* 释放网址空间 */ if (speak_url != RT_NULL) rt_free(speak_url); return 0; } #ifdef FINSH_USING_MSH #include
MSH_CMD_EXPORT(acquire_token, acquire_token); MSH_CMD_EXPORT(baidu_ai_speak, acquire_token); #endif ```3.3. 任务完成结果 [align=center]![result5.png](/uploads/201808/19/092134v1grzgzpvlae1zvg.png)
查看更多
6
个回答
默认排序
按发布时间排序
yqiu
2018-08-19
这家伙很懒,什么也没写!
:victory:
Mculover666
2018-08-19
这家伙很懒,什么也没写!
> --- :lol
lillian
2018-08-19
这家伙很懒,什么也没写!
我看了你的urlEncode接口,这个接口我测试过,编码后是GBK格式的,不是UTF-8的,为何测试可以生成语音呢?
lillian
2018-08-19
这家伙很懒,什么也没写!
学习一下你的get token方法
Mculover666
2018-08-19
这家伙很懒,什么也没写!
>我看了你的urlEncode接口,这个接口我测试过,编码后是GBK格式的,不是UTF-8的,为何测试可以生成语音呢? ... --- 这段代码我测试的时候生成的编码和我用在线工具生成是一样的呀
Mculover666
2018-08-19
这家伙很懒,什么也没写!
>学习一下你的get token方法 --- 可以直接在浏览器中访问看一下回来的数据,然后用cjson解析一下就ok
撰写答案
登录
注册新账号
关注者
0
被浏览
2.1k
关于作者
Mculover666
这家伙很懒,什么也没写!
提问
10
回答
14
被采纳
0
关注TA
发私信
相关问题
1
【LWIP学习营】第一关开发环境搭建
2
LWIP学习营第一周入门移植问题汇总贴
3
【LWIP学习营】f407+lan8720A小结
4
【LwIP学习营】【第一周】仅零散记录,无主题
5
【LWIP学习营】正点原子探索者F407+LAN8720第一周小结
6
【LwIP学习营】【第一周】网络通信基础及实现TCP 聊天客户端
7
【LwIP学习营】【第一周】LWIP移植
8
【LwIP学习营】【第一周】LWIP移植
9
【LwIP学习营】【第一周】开发板适配
10
【LwIP学习营】【第一周】环境搭建和配置验证
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
使用RC522软件包驱动FM1722
2
常量数据类型和表达式陷阱分享
3
进行i2c驱动移植的经验总结
4
在VSCode中使用clang-format
5
我该如何使用这个微雪的WIFI400 WIFI-LPB-100在rtt里或者我该怎样为它开发驱动
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
UART
WIZnet_W5500
ota在线升级
freemodbus
PWM
flash
cubemx
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
编译报错
Debug
rt_mq_消息队列_msg_queue
SFUD
msh
keil_MDK
ulog
C++_cpp
MicroPython
本月问答贡献
出出啊
1517
个答案
342
次被采纳
小小李sunny
1444
个答案
289
次被采纳
张世争
809
个答案
175
次被采纳
crystal266
547
个答案
161
次被采纳
whj467467222
1222
个答案
148
次被采纳
本月文章贡献
catcatbing
3
篇文章
5
次点赞
qq1078249029
2
篇文章
2
次点赞
xnosky
2
篇文章
1
次点赞
Woshizhapuren
1
篇文章
5
次点赞
YZRD
1
篇文章
2
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部