Update x,y and add db writes back in
This commit is contained in:
102
main.go
102
main.go
@ -49,39 +49,39 @@ type Light struct {
|
|||||||
MinOnDurationMS int64 `json:"min_on_duration_ms"`
|
MinOnDurationMS int64 `json:"min_on_duration_ms"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var defaultLights = map[string]Light{
|
var defaultLights = map[string]Light{
|
||||||
"furnace_power": {"Furnace Power", 1146, 785, "urgent", 100},
|
"living_room_stat": {"Living Room Thermostat", 775, 251, "low", 100},
|
||||||
"living_room_stat": {"Living Room Thermostat", 885, 230, "low", 100},
|
"living_room_heat": {"Living Room Heating", 1320, 263, "low", 100},
|
||||||
"living_room_heat": {"Living Room Heating", 1395, 240, "low", 100},
|
"dining_room_stat": {"Dining Room Thermostat", 779, 290, "low", 100},
|
||||||
"dining_room_stat": {"Dining Room Thermostat", 885, 272, "low", 100},
|
"dining_room_heat": {"Dining Room Heating", 1317, 305, "low", 100},
|
||||||
"dining_room_heat": {"Dining Room Heating", 1400, 275, "low", 100},
|
"hot_water_stat": {"Hot Water Thermostat", 773, 488, "low", 100},
|
||||||
"hot_water_stat": {"Hot Water Thermostat", 880, 445, "low", 100},
|
"hot_water_heat": {"Hot Water Heating", 1313, 501, "low", 100},
|
||||||
"hot_water_heat": {"Hot Water Heating", 1405, 445, "low", 100},
|
"first_bed_stat": {"First Bedroom Thermostat", 769, 526, "low", 100},
|
||||||
"first_bed_stat": {"First Bedroom Thermostat", 880, 480, "low", 100},
|
"first_bed_heat": {"First Bedroom Heating", 1309, 540, "low", 100},
|
||||||
"first_bed_heat": {"First Bedroom Heating", 1407, 488, "low", 100},
|
"master_bed_stat": {"Master Bedroom Thermostat", 773, 570, "low", 100},
|
||||||
"master_bed_stat": {"Master Bedroom Thermostat", 880, 530, "low", 100},
|
"master_bed_heat": {"Master Bedroom Heating", 1309, 588, "low", 100},
|
||||||
"master_bed_heat": {"Master Bedroom Heating", 1407, 538, "low", 100},
|
"basement_stat": {"Basement Thermostat", 769, 614, "low", 100},
|
||||||
"basement_stat": {"Basement Thermostat", 879, 564, "low", 100},
|
"basement_heat": {"Basement Heating", 1309, 630, "low", 100},
|
||||||
"basement_heat": {"Basement Heating", 1413, 578, "low", 100},
|
"second_bed_stat": {"Second Bedroom Thermostat", 764, 657, "low", 100},
|
||||||
"second_bed_stat": {"Second Bedroom Thermostat", 875, 613, "low", 100},
|
"second_bed_heat": {"Second Bedroom Heating", 1307, 672, "low", 100},
|
||||||
"second_bed_heat": {"Second Bedroom Heating", 1413, 618, "low", 100},
|
"inducer": {"Inducer", 1307, 711, "low", 100},
|
||||||
"inducer": {"Inducer", 1415, 662, "low", 100},
|
"burner": {"Burner", 1307, 760, "low", 100},
|
||||||
"burner": {"Burner", 1415, 699, "low", 100},
|
"circulator": {"Circulator", 1307, 799, "low", 100},
|
||||||
"circulator": {"Circulator", 1418, 749, "low", 100},
|
"furnace_power": {"Furnace Power", 1038, 837, "urgent", 100},
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
fmt.Println("Starting multi-light monitor")
|
fmt.Println("Starting multi-light monitor")
|
||||||
|
|
||||||
dbPath := getEnv("LIGHT_DB_PATH", "lightlog.db")
|
dbPath := getEnv("LIGHT_DB_PATH", "lightlog.db")
|
||||||
webcamURL := getEnv("WEBCAM_URL", "http://furnace.service:8082/stream")
|
webcamURL := getEnv("WEBCAM_URL", "http://furnace.service:8081/stream")
|
||||||
minBrightness := getEnvInt("MIN_BRIGHTNESS", 160)
|
minBrightness := getEnvInt("MIN_BRIGHTNESS", 170)
|
||||||
checkInterval := getEnvDuration("CHECK_INTERVAL", 2*time.Second)
|
checkInterval := getEnvDuration("CHECK_INTERVAL", 2*time.Second)
|
||||||
webPort := getEnv("FURNACE_WEB_PORT", "8090")
|
webPort := getEnv("FURNACE_WEB_PORT", "8090")
|
||||||
lights, err := loadLightsFromEnv()
|
lights, err := loadLightsFromEnv()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("Using DB:", dbPath)
|
fmt.Println("Using DB:", dbPath)
|
||||||
fmt.Println("Using webcam:", webcamURL)
|
fmt.Println("Using webcam:", webcamURL)
|
||||||
@ -104,6 +104,10 @@ func main() {
|
|||||||
state TEXT,
|
state TEXT,
|
||||||
timestamp DATETIME
|
timestamp DATETIME
|
||||||
)`)
|
)`)
|
||||||
|
_, err = db.Exec(`CREATE INDEX IF NOT EXISTS idx_light_checks_name_ts
|
||||||
|
ON light_checks(name, timestamp DESC
|
||||||
|
);`)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -111,12 +115,14 @@ func main() {
|
|||||||
prevStates := make(map[string]bool)
|
prevStates := make(map[string]bool)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
img, err := grabFrame(webcamURL)
|
img, err := grabFrame(webcamURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("Error grabbing frame:", err)
|
log.Println("Error grabbing frame:", err)
|
||||||
time.Sleep(time.Second)
|
time.Sleep(time.Second)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
|
|
||||||
for key, light := range lights {
|
for key, light := range lights {
|
||||||
on := isLightOn(img, light, minBrightness)
|
on := isLightOn(img, light, minBrightness)
|
||||||
@ -125,11 +131,12 @@ func main() {
|
|||||||
if on != prevStates[key] {
|
if on != prevStates[key] {
|
||||||
stateStr := onOff(on)
|
stateStr := onOff(on)
|
||||||
|
|
||||||
// Notify
|
|
||||||
fmt.Printf("%s: %s\n", light.Name, stateStr)
|
fmt.Printf("%s: %s\n", light.Name, stateStr)
|
||||||
|
|
||||||
|
insertLightEvent(db, key, on, now)
|
||||||
|
|
||||||
sendNtfyNotification(light, on)
|
sendNtfyNotification(light, on)
|
||||||
|
|
||||||
// Update previous state
|
|
||||||
prevStates[key] = on
|
prevStates[key] = on
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -141,7 +148,7 @@ func main() {
|
|||||||
func loadLightsFromEnv() (map[string]Light, error) {
|
func loadLightsFromEnv() (map[string]Light, error) {
|
||||||
raw := os.Getenv("LIGHTS_JSON")
|
raw := os.Getenv("LIGHTS_JSON")
|
||||||
if raw == "" {
|
if raw == "" {
|
||||||
return defaultLights, nil
|
return defaultLights, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var lights map[string]Light
|
var lights map[string]Light
|
||||||
@ -156,7 +163,6 @@ func loadLightsFromEnv() (map[string]Light, error) {
|
|||||||
return lights, nil
|
return lights, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func grabFrame(url string) (image.Image, error) {
|
func grabFrame(url string) (image.Image, error) {
|
||||||
resp, err := http.Get(url)
|
resp, err := http.Get(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -268,10 +274,10 @@ func sendNtfyNotification(light Light, on bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func startWebServer(db *sql.DB, port string) {
|
func startWebServer(db *sql.DB, port string) {
|
||||||
lights, err := loadLightsFromEnv()
|
lights, err := loadLightsFromEnv()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
http.HandleFunc("/lights", func(w http.ResponseWriter, r *http.Request) {
|
http.HandleFunc("/lights", func(w http.ResponseWriter, r *http.Request) {
|
||||||
rows, err := db.Query(`
|
rows, err := db.Query(`
|
||||||
@ -303,3 +309,21 @@ func startWebServer(db *sql.DB, port string) {
|
|||||||
log.Println("HTTP server listening on", port)
|
log.Println("HTTP server listening on", port)
|
||||||
log.Fatal(http.ListenAndServe(":"+port, nil))
|
log.Fatal(http.ListenAndServe(":"+port, nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func insertLightEvent(db *sql.DB, name string, on bool, ts time.Time) {
|
||||||
|
state := "off"
|
||||||
|
if on {
|
||||||
|
state = "on"
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := db.Exec(
|
||||||
|
`INSERT INTO light_checks (name, state, timestamp)
|
||||||
|
VALUES (?, ?, ?)`,
|
||||||
|
name,
|
||||||
|
state,
|
||||||
|
ts,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("DB insert failed:", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user