有這樣一個想法,家里擺一個攝像頭作為安防用途或者監控小孩子、寵物等,
遠端的手機可以通過向攝像頭發送指令來控制攝像頭。
首先,這種想法已經有成熟的產品了,但是這樣的產品有缺陷:
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的圖片