Planning

A python-based intelligent home thermostat, targeted at (but not requiring) the RaspberryPi and similar small computers. (Originally “RaspberryPyMostat”, for ‘RaspberryPi Python Thermostat’, but that’s too long to reasonably name a Python package).

Especially since the introduction of the Nest thermostat, a lot of people have attempted a project like this. I’d like to think that mine is different - perhaps more polished, perhaps it stores historical data in a real, logical way. Multiple temperatures are nice, and the pluggable scheduling and decision engines are something I haven’t seen in any others yet. The completely open API, and the fact that some of the out-of-the-box components use it is new too. And after looking at some of the options out there, I think the idea of it being packaged and distributed properly is pretty novel too, as are my hopes for a platform-agnostic system; a lot of the options out there are really hardware-hacking projects, and I want to make software that works with as many hardware options as it can. But when it comes down to it, this is an idea that I tried a long time ago and never finished, and want to have another try at regardless of whether it does something unique or becomes just another one of the hundred pieces of software that do the same thing. I’m also going to be playing with some technology that I’ve never used before, so for me this is as much about learning and exploring as it is about producing a polished final codebase.

See:

  • Architecture.md for an overview of the architecture, and most of the documentation that currently exists.
  • DISCOVERY.md for some information on service discovery
  • TWISTED.md for some docs on using Twisted for this

Features

Features planned for the initial release

  • Flexible rules-based scheduling. This can include cron-like schedules (do X at a given time of day, or time of day on one or more days of week, etc.), one-time schedule overrides (“I’m going to be away from December 21st to 28th this year, just keep the temperature above Y”), or instant adjustments (“make the temperature X degress NOW”, in the web UI). The most specific schedule wins. Inital scheduling will support some mix of what can be represented by ISO8601 time intervals and cron expressions.
  • Support for N temperature sensors, and scheduling based on them; i.e. set a daytime target temperature based on the temperature of your office, and a nighttime target based on the temperature in the bedroom.
  • Web UI with robust mobile and touch support. Ideally, the entire system should be configurable by a web UI once it’s installed (which should be done with a Puppet module).
  • Some sort of physical on-the-wall touchscreen control, using the web UI.
  • Everything AGPL 3.0.
  • Scheduling and decision (system run) implemented in plugins (packages, entry points) that use a defined API; some way of reflecting this in the Web UI (maybe this should come over the master API). Initially just implement scheduling as described above and setting temperature based on one temp input; subsequent plugins could include averaging across multiple inputs, weighted average, and predictive on/off cycles (including outside temperature input).
  • Support running all on one RPi, or splitting components apart; should support as many OSes as possible. Support for smaller devices as temperature sensors would be nice.
  • Microservice/component architecture.
  • Open, documented APIs. Aside from the main engine, it should be possible to implement the other components in other languages.
  • mDNS / DNS-SD for zero configuration on devices other than the engine.

Features planned for future releases

  • Data on current and desired temperature(s) and heating/cooling state will be collected. This should allow the scheduling engine to build up historical data on how long it takes to heat or cool one degree at a given temperature, and should allow us to trigger heating/cooling to reach the scheduled temperature at the scheduled time (as opposed to starting the heating/cooling at the scheduled time).
  • Historical data stored in some time-series database; should include all temperature values at the beginning of a run, and every X minutes during a run.

Some Technical Bits and Questions

API

Engine

  • The main process will likely have to have a number of threads: API serving (ReST API), timer/cron for scheduling and comparing temp values to thresholds, main thread (am I missing anything?)
  • Use workers (either real Celery, or just async calling a process/thread) to calculate things?
  • schedules and overrides
  • schedules have start and end time, that are cron-like
  • overrides have a specific start time, and end time that’s either specific (input can be a specific datetime, or a duration) or when the next schedule starts
  • backend - when a schedule or override is input, backend recalculates the next X hours of instructions (schedule with overrides applied), caches them, makes them accessible via API
  • schedules and overrides
  • default temperature thresholds (how much over/under to trigger/overshoot and how often to run)
  • schedules/overrides have temperature targets and thresholds - which sensors to look at, how to weight them. Can be a “simple” input (look at only one sensor, one target temp) or a weighted combination. Can save a default calculation method/sensor weighting.
  • make sure we don’t start/stop the system too often

UI

Testing

  • Unit tests should mock out the txmongo connection. Integration tests require Mongo, and should run a Docker container of it. Need to look into how to do this nicely on Travis.
  • We’ll need some real data fixtures, and to look into the right way to dump and load data from/to Mongo.
  • Assuming we’re going with the API-based model, unit tests should be simple. Integration and acceptance tests are another question.
  • TODO: How to test the API server and client?
  • TODO: How to test the separate services, in isolation from the server?
  • TODO: Try to find a strong unit testing framework for the web UI; we can deal with integration/acceptance testing later.
  • TODO: How do I do acceptance/integration testing with service discovery if I have this running (like, in my house) on my LAN? Just use some “system number” variable?

Relay/Physical Control Unit

dead-simple:

  1. Process starts up, uses service discovery to find the decision engine.
  2. Registers itself with some sort of unique ID (hardware UUID, RaspberryPi serial number, etc.)
  3. Discovers available relay outputs and their states, assigns a unique ID to each.
  4. POST this information to the decision engine.
  5. Start a web server.
  6. Wait for an API request from the decision engine, which is either a GET (current status) or POST (set state).

Decision Engine / Master Control Process

Here’s where the complexity lies.

  • Keep (time-series?) database of historical data on temperature, system state, etc. (including data required for predictive system operation)
  • Determine the current and next (N) schedules.
  • Constantly (every N seconds) compare temperature data to current schedule and operate system accordingly
  • Re-read schedules whenever a change takes place
  • Show end-user current system state and upcoming schedules
  • Provide a plugin interface for schedule algorithms
  • Provide a plugin interface for decision (system run/stop) algorithms
  • Support third-party web UIs via its API, which needs to include support for the plug-in scheduling and decision algorithms (which exist only in this process, not the web UI)
  • Support versioning of ReST and internal APIs

Physical Control Interface