<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="/feeds.xsl" type="text/xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:base="https://chameth.com/">
    <title>Chameth.com - posts like monitoring-power-with-wemo but not debugging-beyond-the-debugger, docker-automatic-nginx-proxy, why-you-should-be-using-https</title>
    <subtitle>Personal homepage of Chris Smith</subtitle>
    <link href="https://chameth.com/feeds/posts/like/monitoring-power-with-wemo/unlike/debugging-beyond-the-debugger,docker-automatic-nginx-proxy,why-you-should-be-using-https/" rel="self"/>
    <link href="https://chameth.com/"/>
    <icon>https://chameth.com/favicon.png</icon>
    <updated>2025-05-21T00:00:00Z</updated>
    <id>https://chameth.com/</id>
    <author>
        <name>Chris Smith</name>
    </author>
    <entry>
        <title>Home Automation Without the Megacorps</title>
        <link href="https://chameth.com/home-automation-without-megacorps/"/>
        <updated>2025-05-21T00:00:00Z</updated>
        <id>https://chameth.com/home-automation-without-megacorps/</id>
        <content xml:lang="en" type="html">&lt;p&gt;I first experimented with home automation in 2016, by picking up a Samsung
“SmartThings” hub. It was terrible. The UI to configure things was slow and
clunky, firmware updates were applied whether you wanted them or not, and
everything stopped working if their cloud services stopped. You were also locked
into whatever integrations they deigned to support, of course. After that broke
for the umpteenth time I scaled back and for years the closest I got to home
automation was a couple of Hue bulbs.&lt;/p&gt;
&lt;p&gt;Recently I’ve been building it out again, though. This time using off-the-shelf
components that interop using Zigbee, open-source software, and some code I
wrote myself. It’s great; it runs entirely locally and has had basically zero
downtime. The Zigbee ecosystem lets me integrate all sorts of things without
having to spend lots of money on “smart” alternatives. I think I’ve spent less
on this incarnation than I did on the original SmartThings hub all those years
ago (even without adjusting for inflation!).&lt;/p&gt;
&lt;h3 id=&#34;my-current-setup&#34;&gt;My current setup&lt;/h3&gt;
&lt;p&gt;I run everything on a Raspberry Pi 4, with a Sonoff USB Zigbee adapter based
on the CC2652P chipset&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a class=&#34;footnote-ref&#34; href=&#34;#fn:1&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;. Interfacing with the Zigbee stack is handled by
&lt;a href=&#34;https://www.zigbee2mqtt.io/&#34;&gt;zigbee2mqtt&lt;/a&gt; (z2m for short), an open-source project that
basically bridges your devices to an MQTT broker&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a class=&#34;footnote-ref&#34; href=&#34;#fn:2&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;. When a device reports some
data, it will send a new message over MQTT; when you want to make a device do
something you just post a message back. It’s incredibly lightweight, but
supports a huge array of devices out of the box. And as it’s just using MQTT,
it’s trivial to integrate with other software or build on top of.&lt;/p&gt;
&lt;!--more--&gt;
&lt;p&gt;I know a lot of people building out this kind of home automation use
&lt;a href=&#34;https://www.home-assistant.io/&#34;&gt;Home Assistant&lt;/a&gt;, but I don’t get on with it
terribly well. It felt incredibly sluggish, and the entire project is just a
bit… much. I want a binary or package or docker image I can just run, not an
entire operating system. That’s not how computers are meant to work! In contrast,
z2m is simple to set up, super light weight and responsive.&lt;/p&gt;
&lt;p&gt;Anyway. z2m exposes Zigbee devices over MQTT, so I wrote some code in Go to
connect to the MQTT broker, and listen to the messages. It’s grown a bit beyond
this now, and I’m skipping some boring bits like error handling and JSON
parsing, but at first I had something like:&lt;/p&gt;
&lt;pre class=&#34;chroma-chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;chroma-nx&#34;&gt;message&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-nx&#34;&gt;topic&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-nx&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-nx&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-nf&#34;&gt;ReadSlices&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-w&#34;&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;chroma-k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-nb&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-nx&#34;&gt;topic&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;==&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;zigbee2mqtt/desk-button&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;chroma-k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-nx&#34;&gt;strings&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-nf&#34;&gt;Contains&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-nx&#34;&gt;message&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;single&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;chroma-nx&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-nf&#34;&gt;Publish&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-kc&#34;&gt;nil&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;[]&lt;/span&gt;&lt;span class=&#34;chroma-nb&#34;&gt;byte&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;{\&amp;#34;state\&amp;#34;: \&amp;#34;TOGGLE\&amp;#34;}&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;zigbee2mqtt/room-lights/set&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;chroma-w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I think I actually made this harder to read by trying to simplify it here, but
hopefully you can follow that it was relatively straight forward to listen
for a particular action to happen (in this case me “single”-pressing on the
device called “desk-button”) and then make another device do something in
response (toggling the state of the “room-lights” device).&lt;/p&gt;
&lt;p&gt;So what actually are these devices? At present in z2m I have the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Some generic buttons&lt;/li&gt;
&lt;li&gt;An air quality sensor (USB powered), and a separate temperature sensor (battery powered)&lt;/li&gt;
&lt;li&gt;A light switch&lt;/li&gt;
&lt;li&gt;Some 240V relay modules, that I use to turn non-smart devices on and off&lt;/li&gt;
&lt;li&gt;Some USB relay modules, for the same purpose&lt;/li&gt;
&lt;li&gt;Some “smart” plugs that I mostly use to monitor power usage&lt;/li&gt;
&lt;li&gt;A motorised blind roller&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I think all of these are either Tuya or Moes branded, and were all sourced from
AliExpress. You can get the same things from Amazon or elsewhere, but they tend
to be 3-4x more expensive for the same product.&lt;/p&gt;
&lt;p&gt;One of the cool things about Zigbee devices is that the powered ones work
together to create a mesh network, so you don’t have to worry about network
repeaters or signal strength like you do with Wi-Fi networks. z2m even makes
a map showing the connections:&lt;/p&gt;
&lt;figure class=&#34;image full&#34;&gt;
  &lt;picture&gt;
      &lt;source srcset=&#34;https://chameth.com/home-automation-without-megacorps/zigbee-map.avif&#34; type=&#34;image/avif&#34;/&gt;
      &lt;source srcset=&#34;https://chameth.com/home-automation-without-megacorps/zigbee-map.webp&#34; type=&#34;image/webp&#34;/&gt;
      &lt;img src=&#34;https://chameth.com/home-automation-without-megacorps/zigbee-map.png&#34; alt=&#34;A &amp;#34;map&amp;#34; showing how Zigbee devices connect to one another&#34; loading=&#34;lazy&#34; width=&#34;1093&#34; height=&#34;651&#34;/&gt;
  &lt;/picture&gt;
  &lt;figcaption&gt;&lt;p&gt;The network map produced by z2m. You can see how all the powered devices form a mesh that the lower power ones can connect to.&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id=&#34;some-interesting-automations&#34;&gt;Some interesting automations&lt;/h3&gt;
