Friday, 14 May 2021

With Great Power ...

I've worked on UNIX based systems since 1989, and I've always had a healthy respect for accessing the system as super user. 

I've seen many times where mistakes made as superuser can have devastating consequences. 

So when we added LEDs to the robot, I was a little concerned to find that the neopixel library required root access in order to run. 

This also means that the root user environment had to be configured for all the packages the robot required. (i.e. using sudo pip3 to install all the packages I need). 

In addition, we also need to configure the audio input device as root for the voice control task - otherwise the robot wouldn't be able to access it. 

I decided I really didn't want this, so thought it would be best to have a simple service running as root that controlled the LEDs and the robot, running as a non root user, could send the service messages to change the colour etc. I'm sure there are many other implementations out there I could have used, but I decided what I wanted was so simple I could write my own. 

For communications I chose to use a UDP socket. This means the service can just listen on a port, and clients can fire messages at the port without worrying about creating or maintaining a connection. 

Both the server and client code would be written in Python so, to encode messages to send between the two, I decided to use the standard python 'pickle' module to encode python objects to and from byte arrays. 

Here is the server code:

NeoPixel server code
source at bitbucket.org

This is installed as a systemd service, and enabled to run at startup. 

The corresponding client code is:

NeoPixel client code
source at bitbucket.org

This shows the barebones client/server implementation. As highlighted by the 'TODO' comments there are enhancements I need to make. The port number, and LED configuration should not be hard-coded in the server. I suspect I will create a config file for the server so that LED array configurations can be added and the client code uses a unique ID to select the appropriate one. Also - I'll make it more of a message protocol - with a message type to indicate whether we're setting a single LED - or all LEDs (rather than the current strategy of setting the led to -1. This will allow the protocol to be expanded easily. 

But for now I just wanted to show a few lines of code could create a simple client/server architecture to get around the problem of running the whole robot code as superuser - just to control a few LEDs. 

I've already modified the robot code to use this, and there is no noticable difference between accessing the neopixel code directly - or remotely through the server.  



No comments:

Post a Comment