<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Alex Silcock]]></title><description><![CDATA[Writing about various technology subjects, with a focus on home automation and software development.]]></description><link>http://www.alexsilcock.net/notes/</link><generator>Ghost 0.9</generator><lastBuildDate>Wed, 18 Sep 2024 20:57:39 GMT</lastBuildDate><atom:link href="http://www.alexsilcock.net/notes/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Protecting Home Assistant with Cloudflare Access and mTLS on Android]]></title><description><![CDATA[How to set up client TLS (mTLS) with Cloudflare Access to provide extra security for Home Assistant in the browser and in the Android app.]]></description><link>http://www.alexsilcock.net/notes/protecting-home-assistant-with-cloudflare-access-and-mtls/</link><guid isPermaLink="false">a24fed62-ed05-4eb1-82d2-3779b7dd1253</guid><category><![CDATA[home-assistant]]></category><category><![CDATA[home-automation]]></category><dc:creator><![CDATA[Alex Silcock]]></dc:creator><pubDate>Sun, 27 Nov 2022 13:10:00 GMT</pubDate><content:encoded><![CDATA[<p><em>Updated September 2024: Added step installing Cloudflare CA cert to avoid client cert installation issues</em></p>

<p>TL;DR: Skip to "Setting up mTLS with Cloudflare and Android" for the high level instructions.</p>

<hr>

<p>There are many different ways to set up Home Assistant so that it is accessible when you're away from home, which have various pros and cons, but I had some extra requirements beyond just securing it with HTTPS/TLS which I haven't found any articles about (in bold):</p>

<ol>
<li>Does not expose my home IP address  </li>
<li><strong>Does not publicly expose my Home Assistant instance (i.e. no publicly-accessible login form)</strong>  </li>
<li>Secured using TLS/SSL  </li>
<li>Accessible from any device  </li>
<li><strong>Works with the Home Assistant Android native app</strong>  </li>
<li><strong>Does not require running a network client "tool" on my phone (e.g. VPN client, Cloudflare WARP client)</strong>  </li>
<li>Ideally doesn't require a paid subscription to something  </li>
<li>Can support Google Assistant integration in future</li>
</ol>

<p>This blog post, as with most of my posts, serves as a combination of a reminder to my future self on how I got it working, and hopefully also a useful resource for others. As such, this post will be rough-around-the-edges in places.</p>

<p>Things this blog post doesn't cover:</p>

<ul>
<li>Setting up Cloudflare with your domain</li>
<li>Setting up Cloudflare Tunnel</li>
<li>Configuring Home Assistant to accept reverse-proxied traffic through Cloudflare Tunnel (see Home Assistant docs)</li>
</ul>

<h1 id="waysofexposinghomeassistant">Ways of exposing Home Assistant</h1>

<p>Some different ways of setting up Home Assistant so that it's accessible publicly:</p>

<ul>
<li>Paying for Home Assistant Cloud
<ul><li>Pro: easiest, supports the maintainers</li>
<li>Con: subscription service, leaves your HA instance exposed to the internet</li>
<li>Satisfies requirements 1-6, 8 (I think)</li></ul></li>
<li>Forwarding a port on your home router
<ul><li>Pro: easy to set up</li>
<li>Con: exposing your home IP, and has potential risks from security holes in Home Assistant</li>
<li>Satisfies requirements 3-8</li></ul></li>
<li>Using a VPN (incl. Tailscale) to connect back into your home network
<ul><li>Pro: secure, no attack surface for your home server</li>
<li>Con: you have to install the VPN client wherever you want to use it, and connect/disconnect when needed</li>
<li>Satisfies requirements 1-5, 7</li></ul></li>
<li>Hiding your Home Assistant instance behind Cloudflare, using a Cloudflare Tunnel to connect <em>outbound</em> from your home network to Cloudflare.
<ul><li>Pro: secure, no direct route of attack to your home server</li>
<li>Con: has potential risks from security holes in Home Assistant</li>
<li>Satisfies requirements 1, 3-8</li></ul></li>
</ul>

<p>Requirement 2 (does not publicly expose my Home Assistant instance to the internet) can be mitigated when using Cloudflare by using Cloudflare Access to require visitors to log in (e.g. via Google, Okta, one-time PIN via email) before they even get to your Home Assistant login form. This is great from a security standpoint, but it does cause issues with the Android app.</p>

<h1 id="cloudflareaccessandtheandroidapp">Cloudflare Access and the Android app</h1>

<p>If you set up Cloudflare Access so that it prompts the user to log in via either an OTP sent via email, or via another identity provider before exposing your Home Assistant login form, this breaks compatibility with the Android app. This is because when you access your Home Assistant domain, e.g. <code>ha.mydomain.co.uk</code>, you will be redirected to your identity provider domain before you get to see your Home Assistant login form (e.g. <code>myname.cloudflareaccess.com</code>). This redirect takes you out of the Home Assistant app and into your browser, and so once you've logged into your identity provider, the Android app never receives the auth token generated as part of the final login step, which it needs to be able to communicate with Home Assistant. As such, we need to find another way of authenticating the Android app which does not require redirecting to another domain.</p>

<p>There have been <a href="https://github.com/home-assistant/android/issues/2650">issues raised on GitHub</a> about this exact issue, but there is no solution for the redirect problem at present.</p>

<h1 id="justgettothepoint">Just get to the point</h1>

<p>What <em>does</em> seem to work is having two subdomains, which both back off to the same Home Assistant instance, one which is for use in a browser, and one which is for use from the Android app.</p>

<ul>
<li><code>ha.mydomain.co.uk</code> - for use from a browser
<ul><li>Uses Cloudflare Access to enforce login via an identity provider</li>
<li>Accessible from anywhere, as long as you can log into your identity provider</li></ul></li>
<li><code>ha-android.mydomain.co.uk</code> - for use from the Android app
<ul><li>Uses mTLS (mutual TLS) to require the Android app to present a client TLS certificate to Cloudflare</li>
<li>Requires manual setup on each Android device, but only once</li></ul></li>
</ul>

<p>You will need two separate Cloudflare Tunnels, one for each domain, both of which should back off to the same origin URL.</p>

<p>I've seen a number of other guides/tutorials online describing how to set up Cloudflare Access, but I haven't seen much explaining how to set up mTLS with Cloudflare, so that's what I'll do next.</p>

<h1 id="settingupmtlswithcloudflareandandroid">Setting up mTLS with Cloudflare and Android</h1>

<p>Tl;dr this is how I did it:</p>

<ol>
<li>Remove Cloudflare Access rules for your <code>ha-android</code> domain <br>
<ul><li>Cloudflare Access rules will prompt the user to log in, which we don't want</li></ul></li>
<li>Generate a client certificate in Cloudflare <br>
<ol><li>Use the "SSL/TLS" pane of Cloudflare to generate and download a client certificate and secret (or generate it yourself offline). Store the certificate as <code>cf.pem</code> and the private key as <code>cf.key</code></li>
<li>Convert these two files into a <code>pfx</code> file, which is importable in Android, using the following command (<a href="https://community.cloudflare.com/t/tls-client-certificate-for-android/316440">source</a>):
<code>
openssl pkcs12 -export -out cf.pfx -inkey cf.key -in cf.pem <br>
</code></li>
<li>Securely transfer this file to your Android phone</li></ol></li>
<li>Download and install Cloudflare CA cert on Android device <br>
<ol><li>See guide <a href="https://developers.cloudflare.com/cloudflare-one/connections/connect-devices/warp/user-side-certificates/install-cloudflare-cert/#download-the-cloudflare-root-certificate">on Cloudflare's site</a>. This seems to be required to install the client cert.</li></ol></li>
<li>Install client certificate into Android cert store <br>
<ol><li>Go to Settings > Security > Credential Storage, tap Install from storage, then locate the file you transferred from step 2.</li>
<li>Give the certificate a sensible name so that future-you remembers what it is</li></ol></li>
<li>Create an mTLS rule in Cloudflare WAF to block non-certificate-holders <br>
<ol><li>From the "SSL/TLS" pane in Cloudflare, click "Client certificates", then click the "Create mTLS rule" button. If this isn't visible in Cloudflare, it's because they've moved it to the API Shield section which they are warning about right now ('Nov 2022)</li></ol></li>
<li>Configure Home Assistant app to use cert <br>
<ol><li>Change the "External URL" in your app settings to use your <code>ha-android</code> domain, then restart the app. You should be prompted to select a client certificate on next start.</li></ol></li>
</ol>

<p>That's it. You now have a domain for browser use, and a domain which works in the Android app, without having to start any other VPN apps first.</p>

<h1 id="references">References</h1>

<p>Some posts I found useful while setting this up:</p>

<ul>
<li><a href="https://empty.coffee/home-assistant-cloudflare-zero-trust-setup/">https://empty.coffee/home-assistant-cloudflare-zero-trust-setup/</a> - looking back, this blog post is a much more nicely written version of a significant portion of what I wrote!</li>
</ul>]]></content:encoded></item><item><title><![CDATA[Normalising podcast volumes on macOS]]></title><description><![CDATA[<p>A very quick write-up of a solution I've found to a quite specific problem. I hope it's of use to somebody (or even just me in the future).</p>

<p><strong>Problem</strong>: some podcasts that I like to listen to vary considerably in volume throughout, which means I have to keep adjusting the</p>]]></description><link>http://www.alexsilcock.net/notes/normalising-podcast-volumes-on-macos/</link><guid isPermaLink="false">90b938ae-8f91-442e-97d5-da5ea74a3f05</guid><dc:creator><![CDATA[Alex Silcock]]></dc:creator><pubDate>Mon, 19 Sep 2022 18:09:40 GMT</pubDate><content:encoded><![CDATA[<p>A very quick write-up of a solution I've found to a quite specific problem. I hope it's of use to somebody (or even just me in the future).</p>

<p><strong>Problem</strong>: some podcasts that I like to listen to vary considerably in volume throughout, which means I have to keep adjusting the volume in loud environments, such as when cooking. I wanted to avoid having having to do this when listening to podcasts on my laptop.</p>

<p>Requirements:</p>

<ul>
<li>No change to music player required (I want to keep using Spotify)</li>
<li>No work required ahead of time to prepare each podcast episode</li>
<li>Simple to enable/disable</li>
</ul>

<p><strong>General solution technique</strong>: Employ <a href="https://en.wikipedia.org/wiki/Dynamic_range_compression">dynamic range compression</a> to reduce the volume of the loud parts of the podcast, so that they're closer to the quiet parts, meaning no manual volume adjustment is necessary. This seemed easier to do than trying to control my laptop volume in sync with the podcast.</p>

<p><strong>Specific solution</strong>: run all of my laptop audio output through a software dynamic range compression filter before it goes to the speakers. This means all application audio output is covered which makes it easy to use with Spotify.</p>

<p>This is how I did it on macOS Monterey.</p>

<p><strong>Side note</strong>: This will make music sound <em>awful</em> and remove any punchiness from it (which is already slowly happening across the music industry anyway - see <a href="https://en.wikipedia.org/wiki/Loudness_war">Loudness war</a>), but for spoken word, it does what I wanted it to do. The end result will make podcasts sound more like radio programmes in terms of having consistent volume.</p>

