update for gen2

This commit is contained in:
shoopea 2023-12-16 14:18:09 +01:00
parent e2a5e32322
commit aabf024abc
3 changed files with 198 additions and 67 deletions

178
proxy.go
View File

@ -17,72 +17,15 @@ import (
"github.com/robfig/cron/v3"
)
type ShellyStatus struct {
Wifi ShellyWifiStatus `json:"wifi_sta"`
Cloud ShellyCloudStatus `json:"cloud"`
Mqtt ShellyMqttStatus `json:"mqtt"`
Time string `json:"time"`
Serial int `json:"serial"`
HasUpdate bool `json:"has_update"`
MAC string `json:"mac"`
Relays []ShellyRelaysStatus `json:"relays"`
Meters []ShellyMetersStatus `json:"meters"`
Temperature float32 `json:"temperature"`
OverTemperature bool `json:"overtemperature"`
Update ShellyUpdateStatus `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"`
}
type ShellyWifiStatus struct {
Connected bool `json:"connected"`
SSID string `json:"ssid"`
IP string `json:"ip"`
RSSI int `json:"rssi"`
}
type ShellyCloudStatus struct {
Enabled bool `json:"enabled"`
Connected bool `json:"connected"`
}
type ShellyMqttStatus struct {
Connected bool `json:"connected"`
}
type ShellyRelaysStatus struct {
IsOn bool `json:"ison"`
HasTimer bool `json:"has_timer"`
Overpower bool `json:"overpower"`
}
type ShellyMetersStatus struct {
Power float32 `json:"power"`
IsValid bool `json:"is_valid"`
Timestamp int `json:"timestamp"`
Counters []float32 `json:"counters"`
Total int `json:"total"`
}
type ShellyUpdateStatus struct {
Status string `json:"status"`
HasUpdate bool `json:"has_update"`
NewVersion string `json:"new_version"`
OldVersion string `json:"old_version"`
}
var (
flagset = flag.NewFlagSet("shelly-proxy", flag.ContinueOnError)
// config flags
shellyHost = flagset.String("shellyplug-host", "192.168.30.1", "Shellyplug address (also via SHELLYPLUG_HOST)")
shellyHost = flagset.String("shellyplug-host", "192.168.33.1", "Shellyplug address (also via SHELLYPLUG_HOST)")
shellyPort = flagset.Int("shellyplug-port", 80, "Shellyplug port (also via SHELLYPLUG_HOST)")
//shellyAuthUser = flagset.String("shellyplug-auth-username", "", "Shellyplug authentication username (also via SHELLYPLUG_AUTH_USERNAME)")
//shellyAuthPass = flagset.String("shellyplug-auth-password", "", "Shellyplug authentication username (also via SHELLYPLUG_AUTH_PASSWORD)")
exporterPort = flagset.Int("exporter-port", 9000, "Exporter port (also via EXPORTER_PORT)")
exporterPort = flagset.Int("exporter-port", 5000, "Exporter port (also via EXPORTER_PORT)")
// additional flags
_ = flagset.String("config", "", "Path to config file (ini format)")
@ -92,6 +35,17 @@ var (
ss *ShellyStatus
)
type ShellyStatus struct {
Status1 *ShellyStatus1
Status2 *ShellyStatus2
Version int
}
type ShellyVersion struct {
Gen int `json:"gen"`
Type string `json:"type"`
}
func main() {
// use .env file if it exists
@ -134,24 +88,78 @@ func main() {
}
}
func (s *ShellyStatus) Fetch() {
resp, err := http.Get(fmt.Sprintf("http://%s:%d/status", *shellyHost, *shellyPort))
func (s *ShellyStatus) GetVersion() int {
if s.Version != 0 {
return s.Version
}
resp, err := http.Get(fmt.Sprintf("http://%s:%d/shelly", *shellyHost, *shellyPort))
if err != nil {
log.Fatalf("ShellyStatus.Fetch : http.Get (%s)", err)
log.Fatalf("ShellyStatus.GetVersion : http.Get (%s)", err)
}
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatalf("ShellyStatus.Fetch : io.ReadAll (%s)", err)
log.Fatalf("ShellyStatus.GetVersion : io.ReadAll (%s)", err)
}
if err = json.Unmarshal(body, s); err != nil {
log.Fatalf("ShellyStatus.Fetch : json.Unmarshal (%s)", err)
v := ShellyVersion{}
if err = json.Unmarshal(body, &v); err != nil {
log.Fatalf("ShellyStatus.GetVersion : json.Unmarshal (%s)", err)
}
if v.Type != "" {
s.Version = 1
s.Status1 = &ShellyStatus1{}
}
if v.Gen != 0 {
s.Version = v.Gen
s.Status2 = &ShellyStatus2{}
}
return s.Version
}
func (s *ShellyStatus) Fetch() {
switch s.GetVersion() {
case 1:
resp, err := http.Get(fmt.Sprintf("http://%s:%d/status", *shellyHost, *shellyPort))
if err != nil {
log.Fatalf("ShellyStatus.Fetch : http.Get (%s)", err)
}
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatalf("ShellyStatus.Fetch : io.ReadAll (%s)", err)
}
if err = json.Unmarshal(body, s.Status1); err != nil {
log.Fatalf("ShellyStatus.Fetch : json.Unmarshal (%s)", err)
}
return
case 2:
resp, err := http.Get(fmt.Sprintf("http://%s:%d/rpc/Shelly.GetStatus", *shellyHost, *shellyPort))
if err != nil {
log.Fatalf("ShellyStatus.Fetch : http.Get (%s)", err)
}
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatalf("ShellyStatus.Fetch : io.ReadAll (%s)", err)
}
if err = json.Unmarshal(body, s.Status2); err != nil {
log.Fatalf("ShellyStatus.Fetch : json.Unmarshal (%s)", err)
}
return
default:
return
}
}
func GetMetrics(c *gin.Context) {
c.String(http.StatusOK, `# HELP shellyplug_power Current power drawn in watts
switch ss.Version {
case 1:
c.String(http.StatusOK, `# HELP shellyplug_power Current power drawn in watts
# TYPE shellyplug_power gauge
shellyplug_power %.2f
# HELP shellyplug_overpower Overpower drawn in watts/minute
@ -166,7 +174,43 @@ shellyplug_temperature %.2f
# HELP shellyplug_uptime Plug uptime in seconds
# TYPE shellyplug_uptime gauge
shellyplug_uptime %d
`, ss.Meters[0].Counters[0], float32(0), ss.Meters[0].Total, ss.Temperature, ss.Uptime)
`, ss.Status1.Meters[0].Counters[0], float32(0), 0, ss.Status1.Temperature, ss.Status1.Uptime)
case 2:
c.String(http.StatusOK, `# HELP shellyplug_power Current power drawn in watts
# TYPE shellyplug_power gauge
shellyplug_power %.2f
# HELP shellyplug_overpower Overpower drawn in watts/minute
# TYPE shellyplug_overpower gauge
shellyplug_overpower %.2f
# HELP shellyplug_total_power Total power consumed in watts/minute
# TYPE shellyplug_total_power counter
shellyplug_total_power %d
# HELP shellyplug_temperature Plug temperature in celsius
# TYPE shellyplug_temperature gauge
shellyplug_temperature %.2f
# HELP shellyplug_uptime Plug uptime in seconds
# TYPE shellyplug_uptime gauge
shellyplug_uptime %d
`, ss.Status2.Switch.Power, float32(0), 0, ss.Status2.Switch.Temperature.Celsius, ss.Status2.Sys.Uptime)
default:
c.String(http.StatusOK, `# HELP shellyplug_power Current power drawn in watts
# TYPE shellyplug_power gauge
shellyplug_power %.2f
# HELP shellyplug_overpower Overpower drawn in watts/minute
# TYPE shellyplug_overpower gauge
shellyplug_overpower %.2f
# HELP shellyplug_total_power Total power consumed in watts/minute
# TYPE shellyplug_total_power counter
shellyplug_total_power %d
# HELP shellyplug_temperature Plug temperature in celsius
# TYPE shellyplug_temperature gauge
shellyplug_temperature %.2f
# HELP shellyplug_uptime Plug uptime in seconds
# TYPE shellyplug_uptime gauge
shellyplug_uptime %d
`, float32(0), float32(0), 0, float32(0), 0)
}
}
// IniParser is a parser for config files in classic key/value style format. Each

58
shelly1.go Normal file
View File

@ -0,0 +1,58 @@
package main
type ShellyStatus1 struct {
Wifi ShellyWifiStatus1 `json:"wifi_sta"`
Cloud ShellyCloudStatus1 `json:"cloud"`
Mqtt ShellyMqttStatus1 `json:"mqtt"`
Time string `json:"time"`
Serial int `json:"serial"`
HasUpdate bool `json:"has_update"`
MAC string `json:"mac"`
Relays []ShellyRelaysStatus1 `json:"relays"`
Meters []ShellyMetersStatus1 `json:"meters"`
Temperature float32 `json:"temperature"`
OverTemperature bool `json:"overtemperature"`
Update ShellyUpdateStatus1 `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"`
}
type ShellyWifiStatus1 struct {
Connected bool `json:"connected"`
SSID string `json:"ssid"`
IP string `json:"ip"`
RSSI int `json:"rssi"`
}
type ShellyCloudStatus1 struct {
Enabled bool `json:"enabled"`
Connected bool `json:"connected"`
}
type ShellyMqttStatus1 struct {
Connected bool `json:"connected"`
}
type ShellyRelaysStatus1 struct {
IsOn bool `json:"ison"`
HasTimer bool `json:"has_timer"`
Overpower bool `json:"overpower"`
}
type ShellyMetersStatus1 struct {
Power float32 `json:"power"`
IsValid bool `json:"is_valid"`
Timestamp int `json:"timestamp"`
Counters []float32 `json:"counters"`
Total int `json:"total"`
}
type ShellyUpdateStatus1 struct {
Status string `json:"status"`
HasUpdate bool `json:"has_update"`
NewVersion string `json:"new_version"`
OldVersion string `json:"old_version"`
}

29
shelly2.go Normal file
View File

@ -0,0 +1,29 @@
package main
type ShellyStatus2 struct {
Switch ShellySwitch2 `json:"switch:0"`
Sys ShellySys2 `json:"sys"`
}
type ShellySwitch2 struct {
Power float32 `json:"apower"`
Voltage float32 `json:"voltage"`
Current float32 `json:"current"`
Energy ShellyEnergy2 `json:"aenergy"`
Temperature ShellyTemperature2 `json:"temperature"`
}
type ShellyEnergy2 struct {
Total float32 `json:"total"`
ByMinute []float32 `json:"by_minute"`
MinuteTS int `json:"minute_ts"`
}
type ShellyTemperature2 struct {
Celsius float32 `json:"tC"`
Fahrenheit float32 `json:"tF"`
}
type ShellySys2 struct {
Uptime int `json:"uptime"`
}