diff --git a/alert.go b/alert.go index 05f1b47..cf8bc32 100644 --- a/alert.go +++ b/alert.go @@ -100,17 +100,19 @@ func DispatchAlert(deveui string, alertType string) { } // then we check that an alert was not already sent out recently - if AlertAlreadySentRecently(deveui) { + if AlertAlreadySentRecently(deveui, alertType) { fmt.Printf("Error: Alert for Deveui %s has already been sent!", deveui) return } // then we make an entry that an alert was sent, this will expire automatically - AddAlertAlreadySentRecently(deveui) + AddAlertAlreadySentRecently(deveui, alertType) // then we send the alert if alertType == "alert_button" { alertMessage = fmt.Sprintf("Alarm (%s): Knopf gedrueckt, %s", getDevAlias(deveui), time.Now().Format("02.01.2006 15:04:05")) + } else if alertType == "alert_greenzone" { + alertMessage = fmt.Sprintf("Alarm (%s): Gruene Zone wurde verlassen, %s", getDevAlias(deveui), time.Now().Format("02.01.2006 15:04:05")) } sendAlert(deveui, alertMessage) } diff --git a/persistence.go b/persistence.go index 2747777..173a653 100644 --- a/persistence.go +++ b/persistence.go @@ -192,29 +192,66 @@ func getEmail(deveui string) string { return res } -func AlertAlreadySentRecently(deveui string) bool { +func getDevGreenzone(deveui string) string { + res := "" + + if deveui == "" { + return res + } + conn := globalPool.Get() defer conn.Close() - exists, _ := redis.Bool(conn.Do("EXISTS", alertsentPrefix+deveui)) + greenzone, err := redis.String(conn.Do("HGET", devPrefix+deveui, "greenzone")) + if err == nil { + res = greenzone + } else { + log.Print(err) + } + + return res +} + +func AlertAlreadySentRecently(deveui string, what string) bool { + conn := globalPool.Get() + defer conn.Close() + + exists, _ := redis.Bool(conn.Do("EXISTS", alertsentPrefix+deveui+":"+what)) return exists } -func AddAlertAlreadySentRecently(deveui string) { +func AddAlertAlreadySentRecently(deveui string, what string) { conn := globalPool.Get() defer conn.Close() + expire_duration := 120 + if what == "alert_greenzone" { + expire_duration = 7 * 24 * 60 * 60 + } - _, err := conn.Do("SET", alertsentPrefix+deveui, "1") + _, err := conn.Do("SET", alertsentPrefix+deveui+":"+what, "1") if err != nil { return } // we set an expiration time to prevent duplicate alerts - _, err1 := conn.Do("EXPIRE", alertsentPrefix+deveui, 120) + _, err1 := conn.Do("EXPIRE", alertsentPrefix+deveui+":"+what, expire_duration) if err1 != nil { return } } + +func DeleteGreenzoneAlert(deveui string) bool { + conn := globalPool.Get() + defer conn.Close() + + _, err := conn.Do("DEL", alertsentPrefix+deveui+":alert_greenzone") + if err != nil { + return false + } + + return true + +} diff --git a/wo-bisch-lorahandler.go b/wo-bisch-lorahandler.go index 334078e..24c2981 100644 --- a/wo-bisch-lorahandler.go +++ b/wo-bisch-lorahandler.go @@ -11,6 +11,8 @@ import ( "log" "net/http" "os" + "strconv" + "strings" "time" ) @@ -65,6 +67,30 @@ func Convert2Hex(payload_raw string) (string, error) { return res, err } +func IsOutsideGreenzone(deveui string, lon float64, lat float64) bool { + res := false + if lon < 1 { + return res + } + if lat < 1 { + return res + } + greenzone := getDevGreenzone(deveui) + if greenzone != "" { + coords := strings.Split(greenzone, ",") + if len(coords) == 4 { + lon_min, _ := strconv.ParseFloat(coords[0], 32) + lat_min, _ := strconv.ParseFloat(coords[1], 32) + lon_max, _ := strconv.ParseFloat(coords[2], 32) + lat_max, _ := strconv.ParseFloat(coords[3], 32) + res = (lon < lon_min || lon > lon_max || lat < lat_min || lat > lat_max) + } else { + log.Printf("greenzone does not have right format: %s!", greenzone) + } + } + return res +} + func DecodePayload(s string, deveui string) { type payload struct { Latitude uint32 @@ -85,18 +111,27 @@ func DecodePayload(s string, deveui string) { fmt.Println(err) } - log.Printf("Latitude: %.5f", float32(pl.Latitude)/1000000.0) - log.Printf("Longitude: %.5f", float32(pl.Longitude)/1000000.0) - log.Printf("AlarmBat: %d", pl.AlarmBat) - log.Printf("Flag: %d", pl.Flag) + log.Printf("Latitude: %.5f", float32(pl.Latitude)/1000000.0) + log.Printf("Longitude: %.5f", float32(pl.Longitude)/1000000.0) + log.Printf("AlarmBat: %d", pl.AlarmBat) + log.Printf("Flag: %d", pl.Flag) vbat := (pl.AlarmBat & 0x3fff) // Battery Voltage in mV fw := 160 + (pl.Flag & 0x1f) // Firmware version; 5 bits alarm := (pl.AlarmBat & 0x4000) == 0x4000 // Alarm Bit + outsideGreenzone := IsOutsideGreenzone(deveui, float64(pl.Longitude)/1000000.0, float64(pl.Latitude)/1000000.0) + flags := 0 + if outsideGreenzone { + flags += 2 + } + if alarm { + flags += 1 + } - log.Printf("AlarmBit: %v", alarm) + log.Printf("AlarmBit: %v", alarm) + log.Printf("outsideGreenzone: %v", outsideGreenzone) - mystring := fmt.Sprintf("measurement,deveui=%s lat=%.5f,lon=%.5f,vbat=%d,fw=%d %d\n", deveui, float32(pl.Latitude)/1000000.0, float32(pl.Longitude)/1000000.0, vbat, fw, (time.Now().Unix() * 1000 * 1000 * 1000)) + mystring := fmt.Sprintf("measurement,deveui=%s lat=%.5f,lon=%.5f,vbat=%d,fw=%d,flags=%d %d\n", deveui, float32(pl.Latitude)/1000000.0, float32(pl.Longitude)/1000000.0, vbat, fw, flags, (time.Now().Unix() * 1000 * 1000 * 1000)) WriteStringToFile(mystring, deveui) // we send an alert, when the alert bit is set @@ -104,6 +139,16 @@ func DecodePayload(s string, deveui string) { log.Printf("DispatchAlert (button pressed) for %s\n", deveui) DispatchAlert(deveui, "alert_button") } + if outsideGreenzone { + log.Printf("DispatchAlert (outside greenzone) for %s\n", deveui) + DispatchAlert(deveui, "alert_greenzone") + } else { + // we reset the alert, when we are again withing the greenzone + if AlertAlreadySentRecently(deveui, "alert_greenzone") { + fmt.Printf("Info: we are again in Greenzone for Deveui %s, clear alert!", deveui) + DeleteGreenzoneAlert(deveui) + } + } } else { log.Printf("Payload is not >= 11 bytes (22 chars): %s", s)