You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by sr...@apache.org on 2022/07/26 12:39:07 UTC

[plc4x] branch develop updated: feat(plc4go/cbus): progress on field handling

This is an automated email from the ASF dual-hosted git repository.

sruehl pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git


The following commit(s) were added to refs/heads/develop by this push:
     new 38a8bdf4e feat(plc4go/cbus): progress on field handling
38a8bdf4e is described below

commit 38a8bdf4ec03b7e0705ec183c33108faaba6f0b0
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Tue Jul 26 14:38:46 2022 +0200

    feat(plc4go/cbus): progress on field handling
---
 plc4go/internal/cbus/Field.go                      | 87 +++++++++++++++++-----
 plc4go/internal/cbus/FieldHandler.go               | 74 +++++++++++++++++-
 plc4go/internal/cbus/fieldtype_string.go           |  7 +-
 .../drivers/tests/manual_cbus_driver_test.go}      | 37 +++++----
 .../apache/plc4x/java/cbus/RandomPackagesTest.java | 10 +--
 5 files changed, 162 insertions(+), 53 deletions(-)

diff --git a/plc4go/internal/cbus/Field.go b/plc4go/internal/cbus/Field.go
index a846ceb08..619b0c067 100644
--- a/plc4go/internal/cbus/Field.go
+++ b/plc4go/internal/cbus/Field.go
@@ -22,47 +22,96 @@ package cbus
 import (
 	"fmt"
 	"github.com/apache/plc4x/plc4go/internal/spi/utils"
+	"github.com/apache/plc4x/plc4go/pkg/api/model"
 	readWriteModel "github.com/apache/plc4x/plc4go/protocols/cbus/readwrite/model"
 )
 
-type PlcField interface {
+type StatusRequestType uint8
+
+const (
+	StatusRequestTypeBinaryState StatusRequestType = iota
+	StatusRequestTypeLevel
+)
+
+// StatusField can be used to query status using a P-to-MP-StatusRequest command
+type StatusField interface {
+	model.PlcField
+	GetStatusRequestType() StatusRequestType
 	GetApplicationId() readWriteModel.ApplicationId
 }
 
-type plcField struct {
-	NumElements uint16
+func NewStatusField(statusRequestType StatusRequestType, level *byte, applicationId readWriteModel.ApplicationId, numElements uint16) StatusField {
+	return &statusField{
+		fieldType:         STATUS,
+		statusRequestType: statusRequestType,
+		applicationId:     applicationId,
+		numElements:       numElements,
+	}
 }
 
-func NewField(numElements uint16) PlcField {
-	return &plcField{
-		NumElements: numElements,
+// CALField can be used to get device/network management fields
+type CALField interface {
+	model.PlcField
+}
+
+func NewCALField(numElements uint16) CALField {
+	return &calField{
+		fieldType:   CAL,
+		numElements: numElements,
 	}
 }
 
-func (m plcField) GetAddressString() string {
-	// TODO: implement me
-	return fmt.Sprintf("TODO[%d]", m.NumElements)
+type statusField struct {
+	fieldType         FieldType
+	statusRequestType StatusRequestType
+	level             *byte
+	applicationId     readWriteModel.ApplicationId
+	numElements       uint16
+}
+
+func (m statusField) GetAddressString() string {
+	return fmt.Sprintf("%d[%d]", m.fieldType, m.numElements)
+}
+
+func (m statusField) GetStatusRequestType() StatusRequestType {
+	return m.statusRequestType
+}
+
+func (m statusField) GetApplicationId() readWriteModel.ApplicationId {
+	return m.applicationId
+}
+
+func (m statusField) GetTypeName() string {
+	return STATUS.GetName()
+}
+
+func (m statusField) GetQuantity() uint16 {
+	return m.numElements
+}
+
+type calField struct {
+	fieldType   FieldType
+	numElements uint16
 }
 
-func (m plcField) GetTypeName() string {
-	return "TODO"
+func (m calField) GetAddressString() string {
+	return fmt.Sprintf("%d[%d]", m.fieldType, m.numElements)
 }
 
-func (m plcField) GetApplicationId() readWriteModel.ApplicationId {
-	//TODO implement me
-	panic("implement me")
+func (m calField) GetTypeName() string {
+	return CAL.GetName()
 }
 
-func (m plcField) GetQuantity() uint16 {
-	return m.NumElements
+func (m calField) GetQuantity() uint16 {
+	return m.numElements
 }
 
-func (m plcField) Serialize(writeBuffer utils.WriteBuffer) error {
-	if err := writeBuffer.PushContext("TODO"); err != nil {
+func (m calField) Serialize(writeBuffer utils.WriteBuffer) error {
+	if err := writeBuffer.PushContext(m.fieldType.GetName()); err != nil {
 		return err
 	}
 
-	if err := writeBuffer.PopContext("TODO"); err != nil {
+	if err := writeBuffer.PopContext(m.fieldType.GetName()); err != nil {
 		return err
 	}
 	return nil
diff --git a/plc4go/internal/cbus/FieldHandler.go b/plc4go/internal/cbus/FieldHandler.go
index 5b7751823..5e79ea2e8 100644
--- a/plc4go/internal/cbus/FieldHandler.go
+++ b/plc4go/internal/cbus/FieldHandler.go
@@ -20,15 +20,22 @@
 package cbus
 
 import (
+	"encoding/hex"
+	"github.com/apache/plc4x/plc4go/internal/spi/utils"
 	"github.com/apache/plc4x/plc4go/pkg/api/model"
+	readWriteModel "github.com/apache/plc4x/plc4go/protocols/cbus/readwrite/model"
 	"github.com/pkg/errors"
+	"regexp"
+	"strconv"
+	"strings"
 )
 
 type FieldType uint8
 
 //go:generate stringer -type FieldType
 const (
-	TODO FieldType = 0x00
+	STATUS FieldType = iota
+	CAL
 )
 
 func (i FieldType) GetName() string {
@@ -36,12 +43,73 @@ func (i FieldType) GetName() string {
 }
 
 type FieldHandler struct {
+	statusRequestPattern *regexp.Regexp
+	calPattern           *regexp.Regexp
 }
 
 func NewFieldHandler() FieldHandler {
-	return FieldHandler{}
+	return FieldHandler{
+		statusRequestPattern: regexp.MustCompile(`^status/(?P<statusRequestType>(?P<binary>binary)|level=0x(?P<level>00|20|40|60|80|A0|C0|E0))/(?P<applicationId>.*)`),
+		calPattern:           regexp.MustCompile(`^cal/(?P<calType>recall=\[(?P<recallParamNo>[\w\d]+),(?P<recallCount>\d+)]|identify=\[(?P<identifyAttribute>[\w\d]+)]|getstatus=\[(?P<getstatusParamNo>[\w\d]+),(?P<getstatusCount>\d+)])`),
+	}
 }
 
 func (m FieldHandler) ParseQuery(query string) (model.PlcField, error) {
-	return nil, errors.Errorf("Unable to parse %s", query)
+	if match := utils.GetSubgroupMatches(m.statusRequestPattern, query); match != nil {
+		var level *byte
+		var statusRequestType StatusRequestType
+		statusRequestArgument := match["statusRequestType"]
+		if statusRequestArgument != "" {
+			if match["binary"] != "" {
+				statusRequestType = StatusRequestTypeBinaryState
+			} else if levelArgument := match["level"]; levelArgument != "" {
+				statusRequestType = StatusRequestTypeLevel
+				decodedHex, _ := hex.DecodeString(match["level"])
+				if len(decodedHex) != 1 {
+					panic("invalid state. Should have exactly 1")
+				}
+				level = &decodedHex[0]
+			} else {
+				return nil, errors.Errorf("Unknown statusRequestType%s", statusRequestArgument)
+			}
+		}
+		var applicationId readWriteModel.ApplicationId
+		applicationIdArgument := match["applicationId"]
+		if strings.HasPrefix(applicationIdArgument, "0x") {
+			decodedHex, err := hex.DecodeString(applicationIdArgument[2:])
+			if err != nil {
+				return nil, errors.Wrap(err, "Not a valid hex")
+			}
+			if len(decodedHex) != 1 {
+				return nil, errors.Errorf("Hex must be exatly one byte")
+			}
+			applicationId = readWriteModel.ApplicationId(decodedHex[0])
+		} else {
+			atoi, err := strconv.ParseUint(applicationIdArgument, 10, 8)
+			if err != nil {
+				applicationId = readWriteModel.ApplicationId(atoi)
+			} else {
+				applicationIdByName, ok := readWriteModel.ApplicationIdByName(applicationIdArgument)
+				if !ok {
+					return nil, errors.Errorf("Unknown applicationId%s", applicationIdArgument)
+				}
+				applicationId = applicationIdByName
+			}
+		}
+		return NewStatusField(statusRequestType, level, applicationId, 1), nil
+	} else if match := utils.GetSubgroupMatches(m.calPattern, query); match != nil {
+		calTypeArgument := match["calType"]
+		switch {
+		case strings.HasPrefix(calTypeArgument, "recall="):
+			panic("Implement me ")
+		case strings.HasPrefix(calTypeArgument, "identify="):
+			panic("Implement me ")
+		case strings.HasPrefix(calTypeArgument, "getstatus="):
+			panic("Implement me ")
+		default:
+			return nil, errors.Errorf("Invalid cal type %s", calTypeArgument)
+		}
+	} else {
+		return nil, errors.Errorf("Unable to parse %s", query)
+	}
 }
diff --git a/plc4go/internal/cbus/fieldtype_string.go b/plc4go/internal/cbus/fieldtype_string.go
index fbbc9d338..4c555467a 100644
--- a/plc4go/internal/cbus/fieldtype_string.go
+++ b/plc4go/internal/cbus/fieldtype_string.go
@@ -25,12 +25,13 @@ func _() {
 	// An "invalid array index" compiler error signifies that the constant values have changed.
 	// Re-run the stringer command to generate them again.
 	var x [1]struct{}
-	_ = x[TODO-0]
+	_ = x[STATUS-0]
+	_ = x[CAL-1]
 }
 
-const _FieldType_name = "TODO"
+const _FieldType_name = "STATUSCAL"
 
-var _FieldType_index = [...]uint8{0, 4}
+var _FieldType_index = [...]uint8{0, 6, 9}
 
 func (i FieldType) String() string {
 	if i >= FieldType(len(_FieldType_index)-1) {
diff --git a/plc4go/internal/cbus/FieldHandler.go b/plc4go/tests/drivers/tests/manual_cbus_driver_test.go
similarity index 53%
copy from plc4go/internal/cbus/FieldHandler.go
copy to plc4go/tests/drivers/tests/manual_cbus_driver_test.go
index 5b7751823..d2a1e70da 100644
--- a/plc4go/internal/cbus/FieldHandler.go
+++ b/plc4go/tests/drivers/tests/manual_cbus_driver_test.go
@@ -17,31 +17,28 @@
  * under the License.
  */
 
-package cbus
+package tests
 
 import (
-	"github.com/apache/plc4x/plc4go/pkg/api/model"
-	"github.com/pkg/errors"
+	"github.com/apache/plc4x/plc4go/internal/cbus"
+	"github.com/apache/plc4x/plc4go/internal/spi/testutils"
+	"github.com/apache/plc4x/plc4go/pkg/api"
+	"github.com/apache/plc4x/plc4go/pkg/api/transports"
+	_ "github.com/apache/plc4x/plc4go/tests/initializetest"
+	"testing"
 )
 
-type FieldType uint8
+func TestManualCBusDriver(t *testing.T) {
+	t.Skip()
 
-//go:generate stringer -type FieldType
-const (
-	TODO FieldType = 0x00
-)
-
-func (i FieldType) GetName() string {
-	return i.String()
-}
+	connectionString := "c-bus://192.168.178.101"
+	driverManager := plc4go.NewPlcDriverManager()
+	driverManager.RegisterDriver(cbus.NewDriver())
+	transports.RegisterTcpTransport(driverManager)
+	test := testutils.NewManualTestSuite(connectionString, driverManager, t)
 
-type FieldHandler struct {
-}
-
-func NewFieldHandler() FieldHandler {
-	return FieldHandler{}
-}
+	test.AddTestCase("status/binary/0x04", true)
+	test.AddTestCase("status/level=0x40/0x04", true)
 
-func (m FieldHandler) ParseQuery(query string) (model.PlcField, error) {
-	return nil, errors.Errorf("Unable to parse %s", query)
+	test.Run()
 }
diff --git a/plc4j/drivers/c-bus/src/test/java/org/apache/plc4x/java/cbus/RandomPackagesTest.java b/plc4j/drivers/c-bus/src/test/java/org/apache/plc4x/java/cbus/RandomPackagesTest.java
index 3fd6ce295..7fae9f6f4 100644
--- a/plc4j/drivers/c-bus/src/test/java/org/apache/plc4x/java/cbus/RandomPackagesTest.java
+++ b/plc4j/drivers/c-bus/src/test/java/org/apache/plc4x/java/cbus/RandomPackagesTest.java
@@ -47,7 +47,6 @@ public class RandomPackagesTest {
     void whatEverThisIs() throws Exception {
         byte[] bytes = "\\3436303230303231303167\r".getBytes(StandardCharsets.UTF_8);
         ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
-        cBusOptions = C_BUS_OPTIONS_WITH_SRCHK;
         CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, false, requestContext, cBusOptions, bytes.length);
         assertThat(msg).isNotNull();
         System.out.println(msg);
@@ -244,19 +243,14 @@ public class RandomPackagesTest {
     void wat() throws Exception {
         byte[] bytes = "D8FF0024000002000000000000000008000000000000000000\r\n".getBytes(StandardCharsets.UTF_8);
         ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
-        cBusOptions = C_BUS_OPTIONS_WITH_SRCHK;
         requestContext = new RequestContext(true, false, false);
         CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, true, requestContext, cBusOptions, bytes.length);
         assertThat(msg).isNotNull();
         System.out.println(msg);
         CBusMessageToClient messageToClient = (CBusMessageToClient) msg;
         ReplyOrConfirmationReply reply = (ReplyOrConfirmationReply) messageToClient.getReply();
-            /*
-            MonitoredSALReply monitoredSALReply = (MonitoredSALReply) reply.getReply();
-            System.out.println(monitoredSALReply.getMonitoredSAL());
-             */
-        EncodedReplyCALReply encodedReplyCALReply = (EncodedReplyCALReply) ((ReplyEncodedReply) reply.getReply()).getEncodedReply();
-        System.out.println(encodedReplyCALReply.getCalReply());
+        EncodedReplyStandardFormatStatusReply encodedReplyCALReply = (EncodedReplyStandardFormatStatusReply) ((ReplyEncodedReply) reply.getReply()).getEncodedReply();
+        System.out.println(encodedReplyCALReply.getReply());
         assertMessageMatches(bytes, msg);
     }