仅作为本人学习《物联网开发实战》的学习笔记,原课程链接:极客时间《物联网开发实战》——郭朝斌

物联网平台上需要做什么准备?

这里选择用腾讯云作为实验平台

注册与登录

登录腾讯云,注册或登录即可。

创建项目和产品

登录腾讯云后,进入物联网开发平台,新建一个项目。

在这里插入图片描述

填入项目名,

在这里插入图片描述

进入刚才新建的项目,在里面新建一个产品,我们需要设置几个参数,可以参考下图:

在这里插入图片描述

物模型在哪里使用?

设置完成产品信息后,点击新建的产品,下面是我新建的产品的物模型:

在这里插入图片描述

交互界面如何定义?

交互开发前面还有一个设备开发,可以直接跳过,在交互开发中,我们只需关注两个配置项:打开“使用官方小程序控制产品”,在“扫一扫产品介绍” 中设置一些配置信息,同时也可以设置一下产品图片。其他设置项可以保持默认。

在这里插入图片描述

为调试做准备

进行 “设备调试” 界面,新建一个设备,

在这里插入图片描述

设备新建完成后,点击设备可以查看设备详情:

在这里插入图片描述

设备名称(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,扫描设备的二维码即可添加对应设备:

在这里插入图片描述

在这里插入图片描述

进入设备,调整相关参数,控制“智能电灯”(注:当前开关逻辑是反的)

在这里插入图片描述
在这里插入图片描述

将颜色改为红色:

在这里插入图片描述

在这里插入图片描述

更多推荐