512 lines
16 KiB
Go
512 lines
16 KiB
Go
package rpc
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
)
|
|
|
|
// ErrorCode for DI-Net RPC reply message
|
|
type ErrorCode uint32
|
|
|
|
// Error object for DI-Net RPC reply message
|
|
type Error struct {
|
|
Code ErrorCode `json:"code" msgpack:"code"`
|
|
Descr string `json:"descr,omitempty" msgpack:"descr,omitempty"`
|
|
Data interface{} `json:"data,omitempty" msgpack:"data,omitempty"`
|
|
}
|
|
|
|
// Error returns a descriptive error message
|
|
func (e Error) Error() string {
|
|
if e.Data != nil {
|
|
return fmt.Sprintf("%s (%+v)", e.Code.Error(), e.Code.Error())
|
|
}
|
|
return e.Code.Error()
|
|
}
|
|
|
|
// GetError constructs an error object. It automatically fills in the description based on the given error code.
|
|
// When error Ok is given, nil is returned
|
|
func GetError(err ErrorCode, data ...interface{}) *Error {
|
|
if err == Ok {
|
|
return nil
|
|
}
|
|
|
|
var v interface{}
|
|
if len(data) > 0 {
|
|
v = data[0]
|
|
}
|
|
return &Error{
|
|
Code: err,
|
|
Descr: err.String(),
|
|
Data: v,
|
|
}
|
|
}
|
|
|
|
// ErrorCode constants
|
|
const (
|
|
// Generic
|
|
Ok ErrorCode = 0
|
|
|
|
// Generic
|
|
EParam ErrorCode = 1
|
|
ERange ErrorCode = 2
|
|
ENodev ErrorCode = 3
|
|
ENores ErrorCode = 4
|
|
EBusy ErrorCode = 5
|
|
EOpnotsupp ErrorCode = 6
|
|
EProto ErrorCode = 7
|
|
EChecksum ErrorCode = 8
|
|
ETimeout ErrorCode = 9
|
|
EDisconnected ErrorCode = 10
|
|
EAgain ErrorCode = 11
|
|
EOpdenied ErrorCode = 12
|
|
EIofailed ErrorCode = 13
|
|
ENotfound ErrorCode = 14
|
|
ENomem ErrorCode = 15
|
|
|
|
// Secure server
|
|
ESecsDuplicateProject ErrorCode = 256
|
|
ESecsInvalidProjectState ErrorCode = 257
|
|
ESecsInvalidMutation ErrorCode = 258
|
|
ESecsInvalidAction ErrorCode = 259
|
|
ESecsProjectChanged ErrorCode = 260
|
|
ESecsPlanningChanged ErrorCode = 261
|
|
ESecsDesignChanged ErrorCode = 262
|
|
ESecsDatabaseError ErrorCode = 263
|
|
ESecsNoProjectData ErrorCode = 264
|
|
ESecsInvalidProject ErrorCode = 265
|
|
ESecsInvalidRequest ErrorCode = 266
|
|
ESecsInternalError ErrorCode = 267
|
|
ESecsNoBackend ErrorCode = 268
|
|
ESecsBackendInvalidMessage ErrorCode = 269
|
|
ESecsSetupChanged ErrorCode = 270
|
|
ESecsInvalidProjectType ErrorCode = 271
|
|
ESecsNoProjectGroup ErrorCode = 273
|
|
|
|
// Backend
|
|
EBackendDuplicateProject ErrorCode = 512
|
|
EBackendInvalidProject ErrorCode = 513
|
|
EBackendDeviceError ErrorCode = 514
|
|
EBackendInternalError ErrorCode = 515
|
|
EBackendInvalidMutation ErrorCode = 516
|
|
//Deprecated: Use a more specific error code
|
|
EBackendInvalidGroup ErrorCode = 517
|
|
EBackendAlreadyActivated ErrorCode = 518
|
|
EBackendAlreadyDeactivated ErrorCode = 519
|
|
EBackendMissingActivateGroups ErrorCode = 520
|
|
EBackendMissingDeactivateGroups ErrorCode = 521
|
|
EBackendCp3000CommError ErrorCode = 522
|
|
|
|
// Firmware/device
|
|
EFirmwareTilt ErrorCode = 1024
|
|
//Deprecated: Use a more specific error code
|
|
EFirmwareUltrasonic ErrorCode = 1025
|
|
EFirmwareSpeaker ErrorCode = 1026
|
|
EFirmwareEeprom ErrorCode = 1027
|
|
EFirmwareCalibration ErrorCode = 1028
|
|
EFirmwareBa ErrorCode = 1029
|
|
EFirmwareVref ErrorCode = 1030
|
|
EFirmwareVrefClipping ErrorCode = 1031
|
|
EFirmwareLeaderFailure ErrorCode = 1032
|
|
EFirmwareFollowerFailure ErrorCode = 1033
|
|
EFirmwareRotation ErrorCode = 1034
|
|
EFirmwareDetectionbutton ErrorCode = 1035
|
|
EFirmwareDeadmansTimeout ErrorCode = 1036
|
|
//Deprecated: Use a more specific error code
|
|
EFirmwareBatteryTooLow ErrorCode = 1037
|
|
EFirmwareSwitchComm ErrorCode = 1038
|
|
EFirmwareLeaderConflict ErrorCode = 1039
|
|
EFirmwareTemperature ErrorCode = 1040
|
|
EFirmwareMeasurement ErrorCode = 1041
|
|
EFirmwareGps ErrorCode = 1042
|
|
EFirmwareMcuComm ErrorCode = 1043
|
|
EFirmwareDuStrikeRoleUnknown ErrorCode = 1044
|
|
EFirmwareModemUartFraming ErrorCode = 1045
|
|
EFirmwareBatteryBoard ErrorCode = 1046
|
|
EFirmwareSpeakerL ErrorCode = 1047
|
|
EFirmwareSpeakerF ErrorCode = 1048
|
|
EFirmwareEepromL ErrorCode = 1049
|
|
EFirmwareEepromF ErrorCode = 1050
|
|
//Deprecated: Use a more specific error code
|
|
EFirmwareBatteryTooLowL ErrorCode = 1051
|
|
//Deprecated: Use a more specific error code
|
|
EFirmwareBatteryTooLowF ErrorCode = 1052
|
|
EFirmwareNoMeasurement ErrorCode = 1053
|
|
EFirmwareBattery1Low ErrorCode = 1054
|
|
EFirmwareBattery1Critical ErrorCode = 1055
|
|
EFirmwareBattery1Empty ErrorCode = 1056
|
|
EFirmwareBattery1Removed ErrorCode = 1057
|
|
EFirmwareBattery2Low ErrorCode = 1058
|
|
EFirmwareBattery2Critical ErrorCode = 1059
|
|
EFirmwareBattery2Empty ErrorCode = 1060
|
|
EFirmwareBattery2Removed ErrorCode = 1061
|
|
EFirmwareKeyswitchNotOperational ErrorCode = 1062
|
|
EFirmwareDeviceContainsErrors ErrorCode = 1063
|
|
EFirmwareDeviceService ErrorCode = 1064
|
|
EFirmwareDeviceArmed ErrorCode = 1065
|
|
EFirmwareDeviceActive ErrorCode = 1066
|
|
EFirmwareDeviceIdle ErrorCode = 1067
|
|
EFirmwareDncmNoReqrepBuffer ErrorCode = 1068
|
|
EFirmwareMismatchToken ErrorCode = 1069
|
|
EFirmwareReleaseSwitchComm ErrorCode = 1070
|
|
EFirmwareActivateSwitchComm ErrorCode = 1071
|
|
EFirmwareDeactivateSwitchComm ErrorCode = 1072
|
|
EFirmwareActivateShortNotEnabled ErrorCode = 1073
|
|
EFirmwareDeactivateShortEnabled ErrorCode = 1074
|
|
EFirmwareUltrasonicCurrent1 ErrorCode = 1075
|
|
EFirmwareUltrasonicCurrent2 ErrorCode = 1076
|
|
EFirmwareUltrasonicCurrentBoth ErrorCode = 1077
|
|
EFirmwareUltrasonicIo1 ErrorCode = 1078
|
|
EFirmwareUltrasonicIo2 ErrorCode = 1079
|
|
EFirmwareUltrasonicIoBoth ErrorCode = 1080
|
|
EFirmwareIoFailedI2c ErrorCode = 1081
|
|
EFirmwareIoFailedAdc ErrorCode = 1082
|
|
|
|
// CAN-bus and protocol
|
|
ECanInval ErrorCode = 3000
|
|
ECanIo ErrorCode = 3001
|
|
ECanTimeout ErrorCode = 3002
|
|
ECanAgain ErrorCode = 3003
|
|
ECanNobufs ErrorCode = 3004
|
|
ECanProto ErrorCode = 3005
|
|
ECanCrc ErrorCode = 3006
|
|
|
|
// Backend warnings
|
|
EWrnBackendDeviceWarning ErrorCode = 2000512
|
|
|
|
// Firmware/device warnings
|
|
EWrnFirmwareActivateShortPresent ErrorCode = 2001024
|
|
EWrnFirmwareDeactivateShortPresent ErrorCode = 2001025
|
|
EWrnFirmwareBattery1Low ErrorCode = 2001026
|
|
EWrnFirmwareBattery1Critical ErrorCode = 2001027
|
|
EWrnFirmwareBattery1Empty ErrorCode = 2001028
|
|
EWrnFirmwareBattery1Removed ErrorCode = 2001029
|
|
EWrnFirmwareBattery2Low ErrorCode = 2001030
|
|
EWrnFirmwareBattery2Critical ErrorCode = 2001031
|
|
EWrnFirmwareBattery2Empty ErrorCode = 2001032
|
|
EWrnFirmwareBattery2Removed ErrorCode = 2001033
|
|
EWrnFirmwareUltrasonicCurrent1 ErrorCode = 2001034
|
|
EWrnFirmwareUltrasonicCurrent2 ErrorCode = 2001035
|
|
EWrnFirmwareUltrasonicCurrentBoth ErrorCode = 2001036
|
|
EWrnFirmwareUltrasonicIo1 ErrorCode = 2001037
|
|
EWrnFirmwareUltrasonicIo2 ErrorCode = 2001038
|
|
EWrnFirmwareUltrasonicIoBoth ErrorCode = 2001039
|
|
EWrnFirmwareActivateDetectionNok ErrorCode = 2001040
|
|
EWrnFirmwareNeedsReboot ErrorCode = 2001041
|
|
)
|
|
|
|
// Error returns a descriptive error message
|
|
func (err ErrorCode) Error() string {
|
|
return fmt.Sprintf("dinet error: %d", err)
|
|
}
|
|
|
|
// String returns a long description of ErrorCode
|
|
// nolint
|
|
func (err ErrorCode) String() string {
|
|
switch err {
|
|
case Ok:
|
|
return "OK"
|
|
|
|
// Generic
|
|
case EParam:
|
|
return "Invalid parameter"
|
|
case ERange:
|
|
return "Value/parameter out of range"
|
|
case ENodev:
|
|
return "No such device"
|
|
case ENores:
|
|
return "No such resource"
|
|
case EBusy:
|
|
return "Device or resource busy"
|
|
case EOpnotsupp:
|
|
return "Operation not supported"
|
|
case EProto:
|
|
return "Protocol error"
|
|
case EChecksum:
|
|
return "Checksum error"
|
|
case ETimeout:
|
|
return "Timeout"
|
|
case EDisconnected:
|
|
return "Disconnected"
|
|
case EAgain:
|
|
return "Try again"
|
|
case EOpdenied:
|
|
return "Operation denied"
|
|
case EIofailed:
|
|
return "I/O operation failed"
|
|
case ENotfound:
|
|
return "Not found"
|
|
case ENomem:
|
|
return "Out of memory"
|
|
|
|
// Secure server
|
|
case ESecsDuplicateProject:
|
|
return "Duplicate project found"
|
|
case ESecsInvalidProjectState:
|
|
return "Invalid project state reached"
|
|
case ESecsInvalidMutation:
|
|
return "Invalid mutation requested"
|
|
case ESecsInvalidAction:
|
|
return "Invalid action specified"
|
|
case ESecsProjectChanged:
|
|
return "Project data changed"
|
|
case ESecsPlanningChanged:
|
|
return "Project planning changed"
|
|
case ESecsDesignChanged:
|
|
return "Project design changed"
|
|
case ESecsDatabaseError:
|
|
return "Database error occurred"
|
|
case ESecsNoProjectData:
|
|
return "No project data supplied"
|
|
case ESecsInvalidProject:
|
|
return "Invalid project selected"
|
|
case ESecsInvalidRequest:
|
|
return "Invalid request supplied"
|
|
case ESecsInternalError:
|
|
return "Internal error supplied"
|
|
case ESecsNoBackend:
|
|
return "Backend is not connected"
|
|
case ESecsBackendInvalidMessage:
|
|
return "Backend sent an invalid message"
|
|
case ESecsSetupChanged:
|
|
return "Project setup changed"
|
|
case ESecsInvalidProjectType:
|
|
return "Project type not recognized"
|
|
case ESecsNoProjectGroup:
|
|
return "No project groups provided"
|
|
|
|
// Backend
|
|
case EBackendDuplicateProject:
|
|
return "Duplicate project"
|
|
case EBackendInvalidProject:
|
|
return "Invalid project"
|
|
case EBackendDeviceError:
|
|
return "Device error"
|
|
case EBackendInternalError:
|
|
return "Backend internal error"
|
|
case EBackendInvalidMutation:
|
|
return "Invalid mutation requested"
|
|
case EBackendInvalidGroup:
|
|
return "Invalid group action"
|
|
case EBackendAlreadyActivated:
|
|
return "Group already activated"
|
|
case EBackendAlreadyDeactivated:
|
|
return "Group already deactivated"
|
|
case EBackendMissingActivateGroups:
|
|
return "Missing activate groups"
|
|
case EBackendMissingDeactivateGroups:
|
|
return "Missing deactivate groups"
|
|
case EBackendCp3000CommError:
|
|
return "CP3000 communication to legacy device failed"
|
|
|
|
// Firmware/device
|
|
case EFirmwareTilt:
|
|
return "Tilt position error"
|
|
case EFirmwareUltrasonic:
|
|
return "Ultrasonic error"
|
|
case EFirmwareSpeaker:
|
|
return "Speaker error"
|
|
case EFirmwareEeprom:
|
|
return "EEPROM error"
|
|
case EFirmwareCalibration:
|
|
return "Calibration error"
|
|
case EFirmwareBa:
|
|
return "BA error"
|
|
case EFirmwareVref:
|
|
return "Vref error"
|
|
case EFirmwareVrefClipping:
|
|
return "Vref clipping"
|
|
case EFirmwareLeaderFailure:
|
|
return "Leader failed (failsafe)"
|
|
case EFirmwareFollowerFailure:
|
|
return "Follower failed (failsafe)"
|
|
case EFirmwareRotation:
|
|
return "Rotation position error"
|
|
case EFirmwareDetectionbutton:
|
|
return "Detection button error"
|
|
case EFirmwareDeadmansTimeout:
|
|
return "Deadmans timeout"
|
|
case EFirmwareBatteryTooLow:
|
|
return "One or more device batteries are too low"
|
|
case EFirmwareSwitchComm:
|
|
return "Switch communication error"
|
|
case EFirmwareLeaderConflict:
|
|
return "Leader conflict"
|
|
case EFirmwareTemperature:
|
|
return "Temperature sensor failure"
|
|
case EFirmwareMeasurement:
|
|
return "Measurement error"
|
|
case EFirmwareGps:
|
|
return "GPS error"
|
|
case EFirmwareMcuComm:
|
|
return "MCU communication error"
|
|
case EFirmwareDuStrikeRoleUnknown:
|
|
return "Detection unit strike role unknown"
|
|
case EFirmwareModemUartFraming:
|
|
return "Modem UART framing error"
|
|
case EFirmwareBatteryBoard:
|
|
return "At least 1 battery section broken"
|
|
case EFirmwareSpeakerL:
|
|
return "Speaker error Main board"
|
|
case EFirmwareSpeakerF:
|
|
return "Speaker error Monitor board"
|
|
case EFirmwareEepromL:
|
|
return "EEPROM error Main board"
|
|
case EFirmwareEepromF:
|
|
return "EEPROM error Monitor board"
|
|
case EFirmwareBatteryTooLowL:
|
|
return "Battery too low Main board"
|
|
case EFirmwareBatteryTooLowF:
|
|
return "Battery too low Monitor board"
|
|
case EFirmwareNoMeasurement:
|
|
return "There is no measurement available"
|
|
case EFirmwareBattery1Low:
|
|
return "Battery 1 is low"
|
|
case EFirmwareBattery1Critical:
|
|
return "Battery 1 is critical"
|
|
case EFirmwareBattery1Empty:
|
|
return "Battery 1 is empty"
|
|
case EFirmwareBattery1Removed:
|
|
return "Battery 1 is removed"
|
|
case EFirmwareBattery2Low:
|
|
return "Battery 2 is low"
|
|
case EFirmwareBattery2Critical:
|
|
return "Battery 2 is critical"
|
|
case EFirmwareBattery2Empty:
|
|
return "Battery 2 is empty"
|
|
case EFirmwareBattery2Removed:
|
|
return "Battery 2 is removed"
|
|
case EFirmwareKeyswitchNotOperational:
|
|
return "Keyswitch is not operational"
|
|
case EFirmwareDeviceContainsErrors:
|
|
return "Device contains errors"
|
|
case EFirmwareDeviceService:
|
|
return "State transition not allowed, device is service"
|
|
case EFirmwareDeviceArmed:
|
|
return "State transition not allowed, device is armed"
|
|
case EFirmwareDeviceActive:
|
|
return "State transition not allowed, device is active"
|
|
case EFirmwareDeviceIdle:
|
|
return "State transition not allowed, device is idle"
|
|
case EFirmwareDncmNoReqrepBuffer:
|
|
return "No space for request in buffer"
|
|
case EFirmwareMismatchToken:
|
|
return "Device is already armed using a different token"
|
|
case EFirmwareReleaseSwitchComm:
|
|
return "Switch communication error during release"
|
|
case EFirmwareActivateSwitchComm:
|
|
return "Switch communication error during activate"
|
|
case EFirmwareDeactivateSwitchComm:
|
|
return "Switch communication error during deactivate"
|
|
case EFirmwareActivateShortNotEnabled:
|
|
return "Short is not enabled after activate"
|
|
case EFirmwareDeactivateShortEnabled:
|
|
return "Short is not disabled after deactivate"
|
|
case EFirmwareUltrasonicCurrent1:
|
|
return "Ultrasonic sensor 1 failed (current measurement)"
|
|
case EFirmwareUltrasonicCurrent2:
|
|
return "Ultrasonic sensor 2 failed (current measurement)"
|
|
case EFirmwareUltrasonicCurrentBoth:
|
|
return "Ultrasonic sensor 1 & 2 failed (current measurement)"
|
|
case EFirmwareUltrasonicIo1:
|
|
return "Ultrasonic sensor 1 failed (IO-path measurement)"
|
|
case EFirmwareUltrasonicIo2:
|
|
return "Ultrasonic sensor 2 failed (IO-path measurement)"
|
|
case EFirmwareUltrasonicIoBoth:
|
|
return "Ultrasonic sensor 1 & 2 failed (IO-path measurement)"
|
|
case EFirmwareIoFailedI2c:
|
|
return "I2C bus communication error"
|
|
case EFirmwareIoFailedAdc:
|
|
return "ADC peripheral error"
|
|
|
|
// CAN-bus and protocol
|
|
case ECanInval:
|
|
return "CAN invalid argument"
|
|
case ECanIo:
|
|
return "CAN peripheral I/O error"
|
|
case ECanTimeout:
|
|
return "CAN timeout"
|
|
case ECanAgain:
|
|
return "CAN try again"
|
|
case ECanNobufs:
|
|
return "CAN buffers depleted"
|
|
case ECanProto:
|
|
return "CAN protocol error"
|
|
case ECanCrc:
|
|
return "CAN msg crc error"
|
|
|
|
// Backend warnings
|
|
case EWrnBackendDeviceWarning:
|
|
return "Device warning"
|
|
|
|
// Firmware/device warnings
|
|
case EWrnFirmwareActivateShortPresent:
|
|
return "Short was already present upon activation"
|
|
case EWrnFirmwareDeactivateShortPresent:
|
|
return "Short is still present after deactivation"
|
|
case EWrnFirmwareBattery1Low:
|
|
return "Battery 1 is low"
|
|
case EWrnFirmwareBattery1Critical:
|
|
return "Battery 1 is critical"
|
|
case EWrnFirmwareBattery1Empty:
|
|
return "Battery 1 is empty"
|
|
case EWrnFirmwareBattery1Removed:
|
|
return "Battery 1 is removed"
|
|
case EWrnFirmwareBattery2Low:
|
|
return "Battery 2 is low"
|
|
case EWrnFirmwareBattery2Critical:
|
|
return "Battery 2 is critical"
|
|
case EWrnFirmwareBattery2Empty:
|
|
return "Battery 2 is empty"
|
|
case EWrnFirmwareBattery2Removed:
|
|
return "Battery 2 is removed"
|
|
case EWrnFirmwareUltrasonicCurrent1:
|
|
return "Ultrasonic sensor 1 failed (current measurement)"
|
|
case EWrnFirmwareUltrasonicCurrent2:
|
|
return "Ultrasonic sensor 2 failed (current measurement)"
|
|
case EWrnFirmwareUltrasonicCurrentBoth:
|
|
return "Ultrasonic sensor 1 & 2 failed (current measurement)"
|
|
case EWrnFirmwareUltrasonicIo1:
|
|
return "Ultrasonic sensor 1 failed (IO-path measurement)"
|
|
case EWrnFirmwareUltrasonicIo2:
|
|
return "Ultrasonic sensor 2 failed (IO-path measurement)"
|
|
case EWrnFirmwareUltrasonicIoBoth:
|
|
return "Ultrasonic sensor 1 & 2 failed (IO-path measurement)"
|
|
case EWrnFirmwareActivateDetectionNok:
|
|
return "Detection is not ok after activate"
|
|
case EWrnFirmwareNeedsReboot:
|
|
return "Firmware needs reboot"
|
|
default:
|
|
return "Unknown"
|
|
}
|
|
}
|
|
|
|
// IsError returns true when this error is a standard error and not Ok or a warning
|
|
func (err ErrorCode) IsError() bool {
|
|
return err != 0 && err < 2000000
|
|
}
|
|
|
|
// IsWarning returns true when this error is actually a warning
|
|
func (err ErrorCode) IsWarning() bool {
|
|
return err >= 2000000
|
|
}
|
|
|
|
// CompareError checks if the two errors are the same.
|
|
func CompareError(err1 *Error, err2 *Error) bool {
|
|
if err1 == err2 {
|
|
return true
|
|
}
|
|
// It is possible that the errors are the same, but are pointing to different structs
|
|
if err1 == nil || err2 == nil {
|
|
// One struct is empty so they are not pointing to different structs
|
|
return false
|
|
}
|
|
if err1.Code != err2.Code {
|
|
return false
|
|
}
|
|
// There is no compare interface
|
|
if !reflect.DeepEqual(err1.Data, err2.Data) {
|
|
return false
|
|
}
|
|
return true
|
|
}
|