2 Commits

Author SHA1 Message Date
Hermes 1704d8a833 CUB-228: add battery_calibration_offset to cameras table
CI/CD / lint-and-typecheck (pull_request) Successful in 6s
CI/CD / test (pull_request) Successful in 6s
CI/CD / build (pull_request) Failing after 4m47s
CI/CD / deploy (pull_request) Has been skipped
- Add column to 001_create_tables.sql for fresh databases
- Add migration 002 for existing databases (idempotent via
  pragma_table_info check)
- Implement runIncrementalMigrations in db.go
- Add BatteryCalibrationOffset to Camera model
- Update all camera SELECT queries (cameras List, detail, MQTT
  subscriber getCamera, register)
2026-05-22 22:31:54 -04:00
overseer 1a8f67a392 Merge pull request 'feat: add v3 hardware case and update hub network' (#6) from agent/hermes/remoterig-hardware-v3-network into dev
Build (Dev) / build (push) Failing after 9s
CI/CD / lint-and-typecheck (push) Successful in 9m29s
CI/CD / test (push) Successful in 9m27s
CI/CD / build (push) Failing after 4m50s
CI/CD / deploy (push) Has been skipped
Reviewed-on: #6
2026-05-22 19:43:40 -04:00
6 changed files with 49 additions and 14 deletions
+2 -2
View File
@@ -132,10 +132,10 @@ func GetCameraDetail(database *db.DB) http.HandlerFunc {
// Get camera info
var c models.Camera
err := database.QueryRowContext(r.Context(), `
SELECT camera_id, friendly_name, mac_address, created_at, updated_at
SELECT camera_id, friendly_name, mac_address, battery_calibration_offset, created_at, updated_at
FROM cameras WHERE camera_id = ?
`, cameraID).Scan(
&c.CameraID, &c.FriendlyName, &c.MacAddress,
&c.CameraID, &c.FriendlyName, &c.MacAddress, &c.BatteryCalibrationOffset,
&c.CreatedAt, &c.UpdatedAt,
)
if err == sql.ErrNoRows {
+28
View File
@@ -14,6 +14,9 @@ import (
//go:embed migrations/001_create_tables.sql
var migration001 string
//go:embed migrations/002_add_camera_calibration.sql
var migration002 string
// DB wraps the sql.DB with connection-level settings.
type DB struct {
*sql.DB
@@ -62,6 +65,12 @@ func Open(path string) (*DB, error) {
return nil, err
}
log.Println("Migrations complete")
} else {
// Run incremental migrations on existing databases
if err := runIncrementalMigrations(db); err != nil {
db.Close()
return nil, err
}
}
return &DB{db}, nil
@@ -83,6 +92,25 @@ func migrate(db *sql.DB, sql string) error {
return nil
}
// runIncrementalMigrations applies migrations that haven't been run yet on
// an existing database (one where the 001 schema already exists).
func runIncrementalMigrations(db *sql.DB) error {
// Migration 002: add battery_calibration_offset if it doesn't exist
var colCount int
err := db.QueryRow(`SELECT COUNT(*) FROM pragma_table_info('cameras') WHERE name = 'battery_calibration_offset'`).Scan(&colCount)
if err != nil {
return err
}
if colCount == 0 {
log.Println("Running migration 002: add battery_calibration_offset")
if err := migrate(db, migration002); err != nil {
return err
}
}
return nil
}
// splitSQL splits a SQL string on semicolons, respecting quoted strings.
func splitSQL(sql string) []string {
var stmts []string
@@ -6,6 +6,7 @@ CREATE TABLE IF NOT EXISTS cameras (
camera_id TEXT PRIMARY KEY,
friendly_name TEXT NOT NULL,
mac_address TEXT UNIQUE,
battery_calibration_offset REAL,
created_at DATETIME NOT NULL DEFAULT (datetime('now')),
updated_at DATETIME NOT NULL DEFAULT (datetime('now'))
);
@@ -0,0 +1,5 @@
-- Migration 002: Add battery_calibration_offset to cameras table
-- This column stores a per-camera calibration value for converting raw battery
-- readings (e.g. GoPro Hero 3 byte at offset 57) into percentage values.
ALTER TABLE cameras ADD COLUMN battery_calibration_offset REAL;
+2 -2
View File
@@ -404,9 +404,9 @@ func extractCameraID(topic string) string {
func getCamera(db *db.DB, cameraID string) (models.Camera, error) {
var cam models.Camera
err := db.QueryRow(
"SELECT camera_id, friendly_name, COALESCE(mac_address,''), created_at, updated_at FROM cameras WHERE camera_id = ?",
"SELECT camera_id, friendly_name, COALESCE(mac_address,''), COALESCE(battery_calibration_offset, NULL), created_at, updated_at FROM cameras WHERE camera_id = ?",
cameraID,
).Scan(&cam.CameraID, &cam.FriendlyName, &cam.MacAddress, &cam.CreatedAt, &cam.UpdatedAt)
).Scan(&cam.CameraID, &cam.FriendlyName, &cam.MacAddress, &cam.BatteryCalibrationOffset, &cam.CreatedAt, &cam.UpdatedAt)
return cam, err
}
+1
View File
@@ -10,6 +10,7 @@ type Camera struct {
CameraID string `json:"camera_id"`
FriendlyName string `json:"friendly_name"`
MacAddress string `json:"mac_address,omitempty"`
BatteryCalibrationOffset *float64 `json:"battery_calibration_offset,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}