【微信小程序控制硬件⑦ 进阶篇】动起来做一个微信小程序Mqtt协议控制智能硬件的框架,为心里全栈工程师梦想浇水!

微信小程序控制硬件第1篇 】 全网首发,借助 emq 消息服务器带你如何搭建微信小程序的mqtt服务器,轻松控制智能硬件!
微信小程序控制硬件第2篇 】 开始微信小程序之旅,导入小程序Mqtt客户端源码,实现简单的验证和通讯于服务器!
微信小程序控制硬件第3篇 】 从软件到硬件搭建一个微信小程序控制esp8266的项目,自定义通讯协议,为面试职位和比赛项目加分!
微信小程序控制硬件第4篇 】 深度剖析微信公众号配网 Airkiss 原理与过程,esp8266如何自定义回调参数给微信,实现绑定设备第一步!
微信小程序控制硬件第5篇 】理清接下来必须走的架构思想,学习下 JavaScript 的观察者模式,在微信小程序多页面同时接收到设备推送事件!
微信小程序控制硬件第6篇 】服务器如何集成七牛云存储SDK,把用户自定义设备图片存储在第三方服务器!
微信小程序控制硬件第7篇 】动起来做一个微信小程序Mqtt协议控制智能硬件的框架,为自己心里全栈工程师梦想浇水!!
微信小程序控制硬件第8篇 】微信小程序以 websocket 连接阿里云IOT物联网平台mqtt服务器,封装起来使用就是这么简单!
微信小程序控制硬件第9篇 】巧借阿里云物联网平台的免费连接,从微信小程序颜色采集控制 esp8266 输出七彩灯效果,中秋节来个直播如何?!
微信公众号控制硬件 第10篇 】如何在微信公众号网页实现连接mqtt服务器教程!!
微信小程序控制硬件 第11篇 】全网首发,微信小程序ble蓝牙控制esp32,实现无需网络也可以控制亮度开关。
微信小程序控制硬件 第12篇 】微信小程序蓝牙控制硬件应如何开发?为您全面解析微信小程序蓝牙API的使用。
微信小程序控制硬件 第13篇 】安信可B站直播学习总结,微信小程序MQTT远程控制ESP8266 NodeMCU,谈谈微信生态那些事。



一、前言;


           经过几趟折磨,过年后也就把这个框架弄好了,一直没时间写篇文章分享下!今天有空之余分享下心得!前面说了,要实现一个微信小程序控制自己的硬件(包括esp8266、esp32或者流行的树莓派)都需要一个服务器,而我前面几个分享给大家的是走私有服务器(非微信服务器)

           而前端开发与设备通过Mqtt协议连接的交互信息,无非是通过订阅和发送不同的主题实现控制。
           所以,大多情况下,这种思想是固定的!发送主题,订阅主题!前端拿到设备列表的各个主题去订阅,一个主题就是一个设备!发送的主题就是控制一个设备。所以,我就大胆地设计了这么一个框架,并且分享出来!


在这里插入图片描述


二、涉及的技术点;


  1. JavaScript观察者模式:因为各个页面发送和接收设备信息和主链接MQTT服务器是一个订阅观察的关系!由此我选用了onFire框架!
  2. weui框架使用:因为有些界面毕竟涉及到了美观,所以我就采用了微信开源的ui框架 ----- weui框架!
  3. MQTT协议的了解:这个协议是必须要熟悉的!MQTT协议已经作为物联网认知的一个协议标准了!
  4. 其他要了解的是微信小程序的基本开发流程,从下载开发工具和后台配置以及对微信小程序工程结构的了解!

在这里插入图片描述


三、框架的运行原理;


在这里插入图片描述

  • 再多的文字解释,也不够一个图片的归纳的好。上面是我归纳的;可以看到主要是分为三个模块:

  • 连接服务器主线程:实现与服务器的信息交互!不会直接和各个界面进行联系,只需要和封装库联系!

  • 封装库:作为服务器和用户交互的桥梁!内部封装好 主题订阅、发送消息和接收消息的工作。

  • 用户交互界面:这是一个很广的总结。交互界面有设备控制界面、设备列表界面或者其他分组界面等。但是还是只需要关心你的当前操作设备的订阅主题和发送主题,或者这个设备的图片和设备类型。


四、框架代码流程;


4.1 主线程;


            主线程是与mqtt服务器的连接,这个操作无非肯定是在app.js经行的!
            doConnect()函数涉及了连接、订阅主题以及和本地的封装库的逻辑!


