Homematic: refactor (#9172)
This commit is contained in:
parent
48fa4def43
commit
4cc88a0983
2 changed files with 61 additions and 79 deletions
|
|
@ -4,6 +4,7 @@ import (
|
|||
"encoding/xml"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
|
@ -82,55 +83,37 @@ func (c *Connection) Enable(enable bool) error {
|
|||
// Enabled reads the homematic HMIP-PSM switchchannel state true=on/false=off
|
||||
func (c *Connection) Enabled() (bool, error) {
|
||||
res, err := c.switchCache.Get()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return getBoolValue(res, "STATE"), nil
|
||||
return res.BoolValue("STATE"), err
|
||||
}
|
||||
|
||||
// CurrentPower reads the homematic HMIP-PSM meterchannel power in W
|
||||
func (c *Connection) CurrentPower() (float64, error) {
|
||||
res, err := c.meterCache.Get()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return getFloatValue(res, "POWER"), nil
|
||||
return res.FloatValue("POWER"), err
|
||||
}
|
||||
|
||||
// TotalEnergy reads the homematic HMIP-PSM meterchannel energy in Wh
|
||||
func (c *Connection) TotalEnergy() (float64, error) {
|
||||
res, err := c.meterCache.Get()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return getFloatValue(res, "ENERGY_COUNTER") / 1e3, nil
|
||||
return res.FloatValue("ENERGY_COUNTER") / 1e3, err
|
||||
}
|
||||
|
||||
// Currents reads the homematic HMIP-PSM meterchannel L1 current in A
|
||||
func (c *Connection) Currents() (float64, float64, float64, error) {
|
||||
res, err := c.meterCache.Get()
|
||||
if err != nil {
|
||||
return 0, 0, 0, err
|
||||
}
|
||||
return getFloatValue(res, "CURRENT") / 1e3, 0, 0, nil
|
||||
return res.FloatValue("CURRENT") / 1e3, 0, 0, err
|
||||
}
|
||||
|
||||
// GridCurrentPower reads the homematic HM-ES-TX-WM grid meterchannel power in W
|
||||
func (c *Connection) GridCurrentPower() (float64, error) {
|
||||
res, err := c.meterCache.Get()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return getFloatValue(res, "IEC_POWER"), nil
|
||||
return res.FloatValue("IEC_POWER"), err
|
||||
}
|
||||
|
||||
// GridTotalEnergy reads the homematic HM-ES-TX-WM grid meterchannel energy in kWh
|
||||
func (c *Connection) GridTotalEnergy() (float64, error) {
|
||||
res, err := c.meterCache.Get()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return getFloatValue(res, "IEC_ENERGY_COUNTER"), nil
|
||||
return res.FloatValue("IEC_ENERGY_COUNTER"), err
|
||||
}
|
||||
|
||||
func (c *Connection) XmlCmd(method, channel string, values ...Param) (MethodResponse, error) {
|
||||
|
|
@ -159,64 +142,13 @@ func (c *Connection) XmlCmd(method, channel string, values ...Param) (MethodResp
|
|||
return hmr, err
|
||||
}
|
||||
|
||||
// correct Homematic IP Legacy API (CCU port 2010) method response encoding value
|
||||
res = []byte(strings.Replace(string(res), "ISO-8859-1", "UTF-8", 1))
|
||||
|
||||
// correct XML-RPC-Schnittstelle (CCU port 2001) method response encoding value
|
||||
res = []byte(strings.Replace(string(res), "iso-8859-1", "UTF-8", 1))
|
||||
// correct Homematic IP Legacy API (CCU port 2010) and XML-RPC-Schnittstelle (CCU port 2001) response encoding
|
||||
re := regexp.MustCompile("(?i)iso-8859-1")
|
||||
res = re.ReplaceAll(res, []byte("UTF-8"))
|
||||
|
||||
if err := xml.Unmarshal(res, &hmr); err != nil {
|
||||
return hmr, err
|
||||
}
|
||||
|
||||
return hmr, parseError(hmr)
|
||||
}
|
||||
|
||||
// getCCUFloat selects a float value of a CCU API response member
|
||||
func getFloatValue(res MethodResponse, valueName string) float64 {
|
||||
for _, m := range res.Member {
|
||||
if m.Name == valueName {
|
||||
return m.Value.CCUFloat
|
||||
}
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
// getCCUBool selects a float value of a CCU API response member
|
||||
func getBoolValue(res MethodResponse, valueName string) bool {
|
||||
for _, m := range res.Member {
|
||||
if m.Name == valueName {
|
||||
return m.Value.CCUBool
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// parseError checks on Homematic CCU error codes
|
||||
// Refer to page 30 of https://homematic-ip.com/sites/default/files/downloads/HM_XmlRpc_API.pdf
|
||||
func parseError(res MethodResponse) error {
|
||||
var faultCode int64
|
||||
var faultString string
|
||||
|
||||
faultCode = 0
|
||||
for _, f := range res.Fault {
|
||||
if f.Name == "faultCode" {
|
||||
faultCode = f.Value.CCUInt
|
||||
}
|
||||
if f.Name == "faultString" {
|
||||
faultString = f.Value.CCUString
|
||||
}
|
||||
}
|
||||
|
||||
if faultString == "" {
|
||||
faultString = "Unknown Homematic API Error"
|
||||
}
|
||||
|
||||
if faultCode != 0 {
|
||||
return fmt.Errorf("%s (%v)", faultString, faultCode)
|
||||
}
|
||||
|
||||
return nil
|
||||
return hmr, hmr.Error()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package homematic
|
|||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Homematic CCU XML-RPC types
|
||||
|
|
@ -34,6 +35,55 @@ type MethodResponse struct {
|
|||
Member []Member `xml:"params>param>value>struct>member,omitempty"`
|
||||
Fault []Member `xml:"fault>value>struct>member,omitempty"`
|
||||
}
|
||||
|
||||
// FloatValue selects a float value of a CCU API response member
|
||||
func (res *MethodResponse) FloatValue(val string) float64 {
|
||||
for _, m := range res.Member {
|
||||
if m.Name == val {
|
||||
return m.Value.CCUFloat
|
||||
}
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
// BoolValue selects a float value of a CCU API response member
|
||||
func (res *MethodResponse) BoolValue(val string) bool {
|
||||
for _, m := range res.Member {
|
||||
if m.Name == val {
|
||||
return m.Value.CCUBool
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// Error checks on Homematic CCU error codes
|
||||
// Refer to page 30 of https://homematic-ip.com/sites/default/files/downloads/HM_XmlRpc_API.pdf
|
||||
func (res *MethodResponse) Error() error {
|
||||
var faultCode int64
|
||||
var faultString string
|
||||
|
||||
for _, f := range res.Fault {
|
||||
if f.Name == "faultCode" {
|
||||
faultCode = f.Value.CCUInt
|
||||
}
|
||||
if f.Name == "faultString" {
|
||||
faultString = f.Value.CCUString
|
||||
}
|
||||
}
|
||||
|
||||
if faultCode != 0 {
|
||||
if faultString == "" {
|
||||
faultString = "unknown api error"
|
||||
}
|
||||
|
||||
return fmt.Errorf("%s (%v)", faultString, faultCode)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type Value struct {
|
||||
XMLName xml.Name `xml:"value"`
|
||||
CCUString string `xml:",chardata"`
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue