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


     
    【目标】
    按下手机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(" " + 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);
            }
        }




  • 相关阅读:
    DataGridView 复选框 操作大全
    ClickOnce 创建桌面快捷方式
    测量程序经过的时间
    C# Js 时间格式化问题
    MVC 漫长之路(一)
    SQL 查一年内的数据
    DataRow对象的RowState和DataRowVersion属性特点
    iOS打开百度地图、高德地图导航
    NSURLCache 和 NSCache 的区别
    MagicalRecord的使用(第三方库实现的数据库)
  • 原文地址:https://www.cnblogs.com/yangleda/p/4573546.html
Copyright © 2020-2023  润新知