前言
物联网简介
在我们日程生活中,经常听到物联网,IOT这些新名词。实际物联网的英文缩写就是IOT(Internet of things)。物联网顾名思义就是物物相连的网络。不光人能用手机上网,各种物体借助网络模块也能连上云端进行数据交换,后面为了叙述方便物联网直接称为IOT。
MQTT是什么
学习IOT之前,首先我们学习下理论基础,IOT通讯之间是有协议的,我们的编程核心思想也是基于这套协议的用法——MQTT。MQTT是IBM(对,就是那个弄电脑那个)针对物联网实现的一套通讯协议。MQTT全称不用记,太长反正我也是记不住。只需要记住它是用在IOT上的最通用协议就行了。包括小米其他多物网公司都是用这套协议去通讯。 MQTT核心采用订阅/发布模式,为推送而生。
- MQTT物理模型
- 首先物联网肯定有一台服务器,服务器的作用就是接收数据,处理数据,分发数据
- 多个联网的设备。它们的作用就是给服务器发送数据,或者接收服务器的数据
编程简述
如果你已经明白以上关于物联网mqtt的理论基础,我们对应将其翻译成代码即可。一定会涉及的几个步骤如下:
- 连接服务器
- 订阅话题
- 向对应的话题推送消息或从回应话题接受消息
示例1 - 推送/接收消息
操作准备
- KittenCode下应切换到 Python3模式
- 新建一个新的项目文件,这里我们以mqtt01.py为例子
保证你的KittenCode版本为1.08及以上(新增物联网按钮),如果不是 请到该处重新安装
- 点击界面右上角【物联网】按钮
:::info
- 首次使用需要注册Zone账号,点击【Zone】
- 完成注册后重新登陆
:::
- 成功登入IoT平台控制面板,按照以下步骤先完成话题的创建
- 点击 添加话题按钮 申请独有的话题(话题必须为英文字符串,名称不限制,且全服务器唯一),建议以
/
起头
- 点击 添加话题按钮 申请独有的话题(话题必须为英文字符串,名称不限制,且全服务器唯一),建议以
- 关于登录用户名和密码不建议填写
Topic的名称不要与案例中一样,请自行创建独特的名称
代码编写
import paho.mqtt.client as mqtt
client = mqtt.Client(client_id=”YourName”)
设置账号名和密码,如果需要的话
client.username_pw_set(“username”, “passWord”)
def on_connect(client, userdata, flags, rc): print(“Connected with result code “+str(rc)) client.subscribe(“/test_CC”)
def on_message(sender, userdata, msg): print(msg.topic+” “+str(msg.payload))
client.on_connect = on_connect client.on_message = on_message
client.connect(‘iot.kittenbot.cn’, 1883) client.loop_start()
while True: a = input() if a == ‘exit’: sys.exit(0) else: client.publish(“/test_CC”, a)
2. **话题推送:**在终端中输入要发送给话题的消息,如内容hello CC后,按回车键发送
3. 切换到IoT服务器页面,点击刷新按钮并点选左侧话题,在数据显示部分可以看到这条新收到的消息,说明推送消息成功了~

4. **话题接收:**IoT服务器端,点击**_连接按钮_**,并向它发送 "OKOK",看下KittenCode是否能收到

5. 切换到KittenCode的终端可以看到从话题接收到了消息**“OKOK”**,说明话题接收成功了!

