You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by cd...@apache.org on 2020/11/12 17:25:37 UTC
[plc4x] branch feature/plc4go updated: - Fixed a bug in the "update
change" detection mechanism - Implemented the active read support
This is an automated email from the ASF dual-hosted git repository.
cdutz pushed a commit to branch feature/plc4go
in repository https://gitbox.apache.org/repos/asf/plc4x.git
The following commit(s) were added to refs/heads/feature/plc4go by this push:
new 9365eb8 - Fixed a bug in the "update change" detection mechanism - Implemented the active read support
9365eb8 is described below
commit 9365eb841cda2c0a0d603d2d58b15873a9f9a085
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Thu Nov 12 18:25:28 2020 +0100
- Fixed a bug in the "update change" detection mechanism
- Implemented the active read support
---
plc4go/cmd/main/drivers/knxnetip_test.go | 2 +-
.../internal/plc4go/knxnetip/KncNetIpConnection.go | 12 ++-
plc4go/internal/plc4go/knxnetip/KnxNetIpField.go | 58 +++++++++++++
plc4go/internal/plc4go/knxnetip/KnxNetIpReader.go | 99 ++++++++++++++++++++++
4 files changed, 166 insertions(+), 5 deletions(-)
diff --git a/plc4go/cmd/main/drivers/knxnetip_test.go b/plc4go/cmd/main/drivers/knxnetip_test.go
index db4c12f..dbf2a4c 100644
--- a/plc4go/cmd/main/drivers/knxnetip_test.go
+++ b/plc4go/cmd/main/drivers/knxnetip_test.go
@@ -109,7 +109,7 @@ func TestKnxNetIpPlc4goDriver(t *testing.T) {
}
// Wait 2 minutes
- time.Sleep(120 * time.Second)
+ time.Sleep(1200 * time.Second)
// Do something with the response
/*value1 := rrr.Response.GetValue("field1")
diff --git a/plc4go/internal/plc4go/knxnetip/KncNetIpConnection.go b/plc4go/internal/plc4go/knxnetip/KncNetIpConnection.go
index 07ad4e5..7e2eb64 100644
--- a/plc4go/internal/plc4go/knxnetip/KncNetIpConnection.go
+++ b/plc4go/internal/plc4go/knxnetip/KncNetIpConnection.go
@@ -41,7 +41,7 @@ type ConnectionMetadata struct {
}
func (m ConnectionMetadata) CanRead() bool {
- return false
+ return true
}
func (m ConnectionMetadata) CanWrite() bool {
@@ -314,7 +314,8 @@ func (m *KnxNetIpConnection) GetMetadata() apiModel.PlcConnectionMetadata {
}
func (m *KnxNetIpConnection) ReadRequestBuilder() apiModel.PlcReadRequestBuilder {
- panic("this connection doesn't support reading")
+ return internalModel.NewDefaultPlcReadRequestBuilder(
+ m.fieldHandler, NewKnxNetIpReader(m))
}
func (m *KnxNetIpConnection) WriteRequestBuilder() apiModel.PlcWriteRequestBuilder {
@@ -371,8 +372,11 @@ func (m *KnxNetIpConnection) handleIncomingTunnelingRequest(tunnelingRequestChan
addressData := uint16(cemiDataInd.CemiDataFrame.DestinationAddress[0])<<8 | (uint16(cemiDataInd.CemiDataFrame.DestinationAddress[1]) & 0xFF)
val, ok := m.valueCache[addressData]
changed := false
- if !ok || !m.sliceEqual(val, cemiDataInd.CemiDataFrame.Data) {
- m.valueCache[addressData] = cemiDataInd.CemiDataFrame.Data
+ var payload []int8
+ payload = append(payload, cemiDataInd.CemiDataFrame.DataFirstByte)
+ payload = append(payload, cemiDataInd.CemiDataFrame.Data...)
+ if !ok || !m.sliceEqual(val, payload) {
+ m.valueCache[addressData] = payload
changed = true
}
for _, subscriber := range m.subscribers {
diff --git a/plc4go/internal/plc4go/knxnetip/KnxNetIpField.go b/plc4go/internal/plc4go/knxnetip/KnxNetIpField.go
index 5224580..3d9ee16 100644
--- a/plc4go/internal/plc4go/knxnetip/KnxNetIpField.go
+++ b/plc4go/internal/plc4go/knxnetip/KnxNetIpField.go
@@ -29,6 +29,7 @@ import (
type KnxNetIpField interface {
matches(knxGroupAddress driverModel.KnxGroupAddress) bool
+ toGroupAddress() *driverModel.KnxGroupAddress
apiModel.PlcField
}
@@ -70,6 +71,30 @@ func (k KnxNetIpGroupAddress3LevelPlcField) matches(knxGroupAddress driverModel.
matches(k.SubGroup, strconv.Itoa(int(level3KnxGroupAddress.SubGroup)))
}
+func (k KnxNetIpGroupAddress3LevelPlcField) toGroupAddress() *driverModel.KnxGroupAddress {
+ mainGroup, err := strconv.Atoi(k.MainGroup)
+ if err != nil {
+ return nil
+ }
+ midleGroup, err := strconv.Atoi(k.MiddleGroup)
+ if err != nil {
+ return nil
+ }
+ subGroup, err := strconv.Atoi(k.SubGroup)
+ if err != nil {
+ return nil
+ }
+ ga := &driverModel.KnxGroupAddress {}
+ l3 := &driverModel.KnxGroupAddress3Level{
+ MainGroup: uint8(mainGroup),
+ MiddleGroup: uint8(midleGroup),
+ SubGroup: uint8(subGroup),
+ Parent: ga,
+ }
+ ga.Child = l3
+ return ga
+}
+
type KnxNetIpGroupAddress2LevelPlcField struct {
FieldType *model.KnxDatapointType
// 5 Bits: Values 0-31
@@ -104,6 +129,25 @@ func (k KnxNetIpGroupAddress2LevelPlcField) matches(knxGroupAddress driverModel.
matches(k.SubGroup, strconv.Itoa(int(level2KnxGroupAddress.SubGroup)))
}
+func (k KnxNetIpGroupAddress2LevelPlcField) toGroupAddress() *driverModel.KnxGroupAddress {
+ mainGroup, err := strconv.Atoi(k.MainGroup)
+ if err != nil {
+ return nil
+ }
+ subGroup, err := strconv.Atoi(k.SubGroup)
+ if err != nil {
+ return nil
+ }
+ ga := &driverModel.KnxGroupAddress {}
+ l3 := &driverModel.KnxGroupAddress2Level{
+ MainGroup: uint8(mainGroup),
+ SubGroup: uint16(subGroup),
+ Parent: ga,
+ }
+ ga.Child = l3
+ return ga
+}
+
type KnxNetIpGroupAddress1LevelPlcField struct {
FieldType *model.KnxDatapointType
// 16 Bits
@@ -134,6 +178,20 @@ func (k KnxNetIpGroupAddress1LevelPlcField) matches(knxGroupAddress driverModel.
return matches(k.MainGroup, strconv.Itoa(int(level1KnxGroupAddress.SubGroup)))
}
+func (k KnxNetIpGroupAddress1LevelPlcField) toGroupAddress() *driverModel.KnxGroupAddress {
+ mainGroup, err := strconv.Atoi(k.MainGroup)
+ if err != nil {
+ return nil
+ }
+ ga := &driverModel.KnxGroupAddress {}
+ l3 := &driverModel.KnxGroupAddressFreeLevel{
+ SubGroup: uint16(mainGroup),
+ Parent: ga,
+ }
+ ga.Child = l3
+ return ga
+}
+
func CastToKnxNetIpFieldFromPlcField(plcField apiModel.PlcField) (KnxNetIpField, error) {
if knxNetIpField, ok := plcField.(KnxNetIpField); ok {
return knxNetIpField, nil
diff --git a/plc4go/internal/plc4go/knxnetip/KnxNetIpReader.go b/plc4go/internal/plc4go/knxnetip/KnxNetIpReader.go
new file mode 100644
index 0000000..a5ae873
--- /dev/null
+++ b/plc4go/internal/plc4go/knxnetip/KnxNetIpReader.go
@@ -0,0 +1,99 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+package knxnetip
+
+import (
+ driverModel "github.com/apache/plc4x/plc4go/internal/plc4go/knxnetip/readwrite/model"
+ internalModel "github.com/apache/plc4x/plc4go/internal/plc4go/model"
+ "github.com/apache/plc4x/plc4go/internal/plc4go/spi"
+ "github.com/apache/plc4x/plc4go/internal/plc4go/utils"
+ "github.com/apache/plc4x/plc4go/pkg/plc4go/model"
+ "github.com/apache/plc4x/plc4go/pkg/plc4go/values"
+)
+
+type KnxNetIpReader struct {
+ connection *KnxNetIpConnection
+ spi.PlcReader
+}
+
+func NewKnxNetIpReader(connection *KnxNetIpConnection) *KnxNetIpReader {
+ return &KnxNetIpReader{
+ connection: connection,
+ }
+}
+
+func (m KnxNetIpReader) Read(readRequest model.PlcReadRequest) <-chan model.PlcReadRequestResult {
+ resultChan := make(chan model.PlcReadRequestResult)
+ go func() {
+ responseCodes := map[string]model.PlcResponseCode{}
+ plcValues := map[string]values.PlcValue{}
+ for _, fieldName := range readRequest.GetFieldNames() {
+ field, err := CastToKnxNetIpFieldFromPlcField(readRequest.GetField(fieldName))
+ if err != nil {
+ responseCodes[fieldName] = model.PlcResponseCode_INVALID_ADDRESS
+ plcValues[fieldName] = nil
+ continue
+ }
+
+ // Serialize the field to an uint16
+ wb := utils.NewWriteBuffer()
+ err = field.toGroupAddress().Serialize(*wb)
+ if err != nil {
+ responseCodes[fieldName] = model.PlcResponseCode_INVALID_ADDRESS
+ plcValues[fieldName] = nil
+ continue
+ }
+ rawAddress := wb.GetBytes()
+ address := (uint16(rawAddress[0]) << 8) | uint16(rawAddress[1] & 0xFF)
+
+ // Get the value form the cache
+ int8s, ok := m.connection.valueCache[address]
+ if !ok {
+ responseCodes[fieldName] = model.PlcResponseCode_NOT_FOUND
+ plcValues[fieldName] = nil
+ continue
+ }
+
+ // Decode the data according to the fields type
+ rb := utils.NewReadBuffer(utils.Int8ToUint8(int8s))
+ plcValue, err := driverModel.KnxDatapointParse(rb, field.GetTypeName())
+ if err != nil {
+ responseCodes[fieldName] = model.PlcResponseCode_INVALID_DATA
+ plcValues[fieldName] = nil
+ continue
+ }
+
+ // Add it to the result
+ responseCodes[fieldName] = model.PlcResponseCode_OK
+ plcValues[fieldName] = plcValue
+ }
+ result := internalModel.NewDefaultPlcReadResponse(readRequest, responseCodes, plcValues)
+ resultChan <- model.PlcReadRequestResult{
+ Request: readRequest,
+ Response: result,
+ Err: nil,
+ }
+ }()
+ return resultChan
+}
+
+
+
+
+