Skip to content

Commit

Permalink
feat(plc4xbrowser): added several features
Browse files Browse the repository at this point in the history
- quick access to commands with 0-9
- history command excluded from history
- added history command
- added plc4x browser debug
- added subscribe direct
  • Loading branch information
sruehl committed Aug 3, 2022
1 parent 2bfea4e commit 0458e79
Show file tree
Hide file tree
Showing 5 changed files with 232 additions and 26 deletions.
93 changes: 77 additions & 16 deletions plc4go/internal/cbus/Field.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ func NewCALGetstatusField(unitAddress readWriteModel.UnitAddress, parameter read
}
}

// SALMonitorField can be used to monitor fields
// SALMonitorField can be used to monitor sal fields
type SALMonitorField interface {
model.PlcField
GetUnitAddress() readWriteModel.UnitAddress
Expand All @@ -116,6 +116,22 @@ func NewSALMonitorField(unitAddress readWriteModel.UnitAddress, application read
}
}

// MMIMonitorField can be used to monitor mmi fields
type MMIMonitorField interface {
model.PlcField
GetUnitAddress() readWriteModel.UnitAddress
GetApplication() readWriteModel.ApplicationIdContainer
}

func NewMMIMonitorField(unitAddress readWriteModel.UnitAddress, application readWriteModel.ApplicationIdContainer, numElements uint16) SALMonitorField {
return &mmiMonitorField{
fieldType: MMI_STATUS_MONITOR,
unitAddress: unitAddress,
application: application,
numElements: numElements,
}
}

///////////////////////////////////////
///////////////////////////////////////
//
Expand Down Expand Up @@ -164,6 +180,13 @@ type salMonitorField struct {
numElements uint16
}

type mmiMonitorField struct {
fieldType FieldType
unitAddress readWriteModel.UnitAddress
application readWriteModel.ApplicationIdContainer
numElements uint16
}

//
// Internal section
//
Expand Down Expand Up @@ -280,31 +303,31 @@ func (c calIdentifyField) GetQuantity() uint16 {
return c.numElements
}

func (m calIdentifyField) Serialize(writeBuffer utils.WriteBuffer) error {
if err := writeBuffer.PushContext(m.fieldType.GetName()); err != nil {
func (c calIdentifyField) Serialize(writeBuffer utils.WriteBuffer) error {
if err := writeBuffer.PushContext(c.fieldType.GetName()); err != nil {
return err
}

if err := m.calField.Serialize(writeBuffer); err != nil {
if err := c.calField.Serialize(writeBuffer); err != nil {
return err
}

if err := writeBuffer.WriteUint8("attribute", 8, uint8(m.attribute), utils.WithAdditionalStringRepresentation(m.attribute.String())); err != nil {
if err := writeBuffer.WriteUint8("attribute", 8, uint8(c.attribute), utils.WithAdditionalStringRepresentation(c.attribute.String())); err != nil {
return err
}

if err := writeBuffer.PopContext(m.fieldType.GetName()); err != nil {
if err := writeBuffer.PopContext(c.fieldType.GetName()); err != nil {
return err
}
return nil
}

func (m calGetstatusField) GetParameter() readWriteModel.Parameter {
return m.parameter
func (c calGetstatusField) GetParameter() readWriteModel.Parameter {
return c.parameter
}

func (m calGetstatusField) GetCount() uint8 {
return m.count
func (c calGetstatusField) GetCount() uint8 {
return c.count
}

func (c calGetstatusField) GetAddressString() string {
Expand All @@ -319,23 +342,23 @@ func (c calGetstatusField) GetQuantity() uint16 {
return c.numElements
}

func (m calGetstatusField) Serialize(writeBuffer utils.WriteBuffer) error {
if err := writeBuffer.PushContext(m.fieldType.GetName()); err != nil {
func (c calGetstatusField) Serialize(writeBuffer utils.WriteBuffer) error {
if err := writeBuffer.PushContext(c.fieldType.GetName()); err != nil {
return err
}

if err := m.calField.Serialize(writeBuffer); err != nil {
if err := c.calField.Serialize(writeBuffer); err != nil {
return err
}

if err := writeBuffer.WriteUint8("parameter", 8, uint8(m.parameter), utils.WithAdditionalStringRepresentation(m.parameter.String())); err != nil {
if err := writeBuffer.WriteUint8("parameter", 8, uint8(c.parameter), utils.WithAdditionalStringRepresentation(c.parameter.String())); err != nil {
return err
}
if err := writeBuffer.WriteUint8("count", 8, m.count); err != nil {
if err := writeBuffer.WriteUint8("count", 8, c.count); err != nil {
return err
}

if err := writeBuffer.PopContext(m.fieldType.GetName()); err != nil {
if err := writeBuffer.PopContext(c.fieldType.GetName()); err != nil {
return err
}
return nil
Expand Down Expand Up @@ -378,3 +401,41 @@ func (s salMonitorField) Serialize(writeBuffer utils.WriteBuffer) error {
}
return nil
}

func (m mmiMonitorField) GetAddressString() string {
return fmt.Sprintf("%d/%s%s[%d]", m.fieldType, m.unitAddress, m.application, m.numElements)
}

func (m mmiMonitorField) GetTypeName() string {
return m.fieldType.GetName()
}

func (m mmiMonitorField) GetQuantity() uint16 {
return m.numElements
}

func (m mmiMonitorField) GetUnitAddress() readWriteModel.UnitAddress {
return m.unitAddress
}

func (m mmiMonitorField) GetApplication() readWriteModel.ApplicationIdContainer {
return m.application
}

func (m mmiMonitorField) Serialize(writeBuffer utils.WriteBuffer) error {
if err := writeBuffer.PushContext(m.fieldType.GetName()); err != nil {
return err
}

if err := m.unitAddress.Serialize(writeBuffer); err != nil {
return err
}
if err := m.application.Serialize(writeBuffer); err != nil {
return err
}

if err := writeBuffer.PopContext(m.fieldType.GetName()); err != nil {
return err
}
return nil
}
48 changes: 45 additions & 3 deletions plc4go/internal/cbus/FieldHandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const (
CAL_IDENTIFY
CAL_GETSTATUS
SAL_MONITOR
MMI_STATUS_MONITOR
)

func (i FieldType) GetName() string {
Expand All @@ -48,14 +49,16 @@ func (i FieldType) GetName() string {
type FieldHandler struct {
statusRequestPattern *regexp.Regexp
calPattern *regexp.Regexp
monitorPattern *regexp.Regexp
salMonitorPattern *regexp.Regexp
mmiMonitorPattern *regexp.Regexp
}

func NewFieldHandler() FieldHandler {
return FieldHandler{
statusRequestPattern: regexp.MustCompile(`^status/(?P<statusRequestType>(?P<binary>binary)|level=0x(?P<startingGroupAddressLabel>00|20|40|60|80|A0|C0|E0))/(?P<application>.*)`),
calPattern: regexp.MustCompile(`^cal/(?P<unitAddress>.*)/(?P<calType>recall=\[(?P<recallParamNo>[\w\d]+), ?(?P<recallCount>\d+)]|identify=\[(?P<identifyAttribute>[\w\d]+)]|getstatus=\[(?P<getstatusParamNo>[\w\d]+), ?(?P<getstatusCount>\d+)])`),
monitorPattern: regexp.MustCompile(`^monitor/(?P<unitAddress>.*)/(?P<application>.*)`),
salMonitorPattern: regexp.MustCompile(`^salmonitor/(?P<unitAddress>.*)/(?P<application>.*)`),
mmiMonitorPattern: regexp.MustCompile(`^mmimonitor/(?P<unitAddress>.*)/(?P<application>.*)`),
}
}

Expand Down Expand Up @@ -196,7 +199,7 @@ func (m FieldHandler) ParseQuery(query string) (model.PlcField, error) {
default:
return nil, errors.Errorf("Invalid cal type %s", calTypeArgument)
}
} else if match := utils.GetSubgroupMatches(m.monitorPattern, query); match != nil {
} else if match := utils.GetSubgroupMatches(m.salMonitorPattern, query); match != nil {
var unitAddress readWriteModel.UnitAddress
{
unitAddressArgument := match["unitAddress"]
Expand Down Expand Up @@ -235,6 +238,45 @@ func (m FieldHandler) ParseQuery(query string) (model.PlcField, error) {
}

return NewSALMonitorField(unitAddress, application, 1), nil
} else if match := utils.GetSubgroupMatches(m.mmiMonitorPattern, query); match != nil {
var unitAddress readWriteModel.UnitAddress
{
unitAddressArgument := match["unitAddress"]
if unitAddressArgument == "*" {
unitAddress = nil
} else if strings.HasPrefix(unitAddressArgument, "0x") {
decodedHex, err := hex.DecodeString(unitAddressArgument[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")
}
unitAddress = readWriteModel.NewUnitAddress(decodedHex[0])
} else {
atoi, err := strconv.ParseUint(unitAddressArgument, 10, 8)
if err != nil {
return nil, errors.Errorf("Unknown unit address %s", unitAddressArgument)
}
unitAddress = readWriteModel.NewUnitAddress(byte(atoi))
}
}

var application readWriteModel.ApplicationIdContainer
{
applicationIdArgument := match["application"]
if applicationIdArgument == "*" {
application = readWriteModel.ApplicationIdContainer_RESERVED_FF
} else {
var err error
application, err = applicationIdFromArgument(applicationIdArgument)
if err != nil {
return nil, errors.Wrap(err, "Error getting application id from argument")
}
}
}

return NewMMIMonitorField(unitAddress, application, 1), nil
} else {
return nil, errors.Errorf("Unable to parse %s", query)
}
Expand Down
Loading

0 comments on commit 0458e79

Please sign in to comment.