Advertisement

基于ESP8266灯控

阅读量:

ESP8266灯控硬件:使用淘宝ESP-01模块,带一个ESP8266插槽和一个5V继电器,220V转5V用拆下的手机充电器

ESP8266代码,开放TCP Server(80)端口,同时作为TCP Client连接远端TCP Server,可读取和配置pin1、pin2,可读取adc

复制代码
 WIFI_NAME = "MERCURY_204"

    
 WIFI_PASSWORD = "Password"
    
 SERVER_IP = "192.168.1.200"
    
 SERVER_PORT = 8081
    
  
    
 led1 = 3
    
 led2 = 4
    
 gpio.mode(led1, gpio.OUTPUT)
    
 gpio.mode(led2, gpio.OUTPUT)
    
 wifi.setmode(wifi.STATION)
    
 wifi.sta.config(WIFI_NAME, WIFI_PASSWORD)
    
 wifi.sta.connect()
    
 wifi.sta.autoconnect(1)
    
  
    
 Watchdog = 0
    
 local function receiveData(data)
    
     Watchdog = 0
    
     local _GET = {}
    
     for k, v in string.gmatch(data, "(%w+)=(%d*)") do
    
     _GET[k] = v
    
     end
    
     
    
     local buf = "ID="..node.chipid();
    
     if(_GET.PIN1 == "1")then
    
     gpio.write(led1, gpio.HIGH);
    
     print("led1 on")
    
     elseif(_GET.PIN1 == "0")then
    
     gpio.write(led1, gpio.LOW);
    
     print("led1 off")
    
     end
    
     if(_GET.PIN1 ~= nil)then
    
     buf = buf.." PIN1="..gpio.read(led1)
    
     end
    
     
    
     if(_GET.PIN2 == "1")then
    
     gpio.write(led2, gpio.HIGH);
    
     print("led2 on")
    
     elseif(_GET.PIN2 == "0")then
    
     gpio.write(led2, gpio.LOW);
    
     print("led2 off")
    
     end
    
     if(_GET.PIN2 ~= nil)then
    
     buf = buf.." PIN2="..gpio.read(led2)
    
     end
    
     
    
     if(_GET.ADC ~= nil)then
    
     buf = buf.." ADC="..adc.read(0)
    
     end
    
     return buf
    
 end
    
  
    
 ClientConnectedFlag = 0
    
 i=0
    
 tmr.alarm(1, 1000, 1, function()
    
     if wifi.sta.getip()== nil then
    
     print("IP unavaiable, Waiting...")
    
     i=i+1
    
     if(i>10) then
    
         print("restart nodeMCU")
    
         node.restart()
    
     end
    
     elseif ClientConnectedFlag == 0 then
    
     print("Connecting to Server...")
    
     Client = net.createConnection(net.TCP, 0)
    
     Client:connect(SERVER_PORT, SERVER_IP)
    
  
    
     Client:on("receive", function(Client, data)
    
         Client:send(receiveData(data));
    
         collectgarbage();
    
     end)
    
     Client:on("connection", function(sck, c)
    
         ClientConnectedFlag = 1
    
     end)
    
     Client:on("disconnection", function(sck, c)
    
         ClientConnectedFlag = 0
    
     end)
    
     elseif Watchdog >= 120 then
    
     Watchdog = 0
    
     ClientConnectedFlag = 0
    
     Client:close();
    
     else
    
     Watchdog = Watchdog + 1
    
     end
    
 end)
    
  
    
 srv=net.createServer(net.TCP)
    
 srv:listen(80,function(conn)
    
     conn:on("receive", function(client,data)
    
     client:send(receiveData(data));
    
     client:close();
    
     collectgarbage();
    
     end)
    
 end)
    
    
    
    

阶段一、

PC上使用QT开放两个TCP Server(8080、8081),8081端口用于管理设备,8080端口用于与Android终端通讯

打印Log

Android终端作为TCP Client连接到PC的TCP 8080端口,通过Server获取和配置已连接的设备信息;

利用百度语音识别SDK,在Android上实现语音识别,将识别的文字发送给PC,实现手机端的语音控制。

设备、PC、Android连接方式:


方案改进:利用了之前买的nanopi开发版,手掌心大小,通过网线接入到局域网中,配置静态ip为192.168.1.200,将nanopi代替pc

nanopi上运行ubuntu系统,在pc上建立ubuntux64虚拟机,安装好arm交叉编译器,在pc上完成程序移植,因为下载qt太慢,直接用c重新写了一遍,相比之下c代码对字符串的处理真是麻烦,全部当数组操作。调试ok后编译拷贝到nanopi上,赋予可执行权限,就可以通过nanopi控制esp8266了

