Introduced `SpiParameters` and related structs to process SPI data. Added JSON marshaling/unmarshaling logic and a handler for the "SPI" command in the server. This enables parsing and transforming SPI data effectively for device communication.
215 lines
6.9 KiB
Go
215 lines
6.9 KiB
Go
package n9m
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"strconv"
|
|
"time"
|
|
)
|
|
|
|
/*
|
|
|
|
// main server util
|
|
func (e *Package) RequestGeolocation(serial int, Sid string) {
|
|
e.Payload = map[string]any{
|
|
"MODULE": "DEVEMM",
|
|
"OPERATION": "GETPOS",
|
|
"PARAMETER": map[string]any{
|
|
"SERIAL": serial,
|
|
},
|
|
"SESSION": Sid,
|
|
}
|
|
}
|
|
|
|
func (e *Package) ResponseGeolocation(errorCode int, errorCause string, serial int, longitude float32, latitude float32, altitude float32, speed int, course int, time string) {
|
|
e.Payload = map[string]any{
|
|
"MODULE": "DEVEMM",
|
|
"OPERATION": "GETPOS",
|
|
"RESPONSE": map[string]any{
|
|
"ERRORCODE": errorCode,
|
|
"ERRORCAUSE": errorCause,
|
|
"SERIAL": serial,
|
|
"P": map[string]any{
|
|
"V": errorCode == 0,
|
|
"J": fmt.Sprintf("%4.6v", longitude),
|
|
"W": fmt.Sprintf("%4.6v", latitude),
|
|
"H": fmt.Sprintf("%4.6v", altitude),
|
|
"S": speed, // unit - 0.01 km/h
|
|
"C": course, // direction (angle from north)
|
|
"T": time, // yyyymmddhhmmss
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
*/
|
|
|
|
// 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"`
|
|
}
|