using System;
 
 
namespace YFSoft.Hardware.YF3300_ESP32S3
{
    public static class CPU
    {
        public static class Pins
        {
            // GPIO 0-47
            public const int GPIO0 = 0;
            public const int GPIO1 = 1;
            public const int GPIO2 = 2;
            public const int GPIO3 = 3;
            public const int GPIO4 = 4;
            public const int GPIO5 = 5;
            public const int GPIO6 = 6;
            public const int GPIO7 = 7;
            public const int GPIO8 = 8;
            public const int GPIO9 = 9;
            public const int GPIO10 = 10;
            public const int GPIO11 = 11;
            public const int GPIO12 = 12;
            public const int GPIO13 = 13;
            public const int GPIO14 = 14;
            public const int GPIO15 = 15;
            public const int GPIO16 = 16;
            public const int GPIO17 = 17;
            public const int GPIO18 = 18;
            public const int GPIO19 = 19;
            public const int GPIO20 = 20;
            public const int GPIO21 = 21;
            public const int GPIO22 = 22;
            public const int GPIO23 = 23;
            public const int GPIO24 = 24;
            public const int GPIO25 = 25;
            public const int GPIO26 = 26;
            public const int GPIO27 = 27;
            public const int GPIO28 = 28;
            public const int GPIO29 = 29;
            public const int GPIO30 = 30;
            public const int GPIO31 = 31;
            public const int GPIO32 = 32;
            public const int GPIO33 = 33;
            public const int GPIO34 = 34;
            public const int GPIO35 = 35;
            public const int GPIO36 = 36;
            public const int GPIO37 = 37;
            public const int GPIO38 = 38;
            public const int GPIO39 = 39;
            public const int GPIO40 = 40;
            public const int GPIO41 = 41;
            public const int GPIO42 = 42;
            public const int GPIO43 = 43;
            public const int GPIO44 = 44;
            public const int GPIO45 = 45;
            public const int GPIO46 = 46;
            public const int GPIO47 = 47;
            public const int GPIO48 = 48;
        }
    }
 
    public static class Mainboard
    {
        // 主板引脚定义
        public static class Pins
        {
            // LED 指示灯(根据实际硬件连接)
            public const int YellowLED = CPU.Pins.GPIO40;   // 黄色LED - 网络状态指示
            public const int GreenLED = CPU.Pins.GPIO39;    // 绿色LED - 配网状态指示
 
            // 兼容旧命名
            public const int CommLED = YellowLED;           // 通信指示灯(黄色)
            public const int UserLED = GreenLED;            // 用户指示灯(绿色)
 
            // 按钮
            public const int BOOT = CPU.Pins.GPIO0;
 
            // 开关量输入
            public const int I1 = CPU.Pins.GPIO21;           // 输入1
            public const int I2 = CPU.Pins.GPIO47;           // 输入2
 
            // 继电器输出
            public const int Q1 = CPU.Pins.GPIO48;           // 继电器1
 
        }
 
        // RS485 串口定义
        public static class RS485
        {
            public const string PortName = "COM1";
            public const int DefaultBaudRate = 9600;
            public const int TxPin = CPU.Pins.GPIO9;        // UART1 TX (电路图: TX1=IO9)
            public const int RxPin = CPU.Pins.GPIO10;       // UART1 RX (电路图: RX1=IO10)
        }
 
        // RS232 串口定义
        public static class RS232
        {
            public const string PortName = "COM2";
            public const int DefaultBaudRate = 9600;
            public const int TxPin = CPU.Pins.GPIO11;       // UART2 TX (电路图: TX2=IO11)
            public const int RxPin = CPU.Pins.GPIO12;       // UART2 RX (电路图: RX2=IO12)
        }
 
        // I2C 总线定义
        public static class I2C
        {
            public const int BusId = 1;
            public const int SdaPin = CPU.Pins.GPIO17;
            public const int SclPin = CPU.Pins.GPIO18;
            public const int DefaultSpeed = 100000; // 100kHz
        }
 
        // 开关量输入通道
        public static class DigitalInputs
        {
            public const int Count = 2;
            public static readonly int[] Channels = { Mainboard.Pins.I1, Mainboard.Pins.I2 };
        }
 
        // 继电器输出通道
        public static class Relays
        {
            public const int Count = 1;
            public static readonly int[] Channels = { Mainboard.Pins.Q1 };
        }
 
