diff --git a/cmd/dev-server/main.go b/cmd/dev-server/main.go index 4ffb717..19dfdec 100644 --- a/cmd/dev-server/main.go +++ b/cmd/dev-server/main.go @@ -112,6 +112,18 @@ func handleCameraCoveredAlarm(sPack *n9m.SmartPackage, pack n9m.Package, respons return nil } +func handleSPI(_ *n9m.SmartPackage, pack n9m.Package) (err error) { + var params n9m.SpiParameters + + if err = pack.GetParametersAs(¶ms); err != nil { + return + } + + fmt.Printf("%+v\n", params) + + return +} + func createSmartPackage(conn net.Conn) (pack *n9m.SmartPackage) { pack = n9m.NewSmartPackage(conn) @@ -120,6 +132,7 @@ func createSmartPackage(conn net.Conn) (pack *n9m.SmartPackage) { pack.AddJSONHandler("CERTIFICATE", "CONNECT", handleCertificateConnect) pack.AddJSONHandler("CERTIFICATE", "KEEPALIVE", handleKeepAlive) pack.AddJSONHandler("CONFIGMODEL", "GET", handleGetConfig) + pack.AddJSONHandler("DEVEMM", "SPI", handleSPI) pack.AddAlarmHandler(n9m.AlarmTypeMotionDetection, handleUselessAlarms) diff --git a/devemm.go b/devemm.go index 36db1e9..21a4437 100644 --- a/devemm.go +++ b/devemm.go @@ -1,5 +1,12 @@ package n9m +import ( + "encoding/json" + "fmt" + "strconv" + "time" +) + /* // main server util @@ -36,3 +43,172 @@ func (e *Package) ResponseGeolocation(errorCode int, errorCause string, serial i } */ + +// 3.4.5.28 +type SpiParameters struct { + DriveFlag uint `json:"T"` + DataMask uint `json:"M"` + Position GPSData `json:"P"` + DeviceStatus SpiDeviceStatus `json:"S"` +} + +// 3.4.5.28.1 +type SpiDeviceStatus struct { + Status3G uint `json:"G3"` + Status3GStrength uint `json:"G3S"` + Status4G uint `json:"G4"` + Status4GStrength uint `json:"G4S"` + WIFIStatus uint `json:"W"` + WIFIStrength uint `json:"WS"` + Voltage float64 `json:"V"` + DeviceTemperature float64 `json:"DT"` + IndoorTemperature float64 `json:"TC"` + Speed float64 `json:"S"` + KeyIgnitionState uint `json:"SW"` + RecordStatus []uint `json:"RE"` + Time time.Time `json:"T"` + StorageDeviceNumber uint `json:"STC"` + StorageDeviceInfo []StorageDeviceInfo `json:"SINFO"` + VideoLossStatus []uint `json:"VS"` + Humidity float64 `json:"H"` + TotalMileage float64 `json:"TM"` + HardDriveHeating uint `json:"HTR"` +} + +func (g *SpiDeviceStatus) MarshalJSON() ([]byte, error) { + var alias struct { + Status3G uint `json:"G3"` + Status3GStrength uint `json:"G3S"` + Status4G uint `json:"G4"` + Status4GStrength uint `json:"G4S"` + WIFIStatus uint `json:"W"` + WIFIStrength uint `json:"WS"` + Voltage uint `json:"V"` + DeviceTemperature uint `json:"DT"` + IndoorTemperature uint `json:"TC"` + Speed uint `json:"S"` + SpeedUnits uint `json:"SU"` + KeyIgnitionState uint `json:"SW"` + RecordStatus []uint `json:"RE"` + Time string `json:"T"` + StorageDeviceNumber uint `json:"STC"` + StorageDeviceInfo []StorageDeviceInfo `json:"SINFO"` + VideoLossStatus []uint `json:"VS"` + Humidity uint `json:"H"` + TotalMileage string `json:"TM"` + HardDriveHeating uint `json:"HTR"` + } + + convert := func(v float64) uint { + if v < 0 { + return uint(-v * 100) + } else { + return uint((v + 100) * 100) + } + } + + alias.Status3G = g.Status3G + alias.Status3GStrength = g.Status3GStrength + alias.Status4G = g.Status4G + alias.Status4GStrength = g.Status4GStrength + alias.WIFIStatus = g.WIFIStatus + alias.WIFIStrength = g.WIFIStrength + alias.Voltage = uint(g.Voltage * 100) + alias.DeviceTemperature = convert(g.DeviceTemperature) + alias.IndoorTemperature = convert(g.IndoorTemperature) + alias.Speed = uint(g.Speed * 100) + alias.SpeedUnits = 0 + alias.KeyIgnitionState = g.KeyIgnitionState + alias.RecordStatus = g.RecordStatus + alias.Time = g.Time.Format("20060102150405") + alias.StorageDeviceNumber = g.StorageDeviceNumber + alias.StorageDeviceInfo = g.StorageDeviceInfo + alias.VideoLossStatus = g.VideoLossStatus + alias.Humidity = uint(g.Humidity * 10000) + alias.TotalMileage = fmt.Sprintf("%.6f", g.TotalMileage) + alias.HardDriveHeating = g.HardDriveHeating + + return json.Marshal(alias) +} + +func (g *SpiDeviceStatus) UnmarshalJSON(data []byte) (err error) { + var alias struct { + Status3G uint `json:"G3"` + Status3GStrength uint `json:"G3S"` + Status4G uint `json:"G4"` + Status4GStrength uint `json:"G4S"` + WIFIStatus uint `json:"W"` + WIFIStrength uint `json:"WS"` + Voltage uint `json:"V"` + DeviceTemperature uint `json:"TD"` + IndoorTemperature uint `json:"TC"` + Speed uint `json:"S"` + SpeedUnits uint `json:"SU"` + KeyIgnitionState uint `json:"SW"` + RecordStatus []uint `json:"RE"` + Time string `json:"T"` + StorageDeviceNumber uint `json:"STC"` + StorageDeviceInfo []StorageDeviceInfo `json:"SINFO"` + VideoLossStatus []uint `json:"VS"` + Humidity uint `json:"H"` + TotalMileage string `json:"TM"` + HardDriveHeating uint `json:"HTR"` + } + + if err = json.Unmarshal(data, &alias); err != nil { + return + } + + convert := func(v uint) float64 { + if v < 10000 { + return -float64(v) / 100 + } else { + return float64(v-10000) / 100 + } + } + + g.Status3G = alias.Status3G + g.Status3GStrength = alias.Status3GStrength + g.Status4G = alias.Status4G + g.Status4GStrength = alias.Status4GStrength + g.WIFIStatus = alias.WIFIStatus + g.WIFIStrength = alias.WIFIStrength + g.Voltage = float64(alias.Voltage) / 100 + g.DeviceTemperature = convert(alias.DeviceTemperature) + g.IndoorTemperature = convert(alias.IndoorTemperature) + + g.Speed = float64(alias.Speed) / 100.0 + switch alias.SpeedUnits { + case 0: + break + case 1: + g.Speed *= 1.609 + default: + return fmt.Errorf("Strange speed units") + } + + g.KeyIgnitionState = alias.KeyIgnitionState + g.RecordStatus = alias.RecordStatus + g.Time, _ = time.Parse("20060102150405", alias.Time) + g.StorageDeviceNumber = alias.StorageDeviceNumber + g.StorageDeviceInfo = alias.StorageDeviceInfo + g.VideoLossStatus = alias.VideoLossStatus + g.Humidity = float64(alias.Humidity) / 10000 + + if g.TotalMileage, err = strconv.ParseFloat(alias.TotalMileage, 64); err != nil { + return fmt.Errorf("invalid longitude: %w", err) + } + + g.HardDriveHeating = alias.HardDriveHeating + + return nil +} + +// 3.4.5.28.3 +type StorageDeviceInfo struct { + Type uint `json:"T"` + MediaTime uint `json:"O"` + Status uint `json:"S"` + Capacity uint `json:"TS"` + FreeCapacity uint `json:"LS"` +}