脚本说明

在Modbus Slave Emulator中,可以使用自定义C#脚本。编写脚本时,你需要实现下面这个抽象类,当主站(客户端)发起读写寄存器请求时,执行脚本中对应的方法。

namespace ModbusSlave.Script
{
    public abstract class DefaultHandler
    {
        /// <summary>
        /// 下面四种数组,代表了用户在UI上配置的每种类型的寄存器
        /// 注意:这些数组都是只读的,不要写入数据
        /// 从站配置了多个就访问多少,数组索引不要超限
        /// 比如,配置保持寄存器,起始地址10 (base 0),数量为100
        /// 那么应该使用HoldingRegisters[10],HoldingRegisters[11],...,HoldingRegisters[109]
        /// </summary>
        public ModbusSlave.Script.ReadOnlyArray<bool> CoilDiscretes; //线圈状态数组
        public ModbusSlave.Script.ReadOnlyArray<bool> CoilInputs; //离散输入状态
        public ModbusSlave.Script.ReadOnlyArray<ushort> HoldingRegisters; //保持寄存器
        public ModbusSlave.Script.ReadOnlyArray<ushort> InputRegisters; //输入寄存器

        /// <summary>
        /// 读线圈状态
        /// </summary>
        /// <param name="startAddress">寄存器起始地址(Protocol Address Base 0)</param>
        /// <param name="numberOfPoints">读取的数量</param>
        /// <returns>如果返回null,则返回用户配置的寄存器数据;如果不是null,则返回脚本提供的数据</returns>
        public virtual bool[] ReadCoilDiscretes(ushort startAddress, ushort numberOfPoints)
        {
            return null;
        }

        /// <summary>
        /// 写线圈状态
        /// </summary>
        /// <param name="startAddress">寄存器起始地址(Protocol Address Base 0)</param>
        /// <param name="points">要写入的数据</param>
        public virtual void WriteCoilDiscretes(ushort startAddress, bool[] points)
        {
        }

        /// <summary>
        /// 读离散输入状态
        /// </summary>
        /// <param name="startAddress">寄存器起始地址(Protocol Address Base 0)</param>
        /// <param name="numberOfPoints">读取的数量</param>
        /// <returns>如果返回null,则返回用户配置的寄存器数据;如果不是null,则返回脚本提供的数据</returns>
        public virtual bool[] ReadCoilInputs(ushort startAddress, ushort numberOfPoints)
        {
            return null;
        }

        /// <summary>
        /// 读保持寄存器
        /// </summary>
        /// <param name="startAddress">寄存器起始地址(Protocol Address Base 0)</param>
        /// <param name="numberOfPoints">读取的数量</param>
        /// <returns>如果返回null,则返回用户配置的寄存器数据;如果不是null,则返回脚本提供的数据</returns>
        public virtual ushort[] ReadHoldingRegisters(ushort startAddress, ushort numberOfPoints)
        {
            return null;
        }

        /// <summary>
        /// 写保持寄存器
        /// </summary>
        /// <param name="startAddress">寄存器起始地址(Protocol Address Base 0)</param>
        /// <param name="points">要写入的数据</param>
        public virtual void WriteHoldingRegisters(ushort startAddress, ushort[] points)
        {
        }

        /// <summary>
        /// 读输入寄存器
        /// </summary>
        /// <param name="startAddress">寄存器起始地址(Protocol Address Base 0)</param>
        /// <param name="numberOfPoints">读取的数量</param>
        /// <returns>如果返回null,则返回用户配置的寄存器数据;如果不是null,则返回脚本提供的数据</returns>
        public virtual ushort[] ReadInputRegisters(ushort startAddress, ushort numberOfPoints)
        {
            return null;
        }
    }
}
下面是一个实现上面接口的例子,注意:DefaultHandler的实现类必须命名为Handler
using System;
using System.Collections.Generic;
using System.Linq;
using System.Collections.ObjectModel;

/// <summary>
/// ModbusSlave.Script.DefaultHandler实现示例
/// </summary>
public class Handler : ModbusSlave.Script.DefaultHandler
{
    /// <summary>
    /// 读线圈状态
    /// </summary>
    /// <param name="startAddress">寄存器起始地址(Protocol Address Base 0)</param>
    /// <param name="numberOfPoints">读取的数量</param>
    /// <returns>如果返回null,则返回用户配置的寄存器数据;如果不是null,则返回脚本提供的数据</returns>
    public override bool[] ReadCoilDiscretes(ushort startAddress, ushort numberOfPoints)
    {
        bool[] array = new bool[numberOfPoints];
        for (int i = 0; i < array.Length; i++)
        {
            if (i % 2 == 0)
            {
                //返回在UI表格里配置的数据值,并取反
                array[i] = !CoilDiscretes[startAddress + i];
            }
            else
            {
                array[i] = false;
            }
        }

        return array;
    }

    /// <summary>
    /// 写线圈状态
    /// </summary>
    /// <param name="startAddress">寄存器起始地址(Protocol Address Base 0)</param>
    /// <param name="points">要写入的数据</param>
    public override void WriteCoilDiscretes(ushort startAddress, bool[] points)
    {
        //ignore
    }

    /// <summary>
    /// 读离散输入状态
    /// </summary>
    /// <param name="startAddress">寄存器起始地址(Protocol Address Base 0)</param>
    /// <param name="numberOfPoints">读取的数量</param>
    /// <returns>如果返回null,则返回用户配置的寄存器数据;如果不是null,则返回脚本提供的数据</returns>
    public override bool[] ReadCoilInputs(ushort startAddress, ushort numberOfPoints)
    {
        bool[] array = new bool[numberOfPoints];
        for (int i = 0; i < array.Length; i++)
        {
            array[i] = true;
        }

        return array;
    }

    /// <summary>
    /// 读保持寄存器
    /// </summary>
    /// <param name="startAddress">寄存器起始地址(Protocol Address Base 0)</param>
    /// <param name="numberOfPoints">读取的数量</param>
    /// <returns>如果返回null,则返回用户配置的寄存器数据;如果不是null,则返回脚本提供的数据</returns>
    public override ushort[] ReadHoldingRegisters(ushort startAddress, ushort numberOfPoints)
    {
        ushort[] array = new ushort[numberOfPoints];
        for (int i = 0; i < array.Length; i++)
        {
            //返回在UI表格里配置的数据值,并+3
            array[i] = (ushort) (HoldingRegisters[startAddress + i] + 3);
        }

        return array;
    }

    /// <summary>
    /// 写保持寄存器
    /// </summary>
    /// <param name="startAddress">寄存器起始地址(Protocol Address Base 0)</param>
    /// <param name="points">要写入的数据</param>
    public override void WriteHoldingRegisters(ushort startAddress, ushort[] points)
    {
        //ignore
    }

    /// <summary>
    /// 读输入寄存器
    /// </summary>
    /// <param name="startAddress">寄存器起始地址(Protocol Address Base 0)</param>
    /// <param name="numberOfPoints">读取的数量</param>
    /// <returns></returns>
    public override ushort[] ReadInputRegisters(ushort startAddress, ushort numberOfPoints)
    {
        ushort[] array = new ushort[numberOfPoints];
        for (int i = 0; i < array.Length; i++)
        {
            //返回在UI表格里配置的数据值,并+1
            array[i] = (ushort) (InputRegisters[startAddress + i] + 1);
        }

        return array;
    }
}