|
Page 1 of 1
|
[ 10 posts ] |
|
| Author |
Message |
|
berkinet
Joined: Nov 18, 2008 Posts: 1743 Location: Berkeley, CA
|
 Python help needed
I have a class ( ifkit) that handles all communications with a piece of external hardware. The method that starts and manages the communications is startPhidgetThread. While most of the work involves reading the data flow from the hardware and maintaining states of Indigo custom devices, there are times when I need to write to the external hardware. So far, I have the process working for reading the data. The communication management class is called from plugin.py as: - Code: Select all
def runConcurrentThread(self): threadIfkit = threading.Thread(target=self.ifkit.startPhidgetThread, name='ifKit') threadIfkit.start()
Now, I want to create a plugin action to "write" to the hardware. There is a function defined in ifkit.startPhidgetThread called setOutput that does what I need. I can create the action and define a callback method in plugin.py called ikfitWrite. But, the problem I am having is getting the callback method to call setOutput and pass the two arguments it requires, or find some other means to execute the code contained in setOutput. ifkit looks like: - Code: Select all
class ifkit(object): ######################################## def __init__(self, plugin): self.plugin = plugin self.shutdown = False
def __del__(self): pass ###################### def startPhidgetThread(self): indigo.server.log('ifKit thread starting', type="Phidgets Plugin") def setOutputI(port, value): interfaceKit.setOutputState(port, value)
def <Additional Communications functions> ...
while not self.shutdown: time.sleep(0.5)
Any ideas, pointers, suggestions, examples, etc. most appreciated. EDIT: FWIW, all communications from the hardware are event driven and managed by lower-level interface code provided by the manufacturer. startPhidgetThread also contains callback methods that are invoked by the lower-level interface as needed. That is why I have the endless wait loop at the bottom, waiting for these callbacks, or, my action invocation..
|
| Thu Jan 26, 2012 1:20 pm |
|
 |
|
jay (support)
Site Admin
Joined: Mar 19, 2008 Posts: 6859 Location: Austin, Texas
|
 Re: Python help needed
I think you'll want to look at the iTunes or EasyDAQ plugins - both use a queue object to pass commands from the plugin to the individual device threads. Then in the device thread's main loop you check for any commands that need to be sent to the hardware and send them.
_________________ Jay (Indigo Support)
|
| Thu Jan 26, 2012 2:16 pm |
|
 |
|
mat
Joined: Nov 25, 2010 Posts: 172 Location: UK
|
 Re: Python help needed
The serial test plugin uses a queue method too. Very easy to mod.
|
| Thu Jan 26, 2012 3:06 pm |
|
 |
|
berkinet
Joined: Nov 18, 2008 Posts: 1743 Location: Berkeley, CA
|
 Re: Python help needed
Thanks Jay and Mat. I had looked at the EasyDAQ plugin, but was hoping there was a way to build on what I already have. The current architecture is built on top of a large body of code provided by the Phidgets manufacturer and it is pretty easy to use as it now exists.
I wouldn't think it should be that hard to either call a method defined in a thread, or send a message to a thread to do something. But, if I can't figure out how to do that, I guess I'll take a look at at queues again.
|
| Thu Jan 26, 2012 3:11 pm |
|
 |
|
jay (support)
Site Admin
Joined: Mar 19, 2008 Posts: 6859 Location: Austin, Texas
|
 Re: Python help needed
Threads require some kind of IPC if you want one thread to talk to another. Queues are the easiest way and they're built-in to Python.
_________________ Jay (Indigo Support)
|
| Thu Jan 26, 2012 3:41 pm |
|
 |
|
mat
Joined: Nov 25, 2010 Posts: 172 Location: UK
|
 Re: Python help needed
I'm no python expert. Only took my first look last week.
I've moded the serial plugin to remove the queue as my serial device is "input only", and it receives commands faster than a Nintendo player with 16 fingers can push buttons on my iPad.
If you use a queue method, watch CPU usage. I removed all the pauses in the serial test plugin code to send data without pausing between queue reads and 1 processor core sat at 98% for three days before I realised. Beginners mistake I guess.
|
| Thu Jan 26, 2012 4:54 pm |
|
 |
|
mat
Joined: Nov 25, 2010 Posts: 172 Location: UK
|
 Re: Python help needed
This is what works for me. I don't claim to understand it but just followed the logic. As a really early beginner it works for me, but i'm sure it can be improved, even if I have pasted everything  . - Code: Select all
def sendSerialCommand(self, devId, command): dev = indigo.devices[devId] devProps = dev.pluginProps portName = devProps.get("serialPort") portBaudRate = devProps.get("portBaudRate") portParity = devProps.get("portParity") portDataBits = int(devProps.get("portDataBits")) portStopBits = int(devProps.get("portStopBits")) writeCommand = command conn = self.plugin.openSerial(dev.name, portName, baudrate=portBaudRate, parity=portParity, bytesize=portDataBits, stopbits=portStopBits, timeout=1, writeTimeout=1) sentCount = conn.write(writeCommand)
|
| Thu Jan 26, 2012 5:13 pm |
|
 |
|
berkinet
Joined: Nov 18, 2008 Posts: 1743 Location: Berkeley, CA
|
 Re: Python help needed
Thanks Mat. It is actually the queueing code that might interest me, and I took a look at an earlier version of your plugin to see what you did - similar to what Jay noted, but a little simpler because of the nature of your plugin. It helped a lot, thanks. In my case, the communications is all via IP and is all handled by code that was provided, so all I have to do is call their code in a separate thread and wait for events to call functions in that thread. Very simple. The problem I has was the occasional need to go the other way. I did find out how to send an event to a thread, but that was fairly limited. Though, it might work for you in place of managing a queue. The idea is you send a message to the thread saying an event has taken place. You cannot pass any data. So, the thread would then have to figure out what to do... probably read from some global variable or object. Klugy, and not well suited for multiple threads, but interesting none-the-less. Here is the URL where I could the information. Quite clearly presented. For my case, it looks like a queue is the way to go, though I am still hoping for some way to directly call the function inside the thread.
|
| Thu Jan 26, 2012 5:25 pm |
|
 |
|
mat
Joined: Nov 25, 2010 Posts: 172 Location: UK
|
 Re: Python help needed
No problem, but for the record, I didn't write the serial plugin, I just hacked it to bits to suit my needs. I can't take credit for the original!
Hope you sort it out.
|
| Thu Jan 26, 2012 5:30 pm |
|
 |
|
berkinet
Joined: Nov 18, 2008 Posts: 1743 Location: Berkeley, CA
|
 Re: Python help needed
I figured it out  and it was actually pretty straight forward once I had the right model (which turned out to be a resettable timer). The class is declared as: class foo(threading.Thread): and must have: def __init__(... ...): threading.Thread.__init__(self) Then I can declare all the methods I need, like plus the start method which starts things going, and stays open with a timer loop listening for events from the comms channel Now, in the main plugin code I can start this thread by self.myClass = foo(self, ... ...) self.myClass.start() and, anytime I need to send something to that thread I can just: self.myClass.sendToComms(... ...) No queues, no message passing. Now, In fact, since there will be multiple threads, I save the handles in a dictionary so I can grab the right one and talk to the correct thread. Like: self.threadDict = {} self.threadDict[dev.id] = foo(self, ... ...) self.threadDict[dev.id] .start() and then... self.threadDict[dev.id].sendToComms(... ...)
|
| Thu Feb 02, 2012 7:31 pm |
|
|
|
Page 1 of 1
|
[ 10 posts ] |
|
Who is online |
Users browsing this forum: No registered users and 1 guest |
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot post attachments in this forum
|
|