Add wifi esp32 reporting, and an uptime gauge for tracking that
authorjweigele <jweigele@local>
Thu, 27 Jul 2023 16:33:16 +0000 (09:33 -0700)
committerjweigele <jweigele@local>
Thu, 27 Jul 2023 16:33:16 +0000 (09:33 -0700)
helper/helper.go
reprocess/main.go

index 3fb84680ac44860ed6926cac5e029efd204fa358..e3a2127b1dd9a6bf512f1f0316d40382240aefe6 100644 (file)
@@ -225,7 +225,8 @@ func DecodeDelivery(delivery amqp.Delivery) (map[string]interface{}, error) {
        result := make(map[string]interface{})
        // either explicitly json, or zigbee2mqtt (which we have set to only output json)
        isZigbee := strings.HasPrefix(delivery.RoutingKey, "zigbee2mqtt")
-       if delivery.ContentType == "application/json" || isZigbee {
+       isESP32 := strings.HasPrefix(delivery.RoutingKey, "esp32")
+       if delivery.ContentType == "application/json" || isZigbee || isESP32 {
                err := json.Unmarshal(delivery.Body, &result)
                if err != nil {
                        return result, err
index 9d4d80532c0b7d9e689c13ada7ef4d05d58f9801..74b8162b30bcabf5ffa124a3bd191099947e6e96 100644 (file)
@@ -58,6 +58,14 @@ var (
                []string{"location"},
        )
 
+       uptimeGauge = promauto.NewGaugeVec(
+               prometheus.GaugeOpts{
+                       Name: "sensor_uptime",
+                       Help: "Current remote sensor uptime (s)",
+               },
+               []string{"location", "friendlyname"},
+       )
+
        doorOpenCounter = promauto.NewCounterVec(
                prometheus.CounterOpts{
                        Name: "sensor_door_opened_count",
@@ -74,10 +82,11 @@ var (
                []string{"location"},
        )
 
-       tempExpire  = make(map[string]time.Time)
-       powerExpire = make(map[string]time.Time)
-       pm25Expire  = make(map[string]time.Time)
-       aqiExpire   = make(map[string]time.Time)
+       tempExpire   = make(map[string]time.Time)
+       powerExpire  = make(map[string]time.Time)
+       pm25Expire   = make(map[string]time.Time)
+       aqiExpire    = make(map[string]time.Time)
+       uptimeExpire = make(map[string]time.Time)
 
        doorMap = make(map[string]map[string]interface{})
 
@@ -131,6 +140,10 @@ type hexdevice struct {
        location string
 }
 
+type esp32wifidevice struct {
+       *hexdevice
+}
+
 func (dev *powerdevice) filter() {
        // if this gets excessive we can pass it down the chain
        now := time.Now().UTC()
@@ -171,6 +184,10 @@ func (dev *zigdevice) getRoutingKey() string {
        return fmt.Sprintf("zigbee2mqtt.%s", dev.friendlyName)
 }
 
+func (dev *esp32wifidevice) getRoutingKey() string {
+       return fmt.Sprintf("%s", dev.friendlyName)
+}
+
 func (dev *powerdevice) getReqKey() string {
        return fmt.Sprintf("zigbee2mqtt.%s.get", dev.friendlyName)
 }
@@ -210,6 +227,12 @@ func newhexdevice(friendlyName, location string) *hexdevice {
        }
 }
 
+func newesp32wifidevice(friendlyName, location string) *esp32wifidevice {
+       return &esp32wifidevice{
+               hexdevice: newhexdevice(friendlyName, location),
+       }
+}
+
 func handleTemp(obj map[string]interface{}) {
        logger.V(1).Info("Temperature received", "obj", obj)
        // these should both probably be checked for existence and type but oh well
@@ -258,6 +281,18 @@ func processPM25(location string, pm25 float64, sendChannel chan helper.RabbitSe
 
 }
 
+func processUptime(location string, friendlyName string, uptime float64, sendChannel chan helper.RabbitSend) {
+       // we don't want to have to loop back around on rabbit processing, so just set the gauge here
+       now := time.Now().UTC()
+       // do the label update here
+       uptimeGauge.With(prometheus.Labels{"location": location, "friendlyname": friendlyName}).Set(uptime)
+
+       tempHash := labelValHash{labelValues: []string{location, friendlyName}}
+       expireMutex.Lock()
+       defer expireMutex.Unlock()
+       uptimeExpire[tempHash.getHash()] = now
+}
+
 func (dev *diydevice) handleDIY(obj map[string]interface{}, sendChannel chan helper.RabbitSend) {
        logger.V(1).Info("DIY data received", "obj", obj)
        _, isAction := obj["action"]
@@ -343,31 +378,52 @@ func (dev *powerdevice) handlePower(obj map[string]interface{}, sendChannel chan
 
 }
 
-func (dev *hexdevice) handleHex(obj map[string]interface{}, sendChannel chan helper.RabbitSend) {
-       //now := time.Now().UTC()
-       logger.V(1).Info("Hex data received", "obj", obj)
+func hexCommon(location string, friendlyName string, obj map[string]interface{}, sendChannel chan helper.RabbitSend) {
        pm25, ok := obj["pm25"].(float64)
        if !ok {
-               logger.Error(nil, "contact not found in data, ignoring", "obj", obj)
-               return
+               logger.V(3).Info("pm25 not found in data, ignoring", "obj", obj)
+       } else {
+               processPM25(location, pm25, sendChannel)
        }
-       processPM25(dev.location, pm25, sendChannel)
 
        temperature, ok := obj["temperature"].(float64)
        if !ok {
-               logger.Error(nil, "contact not found in data, ignoring", "obj", obj)
-               return
+               logger.V(3).Info("temperature not found in data, ignoring it ", "obj", obj)
+       } else {
+               if temperature < -55.0 || temperature > 125.0 {
+                       logger.Error(nil, "temperature out of range, ignoring it", "temperature", temperature)
+               } else {
+                       dataMap := make(map[string]interface{}, 0)
+                       // these should all exist properly
+                       dataMap["fahrenheit"] = temperature*9/5 + 32
+                       dataMap["celsius"] = temperature
+                       dataMap["location"] = location
+                       logger.V(2).Info("Sending reprocessed temperature")
+                       // hardcoded temp routingKey for this type of measurement
+                       sendThis := helper.RabbitSend{Data: dataMap, RoutingKey: "temp", IncludeDate: true}
+                       sendChannel <- sendThis
+               }
        }
 
-       dataMap := make(map[string]interface{}, 0)
-       // these should all exist properly
-       dataMap["fahrenheit"] = temperature*9/5 + 32
-       dataMap["celsius"] = temperature
-       dataMap["location"] = dev.location
-       logger.V(2).Info("Sending reprocessed temperature")
-       // hardcoded temp routingKey for this type of measurement
-       sendThis := helper.RabbitSend{Data: dataMap, RoutingKey: "temp", IncludeDate: true}
-       sendChannel <- sendThis
+       uptime, ok := obj["uptime"].(float64)
+       if !ok {
+               logger.V(3).Info("uptime not found in data, ignoring", "obj", obj)
+       } else {
+               processUptime(location, friendlyName, uptime, sendChannel)
+       }
+
+}
+func (dev *hexdevice) handleHex(obj map[string]interface{}, sendChannel chan helper.RabbitSend) {
+       //now := time.Now().UTC()
+       logger.V(1).Info("Hex data received", "obj", obj)
+       hexCommon(dev.location, dev.friendlyName, obj, sendChannel)
+}
+
+// this can be from any number of devices, location is in the map
+func (dev *esp32wifidevice) handleESP32wifi(obj map[string]interface{}, sendChannel chan helper.RabbitSend) {
+       location := obj["location"].(string)
+       logger.V(1).Info("esp32 data received", "obj", obj)
+       hexCommon(location, "wifi", obj, sendChannel)
 }
 
 func (dev *doordevice) handleDoor(obj map[string]interface{}, sendChannel chan helper.RabbitSend) {
@@ -478,6 +534,10 @@ func readLoop(channel chan helper.RabbitSend, devices []device, rabbit helper.Ra
                                        logger.V(2).Info("Hex device, sending to handle", "device", device)
                                        device.(*hexdevice).handleHex(item, channel)
 
+                               case *esp32wifidevice:
+                                       logger.V(2).Info("ESP32 wifi device, sending to handle", "device", device)
+                                       device.(*esp32wifidevice).handleESP32wifi(item, channel)
+
                                default:
                                        logger.Info("Found a device we can't classify", "device", device, "type", t)
                                }
@@ -569,6 +629,7 @@ func expireStaleMetrics() {
        expireStaleMetric(powerExpire, powerGauge)
        expireStaleMetric(pm25Expire, pm25Gauge)
        expireStaleMetric(aqiExpire, aqiGauge)
+       expireStaleMetric(uptimeExpire, uptimeGauge)
 
 }
 
@@ -614,7 +675,9 @@ func main() {
        devices = append(devices, newdoordevice("data_door"))
 
        // hex devices (super custom)
-       devices = append(devices, newhexdevice("0xfffe7e6af7f95560", "Downstairs Test"))
+       devices = append(devices, newhexdevice("0x7e6af7fefff95560", "Downstairs Test"))
+
+       devices = append(devices, newesp32wifidevice("esp32.sensor_info", ""))
 
        //currentTemp, err := fetchTemp(weatherStation)
        channel := make(chan helper.RabbitSend)