From 335f7aad009598fa464b7a476507daca67f8424f Mon Sep 17 00:00:00 2001 From: shenyuguang Date: Fri, 15 Sep 2023 15:54:01 +0800 Subject: [PATCH] update --- Idriver.go | 49 ------------ basedrv.go | 16 ++-- callback.go | 18 ----- commu/commu.go | 130 ++++++++++++++++++++++++++++++- commu/serail.go | 78 +++++++++++++++++++ commu/tcpclient.go | 4 + commu/tcpserver.go | 4 + core/Idriver.go | 51 ++++++++++++ core/core.go | 4 + core/handler.go | 16 ++++ core/instr.go | 31 ++++++-- core/scheduler.go | 29 +++++++ execunit.go | 24 ------ genericdrv.go | 89 ++++++++------------- go.mod | 5 +- go.sum | 4 + strutils.go => utils/strutils.go | 2 +- 17 files changed, 386 insertions(+), 168 deletions(-) delete mode 100644 Idriver.go delete mode 100644 callback.go create mode 100644 commu/serail.go create mode 100644 commu/tcpclient.go create mode 100644 commu/tcpserver.go create mode 100644 core/Idriver.go create mode 100644 core/handler.go create mode 100644 core/scheduler.go delete mode 100644 execunit.go create mode 100644 go.sum rename strutils.go => utils/strutils.go (95%) diff --git a/Idriver.go b/Idriver.go deleted file mode 100644 index d11ce0c..0000000 --- a/Idriver.go +++ /dev/null @@ -1,49 +0,0 @@ -package iotbase - -import "github.com/akingbrDu/iotbase/core" - -type IDriver interface { - // Init * - //@brief: init - // * @param: configJson: 配置参数 - // * @param: modelJson: 物模型参数 - // * @return: 错误码 - Init(device core.Device, configJson string, modelJson string, handler IEventHandler) error - - //// Query * - ////@brief: start - //// * @param: - //// * @return: 字节流 错误码 - //Query() ([]byte, error) - // - //// Process * - ////@brief: process - //// * @param: data: 字节流 - //// * @return: 上报数据, 错误码 - //Process(data []byte) (string, error) - - // ExeCommand * - //@brief: execute command - // * @param: cmd: 命令结构 - // * @return: 错误码 - ExeCommand(cmd core.Command) error - - // SetOption * - //@brief: set option - // * @param: key: 键 - // * @param: value: 值 - // * @return: 错误码 - SetOption(key string, value string) error -} - -// IParamParseHook 初始化解析钩子 -type IParamParseHook interface { - // onParamBefore *初始化解析参数前的钩子 - onParamBefore() error - // onParamParsed *初始化解析参数后的钩子 - onParamParsed() error - // onCreateDefaultCommunicator 创建默认通讯器 - onCreateDefaultCommunicator() (ICommunicator, error) - // onCreateExecUnits 创建执行单元 - onCreateExecUnits(units []ExecUnit) error -} diff --git a/basedrv.go b/basedrv.go index d761320..4616db0 100644 --- a/basedrv.go +++ b/basedrv.go @@ -9,11 +9,11 @@ type BaseDriver struct { device core.Device model core.ModelAriot deploy core.DeployAriot - handler IEventHandler - initParamHook IParamParseHook + handler core.IEventHandler + initParamHook core.IInitHook } -func (drv *BaseDriver) Init(device core.Device, configJson string, modelJson string, handler IEventHandler) error { +func (drv *BaseDriver) Init(device core.Device, configJson string, modelJson string, handler core.IEventHandler) error { drv.handler = handler drv.device = device @@ -32,30 +32,30 @@ func (drv *BaseDriver) Init(device core.Device, configJson string, modelJson str func (drv *BaseDriver) emitStatus(status core.Status) { if drv.handler != nil { - drv.handler.onStatus(status) + drv.handler.OnStatus(status) } } func (drv *BaseDriver) emitError(warn core.Warn) { if drv.handler != nil { - drv.handler.onError(warn) + drv.handler.OnError(warn) } } func (drv *BaseDriver) emitProperty(property core.Property) { if drv.handler != nil { - drv.handler.onProperty(property) + drv.handler.OnProperty(property) } } func (drv *BaseDriver) emitProperties(properties []core.Property) { if drv.handler != nil { - drv.handler.onProperties(properties) + drv.handler.OnProperties(properties) } } func (drv *BaseDriver) emitCommandReply(reply core.CommandReply) { if drv.handler != nil { - drv.handler.onCommandReply(reply) + drv.handler.OnCommandReply(reply) } } diff --git a/callback.go b/callback.go deleted file mode 100644 index add3081..0000000 --- a/callback.go +++ /dev/null @@ -1,18 +0,0 @@ -package iotbase - -import "github.com/akingbrDu/iotbase/core" - -type DbgInformation struct { - FileName string - MethodName string - Line int - Reason string -} - -type IEventHandler interface { - onError(warn core.Warn) - onProperty(property core.Property) - onProperties(properties []core.Property) - onStatus(status core.Status) - onCommandReply(reply core.CommandReply) -} diff --git a/commu/commu.go b/commu/commu.go index ea70d35..5c7dcc6 100644 --- a/commu/commu.go +++ b/commu/commu.go @@ -1,7 +1,131 @@ package commu -import _ "github.com/akingbrDu/iotbase/core" +import ( + "errors" + "fmt" + "github.com/tarm/serial" + "sync" +) -type ICommunicator interface { - Send(cmd InstrCommand) error +var ( + cuFactoryInstance *CommunicatorFactory + recLock sync.Mutex +) + +//const ( +// Serial = "serial" +// TcpClient = "tcpclient" +// TcpServer = "tcpserver" +//) + +//type ICommunicator interface { +// Start() error +// Close() error +//} + +const ( + SerialPortName = "port" + SeralBaudRate = "baudrate" + SerialDataBit = "databit" + SerialStopBit = "stopbit" + SerialParity = "parity" +) + +type CommunicatorFactory struct { +} + +func (factory CommunicatorFactory) CreateTcpServerCommunicator(param map[string]interface{}) (*TcpServerCommunicator, error) { + return nil, nil +} + +func (factory CommunicatorFactory) CreateTcpClientCommunicator(param map[string]interface{}) (*TcpClientCommunicator, error) { + return nil, nil +} + +func (factory CommunicatorFactory) CreateSerialCommunicator(param map[string]interface{}) (*SerialCommunicator, error) { + portName, ok := param[SerialPortName].(string) + if !ok { + fmt.Println("can't parse port field in param information") + return nil, errors.New("can't parse port field in param information") + } + + baudRate, ok := param[SeralBaudRate].(int) + if !ok { + fmt.Println("can't parse baudrate field in param information") + return nil, errors.New("can't parse baudrate field in param information") + } + + dataBits, ok := param[SerialDataBit].(byte) + if !ok { + fmt.Println("can't parse databit field in param information") + return nil, errors.New("can't parse databit field in param information") + } + + stopBits, ok := param[SerialStopBit].(int) + if !ok { + fmt.Println("can't parse stopbit field in param information") + return nil, errors.New("can't parse stopbit field in param information") + } + + sb, err := factory.ConvertStopBits(stopBits) + if err != nil { + return nil, err + } + + parity, ok := param[SerialParity].(int) + if !ok { + fmt.Println("can't parse parity field in param information") + return nil, errors.New("can't parse parity field in param information") + } + + pr, err := factory.ConvertParity(parity) + if err != nil { + return nil, err + } + + return &SerialCommunicator{ + portName: portName, + baudRate: baudRate, + dataBits: dataBits, + stopBits: sb, + parity: pr, + }, nil +} + +func (factory CommunicatorFactory) ConvertStopBits(stopBits int) (serial.StopBits, error) { + switch stopBits { + case 1: + return serial.Stop1, nil + case 2: + return serial.Stop2, nil + default: + return serial.Stop1, errors.New("unsupported stop bit setting") + } +} + +func (factory CommunicatorFactory) ConvertParity(parity int) (serial.Parity, error) { + switch parity { + case 0: + return serial.ParityNone, nil + case 1: + return serial.ParityOdd, nil + case 2: + return serial.ParityEven, nil + case 3: + return serial.ParityMark, nil + case 4: + return serial.ParitySpace, nil + default: + return serial.ParityNone, errors.New("unsupported parity setting") + } +} + +func GetCommunicatorFactory() *CommunicatorFactory { + recLock.Lock() + defer recLock.Unlock() + + if cuFactoryInstance == nil { + cuFactoryInstance = &CommunicatorFactory{} + } + return cuFactoryInstance } diff --git a/commu/serail.go b/commu/serail.go new file mode 100644 index 0000000..0c11f25 --- /dev/null +++ b/commu/serail.go @@ -0,0 +1,78 @@ +package commu + +import ( + "errors" + "fmt" + "github.com/tarm/serial" +) + +type SerialCommunicator struct { + portName string + baudRate int + dataBits byte + stopBits serial.StopBits + parity serial.Parity + + io *serial.Port +} + +func (s *SerialCommunicator) Connect() error { + config := &serial.Config{ + Name: s.portName, // 串口设备名称 + Baud: s.baudRate, // 波特率 + Size: s.dataBits, // 数据位 + StopBits: s.stopBits, + Parity: s.parity, + } + + port, err := serial.OpenPort(config) + if err != nil { + fmt.Println("fail to open serial port with err: ", err) + return errors.New(fmt.Sprintf("fail to open serial port with err: %v", err)) + } + + fmt.Println("success to open serial port: ", s.portName) + s.io = port + return nil +} + +func (s *SerialCommunicator) Send(data []byte) (int, error) { + if s.io == nil { + fmt.Println("serial port is not opened") + return 0, errors.New("serial port is not opened") + } + + byteLen, err := s.io.Write(data) + if err != nil { + fmt.Println("fail to write serial port with err: ", err) + return byteLen, errors.New(fmt.Sprintf("fail to write serial port with err: %v", err)) + } else { + return byteLen, nil + } +} + +func (s *SerialCommunicator) Receive(data []byte) (int, error) { + if s.io == nil { + fmt.Println("serial port is not opened") + return 0, errors.New("serial port is not opened") + } + + byteLen, err := s.io.Read(data) + if err != nil { + fmt.Println("fail to read serial port with err: ", err) + return byteLen, errors.New(fmt.Sprintf("fail to read serial port with err: %v", err)) + } else { + return byteLen, nil + } +} + +func (s *SerialCommunicator) Close() error { + if s.io != nil { + err := s.io.Close() + if err != nil { + fmt.Println("fail to close serial port with err: ", err) + return err + } + } + return nil +} diff --git a/commu/tcpclient.go b/commu/tcpclient.go new file mode 100644 index 0000000..f626728 --- /dev/null +++ b/commu/tcpclient.go @@ -0,0 +1,4 @@ +package commu + +type TcpClientCommunicator struct { +} \ No newline at end of file diff --git a/commu/tcpserver.go b/commu/tcpserver.go new file mode 100644 index 0000000..07175e8 --- /dev/null +++ b/commu/tcpserver.go @@ -0,0 +1,4 @@ +package commu + +type TcpServerCommunicator struct { +} diff --git a/core/Idriver.go b/core/Idriver.go new file mode 100644 index 0000000..b6b191d --- /dev/null +++ b/core/Idriver.go @@ -0,0 +1,51 @@ +package core + +type IDriver interface { + // Init * + //@brief: init + // * @param: configJson: 配置参数 + // * @param: modelJson: 物模型参数 + // * @return: 错误码 + Init(device Device, configJson string, modelJson string, handler IEventHandler) error + + // Run * + // 驱动启动运行 + Run() error + + // ExeCommand * + //@brief: execute command + // * @param: cmd: 命令结构 + // * @return: 错误码 + ExeCommand(cmd Command) error + + // SetOption * + //@brief: set option + // * @param: key: 键 + // * @param: value: 值 + // * @return: 错误码 + SetOption(key string, value string) error +} + +type IQueryDriver interface { + IDriver + IQuery +} + +type ICallbackDriver interface { + IDriver + ICallback +} + +type IQueryAndCallbackDriver interface { + IDriver + IQuery + ICallback +} + +// IInitHook 初始化解析钩子 +type IInitHook interface { + // OnBefInitialize *初始化解析参数前的钩子 + OnBefInitialize() error + // OnInitialized *初始化解析参数后的钩子 + OnInitialized() error +} diff --git a/core/core.go b/core/core.go index beb693d..b91e073 100644 --- a/core/core.go +++ b/core/core.go @@ -61,3 +61,7 @@ type DeviceWarn struct { Identifier string `json:"identifier"` ParamList []WarningParam `json:"paramList"` } + +// IErrorHandler 定义处理器 +type IErrorHandler interface { +} diff --git a/core/handler.go b/core/handler.go new file mode 100644 index 0000000..67537b9 --- /dev/null +++ b/core/handler.go @@ -0,0 +1,16 @@ +package core + +type DbgInformation struct { + FileName string + MethodName string + Line int + Reason string +} + +type IEventHandler interface { + OnError(warn Warn) + OnProperty(property Property) + OnProperties(properties []Property) + OnStatus(status Status) + OnCommandReply(reply CommandReply) +} diff --git a/core/instr.go b/core/instr.go index db6bd1d..8708168 100644 --- a/core/instr.go +++ b/core/instr.go @@ -1,19 +1,34 @@ package core -type IInstrResultParser interface { - parseContent(interface{}) map[string]interface{} +//type IInstrResultParser interface { +// ParseContent(interface{}) map[string]interface{} +//} + +type IInstrCommand interface { + CheckIfFinished() bool + Parse() map[string]interface{} } -type InstrCommand struct { - parser IInstrResultParser +type BaseInstrCommand struct { + //Parser IInstrResultParser } type BinaryInstrCommand struct { - InstrCommand - data []byte + BaseInstrCommand + OutData []byte + IncomingData []byte +} + +func (cmd *BinaryInstrCommand) checkIfFinished() bool { + return true } type StringInstrCommand struct { - InstrCommand - data string + BaseInstrCommand + OutData string + IncomingData string +} + +func (cmd *StringInstrCommand) checkIfFinished() bool { + return true } diff --git a/core/scheduler.go b/core/scheduler.go new file mode 100644 index 0000000..4869091 --- /dev/null +++ b/core/scheduler.go @@ -0,0 +1,29 @@ +package core + +type IScheduler interface { + Register(query IQuery) error + Run() error +} + +// IQuery 查询类驱动需要支持 +type IQuery interface { + Query() error + GetFreq() int +} + +// ICallback 回调类驱动需要支持 +type ICallback interface { + Callback() error +} + +// DefaultSharedScheduler 默认共享端口查询调度 +type DefaultSharedScheduler struct { +} + +func (s *DefaultSharedScheduler) Register(query IQuery) error { + return nil +} + +func (s *DefaultSharedScheduler) Run() error { + return nil +} diff --git a/execunit.go b/execunit.go deleted file mode 100644 index 54d47c9..0000000 --- a/execunit.go +++ /dev/null @@ -1,24 +0,0 @@ -package iotbase - -import "github.com/akingbrDu/iotbase/core" - -// 驱动执行单元 -// 执行单元调度类型 -const ( - Query = iota - Callback -) - -// 执行单元执行模式 -const ( - Interval = iota - Once -) - -type ExecUnit struct { - RunType int - RunMode int - Freq int - Sender ICommunicator - CmdSet []core.InstrCommand -} diff --git a/genericdrv.go b/genericdrv.go index b5f61f0..c7243b7 100644 --- a/genericdrv.go +++ b/genericdrv.go @@ -9,7 +9,13 @@ import ( type GenericDriver struct { BaseDriver - freq int + freq int + runtimeInfo map[string]interface{} + cmuType string + cmuParamInfo map[string]interface{} + protoType string + protoParamInfo map[string]interface{} + defSharedScheduler core.IScheduler } func (drv *GenericDriver) parseRawMessage(rawMessage *json.RawMessage) (map[string]interface{}, error) { @@ -28,10 +34,10 @@ func (drv *GenericDriver) parseRawMessage(rawMessage *json.RawMessage) (map[stri } // Init 因为Go支持组合,对abstract继承的支持不是很好,所以所有Hook接口 -// 都统一放到base包的最下层 -func (drv *GenericDriver) Init(device core.Device, configJson string, modelJson string, handler IEventHandler) error { +// 都统一放到Generic实现的最下面 +func (drv *GenericDriver) Init(device core.Device, configJson string, modelJson string, handler core.IEventHandler) error { if drv.initParamHook != nil { - if err := drv.initParamHook.onParamBefore(); err != nil { + if err := drv.initParamHook.OnBefInitialize(); err != nil { return err } } @@ -47,80 +53,51 @@ func (drv *GenericDriver) Init(device core.Device, configJson string, modelJson return err } - commuParamInfo, err := drv.parseRawMessage(&drv.deploy.Communication.Param) + cmuParamInfo, err := drv.parseRawMessage(&drv.deploy.Communication.Param) if err != nil { fmt.Println("fail to decode communication param field in json with err: :", err) return err } + protoParamInfo, err := drv.parseRawMessage(&drv.deploy.Proto.Param) + if err != nil { + fmt.Println("fail to decode proto param field in json with err: :", err) + return err + } + freq, ok := runtimeInfo["freq"].(int) if !ok { fmt.Println("can't parse freq field in json\"") return errors.New("can't parse freq field in json") } + + //解析一些常用的字段 + drv.runtimeInfo = runtimeInfo + drv.cmuParamInfo = cmuParamInfo + drv.cmuType = drv.deploy.Communication.Type + drv.protoParamInfo = protoParamInfo + drv.protoType = drv.deploy.Proto.Type drv.freq = freq + drv.CreateScheduler() + if drv.initParamHook != nil { - if err := drv.initParamHook.onParamParsed(); err != nil { + if err := drv.initParamHook.OnInitialized(); err != nil { return err } } - defCommunicator, err := drv.createCommunicator(drv.deploy.Communication.Type, commuParamInfo) - if err != nil { - fmt.Println("fail to create communicator with err: :", err) - return err - } - - //创建驱动执行单元 - units, err := drv.createExecUnits(defCommunicator) - if err != nil { - return err - } - - //分配调度 - err = drv.schedule(units) - if err != nil { - return err - } - return nil } -func (drv *GenericDriver) createCommunicator(cType string, param map[string]interface{}) (ICommunicator, error) { - if drv.initParamHook != nil { - if communicator, err := drv.initParamHook.onCreateDefaultCommunicator(); err != nil { - return nil, err - } else if communicator != nil { - return communicator, nil - } - } else { - //create default waiting.. - } - return nil, nil +func (drv *GenericDriver) CreateScheduler() { + drv.defSharedScheduler = &core.DefaultSharedScheduler{} } -func (drv *GenericDriver) createExecUnits(defCommunicator ICommunicator) ([]ExecUnit, error) { - var units []ExecUnit - if drv.initParamHook != nil { - if err := drv.initParamHook.onCreateExecUnits(units); err != nil { - return nil, err - } - - //如果不自定义通讯器,则使用默认通讯器 - for _, unit := range units { - if unit.Sender == nil { - unit.Sender = defCommunicator - } - - if unit.RunType == Query && unit.Freq <= 0 { - unit.Freq = drv.freq - } - } +func (drv *GenericDriver) Run() error { + err := drv.defSharedScheduler.Run() + if err != nil { + return err } - return units, nil -} - -func (drv *GenericDriver) schedule(units []ExecUnit) error { return nil } diff --git a/go.mod b/go.mod index cd57284..e083eac 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,6 @@ module github.com/akingbrDu/iotbase -go 1.16 +go 1.19 + +require github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07 +require golang.org/x/sys v0.12.0 // indirect diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..b36cffd --- /dev/null +++ b/go.sum @@ -0,0 +1,4 @@ +github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07 h1:UyzmZLoiDWMRywV4DUYb9Fbt8uiOSooupjTq10vpvnU= +github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= +golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/strutils.go b/utils/strutils.go similarity index 95% rename from strutils.go rename to utils/strutils.go index 241fb49..fbf2e34 100644 --- a/strutils.go +++ b/utils/strutils.go @@ -1,4 +1,4 @@ -package iotbase +package utils import ( "reflect"