&lt;figure class=&#34;image right&#34;&gt;
  &lt;picture&gt;
      &lt;source srcset=&#34;https://chameth.com/home-automation-without-megacorps/relay.avif&#34; type=&#34;image/avif&#34;/&gt;
      &lt;source srcset=&#34;https://chameth.com/home-automation-without-megacorps/relay.webp&#34; type=&#34;image/webp&#34;/&gt;
      &lt;img src=&#34;https://chameth.com/home-automation-without-megacorps/relay.jpg&#34; alt=&#34;A Zigbee relay and some wago connectors wired up in a project box&#34; loading=&#34;lazy&#34; width=&#34;325&#34; height=&#34;500&#34;/&gt;
  &lt;/picture&gt;
  &lt;figcaption&gt;&lt;p&gt;A Zigbee relay spliced into the power cable for the fan&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;So what do I actually do with all of this? Some of it is just what I’ll call
“laziness automation”: I want to be able to turn on the lights without getting
up and walking to the light switch. So there’s a Zigbee button on my desk that
does it. Then there are some less manual automations: my blinds are
automatically closed at sunset&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a class=&#34;footnote-ref&#34; href=&#34;#fn:3&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;, for example. It feels a bit trivial, but it’s
surprisingly nice just not to have to think about that at all.&lt;/p&gt;
&lt;p&gt;Another nice quality of life automation is the light I have above my monitor.
It’s USB powered, and I now have it going through a Zigbee USB relay that lets
it be toggled on and off. Then I have a small agent running on my desktop that
turns the light on when the computer is unlocked, and off when it locks or
shuts down. I keep meaning to make a “film mode” that detects when I’m watching
a film, and turning all the lights and blinds down, but I haven’t got around
to it yet.&lt;/p&gt;
&lt;p&gt;The most complex automation is probably for a window fan. It’s not smart in
any way, so I cut the power cable and inserted a Zigbee relay. The whole thing
is housed in a little project box to keep it secure. The relay basically acts
as a switch: the live wire leading to the fan runs to the “normally open”&lt;sup id=&#34;fnref:4&#34;&gt;&lt;a class=&#34;footnote-ref&#34; href=&#34;#fn:4&#34; role=&#34;doc-noteref&#34;&gt;4&lt;/a&gt;&lt;/sup&gt;
contact, while the upstream power goes to “common”. When the relay is told to
turn the fan on, the two get connected and the fan gets power. Oh, it’s also
not actually a window fan, but I designed and 3D printed some adapters so that
it sits right in the window.&lt;/p&gt;
&lt;p&gt;So now we have a window fan that can be turned off and on automatically. But I don’t
want to have to press a button to do that. I’m lazy, remember? Instead, I made
it so that the Go code constantly monitors the temperature reported by the air
quality sensor, and queries the free &lt;a href=&#34;https://openweathermap.org/&#34;&gt;OpenWeatherMap API&lt;/a&gt;
to get the rough temperature outside. It can then turn the fan on if the room is
too hot, and outside is cool enough to make a difference (there’s no point in
blowing hotter air in!).&lt;/p&gt;
&lt;figure class=&#34;image left&#34;&gt;
  &lt;picture&gt;
      &lt;source srcset=&#34;https://chameth.com/home-automation-without-megacorps/fan-graph.avif&#34; type=&#34;image/avif&#34;/&gt;
      &lt;source srcset=&#34;https://chameth.com/home-automation-without-megacorps/fan-graph.webp&#34; type=&#34;image/webp&#34;/&gt;
      &lt;img src=&#34;https://chameth.com/home-automation-without-megacorps/fan-graph.png&#34; alt=&#34;A graph of room temperature, slowly rising to 23.5 degrees, then sharply dropping to 19, rising to 20, dropping to 19 again, etc&#34; loading=&#34;lazy&#34; width=&#34;540&#34; height=&#34;500&#34;/&gt;
  &lt;/picture&gt;
  &lt;figcaption&gt;&lt;p&gt;A graph of room temperature, showing the effect of the fan being turned on and off&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;I don’t want it to do that all the time though. The room doesn’t need to be
