11301浏览
查看: 11301|回复: 2

【行空板教程】玩转物联网

[复制链接]
本帖最后由 Hockel 于 2022-4-13 23:34 编辑

前言

互联网仅仅是人与人之间信息交流的网络,我们更希望其满足人与物、物与物之目前的互联网仅仅是人与人之间信息交流的网络,我们更希望其满足人与物、物与物之间信息的自动交互和共享。物联网是互联网的延伸与扩展,物联网可以实现物理世界与信息世界的无缝连接,将各种功能不同的智能传感器嵌入到电网、铁路、桥梁、隧道、公路、建筑、供水系统、大坝、油气管道等物体中,通过无线传感器网络、互联网、超级计算机和云计算等组成物联网,实现人类社会与物理系统的整合,使世界上的物、人、网与社会融合为一个有机的整体。那么本次教程,就让我们打开物联网的大门吧!

相关知识点

MQTT的工作原理

说到物联网,那么就一定要提MQTT协议。那什么是MQTT协议呢?

MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的"轻量级"通讯协议,该协议构建于TCP/IP协议上,由IBM在1999年发布。MQTT最大优点在于,可以以极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。作为一种低开销、低带宽占用的即时通讯协议,使其在物联网、小型设备、移动应用等方面有较广泛的应用。
MQTT是一个基于客户端-服务器的消息发布/订阅传输协议。MQTT协议是轻量、简单、开放和易于实现的,这些特点使它适用范围非常广泛。在很多情况下,包括受限的环境中,如:机器与机器(M2M)通信和物联网(IoT)。其在,通过卫星链路通信传感器、偶尔拨号的医疗设备、智能家居、及一些小型化设备中已广泛使用。

中介承担着转发MQTT 通信的服务器的作用。相对而言,发布者和订阅者则起着客户端的作用。发布者是负责发送消息的客户端,而订阅 者是负责接收消息的客户端。MQTT 交换的消息都附带“主题”地址,各个客户端把这个“主题”视为收信地址,对其执行传输消息的操作。 形象地比喻一下,中介就是接收邮件的邮箱。

中介在等待各个客户端对其进行连接。订阅者连接中介,把自己想订阅的主题名称告诉中介。这就叫作订阅。 然后发布者连接中介,以主题为收信地址发送消息。这就是发布。发布者一发布主题,中介就会把消息传递给订阅了该主题的订阅者。
如上图所示,如果订阅者订阅了主题A,那么只有在发布者发布了主题A 的情况下,中介才会把消息传递给订阅者。订阅者和中介总是处于 连接状态,而发布者则只需在发布时建立连接,不过要在短期内数次发布时,就需要保持连接状态了。因为中介起着转发消息的作用,所以各 个客户端彼此之间没有必要知道对方的IP 地址等网络上的收信地址。又因为多个客户端可以订阅同一个主题,所以发布者和订阅者是一 对多的关系。在设备和服务器的通信中,设备相当于发布者,服务器则相当于订阅者。

主题采用的是分层结构。用“#”和“+”这样的符号能指定多个主题。如上图所示,/Sensor/temperature/# 中使用了“#”符号,这样就 能指定所有开头为/Sensor/temperature/ 的主题。此外,/Sensor/+/room1中使用了符号“+”,这样一来就能指定所有开头是/Sensor/、结尾是/room1 的主题。

MQTT原理转载至 [图解物联网 / 日本NTT DATA集团等著;丁灵译. --北京:人民邮电出版社, 2017.4]

准备阶段

1、注册EASYIOT账号

这里我们用的物联网平台是:DFRobot Easy IoT 物联网平台:https://iot.dfrobot.com.cn/ ,它操作简单,更加适合入门者学习,当然也方便我们教学。我们用浏览器输入网址后,进行登录,没有账号的读者可以选择右上角的注册按钮进行注册。

登录IoT网站,注册账号。进入工作间。新建一个设备,默认名字“设备一”。(ps:一个账号,默认一共有10000条信息的储存容量。这些容量共所有设备共享。)

例如,下图设备上方显示“0/1000”,那么此设备最大可储存1000条信息,已使用0条信息的储存空间。如果此设备收发的信息超过1000条,新信息将不再存入。 每个设备默认每隔1s储存一次消息。 观察到设备唯一识别码Topic以及左侧的用户信息


点击眼睛图标可以将隐藏的Iot_id和Iot_pwd显示出来。

