Hotpot is a controller for a Y-plan central heating system, using node.js on Raspberry Pi. It piggybacks on the existing system so that the existing controller acts as a backup.
The controller can collate data from a number of sources to support user-defined rules to decide whether the heating needs to come on.
- Any number of thermostats, usually one for heating (CH) and one for hot water (HW)
- A detailed timeline that allows fine control over target temperatures
- Any number of Google calendars
- Any other sources you can think of
Because the system is controlled by rules written in Javascript, it is easy (and fun) to derive and add new rules. Experiments have included rules using data from:
- location reports from household mobile devices
- weather information from the UK Meteorological Office data service
- external temperature & humidity sensors
The controller can be used stand-alone without being connected to the internet, though we have found the real power of Hotpot is in the ability to control the system remotely from a web browser. This means the system need never be heating the house when nobody is home, and it's easy to boost the heating in anticipation of a warm house and a hot shower when you are about to head home.
Unlike commercial alternatives, such as Google Nest, no third-party servers are involved, and only simple low-cost hardware is required. All the parts can be purchased for around £40.
The following assumes a standard Y-plan central heating system. This used to be the most common type of system, though there are more modern alternatives.
It's also assumed that you have some way to access your Pi from the internet. This is simplest if you have a router with a static IP address that can be programmed to forward incoming requests to the Pi. There are so many possible hardware options and configurations that you will have to work this bit out for yourself.
Aside from the Raspberry Pi, the only additional hardware required are two DS18x20 one-wire temperature sensors, and a couple of relays - SRD-05VDC-SL-C relays are ideal for this. See the general wiring diagram for details of the mains level wiring, and the circuit diagram which gives a schematic overview.
The wiring of the temperature sensors and the control side of the relays is shown in the Pi pinout diagram.
If you follow the described wiring the existing thermostats are kept in series with the Hotpot relays. Hotpot is designed such that if the relays are left unpowered, the existing thermostats are still in place. This way the traditional controller remains as a backup. Make sure the traditional thermostats are kept at sensible levels.
The wiring shown capitalises on the fact that when the controller for a Y-plan system is powered on, but set to "off", the "Hot water off" control line is held high (at 250V). This means we can draw the power for the Pi from that line if the existing controller is set to "off".
Alternatively you can power the Pi from a separate power source if you choose to do so. In this case you have the option of keeping the existing controller "live" and using it as a backup in case the Pi fails.
Note that the motorised valve in a Y-plan system is a very clever piece of design that uses the minimum number of components to fulfil its function. This does mean that there is a state the valve can get into which causes the valve to draw power continuously when both hot water and heating are off. While the valve is designed for it, and the power consumption is low (a few watts), Hotpot is designed to eliminate this state.
Once your hardware is set up you can use the test programs in server/test
to check hardware functionality: testGpio.js
will let you query and set GPIO pins, while testDS18x20
will let you query temperature sensors.
Note that there have been isolated cases where Raspbian has "frozen" leaving the OS dead but the GPIO powered up. It can be resolved by power-cycling the Pi, but there is nothing in the logs to indicate a problem. If anyone has a solution to this, please raise an issue or a pull request on github.
The following assumes you are using a Linux distribution on your Pi. At time of writing DietPi is a good choice as it's small.
The Hotpot server is implemented using node.js, version 11.15.0 (at
time of writing this is the version installed with DietPi). This is
the only version that has been tested. If you have a different version
of node.js
installed, you can always use nvm
to switch between
versions.
DS18x20 temperature sensors use a 1-wire bus that allows multiple
sensors to be daisy-chained on a single GPIO pin. GPIO 18 (header pin
12) is the pin used in all the examples. Hotpot uses the (deprecated)
sysfs
interface to talk to the one-wire bus, which is configured
in /boot/config.txt
as follows:
# 1-wire settings
dtoverlay=w1-gpio,gpiopin=18
(If you have issues with using multiple sensors on one GPIO pin, you can always
allocate a second GPIO pin. Just add another dtoverlay
line.)
Add the following to /etc/modules-load.d/modules.conf
(or the appropriate alternative on your distribution) to load the drivers
on boot.
w1-gpio
w1-therm
Reboot your Pi and log in. You should now be able to see what 1-wire sensors are attached to the system using:
$ ls /sys/bus/w1/devices
Expect to see devices such as 28-0316027f81ff
, and a w1_bus_master*
subdirectory for each GPIO pin configured as a 1-wire bus.
Note that there are issues with the 1-wire driver. This is implemented using bit twiddling on GPIO pins and is not very robust; specifically it breaks when the Pi is very busy, for example when serving web pages. There are also power issues when communicating with sensors over long wires.
The software is written to be robust to failed or infrequent sensor readings, but ultimately you need the occasional accurate result! You can see the effect in the server log, in the form of messages such as this:
Error polling 28-0115914ff5ff CRC check failed ''
It will also send you mail (if you have an admin mail address set in the config) if no good reading has been received for more than 10 minutes.
There are a number of things you can try to improve performance:
- Use a 5V Vdd to supply the DS18b20s. The signal line must still be pulled up to 3.3V, however (don't pull it to 5V or you'll fry the GPIO)
- Disable IRQs in the
wire
module (sudo sh -c "echo options wire disable_irqs=1 >> /etc/modprobe.d/wire.conf"
and reboot) - Reduce the frequency with which UIs (browser or Android) poll the server.
- Allocate a separate GPIO pin for each sensor.
Select a user to run the server. This could be the root
user on your
Pi, or the default user (usually e.g. pi
or dietpi
), or
(recommended) you can create a special user to run the server
software. In the following we will assume you have created a
user hotpot
.
You can check if your user has access to the gpio by logging in as them and:
$ cat /sys/bus/w1/devices/28-0316027f81ff/w1_slave
(substitute the id of one of your sensors for 28-0316027f81ff
). This
should tell you the temperature currently being reported by the sensor.
If your user doesn't have access, you can add them to the gpio group.
$ sudo adduser hotpot gpio
On systems that use systemd
, create /etc/systemd/system/hotpot.service
with
content:
[Unit]
Description=Hotpot
After=network.target
[Service]
Type=simple
Restart=always
LogsDirectory=hotpot
User=hotpot
WorkingDirectory=~
ExecStart=node Hotpot/server/js/Hotpot.js --config hotpot.cfg
Nice=2
[Install]
WantedBy=multi-user.target
Still as root:
# systemctl daemon-reload
# systemctl enable hotpot
You should see a link being created. Then:
# systemctl start hotpot
should start the service.
The controller uses rules written as Javascript functions to control the temperature of the different services offered by the central heating system. It runs a HTTP(S) server that supports querying and changing the configuration of the system from a browser.
The easiest way to install the software is to clone the git repository direct from github, then run the server install:
$ git clone https://github.com/cdot/Hotpot.git
$ (cd Hotpot/server; npm install)
The server can then be run as follows:
node Hotpot/server/js/Hotpot.js <options>
Pass --help
on the command-line to see the options e.g.
$ node Hotpot/server/js/Hotpot.js --help
-h, --help Show this help
-c, --config=ARG Configuration file (default ./hotpot.cfg)
-C, --confhelp Configuration file help
-t, --trace[=ARG] Trace module e.g. --trace all
-d, --debug Run in debug mode - uses stubs for missing hardware
Note that the server can only be run on platforms that do not have
gpio hardware if you have enabled the --debug
option. In this case
the missing sensors will be simulated.
The server is configured by Javascript read from a file (default
./hotpot.cfg
). The repository has an
annotated example.
Once the server is running, the HTTP interface can be used to query and modify the configuration. If the server configuration is changed from the browser interface, the configuration file will be automatically saved.
Rules are Javascript functions that are able to adjust settings via the controller.
Rule functions can interrogate any part of the system using the internal APIs. Default rules are given for Hot Water and Central Heating. You can derive your own rules and point your hotpot.cfg at them.
Rules should always contain conditions to stop runaway temperature rises and freezing.
System change events, such as temperature and pin state, can be logged to files for later analysis. There is no limit on the size of these files, and you are recommended to rotate them on a regular basis. When a log is rotated make sure the old log is deleted - you don't want to leave an empty file behind.
Histories can either be sampling - such as temperatures - or logging, such as pin states or weather agents. Sampling histories require an interval to be specified to set how often the item is sampled. Logging histories rely on the caller explicitly logging events.
Weather information can be retrieved from the UK Meteorological Office data service, via a simple API that can easily be overridden with your own weather service provider. The class "MetOffice" is the reference implementation.
An API key is required to access weather information from the Met Office. These are available for free.
The weather feature is considered experimental, and is likely to change. It's up to you how you use weather information in the rules; the default rules don't use it.
Hotpot can interface to any number of Calendars. By default only Google Calendar is supported, but the software is designed to make it easy to add alternatives.
Follow the instructions in https://developers.google.com/google-apps/calendar/quickstart/nodejs for configuring the calendar API.
Open the downloaded client_secret
file and copy the following fields:
client_id: "738956347299-catel312312sdfafj546754ajfghph3n.apps.googleusercontent.com",
client_secret: "XAfsu6askjhqweo391d6s6ZD",
redirect_uris: [ "urn:ietf:wg:oauth:2.0:oob", "http://localhost" ]
Create a calendar in hotpot.cfg
e.g.
calendar: {
"Example": {
id: "primary",
secrets: {
},
auth_cache: "./example.auth"
}
}
Paste the copied fields from client_secret
into the secrets
object. The primary
id will access your main calendar. The testCalendars.js
command-line program in the server/test
subdirectory can be used to list all the available calendars.
cd
to the server
subdirectory and run the command-line program node AuthoriseCalendar.js
and follow the instructions. Note that this requires an existing hotpot.cfg
.
Calendars are cached and updated as required. An update can be forced at any time by sending a /refresh_calendars
request to the server.
The rules described above can be overridden by events in a calendar which
contain special requests in the event summary or description. The format of
requests is hotpot: <thermostat> = <temperature>
where
<thermostat>
is the name of a thermostat in hotpot.cfg
(e.g. HW
or CH
)
and <temperature>
is a target temperature in °C. For example, hotpot:CH=18
instructs the server to set a target of 18°C for the CH thermostat for the duration
of the calendar event. Note that requests are case-sensitive.
ALL
applies the request to all thermostats. It is
usually used to turn everything off, for example when away on holiday
e.g. hotpot:ALL=0
.
You can also define an event to boost a thermostat up to a target temperature,
and then revert to the rules after it has been reached, by adding the keyword
boost
. For example, hotpot:CH=20 boost
will switch on the central heating
until the temperature reaches 20°C and then revert to the rules.
You can mix commands for different thermostats in a single event by separating
them with semiclons e.g. hotpot:CH=16 boost;HW=45
Calendar events are only used to generate requests. It is ultimately up to the rules functions whether and how those requests are interpreted.
I recommend you create a specific calendar for Hotpot control, in
which case all events in the calendar are assumed to relate to Hotpot. This is
useful when yo uwant to share control over the system with other people.
In this case you can modify the hotpot.cfg
to dispense with the hotpot:
prefix.
The browser app is served automatically when /index.html
is loaded from
a browser. The app provides control and monitoring capabilities from a web
interface that can be used fom desktops, laptops, tablets and smartphones.
The interface includes full help information.
See DEVELOPING.md