Modbus TCP pooler

Post Reply
costi1010
Posts: 3
Joined: Tue Apr 07, 2020 8:55 pm

Modbus TCP pooler

Post by costi1010 » Tue Apr 07, 2020 9:07 pm

Hi Jean-Marc,

First Thanx for the great tools u providing. Great Work !!!
Quick question: Is there any .php or other pooler for meterN that can work with modbus tcp over IP (usually port 502) ?
I have seen that there are scripts out there like the one from gianfrdp /SDM120C that can read the parameters over an USBto RS485 adapter, though in my case I have a meter that has already integrated a modbus tcp server so that i can read the registers directly from ip with tools like modpoll.

Thanx and appreciated !!

jeanmarc
Posts: 2100
Joined: Thu Aug 29, 2013 7:16 am

Re: Modbus TCP pooler

Post by jeanmarc » Tue Apr 07, 2020 9:45 pm

Hi,
Thanks, well i'am not able to write such com app But, if you can retrieve values, that would be easy to integrate them.
Do you have an example of what it is output ?

costi1010
Posts: 3
Joined: Tue Apr 07, 2020 8:55 pm

Re: Modbus TCP pooler

Post by costi1010 » Tue Apr 07, 2020 10:36 pm

Hi,

Thanx for reply. Values are read over Modbus RTU Over TCP/IP from for ex i read 4 holding registers: Pa,Pb,Pc,Total power which are S16 values. I read them using a gui tool in windows called modpoll which allows me to quickly check the value of holding registers. I am not sure how to include an image in the forum to show that to you. i tried button above but didn't work for me. I feel embarrass not knowing in this forum format to attach a pic :(
Anyway i guess researching a bit u'r docu u do expect a specific format in the .json format like ID(value*unit) which means that i can use some tools to output the values in the expected specific format. This could be this one https://github.com/tallakt/modbus-cli
I'll give it a try with it to see how i can format the output so that it looks like the ones expected by meterN.

jeanmarc
Posts: 2100
Joined: Thu Aug 29, 2013 7:16 am

Re: Modbus TCP pooler

Post by jeanmarc » Wed Apr 08, 2020 3:33 am

Well you can paste RAW data with https://pastebin.com/
You can either choose JSON like {"elect": 1000} or the IEC 62056 data set structure like elect(1000*W), mind that the choose is application wide.

You can write your data formatter in the programming language you are more at ease with (C, CLI, python, ruby, PHP, ...)

costi1010
Posts: 3
Joined: Tue Apr 07, 2020 8:55 pm

Re: Modbus TCP pooler

Post by costi1010 » Tue Apr 14, 2020 8:42 pm

Hi Jeanmarc,

