Saturday, 30 April 2022

Automating heating vents with openHAB, esp8266 and LEGO - Part 2.5; Hardware rework

Working with hardware is fun; working with LEGO hardware is awesome. So before proceeding with the next part of my heating vent automation series, I took the opportunity to refine my vent manipulator, with the following aims:

  • Quieter operation; v1 sounded like a coffee-grinder
  • Faster movement; to sound like a quieter coffee-grinder for less time
  • Lower stack height above floor level; to avoid impeding the sofa-bed mechanism directly overhead

V1 Hardware

As a reminder, here's the first hardware revision featuring a LEGO Technic XL motor and an extremely over-engineered - and tall - chassis.

V2 Hardware

Here's the respun version, which works as well as, if not better than, the original.

The changes:

  • The chassis is half as high above the vent surface
  • The rack-and-pinion mechanism is centered in the chassis to reduce torque
  • The rack is situated lower to reduce flex
  • The motor is reduced in size to a LEGO Technic "M" motor (quieter and faster)
  • The manipulator clamps to the vent with a Technic pulley instead of a brick, further reducing height-above-floor

Now we're in a really good position to get down-and-dirty with some firmware...

Saturday, 26 March 2022

Things people have trouble with in React / Javascript, part 1: Too much React state

I've been on a bit of a Stack Overflow rampage recently, most commonly swooping in and answering questions/fixing problems people are having with their React apps. I'm going to spend my next few blog posts going over what seems to be giving people the most trouble in 2022.

Episode 1: In which things are overstated

This problem typically manifests itself as a question like "why doesn't my UI update" or the inverse "my UI is always updating" (which is almost always related to useEffect - see later in this series). With the useState hook, state management becomes so easy, it's tempting to just scatter state everywhere inside a component instead of thinking about whether it belongs there, or indeed if it's needed at all.

If I see more than 3 useState hooks in one component, I get nervous, and start looking for ways to:

  • Derive the state rather than store it
  • Push it up
  • Pull it down
The React docs (and Dan Abramov himself) talk a lot about pulling-up and pushing-down state, but I think deriving state may actually be more important than either of those.

