-
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathclient.go
204 lines (179 loc) · 6.47 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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
package iot
import (
"context"
"fmt"
"os"
"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 {
DeviceCreate(fqbn, name, serial, devType string) (*iotclient.ArduinoDevicev2, error)
DeviceDelete(id string) error
DeviceList() ([]iotclient.ArduinoDevicev2, error)
DeviceShow(id string) (*iotclient.ArduinoDevicev2, error)
DeviceOTA(id string, file *os.File, expireMins int) error
CertificateCreate(id, csr string) (*iotclient.ArduinoCompressedv2, error)
ThingCreate(thing *iotclient.Thing, force bool) (*iotclient.ArduinoThing, error)
ThingUpdate(id string, thing *iotclient.Thing, force bool) error
ThingDelete(id string) error
ThingShow(id string) (*iotclient.ArduinoThing, error)
ThingList(ids []string, device *string, props bool) ([]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
}
// DeviceCreate allows to create a new device on Arduino IoT Cloud.
// It returns the newly created device, and an error.
func (cl *client) DeviceCreate(fqbn, name, serial, dType string) (*iotclient.ArduinoDevicev2, 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", errorDetail(err))
return nil, err
}
return &dev, nil
}
// DeviceDelete deletes the device corresponding to the passed ID
// from Arduino IoT Cloud.
func (cl *client) DeviceDelete(id string) error {
_, err := cl.api.DevicesV2Api.DevicesV2Delete(cl.ctx, id)
if err != nil {
err = fmt.Errorf("deleting device: %w", errorDetail(err))
return err
}
return nil
}
// DeviceList retrieves and returns a list of all Arduino IoT Cloud devices
// belonging to the user performing the request.
func (cl *client) DeviceList() ([]iotclient.ArduinoDevicev2, error) {
devices, _, err := cl.api.DevicesV2Api.DevicesV2List(cl.ctx, nil)
if err != nil {
err = fmt.Errorf("listing devices: %w", errorDetail(err))
return nil, err
}
return devices, nil
}
// DeviceShow allows to retrieve a specific device, given its id,
// from Arduino IoT Cloud.
func (cl *client) DeviceShow(id string) (*iotclient.ArduinoDevicev2, error) {
dev, _, err := cl.api.DevicesV2Api.DevicesV2Show(cl.ctx, id)
if err != nil {
err = fmt.Errorf("retrieving device, %w", errorDetail(err))
return nil, err
}
return &dev, nil
}
// DeviceOTA performs an OTA upload request to Arduino IoT Cloud, passing
// the ID of the device to be updated and the actual file containing the OTA firmware.
func (cl *client) DeviceOTA(id string, file *os.File, expireMins int) error {
opt := &iotclient.DevicesV2OtaUploadOpts{
ExpireInMins: optional.NewInt32(int32(expireMins)),
}
_, err := cl.api.DevicesV2OtaApi.DevicesV2OtaUpload(cl.ctx, id, file, opt)
if err != nil {
err = fmt.Errorf("uploading device ota: %w", errorDetail(err))
return err
}
return nil
}
// CertificateCreate allows to upload a certificate on Arduino IoT Cloud.
// It returns the certificate parameters populated by the cloud.
func (cl *client) CertificateCreate(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", errorDetail(err))
return nil, err
}
return &newCert.Compressed, nil
}
// ThingCreate adds a new thing on Arduino IoT Cloud.
func (cl *client) ThingCreate(thing *iotclient.Thing, force bool) (*iotclient.ArduinoThing, error) {
opt := &iotclient.ThingsV2CreateOpts{Force: optional.NewBool(force)}
newThing, _, err := cl.api.ThingsV2Api.ThingsV2Create(cl.ctx, *thing, opt)
if err != nil {
return nil, fmt.Errorf("%s: %w", "adding new thing", errorDetail(err))
}
return &newThing, nil
}
// ThingUpdate updates a thing on Arduino IoT Cloud.
func (cl *client) ThingUpdate(id string, thing *iotclient.Thing, force bool) error {
opt := &iotclient.ThingsV2UpdateOpts{Force: optional.NewBool(force)}
_, _, err := cl.api.ThingsV2Api.ThingsV2Update(cl.ctx, id, *thing, opt)
if err != nil {
return fmt.Errorf("%s: %v", "updating thing", errorDetail(err))
}
return nil
}
// ThingDelete deletes a thing from Arduino IoT Cloud.
func (cl *client) ThingDelete(id string) error {
_, err := cl.api.ThingsV2Api.ThingsV2Delete(cl.ctx, id, nil)
if err != nil {
err = fmt.Errorf("deleting thing: %w", errorDetail(err))
return err
}
return nil
}
// ThingShow allows to retrieve a specific thing, given its id,
// from Arduino IoT Cloud.
func (cl *client) ThingShow(id string) (*iotclient.ArduinoThing, error) {
thing, _, err := cl.api.ThingsV2Api.ThingsV2Show(cl.ctx, id, nil)
if err != nil {
err = fmt.Errorf("retrieving thing, %w", errorDetail(err))
return nil, err
}
return &thing, nil
}
// ThingList returns a list of things on Arduino IoT Cloud.
func (cl *client) ThingList(ids []string, device *string, props bool) ([]iotclient.ArduinoThing, error) {
opts := &iotclient.ThingsV2ListOpts{}
opts.ShowProperties = optional.NewBool(props)
if ids != nil {
opts.Ids = optional.NewInterface(ids)
}
if device != nil {
opts.DeviceId = optional.NewString(*device)
}
things, _, err := cl.api.ThingsV2Api.ThingsV2List(cl.ctx, opts)
if err != nil {
err = fmt.Errorf("retrieving things, %w", errorDetail(err))
return nil, err
}
return things, 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
}