Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cache scan results. #554

Open
wants to merge 3 commits into
base: floitsch/ble.40.add-endpoints
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
93 changes: 87 additions & 6 deletions cmd/jag/commands/device.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ import (
"fmt"
"io"
"os"
"path/filepath"
"strconv"
"time"
"unicode/utf8"

"github.com/spf13/viper"
"github.com/toitlang/jaguar/cmd/jag/directory"
"gopkg.in/yaml.v2"
)

const (
Expand Down Expand Up @@ -75,6 +77,55 @@ func readDeviceConfig(cfg *viper.Viper) (Device, error) {
}
}

func readYamlDevices(path string) ([]Device, error) {
data, err := os.ReadFile(path)
if err != nil {
return nil, err
}
var serializable []map[string]interface{}
if err := yaml.Unmarshal(data, &serializable); err != nil {
return nil, err
}
var devices []Device
for _, m := range serializable {
if kind, ok := m["kind"].(string); ok {
switch kind {
case "ble":
d, err := NewDeviceBleFromJson(m, "")
if err != nil {
return nil, err
}
devices = append(devices, d)
case "network":
d, err := NewDeviceNetworkFromJson(m)
if err != nil {
return nil, err
}
devices = append(devices, d)
default:
return nil, fmt.Errorf("unknown device kind: %s", kind)
}
}
}
return devices, nil
}

func writeYamlDevices(path string, devices []Device) error {
var serializable []interface{}
for _, d := range devices {
serializable = append(serializable, d.ToSerializable())
}
data, err := yaml.Marshal(serializable)
if err != nil {
return err
}
// Create the directory if it doesn't exist.
if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
return err
}
return os.WriteFile(path, data, 0644)
}

type Devices struct {
Devices []Device
}
Expand Down Expand Up @@ -172,15 +223,18 @@ func GetDevice(ctx context.Context, sdk *SDK, checkPing bool, deviceSelect devic
if err != nil {
return nil, err
}
manualPick := deviceSelect != nil
if deviceCfg.IsSet("device") && !manualPick {

// Set the manualPick flag before we potentially change the 'deviceSelect' after looking
// at the device-config file.
// In other words: allow to manually pick a device if the device-selection was not set,
// or comes from the device-config file.
manualPick := deviceSelect == nil

if deviceCfg.IsSet("device") && deviceSelect == nil {
d, err := readDeviceConfig(deviceCfg)
if err != nil {
return nil, err
}
if err != nil {
return nil, err
}
if checkPing {
if d.Ping(ctx, sdk) {
return d, nil
Expand All @@ -192,11 +246,38 @@ func GetDevice(ctx context.Context, sdk *SDK, checkPing bool, deviceSelect devic
}
}

if deviceSelect != nil {
// Try to find the device in the cached scan if there is one.
scanCache, err := directory.GetScanCachePath()
if err != nil {
return nil, err
}
if _, err := os.Stat(scanCache); err == nil {
devices, err := readYamlDevices(scanCache)
if err == nil {
// We ignore errors, and just handle it as if there wasn't any scan cache.
for _, d := range devices {
if deviceSelect.Match(d) {
if checkPing {
if d.Ping(ctx, sdk) {
return d, nil
}
fmt.Printf("Failed to ping '%s'.\n", d.Name())
} else {
return d, nil
}
}
}
}
}
}

d, autoSelected, err := scanAndPickDevice(ctx, 0*time.Second, scanPort, deviceSelect, manualPick)
if err != nil {
return nil, err
}
if !manualPick {
if manualPick {
// The user was allowed to manually pick a device.
if autoSelected {
fmt.Printf("Found device '%s' again\n", d.Name())
}
Expand Down
13 changes: 11 additions & 2 deletions cmd/jag/commands/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func ScanCmd() *cobra.Command {
return outputter.Encode(Devices{devices})
}

device, _, err := scanAndPickDevice(ctx, timeout, port, autoSelect, false)
device, _, err := scanAndPickDevice(ctx, timeout, port, autoSelect, true)
if err != nil {
return err
}
Expand Down Expand Up @@ -230,6 +230,15 @@ func scan(ctx context.Context, scanTimeout time.Duration, port uint, autoSelect
devices = append(devices, bleDevices...)
}

scanCachePath, err := directory.GetScanCachePath()
if err != nil {
return nil, err
}
err = writeYamlDevices(scanCachePath, devices)
if err != nil {
fmt.Printf("Failed to write scan cache: %v\n", err)
}

return devices, nil
}

Expand All @@ -245,7 +254,7 @@ func scanAndPickDevice(ctx context.Context, scanTimeout time.Duration, port uint
return d, true, nil
}
}
if manualPick {
if !manualPick {
return nil, false, fmt.Errorf("couldn't find %s", autoSelect)
}
}
Expand Down
15 changes: 15 additions & 0 deletions cmd/jag/directory/directory.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const (
UserConfigPathEnv = "JAG_USER_CONFIG_PATH"
DeviceConfigPathEnv = "JAG_DEVICE_CONFIG_PATH"
SnapshotCachePathEnv = "JAG_SNAPSHOT_CACHE_PATH"
ScanCachePathEnv = "JAG_SCAN_CACHE_PATH"
configFile = ".jaguar"

ToitUserConfigPathEnv = "TOIT_CONFIG_FILE"
Expand Down Expand Up @@ -105,6 +106,20 @@ func GetDeviceConfigPath() (string, error) {
return filepath.Join(configDir, "jaguar", "device.yaml"), nil
}

func GetScanCachePath() (string, error) {
path, ok := os.LookupEnv(ScanCachePathEnv)
if ok {
return path, nil
}

cacheDir, err := getCacheDirPath()
if err != nil {
return "", err
}

return filepath.Join(cacheDir, "jaguar", "scan.yaml"), nil
}

func GetSnapshotsPaths() ([]string, error) {
paths := []string{}
path, ok := os.LookupEnv(SnapshotCachePathEnv)
Expand Down