The controller software lives here on github. My current software development environment is Visual Studio Code with Platform IO installed on top of it. It’s quite a bit better than the Arduino IDE for my usage patterns.
I’ve done my best to build a flexible and well-abstracted design. With the exception of main.cpp, all of the C++ classes are written in the include (.h) files so that I don’t have to deal with multiple files per class.
Here are the classes and a brief description of what they do:
- Action – takes in a textual description of an action (on, off, toggle, plus some dim levels) and converts it to a numeric value. This is a nicer pattern to use than an enum as the parsing code can live here.
- Device – an abstraction for a device that I want to be able to control. It has a text name, a group name, an output pin, and a timeout (in 10 mS units). If you pass it a name and an action, if will implement that action if the name matches either the text name or the group name of the device.
- HardWiredController – the physical controller (not yet built) has a group of switches connected via resistors to the input line, giving a varying voltage based on which switch is pressed. This code uses the ADC in the ESP to get the current value, figures out what button was pushed, and performs the appropriate command.
- Main.cpp – the main setup and loop code. Mostly just delegates out to other classes.
- MainPage.h – the text of the web interface page for the controller
- Manager.h – the manager for all the devices. It creates an array of devices and then handles dispatching commands to them, getting status strings, handling timeouts, etc.
- OnIfAnyDevice.h – the 12V power supply needs to be turned on if any of the lights are on. This class looks at the state of the devices passed in through the constructor and turns itself on if any of them are on.
- StairSensing.h – The program needs to turn on the house lights if the stair lights are turned on. This code tracks whether the stair lights have been turned on and switches the house lights on and off as necessary.
- WebServer.h – The code that handles requests for the UI page and url action commands.
The main loop runs with a 10mS delay so that every time through the loop is roughly that long; that is needed to implement the timeouts in the device class. I could have done this in a more sophisticated manner but what I did is clear and good enough for the requirement.
The Manager and Device classes warrant a bit more discussion. They are use a software pattern called “Chain of Responsibility”; there are basically 5 devices that all look alike, and the manager just passes the action through to all of them and the device that the action belongs to deals with it.
This vastly simplifies the manager class – otherwise it would have to check every string and figure out which device to pass it to – and makes it really easy to implement group devices; the “lights” group refers to all light devices. It also makes it easier to implement the OnIfAnyDevice class, which otherwise would have required special case code.