modbus(二)用NModbus4库实现Modbus tcp从站

public class ModbusTcpSlaveDemo : IDisposable
{

    ILogger _Logger;
    public ModbusTcpSlaveDemo(ILogger<ModbusTcpSlaveDemo> logger)
    {
        _Logger = logger;
        Start();
    }


    #region Modbus TCP 从站实现

    private TcpListener _listener;
    private ModbusSlave _slave;
    private bool _isRunning;

    public byte SlaveId { get; set; } = 1;
    public int Port { get; set; } = 502;

    public void Start()
    {
        if (_isRunning) return;

        try
        {
            // 创建TCP监听器
            _listener = new TcpListener(IPAddress.Any, Port);
            _listener.Start();

            // 创建Modbus TCP从站
            _slave = ModbusTcpSlave.CreateTcp(SlaveId, _listener);

            // 初始化测试数据到Modbus数据存储
            InitializeTestData();

            // 启动从站
            _slave.Listen();

            _isRunning = true;

            _Logger.LogInformation($"Modbus TCP从机启动成功");
            _Logger.LogInformation($"从站ID: {SlaveId}, 端口: {Port}");
            PrintTestDataInfo();
        }
        catch (Exception ex)
        {
            _Logger.LogError(ex, $"Modbus TCP从机启动失败");
            throw;
        }
    }

    private void InitializeTestData()
    {
        // 获取数据存储
        var dataStore = _slave.DataStore;

        // 初始化保持寄存器 (地址 1-9) - 使用正确的API
        for (ushort i = 1; i < 10; i++)
        {
            dataStore.HoldingRegisters[i] = (ushort)((i + 1) * 100);
        }

        // 初始化输入寄存器 (地址 1-9)
        for (ushort i = 1; i < 10; i++)
        {
            dataStore.InputRegisters[i] = (ushort)((i + 1) * 50);
        }

        for (ushort i = 1; i < 10; i++)
        {
            dataStore.CoilDiscretes[i] = (i % 2 == 0);
        }
    }

    private void PrintTestDataInfo()
    {
        var dataStore = _slave.DataStore;

        _Logger.LogInformation("测试数据已设置:");

        // 读取并显示保持寄存器
        var holdingValues = new List<string>();
        for (int i = 1; i < 5; i++)
        {
            holdingValues.Add(dataStore.HoldingRegisters[i].ToString());
        }
        _Logger.LogInformation($"保持寄存器 (地址0-4): {string.Join(", ", holdingValues)}");

        // 读取并显示输入寄存器
        var inputValues = new List<string>();
        for (int i = 1; i < 5; i++)
        {
            inputValues.Add(dataStore.InputRegisters[i].ToString());
        }
        _Logger.LogInformation($"输入寄存器 (地址0-4): {string.Join(", ", inputValues)}");

        // 读取并显示线圈
        var coilValues = new List<string>();
        for (int i = 1; i < 5; i++)
        {
            coilValues.Add(dataStore.CoilDiscretes[i] ? "ON" : "OFF");
        }
        _Logger.LogInformation($"线圈 (地址0-4): {string.Join(", ", coilValues)}");
    }

    public void UpdateHoldingRegister(ushort address, ushort value)
    {
        if (_isRunning)
        {
            _slave.DataStore.HoldingRegisters[address] = value;
            _Logger.LogInformation($"更新保持寄存器地址{address} = {value}");
        }
    }

    public ushort ReadHoldingRegister(ushort address)
    {
        if (_isRunning)
        {
            return _slave.DataStore.HoldingRegisters[address];
        }
        return 0;
    }

    public void UpdateCoil(ushort address, bool value)
    {
        if (_isRunning)
        {
            _slave.DataStore.CoilDiscretes[address] = value;
            _Logger.LogInformation($"更新线圈地址{address} = {(value ? "ON" : "OFF")}");
        }
    }

    public bool ReadCoil(ushort address)
    {
        if (_isRunning)
        {
            return _slave.DataStore.CoilDiscretes[address];
        }
        return false;
    }

    public void Stop()
    {
        if (!_isRunning) return;

        try
        {
            _listener?.Stop();
            _isRunning = false;
            _Logger.LogInformation("Modbus TCP从机已停止");
        }
        catch (Exception ex)
        {
            _Logger.LogError(ex, "停止Modbus从机时出错");
        }
    }

    public void Dispose()
    {
        Stop();
    }

    #endregion
}

 

posted @ 2025-11-22 14:16  daviyoung  阅读(5)  评论(0)    收藏  举报