Arduino+ESP8266+华为云物联网平台实现智能开关

前言
最近在做一个物联网项目,涉及到智能开关的开发。目前已经实现简单的TCP通信远程控制,但是考虑到后期的设备管理以及设备通信所需要的技术和服务器的维护成本,我决定将设备接入云平台。本文将详细阐述如何利用华为云的物联网平台(IoTDA)实现设备的云上管理与通信。
前提条件
- 搭建Arduino+ESP8266的开发环境。可以参考: 软件开发人员从0到1实现物联网项目:初步实现智能开关
- 开通华为云物联网平台服务,并注册一个设备。可以参考官网文档。
准备工作
设备侧选择用MQTT协议,因为对(IoTDA)SDK的编译环境不太了解,这里通过API的方式接入华为云的物联网平台。
获取IoTDA接入信息
首先需要拿到两个信息:
-
华为云物联网平台的接入信息,也就是URL和PORT。接入信息通过下图可以看到。

-
华为云物联网平台的设备连接鉴权信息。可以参考设备连接鉴权 。简单来讲,就是通过注册设备时的设备ID和密钥生成设备连接鉴权所需的参数(ClientId、Username、Password)。生成参数的链接

安装代码库
其次,设备侧作为MQTT的客户端,需要编写相关代码。基于Arduino IDE开发,可以使用现成的库减少工作量。
- 安装
PubSubClient库,用于连接和交互MQTT代理服务器(IoTDA)。 - 安装
ArduinoJson库,用于解析和生成 JSON 数据。

功能实现
基于IoTDA平台实现智能开关,代码要实现以下功能:
- 设备进行WiFi连接与网络通信。
- 设备通过MQTT协议接入IoTDA平台。
- 设备接收IoTDA平台下发的消息。
- 设备根据消息执行相应的控制操作。
WiFi连接
#include <ESP8266WiFi.h> const char* ssid = "xxx"; //wifi名称
const char* password = "xxx"; //wifi密码void setup_wifi() { delay(10); // We start by connecting to WiFi Serial.println(); Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); Serial.print("IP address: "); Serial.println(WiFi.localIP());
}
对以上的代码进行解释:
ESP8266WiFi.h 库提供了与 WiFi 网络连接相关的功能,WiFi.begin(ssid, password); 这行代码就可以自动连接WiFi。
接入IoTDA
设备要接入IoTDA,就需要上面准备的接入信息。在代码中定义如下:
const char* mqttServer = "xxx.myhuaweicloud.com";
const int mqttPort = 1883;
const char* mqttClientId = "xxx";
const char* mqttUser ="xxx";
const char* mqttPassword = "xxx";#define deviceId "xxx"#define mqttTopic "$oc/devices/" deviceId "/sys/messages/down"
mqttTopic是在接入成功后,设备侧订阅的Topic,用来接收平台下发的消息。更多的topic定义参考IoTDA平台预置的topic。
接下来就需要通过PubSubClient库进行接入IoTDA平台了
WiFiClient espClient;
PubSubClient client(espClient); void reconnect() { client.setServer(mqttServer, mqttPort); client.setCallback(callback); while (!client.connected()) { Serial.println("Attempting MQTT connection..."); if (client.connect(mqttClientId, mqttUser, mqttPassword)) { Serial.println("connected"); client.subscribe(mqttTopic); } else { Serial.print(client.state());delay(5000); } }
}
接收IoTDA消息&控制开关
client.connect 成功后会订阅Topic,当在IoTDA平台下发消息时,就会在 callback 函数进行 digitalWrite(RELAY_PIN, state); 控制开关了。
void callback(char* topic, byte* payload, unsigned int length) { StaticJsonDocument<128> doc; DeserializationError error = deserializeJson(doc, payload); if (error) { Serial.print(F("deserializeJson() failed: ")); Serial.println(error.c_str()); return; } const char* stateKey = "state"; if (doc.containsKey(stateKey)) { bool state = doc[stateKey]; digitalWrite(RELAY_PIN, state); Serial.print("Switch state: "); Serial.println(state ? "ON" : "OFF"); }
}
完整代码
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h> const char* ssid = "xxx";
const char* password = "xxx.";
const char* mqttServer = "xxx.myhuaweicloud.com";
const int mqttPort = 1883;
const char* mqttClientId = "xxx";
const char* mqttUser ="xxx";
const char* mqttPassword = "xxx";#define RELAY_PIN 0#define deviceId "xxx"#define mqttTopic "$oc/devices/" deviceId "/sys/messages/down"WiFiClient espClient;
PubSubClient client(espClient); void callback(char* topic, byte* payload, unsigned int length) { StaticJsonDocument<128> doc; DeserializationError error = deserializeJson(doc, payload); if (error) { Serial.print(F("deserializeJson() failed: ")); Serial.println(error.c_str()); return; } const char* stateKey = "state"; if (doc.containsKey(stateKey)) { bool state = doc[stateKey]; digitalWrite(RELAY_PIN, state); Serial.print("Switch state: "); Serial.println(state ? "ON" : "OFF"); }
} void reconnect() { while (!client.connected()) { Serial.println("Attempting MQTT connection..."); if (client.connect(mqttClientId, mqttUser, mqttPassword)) { Serial.println("connected"); client.subscribe(mqttTopic); } else { Serial.print(client.state());delay(5000); } }
} void setup_wifi() { delay(10); Serial.println(); Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); Serial.print("IP address: "); Serial.println(WiFi.localIP());
} void setup() { Serial.begin(115200); pinMode(RELAY_PIN, OUTPUT); digitalWrite(RELAY_PIN, HIGH); setup_wifi(); client.setServer(mqttServer, mqttPort); client.setCallback(callback);
} void loop() { if (!client.connected()) { reconnect(); } client.loop();
}
IoTDA平台下发消息
将编写完成的代码烧录到ESP-01S模块后,就可以通过IoTDA平台进行消息下发了。消息下发位置见下图

