Ability to pick tinygo vs go-ble impl#400
Conversation
pkg/connector/ble/goble/ble.go
Outdated
| ) | ||
|
|
||
| func init() { | ||
| iface.RegisterAdapter(adapter{}) |
There was a problem hiding this comment.
There is no way to register this (or bluez) adapter after the fact, meaning a decision to use one or another during runtime would currently be impossible. Maybe you can add a "UseAdapter" function, or make the adapter public.
There was a problem hiding this comment.
Also, maybe we can use go-ble by default - if impl is nil during InitAdapter call, load go-ble adapter.
There was a problem hiding this comment.
ok, switched it up a bit.
- moved some types to iface subpackage to prevent circular imports
- top-level ble pkg is now more like a facade and for registering the adapters
- go-ble is now default, no need for naked imports
There was a problem hiding this comment.
also updated the description, as the breaking change is now gone, I used aliases to resolve that
| // [MessageForVehicle]. | ||
| // | ||
| // The function overwrites the audience ("aud") and issuer ("iss") JWT claims. | ||
| func SignMessageForFleet(privateKey authentication.ECDHPrivateKey, app string, message jwt.MapClaims) (string, error) { |
There was a problem hiding this comment.
Please avoid unnecessary breaking API changes
There was a problem hiding this comment.
will revert and disable linter rule
There was a problem hiding this comment.
An anti-stutter linter rule would be nice, since it's a common slip. Is there a way to disable the rule for these specific functions?
| if sk.D.Cmp(elliptic.P256().Params().N) >= 0 { | ||
| return nil | ||
| } | ||
| x, y := sk.PublicKey.Curve.ScalarBaseMult(privateScalar) |
There was a problem hiding this comment.
Are these changes required by the Go uprev? The authentication package is used internally and would ideally stay compatible with other Go versions.
There was a problem hiding this comment.
this changed was "forced" by the linter. alternatively we can turn off that rule. it was some
QF1008: could remove embedded field "PublicKey" from selector (staticcheck)
x, y := sk.PublicKey.Curve.ScalarBaseMult(privateScalar)
^
let me know if you'd rather disable that rule
pkg/connector/ble/iface/adapter.go
Outdated
| @@ -0,0 +1,14 @@ | |||
| package iface | |||
There was a problem hiding this comment.
To me it seems more natural to put the shared code in pkg/connector/ble rather than a separate iface directory. Any objections to moving it back?
There was a problem hiding this comment.
...also would limit API breakage.
There was a problem hiding this comment.
yes I had it like that first. @Lenart12 suggested using go-ble as a default, but the problem was cyclic import.
eg. go-ble wants to use ScanResult from pkg/connector/ble and pkg/connector/ble wanted to set go-ble as a default impl.
I am using this as a library and I didn't notice any breaking change. I was able to compile without a change.
I can move it back, but then library user will have to pick the impl
| blockLength = len(out) | ||
| } | ||
|
|
||
| if err := c.writer.WriteCharacteristic(out[:blockLength], blockLength); err != nil { |
There was a problem hiding this comment.
The context should be passed on to the writer.
| ) | ||
|
|
||
| type Writer interface { | ||
| WriteCharacteristic(bytes []byte, length int) error |
There was a problem hiding this comment.
Why a separate length argument?
| ) | ||
|
|
||
| type Writer interface { | ||
| WriteCharacteristic(bytes []byte, length int) error |
There was a problem hiding this comment.
This creates a bit of a hacky almost circular dependency. I think it would be cleaner to have the interface expose methods for for both reading (or exposing a channel for reading packets) and writing; the implmentation should be self-contained.
There was a problem hiding this comment.
I will try to re-think this. first step was to separate it out, but now I got more familiar with both versions, I will try to make it better
…and fix issues found by the linter
…oving some types to iface to prevent circular dependencies, top-level ble pkg is more like a facade
26d4324 to
7ef178c
Compare
|
finally had some time to work on this. pls take a look and let me know, I ran few basic tests, but will test more in upcoming days |
pkg/cache/example_test.go
Outdated
| import ( | ||
| "context" | ||
| "fmt" | ||
| "github.com/teslamotors/vehicle-command/pkg/connector/ble/goble" |
There was a problem hiding this comment.
Nit: group with other local imports
pkg/cli/config.go
Outdated
| "errors" | ||
| "flag" | ||
| "fmt" | ||
| "github.com/teslamotors/vehicle-command/pkg/connector/ble" |
There was a problem hiding this comment.
Group with other local imports
pkg/cli/config.go
Outdated
| flag.StringVar(&c.Backend.FileDir, "keyring-file-dir", keyringDirectory, "keyring `directory` for file-backed keyring types") | ||
| flag.BoolVar(&c.Debug, "keyring-debug", false, "Enable keyring debug logging") | ||
| } | ||
| if c.Flags.isSet(FlagBLE) && c.Flags.isSet(FlagVIN) { |
There was a problem hiding this comment.
I don't think we'd ever require FlagBLE without FlagVIN, but why is FlagVIN made explicitly required here?
There was a problem hiding this comment.
ok, I can remove it
pkg/cli/config.go
Outdated
| flag.BoolVar(&c.Debug, "keyring-debug", false, "Enable keyring debug logging") | ||
| } | ||
| if c.Flags.isSet(FlagBLE) && c.Flags.isSet(FlagVIN) { | ||
| flag.BoolVar(&c.BtTinyGo, "tinygo", false, "Use tinygo ble impl (go-ble is the default.") |
There was a problem hiding this comment.
God help us if we end up needing more than two adapter implementations, but thoughts on bool vs string here?
There was a problem hiding this comment.
updated to use enum
|
|
||
| "github.com/teslamotors/vehicle-command/pkg/connector/ble" | ||
| "github.com/teslamotors/vehicle-command/pkg/protocol" | ||
| goble "github.com/zlymeda/go-ble" |
There was a problem hiding this comment.
- Why change to a fork?
- This specific fork uses tinygo, so why use both this and tinygo directly?
There was a problem hiding this comment.
- I wrote it in the description:
forked go-ble to zlymeda/go-ble see go-ble/ble@master...zlymeda:go-ble:master
- replaced github.com/JuulLabs-OSS/cbgo with github.com/tinygo-org/cbgo
- merged fix Resolve blocking channel
- merged fix use RxMtu() for long read
added updated go + deps
- that fork does not use tinygo, it uses only cbgo part of tinygo (which is for MacOS), same as this repo did using the replace
replace github.com/JuulLabs-OSS/cbgo => github.com/tinygo-org/cbgo v0.0.4
without that I was getting issues (using the replace + using tinygo), it resulted in an error:
go mod tidy
go: github.com/tinygo-org/cbgo@v0.0.4 used for two different module paths (github.com/JuulLabs-OSS/cbgo and github.com/tinygo-org/cbgo)
so in order to fix that I "moved" the replace directly into the fork
There was a problem hiding this comment.
is there anything else I can do? did I answer all the questions? pls let me know
|
examples/ble/main.go
Outdated
| 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") |
There was a problem hiding this comment.
Use tinygo BLE implementation instead of go-ble
pkg/cli/config.go
Outdated
| flag.BoolVar(&c.Debug, "keyring-debug", false, "Enable keyring debug logging") | ||
| } | ||
| if c.Flags.isSet(FlagBLE) { | ||
| flag.Var(&c.BtImpl, "bt-impl", "ble impl to use: goble/tinygo") |
There was a problem hiding this comment.
BLE implementation to use. Allowed values are "tinygo" and "goble" (default).
this should be fixed now |
|
On MacOS, using On an ubuntu system, both BT implementations work, but When I tried to reprodce the above, I got this error spammed. So in addition to the error itself, there's the secondary issue of writing to stderr in a pretty tight loop: |
|
Hi, the tight loop comes from here:
for {
conn, err := tryToConnect(ctx, vin, beacon, adapter)
if err == nil {
return conn, nil
}
log.Warning("BLE connection attempt failed: %+v", err)
if err := ctx.Err(); err != nil {
if lastError != nil {
return nil, lastError
}
return nil, err
}
lastError = err
}maybe we could add small sleep like 100ms between tries? I dont have any MacOS device, so I can't really debug the issue. Is there more relevant logs? I also have ubuntu and when trying to get the climate state, I dont have any significant delay: The issue with "BLE connection attempt failed: Method "Get" with signature "ss" on interface "org.freedesktop.DBus.Properties" doesn't exist" I am using both tinygo and goble for my automations and both are running relatively without problems. One is on raspberry pi 3 running debian, another is a HP mini PC also running debian. |
Description
Resurrecting the work done in this MR: #373
Having 2 implementations for ble. go-ble and tinygo or another custom impl
Also forked go-ble to https://github.com/zlymeda/go-ble see go-ble/ble@master...zlymeda:go-ble:master
I can only test on linux, so if someone can test on MacOs as well as Windows (using tinygo) that'd be great.
I compiled tesla-control and used both tinygo and go-ble. I was able to control my tesla using both (on llinux).
Type of change
Breaking changes
The ble package now needs and adapter implementation.
Checklist:
Confirm you have completed the following steps: