diff --git a/meter/homematic/connection.go b/meter/homematic/connection.go
index 31775e2550..30f0f854d2 100644
--- a/meter/homematic/connection.go
+++ b/meter/homematic/connection.go
@@ -84,10 +84,6 @@ func (c *Connection) XmlCmd(method, channel string, values ...Param) (MethodResp
return hmr, err
}
- if strings.Contains(string(res), "faultCode") {
- return hmr, fmt.Errorf("ccu: %s", string(res))
- }
-
// correct Homematic IP Legacy API (CCU port 2010) method response encoding value
res = []byte(strings.Replace(string(res), "ISO-8859-1", "UTF-8", 1))
@@ -98,7 +94,7 @@ func (c *Connection) XmlCmd(method, channel string, values ...Param) (MethodResp
return hmr, err
}
- return hmr, err
+ return hmr, parseError(hmr)
}
// Initialze CCU methods via system.listMethods call
@@ -149,3 +145,26 @@ func (c *Connection) GridTotalEnergy() (float64, error) {
res, err := c.XmlCmd("getValue", c.MeterChannel, Param{CCUString: "IEC_ENERGY_COUNTER"})
return res.Value.CCUFloat, err
}
+
+// 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 faultCode != 0 {
+ return fmt.Errorf("%s (%v)", faultString, faultCode)
+ }
+
+ return nil
+}
diff --git a/meter/homematic/types.go b/meter/homematic/types.go
index f9ed85b508..ee0d84caba 100644
--- a/meter/homematic/types.go
+++ b/meter/homematic/types.go
@@ -21,7 +21,19 @@ type MethodCall struct {
Params []Param `xml:"params>param,omitempty"`
}
+type Member struct {
+ Name string `xml:"name,omitempty"`
+ Value FaultValue `xml:"value,omitempty"`
+}
+
+type FaultValue struct {
+ XMLName xml.Name `xml:"value"`
+ CCUString string `xml:",chardata"`
+ CCUInt int64 `xml:"i4,omitempty"`
+}
+
type MethodResponse struct {
XMLName xml.Name `xml:"methodResponse"`
Value Param `xml:"params>param,omitempty"`
+ Fault []Member `xml:"fault>value>struct>member,omitempty"`
}
diff --git a/meter/homematic/types_test.go b/meter/homematic/types_test.go
new file mode 100644
index 0000000000..9d99924819
--- /dev/null
+++ b/meter/homematic/types_test.go
@@ -0,0 +1,37 @@
+package homematic
+
+import (
+ "encoding/xml"
+ "strings"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+// Test MethodResponse response
+func TestUnmarshalMethodResponse(t *testing.T) {
+
+ {
+ // Double response test
+ var res MethodResponse
+
+ xmlstr := `20698.0`
+ assert.NoError(t, xml.Unmarshal([]byte(strings.Replace(string(xmlstr), "ISO-8859-1", "UTF-8", 1)), &res))
+
+ assert.Equal(t, float64(20698), res.Value.CCUFloat)
+ }
+
+ {
+ // Faulty response test
+ var res MethodResponse
+
+ xmlstr := `faultCode-2faultStringInvalid device`
+ assert.NoError(t, xml.Unmarshal([]byte(strings.Replace(string(xmlstr), "ISO-8859-1", "UTF-8", 1)), &res))
+
+ assert.Equal(t, "faultCode", res.Fault[0].Name)
+ assert.Equal(t, int64(-2), res.Fault[0].Value.CCUInt)
+ assert.Equal(t, "faultString", res.Fault[1].Name)
+ assert.Equal(t, "Invalid device", res.Fault[1].Value.CCUString)
+ }
+
+}