From eec892cfb44160ba2baa7148f859db9a398c9fbd Mon Sep 17 00:00:00 2001 From: GP Date: Thu, 12 Feb 2026 13:59:04 +1300 Subject: [PATCH 1/3] up and fmt --- go.mod | 2 +- go.sum | 4 +- internal/tc2-hat-comms/at-esl.go | 44 +++++++------ internal/tc2-hat-comms/service-monitor.go | 76 +++++++++++------------ 4 files changed, 62 insertions(+), 64 deletions(-) diff --git a/go.mod b/go.mod index 16f4b8a..309fc01 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.25.0 require ( github.com/TheCacophonyProject/event-reporter/v3 v3.9.0 - github.com/TheCacophonyProject/go-config v1.30.1 + github.com/TheCacophonyProject/go-config v1.30.2 github.com/TheCacophonyProject/go-utils v0.1.3 github.com/TheCacophonyProject/rpi-net-manager v0.5.6 github.com/TheCacophonyProject/window v0.0.0-20211121225840-66e93100eba1 diff --git a/go.sum b/go.sum index 249ccef..568b024 100644 --- a/go.sum +++ b/go.sum @@ -7,8 +7,8 @@ github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAE github.com/TheCacophonyProject/event-reporter/v3 v3.9.0 h1:dtF7n1/9/8poMgKfFlFZ0LAy2EJ743DkZyHuxMWh1E4= github.com/TheCacophonyProject/event-reporter/v3 v3.9.0/go.mod h1:DE4feSd2eALapCgYFnsAiUnHfO9lhczRth6amCNusaA= github.com/TheCacophonyProject/go-config v1.4.0/go.mod h1:oARW/N3eJbcewCqB+Jc7TBwuODawwYgpo56UO6yBdKU= -github.com/TheCacophonyProject/go-config v1.30.1 h1:udmdx1qfi5a16RSF+4C1rAUWApCQ/p9ustUKeS6oW8s= -github.com/TheCacophonyProject/go-config v1.30.1/go.mod h1:+9Z/iu1atKlfwfbbyfpUHaDz9quCgo/BvCianA+zSAs= +github.com/TheCacophonyProject/go-config v1.30.2 h1:GpDnYZ38ea7pun8oewP76uB2dsF/nEQJO92MWbZ0Xdg= +github.com/TheCacophonyProject/go-config v1.30.2/go.mod h1:+9Z/iu1atKlfwfbbyfpUHaDz9quCgo/BvCianA+zSAs= github.com/TheCacophonyProject/go-utils v0.1.3 h1:DSuDeJz7ZM00yQRLsoukWH0fnC+8X8+ziYxOl6l3wEY= github.com/TheCacophonyProject/go-utils v0.1.3/go.mod h1:jZPUZ4GtYVxnlTtqiYKMFWDT//kmxdbwjLW3HCyCmCE= github.com/TheCacophonyProject/rpi-net-manager v0.5.6 h1:/80dbwvwhWz4Yh1eBA64/Yzfzw6W0yWSxuDrdUzz9uE= diff --git a/internal/tc2-hat-comms/at-esl.go b/internal/tc2-hat-comms/at-esl.go index de34aad..7366a95 100644 --- a/internal/tc2-hat-comms/at-esl.go +++ b/internal/tc2-hat-comms/at-esl.go @@ -13,11 +13,11 @@ import ( ) var ( - predictionLockoutNodeRegister int = 5 + predictionLockoutNodeRegister int = 5 predictionLockoutMinutesDefault int64 = 30 // default 30mins. - batteryLockoutHoursNodeRegister int = 12 - batteryLockoutMinutesNodeRegister int = 13 - batteryLockoutMinutesDefault int64 = 180 // default 180mins (3 hours). + batteryLockoutHoursNodeRegister int = 12 + batteryLockoutMinutesNodeRegister int = 13 + batteryLockoutMinutesDefault int64 = 180 // default 180mins (3 hours). ) type ATESLMessenger struct { @@ -37,8 +37,8 @@ type ATESLLastBattery struct { Lockout int64 } -var atesLastPrediction = ATESLLastPrediction{ Lockout: predictionLockoutMinutesDefault } -var atesLastBattery = ATESLLastBattery{ Lockout: batteryLockoutMinutesDefault } +var atesLastPrediction = ATESLLastPrediction{Lockout: predictionLockoutMinutesDefault} +var atesLastBattery = ATESLLastBattery{Lockout: batteryLockoutMinutesDefault} func processATESL(config *CommsConfig, testClassification *TestClassification, eventChannel chan event) error { messenger := ATESLMessenger{ @@ -104,8 +104,8 @@ func (a ATESLMessenger) processBatteryEvent(b batteryEvent, l *ATESLLastBattery) log.Error("Error sending battery reading:", err) return err } - l.Voltage = b.Voltage // Remember the voltage reading - l.When = time.Now() // Remember when we detected it + l.Voltage = b.Voltage // Remember the voltage reading + l.When = time.Now() // Remember when we detected it // Now let's check the event lockout l.Lockout = getBatteryEventLockout(a.BaudRate) @@ -118,7 +118,7 @@ func (a ATESLMessenger) processTrackingEvent(t trackingEvent, l *ATESLLastPredic // TODO: tracking events can be buffered - so the clip age make be significant // if a tacking event was older than our lockout - perhaps we should send it on // - // The ESL API also assumes all events are 'now' so we also need to extend that to be able to provide + // The ESL API also assumes all events are 'now' so we also need to extend that to be able to provide // the age in seconds/minutes if the age is over some reasonable threshold - maybe 2-5mins. lastPrediction := time.Since(l.When).Minutes() @@ -147,7 +147,7 @@ func (a ATESLMessenger) processTrackingEvent(t trackingEvent, l *ATESLLastPredic target = true targetConfidence = 50 // limit to 50% to avoid too much noise - // Special handler for any - with confidence setting + // Special handler for any - with confidence setting } else if _, found := a.TrapSpecies["any"]; found { // We can do without false-positives, not quite any :) @@ -158,7 +158,7 @@ func (a ATESLMessenger) processTrackingEvent(t trackingEvent, l *ATESLLastPredic target = true targetConfidence = a.TrapSpecies["any"] - // If we have specific species let's check for specific confidence levels oer species + // If we have specific species let's check for specific confidence levels oer species } else if _, found := a.TrapSpecies[t.What]; found { target = true targetConfidence = a.TrapSpecies[t.What] @@ -262,13 +262,13 @@ func getRegisteryData(baudRate int, reg int) int64 { regCmd := "m00" // Currently limited to the first 'page' of registery data (m00) - cmd := append([]byte("AT+XCMD=" + regCmd), calcCRC16([]byte(regCmd))...) + cmd := append([]byte("AT+XCMD="+regCmd), calcCRC16([]byte(regCmd))...) log.Infof("get reg %d, data via command %v", reg, cmd) response, _ := sendATCommand(string(cmd), baudRate) // Let's clean-up the output - trim any unwanted charaters - if idx := bytes.Index(response, []byte(regCmd + "\r\n\r\n")); idx != -1 { + if idx := bytes.Index(response, []byte(regCmd+"\r\n\r\n")); idx != -1 { response = response[idx:] } else { // fallback: not found, just log and continue @@ -338,24 +338,22 @@ func getPredictionEventLockout(baudRate int) int64 { } /* +Battery event lockout mins +Time in minutes to have an battery event lockout; default 180mins (3 hours). +Read the 12 (hrs) + 13 (mins) node registery to get the value - Battery event lockout mins - Time in minutes to have an battery event lockout; default 180mins (3 hours). - Read the 12 (hrs) + 13 (mins) node registery to get the value - - 3hours = 'w1203’ - 30min = 'w131e’ - +3hours = 'w1203’ +30min = 'w131e’ */ func getBatteryEventLockout(baudRate int) int64 { hours := getRegisteryData(baudRate, batteryLockoutHoursNodeRegister) - mins := getRegisteryData(baudRate, batteryLockoutMinutesNodeRegister) + mins := getRegisteryData(baudRate, batteryLockoutMinutesNodeRegister) - battery_lockout_minutes := hours * 60 + mins + battery_lockout_minutes := hours*60 + mins if battery_lockout_minutes <= 0 { log.Infof("Battery lockout time not set - using default (%d)", batteryLockoutMinutesDefault) - battery_lockout_minutes = batteryLockoutMinutesDefault + battery_lockout_minutes = batteryLockoutMinutesDefault } log.Infof("Battery lockout time = %d (mins)", battery_lockout_minutes) diff --git a/internal/tc2-hat-comms/service-monitor.go b/internal/tc2-hat-comms/service-monitor.go index 1cc4fad..c895254 100644 --- a/internal/tc2-hat-comms/service-monitor.go +++ b/internal/tc2-hat-comms/service-monitor.go @@ -3,22 +3,22 @@ package comms import ( - "time" "strconv" "strings" + "time" "github.com/TheCacophonyProject/tc2-hat-controller/tracks" "github.com/godbus/dbus/v5" ) type models struct { - Id int32 + Id int32 Labels []string } var ( - animalsList = models{Id: 1, Labels: []string{"bird","cat","deer","dog","false-positive","hedgehog","human","kiwi","leporidae","mustelid","penguin","possum","rodent","sheep","vehicle","wallaby"}} - fpModelLabels = models{Id: 1004, Labels: []string{"animal","false-positive"}} + animalsList = models{Id: 1, Labels: []string{"bird", "cat", "deer", "dog", "false-positive", "hedgehog", "human", "kiwi", "leporidae", "mustelid", "penguin", "possum", "rodent", "sheep", "vehicle", "wallaby"}} + fpModelLabels = models{Id: 1004, Labels: []string{"animal", "false-positive"}} ) type event interface { @@ -37,7 +37,7 @@ type trackingEvent struct { BlankRegion bool Tracking bool LastPredictionFrame int32 - ClipAgeSeconds int32 + ClipAgeSeconds int32 } func (t trackingEvent) isEvent() {} @@ -49,8 +49,8 @@ type batteryEvent struct { } func addTrackingReprocessedEvents(eventsChan chan event) error { - targetSignalName := "org.cacophony.thermalrecorder.TrackingReprocessed" - return addTrackingEventsForSignal(eventsChan, targetSignalName) + targetSignalName := "org.cacophony.thermalrecorder.TrackingReprocessed" + return addTrackingEventsForSignal(eventsChan, targetSignalName) } func addTrackingEvents(eventsChan chan event) error { @@ -116,34 +116,34 @@ func addTrackingEventsForSignal(eventsChan chan event, targetSignalName string) // Match the track model output to our now models switch modelIdType := signal.Body[11].(type) { - case int32: - modelId = signal.Body[11].(int32) - // Reprocessed events have a "post-" id prefix - case string: - modelIdStr := strings.TrimPrefix(signal.Body[11].(string), "post-") - val64, err := strconv.ParseInt(modelIdStr, 10, 32) - if err != nil { - log.Warnf("Failed to parse the model id[%v]: %v", modelIdStr, err) - continue - } - modelId = int32(val64) - default: - log.Warnf("Model id unexpected type %v .. skipping", modelIdType) + case int32: + modelId = signal.Body[11].(int32) + // Reprocessed events have a "post-" id prefix + case string: + modelIdStr := strings.TrimPrefix(signal.Body[11].(string), "post-") + val64, err := strconv.ParseInt(modelIdStr, 10, 32) + if err != nil { + log.Warnf("Failed to parse the model id[%v]: %v", modelIdStr, err) continue + } + modelId = int32(val64) + default: + log.Warnf("Model id unexpected type %v .. skipping", modelIdType) + continue } // Get the labels for the model used in the prediction switch modelId { - case fpModelLabels.Id: - modelLabels = fpModelLabels.Labels - case animalsList.Id: - modelLabels = animalsList.Labels - default: - log.Warnf("Model id key not known %v [%v, %v]", modelId, fpModelLabels.Id, animalsList.Id) - continue - } + case fpModelLabels.Id: + modelLabels = fpModelLabels.Labels + case animalsList.Id: + modelLabels = animalsList.Labels + default: + log.Warnf("Model id key not known %v [%v, %v]", modelId, fpModelLabels.Id, animalsList.Id) + continue + } - // Loop through our track species and get the model scores + // Loop through our track species and get the model scores species := tracks.Species{} for i, v := range modelLabels { species[v] = signal.Body[2].([]int32)[i] @@ -156,11 +156,11 @@ func addTrackingEventsForSignal(eventsChan chan event, targetSignalName string) // See if we have a clip end time clipAgeSeconds := int32(0) if len(signal.Body) >= 13 { - ts := signal.Body[12].(float64); + ts := signal.Body[12].(float64) now := time.Now() - target := time.Unix(int64(ts), int64((ts-float64(int64(ts)))*1e9),) + target := time.Unix(int64(ts), int64((ts-float64(int64(ts)))*1e9)) - clipAgeSeconds = int32(now.Sub(target).Seconds()); + clipAgeSeconds = int32(now.Sub(target).Seconds()) log.Debugf("Clip is %d seconds old", clipAgeSeconds) } @@ -285,12 +285,12 @@ func getThumbnail(clip_id int32, track_id int32) [][]uint16 { } switch frame := t_call.Body[0].(type) { - case [][]uint16: - // Access row/col - log.Debugf("Thubnail (clip id: %d, track_id: %d) is: %d×%d", clip_id, track_id, len(frame), len(frame[0])) - return t_call.Body[0].([][]uint16) - default: - log.Warnf("GetThumbnail returned an unexpected 2D type: %T", frame) + case [][]uint16: + // Access row/col + log.Debugf("Thubnail (clip id: %d, track_id: %d) is: %d×%d", clip_id, track_id, len(frame), len(frame[0])) + return t_call.Body[0].([][]uint16) + default: + log.Warnf("GetThumbnail returned an unexpected 2D type: %T", frame) } return nil } From a9e3b6513bc06d08e314f6a81b53ed58382714a2 Mon Sep 17 00:00:00 2001 From: GP Date: Thu, 12 Feb 2026 14:20:50 +1300 Subject: [PATCH 2/3] adjust lifepo readins so taht it isn't in Li-Ion range --- test/lifepo_battery_readings.csv | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/lifepo_battery_readings.csv b/test/lifepo_battery_readings.csv index 9548d1d..e875b49 100644 --- a/test/lifepo_battery_readings.csv +++ b/test/lifepo_battery_readings.csv @@ -1,4 +1,4 @@ -2025-05-12 11:36:57, 0.0, 6.5267673, 0.0 +2025-05-12 11:36:57, 0.0, 6.3267673, 0.0 2025-05-12 11:36:57, 0.0, 6.5267673, 0.0 2025-05-12 11:39:37, 0.0, 6.5098147, 0.0 2025-05-12 11:39:37, 0.0, 6.5098147, 0.0 @@ -37,4 +37,5 @@ 2025-06-13 22:33:49, 0.0, 6.1707616, 0.0 2025-06-14 07:29:25, 0.0, 5.9503765, 0.0 2025-06-26 01:27:12, 0.0, 6.1538095, 0.0 -2025-06-27 03:24:18, 0.0, 5.9164724, 0.0 \ No newline at end of file +2025-06-27 03:24:18, 0.0, 5.9164724, 0.0 +2025-06-27 04:24:18, 0.0, 5.3164724, 0.0 \ No newline at end of file From ea7a8709bcf016035e12d864b4e32646a4d1ee81 Mon Sep 17 00:00:00 2001 From: GP Date: Thu, 12 Feb 2026 14:23:43 +1300 Subject: [PATCH 3/3] adjust tests --- internal/tc2-hat-attiny/battery_autodetect_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/tc2-hat-attiny/battery_autodetect_test.go b/internal/tc2-hat-attiny/battery_autodetect_test.go index 3e0cf7c..8219888 100644 --- a/internal/tc2-hat-attiny/battery_autodetect_test.go +++ b/internal/tc2-hat-attiny/battery_autodetect_test.go @@ -27,11 +27,11 @@ func TestSpecificVoltageDetection(t *testing.T) { description: "Integration test: overlapping range preference through BatteryMonitor", }, { - name: "6.6V should detect LiFePO4 2 cells", + name: "6.6V should detect Li-Ion 2 cells", voltage: 6.6, - expectedChemistry: "lifepo4", + expectedChemistry: "li-ion", expectedCells: 2, - description: "Integration test: LiFePO4 detection through BatteryMonitor", + description: "Integration test: Li-Ion detection through BatteryMonitor", }, }