Inky Dash is an interface for Inky pHAT, an e-paper display for the Raspberry Pi, that can be accessed from a browser via a local web server. I wanted a fast and easy way to upload images to the e-paper display that met the following goals:
- Web interface for uploading images accessible over the local network
- Should run when the Pi is booted up
- Built cleanly - no hacking together code - so it can be extended in the future
- Provide a chance to build on Node Express/React experience
- Node.js + Express handles REST API and serves the interface.
- React + Redux used in construction of the interface.
The project is structured as a monorepo with the server and UI code bundled together. By treating the application as a whole it meant fewer steps were needed to deploy and run it.Validation
For server side validation Inky Dash uses the schema validation built into express-validator, "[s]chemas are a special, object-based way of defining validations or sanitizations on requests" 1. In the example below the requests value for the image property must be base64 encoded and the value of the palette_colour property has to be either 'red' or 'yellow'.
Checks against the schema can then be made in the middleware, like in the below example for the upload endpoint:
After checking the request against the schema the following function "validationErrorHandler" formats any validation errors, returning an error to the client with a 400 status code if an error occurred, else a call to "next()" is made and we move onto the next step in the middleware.State management
As previously mentioned Redux has been used in this project for state management. Being my first time using Redux there was a little bit of learning curve to begin with but once I had a structure things became more intuitive. As the time of writing I'm using Redux to maintain the state of the display and any errors, both have related actions, reducers, enums and interfaces which as a collective I'm calling a service.
As an example lets follow how the state for the display preview is managed:
- Starting with the upload form control, when an image is selected on the client a call is made to the setPreview function, passing the base64 encoded image.
- The setPreview function is part of the display service it dispatches a SET_PREVIEW action with the base64 encoded preview as the payload.
- The displays reducer then handles the action and sets the state for the preview.
- Using the Redux useSelector hook the display settings page is kept updated with the display state and can refresh the preview image when it changes.
- Finally to ensure the preview is cleared every time the form component is destroyed the useEffect hook is used to set the preview to null.
Other points of interest is a middleware async error handler that catches any errors thrown by async processes such as image manipulation or external calls to Python scripts. And a function that handles the execution a given Python script.
Inky Dash in action
- Schema Validation: https://express-validator.github.io/docs/schema-validation.html
- display-schema.js: https://github.com/End-S/inky_dash/blob/497937240224dab274f64897059f7e4159117e2b/src/validation/display-schema.js
- display.js: https://github.com/End-S/inky_dash/blob/4e1f47f2783bb6bb18bfcb6d1dba6736b2e9a110/src/routes/display.js
- display-settings-form.tsx line 73: https://github.com/End-S/inky_dash/blob/497937240224dab274f64897059f7e4159117e2b/src/ui/src/pages/display-settings/components/display-settings-form.tsx#L73
- display.actions.ts line 42: https://github.com/End-S/inky_dash/blob/497937240224dab274f64897059f7e4159117e2b/src/ui/src/services/display/display.actions.ts#L42
- display.reducers.ts line 48: https://github.com/End-S/inky_dash/blob/497937240224dab274f64897059f7e4159117e2b/src/ui/src/services/display/display.reducers.ts#L48
- display-settings.tsx line 15: https://github.com/End-S/inky_dash/blob/844b3ae0ba93d574d46392407488add6a4c15215/src/ui/src/pages/display-settings/display-settings.tsx#L15
- display-settings-form.tsx line 33: https://github.com/End-S/inky_dash/blob/497937240224dab274f64897059f7e4159117e2b/src/ui/src/pages/display-settings/components/display-settings-form.tsx#L33