使用微信+树莓派+Arduino+服务器构建智能家庭小助手

前言

这是我去年的大创项目《一种基于微信的主动式家庭智能监测系统设计与实现》,因为时间关系,一直都没有好好的梳理一遍应该如何去复现它,最近时间较为充裕,我会较为仔细的描述清楚该项目的核心难点(其实并没有难点?)。当初报这个项目是为了学习一些硬件的简单相关知识,再结合一下前年(17年的项目要在16年年末申报)的社会热点问题,当时大家都比较热衷于“智能家庭”的概念。当时的小米“家庭智能”套件火的是一塌糊涂,甚至还出了贺岁版礼包(如果我没记错的话),再结合当时对自己的技术路线的一个定位,需要弥补一些关于硬件的知识,遂有了这个项目。

因为时间间隔的比较久远,不保证复现过程中100%正确,如果你有跟着走,出现了问题请务必告知,我们一起完善!大部分都是PythonArduino代码,建表SQL因为没法保证大家的物料跟我是一致的,而且大家也不一定会做的跟我完全一样,这块就保留了吧。当然,如果你喜欢论文严谨的格式,也可以到知网down下与本项目相关的渣作

物料准备

我将使用微信公众号、树莓派、Arduino和一台乞丐版配置的云服务器构建一个智能家庭小助手,用于协助我们对室内环境有一个较好的把控。如果你什么都没有可以参考以下清单先行购买物料(所有的必须物料下来,勉强三百多一些?):

  1. 一块树莓派。版本随意,如果你资金比较充裕,可以购买最新型号的树莓派,毕竟最新的3B型号wifi模块信号更好,整体的处理速度更快。¥150~300
  2. 一套Arduino开发套件。注意,是开发套件而不是Arduino这一块板子,我们需要开发套件中的其它元器件。¥150~300
  3. 一台云服务器。如果你要用自己的电脑也可以,在校园网、小区、公司内记得先做内网穿透,不过一台乞丐版的服务器也没多少钱,能省很多事。¥0~10
  4. 微信公众号 如果你之前没申请过的话,貌似开通审核得等两三天?¥0

信息配置

如果一切顺利,现在你的手上应该有一块树莓派、一套Arduino开发套件、一台云服务器、一个微信公众号。微信提供了一套公众号开发SDK,可以使用它,虽然官方提供开发文档已经非常成熟了,但还是觉得不够简洁。在此推荐大家使用itchatmp。

微信公众号: 进入微信公众平台在左下角找到“开发”-“基本配置”,

在该页面中填写相关信息,

  1. 服务器地址(URL):填写IP地址。但必须是公网IP或者已经做了内网穿透的IP地址,也可解析好域名后填入对应域名。
  2. 令牌(Token):用于微信公众号和服务器进行双向交互时的验证。
  3. 消息加解密密钥:随意。 所有内容都填写完毕后,别着急提交。进行下一步,

服务器

登录服务器后,先检查是否安装了Python环境(可直接上Python3)。安装完成后,使用pip下载itchatmp,

$ pip install itchatmp
复制代码

下载完成后,新建一个.py文件(此处以mp.py为例),在文件中写下,

