Notice: Function _load_textdomain_just_in_time was called incorrectly. Translation loading for the simply-static domain was triggered too early. This is usually an indicator for some code in the plugin or theme running too early. Translations should be loaded at the init action or later. Please see Debugging in WordPress for more information. (This message was added in version 6.7.0.) in /var/www/html/wp-includes/functions.php on line 6121
2022 年 7 月 – 第 2 页

树莓派控制舵机

from time import sleep
import RPi.GPIO as GPIO
 
GPIO.setmode(GPIO.BCM)#以BCM模式使用引脚
GPIO.setwarnings(False)# 去除GPIO警告
 
 
def setServoAngle(servo, angle):#此函数将角度转换为占空比
    pwm = GPIO.PWM(servo, 50)#设置pwm波为50Hz,也就是20ms一周期
    pwm.start(8)#启动pwm
    dutyCycle = angle / 18. + 3.#此公式由舵机调零推算得出(+3是偏移量)(占空比=%2.5+(目标角度/180°)*(%12.5-%2.5))
    pwm.ChangeDutyCycle(dutyCycle)#调整pwm占空比
    sleep(0.3)
    pwm.stop()#关闭pwm
 
 
if __name__ == '__main__':
    import sys
 
    servo = int(sys.argv[1])#外部输入参数
    GPIO.setup(servo, GPIO.OUT)#设置指定的引脚为输出模式
    setServoAngle(servo, int(sys.argv[2]))
    GPIO.cleanup()#清除引脚占用

python3 文件名 舵机引脚 舵机角度

  • 注意:控制舵机转动时,发送的控制舵机旋转的两条命令之间要有一定间隔,因为舵机执行转动命令转到固定角度需要一定的时间。
  • 有时执行时需要以sudo执行

硬件连接部分:
舵机为MG90S型号,由三根线控制,棕色为负,红色为正,橙色是信号线

此舵机可以由树莓派直接供电,不需要外接电源

棕色GND

红色VCC

橙色GPIO

舵机接线后一定要检查连接是否正确再上电!!!否则可能会烧坏树莓派!可以在舵机和树莓派之间接一10k电阻。保护树莓派。

此引脚图为网口对着自己时
舵机调零:
舵机旋转角度是绝对位置,每一个位置对应固定的角度(类似于tab缩进,光标在屏幕上有固定的位置,当按下tab键时,光标跳到固定位置而不是固定缩进多少格),mg90s的旋转角度为0°~180°。

舵机调零是指当代码控制舵机在某一位置时(例如0度),舵机臂有可能不在0°位置,此时要通过改变舵机臂的固定位置,使舵机臂物理上处于0°位置。

舵机控制原理:(引用于此秒懂舵机角度控制原理 – 八色木)
舵机内部的控制电路,电位计(可变电阻器)和电机均被连接到电路板上,如内部结构图的右边部分。控制电路通过电位计可监控舵机的当前角度。

如果轴的位置与控制信号相符,那么电机就会关闭。如果控制电路发现这个角度不正确,它就会控制马达转动,直到它达到指定的角度。舵机角度根据制造商的不同而有所不同。比如,一个180度的舵机,它可以在0度至180度之间运动。由于限位装置被安装在主输出装置上,超出这个范围机械结构就不能再转动了。

舵机的输出功率与它所需要转动的距离成正比。如果输出轴需要转动很长的距离,马达就会全速运转,如果它只需要短距离转动,马达就会以较慢的速度运行,这叫做速度比例控制。

控制线用于传输角度控制信号。这个角度是由控制信号脉冲的持续时间决定的,这叫做脉冲编码调制(PCM)。舵机的控制一般需要一个20ms左右的时基脉冲,该脉冲的高电平部分一般为0.5ms-2.5ms范围,总间隔为2ms。脉冲的宽度将决定马达转动的距离。例如:1.5毫秒的脉冲,电机将转向90度的位置(通常称为中立位置,对于180°舵机来说,就是90°位置)。如果脉冲宽度小于1.5毫秒,那么电机轴向朝向0度方向。如果脉冲宽度大于1.5毫秒,轴向就朝向180度方向。以180度舵机为例,对应的控制关系是这样的:

0.5ms———— 0度;

1.0ms———— 45度;

1.5ms———— 90度;

2.0ms———– 135度;

2.5ms———– 180度;

占空比是指在一个脉冲循环内,通电时间相对于总时间所占的比例。占空比(Duty Ratio)在电信领域中有如下含义:例如:脉冲宽度1μs,信号周期4μs的脉冲序列占空比为0.25。
舵机代码中是以占空比来进行舵机旋转角度的控制,而占空比和角度的变化是线性,所以可以得到计算公式为:

占空比 = (0.5ms/20ms) + (旋转角度/180°)((2.5ms/20ms) – (0.5ms/20ms))

20ms是一个脉冲循环的周期,由设置的pwm波的频率为50Hz计算得到。

import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
signal = 18
GPIO.setup(signal, GPIO.OUT)
frequency = 50
pwm = GPIO.PWM(signal, frequency)
def get_duty(direction):
    duty = (1/18)*direction + 2.5
    return duty

if __name__ == '__main__':
    try:
        pwm.start(0)
        while True:
            direction = float(input("Please input a direction between 0 and 180:"))
            duty = get_duty(direction)
            pwm.ChangeDutyCycle(duty)            
    except Exception as e:
        print('An exception has happened',e)        
    finally:
        pwm.stop()
        GPIO.cleanup()

micropython的mqtt编程

main.py

# Complete project details at https://RandomNerdTutorials.com

def sub_cb(topic, msg):
  print((topic, msg))
  if topic == b'notification' and msg == b'received':
    print('ESP received hello message')

def connect_and_subscribe():
  global client_id, mqtt_server, topic_sub
  client = MQTTClient(client_id, mqtt_server,port=21892,user='roown',password='Chinaone',keepalive=60)
  client.set_callback(sub_cb)
  client.connect()
  client.subscribe(topic_sub)
  print('Connected to %s MQTT broker, subscribed to %s topic' % (mqtt_server, topic_sub))
  return client

def restart_and_reconnect():
  print('Failed to connect to MQTT broker. Reconnecting...')
  time.sleep(10)
  machine.reset()

try:
  client = connect_and_subscribe()
except OSError as e:
  restart_and_reconnect()

while True:
  try:
    client.check_msg()
    if (time.time() - last_message) > message_interval:
      msg = b'Hello #%d' % counter
      client.publish(topic_pub, msg)
      last_message = time.time()
      counter += 1
  except OSError as e:
    restart_and_reconnect()

boot.py

# This file is executed on every boot (including wake-boot from deepsleep)
#import esp
#esp.osdebug(None)
#import webrepl
#webrepl.start()
# Complete project details at https://RandomNerdTutorials.com

import time
from umqttsimple import MQTTClient
import ubinascii
import machine
import micropython
import network
import esp
esp.osdebug(None)
import gc
gc.collect()

ssid = '2312-1'
password = 'onlychina1'
mqtt_server = 'mqtt.roown.com'
#EXAMPLE IP ADDRESS
#mqtt_server = '192.168.1.144'
client_id = ubinascii.hexlify(machine.unique_id())
topic_sub = b'notification'
topic_pub = b'hello'

last_message = 0
message_interval = 5
counter = 0

station = network.WLAN(network.STA_IF)

station.active(True)
station.connect(ssid, password)

while station.isconnected() == False:
  pass

print('Connection successful')
print(station.ifconfig())

上位机发送命令

mosquitto_pub -h mqtt.roown.com -p 21892 -u roown -P Chinaone -t "notification" -m "received"

mqtt 测试服务器

测试服务器

mosquitto_sub -h mqtt.roown.com -p 21892 -u roown -P Chinaone -t "esp"
mosquitto_pub -h mqtt.roown.com -p 21892 -u roown -P Chinaone -t "esp" -m "测试"
ssh pi@192.168.1.15

树莓派安装Mosquitto MQTT服务

https://zhuanlan.zhihu.com/p/359395794

1. 安装Mosquitto MQTT组件

  • 登录树莓派(网线连接)
  • 检查网络连通状态

pi@raspberrypi:~ $ ping www.baidu.com

如果网络不通

Win10找到这个设置界面:

先去掉勾选,确定,再重新如勾选,确定。

再测试:

网通了。

  • 更新apt的资源列表

sudo apt-get update

  • 搜索可安装的MQTT

apt search mqtt

MQTT分为服务器和客户端两部分。有很多MQTT软件包可选,我们选择比较流行的mosquitto。

  • 安装mosquitto 和mosquitto-clients

sudo apt-get install mosquitto mosquitto-clients

说明:

mosquitto – the MQTT broker(MQTT代理,即MQTT服务)

mosquitto-clients – 命令行客户端,在调试时很有用。

  • 查看已经安装的mosquitto软件包

dpkg -l mosquitto

2. 配置Mosquitto

在使用Mosquitto之前,我们需要修改配置文件。配置文件位于/etc/mosquito。

  • 查看配置文件

cat /etc/mosquitto/mosquitto.conf

注释中说:

1) 将本地配置放在/etc/mosquitto/conf.d/目录中。

我们看看/etc/mosquitto/conf.d/目录:

里面有一个说明文件,打开看看:

放置在该目录中的任何扩展名为.conf的文件都会被代理作为配置文件加载,用作本地配置。

2) 有一个完全的配置文件说明在:/usr/share/doc/mosquitto/examples/

  • 复制配置文件mosquitto.conf.gz到/etc/mosquitto/conf.d/目录

sudo cp /usr/share/doc/mosquitto/examples/mosquitto.conf.gz /etc/mosquitto/conf.d/

  • 进入/etc/mosquitto/conf.d/目录
  • 解压mosquitto.conf.gz

sudo gzip -d mosquitto.conf.gz

  • 编辑mosquitto.conf

sudo nano /etc/mosquitto/conf.d/mosquitto.conf

这是一个很大的文件,有800多行,所有的行都被#符号注释掉了。

我们修改下面几处,去掉注释符号,修改默认值:

user mosquitto

max_queued_messages 200

message_size_limit 0

allow_zero_length_clientid true

allow_duplicate_messages false

port 1883

autosave_interval 900

autosave_on_changes false

persistence true

persistence_file mosquitto.db

allow_anonymous false

Password_file /etc/mosquitto/passwd.conf

  • 退回登录时的家目录

3. 生成账号密码

下面两种方法选一种。

  • 密文创建账户

sudo Mosquitto_passwd -c /etc/mosquitto/passwd.conf 用户名

输入两遍密码

我们的用户名为ct

sudo mosquitto_passwd -c /etc/mosquitto/passwd.conf ct

  • 明文创建账户

sudo Mosquitto_passwd -b /etc/mosquitto/passwd.conf 用户名 密码

我们不用明文账户。

4. 测试Mosquitto服务

4.1 查看帮助

mosquitto -h

4.2 测试mosquitto

需要开3个终端。

  • 装载指定配置,启动mosquitto服务

mosquitto -c /etc/mosquitto/mosquitto.conf -v

-v记录所有类型的日志,因为我们在调试。以后正式使用mosquitto就不需要记录日志了,因为会占用存储空间。

上面提示日志文件mosquitto.log的权限不够:

ls -l /var/log/mosquitto/mosquitto.log

修改权限:

sudo chmod 666 /var/log/mosquitto/mosquitto.log

再执行:

mosquitto -c /etc/mosquitto/mosquitto.conf -v

服务运行,终端窗口被占用。

  • 测试publish 和subscribe

再打开两个终端:

1) 一个终端执行:

mosquitto_sub -p 1883 -u ct -P xxxxxx -t “test”

订阅subscribe主题Topic:test,等待接收消息。

2) 另一个终端执行:

mosquitto_pub -p 1883 -u ct -P xxxxxx -t test -m “Hello!”

发布主题为test的消息Hello!

3) 订阅窗口显示接收到的消息

4) 查看日志

sudo cat /var/log/mosquitto/mosquitto.log

5. 正式运行mosquitto服务

  • 重新启动树莓派

sudo reboot

  • 查看正在运行的mosquitto进程

ps -ef | grep mosquitto

mosquitto已经在后台启动。

MQTT参考

MQTT是一个专为IoT设计的OASIS标准的Pub/Sub消息协议,已经被广泛应用在汽车工业、制造业、电信业、石油和天然气业等场景。主要特点:超轻量级(内存开销约为6MB)、传输带宽小、消息可靠传输。

01 基本概念

MQTT 架构的核心组件是代理(Broker)和客户端(Client)。Broker的负责在不同的Client之间分发消息。Client有两种角色:发布者(Publisher)和订阅者(Subscriber)。向Broker发布消息的Client是Publisher,向Broker订阅消息的Client是Subscriber。一个Client可以同时既是Publisher也是Subscriber。Client只与Broker建立连接,Client之间不直接相连。这种的好处是Client之间的通信不要求双方同时在线,即使一方离线,消息也可以临时存储在Broker中,等到Client重新上线,Broker再将消息发送给它。每个消息都有一个主题(Topic),Broker正是根据Topic来决策这条消息应该发送给哪些Subscriber。

Broker能够缓冲暂时无法分发到Client的消息。这个特点很适合网络不稳定的场景,例如IoT。除此之外,为了支持可靠的消息传递,MQTT支持 3 种不同类型QoS的消息:0 – 最多一次(at most once),1 – 至少一次(at least once),2 – 恰好一次(exactly once)。具体下文会介绍。

目前MQTT协议有两个版本:MQTT 3.1.1 和 MQTT 5。大多数商业 MQTT Broker现在都支持 MQTT 5,但许多物联网托管云服务仅支持 MQTT 3.1.1。相比MQTT 3.11,MQTT 5具有更强大的系统和云原生可扩展性。

Topic

在MQTT中,Topic指的一个UTF-8编码的字符串,Broker根据Topic为每个Client过滤它应该获取的消息。每个Topic由一个或多个主题级别构成,正斜杠“/”是主题级别分隔符。下图就是一个Topic的例子,可以看到,它是一个四级的Topic。通过使用“/”,可以让Topic的含义更加清晰和便于理解,下图表达的是“我家一楼客厅的温度”这一主题。MQTT的Topic非常轻量级,Client在发布或者订阅它之前不需要专门创建。Broker会接受每一个符合规则的Topic。

每个Topic必须至少包含一个字符,允许空格(但是不推荐包含空格),大小写敏感(例如“myhome/firstfloor”和“Myhome/firstfloor”是两个不同的Topic)。注意:不要以$符号开头设置Topic,因为以$符号开头的topic保留给Broker的内部统计。

Topic在匹配时支持通配符,MQTT支持两种通配符:单级的通配符“+”,多级的通配符“#”。注意:多级通配符必须作为主题的最后一个字符放置,并在前面加上正斜杠。

单级通配符举例:

多级通配符举例:

定义Topic的几大原则:

  • 首字符不要使用斜杠。这会引入一个不必要的主题级别和零字符,零字符没有任何好处,经常会导致混乱。
  • 不要在主题中使用空格。尽管MQTT不禁止空格,但是为了阅读和调试的方便,请不要使用空格。
  • 保持Topic简短。尽可能使Topic简短,否则可能给小型设备带来额外的开销。
  • 只使用ASCII字符,避免不可打印的字符。不可打印的字符会导致调试困难。
  • 将唯一标识符或ClientID嵌入到主题中。方便识别消息的发送方,便于调试和鉴权。
  • 不要订阅#。接收所有的消息可能会导致Client承受不了巨大的负载,进而导致设备故障。
  • 主题的设置要考虑扩展性。主题设置要便于后续扩展。
  • 使用定义精确的Topic而不要使用定义模糊的Topic。当命名Topic时,尽可能对它们进行区分。

Client

Client指连接Broker的客户端。一个Client可以是Publisher,也可以是Subscriber,还可以两个身份都拥有。是Publisher还是Subscriber主要由Client的行为定义,发布消息的称之为Publisher,订阅消息的称之为Subscriber。

一个MQTT Client可以是任何设备(从微控制器到完整的服务器),只要它运行了MQTT库并且通过网络连上了Broker。

Broker

与Client对应的是Broker,它负责接收所有消息,过滤消息,确定订阅了消息的Client,并将消息发送给这些订阅的Client。除此之外,Broker还要负责管理和保存Client的持久会话的数据、对Client的身份认证和授权等等。

MQTT连接

MQTT协议基于TCP/IP,因此Client和Broker都需要一个TCP/IP协议栈。除此之外,MQTT也支持Websocket协议,当然,Websocket也是基于TCP的。目的是使得浏览器可以使用MQTT协议,因为浏览器无法直接操控TCP会话,但是可以操作Websocket会话。

MQTT连接只会在Client和Broker之间建立。Client之间不会直接建立连接。要创建连接,Client先向Broker发送CONNECT消息,Broker以CONNACK消息和状态代码进行响应。一旦连接建立,Broker将其保持打开,直到Client发送断开连接命令或连接中断。

02 QoS保障

QoS保障是指消息发送方和消息接收方之间(既指消息从Client到Broker,也指消息从Broker到Client),用于定义特定消息的交付保证。消息从Client到Broker的QoS级别,由Client在发送消息时定义。消息从Broker到Client的QoS级别,由Client在订阅过程中定义。MQTT设置了三个级别:

  • At most once (0)
  • At least once (1)
  • Exactly once (2)

At most once

该级别只保证best-effort的消息发送。消息接收方不会确认收到消息,发送方也不会存储和重新发送消息。消息只会被发送方发送一次,称之为“即发即忘”。

At least once

该级别保证消息至少发送一次。消息发送方发送完消息后,会等待消息接收方返回的PUBACK数据包,用来确认消息接收方确实收到了消息。如果消息发送方在一段时间内没有收到消息接收方的PUBACK包,它会再次发送这个消息,直到收到PUBACK包。注意:这可能会导致消息的重复发送,因此需要信息的订阅者自己处理重复消息。

Exactly once

该级别保证消息会且仅会被收到一次。这个级别的QoS是最安全的,也是最慢的,因为它需要两个请求/响应往返。消息发送方在发送完消息后,会等待消息接收方返回的PUBREC包。一旦消息发送方收到PUBREC包,它会丢弃原始的消息,保存收到的PUBREC包,并发送PUBREL数据包给消息接收方和等待返回的PUBCOMP包。消息的接收者直到发送PUBCOMP之后,才会确认一开始收到的消息的ID。这样做的目的是防止处理重复的消息。最终,消息的发送者和接收者都确认了消息已经成功发送。

03 持久会话

在非持久会话中,如果Client在订阅过程中因为种种原因掉线了,那么所有的未被接收的消息都会丢失。为了避免上述问题,Client在与Broker创建连接时,可以设置持久会话,这样Client在重新连上后,掉线期间的消息(QoS 1和QoS 2)将不会丢失并可以被正确获取。

Client在和Broker创建连接时,通过设置cleanSession标志位来告诉Broker创建哪种会话:

  • True:非持久会话
  • False:持久会话

04 保留消息

保留消息指的是retained标志位被置为true的普通消息。Broker会保留最后一条收到的保留消息,这样新订阅的Client可以在它们订阅主题后立刻获得一条消息。

保留消息的主要应用在Client想要在订阅主题后就需要立刻获取消息的场景。如果没有保留消息,Client就需要等待消息发布者发布下一条消息,才能知道消息发布者的状态。由于消息发布者的发布频率是不确定的,在某些特殊场景,Client很可能要等待很久才能获取到第一条消息。

05 遗嘱

Client可以使用遗嘱功能在自己异常离线后通知其他Client。遗嘱消息是一条普通的MQTT消息,带有一个Topic、Retained message标志位、QoS标志位和有效负载。遗嘱消息在Client与Broker创建连接时发送给Broker。Broker会存储遗嘱消息,当发现Client异常离线后,将这条遗嘱消息发送给订阅了遗嘱消息Topic的所有Client。如果Client使用DISCONNECT消息正常断开连接,那么Broker将会丢弃存储的遗嘱消息。

06 MQTT和消息队列(MQ)的区别

MQTT的名字中含有MQ,但是其实与消息队列无关。通常可以看到MQTT与传统消息队列存在以下区别:

  • 消息队列存储消息,直到消息被消费。如果没有消费者消费消息,那么消息会阻塞在队列中。
  • 消息队列中,一个消息只能被一个消费者消费。传统的消息队列,一个队列只能被一个消费者消费。而MQTT中,所有的订阅者都可以得到被订阅主题的消息。
  • 消息队列必须被显式命名和创建。消息队列比Topic要严格的多。队列在使用前,必须用单独的命令进行创建。只有在创建后,队列才能被用来生产和消费消息。MQTT的Topic就相对灵活,可以随时创建。

esp32测试mqtt

import network,time,os
import usocket as socket  # 引用socket模块
from machine import UART
import select,json
from umqtt.simple import MQTTClient
def sub_cb(topic, msg):
        global statemqtt
        print((topic, msg))   #打印收到信息
        if msg == b"on":
            lcdmain.my_text_out("mqtt"+":on",0,32)#单片机显示接收的信息
            statemqtt = 1
        elif msg == b"off":
            lcdmain.my_text_out("mqtt"+":off",0,32)
            statemqtt = 0
        elif msg == b"toggle":
            # LED is inversed, so setting it to current state
            # value will make it toggle
            lcdmain.my_text_out("mqtt"+":tog",0,32)
            statemqtt = 1 - statemqtt
def main():
    c = MQTTClient("umqtt_client", "1.tcp.vip.cpolar.cn",20257)
     #建立一个MQTT客户端
    c.set_callback(sub_cb) #设置回调函数
    c.connect() #建立连接
    c.subscribe(b"mqtt/mypi") #监控ledctl这个通道,接收控制命令

if __name__ == '__main__':
    while True:
      main()

树莓派mqtt的使用

安装mosquitto

sudo apt-get update
sudo apt-get -y upgrade
sudo apt-get -y full-upgrade
sudo apt-get -y install mosquitto mosquitto-clients

修改配置文件

sudo nano /etc/mosquitto/mosquitto.conf

Start the systemd service.

systemctl start mosquitto

Enable the systemd service to run on boot.

systemctl enable mosquitto

安装python库

pip3 install paho-mqtt

sudo nano a.py

import paho.mqtt.client as mqtt
client=mqtt.Client("RPi2")
client.connect("192.168.1.8",port=1883,keepalive=60)
client.publish("mqtt/mypi","Off")

参数说明

# =================================================================
# General configuration
# =================================================================

# 客户端心跳的间隔时间
#retry_interval 20

# 系统状态的刷新时间
#sys_interval 10

# 系统资源的回收时间,0表示尽快处理
#store_clean_interval 10

# 服务进程的PID
#pid_file /var/run/mosquitto.pid

# 服务进程的系统用户
#user mosquitto

# 客户端心跳消息的最大并发数
#max_inflight_messages 10

# 客户端心跳消息缓存队列
#max_queued_messages 100

# 用于设置客户端长连接的过期时间,默认永不过期
#persistent_client_expiration

# =================================================================
# Default listener
# =================================================================

# 服务绑定的IP地址
#bind_address

# 服务绑定的端口号
#port 1883

# 允许的最大连接数,-1表示没有限制
#max_connections -1

# cafile:CA证书文件
# capath:CA证书目录
# certfile:PEM证书文件
# keyfile:PEM密钥文件
#cafile
#capath
#certfile
#keyfile

# 必须提供证书以保证数据安全性
#require_certificate false

# 若require_certificate值为true,use_identity_as_username也必须为true
#use_identity_as_username false

# 启用PSK(Pre-shared-key)支持
#psk_hint

# SSL/TSL加密算法,可以使用“openssl ciphers”命令获取
# as the output of that command.
#ciphers

# =================================================================
# Persistence
# =================================================================

# 消息自动保存的间隔时间
#autosave_interval 1800

# 消息自动保存功能的开关
#autosave_on_changes false

# 持久化功能的开关
persistence true

# 持久化DB文件
#persistence_file mosquitto.db

# 持久化DB文件目录
#persistence_location /var/lib/mosquitto/

# =================================================================
# Logging
# =================================================================

# 4种日志模式:stdout、stderr、syslog、topic
# none 则表示不记日志,此配置可以提升些许性能
log_dest none

# 选择日志的级别(可设置多项)
#log_type error
#log_type warning
#log_type notice
#log_type information

# 是否记录客户端连接信息
#connection_messages true

# 是否记录日志时间
#log_timestamp true

# =================================================================
# Security
# =================================================================

# 客户端ID的前缀限制,可用于保证安全性
#clientid_prefixes

# 允许匿名用户
#allow_anonymous true

# 用户/密码文件,默认格式:username:password
#password_file

# PSK格式密码文件,默认格式:identity:key
#psk_file

# pattern write sensor/%u/data
# ACL权限配置,常用语法如下:
# 用户限制:user <username>
# 话题限制:topic [read|write] <topic>
# 正则限制:pattern write sensor/%u/data
#acl_file

# =================================================================
# Bridges
# =================================================================

# 允许服务之间使用“桥接”模式(可用于分布式部署)
#connection <name>
#address <host>[:<port>]
#topic <topic> [[[out | in | both] qos-level] local-prefix remote-prefix]

# 设置桥接的客户端ID
#clientid

# 桥接断开时,是否清除远程服务器中的消息
#cleansession false

# 是否发布桥接的状态信息
#notifications true

# 设置桥接模式下,消息将会发布到的话题地址
# $SYS/broker/connection/<clientid>/state
#notification_topic

# 设置桥接的keepalive数值
#keepalive_interval 60

# 桥接模式,目前有三种:automatic、lazy、once
#start_type automatic

# 桥接模式automatic的超时时间
#restart_timeout 30

# 桥接模式lazy的超时时间
#idle_timeout 60

# 桥接客户端的用户名
#username

# 桥接客户端的密码
#password

# bridge_cafile:桥接客户端的CA证书文件
# bridge_capath:桥接客户端的CA证书目录
# bridge_certfile:桥接客户端的PEM证书文件
# bridge_keyfile:桥接客户端的PEM密钥文件
#bridge_cafile
#bridge_capath
#bridge_certfile
#bridge_keyfile

收发案例

树莓派(收)

import sys
import os
import time
import paho.mqtt.client as mqtt

sys.path.append(os.path.abspath(os.path.dirname(__file__) + '/' + '..'))
sys.path.append("..")

REPORT_TOPIC = 'mqtt/mypi'  # 主题


def on_connect(client, userdata, flags, rc):
    print('connected to mqtt with resurt code ', rc)
    client.subscribe(REPORT_TOPIC)  # 订阅主题


def on_message(client, userdata, msg):

    message = msg.payload.decode()
    print(message)

def server_conenet(client):
    client.on_connect = on_connect  # 启用订阅模式
    client.on_message = on_message  # 接收消息
    client.connect("1.tcp.vip.cpolar.cn", 20257, 60)  # 链接
    # client.loop_start()   # 以start方式运行,需要启动一个守护线程,让服务端运行,否则会随主线程死亡
    client.loop_forever()  # 以forever方式阻塞运行。


def server_stop(client):
    client.loop_stop()  # 停止服务端
    sys.exit(0)


def server_main():
    client_id = time.strftime('%Y%m%d%H%M%S', time.localtime(time.time()))
    client = mqtt.Client(client_id, transport='tcp')
    server_conenet(client)


if __name__ == '__main__':
    # 启动监听
    server_main()

树莓派(发)

import paho.mqtt.client as mqtt

client = mqtt.Client()
# 参数有 Client(client_id="", clean_session=True, userdata=None, protocol=MQTTv311, transport="tcp")
client.connect("1.tcp.vip.cpolar.cn", 20257, 60)  # 连接服务器,端口为1883,维持心跳为60秒
client.publish('mqtt/mypi', 'test string',1)

esp32使用mqtt

import upip
upip.install('micropython-umqtt.simple')

esp32(发)

from umqtt.simple import MQTTClient
import time

SERVER = '1.tcp.vip.cpolar.cn'
CLIENT_ID = 'PYESPCAR_A0' # 客户端的ID
TOPIC = b'mqtt/mypi' # TOPIC的ID

client = MQTTClient(CLIENT_ID,SERVER,user=None,port=20257,keepalive=60)
client.connect()


while True:
    client.publish(TOPIC, 'helloworld')
    time.sleep(1)

参考

https://mpython.readthedocs.io/en/master/library/mPython/umqtt.simple.html

from umqtt.simple import MQTTClient
import time

SERVER = '1.tcp.vip.cpolar.cn'
CLIENT_ID = 'PYESPCAR_A0' # 客户端的ID
TOPIC = b'mqtt/mypi' # TOPIC的ID

client = MQTTClient(CLIENT_ID,SERVER,user=None,port=20257,keepalive=60)
client.connect()


while True:
#    client.publish(TOPIC, b'你好')
    client.publish(TOPIC,str(time.localtime()))
    time.sleep(1)

收(命令行测试)

mosquitto_sub -h 1.tcp.vip.cpolar.cn -p 20257 -t "mqtt/mypi"

esp32(收/发)

import network
import time
station = network.WLAN(network.STA_IF)
station.active(True)
station.connect("1210", "onlychina")
station.isconnected()

time.sleep(5)


#import dht11
from umqtt.simple import MQTTClient
from machine import Pin

led = Pin(4,Pin.OUT)#led引脚输出模式
client_id='PYESPCAR_A0' #设备的ID
server = '1.tcp.vip.cpolar.cn' #onenet地址
port =20257 #连接的端口
# Publish test messages e.g. with:
# mosquitto_pub -t foo_topic -m hello