<ol>
<li>Install <a href="https://github.com/ExistentialAudio/BlackHole#option-2-install-via-homebrew">Blackhole</a>, a free audio loopback driver. This presents an extra input and output device to the system. I used to use Soundflower for this but it hasn't been maintained for a while and has some issues.  </li>
<li>Install <a href="https://www.apple.com/apple-music/apple-digital-masters/">Apple AU Lab</a> (link at bottom of page), a free audio mixer allowing you to route audio through various effects processing units, a number of which are included with macOS.  </li>
<li>On recent versions of macOS, you need to grant microphone permissions to AU Lab so it can receive audio from BlackHole. Most applications prompt you, but AU Lab doesn't for some reason. Run this command to grant the permission (<a href="https://github.com/ExistentialAudio/BlackHole/issues/4#issuecomment-1166148773">source</a>): <br>
<code>
sqlite3 ~/Library/Application\ Support/com.apple.TCC/TCC.db "INSERT INTO access VALUES('kTCCServiceMicrophone','com.apple.audio.aulab',0,2,2,1,NULL,NULL,NULL,'UNUSED',NULL,0, CAST(strftime('%s','now') AS INTEGER)) ;" <br>
</code></li>
<li>Set your system output audio device to BlackHole. This captures audio from all applications (excepting those which are configured to output to a specific other device) - including Spotify, in my case. <em>Note</em>: you will no longer hear any sound until the next step, as it's no longer being routed to your speakers.  </li>
<li>Create a new document in AU Lab, using the "Stereo In/Stereo Out" template. Specify BlackHole as the input source, and your chosen speaker as your output device (for me, a Bluetooth speaker). You should now be able to hear application audio again, as the audio from the BlackHole input is now being routed to your output speaker.  </li>
<li>In the "Audio 1" column, under the "Effects" section, choose "AUDynamicsProcessor" from the drop-down menu to add a dynamic compressor.  </li>
<li>In the popup window for the AUDynamicsProcessor, set the parameters like so: <br>
<ul><li>Compression threshold (centre dot): -50 dB </li>
<li>Headroom (right-hand side dot): only just above the compression threshold dot. ~9 dB</li></ul></li>
<li>Expand the "Details" section and set the following parameters: <br>
<ul><li>Attack time: 0.002</li>
<li>Master Gain: ~11 dB (to amplify the output signal, as the compression makes it significantly quieter)</li></ul></li>
<li>Done</li>
</ol>]]></content:encoded></item><item><title><![CDATA[Migrating Home Assistant from sqlite3 to MySQL 8.0]]></title><description><![CDATA[<p>This post quickly documents some notes around my process of migrating Home Assistant's sqlite3 database to a containerised MySQL database.</p>

<p>I run all of my home server infrastructure in Docker containers as I like the isolation and distribution model that they provide.</p>

<p>The default sqlite3 database used by Home Assistant</p>]]></description><link>http://www.alexsilcock.net/notes/migrating-home-assistant-from-sqlite3-to-mysql-8-0/</link><guid isPermaLink="false">6739c57d-ab46-4ee7-902b-69f9d35683cb</guid><category><![CDATA[home-assistant]]></category><category><![CDATA[home-automation]]></category><dc:creator><![CDATA[Alex Silcock]]></dc:creator><pubDate>Sun, 10 Nov 2019 05:09:12 GMT</pubDate><content:encoded><![CDATA[<p>This post quickly documents some notes around my process of migrating Home Assistant's sqlite3 database to a containerised MySQL database.</p>

<p>I run all of my home server infrastructure in Docker containers as I like the isolation and distribution model that they provide.</p>

<p>The default sqlite3 database used by Home Assistant does not scale well to storing a large number of events and state changes, which makes using the History or Logbook panes of the Home Assistant interface slow to use. MySQL performs significantly better at this, at the expense of having to run a separate Docker container to handle the database.</p>

<h1 id="migrationprocess">Migration process</h1>

<p>The overall process for migrating from the default sqlite3 database to a MySQL looks like the following:</p>

<ol>
<li>Start a containerised instance of MySQL 8.0  </li>
<li>Stop Home Assistant  </li>
<li>Configure HA to point at the containerised MySQL instance  </li>
<li>Start HA, allow it to create its database schema, then stop it again  </li>
<li>Truncate all tables in the MySQL database  </li>
<li>Dump sqlite3 database into an SQL file  </li>
<li>Transform the SQL file from sqlite3-flavour to MySQL-flavour  </li>
<li>Import the SQL file into MySQL  </li>
<li>Start HA</li>
</ol>

<p>Largely following this guide: <a href="https://gist.github.com/seidler2547/93012edf3c7a2414ec1d9a8ebbc9c1a6">https://gist.github.com/seidler2547/93012edf3c7a2414ec1d9a8ebbc9c1a6</a></p>

<p>Below are my "notable points" relating to steps in the above process.</p>

<h2 id="1startacontainerisedinstanceofmysql80">1. Start a containerised instance of MySQL 8.0</h2>

<p>There are a choice of Docker images available - <code>mysql:8.0</code> and <code>mysql/mysql-server:8.0</code>. The difference is apparently that the image with the longer name is an Oracle fork of the "official" <code>mysql</code> image, which uses Red Hat as the base image. The "official" image uses Debian as the base.</p>

<p>In practice, I found that when I tried to run the Oracle-maintained image, it didn't handle being run with a different uid/gid well (didn't have permission to write temporary files). The "official" <code>mysql</code> image didn't have this problem.</p>

<h2 id="4starthatoallowittocreatedatabaseschema">4. Start HA to allow it to create database schema</h2>

<p>Home Assistant wouldn't connect to MySQL on startup, and it threw an error into the logs containing the following line:</p>

<pre><code>Plugin caching_sha2_password could not be loaded: Error loading shared library lib/mariadb/plugin/caching_sha2_password.so: No such file or directory  
</code></pre>

<p>This led me to a <a href="https://community.home-assistant.io/t/external-lan-mysql-db-for-recorder-plugin-caching-sha2-password-could-not-be-loaded/68292">post on the Home Assistant forum</a>, which pointed me in the right direction. MySQL 8.0 changed the default authentication method to one which is more secure, and as part of the MySQL protocol client-server handshake, the server tells the client which auth method to use. The version of SQLAlchemy ORM used in Home Assistant doesn't yet support the new <code>caching_sha2_password</code> plugin, so the easiest solution is to modify the MySQL server settings to default to using the previous <code>mysql_native_password</code> method, which Home Assistant does support.</p>

<p>This can be done by modifying the MySQL container start command to include the <code>--default-authentication-plugin=mysql_native_password</code> flag.</p>

