diff --git a/Makefile b/Makefile index c334312..f5b4ccd 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ .PHONY: all -all: bin/shelly-bulk-update-Darwin-x86_64 bin/shelly-bulk-update-Darwin-arm64 bin/shelly-bulk-update-Linux-x86_64 bin/shelly-bulk-update-Windows-x86_64.exe +all: bin/shelly-bulk-update-Darwin-x86_64 bin/shelly-bulk-update-Darwin-arm64 bin/shelly-bulk-update-Linux-x86_64 bin/shelly-bulk-update-Linux-armv7 bin/shelly-bulk-update-Linux-arm64 bin/shelly-bulk-update-Windows-x86_64.exe bin/shelly-bulk-update-Darwin-x86_64: main.go GOOS=darwin GOARCH=amd64 go build -o $@ . @@ -14,6 +14,9 @@ bin/shelly-bulk-update-Linux-x86_64: main.go bin/shelly-bulk-update-Linux-armv7: main.go GOOS=linux GOARCH=arm GOARM=7 go build -o $@ . +bin/shelly-bulk-update-Linux-arm64: main.go + GOOS=linux GOARCH=arm64 go build -o $@ . + bin/shelly-bulk-update-Windows-x86_64.exe: main.go GOOS=windows GOARCH=amd64 go build -o $@ . diff --git a/go.mod b/go.mod index 4de0580..c31311a 100644 --- a/go.mod +++ b/go.mod @@ -7,8 +7,8 @@ require github.com/grandcat/zeroconf v1.0.0 require ( github.com/cenkalti/backoff v2.2.1+incompatible // indirect github.com/miekg/dns v1.1.56 // indirect - golang.org/x/mod v0.13.0 // indirect - golang.org/x/net v0.17.0 // indirect - golang.org/x/sys v0.13.0 // indirect - golang.org/x/tools v0.14.0 // indirect + golang.org/x/mod v0.14.0 // indirect + golang.org/x/net v0.18.0 // indirect + golang.org/x/sys v0.14.0 // indirect + golang.org/x/tools v0.15.0 // indirect ) diff --git a/go.sum b/go.sum index 4487853..38347c1 100644 --- a/go.sum +++ b/go.sum @@ -10,24 +10,24 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= -golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= +golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= -golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= -golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= +golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8= +golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/main.go b/main.go index 34bec6a..1192413 100644 --- a/main.go +++ b/main.go @@ -205,9 +205,9 @@ func updateShellyGen1(name, address string) { updateStatusCheck, err := checkShellyUpdateStatus(address) if err != nil { fmt.Printf("%s failed to query update status: %s, retrying...\n", prefix, err) - } else { - updateStatus = updateStatusCheck + continue } + updateStatus = updateStatusCheck } fmt.Printf("%s device updated to %s!\n", prefix, updateStatus.OldVersion) @@ -234,6 +234,7 @@ func updateShellyGen2(name, address string) { fmt.Printf("%s already up to date\n", prefix) return } + newVersion := updateVersion fmt.Printf("%s updating to version %s...\n", prefix, updateVersion) err = makeGen2UpdateRequest(address, updateStage) @@ -241,6 +242,29 @@ func updateShellyGen2(name, address string) { fmt.Printf("%s failed to update: %s, aborting...\n", prefix, err) return } + + // wait for update to complete + tries := 0 + for updateVersion != "" { + tries++ + if tries > 12 { + fmt.Printf("%s failed to check if update completed successfully", prefix) + return + } + time.Sleep(time.Second * 5) + updates, err := makeGen2CheckForUpdateRequest(address) + if err != nil { + fmt.Printf("%s failed to query update status: %s, retrying...\n", prefix, err) + continue + } + + if updateStage == "beta" { + updateVersion = updates.Beta.Version + } else { + updateVersion = updates.Stable.Version + } + } + fmt.Printf("%s device updated to %s!\n", prefix, newVersion) } func updateShelly(name, address string, txtRecords []string, genToUpdate int) { @@ -273,7 +297,11 @@ func main() { os.Exit(2) } - resolver, err := zeroconf.NewResolver(nil) + // Listen only for IPv4 addresses. Otherwise, it may happen that ServiceEntry has an empty + // AddrIPv4 slice. It happens when the IPv6 arrives first and ServiceEntries are not updated + // when more data arrives. + // See https://github.com/grandcat/zeroconf/issues/27 + resolver, err := zeroconf.NewResolver(zeroconf.SelectIPTraffic(zeroconf.IPv4)) if err != nil { log.Fatalln("Failed to initialize resolver:", err.Error()) } @@ -290,7 +318,8 @@ func main() { address := entry.HostName if len(entry.AddrIPv4) > 0 { address = entry.AddrIPv4[0].String() - // not yet: + // IPv6 support is still very limited + // See https://shelly-api-docs.shelly.cloud/gen2/General/IPv6 //} else if len(entry.AddrIPv6) > 0 { // address = fmt.Sprintf("[%s]", entry.AddrIPv6[0].String()) }