How to get rid of LoopingCall in python code

339 views Asked by At

I'm using Modbus server example code from pymodbus library to make a data forwarder (reading some serial data, formatting and then assigning data to modbus registers for Modbus master to read). My issue is serial delay (reading from 6 different devices, each device has a 5 sec delay, but it's random, they not sending data at the same time). In this example they use LoopingCall, which is bad for my timing. How do I get rid of it, so I can call function myself?

I tried just to get rid of :

time = 2 # Update delay
loop = LoopingCall(f=updating_writer, a=(context,))
loop.start(time, now=False)

And simply call:

updating_writer()

But obviously I'm missing some arguments:

a=(context,)

Part of my code:

def data_decoder6():
    ser_read_JB1 = ser_JB6.read(386)
    if len(ser_read_JB1) != 0:
        # convert ascii to hex
        aTOh_JB1 = "".join("{:02x}".format(c) for c in ser_read_JB1)
        # convert to string
        iTOs_JB1 = str(aTOh_JB1)
        lokacija = [258,422,426,414,402,406,266,274,270,558,
                    530,534,538,322,326,330,334,338,342,346,
                    350,354,358,362,366,370,374,378,382,386,
                    390,394,398
                        ]
        values_JB1 = [0 for d in range(33)] 
        values_2_JB6 = [0 for e in range(33)]
        for x in range(0, 33):
            values_JB1[x] = (iTOs_JB1[lokacija[x]] + iTOs_JB1[lokacija[x]+1] 
                           + iTOs_JB1[lokacija[x]+2] + iTOs_JB1[lokacija[x]+3])
            #values1 = values.replace('"', '') 
            values_2_JB6[x] = int(values_JB1[x], 16)
            #values.append( 2009 )
        return values_2_JB6
    else:
    values_2_JB6 = [0 for e in range(33)]
    return values_2_JB6

def updating_writer(a):
    allValues = [0 for d in range(198)]
    allValues = (data_decoder1() + data_decoder2() + data_decoder3() + 
    data_decoder4() + data_decoder5() + data_decoder6())
    # modbus part
    log.debug("updating the context")
        context  = a[0]
        register = 0x03
        slave_id = 0x01
        address  = 0x01
        values   = context[slave_id].getValues(register, address, count=198)
        values   = allValues
        log.debug("new values: " + str(values))
        context[slave_id].setValues(register, address, values)

def run_updating_server():
    store = ModbusSlaveContext(
        di = ModbusSequentialDataBlock(0, [0]*1),
        co = ModbusSequentialDataBlock(0, [0]*1),
        hr = ModbusSequentialDataBlock(0, [0]*198),
        ir = ModbusSequentialDataBlock(0, [0]*1))

    context = ModbusServerContext(slaves=store, single=True)
    identity = ModbusDeviceIdentification()
    identity.VendorName  = 'pymodbus'
    identity.ProductCode = 'PM'
    identity.VendorUrl   = 'http://github.com/bashwork/pymodbus/'
    identity.ProductName = 'pymodbus Server'
    identity.ModelName   = 'pymodbus Server'
    identity.MajorMinorRevision = '1.0'

    time = 2 # Update delay
    loop = LoopingCall(f=updating_writer, a=(context,))
    loop.start(time, now=False)
    StartTcpServer(context, identity=identity, address=("10.10.10.253", 502))

run_updating_server()
1

There are 1 answers

2
Jean-Paul Calderone On

This code

loop = LoopingCall(f=updating_writer, a=(context,))
loop.start(time, now=False)

causes

updating_writer(context)

every time seconds (with no call made immediately on the call to loop.start).

So, if you want to get rid of the LoopingCall, you can replace it with equivalent calls to updating_writer(context) scheduled however you prefer.