消息下发格式:
{"state":true
}
当state为true时,表示电平状态为HIGH,电路呈开启状态,此时电路不通电。
而当state为false时,电平状态则为LOW,电路闭合,此时电路处于通电状态。
通过state数值的变化,从而达到远程控制开关。
问题记录
在串口调试时,如果mqtt连接返回-1状态码,意味着连接失败。
那么需要将 PubSubClient.h 库中的两个宏定义MQTT_KEEPALIVE、MQTT_MAX_PACKET_SIZE 的数值调大。本文中的代码已分别调整为60和2048。

总结
借助华为云的物联网平台IoTDA,可以帮助物联网行业的用户快速完成设备联网及行业应用集成,大大提高了开发人员的工作效率。而且按需计费每月前一百万条消息是免费的,很大程度上降低了设备上云的成本。
相关文章:
Arduino+ESP8266+华为云物联网平台实现智能开关
前言 最近在做一个物联网项目,涉及到智能开关的开发。目前已经实现简单的TCP通信远程控制,但是考虑到后期的设备管理以及设备通信所需要的技术和服务器的维护成本,我决定将设备接入云平台。本文将详细阐述如何利用华为云的物联网平台&#x…...
使用 python 拆分 excel 文件
文章目录 1、安装虚拟环境(在特定文件夹内)2、脚本 split.sh3、运行脚本(在特定文件夹内)4、结果 1、安装虚拟环境(在特定文件夹内) brew install python3 xcode-select --install python3 -m venv my_pan…...
uniapp小程序中onShareAppMessage(OBJECT)实现带参数的分享功能
一、引言 小程序中用户点击分享后,在 js 中定义 onShareAppMessage 处理函数(和 onLoad 等生命周期函数同级),设置该页面的分享信息。 用户点击分享按钮的时候会调用。这个分享按钮可能是小程序右上角原生菜单自带的分享按钮&…...
5个免费的3D钣金CAD软件
如果你正在设计简单的折叠钣金零件,则只需设计一些具有圆角半径的法兰:一个简单的钣金模块。 首先,你可以采用老式方式绘图并以 2D 方式完成所有操作。 许多传统制造商仍在使用 2D DWG 和 DXF 图纸。 因此,你很有可能只需快速起草…...
3.26学习总结
java 实例变量和局部变量 实例变量是记录这个类中对象的特点的每一个对象的实例变量都可以不同(例如名字,性别等),其中一个对象的实例变量改变不会影响其他的变量. 类变量是一种特殊的实例变量,他的特殊在于所有的对象的类变量都是相同的,当一个对象改变了类变量那么所有对象…...
Cisco Catalyst3850交换机RTU license使用方法
1 情况说明 客户处采购了4台3850-14T交换机,在配置的时候发现OSPF不支持, 查询原因为当前license不支持 (lanbase, 只能支持2层功能) 报错如下: Access-3850-1(config)#router ospf 100 Protocol not in this image2 如何处理&a…...
简明 Python 教程(第5章 函数)
本章介绍了函数的基本概念和使用方法,包括定义函数、传递参数、局部变量、全局变量、默认参数、关键字参数、返回值和文档字符串。 掌握这些概念对于编写结构化和可维护的Python代码至关重要。 定义函数 使用def关键字 定义函数始于def关键字,它告诉P…...
flutter 保存一堆多语言翻译词条,由key和value组成
原理: 1.从String列表里面获取某个value: List<String> jsonStrings [{"name": "John", "age": 30},{"name": "Jane", "age": 25},{"name": "Bob", "age…...
3月25日,每日信息差
🎖 素材来源官方媒体/网络新闻 🎄 京东汽车将和小米汽车进行深度合作 🌍 百度将为苹果国行iPhone16提供AI功能?百度方面称暂无回应 🌋 国产结核病新型mRNA疫苗即将问世 🎁 美国发布严重地磁暴预警ÿ…...
Git常用指令使用
摘要:之前代码管理都是借助于fork、sourceTree等图形工具,最近发现直接用命令也好用,就总结Git常用的指令 1、Git的介绍 1.1 git官网 安装: Git - Downloading Packagehttps://git-scm.com/download/mac Mac上安装,直接使…...
数据结构与算法 顺序表的基本运算
一、实验内容 编写一个程序实现,实现顺序表的各种基本运算(假设顺序表的元素类型为char),并以此为基础设计一个程序完成下列功能: (1)初始化顺序表; (2)采…...
docker部署nacos(单机与集群)
拉去nacos镜像 [rootlocalhost keepalived]# docker search nacos NAME DESCRIPTION STARS OFFICIAL nacos/nacos-server This project contains a Docker image meant t… 464 …...
开启Safari手势支持
在使用Safari 的时候,大家有没有觉得不支持手势使用起来不是很方便, 触摸板只支持少量简单的手势,如缩放,滚动等。如果使用鼠标的用户,则完全无法使用手势。经过折腾研究,使用CirMenu应用可以完美解决这个要…...
Amuse:.NET application for stable diffusion
目录 Welcome to Amuse! Features Why Choose Amuse? Key Highlights Paint To Image Text To Image Image To Image Image Inpaint Model Manager Hardware Requirements Compute Requirements Memory Requirements System Requirements Realtime Requirements…...
Java冒泡排序详细讲解
冒泡排序是一种简单但效率较低的排序算法,它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。具体实现如下: 算法步骤: 比较相邻的元素:从第一个元素开始,依次…...
python数据解析xpath
前言一、安装?二、使用步骤1.基本使用**【2】谓语(Predicates)**案例 前言 xpath在Python的爬虫学习中,起着举足轻重的地位,对比正则表达式 re两者可以完成同样的工作,实现的功能也差不多,但xp…...
工业镜头常用参数之实效F(Fno.)和像圈
Fno. 工业镜头中常用到的参数F,有时候用F/#,Fno.来表示,指的是镜头通光能力的参数。它可用镜头焦距及入瞳直径来表示,也可通过镜头数值孔径(NA)和光学放大倍率(β)来计算。有效Fno.…...
what is apache?
Apache 通常指 Apache Software Foundation (ASF) 或 Apache HTTP Server,两者都是计算机软件领域的重要实体。 Apache 软件基金会 (ASF):Apache 软件基金会是一个开发开源软件项目的非营利组织。它为涵盖软件开发各个方面的广泛项目提供支持,…...
【二叉树】Leetcode 94. 二叉树的中序遍历【简单】
二叉树的中序遍历 给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。 示例 1: 输入:root [1,null,2,3] 输出:[1,3,2] 解题思路 中序遍历是一种二叉树遍历方式,按照“左根右”的顺序遍历二叉树节点。 1、递归…...
Linux进程控制(等待)
进程等待 为什么要进行进程等待 进程等待是什么? 怎么进行进程等待? 回到我们之前进程状态的代码, 我们知道, 在这段代码中,父进程对子进程没有做任何的操作, 所以当子进程在退出后, 会一直处于…...
实战-EdgeBoard赛事卡:从零部署飞桨模型到智能车竞赛
1. EdgeBoard赛事卡开箱与环境准备 第一次拿到EdgeBoard赛事专用卡时,这块巴掌大的小盒子让我有点怀疑——这么小的板子真能跑动智能车竞赛需要的视觉模型吗?拆开包装后发现,除了板卡本体,配件只有一根Type-C线,确实符…...
GPEN肖像增强使用技巧:自然、强力、细节三种模式适用场景解析
GPEN肖像增强使用技巧:自然、强力、细节三种模式适用场景解析 1. 认识GPEN的三种处理模式 GPEN作为当前最先进的肖像增强工具之一,其核心价值在于提供了三种差异化的处理模式:自然、强力和细节。这三种模式不是简单的强度差异,而…...
从裸机到RTOS:IMX6ULL启动流程与FreeRTOS源码实战解析
1. IMX6ULL裸机启动机制详解 第一次拿到IMX6ULL开发板时,很多人会疑惑:为什么我的程序烧录进去没反应?这得从芯片的启动机制说起。IMX6ULL上电后最先执行的并不是我们写的代码,而是芯片内部ROM中的固化程序。这个ROM代码就像个尽职…...
深入解析GNSS信号跟踪环路:从PLL/DLL原理到Python仿真实践
1. GNSS信号跟踪环路基础概念 当你用手机导航时,背后其实藏着一套精密的信号追踪系统。想象一下,头顶的GPS卫星就像演唱会上的歌手,而你的手机接收机则是要听清歌词的观众。但现实中存在两个主要干扰:一是你和歌手都在移动&#x…...
融合多尺度特征与注意力机制的YOLOv5红外小目标检测优化方案
1. 红外小目标检测的技术挑战 红外遥感图像中的小目标检测一直是计算机视觉领域的难点问题。与可见光图像相比,红外图像具有低对比度、高噪声、目标尺寸小等特点,这使得传统检测算法难以取得理想效果。在实际应用中,军事侦察中的无人机识别、…...
视频硬字幕提取终极指南:用本地AI工具10倍提升你的字幕制作效率
视频硬字幕提取终极指南:用本地AI工具10倍提升你的字幕制作效率 【免费下载链接】video-subtitle-extractor 视频硬字幕提取,生成srt文件。无需申请第三方API,本地实现文本识别。基于深度学习的视频字幕提取框架,包含字幕区域检测…...
SVN 启动模式详解
SVN 启动模式详解 引言 Subversion(简称SVN)是一个开源的版本控制系统,广泛用于软件项目协作开发中。SVN的启动模式是其基本操作的核心,了解并掌握不同的启动模式对于高效使用SVN至关重要。本文将详细介绍SVN的启动模式,包括基本概念、常用模式及其应用场景。 一、SVN启…...
CMake实战:用ExternalProject_Add一键集成第三方库(附spdlog完整配置)
CMake实战:用ExternalProject_Add一键集成第三方库(附spdlog完整配置) 在C项目开发中,第三方库的集成往往是最耗时的环节之一。传统的手动下载、编译、配置头文件路径和链接库文件的方式,不仅效率低下,还会…...
保姆级教程:在Windows上用VSCode和nRF5340 Audio DK板跑通第一个蓝牙例程
从零开始:WindowsVSCode环境下的nRF5340 Audio DK蓝牙开发实战 在嵌入式开发领域,Nordic Semiconductor的nRF5340 Audio DK开发板因其强大的双核架构和出色的蓝牙音频性能而备受瞩目。但对于刚接触这款开发板的工程师来说,从环境配置到成功运…...
告别Transformer的O(n²)烦恼:手把手带你用Mamba-2.0搭建一个长文本摘要模型
突破长文本处理瓶颈:基于Mamba-2.0的高效摘要系统实战指南 在当今信息爆炸的时代,我们每天都被海量文本内容包围——从学术论文、技术文档到商业报告,这些长文本的有效处理已成为知识工作者面临的核心挑战。传统基于Transformer的摘要系统虽然…...
