仅作为本人学习《物联网开发实战》的学习笔记,原课程链接:极客时间《物联网开发实战》——郭朝斌
文章目录
物联网平台上需要做什么准备?
这里选择用腾讯云作为实验平台
注册与登录
登录腾讯云,注册或登录即可。
创建项目和产品
登录腾讯云后,进入物联网开发平台,新建一个项目。
填入项目名,
进入刚才新建的项目,在里面新建一个产品,我们需要设置几个参数,可以参考下图:
物模型在哪里使用?
设置完成产品信息后,点击新建的产品,下面是我新建的产品的物模型:
交互界面如何定义?
交互开发前面还有一个设备开发,可以直接跳过,在交互开发中,我们只需关注两个配置项:打开“使用官方小程序控制产品”,在“扫一扫产品介绍” 中设置一些配置信息,同时也可以设置一下产品图片。其他设置项可以保持默认。
为调试做准备
进行 “设备调试” 界面,新建一个设备,
设备新建完成后,点击设备可以查看设备详情:
设备名称(DeviceName)、设备密钥(SecreKey)和产品 ID (ProductID)三个信息比较重要,后面都用得到,这三个也常被称为设备三元组。
如何打造智能电灯设备?
如何控制 LED 灯的颜色?
RGB LED 接 NodeMCU 的三个 IO 口,NodeMCU ESP-32 的每个 IO 都支持 PWM,所以只需选择任意 3 个空闲引脚即可。下面时 Led 类的定义:
from machine import PWM
from machine import Pin
class Led():
"""
创建 LED 类
"""
def __init__(self, rpin, gpin, bpin, freq=1000):
"""
构造函数
pin:接 LED 的管脚,必须支持 PWM
freq:PWM 的默认频率是 1000
"""
self.pin_red = Pin(rpin)
self.pin_green = Pin(gpin)
self.pin_blue = Pin(bpin)
self.led_red = PWM(self.pin_red, freq = freq)
self.led_green = PWM(self.pin_green, freq = freq)
self.led_blue = PWM(self.pin_blue, freq = freq)
def rgb_light(self, red, green, blue, brightness):
if red in range(256) and \
green in range(256) and \
blue in range(256) and \
0.0 <= brightness and \
brightness <= 1.0:
self.led_red.duty(int(red/255*brightness*1023))
self.led_green.duty(int(green/255*brightness*1023))
self.led_blue.duty(int(blue/255*brightness*1023))
else:
print("red green blue must between 0 and 255, and brightness from 0.0 and 1.0");
def deinit(self):
"""
构析函数
"""
self.led_red.deinit()
self.led_green.deinit()
self.led_blue.deinit()
如何控制电灯的开关?
参考自原文,通过一个 IO 口来控制继电器,从而控制电灯的开和关。
from machine import ADC
from machine import Pin
class Relay():
def __init__(self, pin):
self.relaypin = Pin(pin, Pin.OUT)
self.last_status = 1
def set_state(self, state):
self.relaypin.value(state)
self.last_status = state
def state(self):
self.last_status = self.relaypin.value()
return self.last_status
智能电灯的整体电路如何搭建?
下面是郭老师画的连接示意图:
下面是测试代码,参考自原文,LED 和继电器的 IO 编号需要根据具体接线情况而定。
from machine import PWM, Pin
import time
# 设置对应红、绿、蓝的三个 GPIO 管脚
led_red = PWM(Pin(4), freq = 1000)
led_green = PWM(Pin(16), freq = 1000)
led_blue = PWM(Pin(17), freq = 1000)
# 继电器的 GPIO 引脚
relaypin = Pin(15, Pin.OUT)
# 通过 PWM 的占空比设置颜色
def rgb_light(red, green, blue, brightness):
pwm_red = led_red.duty(int(red/255*brightness*1023))
pwm_green = led_green.duty(int(green/255*brightness*1023))
pwm_blue = led_blue.duty(int(blue/255*brightness*1023))
rgb_light(255, 255, 0, 1.0)
# 周期点亮、熄灭
while True:
relaypin.on()
time.sleep(1)
relaypin.off()
time.sleep(1)
对应的现象:继电器(和 LED)以 1 秒的间隔通和断。
远程控制如何实现?
智能电灯如何与物联网平台通信交互呢?这里就要用到 MQTT 通信协议了。
首选,我们需要在 NodeMCU 开发板上安装一个 MQTT 客户端代码库,可以在串口 REPL 中运行下面的命令进行安装:
import upip
upip.install('micropython-umqtt.simple')
不过上面这个步骤有一个前提—— NodeMCU 需要联网,我们可以在串口 REPL 中输入下面的命令,连接 Wi-Fi 进行联网:
import network
wifi = network.WLAN(network.STA_IF)
wifi.active(True)
wifi.scan()
wifi.connect('你的 WiFi SSID', '对应的 WiFi 密码')
wifi.isconnected()
安装好 umqtt.simple 库之后,我们需要设置一下物联网平台的 MQTT 协议交互的 Topic 和具体的连接参数:
# 发布消息
$thing/up/property/ProductID/DeviceName
# 接收订阅消息
$thing/down/property/ProductID/DeviceName
上面的 ProductID 和 DeviceName 都是前面提到的设备参数,需要根据实际情况来填写。
设备与物联网平台建立 MQTT 连接,涉及 Broker 服务器地址、端口号、设备 ID(ClientID)、用户名(UserName)和密码(Password)。详情可见下图(来自原文)
用户名和密码不好手动生成,我们可以借助一个网页工具来生成(工具来自原文链接)。
有了以上信息,我们就可以开始编写 MQTT 代码了,下面的代码参考原文:
from Led import Led
from Button import Button
from Relay import Relay
import time
import uasyncio
import network
import ujson
from umqtt.simple import MQTTClient
"""
Wi-Fi Gateway : SSID and Password
"""
WIFI_AP_SSID = "你的Wi-Fi 名称"
WIFI_AP_PSW = "你家的 Wi-Fi 密码"
"""
QCloud Device Info
"""
DEVICE_NAME = "你的设备名称"
PRODUCT_ID = "你的产品ID"
DEVICE_KEY = "你的设备密钥"
"""
MQTT topic
"""
MQTT_CONTROL_TOPIC = "$thing/down/property/"+PRODUCT_ID+"/"+DEVICE_NAME
MQTT_CONTROL_REPLY_TOPIC = "$thing/up/property/"+PRODUCT_ID+"/"+DEVICE_NAME
led = Led(4, 16, 17)
relay = Relay(15)
button = Button(0)
mqtt_client = None
color = 0 # enum - 0:red 1:green 2:blue
name = "" # light name, it's optional
brightness = 100 # 0%~100%
light_changed = False
async def wifi_connect(ssid, pwd):
sta = network.WLAN(network.STA_IF)
sta.active(True)
sta.connect(ssid, pwd)
while not sta.isconnected():
print("Wi-Fi Connecting...")
time.sleep_ms(500)
def mqtt_callback(topic, msg):
global led, relay, botton
global color, name, brightness, light_changed
print((topic, msg))
msg_json = ujson.loads(msg)
if msg_json['method'] == 'control':
params = msg_json['params']
power_switch_tmp = params.get('power_switch')
if power_switch_tmp is not None:
power_switch = power_switch_tmp
relay.set_state(power_switch)
brightness_tmp = params.get('brightness')
if brightness_tmp is not None:
brightness = brightness_tmp
color_tmp = params.get('color')
if color_tmp is not None:
color = color_tmp
name_tmp = params.get('name')
if name_tmp is not None:
name = name_tmp
if brightness_tmp is not None or color_tmp is not None:
light_changed = True
async def mqtt_connect():
global mqtt_client
MQTT_SERVER = PRODUCT_ID + ".iotcloud.tencentdevices.com"
MQTT_PORT = 1883
MQTT_CLIENT_ID = PRODUCT_ID+DEVICE_NAME
MQTT_USER_NAME = "你的用户名"
MQTT_PASSWORD = "你的密码"
mqtt_client = MQTTClient(MQTT_CLIENT_ID, MQTT_SERVER, MQTT_PORT, MQTT_USER_NAME, MQTT_PASSWORD, 60)
mqtt_client.set_callback(mqtt_callback)
mqtt_client.connect()
def mqtt_report(client, color, name, switch, brightness):
msg = {
"method": "report",
"clientToken": "clientToken-2444532211",
"params": {
"color": color,
"color_temp": 0,
"name": name,
"power_switch": switch,
"brightness": brightness
}
}
client.publish(MQTT_CONTROL_REPLY_TOPIC.encode(), ujson.dumps(msg).encode())
async def light_loop():
global led, relay, button
global color, name, brightness, light_changed
switch_status_last = 1
LED_status = 1
color = 2 # blue
brightness = 100 # 100%
led.rgb_light(0, 0, 255, brightness/100.0)
time_cnt = 0
mqtt_client.subscribe(MQTT_CONTROL_TOPIC.encode())
while True:
mqtt_client.check_msg()
switch_status = button.state()
LED_status = relay.state()
if switch_status != switch_status_last:
if switch_status == 0 and switch_status_last == 1:
LED_status = 0 if LED_status else 1
relay.set_state(LED_status)
switch_status_last = switch_status
if light_changed:
light_changed = False
led.rgb_light(255 if color==0 else 0, 255 if color==1 else 0, 255 if color==2 else 0, brightness/100.0)
if time_cnt >= 20:
mqtt_report(mqtt_client, color, name, LED_Status, brightness)
time_cnt = 0
time_cnt = time_cnt + 1
uasyncio.sleep_ms(50)
async def main():
global mqtt_client
# Wi-Fi connection
try:
await uasyncio.wait_for(wifi_connect(WIFI_AP_SSID, WIFI_AP_PSW), 20)
except uasyncio.TimeoutError:
print("wifi connected timeout!")
# MQTT connection
try:
await uasyncio.wait_for(mqtt_connect(), 20)
except uasyncio.TimeoutError:
print("mqtt connected timeout!")
await uasyncio.gather(light_loop())
uasyncio.run(main())
原课程并没有给出 Button.py 的内容,下面是我参考其他类编写的 Button 类,要想让 main.py 能调用相关函数,最简单的方法是将 Button.py 等文件复制到 main.py 所在位置(开发板文件系统根目录)。
from machine import Pin
class Button():
def __init__(self, pin):
self.button = Pin(pin, Pin.IN)
self.last_status = self.button.value()
def state(self):
self.last_status = self.button.value()
return self.last_status
在开发板上运行以上 mqtt 代码(main.py),就能在腾讯云控制台来控制智能电灯了。
需要注意的是,我这里电灯开关的逻辑是反的(这个暂时不先处理)。通过云端控制台的在线调试界面,将电灯调成绿色,亮度 50%:
对应的实际现象:
再将颜色改为蓝色,亮度设置为 80% :
对应实际现象:
如何通过手机远程控制?
下载“腾讯连连” APP,扫描设备的二维码即可添加对应设备:
进入设备,调整相关参数,控制“智能电灯”(注:当前开关逻辑是反的)
将颜色改为红色: