120 lines
3.7 KiB
Go
120 lines
3.7 KiB
Go
package cleargrass
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"encoding/hex"
|
|
"time"
|
|
|
|
"github.com/go-ble/ble"
|
|
influxdb2 "github.com/influxdata/influxdb-client-go"
|
|
influxdb2_api "github.com/influxdata/influxdb-client-go/api"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
// https://github.com/alexvenom/XiaomiCleargrassInkDislpay/blob/master/XiaomiClearGrassInk.js
|
|
|
|
// CleargrassUUID is the Bluetooth UUID for Cleargrass BLE sensor data
|
|
var CleargrassUUID ble.UUID = []byte{0xcd, 0xfd}
|
|
|
|
// ParseCleargrassSensorData .
|
|
func ParseCleargrassSensorData(writeAPI *influxdb2_api.WriteAPI, logger *zap.Logger, timestamp time.Time, detector string, description string, advertisement ble.Advertisement, index int, sd ble.ServiceData) {
|
|
logger.Debug("cleargrass", zap.String("event_data", hex.Dump(sd.Data)),
|
|
zap.Int("length", len(sd.Data)))
|
|
for eventOffset := 8; eventOffset < len(sd.Data)-2; {
|
|
eventType := sd.Data[eventOffset]
|
|
eventLength := int(sd.Data[eventOffset+1])
|
|
if eventOffset+eventLength > len(sd.Data) {
|
|
logger.Warn("event length exceeds data length")
|
|
return
|
|
}
|
|
eventData := sd.Data[eventOffset+2 : eventOffset+2+eventLength]
|
|
eventOffset = eventOffset + 2 + eventLength
|
|
|
|
switch eventType {
|
|
case 0x01:
|
|
if eventLength != 4 {
|
|
logger.Warn("temperature/humidity event length should be 4",
|
|
zap.String("event_data", hex.Dump(eventData)))
|
|
continue
|
|
}
|
|
|
|
temperature := float64(binary.LittleEndian.Uint16(eventData[0:2])) / 10
|
|
|
|
point := influxdb2.NewPointWithMeasurement("temperature")
|
|
point.SetTime(timestamp)
|
|
if detector != "" {
|
|
point.AddTag("detector", detector)
|
|
}
|
|
point.AddTag("address", advertisement.Addr().String())
|
|
if description != "" {
|
|
point.AddTag("description", description)
|
|
}
|
|
point.AddTag("unit", "°C")
|
|
point.AddField("value", temperature)
|
|
(*writeAPI).WritePoint(point)
|
|
|
|
logger.Debug("sending sensor reading",
|
|
zap.String("source", advertisement.Addr().String()),
|
|
zap.String("description", description),
|
|
zap.String("measurement", "temperature"),
|
|
zap.String("measurement_unit", "°C"),
|
|
zap.Float64("value", temperature))
|
|
|
|
humidity := float64(binary.LittleEndian.Uint16(eventData[2:4])) / 10
|
|
|
|
point = influxdb2.NewPointWithMeasurement("humidity")
|
|
point.SetTime(timestamp)
|
|
if detector != "" {
|
|
point.AddTag("detector", detector)
|
|
}
|
|
point.AddTag("address", advertisement.Addr().String())
|
|
if description != "" {
|
|
point.AddTag("description", description)
|
|
}
|
|
point.AddTag("unit", "%")
|
|
point.AddField("value", humidity)
|
|
(*writeAPI).WritePoint(point)
|
|
|
|
logger.Debug("sending sensor reading",
|
|
zap.String("source", advertisement.Addr().String()),
|
|
zap.String("description", description),
|
|
zap.String("measurement", "humidity"),
|
|
zap.String("measurement_unit", "%"),
|
|
zap.Float64("value", humidity))
|
|
|
|
case 0x02:
|
|
if eventLength != 1 {
|
|
logger.Warn("battery event length should be 1")
|
|
continue
|
|
}
|
|
|
|
battery := int(eventData[0])
|
|
|
|
point := influxdb2.NewPointWithMeasurement("battery")
|
|
point.SetTime(timestamp)
|
|
if detector != "" {
|
|
point.AddTag("detector", detector)
|
|
}
|
|
point.AddTag("address", advertisement.Addr().String())
|
|
if description != "" {
|
|
point.AddTag("description", description)
|
|
}
|
|
point.AddTag("unit", "%")
|
|
point.AddField("value", battery)
|
|
(*writeAPI).WritePoint(point)
|
|
|
|
logger.Debug("sending sensor reading",
|
|
zap.String("source", advertisement.Addr().String()),
|
|
zap.String("description", description),
|
|
zap.String("measurement", "battery"),
|
|
zap.String("measurement_unit", "%"),
|
|
zap.Int("value", battery))
|
|
|
|
default:
|
|
logger.Warn("unknown event type",
|
|
zap.Uint8("event_type", eventType),
|
|
zap.String("event_data", hex.Dump(eventData)))
|
|
}
|
|
}
|
|
|
|
}
|