        // LED 闪烁时间定义(毫秒)
        public static class LEDTiming
        {
            // 黄色LED - 网络状态指示
            public const int NetworkConnecting_On = 0;          // 常亮(正在连接)
            public const int NetworkConnecting_Off = int.MaxValue;
 
            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 ConfigAP_Off = int.MaxValue;
 
            public const int ConfigSuccess_On = 500;           // 慢闪(配网成功)
            public const int ConfigSuccess_Off = 1500;
 
            public const int ConfigFailed_On = 200;             // 快闪(配网失败)
            public const int ConfigFailed_Off = 200;
 
            public const int ConfigNormal_On = 0;               // 熄灭(正常运行)
            public const int ConfigNormal_Off = 0;
        }
    }
 
    // 设备信息定义
    public static class DeviceInfo
    {
        public const string DeviceName = "YF3300-ESP32S3";      // 设备名称
        public const string Manufacturer = "YFSoft";            // 制造商
        public const string HardwareVersion = "1.0.0";          // 硬件版本
        public const string FirmwareVersion = "1.0.0";          // 固件版本
        public const string Model = "YF3300-ESP32S3";           // 设备型号
    }
 
    // 系统配置常量
    public static class SystemConfig
    {
        // WiFi 配置
        public const int WiFiConnectTimeout = 15000;            // WiFi连接超时(毫秒)
        public const int WiFiReconnectInterval = 5000;          // WiFi重连间隔(毫秒)
 
        // MQTT 配置
        public const string DefaultMqttServer = "mqtt.yfiot.com"; // 默认MQTT服务器
        public const int DefaultMqttPort = 1883;                // 默认MQTT端口
        public const int MqttKeepAliveInterval = 60;            // MQTT心跳间隔(秒)
        public const int MqttReconnectInterval = 5000;          // MQTT重连间隔(毫秒)
 
        // AP 配网配置
        public const string APSSID = "YF3300_ESP32S3";         // AP热点名称
        public const string APPassword = "yf123456";           // AP热点密码
        public const string APIP = "192.168.4.1";              // AP网关IP
        public const int APConfigTimeout = 600000;              // 配网超时(10分钟)
 
        // 数据采集配置
        public const int SensorReadInterval = 30000;            // 传感器读取间隔(毫秒)
        public const int DataUploadInterval = 30000;            // 数据上传间隔(毫秒)
 
        // 看门狗配置
        public const int WatchdogTimeout = 30000;               // 看门狗超时(毫秒)
 
        // NTP 配置
        public const string DefaultNtpServer = "ntp.aliyun.com"; // 默认NTP服务器
        public const int NtpSyncInterval = 3600000;             // NTP同步间隔(1小时)
 
        // 按钮配置
        public const int ButtonLongPressDuration = 5000;        // 长按时间(毫秒)
        public const int ButtonDebounceTime = 50;               // 按钮防抖时间(毫秒)
    }
}
Models/YFLinkModels.cs

using System;
using System.Collections;
 
namespace YeFanIoTTest.Models
{
    // YFLink协议基础请求模型
    public class YFLinkRequest
    {
        public int id { get; set; }                  // 消息ID(32位整数)
        public string ver { get; set; } = "1.3.0";  // 协议版本
        public long timestamp { get; set; }          // 时间戳(1970年1月1日以来的毫秒数)
    }
 
    // YFLink协议基础响应模型
    public class YFLinkResponse
    {
        public int id { get; set; }                  // 消息ID(与请求ID对应)
        public int code { get; set; }                // 返回结果编码(200表示成功)
        public string message { get; set; }          // 返回结果描述
    }
 
    // 属性上传请求模型
    public class PropertyPostRequest : YFLinkRequest
    {
        public Hashtable parameters { get; set; }    // 属性键值对集合
    }
 
    // 属性上传响应模型
    public class PropertyPostResponse : YFLinkResponse
    {
        public ArrayList data { 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; }                // 事件编码(32位整数)
        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; }        // 服务参数
    }
 
    // 服务响应模型
    public class ServiceSendResponse : YFLinkRequest
    {
        public ServiceResultParams parameters { get; set; } // 服务响应参数
    }
 
    // 服务响应参数模型
    public class ServiceResultParams
    {
        public int code { get; set; }                // 服务响应标识符
        public string content { get; set; }          // 服务响应内容
    }
 
    // NTP校时请求模型
    public class NtpRequest : YFLinkRequest
    {
        public NtpParams parameters { get; set; }     // NTP参数
    }
 
    // NTP参数模型
    public class NtpParams
    {
        public long deviceSendTime { get; set; }     // 设备发送请求的时间
    }
 
    // NTP校时响应模型
    public class NtpResponse : YFLinkResponse
    {
        public NtpResponseParams parameters { get; set; } // NTP响应参数
    }
 
    // NTP响应参数模型
    public class NtpResponseParams
    {
        public long deviceSendTime { get; set; }     // 设备发送请求的时间
        public long serverRecvTime { get; set; }     // 服务器接收到该请求的时间
        public long serverSendTime { get; set; }     // 服务器发起发送该响应的时间
    }
}
Models/DeviceModels.cs

