我们再次看一下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命令初步完成。