Stop reporting the flight controller's serial as the drone's
getSerialNumber() is a BaseComponent method, so every component answers for
itself — and the bridge reads it off the flight controller. A Mavic Pro reports
08RDE1J00103H1 (what DJI Go labels "Flight Controller SN") where the airframe
sticker, and the registration, say 08QDE3H012032E. We were publishing the former
as the drone's serial, onto records that exist to satisfy BEK 1649 §5.
Same trap as 002e484, where a component's own firmware stood in for the
aircraft's, but with no correct source to switch to: MSDK v4 exposes no
aircraft-level serial at all — BaseProduct offers only the model and the
firmware package version — so the registered serial can only be typed by hand.
So split the two rather than pick one:
serial the airframe's, hand-entered, and the only one that
reaches the logbook and the CSV export
flight_controller_serial what the aircraft reports; auto-filled on connect,
and what POST /api/drones/auto now upserts on
Keying auto-add on the flight controller's serial keeps the fleet recognising a
connected drone without typing — it is stable per airframe — while leaving the
compliance record's serial to the pilot. A flight controller swapped in a repair
now costs a duplicate fleet entry to merge, where before it would have quietly
rewritten what the logbook claimed the drone was.
Note droneInput.payload() is a whole-record write, so any UI editing a drone must
round-trip flightControllerSerial; blanking it forks the drone into a duplicate
on its next connect. Drones.vue carries it through the edit form for that reason.
The migration copies existing serials into flight_controller_serial rather than
moving them: every current value came from auto-add and is therefore a flight
controller's, but a pilot may since have corrected one by hand and this cannot
tell them apart. Copying keeps auto-add matching the airframes it matched before.
Applied to the remote PocketBase, where drones held no records, so the backfill
was a no-op there.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
33595c99e8
commit
183c83c177
14 files changed
+297
-139
No files matched your search
@@ -182,7 +182,7 @@ func (h *Hub) Ingest(deviceID string, raw map[string]any) {
|
||||
s.Connected = c
|
||||
if !c {
|
||||
s.Telemetry = Telemetry{} // drone unlinked: live telemetry is no longer valid
|
||||
s.Serial, s.Firmware, s.ControllerFirmware = "", "", ""
|
||||
s.FlightControllerSerial, s.Firmware, s.ControllerFirmware = "", "", ""
|
||||
}
|
||||
}
|
||||
if m, ok := raw["model"].(string); ok {
|
||||
|
||||
@@ -31,14 +31,19 @@ type DeviceState struct {
|
||||
// ("success", "failed", …) — not the aircraft's FAA/CAA registration number,
|
||||
// which lives on the drone's logbook record.
|
||||
Registration string `json:"registration"`
|
||||
// Identity of the connected aircraft, as it reports itself. Serial and the
|
||||
// Identity of the connected aircraft, as it reports itself. The serial and the
|
||||
// two firmware versions resolve asynchronously after connect, each on its own
|
||||
// schedule, so these fill in over several events rather than all at once.
|
||||
Serial string `json:"serial"`
|
||||
Firmware string `json:"firmware"`
|
||||
ControllerFirmware string `json:"controllerFirmware"`
|
||||
Telemetry Telemetry `json:"telemetry"`
|
||||
LastSeenMs int64 `json:"lastSeenMs"`
|
||||
//
|
||||
// FlightControllerSerial is the flight controller's own serial, not the number
|
||||
// on the airframe: MSDK v4 exposes no aircraft-level serial, so the serial a
|
||||
// drone is *registered* under is hand-entered on its logbook record instead.
|
||||
// It is nonetheless stable per airframe, which is what the fleet auto-add keys on.
|
||||
FlightControllerSerial string `json:"flightControllerSerial"`
|
||||
Firmware string `json:"firmware"`
|
||||
ControllerFirmware string `json:"controllerFirmware"`
|
||||
Telemetry Telemetry `json:"telemetry"`
|
||||
LastSeenMs int64 `json:"lastSeenMs"`
|
||||
}
|
||||
|
||||
// TrackPoint is one sample of the drone's GPS track (for the map trail).
|
||||
@@ -98,8 +103,8 @@ func toInt(v any) (int, bool) {
|
||||
// answers serial in seconds but firmware can take far longer — so an absent
|
||||
// value never clears one an earlier event already delivered.
|
||||
func applyIdentity(s *DeviceState, raw map[string]any) {
|
||||
if v, ok := raw["serial"].(string); ok && v != "" {
|
||||
s.Serial = v
|
||||
if v, ok := raw["flightControllerSerial"].(string); ok && v != "" {
|
||||
s.FlightControllerSerial = v
|
||||
}
|
||||
if v, ok := raw["firmware"].(string); ok && v != "" {
|
||||
s.Firmware = v
|
||||
|
||||
Reference in new issue
Block a user