I was able to write a small comapp that is extracting any register u like using modbus tcp and display it in the IEC62056 format. So basically i used modpoll which is a command line tool being able to read modbus registers over tcp and u can install it practically on any distrib u want to run (https://www.modbusdriver.com/modpoll.html)
So based on this utility i wrote some code for shell that extracts the values from modbus registers, process them a bit and write them into metern txt files under /dev/shm To run this i used this command ->
./pooler485tcp.sh 192.168.100.200 1 14 27 41 45 173 > /dev/null 2>/dev/null &
which basically takes as inputs the registers i need to read from and pools for the values in a continuous loop and push them under /dev/shm/metern2.txt file
I run meterN inside a container on my QNAP NAS and with this pooler it works like a charm. Of course it looks like very newbie like code :roll: and not optimised at all since i run multiple modpoll commands one after the other but in principle with simple modpoll command we can bring any data we want in the IEC62056 format. One can get the idea behind and use it for their own meters where registers are of course different than mine.
Now i am trying to figure out how i can monitor the 3 phase system in meterN very efficiently hence the power meter i have is a bit more advanced(it's a power analyser from Pilot PMAC770 ) and i have a ton of parameters i can read from and use. (Trying to figure out in forum where to take an example on how to monitor 3 phase system)

Anyway many Thanx for the wonderful SW u have and the great job u've done !!!
Content of pooler485tcp.sh

Code: Select all

#!/bin/bash

#IP Address of the Modbus power meter i.e 192.168.100.200
ADDRESS="$1"
#Register value for the voltage  ex: 40001  coresponding with value 1 as register for modpoll command
V_REGISTER="$2"
#Register value for the Current ex: 40014 corresponding with value 14 as register for modpoll command
I_REGISTER="$3"
#Register value for the Active Power  ex: 40027 corresponding with value 27 as a register for modpoll command
P_REGISTER="$4"
#Register value for the Power Factor  ex: 40041 corresponding with value 41 as a register for modpoll command
POWER_FACTOR_REGISTER="$5"
#Register value for the Frequency  ex: 40045 corresponding with value 45 as a register for modpoll command
F_REGISTER="$6"
#Register value for the Energy  ex: 40173 corresponding with value 173 as a register for modpoll command
E_REGISTER="$7"

while [ true ]; do

#modpoll Command to retrieve 3 voltage registers corresponding to V_L1; V_L2; V_L3 in a three phase circuit
CMD_V="./modpoll -m tcp -t4 -r ${V_REGISTER} -c5 ${ADDRESS} -1"
sleep 0.3
#modpoll Command to retrieve 3 current registers corresponding to I_L1; I_L2; I_L3 in a three phase circuit
CMD_I="./modpoll -m tcp -t4 -r ${I_REGISTER} -c5 ${ADDRESS} -1"
sleep 0.3
#modpoll Command to retrieve 4 current registers corresponding to Active_Power_L1; Active_Power_L2; Active_Power_L3; Total_Active_Power in a three phase circuit
CMD_P="./modpoll -m tcp -t4 -r ${P_REGISTER} -c4 ${ADDRESS} -1"
sleep 0.3
#modpoll Command to retrieve 4 current registers corresponding to POWER_FACTOR_L1; POWER_FACTOR_L2; POWER_FACTOR_L3; TOTAL_POWER_FACTOR  in a three phase circuit
CMD_POWER_FACTOR="./modpoll -m tcp -t4 -r ${POWER_FACTOR_REGISTER} -c4 ${ADDRESS} -1"
sleep 0.3
#modpoll Command to retrieve 1 current register corresponding to FREQUENCY in a three phase circuit
CMD_FREQUENCY="./modpoll -m tcp -t4 -r ${F_REGISTER} -c1 ${ADDRESS} -1"
sleep 0.3
#modpoll Command to retrieve 1 current register corresponding to TOTAL ENERGY in a three phase circuit
CMD_ENERGY="./modpoll -m tcp -t4:int -r ${E_REGISTER} -c1 ${ADDRESS} -1"
sleep 0.3

#Processing Voltage Values
V_VALUE=$CMD_V

#Getting Modbus Voltage values from Voltage registers
MODBUS_VALUE_V_L1=$($V_VALUE |grep ${V_REGISTER}]: |awk -F: {'print $2'})
MODBUS_VALUE_V_L2=$($V_VALUE |grep $((${V_REGISTER}+1))]: |awk -F: {'print $2'})
MODBUS_VALUE_V_L3=$($V_VALUE |grep $((${V_REGISTER}+2))]: |awk -F: {'print $2'})
MODBUS_VALUE_V_AVERAGE=$($V_VALUE |grep $((${V_REGISTER}+4))]: |awk -F: {'print $2'})

#Scaling Values with defined register scaling unit (ex: for Voltage x 0.01, Unit: V)
VOLTAGE_L1="$((MODBUS_VALUE_V_L1 / 100)).$((MODBUS_VALUE_V_L1 % 100))"
VOLTAGE_L2="$((MODBUS_VALUE_V_L2 / 100)).$((MODBUS_VALUE_V_L2 % 100))"
VOLTAGE_L3="$((MODBUS_VALUE_V_L3 / 100)).$((MODBUS_VALUE_V_L3 % 100))"
VOLTAGE_V_AVERAGE="$(awk "BEGIN {print $MODBUS_VALUE_V_AVERAGE/100}")"

#Display Voltage Values
#echo VOLTAGE_V_L1=$VOLTAGE_L1
#echo VOLTAGE_V_L2=$VOLTAGE_L2
#echo VOLTAGE_V_L3=$VOLTAGE_L3
#echo VOLTAGE_V_AVERAGE=$VOLTAGE_V_AVERAGE
#echo ------------------------

#Processing Current Values
I_VALUE=$CMD_I

#Getting Modbus Current values from Current registers
MODBUS_VALUE_I_L1=$($I_VALUE |grep ${I_REGISTER}]: |awk -F: {'print $2'})
MODBUS_VALUE_I_L2=$($I_VALUE |grep $((${I_REGISTER}+1))]: |awk -F: {'print $2'})
MODBUS_VALUE_I_L3=$($I_VALUE |grep $((${I_REGISTER}+2))]: |awk -F: {'print $2'})
MODBUS_VALUE_I_NEUTRAL=$($I_VALUE |grep $((${I_REGISTER}+3))]: |awk -F: {'print $2'})
MODBUS_VALUE_I_AVERAGE=$($I_VALUE |grep $((${I_REGISTER}+4))]: |awk -F: {'print $2'})

#Scaling Values with defined register scaling unit (ex: for Current x 0.0001, Unit: A)
CURRENT_I_L1="$(awk "BEGIN {print ($MODBUS_VALUE_I_L1/1000)*2}")"
CURRENT_I_L2="$(awk "BEGIN {print ($MODBUS_VALUE_I_L2/1000)*2}")"
CURRENT_I_L3="$(awk "BEGIN {print ($MODBUS_VALUE_I_L3/1000)*2}")"
CURRENT_I_NEUTRAL="$(awk "BEGIN {print ($MODBUS_VALUE_I_NEUTRAL/1000)*2}")"
CURRENT_I_AVERAGE="$(awk "BEGIN {print ($MODBUS_VALUE_I_AVERAGE/1000)*2}")"
#Display Current Values
#echo CURRENT_I_L1=$CURRENT_I_L1
#echo CURRENT_I_L2=$CURRENT_I_L2
#echo CURRENT_I_L3=$CURRENT_I_L3
#echo CURRENT_I_NEUTRAL=$CURRENT_I_NEUTRAL
#echo CURRENT_I_AVERAGE=$CURRENT_I_AVERAGE
#echo --------------------------

#Processing Active Power Values
P_VALUE=$CMD_P

#Getting Modbus Active Power values from Power registers
MODBUS_VALUE_P_L1=$($P_VALUE |grep ${P_REGISTER}]: |awk -F: {'print $2'})
MODBUS_VALUE_P_L2=$($P_VALUE |grep $((${P_REGISTER}+1))]: |awk -F: {'print $2'})
MODBUS_VALUE_P_L3=$($P_VALUE |grep $((${P_REGISTER}+2))]: |awk -F: {'print $2'})
MODBUS_VALUE_P_TOT=$($P_VALUE |grep $((${P_REGISTER}+3))]: |awk -F: {'print $2'})

#Scaling Values with defined register scaling unit (ex: for Active Power x 2, Unit: W)
POWER_P_L1="$(awk "BEGIN {print $MODBUS_VALUE_P_L1*2}")"
POWER_P_L2="$(awk "BEGIN {print $MODBUS_VALUE_P_L2*2}")"
POWER_P_L3="$(awk "BEGIN {print $MODBUS_VALUE_P_L3*2}")"
POWER_P_TOT="$(awk "BEGIN {print $MODBUS_VALUE_P_TOT*2}")"

#Display Active Power  Values
#echo POWER_P_L1=$POWER_P_L1
#echo POWER_P_L2=$POWER_P_L2
#echo POWER_P_L3=$POWER_P_L3
#echo POWER_P_TOT=$POWER_P_TOT
#echo ------------------------

#Processing POWER FACTOR Values
POWER_FACTOR_VALUE=$CMD_POWER_FACTOR

#Getting Modbus Power Factor values from Power Factor registers
MODBUS_VALUE_POWER_FACTOR_L1=$($POWER_FACTOR_VALUE |grep ${POWER_FACTOR_REGISTER}]: |awk -F: {'print $2'})
MODBUS_VALUE_POWER_FACTOR_L2=$($POWER_FACTOR_VALUE |grep $((${POWER_FACTOR_REGISTER}+1))]: |awk -F: {'print $2'})
MODBUS_VALUE_POWER_FACTOR_L3=$($POWER_FACTOR_VALUE |grep $((${POWER_FACTOR_REGISTER}+2))]: |awk -F: {'print $2'})
MODBUS_VALUE_POWER_FACTOR_TOT=$($POWER_FACTOR_VALUE |grep $((${POWER_FACTOR_REGISTER}+3))]: |awk -F: {'print $2'})

#Scaling Values with defined register scaling unit (ex: for Power Factor  x 0.01)
POWER_FACTOR_L1="$(awk "BEGIN {print $MODBUS_VALUE_POWER_FACTOR_L1/1000}")"
POWER_FACTOR_L2="$(awk "BEGIN {print $MODBUS_VALUE_POWER_FACTOR_L2/1000}")"
POWER_FACTOR_L3="$(awk "BEGIN {print $MODBUS_VALUE_POWER_FACTOR_L3/1000}")"
POWER_FACTOR_TOT="$(awk "BEGIN {print $MODBUS_VALUE_POWER_FACTOR_TOT/1000}")"

#Display Power Factor  Values
#echo POWER_FACTOR_L1=$POWER_FACTOR_L1
#echo POWER_FACTOR_L2=$POWER_FACTOR_L2
#echo POWER_FACTOR_L3=$POWER_FACTOR_L3
#echo POWER_FACTOR_TOT=$POWER_FACTOR_TOT
#echo ----------------------------------

#Processing FREQUENCY Values
FREQUENCY_VALUE=$CMD_FREQUENCY

#Getting Modbus Frequency  values from Frequency registers
MODBUS_VALUE_FREQUENCY=$($FREQUENCY_VALUE |grep ${F_REGISTER}]: |awk -F: {'print $2'})

#Scaling Values with defined register scaling unit (ex: for Frequency  x 0.01)
FREQUENCY="$(awk "BEGIN {print $MODBUS_VALUE_FREQUENCY/100}")"

#Display Frequency  Value
#echo FREQUENCY=$FREQUENCY
#echo ----------------------------------

#Processing ENERGY Values
ENERGY_VALUE=$CMD_ENERGY

#Getting Modbus ENERGY  values from ENERGY registers
MODBUS_VALUE_ENERGY=$($ENERGY_VALUE |grep ${E_REGISTER}]: |awk -F: {'print $2'})

#Scaling Values with defined register scaling unit (ex: for ENERGY  x 0.1; Unit KWh)
ENERGY="$(awk "BEGIN {print $MODBUS_VALUE_ENERGY/10}")"

#Display ENERGY Value
#echo ENERGY=$ENERGY
#echo ----------------------------------

VOLTAGE=$VOLTAGE_V_AVERAGE
CURRENT=$CURRENT_I_AVERAGE
POWER=$POWER_P_TOT
FACTOR=$POWER_FACTOR_TOT
CHECK="OK"
ID=2

	if [ "$CHECK" = "OK" ]; then
		echo -e "$ID($POWER*W)\n$ID($ENERGY*Wh)\n${ID}_1($VOLTAGE*V)\n${ID}_2($CURRENT*A)\n${ID}_3($FREQUENCY*Hz)\n${ID}_4($FACTOR*F)" >  /dev/shm/metern$ID.txt
    else
        if [ -f /dev/shm/metern$ID.txt ]; then
            POWER="0.00"
            ENERGY=`sed -n '2p' /dev/shm/metern$ID.txt`
			VOLTAGE="0.00"
			CURRENT="0.00"
			FREQUENCY="0.00"
			FACTOR="0.00"
            echo -e "$ID($POWER*W)\n$ENERGY\n${ID}_1($VOLTAGE*V)\n${ID}_2($CURRENT*A)\n${ID}_3($FREQUENCY*Hz)\n${ID}_4($FACTOR*F)" > /dev/shm/metern$ID.txt
        fi
    fi
    sleep 2
done


jeanmarc
Posts: 2100
Joined: Thu Aug 29, 2013 7:16 am

Re: Modbus TCP pooler

Post by jeanmarc » Tue Apr 14, 2020 9:00 pm

Thanks, and thanks for sharing your code, keep up the work :clap:

Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest