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 register struct {
|
||||||
Type string
|
Type string
|
||||||
RegistersRange []registerRange
|
RegistersRange []registerRange
|
||||||
ReadValue func(uint16, uint16) ([]byte, error)
|
|
||||||
Fields []fieldContainer
|
Fields []fieldContainer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +47,7 @@ type fieldContainer struct {
|
||||||
Name string `toml:"name"`
|
Name string `toml:"name"`
|
||||||
ByteOrder string `toml:"byte_order"`
|
ByteOrder string `toml:"byte_order"`
|
||||||
DataType string `toml:"data_type"`
|
DataType string `toml:"data_type"`
|
||||||
Scale float32 `toml:"scale"`
|
Scale float64 `toml:"scale"`
|
||||||
Address []uint16 `toml:"address"`
|
Address []uint16 `toml:"address"`
|
||||||
value interface{}
|
value interface{}
|
||||||
}
|
}
|
||||||
|
@ -155,13 +154,7 @@ func (m *Modbus) Init() error {
|
||||||
return fmt.Errorf("device name is empty")
|
return fmt.Errorf("device name is empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
err := connect(m)
|
err := m.InitRegister(m.DiscreteInputs, cDiscreteInputs)
|
||||||
if err != nil {
|
|
||||||
m.isConnected = false
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = m.InitRegister(m.DiscreteInputs, cDiscreteInputs)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -224,21 +217,7 @@ func (m *Modbus) InitRegister(fields []fieldContainer, name string) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var fn func(uint16, uint16) ([]byte, error)
|
m.registers = append(m.registers, register{name, registersRange, fields})
|
||||||
|
|
||||||
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})
|
|
||||||
|
|
||||||
return nil
|
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 {
|
func validateFieldContainers(t []fieldContainer, n string) error {
|
||||||
nameEncountered := map[string]bool{}
|
nameEncountered := map[string]bool{}
|
||||||
for _, item := range t {
|
for _, item := range t {
|
||||||
|
@ -379,13 +383,27 @@ func removeDuplicates(elements []uint16) []uint16 {
|
||||||
return result
|
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 {
|
func (m *Modbus) getFields() error {
|
||||||
for _, register := range m.registers {
|
for _, register := range m.registers {
|
||||||
rawValues := make(map[uint16][]byte)
|
rawValues := make(map[uint16][]byte)
|
||||||
bitRawValues := make(map[uint16]uint16)
|
bitRawValues := make(map[uint16]uint16)
|
||||||
for _, rr := range register.RegistersRange {
|
for _, rr := range register.RegistersRange {
|
||||||
address := rr.address
|
address := rr.address
|
||||||
readValues, err := register.ReadValue(uint16(rr.address), uint16(rr.length))
|
readValues, err := readRegisterValues(m, register.Type, rr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -530,23 +548,23 @@ func format32(f string, r uint32) interface{} {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func scale16toFloat32(s float32, v uint16) float32 {
|
func scale16toFloat32(s float64, v uint16) float64 {
|
||||||
return float32(v) * s
|
return float64(v) * s
|
||||||
}
|
}
|
||||||
|
|
||||||
func scale32toFloat32(s float32, v uint32) float32 {
|
func scale32toFloat32(s float64, v uint32) float64 {
|
||||||
return float32(v) * s
|
return float64(float64(v) * float64(s))
|
||||||
}
|
}
|
||||||
|
|
||||||
func scaleInt16(s float32, v int16) int16 {
|
func scaleInt16(s float64, v int16) int16 {
|
||||||
return int16(float32(v) * s)
|
return int16(float64(v) * s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func scaleUint16(s float32, v uint16) uint16 {
|
func scaleUint16(s float64, v uint16) uint16 {
|
||||||
return uint16(float32(v) * s)
|
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))
|
return uint32(float64(v) * float64(s))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -562,6 +580,7 @@ func (m *Modbus) Gather(acc telegraf.Accumulator) error {
|
||||||
|
|
||||||
err := m.getFields()
|
err := m.getFields()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
disconnect(m)
|
||||||
m.isConnected = false
|
m.isConnected = false
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,7 +125,7 @@ func TestHoldingRegisters(t *testing.T) {
|
||||||
quantity uint16
|
quantity uint16
|
||||||
byteOrder string
|
byteOrder string
|
||||||
dataType string
|
dataType string
|
||||||
scale float32
|
scale float64
|
||||||
write []byte
|
write []byte
|
||||||
read interface{}
|
read interface{}
|
||||||
}{
|
}{
|
||||||
|
@ -137,7 +137,7 @@ func TestHoldingRegisters(t *testing.T) {
|
||||||
dataType: "FLOAT32",
|
dataType: "FLOAT32",
|
||||||
scale: 0.1,
|
scale: 0.1,
|
||||||
write: []byte{0x08, 0x98},
|
write: []byte{0x08, 0x98},
|
||||||
read: float32(220),
|
read: float64(220),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "register0_register1_ab_float32",
|
name: "register0_register1_ab_float32",
|
||||||
|
@ -147,7 +147,7 @@ func TestHoldingRegisters(t *testing.T) {
|
||||||
dataType: "FLOAT32",
|
dataType: "FLOAT32",
|
||||||
scale: 0.001,
|
scale: 0.001,
|
||||||
write: []byte{0x00, 0x00, 0x03, 0xE8},
|
write: []byte{0x00, 0x00, 0x03, 0xE8},
|
||||||
read: float32(1),
|
read: float64(1),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "register1_register2_abcd_float32",
|
name: "register1_register2_abcd_float32",
|
||||||
|
@ -157,7 +157,7 @@ func TestHoldingRegisters(t *testing.T) {
|
||||||
dataType: "FLOAT32",
|
dataType: "FLOAT32",
|
||||||
scale: 0.1,
|
scale: 0.1,
|
||||||
write: []byte{0x00, 0x00, 0x08, 0x98},
|
write: []byte{0x00, 0x00, 0x08, 0x98},
|
||||||
read: float32(220),
|
read: float64(220),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "register3_register4_abcd_float32",
|
name: "register3_register4_abcd_float32",
|
||||||
|
@ -167,7 +167,7 @@ func TestHoldingRegisters(t *testing.T) {
|
||||||
dataType: "FLOAT32",
|
dataType: "FLOAT32",
|
||||||
scale: 0.1,
|
scale: 0.1,
|
||||||
write: []byte{0x00, 0x00, 0x08, 0x98},
|
write: []byte{0x00, 0x00, 0x08, 0x98},
|
||||||
read: float32(220),
|
read: float64(220),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "register7_ab_float32",
|
name: "register7_ab_float32",
|
||||||
|
@ -177,7 +177,7 @@ func TestHoldingRegisters(t *testing.T) {
|
||||||
dataType: "FLOAT32",
|
dataType: "FLOAT32",
|
||||||
scale: 0.1,
|
scale: 0.1,
|
||||||
write: []byte{0x01, 0xF4},
|
write: []byte{0x01, 0xF4},
|
||||||
read: float32(50),
|
read: float64(50),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "register10_ab_uint16",
|
name: "register10_ab_uint16",
|
||||||
|
|
Loading…
Reference in New Issue