惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Microsoft Security Blog
Microsoft Security Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
A
About on SuperTechFans
月光博客
月光博客
Jina AI
Jina AI
F
Fortinet All Blogs
博客园 - 聂微东
The Cloudflare Blog
美团技术团队
B
Blog RSS Feed
N
Netflix TechBlog - Medium
罗磊的独立博客
The GitHub Blog
The GitHub Blog
I
InfoQ
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Apple Machine Learning Research
Apple Machine Learning Research
H
Help Net Security
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
The Blog of Author Tim Ferriss
MyScale Blog
MyScale Blog
博客园 - 三生石上(FineUI控件)
宝玉的分享
宝玉的分享
阮一峰的网络日志
阮一峰的网络日志
V
V2EX

博客园 - Eric zhou

Github Project-AI Agentic Framework (.NET) 我不是给 AI 装了一堆插件,我是在搭一套工作能力系统 我不是在用 AI 助手,我在把自己的能力沉淀成组织资产 .NET 10 新特性概览与相关文章索引 .NET 10 & C# 14 New Features 新增功能介绍-ASP.NET Core 基于Microsoft.Extensions.AI 和 Microsoft.Extensions.VectorData构建向量搜索 Windows 安装 OpenClaw 踩坑全记录:Node、Git、CMake、VS Build Tools 一次解决 .NET 10 & C# 14 New Features 新增功能介绍-.NET CLI工具改进 .NET 10 & C# 14 New Features 新增功能介绍-再看Top Level Program .NET 10 & C# 14 New Features 新增功能介绍-带修饰符的简单 lambda 参数 .NET 10 & C# 14 New Features 新增功能介绍-Null 条件分配(Null-conditional assignment) .NET 10 & C# 14 New Features 新增功能介绍-field关键字 .NET 10 & C# 14 New Features 新增功能介绍-扩展成员Extension Members 总结归纳.NET 10 中 Minimal APIs 主要应用场景 .NET 10 New feature 新增功能介绍-Minimal APIs增强 .NET 10 New feature 新增功能介绍-WebSocket功能增强 Google A2UI本地部署记录 .NET10 New feature 新增功能介绍-类库新增功能 关于Agentic AI的一些总结和思考 .NET10 New feature 新增功能介绍-JIT编译器改进
基于.NET和C#构建光伏IoT物模型方案
Eric zhou · 2026-01-16 · via 博客园 - Eric zhou

一、目前国内接入最常见、最有代表性的 4 类光伏设备

 image.png

二、华为 SUN2000 逆变器通讯报文示例

这是一个标准 Modbus TCP 请求报文

00 01 00 00 00 06 01 03 75 30 00 06

含义:

Modbus TCP 报文由两部分组成:

MBAP Header(7字节) + PDU(功能码 + 数据)

image.png

image.png

image.png

在光伏逆变器里,这类请求通常用于:

image.png

响应

这是一个标准的Modbus TCP 响应报文结构

00 01 00 00 00 0F 01 03 0C 09 C4 00 64 13 88 00 32

MBAP Header(7字节) + PDU(功能码 + 数据)

image.png

PDU数据解析

image.pngimage.png

结合光伏业务的数值换算

厂家协议通常定义 倍率(Scale)

image.png

最终物模型字段赋值示例

{ “dcVoltage”: 250.0, “dcCurrent”: 10.0, “dcPower”: 5.0, “internalTemp”: 50 }

三、示例代码

报文请求构造 → 响应报文解析 → 寄存器解码 → 光伏设备物模型组织

目标:

  • 协议层、解析层、物模型层解耦

  • 方便后续做 多品牌 Adapter + 配置化映射

代码结构

image.png

1、Modbus TCP 请求报文构造

ModbusRequest.cs

public class ModbusRequest
{
    public ushort TransactionId { get; set; }
    public byte UnitId { get; set; }
    public byte FunctionCode { get; set; } = 0x03;
    public ushort StartAddress { get; set; }
    public ushort Quantity { get; set; }