doConnect: function() {
    var that = this;
    if (that.data.client && that.data.client.isConnected()) {
      console.log('不要重复连接');
      return
    }
    var client = new Client(this.globalData.server_domain, this.globalData.clientId());
    client.connect({
      userName: this.globalData.userName,
      password: this.globalData.password,
      useSSL: true,
      reconnect: true, //设置断线重连,默认是断线不重连
      cleanSession: true,
      keepAliveInterval: this.globalData.keepAliveInterval,
      onFailure: function(errorCode) {
        mDeviceClouds.notifyConnectEvent(false)
        //console.log("connect failed code:" + errorCode.errorCode)
        //console.log("connect failed message:" + errorCode.errorMessage)
      },
      onSuccess: function() {
        that.data.client = client
        client.onMessageArrived = function(msg) {
          if (typeof that.data.onMessageArrived === 'function') {
            return that.data.onMessageArrived(msg)
          }
          //  console.log("onMessageArrived topic:" + msg.destinationName)
          //  console.log("onMessageArrived payload:" + msg.payloadString)
          mDeviceClouds.notifyDeviceStatusEvent(msg.destinationName, msg.payloadString)
        }
        client.onConnectionLost = function(responseObject) {
          if (typeof that.data.onConnectionLost === 'function') {
            return that.data.onConnectionLost(responseObject)
          }
          if (responseObject.errorCode !== 0) {
            //console.log("onConnectionLost:" + responseObject.errorMessage);
          }
        }
        //console.log("connect success..")
        //连接成功mqtt服务器回调
        mDeviceClouds.notifyConnectEvent(true)
      }
    });
  },
  onLaunch: function() {

    //延迟链接,以防后面的收不到链接成功回调
    var that = this
    setTimeout(function() {
      that.doConnect();
    }, 800)

    // 订阅某个设备推送状态函数:参数 device对象
    mDeviceClouds.listenSubDeviceTopicEvent(true, function(device) {
      var client = that.data.client;
      if (client && client.isConnected()) {
        //console.log('订阅成功');
        return client.subscribe(device, {
          qos: 1
        });
      }
      //console.log('订阅失败');
    })
    // 发送消息给设备
    mDeviceClouds.listenWriteDeviceEvent(true, function(device, message, qos = 1, retained = false) {
      var client = that.data.client;
      if (client && client.isConnected()) {
        var message = new Message(message);
        message.destinationName = device;
        message.qos = qos;
        message.retained = retained;
        console.log('发送ok');
        return client.send(message);
      }
    })
  },

4.2 获取设备列表显示设备,以及订阅在线的设备;


            问题来了,从哪里获取设备列表,这个可以从自己的服务器,但是我的框架给出的是本地模拟的数据;这个可以根据小伙伴的业务来定了!可以看到下面,我的是很详细的,有设备名字、设备类型、设备图片、已经设备的订阅主题和发送主题!

//模拟数据
var localData = [{
  'alias': '书房灯',
  'type': 'light',
  'img': 'http://qiniu.xuhongv.com/device_list_light.png',
  'online': true,
  'deviceSubTopic': 'light/29e90c3d0/Sub',
  'devicePubTopic': 'light/29e90c3d0/Pub',
}, {
  'alias': '抽风机插座',
  'type': 'outlet',
  'img': 'http://qiniu.xuhongv.com/device_list_outlet.png',
  'online': true,
  'deviceSubTopic': 'outlet/59e90c3d6/Sub',
  'devicePubTopic': 'outlet/59e90c3d6/Pub',
}, {
  'alias': '卧室灯',
  'type': 'outlet',
  'img': 'http://qiniu.xuhongv.com/device_list_light.png',
  'online': false,
  'deviceSubTopic': 'light/m9e90c396/Sub',
  'devicePubTopic': 'outlet/m9e90c396/Pub',
}, ]

            拿到设备列表之后,自己做一个设备列表把!下面是我的设备列表页面代码!

            根据设备列表数据的是否在线而显示不同的颜色!加载不一样的文字显示!

<view class="page">
  <view wx:for="{{cloudsDevices}}" wx:key="this" data-index='{{index}}' wx:for-item='itemObj' 
   bindtap='jumpDeviceControl'>
    <view class='item-deviceList'>

      <!--设备图片-->
      <image src='{{itemObj.img}}' class='deviceIcon'></image>

      <!--如果设备在线设备名字颜色蓝色,否则就灰色-->
      <text wx:if='{{itemObj.online}}' class='deviceName'>{{itemObj.alias}}</text>
      <text wx:else class='deviceName' style='color:#a1afc9'>{{itemObj.alias}}</text>

      <!--如果设备离线则加载不一样的显示状态-->
      <text wx:if='{{itemObj.online}}' class="deviceStatusLine">在线</text>
      <text wx:else class="deviceStatusLine" style='color:#a1afc9'>离线</text>

      <!--如果设备离线则不显示箭头-->
      <image wx:if='{{itemObj.online}}' class='deviceInto' />

    </view>
    <view class='line'></view>
  </view>
  <view class="weui-footer weui-footer_fixed-bottom">
    <view class="weui-footer__links">
      <navigator url="https://github.com/xuhongv" class="weui-footer__link">WeUI+Mqtt+onfire</navigator>
    </view>
    <view class="weui-footer__text">Copyright ©半颗心脏 https://github.com/xuhongv</view>
  </view>

