diff --git a/README.md b/README.md index d293ed0..c33206f 100644 --- a/README.md +++ b/README.md @@ -139,6 +139,19 @@ Response to Switch.Set command for ShellyPlugUS-AABBCCDDEEFF: Was On: true ``` +#### Updating Devices +Shelly devices support self-updates via the ([Shelly.Update](https://shelly-api-docs.shelly.cloud/gen2/ComponentsAndServices/Shelly#shellyupdate)) RPC. This can be invoked on the command-line with `shellyctl shelly update`. Individual devices can be specified with the `--host` flag, or in bulk using mDNS (`--mdns-search`) or BLE (`--ble-search`) discovery. If no updates are available for the specified release stage, the Shelly devices appear to return error `-114: Resource unavailable: No update info!`; consider using the `--skip-failed-hosts` flag to continue in the face of this error. +``` +shellyctl shelly update --stage=stable --skip-failed-hosts=true --mdns-search --interactive=false + +Response to Shelly.Update command for http://192.168.1.28/rpc: success + +7:31PM ERR error executing request; contining because --skip-failed-hosts=true error="RPC Bad Status -114: Resource unavailable: No update info!" component=discovery + device_name=ShellyPro3-AABBCCDDEEFF instance=http://192.168.1.12:80/rpc request=Shelly.Update + +Response to Shelly.Update command for http://192.168.1.29/rpc: success + ``` + #### Menu Heirarchy - `ble` - `get-config` ([BLE.GetConfig](https://shelly-api-docs.shelly.cloud/gen2/ComponentsAndServices/BLE/#blegetconfig)) @@ -158,7 +171,7 @@ Response to Switch.Set command for ShellyPlugUS-AABBCCDDEEFF: - `reset-counters` ([Cover.ResetCounters](https://shelly-api-docs.shelly.cloud/gen2/ComponentsAndServices/Cover/#coverresetcounters)) - `set-config` ([Cover.SetConfig](https://shelly-api-docs.shelly.cloud/gen2/ComponentsAndServices/Cover/#coversetconfig)) - `stop` ([Cover.Stop](https://shelly-api-docs.shelly.cloud/gen2/ComponentsAndServices/Cover/#coverstop)) -- input +- `input` - `check-expression` ([Input.GetConfig](https://shelly-api-docs.shelly.cloud/gen2/ComponentsAndServices/Input#inputcheckexpression)) - `get-config` ([Input.GetConfig](https://shelly-api-docs.shelly.cloud/gen2/ComponentsAndServices/Input#inputsetconfig)) - `get-status` ([Input.GetStatus](https://shelly-api-docs.shelly.cloud/gen2/ComponentsAndServices/Input#inputgetstatus)) @@ -178,10 +191,18 @@ Response to Switch.Set command for ShellyPlugUS-AABBCCDDEEFF: - `delete-all` ([Schedule.DeleteAll](https://shelly-api-docs.shelly.cloud/gen2/ComponentsAndServices/Schedule#scheduledeleteall)) - `shelly` - `check-for-update` ([Shelly.CheckForUpdate](https://shelly-api-docs.shelly.cloud/gen2/ComponentsAndServices/Shelly#shellycheckforupdate)) + - `detect-location` ([Shelly.DetectLocation](https://shelly-api-docs.shelly.cloud/gen2/ComponentsAndServices/Shelly#shellydetectlocation)) + - `factory-reset` ([Shelly.FactoryReset](https://shelly-api-docs.shelly.cloud/gen2/ComponentsAndServices/Shelly#shellyfactoryreset)) - `get-config` ([Shelly.GetConfig](https://shelly-api-docs.shelly.cloud/gen2/ComponentsAndServices/Shelly#shellygetconfig)) - `get-status` ([Shelly.GetStatus](https://shelly-api-docs.shelly.cloud/gen2/ComponentsAndServices/Shelly#shellygetstatus)) + - `list-methods` ([Shelly.ListMethods](https://shelly-api-docs.shelly.cloud/gen2/ComponentsAndServices/Shelly#shellylistmethods)) + - `list-profiles` ([Shelly.ListProfiles](https://shelly-api-docs.shelly.cloud/gen2/ComponentsAndServices/Shelly#shellylistprofiles)) + - `list-timezones` ([Shelly.ListTimezones](https://shelly-api-docs.shelly.cloud/gen2/ComponentsAndServices/Shelly#shellylisttimezones)) - `reboot` ([Shelly.Reboot](https://shelly-api-docs.shelly.cloud/gen2/ComponentsAndServices/Shelly#shellyreboot)) + - `reset-wifi-config` ([Shelly.ResetWiFiConfig](https://shelly-api-docs.shelly.cloud/gen2/ComponentsAndServices/Shelly#shellyresetwificonfig)) - `set-auth` ([Shelly.SetAuth](https://shelly-api-docs.shelly.cloud/gen2/ComponentsAndServices/Shelly#shellysetauth)) + - `set-profile` ([Shelly.SetProfile](https://shelly-api-docs.shelly.cloud/gen2/ComponentsAndServices/Shelly#shellysetprofile)) + - `update` ([Shelly.Update](https://shelly-api-docs.shelly.cloud/gen2/ComponentsAndServices/Shelly#shellyupdate)) - `switch` - `get-config` ([Switch.GetConfig](https://shelly-api-docs.shelly.cloud/gen2/ComponentsAndServices/Switch#switchgetconfig)) - `get-status` ([Switch.GetStatus](https://shelly-api-docs.shelly.cloud/gen2/ComponentsAndServices/Switch#switchgetstatusg)) diff --git a/cmd/gen.go b/cmd/gen.go index 468284d..444c2b2 100644 --- a/cmd/gen.go +++ b/cmd/gen.go @@ -117,17 +117,19 @@ var ( Short: "RPCs related device management, configuration, and status", }, Requests: []shelly.RPCRequestBody{ + &shelly.ShellyCheckForUpdateRequest{}, + &shelly.ShellyDetectLocationRequest{}, + &shelly.ShellyFactoryResetRequest{}, + &shelly.ShellyGetConfigRequest{}, &shelly.ShellyGetDeviceInfoRequest{}, &shelly.ShellyGetStatusRequest{}, - &shelly.ShellyGetConfigRequest{}, &shelly.ShellyListMethodsRequest{}, &shelly.ShellyListProfilesRequest{}, &shelly.ShellyListTimezonesRequest{}, - &shelly.ShellyDetectLocationRequest{}, + &shelly.ShellyRebootRequest{}, + &shelly.ShellyResetWiFiConfigRequest{}, &shelly.ShellySetProfileRequest{}, - &shelly.ShellyCheckForUpdateRequest{}, &shelly.ShellyUpdateRequest{}, - &shelly.ShellyRebootRequest{}, // ShellySetAuth requires some calculation as it depends on the device ID. // It is implemented in cmd/shelly.go. // &shelly.ShellySetAuthRequest{}, @@ -208,6 +210,11 @@ func init() { c.Parent.Help() } for _, childCmd := range c.Parent.Commands() { + // Hack 🙄 + if c.Parent.Use == "shelly" && childCmd.Use == "reset-wi-fi-config" { + childCmd.Use = "reset-wifi-config" + childCmd.Aliases = append(childCmd.Aliases, "reset-wi-fi-config") + } childRun := childCmd.RunE discoveryFlags(childCmd.Flags(), discoveryFlagsOptions{interactive: true}) childCmd.RunE = func(cmd *cobra.Command, args []string) error { diff --git a/go.mod b/go.mod index 371be41..24aab91 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.21.3 require ( github.com/go-logr/zerologr v1.2.3 github.com/hashicorp/mdns v1.0.5 - github.com/jcodybaker/go-shelly v0.0.0-20240219061436-af3ca73aae03 + github.com/jcodybaker/go-shelly v0.0.0-20240219065811-567c6d96a3af github.com/mongoose-os/mos v0.0.0-20230313140341-b44964e63a92 github.com/prometheus/client_golang v1.18.0 github.com/rs/zerolog v1.31.0 diff --git a/go.sum b/go.sum index d98df92..71bde0c 100644 --- a/go.sum +++ b/go.sum @@ -518,6 +518,10 @@ github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6t github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jcodybaker/go-shelly v0.0.0-20240219061436-af3ca73aae03 h1:vIEb29sw0ebm/7a1aZAPTxUCDS/KCL5492HEGfCmFaY= github.com/jcodybaker/go-shelly v0.0.0-20240219061436-af3ca73aae03/go.mod h1:EfKnkqHSomR+wV7AoVgv6wU+kz1Xm4RSaEKaWMKWgWg= +github.com/jcodybaker/go-shelly v0.0.0-20240219062609-517f47e8956c h1:OMMo81Cy886h1FHJR+nTywptjvyN4lpF5Pmb7Qoz53k= +github.com/jcodybaker/go-shelly v0.0.0-20240219062609-517f47e8956c/go.mod h1:EfKnkqHSomR+wV7AoVgv6wU+kz1Xm4RSaEKaWMKWgWg= +github.com/jcodybaker/go-shelly v0.0.0-20240219065811-567c6d96a3af h1:SZTxDEPrJ5/Dj/0ZLhc0s9N9m86ByTVdQsYp9F+P/zA= +github.com/jcodybaker/go-shelly v0.0.0-20240219065811-567c6d96a3af/go.mod h1:EfKnkqHSomR+wV7AoVgv6wU+kz1Xm4RSaEKaWMKWgWg= github.com/jcodybaker/mdns v0.0.0-20240218225721-3b8606993b85 h1:/Ls0Q1POaNRFf9uopWlac5skKmWCkEwn/EPmueN5Mco= github.com/jcodybaker/mdns v0.0.0-20240218225721-3b8606993b85/go.mod h1:RBWesCDwuRmyqepO+WxO8JSfrh3Tj3LkSzXPQlFq2nM= github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= diff --git a/pkg/gencobra/gencobra.go b/pkg/gencobra/gencobra.go index f684b19..c7ff9b8 100644 --- a/pkg/gencobra/gencobra.go +++ b/pkg/gencobra/gencobra.go @@ -14,6 +14,7 @@ import ( "github.com/rs/zerolog/log" "github.com/spf13/cobra" "github.com/spf13/pflag" + "github.com/spf13/viper" "github.com/stoewer/go-strcase" ) @@ -68,7 +69,12 @@ func RequestToCmd(req shelly.RPCRequestBody, baggage *Baggage) (*cobra.Command, resp := req.NewResponse() raw, err := shelly.Do(ctx, conn, d.AuthCallback(ctx), req, resp) if err != nil { - return fmt.Errorf("executing %s: %w", req.Method(), err) + if viper.GetBool("skip-failed-hosts") { + ll.Err(err).Msg("error executing request; contining because --skip-failed-hosts=true") + continue + } else { + ll.Fatal().Err(err).Msg("error executing request") + } } ll.Debug().RawJSON("raw_response", raw.Response).Msg("got raw response") baggage.Output(