[Twisted-Python] Advice on porting Python application to Twisted

Matthew Humphrey mhumphrey at gmail.com
Tue Aug 27 22:51:03 MDT 2013

(Reply to Matt Haggard)

Matt - I was getting the emails delivered in digest form, so I am having to
reply to my original email instead of to your reply. I have added your
email directly to make sure you get it.

> I am not familiar with how you communicate with hardware on a
> Raspberry PI.  Can you link to your existing code?  In my brief
> reading this morning, I'm guessing you might be using the RPi.GPIO
> library?  If so, I'm looking at
> https://code.google.com/p/raspberry-gpio-python/wiki/Inputs which
> indicates that wait_for_edge() or event_detected() might be useful
> (instead of a "continuously called a 'timeTick' event").  But I'm not
> sure what thread the callbacks to those functions are called in.

> I've also come across
> https://www.kernel.org/doc/Documentation/gpio.txt which makes me think
> it would be possible to register the GPIO events with the Twisted
> reactor (but I've never done that and don't have a Pi to test with).

I wrote a small Python wrapper over the user-space GPIO driver. This uses
some special files under /sys/class/gpio. It is possible to configure a
GPIO input to be interrupt driven, and then using select() or poll() get an
asynchronous event when the configured condition occurs. I tested this out
manually from the Python console, however, my little wrapper class doesn't
support it currently. The other issue is that the simplest way to do button
debounce is to just poll the button once it's pressed and make sure it
stays pressed before some time before treating it as a "button pressed"
event. In my case, I also monitor the button to see if it is held down for
two seconds, as I treat that as an indicator to trigger the machine to
dispense the cat food. I suspect all that behavior could be duplicated in a
Twisted-friendly way, but I am not sure how to do that.

> Perhaps it's time to buy one.

They are a lot of fun for $35-$40.

>> 3) A thread that runs continuously capturing images from a webcam. This
>> ...(snip)

> Someone with more intelligence than me should answer this, but here's
> my attempt:

> You can do this without threads since you're just spawning processes
> for the image captures.  I'm assuming you only want to capture as many
> low res images as you can process. Here's one way to do it:

> from twisted.internet import reactor, task, defer
> (snip)

Thanks, I see the docs on spawning processes now that your example pointed
out their existance. I think I can also emulate the behavior of my polling
loop by using the scheduled callback feature. I will play around with it a
bit and check back if I can't figure it out.

Thanks much for your reply.

On Mon, Aug 26, 2013 at 8:06 PM, Matthew Humphrey <mhumphrey at gmail.com>wrote:

> I recently created a small automated, remote (via web) controlled pet
> feeder using a Raspberry Pi single-board computer. The software is all in
> Python, and uses the simple HTTP server that is part of the Python
> libraries. I discovered Twisted about 2/3 of the way through the project,
> and now that I am done I would like to port it to use Twisted. After
> reading much of the documentation the Twisted web site, some aspects of
> this are fairly obvious to me, while others are not. I could use some
> advice on how best to design my app to fit in with the Twisted framework.
> Here are the major components of the application:
> 1) A web site that hosts a combination of static content and some REST
> APIs. REST apis are called from Javascript Ajax, and do things like
> enable/disable the webcam, dispense a treat, etc. The static content
> consists of a single HTML page, some javascript scripts, and a JPG that is
> captured by #3 below.
> 2) A thread that runs a loop which manages the hardware. It does this with
> a simple state machine composed of a base class and subclasses for all the
> states that the hardware can be in (starting, idle, displaying status on
> the lcd, dispensing a treat, recovering from treat dispense cycle, shutting
> down). After initializing the hardware and the initial state, the thread
> loops continuously calling a "timeTick" event to the current state. WIthin
> the states, the code looks at various hardware status (like whether a
> button is pressed) and decides to take action or to trigger transition to
> another state.
> 3) A thread that runs continuously capturing images from a webcam. This
> thread captures low resolution images continuously, and compares sucessive
> frames to see if there is significant number of different pixels (motion
> detect). If so, it captures a higher resolution image, updates a symbolic
> link to point to the most recent image captured, and deletes any excessive
> files from previous captures. The images captured for the motion detect are
> handled by executing a process and capturing the stdout. The higher res
> images captured by executing a process that writes directly to a file.
> Porting #1 is very straightforward after going through the tutorial on
> Twisted web. However, I am not sure how to handle #2 and #3. I would
> appreciate some suggestions from those who are familiar with Twisted.
> Thanks
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://twistedmatrix.com/pipermail/twisted-python/attachments/20130827/8b942c88/attachment.html>

More information about the Twisted-Python mailing list