Toggling web ad-blocking via a Squid proxy

Squid is a popular open-source proxy that can be configured to block adverts. I run it on a Raspberry Pi & have my iPad Air and Samsung Galaxy S21 Ultra configured to use the proxy when connected to my Wifi at home. There are good articles on the web which show you how to set all this up, so I won’t go over it in this post.

One thing I needed was a way to easily turn the ad-blocking off & back on, since blocking ads sometimes breaks sites or links to sites (especially affiliate tracking links).

You can of course go into the network settings & remove the proxy configuration, then put it all back after you’re done, but this is a pain & I really wanted a 1-tap solution which would work on iOS & Android.

First, I wrote a bash script which would toggle the ads on/off.. this works by emptying/populating the adblock.txt file that Squid consumes & telling Squid to re-read it. Here’s the script I came up with;

/etc/squid/squid_ads_toggle.sh

if [ -s "/etc/squid/adblock.txt" ]; then
        : > /etc/squid/adblock.txt
        /usr/sbin/squid -k reconfigure
        echo "Adverts ENABLED" > /var/www/html/proxyadstoggle.out
else
        curl -sS -L --compressed "http://pgl.yoyo.org/adservers/serverlist.php?hostformat=squid-dstdom-regex&showintro=0&mimetype=plaintext" > /etc/squid/adblock.txt
        /usr/sbin/squid -k reconfigure
        echo "Adverts DISABLED" > /var/www/html/proxyadstoggle.out
fi

Testing this from a command prompt worked, so the next thing I needed to do was be able to trigger it from a web server call. My Raspberry Pi already has Apache & PHP running, so that was the natural place to create a quick PHP page that executes the bash script;

/var/www/html/proxyadstoggle.php

<?php
        print ("Toggling ads on Squid proxy [");
        $exec = "sudo /etc/squid/squid_ads_toggle.sh";
        exec($exec, $output, $retval);
        print($retval."] - ");

        $file = file_get_contents('/var/www/html/proxyadstoggle.out', true);
        print($file);
?>

The last thing I needed to give permission for the web service to run the bash script, which uses visudo to allow the ‘www-data’ user to run it. Now, I realise this isn’t ideal, but I couldn’t find a better solution; please understand the security risks of doing this if you’re going to follow this guide.

sudo visudo

www-data ALL=(ALL) NOPASSWD: /etc/squid/squid_ads_toggle.sh

Testing this in a web browser worked, so next I could move on to triggering it from my iPad and Android phone.. I could just go to the page in a browser, but that felt a bit clunky & there are nicer ways to do this! :)

Shortcuts on iOS

‘Shortcuts’ is a really nice automation app that’s built into iOS; with just 2 steps, I can call the PHP page & output the result into a native popup notification. Here’s how it looks;

The shortcuts can be added to the slide-out widget panel in iOS, which make it really convenient to access!

Running the shortcut will display a notification like this;

Automate on Android

There isn’t a built-in equivalent of ‘Shortcuts’ on Android, but I do have Automate, which I’ve previously used in projects I’ve blogged about on here.

Here’s how the ‘Flow’ looks;

The HTTP Request block needs to save the output to a variable, like this;

And the Toast notification can then display what’s in the variable like this;

You can add the Flow to your home screen as a shortcut (via Automate, or through Widgets), and when you tap it you’ll see a notification like this;

And there you have it! An easy way to toggle ad-blocking on your phone or tablet. Those apps on iOS and Android open up a world of opportunities to integrate with other systems & do some really neat stuff.

Alexa, find me an alternative to IFTTT

On 31st October 2023, the built-in Alexa integration with IFTTT stopped working with very little notice given to its users. This post show how you can replace IFTTT and get your Alexa Routines back up and working!

I don’t have a lot of time invested in a complex IFTTT setup, but we do use it to tell the kids that dinner is ready using this flow;

  1. An Alexa Routine listens for, “Alexa, tell the kids dinner is ready”
  2. The Routine calls an IFTTT Recipe
  3. The IFTTT Recipe writes 2 text files to Dropbox containing commands to execute on the PC
  4. The kids’ PCs, which use the same Dropbox account, have AssistantComputerControl monitoring the text files
  5. As soon as AssistantComputerControl detects the text files it executes the command inside & deletes the file. In my case, it plays a sound telling the kids dinner is ready.

