Fix float conversion and startup connection issue in modbus input (#7002)

This commit is contained in:
Antonio Garcia 2020-02-10 18:54:33 -06:00 committed by GitHub
parent c681eb3524
commit 9d97ed22e6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 59 additions and 40 deletions

View File

@ -40,7 +40,6 @@ type Modbus struct {
type register struct {
Type string
RegistersRange []registerRange
ReadValue func(uint16, uint16) ([]byte, error)
Fields []fieldContainer
}
@ -48,7 +47,7 @@ type fieldContainer struct {
Name string `toml:"name"`
ByteOrder string `toml:"byte_order"`
DataType string `toml:"data_type"`
Scale float32 `toml:"scale"`
Scale float64 `toml:"scale"`
Address []uint16 `toml:"address"`
value interface{}
}
@ -155,13 +154,7 @@ func (m *Modbus) Init() error {
return fmt.Errorf("device name is empty")
}
err := connect(m)
if err != nil {
m.isConnected = false
return err
}
err = m.InitRegister(m.DiscreteInputs, cDiscreteInputs)
err := m.InitRegister(m.DiscreteInputs, cDiscreteInputs)
if err != nil {
return err
}
@ -224,21 +217,7 @@ func (m *Modbus) InitRegister(fields []fieldContainer, name string) error {
}
}
var fn func(uint16, uint16) ([]byte, error)
if name == cDiscreteInputs {
fn = m.client.ReadDiscreteInputs
} else if name == cCoils {
fn = m.client.ReadCoils
} else if name == cInputRegisters {
fn = m.client.ReadInputRegisters
} else if name == cHoldingRegisters {
fn = m.client.ReadHoldingRegisters
} else {
return fmt.Errorf("not Valid function")
}
m.registers = append(m.registers, register{name, registersRange, fn, fields})
m.registers = append(m.registers, register{name, registersRange, fields})
return nil
}
@ -306,6 +285,31 @@ func connect(m *Modbus) error {
}
}
func disconnect(m *Modbus) error {
u, err := url.Parse(m.Controller)
if err != nil {
return err
}
switch u.Scheme {
case "tcp":
m.tcpHandler.Close()
return nil
case "file":
if m.TransmissionMode == "RTU" {
m.rtuHandler.Close()
return nil
} else if m.TransmissionMode == "ASCII" {
m.asciiHandler.Close()
return nil
} else {
return fmt.Errorf("invalid protocol '%s' - '%s' ", u.Scheme, m.TransmissionMode)
}
default:
return fmt.Errorf("invalid controller")
}
}
func validateFieldContainers(t []fieldContainer, n string) error {
nameEncountered := map[string]bool{}
for _, item := range t {
@ -379,13 +383,27 @@ func removeDuplicates(elements []uint16) []uint16 {
return result
}
func readRegisterValues(m *Modbus, rt string, rr registerRange) ([]byte, error) {
if rt == cDiscreteInputs {
return m.client.ReadDiscreteInputs(uint16(rr.address), uint16(rr.length))
} else if rt == cCoils {
return m.client.ReadCoils(uint16(rr.address), uint16(rr.length))
} else if rt == cInputRegisters {
return m.client.ReadInputRegisters(uint16(rr.address), uint16(rr.length))
} else if rt == cHoldingRegisters {
return m.client.ReadHoldingRegisters(uint16(rr.address), uint16(rr.length))
} else {
return []byte{}, fmt.Errorf("not Valid function")
}
}
func (m *Modbus) getFields() error {
for _, register := range m.registers {
rawValues := make(map[uint16][]byte)
bitRawValues := make(map[uint16]uint16)
for _, rr := range register.RegistersRange {
address := rr.address
readValues, err := register.ReadValue(uint16(rr.address), uint16(rr.length))
readValues, err := readRegisterValues(m, register.Type, rr)
if err != nil {
return err
}
@ -530,23 +548,23 @@ func format32(f string, r uint32) interface{} {
}
}
func scale16toFloat32(s float32, v uint16) float32 {
return float32(v) * s
func scale16toFloat32(s float64, v uint16) float64 {
return float64(v) * s
}
func scale32toFloat32(s float32, v uint32) float32 {
return float32(v) * s
func scale32toFloat32(s float64, v uint32) float64 {
return float64(float64(v) * float64(s))
}
func scaleInt16(s float32, v int16) int16 {
return int16(float32(v) * s)
func scaleInt16(s float64, v int16) int16 {
return int16(float64(v) * s)
}
func scaleUint16(s float32, v uint16) uint16 {
return uint16(float32(v) * s)
func scaleUint16(s float64, v uint16) uint16 {
return uint16(float64(v) * s)
}
func scaleUint32(s float32, v uint32) uint32 {
func scaleUint32(s float64, v uint32) uint32 {
return uint32(float64(v) * float64(s))
}
@ -562,6 +580,7 @@ func (m *Modbus) Gather(acc telegraf.Accumulator) error {
err := m.getFields()
if err != nil {
disconnect(m)
m.isConnected = false
return err
}

View File

@ -125,7 +125,7 @@ func TestHoldingRegisters(t *testing.T) {
quantity uint16
byteOrder string
dataType string
scale float32
scale float64
write []byte
read interface{}
}{
@ -137,7 +137,7 @@ func TestHoldingRegisters(t *testing.T) {
dataType: "FLOAT32",
scale: 0.1,
write: []byte{0x08, 0x98},
read: float32(220),
read: float64(220),
},
{
name: "register0_register1_ab_float32",
@ -147,7 +147,7 @@ func TestHoldingRegisters(t *testing.T) {
dataType: "FLOAT32",
scale: 0.001,
write: []byte{0x00, 0x00, 0x03, 0xE8},
read: float32(1),
read: float64(1),
},
{
name: "register1_register2_abcd_float32",
@ -157,7 +157,7 @@ func TestHoldingRegisters(t *testing.T) {
dataType: "FLOAT32",
scale: 0.1,
write: []byte{0x00, 0x00, 0x08, 0x98},
read: float32(220),
read: float64(220),
},
{
name: "register3_register4_abcd_float32",
@ -167,7 +167,7 @@ func TestHoldingRegisters(t *testing.T) {
dataType: "FLOAT32",
scale: 0.1,
write: []byte{0x00, 0x00, 0x08, 0x98},
read: float32(220),
read: float64(220),
},
{
name: "register7_ab_float32",
@ -177,7 +177,7 @@ func TestHoldingRegisters(t *testing.T) {
dataType: "FLOAT32",
scale: 0.1,
write: []byte{0x01, 0xF4},
read: float32(50),
read: float64(50),
},
{
name: "register10_ab_uint16",