using System;
 
namespace YeFanIoTTest.Models
{
    // 设备配置模型 - 包含YFLink协议四元组及MQTT服务器配置
    public class DeviceConfig
    {
        public string ProjectID { get; set; }      // 项目ID
        public string ProductID { get; set; }      // 产品ID
        public string DeviceID { get; set; }       // 设备ID
        public string DeviceKey { get; set; }      // 设备密钥(32位随机字符)
        public string MqttServer { get; set; }     // MQTT服务器地址
        public int MqttPort { get; set; }          // MQTT服务器端口
 
        // 验证设备配置是否有效
        public bool IsValid()
        {
            return !string.IsNullOrEmpty(ProjectID) &&
                   !string.IsNullOrEmpty(ProductID) &&
                   !string.IsNullOrEmpty(DeviceID) &&
                   !string.IsNullOrEmpty(DeviceKey);
        }
    }
 
    // WiFi配置模型
    public class WifiConfig
    {
        public string SSID { get; set; }           // WiFi名称
        public string Password { get; set; }       // WiFi密码
 
        // 验证WiFi配置是否有效
        public bool IsValid()
        {
            return !string.IsNullOrEmpty(SSID) && !string.IsNullOrEmpty(Password);
        }
    }
 
    // 传感器数据模型 - 存储温湿度传感器采集的数据
    public class SensorData
    {
        public double Temperature { get; set; }    // 温度值(摄氏度)
        public double Humidity { get; set; }       // 湿度值(百分比)
        public DateTime Timestamp { get; set; }    // 数据采集时间戳
 
        // 格式化输出传感器数据
        public override string ToString()
        {
            return $"Temperature: {Temperature:F1}°C, Humidity: {Humidity:F1}%";
        }
    }
 
    // 继电器状态模型
    public class RelayState
    {
        public int RelayId { get; set; }           // 继电器ID(1, 2, 3...)
        public bool IsOn { get; set; }             // 继电器状态(true=打开,false=关闭)
        public DateTime Timestamp { get; set; }    // 状态更新时间戳
    }
 
    // 开关量输入状态模型
    public class DigitalInputState
    {
        public int InputId { get; set; }           // 输入通道ID(1, 2, 3...)
        public bool IsHigh { get; set; }           // 输入状态(true=高电平,false=低电平)
        public DateTime Timestamp { get; set; }    // 状态更新时间戳
    }
}
Enums/Enums.cs

using System;
 
namespace YeFanIoTTest.Enums
{
    // 设备状态枚举 - 用于表示设备的生命周期状态
    public enum DeviceState
    {
        Initializing,       // 初始化中
        CheckingConfig,      // 检查配置
        APConfiguring,       // AP配网中
        ConnectingWifi,      // 连接WiFi中
        ConnectingCloud,     // 连接云端中
        NormalRunning,       // 正常运行
        Error                // 错误状态
    }
 
    // 网络状态枚举 - 用于表示WiFi和MQTT连接状态
    public enum NetworkStatus
    {
        Connecting,          // 连接中
        Connected,           // 已连接
        Disconnected,        // 已断开
        Error                // 错误
    }
 
    // 配网状态枚举 - 用于表示AP配网过程的状态
    public enum ConfigStatus
    {
        Configuring,         // 配网中
        Success,             // 配网成功
        Failed,              // 配网失败
        Normal               // 正常运行
    }
 
    // LED闪烁模式枚举
    public enum LedBlinkMode
    {
        Off,                 // 关闭
        On,                  // 常亮
        SlowBlink,           // 慢闪
        FastBlink            // 快闪
    }
 
    // 事件类型枚举 - 对应YFLink协议中的事件类型定义
    public enum EventType
    {
        Info = 0,            // 信息事件
        Warning = 1,         // 告警事件
        Fault = 2            // 故障事件
    }
 
    // 服务类型枚举 - 对应YFLink协议中的服务类型定义
    public enum ServiceType
    {
        Command = 0,         // 命令服务
        Parameter = 1        // 参数服务
    }
}
Drivers/Sht30Sensor.cs

