diff --git a/attic/z2m/z2m.go b/attic/z2m/z2m.go index d5e44fc..4dbe862 100644 --- a/attic/z2m/z2m.go +++ b/attic/z2m/z2m.go @@ -1,113 +1,107 @@ package z2m import ( - "fmt" - "log" - "time" - "strings" - "reflect" - "encoding/json" - "udi/config" - "udi/handlers/handler" - "udi/database" - "udi/handlers/z2m/models/wsdcgq11lm" - "udi/handlers/z2m/models/wsdcgq01lm" - "udi/handlers/z2m/models/gs361ah04" + "encoding/json" + "fmt" + "log" + "reflect" + "strings" + "time" + "udi/config" + "udi/database" + "udi/handlers/handler" + "udi/handlers/z2m/models/gs361ah04" + "udi/handlers/z2m/models/wsdcgq01lm" + "udi/handlers/z2m/models/wsdcgq11lm" ) - type Z2MHandler struct { - handler.CommonHandler - dbh *database.DatabaseHandle + handler.CommonHandler + dbh *database.DatabaseHandle } func parse(T any, payload string, variables *map[string]database.VariableType) error { - observationType := reflect.TypeOf(T) - observation := reflect.New(observationType).Interface() + observationType := reflect.TypeOf(T) + observation := reflect.New(observationType).Interface() - err := json.Unmarshal([]byte(payload), observation) - if err != nil { - return fmt.Errorf("Unable to parse payload into Observation struct: %v, %s", err, payload) - } + err := json.Unmarshal([]byte(payload), observation) + if err != nil { + return fmt.Errorf("Unable to parse payload into Observation struct: %v, %s", err, payload) + } - observationValue := reflect.ValueOf(observation).Elem() + observationValue := reflect.ValueOf(observation).Elem() - for i := 0; i < observationType.NumField(); i++ { - field := observationType.Field(i) - name := field.Name - unit := field.Tag.Get("unit") - value := observationValue.Field(i).Interface() + for i := 0; i < observationType.NumField(); i++ { + field := observationType.Field(i) + name := field.Name + unit := field.Tag.Get("unit") + value := observationValue.Field(i).Interface() - (*variables)[name] = database.VariableType { - Label: name, - Variable: "y", - Unit: unit, - Value: value, - } - } + (*variables)[name] = database.VariableType{ + Label: name, + Variable: "y", + Unit: unit, + Value: value, + } + } - - return nil + return nil } func New(id string, config config.HandlerConfigT) handler.Handler { - t := &Z2MHandler { - } - t.Id = id - t.dbh = database.NewDatabaseHandle() - log.Printf("Handler Z2M %d initialized", id) - return t + t := &Z2MHandler{} + t.Id = id + t.dbh = database.NewDatabaseHandle() + log.Printf("Handler Z2M %d initialized", id) + return t } func (self *Z2MHandler) Handle(message handler.MessageT) { - log.Printf("Handler Z2M %d processing %s -> %s", self.Id, message.Topic, message.Payload) + log.Printf("Handler Z2M %d processing %s -> %s", self.Id, message.Topic, message.Payload) - var measurement database.Measurement - measurement.Time = time.Now() + var measurement database.Measurement + measurement.Time = time.Now() + subTopics := strings.Split(message.Topic, "/") + deviceId := subTopics[1] + log.Printf("DeviceId: %s", deviceId) + device, err1 := self.dbh.GetDeviceByLabel(deviceId) + if err1 != nil { + self.Lost("Error when loading device", err1, message) + return + } + log.Printf("Device: %s", device) - subTopics := strings.Split(message.Topic, "/") - deviceId := subTopics[1] - log.Printf("DeviceId: %s", deviceId) - device, err1 := self.dbh.GetDeviceByLabel(deviceId) - if err1 != nil { - self.Lost("Error when loading device", err1, message) - return - } - log.Printf("Device: %s", device) + measurement.Application = device.Application.Label + measurement.Device = device.Attributes["Label"].(string) - measurement.Application = device.Application.Label - measurement.Device = device.Attributes["Label"].(string) + var T any + switch device.DeviceType.ModelIdentifier { + case "WSDCGQ11LM": + T = wsdcgq11lm.Observation{} + case "WSDCGQ01LM": + T = wsdcgq01lm.Observation{} + case "GS361A-H04": + T = gs361ah04.Observation{} + default: + self.Lost(fmt.Sprintf("No parser found for %s", device.DeviceType.ModelIdentifier), nil, message) + return + } - var T any - switch device.DeviceType.ModelIdentifier { - case "WSDCGQ11LM": - T = wsdcgq11lm.Observation{} - case "WSDCGQ01LM": - T = wsdcgq01lm.Observation{} - case "GS361A-H04": - T = gs361ah04.Observation{} - default: - self.Lost(fmt.Sprintf("No parser found for %s", device.DeviceType.ModelIdentifier), nil, message) - return - } + measurement.Values = make(map[string]database.VariableType) + measurement.Attributes = make(map[string]interface{}) + err3 := parse(T, + message.Payload, + &(measurement.Values)) + if err3 != nil { + self.Lost("Model parser failed", err3, message) + return + } - measurement.Values = make(map[string]database.VariableType) - measurement.Attributes = make(map[string]interface{}) - err3 := parse(T, - message.Payload, - &(measurement.Values)) - if err3 != nil { - self.Lost("Model parser failed", err3, message) - return - } - - measurement.Attributes["Status"] = "ok" - measurement.Attributes["DeviceId"] = deviceId - measurement.Attributes["DeviceModel"] = device.DeviceType.ModelIdentifier - log.Printf("Prepared measurement item: %s", measurement) - self.dbh.StoreMeasurement(&measurement) - self.S() + measurement.Attributes["Status"] = "ok" + measurement.Attributes["DeviceId"] = deviceId + measurement.Attributes["DeviceModel"] = device.DeviceType.ModelIdentifier + log.Printf("Prepared measurement item: %s", measurement) + self.dbh.StoreMeasurement(&measurement) + self.S() } - - diff --git a/src/udi/config-test-2.json b/src/udi/config-test-2.json new file mode 100644 index 0000000..32d348d --- /dev/null +++ b/src/udi/config-test-2.json @@ -0,0 +1,135 @@ +{ + "mqtt": { + "broker": "mqtt://172.23.1.102:1883", + "tlsEnable": "false" + }, + "topicMappings": [ + { + "topics": [ "snmp" ], + "handler": "PREP", + "id": "SNMP", + "config": { + "attributes": { + } + } + }, + { + "topics": [ "tsm" ], + "handler": "PREP", + "id": "TSM", + "config": { + "attributes": { + } + } + }, + { + "topics": [ "dt1/ai/periodic/1" ], + "handler": "DT1T", + "id": "DT1T.0", + "config": { + "attributes": { + "Application": "Temperature Wago", + "Device": "Freezer", + "HardLow": "-273", + "SoftLow": "-50", + "SoftHigh": "20", + "HardHigh": "100" + } + } + }, + { + "topics": [ "dt1/ai/periodic/3" ], + "handler": "DT1T", + "id": "DT1T.1", + "config": { + "attributes": { + "Application": "Temperature Wago", + "Device": "Outdoor", + "HardLow": "-273", + "SoftLow": "-60", + "SoftHigh": "60", + "HardHigh": "100" + } + } + }, + { + "topics": [ "IoT/PV/Values" ], + "handler": "PV", + "id": "PV", + "config": { + "databaseConnStr": "", + "attributes": { + } + } + }, + { + "topics": [ "IoT/Car/Values" ], + "handler": "Car", + "id": "Car", + "config": { + "databaseConnStr": "", + "attributes": { + } + } + }, + { + "topics": [ "IoT/MBGW3/Measurement" ], + "handler": "MBGW3", + "id": "MBGW3", + "config": { + "databaseConnStr": "", + "attributes": { + } + } + }, + { + "topics": [ "IoT/OneWireGW/Bus 1/#" ], + "handler": "SVER", + "id": "SVER0", + "config": { + "databaseConnStr": "", + "attributes": { + "application": "Temperature Heating", + "payloadRegex": "(\\d+(\\.\\d+)?)\\s*([^0-9\\s]\\S*)", + "deviceFrom": "topic", + "devicePart": "3", + "valueFrom": "payload", + "valuePart": "1", + "unitFrom": "payload", + "unitPart": "3" + } + } + }, + { + "topics": [ "shellyplusht/+/status/temperature:0" ], + "handler": "SVEJ", + "id": "SVEJ2", + "config": { + "databaseConnStr": "", + "attributes": { + "application": "Temperature Shelly Plus HT", + "deviceSelector": "T:1", + "valueSelector": "J:$.tC", + "unitSelector": "C:°C" + } + } + }, + { + "topics": [ "shellyplusht/+/status/humidity:0" ], + "handler": "SVEJ", + "id": "SVE4", + "config": { + "databaseConnStr": "", + "attributes": { + "application": "Humidity Shelly Plus HT", + "deviceSelector": "T:1", + "valueSelector": "J:$.rh", + "unitSelector": "C:%" + } + } + } + ], + "archiver": { + "dir": "./tmp/udi" + } +}