中国移动物联网开放平台OneNET——设备接入测试(MQTT协议+HTTP协议)python代码

10 阅读4分钟

一、创建产品与设备

1.1 创建产品

进入OneNET平台(open.iot.10086.cn/console/sum…)后,点击「产品开发」,进入产品列表页面,「创建产品」- 智能化方式选择设备接入 image.png

image.png

1.2 设置物模型

「产品开发」- 「设置物模型」-「添加自定义功能点」或者是「导入物模型」

image.png

image.png

image.png

image.png

这里我添加好了2个属性power、temp和一个事件RolloverEvent

image.png

官方文档open.iot.10086.cn/doc/aiot/fu…

1.3 创建设备

进入OneNET平台后,展开菜单栏中的「设备接入与管理」,点击「设备管理」,进入设备列表页面。 点击「添加设备」,选中单个设备(默认方式),选择具体产品,完善设备基础信息,点击「确定」创建设备。

image.png 这里我创建了名为sheb1的设备

官方文档open.iot.10086.cn/doc/aiot/fu…

二、使用python代码生成密钥(token)

import base64
import hmac
from urllib.parse import quote
import time

# 中国移动官方文档给出的核心秘钥计算算法
def token(id,access_key):  
    version = '2018-10-31'
    res = 'products/%s' % id  # 通过产品ID访问产品API
    # 用户自定义token过期时间
    et = str(int(time.time()) + 63072000) # 设置为2年有效时间
    # 签名方法,支持md5、sha1、sha256
    method = 'sha1'
    # 对access_key进行decode
    key = base64.b64decode(access_key)
    # 计算sign
    org = et + '\n' + method + '\n' + res + '\n' + version
    sign_b = hmac.new(key=key, msg=org.encode(), digestmod=method)
    sign = base64.b64encode(sign_b.digest()).decode()
    # value 部分进行url编码,method/res/version值较为简单无需编码
    sign = quote(sign, safe='')
    res = quote(res, safe='')
    # token参数拼接
    token = 'version=%s&res=%s&et=%s&method=%s&sign=%s' % (version, res, et, method, sign)
    return token

username    = "3BYy2V3T40"                                           # 产品ID
accesskey   = "KyUNtcnDVS1hK71BZY3b2VHztU9pm29Vj4EDCxvt9XU="         # accessKey
password = token(username, accesskey)
print(password)

注意修改参数username(产品ID)、accessKey(产品access_key) ,产品ID和access_key的获取如图

image.png 运行代码生成的token是这样
version=2018-10-31&res=products%2F3BYy2V3T40&et=1835680707&method=sha1&sign=ItaqzT%2BIms%2BBLcv%2FQawZ61%2B8qC8%3D

三、MQTT协议接入设备

准备下面代码运行需要的参数

  • 产品ID image.png
  • 设备ID

image.png

  • 设备密钥即第二步通过代码生成的token

3.1 设备连接

import paho.mqtt.client as mqtt
import json
import time

# OneNET MQTT服务器地址
MQTT_SERVER = "mqtts.heclouds.com"
# 产品ID
P_ID = "W4f1HLHAMz"
# 设备ID
DEVICE_ID = "sheb1"
# 设备密钥
DEVICE_KEY = "version=2018-10-31&res=products%2FW4f1HLHAMz&et=1835595227&method=sha1&sign=ZrBONND4VBN59Rt24tukA378nAM%3D"

client=None

def on_connect(client, userdata, flags, rc, properties):
    print(f"Connected with result code {rc}")
    # 连接成功后的操作,例如订阅主题,这里订阅了全部物模型相关主题
    TOPIC = f"$sys/{P_ID}/{DEVICE_ID}/thing/#"
    client.subscribe(TOPIC)

def on_message(client, userdata, msg):
    print(f"Received message: {msg.topic} {msg.payload}")

def on_publish(client, userdata, result):
    print("Message published")

def connect_mqtt():
    global client
    client = mqtt.Client(client_id=DEVICE_ID, protocol=mqtt.MQTTv311, callback_api_version=mqtt.CallbackAPIVersion.VERSION2)
    client.username_pw_set(username=P_ID, password=DEVICE_KEY)
 
    client.on_connect = on_connect
    client.on_message = on_message
    client.on_publish = on_publish
 
    client.connect(MQTT_SERVER, 1883, 60)
    client.loop_forever()
    
connect_mqtt()

验证结果,在OneNet平台可以看到设备已处于在线状态 image.png

3.2 平台下发数据-设备属性设置

import paho.mqtt.client as mqtt
import json
import time

# OneNET MQTT服务器地址
MQTT_SERVER = "mqtts.heclouds.com"
# 产品ID
P_ID = "W4f1HLHAMz"
# 设备ID
DEVICE_ID = "sheb1"
# 设备密钥
DEVICE_KEY = "version=2018-10-31&res=products%2FW4f1HLHAMz&et=1835595227&method=sha1&sign=ZrBONND4VBN59Rt24tukA378nAM%3D"

client=None

def on_connect(client, userdata, flags, rc, properties):
    print(f"Connected with result code {rc}")
    # 连接成功后的操作,例如订阅主题,这里订阅了全部物模型相关主题
    TOPIC = f"$sys/{P_ID}/{DEVICE_ID}/thing/#"
    client.subscribe(TOPIC)
    

def on_message(client, userdata, msg):
    print(f"Received message: {msg.topic} {msg.payload}")
    # 设备侧收到平台下发的数据
    if msg.topic == f"$sys/{P_ID}/{DEVICE_ID}/thing/property/set":
        data = json.loads(msg.payload)
        print(data)
        # 设备属性设置响应
        TOPIC = f"$sys/{P_ID}/{DEVICE_ID}/thing/property/set_reply"
        # 其中id需要与下发数据id一致,code为200代表成功,msg可以自定义
        payload = {
            "id": data['id'],
            "code": 200,
            "msg": "success"
        }
        client.publish(TOPIC, json.dumps(payload))

def on_publish(client, userdata, result):
    print("Message published")

def connect_mqtt():
    global client
    client = mqtt.Client(client_id=DEVICE_ID, protocol=mqtt.MQTTv311, callback_api_version=mqtt.CallbackAPIVersion.VERSION2)
    client.username_pw_set(username=P_ID, password=DEVICE_KEY)
 
    client.on_connect = on_connect
    client.on_message = on_message
    client.on_publish = on_publish
 
    client.connect(MQTT_SERVER, 1883, 60)
    client.loop_forever()
                
connect_mqtt()

在设备管理详情页点击「设备调试」Tab栏,或进入产品开发-设备调试流程模块,选择「应用模拟器」,点击「启动调试」,可进行设置设备属性,topic: $sys/{pid}/{device-name}/thing/property/set_reply

image.png 可以看到已经收到属性设置 image.png

3.3 属性上报

import paho.mqtt.client as mqtt
import json
import time

# OneNET MQTT服务器地址
MQTT_SERVER = "mqtts.heclouds.com"
# 产品ID
P_ID = "W4f1HLHAMz"
# 设备ID
DEVICE_ID = "sheb1"
# 设备密钥
DEVICE_KEY = "version=2018-10-31&res=products%2FW4f1HLHAMz&et=1835595227&method=sha1&sign=ZrBONND4VBN59Rt24tukA378nAM%3D"

client=None

def on_connect(client, userdata, flags, rc, properties):
    print(f"Connected with result code {rc}")
    # 连接成功后的操作,例如订阅主题,这里订阅了全部物模型相关主题
    TOPIC = f"$sys/{P_ID}/{DEVICE_ID}/thing/#"
    client.subscribe(TOPIC)

def on_message(client, userdata, msg):
    print(f"Received message: {msg.topic} {msg.payload}")

def on_publish(client, userdata, result):
    print("Message published")

def connect_mqtt():
    global client
    client = mqtt.Client(client_id=DEVICE_ID, protocol=mqtt.MQTTv311, callback_api_version=mqtt.CallbackAPIVersion.VERSION2)
    client.username_pw_set(username=P_ID, password=DEVICE_KEY)
 
    client.on_connect = on_connect
    client.on_message = on_message
    client.on_publish = on_publish
 
    client.connect(MQTT_SERVER, 1883, 60)
    # 非阻塞启动循环
    client.loop_start()
    
# 属性上报
def property_post():
    # 主题(Topic)- 设备属性上报请求
    TOPIC = f"$sys/{P_ID}/{DEVICE_ID}/thing/property/post"
    timestamp = time.time()
    # 发布消息
    payload = {
        "id": "123",
        "version": "1.0",
        "params": {
            "power": { # power为产品物模型中定义的属性名称
                "value": 55,
                "time": timestamp
            },
            "temp": { # temp为产品物模型中定义的属性名称
                "value": 55,
                "time": timestamp
            }
        }
    }
    client.publish(TOPIC, json.dumps(payload))
    
connect_mqtt()
property_post()
client.loop_stop()

验证结果,在OneNet平台中可以看到属性已经上报成功 image.png

3.4 事件上报

import paho.mqtt.client as mqtt
import json
import time

# OneNET MQTT服务器地址
MQTT_SERVER = "mqtts.heclouds.com"
# 产品ID
P_ID = "W4f1HLHAMz"
# 设备ID
DEVICE_ID = "sheb1"
# 设备密钥
DEVICE_KEY = "version=2018-10-31&res=products%2FW4f1HLHAMz&et=1835595227&method=sha1&sign=ZrBONND4VBN59Rt24tukA378nAM%3D"

client=None

def on_connect(client, userdata, flags, rc, properties):
    print(f"Connected with result code {rc}")
    # 连接成功后的操作,例如订阅主题,这里订阅了全部物模型相关主题
    TOPIC = f"$sys/{P_ID}/{DEVICE_ID}/thing/#"
    client.subscribe(TOPIC)

def on_message(client, userdata, msg):
    print(f"Received message: {msg.topic} {msg.payload}")

def on_publish(client, userdata, result):
    print("Message published")

def connect_mqtt():
    global client
    client = mqtt.Client(client_id=DEVICE_ID, protocol=mqtt.MQTTv311, callback_api_version=mqtt.CallbackAPIVersion.VERSION2)
    client.username_pw_set(username=P_ID, password=DEVICE_KEY)
 
    client.on_connect = on_connect
    client.on_message = on_message
    client.on_publish = on_publish
 
    client.connect(MQTT_SERVER, 1883, 60)
    # 非阻塞启动循环
    client.loop_start()
    
# 事件上报
def event_post():
    # 主题(Topic)- 设备属性上报请求
    TOPIC = f"$sys/{P_ID}/{DEVICE_ID}/thing/event/post"
    timestamp = time.time()
    # 发布消息
    payload = {
        "id": "123",
        "version": "1.0",
        "params": {
            "RolloverEvent": { # RolloverEvent为产品物模型中定义的事件名称
                "time":timestamp,
                "value":{
                    "RolloverAccP":18, # 物模型中定义的事件输出参数
                    "RolloverAccE":19,
                }
            }
        }
    }
    client.publish(TOPIC, json.dumps(payload))
                
connect_mqtt()
event_post()
client.loop_stop()

验证结果,在OneNet平台中可以看到事件已经上报成功 image.png

四、HTTP协议接入设备

注意HTTP协议接入需要在第一步「创建产品」的时候接入协议选择HTTP,其他创建产品和创建设备的步骤都一样,验证结果也一样,不再赘述,下面直接贴代码

4.1 设备上下线

import requests
import json

# OneNET MQTT服务器地址
MQTT_SERVER = "https://open.iot.10086.cn/fuse/http/"
# 产品ID
P_ID = "3BYy2V3T40"
# 设备ID
DEVICE_ID = "sheb2"
# 设备密钥
DEVICE_KEY = "version=2018-10-31&res=products%2F3BYy2V3T40&et=1835667958&method=sha1&sign=EDkn0Yk8NaVcFQZJlVZdEab98N0%3D"

hd = {
    "Content-Type": "application/json",
    "token": DEVICE_KEY
}

# 设备上下线
def on_connect():
    data = {
        'pid': P_ID,
        'devName': DEVICE_ID,
        'status': 1, # 1:上线 0:下线
        "protocol":"HTTP",
        "network": 0,  # 联网方式,整数,上报卡标识或设备标识时必须,根据联网方式不同,校验以下卡标识和设备标识,取值**0-非蜂窝 1-移动 2-电信 3-联通 4-广电**
        "sn": 'xxxxxxxxxxxx' # 设备序列号,模拟的时候可以随便填,但要注意规则:10-32个字符,只支持数字、大小写字母及“-”或“:”
    }
    page = requests.post(f'{MQTT_SERVER}device/online', headers=hd, json=data, verify=False).json()
    print(page)
    
on_connect()

4.2 设备属性上报

import requests
import json
import time

# OneNET MQTT服务器地址
MQTT_SERVER = "https://open.iot.10086.cn/fuse/http/"
# 产品ID
P_ID = "3BYy2V3T40"
# 设备ID
DEVICE_ID = "sheb2"
# 设备密钥
DEVICE_KEY = "version=2018-10-31&res=products%2F3BYy2V3T40&et=1835667958&method=sha1&sign=EDkn0Yk8NaVcFQZJlVZdEab98N0%3D"

hd = {
    "Content-Type": "application/json",
    "token": DEVICE_KEY
}


# 设备属性上报
def property_post():
    TOPIC = f"$sys/{P_ID}/{DEVICE_ID}/thing/property/post"
    timestamp = time.time()
    data = {
        "id": "123",
        "version": "1.0",
        "params": {
            "power": {
                "value": 10,
                "time": timestamp
            },
            "temp": {
                "value": 11,
                "time": timestamp
            }
        }
    }
    page = requests.post(f'{MQTT_SERVER}/device/thing/property/post?topic={TOPIC}&protocol=http', headers=hd, json=data, verify=False).json()
    print(page)
    
property_post()

4.3 设备事件上报

import requests
import json
import time

# OneNET MQTT服务器地址
MQTT_SERVER = "https://open.iot.10086.cn/fuse/http/"
# 产品ID
P_ID = "3BYy2V3T40"
# 设备ID
DEVICE_ID = "sheb2"
# 设备密钥
DEVICE_KEY = "version=2018-10-31&res=products%2F3BYy2V3T40&et=1835667958&method=sha1&sign=EDkn0Yk8NaVcFQZJlVZdEab98N0%3D"

hd = {
    "Content-Type": "application/json",
    "token": DEVICE_KEY
}

# 设备事件上报
def event_post():
    TOPIC = f"$sys/{P_ID}/{DEVICE_ID}/thing/event/post"
    timestamp = time.time()
    data = {
        "id": "123",
        "version": "1.0",
        "params": {
            "RolloverEvent": {
                "time":timestamp,
                "value":{
                    "power":99
                }
            }
        }
    }
    page = requests.post(f'{MQTT_SERVER}/device/thing/event/post?topic={TOPIC}&protocol=http', headers=hd, json=data, verify=False).json()
    print(page)
    
event_post()