</view>

  • 效果如下:
    在这里插入图片描述

4.3 点击某设备如何实现携带此设备信息到控制界面;


            这个问题其实原理很简答的!点击某个设备,获取其索引!然后根据这个索引来从设备列表的中查找到这个设备,然后就可以把这个设备的某些信息去跳转到下一个设备了,比如设备的名字和类型,最主要的是设备的订阅主题,因为设备一直在接收此主题的消息。下面是点击一项设备时候触发的方法:

jumpDeviceControl: function(e) {
    //拿到当前点击设备的设备对象
    var device = this.data.devicesCloudsDatas["listData"][e.currentTarget.dataset.index];
    //设备是否在线?如果在线则可以跳转
    if (device.online)
      //判断设备类型
      switch (device.type) {
        case 'light':
         //携带设备订阅主题和名字跳转给下一个界面
          wx.navigateTo({
            url: "../deviceLight/deviceLight?devicePubTopic=" + device.devicePubTopic + "&deviceSubTopic=" + device.deviceSubTopic + "&alias=" + device.alias
          })
          break;
        case 'outlet':
           //携带设备订阅主题和名字跳转给下一个界面
          wx.navigateTo({
            url: "../deviceSocket/deviceSocket?devicePubTopic=" + device.devicePubTopic + "&deviceSubTopic=" + device.deviceSubTopic + "&alias=" + device.alias
          })
          break;
        default:
          break;
      }
  }

4.4 控制界面如何获取上个界面传过来的信息;


            首先你得明白,onLoad()方法里面的参数就是上个界面传来的!因此,我们拿到了参数之后,要向我们的本地的订阅中心订阅发来所有信息,判断是否当前设备的发来的;如下代码:

 callBackDeviceStatus: function (topic, payload) {
    //此处判断服务器的下发主题和此设备的主题是否一致!
    if (this.data.devicePubTopic === topic) {
      console.log("设备状态回调:" + payload);
      //这里处理同步ui工作的代码逻辑处理
    }
  },
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {

    console.log("拿到上个界面传来的设备信息:" + options.devicePubTopic);

    //根据设备名字,设置标题
    wx.setNavigationBarTitle({
      title: options.alias
    })
    this.setData({
      devicePubTopic: options.devicePubTopic,
      deviceSubTopic: options.deviceSubTopic
    })

    //设置监听函数
    mDeviceClouds.listenDeviceStatusEvent(true, this.callBackDeviceStatus);

    //控制设备,此函数任意地方调用!第一个参数是topic,第二个是payload
    //mDeviceClouds.notifyWriteDeviceEvent(options.deviceSubTopic, "hello world , i am from wechat");
  },

            既然我们拿到了设备的订阅主题,那么我们就可以做自己协议来控制了,比如点击开关灯以及控制亮度灯!看我下面的一个按键回调如何把定协议发送给设备:

 //按键触发
  onSwitch: function (e) {
    console.log("onSwitch success :" + e.detail.value);
    //同步数据
    if (e.detail.value)
      this.setData({
        lightValue: 100,
        valuePic: this.data.pathLightOpen
      })
    else this.setData({
      lightValue: 0,
      valuePic: this.data.pathLightOff
    })
    //开始构造json数据
    var jsonObj = new Object();
    jsonObj.change = "power";
    jsonObj.value = "" + e.detail.value + "";
    //开始发布消息
    //mDeviceClouds.notifyWriteDeviceEvent(this.data.deviceSubTopic, JSON.stringify(jsonObj));
  }

五、其他;


5.1 特性

  • 支持断线重连!重新订阅主题!
  • 拓展性强,与具体的通讯协议没有任何耦合!开发者可以根据自己业务来做协议!

5.2 如何修改信息;


  • 修改连接域名等连接信息!
    在这里插入图片描述

  • 修改模拟的设备列表数据,小伙伴也可以从自己的服务器获取(修改格式时候要对应在index.js做适配):
    在这里插入图片描述

  • 工程框架结构:
    在这里插入图片描述


六、下载;


  • 工程的读懂需要一定的微信小程序开发基础,请自备!

  • 框架下载(个人整理,收点小费):http://www.demodashi.com/demo/15147.html

展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 成长之路 设计师: Amelia_0503
应支付0元
点击重新获取
扫码支付

支付成功即可阅读