Async Server, changing or accessing Datastore while running

558 views
Skip to first unread message

Joe Wilcoxson

unread,
Jan 18, 2013, 11:11:36 AM1/18/13
to pymo...@googlegroups.com
Currently, I am working with the asynchronous-server.py example. After I initialize the Datastore and call StartSerialServer, how can I modify the Datastore, or access values in it. My goal is to have a Modbus client write to the pymodbus Server, and have the pymodbus Server periodically write out its datastore values to a text file. I can call store.getValues(), and write that info to a txt file, I just dont know how to do it once StartSerialServer is called. 

Galen Collins

unread,
Jan 22, 2013, 11:03:47 AM1/22/13
to pymo...@googlegroups.com
What you can do is start a twisted timer with LoopingCall (or a background thread) and pass it the datastore context to read from.  When the thread runs, simply write the datastore out to disk in any format that makes sense to you.  You may have to copy the code from StartSerialServer and make your own starting point where you wire things up as when you call StartSerialServe, it blocks indefinitely on the twisted event loop run call.  Does this make sense or get you closer?  If needed I can write up a little example that may help you on your way.

igorj...@gmail.com

unread,
Mar 14, 2013, 5:05:09 PM3/14/13
to pymo...@googlegroups.com, joe.wi...@gmail.com
I'm having the same problem changing values in datastore while the server is running. I would love if someone would show a simple sample on how to do it. 

caerb...@gmail.com

unread,
Mar 14, 2013, 9:38:04 PM3/14/13
to pymo...@googlegroups.com, joe.wi...@gmail.com
Firstly, I have no real idea, I am muddling my way through this but  this is how I have done it for my work which has numbers updated every second. 

I added a LoopingCall that ran every second as follows

from twisted.internet.task import LoopingCall

lc = LoopingCall(get_MCA_Data)

lc.start(1.0)

The get_MCA_Data function collects data from an external device and puts it into the Datastore as follows  (I am only using Holding Registers hence the first argument 3)

store.setValues(3,0,list(fields))

where fields contains the data I want to put into the store.

Now my question.

I am pretty sure that I have generated the fields in the ugliest way possible.

Single WORD ints were easy but I needed LONG ints so I used the BinaryPayloadBuilder and specifically the add_32bit_uint function, but the output of the build() function wouldn't work in the setValues function so I created payload as follows

payload = builder.__str__()
fields = struct.unpack('16H',payload)
and used list(fields) in setValues()

Surely there is a much nicer way that this to deal with LONG and FLOAT?

I am also not sure exactly how to deal with data sent to the server.

I could just read from the datastore into my variable on the same LoopingCall which would not be as responsive as I may need.

Is there a way of accessing a Callback when data is changed in the datastore?

Galen Collins

unread,
Mar 17, 2013, 5:14:20 PM3/17/13
to pymo...@googlegroups.com, Joe Wilcoxson
Okay the way you are doing this is correct (if you want to periodically update data).  As for what to do when the server writes values, it really depends on what you are trying to do, but I suggest generally subclassing the lowest datastore item that you need for your use case (datastore, slave context, or server context) and have it do a callback in another thread or process (not in the same thread unless you can afford slower server responses or if the work you need to do is quite quick).  Here are two examples of getting a callback from a server update and writing to the context every so often:


As for using the payload builder to write directly to the datastore, I didn't know if there was a use case for that or not and I wasn't sure of the best way to help people initialize datastores.  However, I am working on some kind of unified way of serializing/deserializing and writing to datastores directly, so stay tuned (it will be cleaner than what you are currently doing).

Galen


--
You received this message because you are subscribed to the Google Groups "pymodbus" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pymodbus+u...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Reply all
Reply to author
Forward
0 new messages