We can remove the Alexa Routine call to IFTTT by replacing it with a service called Voice Monkey. Voice Monkey has a lot more features, like being able to call a web service & have Alexa read out a response. I couldn’t do that with IFTTT!

If you still want to call a IFTTT Recipe, you can change the Recipe to be triggered by a HTTP request, then call that from your Voice Monkey Flow.

In my case, I wanted to remove IFTTT entirely from my workflow, so instead of having that write the text files to Dropbox, I did the same thing using an Azure Logic App, which I’ve blogged about before and have a video showing them in action here;

My new workflow is as follows;

  1. An Alexa Routine listens for, “Alexa, tell the kids dinner is ready”
  2. The Routine calls a Voice Monkey Flow
  3. The Flow makes a HTTP call to a Logic App, then responds with a custom message for Alexa to read out.
  4. The Logic App writes 2 text files to Dropbox containing commands to execute on the PC
  5. Our 2 kids’ PCs, which use the same Dropbox account, have AssistantComputerControl monitoring the text files
  6. As soon as AssistantComputerControl detects the text files it executes the command inside & deletes the file. In my case, it plays a sound telling the kids dinner is ready.

If you don’t need anything as fancy as Voice Money, you could try URL Switch, which is easier to set up, and lets you call any webservice/HTTP address. I gave that a go & it worked fine, but the options in Voice Monkey give a lot more flexibility & things to play with!

Arduino IR Code Translator – Unsupported Device Control with a Fire TV Remote

[Update: As featured on Hackaday! :) ]

The Fire TV remote has a neat feature which lets you control other equipment like the TV or a soundbar. The list of manufacturers & devices it’ll control is massive.. but not all encompassing!

I bought an Edifier R1855DB (very similar to the R1850DB), and wanted to control it using the Fire TV remote.. which saves juggling 2 remotes (and the Edifier one is pretty cheap & feels like it could break at any moment!).

I soon found out that this particular Edifier model isn’t in the list of supported devices in the Fire TV equipment control feature which is really frustrating. There’s no route to get added to the Amazon list, nor does it have a ‘learn’ mode.

When I contacted Edifier they said “Our remotes use custom IR codes that can not be inputted into a universal remote”. And “information about the IR code is not open to the public”. Pretty ridiculous.

This is where I got curious about what IR codes the Edifier remote is sending out.. so I took a cheap Arduino Nano microcontroller and an IR receiver & wired them up on a breadboard. There’s an IR library with a bunch of examples, so I used the ‘IR dump’ code, uploaded it to the board & could instantly see the codes from the remote.

Capturing IR Codes

Apparently the Edifier R1855DB uses the NEC protocol, which is really common, and you can see the sequences it sends easily enough. I noted down the IR codes for each of the buttons I was interested in, and can now look at transmitting them!

You can get an IR transmitter for the Arduino .. at first I tried an IR LED from an old TV remote, but it needed a transistor to make it work properly, which I didn’t have. So I ended up buying a KY-005 IR module from eBay for £2.50.

KY-005 IR Module attached to the Arduino Nano

Hooking this up to the Arduino was simple, and I tested it was working using more example code from the IR Remote library. Finding the right format to play back the NEC codes I captured was a bit trial-and-error.. I eventually found the raw codes worked best. I actually used a Raspberry Pi with another IR receiver to validate the codes being sent were identical to the original remote.

What I can then do is have an IR receiver AND transmitter hooked up to the same Arduino and have it act as a translator between one manufacturers codes to another.

We can power the Arduino using the USB socket on the TV. This only powers up when the TV is on, which is quite handy.. and if it turns on, we can write some code to send the speaker power on IR command when the Arduino boots.

Here’s a quick wiring diagram, showing how everything is connected together;

Wiring Diagram

I didn’t have a cable long enough, so I took an old USB cable, cut it up, and soldered it into the IR transmitter so that I could place it near the Edifier IR receiver.. that was the most fiddly bit of this project.

Once I had that set up, I picked a supported device from the Fire TV equipment list – the Amazon Basics Soundbar – and dumped the IR codes for it from the Fire TV remote.

I then wrote some code to listen for the Amazon Basics Soundbar commands & emit a corresponding Edifier IR code. This worked an absolute treat after a bit of debugging. I even added a sequence detector so you can press Mute x2 then Vol Up to send the speaker power signal in case it somehow gets out of sync. Adapting the code to work with whatever equipment you have should be straightforward..

Altering the Arduino code for your equipment

You can build your own version of this for about £8, and it’s incredibly easy to put together, only requiring some basic electronics and coding skills.

Hope this has been useful.. let me know how you get on if you decide to build one of these yourself.

The GitHub repo for this project has a lot more detail & all the source code you need; https://github.com/mattcuk/IRtranslator

There’s a video of this project on YouTube if you want to see a bit more of the build process and see it working.

Installing SABnzbd on a Raspberry Pi running OSMC

For quite some time I’ve been running SABnzbd on a PC, downloading files, and then transferring them over the local network to a USB drive attached to a Raspberry Pi which is running OSMC. There’s a Linux version of SABnzbd which means I can cut out the PC and have the Pi handle the downloads. It’ll mean I can queue up the downloads from a web interface running on whatever device I have to hand, like an iPad.

First Try

The initial installation of SABnzbd was quite easy;

sudo apt-get install python-openssl unrar par2

sudo apt-get install sabnzbdplus

Edit the settings so that the web client starts up on port 8085..

sudo nano /etc/default/sabnzbdplus

USER=osmc
HOST=0.0.0.0
PORT=8085

sudo service sabnzbdplus restart

This then allowed me to connect to SABnzbd and transfer over all my settings that I was using on my PC.

Delayed Start

What I found was that SABnzbd started before the USB drive was properly mounted by OSMC, so I disabled the main service from starting up, and added a script to wait for the USB drive to get mounted at a particular path.

There was a good forum post here that pointed me in the right direction.

Disable the default service…

sudo update-rc.d sabnzbdplus disable

Write a quick shell script to wait for the directory/USB drive to be mounted…

nano /home/osmc/startsabnzb.sh

#!/bin/sh

# Wait for this folder to be mounted...
DIR=/media/Elements

while [ ! -d "$DIR" ]; do
sleep 120
done

/etc/init.d/sabnzbdplus start

chmod a+x /home/osmc/startsabnzb

Add the script to system startup…

sudo nano /etc/rc.local

/home/osmc/startsabnzb.sh

Upgrading

The version of SABnzbd that installed above was very dated. That repo doesn’t get updated very often. Here’s how I updated it to the latest version.

sudo su root

echo "deb http://ppa.launchpad.net/jcfp/nobetas/ubuntu xenial main" | tee -a /etc/apt/sources.list
echo "deb http://ppa.launchpad.net/jcfp/sab-addons/ubuntu xenial main" | tee -a /etc/apt/sources.list

apt-key adv --keyserver hkp://pool.sks-keyservers.net:11371 --recv-keys 0x98703123E0F52B2BE16D586EF13930B14BB9F05F

sudo apt-get update

Upgrading sabyenc

This solved the issue where SABnzbd was complaining that sabyenc wasn’t the right version. It uses the 2nd repo (sab-addons) we added in the steps above.

sudo apt-get install python-sabyenc

Final thoughts

SABnzbd runs quite well on the Pi. It is a lot slower than it was on a PC.. it only manages about 3 MB/s on the download on a wired connection (compared to 6 MB/s on a Wifi connection on a laptop), and unpacking is slow.

However, the files are unpacked onto the device which I was manually copying the files to anyway, so that saves time.

Automated mains socket power-off for OSMC on a Raspberry Pi

I’ve chosen to replace an ageing mini-PC which I’ve used since 2010 with a new Raspberry Pi 3 B+ running OSMC. It makes for a really capable media centre which can playback newer h.265 HEVC video files at 1080p without any problems, or it can serve 4K files over NFS to a box with a hardware h.265 chip like the Fire TV Box.

This form factor is easy to take on holiday and you can use an old infrared remote control (or Harmony learning remote) with it too.

However, the one thing I’ve struggled with is how to make it easy for my family to use in regard to switching it on and off. The Pi doesn’t have a power button. Some power supplies have an inline rocker switch, which almost fits the bill. I wanted something more automated.

Fortunately I had a spare Energenie power socket from a previous project where I use one to turn off our bass speaker when the TV isn’t on. These power sockets are controlled remotely (over RF) from a Pi which you attach an Energenie control board/shield to.