using System;
using System.Device.I2c;
using Microsoft.Extensions.Logging;
using nanoFramework.Logging;
using nanoFramework.Hardware.Esp32;
using YFSoft.Hardware.YF3300_ESP32S3;
 
namespace YeFanIoTTest.Drivers
{
    // SHT30传感器数据模型
    public class Sht30Data
    {
        public double Temperature { get; set; }     // 温度值(摄氏度)
        public double Humidity { get; set; }        // 湿度值(百分比)
        public DateTime Timestamp { get; set; }     // 数据读取时间戳
 
        // 格式化输出传感器数据
        public override string ToString()
        {
            return $"Temperature: {Temperature:F1}°C, Humidity: {Humidity:F1}%, Time: {Timestamp:HH:mm:ss}";
        }
    }
 
    // SHT30温湿度传感器驱动类
    // 使用纯I2C通信协议实现,不依赖外部库
    public class Sht30Sensor : IDisposable
    {
        private readonly ILogger _logger;
        private I2cDevice _i2cDevice;                       // I2C 设备实例
        private bool _disposed = false;
 
        // SHT30 I2C命令定义
        private const byte CMD_MEASURE_HIGH_REP = 0x2C;      // 单次测量命令(高重复性)
        private const byte CMD_MEASURE_HIGH_REP_2 = 0x06;    // 单次测量命令第二字节
        private const byte CMD_SOFT_RESET = 0x30;            // 软复位命令
        private const byte CMD_SOFT_RESET_2 = 0xA2;          // 软复位命令第二字节
        private const byte CMD_READ_STATUS = 0xF3;           // 读状态寄存器命令
        private const byte CMD_READ_STATUS_2 = 0x2D;         // 读状态寄存器命令第二字节
 
        // 默认构造函数:使用默认I2C配置
        public Sht30Sensor()
        {
            _logger = LogDispatcher.LoggerFactory.CreateLogger("Sht30Sensor");
            
            try
            {
                // 配置I2C引脚
                Configuration.SetPinFunction(Mainboard.I2C.SdaPin, DeviceFunction.I2C1_DATA);
                Configuration.SetPinFunction(Mainboard.I2C.SclPin, DeviceFunction.I2C1_CLOCK);
 
                // 创建I2C设备(默认地址0x44)
                var i2cSettings = new I2cConnectionSettings(Mainboard.I2C.BusId, 0x44);
                _i2cDevice = I2cDevice.Create(i2cSettings);
 
                _logger.LogInformation($"SHT30 sensor initialized on I2C bus {Mainboard.I2C.BusId}, address: 0x44");
            }
            catch (Exception ex)
            {
                _logger.LogError($"Failed to initialize SHT30 sensor: {ex.Message}");
                throw;
            }
        }
 
        // 带参数构造函数
        // i2cBusId: I2C总线ID
        // sensorAddress: 传感器地址(0x44或0x45)
        public Sht30Sensor(int i2cBusId, byte sensorAddress)
        {
            _logger = LogDispatcher.LoggerFactory.CreateLogger("Sht30Sensor");
            
            try
            {
                // 配置I2C引脚
                Configuration.SetPinFunction(Mainboard.I2C.SdaPin, DeviceFunction.I2C1_DATA);
                Configuration.SetPinFunction(Mainboard.I2C.SclPin, DeviceFunction.I2C1_CLOCK);
 
                // 创建I2C设备
                var i2cSettings = new I2cConnectionSettings(i2cBusId, sensorAddress);
                _i2cDevice = I2cDevice.Create(i2cSettings);
 
                _logger.LogInformation($"SHT30 sensor initialized on I2C bus {i2cBusId}, address: 0x{sensorAddress:X2}");
            }
            catch (Exception ex)
            {
                _logger.LogError($"Failed to initialize SHT30 sensor: {ex.Message}");
                throw;
            }
        }
 