cooled if I’m not around. There are various Zigbee presence sensors you can get,
but the cheaper ones seem to be of dubious quality. Instead, I wrote some code
to guess whether I’m present. It uses the state of the monitor light
as a proxy for “is the computer in use”, and then makes some guesses based on
the last time the computer was used and the current time (if I turn the computer
off at midnight it probably means I’m going to sleep; if I turn it off at 2pm
it probably means I’m going out somewhere).&lt;/p&gt;
&lt;p&gt;You can see in the graph that the fan has a decent impact on temperature. I
coded it to cool the room to 19 degrees, but then not turn on again until it
was above 20. This prevents it flip-flopping on and off constantly. You can
clearly see the pattern in the graph, as it actively cools and then slowly
the room warms back up. This arrangement is much better than being woken up at
5am because it’s painfully cold. Trust me.&lt;/p&gt;
&lt;h3 id=&#34;bonuses-metrics-and-3d-printer&#34;&gt;Bonuses: metrics and 3D printer&lt;/h3&gt;
&lt;p&gt;One of the things my custom Go code does is collate all the various stats
reported by the Zigbee devices, and inserts them into a &lt;a href=&#34;https://victoriametrics.com/&#34;&gt;VictoriaMetrics&lt;/a&gt;
database. I originally hosted this on the Pi itself, and it performed fine, but
I’ve since moved it onto a server so that I can use it for some other things
as well.&lt;/p&gt;
&lt;p&gt;I set up Grafana to point to VM, and can create dashboards showing power usage,
what devices are turned on when, and a bunch of environmental conditions. This
also makes it easy to spot how good the data coming from the devices are. For
example, the air quality sensor reports a figure for the amount of Carbon Dioxide
in the air, as well as the amount of Volatile Organic Compounds (VOCs). The
graphs are basically identical, but on a different scale. It turns out this
particular device has no actual way of detecting CO₂, so it just “calculates”
it from the VOCs figure. Useful to know if you want to actually use that data.&lt;/p&gt;
&lt;p&gt;Recently I came across &lt;a href=&#34;https://github.com/torbenconto/bambulabs_api&#34;&gt;a go library for interacting with Bambu Lab printers&lt;/a&gt;,
so I’ve also hooked that into my automation. It exports metrics about the
printer, so I now have a way of seeing what’s going on when I’m not physically
present&lt;sup id=&#34;fnref:5&#34;&gt;&lt;a class=&#34;footnote-ref&#34; href=&#34;#fn:5&#34; role=&#34;doc-noteref&#34;&gt;5&lt;/a&gt;&lt;/sup&gt;. I even added a HTTP endpoint (exposed over &lt;a href=&#34;https://tailscale.com/&#34;&gt;Tailscale&lt;/a&gt;) that
shows pictures from the built-in camera.&lt;/p&gt;
&lt;p&gt;On the automation front, I’ve made it automatically turn off the printer’s light
when it finishes a print, and also added push notifications via &lt;a href=&#34;https://pushover.net/&#34;&gt;PushOver&lt;/a&gt;
whenever the state changes. No longer will I be sat in another room blissfully
unaware it ran out of filament seconds after I walked out the door!&lt;/p&gt;
&lt;h3 id=&#34;was-it-worth-it&#34;&gt;Was it worth it?&lt;/h3&gt;
&lt;p&gt;These days you could probably just buy some kind of ‘smart home’ hub that works
well enough, and do most of what I’ve done with a lot less effort and no coding.
I’m still of the opinion that for something so essentially &lt;em&gt;local&lt;/em&gt;, it should
itself be managed entirely locally. I don’t trust companies like Google or
Amazon not to kill their products, or change or remove an API I rely on.&lt;/p&gt;
&lt;p&gt;Obviously the “Not Invented Here” approach of coding everything yourself doesn’t
suit everyone, but as someone who enjoys coding and enjoys having things work
&lt;em&gt;just so&lt;/em&gt; it works very well for me.&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr/&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;It turns out the chipset is important. I initially used a similar Sonoff
dongle that used a CC2531 chipset, and its performance wasn’t great. It often
failed to pair with new devices, and dropped links to existing ones. The
&lt;a href=&#34;https://www.zigbee2mqtt.io/advanced/zigbee/02_improve_network_range_and_stability.html&#34;&gt;zigbee2mqtt docs&lt;/a&gt;
do explicitly advise against the CC2531 chips for that reason. At the time they
recommended CC2652Ps, so that’s what I went with. If you’re starting new I’d
go with whatever their latest recommendation was. &lt;a class=&#34;footnote-backref&#34; href=&#34;#fnref:1&#34; role=&#34;doc-backlink&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;MQTT is basically a network protocol for publishing and subscribing to
arbitrary messages. A broker is the thing that sits in the middle and routes
the messages. I use &lt;a href=&#34;https://mosquitto.org/&#34;&gt;Mosquitto&lt;/a&gt; but any will do. &lt;a class=&#34;footnote-backref&#34; href=&#34;#fnref:2&#34; role=&#34;doc-backlink&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34;&gt;
&lt;p&gt;They originally also re-opened at sunrise but that was a terrible
mistake. Who knew the sun rose so early?! &lt;a class=&#34;footnote-backref&#34; href=&#34;#fnref:3&#34; role=&#34;doc-backlink&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:4&#34;&gt;
&lt;p&gt;“open” meaning “there’s a gap so it doesn’t work” not
“open for business”. This confusion in terminology also extends to drawbridges. &lt;a class=&#34;footnote-backref&#34; href=&#34;#fnref:4&#34; role=&#34;doc-backlink&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:5&#34;&gt;
&lt;p&gt;I use the printer in LAN mode, which means there’s no way to monitor it
from a phone, even if you’re connected to the same network still. &lt;a class=&#34;footnote-backref&#34; href=&#34;#fnref:5&#34; role=&#34;doc-backlink&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</content>
    </entry>
    <entry>
        <title>Monitoring power draw with WeMo Insight Switches</title>
        <link href="https://chameth.com/monitoring-power-with-wemo/"/>
        <updated>2016-05-02T00:00:00Z</updated>
        <id>https://chameth.com/monitoring-power-with-wemo/</id>
        <content xml:lang="en" type="html">&lt;figure class=&#34;image left&#34;&gt;
  &lt;picture&gt;
      &lt;source srcset=&#34;https://chameth.com/monitoring-power-with-wemo/switch.avif&#34; type=&#34;image/avif&#34;/&gt;
      &lt;source srcset=&#34;https://chameth.com/monitoring-power-with-wemo/switch.webp&#34; type=&#34;image/webp&#34;/&gt;
      &lt;img src=&#34;https://chameth.com/monitoring-power-with-wemo/switch.jpg&#34; alt=&#34;A WeMo Insight Switch&#34; loading=&#34;lazy&#34; width=&#34;522&#34; height=&#34;522&#34;/&gt;
  &lt;/picture&gt;
  &lt;figcaption&gt;&lt;p&gt;A WeMo Insight Switch&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;I recently picked up a couple of &lt;a href=&#34;http://www.belkin.com/uk/p/P-F7C029/&#34;&gt;Belkin’s WeMo
