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("weight") point.SetTime(scaleTimestamp) if detector != "" { point.AddTag("detector", detector) } point.AddTag("address", advertisement.Addr().String()) if description != "" { point.AddTag("description", description) } point.AddTag("unit", "kg") point.AddTag("original_unit", originalUnit) point.AddField("time_difference", difference.Seconds()) point.AddField("value", 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)) } }