-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Marc Ritter
committed
Dec 4, 2023
1 parent
c1dc637
commit 7025ed4
Showing
4 changed files
with
224 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
package shellyplug | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/prometheus/client_golang/prometheus" | ||
log "github.com/sirupsen/logrus" | ||
|
||
"github.com/webdevops/shelly-plug-exporter/discovery" | ||
"github.com/webdevops/shelly-plug-exporter/shellyprober" | ||
) | ||
|
||
func (sp *ShellyPlug) collectFromTargetGen1em(target discovery.DiscoveryTarget, logger *log.Entry, infoLabels, targetLabels prometheus.Labels) { | ||
shellyProber := shellyprober.ShellyProberGen1Em{ | ||
Target: target, | ||
Client: sp.client, | ||
Ctx: sp.ctx, | ||
Cache: globalCache, | ||
} | ||
|
||
if result, err := shellyProber.GetSettings(); err == nil { | ||
if discovery.ServiceDiscovery != nil { | ||
discovery.ServiceDiscovery.MarkTarget(target.Address, discovery.TargetHealthy) | ||
} | ||
|
||
targetLabels["plugName"] = result.Name | ||
|
||
infoLabels["plugName"] = result.Name | ||
infoLabels["plugModel"] = result.Device.Type | ||
|
||
powerLimitLabels := copyLabelMap(targetLabels) | ||
powerLimitLabels["id"] = "emeter:0" | ||
powerLimitLabels["name"] = "" | ||
sp.prometheus.powerLoadLimit.With(powerLimitLabels).Set(result.MaxPower) | ||
} else { | ||
logger.Errorf(`failed to fetch settings: %v`, err) | ||
if discovery.ServiceDiscovery != nil { | ||
discovery.ServiceDiscovery.MarkTarget(target.Address, discovery.TargetUnhealthy) | ||
} | ||
} | ||
|
||
sp.prometheus.info.With(infoLabels).Set(1) | ||
|
||
if result, err := shellyProber.GetStatus(); err == nil { | ||
sp.prometheus.sysUnixtime.With(targetLabels).Set(float64(result.Unixtime)) | ||
sp.prometheus.sysUptime.With(targetLabels).Set(float64(result.Uptime)) | ||
sp.prometheus.sysMemTotal.With(targetLabels).Set(float64(result.RAMTotal)) | ||
sp.prometheus.sysMemFree.With(targetLabels).Set(float64(result.RAMFree)) | ||
sp.prometheus.sysFsSize.With(targetLabels).Set(float64(result.FsSize)) | ||
sp.prometheus.sysFsFree.With(targetLabels).Set(float64(result.FsFree)) | ||
|
||
wifiLabels := copyLabelMap(targetLabels) | ||
wifiLabels["ssid"] = result.WifiSta.Ssid | ||
sp.prometheus.wifiRssi.With(wifiLabels).Set(float64(result.WifiSta.Rssi)) | ||
|
||
sp.prometheus.updateNeeded.With(targetLabels).Set(boolToFloat64(result.HasUpdate)) | ||
sp.prometheus.cloudEnabled.With(targetLabels).Set(boolToFloat64(result.Cloud.Enabled)) | ||
sp.prometheus.cloudConnected.With(targetLabels).Set(boolToFloat64(result.Cloud.Connected)) | ||
|
||
for relayID, powerUsage := range result.Emeters { | ||
powerUsageLabels := copyLabelMap(targetLabels) | ||
powerUsageLabels["id"] = fmt.Sprintf("emeter:%d", relayID) | ||
powerUsageLabels["name"] = targetLabels["plugName"] | ||
|
||
sp.prometheus.powerLoadCurrent.With(powerUsageLabels).Set(powerUsage.Power * -1) | ||
// total is provided as watt/minutes, we want watt/hours | ||
powerUsageLabels["direction"] = "in" | ||
sp.prometheus.powerLoadTotal.With(powerUsageLabels).Set(powerUsage.Total / 60) | ||
} | ||
|
||
for relayID, relay := range result.Relays { | ||
switchLabels := copyLabelMap(targetLabels) | ||
switchLabels["id"] = fmt.Sprintf("relay:%d", relayID) | ||
switchLabels["name"] = targetLabels["plugName"] | ||
|
||
switchOnLabels := copyLabelMap(switchLabels) | ||
switchOnLabels["source"] = relay.Source | ||
|
||
sp.prometheus.switchOn.With(switchOnLabels).Set(boolToFloat64(relay.Ison)) | ||
sp.prometheus.switchOverpower.With(switchLabels).Set(boolToFloat64(relay.Overpower)) | ||
sp.prometheus.switchTimer.With(switchLabels).Set(boolToFloat64(relay.HasTimer)) | ||
} | ||
} else { | ||
logger.Errorf(`failed to fetch status: %v`, err) | ||
if discovery.ServiceDiscovery != nil { | ||
discovery.ServiceDiscovery.MarkTarget(target.Address, discovery.TargetUnhealthy) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
package shellyprober | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/go-resty/resty/v2" | ||
"github.com/patrickmn/go-cache" | ||
"github.com/webdevops/shelly-plug-exporter/discovery" | ||
) | ||
|
||
type ( | ||
ShellyProberGen1Em struct { | ||
Target discovery.DiscoveryTarget | ||
Client *resty.Client | ||
Ctx context.Context | ||
Cache *cache.Cache | ||
} | ||
|
||
ShellyProberGen1EmResultSettings struct { | ||
Name string `json:"name"` | ||
MaxPower float64 `json:"max_power"` | ||
Fw string `json:"fw"` | ||
|
||
Device struct { | ||
Hostname string `json:"hostname"` | ||
Mac string `json:"mac"` | ||
Type string `json:"type"` | ||
} `json:"device"` | ||
} | ||
|
||
ShellyProberGen1EmResultStatus struct { | ||
WifiSta struct { | ||
Connected bool `yaml:"connected"` | ||
Ssid string `yaml:"ssid"` | ||
IP string `yaml:"ip"` | ||
Rssi int `yaml:"rssi"` | ||
} `yaml:"wifi_sta"` | ||
Cloud struct { | ||
Enabled bool `yaml:"enabled"` | ||
Connected bool `yaml:"connected"` | ||
} `yaml:"cloud"` | ||
Mqtt struct { | ||
Connected bool `yaml:"connected"` | ||
} `yaml:"mqtt"` | ||
Time string `yaml:"time"` | ||
Unixtime int `yaml:"unixtime"` | ||
Serial int `yaml:"serial"` | ||
HasUpdate bool `yaml:"has_update"` | ||
Mac string `yaml:"mac"` | ||
CfgChangedCnt int `yaml:"cfg_changed_cnt"` | ||
ActionsStats struct { | ||
Skipped int `yaml:"skipped"` | ||
} `yaml:"actions_stats"` | ||
Relays []struct { | ||
Ison bool `yaml:"ison"` | ||
HasTimer bool `yaml:"has_timer"` | ||
TimerStarted int `yaml:"timer_started"` | ||
TimerDuration int `yaml:"timer_duration"` | ||
TimerRemaining int `yaml:"timer_remaining"` | ||
Overpower bool `yaml:"overpower"` | ||
IsValid bool `yaml:"is_valid"` | ||
Source string `yaml:"source"` | ||
} `yaml:"relays"` | ||
Emeters []struct { | ||
Power float64 `yaml:"power"` | ||
Pf float64 `yaml:"pf"` | ||
Current float64 `yaml:"current"` | ||
Voltage float64 `yaml:"voltage"` | ||
IsValid bool `yaml:"is_valid"` | ||
Total float64 `yaml:"total"` | ||
TotalReturned float64 `yaml:"total_returned"` | ||
} `yaml:"emeters"` | ||
TotalPower float64 `yaml:"total_power"` | ||
EmeterN struct { | ||
Current int `yaml:"current"` | ||
Ixsum float64 `yaml:"ixsum"` | ||
Mismatch bool `yaml:"mismatch"` | ||
IsValid bool `yaml:"is_valid"` | ||
} `yaml:"emeter_n"` | ||
FsMounted bool `yaml:"fs_mounted"` | ||
VData int `yaml:"v_data"` | ||
CtCalst int `yaml:"ct_calst"` | ||
Update struct { | ||
Status string `yaml:"status"` | ||
HasUpdate bool `yaml:"has_update"` | ||
NewVersion string `yaml:"new_version"` | ||
OldVersion string `yaml:"old_version"` | ||
BetaVersion string `yaml:"beta_version"` | ||
} `yaml:"update"` | ||
RAMTotal int `yaml:"ram_total"` | ||
RAMFree int `yaml:"ram_free"` | ||
FsSize int `yaml:"fs_size"` | ||
FsFree int `yaml:"fs_free"` | ||
Uptime int `yaml:"uptime"` | ||
} | ||
) | ||
|
||
func (sp *ShellyProberGen1Em) fetch(url string, target interface{}) error { | ||
r := sp.Client.R().SetContext(sp.Ctx).SetResult(&target).ForceContentType("application/json") | ||
_, err := r.Get(sp.Target.Url(url)) | ||
return err | ||
} | ||
|
||
func (sp *ShellyProberGen1Em) GetSettings() (ShellyProberGen1EmResultSettings, error) { | ||
result := ShellyProberGen1EmResultSettings{} | ||
err := sp.fetch("/settings", &result) | ||
return result, err | ||
} | ||
|
||
func (sp *ShellyProberGen1Em) GetStatus() (ShellyProberGen1EmResultStatus, error) { | ||
result := ShellyProberGen1EmResultStatus{} | ||
err := sp.fetch("/status", &result) | ||
return result, err | ||
} |