【YFIOs】用C#开发硬件之设备上云

设备初始化到数据上传的完整实现。

NuGet 软件包

包名 版本 用途
nanoFramework.CoreLibrary 1.17.11 基础运行时(System 命名空间)
nanoFramework.Hardware.Esp32 1.6.37 ESP32 引脚功能配置(I2C/SPI/UART)
nanoFramework.Iot.Device.DhcpServer 1.2.938 AP 模式 DHCP 服务器
nanoFramework.Logging 1.1.161 日志记录(ILogger)
nanoFramework.M2Mqtt 5.1.212 MQTT 客户端(连接叶帆物联平台)
nanoFramework.Networking.Sntp 1.6.42 NTP 时间同步
nanoFramework.System.Collections 1.5.67 Hashtable / ArrayList(属性上传)
nanoFramework.System.Device.Gpio 1.1.57 GPIO 控制(LED/按钮/继电器/数字输入)
nanoFramework.System.Device.I2c 1.1.29 I2C 通信(SHT30 温湿度传感器)
nanoFramework.System.Device.Wifi 1.5.141 WiFi STA/AP 管理
nanoFramework.System.Math 1.5.116 数学运算(指数退避重连)
nanoFramework.System.Net 1.11.50 DNS 解析(网络可达性检测)
nanoFramework.System.Net.Http.Server 1.5.204 Web 服务器(配网页面)
nanoFramework.System.Text 1.3.42 StringBuilder / UTF-8 编码
nanoFramework.System.Threading 1.1.52 线程/定时器
nanoFramework.WebServer 1.2.140 WebServer 路由框架(属性路由)

系统架构

复制代码

|----------------------------------------------------------------|
| ┌─────────────────────────────────────────────────────────┐ |
| │ YF3300-ESP32S3 设备 │ |
| │ │ |
| │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────┐ │ |
| │ │ SHT30 │ │ 继电器 │ │ 数字输入 │ │ BOOT │ │ |
| │ │ 温湿度 │ │ GPIO48 │ │ GPIO21/47│ │ GPIO0 │ │ |
| │ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬────┘ │ |
| │ │ I2C │ GPIO │ GPIO │ GPIO │ |
| │ ┌────▼──────────────▼────────────▼──────────────▼─────┐ │ |
| │ │ 驱动层 (Drivers/) │ │ |
| │ │ Sht30Sensor │ RelayDriver │ DigitalInputDriver │ │ |
| │ │ ButtonDriver│ LedManager │ │ |
| │ └────────────────────────┬────────────────────────────┘ │ |
| │ │ │ |
| │ ┌────────────────────────▼────────────────────────────┐ │ |
| │ │ 管理层 (Managers/) │ │ |
| │ │ MqttClientManager ←→ WifiManager ←→ APConfigManager│ │ |
| │ │ NtpTimeManager │ ConfigurationManager │ │ |
| │ └────────────────────────┬────────────────────────────┘ │ |
| │ │ MQTT (YFLink协议) │ |
| └───────────────────────────┼──────────────────────────────┘ |
| |
| ┌────────▼────────┐ |
| │ 叶帆物联网平台 │ |
| │ iot.yfios.net │ |
| │ MQTT:1883 │ |
| └─────────────────┘ |


启动流程(12步初始化)

程序在 Main() 中按顺序执行12个步骤完成系统初始化:

步骤 组件 GPIO/接口 说明
1 Logger - 初始化 DebugLoggerFactory 日志系统
2 GPIO - 创建 GpioController 实例
3 LED GPIO39/40 黄色(网络状态) + 绿色(配网状态)
4 Relay GPIO48 1路继电器输出驱动
5 Digital Input GPIO21/47 2路开关量输入,回调模式
6 SHT30 I2C(17/18) 温湿度传感器,地址0x44
7 Button GPIO0 BOOT按钮,短按切换继电器/长按配网
8 Configuration - WiFi凭证读写的配置管理器
9 WiFi Manager - STA/AP双模式WiFi管理
10 WiFi Connect - 加载配置连接WiFi,成功后初始化NTP
11 AP Config - AP配网管理器,含Web服务器
12 MQTT Connect - 连接叶帆物联网平台

