电子工程师技术服务社区
公告
登录
|
注册
首页
技术问答
厂商活动
正点原子
板卡试用
资源库
下载
文章
社区首页
文章
如何打造属于你的私人语音助手之控制LED灯(NodeMCU)
分 享
扫描二维码分享
如何打造属于你的私人语音助手之控制LED灯(NodeMCU)
树莓派
nodemcu
MQTT
IAMLIUBO
关注
发布时间: 2020-04-07
丨
阅读: 2670
## 我是谁,谁又是我 Hi, 大家好,我是刘波,人在江湖行走的ID是:[IAMLIUBO](https://blogs.oopswow.com/)!受到电子芯吧客平台用户活跃度的感召,为了防止世界被破坏,为了保护世界的和平,于是我决定也要来电子芯吧客平台混个脸熟了(我不会承认我是为了稿费才来的!绝对不会!滑稽.gif)。 ## 前言 我们在上篇文章中,已经在树莓派上搭建好了MQTT server,既然都搭建好了,岂有不用的道理?那么本篇文章就教大家语音控制LED灯!带你解锁更多技能! ## 准备 在本篇文章中,你需要准备以下内容: **硬件** * 树莓派(已经搭建好wukong的pi,初学者请从前面几篇文章开始) * ESP8266(建议NodeMCU,芯吧客商城有售) * LED灯(直插的就可以) **软件** * Arduino IDE 这就是本篇文章需要准备的硬件跟软件,相信大多数Geek应该都有吧,那么废话说少,接下来开始!本次文章代码分为树莓派和NodeMCU两部分,我们先来看树莓派上的设置。 ## 树莓派 ### config.yml配置修改 本篇文章我们使用的是**chenzhuo**贡献的ControMqtt技能,相关介绍,大家可以从这个网址进行参考: [wukong-ControMqtt-chenzhuo](https://wukong.hahack.com/#/contrib?id=controlmqtt) 由于这个技能是之前dingdang,也就是wukong的前身的一个项目,有两处需要简单修改一下,这里我们先修改一下config.yml配置文件,增加关于MQTT的几个配置。 我们在config.yml文件的最后增加以下内容: ```yml # 使用mqtt与其他设备连接,作为Publisher mqttPub: host: 'XXX.XXX.XXX.XXX' #替换为你树莓派IP,或者其它MQTT server的IP port: '1883' #MQTT Server默认的端口号 topic_s: '/wukong/mqtt' #接收设备反馈信息的主题 ``` 大家增加上面的内容就可以了。 ### ControMqtt.py 代码修改 大家可以直接copy下面的代码,然后覆盖掉原来的就可以了,下面的代码我已经PR到**wukong-contrib**仓库,正在等在**wzpan**大佬的审核,我已经测试过,没有问题。 ```python # -*- coding: utf-8 #author: chenzhuo #Raspberry Pi or other platform can connect to the mqtt client,publisher and subscriber can access to bidirectional communication by switching their identities. #Example:you can get temperature of the enviroment collected by Arduino using Raspberry Pi when Raspberry Pi and Arduino communicate with each other. #The actions' file must be /home/pi/.wukong/action.json #Fix: Hcreak 2019.10 #Fix: imliubo 2020.04 NodeMCU code reference: https://wukong.hahack.com/#/contrib?id=controlmqtt import paho.mqtt.client as mqtt import paho.mqtt.publish as publish import time import json import os from robot import config, logging from robot.sdk.AbstractPlugin import AbstractPlugin logger = logging.getLogger(__name__) class Plugin(AbstractPlugin): SLUG = "mqttPub" def search_word(self, text): home_dir = os.path.expandvars('$HOME') location = home_dir + '/.wukong/action.json' if os.path.exists(location): f = open(location).read() try: fjson = json.loads(f) for key in fjson.keys(): value = fjson[key] if isinstance(value,list): # 向上兼容 for word in value: if word in text: return key,word if isinstance(value,dict): for word in value.keys(): if word in text: return key,value[word] except Exception as e: logger.error(e) self.say("抱歉出了问题", cache=True) return else: return def handle(self, text, parsed): profile = config.get() #get config if ( self.SLUG not in profile ) or ( 'host' not in profile[self.SLUG] ) or ( 'topic_s' not in profile[self.SLUG] ): self.say("主人,配置有误", cache=True) return host = profile[self.SLUG]['host'] port = 1883 if ( 'port' in profile[self.SLUG] ): port = int(profile[self.SLUG]['port']) topic_s = profile[self.SLUG]['topic_s'] # text = text.split(",")[0] #百度语音识别返回的数据中有个中文, topic_p,payload = self.search_word(text) try: # self.say("已经接收到指令", cache=True) mqtt_contro(host,port,topic_s,topic_p,payload,self.con) except Exception as e: logger.error(e) self.say("抱歉出了问题", cache=True) return def isValid(self, text, parsed): if self.search_word(text) == None: return False else: return True class mqtt_contro(object): def __init__(self,host,port,topic_s,topic_p,message,mic): self._logger = logging.getLogger(__name__) self.host = host self.port = port self.topic_s = topic_s self.topic_p = topic_p self.message = message self.mic = mic self.mqttc = mqtt.Client() self.mqttc.on_message = self.on_message self.mqttc.on_connect = self.on_connect #mqttc.on_publish = on_publish #mqttc.on_subscribe = on_subscribe #mqttc.on_log = on_log if self.host and self.topic_p: publish.single(self.topic_p, payload=self.message, hostname=self.host,port=self.port) if self.port and self.topic_s and self.host: self.mqttc.connect(self.host, self.port, 5) self.mqttc.subscribe(topic_s, 0) #while True: # self.mqttc.loop(timeout=5) self.mqttc.loop_start() def on_connect(self,mqttc, obj, flags, rc): if rc == 0: pass else: self._logger.critical("error connect") def on_message(self,mqttc, obj, msg): if msg.payload: self.mqttc.loop_stop() self.mqttc.disconnect() self.mic.say(str(msg.payload.decode("utf-8"))) else: time.sl
eep(5) self.mqttc.loop_stop() self.mqttc.disconnect() self.mic.say("连接超时", cache=True) def on_publish(self,mqttc, obj, mid): self._logger.debug("mid: " + str(mid)) def on_subscribe(self,mqttc, obj, mid, granted_qos): self._logger.debug("Subscribed: " + str(mid) + " " + str(granted_qos)) def on_log(self,mqttc, obj, level, string): self._logger.debug(string) ``` ### 增加 action.json 文件 这个文件是非常重要的,因为这里面的配置是用来命中技能和跟我们的下位机进行交互的,不过非常简单,我这里只加了一设备的配置,你如果还有别的设备,可以多加一点。 ```json { "开发板一": ["开灯","关灯"] } ``` 这里来给大家稍微解释一下,方便大家任意的添加其它设备。 其中**开发板一**这个名字可以随便修改,其实这是一个MQTT主题,也就是我们下位机(NodeMCU)订阅的主题,你可以修改为其它的,然后**开灯**,**关灯**,是下发的命令,也是我们命中技能的关键词,当你唤醒wukong时,如果说出了**开灯**或者**关灯**,就会命中当前技能,然后向**开发板一**这个主题发送命令,我们的下位机收到后,通过比对命令,就可以触发响应的操作了。 这就是我们需要在树莓派上需要进行的所有操作,下面我们再来看看NodeMCU的代码。 ## NodeMCU ### 代码 大家还记得我们在**如何打造属于你的私人语音助手之MQTT开发**这篇文章中的代码吗?没错,本节的代码就是在那篇文章的基础上简单修改了下,直接上代码: ```C /@@* wukong-robot control the NodeMCU by MQTT Compile with Arduino IDE Author: IAMLIUBO Github: github.com/imliubo */ #include "EspMQTTClient.h" #define LED_PIN D0 #define BLINK_PIN D4 void onConnectionEstablished(); EspMQTTClient client( "xxxxxxxxx", // Wifi ssid "xxxxxxxxx", // Wifi password onConnectionEstablished, // MQTT connection established callback "192.168.1.57", // MQTT broker ip 1883, // MQTT broker port "", // MQTT username "", // MQTT password "nodeMCU" // Client name ); long lastTime = 0; uint8_t pin_status = 0; void LED_Control_Callback(const String & payload) { const char* p = payload.c_str(); // Serial.println(p); if (strstr(p, "开灯")) { //命令会在MQTT消息中传过来,我们通过利用strtr()函数,就可以执行相应的操作了。 digitalWrite(LED_PIN, LOW); client.publish("/wukong/mqtt", "主人,灯已打开!");// "/wukong/mqtt" 是在config.yml中定义的 topic_s 字段,用来回复wukong_robot的自定义消息,也就是执行完命令后的语音, } if (strstr(p, "关灯")) { digitalWrite(LED_PIN, HIGH); client.publish("/wukong/mqtt", "主人,灯已关闭!"); } } void onConnectionEstablished() { client.subscribe("开发板一", LED_Control_Callback);// "开发板一" 是在action.json文件中定义的,用来接收wukong-robot下发的命令。 } void setup() { Serial.begin(115200); pinMode(BLINK_PIN, OUTPUT); pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, HIGH); } void loop() { client.loop(); long now = millis(); if (now - lastTime > 1000) { lastTime = now; digitalWrite(BLINK_PIN, !pin_status); pin_status = !pin_status; } } ``` 大家如果没有使用过Arduino开发NodeMCU(ESP8266),可以参考我的这篇文章**使用Arduino来开发ESP8266**先搭建好环境,大家直接将上面的代码下载到NodeMCU就可以了。 ## 运行效果 [私人语音助手控制LED演示](https://www.bilibili.com/video/av625243910)
原创作品,未经权利人授权禁止转载。详情见
转载须知
。
举报文章
点赞
(
1
)
IAMLIUBO
擅长:工控电子 能源电源 光电显示 设计,制造及服务 智能硬件
关注
评论
(1)
登录后可评论,请
登录
或
注册
06d00f0de7be16e9
18
天前...
老师,没有你那个自己画的板子只有ESP8266模块怎么接入直插式的LED灯泡
0
回复
发布
相关文章推荐
MK-米客方德推出工业级存储卡
Beetle ESP32 C3 蓝牙数据收发
Beetle ESP32 C3 wifi联网获取实时天气信息
开箱测评Beetle ESP32-C3 (RISC-V芯片)模块
正点原子数控电源DP100测评
DP100试用评测-----开箱+初体验
Beetle ESP32 C3环境搭建
【花雕体验】16 使用Beetle ESP32 C3控制8X32位WS2812硬屏之二
X
你的打赏是对原创作者最大的认可
请选择打赏IC币的数量,一经提交无法退回 !
100IC币
500IC币
1000IC币
自定义
IC币
确定
X
提交成功 ! 谢谢您的支持
返回
我要举报该内容理由
×
广告及垃圾信息
抄袭或未经授权
其它举报理由
请输入您举报的理由(50字以内)
取消
提交