为了稍后编程需要,记下相关账号:

  • iot_id: Skv3zKyNb

  • iot_pwd: r1lD3ztJ4b

  • topic: BJpHJt1VW

2、paho-mqtt python库

行空板内置了paho-mqtt库,这里我们主要用到下面这几个函数:

  • 使用 connect() / connect_async() 连接Broker
  • 调用 loop() 保持与Broker网络连接
  • 使用 loop_start() 调用一个loop()进程
  • 使用 loop_forever() 保持 loop()调用
  • 使用 subscribe() 订阅主题并接收消息
  • 使用 publish() 发布消息
  • 使用 disconnect() 与Broker断开连接

    详细文档https://pypi.org/project/paho-mqtt/1.1/

3、pingpong库

如果我们想要控制外部LED灯的亮灭,这个时候就需要用到pingpong库,这个在我们行空板是内置安装了,我们就不需要再安装了。

控制Led灯

行空板背面有一颗蓝色LED灯(标记为L)可供用户控制。
L灯为高低电平控制,接到了行空板的P25接口上,因此控制P25即可控制L灯。

  • 语法:Pin(Pin.P25, Pin.OUT).write_digital(电平信号)
  • 返回值:无
  • 输入参数:1高电平, 0低电平
  • 示例代码:
# -*- coding: UTF-8 -*-
import time
from pinpong.board import Board,Pin

Board().begin()               #初始化

led = Pin(Pin.P25, Pin.OUT) #引脚初始化为电平输出模式,P25为L灯的引脚

while True:
  #led.value(1) #输出高电平 方法1
  led.write_digital(1) #输出高电平 方法2
  print("1 LED亮") #终端打印信息
  time.sleep(1) #等待1秒 保持状态

  #led.value(0) #输出低电平 方法1
  led.write_digital(0) #输出低电平 方法2
  print("0 LED灭") #终端打印信息
  time.sleep(1) #等待1秒 保持状态

程序设计

1、向物联网平台发布数据

import paho.mqtt.client as mqtt
import time

server =  "182.254.130.180"
port = 1883
iot_id = ""
iot_pwd = ""
topic = ""

# 以当前时间作为client_id
client_id = time.strftime('%Y%m%d%H%M%S',time.localtime(time.time()))  
# ClientId不能重复,所以使用当前时间
client = mqtt.Client(client_id) 
 #设置连接的服务器、端口及keepalive
client.connect(server,port , 30) 
# 设置连接用户和密码,必须设置,否则会返回Connected with result code 4
client.username_pw_set(iot_id, iot_pwd)
client.loop_start()

def publish_msg(msg):
    # 向topic发送msg信息
    client.publish(topic,msg,1) 

if __name__ == '__main__':
    while True:
        message = input("please input your message: ")
        publish_msg(message)

测试结果:

2、订阅物联网发来的数据

作为一个接收者,同一个主题没有发布(pub)信息的时候,就自己一直等候。

import paho.mqtt.client as mqtt
import time

server =  "182.254.130.180"
port = 1883
iot_id = "uqtPhtNGg"
iot_pwd = "XqtE2tNMRz"
topic = "VmK3TXE7R"

# 以当前时间作为client_id
client_id = time.strftime('%Y%m%d%H%M%S',time.localtime(time.time()))  
# ClientId不能重复,所以使用当前时间
client = mqtt.Client(client_id) 
 #设置连接的服务器、端口及keepalive
client.connect(server,port , 30) 
# 设置连接用户和密码,必须设置,否则会返回Connected with result code 4
client.username_pw_set(iot_id, iot_pwd)

def on_connect(client, userdata, flags, rc):
    client.subscribe(topic)  # 填写订阅的主题

def on_message(client, userdata, msg):
    print(msg.topic+" " + ":" + str(msg.payload))  # 打印接受的消息

def on_publish(topic, payload, qos):
    client.publish(topic, payload, qos)

def subscribe_msg():
    client.on_connect = on_connect
    client.on_message = on_message
    client.loop_forever()

if __name__ == '__main__':
    subscribe_msg()

测试结果:

3、按钮控制LED

电路连接:

程序编写:

from unihiker import GUI  #导入包
import time
from pinpong.board import Board,Pin
Board().begin()               #初始化

led = Pin(Pin.P24, Pin.OUT) #引脚初始化为电平输出模式,P25为L灯的引脚
led.write_digital(0)

