-
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathclient.go
136 lines (119 loc) · 4.08 KB
/
client.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package iot
import (
"context"
"encoding/json"
"fmt"
"github.com/antihax/optional"
iotclient "github.com/arduino/iot-client-go"
)
// Client can be used to perform actions on Arduino IoT Cloud.
type Client interface {
AddDevice(fqbn, name, serial, devType string) (string, error)
DeleteDevice(id string) error
ListDevices() ([]iotclient.ArduinoDevicev2, error)
AddCertificate(id, csr string) (*iotclient.ArduinoCompressedv2, error)
AddThing(thing *iotclient.Thing, force bool) (string, error)
GetThing(id string) (*iotclient.ArduinoThing, error)
}
type client struct {
ctx context.Context
api *iotclient.APIClient
}
// NewClient returns a new client implementing the Client interface.
// It needs a ClientID and SecretID for cloud authentication.
func NewClient(clientID, secretID string) (Client, error) {
cl := &client{}
err := cl.setup(clientID, secretID)
if err != nil {
err = fmt.Errorf("instantiate new iot client: %w", err)
return nil, err
}
return cl, nil
}
// AddDevice allows to create a new device on Arduino IoT Cloud.
// It returns the ID associated to the new device, and an error.
func (cl *client) AddDevice(fqbn, name, serial, dType string) (string, error) {
payload := iotclient.CreateDevicesV2Payload{
Fqbn: fqbn,
Name: name,
Serial: serial,
Type: dType,
}
dev, _, err := cl.api.DevicesV2Api.DevicesV2Create(cl.ctx, payload)
if err != nil {
err = fmt.Errorf("creating device, %w", err)
return "", err
}
return dev.Id, nil
}
// DeleteDevice deletes the device corresponding to the passed ID
// from Arduino IoT Cloud.
func (cl *client) DeleteDevice(id string) error {
_, err := cl.api.DevicesV2Api.DevicesV2Delete(cl.ctx, id)
if err != nil {
err = fmt.Errorf("deleting device: %w", err)
return err
}
return nil
}
// ListDevices retrieves and returns a list of all Arduino IoT Cloud devices
// belonging to the user performing the request.
func (cl *client) ListDevices() ([]iotclient.ArduinoDevicev2, error) {
devices, _, err := cl.api.DevicesV2Api.DevicesV2List(cl.ctx, nil)
if err != nil {
err = fmt.Errorf("listing devices: %w", err)
return nil, err
}
return devices, nil
}
// AddCertifcate allows to upload a certificate on Arduino IoT Cloud.
// It returns the certificate parameters populated by the cloud.
func (cl *client) AddCertificate(id, csr string) (*iotclient.ArduinoCompressedv2, error) {
cert := iotclient.CreateDevicesV2CertsPayload{
Ca: "Arduino",
Csr: csr,
Enabled: true,
}
newCert, _, err := cl.api.DevicesV2CertsApi.DevicesV2CertsCreate(cl.ctx, id, cert)
if err != nil {
err = fmt.Errorf("creating certificate, %w", err)
return nil, err
}
return &newCert.Compressed, nil
}
// AddThing adds a new thing on Arduino IoT Cloud.
func (cl *client) AddThing(thing *iotclient.Thing, force bool) (string, error) {
opt := &iotclient.ThingsV2CreateOpts{Force: optional.NewBool(force)}
newThing, resp, err := cl.api.ThingsV2Api.ThingsV2Create(cl.ctx, *thing, opt)
if err != nil {
var respObj map[string]interface{}
json.NewDecoder(resp.Body).Decode(&respObj)
resp.Body.Close()
return "", fmt.Errorf("%s: %s: %v", "adding new thing", err, respObj)
}
return newThing.Id, nil
}
// GetThing allows to retrieve a specific thing, given its id,
// from Arduino IoT Cloud.
func (cl *client) GetThing(id string) (*iotclient.ArduinoThing, error) {
thing, _, err := cl.api.ThingsV2Api.ThingsV2Show(cl.ctx, id, nil)
if err != nil {
err = fmt.Errorf("retrieving thing, %w", err)
return nil, err
}
return &thing, nil
}
func (cl *client) setup(client, secret string) error {
// Get the access token in exchange of client_id and client_secret
tok, err := token(client, secret)
if err != nil {
err = fmt.Errorf("cannot retrieve token given client and secret: %w", err)
return err
}
// We use the token to create a context that will be passed to any API call
cl.ctx = context.WithValue(context.Background(), iotclient.ContextAccessToken, tok.AccessToken)
// Create an instance of the iot-api Go client, we pass an empty config
// because defaults are ok
cl.api = iotclient.NewAPIClient(iotclient.NewConfiguration())
return nil
}