Python Forum
Simple syntax to asynchronously get access to MODBUS register
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Simple syntax to asynchronously get access to MODBUS register
#1
I am trying to run three simple tasks in parallel using asyncio and sharing global variables.
Two of them are working perfectly. One read websockets ("async with websockets.connect("ws://192.168.1.137:9000") as websocket:" Another one access IO via a dedicated library.
I did not find any solution and the good syntax for getting AsyncModbusTCPClient running within the third task (sync MODBUS is easy to implement but would not fit within async task)
The following would just block everything:
    async def get_var_modbus(loop):
        client = await AsyncModbusTCPClient( schedulers.ASYNC_IO,host="192.168.1.200", loop=loop, port=502, timeout=20, unit=3)
        while True:
            print("INIT")
            print("Reading coils")
            rr = await client.read_input_registers(0, 1, unit=0x03)
            print(rr.registers)
            await asyncio.sleep(1)
Full code below
    from pymodbus.client.asynchronous import schedulers
    from pymodbus.client.asynchronous.tcp import AsyncModbusTCPClient
    import json
    import time
    from pypx800v5 import *
    import aiohttp
    import asyncio
    import requests_async as requests
    import numpy as np
    import logging
    from datetime import datetime
    import websockets
    import contextvars
    import warnings
    warnings.filterwarnings("ignore", category=DeprecationWarning) 
    # SDM230 via MODBUS
    
    SDM230A=["Voltage","Current","Active Power","Apparent Power","Reactive Power","Power Factor","Phase Angle","Frequency","Import Active Energy","Export Active Energy","Import Reactive Energy","Export Reactive Energy"]
    SDM230B=["Total system power demand","Maximum total system power demand","Current system positive power demand","Maximum system positive power demand","Current system reverse power demand","Maximum system reverse power demand"]
    SDM230C=["Current demand","Maximum current Demand"]
    SDM230D=["Total Active Energy","Total Reactive Energy"]
    SDM230Labels=SDM230A+SDM230B+SDM230C+SDM230D
    SDM230Var=["Voltage","Current","ActivePower","ApparentPower","ReactivePower","PowerFactor","PhaseAngle","Frequency","ImportActiveEnergy","ExportActiveEnergy","ImportReactiveEnergy","ExportReactiveEnergy","TotalSysPowerDemand","MaxTotalSysPowerDemand","CurrentSysPositivePowerDemand","MaxSysPositivePowerDemand","CurrentSysReversePowerDemand","MaxSysReversePowerDemand","CurrentDemand","MaximumCurrentDemand","TotalActiveEnergy","TotalReactiveEnergy"]
    VoltageAdd=262199
    CurrentAdd=262200
    ActivePowerAdd=262201
    ImportActiveEnergyAdd=262202
    
    # inversor via Websockets
    TempChaudiereAdd=262198
    PuissMaxChauffeauAdd=262193
    WREDAdd=262194
    PacBat6TLAdd=262195
    totPVAdd=262196
    SOC6TLAdd=262197
    
    
    # shared variables
    
    WRED= 0
    PacBat6TL=0
    PacPV6TL=0
    Pac6TLM=0
    SOC6TL=0
    PAC6TL=0
    totPV=0
    

    
    
    
    # --------------------------------------------------------------------------- #
    # configure the client logging
    # --------------------------------------------------------------------------- #
    
    logging.basicConfig()
    log = logging.getLogger()
    log.setLevel(logging.DEBUG)
    
    async def get_var_modbus(loop):
        client = await AsyncModbusTCPClient( schedulers.ASYNC_IO,host="192.168.1.200", port=502, loop=loop, timeout=20, unit=3)
        while True:
            print("INIT")
            print("Reading coils")
            rr = await client.read_input_registers(0, 1, unit=0x03)
            print(rr.registers)
            await asyncio.sleep(1)
    
    
    
    async def get_var_socket():
        global WRED
        global PacBat6TL
        global PacPV6TL
        global Pac6TLM
        global SOC6TL
        global PAC6TL
        global totPV
        print("")
        i=0
        dict={}
        async with websockets.connect("ws://192.168.1.137:9000") as websocket:
                while True:
                    i=i+1
                    data=(await websocket.recv())
                    try:
                        message=json.loads(data)
                    except:
                        break           
                    if  "product" in message:
                        if message["product"]=="ems":
                            print(message)
                            if "WRED" in message:
                                WRED=message["WRED"]                    
                            if "PacBat6TL" in message:
                                PacBat6TL=message["PacBat6TL"]
                            if "PacPV6TL" in message:
                                PacPV6TL=message["PacPV6TL"]
                                totPV=PacPV6TL
                            if "Pac6TLM" in message:
                                Pac6TLM=message["Pac6TLM"]
                                totPV=totPV+Pac6TLM
                            if "SOC6TL" in message:
                                SOC6TL=message["SOC6TL"]
                            if "PAC6TL" in message:
                                PAC6TL=message["PAC6TL"]
    
    async def get_ipx_update():
        print("")
        i=0
        dict={}
        async with IPX800(host='192.168.1.139', api_key='API') as ipx:
                await ipx.init_config()
                while True:
                    try:
                        await ipx.update_ana(WREDAdd,WRED)
                    except:
                        print("ERROR")
                    try:
                        await ipx.update_ana(PacBat6TLAdd,PacBat6TL)
                    except:
                        print("ERROR")
                    try:
                        await ipx.update_ana(totPVAdd,totPV)
                    except:
                        print("ERROR")
                    try:
                        await ipx.update_ana(SOC6TLAdd,SOC6TL)
                    except:
                       print("ERROR")
                    await asyncio.sleep(1)
    
    
    def main():   
        loop = asyncio.get_event_loop()   
        loop.create_task(get_var_socket())
        loop.create_task(get_ipx_update())
        loop.create_task(get_var_modbus(loop))    
        loop.run_forever()
    
    
    if __name__ == '__main__':
        try:
            main()
        except Exception as f:
            print('main error: ', f)
            sleep(3)
Reply
#2
Using the async_modbus library (built on the top of umodbus https://pypi.org/project/async-modbus/) it works very well. I have used this library with success. Please find below the syntax,
async def get_var_modbus(loop):
   reader, writer = await asyncio.open_connection('192.168.1.200', 502)
   client = AsyncTCPClient((reader, writer))loop=loop, port=502, timeout=20, unit=3)
        while True:
            print("Reading holding registers ADAM3066")
            reply = await client.read_holding_registers(slave_id=3, starting_address=0, quantity=8)
           
            print("reply:",reply)
      

  await asyncio.sleep(1)
OUTPUT:
Reading holding registers ADAM3066
reply: [65535 65535 65535 65535 289 65535 65535 65535]

The ADAM 3066 is a RS-485 MODBUS RTU 1-WIRE interface connected to a MODBUS TCP gateway at 192.168.1.200, I have one sensor connected on the input 5 of ADAM 3066 which return a temperature of 28.9 degrees C
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Pymodbus Write value to register stsxbel 10 8,198 Aug-18-2022, 01:42 PM
Last Post: DeaD_EyE
  Modbus-tk library catching modbus-tk exception zazas321 1 2,107 Nov-10-2020, 03:06 PM
Last Post: Larz60+
  simple f-string expressions to access a dictionary Skaperen 0 1,531 Jul-15-2020, 05:04 AM
Last Post: Skaperen
  Login and Register system finndude 1 2,408 Apr-24-2020, 10:05 PM
Last Post: deanhystad
  AttributeError: 'Register' object has no attribute 'bit_7' colt 1 2,001 Dec-12-2019, 09:39 PM
Last Post: micseydel
  simple syntax question speedskis777 7 3,599 Mar-11-2019, 02:26 AM
Last Post: snippsat
  How to implement class register? AlekseyPython 0 1,996 Feb-14-2019, 06:19 AM
Last Post: AlekseyPython
  simple register code aocii 2 2,637 Dec-22-2018, 11:15 AM
Last Post: aocii
  Segmentation fault when connecting to modbus device with Libmodbus alice 0 2,457 Dec-18-2018, 04:03 PM
Last Post: alice
  Python script runs on startup but does not register keystrokes. mericanpi 3 3,465 Sep-07-2018, 02:58 PM
Last Post: mericanpi

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020