        // 读取传感器数据
        // 返回:Sht30Data对象,读取失败返回null
        public Sht30Data ReadMeasurement()
        {
            if (_disposed)
            {
                _logger.LogWarning("Sensor has been disposed");
                return null;
            }
 
            try
            {
                // 发送测量命令(单次测量,高重复性)
                byte[] writeBuffer = new byte[] { CMD_MEASURE_HIGH_REP, CMD_MEASURE_HIGH_REP_2 };
                _i2cDevice.Write(writeBuffer);
 
                // 等待测量完成(高重复性测量需要约15ms)
                System.Threading.Thread.Sleep(20);
 
                // 读取6字节数据:温度高字节、温度低字节、温度CRC、湿度高字节、湿度低字节、湿度CRC
                byte[] readBuffer = new byte[6];
                _i2cDevice.Read(readBuffer);
 
                // 解析温度数据(前2字节)
                int rawTemperature = (readBuffer[0] << 8) | readBuffer[1];
                
                // 解析湿度数据(后2字节,跳过CRC)
                int rawHumidity = (readBuffer[3] << 8) | readBuffer[4];
 
                // 计算实际温度和湿度
                // 温度公式:T = -45 + 175 * (raw / 65535.0)
                // 湿度公式:RH = 100 * (raw / 65535.0)
                double temperature = -45.0 + (175.0 * rawTemperature / 65535.0);
                double humidity = 100.0 * rawHumidity / 65535.0;
 
                // CRC校验(可选)
                if (!CheckCRC(readBuffer[0], readBuffer[1], readBuffer[2]))
                {
                    _logger.LogWarning("Temperature CRC check failed");
                }
                
                if (!CheckCRC(readBuffer[3], readBuffer[4], readBuffer[5]))
                {
                    _logger.LogWarning("Humidity CRC check failed");
                }
 
                return new Sht30Data
                {
                    Temperature = temperature,
                    Humidity = humidity,
                    Timestamp = DateTime.UtcNow
                };
            }
            catch (Exception ex)
            {
                _logger.LogError($"Failed to read SHT30 sensor: {ex.Message}");
                return null;
            }
        }
 
        // 重置传感器
        public void Reset()
        {
            if (_disposed)
            {
                _logger.LogWarning("Sensor has been disposed");
                return;
            }
 
            try
            {
                // 发送软复位命令
                byte[] writeBuffer = new byte[] { CMD_SOFT_RESET, CMD_SOFT_RESET_2 };
                _i2cDevice.Write(writeBuffer);
 
                // 等待复位完成
                System.Threading.Thread.Sleep(10);
 
                _logger.LogInformation("SHT30 sensor reset successfully");
            }
            catch (Exception ex)
            {
                _logger.LogError($"Failed to reset SHT30 sensor: {ex.Message}");
            }
        }
 
        // 读取状态寄存器
        public ushort ReadStatus()
        {
            if (_disposed)
            {
                _logger.LogWarning("Sensor has been disposed");
                return 0;
            }
 
            try
            {
                // 发送读状态命令
                byte[] writeBuffer = new byte[] { CMD_READ_STATUS, CMD_READ_STATUS_2 };
                _i2cDevice.Write(writeBuffer);
 
                // 读取3字节:状态高字节、状态低字节、CRC
                byte[] readBuffer = new byte[3];
                _i2cDevice.Read(readBuffer);
 
                // 组合状态字
                ushort status = (ushort)((readBuffer[0] << 8) | readBuffer[1]);
 
                return status;
            }
            catch (Exception ex)
            {
                _logger.LogError($"Failed to read SHT30 status: {ex.Message}");
                return 0;
            }
        }
 
        // CRC校验函数
        // data1: 数据字节1
        // data2: 数据字节2
        // crc: CRC校验字节
        // 返回:校验是否通过
        private bool CheckCRC(byte data1, byte data2, byte crc)
        {
            // SHT30使用CRC-8校验
            // 多项式:0x31 (x^8 + x^5 + x^4 + 1)
            // 初始值:0xFF
            byte crcValue = 0xFF;
            
            // 计算第一个字节的CRC
            crcValue ^= data1;
            for (int i = 0; i < 8; i++)
            {
                if ((crcValue & 0x80) != 0)
                {
                    crcValue = (byte)((crcValue << 1) ^ 0x31);
                }
                else
                {
                    crcValue = (byte)(crcValue << 1);
                }
            }
            
            // 计算第二个字节的CRC
            crcValue ^= data2;
            for (int i = 0; i < 8; i++)
            {
                if ((crcValue & 0x80) != 0)
                {
                    crcValue = (byte)((crcValue << 1) ^ 0x31);
                }
                else
                {
                    crcValue = (byte)(crcValue << 1);
                }
            }
            
            return crcValue == crc;
        }
 
        // 释放资源
        public void Dispose()
        {
            if (_disposed) return;
 
            try
            {
                if (_i2cDevice != null)
                {
                    _i2cDevice.Dispose();
                    _i2cDevice = null;
                }
 
                _disposed = true;
                _logger.LogInformation("SHT30 sensor disposed");
            }
            catch (Exception ex)
            {
                _logger.LogError($"Error disposing SHT30 sensor: {ex.Message}");
            }
        }
    }

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