Insight Switches&lt;/a&gt; to monitor power usage for my PC and networking equipment. WeMo is Belkin’s
home automation brand, and the switches allow you to toggle power on and off with an app, and
monitor power usage.&lt;/p&gt;
&lt;p&gt;The WeMo Android app is pretty dismal. It’s slow, doesn’t look great, and crashed about a dozen
times during the setup process for each of my two switches. It also doesn’t provide much
information at all about power: you can see average power draw and current power draw, and that’s
basically it.&lt;/p&gt;
&lt;p&gt;Belkin has provided an option to e-mail yourself a spreadsheet with historical power data, and can
even do it on a regularly scheduled basis, but that’s not really a nice solution if you want
up-to-date power stats. Even if you were happy with data arriving in batch, having to get hold
of an e-mail attachment and parse out a weirdly formatted spreadsheet doesn’t make for easy
automation. It also relies on Belkin supporting the service indefinitely, which isn’t necessarily
going to happen.&lt;/p&gt;
&lt;!--more--&gt;
&lt;h3 id=&#34;enter-the-soap-api&#34;&gt;Enter the SOAP API&lt;/h3&gt;
&lt;p&gt;Fortunately, the devices themselves expose an API to get the data. Once a switch is setup with the
WeMo app, it connects to a WiFi network. You can discover WeMo devices on the network using a UPnP
broadcast, and then from there a list of supported services. Each service has a number of SOAP
actions, with nice obvious names, and parameters documented in the XML service description.&lt;/p&gt;
&lt;p&gt;For the insight switches, there’s a service at &lt;code&gt;/upnp/control/insight1&lt;/code&gt; which has a number of
actions including &lt;code&gt;GetPower&lt;/code&gt; and &lt;code&gt;GetTodayKWH&lt;/code&gt;. Sending a SOAP request isn’t too difficult
(albeit nowhere near as nice as a REST JSON API) — here’s a sample request I made using
the &lt;a href=&#34;https://chrome.google.com/webstore/detail/dhc-rest-client/aejoelaoggembcahagimdiliamlcdmfm/&#34;&gt;DHC chrome extension&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&#34;chroma-chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-nf&#34;&gt;POST&lt;/span&gt; &lt;span class=&#34;chroma-nn&#34;&gt;/upnp/control/insight1&lt;/span&gt; &lt;span class=&#34;chroma-kr&#34;&gt;HTTP&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;chroma-m&#34;&gt;1.1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-n&#34;&gt;Accept&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-l&#34;&gt;*/*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-n&#34;&gt;Accept-Encoding&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-l&#34;&gt;gzip, deflate&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-n&#34;&gt;Accept-Language&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-l&#34;&gt;en-GB,en;q=0.8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-n&#34;&gt;Content-Type&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-l&#34;&gt;text/xml&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-n&#34;&gt;Origin&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-l&#34;&gt;chrome-extension://aejoelaoggembcahagimdiliamlcdmfm&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-n&#34;&gt;SOAPACTION&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-l&#34;&gt;&amp;#34;urn:Belkin:service:insight:1#GetPower&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-n&#34;&gt;User-Agent&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-l&#34;&gt;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.29 Safari/537.36&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-nt&#34;&gt;&amp;lt;s:Envelope&lt;/span&gt; &lt;span class=&#34;chroma-na&#34;&gt;xmlns:s=&lt;/span&gt;&lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;http://schemas.xmlsoap.org/soap/envelope/&amp;#34;&lt;/span&gt; &lt;span class=&#34;chroma-na&#34;&gt;s:encodingStyle=&lt;/span&gt;&lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;http://schemas.xmlsoap.org/soap/encoding/&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    &lt;span class=&#34;chroma-nt&#34;&gt;&amp;lt;s:Body&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;        &lt;span class=&#34;chroma-nt&#34;&gt;&amp;lt;u:GetPower&lt;/span&gt; &lt;span class=&#34;chroma-na&#34;&gt;xmlns:u=&lt;/span&gt;&lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;urn:Belkin:service:insight:1&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-nt&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    &lt;span class=&#34;chroma-nt&#34;&gt;&amp;lt;/s:Body&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-nt&#34;&gt;&amp;lt;/s:Envelope&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The name of the action (in the SOAPACTION header) and the XML namespace in the body are both
constructed from information in the service definition. The result that comes back is:&lt;/p&gt;
&lt;pre class=&#34;chroma-chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-nt&#34;&gt;&amp;lt;s:Envelope&lt;/span&gt; &lt;span class=&#34;chroma-na&#34;&gt;xmlns:s=&lt;/span&gt;&lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;http://schemas.xmlsoap.org/soap/envelope/&amp;#34;&lt;/span&gt; &lt;span class=&#34;chroma-na&#34;&gt;s:encodingStyle=&lt;/span&gt;&lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;http://schemas.xmlsoap.org/soap/encoding/&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    &lt;span class=&#34;chroma-nt&#34;&gt;&amp;lt;s:Body&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;        &lt;span class=&#34;chroma-nt&#34;&gt;&amp;lt;u:GetPowerResponse&lt;/span&gt; &lt;span class=&#34;chroma-na&#34;&gt;xmlns:u=&lt;/span&gt;&lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;urn:Belkin:service:insight:1&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;            &lt;span class=&#34;chroma-nt&#34;&gt;&amp;lt;InstantPower&amp;gt;&lt;/span&gt;92170&lt;span class=&#34;chroma-nt&#34;&gt;&amp;lt;/InstantPower&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;        &lt;span class=&#34;chroma-nt&#34;&gt;&amp;lt;/u:GetPowerResponse&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    &lt;span class=&#34;chroma-nt&#34;&gt;&amp;lt;/s:Body&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-nt&#34;&gt;&amp;lt;/s:Envelope&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The current power draw in milliwatts is returned in the &lt;code&gt;&amp;lt;InstantPower&amp;gt;&lt;/code&gt; argument.&lt;/p&gt;
&lt;h3 id=&#34;putting-the-data-to-work&#34;&gt;Putting the data to work&lt;/h3&gt;
&lt;p&gt;So now we have a way to pull the current power draw, a nice thing to do would be to plot a graph
of it to see the variation over time. This is the short of thing you’d expect to see in the Belkin
app, but it’s sadly missing. After a bit of research I settled on the tried and true
&lt;a href=&#34;http://oss.oetiker.ch/rrdtool/&#34;&gt;rrdtool&lt;/a&gt; to store data and generate graphs. I created a
new database to store the values from the two switches:&lt;/p&gt;
&lt;pre class=&#34;chroma-chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;rrdtool create power.rrd &lt;span class=&#34;chroma-se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    --start now &lt;span class=&#34;chroma-se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    --step &lt;span class=&#34;chroma-m&#34;&gt;60&lt;/span&gt; &lt;span class=&#34;chroma-se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    DS:wemoComputer:GAUGE:120:U:U &lt;span class=&#34;chroma-se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    DS:wemoNetworking:GAUGE:120:U:U &lt;span class=&#34;chroma-se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    RRA:AVERAGE:0.5:1:1440 &lt;span class=&#34;chroma-se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    RRA:AVERAGE:0.5:10:1008 &lt;span class=&#34;chroma-se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    RRA:AVERAGE:0.5:30:1488 &lt;span class=&#34;chroma-se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    RRA:AVERAGE:0.5:120:1488 &lt;span class=&#34;chroma-se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    RRA:AVERAGE:0.5:360:1488 &lt;span class=&#34;chroma-se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    RRA:AVERAGE:0.5:1440:36500
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This creates a database file which expects values to be given every 60 seconds for two data series:
‘wemoComputer’ and ‘wemoNetworking’. These are gauge types (i.e., a value we read off a gauge,
rather than a counter that keeps going up) with no minimum and maximum (‘U’).&lt;/p&gt;
&lt;p&gt;It then defines a series of round-robin archives. Each of these stores a fixed number of entries,
and the oldest is overwritten when they become full. The interesting arguments are the step count
(second to last) and number of samples (last argument). The first one takes every sample and keeps
1,440 of them (i.e., a full day at 1-minute resolution); the last one has a step of 1,440 and keeps
36500 of them (i.e., 100 years at 1-day resolution). The use of RRAs ensures that rrdtool can retain
enough data to create historical graphs, while providing a fixed, finite maximum file size. With
sufficient RRA coverage you can graph most timescales and have data available at a reasonable
resolution.&lt;/p&gt;
&lt;p&gt;Next, I created a small python script to retrieve the power using SOAP:&lt;/p&gt;
&lt;pre class=&#34;chroma-chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-ch&#34;&gt;#!/usr/bin/python3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;chroma-nn&#34;&gt;requests&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;chroma-nn&#34;&gt;xml.etree&lt;/span&gt; &lt;span class=&#34;chroma-kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;ElementTree&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;chroma-nf&#34;&gt;get_power&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;ip_and_port&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    &lt;span class=&#34;chroma-n&#34;&gt;headers&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;chroma-s1&#34;&gt;&amp;#39;Content-type&amp;#39;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-s1&#34;&gt;&amp;#39;text/xml&amp;#39;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-s1&#34;&gt;&amp;#39;SOAPACTION&amp;#39;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-s1&#34;&gt;&amp;#39;&amp;#34;urn:Belkin:service:insight:1#GetPower&amp;#34;&amp;#39;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    &lt;span class=&#34;chroma-n&#34;&gt;payload&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;chroma-s1&#34;&gt;&amp;#39;&amp;#39;&amp;#39;&amp;lt;s:Envelope xmlns:s=&amp;#34;http://schemas.xmlsoap.org/soap/envelope/&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-s1&#34;&gt;                             s:encodingStyle=&amp;#34;http://schemas.xmlsoap.org/soap/encoding/&amp;#34;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-s1&#34;&gt;                  &amp;lt;s:Body&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-s1&#34;&gt;                   &amp;lt;u:GetPower xmlns:u=&amp;#34;urn:Belkin:service:insight:1&amp;#34;/&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-s1&#34;&gt;                  &amp;lt;/s:Body&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-s1&#34;&gt;                 &amp;lt;/s:Envelope&amp;gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    &lt;span class=&#34;chroma-n&#34;&gt;r&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;requests&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;post&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;http://&lt;/span&gt;&lt;span class=&#34;chroma-si&#34;&gt;%s&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;/upnp/control/insight1&amp;#34;&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;ip_and_port&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;headers&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;headers&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;payload&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    &lt;span class=&#34;chroma-n&#34;&gt;et&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;ElementTree&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;fromstring&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;text&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    &lt;span class=&#34;chroma-k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;et&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;find&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-s1&#34;&gt;&amp;#39;.//InstantPower&amp;#39;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;text&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I then have a dictionary of IP addresses to data series names, and the script polls each one in
turn and then executes an &lt;code&gt;rrdtool update&lt;/code&gt; query to add the items to the database. I have this
script running every minute via cron.&lt;/p&gt;
&lt;aside class=&#34;update raised-box&#34;&gt;
  &lt;h5 class=&#34;plain-header&#34;&gt;Update 2016-05-06:&lt;/h5&gt;
  &lt;p&gt;After leaving my script running for a few days, it suddenly
