From 477a92259c2f47f9d842f3a99276ade4ff6e3558 Mon Sep 17 00:00:00 2001 From: andig Date: Sat, 28 Oct 2023 17:35:06 +0200 Subject: [PATCH] Mqtt: publish complex values (#10529) --- server/mqtt.go | 76 +++++++++++++++++++++++++++----------------------- 1 file changed, 41 insertions(+), 35 deletions(-) diff --git a/server/mqtt.go b/server/mqtt.go index 91e9903f4..733dbcf74 100644 --- a/server/mqtt.go +++ b/server/mqtt.go @@ -63,6 +63,45 @@ func (m *MQTT) encode(v interface{}) string { } } +func (m *MQTT) publishComplex(topic string, retained bool, payload interface{}) { + if payload == nil { + m.publishSingleValue(topic, retained, payload) + return + } + + switch typ := reflect.TypeOf(payload); typ.Kind() { + case reflect.Slice: + // publish count + val := reflect.ValueOf(payload) + m.publishSingleValue(topic, retained, val.Len()) + + // loop slice + for i := 0; i < val.Len(); i++ { + m.publishComplex(fmt.Sprintf("%s/%d", topic, i+1), retained, val.Index(i).Interface()) + } + + case reflect.Map: + // loop map + for iter := reflect.ValueOf(m).MapRange(); iter.Next(); { + k := iter.Key().String() + m.publishComplex(fmt.Sprintf("%s/%s", topic, k), retained, iter.Value().Interface()) + } + + case reflect.Struct: + val := reflect.ValueOf(payload) + typ := val.Type() + + // loop struct + for i := 0; i < typ.NumField(); i++ { + n := typ.Field(i).Name + m.publishComplex(fmt.Sprintf("%s/%s", topic, strings.ToLower(n[:1])+n[1:]), retained, val.Field(i).Interface()) + } + + default: + m.publishSingleValue(topic, retained, payload) + } +} + func (m *MQTT) publishSingleValue(topic string, retained bool, payload interface{}) { token := m.Handler.Client.Publish(topic, m.Handler.Qos, retained, m.encode(payload)) go m.Handler.WaitForToken("send", topic, token) @@ -78,43 +117,10 @@ func (m *MQTT) publish(topic string, retained bool, payload interface{}) { } // publish sum value - payload = total + m.publishSingleValue(topic, retained, total) } - // publish slices of structs as sub topics - if payload != nil { - if typ := reflect.TypeOf(payload); typ.Kind() == reflect.Slice && typ.Elem().Kind() == reflect.Struct { - val := reflect.ValueOf(payload) - - // loop slice - for i := 0; i < val.Len(); i++ { - val := val.Index(i) - typ := val.Type() - - // loop struct - for j := 0; j < typ.NumField(); j++ { - n := typ.Field(j).Name - v := val.Field(j).Interface() - m.publishSingleValue(fmt.Sprintf("%s/%d/%s", topic, i+1, strings.ToLower(n[:1])+n[1:]), retained, v) - } - } - - // publish count - payload = val.Len() - } - } - - // publish vehicles - if slice, ok := payload.([]string); ok && strings.HasSuffix(topic, "vehicles") { - // publish count - payload = len(slice) - - for i, v := range slice { - m.publishSingleValue(fmt.Sprintf("%s/%d", topic, i+1), retained, v) - } - } - - m.publishSingleValue(topic, retained, payload) + m.publishComplex(topic, retained, payload) } func (m *MQTT) listenSetters(topic string, site site.API, lp loadpoint.API) {