LOADING
1064 words
5 minutes
物联网设备控制小程序:从使用到设备接入

这个小程序是给 50 到 60 人规模的小团队使用的设备控制工具。它的目标不是做复杂的大平台,而是让团队成员能稳定地登录、绑定设备、查看状态、下发命令,并把常用操作沉淀成任务或模板。

查看完整接入示例

小程序能做什么

  • 微信一键登录,首次使用访问码绑定身份,后续直接登录。
  • 管理员维护访问码、团队人数上限和允许名单。
  • 用户手动绑定设备,可选择个人可见或团队共享。
  • 查看设备在线状态、最近上报时间和状态数据。
  • 下发设备命令,例如开关、模式切换、参数设置和请求链接。
  • 创建手动任务、任务模板和自动任务。
  • 自动任务支持两种触发表达:定时触发和钩子触发。

为什么不是只支持 ESP32

ESP32-S3 只是当前固件示例。真正的接入协议是 HTTP JSON,所以树莓派、Linux 网关、Windows 上位机、其他联网 MCU,甚至一段 Python 脚本都可以接入。

设备只要能完成三件事就行:

  1. 定期上报状态。
  2. 主动拉取待执行命令。
  3. 执行后回写成功或失败。

这种设计适合弱服务器,因为服务器不需要和每台设备保持长连接,小程序也不需要高频直连设备。

设备接入流程

1. 上报状态

设备定期请求:

POST https://api.niuhaoyu.xyz/api/device/{deviceId}/status

请求体示例:

{
"online": true,
"status": {
"power": "on",
"temperature": 26.5,
"mode": "eco"
}
}

2. 拉取命令

设备轮询:

GET https://api.niuhaoyu.xyz/api/device/{deviceId}/commands/next

如果有命令,服务器会返回类似数据:

{
"id": "cmd-xxx",
"command": {
"type": "setPower",
"payload": {
"power": "off"
}
}
}

3. 回写结果

执行完成后请求:

POST https://api.niuhaoyu.xyz/api/device/{deviceId}/commands/{commandId}

成功示例:

{
"status": "success",
"result": {
"power": "off"
}
}

失败示例:

{
"status": "failed",
"message": "unsupported command"
}

任务系统怎么理解

小程序里只需要理解两类任务:

  • 手动任务:用户点击后立即执行。
  • 自动任务:保存成规则,由定时或钩子触发。

模板不是任务类型,它只是常用操作的保存方式。比如“打开电源 10 秒后关闭”可以保存成模板,需要时一键执行;“每天 08<00> 打开设备”则应该保存成自动任务。

常用命令类型

类型用途Payload 示例
setPower开关{"power":"on"}
setMode模式切换{"mode":"eco"}
setValue参数设置{"key":"threshold","value":50}
httpRequest让设备请求一个链接{"method":"GET","url":"https://example.com/action"}

完整设备示例

下面示例可以在电脑、树莓派或普通 Linux 网关上运行。真实项目里不要把设备 token 写进公开仓库,应该从环境变量或本地安全配置读取。

import json
import os
import time
import urllib.request
API_BASE = os.getenv("IOT_API_BASE", "https://api.niuhaoyu.xyz/api")
DEVICE_ID = os.getenv("IOT_DEVICE_ID", "demo-python-001")
DEVICE_TOKEN = os.getenv("IOT_DEVICE_TOKEN", "replace-with-device-token")
def request_json(path, method="GET", payload=None):
data = None
if payload is not None:
data = json.dumps(payload).encode("utf-8")
req = urllib.request.Request(
API_BASE + path,
data=data,
method=method,
headers={
"Content-Type": "application/json",
"Authorization": "Bearer " + DEVICE_TOKEN,
},
)
with urllib.request.urlopen(req, timeout=8) as resp:
return json.loads(resp.read().decode("utf-8"))
def report_status(state):
return request_json(
"/device/%s/status" % DEVICE_ID,
method="POST",
payload={
"online": True,
"status": state,
},
)
def next_command():
result = request_json("/device/%s/commands/next" % DEVICE_ID)
return (result.get("data") or {}).get("command")
def finish_command(command_id, status, result=None, message=""):
payload = {"status": status}
if result is not None:
payload["result"] = result
if message:
payload["message"] = message
return request_json(
"/device/%s/commands/%s" % (DEVICE_ID, command_id),
method="POST",
payload=payload,
)
def execute(command, state):
command_type = command.get("type")
payload = command.get("payload") or {}
if command_type == "setPower":
state["power"] = payload.get("power", "off")
return True, state, ""
if command_type == "setMode":
state["mode"] = payload.get("mode", "normal")
return True, state, ""
if command_type == "setValue":
key = payload.get("key", "value")
state[key] = payload.get("value")
return True, state, ""
return False, state, "unsupported command: %s" % command_type
def main():
state = {
"power": "off",
"mode": "normal",
"temperature": 26.5,
}
while True:
report_status(state)
item = next_command()
if item:
command_id = item.get("id")
command = item.get("command") or {}
ok, state, message = execute(command, state)
if ok:
finish_command(command_id, "success", result=state)
else:
finish_command(command_id, "failed", message=message)
time.sleep(3)
if __name__ == "__main__":
main()

小程序使用建议

首次使用时先完成微信登录和访问码绑定。添加设备时,如果只是自己调试,选择“个人可见”;如果团队都要用,选择“团队共享”。设备上线后,先在设备详情页确认状态能刷新,再创建任务。

手动任务适合立即控制。自动任务适合规则化场景,例如每天固定时间执行,或者后续由设备告警、传感器阈值、外部 HTTP 事件触发。

物联网设备控制小程序:从使用到设备接入
/posts/iot-miniprogram-guide/
Author
niuniu
Published at
2026-06-08
License
CC BY-NC-SA 4.0

Some information may be outdated