-
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathcreate.go
127 lines (113 loc) · 2.96 KB
/
create.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
package device
import (
"errors"
"fmt"
"strings"
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
"github.com/bcmi-labs/iot-cloud-cli/arduino/grpc"
"github.com/bcmi-labs/iot-cloud-cli/internal/config"
"github.com/bcmi-labs/iot-cloud-cli/internal/iot"
)
// CreateParams contains the paramters needed
// to find the device to be provisioned.
// If Port is an empty string, then each serial port is analyzed.
// If Fqbn is an empty string, then the first device found gets selected.
type CreateParams struct {
Port string
Name string
Fqbn string
}
type device struct {
fqbn string
serial string
dType string
port string
}
// Create command is used to provision a new arduino device
// and to add it to the arduino iot cloud.
func Create(params *CreateParams) (string, error) {
rpcComm, rpcClose, err := grpc.NewClient()
if err != nil {
return "", err
}
defer rpcClose()
ports, err := rpcComm.BoardList()
if err != nil {
return "", err
}
dev := deviceFromPorts(ports, params)
if dev == nil {
err = errors.New("no device found")
return "", err
}
conf, err := config.Retrieve()
if err != nil {
return "", err
}
iotClient, err := iot.NewClient(conf.Client, conf.Secret)
if err != nil {
return "", err
}
fmt.Println("Creating a new device on the cloud")
devID, err := iotClient.AddDevice(dev.fqbn, params.Name, dev.serial, dev.dType)
if err != nil {
return "", err
}
prov := &provision{
Commander: rpcComm,
Client: iotClient,
dev: dev,
id: devID}
err = prov.run()
if err != nil {
// TODO: delete the device on iot cloud
err = fmt.Errorf("%s: %w", "cannot provision device", err)
return "", err
}
return devID, nil
}
// deviceFromPorts returns a board that matches all the criteria
// passed in. If no criteria are passed, it returns the first device found.
func deviceFromPorts(ports []*rpc.DetectedPort, params *CreateParams) *device {
for _, port := range ports {
if portFilter(port, params) {
continue
}
board := boardFilter(port.Boards, params)
if board != nil {
t := strings.Split(board.Fqbn, ":")[2]
dev := &device{board.Fqbn, port.SerialNumber, t, port.Address}
return dev
}
}
return nil
}
// portFilter filters out the given port if the port parameter is not an empty string
// and if they do not match.
// It returns:
// true -> to skip the port
// false -> to keep the port
func portFilter(port *rpc.DetectedPort, params *CreateParams) bool {
if len(port.Boards) == 0 {
return true
}
if params.Port != "" && params.Port != port.Address {
return true
}
return false
}
// boardFilter looks for a board which has the same fqbn passed as parameter.
// It returns:
// - a board if it is found.
// - nil if no board matching the fqbn parameter is found.
func boardFilter(boards []*rpc.BoardListItem, params *CreateParams) (board *rpc.BoardListItem) {
if params.Fqbn == "" {
return boards[0]
}
for _, b := range boards {
if b.Fqbn == params.Fqbn {
return b
}
}
return
}