219 lines
6.5 KiB
Go
219 lines
6.5 KiB
Go
package cmd
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"sync"
|
|
"time"
|
|
|
|
"git.ocjtech.us/jeff/bluelisten/lib/bluetooth"
|
|
xiaomi_mijia "git.ocjtech.us/jeff/bluelisten/lib/xiaomi/mijia"
|
|
xiaomi_scale "git.ocjtech.us/jeff/bluelisten/lib/xiaomi/scale"
|
|
"github.com/currantlabs/ble"
|
|
"github.com/currantlabs/ble/linux"
|
|
mqtt "github.com/eclipse/paho.mqtt.golang"
|
|
influxdb2 "github.com/influxdata/influxdb-client-go"
|
|
influxdb2_api "github.com/influxdata/influxdb-client-go/api"
|
|
"github.com/pkg/errors"
|
|
"github.com/spf13/cobra"
|
|
"github.com/spf13/viper"
|
|
)
|
|
|
|
// listenCmd represents the listen command
|
|
var listenCmd = &cobra.Command{
|
|
Use: "listen",
|
|
Short: "A brief description of your command",
|
|
Long: `A longer description that spans multiple lines and likely contains examples
|
|
and usage of using your command. For example:
|
|
|
|
Cobra is a CLI library for Go that empowers applications.
|
|
This application is a tool to generate the needed files
|
|
to quickly create a Cobra application.`,
|
|
Run: listen,
|
|
}
|
|
|
|
func init() {
|
|
rootCmd.AddCommand(listenCmd)
|
|
|
|
// Here you will define your flags and configuration settings.
|
|
|
|
// Cobra supports Persistent Flags which will work for this command
|
|
// and all subcommands, e.g.:
|
|
// listenCmd.PersistentFlags().String("foo", "", "A help for foo")
|
|
|
|
// Cobra supports local flags which will only run when this command
|
|
// is called directly, e.g.:
|
|
// listenCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
|
}
|
|
|
|
var client influxdb2.Client
|
|
var writeAPI influxdb2_api.WriteAPI
|
|
|
|
func listen(cmd *cobra.Command, args []string) {
|
|
d, err := linux.NewDevice()
|
|
if err != nil {
|
|
log.Fatalf("can't new device : %s", err)
|
|
}
|
|
ble.SetDefaultDevice(d)
|
|
|
|
serverURL := viper.GetString("influxdb2.server_url")
|
|
token := viper.GetString("influxdb2.token")
|
|
organization := viper.GetString("influxdb2.organization")
|
|
bucket := viper.GetString("influxdb2.bucket")
|
|
|
|
client = influxdb2.NewClientWithOptions(serverURL, token, influxdb2.DefaultOptions().SetBatchSize(20))
|
|
writeAPI = client.WriteAPI(organization, bucket)
|
|
|
|
ctx := ble.WithSigHandler(context.WithCancel(context.Background()))
|
|
chkErr(ble.listen(ctx, true, advHandler, nil))
|
|
|
|
writeAPI.Flush()
|
|
client.Close()
|
|
}
|
|
|
|
var tileUUID ble.UUID = []byte{0xed, 0xfe}
|
|
var nestUUID ble.UUID = []byte{0xaf, 0xfe}
|
|
|
|
var mux sync.Mutex
|
|
var mqttClient mqtt.Client
|
|
|
|
func advHandler(a ble.Advertisement) {
|
|
|
|
// fmt.Printf("[%s] %3d:\n", a.Address(), a.RSSI())
|
|
// fmt.Printf("\n")
|
|
// if len(a.LocalName()) > 0 {
|
|
// fmt.Printf(" Name: %s\n", a.LocalName())
|
|
// }
|
|
// if len(a.Services()) > 0 {
|
|
// fmt.Printf(" Svcs: %v\n", a.Services())
|
|
// }
|
|
// if len(a.ManufacturerData()) > 0 {
|
|
// fmt.Printf(" MD: %v\n", a.ManufacturerData())
|
|
// }
|
|
// fmt.Printf("\n")
|
|
|
|
if len(a.ServiceData()) > 0 {
|
|
for index, sd := range a.ServiceData() {
|
|
switch {
|
|
case sd.UUID.Equal(xiaomi_scale.XiaomiScaleV1UUID):
|
|
xiaomi_scale.ParseXiaomiScaleV1(&mux, &writeAPI, a, index, sd)
|
|
|
|
case sd.UUID.Equal(xiaomi_scale.XiaomiScaleV2UUID):
|
|
xiaomi_scale.ParseXiaomiScaleV2(&mux, &writeAPI, a, index, sd)
|
|
|
|
case sd.UUID.Equal(xiaomi_mijia.XiaomiMijiaHTV1UUID):
|
|
xiaomi_mijia.ParseXiaomiMijiaSensorData(&mux, &writeAPI, a, index, sd)
|
|
|
|
case sd.UUID.Equal(tileUUID):
|
|
timestamp := time.Now()
|
|
point := influxdb2.NewPointWithMeasurement("sensor")
|
|
point.SetTime(timestamp)
|
|
detector, _ := os.Hostname()
|
|
if detector != "" {
|
|
point.AddTag("detector", detector)
|
|
}
|
|
point.AddTag("address", a.Address().String())
|
|
description := bluetooth.GetDescription(a.Address())
|
|
if description != "" {
|
|
point.AddTag("description", description)
|
|
}
|
|
point.AddField("rssi", a.RSSI())
|
|
writeAPI.WritePoint(point)
|
|
|
|
// mux.Lock()
|
|
// fmt.Printf("*******************************************\n")
|
|
// fmt.Printf("Tile\n")
|
|
// if len(a.LocalName()) > 0 {
|
|
// fmt.Printf(" Name: %s\n", a.LocalName())
|
|
// }
|
|
// if len(a.Services()) > 0 {
|
|
// fmt.Printf(" Svcs: %v\n", a.Services())
|
|
// }
|
|
// if len(a.ManufacturerData()) > 0 {
|
|
// fmt.Printf(" MD: %v\n", a.ManufacturerData())
|
|
// }
|
|
// fmt.Printf("[%s] %3d:\n", a.Address(), a.RSSI())
|
|
// fmt.Printf("%d %v %v %d\n", index, sd.UUID, sd.Data, len(sd.Data))
|
|
// fmt.Printf("*******************************************\n")
|
|
// mux.Unlock()
|
|
|
|
case sd.UUID.Equal(nestUUID):
|
|
timestamp := time.Now()
|
|
point := influxdb2.NewPointWithMeasurement("sensor")
|
|
point.SetTime(timestamp)
|
|
detector, _ := os.Hostname()
|
|
if detector != "" {
|
|
point.AddTag("detector", detector)
|
|
}
|
|
point.AddTag("address", a.Address().String())
|
|
description := bluetooth.GetDescription(a.Address())
|
|
if description != "" {
|
|
point.AddTag("description", description)
|
|
}
|
|
point.AddField("rssi", a.RSSI())
|
|
writeAPI.WritePoint(point)
|
|
|
|
// mux.Lock()
|
|
// fmt.Printf("*******************************************\n")
|
|
// fmt.Printf("Nest\n")
|
|
// if len(a.LocalName()) > 0 {
|
|
// fmt.Printf(" Name: %s\n", a.LocalName())
|
|
// }
|
|
// if len(a.Services()) > 0 {
|
|
// fmt.Printf(" Svcs: %v\n", a.Services())
|
|
// }
|
|
// if len(a.ManufacturerData()) > 0 {
|
|
// fmt.Printf(" MD: %v\n", a.ManufacturerData())
|
|
// }
|
|
// fmt.Printf("[%s] %3d:\n", a.Address(), a.RSSI())
|
|
// fmt.Printf("%d %v %v %d\n", index, sd.UUID, sd.Data, len(sd.Data))
|
|
// fmt.Printf("*******************************************\n")
|
|
// mux.Unlock()
|
|
|
|
default:
|
|
timestamp := time.Now()
|
|
point := influxdb2.NewPointWithMeasurement("sensor")
|
|
point.SetTime(timestamp)
|
|
point.AddTag("address", a.Address().String())
|
|
description := bluetooth.GetDescription(a.Address())
|
|
if description != "" {
|
|
point.AddTag("description", description)
|
|
}
|
|
point.AddField("rssi", a.RSSI())
|
|
writeAPI.WritePoint(point)
|
|
|
|
mux.Lock()
|
|
fmt.Printf("*******************************************\n")
|
|
fmt.Printf("Unknown\n")
|
|
if len(a.LocalName()) > 0 {
|
|
fmt.Printf(" Name: %s\n", a.LocalName())
|
|
}
|
|
if len(a.Services()) > 0 {
|
|
fmt.Printf(" Svcs: %v\n", a.Services())
|
|
}
|
|
if len(a.ManufacturerData()) > 0 {
|
|
fmt.Printf(" MD: %v\n", a.ManufacturerData())
|
|
}
|
|
fmt.Printf("[%s] %3d:\n", a.Address(), a.RSSI())
|
|
fmt.Printf("%d %v %v %d\n", index, sd.UUID, sd.Data, len(sd.Data))
|
|
fmt.Printf("*******************************************\n")
|
|
mux.Unlock()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func chkErr(err error) {
|
|
switch errors.Cause(err) {
|
|
case nil:
|
|
case context.DeadlineExceeded:
|
|
fmt.Printf("done\n")
|
|
case context.Canceled:
|
|
fmt.Printf("canceled\n")
|
|
default:
|
|
log.Fatalf(err.Error())
|
|
}
|
|
}
|