Skip to content

Commit e355ad9

Browse files
Paolo Calaopolldo
Paolo Calao
authored andcommitted
Add dashboard list command (#45)
command to retrieve information about dashboards: 'arduino-cloud-cli dashboard list --show-widgets' widgets are printed out (in text format) only if '--show-widgets' flag is passed. When showed, widgets are grouped in 3 widgets per row. * Update iot-clients-go version * Add dashboard list command * Update readme * Fix - print UpdatedAt string * Limit number of widgets per row * Add flag to show widgets * Remove share details * Update readme
1 parent a38df97 commit e355ad9

File tree

9 files changed

+262
-3
lines changed

9 files changed

+262
-3
lines changed

Diff for: README.md

+6
Original file line numberDiff line numberDiff line change
@@ -118,3 +118,9 @@ The default OTA upload should complete in 10 minutes. Use `--deferred` flag to e
118118
`$ arduino-cloud-cli ota upload --device-id <deviceID> --file <sketch-file.ino.bin>`
119119

120120
`$ arduino-cloud-cli ota upload --device-id <deviceID> --file <sketch-file.ino.bin> --deferred`
121+
122+
## Dashboard commands
123+
124+
Print a list of available dashboards and their widgets by using this command:
125+
126+
`$ arduino-cloud-cli dashboard list --show-widgets`

Diff for: cli/cli.go

+2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"github.com/arduino/arduino-cli/cli/errorcodes"
2727
"github.com/arduino/arduino-cli/cli/feedback"
2828
"github.com/arduino/arduino-cloud-cli/cli/config"
29+
"github.com/arduino/arduino-cloud-cli/cli/dashboard"
2930
"github.com/arduino/arduino-cloud-cli/cli/device"
3031
"github.com/arduino/arduino-cloud-cli/cli/ota"
3132
"github.com/arduino/arduino-cloud-cli/cli/thing"
@@ -51,6 +52,7 @@ func Execute() {
5152
cli.AddCommand(config.NewCommand())
5253
cli.AddCommand(device.NewCommand())
5354
cli.AddCommand(thing.NewCommand())
55+
cli.AddCommand(dashboard.NewCommand())
5456
cli.AddCommand(ota.NewCommand())
5557

5658
cli.PersistentFlags().BoolVarP(&cliFlags.verbose, "verbose", "v", false, "Print the logs on the standard output.")

Diff for: cli/dashboard/dashboard.go

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// This file is part of arduino-cloud-cli.
2+
//
3+
// Copyright (C) 2021 ARDUINO SA (http://www.arduino.cc/)
4+
//
5+
// This program is free software: you can redistribute it and/or modify
6+
// it under the terms of the GNU Affero General Public License as published
7+
// by the Free Software Foundation, either version 3 of the License, or
8+
// (at your option) any later version.
9+
//
10+
// This program is distributed in the hope that it will be useful,
11+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
// GNU Affero General Public License for more details.
14+
//
15+
// You should have received a copy of the GNU Affero General Public License
16+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
18+
package dashboard
19+
20+
import (
21+
"github.com/spf13/cobra"
22+
)
23+
24+
func NewCommand() *cobra.Command {
25+
dashboardCommand := &cobra.Command{
26+
Use: "dashboard",
27+
Short: "Dashboard commands.",
28+
Long: "Dashboard commands.",
29+
}
30+
31+
dashboardCommand.AddCommand(initListCommand())
32+
33+
return dashboardCommand
34+
}

Diff for: cli/dashboard/list.go

+112
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
// This file is part of arduino-cloud-cli.
2+
//
3+
// Copyright (C) 2021 ARDUINO SA (http://www.arduino.cc/)
4+
//
5+
// This program is free software: you can redistribute it and/or modify
6+
// it under the terms of the GNU Affero General Public License as published
7+
// by the Free Software Foundation, either version 3 of the License, or
8+
// (at your option) any later version.
9+
//
10+
// This program is distributed in the hope that it will be useful,
11+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
// GNU Affero General Public License for more details.
14+
//
15+
// You should have received a copy of the GNU Affero General Public License
16+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
18+
package dashboard
19+
20+
import (
21+
"math"
22+
"os"
23+
"strings"
24+
25+
"github.com/arduino/arduino-cli/cli/errorcodes"
26+
"github.com/arduino/arduino-cli/cli/feedback"
27+
"github.com/arduino/arduino-cli/table"
28+
"github.com/arduino/arduino-cloud-cli/command/dashboard"
29+
"github.com/sirupsen/logrus"
30+
"github.com/spf13/cobra"
31+
)
32+
33+
const (
34+
widgetsPerRow = 3
35+
)
36+
37+
var listFlags struct {
38+
showWidgets bool
39+
}
40+
41+
func initListCommand() *cobra.Command {
42+
listCommand := &cobra.Command{
43+
Use: "list",
44+
Short: "List dashboards",
45+
Long: "List dashboards on Arduino IoT Cloud",
46+
Run: runListCommand,
47+
}
48+
49+
listCommand.Flags().BoolVarP(&listFlags.showWidgets, "show-widgets", "s", false, "Show names of dashboard widgets")
50+
return listCommand
51+
}
52+
53+
func runListCommand(cmd *cobra.Command, args []string) {
54+
logrus.Info("Listing dashboards")
55+
56+
dash, err := dashboard.List()
57+
if err != nil {
58+
feedback.Errorf("Error during dashboard list: %v", err)
59+
os.Exit(errorcodes.ErrGeneric)
60+
}
61+
62+
feedback.PrintResult(listResult{dash})
63+
}
64+
65+
type listResult struct {
66+
dashboards []dashboard.DashboardInfo
67+
}
68+
69+
func (r listResult) Data() interface{} {
70+
return r.dashboards
71+
}
72+
73+
func (r listResult) String() string {
74+
if len(r.dashboards) == 0 {
75+
return "No dashboard found."
76+
}
77+
t := table.New()
78+
79+
head := []interface{}{"Name", "ID", "UpdatedAt"}
80+
if listFlags.showWidgets {
81+
head = append(head, "Widgets")
82+
}
83+
t.SetHeader(head...)
84+
85+
for _, dash := range r.dashboards {
86+
row := []interface{}{dash.Name, dash.ID, dash.UpdatedAt}
87+
88+
if listFlags.showWidgets {
89+
// Limit number of widgets per row.
90+
if len(dash.Widgets) > widgetsPerRow {
91+
row = append(row, strings.Join(dash.Widgets[:widgetsPerRow], ", "))
92+
dash.Widgets = dash.Widgets[widgetsPerRow:]
93+
} else {
94+
row = append(row, strings.Join(dash.Widgets, ", "))
95+
dash.Widgets = nil
96+
}
97+
}
98+
t.AddRow(row...)
99+
100+
// Print remaining widgets in new rows
101+
if listFlags.showWidgets {
102+
for len(dash.Widgets) > 0 {
103+
row := []interface{}{"", "", ""}
104+
l := int(math.Min(float64(len(dash.Widgets)), widgetsPerRow))
105+
row = append(row, strings.Join(dash.Widgets[:l], ", "))
106+
dash.Widgets = dash.Widgets[l:]
107+
t.AddRow(row...)
108+
}
109+
}
110+
}
111+
return t.Render()
112+
}

Diff for: command/dashboard/dashboard.go

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// This file is part of arduino-cloud-cli.
2+
//
3+
// Copyright (C) 2021 ARDUINO SA (http://www.arduino.cc/)
4+
//
5+
// This program is free software: you can redistribute it and/or modify
6+
// it under the terms of the GNU Affero General Public License as published
7+
// by the Free Software Foundation, either version 3 of the License, or
8+
// (at your option) any later version.
9+
//
10+
// This program is distributed in the hope that it will be useful,
11+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
// GNU Affero General Public License for more details.
14+
//
15+
// You should have received a copy of the GNU Affero General Public License
16+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
18+
package dashboard
19+
20+
import (
21+
iotclient "github.com/arduino/iot-client-go"
22+
)
23+
24+
// DashboardInfo contains the most interesting
25+
// information, in string format, of an Arduino IoT Cloud dashboard.
26+
type DashboardInfo struct {
27+
Name string `json:"name"`
28+
ID string `json:"id"`
29+
UpdatedAt string `json:"updated_at"`
30+
Widgets []string `json:"widgets"`
31+
}
32+
33+
func getDashboardInfo(dashboard *iotclient.ArduinoDashboardv2) *DashboardInfo {
34+
var widgets []string
35+
for _, w := range dashboard.Widgets {
36+
widgets = append(widgets, w.Name)
37+
}
38+
info := &DashboardInfo{
39+
Name: dashboard.Name,
40+
ID: dashboard.Id,
41+
UpdatedAt: dashboard.UpdatedAt.String(),
42+
Widgets: widgets,
43+
}
44+
return info
45+
}

Diff for: command/dashboard/list.go

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// This file is part of arduino-cloud-cli.
2+
//
3+
// Copyright (C) 2021 ARDUINO SA (http://www.arduino.cc/)
4+
//
5+
// This program is free software: you can redistribute it and/or modify
6+
// it under the terms of the GNU Affero General Public License as published
7+
// by the Free Software Foundation, either version 3 of the License, or
8+
// (at your option) any later version.
9+
//
10+
// This program is distributed in the hope that it will be useful,
11+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
// GNU Affero General Public License for more details.
14+
//
15+
// You should have received a copy of the GNU Affero General Public License
16+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
18+
package dashboard
19+
20+
import (
21+
"github.com/arduino/arduino-cloud-cli/internal/config"
22+
"github.com/arduino/arduino-cloud-cli/internal/iot"
23+
)
24+
25+
// List command is used to list
26+
// the dashboards of Arduino IoT Cloud.
27+
func List() ([]DashboardInfo, error) {
28+
conf, err := config.Retrieve()
29+
if err != nil {
30+
return nil, err
31+
}
32+
iotClient, err := iot.NewClient(conf.Client, conf.Secret)
33+
if err != nil {
34+
return nil, err
35+
}
36+
37+
foundDashboards, err := iotClient.DashboardList()
38+
if err != nil {
39+
return nil, err
40+
}
41+
42+
var dashboards []DashboardInfo
43+
for _, found := range foundDashboards {
44+
info := getDashboardInfo(&found)
45+
dashboards = append(dashboards, *info)
46+
}
47+
48+
return dashboards, nil
49+
}

Diff for: go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ require (
66
github.com/antihax/optional v1.0.0
77
github.com/arduino/arduino-cli v0.0.0-20210607095659-16f41352eac3
88
github.com/arduino/go-paths-helper v1.6.1
9-
github.com/arduino/iot-client-go v1.3.4-0.20210902151346-1cd63fb0c784
9+
github.com/arduino/iot-client-go v1.3.4-0.20210930122852-04551f4cb061
1010
github.com/howeyc/crc16 v0.0.0-20171223171357-2b2a61e366a6
1111
github.com/juju/errors v0.0.0-20181118221551-089d3ea4e4d5
1212
github.com/sirupsen/logrus v1.8.1

Diff for: go.sum

+2-2
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@ github.com/arduino/go-properties-orderedmap v1.3.0/go.mod h1:DKjD2VXY/NZmlingh4l
6060
github.com/arduino/go-timeutils v0.0.0-20171220113728-d1dd9e313b1b/go.mod h1:uwGy5PpN4lqW97FiLnbcx+xx8jly5YuPMJWfVwwjJiQ=
6161
github.com/arduino/go-win32-utils v0.0.0-20180330194947-ed041402e83b h1:3PjgYG5gVPA7cipp7vIR2lF96KkEJIFBJ+ANnuv6J20=
6262
github.com/arduino/go-win32-utils v0.0.0-20180330194947-ed041402e83b/go.mod h1:iIPnclBMYm1g32Q5kXoqng4jLhMStReIP7ZxaoUC2y8=
63-
github.com/arduino/iot-client-go v1.3.4-0.20210902151346-1cd63fb0c784 h1:Wo4g3vuu8Tv57GggLK1T2as/xEqG7CIDnOA49C6Ce7I=
64-
github.com/arduino/iot-client-go v1.3.4-0.20210902151346-1cd63fb0c784/go.mod h1:gYvpMt7Qw+OSScTLyIlCnpbvy9y96ey/2zhB4w6FoK0=
63+
github.com/arduino/iot-client-go v1.3.4-0.20210930122852-04551f4cb061 h1:uQeaIHzj0tOlqnHaRskSy6UwMgQ6LIOECySpaYBCt5M=
64+
github.com/arduino/iot-client-go v1.3.4-0.20210930122852-04551f4cb061/go.mod h1:gYvpMt7Qw+OSScTLyIlCnpbvy9y96ey/2zhB4w6FoK0=
6565
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
6666
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
6767
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=

Diff for: internal/iot/client.go

+11
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ type Client interface {
3939
ThingDelete(id string) error
4040
ThingShow(id string) (*iotclient.ArduinoThing, error)
4141
ThingList(ids []string, device *string, props bool) ([]iotclient.ArduinoThing, error)
42+
DashboardList() ([]iotclient.ArduinoDashboardv2, error)
4243
}
4344

4445
type client struct {
@@ -202,6 +203,16 @@ func (cl *client) ThingList(ids []string, device *string, props bool) ([]iotclie
202203
return things, nil
203204
}
204205

206+
// DashboardList returns a list of dashboards on Arduino IoT Cloud.
207+
func (cl *client) DashboardList() ([]iotclient.ArduinoDashboardv2, error) {
208+
dashboards, _, err := cl.api.DashboardsV2Api.DashboardsV2List(cl.ctx, nil)
209+
if err != nil {
210+
err = fmt.Errorf("listing dashboards: %w", errorDetail(err))
211+
return nil, err
212+
}
213+
return dashboards, nil
214+
}
215+
205216
func (cl *client) setup(client, secret string) error {
206217
// Get the access token in exchange of client_id and client_secret
207218
tok, err := token(client, secret)

0 commit comments

Comments
 (0)