物联网-手机远程控制家里的摄像头(1)
有这样一个想法,家里摆一个摄像头作为安防用途或者监控小孩子、宠物等,
远端的手机可以通过向摄像头发送指令来控制摄像头。
首先,这种想法已经有成熟的产品了,但是这样的产品有缺陷:
1.没法自己DIY一些功能,出了BUG时只能等待厂家的固件
2.因为要用到服务商的云平台,可能因此每年产生几百块的服务费
3.平台无法复用,比如无法添加NAS功能
4.隐私泄露的问题
这样的产品的需求是:
1.低功耗,因为需要24小时运行
2.高清摄像,红外夜视(可选),容易看清贼的脸
3.稳定的代码
4.历史记录查看功能
5.较低的延迟
6.自动判断视野内是否有物体在动作(图像处理)
7.最好使用免费的云服务
根据上述的需求,目前产生了下述想法:
1.使用树莓派或者承载openwrt的路由器作为主体,顺带可以做NAS
2.使用邮箱作为云服务平台
3.采用高性价比的摄像头
这里具体来分析一下:
1.要打通手机和摄像头的通道,最简单的是手机和摄像头直连。最近几年独立的ip
越来越紧缺,我们从ISP拿到的ip很多已经是内网的IP,也就是说,无法直接连接
手机和摄像头。
下图是一种比较好的情况,服务器处在NAT里面,手机具有独立IP,这样,可以通过
反向连接的方式打通手机和服务器的通道,手机直接去连接NAT内部的服务器是
无法成功的,因为在这里一个ip对应好多机器(除非开了DMZ主机或者虚拟服务器)
但是这里考虑最坏的情况,手机和服务器都在NAT内部,无法互相连接。
这样,就需要外部的服务器来中转了。
于是,本人考虑了以下几种情况:
1.使用微信API
看了微信API的文档,得知如果需要使用这个API,需要自己搭建一个
服务器用于和微信服务器交互,虽然有免费的空间,但是速度慢是肯定的,
因为时延和稳定性的要求,加上成本的要求(如果买虚拟空间会增加成本),
这个方案暂时pass。
2.使用微博API
网上查得,微博似乎开放了私信API,但是又看到一些API的用户
吐槽微博随意关闭API,所以这个待定
3. 使用飞信API
因为官方没有公布API,使用私有的API会产生不稳定的现象,
而且也不见得支持图片的发送,所以暂时放弃
4.使用百度云API
百度云API可以存储资料,虽然通过旁敲侧击的方法可以用于通讯,
但是需要做专用的软件来支持这个功能。目前百度云API暂时用来
存储视频资料。
5.使用邮箱
目前互联网世界有数不尽的邮件服务商,不会出现后续无法用此方法的情况,
而且邮箱自古以来就是用来通讯的。虽然存在若干不方便的因素,
但是不影响使用,后续可以做APP解决。这里暂时使用邮箱来解决问题。
树莓派测试代码
因为要用到linux,所以暂时使用方便的Python。这里的demo是
使用邮箱来接收指令并且发送图片。
#!/usr/bin/python # -*- coding: utf-8 -*- #python2.7 mailtest.py from smtplib import SMTP from smtplib import SMTPRecipientsRefused from poplib import POP3 from time import sleep #for attach img from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from email.mime.image import MIMEImage import sys smtpserver = 'smtp.163.com' pop3server = 'pop.163.com' email_addr = 'usr@163.com' username = 'usr' password = 'IWantToFly' #https://docs.python.org/2/library/smtplib.html def send_mail(): mail_attach = '1.jpg' msg = MIMEMultipart() msg["To"] = '' msg["From"] = '' msg["Subject"] = 'MY_CMD:1' msg_text = MIMEText('<img src="cid:1.jpg">' , 'html') msg.attach(msg_text) fp = open(mail_attach, 'rb') img = MIMEImage(fp.read()) fp.close() img.add_header('Content-ID', mail_attach) msg.attach(img) send_svr = SMTP(smtpserver) #send_svr.set_debuglevel(1) #print send_svr.ehlo()[0] #服务器属性等 send_svr.login(username,password) try: errs = send_svr.sendmail(email_addr,email_addr,msg.as_string()) except SMTPRecipientsRefused: print 'server refused....' sys.exit(1) send_svr.quit() assert len(errs) == 0,errs print 'send end' #https://docs.python.org/2/library/poplib.html def recv_mail(): recv_svr = POP3(pop3server) recv_svr.user(username) recv_svr.pass_(password) #msg_cnt is the last mail index, mail index is range(1, msg_cnt) msg_cnt, mailbox_size = recv_svr.stat() for i in range(1, msg_cnt): try: #only list msg header to reduce size, use retr to retrive the whole body rsp,msg,siz = recv_svr.top(i, 0) #print msg for msg_one_entry in msg: if msg_one_entry.find('Subject:') == 0: #response to command here print msg_one_entry except: print '_______error' #recv_mail() send_mail()
这里有两个函数,用于接收的函数是用来接收指令的,用于发送的函数是用来发送本地的图片(后续改成用摄像头生成的图片)
当接收到的指令和某个预定义的指令匹配时,采用对应的action(比如连续发三张图片,或者发一个MP4)
开始的服务器地址和用户名密码是要自己填的。
下面显示一下效果:
发出去的(想象成你在手机上发了这个邮件):
收到的(想象成你在手机上收到了这个邮件):
( ⊙ o ⊙ ) 是一张doge的图片