From 72757b5ae7885861c8ee4cdc4b4e9cdf85fb43aa Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Fri, 12 Jul 2024 11:16:37 +0200 Subject: [PATCH 01/36] add hottis threeway thermometer --- src/udi/config-test-ttn.json | 2 +- .../hottisThreeWayThermometer.go | 74 +++++++++++++++++++ src/udi/handlers/ttn/ttn.go | 3 + 3 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 src/udi/handlers/ttn/models/hottisThreeWayThermometer/hottisThreeWayThermometer.go diff --git a/src/udi/config-test-ttn.json b/src/udi/config-test-ttn.json index 78ff7a3..b8229a9 100644 --- a/src/udi/config-test-ttn.json +++ b/src/udi/config-test-ttn.json @@ -1,7 +1,7 @@ { "mqtt": { "broker": "ssl://eu1.cloud.thethings.network:8883", - "username": "de-hottis-lora-test1@ttn", + "username": "de-hottis-saerbeck-monitoring@ttn", "tlsEnable": "true" }, "topicMappings": [ diff --git a/src/udi/handlers/ttn/models/hottisThreeWayThermometer/hottisThreeWayThermometer.go b/src/udi/handlers/ttn/models/hottisThreeWayThermometer/hottisThreeWayThermometer.go new file mode 100644 index 0000000..a1f7a14 --- /dev/null +++ b/src/udi/handlers/ttn/models/hottisThreeWayThermometer/hottisThreeWayThermometer.go @@ -0,0 +1,74 @@ +package hottisThreeWayThermometer + +import ( + "log" + "fmt" + "bytes" + "encoding/base64" + "encoding/binary" + "udi/database" +) + +type hottisThreeWayThermometerValues struct { + Status uint8 +// Battery uint16 + SensorAddress1 uint64 + Value1 int32 + SensorAddress2 uint64 + Value2 int32 + SensorAddress3 uint64 + Value3 int32 +} + + +func Parse(fPort int, _ []byte, frmPayload string, variables *map[string]database.VariableType, attributes *map[string]interface{}, _ *database.Device) error { + if fPort != 2 { + return fmt.Errorf("Unexpected fPort %d", fPort) + } + + b, err := base64.StdEncoding.DecodeString(frmPayload) + if err != nil { + return fmt.Errorf("Unable to base64-decode payload: %v", err) + } + + var values hottisThreeWayThermometerValues + err = binary.Read(bytes.NewReader(b), binary.LittleEndian, &values) + if err != nil { + return fmt.Errorf("Unable to cast into struct: %v", err) + } + + var value1 float32 = float32(values.Value1) / 128.0 + var value2 float32 = float32(values.Value2) / 128.0 + var value3 float32 = float32(values.Value3) / 128.0 + + //log.Printf("Status: %d, Battery: %d", values.Status, values.Battery); + log.Printf("Status: %d", values.Status); + log.Printf("Sensor1: Addr: %d, Value: %f", values.SensorAddress1, value1); + log.Printf("Sensor2: Addr: %d, Value: %f", values.SensorAddress2, value2); + log.Printf("Sensor3: Addr: %d, Value: %f", values.SensorAddress3, value3); + + (*variables)["Temperature1"] = database.VariableType { + Label: "Temperature1", + Variable: "Temperature", + Unit: "°C", + Value: value1, + } + (*variables)["Temperature2"] = database.VariableType { + Label: "Temperature2", + Variable: "Temperature", + Unit: "°C", + Value: value2, + } + (*variables)["Temperature3"] = database.VariableType { + Label: "Temperature3", + Variable: "Temperature", + Unit: "°C", + Value: value3, + } + + (*attributes)["Status"] = values.Status + (*attributes)["SensorAddress1"] = values.SensorAddress1 + (*attributes)["SensorAddress2"] = values.SensorAddress2 + (*attributes)["SensorAddress3"] = values.SensorAddress3 + return nil +} diff --git a/src/udi/handlers/ttn/ttn.go b/src/udi/handlers/ttn/ttn.go index eb0ea3a..5731fd7 100644 --- a/src/udi/handlers/ttn/ttn.go +++ b/src/udi/handlers/ttn/ttn.go @@ -14,6 +14,7 @@ import ( "udi/handlers/ttn/models/draginoLsn50" "udi/handlers/ttn/models/rawPayloadPrinter" "udi/handlers/ttn/models/hottisScd30" + "udi/handlers/ttn/models/hottisThreeWayThermometer" "udi/database" ) @@ -152,6 +153,8 @@ func (self *TTNHandler) Handle(message handler.MessageT) { parser = rawPayloadPrinter.Parse case "hottis-scd30": parser = hottisScd30.Parse + case "hottis-threeway-thermometer": + parser = hottisThreeWayThermometer.Parse default: self.Lost(fmt.Sprintf("No parser found for %s", device.DeviceType.ModelIdentifier), nil, message) return From d970151aca6c7dbc2b4c4bb5f59c53ecc90191ce Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Fri, 12 Jul 2024 12:03:35 +0200 Subject: [PATCH 02/36] new builder image --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 23e1014..082e4fb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.21-alpine as builder +FROM golang:1.22.5-alpine3.20 as builder RUN mkdir -p /go/src COPY ./src/ /go/src From a5856f08ab868347e7ef8060663f58cbbd88c2db Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Fri, 12 Jul 2024 12:52:57 +0200 Subject: [PATCH 03/36] increase some module version according to trivy results --- src/udi/go.mod | 13 +++++++------ src/udi/go.sum | 24 ++++++++++-------------- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/src/udi/go.mod b/src/udi/go.mod index 61428b4..a5403ac 100644 --- a/src/udi/go.mod +++ b/src/udi/go.mod @@ -1,24 +1,25 @@ module udi -go 1.21.3 +go 1.22.3 require ( github.com/eclipse/paho.mqtt.golang v1.4.3 github.com/google/uuid v1.4.0 github.com/oliveagle/jsonpath v0.0.0-20180606110733-2e52cf6e6852 - gorm.io/driver/postgres v1.5.4 - gorm.io/gorm v1.25.5 + gorm.io/driver/postgres v1.5.9 + gorm.io/gorm v1.25.11 ) require ( github.com/gorilla/websocket v1.5.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect - github.com/jackc/pgx/v5 v5.4.3 // indirect + github.com/jackc/pgx/v5 v5.5.5 // indirect + github.com/jackc/puddle/v2 v2.2.1 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect - golang.org/x/crypto v0.19.0 // indirect - golang.org/x/net v0.20.0 // indirect + golang.org/x/crypto v0.17.0 // indirect + golang.org/x/net v0.10.0 // indirect golang.org/x/sync v0.1.0 // indirect golang.org/x/text v0.14.0 // indirect ) diff --git a/src/udi/go.sum b/src/udi/go.sum index 81a005b..e74b578 100644 --- a/src/udi/go.sum +++ b/src/udi/go.sum @@ -11,8 +11,10 @@ github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsI github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= -github.com/jackc/pgx/v5 v5.4.3 h1:cxFyXhxlvAifxnkKKdlxv8XqUf59tDlYjnV5YYfsJJY= -github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA= +github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw= +github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A= +github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk= +github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= @@ -26,25 +28,19 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= -golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= -golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= +golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gorm.io/driver/postgres v1.5.4 h1:Iyrp9Meh3GmbSuyIAGyjkN+n9K+GHX9b9MqsTL4EJCo= -gorm.io/driver/postgres v1.5.4/go.mod h1:Bgo89+h0CRcdA33Y6frlaHHVuTdOf87pmyzwW9C/BH0= -gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls= -gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= +gorm.io/driver/postgres v1.5.9 h1:DkegyItji119OlcaLjqN11kHoUgZ/j13E0jkJZgD6A8= +gorm.io/driver/postgres v1.5.9/go.mod h1:DX3GReXH+3FPWGrrgffdvCk3DQ1dwDPdmbenSkweRGI= +gorm.io/gorm v1.25.11 h1:/Wfyg1B/je1hnDx3sMkX+gAlxrlZpn6X0BXRlwXlvHg= +gorm.io/gorm v1.25.11/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ= From 532e12a9a61ea63c7bf6ae841f637ef3204c92d9 Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Fri, 12 Jul 2024 14:22:37 +0200 Subject: [PATCH 04/36] increase some more module version according to trivy results --- src/udi/go.mod | 2 +- src/udi/go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/udi/go.mod b/src/udi/go.mod index a5403ac..6887d05 100644 --- a/src/udi/go.mod +++ b/src/udi/go.mod @@ -19,7 +19,7 @@ require ( github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect golang.org/x/crypto v0.17.0 // indirect - golang.org/x/net v0.10.0 // indirect + golang.org/x/net v0.17.0 // indirect golang.org/x/sync v0.1.0 // indirect golang.org/x/text v0.14.0 // indirect ) diff --git a/src/udi/go.sum b/src/udi/go.sum index e74b578..e4bea0b 100644 --- a/src/udi/go.sum +++ b/src/udi/go.sum @@ -30,8 +30,8 @@ github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKs github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= -golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= From 79d64223790f2f1870964dc7535fb6ef809b7197 Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Fri, 12 Jul 2024 15:42:38 +0200 Subject: [PATCH 05/36] new query and some updates --- queries/saerbeck.sql | 12 ++++++++++++ src/udi/go.mod | 8 ++++---- src/udi/go.sum | 16 ++++++++-------- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/queries/saerbeck.sql b/queries/saerbeck.sql index f0dffcc..8bf6ad2 100644 --- a/queries/saerbeck.sql +++ b/queries/saerbeck.sql @@ -9,3 +9,15 @@ create or replace view badesee_temperature_v as from measurements where application = 'de-hottis-saerbeck-monitoring' and device = 'eui-a84041318187ec13'; + +create or replace view cubecell_threeway_temperature_v as + select time, + cast(values->'Temperature1'->>'value' as float) as Temp1, + cast(values->'Temperature2'->>'value' as float) as Temp2, + cast(values->'Temperature3'->>'value' as float) as Temp3, + device + from measurements + where application = 'de-hottis-saerbeck-monitoring' and + device = 'eui-70b3d57ed0068fa4'; + + diff --git a/src/udi/go.mod b/src/udi/go.mod index 6887d05..4c19480 100644 --- a/src/udi/go.mod +++ b/src/udi/go.mod @@ -18,8 +18,8 @@ require ( github.com/jackc/puddle/v2 v2.2.1 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect - golang.org/x/crypto v0.17.0 // indirect - golang.org/x/net v0.17.0 // indirect - golang.org/x/sync v0.1.0 // indirect - golang.org/x/text v0.14.0 // indirect + golang.org/x/crypto v0.25.0 // indirect + golang.org/x/net v0.27.0 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/text v0.16.0 // indirect ) diff --git a/src/udi/go.sum b/src/udi/go.sum index e4bea0b..9ea105e 100644 --- a/src/udi/go.sum +++ b/src/udi/go.sum @@ -28,14 +28,14 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= +golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= From 64f74c60f3864217d6c0a1c0a1faa9ce87074566 Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Wed, 31 Jul 2024 15:29:54 +0200 Subject: [PATCH 06/36] battery --- .../hottisThreeWayThermometer.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/udi/handlers/ttn/models/hottisThreeWayThermometer/hottisThreeWayThermometer.go b/src/udi/handlers/ttn/models/hottisThreeWayThermometer/hottisThreeWayThermometer.go index a1f7a14..9009355 100644 --- a/src/udi/handlers/ttn/models/hottisThreeWayThermometer/hottisThreeWayThermometer.go +++ b/src/udi/handlers/ttn/models/hottisThreeWayThermometer/hottisThreeWayThermometer.go @@ -11,7 +11,7 @@ import ( type hottisThreeWayThermometerValues struct { Status uint8 -// Battery uint16 + Battery uint16 SensorAddress1 uint64 Value1 int32 SensorAddress2 uint64 @@ -37,16 +37,24 @@ func Parse(fPort int, _ []byte, frmPayload string, variables *map[string]databas return fmt.Errorf("Unable to cast into struct: %v", err) } + var battery float32 = float32(values.Battery) / 1000.0 var value1 float32 = float32(values.Value1) / 128.0 var value2 float32 = float32(values.Value2) / 128.0 var value3 float32 = float32(values.Value3) / 128.0 //log.Printf("Status: %d, Battery: %d", values.Status, values.Battery); log.Printf("Status: %d", values.Status); + log.Printf("Battery: %d, %f", values.Battery, battery); log.Printf("Sensor1: Addr: %d, Value: %f", values.SensorAddress1, value1); log.Printf("Sensor2: Addr: %d, Value: %f", values.SensorAddress2, value2); log.Printf("Sensor3: Addr: %d, Value: %f", values.SensorAddress3, value3); + (*variables)["Battery"] = database.VariableType { + Label: "Battery", + Variable: "Voltage", + Unit: "V", + Value: battery, + } (*variables)["Temperature1"] = database.VariableType { Label: "Temperature1", Variable: "Temperature", From f10f9afd8b313dfc6d300f7cc3fd337035b3ddb1 Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Wed, 31 Jul 2024 16:10:52 +0200 Subject: [PATCH 07/36] sensor labels --- .../hottisThreeWayThermometer.go | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/udi/handlers/ttn/models/hottisThreeWayThermometer/hottisThreeWayThermometer.go b/src/udi/handlers/ttn/models/hottisThreeWayThermometer/hottisThreeWayThermometer.go index 9009355..2c4789a 100644 --- a/src/udi/handlers/ttn/models/hottisThreeWayThermometer/hottisThreeWayThermometer.go +++ b/src/udi/handlers/ttn/models/hottisThreeWayThermometer/hottisThreeWayThermometer.go @@ -6,6 +6,7 @@ import ( "bytes" "encoding/base64" "encoding/binary" + "encoding/json" "udi/database" ) @@ -20,8 +21,25 @@ type hottisThreeWayThermometerValues struct { Value3 int32 } +func getSensorName(sensorsMap *map[string]string, uint64_t sensorAddress) string { + key := strconv.FormatUint(sensorAddress, 10) + if sensorName, exists := (*sensorsMap)[key]; exists { + return sensorName + } + return "Sensor" + key +} func Parse(fPort int, _ []byte, frmPayload string, variables *map[string]database.VariableType, attributes *map[string]interface{}, _ *database.Device) error { + sensorsMap := make(map[string]string) + sensorsJSON, ok := (*attributes)["Sensors"].(string) + if !ok { + return fmt.Errorf("Unable to load sensor map from attributes") + } + errJ := json.Unmarshal([]byte(sensorsJSON), &sensorsMap) + if errJ != nil { + return fmt.Errorf("Unable to parse sensor map: %v", errJ) + } + if fPort != 2 { return fmt.Errorf("Unexpected fPort %d", fPort) } @@ -56,19 +74,19 @@ func Parse(fPort int, _ []byte, frmPayload string, variables *map[string]databas Value: battery, } (*variables)["Temperature1"] = database.VariableType { - Label: "Temperature1", + Label: getSensorName(&sensorsMap, values.SensorAddress1), Variable: "Temperature", Unit: "°C", Value: value1, } (*variables)["Temperature2"] = database.VariableType { - Label: "Temperature2", + Label: getSensorName(&sensorsMap, values.SensorAddress2), Variable: "Temperature", Unit: "°C", Value: value2, } (*variables)["Temperature3"] = database.VariableType { - Label: "Temperature3", + Label: getSensorName(&sensorsMap, values.SensorAddress3), Variable: "Temperature", Unit: "°C", Value: value3, From 97c6a045d2734da7dce0de1cdcdb1a3e6f628995 Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Wed, 31 Jul 2024 16:14:29 +0200 Subject: [PATCH 08/36] sensor labels --- .../hottisThreeWayThermometer/hottisThreeWayThermometer.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/udi/handlers/ttn/models/hottisThreeWayThermometer/hottisThreeWayThermometer.go b/src/udi/handlers/ttn/models/hottisThreeWayThermometer/hottisThreeWayThermometer.go index 2c4789a..1c75f03 100644 --- a/src/udi/handlers/ttn/models/hottisThreeWayThermometer/hottisThreeWayThermometer.go +++ b/src/udi/handlers/ttn/models/hottisThreeWayThermometer/hottisThreeWayThermometer.go @@ -4,6 +4,7 @@ import ( "log" "fmt" "bytes" + "strconv" "encoding/base64" "encoding/binary" "encoding/json" @@ -21,7 +22,7 @@ type hottisThreeWayThermometerValues struct { Value3 int32 } -func getSensorName(sensorsMap *map[string]string, uint64_t sensorAddress) string { +func getSensorName(sensorsMap *map[string]string, sensorAddress uint64) string { key := strconv.FormatUint(sensorAddress, 10) if sensorName, exists := (*sensorsMap)[key]; exists { return sensorName From d6e7fa39495ac9639408ad9857f97e46410af492 Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Wed, 31 Jul 2024 16:22:39 +0200 Subject: [PATCH 09/36] sensor labels --- .../hottisThreeWayThermometer/hottisThreeWayThermometer.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/udi/handlers/ttn/models/hottisThreeWayThermometer/hottisThreeWayThermometer.go b/src/udi/handlers/ttn/models/hottisThreeWayThermometer/hottisThreeWayThermometer.go index 1c75f03..602c1c3 100644 --- a/src/udi/handlers/ttn/models/hottisThreeWayThermometer/hottisThreeWayThermometer.go +++ b/src/udi/handlers/ttn/models/hottisThreeWayThermometer/hottisThreeWayThermometer.go @@ -30,9 +30,9 @@ func getSensorName(sensorsMap *map[string]string, sensorAddress uint64) string { return "Sensor" + key } -func Parse(fPort int, _ []byte, frmPayload string, variables *map[string]database.VariableType, attributes *map[string]interface{}, _ *database.Device) error { +func Parse(fPort int, _ []byte, frmPayload string, variables *map[string]database.VariableType, attributes *map[string]interface{}, device *database.Device) error { sensorsMap := make(map[string]string) - sensorsJSON, ok := (*attributes)["Sensors"].(string) + sensorsJSON, ok := (*device).Attributes["Sensors"].(string) if !ok { return fmt.Errorf("Unable to load sensor map from attributes") } From 1d1942a4d3553b655e01a01f32560c42329d59cd Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Wed, 31 Jul 2024 16:26:51 +0200 Subject: [PATCH 10/36] sensor labels --- .../hottisThreeWayThermometer/hottisThreeWayThermometer.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/udi/handlers/ttn/models/hottisThreeWayThermometer/hottisThreeWayThermometer.go b/src/udi/handlers/ttn/models/hottisThreeWayThermometer/hottisThreeWayThermometer.go index 602c1c3..3dca107 100644 --- a/src/udi/handlers/ttn/models/hottisThreeWayThermometer/hottisThreeWayThermometer.go +++ b/src/udi/handlers/ttn/models/hottisThreeWayThermometer/hottisThreeWayThermometer.go @@ -34,7 +34,7 @@ func Parse(fPort int, _ []byte, frmPayload string, variables *map[string]databas sensorsMap := make(map[string]string) sensorsJSON, ok := (*device).Attributes["Sensors"].(string) if !ok { - return fmt.Errorf("Unable to load sensor map from attributes") + return fmt.Errorf("Unable to load sensor map from attributes: %s", (*device).Attributes) } errJ := json.Unmarshal([]byte(sensorsJSON), &sensorsMap) if errJ != nil { From 6f9327fdd685ce826255c16077fdbee899722199 Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Wed, 31 Jul 2024 16:36:17 +0200 Subject: [PATCH 11/36] sensor labels --- .../hottisThreeWayThermometer/hottisThreeWayThermometer.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/udi/handlers/ttn/models/hottisThreeWayThermometer/hottisThreeWayThermometer.go b/src/udi/handlers/ttn/models/hottisThreeWayThermometer/hottisThreeWayThermometer.go index 3dca107..bddb2d4 100644 --- a/src/udi/handlers/ttn/models/hottisThreeWayThermometer/hottisThreeWayThermometer.go +++ b/src/udi/handlers/ttn/models/hottisThreeWayThermometer/hottisThreeWayThermometer.go @@ -31,10 +31,11 @@ func getSensorName(sensorsMap *map[string]string, sensorAddress uint64) string { } func Parse(fPort int, _ []byte, frmPayload string, variables *map[string]database.VariableType, attributes *map[string]interface{}, device *database.Device) error { + deviceAttrs := (*device).Attributes sensorsMap := make(map[string]string) - sensorsJSON, ok := (*device).Attributes["Sensors"].(string) + sensorsJSON, ok := deviceAttrs["Sensors"].(string) if !ok { - return fmt.Errorf("Unable to load sensor map from attributes: %s", (*device).Attributes) + return fmt.Errorf("Unable to load sensor map from attributes") } errJ := json.Unmarshal([]byte(sensorsJSON), &sensorsMap) if errJ != nil { From f2f16c811ada449e77152a080d578b890b48538b Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Wed, 31 Jul 2024 16:50:54 +0200 Subject: [PATCH 12/36] still sensor labels --- .../hottisThreeWayThermometer.go | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/udi/handlers/ttn/models/hottisThreeWayThermometer/hottisThreeWayThermometer.go b/src/udi/handlers/ttn/models/hottisThreeWayThermometer/hottisThreeWayThermometer.go index bddb2d4..1f6ddb8 100644 --- a/src/udi/handlers/ttn/models/hottisThreeWayThermometer/hottisThreeWayThermometer.go +++ b/src/udi/handlers/ttn/models/hottisThreeWayThermometer/hottisThreeWayThermometer.go @@ -7,7 +7,6 @@ import ( "strconv" "encoding/base64" "encoding/binary" - "encoding/json" "udi/database" ) @@ -22,9 +21,9 @@ type hottisThreeWayThermometerValues struct { Value3 int32 } -func getSensorName(sensorsMap *map[string]string, sensorAddress uint64) string { +func getSensorName(sensorsMap *map[string]interface{}, sensorAddress uint64) string { key := strconv.FormatUint(sensorAddress, 10) - if sensorName, exists := (*sensorsMap)[key]; exists { + if sensorName, exists := (*sensorsMap)[key].(string); exists { return sensorName } return "Sensor" + key @@ -32,15 +31,7 @@ func getSensorName(sensorsMap *map[string]string, sensorAddress uint64) string { func Parse(fPort int, _ []byte, frmPayload string, variables *map[string]database.VariableType, attributes *map[string]interface{}, device *database.Device) error { deviceAttrs := (*device).Attributes - sensorsMap := make(map[string]string) - sensorsJSON, ok := deviceAttrs["Sensors"].(string) - if !ok { - return fmt.Errorf("Unable to load sensor map from attributes") - } - errJ := json.Unmarshal([]byte(sensorsJSON), &sensorsMap) - if errJ != nil { - return fmt.Errorf("Unable to parse sensor map: %v", errJ) - } + sensorsMap := deviceAttrs["Sensors"].(map[string]interface{}) if fPort != 2 { return fmt.Errorf("Unexpected fPort %d", fPort) From 3d68aa0e6189786e5f45391e33cfca29a0d5b80c Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Mon, 11 Nov 2024 12:43:29 +0100 Subject: [PATCH 13/36] prepare changes --- src/udi/ENVDB.uditest | 4 +- src/udi/config-test.json | 102 ++--------------------------------- src/udi/database/database.go | 22 ++++++++ 3 files changed, 28 insertions(+), 100 deletions(-) diff --git a/src/udi/ENVDB.uditest b/src/udi/ENVDB.uditest index ad5498a..bdbe407 100644 --- a/src/udi/ENVDB.uditest +++ b/src/udi/ENVDB.uditest @@ -1,6 +1,6 @@ -PGUSER="uditest" +PGUSER="udi-hottis" PGHOST=`kubectl get services traefik -n system -o jsonpath="{.status.loadBalancer.ingress[0].ip}"` -PGPASSWORD=`kubectl get secrets uditest-db-cred -n udi-test -o jsonpath="{.data.PGPASSWORD}" | base64 --decode` +PGPASSWORD=`kubectl get secrets default-udi-db-cred -n udi -o jsonpath="{.data.PGPASSWORD}" | base64 --decode` PGSSLMODE=require PGDATABASE="uditest" export PGUSER PGHOST PGPASSWORD PGSSLMODE PGDATABASE diff --git a/src/udi/config-test.json b/src/udi/config-test.json index ecc68f5..d31c720 100644 --- a/src/udi/config-test.json +++ b/src/udi/config-test.json @@ -4,72 +4,6 @@ "tlsEnable": "false" }, "topicMappings": [ - { - "topics": [ "IoT/PV/Values" ], - "handler": "PV", - "id": "PV", - "config": { - "attributes": { - } - } - }, - { - "topics": [ "IoT/MBGW3/Measurement" ], - "handler": "MBGW3", - "id": "MBGW3", - "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/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": [ "NR/Multisensor/+/Temperatur" ], "handler": "SVEJ", @@ -85,46 +19,18 @@ } }, { - "topics": [ "NR/Multisensor/+/Feuchte" ], + "topics": [ "zigbee2mqtt/+" ], "handler": "SVEJ", "id": "SVEJ1", "config": { "databaseConnStr": "", "attributes": { - "application": "Humidity Multisensor", - "deviceSelector": "T:2", - "valueSelector": "J:$.CurrentRelativeHumidity", - "unitSelector": "C:%" - } - } - }, - { - "topics": [ "shellyplusht/+/status/temperature:0" ], - "handler": "SVEJ", - "id": "SVEJ2", - "config": { - "databaseConnStr": "", - "attributes": { - "application": "Temperature Shelly Plus HT", - "deviceSelector": "T:1", - "valueSelector": "J:$.tC", + "application": "Temperature Multisensor", + "deviceSelector": "L:1", + "valueSelector": "J:$.temperature", "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": { diff --git a/src/udi/database/database.go b/src/udi/database/database.go index c04f804..8374e31 100644 --- a/src/udi/database/database.go +++ b/src/udi/database/database.go @@ -70,5 +70,27 @@ func (self *DatabaseHandle) GetDeviceByLabelAndApplication(applicationLabel stri return &device, nil } +func (self *DatabaseHandle) GetDeviceByLabel(deviceLabel string) (*Device, error) { + if ! self.initialized { + err := fmt.Errorf("Database connection not initialized") + return nil, err + } + + var device Device + result := self.dbh. + Preload("Application"). + Preload("DeviceType"). + Where("devices.label = ?", deviceLabel). + First(&device) + + if result.Error != nil { + err := fmt.Errorf("Query failed: %s", result.Error) + return nil, err + } + + return &device, nil +} + + From a55f80b7d93c8dd11945583dd6b81522d80a27fe Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Mon, 11 Nov 2024 12:44:02 +0100 Subject: [PATCH 14/36] saerbeck query --- queries/saerbeck.sql | 30 ++++++++++++++++++++++----- src/udi/handlers/svej/svej.go | 38 ++++++++++++++++++++++++++++------- 2 files changed, 56 insertions(+), 12 deletions(-) diff --git a/queries/saerbeck.sql b/queries/saerbeck.sql index 8bf6ad2..e9d05ab 100644 --- a/queries/saerbeck.sql +++ b/queries/saerbeck.sql @@ -10,14 +10,34 @@ create or replace view badesee_temperature_v as where application = 'de-hottis-saerbeck-monitoring' and device = 'eui-a84041318187ec13'; -create or replace view cubecell_threeway_temperature_v as +create or replace view cubecell_threeway_temperature2_v as select time, - cast(values->'Temperature1'->>'value' as float) as Temp1, - cast(values->'Temperature2'->>'value' as float) as Temp2, - cast(values->'Temperature3'->>'value' as float) as Temp3, - device + cast(values->'Temperature2'->>'value' as float) as value, + values->'Temperature2'->>'label' as label from measurements where application = 'de-hottis-saerbeck-monitoring' and device = 'eui-70b3d57ed0068fa4'; +create or replace view cubecell_threeway_temperature1_v as + select time, + cast(values->'Temperature1'->>'value' as float) as value, + values->'Temperature1'->>'label' as label + from measurements + where application = 'de-hottis-saerbeck-monitoring' and + device = 'eui-70b3d57ed0068fa4'; +create or replace view cubecell_threeway_temperature3_v as + select time, + cast(values->'Temperature3'->>'value' as float) as value, + values->'Temperature3'->>'label' as label + from measurements + where application = 'de-hottis-saerbeck-monitoring' and + device = 'eui-70b3d57ed0068fa4'; + +create or replace view cubecell_threeway_battery_v as + select time, + cast(values->'Battery'->>'value' as float) as value, + values->'Battery'->>'label' as label + from measurements + where application = 'de-hottis-saerbeck-monitoring' and + device = 'eui-70b3d57ed0068fa4'; diff --git a/src/udi/handlers/svej/svej.go b/src/udi/handlers/svej/svej.go index 986d3c5..af6f19d 100644 --- a/src/udi/handlers/svej/svej.go +++ b/src/udi/handlers/svej/svej.go @@ -79,16 +79,18 @@ func New(id string, config config.HandlerConfigT) handler.Handler { return t } -func extractionHelper(subTopics []string, jPayload interface{}, selector string, jp *jsonpath.Compiled) (string, error) { +func (self *SingleValueExtractorJsonpathHandler) ExtractionHelper(subTopics []string, jPayload interface{}, selector string, jp *jsonpath.Compiled) (string, error) { var res string switch selector[:2] { case "J:": + // extract using jsonpath from payload r, e := jp.Lookup(jPayload) if e != nil { return "", fmt.Errorf("jp.Lookup failed with %s", e) } res = fmt.Sprint(r) case "T:": + // T: extract from topic i, e := strconv.Atoi(selector[2:]) if e != nil { return "", fmt.Errorf("Atoi failed with %s", e) @@ -97,7 +99,26 @@ func extractionHelper(subTopics []string, jPayload interface{}, selector string, return "", fmt.Errorf("not enough subtopics") } res = subTopics[i] + case "L:": + // L: extract from topic and later match against devices table in database + i, e := strconv.Atoi(selector[2:]) + if e != nil { + return "", fmt.Errorf("Atoi failed with %s", e) + } + if i >= len(subTopics) { + return "", fmt.Errorf("not enough subtopics") + } + ext := subTopics[i] + lookup, err1b := self.dbh.GetDeviceByLabel(ext) + if err1b != nil { + log.Printf("ext lookup %s failed: %v", ext, err1b) + res = ext + } else { + log.Printf("ext: %s", lookup) + res = ext + } case "C:": + // use constant value res = selector[2:] default: return "", fmt.Errorf("Invalid selector: %s", selector[:2]) @@ -111,14 +132,14 @@ func (self *SingleValueExtractorJsonpathHandler) Handle(message handler.MessageT self.Lost("Handler is not marked as ready", nil, message) return } - //log.Printf("Handler SingleValueExtractorJsonpath %d processing %s -> %s", self.Id, message.Topic, message.Payload) + log.Printf("Handler SingleValueExtractorJsonpath %d processing %s -> %s", self.Id, message.Topic, message.Payload) var measurement database.Measurement measurement.Time = time.Now() measurement.Application = self.application subTopics := strings.Split(message.Topic, "/") - //log.Printf("Subtopics: %s", strings.Join(subTopics, ", ")) + log.Printf("Subtopics: %s", strings.Join(subTopics, ", ")) var jPayload interface{} err := json.Unmarshal([]byte(message.Payload), &jPayload) if err != nil { @@ -126,17 +147,20 @@ func (self *SingleValueExtractorJsonpathHandler) Handle(message handler.MessageT return } - device, err1 := extractionHelper(subTopics, jPayload, self.deviceSelector, self.deviceJsonpath) + device, err1 := self.ExtractionHelper(subTopics, jPayload, self.deviceSelector, self.deviceJsonpath) if err1 != nil { self.Lost("Device extraction failed", err1, message) return } - value, err2 := extractionHelper(subTopics, jPayload, self.valueSelector, self.valueJsonpath) + log.Printf("device: %s", device) + + value, err2 := self.ExtractionHelper(subTopics, jPayload, self.valueSelector, self.valueJsonpath) if err2 != nil { self.Lost("Value extraction failed", err2, message) return } - unit, err3 := extractionHelper(subTopics, jPayload, self.unitSelector, self.unitJsonpath) + + unit, err3 := self.ExtractionHelper(subTopics, jPayload, self.unitSelector, self.unitJsonpath) if err3 != nil { self.Lost("Unit extraction failed", err3, message) return @@ -152,7 +176,7 @@ func (self *SingleValueExtractorJsonpathHandler) Handle(message handler.MessageT measurement.Values = make(map[string]database.VariableType) measurement.Values["Value"] = variable - //log.Printf("Prepared measurement item: %s", measurement) + log.Printf("Prepared measurement item: %s", measurement) self.dbh.StoreMeasurement(&measurement) self.S() } From 830596f211adc69a57041bc3987b6774e4b0b8af Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Mon, 11 Nov 2024 12:45:47 +0100 Subject: [PATCH 15/36] saerbeck query --- queries/saerbeck.sql | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/queries/saerbeck.sql b/queries/saerbeck.sql index 8bf6ad2..e9d05ab 100644 --- a/queries/saerbeck.sql +++ b/queries/saerbeck.sql @@ -10,14 +10,34 @@ create or replace view badesee_temperature_v as where application = 'de-hottis-saerbeck-monitoring' and device = 'eui-a84041318187ec13'; -create or replace view cubecell_threeway_temperature_v as +create or replace view cubecell_threeway_temperature2_v as select time, - cast(values->'Temperature1'->>'value' as float) as Temp1, - cast(values->'Temperature2'->>'value' as float) as Temp2, - cast(values->'Temperature3'->>'value' as float) as Temp3, - device + cast(values->'Temperature2'->>'value' as float) as value, + values->'Temperature2'->>'label' as label from measurements where application = 'de-hottis-saerbeck-monitoring' and device = 'eui-70b3d57ed0068fa4'; +create or replace view cubecell_threeway_temperature1_v as + select time, + cast(values->'Temperature1'->>'value' as float) as value, + values->'Temperature1'->>'label' as label + from measurements + where application = 'de-hottis-saerbeck-monitoring' and + device = 'eui-70b3d57ed0068fa4'; +create or replace view cubecell_threeway_temperature3_v as + select time, + cast(values->'Temperature3'->>'value' as float) as value, + values->'Temperature3'->>'label' as label + from measurements + where application = 'de-hottis-saerbeck-monitoring' and + device = 'eui-70b3d57ed0068fa4'; + +create or replace view cubecell_threeway_battery_v as + select time, + cast(values->'Battery'->>'value' as float) as value, + values->'Battery'->>'label' as label + from measurements + where application = 'de-hottis-saerbeck-monitoring' and + device = 'eui-70b3d57ed0068fa4'; From 45e4cd793bb4a2d953b4d841c65a9b0b5bd47d67 Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Mon, 11 Nov 2024 15:00:04 +0100 Subject: [PATCH 16/36] static parse function --- .gitignore | 1 + src/udi/config-test.json | 8 +- src/udi/dispatcher/dispatcher.go | 3 + .../z2m/models/wsdcgq11lm/wsdcgq11lm.go | 48 ++++++++++++ src/udi/handlers/z2m/z2m.go | 74 +++++++++++++++++++ 5 files changed, 128 insertions(+), 6 deletions(-) create mode 100644 src/udi/handlers/z2m/models/wsdcgq11lm/wsdcgq11lm.go create mode 100644 src/udi/handlers/z2m/z2m.go diff --git a/.gitignore b/.gitignore index 6c5c728..bd0cd5f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ src/udi/udi +src/udi/main src/udi/migrate_schema tmp/ ENVDB diff --git a/src/udi/config-test.json b/src/udi/config-test.json index d31c720..e2eb4b4 100644 --- a/src/udi/config-test.json +++ b/src/udi/config-test.json @@ -20,15 +20,11 @@ }, { "topics": [ "zigbee2mqtt/+" ], - "handler": "SVEJ", - "id": "SVEJ1", + "handler": "Z2M", + "id": "Z2M", "config": { "databaseConnStr": "", "attributes": { - "application": "Temperature Multisensor", - "deviceSelector": "L:1", - "valueSelector": "J:$.temperature", - "unitSelector": "C:°C" } } } diff --git a/src/udi/dispatcher/dispatcher.go b/src/udi/dispatcher/dispatcher.go index d8e570e..ae8fbac 100644 --- a/src/udi/dispatcher/dispatcher.go +++ b/src/udi/dispatcher/dispatcher.go @@ -18,6 +18,7 @@ import "udi/handlers/svej" import "udi/handlers/dt1t" import "udi/handlers/locative" import "udi/handlers/snmp" +import "udi/handlers/z2m" var handlerMap map[string]handler.Handler = make(map[string]handler.Handler) @@ -50,6 +51,8 @@ func InitDispatcher() { factory = locative.New case "SNMP": factory = snmp.New + case "Z2M": + factory = z2m.New default: factory = nil log.Printf("No handler %s found, ignore mapping", mapping.Handler) diff --git a/src/udi/handlers/z2m/models/wsdcgq11lm/wsdcgq11lm.go b/src/udi/handlers/z2m/models/wsdcgq11lm/wsdcgq11lm.go new file mode 100644 index 0000000..d9f435b --- /dev/null +++ b/src/udi/handlers/z2m/models/wsdcgq11lm/wsdcgq11lm.go @@ -0,0 +1,48 @@ +package wsdcgq11lm + +import ( + //"log" + "fmt" + "reflect" + "encoding/json" + "udi/database" +) + +type Observation struct { + LinkQuality uint8 `unit:"" json:"linkquality"` + Battery uint8 `unit:"%" json:"battery"` + Humidity float32 `unit:"%H" json:"humidity"` + Pressure float32 `unit:"mbar" json:"pressure"` + Temperature float32 `unit:"°C" json:"temperature"` + Voltage uint16 `unit:"mV" json:"voltage"` +} + + +func Parse(payload string, variables *map[string]database.VariableType, attributes *map[string]interface{}, _ *database.Device) error { + var observation Observation + err := json.Unmarshal([]byte(payload), &observation) + if err != nil { + return fmt.Errorf("Unable to parse payload into Observation struct: %v, %s", err, payload) + } + + observationType := reflect.TypeOf(observation) + observationValue := reflect.ValueOf(observation) + + 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, + } + } + + (*attributes)["Status"] = "ok" + + return nil +} diff --git a/src/udi/handlers/z2m/z2m.go b/src/udi/handlers/z2m/z2m.go new file mode 100644 index 0000000..d9427f2 --- /dev/null +++ b/src/udi/handlers/z2m/z2m.go @@ -0,0 +1,74 @@ +package z2m + +import ( + "fmt" + "log" + "time" + "strings" + //"encoding/json" + "udi/config" + "udi/handlers/handler" + "udi/database" + "udi/handlers/z2m/models/wsdcgq11lm" +) + + +type Z2MHandler struct { + handler.CommonHandler + dbh *database.DatabaseHandle +} + + +func New(id string, config config.HandlerConfigT) handler.Handler { + t := &Z2MHandler { + } + t.Id = id + t.dbh = database.NewDatabaseHandle() + return t +} + +func (self *Z2MHandler) Handle(message handler.MessageT) { + log.Printf("Handler Z2M %d processing %s -> %s", self.Id, message.Topic, message.Payload) + + 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) + + measurement.Application = device.Application.Label + measurement.Device = device.Attributes["Label"].(string) + + var parser func(string, *map[string]database.VariableType, *map[string]interface{}, *database.Device) error + switch device.DeviceType.ModelIdentifier { + case "WSDCGQ11LM": + parser = wsdcgq11lm.Parse + 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 := parser(message.Payload, + &(measurement.Values), + &(measurement.Attributes), + device) + if err3 != nil { + self.Lost("Model parser failed", err3, message) + return + } + log.Printf("Prepared measurement item: %s", measurement) + self.dbh.StoreMeasurement(&measurement) + self.S() +} + + From 81e067e672da74d7b7e4f2495d2465d8a797fb19 Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Mon, 11 Nov 2024 16:11:32 +0100 Subject: [PATCH 17/36] seems to work now --- .../z2m/models/wsdcgq11lm/wsdcgq11lm.go | 37 ---------------- src/udi/handlers/z2m/z2m.go | 44 ++++++++++++++++--- 2 files changed, 37 insertions(+), 44 deletions(-) diff --git a/src/udi/handlers/z2m/models/wsdcgq11lm/wsdcgq11lm.go b/src/udi/handlers/z2m/models/wsdcgq11lm/wsdcgq11lm.go index d9f435b..db7ffd2 100644 --- a/src/udi/handlers/z2m/models/wsdcgq11lm/wsdcgq11lm.go +++ b/src/udi/handlers/z2m/models/wsdcgq11lm/wsdcgq11lm.go @@ -1,13 +1,5 @@ package wsdcgq11lm -import ( - //"log" - "fmt" - "reflect" - "encoding/json" - "udi/database" -) - type Observation struct { LinkQuality uint8 `unit:"" json:"linkquality"` Battery uint8 `unit:"%" json:"battery"` @@ -17,32 +9,3 @@ type Observation struct { Voltage uint16 `unit:"mV" json:"voltage"` } - -func Parse(payload string, variables *map[string]database.VariableType, attributes *map[string]interface{}, _ *database.Device) error { - var observation Observation - err := json.Unmarshal([]byte(payload), &observation) - if err != nil { - return fmt.Errorf("Unable to parse payload into Observation struct: %v, %s", err, payload) - } - - observationType := reflect.TypeOf(observation) - observationValue := reflect.ValueOf(observation) - - 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, - } - } - - (*attributes)["Status"] = "ok" - - return nil -} diff --git a/src/udi/handlers/z2m/z2m.go b/src/udi/handlers/z2m/z2m.go index d9427f2..a9dc3c5 100644 --- a/src/udi/handlers/z2m/z2m.go +++ b/src/udi/handlers/z2m/z2m.go @@ -5,7 +5,8 @@ import ( "log" "time" "strings" - //"encoding/json" + "reflect" + "encoding/json" "udi/config" "udi/handlers/handler" "udi/database" @@ -18,6 +19,35 @@ type Z2MHandler struct { dbh *database.DatabaseHandle } +func parse(T any, payload string, variables *map[string]database.VariableType, attributes *map[string]interface{}) error { + 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) + } + + 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() + + (*variables)[name] = database.VariableType { + Label: name, + Variable: "y", + Unit: unit, + Value: value, + } + } + + (*attributes)["Status"] = "ok" + + return nil +} func New(id string, config config.HandlerConfigT) handler.Handler { t := &Z2MHandler { @@ -47,10 +77,10 @@ func (self *Z2MHandler) Handle(message handler.MessageT) { measurement.Application = device.Application.Label measurement.Device = device.Attributes["Label"].(string) - var parser func(string, *map[string]database.VariableType, *map[string]interface{}, *database.Device) error + var T any switch device.DeviceType.ModelIdentifier { case "WSDCGQ11LM": - parser = wsdcgq11lm.Parse + T = wsdcgq11lm.Observation{} default: self.Lost(fmt.Sprintf("No parser found for %s", device.DeviceType.ModelIdentifier), nil, message) return @@ -58,10 +88,10 @@ func (self *Z2MHandler) Handle(message handler.MessageT) { measurement.Values = make(map[string]database.VariableType) measurement.Attributes = make(map[string]interface{}) - err3 := parser(message.Payload, - &(measurement.Values), - &(measurement.Attributes), - device) + err3 := parse(T, + message.Payload, + &(measurement.Values), + &(measurement.Attributes)) if err3 != nil { self.Lost("Model parser failed", err3, message) return From b6a7447cb30da6110f4e44baf5b3ce6f92b9e68c Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Mon, 11 Nov 2024 16:13:04 +0100 Subject: [PATCH 18/36] fix --- src/udi/handlers/svej/svej.go | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/udi/handlers/svej/svej.go b/src/udi/handlers/svej/svej.go index af6f19d..a32c62f 100644 --- a/src/udi/handlers/svej/svej.go +++ b/src/udi/handlers/svej/svej.go @@ -99,24 +99,6 @@ func (self *SingleValueExtractorJsonpathHandler) ExtractionHelper(subTopics []st return "", fmt.Errorf("not enough subtopics") } res = subTopics[i] - case "L:": - // L: extract from topic and later match against devices table in database - i, e := strconv.Atoi(selector[2:]) - if e != nil { - return "", fmt.Errorf("Atoi failed with %s", e) - } - if i >= len(subTopics) { - return "", fmt.Errorf("not enough subtopics") - } - ext := subTopics[i] - lookup, err1b := self.dbh.GetDeviceByLabel(ext) - if err1b != nil { - log.Printf("ext lookup %s failed: %v", ext, err1b) - res = ext - } else { - log.Printf("ext: %s", lookup) - res = ext - } case "C:": // use constant value res = selector[2:] From abc0ad082515ddb00c5efe46e9ddf64ceb97ecb4 Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Mon, 11 Nov 2024 17:19:04 +0100 Subject: [PATCH 19/36] some more attributes --- src/udi/handlers/z2m/z2m.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/udi/handlers/z2m/z2m.go b/src/udi/handlers/z2m/z2m.go index a9dc3c5..1f45891 100644 --- a/src/udi/handlers/z2m/z2m.go +++ b/src/udi/handlers/z2m/z2m.go @@ -19,7 +19,7 @@ type Z2MHandler struct { dbh *database.DatabaseHandle } -func parse(T any, payload string, variables *map[string]database.VariableType, attributes *map[string]interface{}) error { +func parse(T any, payload string, variables *map[string]database.VariableType) error { observationType := reflect.TypeOf(T) observation := reflect.New(observationType).Interface() @@ -44,7 +44,6 @@ func parse(T any, payload string, variables *map[string]database.VariableType, a } } - (*attributes)["Status"] = "ok" return nil } @@ -90,12 +89,15 @@ func (self *Z2MHandler) Handle(message handler.MessageT) { measurement.Attributes = make(map[string]interface{}) err3 := parse(T, message.Payload, - &(measurement.Values), - &(measurement.Attributes)) + &(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() From c5150b1b4fa1719a8e46252f96598ebd4cbe4c8b Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Mon, 11 Nov 2024 17:20:13 +0100 Subject: [PATCH 20/36] configuration --- deployment/instances/udi/default/config.json | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/deployment/instances/udi/default/config.json b/deployment/instances/udi/default/config.json index 00ebd30..5af039c 100644 --- a/deployment/instances/udi/default/config.json +++ b/deployment/instances/udi/default/config.json @@ -119,6 +119,16 @@ } } }, + { + "topics": [ "zigbee2mqtt/+" ], + "handler": "Z2M", + "id": "Z2M", + "config": { + "databaseConnStr": "", + "attributes": { + } + } + }, { "topics": [ "shellyplusht/+/status/temperature:0" ], "handler": "SVEJ", From 57c635b1e0715dfbff2eca6fb9102e953ed4b732 Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Mon, 11 Nov 2024 17:20:38 +0100 Subject: [PATCH 21/36] drop scan --- .woodpecker.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.woodpecker.yml b/.woodpecker.yml index 3866ede..c53d46b 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -14,13 +14,6 @@ steps: when: - event: [push, tag] - scan_image: - image: aquasec/trivy - commands: - - trivy image $FORGE_NAME/$CI_REPO:$CI_COMMIT_SHA --quiet --exit-code 1 - when: - - event: [push, tag] - deploy: image: portainer/kubectl-shell:latest secrets: From aa3f784a41e71b03f60d84e2c48fba0b1b42f85f Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Mon, 11 Nov 2024 17:59:23 +0100 Subject: [PATCH 22/36] mi sensor --- queries/hottis.sql | 19 +++++++++++++++++-- .../z2m/models/wsdcgq01lm/wsdcgq01lm.go | 11 +++++++++++ src/udi/handlers/z2m/z2m.go | 3 +++ 3 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 src/udi/handlers/z2m/models/wsdcgq01lm/wsdcgq01lm.go diff --git a/queries/hottis.sql b/queries/hottis.sql index ef43632..17f9aca 100644 --- a/queries/hottis.sql +++ b/queries/hottis.sql @@ -43,7 +43,15 @@ create or replace view temperature_v as cast(values->'Value'->>'value' as float) as temperature, device from measurements - where application in ('Temperature Multisensor', 'Temperature Shelly Plus HT'); + where application in ('Temperature Multisensor', 'Temperature Shelly Plus HT') + union + select time, + cast(values->'Temperature'->>'value' as float) as temperature, + device + from measurements + where application = 'Zigbee2MQTT Hottis Eupenstr.' and + attributes->>'DeviceModel' in ('WSDCGQ11LM', 'WSDCGQ01LM'); + create or replace view temperature2_v as select time, @@ -57,7 +65,14 @@ create or replace view humidity_v as cast(values->'Value'->>'value' as float) as humidity, device from measurements - where application in ('Humidity Multisensor'); + where application in ('Humidity Multisensor') + union + select time, + cast(values->'Humidity'->>'value' as float) as temperature, + device + from measurements + where application = 'Zigbee2MQTT Hottis Eupenstr.' and + attributes->>'DeviceModel' in ('WSDCGQ11LM', 'WSDCGQ01LM'); create or replace view soil_v as select time, diff --git a/src/udi/handlers/z2m/models/wsdcgq01lm/wsdcgq01lm.go b/src/udi/handlers/z2m/models/wsdcgq01lm/wsdcgq01lm.go new file mode 100644 index 0000000..29b3e02 --- /dev/null +++ b/src/udi/handlers/z2m/models/wsdcgq01lm/wsdcgq01lm.go @@ -0,0 +1,11 @@ +package wsdcgq01lm + +type Observation struct { + LinkQuality uint8 `unit:"" json:"linkquality"` + Battery uint8 `unit:"%" json:"battery"` + Humidity float32 `unit:"%H" json:"humidity"` + Pressure float32 `unit:"mbar" json:"pressure"` + Temperature float32 `unit:"°C" json:"temperature"` + Voltage uint16 `unit:"mV" json:"voltage"` +} + diff --git a/src/udi/handlers/z2m/z2m.go b/src/udi/handlers/z2m/z2m.go index 1f45891..6779d09 100644 --- a/src/udi/handlers/z2m/z2m.go +++ b/src/udi/handlers/z2m/z2m.go @@ -11,6 +11,7 @@ import ( "udi/handlers/handler" "udi/database" "udi/handlers/z2m/models/wsdcgq11lm" + "udi/handlers/z2m/models/wsdcgq01lm" ) @@ -80,6 +81,8 @@ func (self *Z2MHandler) Handle(message handler.MessageT) { switch device.DeviceType.ModelIdentifier { case "WSDCGQ11LM": T = wsdcgq11lm.Observation{} + case "WSDCGQ01LM": + T = wsdcgq01lm.Observation{} default: self.Lost(fmt.Sprintf("No parser found for %s", device.DeviceType.ModelIdentifier), nil, message) return From f8bcfe4d25ff2e513ccb951355b8aa0c1bdbbb43 Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Mon, 11 Nov 2024 18:00:13 +0100 Subject: [PATCH 23/36] fix --- src/udi/handlers/z2m/models/wsdcgq11lm/wsdcgq11lm.go | 1 - 1 file changed, 1 deletion(-) diff --git a/src/udi/handlers/z2m/models/wsdcgq11lm/wsdcgq11lm.go b/src/udi/handlers/z2m/models/wsdcgq11lm/wsdcgq11lm.go index db7ffd2..1cc0a67 100644 --- a/src/udi/handlers/z2m/models/wsdcgq11lm/wsdcgq11lm.go +++ b/src/udi/handlers/z2m/models/wsdcgq11lm/wsdcgq11lm.go @@ -4,7 +4,6 @@ type Observation struct { LinkQuality uint8 `unit:"" json:"linkquality"` Battery uint8 `unit:"%" json:"battery"` Humidity float32 `unit:"%H" json:"humidity"` - Pressure float32 `unit:"mbar" json:"pressure"` Temperature float32 `unit:"°C" json:"temperature"` Voltage uint16 `unit:"mV" json:"voltage"` } From 18700899421358f0fa239564f131aafb999e9878 Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Mon, 11 Nov 2024 20:02:12 +0100 Subject: [PATCH 24/36] queries --- queries/hottis.sql | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/queries/hottis.sql b/queries/hottis.sql index 17f9aca..3c42c7b 100644 --- a/queries/hottis.sql +++ b/queries/hottis.sql @@ -52,6 +52,13 @@ create or replace view temperature_v as where application = 'Zigbee2MQTT Hottis Eupenstr.' and attributes->>'DeviceModel' in ('WSDCGQ11LM', 'WSDCGQ01LM'); +create or replace view voltage_v as + select time, + cast(values->'Voltage'->>'value' as float) / 1000 as voltage, + device + from measurements + where application = 'Zigbee2MQTT Hottis Eupenstr.' and + attributes->>'DeviceModel' in ('WSDCGQ11LM', 'WSDCGQ01LM'); create or replace view temperature2_v as select time, From b9e639e0a272a84a58d42ed5645f8406c4868596 Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Fri, 15 Nov 2024 10:52:29 +0100 Subject: [PATCH 25/36] additional model --- src/udi/handlers/z2m/z2m.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/udi/handlers/z2m/z2m.go b/src/udi/handlers/z2m/z2m.go index 6779d09..9f907a0 100644 --- a/src/udi/handlers/z2m/z2m.go +++ b/src/udi/handlers/z2m/z2m.go @@ -12,6 +12,7 @@ import ( "udi/database" "udi/handlers/z2m/models/wsdcgq11lm" "udi/handlers/z2m/models/wsdcgq01lm" + "udi/handlers/z2m/models/gs361ah04" ) @@ -83,6 +84,8 @@ func (self *Z2MHandler) Handle(message handler.MessageT) { 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 From 23962cdebcde285778afc85be02b6a6ac5d465e8 Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Fri, 15 Nov 2024 11:11:35 +0100 Subject: [PATCH 26/36] new model --- .../handlers/z2m/models/gs361ah04/gs361ah04.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/udi/handlers/z2m/models/gs361ah04/gs361ah04.go diff --git a/src/udi/handlers/z2m/models/gs361ah04/gs361ah04.go b/src/udi/handlers/z2m/models/gs361ah04/gs361ah04.go new file mode 100644 index 0000000..f23a0f7 --- /dev/null +++ b/src/udi/handlers/z2m/models/gs361ah04/gs361ah04.go @@ -0,0 +1,15 @@ +package gs361ah04 + +type Observation struct { + LinkQuality uint8 `unit:"" json:"linkquality"` + Battery uint8 `unit:"%" json:"battery"` + AwayMode string `unit:"" json:"away_mode"` + ChildLock string `unit:"" json:"child_lock"` + CurrentHeatingSetpoint float32 `unit:"°C" json:"current_heating_setpoint"` + LocalTemperature float32 `unit:"°C" json:"local_temperature"` + Preset string `unit:"" json:"preset"` + SystemMode string `unit:"" json:"system_mode"` + ValveDetection string `unit:"" json:"valve_detection"` + WindowDetection string `unit:"" json:"window_detection"` +} + From 418b44289d4765ac4faba9351679eaae9c9d48cb Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Fri, 15 Nov 2024 11:22:35 +0100 Subject: [PATCH 27/36] disable debugging code --- src/udi/handlers/snmp/snmp.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/udi/handlers/snmp/snmp.go b/src/udi/handlers/snmp/snmp.go index 899f946..c9b0b4f 100644 --- a/src/udi/handlers/snmp/snmp.go +++ b/src/udi/handlers/snmp/snmp.go @@ -37,7 +37,7 @@ func New(id string, config config.HandlerConfigT) handler.Handler { } func (self *SnmpHandler) Handle(message handler.MessageT) { - log.Printf("Handler SNMP %d processing %s -> %s", self.Id, message.Topic, message.Payload) + # log.Printf("Handler SNMP %d processing %s -> %s", self.Id, message.Topic, message.Payload) var observation observation_t err := json.Unmarshal([]byte(message.Payload), &observation) @@ -66,7 +66,7 @@ func (self *SnmpHandler) Handle(message handler.MessageT) { } } - log.Printf("Prepared measurement item: %s", measurement) + # log.Printf("Prepared measurement item: %s", measurement) self.dbh.StoreMeasurement(&measurement) self.S() From c3323736917e93b864aeabc8331c774edfa5b36c Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Fri, 15 Nov 2024 11:24:26 +0100 Subject: [PATCH 28/36] disable debugging code --- src/udi/handlers/snmp/snmp.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/udi/handlers/snmp/snmp.go b/src/udi/handlers/snmp/snmp.go index c9b0b4f..f1d39f0 100644 --- a/src/udi/handlers/snmp/snmp.go +++ b/src/udi/handlers/snmp/snmp.go @@ -37,7 +37,7 @@ func New(id string, config config.HandlerConfigT) handler.Handler { } func (self *SnmpHandler) Handle(message handler.MessageT) { - # log.Printf("Handler SNMP %d processing %s -> %s", self.Id, message.Topic, message.Payload) + // log.Printf("Handler SNMP %d processing %s -> %s", self.Id, message.Topic, message.Payload) var observation observation_t err := json.Unmarshal([]byte(message.Payload), &observation) @@ -66,7 +66,7 @@ func (self *SnmpHandler) Handle(message handler.MessageT) { } } - # log.Printf("Prepared measurement item: %s", measurement) + // log.Printf("Prepared measurement item: %s", measurement) self.dbh.StoreMeasurement(&measurement) self.S() From c3dce9faab65329eab53e7b4af66c5386dc26b5e Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Fri, 15 Nov 2024 11:26:26 +0100 Subject: [PATCH 29/36] disable debugging code --- src/udi/handlers/snmp/snmp.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/udi/handlers/snmp/snmp.go b/src/udi/handlers/snmp/snmp.go index f1d39f0..c4bcb7c 100644 --- a/src/udi/handlers/snmp/snmp.go +++ b/src/udi/handlers/snmp/snmp.go @@ -2,7 +2,7 @@ package snmp import ( "time" - "log" + // "log" "encoding/json" "udi/config" "udi/handlers/handler" From 95831d5e477328465b9fed0629900a0bbf8fab11 Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Wed, 4 Dec 2024 12:49:49 +0100 Subject: [PATCH 30/36] gy21 --- .../ttn/models/hottisGy21/hottisGY21.go | 55 +++++++++++++++++++ src/udi/handlers/ttn/ttn.go | 3 + 2 files changed, 58 insertions(+) create mode 100644 src/udi/handlers/ttn/models/hottisGy21/hottisGY21.go diff --git a/src/udi/handlers/ttn/models/hottisGy21/hottisGY21.go b/src/udi/handlers/ttn/models/hottisGy21/hottisGY21.go new file mode 100644 index 0000000..15e4f15 --- /dev/null +++ b/src/udi/handlers/ttn/models/hottisGy21/hottisGY21.go @@ -0,0 +1,55 @@ +package hottisGy21 + +import ( + //"log" + "fmt" + "bytes" + "encoding/base64" + "encoding/binary" + "udi/database" +) + +type hottisGy21Values struct { + Connected uint8 + Status uint8 + RawHumidity uint16 + RawTemperature uint16 +} + + +func Parse(fPort int, _ []byte, frmPayload string, variables *map[string]database.VariableType, attributes *map[string]interface{}, _ *database.Device) error { + if fPort != 2 { + return fmt.Errorf("Unexpected fPort %d", fPort) + } + + b, err := base64.StdEncoding.DecodeString(frmPayload) + if err != nil { + return fmt.Errorf("Unable to base64-decode payload: %v", err) + } + + var values hottisGy21Values + err = binary.Read(bytes.NewReader(b), binary.LittleEndian, &values) + if err != nil { + return fmt.Errorf("Unable to cast into struct: %v", err) + } + var temperature float32 = -46.85 + 175.72 * (float32(values.RawTemperature) / 65536.0) + var humidity float32 = -6 + 125 * (float32(values.RawHumidity) / 65536.0); + + // log.Printf("CO2: %f, Temp: %f, Hum: %f, Status: %d", co2concentration, temperature, humidity, values.Status) + + (*variables)["Humidity"] = database.VariableType { + Label: "Humidity", + Variable: "Humidity", + Unit: "%", + Value: humidity, + } + (*variables)["Temperature"] = database.VariableType { + Label: "Temperature", + Variable: "Temperature", + Unit: "°C", + Value: temperature, + } + + (*attributes)["Status"] = values.Status + return nil +} diff --git a/src/udi/handlers/ttn/ttn.go b/src/udi/handlers/ttn/ttn.go index 5731fd7..6fd18a5 100644 --- a/src/udi/handlers/ttn/ttn.go +++ b/src/udi/handlers/ttn/ttn.go @@ -14,6 +14,7 @@ import ( "udi/handlers/ttn/models/draginoLsn50" "udi/handlers/ttn/models/rawPayloadPrinter" "udi/handlers/ttn/models/hottisScd30" + "udi/handlers/ttn/models/hottisGy21 "udi/handlers/ttn/models/hottisThreeWayThermometer" "udi/database" ) @@ -153,6 +154,8 @@ func (self *TTNHandler) Handle(message handler.MessageT) { parser = rawPayloadPrinter.Parse case "hottis-scd30": parser = hottisScd30.Parse + case "hottis-gy21": + parser = hottisGy21.Parse case "hottis-threeway-thermometer": parser = hottisThreeWayThermometer.Parse default: From 1b6ac5d762860c1130c50c4868382358de4834fd Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Wed, 4 Dec 2024 12:52:03 +0100 Subject: [PATCH 31/36] gy21, fix --- src/udi/handlers/ttn/ttn.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/udi/handlers/ttn/ttn.go b/src/udi/handlers/ttn/ttn.go index 6fd18a5..d7a8a58 100644 --- a/src/udi/handlers/ttn/ttn.go +++ b/src/udi/handlers/ttn/ttn.go @@ -14,7 +14,7 @@ import ( "udi/handlers/ttn/models/draginoLsn50" "udi/handlers/ttn/models/rawPayloadPrinter" "udi/handlers/ttn/models/hottisScd30" - "udi/handlers/ttn/models/hottisGy21 + "udi/handlers/ttn/models/hottisGy21" "udi/handlers/ttn/models/hottisThreeWayThermometer" "udi/database" ) From a21fae4f8a0cf68562178b25f1bce2c9d6d2efe2 Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Wed, 4 Dec 2024 13:17:06 +0100 Subject: [PATCH 32/36] view --- queries/hottis.sql | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/queries/hottis.sql b/queries/hottis.sql index 3c42c7b..80a2f98 100644 --- a/queries/hottis.sql +++ b/queries/hottis.sql @@ -118,3 +118,14 @@ create or replace view router_v as cast(values->'wan-out'->>'value' as int) as wanOutOctetsPerSeconds from measurements where application = 'SNMP' and device = '172.16.3.1'; + +create or replace view lora_sht21_v as + select time, + cast(values->'Humidity'->>'value' as float) as humidity, + cast(values->'Temperature'->>'value' as float) as temperature, + m.device as device, + d.attributes->>'Label' as label + from measurements m, devices d + where m.application = 'de-hottis-app01' and + m.attributes->>'DeviceType' = 'hottis-gy21' and + m.device = d.label; From cedb1dfa5a2978dc9e57ed5812eebbdaf44c5f9b Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Thu, 12 Dec 2024 23:21:09 +0100 Subject: [PATCH 33/36] more debugging for database issue --- src/udi/database/database.go | 4 ++-- src/udi/handlers/dt1t/dt1t.go | 1 + src/udi/handlers/locative/locative.go | 1 + src/udi/handlers/mbgw3/mbgw3.go | 1 + src/udi/handlers/pv/pv.go | 1 + src/udi/handlers/snmp/snmp.go | 1 + src/udi/handlers/sver/sver.go | 1 + src/udi/handlers/z2m/z2m.go | 1 + 8 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/udi/database/database.go b/src/udi/database/database.go index 8374e31..0634ace 100644 --- a/src/udi/database/database.go +++ b/src/udi/database/database.go @@ -25,7 +25,7 @@ func NewDatabaseHandle() *DatabaseHandle { } else { db.dbh = conn db.initialized = true - //log.Println("Database connection opened") + log.Println("Database connection opened") } return &db } @@ -44,7 +44,7 @@ func (self *DatabaseHandle) StoreMeasurement(measurement *Measurement) { return } - //log.Println("Successfully stored measurement") + log.Println("Successfully stored measurement") counter.S("Stored") } diff --git a/src/udi/handlers/dt1t/dt1t.go b/src/udi/handlers/dt1t/dt1t.go index ba144f9..aae1c20 100644 --- a/src/udi/handlers/dt1t/dt1t.go +++ b/src/udi/handlers/dt1t/dt1t.go @@ -38,6 +38,7 @@ func New(id string, config config.HandlerConfigT) handler.Handler { t.Id = id t.dbh = database.NewDatabaseHandle() + log.Printf("Handler DT1T %d initialized", id) t.ready = true return t } diff --git a/src/udi/handlers/locative/locative.go b/src/udi/handlers/locative/locative.go index 851c673..db05b43 100644 --- a/src/udi/handlers/locative/locative.go +++ b/src/udi/handlers/locative/locative.go @@ -31,6 +31,7 @@ func New(id string, config config.HandlerConfigT) handler.Handler { } t.Id = id t.dbh = database.NewDatabaseHandle() + log.Printf("Handler Locative %d initialized", id) return t } diff --git a/src/udi/handlers/mbgw3/mbgw3.go b/src/udi/handlers/mbgw3/mbgw3.go index a97cbb3..f3f93dc 100644 --- a/src/udi/handlers/mbgw3/mbgw3.go +++ b/src/udi/handlers/mbgw3/mbgw3.go @@ -31,6 +31,7 @@ func New(id string, config config.HandlerConfigT) handler.Handler { } t.Id = id t.dbh = database.NewDatabaseHandle() + log.Printf("Handler MBGW3 %d initialized", id) return t } diff --git a/src/udi/handlers/pv/pv.go b/src/udi/handlers/pv/pv.go index 807b03c..4723473 100644 --- a/src/udi/handlers/pv/pv.go +++ b/src/udi/handlers/pv/pv.go @@ -41,6 +41,7 @@ func New(id string, config config.HandlerConfigT) handler.Handler { } t.Id = id t.dbh = database.NewDatabaseHandle() + log.Printf("Handler PV %d initialized", id) return t } diff --git a/src/udi/handlers/snmp/snmp.go b/src/udi/handlers/snmp/snmp.go index c4bcb7c..de6ce38 100644 --- a/src/udi/handlers/snmp/snmp.go +++ b/src/udi/handlers/snmp/snmp.go @@ -33,6 +33,7 @@ func New(id string, config config.HandlerConfigT) handler.Handler { } t.Id = id t.dbh = database.NewDatabaseHandle() + log.Printf("Handler SNMP %d initialized", id) return t } diff --git a/src/udi/handlers/sver/sver.go b/src/udi/handlers/sver/sver.go index 32bbbbe..5118a6b 100644 --- a/src/udi/handlers/sver/sver.go +++ b/src/udi/handlers/sver/sver.go @@ -111,6 +111,7 @@ func New(id string, config config.HandlerConfigT) handler.Handler { t.Id = id t.ready = true t.dbh = database.NewDatabaseHandle() + log.Printf("Handler SVER %d initialized", id) return t } diff --git a/src/udi/handlers/z2m/z2m.go b/src/udi/handlers/z2m/z2m.go index 9f907a0..d5e44fc 100644 --- a/src/udi/handlers/z2m/z2m.go +++ b/src/udi/handlers/z2m/z2m.go @@ -55,6 +55,7 @@ func New(id string, config config.HandlerConfigT) handler.Handler { } t.Id = id t.dbh = database.NewDatabaseHandle() + log.Printf("Handler Z2M %d initialized", id) return t } From 166c414af1d0f322beaaeffc21e515375ae78be5 Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Thu, 12 Dec 2024 23:23:32 +0100 Subject: [PATCH 34/36] more debugging for database issue --- src/udi/handlers/mbgw3/mbgw3.go | 1 + src/udi/handlers/pv/pv.go | 1 + src/udi/handlers/snmp/snmp.go | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/udi/handlers/mbgw3/mbgw3.go b/src/udi/handlers/mbgw3/mbgw3.go index f3f93dc..42ea730 100644 --- a/src/udi/handlers/mbgw3/mbgw3.go +++ b/src/udi/handlers/mbgw3/mbgw3.go @@ -2,6 +2,7 @@ package mbgw3 import ( "time" + "log" "strconv" "encoding/json" "udi/config" diff --git a/src/udi/handlers/pv/pv.go b/src/udi/handlers/pv/pv.go index 4723473..7cff306 100644 --- a/src/udi/handlers/pv/pv.go +++ b/src/udi/handlers/pv/pv.go @@ -3,6 +3,7 @@ package pv import ( "reflect" "time" + "log" "encoding/json" "udi/config" "udi/handlers/handler" diff --git a/src/udi/handlers/snmp/snmp.go b/src/udi/handlers/snmp/snmp.go index de6ce38..e6e5e8e 100644 --- a/src/udi/handlers/snmp/snmp.go +++ b/src/udi/handlers/snmp/snmp.go @@ -2,7 +2,7 @@ package snmp import ( "time" - // "log" + "log" "encoding/json" "udi/config" "udi/handlers/handler" From a1b98d3438b730a832092af2ffeba36225c93016 Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Fri, 13 Dec 2024 10:02:32 +0100 Subject: [PATCH 35/36] more debugging --- src/udi/handlers/svej/svej.go | 1 + src/udi/handlers/ttn/ttn.go | 1 + 2 files changed, 2 insertions(+) diff --git a/src/udi/handlers/svej/svej.go b/src/udi/handlers/svej/svej.go index a32c62f..4229e0b 100644 --- a/src/udi/handlers/svej/svej.go +++ b/src/udi/handlers/svej/svej.go @@ -76,6 +76,7 @@ func New(id string, config config.HandlerConfigT) handler.Handler { t.Id = id t.ready = true t.dbh = database.NewDatabaseHandle() + log.Printf("Handler SVEJ %d initialized", id) return t } diff --git a/src/udi/handlers/ttn/ttn.go b/src/udi/handlers/ttn/ttn.go index d7a8a58..c74a31a 100644 --- a/src/udi/handlers/ttn/ttn.go +++ b/src/udi/handlers/ttn/ttn.go @@ -86,6 +86,7 @@ func New(id string, config config.HandlerConfigT) handler.Handler { } t.Id = id t.dbh = database.NewDatabaseHandle() + log.Printf("Handler TTN %d initialized", id) return t } From 51e482e94e59b066fc6ccd23a6259f13624680c0 Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Fri, 13 Dec 2024 10:27:02 +0100 Subject: [PATCH 36/36] fix --- src/udi/handlers/ttn/ttn.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/udi/handlers/ttn/ttn.go b/src/udi/handlers/ttn/ttn.go index c74a31a..cfccedf 100644 --- a/src/udi/handlers/ttn/ttn.go +++ b/src/udi/handlers/ttn/ttn.go @@ -2,7 +2,7 @@ package ttn import ( "fmt" - //"log" + "log" "time" "encoding/json" "udi/config"