import itchatmpitchatmp.update_config(itchatmp.WechatConfig(# 填写上一步在微信公众号的配置内容token='yourToken',appId = 'yourAppId',appSecret = 'yourAppSecret'))@itchatmp.msg_register(itchatmp.content.TEXT)def text_reply(msg):return msg['Content']itchatmp.run()
复制代码

此时执行,(需要root权限)

$ python mp.py
复制代码

看到下边这句话后就可以去微信公众号点击确认啦~

itchatmp started! press Ctrl+C to exit.
复制代码

效果: 进入到对应的微信公众号中,你输入任何内容,它都会给你返回相同的内容。如果微信公众平台告诉你Token验证失效估计就是你的IP地址不对。

数据库

使用数据库是为了存储数据(完全可以使用txt文件来维护),在此为了简化手拼SQL易出错以及本项目并不需要进行多少性能优化的情况下,直接采用ORM(对象关系映射技术)。 P.S.我将采用sqlalchemy这个框架进行,在廖雪峰的博客上有较为细致的讲解,大家可以先自行研究一番到底是个什么东西。

这是定义好的硬件类,其实也就是硬件表,

# 硬件表
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为例),在其中写下,

from 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. 增加一个元器件:
# 添加电子原件方法
# 原件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. 修改一个元器件的状态:
# 执行write操作
def writeHardware(hardwarename, status, num):unit = readHardware(hardwarename)unit = session.query(Hardware).get(unit.id)if unit:unit.status = statusif 'Unit' in hardwarename:unit.num = num;session.add(unit)session.commit()return '操作成功'return '操作失败,请联系管理员'
复制代码
  1. 读取一个元器件的状态:
# 执行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
复制代码
  1. 稍微做了点封装的update方法:
#  电子原件执行read或write筛选方法
def updateStatusWithHardware(tableName, operatorStatus, hardwarename, status):if tableName == 'hardware':if operatorStatus == 1:return writeHardware(hardwarename, status, 0)else:return readHardware(hardwarename)
复制代码

现在我们完成了test.py的编写,主要完成了使用ORM技术编写了操作数据库的各种方法。接下来,我们要使用微信公众号对数据库进行修改。

上位机配置

在这个环节中,我们要做到用户发送“开灯”、“关灯”、“开风扇”、“温度”等消息给公众号后,能够在数据库中看到状态被修改并且反馈。

简单的来概括一下要做的工作:首先要让服务器接收到公众号发送而来的消息;其次要对发送者进行筛选,不能谁都可以操作这套系统;接着匹配消息,执行不同的方法;最后给公众号反馈回消息。

服务器接收公众号发送的消息我们已经在第一步中完成了,现在要对接收到的消息体进行解析,根据userID来筛选谁能对这套系统进行操作。我的做法非常简单,用一个"pjhubs.txt"文件保存了能够操作这套系统的用户ID。每次接收到消息时,都先从消息体中取出fromUserName字段数据与txt文件中的数据进行比对,如果在txt文件中才允许接着进行操作。

import itchatmp
import test# 配置微信公众号信息
itchatmp.update_config(itchatmp.WechatConfig(token='你的token',appId = '你的appId',appSecret = '你的appSecret'))# 接收用户消息
@itchatmp.msg_register(itchatmp.content.TEXT)
def text_reply(msg):toUserName = msg['FromUserName']content = msg['Content']isContain = 0# pjhubs.txt为有权限的用户列表f = open("pjhubs.txt","r")lines = f.readlines()for line in lines:if line[:-1] == toUserName:isContain = 1;   if isContain == 0:return '该系统并未对您开放,请联系PJ进行配置'else:if content == '添加':# test.addNewUnit('tempUnit', 1, 2)return '操作成功!'elif content == '开灯':return test.updateStatusWithHardware('hardware', 1, 'redLED', 1)elif content == '关灯':return test.updateStatusWithHardware('hardware', 1, 'redLED', 0)elif content == '温度':unit = test.updateStatusWithHardware('hardware', 0, 'tempUnit', 1)returnString = '当前温度为:' + str(unit.num) + '°'return returnStringelif content == '开风扇':return test.updateStatusWithHardware('hardware', 1, 'tempUnit', 1)elif content == '关风扇':return test.updateStatusWithHardware('hardware', 1, 'tempUnit', 0)# 新用户关注公众号时
@itchatmp.msg_register(itchatmp.content.EVENT)
def user_management(event):if(event['Event']=='subscribe'):return u'欢迎来到PJHubs,如果你想试用室内环境智能监测系统,请联系PJ'
itchatmp.run()
复制代码

执行,

$ python mp.py
复制代码

在微信公众号中发送“开灯”、“关灯”、“开风扇”、“温度”等指令都会对数据库进行操作。此时可以select对应表查看数据是否一致再进行下一步。

API编写

这是知乎上一些关于API的内容讲解。我们在此使用Flask轻量级的web框架进行API编写。主要是给树莓派操作数据库使用的。 通过pip安装好flask后,我们可以先尝试写一个最简单的restful格式的API:

from flask import Flask
from flask_restful import Resource, Api
from flask import jsonify, request
from flask import abort
from flask import make_response
import testapp = Flask(__name__)
api = Api(app)@app.route('/')
def index():return 'Get out!?'if __name__ == '__main__':app.run(host='0.0.0.0',debug=True)
复制代码

此时我们去浏览器中输入ip地址或域名,即可看到“Get out!?”这句话。现在我们要接着编写几个资源访问路径以便树莓派访问。

# 获取所有硬件信息(求快可以这么写)
@app.route('/dachuang/api/v1/allHardware')
def get_allHardware():LED = test.readHardware('redLED')UNIT= test.readHardware('tempUnit')LEDres = { 'id' : LED.id,'name' : LED.name,'status' : LED.status,'num' : LED.num }UNITres = { 'id' : UNIT.id,'name' : UNIT.name,'status' : UNIT.status,'num' : UNIT.num }return jsonify([LEDres, UNITres])# 更新固定元器件(求快用了GET,最好是POST)
@app.route('/dachuang/api/v1/updateHardware', methods=['GET'])
def get_updateHardware():hardwarename = request.args.get('hardwarename')status = request.args.get('status')num = request.args.get('num')if status == '3':unit = test.readHardware(hardwarename)test.writeHardware(hardwarename, unit.status, num)else:test.writeHardware(hardwarename, unit.status, num)return jsonify({'code' : '1'})
复制代码

我们只需要起两个API服务即可满足要求。此时我们可以根据写好的API访问规则到浏览器中验证一番。

下位机配置——树莓派

树莓派是整套系统的灵魂所在,对上承载着数据库的更新,对下负担着Arduino的操作。当然,如果不考虑性能你可以直接用Arduino的wifi模组,直接对API发起请求。

树莓派首先要去在固定时间间隔内轮询特定API,根据API反馈回来的数据对固定串口发送特定字符,接收Arduino传递上来的数据,拼接API更新数据库。

serial是对树莓派上的串口进行操作库,urllib2是网络请求库,json是解析和发送JSON格式库。

import serial
import urllib2
import jsonhostname = 'http://你的地址/dachuang/api/v1/allHardware'
# /dev/ttyACM0 是树莓派上编号为0的USB口(可以在/dev目录下通过观察拔插对应的USB口找到对应的编号)
ser = serial.Serial('/dev/ttyACM0', 9600, timeout = 4)while 1:r = urllib2.Request(hostname)r = urllib2.urlopen(r)res = r.read()result = json.loads(res)print resultsend = ''# 通过json库解析完后的数据就是字典if result[0]['status'] == 1:send += 'a'else:send += 'A'if result[1]['status'] == 1:send += 'b'else:send += 'B'# 从下位机Arduino上读取到的数据拼接URL发送回服务器,更新数据库ser.write(send)response = ser.readall()if '' != response:response = response[0:2]ret = urllib2.Request("http://你的地址/dachuang/api/v1/updateHardware?hardwarename=tempUnit&status=3" + '&num=' + response)ret = urllib2.urlopen(ret)
复制代码

我在此重新定义了一套操作流程, a -> “开灯” A -> “关灯” b -> “开风扇” B -> “关风扇” 因为受到Arduino本身性能的影响,如果你还给它发一长串的字符串比如“open light”等,那估计单单就解析并匹配,分时操作已经过了。?。因此我才想重新定义一套ASCII码关系映射,并且限制树莓派每次轮询的时间为4秒一次,可根据用户所搭建的下位机硬件系统复杂适度增减轮询时间。

下位机配置——Arduino

Arduino要做的事情只有接收串口数据,解析串口数据,根据数据分别操作不同的硬件。Arduino用C写的,定义了一套规则,用起来非常顺手亲切。

#define yellowLED 13
#define REDled 12
#define Buzzer 8
#define fanPin 2void setup()  {Serial.begin(9600); // 9600 bpspinMode(yellowLED, OUTPUT);pinMode(Buzzer,OUTPUT);pinMode(REDled,OUTPUT);pinMode(fanPin,OUTPUT);
}
void loop() {//读取A0口的电压值,温度传感器所在串口int n = analogRead(A0);    //使用浮点数存储温度数据,温度数据由电>压值换算得到float vol = n * (5.0 / 1023.0*100);   if ( Serial.available() ) {// 向串口写入温度Serial.println(vol);// 读取树莓派写入串口的数据int res = Serial.read();// 根据ASCII码执行不同硬件操作函数if (res == 97) {digitalWrite(yellowLED, HIGH);}if (res == 65){digitalWrite(yellowLED, LOW);}if (res == 98) {digitalWrite(fanPin, HIGH);}if (res == 66) {digitalWrite(fanPin, LOW);}}// 超过30°后开启高温预警,蜂鸣器奏响和风扇打开if (vol > 30) {    buzzerBegin();}
}// 蜂鸣器响铃
void buzzerBegin() {digitalWrite(fanPin, HIGH);digitalWrite(REDled, HIGH);//频率从200HZ 增加到800HZ,模拟警报声for(int i=200;i<=800;i++) {tone(Buzzer,i);delay(5);}delay(100);for(int i=800;i>=200;i--) {tone(Buzzer,i);delay(5);}digitalWrite(REDled, LOW);digitalWrite(fanPin, LOW);
}
复制代码

