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" ) var _ rt.Handler = (*Handler)(nil) type ( Handler struct { byteOrder binary.ByteOrder // 字节序 logics map[uint8]LogicFunc handlerMap map[uint8]FunctionHandler dataMap map[uint8]*DataMgr mu sync.RWMutex } FunctionHandler interface { Function(handler *Handler, req protocol.Packet, resp protocol.Packet) *protocol.MError FnCode() uint8 } LogicFunc func(startAddr, number int, val any) ) func NewHandler(byteOrder binary.ByteOrder) *Handler { p := &Handler{ byteOrder: byteOrder, //functions: make(map[uint8]FunctionFunc), logics: make(map[uint8]LogicFunc), handlerMap: make(map[uint8]FunctionHandler), dataMap: make(map[uint8]*DataMgr), mu: sync.RWMutex{}, } // 添加功能码对应功能 p.RegisterFunction(NewReadCoils(0x01)) p.RegisterFunction(NewReadDiscreteInputs(0x02)) p.RegisterFunction(NewReadHoldingRegisters(0x03)) p.RegisterFunction(NewReadInputRegisters(0x04)) p.RegisterFunction(NewWriteSingleCoil(0x05)) p.RegisterFunction(NewWriteHoldingRegister(0x06)) p.RegisterFunction(NewWriteMultipleCoils(0x0F)) p.RegisterFunction(NewWriteHoldingRegisters(0x10)) return p } func (p *Handler) RegisterFunction(fn FunctionHandler) { p.handlerMap[fn.FnCode()] = fn } func (p *Handler) RegisterLogic(fnCode uint8, fn LogicFunc) { p.logics[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 } func (p *Handler) Handle(conn *connection.Connection, pkg packet.IPacket) { req, ok := pkg.(protocol.Packet) if !ok { nlog.Error(packet.ErrWrongPacketType) } var err *protocol.MError resp := req.Copy() fnCode := req.GetFunction() handler, ok := p.handlerMap[fnCode] if ok { err = handler.Function(p, req, resp) } else { err = &protocol.IllegalFunction } if err != &protocol.Success { resp.SetError(err) } _ = conn.Send(resp.GetHeader(), resp.GetBody()) } func (p *Handler) HandleLogic(fnCode uint8, startAddr, number int, val any) { go func() { if fn, ok := p.logics[fnCode]; ok { fn(startAddr, number, val) } }() }