stopped getting any data. It turns out the WeMo switches spontaneously change the ports they listen
on every now and then. To reliably query them, you need to perform an SSDP search on the network,
and get the correct address from the switches’ response.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;After leaving the script to run for a bit and gather data, it’s time to make some graphs. I use
the following to create a graph with a background gradient:&lt;/p&gt;
&lt;pre class=&#34;chroma-chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;rrdtool graph desk-1d.png &lt;span class=&#34;chroma-se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;        -o -X0 -w800 -h500 &lt;span class=&#34;chroma-se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;        -u &lt;span class=&#34;chroma-m&#34;&gt;2000&lt;/span&gt; -l &lt;span class=&#34;chroma-m&#34;&gt;20&lt;/span&gt; -r &lt;span class=&#34;chroma-se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;        DEF:raw&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power.rrd:wemoComputer:AVERAGE &lt;span class=&#34;chroma-se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;        CDEF:power&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;raw,1000,/ &lt;span class=&#34;chroma-se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;        CDEF:powerz&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,2000,LT,power,2000,IF CDEF:powerzNoUnk&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,UN,0,powerz,IF AREA:powerzNoUnk#ff0000 &lt;span class=&#34;chroma-se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;        CDEF:powery&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,1500,LT,power,1500,IF CDEF:poweryNoUnk&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,UN,0,powery,IF AREA:poweryNoUnk#ff0000 &lt;span class=&#34;chroma-se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;        CDEF:powerx&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,1000,LT,power,1000,IF CDEF:powerxNoUnk&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,UN,0,powerx,IF AREA:powerxNoUnk#ff0000 &lt;span class=&#34;chroma-se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;        CDEF:powerw&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,900,LT,power,900,IF CDEF:powerwNoUnk&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,UN,0,powerw,IF AREA:powerwNoUnk#ff0000 &lt;span class=&#34;chroma-se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;        CDEF:powerv&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,800,LT,power,800,IF CDEF:powervNoUnk&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,UN,0,powerv,IF AREA:powervNoUnk#ff1b00 &lt;span class=&#34;chroma-se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;        CDEF:poweru&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,700,LT,power,700,IF CDEF:poweruNoUnk&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,UN,0,poweru,IF AREA:poweruNoUnk#ff4100 &lt;span class=&#34;chroma-se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;        CDEF:powert&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,600,LT,power,600,IF CDEF:powertNoUnk&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,UN,0,powert,IF AREA:powertNoUnk#ff6600 &lt;span class=&#34;chroma-se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;        CDEF:powers&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,400,LT,power,400,IF CDEF:powersNoUnk&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,UN,0,powers,IF AREA:powersNoUnk#ff8e00 &lt;span class=&#34;chroma-se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;        CDEF:powerr&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,200,LT,power,200,IF CDEF:powerrNoUnk&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,UN,0,powerr,IF AREA:powerrNoUnk#ffb500 &lt;span class=&#34;chroma-se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;        CDEF:powerq&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,180,LT,power,180,IF CDEF:powerqNoUnk&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,UN,0,powerq,IF AREA:powerqNoUnk#ffdb00 &lt;span class=&#34;chroma-se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;        CDEF:powerp&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,160,LT,power,160,IF CDEF:powerpNoUnk&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,UN,0,powerp,IF AREA:powerpNoUnk#fdff00 &lt;span class=&#34;chroma-se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;        CDEF:powero&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,140,LT,power,140,IF CDEF:poweroNoUnk&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,UN,0,powero,IF AREA:poweroNoUnk#d7ff00 &lt;span class=&#34;chroma-se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;        CDEF:powern&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,120,LT,power,120,IF CDEF:powernNoUnk&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,UN,0,powern,IF AREA:powernNoUnk#b0ff00 &lt;span class=&#34;chroma-se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;        CDEF:powerm&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,100,LT,power,100,IF CDEF:powermNoUnk&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,UN,0,powerm,IF AREA:powermNoUnk#8aff00 &lt;span class=&#34;chroma-se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;        CDEF:powerl&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,90,LT,power,90,IF CDEF:powerlNoUnk&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,UN,0,powerl,IF AREA:powerlNoUnk#65ff00 &lt;span class=&#34;chroma-se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;        CDEF:powerk&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,80,LT,power,80,IF CDEF:powerkNoUnk&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,UN,0,powerk,IF AREA:powerkNoUnk#3eff00 &lt;span class=&#34;chroma-se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;        CDEF:powerj&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,70,LT,power,70,IF CDEF:powerjNoUnk&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,UN,0,powerj,IF AREA:powerjNoUnk#17ff00 &lt;span class=&#34;chroma-se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;        CDEF:poweri&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,60,LT,power,60,IF CDEF:poweriNoUnk&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,UN,0,poweri,IF AREA:poweriNoUnk#00ff10 &lt;span class=&#34;chroma-se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;        CDEF:powerh&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,50,LT,power,50,IF CDEF:powerhNoUnk&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,UN,0,powerh,IF AREA:powerhNoUnk#00ff36 &lt;span class=&#34;chroma-se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;        CDEF:powerg&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,40,LT,power,40,IF CDEF:powergNoUnk&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,UN,0,powerg,IF AREA:powergNoUnk#00ff5c &lt;span class=&#34;chroma-se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;        CDEF:powerf&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,30,LT,power,30,IF CDEF:powerfNoUnk&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,UN,0,powerf,IF AREA:powerfNoUnk#00ff83 &lt;span class=&#34;chroma-se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;        CDEF:powere&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,20,LT,power,20,IF CDEF:powereNoUnk&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,UN,0,powere,IF AREA:powereNoUnk#00ffa8 &lt;span class=&#34;chroma-se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;        CDEF:powerd&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,0,LT,power,0,IF CDEF:powerdNoUnk&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;power,UN,0,powerd,IF AREA:powerdNoUnk#00ffd0 &lt;span class=&#34;chroma-se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;        LINE:power#080
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This seems a bit unweildy, but it’s fairly straight forward. The options tell rrdtool to create
a graph with a canvas size of 800x500 pixels, a lower limit of 20W, upper limit of 2kW, and a
log scale. The first &lt;code&gt;CDEF&lt;/code&gt; divides our raw value (which was in millwatts) by 1000 to get a value
in watts. rrdtool uses reverse polish notation like some calculators, so you provide the arguments
before the operator.&lt;/p&gt;
&lt;p&gt;The big block of &lt;code&gt;CDEF&lt;/code&gt;/&lt;code&gt;CDEF&lt;/code&gt;/&lt;code&gt;AREA&lt;/code&gt; parameters creates a series of area plots in different colours
according to the power level. They’re in descending order so the smaller areas are drawn on top of
the larger layers. This results in a graph that looks like this:&lt;/p&gt;
&lt;figure class=&#34;image full&#34;&gt;
  &lt;picture&gt;
      &lt;source srcset=&#34;https://chameth.com/monitoring-power-with-wemo/desk-1d.avif&#34; type=&#34;image/avif&#34;/&gt;
      &lt;source srcset=&#34;https://chameth.com/monitoring-power-with-wemo/desk-1d.webp&#34; type=&#34;image/webp&#34;/&gt;
      &lt;img src=&#34;https://chameth.com/monitoring-power-with-wemo/desk-1d.png&#34; alt=&#34;Graph of power usage over a day&#34; loading=&#34;lazy&#34; width=&#34;881&#34; height=&#34;541&#34;/&gt;
  &lt;/picture&gt;
  &lt;figcaption&gt;&lt;p&gt;Graph of power usage over a day&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;This graph shows the total power for all the things plugged in at my desk. You can see the idle
