126 lines
3.5 KiB
Go
126 lines
3.5 KiB
Go
|
package scale
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"encoding/binary"
|
||
|
"fmt"
|
||
|
"log"
|
||
|
"os"
|
||
|
"sync"
|
||
|
"time"
|
||
|
|
||
|
"github.com/currantlabs/ble"
|
||
|
influxdb2 "github.com/influxdata/influxdb-client-go"
|
||
|
influxdb2_api "github.com/influxdata/influxdb-client-go/api"
|
||
|
)
|
||
|
|
||
|
// XiaomiScaleV2UUID is BLE UUID for Xiaomi Scale V2
|
||
|
var XiaomiScaleV2UUID ble.UUID = []byte{0x1b, 0x18}
|
||
|
|
||
|
// ParseXiaomiScaleV2 parses V2 scale service data
|
||
|
func ParseXiaomiScaleV2(mux *sync.Mutex, writeAPI *influxdb2_api.WriteAPI, advertisement ble.Advertisement, index int, sd ble.ServiceData) {
|
||
|
timestamp := time.Now()
|
||
|
|
||
|
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)
|
||
|
hostname, _ := os.Hostname()
|
||
|
if hostname != "" {
|
||
|
point.AddTag("detector", hostname)
|
||
|
}
|
||
|
point.AddTag("address", advertisement.Address().String())
|
||
|
point.AddTag("weight_unit", "kg")
|
||
|
point.AddTag("original_weight_unit", originalUnit)
|
||
|
point.AddField("rssi", advertisement.RSSI())
|
||
|
point.AddField("weight", weight)
|
||
|
if hasImpedance {
|
||
|
point.AddField("impedance", scaleData.Impedance)
|
||
|
}
|
||
|
(*writeAPI).WritePoint(point)
|
||
|
|
||
|
mux.Lock()
|
||
|
fmt.Printf("*******************************************\n")
|
||
|
fmt.Printf("Xiaomi V2 Scale\n")
|
||
|
fmt.Printf("[%s] %3d:\n", advertisement.Address(), advertisement.RSSI())
|
||
|
if len(advertisement.LocalName()) > 0 {
|
||
|
fmt.Printf(" Name: %s\n", advertisement.LocalName())
|
||
|
}
|
||
|
if len(advertisement.Services()) > 0 {
|
||
|
fmt.Printf(" Svcs: %v\n", advertisement.Services())
|
||
|
}
|
||
|
if len(advertisement.ManufacturerData()) > 0 {
|
||
|
fmt.Printf(" MD: %v\n", advertisement.ManufacturerData())
|
||
|
}
|
||
|
fmt.Printf(" rawUnit: %d\n", scaleData.RawUnit)
|
||
|
fmt.Printf(" Control byte: %d %b\n", scaleData.ControlByte, scaleData.ControlByte)
|
||
|
fmt.Printf(" Control byte X: %d\n", scaleData.ControlByte&^(1<<5)&^(1<<1))
|
||
|
fmt.Printf(" Is stabilized: %v\n", isStabilized)
|
||
|
fmt.Printf(" Has impedance: %v\n", hasImpedance)
|
||
|
fmt.Printf(" Year: %d\n", scaleData.Year)
|
||
|
fmt.Printf(" Month: %d\n", scaleData.Month)
|
||
|
fmt.Printf(" Day: %v\n", scaleData.Day)
|
||
|
fmt.Printf(" Hour: %d\n", scaleData.Hour)
|
||
|
fmt.Printf(" Minute: %d\n", scaleData.Minute)
|
||
|
fmt.Printf(" Second: %d\n", scaleData.Second)
|
||
|
fmt.Printf(" Measurement taken %s ago\n", difference)
|
||
|
fmt.Printf(" Impedance: %d\n", scaleData.Impedance)
|
||
|
fmt.Printf(" Raw weight: %d\n", scaleData.RawWeight)
|
||
|
fmt.Printf(" Weight: %f %s\n", weight, originalUnit)
|
||
|
fmt.Printf("*******************************************\n")
|
||
|
mux.Unlock()
|
||
|
}
|
||
|
|
||
|
}
|