gui=GUI()
img_btn = gui.draw_image(x=120, y=120, w=80, h=50, image='bt2.png', origin='center', onclick=lambda: Change())
num = 0

def Change():
    global num
    num = num + 1
    if(num % 2 == 1):
        img_btn.config(image='bt1.png')
        led.write_digital(1)
    else:
        img_btn.config(image='bt2.png')
        led.write_digital(0)

while True:
    time.sleep(1)

效果:

4、远程控制开关灯

from unihiker import GUI  #导入包
import time
from pinpong.board import Board,Pin
import paho.mqtt.client as mqtt
import time

server =  "182.254.130.180"
port = 1883
iot_id = "uqtPhtNGg"
iot_pwd = "XqtE2tNMRz"
topic = "VmK3TXE7R"

Board().begin()               #初始化
led = Pin(Pin.P24, Pin.OUT) #引脚初始化为电平输出模式,P25为L灯的引脚
led.write_digital(0)

gui=GUI()
img_btn = gui.draw_image(x=120, y=120, w=80, h=50, image='bt2.png', origin='center', onclick=lambda: Change())
gui.draw_text(x=60, y=20,color="#4169E1", font_size=18,text="玩转物联网")

num = 0

client_id = time.strftime('%Y%m%d%H%M%S',time.localtime(time.time()))   # 以当前时间作为client_id
client = mqtt.Client(client_id)    # ClientId不能重复,所以使用当前时间
client.username_pw_set(iot_id, iot_pwd) # 设置连接用户和密码,必须设置,否则会返回Connected with result code 4
client.connect(server, port, 30)   # 1883为服务端口号,如果是安全认证,端口号需要修改为1884

def on_connect(client, userdata, flags, rc):
    client.subscribe(topic)  # 填写订阅的主题

def on_message(client, userdata, msg): #接受来自easyiot信息
    global _msg
    _msg = 0
    _msg = msg.payload
    _msg = _msg.decode()
    print(_msg) # 打印接受的消息
    if(_msg == "on"):
        print("灯已打开")
        led.write_digital(1)
    elif(_msg == "off"):
        led.write_digital(0)
        print("灯已关闭")

def send_msg(msg): # 向物联网发送消息
    client.publish(topic,msg,1) # 向topic发送msg信息
#     client.loop_start()

def subscribe_msg():
    client.on_connect = on_connect
    client.on_message = on_message
    client.loop_forever()

def Change():
    global num
    num = num + 1
    if(num % 2 == 1):
        img_btn.config(image='bt1.png')
        led.write_digital(1)
        send_msg("灯已打开")
    else:
        img_btn.config(image='bt2.png')
        led.write_digital(0)
        send_msg("灯已关闭")

if __name__ == '__main__':
        subscribe_msg()        
        while True:
            time.sleep(1)

效果:




注意事项

loop()方法在MQTT客户端中也非常重要,它主要是用来去查询消息缓存区。当有新的消息到达时,这些消息会存储在接收缓存区,等待有客户端程序去读取。loop()方法就是一个内置的读取接收和发送缓存区,并分发消息的方法。简单说就是,如果不loop,也不自己去主动读取接收缓存区,就触发不了回调函数,所以要记着写上loop。

Paho python client中提供了3个方法:

loop_forever() --会阻塞程序,其实是周期调用loop()方法,如果程序需要一直处于订阅中的话,可以用这个方法,它也会对客户端进行重连。
loop_start() --会新起一个thread,这个thread会调用loop_forever(),所以也会周期调用loop(),并且会保证客户端自动re-connect
loop() --这个方法只会loop指定的时间(默认1s),只会就结束,不会继续去读取缓存区,所以如果在程序中使用的话,需要自己写个周期调用

总结

好了,本次课程到这里就结束了!通过本次课程我们学会了如何使用行空板通过mqtt协议发布消息和订阅消息。剩下的我们是不是就可以做一个智能家居项目呢?算是抛砖引玉吧。期待读者们有更多物联网相关的作品。更多教程欢迎关注:跟着hockel玩科创!



6.png

派大星ym  初级技匠

发表于 2022-8-1 14:56:33

酷酷酷酷
回复

使用道具 举报

JVUm7ppJGaRK  高级技师

发表于 2023-1-6 22:46:52

好高端的样子
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail