0

I'm trying to make a script to read holding registers from modbus TCP devices and insert the UINT32 decoded into MySQL :

  1. Read 2 registers with pymodbus
  2. Decode into uint32
  3. Insert decoded values into mySQL
  4. Start again every x minutes

I'm not a programmer and discovering Python.

I tried this code which seems to work but I do not understand everything, I do not know if it is the right solution to use "threading". Do you have something better to offer me?

Thank you

import time
import pymysql.cursors
from pymodbus.constants import Endian
from pymodbus.payload import BinaryPayloadDecoder
from threading import Thread, Lock
from pyModbusTCP.client import ModbusClient

# connect database
#sqlconnection = pymysql.connect(host='127.0.0.1',
#                             user='root',
#                             password='',
#                             database='database',
#                             charset='utf8mb4',
#                             cursorclass=pymysql.cursors.DictCursor)

# read devices informations (ID, IP, Port, Register address)
#with sqlconnection:
#    with sqlconnection.cursor() as cursor:
#        sql = "SELECT `dev_id`, H0.hw_address, H0.hw_port FROM `devicestatus` LEFT JOIN `hardware` H0 ON H0.hw_id = devicestatus.dev_hw_id WHERE H0.hw_enabled = 1 AND devicestatus.dev_used = 1 ORDER BY H0.hw_address, dev_name"
#        cursor.execute(sql,)
#        result = cursor.fetchall()



# sample of result
result = [{'dev_id': 7, 'hw_address': '127.0.0.1', 'hw_port': 502}, {'dev_id': 8, 'hw_address': '127.0.0.1', 'hw_port': 502}, {'dev_id': 9, 'hw_address': '127.0.0.1', 'hw_port': 502}]


# set global variables
regs = []
sf_value = 0


# init a thread lock
regs_lock = Lock()


# modbus polling thread
def polling_thread():
    global regs

    # polling loop
    while True:
        
        REGISTER_ADDRESS = 98 #First device is at address %MD100 (in Schneider M221 simulator), i dont' understand why i need to do -2

        # For each dictionary of the list, "extract" each value of element : information useful to launch Modbus requests, one per device.
        for val in result:
            # set modbusTCP variables :
            DEV_ID = val['dev_id']
            SERVER_HOST = val['hw_address']
            SERVER_PORT = val['hw_port']
            SERVER_ID = 1
            REGISTER_ADDRESS = REGISTER_ADDRESS + 2 # to read %MD100 %MD102 %MD104 ...
            REGISTER_COUNT = 2
            print("Target :", SERVER_HOST, SERVER_PORT, REGISTER_ADDRESS)

            client = ModbusClient(host=SERVER_HOST, port=int(SERVER_PORT), unit_id=int(SERVER_ID), auto_open=True, auto_close=True, timeout=2)
            
            # keep TCP open
            if not client.is_open():
                client.open()
            # do modbus reading on socket
            reg_read = client.read_holding_registers(REGISTER_ADDRESS, REGISTER_COUNT)


            # if read is ok, store result in regs (with thread lock synchronization)
            if reg_read:
                # decode the 2 registers into a 32 bit integer
                decoder = BinaryPayloadDecoder.fromRegisters(reg_read, byteorder=Endian.Big, wordorder=Endian.Little)
                sf_value = decoder.decode_32bit_int()

                with regs_lock:
                    regs = sf_value
                    print(regs)
                    # To do : insert each data into sql table
                    #with sqlconnection:
                        #with sqlconnection.cursor() as cursor:
                            # Create a new record
                            #sql = "INSERT INTO ...
        # x sec before next polling
        time.sleep(2)


# start polling thread
tp = Thread(target=polling_thread)
# set daemon: polling thread will exit if main thread exit
tp.daemon = True
tp.start()

# display loop (in main thread)
while True:
    # print regs (with thread lock synchronization)
    with regs_lock:
        #print(regs)
        print("What is this part ? everything is done in the polling_thread")
    # x sec before next print
    time.sleep(2)
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Makimax
  • 13
  • 2
  • Like this example ? https://pymodbus.readthedocs.io/en/latest/source/example/async_asyncio_client.html – Makimax Dec 23 '21 at 00:19
  • Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking. – Community Dec 29 '21 at 13:46

0 Answers0