Skip to content
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,17 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: 1.23.0
Comment thread
sethterashima marked this conversation as resolved.
go-version: 1.24.3

- name: No formatting changes
run: |
make format
git diff --exit-code

- name: Setup golangci-lint
uses: golangci/golangci-lint-action@v6
uses: golangci/golangci-lint-action@v7
with:
version: v1.61.0
version: v2.1.5

- name: Linter passes
run: make linters
Expand Down
122 changes: 73 additions & 49 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -1,59 +1,83 @@
---
run:
timeout: 4m

issues:
exclude-dirs:
- temp
exclude:
- "Error return value of `w.Write` is not checked"
- "Error return value of `fmt.Fprintf` is not checked"
- "Error return value of `fmt.Fprintln` is not checked"
- "Error return value of `file.Close` is not checked"
- "Error return value of `os.Setenv` is not checked"
# ECDH code needs to support a Go 1.21 toolchain
- "elliptic.([A-Za-z]+) has been deprecated since Go 1.21: for ECDH"
version: "2"

linters:
enable:
- errcheck
- gofmt
- gosimple
- govet
- misspell
- revive
- unused

linters-settings:
revive:
settings:
revive:
rules:
- name: blank-imports
- name: context-as-argument
- name: context-keys-type
- name: dot-imports
arguments:
- allowedPackages:
- github.com/onsi/ginkgo
- github.com/onsi/ginkgo/v2
- github.com/onsi/gomega
- name: empty-block
- name: error-naming
- name: error-return
- name: error-strings
- name: errorf
- name: increment-decrement
- name: indent-error-flow
- name: package-comments
disabled: true
- name: range
- name: receiver-naming
- name: redefines-builtin-id
- name: superfluous-else
- name: time-naming
- name: unexported-return
- name: unreachable-code
- name: unused-parameter
- name: var-declaration
- name: var-naming
- name: exported

staticcheck:
checks:
- "-QF1008"

exclusions:
generated: lax
presets:
- comments
- common-false-positives
- legacy
- std-error-handling
rules:
- name: blank-imports
- name: context-as-argument
- name: context-keys-type
- name: dot-imports
arguments:
- allowedPackages:
- "github.com/onsi/ginkgo"
- "github.com/onsi/ginkgo/v2"
- "github.com/onsi/gomega"
- name: empty-block
- name: error-naming
- name: error-return
- name: error-strings
- name: errorf
# Uncomment when all issues are fixed
# - name: exported
- name: increment-decrement
- name: indent-error-flow
- name: package-comments
disabled: true
- name: range
- name: receiver-naming
- name: redefines-builtin-id
- name: superfluous-else
- name: time-naming
- name: unexported-return
- name: unreachable-code
- name: unused-parameter
- name: var-declaration
- name: var-naming
- path: (.+)\.go$
text: Error return value of `w.Write` is not checked
- path: (.+)\.go$
text: Error return value of `fmt.Fprintf` is not checked
- path: (.+)\.go$
text: Error return value of `fmt.Fprintln` is not checked
- path: (.+)\.go$
text: Error return value of `file.Close` is not checked
- path: (.+)\.go$
text: Error return value of `os.Setenv` is not checked
- path: (.+)\.go$ # ECDH code needs to support a Go 1.21 toolchain
text: 'elliptic.([A-Za-z]+) has been deprecated since Go 1.21: for ECDH'
paths:
- temp
- third_party$
- builtin$
- examples$

formatters:
enable:
- gofmt
exclusions:
generated: lax
paths:
- temp
- third_party$
- builtin$
- examples$
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
LINTER = golangci-lint run -v $(LINTER_FLAGS) --exclude-use-default=false --timeout $(LINTER_DEADLINE)
LINTER = golangci-lint run -v $(LINTER_FLAGS) --timeout $(LINTER_DEADLINE)
LINTER_DEADLINE = 30s
LINTER_FLAGS ?=

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ curl --cacert cert.pem \
Requirements:

* You've [installed Golang](https://go.dev/doc/install). The package was
tested with Go 1.23.0.
tested with Go 1.24.3.
* You're using macOS or Linux. (Everything except BLE should run on Windows,
but Windows is not officially supported).

Expand Down
12 changes: 6 additions & 6 deletions cmd/tesla-control/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,8 @@ func configureFlags(c *cli.Config, commandName string, forceBLE bool) error {
}

// Verify all required parameters are present.
havePrivateKey := !(c.KeyringKeyName == "" && c.KeyFilename == "")
haveOAuth := !(c.KeyringTokenName == "" && c.TokenFilename == "")
havePrivateKey := c.KeyringKeyName != "" || c.KeyFilename != ""
haveOAuth := c.KeyringTokenName != "" || c.TokenFilename != ""
haveVIN := c.VIN != ""
_, err := checkReadiness(commandName, havePrivateKey, haveOAuth, haveVIN)
return err
Expand Down Expand Up @@ -1052,9 +1052,10 @@ var commands = map[string]*Command{
return errors.New("expected numeric ID")
}
return car.RemoveChargeSchedule(ctx, id)
} else {
return errors.New("missing schedule ID")
}

return errors.New("missing schedule ID")

case "HOME":
home = true
case "WORK":
Expand Down Expand Up @@ -1156,9 +1157,8 @@ var commands = map[string]*Command{
return errors.New("expected numeric ID")
}
return car.RemovePreconditionSchedule(ctx, id)
} else {
return errors.New("missing schedule ID")
}
return errors.New("missing schedule ID")
case "HOME":
home = true
case "WORK":
Expand Down
6 changes: 3 additions & 3 deletions cmd/tesla-control/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (
"github.com/teslamotors/vehicle-command/internal/log"
"github.com/teslamotors/vehicle-command/pkg/account"
"github.com/teslamotors/vehicle-command/pkg/cli"
"github.com/teslamotors/vehicle-command/pkg/connector/ble"
"github.com/teslamotors/vehicle-command/pkg/connector/ble/goble"
"github.com/teslamotors/vehicle-command/pkg/protocol"
"github.com/teslamotors/vehicle-command/pkg/vehicle"
)
Expand Down Expand Up @@ -164,8 +164,8 @@ func main() {

acct, car, err := config.Connect(ctx)
if err != nil {
if ble.IsAdapterError(err) {
writeErr("%s", ble.AdapterErrorHelpMessage(err))
if goble.IsAdapterError(err) {
writeErr("%s", goble.AdapterErrorHelpMessage(err))
} else {
writeErr("Error: %s", err)
}
Expand Down
32 changes: 22 additions & 10 deletions examples/ble/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import (
debugger "github.com/teslamotors/vehicle-command/internal/log"

"github.com/teslamotors/vehicle-command/pkg/connector/ble"
"github.com/teslamotors/vehicle-command/pkg/connector/ble/goble"
"github.com/teslamotors/vehicle-command/pkg/connector/ble/tinygo"
"github.com/teslamotors/vehicle-command/pkg/protocol"
"github.com/teslamotors/vehicle-command/pkg/vehicle"
)
Expand All @@ -23,6 +25,7 @@ func main() {
logger := log.New(os.Stderr, "", 0)
status := 1
debug := false
useTinyGo := false
defer func() {
os.Exit(status)
}()
Expand All @@ -38,6 +41,7 @@ func main() {
flag.StringVar(&privateKeyFile, "key", "", "Private key `file` for authorizing commands (PEM PKCS8 NIST-P256)")
flag.StringVar(&vin, "vin", "", "Vehicle Identification Number (`VIN`) of the car")
flag.BoolVar(&debug, "debug", false, "Enable debugging of TX/RX BLE packets")
flag.BoolVar(&useTinyGo, "tinygo", false, "Use tinygo ble impl (go-ble is the default")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use tinygo BLE implementation instead of go-ble

if runtime.GOOS == "linux" {
flag.StringVar(&btAdapter, "bt-adapter", "", "Optional ID of Bluetooth adapter to use")
}
Expand All @@ -48,13 +52,21 @@ func main() {
debugger.SetLevel(debugger.LevelDebug)
}

err := ble.InitAdapterWithID(btAdapter)
if err != nil {
if ble.IsAdapterError(err) {
logger.Print(ble.AdapterErrorHelpMessage(err))
} else {
logger.Printf("Failed to initialize BLE adapter: %s", err)
var adapter ble.Adapter
var err error

if useTinyGo {
adapter, err = tinygo.NewAdapter(btAdapter)
} else {
adapter, err = goble.NewAdapter(btAdapter)
if err != nil && goble.IsAdapterError(err) {
logger.Print(goble.AdapterErrorHelpMessage(err))
return
}
}

if err != nil {
logger.Printf("Failed to initialize BLE adapter: %s", err)
return
}

Expand All @@ -68,7 +80,7 @@ func main() {
defer cancel()
doneChan := make(chan struct{})
go func() {
_, err := ble.ScanVehicleBeacon(ctx, vin)
_, err := ble.ScanVehicleBeacon(ctx, vin, adapter)
if err != nil && ctx.Err() == nil {
logger.Printf("Scan failed: %s", err)
} else if ctx.Err() == nil {
Expand Down Expand Up @@ -105,14 +117,14 @@ func main() {
}
}

scan, err := ble.ScanVehicleBeacon(ctx, vin)
beacon, err := ble.ScanVehicleBeacon(ctx, vin, adapter)
if err != nil {
logger.Println(err)
return
}
logger.Printf("Found vehicle: %s (%s) %ddBm", scan.LocalName, scan.Address, scan.RSSI)
logger.Printf("Found vehicle: %s (%s) %ddBm", beacon.LocalName, beacon.Address, beacon.RSSI)

conn, err := ble.NewConnectionFromScanResult(ctx, vin, scan)
conn, err := ble.NewConnectionFromBeacon(ctx, vin, beacon, adapter)
if err != nil {
logger.Printf("Failed to connect to vehicle: %s", err)
return
Expand Down
40 changes: 22 additions & 18 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,35 +1,39 @@
module github.com/teslamotors/vehicle-command

go 1.23.0
go 1.24

require (
github.com/99designs/keyring v1.2.2
github.com/cronokirby/saferith v0.33.0
github.com/go-ble/ble v0.0.0-20240122180141-8c5522f54333
github.com/golang-jwt/jwt/v5 v5.2.2
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
golang.org/x/term v0.5.0
google.golang.org/protobuf v1.34.2
github.com/zlymeda/go-ble v0.0.0-20250503163836-ac689226ee0c
golang.org/x/term v0.32.0
google.golang.org/protobuf v1.36.6
tinygo.org/x/bluetooth v0.11.1-0.20250505124847-38847b0d22b1
)

require (
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect
github.com/JuulLabs-OSS/cbgo v0.0.1 // indirect
github.com/danieljoos/wincred v1.2.0 // indirect
github.com/dvsekhvalnov/jose2go v1.6.0 // indirect
github.com/danieljoos/wincred v1.2.2 // indirect
github.com/dvsekhvalnov/jose2go v1.8.0 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect
github.com/google/go-cmp v0.5.8 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect
github.com/konsorten/go-windows-terminal-sequences v1.0.1 // indirect
github.com/mattn/go-colorable v0.1.6 // indirect
github.com/mattn/go-isatty v0.0.12 // indirect
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
github.com/mgutz/logxi v0.0.0-20161027140823-aebf8a7d67ab // indirect
github.com/mtibben/percent v0.2.1 // indirect
github.com/pkg/errors v0.8.1 // indirect
github.com/raff/goble v0.0.0-20190909174656-72afc67d6a99 // indirect
github.com/sirupsen/logrus v1.5.0 // indirect
golang.org/x/sys v0.8.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/raff/goble v0.0.0-20200327175727-d63360dcfd80 // indirect
github.com/saltosystems/winrt-go v0.0.0-20241223121953-98e32661f6ff // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/soypat/cyw43439 v0.0.0-20250505012923-830110c8f4af // indirect
github.com/soypat/seqs v0.0.0-20250124201400-0d65bc7c1710 // indirect
github.com/tinygo-org/cbgo v0.0.4 // indirect
github.com/tinygo-org/pio v0.2.0 // indirect
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 // indirect
golang.org/x/sys v0.33.0 // indirect
)

replace github.com/JuulLabs-OSS/cbgo => github.com/tinygo-org/cbgo v0.0.4
Loading