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