0×00前言
一提到智能家庭,大家可能首先想到的是各种大佬级公司搞的牛逼产品,或者说是创新产品。想想就觉得很复杂,有的用工控机,有的用树莓派,还有的用arduino,不管用什么,都绕不过服务器进行控制,比如yeelink平台,腾讯的智能硬件平台等等。其实,真实实现起来,并没有想想中这么复杂,我们甚至只用一个小的单片机就能实现。
0×01单片机实现web服务器
探讨用单片机来实现web服务器的文章通过baidu也能找到几篇,但比较详实的实现方法并没有找到,这里考虑有两种思路可以完成,一种是有线的lan模块,如w5500,这种模块本身就带有web服务的部分功能,使用起来比较简单,但是只能基于lan进行访问。另一种是通过stm32等单片机,配合网络模块来完成。当前我能想到的最简单的方法就是用stm32+esp8266来实现。
基于第一种方法,我觉得受模块性能影响比较大,受限于模块,没有开发感。于是考虑用第二种方法。这个方法里,有人用arduino来完成,这要基于c进行编程。另外,就是考虑用micropython,这样直接可以用python来实现。这里依然使用tpyboard v202。
0×02模拟实现家庭智能家居控制平台
因为没有想好要做一个多么复杂的实验,只是想能模拟一下效果,所有在整个的模块过程中,我选用了tpyboard v202开发板做主控制板,用一个发光二极管来模拟一个台灯(现实中,这里其实可以用一个继电器来控制其它设备的通断电),用一个直流小电机加迷你风扇叶表示模拟电风扇。整个实现还用到了一个三极管(S9014,NPN)来控制直流电机。
0×03硬件的搭建与连接
1、发光二极管的使用
发光二极管使用比较简单,直接看它的两条“腿”,长的那个是正极,反之是负极。
2、直流小电机的使用方法
上图直流小电机中,红色框内的两个接线端A和B,无论那个接正极或负极都可以,只不过转动的方向不一样而已。本次我是用B端接入正极,正好是顺时针转动。
3、三极管S9014(NPN)的使用方法
本次我们使用S9014的放大和开关功能,集电极接入v202的3.3V引脚,发射极接入电机某一端,通过给基极高低电平来控制发射极和集电极之间是否导通,从而控制直流电机转动或停止。
4、接线方法
我的实物连接图
0×04利用micropython实现web服务器
首先,编辑一个main.py文件。v202 开机自启动main.py 文件
try: import usocket as socket except: import socket import network from machine import UART from machine import Pin led_flag=Pin(2, Pin.OUT)#esp8266模块上的小灯 高电平:灭 低电平:亮 led = Pin(4, Pin.OUT)#发光二极管的控制引脚 motor = Pin(5, Pin.OUT)#直流电机的控制引脚 #初始化 led.low() motor.low() led_flag.high() def do_connect(ssid,pwd): sta_if = network.WLAN(network.STA_IF)#STA 模式 sta_if.active(False) if not sta_if.isconnected():#判断是否连接 sta_if.active(True) sta_if.connect(ssid,pwd)#ssid:WIFI名称 pwd:WIFI 密码 while not sta_if.isconnected(): pass if sta_if.isconnected(): return sta_if.ifconfig()[0] def main(ip_,dev_data,login_data,name,pwd): s = socket.socket() ai = socket.getaddrinfo(ip_, 80) addr = ai[0][-1] s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind(addr) s.listen(5) led_flag.low() #s_data=login_data while True: res = s.accept() client_s = res[0] client_addr = res[1] led_flag.high() req =client_s.readline() while True: h = client_s.readline() if h == b"" or h == b"\r\n": break #print(h) req+=(h.decode('utf-8').lower()) print("Request:") req=req.decode('utf-8').lower().split('\r\n') #http header 解析 req_data=req[0].lstrip().rstrip().replace(' ','') print(req_data) if req_data.find('favicon.ico')>-1: client_s.close() continue else: if len(req_data)<=12: #说明是第一次访问,输入login.html s_data=login_data else: req_data=req_data.replace('get/?','').replace('http/1.1','') _name=req_data.find('name') _pwd=req_data.find('pwd') if _name>-1 and _pwd>-1: #判断是否是用户登录 if req_data.find(name)>-1 and req_data.find(pwd)>-1: s_data=dev_data print('Login Success!') else: f=open('fail.html','r') s_data=f.read() f.close() print('Login Fail!') else: #判断是否是控制LED _index=req_data.find('led=') if _index>-1: s_data=dev_data led_val=req_data[_index+4:_index+6].lstrip().rstrip() print('led:',led_val) if led_val=='on': led.value(1) else: led.value(0) #判断是否是控制电机 _index=req_data.find('motor=') if _index>-1: s_data=dev_data motor_val=req_data[_index+6:_index+8].lstrip().rstrip() print('motor_val:',motor_val) if motor_val=='on': motor.value(1) else: motor.value(0) print('-----------') client_s.send(s_data) client_s.close() led_flag.low() f=open('device.html','r') dev_html=f.read() f.close() f=open('login.html','r') login_html=f.read() f.close() f=open('info.txt','r') info=f.read() f.close() name=info.split(',')[0].lstrip().rstrip() pwd=info.split(',')[1].lstrip().rstrip() print('name:',name) print('pwd:',pwd) myip_=do_connect('essid','pwd')#家中网络的WIFI名称和密码 print(myip_) main(myip_,dev_html,login_html,name,pwd)
login.html 登录页面