Issue #017 [Done/closed] - Enhancement proposal for server module example and usage

Posted by andreas.riegg

Happy new year and thanx for the ongoing work with webiopi.

I have done some implementation work with custom python server modules now and implemented a way that helps to make this task easier for me. Maybe we can share this with other users of webiopi server modules.

I implemented a server module called webiopi_mysrv.py that has all necessary things inside it to be run as server module in interactive mode (development time) as well in deamon mode (just runtime). I place this module in a known path (e.g. /home/pi/webiopi_mysrv/ and register it once with a custom webiopi_mysrv.py.init (see attachments) that gets installed as webiopi_mysrv in /etc/init.d/ the usual way. This way that module can be started and stopped as deamon or even automatically at startup without having to do the installation stuff too often. I also can run it in interactive mode and stop in with CTRL-C during development and bugfixing. I can have multiple different versions of webiopi_mysrv.py and just by renaming them I can test different alternatives even in deamon mode without having to do the installation stuff again and again.

I also discovered that when my module is terminated in deamon mode, the cleaning up code at the end is not executed. For that reason I added some code that catches the SIGTERM when the module is terminated in deamon mode so that my cleanup code is also executed in this case. I have attached a version of webiopi_mysrv.py that is implemented according to demo.py but contains all the stuff that makes server initialization and finalization more streamlined and does cleanup the same way in interactive and deamon mode to be consistent. It also contains mode comments for others to understand how to use it and adds an example macro without parameters for completeness of pythton server module usage possibilities.

Maybe this is a good improvement for the python server module example and its usage documentation.

Best regards.

Files attached


Comment 1

Posted by trouch


Comment 2

Posted by trouch

Just made few changes on the SVN, please take a look on r680 I've added signal handling directly in WebIOPi core to break the loop, any code after runloop should now be executed when SIGTERM is received. I also updated the demo. For the init script, I will add it on the wiki as we only have to copy the default init script and change $DAEMON_ARGS


Comment 3

Posted by andreas.riegg

Thanx, I have seen the changes to webiopi.py and the update of demo.py. I assume that SIGINT is automatically thrown when CTRL-C is pressed so this way we have now a very uniform termination handling embedded into webiopi core. And with the updated comments in demo.py it will be much easier to develop own server scripts as demo.py is mostly self-documenting now.

Concerning the other ideas behind webiopi_mysrv my intent was not to integrate that all into the webiopi.py core and its installation setup. My intent was more like that I assume when someone uses the Raspi and Webiopi over time more intesively as a e.g. home automation server, sooner or later will have the need to have some functionality implemented as an additional server script that will also provide some remote usable macros as you provide and maybe some initializations or cleanup actions. It's absolutely clear that this additional functionality should never never be inside webiopi.py as this implements the what I would call basic WEB API functionalities and thats fully ok so.

So my idea behind the other things with webiopi_mysrv is more like having a kind of luxury "example/demo" for all those that have to implement a server script on their own. With "luxury" I mean the good practice of símple ready-made reusability for others. So it comes with a predefined name being a little bit more distinct that just "demo" but indicating its clear relationship and purpose (so I choose webiopi_mysrv). It also comes with a complete init-script so that its installation as a server script is equally easy as the installtion of the webiopi core is already today. It is placed on a (choosable?)standard path (so I choose ../webiopi_mysrv to have it clearly separated from the webiopi core, but any other path can of course be possible) which in turn allows the init-script to remain simple. It could also comes with a very simple default implementation doing nothing more than just the server instantiation with default values, the loop definition with an empty loop and e.g. the 1 second delay and the server.stop() from demo.py and has comments inside where to place the specific things (which you already did in the r680-version demo.py right now).

The full automatic setup of webiopi would then comprise the following things: Already in place:

Having this setup, a developer will have the following options on server side: -A Use only the webiopi core from shell level ($ python -m webiopi ...) -B Use only the webiopi core in deamon mode ($ webiopi start/stop) -C Use only the webiopi core in atomatic startup mode ($ update-rc.d webiopi defaults) -D Use the webiopi_mysrv "empty" from shell level ($ python webiopi_mysrv.py ...) -E Use the webiopi_mysrv "empty" in deamon mode ($ webiopi_mysrv start/stop) -F Use the webiopi_mysrv "empty" in atomatic startup mode ($ update-rc.d webiopi_mysrv defaults)

I even could setup a complete SD-Card with Raspbian, DHCP + SSH enabled and Webiopi like above once, duplicate it, put it into a new Raspi, change the hostname, throw any changed webiopi_mysrv.py onto it via SSH or some FTP and let it run the new webiopi server with added functionalities.

That are my thoughts behind webiopi_mysrv (or whatever name ist is given), but you already added some things which is also ok for me.

Best regards


Comment 4

Posted by trouch

Thanks for your feedback. Yes, SIGINT handles CTRL-C.

If I well understand, you actually want to give more options by default to the user. I will reorganize a little the example, and add a simpler one. I will also add some init example as you suggest.

The thing tricky with this project, is that I have to manage users and developers from totally noob which use WebIOPi with the PiStore, to advanced developers which use the WebIOPi server library. I have also in mind issue #4 https://code.google.com/p/webiopi/issues/detail?id=4

There is one thing I still don't understand, what do you mean by "setup" in "without having to do any setup again" ? Is it setup.sh script or the custom following setup ?


Comment 5

Posted by andreas.riegg

It's just the comfort of setting up the webiopi_mysrv.py thing in a standard way completely only once direct after webiopi core setup. Afterwards I can just modify the webiopi_mysrv.py module or rename different versions of it like webiopi_mysrv_1.py and webiopi_mysrv_2.py and have all the stuff concerning init.d handling ready to use in place. This is very useful in intensive testing scenarios.

To understand this type of comfort a little better I can explain my "development environment" a little more. As I mentioned before in another post, I use mainly the webiopi REST-API via HTTP calls from Android native Apps that I write myself using Eclipse (on Windows). The Raspi is great hardware for low cost/low energy consumption runtime, but only limited for intensive interactive software development. For that reason I also have Python on my Windows machine just beside the Eclipse Java stuff for Android. In order to be able to run webiopi for development and testing purposes on the same Windows machine I have written a "fake" GPIO.py module sitting in a /_webiopi subdirectory including an empty __init__.py module. This allows to have the import statement in webiopi.py or even demo.py unchanged and so I can run webiopi or any server script of my own without using a Raspi obn my Windows machine. The fake GPIO.py implements all (most?) calls from the original one and even remembers the state of setting outputs or pwm to something. If something is set e.g. like GPIO.output(5, GPIO.HIGH) it stores the value in state variables/lists and prints a log message on the console to see the call taking place.

So when I test an Andriod app using webiopi, I do it this way:

Advantages are:

So that's the kind of development comfort that I personally like and that I want to share. On the other hand, you are right, this kind of development setup is nothing for noobs and may be too complicated for simple usage requirements like switching LEDs on and off.

Anyway, the REST API you already provide is a very good base providing a simple and performant way to control Linux server GPIOs from an Android smartphone via TCP/IP. If some day in the future also I2C and SPI get integrated, something like a dream for real open source home automation will become true: Using and controlling I2C and SPI based electronics via Smartphones (either as native apps or via Browser and Javascript) and TCP/IP in an affordable and efficient runtime environment that is very rich and dynamic (Python). And, with the server script and its macro functionality, it's also possible to implement functionality on server side when it makes sense. But this would be another long discussion ...

Concerning issue #4 that you mentioned it may make sense to also add a shutdown script hook in addition to the startup script mentioned there.

Best reagards


Comment 6

Posted by trouch

Okay, what a complex setup you have ! On my side:

I only run setup.sh when :

When I change and debug webiopi.py, I simply execute "sudo python webiopi.py" in the python folder. It warns about an existing webiopi, but it works.

Please take a look on r686, I've moved demo to examples/custom, and added a basic example too. There is also daemon script examples we can directly use in each basic and custom folder by typing "sudo ./webiopi_custom.daemon start" for instance. Or we can copy it in /etc/init.d then change the HOME var to point the the correct folder. I also display again webiopi usage at the end of install and removed default boot startup to avoid previous install corruption.


Comment 7

Posted by trouch

0.5.3 released with suggested changes, wiki updated