MQTT学习笔记——Yeelink MQTT服务 使用mqtt.js和paho-mqtt

0 前言

    2014年8月yeelink推出基于MQTT协议的开关类型设备控制API,相比于基于HTTP RESTful的轮训方式,通过订阅相关主题消息,可以远程控制类应用实时性更好。本文使用两种方式实现开关类型设备的远程控制,一种是基于nodeJS的MQTT.js扩展库,另一种是基于python的paho-mqtt扩展库。
    【相关博文——MQTT】
    【相关博文——HTTP RESTful】
    
1 安装和使用mqtt.js
    由于没有在树莓派上安装nodeJS,也没有安装GPIO扩展库,所以本例并没有演示如何通过yeelink推送的消息控制GPIO。所以本例暂时只能在PC机上运行,但是通过该例子可以熟悉yeelink MQTT的基本使用方法。
1.1 安装mqtt.js
npm install mqtt 或 cnpm install mqtt

1.2 实现代码——yeelink_mqtt.js
var mqtt = require('mqtt'); 

var username = 'U-ApiKey'; 
var password = 'ffa3826972d6cc7ba5b17e104ec5xxxx'; 
var hostname = 'mqtt.yeelink.net'; 
var topic = '/v1.1/device/1949/sensor/2511/datapoints'; 

var url = 'mqtt://' + username + ':' + password + '@' + hostname; 

console.log(url);

var client = mqtt.connect(url); 
// 订阅主题 
client.subscribe(topic); 

client.on('message', function(topic, message) { 
    console.log(topic); 
    console.log(message); 
});

1.3 运行
    【执行代码】
    node yeelink_mqtt.js
    【修改状态】
    登录yeelink平台通过网页修改开关设备状态,也可通过其他方法修改设备状态。一旦设备状态发生修改,那么控制台便会输出被推送的消息,整个过程几乎没有延时。
    【控制台输出】
mqtt://U-ApiKey:[email protected]
/v1.1/device/1949/sensor/2511/datapoints
{"sensor_id":2511,"timestamp":1410835745,"value":1}
/v1.1/device/1949/sensor/2511/datapoints
{"sensor_id":2511,"timestamp":1410835754,"value":0}

1.4 简单说明
    【1】MQTT协议中可指定用户名和密码,在yeelink协议中,用户名变为U-ApiKey,密码为U-ApiKey的具体值。
    【2】订阅主题为设备URI,需要把API版本号修改为v1.1
    【3】主机名称为mqtt.yeelink.net,而不是api.yeelink.net
    在mqtt.js的示例代码中:client = mqtt.connect(‘mqtt://user:pass@localhost‘);
    在yeelink的示例代码中:client = mqtt.connect("mqtt://U-ApiKey:<your_key>@mqtt.yeelink.net");
    以上的两个示例代码更可以说明各参数的对应关系。

2 安装和使用paho-mqtt
    本例演示在树莓派上安装paho-mqtt,通过推送消息的内容控制GPIO
2.1 安装paho-mqtt
    pip install paho-mqtt

2.2 实现代码
# -*- coding: utf-8 -*-  
import paho.mqtt.client as mqtt
import RPi.GPIO as GPIO
import json

hostname = 'mqtt.yeelink.net'
username = 'U-ApiKey'
password = 'ffa3826972d6cc7ba5b17e104ec5xxxx'
topic = '/v1.1/device/1949/sensor/2511/datapoints'
# BCM GPIO编号
pins = [17,18,27,22,23,24,25,4]
pin = 18

def gpio_setup():
    # 采用BCM编号
    GPIO.setmode(GPIO.BCM)
    # 设置所有GPIO为输出状态,且输出低电平
    for pin in pins:
        GPIO.setup(pin, GPIO.OUT)
        GPIO.output(pin, GPIO.LOW)
        
def gpio_destroy():
    for pin in pins:
        GPIO.output(pin, GPIO.LOW)
        GPIO.setup(pin, GPIO.IN)
        
# 连接成功回调函数
def on_connect(client, userdata, flags, rc):
    print("Connected with result code " + str(rc))
    # 连接完成之后订阅主题
    client.subscribe(topic)

# 消息推送回调函数
def on_message(client, userdata, msg):
    print(msg.topic+" "+str(msg.payload))
    # 获得负载中的pin 和 value
    gpio = json.loads(str(msg.payload))

    if gpio['value'] == 0:
        GPIO.output(pin, GPIO.LOW)
    else:
        GPIO.output(pin, GPIO.HIGH)    

if __name__ == '__main__':
    client = mqtt.Client()
    client.on_connect = on_connect
    client.on_message = on_message
    gpio_setup()
    
    try:
        # 配置用户名和密码
        client.username_pw_set(username, password)
        client.connect(hostname, 1883, 60)
        client.loop_forever()
    except KeyboardInterrupt:
        client.disconnect()
        gpio_destroy()

2.3 运行
    【执行代码】
    python yeelink_mqtt.js
    【修改状态】
    登录yeelink平台通过网页修改开关设备状态,也可通过其他方法修改设备状态。一旦设备状态发生修改,那么控制台便会输出被推送的消息,整个过程几乎没有延时。
    【控制台输出】
Connected with result code 0
/v1.1/device/1949/sensor/2511/datapoints {"sensor_id":2511,"timestamp":141083559 8,"value":1} 
/v1.1/device/1949/sensor/2511/datapoints {"sensor_id":2511,"timestamp":141083560 2,"value":0}

2.4 简单说明
    【1】请注意代码中的用户名,密码设置,通过client.username_pw_set(username, password)设置用户名和密码,但是用户名和密码此时变为了U-ApiKey和U-ApiKey的具体值。
    【2】on_connect为连接成功回调函数,on_message为收到推送消息回调函数。
    【3】连接成功之后订阅主题,若接收到服务器推送的消息,通过消息中value控制GPIO。

3 总结
    【1】在yeelink应用中U-ApiKey变为了用户名和密码
    【2】设备URI变为了主题
    【3】订阅了相关主题的消息之后,若通过其他方法(HTTP RESTful)改变开关设备状态,那么设备便会接收到来自yeelink平台的推送消息,我们可以认为消息推送是实时的。
    【4】相对于设备控制,MQTT协议比HTTP协议要简洁些,实时性更好。

4 参考资料

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。