DIY一个具有远程控制功能的智能家居原型系统
本帖最后由 gongqingkui 于 2016-9-16 10:58 编辑smarthome 0.1是一个智能家居系统的雏形。主要实现局域网、因特网远程控制家里的电器;下一步要实现根据传感器数据控制家电功能;远景要实现根据人工智能自己控制电器功能;现在初步实现第一个功能。长得大概是这个样子。系统框图如下。远程控制主要实现方式:局域网或者手机登录架设在cubieboard2上的网页界面,点击开关、输入数字、输入文字提交之后,系统将数据交给后台python程序;由python程序提交给串口通信。串口数据发送到连接在cubieboard2上的arduino模块。arduino模块解析串口数据,控制相应的LED,伺服器和LCD显示器。 系统运行视频在这里。http://v.youku.com/v_show/id_XMTcyNjk1MjY3Mg==.html cubieboard2未出镜,他是系统主核心,完成web服务器架设,与arduino串口通信的功能,同时肩负arduino模块供电。程序代码:https://github.com/gongqingkui/smarthome启动服务器pythonweb_manual.py 1234访问相应服务器http://ip:1234就可以看到控制界面如图。
提交相应动作后,挂在Arduino上的各种设备会做出反应。以后的文章会逐步复述这个小系统是怎么搭建起来的。
本帖最后由 gongqingkui 于 2016-9-22 23:09 编辑
这个系统可以识别三种指令:二值型、整数型和字符串型。LED开关、闪烁显然是二值型的指令控制的。命令首字母为b,为b0或者b1,标示二值型的关和开。这里以控制Arduino板子上的LED为例:只用一句话digitalWrite(13, HIGH);或者digitalWrite(13,LOW);。这个LED的引脚接在13脚上,所以控制它高低电平就可以实现闪烁或者亮灭的功能。同理,如果不接Arduino板上的LED而另外接诸如继电器之类的元件,就可以实现控制外围高压电路的功能。数值型指令发送一个整数,命令首字母为d,为dIntNUM。这里用伺服器作为实例。伺服器根据收到的0-180的数据进行角度调整。语句也很简单。引入并且实例化Servo:#include <Servo.h>Servo servo1;在setup()函数中servo1.attach(10);设定伺服器1的数据引脚接到10脚上。在程序loop中进行接收和处理指令,之后发送角度到伺服器1:servo1.write(ans);字符型的指令发送一条字符串给Arduino主机,命令首字母为s,为sString。这里用1602液晶屏做例子,把收到的字符串显示到液晶屏上。语句基本是:#include <LiquidCrystal.h>LiquidCrystal lcd(12, 11, 5, 4, 3, 2);初始化setup时:lcd.begin(16,2);在随便输出点什么看看:lcd.print("SmartHome");。接收到相关字符串后,先设定显示位置lcd.setCursor(0,0);然后输出数据lcd.print(data + 1);以上,实现了接收指令后解析,发送到相应的设备或者控制外围硬件做出反应的功能。下面说明如何给Arduino发送指令。 本帖最后由 gongqingkui 于 2016-10-18 10:39 编辑
串口这个小系统Arduino的串口接收消息并解析、控制硬件。接收的三种消息分别用不同字母开头,Arduino判断首字母并解析出相应数据,发送控制命令给硬件。在setup中打开和初始化串口。Serial.begin(9600);Serial.flush();在loop中接收串口发来的消息,存进buffer中,并调用splitString函数处理数据,再调用setLED完成对硬件发送控制指令的操作。在测试时,可以使用Arduino自带的串口监视器,自己手动发送以b、d、s开头的测试信号。下面再连到Cubieboard上去。cubieboard串口链接在这个小系统的设计中,Arduino负责硬件控制,接受解析指令。而另外一台Cubieboard2负责构建IOT服务器。这个服务器现在主要完成web接口和发送指令给Arduino的功能,未来还要完成自动控制和智能控制的功能。之所以不直接用Arduino做中心,也是考虑为未来自动和智能控制的留空间。首先Cubieboard最简单先要和Arduino用串口连起来。插上USB转串口线之后,进到/dev/中ls下,可以看到以ttyUSB开头的设备,例如ttyUSB0,就表示串口线的名字。然后把TX和RX脚连到Arduino的0和1脚上。用minicom软件测试下连上Arduino没有。首先下载安装sudo apt-get install minicom然后再配置下sudo minicom –s主要是把串口设置中的名字修改为USB串口线名字,关闭硬件流控制功能。然后就可以打开minicom测试了。直接输入相应的控制指令并且回车,就会将指令发送到Arduino中,如果有错的话,可以试下把串口线rx和tx对调。 本帖最后由 gongqingkui 于 2016-10-18 10:41 编辑
python串口Minicom串口测试正常之后,就可以写Python程序通过串口发送指令了。写好串口收发程序也是为了下一步web封装和与在线物联网服务连接。发送程序serialPortModule.py比较简单:import serial
defserialSend(str):
t = serial.Serial('/dev/ttyUSB1',9600)
with t:
n = t.write(str)
t.close()
return n
引入serial包后,新建一个发送函数serialSend,以待发送指令作为参数。语句很简单,返回发送的指令长度。这里唯一需要注意的是ttyUSB的编号,要在/dev/里查询得到。那么接收的程序serialRead.py是这样的:import serial
defserialRead():
t = serial.Serial('/dev/ttyUSB1',9600)
print t.isOpen()
with t:
while(1):
s = t.readline()
print s
#todo save to DB or web
if __name__ =='__main__':
serialRead()
程序自动接收串口发送的字符串指令,解析后可以完成转发到在线服务器或者存储到数据库的操作。 本帖最后由 gongqingkui 于 2016-10-18 10:42 编辑
web封装编写好串口发送函数后,可在命令行下进行简单测试。测试无误后,可以编写web程序,在web程序中,根据用户点击,来调用串口发送函数,进行指令的传递。Web服务器这里用的是python的web库。代码如下:web_manual.py程序导入相应的包后,首先用render指明模板所在目录templates/,然后指定URL访问列表情况,最后根据URL中制定名字,编写相应的控制器。控制器中的GET和POST分别指代两种访问方法,用render.具体模板名来传值到相应模板。Db类和sqldb类用来访问本地sqlite3数据库。经过以上程序,在服务器中打开python web.py 1234,然后访问localhost:1234既可以访问到这个简单的网站,实现局域网内查看和控制设备的能力。# encoding: utf-8
import web
import os
import sqlite3
import time
import serial
from actuatorModule import execute
from web import form
# templete floder
render = web.template.render('templates/')
# url tables
urls = ('/', 'index',
'/manualcontroller', 'manualcontroller',
'/temperature', 'temperature',
'/humidity', 'humidity'
)
class index:
def GET(self):
return render.index()
class temperature:
def GET(self):
db1 = db()
rs = db1.execute('select * from temperature order by id desc limit 20')
return render.temperature(rs)
class humidity:
def GET(self):
db1 = db()
rs = db1.execute('select * from humidity order by id desc limit 20')
return render.humidity(rs)
class manualcontroller:
def GET(self):
return web.seeother('/')
def POST(self):
i = web.input()
print i.switcher1, i.servor1, i.led1
if i.servor1 != "":
if int(i.servor1)>=0 and int(i.servor1) <=180:
execute("d",i.servor1)
elif i.led1 != "":
if i.led1 !="":
execute("s",i.led1)
elif i.switcher1 != "":
if i.switcher1 == "1" or i.switcher1 == "0" :
execute("b",i.switcher1)
return web.seeother('/')
class db:
def __init__(self):
self.db = sqldb()
def insert(self,table,values):
return
def delete(self,table,index):
return
def update(self,table,index,values):
return
def select(self,table,index):
i = (table,index)
sql = 'select * from %s where id = %d'%(table,index)
self.db.cu.execute(sql)
rs = self.db.cu.fetchall()
self.db.conn.commit()
return rs
def execute(self,sql):
self.db.cu.execute(sql)
rs = self.db.cu.fetchall()
self.db.conn.commit()
return rs
class sqldb:
def __init__(self):
self.db = 'db.db'
if os.path.exists(self.db):
self.conn = sqlite3.connect(self.db)
self.cu = self.conn.cursor()
else:
self.conn = sqlite3.connect(self.db)
self.cu = self.conn.cursor()
self.cu.execute(
'create table sensors(id integer primary key autoincrement,date text,value text)')
self.cu.execute(
'insert into sensors values(null,\'2016-1-1 12:00:00\',\'32\')')
self.cu.execute(
'create table actuators(id integer primary key autoincrement,date text,value text)')
self.cu.execute(
'insert into actuators values(null,\'2016-1-1 12:00:02\',\'open AC ato 26\')')
self.conn.commit()
if __name__ == '__main__':
app = web.application(urls, globals())
app.run()采用上诉方法开启服务器之后,智能内网访问web服务,为了达到外网操作的能力,需要使用花生壳的动态IP的映射的服务。
:),棒,在网页中修改了字,在1602中就显示了对应的字 辛苦楼主了 花生棒
一般家庭使用的网络均是动态变更IP地址的,外网访问不方便。这里使用花生棒来保证外网访问内网的能力。需要在oray注册账号,并购买花生棒,绑定账号,指定内网IP和Port对外共享,之后就可以在外网使用内网服务了。
页:
[1]