IR-controlled A/C (4/many) - The UI

3 minute read

One very important realization, pretty early in my geek life, was that I’m not a designer. And by that I mean that most websites I have (tried to) designed have ended up being very … let’s just say no great, and that it usually takes me a large amount of time to get to that result.

The graphical design

Well, I’m trying to replace IR remotes, so I tried to make it look a little bit like a remote control. I just wanted to combine the several rooms into one view.

I found a decent font that looks like 7 segment, which was fine to display the room names, and for the temperature itself, I went with an 7-segment SVG, and I can easily switch any part from Javascript. I just define a map with the state of each segment for each number between 0 and 10.

class SevenSegmentDisplay {
  el = undefined;
  mapping = [
    [1, 1, 1, 1, 1, 1, 0],
    [0, 1, 1, 0, 0, 0, 0],
    [1, 1, 0, 1, 1, 0, 1],
    [1, 1, 1, 1, 0, 0, 1],
    [0, 1, 1, 0, 0, 1, 1],
    [1, 0, 1, 1, 0, 1, 1],
    [1, 0, 1, 1, 1, 1, 1],
    [1, 1, 1, 0, 0, 0, 0],
    [1, 1, 1, 1, 1, 1, 1],
    [1, 1, 1, 1, 0, 1, 1]
  ];

  constructor() {
    this.el = $(`<svg xmlns="http://www.w3.org/2000/svg" width="192px" height="320px" viewBox="-1 -1 12 20">
            <g id="adefg" style="fill-rule:evenodd; stroke:#DDDDDD; stroke-width:0.25; stroke-opacity:1; stroke-linecap:butt; stroke-linejoin:miter;">
            	<polygon id="a" points=" 1, 1  2, 0  8, 0  9, 1  8, 2  2, 2" fill="#DDDDDD"/>
            	<polygon id="b" points=" 9, 1 10, 2 10, 8  9, 9  8, 8  8, 2" fill="#DDDDDD"/>
            	<polygon id="c" points=" 9, 9 10,10 10,16  9,17  8,16  8,10" fill="#DDDDDD"/>
            	<polygon id="d" points=" 9,17  8,18  2,18  1,17  2,16  8,16" fill="#DDDDDD"/>
            	<polygon id="e" points=" 1,17  0,16  0,10  1, 9  2,10  2,16" fill="#DDDDDD"/>
            	<polygon id="f" points=" 1, 9  0, 8  0, 2  1, 1  2, 2  2, 8" fill="#DDDDDD"/>
            	<polygon id="g" points=" 1, 9  2, 8  8, 8  9, 9  8,10  2,10" fill="#DDDDDD"/>
            </g>
            </svg>`);
  }

  // Getter for the element
  get element() {
    return this.el
  }

  setDigit(number) {
    number = parseInt(number);
    if (number > 9 || number < 0) {
      console.error("Can't display number " + number);
      return;
    }

    let elements = this.el.find("polygon")
    for (let i = 0; i < 7; i++) {
      $(elements[i]).attr("fill",
        (this.mapping[number][i] ? LCDOn : LCDOff));
    }
  }
}

The code design

With the basic functionalities, ie. get the current state, display it, and send updates, there weren’t too many design decisions to be made. A local config file would have the (tunnel) IP address and port of the Pi inside my home acting as a gateway.

The quirks

With 3 rooms and several buttons (off/heat/cool, etc.) I had to add a litle bit of a wait between the time a key is pressed and the time I send the instruction over — otherwise,there’s a risk that a 3 degre adjustment beeps 3 times (well, 6, because it’s all in Celsius and the increment is 0.5°C)).
A timeout was easily added to solve that.

I also had to add some logic around the modes: if some rooms are heating and I set a room to “Cool”, it should stop the rooms that were heating. Again here, fairly easy logic.

I chose to reload fully the data after sending the POST request over, because I’m pretty lazy and it’s a good way to check visually that the new status aligns with the desired status.

I also added a mode for “all room the same”, which hides the several controllers and just shows one. From the start, I actually had in my Go backend a meta-room called “all”, which I forgot to mention. So there’s a toggle between “all room the same” and “to each their own settings”.

The results

The UI. Tadah!