<a name="EtPDA"></a>
### 代码详解
- 在代码中先引入库 **paho.mqtt.client** ,之后创建一个mqtt客户端实例 **client **
- client_id:你的设备在服务器显示的名称。如上面我用的client_id是YourName,因此在IOT的服务器就可以看到对应消息是YourName这个设备发出的(类比群聊的概念)
> 如果你在服务器申请话题是设置了私有登录用户名和密码,这里你需要将
> # client.username_pw_set("username", "passWord") 中的 username 和 passWord 填写好
> 但案例中我们不建议去设置私有化
```python
import paho.mqtt.client as mqtt
client = mqtt.Client(client_id="YourName")
# 设置账号名和密码,如果需要的话
# client.username_pw_set("username", "passWord")
- 注册客户端的各种回调函数,其中在与服务器连接成功后我们订阅了一个话题 /test_topic 。并且注册了当接收到消息的回调函数 on_message,其中msg参数是个字典类型,包含了topic和话题的内容。 ```python def on_connect(client, userdata, flags, rc): print(“Connected with result code “+str(rc)) client.subscribe(“/test_topic”)
def on_message(sender, userdata, msg): print(msg.topic+” “+str(msg.payload))
client.on_connect = on_connect client.on_message = on_message
- 接下来我们就要连接mqtt服务器(Broker),这里以小喵家的iot服务器[iot.kittenbot.cn:1883]为例子
- **connect **需要传入的参数:mqtt服务器ip, 端口号(一般是默认的不填也行)
- 连接后还需要使用 **loop_start** 函数启动客户端,此时python3内部启动一个线程监听mqtt的协议和通讯,当有任何消息或事件过来时,我们前面设置的回调函数 **on_message** 将会被调用
```python
client.connect('iot.kittenbot.cn', 1883)
client.loop_start()
- 最后我们做个循环 input() 读取用户的输入,并将其发布到话题中。如果用户输入的 exit 则退出程序
while True:
a = input()
if a == 'exit':
sys.exit(0)
else:
client.publish("/test_topic", a)
示例2 - 推送喵比特温度
操作准备
这个案例涉及到与硬件的交互,需要先连接喵比特硬件,不清楚的可以查看前篇教程 - Python3硬件互动案例
效果:将喵比特检测到的温度值推送到IoT服务器上
与喵比特硬件交互必不可少的库
import time from meowbit import * board = MeowBit() board.connect()
client = mqtt.Client(client_id=”YourName”)
设置账号名和密码,如果需要的话
client.username_pw_set(“username”, “passWord”)
def on_connect(client, userdata, flags, rc): print(“Connected with result code “+str(rc)) client.subscribe(“/test_CC”)
def on_message(sender, userdata, msg): print(msg.topic+” “+str(msg.payload))
client.on_connect = on_connect client.on_message = on_message
client.connect(‘iot.kittenbot.cn’, 1883) client.loop_start()
每隔5秒向话题推送温度,温度值即board.sensor.getTemp()
while True: client.publish(“/test_CC”, board.sensor.getTemp()) time.sleep(5)
2. IoT平台效果

<a name="SFnNc"></a>
## 示例3 - 远程点亮喵比特的LED
<a name="ay0Sj"></a>
### 操作准备
> 这个案例涉及到与硬件的交互,需要先连接喵比特硬件,不清楚的可以查看前篇教程 -[ Python3硬件互动案例](https://www.yuque.com/kittenbot/vozgi0/cxhk32)
效果:在 **示例2 **的基础上,根据** 示例1 **增加从IoT服务器对喵比特发送消息,可以控制喵比特LED的亮灭
1. 复制下面代码到KittenCode,并点击**_ 运行按钮_**
```python
# mqtt01.py
import paho.mqtt.client as mqtt
# 与喵比特硬件交互必不可少的库
import time
from meowbit import *
board = MeowBit()
board.connect()
client = mqtt.Client(client_id="YourName")
# 设置账号名和密码,如果需要的话
# client.username_pw_set("username", "passWord")
def on_connect(client, userdata, flags, rc):
print("Connected with result code "+str(rc))
client.subscribe("/test_CC")
def on_message(sender, userdata, msg):
a=str(msg.payload,'UTF-8')
print(msg.topic+" "+a)
if(a=='ON'):
print('led on')
# board.led1.on()
board.screen.fill((255,255,255))
if(a=='OFF'):
print('led off')
# board.led1.off()
board.screen.fill(0)
client.on_connect = on_connect
client.on_message = on_message
client.connect('iot.kittenbot.cn', 1883)
client.loop_start()
# 每隔5秒向话题推送温度,温度值即board.sensor.getTemp()
while True:
client.publish("/test_CC", board.sensor.getTemp())
time.sleep(5)
综合示例 - 智能物联网教室
操作准备
智能教室的硬件准备:
- 风扇*1
- 窗(舵机*1)
- 门(Geekservo 2KG舵机*1)
智能教室的工作目标:
- 检测温度
- 检测湿度
- 检测是否有下雨(雨滴传感器)
- 并将3个数据自动推送到物联网服务器上
项目部件:发挥大家的创意,首先搭建出以下3样东西
- 智能风扇:可以根据温度自动控制(气温高了,自动开风扇),也可以物联网进行控制
- 智能门:可以物联网进行控制
- 智能窗:可以根据雨滴传感器自控控制(下雨了,自动关窗),也可以物联网进行控制
- 硬件接线:
- 智能风扇 => 接在Robotbit的M1A接口上(可以接M1A、M1B、M2A、M2B)
- 智能门舵机 => 接在Robotbit的舵机接口S2上(可以接S1-S8)
- 智能窗舵机 => 接在Robotbit的舵机接口S1上(可以接S1-S8)
- 智能窗温湿度模块 => 接在Robotbit的P15口上,绿色线(可以接P0-P15)
- 智能窗雨滴模块 => 接在Robotbit的P1口上,蓝色线(雨滴模块是属于模拟读模块,只能接P0、P1、P2)
- 示例代码 ```python import paho.mqtt.client as mqtt#iot的相关库
与喵比特硬件交互必不可少的库
import time from meowbit import * board = MeowBit() board.connect() robotbit=board.RobotBit()#请确保你的Robotbit已经插上,否则报错
dht11 = board.DHT11(‘P15’)#温湿度传感器接口定义
p1 = board.MeowPin(‘P1’,ANALOG)#雨滴传感器接口定义
robotbit.geekServo2kg(2, int(90))# S1舵机状态,开门(90度开门,0度关门)
robotbit.geekServo2kg(1, int(180))# S2舵机状态,开窗(180度开窗,250度关窗)
client = mqtt.Client(client_id=”YourName”)#设置你服务器上显示的设备名称
设置账号名和密码,如果需要的话
client.username_pw_set(“username”, “passWord”)
def on_connect(client, userdata, flags, rc): print(“Connected with result code “+str(rc))
# client.subscribe("CC_temp")
# client.subscribe("CC_humi")
# client.subscribe("CC_rain")
client.subscribe("CC_control")
def on_message(sender, userdata, msg): a=str(msg.payload,’UTF-8’) print(msg.topic+” “+a) if(a==’dooron’): robotbit.geekServo2kg(2, int(90))# S1舵机状态,开门(90度开门,0度关门)
if(a=='dooroff'):
robotbit.geekServo2kg(2, int(0))# S1舵机状态,关门(90度开门,0度关门)
if(a=='windowon'):
robotbit.geekServo2kg(1, int(180))# S2舵机状态,开窗(180度开窗,250度关窗)
if(a=='windowoff'):
robotbit.geekServo2kg(1, int(250))# S2舵机状态,关窗(180度开窗,250度关窗)
if(a=='fanon'):
robotbit.motor(1, 100, 0)#开风扇
if(a=='fanoff'):
robotbit.stopMotor(1)#关风扇
client.on_connect = on_connect client.on_message = on_message client.connect(‘iot.kittenbot.cn’, 1883) client.loop_start()
while True: dht11.measure()#提取温湿度值 T=dht11.temperature() H=dht11.humidity() R=p1.getAnalog()#雨水数值0-4095,干燥状态接近0
#如果温度太高打开风扇
if T>=22:
robotbit.motor(1, 100, 0)
print('fan on')
else:
robotbit.stopMotor(1)
print('fan off')
#如果下雨,关窗
if R>=50:
robotbit.geekServo2kg(1, int(250))# S2舵机状态,关窗(180度开窗,250度关窗)
print('window off')
else:
robotbit.geekServo2kg(1, int(180))# S2舵机状态,开窗(180度开窗,250度关窗)
print('window on')
client.publish("CC_temp",T)#向物联网服务器推送温湿度与雨水状态
client.publish("CC_humi",H)
client.publish("CC_rain",R)
print('temp='+str(T))
print('humi='+str(H))
print('rain='+str(R))
time.sleep(10)#每隔10秒
```
效果展示
- 点击 物联网 按钮,打开物联网页面
- 添加话题:分别用于接收,温度、湿度、雨滴数值。控制(用于发送命令控制门窗风扇)
- 分别点击不同话题,切换到数据显示的中的 图表 页图表查看数据情况
- 在负责控制的话题下点击连接,对应发送如图所示的6种命令,可分别控制门、窗、风扇的开关状态