<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>whizzy.org</title>
	<atom:link href="/feed/" rel="self" type="application/rss+xml" />
	<link>/</link>
	<description>On code and gadgets.</description>
	<lastBuildDate>Wed, 14 Jul 2021 13:46:20 +0000</lastBuildDate>
	<language>en-GB</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=5.7.2</generator>
	<item>
		<title>Finally moving to a static site</title>
		<link>/2021/07/14/finally-moving-to-a-static-site/</link>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Wed, 14 Jul 2021 13:46:20 +0000</pubDate>
				<category><![CDATA[Making the world a better place]]></category>
		<guid isPermaLink="false">/?p=1110</guid>

					<description><![CDATA[Amazon have made some changes to the (admittedly generous) Alexa AWS credits programme [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>Amazon have made some changes to the (admittedly generous) Alexa AWS credits programme which made me think about the services that I run there and how to reduce my bill a bit.  This WP blog was hosted on a t2.micro instance running Apache, MySQL, PHP, and WordPress.  You need to add a bit of swap in order to keep MySQL happy but generally speaking it will tick along at very low load.  So low in fact that I thought about merging the blog hosting instance with another instance which runs various home automation services, but decided that was too risky.</p>



<p>Rather than a security bug in WordPress exposing my internal network to the world I&#8217;ve decided to move everything to static pages.  I don&#8217;t really post here any more, so it&#8217;s not like I need everything that WordPress offers and there are lots of places which will host static pages for either free or very cheap, so why not try it out?  Here&#8217;s what I decided on and how I did it.</p>



<h2>Hosting</h2>



<p>I considered the following:</p>



<ol><li>Creating a virtualhost in an already existing Apache set up</li><li>Uploading a static copy of these pages to S3</li><li>Uploading a static copy of these pages to Github Pages</li><li>Moving to a cheaper cloud provider</li></ol>



<p>I ruled out 1, I don&#8217;t want any public facing services on my otherwise private servers.  I know enough to know that I don&#8217;t know anything about securing web servers.</p>



<p>I think #2 and #3 are largely the same in the end.  As you have probably worked out by now, I decided that Github was the one I would try.  This was decided entirely on cost.  S3 would have cost me a couple of pennies a month, Github was free.</p>



<p>I also considered spinning up a new instance in <a rel="noreferrer noopener" href="http://do.co/lnl" data-type="URL" data-id="do.co/lnl" target="_blank">Digital Ocean</a> or <a rel="noreferrer noopener" href="https://linode.com/latenightlinux" target="_blank">Linode</a> (referral link, get $100 credit) which would have been about 20% cheaper for a t2.micro equivalent.  Github pages are free though, and get a decent CDN behind them.  WordPress on a small server is slow without doing work.</p>



<h2>Getting the data out of WordPress</h2>



<p>I used the <a href="https://patrickposner.dev/plugins/simply-static/">Simply Static</a> plugin for WordPress to export the pages and images to HTML.  It worked pretty well, and I would recommend it.  Simply Static produced a zip file with everything in.  I unzipped it and copied everything to the root of a new Github repo, committed it, pushed it, and it worked.</p>



<p>Some tips for preparing your blog for export:</p>



<ul><li>Disable comments on all your posts. This is a faff as you have to do it on each existing post. In the end I followed this guide: <a href="https://themeisle.com/blog/disable-comments-in-wordpress/" target="_blank" rel="noreferrer noopener">https://themeisle.com/blog/disable-comments-in-wordpress/</a><br>See section 3 on how to remove the ability to comment on existing posts.</li><li>Remove all the meta links etc from the footer and sidebar.  I did this through the WordPress &#8220;Appearance&#8221; -> &#8220;Customise&#8221; menu to remove widgets and links as required.</li></ul>



<h2>Adding new content in the future</h2>



<p>I have zero interest in learning some new static blogging platform or writing posts in HTML or Markdown or using some automated jiggery pokery.  I really like WordPress for it&#8217;s WYSIWYG writing interface.   I write about one post every two years.  I intend to switch off the instance hosting WordPress until such time as I need to write a new post, then I&#8217;ll switch it on, write the post and export it using Simply Static.  This will cost me a few cents for the disk storage, and zero effort.</p>



<p></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Double helping of Pi Hole</title>
		<link>/2021/01/02/double-helping-of-pi-hole/</link>
					<comments>/2021/01/02/double-helping-of-pi-hole/#comments</comments>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Sat, 02 Jan 2021 17:45:02 +0000</pubDate>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[RaspberryPi]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<guid isPermaLink="false">/?p=1020</guid>

					<description><![CDATA[Improve the performance of Pi Hole by running it on a more powerful computer. Durr.]]></description>
										<content:encoded><![CDATA[
<p>In <a href="https://latenightlinux.com/late-night-linux-episode-100/">episode 100 of Late Night Linux</a> I talked a little bit about trying out <a href="https://pi-hole.net/">Pi Hole</a> and <a href="https://adguard.com/en/welcome.html">AdGuard</a> to replace my home grown ad blocker based on <a href="http://www.thekelleys.org.uk/dnsmasq/doc.html">dnsmasq</a> and a massive hosts file.</p>



<p>I came down in favour of Pi Hole for a couple of reasons but the deciding factor was that Pi Hole felt a bit more open and that it was built on top of <code>dnsmasq</code> which allowed me to reuse config for TFTP which netboots some devices which needed it.</p>



<p>Now that I&#8217;ve been using Pi Hole for a few months I have a much better understanding of its limitations and the big one for me is performance. Not the performance when servicing DNS requests but performance when querying the stats data, when reloading block lists and when enabling and disabling certain lists. I suspect a lot of the problems I was having is down to flaky SD cards.</p>



<p>I fully expect that for most people this will never be a problem, but for me it was an itch I wanted to scratch, so here&#8217;s what I did:</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" width="341" height="581" src="/wp-content/uploads/2021/01/Double-Pi-Hole.png" alt="" class="wp-image-1021" srcset="/wp-content/uploads/2021/01/Double-Pi-Hole.png 341w, /wp-content/uploads/2021/01/Double-Pi-Hole-176x300.png 176w" sizes="(max-width: 341px) 100vw, 341px" /></figure></div>



<p>Through the actually quite generous <a href="https://developer.amazon.com/en-US/alexa/alexa-skills-kit/new/aws-promotional-credits">Amazon Alexa AWS Credits promotion</a> I have free money to spend on AWS services, so I spun up a <code>t2.micro</code> EC2 instance (1 vCPU, 1GB RAM &#8211; approx £10 a month) running Ubuntu.</p>



<p>I installed Pi Hole on that instance along with Wireguard which connects it back to my local network at home.  I used <a href="https://www.linode.com/docs/guides/set-up-wireguard-vpn-on-ubuntu/">this guide from Linode</a> to get Wireguard set up.  </p>



<p>The Pi Hole running in AWS hosts the large block files and is configured with a normal upstream DNS server as its upstream (I&#8217;m using Cloudflare).</p>



<figure class="wp-block-image size-large"><img loading="lazy" width="484" height="627" src="/wp-content/uploads/2021/01/image-2.png" alt="" class="wp-image-1024" srcset="/wp-content/uploads/2021/01/image-2.png 484w, /wp-content/uploads/2021/01/image-2-232x300.png 232w" sizes="(max-width: 484px) 100vw, 484px" /><figcaption>Pi Hole running in AWS configured with Cloudflare as its upstream DNS</figcaption></figure>



<p>I use three Ad block lists:</p>



<ul><li><code>OISD:</code> <a href="https://dbl.oisd.nl/">https://dbl.oisd.nl/</a></li><li><code>Wally3k:</code> <a href="https://v.firebog.net/hosts/static/w3kbl.txt">https://v.firebog.net/hosts/static/w3kbl.txt</a></li><li><code>Polish Filters Team: </code><a href="https://raw.githubusercontent.com/PolishFiltersTeam/KADhosts/master/KADhosts_without_controversies.txt">https://raw.githubusercontent.com/PolishFiltersTeam/KADhosts/master/KADhosts_without_controversies.txt</a></li></ul>



<figure class="wp-block-image size-large"><img loading="lazy" width="1000" height="389" src="/wp-content/uploads/2021/01/image-1.png" alt="" class="wp-image-1023" srcset="/wp-content/uploads/2021/01/image-1.png 1000w, /wp-content/uploads/2021/01/image-1-300x117.png 300w, /wp-content/uploads/2021/01/image-1-768x299.png 768w, /wp-content/uploads/2021/01/image-1-720x280.png 720w" sizes="(max-width: 1000px) 100vw, 1000px" /></figure>



<p>Pi Hole running on a <code>t2.micro</code> instance is really speedy.  I can reload the block list in a matter of seconds (versus minutes on the Pi) and querying the stats database no longer locks up and crashes Pi Hole&#8217;s management engine FTL.</p>



<p>The Pi Hole running on my LAN is configured to use the above AWS based Pi Hole as its upstream DNS server and also has a couple of additional block lists for <a href="https://raw.githubusercontent.com/8none1/pihole-blocklists/main/youtube/hosts">YouTube</a> and <a href="https://raw.githubusercontent.com/llacb47/mischosts/master/social/tiktok-block">TikTok</a>.</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" width="1000" height="389" src="/wp-content/uploads/2021/01/image.png" alt="" class="wp-image-1022" srcset="/wp-content/uploads/2021/01/image.png 1000w, /wp-content/uploads/2021/01/image-300x117.png 300w, /wp-content/uploads/2021/01/image-768x299.png 768w, /wp-content/uploads/2021/01/image-720x280.png 720w" sizes="(max-width: 1000px) 100vw, 1000px" /></figure></div>



<p>This allows me use Pi Hole on a Pi as the DHCP server on my LAN and benefit from the GUI to configure things.  I can quickly and easily block YouTube when the kids have done enough and won&#8217;t listen to reason and the heavy lifting of bulk ad blocking is done on an AWS EC2 instance.  The Pi on the LAN will cache a good amount of DNS and so everything whizzes along quickly.</p>



<p>Pi Hole on the LAN has a block list of about 3600 hosts, whereas the version running in AWS has over 1.5 million.</p>



<p>All things considered I&#8217;m really happy with Pi Hole and the split-load set up I have now makes it even easier to live with.  I would like to see an improved Pi Hole API for enabling and disabling specific Ad lists so that I can make it easier to automate (e.g. unblock YouTube for two hours on a Saturday morning).  I think that will come in time.  The split-load set up also allows for easy fallback should the AWS machine need maintenance &#8211; it would be nice to have a &#8220;DNS server of last resort&#8221; in Pi Hole to make that automatic.  Perhaps it already does, I should investigate.</p>



<p>Why not just run Pi Hole on a more powerful computer in the first place? That would be too easy.</p>



<p>If you fancy trying out Pi Hole in the cloud or just playing with Wireguard you can get $100 free credit with Linode with the Late Night Linux referral code: <a href="https://linode.com/latenightlinux">https://linode.com/latenightlinux</a></p>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>/2021/01/02/double-helping-of-pi-hole/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title>DNS over HTTPS in a snap</title>
		<link>/2019/07/16/dns-over-https-in-a-snap/</link>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Tue, 16 Jul 2019 20:07:44 +0000</pubDate>
				<category><![CDATA[IoT]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[RaspberryPi]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">/?p=970</guid>

					<description><![CDATA[Background Story With the recent news about the ISP UK association proposing Mozilla [&#8230;]]]></description>
										<content:encoded><![CDATA[
<h2>Background Story</h2>



<p>With the recent news about the ISP UK association proposing Mozilla as &#8220;<a href="https://www.ispa.org.uk/ispa-announces-finalists-for-2019-internet-heroes-and-villains-trump-and-mozilla-lead-the-way-as-villain-nominees/">Internet villain of the year</a>&#8221; for enabling DNS over HTTPS (and subsequently changing their mind and dropping the whole category of villain of the year.  Good move I think.) I figured it was probably about time that I looked at enabling DoH at home.</p>



<p>Cloudflare have a suite of open source tools called <a href="https://github.com/cloudflare/cloudflared/">cloudflared</a> which has, among other things, a DNS over HTTPS proxy.  By default it points at their 1.1.1.1 service, but you can change that if you want to.  Note, at the time of writing there is a <a href="https://github.com/cloudflare/cloudflared/issues/113">bug</a> which seems to stop Google&#8217;s DNS service working.  If you&#8217;re looking to stop people seeing your DNS traffic then Google probably isn&#8217;t the right DNS service to use anyway.</p>



<figure class="wp-block-image size-large"><img loading="lazy" width="353" height="469" src="/wp-content/uploads/2019/07/proxy-dns.jpg" alt="" class="wp-image-972" srcset="/wp-content/uploads/2019/07/proxy-dns.jpg 353w, /wp-content/uploads/2019/07/proxy-dns-226x300.jpg 226w" sizes="(max-width: 353px) 100vw, 353px" /></figure>



<p>I already have dnsmasq running as my DNS server and I have quite a lot of config which I wanted to keep (e.g. adblocking) so I figured I would add cloudflared&#8217;s proxy-dns alongside dnsmasq and have dnsmasq use proxy-dns as it&#8217;s upstream server, which would in turn pass the DNS lookups to 1.1.1.1 over HTTPS.  dnsmasq would then cache the results locally.</p>



<p>So far, so good.  I&#8217;d built cloudflared on my desktop to test it, now I wanted to move it on to the Raspberry Pi, run it as a service, and ideally have a package so that I didn&#8217;t have to mess around rebuilding it in loads of places if I wanted to move to a different box.</p>



<h2>Make a snap</h2>



<p>Making a snap of proxy-dns would give the the package I wanted, and could allow me to run proxy-dns as a daemon with two words in the YAML.  Snapcraft&#8217;s <a href="https://snapcraft.io/build">build service</a> would build me an ARM binary, as well as loads of others, for free.</p>



<p>I downloaded the source for <a href="https://github.com/cloudflare/cloudflared">cloudflared</a> and added three files:</p>



<ol><li>A <a href="https://github.com/8none1/cloudflaredohsnap/blob/master/snapcraft.yaml">snapcraft.yaml</a> which describes how to build cloudflared and sets it to be run as a daemon</li><li>A <a href="https://github.com/8none1/cloudflaredohsnap/blob/master/snap/hooks/configure">configure hook</a> which lets me set some config options</li><li>A <a href="https://github.com/8none1/cloudflaredohsnap/blob/master/launcher/launcher">launcher script</a> which sets the config at run time</li></ol>



<p>None of these are very complicated, as you can see.  Hat-tip to <a href="https://twitter.com/popey">Popey</a> for help with the snapcraft.yaml.</p>



<p>The I pushed these back to my project on <a href="https://github.com/8none1/cloudflaredohsnap">GitHub</a> and added that project to the <a href="https://snapcraft.io/build">Snapcraft.io build service</a>.  Now, whenever I push a new change back to GitHub the snap will get rebuilt <strong>automatically</strong> and uploaded to the store! All I would need to do is a snap refresh and I&#8217;d be upgraded to the latest version. All my requirements solved in one place.</p>



<h2>How to use the snap</h2>



<p>If your Pi is running snapd, it&#8217;s dead easy (e.g. Ubuntu MATE or Ubuntu Core):</p>



<pre class="wp-block-preformatted">sudo snap install cloudflaredoh --edge</pre>



<p>The snap is currently in the edge channel, meaning it&#8217;s not ready for the main stage just yet.  Once I&#8217;ve spent a bit more time on it, I will move it to stable.</p>



<pre class="wp-block-preformatted">sudo snap set cloudflaredoh address=127.0.0.1<br>sudo snap set cloudflaredoh port=5053</pre>



<p>Configure proxy-dns to listen on 127.0.0.1.  If you want it to answer DNS queries from other computers on your network try either the IP address of the box, or just 0.0.0.0 to listen on all interfaces.  It will also configure proxy-dns to listen on port 5053.  If you want it to answer DNS queries from other computers on your network, use the default DNS port of 53.</p>



<pre class="wp-block-preformatted">sudo snap get cloudflaredoh</pre>



<p>This will show you the currently set config options.</p>



<pre class="wp-block-preformatted">sudo snap restart cloudflaredoh</pre>



<p>Restart proxy-dns and use the new config.</p>



<p>Now you can use something like nslookup to query the DNS server and make sure it&#8217;s doing what you expected.</p>



<h2>10 Steps To DNS-over-HTTPS</h2>



<ol><li>Get a Raspberry Pi</li><li>Download Ubuntu Core and write it to an SD card</li><li>Put the SD card in your Pi and boot it</li><li>Set up the network on Ubuntu Core (tip: register for an <a href="https://login.ubuntu.com/+login">Ubuntu One</a> account first)</li><li>sudo snap install cloudflaredoh</li><li>sudo snap set cloudflaredoh address=0.0.0.0</li><li>sudo snap set cloudflaredoh port=53</li><li>sudo snap restart cloudflaredoh</li><li>Configure your client&#8217;s DNS server as the IP address of your Pi</li><li>Have a cup of tea</li></ol>



<h2>Update 2019-08-01</h2>



<p>I&#8217;ve got a new Github repo set up with an improved snapcraft.yaml which pulls directly from the upstream project.  I&#8217;m aiming to get this hooked up to the Snapcraft build service so that we can package the latest version automatically.  More on this later.  In the meantime, you can clone this and build the latest version yourself:</p>



<p><a href="https://github.com/8none1/cloudflarednsproxy">https://github.com/8none1/cloudflarednsproxy</a></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Whizzy Labs Wireless Sensor</title>
		<link>/2019/06/11/whizzy-labs-wireless-sensor/</link>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Tue, 11 Jun 2019 15:36:26 +0000</pubDate>
				<category><![CDATA[Arduino]]></category>
		<category><![CDATA[IoT]]></category>
		<guid isPermaLink="false">/?p=878</guid>

					<description><![CDATA[Sheesh! Making a wireless sensor has proven to be a lot harder than [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Sheesh! Making a wireless sensor has proven to be a lot harder than I had expected.</p>
<p>Like a lot of weekend hardware hackers I thought it would be fun to build a wireless temperature sensor. I could use it as a feedback mechanism for my <a href="/2014/01/raspberry-pi-powered-heating-controller-part-1/">Raspberry Pi heating controller</a>, I could create graphs of temperatures in different rooms (everyone loves a graph right?), and with a little bit of forward planning I could make a fairly useful Arduino breakout board which could be used for lots of other fun wireless projects.</p>
<p>I&#8217;ve been through four iterations of the design before I finally found something that worked. I could have avoided some of this if I&#8217;d have spent more time testing on breadboard, but then I wouldn&#8217;t get to order colourful PCBs!</p>
<p><img loading="lazy" class="alignnone size-large wp-image-949" src="/wp-content/uploads/2017/03/photo_2017-06-19_16-39-12-1024x327.jpg" alt="" width="770" height="246" srcset="/wp-content/uploads/2017/03/photo_2017-06-19_16-39-12-1024x327.jpg 1024w, /wp-content/uploads/2017/03/photo_2017-06-19_16-39-12-300x96.jpg 300w, /wp-content/uploads/2017/03/photo_2017-06-19_16-39-12-768x246.jpg 768w, /wp-content/uploads/2017/03/photo_2017-06-19_16-39-12-1200x384.jpg 1200w, /wp-content/uploads/2017/03/photo_2017-06-19_16-39-12.jpg 1276w" sizes="(max-width: 770px) 100vw, 770px" /></p>
<h2>The Brief</h2>
<h3>Cheap</h3>
<p>In common with a lot of my other weekend projects, this is very likely to be a white elephant, so it needs to be cheap to start with.  There are lots of excellent wireless sensors already available, the <a href="https://lowpowerlab.com/shop/">Moteino</a> is well regarded.  Using that as a baseline, could I build something similar for less than £5 per unit?  The answer is &#8220;nearly&#8221;, see the Bill Of Materials below.</p>
<h3>Use a ready made microcontroller board</h3>
<p>I didn&#8217;t want to have to design a board which I would then have to solder an ATmega328/P to myself. Laying out that board would be hard, plus I would have to spec and solder all the supporting components. I could have done that with through-hole components I suppose, but then the board would have been massive, and I very much doubt it would have actually worked out any cheaper.  Instead, I decided that a better idea was to solder on a ready-made Arduino clone, specifically the <a href="https://www.arduino.cc/en/Main/ArduinoBoardProMini">Pro Mini</a>. I buy them from <a href="http://rover.ebay.com/rover/1/710-53481-19255-0/1?icep_ff3=2&amp;pub=5575128401&amp;toolid=10001&amp;campid=5337704861&amp;customid=&amp;icep_item=321413432145&amp;ipn=psmain&amp;icep_vectorid=229508&amp;kwid=902099&amp;mtid=824&amp;kw=lg">this supplier on eBay</a> and I&#8217;ve never had any problems. They are 3v / 5v switchable, very reliable and turn up quickly.  Power consumption was going to be an important metric and running them off of a 3V supply would be essential.</p>
<h3>Use a ready made radio module</h3>
<p>As with the MCU, I don&#8217;t want to be laying out a radio board or soldering surface mount components.  I needed a ready-made radio module which was cheap, readily available and had low power requirements.  I started off with the NRF24L01.  It had a small footprint, cost around 99p a unit, had a built in antenna and was supported by the <a href="http://www.airspayce.com/mikem/arduino/RadioHead/">RadioHead library</a>.  Initial testing on breadboard showed that the range of these devices would be sufficient for my house.  I designed the first two revisions of the sensor board around this radio (and a CR2032, see the battery section below).  Initial current draw was a bit too high for the CR2032, but I could have worked around that by using AAA batteries instead &#8211; but more annoying was that the range of the radios was not at all reliable.  The 2.4GHz spectrum is very noisy and the addition of two baby monitors since the original breadboard test hasn&#8217;t helped, but in testing on the PCB I found these radios to be pretty much useless.  I also tried using the version with the power amp as the central transceiver, this helped a little bit but they were still failing to get at least 50% of their transmissions to the other end, even over a couple of meters.  Other people have reported really good range with these boards, but crucially those range tests were done outside.  It&#8217;s my considered opinion that these radios and Wifi in the house do not co-exist.</p>
<p>So I gave up with those, and tried the <strong>XL4432-SMT</strong>.  This is based on the Si443x chipset from <a href="http://www.silabs.com/products/wireless/proprietary/ezradiopro-ism-band-transmitters-recievers-transceivers">Silicon Labs</a>.  They&#8217;re <a href="http://rover.ebay.com/rover/1/710-53481-19255-0/1?icep_ff3=2&amp;pub=5575128401&amp;toolid=10001&amp;campid=5337704861&amp;customid=&amp;icep_item=142189527394&amp;ipn=psmain&amp;icep_vectorid=229508&amp;kwid=902099&amp;mtid=824&amp;kw=lg">readily available on eBay</a> for around £.170 each, so nearly twice the price of the NRF24L01.  They&#8217;re well supported by the <a href="http://www.airspayce.com/mikem/arduino/RadioHead/">RadioHead</a> library, can run down to 1.8V, have low current draw when on (virtually nothing when in stand-by), support a wide frequency range around the 433MHz ISM band and in range testing they out-performed the NRF24L01 by a long way.  The downside is that these pre-made boards use 1.27mm pitch / castellated connections.  I had to design an Eagle part to interface with them, but that wasn&#8217;t really too hard.  See below for links to the parts I made.  Another drawback was the antenna; being a much lower frequency means they need a much longer antenna so I would need to find a project box which could hold them.<br />
The Si443x also has a temperature sensor and a wake up timer on board.  However, reading the errata from Silicon Labs it seems that the WUT is actually broken and the temperature sensor was returning very strange results.  The datasheet says that you need to calibrate the temperature sensor so I tried doing this but go nowhere fast, and so I opted to use a 1wire sensor instead.</p>
<p>The other option for a radio would have been an ESP8266.  You can get ready made boards cheap on eBay, and I could have done away with a separate MCU altogether but the power consumption of these devices is just too great for a project which needs to run of a couple of batteries for a year.</p>
<h3>Run for a long time on batteries</h3>
<p>What&#8217;s the point in a wireless sensor if you have to plug it in to the mains.  This project must run from batteries, and those batteries need to last a long time &#8211; having to change the batteries every few months would quickly get boring and the sensors would be left doing nothing.  Obviously having the MCU go in to a sleep state between runs is going to be necessary, plus a radio which has modest power requirements when running.  We can further reduce the power needs by making sure that the &#8220;work&#8221; that the sensor has to do is done as quickly as possible.  The default 1wire temperature sensor code you find will typically takes around 2700msec to read.  That&#8217;s a very long time.  I changed the code a bit by hard-coding the hardware address of the sensor on the board and by only reading two bytes of temperature data (good for 0.5 degree accuracy).  More information can be found below.</p>
<p>From a size perspective a CR2032 battery looks very appealing.  Some early testing made me think that they would work fine but in real life I had a lot of problems.  In hindsight I think I can put most of the problems down the Brown Out Detector on the Pro Mini being set to 2.8V, more on that in a moment.</p>
<p>UPDATE:  Whoops.  This post has been sat in drafts for nearly 2 years.  Guess it&#8217;s not getting finished then.  I&#8217;m posting this in case the above is interesting.  Topics that I wanted to cover but haven&#8217;t are:</p>
<ul>
<li>Fit neatly in a box</li>
<li>Read the temperature</li>
<li>Be extensible</li>
<li>Reading 1wire temperature sensors quickly</li>
<li>Lower the BOD to 1.8V</li>
<li>Bill Of Materials</li>
</ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Ubuntu Developer Desktop Survey 2019</title>
		<link>/2019/05/07/ubuntu-developer-desktop-survey-2019/</link>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Tue, 07 May 2019 17:53:31 +0000</pubDate>
				<category><![CDATA[Making the world a better place]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<guid isPermaLink="false">/?p=962</guid>

					<description><![CDATA[It’s clear that a lot of people develop software using Ubuntu. What’s less [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>It’s clear that a lot of people develop software using Ubuntu. What’s less clear is exactly what sort of software is being built. We see reports of people developing Linux apps, Android apps, web services, self driving cars… the list is huge. We need to get better clarity; to understand how that relates to Ubuntu desktop.</p>



<p>We can get some reasonable insights from the <a href="https://insights.stackoverflow.com/survey/2019">Stack Overflow Developer Survey</a>, but I&#8217;m keen to really dig down in to the Ubuntu community specifically.</p>



<p>When I was chatting with <a href="https://bartongeorge.io/">Barton George</a> a few weeks back he expressed the same interest;  what <em>are</em> people doing with the <a href="https://www.dell.com/learn/us/en/555/campaigns/xps-linux-laptop_us">Sputnik</a> machines from Dell?  We want to learn more about the sorts of software projects that you&#8217;re working on so that we can make the Ubuntu developer experience as good as possible.</p>



<p>To that end we put together the <a href="http://desktopdevelopersurvey2019.ubuntu.com/">Ubuntu Developer Desktop Survey</a> to help us understand more about what you’re doing and how you’re doing it. This survey is aimed primarily at people who are using Ubuntu to develop software targeting any platform. It doesn’t matter if you do that at work, at home, at school – if you’re building software then we’re glad to hear from you. To be clear: this doesn’t mean we’re abandoning our mantra of Ubuntu being for human beings, software developers are human beings too. Right now I want to get a better view in to what software developers are doing.</p>



<p>The survey will close on Friday 31st May 2019 and we will publish the results very shortly afterwards.  We&#8217;ll then follow that up with some further analysis and some ideas as to how this will influence the desktop product roadmap in the future.  Please take this opportunity to help shape Ubuntu for the better.</p>



<p>You can find the survey here:</p>



<p style="text-align:center"><a href="http://desktopdevelopersurvey2019.ubuntu.com/">http://desktopdevelopersurvey2019.ubuntu.com/</a></p>



<p>You don’t need to register or sign in to complete the form.</p>



<p></p>



<p></p>



<p></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Ubuntu Desktop goings on.  Friday 19th May 2017</title>
		<link>/2017/05/19/ubuntu-desktop-goings-on-friday-19th-may-2017/</link>
					<comments>/2017/05/19/ubuntu-desktop-goings-on-friday-19th-may-2017/#comments</comments>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Fri, 19 May 2017 14:45:55 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">/?p=943</guid>

					<description><![CDATA[Ubuntu Desktop Newsletter I&#8217;m going to start a weekly newsletter style update to [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Ubuntu Desktop Newsletter</h1>
<p>I&#8217;m going to start a weekly newsletter style update to keep people abreast of what&#8217;s been going on with Ubuntu Desktop as we move to GNOME Shell and build the foundations for 18.04 LTS.  Here&#8217;s the first instalment:</p>
<h2>Friday 19th May 2017</h2>
<h3>GNOME</h3>
<p>We’re on to the last few MIR (<a href="https://wiki.ubuntu.com/MainInclusionProcess">https://wiki.ubuntu.com/MainInclusionProcess</a>) reviews for the packages needed to update the seeds in order to deliver the GNOME desktop by default.<br />
We still have some security questions to answer about how we deal with updates to mozjs/gjs in an LTS release (where mozjs has a support period of 12 months but we need to offer support for a full five years). This is being looked at now, but for 17.10 we are set.<br />
We are aiming to have the seeds updated next week, and this will be the first milestone on the road to a fantastic GNOME experience in 17.10 Artful.</p>
<p>We’ve been fixing bugs in the Ambiance &amp; Radiance themes to make them look crisp on GNOME Shell.<br />
<a href="http://www.omgubuntu.co.uk/2017/05/install-improved-ambiance-gnome-theme">http://www.omgubuntu.co.uk/2017/05/install-improved-ambiance-gnome-theme</a></p>
<p>We’ve also triaged over 400 GNOME Shell bugs in Launchpad to allow us to more easily focus on the important issues.</p>
<p>We have been working on removing Ubuntu’s custom “aptdaemon” plugin in GNOME Software in favour of the upstream solution which uses PackageKit. This allows us to share more code with other distributions.</p>
<h3>LivePatch</h3>
<p><a href="https://www.ubuntu.com/server/livepatch">https://www.ubuntu.com/server/livepatch</a></p>
<p>LivePatch delivers essential kernel security updates to Ubuntu machines without having to reboot to apply them. As an Ubuntu user you can sign up for a free account.<br />
We’re working on integrating LivePatch in to the supported LTS desktops to provide a friendly way to setup and configure the service.<br />
This week we started to investigate the APIs provided by the LivePatch services so we can report LivePatch activity to the user, obtain an API key on behalf of the user &amp; set up the service. Work has also started on the software-properties-gtk dialogs (aka Software &amp; Updates in System Settings) to add the options required for LivePatch.</p>
<h3>QA</h3>
<p>Added upgrade tests from Zesty to Artful for Ubuntu and flavours. Working on making all these tests pass now so that everyone will have a solid and reliable upgrade path.<br />
Work is being done on the installer tests. This will extend the current installer tests to check that not only has the install completed successfully but that all desktop environment is working as expected, this had previously been covered with manual tests.</p>
<h3>Package Updates</h3>
<ul>
<li>GStreamer is now at 1.12 final in 17.10.</li>
<li>Chromium: stable 58.0.3029.110, beta 59.0.3071.47, dev 60.0.3095.5</li>
<li>LibreOffice 5.3.3 is being tested.</li>
<li>CUPS-filters: 1.14.0</li>
<li>Snapd-glib: 1.12</li>
</ul>
<h3>Snaps</h3>
<p>More GNOME applications are being packaged as Snaps. There is still some work to do to get them fully confined and fully integrated into the desktop. We’re working on adding Snap support to Gtk’s Portals to allow desktop Snaps to access resources outside their sandbox.<br />
We will start tracking the Snaps here:<br />
<a href="https://wiki.ubuntu.com/DesktopTeam/GNOME/Snaps">https://wiki.ubuntu.com/DesktopTeam/GNOME/Snaps</a></p>
<h3>In the news</h3>
<p>Interview with Ken VanDine on the GNOME Desktop in Ubuntu:  <a href="http://www.omgubuntu.co.uk/2017/05/ubuntu-switch-to-gnome-questions-answered">http://www.omgubuntu.co.uk/2017/05/ubuntu-switch-to-gnome-questions-answered<br />
</a></p>
<p>There&#8217;s also a survey running to get feedback on some extensions which could be shipped with Ubuntu Desktop: <a href="http://www.omgubuntu.co.uk/2017/05/ubuntu-desktop-gnome-extensions-survey-1710">http://www.omgubuntu.co.uk/2017/05/ubuntu-desktop-gnome-extensions-survey-1710</a></p>
<p>This was picked up by the Linux Unplugged podcast as their headline story: <a href="http://www.jupiterbroadcasting.com/114701/that-new-user-smell-lup-197/">http://www.jupiterbroadcasting.com/114701/that-new-user-smell-lup-197/</a></p>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>/2017/05/19/ubuntu-desktop-goings-on-friday-19th-may-2017/feed/</wfw:commentRss>
			<slash:comments>8</slash:comments>
		
		
			</item>
		<item>
		<title>Retrieving user profile data from Login With Amazon on Alexa</title>
		<link>/2017/03/27/retrieving-user-profile-data-from-login-with-amazon-on-alexa/</link>
					<comments>/2017/03/27/retrieving-user-profile-data-from-login-with-amazon-on-alexa/#comments</comments>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Mon, 27 Mar 2017 20:21:54 +0000</pubDate>
				<category><![CDATA[Alexa]]></category>
		<category><![CDATA[IoT]]></category>
		<guid isPermaLink="false">/?p=921</guid>

					<description><![CDATA[In my previous post about How To Add OAUTH to your Alexa app [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>In my previous post about <a href="/2016/12/howto-add-oauth-to-your-alexa-smart-home-skill-in-10-minutes/">How To Add OAUTH to your Alexa app in 10 minutes</a> a couple of people commented that they couldn&#8217;t actually access the users information once they had linked their account.  I didn&#8217;t actually try and access any of the user information because the only user of my skill is me, and I already know my name and email address.  Nevertheless, I had a quick play with it over the weekend and here&#8217;s a simple skill to show you how to access the user&#8217;s profile information from a Python skill running in AWS Lambda.</p>
<p>First of all you need to make sure your skill is set up to use Login With Amazon.  I&#8217;ve covered this for Smart Home skills <a href="/2016/12/howto-add-oauth-to-your-alexa-smart-home-skill-in-10-minutes/">here</a> but it works just the same for normal skills.</p>
<p>You also need to make sure your skill is configured to use the scopes &#8220;<strong>profile</strong>&#8221; and &#8220;<strong>postal_code</strong>&#8220;.  This is done in the Configuration tab in the developer console for your skill:</p>
<p><a href="http://whizzy.org/wp-content/uploads/2017/03/scopes.png"><img loading="lazy" class="aligncenter size-full wp-image-922" src="http://whizzy.org/wp-content/uploads/2017/03/scopes.png" alt="" width="891" height="632" srcset="/wp-content/uploads/2017/03/scopes.png 891w, /wp-content/uploads/2017/03/scopes-300x213.png 300w, /wp-content/uploads/2017/03/scopes-768x545.png 768w" sizes="(max-width: 891px) 100vw, 891px" /></a></p>
<p>The Interaction Model for this skill is as follows:</p>
<pre>{
  "intents": [
    {
      "intent": "AMAZON.HelpIntent"
    },
    {
      "intent": "AMAZON.CancelIntent"
    },
    {
      "intent": "AMAZON.StopIntent"
    },
    {
      "slots": [
        {
          "name": "Options",
          "type": "Options"
        }
      ],
      "intent": "GreetIntent"
    }
  ]
}
</pre>
<p>The Custom Slot type &#8220;Options&#8221; is:</p>
<pre>First name
Last name
Post code
email address
user id</pre>
<p>And the Sample Utterances are:</p>
<pre>GreetIntent Tell me my {Options}
GreetIntent What is my {Options}</pre>
<p>And here&#8217;s the code (also on <a href="https://github.com/8none1/AlexaGreeter/blob/master/lambda_function.py">GitHub here</a>):</p>
<pre>#!/usr/bin/python

import requests

def build_speechlet_response(title, output, reprompt_text, should_end_session):
    return {
        'outputSpeech': {
            'type': 'PlainText',
            'text': output
        },
        'card': {
            'type': 'Simple',
            'title': "Greeter",
            'content': output
        },
        'reprompt': {
            'outputSpeech': {
                'type': 'PlainText',
                'text': reprompt_text
            }
        },
        'shouldEndSession': should_end_session
    }


def build_response(session_attributes, speechlet_response):
    return {
        'version': '1.0',
        'sessionAttributes': session_attributes,
        'response': speechlet_response
    }
    

def get_user_info(access_token):
    #print access_token
    amazonProfileURL = 'https://api.amazon.com/user/profile?access_token='
    r = requests.get(url=amazonProfileURL+access_token)
    if r.status_code == 200:
        return r.json()
    else:
        return False

def handle_end():
    return build_response({}, build_speechlet_response("Session ended", "Goodbye!", "", True))

def launch_request(access_token):
    session_attributes = {}
    card_title = "Welcome"
    if access_token is None:
        speech_output = "Your user details are not available at this time.  Have you completed account linking via the Alexa app?"
        reprompt_text = ""
        should_end_session = True
    else:
        user_details = get_user_info(access_token)
        if user_details is None:
            speech_output = "There was a problem getting your user details."
            should_end_sesion = True
        else:
            print user_details
            speech_output = "Hello "+user_details['name'].split(" ")[0]+"!  I know all about you now.  We can be friends!"
            reprompt_text = "What can I tell you about your user information?  First name, last name, email address or postcode?"
            should_end_session = False
    return build_response(session_attributes, build_speechlet_response(
        card_title, speech_output, reprompt_text, should_end_session))

def intent_request(intent_request, access_token):
    intent = intent_request['intent']
    intent_name = intent['name']
    
    if intent_name == "GreetIntent":           
        if access_token is not None:
            user_details = get_user_info(access_token)
            if user_details is None:
                query_type = False
            else:
                query_type = intent['slots']['Options']['value']
        else:
            return handle_end()
        
        if query_type == "post code":
            speech_output = "Your post code is "+user_details['postal_code']+"."
        elif query_type == "first name":
            speech_output = "Your first name is "+user_details['name'].split(" ")[0]+"."
        elif query_type == "last name":
            speech_output = "Your last name is "+user_details['name'].split(" ")[1]+"."
        elif query_type == "email address":
            speech_output = "Your email address is "+user_details['email']+"."
        elif query_type == "user id":
            speech_output = "Your user id is "+user_details['user_id']+"."
        else:
            speech_output = "Something went wrong.  Goodbye."
        card_title = "What I know about you"
        return build_response({}, build_speechlet_response(card_title, speech_output, None, True))
        
    if intent_name == "AMAZON.HelpIntent":
        print "Help intent"
        card_title = "No help available!"
        speech_output = "Sorry, I can't help you."
        return build_response({}, build_speechlet_response(card_title, speech_output, None, True))
        
    if intent_name == "AMAZON.CancelIntent" or intent_name == "AMAZON.StopIntent":
        card_title = "Session Ended"
        speech_output = "Good bye!"
        return build_response({}, build_speechlet_response(card_title, speech_output, None, True))
    


def lambda_handler(event, context):
    print event
    try:
        access_token = event['context']['System']['user']['accessToken']
    except:
        access_token = None
    if event['request']['type'] == "LaunchRequest":
        return launch_request(access_token)
    elif event['request']['type'] == "IntentRequest":
        return intent_request(event['request'],access_token)
</pre>
<p>The important part is:</p>
<pre>event['context']['System']['user']['accessToken']</pre>
<p>Once that is available to your Lambda script then you know that the user has done the OAUTH account linking, and then you can query the Amazon APIs for the user&#8217;s info.</p>
<p>I&#8217;m not proud of this code, so I will tidy it up in to a better demo at some point and update this post accordingly.</p>
<p>Here&#8217;s a quick video of what it does:</p>
<p><iframe loading="lazy" width="770" height="433" src="https://www.youtube.com/embed/ll7XEvzdetY?feature=oembed" frameborder="0" allowfullscreen></iframe></p>
]]></content:encoded>
					
					<wfw:commentRss>/2017/03/27/retrieving-user-profile-data-from-login-with-amazon-on-alexa/feed/</wfw:commentRss>
			<slash:comments>7</slash:comments>
		
		
			</item>
		<item>
		<title>Cisco 7941, Asterisk and SIP</title>
		<link>/2017/02/23/cisco-7941-asterisk-and-sip/</link>
					<comments>/2017/02/23/cisco-7941-asterisk-and-sip/#comments</comments>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Thu, 23 Feb 2017 23:43:31 +0000</pubDate>
				<category><![CDATA[asterisk]]></category>
		<category><![CDATA[Making the world a better place]]></category>
		<category><![CDATA[RaspberryPi]]></category>
		<guid isPermaLink="false">/?p=882</guid>

					<description><![CDATA[Edit: I heard that Cisco have now removed the SIP firmware from their [&#8230;]]]></description>
										<content:encoded><![CDATA[<p style="text-align: left;">Edit: I heard that Cisco have now removed the SIP firmware from their site.  Someone seems to have hosted the files here: <a href="http://s000.tinyupload.com/index.php?file_id=44134296078826321023">http://s000.tinyupload.com/index.php?file_id=44134296078826321023</a></p>
<p>Edit 2: Looks like the tinyupload file has gone missing too.  Try this one:<br />
<a href="https://drive.google.com/file/d/1EBJ-s9TIMKM0JVmZFWRk2bKeGxR9srFv">https://drive.google.com/file/d/1EBJ-s9TIMKM0JVmZFWRk2bKeGxR9srFv</a></p>
<p>I got a Cisco 7941 off eBay.  This is a phone which was £400 when new (some time around 2004) but can now be picked up for about £10.  These phones went End Of Sale in January 2010, so even if mine was one of the last phones to roll off the production line it&#8217;s still about 7 years old but it&#8217;s still working perfectly.  A testament to the good build quality of these phones, and perhaps the previous owner&#8217;s careful handling.</p>
<p><img loading="lazy" class="alignnone wp-image-959 size-full" src="/wp-content/uploads/2018/08/7941.jpg" alt="" width="440" height="391" srcset="/wp-content/uploads/2018/08/7941.jpg 440w, /wp-content/uploads/2018/08/7941-300x267.jpg 300w" sizes="(max-width: 440px) 100vw, 440px" /></p>
<p>Since these devices are no longer supported many companies will be getting rid of them (or probably already have) so there should be some bargains to be had for phone geeks.</p>
<p><em><strong>Q</strong></em>: Does the Cisco 7941 work with Asterisk?<br />
<em><strong>A</strong></em>: Yes.  You need to load the SIP firmware (the focus of this post) or chan-sccp (out of scope for this post but I&#8217;ll check it out at some point).</p>
<p><em><strong>Q</strong></em>: Does the Cisco 7941 work with SIP?<br />
<em><strong>A</strong></em>: Yes.  You need to flash the correct firmware though.</p>
<p><em><strong>Q</strong></em>: Is it really hard to get working?<br />
<em><strong>A</strong></em>: No.  If you&#8217;re comfortable with Linux and a few command line tools.  And assuming you already have Asterisk set up.</p>
<p><em><strong>Q</strong></em>: Is a lot of the information on the web about how to set up the 7941 wrong?<br />
<em><strong>A</strong></em>: Yes.  There is a lot of confusion about config files (the 7940 and 7941 use different ones).</p>
<p><em><strong>Q</strong></em>: Will you tell us how you got your phone to work?<br />
<em><strong>A</strong></em>: Yes!  However &#8211; this is what works for me.  You will need to tweak the config in places.</p>
<p>The steps to getting this phone working as a SIP extension on Asterisk on Ubuntu / Raspberry Pi:</p>
<ol>
<li><a href="#tftp">Set up a TFTP server</a></li>
<li><a href="#download">Download the SIP firmware from Cisco</a></li>
<li><a href="#flash">Flash the phone with the firmware via the TFTP server</a></li>
<li><a href="#asterisk">Configure the SIP extension in Asterisk</a></li>
<li><a href="#config">Write the config files for the phone and upload them via the TFTP server</a></li>
<li><a href="#call">Make a call!</a></li>
<li><a href="#extras">Optional Extras</a>
<ol>
<li><a href="#dialplan">Dial plan</a></li>
<li><a href="#ringtones">Ring tones</a></li>
<li><a href="#dialtones">Dial tones</a></li>
<li><a href="#wallpaper">Wallpaper</a></li>
<li><a href="#directory">Telephone Directory</a></li>
</ol>
</li>
<li><a href="#tip">Final Tip</a></li>
</ol>
<h2 id="tftp">Set up a TFTP Server</h2>
<p>The phone will download it&#8217;s firmware and config via TFTP.  It needs to download it&#8217;s config on every boot, so you will always need a TFTP server running.  I think that if the TFTP server is unavailable it will just use the previous config, so it&#8217;s possible that you can get away without it, but I haven&#8217;t tried.  My recommendation is that you install <a href="http://www.thekelleys.org.uk/dnsmasq/doc.html">dnsmasq</a>.  It&#8217;s a small and full featured DNS server which also includes a DHCP &amp; TFTP server which are easy to configure and it&#8217;s almost certainly packaged for your distro.  You should also (temporarily) disable any other DHCP servers on your local network so that dnsmasq is the only thing offering DHCP addresses.  This will simplify the process of getting the phone to find the TFTP server, since with dnsmasq it will all be automatic.  If you later re-enable your original DHCP server, say on your router, then you will need to configure it to give out the address of the dnsmasq TFTP server and disable DHCP on dnsmasq.  In my opinion, if you&#8217;re going to be running a Cisco IP phone on your network you&#8217;d be better off moving all DHCP to dnsmasq.</p>
<p>The full configuration of dnsmasq it&#8217;s out of scope for this doc, but in a nutshell you need these in your dnsmasq config:</p>
<ul>
<li>Set up a DHCP range</li>
</ul>
<pre style="padding-left: 90px;">dhcp-range=192.168.1.1,192.168.1.100,24h</pre>
<ul>
<li>Enable the TFTP server</li>
</ul>
<pre style="padding-left: 90px;">enable-tftp</pre>
<ul>
<li>Set the TFTP path</li>
</ul>
<pre style="padding-left: 90px;">tftp-root=/home/&lt;your user&gt;/tftp  (or whatever works for you)
</pre>
<h2 id="download">Download the SIP Firmware from Cisco</h2>
<p>Usually Cisco require a valid support contract before you can download anything useful from their website, but it seems that since these phones are now out of support they have offered up the firmware free of charge.  You do still need to register an account to download the files.  At the time of writing the latest version is <strong>9.4.2 SR 3</strong> dated 14th February 2017 &#8211; so bang up to date, even though these phones are end-of-life.  Bizarre, but good for us.  Thanks Cisco!</p>
<p>Go here: <a href="https://software.cisco.com/download/type.html?mdfid=280083379&amp;catid=280789323">https://software.cisco.com/download/type.html?mdfid=280083379&amp;catid=280789323</a></p>
<p>Follow the link to the SIP software.</p>
<p>You want to download the &#8220;SIP firmware files only&#8221;</p>
<p>Unzip that file into the root of your TFTP server (the location you set in the previous step).  You should have 8 files in there:</p>
<pre>apps41.9-4-2ES26.sbn
dsp41.9-4-2ES26.sbn
term41.default.loads
cnu41.9-4-2ES26.sbn
jar41sip.9-4-2ES26.sbn
term61.default.loads
cvm41sip.9-4-2ES26.sbn
SIP41.9-4-2SR3-1S.loads</pre>
<p>This is everything you need to reflash your phone to the latest SIP firmware.  Now you need to get the phone to reboot in to firmware download mode.</p>
<h2 id="flash">Flash the phone with the firmware via the TFTP server</h2>
<ol>
<li>Unplug the phone from the power.  Make sure that the network cable is still connected (unless you&#8217;re using using PoE).</li>
<li>Plug the power back in and hold down the <strong>#</strong> key</li>
<li>Eventually you will see the &#8220;line&#8221; lights start to flash orange.  It might take a couple of minutes to get to this stage, don&#8217;t give up, just keep holding down #</li>
<li>When the line lights are flashing type <strong>123456789*0#</strong>  This will start firmware download mode.</li>
<li>The screen will go black for a moment and then go through the process of getting an IP address and connecting to the TFTP server</li>
<li>Once connected to the TFTP server the software download will start</li>
<li>The phone will reboot once download is complete and present you with an &#8220;Unprovisioned&#8221; message on the screen.  This is good news!  The phone firmware has now been updated.</li>
</ol>
<p>I put together a video showing this process.  It&#8217;s not very interesting but it will give you an idea of what to expect.  The actual downloading of the firmware section has been sped up 3X.</p>
<p><iframe loading="lazy" title="How to start firmware download mode on your Cisco 7941" width="770" height="433" src="https://www.youtube.com/embed/oN63nfnC-sA?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></p>
<h2 id="asterisk">Configure the SIP extension in Asterisk</h2>
<p>Now you need to configure the SIP extension in Asterisk.  Do this as per any other SIP extension, but bear this important piece of information in mind:  The Cisco 7941 can only deal with 8 character passwords, so keep your SIP authentication secret to 8 characters.</p>
<p>While you&#8217;re in Asterisk configuration mode, take a moment to note down these bits of information as well (in Advanced SIP settings in FreePBX):</p>
<ul>
<li>RTP Port range, start and end.</li>
<li>Bind Port (probably 5060)</li>
</ul>
<h2 id="config">Write the config files for the phone and upload them via the TFTP server</h2>
<p>Please take the time to read this section fully,  this is the part that is most troublesome.  The Cisco 7941 is very picky about it&#8217;s config file and even a small mistake will stop the phone from working.  These settings are specific to the 79&#215;1 series of phones running at least version 8.x of the firmware.  If your phone is not a 79&#215;1 and/or is not running v9.x.x of the firmware then these settings are not for you.</p>
<p>Once the phone has loaded it&#8217;s firmware and booted, it will go looking for a file called SEP&lt;PHONE MAC ADDRESS&gt;.cnf.xml.  So if the MAC address of your phone is 11:22:33:44:55:66 then the config file needs to be named <strong>SEP112233445566.cnf.xml</strong>.  This file needs to be in the root of your TFTP server.</p>
<p>You will see mention of a file called XMLDefault.cnf.xml.  If you&#8217;ve only got a few phones, don&#8217;t worry about this, you don&#8217;t need it.</p>
<p>So here is a config file which is about as minimal as I can make it:</p>
<pre>&lt;device&gt;
    &lt;deviceProtocol&gt;SIP&lt;/deviceProtocol&gt;
    &lt;sshUserId&gt;cisco&lt;/sshUserId&gt;
    &lt;sshPassword&gt;cisco&lt;/sshPassword&gt;
    &lt;ipAddressMode&gt;0&lt;/ipAddressMode&gt;

    &lt;devicePool&gt;
        &lt;dateTimeSetting&gt;
            &lt;dateTemplate&gt;D/M/Ya&lt;/dateTemplate&gt;
            &lt;timeZone&gt;GMT Standard/Daylight Time&lt;/timeZone&gt;
            &lt;ntps&gt;
                &lt;ntp&gt;
                    &lt;name&gt;<strong>#IP ADDRESS OF AN NTP SERVER#</strong>&lt;/name&gt;
                    &lt;ntpMode&gt;Unicast&lt;/ntpMode&gt;
                &lt;/ntp&gt;
            &lt;/ntps&gt;
        &lt;/dateTimeSetting&gt;

        &lt;callManagerGroup&gt;
            &lt;members&gt;
                &lt;member priority="0"&gt;
                    &lt;callManager&gt;
                        &lt;ports&gt;
                            &lt;ethernetPhonePort&gt;2000&lt;/ethernetPhonePort&gt;
                            &lt;sipPort&gt;<strong>#SIP PORT NUMBER FROM YOUR ASTERISK SERVER#</strong>&lt;/sipPort&gt;
                        &lt;/ports&gt;
                        &lt;processNodeName&gt;<strong>#IP ADDRESS OF YOUR ASTERISK SERVER#</strong>&lt;/processNodeName&gt;
                    &lt;/callManager&gt;
                &lt;/member&gt;
            &lt;/members&gt;
        &lt;/callManagerGroup&gt;
    &lt;/devicePool&gt;

    &lt;sipProfile&gt;
        &lt;sipProxies&gt;
            &lt;registerWithProxy&gt;true&lt;/registerWithProxy&gt;
        &lt;/sipProxies&gt;
        &lt;sipCallFeatures&gt;
            &lt;cnfJoinEnabled&gt;true&lt;/cnfJoinEnabled&gt;
            &lt;rfc2543Hold&gt;false&lt;/rfc2543Hold&gt;
            &lt;callHoldRingback&gt;2&lt;/callHoldRingback&gt;
            &lt;localCfwdEnable&gt;true&lt;/localCfwdEnable&gt;
            &lt;semiAttendedTransfer&gt;true&lt;/semiAttendedTransfer&gt;
            &lt;anonymousCallBlock&gt;2&lt;/anonymousCallBlock&gt;
            &lt;callerIdBlocking&gt;2&lt;/callerIdBlocking&gt;
            &lt;dndControl&gt;0&lt;/dndControl&gt;
            &lt;remoteCcEnable&gt;true&lt;/remoteCcEnable&gt;
        &lt;/sipCallFeatures&gt;

        &lt;sipStack&gt;
            &lt;sipInviteRetx&gt;6&lt;/sipInviteRetx&gt;
            &lt;sipRetx&gt;10&lt;/sipRetx&gt;
            &lt;timerInviteExpires&gt;180&lt;/timerInviteExpires&gt;
            &lt;timerRegisterExpires&gt;3600&lt;/timerRegisterExpires&gt;
            &lt;timerRegisterDelta&gt;5&lt;/timerRegisterDelta&gt;
            &lt;timerKeepAliveExpires&gt;120&lt;/timerKeepAliveExpires&gt;
            &lt;timerSubscribeExpires&gt;120&lt;/timerSubscribeExpires&gt;
            &lt;timerSubscribeDelta&gt;5&lt;/timerSubscribeDelta&gt;
            &lt;timerT1&gt;500&lt;/timerT1&gt;
            &lt;timerT2&gt;4000&lt;/timerT2&gt;
            &lt;maxRedirects&gt;70&lt;/maxRedirects&gt;
            &lt;remotePartyID&gt;true&lt;/remotePartyID&gt;
            &lt;userInfo&gt;None&lt;/userInfo&gt;
        &lt;/sipStack&gt;

        &lt;autoAnswerTimer&gt;1&lt;/autoAnswerTimer&gt;
        &lt;autoAnswerAltBehavior&gt;false&lt;/autoAnswerAltBehavior&gt;
        &lt;autoAnswerOverride&gt;true&lt;/autoAnswerOverride&gt;
        &lt;transferOnhookEnabled&gt;false&lt;/transferOnhookEnabled&gt;
        &lt;enableVad&gt;false&lt;/enableVad&gt;
        &lt;preferredCodec&gt;g711ulaw&lt;/preferredCodec&gt;
        &lt;dtmfAvtPayload&gt;101&lt;/dtmfAvtPayload&gt;
        &lt;dtmfDbLevel&gt;3&lt;/dtmfDbLevel&gt;
        &lt;dtmfOutofBand&gt;avt&lt;/dtmfOutofBand&gt;
        &lt;alwaysUsePrimeLine&gt;false&lt;/alwaysUsePrimeLine&gt;
        &lt;alwaysUsePrimeLineVoiceMail&gt;false&lt;/alwaysUsePrimeLineVoiceMail&gt;
        &lt;kpml&gt;3&lt;/kpml&gt;
        &lt;natEnabled&gt;false&lt;/natEnabled&gt;
        &lt;phoneLabel&gt;<strong>#PHONE NAME#</strong>&lt;/phoneLabel&gt;
        &lt;stutterMsgWaiting&gt;0&lt;/stutterMsgWaiting&gt;
        &lt;callStats&gt;false&lt;/callStats&gt;
        &lt;silentPeriodBetweenCallWaitingBursts&gt;10&lt;/silentPeriodBetweenCallWaitingBursts&gt;
        &lt;disableLocalSpeedDialConfig&gt;false&lt;/disableLocalSpeedDialConfig&gt;
        &lt;startMediaPort&gt;<strong>#RTP START PORT#</strong>&lt;/startMediaPort&gt;
        &lt;stopMediaPort&gt;<strong>#RTP END PORT#</strong>&lt;/stopMediaPort&gt;

        &lt;sipLines&gt;
            &lt;line button="1"&gt;
                &lt;featureID&gt;9&lt;/featureID&gt;
                &lt;featureLabel&gt;<strong>#EXT NUM#</strong>&lt;/featureLabel&gt;
                &lt;proxy&gt;USECALLMANAGER&lt;/proxy&gt;
                &lt;port&gt;<strong>#SIP PORT#</strong>&lt;/port&gt;
                &lt;name&gt;<strong>#EXT NUM#</strong>&lt;/name&gt;
                &lt;displayName&gt;<strong>#EXT NAME#</strong>&lt;/displayName&gt;
                &lt;autoAnswer&gt;
                    &lt;autoAnswerEnabled&gt;2&lt;/autoAnswerEnabled&gt;
                &lt;/autoAnswer&gt;
                &lt;callWaiting&gt;3&lt;/callWaiting&gt;
                &lt;authName&gt;<strong>#SIP AUTH NAME#</strong>&lt;/authName&gt;
                &lt;authPassword&gt;<strong>#8 CHAR PASSWORD#</strong>&lt;/authPassword&gt;
                &lt;sharedLine&gt;false&lt;/sharedLine&gt;
                &lt;messageWaitingLampPolicy&gt;1&lt;/messageWaitingLampPolicy&gt;
                &lt;messagesNumber&gt;<strong>#VM NUM#</strong>&lt;/messagesNumber&gt;
                &lt;ringSettingIdle&gt;4&lt;/ringSettingIdle&gt;
                &lt;ringSettingActive&gt;5&lt;/ringSettingActive&gt;
                &lt;contact&gt;<strong>#EXT NUM#</strong>&lt;/contact&gt;
                &lt;forwardCallInfoDisplay&gt;
                    &lt;callerName&gt;true&lt;/callerName&gt;
                    &lt;callerNumber&gt;true&lt;/callerNumber&gt;
                    &lt;redirectedNumber&gt;false&lt;/redirectedNumber&gt;
                    &lt;dialedNumber&gt;true&lt;/dialedNumber&gt;
                &lt;/forwardCallInfoDisplay&gt;
            &lt;/line&gt;

            &lt;line button="2"&gt;
                &lt;featureID&gt;9&lt;/featureID&gt;
                &lt;featureLabel&gt;<strong>#EXT NUM#</strong>&lt;/featureLabel&gt;
                &lt;proxy&gt;USECALLMANAGER&lt;/proxy&gt;
                &lt;port&gt;<strong>#SIP PORT#</strong>&lt;/port&gt;
                &lt;name&gt;<strong>#EXT NUM#</strong>&lt;/name&gt;
                &lt;displayName&gt;<strong>#EXT NUM#</strong>&lt;/displayName&gt;
                &lt;autoAnswer&gt;
                    &lt;autoAnswerEnabled&gt;2&lt;/autoAnswerEnabled&gt;
                &lt;/autoAnswer&gt;
                &lt;callWaiting&gt;3&lt;/callWaiting&gt;
                &lt;authName&gt;<strong>#SIP AUTH NAME#</strong>&lt;/authName&gt;
                &lt;authPassword&gt;<strong>#8 CHAR PASSWORD#</strong>&lt;/authPassword&gt;
                &lt;sharedLine&gt;false&lt;/sharedLine&gt;
                &lt;messageWaitingLampPolicy&gt;1&lt;/messageWaitingLampPolicy&gt;
                &lt;messagesNumber&gt;<strong>#VM NUM#</strong>&lt;/messagesNumber&gt;
                &lt;ringSettingIdle&gt;4&lt;/ringSettingIdle&gt;
                &lt;ringSettingActive&gt;5&lt;/ringSettingActive&gt;
                &lt;contact&gt;<strong>#EXT NUM#</strong>&lt;/contact&gt;
                &lt;forwardCallInfoDisplay&gt;
                    &lt;callerName&gt;true&lt;/callerName&gt;
                    &lt;callerNumber&gt;true&lt;/callerNumber&gt;
                    &lt;redirectedNumber&gt;false&lt;/redirectedNumber&gt;
                    &lt;dialedNumber&gt;true&lt;/dialedNumber&gt;
                &lt;/forwardCallInfoDisplay&gt;
            &lt;/line&gt;
        &lt;/sipLines&gt;

        &lt;voipControlPort&gt;<strong>#SIP PORT#</strong>&lt;/voipControlPort&gt;
        &lt;dscpForAudio&gt;184&lt;/dscpForAudio&gt;
        &lt;ringSettingBusyStationPolicy&gt;0&lt;/ringSettingBusyStationPolicy&gt;
        &lt;dialTemplate&gt;dialplan.xml&lt;/dialTemplate&gt;
    &lt;/sipProfile&gt;

    &lt;commonProfile&gt;
        &lt;phonePassword&gt;&lt;/phonePassword&gt;
        &lt;backgroundImageAccess&gt;true&lt;/backgroundImageAccess&gt;
        &lt;callLogBlfEnabled&gt;1&lt;/callLogBlfEnabled&gt;
    &lt;/commonProfile&gt;

    &lt;loadInformation&gt;SIP41.9-4-2SR3-1S&lt;/loadInformation&gt;
    &lt;vendorConfig&gt;
        &lt;disableSpeaker&gt;false&lt;/disableSpeaker&gt;
        &lt;disableSpeakerAndHeadset&gt;false&lt;/disableSpeakerAndHeadset&gt;
        &lt;pcPort&gt;0&lt;/pcPort&gt;
        &lt;settingsAccess&gt;1&lt;/settingsAccess&gt;
        &lt;garp&gt;0&lt;/garp&gt;
        &lt;voiceVlanAccess&gt;0&lt;/voiceVlanAccess&gt;
        &lt;videoCapability&gt;0&lt;/videoCapability&gt;
        &lt;autoSelectLineEnable&gt;0&lt;/autoSelectLineEnable&gt;
        &lt;webAccess&gt;0&lt;/webAccess&gt;
        &lt;spanToPCPort&gt;1&lt;/spanToPCPort&gt;
        &lt;loggingDisplay&gt;1&lt;/loggingDisplay&gt;
        &lt;loadServer&gt;&lt;/loadServer&gt;
        &lt;sshAccess&gt;0&lt;/sshAccess&gt;
    &lt;/vendorConfig&gt;

    &lt;versionStamp&gt;001&lt;/versionStamp&gt;
    &lt;networkLocale&gt;United_Kingdom&lt;/networkLocale&gt;
    &lt;networkLocaleInfo&gt;
        &lt;name&gt;United_Kingdom&lt;/name&gt;
        &lt;uid&gt;64&lt;/uid&gt;
        &lt;version&gt;1.0.0.0-4&lt;/version&gt; 
    &lt;/networkLocaleInfo&gt;

    &lt;deviceSecurityMode&gt;1&lt;/deviceSecurityMode&gt;
    &lt;authenticationURL&gt;&lt;/authenticationURL&gt;
    &lt;servicesURL&gt;&lt;/servicesURL&gt;
    &lt;transportLayerProtocol&gt;2&lt;/transportLayerProtocol&gt;
    &lt;certHash&gt;&lt;/certHash&gt;
    &lt;encrConfig&gt;false&lt;/encrConfig&gt;
    &lt;dialToneSetting&gt;2&lt;/dialToneSetting&gt;
&lt;/device&gt;

</pre>
<p>Copy and paste this into a text editor and search and replace the following:</p>
<ul>
<li>#IP ADDRESS OF AN NTP SERVER#  &#8211;  with  &#8211;  the IP address of an NTP server</li>
<li>#SIP PORT FROM YOUR ASTERISK SERVER#  &#8211;  with  &#8211;  the SIP port of your asterisk server is listening on.  Probably 5060</li>
<li>#IP ADDRESS OF YOUR ASTERISK SERVER#  &#8211;  with  &#8211;  the IP address of your Asterisk server</li>
<li>#PHONE NAME#  &#8211;  with  &#8211;  the text you want to appear at the top right of the phone screen</li>
<li>#RTP START PORT#  &#8211;  with  &#8211;  the RTP port range start from the previous stage</li>
<li>#RTP END PORT#&#8217;  &#8211;  with  &#8211;  the RTP port range end from the the previous stage</li>
<li>#EXT NUM#  &#8211;  with  &#8211;  the Asterisk extension number as configured in the previous stage</li>
<li>#SIP PORT#  &#8211;  with  &#8211;  the SIP port of your Asterisk server.  Probably 5060</li>
<li>#EXT NAME#  &#8211;  with  &#8211;  the name you want to give this extension</li>
<li>#SIP AUTH NAME#  &#8211;  with  &#8211;  the username for the SIP extension as configured in Asterisk</li>
<li>#8 CHAR PASSWORD#  &#8211;  with  &#8211;  the password for the SIP extension as configured in Asterisk</li>
<li>#VM NUM#  &#8211;  with  &#8211;  the number you dial for Voicemail.  Probably *98</li>
</ul>
<p>Note that this config file has two lines configured.  If you just blindly search and replace you&#8217;ll end up with two extensions configured the same.</p>
<p>Some comments on what some of the XML tags do:</p>
<ul>
<li>ipAddressMode &#8211; 0 is IP v4 only. But this seems to have little effect.</li>
<li>registerWithProxy &#8211; true &#8211; Registers the device with Asterisk, this allows incoming calls to be sent to the phone.  If you&#8217;re getting &#8220;Unregistered&#8221; message on the screen, check you have this set.</li>
<li>featureId &#8211; 9 is SIP</li>
<li>autoAnswerEnabled &#8211; 2 &#8211; 2 seems to be &#8220;off&#8221;</li>
<li>webAccess &#8211; 0 &#8211; 0 is on (?!)</li>
<li>sshAccess -0 &#8211; ditto</li>
<li>versionStamp &#8211; bump this up every time you make a change.  Something like YYYMMDD001..2..3 etc</li>
<li>networkLocale &#8211; United_Kingdom &#8211; sets the tones to UK, see the optional extras section for more info.</li>
<li>transportLayerProtocol &#8211; 2 is UDP, 1 is TCP</li>
<li>dialToneSettings &#8211; 2 is &#8220;always use internal dialtone&#8221;.  See option extras for more info.</li>
</ul>
<p>Edit this file as necessary and then save it to the root of your TFTP server with the filename: <strong>SEP&lt;MAC&gt;.cnf.xml.  </strong>If your phone MAC address was aa:bb:33:44:55:66 then the filename would be: <strong>SEPAABB33445566.cnf.xml</strong>  Note that it&#8217;s case sensitive, letters in the MAC address should be in upper case the extensions should be in lowercase.  You can get the MAC address for the phone from the syslog on your dnsmasq server.</p>
<p>If your phone is still in &#8220;Unprovisioned&#8221; mode it will have been asking for this config file repeatedly.  Once you save the file you should see the phone reboot shortly afterwards.  It may download the firmware again for some reason, just leave it to get on with it.</p>
<h2 id="call">Make a call!</h2>
<p>If everything has worked you should see your extension listed on the right hand side of the screen near the buttons, and the name of the phone should appear at the top of the screen.  If the icon next to the line buttons is that of a phone without an x through it, then you&#8217;re probably good to go!  Press the line button and see if you get a dial tone.  If not, then check the phone logs:</p>
<ul>
<li>Press Settings</li>
<li>Press 6</li>
<li>Press 1</li>
</ul>
<p>From these logs you should be able to tell if the phone has loaded your config correctly.  Errors about &#8220;updating locale&#8221; or &#8220;no trust list installed&#8221; can be ignored.  If there is a problem with the config file itself a generic error will be listed here.  If the phone won&#8217;t load the config file the most likely reason is that there is a typo in your XML file.  Good luck finding it.  You can SSH in to the phone to get more detailed logs and debugging information, but I haven&#8217;t tried this yet.  Google is your friend.</p>
<h2 id="extras">Optional Extras</h2>
<h3 id="dialplan">Dial plan</h3>
<p>The dial plan tells the phone how to process the digits you type and when to start sending the call.  Without a dial plan the phone simply waits a period of time for you to stop typing numbers before it decides you&#8217;re done and starts the call.  By using a dial plan you can reduce the amount of time spent waiting after you&#8217;ve finished keying in the number.  Here&#8217;s an example plan I&#8217;ve edited based on this post on Phil Lavin&#8217;s blog (Thanks Phil!) <a href="http://phil.lavin.me.uk/2012/11/united-kingdom-dial-plan-xml-for-cisco-phones/">http://phil.lavin.me.uk/2012/11/united-kingdom-dial-plan-xml-for-cisco-phones/</a></p>
<pre>&lt;DIALTEMPLATE&gt;
    &lt;TEMPLATE MATCH="999" Timeout="0"/&gt; &lt;!-- Emergency --&gt;
    &lt;TEMPLATE MATCH="112" Timeout="0"/&gt; &lt;!-- Emergency --&gt;
    &lt;TEMPLATE MATCH="0500......" Timeout="0"/&gt; &lt;!-- Apparently 0500 is always 10 digits --&gt;
    &lt;TEMPLATE MATCH="0800......" Timeout="0"/&gt; &lt;!-- Apparently 0800 is always 10 digits --&gt;
    &lt;TEMPLATE MATCH="00*" Timeout="5"/&gt; &lt;!-- International, 00 prefixed. No fixed length --&gt;
    &lt;TEMPLATE MATCH="0.........." Timeout="0"/&gt; &lt;!-- UK 11 digit, 0 prefixed --&gt;
    &lt;TEMPLATE MATCH="26...." Timeout="0"/&gt; &lt;!-- My local STD numbers start 26 --&gt;
    &lt;TEMPLATE MATCH="\*.." Timeout="0"/&gt; &lt;!-- Asterisk *.. codes --&gt;
    &lt;TEMPLATE MATCH="\*98...." Timeout="0"/&gt; &lt;!-- Asterisk direct VM access *981234--&gt;
    &lt;TEMPLATE MATCH="1..." Timeout="0"/&gt; &lt;!-- Internal numbers --&gt;
    &lt;TEMPLATE MATCH="2..." Timeout="0"/&gt;  &lt;!-- Internal numbers --&gt;
    &lt;TEMPLATE MATCH="*" Timeout="5"/&gt; &lt;!-- Anything else --&gt;
&lt;/DIALTEMPLATE&gt;</pre>
<p>Save this to the root of your TFTP server, named &#8220;<strong>dialplan.xml</strong>&#8221; (lowercase).</p>
<h3 id="ringtones">Ring tones</h3>
<p>Everyone likes novelty ringtones.  You can find plenty of ringtones in a format which is compatible with your phone (raw format, 8000 Hz sample rate, 8 bit, ulaw, max 2 seconds).  These files need to be placed in to the root of your TFTP server.  I tried putting them in a sub-directory but it didn&#8217;t work.  Then you need to create a file called &#8220;ringlist.xml&#8221; also in the root of the server.  The format of this file is:</p>
<pre>&lt;CiscoIPPhoneRingList&gt;
    &lt;Ring&gt;
        &lt;DisplayName&gt;#<strong>DISPLAY TEXT</strong>#&lt;/DisplayName&gt;
        &lt;FileName&gt;#<strong>FILENAME</strong>#&lt;/FileName&gt;
    &lt;/Ring&gt;
    &lt;Ring&gt;
        &lt;DisplayName&gt;#<strong>DISPLAY TEXT</strong>#&lt;/DisplayName&gt;
        &lt;FileName&gt;#<strong>FILENAME</strong>#&lt;/FileName&gt;
    &lt;/Ring&gt;
&lt;/CiscoIPPhoneRingList&gt;</pre>
<p>Filenames are case sensitive.  Once you&#8217;ve save this file, copy it to &#8220;<strong>distinctiveringlist.xml</strong>&#8221; as well.  This will allow you to set ring tones for the default ringer and different rings for each line.</p>
<h3 id="dialtones">Dial tones</h3>
<p>By default the 7941 will have a psuedo North American dial tone.  This is annoyingly shrill (yes, it is).  By specifying a NetworkLocale in the phone config we can get it to load a different set of informational tones from a file stored in (per the example XML above) United_Kingdom.  In the root of the TFTP server create a directory called <strong>United_Kingdom</strong>.  In this directory you need to create a file called <strong>g3-tones.xml</strong>.  Bizarrely Cisco require you to have a support contract in order to download the correct tones settings for your country, despite giving the phone firmware away for free.  Go figure.  So this means I&#8217;m not going to paste the XML here.  If you search hard enough you&#8217;ll find an example g3-tones.xml file you can use as a base.  In our phone configuration above we told the phone to always use the internal dialing tone, so this means we only need to change the <strong>idial</strong> section of the tones file.  The magic numbers are:</p>
<ul>
<li>31538</li>
<li>-780</li>
<li>30831</li>
<li>-973</li>
</ul>
<h3 id="wallpaper">Wallpaper</h3>
<p>The phone comes with a single default wallpaper with horizontal lines on it.  This is easily replaced by your own designs with a simple PNG.   Create a directory in the root of the TFTP server called <strong>Desktops</strong>.  In here create another directory called <strong>320x196x4</strong>.</p>
<p>In to this directory you need to place a &#8220;List.xml&#8221; file:</p>
<pre>&lt;CiscoIPPhoneImageList&gt;
    &lt;ImageItem Image="TFTP:Desktops/320x196x4/ubuntu-tn.png"
       URL="TFTP:Desktops/320x196x4/ubuntu.png"/&gt;
&lt;/CiscoIPPhoneImageList&gt;</pre>
<p>The &#8220;<strong>-tn</strong>&#8221; in the file is a smaller thumbnail version of the larger image.  The PNGs need to be sized exactly 320&#215;196 for the large and 80&#215;49 for the thumbnail.  Here&#8217;s something to get you started:</p>
<p><a href="http://whizzy.org/wp-content/uploads/2017/02/Ubuntu-Logo-tn.png"><img loading="lazy" class="aligncenter size-full wp-image-890" src="http://whizzy.org/wp-content/uploads/2017/02/Ubuntu-Logo-tn.png" alt="" width="80" height="49" /></a></p>
<p><a href="http://whizzy.org/wp-content/uploads/2017/02/Ubuntu-Logo.png"><img loading="lazy" class="size-full wp-image-889 aligncenter" src="http://whizzy.org/wp-content/uploads/2017/02/Ubuntu-Logo.png" alt="" width="320" height="196" srcset="/wp-content/uploads/2017/02/Ubuntu-Logo.png 320w, /wp-content/uploads/2017/02/Ubuntu-Logo-300x184.png 300w" sizes="(max-width: 320px) 100vw, 320px" /></a></p>
<h3 id="directory">Telephone Directory</h3>
<p>You will have noticed that the phone has a &#8220;Directories&#8221; button and a &#8220;Services&#8221; button.  I haven&#8217;t managed to add an extra phone book to the Directories button yet although I think it&#8217;s certainly possible, just that the XML file refuses to do anything.  However, I have got a phone directory working on the Services button.</p>
<p>In the main phone config file there is a tag for &#8220;servicesURL&#8221;.  Point this to a web server on your local network which will serve up an XML file.  For example:</p>
<pre> &lt;servicesURL&gt;http://192.168.1.1/phone/directory.xml&lt;/servicesURL&gt;</pre>
<p>Assuming you are using Apache 2 to serve that XML file (or it could equally be a CGI script which generates the XML dynamically from a database such as the FreePBX phone book) the format looks like this:</p>
<pre>&lt;CiscoIPPhoneDirectory&gt;
   &lt;Title&gt;Whizzy Towers&lt;/Title&gt;
   &lt;DirectoryEntry&gt;
       &lt;Telephone&gt;1500&lt;/Telephone&gt;
       &lt;Name&gt;Lenny&lt;/Name&gt;
   &lt;/DirectoryEntry&gt;
   &lt;DirectoryEntry&gt;
       &lt;Telephone&gt;1234&lt;/Telephone&gt;
       &lt;Name&gt;Speaking Clock&lt;/Name&gt;
   &lt;/DirectoryEntry&gt;
&lt;/CiscoIPPhoneDirectory&gt;</pre>
<p>Important note:  You must tell Apache to serve those files as type &#8220;<strong>text/xml</strong>&#8220;.  &#8220;<strong>application/xml</strong>&#8221; will not work.</p>
<p>You can do this via your CGI script, or if you want to serve a static file add something like this to your Apache config:</p>
<pre> &lt;Location /phone/&gt;
     ForceType text/xml
 &lt;/Location&gt;</pre>
<p>Inside your VirtualHost section.</p>
<h2 id="tip">Final Tip</h2>
<p>Watch /var/log/syslog on the machine running the TFTP server.  You&#8217;ll be able to see exactly what files the phone is asking for.  Bear in mind that it does ask for files it doesn&#8217;t strictly need, so don&#8217;t worry too much about file not found errors unless it&#8217;s one of the above.</p>
<p>Here&#8217;s a final video showing the boot up for a fully configured phone</p>
<p><iframe loading="lazy" title="Fully configured Cisco 7941 connecting to Asterisk via SIP" width="770" height="433" src="https://www.youtube.com/embed/QlLLzbD7pHM?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></p>
]]></content:encoded>
					
					<wfw:commentRss>/2017/02/23/cisco-7941-asterisk-and-sip/feed/</wfw:commentRss>
			<slash:comments>38</slash:comments>
		
		
			</item>
		<item>
		<title>HOWTO:  Add OAUTH to your Alexa Smart Home skill in 10 minutes</title>
		<link>/2016/12/05/howto-add-oauth-to-your-alexa-smart-home-skill-in-10-minutes/</link>
					<comments>/2016/12/05/howto-add-oauth-to-your-alexa-smart-home-skill-in-10-minutes/#comments</comments>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Mon, 05 Dec 2016 19:07:19 +0000</pubDate>
				<category><![CDATA[IoT]]></category>
		<guid isPermaLink="false">/?p=819</guid>

					<description><![CDATA[Alexa smart home skills require you to provide OAUTH2 so that users can [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Alexa smart home skills require you to provide <a href="https://oauth.net/2/">OAUTH2</a> so that users can authorise a skill to access the assumed cloud service powering their lightbulbs or any number of other pointlessly connected devices.  This makes sense since OAUTH2 is a standard and secure way to grant access for users from one system to the resources of another.  However, with this come a few caveats which are potential blockers for casual skill developers like me.  If you&#8217;re writing a skill for your own personal use, with no intention of adding it to the store, you still have to have a valid and recognised SSL certificate and a whole OAUTH2 server set up somewhere.</p>
<p>The SSL certificate is easy enough to implement, but it&#8217;s a bit of a faff (renewing Let&#8217;s Encrypt certs, or paying for cert which needs you to deal with the certificate authorities, send in scans of your passport and other tedious red tape) but &#8211; in my opinion anyway &#8211; setting up an OAUTH server is even more of a faff.  If only there was some way to avoid having to do either of these things&#8230;.</p>
<h2>Using &#8220;Login With Amazon&#8221; as your OAUTH provider</h2>
<p>Since you already have an Amazon account you can use &#8220;Login With Amazon&#8221; as your skill&#8217;s OAUTH server and your normal everyday Amazon account as your credentials.  You&#8217;re only sharing your Amazon account data with yourself, and even then we can restrict it to just your login ID.  You don&#8217;t actually need to do anything with the OAUTH token once it&#8217;s returned since you&#8217;re the only user.  I mean, you could if you wanted to, but this HOWTO assumes that you&#8217;re the only user and that you don&#8217;t care about that sort of thing.  We are also going to assume that you have already created the Lambda function and the smart home skill or are familiar with how to do that.  This is a bit tricky because you can&#8217;t test your smart home skill on a real device until you&#8217;ve implemented OAUTH, and you can&#8217;t complete the OAUTH set-up until you&#8217;ve got the IDs from your Lambda function and skill.  If you haven&#8217;t written your skill yet, just create a placeholder Lambda function and smart home skill to be going on with.</p>
<p>Much of this information is available from the official Amazon instructions available here:<a href="https://developer.amazon.com/public/community/post/Tx3CX1ETRZZ2NPC/Alexa-Account-Linking-5-Steps-to-Seamlessly-Link-Your-Alexa-Skill-with-Login-wit"> https://developer.amazon.com/public/community/post/Tx3CX1ETRZZ2NPC/Alexa-Account-Linking-5-Steps-to-Seamlessly-Link-Your-Alexa-Skill-with-Login-wit</a>. What follows is a rehash and slight reorganisation of that doc which is hopefully a bit easier to follow.</p>
<h3>1. Create a new Login With Amazon Security Profile</h3>
<p>From the Amazon Developer Site, go to Apps &amp; Services -&gt; Login With Amazon.  Or click <a href="https://developer.amazon.com/lwa/sp/overview.html">https://developer.amazon.com/lwa/sp/overview.html</a></p>
<p>Click &#8220;Create a New Security Profile&#8221;.  Fill out the form along these lines:</p>
<p><a href="wp-content/uploads/2016/12/Screenshot-from-2016-11-30-13-40-23.png"><img loading="lazy" class="aligncenter wp-image-823 size-large" src="wp-content/uploads/2016/12/Screenshot-from-2016-11-30-13-40-23-1024x468.png" alt="screenshot-from-2016-11-30-13-40-23" width="770" height="352" srcset="/wp-content/uploads/2016/12/Screenshot-from-2016-11-30-13-40-23-1024x468.png 1024w, /wp-content/uploads/2016/12/Screenshot-from-2016-11-30-13-40-23-300x137.png 300w, /wp-content/uploads/2016/12/Screenshot-from-2016-11-30-13-40-23-768x351.png 768w, /wp-content/uploads/2016/12/Screenshot-from-2016-11-30-13-40-23.png 1150w" sizes="(max-width: 770px) 100vw, 770px" /></a></p>
<p>and hit Save.</p>
<p>You should see a message along the lines of &#8220;Login with Amazon successfully enabled for Security Profile.&#8221;</p>
<p>Hover the mouse over the cog icon to the right of your new security profile and choose &#8220;Security Profile&#8221;.</p>
<p>Copy your &#8220;Client ID&#8221;  and &#8220;Client Secret&#8221; and paste it in to a notepad.  You&#8217;ll need this again shortly.</p>
<p><a href="wp-content/uploads/2016/12/clientid2.png"><img loading="lazy" class="aligncenter wp-image-825 size-large" src="wp-content/uploads/2016/12/clientid2-1024x526.png" alt="clientid2" width="770" height="396" srcset="/wp-content/uploads/2016/12/clientid2-1024x526.png 1024w, /wp-content/uploads/2016/12/clientid2-300x154.png 300w, /wp-content/uploads/2016/12/clientid2-768x395.png 768w, /wp-content/uploads/2016/12/clientid2.png 1158w" sizes="(max-width: 770px) 100vw, 770px" /></a></p>
<h3>2. Configure your skill to use Login With Amazon</h3>
<p>Back in the <a href="https://developer.amazon.com/edw/home.html#/">Developer Console</a>, navigate to the Configuration page for your skill.  (Click on your skill, then click on Configuration).  You need to enable &#8220;<strong>Account Linking</strong>&#8221; and this will then show the extra boxes discussed below.</p>
<p>In to the &#8220;<strong>Authorization URL</strong>&#8221; box you should put:</p>
<pre>https://www.amazon.com/ap/oa/?redirect_url=</pre>
<p>and then copy the Redirect URL from further down the page and append it to the end of the Authorization URL.  For example:</p>
<pre>https://www.amazon.com/ap/oa/?redirect_url=https://layla.amazon.com/api/skill/link/1234ABCD1234AB</pre>
<p><a href="wp-content/uploads/2016/12/authurl.png"><img loading="lazy" class="aligncenter wp-image-827 size-full" src="wp-content/uploads/2016/12/authurl.png" alt="authurl" width="801" height="775" srcset="/wp-content/uploads/2016/12/authurl.png 801w, /wp-content/uploads/2016/12/authurl-300x290.png 300w, /wp-content/uploads/2016/12/authurl-768x743.png 768w" sizes="(max-width: 801px) 100vw, 801px" /></a></p>
<p>As far as I can tell Layla is for UK/Europe and Pitangui is for the US.  Use the appropriate one for you.  Also, keep a <span style="text-decoration: underline;">note of the redirect URL</span> in your notepad, you will need this again later.</p>
<p>In to the &#8220;<strong>Client Id</strong>&#8221; box paste your client id from step 1.</p>
<p>You can leave &#8220;<strong>Domain List</strong>&#8221; blank for now.</p>
<p>For &#8220;<strong>Scope</strong>&#8221; I suggest you use:</p>
<pre>profile:user_id</pre>
<p>This will give your Alexa Skill access to a minimal amount of information about you from Amazon, in this case just a user_id.  That user ID is unique to your app so can&#8217;t be used by other apps or to identify that user elsewhere.  Since you don&#8217;t really have any customers for your skill, only you, there is no reason to provide access to any other information.</p>
<p>Further down the page you need to configure the <strong>Grant Type</strong>:</p>
<p><a href="wp-content/uploads/2016/12/granttype.png"><img loading="lazy" class="aligncenter wp-image-828 size-full" src="wp-content/uploads/2016/12/granttype.png" alt="granttype" width="842" height="534" srcset="/wp-content/uploads/2016/12/granttype.png 842w, /wp-content/uploads/2016/12/granttype-300x190.png 300w, /wp-content/uploads/2016/12/granttype-768x487.png 768w" sizes="(max-width: 842px) 100vw, 842px" /></a></p>
<p>Select an &#8220;<strong>Auth Code Grant</strong>&#8221;</p>
<p>Set the &#8220;<strong>Access Token URI</strong>&#8221; to:</p>
<pre>https://api.amazon.com/auth/o2/token</pre>
<p>and in to &#8220;<strong>Client Secret</strong>&#8221; paste your secret from step 1.</p>
<p>You must include a link to your &#8220;<strong>Privacy Policy URL</strong>&#8220;.  Since you are the only person who cares you could host a blank file somewhere, or maybe link to a Rick Astley video on YouTube?</p>
<p>Finally hit <strong>Save</strong>.</p>
<h3>3. Link Login With Amazon back to your Skill</h3>
<p>Head back to the Login With Amazon page: <a href="https://developer.amazon.com/lwa/sp/overview.html">https://developer.amazon.com/lwa/sp/overview.html</a></p>
<p>Hover over the cog of your Security Profile and choose<strong> Web Settings</strong>:</p>
<p><a href="wp-content/uploads/2016/12/returnurl.png"><img loading="lazy" class="aligncenter wp-image-830 size-full" src="wp-content/uploads/2016/12/returnurl.png" alt="returnurl" width="920" height="358" srcset="/wp-content/uploads/2016/12/returnurl.png 920w, /wp-content/uploads/2016/12/returnurl-300x117.png 300w, /wp-content/uploads/2016/12/returnurl-768x299.png 768w" sizes="(max-width: 920px) 100vw, 920px" /></a></p>
<p>In to the &#8220;<strong>Allowed Return URLs</strong>&#8221; box paste your Redirect URL from step 2 and hit save.</p>
<h3>4.  Login to Amazon from your skill and do the OAUTH dance</h3>
<p>From the Alexa app on your phone navigate to your new Smart Home Skill and you see that it says &#8220;<strong>Account Linking Required</strong>&#8220;.</p>
<p><a href="wp-content/uploads/2016/12/IMG_0473.png"><img loading="lazy" class="aligncenter size-medium wp-image-831" src="wp-content/uploads/2016/12/IMG_0473-197x300.png" alt="img_0473" width="197" height="300" srcset="/wp-content/uploads/2016/12/IMG_0473-197x300.png 197w, /wp-content/uploads/2016/12/IMG_0473.png 638w" sizes="(max-width: 197px) 100vw, 197px" /></a></p>
<p>Click &#8220;<strong>Enable Skill</strong>&#8221; and you&#8217;ll be asked to login with your Amazon credentials:</p>
<p><a href="wp-content/uploads/2016/12/IMG_0474.png"><img loading="lazy" class="aligncenter size-medium wp-image-832" src="wp-content/uploads/2016/12/IMG_0474-175x300.png" alt="img_0474" width="175" height="300" srcset="/wp-content/uploads/2016/12/IMG_0474-175x300.png 175w, /wp-content/uploads/2016/12/IMG_0474-599x1024.png 599w, /wp-content/uploads/2016/12/IMG_0474.png 640w" sizes="(max-width: 175px) 100vw, 175px" /></a></p>
<p>Once you log in you should see a success message:</p>
<p><a href="wp-content/uploads/2016/12/IMG_0475.png"><img loading="lazy" class="aligncenter size-medium wp-image-833" src="wp-content/uploads/2016/12/IMG_0475-176x300.png" alt="img_0475" width="176" height="300" srcset="/wp-content/uploads/2016/12/IMG_0475-176x300.png 176w, /wp-content/uploads/2016/12/IMG_0475-600x1024.png 600w, /wp-content/uploads/2016/12/IMG_0475.png 640w" sizes="(max-width: 176px) 100vw, 176px" /></a></p>
<p>And you&#8217;re done.</p>
<p>&nbsp;</p>
<p>Additional:  Here&#8217;s a post on how to read the users details from Amazon once they are linked:  <a href="/2017/03/retrieving-user-profile-data-from-login-with-amazon-on-alexa/">/2017/03/retrieving-user-profile-data-from-login-with-amazon-on-alexa/</a></p>
]]></content:encoded>
					
					<wfw:commentRss>/2016/12/05/howto-add-oauth-to-your-alexa-smart-home-skill-in-10-minutes/feed/</wfw:commentRss>
			<slash:comments>13</slash:comments>
		
		
			</item>
		<item>
		<title>bravialib &#8211; a Python library to abstract the Bravia web API</title>
		<link>/2016/11/30/bravialib-a-python-library-to-abstract-the-bravia-web-api/</link>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Wed, 30 Nov 2016 20:17:01 +0000</pubDate>
				<category><![CDATA[IoT]]></category>
		<guid isPermaLink="false">/?p=817</guid>

					<description><![CDATA[I posted this to Github, but thought I would mirror it here too. [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>I posted this to Github, but thought I would mirror it here too. You can download the code from here:</p>
<p><a href="https://github.com/8none1/bravialib">https://github.com/8none1/bravialib</a></p>
<p>&nbsp;</p>
<h1>bravialib</h1>
<p>A Python library for talking to some Sony Bravia TVs, and an accompanying Alexa Skill to let you control the TV by voice. If you like that sort of thing.</p>
<p>These scripts make use of the excellent Requests module. You&#8217;ll need to install that first.</p>
<h2><a id="user-content-bravialib-itself" class="anchor" href="https://github.com/8none1/bravialib/blob/master/README.md#bravialib-itself"></a>bravialib itself</h2>
<p>This is a fairly simple library which allows you to &#8220;pair&#8221; the script with the TV and will then send cookie-authenticated requests to the TVs own web API to control pretty much everything. You can:</p>
<ul>
<li>Set up the initial pairing between the script and the TV</li>
<li>Retrieve system information from the TV (serial, model, mac addr etc)</li>
<li>Enumerate the available TV inputs (HDMI1,2,3,4 etc)</li>
<li>Switch to a given input</li>
<li>Enumerate the remote control buttons</li>
<li>Virtually press those buttons</li>
<li>Find out what Smart TV apps are available</li>
<li>Start those apps</li>
<li>Enumerate the available DVB-T channels</li>
<li>Switch to those channels</li>
<li>Send Wake On Lan packets to switch the TV on from cold (assuming you&#8217;ve enabled that)</li>
<li>A couple of convenience functions</li>
</ul>
<p>The library tries to hide the complexity and pre-requisites and give you an easy to use API.</p>
<p>I built this for a couple of reasons: 1. Because the TV had an undocumented API, and that tickles me 2. I quite fancied hooking it up to Alexa for lols</p>
<p>Most of the information about how to talk to the TV&#8217;s API came from looking at packet captures from the iPhone app &#8220;TV Sideview&#8221;.</p>
<p>There is a script called <code>testit.py</code> that will give you a few clues about how to use it, but it&#8217;s a bit of a mess. I&#8217;ve left a lot of comments in the code for the library which should help you.</p>
<p>Really, I think that this library should be imported in to a long-running process rather than be called every time you want to press a remote control button. On a Raspberry Pi, Requests can take a while (a couple of seconds) to import, and then <code>bravialib</code> pre-populates a few data sources, and all of that takes time, like about 20 seconds &#8211; so you really don&#8217;t want to use this library if you just want to fire a few remote control commands. Also &#8211; be aware that the TV takes a long time to boot and accept commands. From cold you&#8217;re talking about a minute maybe two, it&#8217;s really annoying.</p>
<h2><a id="user-content-the-aforementioned-long-running-process---bravia_restpy" class="anchor" href="https://github.com/8none1/bravialib/blob/master/README.md#the-aforementioned-long-running-process---bravia_restpy"></a>The aforementioned long running process &#8211; <code>bravia_rest.py</code></h2>
<p>As the main library takes a while to start and needs a certain amount of data from the TV to work properly it really makes sense to start it up once and then leave it running as long as you can. The <code>bravia_rest.py</code> script does exactly that, and also exposes some of the functionality as a very crude REST interface that you can easily hook it in to various home automation systems.</p>
<p>First you need to add the IP address and MAC address (needed to turn on the TV the first time the script is run, it can be discovered automatically if you just power the TV on for a few minutes before you run the script).</p>
<p>Then run <code>bravia_rest.py</code>.</p>
<p>If this is the first time you have run it you will need to pair with the TV. You will be told to point your browser at the IP address of the machine where the script is running on port 8090 (by default). Doing this will make the script attempt to pair with the TV. If it works you will see a PIN number on the TV screen, you will need to enter this in to the box in your browser. After a few seconds, and with a bit of luck, pairing will now complete. This shouldn&#8217;t take too long.</p>
<p>If you are now paired, in your browser go to /dumpinfo for a view in to what the script knows about the TV.</p>
<p>Once everything is running you can <code>POST</code> to these URLs for things to happen (no body is required):</p>
<ul>
<li><code>/set/power/[on|off]</code> &#8211; turns the telly on and off</li>
<li><code>/set/send/&lt;button&gt;</code> &#8211; e.g. mute, play, pause, up, down. See dumpinfo for all the key names.</li>
<li><code>/set/volumeup/3</code> &#8211; turn the volume up 3 notches. You MUST pass a number, even it it&#8217;s just 1.</li>
<li><code>/set/volumedown/1</code> &#8211; as above.</li>
<li><code>/set/loadapp/&lt;app name&gt;</code> &#8211; e.g. Netflix, iplayer. Again /dumpinfo will show you what apps are available.</li>
<li><code>/set/channel/&lt;channel&gt;</code> &#8211; e.g. BBC ONE, BBC TWO</li>
<li><code>/set/input/&lt;input label&gt;</code> &#8211; You need to have given your inputs labels on the TV, then pass the label here.</li>
</ul>
<h2><a id="user-content-hooking-it-up-to-alexa" class="anchor" href="https://github.com/8none1/bravialib/blob/master/README.md#hooking-it-up-to-alexa"></a>Hooking it up to Alexa</h2>
<p>Now we can poke the TV through a simplified REST interface, it&#8217;s much easier to hook in to other things, like Alexa for example. Setting up a custom skill in AWS/Lambda is beyond the scope of what I can write up at lunchtime, I&#8217;m sure there are lots of other people who have done it better than I could. You&#8217;ll need to create a custom app and upload a <strong>Python Deployment Package</strong> to Lambda including my <code>lambda_function.py</code> script (see inside the <code>Alexa</code> directory), a <code>secrets.py</code> file with your info in it, a copy of the Requests library (you need to create a Python <strong>Virtual Environment</strong> &#8211; it&#8217;s quite easy) and possibly a copy of your PEM for a self signed HTTPS certificate. I&#8217;ve also included the skills data such as the utterances that I&#8217;m using. These will need to be adjusted for your locale.</p>
<p>You can read more about Python deployment packages and AWS here:<a href="http://docs.aws.amazon.com/lambda/latest/dg/lambda-python-how-to-create-deployment-package.html">http://docs.aws.amazon.com/lambda/latest/dg/lambda-python-how-to-create-deployment-package.html</a><a href="http://docs.aws.amazon.com/lambda/latest/dg/with-s3-example-deployment-pkg.html#with-s3-example-deployment-pkg-python">http://docs.aws.amazon.com/lambda/latest/dg/with-s3-example-deployment-pkg.html#with-s3-example-deployment-pkg-python</a></p>
<p>Here&#8217;s how it works:</p>
<p><a href="https://raw.githubusercontent.com/8none1/bravialib/master/docs/Alexa%20Bravia%20Block%20Diagram.png" target="_blank" rel="noopener noreferrer"><img title="Alexa Block Diagram" src="https://raw.githubusercontent.com/8none1/bravialib/master/docs/Alexa%20Bravia%20Block%20Diagram.png" alt="block diagram" /></a></p>
<ol>
<li>You issue the command to Alexa: <code>Alexa tell The TV to change to channel BBC ONE</code>.</li>
<li>Your voice is sent to AWS (the green lines) decoded and the utterances and intents etc are sent to the Lambda script.</li>
<li>The Lambda script works out what the requested actions are and sends them back out (the orange lines) to a web server running in your home (in my case a Raspberry Pi running Apache and the <code>bravia_proxy.py</code> script). You need to make that Apache server accessible to the outside world so that AWS can POST data to it. I would recommend that you configure Apache to use SSL and you put at least BASIC Auth in front of the proxy script.</li>
<li>The <code>bravia_proxy.py</code> script receives the POSTed form from AWS and in turn POSTs to the <code>bravia_rest.py</code> script having done a quick bit of sanity checking and normalisation. The proxy and the rest scripts could live on different hosts (and probably should, there are no security considerations in either script &#8211; so ya know, don&#8217;t use them.)</li>
<li><code>bravia_rest.py</code> uses <code>bravialib</code> to poke the TV in the right way and returns back a yes or a no which then flows back (the blue lines) to AWS and your Lambda function.</li>
<li>If everything worked you should hear &#8220;OK&#8221; from Alexa and your TV should do what you told it.</li>
</ol>
<p>I could have put <code>bravia_rest.py</code> straight on the web an implemented some basic auth and SSL there &#8211; but I think this is something better handled by Apache (or whichever server you prefer), not some hacked up script that I wrote.</p>
<h3>Caveats:</h3>
<ul>
<li>It doesn&#8217;t deal with the TV being off at all well at the moment.</li>
<li>I don&#8217;t know what happens when the cookies expire.</li>
<li>I haven&#8217;t done much testing.</li>
<li>I have no idea what I&#8217;m doing.</li>
</ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>24 hours with Amazon Prime</title>
		<link>/2016/11/18/24-hours-with-amazon-prime/</link>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Fri, 18 Nov 2016 19:05:14 +0000</pubDate>
				<category><![CDATA[Making the world a better place]]></category>
		<guid isPermaLink="false">/?p=803</guid>

					<description><![CDATA[Preamble As a analytically minded person, is it worth getting Amazon Prime? I [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Preamble</h1>
<h2><em><strong>As a analytically minded person, is it worth getting Amazon Prime?</strong></em></h2>
<p>I signed up yesterday and spent the evening setting up the various services.  It was on offer with £20 off, it was the day before The Grand Tour came out, and I recently bought an Amazon Dot &#8211; well played Amazon, well played.</p>
<p>As I&#8217;m sure you&#8217;re aware Amazon Prime comes with a few bundled goodies to sweeten the deal. But are they actually useful? I think the real value is the next day delivery (if you order lots of things from Amazon), the online photo storage and perhaps the video. Everything else falls short of being good enough to be considered a real product in it&#8217;s own right.  Yes, I know that&#8217;s on purpose &#8211; but the marketing material would have you believe otherwise.  How about that.</p>
<h3>The loan of a book a month from the Kindle Lending Library</h3>
<p><strong>Rating: 4/10 (based on going to an actual library being 8/10)</strong><br />
You&#8217;re not going to find many books you actually want to read in there. Browsing the catalogue from your desktop is virtually impossible and it&#8217;s been made that way deliberately. This is frustrating and annoying. Also annoying is that if you use the Kindle app on your phone you get nagged to upgrade to Kindle Unlimited all the bloody time.  You can share this with someone else on your household account, but they won&#8217;t thank you for it.</p>
<h3>Prime Music</h3>
<p><strong>Rating: 6.5/10 (based on Spotify Premium being 10/10)</strong><br />
Better than I expected, but still full of annoyances. And again with the constant nagging to upgrade to Music Unlimited.<br />
The selection is ok. It feels like they&#8217;ve taken the time to make it just-good-enough that you will use it but not good enough that you won&#8217;t consider upgrading.</p>
<p>You can&#8217;t share this perk with anyone else in your household, and since there&#8217;s no point in two people in your household having a Prime account each, you end up setting up another Chrome profile just to access the music service for managing play lists etc. Also annoying is that you can&#8217;t play music on an Echo or Dot <em>and</em> play music in the browser at the same time. This raises the question of what will happen if you have two Amazon Alexa devices on the same account and you try and play music on both. If you can&#8217;t (and I don&#8217;t know yet, perhaps someone can comment if they do) then one of the good features of Alexa is somewhat spoiled.  (Edit: some searching suggests that indeed you cannot listen to Prime Music on more than one device at at time.)</p>
<p>This service is a very good replacement for the kitchen radio but not a replacement for even a free Spotify subscription.  If you already have a premium Spotify account then this will be of no interest to you at all.</p>
<h3>Prime Video</h3>
<p><strong>Rating: 7.5/10 (based on Netflix being 10/10)</strong></p>
<p>Not so many nag screens here, but guess what, you still need to spend more money for the full experience.  It&#8217;s a bit galling to discover that some of the headline shows need to be paid for (Game Of Thrones for example).  But, there is some genuinely good exclusive content here, The Grand Tour for example.  I don&#8217;t see myself watching it more than Netflix but it&#8217;s worth, say, 3 quid a month of the £6.50 a month Prime subscription.</p>
<p>Installing on an iPhone was easy enough, but on Android it&#8217;s outrageously bad.  You have to install Amazon&#8217;s &#8220;Underground&#8221; app store, and to do that you have to enable &#8220;Unknown Sources&#8221;.  Unlol.  The app works fine, and you can uninstall Underground once it&#8217;s on there.  The app on my Sony TV is fine.  Prime Video doesn&#8217;t support Chromecast, which isn&#8217;t a surprise but is, you guessed it, annoying.</p>
<h3>Next Day Delivery</h3>
<p><strong>Rating: 10/10 (based on going to the shops being 1/10)</strong></p>
<p>I don&#8217;t order that much from Amazon, which is why I&#8217;m wondering if this is all worth it, but when I do having it turn up the next day for &#8220;free&#8221; is nice.</p>
<h3>Unlimited Online Photo Storage</h3>
<p><strong>Rating: 9/10 (based on Google Drive being 7/10)</strong></p>
<p>Google also offer unlimited photo storage, but critically they compress your photos.  The Amazon offering does not (based on MD5 sums for a picture selected at random).  There is also an excellent Linux cli util called acd_cli (<a href="https://github.com/yadayada/acd_cli">https://github.com/yadayada/acd_cli</a>).  You&#8217;ll want to exclude videos and other files from being uploaded because they will count towards your 5GB limit for other stuff.  Something like this:</p>
<pre>acd_cli --verbose ul -xe mov -xe mp4 -xe ini . /Pictures</pre>
<p>Don&#8217;t be surprised if this has a storage limit applied in the future.</p>
<h3>Prime Early Access</h3>
<p><strong>Rating: 0/10 (based on normal Amazon shopping being 10/10)</strong></p>
<p>Early access to the electronic jumble sale that is Black Friday.  Pointless.</p>
<h3>Twitch Prime</h3>
<p><strong>Rating: 5/10 (based on not having it being 0/10)</strong></p>
<p>Skip this if you don&#8217;t know what Twitch is.  With Prime you can subscribe to a channel for a month for free.  It&#8217;s a free way to support Twitch streamers you like, and you get some crappy game add-ons that you won&#8217;t ever use.</p>
<h2>Summary</h2>
<p>Amazon Prime is basically shareware from the late 90s.  It does do what they claim, but there are constant nags to spend money on the basis that all the good stuff is just out of reach.</p>
<p>The new Amazon Dot in the kitchen was not warmly welcomed by everyone at Whizzy Towers but having it play music on demand has changed that perception quite a lot in the last day.  I have saved the first episode of The Grand Tour to watch tonight, which I am looking forward to since the reviews have been good, and all my photos which had previously been backed up on to a USB HDD are now slowly making their way to the cloud.  I also ordered a £5 book yesterday which arrived today as promised.</p>
<p>However, the shortcomings have the feeling of being deliberate.  Which is more annoying than if the services were just a bit crap.</p>
<p>So all in all you&#8217;re getting what you pay for.  It&#8217;s not amazing value, but neither is it a total rip off.  Someone at Amazon has done their job well.  I would recommend you get it.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>What to do with Unity 8 now</title>
		<link>/2016/10/14/what-to-do-with-unity-8-now/</link>
					<comments>/2016/10/14/what-to-do-with-unity-8-now/#comments</comments>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Fri, 14 Oct 2016 13:09:24 +0000</pubDate>
				<category><![CDATA[Making the world a better place]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<guid isPermaLink="false">/?p=786</guid>

					<description><![CDATA[As you&#8217;re probably aware Ubuntu 16.10 was released yesterday and brings with it [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>As you&#8217;re probably aware Ubuntu 16.10 was released yesterday and brings with it the Unity 8 desktop session as a preview of what&#8217;s being worked on right now and a reflection of the current state of play.</p>
<p>You might have already logged in and kicked the proverbial tyres.  If not I would urge you to do so.  Please take the time to install a couple of apps as laid out here:</p>
<p><a href="http://insights.ubuntu.com/2016/10/13/unity-8-preview-session-in-ubuntu-16-10-yakkety-yak/">http://insights.ubuntu.com/2016/10/13/unity-8-preview-session-in-ubuntu-16-10-yakkety-yak/</a></p>
<p>The main driver for getting Unity 8 in to 16.10 was the chance to get it in the hands of users so we can get feedback and bug reports.  If you find something doesn&#8217;t work, please, log a bug.  We don&#8217;t monitor every forum or comments section on the web so the absolute best way to provide your feedback to people who can act on it is a bug report with clear steps on how to reproduce the issue (in the case of crashes) or an explanation of why you think a particular behaviour is wrong.  This is how you get things changed or fixed.</p>
<p>You can contribute to Ubuntu by simply playing with it.</p>
<p>Read about logging bugs in Ubuntu here: <a href="https://help.ubuntu.com/community/ReportingBugs">https://help.ubuntu.com/community/ReportingBugs</a></p>
<p>And when you are ready to log a bug, log it against Unity 8 here: <a href="https://bugs.launchpad.net/ubuntu/+source/unity8">https://bugs.launchpad.net/ubuntu/+source/unity8</a></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>/2016/10/14/what-to-do-with-unity-8-now/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Apache &#8211; 20 second lag before serving pages</title>
		<link>/2016/10/13/apache-20-second-lag-before-serving-pages/</link>
					<comments>/2016/10/13/apache-20-second-lag-before-serving-pages/#comments</comments>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Thu, 13 Oct 2016 10:15:09 +0000</pubDate>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[Making the world a better place]]></category>
		<guid isPermaLink="false">/?p=780</guid>

					<description><![CDATA[TL;DR:  There is no such thing as a &#8220;none&#8221; directive in Apache 2. [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><strong>TL;DR</strong>:  There is no such thing as a &#8220;none&#8221; directive in Apache 2.  If you&#8217;ve got &#8220;deny from none&#8221; or &#8220;allow from none&#8221; then you&#8217;re doing DNS lookups on each host that connects regardless of whether you want to or not.</p>
<p>I was experiencing a very annoying problem trying to serve static HTML pages and CGI scripts from Apache 2 recently.  The problem manifested itself like this:</p>
<ul>
<li>Running the scripts on the server hosting Apache shows they ran in well under a second</li>
<li>Connecting to the Apache server from the LAN, everything was fine and ran in under a second</li>
<li>Connecting to the Apache server from the Internet, but from a machine known to my network, ran fine</li>
<li>Connecting from an AWS Lambda script, suddenly there is a 20 second or more delay before getting data back</li>
<li>Connecting from Digital Ocean, there is a 20 second delay</li>
<li>Connecting from another computer on the internet, there is a 20 second delay</li>
</ul>
<p>What the heck is going on here?</p>
<p>I spent time trying to debug my CGI scripts and adding lots more logging and finally convinced myself that it was a problem with the Apache config and not something like MTUs or routing problems.</p>
<p>But what was causing it?  It started to feel like like a DNS related issue since the machines where it ran fine where all known to me, and so had corresponding entries in my local DNS server.  But but but&#8230; I clearly had &#8220;HostnameLookups Off&#8221; in my apache2.conf file.  When I looked at the logs again, I noticed that indeed hostnames were being looked up, even though I told it not to.</p>
<p><a href="http://whizzy.org/wp-content/uploads/2016/10/966381.jpg"><img loading="lazy" class="aligncenter size-medium wp-image-781" src="/wp-content/uploads/2016/10/966381-300x225.jpg" alt="966381" width="300" height="225" srcset="/wp-content/uploads/2016/10/966381-300x225.jpg 300w, /wp-content/uploads/2016/10/966381.jpg 640w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<p>Why?  Because I don&#8217;t know how to configure Apache servers properly.  At some point in time I thought this was a good idea:</p>
<pre style="padding-left: 90px;">Order deny, allow
Deny from none
Allow from all</pre>
<p>But, there is <span style="text-decoration: underline;">no such thing as a &#8220;none&#8221; directive</span>.  Apache interprets &#8220;none&#8221; as a host name and so has to look it up to see if it&#8217;s supposed to be blocking it or not, which causes a DNS lookup delays and hostnames to appear in your Apache logs.</p>
<p>Enlightenment came from here:<a href="http://kb.simplywebhosting.com/idx/6/213/article/"> http://kb.simplywebhosting.com/idx/6/213/article/</a></p>
<p>There is also a suggestion that inline comments can do the same thing here:  <a href="https://www.drovemebatty.com/wp/entries/11">https://www.drovemebatty.com/wp/entries/11</a></p>
]]></content:encoded>
					
					<wfw:commentRss>/2016/10/13/apache-20-second-lag-before-serving-pages/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Unity 7 Low Graphics Mode</title>
		<link>/2016/09/01/unity-7-low-graphics-mode/</link>
					<comments>/2016/09/01/unity-7-low-graphics-mode/#comments</comments>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Thu, 01 Sep 2016 10:43:23 +0000</pubDate>
				<category><![CDATA[Ubuntu]]></category>
		<guid isPermaLink="false">/?p=753</guid>

					<description><![CDATA[Unity 7 has had a low graphics mode for a long time but [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Unity 7 has had a low graphics mode for a long time but recently we&#8217;ve been making it better.</p>
<p><a href="https://wiki.ubuntu.com/hikiko">Eleni</a> has been making improvements to reduce the amount of visual effects that are seen while running in low graphics mode.  At a high level this includes things like:</p>
<ul>
<li>Reducing the amount of animation in elements such as the window switcher, launcher and menus (in some cases down to zero)</li>
<li>Removing blur and fade in/out</li>
<li>Reducing shadows</li>
</ul>
<p>The result of these changes will be beneficial to people running Ubuntu in a virtual machine (where hardware 3D acceleration is not available) and for remote-control of desktops with VNC, RDP etc.</p>
<p>Low graphics mode should enable itself when it detects certain GL features are not available (e.g. in a virtualised environment) but there are times when you might want to force it on.  Here&#8217;s how you can force low graphics mode on 16.04 LTS (Xenial) :</p>
<ol>
<li>nano ~/.config/upstart/lowgfx.conf</li>
<li>Paste this into it:</li>
</ol>
<pre>start on starting unity7
pre-start script
    initctl set-env -g UNITY_LOW_GFX_MODE=1
end script</pre>
<ol start="3">
<li>Log out and back in</li>
</ol>
<p>If you want to stop using low graphics comment out the initctl line by placing a &#8216;#&#8217; at the start of the line.</p>
<p>This hack won&#8217;t work in 16.10 Yakkety because we&#8217;re moving to systemd for the user session.  I&#8217;ll write up some instructions for 16.10 once it&#8217;s available.</p>
<p>Here&#8217;s a quick video of some of the effects in low graphics mode:</p>
<p><iframe loading="lazy" src="//www.youtube.com/embed/gWUyP-oTRVg" width="560" height="315" frameborder="0" allowfullscreen="allowfullscreen"></iframe></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>/2016/09/01/unity-7-low-graphics-mode/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title>DHCP clients not registering hostnames in DNS automatically</title>
		<link>/2016/02/17/dhcp-clients-not-registering-hostnames-in-dns-automatically/</link>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Wed, 17 Feb 2016 20:43:59 +0000</pubDate>
				<category><![CDATA[IoT]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[RaspberryPi]]></category>
		<guid isPermaLink="false">/?p=730</guid>

					<description><![CDATA[To remind myself as much as anything: I run a dnsmasq server on [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>To remind myself as much as anything:</p>
<p>I run a dnsmasq server on my router (which is a <a href="/2015/05/multipathrouting-rasppi2/">Raspberry Pi 2</a>) to handle local DNS, DNS proxying and DHCP. For some reason one of the hosts stopped registering its hostname with the DHCP server, and so I couldn&#8217;t resolve its name to an IP address from other clients on my network.</p>
<p>I&#8217;m pretty sure it used to work, and I&#8217;m also pretty sure I didn&#8217;t change anything &#8211; so why did it suddenly stop? My theory is that the disk on the client became corrupt and a fsck fix removed some files.</p>
<p>Anyway, the cause is that the DHCP client didn&#8217;t know to send it&#8217;s hostname along with the DHCP request.</p>
<p>This is fixed by creating (or editing) <code>/etc/dhcp/dhclient.conf</code> and adding this line:</p>
<p><code>send host-name = gethostname();</code></p>
<p>&nbsp;</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Online searches in the dash to be off by default.</title>
		<link>/2015/12/10/online-searches-in-the-dash-to-be-off-by-default/</link>
					<comments>/2015/12/10/online-searches-in-the-dash-to-be-off-by-default/#comments</comments>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Thu, 10 Dec 2015 10:53:10 +0000</pubDate>
				<category><![CDATA[Ubuntu]]></category>
		<guid isPermaLink="false">/?p=721</guid>

					<description><![CDATA[Scopes are a leading feature of the Ubuntu Phone and of Unity 8 [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><span style="font-weight: 400;">Scopes are a leading feature of the Ubuntu Phone and of Unity 8 in general.  That concept, the story of scopes, started out in Unity 7 and in 12.10 when we added results from online searches to the dash home screen. </span></p>
<p><span style="font-weight: 400;">Well, we’re making some changes to the Unity 7 Dash searches in 16.04 LTS.  On Unity 8 the Scopes concept has evolved into something which gives the user finer control over what is searched and provides more targeted results.  This functionality cannot be added into Unity 7 and so we’ve taken the decision to gracefully retire some aspects of the Unity 7 online search features.</span></p>
<h3><span style="font-weight: 400;">What is changing?</span></h3>
<p><span style="font-weight: 400;">First of all online search will be off by default.  This means that out-of-the-box none of your search terms will leave your computer.  You can toggle this back on through the Security &amp; Privacy option in System Settings.  Additionally, if you do toggle this back on then results from Amazon &amp; Skimlinks will remain off by default.  You can toggle them back on if you wish.  Further, the following scopes will be retired from the default install and moved to the Universe repository for 16.04 LTS onwards:</span></p>
<ol>
<ol>
<li style="font-weight: 400;"><span style="font-weight: 400;">Audacious</span></li>
<li style="font-weight: 400;"><span style="font-weight: 400;">Clementine</span></li>
<li style="font-weight: 400;"><span style="font-weight: 400;">gmusicbrowser</span></li>
<li style="font-weight: 400;"><span style="font-weight: 400;">Gourmet</span></li>
<li style="font-weight: 400;"><span style="font-weight: 400;">Guayadeque</span></li>
<li style="font-weight: 400;"><span style="font-weight: 400;">Musique</span></li>
</ol>
</ol>
<p><span style="font-weight: 400;">The Music Store will be removed completely for 16.04 LTS onwards.</span></p>
<h3><span style="font-weight: 400;">Why now?</span></h3>
<p><span style="font-weight: 400;">By making these changes now we can better manage our development priorities, servers, network bandwidth etc throughout the LTS period. We allow ourselves more freedom to make changes without further affecting the LTS release (e.g SRUs), specifically we can better manage the eventual transition to Unity 8 and not have to maintain two sets of scope infrastructure for the duration of the LTS support period of five years.</span></p>
<h3><span style="font-weight: 400;">What about previous supported releases?</span></h3>
<p><span style="font-weight: 400;">Search results being off by default will not affect previous releases or upgrades, only new installs (i.e. we will not touch your existing settings).  Changes to search results from Amazon &amp; Skimlinks will also only affect 16.04 and beyond.  The removal of the Music Store will be SRU’d back to older supported releases and the option will be removed from the Dash.</span></p>
<h3><span style="font-weight: 400;">When will this happen?</span></h3>
<p><span style="font-weight: 400;">We’re preparing the make the changes in the archive, to Unity 7 and to the Online Search servers right now.  This will take a little while to test and roll out.  We’ll let you know once all the changes are in Xenial.</span></p>
]]></content:encoded>
					
					<wfw:commentRss>/2015/12/10/online-searches-in-the-dash-to-be-off-by-default/feed/</wfw:commentRss>
			<slash:comments>33</slash:comments>
		
		
			</item>
		<item>
		<title>Hacking 433Mhz support into a cheap Carbon Monoxide detector</title>
		<link>/2015/10/20/hacking-433mhz-support-into-a-cheap-carbon-monoxide-detector/</link>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Tue, 20 Oct 2015 20:37:27 +0000</pubDate>
				<category><![CDATA[Arduino]]></category>
		<category><![CDATA[IoT]]></category>
		<category><![CDATA[Making the world a better place]]></category>
		<guid isPermaLink="false">/?p=684</guid>

					<description><![CDATA[Skill level:  Easy My home automation systems use two mechanisms for communication:  Ethernet (both [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><strong>Skill level:  Easy</strong></p>
<p>My home automation systems use two mechanisms for communication:  Ethernet (both wired and wireless) and 433MHz OOK radio.</p>
<p>433MHz transmitters are readily available and are cheap but unreliable.  Wifi enabled MCUs such as the ESP8266 are also cheap (coming in at around the same cost as an Arduino clone, a 433MHz transmitter and a bag of bits to connect them together), they are reliable enough but extremely power hungry.  If I can plug a project into the mains then I&#8217;ll use an ESP8266 and a mobile phone charger for power, if the project needs to run off batteries then a 433MHz equipped Arduino is the way I&#8217;ve gone.</p>
<p>Like most people playing with 433MHz radio I found reliability and range of the radio link to be super flaky.  I&#8217;ve finally got a more-or-less reliable set-up:</p>
<ul>
<li>A full wave dipole antenna at the receiver</li>
<li>A high quality receiver from RF Solutions in place of the cheap ones which are bundled with transmitters. <a href="http://rover.ebay.com/rover/1/710-53481-19255-0/1?icep_ff3=2&amp;pub=5575128401&amp;toolid=10001&amp;campid=5337704861&amp;customid=&amp;icep_item=231721857012&amp;ipn=psmain&amp;icep_vectorid=229508&amp;kwid=902099&amp;mtid=824&amp;kw=lg" target="_blank" rel="noopener noreferrer">A decent receiver on eBay</a></li>
<li>A big capacitor on the transmitter.  I saw the frequency and amplitude drifting massively during transmission.  Adding a 470µF cap helps.  Allow time for the cap to charge and the oscillator to stabilise, a few seconds delay seemed to do the trick.</li>
<li>Using the RCSwitch library on the transmitter:
<ul>
<li>
<pre>RCSwitch mySwitch = RCSwitch();</pre>
</li>
<li>
<pre>mySwitch.setProtocol(2); // Much longer pulse lengths = much better range?</pre>
</li>
<li>
<pre>mySwitch.setRepeatTransmit(20); // Just brute-force it!</pre>
</li>
</ul>
</li>
</ul>
<p>With this setup I can get receive a 24bit number from an Arduino running off 2 AA batteries and a coiled 1/2 wave antenna from about 5 meters indoors through walls.  That&#8217;s still poor, but it does the job.  Increasing the voltage to the transmitter would probably help.</p>
<p>Once you have a reliable 433MHz receiver setup then you can also buy off the shelf 433MHz enabled home automation gizmos like <a href="http://rover.ebay.com/rover/1/710-53481-19255-0/1?icep_ff3=2&amp;pub=5575128401&amp;toolid=10001&amp;campid=5337704861&amp;customid=&amp;icep_item=181665729292&amp;ipn=psmain&amp;icep_vectorid=229508&amp;kwid=902099&amp;mtid=824&amp;kw=lg" target="_blank" rel="noopener noreferrer">this smoke alarm</a> or <a href="http://rover.ebay.com/rover/1/710-53481-19255-0/1?icep_ff3=2&amp;pub=5575128401&amp;toolid=10001&amp;campid=5337704861&amp;customid=&amp;icep_item=281405424486&amp;ipn=psmain&amp;icep_vectorid=229508&amp;kwid=902099&amp;mtid=824&amp;kw=lg" target="_blank" rel="noopener noreferrer">these door sensors</a>.  They have a set of jumpers inside where you can set an ID, which is essentially the same 24bit number that RCSwitch lets you transmit.  For what it&#8217;s worth I also have <a href="https://en.wikipedia.org/wiki/British_Standards" target="_blank" rel="noopener noreferrer">kite-marked</a> smoke detectors in my house, but from the testing I&#8217;ve done with a bit of smoldering paper the cheap imports work just fine.</p>
<p>I couldn&#8217;t find a cheap Carbon Monoxide which also has 433MHz support so I thought I&#8217;d quickly hack one together out of <a href="http://rover.ebay.com/rover/1/710-53481-19255-0/1?icep_ff3=2&amp;pub=5575128401&amp;toolid=10001&amp;campid=5337704861&amp;customid=&amp;icep_item=281723682194&amp;ipn=psmain&amp;icep_vectorid=229508&amp;kwid=902099&amp;mtid=824&amp;kw=lg" target="_blank" rel="noopener noreferrer">this Carbon Monoxide detector</a> and an Arduino clone and 433MHz radio:</p>
<p><a href="http://whizzy.org/wp-content/uploads/2015/10/IMG_1237.jpg"><img loading="lazy" class="alignleft size-medium wp-image-703" src="/wp-content/uploads/2015/10/IMG_1237-225x300.jpg" alt="CO Alarm inside" width="225" height="300" srcset="/wp-content/uploads/2015/10/IMG_1237-225x300.jpg 225w, /wp-content/uploads/2015/10/IMG_1237-768x1024.jpg 768w, /wp-content/uploads/2015/10/IMG_1237-1152x1536.jpg 1152w, /wp-content/uploads/2015/10/IMG_1237-1536x2048.jpg 1536w, /wp-content/uploads/2015/10/IMG_1237-1200x1600.jpg 1200w, /wp-content/uploads/2015/10/IMG_1237-1980x2640.jpg 1980w, /wp-content/uploads/2015/10/IMG_1237-scaled.jpg 1920w" sizes="(max-width: 225px) 100vw, 225px" /></a></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><div id="attachment_706" style="width: 310px" class="wp-caption alignleft"><a href="http://whizzy.org/wp-content/uploads/2015/10/IMG_1238.jpg"><img aria-describedby="caption-attachment-706" loading="lazy" class="wp-image-706 size-medium" src="/wp-content/uploads/2015/10/IMG_1238-300x225.jpg" alt="IMG_1238" width="300" height="225" srcset="/wp-content/uploads/2015/10/IMG_1238-300x225.jpg 300w, /wp-content/uploads/2015/10/IMG_1238-1024x768.jpg 1024w, /wp-content/uploads/2015/10/IMG_1238-768x576.jpg 768w, /wp-content/uploads/2015/10/IMG_1238-1536x1152.jpg 1536w, /wp-content/uploads/2015/10/IMG_1238-2048x1536.jpg 2048w, /wp-content/uploads/2015/10/IMG_1238-1200x900.jpg 1200w, /wp-content/uploads/2015/10/IMG_1238-1980x1485.jpg 1980w" sizes="(max-width: 300px) 100vw, 300px" /></a><p id="caption-attachment-706" class="wp-caption-text">You can barely notice it!</p></div></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>It&#8217;s certainly untidy, but it does the job.  If I had PCB facilities at home I&#8217;m fairly sure it could be made to fit inside the alarm, along with some more holes in the case for ventilation.</p>
<p>The premise is simple enough.  The Arduino is powered by the 3v3 regulator on the CO alarm PCB.  The cathode of the red alarm LED is connected to pin 2 of the Arduino as an external interrupt.  When the pin goes low the Arduino wakes up and sends it&#8217;s 24bit ID number over the radio which is picked up by the receiver which sends an SMS alert, switches the boiler off, etc.  I&#8217;ve connected the radio transmitter to directly to the 3 x AA batteries (4.5 volts) via a transistor which is switched by a pin on the Arduino.  In standy-by mode the additional equipment draws a fraction of a milliamp and so I&#8217;m not worried about draining the batteries faster.</p>
<p>As with the smoke alarms, this is not my only source of Carbon Monoxide detection.  I&#8217;ve yet to test it&#8217;s sensitivity.  This is considered to be a &#8220;well, if it works, and it turns the boiler off automatically then it&#8217;s certainly worth a go, but I&#8217;m not relying on it&#8221; project.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>My first 10 years with Ubuntu</title>
		<link>/2015/10/14/10-years-with-ubuntu/</link>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Wed, 14 Oct 2015 08:00:57 +0000</pubDate>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<guid isPermaLink="false">/?p=685</guid>

					<description><![CDATA[Today I have had a Launchpad account for ten years! I got started [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><a href="http://whizzy.org/wp-content/uploads/2015/10/IMG_1220.jpg"><img loading="lazy" class="alignleft wp-image-691" src="http://whizzy.org/wp-content/uploads/2015/10/IMG_1220.jpg" alt="IMG_1220" width="799" height="132" srcset="/wp-content/uploads/2015/10/IMG_1220.jpg 1005w, /wp-content/uploads/2015/10/IMG_1220-300x50.jpg 300w, /wp-content/uploads/2015/10/IMG_1220-768x127.jpg 768w" sizes="(max-width: 799px) 100vw, 799px" /></a></p>
<p>Today I have had a <a href="https://launchpad.net/~willcooke">Launchpad account</a> for ten years!</p>
<p>I got started out on this road around 1992.  I remember the day <a href="http://www.kryogenix.org/">Stuart</a> got a PC and installed Minix on it.  That box was biege, naturally, was about 3 feet square and constructed from inch thick iron plate.  Minix was totally alien when compared to the Acorn <a href="https://en.wikipedia.org/wiki/Acorn_MOS">MOS</a> and <a href="https://en.wikipedia.org/wiki/RISC_OS">RISCOS</a> powered machines I&#8217;d used until then, and absolutely intriguing.</p>
<p>A few years later at university I encountered VAX/VMS and Sun SPARCstations and The Internet and <a href="https://en.wikipedia.org/wiki/Surfers_(talker)">Surfers</a> and Mozilla and a Gopher connected Coke machine.</p>
<p>Then out into the big wide world of work and run-ins with AS400 and RS/6000s running AIX.  During this time I started seeing more and more Red Hat in places where there once would have been the more established players, providing email and web servers.  The fascination with *nix was always there and I started using Red Hat at home for fun.</p>
<p>I quickly ran into frustrations with RPMs and Stuart, always a source of wisdom, suggested I try Debian.</p>
<p>Dpkg made my life a whole lot easier and I started using Debian as my default OS for everything. Pretty soon after that I found myself compiling kernels, modules and software packages because I needed or wanted something in a newer version.  Coupled with the availability of cheap unbranded webcams, sound cards, network cards, TV cards etc and a strong desire to make these things work with Linux meant that I had found a wonderful way to stay up until 4 in the morning getting more and more frustrated.  The phrase &#8220;I&#8217;m going home to play with the kernel&#8221; was frequently questioned by my boss Jeremy.  I wanted these things to work but was endlessly faffing about trying to make it happen.</p>
<p>Better call Stuart.</p>
<p>&#8220;You should try this new Debian based distribution called Ubuntu&#8221; he said.</p>
<p>So I did, and it just worked.  A box fresh kernel with all the goodies I needed already compiled in and an up-to-date GNOME desktop (I&#8217;d set my allegiances before trying Ubuntu so this was another tick in the box), not forgetting one of the brownest themes known to man.</p>
<p>And that was that.  Ubuntu worked for me and I was immediately a fan.</p>
<p>And here I am today, 10 years later, still running Ubuntu.  My servers run Ubuntu, all the desktops in my house run Ubuntu, I have an Ubuntu powered phone and soon I&#8217;ll have an Ubuntu powered Mycroft with which I&#8217;ll be able to control my Ubuntu powered things while wearing my Ubuntu T shirt and drinking tea (should that be kool-aid?) from my Ubuntu mug.</p>
<p>I salute my Ubuntu brothers and sisters.  Thanks for making all of this possible.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Big Bug Bonanza Ubuntu 16.04 LTS</title>
		<link>/2015/09/14/big-bug-bonanza-16-04-lts/</link>
					<comments>/2015/09/14/big-bug-bonanza-16-04-lts/#comments</comments>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Mon, 14 Sep 2015 15:30:12 +0000</pubDate>
				<category><![CDATA[Ubuntu]]></category>
		<guid isPermaLink="false">/?p=679</guid>

					<description><![CDATA[The vast majority of Ubuntu desktop users prefer to stick with a long [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>The vast majority of Ubuntu desktop users prefer to stick with a long term support release (<a href="https://wiki.ubuntu.com/LTS">https://wiki.ubuntu.com/LTS</a>) rather than the regular 6 monthly releases, so 16.04 LTS represents the next big upgrade for most Ubuntu users.  16.04 LTS will be running Unity 7 by default as it has done for the last six years and our focus for the Unity 7 stack is fixing bugs which adversely affect the user experience of the desktop.</p>
<p>Over the years the bug lists for Unity 7 and Compiz have grown to become unmanageable.  To make sure we are focusing on the most important issues we have to do some serious tidying up of the bug lists and we need some help.</p>
<p>At the time of writing there are 2680 open bugs for Unity 7 (<a href="https://launchpad.net/ubuntu/+source/unity/+bugs">https://launchpad.net/ubuntu/+source/unity/+bugs</a>) and 1455 for Compiz (<a href="https://launchpad.net/ubuntu/+source/compiz/+bugs">https://launchpad.net/ubuntu/+source/compiz/+bugs</a>) and 322 for nux, our graphical toolkit (<a href="https://launchpad.net/ubuntu/+source/nux/+bugs">https://launchpad.net/ubuntu/+source/nux/+bugs</a>).</p>
<p>We&#8217;re proposing to cut this down to size with the following plan:</p>
<ol>
<li><strong>Close all bugs which relate to an unsupported release of Ubuntu.</strong>  We will do a manual review of the high heat bugs affecting unsupported releases first, but low heat bugs will most likely be closed by a robot.  The rationale is that the majority of these older bugs will have been fixed and that the original reporter is probably no longer affected by the bug and has forgotten to close it.  Plus manually screening each of these bugs cannot be done at this scale in a reasonable timeframe.  There will be some collateral damage which is an unfortunate but unavoidable side-effect.  Sorry if this affects you, but please do re-open the bug against a supported release.</li>
<li><strong>Close all private apport bugs and review public ones with a view to closing them as well.</strong>  Apport is the automated error reporting tool which runs when it detects a crash.  It can open a private bug in Launchpad, private because stack traces might contain sensitive information which shouldn’t be public.  We have <a href="http://errors.ubuntu.com/">errors.ubuntu.com</a> which can monitor crashes and provide a <em>much</em> clearer picture of which crashers are affecting numerous people and which are one-offs.  We will use errors.ubuntu.com instead of trying to triage the 250 or so bugs which fall in to this category.</li>
<li><strong>Manually try to reproduce bugs and flag those which are still a problem.</strong>  This is where we need the most help.  We will create a list of bugs which need to be checked and then ask people to spend a few minutes trying to reproduce a chosen bug on 15.10.  If it’s still a problem then the tester would mark the bug as triaged or add a specific tag, or if it cannot be reproduced then they would mark the bug as Invalid.  This will give us a curated list of real bugs which we can then triage further to assess the impact and priority.  We will work through the triaged list in an agile manner and have regular meetings to review what has been fixed and decide on which bugs to focus on next.  By distributing this problem across many people we can get the job done in a reasonable time scale.</li>
</ol>
<h2>How you can help</h2>
<p>First of all we need help in triaging the bug list.  You don’t need to be a superstar software developer to do this, everyone can help and contribute to Ubuntu.  You will need a <a href="https://launchpad.net/">Launchpad</a> account though.  We will publish a link to a list of bugs in Launchpad for Unity 7 (and in time Compiz &amp; Nux) which we think need manual checking.  The links are available at this wiki page:  <a href="https://wiki.ubuntu.com/BigDesktopBugScrub">https://wiki.ubuntu.com/BigDesktopBugScrub</a></p>
<p>Please choose a bug from this list and try to recreate it in 15.10.  If your main machine isn’t running 15.10 you could set up a virtual machine using VirtualBox.</p>
<ol>
<li><strong>Choose a bug from the list. </strong> The heat metric is a good indication of which bugs are more important to a lot of people.  The list is sorted by heat so selecting one from somewhere near the top is a good starting point.  It’s possible that someone else will be working on the same bug as you so check the comments to see if anyone has added anything recently.</li>
<li><strong>Can you recreate the bug?</strong>  There are a number of possible outcomes when you attempt to recreate the bug.  Listed below are the most common ones.  If you can’t match one of these categories directly, or don&#8217;t know what to do just leave the bug where it is and try a different one.
<ol>
<li><strong>No &#8211; I can’t understand from the report what the problem is</strong>:
<ol>
<li>Add a comment along the lines of:  “Thank you for taking the time to report this bug.  Unfortunately we can’t work out how to recreate this bug from your description.  Please describe the process you go through to trigger this bug and then change the bug status to NEW.  See this page for more information. https://wiki.ubuntu.com/BigDesktopBugScrub”</li>
<li>Set the bug status to <strong>Incomplete</strong></li>
</ol>
</li>
<li><strong>No &#8211; I’ve tried to but it doesn’t seem to be a problem any more</strong>:
<ol>
<li>Add a comment along the lines of: “Thank you for taking the time to report this bug.  We have tried to recreate this on the latest release of Ubuntu and cannot reproduce it.  This bug is being marked as Invalid.  If you believe the problem to still exist in the latest version of Ubuntu please comment on why that is the case and change the bug status to NEW.”</li>
<li>Set the bug status to <strong>Invalid</strong></li>
</ol>
</li>
<li><strong>Yes &#8211; it’s still a problem in 15.10</strong>:
<ol>
<li>Add a comment along the lines of: “As part of the big bug review for 16.04 LTS I have tested this on 15.10 and the bug is still there.”</li>
<li>Mark the bug as <strong>Triaged</strong> or, if you don&#8217;t have permission to do that, add the tag “desktop-bugscrub-triaged”</li>
</ol>
</li>
<li><strong>Yes &#8211; but I don’t think it’s really a bug (perhaps a feature request)</strong>:
<ol>
<li>Add a comment along the lines of: “As part of the big bug review for 16.04 LTS I have tested this on 15.10 and the bug is still there.  I think this is a feature request rather than a bug.”</li>
<li>Mark the bug as “<strong>Opinion</strong>”, or if you don’t have permission to do that, add the tag “desktop-bugscrub-opinion”</li>
</ol>
</li>
</ol>
</li>
<li><strong>Thank you!</strong>  We’re one bug closer to perfection!</li>
<li>Lather, Rinse, Repeat</li>
</ol>
<p>&nbsp;</p>
<h2>What happens next</h2>
<p>Once we have a list of high quality, reproducible bug reports which are affecting many people we can start to chip away at them in a logical manner.  We will be using an Agile-like workflow:</p>
<ol>
<li>Meet at the start of a “<a href="http://scrummethodology.com/scrum-sprint/">sprint</a>” to discuss which of the most important bugs (importance will be decided on a mixture of bug heat and expert knowledge) will be working on during the sprint duration.  We will decide how many of the bugs we think are fixable in that sprint and take them into our backlog.  The backlog will be managed using Trello (<a href="https://trello.com/b/9YvUSYqq/unity-7">https://trello.com/b/9YvUSYqq/unity-7</a>).</li>
<li>The sprint will start and developers will take bugs (Cards) from the backlog to work on.</li>
<li>The card will move to the In Progress colum</li>
<li>If there is a problem the bug will move to the blocked column and these cards will be discussed at regular intervals during the sprint.</li>
<li>Once a bug is fixed it will move to the Review column.  A code review will be done and if everything is OK then the fix will be merged and automatically tested.  If there are problems it will move back to the In Progress column.</li>
<li>At the end of the sprint the fixes will be demonstrated and everyone will have a chance to spot any problems with the fix.  If there is a problem the card will go back into the Backlog for more work next sprint.  If everything is OK then the card is moved to Done and that bug is now fixed.</li>
<li>The next sprint will start and we will go back to step 1.</li>
</ol>
<p>&nbsp;</p>
<p>We will endeavour to do our reviews in a Hangout On Air so that everyone can join to see what progress is being made.  We will also use our IRC channel on Freenode <a href="http://is.gd/ubuntu_desktop_irc">#ubuntu-desktop</a>.</p>
<p>&nbsp;</p>
<h2>Software developers who want to help</h2>
<p>If you are a developer who wants to help fix the code as well as triage bugs please join us on IRC (<a href="http://is.gd/ubuntu_desktop_irc">#ubuntu-desktop on Freenode</a>) and introduce yourself.  We can get you write access to the Trello board and invite you along to the Sprint planning and review meetings.  We&#8217;d love you to get involved.</p>
<h2>Bug Squash Hours</h2>
<p>In order to kick start the process we will be setting aside a few hours a week where a core Unity 7 developer will be available on IRC to help answer questions about bugs and we&#8217;ll be working through the list as well.  Feel free to ask for help or come and join us while we work through the bug list.  Exact schedule will be announced as soon as we know what it is.</p>
<p>&nbsp;</p>
<h2>Ubuntu Online Summit</h2>
<p>We will have a session at UOS to review how the bug triage is going, discuss our tooling and policy on which bugs to auto-close etc.</p>
]]></content:encoded>
					
					<wfw:commentRss>/2015/09/14/big-bug-bonanza-16-04-lts/feed/</wfw:commentRss>
			<slash:comments>6</slash:comments>
		
		
			</item>
		<item>
		<title>HOWTO:  Very low power usage on Pro Mini V2 (Arduino clone)</title>
		<link>/2015/06/11/howto-very-low-power-usage-on-pro-mini-v2-arduino-clone/</link>
					<comments>/2015/06/11/howto-very-low-power-usage-on-pro-mini-v2-arduino-clone/#comments</comments>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Thu, 11 Jun 2015 19:39:24 +0000</pubDate>
				<category><![CDATA[Arduino]]></category>
		<category><![CDATA[IoT]]></category>
		<guid isPermaLink="false">/?p=655</guid>

					<description><![CDATA[Skill level:  Easy enough if you&#8217;ve got a soldering iron. Introduction The Pro [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><strong>Skill level:</strong>  <em>Easy enough if you&#8217;ve got a soldering iron.</em></p>
<h2>Introduction</h2>
<p>The Pro Mini V2 is an <a href="http://www.arduino.cc/en/Main/ArduinoBoardProMini">Arduino Pro Mini</a> clone available on eBay for, typically, £1.50.  The version I buy is adjustable between 5v and 3.3v and has an ATmega 328 clocked at 8 MHz.  It&#8217;s an ideal board for development of IoT remote sensors and great for playing with and learning about the <a href="http://www.arduino.cc/">Arduino</a> development environment.</p>
<p>Here&#8217;s a link to the version I buy and know works: <a href="http://rover.ebay.com/rover/1/710-53481-19255-0/1?icep_ff3=2&amp;pub=5575128401&amp;toolid=10001&amp;campid=5337704861&amp;customid=lowpowerarduino&amp;icep_item=321413432145&amp;ipn=psmain&amp;icep_vectorid=229508&amp;kwid=902099&amp;mtid=824&amp;kw=lg" target="_blank" rel="noopener noreferrer">3V Pro Mini 2 Arduino Clone</a><img style="text-decoration: none; border: 0; padding: 0; margin: 0;" src="http://rover.ebay.com/roverimp/1/710-53481-19255-0/1?ff3=2&amp;pub=5575128401&amp;toolid=10001&amp;campid=5337704861&amp;customid=lowpowerarduino&amp;item=321413432145&amp;mpt=[CACHEBUSTER]" alt="" /></p>
<p>When you want to put a sensor in a remote location the last thing you want to do is have to run a power cable to it. I&#8217;ve experimented with solar with generally poor results so battery operation is the obvious solution.  While Li-ion batteries offer higher energy density the sweet spot still seems to be the good ol&#8217; alkaline battery.  They&#8217;re cheap, safe, recyclable and readily available.</p>
<p>For what it&#8217;s worth the Ikea alkaline batteries offer good value:  <a href="http://www.batteryshowdown.com/results-lo.html">http://www.batteryshowdown.com/results-lo.html</a> (I suggest buying as many packets as you can carry, so that you never ever have to go back there.  Unless you like arguing with your wife of course.)</p>
<h2>Power Usage</h2>
<p>The ATmega 328 has various power saving functions which involve putting it to sleep when not doing anything.  I use the <a href="http://www.rocketscream.com/blog/2011/07/04/lightweight-low-power-arduino-library/">Rocket Scream Low Power library</a> to take care of putting the processor into a low power state, but I wasn&#8217;t seeing anything like the low power savings they detail on their site.</p>
<p>Some quick calculations:  Let&#8217;s assume a AA battery provides 2000 mAh.  I measured my Pro Mini V2 as drawing 6.7mA when powered up and doing things and 2.8mA when in sleep mode.  As a conservative estimate, let&#8217;s say it&#8217;s running for 1 hour in every 24 hour period and asleep the rest of the time.  That averages out to about 3mAh of draw.</p>
<p>For a 2000 mAh battery, that would give about 667 hours of runtime, or 28 days. <strong>So a standard Pro Mini V2 could run for about a month on a pair of AA batteries.  </strong>Not bad, but I think changing the batteries every month is still going to be a bit of a drag. Besides, Rocket Scream are seeing power usages in the <strong><em>micro</em></strong>-amps range when asleep.  There is clearly work to do.</p>
<h2>How to dramatically reduce the power consumption</h2>
<p>In this photo you can see I&#8217;ve identified some sections which are related to the power usage of the Pro Mini.</p>
<p><a href="/wp-content/uploads/2015/06/arduino_highlights.jpg"><img loading="lazy" class="alignleft size-medium wp-image-658" src="/wp-content/uploads/2015/06/arduino_highlights-225x300.jpg" alt="arduino_highlights" width="225" height="300" srcset="/wp-content/uploads/2015/06/arduino_highlights-225x300.jpg 225w, /wp-content/uploads/2015/06/arduino_highlights.jpg 640w" sizes="(max-width: 225px) 100vw, 225px" /></a>The red section is the power LED.  This is always on when power is applied and sucks about 0.2mA when lit. If you don&#8217;t need this to be lit all the time then you can easily remove it to save some juice.  I found the easiest way was to use a pair of cutters to snip/crush the middle of the LED and then use a soldering iron to remove the bits left over.</p>
<p>The green section is the on-board regulator.  If you are going to be supplying power to the board via a couple of AA batteries (each battery being 1.5v, so two is 3v) then you don&#8217;t need the regulator.  You can cut this off too if you like, but.. keep reading, there&#8217;s no need to hack it off.</p>
<p>Saving the best until last, the yellow section is the power-selection jumper to switch between 3.3v and 5v.  It passes the power supplied by the RAW pin through the regulator and on to the board.  The regulator is inherently inefficient.  You might think that you could bypass the on-board regulator by powering the board by apply power to the Vcc pin instead, but it still seems to power the regulator.  By simply unsoldering this jumper you can disable the on-board regulator and save loads of power.  <span style="text-decoration: underline;">Once removed you will need to apply power to the Vcc pin at ~ 3.3V</span>.  I used some solder-wick to clean up but you could just scrape it off with a soldering iron if you need to.</p>
<p>Here&#8217;s one I prepared earlier.</p>
<p><div id="attachment_662" style="width: 235px" class="wp-caption alignleft"><a href="/wp-content/uploads/2015/06/IMG_1029.jpg"><img aria-describedby="caption-attachment-662" loading="lazy" class="wp-image-662 size-medium" src="/wp-content/uploads/2015/06/IMG_1029-225x300.jpg" alt="IMG_1029" width="225" height="300" srcset="/wp-content/uploads/2015/06/IMG_1029-225x300.jpg 225w, /wp-content/uploads/2015/06/IMG_1029.jpg 640w" sizes="(max-width: 225px) 100vw, 225px" /></a><p id="caption-attachment-662" class="wp-caption-text">With the jumper and LED removed. (Red and yellow boxes from previous image)</p></div></p>
<p>&nbsp;</p>
<p>With the LED and solder jumper removed I measured the power usage again.  Running current is now down to 3.8mA, pretty much half of what it was.  But, most impressively the power used when asleep is down to 0.004mA.  <em><strong>4 microamps! Yay!</strong></em></p>
<p>Some more quick calculations based on the same usage as before:  average power consumption drops to 0.17mA.  That gives us 490 days, <strong>1.3 years run time off a pair of AA batteries.  </strong>That should allow for 2.5 minutes &#8220;work&#8221; an hour.  Waking up, taking some readings and sending them off via a radio should take well under 1 minute, which should allow for more power usage by a radio.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2>Conclusion</h2>
<p>Unless you&#8217;re going to run your Arduino off a permanently attached serial connector, then just do this.  Get yourself a couple of AA batteries &amp; a battery holder.  Apply the +ve side of the batteries to Vcc and the -ve to ground.  Stick your multi-meter in between the battery and Vcc pin to measure the lovely low current usage.  You can read the battery power being provided with the <a href="http://provideyourown.com/2012/secret-arduino-voltmeter-measure-battery-voltage/">Secret Arduino Volt-meter</a> trick.</p>
<p>I&#8217;ve got quite a few sensors around the house running with this set-up so I will monitor battery usage over the next few weeks or months and report back.</p>
<p>&nbsp;</p>
<h2>Coming Soon&#8230;</h2>
<p>A write up of my cheapo IoT sensor network, including smoke detectors, door contact sensors, movement sensors, house-plant watering monitors, room temperature sensors and a weather station.  Plus, build an IoT sensor <em><strong>and</strong></em> buy a sausage roll for less than a fiver.</p>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>/2015/06/11/howto-very-low-power-usage-on-pro-mini-v2-arduino-clone/feed/</wfw:commentRss>
			<slash:comments>9</slash:comments>
		
		
			</item>
		<item>
		<title>Multipath routing on a Raspberry Pi 2</title>
		<link>/2015/05/23/multipathrouting-rasppi2/</link>
					<comments>/2015/05/23/multipathrouting-rasppi2/#comments</comments>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Sat, 23 May 2015 13:01:00 +0000</pubDate>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[RaspberryPi]]></category>
		<guid isPermaLink="false">/?p=627</guid>

					<description><![CDATA[Skill level:  Not for the faint hearted! A few years ago, when I [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><strong>Skill level:</strong>  <em>Not for the faint hearted!</em></p>
<p>A few years ago, when I started working at home, I had a second ADSL line installed so that I could still get online if my ISP had an outage.  As well as fault tolerance I wanted to try and use all the available bandwidth rather than just have it sitting there &#8220;just in case&#8221;.  I achieved this using multi path routing and documented the solution here:  <a href="/2012/03/over-engineering-ftw/" target="_blank" rel="noopener noreferrer">Over Engineering FTW</a>.</p>
<p>This has been running really well on a Raspberry Pi for about 3 years (with an older kernel, see later in this post for why) but recently the SD card has started to fail.  Although this would be easy to fix; simply replace the SD card and copy my scripts over, the rural town I live in has just been upgraded to FTTC and so my connection speed has gone from about 8 Mbps to about 70 Mbps on each line.  The first generation Pi doesn&#8217;t have enough horsepower to cope with 70 Mbps let alone 140Mbps, and indeed the ethernet interface is only 100Mbps.  I had a Raspberry Pi 2 spare anyway so I figured I would use that and add a second gigabit NIC so I could cope with the theoretical 140 Mbps connection to the internet, and since I had two NICs I might as well use both of them.</p>
<h2>Physical layout</h2>
<p>This is what I came up with:</p>
<p><a href="http://whizzy.org/wp-content/uploads/2015/05/New-network-config.png"><img loading="lazy" class="alignleft size-medium wp-image-631" src="/wp-content/uploads/2015/05/New-network-config-267x300.png" alt="New network config" width="267" height="300" srcset="/wp-content/uploads/2015/05/New-network-config-267x300.png 267w, /wp-content/uploads/2015/05/New-network-config-768x864.png 768w, /wp-content/uploads/2015/05/New-network-config.png 849w" sizes="(max-width: 267px) 100vw, 267px" /></a></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<ul>
<li>Two lines coming from the cabinet to my house, one with Plusnet and one with TalkTalk</li>
<li>The Plusnet line:
<ul>
<li>It came with an OpenReach vDSL bridge and a crappy locked down router, so I chucked the router away and used PPPoE tools to bring up the PPP connection</li>
<li>The vDSL bridge talks to the Raspberry Pi over a VLAN to keep it separated from the other noise on the switch</li>
<li>Interface eth1.1000 is an unnumbered interface and ppoeconf uses a layer 2 discovery protocol to find the bridge</li>
<li>Once the PPP connection is established ppp1 can be used to route traffic to the internet</li>
</ul>
</li>
<li>The TalkTalk line:
<ul>
<li>It too came with a crappy router, but no OpenReach bridge.  So I had to use it.</li>
<li>The TalkTalk router talks to the Raspberry Pi over VLAN 10.  Those ports are untagged on the switch, so as far as everyone on that network knows its just a self contained LAN.</li>
<li>Interface eth0 on the Raspberry Pi has an address on that LAN and uses the TalkTalk router to talk to the internet</li>
</ul>
</li>
<li>The main LAN:
<ul>
<li>Interface eth1 is used to connect to the main LAN</li>
<li>Clients on the LAN use the Raspberry Pi as their default gateway</li>
</ul>
</li>
</ul>
<p>With me so far?  Essentially we have the normal eth0 interface of the Pi connected to one LAN with its own router and eth1 (a USB gigabit ethernet adapter) has a tagged VLAN for connection to the OpenReach bridge (eth1.1000) and an untagged default network for connecting the the main LAN.  Once the layer 2 connection with the bridge is established a PPP connection becomes the second route to the internet.</p>
<h2>The death of route caching</h2>
<p>Around version 3.6 of the Linux kernel &#8220;route caching&#8221; was <a href="http://git.kernel.org/cgit/linux/kernel/git/davem/net-next.git/commit/?id=89aef8921bfbac22f00e04f8450f6e447db13e42">removed</a>.  With route caching in place you could set up a default route with multiple hops, something along the lines of:</p>
<p>ip route add default nexthop via 192.168.1.254 dev eth0 nexthop via 192.168.2.254 dev eth1</p>
<p>When a packet needed routing to the internet the kernel would do a round-robin selection of which route to use and then <em>remember that route</em> for a period of time.  The upshot of this was, for example, that if you connected to www.bbc.co.uk and got routed first via 192.168.1.254 and so SNATed to 212.159.20.70 then all subsequent traffic for that destination also got routed via the same route and had the same source IP address.  <span style="text-decoration: underline;">Without</span> route caching the next <em>packet</em> to that same destination would (probably) use the other route, and in the case of my home user scenario would arrive from a different source IP address &#8211; my two internet connections having different IP addresses.  Although HTTP is a connectionless protocol this change of IP address did seem to freak some services out.  For protocols with connections the story is worse, e.g. packets of an SSH connection would arrive at the far end from from two different IP addresses and probably get dropped.  Route caching was a simple fix for this issue and worked well, as far as I was concerned anyway.</p>
<p>Im sure the reasons to remove it are valid, but for my simple use case it worked very well and the alternative, and now <em>only</em> option is to use connection marking to simulate the route caching.  When I first looked at it I was baffled and thought I would just go back to a pre 3.6 kernel and use route caching again.  But, in the standard Raspbian distro there isn&#8217;t a kernel old enough for the Raspberry Pi 2 to make use of it.</p>
<p>So I was stuck&#8230;  I had to use a Raspberry Pi 2 to get enough packet throughput to max out my internet connections, and I couldn&#8217;t use route caching because there wasn&#8217;t a kernel old enough.  This meant I was going to have to either compile my own kernel or learn to use connection marking.  Joy.</p>
<h2>Alternative projects</h2>
<p>The documentation for <a href="http://www.netfilter.org/">Netfilter</a> is extensive but I found a lot of it to be out of date and very hard to grok.  I found a few projects who had already implemented connection tracking/marking namely <a href="http://sourceforge.net/projects/humbertolj/">FWGuardian</a> and <a href="https://github.com/drsound/fault_tolerant_router">Fault Tolerant Router</a>.</p>
<p>FWGuardian is, as far as I can tell, designed for something orthogonal to my set up.  Where you might have lots of connections coming in to a server, or a number of offices which need to connect to other offices via pre-defined routes.  I played around with it for a while, and Humberto very kindly offered me support over email, but ultimately it was too involved and complex for my needs.  You should check out the project though if you have advanced requirements.  It&#8217;s got some brilliant features for a more enterprise oriented setup.</p>
<p>Fault Tolerant Router is a much simpler setup and matched my requirements very closely.  At it&#8217;s core it&#8217;s a Ruby script which can write your iptables rules and routing tables and constantly monitor the links.  If one goes down it can dynamically rewrite your rules and direct all traffic down the working connection.  However, it&#8217;s not expecting to use a PPP connection where gateways can change and it&#8217;s not really been tested with VLANs, although in practice it handled VLANs just fine.</p>
<p>But, at the end of the day, I wanted to learn how to do this myself and so I used the rules generated by Fault Tolerant Router to understand how connection marking was supposed to work and then started to implement my own home-grown solution for teh lolz.</p>
<h2>Multi-path routing and connection marking</h2>
<p>As I understand it, the idea with connection marking, or connection tracking &#8211; I&#8217;m not sure what the difference is, is that when a new conversation starts the packets are marked with an identifier.  You can then set <em>ip rules</em> to dictate which route packets with a particular mark take.  In essence once a new connection is established and a route selected, all other packets in that conversation take on the same mark and so the same route.  This emulates the route caching of the past.  I don&#8217;t really get how, in the case of an HTTP conversation (or flow) which is connectionless, all the packets in the conversation get marked the same.  <a href="http://www.rigacci.org/wiki/lib/exe/fetch.php/doc/appunti/linux/sa/iptables/conntrack.html">This page</a> has some more details, but I haven&#8217;t read it properly yet.  Anyway, we don&#8217;t know <em>HOW</em> it works, but it does.  Good enough.</p>
<h3>IPtables</h3>
<p>First of all we need to create the iptables configuration to set up connection marking.  Here&#8217;s the relevant extract from the iptables.save file:</p>
<pre><code>*mangle
 :PREROUTING ACCEPT [0:0]
 :POSTROUTING ACCEPT [0:0]
 :OUTPUT ACCEPT [0:0]
 :INPUT ACCEPT [0:0]
 [0:0] -A PREROUTING -i eth1 -j CONNMARK --restore-mark</code>
 <code>[0:0] -A PREROUTING -i ppp1 -m conntrack --ctstate NEW -j CONNMARK --set-mark 1</code>
 <code>[0:0] -A PREROUTING -i eth0 -m conntrack --ctstate NEW -j CONNMARK --set-mark 2</code>
 <code>[0:0] -A POSTROUTING -o ppp1 -m conntrack --ctstate NEW -j CONNMARK --set-mark 1</code>
 <code>[0:0] -A POSTROUTING -o eth0 -m conntrack --ctstate NEW -j CONNMARK --set-mark 2</code></pre>
<p><span style="color: #d5d9e8;">-i = &#8211;in-interface and -0 = &#8211;out-interface</span></p>
<p>These rules set a mark depending on which interface is used.  These changes happen in the mangle table.</p>
<p>Packets going in or out the WAN via ppp1 or eth0 which are a <strong>new</strong> connection are marked with a 1 or a 2 depending on which interface they use.  The decision about which route to use is done in the rules which we will see later.  Any packets coming in to eth1, so from the LAN, have their marks restored on the way in so they can be dealt with accordingly.</p>
<p>Now let&#8217;s have a look at the filter table:</p>
<pre><code>*filter</code>
 <code>:INPUT DROP [0:0]</code>
 <code>:FORWARD DROP [0:0]</code>
 <code>:OUTPUT ACCEPT [0:0]</code>
 <code>:LAN_WAN - [0:0]</code>
 <code>:WAN_LAN - [0:0]</code></pre>
<pre><code>[0:0] -A INPUT -i lo -j ACCEPT</code>
 <code>[0:0] -A INPUT -i eth1 -j ACCEPT</code>
 <code>[0:0] -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT</code></pre>
<pre><code>[0:0] -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT</code>
 <code>[0:0] -A FORWARD -i eth1 -o ppp1 -j LAN_WAN</code>
 <code>[0:0] -A FORWARD -i eth1 -o eth0 -j LAN_WAN</code>
 <code>[0:0] -A FORWARD -i ppp1 -o eth1 -j WAN_LAN</code>
 <code>[0:0] -A FORWARD -i eth0 -o eth1 -j WAN_LAN</code></pre>
<pre><code>## Clamp MSS (ideal for PPPoE connections)</code>
 <code>[0:0] -I FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu</code>
 <code>[0:0] -A LAN_WAN -j ACCEPT</code>
 <code>[0:0] -A WAN_LAN -j REJECT</code></pre>
<p>The default policy is set to DROP, so any packet not matching one of the rules are dropped.</p>
<p>INPUT applies to packets which are bound for the router itself.  Packets from the local interface are allowed, and packets from eth1 (the main LAN) are also allowed.</p>
<p>FORWARD applies to packets which are passing through the router on their way somewhere else.  Packets which are known to be part of an already in-progress session are allowed.  Packets are then categorised as LAN to WAN or WAN to LAN and dealt with by the rules LAN_WAN or WAN_LAN, getting accepted and rejected respectively.  All this boils down to LAN clients using the Raspberry Pi as a router and so having their packets forwarded are allowed out and packets coming in from the internet are rejected, the exception being if they are part of an on-going connection.</p>
<p>Clamping MSS to MTU deals with a particular issue with using PPPoE connections where the MTU can&#8217;t be the usual 1500 bytes.  Because a lot of ISPs block the ICMP messages that would normally deal with asking the client to send smaller packet sizes we use this handy trick to make sure that packets can go out unfragmented.  If you find that some web pages are slow to load and others are not, then try switching this on.  If you&#8217;re only using upstream ISP provided routers you probably don&#8217;t need this.</p>
<p>Lastly in iptables we enable SNAT or masquerading so that connections out to the internet appear to come from a valid internet routable IP address not our LAN IP address:</p>
<pre><code>#SNAT: LAN --&gt; WAN</code>
 <code>[0:0] -A POSTROUTING -o ppp1 -j SNAT --to-source 212.159.20.70</code>
 <code>[0:0] -A POSTROUTING -o eth0 -j SNAT --to-source 192.168.1.253</code></pre>
<h3>Routing tables</h3>
<p>We&#8217;ve configured iptables to add a mark to traffic depending on which WAN interface it is going in or out of.  But this is only marking the packets, there is no logic to make sure that packets of the same mark use the same route.  To make this happen we use ip rules.</p>
<p>First create three new routing tables by editing /etc/iproute2/rt_tables.  I&#8217;ve added this to the bottom:</p>
<pre><code>1 plusnet</code>
 <code>2 talktalk</code>
 <code>3 loadbal</code></pre>
<p>Now we add a default route to the first two of those tables:</p>
<pre><code>ip route add default via $PPP_GATEWAY_ADDRESS dev ppp1 src 212.159.20.70 table plusnet
</code><code>ip route add default via 192.168.1.254 dev eth0 src 192.168.1.253 table talktalk</code></pre>
<p>$PPP_GATEWAY_ADDRESS is set when the PPP session is established and changes.  We can look at ways to find that address later, but for now just substitute the &#8220;P-t-P&#8221; IP address from &#8220;<code>ifconfig ppp1</code>&#8221; or whatever your ppp interface number is, or in the case of an ISP-provided router, the LAN side IP of that router.</p>
<p>This is simply creating a routing table with the name of the ISP that will be used and a default route which can find its way to the internet for that ISP.</p>
<p>Next we create the loadbal routing table which is a combination of the previous two:</p>
<pre><code>ip route add default table loadbal nexthop via $PPP_GATEWAY_ADDRESS dev ppp1 nexthop via 192.168.1.254 dev eth0</code></pre>
<p>which is the same idea as we used in the old route caching days, a round-robin route which flicks between the two available routes to the internet.</p>
<h3>ip rules</h3>
<p>We&#8217;ve now created the iptables entries to track and mark traffic from each of the two ISPs and add some basic firewalling and IP masquerading.  We&#8217;ve also created a routing table for each ISP and a load-balancing table which splits the traffic between the two ISPs.</p>
<p>Now we need to create some rules to govern which of the routing tables is used for a particular connection.  The commands to do this are:</p>
<pre><code>ip rule add from $PPP_IPADDR table plusnet pref 40000
ip rule add from 192.168.1.253 table talktalk pref 40100
ip rule add fwmark 0x1 table plusnet pref 40200
ip rule add fwmark 0x2 table talktalk pref 40300
ip rule add from 0/0 table loadbal pref 40400</code></pre>
<p>The rules are matched in numerical order based on preference and once a rule matches that&#8217;s it.  The first two rules make sure that traffic from the routers uses the correct table.</p>
<p>The important rules are the last three.  Traffic which has been marked &#8220;1&#8221; will always use the plusnet routing table, traffic marked as &#8220;2&#8221; will always use the talktalk routing table.  This ensures that all traffic which is part of an on-going conversation will always use the same router out to the internet, and so always come from the same IP address.</p>
<p>The last rule only matches traffic which is not already marked i.e. new conversations.  This routing table, as can be seen in the previous section, has a multi-path route to balance traffic between the two routes out.  Once a conversation is established the IPtables conntrack rules will mark the traffic and so one of the two fwmark rules will match.</p>
<p>Now delete the main default route so that the above rules don&#8217;t get bypassed with a route in the &#8220;main&#8221; table:</p>
<pre><code>ip route del default</code></pre>
<p>And that&#8217;s it.  You should now have a router which splits the traffic fairly evenly across two internet connections and keeps tabs on which packets should go out of which routers.  I&#8217;ve had this running for a month or so now, and it seems to be working fine.  I&#8217;ve had the Pi lock up a couple of times, but I think that&#8217;s related to the USB gigabit ethernet adapter.</p>
<h2>Smart Netflix hacks</h2>
<p>Services such as <a href="https://www.unblock-us.com/">unblock-us</a> allow you to work around some geographic content blocks by acting as your DNS server and replying with the IP address of, say, the US based Netflix server instead of the UK ones.  I&#8217;ve installed dnsmasq on my Pi as well and configured it to use the Unblock DNS servers instead of my ISP or Google servers.  The clients on the LAN get their network configuration over DHCP from the Pi which sets the DNS server address for the clients to the Pi itself which then handles DNS lookups using the Unblock servers upstream.  This works really well for most Netflix clients but I was having a lot of problems getting the Chromecast to work with Netflix and Unblock US.</p>
<p>It turns out that Google have hard-coded it&#8217;s own DNS servers into the Chromecast and so your local DNS settings are ignored.  Nice one Google.</p>
<p>Because we&#8217;re using a Linux box as our router we can do this:</p>
<pre><code>iptables -t nat -A PREROUTING -s &lt;Netflix Client IP&gt;/32 -d 8.8.8.8 -p udp --dport 53 -j DNAT --to &lt;Alternative DNS Server IP Address&gt;
 iptables -t nat -A PREROUTING -s &lt;Netflix Client IP&gt;/32 -d 8.8.4.4 -p udp --dport 53 -j DNAT --to &lt;Alternative DNS Server IP Address&gt;</code></pre>
<p>Using the NAT table we rewrite the DNS lookup bound for Google&#8217;s DNS servers to send it to our dnsmasq server instead. lol.</p>
<h2>Spreading interrupts across cores</h2>
<p>Network cards have queues for tx and rx.  Higher end cards will typically have more queues, but on the Pi the on-board NIC (which is actually connected via USB) has one for tx and one for rx, as do the VLAN interfaces and the PPP interfaces.  Each of these queues has a CPU affinity and it seems that by default the queues all use the same CPU core.</p>
<p>When downloading an ISO with BitTorrent and the load-balancing set up I was able to achieve just over 10 MBytes a second.  But the Pi became really unresponsive.  Looking at top showed one CPU core maxed out in soft interrupts:</p>
<p><a href="http://whizzy.org/wp-content/uploads/2015/05/without_queues_spread.png"><img loading="lazy" class="alignleft size-medium wp-image-636" src="/wp-content/uploads/2015/05/without_queues_spread-300x159.png" alt="without_queues_spread" width="300" height="159" srcset="/wp-content/uploads/2015/05/without_queues_spread-300x159.png 300w, /wp-content/uploads/2015/05/without_queues_spread-1024x544.png 1024w, /wp-content/uploads/2015/05/without_queues_spread-768x408.png 768w, /wp-content/uploads/2015/05/without_queues_spread-1536x816.png 1536w, /wp-content/uploads/2015/05/without_queues_spread-1200x638.png 1200w, /wp-content/uploads/2015/05/without_queues_spread.png 1735w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>By adjusting the CPU affinity to spread these IRQs across multiple CPUs I squeeze out a tiny bit more network throughput, but more usefully the Pi remained responsive under heavy load:</p>
<p><a href="http://whizzy.org/wp-content/uploads/2015/05/with_queues_spread.png"><img loading="lazy" class="alignleft size-medium wp-image-637" src="/wp-content/uploads/2015/05/with_queues_spread-300x162.png" alt="with_queues_spread" width="300" height="162" srcset="/wp-content/uploads/2015/05/with_queues_spread-300x162.png 300w, /wp-content/uploads/2015/05/with_queues_spread-1024x553.png 1024w, /wp-content/uploads/2015/05/with_queues_spread-768x415.png 768w, /wp-content/uploads/2015/05/with_queues_spread-1536x830.png 1536w, /wp-content/uploads/2015/05/with_queues_spread-1200x649.png 1200w, /wp-content/uploads/2015/05/with_queues_spread.png 1902w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>The commands I used to do this are:</p>
<pre><code>echo 1 &gt; /sys/class/net/eth0/queues/rx-0/rps_cpus
echo 1 &gt; /sys/class/net/eth0/queues/tx-0/xps_cpus
echo 2 &gt; /sys/class/net/eth1/queues/tx-0/xps_cpus
echo 2 &gt; /sys/class/net/eth1/queues/rx-0/rps_cpus
echo 4 &gt; /sys/class/net/eth1.1000/queues/tx-0/xps_cpus
echo 4 &gt; /sys/class/net/eth1.1000/queues/rx-0/rps_cpus
echo 8 &gt; /sys/class/net/ppp1/queues/tx-0/xps_cpus
echo 8 &gt; /sys/class/net/ppp1/queues/rx-0/rps_cpus</code></pre>
<h2>Source</h2>
<p>Here&#8217;s a tgz file containing my iptables rules and a script to set up the above: <a href="/wp-content/uploads/2015/05/routing.tgz">routing</a></p>
<p><em><strong>Update:</strong></em>  I&#8217;ve put the files in this Github repo:  <a href="https://github.com/8none1/multipathrouting">https://github.com/8none1/multipathrouting</a></p>
<p>If you&#8217;re interested in helping to make the scripts a bit more generic and adding fault-tolerance let me know.</p>
]]></content:encoded>
					
					<wfw:commentRss>/2015/05/23/multipathrouting-rasppi2/feed/</wfw:commentRss>
			<slash:comments>7</slash:comments>
		
		
			</item>
		<item>
		<title>Snapping Mosquitto MQTT broker</title>
		<link>/2015/02/04/snapping-mosquitto-mqtt-broker/</link>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Wed, 04 Feb 2015 17:32:44 +0000</pubDate>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[Making the world a better place]]></category>
		<category><![CDATA[RaspberryPi]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<guid isPermaLink="false">/?p=598</guid>

					<description><![CDATA[As part of my ever expanding home automation system I wanted to use [&#8230;]]]></description>
										<content:encoded><![CDATA[<p style="text-align: justify;"><em>As part of my ever expanding home automation system I wanted to use MQTT to publish data on my network. With the release of the Raspberry Pi 2 I can run Ubuntu Core to create a reliable, secure and easily updated server which is a perfect fit for requirements of an MQTT broker and general HA controller. I asked some Ubuntu friends to help me package Mosquitto as a Snap, and in return I would write down how we did it. Here&#8217;s the story&#8230;</em></p>
<p>Start by reading this: <a title="https://developer.ubuntu.com/en/snappy/" href="https://developer.ubuntu.com/en/snappy/">https://developer.ubuntu.com/en/snappy/</a></p>
<p style="text-align: justify;"><span style="text-decoration: underline;">In summary;</span> a Snappy application is secure because it&#8217;s wrapped with AppArmor. It&#8217;s easier to install and upgrade because everything is packaged in a single file and installed to a single location. That location is backed-up before you install a new version, and so if the installation goes wrong you can revert to the previous version easily by copying the original files back (or rather, Snappy will do all of that for you). Simplifying things slightly there are two types of Snappy &#8220;application&#8221;: Apps and Frameworks. Frameworks can extend the OS and provide a mediation layer to access shared resources. Apps are your more traditional top-level items which can use the provided frameworks, or bundle everything they need in to their Snap. This makes things much easier for app providers because they are now in charge &#8211; they can be assured that no library will change underneath them.  This is a huge benefit!</p>
<h2>Let&#8217;s get Mosquitto snapped.</h2>
<h3>1. Install QEMU to run an Ubuntu Core machine</h3>
<p><a title="http://www.ubuntu.com/cloud/tools/snappy#snappy-local" href="http://www.ubuntu.com/cloud/tools/snappy#snappy-local">http://www.ubuntu.com/cloud/tools/snappy#snappy-local</a></p>
<p>First we install the KVM hypervisor:</p>
<pre style="padding-left: 60px;">sudo apt-get install qemu-kvm</pre>
<p>Then check everything is as it should be with:</p>
<pre style="padding-left: 60px;">kvm-ok</pre>
<p>Now download the latest Ubuntu Core image from here: <a title="http://cdimage.ubuntu.com/ubuntu-core/preview/" href="http://cdimage.ubuntu.com/ubuntu-core/preview/">http://cdimage.ubuntu.com/ubuntu-core/preview/</a>  At the time of writing this is the newest x86-64 image: <a title="http://cdimage.ubuntu.com/ubuntu-core/preview/ubuntu-core-alpha-02_amd64-virt.img" href="http://cdimage.ubuntu.com/ubuntu-core/preview/ubuntu-core-alpha-02_amd64-virt.img">http://cdimage.ubuntu.com/ubuntu-core/preview/ubuntu-core-alpha-02_amd64-virt.img</a></p>
<p>Then launch the virtual machine. This command port forwards 8022 on your local machine to 22 on the virtual machine, so you can SSH to port 8022 on localhost and actually connect to the Ubuntu Core machine. It gives the Core machine 512MB of RAM, nicely achievable on a modest budget (The Pi2 has 1 GB).  We also forward port 1883 from to the VM, which will allow us to connect to the Mosquitto server on our VM once it&#8217;s all installed.</p>
<pre style="padding-left: 60px;">kvm -m 512 -redir :8022::22 -redir :1883::1883 &lt;vm image file&gt;</pre>
<p>Once it&#8217;s booted you can connect to it with SSH. The username and password are &#8220;ubuntu&#8221;.</p>
<pre style="padding-left: 60px;">ssh -p 8022 ubuntu@localhost</pre>
<p>To make things a bit easier, why not use key authentication? On your host machine:</p>
<pre style="padding-left: 60px;">ssh-copy-id -p 8022 ubuntu@localhost</pre>
<p>We should also upgrade our Ubuntu Core VM before we start.  SSH in to your box and run:</p>
<pre style="padding-left: 60px;">sudo snappy update
sudo reboot</pre>
<h3>2. Build Mosquitto in the right way</h3>
<p>Back on your host (not the virtual machine you just created above) create some directories to hold the code and download the latest stable source and the build dependencies for Mosquitto:</p>
<pre style="padding-left: 60px;">sudo apt-get install build-essential cmake
sudo apt-get build-dep mosquitto</pre>
<pre style="padding-left: 60px;">mkdir -p mosquitto/install mosquitto/build</pre>
<pre style="padding-left: 60px;">cd mosquitto</pre>
<pre style="padding-left: 60px;">wget http://mosquitto.org/files/source/mosquitto-1.3.5.tar.gz</pre>
<pre style="padding-left: 60px;">tar xvzf mosquitto-1.3.5.tar.gz</pre>
<pre style="padding-left: 60px;">cd build</pre>
<p>Time to build Mosquitto.  Before you run the commands below, a bit of background information.  The cmake line will force cmake to install the binaries to the location specified with INSTALL_PREFIX, rather than /usr/local.  This is required to bundle all of the binaries and other files to the &#8220;install&#8221; directory we created above, making it possible to package as a Snappy.</p>
<pre style="padding-left: 60px;">cmake -DCMAKE_INSTALL_PREFIX=`readlink -f ../install/` ../mosquitto-1.3.5</pre>
<pre style="padding-left: 60px;">make -j`nproc`

make install</pre>
<p>nproc spits out the number of processor cores you have, so the make line above will use as many processor cores as you have available.  It&#8217;s not required, and for Mosquitto which is fairly small it&#8217;s not worth worrying about, but for a bigger job this is quite handy.</p>
<p>If you look in the &#8220;../install&#8221; directory you&#8217;ll see a familiar structure containing all the goodies needed by Mosquitto.</p>
<h3>3. Find the libraries needed and copy them in to your Snappy project</h3>
<p>Change in to the install/lib directory and use ldd to display the linked libraries for the two main .so files:</p>
<pre style="padding-left: 60px;">ldd lib/libmosquitto.so.1.3.5 lib/libmosquittopp.so.1.3.5 | grep '=&gt;' | awk '{ print $1 }' | sort | uniq</pre>
<p>This uses ldd to show the libraries required by Mosquitto, and then sorts them in to a nice list. You&#8217;ll see something like this:</p>
<pre style="padding-left: 60px;">libcares.so.2
libcrypto.so.1.0.0
libc.so.6
libdl.so.2
libgcc_s.so.1
libmosquitto.so.1
libm.so.6
libpthread.so.0
librt.so.1
libssl.so.1.0.0
libstdc++.so.6
linux-vdso.so.1</pre>
<p>Now, on the Ubuntu Core machine we can run this little script:</p>
<pre style="padding-left: 60px;">for i in `cat`; do find /lib /usr/lib -name $i; done</pre>
<p>Copy the list from the previous command to the clipboard and then paste it in to terminal where this command is running and hit Ctrl-D to submit the list.  The script will then search Ubuntu Core for the libraries required.  If it finds them they will be displayed, if it doesn&#8217;t then they are not available in Ubuntu Core by default and will need to be included in your Snappy package.</p>
<p><code>linux-vdso</code> is the Linux kernel and is available on every Linux system by default, so we don&#8217;t need to provide that specifically.</p>
<p><code>libssl, libcrypto, libpthread, librt, libc </code>and<code> libdl</code> are all available in Ubuntu Core by default &#8211; so we don&#8217;t need those either.</p>
<p>That leaves just <code>libcares</code> to be copied in to our package.</p>
<pre style="padding-left: 60px;"> cp /usr/lib/x86_64-linux-gnu/libcares.so.2.1.0 .</pre>
<p>We should already be in the &#8216;lib&#8217; directory, hence the &#8216;.&#8217; above.  We are copying libcares in to the lib directory of our Snap, and when we run the Snap we will pass in the library path to make sure Mosquitto can find it.  More on this later.</p>
<h3>4. Add the meta data required for the Snappy package</h3>
<p>Reference: <a title=" https://developer.ubuntu.com/en/snappy/guides/packaging-format-apps/" href="https://developer.ubuntu.com/en/snappy/guides/packaging-format-apps/">https://developer.ubuntu.com/en/snappy/guides/packaging-format-apps/</a></p>
<p>Create the meta data directory inside the install directory (change to the install directory, it should just be cd ..):</p>
<pre style="padding-left: 60px;">mkdir meta</pre>
<p>Create the package.yaml file:</p>
<pre style="padding-left: 60px;">nano meta/package.yaml</pre>
<p>And this is what we&#8217;re putting in it:</p>
<pre style="padding-left: 60px;">name: mosquitto.willcooke
architecture: amd64
version: 1.3.5
icon:
services:
 - name: mosquitto
 start: ./sbin/mosquitto.sh
ports:
 required: 1883</pre>
<p>Information about these fields and what they mean is available in the reference linked to above, but they are easily understandable.  A comment on the name though, you need to append .&lt;yournamespace&gt; where your namespace is as you select in your Ubuntu myapps account.  One thing to mention, you can see that to start our Snap we are calling a shell script.  This allows us to pass in extra options to Mosquitto when it runs.</p>
<p>Next we need to create a readme file:</p>
<pre style="padding-left: 60px;">nano meta/readme.md</pre>
<p>This file needs to contain at least a couple of non-blank lines.  Here&#8217;s what we put in it:</p>
<pre style="padding-left: 60px;">This is a Snappy package for Mosquitto MQTT broker.</pre>
<pre style="padding-left: 60px;">Information about Mosquitto is available here:  http://mosquitto.org/</pre>
<pre style="padding-left: 60px;">Information about MQTT is available here: http://mqtt.org/</pre>
<p>We also need to configure our Mosquitto server, by editing the conf file.  Most of the settings can be left as default, so we will create a new conf file with only the bits in we need.</p>
<pre style="padding-left: 60px;">mv etc/mosquitto/mosquitto.conf etc/mosquitto/mosquitto.conf.ori</pre>
<pre style="padding-left: 60px;">nano etc/mosquitto/mosquitto.conf</pre>
<p>Add these two lines:</p>
<pre style="padding-left: 60px;">user root
persistence_location /var/apps/mosquitto/current/</pre>
<p>We need to change this to run as root.  Since our Snap will be confined there is no risk here.  I expect the ability to run as non-root users when using Snappy will be improved, but really it&#8217;s not necessary.</p>
<p>We also need to add a small shell script to start Mosquitto with the right options.  Create a file in install/sbin called mosquitto.sh:</p>
<pre style="padding-left: 60px;">nano sbin/mosquitto.sh</pre>
<p>And add this:</p>
<pre style="padding-left: 30px;">#!/bin/sh
LD_LIBRARY_PATH=./lib:$LD_LIBRARY_PATH exec ./sbin/mosquitto -c etc/mosquitto/mosquitto.conf</pre>
<p>We are specifying where to find the extra libraries we require and where to find the conf file.  Make that file executable:</p>
<pre style="padding-left: 60px;">chmod +x sbin/mosquitto.sh</pre>
<h3>5. Build your Snappy package</h3>
<p>Add the Snappy PPA to get the build tools, and then install them:</p>
<pre style="padding-left: 60px;">sudo add-apt-repository ppa:snappy-dev/beta
sudo apt-get update
sudo apt-get dist-upgrade
sudo apt install snappy-tools</pre>
<p>In your <code>install</code> directory run:</p>
<pre style="padding-left: 60px;">snappy build .</pre>
<p>If you see an error about ImportError: No module named &#8216;click.repository&#8217; then you likely have a clash between the Click library version in the SDK team PPA and the version in the Snappy PPA.  This will be fixed soon, but in the meantime I would suggest installing ppa-purge via apt-get and then running <code>sudo ppa-purge ppa:ubuntu-sdk-team/ppa</code>.</p>
<p>If you see an error about &#8220;expected &lt;block end&gt;&#8221; in the package.yaml check the whitespace in the file.  It&#8217;s likely a copy and paste error.</p>
<h3>6. Install your Snappy package</h3>
<p>Once you have your .snap file you can install it to your virtual machine like this:</p>
<pre>snappy-remote --url=ssh://localhost:8022 install ./mosquitto_1.3.5_amd64.snap</pre>
<p>&nbsp;</p>
<h3>7. Test your Snappy package</h3>
<p>If everything has gone to plan Mosquitto should now be running on your virtual machine.  In order to test you&#8217;ll need to write a test Publisher and Subscriber.  I used the Python Paho library.</p>
<p>Here&#8217;s an example Publisher:</p>
<pre style="padding-left: 60px;">#!/usr/bin/python</pre>
<pre style="padding-left: 60px;">import paho.mqtt.client as mqtt
from datetime import datetime
from time import sleep</pre>
<pre style="padding-left: 60px;">def send_mqtt(topic, message):
 log("Sending MQTT")
 log("Topic: "+topic)
 log("Message: "+message)
 mqttc.reconnect()
 mqttc.publish(topic, message)
 mqttc.loop() 
 mqttc.disconnect()</pre>
<pre style="padding-left: 60px;">print "Time server starting up...."
mqttc = mqtt.Client("python_pub")
mqttc.connect("localhost", 1883)</pre>
<pre style="padding-left: 60px;">while True:
 tstr = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
 send_mqtt("/information/time",tstr)
 sleep(10)</pre>
<p>And here&#8217;s an example Subscriber:</p>
<pre style="padding-left: 60px;">#!/usr/bin/python</pre>
<pre style="padding-left: 60px;">import paho.mqtt.client as mqtt
import datetime</pre>
<pre style="padding-left: 60px;">def on_connect(client, userdata, rc):
 print "Connected with result code "+str(rc)
 client.subscribe("#")
 
def on_message(client, userdata, msg):
 print "Topic: ", msg.topic+'\nMessage: '+str(msg.payload)
 
 
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message</pre>
<pre style="padding-left: 60px;">client.connect("localhost", 1883, 60)</pre>
<pre style="padding-left: 60px;">client.loop_forever()</pre>
<p>&nbsp;</p>
<h2>What&#8217;s next?</h2>
<p>We&#8217;ve built a Snappy package for amd64 (or whatever your native architecture is), but we really need to be cross-architecture to give people the best choice of platform on which to use the package.  This involves cross compiling, which can be tricky to put it mildly.</p>
<p>I spoke to <a title="https://plus.google.com/+AlexanderSack/posts" href="https://plus.google.com/+AlexanderSack/posts">Alexander Sack</a>, the Director of Ubuntu Core, and asked what was coming next for Snappy and I was very excited to hear about easier cross-compilation methods as well as a cool script to help automate gathering the libraries in to your package.  I&#8217;ll find out more about these and follow up with another post about</p>
<h2>Special Thanks</h2>
<p>A huge &#8220;Thank You!&#8221; to <a title="https://plus.google.com/113078171667682980510/posts" href="https://plus.google.com/113078171667682980510/posts">Saviq</a> and <a title="https://www.google.com/+DidierRoche" href="https://www.google.com/+DidierRoche">Didrocks</a> for doing the actual work and letting me watch.</p>
<p>&nbsp;</p>
<h2>Where to get Snappy Mosquitto</h2>
<p>amd64 version:  <a title="https://myapps.developer.ubuntu.com/dev/click-apps/ubuntu/1500/" href="https://myapps.developer.ubuntu.com/dev/click-apps/ubuntu/1500/">https://myapps.developer.ubuntu.com/dev/click-apps/ubuntu/1500/</a><br />
armhf version: <a title="https://myapps.developer.ubuntu.com/dev/click-apps/ubuntu/1502/" href="https://myapps.developer.ubuntu.com/dev/click-apps/ubuntu/1502/">https://myapps.developer.ubuntu.com/dev/click-apps/ubuntu/1502/</a> (please note, I haven&#8217;t been able to test the ARM version because of a lack of hardware.  If it doesn&#8217;t work let me know and I can fix it.)</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Recording screencasts from the Unity 8 Desktop Preview</title>
		<link>/2014/08/28/recording-screencasts-from-the-unity-8-desktop-preview/</link>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Thu, 28 Aug 2014 12:33:10 +0000</pubDate>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[Making the world a better place]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<guid isPermaLink="false">/?p=590</guid>

					<description><![CDATA[Obtaining and running Unity 8 Desktop Preview If you like playing with new [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Obtaining and running Unity 8 Desktop Preview</h1>
<p>If you like playing with new toys you might have already downloaded and tried the Unity 8 Desktop Preview (available here:  <a href="http://cdimage.ubuntu.com/ubuntu-desktop-next/daily-live/current/" target="_blank" rel="noopener noreferrer">http://cdimage.ubuntu.com/ubuntu-desktop-next/daily-live/current/</a>)</p>
<p>If you haven&#8217;t, you should take it for a spin.  If you have an Intel graphics everything should be fine and dandy, if not YMMV at the moment.</p>
<ol>
<li>Download the ISO</li>
<li>Find a spare &gt;1GB USB thumb drive</li>
<li>Run &#8220;disks&#8221; via the dash</li>
<li>Highlight your USB drive and from the cog icon on the right choose &#8220;Restore Disk Image&#8230;&#8221;</li>
<li>Select your ISO and &#8220;Start Restoring&#8221;  &#8211; this will of course erase everything else on your USB stick</li>
<li>Done</li>
</ol>
<p>You can now boot from your USB stick and have a play with Unity 8.  Right now you&#8217;ll be seeing the Phone view of Unity 8, but that will all be changing in time.</p>
<h1>Capturing a screencast</h1>
<p>Once you&#8217;ve got everything up and running you might like to make a few screencasts, so how do you do it?  Well, the Mir developers have provided us with the mirscreencast tool so let&#8217;s use that:</p>
<p>Switch to tty1 (ctrl+alt+f1) and log in and run:</p>
<pre>mirscreencast --file &lt;output file&gt; -m /run/lightdm-mir-0</pre>
<p>Then switch back to tty8 (ctrl-alt-f8) and use Unity.</p>
<p>Your file will now be filling up FAST.  Mirscreencast will be trying to write every raw frame to that file, probably at a rate of 60 frames a second.  To kill mirscreencast I first hit ctrl-z and then:</p>
<pre> pkill -9 mirscreencast</pre>
<p>but there is probably a better way.</p>
<h1>Capturing a better screencast</h1>
<p>There are a few command line options for mirscreencast which will can help us shrink the file size a bit:</p>
<pre>mirscreencast --file &lt;output file&gt; -m /run/lightdm-mir-0 -s 683 384 -n 3600</pre>
<p>The option &#8220;-s&#8221; will resize the captured frames.  Note that 683 384 is exactly half my native resolution, so you will need to adjust this to your display.</p>
<p>The option &#8220;-n&#8221; will capture n frames and then stop.  At 60 frames a second, 3600 frames is one minute.  If you use -n then mirscreencast will exit gracefully at the end.</p>
<h1>Playing back your screencast</h1>
<p>I am lucky enough to have a spare machine with a touch screen just for running Unity 8 on (<a href="http://www.dell.com/uk/dfh/p/inspiron-11-3137/pd" target="_blank" rel="noopener noreferrer">http://www.dell.com/uk/dfh/p/inspiron-11-3137/pd</a>) so I SCP the raw video file on to my main machine for playback and editing.</p>
<p>I use mplayer for most of my video playback and encoding needs and it will happily play the raw video file, but it needs a few pointers:</p>
<pre>mplayer -demuxer rawvideo -rawvideo fps=60:w=683:h=384:format=bgra &lt;filename&gt;</pre>
<p>or, to convert the raw file into something which you can edit in OpenShot try this:</p>
<pre>mencoder -demuxer rawvideo -rawvideo fps=60:w=683:h=384:format=bgra -ovc x264 -o &lt;output filename&gt; &lt;filename&gt;</pre>
<p>And then you can edit and upload the processed file.  When I export from OpenShot I use the &#8220;Web&#8221; profile, then target &#8220;YouTube-HD&#8221;, &#8220;HD 720p 29.97 fps&#8221; &#8220;Med&#8221; &#8211; it&#8217;s a bit overly compressed, but it looks OK.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Raspberry Pi powered heating controller (Part 4)</title>
		<link>/2014/02/04/raspberry-pi-powered-heating-controller-part-4/</link>
					<comments>/2014/02/04/raspberry-pi-powered-heating-controller-part-4/#comments</comments>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Tue, 04 Feb 2014 19:25:00 +0000</pubDate>
				<category><![CDATA[Making the world a better place]]></category>
		<category><![CDATA[RaspberryPi]]></category>
		<guid isPermaLink="false">/?p=571</guid>

					<description><![CDATA[It&#8217;s really happening!  The breadboard prototype has been running the heating and hot [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><img loading="lazy" class="size-medium wp-image-572 alignleft" style="background-color: black;" alt="Heating PCB" src="/wp-content/uploads/2014/02/heating5_pcb-254x300.png" width="254" height="300" srcset="/wp-content/uploads/2014/02/heating5_pcb-254x300.png 254w, /wp-content/uploads/2014/02/heating5_pcb-768x905.png 768w, /wp-content/uploads/2014/02/heating5_pcb.png 822w" sizes="(max-width: 254px) 100vw, 254px" /></p>
<p>It&#8217;s really happening!  The breadboard prototype has been running the heating and hot water for a week or so now, and so far nothing has caught on fire.  The relays are happy, they&#8217;re not getting warm or anything, the Pi is turning things on and off when it&#8217;s supposed to, the REST API is working, and I&#8217;ve knocked up a quick Web interface to switch things remotely.  Last night for the first time I switched the heating on from the sofa, because I was a little bit cold.</p>
<h2 style="text-align: center;">Great success!</h2>
<p style="text-align: center;"><img loading="lazy" class="wp-image-573 aligncenter" alt="Borat" src="http://whizzy.org/wp-content/uploads/2014/02/borat.jpg" width="297" height="297" srcset="/wp-content/uploads/2014/02/borat.jpg 297w, /wp-content/uploads/2014/02/borat-150x150.jpg 150w" sizes="(max-width: 297px) 100vw, 297px" /></p>
<p><span style="font-size: 14px; line-height: 1.5em;">I&#8217;ve turned the breadboard layout in to a PCB design and today at 09:11 UTC it was sent off for manufacture, I should have it back in a week.  All the other components are on their way and so next weekend I should be able to put everything together and solder it to the board.  With a bit of luck it will work first time.</span></p>
<p>I&#8217;m quite please with the board layout, it&#8217;s a fairly useful breakout board for the Raspberry Pi.  In the future I would like to re-work it with smaller traces so that it can fit directly on top of the Pi.</p>
<p>The software to drive everything is rather basic, but I will make it available via Github anyway, it might come in handy.  I will be working on this over the coming months, so it should improve soon.  You&#8217;ll need a MySQL server set up.  The schema for the database is included in the repo.  The whole thing has grown organically and so the naming and structure is poor, but it works.</p>
<p>Code:  <a href="https://github.com/8none1/heating">https://github.com/8none1/heating</a></p>
<p><span style="font-size: 14px; line-height: 1.5em;">I&#8217;ve starting making some 1wire temperature sensors which I will place in various rooms and hook up back to the Pi via cat5.</span></p>
<p><a href="http://whizzy.org/wp-content/uploads/2014/02/1wire_heat.jpg"><img loading="lazy" class="alignleft size-medium wp-image-574" alt="1wire_heat" src="/wp-content/uploads/2014/02/1wire_heat-300x225.jpg" width="300" height="225" srcset="/wp-content/uploads/2014/02/1wire_heat-300x225.jpg 300w, /wp-content/uploads/2014/02/1wire_heat.jpg 764w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<p>I won&#8217;t be able to control individual radiators at the moment, but I can set a target temperature for a given room and rely on the TRVs to control the temperature in other rooms.</p>
<p>I&#8217;ll also be adding outside temperature sensors and looking to replace the main room stat with another Pi in the future.</p>
<p>In summary then, I should have the final thing built in the next couple of weeks.  More to follow when that happens.  I&#8217;m considering looking at moving the whole thing to a micro controller rather than a Pi, that would reduce the BOM quite considerably, and might even warrant a commercial product in the long run &#8211; a hackable heating controller.  Is this something people might be interested in?</p>
<h2>Further Updates</h2>
<ul>
<li><a title="Raspberry Pi powered heating controller (Part 1)" href="/2014/01/raspberry-pi-powered-heating-controller-part-1/">Part 1</a></li>
<li><a title="Raspberry Pi powered heating controller (Part 2)" href="/2014/01/raspberry-pi-powered-heating-controller-part-2/">Part 2</a></li>
<li><a title="Raspberry Pi powered heating controller (Part 3)" href="/2014/01/raspberry-pi-powered-heating-controller-part-3/">Part 3</a></li>
</ul>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>/2014/02/04/raspberry-pi-powered-heating-controller-part-4/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title>Raspberry Pi powered heating controller (Part 3)</title>
		<link>/2014/01/27/raspberry-pi-powered-heating-controller-part-3/</link>
					<comments>/2014/01/27/raspberry-pi-powered-heating-controller-part-3/#comments</comments>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Mon, 27 Jan 2014 14:38:03 +0000</pubDate>
				<category><![CDATA[Making the world a better place]]></category>
		<category><![CDATA[RaspberryPi]]></category>
		<guid isPermaLink="false">/?p=561</guid>

					<description><![CDATA[I&#8217;ve had all the parts hooked up on breadboard for a few weeks [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>I&#8217;ve had all the parts hooked up on breadboard for a few weeks now, and in theory everything works.  I haven&#8217;t actually tested the prototype with the real heating system yet as it&#8217;s been cold and I don&#8217;t want to risk blowing anything up and having to deal with a cold house and an angry family.  Sometime in the next month or so I will do that, but as far as I can tell it will Just Work (lolz).</p>
<p><div id="attachment_562" style="width: 310px" class="wp-caption alignnone"><a href="http://whizzy.org/wp-content/uploads/2014/01/final_breadboard.jpg"><img aria-describedby="caption-attachment-562" loading="lazy" class="size-medium wp-image-562 " alt="The final circuit design" src="/wp-content/uploads/2014/01/final_breadboard-300x225.jpg" width="300" height="225" /></a><p id="caption-attachment-562" class="wp-caption-text">The final circuit design</p></div></p>
<p>In the meantime I&#8217;ve been thinking about the software to drive the thing.</p>
<p>My programming skills are pretty basic so I have been trying to keep everything as simple as possible.  <span style="font-size: 14px; line-height: 1.5em;"> It became apparent that I was going to need some inter-process communication so that I could handle switching things on and off from outside the controller program (for web control etc).  This presented me with a problem as all the basic reading from files/FIFOs were blocking &#8211; in that they would sit and wait for a &#8220;command&#8221; to be received before continuing &#8211; and that was too limiting for my needs.  I was going to </span><span style="font-size: 14px; line-height: 1.5em;">have to deal with some kind of threading.  This troubled me deeply.  The good people of Google+ suggested a few options and in the end I decided a RESTful interface was the way to go as it should be accessible from the widest range of other languages I might have to use, and especially easy from a web browser.</span></p>
<p>Originally I had imagined that I would have a single Python script to handle pretty much everything, including:</p>
<ul>
<li>Switching the relays on/off</li>
<li>Responding to button presses</li>
<li>Proving a scheduling engine for standard &#8220;on at this time, off at this time&#8221; behaviours</li>
<li>Providing a way for other things to control the system</li>
<li>Monitoring temperatures around the house</li>
<li>Intelligent switching (e.g. it&#8217;s extra cold this morning, turn on early)</li>
</ul>
<p>That way, I figured, I could just write one script and each function could interact with each other function very easily.  But following a conversation with Mark S. a few years ago, and then more recently with Stuart L. I was starting to think that the monolithic architecture was not the way to go and instead I should push the intelligence out to the edges and the main loop should just deal with the basic on/off functionality.  I was worried that if something went wrong with the electronics, for example the heating turned on but never off, then it would be difficult to spot from outside the main loop.  But, given that the heating system has a lot of built-in safety features like room stats, boiler stats and hot water stats which are all wired in series with the mains that won&#8217;t be a problem, and besides the current controller doesn&#8217;t do anything more intelligent than ON or OFF.</p>
<p>To that end I decided that I&#8217;d go with this architecture:</p>
<p><a href="http://whizzy.org/wp-content/uploads/2014/01/Heating-System-Architecture.jpg"><img loading="lazy" class="size-medium wp-image-564 alignnone" alt="Heating System Architecture" src="/wp-content/uploads/2014/01/Heating-System-Architecture-300x250.jpg" width="300" height="250" /></a></p>
<p>The Relay Controller would handle switching the power on and off in the right order to the right outputs, it would handle the switches for manual override, provide feedback via LEDs, and it would provide a REST interface for anything else to control the system or find out what the current state is.  This way I can write a much more simple script to manage the scheduler for example.  It can run independently and then simply poke the relay controller at the right time.  I also decided that the relay controller would only have the ability to switch <strong>off</strong> after a certain period of time.  The default will be 60 mins.  This further simplifies things and puts just the right amount of intelligence in the core.  The scheduler just says &#8220;switch on now, and off again in 90 minutes&#8221;.  If the scheduler crashes the correct state is maintained by the controller and things just pick up from where they were when the scheduler starts again.  If the controller crashes then the power is removed from the system and it &#8220;fails safe&#8221;.</p>
<p>The REST API is simple:</p>
<ul>
<li>/get/ch <em>or</em> hw/ &#8211; gets the current state of the system as a JSON object. e.g. &#8220;http://10.0.0.1/get/ch&#8221;</li>
<li>/set/<em>ch</em> or <em>hw</em>/on <em>or</em> off &#8211; switch the system on or off.  e.g. &#8220;http://10.0.0.1/set/ch/on&#8221; switches the central eating on for the default time (60 minutes)</li>
<li>/set/ch <em>or</em> hw/on/n &#8211; switch the system on for n minutes.  e.g. &#8220;http://10.0.0.1/set/hw/on/90&#8221; switches hot water on for 90 minutes</li>
</ul>
<p>I used the Python SimpleHTTPServer, the ThreadedHTTPServer and threading.Thread.</p>
<p>I&#8217;m certain that it could be rewritten using proper OO methods and whatnot, and there is quite a lot of code which started out as an idea which then became redundant, but if you&#8217;re interested it&#8217;s available here:  <a href="/wp-content/uploads/2014/01/piheat.txt">piheat</a><a href="/wp-content/uploads/2014/01/piheat.txt"><br />
</a></p>
<p><span style="font-size: 14px; line-height: 1.5em;">Next on the agenda is to draw a PCB and get it made (once I&#8217;ve tested the circuit properly) and work on the scheduling engine.  At this rate I should be finished right around the time when we don&#8217;t need to use the heating any more.</span></p>
<h2>Further Updates</h2>
<ul>
<li><a title="Raspberry Pi powered heating controller (Part 1)" href="/2014/01/raspberry-pi-powered-heating-controller-part-1/">Part 1</a></li>
<li><a title="Raspberry Pi powered heating controller (Part 2)" href="/2014/01/raspberry-pi-powered-heating-controller-part-2/">Part 2</a></li>
<li><a title="Raspberry Pi powered heating controller (Part 4)" href="/2014/02/raspberry-pi-powered-heating-controller-part-4/">Part 4</a></li>
</ul>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>/2014/01/27/raspberry-pi-powered-heating-controller-part-3/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Raspberry Pi powered heating controller (Part 2)</title>
		<link>/2014/01/11/raspberry-pi-powered-heating-controller-part-2/</link>
					<comments>/2014/01/11/raspberry-pi-powered-heating-controller-part-2/#comments</comments>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Sat, 11 Jan 2014 21:57:25 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">/?p=547</guid>

					<description><![CDATA[In which one Raspberry Pi is seen. In part one of this series [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><span style="color: #888888;"><em>In which one Raspberry Pi is seen.</em></span></p>
<p>In <a title="Raspberry Pi powered heating controller (Part 1)" href="/2014/01/raspberry-pi-powered-heating-controller-part-1/">part one of this series</a> I explained how the central heating system was wired up and what electrical connections you needed to make to switch your heating and hot water on and off.</p>
<p style="text-align: center;"><a href="http://whizzy.org/wp-content/uploads/2014/01/photo.jpg"><img loading="lazy" class="size-medium wp-image-554 aligncenter" alt="Heating Controller - breadboard" src="/wp-content/uploads/2014/01/photo-300x225.jpg" width="300" height="225" srcset="/wp-content/uploads/2014/01/photo-300x225.jpg 300w, /wp-content/uploads/2014/01/photo-1024x768.jpg 1024w, /wp-content/uploads/2014/01/photo-768x576.jpg 768w, /wp-content/uploads/2014/01/photo-1536x1152.jpg 1536w, /wp-content/uploads/2014/01/photo-2048x1536.jpg 2048w, /wp-content/uploads/2014/01/photo-1200x900.jpg 1200w, /wp-content/uploads/2014/01/photo-1980x1485.jpg 1980w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<p>I ordered all the parts and now I&#8217;ve plugged them all together.  Here&#8217;s a quick video demonstrating how it will all work.</p>
<p><iframe loading="lazy" width="770" height="433" src="https://www.youtube.com/embed/5pGTKUu8E4Q?feature=oembed" frameborder="0" allowfullscreen></iframe></p>
<h2>Further Updates</h2>
<ul>
<li><a title="Raspberry Pi powered heating controller (Part 1)" href="/2014/01/raspberry-pi-powered-heating-controller-part-1/">Part 1</a></li>
<li><a title="Raspberry Pi powered heating controller (Part 3)" href="/2014/01/raspberry-pi-powered-heating-controller-part-3/">Part 3</a></li>
<li><a title="Raspberry Pi powered heating controller (Part 4)" href="/2014/02/raspberry-pi-powered-heating-controller-part-4/">Part 4</a></li>
</ul>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>/2014/01/11/raspberry-pi-powered-heating-controller-part-2/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Raspberry Pi powered heating controller (Part 1)</title>
		<link>/2014/01/04/raspberry-pi-powered-heating-controller-part-1/</link>
					<comments>/2014/01/04/raspberry-pi-powered-heating-controller-part-1/#comments</comments>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Sat, 04 Jan 2014 22:02:04 +0000</pubDate>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[Making the world a better place]]></category>
		<category><![CDATA[RaspberryPi]]></category>
		<guid isPermaLink="false">/?p=509</guid>

					<description><![CDATA[In which no Raspberry Pi&#8217;s are seen. TL;DR:  It should be fairly straight [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><span style="color: #808080; font-size: medium;"><em>In which no Raspberry Pi&#8217;s are seen.</em></span></p>
<p><em><span style="text-decoration: underline;"><strong>TL;DR:</strong> </span> It should be fairly straight forward to add a Raspberry Pi controlled heating and hot water system to a standard UK domestic set up and, more importantly, remove it again without messing with the existing set up.  As a minimum you&#8217;ll need a Raspberry Pi and 4 relays.  A few other bits and bobs wouldn&#8217;t go a miss though.  The theory checks out, I&#8217;ve ordered the bits, come back next time to see what it looks like.</em></p>
<p><span style="line-height: 1.5em;">It occurs to me that for a long time we&#8217;ve had a thermostat in our homes which switches the heating off when it gets warm enough, but wouldn&#8217;t it be just as useful to have something which turns the heating </span><strong style="line-height: 1.5em;">on</strong><span style="line-height: 1.5em;"> when it gets too cold?</span></p>
<p>This thought, together with a Raspberry Pi that wasn&#8217;t doing much and a strong desire to make my home more connected, led me to think about how I might control my heating system from, say, a smart phone.  I&#8217;m far from being the first person to think of this idea, and there are loads of really good examples out there, but none of them did quite what I wanted in the way I wanted to do it.  So I&#8217;m going to start from first principals and walk through this project design to try and build a removable &amp; non-destructive add-on to an existing system.  I&#8217;m writing this at the very start of the project, so I&#8217;ve no idea if it will work, if I will break some expensive components on way to getting it working, or if I will just give up before I get to the end.  Let&#8217;s see.</p>
<h2>Typical domestic hot water and heating systems</h2>
<p>This may be UK specific.  Here is a very very crude diagram of a typical home set up:</p>
<p><div id="attachment_514" style="width: 238px" class="wp-caption alignnone"><a href="http://whizzy.org/wp-content/uploads/2014/01/CH-HWC-2.png"><img aria-describedby="caption-attachment-514" loading="lazy" class="size-medium wp-image-514" src="/wp-content/uploads/2014/01/CH-HWC-2-228x300.png" alt="A crude diagram of how the central heating system works in a typical UK home." width="228" height="300" /></a><p id="caption-attachment-514" class="wp-caption-text">A crude diagram of how the central heating system works in a typical UK home.</p></div></p>
<p><span style="line-height: 1.5em;">The boiler burns gas and heats water.  That hot water is circulated around the system (called the primary circuit) by a pump and can do three jobs.  It can circulate through a heating element in a hot water cylinder and heat more water which is stored in the cylinder.  Note that the water which circulates through the element does not come in to contact with the actual water it is heating, the two are kept </span>separate for water quality reasons.  The second job it can do is circulate through radiators in the home and hear the air.  The third job is to do both.  The hot water from the boiler moves around the primary circuit losing it&#8217;s heat to either the hot water in the cylinder or the air and eventually passes through the boiler again, heats up, and goes round and round again.</p>
<p>There are two &#8220;header&#8221; tanks of cold water in the loft.  One is for the cold water to the bathroom for flushing the loo, filling the bath, brushing your teeth, that kind of thing.  This tank also fills the hot water cylinder.  The other is the header tank for the primary system and ensures that it can&#8217;t boil dry.  Both use gravity and water pressure to make sure the water flows to where it is needed.</p>
<p>The system in the diagram is an &#8220;open&#8221; system.  If the hot water in the cylinder gets too hot it can expand up the vent pipe and dump itself in to the cold water tank.  The cold water tank can over flow to outside.  If the hot water in the primary gets too hot it can expand up in to the header tank ready to be reused to fill the primary when the water cools.</p>
<p>There is such a thing as a sealed pressurised system which doesn&#8217;t have these vents.  These are more complex and if you have one please be very careful in tinkering with the control mechanisms.  In an open system, if you get things wrong and the boiler runs and runs you would end up with a lot of steam in the loft.   In a pressurised system things can go pop and blast you with boiling water.  That said, in an open system you could still end up dumping a header tank full of boiling water down on to the bedrooms below.  <span style="text-decoration: underline;">People have died</span> from this happening, so tinkering with the heating system is not something to be taken lightly.</p>
<p>In summary then; we have three things we can ask a system for:</p>
<ol>
<li>Make hot water</li>
<li>Heat the house</li>
<li>Make hot water and heat the house</li>
</ol>
<p>And we have a number of key elements:</p>
<ol>
<li>Boiler</li>
<li>Hot water cylinder</li>
<li>Primary header tank</li>
<li>Cold water tank</li>
</ol>
<p><span style="line-height: 1.5em; font-size: 1.5em;">Typical electrical system to control hot water and heating</span></p>
<p>Once we understand how the wet bits fit together we can take a look at the electrical components:</p>
<p><div id="attachment_518" style="width: 310px" class="wp-caption alignnone"><a href="http://whizzy.org/wp-content/uploads/2014/01/Y-Plan-Wiring.gif"><img aria-describedby="caption-attachment-518" loading="lazy" class="size-medium wp-image-518" src="/wp-content/uploads/2014/01/Y-Plan-Wiring-300x278.gif" alt="Y Plan electrical wiring plan for central heating and hot water." width="300" height="278" srcset="/wp-content/uploads/2014/01/Y-Plan-Wiring-300x278.gif 300w, /wp-content/uploads/2014/01/Y-Plan-Wiring-768x713.gif 768w" sizes="(max-width: 300px) 100vw, 300px" /></a><p id="caption-attachment-518" class="wp-caption-text">Y Plan electrical wiring plan for central heating and hot water.</p></div></p>
<p>There are multiple &#8220;standards&#8221; for wiring up a heating system.  You can find heaps of information on the excellent <a href="http://wiki.diyfaq.org.uk/index.php?title=Central_Heating_Controls_and_Zoning">DIY FAQ wiki</a>.</p>
<p>My system has been wired in the &#8220;Y Plan&#8221; configuration and if you have a single 3-port valve in your airing cupboard and a couple of tanks in your loft &#8211; then there is a good chance you have too.  I will run through the wiring, and some of the inherent safety systems built in (which is why I&#8217;m keen to make sure my controller is a simple replacement for the existing controller, and is not a complete re-wire).  Before we start though, a further word of caution.  Mains electricity is lethal.  You need be comfortable playing with this stuff to consider attempting anything to do with the heating system.  It&#8217;s also probably illegal in UK due to some draconian restrictions on what a home owner can and can not do to the wiring in their own home.  Don&#8217;t try this at home kids.  A competent tradesman might be able to help you hook it all together.</p>
<p>The incoming mains supply goes through a double pole switch which will disconnect live and neutral when switched off.  In this diagram, the live feed provides power to only the controller (sometimes you might see a parallel (switched and fused) connection to the boiler from that live).  So first and foremost, all power to the <span style="text-decoration: underline;">components</span> comes through the controller. Neutral is common to pump, boiler and valve and so is earth.</p>
<p>Thermostats are placed in series for both the hot water circuits and the heating circuits.  These will physically break the circuit when a specific temperature is reached.</p>
<p>Let&#8217;s consider this example:  I tell the controller to heat the water.  It connects the live feed to the &#8220;HW ON&#8221; cable via point 6 on the diagram. The current flows to the cylinder stat, which allows the current through since the temperature is lower than the trigger point it is set to.  The pump and the boiler are connected in parallel so you can&#8217;t run the boiler with out the pump running too (at least that&#8217;s the plan), and they are provided power via the room stat to point 8 on the diagram.  The boiler is told to turn on, and the pump moves that heated water around the system.  The hot water reaches the three port valve.  The valve has an electrical actuator on which moves to set position depending on what electrical connections are made to it.  In our case, no INPUT power is being applied to the valve, so it sits in it&#8217;s default position &#8211; which just happens to be &#8220;Hot water mode&#8221;, and so the heated water from the boiler passes through the hot water cylinder only.  When the hot water cylinder get&#8217;s to the right temperature the thermostats clicks over to the other contactor and now no power is applied to the pump and boiler via the HW ON output on the controller.  Instead, the grey wire, point 7 on the connector, is energised.  This tells the valve that HW is no longer required.  This system is pretty safe, since as soon as the cylinder stat is triggered power is removed from the boiler and so it would shut down.  Now, thermostats do fail, but they usually &#8220;fail safe&#8221;, but sometimes they don&#8217;t.</p>
<p>What if I want just the heating to run?  The controller connects to the live input to the CH cable via point 4 on the connector.  This passes through the room stat which will allow the current to flow if it&#8217;s below the temperature set.  The current ends up at the valve via point 5 on the connector.  In this case, where we only want heating, the &#8220;white&#8221; wire is live (it&#8217;s black on the diagram) and the valve connects the &#8220;white&#8221; wire to the &#8220;orange&#8221; wire which goes back to point 8 on the connector, and in turn provides power to the boiler and pump.  At this point the &#8220;grey&#8221; wire is also energised, as the controller makes it&#8217;s &#8220;HW OFF&#8221; output live when you ask for only heating. The room stat is able to cut power to the circuit when it reaches the set temperature.</p>
<p>If we want both hot water and heating, the controller energises the &#8220;CH ON&#8221; and &#8220;HW ON&#8221; outputs.  Here current is provided to the pump and boiler when any of the thermostats indicates that more heating is required.  If the HW reaches it&#8217;s temperature first, then the stat energises the grey wire, which tells the valve that no more hot water is required, and so it will move to the CH ONLY position, and current will continue to be provided by the orange wire when the valve reaches the correct position.  The heated water from the boiler will stop circulating through the hot water cylinder and go only through the radiators &#8211; concentrating the heating to where it is needed.  Pretty neat!</p>
<p>This system strikes me as being both simple and brilliant at the same time.  It&#8217;s also pretty safe, as long as the stats are working as they should do.</p>
<p>In summary then, the controller is able to indicate a requirement for hot water, central heating, or both by linking three outputs to live in the right sequence.  The four states are therefore:</p>
<ol>
<li>HW OFF, CH OFF (0,0)</li>
<li>HW OFF, CH ON (0,1)</li>
<li>HW ON, CH OFF (1,0)</li>
<li>HW ON, CH ON (1,1)</li>
</ol>
<h2>Confirming my deductions</h2>
<p>I&#8217;ve looked at the plumbing, and I&#8217;ve looked at the wiring, and I&#8217;m pretty sure that I know what&#8217;s going on.  Next thing to do is apply the scientific method and gather the evidence to back up my assumptions.</p>
<p><a href="http://whizzy.org/wp-content/uploads/2014/01/controller1.jpg"><img loading="lazy" class="alignnone size-medium wp-image-505" title="The horrors that lurk behind the heating controller" src="/wp-content/uploads/2014/01/controller1-300x225.jpg" alt="Behind the heating controller" width="300" height="225" srcset="/wp-content/uploads/2014/01/controller1-300x225.jpg 300w, /wp-content/uploads/2014/01/controller1-1024x768.jpg 1024w, /wp-content/uploads/2014/01/controller1-768x576.jpg 768w, /wp-content/uploads/2014/01/controller1-1200x900.jpg 1200w, /wp-content/uploads/2014/01/controller1.jpg 1204w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<p>The first thing I did was to turn off the power to the heating system.  I&#8217;m paranoid, so I turned it off at the fused connection to the left of the controller and also at the fuse box.  I also wore rubber boots, and jumped in the air every time I touched a wire.  Better safe than sorry, eh?  And, rightly so it turns out.  The fused connection unit did actually cut all the power to the heating system, but look carefully at the third connection from the left and you&#8217;ll see an earth wire being used to carry live current.  This is against all the regulations.  Whoever installed this system originally was clearly a free spirit.  I was also quite impressed that they&#8217;d managed to squeeze all the connections in to a double gang back box.  What a mess.  Remember kids, only a competent person is allowed to fiddle with these things &#8211; they do a better quality job you see.</p>
<p>Looking at the zoomed in image you can see 6 terminals:  N, L 1, 2, 3, 4.</p>
<p>N &amp; L are self explanatory.  2 is not connected to anything, and so I don&#8217;t need to worry about it.  So that leaves three connections that do something (1, 3 and 4).  Exactly what I was expecting.  One will be CH ON, one HW ON, and one HW off.  Which is which?</p>
<p>Looking at the back of the controller unit it&#8217;s self:</p>
<p><a href="http://whizzy.org/wp-content/uploads/2014/01/controller_rear.jpg"><img loading="lazy" class="alignnone size-medium wp-image-507" src="/wp-content/uploads/2014/01/controller_rear-300x225.jpg" alt="Rear of heating controller" width="300" height="225" srcset="/wp-content/uploads/2014/01/controller_rear-300x225.jpg 300w, /wp-content/uploads/2014/01/controller_rear-768x576.jpg 768w, /wp-content/uploads/2014/01/controller_rear.jpg 897w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<p>My theory is sound!  1 is <strong>HW OFF</strong>, 3 is <strong>HW ON</strong>, 4 is <strong>CH ON</strong>.</p>
<p>It looks like everything is connected as I had expected, but better safe than sorry.  Let&#8217;s do a bit more testing:</p>
<p><a href="http://whizzy.org/wp-content/uploads/2014/01/controller2.jpg"><img loading="lazy" class="alignnone size-medium wp-image-506" src="/wp-content/uploads/2014/01/controller2-300x225.jpg" alt="Testing harness" width="300" height="225" srcset="/wp-content/uploads/2014/01/controller2-300x225.jpg 300w, /wp-content/uploads/2014/01/controller2-1024x768.jpg 1024w, /wp-content/uploads/2014/01/controller2-768x576.jpg 768w, /wp-content/uploads/2014/01/controller2.jpg 1141w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<p>I wired in a few bits of cable and then (not shown) removed the connections to the rest of the system (labelling where they came from when I removed them!).  I left the L &amp; N connected.  To recap, I <strong>removed</strong> the existing wires from 1, 3 and 4 and replaced them with my cables which came down to some screw down connector blocks.  The reason I put connector blocks on the end was two fold.  Firstly, to make it easier to probe with my multimeter and secondly to stop me accidentally brushing against one of the cables and giving myself a shock.  I also labelled the permanent live with a bit of red heat-shrink, just so I don&#8217;t get confused.</p>
<p><a href="http://whizzy.org/wp-content/uploads/2014/01/controller.jpg"><img loading="lazy" class="alignnone size-medium wp-image-508" src="/wp-content/uploads/2014/01/controller-225x300.jpg" alt="Test harness 2" width="225" height="300" srcset="/wp-content/uploads/2014/01/controller-225x300.jpg 225w, /wp-content/uploads/2014/01/controller.jpg 612w" sizes="(max-width: 225px) 100vw, 225px" /></a></p>
<p>Putting the controlled back on, I hooked up my multimeter and switched through the options to see what happens when.  My findings are below:</p>
<table class="wp-gallery" style="border: 2px solid #000000; height: 200px; width: 200px;" border="2" cellspacing="5" cellpadding="2" align="left">
<tbody>
<tr style="background-color: #a9a8a8;">
<td></td>
<td>1</td>
<td>3</td>
<td>4</td>
</tr>
<tr style="background-color: #d9d8d8;">
<td>ALL OFF</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr style="background-color: #a9a8a8;">
<td>HW ONLY</td>
<td>0</td>
<td style="background-color: #28f10d;">240V</td>
<td>0</td>
</tr>
<tr style="background-color: #d9d8d8;">
<td>CH ONLY</td>
<td style="background-color: #28f10d;">240V</td>
<td>0</td>
<td style="background-color: #28f10d;">240V</td>
</tr>
<tr style="background-color: #a9a8a8;">
<td>BOTH ON</td>
<td>0</td>
<td style="background-color: #28f10d;">240V</td>
<td style="background-color: #28f10d;">240V</td>
</tr>
</tbody>
</table>
<p>.</p>
<p>.</p>
<p>.</p>
<p>.</p>
<p>.</p>
<p>Exactly what I expected.  Point 1 must, therefore be &#8220;HW OFF&#8221;, point 2 &#8220;HW ON&#8221; and point 3 &#8220;CH ON&#8221; &#8211; which they are, as we saw from the back of the controller.  I&#8217;m now confident enough with the set up to proceed with roughing out a block diagram for the controller and ordering the parts.</p>
<p><span style="font-size: 1.5em; line-height: 1.5em;">The plan</span></p>
<p><a href="http://whizzy.org/wp-content/uploads/2014/01/heating_controller_block.png"><img loading="lazy" class="alignnone size-medium wp-image-532" src="/wp-content/uploads/2014/01/heating_controller_block-300x192.png" alt="heating_controller_block" width="300" height="192" /></a>  <a href="http://whizzy.org/wp-content/uploads/2014/01/Heating-Controller-1.png"><img loading="lazy" class="alignnone size-medium wp-image-538" src="/wp-content/uploads/2014/01/Heating-Controller-1-300x222.png" alt="Heating Controller Crude" width="300" height="222" /></a></p>
<p>This rather unclear breadboard layout (with the awesome <a href="http://fritzing.org/home/">http://fritzing.org/home/</a>) logically lays out what I intend to do.  I&#8217;ve also added a crude block diagram for good measure.</p>
<p>First, I will add a real-time clock module.  They&#8217;re cheap and easy to fit.  This will provide the Pi with a source of time when it can&#8217;t talk to NTP servers, and so it will be able to turn things on and off at the right times, even when the network connection is down.</p>
<p>Next I will add four relays.  I will take the main 240V incoming supply out of the existing controller and put it through relay 1.  This relay will pass the supply on to the existing controller via the &#8220;Normally Closed&#8221; relay output.  When I switch this relay, the supply to the existing controller will be dropped, and instead routed to the other three relays which will then be able to switch this current.  These three relays will be wired in parallel with the existing controller connections, much like in the image above showing the test harness connected in to the controller connections.  That is to say: one relay will go to point 1, one to point 3 and one to point 4.  The existing safety features (thermostats in series in the circuits) are un-changed and so still offer the same protection.  In order to activate heating or hot water we switch the relays as per the table above.  By adding my new system in parallel and being able to easily switch between the two I can bring the RasPi powered one online gradually.  A few hours here, a few hours there.  And once I&#8217;m happy that it&#8217;s not going to go crazy I can leave it unsupervised for longer and longer periods.  It also means that if I update the software and break something, we can still wash.</p>
<p>I will also add a number of 1wire temperature sensors.  I will have three on the hot water cylinder: 1 at each of the top, middle and bottom.  This will give me insight in to how much hot water is in the cylinder, and the temperature thereof.  This is not intended to be a safety system.  The temperature readings from these sensors will not be relied upon to switch things off in an emergency, that will be left to the original thermostats, <em>but</em> &#8211; we could use these readings as well to help make decisions.  I will also fit a temperature sensors in the cold water tank, the primary header tank and somewhere outside.  This will give me insight in to a couple of things:  Firstly, how cold is the water in the CW tank, and what is the temperature outside?  This has a direct effect on the number of showers that can be had from a given amount of hot water at a known temperature. Useful for trending too.  Secondly, fitting a sensor in the primary header tank can report when the header tank is getting hot.  Really, the header shouldn&#8217;t heat up too much.  If it does then either the system is &#8220;pumping over&#8221; &#8211; where the pump is <span style="text-decoration: underline;">forcing</span> water up the vent pipe pipe OR the water is so hot it has expanded enough to push water out of the vent, or I expect some combination of the two.  Either situation is sub-optimal, and with a sensor in the header tank I get some visibility of what&#8217;s going on.  I might also add a sensor to the boiler input and output, so get an idea of how much work the boiler is doing.  Adding a sensor to each room would be a nice addition at some point too.</p>
<p>A couple of switches will be added for manually switching the hot water or heating on/off from the airing cupboard, where the current controller is situated and where the more senior visitors to Whizzy Towers will expect the heating buttons to be.</p>
<h4>Shopping list:</h4>
<ul>
<li>1 x Real Time Clock.  <a href="http://www.ebay.co.uk/itm/200929798800?ssPageName=STRK:MEWNX:IT&amp;_trksid=p3984.m1439.l2649">http://www.ebay.co.uk/itm/200929798800?ssPageName=STRK:MEWNX:IT&amp;_trksid=p3984.m1439.l2649</a></li>
<li><span style="line-height: 1.5em;">4 mains rated relays.  </span><a style="line-height: 1.5em;" href="http://www.ebay.co.uk/itm/190950013824?var=490205033810&amp;ssPageName=STRK:MEWNX:IT&amp;_trksid=p3984.m1439.l2649">http://www.ebay.co.uk/itm/190950013824?var=490205033810&amp;ssPageName=STRK:MEWNX:IT&amp;_trksid=p3984.m1439.l2649</a><span style="line-height: 1.5em;"><br />
</span></li>
<li><span style="line-height: 1.5em;">Some 1wire temperature sensors.  <a href="http://www.ebay.co.uk/itm/DS18S20-Temperature-Sensor-1-Wire-Dallas-Maxim-/130621920626">http://www.ebay.co.uk/itm/DS18S20-Temperature-Sensor-1-Wire-Dallas-Maxim-/130621920626</a></span></li>
<li>A few meters of 0.75mm 5 core heat resistant flex (type 3095Y).  <a href="http://www.ebay.co.uk/itm/5-Core-Heat-Resistant-Flex-Electrical-Cable-3095Y-0-75mm-/310663083027?pt=UK_BOI_Electrical_Components_Supplies_ET&amp;var=&amp;hash=item4854f67413">http://www.ebay.co.uk/itm/5-Core-Heat-Resistant-Flex-Electrical-Cable-3095Y-0-75mm-/310663083027?pt=UK_BOI_Electrical_Components_Supplies_ET&amp;var=&amp;hash=item4854f67413</a></li>
<li>A short bit of twin brown and earth for the connections between the 1st relay and the original controller live input.</li>
<li>A 4k7 resistor</li>
</ul>
<p>Couple that with a few odd bits of wire, some LEDs a bit of Python and we should have ourselves a Raspberry Pi powered heating and hot water controller which is relatively safe, easy to remove and cheap to build.  Let&#8217;s see what happens when all the bits turn up.  Should be here in a week or so.</p>
<p>Stay tuned.</p>
<h2>Further Updates</h2>
<ol>
<li><a title="Raspberry Pi powered heating controller (Part 2)" href="/2014/01/raspberry-pi-powered-heating-controller-part-2/">Part 2</a></li>
<li><a title="Raspberry Pi powered heating controller (Part 3)" href="/2014/01/raspberry-pi-powered-heating-controller-part-3/">Part 3</a></li>
<li><a title="Raspberry Pi powered heating controller (Part 4)" href="/2014/02/raspberry-pi-powered-heating-controller-part-4/">Part 4</a></li>
</ol>
]]></content:encoded>
					
					<wfw:commentRss>/2014/01/04/raspberry-pi-powered-heating-controller-part-1/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title>Absolute beginners guide to Google Maps JavaScript v3</title>
		<link>/2013/12/17/absolute-beginners-guide-to-google-maps-javascript-v3/</link>
					<comments>/2013/12/17/absolute-beginners-guide-to-google-maps-javascript-v3/#comments</comments>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Tue, 17 Dec 2013 14:58:55 +0000</pubDate>
				<category><![CDATA[Google Maps]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Making the world a better place]]></category>
		<guid isPermaLink="false">/?p=457</guid>

					<description><![CDATA[Since I first published my HowTo and the subsequent follow up for novices to [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Since I first published my <a title="Absolute beginners guide to Google Maps Javascript" href="/2009/05/absolute-beginners-guide-to-google-maps-javascript/">HowTo</a> and the <a title="Absolute beginners guide to Google Maps Javascript Part 2" href="/2009/05/absolute-begineers-guide-to-google-maps-javascript-part-2/">subsequent</a> follow up for novices to get a Google Map on a web page it&#8217;s been the most popular post on my site by quite a margin.  Sadly it&#8217;s been resting on its laurels, and is now quite out of date and indeed broken.  So spurred on by my recent server replacement and attempt to revitalise this blog I present the new, improved, and generally working&#8230; Beginners Guide To Google Maps JavaScript v3.</p>
<p>The premise is simple; you&#8217;ve got a requirement to put a map on your site.  You don&#8217;t have the first clue how to do it.  You follow these instructions and you get you map.  Hopefully you&#8217;ll pick up enough to tweak the map to your requirements, if not &#8211; please ask in the comments and I&#8217;ll try and help you.  I&#8217;m assuming that you&#8217;ve got a bit of HTML experience, and that you&#8217;ve got a JavaScript debugger available to you (either Firebug for Firefox or Developer Tools built in to Chrome).</p>
<p>I&#8217;ve based a lot of this on the official Google tutorial here:  <a href="https://developers.google.com/maps/documentation/javascript/tutorial">https://developers.google.com/maps/documentation/javascript/tutorial</a>.  (I&#8217;m pretty sure they borrowed that from me in the first place, so it&#8217;s only fair <img src="https://s.w.org/images/core/emoji/13.0.1/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /> ).</p>
<h1>Part 1.  Getting the map on the page</h1>
<p>Get yourself an API key for Google Maps from here:  <a href="https://developers.google.com/maps/documentation/javascript/tutorial#api_key" target="_blank" rel="noopener noreferrer">https://developers.google.com/maps/documentation/javascript/tutorial#api_key</a></p>
<p>Let&#8217;s start from the end and work back to the beginning.  Save this as an HTML document, change the API key, open it in your browser and you&#8217;ll have a map.  I&#8217;ve saved you a bit of time by already centring it on Barrow-in-Furness bus depot.</p>
<p>[js]<br />
&lt;!DOCTYPE html&gt;<br />
&lt;html&gt;<br />
  &lt;head&gt;<br />
&lt;title&gt;My first Google Map&lt;/title&gt;<br />
    &lt;meta name=&quot;viewport&quot; content=&quot;initial-scale=1.0, user-scalable=no&quot; /&gt;<br />
    &lt;style type=&quot;text/css&quot;&gt;<br />
      html { height: 100% }<br />
      body { height: 100%; margin: 0; padding: 0 }<br />
      #map-canvas { height: 100% }<br />
    &lt;/style&gt;<br />
    &lt;script type=&quot;text/javascript&quot;<br />
      src=&quot;https://maps.googleapis.com/maps/api/js?key=XXXXXXXXXXXXXXXX&amp;sensor=false&quot;&gt;<br />
    &lt;/script&gt;<br />
    &lt;script type=&quot;text/javascript&quot;&gt;<br />
      function initialize() {<br />
      	var myLatLng = new google.maps.LatLng(54.124634, -3.237029)<br />
        var mapOptions = {<br />
          center: myLatLng,<br />
          zoom: 17,<br />
          mapTypeId: google.maps.MapTypeId.SATELLITE<br />
          };</p>
<p>        var map = new google.maps.Map(document.getElementById(&quot;map-canvas&quot;),<br />
            mapOptions);</p>
<p>        var myMarker = new google.maps.Marker({<br />
          position: myLatLng,<br />
          map: map,<br />
          title: &quot;A place on Earth&quot;,<br />
          draggable: true,<br />
          })<br />
        }</p>
<p>      google.maps.event.addDomListener(window, &#8216;load&#8217;, initialize);<br />
    &lt;/script&gt;<br />
  &lt;/head&gt;<br />
  &lt;body&gt;<br />
    &lt;div id=&quot;map-canvas&quot;/&gt;<br />
  &lt;/body&gt;<br />
&lt;/html&gt;<br />
[/js]</p>
<p>Copy and paste that in to a text editor, replace XXXXXXXXXXXXXXXX with your own API key, save it somewhere and the load it up in your browser.  You should see a satellite style map with a marker in the middle. You&#8217;re done.  Simple eh?  Read on learn a bit about how it works, and what you can do to change the appearance.</p>
<h2>Part 1.1 Understanding the basic HTML</h2>
<p>In order to try and guarantee a consistent layout across browsers you need to make sure that your page is rendered in &#8216;Standards Compliant&#8217; mode as opposed to &#8216;Quirks&#8217; mode. To do this you need to specify a DOCTYPE at the top of your HTML file.  We&#8217;re using a very simple &#8220;html&#8221; DOCTYPE which tells the browser that we&#8217;re HTML5.  In HTML4.x there were a plethora of variations &#8211; thankfully we don&#8217;t need to care about them anymore.  HTML5 is the way to go, and so the only DOCTYPE we care about is &#8220;html&#8221;.</p>
<p>We set the title of the page, and then we set some initial viewport settings to help mobile browsers render the page correctly.  This is widely regarded as a good thing, and you can learn more about it from here: <a href="http://webdesign.tutsplus.com/tutorials/htmlcss-tutorials/quick-tip-dont-forget-the-viewport-meta-tag/">http://webdesign.tutsplus.com/tutorials/htmlcss-tutorials/quick-tip-dont-forget-the-viewport-meta-tag/</a></p>
<p>Skipping over the style and scripts for a moment, we create the main body of the page with a single div element in it.  We give it the id &#8220;map-canvas&#8221;, and then we close off the bottom of the body and mark the end of the HTML.  You won&#8217;t be surprised to read that the div we&#8217;ve just created will be where the map will soon appear.</p>
<h2>Part 1.2 All about style</h2>
<p>In standard HTML5 (remember the DOCTYPE from above) there are a few specifics you need to know about CSS.  If an element specifies a size as a percentage, then that percentage is calculated from the parent objects size.  Imagine you have a nested DIV, called DIV2.  It lives inside DIV1.  Where DIV1 has a fixed size of 500px by 500px, then DIV2 knows that 100% high equals 500px, but what if DIV1 didn&#8217;t have a size specified?  In that case, in standards mode, DIV2 would decide that 100% high equals zero px &#8211; because it doesn&#8217;t know any better.  This has caught people out a few times.  In order to make sure that all our DIVs can inherit a size correctly we set the height of the entire HTML page and the BODY to be 100%.  This is calculated by the browser when the page loads, and then can flow down to the elements within the page correctly.</p>
<p>Once we have the parent elements size set correctly (the page, and the body) we can style our map DIV to be 100% high safe in the knowledge that it has enough information to render and the correct size and not 0 px high.</p>
<h2>Part 1.3 The Meat Section</h2>
<p>Now we&#8217;re going to look at the actual JavaScript and understand what it&#8217;s doing and in which order.</p>
<p>First of all, we have the scripts in the HEAD tag.  The browser will load the head part of the HTML first and your scripts will be loaded before the page is fully rendered.  Any functionality that you make available in your scripts should be available to the rest of the page when it comes to need it.  This is generally the right way to do it.</p>
<p>The first SCRIPT tag takes care of loading the Google Maps code.  We tell the browser that the content of the script is text/javascript and then where to find it.  There are a couple of parameters we pass  in to the script through the URL.  The first one is &#8220;key&#8221; &#8211; this is your simple API key for access Google Maps (see above for details of where to get this key).  The second parameter is &#8220;sensor&#8221;.  This is required and must be &#8220;false&#8221; if you&#8217;re not using a GPS (or similar) to work out where you are.  In our case, we&#8217;re just picking a point on and saying &#8220;centre the map here&#8221; &#8211; so we use false.  If were using a GPS to centre the map on our current location, then this would be &#8220;true&#8221;.</p>
<p>This script gets loaded by the browser and now we can start to make use of the Google Maps JavaScript APIs in the rest of our page.</p>
<p>The second script is a bit more complex, but should be easy to understand:</p>
<p>We create a new function called &#8220;initialize&#8221;.<br />
Inside that function we create an object called myLatLng.  We use the Google provided API google.maps.LatLng() to create an object which can be understood by the rest of the Google Maps API and pass in the co-ordinates of Barrow-in-Furness bus depot.  We use &#8220;var&#8221; to limit that object&#8217;s &#8220;scope&#8221; to within the &#8220;initialize&#8221; function &#8211; that is to say, we won&#8217;t be able to get access to that particular myLatLng from other functions on the page.<br />
Next we create another thing called mapOptions.  The format of this is as per the spec here: <a href="https://developers.google.com/maps/documentation/javascript/reference?hl=en#MapOptions">https://developers.google.com/maps/documentation/javascript/reference?hl=en#MapOptions<br />
</a></p>
<p>There are loads of options, most of which we don&#8217;t need to worry about, so we&#8217;re just setting a few key options:  where the map is centered, how much it is zoomed in, and the type of map we see.  The map types are provided by Google as a set of constants, which are identifiable by being all in upper case.  In our case we&#8217;re using SATELLITE, but we could also use HYBRID, ROADMAP or TERRAIN.</p>
<p>Once we&#8217;ve set up the various mapOptions we create a new var called &#8220;map&#8221; which is an instance of a Map object as provided by the Google APIs.  We pass in to it the id of the HTML object where we want the map to appear, as we created in section 1.2, and we pass in the options var which we just created.  This is enough information for the Google APIs to set up the map as we want it and put it on the page.</p>
<p>The last thing we do in our example is add a marker.  A marker is the indicator which you use to highlight a point on the map.  Google provide a lot of icons and colours for us to use, but the default is the red tear-drop one, so we&#8217;ll stick with that for now.</p>
<p>To create a marker we create a new instance of google.Maps.Marker and set up some of the options as we did for the map itself.  We tell it the position for the marker to appear.  We use the &#8220;myLatLng&#8221; object we created earlier.  You might notice that we are using the myLatLng object twice in our example.  Once as the centre point for the map, and once for the position of the marker.  You can probably deduce from this that the marker will appear in the centre of the map.  We also tell the marker which map it should be added to.  We only have one map on our page, but if we had many this is how you&#8217;d add a marker to the correct map.  We give it a title, which is simply a string and we make it draggable by setting the draggable option to &#8220;true&#8221;.  You can read more about the marker options here: <a href="https://developers.google.com/maps/documentation/javascript/reference?hl=en#MarkerOptions">https://developers.google.com/maps/documentation/javascript/reference?hl=en#MarkerOptions</a></p>
<p>That&#8217;s very nearly it for our first simple map.  The last thing to do is use a DOM listener to trigger the above JavaScript when the page loads, and so make our map and marker appear.</p>
<p>google.maps.event.addDomListener is provided via the Google APIs and we pass in three pieces of information.  window is the object provided by the browser.  The &#8216;load&#8217; event is actually is separate from the &#8220;onload&#8221; event you might have read about.  The load event signifies that the page is fully rendered and any JavaScript which wants to manipulate the DOM can begin work, and that&#8217;s what we want to do.  We want to swap the empty div with the id of &#8220;map&#8221; with the actual map.  So once the page is indeed loaded the command will execute the &#8220;initialize&#8221; function and all the magic will happen.</p>
<p>And that&#8217;s it.  We&#8217;re done.  We&#8217;ve got a map on the page centred at our chosen location, and there is a little marker to show a specific part of the map.</p>
<p>If you compare this to the original <a title="Absolute beginners guide to Google Maps Javascript" href="/2009/05/absolute-beginners-guide-to-google-maps-javascript/">Beginners Guide</a> I think you&#8217;ll say that this new version of the API is even easier to use.  I will try and find time of the next few months to jot down a few notes on doing more interesting things with the map but I hope that this will get you started.</p>
]]></content:encoded>
					
					<wfw:commentRss>/2013/12/17/absolute-beginners-guide-to-google-maps-javascript-v3/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Combining MythTV and Asterisk</title>
		<link>/2013/12/15/combining-mythtv-and-asterisk/</link>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Sun, 15 Dec 2013 10:56:04 +0000</pubDate>
				<category><![CDATA[asterisk]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[tv]]></category>
		<guid isPermaLink="false">/?p=468</guid>

					<description><![CDATA[I&#8217;ve had this idea for a while and with the discovery of the [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>I&#8217;ve had this idea for a while and with the discovery of the Google Text-to-speech and Voice Recognition AGI scripts from Zaf (<a href="http://zaf.github.io/asterisk-googletts/">http://zaf.github.io/asterisk-googletts/</a> &amp; <a href="http://zaf.github.io/asterisk-speech-recog/">http://zaf.github.io/asterisk-speech-recog/</a>) I&#8217;ve implemented a quick proof-of-concept.</p>
<p>You can see the results in this YouTube video:</p>
<p><iframe loading="lazy" width="770" height="433" src="https://www.youtube.com/embed/7DMeRVU9hik?feature=oembed" frameborder="0" allowfullscreen></iframe></p>
<p>Over the next few days I&#8217;ll tidy up the code and write up a blog post about how to do it.  It&#8217;s pretty straight forward though, using APIs provided by Google, MythTV and Asterisk and then just glueing them together.</p>
<p>&nbsp;</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Convincing MythTV to tune in to DVB-T2 MUXes</title>
		<link>/2013/11/25/convincing-mythtv-to-tune-in-to-dvb-t2-muxes/</link>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Mon, 25 Nov 2013 19:09:38 +0000</pubDate>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[tv]]></category>
		<guid isPermaLink="false">/?p=452</guid>

					<description><![CDATA[So that I remember for next time, and so I can start writing [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>So that I remember for next time, and so I can start writing down some of the issues I&#8217;ve had to sort out since re-building my servers, here is what you have to do to tune to a DVB-T2 mux in MythTV (0.27 fixes).</p>
<p>This is the frequency for the PSB3 mux on Sandy Heath, I expect the encoding scheme will work pretty much where ever. At the very least it should get you started:</p>
<p>&nbsp;</p>
<pre>Frequency:  474200000
Bandwidth:  8 MHz
Inversion:  Auto
Constellation:  QAM 256
LP Coderate: 2/3
HO Coderate: Auto
Trans. Mode: 8K
Guard Interval: 1/32
Hierarchy:  None</pre>
<p>If that doesn&#8217;t work, and you know it should (as in you are on the same transmitter) try setting the tuning timeouts higher. Also, just blindly re-trying because &#8220;WHY DOESN&#8217;T IT WORK&#8221; seemed to help.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>And we&#8217;re back&#8230;</title>
		<link>/2013/11/22/and-were-back/</link>
					<comments>/2013/11/22/and-were-back/#comments</comments>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Fri, 22 Nov 2013 19:51:24 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">/?p=450</guid>

					<description><![CDATA[I&#8217;ve moved to another server, and in the process I&#8217;ve had a whole [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>I&#8217;ve moved to another server, and in the process I&#8217;ve had a whole lot of problems.  For anyone that&#8217;s read any of my blog before that won&#8217;t come as a surprise.</p>
<p>Once I&#8217;ve got all the kinks worked out, I&#8217;ll tell you how I fixed it.  For now, this is just a test&#8230;</p>
]]></content:encoded>
					
					<wfw:commentRss>/2013/11/22/and-were-back/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Asterisk UK Caller ID &#038; SMS redux</title>
		<link>/2013/02/12/asterisk-uk-caller-id-sms-redux/</link>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Tue, 12 Feb 2013 12:41:57 +0000</pubDate>
				<category><![CDATA[asterisk]]></category>
		<guid isPermaLink="false">/?p=443</guid>

					<description><![CDATA[Update 28 Dec 2013:  As far as caller ID goes, I might have [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><span style="text-decoration: underline;"><strong>Update 28 Dec 2013:</strong> </span> As far as caller ID goes, I might have been barking up completely the wrong tree here.  Have a look here: <a href="http://forums.digium.com/viewtopic.php?f=1&amp;t=85028">http://forums.digium.com/viewtopic.php?f=1&amp;t=85028</a>.  I&#8217;ve re-implemented that patch for Dahdi and I&#8217;m testing it now.  Get in touch if you want to test it as well.  Once I&#8217;m happy it&#8217;s actually working, I&#8217;ll post it here.</p>
<p>&nbsp;</p>
<p><strong>tl;dr: Scroll down to “How to fix Caller ID in the UK on Asterisk 11 and Dahdi 2.6.1″</strong></p>
<p>I’ve been having some problems with Asterisk 1.6 for a while now, in that when I’m dialled in to conferences via SIP, or when I call someone via the work Asterisk server from my Asterisk server at home I get cut off every 15 minutes. My colleagues have all kind of accepted this now, it was starting to get annoying. It was a known problem in Asterisk 1.6, and so I was going to have to upgrade.</p>
<p>The Ubuntu Asterisk packages are fairly up-to-date but FreePBX isn’t packaged, and it’s a pain in the backside to get set up with the correct permissions, especially if you install Asterisk from packages. I had a spare machine anyway so I decided that I’d give FreePBX Distro a go and once I’d burnt the ISO to a CD (ya rly) I found the set up process to be simple and quick.</p>
<p>FreePBX Distro is a stripped down CentOS (2.6.32 kernel) which boots quick, has minimal footprint and bundles in loads and loads of FreePBX “apps” like conferences, voicemail, blacklisting and makes setting up extensions a breeze. It also includes things like kernel source for <a style="text-decoration: none" href="http://www.isettlements.com/blog/time-to-sell-my-structured-settlement/"><font color="#555555">I sell settlement</font></a> so building extra modules from source is pretty easy. Which is a good job, because it was about to get messy.</p>
<p>If you’ve found this page via Google then this will probably sound pretty familiar:</p>
<ul>
<li>You got a TDM400p four port FXO/FXS interface card, or a clone from someone like OpenVox (which work perfectly by the way – as do those cheap daughter cards off eBay).</li>
<li>You’ve upgraded to <strong>Asterisk 11</strong>, or <strong>Asterisk 1.8</strong> perhaps, or changed to the <strong>Dahdi 2.6.1</strong> drivers and all of a sudden your ”<strong>UK Caller ID</strong>” has “<strong>stopped working</strong>” or at the very least become “<strong>intermittent</strong>“.</li>
<li>It was working fine before, so it’s <strong>not a hardware issue</strong> and your phone provided have <strong>NOT suddenly stopped sending caller ID information</strong>, regardless of what people of forums tell you. No, in fact this is clearly a bug which has crept in somewhere along the line.</li>
<li>You’ve searched and searched and tried things like setting<strong> rxgain=x.x</strong> and <strong>txgain=x.x</strong> or whatever. (Side note: setting txgain and rxgain in chan_dahdi_channels_custom.conf has no effect, the only place is seems to work is in <strong>chan_dahdi_groups.conf</strong>)</li>
<li>You might have even stumbled across a post hinting that <strong>cid_rxgain=x.x</strong> will solve your problems, only it didn’t</li>
</ul>
<p>If that sounds like you, dear reader, then read on. I am your salvation.</p>
<ol>
<li>This page: http://downloads.openvox.cn/pub/drivers/callerid_patches/ (I can only attribute this discovery to divine intervention)</li>
<li>Find a new wctdm.c driver here: http://downloads.openvox.cn/pub/drivers/callerid_patches/2.6.1-wctdm.c</li>
<li>Download the 2.6.1 Dahdi source from here: http://downloads.asterisk.org/pub/telephony/dahdi-linux-complete/dahdi-linux-complete-2.6.1+2.6.1.tar.gz</li>
<li>Replace dahdi-linux-complete-2.6.1+2.6.1/linux/drivers/dahdi/wctdm.c with the version downloaded from openvox</li>
<li>Note it doesn’t compile, add the missing semicolon to line 333 (or thereabouts), successfully build and install the new driver</li>
<li>You might need to change /etc/modprobe.d/dahdi.conf and add:</li>
</ol>
<pre>options wctdm opermode=UK fwringdetect=1 battthresh=4</pre>
<ol>
<li>restart Dahdi and Asterisk and caller ID should now be fixed! Yay!</li>
</ol>
<h1>How to fix Caller ID in the UK on Asterisk 11 and Dahdi 2.6.1</h1>
<p>Here is a patch against wctdm.c from stock Dahdi 2.6.1 with the fixes in: <a href="/wp-content/uploads/2013/02/wctdm.c.patch">wctdm.c</a>.patch</p>
<p><strong>OR:</strong> Replace dahdi-linux-complete-2.6.1+2.6.1/linux/drivers/dahdi/wctdm.c with this one: <a href="/wp-content/uploads/2013/02/wctdm.c">wctdm</a>.c</p>
<p><strong>OR:</strong> If you’re running FreePBX distro 64 bit “BETA-3.211.63-5 Release Date-01-24-13″ (or close) here is a binary driver: <a href="/wp-content/uploads/2013/02/wctdm.ko">wctdm</a>.ko  Move it to /lib/modules/2.6.32-279.11.1.el6.x86_64/dahdi/wctdm.ko</p>
<p>It works for me. I have not had to increase the rxgain, or txgain or anything else. It just works.</p>
<p>Once that’s working, we can move on to…</p>
<h1>How to send &amp; receive SMS in the UK on FreePBX Distro Beta 3.211</h1>
<p>I’ve talked about receiving and sending SMSes before, but that was quite a long time ago, and things have moved on a bit since then. I’ve also learnt a bit more about the Asterisk dial plan, and have a slightly cleaner way of doing it now.</p>
<p>You need to have working caller ID. Hint: see above.<br />
You need to install smsq.<br />
smsq doesn’t come built in FreePBX Distro so you have to build it yourself if you want to send SMS. This is pretty easy:</p>
<ol>
<li>Download the Asterisk 11.2.1 source from here: http://downloads.asterisk.org/pub/telephony/asterisk/asterisk-11.2.1.tar.gz</li>
<li>Install popt: yum install popt-devel.i686 popt.i686 popt.x86_64 popt-devel.x86_64 (prerequisite for smsq)</li>
<li>In the Asterisk source directory do “./configure”</li>
<li>run “make menuselect”</li>
<li>Scroll down to “Utilities”</li>
<li>In the right hand pane, check “smsq”</li>
<li>Save &amp; Exit</li>
<li>run “make”</li>
<li>DO NOT run “make install” as this will trash your FreePBX config</li>
<li>Once that’s done you should find an executable smsq in the utils directory</li>
</ol>
<p>Just to be sure, create /var/spool/asterisk/sms/motx and /var/spool/asterisk/sms/mtrx<br />
You can find more details on building Asterisk here: http://blogs.digium.com/2012/11/05/how-to-install-asterisk-11-on-centos-6/</p>
<p>You need to be able to send SMS in order to register with the BT SMS system, otherwise when you receive an SMS you will get a phone call from the BT robots who will read the text to you, badly.</p>
<p>To register with BT try this:</p>
<pre>&lt;path to smsq&gt;/smsq –motx-channel=DAHDI/2/17094009 -d 00000 -m “test”</pre>
<p>where DAHDI/2 is the channel number of your outgoing line.</p>
<p>If you look in the Asterisk logs you should see the message going out with some TX and RX hex dumps. If it works, a short while later you will receive a phone call from either the SMS system trying to talk modem at you, or the robot. Either way, this means your text went out. Great success!</p>
<p>Now we need to set up receive, which is pretty straight forward.</p>
<p>Edit /etc/asterisk/extensions_custom.conf and add the below. Note – I’ve added a lot of comments to explain what’s going on, it might improve readability if you take them out.</p>
<pre>[from-internal-additional-custom]
;; This makes sure our new 'app' gets included in the FreePBX dial plan
include =&gt; app-rx-sms
[app-rx-sms]
;; This is the app to receive an SMS which will be called when we match
;; the caller ID of an incoming call to the BT computer
exten =&gt; s,1,Answer()
;; This wait seems to help
exten =&gt; s,n,Wait(0.5)
;; We simply use the built in SMS function
exten =&gt; s,n,SMS(default,a)
;; Hangup with code 16, normal termination.
exten =&gt; s,n,Hangup(16)
;; Done
;; We also extend the from-pstn context with a branch to the SMS app
;; if the caller ID matches, hence why it's necessary to get caller
;; id working first
[from-pstn-custom]
;; we add ourselves in to the end of the current dialplan
;; priority 7 gets us there...
exten =&gt; s,7,GotoIf($["${CALLERID(num)}" = "08005875290"]?app-rx-sms,s,1)
;; pretty simple - if the caller ID matches, go to the sms app
exten =&gt; s,n(dest-ext),Goto(ext-group,1100,1)
;; Note: 1100 is my "ring all" group. You will need to change 1100
;; to what ever you use. You should see this at the end of the
;; from-pstn context in extensions_additional.conf</pre>
<p>Save that, and in asterisk do a “dialplan reload”. From smsq send an SMS to 00000 saying “register”· If everything works you should get a text file in /var/spool/asterisk/sms/mtrx.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Device control over HDMI via CEC.  libcec FTW.</title>
		<link>/2012/11/26/device-control-over-hdmi-via-cec-libcec-ftw/</link>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Mon, 26 Nov 2012 15:28:18 +0000</pubDate>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[Making the world a better place]]></category>
		<category><![CDATA[tv]]></category>
		<guid isPermaLink="false">/?p=425</guid>

					<description><![CDATA[Blimey, it&#8217;s been a while.  I&#8217;ve been a bit busy, and let&#8217;s be [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Blimey, it&#8217;s been a while.  I&#8217;ve been a bit busy, and let&#8217;s be honest; writing up blog posts always sounds like a good idea, but when you get in to it &#8211; it&#8217;s really hard work.</p>
<p>Anyway &#8211; I finally got round to buying a Pulse-Eight CEC to USB adapter:  <a href="http://www.pulse-eight.com/store/products/104-usb-hdmi-cec-adapter.aspx">http://www.pulse-eight.com/store/products/104-usb-hdmi-cec-adapter.aspx</a></p>
<p>This awesome little box of tricks makes up for the lack of CEC control in the vast majority of HDMI-Out equipped graphics cards.  It&#8217;s the final piece in the jigsaw of a Linux based home entertainment device.  It allows you to talk to the other devices in your HDMI network; your surround sound amplifier and your big screen TV being the best examples (assuming they support CEC of course).</p>
<p>CEC has been around for a long time but for some reason it doesn&#8217;t seem to be widely used, or very well implemented, in most consumer electronics devices.  It&#8217;s a published standard but with OEM manufacturers wanting to differentiate their products and introduce a bit of vendor lock-in, they all call it something different.  The fact is that your Toshiba Regza Link TV will talk to your Sony Bravia Link Amp just fine, for the most part.  There might be a couple of proprietary things which don&#8217;t work, but on, off, volume up, volume down etc will all just work.</p>
<p>Pulse Eight&#8217;s USB to CEC adapter lets your computer get in on the act too, and opens up a whole realm of automatic switching, which really cuts down on the number of remote controls you need and the number of buttons you have to remember the purpose of.</p>
<p>The good folk at Pulse Eight have also made libCEC, an open source library to allow pretty much any software to take advantage of the USB adapter.  <a href="http://libcec.pulse-eight.com/">http://libcec.pulse-eight.com/</a></p>
<p>It comes with C++, C and .NET interfaces, and a CLI utility called cec-client.  XBMC &amp; MythTV already support libCEC and have some neat features baked right in.  It&#8217;s good, but it&#8217;s not exactly what I was looking for &#8211; I want a bit more control.</p>
<p>Now, I don&#8217;t know anything about C++ or C or .NET, so until someone writes some Python bindings, my ticket to this party lies solely with the CLI utility cec-client.  It can do most things on the &#8220;transmit&#8221; side, so you can send commands to your other CEC devices fairly easily.  Acting on a request, or listening to the CEC traffic is a bit more complex &#8211; but not beyond the realms of possibility.</p>
<p>This weekend I wrote (and rewrote and rewrote) a couple of Bash scripts to:</p>
<ul>
<li>Let me control the system volume (i.e. the real hardware, not the mixer on the computer) on the TV &amp; Amp from the PCs remote control</li>
<li>Let me switch the TV &amp; Amp on and off</li>
<li>Activate proper muting, again not the mixer on the computer &#8211; the hardware itself</li>
<li>Switch the amp &amp; TV to my MythTV PC</li>
<li>Power off all the hardware when the PC suspends, and then switching it all back on again</li>
<li>Shut the whole lot down when the screensaver on the PC kicks in.</li>
</ul>
<p style="text-align: left;">I make these scripts available for your amusement:</p>
<div>
<ul>
<li><a href="/wp-content/uploads/2012/11/cecserver.sh_.txt">cecserver.sh</a></li>
<li><a href="/wp-content/uploads/2012/11/cecsimple.sh_.txt">cecsimple.sh</a></li>
</ul>
</div>
<p>cecsimple is a client of the &#8220;server&#8221; which itself is a client of cec-client.  Fire up the server and then issue it commands down the FIFO either directly or via the abstraction layer which is cecsimple.sh.</p>
<p>&nbsp;</p>
<p>I hooked up the volume control and amp power via &#8220;irexec&#8221; and lirc.  I tell irexec to execute, for example, &#8220;cecsimple.sh volup&#8221; or &#8220;cecsimple.sh ampon&#8221;.  If the server component is already running then these commands are sent very quickly and you don&#8217;t really notice the lag.</p>
<p>To switch the TV off when the PC goes in to suspend mode I added a script in /etc/pm/sleep.d which calls &#8220;cecsimple.sh tvoff&#8221; and then &#8220;cecsimple.sh tvon&#8221; when it resumes.  In theory if the TV is using the Amp to output surround sound audio then the TV will tell the Amp to turn off, it it&#8217;s not &#8211; it wont.</p>
<p>To switch things off when the screensaver kicks in, I simply &#8220;sudo pm-suspend&#8221; from an &#8220;xscreensaver-command -watch&#8221; script.</p>
<p>&nbsp;</p>
<p>The practical upshot is that I can now control 99% of my media centre from a single remote control.  I&#8217;ve opted to use the remote connected to the PC as I found it to be the least laggy &#8211; using the TV remote to send up/down/left/right etc to the PC was sluggish.</p>
<p>&nbsp;</p>
<p>I think it should be possible to parse the log output from cec-client and write a &#8220;listener&#8221; component too, but it&#8217;s probably a better idea to learn some rudimentary C and do it properly.  Or some Python bindings.  Oh yeah, and you know what would be really cool, a hook in to MythTV so that when I&#8217;m watching something in surround sound the amp turns on automatically. That would be cool.</p>
<p>&nbsp;</p>
<p>UPDATE 3 Dec 2013:  When someone leaves the amp&#8217;s HDMI switch set on the PS3 and you switch the MythTV box on from the remote, the amp doesn&#8217;t automatically switch to MythTV.  This has been annoying me for a while now, so I fixed it.</p>
<p>In the scripts linked to above the &#8220;active source&#8221; command does this:</p>
<pre>send_command "tx 45 82 11 00"</pre>
<p>4 (the MythTV device) to 5 (the amp) &#8211; 82 (switch active source) to 1.1.0.0 &#8211; but my Sony amp just ignores this request.</p>
<p>I spent some time trying out a few alternatives with cec-client and I&#8217;ve found one which works, and it kinda makes sense why:</p>
<pre>send_command "tx 45 70 11 00"</pre>
<p>4 (MythTV) to 5 (Sony amp) 70 (System Audio Mode) 1.1.0.0 (the input where MythTV is connected)</p>
<p>My assumption is that amp only speaks &#8220;system audio&#8221; &#8211; what with it being an amp.  I&#8217;ve changed the &#8220;activesrc&#8221; with the 45:70:11:00 code and now it works!  (It also switches the amp on, whether I like it or not &#8211; so it&#8217;s not perfect).</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>Useful links:</p>
<ul>
<li><a href="http://www.cec-o-matic.com/">http://www.cec-o-matic.com/</a></li>
<li><a href="http://www.jwz.org/xscreensaver/man3.html">http://www.jwz.org/xscreensaver/man3.html</a></li>
<li><a href="https://github.com/Pulse-Eight/libcec">https://github.com/Pulse-Eight/libcec</a></li>
</ul>
<p>&nbsp;</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Fixing &#8220;warning: Please check that your locale settings&#8221;</title>
		<link>/2012/08/16/fixing-warning-please-check-that-your-locale-settings/</link>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Thu, 16 Aug 2012 17:01:58 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">/?p=415</guid>

					<description><![CDATA[I took an Amazon AWS t1.micro instance for a spin the other day. [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>I took an Amazon AWS t1.micro instance for a spin the other day. A free server is not to be sniffed at. Of course I installed Ubuntu 12.04 on it.</p>
<p>I was getting a lot of locale errors, things like this:</p>
<pre>perl: warning: Setting locale failed.
 perl: warning: Please check that your locale settings:
 LANGUAGE = (unset),
 LC_ALL = (unset),
 LC_MESSAGES = "en_GB.UTF-8",
 LC_COLLATE = "en_GB.UTF-8",
 LC_CTYPE = "en_GB.UTF-8",
 LANG = "en_US.UTF-8"
 are supported and installed on your system.</pre>
<p>I thought this would just go away by itself, but it didn&#8217;t &#8211; so I had to fix it. Note: I&#8217;m in the UK, so I&#8217;m using en_GB as my locale, change yours to en_US or whatever.</p>
<p>Type:</p>
<pre>export LANGUAGE=en_GB.UTF-8
sudo locale-gen en_GB.UTF-8
sudo dpkg-reconfigure locales</pre>
<p>And you should be all set.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Monetizing my feeds</title>
		<link>/2012/08/04/monetizing-my-feeds/</link>
					<comments>/2012/08/04/monetizing-my-feeds/#comments</comments>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Sat, 04 Aug 2012 15:32:07 +0000</pubDate>
				<category><![CDATA[Making the world a better place]]></category>
		<guid isPermaLink="false">/?p=403</guid>

					<description><![CDATA[I decided I wanted to add adverts to my RSS feed. Hardly anyone [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>I decided I wanted to add adverts to my RSS feed. Hardly anyone subscribes to this blog, a dozen people or so (Hello! I bet I know exactly who you all are), but I do get a few hundred hits a month on my <a title="Absolute beginners guide to Google Maps Javascript" href="/2009/05/absolute-beginners-guide-to-google-maps-javascript/">Beginners Guide To Google Maps tutorial</a>. So adding adverts to the feed shouldn&#8217;t really hurt anyone, and as a bonus the bandwidth used serving the RSS feed should reduce.</p>
<p>AdSense lets you easily monetize a feed by sucking in an RSS feed, and this is <a style="text-decoration: none;" href="http://www.phonetipsandtricks.com/increase-adsense-earnings/"><span style="text-decoration: none; color: #3d3d3d;">how to increase your Adsense earnings</span></a>, parsing it and adding the advert code and then spitting it back out again via FeedBurner.  You can do this by logging in to your AdSense account, click &#8220;My Ads&#8221; and then expand the &#8220;Feeds&#8221; section on the left. Once you&#8217;ve filled in the boxes, it&#8217;ll provide you with a new URL for your feed complete with adverts.</p>
<p>All this is pretty easy, but then comes the question of how you get people to see the new monetized feed?</p>
<p>First things first, FeedBurner can generate a little bit of HTML for you to add to your WordPress Sidebar. It&#8217;s described here<a href=" http://support.google.com/feedburner/answer/78487/?hl=en&amp;"> http://support.google.com/feedburner/answer/78487/?hl=en&amp;</a> and for the sake of completeness also described here:</p>
<ol>
<li>Log in to FeedBurner using the same credentials as you log in to AdSense</li>
<li>Click on <strong>Publicize</strong> from the menus near the top of the page</li>
<li>Click on <strong>Chicklet Chooser</strong></li>
<li>Choose the type of button you&#8217;d like to appear on you blog. Personally I think the smaller &#8220;Subscribe in a reader&#8221; is the best choice</li>
<li>Then the Javascript at the button of the page is automatically updated, so copy it to the clipboard (ctrl-c)</li>
<li>Go to the Admin page of your WordPress blog</li>
<li>Choose <strong>Appearance</strong></li>
<li>Choose <strong>Widgets</strong></li>
<li>Drag &#8220;<strong>Text: Arbitrary text for HTML</strong>&#8221; to your sidebar</li>
<li>Drop down the Sidebar widget and paste the text from above in to the big box</li>
<li>Click <strong>Save</strong> and click <strong>close</strong></li>
<li>You&#8217;re done!</li>
</ol>
<p>That was the easy bit. Now new subscribers to your blog feed can simply click the button and will be taken to the new monetized feed.</p>
<p>But what about existing subscribers? Or 3rd party links which point direct at your &#8220;/feed/&#8221; URL? There&#8217;s the rub.</p>
<p>What you need to do is redirect them to the new URL, but then if you put a <em>global</em> redirect from the old URL to the new URL, how is FeedBurner going to keep itself updated? (It&#8217;ll get redirected back to itself and so never see any of your new posts)</p>
<p>The trick is to use <strong>mod_rewrite</strong> and check for the <strong>HTTP_USER_AGENT</strong> of &#8220;FeedBurner&#8221;.</p>
<p>I&#8217;m going to assume that you&#8217;ve already got mod_rewrite enabled in your Apache config. If you&#8217;re running WordPress on your own server then you most likely have it enabled without even realising.</p>
<p>In your blog&#8217;s web directory you will find a &#8220;<strong>.htaccess</strong>&#8221; file, open this up and you&#8217;ll probably see something like this:</p>
<pre># BEGIN WordPress
 RewriteEngine On
 RewriteBase /
 RewriteRule ^index.php$ - [L]
 RewriteCond %{REQUEST_FILENAME} !-f
 RewriteCond %{REQUEST_FILENAME} !-d
 RewriteRule . /index.php [L]</pre>
<p>What you need to do is add these lines between &#8220;<strong>RewriteBase /</strong>&#8221; and &#8220;<strong>RewriteRule ^index.php$ &#8211; [L]</strong>&#8221;</p>
<pre>RewriteCond %{REQUEST_URI} ^/feed/* [NC]
 RewriteCond %{HTTP_USER_AGENT} !FeedBurner
 RewriteRule ^feed/?.*$ http://feeds.feedburner.com/Whizzyorg [R,L]
 #Next rule</pre>
<p>How does it work?</p>
<p>Mod_rewrite matches all the conditions in order, when it hits a Rule it decides if all the preceding conditions are met, and if so acts on the rule. If not, if moves on to the next line. The rules are the the separators between the conditions.</p>
<p>So the new logic says:</p>
<ul>
<li><span style="text-decoration: underline;">IF</span> you&#8217;re trying to get to &#8220;<strong>/feed/</strong>&#8221; (the [NC] makes it case insensitive)</li>
<li><span style="text-decoration: underline;">AND</span> your <strong>USER_AGENT</strong> is <em>NOT</em> &#8220;FeedBurner&#8221; (the ! inverts the logic)</li>
<li><span style="text-decoration: underline;">THEN</span> re-direct people to the new URL</li>
</ul>
<p>So, if you are FeedBurner you get access to the old standard WordPress RSS feed and keep yourself updated, if you&#8217;re anyone else you get redirected and see the adverts.</p>
<p>The adverts are fairly inconspicuous and are easily blocked by those in the know, so I don&#8217;t have a problem with it.</p>
<p>Neat!</p>
]]></content:encoded>
					
					<wfw:commentRss>/2012/08/04/monetizing-my-feeds/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Over engineering FTW</title>
		<link>/2012/03/08/over-engineering-ftw/</link>
					<comments>/2012/03/08/over-engineering-ftw/#comments</comments>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Thu, 08 Mar 2012 20:26:37 +0000</pubDate>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[Making the world a better place]]></category>
		<guid isPermaLink="false">/?p=383</guid>

					<description><![CDATA[Working from home has many advantages.  No commuting, relaxed approach to being dressed, [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Working from home has many advantages.  No commuting, relaxed approach to being dressed, loud music.</p>
<p>One of the drawbacks however, is that you are entirely reliant on your broadband connection.  You could, as many do, have a 3G modem/phone as a backup.  Fine for a few hours, but you&#8217;re soon going to run in to data caps, invisible proxies and traffic shapers (more so than a fixed line telco).</p>
<p>&nbsp;</p>
<p>So what to do?  My solution has been to get a second line installed.  The big UK telcos are running a lot of offers at the moment to try and secure as many customers as they can in readiness for their Triple &amp; Quadruple Play strategies.  This means you can get a reasonable ADSL line and line rental for about 15 to 20 quid a month.</p>
<p>When you&#8217;re as reliant on a connection as I am, that&#8217;s money well spent.  It also gives you a perfect opportunity to play with some new toys!</p>
<p>Now, you could simply plug in another wifi router to the new line, and when the primary connection fails move your connections over to the secondary one.  But where&#8217;s the fun in that?  What you <em><strong>really</strong></em> want to do is some load-balancing and multi-path routing over both the lines.  You won&#8217;t see a sudden doubling in download speeds in normal browsing, but certain activities which open a lot of connections to different IP address should benefit, <em><strong>and</strong></em> you get to play with routing tables.</p>
<p>Here&#8217;s what it looks like:</p>
<p><a href="http://whizzy.org/wp-content/uploads/2012/03/Networksetup.png"><img loading="lazy" class="alignnone size-medium wp-image-385" title="Networksetup" src="/wp-content/uploads/2012/03/Networksetup-300x88.png" alt="" width="300" height="88" srcset="/wp-content/uploads/2012/03/Networksetup-300x88.png 300w, /wp-content/uploads/2012/03/Networksetup-768x227.png 768w, /wp-content/uploads/2012/03/Networksetup.png 956w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<p>&nbsp;</p>
<p>We don&#8217;t really get much diversity until we get south of the exchange, and even then we&#8217;re probably going to live in the same fibre all the way to The Internet, but we do work round the much more common problem of ISP configuration errors.</p>
<p>Here&#8217;s how it works:</p>
<p>Router 1 (R1) and Router 2 (R2) are two independent ADSL modem/routers  connected to a phone line each and the ethernet port connected to a NIC in a server.  These modem/routers also take care of NAT, so that any traffic coming from inside your network will be translated to appear as if it had come from the appropriate router on it&#8217;s way to the rest of the internet.  The server has three NICs in total, one each for the two routers and one back to the LAN for everyone else on the network to use as a gateway.</p>
<pre>$IF0 = eth0
$IF1 = eth1
$IF2 = eth2</pre>
<p>The IP addresses associated with those interfaces are:</p>
<pre>$IP0 = 192.168.3.100
$IP1 = 192.168.1.1
$IP2 = 192.168.2.1</pre>
<p>The routers are configured with these LAN IPs:</p>
<pre>$P1 = 192.168.1.254
$P2 = 192.168.2.254</pre>
<p>As you can see on the diagram, the networks are all /24 (255.255.255.0) which gives us network numbers of:</p>
<pre>$P0_NET = 192.168.3.0
$P1_NET = 192.168.1.0
$P2_NET = 192.168.2.0</pre>
<p>Then we configure the Ubuntu box as a router &amp; NATing gateway:</p>
<p>1.  Enable IP forwarding by editing<em> /etc/sysctl.conf</em> and uncommenting or adding a line like this:</p>
<pre>net.ipv4.ip_forward=1</pre>
<p>2.  Create two new routing tables.  Edit /etc/iproute2/rt_tables and add a line for each of your providers.  For example:</p>
<pre>1 my_isp_name
2 my_other_isp_name</pre>
<p>3. Create some routes in each of the routing tables so the server knows where to send data.  They take the general format of:</p>
<pre>ip route add <em>$P1_NET</em> dev <em>$IF1</em> src <em>$IP1</em> table my_isp_name
ip route add default via <em>$P1</em> table my_isp_name
ip route add <em>$P2_NET</em> dev <em>$IF2</em> src <em>$IP2</em> table my_other_isp_name
ip route add default via <em>$P2</em> table my_other_isp_name</pre>
<p>&nbsp;</p>
<p>Using the real numbers and the template above gives us this actual set of commands:</p>
<pre>ip route add 192.168.1.0 dev eth1 src 192.168.1.1 table my_isp_name
ip route add default via 192.168.1.254 via eth1 table my_isp_name
ip route add 192.168.2.0 dev eth2 src 192.168.2.1 table my_other_isp_name
ip route add default via 192.168.2.254 via eth1 table my_other_isp_name</pre>
<p>&nbsp;</p>
<p>In english, that means:  In order to send traffic to the 192.168.1.0 network or the 192.168.2.0 network send it out of eth1 or eth2 from IP address 192.168.1.1 or 192.168.2.1.  These routes are then stored in the relevent routing table; either one called my_isp_name or one called my_other_isp_name.</p>
<p>&nbsp;</p>
<p>4. Create some additional routes for communicating between the routing tables and the local interfaces.  This is as much of an efficiency saving as anything, telling each routing table the quickest way to the other interfaces.</p>
<pre>ip route add <em>$P0_NET</em> dev $IF0 table my_isp_name
ip route add <em>$P2_NET</em> dev <em>$IF2</em> table my_isp_name
ip route add 127.0.0.0/8 dev lo table my_isp_name
ip route add <em>$P0_NET</em> dev <em>$IF0</em> table my_other_isp_name
ip route add <em>$P1_NET</em> dev <em>$IF1</em> table my_other_isp_name
ip route add 127.0.0.0/8 dev lo table my_other_isp_name</pre>
<p>5.  Add the routes to the main routing table, so that traffic knows how to find the networks which have the gateways to the internet on:</p>
<pre>ip route add <em>$P1_NET</em> dev <em>$IF1</em> src <em>$IP1</em>
ip route add <em>$P2_NET</em> dev <em>$IF2</em> src <em>$IP2</em></pre>
<p>6.  Apply the correct routing rules depending on where the traffic is coming from:</p>
<pre>ip rule add from <em>$IP1</em> table my_isp_name
ip rule add from <em>$IP2</em> table my_other_isp_name</pre>
<p>7.  The science bit.  Create a route which will send traffic down each of the internet connections in turn.  This is a global default route, so any traffic which isn&#8217;t bound for the local <em>$P0_NET</em> network will use this rule to get to the internet.</p>
<pre>ip route add default scope global nexthop via <em>$P1</em> dev <em>$IF1</em> weight 2 nexthop via <em>$P2</em> dev <em>$IF2</em> weight 1</pre>
<p>As you can see, this isn&#8217;t a 50/50 split.  We&#8217;ve applied some weighting, in this case because I get more GBs with my_isp_name.  We&#8217;re actually going to send twice as much traffic down <em>$IF1</em> as we are down <em>$IF2</em>.</p>
<p>8.  By default, routes to other networks are cached for 10 mins.  This means that once a route is decided on, traffic will always follow the same route for at least the next 10 minutes.  The counter will be reset every time that particular route is used.  This is great for large downloads because it means that your IP address isn&#8217;t suddenly going to change half way through getting the file.  But, for something like IRC where it&#8217;s possible that no traffic will be sent for 10 minutes, then the IRC server could well see your IP address changing as traffic flips between the two routes.  IRC servers don&#8217;t like that.  So you need to fix some routes so that traffic will always follow the same path.</p>
<pre>ip route add 174.143.119.91/32 via <em>$P2</em></pre>
<p>This sets the route to a specific Freenode IRC server to always go via my_other_isp_name.</p>
<p>9.  Last of all, we need to add an extra layer of NAT so that traffic can find its way back to the host on the LAN side.  This is necessary because our internet modem/routers are not really routers at all.  They simply take traffic from one side, rewrite the headers and push it out the other side, while maintaining a look up table of what came from where and doing the reverse when a reply arrives. If you can configure the routes on to your modem, then you don&#8217;t need to be reading this in the first place, so let&#8217;s assume you can&#8217;t.</p>
<pre>iptables --table nat --append POSTROUTING --out-interface $IF1 -j MASQUERADE
iptables --table nat --append POSTROUTING --out-interface $IF2 -j MASQUERADE
iptables --append FORWARD --in-interface $IF0 -j ACCEPT</pre>
<p>For things like port forwarding you do now have to deal with a bit of an odd NAT situation.  For example, let&#8217;s assume I want to run a web server on the same machine that runs the routing.  I decide to only make the server available on the WAN IP address of $R1.  I set up Router 1 to NAT port 80 on the WAN to port 80 on $IP1.  Then I need to configure the web server on the routing server to listen on that interface.  Not too bad really.</p>
<p>And there you have it.  Two internet connections, both available to all the clients on your network.  Make sure that your clients use the IP address of the server as their default gateway and everything should just work.  The additional load on the server is negligible.</p>
<p>If you reboot the server you&#8217;ll need to add all the routing information again, so create yourself a Bash and have it run from /etc/rc.local or something.</p>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>/2012/03/08/over-engineering-ftw/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title>Overriding Outbound Dial Command Options</title>
		<link>/2011/09/05/overriding-outbound-dial-command-options/</link>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Mon, 05 Sep 2011 19:03:24 +0000</pubDate>
				<category><![CDATA[asterisk]]></category>
		<guid isPermaLink="false">/?p=365</guid>

					<description><![CDATA[I&#8217;ve previously noted that you can apply time limits to calls going out [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>I&#8217;ve previously noted that you can apply time limits to calls going out of your Asterisk box:</p>
<p><a href="/2011/02/more-asterisk-hints/">/2011/02/more-asterisk-hints/</a></p>
<p>using the L(nnn,mmm,yyy) options for DIAL_TRUNK_OPTIONS. But, what if you don&#8217;t want to limit the length of calls for a specific trunk?</p>
<p>Well, FreePBX has a context called [macro-dialout-trunk-predial-hook] which lets you jump in at the very last moment and override any settings you like, which is perfect for this sort of thing.</p>
<p>I got the idea from here:</p>
<p><a href="http://www.freepbx.org/book/export/html/5893">http://www.freepbx.org/book/export/html/5893</a></p>
<p>I&#8217;ve added this to extensions_custom.conf:</p>
<pre>[macro-dialout-trunk-predial-hook]
 exten =&gt; s,1,NoOp(Trunk ${OUT_${DIAL_TRUNK}} selected)
 exten =&gt; s,n,Gotoif($["${OUT_${DIAL_TRUNK}}" != "SIP/TRUNK_NAME"]?skip)
 exten =&gt; s,n,NoOp(Setting DIAL_TRUNK_OPTIONS to Ww)
 exten =&gt; s,n,Set(DIAL_TRUNK_OPTIONS="Ww")
 exten =&gt; s,n(skip),MacroExit()</pre>
<p>Which tests the name of the trunk which is to be used and explicitly sets DIAL_TRUNK_OPTIONS if it matches, otherwise nothing happens. This is a very powerful feature and my extremely crude hack doesn&#8217;t do it justice. I wanted to make a note of this before I forgot.</p>
<p>A better way might be to look at the dial prefix? I&#8217;ll investigate that option, but for now that will have to do.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>NOOP scheduler &#8211; not worth it for SSD</title>
		<link>/2011/08/16/noop-scheduler-not-worth-it-for-ssd/</link>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Tue, 16 Aug 2011 09:45:33 +0000</pubDate>
				<category><![CDATA[linux]]></category>
		<guid isPermaLink="false">/?p=359</guid>

					<description><![CDATA[I&#8217;ve got a new Thinkpad X220i with a 128GB SSD. Reading around the [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>I&#8217;ve got a new Thinkpad X220i with a 128GB SSD.</p>
<p>Reading around the internet I found a lot of stuff about squeezing a bit more throughput from your drive.</p>
<p>I did a couple of benchmarks in Ubuntu 11.04:</p>
<ul>
<li>Adding noatime,discard to /etc/fstab</li>
</ul>
<p><span style="text-decoration: underline;"><strong>Result:</strong></span>  No change.  Not better or worse, but in theory the &#8220;discard&#8221; will help in the long term</p>
<p><span style="text-decoration: underline;"><strong>Decision:</strong></span>  Switch this on.</p>
<ul>
<li>Setting the scheduler to noop in /etc/rc.local</li>
</ul>
<p><span style="text-decoration: underline;"><strong>Result:</strong></span> Average read rate increased by 2MB/s but Average access time went from 0.2ms to 0.3 ms.  In itself that&#8217;s not a real problem, but the graphs show a different picture.</p>
<p><span style="text-decoration: underline;">Without NOOP</span></p>
<p>Note the scale on the right hand side.</p>
<p><a href="http://whizzy.org/wp-content/uploads/2011/08/without_noop.png"><img loading="lazy" class="alignnone size-medium wp-image-362" title="without_noop" src="/wp-content/uploads/2011/08/without_noop-300x193.png" alt="" width="300" height="193" /></a></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span style="text-decoration: underline;">With NOOP</span></p>
<p><a href="http://whizzy.org/wp-content/uploads/2011/08/with_noop.png"><img loading="lazy" class="alignnone size-medium wp-image-361" title="with_noop" src="/wp-content/uploads/2011/08/with_noop-300x195.png" alt="" width="300" height="195" /></a></p>
<p>The access speed is all over the place.</p>
<p><span style="text-decoration: underline;"><strong>Decision:</strong></span>  Switch this off</p>
<p>&nbsp;</p>
<p>I&#8217;d be interested in hearing if your experience differs, but it seems to me that &#8220;Doing nothing&#8221; is a valid choice.  Ubuntu, out of the box, doesn&#8217;t really require any fettling in order to get the best from your SSD.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Off to pastures new</title>
		<link>/2011/07/22/off-to-pastures-new/</link>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Fri, 22 Jul 2011 15:33:27 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">/?p=352</guid>

					<description><![CDATA[]]></description>
										<content:encoded><![CDATA[<p><a href="http://whizzy.org/wp-content/uploads/2011/07/tumblr_l56x4xU4ct1qzpwi0o1_400.jpg"><img loading="lazy" class="alignnone size-medium wp-image-355" title="tumblr_l56x4xU4ct1qzpwi0o1_400" src="/wp-content/uploads/2011/07/tumblr_l56x4xU4ct1qzpwi0o1_400-207x300.jpg" alt="" width="207" height="300" /></a></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>TCP sessions causing lag</title>
		<link>/2011/07/04/tcp-sessions-causing-lag/</link>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Mon, 04 Jul 2011 12:06:33 +0000</pubDate>
				<category><![CDATA[Making the world a better place]]></category>
		<guid isPermaLink="false">/?p=353</guid>

					<description><![CDATA[I like to play Call Of Duty online on this year&#8217;s some of [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>I like to play Call Of Duty online on <A href="https://gamingbuff.com/">this year&#8217;s some of the best gaming monitors</a>. I find it&#8217;s a really good way to get angry and frustrated at inanimate objects. I also run a Bit Torrent client on my network.</p>
<p>I don&#8217;t suck at MW2 and I&#8217;m not too bad at Black Ops either, but on the PS3 Black Ops has been very unstable to the point of hanging the console.</p>
<p>Anyway, what really gets me cross is Lag. You can tell a match is going to be laggy the second the game opens. It feels as if you&#8217;re running through treacle. &#8220;GET A MOVE ON&#8221; I scream. And then it starts; you get shot while behind brick walls, your shots fail to connect even though &#8220;IT WAS CLEARLY A HEADSHOT WHY WONT YOU JUST DIE?&#8221;. And so on. You know what I&#8217;m talking about.</p>
<p>Originally I had a written a script to ping the PS3 and when it came online and tell Transmission to pause all the Torrents. When the PS3 went offline again it would start them. I thought this would be enough, but it isn&#8217;t. Even with Transmission paused and the bandwidth limited to zero kBps it still maintains a connection to other peers.</p>
<p>While this isn&#8217;t a significant amount of traffic over the WAN &#8211; it really does cause lag. Presumably having something like 1000 NAT sessions in the memory of my router is a bit of a stretch, so now I simply kill Transmission when the PS3 comes online. It takes a few minutes for the sessions to get pruned but it&#8217;s made a noticeable difference to the quality of my matches.</p>
<p>Of course, you&#8217;re still at the mercy of the internet connection of whoever hosts the match &#8211; but that&#8217;s beyond your control.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Trimming Freesat Channels In MythTV</title>
		<link>/2011/06/08/trimming-freesat-channels-in-mythtv/</link>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Wed, 08 Jun 2011 12:42:58 +0000</pubDate>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[Making the world a better place]]></category>
		<category><![CDATA[tv]]></category>
		<guid isPermaLink="false">/?p=342</guid>

					<description><![CDATA[There are loads and loads of free-to-air channels available on the Astra 28 [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>There are loads and loads of free-to-air channels available on the Astra 28 constellation, the vast majority of which I do not watch.</p>
<p>So to make things a bit easier for me after a full re-scan, I&#8217;ve put together a list of the channels I don&#8217;t watch and with a tiny bit of SQL I can trim them from my channel list.</p>
<p>To make things a bit easier for <em>you</em> here is a SQL dump of my &#8220;unwatched channels&#8221; list:</p>
<p><a href="/wp-content/uploads/2012/08/unwatched_channels.sql_.txt">unwatched_channels.sql</a></p>
<p>And here is the SQL to trim these from your channel list:</p>
<p><code>update channel set visible=0,useonairguide=0 where name in (select name from unwatched_channels)</code></p>
<p>You&#8217;ll probably want to edit that list yourself to remove and add the channels as you prefer. Generally speaking, my list trims:</p>
<ul>
<li>Regional variations</li>
<li>Specialist interest</li>
<li>Shopping</li>
<li>Games and other text based services</li>
</ul>
<p>I&#8217;ll update this list occasionally, this page will always have my most up to date information.</p>
<ul>
<li>UPDATE: 6 Sept 11.  Refreshed channel list</li>
<li>UPDATE: 8 Oct 11. Refreshed channel list</li>
<li>UPDATE: 14 Dec 2011.  Refreshed channel list</li>
<li>UPDATE: 4 Aug 2012.  Refreshed channel list</li>
<li>UPDATE: 29 Dec 2013.  New list of channel IDs available here: <a href="http://whizzy.org/wp-content/uploads/2013/12/unwatched_by_chanid.csv">unwatched_by_chanid</a>.  Add a new table and import that CSV file.  Then do a &#8220;update channel set visible=0 where chanid in (select chanid from &lt;your new table&gt;&#8221;</li>
</ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Maggy Scraggle Loves The Beautiful Ice-cream Man</title>
		<link>/2011/04/17/maggy-scraggle-loves-the-beautiful-ice-cream-man/</link>
					<comments>/2011/04/17/maggy-scraggle-loves-the-beautiful-ice-cream-man/#comments</comments>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Sun, 17 Apr 2011 09:07:21 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">/?p=334</guid>

					<description><![CDATA[&#160; I was fortunate enough to be introduced to this book by my [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><a href="http://whizzy.org/wp-content/uploads/2011/04/11.jpg"><img loading="lazy" class="alignnone size-medium wp-image-332" title="1" src="/wp-content/uploads/2011/04/11-300x235.jpg" alt="" width="300" height="235" /></a></p>
<p>&nbsp;</p>
<p>I was fortunate enough to be introduced to this book by my wife reading it to our son.</p>
]]></content:encoded>
					
					<wfw:commentRss>/2011/04/17/maggy-scraggle-loves-the-beautiful-ice-cream-man/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>More Asterisk hints</title>
		<link>/2011/02/13/more-asterisk-hints/</link>
					<comments>/2011/02/13/more-asterisk-hints/#comments</comments>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Sun, 13 Feb 2011 19:21:08 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">/?p=322</guid>

					<description><![CDATA[Wow &#8211; a day of fixing loads of niggling little Asterisk problems! Max [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Wow &#8211; a day of fixing loads of niggling little Asterisk problems!</p>
<ul>
<li>Max duration</li>
</ul>
<p>My calling plan gives me unlimited free calls as long as those calls are under an hour in duration.  Pretty standard BT stuff.  If you do make a call over an hour you don&#8217;t just get charged for that bit of the call over the hour, oh no, you get charged for the whole call.<br />
Anyway &#8211; we have the technology to defeat them!</p>
<p>In FreePBX under General Settings change your Asterisk Outbound Dial command options to include:</p>
<pre>L(3360000,3240000,10000)</pre>
<p>which will drop the call after 3360000ms (56 minutes) and should alert you at 3240000ms.</p>
<ul>
<li>Courtesy Tone</li>
</ul>
<p>The above works very well and drops the calls, but without a bit of extra magic you don&#8217;t get the warning in your ear &#8211; it just drops the call.  To enable the warning tones etc edit this:</p>
<pre>/etc/asterisk/features_general_custom.conf</pre>
<p>and add</p>
<pre>courtesytone=beep</pre>
<p>substituting &#8220;beep&#8221; for what ever noise you want to hear.</p>
<ul>
<li>Call Recording</li>
</ul>
<p>By also adding:</p>
<pre>Ww</pre>
<p>to the Dial command options in #1 you can press *1 when you&#8217;re in a call to start recording.  It plays the courtesy tone to both parties though.</p>
]]></content:encoded>
					
					<wfw:commentRss>/2011/02/13/more-asterisk-hints/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Meridian Mail</title>
		<link>/2011/02/13/meridian-mail/</link>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Sun, 13 Feb 2011 17:34:26 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">/?p=320</guid>

					<description><![CDATA[Has anyone got a WAV or similar of the lady from Nortel saying [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Has anyone got a WAV or similar of the lady from Nortel saying &#8220;Meridian Mail.  Mailbox?&#8221;</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>g729 in Asterisk</title>
		<link>/2011/02/13/g729-in-asterisk/</link>
					<comments>/2011/02/13/g729-in-asterisk/#comments</comments>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Sun, 13 Feb 2011 17:29:25 +0000</pubDate>
				<category><![CDATA[asterisk]]></category>
		<category><![CDATA[linux]]></category>
		<guid isPermaLink="false">/?p=317</guid>

					<description><![CDATA[I run Asterisk 1.8 at home for my own amusement.  I&#8217;ve just got [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>I run Asterisk 1.8 at home for my own amusement.  I&#8217;ve just got a SIP trunk running again to <a href="http://www.sipgate.co.uk/">SIPGate</a> which had stopped running for some reason.  I&#8217;d set the DID for the SIPGate number to check for faxes and then, if it&#8217;s not a fax, go to my MOH application, but for some reason it didn&#8217;t work.</p>
<p>I also couldn&#8217;t access voicemail from the SIPGate trunk either, but I could get it to work with a phone connected to an ATA.</p>
<p>I had a look in the logs:</p>
<blockquote>
<pre>channel.c: Unable to find a codec translation path from 0x100 (g729) to 0x40 (slin)</pre>
</blockquote>
<p>Since slin is, I think, the Asterisk native format this is quite bad.  My assumption is that SIPGate sends through G.729 encoded audio regardless of whether you want it to or not (as configured in your allow/disallow lines for the SIP trunk PEER).</p>
<p>G729 from SIPGate works to the ATA because the ATA supports G729 and G729 to G729 pass-through works without any extra requirements from Asterisk.</p>
<p>So &#8211; in order to get SIPGate to Asterisk apps working again I installed the G729 codec binaries from here:</p>
<p><a href="http://asterisk.hosting.lv/">http://asterisk.hosting.lv/</a></p>
<p>and restarted Asterisk.  Now a:</p>
<pre>         core show translations</pre>
<p>shows I can convert between G729 and loads of other codecs.</p>
]]></content:encoded>
					
					<wfw:commentRss>/2011/02/13/g729-in-asterisk/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Asterisk VoIP calls causing PPP to drop on ADSL modems</title>
		<link>/2010/10/18/asterisk-voip-calls-causing-ppp-to-drop-on-adsl-modems/</link>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Mon, 18 Oct 2010 15:02:28 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">/?p=311</guid>

					<description><![CDATA[The internet FTW. I&#8217;ve been having this odd problem since I got my [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>The internet FTW.</p>
<p>I&#8217;ve been having this odd problem since I got my Asterisk box back up and running in that whenever a call came in and hung up I&#8217;d lose internet connectivity for a few seconds.</p>
<p>I tracked it down to the router dropping the PPP connection, which initially made me think that the polarity reversal indicating the call had hung up was causing the modem to b0rk, perhaps due to the distance between the phone socket and the modem, or my dodgy cat5 cabling, or something.</p>
<p>Turns out it was none of the above.  EDIT:  Bit hasty there.  Hasn&#8217;t fixed it al all.</p>
<p>This post:</p>
<p>http://forums.contribs.org/index.php/topic,43733.msg209081.html#msg209081</p>
<p>points to exactly my problem.  I disabled the DDoS protection and no more dropped internet connections.  I don&#8217;t worry about DDoS attacks too much, so for now I&#8217;m going to leave it off.</p>
<p>UPDATE:  None of the above actually worked.  In the end it turned out the modem had simply broken.  The NV RAM wasn&#8217;t remembering the config after a proper reboot and it was generally broken.  So I replaced the whole thing with a new DrayTek modem.  The old one did pretty well, it worked perfectly for about 3 years non-stop.</p>
<p>Search hints:</p>
<p>DrayTek VoIP Asterisk dropping ADSL PPP drop DDoS SIP</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>SMSq No call scheduled as already sending</title>
		<link>/2010/10/15/smsq-no-call-scheduled-as-already-sending/</link>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Fri, 15 Oct 2010 10:06:13 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">/?p=303</guid>

					<description><![CDATA[In order to remind myself: I kept getting this error when trying to [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>In order to remind myself:</p>
<p>I kept getting this error when trying to send an SMS;</p>
<p>No call scheduled as already sending</p>
<p>It seems SMSq or Asterisk is quite picky about who sends the SMS.  If I tired to send an SMS as myself it would fail, and then clog up /var/spool/asterisk/sms/motx with undead SMSes.</p>
<p>If I run smsq as the same user as Asterisk is running as it works (once you&#8217;ve deleted all the crap out of motx directory.</p>
<p>Just need to work out why now.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Getting NUT to talk to LiebertPSP UPS</title>
		<link>/2010/10/06/getting-nut-to-talk-to-liebertpsp-ups/</link>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Wed, 06 Oct 2010 16:17:07 +0000</pubDate>
				<category><![CDATA[linux]]></category>
		<guid isPermaLink="false">/?p=297</guid>

					<description><![CDATA[I got hold of a couple of LiebertPSP UPSes and connected to my [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>I got hold of a couple of LiebertPSP UPSes and connected to my servers.  They&#8217;re perfectly good for what I need them for, namely stopping my servers having the rug pulled out from underneath them with no notice if there is a power cut.</p>
<p>They don&#8217;t appear to have advanced functions like switching off the load independently of the supply which means you can&#8217;t power down the servers and then have the UPS switch them back on again once the power is restored and the battery has had a chance to charge, but I can live without that sort of thing.</p>
<p>I assumed that something somewhere would support these, and for the most part NUT does a bang up job.  It&#8217;s a bit advanced for my needs but most of the work has already been done.  In NUT the LiebertPSP is sort-of-supported by the Belkin USB driver with a few notable exceptions:</p>
<ul>
<li>The Online/On Battery indication doesn&#8217;t work</li>
<li>The numeric values don&#8217;t work for things like Output Voltage</li>
</ul>
<p>The numbers I can live without but the Online / On Battery is really rather important.</p>
<p>So I&#8217;ve cobbled together a new sub-driver using the tools supplied with Nut.  It&#8217;s far from complete but it does fix most of the annoying problems.</p>
<p><a href="/wp-content/uploads/2010/10/liebertpsp.tar.gz">/wp-content/uploads/2010/10/liebertpsp.tar.gz</a></p>
<p>You&#8217;ll need to download the Nut source and put the .c and .h files in the above tarball in to the drivers directory, then you&#8217;ll need to apply this patch in the drivers directory to get the new driver included in the build and to stop the native Belkin driver from claiming the ID of the LiebertPSP:</p>
<p><a href="/wp-content/uploads/2010/10/liebertpsp.diff">/wp-content/uploads/2010/10/liebertpsp.diff</a></p>
<p>Then recompile Nut.</p>
<p>If everything works you should see a bit more info from your UPS:</p>
<pre>battery.type: PbAc</pre>
<pre>device.mfr: Emerson Network Power</pre>
<pre>device.model: LiebertPSP</pre>
<pre>device.serial:</pre>
<pre>device.type: ups</pre>
<pre>driver.name: usbhid-ups</pre>
<pre>driver.parameter.bus: 004</pre>
<pre>driver.parameter.pollfreq: 30</pre>
<pre>driver.parameter.pollinterval: 2</pre>
<pre>driver.parameter.port: auto</pre>
<pre>driver.version: 2.4.3-2519M</pre>
<pre>driver.version.data: LiebertPSP HID 0.1</pre>
<pre>driver.version.internal: 0.35</pre>
<pre>ups.input.frequency: 50.0</pre>
<pre>ups.input.voltage: 243</pre>
<pre>ups.mfr: Emerson Network Power</pre>
<pre>ups.model: LiebertPSP</pre>
<pre>ups.output.percentload: 54</pre>
<pre>ups.output.voltage: 240</pre>
<pre>ups.powersummary.capacitygranularity1: 1</pre>
<pre>ups.powersummary.capacitygranularity2: 1</pre>
<pre>ups.powersummary.capacitymode: 2</pre>
<pre>ups.powersummary.configvoltage: 12.0</pre>
<pre>ups.powersummary.designcapacity: 100</pre>
<pre>ups.powersummary.fullchargecapacity: 100</pre>
<pre>ups.powersummary.imanufacturer: 19</pre>
<pre>ups.powersummary.ioeminformation: 19</pre>
<pre>ups.powersummary.iproduct: 1</pre>
<pre>ups.powersummary.presentstatus.batterypresent: 1</pre>
<pre>ups.powersummary.presentstatus.belowremainingcapacitylimit: 0</pre>
<pre>ups.powersummary.presentstatus.charging: 1</pre>
<pre>ups.powersummary.presentstatus.discharging: 0</pre>
<pre>ups.powersummary.presentstatus.needreplacement: 0</pre>
<pre>ups.powersummary.presentstatus.shutdownimminent: 0</pre>
<pre>ups.powersummary.rechargeable: 1</pre>
<pre>ups.powersummary.remainingcapacity: 100</pre>
<pre>ups.powersummary.remainingcapacitylimit: 38</pre>
<pre>ups.powersummary.voltage: 14</pre>
<pre>ups.powersummary.warningcapacitylimit: 38</pre>
<pre>ups.productid: 0001</pre>
<pre>ups.serial:</pre>
<pre>ups.status: OL</pre>
<pre>ups.vendorid: 10af</pre>
<p>Search hints:</p>
<p>Vendor ID: 0x10af</p>
<p>Product ID: 0x0001</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>LogWatch SMART monitoring</title>
		<link>/2010/09/27/logwatch-smart-monitoring/</link>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Mon, 27 Sep 2010 11:09:23 +0000</pubDate>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[Making the world a better place]]></category>
		<guid isPermaLink="false">/?p=299</guid>

					<description><![CDATA[Why is one of my boxes reporting SMART data in the LogWatch and [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Why is one of my boxes reporting SMART data in the LogWatch and the others not?</p>
<p>I&#8217;d installed smartmontools but it just doesn&#8217;t seem to be working.</p>
<p>Finally sussed it.   Have a look at /etc/default/smartmontools and enable deamon</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Hauppauge WinTV Nova-S Plus on Linux</title>
		<link>/2010/08/04/hauppauge-wintv-nova-s-plus-on-linux/</link>
					<comments>/2010/08/04/hauppauge-wintv-nova-s-plus-on-linux/#comments</comments>
		
		<dc:creator><![CDATA[will]]></dc:creator>
		<pubDate>Wed, 04 Aug 2010 17:15:09 +0000</pubDate>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[Making the world a better place]]></category>
		<category><![CDATA[tv]]></category>
		<guid isPermaLink="false">/?p=291</guid>

					<description><![CDATA[The Nova-S Plus is a  good card.  http://www.hauppauge.co.uk/site/products/data_novasplus.html But, it would appear there [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>The Nova-S Plus is a  good card.  <a href="http://www.hauppauge.co.uk/site/products/data_novasplus.html">http://www.hauppauge.co.uk/site/products/data_novasplus.html</a></p>
<p>But, it would appear there is a defect in these boards, or at least a strange design, which means that they won&#8217;t lock on to some frequencies which require the 22kHz tone sending to the LNB with new drivers because there&#8217;s no link between the flange and dolphin-points.  There&#8217;s plenty to read about here:</p>
<p><a href="https://bugzilla.kernel.org/show_bug.cgi?id=9476">https://bugzilla.kernel.org/show_bug.cgi?id=9476</a></p>
<p>And there&#8217;s a patch which fixes the problem by controlling the tone generator directly but it&#8217;ll never get in to the main kernel.  For your convenience here is a link to a binary driver built for Ubuntu Lucid kernel version 2.6.32-23-generic:</p>
<p><a href="/wp-content/uploads/2010/08/isl6421.ko">/wp-content/uploads/2010/08/isl6421.ko</a></p>
<p>Replace the current isl6421.ko from /lib/modules/2.6.32-23-generic/kernel/drivers/media/dvb/frontends/isl6421.ko with this one.  It might also work for newer kernel versions, or not.  Who knows?  Not me.</p>
<p>I&#8217;ve also got a Hauppauge S2 HD and this patched driver doesn&#8217;t seem to effect it.</p>
<p>Search hints:</p>
<p>Hauppauge Nova S plus linux won&#8217;t lock horizontal 22khz tone can&#8217;t pick up some channels. You can also check out my guide on <a style="text-decoration: none" href="http://outdoormoviehq.com/ultimate-guide-to-outdoor-movies/"><font color="#555555">Everything You Need to Set Up a Backyard Cinema</font></a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>/2010/08/04/hauppauge-wintv-nova-s-plus-on-linux/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
	</channel>
</rss>