What I’ve done with the Pi 3 is have it powered through an Energenie socket, and set up a service that executes when it detects OSMC is shutting down. That service will make a quick HTTP call to the Pi with the Energenie controller shield, which will in turn send an RF signal to turn the mains socket off.

 

osmcshutdown

 

Here’s how you can set it up like I have…

Scripts for the Pi running OSMC

First, add a new service script.. create a new file in this folder;

/etc/systemd/system/callenergenie.service


[Unit]
Description=Energenie Remote Call to Secondary Pi
Before=multi-user.target
After=network.target
Conflicts=shutdown.target
[Service]
ExecStart=/bin/true
ExecStop=/bin/sh /home/osmc/callenergenie.sh
Type=oneshot
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target

Then enable it with;

sudo systemctl enable callenergenie.service

There are a couple of useful things happening in this service, the After parameter makes sure the code runs before the network code is shut down, and Conflicts parameter is looking for OSMC shutting down.

Now add a helper script… this will make the webserver call as a background task, so control will be given back to the service immediately, rather than it waiting for the wget to complete.

/home/osmc/callenergenie.sh


echo Calling energenie socket…
wget –quiet –background –output-document="callenergenie.log" "http://192.168.1.99/callenergenie.php?delay=10&switch=2&state=off&quot;
echo Sleeping for 2 seconds
sleep 2
echo Done.
exit 0

This calls the PHP script, telling it which socket to turn off, and how long to delay before sending the command, which we’re doing so that the Pi has time to shut down before the power is cut.

Scripts for the Pi with the Energenie shield

This is the PHP script I added to the other Pi which was already configured to be a PHP web server.

/var/www/html/callenergenie.php


<?php
/* MattC – Call this with various parameters..
callenergenie.php?
delay = time in seconds to sleep before calling Energenie
switch = which socket to talk to
state = turn socket on/off
e.g. callenergenie.php?delay=5&switch=2&state=off
*/
print ("Waiting ".$_GET['delay']." seconds");
sleep($_GET['delay']);
print ("Switching socket ".$_GET['switch']." ".$_GET['state']);
exec("sudo python /var/www/callenergenie.py ".$_GET['state']." ".$_GET['switch']);
?>

To allow PHP to run the script as root, I needed to add the Apache user to the list of sudo-ers.. not that secure tho :( I’d be interested in anyone who knows how to run the Energenie scripts a regular user.. their Python doesn’t like it when it’s not root.

nano /etc/sudoers

www-data ALL=(ALL) NOPASSWD:ALL

The nice thing about the PHP script is that we can actually call it to turn the Pi on remotely too.. so you could configure that into a widget on your phone, or add it to Alexa.

Adding IR Remote Control Support to the Raspberry Pi

In my last post I took you through how I created a small portable media centre that I can easily take on holiday to hook up to the hotel TV.

To reduce the amount space it took up, I used a cheap USB keypad which could be used to control the media center. It worked really well & having something hard-wired meant I didn’t have to worry about a Bluetooth-paired device needing re-pairing.

However, what I then realised was it would be good to be able to use a spare remote control instead. I was using the OpenElec distribution and looked through their documentation for how to do this, but only found references to version 3 of the software (it’s on version 7) and how to get LIRC working with it. There were plenty of blog posts on hooking up IR support, but a lot of them were written 2-3 years ago, and the software has moved on somewhat.

Hardware Setup

What I did first was buy a suitable IR receiver. I chose the Vishay TSOP4838 (which costs less than £1) because of the voltage range (2.5-5.5v) and receiver frequency (38KHz). If you look at the datasheet for the product, you’ll see which pins should get wired up to the Pi;

Simply wire pin 1 to GPIO 18, pin 2 to GND, and pin 3 to a 3.3v power pin, e.g.

By using some short F-F jumper wires and a small cut in the side of the case, I was able to position the reciever neatly(ish) on the side.. it’s still easily removable, but you could integrate it into the case a bit more seamlessly than this ;)

Software Setup

Before this project I was using OpenElec, but had limited success getting the IR support working properly. I switched to OSMC which I’d read had better IR support through the main UI. I think I was actually on the right track with OpenElec, but I realised later that the old vintage Xbox remote I was trying to use wasn’t 100% working.

If you’re going to use a remote control that’s officially recognised, then you can jump this part about learning IR remote control codes.