    public byte[] ToBytes()
    {
        var buffer = new List<byte>();

        // Transaction ID
        buffer.AddRange(BitConverter.GetBytes(TransactionId).Reverse());

        // Protocol ID (0x0000)
        buffer.Add(0x00);
        buffer.Add(0x00);

        // Length = UnitId + PDU
        ushort length = 1 + 1 + 2 + 2;
        buffer.AddRange(BitConverter.GetBytes(length).Reverse());

        // Unit ID
        buffer.Add(UnitId);

        // PDU
        buffer.Add(FunctionCode);
        buffer.AddRange(BitConverter.GetBytes(StartAddress).Reverse());
        buffer.AddRange(BitConverter.GetBytes(Quantity).Reverse());

        return buffer.ToArray();
    }
}

2. Modbus TCP 响应解析

ModbusResponse.cs

public class ModbusResponse
{
    public ushort TransactionId { get; set; }
    public byte UnitId { get; set; }
    public byte FunctionCode { get; set; }
    public byte ByteCount { get; set; }
    public byte[] Data { get; set; }
}

ModbusParser.cs

public static class ModbusParser
{
    public static ModbusResponse ParseResponse(byte[] response)
    {
        if (response.Length < 9)
            throw new Exception("Invalid Modbus response length");

        var result = new ModbusResponse();

        result.TransactionId = ReadUInt16(response, 0);
        ushort protocolId = ReadUInt16(response, 2);
        ushort length = ReadUInt16(response, 4);

        if (protocolId != 0)
            throw new Exception("Invalid Protocol ID");

        result.UnitId = response[6];
        result.FunctionCode = response[7];
        result.ByteCount = response[8];

        result.Data = response.Skip(9).Take(result.ByteCount).ToArray();

        return result;
    }

    private static ushort ReadUInt16(byte[] buffer, int index)
    {
        return (ushort)((buffer[index] << 8) | buffer[index + 1]);
    }
}

3. 寄存器解码(倍率 + 字节序)

RegisterDecoder.cs

public static class RegisterDecoder
{
    public static ushort ReadUInt16(byte[] data, int registerIndex)
    {
        int offset = registerIndex * 2;
        return (ushort)((data[offset] << 8) | data[offset + 1]);
    }

    public static double ReadScaledValue(
        byte[] data,
        int registerIndex,
        double scale)
    {
        return ReadUInt16(data, registerIndex) / scale;
    }
}

4、光伏设备物模型定义

PvThingModel.cs

public class PvThingModel
{
    public double DcVoltage { get; set; }
    public double DcCurrent { get; set; }
    public double DcPower { get; set; }
    public double InternalTemperature { get; set; }

    public DateTime Timestamp { get; set; } = DateTime.UtcNow;
}

5. 从响应到物模型的映射

public static class PvThingModelBuilder
{
    public static PvThingModel FromModbus(ModbusResponse response)
    {
        var data = response.Data;

        return new PvThingModel
        {
            DcVoltage = RegisterDecoder.ReadScaledValue(data, 0, 10),     // 30000
            DcCurrent = RegisterDecoder.ReadScaledValue(data, 1, 10),     // 30001
            DcPower = RegisterDecoder.ReadScaledValue(data, 2, 1000),     // 30002
            InternalTemperature = RegisterDecoder.ReadUInt16(data, 3)     // 30003
        };
    }
}

6. 完整示例调用(Demo)

public class Demo
{
    public static void Run()
    {
        // 1. 构造请求
        var request = new ModbusRequest
        {
            TransactionId = 1,
            UnitId = 1,
            StartAddress = 30000,
            Quantity = 6
        };

        byte[] requestBytes = request.ToBytes();

        // === 这里通常通过 TCP Socket 发送 requestBytes ===

        // 2. 模拟接收到的响应报文
        byte[] responseBytes =
        {
            0x00,0x01,0x00,0x00,0x00,0x0F,0x01,0x03,0x0C,
            0x09,0xC4,0x00,0x64,0x13,0x88,0x00,0x32
        };

        // 3. 解析响应
        var response = ModbusParser.ParseResponse(responseBytes);

        // 4. 构建物模型
        PvThingModel model = PvThingModelBuilder.FromModbus(response);

        Console.WriteLine($"DC Voltage: {model.DcVoltage} V");
        Console.WriteLine($"DC Current: {model.DcCurrent} A");
        Console.WriteLine($"DC Power: {model.DcPower} kW");
        Console.WriteLine($"Temperature: {model.InternalTemperature} ℃");
    }
}