【仓颉】二、一个仓颉的Modbus库-6. Modbus轮询报文:ModbusRequest与ModbusDataResponse

我们再次看一下ModbusBase:

package modbus

import hex_bufferconvert.*
import hex_bufferconvert.macros.*
/*struct ModbusCommand {
    static const READ_COIL_STATUS  = 1u8
    static const READ_INPUT_STATUS = 2u8
    static const READ_HOLDING_REGISTER = 3u8
    static const READ_INPUT_REGISTER = 4u8
    static const FORCE_SINGLE_COIL = 5u8
    static const PRESET_SINGLE_REGISTER = 6u8
    static const FORCE_MULTIPLE_COILS = 15u8
    static const PRESET_MULTIPLE_REGISTERS = 16u8
}*/
abstract class ModbusBase{
    var linkLayer : ILinkLayer
    init(id:UInt8,command:UInt8,initLen:UInt8,linkLayer:ILinkLayer) {
        this.linkLayer = linkLayer
        this.linkLayer.initLen(initLen)
        linkLayer.BaseData.setUInt8(0,id)
        linkLayer.BaseData.setUInt8(1,command)
    }
    init(buffer : Array<Byte>,linkLayer:ILinkLayer) {
        this.linkLayer = linkLayer
        this.linkLayer.setBuffer(buffer)
    }
    //取出内容部分。仅在继承子类中可用
    protected prop Content : Array<UInt8>{
        get(){          
            @LenCheckThrow(linkLayer.BaseData.size <= 3)
            linkLayer.BaseData[2..]
        }
    }
    //Modbus报文帧的地址ID
    public mut prop Id: UInt8 {
        get() {
            linkLayer.BaseData.getUInt8(0)
        }
        set(value) {
            linkLayer.BaseData.setUInt8(0,value)
        }
    }
    //Modbus报文帧的命令字
    public mut prop Command: UInt8 {
        get() {
            linkLayer.BaseData.getUInt8(1)
        }
        set(value) {
            linkLayer.BaseData.setUInt8(1,value)
        }
    }

    public func toArray() : Array<UInt8>{
        linkLayer.getFrameData()
    }

    public static func createRequest(addr:UInt8,command:UInt8,startRegNo:UInt16,regCount:UInt16,linkLayer:ILinkLayer) : ModbusRequest{
        ModbusRequest(addr,command,startRegNo,regCount,linkLayer)
    }
    public static func createRequest(basedata : Array<Byte>,linkLayer:ILinkLayer) : ModbusRequest{
        ModbusRequest(basedata,linkLayer)
    }
    public static func createResponse(addr:UInt8,command:UInt8,datas:Array<UInt8>,linkLayer:ILinkLayer) : ModbusDataResponse{
        ModbusDataResponse(addr,command,datas,linkLayer)
    }
    public static func createResponse(basedata : Array<Byte>,linkLayer:ILinkLayer) : ModbusDataResponse{
        ModbusDataResponse(basedata,linkLayer)
    }
}

构造函数传入连接层的实例,构建连接层长度。基础数据从连接层引用,逻辑通畅了。

CreateRequest与CreateResponse以及他们的重载,是构建不同报文的静态方法。分别提供从命令结构创建,以及从数组创建两条路。

对应两个派生类:ModbusRequest与ModbusDataResponse

src/modbus/modbus_request.cj

package modbus

import hex_bufferconvert.*
//请求报文
class ModbusRequest <: ModbusBase{
    public init(id:UInt8,command:UInt8,startRegNo:UInt16,regCount:UInt16,linkLayer: ILinkLayer) {
        super(id, command, 6, linkLayer)
        this.StartRegNo = startRegNo
        this.RegCount = regCount
    }
    public init(basedata : Array<Byte>,linkLayer: ILinkLayer) {
        super(basedata,linkLayer)
    }
    //起始寄存器号
    public mut prop StartRegNo : UInt16{
        get(){
            Content.getUInt16AB(0)
        }
        set(value){
            Content.setUInt16AB(0, value)
        }
    }
    //寄存器个数
    public mut prop RegCount : UInt16{
        get(){
            Content.getUInt16AB(2)
        }
        set(value){
            Content.setUInt16AB(2, value)
        }
    }
}

src/modbus/modbus_dataresponse.cj

package modbus

//Modbus报文传送帧。响应数据,发送控制,发送遥调,以及遥控遥调响应
class ModbusDataResponse <: ModbusBase{    
    //从命令创建Modbus报文帧
    public init(id:UInt8,command:UInt8,datas:Array<UInt8>,linkLayer: ILinkLayer) {
        super(id, command, UInt8(3 + datas.size), linkLayer)
        if(datas.size > 252){
            throw Exception("数据长度不能超过252")
        }
        this.DataLen = UInt8(datas.size)
        datas.copyTo(this.Datas,0,0,datas.size)
    }
    //从数组创建Modbus报文帧
    public init(basedata : Array<Byte>,linkLayer: ILinkLayer) {
        super(basedata,linkLayer)
    }
    //数据长度
    public mut prop DataLen : UInt8{
        get(){
            Content.getUInt8(0)
        }
        set(value){
            Content.setUInt8(0,value)
        }
    }
    //取出内容部分。仅在继承子类中可用
    protected prop Datas : Array<UInt8>{
        get(){          
            @LenCheckThrow(Content.size <= 1)
            Content[1..]
        }
    }
}

至此,Modbus命令初步完成。

  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值