ble-sensors/lib/xiaomi/scale/scale_v2.go

99 lines
2.5 KiB
Go

package scale
import (
"bytes"
"encoding/binary"
"log"
"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"
)
// XiaomiScaleV2UUID is BLE UUID for Xiaomi Scale V2
var XiaomiScaleV2UUID ble.UUID = []byte{0x1b, 0x18}
// ParseXiaomiScaleV2 parses V2 scale service data
func ParseXiaomiScaleV2(writeAPI *influxdb2_api.WriteAPI, logger *zap.Logger, timestamp time.Time, detector string, description string, advertisement ble.Advertisement, index int, sd ble.ServiceData) {
var scaleData struct {
RawUnit uint8
ControlByte uint8
Year uint16
Month uint8
Day uint8
Hour uint8
Minute uint8
Second uint8
Impedance uint16
RawWeight uint16
}
err := binary.Read(bytes.NewBuffer(sd.Data), binary.LittleEndian, &scaleData)
if err != nil {
panic(err)
}
isStabilized := (scaleData.ControlByte & (1 << 5)) != 0
hasImpedance := (scaleData.ControlByte & (1 << 1)) != 0
var originalUnit string
var weight float64
switch scaleData.RawUnit {
case 3:
originalUnit = "lbs"
weight = float64(scaleData.RawWeight) / 100.0 * 0.453592
case 2:
originalUnit = "kg"
weight = float64(scaleData.RawWeight) / 200.0
default:
originalUnit = "unknown"
weight = float64(scaleData.RawWeight)
}
if isStabilized {
loc, err := time.LoadLocation("Local")
if err != nil {
log.Fatal(err)
}
scaleTimestamp := time.Date(
int(scaleData.Year),
time.Month(scaleData.Month),
int(scaleData.Day),
int(scaleData.Hour),
int(scaleData.Minute),
int(scaleData.Second),
0,
loc)
difference := timestamp.Sub(scaleTimestamp)
point := influxdb2.NewPointWithMeasurement("sensor")
point.SetTime(scaleTimestamp)
if detector != "" {
point.AddTag("detector", detector)
}
point.AddTag("address", advertisement.Addr().String())
point.AddTag("weight_unit", "kg")
point.AddTag("original_weight_unit", originalUnit)
point.AddField("time_difference", difference.Seconds())
point.AddField("weight", weight)
if hasImpedance {
point.AddField("impedance", scaleData.Impedance)
}
(*writeAPI).WritePoint(point)
logger.Debug("xiaomi v2 scale",
zap.String("name", advertisement.LocalName()),
zap.String("source", advertisement.Addr().String()),
zap.String("description", description),
zap.Bool("is_stabilized", isStabilized),
zap.Bool("has_impedance", hasImpedance),
zap.Float64("weight", weight))
}
}