搭建树莓派手机远程开门系统

 
【目标】
按下手机app中的按钮,寝室的门锁打开。

【基本原理】
Raspberry Pi 作为控制装置:其运行Linux系统,因此功能强大;提供GPIO接口,因此便于控制物理开门机构。
yeelink 平台作为云提供者:自己搭建web服务器成本高难度大,yeelink提供免费的物联网云服务,并开放API,可以用于编写手机app。

在yeelink 平台注册一个开关型传感器,平时其value为0。
RasPi 每5s 通过yeelink HTTP API 检查value 值,当检测到1时开门。
开发可以通过yeelink HTTP API操作value值的安卓app,实现手机远程开门。
 
【初次配置RasPi】
组装RasPi外壳。应当加装散热片。夏天时考虑加装散热风扇。
(查看CPU温度命令:cat /sys/class/thermal/thermal_zone0/temp)
 
将TF卡通过读卡器连接到Windows电脑,用 Win32DiskImager 烧录RasPi系统到TF卡。
RasPi系统镜像可以从官网下载。
如需恢复TF卡,可以烧录bootsector镜像。

配置视频输出:
在Windows上打开TF卡,找到config.txt,修改一下内容
hdmi_force_hotplug=1
hdmi_group=2
hdmi_mode=16
hdmi_drive=2
config_hdmi_boost=4
sdtv_mode=2
arm_freq=800

将TF卡,键盘,HDMI线,和其它需要的外设接入RasPi,打开电源。

初次开机进入半图形设置界面,选择扩展存储卡空间,修改pi用户密码,选择开机默认启用命令行,TimeZone设置为Asia,键盘设置为104-US,确认并自动重启。

配置自动连接WiFi:
前提确保无线网卡正常工作。

sudo nano /etc/wpa_supplicant/wpa_supplicant.conf
在文件末尾添加形如以下内容
network={
        ssid="名称"
        psk="密码"
}
保存退出。
 
sudo reboot
测试开机后能否自动连接到指定WiFi。

从启动输出或从路由器查看RasPi的ip地址,。
在Windows上使用putty,在安卓手机上使用ConnectBot,进行SSH连接。
在Windows上使用FileZilla,进行sftp连接,连接地址以sftp://开头。
从此可以不再使用独立显示器和键盘。

【定时关机】
sudo crontab -u root -e
添加如下内容
35 22 * * * /sbin/init 0 

【开机运行】
 sudo nano /etc/rc.local
添加以下内容
sudo nohup python -u /home/pi/unlockhandler.py >/home/pi/unlockhandler.log 2>&1 &

【下载安装依赖】 

sudo apt-get install python-dev

下载 RPi.GPIO-0.5.11.tar.gz 到/home/pi/

tar xvzf RPi.GPIO-0.5.11.tar.gz
cd RPi.GPIO-0.5.11
sudo python setup.py install

下载 requests-2.7.0.tar.gz 到/home/pi/
tar xvzf requests-2.7.0.tar.gz
cd requests-2.7.0
sudo python setup.py install

rm requests-2.7.0.tar.gz
rm  RPi.GPIO-0.5.11.tar.gz
sudo rm -rf requests-2.7.0
sudo rm -rf RPi.GPIO-0.5.11
 
【基于Python的GPIO】
四个GPIO针脚控制步进电机,三个GPIO针脚控制RGB三色LED灯。
 
图片
 
编写unlockhandler.py 

源代码:
import json
import requests   
import RPi.GPIO as GPIO  
import time 
 
GPIO.setmode(GPIO.BOARD)
 
led_R = 40
led_G = 38
led_B = 36
stepper_A = 37
stepper_B = 35
stepper_C = 33
stepper_D = 31
 
GPIO.setwarnings(False)
GPIO.setup(led_R, GPIO.OUT)
GPIO.setup(led_G, GPIO.OUT)
GPIO.setup(led_B, GPIO.OUT)
GPIO.setup(stepper_A, GPIO.OUT)
GPIO.setup(stepper_B, GPIO.OUT)
GPIO.setup(stepper_C, GPIO.OUT)
GPIO.setup(stepper_D, GPIO.OUT)
GPIO.setwarnings(True)
 
GPIO.output(led_R, 0)
GPIO.output(led_G, 0)
GPIO.output(led_B, 0)
GPIO.output(stepper_A, 0)  
GPIO.output(stepper_B, 0)
GPIO.output(stepper_C, 0)
GPIO.output(stepper_D, 0)
 
 
def setStep(w1, w2, w3, w4):
    GPIO.output(stepper_A, w1)
    GPIO.output(stepper_B, w2)
    GPIO.output(stepper_C, w3)
    GPIO.output(stepper_D, w4)
 
