Sam Gentle.com

Prototype wrapup #39

Last week was mostly milights, and this week was even more milights. I got a new remote and wifi bridge that I'm hoping to use to finish descrambling the protocol, but in the mean time I wanted to use the wifi bridge to do some fun stuff. So mostly this was code to get colour data from OS X onto my lights.

Monday

The first thing I wanted was to match the colour temperature of my lights to that of my screen. I use f.lux to set the colour temperature for my monitors, so I was hoping to get the information out of that. Unfortunately, f.lux doesn't have an API, so I went looking for ways to get the information from OS X directly. My first attempt was to read the ICC profile out of the display using Python/PyObjC and parse it using PIL's ICC support. Unfortunately, the image profile didn't seem to contain the information I was looking for.

Tuesday

Attempt 2 involved a lot of looking through ICC data. I eventually realised that what I was looking for wasn't the "media white point" or the "chromatic adaptation", which are both ways in which the white point can be set, but another, third way, called the "vcgt", or Video Card Gamma Table. I pulled a parser with vcgt support out of pypng, used that to read the data, had to parse the data manually anyway (there are two different kinds, table-based and formula-based), but finally I had my data. I had to convert the rgb values to color temperatures, which I did using Python's super complicated color library. I think there's probably an easier way to do that, but it worked well enough and I managed to get a value I could pipe to another command which set the display temperature. The updating was still a bit strange, though, I think because f.lux doesn't always update the ICC profile when it makes changes.

Wednesday

Cleanup time. I suspected that there was a way to get the vcgt without having to parse the ICC data. I eventually found CGGetDisplayTransferByTable. There's also CGGetDisplayTransferByFormula but it straight up doesn't work. I only wanted the max gamma values anyway, so the table version was fine. I then proceeded as before but, to cut down on Python's ferocious startup time, I made the scripts stream updates instead of sending one per invocation. Finally, I could click around in f.lux and watch my lights update. Victory!

Friday

Fresh off my high from making colour temperatures work, I forged ahead with part 2 of the plan: getting RGB values from my monitor onto my lights. With a bit more background in using PyObjC it was easier this time, though I still spent a while figuring out how to make graphics contexts work. My approach was to take a screenshot, draw it onto a 1x1 canvas, and then read the pixel data from that canvas. This worked really well, and was fast enough to pull data at close to realtime when I tested it. I actually ran into more issues with the lights than with OS X, because they have a fairly limited bandwidth via the bridge. I added some optimisations to avoid resending repeated colour commands and that helped a bit. Also the hue settings on the lights are, uh, only vaguely related to actual hues. I ended up doing a quadratic regression to approximate what the colours should actually look like, which worked okay but I probably need to do it again with more data. Still, broadly speaking, it was a success.

Conventional Wisdom 2: Honesty is the best policy

Who would willingly describe themselves as dishonest? Well, maybe I should. I don't mean that I lie a lot; sure, I lie, but not very often. But I think honesty is more than not lying, I think it's representing the truth as best you can; not just avoiding direct responsibility for untruth, but actively striving to increase the truth in the universe. By not lying, yes, but also by pushing back against falsehoods and misunderstandings, and by making an effort to speak the truth when you could say nothing.

In that sense, then, the opposite of honesty isn't deceit, but cowardice. It's when you have something to say but don't say it because of fear of the repercussions, or when you see something wrong but don't correct it, or avoid revealing the truth because you're afraid of what it might mean. Lying is a way of trying to control reality by controlling what people think, and this broader dishonesty is no different. If you hold back who you are so that people will like you, you turn your friends into rubes, and your relationships into performances.

It's this kind of broad dishonesty that I feel I am sometimes a perpetrator of, and what I want to push back against this month. It's not so much that I actively try to deceive as that I don't go out of my way to inform. I'm happy to leave things unsaid and remain snuggled safe in the bosom of the status quo. Why rock the boat? But, ideologically, that behaviour doesn't agree with me at all. I'm a global optimiser at heart. Really, it's cowardice. I don't say that with any real sense of self-loathing, it's just a fact; when I don't speak up, it's because I'm afraid of the consequences.

So for this month, I'm taking a few different steps to commit myself to honesty as the best policy. I'm getting more active on Twitter, which I normally use really just to repost stuff from here. I intend to use it more like a journal, write random thoughts there and be generally more open about what's going on in my day. I'm pinned halfway between thinking it will be difficult because nobody will care and thinking it will be difficult because people will care, so it should be fun to find out.

The second thing is I'm going to write a bit differently on this site. I generally try to avoid being too personal and bloggy here, not out of any particular desire to hide, but mostly because I think ideas and generalities are more interesting than what I had for breakfast or whatever. The point is the work, not me. Still, I think there's value in putting the process back into the work, so I'm going to write more personally and see how that feels. I'm going to make an effort to write about any topcs I've been avoiding, and I'm also going to add some "here's who I am" type material to the site, which I've been putting off for ages.

Lastly, and perhaps most dauntingly, I'm going to try to bring this honesty to my personal life. That means describing this experiment to people I'm talking to, making an effort to be honest with them, to speak up if they say something I don't agree with, to avoid censoring myself if there's something I think about saying, and to provide them with the opportunity to be honest back if they want. These type of interactions are more scary, both because real life seems more real than the internet, and also because the potential for consequences is greater.

Still, despite the possible consequences, I do feel that there is something inherently righteous in taking the risk. If I suffer consequences for my honesty, then those consequences were always there waiting for me, I was just hiding from them. Better to face them head-on with courage than hope they never find me; that's no way to live.

I guess we'll see if I still feel that way in a month.

Conventional Wisdom 1 - Conclusion

Well, my month of early to bed, early to rise is over and, although it didn't make me wealthy or wise as promised, I still learned a lot. So how well did I stick to it, what did I learn, what was good or bad about it, and is it a habit worth keeping?

Graph of sleep times

To avoid weaseling out or tricking myself, I tracked my sleep data using Sleep as Android. The graph is a bit confusing; you have to read it bottom to top, so that first entry (New Years Eve) is 5am to 1pm. You can see that the first two weeks went pretty well, but things got a bit patchier after that. The first week I was usually asleep between 10 or 11, and consequently ended up quite sleep deprived. That was fine for a couple days, but beyond that it was just miserable. I eventually realised that to sustainably get up at 6am required being in bed at 9pm.

So my first observation is that being in bed at 9pm is hard. I had to fundamentally change the way I thought about the day, because 6pm no longer meant I could still go for a walk, do some shopping, eat dinner, play a video game, chat to some friends... Rather, it meant 3 hours left in my day, time to start winding down. I could usually only fit one leisure activity in that much time before I needed to get ready for bed, and better make sure it's relaxing because if I'm all riled up from something I was doing at 8:50 I'll probably still be thinking about it when I'm trying to fall asleep.

That stuff was relatively manageable by moving a lot of my relaxation time into the morning or during the day, but what made it so hard was other people. During the month I was invited to evening birthdays, meetings, parties, conversations, dinners, and none of them finished at 9. You have to make a constant effort to bow out of things early, and realistically it means sacrificing a lot of social stuff. I'm not enormously social, but you'd be surprised the number of evening activities you don't notice. Most memorable was my sister calling me to ask if I was coming to her birthday party while I was in the middle of getting ready for bed. Ouch.

I wrote previously about the sense of finite time that comes with getting up early. That's a good thing in as much as it stops you from deceiving yourself about how much time there is in a day, but that rigidity can also be a downside. It was pretty upsetting to look at the time and realise I had barely any day left and more to do, or feel like I was racing against the clock up until I went to sleep. So the rigid bedtime felt quite constraining sometimes, but without it I had to either be sleep deprived or wake up late.

I also mentioned the feeling of getting the jump on the day, and the benefit of being up before anything else. I think that's probably the strongest benefit I found, but I also liked the consistency because it tended to lead to more stability. Getting up at the same time made having a morning routine easier, and that routine being in the morning meant it was much less likely to get swallowed by anything else. All together, I found it led to better-organised days and more of a sense of being on top of things.

My final verdict, then, is a weak keep. I'm going to keep doing it, but I'm not going to take it as seriously. I liked getting up early, but sacrificing other things for it doesn't always make sense. I also like having the flexibility to add a couple extra hours at the end of a day sometimes. It may not mean anything in terms of the grand river of time, but for us mere mortals it can turn a mediocre day into a mediocre day with a nice evening at the end.

Prototype wrapup #38

Last week I started looking into figuring out the protocol scrambling for milight bulbs, and this week was more of the same. I had an unfortunate setback, though, when I managed to blow up my remote control, so it'll probably be a bit longer until I can figure it out.

Tuesday

It would appear that systemd has won and, despite ideological concerns about one-daemon-to-rule-them-all, in practical terms I don't care that much as long as it works and I can run services. Problem is I can't remember the service syntax. I had this issue with Upstart too, and I just had one template file I would copy around, but this time I figured I'd do it right. So I made a Rust command that generates a systemd unit file using switches like --restart and --wantedby. The Rust library ecosystem still hurts (I spent most of my time figuring out which command line parser to use) but overall it was fine.

Wednesday

I had a good time with this one. I needed a lot of data from the milight remote under repeatable conditions, up to and including resetting the remote between commands (to reset the counter to zero). Doing that by hand was really annoying, so I figured I'd use a little ESP8266 to turn the remote into a zombie under my control. Switching the power was fine (thanks, transistors), but automating the buttons was harder, because they use capacitive touch. In the end, I figured out that, isntead of changing the output, switching the microcontroller's input from floating to pullup and back could trigger it reliably. Unfortunately, switching the inputs happened too slowly to send a single touch without repeats, and somewhere in the middle there my breadboard power supply catastrophically failed, taking the remote with it.

Thursday

Undaunted, or at least only mildly daunted, I decided to do the best I could with my existing data. I started rewriting my descrambler and looking through the patterns in the data. After a while my eyes went funny and I started to feel a bit too much like John Nash, but I got some fairly tantalising clues. Byte-swapping the data made things easier to understand (the high bit changes more than the low one) and I began to think maybe the key is the second byte rather than the first, but that's as far as I got. I think I really need that counter data to get much further.

Saturday

I wanted to put Minecraft on my Pocket CHIP, but from experience the default home screen kinda freaks out when you add new stuff to it. I've used Marshmallow's fork before, but it used some janky install script instead of a proper apt repository. I thought, well, how hard could it be to make a repository and put it on Github pages? Pretty hard, as it turns out, but I made a fairly generic Makefile in case I ever need to do it again. Hopefully not, though.

Getting the jump

One thing that has been interesting about early to bed, early to rise is the psychological effect of having more time between when I get up and when my day starts. Nobody else schedules meetings at 6am, and even though I could start working as soon as I wake up, I normally start an hour or two after that.

But when you get up late, you sometimes don't get any time before things happen. The day has started without you, you've woken up 5 minutes before your meeting, something important is happening and you need to deal with it right now, quick, get going! These days are the worst, because you start behind and stay behind, and spend the rest of the day struggling to get back to zero.

Whereas when you start ahead, and you know you've got the jump on the day, you can relax a bit. There's plenty of time before the day starts, so what should that day contain? What would be a good use of that time? Can you prepare for anything you know is going to happen? Are there any problems you think will come up and is there anything you can do about them now?

Of course, this isn't so much about waking up as it is about preparation. Any time you go into a situation without having time to think about that situation, you're at a disadvantage. But what's interesting is that a day is a situation like any other, and you can't really prepare for it unless you have time to think before it starts.