使用微信+树莓派+Arduino+服务器构建智能家庭小助手
这次我将使用微信公众号、树莓派、Arduino和一台乞丐版配置的云服务器构建一个智能家庭小助手,用于协助我们对室内环境有一个较好的把控。如果你什么都没有可以参考以下清单先行购买物料(所有的必须物料下来,勉强三百多一些?):
1. 一块树莓派。版本随意,如果你资金比较充裕,可以购买最新型号的树莓派,毕竟最新的3B型号wifi模块信号更好,整体的处理速度更快。¥150300300
2. 一套Arduino开发套件。注意,是开发套件而不是Arduino这一块板子,我们需要开发套件中的其它元器件。¥150
3. 一台云服务器。如果你要用自己的电脑也可以,在校园网、小区、公司内记得先做内网穿透,不过一台乞丐版的服务器也没多少钱,能省很多事。¥0~10
4.微信公众号。如果你之前没申请过的话,貌似开通审核得等两三天?¥0
如果一切顺利,现在你的手上应该有一块树莓派、一套Arduino开发套件、一台云服务器、一个微信公众号。
微信公众号 -> 服务器
在此微信提供了一套公众号开发SDK,可以使用它,虽然官方提供开发文档已经非常成熟了,但还是觉得不够简洁。在此推荐大家使用itchatmp。
微信公众号:
进入微信公众平台在左下角找到“开发”-“基本配置”,
在该页面中填写相关信息,
服务器地址(URL):填写IP地址。但必须是公网IP或者已经做了内网穿透的IP地址,也可解析好域名后填入对应域名。
令牌(Token):用于微信公众号和服务器进行双向交互时的验证。
消息加解密密钥:随意。
所有内容都填写完毕后,别着急提交。进行下一步,
服务器:
登录服务器后,先检查是否安装了Python环境(可直接上Python3)。安装完成后,使用pip下载itchatmp,
1 | pip install itchatmp |
下载完成后,新建一个.py文件(此处以mp.py为例),在文件中写下,
1
2
3
4
5
6
7
8
9
10
11
12
13import itchatmp
itchatmp.update_config(itchatmp.WechatConfig(
# 填写上一步在微信公众号的配置内容
token='yourToken',
appId = 'yourAppId',
appSecret = 'yourAppSecret'))
def text_reply(msg):
return msg['Content']
itchatmp.run()
此时执行,(需要root权限)
1
python mp.py
看到下边这句话后就可以去微信公众号点击确认啦~
1
itchatmp started! press Ctrl+C to exit.
效果:
进入到对应的微信公众号中,你输入任何内容,它都会给你返回相同的内容。如果微信公众平台告诉你Token验证失效估计就是你的IP地址不对。
数据库
使用数据库是为了存储数据(可以使用txt文件来维护),在此为了简化手拼SQL易出错以及本项目并不需要进行多少性能优化的情况下,直接采用ORM(对象关系映射技术)。
PS:我们将采用sqlalchemy这个框架进行,在廖雪峰的博客上有较为细致的讲解,大家可以先自行研究一番到底是个什么东西。
这是定义好的硬件类,其实也就是硬件表,
1
2
3
4
5
6
7
8# 硬件表
class Hardware(Base):
__tablename__ = 'hardware'
id = Column(Integer, primary_key=True)
name = Column(String(64), nullable=False)
status = Column(Integer, nullable=False)
num = Column(Integer, nullable=False)
新建一个py文件(以test.py为例),在其中写下,
1
2
3
4
5
6
7
8
9
10
11from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, String, Integer
from sqlalchemy.orm import sessionmaker
# '数据库类型+数据库驱动名称://用户名:口令@机器地址:端口号/数据库名'
engine = create_engine('mysql+mysqldb://root:mimamima@localhost:3306/restful?charset=utf8')
Base = declarative_base()
Base.metadata.create_all(engine)
Session = sessionmaker(bind = engine)
session = Session()
到这一步为止,就完成了使用ORM进行MySQL数据库操作的铺垫。接下来,我们将进行数据库的增删改查方法的编写。
- 增加一个元器件:
1
2
3
4
5
6
7
8
9
10
11
12
13# 添加电子原件方法
# 原件name及针脚num需要配置
# 原件状态默认关闭
def addNewUnit(hardwareName, status, num):
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
unit = Hardware(
name = hardwareName,
status = status,
num = num)
session.add(unit)
session.commit() - 修改一个元器件的状态:
1
2
3
4
5
6
7
8
9
10
11
12# 执行write操作
def writeHardware(hardwarename, status, num):
unit = readHardware(hardwarename)
unit = session.query(Hardware).get(unit.id)
if unit:
unit.status = status
if 'Unit' in hardwarename:
unit.num = num;
session.add(unit)
session.commit()
return '操作成功'
return '操作失败,请联系管理员' - 读取一个元器件的状态:
1
2
3
4
5
6
7# 执行read操作
def readHardware(hardwarename):
Base.metadata.create_all(engine)
Session = sessionmaker(bind = engine)
session = Session()
unit = session.query(Hardware).filter_by(name=hardwarename).first()
return unit - 稍微做了点封装的update方法: 现在我们完成了test.py的编写,主要完成了使用ORM技术编写了操作数据库的各种方法。接下来,我们要使用微信公众号对数据库进行修改。
1
2
3
4
5
6
7# 电子原件执行read或write筛选方法
def updateStatusWithHardware(tableName, operatorStatus, hardwarename, status):
if tableName == 'hardware':
if operatorStatus == 1:
return writeHardware(hardwarename, status, 0)
else:
return readHardware(hardwarename)
微信公众号 -> 数据库
在这个环节中,我们要做到用户发送“开灯”、“关灯”、“开风扇”、“温度”等消息给公众号后,能够在数据库中看到状态被修改并且反馈。
简单的来概括一下要做的工作:首先要让服务器接收到公众号发送而来的消息;其次要对发送者进行筛选,不能谁都可以操作这套系统;接着匹配消息,执行不同的方法;最后给公众号反馈回消息。
服务器接收公众号发送的消息我们已经在第一步中完成了,现在要对接收到的消息体进行解析,根据userID来筛选谁能对这套系统进行操作。我的做法非常简单,用一个”pjhubs.txt”文件保存了能够操作这套系统的用户ID。每次接收到消息时,都先从消息体中取出fromUserName字段数据与txt文件中的数据进行比对,如果在txt文件中才允许接着进行操作。
1 | import itchatmp |
执行,
1 | python mp.py |
在微信公众号中发送“开灯”、“关灯”、“开风扇”、“温度”等指令都会对数据库进行操作。此时可以select对应表查看数据是否一致再进行下一步。
API
这是知乎上一些关于API的内容讲解。我们在此使用Flask轻量级的web框架进行API编写。主要是给树莓派操作数据库使用的。
通过pip安装好flask后,我们可以先尝试写一个最简单的restful格式的API:
1 | from flask import Flask |
此时我们去浏览器中输入ip地址或域名,即可看到“Get out!🙂”这句话。现在我们要接着编写几个资源访问路径以便树莓派访问。
1 | # 获取所有硬件信息(求快可以这么写) |
我们只需要起两个API服务即可满足要求。此时我们可以根据写好的API访问规则到浏览器中验证一番。
树莓派
树莓派是整套系统的灵魂所在,对上承载着数据库的更新,对下负担着Arduino的操作。当然,如果不考虑性能你可以直接用Arduino的wifi模组,直接对API发起请求。
树莓派首先要去在固定时间间隔内轮询特定API,根据API反馈回来的数据对固定串口发送特定字符,接收Arduino传递上来的数据,拼接API更新数据库。
serial是对树莓派上的串口进行操作库,urllib2是网络请求库,json是解析和发送JSON格式库。
1 | import serial |
我在此重新定义了一套操作流程,
a -> “开灯”
A -> “关灯”
b -> “开风扇”
B -> “关风扇”
因为受到Arduino本身性能的影响,如果你还给它发一长串的字符串比如“open light”等,那估计单单就解析并匹配,分时操作已经过了。😂。因此我才想重新定义一套ASCII码关系映射,并且限制树莓派每次轮询的时间为4秒一次,可根据用户所搭建的下位机硬件系统复杂适度增减轮询时间。
Arduino
Arduino要做的事情只有接收串口数据,解析串口数据,根据数据分别操作不同的硬件。Arduino用C写的,定义了一套规则,用起来非常顺手亲切。
1 |
|
联调
至此我们完成了全部的基础工作,在联调的过程中,当初我也发生了非常多的问题,这无法避免,稍不注意电路连错了以后就全盘皆输了,在此我只能祝大家好运,Arduino连接各个元器件的方式并没有展开,因为我相信大家的电路设计一定比我强!👍
在联调的过程中,你需要做的是,
- 运行restful.py,把整套API服务跑起来;
- 运行mp.py,让公众号和服务器打通;
- Arduino通过USB与树莓派相连后,树莓派再通电;
- 在公众号上发送指令,观察Arduino上元器件状态变化。
结果: