微信小程序连接物联网(三):微信小程序远程遥控宿舍开门 基于NodeMCU通过MQTT协议连接阿里云物联网平台

索引

这是用微信小程序遥控开门的系列文章,具体微信小程序连接物联网的代码在第三章提及。

微信小程序连接物联网(一):初始化ESP8266 NodeMCU
微信小程序连接物联网(二):NodeMCU Lua学习笔记
微信小程序连接物联网(三):微信小程序远程遥控宿舍开门 基于NodeMCU通过MQTT协议连接阿里云物联网平台

微信小程序远程遥控宿舍开门

  • 索引
  • 前言
    • 整个制作的耗材成本
    • 源码下载地址
    • 思路
  • 1. 使用MQTT.fx客户端工具测试
  • 2. Nodemcu连接阿里云物联网
  • 3. 微信小程序连接物联网
  • 4. 阿里云物联网M2M规则转发
  • 完成的样子

前言

折腾宿舍远程开门的这两周里碰壁不少,还好功能实现了。我想还有很多和我有同一想法的人。所以记录过程下来供参考少走弯路吧。我不是电子专业的学生,且这个Nodemcu也没涉及到底层知识,文中有错误的地方欢迎指正。

整个制作的耗材成本

  1. Esp8266 NodeMCU Lua芯片(30元)
  2. MG90S舵机(12元)
  3. 迷你充电宝(6元)
  4. USB数据线

源码下载地址

收到很多做毕设的小伙伴私信,这里补上完整的项目源码:
https://gitee.com/koevas/IOT-wechat

思路

微信小程序连接物联网(三):微信小程序远程遥控宿舍开门 基于NodeMCU通过MQTT协议连接阿里云物联网平台_第1张图片

微信小程序连接物联网(三):微信小程序远程遥控宿舍开门 基于NodeMCU通过MQTT协议连接阿里云物联网平台_第2张图片

1. 使用MQTT.fx客户端工具测试

官网:MQTT.fx

阿里云文档(使用MQTT.fx接入物联网平台):
https://help.aliyun.com/document_detail/140507.html

先在阿里云物联网平台创建一个产品,ProductKey为产品密钥
微信小程序连接物联网(三):微信小程序远程遥控宿舍开门 基于NodeMCU通过MQTT协议连接阿里云物联网平台_第3张图片
再创建两个设备
一个是宿舍门的被控端,用在nodemcu连接
一个是宿舍门的控制端,用在微信小程序连接
微信小程序连接物联网(三):微信小程序远程遥控宿舍开门 基于NodeMCU通过MQTT协议连接阿里云物联网平台_第4张图片
创建完设备获取到三元组,记录下来
微信小程序连接物联网(三):微信小程序远程遥控宿舍开门 基于NodeMCU通过MQTT协议连接阿里云物联网平台_第5张图片
在MQTT.fx上填写连接信息,用{}的变量请换成自己的三元组。
微信小程序连接物联网(三):微信小程序远程遥控宿舍开门 基于NodeMCU通过MQTT协议连接阿里云物联网平台_第6张图片

产品密钥:{ProductKey}
设备名字:{DeviceName}
设备密钥:{DeviceSecret}

Profile Name: Class_Door	# 在MQTT.fx里的名字,随便写
Profile Type: MQTT Broker	# 类型为MQTT代理
Broker Address: {ProductKey}.iot-as-mqtt.cn-shanghai.aliyuncs.com	# 设备名 + 域名后缀
Broker Port: 1883	# MQTT协议的连接端口,默认为1883
Client ID: {DeviceName}|securemode=3,signmethod=hmacsha1|

用户名:

User Name: {DeviceName}&{ProductKey}

密码:
密码需经过HmacSHA1算法加密生成,可以用 在线加密解密工具 生成
加密所需的明文为:

clientId{DeviceName}deviceName{DeviceName}productKey{ProductKey}

加密所需的密钥为:

{DeviceSecret}

微信小程序连接物联网(三):微信小程序远程遥控宿舍开门 基于NodeMCU通过MQTT协议连接阿里云物联网平台_第7张图片

连接成功后订阅消息,然后在阿里云物联网在线调试上发送一条数据,测试有没有收到。
微信小程序连接物联网(三):微信小程序远程遥控宿舍开门 基于NodeMCU通过MQTT协议连接阿里云物联网平台_第8张图片

2. Nodemcu连接阿里云物联网

使用MG90S舵机,可以旋转角度为0-180°,产生的扭矩足够打开宿舍的门锁,电源接到esp8266的Vin、GND口。PWM信号线接到esp8266的D3口。
微信小程序连接物联网(三):微信小程序远程遥控宿舍开门 基于NodeMCU通过MQTT协议连接阿里云物联网平台_第9张图片
打开esplorer编写init.lua烧录进esp8266里

连接wifi代码

-- wifi config
station_cfg = {}
station_cfg.ssid = "gzta"
station_cfg.pwd = "12345678"

-- wifi connect
print('Setting up WIFI...')
wifi.setmode(wifi.STATION)
wifi.sta.config(station_cfg)

-- wifi eventmon
wifi.eventmon.register(wifi.eventmon.STA_CONNECTED, function(T)
    print("wifi connecting...")
end)

wifi.eventmon.register(wifi.eventmon.STA_GOT_IP, function(T)
    print("wifi connect:" .. wifi.sta.getip())
end)

wifi.eventmon.register(wifi.eventmon.STA_DISCONNECTED, function(T)
    print("wifi disconnect...")
end)

控制舵机旋转角度的代码,用于打开门锁,旋转3秒后恢复到原来的位置。

-- Open the door for 3 seconds
function DoorOpen()
    pin = 3
    -- 20 - 130
    pwm.setup(pin, 50, 40)
    pwm.start(pin)
    print("start move position")
    tmr.create():alarm(3000, tmr.ALARM_SINGLE, function()
        print("recover position")
        pwm.setduty(pin, 120)
        pwm.stop(pin)
    end)
end

完整代码如下:
更改自己的wifi配置、topic、物联网三元组即可


-- wifi config
station_cfg = {}
station_cfg.ssid = "gzta"
station_cfg.pwd = "12345678"

-- topic
topic0 = "/a1UlGaNjWAO/Class_Door/user/message"

-- aliyun IOT config
ProductKey = "换成自己的"
DeviceName = "换成自己的"
DeviceSecret = "换成自己的"

mqttAddress = ProductKey .. ".iot-as-mqtt.cn-shanghai.aliyuncs.com"
mqttPort = 1883
ClientID = DeviceName .. "|securemode=3,signmethod=hmacsha1|"
UserName = DeviceName .. "&" .. ProductKey
hmac_data = "clientId" .. DeviceName .. "deviceName" .. DeviceName .. "productKey" .. ProductKey
Password = crypto.toHex(crypto.hmac("sha1", hmac_data, DeviceSecret))

-- wifi connect
print('Setting up WIFI...')
wifi.setmode(wifi.STATION)
wifi.sta.config(station_cfg)

-- wifi eventmon
wifi.eventmon.register(wifi.eventmon.STA_CONNECTED, function(T)
    print("wifi connecting...")
end)

wifi.eventmon.register(wifi.eventmon.STA_GOT_IP, function(T)
    print("wifi connect:" .. wifi.sta.getip())
end)

wifi.eventmon.register(wifi.eventmon.STA_DISCONNECTED, function(T)
    print("wifi disconnect...")
end)

-- aliyun iot connect
MQTT_connect_Flag = 0
myMQTT = mqtt.Client(ClientID, 120, UserName, Password)

Connect_timer = tmr.create()
Connect_timer:alarm(1000, tmr.ALARM_SEMI, function()
    if myMQTT ~= nil then
        print("MQTT client connect...")
        myMQTT:connect(mqttAddress, mqttPort, 0, mqtt_connect, mqtt_disconnect)
    end
end)

function mqtt_connect(client)
    print("mqtt connect success")
    myMQTT = client
    MQTT_connect_Flag = 1
    client:subscribe(topic0, 0, function(client)
        print("subscribe success")
    end)
    Connect_timer:stop()
end

function mqtt_disconnect(client, reason)
    print("mqtt connect Fail:" .. reason)
    MQTT_connect_Flag = 0
    Connect_timer:start()
end


-- mqtt client offline event
myMQTT:on("offline", function(client)
    print("mqtt client offline event")
    Connect_timer:start()
end)

-- mqtt client message event
myMQTT:on("message", function(client, topic, data)
    print(topic .. ":" .. data)
    t = sjson.decode(data)
    if t["method"] == "thing.service.DoorOpen" then
        DoorOpen()
    end
end)

-- Open the door for 3 seconds
function DoorOpen()
    pin = 3
    -- 20 - 130
    pwm.setup(pin, 50, 40)
    pwm.start(pin)
    print("start move position")
    tmr.create():alarm(3000, tmr.ALARM_SINGLE, function()
        print("recover position")
        pwm.setduty(pin, 120)
        pwm.stop(pin)
    end)
end

3. 微信小程序连接物联网

需要用到两个js库,分别是

  • MQTT的js库:
    https://unpkg.com/mqtt/dist/mqtt.min.js
  • 官方库aliyun-iot-client-sdk的hmac-sha1算法库:
    https://raw.githubusercontent.com/xihu-fm/aliyun-iot-client-sdk/master/lib/hex_hmac_sha1.js

主要流程:

  1. 新建一个小程序项目。复制mqtt.min.js和hex_hmac_sha1.js放到小程序项目的utils目录中,目录结构如下:
    微信小程序连接物联网(三):微信小程序远程遥控宿舍开门 基于NodeMCU通过MQTT协议连接阿里云物联网平台_第10张图片
  2. 配置开发者后台socket 合法域名 为:wss://productKey.iot-as-mqtt.cn-shanghai.aliyuncs.com(替换productKey为自己的产品key)
    微信小程序连接物联网(三):微信小程序远程遥控宿舍开门 基于NodeMCU通过MQTT协议连接阿里云物联网平台_第11张图片

核心的js代码参考了这篇博客,因为自己的宿舍小程序还有一些登录验证的代码,所以就不放出自己小程序完整的js代码了

var mqtt = require('../../utils/mqtt.min.js')
const crypto = require('../../utils/hex_hmac_sha1.js');
Page({
  data: {
   
  },
  
  // 发送开门指令,仅供参考,使用时请修改自己的topic
  command_opendoor(){
    var connectText = '{ "method": "thing.service.DoorOpen"}'
    client.publish('/a1UlGaNaaa/Door_Console/user/message', connectText, function (err){
      if (!err) {
        console.log('开门指令发送成功!');
      }
    })
  },
  
  onLoad: function () {
    this.doConnect()
  },
  
  doConnect(){
    const deviceConfig = {
      productKey: "替换",
      deviceName: "替换",
      deviceSecret: "替换",
      regionId: "cn-shanghai"
    };
    const options = this.initMqttOptions(deviceConfig);
    console.log(options)
    //替换productKey为你自己的产品的
    const client = mqtt.connect('wxs://productKey.iot-as-mqtt.cn-shanghai.aliyuncs.com',options)
    client.on('connect', function () {
      console.log('连接服务器成功')
      //订阅主题,替换productKey和deviceName(这里的主题可能会不一样,具体请查看后台设备Topic列表或使用自定义主题)
      client.subscribe('/productKey/deviceName/get', function (err) {
        if (!err) {
           console.log('订阅成功!');
        }
      })
    })
	//接收消息监听
    client.on('message', function (topic, message) {
      // message is Buffer
      console.log('收到消息:'+message.toString())
     //关闭连接 client.end()
    })
  },
  //IoT平台mqtt连接参数初始化
 initMqttOptions(deviceConfig) {

    const params = {
      productKey: deviceConfig.productKey,
      deviceName: deviceConfig.deviceName,
      timestamp: Date.now(),
      clientId: Math.random().toString(36).substr(2),
    }
    //CONNECT参数
    const options = {
      keepalive: 60, //60s
      clean: true, //cleanSession不保持持久会话
      protocolVersion: 4 //MQTT v3.1.1
    }
    //1.生成clientId,username,password
    options.password = this.signHmacSha1(params, deviceConfig.deviceSecret);
    options.clientId = `${params.clientId}|securemode=2,signmethod=hmacsha1,timestamp=${params.timestamp}|`;
    options.username = `${params.deviceName}&${params.productKey}`;

    return options;
  },

/*
  生成基于HmacSha1的password
  参考文档:https://help.aliyun.com/document_detail/73742.html?#h2-url-1
*/
 signHmacSha1(params, deviceSecret) {

    let keys = Object.keys(params).sort();
    // 按字典序排序
    keys = keys.sort();
    const list = [];
    keys.map((key) => {
      list.push(`${key}${params[key]}`);
    });
    const contentStr = list.join('');
    return crypto.hex_hmac_sha1(deviceSecret, contentStr);
  }
})

前端界面(有点丑Emmm):
微信小程序连接物联网(三):微信小程序远程遥控宿舍开门 基于NodeMCU通过MQTT协议连接阿里云物联网平台_第12张图片

4. 阿里云物联网M2M规则转发

由于MQTT协议里同一ClientID只能有一个连接,如果是用同一个ClientID 在不同地方登录,会先把最先登录的ClientID踢下线。所以微信小程序和NodeMCU不能共用一个设备。 既然如此,就将微信小程序和NodeMCU划分为两个不同设备。使用规则转发的方式通信。当微信小程序设备端发布消息时,NodeMCU端也同样能收到消息。

阿里云物联网平台官方文档:

基于规则引擎的M2M设备间通信
云产品流转概述

新建规则查询语句:
将微信小程序端收到的数据同时完整地转发给Nodemcu端

SELECT * FROM "/a1UlGaNaaa/Door_Console/user/message"

微信小程序连接物联网(三):微信小程序远程遥控宿舍开门 基于NodeMCU通过MQTT协议连接阿里云物联网平台_第13张图片

完成的样子

微信小程序连接物联网(三):微信小程序远程遥控宿舍开门 基于NodeMCU通过MQTT协议连接阿里云物联网平台_第14张图片
远程宿舍开门的功能需求简单,又无其他业务需求,就不需要利用到个人服务器保存什么数据了。所有操作只与阿里云的物联网平台交互

你可能感兴趣的:(微信小程序连接物联网)