Just a quick update: I have the project mostly working, but of course I'm sure I will still make little tweaks with it. Most of the work is done on the Linux side using Python, and I have three major modules:
- Database module: a wrapper around a sqlite database that implements my business logic. It defines a class that does all of the actual operations on the database, and has methods that do all of the various high level operations including importing/exporting data, and performing queries and updates. All of the database details and SQL are in this module, the rest of the system doesn't really have to know how the work is being accomplished.
- Local Interface module: this is the process that is called from the sketch when barcodes are scanned. This module takes the scanned code, figures out what to do with it, calls the Database module to actually do the work, then takes the results from the database module, formats the LCD screen output, and sends it back to the sketch for display.
- Remote Interface module: this is a Bottle framework application to allow remote control of the system. It implements a set of web pages to perform certain operations such as configuring the system, viewing data, and importing/exporting data. It also implements a RESTful API to allow remote access from the C# program, letting it get at certain data and remotely perform some of the same actions that are done by a local scan operation.
This is all tied together by a relatively simple sketch running on the Yun's '32U4 processor that takes data from the scanner, passes it to the Local Interface module, receives data from that module, and displays it. It doesn't perform any of the business logic, it's pretty much just a smart I/O controller. It does kick off the system by using Process objects to start the bottle application, and to make calls to the Local Interface module.
A few details are different than I had originally planned. First, by using the Bottle framework to create a web application, a lot of the things I was going to do with the C# app can now be done with simple web pages, greatly simplifying the C# app's duties.
Another significant change is my plan to use a Process object to call the Local Interface module, passing the scanned code as a parameter: that worked, but was too slow, taking a couple seconds to spawn the process and get the data back. Instead, I start the Process in setup(), and keep the process open. The Python module loops forever, and uses sys.raw_input() to read from stdin. When a code is scanned, the sketch writes to the Process object, the Python script picks it up, processes it, and uses sys.stdout.write() to send data back, which the sketch reads from the Process object. I could've used simple Python print statements, but sys.stdout.write() has the advantage of not inserting various spaces and newlines in the output. By keeping the Process open all of the time, the response time is shortened down to about 400 milliseconds - quite acceptable, as it takes about that long to move your eyes from the code being scanned to the display.
At this point, Robin is probably wondering why I didn't just bypass the Bridge and use the serial port directly? Well, a few reasons: The first is that it was simple enough to do almost the same thing using the Process object -- I think it's even simpler than going into Linux to disable the login on the tty port, using PySerial to open up the serial port, and configuring Linux to automatically start the required scripts. But the bigger reason is that I actually have two scanners and two displays attached to the Yun: if I bypassed the Bridge, I would have to write some steering logic on both sides of the serial port to figure out which scanner and which display is associated with the data. But by using two Process objects, I can have one for each data stream, and not only they are the data streams automatically kept separate, but each process has its own set of local data to keep state information between scans - no extra work is needed to be able to implement a second scanner/display, just instantiate a second Process object. A final reason is that leaving the Bridge in place allowed me to add the feature described in the next paragraph:
The last change is a new requirement to be able to send some asynchronous events from the Bottle web application to the sketch. I could've come up with some way to send that information to the process running the Local Interface module, and have that send it to the sketch through the Process object, but I took the easy way out: I just implemented a very simple REST API in the sketch, similar to the basic Bridge Library example. When certain buttons are pressed in the web application, it causes a call directly to the sketch. This seemed like the easiest way to go without inventing a new communications method. (With all of the business logic in Linux, and the sketch being basically a dumb I/O processor, there was plenty of memory left to implement the rudimentary API.)
PCWorxLA:
I personally loath Python, for various reasons.
This was my first significant exposure to Python, and while the list/dictionary/string processing abilities made some facets of it simpler (or at least needed less statements) I don't find it very good as a formal development environment. The flexibility in data typing has some appeal at times, but in general I found that it allowed problems that were not detected until run-time, and sometimes not until much later when a strange data situation arose. Many of the issues I tracked down would've been caught at compile time with a more formal and strongly typed language. I can see why developing strong unit testing scripts is such a big thing with the more serious Python developers, as some bugs aren't shown until you've called your function dozens or hundreds of times with every conceivable combination of data. Yes, you still need to do unit testing with a strongly typed language, but many of the bugs (like assuming a value is an integer when it turns out to be a string) would've been caught at compile time.
I'm glad I took some time to do some real work with Python: Python will likely stay in my box of tricks for some future tasks, but it is unlikely to take over as my go-to language for a serious development effort.
Anyway, if you're still reading this, thanks to all for your advice and guidance. The project is a success. I offer this recap of the project in case there is anyone out there looking for some architecture ideas for building a somewhat larger project than the typical small sketch.