You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ntool-biz/nmodbus/handler/handler.go

91 lines
1.9 KiB
Go

1 year ago
package handler
import (
"encoding/binary"
"git.noahlan.cn/noahlan/nnet/connection"
"git.noahlan.cn/noahlan/nnet/packet"
rt "git.noahlan.cn/noahlan/nnet/router"
"git.noahlan.cn/noahlan/ntool-biz/nmodbus/protocol"
"git.noahlan.cn/noahlan/ntool/nlog"
"sync"
1 year ago
)
var _ rt.Handler = (*Handler)(nil)
type (
Handler struct {
byteOrder binary.ByteOrder // 字节序
functions map[uint8]FunctionHandler
dataMap map[uint8]*DataMgr
mu sync.RWMutex
1 year ago
}
FunctionHandler func(handler *Handler, pkg protocol.Packet) ([]byte, *protocol.MError)
)
func NewHandler(byteOrder binary.ByteOrder) *Handler {
p := &Handler{
byteOrder: byteOrder,
functions: make(map[uint8]FunctionHandler),
dataMap: make(map[uint8]*DataMgr),
mu: sync.RWMutex{},
1 year ago
}
// 添加功能码对应功能
p.functions[0x01] = ReadCoils
p.functions[0x02] = ReadDiscreteInputs
p.functions[0x03] = ReadHoldingRegisters
p.functions[0x04] = ReadInputRegisters
p.functions[0x05] = WriteSingleCoil
p.functions[0x06] = WriteHoldingRegister
p.functions[0x0F] = WriteMultipleCoils
p.functions[0x10] = WriteHoldingRegisters
return p
}
func (p *Handler) RegisterFunction(fnCode uint8, fn FunctionHandler) {
p.functions[fnCode] = fn
}
func (p *Handler) DataManager(address uint8) *DataMgr {
p.mu.Lock()
defer p.mu.Unlock()
ret, ok := p.dataMap[address]
if !ok {
ret = NewDataManager(address)
p.dataMap[address] = ret
}
return ret
}
1 year ago
func (p *Handler) Handle(conn *connection.Connection, pkg packet.IPacket) {
pp, ok := pkg.(protocol.Packet)
if !ok {
nlog.Error(packet.ErrWrongPacketType)
}
var (
err *protocol.MError
data []byte
)
resp := pp.Copy()
fnCode := pp.GetFunction()
fn, ok := p.functions[fnCode]
if ok {
data, err = fn(p, pp)
resp.SetBody(data)
} else {
err = &protocol.IllegalFunction
}
if err != &protocol.Success {
resp.SetError(err)
}
_ = conn.Send(resp.GetHeader(), resp.GetBody())
}