物联网实践: 树莓派+dht11+html5 实现远程温湿度查看

(转载请注明来源:cnblogs coder-fang)

  1. 开发说明:python开发websocket服务与树莓派GPIO控制,html做为前端展示,这里使用uni-app UI框架。
  2. 服务及架构图示:
  3. websocket服务代码:
    from websocket_server import WebsocketServer
    import mymqtt
    import time,json
    class WebSock:
        def __init__(self,port):
            self.server = WebsocketServer(port, host='0.0.0.0')
            self.server.set_fn_new_client(self.new_client)
            self.server.set_fn_message_received(self.recv_fromclient)
            self.server.set_fn_client_left(self.client_left)
            self.clients=[]
            self.mqtt = mymqtt.MyMqtt(self.on_mqttconnect,self.on_mqttdisconnect,self.on_mqttmessage)
            
            self.status={"cmd":"gettemp","temp":25,"humi":33,"timespan":time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) }
    
        def on_mqttconnect(self,client, userdata, flags, rc):
            print("Conned broker with result code: " + str(rc))
        def on_mqttdisconnect(self,client, userdata, flags, rc):
            print("DisConned broker with result code: " + str(rc))
    
        def on_mqttmessage(self,client, userdata, msg):                        
            if msg.topic == "dev/up/temp":
                newmsg = str(msg.payload, encoding="utf-8")
                self.status = json.loads(newmsg)
                self.server.send_message_to_all(json.dumps(self.status))
    
    
        def new_client(self,client, server):        
            self.clients.append(client)
            print("newclient:"+str(len(self.clients)))        
    
        def recv_fromclient(self,client, server, message):
            print("getsockreq:"+message)
            if(message =='gettemp'):            
                self.mqtt.Pub('dev/get/temp',"")
    
        def client_left(self,client, server):
            self.clients.remove(client)
            print("client left:" +str(len(self.clients)))
        def Run(self):
            self.mqtt.Start("dev/up/temp")
            self.server.run_forever()
        def Stop(self):
            self.mqtt.Stop()
            self.server.shutdown()
    View Code
  4. 树莓派dht11 GPIO代码:
    import RPi.GPIO as GPIO
    import time
    
    class DHT11():
        def __init__(self,pin):
            self.channel=pin        
            GPIO.setmode(GPIO.BCM)        #以BCM编码格式        
            time.sleep(1)            #时延一秒        
            
        def GetTemp(self):
            try:
                data=[]
                j=0
                GPIO.setup(self.channel, GPIO.OUT)
                GPIO.output(self.channel, GPIO.LOW)
                time.sleep(0.02)        #给信号提示传感器开始工作
                GPIO.output(self.channel, GPIO.HIGH)        
                GPIO.setup(self.channel, GPIO.IN)    
                while GPIO.input(self.channel) == GPIO.HIGH:
                    continue     
                while GPIO.input(self.channel) == GPIO.LOW:
                    continue        
                while GPIO.input(self.channel) == GPIO.HIGH:
                    continue
                
                while j < 40:
                    k = 0
                    while GPIO.input(self.channel) == GPIO.LOW:
                        continue            
                    while GPIO.input(self.channel) == GPIO.HIGH:
                        k += 1
                        if k > 100:
                            break            
                    if k < 12:
                        data.append(0)
                    else:
                        data.append(1)
                
                    j += 1        
                
                        
                humidity_bit = data[0:8]        #分组
                humidity_point_bit = data[8:16]
                temperature_bit = data[16:24]
                temperature_point_bit = data[24:32]
                check_bit = data[32:40]
                
                humidity = 0
                humidity_point = 0
                temperature = 0
                temperature_point = 0
                check = 0
                
                for i in range(8):
                    humidity += humidity_bit[i] * 2 ** (7 - i)                #转换成十进制数据
                    humidity_point += humidity_point_bit[i] * 2 ** (7 - i)
                    temperature += temperature_bit[i] * 2 ** (7 - i)
                    temperature_point += temperature_point_bit[i] * 2 ** (7 - i)
                    check += check_bit[i] * 2 ** (7 - i)
                
                tmp = humidity + humidity_point + temperature + temperature_point        #十进制的数据相加
                
                if check == tmp:                                #数据校验,相等则输出
                    print("temperature : "+str(temperature)+", humidity : " + str(humidity))
                    return True,temperature,humidity
                else:                                        #错误输出错误信息,和校验数据
                    print("wrong")
                    print("temperature : "+ str(temperature)+", humidity : " + str(humidity)+
                     " check : "+ str(check)+ " tmp : "+ str(tmp))
                    return False,-20,0
            except:
                    return False,-20,0
    
        def Cleanup(self):
            GPIO.cleanup(self.channel)
    View Code
  5. 树莓派mqtt客户代码:
    import mymqtt,time,random,json
    from clients.dht11 import DHT11
    class DevCtrl:
        def __init__(self):        
            self.mqtt = mymqtt.MyMqtt(self.on_mqttconnect,self.on_mqttdisconnect,self.on_mqttmessage)
            self.dht11 = DHT11(4)
    
        def on_mqttconnect(self,client, userdata, flags, rc):
            print("Conned broker with result code: " + str(rc))
        def on_mqttdisconnect(self,client, userdata, flags, rc):
            print("DisConned broker with result code: " + str(rc))
    
        def on_mqttmessage(self,client, userdata, msg):        
            if(msg.topic == "dev/get/temp"):
                print("gettemp reques")
                ret,temp,humi = self.dht11.GetTemp()
                status={"cmd":"gettemp","temp":temp,"humi":humi,"timespan":time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) }
                self.mqtt.Pub("dev/up/temp",json.dumps( status))
    
    
        def Run(self):
            self.mqtt.Start("dev/get/temp",0,True)  
            
                
        def Stop(self):
            self.dht11.Cleanup()
            self.mqtt.Stop(True)
            
    View Code
  6. UI代码:
    <template>
        <view class="content ">
            <view class=" uni-flex uni-row ">
    
                <text>上次更新时间:{{updatetext}}</text>
                <button @click="getData()" :disabled="isloading" style="height: 70%;margin: 10rpx;padding: 0rpx;" type="primary"
                 :loading="isloading" size="mini">刷新</button>
    
    
            </view>
            <view class="qiun-charts ">
                <canvas canvas-id="canvasGauge" id="canvasGauge" class="charts"></canvas>
            </view>
    
            <view class="qiun-charts ">
                <canvas canvas-id="canvasGaugeshidu" id="canvasGaugeshidu" class="charts"></canvas>
            </view>
            <Prompt title="输入设备密码" :visible.sync="promptVisible" placeholder="输入密码" @confirm="clickPromptConfirm" mainColor="#e74a39">
                <!-- 这里放入slot内容-->
    
            </Prompt>
        </view>
    </template>
    
    <script>
        import uCharts from '@/components/u-charts/u-charts/u-charts.js';
        import Prompt from '@/components/zz-prompt/index.vue'
        var _self;
        var canvaGauge = null;
    
        export default {
            components: {
                Prompt
            },
            data() {
                return {
                    cWidth: '',
                    cHeight: '',
                    updatetext: '',
                    isloading: true,
                    pixelRatio: 1,
                    gaugeWidth: 15,
                    IsOpen: false,
                    promptVisible: true
                }
            },
    
    
    
            onLoad() {
                _self = this;
                this.cWidth = uni.upx2px(750);
                this.cHeight = uni.upx2px(500);
                //this.getServerData();
                uni.connectSocket({
                    url: 'ws://192.168.3.71:40000',
    
                    fail: () => {
                        console.log("disconnected sock");
                        uni.showModal({
                            content: 'Can not connect web server',
                            showCancel: false
                        });
                    }
                });
                uni.onSocketOpen(function() {
                    console.log("WebSock opened");
                    _self.IsOpen = true;
                });
    
                uni.onSocketClose(function(res) {
                    console.log('WebSocket 已关闭!');
                    _self.IsOpen = false;
                });
                uni.onSocketError(function(res) {
                    uni.showModal({
                        content: 'Can not connect web server',
                        showCancel: false
                    });
                    _self.IsOpen = false;
                });
                uni.onSocketMessage(function(res) {
                    console.log("recvmsg:" + res.data);
                    var ret = JSON.parse(res.data);
                    if (ret.cmd == "gettemp")
                    {
                        _self.DrawData(ret.temp, ret.humi)
                        _self.updatetext = ret.timespan
                    }
                        
    
                });
            },
            methods: {
                clickPromptConfirm(val) {
    
                    if (val == "123123") {
                        this.promptVisible = false;
                        _self.getData();
                        _self.isloading = true
                    } else {
                        uni.showModal({
                            content: '密码不正确',
                            showCancel: false
                        });
                    }
                },
                getData() {
                    _self = this;
                    _self.isloading = true;
                    uni.sendSocketMessage({
                        data: "gettemp"
                    });
                    setTimeout(() => {
                        _self.isloading = false;
                    }, 3000)
    
                },
                DrawData(temp, humi) {
                    let Gauge = {
                        categories: [],
                        series: []
                    };
                    //这里我后台返回的是数组,所以用等于,如果您后台返回的是单条数据,需要push进去
                    Gauge.categories = [{
                        "value": 0.43,
                        "color": "#1890ff"
                    }, {
                        "value": 0.56,
                        "color": "#2fc25b"
                    }, {
                        "value": 1,
                        "color": "#f04864"
                    }];
                    Gauge.series = [{
                        "name": "温度",
                        "data": ((temp) / 100 + 0.2) / 0.8,
                        "value": temp
                    }];
    
                    let Gaugeshidu = {
                        categories: [],
                        series: []
                    };
                    //这里我后台返回的是数组,所以用等于,如果您后台返回的是单条数据,需要push进去
                    Gaugeshidu.categories = [{
                        "value": 0.45,
                        "color": "#1890ff"
                    }, {
                        "value": 0.75,
                        "color": "#2fc25b"
                    }, {
                        "value": 1,
                        "color": "#f04864"
                    }];
                    Gaugeshidu.series = [{
                        "name": "湿度",
                        "data": humi / 100
                    }];
    
                    _self.showGauge("canvasGauge", Gauge, Gauge.series[0].value+"°C", -20, 60, 8);
                    _self.showGauge("canvasGaugeshidu", Gaugeshidu, humi+"%");
                },
                showGauge(canvasId, chartData, name, start = 0, end = 100, step = 10) {
                    canvaGauge = new uCharts({
                        $this: _self,
                        canvasId: canvasId,
                        type: 'gauge',
                        fontSize: 11,
                        legend: false,
                        title: {
                            name: name,
                            color: chartData.categories[1].color,
                            fontSize: 25 * _self.pixelRatio,
                            offsetY: 50 * _self.pixelRatio, //新增参数,自定义调整Y轴文案距离
                        },
                        subtitle: {
                            name: chartData.series[0].name,
                            color: '#666666',
                            fontSize: 15 * _self.pixelRatio,
                            offsetY: -50 * _self.pixelRatio, //新增参数,自定义调整Y轴文案距离
                        },
                        extra: {
                            gauge: {
                                type: 'default',
                                width: _self.gaugeWidth * _self.pixelRatio, //仪表盘背景的宽度
                                startAngle: 0.75,
                                endAngle: 0.25,
                                startNumber: start,
                                endNumber: end,
                                splitLine: {
                                    fixRadius: 0,
                                    splitNumber: step,
                                    width: _self.gaugeWidth * _self.pixelRatio, //仪表盘背景的宽度
                                    color: '#FFFFFF',
                                    childNumber: 5,
                                    childWidth: _self.gaugeWidth * 0.2 * _self.pixelRatio, //仪表盘背景的宽度
                                },
                                pointer: {
                                    width: _self.gaugeWidth * 0.8 * _self.pixelRatio, //指针宽度
                                    color: 'auto'
                                }
                            }
                        },
                        background: '#FFFFFF',
                        pixelRatio: _self.pixelRatio,
                        categories: chartData.categories,
                        series: chartData.series,
                        animation: true,
                        width: _self.cWidth * _self.pixelRatio,
                        height: _self.cHeight * _self.pixelRatio,
                        dataLabel: true,
                    });
    
                }
            }
        }
    </script>
    
    <style>
        /*样式的width和height一定要与定义的cWidth和cHeight相对应*/
        .qiun-charts {
            width: 750upx;
            height: 500upx;
            background-color: #FFFFFF;
        }
    
        .charts {
            width: 750upx;
            height: 500upx;
            background-color: #FFFFFF;
        }
    
        .content {
            align-content: center;
            -webkit-box-align: center;
            margin-left: 50rpx;
        }
    
        .fixheader {
            align-items: center;
            z-index: 9000;
            background-color: transparent;
            position: fixed;
            width: 100%;
            height: auto;
            overflow-y: auto;
        }
    </style>
    View Code
  7. 手机远程访问效果图:

猜你喜欢

转载自www.cnblogs.com/coder-fang/p/12190601.html
今日推荐