Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modbus Input plugin #6154

Merged
merged 93 commits into from
Jan 29, 2020
Merged

Modbus Input plugin #6154

merged 93 commits into from
Jan 29, 2020

Conversation

garciaolais
Copy link
Contributor

@garciaolais garciaolais commented Jul 23, 2019

This adds a new input plugin for Modbus TCP/RTU protocol

closes #5412

Required for all PRs:

  • Signed CLA.
  • Associated README.md updated.
  • Has appropriate unit tests.

@danielnelson
Copy link
Contributor

@fdamador Can you review?

Does this supersede #4623?

@danielnelson
Copy link
Contributor

@garciaolais To get the tests running you will need to run dep ensure and commit the results.

@fdamador
Copy link

@fdamador Can you review?

Does this supersede #4623?

Yes, I've already reviewed his code except for the Test projects. Yes. This new commit from @garciaolais supersedes my #4623 plugin.

@danielnelson danielnelson mentioned this pull request Jul 25, 2019
3 tasks
@garciaolais
Copy link
Contributor Author

@garciaolais To get the tests running you will need to run dep ensure and commit the results.

Done 👍

@fdamador
Copy link

I've ran the modbust_test.go project and it covers about 77.5% of the code. I'll get some further test code added so that we can get this up to 100%. Will review over the weekend.

@garciaolais
Copy link
Contributor Author

We recently switched to using Go modules instead of dep, you can upgrade by removing Gopkg.lock and Gopkg.toml and then running make && make check, this should modify go.mod and go.sum and you should be good.

Hi

Do I need additional steps?

Maybe update my Makefile or something else.

Because if I remove the Gopkg.* files I get this error...

could not find project Gopkg.toml, use dep init to initiate a manifest

@fdamador
Copy link

fdamador commented Jan 26, 2020 via email

@danielnelson
Copy link
Contributor

@garciaolais Thanks for bearing with me during this transition, perhaps it will help if you merge the master branch? If that's not all there is to it, do you mind if I push to your branch and fix it?

@garciaolais
Copy link
Contributor Author

@garciaolais If that's not all there is to it, do you mind if I push to your branch and fix it?

@danielnelson any help is highly appreciated 👍

@danielnelson danielnelson merged commit 9389099 into influxdata:master Jan 29, 2020
@serrj-sv
Copy link

serrj-sv commented Feb 7, 2020

Is it possible to make a conversion to FLOAT32 more neat?
Using latest nightly, with following config
holding_registers = [ { name = "active_power", byte_order = "ABCD", data_type = "FLOAT32", scale=0.01, address = [50536,50537]}, ]
I get following result:
> modbus,host=influx,name=mon1.pdr1,type=holding_register active_power=99.72999572753906 1581094677000000000
Note amount of digits after point

@serrj-sv
Copy link

serrj-sv commented Feb 7, 2020

Found one more issue: if host associated with input plugin is down it prevents telegraf service from starting. Service goes into loop with following message:
E! [telegraf] Error running agent: could not initialize input inputs.modbus: dial tcp 10.0.4.70:502: i/o timeout
This one seems related to 3723

@danielnelson
Copy link
Contributor

On the float noise, we probably can't improve upon it. Could be interesting to see what value you get if you set the data type to UINT32 with no scale (just to look at the raw value). One thing that could possilby be done is a manual setting for precision and we could round the value. In most cases I would recommend handling this in the tool you are using to display the value.

@garciaolais For the initialization issue, would we be able to remove the connect function out of the Init function?

@serrj-sv
Copy link

serrj-sv commented Feb 7, 2020

Could be interesting to see what value you get if you set the data type to UINT32 with no scale (just to look at the raw value).

UINT32 (1.0) => FLOAT32 (0.01)
9928 => 99.27999877929688
9979 => 99.79000091552734
9930 => 99.29999542236328
9923 => 99.22999572753906
9917 => 99.16999816894531
9892 => 98.91999816894531

@danielnelson
Copy link
Contributor

Oh, yes we can fix this, we just need to convert to float64 before we apply the scale.

@garciaolais
Copy link
Contributor Author

Hi

@danielnelson @serrj-sv

Today I worked in these two issues PR-7002

@serrj-sv If you have a chance please test it 👍

@serrj-sv
Copy link

serrj-sv commented Feb 9, 2020

@garciaolais
Just tested:

  • connection issue seems fixed. I'll monitor how it works
  • for float conversion I get mixed result:
    1581256130000000000 95.33
    1581256140000000000 95.55
    1581256150000000000 95.97
    1581256160000000000 96.15
    1581256170000000000 96.75
    1581256180000000000 96.82000000000001
    1581256190000000000 97.18
    1581256200000000000 96.94
    1581256210000000000 96.24000000000001
    1581256220000000000 96.32000000000001
    1581256230000000000 95.76
    1581256240000000000 95.48
    1581256250000000000 95.63
    1581256260000000000 95.83
    1581256270000000000 96
    1581256280000000000 94.79
    1581256290000000000 94.63
  • Not an issue but rather suggestion/feature request: possibility to specify multiple hosts per "input" config section (for cases when you collect data from multiple SIMILAR devices). The way it works with inouts.snmp, for example

@garciaolais
Copy link
Contributor Author

garciaolais commented Feb 9, 2020

  • for float conversion I get mixed result:
    1581256130000000000 95.33
    1581256140000000000 95.55
    1581256150000000000 95.97
    1581256160000000000 96.15
    1581256170000000000 96.75
    1581256180000000000 96.82000000000001
    1581256190000000000 97.18
    1581256200000000000 96.94
    1581256210000000000 96.24000000000001
    1581256220000000000 96.32000000000001
    1581256230000000000 95.76
    1581256240000000000 95.48
    1581256250000000000 95.63
    1581256260000000000 95.83
    1581256270000000000 96
    1581256280000000000 94.79
    1581256290000000000 94.63

@serrj-sv Thanks for your feedback. I think the conversion its the normal result, please check the next example -> float64-golang

and this post -> why-am-i-losing-precision-while-converting-float32-to-float64

@fbergroth
Copy link

Hi, maybe I'm missing something, but is scale enough for input registers?

I have signals where the values needs to be remapped to a certain range, say [-50, 150], so I would need a way to specify an offset as well (or ideally just (min, max)).`

@danielnelson
Copy link
Contributor

@fbergroth Can you open a new feature request?

@fbergroth
Copy link

@danielnelson Sure: #7009

athoune pushed a commit to bearstech/telegraf that referenced this pull request Apr 17, 2020
@ToM-MaS
Copy link

ToM-MaS commented May 9, 2020

Hello everyone,
for testing I use a public demo device of a manufacturer.

The manufacturers manual shows this for the Modbus adress list:

Address	Format 	RD/WR 	Unit	Comment
19000 	FLOAT 	RD 	V 	Voltage L1-N
19002 	FLOAT 	RD 	V 	Voltage L2-N
19004 	FLOAT 	RD 	V 	Voltage L3-N
19006 	FLOAT 	RD 	V 	Voltage L1-L2
19008 	FLOAT 	RD 	V 	Voltage L2-L3
19010 	FLOAT 	RD 	V 	Voltage L1-L3

I have configured in telegraf.conf:

[[inputs.modbus]]
  name = "Device_UMG604"
  slave_id = 1

  ## Timeout for each request
  timeout = "1s"

  # TCP - connect via Modbus/TCP
  controller = "t<delete_this>cp:/<delete_this>/umg<delete_this>604.jani<delete_this>tza.de:5<delete_this>02"
 
 input_registers = [
    { name = "Voltage L1-N (V)",   byte_order = "ABCD",   data_type = "FLOAT32",   scale=1.0,     address = [19000,19001]},
  ]

When I click together a query in Chronograph (and modify the query as shown below), the left scale of the graph shows as values: 1.13e+9 Volt or 1.13B Volt. Expected would be something around 230.0 Volt (float value).

SELECT "Voltage L1-N (V)" AS "Voltage L1-N (V)" FROM "telegraf"."autogen"."modbus" WHERE time > :dashboardTime: AND time < :upperDashboardTime: AND "name"='Device_UMG604'

So I had it exported as CSV. It looks like this:

"time","modbus.Voltage L1-N (V)"
"2020-04-26T21:38:50.000Z","1130678532"
"2020-04-26T21:38:55.000Z","1130684293"
"2020-04-26T21:39:00.000Z","1130679969"
"2020-04-26T21:39:05.000Z","1130671574"
"2020-04-26T21:39:10.000Z","1130679470"
"2020-04-26T21:39:15.000Z","1130677593"
"2020-04-26T21:39:20.000Z","1130679974"
"2020-04-26T21:39:25.000Z","1130672015"
"2020-04-26T21:39:30.000Z","1130675830"
"2020-04-26T21:39:35.000Z","1130675929"
"2020-04-26T21:39:40.000Z","1130675135"
"2020-04-26T21:39:45.000Z","1130679073"

1st question:
It seems the values in InfuxDB are integer instead of float32. Is this expected?
Where can or should I change something to get float values in Chronograph? (e.g. the value for the upper example should be around e.g. 230.0 Volt)

2nd question:
How do I set that my modbus device is queried every 100ms? From the CSV values above it seems that there is a new row each 5 seconds. Not sure where this rythm comes from, does anyone know?!

@garciaolais
Copy link
Contributor Author

Hello @ToM-MaS

I can help you with your first question

1st question:
It seems the values in InfuxDB are integer instead of float32. Is this expected?
Where can or should I change something to get float values in Chronograph? (e.g. the value for the upper example should be around e.g. 230.0 Volt)

I read the documentation for your device UMG-604
image

Please note two things

  1. The byte order in your device
  2. Float values are in IEEE-754

So, I made a little test with my device

My Modbus Device
image

telegraf.conf

{ name = "VL1-N",byte_order = "ABCD",data_type = "FLOAT32-IEEE", scale=1.0, address = [2,1]}

modbus,host=9e88b516fd94,name=Device,type=holding_register

VL1-N= 228.78521728515625 ✨

PD. You can get the same value with different configuration for example

{ name = "VL1-N-ABCD",
byte_order = "ABCD",
data_type = "FLOAT32-IEEE",
scale=1.0,
address = [2,1]}

{ name = "VL1-N-CDAB",
byte_order = "CDAB",
data_type = "FLOAT32-IEEE",
scale=1.0,
address = [1,2]
}

@ToM-MaS
Copy link

ToM-MaS commented May 12, 2020

Hello @garciaolais
the byte order was OK but the "data_type = "FLOAT32-IEEE"" instead of "FLOAT32" gave me sane values.
So I'm wondering where the data type FLOAT32-IEEE is documented? Are there more data types of this kind?

BTW, I solved my question about the query frequency by adding the line interval = "100ms" to the inputs.modbus section:

[[inputs.modbus]]
  ## Query interval for each request
  interval = "100ms"

@garciaolais
Copy link
Contributor Author

So I'm wondering where the data type FLOAT32-IEEE is documented? Are there more data types of this kind?

Hello @ToM-MaS

Well, The device manufacturer define the datatype

You can find a lot of information about it in this link
https://en.wikipedia.org/wiki/Single-precision_floating-point_format

@ToM-MaS
Copy link

ToM-MaS commented May 12, 2020

Hello @garciaolais,
I think I understand now what you mean. I think I understand what FLOAT32-IEEE means.

The template configuration of the modbus plugin says about supported formats:
## data_type - INT16, UINT16, INT32, UINT32, INT64, UINT64, FLOAT32, FLOAT32-IEEE (the IEEE 754 binary representation)

So "DOUBLE64" and "DOUBLE64-IEEE" or something similar is not supported?
What about "LONG64", SHORT or STRING?

It would be intersting to know what datatypes are accepted in telegraf.conf besides the ones listed above.
Are the accepted datatype formats defined by the language specification of GO or by the source code of Telegraf / InfluxDB or by something else?

idohalevi pushed a commit to idohalevi/telegraf that referenced this pull request Sep 29, 2020
arstercz pushed a commit to arstercz/telegraf that referenced this pull request Mar 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/iot New plugins or features relating to IoT monitoring new plugin
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add Modbus Input Plugin