Close

First day of refactoring&testing

A project log for pyLCI - Linux Control Interface

Makes Raspberry Pi accessible, portable and easily configurable.

aryaArya 03/22/2016 at 08:150 Comments

This is a project I've been working on for some time, but with long interruption periods. However, this project is great and it's worth working on, and Hackaday Prize provides me with inspiration, motivation and a deadline - and I don't even know which of them is the most important factor, they all are.

With that in mind, my intentions are to release the system in the wild for testing by any interested users so that I can receive valuable feedback and see what's there to improve, as well to spread the word about it so that more people think about such an interface and therefore see which problems it can solve for them. Given the contest time constraints, it seems to me that the best idea is to release minimal runnable version which supports some basic and most necessary functions, as well as all the hardware that I currently have written drivers for. I'll designate that version to be 1.0 - in a nutshell, that'll already be useful and sufficient for many users. From that point, even if I become unable/unwilling to work on the project (highly unlikely, but still), the idea and basic working code will be available for users and developers among them, so that the project will be able to go on if there are enough concerned people.

Here you can read more condensed info about V1.0 if you're interested.

After a break, read my thoughts about the current system state and what I've done this week, up to this day.



There's next version of the system I've been working on for a long time, or rather what's planned to be the next version of the system. It has got many important points right, but is also wrong in some crucial aspects and would need much more time than is available until my release date. (That time also includes writing some promotional materials!) Telling about the next version would need much more time than I have, so let's just skip this until later.

With all this in mind, today I've sat down and re-designed the most basic parts of the system.

First of all, the system consists of:

  1. output and input devices
  2. applications, which provide functions the end user wants to perform using the system
  3. core, which ties the applications and IO together

1. IO - hardware and drivers.

Till this day, I've worked on using 1$-a-piece I2C IO expander boards for interfacing with buttons, which is not the designed function because these boards are designed for HD44780-based LCD displays. However, the idea worked great and I've written an Instructable on it which I need to revise a bit before I am sure it's good enough to be published. I've also refactored the code which was driving such a backpack which was used, as intended, with an LCD, so now it's cleaner and also works better in some aspects.

Also, I've added GPIO-driven buttons, working with RPi.GPIO library - it's important because it drives the hardware requirements down along with minimal price, and I will add a GPIO-driven LCD code this week for same reasons. Can't get any cheaper and more basic than 4$ and wires, I think. Hey, it's a perfect project for Pi Zero! ;-) I yet need to test the system with PiFaceCAD - it's been quite some time since that combo was used. However, it should work great once I include a couple of fixes for problems I found out about this week.

One great thing - writing drivers for input&output is hella easy. However, there are things to be done as right now there's an evdev layer between input devices and pyLCS input interfaces, which in most cases is not necessary. Once I remove it, I think it'll remove a significant obstacle for running pyLCS on OpenWRT, removing python-evdev requirement, as well as simplify the code and make it much more fast and less bloated.

That feeling when you confuse variables and then stare blankly at things which seem to have no reason not to work

2. Applications

This is the hardest part, I think. There's a lot of compatibilities to keep in mind and a lot of things to be known about different Linux environments to make applications which work reliably for most of people, if not for everybody. I can't really reach "everybody happy" goal with applications more complicated than a couple of external command calls, so I need to make my applications understandable and system to add them in a way as simple as possible. I'll be describing applications one-by-one as I make them, as well the decisions that drive me.

The simplest approach which fits my requirements is simply unpacking applications in designated separate folders, then having the system scan those and import them all automagically so that application installation is at most a simple "tar xvzf file&&./update.sh", the last script just syncing the working directory with the system's distribution of the pyLCS... More about pyLCS&distribution relationship later.

No packaging of files is planned in this system, but none seems necessary as well. I've used that approach in two big projects of mine, and I know what works and what doesn't, so I figure the "unpacking-tarballed-apps" approach is more than enough for what's required and really, really simple.

Of course, that means dynamic location of applications in different folders. Those folders, however, are all to be located in a single folder - which might seem to be problematic with a big count of applications, but I don't think there are going to be THAT many so as to for it to become a problem.

Testing the applications is a great thing, and we need to make it easy. My first step towards it is going to be a command-line argument for the main.py script (the part which launches the system), so that you could specify an application name and it'd load that and that application only, skipping other applications, menus and all that fuss, which takes precious debugging time. I'm not yet thinking of any more testing helpers, but of course I'm going to automate my problem-solving, and it's going to be open-source.

