Initial commit: PilotVault multi-service project
Add API Server (Go/PocketBase), Web App (Go BFF + Vue), Fly App (Flutter/DJI MSDK), Adobe Plugin, and Docker/Docker AIO deployment configs. Design assets and build artifacts are gitignored. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
commit
afc6952eda
172 files changed
+24591
No files matched your search
@@ -0,0 +1,112 @@
|
||||
package hub
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
// Telemetry holds the latest flight-controller / battery values for a device.
|
||||
// Pointers distinguish "not yet reported" (nil) from a genuine zero value.
|
||||
type Telemetry struct {
|
||||
SatelliteCount *int `json:"satelliteCount,omitempty"`
|
||||
IsFlying *bool `json:"isFlying,omitempty"`
|
||||
FlightMode *string `json:"flightMode,omitempty"`
|
||||
Altitude *float64 `json:"altitude,omitempty"`
|
||||
Latitude *float64 `json:"latitude,omitempty"`
|
||||
Longitude *float64 `json:"longitude,omitempty"`
|
||||
VelocityX *float64 `json:"velocityX,omitempty"`
|
||||
VelocityY *float64 `json:"velocityY,omitempty"`
|
||||
VelocityZ *float64 `json:"velocityZ,omitempty"`
|
||||
BatteryPercent *int `json:"batteryPercent,omitempty"`
|
||||
}
|
||||
|
||||
// DeviceState is the server's aggregated view of one app/drone.
|
||||
type DeviceState struct {
|
||||
DeviceID string `json:"deviceId"`
|
||||
Online bool `json:"online"` // app's websocket is connected to the server
|
||||
Connected bool `json:"connected"` // a drone is connected to the app
|
||||
Model string `json:"model"`
|
||||
Registration string `json:"registration"`
|
||||
Telemetry Telemetry `json:"telemetry"`
|
||||
LastSeenMs int64 `json:"lastSeenMs"`
|
||||
}
|
||||
|
||||
// TrackPoint is one sample of the drone's GPS track (for the map trail).
|
||||
type TrackPoint struct {
|
||||
Lat float64 `json:"lat"`
|
||||
Lng float64 `json:"lng"`
|
||||
Alt float64 `json:"alt"`
|
||||
TS int64 `json:"ts"`
|
||||
}
|
||||
|
||||
// ServerToUI is the message a dashboard receives over /ws/ui.
|
||||
type ServerToUI struct {
|
||||
Type string `json:"type"` // "snapshot" | "update" | "removed"
|
||||
Device *DeviceState `json:"device,omitempty"`
|
||||
Devices []*DeviceState `json:"devices,omitempty"`
|
||||
DeviceID string `json:"deviceId,omitempty"` // for "removed"
|
||||
Event map[string]any `json:"event,omitempty"` // the raw device event that triggered this
|
||||
TS int64 `json:"ts"`
|
||||
}
|
||||
|
||||
// Command is what the server pushes down to a device over /ws/device.
|
||||
type Command struct {
|
||||
Type string `json:"type"` // always "command"
|
||||
Command string `json:"command"`
|
||||
Payload map[string]any `json:"payload,omitempty"`
|
||||
TS int64 `json:"ts"`
|
||||
}
|
||||
|
||||
// toFloat coerces a JSON-decoded value into a float64.
|
||||
func toFloat(v any) (float64, bool) {
|
||||
switch n := v.(type) {
|
||||
case float64:
|
||||
return n, true
|
||||
case float32:
|
||||
return float64(n), true
|
||||
case int:
|
||||
return float64(n), true
|
||||
case int64:
|
||||
return float64(n), true
|
||||
case json.Number:
|
||||
f, err := n.Float64()
|
||||
return f, err == nil
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// toInt coerces a JSON-decoded value into an int.
|
||||
func toInt(v any) (int, bool) {
|
||||
if f, ok := toFloat(v); ok {
|
||||
return int(f), true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// applyTelemetry copies any present telemetry fields from a raw event map.
|
||||
func applyTelemetry(t *Telemetry, raw map[string]any) {
|
||||
if v, ok := toInt(raw["satelliteCount"]); ok {
|
||||
t.SatelliteCount = &v
|
||||
}
|
||||
if v, ok := raw["isFlying"].(bool); ok {
|
||||
t.IsFlying = &v
|
||||
}
|
||||
if v, ok := raw["flightMode"].(string); ok {
|
||||
t.FlightMode = &v
|
||||
}
|
||||
if v, ok := toFloat(raw["altitude"]); ok {
|
||||
t.Altitude = &v
|
||||
}
|
||||
if v, ok := toFloat(raw["latitude"]); ok {
|
||||
t.Latitude = &v
|
||||
}
|
||||
if v, ok := toFloat(raw["longitude"]); ok {
|
||||
t.Longitude = &v
|
||||
}
|
||||
if v, ok := toFloat(raw["velocityX"]); ok {
|
||||
t.VelocityX = &v
|
||||
}
|
||||
if v, ok := toFloat(raw["velocityY"]); ok {
|
||||
t.VelocityY = &v
|
||||
}
|
||||
if v, ok := toFloat(raw["velocityZ"]); ok {
|
||||
t.VelocityZ = &v
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user