def forward(delay, steps):  
  for i in range(0, steps):
    setStep(1, 0, 1, 0)
    time.sleep(delay)
    setStep(0, 1, 1, 0)
    time.sleep(delay)
    setStep(0, 1, 0, 1)
    time.sleep(delay)
    setStep(1, 0, 0, 1)
    time.sleep(delay)
 
def backwards(delay, steps):  
  for i in range(0, steps):
    setStep(1, 0, 0, 1)
    time.sleep(delay)
    setStep(0, 1, 0, 1)
    time.sleep(delay)
    setStep(0, 1, 1, 0)
    time.sleep(delay)
    setStep(1, 0, 1, 0)
    time.sleep(delay)
 
  
apiurl = 'http://api.yeelink.net/v1.0/device/*****/sensor/*****/datapoints'  
apiheaders = {'U-ApiKey': '********************************'}  
 
payload={'value': 0}
rpost = requests.post(apiurl, headers=apiheaders, data=json.dumps(payload))
print time.strftime('%H:%M:%S'), 
print("Ready.") 
GPIO.output(led_R, 1)
time.sleep(0.5) 
GPIO.output(led_R, 0)
GPIO.output(led_G, 1)
time.sleep(0.5) 
GPIO.output(led_G, 0)
GPIO.output(led_B, 1)
time.sleep(0.5) 
GPIO.output(led_B, 0)
 
while True:    
  rget = requests.get(apiurl,headers=apiheaders)
  dic = json.loads(rget.text)
  #print time.strftime('%H:%M:%S'),
  
  if dic['value'] == 1: 
    print time.strftime('%H:%M:%S'),  
    print("Unlocking!")
    GPIO.output(led_R, 1)
 
    # unlock work flow 
    forward(0.01, 128)
    time.sleep(2)
    backwards(0.01, 128)
    setStep(0, 0, 0, 0)
 
    payload={'value': 0}
    rpost = requests.post(apiurl, headers=apiheaders, data=json.dumps(payload))
    print("Done.")
    GPIO.output(led_R, 0)
    time.sleep(1)
 
  else:  
    #print("Stand by.")
    GPIO.output(led_G, 1)
    time.sleep(0.2)  
    GPIO.output(led_G, 0)
    time.sleep(4.8)
   
简述:
用 requests 库操作HTTP请求,用 json 库处理返回的 json 数据。
刚运行时,配置好针脚,将value初始化为0,三灯闪烁。
每5s读取一次value值:如果是1则操作步进电机开门,然后将value置回0,过程中亮红灯;如果是0则闪绿灯。

【安卓app】
主要源代码:
 public class MainActivity extends ActionBarActivity {
 
    PostHandler handler = null;
    TextView textView = null;
    Button startButton = null;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        handler = new PostHandler();
        textView = (TextView) findViewById(R.id.textView);
        startButton = (Button) findViewById(R.id.startButton);
        startButton.setOnClickListener(new OCL());
 
    }
 
    private class OCL implements View.OnClickListener {
        public void onClick(View v) {
            PostThread pt = new PostThread();
            new Thread(pt).start();
        }
    }
 
    class PostHandler extends Handler {
        public PostHandler() {
        }
        public PostHandler(Looper L) {
            super(L);
        }
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            // 接收消息更新UI
            Integer statusCode = msg.what;
            String status = null;
 
            switch (statusCode){
                case 0: status = "未能发送指令,请检查网络!";break;
                case 200: status = "指令发送成功!";startButton.setEnabled(false);break;
                default: status = "错误的返回值:" + statusCode + " !";break;
            }
            textView.append("\n\n" + status);
        }
    }
 
    class PostThread implements Runnable {
        public void run() {
 
            HttpClient httpClient = null;
            HttpGet httpGet = null;
            HttpPost httpPost = null;
            HttpResponse response = null;
            Integer statusCode = 0;
 
            httpClient = new DefaultHttpClient();
            httpGet = new HttpGet("http://api.yeelink.net/v1.0/device/*****/sensor/*****/datapoints");
            httpPost = new HttpPost("http://api.yeelink.net/v1.0/device/*****/sensor/*****/datapoints");
            httpGet.addHeader("U-ApiKey", "***************************************");
            httpPost.addHeader("U-ApiKey", "******************************************");
            JSONObject obj = new JSONObject();
            try {
                obj.put("value", 1);
                httpPost.setEntity(new StringEntity(obj.toString()));
                response = httpClient.execute(httpPost);
                statusCode = response.getStatusLine().getStatusCode();
            } catch (Exception e) {
                e.printStackTrace();
            }
 
            // 网络线程发送消息
            Message msg = new Message();
            msg.what = statusCode;
            handler.sendMessage(msg);
        }
    }




posted @ 2015-06-13 15:11  杨乐达  阅读(1966)  评论(0编辑  收藏  举报