<h2 id="78transformsqlfilefromsqlite3formatandimportintomysql">7+8. Transform SQL file from sqlite3 format and import into MySQL</h2>

<p>As I didn't have any sqlite tooling installed locally on my server, I used a Docker image containing <code>sqlite</code> to dump the database contents as SQL.</p>

<p>Importing this into MySQL involved transforming the SQL format first, and with a couple of small modifications to the gigantic shell command included in the guide linked above, I was able to do this in one go:</p>

<pre><code># not shown: cd into home assistant directory
docker run --rm -it -v $(pwd):/db keinos/sqlite3 sqlite3 /db/home-assistant_v2.db .dump | \  
    sed -re 's/^PRAGMA .+OFF/SET FOREIGN_KEY_CHECKS=0;SET UNIQUE_CHECKS=0/' \
        -e 's/^CREATE INDEX .+//' \
        -e 's/^BEGIN TRANSACTION;\r$/SET autocommit=0;BEGIN;/' \
        -e '/CREATE TABLE/,/\);/ d' \
        -e 's/^INSERT INTO "([^"]+)"/INSERT INTO \1/' \
        -e 's/\\n/\n/g' | \
    perl -pe 'binmode STDOUT, ":utf8";s/\\u([0-9A-Fa-f]{4})/pack"U*",hex($1)/ge' | \
    docker exec -i &lt;MYSQLCONTAINERID&gt; mysql --default-character-set=utf8 -u hass -p&lt;YOURMYSQLPASSWORD&gt; homeassistant
</code></pre>

<p>This command took about 30 minutes to run, but completed the full migration from a SQLite file to a MySQL database.</p>]]></content:encoded></item><item><title><![CDATA[Making a bootable Windows 10 installer USB stick on OS X]]></title><description><![CDATA[<p>Trying to create a Windows 10 USB stick installer using an official Microsoft ISO on Mac OS X 10.11.6 seems to be hard work.</p>

<p><strong>tl;dr: Using <a href="https://rufus.akeo.ie/">Rufus</a> inside a Windows XP VM works</strong></p>

<p>I happened to have one lying around, and passing the USB stick device through</p>]]></description><link>http://www.alexsilcock.net/notes/making-a-bootable-windows-10-installer-usb-stick-from-os-x/</link><guid isPermaLink="false">23f4eb3c-a11e-4c9f-9fe1-1b0131a422d7</guid><dc:creator><![CDATA[Alex Silcock]]></dc:creator><pubDate>Tue, 05 Dec 2017 14:54:53 GMT</pubDate><content:encoded><![CDATA[<p>Trying to create a Windows 10 USB stick installer using an official Microsoft ISO on Mac OS X 10.11.6 seems to be hard work.</p>

<p><strong>tl;dr: Using <a href="https://rufus.akeo.ie/">Rufus</a> inside a Windows XP VM works</strong></p>

<p>I happened to have one lying around, and passing the USB stick device through to the XP VM worked perfectly.</p>

<p>Methods that don't work:</p>

<ul>
<li>sudo dd if=win10.iso of=/dev/rdisk3s1 bs=1m</li>
<li>unetbootin (the USB stick boots, but Windows 10 isn't an option in the list)</li>
</ul>]]></content:encoded></item><item><title><![CDATA[Initial experiments with ReSpeaker]]></title><description><![CDATA[<p>Last year I backed a Kickstarter project called <a href="https://www.kickstarter.com/projects/seeed/respeaker-an-open-modular-voice-interface-to-hack">ReSpeaker</a>, which is a (Linux-based) hardware module designed to make it as easy as possible to add speech recognition to projects. The main selling point for me is that a "far-field" microphone array is available for it, which allows far better isolation</p>]]></description><link>http://www.alexsilcock.net/notes/initial-experiments-with-respeaker/</link><guid isPermaLink="false">7875eebe-f967-4bd1-b1b6-f44bbe119b20</guid><category><![CDATA[home-automation]]></category><dc:creator><![CDATA[Alex Silcock]]></dc:creator><pubDate>Sun, 29 Jan 2017 02:50:00 GMT</pubDate><content:encoded><![CDATA[<p>Last year I backed a Kickstarter project called <a href="https://www.kickstarter.com/projects/seeed/respeaker-an-open-modular-voice-interface-to-hack">ReSpeaker</a>, which is a (Linux-based) hardware module designed to make it as easy as possible to add speech recognition to projects. The main selling point for me is that a "far-field" microphone array is available for it, which allows far better isolation of audio sources and enables recognition over greater distances, which is ideal for speech recognition applications - my ReSpeaker is going to be an interface to my home automation system. <br>
I won't go into detail about the ReSpeaker itself, as it's well documented elsewhere online. This post is mainly to document some less-obvious things I encountered when setting it up.</p>

<h1 id="wherearetheintrodocs">Where are the intro docs?</h1>

<p>Some docs are located <a href="https://github.com/respeaker/get_started_with_respeaker">here</a>. There are a number of interesting/useful repos in the same GitHub organisation.</p>

<h1 id="connectingtowifi">Connecting to Wi-Fi</h1>

<p>Initially the ReSpeaker broadcasts its own wireless network. After connecting to this, visit <a href="http://192.168.100.1/home.html">http://192.168.100.1/home.html</a> to access the main ReSpeaker menu, which contains an option to connect the ReSpeaker to a wireless network of your choice.</p>

<p>There's also an installation of JUCI running at <a href="http://192.168.100.1/#!/overview">http://192.168.100.1/#!/overview</a>, which is a web interface to most of OpenWRT's configuration (since ReSpeaker's Linux core is based on OpenWRT).</p>

<h2 id="sidenoteaboutnetworking">Side note about networking</h2>

<p>The ReSpeaker can act in station and access point mode simultaneously; it uses a bridge with an IP of <code>192.168.100.1</code> to bridge the station interface (WAN) of <code>apcli0</code> (also listed as <code>ra0</code>) with <code>eth0.1</code> (LAN):</p>

<pre><code>root@ReSpeaker:~# brctl show  
bridge name   bridge id           STP enabled   interfaces  
br-lan        7fff.9c65f91dc3cf   no            eth0.1  
                                                ra0
</code></pre>

<p>If you set up a route on your PC manually, you can access 192.168.100.1 when connected to your normal wireless network. The firewall is configured to allow WAN traffic into the LAN but not vice-versa.</p>

<p>The config files for this are in the standard OpenWRT location of <code>/etc/config/{firewall,network,wireless}</code>. Most of these settings are also editable through JUCI.</p>

<p>After connecting the ReSpeaker to your wireless network, you can disable the ReSpeaker's own access point by going to JUCI, then <code>Wifi =&gt; Interfaces =&gt; ReSpeakerXXXXXX @</code>, and turning off "Enabled".</p>

<h1 id="accessingtherespeakerconsole">Accessing the ReSpeaker console</h1>

<p>If you mess up your networking somehow and can't access its web UI, you can access a shell through an emulated serial console to fix it when connected over USB. Example command to connect:</p>

<p><code>screen /dev/tty.usbmodem1411 57600</code></p>

<h1 id="runningcodesamples">Running code samples</h1>

<p>I wanted to play with the LEDs, but out of the box the music player Mopidy has exclusive claim to their usage (presumably to support the intro "Hi, ReSpeaker" demo) - attempting to use them within Python will give you a "resource busy" error. Stop Mopidy running with:</p>

<p><code>/etc/init.d/mopidy stop</code></p>

<p>Now you can use the LEDs as described in the <a href="https://github.com/respeaker/get_started_with_respeaker/blob/master/ProgrammingGuide.md#data-exchange-between-arduino-and-openwrt">Programming Guide</a>.</p>

<p>It may have just been because I was powering ReSpeaker from my laptop, but it doesn't seem to be able to supply enough power to the LEDs to run them at full power - the board browned out at around 80% of full power (setting them to colour 0xCCCCCC made it a bit unstable).</p>

<h1 id="miscusefulinfoivegleaned">Misc useful info I've gleaned</h1>

<p>The onboard Atmega32u4 is running <a href="https://github.com/respeaker/respeaker_arduino_library/blob/master/examples/pixels_pattern/pixels_pattern.ino">this code</a> by default.</p>]]></content:encoded></item><item><title><![CDATA[Java 8 on OS X El Capitan with command-line support]]></title><description><![CDATA[<p>Here's a quick tip if you want to install Java to be able to <em>run</em> Java apps from the command-line on OS X.</p>

<p>Intuitively, installing the JRE appears to be the obvious choice, as you're not bothered about <code>javac</code> or other developer tools. However, the JRE DMG package doesn't register</p>]]></description><link>http://www.alexsilcock.net/notes/java-8-on-os-x-el-capitan-with-command-line-support/</link><guid isPermaLink="false">ff51d557-2168-416f-b886-1c773aeaddde</guid><dc:creator><![CDATA[Alex Silcock]]></dc:creator><pubDate>Sun, 12 Jun 2016 15:47:26 GMT</pubDate><content:encoded><![CDATA[<p>Here's a quick tip if you want to install Java to be able to <em>run</em> Java apps from the command-line on OS X.</p>

<p>Intuitively, installing the JRE appears to be the obvious choice, as you're not bothered about <code>javac</code> or other developer tools. However, the JRE DMG package doesn't register itself as a full JVM, merely a "Internet Plug-In". It'll allow you to run GUI applications that use Java, but it will still result in a prompt to download a JVM if you run <code>java</code> from a terminal. This is because the JRE is installed into <code>/Library/Internet Plug-Ins/JavaAppletPlugin.plugin</code>, but <code>/usr/bin/java</code> only looks for JVMs in <code>/Library/Java/JavaVirtualMachines</code>.</p>

<p>Instead, download the Oracle JDK - this installs itself into <code>/Library/Java/JavaVirtualMachines</code> and therefore can be used from both the command-line and from GUI apps.</p>]]></content:encoded></item><item><title><![CDATA[Home automation with Arduino and 433Mhz plug-in receivers]]></title><description><![CDATA[<p>I've been in the process of building a networked home automation system for my lighting (and in the future, other devices) using off-the-shelf plug-in receivers for the last year or so. I've been meaning to write a blog post about it for some time, but in the meantime, here's a</p>]]></description><link>http://www.alexsilcock.net/notes/home-automation-with-arduino-and-433mhz-plug-in-receivers/</link><guid isPermaLink="false">8daa2d43-8b1c-430f-ae9b-a83edd97ab01</guid><category><![CDATA[home-automation]]></category><dc:creator><![CDATA[Alex Silcock]]></dc:creator><pubDate>Mon, 02 May 2016 01:23:27 GMT</pubDate><content:encoded><![CDATA[<p>I've been in the process of building a networked home automation system for my lighting (and in the future, other devices) using off-the-shelf plug-in receivers for the last year or so. I've been meaning to write a blog post about it for some time, but in the meantime, here's a collection of information that may be of use.</p>

<h1 id="controllingexistinglamps">Controlling existing lamps</h1>

<p>A range of 433Mhz plug-in remote controlled mains switches are available from various brands, which are able to either switch on/off a device with a standard UK plug, or dim it. Initially I used a set of Maplin switches, but later replaced them with Nexa units as they seemed more reliable (and the relays are quieter when switching). These can be controlled with a handheld remote, but the signal that it emits can be emulated using an Arduino and a 433Mhz radio transmitter.</p>

<p>Other people have done the hard work in reverse engineering the radio protocols, and others have written Arduino libraries to transmit the commands, but I've combined control of both Maplin and Nexa sockets into one Arduino sketch. <a href="https://github.com/ultrafez/switcherduino">switcherduino</a> is my Arduino firmware that can be used as a USB serial device to dim or turn on/off these devices.</p>

<h1 id="orchestrationsoftware">Orchestration software</h1>

<p>I use a simple Node.js-based webapp to act as an interface to the USB switcherduino, which maintains state about devices, allows associating devices into groups, executes pre-computed scenes, runs sequences on certain events (e.g. connecting to wifi), and provides an API to enable voice control (integrating with Tasker and AutoVoice for Android).</p>

<p>This is currently not open-source as the software is minimal and quite rough-around-the-edges, but there seems to be a range of other projects for this sort of thing such as <a href="http://www.domoticz.com">Domoticz</a>, <a href="https://www.home-assistant.io">Home Assistant</a>, <a href="http://www.openhab.org">OpenHAB</a> etc. I haven't tried any of them, but I've heard good things about Domoticz. Here's a <a href="https://www.reddit.com/r/homeautomation/comments/1uee1f/open_source_control_software_roundup">list of similar projects</a>.</p>

<h1 id="productsavailable">Products available</h1>

<p>Most of my sockets are these <a href="http://www.clasohlson.com/uk/Nexa-EYCR-250UK-Dimmable-Remote-Switch-Receiver/Pr182653000">Nexa EYCR-250 dimmable sockets</a>, which are part of the "System Nexa" range. Mine were bought at Clas Ohlson for the bargain price of £3.99 each.</p>

<p>Other sockets that I have or have used are the <a href="http://www.clasohlson.com/uk/Nexa-EYCR-2300UK-Remote-Switch-Receiver/Pr182652000">Nexa EYCR-2300 non-dimmable sockets</a> which are better suited for non-dimmable equipment (such as a Raspberry Pi), and <a href="http://www.maplin.co.uk/p/remote-controlled-mains-sockets-set-3-pack-n79ka">this set (N79KA)</a> from Maplin. The Maplin set has a less robust radio protocol and seems to have more trouble with interference and has a shorter range (in my experience).</p>

<h2 id="nexacompatibleproductsbrands">Nexa-compatible products/brands</h2>

<p>Some other brands are apparently compatible with Nexa's protocol. I'll list them here as I find out about them.</p>

<p>Apparently the Nexa switches are manufactured by Arctech, and so share the same protocol as a number of other brands, documented <a href="https://wiki.pilight.org/doku.php/arctech_switch">here at the PiLight wiki</a>.</p>

<table>  
<thead>  
<tr>  
<th>Brand</th>  
<th>Tested?</th>  
<th>More info</th>  
</tr>  
</thead>  
<tbody>  
<tr>  
<td><a href="http://www.homeeasy.eu">Home Easy</a></td><td>No</td><td rowspan="4"><a href="http://www.automatedhome.co.uk/reviews/homeeasy-wireless-home-automation-review.html">Blog post</a></td>  
</tr>  
<tr>  
<td><a href="http://www.chbyron.eu/">C H Byron / Smartwares Safety and Lighting</a></td><td>No</td>  
</tr>  
<tr>  
<td><a href="http://www.rshomeautomation.com">RS Home Automation</a></td><td>No</td>  
</tr>  
<tr>  
<td>Traditional Trading</td><td>No</td>  
</tr>  
<tr>  
<td>Chacon</td><td>No</td><td><a href="https://community.zipato.com/topic/please-add-some-chacon-products-under-nexa-brand-under-devices_2">Here</a></td>  
</tr>  
<tr>  
<td>KAKU</td><td>No</td><td><a href="https://forum.pilight.org/Thread-Nexa-Dimmer-arctech-switch">Discussion - same protocol?</a></td>  
</tr>  
</tbody>  
</table>

<h2 id="maplincompatibleproducts">Maplin-compatible products</h2>

<p><a href="https://github.com/sui77/rc-switch/wiki">This GitHub repo's wiki</a> has a good description of hardware using the same protocol.</p>]]></content:encoded></item><item><title><![CDATA[Installing KVM on Debian 8 (Jessie)]]></title><description><![CDATA[<p>I recently bought a HP MicroServer gen8, and part of my plan for it was to use it as a host for virtual machines. After some research, I chose to use KVM as my hypervisor as it would allow me to store the VM disk/mounts on a software RAID</p>]]></description><link>http://www.alexsilcock.net/notes/installing-kvm-on-debian-8/</link><guid isPermaLink="false">15d2fcca-330d-4e7e-add0-8350413828a8</guid><dc:creator><![CDATA[Alex Silcock]]></dc:creator><pubDate>Sun, 24 Apr 2016 23:09:03 GMT</pubDate><content:encoded><![CDATA[<p>I recently bought a HP MicroServer gen8, and part of my plan for it was to use it as a host for virtual machines. After some research, I chose to use KVM as my hypervisor as it would allow me to store the VM disk/mounts on a software RAID array, something that's not (easily) possible using VMware ESXi.</p>

<p>My setup tries to modify as little of the out-of-the-box Debian 8 configuration as possible. I enable public bridging so that all of my VMs are accessible from my wider LAN, but a private bridge could be added later.</p>

<h1 id="letsgo">Let's go</h1>

<p>Make yourself comfortable  </p>

<pre><code>sudo apt-get install tmux vim  
</code></pre>

<h2 id="installkvmandtools">Install KVM and tools</h2>

<p>Install KVM, CLI tools (including <code>virsh</code>) and <code>tunctl</code> utility (required for setting up <a href="http://www.linux-kvm.org/page/Networking#Public_Bridge">public bridging</a>):  </p>

<pre><code>sudo apt-get install qemu-kvm libvirt-bin uml-utilities  
sudo adduser &lt;user&gt; kvm  
sudo adduser &lt;user&gt; libvirt  
</code></pre>

<p>This should now work (no VMs listed):  </p>

<pre><code>virsh --connect qemu:///system list --all  
</code></pre>

<h2 id="setupbridgenetworking">Set up bridge networking</h2>

<p>Add a bridge adapter. This will wrap the existing <code>eth0</code> interface, which I'm using DHCP on (as I use address reservation on my home router to gain a "static" address). Debian 8 uses NetworkManager to configure networking, so in <code>/etc/network/interfaces</code> no adapters (besides loopback) will be listed.</p>

<p>Add the following to <code>/etc/networking/interfaces</code>:  </p>

<pre><code># Bridge for KVM
auto br0  
iface br0 inet dhcp  
    bridge_ports eth0
    bridge_stp off
    bridge_maxwait 0
    bridge_fd 0
</code></pre>

<p>NetworkManager will stop managing any devices listed in <code>/etc/networking/interfaces</code>.</p>

<p>Reboot to ensure network changes have taken effect (restarting networking using the init script wasn't enough):  </p>

<pre><code>sudo reboot  
</code></pre>

<p>You should now be able to see the network bridge containing eth0 (bridge id redacted):  </p>

<pre><code>$ sudo brctl show
bridge name    bridge id       STP enabled interfaces  
br0        8000.xxxxxxxxxxxx   no      eth0  
</code></pre>

<p>And <code>ip addr</code> should show that the bridge adapter <code>br0</code> has received an IP address via DHCP, and that <code>eth0</code> no longer does:</p>

<pre><code>$ ip addr
1: lo: &lt;LOOPBACK,UP,LOWER_UP&gt; mtu 65536 qdisc noqueue state UNKNOWN group default  
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc mq master br0 state UP group default qlen 1000  
    link/ether [redacted MAC] brd ff:ff:ff:ff:ff:ff
3: eth1: &lt;NO-CARRIER,BROADCAST,MULTICAST,UP&gt; mtu 1500 qdisc mq state DOWN group default qlen 1000  
    link/ether [redacted MAC] brd ff:ff:ff:ff:ff:ff
4: br0: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc noqueue state UP group default  
    link/ether [redacted MAC] brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.XX/24 brd 192.168.0.255 scope global br0
       valid_lft forever preferred_lft forever
    inet6 [redacted MAC]/64 scope global mngtmpaddr dynamic
       valid_lft 6917sec preferred_lft 3316sec
    inet6 [redacted MAC]/64 scope global mngtmpaddr dynamic
       valid_lft forever preferred_lft forever
    inet6 [redacted MAC]/64 scope link
       valid_lft forever preferred_lft forever
</code></pre>

<p>I haven't tested this setup, but I believe it should be complete. Next step is to install Docker, on which I will install a container for the Kimchi KVM management tool.</p>]]></content:encoded></item><item><title><![CDATA[Installing Python 3, PyGame and PyOpenGL on Mac OS X El Capitan]]></title><description><![CDATA[<p>I needed to get set up for a project recently that used PyGame and PyOpenGL, running on top of Python 3. I'm running El Capitan currently and in the past I've had extreme difficulty getting a PyGame setup working (on Mavericks), so I was pleased to find it was a</p>]]></description><link>http://www.alexsilcock.net/notes/installing-python-3-pygame-and-pyopengl-on-mac-os-x-el-capitan/</link><guid isPermaLink="false">5f30c6dc-f33b-419b-834e-08274cebac9e</guid><dc:creator><![CDATA[Alex Silcock]]></dc:creator><pubDate>Sun, 24 Apr 2016 23:08:08 GMT</pubDate><content:encoded><![CDATA[<p>I needed to get set up for a project recently that used PyGame and PyOpenGL, running on top of Python 3. I'm running El Capitan currently and in the past I've had extreme difficulty getting a PyGame setup working (on Mavericks), so I was pleased to find it was a flawless setup process on El Capitan (thanks go to the Homebrew contributors for streamlining it so well).</p>

<p>These instructions (largely based on <a href="http://kidscancode.org/blog/2015/09/pygame_install/">this page</a>) assume you've already got Homebrew installed, with Homebrew <code>git</code>.</p>

<pre><code>$ brew cask install xquartz

$ brew install python3

$ pip3 install --upgrade pip setuptools

$ brew install python

$ pip install --upgrade pip setuptools

$ brew linkapps python3

$ brew linkapps python

$ brew install sdl sdl_image sdl_ttf portmidi libogg libvorbis

$ brew install sdl_mixer --with-libvorbis

$ brew tap homebrew/headonly

$ brew install smpeg

$ brew install mercurial

$ pip3 install hg+http://bitbucket.org/pygame/pygame

$ pip3 install pygame

$ pip3 install pyopengl
</code></pre>

<p>Now you've got a working PyGame setup (don't forget to run your script using <code>python3</code>).</p>]]></content:encoded></item><item><title><![CDATA[File transfer from a Nexus 5 to a Mac running Mavericks]]></title><description><![CDATA[<p>OS X doesn't have native support for MTP (Media Transfer Protocol), the protocol that the Nexus 5 and other modern Android devices use when connecting to a computer in order to transfer files. It is possible to transfer files to and from devices that use MTP by installing a tool</p>]]></description><link>http://www.alexsilcock.net/notes/file-transfer-from-a-nexus-5-to-a-mac-running-mavericks/</link><guid isPermaLink="false">8862c465-c875-4514-a0f8-6eb61d93140c</guid><dc:creator><![CDATA[Alex Silcock]]></dc:creator><pubDate>Mon, 16 Mar 2015 13:57:30 GMT</pubDate><content:encoded><![CDATA[<p>OS X doesn't have native support for MTP (Media Transfer Protocol), the protocol that the Nexus 5 and other modern Android devices use when connecting to a computer in order to transfer files. It is possible to transfer files to and from devices that use MTP by installing a tool called <a href="https://www.android.com/intl/en_uk/filetransfer/">Android File Transfer</a> on your Mac.</p>

<p>I was having difficulty getting Android File Transfer to detect that my Nexus 5 (running KitKat 4.4.4) was connected via USB, when I discovered that MTP mode has to be manually enabled on the phone in order for Android File Transfer to detect it. The setting is hidden in Settings -> Storage, and can be found by tapping the menu button and tapping "USB computer connection". After enabling MTP mode using the checkbox, Android File Transfer detected the phone a couple of seconds later and file transfer then worked as expected.</p>

<p>Thanks to <a href="http://www.random-host.com/blogs/enable-media-device-mtp-usb-mode-android-44-kitkat-and-50-lollipop">the original blog post</a> I found explaining the setting and where to find it.</p>]]></content:encoded></item><item><title><![CDATA[Quick snippet: redirecting requests with a missing www. in Apache]]></title><description><![CDATA[<p>Getting <code>www.</code> prepended to requests to <code>alexsilcock.net</code> using mod_rewrite sometimes feels like voodoo, and in the past I've managed to get it partially working but with unexplained infinite redirect loops. To save experimenting with it in the future, here's the easiest way of accomplishing it:</p>

<pre><code>RewriteCond %{HTTP_HOST}</code></pre>]]></description><link>http://www.alexsilcock.net/notes/quick-snippet-adding-a-missing-www-in-apache/</link><guid isPermaLink="false">cbb85c79-edc7-4fec-8776-ac3509c4d4eb</guid><dc:creator><![CDATA[Alex Silcock]]></dc:creator><pubDate>Sun, 28 Dec 2014 18:13:57 GMT</pubDate><content:encoded><![CDATA[<p>Getting <code>www.</code> prepended to requests to <code>alexsilcock.net</code> using mod_rewrite sometimes feels like voodoo, and in the past I've managed to get it partially working but with unexplained infinite redirect loops. To save experimenting with it in the future, here's the easiest way of accomplishing it:</p>