What do I mean? Well, I see people doing this:

    const [cars, setCars] = useState([]);
    const [preferredColor, setPreferredColor] = useState(undefined);
    const [preferredMaker, setPreferredMaker= = useState(undefined);
    // DON'T DO THIS:
    const [filteredCars, setFilteredCars] = useState([]);
Obviously I've left out tons of code where the list of cars is fetched and the UI is wired up, but honestly, you can already see the trouble brewing. The cars list and the filteredCars list are both held as React state. But filteredCars shouldn't be - it's the result of applying the user's selections (preferred color and maker) and so can be trivially calculated at render time. As soon as you realise this, all kinds of UI problems with staleness, flicker, and lag just melt away:
    const [cars, setCars] = useState([]);
    const [preferredColor, setPreferredColor] = useState(undefined);
    const [preferredMaker, setPreferredMaker= = useState(undefined);
    // Derive the visible list based on what we have and what we know
    const filteredCars = filterCars(cars, preferredColor, preferredMaker);

I think some people have trouble with their mental model around functional components, and are afraid to have a "naked const" sitting there in their function - somehow it's a hack or a lesser variable than one that useState handed you. Quite the reverse I think.

Another argument might be that it's "inefficient" to derive the data on each and every render. To that, I counter that if you are maintaining the cars and filteredCars lists properly (and this is certainly not guaranteed), then the number of renders should be exactly the same, and thus the amount of work being done is the same. However there's a strong chance that deriving-on-the-fly will actually save you unnecessary renders. I might keep using this car-filtering analogy through this series to explain why this is.

Saturday, 26 February 2022

New Toy

I just received this from the good folk at PowerPal:

This is a cool device that basically should give me real-time API-based access to the power usage of my house. The next logical step for me is to then bundle it up into my openHAB setup. I'll probably begin with just using the HTTP binding to get what I need, and maybe (and it's a BIG maybe) turn it into a genuine binding at some point in the future. My experience trying to get the Broadlink binding merged into the openHAB addons codebase has turned me off that process a little...

Saturday, 29 January 2022

2022 To-Do List

There's just never enough time and/or motivation to do all the things I've got on the back-burner, but some of these have been around for just too long. Hopefully listing them here (and ideally ticking them off with suitable links) will be motivating...

  • The openHAB Broadlink Binding still hasn't been merged into the openHAB codebase. Every week it becomes harder - with such a busy upstream repository, with very exacting code-review standards, it's like nailing jelly to the wall ... of a moving train.
  • frenzy.js my browser-based retro 8-bit arcade game has been rotting for years now. It needs a full React upgrade and some deep thought (or reading-up, or both) about some of the basic game algorithms (like collision-detection, for example)
  • Tons of openHAB mini-projects to automate things around the house - blinds, heating vents, all sorts of stuff

Wish me luck...

Thursday, 30 December 2021

Computers I Have Known - Part 4

For the final instalment of my Computers I Have Known series, a fun distraction from the 2021 dumpster fire, I present my first ever "work computer", the Hewlett-Packard PA-RISC 9000. I was working as a software engineer at a division of Hewlett Packard's network test organisation, writing C code to be executed on test equipment.

This was truly a "tool" of a machine - totally locked down via the Common User Environment, and with very little horsepower onboard beyond what was needed to bring up XWindows, my 21" screen typically consisted of myriad XTerm windows running Telnet sessions into gcc and/or vim on various servers and target boxes.

It was that anonymous that I don't even know what model it was, nor how much RAM or disk capacity it had. But some Googling makes me think it was probably a Series 700 model, most likely a 712:

This is pretty-much exactly how mine looked (even the 4033A monitor designation rings a bell) - we'd sit them vertically for the simple reason that they looked less obviously-PC-like, and thus weirder, and thus cooler...

I'm shocked now reading how much these things cost - $USD8000 or so in 1994 dollars is a lot - but I guess being in a division of Hewlett Packard we'd have been getting them essentially free.

Alongside this workstation, my desk at the time would have had a black HP 14" (Omnibook?) Windows 2000 laptop, with a wired 10/100 Ethernet card sitting in its PCMCIA slot. The laptop would also have been tightly locked-down with a common operating environment and would really only be used for email, web browsing and opening Office documents. I would suspend the PC at the end of each day by shutting its lid, but the HP-UX box would stay permanently powered-on; it took *forever* to boot up.

[HP 46011A keyboard image from]

I still recall being weirdly fond and proud of this machine, with its odd not-quite-a-PC keyboard and enormous (for the time) screen. Having come straight from a UNIX-heavy computer science/engineering university course, it was awesome to actually have my own UNIX workstation, and I customised whatever I was able to in terms of window management and the shell startup files to optimise it to my tastes.

It was no SGI Indy but it was mine, it didn't cost me anything, and it allowed me to earn income converting coffee into code. So it was cool.

Sunday, 28 November 2021

Importing/capturing digital video (DV) for FREE on a Mac in 2021

Like many others, I have a giant box of Mini DV video cassettes from 10+ years ago that I fairly-urgently need to get onto a more long-term-safe medium. As it's a pretty tedious job I have tended to do this in batches, when I can be bothered getting all the necessary bits together. Fortunately my trusty 2012 MacBook Pro has Thunderbolt ports that with just a couple of cheap adapters, can connect to the 4-pin Firewire port of my still-functional Panasonic NV-GS27 camcorder and do the job.

But while the hardware is willing, sometimes the software is not. It's all too easy to get on the upgrade treadmill and forget about applications you only use once every couple of years. In the past I used Vidi, which was minimal but $0, and thus excellent. But it won't work on 64-bit MacOS and appears unmaintained so I needed something new.

All I needed was something that could capture the raw data from each cassette and dump it into a .dv file that I can stash away on a hard drive.After a very dismaying tour through Google and YouTube made me think I'd either need to pay for a software package, or kludge something together using libdc1394 (which would be massive overkill) I finally found what I needed by searching Github directly: vrecord by AMIA Open Source.

vrecord works beautifully on my Catalina (OSX 10.15) MacBook Pro - follow the Basic Usage guide and you'll be capturing those precious memories in no time.

Sunday, 31 October 2021

Bravia, Bravia, wherefore art thou Bravia

Just a quick post that might help anyone with a Sony Bravia X70G/X70xxG family LCD TV.

We just upgraded our 12-year old 40" Bravia to the KD-55X7000G model, which I got almost-new for half price, because I can't resist a bargain. It's not a very high-end TV, but it's got Netflix etc and it puts out a good picture. The operating system is described as "Linux", and it's functional* and snappy, which is all I really want. As a reluctant "Smart TV" purchaser, I'd rather a "dumb" smart TV than one that shows me advertisements.

One of the ways it is unacceptably dumb though, is doing DHCP while it's doing something else. Yes, a TV capable of showing 4K content at 60Hz (that's 4096x2160 * 60 = 530,841,600 pixels per second if you're counting) can't handle obtaining a new DHCP lease - an exchange of 2 simple UDP datagrams over the network.

This was manifesting itself very annoyingly during Netflix sessions. The pattern would be: we'd turn on the TV, then get sidetracked for a bit, then finally settle down and watch a 22-minute episode of "Superstore" on Netflix. All fine. Then, reliably as clockwork, if we decided to watch a second episode, at some point during the show we'd get a "can't access Netflix servers" error, which was completely unrecoverable. Even a swift reboot of the TV wouldn't be enough - leaving it off for about five minutes seemed to be required to flush out the problem.

It turned out that I hadn't explicitly added the TV's MAC address to my dnsmasq configuration, so it was being given an IP address with the default lease time of one hour. Now dnsmasq is pretty smart and won't assign a different IP address to a device once it's seen it (unless it absolutely has to) so it wasn't even anything as nasty as the TV getting a different IP. No, it was simply asking to renew the lease. Obviously the straw that broke the camel's back.

So the "solution" I'm using (and has been flawless so far) is to:

  1. give the TV a static IP address; and
  2. give it a 24 hour lease time
24 hours is more than enough time to cover any foreseeable Netflix binge and the TV will do a DHCPDISCOVER on boot the next time anyway, so we're covered nicely.

(*) Oh there is one other thing - the TV unfathomably doesn't seem to be able to set its clock from the network - I'm looking at fixing that soon, fingers crossed...