power draw is around 60W. When I’m using the computer it jumps up to around 130W, and when the
computer is under heavy load (playing games, for example) it goes up even further to the 200W mark.
With a couple of small tweaks to the rrdtool command, I also have a graph showing the entire week:&lt;/p&gt;
&lt;figure class=&#34;image full&#34;&gt;
  &lt;picture&gt;
      &lt;source srcset=&#34;https://chameth.com/monitoring-power-with-wemo/desk-1w.avif&#34; type=&#34;image/avif&#34;/&gt;
      &lt;source srcset=&#34;https://chameth.com/monitoring-power-with-wemo/desk-1w.webp&#34; type=&#34;image/webp&#34;/&gt;
      &lt;img src=&#34;https://chameth.com/monitoring-power-with-wemo/desk-1w.png&#34; alt=&#34;Graph of power usage over a week&#34; loading=&#34;lazy&#34; width=&#34;881&#34; height=&#34;541&#34;/&gt;
  &lt;/picture&gt;
  &lt;figcaption&gt;&lt;p&gt;Graph of power usage over a week&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The two huge spikes near the start of the data are caused by a heater under my desk. They’re also
one of the main reasons I chose to plot the graphs with a logarithmic scale. With a linear scale
between 20W and 2kW, the graph would be completely dominated by these large spikes — in fact
the difference in height between the two spikes would take almost half the graph! The
relative difference between the normal values of 60-200W and the heater’s value of 1.8kW isn’t
actually that interesting, and certainly not worth using about 80% of the graph to demonstrate. The
log scale helps to compress this, and emphasises the difference in the smaller values more.&lt;/p&gt;
</content>
    </entry>
    <entry>
        <title>Reverse engineering the Sense API</title>
        <link href="https://chameth.com/sense-api/"/>
        <updated>2016-04-10T00:00:00Z</updated>
        <id>https://chameth.com/sense-api/</id>
        <content xml:lang="en" type="html">&lt;figure class=&#34;image right&#34;&gt;
  &lt;picture&gt;
      &lt;source srcset=&#34;https://chameth.com/sense-api/sense.avif&#34; type=&#34;image/avif&#34;/&gt;
      &lt;source srcset=&#34;https://chameth.com/sense-api/sense.webp&#34; type=&#34;image/webp&#34;/&gt;
      &lt;img src=&#34;https://chameth.com/sense-api/sense.jpg&#34; alt=&#34;A Sense unit and its two pillow sensors&#34; loading=&#34;lazy&#34; width=&#34;550&#34; height=&#34;400&#34;/&gt;
  &lt;/picture&gt;
  &lt;figcaption&gt;&lt;p&gt;A Sense unit and its two pillow sensors&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Sense is a little device that sits by your bedside and, in
conjunction with a little ‘pill’ attached to your pillow, monitors your sleeping patterns and
any environmental conditions that might hamper them. Android and iOS apps show you your sleep
history, and offer suggestions for improvements.&lt;/p&gt;
&lt;p&gt;Sense was &lt;a href=&#34;https://www.kickstarter.com/projects/hello/sense-know-more-sleep-better/description&#34;&gt;Kickstarted&lt;/a&gt;
in August 2014, raising over 2.4 million US dollars, and shipped to backers in mid 2015. The
campaign blurb included this snippet:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Building with Sense&lt;/p&gt;
&lt;p&gt;You’ll always have access to your data via our API. Take it, play with it, graph it, do whatever
you want with it. It’s yours. That’s important to us.&lt;/p&gt;
&lt;p&gt;We enjoy tinkering with and building on-top of other products we like. Sense will let you have
that experience.&lt;/p&gt;
&lt;p&gt;We’d love to hear your thoughts on what you might want to build with Sense, and how you could
directly interact with the hardware, and the data it collects.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Sounds great! But a year after shipping, there’s no sign of an API, and some of us who enjoy
tinkering are getting a bit restless…&lt;/p&gt;
&lt;!--more--&gt;
&lt;aside class=&#34;update raised-box&#34;&gt;
  &lt;h5 class=&#34;plain-header&#34;&gt;Update 2019-05-28:&lt;/h5&gt;
  &lt;p&gt;Hello, the company behind Sense, shut down in 2017 and took the Sense APIs with
