From ef99d9a8a86b59ad590dce7f1bdfc9f81a41d280 Mon Sep 17 00:00:00 2001 From: fabik111 Date: Thu, 21 Aug 2025 17:56:59 +0200 Subject: [PATCH 01/27] add provisioning-api client --- internal/provisioning-api/client.go | 278 ++++++++++++++++++++++++++++ internal/provisioning-api/dto.go | 76 ++++++++ 2 files changed, 354 insertions(+) create mode 100644 internal/provisioning-api/client.go create mode 100644 internal/provisioning-api/dto.go diff --git a/internal/provisioning-api/client.go b/internal/provisioning-api/client.go new file mode 100644 index 00000000..65992ddf --- /dev/null +++ b/internal/provisioning-api/client.go @@ -0,0 +1,278 @@ +// This file is part of arduino-cloud-cli. +// +// Copyright (C) 2025 ARDUINO SA (http://www.arduino.cc/) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package provisioningapi + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "io" + "net/http" + "strings" + + "github.com/arduino/arduino-cloud-cli/config" + "github.com/arduino/arduino-cloud-cli/internal/iot" + "golang.org/x/oauth2" +) + +type ProvisioningApiClient struct { + client *http.Client + host string + src oauth2.TokenSource + organization string +} + +func NewClient(credentials *config.Credentials) *ProvisioningApiClient { + host := iot.GetArduinoAPIBaseURL() + tokenSource := iot.NewUserTokenSource(credentials.Client, credentials.Secret, host, credentials.Organization) + return &ProvisioningApiClient{ + client: &http.Client{}, + src: tokenSource, + host: host, + organization: credentials.Organization, + } +} + +func (c *ProvisioningApiClient) performRequest(endpoint, method, token string, body io.Reader) (*http.Response, error) { + req, err := http.NewRequest(method, endpoint, body) + if err != nil { + return nil, err + } + req.Header.Add("Authorization", "Bearer "+token) + req.Header.Add("Content-Type", "application/json") + if c.organization != "" { + req.Header.Add("X-Organization", c.organization) + } + res, err := c.client.Do(req) + if err != nil { + return nil, err + } + return res, nil +} + +func (c *ProvisioningApiClient) getToken() (*oauth2.Token, error) { + token, err := c.src.Token() + if err != nil { + if strings.Contains(err.Error(), "401") { + return nil, errors.New("wrong credentials") + } + return nil, fmt.Errorf("cannot retrieve a valid token: %w", err) + } + return token, nil +} + +func (c *ProvisioningApiClient) ClaimDevice(data ClaimData) (*ClaimResponse, *BadResponse, error) { + endpoint := c.host + "provisioning/v1/onboarding/claim" + token, err := c.getToken() + if err != nil { + return nil, nil, err + } + + dataJson, err := json.Marshal(data) + if err != nil { + return nil, nil, fmt.Errorf("failed to marshal claim data: %w", err) + } + + res, err := c.performRequest(endpoint, http.MethodPost, token.AccessToken, bytes.NewReader(dataJson)) + if err != nil { + return nil, nil, err + } + defer res.Body.Close() + + respBytes, err := io.ReadAll(res.Body) + if err != nil { + return nil, nil, err + } + + if res.StatusCode == http.StatusOK { + var response ClaimResponse + + err = json.Unmarshal(respBytes, &response) + if err != nil { + return nil, nil, err + } + return &response, nil, nil + } + var badResponse BadResponse + + err = json.Unmarshal(respBytes, &badResponse) + if err != nil { + return nil, nil, err + } + + return nil, &badResponse, nil +} + +func (c *ProvisioningApiClient) RegisterDevice(data RegisterBoardData) (*BadResponse, error) { + endpoint := c.host + "provisioning/v1/boards/register" + token, err := c.getToken() + if err != nil { + return nil, err + } + + dataJson, err := json.Marshal(data) + if err != nil { + return nil, fmt.Errorf("failed to marshal register data: %w", err) + } + + res, err := c.performRequest(endpoint, http.MethodPost, token.AccessToken, bytes.NewReader(dataJson)) + if err != nil { + return nil, err + } + defer res.Body.Close() + + respBytes, err := io.ReadAll(res.Body) + if err != nil { + return nil, err + } + + if res.StatusCode == http.StatusOK { + return nil, nil + } + var badResponse BadResponse + + err = json.Unmarshal(respBytes, &badResponse) + if err != nil { + return nil, err + } + + return &badResponse, nil +} + +func (c *ProvisioningApiClient) Unclaim(provisioningId string) (*BadResponse, error) { + endpoint := c.host + "provisioning/v1/onboarding/" + provisioningId + token, err := c.getToken() + if err != nil { + return nil, err + } + + res, err := c.performRequest(endpoint, http.MethodDelete, token.AccessToken, nil) + if err != nil { + return nil, err + } + defer res.Body.Close() + + if res.StatusCode == http.StatusOK { + return nil, nil + } + var badResponse BadResponse + respBytes, err := io.ReadAll(res.Body) + if err != nil { + return nil, err + } + err = json.Unmarshal(respBytes, &badResponse) + if err != nil { + return nil, err + } + + return &badResponse, nil +} + +func (c *ProvisioningApiClient) GetProvisioningList() (*OnboardingsResponse, error) { + endpoint := c.host + "provisioning/v1/onboarding?all=true" + token, err := c.getToken() + if err != nil { + return nil, err + } + + res, err := c.performRequest(endpoint, http.MethodGet, token.AccessToken, nil) + if err != nil { + return nil, err + } + defer res.Body.Close() + + if res.StatusCode == http.StatusOK { + var response OnboardingsResponse + + respBytes, err := io.ReadAll(res.Body) + if err != nil { + return nil, err + } + + err = json.Unmarshal(respBytes, &response) + if err != nil { + return nil, err + } + return &response, nil + } else if res.StatusCode == 400 { + return nil, errors.New(endpoint + " returned bad request") + } else if res.StatusCode == 401 { + return nil, errors.New(endpoint + " returned unauthorized request") + } else if res.StatusCode == 403 { + return nil, errors.New(endpoint + " returned forbidden request") + } else if res.StatusCode == 500 { + return nil, errors.New(endpoint + " returned internal server error") + } + + return nil, err +} + +func (c *ProvisioningApiClient) GetProvisioningDetail(provID string) (*Onboarding, error) { + onboardingList, err := c.GetProvisioningList() + if err != nil { + return nil, fmt.Errorf("failed to get provisioning list: %w", err) + } + + for _, onboarding := range onboardingList.Onboardings { + if onboarding.ID == provID { + return &onboarding, nil + } + } + + return nil, fmt.Errorf("onboarding with ID %s not found", provID) +} + +func (c *ProvisioningApiClient) GetBoardsDetail() (*BoardTypeList, error) { + endpoint := c.host + "iot/v1/supported/devices" + token, err := c.getToken() + if err != nil { + return nil, err + } + + res, err := c.performRequest(endpoint, http.MethodGet, token.AccessToken, nil) + if err != nil { + return nil, err + } + defer res.Body.Close() + + if res.StatusCode == http.StatusOK { + var response BoardTypeList + + respBytes, err := io.ReadAll(res.Body) + if err != nil { + return nil, err + } + + err = json.Unmarshal(respBytes, &response) + if err != nil { + return nil, err + } + return &response, nil + } else if res.StatusCode == 400 { + return nil, errors.New(endpoint + " returned bad request") + } else if res.StatusCode == 401 { + return nil, errors.New(endpoint + " returned unauthorized request") + } else if res.StatusCode == 403 { + return nil, errors.New(endpoint + " returned forbidden request") + } else if res.StatusCode == 500 { + return nil, errors.New(endpoint + " returned internal server error") + } + + return nil, err +} diff --git a/internal/provisioning-api/dto.go b/internal/provisioning-api/dto.go new file mode 100644 index 00000000..af6f91ad --- /dev/null +++ b/internal/provisioning-api/dto.go @@ -0,0 +1,76 @@ +// This file is part of arduino-cloud-cli. +// +// Copyright (C) 2025 ARDUINO SA (http://www.arduino.cc/) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package provisioningapi + +type RegisterBoardData struct { + PID string `json:"pid"` + PublicKey string `json:"public_key"` + Serial *string `json:"serial"` + UniqueHardwareID string `json:"unique_hardware_id"` + VID string `json:"vid"` +} + +type ClaimData struct { + BLEMac string `json:"ble_mac"` + BoardToken string `json:"board_token"` + ConnectionType string `json:"connection_type"` + DeviceName string `json:"device_name"` +} + +type BadResponse struct { + Err string `json:"err"` + ErrCode int `json:"err_code"` +} + +type ClaimResponse struct { + BoardId string `json:"id"` +} + +type BoardType struct { + FQBN *string `json:"fqbn,omitempty"` + Label string `json:"label"` + MinProvSketchVersion *string `json:"min_provisioning_sketch_version,omitempty"` + MinWiFiVersion *string `json:"min_provisioning_wifi_version,omitempty"` + Provisioning *string `json:"provisioning,omitempty"` + Tags []string `json:"tags"` + Type string `json:"type"` + Vendor string `json:"vendor"` + OTAAvailable *bool `json:"ota_available,omitempty"` +} + +type BoardTypeList []BoardType + +type Onboarding struct { + ID string `json:"id"` + UniqueHardwareID string `json:"unique_hardware_id"` + DeviceName string `json:"device_name"` + ConnectionType string `json:"connection_type"` + DeviceID *string `json:"device_id"` + UserID string `json:"user_id"` + OrgID *string `json:"org_id"` + BLEMac string `json:"ble_mac"` + CreatedAt string `json:"created_at"` + ProvisionedAt *string `json:"provisioned_at"` + ClaimedAt string `json:"claimed_at"` + EndedAt *string `json:"ended_at"` + FQBN string `json:"fqbn"` +} + +type OnboardingsResponse struct { + Onboardings []Onboarding `json:"onboardings"` +} From d6bb83939daa8cb41d027fe0116ae5a804b70e2c Mon Sep 17 00:00:00 2001 From: fabik111 Date: Thu, 21 Aug 2025 17:57:27 +0200 Subject: [PATCH 02/27] update board with crypto list --- command/device/board.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/command/device/board.go b/command/device/board.go index 568285c2..8d0a56f5 100644 --- a/command/device/board.go +++ b/command/device/board.go @@ -35,6 +35,8 @@ var ( "arduino:samd:mkrnb1500", "arduino:mbed_opta:opta", "arduino:mbed_giga:giga", + "arduino:renesas_uno:unor4wifi", + "arduino:renesas_portenta:portenta_c33", } loraFQBN = []string{ "arduino:samd:mkrwan1310", From e7593830b0c0829045101b692d191072efa030a7 Mon Sep 17 00:00:00 2001 From: fabik111 Date: Thu, 21 Aug 2025 18:02:53 +0200 Subject: [PATCH 03/27] draft provisioning v2 --- command/device/create.go | 35 +++++++++++++++++++++++-- command/device/provisionv2.go | 48 +++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 command/device/provisionv2.go diff --git a/command/device/create.go b/command/device/create.go index cabc9996..399d13f9 100644 --- a/command/device/create.go +++ b/command/device/create.go @@ -22,9 +22,11 @@ import ( "errors" "fmt" + "github.com/arduino/arduino-cloud-cli/arduino" "github.com/arduino/arduino-cloud-cli/arduino/cli" "github.com/arduino/arduino-cloud-cli/config" "github.com/arduino/arduino-cloud-cli/internal/iot" + provisioningapi "github.com/arduino/arduino-cloud-cli/internal/provisioning-api" "github.com/sirupsen/logrus" ) @@ -70,6 +72,36 @@ func Create(ctx context.Context, params *CreateParams, cred *config.Credentials) return nil, err } + provisioningClient := provisioningapi.NewClient(cred) + + boardsList, err := provisioningClient.GetBoardsDetail() + if err != nil { + return nil, err + } + var boardProvisioningDetails provisioningapi.BoardType + for _, b := range *boardsList { + if *b.FQBN == board.fqbn { + boardProvisioningDetails = b + break + } + } + + if boardProvisioningDetails.FQBN == nil { + return nil, fmt.Errorf("board with fqbn %s not found in provisioning API", board.fqbn) + } + + var devInfo *DeviceInfo + if boardProvisioningDetails.Provisioning != nil && *boardProvisioningDetails.Provisioning == "v2" { + //TODO ADD function for V2 provisioning + } else { + logrus.Info("Provisioning V1 started") + devInfo, err = runProvisioningV1(ctx, params, &comm, iotClient, board) + } + + return devInfo, err +} + +func runProvisioningV1(ctx context.Context, params *CreateParams, comm *arduino.Commander, iotClient *iot.Client, board *board) (*DeviceInfo, error) { logrus.Info("Creating a new device on the cloud") dev, err := iotClient.DeviceCreate(ctx, board.fqbn, params.Name, board.serial, board.dType, params.ConnectionType) if err != nil { @@ -77,7 +109,7 @@ func Create(ctx context.Context, params *CreateParams, cred *config.Credentials) } prov := &provision{ - Commander: comm, + Commander: *comm, cert: iotClient, board: board, id: dev.Id, @@ -94,7 +126,6 @@ func Create(ctx context.Context, params *CreateParams, cred *config.Credentials) } return nil, fmt.Errorf("cannot provision device: %w", err) } - devInfo := &DeviceInfo{ Name: dev.Name, ID: dev.Id, diff --git a/command/device/provisionv2.go b/command/device/provisionv2.go new file mode 100644 index 00000000..e60774e0 --- /dev/null +++ b/command/device/provisionv2.go @@ -0,0 +1,48 @@ +// This file is part of arduino-cloud-cli. +// +// Copyright (C) 2021 ARDUINO SA (http://www.arduino.cc/) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package device + +import ( + "github.com/arduino/arduino-cloud-cli/arduino" + configurationprotocol "github.com/arduino/arduino-cloud-cli/internal/board-protocols/configuration-protocol" + "github.com/arduino/arduino-cloud-cli/internal/board-protocols/transport" + provisioningapi "github.com/arduino/arduino-cloud-cli/internal/provisioning-api" +) + +type ProvisionV2 struct { + arduino.Commander + provisioningClient *provisioningapi.ProvisioningApiClient + serial transport.TransportInterface + provProt *configurationprotocol.NetworkConfigurationProtocol + board *board + id string +} + +func NewProvisionV2(provisioningClient *provisioningapi.ProvisioningApiClient, serial transport.TransportInterface, provProt *configurationprotocol.NetworkConfigurationProtocol, board *board, id string) *ProvisionV2 { + return &ProvisionV2{ + provisioningClient: provisioningClient, + serial: serial, + provProt: provProt, + board: board, + id: id, + } +} + +func (p *ProvisionV2) run() error { + +} From 47f3ee327d1055e0b4092d48af5f0b7eca070d0c Mon Sep 17 00:00:00 2001 From: fabik111 Date: Thu, 21 Aug 2025 18:03:17 +0200 Subject: [PATCH 04/27] refactor network configuration feature --- command/device/configurationstates.go | 340 ++++++++++++++++++ command/device/configure.go | 328 ++--------------- .../configuration_protocol.go | 2 + 3 files changed, 373 insertions(+), 297 deletions(-) create mode 100644 command/device/configurationstates.go diff --git a/command/device/configurationstates.go b/command/device/configurationstates.go new file mode 100644 index 00000000..be78de58 --- /dev/null +++ b/command/device/configurationstates.go @@ -0,0 +1,340 @@ +// This file is part of arduino-cloud-cli. +// +// Copyright (C) 2025 ARDUINO SA (http://www.arduino.cc/) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package device + +import ( + "context" + "errors" + "fmt" + "time" + + configurationprotocol "github.com/arduino/arduino-cloud-cli/internal/board-protocols/configuration-protocol" + "github.com/arduino/arduino-cloud-cli/internal/board-protocols/configuration-protocol/cborcoders" + "github.com/arduino/arduino-cloud-cli/internal/board-protocols/transport" + "github.com/sirupsen/logrus" +) + +type ConfigStatus int + +// This enum represents the different states of the network configuration process +// of the Arduino Board Configuration Protocol. +const ( + NoneState ConfigStatus = iota + WaitForConnection + WaitingForInitialStatus + WaitingForNetworkOptions + BoardReady + FlashProvisioningSketch + GetSketchVersionRequest + WaitingSketchVersion + WiFiFWVersionRequest + WaitingWiFiFWVersion + RequestBLEMAC + WaitBLEMAC + SendInitialTS + MissingParameter + UUIDRequest + WaitingUUID + WaitingSignature + WaitingPublicKey + ClaimDevice + RegisterDevice + RequestReset + WaitResetResponse + GetNetConfigLibVersionRequest + WaitingNetConfigLibVersion + ConfigureNetwork + SendConnectionRequest + WaitingForConnectionCommandResult + WaitingForNetworkConfigResult + End +) + +type ConfigurationStates struct { + extInterface transport.TransportInterface + configProtocol *configurationprotocol.NetworkConfigurationProtocol +} + +func NewConfigurationStates(extInterface transport.TransportInterface, configProtocol *configurationprotocol.NetworkConfigurationProtocol) *ConfigurationStates { + return &ConfigurationStates{ + extInterface: extInterface, + configProtocol: configProtocol, + } +} + +func (c *ConfigurationStates) WaitForConnection() (ConfigStatus, error) { + if c.extInterface.Connected() { + return WaitingForInitialStatus, nil + } + return NoneState, errors.New("impossible to connect with the device") +} + +func (c *ConfigurationStates) WaitingForInitialStatus() (ConfigStatus, error) { + logrus.Info("NetworkConfigure: waiting for initial status from device") + res, err := c.configProtocol.ReceiveData(30) + if err != nil { + return NoneState, fmt.Errorf("communication error: %w, please check the NetworkConfigurator lib is activated in the sketch", err) + } + + if res == nil { + return WaitingForNetworkOptions, nil + } else if res.Type() == cborcoders.ProvisioningStatusMessageType { + status := res.ToProvisioningStatusMessage() + if status.Status == 1 { + return WaitingForInitialStatus, nil + } else if status.Status == -6 || status.Status <= -101 { + newState, err := c.HandleStatusMessage(status.Status) + if err != nil { + return NoneState, err + } + if newState != NoneState { + return newState, nil + } + } else { + return WaitingForNetworkOptions, nil + } + + } else if res.Type() == cborcoders.WiFiNetworksType { + return BoardReady, nil + } + + return WaitingForNetworkOptions, nil +} + +// In this state the cli is waiting for the available network options as specified in the +// Arduino Board Configuration Protocol. +func (c *ConfigurationStates) WaitingForNetworkOptions() (ConfigStatus, error) { + logrus.Info("NetworkConfigure: waiting for network options from device") + res, err := c.configProtocol.ReceiveData(30) + if err != nil { + return NoneState, err + } + + if res != nil { + // At the moment of writing, the only type of message that can be received in this state is the + // WiFiNetworksType, which contains the available WiFi networks list. + if res.Type() == cborcoders.WiFiNetworksType { + return BoardReady, nil + } else if res.Type() == cborcoders.ProvisioningStatusMessageType { + status := res.ToProvisioningStatusMessage() + if status.Status == 1 { + return WaitingForInitialStatus, nil + } else { + newState, err := c.HandleStatusMessage(status.Status) + if err != nil { + return NoneState, err + } + if newState != NoneState { + return newState, nil + } + } + } + } + + return NoneState, errors.New("timeout: no network options received from the device, please retry enabling the NetworkCofnigurator lib in the sketch") +} + +func (cs *ConfigurationStates) ConfigureNetwork(ctx context.Context, c *NetConfig) (ConfigStatus, error) { + var cmd cborcoders.Cmd + if c.Type == 1 { // WiFi + cmd = cborcoders.From(cborcoders.ProvisioningWifiConfigMessage{ + SSID: c.WiFi.SSID, + PWD: c.WiFi.PWD, + }) + } else if c.Type == 2 { // Ethernet + cmd = cborcoders.From(cborcoders.ProvisioningEthernetConfigMessage{ + Static_ip: c.Eth.IP.Bytes[:], + Dns: c.Eth.DNS.Bytes[:], + Gateway: c.Eth.Gateway.Bytes[:], + Netmask: c.Eth.Netmask.Bytes[:], + Timeout: c.Eth.Timeout, + ResponseTimeout: c.Eth.ResponseTimeout, + }) + } else if c.Type == 3 { // NB-IoT + cmd = cborcoders.From(cborcoders.ProvisioningNBConfigMessage{ + PIN: c.NB.PIN, + Apn: c.NB.APN, + Login: c.NB.Login, + Pass: c.NB.Pass, + }) + } else if c.Type == 4 { // GSM + cmd = cborcoders.From(cborcoders.ProvisioningGSMConfigMessage{ + PIN: c.GSM.PIN, + Apn: c.GSM.APN, + Login: c.GSM.Login, + Pass: c.GSM.Pass, + }) + } else if c.Type == 5 { // LoRa + cmd = cborcoders.From(cborcoders.ProvisioningLoRaConfigMessage{ + AppEui: c.Lora.AppEUI, + AppKey: c.Lora.AppKey, + Band: c.Lora.Band, + ChannelMask: c.Lora.ChannelMask, + DeviceClass: c.Lora.DeviceClass, + }) + } else if c.Type == 6 { // CAT-M1 + cmd = cborcoders.From(cborcoders.ProvisioningCATM1ConfigMessage{ + PIN: c.CATM1.PIN, + Apn: c.CATM1.APN, + Login: c.CATM1.Login, + Pass: c.CATM1.Pass, + Band: c.CATM1.Band, + }) + } else if c.Type == 7 { // Cellular + cmd = cborcoders.From(cborcoders.ProvisioningCellularConfigMessage{ + PIN: c.CellularSetting.PIN, + Apn: c.CellularSetting.APN, + Login: c.CellularSetting.Login, + Pass: c.CellularSetting.Pass, + }) + } else { + return NoneState, errors.New("invalid configuration type") + } + + err := cs.configProtocol.SendData(cmd) + if err != nil { + return NoneState, err + } + + sleepCtx(ctx, 1*time.Second) + return SendConnectionRequest, nil +} + +func (c *ConfigurationStates) SendConnectionRequest() (ConfigStatus, error) { + connectMessage := cborcoders.From(cborcoders.ProvisioningCommandsMessage{Command: configurationprotocol.Commands["Connect"]}) + err := c.configProtocol.SendData(connectMessage) + if err != nil { + return NoneState, err + } + return WaitingForConnectionCommandResult, nil + +} + +func (c *ConfigurationStates) WaitingForConnectionCommandResult() (ConfigStatus, error) { + res, err := c.configProtocol.ReceiveData(60) + if err != nil { + return NoneState, err + } + + if res != nil && res.Type() == cborcoders.ProvisioningStatusMessageType { + status := res.ToProvisioningStatusMessage() + if status.Status == 1 { + return WaitingForNetworkConfigResult, nil + } else if status.Status == -4 { + return ConfigureNetwork, nil + } else { + newState, err := c.HandleStatusMessage(status.Status) + if err != nil { + return NoneState, err + } + if newState != NoneState { + return newState, nil + } + } + } + + return NoneState, errors.New("timeout: no confirmation of connection command received from the device, please retry") +} + +func (c *ConfigurationStates) WaitingForNetworkConfigResult() (ConfigStatus, error) { + res, err := c.configProtocol.ReceiveData(200) + if err != nil { + return NoneState, err + } + + if res != nil && res.Type() == cborcoders.ProvisioningStatusMessageType { + status := res.ToProvisioningStatusMessage() + + if status.Status == 2 { + return End, nil + } else { + newState, err := c.HandleStatusMessage(status.Status) + if err != nil { + return NoneState, err + } + if newState != NoneState { + return newState, nil + } + } + } + + return NoneState, errors.New("timeout: no result received from the device for network configuration, please retry") +} + +// Keep for reference +/* +func (c *ConfigurationStates) printNetworkOption(msg *cborcoders.Cmd) { + if msg.Type() == cborcoders.WiFiNetworksType { + networks := msg.ToWiFiNetworks() + for _, network := range networks { + fmt.Printf("SSID: %s, RSSI %d \n", network.SSID, network.RSSI) + } + } +} +*/ + +func (c *ConfigurationStates) HandleStatusMessage(status int16) (ConfigStatus, error) { + statusMessage := configurationprotocol.StatusBoard[status] + logrus.Debugf("NetworkConfigure: status message received: %s", statusMessage) + + switch statusMessage { + case "Connecting": + return NoneState, nil + case "Connected": + return NoneState, nil + case "Resetted": + return NoneState, nil + case "Scanning for WiFi networks": + return WaitingForNetworkOptions, nil + case "Failed to connect": + return NoneState, errors.New("connection failed invalid credentials or network configuration") + case "Disconnected": + return NoneState, nil + case "Parameters not provided": + return MissingParameter, nil + case "Invalid parameters": + return NoneState, errors.New("the provided parameters for network configuration are invalid") + case "Cannot execute anew request while another is pending": + return NoneState, errors.New("board is busy, restart the board and try again") + case "Invalid request": + return NoneState, errors.New("invalid request sent to the board") + case "Internet not available": + return NoneState, errors.New("internet not available, check your network connection") + case "HW Error connectivity module": + return NoneState, errors.New("hardware error in connectivity module, check the board") + case "HW Connectivity Module stopped": + return NoneState, errors.New("hardware connectivity module stopped, restart the board and check your sketch") + case "Error initializing secure element": + return NoneState, errors.New("error initializing secure element, check the board and try again") + case "Error configuring secure element": + return NoneState, errors.New("error configuring secure element, check the board and try again") + case "Error locking secure element": + return NoneState, errors.New("error locking secure element, check the board and try again") + case "Error generating UHWID": + return NoneState, errors.New("error generating UHWID, check the board and try again") + case "Error storage begin module": + return NoneState, errors.New("error beginning storage module, check the board storage partitioning and try again") + case "Fail to partition the storage": + return NoneState, errors.New("failed to partition the storage, check the board storage and try again") + case "Generic error": + return NoneState, errors.New("generic error, check the board and try again") + default: + return NoneState, errors.New("generic error, check the board and try again") + } + +} diff --git a/command/device/configure.go b/command/device/configure.go index f8f642d5..a104736f 100644 --- a/command/device/configure.go +++ b/command/device/configure.go @@ -20,15 +20,11 @@ package device import ( "context" "errors" - "fmt" - "time" "github.com/arduino/arduino-cloud-cli/arduino/cli" configurationprotocol "github.com/arduino/arduino-cloud-cli/internal/board-protocols/configuration-protocol" - "github.com/arduino/arduino-cloud-cli/internal/board-protocols/configuration-protocol/cborcoders" "github.com/arduino/arduino-cloud-cli/internal/board-protocols/transport" "github.com/arduino/arduino-cloud-cli/internal/serial" - "github.com/sirupsen/logrus" ) func NetConfigure(ctx context.Context, boardFilters *CreateParams, NetConfig *NetConfig) error { @@ -56,82 +52,78 @@ func NetConfigure(ctx context.Context, boardFilters *CreateParams, NetConfig *Ne return err } - nc := NewNetworkConfigure(extInterface) + nc := NewNetworkConfigure(extInterface, configProtocol) err = nc.Run(ctx, NetConfig) return err } -type ConfigStatus int - -// This enum represents the different states of the network configuration process -// of the Arduino Board Configuration Protocol. -const ( - NoneState ConfigStatus = iota - WaitForConnection - WaitingForInitialStatus - WaitingForNetworkOptions - ConfigureNetwork - SendConnectionRequest - WaitingForConnectionCommandResult - WaitingForNetworkConfigResult - End -) - type NetworkConfigure struct { + configStates *ConfigurationStates state ConfigStatus - extInterface transport.TransportInterface configProtocol *configurationprotocol.NetworkConfigurationProtocol } -func NewNetworkConfigure(extInterface transport.TransportInterface) *NetworkConfigure { +func NewNetworkConfigure(extInterface transport.TransportInterface, configProtocol *configurationprotocol.NetworkConfigurationProtocol) *NetworkConfigure { return &NetworkConfigure{ - extInterface: extInterface, - configProtocol: configurationprotocol.NewNetworkConfigurationProtocol(&extInterface), + configStates: NewConfigurationStates(extInterface, configProtocol), + configProtocol: configProtocol, } } func (nc *NetworkConfigure) Run(ctx context.Context, netConfig *NetConfig) error { nc.state = WaitForConnection var err error + var nextState ConfigStatus for nc.state != End { switch nc.state { case WaitForConnection: - err = nc.waitForConnection() + nextState, err = nc.configStates.WaitForConnection() if err != nil { - nc.state = End + nextState = End } + nc.state = nextState case WaitingForInitialStatus: - err = nc.waitingForInitialStatus() + nextState, err = nc.configStates.WaitingForInitialStatus() if err != nil { - nc.state = End + nextState = End } + nc.state = nextState case WaitingForNetworkOptions: - err = nc.waitingForNetworkOptions() + nextState, err = nc.configStates.WaitingForNetworkOptions() if err != nil { - nc.state = End + nextState = End } + nc.state = nextState + case BoardReady: + nc.state = ConfigureNetwork case ConfigureNetwork: - err = nc.configureNetwork(ctx, netConfig) + nextState, err = nc.configStates.ConfigureNetwork(ctx, netConfig) if err != nil { - nc.state = End + nextState = End } + nc.state = nextState case SendConnectionRequest: - err = nc.sendConnectionRequest() + nextState, err = nc.configStates.SendConnectionRequest() if err != nil { - nc.state = End + nextState = End } + nc.state = nextState case WaitingForConnectionCommandResult: - err = nc.waitingForConnectionCommandResult() + nextState, err = nc.configStates.WaitingForConnectionCommandResult() if err != nil { - nc.state = End + nextState = End } + nc.state = nextState + case MissingParameter: + nc.state = ConfigureNetwork case WaitingForNetworkConfigResult: - err = nc.waitingForNetworkConfigResult() + nextState, err = nc.configStates.WaitingForNetworkConfigResult() if err != nil { - nc.state = End + nextState = End } + nc.state = nextState } } @@ -139,261 +131,3 @@ func (nc *NetworkConfigure) Run(ctx context.Context, netConfig *NetConfig) error nc.configProtocol.Close() return err } - -func (nc *NetworkConfigure) waitForConnection() error { - if nc.extInterface.Connected() { - nc.state = WaitingForInitialStatus - } - return nil -} - -func (nc *NetworkConfigure) waitingForInitialStatus() error { - logrus.Info("NetworkConfigure: waiting for initial status from device") - res, err := nc.configProtocol.ReceiveData(30) - if err != nil { - return fmt.Errorf("communication error: %w, please check the NetworkConfigurator lib is activated in the sketch", err) - } - - if res == nil { - nc.state = WaitingForNetworkOptions - } else if res.Type() == cborcoders.ProvisioningStatusMessageType { - status := res.ToProvisioningStatusMessage() - if status.Status == 1 { - nc.state = WaitingForInitialStatus - } else if status.Status == -6 || status.Status <= -101 { - newState, err := nc.handleStatusMessage(status.Status) - if err != nil { - return err - } - if newState != NoneState { - nc.state = newState - } - } else { - nc.state = WaitingForNetworkOptions - } - - } else if res.Type() == cborcoders.WiFiNetworksType { - nc.state = ConfigureNetwork - } - - return nil -} - -// In this state the cli is waiting for the available network options as specified in the -// Arduino Board Configuration Protocol. -func (nc *NetworkConfigure) waitingForNetworkOptions() error { - logrus.Info("NetworkConfigure: waiting for network options from device") - res, err := nc.configProtocol.ReceiveData(30) - if err != nil { - return err - } - - if res != nil { - // At the moment of writing, the only type of message that can be received in this state is the - // WiFiNetworksType, which contains the available WiFi networks list. - if res.Type() == cborcoders.WiFiNetworksType { - nc.state = ConfigureNetwork - } else if res.Type() == cborcoders.ProvisioningStatusMessageType { - status := res.ToProvisioningStatusMessage() - if status.Status == 1 { - nc.state = WaitingForInitialStatus - } else { - newState, err := nc.handleStatusMessage(status.Status) - if err != nil { - return err - } - if newState != NoneState { - nc.state = newState - } - } - } - } - - return nil -} - -func (nc *NetworkConfigure) configureNetwork(ctx context.Context, c *NetConfig) error { - var cmd cborcoders.Cmd - if c.Type == 1 { // WiFi - cmd = cborcoders.From(cborcoders.ProvisioningWifiConfigMessage{ - SSID: c.WiFi.SSID, - PWD: c.WiFi.PWD, - }) - } else if c.Type == 2 { // Ethernet - cmd = cborcoders.From(cborcoders.ProvisioningEthernetConfigMessage{ - Static_ip: c.Eth.IP.Bytes[:], - Dns: c.Eth.DNS.Bytes[:], - Gateway: c.Eth.Gateway.Bytes[:], - Netmask: c.Eth.Netmask.Bytes[:], - Timeout: c.Eth.Timeout, - ResponseTimeout: c.Eth.ResponseTimeout, - }) - } else if c.Type == 3 { // NB-IoT - cmd = cborcoders.From(cborcoders.ProvisioningNBConfigMessage{ - PIN: c.NB.PIN, - Apn: c.NB.APN, - Login: c.NB.Login, - Pass: c.NB.Pass, - }) - } else if c.Type == 4 { // GSM - cmd = cborcoders.From(cborcoders.ProvisioningGSMConfigMessage{ - PIN: c.GSM.PIN, - Apn: c.GSM.APN, - Login: c.GSM.Login, - Pass: c.GSM.Pass, - }) - } else if c.Type == 5 { // LoRa - cmd = cborcoders.From(cborcoders.ProvisioningLoRaConfigMessage{ - AppEui: c.Lora.AppEUI, - AppKey: c.Lora.AppKey, - Band: c.Lora.Band, - ChannelMask: c.Lora.ChannelMask, - DeviceClass: c.Lora.DeviceClass, - }) - } else if c.Type == 6 { // CAT-M1 - cmd = cborcoders.From(cborcoders.ProvisioningCATM1ConfigMessage{ - PIN: c.CATM1.PIN, - Apn: c.CATM1.APN, - Login: c.CATM1.Login, - Pass: c.CATM1.Pass, - Band: c.CATM1.Band, - }) - } else if c.Type == 7 { // Cellular - cmd = cborcoders.From(cborcoders.ProvisioningCellularConfigMessage{ - PIN: c.CellularSetting.PIN, - Apn: c.CellularSetting.APN, - Login: c.CellularSetting.Login, - Pass: c.CellularSetting.Pass, - }) - } else { - return errors.New("invalid configuration type") - } - - err := nc.configProtocol.SendData(cmd) - if err != nil { - return err - } - - nc.state = SendConnectionRequest - sleepCtx(ctx, 1*time.Second) - return nil -} - -func (nc *NetworkConfigure) sendConnectionRequest() error { - connectMessage := cborcoders.From(cborcoders.ProvisioningCommandsMessage{Command: configurationprotocol.Commands["Connect"]}) - err := nc.configProtocol.SendData(connectMessage) - if err != nil { - return err - } - nc.state = WaitingForConnectionCommandResult - return nil -} - -func (nc *NetworkConfigure) waitingForConnectionCommandResult() error { - res, err := nc.configProtocol.ReceiveData(60) - if err != nil { - return err - } - - if res != nil && res.Type() == cborcoders.ProvisioningStatusMessageType { - status := res.ToProvisioningStatusMessage() - if status.Status == 1 { - nc.state = WaitingForNetworkConfigResult - } else { - newState, err := nc.handleStatusMessage(status.Status) - if err != nil { - return err - } - if newState != NoneState { - nc.state = newState - } - } - } - - return nil -} - -func (nc *NetworkConfigure) waitingForNetworkConfigResult() error { - res, err := nc.configProtocol.ReceiveData(200) - if err != nil { - return err - } - - if res != nil && res.Type() == cborcoders.ProvisioningStatusMessageType { - status := res.ToProvisioningStatusMessage() - - if status.Status == 2 { - nc.state = End - } else { - newState, err := nc.handleStatusMessage(status.Status) - if err != nil { - return err - } - if newState != NoneState { - nc.state = newState - } - } - } - - return nil -} - -func (nc *NetworkConfigure) printNetworkOption(msg *cborcoders.Cmd) { - if msg.Type() == cborcoders.WiFiNetworksType { - networks := msg.ToWiFiNetworks() - for _, network := range networks { - fmt.Printf("SSID: %s, RSSI %d \n", network.SSID, network.RSSI) - } - } -} - -func (nc *NetworkConfigure) handleStatusMessage(status int16) (ConfigStatus, error) { - statusMessage := configurationprotocol.StatusBoard[status] - logrus.Debugf("NetworkConfigure: status message received: %s", statusMessage) - - switch statusMessage { - case "Connecting": - return NoneState, nil - case "Connected": - return NoneState, nil - case "Resetted": - return NoneState, nil - case "Scanning for WiFi networks": - return WaitingForNetworkOptions, nil - case "Failed to connect": - return NoneState, errors.New("connection failed invalid credentials or network configuration") - case "Disconnected": - return NoneState, nil - case "Parameters not provided": - return ConfigureNetwork, nil - case "Invalid parameters": - return NoneState, errors.New("the provided parameters for network configuration are invalid") - case "Cannot execute anew request while another is pending": - return NoneState, errors.New("board is busy, restart the board and try again") - case "Invalid request": - return NoneState, errors.New("invalid request sent to the board") - case "Internet not available": - return NoneState, errors.New("internet not available, check your network connection") - case "HW Error connectivity module": - return NoneState, errors.New("hardware error in connectivity module, check the board") - case "HW Connectivity Module stopped": - return NoneState, errors.New("hardware connectivity module stopped, restart the board and check your sketch") - case "Error initializing secure element": - return NoneState, errors.New("error initializing secure element, check the board and try again") - case "Error configuring secure element": - return NoneState, errors.New("error configuring secure element, check the board and try again") - case "Error locking secure element": - return NoneState, errors.New("error locking secure element, check the board and try again") - case "Error generating UHWID": - return NoneState, errors.New("error generating UHWID, check the board and try again") - case "Error storage begin module": - return NoneState, errors.New("error beginning storage module, check the board storage partitioning and try again") - case "Fail to partition the storage": - return NoneState, errors.New("failed to partition the storage, check the board storage and try again") - case "Generic error": - return NoneState, errors.New("generic error, check the board and try again") - default: - return NoneState, errors.New("generic error, check the board and try again") - } - -} diff --git a/internal/board-protocols/configuration-protocol/configuration_protocol.go b/internal/board-protocols/configuration-protocol/configuration_protocol.go index cfff4382..3d275cc7 100644 --- a/internal/board-protocols/configuration-protocol/configuration_protocol.go +++ b/internal/board-protocols/configuration-protocol/configuration_protocol.go @@ -19,6 +19,7 @@ package configurationprotocol import ( "fmt" + "time" "github.com/arduino/arduino-cloud-cli/internal/board-protocols/configuration-protocol/cborcoders" "github.com/arduino/arduino-cloud-cli/internal/board-protocols/frame" @@ -111,6 +112,7 @@ func (ncp *NetworkConfigurationProtocol) Close() error { if err != nil { return fmt.Errorf("error sending end of transmission: %w", err) } + time.Sleep(1 * time.Second) } err := (*ncp.transport).Close() From dd1471ae8cd8c8242a647b2ccb05bce90978bf02 Mon Sep 17 00:00:00 2001 From: fabik111 Date: Fri, 22 Aug 2025 17:48:05 +0200 Subject: [PATCH 05/27] draft FSM for provisioning 2.0 --- command/device/create.go | 1 + command/device/provisionv2.go | 485 ++++++++++++++++++++++++++++++- internal/provisioning-api/dto.go | 2 +- 3 files changed, 479 insertions(+), 9 deletions(-) diff --git a/command/device/create.go b/command/device/create.go index 399d13f9..b792764d 100644 --- a/command/device/create.go +++ b/command/device/create.go @@ -93,6 +93,7 @@ func Create(ctx context.Context, params *CreateParams, cred *config.Credentials) var devInfo *DeviceInfo if boardProvisioningDetails.Provisioning != nil && *boardProvisioningDetails.Provisioning == "v2" { //TODO ADD function for V2 provisioning + // TODO check if ConnectionType is null } else { logrus.Info("Provisioning V1 started") devInfo, err = runProvisioningV1(ctx, params, &comm, iotClient, board) diff --git a/command/device/provisionv2.go b/command/device/provisionv2.go index e60774e0..3ab3a316 100644 --- a/command/device/provisionv2.go +++ b/command/device/provisionv2.go @@ -18,31 +18,500 @@ package device import ( + "errors" + "fmt" + "strconv" + "strings" + "time" + "github.com/arduino/arduino-cloud-cli/arduino" configurationprotocol "github.com/arduino/arduino-cloud-cli/internal/board-protocols/configuration-protocol" + "github.com/arduino/arduino-cloud-cli/internal/board-protocols/configuration-protocol/cborcoders" "github.com/arduino/arduino-cloud-cli/internal/board-protocols/transport" provisioningapi "github.com/arduino/arduino-cloud-cli/internal/provisioning-api" + "github.com/sirupsen/logrus" ) +type ConnectedBoardInfos struct { + UHWID string + PublicKey string + Signature string + BLEMacAddress string +} + type ProvisionV2 struct { arduino.Commander - provisioningClient *provisioningapi.ProvisioningApiClient - serial transport.TransportInterface - provProt *configurationprotocol.NetworkConfigurationProtocol - board *board - id string + provisioningClient *provisioningapi.ProvisioningApiClient + extInterface transport.TransportInterface + provProt *configurationprotocol.NetworkConfigurationProtocol + board *board + boardProvDetails provisioningapi.BoardType + state ConfigStatus + configStates *ConfigurationStates + connectedBoardInfos ConnectedBoardInfos + provParams *CreateParams + provisioningId string } -func NewProvisionV2(provisioningClient *provisioningapi.ProvisioningApiClient, serial transport.TransportInterface, provProt *configurationprotocol.NetworkConfigurationProtocol, board *board, id string) *ProvisionV2 { +func NewProvisionV2(provisioningClient *provisioningapi.ProvisioningApiClient, extInterface transport.TransportInterface, provProt *configurationprotocol.NetworkConfigurationProtocol, board *board, boardProvDetails provisioningapi.BoardType, provParams *CreateParams) *ProvisionV2 { return &ProvisionV2{ provisioningClient: provisioningClient, - serial: serial, + extInterface: extInterface, provProt: provProt, board: board, - id: id, + boardProvDetails: boardProvDetails, + configStates: NewConfigurationStates(extInterface, provProt), + provParams: provParams, } } func (p *ProvisionV2) run() error { + var err error + err = p.provProt.Connect(p.board.address) + if err != nil { + return err + } + p.state = WaitForConnection + var nextState ConfigStatus + + for p.state != End { + + switch p.state { + case WaitForConnection: + nextState, err = p.configStates.WaitForConnection() + if err != nil { + nextState = End + } + p.state = nextState + case WaitingForInitialStatus: + nextState, err = p.configStates.WaitingForInitialStatus() + if err != nil { + nextState = End + } + p.state = nextState + case WaitingForNetworkOptions: + nextState, err = p.configStates.WaitingForNetworkOptions() + if err != nil { + nextState = FlashProvisioningSketch + } + p.state = nextState + case BoardReady: + p.state = GetSketchVersionRequest + //TODO complete the FSM + case GetSketchVersionRequest: + err = p.getSketchVersionRequest() + case ConfigureNetwork: + nextState, err = p.configStates.ConfigureNetwork(ctx, netConfig) + if err != nil { + nextState = End + } + p.state = nextState + case SendConnectionRequest: + nextState, err = p.configStates.SendConnectionRequest() + if err != nil { + nextState = End + } + p.state = nextState + case WaitingForConnectionCommandResult: + nextState, err = p.configStates.WaitingForConnectionCommandResult() + if err != nil { + nextState = End + } + p.state = nextState + case MissingParameter: + p.state = ConfigureNetwork + case WaitingForNetworkConfigResult: + nextState, err = p.configStates.WaitingForNetworkConfigResult() + if err != nil { + nextState = End + } + p.state = nextState + } + + } + + p.provProt.Close() + return err +} + +func (p *ProvisionV2) getSketchVersionRequest() error { + logrus.Info("Provisioning V2: Requesting Sketch Version") + getSketchVersionMessage := cborcoders.From(cborcoders.ProvisioningCommandsMessage{Command: configurationprotocol.Commands["GetSketchVersion"]}) + err := p.provProt.SendData(getSketchVersionMessage) + if err != nil { + return err + } + p.state = WaitingSketchVersion + return nil +} + +/* + * This function returns + * - <0 if version1 < version2 + * - 0 if version1 == version2 + * - >0 if version1 > version2 + */ +func (p *ProvisionV2) compareVersions(version1, version2 string) int { + version1Tokens := strings.Split(version1, ".") + version2Tokens := strings.Split(version2, ".") + if len(version1Tokens) != len(version2Tokens) { + return -1 + } + for i := 0; i < len(version1Tokens) && i < len(version2Tokens); i++ { + version1Num, _ := strconv.Atoi(version1Tokens[i]) + version2Num, _ := strconv.Atoi(version2Tokens[i]) + if version1Num != version2Num { + return version1Num - version2Num + } + } + return 0 +} + +func (p *ProvisionV2) waitingSketchVersion() error { + res, err := p.provProt.ReceiveData(60) + if err != nil { + return err + } + + if res == nil { + logrus.Error("Provisioning V2: Requesting sketch Version failed, flashing...") + p.state = FlashProvisioningSketch + return nil + } + + if res.Type() == cborcoders.ProvisioningSketchVersionMessageType { + sketch_version := res.ToProvisioningSketchVersionMessage().ProvisioningSketchVersion + logrus.Info("Provisioning V2: Received Sketch Version %s", sketch_version) + + if p.boardProvDetails.MinProvSketchVersion != nil && + p.compareVersions(sketch_version, *p.boardProvDetails.MinProvSketchVersion) < 0 { + logrus.Info("Provisioning V2: Sketch version %s is lower than required minimum %s. Updating...", sketch_version, *p.boardProvDetails.MinProvSketchVersion) + p.state = FlashProvisioningSketch + return nil + } + + p.state = WiFiFWVersionRequest + } else if res.Type() == cborcoders.ProvisioningStatusMessageType { + status := res.ToProvisioningStatusMessage() + newState, err := p.configStates.HandleStatusMessage(status.Status) + if err != nil { + return err + } + if newState != NoneState { + p.state = newState + return nil + } + } + + return nil +} + +func (p *ProvisionV2) getWiFiFWVersionRequest() error { + logrus.Info("Provisioning V2: Requesting WiFi FW Version") + getWiFiFWVersionMessage := cborcoders.From(cborcoders.ProvisioningCommandsMessage{Command: configurationprotocol.Commands["GetWiFiFWVersion"]}) + err := p.provProt.SendData(getWiFiFWVersionMessage) + if err != nil { + return err + } + p.state = WaitingWiFiFWVersion + time.Sleep(1 * time.Second) + return nil +} + +func (p *ProvisionV2) waitWiFiFWVersion() error { + res, err := p.provProt.ReceiveData(60) + if err != nil { + return err + } + + if res == nil { + return errors.New("Provisioning V2: Requesting WiFi FW Version failed") + } + + if res.Type() == cborcoders.ProvisioningWiFiFWVersionMessageType { + wifi_version := res.ToProvisioningWiFiFWVersionMessage().WiFiFWVersion + fmt.Printf("Received WiFi FW Version: %s\n", wifi_version) + if p.boardProvDetails.MinWiFiVersion != nil && + p.compareVersions(wifi_version, *p.boardProvDetails.MinWiFiVersion) < 0 { + return fmt.Errorf("Provisioning V2: WiFi FW version %s is lower than required minimum %s. Please update the board firmware using Arduino IDE or Arduino CLI", wifi_version, *p.boardProvDetails.MinWiFiVersion) + } + p.state = RequestBLEMAC + + } else if res.Type() == cborcoders.ProvisioningStatusMessageType { + status := res.ToProvisioningStatusMessage() + newState, err := p.configStates.HandleStatusMessage(status.Status) + if err != nil { + return err + } + if newState != NoneState { + p.state = newState + return nil + } + } + return errors.New("Provisioning V2: WiFi FW version not received") +} + +func (p *ProvisionV2) BLEMacRequest() error { + logrus.Info("Provisioning V2: Requesting BLE MAC") + getblemacMessage := cborcoders.From(cborcoders.ProvisioningCommandsMessage{Command: configurationprotocol.Commands["GetBLEMac"]}) + err := p.provProt.SendData(getblemacMessage) + if err != nil { + return err + } + p.state = WaitBLEMAC + time.Sleep(1 * time.Second) + return nil +} + +func (p *ProvisionV2) waitBLEMac() error { + res, err := p.provProt.ReceiveData(60) + if err != nil { + return err + } + + if res == nil { + return errors.New("Provisioning V2: BLEMac was not received") + } + + if res.Type() == cborcoders.ProvisioningBLEMacAddressMessageType { + mac := res.ToProvisioningBLEMacAddressMessage().BLEMacAddress + logrus.Info("Provisioning V2: Received MAC in hex: %02X\n", mac) + macStr := fmt.Sprintf("%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]) + p.connectedBoardInfos.BLEMacAddress = macStr + p.state = SendInitialTS + } else if res.Type() == cborcoders.ProvisioningStatusMessageType { + status := res.ToProvisioningStatusMessage() + newState, err := p.configStates.HandleStatusMessage(status.Status) + if err != nil { + return err + } + if newState != NoneState { + p.state = newState + return nil + } + } + return errors.New("Provisioning V2: BLE MAC address not received") +} + +func (p *ProvisionV2) sendInitialTS() error { + logrus.Info("Provisioning V2: Sending initial timestamp") + ts := time.Now().Unix() + logrus.Infof("Provisioning V2: Sending timestamp: %d\n", ts) + tsMessage := cborcoders.From(cborcoders.ProvisioningTimestampMessage{Timestamp: uint64(ts)}) + err := p.provProt.SendData(tsMessage) + if err != nil { + return err + } + p.state = UUIDRequest + time.Sleep(1 * time.Second) + return nil +} + +func (p *ProvisionV2) uidRequest() error { + logrus.Info("Provisioning V2: Requesting UniqueID") + getuuidMessage := cborcoders.From(cborcoders.ProvisioningCommandsMessage{Command: configurationprotocol.Commands["GetID"]}) + err := p.provProt.SendData(getuuidMessage) + if err != nil { + return err + } + p.state = WaitingPublicKey + return nil +} + +func (p *ProvisionV2) waitingPublicKey() error { + res, err := p.provProt.ReceiveData(60) + if err != nil { + return err + } + + if res == nil { + return errors.New("Provisioning V2: public key was not received") + } + + if res.Type() == cborcoders.ProvisioningPublicKeyMessageType { + pubKey := res.ToProvisioningPublicKeyMessage().ProvisioningPublicKey + logrus.Infof("Provisioning V2: Received Public Key\n") + p.connectedBoardInfos.PublicKey = pubKey + p.state = WaitingUUID + } else if res.Type() == cborcoders.ProvisioningStatusMessageType { + status := res.ToProvisioningStatusMessage() + newState, err := p.configStates.HandleStatusMessage(status.Status) + if err != nil { + return err + } + if newState == MissingParameter { + p.state = SendInitialTS + return nil + } + + if newState != NoneState { + p.state = newState + return nil + } + } + return errors.New("Provisioning V2: Public Key not received") +} + +func (p *ProvisionV2) waitingUID() error { + res, err := p.provProt.ReceiveData(60) + if err != nil { + return err + } + + if res == nil { + return errors.New("Provisioning V2: UniqueID was not received") + } + + if res.Type() == cborcoders.ProvisioningUniqueIdMessageType { + uid := res.ToProvisioningUniqueIdMessage().UniqueId + logrus.Infof("Provisioning V2: Received UniqueID\n") + uidString := string(uid[:]) + p.connectedBoardInfos.UHWID = uidString + p.state = WaitingSignature + } else if res.Type() == cborcoders.ProvisioningStatusMessageType { + status := res.ToProvisioningStatusMessage() + newState, err := p.configStates.HandleStatusMessage(status.Status) + if err != nil { + return err + } + if newState == MissingParameter { + p.state = SendInitialTS + return nil + } + + if newState != NoneState { + p.state = newState + return nil + } + } + return errors.New("Provisioning V2: UniqueID was not received") +} + +func (p *ProvisionV2) waitingSignature() error { + res, err := p.provProt.ReceiveData(60) + if err != nil { + return err + } + + if res == nil { + return errors.New("Provisioning V2: Signature was not received") + } + + if res.Type() == cborcoders.ProvisioningSignatureMessageType { + signature := res.ToProvisioningSignatureMessage().Signature + logrus.Infof("Provisioning V2: Received Signature\n") + p.connectedBoardInfos.Signature = string(signature[:]) + p.state = ClaimDevice + } else if res.Type() == cborcoders.ProvisioningStatusMessageType { + status := res.ToProvisioningStatusMessage() + newState, err := p.configStates.HandleStatusMessage(status.Status) + if err != nil { + return err + } + + if newState != NoneState { + p.state = newState + return nil + } + } + return errors.New("Provisioning V2: Signature was not received") +} + +func (p *ProvisionV2) claimDevice() error { + logrus.Info("Provisioning V2: Claiming device...") + + claimData := provisioningapi.ClaimData{ + BLEMac: p.connectedBoardInfos.BLEMacAddress, + BoardToken: p.connectedBoardInfos.Signature, + ConnectionType: *p.provParams.ConnectionType, + DeviceName: p.provParams.Name, + } + + provResp, provErr, err := p.provisioningClient.ClaimDevice(claimData) + if err != nil { + return err + } + + if provErr != nil { + if provErr.ErrCode == 1 || provErr.ErrCode == 2 { + logrus.Warn("Provisioning V2: Device claim failed. The board has to migrate") + p.state = RegisterDevice + } else if provErr.ErrCode == 3 { + // If the device key and the DB key are different + return fmt.Errorf("Provisioning V2: Device claim failed. Keys do not match. Please contact the Arduino Support with this hardware id: %s", p.connectedBoardInfos.UHWID) + } else { + return fmt.Errorf("Provisioning V2: Device claim failed with error: %s", provErr.Err) + } + } + + if provResp != nil { + p.provisioningId = provResp.OnboardId + p.state = RequestReset + return nil + } + + return errors.New("Provisioning V2: Device ID not received") +} + +func (p *ProvisionV2) RegisterDevice() error { + logrus.Info("Provisioning V2: Registering device...") + + registerData := provisioningapi.RegisterBoardData{ + PID: p.boardProvDetails.Type, + PublicKey: p.connectedBoardInfos.PublicKey, + Serial: &p.board.serial, + UniqueHardwareID: p.connectedBoardInfos.UHWID, + VID: p.board.dType, //TODO ask for sending fqbn + } + + provErr, err := p.provisioningClient.RegisterDevice(registerData) + if err != nil { + return err + } + + if provErr != nil { + return fmt.Errorf("Provisioning V2: Device registration failed with error: %s", provErr.Err) + } + + logrus.Info("Provisioning V2: Device registered successfully, claiming...") + p.state = ClaimDevice + return nil +} + +func (p *ProvisionV2) ResetRequest() error { + logrus.Info("Provisioning V2: Requesting Reset Stored Credentials") + resetMessage := cborcoders.From(cborcoders.ProvisioningCommandsMessage{Command: configurationprotocol.Commands["Reset"]}) + err := p.provProt.SendData(resetMessage) + if err != nil { + return err + } + p.state = WaitResetResponse + return nil +} + +func (p *ProvisionV2) waitingForResetResult() error { + res, err := p.provProt.ReceiveData(60) + if err != nil { + return err + } + + if res != nil && res.Type() == cborcoders.ProvisioningStatusMessageType { + status := res.ToProvisioningStatusMessage() + if status.Status == 4 { + logrus.Info("Provisioning V2: Reset Stored Credentials successful") + p.state = ConfigureNetwork + } else { + newState, err := p.configStates.HandleStatusMessage(status.Status) + if err != nil { + return err + } + + if newState != NoneState { + p.state = newState + return nil + } + } + } + return errors.New("Provisioning V2: Reset Stored Credentials failed") } diff --git a/internal/provisioning-api/dto.go b/internal/provisioning-api/dto.go index af6f91ad..06a13a70 100644 --- a/internal/provisioning-api/dto.go +++ b/internal/provisioning-api/dto.go @@ -38,7 +38,7 @@ type BadResponse struct { } type ClaimResponse struct { - BoardId string `json:"id"` + OnboardId string `json:"id"` } type BoardType struct { From fff4460883b9caa8abf12ccd9a77df823a30a454 Mon Sep 17 00:00:00 2001 From: fabik111 Date: Mon, 25 Aug 2025 18:05:14 +0200 Subject: [PATCH 06/27] move map for fqbn and vid and pid to package boardpids --- command/ota/generate.go | 9 ++++---- internal/{ota => boardpids}/boardpids.go | 28 +++++++++++++----------- internal/ota/decoder_test.go | 13 ++++++----- 3 files changed, 27 insertions(+), 23 deletions(-) rename internal/{ota => boardpids}/boardpids.go (70%) diff --git a/command/ota/generate.go b/command/ota/generate.go index 50663222..caf1eaa9 100644 --- a/command/ota/generate.go +++ b/command/ota/generate.go @@ -23,6 +23,7 @@ import ( "os" "strings" + "github.com/arduino/arduino-cloud-cli/internal/boardpids" inota "github.com/arduino/arduino-cloud-cli/internal/ota" ) @@ -37,12 +38,12 @@ func Generate(binFile string, outFile string, fqbn string) error { // Esp32 boards have a wide range of vid and pid, we don't map all of them // If the fqbn is the one of an ESP32 board, we force a default magic number that matches the same default expected on the fw side if !strings.HasPrefix(fqbn, "arduino:esp32") && strings.HasPrefix(fqbn, "esp32") { - magicNumberPart1 = inota.Esp32MagicNumberPart1 - magicNumberPart2 = inota.Esp32MagicNumberPart2 + magicNumberPart1 = boardpids.Esp32MagicNumberPart1 + magicNumberPart2 = boardpids.Esp32MagicNumberPart2 } else { //For Arduino Boards we use vendorId and productID to form the magic number - magicNumberPart1 = inota.ArduinoVendorID - productID, ok := inota.ArduinoFqbnToPID[fqbn] + magicNumberPart1 = boardpids.ArduinoVendorID + productID, ok := boardpids.ArduinoFqbnToPID[fqbn] if !ok { return errors.New("fqbn not valid") } diff --git a/internal/ota/boardpids.go b/internal/boardpids/boardpids.go similarity index 70% rename from internal/ota/boardpids.go rename to internal/boardpids/boardpids.go index 6b4b824f..78733c12 100644 --- a/internal/ota/boardpids.go +++ b/internal/boardpids/boardpids.go @@ -15,7 +15,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -package ota +package boardpids var ( BoardTypes = map[uint32]string{ @@ -44,21 +44,23 @@ var ( "025F": "arduino:mbed_nicla:nicla_vision", "0064": "arduino:mbed_opta:opta", "0266": "arduino:mbed_giga:giga", + "0068": "arduino:renesas_portenta:portenta_c33", } ArduinoFqbnToPID = map[string]string{ - "arduino:samd:nano_33_iot": "8057", - "arduino:samd:mkr1000": "804E", - "arduino:samd:mkrgsm1400": "8052", - "arduino:samd:mkrnb1500": "8055", - "arduino:samd:mkrwifi1010": "8054", - "arduino:mbed_nano:nanorp2040connect": "005E", - "arduino:mbed_portenta:envie_m7": "025B", - "arduino:mbed_nicla:nicla_vision": "025F", - "arduino:mbed_opta:opta": "0064", - "arduino:mbed_giga:giga": "0266", - "arduino:renesas_uno:unor4wifi": "1002", - "arduino:esp32:nano_nora": "0070", + "arduino:samd:nano_33_iot": "8057", + "arduino:samd:mkr1000": "804E", + "arduino:samd:mkrgsm1400": "8052", + "arduino:samd:mkrnb1500": "8055", + "arduino:samd:mkrwifi1010": "8054", + "arduino:mbed_nano:nanorp2040connect": "005E", + "arduino:mbed_portenta:envie_m7": "025B", + "arduino:mbed_nicla:nicla_vision": "025F", + "arduino:mbed_opta:opta": "0064", + "arduino:mbed_giga:giga": "0266", + "arduino:renesas_uno:unor4wifi": "1002", + "arduino:esp32:nano_nora": "0070", + "arduino:renesas_portenta:portenta_c33": "0068", } ArduinoVendorID = "2341" diff --git a/internal/ota/decoder_test.go b/internal/ota/decoder_test.go index 49290b91..5b3d9347 100644 --- a/internal/ota/decoder_test.go +++ b/internal/ota/decoder_test.go @@ -3,6 +3,7 @@ package ota import ( "testing" + "github.com/arduino/arduino-cloud-cli/internal/boardpids" "github.com/stretchr/testify/assert" ) @@ -10,17 +11,17 @@ func TestDecodeHeader(t *testing.T) { header, err := DecodeOtaFirmwareHeaderFromFile("testdata/cloud.ota") assert.Nil(t, err) - assert.Equal(t, ArduinoVendorID, header.VID) + assert.Equal(t, boardpids.ArduinoVendorID, header.VID) assert.Equal(t, "8057", header.PID) assert.Equal(t, "arduino:samd:nano_33_iot", *header.FQBN) - assert.Equal(t, ArduinoFqbnToPID["arduino:samd:nano_33_iot"], header.PID) + assert.Equal(t, boardpids.ArduinoFqbnToPID["arduino:samd:nano_33_iot"], header.PID) header, err = DecodeOtaFirmwareHeaderFromFile("testdata/blink.ota") assert.Nil(t, err) - assert.Equal(t, ArduinoVendorID, header.VID) + assert.Equal(t, boardpids.ArduinoVendorID, header.VID) assert.Equal(t, "8057", header.PID) assert.Equal(t, "arduino:samd:nano_33_iot", *header.FQBN) - assert.Equal(t, ArduinoFqbnToPID["arduino:samd:nano_33_iot"], header.PID) + assert.Equal(t, boardpids.ArduinoFqbnToPID["arduino:samd:nano_33_iot"], header.PID) } @@ -40,8 +41,8 @@ func TestDecodeEsp32Header(t *testing.T) { header, err := DecodeOtaFirmwareHeaderFromFile("testdata/esp32.ota") assert.Nil(t, err) - assert.Equal(t, Esp32MagicNumberPart1, header.VID) - assert.Equal(t, Esp32MagicNumberPart2, header.PID) + assert.Equal(t, boardpids.Esp32MagicNumberPart1, header.VID) + assert.Equal(t, boardpids.Esp32MagicNumberPart2, header.PID) assert.Nil(t, header.FQBN) assert.Equal(t, "ESP32", header.BoardType) From 71e4b8ba96b1646fa5426379d310a832f5f2250d Mon Sep 17 00:00:00 2001 From: fabik111 Date: Mon, 25 Aug 2025 18:06:45 +0200 Subject: [PATCH 07/27] move function for getting network configuration from the user to command/device package --- cli/device/configure.go | 119 +----------------------------- command/device/configure.go | 139 ++++++++++++++++++++++++++++++++---- 2 files changed, 126 insertions(+), 132 deletions(-) diff --git a/cli/device/configure.go b/cli/device/configure.go index c8834640..713a512a 100644 --- a/cli/device/configure.go +++ b/cli/device/configure.go @@ -20,11 +20,7 @@ package device import ( "context" "encoding/json" - "errors" - "fmt" - "net" "os" - "strings" "github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/feedback" @@ -83,7 +79,7 @@ func runConfigureCommand(flags *netConfigurationFlags) error { } } else { feedback.Print("Insert network configuration") - getInputFromMenu(netParams) + device.GetInputFromMenu(netParams) } boardFilterParams := &device.CreateParams{} @@ -105,116 +101,3 @@ func runConfigureCommand(flags *netConfigurationFlags) error { feedback.Print("Network configuration successfully completed.") return nil } - -func getInputFromMenu(config *device.NetConfig) error { - - switch config.Type { - case 1: - config.WiFi = getWiFiSetting() - case 2: - config.Eth = getEthernetSetting() - case 3: - config.NB = getCellularSetting() - case 4: - config.GSM = getCellularSetting() - case 5: - config.Lora = getLoraSetting() - case 6: - config.CATM1 = getCatM1Setting() - case 7: - config.CellularSetting = getCellularSetting() - default: - return errors.New("invalid connection type, please try again") - } - return nil -} - -func getWiFiSetting() device.WiFiSetting { - var wifi device.WiFiSetting - fmt.Print("Enter SSID: ") - fmt.Scanln(&wifi.SSID) - fmt.Print("Enter Password: ") - fmt.Scanln(&wifi.PWD) - return wifi -} - -func getEthernetSetting() device.EthernetSetting { - var eth device.EthernetSetting - fmt.Println("Do you want to use DHCP? (yes/no): ") - var useDHCP string - fmt.Scanln(&useDHCP) - if useDHCP == "yes" || useDHCP == "y" { - eth.IP = device.IPAddr{Type: 0, Bytes: [16]byte{}} - eth.Gateway = device.IPAddr{Type: 0, Bytes: [16]byte{}} - eth.Netmask = device.IPAddr{Type: 0, Bytes: [16]byte{}} - eth.DNS = device.IPAddr{Type: 0, Bytes: [16]byte{}} - } else { - fmt.Println("Enter IP Address: ") - eth.IP = getIPAddr() - fmt.Println("Enter DNS: ") - eth.DNS = getIPAddr() - fmt.Println("Enter Gateway: ") - eth.Gateway = getIPAddr() - fmt.Println("Enter Netmask: ") - eth.Netmask = getIPAddr() - } - - return eth -} - -func getIPAddr() device.IPAddr { - var ip device.IPAddr - var ipString string - fmt.Scanln(&ipString) - if ipString == "" { - return ip - } - if strings.Count(ipString, ":") > 0 { - ip.Type = 1 // IPv6 - } else { - ip.Type = 0 // IPv4 - } - ip.Bytes = [16]byte(net.ParseIP(ipString).To16()) - return ip -} - -func getCellularSetting() device.CellularSetting { - var cellular device.CellularSetting - fmt.Println("Enter PIN: ") - fmt.Scanln(&cellular.PIN) - fmt.Print("Enter APN: ") - fmt.Scanln(&cellular.APN) - fmt.Print("Enter Login: ") - fmt.Scanln(&cellular.Login) - fmt.Print("Enter Password: ") - fmt.Scanln(&cellular.Pass) - return cellular -} - -func getCatM1Setting() device.CATM1Setting { - var catm1 device.CATM1Setting - fmt.Print("Enter PIN: ") - fmt.Scanln(&catm1.PIN) - fmt.Print("Enter APN: ") - fmt.Scanln(&catm1.APN) - fmt.Print("Enter Login: ") - fmt.Scanln(&catm1.Login) - fmt.Print("Enter Password: ") - fmt.Scanln(&catm1.Pass) - return catm1 -} - -func getLoraSetting() device.LoraSetting { - var lora device.LoraSetting - fmt.Print("Enter AppEUI: ") - fmt.Scanln(&lora.AppEUI) - fmt.Print("Enter AppKey: ") - fmt.Scanln(&lora.AppKey) - fmt.Print("Enter Band (Byte hex format): ") - fmt.Scanln(&lora.Band) - fmt.Print("Enter Channel Mask: ") - fmt.Scanln(&lora.ChannelMask) - fmt.Print("Enter Device Class: ") - fmt.Scanln(&lora.DeviceClass) - return lora -} diff --git a/command/device/configure.go b/command/device/configure.go index a104736f..f8ac7c2d 100644 --- a/command/device/configure.go +++ b/command/device/configure.go @@ -20,6 +20,9 @@ package device import ( "context" "errors" + "fmt" + "net" + "strings" "github.com/arduino/arduino-cloud-cli/arduino/cli" configurationprotocol "github.com/arduino/arduino-cloud-cli/internal/board-protocols/configuration-protocol" @@ -58,9 +61,121 @@ func NetConfigure(ctx context.Context, boardFilters *CreateParams, NetConfig *Ne return err } +func GetInputFromMenu(config *NetConfig) error { + + switch config.Type { + case 1: + config.WiFi = getWiFiSetting() + case 2: + config.Eth = getEthernetSetting() + case 3: + config.NB = getCellularSetting() + case 4: + config.GSM = getCellularSetting() + case 5: + config.Lora = getLoraSetting() + case 6: + config.CATM1 = getCatM1Setting() + case 7: + config.CellularSetting = getCellularSetting() + default: + return errors.New("invalid connection type, please try again") + } + return nil +} + +func getWiFiSetting() WiFiSetting { + var wifi WiFiSetting + fmt.Print("Enter SSID: ") + fmt.Scanln(&wifi.SSID) + fmt.Print("Enter Password: ") + fmt.Scanln(&wifi.PWD) + return wifi +} + +func getEthernetSetting() EthernetSetting { + var eth EthernetSetting + fmt.Println("Do you want to use DHCP? (yes/no): ") + var useDHCP string + fmt.Scanln(&useDHCP) + if useDHCP == "yes" || useDHCP == "y" { + eth.IP = IPAddr{Type: 0, Bytes: [16]byte{}} + eth.Gateway = IPAddr{Type: 0, Bytes: [16]byte{}} + eth.Netmask = IPAddr{Type: 0, Bytes: [16]byte{}} + eth.DNS = IPAddr{Type: 0, Bytes: [16]byte{}} + } else { + fmt.Println("Enter IP Address: ") + eth.IP = getIPAddr() + fmt.Println("Enter DNS: ") + eth.DNS = getIPAddr() + fmt.Println("Enter Gateway: ") + eth.Gateway = getIPAddr() + fmt.Println("Enter Netmask: ") + eth.Netmask = getIPAddr() + } + + return eth +} + +func getIPAddr() IPAddr { + var ip IPAddr + var ipString string + fmt.Scanln(&ipString) + if ipString == "" { + return ip + } + if strings.Count(ipString, ":") > 0 { + ip.Type = 1 // IPv6 + } else { + ip.Type = 0 // IPv4 + } + ip.Bytes = [16]byte(net.ParseIP(ipString).To16()) + return ip +} + +func getCellularSetting() CellularSetting { + var cellular CellularSetting + fmt.Println("Enter PIN: ") + fmt.Scanln(&cellular.PIN) + fmt.Print("Enter APN: ") + fmt.Scanln(&cellular.APN) + fmt.Print("Enter Login: ") + fmt.Scanln(&cellular.Login) + fmt.Print("Enter Password: ") + fmt.Scanln(&cellular.Pass) + return cellular +} + +func getCatM1Setting() CATM1Setting { + var catm1 CATM1Setting + fmt.Print("Enter PIN: ") + fmt.Scanln(&catm1.PIN) + fmt.Print("Enter APN: ") + fmt.Scanln(&catm1.APN) + fmt.Print("Enter Login: ") + fmt.Scanln(&catm1.Login) + fmt.Print("Enter Password: ") + fmt.Scanln(&catm1.Pass) + return catm1 +} + +func getLoraSetting() LoraSetting { + var lora LoraSetting + fmt.Print("Enter AppEUI: ") + fmt.Scanln(&lora.AppEUI) + fmt.Print("Enter AppKey: ") + fmt.Scanln(&lora.AppKey) + fmt.Print("Enter Band (Byte hex format): ") + fmt.Scanln(&lora.Band) + fmt.Print("Enter Channel Mask: ") + fmt.Scanln(&lora.ChannelMask) + fmt.Print("Enter Device Class: ") + fmt.Scanln(&lora.DeviceClass) + return lora +} + type NetworkConfigure struct { configStates *ConfigurationStates - state ConfigStatus configProtocol *configurationprotocol.NetworkConfigurationProtocol } @@ -72,60 +187,56 @@ func NewNetworkConfigure(extInterface transport.TransportInterface, configProtoc } func (nc *NetworkConfigure) Run(ctx context.Context, netConfig *NetConfig) error { - nc.state = WaitForConnection + state := WaitForConnection + nextState := state var err error - var nextState ConfigStatus - for nc.state != End { - switch nc.state { + for state != End { + + switch state { case WaitForConnection: nextState, err = nc.configStates.WaitForConnection() if err != nil { nextState = End } - nc.state = nextState case WaitingForInitialStatus: nextState, err = nc.configStates.WaitingForInitialStatus() if err != nil { nextState = End } - nc.state = nextState case WaitingForNetworkOptions: nextState, err = nc.configStates.WaitingForNetworkOptions() if err != nil { nextState = End } - nc.state = nextState case BoardReady: - nc.state = ConfigureNetwork + nextState = ConfigureNetwork case ConfigureNetwork: nextState, err = nc.configStates.ConfigureNetwork(ctx, netConfig) if err != nil { nextState = End } - nc.state = nextState case SendConnectionRequest: nextState, err = nc.configStates.SendConnectionRequest() if err != nil { nextState = End } - nc.state = nextState case WaitingForConnectionCommandResult: nextState, err = nc.configStates.WaitingForConnectionCommandResult() if err != nil { nextState = End } - nc.state = nextState case MissingParameter: - nc.state = ConfigureNetwork + nextState = ConfigureNetwork case WaitingForNetworkConfigResult: nextState, err = nc.configStates.WaitingForNetworkConfigResult() if err != nil { nextState = End } - nc.state = nextState } + state = nextState + } nc.configProtocol.Close() From 8176c88e6cc046d433dff16613c7bb32354d3ebc Mon Sep 17 00:00:00 2001 From: fabik111 Date: Mon, 25 Aug 2025 18:07:34 +0200 Subject: [PATCH 08/27] add connected method to NetworkConfigurationProtocol --- .../configuration-protocol/configuration_protocol.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/internal/board-protocols/configuration-protocol/configuration_protocol.go b/internal/board-protocols/configuration-protocol/configuration_protocol.go index 3d275cc7..ea467ae5 100644 --- a/internal/board-protocols/configuration-protocol/configuration_protocol.go +++ b/internal/board-protocols/configuration-protocol/configuration_protocol.go @@ -100,6 +100,13 @@ func (ncp *NetworkConfigurationProtocol) Connect(address string) error { } +func (ncp *NetworkConfigurationProtocol) Connected() bool { + if ncp.transport == nil || *ncp.transport == nil { + return false + } + return (*ncp.transport).Connected() +} + func (ncp *NetworkConfigurationProtocol) Close() error { if ncp.transport == nil || *ncp.transport == nil { return fmt.Errorf("NetworkConfigurationProtocol: transport interface is not initialized") From ebad5c280fd1e8bcc64e4b1f6a9c36699fdfa585 Mon Sep 17 00:00:00 2001 From: fabik111 Date: Mon, 25 Aug 2025 18:08:17 +0200 Subject: [PATCH 09/27] add iot-api raw client --- internal/iot-api-raw/client.go | 161 ++++++++++++++++++++++++++++ internal/iot-api-raw/dto.go | 23 ++++ internal/provisioning-api/client.go | 41 +------ internal/provisioning-api/dto.go | 14 --- 4 files changed, 185 insertions(+), 54 deletions(-) create mode 100644 internal/iot-api-raw/client.go create mode 100644 internal/iot-api-raw/dto.go diff --git a/internal/iot-api-raw/client.go b/internal/iot-api-raw/client.go new file mode 100644 index 00000000..07a9e90c --- /dev/null +++ b/internal/iot-api-raw/client.go @@ -0,0 +1,161 @@ +package iotapiraw + +import ( + "encoding/base64" + "encoding/json" + "errors" + "fmt" + "io" + "net/http" + "strings" + + "github.com/arduino/arduino-cloud-cli/config" + "github.com/arduino/arduino-cloud-cli/internal/iot" + "github.com/arduino/go-paths-helper" + "golang.org/x/oauth2" +) + +type IoTApiRawClient struct { + client *http.Client + host string + src oauth2.TokenSource + organization string +} + +func NewClient(credentials *config.Credentials) *IoTApiRawClient { + host := iot.GetArduinoAPIBaseURL() + tokenSource := iot.NewUserTokenSource(credentials.Client, credentials.Secret, host, credentials.Organization) + return &IoTApiRawClient{ + client: &http.Client{}, + src: tokenSource, + host: host, + organization: credentials.Organization, + } +} + +func (c *IoTApiRawClient) performRequest(endpoint, method, token string, body io.Reader) (*http.Response, error) { + req, err := http.NewRequest(method, endpoint, body) + if err != nil { + return nil, err + } + req.Header.Add("Authorization", "Bearer "+token) + req.Header.Add("Content-Type", "application/json") + if c.organization != "" { + req.Header.Add("X-Organization", c.organization) + } + res, err := c.client.Do(req) + if err != nil { + return nil, err + } + return res, nil +} + +func (c *IoTApiRawClient) getToken() (*oauth2.Token, error) { + token, err := c.src.Token() + if err != nil { + if strings.Contains(err.Error(), "401") { + return nil, errors.New("wrong credentials") + } + return nil, fmt.Errorf("cannot retrieve a valid token: %w", err) + } + return token, nil +} + +func (c *IoTApiRawClient) GetBoardsDetail() (*BoardTypeList, error) { + endpoint := c.host + "iot/v1/supported/devices" + token, err := c.getToken() + if err != nil { + return nil, err + } + + res, err := c.performRequest(endpoint, http.MethodGet, token.AccessToken, nil) + if err != nil { + return nil, err + } + defer res.Body.Close() + + if res.StatusCode == http.StatusOK { + var response BoardTypeList + + respBytes, err := io.ReadAll(res.Body) + if err != nil { + return nil, err + } + + err = json.Unmarshal(respBytes, &response) + if err != nil { + return nil, err + } + return &response, nil + } else if res.StatusCode == 400 { + return nil, errors.New(endpoint + " returned bad request") + } else if res.StatusCode == 401 { + return nil, errors.New(endpoint + " returned unauthorized request") + } else if res.StatusCode == 403 { + return nil, errors.New(endpoint + " returned forbidden request") + } else if res.StatusCode == 500 { + return nil, errors.New(endpoint + " returned internal server error") + } + + return nil, err +} + +func (c *IoTApiRawClient) DownloadProvisioningV2Sketch(fqbn string, path *paths.Path, filename *string) (string, error) { + endpoint := c.host + "iot/v2/binaries/provisioningv2?fqbn=" + fqbn + token, err := c.getToken() + if err != nil { + return "", err + } + + res, err := c.performRequest(endpoint, http.MethodGet, token.AccessToken, nil) + if err != nil { + return "", err + } + defer res.Body.Close() + + if res.StatusCode == http.StatusOK { + var response Prov2SketchBinRes + respBytes, err := io.ReadAll(res.Body) + if err != nil { + return "", err + } + + err = json.Unmarshal(respBytes, &response) + if err != nil { + return "", err + } + + if filename != nil { + path = path.Join(*filename) + } else { + path = path.Join(response.FileName) + } + + path.Parent().MkdirAll() + + bytes, err := base64.StdEncoding.DecodeString(response.Binary) + if err != nil { + return "", err + } + + if err = path.WriteFile(bytes); err != nil { + return "", fmt.Errorf("writing provisioning v2 binary: %w", err) + } + p, err := path.Abs() + if err != nil { + return "", fmt.Errorf("cannot retrieve absolute path of downloaded provisioning v2 binary: %w", err) + } + return p.String(), nil + } else if res.StatusCode == 400 { + return "", errors.New(endpoint + " returned bad request") + } else if res.StatusCode == 401 { + return "", errors.New(endpoint + " returned unauthorized request") + } else if res.StatusCode == 403 { + return "", errors.New(endpoint + " returned forbidden request") + } else if res.StatusCode == 500 { + return "", errors.New(endpoint + " returned internal server error") + } + + return "", errors.New("failed to download the provisioning v2 binary: unknown error") + +} diff --git a/internal/iot-api-raw/dto.go b/internal/iot-api-raw/dto.go new file mode 100644 index 00000000..69d07968 --- /dev/null +++ b/internal/iot-api-raw/dto.go @@ -0,0 +1,23 @@ +package iotapiraw + +type BoardType struct { + FQBN *string `json:"fqbn,omitempty"` + Label string `json:"label"` + MinProvSketchVersion *string `json:"min_provisioning_sketch_version,omitempty"` + MinWiFiVersion *string `json:"min_provisioning_wifi_version,omitempty"` + Provisioning *string `json:"provisioning,omitempty"` + Tags []string `json:"tags"` + Type string `json:"type"` + Vendor string `json:"vendor"` + OTAAvailable *bool `json:"ota_available,omitempty"` +} + +type BoardTypeList []BoardType + +type Prov2SketchBinRes struct { + Binary string `json:"bin"` + FileName string `json:"filename"` + FQBN string `json:"fqbn"` + Name string `json:"name"` + SHA256 string `json:"sha256"` +} diff --git a/internal/provisioning-api/client.go b/internal/provisioning-api/client.go index 65992ddf..f08563f5 100644 --- a/internal/provisioning-api/client.go +++ b/internal/provisioning-api/client.go @@ -155,7 +155,7 @@ func (c *ProvisioningApiClient) RegisterDevice(data RegisterBoardData) (*BadResp return &badResponse, nil } -func (c *ProvisioningApiClient) Unclaim(provisioningId string) (*BadResponse, error) { +func (c *ProvisioningApiClient) UnclaimDevice(provisioningId string) (*BadResponse, error) { endpoint := c.host + "provisioning/v1/onboarding/" + provisioningId token, err := c.getToken() if err != nil { @@ -237,42 +237,3 @@ func (c *ProvisioningApiClient) GetProvisioningDetail(provID string) (*Onboardin return nil, fmt.Errorf("onboarding with ID %s not found", provID) } - -func (c *ProvisioningApiClient) GetBoardsDetail() (*BoardTypeList, error) { - endpoint := c.host + "iot/v1/supported/devices" - token, err := c.getToken() - if err != nil { - return nil, err - } - - res, err := c.performRequest(endpoint, http.MethodGet, token.AccessToken, nil) - if err != nil { - return nil, err - } - defer res.Body.Close() - - if res.StatusCode == http.StatusOK { - var response BoardTypeList - - respBytes, err := io.ReadAll(res.Body) - if err != nil { - return nil, err - } - - err = json.Unmarshal(respBytes, &response) - if err != nil { - return nil, err - } - return &response, nil - } else if res.StatusCode == 400 { - return nil, errors.New(endpoint + " returned bad request") - } else if res.StatusCode == 401 { - return nil, errors.New(endpoint + " returned unauthorized request") - } else if res.StatusCode == 403 { - return nil, errors.New(endpoint + " returned forbidden request") - } else if res.StatusCode == 500 { - return nil, errors.New(endpoint + " returned internal server error") - } - - return nil, err -} diff --git a/internal/provisioning-api/dto.go b/internal/provisioning-api/dto.go index 06a13a70..f2da081d 100644 --- a/internal/provisioning-api/dto.go +++ b/internal/provisioning-api/dto.go @@ -41,20 +41,6 @@ type ClaimResponse struct { OnboardId string `json:"id"` } -type BoardType struct { - FQBN *string `json:"fqbn,omitempty"` - Label string `json:"label"` - MinProvSketchVersion *string `json:"min_provisioning_sketch_version,omitempty"` - MinWiFiVersion *string `json:"min_provisioning_wifi_version,omitempty"` - Provisioning *string `json:"provisioning,omitempty"` - Tags []string `json:"tags"` - Type string `json:"type"` - Vendor string `json:"vendor"` - OTAAvailable *bool `json:"ota_available,omitempty"` -} - -type BoardTypeList []BoardType - type Onboarding struct { ID string `json:"id"` UniqueHardwareID string `json:"unique_hardware_id"` From 8132fad338b2942709f406c65b9f556ca34aeb19 Mon Sep 17 00:00:00 2001 From: fabik111 Date: Mon, 25 Aug 2025 18:08:51 +0200 Subject: [PATCH 10/27] end fsm for provisioning v2 --- command/device/configurationstates.go | 13 +- command/device/provisionv2.go | 288 +++++++++++++++++++++----- 2 files changed, 238 insertions(+), 63 deletions(-) diff --git a/command/device/configurationstates.go b/command/device/configurationstates.go index be78de58..47a29f1c 100644 --- a/command/device/configurationstates.go +++ b/command/device/configurationstates.go @@ -25,7 +25,6 @@ import ( configurationprotocol "github.com/arduino/arduino-cloud-cli/internal/board-protocols/configuration-protocol" "github.com/arduino/arduino-cloud-cli/internal/board-protocols/configuration-protocol/cborcoders" - "github.com/arduino/arduino-cloud-cli/internal/board-protocols/transport" "github.com/sirupsen/logrus" ) @@ -48,8 +47,8 @@ const ( WaitBLEMAC SendInitialTS MissingParameter - UUIDRequest - WaitingUUID + IDRequest + WaitingID WaitingSignature WaitingPublicKey ClaimDevice @@ -62,23 +61,23 @@ const ( SendConnectionRequest WaitingForConnectionCommandResult WaitingForNetworkConfigResult + WaitingForProvisioningResult + UnclaimDevice End ) type ConfigurationStates struct { - extInterface transport.TransportInterface configProtocol *configurationprotocol.NetworkConfigurationProtocol } -func NewConfigurationStates(extInterface transport.TransportInterface, configProtocol *configurationprotocol.NetworkConfigurationProtocol) *ConfigurationStates { +func NewConfigurationStates(configProtocol *configurationprotocol.NetworkConfigurationProtocol) *ConfigurationStates { return &ConfigurationStates{ - extInterface: extInterface, configProtocol: configProtocol, } } func (c *ConfigurationStates) WaitForConnection() (ConfigStatus, error) { - if c.extInterface.Connected() { + if c.configProtocol.Connected() { return WaitingForInitialStatus, nil } return NoneState, errors.New("impossible to connect with the device") diff --git a/command/device/provisionv2.go b/command/device/provisionv2.go index 3ab3a316..26aebd71 100644 --- a/command/device/provisionv2.go +++ b/command/device/provisionv2.go @@ -18,6 +18,7 @@ package device import ( + "context" "errors" "fmt" "strconv" @@ -25,13 +26,27 @@ import ( "time" "github.com/arduino/arduino-cloud-cli/arduino" + "github.com/arduino/arduino-cloud-cli/config" configurationprotocol "github.com/arduino/arduino-cloud-cli/internal/board-protocols/configuration-protocol" "github.com/arduino/arduino-cloud-cli/internal/board-protocols/configuration-protocol/cborcoders" "github.com/arduino/arduino-cloud-cli/internal/board-protocols/transport" + "github.com/arduino/arduino-cloud-cli/internal/boardpids" + iotapiraw "github.com/arduino/arduino-cloud-cli/internal/iot-api-raw" provisioningapi "github.com/arduino/arduino-cloud-cli/internal/provisioning-api" + "github.com/arduino/go-paths-helper" "github.com/sirupsen/logrus" ) +var connectionTypeIDByName = map[string]int32{ + "wifi": 1, + "eth": 2, + "nb": 3, + "gsm": 4, + "lora": 5, + "catm1": 6, + "cellular": 7, +} + type ConnectedBoardInfos struct { UHWID string PublicKey string @@ -39,36 +54,60 @@ type ConnectedBoardInfos struct { BLEMacAddress string } +type ProvisioningV2BoardParams struct { + fqbn string + address string + protocol string + serial string + minProvSketchVersion string + minWiFiVersion *string + name string + connectionType string + netConfig NetConfig +} + type ProvisionV2 struct { arduino.Commander + iotApiClient *iotapiraw.IoTApiRawClient provisioningClient *provisioningapi.ProvisioningApiClient - extInterface transport.TransportInterface provProt *configurationprotocol.NetworkConfigurationProtocol - board *board - boardProvDetails provisioningapi.BoardType state ConfigStatus configStates *ConfigurationStates connectedBoardInfos ConnectedBoardInfos - provParams *CreateParams provisioningId string + deviceId string } -func NewProvisionV2(provisioningClient *provisioningapi.ProvisioningApiClient, extInterface transport.TransportInterface, provProt *configurationprotocol.NetworkConfigurationProtocol, board *board, boardProvDetails provisioningapi.BoardType, provParams *CreateParams) *ProvisionV2 { +func NewProvisionV2(iotClient *iotapiraw.IoTApiRawClient, credentials *config.Credentials, extInterface transport.TransportInterface) *ProvisionV2 { + provProt := configurationprotocol.NewNetworkConfigurationProtocol(&extInterface) return &ProvisionV2{ - provisioningClient: provisioningClient, - extInterface: extInterface, + iotApiClient: iotClient, + provisioningClient: provisioningapi.NewClient(credentials), provProt: provProt, - board: board, - boardProvDetails: boardProvDetails, - configStates: NewConfigurationStates(extInterface, provProt), - provParams: provParams, + configStates: NewConfigurationStates(provProt), + deviceId: "", + } +} + +func (p *ProvisionV2) connectToBoard(address string) error { + err := p.provProt.Connect(address) + return err +} + +/* + * The function return the Arduino Cloud Device ID of the new created board + * if the process ends successfully. Otherwise, an error + */ +func (p *ProvisionV2) GetProvisioningResult() (string, error) { + if p.deviceId == "" { + return "", errors.New("device not provisioned") } + return p.deviceId, nil } -func (p *ProvisionV2) run() error { +func (p *ProvisionV2) Run(ctx context.Context, params ProvisioningV2BoardParams) error { var err error - err = p.provProt.Connect(p.board.address) - if err != nil { + if err = p.connectToBoard(params.address); err != nil { return err } p.state = WaitForConnection @@ -97,35 +136,123 @@ func (p *ProvisionV2) run() error { p.state = nextState case BoardReady: p.state = GetSketchVersionRequest - //TODO complete the FSM case GetSketchVersionRequest: err = p.getSketchVersionRequest() + if err != nil { + p.state = End + } + case WaitingSketchVersion: + err = p.waitingSketchVersion(params.minProvSketchVersion) + if err != nil { + p.state = End + } + case FlashProvisioningSketch: + err = p.flashProvisioningSketch(ctx, params.fqbn, params.address, params.protocol) + if err != nil { + p.state = End + } + case WiFiFWVersionRequest: + err = p.getWiFiFWVersionRequest() + if err != nil { + p.state = End + } + case WaitingWiFiFWVersion: + err = p.waitWiFiFWVersion(params.minWiFiVersion) + if err != nil { + p.state = End + } + case RequestBLEMAC: + err = p.getBLEMACRequest() + if err != nil { + p.state = End + } + case WaitBLEMAC: + err = p.waitBLEMac() + if err != nil { + p.state = End + } + case SendInitialTS: + err = p.sendInitialTS() + if err != nil { + p.state = End + } + + case IDRequest: + err = p.getIDRequest() + if err != nil { + p.state = End + } + case WaitingPublicKey: + err = p.waitingPublicKey() + if err != nil { + p.state = End + } + case WaitingID: + err = p.waitingUHWID() + if err != nil { + p.state = End + } + case WaitingSignature: + err = p.waitingSignature() + if err != nil { + p.state = End + } + case ClaimDevice: + err = p.claimDevice(params.name, params.connectionType) + if err != nil { + p.state = End + } + case RegisterDevice: + err = p.registerDevice(params.fqbn, params.serial) + if err != nil { + p.state = End + } + + case RequestReset: + err = p.resetBoardRequest() + if err != nil { + p.state = UnclaimDevice + } + case WaitResetResponse: + err = p.waitingForResetResult() + if err != nil { + p.state = UnclaimDevice + } case ConfigureNetwork: - nextState, err = p.configStates.ConfigureNetwork(ctx, netConfig) + nextState, err = p.configStates.ConfigureNetwork(ctx, ¶ms.netConfig) if err != nil { - nextState = End + nextState = UnclaimDevice } - p.state = nextState case SendConnectionRequest: nextState, err = p.configStates.SendConnectionRequest() if err != nil { - nextState = End + nextState = UnclaimDevice } p.state = nextState case WaitingForConnectionCommandResult: nextState, err = p.configStates.WaitingForConnectionCommandResult() if err != nil { - nextState = End + nextState = UnclaimDevice + } + + if nextState == MissingParameter { + nextState = ConfigureNetwork } p.state = nextState - case MissingParameter: - p.state = ConfigureNetwork case WaitingForNetworkConfigResult: - nextState, err = p.configStates.WaitingForNetworkConfigResult() + _, err = p.configStates.WaitingForNetworkConfigResult() if err != nil { - nextState = End + nextState = UnclaimDevice } - p.state = nextState + p.state = WaitingForProvisioningResult + case WaitingForProvisioningResult: + err = p.waitProvisioningResult(ctx) + if err != nil { + p.state = UnclaimDevice + } + case UnclaimDevice: + err = p.unclaimDevice() + } } @@ -147,9 +274,9 @@ func (p *ProvisionV2) getSketchVersionRequest() error { /* * This function returns - * - <0 if version1 < version2 - * - 0 if version1 == version2 - * - >0 if version1 > version2 + * - <0 if version1 < version2 + * - =0 if version1 == version2 + * - >0 if version1 > version2 */ func (p *ProvisionV2) compareVersions(version1, version2 string) int { version1Tokens := strings.Split(version1, ".") @@ -167,7 +294,7 @@ func (p *ProvisionV2) compareVersions(version1, version2 string) int { return 0 } -func (p *ProvisionV2) waitingSketchVersion() error { +func (p *ProvisionV2) waitingSketchVersion(minSketchVersion string) error { res, err := p.provProt.ReceiveData(60) if err != nil { return err @@ -183,9 +310,8 @@ func (p *ProvisionV2) waitingSketchVersion() error { sketch_version := res.ToProvisioningSketchVersionMessage().ProvisioningSketchVersion logrus.Info("Provisioning V2: Received Sketch Version %s", sketch_version) - if p.boardProvDetails.MinProvSketchVersion != nil && - p.compareVersions(sketch_version, *p.boardProvDetails.MinProvSketchVersion) < 0 { - logrus.Info("Provisioning V2: Sketch version %s is lower than required minimum %s. Updating...", sketch_version, *p.boardProvDetails.MinProvSketchVersion) + if p.compareVersions(sketch_version, minSketchVersion) < 0 { + logrus.Info("Provisioning V2: Sketch version %s is lower than required minimum %s. Updating...", sketch_version, minSketchVersion) p.state = FlashProvisioningSketch return nil } @@ -206,6 +332,36 @@ func (p *ProvisionV2) waitingSketchVersion() error { return nil } +func (p *ProvisionV2) flashProvisioningSketch(ctx context.Context, fqbn, address, protocol string) error { + logrus.Info("Provisioning V2: Downloading provisioning sketch") + path := paths.TempDir().Join("cloud-cli").Join("provisioning_v2_sketch") + + file, err := p.iotApiClient.DownloadProvisioningV2Sketch(fqbn, path, nil) + if err != nil { + logrus.Error("Provisioning V2: Downloading provisioning sketch failed") + return err + } + + // Try to upload the provisioning sketch + logrus.Infof("%s\n", "Uploading provisioning sketch on the board") + errMsg := "Provisioning V2: error while uploading the provisioning sketch" + err = retry(ctx, 5, time.Millisecond*1000, errMsg, func() error { + return p.UploadBin(ctx, fqbn, file, address, protocol) + }) + if err != nil { + return err + } + + logrus.Info("Provisioning V2: Uploading provisioning sketch succeeded") + sleepCtx(ctx, 3*time.Second) + if err = p.connectToBoard(address); err != nil { + return err + } + p.state = WaitForConnection + return nil + +} + func (p *ProvisionV2) getWiFiFWVersionRequest() error { logrus.Info("Provisioning V2: Requesting WiFi FW Version") getWiFiFWVersionMessage := cborcoders.From(cborcoders.ProvisioningCommandsMessage{Command: configurationprotocol.Commands["GetWiFiFWVersion"]}) @@ -218,7 +374,7 @@ func (p *ProvisionV2) getWiFiFWVersionRequest() error { return nil } -func (p *ProvisionV2) waitWiFiFWVersion() error { +func (p *ProvisionV2) waitWiFiFWVersion(minWiFiVersion *string) error { res, err := p.provProt.ReceiveData(60) if err != nil { return err @@ -231,9 +387,9 @@ func (p *ProvisionV2) waitWiFiFWVersion() error { if res.Type() == cborcoders.ProvisioningWiFiFWVersionMessageType { wifi_version := res.ToProvisioningWiFiFWVersionMessage().WiFiFWVersion fmt.Printf("Received WiFi FW Version: %s\n", wifi_version) - if p.boardProvDetails.MinWiFiVersion != nil && - p.compareVersions(wifi_version, *p.boardProvDetails.MinWiFiVersion) < 0 { - return fmt.Errorf("Provisioning V2: WiFi FW version %s is lower than required minimum %s. Please update the board firmware using Arduino IDE or Arduino CLI", wifi_version, *p.boardProvDetails.MinWiFiVersion) + if minWiFiVersion != nil && + p.compareVersions(wifi_version, *minWiFiVersion) < 0 { + return fmt.Errorf("Provisioning V2: WiFi FW version %s is lower than required minimum %s. Please update the board firmware using Arduino IDE or Arduino CLI", wifi_version, *minWiFiVersion) } p.state = RequestBLEMAC @@ -251,7 +407,7 @@ func (p *ProvisionV2) waitWiFiFWVersion() error { return errors.New("Provisioning V2: WiFi FW version not received") } -func (p *ProvisionV2) BLEMacRequest() error { +func (p *ProvisionV2) getBLEMACRequest() error { logrus.Info("Provisioning V2: Requesting BLE MAC") getblemacMessage := cborcoders.From(cborcoders.ProvisioningCommandsMessage{Command: configurationprotocol.Commands["GetBLEMac"]}) err := p.provProt.SendData(getblemacMessage) @@ -302,12 +458,12 @@ func (p *ProvisionV2) sendInitialTS() error { if err != nil { return err } - p.state = UUIDRequest + p.state = IDRequest time.Sleep(1 * time.Second) return nil } -func (p *ProvisionV2) uidRequest() error { +func (p *ProvisionV2) getIDRequest() error { logrus.Info("Provisioning V2: Requesting UniqueID") getuuidMessage := cborcoders.From(cborcoders.ProvisioningCommandsMessage{Command: configurationprotocol.Commands["GetID"]}) err := p.provProt.SendData(getuuidMessage) @@ -332,7 +488,7 @@ func (p *ProvisionV2) waitingPublicKey() error { pubKey := res.ToProvisioningPublicKeyMessage().ProvisioningPublicKey logrus.Infof("Provisioning V2: Received Public Key\n") p.connectedBoardInfos.PublicKey = pubKey - p.state = WaitingUUID + p.state = WaitingID } else if res.Type() == cborcoders.ProvisioningStatusMessageType { status := res.ToProvisioningStatusMessage() newState, err := p.configStates.HandleStatusMessage(status.Status) @@ -352,7 +508,7 @@ func (p *ProvisionV2) waitingPublicKey() error { return errors.New("Provisioning V2: Public Key not received") } -func (p *ProvisionV2) waitingUID() error { +func (p *ProvisionV2) waitingUHWID() error { res, err := p.provProt.ReceiveData(60) if err != nil { return err @@ -363,10 +519,10 @@ func (p *ProvisionV2) waitingUID() error { } if res.Type() == cborcoders.ProvisioningUniqueIdMessageType { - uid := res.ToProvisioningUniqueIdMessage().UniqueId + uhwid := res.ToProvisioningUniqueIdMessage().UniqueId logrus.Infof("Provisioning V2: Received UniqueID\n") - uidString := string(uid[:]) - p.connectedBoardInfos.UHWID = uidString + uhwidString := string(uhwid[:]) + p.connectedBoardInfos.UHWID = uhwidString p.state = WaitingSignature } else if res.Type() == cborcoders.ProvisioningStatusMessageType { status := res.ToProvisioningStatusMessage() @@ -374,10 +530,6 @@ func (p *ProvisionV2) waitingUID() error { if err != nil { return err } - if newState == MissingParameter { - p.state = SendInitialTS - return nil - } if newState != NoneState { p.state = newState @@ -417,14 +569,14 @@ func (p *ProvisionV2) waitingSignature() error { return errors.New("Provisioning V2: Signature was not received") } -func (p *ProvisionV2) claimDevice() error { +func (p *ProvisionV2) claimDevice(name, connectionType string) error { logrus.Info("Provisioning V2: Claiming device...") claimData := provisioningapi.ClaimData{ BLEMac: p.connectedBoardInfos.BLEMacAddress, BoardToken: p.connectedBoardInfos.Signature, - ConnectionType: *p.provParams.ConnectionType, - DeviceName: p.provParams.Name, + ConnectionType: connectionType, + DeviceName: name, } provResp, provErr, err := p.provisioningClient.ClaimDevice(claimData) @@ -453,15 +605,15 @@ func (p *ProvisionV2) claimDevice() error { return errors.New("Provisioning V2: Device ID not received") } -func (p *ProvisionV2) RegisterDevice() error { +func (p *ProvisionV2) registerDevice(fqbn, serial string) error { logrus.Info("Provisioning V2: Registering device...") registerData := provisioningapi.RegisterBoardData{ - PID: p.boardProvDetails.Type, + PID: boardpids.ArduinoFqbnToPID[fqbn], PublicKey: p.connectedBoardInfos.PublicKey, - Serial: &p.board.serial, + Serial: &serial, UniqueHardwareID: p.connectedBoardInfos.UHWID, - VID: p.board.dType, //TODO ask for sending fqbn + VID: boardpids.ArduinoVendorID, //Only Arduino boards can support Provisioning 2.0 } provErr, err := p.provisioningClient.RegisterDevice(registerData) @@ -478,7 +630,7 @@ func (p *ProvisionV2) RegisterDevice() error { return nil } -func (p *ProvisionV2) ResetRequest() error { +func (p *ProvisionV2) resetBoardRequest() error { logrus.Info("Provisioning V2: Requesting Reset Stored Credentials") resetMessage := cborcoders.From(cborcoders.ProvisioningCommandsMessage{Command: configurationprotocol.Commands["Reset"]}) err := p.provProt.SendData(resetMessage) @@ -515,3 +667,27 @@ func (p *ProvisionV2) waitingForResetResult() error { return errors.New("Provisioning V2: Reset Stored Credentials failed") } + +func (p *ProvisionV2) waitProvisioningResult(ctx context.Context) error { + logrus.Info("Provisioning V2: Waiting for provisioning result...") + + for n := 0; n < 20; n++ { + res, err := p.provisioningClient.GetProvisioningDetail(p.provisioningId) + if err != nil { + return err + } + if res.DeviceID != nil { + p.deviceId = *res.DeviceID + p.state = End + } + sleepCtx(ctx, 10*time.Second) + } + return errors.New("Provisioning V2: Timeout expires for board provisioning. The board was not able to reach the Arduino IoT Cloud for completing the provisioning.") +} + +func (p *ProvisionV2) unclaimDevice() error { + logrus.Warnf("Provisioning V2: Something went wrong, unclaiming device...") + _, err := p.provisioningClient.UnclaimDevice(p.provisioningId) + p.state = End + return err +} From c84d9f6fbdea513b8dd36650d83446187642ac3f Mon Sep 17 00:00:00 2001 From: fabik111 Date: Mon, 25 Aug 2025 18:09:16 +0200 Subject: [PATCH 11/27] draft runProvisioningV2 function --- command/device/create.go | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/command/device/create.go b/command/device/create.go index b792764d..1c07f45e 100644 --- a/command/device/create.go +++ b/command/device/create.go @@ -26,7 +26,7 @@ import ( "github.com/arduino/arduino-cloud-cli/arduino/cli" "github.com/arduino/arduino-cloud-cli/config" "github.com/arduino/arduino-cloud-cli/internal/iot" - provisioningapi "github.com/arduino/arduino-cloud-cli/internal/provisioning-api" + iotapiraw "github.com/arduino/arduino-cloud-cli/internal/iot-api-raw" "github.com/sirupsen/logrus" ) @@ -72,13 +72,13 @@ func Create(ctx context.Context, params *CreateParams, cred *config.Credentials) return nil, err } - provisioningClient := provisioningapi.NewClient(cred) + iotApiRawClient := iotapiraw.NewClient(cred) - boardsList, err := provisioningClient.GetBoardsDetail() + boardsList, err := iotApiRawClient.GetBoardsDetail() if err != nil { return nil, err } - var boardProvisioningDetails provisioningapi.BoardType + var boardProvisioningDetails iotapiraw.BoardType for _, b := range *boardsList { if *b.FQBN == board.fqbn { boardProvisioningDetails = b @@ -92,8 +92,8 @@ func Create(ctx context.Context, params *CreateParams, cred *config.Credentials) var devInfo *DeviceInfo if boardProvisioningDetails.Provisioning != nil && *boardProvisioningDetails.Provisioning == "v2" { - //TODO ADD function for V2 provisioning - // TODO check if ConnectionType is null + logrus.Info("Provisioning V2 started") + devInfo, err = runProvisioningV2(ctx, params, &comm, iotClient, board) } else { logrus.Info("Provisioning V1 started") devInfo, err = runProvisioningV1(ctx, params, &comm, iotClient, board) @@ -102,6 +102,25 @@ func Create(ctx context.Context, params *CreateParams, cred *config.Credentials) return devInfo, err } +func runProvisioningV2(ctx context.Context, params *CreateParams, comm *arduino.Commander, iotClient *iotapiraw.IoTApiRawClient, cred *config.Credentials) (*DeviceInfo, error) { + if params.ConnectionType == nil { + return nil, errors.New("connection type is required for Provisioning V2") + } + + netConfig := NetConfig{ + Type: connectionTypeIDByName[*params.ConnectionType], + } + + err := GetInputFromMenu(&netConfig) + if err != nil { + return nil, err + } + + // func NewProvisionV2(iotClient *iotapiraw.IoTApiRawClient, credentials *config.Credentials, extInterface transport.TransportInterface) + prov := NewProvisionV2(iotClient, cred) + +} + func runProvisioningV1(ctx context.Context, params *CreateParams, comm *arduino.Commander, iotClient *iot.Client, board *board) (*DeviceInfo, error) { logrus.Info("Creating a new device on the cloud") dev, err := iotClient.DeviceCreate(ctx, board.fqbn, params.Name, board.serial, board.dType, params.ConnectionType) From e481d3019885b942357cae0b3e2a0d96266ed499 Mon Sep 17 00:00:00 2001 From: fabik111 Date: Tue, 26 Aug 2025 17:55:50 +0200 Subject: [PATCH 12/27] add runProvisioningv2 function --- command/device/create.go | 66 ++++++++++++++++++++++------------ internal/iot-api-raw/client.go | 14 ++++++++ 2 files changed, 57 insertions(+), 23 deletions(-) diff --git a/command/device/create.go b/command/device/create.go index 1c07f45e..f255e6bf 100644 --- a/command/device/create.go +++ b/command/device/create.go @@ -25,8 +25,10 @@ import ( "github.com/arduino/arduino-cloud-cli/arduino" "github.com/arduino/arduino-cloud-cli/arduino/cli" "github.com/arduino/arduino-cloud-cli/config" + "github.com/arduino/arduino-cloud-cli/internal/board-protocols/transport" "github.com/arduino/arduino-cloud-cli/internal/iot" iotapiraw "github.com/arduino/arduino-cloud-cli/internal/iot-api-raw" + "github.com/arduino/arduino-cloud-cli/internal/serial" "github.com/sirupsen/logrus" ) @@ -67,42 +69,26 @@ func Create(ctx context.Context, params *CreateParams, cred *config.Credentials) ) } - iotClient, err := iot.NewClient(cred) - if err != nil { - return nil, err - } - iotApiRawClient := iotapiraw.NewClient(cred) - boardsList, err := iotApiRawClient.GetBoardsDetail() + boardProvisioningDetails, err := iotApiRawClient.GetBoardDetailByFQBN(board.fqbn) if err != nil { return nil, err } - var boardProvisioningDetails iotapiraw.BoardType - for _, b := range *boardsList { - if *b.FQBN == board.fqbn { - boardProvisioningDetails = b - break - } - } - - if boardProvisioningDetails.FQBN == nil { - return nil, fmt.Errorf("board with fqbn %s not found in provisioning API", board.fqbn) - } var devInfo *DeviceInfo if boardProvisioningDetails.Provisioning != nil && *boardProvisioningDetails.Provisioning == "v2" { logrus.Info("Provisioning V2 started") - devInfo, err = runProvisioningV2(ctx, params, &comm, iotClient, board) + devInfo, err = runProvisioningV2(ctx, params, &comm, iotApiRawClient, cred, board, boardProvisioningDetails) } else { logrus.Info("Provisioning V1 started") - devInfo, err = runProvisioningV1(ctx, params, &comm, iotClient, board) + devInfo, err = runProvisioningV1(ctx, params, &comm, cred, board) } return devInfo, err } -func runProvisioningV2(ctx context.Context, params *CreateParams, comm *arduino.Commander, iotClient *iotapiraw.IoTApiRawClient, cred *config.Credentials) (*DeviceInfo, error) { +func runProvisioningV2(ctx context.Context, params *CreateParams, comm *arduino.Commander, iotClient *iotapiraw.IoTApiRawClient, cred *config.Credentials, board *board, boardProvisioningDetails *iotapiraw.BoardType) (*DeviceInfo, error) { if params.ConnectionType == nil { return nil, errors.New("connection type is required for Provisioning V2") } @@ -116,13 +102,47 @@ func runProvisioningV2(ctx context.Context, params *CreateParams, comm *arduino. return nil, err } - // func NewProvisionV2(iotClient *iotapiraw.IoTApiRawClient, credentials *config.Credentials, extInterface transport.TransportInterface) - prov := NewProvisionV2(iotClient, cred) + var extInterface transport.TransportInterface + extInterface = &serial.Serial{} + + prov := NewProvisionV2(comm, iotClient, cred, extInterface) + // Start the provisioning process + err = prov.Run(ctx, ProvisioningV2BoardParams{ + fqbn: board.fqbn, + address: board.address, + protocol: board.protocol, + serial: board.serial, + minProvSketchVersion: *boardProvisioningDetails.MinProvSketchVersion, + minWiFiVersion: boardProvisioningDetails.MinWiFiVersion, + name: params.Name, + connectionType: *params.ConnectionType, + netConfig: netConfig, + }) + if err != nil { + return nil, err + } + devId, err := prov.GetProvisioningResult() + if err != nil { + return nil, err + } + + devInfo := &DeviceInfo{ + Name: params.Name, + ID: devId, + Board: *params.ConnectionType, + Serial: board.serial, + FQBN: board.fqbn, + } + return devInfo, nil } -func runProvisioningV1(ctx context.Context, params *CreateParams, comm *arduino.Commander, iotClient *iot.Client, board *board) (*DeviceInfo, error) { +func runProvisioningV1(ctx context.Context, params *CreateParams, comm *arduino.Commander, cred *config.Credentials, board *board) (*DeviceInfo, error) { logrus.Info("Creating a new device on the cloud") + iotClient, err := iot.NewClient(cred) + if err != nil { + return nil, err + } dev, err := iotClient.DeviceCreate(ctx, board.fqbn, params.Name, board.serial, board.dType, params.ConnectionType) if err != nil { return nil, err diff --git a/internal/iot-api-raw/client.go b/internal/iot-api-raw/client.go index 07a9e90c..d0ec0b38 100644 --- a/internal/iot-api-raw/client.go +++ b/internal/iot-api-raw/client.go @@ -100,6 +100,20 @@ func (c *IoTApiRawClient) GetBoardsDetail() (*BoardTypeList, error) { return nil, err } +func (c *IoTApiRawClient) GetBoardDetailByFQBN(fqbn string) (*BoardType, error) { + boardsList, err := c.GetBoardsDetail() + if err != nil { + return nil, err + } + + for _, b := range *boardsList { + if *b.FQBN == fqbn { + return &b, nil + } + } + return nil, fmt.Errorf("board with fqbn %s not found", fqbn) +} + func (c *IoTApiRawClient) DownloadProvisioningV2Sketch(fqbn string, path *paths.Path, filename *string) (string, error) { endpoint := c.host + "iot/v2/binaries/provisioningv2?fqbn=" + fqbn token, err := c.getToken() From c1e57361bd0239ca338a33f72d1ba27da465405d Mon Sep 17 00:00:00 2001 From: fabik111 Date: Tue, 26 Aug 2025 17:56:43 +0200 Subject: [PATCH 13/27] refactor network configuration FSM --- command/device/configurationstates.go | 128 ++++++++++++-------------- command/device/configure.go | 33 ++----- 2 files changed, 67 insertions(+), 94 deletions(-) diff --git a/command/device/configurationstates.go b/command/device/configurationstates.go index 47a29f1c..d25a590f 100644 --- a/command/device/configurationstates.go +++ b/command/device/configurationstates.go @@ -64,6 +64,13 @@ const ( WaitingForProvisioningResult UnclaimDevice End + ErrorState +) + +const ( + CommandResponseTimeoutLong_s = 60 + CommandResponseTimeoutShort_s = 30 + ConnectResponseTimeout_s = 200 ) type ConfigurationStates struct { @@ -80,35 +87,33 @@ func (c *ConfigurationStates) WaitForConnection() (ConfigStatus, error) { if c.configProtocol.Connected() { return WaitingForInitialStatus, nil } - return NoneState, errors.New("impossible to connect with the device") + return ErrorState, errors.New("impossible to connect with the device") } func (c *ConfigurationStates) WaitingForInitialStatus() (ConfigStatus, error) { logrus.Info("NetworkConfigure: waiting for initial status from device") - res, err := c.configProtocol.ReceiveData(30) + res, err := c.configProtocol.ReceiveData(CommandResponseTimeoutShort_s) if err != nil { - return NoneState, fmt.Errorf("communication error: %w, please check the NetworkConfigurator lib is activated in the sketch", err) + return ErrorState, fmt.Errorf("communication error: %w, please check the NetworkConfigurator lib is activated in the sketch", err) } if res == nil { return WaitingForNetworkOptions, nil - } else if res.Type() == cborcoders.ProvisioningStatusMessageType { + } + + if res.Type() == cborcoders.ProvisioningStatusMessageType { status := res.ToProvisioningStatusMessage() if status.Status == 1 { return WaitingForInitialStatus, nil - } else if status.Status == -6 || status.Status <= -101 { - newState, err := c.HandleStatusMessage(status.Status) - if err != nil { - return NoneState, err - } - if newState != NoneState { - return newState, nil - } - } else { - return WaitingForNetworkOptions, nil } - } else if res.Type() == cborcoders.WiFiNetworksType { + if status.Status == -6 || status.Status <= -101 { + return c.HandleStatusMessage(status.Status) + } + return WaitingForNetworkOptions, nil + } + + if res.Type() == cborcoders.WiFiNetworksType { return BoardReady, nil } @@ -119,9 +124,9 @@ func (c *ConfigurationStates) WaitingForInitialStatus() (ConfigStatus, error) { // Arduino Board Configuration Protocol. func (c *ConfigurationStates) WaitingForNetworkOptions() (ConfigStatus, error) { logrus.Info("NetworkConfigure: waiting for network options from device") - res, err := c.configProtocol.ReceiveData(30) + res, err := c.configProtocol.ReceiveData(CommandResponseTimeoutShort_s) if err != nil { - return NoneState, err + return ErrorState, err } if res != nil { @@ -129,23 +134,19 @@ func (c *ConfigurationStates) WaitingForNetworkOptions() (ConfigStatus, error) { // WiFiNetworksType, which contains the available WiFi networks list. if res.Type() == cborcoders.WiFiNetworksType { return BoardReady, nil - } else if res.Type() == cborcoders.ProvisioningStatusMessageType { + } + + if res.Type() == cborcoders.ProvisioningStatusMessageType { status := res.ToProvisioningStatusMessage() if status.Status == 1 { return WaitingForInitialStatus, nil - } else { - newState, err := c.HandleStatusMessage(status.Status) - if err != nil { - return NoneState, err - } - if newState != NoneState { - return newState, nil - } } + + return c.HandleStatusMessage(status.Status) } } - return NoneState, errors.New("timeout: no network options received from the device, please retry enabling the NetworkCofnigurator lib in the sketch") + return ErrorState, errors.New("timeout: no network options received from the device, please retry enabling the NetworkCofnigurator lib in the sketch") } func (cs *ConfigurationStates) ConfigureNetwork(ctx context.Context, c *NetConfig) (ConfigStatus, error) { @@ -202,12 +203,12 @@ func (cs *ConfigurationStates) ConfigureNetwork(ctx context.Context, c *NetConfi Pass: c.CellularSetting.Pass, }) } else { - return NoneState, errors.New("invalid configuration type") + return ErrorState, errors.New("invalid configuration type") } err := cs.configProtocol.SendData(cmd) if err != nil { - return NoneState, err + return ErrorState, err } sleepCtx(ctx, 1*time.Second) @@ -218,42 +219,39 @@ func (c *ConfigurationStates) SendConnectionRequest() (ConfigStatus, error) { connectMessage := cborcoders.From(cborcoders.ProvisioningCommandsMessage{Command: configurationprotocol.Commands["Connect"]}) err := c.configProtocol.SendData(connectMessage) if err != nil { - return NoneState, err + return ErrorState, err } return WaitingForConnectionCommandResult, nil } func (c *ConfigurationStates) WaitingForConnectionCommandResult() (ConfigStatus, error) { - res, err := c.configProtocol.ReceiveData(60) + res, err := c.configProtocol.ReceiveData(CommandResponseTimeoutLong_s) if err != nil { - return NoneState, err + return ErrorState, err } if res != nil && res.Type() == cborcoders.ProvisioningStatusMessageType { status := res.ToProvisioningStatusMessage() if status.Status == 1 { return WaitingForNetworkConfigResult, nil - } else if status.Status == -4 { + } + + if status.Status == -4 { return ConfigureNetwork, nil - } else { - newState, err := c.HandleStatusMessage(status.Status) - if err != nil { - return NoneState, err - } - if newState != NoneState { - return newState, nil - } } + + return c.HandleStatusMessage(status.Status) + } - return NoneState, errors.New("timeout: no confirmation of connection command received from the device, please retry") + return ErrorState, errors.New("timeout: no confirmation of connection command received from the device, please retry") } func (c *ConfigurationStates) WaitingForNetworkConfigResult() (ConfigStatus, error) { - res, err := c.configProtocol.ReceiveData(200) + res, err := c.configProtocol.ReceiveData(ConnectResponseTimeout_s) if err != nil { - return NoneState, err + return ErrorState, err } if res != nil && res.Type() == cborcoders.ProvisioningStatusMessageType { @@ -261,18 +259,12 @@ func (c *ConfigurationStates) WaitingForNetworkConfigResult() (ConfigStatus, err if status.Status == 2 { return End, nil - } else { - newState, err := c.HandleStatusMessage(status.Status) - if err != nil { - return NoneState, err - } - if newState != NoneState { - return newState, nil - } } + return c.HandleStatusMessage(status.Status) + } - return NoneState, errors.New("timeout: no result received from the device for network configuration, please retry") + return ErrorState, errors.New("timeout: no result received from the device for network configuration, please retry") } // Keep for reference @@ -301,39 +293,39 @@ func (c *ConfigurationStates) HandleStatusMessage(status int16) (ConfigStatus, e case "Scanning for WiFi networks": return WaitingForNetworkOptions, nil case "Failed to connect": - return NoneState, errors.New("connection failed invalid credentials or network configuration") + return ErrorState, errors.New("connection failed invalid credentials or network configuration") case "Disconnected": return NoneState, nil case "Parameters not provided": return MissingParameter, nil case "Invalid parameters": - return NoneState, errors.New("the provided parameters for network configuration are invalid") + return ErrorState, errors.New("the provided parameters for network configuration are invalid") case "Cannot execute anew request while another is pending": - return NoneState, errors.New("board is busy, restart the board and try again") + return ErrorState, errors.New("board is busy, restart the board and try again") case "Invalid request": - return NoneState, errors.New("invalid request sent to the board") + return ErrorState, errors.New("invalid request sent to the board") case "Internet not available": - return NoneState, errors.New("internet not available, check your network connection") + return ErrorState, errors.New("internet not available, check your network connection") case "HW Error connectivity module": - return NoneState, errors.New("hardware error in connectivity module, check the board") + return ErrorState, errors.New("hardware error in connectivity module, check the board") case "HW Connectivity Module stopped": - return NoneState, errors.New("hardware connectivity module stopped, restart the board and check your sketch") + return ErrorState, errors.New("hardware connectivity module stopped, restart the board and check your sketch") case "Error initializing secure element": - return NoneState, errors.New("error initializing secure element, check the board and try again") + return ErrorState, errors.New("error initializing secure element, check the board and try again") case "Error configuring secure element": - return NoneState, errors.New("error configuring secure element, check the board and try again") + return ErrorState, errors.New("error configuring secure element, check the board and try again") case "Error locking secure element": - return NoneState, errors.New("error locking secure element, check the board and try again") + return ErrorState, errors.New("error locking secure element, check the board and try again") case "Error generating UHWID": - return NoneState, errors.New("error generating UHWID, check the board and try again") + return ErrorState, errors.New("error generating UHWID, check the board and try again") case "Error storage begin module": - return NoneState, errors.New("error beginning storage module, check the board storage partitioning and try again") + return ErrorState, errors.New("error beginning storage module, check the board storage partitioning and try again") case "Fail to partition the storage": - return NoneState, errors.New("failed to partition the storage, check the board storage and try again") + return ErrorState, errors.New("failed to partition the storage, check the board storage and try again") case "Generic error": - return NoneState, errors.New("generic error, check the board and try again") + return ErrorState, errors.New("generic error, check the board and try again") default: - return NoneState, errors.New("generic error, check the board and try again") + return ErrorState, errors.New("generic error, check the board and try again") } } diff --git a/command/device/configure.go b/command/device/configure.go index f8ac7c2d..b955009e 100644 --- a/command/device/configure.go +++ b/command/device/configure.go @@ -55,7 +55,7 @@ func NetConfigure(ctx context.Context, boardFilters *CreateParams, NetConfig *Ne return err } - nc := NewNetworkConfigure(extInterface, configProtocol) + nc := NewNetworkConfigure(configProtocol) err = nc.Run(ctx, NetConfig) return err @@ -179,9 +179,9 @@ type NetworkConfigure struct { configProtocol *configurationprotocol.NetworkConfigurationProtocol } -func NewNetworkConfigure(extInterface transport.TransportInterface, configProtocol *configurationprotocol.NetworkConfigurationProtocol) *NetworkConfigure { +func NewNetworkConfigure(configProtocol *configurationprotocol.NetworkConfigurationProtocol) *NetworkConfigure { return &NetworkConfigure{ - configStates: NewConfigurationStates(extInterface, configProtocol), + configStates: NewConfigurationStates(configProtocol), configProtocol: configProtocol, } } @@ -191,51 +191,32 @@ func (nc *NetworkConfigure) Run(ctx context.Context, netConfig *NetConfig) error nextState := state var err error - for state != End { + for state != End && state != ErrorState { switch state { case WaitForConnection: nextState, err = nc.configStates.WaitForConnection() - if err != nil { - nextState = End - } case WaitingForInitialStatus: nextState, err = nc.configStates.WaitingForInitialStatus() - if err != nil { - nextState = End - } case WaitingForNetworkOptions: nextState, err = nc.configStates.WaitingForNetworkOptions() - if err != nil { - nextState = End - } case BoardReady: nextState = ConfigureNetwork case ConfigureNetwork: nextState, err = nc.configStates.ConfigureNetwork(ctx, netConfig) - if err != nil { - nextState = End - } case SendConnectionRequest: nextState, err = nc.configStates.SendConnectionRequest() - if err != nil { - nextState = End - } case WaitingForConnectionCommandResult: nextState, err = nc.configStates.WaitingForConnectionCommandResult() - if err != nil { - nextState = End - } case MissingParameter: nextState = ConfigureNetwork case WaitingForNetworkConfigResult: nextState, err = nc.configStates.WaitingForNetworkConfigResult() - if err != nil { - nextState = End - } } - state = nextState + if nextState != NoneState { + state = nextState + } } From 9fa6d51ae498d13392b2730c1eb16669fa796fa1 Mon Sep 17 00:00:00 2001 From: fabik111 Date: Tue, 26 Aug 2025 17:57:06 +0200 Subject: [PATCH 14/27] refactor provisioningv2 FSM --- command/device/provisionv2.go | 430 ++++++++++++++-------------------- 1 file changed, 173 insertions(+), 257 deletions(-) diff --git a/command/device/provisionv2.go b/command/device/provisionv2.go index 26aebd71..25f5fba1 100644 --- a/command/device/provisionv2.go +++ b/command/device/provisionv2.go @@ -21,6 +21,7 @@ import ( "context" "errors" "fmt" + "os" "strconv" "strings" "time" @@ -47,6 +48,11 @@ var connectionTypeIDByName = map[string]int32{ "cellular": 7, } +const ( + MaxRetriesFlashProvSketch = 5 + MaxRetriesProvisioningResult = 20 +) + type ConnectedBoardInfos struct { UHWID string PublicKey string @@ -71,16 +77,16 @@ type ProvisionV2 struct { iotApiClient *iotapiraw.IoTApiRawClient provisioningClient *provisioningapi.ProvisioningApiClient provProt *configurationprotocol.NetworkConfigurationProtocol - state ConfigStatus configStates *ConfigurationStates connectedBoardInfos ConnectedBoardInfos provisioningId string deviceId string } -func NewProvisionV2(iotClient *iotapiraw.IoTApiRawClient, credentials *config.Credentials, extInterface transport.TransportInterface) *ProvisionV2 { +func NewProvisionV2(comm *arduino.Commander, iotClient *iotapiraw.IoTApiRawClient, credentials *config.Credentials, extInterface transport.TransportInterface) *ProvisionV2 { provProt := configurationprotocol.NewNetworkConfigurationProtocol(&extInterface) return &ProvisionV2{ + Commander: *comm, iotApiClient: iotClient, provisioningClient: provisioningapi.NewClient(credentials), provProt: provProt, @@ -110,113 +116,61 @@ func (p *ProvisionV2) Run(ctx context.Context, params ProvisioningV2BoardParams) if err = p.connectToBoard(params.address); err != nil { return err } - p.state = WaitForConnection - var nextState ConfigStatus + state := WaitForConnection + nextState := NoneState - for p.state != End { + // FSM for Provisioning 2.0 + for state != End && state != ErrorState { - switch p.state { + switch state { case WaitForConnection: nextState, err = p.configStates.WaitForConnection() - if err != nil { - nextState = End - } - p.state = nextState case WaitingForInitialStatus: nextState, err = p.configStates.WaitingForInitialStatus() - if err != nil { - nextState = End - } - p.state = nextState case WaitingForNetworkOptions: nextState, err = p.configStates.WaitingForNetworkOptions() if err != nil { nextState = FlashProvisioningSketch } - p.state = nextState case BoardReady: - p.state = GetSketchVersionRequest + nextState = GetSketchVersionRequest case GetSketchVersionRequest: - err = p.getSketchVersionRequest() - if err != nil { - p.state = End - } + nextState, err = p.getSketchVersionRequest() case WaitingSketchVersion: - err = p.waitingSketchVersion(params.minProvSketchVersion) - if err != nil { - p.state = End - } + nextState, err = p.waitingSketchVersion(params.minProvSketchVersion) case FlashProvisioningSketch: - err = p.flashProvisioningSketch(ctx, params.fqbn, params.address, params.protocol) - if err != nil { - p.state = End - } + nextState, err = p.flashProvisioningSketch(ctx, params.fqbn, params.address, params.protocol) case WiFiFWVersionRequest: - err = p.getWiFiFWVersionRequest() - if err != nil { - p.state = End - } + nextState, err = p.getWiFiFWVersionRequest(ctx) case WaitingWiFiFWVersion: - err = p.waitWiFiFWVersion(params.minWiFiVersion) - if err != nil { - p.state = End - } + nextState, err = p.waitWiFiFWVersion(params.minWiFiVersion) case RequestBLEMAC: - err = p.getBLEMACRequest() - if err != nil { - p.state = End - } + nextState, err = p.getBLEMACRequest(ctx) case WaitBLEMAC: - err = p.waitBLEMac() - if err != nil { - p.state = End - } + nextState, err = p.waitBLEMac() case SendInitialTS: - err = p.sendInitialTS() - if err != nil { - p.state = End - } - + nextState, err = p.sendInitialTS(ctx) case IDRequest: - err = p.getIDRequest() - if err != nil { - p.state = End - } + nextState, err = p.getIDRequest() case WaitingPublicKey: - err = p.waitingPublicKey() - if err != nil { - p.state = End - } + nextState, err = p.waitingPublicKey() case WaitingID: - err = p.waitingUHWID() - if err != nil { - p.state = End - } + nextState, err = p.waitingUHWID() case WaitingSignature: - err = p.waitingSignature() - if err != nil { - p.state = End - } + nextState, err = p.waitingSignature() case ClaimDevice: - err = p.claimDevice(params.name, params.connectionType) - if err != nil { - p.state = End - } + nextState, err = p.claimDevice(params.name, params.connectionType) case RegisterDevice: - err = p.registerDevice(params.fqbn, params.serial) - if err != nil { - p.state = End - } - + nextState, err = p.registerDevice(params.fqbn, params.serial) case RequestReset: - err = p.resetBoardRequest() + nextState, err = p.resetBoardRequest() if err != nil { - p.state = UnclaimDevice + nextState = UnclaimDevice } case WaitResetResponse: - err = p.waitingForResetResult() + nextState, err = p.waitingForResetResult() if err != nil { - p.state = UnclaimDevice + nextState = UnclaimDevice } case ConfigureNetwork: nextState, err = p.configStates.ConfigureNetwork(ctx, ¶ms.netConfig) @@ -228,7 +182,6 @@ func (p *ProvisionV2) Run(ctx context.Context, params ProvisioningV2BoardParams) if err != nil { nextState = UnclaimDevice } - p.state = nextState case WaitingForConnectionCommandResult: nextState, err = p.configStates.WaitingForConnectionCommandResult() if err != nil { @@ -238,21 +191,23 @@ func (p *ProvisionV2) Run(ctx context.Context, params ProvisioningV2BoardParams) if nextState == MissingParameter { nextState = ConfigureNetwork } - p.state = nextState case WaitingForNetworkConfigResult: _, err = p.configStates.WaitingForNetworkConfigResult() if err != nil { nextState = UnclaimDevice } - p.state = WaitingForProvisioningResult + nextState = WaitingForProvisioningResult case WaitingForProvisioningResult: - err = p.waitProvisioningResult(ctx) + nextState, err = p.waitProvisioningResult(ctx) if err != nil { - p.state = UnclaimDevice + nextState = UnclaimDevice } case UnclaimDevice: - err = p.unclaimDevice() + nextState, err = p.unclaimDevice() + } + if nextState != NoneState { + state = nextState } } @@ -261,15 +216,15 @@ func (p *ProvisionV2) Run(ctx context.Context, params ProvisioningV2BoardParams) return err } -func (p *ProvisionV2) getSketchVersionRequest() error { +func (p *ProvisionV2) getSketchVersionRequest() (ConfigStatus, error) { logrus.Info("Provisioning V2: Requesting Sketch Version") getSketchVersionMessage := cborcoders.From(cborcoders.ProvisioningCommandsMessage{Command: configurationprotocol.Commands["GetSketchVersion"]}) err := p.provProt.SendData(getSketchVersionMessage) if err != nil { - return err + return ErrorState, err } - p.state = WaitingSketchVersion - return nil + + return WaitingSketchVersion, nil } /* @@ -294,94 +249,91 @@ func (p *ProvisionV2) compareVersions(version1, version2 string) int { return 0 } -func (p *ProvisionV2) waitingSketchVersion(minSketchVersion string) error { - res, err := p.provProt.ReceiveData(60) +func (p *ProvisionV2) waitingSketchVersion(minSketchVersion string) (ConfigStatus, error) { + res, err := p.provProt.ReceiveData(CommandResponseTimeoutLong_s) if err != nil { - return err + return ErrorState, err } if res == nil { logrus.Error("Provisioning V2: Requesting sketch Version failed, flashing...") - p.state = FlashProvisioningSketch - return nil + return FlashProvisioningSketch, nil } if res.Type() == cborcoders.ProvisioningSketchVersionMessageType { sketch_version := res.ToProvisioningSketchVersionMessage().ProvisioningSketchVersion - logrus.Info("Provisioning V2: Received Sketch Version %s", sketch_version) + logrus.Infof("Provisioning V2: Received Sketch Version %s", sketch_version) if p.compareVersions(sketch_version, minSketchVersion) < 0 { - logrus.Info("Provisioning V2: Sketch version %s is lower than required minimum %s. Updating...", sketch_version, minSketchVersion) - p.state = FlashProvisioningSketch - return nil + logrus.Infof("Provisioning V2: Sketch version %s is lower than required minimum %s. Updating...", sketch_version, minSketchVersion) + return FlashProvisioningSketch, nil } - p.state = WiFiFWVersionRequest - } else if res.Type() == cborcoders.ProvisioningStatusMessageType { + return WiFiFWVersionRequest, nil + } + + if res.Type() == cborcoders.ProvisioningStatusMessageType { status := res.ToProvisioningStatusMessage() - newState, err := p.configStates.HandleStatusMessage(status.Status) - if err != nil { - return err - } - if newState != NoneState { - p.state = newState - return nil - } + return p.configStates.HandleStatusMessage(status.Status) } - return nil + return NoneState, nil } -func (p *ProvisionV2) flashProvisioningSketch(ctx context.Context, fqbn, address, protocol string) error { +func (p *ProvisionV2) flashProvisioningSketch(ctx context.Context, fqbn, address, protocol string) (ConfigStatus, error) { logrus.Info("Provisioning V2: Downloading provisioning sketch") path := paths.TempDir().Join("cloud-cli").Join("provisioning_v2_sketch") file, err := p.iotApiClient.DownloadProvisioningV2Sketch(fqbn, path, nil) if err != nil { logrus.Error("Provisioning V2: Downloading provisioning sketch failed") - return err + return ErrorState, err } // Try to upload the provisioning sketch logrus.Infof("%s\n", "Uploading provisioning sketch on the board") errMsg := "Provisioning V2: error while uploading the provisioning sketch" - err = retry(ctx, 5, time.Millisecond*1000, errMsg, func() error { + err = retry(ctx, MaxRetriesFlashProvSketch, time.Millisecond*1000, errMsg, func() error { return p.UploadBin(ctx, fqbn, file, address, protocol) }) if err != nil { - return err + return ErrorState, err + } + + err = os.Remove(file) + if err != nil { + logrus.Error("Provisioning V2: Removing temporary file failed") + return ErrorState, err } logrus.Info("Provisioning V2: Uploading provisioning sketch succeeded") sleepCtx(ctx, 3*time.Second) if err = p.connectToBoard(address); err != nil { - return err + return ErrorState, err } - p.state = WaitForConnection - return nil + return WaitForConnection, nil } -func (p *ProvisionV2) getWiFiFWVersionRequest() error { +func (p *ProvisionV2) getWiFiFWVersionRequest(ctx context.Context) (ConfigStatus, error) { logrus.Info("Provisioning V2: Requesting WiFi FW Version") getWiFiFWVersionMessage := cborcoders.From(cborcoders.ProvisioningCommandsMessage{Command: configurationprotocol.Commands["GetWiFiFWVersion"]}) err := p.provProt.SendData(getWiFiFWVersionMessage) if err != nil { - return err + return ErrorState, err } - p.state = WaitingWiFiFWVersion - time.Sleep(1 * time.Second) - return nil + sleepCtx(ctx, 1*time.Second) + return WaitingWiFiFWVersion, nil } -func (p *ProvisionV2) waitWiFiFWVersion(minWiFiVersion *string) error { - res, err := p.provProt.ReceiveData(60) +func (p *ProvisionV2) waitWiFiFWVersion(minWiFiVersion *string) (ConfigStatus, error) { + res, err := p.provProt.ReceiveData(CommandResponseTimeoutLong_s) if err != nil { - return err + return ErrorState, err } if res == nil { - return errors.New("Provisioning V2: Requesting WiFi FW Version failed") + return ErrorState, errors.New("provisioning V2: Requesting WiFi FW Version failed") } if res.Type() == cborcoders.ProvisioningWiFiFWVersionMessageType { @@ -389,133 +341,117 @@ func (p *ProvisionV2) waitWiFiFWVersion(minWiFiVersion *string) error { fmt.Printf("Received WiFi FW Version: %s\n", wifi_version) if minWiFiVersion != nil && p.compareVersions(wifi_version, *minWiFiVersion) < 0 { - return fmt.Errorf("Provisioning V2: WiFi FW version %s is lower than required minimum %s. Please update the board firmware using Arduino IDE or Arduino CLI", wifi_version, *minWiFiVersion) + return ErrorState, fmt.Errorf("provisioning V2: WiFi FW version %s is lower than required minimum %s. Please update the board firmware using Arduino IDE or Arduino CLI", wifi_version, *minWiFiVersion) } - p.state = RequestBLEMAC - } else if res.Type() == cborcoders.ProvisioningStatusMessageType { + return RequestBLEMAC, nil + } + + if res.Type() == cborcoders.ProvisioningStatusMessageType { status := res.ToProvisioningStatusMessage() - newState, err := p.configStates.HandleStatusMessage(status.Status) - if err != nil { - return err - } - if newState != NoneState { - p.state = newState - return nil - } + return p.configStates.HandleStatusMessage(status.Status) } - return errors.New("Provisioning V2: WiFi FW version not received") + + return ErrorState, errors.New("provisioning V2: WiFi FW version not received") } -func (p *ProvisionV2) getBLEMACRequest() error { +func (p *ProvisionV2) getBLEMACRequest(ctx context.Context) (ConfigStatus, error) { logrus.Info("Provisioning V2: Requesting BLE MAC") getblemacMessage := cborcoders.From(cborcoders.ProvisioningCommandsMessage{Command: configurationprotocol.Commands["GetBLEMac"]}) err := p.provProt.SendData(getblemacMessage) if err != nil { - return err + return ErrorState, err } - p.state = WaitBLEMAC - time.Sleep(1 * time.Second) - return nil + sleepCtx(ctx, 1*time.Second) + return WaitBLEMAC, nil } -func (p *ProvisionV2) waitBLEMac() error { - res, err := p.provProt.ReceiveData(60) +func (p *ProvisionV2) waitBLEMac() (ConfigStatus, error) { + res, err := p.provProt.ReceiveData(CommandResponseTimeoutLong_s) if err != nil { - return err + return ErrorState, err } if res == nil { - return errors.New("Provisioning V2: BLEMac was not received") + return ErrorState, errors.New("provisioning V2: BLEMac was not received") } if res.Type() == cborcoders.ProvisioningBLEMacAddressMessageType { mac := res.ToProvisioningBLEMacAddressMessage().BLEMacAddress - logrus.Info("Provisioning V2: Received MAC in hex: %02X\n", mac) + logrus.Infof("Provisioning V2: Received MAC in hex: %02X\n", mac) macStr := fmt.Sprintf("%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]) p.connectedBoardInfos.BLEMacAddress = macStr - p.state = SendInitialTS - } else if res.Type() == cborcoders.ProvisioningStatusMessageType { + return SendInitialTS, nil + } + + if res.Type() == cborcoders.ProvisioningStatusMessageType { status := res.ToProvisioningStatusMessage() - newState, err := p.configStates.HandleStatusMessage(status.Status) - if err != nil { - return err - } - if newState != NoneState { - p.state = newState - return nil - } + return p.configStates.HandleStatusMessage(status.Status) } - return errors.New("Provisioning V2: BLE MAC address not received") + + return ErrorState, errors.New("provisioning V2: BLE MAC address not received") } -func (p *ProvisionV2) sendInitialTS() error { +func (p *ProvisionV2) sendInitialTS(ctx context.Context) (ConfigStatus, error) { logrus.Info("Provisioning V2: Sending initial timestamp") ts := time.Now().Unix() logrus.Infof("Provisioning V2: Sending timestamp: %d\n", ts) tsMessage := cborcoders.From(cborcoders.ProvisioningTimestampMessage{Timestamp: uint64(ts)}) err := p.provProt.SendData(tsMessage) if err != nil { - return err + return ErrorState, err } - p.state = IDRequest - time.Sleep(1 * time.Second) - return nil + sleepCtx(ctx, 1*time.Second) + return IDRequest, nil } -func (p *ProvisionV2) getIDRequest() error { +func (p *ProvisionV2) getIDRequest() (ConfigStatus, error) { logrus.Info("Provisioning V2: Requesting UniqueID") getuuidMessage := cborcoders.From(cborcoders.ProvisioningCommandsMessage{Command: configurationprotocol.Commands["GetID"]}) err := p.provProt.SendData(getuuidMessage) if err != nil { - return err + return ErrorState, err } - p.state = WaitingPublicKey - return nil + + return WaitingPublicKey, nil } -func (p *ProvisionV2) waitingPublicKey() error { - res, err := p.provProt.ReceiveData(60) +func (p *ProvisionV2) waitingPublicKey() (ConfigStatus, error) { + res, err := p.provProt.ReceiveData(CommandResponseTimeoutLong_s) if err != nil { - return err + return ErrorState, err } if res == nil { - return errors.New("Provisioning V2: public key was not received") + return ErrorState, errors.New("provisioning V2: public key was not received") } if res.Type() == cborcoders.ProvisioningPublicKeyMessageType { pubKey := res.ToProvisioningPublicKeyMessage().ProvisioningPublicKey logrus.Infof("Provisioning V2: Received Public Key\n") p.connectedBoardInfos.PublicKey = pubKey - p.state = WaitingID - } else if res.Type() == cborcoders.ProvisioningStatusMessageType { + return WaitingID, nil + } + + if res.Type() == cborcoders.ProvisioningStatusMessageType { status := res.ToProvisioningStatusMessage() newState, err := p.configStates.HandleStatusMessage(status.Status) - if err != nil { - return err - } if newState == MissingParameter { - p.state = SendInitialTS - return nil - } - - if newState != NoneState { - p.state = newState - return nil + return SendInitialTS, nil } + return newState, err } - return errors.New("Provisioning V2: Public Key not received") + return ErrorState, errors.New("provisioning V2: Public Key not received") } -func (p *ProvisionV2) waitingUHWID() error { - res, err := p.provProt.ReceiveData(60) +func (p *ProvisionV2) waitingUHWID() (ConfigStatus, error) { + res, err := p.provProt.ReceiveData(CommandResponseTimeoutLong_s) if err != nil { - return err + return ErrorState, err } if res == nil { - return errors.New("Provisioning V2: UniqueID was not received") + return ErrorState, errors.New("provisioning V2: UniqueID was not received") } if res.Type() == cborcoders.ProvisioningUniqueIdMessageType { @@ -523,53 +459,43 @@ func (p *ProvisionV2) waitingUHWID() error { logrus.Infof("Provisioning V2: Received UniqueID\n") uhwidString := string(uhwid[:]) p.connectedBoardInfos.UHWID = uhwidString - p.state = WaitingSignature - } else if res.Type() == cborcoders.ProvisioningStatusMessageType { - status := res.ToProvisioningStatusMessage() - newState, err := p.configStates.HandleStatusMessage(status.Status) - if err != nil { - return err - } + return WaitingSignature, nil + } - if newState != NoneState { - p.state = newState - return nil - } + if res.Type() == cborcoders.ProvisioningStatusMessageType { + status := res.ToProvisioningStatusMessage() + return p.configStates.HandleStatusMessage(status.Status) } - return errors.New("Provisioning V2: UniqueID was not received") + + return ErrorState, errors.New("provisioning V2: UniqueID was not received") } -func (p *ProvisionV2) waitingSignature() error { - res, err := p.provProt.ReceiveData(60) +func (p *ProvisionV2) waitingSignature() (ConfigStatus, error) { + res, err := p.provProt.ReceiveData(CommandResponseTimeoutLong_s) if err != nil { - return err + return ErrorState, err } if res == nil { - return errors.New("Provisioning V2: Signature was not received") + return ErrorState, errors.New("provisioning V2: Signature was not received") } if res.Type() == cborcoders.ProvisioningSignatureMessageType { signature := res.ToProvisioningSignatureMessage().Signature logrus.Infof("Provisioning V2: Received Signature\n") p.connectedBoardInfos.Signature = string(signature[:]) - p.state = ClaimDevice - } else if res.Type() == cborcoders.ProvisioningStatusMessageType { - status := res.ToProvisioningStatusMessage() - newState, err := p.configStates.HandleStatusMessage(status.Status) - if err != nil { - return err - } + return ClaimDevice, nil + } - if newState != NoneState { - p.state = newState - return nil - } + if res.Type() == cborcoders.ProvisioningStatusMessageType { + status := res.ToProvisioningStatusMessage() + return p.configStates.HandleStatusMessage(status.Status) } - return errors.New("Provisioning V2: Signature was not received") + + return ErrorState, errors.New("provisioning V2: Signature was not received") } -func (p *ProvisionV2) claimDevice(name, connectionType string) error { +func (p *ProvisionV2) claimDevice(name, connectionType string) (ConfigStatus, error) { logrus.Info("Provisioning V2: Claiming device...") claimData := provisioningapi.ClaimData{ @@ -581,31 +507,32 @@ func (p *ProvisionV2) claimDevice(name, connectionType string) error { provResp, provErr, err := p.provisioningClient.ClaimDevice(claimData) if err != nil { - return err + return ErrorState, err } if provErr != nil { if provErr.ErrCode == 1 || provErr.ErrCode == 2 { logrus.Warn("Provisioning V2: Device claim failed. The board has to migrate") - p.state = RegisterDevice - } else if provErr.ErrCode == 3 { + return RegisterDevice, nil + } + + if provErr.ErrCode == 3 { // If the device key and the DB key are different - return fmt.Errorf("Provisioning V2: Device claim failed. Keys do not match. Please contact the Arduino Support with this hardware id: %s", p.connectedBoardInfos.UHWID) - } else { - return fmt.Errorf("Provisioning V2: Device claim failed with error: %s", provErr.Err) + return ErrorState, fmt.Errorf("provisioning V2: Device claim failed. Keys do not match. Please contact the Arduino Support with this hardware id: %s", p.connectedBoardInfos.UHWID) } + + return ErrorState, fmt.Errorf("provisioning V2: Device claim failed with error: %s", provErr.Err) } if provResp != nil { p.provisioningId = provResp.OnboardId - p.state = RequestReset - return nil + return RequestReset, nil } - return errors.New("Provisioning V2: Device ID not received") + return ErrorState, errors.New("provisioning V2: Device ID not received") } -func (p *ProvisionV2) registerDevice(fqbn, serial string) error { +func (p *ProvisionV2) registerDevice(fqbn, serial string) (ConfigStatus, error) { logrus.Info("Provisioning V2: Registering device...") registerData := provisioningapi.RegisterBoardData{ @@ -618,76 +545,65 @@ func (p *ProvisionV2) registerDevice(fqbn, serial string) error { provErr, err := p.provisioningClient.RegisterDevice(registerData) if err != nil { - return err + return ErrorState, err } if provErr != nil { - return fmt.Errorf("Provisioning V2: Device registration failed with error: %s", provErr.Err) + return ErrorState, fmt.Errorf("provisioning V2: Device registration failed with error: %s", provErr.Err) } logrus.Info("Provisioning V2: Device registered successfully, claiming...") - p.state = ClaimDevice - return nil + return ClaimDevice, nil } -func (p *ProvisionV2) resetBoardRequest() error { +func (p *ProvisionV2) resetBoardRequest() (ConfigStatus, error) { logrus.Info("Provisioning V2: Requesting Reset Stored Credentials") resetMessage := cborcoders.From(cborcoders.ProvisioningCommandsMessage{Command: configurationprotocol.Commands["Reset"]}) err := p.provProt.SendData(resetMessage) if err != nil { - return err + return ErrorState, err } - p.state = WaitResetResponse - return nil + + return WaitResetResponse, nil } -func (p *ProvisionV2) waitingForResetResult() error { - res, err := p.provProt.ReceiveData(60) +func (p *ProvisionV2) waitingForResetResult() (ConfigStatus, error) { + res, err := p.provProt.ReceiveData(CommandResponseTimeoutLong_s) if err != nil { - return err + return ErrorState, err } if res != nil && res.Type() == cborcoders.ProvisioningStatusMessageType { status := res.ToProvisioningStatusMessage() if status.Status == 4 { logrus.Info("Provisioning V2: Reset Stored Credentials successful") - p.state = ConfigureNetwork - } else { - newState, err := p.configStates.HandleStatusMessage(status.Status) - if err != nil { - return err - } - - if newState != NoneState { - p.state = newState - return nil - } + return ConfigureNetwork, nil } + return p.configStates.HandleStatusMessage(status.Status) } - return errors.New("Provisioning V2: Reset Stored Credentials failed") + return ErrorState, errors.New("provisioning V2: Reset Stored Credentials failed") } -func (p *ProvisionV2) waitProvisioningResult(ctx context.Context) error { +func (p *ProvisionV2) waitProvisioningResult(ctx context.Context) (ConfigStatus, error) { logrus.Info("Provisioning V2: Waiting for provisioning result...") - for n := 0; n < 20; n++ { + for n := 0; n < MaxRetriesProvisioningResult; n++ { res, err := p.provisioningClient.GetProvisioningDetail(p.provisioningId) if err != nil { - return err + return ErrorState, err } if res.DeviceID != nil { p.deviceId = *res.DeviceID - p.state = End + return End, nil } sleepCtx(ctx, 10*time.Second) } - return errors.New("Provisioning V2: Timeout expires for board provisioning. The board was not able to reach the Arduino IoT Cloud for completing the provisioning.") + return ErrorState, errors.New("provisioning V2: Timeout expires for board provisioning. The board was not able to reach the Arduino IoT Cloud for completing the provisioning") } -func (p *ProvisionV2) unclaimDevice() error { +func (p *ProvisionV2) unclaimDevice() (ConfigStatus, error) { logrus.Warnf("Provisioning V2: Something went wrong, unclaiming device...") _, err := p.provisioningClient.UnclaimDevice(p.provisioningId) - p.state = End - return err + return End, err } From 210646437901669e0476998d63607f88096913f2 Mon Sep 17 00:00:00 2001 From: fabik111 Date: Thu, 28 Aug 2025 14:15:13 +0200 Subject: [PATCH 15/27] fix clients --- internal/iot-api-raw/client.go | 6 +++--- internal/provisioning-api/client.go | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/internal/iot-api-raw/client.go b/internal/iot-api-raw/client.go index d0ec0b38..70959955 100644 --- a/internal/iot-api-raw/client.go +++ b/internal/iot-api-raw/client.go @@ -62,7 +62,7 @@ func (c *IoTApiRawClient) getToken() (*oauth2.Token, error) { } func (c *IoTApiRawClient) GetBoardsDetail() (*BoardTypeList, error) { - endpoint := c.host + "iot/v1/supported/devices" + endpoint := c.host + "/iot/v1/supported/devices" token, err := c.getToken() if err != nil { return nil, err @@ -107,7 +107,7 @@ func (c *IoTApiRawClient) GetBoardDetailByFQBN(fqbn string) (*BoardType, error) } for _, b := range *boardsList { - if *b.FQBN == fqbn { + if b.FQBN != nil && *b.FQBN == fqbn { return &b, nil } } @@ -115,7 +115,7 @@ func (c *IoTApiRawClient) GetBoardDetailByFQBN(fqbn string) (*BoardType, error) } func (c *IoTApiRawClient) DownloadProvisioningV2Sketch(fqbn string, path *paths.Path, filename *string) (string, error) { - endpoint := c.host + "iot/v2/binaries/provisioningv2?fqbn=" + fqbn + endpoint := c.host + "/iot/v2/binaries/provisioningv2?fqbn=" + fqbn token, err := c.getToken() if err != nil { return "", err diff --git a/internal/provisioning-api/client.go b/internal/provisioning-api/client.go index f08563f5..0298cf72 100644 --- a/internal/provisioning-api/client.go +++ b/internal/provisioning-api/client.go @@ -78,7 +78,7 @@ func (c *ProvisioningApiClient) getToken() (*oauth2.Token, error) { } func (c *ProvisioningApiClient) ClaimDevice(data ClaimData) (*ClaimResponse, *BadResponse, error) { - endpoint := c.host + "provisioning/v1/onboarding/claim" + endpoint := c.host + "/provisioning/v1/onboarding/claim" token, err := c.getToken() if err != nil { return nil, nil, err @@ -113,14 +113,14 @@ func (c *ProvisioningApiClient) ClaimDevice(data ClaimData) (*ClaimResponse, *Ba err = json.Unmarshal(respBytes, &badResponse) if err != nil { - return nil, nil, err + return nil, nil, fmt.Errorf("failed to unmarshal bad response: %s", respBytes) } return nil, &badResponse, nil } func (c *ProvisioningApiClient) RegisterDevice(data RegisterBoardData) (*BadResponse, error) { - endpoint := c.host + "provisioning/v1/boards/register" + endpoint := c.host + "/provisioning/v1/boards/register" token, err := c.getToken() if err != nil { return nil, err @@ -156,7 +156,7 @@ func (c *ProvisioningApiClient) RegisterDevice(data RegisterBoardData) (*BadResp } func (c *ProvisioningApiClient) UnclaimDevice(provisioningId string) (*BadResponse, error) { - endpoint := c.host + "provisioning/v1/onboarding/" + provisioningId + endpoint := c.host + "/provisioning/v1/onboarding/" + provisioningId token, err := c.getToken() if err != nil { return nil, err @@ -185,7 +185,7 @@ func (c *ProvisioningApiClient) UnclaimDevice(provisioningId string) (*BadRespon } func (c *ProvisioningApiClient) GetProvisioningList() (*OnboardingsResponse, error) { - endpoint := c.host + "provisioning/v1/onboarding?all=true" + endpoint := c.host + "/provisioning/v1/onboarding?all=true" token, err := c.getToken() if err != nil { return nil, err From 99214559e02c2a9331492cc6739d941570d3ebb8 Mon Sep 17 00:00:00 2001 From: fabik111 Date: Thu, 28 Aug 2025 14:15:39 +0200 Subject: [PATCH 16/27] fix print --- command/device/provisionv2.go | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/command/device/provisionv2.go b/command/device/provisionv2.go index 25f5fba1..5f1fe95f 100644 --- a/command/device/provisionv2.go +++ b/command/device/provisionv2.go @@ -25,6 +25,7 @@ import ( "strconv" "strings" "time" + "unicode" "github.com/arduino/arduino-cloud-cli/arduino" "github.com/arduino/arduino-cloud-cli/config" @@ -291,7 +292,7 @@ func (p *ProvisionV2) flashProvisioningSketch(ctx context.Context, fqbn, address } // Try to upload the provisioning sketch - logrus.Infof("%s\n", "Uploading provisioning sketch on the board") + logrus.Info("Uploading provisioning sketch on the board") errMsg := "Provisioning V2: error while uploading the provisioning sketch" err = retry(ctx, MaxRetriesFlashProvSketch, time.Millisecond*1000, errMsg, func() error { return p.UploadBin(ctx, fqbn, file, address, protocol) @@ -338,7 +339,7 @@ func (p *ProvisionV2) waitWiFiFWVersion(minWiFiVersion *string) (ConfigStatus, e if res.Type() == cborcoders.ProvisioningWiFiFWVersionMessageType { wifi_version := res.ToProvisioningWiFiFWVersionMessage().WiFiFWVersion - fmt.Printf("Received WiFi FW Version: %s\n", wifi_version) + logrus.Infof("Received WiFi FW Version: %s", wifi_version) if minWiFiVersion != nil && p.compareVersions(wifi_version, *minWiFiVersion) < 0 { return ErrorState, fmt.Errorf("provisioning V2: WiFi FW version %s is lower than required minimum %s. Please update the board firmware using Arduino IDE or Arduino CLI", wifi_version, *minWiFiVersion) @@ -378,7 +379,7 @@ func (p *ProvisionV2) waitBLEMac() (ConfigStatus, error) { if res.Type() == cborcoders.ProvisioningBLEMacAddressMessageType { mac := res.ToProvisioningBLEMacAddressMessage().BLEMacAddress - logrus.Infof("Provisioning V2: Received MAC in hex: %02X\n", mac) + logrus.Infof("Provisioning V2: Received MAC in hex: %02X", mac) macStr := fmt.Sprintf("%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]) p.connectedBoardInfos.BLEMacAddress = macStr return SendInitialTS, nil @@ -395,7 +396,7 @@ func (p *ProvisionV2) waitBLEMac() (ConfigStatus, error) { func (p *ProvisionV2) sendInitialTS(ctx context.Context) (ConfigStatus, error) { logrus.Info("Provisioning V2: Sending initial timestamp") ts := time.Now().Unix() - logrus.Infof("Provisioning V2: Sending timestamp: %d\n", ts) + logrus.Infof("Provisioning V2: Sending timestamp: %d", ts) tsMessage := cborcoders.From(cborcoders.ProvisioningTimestampMessage{Timestamp: uint64(ts)}) err := p.provProt.SendData(tsMessage) if err != nil { @@ -428,7 +429,7 @@ func (p *ProvisionV2) waitingPublicKey() (ConfigStatus, error) { if res.Type() == cborcoders.ProvisioningPublicKeyMessageType { pubKey := res.ToProvisioningPublicKeyMessage().ProvisioningPublicKey - logrus.Infof("Provisioning V2: Received Public Key\n") + logrus.Info("Provisioning V2: Received Public Key") p.connectedBoardInfos.PublicKey = pubKey return WaitingID, nil } @@ -456,7 +457,7 @@ func (p *ProvisionV2) waitingUHWID() (ConfigStatus, error) { if res.Type() == cborcoders.ProvisioningUniqueIdMessageType { uhwid := res.ToProvisioningUniqueIdMessage().UniqueId - logrus.Infof("Provisioning V2: Received UniqueID\n") + logrus.Infof("Provisioning V2: Received UniqueID") uhwidString := string(uhwid[:]) p.connectedBoardInfos.UHWID = uhwidString return WaitingSignature, nil @@ -482,8 +483,12 @@ func (p *ProvisionV2) waitingSignature() (ConfigStatus, error) { if res.Type() == cborcoders.ProvisioningSignatureMessageType { signature := res.ToProvisioningSignatureMessage().Signature - logrus.Infof("Provisioning V2: Received Signature\n") - p.connectedBoardInfos.Signature = string(signature[:]) + logrus.Infof("Provisioning V2: Received Signature") + + signatureString := strings.TrimRightFunc(fmt.Sprintf("%s", signature), func(r rune) bool { + return unicode.IsLetter(r) == false && unicode.IsNumber(r) == false + }) + p.connectedBoardInfos.Signature = signatureString return ClaimDevice, nil } @@ -507,7 +512,7 @@ func (p *ProvisionV2) claimDevice(name, connectionType string) (ConfigStatus, er provResp, provErr, err := p.provisioningClient.ClaimDevice(claimData) if err != nil { - return ErrorState, err + return ErrorState, fmt.Errorf("provisioning V2: failed to claim device: %w", err) } if provErr != nil { @@ -545,7 +550,7 @@ func (p *ProvisionV2) registerDevice(fqbn, serial string) (ConfigStatus, error) provErr, err := p.provisioningClient.RegisterDevice(registerData) if err != nil { - return ErrorState, err + return ErrorState, fmt.Errorf("provisioning V2: failed to register device: %w", err) } if provErr != nil { From 51ee3ed47c782c9e4fe9e8fd5d01d8f73dd4c6a0 Mon Sep 17 00:00:00 2001 From: fabik111 Date: Thu, 28 Aug 2025 15:39:03 +0200 Subject: [PATCH 17/27] add log for network configuration --- command/device/configurationstates.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/command/device/configurationstates.go b/command/device/configurationstates.go index d25a590f..98463d88 100644 --- a/command/device/configurationstates.go +++ b/command/device/configurationstates.go @@ -150,6 +150,7 @@ func (c *ConfigurationStates) WaitingForNetworkOptions() (ConfigStatus, error) { } func (cs *ConfigurationStates) ConfigureNetwork(ctx context.Context, c *NetConfig) (ConfigStatus, error) { + logrus.Info("NetworkConfigure: Sending network configuration") var cmd cborcoders.Cmd if c.Type == 1 { // WiFi cmd = cborcoders.From(cborcoders.ProvisioningWifiConfigMessage{ @@ -216,6 +217,7 @@ func (cs *ConfigurationStates) ConfigureNetwork(ctx context.Context, c *NetConfi } func (c *ConfigurationStates) SendConnectionRequest() (ConfigStatus, error) { + logrus.Info("NetworkConfigure: Sending connection request") connectMessage := cborcoders.From(cborcoders.ProvisioningCommandsMessage{Command: configurationprotocol.Commands["Connect"]}) err := c.configProtocol.SendData(connectMessage) if err != nil { @@ -226,6 +228,7 @@ func (c *ConfigurationStates) SendConnectionRequest() (ConfigStatus, error) { } func (c *ConfigurationStates) WaitingForConnectionCommandResult() (ConfigStatus, error) { + logrus.Info("NetworkConfigure: Waiting for connection command result") res, err := c.configProtocol.ReceiveData(CommandResponseTimeoutLong_s) if err != nil { return ErrorState, err @@ -249,6 +252,7 @@ func (c *ConfigurationStates) WaitingForConnectionCommandResult() (ConfigStatus, } func (c *ConfigurationStates) WaitingForNetworkConfigResult() (ConfigStatus, error) { + logrus.Info("NetworkConfigure: Waiting for network configuration result") res, err := c.configProtocol.ReceiveData(ConnectResponseTimeout_s) if err != nil { return ErrorState, err From 18d64dc751af2fadb8137687e93c66c63eaaafbe Mon Sep 17 00:00:00 2001 From: fabik111 Date: Thu, 28 Aug 2025 16:10:29 +0200 Subject: [PATCH 18/27] fix connection error for cellular, cat-m1, nb-iot and gsm boards --- command/device/configurationstates.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/command/device/configurationstates.go b/command/device/configurationstates.go index 98463d88..aa6f6eae 100644 --- a/command/device/configurationstates.go +++ b/command/device/configurationstates.go @@ -107,7 +107,7 @@ func (c *ConfigurationStates) WaitingForInitialStatus() (ConfigStatus, error) { return WaitingForInitialStatus, nil } - if status.Status == -6 || status.Status <= -101 { + if status.Status == -6 || status.Status < -101 { return c.HandleStatusMessage(status.Status) } return WaitingForNetworkOptions, nil @@ -264,6 +264,11 @@ func (c *ConfigurationStates) WaitingForNetworkConfigResult() (ConfigStatus, err if status.Status == 2 { return End, nil } + //For boards of type Cellular, CAT-M1, GSM e NB-IOT that + //returns -3 or -101 when the network configuration is invalid + if status.Status == -3 || status.Status == -101 { + return ErrorState, errors.New("connection failed: invalid network configuration") + } return c.HandleStatusMessage(status.Status) } @@ -297,7 +302,7 @@ func (c *ConfigurationStates) HandleStatusMessage(status int16) (ConfigStatus, e case "Scanning for WiFi networks": return WaitingForNetworkOptions, nil case "Failed to connect": - return ErrorState, errors.New("connection failed invalid credentials or network configuration") + return ErrorState, errors.New("connection failed: invalid network configuration") case "Disconnected": return NoneState, nil case "Parameters not provided": From d02e70751ccc03f869174d3faaf1886512625bde Mon Sep 17 00:00:00 2001 From: fabik111 Date: Thu, 28 Aug 2025 16:10:50 +0200 Subject: [PATCH 19/27] add starting message --- cli/device/create.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cli/device/create.go b/cli/device/create.go index bca5453e..0323a57c 100644 --- a/cli/device/create.go +++ b/cli/device/create.go @@ -83,6 +83,8 @@ func runCreateCommand(flags *createFlags) error { ctx, cancel := cleanup.InterruptableContext(context.Background()) defer cancel() + feedback.Printf("Creating device with name %s", flags.name) + dev, err := device.Create(ctx, params, cred) if err != nil { return err From fe6f01136d98bfbcba30e44e78d3c7f53376bb31 Mon Sep 17 00:00:00 2001 From: fabik111 Date: Thu, 28 Aug 2025 16:12:36 +0200 Subject: [PATCH 20/27] use ntp service for getting ts for claiming --- command/device/provisionv2.go | 13 +++++++++++-- go.mod | 9 +++++---- go.sum | 11 +++++++++++ 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/command/device/provisionv2.go b/command/device/provisionv2.go index 5f1fe95f..844af052 100644 --- a/command/device/provisionv2.go +++ b/command/device/provisionv2.go @@ -36,6 +36,7 @@ import ( iotapiraw "github.com/arduino/arduino-cloud-cli/internal/iot-api-raw" provisioningapi "github.com/arduino/arduino-cloud-cli/internal/provisioning-api" "github.com/arduino/go-paths-helper" + "github.com/beevik/ntp" "github.com/sirupsen/logrus" ) @@ -395,10 +396,18 @@ func (p *ProvisionV2) waitBLEMac() (ConfigStatus, error) { func (p *ProvisionV2) sendInitialTS(ctx context.Context) (ConfigStatus, error) { logrus.Info("Provisioning V2: Sending initial timestamp") - ts := time.Now().Unix() + var ts int64 + t, err := ntp.Time("time.arduino.cc") + if err == nil { + ts = t.Unix() + } else { + logrus.Warnf("Provisioning V2: Cannot get time from NTP server, using local time: %v", err) + ts = time.Now().Unix() + } + logrus.Infof("Provisioning V2: Sending timestamp: %d", ts) tsMessage := cborcoders.From(cborcoders.ProvisioningTimestampMessage{Timestamp: uint64(ts)}) - err := p.provProt.SendData(tsMessage) + err = p.provProt.SendData(tsMessage) if err != nil { return ErrorState, err } diff --git a/go.mod b/go.mod index 99b2ec48..451f149c 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/stretchr/testify v1.9.0 go.bug.st/cleanup v1.0.0 go.bug.st/serial v1.6.2 - golang.org/x/crypto v0.18.0 + golang.org/x/crypto v0.23.0 golang.org/x/oauth2 v0.25.0 google.golang.org/grpc v1.61.0 gopkg.in/yaml.v3 v3.0.1 @@ -28,6 +28,7 @@ require ( require ( github.com/Microsoft/go-winio v0.6.1 // indirect github.com/arduino/go-properties-orderedmap v1.7.1 // indirect + github.com/beevik/ntp v1.4.3 // indirect github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect github.com/cmaglie/pb v1.0.27 // indirect github.com/codeclysm/extract/v4 v4.0.0 // indirect @@ -73,9 +74,9 @@ require ( go.bug.st/downloader/v2 v2.1.1 // indirect go.bug.st/relaxed-semver v0.9.0 // indirect golang.org/x/mod v0.14.0 // indirect - golang.org/x/net v0.20.0 // indirect - golang.org/x/sys v0.16.0 // indirect - golang.org/x/text v0.14.0 // indirect + golang.org/x/net v0.25.0 // indirect + golang.org/x/sys v0.20.0 // indirect + golang.org/x/text v0.15.0 // indirect golang.org/x/tools v0.17.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240205150955-31a09d347014 // indirect google.golang.org/protobuf v1.34.2 // indirect diff --git a/go.sum b/go.sum index 4b8560ba..682a669c 100644 --- a/go.sum +++ b/go.sum @@ -80,6 +80,8 @@ github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/beevik/ntp v1.4.3 h1:PlbTvE5NNy4QHmA4Mg57n7mcFTmr1W1j3gcK7L1lqho= +github.com/beevik/ntp v1.4.3/go.mod h1:Unr8Zg+2dRn7d8bHFuehIMSvvUYssHMxW3Q5Nx4RW5Q= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= @@ -487,6 +489,8 @@ golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -569,6 +573,8 @@ golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -672,9 +678,12 @@ golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= +golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -686,6 +695,8 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= From 7c80384d235a47dcc5ca607ea61f51efb2060cc9 Mon Sep 17 00:00:00 2001 From: fabik111 Date: Thu, 28 Aug 2025 18:11:44 +0200 Subject: [PATCH 21/27] fix provisioning fsm --- command/device/provisionv2.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/command/device/provisionv2.go b/command/device/provisionv2.go index 844af052..0821afee 100644 --- a/command/device/provisionv2.go +++ b/command/device/provisionv2.go @@ -129,6 +129,9 @@ func (p *ProvisionV2) Run(ctx context.Context, params ProvisioningV2BoardParams) nextState, err = p.configStates.WaitForConnection() case WaitingForInitialStatus: nextState, err = p.configStates.WaitingForInitialStatus() + if err != nil { + nextState = FlashProvisioningSketch + } case WaitingForNetworkOptions: nextState, err = p.configStates.WaitingForNetworkOptions() if err != nil { @@ -197,15 +200,16 @@ func (p *ProvisionV2) Run(ctx context.Context, params ProvisioningV2BoardParams) _, err = p.configStates.WaitingForNetworkConfigResult() if err != nil { nextState = UnclaimDevice + } else { + nextState = WaitingForProvisioningResult } - nextState = WaitingForProvisioningResult case WaitingForProvisioningResult: nextState, err = p.waitProvisioningResult(ctx) if err != nil { nextState = UnclaimDevice } case UnclaimDevice: - nextState, err = p.unclaimDevice() + nextState, _ = p.unclaimDevice() } if nextState != NoneState { @@ -276,6 +280,9 @@ func (p *ProvisionV2) waitingSketchVersion(minSketchVersion string) (ConfigStatu if res.Type() == cborcoders.ProvisioningStatusMessageType { status := res.ToProvisioningStatusMessage() + if status.Status == -7 { + return FlashProvisioningSketch, nil + } return p.configStates.HandleStatusMessage(status.Status) } @@ -294,6 +301,7 @@ func (p *ProvisionV2) flashProvisioningSketch(ctx context.Context, fqbn, address // Try to upload the provisioning sketch logrus.Info("Uploading provisioning sketch on the board") + p.provProt.Close() errMsg := "Provisioning V2: error while uploading the provisioning sketch" err = retry(ctx, MaxRetriesFlashProvSketch, time.Millisecond*1000, errMsg, func() error { return p.UploadBin(ctx, fqbn, file, address, protocol) From 7e4e2efdc348bc038e23db18f61b46bce7ebeed4 Mon Sep 17 00:00:00 2001 From: fabik111 Date: Fri, 29 Aug 2025 11:29:53 +0200 Subject: [PATCH 22/27] fix parsing uhwid --- command/device/provisionv2.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/command/device/provisionv2.go b/command/device/provisionv2.go index 0821afee..6fd0b779 100644 --- a/command/device/provisionv2.go +++ b/command/device/provisionv2.go @@ -475,7 +475,7 @@ func (p *ProvisionV2) waitingUHWID() (ConfigStatus, error) { if res.Type() == cborcoders.ProvisioningUniqueIdMessageType { uhwid := res.ToProvisioningUniqueIdMessage().UniqueId logrus.Infof("Provisioning V2: Received UniqueID") - uhwidString := string(uhwid[:]) + uhwidString := fmt.Sprintf("%02x", uhwid) p.connectedBoardInfos.UHWID = uhwidString return WaitingSignature, nil } From 9e7501c8f3c969ac3cd067680f1eca94af2aec7e Mon Sep 17 00:00:00 2001 From: fabik111 Date: Mon, 1 Sep 2025 14:55:28 +0200 Subject: [PATCH 23/27] bump up the arduino-cli dependency to version 0.29.x last commit --- go.mod | 8 ++++---- go.sum | 19 +++++-------------- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/go.mod b/go.mod index 451f149c..8c85a5bc 100644 --- a/go.mod +++ b/go.mod @@ -3,10 +3,12 @@ module github.com/arduino/arduino-cloud-cli go 1.23 require ( - github.com/arduino/arduino-cli v0.0.0-20240927141754-d9dd4ba1ed71 + github.com/arduino/arduino-cli v0.0.0-20250901123057-20dd7c932f59 github.com/arduino/go-paths-helper v1.12.1 github.com/arduino/go-win32-utils v1.0.0 github.com/arduino/iot-client-go/v3 v3.1.1 + github.com/beevik/ntp v1.4.3 + github.com/fxamacker/cbor/v2 v2.8.0 github.com/gofrs/uuid v4.2.0+incompatible github.com/google/go-cmp v0.6.0 github.com/howeyc/crc16 v0.0.0-20171223171357-2b2a61e366a6 @@ -28,7 +30,6 @@ require ( require ( github.com/Microsoft/go-winio v0.6.1 // indirect github.com/arduino/go-properties-orderedmap v1.7.1 // indirect - github.com/beevik/ntp v1.4.3 // indirect github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect github.com/cmaglie/pb v1.0.27 // indirect github.com/codeclysm/extract/v4 v4.0.0 // indirect @@ -37,7 +38,6 @@ require ( github.com/emirpasic/gods v1.18.1 // indirect github.com/fatih/color v1.13.0 // indirect github.com/fsnotify/fsnotify v1.5.1 // indirect - github.com/fxamacker/cbor/v2 v2.8.0 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/h2non/filetype v1.1.3 // indirect github.com/hashicorp/hcl v1.0.0 // indirect @@ -72,7 +72,7 @@ require ( github.com/x448/float16 v0.8.4 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect go.bug.st/downloader/v2 v2.1.1 // indirect - go.bug.st/relaxed-semver v0.9.0 // indirect + go.bug.st/relaxed-semver v0.10.1 // indirect golang.org/x/mod v0.14.0 // indirect golang.org/x/net v0.25.0 // indirect golang.org/x/sys v0.20.0 // indirect diff --git a/go.sum b/go.sum index 682a669c..1f3605b6 100644 --- a/go.sum +++ b/go.sum @@ -62,8 +62,8 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/arduino/arduino-cli v0.0.0-20240927141754-d9dd4ba1ed71 h1:UsiGQuo0H5l7DmZYuEn20jBiPHSOj8QF80uyoegXE90= -github.com/arduino/arduino-cli v0.0.0-20240927141754-d9dd4ba1ed71/go.mod h1:jkWY40xUrKH6CYi1ppeFF4h6LS3UaOUMo+fk4zYf74I= +github.com/arduino/arduino-cli v0.0.0-20250901123057-20dd7c932f59 h1:KjD3s14n+hc6G+NFzg6gh5F3AZU9zfoSSoa/ivZizbk= +github.com/arduino/arduino-cli v0.0.0-20250901123057-20dd7c932f59/go.mod h1:jkWY40xUrKH6CYi1ppeFF4h6LS3UaOUMo+fk4zYf74I= github.com/arduino/go-paths-helper v1.0.1/go.mod h1:HpxtKph+g238EJHq4geEPv9p+gl3v5YYu35Yb+w31Ck= github.com/arduino/go-paths-helper v1.12.1 h1:WkxiVUxBjKWlLMiMuYy8DcmVrkxdP7aKxQOAq7r2lVM= github.com/arduino/go-paths-helper v1.12.1/go.mod h1:jcpW4wr0u69GlXhTYydsdsqAjLaYK5n7oWHfKqOG6LM= @@ -456,8 +456,8 @@ go.bug.st/cleanup v1.0.0 h1:XVj1HZxkBXeq3gMT7ijWUpHyIC1j8XAoNSyQ06CskgA= go.bug.st/cleanup v1.0.0/go.mod h1:EqVmTg2IBk4znLbPD28xne3abjsJftMdqqJEjhn70bk= go.bug.st/downloader/v2 v2.1.1 h1:nyqbUizo3E2IxCCm4YFac4FtSqqFpqWP+Aae5GCMuw4= go.bug.st/downloader/v2 v2.1.1/go.mod h1:VZW2V1iGKV8rJL2ZEGIDzzBeKowYv34AedJz13RzVII= -go.bug.st/relaxed-semver v0.9.0 h1:qt0T8W70VCurvsbxRK25fQwiTOFjkzwC/fDOpyPnchQ= -go.bug.st/relaxed-semver v0.9.0/go.mod h1:ug0/W/RPYUjliE70Ghxg77RDHmPxqpo7SHV16ijss7Q= +go.bug.st/relaxed-semver v0.10.1 h1:g61DeaZ48IsikiPpd52wE/extF+sqX0SyllzsEIWhBM= +go.bug.st/relaxed-semver v0.10.1/go.mod h1:lPVGdtzbQ9/2fv6iXqIXWHOj6cMTUJ/l/Lu1w+sgdio= go.bug.st/serial v1.6.2 h1:kn9LRX3sdm+WxWKufMlIRndwGfPWsH1/9lCWXQCasq8= go.bug.st/serial v1.6.2/go.mod h1:UABfsluHAiaNI+La2iESysd9Vetq7VRdpxvjx7CmmOE= go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= @@ -487,8 +487,6 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= -golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -571,8 +569,6 @@ golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -676,14 +672,11 @@ golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= -golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= +golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -693,8 +686,6 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= From f6677078e7a5770599b4b58009ba3af74f2761e9 Mon Sep 17 00:00:00 2001 From: fabik111 Date: Mon, 1 Sep 2025 17:07:48 +0200 Subject: [PATCH 24/27] fix catm1 config --- command/device/configurationstates.go | 2 +- .../configuration-protocol/cborcoders/enc_dec.go | 2 +- .../cborcoders/enc_dec_test.go | 13 ++++++++++++- .../configuration-protocol/cborcoders/model.go | 2 +- 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/command/device/configurationstates.go b/command/device/configurationstates.go index aa6f6eae..ec095452 100644 --- a/command/device/configurationstates.go +++ b/command/device/configurationstates.go @@ -194,7 +194,7 @@ func (cs *ConfigurationStates) ConfigureNetwork(ctx context.Context, c *NetConfi Apn: c.CATM1.APN, Login: c.CATM1.Login, Pass: c.CATM1.Pass, - Band: c.CATM1.Band, + Band: nil, }) } else if c.Type == 7 { // Cellular cmd = cborcoders.From(cborcoders.ProvisioningCellularConfigMessage{ diff --git a/internal/board-protocols/configuration-protocol/cborcoders/enc_dec.go b/internal/board-protocols/configuration-protocol/cborcoders/enc_dec.go index b76aff8f..e9ff9aa7 100644 --- a/internal/board-protocols/configuration-protocol/cborcoders/enc_dec.go +++ b/internal/board-protocols/configuration-protocol/cborcoders/enc_dec.go @@ -79,7 +79,7 @@ func init() { panic(err) } - _em, err = cbor.EncOptions{IndefLength: 1}.EncModeWithTags(tags) + _em, err = cbor.EncOptions{IndefLength: 1, NilContainers: cbor.NilContainerAsEmpty}.EncModeWithTags(tags) if err != nil { panic(err) diff --git a/internal/board-protocols/configuration-protocol/cborcoders/enc_dec_test.go b/internal/board-protocols/configuration-protocol/cborcoders/enc_dec_test.go index f0f47bdc..3abe5b52 100644 --- a/internal/board-protocols/configuration-protocol/cborcoders/enc_dec_test.go +++ b/internal/board-protocols/configuration-protocol/cborcoders/enc_dec_test.go @@ -185,13 +185,24 @@ func TestEncodeDecode(t *testing.T) { name: "provisioning catm1 config", in: From(ProvisioningCATM1ConfigMessage{ PIN: "12345678", - Band: [4]uint32{1, 2, 524288, 134217728}, + Band: []uint32{1, 2, 524288, 134217728}, Apn: "apn.arduino.cc", Login: "TESTUSER", Pass: "TESTPASSWORD", }), want: "DA00012008856831323334353637388401021A000800001A080000006E61706E2E61726475696E6F2E63636854455354555345526C5445535450415353574F5244", }, + { + name: "provisioning catm1 config no band", + in: From(ProvisioningCATM1ConfigMessage{ + PIN: "12345678", + Band: []uint32{}, + Apn: "apn.arduino.cc", + Login: "TESTUSER", + Pass: "TESTPASSWORD", + }), + want: "DA0001200885683132333435363738806E61706E2E61726475696E6F2E63636854455354555345526C5445535450415353574F5244", + }, { name: "provisioning ethernet config ipv4", in: From(ProvisioningEthernetConfigMessage{ diff --git a/internal/board-protocols/configuration-protocol/cborcoders/model.go b/internal/board-protocols/configuration-protocol/cborcoders/model.go index ccb3f066..158af8c3 100644 --- a/internal/board-protocols/configuration-protocol/cborcoders/model.go +++ b/internal/board-protocols/configuration-protocol/cborcoders/model.go @@ -133,7 +133,7 @@ func (t ProvisioningLoRaConfigMessage) String() string { type ProvisioningCATM1ConfigMessage struct { _ struct{} `cbor:",toarray"` PIN string - Band [4]uint32 + Band []uint32 Apn string Login string Pass string From 1e712ea8403369ecd8601b8c7a9bafab930aef6c Mon Sep 17 00:00:00 2001 From: fabik111 Date: Mon, 1 Sep 2025 17:22:34 +0200 Subject: [PATCH 25/27] update .licenses --- .../arduino/arduino-cli/arduino.dep.yml | 6 +- .../arduino/arduino-cli/arduino/cores.dep.yml | 6 +- .../arduino/cores/packageindex.dep.yml | 6 +- .../arduino/cores/packagemanager.dep.yml | 6 +- .../arduino-cli/arduino/discovery.dep.yml | 6 +- .../discovery/discoverymanager.dep.yml | 6 +- .../arduino-cli/arduino/globals.dep.yml | 6 +- .../arduino-cli/arduino/httpclient.dep.yml | 6 +- .../arduino-cli/arduino/libraries.dep.yml | 6 +- .../arduino/libraries/librariesindex.dep.yml | 6 +- .../libraries/librariesmanager.dep.yml | 6 +- .../arduino-cli/arduino/resources.dep.yml | 6 +- .../arduino-cli/arduino/security.dep.yml | 6 +- .../arduino-cli/arduino/serialutils.dep.yml | 6 +- .../arduino-cli/arduino/sketch.dep.yml | 6 +- .../arduino/arduino-cli/arduino/utils.dep.yml | 6 +- .../arduino-cli/cli/errorcodes.dep.yml | 6 +- .../arduino/arduino-cli/cli/feedback.dep.yml | 6 +- .../arduino/arduino-cli/cli/globals.dep.yml | 6 +- .../arduino/arduino-cli/cli/instance.dep.yml | 6 +- .../arduino/arduino-cli/cli/output.dep.yml | 6 +- .../arduino/arduino-cli/commands.dep.yml | 6 +- .../arduino-cli/commands/board.dep.yml | 6 +- .../arduino-cli/commands/upload.dep.yml | 6 +- .../arduino/arduino-cli/configuration.dep.yml | 6 +- .../arduino/arduino-cli/executils.dep.yml | 6 +- .../arduino/arduino-cli/i18n.dep.yml | 4 +- .../rpc/cc/arduino/cli/commands/v1.dep.yml | 6 +- .../arduino/arduino-cli/table.dep.yml | 6 +- .../arduino/arduino-cli/version.dep.yml | 6 +- .licenses/go/github.com/beevik/ntp.dep.yml | 36 +++++++++++ .licenses/go/go.bug.st/relaxed-semver.dep.yml | 2 +- .../go/golang.org/x/crypto/blowfish.dep.yml | 6 +- .../go/golang.org/x/crypto/cast5.dep.yml | 6 +- .../go/golang.org/x/crypto/curve25519.dep.yml | 6 +- .../go/golang.org/x/crypto/openpgp.dep.yml | 6 +- .../golang.org/x/crypto/openpgp/armor.dep.yml | 6 +- .../x/crypto/openpgp/elgamal.dep.yml | 6 +- .../x/crypto/openpgp/errors.dep.yml | 6 +- .../x/crypto/openpgp/packet.dep.yml | 6 +- .../golang.org/x/crypto/openpgp/s2k.dep.yml | 6 +- .licenses/go/golang.org/x/crypto/ssh.dep.yml | 6 +- .../go/golang.org/x/crypto/ssh/agent.dep.yml | 6 +- .../crypto/ssh/internal/bcrypt_pbkdf.dep.yml | 6 +- .../x/crypto/ssh/knownhosts.dep.yml | 6 +- .licenses/go/golang.org/x/net/bpf.dep.yml | 63 +++++++++++++++++++ .licenses/go/golang.org/x/net/context.dep.yml | 6 +- .licenses/go/golang.org/x/net/http2.dep.yml | 6 +- .../go/golang.org/x/net/internal/iana.dep.yml | 63 +++++++++++++++++++ .../golang.org/x/net/internal/socket.dep.yml | 62 ++++++++++++++++++ .../golang.org/x/net/internal/socks.dep.yml | 6 +- .../x/net/internal/timeseries.dep.yml | 6 +- .licenses/go/golang.org/x/net/ipv4.dep.yml | 63 +++++++++++++++++++ .licenses/go/golang.org/x/net/proxy.dep.yml | 6 +- .licenses/go/golang.org/x/net/trace.dep.yml | 6 +- .licenses/go/golang.org/x/sys/unix.dep.yml | 6 +- .licenses/go/golang.org/x/text/runes.dep.yml | 6 +- 57 files changed, 440 insertions(+), 153 deletions(-) create mode 100644 .licenses/go/github.com/beevik/ntp.dep.yml create mode 100644 .licenses/go/golang.org/x/net/bpf.dep.yml create mode 100644 .licenses/go/golang.org/x/net/internal/iana.dep.yml create mode 100644 .licenses/go/golang.org/x/net/internal/socket.dep.yml create mode 100644 .licenses/go/golang.org/x/net/ipv4.dep.yml diff --git a/.licenses/go/github.com/arduino/arduino-cli/arduino.dep.yml b/.licenses/go/github.com/arduino/arduino-cli/arduino.dep.yml index 1b50329e..0b130cee 100644 --- a/.licenses/go/github.com/arduino/arduino-cli/arduino.dep.yml +++ b/.licenses/go/github.com/arduino/arduino-cli/arduino.dep.yml @@ -1,12 +1,12 @@ --- name: github.com/arduino/arduino-cli/arduino -version: v0.0.0-20240927141754-d9dd4ba1ed71 +version: v0.0.0-20250901123057-20dd7c932f59 type: go summary: homepage: https://pkg.go.dev/github.com/arduino/arduino-cli/arduino license: gpl-3.0 licenses: -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/LICENSE.txt +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/LICENSE.txt text: |2 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 @@ -682,7 +682,7 @@ licenses: the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/README.md +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/README.md text: |- Arduino CLI is licensed under the [GPL 3.0] license. diff --git a/.licenses/go/github.com/arduino/arduino-cli/arduino/cores.dep.yml b/.licenses/go/github.com/arduino/arduino-cli/arduino/cores.dep.yml index 4db7455f..8c5d103d 100644 --- a/.licenses/go/github.com/arduino/arduino-cli/arduino/cores.dep.yml +++ b/.licenses/go/github.com/arduino/arduino-cli/arduino/cores.dep.yml @@ -1,12 +1,12 @@ --- name: github.com/arduino/arduino-cli/arduino/cores -version: v0.0.0-20240927141754-d9dd4ba1ed71 +version: v0.0.0-20250901123057-20dd7c932f59 type: go summary: homepage: https://pkg.go.dev/github.com/arduino/arduino-cli/arduino/cores license: gpl-3.0 licenses: -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/LICENSE.txt +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/LICENSE.txt text: |2 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 @@ -682,7 +682,7 @@ licenses: the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/README.md +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/README.md text: |- Arduino CLI is licensed under the [GPL 3.0] license. diff --git a/.licenses/go/github.com/arduino/arduino-cli/arduino/cores/packageindex.dep.yml b/.licenses/go/github.com/arduino/arduino-cli/arduino/cores/packageindex.dep.yml index a1a9ad53..d8fed56b 100644 --- a/.licenses/go/github.com/arduino/arduino-cli/arduino/cores/packageindex.dep.yml +++ b/.licenses/go/github.com/arduino/arduino-cli/arduino/cores/packageindex.dep.yml @@ -1,12 +1,12 @@ --- name: github.com/arduino/arduino-cli/arduino/cores/packageindex -version: v0.0.0-20240927141754-d9dd4ba1ed71 +version: v0.0.0-20250901123057-20dd7c932f59 type: go summary: homepage: https://pkg.go.dev/github.com/arduino/arduino-cli/arduino/cores/packageindex license: gpl-3.0 licenses: -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/LICENSE.txt +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/LICENSE.txt text: |2 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 @@ -682,7 +682,7 @@ licenses: the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/README.md +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/README.md text: |- Arduino CLI is licensed under the [GPL 3.0] license. diff --git a/.licenses/go/github.com/arduino/arduino-cli/arduino/cores/packagemanager.dep.yml b/.licenses/go/github.com/arduino/arduino-cli/arduino/cores/packagemanager.dep.yml index 2a98e9af..a34672ac 100644 --- a/.licenses/go/github.com/arduino/arduino-cli/arduino/cores/packagemanager.dep.yml +++ b/.licenses/go/github.com/arduino/arduino-cli/arduino/cores/packagemanager.dep.yml @@ -1,12 +1,12 @@ --- name: github.com/arduino/arduino-cli/arduino/cores/packagemanager -version: v0.0.0-20240927141754-d9dd4ba1ed71 +version: v0.0.0-20250901123057-20dd7c932f59 type: go summary: homepage: https://pkg.go.dev/github.com/arduino/arduino-cli/arduino/cores/packagemanager license: gpl-3.0 licenses: -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/LICENSE.txt +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/LICENSE.txt text: |2 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 @@ -682,7 +682,7 @@ licenses: the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/README.md +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/README.md text: |- Arduino CLI is licensed under the [GPL 3.0] license. diff --git a/.licenses/go/github.com/arduino/arduino-cli/arduino/discovery.dep.yml b/.licenses/go/github.com/arduino/arduino-cli/arduino/discovery.dep.yml index 7333fe0d..8c434189 100644 --- a/.licenses/go/github.com/arduino/arduino-cli/arduino/discovery.dep.yml +++ b/.licenses/go/github.com/arduino/arduino-cli/arduino/discovery.dep.yml @@ -1,12 +1,12 @@ --- name: github.com/arduino/arduino-cli/arduino/discovery -version: v0.0.0-20240927141754-d9dd4ba1ed71 +version: v0.0.0-20250901123057-20dd7c932f59 type: go summary: homepage: https://pkg.go.dev/github.com/arduino/arduino-cli/arduino/discovery license: gpl-3.0 licenses: -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/LICENSE.txt +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/LICENSE.txt text: |2 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 @@ -682,7 +682,7 @@ licenses: the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/README.md +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/README.md text: |- Arduino CLI is licensed under the [GPL 3.0] license. diff --git a/.licenses/go/github.com/arduino/arduino-cli/arduino/discovery/discoverymanager.dep.yml b/.licenses/go/github.com/arduino/arduino-cli/arduino/discovery/discoverymanager.dep.yml index 4eab991b..79fcf196 100644 --- a/.licenses/go/github.com/arduino/arduino-cli/arduino/discovery/discoverymanager.dep.yml +++ b/.licenses/go/github.com/arduino/arduino-cli/arduino/discovery/discoverymanager.dep.yml @@ -1,12 +1,12 @@ --- name: github.com/arduino/arduino-cli/arduino/discovery/discoverymanager -version: v0.0.0-20240927141754-d9dd4ba1ed71 +version: v0.0.0-20250901123057-20dd7c932f59 type: go summary: homepage: https://pkg.go.dev/github.com/arduino/arduino-cli/arduino/discovery/discoverymanager license: gpl-3.0 licenses: -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/LICENSE.txt +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/LICENSE.txt text: |2 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 @@ -682,7 +682,7 @@ licenses: the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/README.md +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/README.md text: |- Arduino CLI is licensed under the [GPL 3.0] license. diff --git a/.licenses/go/github.com/arduino/arduino-cli/arduino/globals.dep.yml b/.licenses/go/github.com/arduino/arduino-cli/arduino/globals.dep.yml index 384f866f..f9fb5093 100644 --- a/.licenses/go/github.com/arduino/arduino-cli/arduino/globals.dep.yml +++ b/.licenses/go/github.com/arduino/arduino-cli/arduino/globals.dep.yml @@ -1,12 +1,12 @@ --- name: github.com/arduino/arduino-cli/arduino/globals -version: v0.0.0-20240927141754-d9dd4ba1ed71 +version: v0.0.0-20250901123057-20dd7c932f59 type: go summary: homepage: https://pkg.go.dev/github.com/arduino/arduino-cli/arduino/globals license: gpl-3.0 licenses: -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/LICENSE.txt +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/LICENSE.txt text: |2 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 @@ -682,7 +682,7 @@ licenses: the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/README.md +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/README.md text: |- Arduino CLI is licensed under the [GPL 3.0] license. diff --git a/.licenses/go/github.com/arduino/arduino-cli/arduino/httpclient.dep.yml b/.licenses/go/github.com/arduino/arduino-cli/arduino/httpclient.dep.yml index cdb9ba4d..98d8895c 100644 --- a/.licenses/go/github.com/arduino/arduino-cli/arduino/httpclient.dep.yml +++ b/.licenses/go/github.com/arduino/arduino-cli/arduino/httpclient.dep.yml @@ -1,12 +1,12 @@ --- name: github.com/arduino/arduino-cli/arduino/httpclient -version: v0.0.0-20240927141754-d9dd4ba1ed71 +version: v0.0.0-20250901123057-20dd7c932f59 type: go summary: homepage: https://pkg.go.dev/github.com/arduino/arduino-cli/arduino/httpclient license: gpl-3.0 licenses: -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/LICENSE.txt +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/LICENSE.txt text: |2 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 @@ -682,7 +682,7 @@ licenses: the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/README.md +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/README.md text: |- Arduino CLI is licensed under the [GPL 3.0] license. diff --git a/.licenses/go/github.com/arduino/arduino-cli/arduino/libraries.dep.yml b/.licenses/go/github.com/arduino/arduino-cli/arduino/libraries.dep.yml index 6cb8090d..f12eea8b 100644 --- a/.licenses/go/github.com/arduino/arduino-cli/arduino/libraries.dep.yml +++ b/.licenses/go/github.com/arduino/arduino-cli/arduino/libraries.dep.yml @@ -1,12 +1,12 @@ --- name: github.com/arduino/arduino-cli/arduino/libraries -version: v0.0.0-20240927141754-d9dd4ba1ed71 +version: v0.0.0-20250901123057-20dd7c932f59 type: go summary: homepage: https://pkg.go.dev/github.com/arduino/arduino-cli/arduino/libraries license: gpl-3.0 licenses: -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/LICENSE.txt +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/LICENSE.txt text: |2 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 @@ -682,7 +682,7 @@ licenses: the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/README.md +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/README.md text: |- Arduino CLI is licensed under the [GPL 3.0] license. diff --git a/.licenses/go/github.com/arduino/arduino-cli/arduino/libraries/librariesindex.dep.yml b/.licenses/go/github.com/arduino/arduino-cli/arduino/libraries/librariesindex.dep.yml index d1ae1b74..cf177401 100644 --- a/.licenses/go/github.com/arduino/arduino-cli/arduino/libraries/librariesindex.dep.yml +++ b/.licenses/go/github.com/arduino/arduino-cli/arduino/libraries/librariesindex.dep.yml @@ -1,12 +1,12 @@ --- name: github.com/arduino/arduino-cli/arduino/libraries/librariesindex -version: v0.0.0-20240927141754-d9dd4ba1ed71 +version: v0.0.0-20250901123057-20dd7c932f59 type: go summary: homepage: https://pkg.go.dev/github.com/arduino/arduino-cli/arduino/libraries/librariesindex license: gpl-3.0 licenses: -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/LICENSE.txt +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/LICENSE.txt text: |2 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 @@ -682,7 +682,7 @@ licenses: the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/README.md +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/README.md text: |- Arduino CLI is licensed under the [GPL 3.0] license. diff --git a/.licenses/go/github.com/arduino/arduino-cli/arduino/libraries/librariesmanager.dep.yml b/.licenses/go/github.com/arduino/arduino-cli/arduino/libraries/librariesmanager.dep.yml index 1d8119ec..ffcbf7f8 100644 --- a/.licenses/go/github.com/arduino/arduino-cli/arduino/libraries/librariesmanager.dep.yml +++ b/.licenses/go/github.com/arduino/arduino-cli/arduino/libraries/librariesmanager.dep.yml @@ -1,12 +1,12 @@ --- name: github.com/arduino/arduino-cli/arduino/libraries/librariesmanager -version: v0.0.0-20240927141754-d9dd4ba1ed71 +version: v0.0.0-20250901123057-20dd7c932f59 type: go summary: homepage: https://pkg.go.dev/github.com/arduino/arduino-cli/arduino/libraries/librariesmanager license: gpl-3.0 licenses: -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/LICENSE.txt +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/LICENSE.txt text: |2 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 @@ -682,7 +682,7 @@ licenses: the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/README.md +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/README.md text: |- Arduino CLI is licensed under the [GPL 3.0] license. diff --git a/.licenses/go/github.com/arduino/arduino-cli/arduino/resources.dep.yml b/.licenses/go/github.com/arduino/arduino-cli/arduino/resources.dep.yml index 9896b30a..55e64f7c 100644 --- a/.licenses/go/github.com/arduino/arduino-cli/arduino/resources.dep.yml +++ b/.licenses/go/github.com/arduino/arduino-cli/arduino/resources.dep.yml @@ -1,12 +1,12 @@ --- name: github.com/arduino/arduino-cli/arduino/resources -version: v0.0.0-20240927141754-d9dd4ba1ed71 +version: v0.0.0-20250901123057-20dd7c932f59 type: go summary: homepage: https://pkg.go.dev/github.com/arduino/arduino-cli/arduino/resources license: gpl-3.0 licenses: -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/LICENSE.txt +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/LICENSE.txt text: |2 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 @@ -682,7 +682,7 @@ licenses: the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/README.md +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/README.md text: |- Arduino CLI is licensed under the [GPL 3.0] license. diff --git a/.licenses/go/github.com/arduino/arduino-cli/arduino/security.dep.yml b/.licenses/go/github.com/arduino/arduino-cli/arduino/security.dep.yml index ecc024a3..308e9ab8 100644 --- a/.licenses/go/github.com/arduino/arduino-cli/arduino/security.dep.yml +++ b/.licenses/go/github.com/arduino/arduino-cli/arduino/security.dep.yml @@ -1,12 +1,12 @@ --- name: github.com/arduino/arduino-cli/arduino/security -version: v0.0.0-20240927141754-d9dd4ba1ed71 +version: v0.0.0-20250901123057-20dd7c932f59 type: go summary: homepage: https://pkg.go.dev/github.com/arduino/arduino-cli/arduino/security license: gpl-3.0 licenses: -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/LICENSE.txt +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/LICENSE.txt text: |2 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 @@ -682,7 +682,7 @@ licenses: the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/README.md +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/README.md text: |- Arduino CLI is licensed under the [GPL 3.0] license. diff --git a/.licenses/go/github.com/arduino/arduino-cli/arduino/serialutils.dep.yml b/.licenses/go/github.com/arduino/arduino-cli/arduino/serialutils.dep.yml index 203433c7..2f3169c8 100644 --- a/.licenses/go/github.com/arduino/arduino-cli/arduino/serialutils.dep.yml +++ b/.licenses/go/github.com/arduino/arduino-cli/arduino/serialutils.dep.yml @@ -1,12 +1,12 @@ --- name: github.com/arduino/arduino-cli/arduino/serialutils -version: v0.0.0-20240927141754-d9dd4ba1ed71 +version: v0.0.0-20250901123057-20dd7c932f59 type: go summary: homepage: https://pkg.go.dev/github.com/arduino/arduino-cli/arduino/serialutils license: gpl-3.0 licenses: -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/LICENSE.txt +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/LICENSE.txt text: |2 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 @@ -682,7 +682,7 @@ licenses: the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/README.md +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/README.md text: |- Arduino CLI is licensed under the [GPL 3.0] license. diff --git a/.licenses/go/github.com/arduino/arduino-cli/arduino/sketch.dep.yml b/.licenses/go/github.com/arduino/arduino-cli/arduino/sketch.dep.yml index 778d30a7..bdd0aa8d 100644 --- a/.licenses/go/github.com/arduino/arduino-cli/arduino/sketch.dep.yml +++ b/.licenses/go/github.com/arduino/arduino-cli/arduino/sketch.dep.yml @@ -1,12 +1,12 @@ --- name: github.com/arduino/arduino-cli/arduino/sketch -version: v0.0.0-20240927141754-d9dd4ba1ed71 +version: v0.0.0-20250901123057-20dd7c932f59 type: go summary: homepage: https://pkg.go.dev/github.com/arduino/arduino-cli/arduino/sketch license: gpl-3.0 licenses: -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/LICENSE.txt +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/LICENSE.txt text: |2 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 @@ -682,7 +682,7 @@ licenses: the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/README.md +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/README.md text: |- Arduino CLI is licensed under the [GPL 3.0] license. diff --git a/.licenses/go/github.com/arduino/arduino-cli/arduino/utils.dep.yml b/.licenses/go/github.com/arduino/arduino-cli/arduino/utils.dep.yml index 110f64d6..f6af2731 100644 --- a/.licenses/go/github.com/arduino/arduino-cli/arduino/utils.dep.yml +++ b/.licenses/go/github.com/arduino/arduino-cli/arduino/utils.dep.yml @@ -1,12 +1,12 @@ --- name: github.com/arduino/arduino-cli/arduino/utils -version: v0.0.0-20240927141754-d9dd4ba1ed71 +version: v0.0.0-20250901123057-20dd7c932f59 type: go summary: homepage: https://pkg.go.dev/github.com/arduino/arduino-cli/arduino/utils license: gpl-3.0 licenses: -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/LICENSE.txt +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/LICENSE.txt text: |2 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 @@ -682,7 +682,7 @@ licenses: the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/README.md +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/README.md text: |- Arduino CLI is licensed under the [GPL 3.0] license. diff --git a/.licenses/go/github.com/arduino/arduino-cli/cli/errorcodes.dep.yml b/.licenses/go/github.com/arduino/arduino-cli/cli/errorcodes.dep.yml index 8ffd6572..a2231c53 100644 --- a/.licenses/go/github.com/arduino/arduino-cli/cli/errorcodes.dep.yml +++ b/.licenses/go/github.com/arduino/arduino-cli/cli/errorcodes.dep.yml @@ -1,12 +1,12 @@ --- name: github.com/arduino/arduino-cli/cli/errorcodes -version: v0.0.0-20240927141754-d9dd4ba1ed71 +version: v0.0.0-20250901123057-20dd7c932f59 type: go summary: homepage: https://pkg.go.dev/github.com/arduino/arduino-cli/cli/errorcodes license: gpl-3.0 licenses: -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/LICENSE.txt +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/LICENSE.txt text: |2 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 @@ -682,7 +682,7 @@ licenses: the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/README.md +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/README.md text: |- Arduino CLI is licensed under the [GPL 3.0] license. diff --git a/.licenses/go/github.com/arduino/arduino-cli/cli/feedback.dep.yml b/.licenses/go/github.com/arduino/arduino-cli/cli/feedback.dep.yml index 1310719c..b7ad6c1c 100644 --- a/.licenses/go/github.com/arduino/arduino-cli/cli/feedback.dep.yml +++ b/.licenses/go/github.com/arduino/arduino-cli/cli/feedback.dep.yml @@ -1,12 +1,12 @@ --- name: github.com/arduino/arduino-cli/cli/feedback -version: v0.0.0-20240927141754-d9dd4ba1ed71 +version: v0.0.0-20250901123057-20dd7c932f59 type: go summary: homepage: https://pkg.go.dev/github.com/arduino/arduino-cli/cli/feedback license: gpl-3.0 licenses: -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/LICENSE.txt +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/LICENSE.txt text: |2 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 @@ -682,7 +682,7 @@ licenses: the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/README.md +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/README.md text: |- Arduino CLI is licensed under the [GPL 3.0] license. diff --git a/.licenses/go/github.com/arduino/arduino-cli/cli/globals.dep.yml b/.licenses/go/github.com/arduino/arduino-cli/cli/globals.dep.yml index ff66309b..6a05de77 100644 --- a/.licenses/go/github.com/arduino/arduino-cli/cli/globals.dep.yml +++ b/.licenses/go/github.com/arduino/arduino-cli/cli/globals.dep.yml @@ -1,12 +1,12 @@ --- name: github.com/arduino/arduino-cli/cli/globals -version: v0.0.0-20240927141754-d9dd4ba1ed71 +version: v0.0.0-20250901123057-20dd7c932f59 type: go summary: homepage: https://pkg.go.dev/github.com/arduino/arduino-cli/cli/globals license: gpl-3.0 licenses: -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/LICENSE.txt +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/LICENSE.txt text: |2 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 @@ -682,7 +682,7 @@ licenses: the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/README.md +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/README.md text: |- Arduino CLI is licensed under the [GPL 3.0] license. diff --git a/.licenses/go/github.com/arduino/arduino-cli/cli/instance.dep.yml b/.licenses/go/github.com/arduino/arduino-cli/cli/instance.dep.yml index a6d996a5..da28827e 100644 --- a/.licenses/go/github.com/arduino/arduino-cli/cli/instance.dep.yml +++ b/.licenses/go/github.com/arduino/arduino-cli/cli/instance.dep.yml @@ -1,12 +1,12 @@ --- name: github.com/arduino/arduino-cli/cli/instance -version: v0.0.0-20240927141754-d9dd4ba1ed71 +version: v0.0.0-20250901123057-20dd7c932f59 type: go summary: homepage: https://pkg.go.dev/github.com/arduino/arduino-cli/cli/instance license: gpl-3.0 licenses: -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/LICENSE.txt +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/LICENSE.txt text: |2 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 @@ -682,7 +682,7 @@ licenses: the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/README.md +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/README.md text: |- Arduino CLI is licensed under the [GPL 3.0] license. diff --git a/.licenses/go/github.com/arduino/arduino-cli/cli/output.dep.yml b/.licenses/go/github.com/arduino/arduino-cli/cli/output.dep.yml index 53b8e7dc..835ddc68 100644 --- a/.licenses/go/github.com/arduino/arduino-cli/cli/output.dep.yml +++ b/.licenses/go/github.com/arduino/arduino-cli/cli/output.dep.yml @@ -1,12 +1,12 @@ --- name: github.com/arduino/arduino-cli/cli/output -version: v0.0.0-20240927141754-d9dd4ba1ed71 +version: v0.0.0-20250901123057-20dd7c932f59 type: go summary: homepage: https://pkg.go.dev/github.com/arduino/arduino-cli/cli/output license: gpl-3.0 licenses: -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/LICENSE.txt +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/LICENSE.txt text: |2 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 @@ -682,7 +682,7 @@ licenses: the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/README.md +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/README.md text: |- Arduino CLI is licensed under the [GPL 3.0] license. diff --git a/.licenses/go/github.com/arduino/arduino-cli/commands.dep.yml b/.licenses/go/github.com/arduino/arduino-cli/commands.dep.yml index 60b9d7d0..18a5dc4f 100644 --- a/.licenses/go/github.com/arduino/arduino-cli/commands.dep.yml +++ b/.licenses/go/github.com/arduino/arduino-cli/commands.dep.yml @@ -1,12 +1,12 @@ --- name: github.com/arduino/arduino-cli/commands -version: v0.0.0-20240927141754-d9dd4ba1ed71 +version: v0.0.0-20250901123057-20dd7c932f59 type: go summary: homepage: https://pkg.go.dev/github.com/arduino/arduino-cli/commands license: gpl-3.0 licenses: -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/LICENSE.txt +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/LICENSE.txt text: |2 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 @@ -682,7 +682,7 @@ licenses: the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/README.md +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/README.md text: |- Arduino CLI is licensed under the [GPL 3.0] license. diff --git a/.licenses/go/github.com/arduino/arduino-cli/commands/board.dep.yml b/.licenses/go/github.com/arduino/arduino-cli/commands/board.dep.yml index 578a7576..822403ef 100644 --- a/.licenses/go/github.com/arduino/arduino-cli/commands/board.dep.yml +++ b/.licenses/go/github.com/arduino/arduino-cli/commands/board.dep.yml @@ -1,12 +1,12 @@ --- name: github.com/arduino/arduino-cli/commands/board -version: v0.0.0-20240927141754-d9dd4ba1ed71 +version: v0.0.0-20250901123057-20dd7c932f59 type: go summary: homepage: https://pkg.go.dev/github.com/arduino/arduino-cli/commands/board license: gpl-3.0 licenses: -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/LICENSE.txt +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/LICENSE.txt text: |2 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 @@ -682,7 +682,7 @@ licenses: the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/README.md +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/README.md text: |- Arduino CLI is licensed under the [GPL 3.0] license. diff --git a/.licenses/go/github.com/arduino/arduino-cli/commands/upload.dep.yml b/.licenses/go/github.com/arduino/arduino-cli/commands/upload.dep.yml index e6911982..2986961d 100644 --- a/.licenses/go/github.com/arduino/arduino-cli/commands/upload.dep.yml +++ b/.licenses/go/github.com/arduino/arduino-cli/commands/upload.dep.yml @@ -1,12 +1,12 @@ --- name: github.com/arduino/arduino-cli/commands/upload -version: v0.0.0-20240927141754-d9dd4ba1ed71 +version: v0.0.0-20250901123057-20dd7c932f59 type: go summary: homepage: https://pkg.go.dev/github.com/arduino/arduino-cli/commands/upload license: gpl-3.0 licenses: -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/LICENSE.txt +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/LICENSE.txt text: |2 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 @@ -682,7 +682,7 @@ licenses: the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/README.md +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/README.md text: |- Arduino CLI is licensed under the [GPL 3.0] license. diff --git a/.licenses/go/github.com/arduino/arduino-cli/configuration.dep.yml b/.licenses/go/github.com/arduino/arduino-cli/configuration.dep.yml index 1d247959..9b25a6d6 100644 --- a/.licenses/go/github.com/arduino/arduino-cli/configuration.dep.yml +++ b/.licenses/go/github.com/arduino/arduino-cli/configuration.dep.yml @@ -1,12 +1,12 @@ --- name: github.com/arduino/arduino-cli/configuration -version: v0.0.0-20240927141754-d9dd4ba1ed71 +version: v0.0.0-20250901123057-20dd7c932f59 type: go summary: homepage: https://pkg.go.dev/github.com/arduino/arduino-cli/configuration license: gpl-3.0 licenses: -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/LICENSE.txt +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/LICENSE.txt text: |2 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 @@ -682,7 +682,7 @@ licenses: the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/README.md +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/README.md text: |- Arduino CLI is licensed under the [GPL 3.0] license. diff --git a/.licenses/go/github.com/arduino/arduino-cli/executils.dep.yml b/.licenses/go/github.com/arduino/arduino-cli/executils.dep.yml index d480b834..cb2692b0 100644 --- a/.licenses/go/github.com/arduino/arduino-cli/executils.dep.yml +++ b/.licenses/go/github.com/arduino/arduino-cli/executils.dep.yml @@ -1,12 +1,12 @@ --- name: github.com/arduino/arduino-cli/executils -version: v0.0.0-20240927141754-d9dd4ba1ed71 +version: v0.0.0-20250901123057-20dd7c932f59 type: go summary: homepage: https://pkg.go.dev/github.com/arduino/arduino-cli/executils license: gpl-3.0 licenses: -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/LICENSE.txt +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/LICENSE.txt text: |2 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 @@ -682,7 +682,7 @@ licenses: the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/README.md +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/README.md text: |- Arduino CLI is licensed under the [GPL 3.0] license. diff --git a/.licenses/go/github.com/arduino/arduino-cli/i18n.dep.yml b/.licenses/go/github.com/arduino/arduino-cli/i18n.dep.yml index ab465351..1e91f5cb 100644 --- a/.licenses/go/github.com/arduino/arduino-cli/i18n.dep.yml +++ b/.licenses/go/github.com/arduino/arduino-cli/i18n.dep.yml @@ -1,12 +1,12 @@ --- name: github.com/arduino/arduino-cli/i18n -version: v0.0.0-20240927141754-d9dd4ba1ed71 +version: v0.0.0-20250901123057-20dd7c932f59 type: go summary: homepage: https://pkg.go.dev/github.com/arduino/arduino-cli/i18n license: gpl-3.0 licenses: -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/LICENSE.txt +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/LICENSE.txt text: |2 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 diff --git a/.licenses/go/github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1.dep.yml b/.licenses/go/github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1.dep.yml index 30bcbc74..287ac582 100644 --- a/.licenses/go/github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1.dep.yml +++ b/.licenses/go/github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1.dep.yml @@ -1,12 +1,12 @@ --- name: github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1 -version: v0.0.0-20240927141754-d9dd4ba1ed71 +version: v0.0.0-20250901123057-20dd7c932f59 type: go summary: homepage: https://pkg.go.dev/github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1 license: gpl-3.0 licenses: -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/LICENSE.txt +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/LICENSE.txt text: |2 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 @@ -682,7 +682,7 @@ licenses: the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/README.md +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/README.md text: |- Arduino CLI is licensed under the [GPL 3.0] license. diff --git a/.licenses/go/github.com/arduino/arduino-cli/table.dep.yml b/.licenses/go/github.com/arduino/arduino-cli/table.dep.yml index 0bbeaf16..4d8e29a0 100644 --- a/.licenses/go/github.com/arduino/arduino-cli/table.dep.yml +++ b/.licenses/go/github.com/arduino/arduino-cli/table.dep.yml @@ -1,12 +1,12 @@ --- name: github.com/arduino/arduino-cli/table -version: v0.0.0-20240927141754-d9dd4ba1ed71 +version: v0.0.0-20250901123057-20dd7c932f59 type: go summary: homepage: https://pkg.go.dev/github.com/arduino/arduino-cli/table license: gpl-3.0 licenses: -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/LICENSE.txt +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/LICENSE.txt text: |2 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 @@ -682,7 +682,7 @@ licenses: the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/README.md +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/README.md text: |- Arduino CLI is licensed under the [GPL 3.0] license. diff --git a/.licenses/go/github.com/arduino/arduino-cli/version.dep.yml b/.licenses/go/github.com/arduino/arduino-cli/version.dep.yml index b9a1b664..7f1e928b 100644 --- a/.licenses/go/github.com/arduino/arduino-cli/version.dep.yml +++ b/.licenses/go/github.com/arduino/arduino-cli/version.dep.yml @@ -1,12 +1,12 @@ --- name: github.com/arduino/arduino-cli/version -version: v0.0.0-20240927141754-d9dd4ba1ed71 +version: v0.0.0-20250901123057-20dd7c932f59 type: go summary: homepage: https://pkg.go.dev/github.com/arduino/arduino-cli/version license: gpl-3.0 licenses: -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/LICENSE.txt +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/LICENSE.txt text: |2 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 @@ -682,7 +682,7 @@ licenses: the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . -- sources: arduino-cli@v0.0.0-20240927141754-d9dd4ba1ed71/README.md +- sources: arduino-cli@v0.0.0-20250901123057-20dd7c932f59/README.md text: |- Arduino CLI is licensed under the [GPL 3.0] license. diff --git a/.licenses/go/github.com/beevik/ntp.dep.yml b/.licenses/go/github.com/beevik/ntp.dep.yml new file mode 100644 index 00000000..951e20d6 --- /dev/null +++ b/.licenses/go/github.com/beevik/ntp.dep.yml @@ -0,0 +1,36 @@ +--- +name: github.com/beevik/ntp +version: v1.4.3 +type: go +summary: Package ntp provides an implementation of a Simple NTP (SNTP) client capable + of querying the current time from a remote NTP server. +homepage: https://pkg.go.dev/github.com/beevik/ntp +license: bsd-2-clause +licenses: +- sources: LICENSE + text: | + Copyright © 2015-2023 Brett Vickers. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDER ``AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +notices: [] diff --git a/.licenses/go/go.bug.st/relaxed-semver.dep.yml b/.licenses/go/go.bug.st/relaxed-semver.dep.yml index bc044af9..90ec5ac2 100644 --- a/.licenses/go/go.bug.st/relaxed-semver.dep.yml +++ b/.licenses/go/go.bug.st/relaxed-semver.dep.yml @@ -1,6 +1,6 @@ --- name: go.bug.st/relaxed-semver -version: v0.9.0 +version: v0.10.1 type: go summary: homepage: https://pkg.go.dev/go.bug.st/relaxed-semver diff --git a/.licenses/go/golang.org/x/crypto/blowfish.dep.yml b/.licenses/go/golang.org/x/crypto/blowfish.dep.yml index 449f8662..4f682e0d 100644 --- a/.licenses/go/golang.org/x/crypto/blowfish.dep.yml +++ b/.licenses/go/golang.org/x/crypto/blowfish.dep.yml @@ -1,12 +1,12 @@ --- name: golang.org/x/crypto/blowfish -version: v0.18.0 +version: v0.23.0 type: go summary: Package blowfish implements Bruce Schneier's Blowfish encryption algorithm. homepage: https://pkg.go.dev/golang.org/x/crypto/blowfish license: bsd-3-clause licenses: -- sources: crypto@v0.18.0/LICENSE +- sources: crypto@v0.23.0/LICENSE text: | Copyright (c) 2009 The Go Authors. All rights reserved. @@ -35,7 +35,7 @@ licenses: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- sources: crypto@v0.18.0/PATENTS +- sources: crypto@v0.23.0/PATENTS text: | Additional IP Rights Grant (Patents) diff --git a/.licenses/go/golang.org/x/crypto/cast5.dep.yml b/.licenses/go/golang.org/x/crypto/cast5.dep.yml index bcdeb025..369aae2e 100644 --- a/.licenses/go/golang.org/x/crypto/cast5.dep.yml +++ b/.licenses/go/golang.org/x/crypto/cast5.dep.yml @@ -1,12 +1,12 @@ --- name: golang.org/x/crypto/cast5 -version: v0.18.0 +version: v0.23.0 type: go summary: Package cast5 implements CAST5, as defined in RFC 2144. homepage: https://pkg.go.dev/golang.org/x/crypto/cast5 license: bsd-3-clause licenses: -- sources: crypto@v0.18.0/LICENSE +- sources: crypto@v0.23.0/LICENSE text: | Copyright (c) 2009 The Go Authors. All rights reserved. @@ -35,7 +35,7 @@ licenses: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- sources: crypto@v0.18.0/PATENTS +- sources: crypto@v0.23.0/PATENTS text: | Additional IP Rights Grant (Patents) diff --git a/.licenses/go/golang.org/x/crypto/curve25519.dep.yml b/.licenses/go/golang.org/x/crypto/curve25519.dep.yml index 9565db0c..27ff49f5 100644 --- a/.licenses/go/golang.org/x/crypto/curve25519.dep.yml +++ b/.licenses/go/golang.org/x/crypto/curve25519.dep.yml @@ -1,13 +1,13 @@ --- name: golang.org/x/crypto/curve25519 -version: v0.18.0 +version: v0.23.0 type: go summary: Package curve25519 provides an implementation of the X25519 function, which performs scalar multiplication on the elliptic curve known as Curve25519. homepage: https://pkg.go.dev/golang.org/x/crypto/curve25519 license: bsd-3-clause licenses: -- sources: crypto@v0.18.0/LICENSE +- sources: crypto@v0.23.0/LICENSE text: | Copyright (c) 2009 The Go Authors. All rights reserved. @@ -36,7 +36,7 @@ licenses: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- sources: crypto@v0.18.0/PATENTS +- sources: crypto@v0.23.0/PATENTS text: | Additional IP Rights Grant (Patents) diff --git a/.licenses/go/golang.org/x/crypto/openpgp.dep.yml b/.licenses/go/golang.org/x/crypto/openpgp.dep.yml index af05f837..4ba5db06 100644 --- a/.licenses/go/golang.org/x/crypto/openpgp.dep.yml +++ b/.licenses/go/golang.org/x/crypto/openpgp.dep.yml @@ -1,12 +1,12 @@ --- name: golang.org/x/crypto/openpgp -version: v0.18.0 +version: v0.23.0 type: go summary: Package openpgp implements high level operations on OpenPGP messages. homepage: https://pkg.go.dev/golang.org/x/crypto/openpgp license: bsd-3-clause licenses: -- sources: crypto@v0.18.0/LICENSE +- sources: crypto@v0.23.0/LICENSE text: | Copyright (c) 2009 The Go Authors. All rights reserved. @@ -35,7 +35,7 @@ licenses: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- sources: crypto@v0.18.0/PATENTS +- sources: crypto@v0.23.0/PATENTS text: | Additional IP Rights Grant (Patents) diff --git a/.licenses/go/golang.org/x/crypto/openpgp/armor.dep.yml b/.licenses/go/golang.org/x/crypto/openpgp/armor.dep.yml index 0dc3804c..7784e1ad 100644 --- a/.licenses/go/golang.org/x/crypto/openpgp/armor.dep.yml +++ b/.licenses/go/golang.org/x/crypto/openpgp/armor.dep.yml @@ -1,12 +1,12 @@ --- name: golang.org/x/crypto/openpgp/armor -version: v0.18.0 +version: v0.23.0 type: go summary: Package armor implements OpenPGP ASCII Armor, see RFC 4880. homepage: https://pkg.go.dev/golang.org/x/crypto/openpgp/armor license: bsd-3-clause licenses: -- sources: crypto@v0.18.0/LICENSE +- sources: crypto@v0.23.0/LICENSE text: | Copyright (c) 2009 The Go Authors. All rights reserved. @@ -35,7 +35,7 @@ licenses: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- sources: crypto@v0.18.0/PATENTS +- sources: crypto@v0.23.0/PATENTS text: | Additional IP Rights Grant (Patents) diff --git a/.licenses/go/golang.org/x/crypto/openpgp/elgamal.dep.yml b/.licenses/go/golang.org/x/crypto/openpgp/elgamal.dep.yml index e8bdefb6..dc98ffd8 100644 --- a/.licenses/go/golang.org/x/crypto/openpgp/elgamal.dep.yml +++ b/.licenses/go/golang.org/x/crypto/openpgp/elgamal.dep.yml @@ -1,6 +1,6 @@ --- name: golang.org/x/crypto/openpgp/elgamal -version: v0.18.0 +version: v0.23.0 type: go summary: Package elgamal implements ElGamal encryption, suitable for OpenPGP, as specified in "A Public-Key Cryptosystem and a Signature Scheme Based on Discrete Logarithms," @@ -8,7 +8,7 @@ summary: Package elgamal implements ElGamal encryption, suitable for OpenPGP, as homepage: https://pkg.go.dev/golang.org/x/crypto/openpgp/elgamal license: bsd-3-clause licenses: -- sources: crypto@v0.18.0/LICENSE +- sources: crypto@v0.23.0/LICENSE text: | Copyright (c) 2009 The Go Authors. All rights reserved. @@ -37,7 +37,7 @@ licenses: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- sources: crypto@v0.18.0/PATENTS +- sources: crypto@v0.23.0/PATENTS text: | Additional IP Rights Grant (Patents) diff --git a/.licenses/go/golang.org/x/crypto/openpgp/errors.dep.yml b/.licenses/go/golang.org/x/crypto/openpgp/errors.dep.yml index 38fd876f..484e001b 100644 --- a/.licenses/go/golang.org/x/crypto/openpgp/errors.dep.yml +++ b/.licenses/go/golang.org/x/crypto/openpgp/errors.dep.yml @@ -1,12 +1,12 @@ --- name: golang.org/x/crypto/openpgp/errors -version: v0.18.0 +version: v0.23.0 type: go summary: Package errors contains common error types for the OpenPGP packages. homepage: https://pkg.go.dev/golang.org/x/crypto/openpgp/errors license: bsd-3-clause licenses: -- sources: crypto@v0.18.0/LICENSE +- sources: crypto@v0.23.0/LICENSE text: | Copyright (c) 2009 The Go Authors. All rights reserved. @@ -35,7 +35,7 @@ licenses: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- sources: crypto@v0.18.0/PATENTS +- sources: crypto@v0.23.0/PATENTS text: | Additional IP Rights Grant (Patents) diff --git a/.licenses/go/golang.org/x/crypto/openpgp/packet.dep.yml b/.licenses/go/golang.org/x/crypto/openpgp/packet.dep.yml index 48b8a419..eb6d99c1 100644 --- a/.licenses/go/golang.org/x/crypto/openpgp/packet.dep.yml +++ b/.licenses/go/golang.org/x/crypto/openpgp/packet.dep.yml @@ -1,13 +1,13 @@ --- name: golang.org/x/crypto/openpgp/packet -version: v0.18.0 +version: v0.23.0 type: go summary: Package packet implements parsing and serialization of OpenPGP packets, as specified in RFC 4880. homepage: https://pkg.go.dev/golang.org/x/crypto/openpgp/packet license: bsd-3-clause licenses: -- sources: crypto@v0.18.0/LICENSE +- sources: crypto@v0.23.0/LICENSE text: | Copyright (c) 2009 The Go Authors. All rights reserved. @@ -36,7 +36,7 @@ licenses: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- sources: crypto@v0.18.0/PATENTS +- sources: crypto@v0.23.0/PATENTS text: | Additional IP Rights Grant (Patents) diff --git a/.licenses/go/golang.org/x/crypto/openpgp/s2k.dep.yml b/.licenses/go/golang.org/x/crypto/openpgp/s2k.dep.yml index c178e683..cc460fa6 100644 --- a/.licenses/go/golang.org/x/crypto/openpgp/s2k.dep.yml +++ b/.licenses/go/golang.org/x/crypto/openpgp/s2k.dep.yml @@ -1,13 +1,13 @@ --- name: golang.org/x/crypto/openpgp/s2k -version: v0.18.0 +version: v0.23.0 type: go summary: Package s2k implements the various OpenPGP string-to-key transforms as specified in RFC 4800 section 3.7.1. homepage: https://pkg.go.dev/golang.org/x/crypto/openpgp/s2k license: bsd-3-clause licenses: -- sources: crypto@v0.18.0/LICENSE +- sources: crypto@v0.23.0/LICENSE text: | Copyright (c) 2009 The Go Authors. All rights reserved. @@ -36,7 +36,7 @@ licenses: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- sources: crypto@v0.18.0/PATENTS +- sources: crypto@v0.23.0/PATENTS text: | Additional IP Rights Grant (Patents) diff --git a/.licenses/go/golang.org/x/crypto/ssh.dep.yml b/.licenses/go/golang.org/x/crypto/ssh.dep.yml index b2e4ec28..2c39eb21 100644 --- a/.licenses/go/golang.org/x/crypto/ssh.dep.yml +++ b/.licenses/go/golang.org/x/crypto/ssh.dep.yml @@ -1,12 +1,12 @@ --- name: golang.org/x/crypto/ssh -version: v0.18.0 +version: v0.23.0 type: go summary: Package ssh implements an SSH client and server. homepage: https://pkg.go.dev/golang.org/x/crypto/ssh license: bsd-3-clause licenses: -- sources: crypto@v0.18.0/LICENSE +- sources: crypto@v0.23.0/LICENSE text: | Copyright (c) 2009 The Go Authors. All rights reserved. @@ -35,7 +35,7 @@ licenses: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- sources: crypto@v0.18.0/PATENTS +- sources: crypto@v0.23.0/PATENTS text: | Additional IP Rights Grant (Patents) diff --git a/.licenses/go/golang.org/x/crypto/ssh/agent.dep.yml b/.licenses/go/golang.org/x/crypto/ssh/agent.dep.yml index b4f34666..85f57262 100644 --- a/.licenses/go/golang.org/x/crypto/ssh/agent.dep.yml +++ b/.licenses/go/golang.org/x/crypto/ssh/agent.dep.yml @@ -1,13 +1,13 @@ --- name: golang.org/x/crypto/ssh/agent -version: v0.18.0 +version: v0.23.0 type: go summary: Package agent implements the ssh-agent protocol, and provides both a client and a server. homepage: https://pkg.go.dev/golang.org/x/crypto/ssh/agent license: bsd-3-clause licenses: -- sources: crypto@v0.18.0/LICENSE +- sources: crypto@v0.23.0/LICENSE text: | Copyright (c) 2009 The Go Authors. All rights reserved. @@ -36,7 +36,7 @@ licenses: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- sources: crypto@v0.18.0/PATENTS +- sources: crypto@v0.23.0/PATENTS text: | Additional IP Rights Grant (Patents) diff --git a/.licenses/go/golang.org/x/crypto/ssh/internal/bcrypt_pbkdf.dep.yml b/.licenses/go/golang.org/x/crypto/ssh/internal/bcrypt_pbkdf.dep.yml index e62bee50..38e497ed 100644 --- a/.licenses/go/golang.org/x/crypto/ssh/internal/bcrypt_pbkdf.dep.yml +++ b/.licenses/go/golang.org/x/crypto/ssh/internal/bcrypt_pbkdf.dep.yml @@ -1,12 +1,12 @@ --- name: golang.org/x/crypto/ssh/internal/bcrypt_pbkdf -version: v0.18.0 +version: v0.23.0 type: go summary: Package bcrypt_pbkdf implements bcrypt_pbkdf(3) from OpenBSD. homepage: https://pkg.go.dev/golang.org/x/crypto/ssh/internal/bcrypt_pbkdf license: bsd-3-clause licenses: -- sources: crypto@v0.18.0/LICENSE +- sources: crypto@v0.23.0/LICENSE text: | Copyright (c) 2009 The Go Authors. All rights reserved. @@ -35,7 +35,7 @@ licenses: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- sources: crypto@v0.18.0/PATENTS +- sources: crypto@v0.23.0/PATENTS text: | Additional IP Rights Grant (Patents) diff --git a/.licenses/go/golang.org/x/crypto/ssh/knownhosts.dep.yml b/.licenses/go/golang.org/x/crypto/ssh/knownhosts.dep.yml index c8144dfa..777f3cfc 100644 --- a/.licenses/go/golang.org/x/crypto/ssh/knownhosts.dep.yml +++ b/.licenses/go/golang.org/x/crypto/ssh/knownhosts.dep.yml @@ -1,6 +1,6 @@ --- name: golang.org/x/crypto/ssh/knownhosts -version: v0.18.0 +version: v0.23.0 type: go summary: Package knownhosts implements a parser for the OpenSSH known_hosts host key database, and provides utility functions for writing OpenSSH compliant known_hosts @@ -8,7 +8,7 @@ summary: Package knownhosts implements a parser for the OpenSSH known_hosts host homepage: https://pkg.go.dev/golang.org/x/crypto/ssh/knownhosts license: bsd-3-clause licenses: -- sources: crypto@v0.18.0/LICENSE +- sources: crypto@v0.23.0/LICENSE text: | Copyright (c) 2009 The Go Authors. All rights reserved. @@ -37,7 +37,7 @@ licenses: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- sources: crypto@v0.18.0/PATENTS +- sources: crypto@v0.23.0/PATENTS text: | Additional IP Rights Grant (Patents) diff --git a/.licenses/go/golang.org/x/net/bpf.dep.yml b/.licenses/go/golang.org/x/net/bpf.dep.yml new file mode 100644 index 00000000..e75ae79d --- /dev/null +++ b/.licenses/go/golang.org/x/net/bpf.dep.yml @@ -0,0 +1,63 @@ +--- +name: golang.org/x/net/bpf +version: v0.25.0 +type: go +summary: Package bpf implements marshaling and unmarshaling of programs for the Berkeley + Packet Filter virtual machine, and provides a Go implementation of the virtual machine. +homepage: https://pkg.go.dev/golang.org/x/net/bpf +license: other +licenses: +- sources: net@v0.25.0/LICENSE + text: | + Copyright (c) 2009 The Go Authors. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- sources: net@v0.25.0/PATENTS + text: | + Additional IP Rights Grant (Patents) + + "This implementation" means the copyrightable works distributed by + Google as part of the Go project. + + Google hereby grants to You a perpetual, worldwide, non-exclusive, + no-charge, royalty-free, irrevocable (except as stated in this section) + patent license to make, have made, use, offer to sell, sell, import, + transfer and otherwise run, modify and propagate the contents of this + implementation of Go, where such license applies only to those patent + claims, both currently owned or controlled by Google and acquired in + the future, licensable by Google that are necessarily infringed by this + implementation of Go. This grant does not include claims that would be + infringed only as a consequence of further modification of this + implementation. If you or your agent or exclusive licensee institute or + order or agree to the institution of patent litigation against any + entity (including a cross-claim or counterclaim in a lawsuit) alleging + that this implementation of Go or any code incorporated within this + implementation of Go constitutes direct or contributory patent + infringement, or inducement of patent infringement, then any patent + rights granted to you under this License for this implementation of Go + shall terminate as of the date such litigation is filed. +notices: [] diff --git a/.licenses/go/golang.org/x/net/context.dep.yml b/.licenses/go/golang.org/x/net/context.dep.yml index 3a5b464d..5ce2b786 100644 --- a/.licenses/go/golang.org/x/net/context.dep.yml +++ b/.licenses/go/golang.org/x/net/context.dep.yml @@ -1,13 +1,13 @@ --- name: golang.org/x/net/context -version: v0.20.0 +version: v0.25.0 type: go summary: Package context defines the Context type, which carries deadlines, cancelation signals, and other request-scoped values across API boundaries and between processes. homepage: https://pkg.go.dev/golang.org/x/net/context license: bsd-3-clause licenses: -- sources: net@v0.20.0/LICENSE +- sources: net@v0.25.0/LICENSE text: | Copyright (c) 2009 The Go Authors. All rights reserved. @@ -36,7 +36,7 @@ licenses: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- sources: net@v0.20.0/PATENTS +- sources: net@v0.25.0/PATENTS text: | Additional IP Rights Grant (Patents) diff --git a/.licenses/go/golang.org/x/net/http2.dep.yml b/.licenses/go/golang.org/x/net/http2.dep.yml index 7337b512..4e442b81 100644 --- a/.licenses/go/golang.org/x/net/http2.dep.yml +++ b/.licenses/go/golang.org/x/net/http2.dep.yml @@ -1,12 +1,12 @@ --- name: golang.org/x/net/http2 -version: v0.20.0 +version: v0.25.0 type: go summary: Package http2 implements the HTTP/2 protocol. homepage: https://pkg.go.dev/golang.org/x/net/http2 license: bsd-3-clause licenses: -- sources: net@v0.20.0/LICENSE +- sources: net@v0.25.0/LICENSE text: | Copyright (c) 2009 The Go Authors. All rights reserved. @@ -35,7 +35,7 @@ licenses: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- sources: net@v0.20.0/PATENTS +- sources: net@v0.25.0/PATENTS text: | Additional IP Rights Grant (Patents) diff --git a/.licenses/go/golang.org/x/net/internal/iana.dep.yml b/.licenses/go/golang.org/x/net/internal/iana.dep.yml new file mode 100644 index 00000000..3be2feba --- /dev/null +++ b/.licenses/go/golang.org/x/net/internal/iana.dep.yml @@ -0,0 +1,63 @@ +--- +name: golang.org/x/net/internal/iana +version: v0.25.0 +type: go +summary: Package iana provides protocol number resources managed by the Internet Assigned + Numbers Authority (IANA). +homepage: https://pkg.go.dev/golang.org/x/net/internal/iana +license: other +licenses: +- sources: net@v0.25.0/LICENSE + text: | + Copyright (c) 2009 The Go Authors. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- sources: net@v0.25.0/PATENTS + text: | + Additional IP Rights Grant (Patents) + + "This implementation" means the copyrightable works distributed by + Google as part of the Go project. + + Google hereby grants to You a perpetual, worldwide, non-exclusive, + no-charge, royalty-free, irrevocable (except as stated in this section) + patent license to make, have made, use, offer to sell, sell, import, + transfer and otherwise run, modify and propagate the contents of this + implementation of Go, where such license applies only to those patent + claims, both currently owned or controlled by Google and acquired in + the future, licensable by Google that are necessarily infringed by this + implementation of Go. This grant does not include claims that would be + infringed only as a consequence of further modification of this + implementation. If you or your agent or exclusive licensee institute or + order or agree to the institution of patent litigation against any + entity (including a cross-claim or counterclaim in a lawsuit) alleging + that this implementation of Go or any code incorporated within this + implementation of Go constitutes direct or contributory patent + infringement, or inducement of patent infringement, then any patent + rights granted to you under this License for this implementation of Go + shall terminate as of the date such litigation is filed. +notices: [] diff --git a/.licenses/go/golang.org/x/net/internal/socket.dep.yml b/.licenses/go/golang.org/x/net/internal/socket.dep.yml new file mode 100644 index 00000000..bdcec430 --- /dev/null +++ b/.licenses/go/golang.org/x/net/internal/socket.dep.yml @@ -0,0 +1,62 @@ +--- +name: golang.org/x/net/internal/socket +version: v0.25.0 +type: go +summary: Package socket provides a portable interface for socket system calls. +homepage: https://pkg.go.dev/golang.org/x/net/internal/socket +license: other +licenses: +- sources: net@v0.25.0/LICENSE + text: | + Copyright (c) 2009 The Go Authors. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- sources: net@v0.25.0/PATENTS + text: | + Additional IP Rights Grant (Patents) + + "This implementation" means the copyrightable works distributed by + Google as part of the Go project. + + Google hereby grants to You a perpetual, worldwide, non-exclusive, + no-charge, royalty-free, irrevocable (except as stated in this section) + patent license to make, have made, use, offer to sell, sell, import, + transfer and otherwise run, modify and propagate the contents of this + implementation of Go, where such license applies only to those patent + claims, both currently owned or controlled by Google and acquired in + the future, licensable by Google that are necessarily infringed by this + implementation of Go. This grant does not include claims that would be + infringed only as a consequence of further modification of this + implementation. If you or your agent or exclusive licensee institute or + order or agree to the institution of patent litigation against any + entity (including a cross-claim or counterclaim in a lawsuit) alleging + that this implementation of Go or any code incorporated within this + implementation of Go constitutes direct or contributory patent + infringement, or inducement of patent infringement, then any patent + rights granted to you under this License for this implementation of Go + shall terminate as of the date such litigation is filed. +notices: [] diff --git a/.licenses/go/golang.org/x/net/internal/socks.dep.yml b/.licenses/go/golang.org/x/net/internal/socks.dep.yml index c0776014..d87d267f 100644 --- a/.licenses/go/golang.org/x/net/internal/socks.dep.yml +++ b/.licenses/go/golang.org/x/net/internal/socks.dep.yml @@ -1,12 +1,12 @@ --- name: golang.org/x/net/internal/socks -version: v0.20.0 +version: v0.25.0 type: go summary: Package socks provides a SOCKS version 5 client implementation. homepage: https://pkg.go.dev/golang.org/x/net/internal/socks license: bsd-3-clause licenses: -- sources: net@v0.20.0/LICENSE +- sources: net@v0.25.0/LICENSE text: | Copyright (c) 2009 The Go Authors. All rights reserved. @@ -35,7 +35,7 @@ licenses: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- sources: net@v0.20.0/PATENTS +- sources: net@v0.25.0/PATENTS text: | Additional IP Rights Grant (Patents) diff --git a/.licenses/go/golang.org/x/net/internal/timeseries.dep.yml b/.licenses/go/golang.org/x/net/internal/timeseries.dep.yml index a612a972..6701aa7f 100644 --- a/.licenses/go/golang.org/x/net/internal/timeseries.dep.yml +++ b/.licenses/go/golang.org/x/net/internal/timeseries.dep.yml @@ -1,12 +1,12 @@ --- name: golang.org/x/net/internal/timeseries -version: v0.20.0 +version: v0.25.0 type: go summary: Package timeseries implements a time series structure for stats collection. homepage: https://pkg.go.dev/golang.org/x/net/internal/timeseries license: bsd-3-clause licenses: -- sources: net@v0.20.0/LICENSE +- sources: net@v0.25.0/LICENSE text: | Copyright (c) 2009 The Go Authors. All rights reserved. @@ -35,7 +35,7 @@ licenses: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- sources: net@v0.20.0/PATENTS +- sources: net@v0.25.0/PATENTS text: | Additional IP Rights Grant (Patents) diff --git a/.licenses/go/golang.org/x/net/ipv4.dep.yml b/.licenses/go/golang.org/x/net/ipv4.dep.yml new file mode 100644 index 00000000..34f6bc89 --- /dev/null +++ b/.licenses/go/golang.org/x/net/ipv4.dep.yml @@ -0,0 +1,63 @@ +--- +name: golang.org/x/net/ipv4 +version: v0.25.0 +type: go +summary: Package ipv4 implements IP-level socket options for the Internet Protocol + version 4. +homepage: https://pkg.go.dev/golang.org/x/net/ipv4 +license: other +licenses: +- sources: net@v0.25.0/LICENSE + text: | + Copyright (c) 2009 The Go Authors. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- sources: net@v0.25.0/PATENTS + text: | + Additional IP Rights Grant (Patents) + + "This implementation" means the copyrightable works distributed by + Google as part of the Go project. + + Google hereby grants to You a perpetual, worldwide, non-exclusive, + no-charge, royalty-free, irrevocable (except as stated in this section) + patent license to make, have made, use, offer to sell, sell, import, + transfer and otherwise run, modify and propagate the contents of this + implementation of Go, where such license applies only to those patent + claims, both currently owned or controlled by Google and acquired in + the future, licensable by Google that are necessarily infringed by this + implementation of Go. This grant does not include claims that would be + infringed only as a consequence of further modification of this + implementation. If you or your agent or exclusive licensee institute or + order or agree to the institution of patent litigation against any + entity (including a cross-claim or counterclaim in a lawsuit) alleging + that this implementation of Go or any code incorporated within this + implementation of Go constitutes direct or contributory patent + infringement, or inducement of patent infringement, then any patent + rights granted to you under this License for this implementation of Go + shall terminate as of the date such litigation is filed. +notices: [] diff --git a/.licenses/go/golang.org/x/net/proxy.dep.yml b/.licenses/go/golang.org/x/net/proxy.dep.yml index 483ff363..4d60ef78 100644 --- a/.licenses/go/golang.org/x/net/proxy.dep.yml +++ b/.licenses/go/golang.org/x/net/proxy.dep.yml @@ -1,13 +1,13 @@ --- name: golang.org/x/net/proxy -version: v0.20.0 +version: v0.25.0 type: go summary: Package proxy provides support for a variety of protocols to proxy network data. homepage: https://pkg.go.dev/golang.org/x/net/proxy license: bsd-3-clause licenses: -- sources: net@v0.20.0/LICENSE +- sources: net@v0.25.0/LICENSE text: | Copyright (c) 2009 The Go Authors. All rights reserved. @@ -36,7 +36,7 @@ licenses: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- sources: net@v0.20.0/PATENTS +- sources: net@v0.25.0/PATENTS text: | Additional IP Rights Grant (Patents) diff --git a/.licenses/go/golang.org/x/net/trace.dep.yml b/.licenses/go/golang.org/x/net/trace.dep.yml index 7d486480..94ae6214 100644 --- a/.licenses/go/golang.org/x/net/trace.dep.yml +++ b/.licenses/go/golang.org/x/net/trace.dep.yml @@ -1,12 +1,12 @@ --- name: golang.org/x/net/trace -version: v0.20.0 +version: v0.25.0 type: go summary: Package trace implements tracing of requests and long-lived objects. homepage: https://pkg.go.dev/golang.org/x/net/trace license: bsd-3-clause licenses: -- sources: net@v0.20.0/LICENSE +- sources: net@v0.25.0/LICENSE text: | Copyright (c) 2009 The Go Authors. All rights reserved. @@ -35,7 +35,7 @@ licenses: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- sources: net@v0.20.0/PATENTS +- sources: net@v0.25.0/PATENTS text: | Additional IP Rights Grant (Patents) diff --git a/.licenses/go/golang.org/x/sys/unix.dep.yml b/.licenses/go/golang.org/x/sys/unix.dep.yml index e04edef8..8c6dd955 100644 --- a/.licenses/go/golang.org/x/sys/unix.dep.yml +++ b/.licenses/go/golang.org/x/sys/unix.dep.yml @@ -1,12 +1,12 @@ --- name: golang.org/x/sys/unix -version: v0.16.0 +version: v0.20.0 type: go summary: Package unix contains an interface to the low-level operating system primitives. homepage: https://pkg.go.dev/golang.org/x/sys/unix license: bsd-3-clause licenses: -- sources: sys@v0.16.0/LICENSE +- sources: sys@v0.20.0/LICENSE text: | Copyright (c) 2009 The Go Authors. All rights reserved. @@ -35,7 +35,7 @@ licenses: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- sources: sys@v0.16.0/PATENTS +- sources: sys@v0.20.0/PATENTS text: | Additional IP Rights Grant (Patents) diff --git a/.licenses/go/golang.org/x/text/runes.dep.yml b/.licenses/go/golang.org/x/text/runes.dep.yml index baa52fe7..aec13555 100644 --- a/.licenses/go/golang.org/x/text/runes.dep.yml +++ b/.licenses/go/golang.org/x/text/runes.dep.yml @@ -1,12 +1,12 @@ --- name: golang.org/x/text/runes -version: v0.14.0 +version: v0.15.0 type: go summary: Package runes provide transforms for UTF-8 encoded text. homepage: https://pkg.go.dev/golang.org/x/text/runes license: bsd-3-clause licenses: -- sources: text@v0.14.0/LICENSE +- sources: text@v0.15.0/LICENSE text: | Copyright (c) 2009 The Go Authors. All rights reserved. @@ -35,7 +35,7 @@ licenses: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- sources: text@v0.14.0/PATENTS +- sources: text@v0.15.0/PATENTS text: | Additional IP Rights Grant (Patents) From a9c9b8bcec0ada152c14a9f409f6f2d03e408fad Mon Sep 17 00:00:00 2001 From: fabik111 Date: Tue, 2 Sep 2025 13:36:49 +0200 Subject: [PATCH 26/27] accept new licenses --- .licensed.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.licensed.yml b/.licensed.yml index 25d5cda8..9ff10357 100644 --- a/.licensed.yml +++ b/.licensed.yml @@ -4,6 +4,10 @@ reviewed: - golang.org/x/crypto/curve25519/internal/field - golang.org/x/crypto/internal/poly1305 - golang.org/x/crypto/curve25519 + - golang.org/x/net/bpf + - golang.org/x/net/internal/iana + - golang.org/x/net/internal/socket + - golang.org/x/net/ipv4 - google.golang.org/protobuf/encoding/protojson - google.golang.org/protobuf/internal/encoding/json - github.com/klauspost/compress From ecef7cc7a72d3bc9d24104f8b4440456f6d57e5b Mon Sep 17 00:00:00 2001 From: fabik111 Date: Tue, 9 Sep 2025 15:53:05 +0200 Subject: [PATCH 27/27] refactor getToken function --- internal/iot-api-raw/client.go | 16 ++-------------- internal/iot/token.go | 11 +++++++++++ internal/provisioning-api/client.go | 20 ++++---------------- 3 files changed, 17 insertions(+), 30 deletions(-) diff --git a/internal/iot-api-raw/client.go b/internal/iot-api-raw/client.go index 70959955..2565cee5 100644 --- a/internal/iot-api-raw/client.go +++ b/internal/iot-api-raw/client.go @@ -7,7 +7,6 @@ import ( "fmt" "io" "net/http" - "strings" "github.com/arduino/arduino-cloud-cli/config" "github.com/arduino/arduino-cloud-cli/internal/iot" @@ -50,20 +49,9 @@ func (c *IoTApiRawClient) performRequest(endpoint, method, token string, body io return res, nil } -func (c *IoTApiRawClient) getToken() (*oauth2.Token, error) { - token, err := c.src.Token() - if err != nil { - if strings.Contains(err.Error(), "401") { - return nil, errors.New("wrong credentials") - } - return nil, fmt.Errorf("cannot retrieve a valid token: %w", err) - } - return token, nil -} - func (c *IoTApiRawClient) GetBoardsDetail() (*BoardTypeList, error) { endpoint := c.host + "/iot/v1/supported/devices" - token, err := c.getToken() + token, err := iot.GetToken(c.src) if err != nil { return nil, err } @@ -116,7 +104,7 @@ func (c *IoTApiRawClient) GetBoardDetailByFQBN(fqbn string) (*BoardType, error) func (c *IoTApiRawClient) DownloadProvisioningV2Sketch(fqbn string, path *paths.Path, filename *string) (string, error) { endpoint := c.host + "/iot/v2/binaries/provisioningv2?fqbn=" + fqbn - token, err := c.getToken() + token, err := iot.GetToken(c.src) if err != nil { return "", err } diff --git a/internal/iot/token.go b/internal/iot/token.go index bfa3df37..3c1912d2 100644 --- a/internal/iot/token.go +++ b/internal/iot/token.go @@ -70,3 +70,14 @@ func ctxWithToken(ctx context.Context, src oauth2.TokenSource) (context.Context, } return context.WithValue(ctx, iotclient.ContextOAuth2, src), nil } + +func GetToken(src oauth2.TokenSource) (*oauth2.Token, error) { + token, err := src.Token() + if err != nil { + if strings.Contains(err.Error(), "401") { + return nil, errors.New("wrong credentials") + } + return nil, fmt.Errorf("cannot retrieve a valid token: %w", err) + } + return token, nil +} diff --git a/internal/provisioning-api/client.go b/internal/provisioning-api/client.go index 0298cf72..3bba5591 100644 --- a/internal/provisioning-api/client.go +++ b/internal/provisioning-api/client.go @@ -24,7 +24,6 @@ import ( "fmt" "io" "net/http" - "strings" "github.com/arduino/arduino-cloud-cli/config" "github.com/arduino/arduino-cloud-cli/internal/iot" @@ -66,20 +65,9 @@ func (c *ProvisioningApiClient) performRequest(endpoint, method, token string, b return res, nil } -func (c *ProvisioningApiClient) getToken() (*oauth2.Token, error) { - token, err := c.src.Token() - if err != nil { - if strings.Contains(err.Error(), "401") { - return nil, errors.New("wrong credentials") - } - return nil, fmt.Errorf("cannot retrieve a valid token: %w", err) - } - return token, nil -} - func (c *ProvisioningApiClient) ClaimDevice(data ClaimData) (*ClaimResponse, *BadResponse, error) { endpoint := c.host + "/provisioning/v1/onboarding/claim" - token, err := c.getToken() + token, err := iot.GetToken(c.src) if err != nil { return nil, nil, err } @@ -121,7 +109,7 @@ func (c *ProvisioningApiClient) ClaimDevice(data ClaimData) (*ClaimResponse, *Ba func (c *ProvisioningApiClient) RegisterDevice(data RegisterBoardData) (*BadResponse, error) { endpoint := c.host + "/provisioning/v1/boards/register" - token, err := c.getToken() + token, err := iot.GetToken(c.src) if err != nil { return nil, err } @@ -157,7 +145,7 @@ func (c *ProvisioningApiClient) RegisterDevice(data RegisterBoardData) (*BadResp func (c *ProvisioningApiClient) UnclaimDevice(provisioningId string) (*BadResponse, error) { endpoint := c.host + "/provisioning/v1/onboarding/" + provisioningId - token, err := c.getToken() + token, err := iot.GetToken(c.src) if err != nil { return nil, err } @@ -186,7 +174,7 @@ func (c *ProvisioningApiClient) UnclaimDevice(provisioningId string) (*BadRespon func (c *ProvisioningApiClient) GetProvisioningList() (*OnboardingsResponse, error) { endpoint := c.host + "/provisioning/v1/onboarding?all=true" - token, err := c.getToken() + token, err := iot.GetToken(c.src) if err != nil { return nil, err }