forked from Elara6331/itd
		
	Send response types in socket responses and create api package
This commit is contained in:
		
							
								
								
									
										102
									
								
								api/client.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								api/client.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,102 @@ | ||||
| package api | ||||
|  | ||||
| import ( | ||||
| 	"bufio" | ||||
| 	"encoding/json" | ||||
| 	"errors" | ||||
| 	"net" | ||||
|  | ||||
| 	"github.com/mitchellh/mapstructure" | ||||
| 	"go.arsenm.dev/infinitime" | ||||
| 	"go.arsenm.dev/itd/internal/types" | ||||
| ) | ||||
|  | ||||
| const DefaultAddr = "/tmp/itd/socket" | ||||
|  | ||||
| type Client struct { | ||||
| 	conn          net.Conn | ||||
| 	respCh        chan types.Response | ||||
| 	heartRateCh   chan uint8 | ||||
| 	battLevelCh   chan uint8 | ||||
| 	stepCountCh   chan uint32 | ||||
| 	motionCh      chan infinitime.MotionValues | ||||
| 	dfuProgressCh chan DFUProgress | ||||
| } | ||||
|  | ||||
| func New(addr string) (*Client, error) { | ||||
| 	conn, err := net.Dial("unix", addr) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	out := &Client{ | ||||
| 		conn:   conn, | ||||
| 		respCh: make(chan types.Response, 5), | ||||
| 	} | ||||
|  | ||||
| 	go func() { | ||||
| 		scanner := bufio.NewScanner(conn) | ||||
| 		for scanner.Scan() { | ||||
| 			var res types.Response | ||||
| 			err = json.Unmarshal(scanner.Bytes(), &res) | ||||
| 			if err != nil { | ||||
| 				continue | ||||
| 			} | ||||
| 			out.handleResp(res) | ||||
| 		} | ||||
| 	}() | ||||
| 	return out, err | ||||
| } | ||||
|  | ||||
| func (c *Client) request(req types.Request) (types.Response, error) { | ||||
| 	// Encode request into connection | ||||
| 	err := json.NewEncoder(c.conn).Encode(req) | ||||
| 	if err != nil { | ||||
| 		return types.Response{}, err | ||||
| 	} | ||||
|  | ||||
| 	res := <-c.respCh | ||||
|  | ||||
| 	if res.Error { | ||||
| 		return res, errors.New(res.Message) | ||||
| 	} | ||||
|  | ||||
| 	return res, nil | ||||
| } | ||||
|  | ||||
| func (c *Client) requestNoRes(req types.Request) error { | ||||
| 	// Encode request into connection | ||||
| 	err := json.NewEncoder(c.conn).Encode(req) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (c *Client) handleResp(res types.Response) error { | ||||
| 	switch res.Type { | ||||
| 	case types.ResTypeWatchHeartRate: | ||||
| 		c.heartRateCh <- uint8(res.Value.(float64)) | ||||
| 	case types.ResTypeWatchBattLevel: | ||||
| 		c.battLevelCh <- uint8(res.Value.(float64)) | ||||
| 	case types.ResTypeWatchStepCount: | ||||
| 		c.stepCountCh <- uint32(res.Value.(float64)) | ||||
| 	case types.ResTypeWatchMotion: | ||||
| 		out := infinitime.MotionValues{} | ||||
| 		err := mapstructure.Decode(res.Value, &out) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		c.motionCh <- out | ||||
| 	case types.ResTypeDFUProgress: | ||||
| 		out := DFUProgress{} | ||||
| 		err := mapstructure.Decode(res.Value, &out) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		c.dfuProgressCh <- out | ||||
| 	default: | ||||
| 		c.respCh <- res | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										121
									
								
								api/info.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								api/info.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,121 @@ | ||||
| package api | ||||
|  | ||||
| import ( | ||||
| 	"github.com/mitchellh/mapstructure" | ||||
| 	"go.arsenm.dev/infinitime" | ||||
| 	"go.arsenm.dev/itd/internal/types" | ||||
| ) | ||||
|  | ||||
| func (c *Client) Address() (string, error) { | ||||
| 	res, err := c.request(types.Request{ | ||||
| 		Type: types.ReqTypeBtAddress, | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
|  | ||||
| 	return res.Value.(string), nil | ||||
| } | ||||
|  | ||||
| func (c *Client) Version() (string, error) { | ||||
| 	res, err := c.request(types.Request{ | ||||
| 		Type: types.ReqTypeFwVersion, | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
|  | ||||
| 	return res.Value.(string), nil | ||||
| } | ||||
|  | ||||
| func (c *Client) BatteryLevel() (uint8, error) { | ||||
| 	res, err := c.request(types.Request{ | ||||
| 		Type: types.ReqTypeBattLevel, | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		return 0, err | ||||
| 	} | ||||
|  | ||||
| 	return uint8(res.Value.(float64)), nil | ||||
| } | ||||
|  | ||||
| func (c *Client) WatchBatteryLevel() (<-chan uint8, error) { | ||||
| 	c.battLevelCh = make(chan uint8, 2) | ||||
| 	err := c.requestNoRes(types.Request{ | ||||
| 		Type: types.ReqTypeBattLevel, | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return c.battLevelCh, nil | ||||
| } | ||||
|  | ||||
| func (c *Client) HeartRate() (uint8, error) { | ||||
| 	res, err := c.request(types.Request{ | ||||
| 		Type: types.ReqTypeHeartRate, | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		return 0, err | ||||
| 	} | ||||
|  | ||||
| 	return uint8(res.Value.(float64)), nil | ||||
| } | ||||
|  | ||||
| func (c *Client) WatchHeartRate() (<-chan uint8, error) { | ||||
| 	c.heartRateCh = make(chan uint8, 2) | ||||
| 	err := c.requestNoRes(types.Request{ | ||||
| 		Type: types.ReqTypeWatchHeartRate, | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return c.heartRateCh, nil | ||||
| } | ||||
|  | ||||
| func (c *Client) StepCount() (uint32, error) { | ||||
| 	res, err := c.request(types.Request{ | ||||
| 		Type: types.ReqTypeStepCount, | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		return 0, err | ||||
| 	} | ||||
|  | ||||
| 	return uint32(res.Value.(float64)), nil | ||||
| } | ||||
|  | ||||
| func (c *Client) WatchStepCount() (<-chan uint32, error) { | ||||
| 	c.stepCountCh = make(chan uint32, 2) | ||||
| 	err := c.requestNoRes(types.Request{ | ||||
| 		Type: types.ReqTypeWatchStepCount, | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return c.stepCountCh, nil | ||||
| } | ||||
|  | ||||
| func (c *Client) Motion() (infinitime.MotionValues, error) { | ||||
| 	out := infinitime.MotionValues{} | ||||
| 	res, err := c.request(types.Request{ | ||||
| 		Type: types.ReqTypeMotion, | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		return out, err | ||||
| 	} | ||||
| 	err = mapstructure.Decode(res.Value, &out) | ||||
| 	if err != nil { | ||||
| 		return out, err | ||||
| 	} | ||||
| 	return out, nil | ||||
| } | ||||
|  | ||||
| func (c *Client) WatchMotion() (<-chan infinitime.MotionValues, error) { | ||||
| 	c.motionCh = make(chan infinitime.MotionValues, 2) | ||||
| 	err := c.requestNoRes(types.Request{ | ||||
| 		Type: types.ReqTypeWatchMotion, | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return c.motionCh, nil | ||||
| } | ||||
							
								
								
									
										29
									
								
								api/time.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								api/time.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| package api | ||||
|  | ||||
| import ( | ||||
| 	"time" | ||||
|  | ||||
| 	"go.arsenm.dev/itd/internal/types" | ||||
| ) | ||||
|  | ||||
| func (c *Client) SetTime(t time.Time) error { | ||||
| 	_, err := c.request(types.Request{ | ||||
| 		Type: types.ReqTypeSetTime, | ||||
| 		Data: t.Format(time.RFC3339), | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (c *Client) SetTimeNow() error { | ||||
| 	_, err := c.request(types.Request{ | ||||
| 		Type: types.ReqTypeSetTime, | ||||
| 		Data: "now", | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										33
									
								
								api/upgrade.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								api/upgrade.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| package api | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
|  | ||||
| 	"go.arsenm.dev/itd/internal/types" | ||||
| ) | ||||
|  | ||||
| type DFUProgress types.DFUProgress | ||||
|  | ||||
| type UpgradeType uint8 | ||||
|  | ||||
| const ( | ||||
| 	UpgradeTypeArchive UpgradeType = iota | ||||
| 	UpgradeTypeFiles | ||||
| ) | ||||
|  | ||||
| func (c *Client) FirmwareUpgrade(upgType UpgradeType, files ...string) (<-chan DFUProgress, error) { | ||||
| 	err := json.NewEncoder(c.conn).Encode(types.Request{ | ||||
| 		Type: types.ReqTypeFwUpgrade, | ||||
| 		Data: types.ReqDataFwUpgrade{ | ||||
| 			Type:  int(upgType), | ||||
| 			Files: files, | ||||
| 		}, | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	c.dfuProgressCh = make(chan DFUProgress, 5) | ||||
|  | ||||
| 	return c.dfuProgressCh, nil | ||||
| } | ||||
		Reference in New Issue
	
	Block a user