Compare commits
17 Commits
v0.0.1
...
0721b7f9d4
| Author | SHA1 | Date | |
|---|---|---|---|
| 0721b7f9d4 | |||
| b7bd385c43 | |||
| cbcefb149e | |||
| cb8d207249 | |||
| 7786ea1d58 | |||
| 6e16aa7a7a | |||
| 91f7132d5e | |||
| b186f77bea | |||
| adb297c6dd | |||
| b4992cb393 | |||
| a5490b8364 | |||
| 44d1f5552b | |||
| 5e34f656b3 | |||
| 560d19860e | |||
| ea1a7fa9f4 | |||
| 81fe634ed8 | |||
| 281e1dcbac |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1,3 @@
|
|||||||
/itctl
|
/itctl
|
||||||
/itd
|
/itd
|
||||||
|
/itgui
|
||||||
14
Makefile
14
Makefile
@@ -7,14 +7,20 @@ all:
|
|||||||
go build $(GOFLAGS)
|
go build $(GOFLAGS)
|
||||||
go build ./cmd/itctl $(GOFLAGS)
|
go build ./cmd/itctl $(GOFLAGS)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f itctl
|
||||||
|
rm -f itd
|
||||||
|
|
||||||
install:
|
install:
|
||||||
install -Dm755 ./itd $(BIN_PREFIX)/itd
|
install -Dm755 ./itd $(BIN_PREFIX)/itd
|
||||||
install -Dm755 ./itctl $(BIN_PREFIX)/itctl
|
install -Dm755 ./itctl $(BIN_PREFIX)/itctl
|
||||||
install -Dm644 ./itd.service $(SERVICE_PREFIX)/itd.service
|
install -Dm644 ./itd.service $(SERVICE_PREFIX)/itd.service
|
||||||
install -Dm644 ./itd.toml $(CFG_PREFIX)/itd.toml
|
install -Dm644 ./itd.toml $(CFG_PREFIX)/itd.toml
|
||||||
|
|
||||||
clean:
|
uninstall:
|
||||||
rm -f itctl
|
rm $(BIN_PREFIX)/itd
|
||||||
rm -f itd
|
rm $(BIN_PREFIX)/itctl
|
||||||
|
rm $(SERVICE_PREFIX)/itd.service
|
||||||
|
rm $(CFG_PREFIX)/itd.toml
|
||||||
|
|
||||||
.PHONY: all install clean
|
.PHONY: all clean install uninstall
|
||||||
22
README.md
22
README.md
@@ -3,6 +3,10 @@
|
|||||||
|
|
||||||
`itd` is a daemon that uses my infinitime [library](https://go.arsenm.dev/infinitime) to interact with the [PineTime](https://www.pine64.org/pinetime/) running [InfiniTime](https://infinitime.io).
|
`itd` is a daemon that uses my infinitime [library](https://go.arsenm.dev/infinitime) to interact with the [PineTime](https://www.pine64.org/pinetime/) running [InfiniTime](https://infinitime.io).
|
||||||
|
|
||||||
|
[](https://ci.appveyor.com/project/moussaelianarsen/itd)
|
||||||
|
[](https://minio.arsenm.dev/minio/itd/)
|
||||||
|
[](https://aur.archlinux.org/packages/itd-git/)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
@@ -56,6 +60,24 @@ Flags:
|
|||||||
|
|
||||||
Use "itctl [command] --help" for more information about a command.
|
Use "itctl [command] --help" for more information about a command.
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Interactive mode
|
||||||
|
|
||||||
|
Running `itctl` by itself will open interactive mode. It's essentially a shell where you can enter commands. For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ itctl
|
||||||
|
itctl> fw ver
|
||||||
|
1.3.0
|
||||||
|
itctl> get batt
|
||||||
|
81%
|
||||||
|
itctl> get heart
|
||||||
|
92 BPM
|
||||||
|
itctl> set time 2021-08-22T00:06:18-07:00
|
||||||
|
itctl> set time now
|
||||||
|
itctl> exit
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Installation
|
### Installation
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import (
|
|||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/spf13/viper"
|
||||||
"go.arsenm.dev/itd/internal/types"
|
"go.arsenm.dev/itd/internal/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -36,7 +37,7 @@ var addressCmd = &cobra.Command{
|
|||||||
Short: "Get InfiniTime's bluetooth address",
|
Short: "Get InfiniTime's bluetooth address",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
// Connect to itd UNIX socket
|
// Connect to itd UNIX socket
|
||||||
conn, err := net.Dial("unix", SockPath)
|
conn, err := net.Dial("unix", viper.GetString("sockPath"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal().Err(err).Msg("Error dialing socket. Is itd running?")
|
log.Fatal().Err(err).Msg("Error dialing socket. Is itd running?")
|
||||||
}
|
}
|
||||||
@@ -44,7 +45,7 @@ var addressCmd = &cobra.Command{
|
|||||||
|
|
||||||
// Encode request into connection
|
// Encode request into connection
|
||||||
err = json.NewEncoder(conn).Encode(types.Request{
|
err = json.NewEncoder(conn).Encode(types.Request{
|
||||||
Type: ReqTypeBtAddress,
|
Type: types.ReqTypeBtAddress,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal().Err(err).Msg("Error making request")
|
log.Fatal().Err(err).Msg("Error making request")
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import (
|
|||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/spf13/viper"
|
||||||
"go.arsenm.dev/itd/internal/types"
|
"go.arsenm.dev/itd/internal/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -36,7 +37,7 @@ var batteryCmd = &cobra.Command{
|
|||||||
Short: "Get battery level from InfiniTime",
|
Short: "Get battery level from InfiniTime",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
// Connect to itd UNIX socket
|
// Connect to itd UNIX socket
|
||||||
conn, err := net.Dial("unix", SockPath)
|
conn, err := net.Dial("unix", viper.GetString("sockPath"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal().Err(err).Msg("Error dialing socket. Is itd running?")
|
log.Fatal().Err(err).Msg("Error dialing socket. Is itd running?")
|
||||||
}
|
}
|
||||||
@@ -44,7 +45,7 @@ var batteryCmd = &cobra.Command{
|
|||||||
|
|
||||||
// Encode request into connection
|
// Encode request into connection
|
||||||
err = json.NewEncoder(conn).Encode(types.Request{
|
err = json.NewEncoder(conn).Encode(types.Request{
|
||||||
Type: ReqTypeBattLevel,
|
Type: types.ReqTypeBattLevel,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal().Err(err).Msg("Error making request")
|
log.Fatal().Err(err).Msg("Error making request")
|
||||||
|
|||||||
@@ -18,23 +18,6 @@
|
|||||||
|
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
const SockPath = "/tmp/itd/socket"
|
|
||||||
|
|
||||||
const (
|
|
||||||
ReqTypeHeartRate = "hrt"
|
|
||||||
ReqTypeBattLevel = "battlvl"
|
|
||||||
ReqTypeFwVersion = "fwver"
|
|
||||||
ReqTypeFwUpgrade = "fwupg"
|
|
||||||
ReqTypeBtAddress = "btaddr"
|
|
||||||
ReqTypeNotify = "notify"
|
|
||||||
ReqTypeSetTime = "settime"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
UpgradeTypeArchive = iota
|
|
||||||
UpgradeTypeFiles
|
|
||||||
)
|
|
||||||
|
|
||||||
type DFUProgress struct {
|
type DFUProgress struct {
|
||||||
Received int64 `mapstructure:"recvd"`
|
Received int64 `mapstructure:"recvd"`
|
||||||
Total int64 `mapstructure:"total"`
|
Total int64 `mapstructure:"total"`
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import (
|
|||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/spf13/viper"
|
||||||
"go.arsenm.dev/itd/internal/types"
|
"go.arsenm.dev/itd/internal/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -35,7 +36,7 @@ var heartCmd = &cobra.Command{
|
|||||||
Short: "Get heart rate from InfiniTime",
|
Short: "Get heart rate from InfiniTime",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
// Connect to itd UNIX socket
|
// Connect to itd UNIX socket
|
||||||
conn, err := net.Dial("unix", SockPath)
|
conn, err := net.Dial("unix", viper.GetString("sockPath"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal().Err(err).Msg("Error dialing socket. Is itd running?")
|
log.Fatal().Err(err).Msg("Error dialing socket. Is itd running?")
|
||||||
}
|
}
|
||||||
@@ -43,7 +44,7 @@ var heartCmd = &cobra.Command{
|
|||||||
|
|
||||||
// Encode request into connection
|
// Encode request into connection
|
||||||
err = json.NewEncoder(conn).Encode(types.Request{
|
err = json.NewEncoder(conn).Encode(types.Request{
|
||||||
Type: ReqTypeHeartRate,
|
Type: types.ReqTypeHeartRate,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal().Err(err).Msg("Error making request")
|
log.Fatal().Err(err).Msg("Error making request")
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import (
|
|||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/spf13/viper"
|
||||||
"go.arsenm.dev/itd/internal/types"
|
"go.arsenm.dev/itd/internal/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -40,7 +41,7 @@ var notifyCmd = &cobra.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Connect to itd UNIX socket
|
// Connect to itd UNIX socket
|
||||||
conn, err := net.Dial("unix", SockPath)
|
conn, err := net.Dial("unix", viper.GetString("sockPath"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal().Err(err).Msg("Error dialing socket. Is itd running?")
|
log.Fatal().Err(err).Msg("Error dialing socket. Is itd running?")
|
||||||
}
|
}
|
||||||
@@ -48,7 +49,7 @@ var notifyCmd = &cobra.Command{
|
|||||||
|
|
||||||
// Encode request into connection
|
// Encode request into connection
|
||||||
err = json.NewEncoder(conn).Encode(types.Request{
|
err = json.NewEncoder(conn).Encode(types.Request{
|
||||||
Type: ReqTypeNotify,
|
Type: types.ReqTypeNotify,
|
||||||
Data: types.ReqDataNotify{
|
Data: types.ReqDataNotify{
|
||||||
Title: args[0],
|
Title: args[0],
|
||||||
Body: args[1],
|
Body: args[1],
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"github.com/abiosoft/ishell"
|
"github.com/abiosoft/ishell"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
// rootCmd represents the base command when called without any subcommands
|
// rootCmd represents the base command when called without any subcommands
|
||||||
@@ -60,5 +61,18 @@ var rootCmd = &cobra.Command{
|
|||||||
// Execute adds all child commands to the root command and sets flags appropriately.
|
// Execute adds all child commands to the root command and sets flags appropriately.
|
||||||
// This is called by main.main(). It only needs to happen once to the rootCmd.
|
// This is called by main.main(). It only needs to happen once to the rootCmd.
|
||||||
func Execute() {
|
func Execute() {
|
||||||
|
rootCmd.CompletionOptions.DisableDefaultCmd = true
|
||||||
cobra.CheckErr(rootCmd.Execute())
|
cobra.CheckErr(rootCmd.Execute())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// Register flag for socket path
|
||||||
|
rootCmd.Flags().StringP("socket-path", "s", "", "Path to itd socket")
|
||||||
|
|
||||||
|
// Bind flag and environment variable to viper key
|
||||||
|
viper.BindPFlag("sockPath", rootCmd.Flags().Lookup("socket-path"))
|
||||||
|
viper.BindEnv("sockPath", "ITCTL_SOCKET_PATH")
|
||||||
|
|
||||||
|
// Set default value for socket path
|
||||||
|
viper.SetDefault("sockPath", "/tmp/itd/socket")
|
||||||
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import (
|
|||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/spf13/viper"
|
||||||
"go.arsenm.dev/itd/internal/types"
|
"go.arsenm.dev/itd/internal/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -41,7 +42,7 @@ var timeCmd = &cobra.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Connect to itd UNIX socket
|
// Connect to itd UNIX socket
|
||||||
conn, err := net.Dial("unix", SockPath)
|
conn, err := net.Dial("unix", viper.GetString("sockPath"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal().Err(err).Msg("Error dialing socket. Is itd running?")
|
log.Fatal().Err(err).Msg("Error dialing socket. Is itd running?")
|
||||||
}
|
}
|
||||||
@@ -49,7 +50,7 @@ var timeCmd = &cobra.Command{
|
|||||||
|
|
||||||
// Encode request into connection
|
// Encode request into connection
|
||||||
err = json.NewEncoder(conn).Encode(types.Request{
|
err = json.NewEncoder(conn).Encode(types.Request{
|
||||||
Type: ReqTypeSetTime,
|
Type: types.ReqTypeSetTime,
|
||||||
Data: args[0],
|
Data: args[0],
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ var upgradeCmd = &cobra.Command{
|
|||||||
Aliases: []string{"upg"},
|
Aliases: []string{"upg"},
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
// Connect to itd UNIX socket
|
// Connect to itd UNIX socket
|
||||||
conn, err := net.Dial("unix", SockPath)
|
conn, err := net.Dial("unix", viper.GetString("sockPath"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal().Err(err).Msg("Error dialing socket. Is itd running?")
|
log.Fatal().Err(err).Msg("Error dialing socket. Is itd running?")
|
||||||
}
|
}
|
||||||
@@ -49,13 +49,13 @@ var upgradeCmd = &cobra.Command{
|
|||||||
if viper.GetString("archive") != "" {
|
if viper.GetString("archive") != "" {
|
||||||
// Get archive data struct
|
// Get archive data struct
|
||||||
data = types.ReqDataFwUpgrade{
|
data = types.ReqDataFwUpgrade{
|
||||||
Type: UpgradeTypeArchive,
|
Type: types.UpgradeTypeArchive,
|
||||||
Files: []string{viper.GetString("archive")},
|
Files: []string{viper.GetString("archive")},
|
||||||
}
|
}
|
||||||
} else if viper.GetString("initPkt") != "" && viper.GetString("firmware") != "" {
|
} else if viper.GetString("initPkt") != "" && viper.GetString("firmware") != "" {
|
||||||
// Get files data struct
|
// Get files data struct
|
||||||
data = types.ReqDataFwUpgrade{
|
data = types.ReqDataFwUpgrade{
|
||||||
Type: UpgradeTypeFiles,
|
Type: types.UpgradeTypeFiles,
|
||||||
Files: []string{viper.GetString("initPkt"), viper.GetString("firmware")},
|
Files: []string{viper.GetString("initPkt"), viper.GetString("firmware")},
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -66,7 +66,7 @@ var upgradeCmd = &cobra.Command{
|
|||||||
|
|
||||||
// Encode response into connection
|
// Encode response into connection
|
||||||
err = json.NewEncoder(conn).Encode(types.Request{
|
err = json.NewEncoder(conn).Encode(types.Request{
|
||||||
Type: ReqTypeFwUpgrade,
|
Type: types.ReqTypeFwUpgrade,
|
||||||
Data: data,
|
Data: data,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import (
|
|||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/spf13/viper"
|
||||||
"go.arsenm.dev/itd/internal/types"
|
"go.arsenm.dev/itd/internal/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -36,7 +37,7 @@ var versionCmd = &cobra.Command{
|
|||||||
Short: "Get firmware version of InfiniTime",
|
Short: "Get firmware version of InfiniTime",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
// Connect to itd UNIX socket
|
// Connect to itd UNIX socket
|
||||||
conn, err := net.Dial("unix", SockPath)
|
conn, err := net.Dial("unix", viper.GetString("sockPath"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal().Err(err).Msg("Error dialing socket. Is itd running?")
|
log.Fatal().Err(err).Msg("Error dialing socket. Is itd running?")
|
||||||
}
|
}
|
||||||
@@ -44,7 +45,7 @@ var versionCmd = &cobra.Command{
|
|||||||
|
|
||||||
// Encode request into connection
|
// Encode request into connection
|
||||||
err = json.NewEncoder(conn).Encode(types.Request{
|
err = json.NewEncoder(conn).Encode(types.Request{
|
||||||
Type: ReqTypeFwVersion,
|
Type: types.ReqTypeFwVersion,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal().Err(err).Msg("Error making request")
|
log.Fatal().Err(err).Msg("Error making request")
|
||||||
|
|||||||
38
cmd/itgui/error.go
Normal file
38
cmd/itgui/error.go
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"image/color"
|
||||||
|
|
||||||
|
"fyne.io/fyne/v2"
|
||||||
|
"fyne.io/fyne/v2/canvas"
|
||||||
|
"fyne.io/fyne/v2/container"
|
||||||
|
"fyne.io/fyne/v2/dialog"
|
||||||
|
"fyne.io/fyne/v2/widget"
|
||||||
|
)
|
||||||
|
|
||||||
|
func guiErr(err error, msg string, parent fyne.Window) {
|
||||||
|
// Create new label containing message
|
||||||
|
msgLbl := widget.NewLabel(msg)
|
||||||
|
// Text formatting settings
|
||||||
|
msgLbl.Wrapping = fyne.TextWrapWord
|
||||||
|
msgLbl.Alignment = fyne.TextAlignCenter
|
||||||
|
// Create new rectangle to set the size of the dialog
|
||||||
|
rect := canvas.NewRectangle(color.Transparent)
|
||||||
|
// Set minimum size of rectangle to 350x0
|
||||||
|
rect.SetMinSize(fyne.NewSize(350, 0))
|
||||||
|
// Create new container containing message and rectangle
|
||||||
|
content := container.NewVBox(
|
||||||
|
msgLbl,
|
||||||
|
rect,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
// Create new label containing error text
|
||||||
|
errLbl := widget.NewLabel(err.Error())
|
||||||
|
// Create new dropdown containing error label
|
||||||
|
content.Add(widget.NewAccordion(
|
||||||
|
widget.NewAccordionItem("More Details", errLbl),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
// Show error dialog
|
||||||
|
dialog.NewCustom("Error", "Ok", content, parent).Show()
|
||||||
|
}
|
||||||
149
cmd/itgui/info.go
Normal file
149
cmd/itgui/info.go
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"image/color"
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"fyne.io/fyne/v2"
|
||||||
|
"fyne.io/fyne/v2/canvas"
|
||||||
|
"fyne.io/fyne/v2/container"
|
||||||
|
"fyne.io/fyne/v2/theme"
|
||||||
|
"go.arsenm.dev/itd/internal/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func infoTab(parent fyne.Window) *fyne.Container {
|
||||||
|
infoLayout := container.NewVBox(
|
||||||
|
// Add rectangle for a bit of padding
|
||||||
|
canvas.NewRectangle(color.Transparent),
|
||||||
|
)
|
||||||
|
|
||||||
|
// Create label for heart rate
|
||||||
|
heartRateLbl := newText("0 BPM", 24)
|
||||||
|
// Creae container to store heart rate section
|
||||||
|
heartRate := container.NewVBox(
|
||||||
|
newText("Heart Rate", 12),
|
||||||
|
heartRateLbl,
|
||||||
|
canvas.NewLine(theme.ShadowColor()),
|
||||||
|
)
|
||||||
|
infoLayout.Add(heartRate)
|
||||||
|
|
||||||
|
// Watch for heart rate updates
|
||||||
|
go watch(types.ReqTypeWatchHeartRate, func(data interface{}) {
|
||||||
|
// Change text of heart rate label
|
||||||
|
heartRateLbl.Text = fmt.Sprintf("%d BPM", int(data.(float64)))
|
||||||
|
// Refresh label
|
||||||
|
heartRateLbl.Refresh()
|
||||||
|
}, parent)
|
||||||
|
|
||||||
|
// Create label for battery level
|
||||||
|
battLevelLbl := newText("0%", 24)
|
||||||
|
// Create container to store battery level section
|
||||||
|
battLevel := container.NewVBox(
|
||||||
|
newText("Battery Level", 12),
|
||||||
|
battLevelLbl,
|
||||||
|
canvas.NewLine(theme.ShadowColor()),
|
||||||
|
)
|
||||||
|
infoLayout.Add(battLevel)
|
||||||
|
|
||||||
|
// Watch for changes in battery level
|
||||||
|
go watch(types.ReqTypeWatchBattLevel, func(data interface{}) {
|
||||||
|
battLevelLbl.Text = fmt.Sprintf("%d%%", int(data.(float64)))
|
||||||
|
battLevelLbl.Refresh()
|
||||||
|
}, parent)
|
||||||
|
|
||||||
|
fwVerString, err := get(types.ReqTypeFwVersion)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fwVer := container.NewVBox(
|
||||||
|
newText("Firmware Version", 12),
|
||||||
|
newText(fwVerString.(string), 24),
|
||||||
|
canvas.NewLine(theme.ShadowColor()),
|
||||||
|
)
|
||||||
|
infoLayout.Add(fwVer)
|
||||||
|
|
||||||
|
btAddrString, err := get(types.ReqTypeBtAddress)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
btAddr := container.NewVBox(
|
||||||
|
newText("Bluetooth Address", 12),
|
||||||
|
newText(btAddrString.(string), 24),
|
||||||
|
canvas.NewLine(theme.ShadowColor()),
|
||||||
|
)
|
||||||
|
infoLayout.Add(btAddr)
|
||||||
|
|
||||||
|
return infoLayout
|
||||||
|
}
|
||||||
|
|
||||||
|
func watch(req int, onRecv func(data interface{}), parent fyne.Window) error {
|
||||||
|
conn, err := net.Dial("unix", SockPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
err = json.NewEncoder(conn).Encode(types.Request{
|
||||||
|
Type: req,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
scanner := bufio.NewScanner(conn)
|
||||||
|
for scanner.Scan() {
|
||||||
|
res, err := getResp(scanner.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
guiErr(err, "Error getting response from connection", parent)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
onRecv(res.Value)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func get(req int) (interface{}, error) {
|
||||||
|
conn, err := net.Dial("unix", SockPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
err = json.NewEncoder(conn).Encode(types.Request{
|
||||||
|
Type: req,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
line, _, err := bufio.NewReader(conn).ReadLine()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
res, err := getResp(line)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return res.Value, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getResp(line []byte) (*types.Response, error) {
|
||||||
|
var res types.Response
|
||||||
|
err := json.Unmarshal(line, &res)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if res.Error {
|
||||||
|
return nil, errors.New(res.Message)
|
||||||
|
}
|
||||||
|
return &res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func newText(t string, size float32) *canvas.Text {
|
||||||
|
text := canvas.NewText(t, theme.ForegroundColor())
|
||||||
|
text.TextSize = size
|
||||||
|
return text
|
||||||
|
}
|
||||||
28
cmd/itgui/main.go
Normal file
28
cmd/itgui/main.go
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fyne.io/fyne/v2/app"
|
||||||
|
"fyne.io/fyne/v2/container"
|
||||||
|
)
|
||||||
|
|
||||||
|
var SockPath = "/tmp/itd/socket"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Create new app
|
||||||
|
a := app.New()
|
||||||
|
// Create new window with title "itgui"
|
||||||
|
window := a.NewWindow("itgui")
|
||||||
|
|
||||||
|
// Create new app tabs container
|
||||||
|
tabs := container.NewAppTabs(
|
||||||
|
container.NewTabItem("Info", infoTab(window)),
|
||||||
|
container.NewTabItem("Notify", notifyTab(window)),
|
||||||
|
container.NewTabItem("Set Time", timeTab(window)),
|
||||||
|
container.NewTabItem("Upgrade", upgradeTab(window)),
|
||||||
|
)
|
||||||
|
|
||||||
|
// Set tabs as window content
|
||||||
|
window.SetContent(tabs)
|
||||||
|
// Show window and run app
|
||||||
|
window.ShowAndRun()
|
||||||
|
}
|
||||||
49
cmd/itgui/notify.go
Normal file
49
cmd/itgui/notify.go
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"fyne.io/fyne/v2"
|
||||||
|
"fyne.io/fyne/v2/container"
|
||||||
|
"fyne.io/fyne/v2/layout"
|
||||||
|
"fyne.io/fyne/v2/widget"
|
||||||
|
"go.arsenm.dev/itd/internal/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func notifyTab(parent fyne.Window) *fyne.Container {
|
||||||
|
// Create new entry for notification title
|
||||||
|
titleEntry := widget.NewEntry()
|
||||||
|
titleEntry.SetPlaceHolder("Title")
|
||||||
|
|
||||||
|
// Create multiline entry for notification body
|
||||||
|
bodyEntry := widget.NewMultiLineEntry()
|
||||||
|
bodyEntry.SetPlaceHolder("Body")
|
||||||
|
|
||||||
|
// Create new button to send notification
|
||||||
|
sendBtn := widget.NewButton("Send", func() {
|
||||||
|
// Dial itd UNIX socket
|
||||||
|
conn, err := net.Dial("unix", SockPath)
|
||||||
|
if err != nil {
|
||||||
|
guiErr(err, "Error dialing socket", parent)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Encode notify request on connection
|
||||||
|
json.NewEncoder(conn).Encode(types.Request{
|
||||||
|
Type: types.ReqTypeNotify,
|
||||||
|
Data: types.ReqDataNotify{
|
||||||
|
Title: titleEntry.Text,
|
||||||
|
Body: bodyEntry.Text,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// Return new container containing all elements
|
||||||
|
return container.NewVBox(
|
||||||
|
layout.NewSpacer(),
|
||||||
|
titleEntry,
|
||||||
|
bodyEntry,
|
||||||
|
sendBtn,
|
||||||
|
layout.NewSpacer(),
|
||||||
|
)
|
||||||
|
}
|
||||||
79
cmd/itgui/time.go
Normal file
79
cmd/itgui/time.go
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"net"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"fyne.io/fyne/v2"
|
||||||
|
"fyne.io/fyne/v2/container"
|
||||||
|
"fyne.io/fyne/v2/layout"
|
||||||
|
"fyne.io/fyne/v2/widget"
|
||||||
|
"go.arsenm.dev/itd/internal/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func timeTab(parent fyne.Window) *fyne.Container {
|
||||||
|
// Create new entry for time string
|
||||||
|
timeEntry := widget.NewEntry()
|
||||||
|
// Set text to current time formatter properly
|
||||||
|
timeEntry.SetText(time.Now().Format(time.RFC1123))
|
||||||
|
|
||||||
|
// Create button to set current time
|
||||||
|
currentBtn := widget.NewButton("Set Current", func() {
|
||||||
|
timeEntry.SetText(time.Now().Format(time.RFC1123))
|
||||||
|
setTime(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Create button to set time inside entry
|
||||||
|
timeBtn := widget.NewButton("Set", func() {
|
||||||
|
// Parse time as RFC1123 string
|
||||||
|
parsedTime, err := time.Parse(time.RFC1123, timeEntry.Text)
|
||||||
|
if err != nil {
|
||||||
|
guiErr(err, "Error parsing time string", parent)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Set time to parsed time
|
||||||
|
setTime(false, parsedTime)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Return new container with all elements centered
|
||||||
|
return container.NewVBox(
|
||||||
|
layout.NewSpacer(),
|
||||||
|
timeEntry,
|
||||||
|
currentBtn,
|
||||||
|
timeBtn,
|
||||||
|
layout.NewSpacer(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// setTime sets the first element in the variadic parameter
|
||||||
|
// if current is false, otherwise, it sets the current time.
|
||||||
|
func setTime(current bool, t ...time.Time) error {
|
||||||
|
// Dial UNIX socket
|
||||||
|
conn, err := net.Dial("unix", SockPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
var data string
|
||||||
|
// If current is true, use the string "now"
|
||||||
|
// otherwise, use the formatted time from the
|
||||||
|
// first element in the variadic parameter.
|
||||||
|
// "now" is more accurate than formatting
|
||||||
|
// current time as only seconds are preserved
|
||||||
|
// in that case.
|
||||||
|
if current {
|
||||||
|
data = "now"
|
||||||
|
} else {
|
||||||
|
data = t[0].Format(time.RFC3339)
|
||||||
|
}
|
||||||
|
// Encode SetTime request with above data
|
||||||
|
err = json.NewEncoder(conn).Encode(types.Request{
|
||||||
|
Type: types.ReqTypeSetTime,
|
||||||
|
Data: data,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
191
cmd/itgui/upgrade.go
Normal file
191
cmd/itgui/upgrade.go
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"fyne.io/fyne/v2"
|
||||||
|
"fyne.io/fyne/v2/container"
|
||||||
|
"fyne.io/fyne/v2/dialog"
|
||||||
|
"fyne.io/fyne/v2/layout"
|
||||||
|
"fyne.io/fyne/v2/storage"
|
||||||
|
"fyne.io/fyne/v2/widget"
|
||||||
|
"github.com/mitchellh/mapstructure"
|
||||||
|
"go.arsenm.dev/itd/internal/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func upgradeTab(parent fyne.Window) *fyne.Container {
|
||||||
|
var (
|
||||||
|
archivePath string
|
||||||
|
fiwmarePath string
|
||||||
|
initPktPath string
|
||||||
|
)
|
||||||
|
|
||||||
|
// Create archive selection dialog
|
||||||
|
archiveDialog := dialog.NewFileOpen(func(uc fyne.URIReadCloser, e error) {
|
||||||
|
if e != nil || uc == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
uc.Close()
|
||||||
|
archivePath = uc.URI().Path()
|
||||||
|
}, parent)
|
||||||
|
// Limit dialog to .zip files
|
||||||
|
archiveDialog.SetFilter(storage.NewExtensionFileFilter([]string{".zip"}))
|
||||||
|
// Create button to show dialog
|
||||||
|
archiveBtn := widget.NewButton("Select archive (.zip)", archiveDialog.Show)
|
||||||
|
|
||||||
|
// Create firmware selection dialog
|
||||||
|
firmwareDialog := dialog.NewFileOpen(func(uc fyne.URIReadCloser, e error) {
|
||||||
|
if e != nil || uc == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
uc.Close()
|
||||||
|
fiwmarePath = uc.URI().Path()
|
||||||
|
}, parent)
|
||||||
|
// Limit dialog to .bin files
|
||||||
|
firmwareDialog.SetFilter(storage.NewExtensionFileFilter([]string{".bin"}))
|
||||||
|
// Create button to show dialog
|
||||||
|
firmwareBtn := widget.NewButton("Select init packet (.bin)", firmwareDialog.Show)
|
||||||
|
|
||||||
|
// Create init packet selection dialog
|
||||||
|
initPktDialog := dialog.NewFileOpen(func(uc fyne.URIReadCloser, e error) {
|
||||||
|
if e != nil || uc == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
uc.Close()
|
||||||
|
initPktPath = uc.URI().Path()
|
||||||
|
}, parent)
|
||||||
|
// Limit dialog to .dat files
|
||||||
|
initPktDialog.SetFilter(storage.NewExtensionFileFilter([]string{".dat"}))
|
||||||
|
// Create button to show dialog
|
||||||
|
initPktBtn := widget.NewButton("Select init packet (.dat)", initPktDialog.Show)
|
||||||
|
|
||||||
|
// Hide init packet and firmware buttons
|
||||||
|
initPktBtn.Hide()
|
||||||
|
firmwareBtn.Hide()
|
||||||
|
|
||||||
|
// Create dropdown to select upgrade type
|
||||||
|
upgradeTypeSelect := widget.NewSelect([]string{
|
||||||
|
"Archive",
|
||||||
|
"Files",
|
||||||
|
}, func(s string) {
|
||||||
|
// Hide all buttons
|
||||||
|
archiveBtn.Hide()
|
||||||
|
initPktBtn.Hide()
|
||||||
|
firmwareBtn.Hide()
|
||||||
|
// Unhide appropriate button(s)
|
||||||
|
switch s {
|
||||||
|
case "Archive":
|
||||||
|
archiveBtn.Show()
|
||||||
|
case "Files":
|
||||||
|
initPktBtn.Show()
|
||||||
|
firmwareBtn.Show()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// Select first elemetn
|
||||||
|
upgradeTypeSelect.SetSelectedIndex(0)
|
||||||
|
|
||||||
|
// Create new button to start DFU
|
||||||
|
startBtn := widget.NewButton("Start", func() {
|
||||||
|
// If archive path does not exist and both init packet and firmware paths
|
||||||
|
// also do not exist, return error
|
||||||
|
if archivePath == "" && (initPktPath == "" && fiwmarePath == "") {
|
||||||
|
guiErr(nil, "Upgrade requires archive or files selected", parent)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create new label for byte progress
|
||||||
|
progressLbl := widget.NewLabelWithStyle("0 / 0 B", fyne.TextAlignCenter, fyne.TextStyle{})
|
||||||
|
// Create new progress bar
|
||||||
|
progressBar := widget.NewProgressBar()
|
||||||
|
// Create modal dialog containing label and progress bar
|
||||||
|
progressDlg := widget.NewModalPopUp(container.NewVBox(
|
||||||
|
layout.NewSpacer(),
|
||||||
|
progressLbl,
|
||||||
|
progressBar,
|
||||||
|
layout.NewSpacer(),
|
||||||
|
), parent.Canvas())
|
||||||
|
// Resize modal to 300x100
|
||||||
|
progressDlg.Resize(fyne.NewSize(300, 100))
|
||||||
|
|
||||||
|
var fwUpgType int
|
||||||
|
var files []string
|
||||||
|
// Get appropriate upgrade type and file paths
|
||||||
|
switch upgradeTypeSelect.Selected {
|
||||||
|
case "Archive":
|
||||||
|
fwUpgType = types.UpgradeTypeArchive
|
||||||
|
files = append(files, archivePath)
|
||||||
|
case "Files":
|
||||||
|
fwUpgType = types.UpgradeTypeFiles
|
||||||
|
files = append(files, initPktPath, fiwmarePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dial itd UNIX socket
|
||||||
|
conn, err := net.Dial("unix", SockPath)
|
||||||
|
if err != nil {
|
||||||
|
guiErr(err, "Error dialing socket", parent)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
// Encode firmware upgrade request to connection
|
||||||
|
json.NewEncoder(conn).Encode(types.Request{
|
||||||
|
Type: types.ReqTypeFwUpgrade,
|
||||||
|
Data: types.ReqDataFwUpgrade{
|
||||||
|
Type: fwUpgType,
|
||||||
|
Files: files,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// Show progress dialog
|
||||||
|
progressDlg.Show()
|
||||||
|
// Hide progress dialog after completion
|
||||||
|
defer progressDlg.Hide()
|
||||||
|
|
||||||
|
scanner := bufio.NewScanner(conn)
|
||||||
|
for scanner.Scan() {
|
||||||
|
var res types.Response
|
||||||
|
// Decode scanned line into response struct
|
||||||
|
err = json.Unmarshal(scanner.Bytes(), &res)
|
||||||
|
if err != nil {
|
||||||
|
guiErr(err, "Error decoding response", parent)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if res.Error {
|
||||||
|
guiErr(err, "Error returned in response", parent)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var event types.DFUProgress
|
||||||
|
// Decode response data into progress struct
|
||||||
|
err = mapstructure.Decode(res.Value, &event)
|
||||||
|
if err != nil {
|
||||||
|
guiErr(err, "Error decoding response value", parent)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// If transfer finished, break
|
||||||
|
if event.Received == event.Total {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// Set label text to received / total B
|
||||||
|
progressLbl.SetText(fmt.Sprintf("%d / %d B", event.Received, event.Total))
|
||||||
|
// Set progress bar values
|
||||||
|
progressBar.Max = float64(event.Total)
|
||||||
|
progressBar.Value = float64(event.Received)
|
||||||
|
// Refresh progress bar
|
||||||
|
progressBar.Refresh()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Return container containing all elements
|
||||||
|
return container.NewVBox(
|
||||||
|
layout.NewSpacer(),
|
||||||
|
upgradeTypeSelect,
|
||||||
|
archiveBtn,
|
||||||
|
firmwareBtn,
|
||||||
|
initPktBtn,
|
||||||
|
startBtn,
|
||||||
|
layout.NewSpacer(),
|
||||||
|
)
|
||||||
|
}
|
||||||
47
config.go
Normal file
47
config.go
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/rs/zerolog"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// Set up logger
|
||||||
|
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
|
||||||
|
|
||||||
|
// Set config settings
|
||||||
|
setCfgDefaults()
|
||||||
|
viper.AddConfigPath("$HOME/.config")
|
||||||
|
viper.AddConfigPath("/etc")
|
||||||
|
viper.SetConfigName("itd")
|
||||||
|
viper.SetConfigType("toml")
|
||||||
|
viper.WatchConfig()
|
||||||
|
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
|
||||||
|
viper.SetEnvPrefix("itd")
|
||||||
|
// Ignore error because defaults set
|
||||||
|
viper.ReadInConfig()
|
||||||
|
viper.AutomaticEnv()
|
||||||
|
}
|
||||||
|
|
||||||
|
func setCfgDefaults() {
|
||||||
|
viper.SetDefault("cfg.version", 2)
|
||||||
|
|
||||||
|
viper.SetDefault("socket.path", "/tmp/itd/socket")
|
||||||
|
|
||||||
|
viper.SetDefault("conn.reconnect", true)
|
||||||
|
|
||||||
|
viper.SetDefault("on.connect.notify", true)
|
||||||
|
|
||||||
|
viper.SetDefault("on.reconnect.notify", true)
|
||||||
|
viper.SetDefault("on.reconnect.setTime", true)
|
||||||
|
|
||||||
|
viper.SetDefault("notifs.ignore.sender", []string{})
|
||||||
|
viper.SetDefault("notifs.ignore.summary", []string{"InfiniTime"})
|
||||||
|
viper.SetDefault("notifs.ignore.body", []string{})
|
||||||
|
|
||||||
|
viper.SetDefault("music.vol.interval", 5)
|
||||||
|
}
|
||||||
5
go.mod
5
go.mod
@@ -3,6 +3,7 @@ module go.arsenm.dev/itd
|
|||||||
go 1.16
|
go 1.16
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
fyne.io/fyne/v2 v2.0.4
|
||||||
github.com/VividCortex/ewma v1.2.0 // indirect
|
github.com/VividCortex/ewma v1.2.0 // indirect
|
||||||
github.com/abiosoft/ishell v2.0.0+incompatible
|
github.com/abiosoft/ishell v2.0.0+incompatible
|
||||||
github.com/abiosoft/readline v0.0.0-20180607040430-155bce2042db // indirect
|
github.com/abiosoft/readline v0.0.0-20180607040430-155bce2042db // indirect
|
||||||
@@ -19,7 +20,7 @@ require (
|
|||||||
github.com/spf13/cast v1.4.1 // indirect
|
github.com/spf13/cast v1.4.1 // indirect
|
||||||
github.com/spf13/cobra v1.2.1
|
github.com/spf13/cobra v1.2.1
|
||||||
github.com/spf13/viper v1.8.1
|
github.com/spf13/viper v1.8.1
|
||||||
go.arsenm.dev/infinitime v0.0.0-20210821070429-ea488067fb9b
|
go.arsenm.dev/infinitime v0.0.0-20210825051734-745b4bd37cf4
|
||||||
golang.org/x/sys v0.0.0-20210820121016-41cdb8703e55 // indirect
|
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf // indirect
|
||||||
golang.org/x/text v0.3.7 // indirect
|
golang.org/x/text v0.3.7 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
40
go.sum
40
go.sum
@@ -37,8 +37,11 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl
|
|||||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||||
|
fyne.io/fyne/v2 v2.0.4 h1:eDGaPGzeR4qNqWuAp9Li1kY4eVIHldCkf42KMakKIK4=
|
||||||
|
fyne.io/fyne/v2 v2.0.4/go.mod h1:nNpgL7sZkDVLraGtQII2ArNRnnl6kHup/KfQRxIhbvs=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
|
github.com/Kodeworks/golang-image-ico v0.0.0-20141118225523-73f0f4cfade9/go.mod h1:7uhhqiBaR4CpN0k9rMjOtjpcfGd6DG2m04zQxKnWQ0I=
|
||||||
github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA=
|
github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA=
|
||||||
github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow=
|
github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow=
|
||||||
github.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4=
|
github.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4=
|
||||||
@@ -46,6 +49,7 @@ github.com/abiosoft/ishell v2.0.0+incompatible h1:zpwIuEHc37EzrsIYah3cpevrIc8Oma
|
|||||||
github.com/abiosoft/ishell v2.0.0+incompatible/go.mod h1:HQR9AqF2R3P4XXpMpI0NAzgHf/aS6+zVXRj14cVk9qg=
|
github.com/abiosoft/ishell v2.0.0+incompatible/go.mod h1:HQR9AqF2R3P4XXpMpI0NAzgHf/aS6+zVXRj14cVk9qg=
|
||||||
github.com/abiosoft/readline v0.0.0-20180607040430-155bce2042db h1:CjPUSXOiYptLbTdr1RceuZgSFDQ7U15ITERUGrUORx8=
|
github.com/abiosoft/readline v0.0.0-20180607040430-155bce2042db h1:CjPUSXOiYptLbTdr1RceuZgSFDQ7U15ITERUGrUORx8=
|
||||||
github.com/abiosoft/readline v0.0.0-20180607040430-155bce2042db/go.mod h1:rB3B4rKii8V21ydCbIzH5hZiCQE7f5E9SzUb/ZZx530=
|
github.com/abiosoft/readline v0.0.0-20180607040430-155bce2042db/go.mod h1:rB3B4rKii8V21ydCbIzH5hZiCQE7f5E9SzUb/ZZx530=
|
||||||
|
github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c=
|
||||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||||
@@ -85,17 +89,28 @@ github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
|
|||||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||||
github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BMXYYRWTLOJKlh+lOBt6nUQgXAfB7oVIQt5cNreqSLI=
|
github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BMXYYRWTLOJKlh+lOBt6nUQgXAfB7oVIQt5cNreqSLI=
|
||||||
github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:rZfgFAXFS/z/lEd6LJmf9HVZ1LkgYiHx5pHhV5DR16M=
|
github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:rZfgFAXFS/z/lEd6LJmf9HVZ1LkgYiHx5pHhV5DR16M=
|
||||||
|
github.com/fredbi/uri v0.0.0-20181227131451-3dcfdacbaaf3 h1:FDqhDm7pcsLhhWl1QtD8vlzI4mm59llRvNzrFg6/LAA=
|
||||||
|
github.com/fredbi/uri v0.0.0-20181227131451-3dcfdacbaaf3/go.mod h1:CzM2G82Q9BDUvMTGHnXf/6OExw/Dz2ivDj48nVg7Lg8=
|
||||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||||
github.com/fsnotify/fsnotify v1.5.0 h1:NO5hkcB+srp1x6QmwvNZLeaOgbM8cmBTN32THzjvu2k=
|
github.com/fsnotify/fsnotify v1.5.0 h1:NO5hkcB+srp1x6QmwvNZLeaOgbM8cmBTN32THzjvu2k=
|
||||||
github.com/fsnotify/fsnotify v1.5.0/go.mod h1:BX0DCEr5pT4jm2CnQdVP1lFV521fcCNcyEeNp4DQQDk=
|
github.com/fsnotify/fsnotify v1.5.0/go.mod h1:BX0DCEr5pT4jm2CnQdVP1lFV521fcCNcyEeNp4DQQDk=
|
||||||
|
github.com/fyne-io/mobile v0.1.3-0.20210412090810-650a3139866a h1:3TAJhl8vXyli0tooKB0vd6gLCyBdWL4QEYbDoJpHEZk=
|
||||||
|
github.com/fyne-io/mobile v0.1.3-0.20210412090810-650a3139866a/go.mod h1:/kOrWrZB6sasLbEy2JIvr4arEzQTXBTZGb3Y96yWbHY=
|
||||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
|
github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7 h1:SCYMcCJ89LjRGwEa0tRluNRiMjZHalQZrVrvTbPh+qw=
|
||||||
|
github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7/go.mod h1:482civXOzJJCPzJ4ZOX/pwvXBWSnzD4OKMdH4ClKGbk=
|
||||||
|
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1 h1:QbL/5oDUmRBzO9/Z7Seo6zf912W/a6Sr4Eu0G/3Jho0=
|
||||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20210410170116-ea3d685f79fb h1:T6gaWBvRzJjuOrdCtg8fXXjKai2xSDqWTcKFUPuw8Tw=
|
||||||
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20210410170116-ea3d685f79fb/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA=
|
github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA=
|
||||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||||
|
github.com/goki/freetype v0.0.0-20181231101311-fa8a33aabaff h1:W71vTCKoxtdXgnm1ECDFkfQnpdqAO00zzGXLA5yaEX8=
|
||||||
|
github.com/goki/freetype v0.0.0-20181231101311-fa8a33aabaff/go.mod h1:wfqRWLHRBsRgkp5dmbG56SA0DmVtwrF5N3oPdI8t+Aw=
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
@@ -186,6 +201,8 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:
|
|||||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||||
|
github.com/jackmordaunt/icns v0.0.0-20181231085925-4f16af745526/go.mod h1:UQkeMHVoNcyXYq9otUupF7/h/2tmHlhrS2zw7ZVvUqc=
|
||||||
|
github.com/josephspurrier/goversioninfo v0.0.0-20200309025242-14b0ab84c6ca/go.mod h1:eJTEwMjXb7kZ633hO3Ln9mBUCOjX2+FlTljvpl9SYdE=
|
||||||
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||||
@@ -199,6 +216,7 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
|
|||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/lucor/goinfo v0.0.0-20200401173949-526b5363a13a/go.mod h1:ORP3/rB5IsulLEBwQZCJyyV6niqmI7P4EWSmkug+1Ng=
|
||||||
github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls=
|
github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls=
|
||||||
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||||
@@ -226,12 +244,14 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
|
|||||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/muka/go-bluetooth v0.0.0-20210812063148-b6c83362e27d h1:EG/xyWjHT19rkUpwsWSkyiCCmyqNwFovr9m10rhyOxU=
|
github.com/muka/go-bluetooth v0.0.0-20210812063148-b6c83362e27d h1:EG/xyWjHT19rkUpwsWSkyiCCmyqNwFovr9m10rhyOxU=
|
||||||
github.com/muka/go-bluetooth v0.0.0-20210812063148-b6c83362e27d/go.mod h1:dMCjicU6vRBk34dqOmIZm0aod6gUwZXOXzBROqGous0=
|
github.com/muka/go-bluetooth v0.0.0-20210812063148-b6c83362e27d/go.mod h1:dMCjicU6vRBk34dqOmIZm0aod6gUwZXOXzBROqGous0=
|
||||||
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||||
github.com/paypal/gatt v0.0.0-20151011220935-4ae819d591cf/go.mod h1:+AwQL2mK3Pd3S+TUwg0tYQjid0q1txyNUJuuSmz8Kdk=
|
github.com/paypal/gatt v0.0.0-20151011220935-4ae819d591cf/go.mod h1:+AwQL2mK3Pd3S+TUwg0tYQjid0q1txyNUJuuSmz8Kdk=
|
||||||
github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ=
|
github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ=
|
||||||
github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||||
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
|
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
|
||||||
@@ -258,6 +278,7 @@ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykE
|
|||||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||||
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
||||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||||
|
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||||
github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY=
|
github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY=
|
||||||
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
|
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
|
||||||
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||||
@@ -267,10 +288,15 @@ github.com/spf13/cobra v1.2.1 h1:+KmjbUw1hriSNMF55oPrkZcb27aECyrj8V2ytv7kWDw=
|
|||||||
github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk=
|
github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk=
|
||||||
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
|
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
|
||||||
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
||||||
|
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
github.com/spf13/viper v1.8.1 h1:Kq1fyeebqsBfbjZj4EL7gj2IO0mMaiyjYUWcUsl2O44=
|
github.com/spf13/viper v1.8.1 h1:Kq1fyeebqsBfbjZj4EL7gj2IO0mMaiyjYUWcUsl2O44=
|
||||||
github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns=
|
github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns=
|
||||||
|
github.com/srwiley/oksvg v0.0.0-20200311192757-870daf9aa564 h1:HunZiaEKNGVdhTRQOVpMmj5MQnGnv+e8uZNu3xFLgyM=
|
||||||
|
github.com/srwiley/oksvg v0.0.0-20200311192757-870daf9aa564/go.mod h1:afMbS0qvv1m5tfENCwnOdZGOF8RGR/FsZ7bvBxQGZG4=
|
||||||
|
github.com/srwiley/rasterx v0.0.0-20200120212402-85cb7272f5e9 h1:m59mIOBO4kfcNCEzJNy71UkeF4XIx2EVmL9KLwDQdmM=
|
||||||
|
github.com/srwiley/rasterx v0.0.0-20200120212402-85cb7272f5e9/go.mod h1:mvWM0+15UqyrFKqdRjY6LuAVJR0HOVhJlEgZ5JWtSWU=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
@@ -287,8 +313,8 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
|||||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
go.arsenm.dev/infinitime v0.0.0-20210821070429-ea488067fb9b h1:Wwj7F0gqYHUx+9H8fCCIy5JZTlCusJRpPuzeSFM0EoU=
|
go.arsenm.dev/infinitime v0.0.0-20210825051734-745b4bd37cf4 h1:XZyynxrvGxP0mwyhdiuMrvj5SkiK6N+MDiC6DiGzgWU=
|
||||||
go.arsenm.dev/infinitime v0.0.0-20210821070429-ea488067fb9b/go.mod h1:gaepaueUz4J5FfxuV19B4w5pi+V3mD0LTef50ryxr/Q=
|
go.arsenm.dev/infinitime v0.0.0-20210825051734-745b4bd37cf4/go.mod h1:gaepaueUz4J5FfxuV19B4w5pi+V3mD0LTef50ryxr/Q=
|
||||||
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
|
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
|
||||||
go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
|
go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
|
||||||
go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=
|
go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=
|
||||||
@@ -321,6 +347,8 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH
|
|||||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
|
golang.org/x/image v0.0.0-20200430140353-33d19683fad8 h1:6WW6V3x1P/jokJBpRQYUJnMHRP6isStQwCozxnU7XQw=
|
||||||
|
golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
@@ -379,6 +407,7 @@ golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v
|
|||||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
||||||
|
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0=
|
||||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
@@ -433,6 +462,7 @@ golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200720211630-cb9d2d5c5666/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -449,8 +479,8 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210820121016-41cdb8703e55 h1:rw6UNGRMfarCepjI8qOepea/SXwIBVfTKjztZ5gBbq4=
|
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf h1:2ucpDCmfkl8Bd/FsLtiD653Wf96cW37s+iGx93zsu4k=
|
||||||
golang.org/x/sys v0.0.0-20210820121016-41cdb8703e55/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
@@ -477,6 +507,7 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn
|
|||||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
|
golang.org/x/tools v0.0.0-20190808195139-e713427fea3f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
@@ -498,6 +529,7 @@ golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapK
|
|||||||
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||||
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||||
|
golang.org/x/tools v0.0.0-20200328031815-3db5fc6bac03/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||||
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||||
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
|
|||||||
@@ -1,5 +1,22 @@
|
|||||||
package types
|
package types
|
||||||
|
|
||||||
|
const (
|
||||||
|
ReqTypeHeartRate = iota
|
||||||
|
ReqTypeBattLevel
|
||||||
|
ReqTypeFwVersion
|
||||||
|
ReqTypeFwUpgrade
|
||||||
|
ReqTypeBtAddress
|
||||||
|
ReqTypeNotify
|
||||||
|
ReqTypeSetTime
|
||||||
|
ReqTypeWatchHeartRate
|
||||||
|
ReqTypeWatchBattLevel
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
UpgradeTypeArchive = iota
|
||||||
|
UpgradeTypeFiles
|
||||||
|
)
|
||||||
|
|
||||||
type ReqDataFwUpgrade struct {
|
type ReqDataFwUpgrade struct {
|
||||||
Type int
|
Type int
|
||||||
Files []string
|
Files []string
|
||||||
@@ -12,7 +29,7 @@ type Response struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Request struct {
|
type Request struct {
|
||||||
Type string `json:"type"`
|
Type int `json:"type"`
|
||||||
Data interface{} `json:"data,omitempty"`
|
Data interface{} `json:"data,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -20,3 +37,8 @@ type ReqDataNotify struct {
|
|||||||
Title string
|
Title string
|
||||||
Body string
|
Body string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DFUProgress struct {
|
||||||
|
Received int64 `mapstructure:"recvd"`
|
||||||
|
Total int64 `mapstructure:"total"`
|
||||||
|
}
|
||||||
|
|||||||
21
itd.toml
21
itd.toml
@@ -1,14 +1,25 @@
|
|||||||
|
# This is temporary, it is to show a notice
|
||||||
|
# to people still using the old config
|
||||||
|
cfg.version = 2
|
||||||
|
|
||||||
|
[socket]
|
||||||
|
path = "/tmp/itd/socket"
|
||||||
|
|
||||||
[conn]
|
[conn]
|
||||||
reconnect = true
|
reconnect = true
|
||||||
|
|
||||||
[notify]
|
[on.connect]
|
||||||
onConnect = true
|
notify = true
|
||||||
onReconnect = true
|
|
||||||
|
|
||||||
[notifications.ignore]
|
[on.reconnect]
|
||||||
|
notify = true
|
||||||
|
setTime = true
|
||||||
|
|
||||||
|
[notifs.ignore]
|
||||||
sender = []
|
sender = []
|
||||||
summary = ["InfiniTime"]
|
summary = ["InfiniTime"]
|
||||||
body = []
|
body = []
|
||||||
|
|
||||||
[music]
|
[music]
|
||||||
volInterval = 5
|
vol.interval = 5
|
||||||
|
|
||||||
|
|||||||
31
main.go
31
main.go
@@ -19,11 +19,8 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/rs/zerolog"
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
"go.arsenm.dev/infinitime"
|
"go.arsenm.dev/infinitime"
|
||||||
@@ -31,25 +28,11 @@ import (
|
|||||||
|
|
||||||
var firmwareUpdating = false
|
var firmwareUpdating = false
|
||||||
|
|
||||||
func init() {
|
|
||||||
// Set up logger
|
|
||||||
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
|
|
||||||
|
|
||||||
// Set config settings
|
|
||||||
viper.AddConfigPath("$HOME/.config")
|
|
||||||
viper.AddConfigPath("/etc")
|
|
||||||
viper.SetConfigName("itd")
|
|
||||||
viper.SetConfigType("toml")
|
|
||||||
viper.WatchConfig()
|
|
||||||
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
|
|
||||||
viper.SetEnvPrefix("itd")
|
|
||||||
if err := viper.ReadInConfig(); err != nil {
|
|
||||||
log.Warn().Err(err).Msg("Could not read in config")
|
|
||||||
}
|
|
||||||
viper.AutomaticEnv()
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
if viper.GetInt("cfg.version") != 2 {
|
||||||
|
log.Fatal().Msg("Please update your config to the newest format, only v2 configs supported.")
|
||||||
|
}
|
||||||
|
|
||||||
// Cleanly exit after function
|
// Cleanly exit after function
|
||||||
defer infinitime.Exit()
|
defer infinitime.Exit()
|
||||||
|
|
||||||
@@ -63,14 +46,16 @@ func main() {
|
|||||||
|
|
||||||
// When InfiniTime reconnects
|
// When InfiniTime reconnects
|
||||||
dev.OnReconnect(func() {
|
dev.OnReconnect(func() {
|
||||||
|
if viper.GetBool("on.reconnect.setTime") {
|
||||||
// Set time to current time
|
// Set time to current time
|
||||||
err = dev.SetTime(time.Now())
|
err = dev.SetTime(time.Now())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msg("Error setting current time on connected InfiniTime")
|
log.Error().Err(err).Msg("Error setting current time on connected InfiniTime")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If config specifies to notify on reconnect
|
// If config specifies to notify on reconnect
|
||||||
if viper.GetBool("notify.onReconnect") {
|
if viper.GetBool("on.reconnect.notify") {
|
||||||
// Send notification to InfiniTime
|
// Send notification to InfiniTime
|
||||||
err = dev.Notify("itd", "Successfully reconnected")
|
err = dev.Notify("itd", "Successfully reconnected")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -89,7 +74,7 @@ func main() {
|
|||||||
log.Info().Str("version", ver).Msg("Connected to InfiniTime")
|
log.Info().Str("version", ver).Msg("Connected to InfiniTime")
|
||||||
|
|
||||||
// If config specifies to notify on connect
|
// If config specifies to notify on connect
|
||||||
if viper.GetBool("notify.onConnect") {
|
if viper.GetBool("on.connect.notify") {
|
||||||
// Send notification to InfiniTime
|
// Send notification to InfiniTime
|
||||||
err = dev.Notify("itd", "Successfully connected")
|
err = dev.Notify("itd", "Successfully connected")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
8
music.go
8
music.go
@@ -19,10 +19,10 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"go.arsenm.dev/infinitime"
|
|
||||||
"go.arsenm.dev/infinitime/pkg/player"
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
|
"go.arsenm.dev/infinitime"
|
||||||
|
"go.arsenm.dev/infinitime/pkg/player"
|
||||||
)
|
)
|
||||||
|
|
||||||
func initMusicCtrl(dev *infinitime.Device) error {
|
func initMusicCtrl(dev *infinitime.Device) error {
|
||||||
@@ -85,9 +85,9 @@ func initMusicCtrl(dev *infinitime.Device) error {
|
|||||||
case infinitime.MusicEventPrev:
|
case infinitime.MusicEventPrev:
|
||||||
player.Prev()
|
player.Prev()
|
||||||
case infinitime.MusicEventVolUp:
|
case infinitime.MusicEventVolUp:
|
||||||
player.VolUp(viper.GetUint("music.volInterval"))
|
player.VolUp(viper.GetUint("music.vol.interval"))
|
||||||
case infinitime.MusicEventVolDown:
|
case infinitime.MusicEventVolDown:
|
||||||
player.VolDown(viper.GetUint("music.volInterval"))
|
player.VolDown(viper.GetUint("music.vol.interval"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|||||||
@@ -90,9 +90,9 @@ func initNotifRelay(dev *infinitime.Device) error {
|
|||||||
|
|
||||||
// ignored checks whether any fields were ignored in the config
|
// ignored checks whether any fields were ignored in the config
|
||||||
func ignored(sender, summary, body string) bool {
|
func ignored(sender, summary, body string) bool {
|
||||||
ignoreSender := viper.GetStringSlice("notifications.ignore.sender")
|
ignoreSender := viper.GetStringSlice("notifs.ignore.sender")
|
||||||
ignoreSummary := viper.GetStringSlice("notifications.ignore.summary")
|
ignoreSummary := viper.GetStringSlice("notifs.ignore.summary")
|
||||||
ignoreBody := viper.GetStringSlice("notifications.ignore.body")
|
ignoreBody := viper.GetStringSlice("notifs.ignore.body")
|
||||||
return strSlcContains(ignoreSender, sender) ||
|
return strSlcContains(ignoreSender, sender) ||
|
||||||
strSlcContains(ignoreSummary, summary) ||
|
strSlcContains(ignoreSummary, summary) ||
|
||||||
strSlcContains(ignoreBody, body)
|
strSlcContains(ignoreBody, body)
|
||||||
|
|||||||
91
socket.go
91
socket.go
@@ -29,42 +29,26 @@ import (
|
|||||||
|
|
||||||
"github.com/mitchellh/mapstructure"
|
"github.com/mitchellh/mapstructure"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
|
"github.com/spf13/viper"
|
||||||
"go.arsenm.dev/infinitime"
|
"go.arsenm.dev/infinitime"
|
||||||
"go.arsenm.dev/itd/internal/types"
|
"go.arsenm.dev/itd/internal/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
const SockPath = "/tmp/itd/socket"
|
|
||||||
|
|
||||||
const (
|
|
||||||
ReqTypeHeartRate = "hrt"
|
|
||||||
ReqTypeBattLevel = "battlvl"
|
|
||||||
ReqTypeFwVersion = "fwver"
|
|
||||||
ReqTypeFwUpgrade = "fwupg"
|
|
||||||
ReqTypeBtAddress = "btaddr"
|
|
||||||
ReqTypeNotify = "notify"
|
|
||||||
ReqTypeSetTime = "settime"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
UpgradeTypeArchive = iota
|
|
||||||
UpgradeTypeFiles
|
|
||||||
)
|
|
||||||
|
|
||||||
func startSocket(dev *infinitime.Device) error {
|
func startSocket(dev *infinitime.Device) error {
|
||||||
// Make socket directory if non existant
|
// Make socket directory if non-existent
|
||||||
err := os.MkdirAll(filepath.Dir(SockPath), 0755)
|
err := os.MkdirAll(filepath.Dir(viper.GetString("socket.path")), 0755)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove old socket if it exists
|
// Remove old socket if it exists
|
||||||
err = os.RemoveAll(SockPath)
|
err = os.RemoveAll(viper.GetString("socket.path"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Listen on socket path
|
// Listen on socket path
|
||||||
ln, err := net.Listen("unix", SockPath)
|
ln, err := net.Listen("unix", viper.GetString("socket.path"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -83,7 +67,7 @@ func startSocket(dev *infinitime.Device) error {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
// Log socket start
|
// Log socket start
|
||||||
log.Info().Str("path", SockPath).Msg("Started control socket")
|
log.Info().Str("path", viper.GetString("socket.path")).Msg("Started control socket")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -108,7 +92,7 @@ func handleConnection(conn net.Conn, dev *infinitime.Device) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch req.Type {
|
switch req.Type {
|
||||||
case ReqTypeHeartRate:
|
case types.ReqTypeHeartRate:
|
||||||
// Get heart rate from watch
|
// Get heart rate from watch
|
||||||
heartRate, err := dev.HeartRate()
|
heartRate, err := dev.HeartRate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -119,7 +103,33 @@ func handleConnection(conn net.Conn, dev *infinitime.Device) {
|
|||||||
json.NewEncoder(conn).Encode(types.Response{
|
json.NewEncoder(conn).Encode(types.Response{
|
||||||
Value: heartRate,
|
Value: heartRate,
|
||||||
})
|
})
|
||||||
case ReqTypeBattLevel:
|
case types.ReqTypeWatchHeartRate:
|
||||||
|
heartRateCh, err := dev.WatchHeartRate()
|
||||||
|
if err != nil {
|
||||||
|
connErr(conn, err, "Error getting heart rate channel")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
for heartRate := range heartRateCh {
|
||||||
|
json.NewEncoder(conn).Encode(types.Response{
|
||||||
|
Value: heartRate,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
case types.ReqTypeWatchBattLevel:
|
||||||
|
battLevelCh, err := dev.WatchBatteryLevel()
|
||||||
|
if err != nil {
|
||||||
|
connErr(conn, err, "Error getting heart rate channel")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
for battLevel := range battLevelCh {
|
||||||
|
json.NewEncoder(conn).Encode(types.Response{
|
||||||
|
Value: battLevel,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
case types.ReqTypeBattLevel:
|
||||||
// Get battery level from watch
|
// Get battery level from watch
|
||||||
battLevel, err := dev.BatteryLevel()
|
battLevel, err := dev.BatteryLevel()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -130,7 +140,7 @@ func handleConnection(conn net.Conn, dev *infinitime.Device) {
|
|||||||
json.NewEncoder(conn).Encode(types.Response{
|
json.NewEncoder(conn).Encode(types.Response{
|
||||||
Value: battLevel,
|
Value: battLevel,
|
||||||
})
|
})
|
||||||
case ReqTypeFwVersion:
|
case types.ReqTypeFwVersion:
|
||||||
// Get firmware version from watch
|
// Get firmware version from watch
|
||||||
version, err := dev.Version()
|
version, err := dev.Version()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -141,22 +151,22 @@ func handleConnection(conn net.Conn, dev *infinitime.Device) {
|
|||||||
json.NewEncoder(conn).Encode(types.Response{
|
json.NewEncoder(conn).Encode(types.Response{
|
||||||
Value: version,
|
Value: version,
|
||||||
})
|
})
|
||||||
case ReqTypeBtAddress:
|
case types.ReqTypeBtAddress:
|
||||||
// Encode bluetooth address to connection
|
// Encode bluetooth address to connection
|
||||||
json.NewEncoder(conn).Encode(types.Response{
|
json.NewEncoder(conn).Encode(types.Response{
|
||||||
Value: dev.Address(),
|
Value: dev.Address(),
|
||||||
})
|
})
|
||||||
case ReqTypeNotify:
|
case types.ReqTypeNotify:
|
||||||
// If no data, return error
|
// If no data, return error
|
||||||
if req.Data == nil {
|
if req.Data == nil {
|
||||||
connErr(conn, nil, "Data required for notify types.Request")
|
connErr(conn, nil, "Data required for notify request")
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
var reqData types.ReqDataNotify
|
var reqData types.ReqDataNotify
|
||||||
// Decode data map to notify types.Request data
|
// Decode data map to notify request data
|
||||||
err = mapstructure.Decode(req.Data, &reqData)
|
err = mapstructure.Decode(req.Data, &reqData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
connErr(conn, err, "Error decoding types.Request data")
|
connErr(conn, err, "Error decoding request data")
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// Send notification to watch
|
// Send notification to watch
|
||||||
@@ -167,16 +177,16 @@ func handleConnection(conn net.Conn, dev *infinitime.Device) {
|
|||||||
}
|
}
|
||||||
// Encode empty types.Response to connection
|
// Encode empty types.Response to connection
|
||||||
json.NewEncoder(conn).Encode(types.Response{})
|
json.NewEncoder(conn).Encode(types.Response{})
|
||||||
case ReqTypeSetTime:
|
case types.ReqTypeSetTime:
|
||||||
// If no data, return error
|
// If no data, return error
|
||||||
if req.Data == nil {
|
if req.Data == nil {
|
||||||
connErr(conn, nil, "Data required for settime types.Request")
|
connErr(conn, nil, "Data required for settime request")
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// Get string from data or return error
|
// Get string from data or return error
|
||||||
reqTimeStr, ok := req.Data.(string)
|
reqTimeStr, ok := req.Data.(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
connErr(conn, nil, "Data for settime types.Request must be RFC3339 formatted time string")
|
connErr(conn, nil, "Data for settime request must be RFC3339 formatted time string")
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,7 +194,7 @@ func handleConnection(conn net.Conn, dev *infinitime.Device) {
|
|||||||
if reqTimeStr == "now" {
|
if reqTimeStr == "now" {
|
||||||
reqTime = time.Now()
|
reqTime = time.Now()
|
||||||
} else {
|
} else {
|
||||||
// Parse time as RFC3339/ISO9601
|
// Parse time as RFC3339/ISO8601
|
||||||
reqTime, err = time.Parse(time.RFC3339, reqTimeStr)
|
reqTime, err = time.Parse(time.RFC3339, reqTimeStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
connErr(conn, err, "Invalid time format. Time string must be formatted as ISO8601 or the word `now`")
|
connErr(conn, err, "Invalid time format. Time string must be formatted as ISO8601 or the word `now`")
|
||||||
@@ -199,21 +209,21 @@ func handleConnection(conn net.Conn, dev *infinitime.Device) {
|
|||||||
}
|
}
|
||||||
// Encode empty types.Response to connection
|
// Encode empty types.Response to connection
|
||||||
json.NewEncoder(conn).Encode(types.Response{})
|
json.NewEncoder(conn).Encode(types.Response{})
|
||||||
case ReqTypeFwUpgrade:
|
case types.ReqTypeFwUpgrade:
|
||||||
// If no data, return error
|
// If no data, return error
|
||||||
if req.Data == nil {
|
if req.Data == nil {
|
||||||
connErr(conn, nil, "Data required for firmware upgrade types.Request")
|
connErr(conn, nil, "Data required for firmware upgrade request")
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
var reqData types.ReqDataFwUpgrade
|
var reqData types.ReqDataFwUpgrade
|
||||||
// Decode data map to firmware upgrade types.Request data
|
// Decode data map to firmware upgrade request data
|
||||||
err = mapstructure.Decode(req.Data, &reqData)
|
err = mapstructure.Decode(req.Data, &reqData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
connErr(conn, err, "Error decoding types.Request data")
|
connErr(conn, err, "Error decoding request data")
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
switch reqData.Type {
|
switch reqData.Type {
|
||||||
case UpgradeTypeArchive:
|
case types.UpgradeTypeArchive:
|
||||||
// If less than one file, return error
|
// If less than one file, return error
|
||||||
if len(reqData.Files) < 1 {
|
if len(reqData.Files) < 1 {
|
||||||
connErr(conn, nil, "Archive upgrade requires one file with .zip extension")
|
connErr(conn, nil, "Archive upgrade requires one file with .zip extension")
|
||||||
@@ -230,7 +240,7 @@ func handleConnection(conn net.Conn, dev *infinitime.Device) {
|
|||||||
connErr(conn, err, "Error loading archive file")
|
connErr(conn, err, "Error loading archive file")
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case UpgradeTypeFiles:
|
case types.UpgradeTypeFiles:
|
||||||
// If less than two files, return error
|
// If less than two files, return error
|
||||||
if len(reqData.Files) < 2 {
|
if len(reqData.Files) < 2 {
|
||||||
connErr(conn, nil, "Files upgrade requires two files. First with .dat and second with .bin extension.")
|
connErr(conn, nil, "Files upgrade requires two files. First with .dat and second with .bin extension.")
|
||||||
@@ -272,6 +282,7 @@ func handleConnection(conn net.Conn, dev *infinitime.Device) {
|
|||||||
err = dev.DFU.Start()
|
err = dev.DFU.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
connErr(conn, err, "Error performing upgrade")
|
connErr(conn, err, "Error performing upgrade")
|
||||||
|
firmwareUpdating = false
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
firmwareUpdating = false
|
firmwareUpdating = false
|
||||||
|
|||||||
Reference in New Issue
Block a user