Switch to autogenerated DRPC framework
This commit is contained in:
29
api/api.go
29
api/api.go
@@ -4,14 +4,15 @@ import (
|
||||
"io"
|
||||
"net"
|
||||
|
||||
"go.arsenm.dev/lrpc/client"
|
||||
"go.arsenm.dev/lrpc/codec"
|
||||
"go.arsenm.dev/itd/internal/rpc"
|
||||
"storj.io/drpc/drpcconn"
|
||||
)
|
||||
|
||||
const DefaultAddr = "/tmp/itd/socket"
|
||||
|
||||
type Client struct {
|
||||
client *client.Client
|
||||
conn *drpcconn.Conn
|
||||
client rpc.DRPCITDClient
|
||||
}
|
||||
|
||||
func New(sockPath string) (*Client, error) {
|
||||
@@ -19,19 +20,27 @@ func New(sockPath string) (*Client, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dconn := drpcconn.New(conn)
|
||||
|
||||
out := &Client{
|
||||
client: client.New(conn, codec.Default),
|
||||
}
|
||||
return out, nil
|
||||
return &Client{
|
||||
conn: dconn,
|
||||
client: rpc.NewDRPCITDClient(dconn),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func NewFromConn(conn io.ReadWriteCloser) *Client {
|
||||
dconn := drpcconn.New(conn)
|
||||
|
||||
return &Client{
|
||||
client: client.New(conn, codec.Default),
|
||||
conn: dconn,
|
||||
client: rpc.NewDRPCITDClient(dconn),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) Close() error {
|
||||
return c.client.Close()
|
||||
func (c *Client) FS() *FSClient {
|
||||
return &FSClient{rpc.NewDRPCFSClient(c.conn)}
|
||||
}
|
||||
|
||||
func (c *Client) Close() error {
|
||||
return c.conn.Close()
|
||||
}
|
||||
|
||||
@@ -3,24 +3,34 @@ package api
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go.arsenm.dev/infinitime"
|
||||
"go.arsenm.dev/itd/internal/rpc"
|
||||
)
|
||||
|
||||
func (c *Client) FirmwareUpgrade(ctx context.Context, upgType UpgradeType, files ...string) (chan infinitime.DFUProgress, error) {
|
||||
progressCh := make(chan infinitime.DFUProgress, 5)
|
||||
err := c.client.Call(
|
||||
ctx,
|
||||
"ITD",
|
||||
"FirmwareUpgrade",
|
||||
FwUpgradeData{
|
||||
Type: upgType,
|
||||
Files: files,
|
||||
},
|
||||
progressCh,
|
||||
)
|
||||
type DFUProgress struct {
|
||||
Sent int64
|
||||
Received int64
|
||||
Total int64
|
||||
Err error
|
||||
}
|
||||
|
||||
func (c *Client) FirmwareUpgrade(ctx context.Context, upgType UpgradeType, files ...string) (chan DFUProgress, error) {
|
||||
progressCh := make(chan DFUProgress, 5)
|
||||
fc, err := c.client.FirmwareUpgrade(ctx, &rpc.FirmwareUpgradeRequest{
|
||||
Type: rpc.FirmwareUpgradeRequest_Type(upgType),
|
||||
Files: files,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
go fsRecvToChannel[rpc.DFUProgress](fc, progressCh, func(evt *rpc.DFUProgress, err error) DFUProgress {
|
||||
return DFUProgress{
|
||||
Sent: evt.Sent,
|
||||
Received: evt.Recieved,
|
||||
Total: evt.Total,
|
||||
Err: err,
|
||||
}
|
||||
})
|
||||
|
||||
return progressCh, nil
|
||||
}
|
||||
|
||||
155
api/fs.go
155
api/fs.go
@@ -1,96 +1,119 @@
|
||||
package api
|
||||
|
||||
import "context"
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
|
||||
func (c *Client) RemoveAll(ctx context.Context, paths ...string) error {
|
||||
return c.client.Call(
|
||||
ctx,
|
||||
"FS",
|
||||
"RemoveAll",
|
||||
paths,
|
||||
nil,
|
||||
)
|
||||
"go.arsenm.dev/itd/internal/rpc"
|
||||
)
|
||||
|
||||
type FSClient struct {
|
||||
client rpc.DRPCFSClient
|
||||
}
|
||||
|
||||
func (c *Client) Remove(ctx context.Context, paths ...string) error {
|
||||
return c.client.Call(
|
||||
ctx,
|
||||
"FS",
|
||||
"Remove",
|
||||
paths,
|
||||
nil,
|
||||
)
|
||||
func (c *FSClient) RemoveAll(ctx context.Context, paths ...string) error {
|
||||
_, err := c.client.RemoveAll(ctx, &rpc.PathsRequest{Paths: paths})
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Client) Rename(ctx context.Context, old, new string) error {
|
||||
return c.client.Call(
|
||||
ctx,
|
||||
"FS",
|
||||
"Rename",
|
||||
[2]string{old, new},
|
||||
nil,
|
||||
)
|
||||
func (c *FSClient) Remove(ctx context.Context, paths ...string) error {
|
||||
_, err := c.client.Remove(ctx, &rpc.PathsRequest{Paths: paths})
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Client) MkdirAll(ctx context.Context, paths ...string) error {
|
||||
return c.client.Call(
|
||||
ctx,
|
||||
"FS",
|
||||
"MkdirAll",
|
||||
paths,
|
||||
nil,
|
||||
)
|
||||
func (c *FSClient) Rename(ctx context.Context, old, new string) error {
|
||||
_, err := c.client.Rename(ctx, &rpc.RenameRequest{
|
||||
From: old,
|
||||
To: new,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Client) Mkdir(ctx context.Context, paths ...string) error {
|
||||
return c.client.Call(
|
||||
ctx,
|
||||
"FS",
|
||||
"Mkdir",
|
||||
paths,
|
||||
nil,
|
||||
)
|
||||
func (c *FSClient) MkdirAll(ctx context.Context, paths ...string) error {
|
||||
_, err := c.client.MkdirAll(ctx, &rpc.PathsRequest{Paths: paths})
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Client) ReadDir(ctx context.Context, dir string) (out []FileInfo, err error) {
|
||||
err = c.client.Call(
|
||||
ctx,
|
||||
"FS",
|
||||
"ReadDir",
|
||||
dir,
|
||||
&out,
|
||||
)
|
||||
return
|
||||
func (c *FSClient) Mkdir(ctx context.Context, paths ...string) error {
|
||||
_, err := c.client.Mkdir(ctx, &rpc.PathsRequest{Paths: paths})
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Client) Upload(ctx context.Context, dst, src string) (chan FSTransferProgress, error) {
|
||||
func (c *FSClient) ReadDir(ctx context.Context, dir string) ([]FileInfo, error) {
|
||||
res, err := c.client.ReadDir(ctx, &rpc.PathRequest{Path: dir})
|
||||
return convertEntries(res.Entries), err
|
||||
}
|
||||
|
||||
func convertEntries(e []*rpc.FileInfo) []FileInfo {
|
||||
out := make([]FileInfo, len(e))
|
||||
for i, fi := range e {
|
||||
out[i] = FileInfo{
|
||||
Name: fi.Name,
|
||||
Size: fi.Size,
|
||||
IsDir: fi.IsDir,
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (c *FSClient) Upload(ctx context.Context, dst, src string) (chan FSTransferProgress, error) {
|
||||
progressCh := make(chan FSTransferProgress, 5)
|
||||
err := c.client.Call(
|
||||
ctx,
|
||||
"FS",
|
||||
"Upload",
|
||||
[2]string{dst, src},
|
||||
progressCh,
|
||||
)
|
||||
tc, err := c.client.Upload(ctx, &rpc.TransferRequest{Source: src, Destination: dst})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
go fsRecvToChannel[rpc.TransferProgress](tc, progressCh, func(evt *rpc.TransferProgress, err error) FSTransferProgress {
|
||||
return FSTransferProgress{
|
||||
Sent: evt.Sent,
|
||||
Total: evt.Total,
|
||||
Err: err,
|
||||
}
|
||||
})
|
||||
|
||||
return progressCh, nil
|
||||
}
|
||||
|
||||
func (c *Client) Download(ctx context.Context, dst, src string) (chan FSTransferProgress, error) {
|
||||
func (c *FSClient) Download(ctx context.Context, dst, src string) (chan FSTransferProgress, error) {
|
||||
progressCh := make(chan FSTransferProgress, 5)
|
||||
err := c.client.Call(
|
||||
ctx,
|
||||
"FS",
|
||||
"Download",
|
||||
[2]string{dst, src},
|
||||
progressCh,
|
||||
)
|
||||
tc, err := c.client.Download(ctx, &rpc.TransferRequest{Source: src, Destination: dst})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
go fsRecvToChannel[rpc.TransferProgress](tc, progressCh, func(evt *rpc.TransferProgress, err error) FSTransferProgress {
|
||||
return FSTransferProgress{
|
||||
Sent: evt.Sent,
|
||||
Total: evt.Total,
|
||||
Err: err,
|
||||
}
|
||||
})
|
||||
|
||||
return progressCh, nil
|
||||
}
|
||||
|
||||
// fsRecvToChannel converts a DRPC stream client to a Go channel, using cf to convert
|
||||
// RPC generated types to API response types.
|
||||
func fsRecvToChannel[R any, A any](s StreamClient[R], ch chan<- A, cf func(evt *R, err error) A) {
|
||||
defer close(ch)
|
||||
|
||||
var err error
|
||||
var evt *R
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-s.Context().Done():
|
||||
return
|
||||
default:
|
||||
evt, err = s.Recv()
|
||||
if errors.Is(err, io.EOF) {
|
||||
return
|
||||
} else if err != nil {
|
||||
ch <- cf(new(R), err)
|
||||
return
|
||||
}
|
||||
ch <- cf(evt, nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
72
api/get.go
72
api/get.go
@@ -3,71 +3,39 @@ package api
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go.arsenm.dev/infinitime"
|
||||
"go.arsenm.dev/itd/internal/rpc"
|
||||
)
|
||||
|
||||
func (c *Client) HeartRate(ctx context.Context) (out uint8, err error) {
|
||||
err = c.client.Call(
|
||||
ctx,
|
||||
"ITD",
|
||||
"HeartRate",
|
||||
nil,
|
||||
&out,
|
||||
)
|
||||
return
|
||||
func (c *Client) HeartRate(ctx context.Context) (uint8, error) {
|
||||
res, err := c.client.HeartRate(ctx, &rpc.Empty{})
|
||||
return uint8(res.Value), err
|
||||
}
|
||||
|
||||
func (c *Client) BatteryLevel(ctx context.Context) (out uint8, err error) {
|
||||
err = c.client.Call(
|
||||
ctx,
|
||||
"ITD",
|
||||
"BatteryLevel",
|
||||
nil,
|
||||
&out,
|
||||
)
|
||||
return
|
||||
func (c *Client) BatteryLevel(ctx context.Context) (uint8, error) {
|
||||
res, err := c.client.BatteryLevel(ctx, &rpc.Empty{})
|
||||
return uint8(res.Value), err
|
||||
}
|
||||
|
||||
func (c *Client) Motion(ctx context.Context) (out infinitime.MotionValues, err error) {
|
||||
err = c.client.Call(
|
||||
ctx,
|
||||
"ITD",
|
||||
"Motion",
|
||||
nil,
|
||||
&out,
|
||||
)
|
||||
return
|
||||
type MotionValues struct {
|
||||
X, Y, Z int16
|
||||
}
|
||||
|
||||
func (c *Client) Motion(ctx context.Context) (MotionValues, error) {
|
||||
res, err := c.client.Motion(ctx, &rpc.Empty{})
|
||||
return MotionValues{int16(res.X), int16(res.Y), int16(res.Z)}, err
|
||||
}
|
||||
|
||||
func (c *Client) StepCount(ctx context.Context) (out uint32, err error) {
|
||||
err = c.client.Call(
|
||||
ctx,
|
||||
"ITD",
|
||||
"StepCount",
|
||||
nil,
|
||||
&out,
|
||||
)
|
||||
return
|
||||
res, err := c.client.StepCount(ctx, &rpc.Empty{})
|
||||
return res.Value, err
|
||||
}
|
||||
|
||||
func (c *Client) Version(ctx context.Context) (out string, err error) {
|
||||
err = c.client.Call(
|
||||
ctx,
|
||||
"ITD",
|
||||
"Version",
|
||||
nil,
|
||||
&out,
|
||||
)
|
||||
return
|
||||
res, err := c.client.Version(ctx, &rpc.Empty{})
|
||||
return res.Value, err
|
||||
}
|
||||
|
||||
func (c *Client) Address(ctx context.Context) (out string, err error) {
|
||||
err = c.client.Call(
|
||||
ctx,
|
||||
"ITD",
|
||||
"Address",
|
||||
nil,
|
||||
&out,
|
||||
)
|
||||
return
|
||||
res, err := c.client.Address(ctx, &rpc.Empty{})
|
||||
return res.Value, err
|
||||
}
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
package api
|
||||
|
||||
import "context"
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go.arsenm.dev/itd/internal/rpc"
|
||||
)
|
||||
|
||||
func (c *Client) Notify(ctx context.Context, title, body string) error {
|
||||
return c.client.Call(
|
||||
ctx,
|
||||
"ITD",
|
||||
"Notify",
|
||||
NotifyData{
|
||||
Title: title,
|
||||
Body: body,
|
||||
},
|
||||
nil,
|
||||
)
|
||||
_, err := c.client.Notify(ctx, &rpc.NotifyRequest{
|
||||
Title: title,
|
||||
Body: body,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -4,23 +4,48 @@ import (
|
||||
"context"
|
||||
|
||||
"go.arsenm.dev/infinitime"
|
||||
"go.arsenm.dev/itd/internal/rpc"
|
||||
)
|
||||
|
||||
type ResourceOperation uint8
|
||||
|
||||
const (
|
||||
ResourceOperationRemoveObsolete = infinitime.ResourceOperationRemoveObsolete
|
||||
ResourceOperationUpload = infinitime.ResourceOperationUpload
|
||||
)
|
||||
|
||||
type ResourceLoadProgress struct {
|
||||
Operation ResourceOperation
|
||||
Name string
|
||||
Total int64
|
||||
Sent int64
|
||||
Err error
|
||||
}
|
||||
|
||||
// LoadResources loads resources onto the watch from the given
|
||||
// file path to the resources zip
|
||||
func (c *Client) LoadResources(ctx context.Context, path string) (<-chan infinitime.ResourceLoadProgress, error) {
|
||||
progCh := make(chan infinitime.ResourceLoadProgress)
|
||||
func (c *FSClient) LoadResources(ctx context.Context, path string) (<-chan ResourceLoadProgress, error) {
|
||||
progCh := make(chan ResourceLoadProgress, 2)
|
||||
|
||||
err := c.client.Call(
|
||||
ctx,
|
||||
"FS",
|
||||
"LoadResources",
|
||||
path,
|
||||
progCh,
|
||||
)
|
||||
rc, err := c.client.LoadResources(ctx, &rpc.PathRequest{Path: path})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
go fsRecvToChannel[rpc.ResourceLoadProgress](rc, progCh, func(evt *rpc.ResourceLoadProgress, err error) ResourceLoadProgress {
|
||||
return ResourceLoadProgress{
|
||||
Operation: ResourceOperation(evt.Operation),
|
||||
Name: evt.Name,
|
||||
Sent: evt.Sent,
|
||||
Total: evt.Total,
|
||||
Err: err,
|
||||
}
|
||||
})
|
||||
|
||||
return progCh, nil
|
||||
}
|
||||
|
||||
type StreamClient[T any] interface {
|
||||
Recv() (*T, error)
|
||||
Context() context.Context
|
||||
}
|
||||
|
||||
11
api/set.go
11
api/set.go
@@ -3,14 +3,11 @@ package api
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"go.arsenm.dev/itd/internal/rpc"
|
||||
)
|
||||
|
||||
func (c *Client) SetTime(ctx context.Context, t time.Time) error {
|
||||
return c.client.Call(
|
||||
ctx,
|
||||
"ITD",
|
||||
"SetTime",
|
||||
t,
|
||||
nil,
|
||||
)
|
||||
_, err := c.client.SetTime(ctx, &rpc.SetTimeRequest{UnixNano: t.UnixNano()})
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ type NotifyData struct {
|
||||
type FSTransferProgress struct {
|
||||
Total uint32
|
||||
Sent uint32
|
||||
Err error
|
||||
}
|
||||
|
||||
type FileInfo struct {
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
package api
|
||||
|
||||
import "context"
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go.arsenm.dev/itd/internal/rpc"
|
||||
)
|
||||
|
||||
func (c *Client) WeatherUpdate(ctx context.Context) error {
|
||||
return c.client.Call(
|
||||
ctx,
|
||||
"ITD",
|
||||
"WeatherUpdate",
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
_, err := c.client.WeatherUpdate(ctx, &rpc.Empty{})
|
||||
return err
|
||||
}
|
||||
|
||||
126
api/watch.go
126
api/watch.go
@@ -3,69 +3,133 @@ package api
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go.arsenm.dev/infinitime"
|
||||
"go.arsenm.dev/itd/internal/rpc"
|
||||
)
|
||||
|
||||
func (c *Client) WatchHeartRate(ctx context.Context) (<-chan uint8, error) {
|
||||
outCh := make(chan uint8, 2)
|
||||
err := c.client.Call(
|
||||
ctx,
|
||||
"ITD",
|
||||
"WatchHeartRate",
|
||||
nil,
|
||||
outCh,
|
||||
)
|
||||
wc, err := c.client.WatchHeartRate(ctx, &rpc.Empty{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
go func() {
|
||||
defer close(outCh)
|
||||
|
||||
var err error
|
||||
var evt *rpc.IntResponse
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
wc.Close()
|
||||
return
|
||||
default:
|
||||
evt, err = wc.Recv()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
outCh <- uint8(evt.Value)
|
||||
}
|
||||
}()
|
||||
|
||||
return outCh, nil
|
||||
}
|
||||
|
||||
func (c *Client) WatchBatteryLevel(ctx context.Context) (<-chan uint8, error) {
|
||||
outCh := make(chan uint8, 2)
|
||||
err := c.client.Call(
|
||||
ctx,
|
||||
"ITD",
|
||||
"WatchBatteryLevel",
|
||||
nil,
|
||||
outCh,
|
||||
)
|
||||
wc, err := c.client.WatchBatteryLevel(ctx, &rpc.Empty{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
go func() {
|
||||
defer close(outCh)
|
||||
|
||||
var err error
|
||||
var evt *rpc.IntResponse
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
wc.Close()
|
||||
return
|
||||
default:
|
||||
evt, err = wc.Recv()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
outCh <- uint8(evt.Value)
|
||||
}
|
||||
}()
|
||||
|
||||
return outCh, nil
|
||||
}
|
||||
|
||||
func (c *Client) WatchStepCount(ctx context.Context) (<-chan uint32, error) {
|
||||
outCh := make(chan uint32, 2)
|
||||
err := c.client.Call(
|
||||
ctx,
|
||||
"ITD",
|
||||
"WatchStepCount",
|
||||
nil,
|
||||
outCh,
|
||||
)
|
||||
wc, err := c.client.WatchStepCount(ctx, &rpc.Empty{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
go func() {
|
||||
defer close(outCh)
|
||||
|
||||
var err error
|
||||
var evt *rpc.IntResponse
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
wc.Close()
|
||||
return
|
||||
default:
|
||||
evt, err = wc.Recv()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
outCh <- evt.Value
|
||||
}
|
||||
}()
|
||||
|
||||
return outCh, nil
|
||||
}
|
||||
|
||||
func (c *Client) WatchMotion(ctx context.Context) (<-chan infinitime.MotionValues, error) {
|
||||
outCh := make(chan infinitime.MotionValues, 2)
|
||||
err := c.client.Call(
|
||||
ctx,
|
||||
"ITD",
|
||||
"WatchMotion",
|
||||
nil,
|
||||
outCh,
|
||||
)
|
||||
func (c *Client) WatchMotion(ctx context.Context) (<-chan MotionValues, error) {
|
||||
outCh := make(chan MotionValues, 2)
|
||||
wc, err := c.client.WatchMotion(ctx, &rpc.Empty{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
go func() {
|
||||
defer close(outCh)
|
||||
|
||||
var err error
|
||||
var evt *rpc.MotionResponse
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
wc.Close()
|
||||
return
|
||||
default:
|
||||
evt, err = wc.Recv()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
outCh <- MotionValues{int16(evt.X), int16(evt.Y), int16(evt.Z)}
|
||||
}
|
||||
}()
|
||||
|
||||
return outCh, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user