FOR TIPS, gUIDES & TUTORIALS

subscribe to our Youtube

GO TO YOUTUBE

14455 questions

17168 answers

28195 comments

0 members

We are migrating to our new platform at https://community.teltonika.lt. Moving forward, you can continue discussions on this new platform. This current platform will be temporarily maintained for reference purposes.
0 votes
758 views 6 comments
by anonymous
I have made a python script which sends data to the thingsboard cloud only when it has changed and in a format the is usable in thingsboard cloud. I now need to get data from modbus device 1 to use this in the python script. How do I do that ?

1 Answer

0 votes
by anonymous

Hello,

It is possible to send Modbus requests from the command line using ubus. You can also use this command to request info from the RUT itself if it is configured as Modbus TCP slave.

To read from Modbus slave, you can use the following command:

  • ubus call modbus_master tcp.test

For information:

  • ubus -v list modbus_master 

For example:

  • ubus call modbus_master tcp.test '{"ip":"192.168.1.10", "port":502, "id":1, "timeout":1, "function":3, "first_reg":1, "reg_count":"2", "data_type":"16bit_int_hi_first", "no_brackets":1}'

You can parse the response using Python, which would probably be easier. But you can also use 'sed', for example:

  • ubus call modbus_master tcp.test '{"ip":"192.168.155.1", "port":502, "id":1, "timeout":1, "function":3, "first_reg":8, "reg_count":"3", "data_type":"ascii", "no_brackets":1}' | sed -n 's/.*"result": "\(.*\)".*/\1/p'

Make sure to adjust the commands to your needs. For instance, you can use function 3 for reading and function 6 for writing. As for the available data types (and other options), you can configure a modbus request in the modbus master section of the WebUI and verify the data type in the modbus_master configuration file by running the following command:

  • cat /etc/config/modbus_master

The config will show you your configured requests and their data types.

Kind Regards,

Andzej

by anonymous

I tried to put  your suggestion in my python script. I get a syntax error. It is difficult to see but it points at the comma after the "regcount":"2".



ubus call modbus_master tcp.test '{"ip":"192.168.178.80", "port":502, "id":1, "timeout":1, "function":3, "first_reg":1, "reg_c
ount":"2", "data_type":"16bit_int_hi_first", "no_brackets":1}'
^
SyntaxError: invalid syntax




by anonymous

Hi,

I do not see the output properly. Could try to paste it again? Also, ensure that there are no new lines or breaks that may have occurred during the copy-pasting. It happens quite often.

Also, you can pass json. Shell example:

#!/bin/sh

a=$1

b=$2

c=$3

json=$(printf '{"ip":"127.0.0.1","port":502,"id":1,"timeout":1,"function":3,"first_reg":%d,"reg_count":"%s","data_type":"%s","no_brackets":1}' "$a" "$b" "$c")

ubus call modbus_master tcp.test "$json"

For example:

  • sh /etc/script.sh 8 3 ascii

Kind Regards,

by anonymous

I am not sure we are talking about the same thing. I want to do all in a python script. This is now my script. However when running it in the CLI environment it doesnt accept a=$1.

Copying it from the CLI environment doesnt show the entire line for json=$(printf '{"ip":"192.1 .. but this is completely as in your suggestion.

import time                    

import datetime                

import json                                                                                                                       

import requests                                                                                                                    

                                                                    

print('hello_world')                   

print('hello_world2')                           

                               

presentDate = datetime.datetime.now()                                                                                              

                                           

unix_timestamp = round(datetime.datetime.timestamp(presentDate)*1000)

                                                

print(unix_timestamp)           

                               

a=$1                                                                                                                              

                                           

b=$2                                    

                                                

c=$3                     

                               

json=$(printf '{"ip":"192.168.178.80","port":502,"id":1,"timeout":1,"function":3,"first_reg":%d,"reg_count":"%s","data_type":"%s","

                                           

ubus call modbus_master tcp.test "$json"

by anonymous

Hello,

Yes, this will not work if you paste it into your Python script directly, because it is a shell command. I suggested a shell command that can be used to query Modbus slave devices from RUT using ubus. You will need to run this as a shell command from your Python code, so you need to handle that in your Python code.

For example:

import subprocess

import json

first_reg = 8

reg_count = "3"

data_type = "ascii"

cmd = f"ubus call modbus_master tcp.test '{{\"ip\":\"192.168.11.11\",\"port\":502,\"id\":1,\"timeout\":1,\"function\":3,\"first_reg\":{first_reg},\"reg_count\":\"{reg_count}\",\"data_type\":\"{data_type}\",\"no_brackets\":1}}'"

result = subprocess.run(cmd, shell=True, capture_output=True)

data = json.loads(result.stdout)

print(data)

Output:

Kind Regards,

Andzej

by anonymous

Thanks a lot that works perfect. I have two more questions.

1. What is the datatype for a unsigned 32 bit. For 16 bit it is 16bit_int_hi_first but I can't find the possible datatypes.

I also saw the option to use it without a shell command like below but I cant get this to work as the CLI python program keeps complaining that it has no pymodbus module. 

from pymodbus.client import ModbusTcpClient

client = ModbusTcpClient('127.0.0.1')
client.connect()
client.write_coil(1, True)
result = client.read_coils(1,1)
print(result.bits[0])
client.close()
by anonymous

Hello,

  

The ubus parameter for 32-bit unsigned integer is 32bit_uint1234.

As for the pymodbus, the issue is as the error suggests - you need to have the pymodbus library installed to use this feature.

  

Best regards,
DaumantasG