主循环逻辑

复制代码

|--------------------------------------------|
| ┌──────────────┐ |
| │ counter++ │ |
| └──────┬───────┘ |
| |
| |
| ┌──────────────┐ 每5秒读取一次 |
| │ 读取传感器 │◄── NTP时间 / 温湿度 / 数字输入 / 继电器状态 |
| └──────┬───────┘ |
| |
| |
| ┌──────────────┐ counter % 6 == 0 (约30秒) |
| │ 是否上传? │─── NO ──► Sleep(5000ms) ──► 循环 |
| └──────┬───────┘ |
| │ YES |
| |
| ┌──────────────┐ |
| │ UploadData │ 构建属性Hashtable → MQTT发布 |
| │ ToCloud() │ 属性: H(湿度) T(温度) I1 I2 Q1 |
| └──────────────┘ |


核心代码详解

1. 硬件引脚定义 (Hardware/YF3300_ESP32S3.cs)

Hardware/YF3300_ESP32S3.cs

复制代码

|----------------------------------------------------------------|
| using System; |
| |
| namespace YFSoft.Hardware.YF3300_ESP32S3 |
| { |
| public static class CPU |
| { |
| public static class Pins |
| { |
| // GPIO 0-48 全部定义 |
| public const int GPIO0 = 0; |
| public const int GPIO9 = 9; // RS485 TX |
| public const int GPIO10 = 10; // RS485 RX |
| public const int GPIO11 = 11; // RS232 TX |
| public const int GPIO12 = 12; // RS232 RX |
| public const int GPIO17 = 17; // I2C SDA |
| public const int GPIO18 = 18; // I2C SCL |
| public const int GPIO21 = 21; // 开关量输入1 |
| public const int GPIO39 = 39; // 绿色LED |
| public const int GPIO40 = 40; // 黄色LED |
| public const int GPIO47 = 47; // 开关量输入2 |
| public const int GPIO48 = 48; // 继电器1 |
| } |
| } |
| |
| public static class Mainboard |
| { |
| public static class Pins |
| { |
| public const int YellowLED = CPU.Pins.GPIO40; // 网络状态 |
| public const int GreenLED = CPU.Pins.GPIO39; // 配网状态 |
| public const int BOOT = CPU.Pins.GPIO0; |
| public const int I1 = CPU.Pins.GPIO21; |
| public const int I2 = CPU.Pins.GPIO47; |
| public const int Q1 = CPU.Pins.GPIO48; |
| } |
| |
| public static class RS485 |
| { |
| public const string PortName = "COM1"; |
| public const int TxPin = CPU.Pins.GPIO9; |
| public const int RxPin = CPU.Pins.GPIO10; |
| } |
| |
| public static class I2C |
| { |
| public const int BusId = 1; |
| public const int SdaPin = CPU.Pins.GPIO17; |
| public const int SclPin = CPU.Pins.GPIO18; |
| } |
| } |
| |
| // LED闪烁时序定义(毫秒) |
| public static class LEDTiming |
| { |
| // 黄色LED - 网络状态 |
| public const int NetworkConnecting_On = 0; // 常亮 |
| public const int NetworkNormal_On = 500; // 慢闪 |
| public const int NetworkNormal_Off = 1500; |
| public const int NetworkError_On = 200; // 快闪 |
| public const int NetworkError_Off = 200; |
| |
| // 绿色LED - 配网状态 |
| public const int ConfigAP_On = 0; // 常亮(配网中) |
| public const int ConfigSuccess_On = 500; // 慢闪(成功) |
| public const int ConfigFailed_On = 200; // 快闪(失败) |
| } |
| |
| // 系统配置常量 |
| public static class SystemConfig |
| { |
| public const int WiFiConnectTimeout = 15000; // WiFi连接超时(ms) |
| public const int WiFiReconnectInterval = 5000; // 重连间隔(ms) |
| public const int MqttKeepAliveInterval = 60; // MQTT心跳(s) |
| public const string APSSID = "YF3300_ESP32S3"; |
| public const string APPassword = "yf123456"; |
| public const string APIP = "192.168.4.1"; |
| public const int APConfigTimeout = 600000; // 配网超时(10分钟) |
| public const int SensorReadInterval = 30000; // 传感器读取间隔 |
| public const int DataUploadInterval = 30000; // 数据上传间隔 |
| } |
| } |


YFLink协议使用JSON格式通过MQTT通信,所有请求都包含 idver(版本号1.3.0)、timestamp 三个基础字段。

Models/YFLinkModels.cs

复制代码

|--------------------------------------------------------|
| using System.Collections; |
| |
| namespace YeFanIoTTest.Models |
| { |
| // 基础请求/响应 |
| public class YFLinkRequest |
| { |
| public int id { get; set; } // 消息ID |
| public string ver { get; set; } = "1.3.0"; // 协议版本 |
| public long timestamp { get; set; } // Unix毫秒时间戳 |
| } |
| |
| public class YFLinkResponse |
| { |
| public int id { get; set; } |
| public int code { get; set; } // 200=成功 |
| public string message { get; set; } |
| } |
| |
| // ★ 属性上传 |
| public class PropertyPostRequest : YFLinkRequest |
| { |
| public Hashtable parameters { get; set; } // 属性键值对 |
| } |
| |
| // 事件上传 |
| public class EventPostRequest : YFLinkRequest |
| { |
| public ArrayList parameters { get; set; } // 事件数据列表 |
| } |
| |
| public class EventData |
| { |
| public int type { get; set; } // 0-信息 1-告警 2-故障 |
| public int code { get; set; } // 事件编码 |
| public string content { get; set; } // 事件内容(≤1024字节) |
| public long time { get; set; } // 事件时间戳 |
| } |
| |
| // 服务下发(云端→设备) |
| public class ServiceSendRequest : YFLinkRequest |
| { |
| public int serviceType { get; set; } // 0-命令 1-参数 |
| public ServiceParams parameters { get; set; } |
| } |
| |
| public class ServiceParams |
| { |
| public string command { get; set; } |
| public string parameter { get; set; } |
| } |
| |
| // NTP校时 |
| public class NtpRequest : YFLinkRequest |
| { |
| public NtpParams parameters { get; set; } |
| } |
| |
| public class NtpParams |
| { |
| public long deviceSendTime { get; set; } |
| } |
| |
| public class NtpResponse : YFLinkResponse |
| { |
| public NtpResponseParams parameters { get; set; } |
| } |
| |
| public class NtpResponseParams |
| { |
| public long deviceSendTime { get; set; } |
| public long serverRecvTime { get; set; } |
| public long serverSendTime { get; set; } |
| } |
| } |


3. MQTT 连接与YFLink认证 (Managers/MqttClientManager.cs)

这是与叶帆物联网平台通信的核心代码,包含YFLink协议的三元组认证(HMAC-SHA1签名)。

3.1 MQTT连接参数
复制代码

|---------------------------------------------------------------------------------|
| // MQTT服务器 |
| private const string MqttServer = "iot.yfios.net"; |
| private const int MqttPort = 1883; |
| |
| // YFLink三元组 |
| private const string ProjectId = "YFIoT_TEST"; |
| private const string ProductId = "YF3300_ESP32S3"; |
| private const string DeviceId = "YF3300_ESP32S301"; |
| private const string DeviceKey = "dxR99LCS7Uldc7KUnurFBeBi"; |
| |
| // MQTT主题(V1.3.0格式) |
| private const string PropertyPostTopic = "{0}/{1}/{2}/property/post"; // 属性上传 |
| private const string EventPostTopic = "{0}/{1}/{2}/event/post"; // 事件上传 |
| private const string ServiceSendTopic = "{0}/{1}/{2}/service/send"; // 服务下发 |

3.2 HMAC-SHA1 认证算法

认证公式

复制代码

