Add SPI data handling and serialization support
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.
This commit is contained in:
		@@ -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)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										176
									
								
								devemm.go
									
									
									
									
									
								
							
							
						
						
									
										176
									
								
								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"`
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user