# Received messages from subscriptions will be delivered to this callback
c = MQTTClient(client_id, server,port,keepalive=60) #(self, client_id, server, port=0, user=None, password=None, keepalive=0,ssl=False, ssl_params={}):
def sub_cb(topic, msg):
    print((topic, msg))
    msg_str = msg.decode()#消息转换为二进制转换字符串
    if(msg_str == "TurnOn"):
        led.value(1)
        topic_str = topic.decode() #二进制转换字符串,转换"request","response"变成消息
        #b'$sys/449990/pc_esp32/cmd/request/90651f67-14fc-431c-97b7-6321911728ed'
        #b'$sys/449990/pc_esp32/cmd/response/90651f67-14fc-431c-97b7-6321911728ed'
        topic = topic_str.replace("request","response").encode()
        if(led.value()):c.publish(topic,b"light is turn on")
    if(msg_str == "TurnOff"):
        led.value(0)
        topic_str = topic.decode() #二进制转换字符串,转换"request","response"变成消息
        topic = topic_str.replace("request","response").encode()
        if(led.value() == 0):c.publish(topic,b"light is turn off")



def main():   # test server : iot.eclipse.org
    c.set_callback(sub_cb)
    c.connect()
    c.subscribe(b'mqtt/mypi')# subscribe foo_topic tipic
    while True:
        try:#防止dht11读取错误异常退出(leb灯打开后会有超时情况:File "dht.py", line 17, in measure   -->>   OSError: [Errno 116] ETIMEDOUT)
#            _,temperature,Humidity = dht11.dht11(15)#传入引脚号
            #print(temperature,Humidity)
            c.publish(b'mqtt/mypi', "{ 'id': 123,  'dp': { 'temperatrue': 22,'humidity': [{ 'v':" + str(33) +", }]}}")#发送数据
        except OSError:
            print(OSError)
        # Non-blocking wait for message
        c.check_msg()
        # Then need to sleep to avoid 100% CPU usage (in a real
        # app other useful actions would be performed instead)
        time.sleep(6)

    c.disconnect()

if __name__ == "__main__":
    main()

参考链接

https://www.bilibili.com/read/cv12453670

#coding:utf-8
import network
import time
station = network.WLAN(network.STA_IF)
station.active(True)
station.connect("1210", "onlychina")
station.isconnected()

time.sleep(5)


#import dht11
from umqtt.simple import MQTTClient
from machine import Pin

led = Pin(4,Pin.OUT)#led引脚输出模式
client_id='PYESPCAR_A0' #设备的ID
server = '1.tcp.vip.cpolar.cn' #onenet地址
port =20257 #连接的端口
# Publish test messages e.g. with:
# mosquitto_pub -t foo_topic -m hello

# Received messages from subscriptions will be delivered to this callback
c = MQTTClient(client_id, server,port,keepalive=60) #(self, client_id, server, port=0, user=None, password=None, keepalive=0,ssl=False, ssl_params={}):
def sub_cb(topic, msg):
    print((topic, msg))
    msg_str = msg.decode()#消息转换为二进制转换字符串
    if(msg_str == "TurnOn"):
        led.value(1)
        topic_str = topic.decode() #二进制转换字符串,转换"request","response"变成消息
        #b'$sys/449990/pc_esp32/cmd/request/90651f67-14fc-431c-97b7-6321911728ed'
        #b'$sys/449990/pc_esp32/cmd/response/90651f67-14fc-431c-97b7-6321911728ed'
        topic = topic_str.replace("request","response").encode()
        if(led.value()):c.publish(topic,b"开灯")
    if(msg_str == "TurnOff"):
        led.value(0)
        topic_str = topic.decode() #二进制转换字符串,转换"request","response"变成消息
        topic = topic_str.replace("request","response").encode()
        if(led.value() == 0):c.publish(topic,b"关灯")



def main():   # test server : iot.eclipse.org
    c.set_callback(sub_cb)
    c.connect()
    c.subscribe(b'mqtt/mypi')# subscribe foo_topic tipic
    while True:
        try:#防止dht11读取错误异常退出(leb灯打开后会有超时情况:File "dht.py", line 17, in measure   -->>   OSError: [Errno 116] ETIMEDOUT)
#            _,temperature,Humidity = dht11.dht11(15)#传入引脚号
            #print(temperature,Humidity)
            c.publish(b'mqtt/mypi','TurnOff')#发送数据
        except OSError:
            print(OSError)
        # Non-blocking wait for message
        c.check_msg()
        # Then need to sleep to avoid 100% CPU usage (in a real
        # app other useful actions would be performed instead)
        time.sleep(6)

    c.disconnect()

if __name__ == "__main__":
    main()

带断线重连功能的mqtt(umqttsimple.py)

try:
    import usocket as socket
except:
    import socket
import ustruct as struct
from ubinascii import hexlify

class MQTTException(Exception):
    pass

class MQTTClient:

    def __init__(self, client_id, server, port=0, user=None, password=None, keepalive=0,
                 ssl=False, ssl_params={}):
        if port == 0:
            port = 8883 if ssl else 1883
        self.client_id = client_id
        self.sock = None
        self.server = server
        self.port = port
        self.ssl = ssl
        self.ssl_params = ssl_params
        self.pid = 0
        self.cb = None
        self.user = user
        self.pswd = password
        self.keepalive = keepalive
        self.lw_topic = None
        self.lw_msg = None
        self.lw_qos = 0
        self.lw_retain = False

    def _send_str(self, s):
        self.sock.write(struct.pack("!H", len(s)))
        self.sock.write(s)

    def _recv_len(self):
        n = 0
        sh = 0
        while 1:
            b = self.sock.read(1)[0]
            n |= (b & 0x7f) << sh
            if not b & 0x80:
                return n
            sh += 7

    def set_callback(self, f):
        self.cb = f

    def set_last_will(self, topic, msg, retain=False, qos=0):
        assert 0 <= qos <= 2
        assert topic
        self.lw_topic = topic
        self.lw_msg = msg
        self.lw_qos = qos
        self.lw_retain = retain

    def connect(self, clean_session=True):
        self.sock = socket.socket()
        addr = socket.getaddrinfo(self.server, self.port)[0][-1]
        self.sock.connect(addr)
        if self.ssl:
            import ussl
            self.sock = ussl.wrap_socket(self.sock, **self.ssl_params)
        premsg = bytearray(b"\x10\0\0\0\0\0")
        msg = bytearray(b"\x04MQTT\x04\x02\0\0")

        sz = 10 + 2 + len(self.client_id)
        msg[6] = clean_session << 1
        if self.user is not None:
            sz += 2 + len(self.user) + 2 + len(self.pswd)
            msg[6] |= 0xC0
        if self.keepalive:
            assert self.keepalive < 65536
            msg[7] |= self.keepalive >> 8
            msg[8] |= self.keepalive & 0x00FF
        if self.lw_topic:
            sz += 2 + len(self.lw_topic) + 2 + len(self.lw_msg)
            msg[6] |= 0x4 | (self.lw_qos & 0x1) << 3 | (self.lw_qos & 0x2) << 3
            msg[6] |= self.lw_retain << 5

        i = 1
        while sz > 0x7f:
            premsg[i] = (sz & 0x7f) | 0x80
            sz >>= 7
            i += 1
        premsg[i] = sz

        self.sock.write(premsg, i + 2)
        self.sock.write(msg)
        #print(hex(len(msg)), hexlify(msg, ":"))
        self._send_str(self.client_id)
        if self.lw_topic:
            self._send_str(self.lw_topic)
            self._send_str(self.lw_msg)
        if self.user is not None:
            self._send_str(self.user)
            self._send_str(self.pswd)
        resp = self.sock.read(4)
        assert resp[0] == 0x20 and resp[1] == 0x02
        if resp[3] != 0:
            raise MQTTException(resp[3])
        return resp[2] & 1

    def disconnect(self):
        self.sock.write(b"\xe0\0")
        self.sock.close()

    def ping(self):
        self.sock.write(b"\xc0\0")

    def publish(self, topic, msg, retain=False, qos=0):
        pkt = bytearray(b"\x30\0\0\0")
        pkt[0] |= qos << 1 | retain
        sz = 2 + len(topic) + len(msg)
        if qos > 0:
            sz += 2
        assert sz < 2097152
        i = 1
        while sz > 0x7f:
            pkt[i] = (sz & 0x7f) | 0x80
            sz >>= 7
            i += 1
        pkt[i] = sz
        #print(hex(len(pkt)), hexlify(pkt, ":"))
        self.sock.write(pkt, i + 1)
        self._send_str(topic)
        if qos > 0:
            self.pid += 1
            pid = self.pid
            struct.pack_into("!H", pkt, 0, pid)
            self.sock.write(pkt, 2)
        self.sock.write(msg)
        if qos == 1:
            while 1:
                op = self.wait_msg()
                if op == 0x40:
                    sz = self.sock.read(1)
                    assert sz == b"\x02"
                    rcv_pid = self.sock.read(2)
                    rcv_pid = rcv_pid[0] << 8 | rcv_pid[1]
                    if pid == rcv_pid:
                        return
        elif qos == 2:
            assert 0

    def subscribe(self, topic, qos=0):
        assert self.cb is not None, "Subscribe callback is not set"
        pkt = bytearray(b"\x82\0\0\0")
        self.pid += 1
        struct.pack_into("!BH", pkt, 1, 2 + 2 + len(topic) + 1, self.pid)
        #print(hex(len(pkt)), hexlify(pkt, ":"))
        self.sock.write(pkt)
        self._send_str(topic)
        self.sock.write(qos.to_bytes(1, "little"))
        while 1:
            op = self.wait_msg()
            if op == 0x90:
                resp = self.sock.read(4)
                #print(resp)
                assert resp[1] == pkt[2] and resp[2] == pkt[3]
                if resp[3] == 0x80:
                    raise MQTTException(resp[3])
                return

    # Wait for a single incoming MQTT message and process it.
    # Subscribed messages are delivered to a callback previously
    # set by .set_callback() method. Other (internal) MQTT
    # messages processed internally.
    def wait_msg(self):
        res = self.sock.read(1)
        self.sock.setblocking(True)
        if res is None:
            return None
        if res == b"":
            raise OSError(-1)
        if res == b"\xd0":  # PINGRESP
            sz = self.sock.read(1)[0]
            assert sz == 0
            return None
        op = res[0]
        if op & 0xf0 != 0x30:
            return op
        sz = self._recv_len()
        topic_len = self.sock.read(2)
        topic_len = (topic_len[0] << 8) | topic_len[1]
        topic = self.sock.read(topic_len)
        sz -= topic_len + 2
        if op & 6:
            pid = self.sock.read(2)
            pid = pid[0] << 8 | pid[1]
            sz -= 2
        msg = self.sock.read(sz)
        self.cb(topic, msg)
        if op & 6 == 2:
            pkt = bytearray(b"\x40\x02\0\0")
            struct.pack_into("!H", pkt, 2, pid)
            self.sock.write(pkt)
        elif op & 6 == 4:
            assert 0

    # Checks whether a pending message from server is available.
    # If not, returns immediately with None. Otherwise, does
    # the same processing as wait_msg.
    def check_msg(self):
        self.sock.setblocking(False)
        return self.wait_msg()

主程序(main.py)

# Complete project details at https://RandomNerdTutorials.com/micropython-mqtt-publish-ds18b10-esp32-esp8266/
import time
from umqttsimple import MQTTClient
import ubinascii
import machine
import micropython
import network
import esp
from machine import Pin
import onewire
import ds18x20
esp.osdebug(None)
import gc
gc.collect()

ssid = '1210'
password = 'onlychina'
mqtt_server = '1.tcp.vip.cpolar.cn'
#EXAMPLE IP ADDRESS
#mqtt_server = '192.168.1.106'

client_id = ubinascii.hexlify(machine.unique_id())

topic_pub_temp = b'esp/ds18b20/temperature'

last_message = 0
message_interval = 5

station = network.WLAN(network.STA_IF)

station.active(True)
station.connect(ssid, password)

while station.isconnected() == False:
  pass

print('Connection successful')

ds_pin = machine.Pin(4)
ds_sensor = ds18x20.DS18X20(onewire.OneWire(ds_pin))

def connect_mqtt():
  global client_id, mqtt_server
  client = MQTTClient(client_id, mqtt_server,port=20257,keepalive=60)
  #client = MQTTClient(client_id, mqtt_server, user=your_username, password=your_password)
  client.connect()
  print('Connected to %s MQTT broker' % (mqtt_server))
  return client

def restart_and_reconnect():
  print('Failed to connect to MQTT broker. Reconnecting...')
  time.sleep(10)
  machine.reset()

def read_sensor():
  try:
    roms = ds_sensor.scan()
    ds_sensor.convert_temp()
    time.sleep_ms(750)
    for rom in roms: 
      temp = ds_sensor.read_temp(rom)
      # uncomment for Fahrenheit
      temp = temp * (9/5) + 32.0
    if (isinstance(temp, float) or (isinstance(temp, int))):
      temp = (b'{0:3.1f},'.format(temp))
      return temp
    else:
      return('Invalid sensor readings.')
  except OSError as e:
    return('Failed to read sensor.')

try:
  client = connect_mqtt()
except OSError as e:
  restart_and_reconnect()

while True:
  try:
    if (time.time() - last_message) > message_interval:
#      temp = read_sensor()  #zjg
      temp = str(time.localtime())
      print(temp)
      client.publish(topic_pub_temp, temp)
      last_message = time.time()
  except OSError as e:
    restart_and_reconnect()

同步网络时间

#coding:utf-8
# Complete project details at https://RandomNerdTutorials.com/micropython-mqtt-publish-ds18b10-esp32-esp8266/
import time,ntptime
from umqttsimple import MQTTClient
import ubinascii
import machine
import micropython
import network
import esp
from machine import Pin,RTC
import onewire
import ds18x20

rtc = RTC()

led1=Pin(12,Pin.OUT)

def set_ntptime():
  print("正在从NTP时间服务器获取时间,并校时到ESP8266/ESP32中(多次网络校时会出错OSError: -202,请断开串口连接再重试即可):")  
  print("  A.网络校时前本地时间:%s" %str(time.localtime()))  
  ntptime.NTP_DELTA = 3155644800    # 设置  UTC+8偏移时间(秒),不设置就是UTC0
  ntptime.host = 'ntp1.aliyun.com'  # 可选ntp服务器为阿里云服务器,默认是"pool.ntp.org"
  ntptime.settime()                 # 从NTP服务器获取时间,并写入到ESP8266/ESP32设备中,到这就已经设置好了
  print("  B.网络校时后本地时间:%s" %str(time.localtime()))


def sync_ntp():
     ntptime.NTP_DELTA = 3155644800   # 可选 UTC+8偏移时间(秒),不设置就是UTC0
     ntptime.host = 'ntp1.aliyun.com'  # 可选,ntp服务器,默认是"pool.ntp.org"
     ntptime.settime()   # 修改设备时间,到这就已经设置好了

esp.osdebug(None)
import gc
gc.collect()

ssid = '1210'
password = 'onlychina'
mqtt_server = 'mqtt.begair.com'
#EXAMPLE IP ADDRESS
#mqtt_server = '192.168.1.106'

client_id = ubinascii.hexlify(machine.unique_id())

topic_pub_temp = b'esp1'

last_message = 0
message_interval = 5

station = network.WLAN(network.STA_IF)

station.active(True)
station.connect(ssid, password)

while station.isconnected() == False:
  pass

print('Connection successful')

ds_pin = machine.Pin(4)
ds_sensor = ds18x20.DS18X20(onewire.OneWire(ds_pin))

def connect_mqtt():
  global client_id, mqtt_server
  client = MQTTClient(client_id, mqtt_server,port=20257,keepalive=60)
  #client = MQTTClient(client_id, mqtt_server, user=your_username, password=your_password)
  client.connect()
  print('Connected to %s MQTT broker' % (mqtt_server))
  return client

def restart_and_reconnect():
  print('Failed to connect to MQTT broker. Reconnecting...')
  time.sleep(10)
  machine.reset()

def read_sensor():
  try:
    roms = ds_sensor.scan()
    ds_sensor.convert_temp()
    time.sleep_ms(750)
    for rom in roms: 
      temp = ds_sensor.read_temp(rom)
      # uncomment for Fahrenheit
      temp = temp * (9/5) + 32.0
    if (isinstance(temp, float) or (isinstance(temp, int))):
      temp = (b'{0:3.1f},'.format(temp))
      return temp
    else:
      return('Invalid sensor readings.')
  except OSError as e:
    return('Failed to read sensor.')

# 同步时间
def sync_ntp():
     ntptime.NTP_DELTA = 3155644800   # 可选 UTC+8偏移时间(秒),不设置就是UTC0
     ntptime.host = 'ntp1.aliyun.com'  # 可选,ntp服务器,默认是"pool.ntp.org"
     try:
         ntptime.settime()   # 修改设备时间,到这就已经设置好了
     except:
         for i in range(6):
            led1.value(1)              #turn off 0是亮
            time.sleep(0.1)
            led1.value(0)             
            time.sleep(0.1)
         print('同步失败')



try:
  client = connect_mqtt()
except OSError as e:
  restart_and_reconnect()

while True:
    for i in range(5):
        sync_ntp()
        time.sleep(1)
    while True:
        dt=time.localtime()
        try:
            if (time.time() - last_message) > message_interval:
    #      temp = read_sensor()  #zjg
                temp = str(dt)
                print(temp)
                client.publish(topic_pub_temp, b'真可以了')
                client.publish(topic_pub_temp, temp)
                last_message = time.time()
        except OSError as e:
            restart_and_reconnect()



带有账号权限的收发

#coding:utf-8
# Complete project details at https://RandomNerdTutorials.com/micropython-mqtt-publish-ds18b10-esp32-esp8266/
import time,ntptime
from umqttsimple import MQTTClient
import ubinascii
import machine
import micropython
import network
import esp
from machine import Pin,RTC
import onewire
import ds18x20

rtc = RTC()

led1=Pin(12,Pin.OUT)

def set_ntptime():
  print("正在从NTP时间服务器获取时间,并校时到ESP8266/ESP32中(多次网络校时会出错OSError: -202,请断开串口连接再重试即可):")  
  print("  A.网络校时前本地时间:%s" %str(time.localtime()))  
  ntptime.NTP_DELTA = 3155644800    # 设置  UTC+8偏移时间(秒),不设置就是UTC0
  ntptime.host = 'ntp1.aliyun.com'  # 可选ntp服务器为阿里云服务器,默认是"pool.ntp.org"
  ntptime.settime()                 # 从NTP服务器获取时间,并写入到ESP8266/ESP32设备中,到这就已经设置好了
  print("  B.网络校时后本地时间:%s" %str(time.localtime()))


esp.osdebug(None)
import gc
gc.collect()

ssid = '1210'
password = 'onlychina'
mqtt_server = 'mqtt.begair.com'
#EXAMPLE IP ADDRESS
#mqtt_server = '192.168.1.106'

client_id = ubinascii.hexlify(machine.unique_id())

topic_pub_temp = b'begair'

last_message = 0
message_interval = 5

station = network.WLAN(network.STA_IF)

station.active(True)
station.connect(ssid, password)

while station.isconnected() == False:
  pass

print('Connection successful')

ds_pin = machine.Pin(4)
ds_sensor = ds18x20.DS18X20(onewire.OneWire(ds_pin))

def connect_mqtt():
  global client_id, mqtt_server
  client = MQTTClient(client_id, mqtt_server,port=20257,user='getair',password='raspberry',keepalive=60)
  #client = MQTTClient(client_id, mqtt_server, user=your_username, password=your_password)
  client.connect()
  print('Connected to %s MQTT broker' % (mqtt_server))
  return client

def restart_and_reconnect():
  print('Failed to connect to MQTT broker. Reconnecting...')
  time.sleep(10)
  machine.reset()

def read_sensor():
  try:
    roms = ds_sensor.scan()
    ds_sensor.convert_temp()
    time.sleep_ms(750)
    for rom in roms: 
      temp = ds_sensor.read_temp(rom)
      # uncomment for Fahrenheit
      temp = temp * (9/5) + 32.0
    if (isinstance(temp, float) or (isinstance(temp, int))):
      temp = (b'{0:3.1f},'.format(temp))
      return temp
    else:
      return('Invalid sensor readings.')
  except OSError as e:
    return('Failed to read sensor.')

# 同步时间
def sync_ntp():
     ntptime.NTP_DELTA = 3155644800   # 可选 UTC+8偏移时间(秒),不设置就是UTC0
     ntptime.host = 'ntp1.aliyun.com'  # 可选,ntp服务器,默认是"pool.ntp.org"
     try:
         ntptime.settime()   # 修改设备时间,到这就已经设置好了
     except:
         for i in range(6):
            led1.value(1)              #turn off 0是亮
            time.sleep(0.1)
            led1.value(0)             
            time.sleep(0.1)
         print('同步失败')



try:
  client = connect_mqtt()
except OSError as e:
  restart_and_reconnect()

while True:
    for i in range(5):
        sync_ntp()
        time.sleep(1)
    while True:
        dt=time.localtime()
        try:
            if (time.time() - last_message) > message_interval:
    #      temp = read_sensor()  #zjg
                temp = str(dt)
                print(temp)
                client.publish(topic_pub_temp, b'真可以了')
                client.publish(topic_pub_temp, temp)
                last_message = time.time()
        except OSError as e:
            restart_and_reconnect()

MQTT参考

https://zhuanlan.zhihu.com/p/383708520

读取Pin脚状态并发送

#coding:utf-8
# Complete project details at https://RandomNerdTutorials.com/micropython-mqtt-publish-ds18b10-esp32-esp8266/
import time,ntptime
from umqttsimple import MQTTClient
import ubinascii
import machine
import micropython
import network
import esp
from machine import Pin,RTC
import onewire
import ds18x20

rtc = RTC()


led = machine.Pin(13,machine.Pin.OUT)  #定义led为输出
sw = machine.Pin(0,machine.Pin.IN)    #定义sw为输入


led1=Pin(12,Pin.OUT)

def set_ntptime():
  print("正在从NTP时间服务器获取时间,并校时到ESP8266/ESP32中(多次网络校时会出错OSError: -202,请断开串口连接再重试即可):")  
  print("  A.网络校时前本地时间:%s" %str(time.localtime()))  
  ntptime.NTP_DELTA = 3155644800    # 设置  UTC+8偏移时间(秒),不设置就是UTC0
  ntptime.host = 'ntp1.aliyun.com'  # 可选ntp服务器为阿里云服务器,默认是"pool.ntp.org"
  ntptime.settime()                 # 从NTP服务器获取时间,并写入到ESP8266/ESP32设备中,到这就已经设置好了
  print("  B.网络校时后本地时间:%s" %str(time.localtime()))