As a proof-of-concept, today I've designed a simple system shutdown&reboot application and hard-coded it in the system as the one and only application to be detected (there's one more menu entry in the code because there's a bug fix yet to be backported from the next version of system I've been working on.) It works great and I fixed some more bugs in other parts of the system due to the testing. With this application done, I'm going to design the auto-detection part, remove the hard-coded parts and move on to writing more applications for the release.

Hey, I've made some exception handlers! This one is good for SyntaxError!

3. System core

First of all, I'm making the core parts (such as main.py) output diagnostic messages to the screen used as pyLCS output so that even without launching the script it can be seen which part of it failed and whether applications or something else are to blame. Also, I'm making things more exception-proof so that one application crashing doesn't crash the entire system but merely gets that application unloaded (I've done it for the next version already, but for this one I yet have to try.) Of course, that means making a boot log of applications that fail to load and showing it on the screen while booting pyLCS, as well as making time limits for the applications to limit freezes (now for this one I have no idea, it just seem to be the best solution imaginable), or, alternatively, make guidelines for applications and make it so at least it's visible which one of applications is blocking the pyLCS boot process. Anyway, I've got plenty of ideas to be taken from the second LCS version, with the exception that the second version is much more asynchronous when it comes to working with applications.

Second thing is that core has to be small and fast. Excluding evdev from the input device management is certainly a thing that has to be done. Once again, I'm not sure it fits in the release - and it works great, apart from the bloatedness. Of course, I removed plenty of junk code and what once was "applications" for the previous system revisions. They're probably going to be refined to suit new system, provide some basic set of tools which works without any problems and do it well.

I'll also change input interface button mappings a little bit for devices that I own and therefore am developing with. Maybe I even could make it a separate file, you know, that'd be nice - but it'll need to be capable of being autogenerated and be scalable for future versions. Button mappings have to be separate for each driver, as drivers correspond to some physical devices out there which have their buttons mapped so that they're more or less comfortable to use, but there also have to be options to specify alternative button mappings in parameters, as you can have multiple devices using same driver that you'd want to assign different keys to. IMO, the best idea would be to use config files and to pass filenames as initialisation arguments for drivers, and that's probably what I'm going to make it. For that though, I need to re-work input subsystem - again! - so that is supports multiple devices. It's possible to specify many in the config file, as I knew this would be necessary, but it's not yet supported.

AFAIK input system was the first one to be written. Now I know why it's such a mess. Also, output system is much more simple in terms of what it needs to do so there are less possibilities to mess it up. The problem with input system is that I wrote it having only USB HID devices available, thus the overhead and evdev layers. Thankfully, I worked around it so that once the thing's fixed, there's even no need to change config files once it's updated. Also, seems like menus suffer from that too - there are quite some buttons that might need to be re-mapped for different users.

I've made an installer script which makes an /opt/lcs folder, puts all the files there and installs a systemd unit for the system. Currently, it assumes Raspbian Jessie and therefore systemctl and all new shiny tools coming with it, however, you can easily modify setup.sh to detect whether it's run on a systemd system or not and make it use different autorun files, I guess you can even convert systemd units to init.d scripts - can't you?

Oh, updates. I've also made a basic updater script - it pulls any new commits from GitHub, then moves contents of those and also all local changes to the /opt/lcs directory where, again, the copy of software which's used to be run automatically is located. I will need to improve on it but right now it does what it has to do.

:devil:

What's next?

GPIO-connected LCDs, app subsystem and some basic apps, as well as a nice configuration script. Oh, and promotion. I think I need plenty of that to have chances of going through Hackaday Prize. If I have time before the release, I'll also re-make the input subsystem - it all depends whether I'll have enough time and whether I'll manage to develop a clear idea of how exactly to structure it.

I also want to use a VGA I2C breakout and a USB numpad to show that the system can be used with all kinds of computers, not just RPi but even desktops and laptops. See, even though there's hardly anything limiting it, that might not be as obvious.

So far, so good. I even have a couple of schedule days reserved for emergencies, illnesses and alike. Now making videos... I need at least a couple of those, and I have no experience. Guess that could take longer than I think.

Hey, this is my new shutdown&reboot app and it works great! Shutdown&reboot is about everything it does though.

Discussions