编写设备属性文件,编写读写配置文件接口

复制代码
 devices.txt

    
 #id:name:description
    
 12063707:人检测传感器:传感器
    
 4437787:插座:灯、风扇
    
 12345:测试:测试
    
    
    
    

使用小米USB WIFI代替网线,可让nano pi插电即可用,原先的nano pi系统中不包含mt7601驱动,下载最新镜像,即插即用,配置正确wifi名称和密码即可。

复制代码
 su root

    
 nmcli dev
    
 nmcli r wifi on
    
 nmcli dev wifi
    
 nmcli dev wifi connect "TP-LINK_102" password "88888888" ifname wlan0
    
    
    
    

NanoPI镜像下载地址及列表:http://wiki.friendlyarm.com/wiki/index.php/NanoPi_M1#Get_Image_Files

目前使用的是nanopi-m1_sd_friendlycore-xenial_4.14_armhf_20190823.img.zip,系统镜像更新加载方式请参看NanoPI官方说明。


加入LUA脚本接口,在控制器中解析并执行LUA脚本,脚本中实现简单的逻辑判断,例如加入人体热释电传感器后,如果检测到信号为1,则打开电灯。

LUA源码,官方网站:http://www.lua.org/ftp/

C和LUA互相调用方法可以参看博客:https://www.cnblogs.com/stephen-liu74/archive/2012/07/23/2469902.html

复制代码
 伪代码:

    
 onDeviceChange:
    
     如果pin1变化,pin1值为1,名称是"IRA"
    
     如果时间在晚上5点以后,名称是"LIGHT"的pin1值为0 {
    
         名称是"LIGHT"的pin1值设置为1
    
         播放MP3文件
    
         //汇报当天家中情况: 红外传感器捕捉几次,
    
     }
    
    
    
    

下载安装注册蒲公英VPN,只要安装蒲公英VPN即可在外网环境下以同一局域网方式互相访问,实现远程监看和控制家中设备。


利用nano pi麦克风,拾取环境音,利用百度语音识别API完成指令识别,响应诸如”开灯“、”关灯“之类指令,实现插座语音控制。

百度语音转文字API接口:vop.baidu.com/server_api,并根据指令进行智能应答

百度文字转语音API接口:tsn.baidu.com/text2audio

增加查询天气接口:http://wthrcdn.etouch.cn/weather_mini?city=上海,可查询最近5日天气,响应诸如”今天天气“、”明天天气“之类指令。使用gzip解压后得到json数据:


由于程序不断更改,经常运行几天后出现异常退出,不方便gdb调试,为不影响自己使用体验,使用了linux中cron服务,定期开启脚本,脚本启动后检查进程是否存在,如果不存在则启动进程。脚本start.sh

复制代码
 #!/bin/bash

    
 work_path=$(dirname $(readlink -f $0))
    
 cd ${work_path}
    
 PROCESS=`ps -e|grep MasterControl| wc -l` 
    
 #echo $PROCESS
    
 if [ $PROCESS -eq 0 ]
    
 then
    
     nohup ./MasterController &
    
 fi
    
    
    
    
复制代码
 //cron常用指令

    
 sudo apt-get install cron
    
 service cron start
    
 service cron stop
    
 service cron restart
    
 crontab -e
    
 ls -l /etc/init.d //查看本机上所有cron服务
    
  
    
 echo "*/2 * * * * /home/user/start.sh" >> davecron
    
 crontab davecron //davecron为cron配置脚本
    
    
    
    

阶段二、

尝试了在NanoPi上实现Http Server,基于开源libhv库

libhv是一个类似于libevent、libev、libuv的跨平台网络库,提供了更简单的接口和更丰富的协议。

项目地址:https://github.com/ithewei/libhv.git
码云镜像:https://gitee.com/ithewei/libhv.git
libhv博客专栏:
libhv源码分析:

他的Demo非常丰富,包含http客户端/服务器、websocket客户端/服务器、curl、httpd、sendmail、ftp、nc、nmap等,调用风格和golang的gin框架非常相似,支持跨平台,事件循环机制使用很方便。

在NanoPi上开放了80端口,同时支持http和websocket的连接,websocket用于提供手机连接实现消息和事件的及时推送。

复制代码
 //设备端更新

    
 router.POST("/device", post_device);
    
 //移动端访问:
    
 // curl -v -X GET http://ip:port/device/1
    
 router.GET("/device", get_device);
    
 router.GET("/device/:device_id", get_device);
    
 //移动端控制:
    
 // curl -v -X POST http://ip:port/control -H "Content-Type:application/json" -d '{"device_id":"1","pin1":"1","pin2":"1"}'
    
 router.POST("/control", post_control);
    
    
    
    