|-------------------------------------------------------------------------|
| clientId = "{项目ID}-{产品ID}-{设备ID}" |
| userName = "{项目ID}&{产品ID}&{设备ID}" |
| password = HMAC-SHA1(DeviceKey, clientId + userName).toLowerCase(hex) |

Managers/MqttClientManager.cs - Connect方法

复制代码

|-------------------------------------------------------------------------------------------------|
| public bool Connect() |
| { |
| // clientId: YFIoT_TEST-YF3300_ESP32S3-YF3300_ESP32S301 |
| // userName: YFIoT_TEST&YF3300_ESP32S3&YF3300_ESP32S301 |
| // password: HMAC-SHA1签名 → 小写十六进制 |
| string clientId = $"{ProjectId}-{ProductId}-{DeviceId}"; |
| string username = $"{ProjectId}&{ProductId}&{DeviceId}"; |
| string password = CalculateHmacSha1(clientId + username, DeviceKey).ToLower(); |
| |
| _mqttClient = new MqttClient(MqttServer, MqttPort, false, null, null, MqttSslProtocols.None); |
| |
| // 注册回调 |
| _mqttClient.MqttMsgPublishReceived += OnMessageReceived; |
| _mqttClient.ConnectionClosed += OnConnectionClosed; |
| |
| var result = _mqttClient.Connect(clientId, username, password, false, 60); |
| if (result == MqttReasonCode.Success) |
| { |
| SubscribeServiceTopic(); // 订阅服务下发主题 |
| return true; |
| } |
| return false; |
| } |

3.3 属性上传

属性上传使用自定义JSON序列化(nanoFramework的 System.Text.Json 功能有限):

复制代码

|------------------------------------------------------------------------------------|
| public bool PublishProperties(Hashtable properties) |
| { |
| var request = new PropertyPostRequest |
| { |
| id = GenerateMessageId(), |
| timestamp = GetCurrentTimestamp(), |
| parameters = properties // { "H":36.2, "T":29.3, "I1":0, "I2":0, "Q1":0 } |
| }; |
| |
| string json = SerializeToJson(request); |
| string topic = string.Format(PropertyPostTopic, ProjectId, ProductId, DeviceId); |
| _mqttClient.Publish(topic, Encoding.UTF8.GetBytes(json), null, null, |
| MqttQoSLevel.AtLeastOnce, false); |
| return true; |
| } |

上传的JSON格式

复制代码

|-------------------------------|
| { |
| "id": 1234578, |
| "timestamp": 1716355200000, |
| "params": { |
| "H": 36.2, |
| "T": 29.3, |
| "I1": 0, |
| "I2": 0, |
| "Q1": 0 |
| } |
| } |

相关推荐
yqcoder1 小时前
httpOnly 是什么,又有什么用?
开发语言·前端·javascript
wuqingshun3141592 小时前
重写equals而不重写hashCode,会出什么问题?
java·开发语言
飞猪~2 小时前
LangChain python 版本 第一集
开发语言·python·langchain
李燚4 小时前
Go 项目怎么组织:DDD 4 层 vs MVC vs 脚本式
开发语言·golang·mvc·ddd·agent框架·eino
2zcode5 小时前
免费开源项目文档:基于MATLAB图像处理的啤酒瓶口缺陷检测系统设计与实现
开发语言·图像处理·matlab
人工智能时代 准备好了吗5 小时前
AI回答内容进入率监测:引用识别、文本匹配与语义判断
开发语言·人工智能·python
LONGZETECH5 小时前
新能源汽车动力电池检测仿真教学系统:C/S 分层架构与数字化实训落地全解析
大数据·c语言·开发语言·人工智能·架构·系统架构·汽车
郝学胜-神的一滴5 小时前
中级OpenGL教程 013:渲染器类架构设计与逐帧渲染流程详解
开发语言·c++·unity·游戏引擎·图形渲染·opengl·unreal
Metaphor6926 小时前
使用 Python 冻结 Excel 文件中的行、列和单元格
开发语言·python·excel