ble-sensors/cmd/scan.go
Jeffrey C. Ollie 523a561015
Some checks failed
continuous-integration/drone/push Build is failing
much work
2020-08-13 00:13:15 -05:00

161 lines
5 KiB
Go

package cmd
import (
"context"
"os"
"time"
"git.ocjtech.us/jeff/ble-sensors/lib/bluetooth"
cleargrass "git.ocjtech.us/jeff/ble-sensors/lib/cleargrass"
xiaomi_mijia "git.ocjtech.us/jeff/ble-sensors/lib/xiaomi/mijia"
xiaomi_scale "git.ocjtech.us/jeff/ble-sensors/lib/xiaomi/scale"
"github.com/go-ble/ble"
"github.com/go-ble/ble/linux"
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"
"go.uber.org/zap"
)
// 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.:
}
var client influxdb2.Client
var writeAPI influxdb2_api.WriteAPI
func listen(cmd *cobra.Command, args []string) {
logger.Debug("starting up")
d, err := linux.NewDevice(ble.OptDeviceID(0))
if err != nil {
logger.Fatal("can't get new device",
zap.String("error", err.Error()))
}
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(logger, d.Scan(ctx, true, advHandler))
writeAPI.Flush()
client.Close()
logger.Sync()
}
var tileUUID ble.UUID = []byte{0xed, 0xfe}
var nestUUID ble.UUID = []byte{0xaf, 0xfe}
var detector, _ = os.Hostname()
func advHandler(advertisement ble.Advertisement) {
timestamp := time.Now()
description := bluetooth.GetDescription(advertisement.Addr())
point := influxdb2.NewPointWithMeasurement("sensor")
point.SetTime(timestamp)
if detector != "" {
point.AddTag("detector", detector)
}
point.AddTag("address", advertisement.Addr().String())
if description != "" {
point.AddTag("description", description)
}
point.AddTag("measurement", "rssi")
point.AddTag("measurement_unit", "dBm")
point.AddField("value", advertisement.RSSI())
writeAPI.WritePoint(point)
logger.Debug("sending sensor reading",
zap.String("source", advertisement.Addr().String()),
zap.String("description", description),
zap.String("measurement", "rssi"),
zap.String("measurement_unit", "dBm"),
zap.Int("value", advertisement.RSSI()))
if len(advertisement.ServiceData()) > 0 {
for index, sd := range advertisement.ServiceData() {
switch {
case sd.UUID.Equal(xiaomi_scale.XiaomiScaleV1UUID):
xiaomi_scale.ParseXiaomiScaleV1(&writeAPI, logger, timestamp, detector, description, advertisement, index, sd)
case sd.UUID.Equal(xiaomi_scale.XiaomiScaleV2UUID):
xiaomi_scale.ParseXiaomiScaleV2(&writeAPI, logger, timestamp, detector, description, advertisement, index, sd)
case sd.UUID.Equal(xiaomi_mijia.XiaomiMijiaHTV1UUID):
xiaomi_mijia.ParseXiaomiMijiaSensorData(&writeAPI, logger, timestamp, detector, description, advertisement, index, sd)
case sd.UUID.Equal(cleargrass.CleargrassUUID):
cleargrass.ParseCleargrassSensorData(&writeAPI, logger, timestamp, detector, description, advertisement, index, sd)
case sd.UUID.Equal(tileUUID):
logger.Debug("ignoring tile ble advertisement",
zap.String("source", advertisement.Addr().String()),
zap.String("description", description),
zap.String("name", advertisement.LocalName()),
zap.String("uuid", sd.UUID.String()))
case sd.UUID.Equal(nestUUID):
logger.Debug("ignoring nest ble advertisement",
zap.String("source", advertisement.Addr().String()),
zap.String("description", description),
zap.String("name", advertisement.LocalName()),
zap.String("uuid", sd.UUID.String()))
default:
logger.Info("unknown service data type",
zap.String("source", advertisement.Addr().String()),
zap.String("description", description),
zap.String("name", advertisement.LocalName()),
zap.String("uuid", sd.UUID.String()),
zap.Binary("data", sd.Data))
}
}
}
}
func chkErr(logger *zap.Logger, err error) {
logger.Debug("chkErr")
switch errors.Cause(err) {
case nil:
case context.DeadlineExceeded:
logger.Debug("done")
case context.Canceled:
logger.Debug("canceled")
default:
logger.Fatal("error",
zap.String("error", err.Error()))
}
}