<pre><code>RewriteCond %{HTTP_HOST} !^www\.alexsilcock\.net$ [NC]
RewriteRule . http://www.alexsilcock.net%{REQUEST_URI} [R=301,L]
</code></pre>

<p>This works with requests to the base site URL, subdirectories of the site, and is SEO-friendly with its <a href="https://en.wikipedia.org/wiki/HTTP_301">301 Moved Permanently</a> HTTP response code.</p>]]></content:encoded></item><item><title><![CDATA[Trailing-slashes when reverse proxying with mod_proxy]]></title><description><![CDATA[<p>I often want to mount a node.js single-page web application into a subdirectory of an Apache-hosted website, and the reverse-proxy feature of the Apache module <a href="https://httpd.apache.org/docs/current/mod/mod_proxy.html">mod_proxy</a> is perfect for this. Getting the forward-slashes at the end of the URL correct is important for successfully loading assets, so this</p>]]></description><link>http://www.alexsilcock.net/notes/trailing-slashes-when-reverse-proxying-with-mod_proxy/</link><guid isPermaLink="false">505a595b-1feb-4d0b-83df-89ecae8f1a2a</guid><category><![CDATA[apache]]></category><dc:creator><![CDATA[Alex Silcock]]></dc:creator><pubDate>Sun, 28 Dec 2014 18:02:19 GMT</pubDate><content:encoded><![CDATA[<p>I often want to mount a node.js single-page web application into a subdirectory of an Apache-hosted website, and the reverse-proxy feature of the Apache module <a href="https://httpd.apache.org/docs/current/mod/mod_proxy.html">mod_proxy</a> is perfect for this. Getting the forward-slashes at the end of the URL correct is important for successfully loading assets, so this post provides a short summary of how to do so.</p>

<p><strong>tl;dr: snippet at the end of this post</strong></p>

<p>If my application references its CSS and JS using relative paths, e.g. <code>&lt;script src="assets/main.css"&gt;</code>, the following ProxyPass rule in the Apache config appears to work correctly:</p>

<pre><code>ProxyPass /someapp http://localhost:23456
</code></pre>

<p>This works fine if you request <code>example.com/someapp/</code>, because the browser will translate a script source of <code>assets/main.css</code> into an HTTP request for <code>http://example.com/someapp/assets/main.css</code>.</p>

<p>However, visiting <code>http://example.com/someapp</code> (note the lack of trailing-slash) will mean the CSS request goes to <code>http://example.com/assets/main.css</code>, which is outside the directory of the proxied app. To ensure that the application is only visited with the trailing slash present, requests can be redirected to the application using the following mod_rewrite rule (assuming you've already turned <code>RewriteEngine on</code>):</p>

<pre><code>RewriteRule ^/someapp$ someapp/ [L,R=301]
</code></pre>

<p>These rules combine to form the following snippet that I use when mounting a node.js web application under a subdirectory on my website:</p>

<pre><code>RewriteRule ^/someapp$ someapp/ [L,R=301]
ProxyPass /someapp http://localhost:23456
ProxyPassReverse /someapp http://localhost:23456
</code></pre>]]></content:encoded></item><item><title><![CDATA[The standard "Hello World" post]]></title><description><![CDATA[<p>For years (yes, it probably is that long), I'd always intended to set up some sort of blog or ultimately something online where I could post notes about projects I've been working on; sometimes it'd be the solution to a tricky software development problem I'd encountered, or it'd be that</p>]]></description><link>http://www.alexsilcock.net/notes/the-standard-hello-world-post/</link><guid isPermaLink="false">eab4302f-1eac-4318-940d-4a2451f2f156</guid><dc:creator><![CDATA[Alex Silcock]]></dc:creator><pubDate>Mon, 10 Nov 2014 00:32:53 GMT</pubDate><content:encoded><![CDATA[<p>For years (yes, it probably is that long), I'd always intended to set up some sort of blog or ultimately something online where I could post notes about projects I've been working on; sometimes it'd be the solution to a tricky software development problem I'd encountered, or it'd be that last little obscure bit of server configuration that I needed to get something working properly (most recently it was OpenVPN - I'm looking at you, iptables!)</p>

<p>At long last I can finally tick off "set up some sort of blog-type thing" on my mental to-do list! I expect most of my posts here to be about techy things, often for my own reference, but undoubtedly I'll make the occasional post about something less electronic.</p>

<p>Listening to: Knife Party - EDM Trend Machine  </p>

<iframe width="100%" height="166" scrolling="no" frameborder="no" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/175930491&amp;color=ff5500&amp;auto_play=false&amp;hide_related=false&amp;show_comments=true&amp;show_user=true&amp;show_reposts=false"></iframe>]]></content:encoded></item></channel></rss>