it. The information below is no longer relevant. I’m not personally aware of
any way to interact with the Sense hardware directly.&lt;/p&gt;
&lt;/aside&gt;
&lt;h3 id=&#34;reverse-engineering-to-the-rescue&#34;&gt;Reverse engineering to the rescue&lt;/h3&gt;
&lt;p&gt;Data from the Sense hardware is transmitted off onto the Internet somewhere, and then pulled
down by the mobile apps. If we can snoop that traffic, we can probably figure out how to grab
the data from the Sense.&lt;/p&gt;
&lt;p&gt;So the first step is to capture the raw network traffic while the Sense and the app are in use. I
crafted an extremely over-the-top setup that involves my phone and the Sense being on a new,
separate wireless network that gateways through a Linux server that can look in on all the
traffic (because you never know when a dedicated capturing network will come in handy, right?…)&lt;/p&gt;
&lt;p&gt;Running &lt;code&gt;tshark&lt;/code&gt; while the app and device are active showed they were making HTTPS requests an
Amazon Elastic Cloud instance. That’s not really much use, as we can’t see the content of the
requests. The next step is to move up the network stack and target the HTTPS traffic specifically.
Step in, &lt;a href=&#34;https://mitmproxy.org/&#34;&gt;&lt;code&gt;mitmproxy&lt;/code&gt;&lt;/a&gt;. This automates man-in-the-middle attacks
on HTTPS requests. When it receives such a request, it cooks up its own certificate and sends that
to the client, and then sits in between while the client and the server communicate.&lt;/p&gt;
&lt;p&gt;The certificates generated by &lt;code&gt;mitmproxy&lt;/code&gt; aren’t issued by a trusted source, so (well behaved)
browsers and apps will throw up lots of warnings and refuse to communicate with it for the most
part. This is the mechanism that stops anyone impersonating your banking website when you access it
over HTTPS, so is generally a very good thing. In this case, both the Sense itself and the Android
app refused to talk with the blatant attacker.&lt;/p&gt;
&lt;p&gt;We control the Android phone, though, so can just tell it that we trust the dodgy certificate
issuer. This involves grabbing the certificate generated by mitmproxy, and adding it to Android’s
key store. The process is &lt;a href=&#34;http://docs.mitmproxy.org/en/stable/certinstall.html#installing-the-mitmproxy-ca-certificate-manually&#34;&gt;documented nicely in the mitmproxy docs&lt;/a&gt;
and is pretty straightforward. With Android trusting our certificate authority, the Sense app
starts talking through the proxy and we can look at the plain HTTP requests.&lt;/p&gt;
&lt;h3 id=&#34;the-api&#34;&gt;The API&lt;/h3&gt;
&lt;p&gt;Logging in to the Android app and navigating through the various screens shows that the API is
actually pretty nice. It’s RESTful, and uses an OAuth bearer token for authorisation, as you can
see in the &lt;code&gt;mitmproxy&lt;/code&gt; output of the authentication and first few requests:&lt;/p&gt;
&lt;pre class=&#34;chroma-chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;POST https://api.hello.is/v1/oauth2/token
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    ← 200 application/json 151B 1.17s
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;GET https://api.hello.is/v2/account/preferences
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    ← 200 application/json 124B 109ms
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;GET https://api.hello.is/v1/account
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    ← 200 application/json 181B 388ms
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;GET https://api.hello.is/v2/devices
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    ← 200 application/json 235B 126ms
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;POST https://api.hello.is/v1/app/checkin
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    ← 200 application/json 106B 119ms
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;GET https://api.hello.is/v2/insights
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    ← 200 application/json 1.4kB 157ms
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;POST https://api.hello.is/v1/notifications/registration
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    ← 204 [no content] 364ms
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;GET https://api.hello.is/v2/timeline/2016-04-09
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    ← 200 application/json 160B 550ms
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;GET https://api.hello.is/v1/questions?date=2016-04-10
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    ← 200 application/json 284B 132ms
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;PATCH https://api.hello.is/v1/app/stats
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    ← 202 [no content] 126ms
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;GET https://api.hello.is/v1/app/stats/unread
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    ← 200 application/json 71B 171ms
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;authorisation&#34;&gt;Authorisation&lt;/h4&gt;
&lt;p&gt;To get a bearer token, you send a POST request to &lt;code&gt;/v1/oauth2/token&lt;/code&gt;, supplying the username and
password, and a client ID and secret. Presumably if the API is ever opened up you’ll be able to
register clients and get your own ID and secret, but for now reusing the ones from the Android
app works fine. [I’ve prettified and linewrapped the content to make it a bit easier to read.]&lt;/p&gt;
&lt;pre class=&#34;chroma-chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-nf&#34;&gt;POST&lt;/span&gt; &lt;span class=&#34;chroma-nn&#34;&gt;/v1/oauth2/token&lt;/span&gt; &lt;span class=&#34;chroma-kr&#34;&gt;HTTP&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;chroma-m&#34;&gt;1.1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-n&#34;&gt;Host&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-l&#34;&gt;api.hello.is&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-n&#34;&gt;Accept&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-l&#34;&gt;*/*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-n&#34;&gt;Content-Length&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-l&#34;&gt;123&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-n&#34;&gt;Content-Type&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-l&#34;&gt;application/x-www-form-urlencoded&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;grant_type=password
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt; &amp;amp;client_id=8d3c1664-05ae-47e4-bcdb-477489590aa4
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt; &amp;amp;client_secret=4f771f6f-5c10-4104-bbc6-3333f5b11bf9
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt; &amp;amp;username=USERNAME
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt; &amp;amp;password=PASSWORD
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&#34;chroma-chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-kr&#34;&gt;HTTP&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;chroma-m&#34;&gt;1.1&lt;/span&gt; &lt;span class=&#34;chroma-m&#34;&gt;200&lt;/span&gt; &lt;span class=&#34;chroma-ne&#34;&gt;OK&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-n&#34;&gt;Cache-Control&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-l&#34;&gt;no-cache&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-n&#34;&gt;Content-Type&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-l&#34;&gt;application/json&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-n&#34;&gt;Date&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-l&#34;&gt;Sun, 10 Apr 2016 17:25:16 GMT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-n&#34;&gt;transfer-encoding&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-l&#34;&gt;chunked&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-n&#34;&gt;Connection&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-l&#34;&gt;keep-alive&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;  &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;token_type&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;Bearer&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;  &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;expires_in&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-mi&#34;&gt;31536000&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;  &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;account_id&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;1234&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;  &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;access_token&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;2.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;  &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;refresh_token&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;2.yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;sleep-timeline&#34;&gt;Sleep timeline&lt;/h4&gt;
&lt;p&gt;Getting the timeline for one night is just a straight up GET request. It gives a detailed log of
events, including different ‘depths’ of sleep (I’ve cut out a whole bunch here for simplicity).
It also shows metrics relating to the entire night, and their condition (‘warning’ or ‘ideal’).&lt;/p&gt;
&lt;pre class=&#34;chroma-chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-nf&#34;&gt;GET&lt;/span&gt; &lt;span class=&#34;chroma-nn&#34;&gt;/v2/timeline/2016-04-08&lt;/span&gt; &lt;span class=&#34;chroma-kr&#34;&gt;HTTP&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;chroma-m&#34;&gt;1.1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-n&#34;&gt;Host&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-l&#34;&gt;api.hello.is&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-n&#34;&gt;Accept&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-l&#34;&gt;*/*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-n&#34;&gt;Authorization&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-l&#34;&gt;Bearer 2.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&#34;chroma-chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-kr&#34;&gt;HTTP&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;chroma-m&#34;&gt;1.1&lt;/span&gt; &lt;span class=&#34;chroma-m&#34;&gt;200&lt;/span&gt; &lt;span class=&#34;chroma-ne&#34;&gt;OK&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-n&#34;&gt;Cache-Control&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-l&#34;&gt;no-cache&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-n&#34;&gt;Content-Type&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-l&#34;&gt;application/json&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-n&#34;&gt;Date&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-l&#34;&gt;Sun, 10 Apr 2016 17:29:00 GMT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-n&#34;&gt;transfer-encoding&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-l&#34;&gt;chunked&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-n&#34;&gt;Connection&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-l&#34;&gt;keep-alive&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;  &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;score&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-mi&#34;&gt;76&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;  &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;score_condition&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;WARNING&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;  &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;message&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;You were asleep for **8.2 hours**, and sleeping soundly for 3.2 hours.&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;  &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;date&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;2016-04-08&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;  &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;events&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    &lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;      &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;timestamp&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-mi&#34;&gt;1460168700000&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;      &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;timezone_offset&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-mi&#34;&gt;3600000&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;      &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;duration_millis&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-mi&#34;&gt;60000&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;      &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;message&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;You went to bed.&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;      &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;sleep_depth&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;      &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;sleep_state&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;AWAKE&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;      &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;event_type&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;GOT_IN_BED&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;      &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;valid_actions&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:[&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;ADJUST_TIME&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;VERIFY&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;INCORRECT&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    &lt;span class=&#34;chroma-p&#34;&gt;},{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;      &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;timestamp&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-mi&#34;&gt;1460169600000&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;      &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;timezone_offset&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-mi&#34;&gt;3600000&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;      &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;duration_millis&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-mi&#34;&gt;60000&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;      &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;message&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;You fell asleep.&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;      &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;sleep_depth&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-mi&#34;&gt;100&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;      &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;sleep_state&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;SOUND&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;      &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;event_type&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;FELL_ASLEEP&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;      &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;valid_actions&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:[&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;ADJUST_TIME&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;VERIFY&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;INCORRECT&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    &lt;span class=&#34;chroma-p&#34;&gt;},{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;      &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;timestamp&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-mi&#34;&gt;1460177040000&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;      &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;timezone_offset&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-mi&#34;&gt;3600000&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;      &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;duration_millis&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-mi&#34;&gt;60000&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;      &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;message&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;You were moving around quite a bit.&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;      &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;sleep_depth&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;      &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;sleep_state&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;AWAKE&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;      &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;event_type&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;GENERIC_MOTION&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;      &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;valid_actions&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:[&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;VERIFY&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;INCORRECT&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    &lt;span class=&#34;chroma-p&#34;&gt;},{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;      &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;timestamp&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-mi&#34;&gt;1460199000000&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;      &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;timezone_offset&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-mi&#34;&gt;3600000&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;      &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;duration_millis&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-mi&#34;&gt;60000&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;      &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;message&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;Good morning.&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;      &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;sleep_depth&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;      &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;sleep_state&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;AWAKE&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;      &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;event_type&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;WOKE_UP&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;      &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;valid_actions&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:[&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;ADJUST_TIME&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;VERIFY&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;INCORRECT&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    &lt;span class=&#34;chroma-p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;  &lt;span class=&#34;chroma-p&#34;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;  &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;metrics&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    &lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;total_sleep&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-mi&#34;&gt;490&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;unit&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;MINUTES&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;condition&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;IDEAL&amp;#34;&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    &lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;sound_sleep&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-mi&#34;&gt;190&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;unit&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;MINUTES&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;condition&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;IDEAL&amp;#34;&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    &lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;time_to_sleep&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-mi&#34;&gt;15&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;unit&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;MINUTES&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;condition&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;IDEAL&amp;#34;&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    &lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;times_awake&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;unit&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;QUANTITY&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;condition&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;IDEAL&amp;#34;&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    &lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;fell_asleep&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-mi&#34;&gt;1460169600000&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;unit&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;TIMESTAMP&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;condition&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;IDEAL&amp;#34;&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    &lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;woke_up&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-mi&#34;&gt;1460199000000&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;unit&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;TIMESTAMP&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;condition&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;IDEAL&amp;#34;&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    &lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;temperature&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-kc&#34;&gt;null&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;unit&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;CONDITION&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;condition&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;IDEAL&amp;#34;&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    &lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;humidity&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-kc&#34;&gt;null&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;unit&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;CONDITION&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;condition&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;IDEAL&amp;#34;&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    &lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;particulates&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-kc&#34;&gt;null&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;unit&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;CONDITION&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;condition&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;WARNING&amp;#34;&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    &lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;light&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-kc&#34;&gt;null&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;unit&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;CONDITION&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;condition&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;IDEAL&amp;#34;&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;    &lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;sound&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-kc&#34;&gt;null&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;unit&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;CONDITION&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;condition&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;IDEAL&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;  &lt;span class=&#34;chroma-p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;other-interesting-resources&#34;&gt;Other interesting resources&lt;/h4&gt;
&lt;p&gt;Pretty much everything displayed in the app is available as a REST resource. They clearly
put some thought into API design, which makes it even more of a shame that they haven’t made it
public yet. Some of the other interesting resources are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/v1/alarms&lt;/code&gt;: the alarms set on the Sense.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/v1/room/current?temp_unit=c&lt;/code&gt;: gives the latest environmental readouts from the Sense.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/v1/room/all_sensors/hours?quantity=2&amp;amp;from_utc=&amp;lt;timestamp&amp;gt;&lt;/code&gt;: sensor history.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/v2/devices&lt;/code&gt;: the paired devices, including battery status of pills.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/v2/insights&lt;/code&gt;: JSON representation of the cards displayed on the main screen (recommendations,
analysis, etc).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/v2/trends/LAST_WEEK&lt;/code&gt; (or &lt;code&gt;MONTH&lt;/code&gt; or &lt;code&gt;3_MONTHS&lt;/code&gt;): gives graph data for sleep scores, duration
and depths.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now the API is figured out, all that’s left is to build something that uses it…&lt;/p&gt;
</content>
    </entry>
</feed>
