initial commit
This commit is contained in:
7
go.mod
Normal file
7
go.mod
Normal file
@@ -0,0 +1,7 @@
|
||||
module ShellyCalibrationHelper
|
||||
|
||||
go 1.24
|
||||
|
||||
require github.com/sirupsen/logrus v1.9.3
|
||||
|
||||
require golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
|
15
go.sum
Normal file
15
go.sum
Normal file
@@ -0,0 +1,15 @@
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
179
main.go
Normal file
179
main.go
Normal file
@@ -0,0 +1,179 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
shellyFlag = flag.String("s", "", "list shelly ips, comma seperated")
|
||||
debugFlag = flag.Bool("d", false, "enable debug mode")
|
||||
)
|
||||
|
||||
const (
|
||||
SleepMinutes = 5
|
||||
)
|
||||
|
||||
type ShellyStatus struct {
|
||||
WifiSta struct {
|
||||
Connected bool `json:"connected"`
|
||||
Ssid string `json:"ssid"`
|
||||
Ip string `json:"ip"`
|
||||
Rssi int `json:"rssi"`
|
||||
} `json:"wifi_sta"`
|
||||
Cloud struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
Connected bool `json:"connected"`
|
||||
} `json:"cloud"`
|
||||
Mqtt struct {
|
||||
Connected bool `json:"connected"`
|
||||
} `json:"mqtt"`
|
||||
Time string `json:"time"`
|
||||
UnixTime int `json:"unixtime"`
|
||||
Serial int `json:"serial"`
|
||||
HasUpdate bool `json:"has_update"`
|
||||
Mac string `json:"mac"`
|
||||
CfgChangedCnt int `json:"cfg_changed_cnt"`
|
||||
ActionsStats struct {
|
||||
Skipped int `json:"skipped"`
|
||||
} `json:"actions_stats"`
|
||||
Thermostats []struct {
|
||||
Pos float64 `json:"pos"`
|
||||
TargetT struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
Value float64 `json:"value"`
|
||||
ValueOp float64 `json:"value_op"`
|
||||
Units string `json:"units"`
|
||||
} `json:"target_t"`
|
||||
Tmp struct {
|
||||
Value float64 `json:"value"`
|
||||
Units string `json:"units"`
|
||||
IsValid bool `json:"is_valid"`
|
||||
} `json:"tmp"`
|
||||
Schedule bool `json:"schedule"`
|
||||
ScheduleProfile int `json:"schedule_profile"`
|
||||
BoostMinutes int `json:"boost_minutes"`
|
||||
WindowOpen bool `json:"window_open"`
|
||||
} `json:"thermostats"`
|
||||
Calibrated bool `json:"calibrated"`
|
||||
Bat struct {
|
||||
Value int `json:"value"`
|
||||
Voltage float64 `json:"voltage"`
|
||||
} `json:"bat"`
|
||||
Charger bool `json:"charger"`
|
||||
Update struct {
|
||||
Status string `json:"status"`
|
||||
HasUpdate bool `json:"has_update"`
|
||||
NewVersion string `json:"new_version"`
|
||||
OldVersion string `json:"old_version"`
|
||||
BetaVersion interface{} `json:"beta_version"`
|
||||
} `json:"update"`
|
||||
RamTotal int `json:"ram_total"`
|
||||
RamFree int `json:"ram_free"`
|
||||
FsSize int `json:"fs_size"`
|
||||
FsFree int `json:"fs_free"`
|
||||
Uptime int `json:"uptime"`
|
||||
FwInfo struct {
|
||||
Device string `json:"device"`
|
||||
Fw string `json:"fw"`
|
||||
} `json:"fw_info"`
|
||||
PsMode int `json:"ps_mode"`
|
||||
DbgFlags int `json:"dbg_flags"`
|
||||
}
|
||||
|
||||
type ShellyRebootResponse struct {
|
||||
Ok bool `json:"ok"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
if *debugFlag {
|
||||
log.SetLevel(log.DebugLevel)
|
||||
}
|
||||
|
||||
if *shellyFlag == "" {
|
||||
log.Fatal("no shelly ips specified")
|
||||
}
|
||||
|
||||
for _, ip := range strings.Split(*shellyFlag, ",") {
|
||||
go func() {
|
||||
err := checkShelly(ip)
|
||||
if err != nil {
|
||||
log.Fatalf("shelly worker %s failed: %v", ip, err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
func checkShelly(ip string) error {
|
||||
log.Infof("shelly worker %s started", ip)
|
||||
|
||||
for {
|
||||
resp, err := http.Get(fmt.Sprintf("http://%s/status", ip))
|
||||
if err != nil {
|
||||
log.Warningf("shelly %s status check failed: %v", ip, err)
|
||||
time.Sleep(time.Duration(SleepMinutes) * time.Minute)
|
||||
continue
|
||||
}
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
log.Warningf("shelly %s status check failed: %v", ip, resp.Status)
|
||||
time.Sleep(time.Duration(SleepMinutes) * time.Minute)
|
||||
continue
|
||||
}
|
||||
|
||||
respBin, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Warningf("shelly %s response cannot be read: %v", ip, err)
|
||||
time.Sleep(time.Duration(SleepMinutes) * time.Minute)
|
||||
continue
|
||||
}
|
||||
|
||||
shellyStatus := new(ShellyStatus)
|
||||
if err := json.Unmarshal(respBin, shellyStatus); err != nil {
|
||||
log.Warningf("shelly %s response cannot be parsed: %v", ip, err)
|
||||
time.Sleep(time.Duration(SleepMinutes) * time.Minute)
|
||||
continue
|
||||
}
|
||||
|
||||
if !shellyStatus.Calibrated {
|
||||
log.Infof("shelly %s calibrated: %v", ip, shellyStatus.Calibrated)
|
||||
rebootResp, err := http.Get(fmt.Sprintf("http://%s/reboot", ip))
|
||||
if err != nil {
|
||||
log.Warningf("shelly %s reboot request failed: %v", ip, err)
|
||||
time.Sleep(time.Duration(SleepMinutes) * time.Minute)
|
||||
continue
|
||||
}
|
||||
|
||||
if rebootResp.StatusCode != 200 {
|
||||
log.Warningf("shelly %s reboot request failed: %v", ip, resp.Status)
|
||||
time.Sleep(time.Duration(SleepMinutes) * time.Minute)
|
||||
continue
|
||||
}
|
||||
|
||||
rebootBin, err := io.ReadAll(rebootResp.Body)
|
||||
if err != nil {
|
||||
log.Warningf("shelly %s reboot response cannot be read: %v", ip, err)
|
||||
time.Sleep(time.Duration(SleepMinutes) * time.Minute)
|
||||
continue
|
||||
}
|
||||
|
||||
shellyReboot := new(ShellyRebootResponse)
|
||||
if err := json.Unmarshal(rebootBin, shellyReboot); err != nil {
|
||||
log.Warningf("shelly %s reboot response cannot be parsed: %v", ip, err)
|
||||
time.Sleep(time.Duration(SleepMinutes) * time.Minute)
|
||||
continue
|
||||
}
|
||||
log.Infof("shelly %s reboot response: %v", ip, shellyReboot.Ok)
|
||||
}
|
||||
|
||||
time.Sleep(time.Minute * 5)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user