Repository: edgexfoundry/device-modbus-go
Pull request #513 (2023-10-24 03:16:05)

feat: Accept DISCRETES_INPUT and DISCRETE_INPUTS as primary table
Since the DISCRETES_INPUT looks like a fairly obvious typo, the best way is to accept both DISCRETE_INPUTS and DISCRETES_INPUT

<!-- Expected Commit Message Description (imported automatically by GitHub) -->
<!-- Must conform to [conventional commits guidelines](https://github.com/edgexfoundry/device-modbus-go/blob/main/.github/Contributing.md) -->
<!-- Expected Commit message must contain Closes/Fixes #IssueNumber statement when there is a related issue -->

<!-- Add additional detailed description of need for change if no related issue -->

**If your build fails** due to your commit message not passing the build checks, please review the guidelines here: https://github.com/edgexfoundry/device-modbus-go/blob/main/.github/Contributing.md

## PR Checklist
Please check if your PR fulfills the following requirements:

- [x] I am not introducing a breaking change (if you are, flag in conventional commit message with `BREAKING CHANGE:` describing the break)
- [x] I am not introducing a new dependency (add notes below if you are)
- [x] I have added unit tests for the new feature or bug fix (if not, why?)
- [x] I have fully tested (add details below) this the new feature or bug fix (if not, why?)
- [ ] I have opened a PR for the related docs change (if not, why?)
  <link to docs PR>

## Testing Instructions
<!-- How can the reviewers test your change? -->
Run unit test or run device service to verify the DISCRETE_INPUTS is available.

## New Dependency Instructions (If applicable)
<!-- Please follow [vetting instructions](https://wiki.edgexfoundry.org/display/FA/Vetting+Process+for+3rd+Party+Dependencies) and place results here -->


Patch:
diff --git a/internal/driver/constant.go b/internal/driver/constant.go
index 295ce7c..7f1a957 100644
--- a/internal/driver/constant.go
+++ b/internal/driver/constant.go
@@ -25,6 +25,7 @@ const (
 	FLOAT64 = "FLOAT64"
 
 	DISCRETES_INPUT   = "DISCRETES_INPUT"
+	DISCRETE_INPUTS   = "DISCRETE_INPUTS" // since DISCRETES_INPUT looks like a typo and it come from Modbus spec, so we also support DISCRETE_INPUTS as primary table
 	COILS             = "COILS"
 	INPUT_REGISTERS   = "INPUT_REGISTERS"
 	HOLDING_REGISTERS = "HOLDING_REGISTERS"
@@ -43,6 +44,7 @@ const (
 
 var PrimaryTableBitCountMap = map[string]uint16{
 	DISCRETES_INPUT:   1,
+	DISCRETE_INPUTS:   1,
 	COILS:             1,
 	INPUT_REGISTERS:   16,
 	HOLDING_REGISTERS: 16,
diff --git a/internal/driver/modbusclient.go b/internal/driver/modbusclient.go
index 837429b..a76853a 100644
--- a/internal/driver/modbusclient.go
+++ b/internal/driver/modbusclient.go
@@ -64,7 +64,7 @@ func (c *ModbusClient) GetValue(commandInfo interface{}) ([]byte, error) {
 	var err error
 
 	switch modbusCommandInfo.PrimaryTable {
-	case DISCRETES_INPUT:
+	case DISCRETES_INPUT, DISCRETE_INPUTS:
 		response, err = c.client.ReadDiscreteInputs(modbusCommandInfo.StartingAddress, modbusCommandInfo.Length)
 	case COILS:
 		response, err = c.client.ReadCoils(modbusCommandInfo.StartingAddress, modbusCommandInfo.Length)
@@ -94,7 +94,7 @@ func (c *ModbusClient) SetValue(commandInfo interface{}, value []byte) error {
 	var err error
 
 	switch modbusCommandInfo.PrimaryTable {
-	case DISCRETES_INPUT:
+	case DISCRETES_INPUT, DISCRETE_INPUTS:
 		err = fmt.Errorf("Error: DISCRETES_INPUT is Read-Only..!!")
 
 	case COILS:


Test patch:
diff --git a/internal/driver/deviceclient_test.go b/internal/driver/deviceclient_test.go
index 00bef75..8a2c09f 100644
--- a/internal/driver/deviceclient_test.go
+++ b/internal/driver/deviceclient_test.go
@@ -209,17 +209,33 @@ func TestTransformDataBytesToResult_BOOL(t *testing.T) {
 			STARTING_ADDRESS: 10,
 		},
 	}
-	commandInfo, err := createCommandInfo(&req)
-	require.NoError(t, err)
-	dataBytes := []byte{1} // => 00000001
-	expected := true
 
-	commandValue, err := TransformDataBytesToResult(&req, dataBytes, commandInfo)
-	require.NoError(t, err)
-	result, err := commandValue.BoolValue()
-	require.NoError(t, err)
-
-	assert.Equal(t, expected, result)
+	tests := []struct {
+		name         string
+		primaryTable string
+		data         []byte
+		expected     bool
+	}{
+		{"transform true value from DISCRETES_INPUT", DISCRETES_INPUT, []byte{1}, true},
+		{"transform false value from DISCRETES_INPUT", DISCRETES_INPUT, []byte{0}, false},
+		{"transform true value from DISCRETE_INPUTS", DISCRETE_INPUTS, []byte{1}, true},
+		{"transform false value from DISCRETE_INPUTS", DISCRETE_INPUTS, []byte{0}, false},
+		{"transform true value from COILS", COILS, []byte{1}, true},
+		{"transform false value from COILS", COILS, []byte{0}, false},
+	}
+	for _, testCase := range tests {
+		t.Run(testCase.name, func(t *testing.T) {
+			req.Attributes[PRIMARY_TABLE] = testCase.primaryTable
+			commandInfo, err := createCommandInfo(&req)
+			require.NoError(t, err)
+			commandValue, err := TransformDataBytesToResult(&req, testCase.data, commandInfo)
+			require.NoError(t, err)
+			result, err := commandValue.BoolValue()
+			require.NoError(t, err)
+
+			assert.Equal(t, testCase.expected, result)
+		})
+	}
 }
 
 func TestTransformDataBytesToResult_RawType_INT16_ValueType_FLOAT32(t *testing.T) {