From 2e8c825fffbba8236e7ae3ad9607f89939a840dc Mon Sep 17 00:00:00 2001 From: Arsen Musayelyan Date: Tue, 23 Nov 2021 11:12:16 -0800 Subject: [PATCH] Add BLE FS to API package --- api/fs.go | 95 +++++++++++++++++++++++++++++++++++++++++ internal/types/types.go | 75 +++++++++++++++++++++++++++++--- 2 files changed, 163 insertions(+), 7 deletions(-) create mode 100644 api/fs.go diff --git a/api/fs.go b/api/fs.go new file mode 100644 index 0000000..6ba210f --- /dev/null +++ b/api/fs.go @@ -0,0 +1,95 @@ +package api + +import ( + "github.com/mitchellh/mapstructure" + "go.arsenm.dev/itd/internal/types" +) + +func (c *Client) Rename(old, new string) error { + _, err := c.request(types.Request{ + Type: types.ReqTypeFS, + Data: types.ReqDataFS{ + Type: types.FSTypeMove, + Files: []string{old, new}, + }, + }) + if err != nil { + return err + } + return nil +} + +func (c *Client) Remove(path string) error { + _, err := c.request(types.Request{ + Type: types.ReqTypeFS, + Data: types.ReqDataFS{ + Type: types.FSTypeDelete, + Files: []string{path}, + }, + }) + if err != nil { + return err + } + return nil +} + +func (c *Client) Mkdir(path string) error { + _, err := c.request(types.Request{ + Type: types.ReqTypeFS, + Data: types.ReqDataFS{ + Type: types.FSTypeMkdir, + Files: []string{path}, + }, + }) + if err != nil { + return err + } + return nil +} + +func (c *Client) ReadDir(path string) ([]types.FileInfo, error) { + res, err := c.request(types.Request{ + Type: types.ReqTypeFS, + Data: types.ReqDataFS{ + Type: types.FSTypeList, + Files: []string{path}, + }, + }) + if err != nil { + return nil, err + } + var out []types.FileInfo + err = mapstructure.Decode(res.Value, &out) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *Client) ReadFile(path string) (string, error) { + res, err := c.request(types.Request{ + Type: types.ReqTypeFS, + Data: types.ReqDataFS{ + Type: types.FSTypeRead, + Files: []string{path}, + }, + }) + if err != nil { + return "", err + } + return res.Value.(string), nil +} + +func (c *Client) WriteFile(path, data string) error { + _, err := c.request(types.Request{ + Type: types.ReqTypeFS, + Data: types.ReqDataFS{ + Type: types.FSTypeRead, + Files: []string{path}, + }, + }) + if err != nil { + return err + } + return nil +} diff --git a/internal/types/types.go b/internal/types/types.go index 5268b28..54a8e53 100644 --- a/internal/types/types.go +++ b/internal/types/types.go @@ -1,5 +1,10 @@ package types +import ( + "fmt" + "strconv" +) + const ( ReqTypeHeartRate = iota ReqTypeBattLevel @@ -33,9 +38,9 @@ const ( ) type ReqDataFS struct { - Type int `json:"type"` + Type int `json:"type"` Files []string `json:"files"` - Data string `json:"data,omitempty"` + Data string `json:"data,omitempty"` } type ReqDataFwUpgrade struct { @@ -74,8 +79,64 @@ type MotionValues struct { } type FileInfo struct { - Name string `json:"name"` - Size int64 `json:"size"` - IsDir bool `json:"isDir"` - -} \ No newline at end of file + Name string `json:"name"` + Size int64 `json:"size"` + IsDir bool `json:"isDir"` +} + +func (fi FileInfo) String() string { + var isDirChar rune + if fi.IsDir { + isDirChar = 'd' + } else { + isDirChar = '-' + } + + // Get human-readable value for file size + val, unit := bytesHuman(fi.Size) + prec := 0 + // If value is less than 10, set precision to 1 + if val < 10 { + prec = 1 + } + // Convert float to string + valStr := strconv.FormatFloat(val, 'f', prec, 64) + + // Return string formatted like so: + // - 10 kB file + // or: + // d 0 B . + return fmt.Sprintf( + "%c %3s %-2s %s", + isDirChar, + valStr, + unit, + fi.Name, + ) +} + +// bytesHuman returns a human-readable string for +// the amount of bytes inputted. +func bytesHuman(b int64) (float64, string) { + const unit = 1000 + // Set possible units prefixes (PineTime flash is 4MB) + units := [2]rune{'k', 'M'} + // If amount of bytes is less than smallest unit + if b < unit { + // Return unchanged with unit "B" + return float64(b), "B" + } + + div, exp := int64(unit), 0 + // Get decimal values and unit prefix index + for n := b / unit; n >= unit; n /= unit { + div *= unit + exp++ + } + + // Create string for full unit + unitStr := string([]rune{units[exp], 'B'}) + + // Return decimal with unit string + return float64(b) / float64(div), unitStr +}