Fix float conversion and startup connection issue in modbus input (#7002)
This commit is contained in:
parent
c681eb3524
commit
9d97ed22e6
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
Loading…
Reference in New Issue