Learning IR remote commands

The remote I found in the loft was an old DVD player remote which (unsurprisingly) wasn’t in the list of pre-recognised remotes in the OSMC installation. I needed to get the Pi to learn the IR pulses being sent out by the remote and map them to the Kodi functions.

1. First off, you need to telnet to the Pi. Username: osmc, Password: osmc.

2. Next you need to stop the LIRC service which is being locked/used by Kodi

sudo systemctl stop lircd_helper@lirc0

3. Now you can run the IR learn mode.. this will record what it finds to the config file you specify;

irrecord -d /dev/lirc0 /home/osmc/lircd.conf

4. Follow the on-screen instructions which will recognise your remote.

One observation I had was that this only worked properly if I stopped after the first prompt to press lots of keys on the remote.. if I completed the second stage, the key mapping didn’t work, e.g.

If I ignored the second phase & let it abort, the learn process worked

When it’s working, you’ll be able to enter the Kodi function (like KEY_UP, KEY_DOWN, etc) & map it to a key press on your remote;

Once you’ve mapped all the functions you want, we then need to move back to OSMC and tell it to use that config file we’ve just written.

OSMC Settings

In OSMC you need to do the following;

1. Disable the CEC service (via System Settings > Input > Peripherals > CEC Adapter), which seems to be needed for LIRC to work.

2. Now go into OSMC settings and pick the Raspberry Pi icon

3. Go into Hardware Support and enabled LIRC GPIO Support. You shouldn’t need to change anything if you connected the sensor to GPIO 18.

4. Now go back and select the Remote Control option.

5. Ignore the list of pre-installed remotes and select Browse;

6. Navigate to the folder where LIRC wrote your config file;

7. Confirm the change & reboot the box;

That should be it.. your remote should be able to control everything in Kodi.

Raspberry Pi Heating Controller – Part 2 – Software Architecture

One of the early design decisions for the Raspberry Pi powered heating controller was to have the Pi secured behind a firewall without direct access to it from the Internet. What I decided to do was have a set of simple PHP web pages on a remote web host that you can access from anywhere, and the Pi control server talks to that web host to send/receive data.

What I didn’t want was for the Pi to run a web server that ends up getting compromised & having the run of my home network.

arch-mode1
The Pi server and remote webspace need to be paired with an access key. Anyone accessing the remote site needs the correct access key to be able to control the system.. and the level of control is limited by the API we’ll put in place.. i.e. remote clients won’t have direct access to your internal network via an open port on your home router.

Of course, you could actually host the ‘remote’ part of this set up on your Pi and use port forwarding; the architecture allows for both types of access. The access key is still needed to control the system, but you’ll be more vulnerable to attacks on your Apache/PHP installation & need to keep up-to-date with software patches to help ensure your system is secure.

arch-mode2

Home Automation Project – Raspberry Pi Heating Controller – Part 1

pi-controlI’m going to build a home automation project which connects a Raspberry Pi to control my central heating. I wasn’t particularly happy ripping out all the existing controls, and wanted to piggyback onto them.. which helps if the Pi ever fails (I’ve still got the old controls to fall back on).

I also didn’t want to mess with the existing heating control board, so bought a duplicate unit (British Gas UP2) from eBay for about £12.. I can perfect the project on that, and install it when I’m ready.

This set of videos goes through each step of the project.. starting off with opening the control board, an overview of what I want to do, and testing out the changes.

Opening up the Control Panel

This was a bit tricky.. it wasn’t quite obvious which plastic clips needed pushing in to pull the board out.. if you were doing this on your actual panel (not an eBay-bought duplicate) then this video should help work out what you need to do to get into it without damaging anything.

 

Project Overview

Next up, I’ll quickly go over what I intend to do to piggyback onto the control board. There’s a project here which did exactly what I wanted to do. He’s not using a PiFace 2 like I intend to use, and he wants to be able to control the hot water as well, but everything else is the same.

 

Safety First – Masking off the High Voltage Area

In this second video, I’ll show how I’m masking off the high voltage area of the board to make it a bit safer when I’m testing things out. Obviously most of the time the board is off, but this helps keep things safer when it is on without the cover.

 

Identifying Solder Points

Luckily this blog gave me a good starting point, but it wasn’t clear where to get the status of the central heating.. I used a multimeter to find a spot which changed voltage when the system was on, and this diagram shows you what I found;

pi-heat-3

Soldering

Since I only needed 4 wires for this project (2 for the switch, and 2 for the system state), I took an old USB cable, cut the ends off, stripped the wires and soldered it to the board without much trouble.

pi-solder

Soldering Complete!

This shows the control board after the soldering has been completed.. it’s pretty simple soldering; the only tricky part was finding the points to connect to for the system state (on/off). I’ve stuck down some of the wires so that they don’t catch or get stuck underneath the control boards buttons.

 

Testing the Wiring

Now that I’ve done the soldering, I’m testing out the wiring.. seeing whether connecting the two wires for the switch turns the central heating on, and when it is on, whether we get voltage on the other two wires to indicate the system state.

 

Controlling from Software

I’ve now hooked it up to the Pi Face 2 board, which can be controlled with a few lines of Python to simulate a button press, and detect the state of the system.

With these basics in place, the rest of the control software can be written to do scheduling, bring in temperature readings, and allow the system to be controlled remotely.

Controlling Power Sockets using a Raspberry Pi

The subwoofer we had in our home cinema setup died a few weeks ago, so I did my research and found a nice replacement. The only thing I didn’t spot was the fact it never goes into standby if there’s no signal (unlike the old one). I tried using some eco plugs which turn off peripherals when the TV was turned off.. but it learns the TV remote signals, and completely turns the TV off as well.. meaning that you have to hit the power button twice to turn the TV back on; that doesn’t work well with the Harmony all-in-one remote we use.

What I decided to do was buy an Energenie socket, which can be switched on/off wirelessly from a Raspberry Pi. The kit comes with 2 sockets and a transmitter to attach to the GPIO headers on the Pi, and costs about £20.

In my subwoofer scenario I basically want it switched on when the TV is on, and off when the TV is off. The TV has a Chromecast plugged into it which is visible on my local network. If you’ve got a Smart TV on your network, maybe that’ll be visible in the same way. So when the TV/Chromecast appear on the network, we know to switch on the power socket.

energeniesockets

Here’s the small Energenie transmitter attached to the GPIO headers on my B+.. it’s pretty tiny and the case I’ve got still fits over the top. Notice the small hole where you can attach an aerial.. if you want extra range, then you’ll need to solder one on.. I added a 135mm wire, since the range I got out of it just wasn’t enough to get from the dining room cupboard to the living room.

energeniepi

 

To put this together, we can use the Raspberry Pi Network Spy code I wrote in my previous blog posts on element14;

Raspberry Pi Network Spy – Part 1 – Initial Setup + d/b Schema
Raspberry Pi Network Spy – Part 2 – D/b Setup + PHP for the scanner

All we need is a new PHP page that’ll call one of the functions we’ve already written.. we need a list of the MAC addresses that are currently visible on the network, then check whether the Chromecast is there. Once we know whether the TV/Chromecast is on or off, we then call a Python script that will turn the Energenie socket on/off.

Here’s the PHP;

arp-chromecast.php

The Python script could follow the Energenie example script, but there’s actually an even more simple Python package which I’ve used in this project. To install it I did the following;

sudo apt-get install python-pip
sudo pip install energenie

Then I wrote this helper Python script (which we’ll call from PHP) that accepts a couple of parameters, like this callenergenie.py [on|off] [switch_number];

callenergenie.py

from energenie import switch_on, switch_off
import sys

if len(sys.argv)==1:
print ‘Please specify arguments like this callenergenie.py [on|off] [switch_number]’
print ‘eg. callenergenie.py on 1’
print ‘eg. callenergenie.py off 2′
else:
on_or_off = sys.argv[1]
which_switch = int(sys.argv[2])

if (on_or_off==’on’):
print ‘Switching on ‘, which_switch
switch_on(which_switch)

if (on_or_off==’off’):
print ‘Switching off ‘, which_switch
switch_off(which_switch)

Now that we’ve written the PHP & Python, all we need to do is run the PHP every minute to scan the network and do the switching. We’ll do this using another cron job;

crontab -e

*/1 * * * * sudo /usr/bin/php /var/www/arp-chromecast.php

 

Project Mentions

This project of mine has been included in PC Pro magazine, and on one of my favourite tech podcasts, TekThing (at 22min 40sec in the video below)!