package n9m import ( "errors" "fmt" "net" ) type notFoundError struct { message string } func (e *notFoundError) Error() string { return fmt.Sprintf("not found %s", e.message) } func NewSmartPackage(conn net.Conn) *SmartPackage { return &SmartPackage{ pack: Package{}, conn: conn, buff: make([]byte, 1024), payloadProcess: make(map[PayloadType]ProcessFunc), jsonProcess: make(map[string]ProcessFunc), alarmProcess: make(map[AlarmType]AlarmProcessFunc), Storage: make(map[string]interface{}), } } func (pack *SmartPackage) AddPayloadHandler(payloadType PayloadType, processFunc ProcessFunc) { pack.payloadProcess[payloadType] = processFunc } func (pack *SmartPackage) AddJSONHandler(module, operation string, processFunc ProcessFunc) { pack.jsonProcess[fmt.Sprintf("%s:%s", module, operation)] = processFunc } func (pack *SmartPackage) AddAlarmHandler(alarmType AlarmType, processFunc AlarmProcessFunc) { pack.alarmProcess[alarmType] = processFunc } func (pack *SmartPackage) handleAlarm() (err error) { if !(pack.pack.PayloadType == PayloadTypeData && pack.pack.Payload.Module == "EVEM" && pack.pack.Payload.Operation == "SENDALARMINFO") { return fmt.Errorf("invalid payload type or operation for alarm handling") } var params SendAlarmInfoParameters if err = pack.pack.GetParametersAs(¶ms); err != nil { return fmt.Errorf("invalid payload") } var processFunc AlarmProcessFunc var ok bool if processFunc, ok = pack.alarmProcess[params.AlarmType]; !ok { return ¬FoundError{ message: fmt.Sprintf("alarm %d", params.AlarmType), } } var response SendAlarmInfoResponse response.ErrorCode = 0 response.AlarmType = params.AlarmType response.CommandType = params.CommandType response.AlarmUID = params.AlarmUID response.NumberOfRestarts = params.NumberOfRestarts response.InstructionSerial = params.InstructionSerial return processFunc(pack, pack.pack, response) } func (pack *SmartPackage) handleJson() (err error) { if pack.pack.PayloadType != PayloadTypeData { return fmt.Errorf("invalid json payload type") } var nfErr *notFoundError if err = pack.handleAlarm(); err == nil || errors.As(err, &nfErr) { return } var processFunc ProcessFunc var ok bool var key = fmt.Sprintf("%s:%s", pack.pack.Payload.Module, pack.pack.Payload.Operation) if processFunc, ok = pack.jsonProcess[key]; !ok { return ¬FoundError{ message: fmt.Sprintf("json %s", key), } } return processFunc(pack, pack.pack) } func (pack *SmartPackage) handle() (err error) { var nfErr *notFoundError if err = pack.handleJson(); err == nil || errors.As(err, &nfErr) { return } var processFunc ProcessFunc var ok bool if processFunc, ok = pack.payloadProcess[pack.pack.PayloadType]; !ok { return ¬FoundError{ message: fmt.Sprintf("payload type %d", pack.pack.PayloadType), } } return processFunc(pack, pack.pack) } func (pack *SmartPackage) handleLoop() (err error) { for pack.pack.ReadPackage() { if err = pack.handle(); err != nil { return err } } return } func (pack *SmartPackage) Handle() (err error) { if err = pack.handleLoop(); err != nil { return err } var rn int if rn, err = pack.conn.Read(pack.buff); err != nil { return } pack.pack.AddToAccum(pack.buff[:rn]) return pack.handleLoop() } func (pack *SmartPackage) GetPackage() Package { return pack.pack } func (pack *SmartPackage) Write(data []byte) (int, error) { return pack.conn.Write(data) }