将所有数据传输统一为json格式,在nodemcu中对json的解析也很方便:

复制代码
 local _GET = {}

    
 for k, v in string.gmatch(data, '"(%w+)"%s*:%s*"(.-)"') do
    
     _GET[k] = v
    
 end
    
 if(_GET.PIN1 == "1")then
    
     gpio.write(led1, gpio.HIGH)
    
 elseif(_GET.PIN1 == "0")then
    
     gpio.write(led1, gpio.LOW)
    
 end
    
    
    
    

json数据生成

复制代码
 local content ='[{"ID":"'..node.chipid()..'","PIN1":"'..gpio.read(led1)..

    
     '","PIN2":"'..gpio.read(key1)..
    
     '","ADC":"'..adc.read(0)..
    
     '","IP":"'..wifi.sta.getip()..
    
     '","TYPE":"ACK"}]'
    
 local buf = 'HTTP/1.1 200 OK\r\n'..
    
     'Connection: close\r\n'..
    
     'Content-Type: application/json\r\n'..
    
     'Content-Length:'..#content..'\r\n'..
    
     '\r\n'..content..'\r\n'
    
    
    
    

注意在http response格式协议中,content字段之前有两个\r\n。之前没注意,一直是http server获取不到response,一度以为是libhv出了问题,后来找到是返回数据格式不对……

在NanoPi中安装了网云穿内网穿透工具,方便出门在外查看和控制家中设备。

网云穿web控制台:https://i.xiaomy.net/#/,前一个月免费试用可直接访问申请到网址的80端口,3Mbps每月1G,支持tcp和http协议。试用之后提供一个固定非80的端口,仅支持tcp协议,这样也能满足我的需求。ping得ip对应地址为北京市昌平 联通

客户端下载:https://down.xiaomy.net/linux/wyc_linux_arm,添加到开机启动中

添加开机启动:nano /etc/rc.local

nohup /root/workspace/wyc_linux_arm -token=***** &

后面陆续找到了其他内网穿透的平台:

闪库:ip地址在江苏常州

ngrok:ip地址在美国加利福尼亚洛杉矶

统一感觉就是免费的带宽太小,安全度低,还是钞能力好。


阶段三、

目前阿里云提供免费的物联网平台服务,阿里云物联网平台为设备提供安全可靠的连接通信能力,向下连接海量设备,支撑设备数据采集上云;向上提供云端API,服务端通过调用云端API将指令下发至设备端,实现远程控制。提供MQTTCoAPHTTP、HTTPS等多种协议的设备端SDK。物联网平台提供完整的设备生命周期管理功能,支持设备注册功能定义数据解析在线调试远程配置OTA升级实时监控设备分组设备删除等功能。提供多种身份验证方式,支持TLS、DTLS的安全通信方式。物联网平台规则引擎方便物联网设备消息转发和管理。

阿里云控制台地址:https://homenew.console.aliyun.com,阿里云使用MQTT.fx接入物联网平台https://help.aliyun.com/document_detail/86706.html,里面的Password生成小工具方便生成密码。解压文件后,双击sign.html文件,根据网页提示,配置参数,生成password。也可以使用Nodemcu中crypto、encoder模块生成密码。

复制代码
 local myMQTTtimes='6666'

    
 local myMQTThost=ProductKey..".iot-as-mqtt."..RegionId..".aliyuncs.com"
    
 local myMQTTClientId=ClientId.."|securemode=3,signmethod=hmacsha1,timestamp="..myMQTTtimes.."|"
    
 local myMQTTusername=DeviceName.."&"..ProductKey
    
 local hmacdata="clientId"..ClientId.."deviceName"..DeviceName.."productKey"..ProductKey.."timestamp"..myMQTTtimes
    
 local myMQTTpassword=encoder.toHex(crypto.hmac("sha1",hmacdata,DeviceSecret))
    
    
    
    

Nodemcu支持mqtt服务,需要在https://nodemcu-build.com/填写e-mail地址,选择ADC、crypto、encoder、file、GPIO、HTTP、I2C、MQTT、net、node、SNTP、SPI、timer、UART、WIFI,编译后发送固件到自己的邮箱,使用esptool工具即可烧录到esp8266中。

Nodemcu也支持源码Docker编译,Docker: Give Docker NodeMCU build a try. 其安装和编译方式在链接中介绍非常清晰。

串口波特率设置uart.setup(0,115200,8,0,1,0)

HTTP手册:https://nodemcu.readthedocs.io/en/release/modules/http/

timer手册:https://nodemcu.readthedocs.io/en/release/modules/tmr/

mqtt手册:https://nodemcu.readthedocs.io/en/release/modules/mqtt/

全部评论 (0)

还没有任何评论哟~