ble-sensors/cmd/scan.go
2020-08-08 19:00:41 -05:00

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())
}
}