上下位机联调

至此我们完成了全部的基础工作,在联调的过程中,当初我也发生了非常多的问题,这无法避免,稍不注意电路连错了以后就全盘皆输了,在此我只能祝大家好运,Arduino连接各个元器件的方式并没有展开,因为我相信大家的电路设计一定比我强!?

在联调的过程中,你需要做的是,

  1. 运行restful.py,把整套API服务跑起来;
  2. 运行mp.py,让公众号和服务器打通;
  3. Arduino通过USB与树莓派相连后,树莓派再通电;
  4. 在公众号上发送指令,观察Arduino上元器件状态变化。

结果:

github地址:github.com/windstormey…

使用微信+树莓派+Arduino+服务器构建你的看门狗相关推荐

  1. uplay服务器未响应,《看门狗:军团》存在崩溃丢失存档BUG 育碧正在修复

    原标题:<看门狗:军团>存在崩溃丢失存档BUG 育碧正在修复 <看门狗:军团>的部分玩家们近日在游戏中遇到了一个十分恼人的问题--在进行游戏时,有时会遇到游戏未响应或崩溃的问题 ...

  2. linux看门狗树莓派,给树莓派安装看门狗

    你还在担心树莓派死机吗?给他装个看门狗吧! 什么是看门狗程序? 看门狗程序就是一个健康监控程序,每间隔一定时间(默认10秒)检查一次是否在设定的健康工作范围内,如果超过即启动硬件复位程序,让设备重新启 ...

  3. linux看门狗设备,基于Linux构建无人值守系统(看门狗)

    基于Linux构建无人值守系统(看门狗) 在各种嵌入式设备soc中基本都提供了看门狗,在很长一段时间里我对看门狗的理解就是"关掉它,不然它会找麻烦".但是当某种需求存在的时候,它又 ...

  4. Arduino Ethernet构建简易服务器

    Arduino Ethernet构建简易服务器 首先先介绍一下用到的器件: Ethernet扩展板 接下来,我们将使用Arduino和Ethernet扩展板作为Web服务器,通过浏览器在局域网内访问该 ...

  5. 阿里云进阶课程三——基于云服务器构建微信公众号管理系统

    基于阿里云服务器构建微信公众号管理系统 准备工作 阿里云服务器镜像配置 FileZilla和终端工具安装 下载微擎压缩包 微擎的安装和配置 在云服务器上配置微擎文件 设置数据库信息 云服务器上安装微擎 ...

  6. 基于 树莓派4 + STM32H7 构建支持云端应用的嵌入式系统平台 【一】

    基于 树莓派4 + STM32H7 构建支持云端应用的嵌入式系统平台 [一] 一. 想法概述 1. 想法由来 2. 系统架构 3. 系统选型 4. 开发语言 5. 涉及到的框架 6. 开发工具 7. ...

  7. arduino服务器_如何使用Arduino检查Web服务器的响应状态

    arduino服务器 by Harshita Arora 通过Harshita Arora 如何使用Arduino检查Web服务器的响应状态 (How to use Arduino to check ...

  8. [读书笔记]从物联到万联——Node.js与树莓派万维物联网构建实战

    前言 本文是"从物联到万联,Node.js与树莓派万维物联网构建实战"一书的读书笔记,该书翻译自"Building the Web of Things with exam ...

  9. 微信支付HTTPS服务器证书验证(PHP)

    PHP代码验证是否包含CA证书 如果无法通过验证,请点击连接查看官方操作,安装相应的ca证书即可 # test_wechat_ca.php <?php $data = array('mch_id ...

最新文章

  1. 算法练习day12——190331(哈希函数、哈希表、布隆过滤器、一致性哈希)
  2. (转) Spring 3 报org.aopalliance.intercept.MethodInterceptor问题解决方法
  3. poj 2484 A Funny Game
  4. 实用分享-Visual Studio图像查看插件(Image Watch)
  5. 【vivado】PL通过axi_hp接口控制PS的DDR
  6. 关于Bom下标准模式和混杂模式!
  7. spring cloud微服务分布式云架构简介
  8. python判断是不是整数_在Python中确定值是否为整数
  9. Android开机启动广播
  10. 李雅普诺夫稳定性定理
  11. 视频剪辑好帮手——pr软件学习(一)
  12. Python数据预处理--Gensim构建语料词典
  13. Win7通过CMD命令开启无线热点
  14. SQL 的一点简单的面试题求助
  15. 大学计算机实验报告虚拟机,1虚拟机安装和使用实验报告书
  16. 判断质数和合数的java_质数与合数知识点总结(质数和合数的知识点)
  17. byte转16进制字符串<——>16进制转byte
  18. 简明图解冯·诺依曼计算机体系
  19. [面试] lcy - 箴言
  20. 【含源码】用python做游戏有多简单好玩

热门文章

  1. oracle 00600 kccpb,ora-00600 [kccpb_sanity_check_2] 错误处理
  2. hrbust 2155 钱多多【水题】
  3. 一文看懂推荐系统:物品冷启05:流量调控
  4. 多人使用服务器,如何开个人账户?以及 个人账户如何操作服务器?
  5. 不能通过“www.baidu.com”访问百度解决方法
  6. *POJ1830 高斯消元
  7. 各种可执行文件的打包教程,让你的可执行文件美观起来(打包成一个文件,自定义图标)!!!
  8. matlab的讲稿ppt,Matlab初步(讲稿200508)之一_Matlab讲解_doc_大学课件预览_高等教育资讯网...
  9. VA虚拟应用匠心独妙,细节的精彩
  10. LeetCode-Python-1276. 不浪费原料的汉堡制作方案(鸡兔同笼 + 数学)