esp.osdebug(None)
import gc
gc.collect()

ssid = '1210'
password = 'onlychina'
mqtt_server = 'mqtt.begair.com'
#EXAMPLE IP ADDRESS
#mqtt_server = '192.168.1.106'

client_id = ubinascii.hexlify(machine.unique_id())

topic_pub_temp = b'beg'

last_message = 0
message_interval = 5

station = network.WLAN(network.STA_IF)

station.active(True)
station.connect(ssid, password)

while station.isconnected() == False:
  pass

print('Connection successful')

ds_pin = machine.Pin(4)
ds_sensor = ds18x20.DS18X20(onewire.OneWire(ds_pin))

def connect_mqtt():
  global client_id, mqtt_server
  client = MQTTClient(client_id, mqtt_server,port=20257,user='getair',password='raspberry',keepalive=60)
  #client = MQTTClient(client_id, mqtt_server, user=your_username, password=your_password)
  client.connect()
  print('Connected to %s MQTT broker' % (mqtt_server))
  return client

def restart_and_reconnect():
  print('Failed to connect to MQTT broker. Reconnecting...')
  time.sleep(10)
  machine.reset()

def read_sensor():
  try:
    roms = ds_sensor.scan()
    ds_sensor.convert_temp()
    time.sleep_ms(750)
    for rom in roms: 
      temp = ds_sensor.read_temp(rom)
      # uncomment for Fahrenheit
      temp = temp * (9/5) + 32.0
    if (isinstance(temp, float) or (isinstance(temp, int))):
      temp = (b'{0:3.1f},'.format(temp))
      return temp
    else:
      return('Invalid sensor readings.')
  except OSError as e:
    return('Failed to read sensor.')

# 同步时间
def sync_ntp():
     ntptime.NTP_DELTA = 3155644800   # 可选 UTC+8偏移时间(秒),不设置就是UTC0
     ntptime.host = 'ntp1.aliyun.com'  # 可选,ntp服务器,默认是"pool.ntp.org"
     try:
         ntptime.settime()   # 修改设备时间,到这就已经设置好了
     except:
         for i in range(6):
            led1.value(1)              #turn off 0是亮
            time.sleep(0.1)
            led1.value(0)             
            time.sleep(0.1)
         print('同步失败')



try:
  client = connect_mqtt()
except OSError as e:
  restart_and_reconnect()

while True:
    for i in range(5):
        sync_ntp()
        time.sleep(1)
    while True:
        sw = machine.Pin(0,machine.Pin.IN)    #定义sw为输入
        dt=time.localtime()
        try:
            if (time.time() - last_message) > message_interval:
    #      temp = read_sensor()  #zjg
                temp = str(dt)
    #                print(temp)
                if (sw.value() == 1): 
                    client.publish(topic_pub_temp, b'真可以了')
                    led.on()
                else:
                    client.publish(topic_pub_temp, temp)
                    led.off()
                last_message = time.time()
        except OSError as e:
            restart_and_reconnect()

自动联网的mqtt传感器

#coding:utf-8
# Complete project details at https://RandomNerdTutorials.com/micropython-mqtt-publish-ds18b10-esp32-esp8266/
import time,ntptime
from umqttsimple import MQTTClient
import ubinascii
import machine
import micropython
import network
import esp
from machine import Pin,RTC
import onewire
import ds18x20
import wifimgr


rtc = RTC()


led = machine.Pin(13,machine.Pin.OUT)  #定义led为输出
sw = machine.Pin(0,machine.Pin.IN)    #定义sw为输入


led1=Pin(12,Pin.OUT)

def set_ntptime():
  print("正在从NTP时间服务器获取时间,并校时到ESP8266/ESP32中(多次网络校时会出错OSError: -202,请断开串口连接再重试即可):")  
  print("  A.网络校时前本地时间:%s" %str(time.localtime()))  
  ntptime.NTP_DELTA = 3155644800    # 设置  UTC+8偏移时间(秒),不设置就是UTC0
  ntptime.host = 'ntp1.aliyun.com'  # 可选ntp服务器为阿里云服务器,默认是"pool.ntp.org"
  ntptime.settime()                 # 从NTP服务器获取时间,并写入到ESP8266/ESP32设备中,到这就已经设置好了
  print("  B.网络校时后本地时间:%s" %str(time.localtime()))


esp.osdebug(None)
import gc
gc.collect()

mqtt_server = 'mqtt.roown.com'
#EXAMPLE IP ADDRESS
#mqtt_server = '192.168.1.106'

client_id = ubinascii.hexlify(machine.unique_id())

topic_pub_temp = b'beg'

last_message = 0
message_interval = 0.002

led1.value(1)
try:
    wlan = wifimgr.get_connection()
    if wlan is None:
        print("Could not initialize the network connection.")
    led1.value(1)
    time.sleep(1)
    led1.value(0)
    print('Connection successful')
except:
    print('连接 wifi 失败')
    machine.reset()    
led1.value(1)


ds_pin = machine.Pin(4)
ds_sensor = ds18x20.DS18X20(onewire.OneWire(ds_pin))

def connect_mqtt():
  global client_id, mqtt_server
  client = MQTTClient(client_id, mqtt_server,port=21892,user='roown',password='Chinaone',keepalive=60)
  #client = MQTTClient(client_id, mqtt_server, user=your_username, password=your_password)
  client.connect()
  print('Connected to %s MQTT broker' % (mqtt_server))
  return client

def restart_and_reconnect():
  print('Failed to connect to MQTT broker. Reconnecting...')
  time.sleep(10)
  machine.reset()

def read_sensor():
  try:
    roms = ds_sensor.scan()
    ds_sensor.convert_temp()
    time.sleep_ms(750)
    for rom in roms: 
      temp = ds_sensor.read_temp(rom)
      # uncomment for Fahrenheit
      temp = temp * (9/5) + 32.0
    if (isinstance(temp, float) or (isinstance(temp, int))):
      temp = (b'{0:3.1f},'.format(temp))
      return temp
    else:
      return('Invalid sensor readings.')
  except OSError as e:
    return('Failed to read sensor.')

# 同步时间
def sync_ntp():
     ntptime.NTP_DELTA = 3155644800   # 可选 UTC+8偏移时间(秒),不设置就是UTC0
     ntptime.host = 'ntp1.aliyun.com'  # 可选,ntp服务器,默认是"pool.ntp.org"
     try:
         ntptime.settime()   # 修改设备时间,到这就已经设置好了
     except:
         for i in range(6):
            led1.value(1)              #turn off 0是亮
            time.sleep(0.1)
            led1.value(0)             
            time.sleep(0.1)
         print('同步失败')



try:
  client = connect_mqtt()
except OSError as e:
  restart_and_reconnect()

while True:
    for i in range(5):
        sync_ntp()
        time.sleep(1)
    while True:
        sw = machine.Pin(0,machine.Pin.IN)    #定义sw为输入
        dt=time.localtime()
        ws=sw.value()
        try:
            if (time.time() - last_message) > message_interval:  #zjg
    #      temp = read_sensor()  #zjg
                temp = str(dt)
    #                print(temp)
                if (ws == 1):
                    led.on()
                    client.publish(topic_pub_temp, b'真可以了')
                else:
                    led.off()
                    client.publish(topic_pub_temp, temp)
                last_message = time.time()
        except OSError as e:
            restart_and_reconnect()