Making smart devices actually smart!

This all started a couple of years ago when I received a very large unexpected electricity bill. Around a year before this I had a new heating system installed which included an electric flow boiler to replace the old electric storage type.

12kW of money sucking horror

I knew this thing was going to cost more to run because it draws power whenever the heating is set to on but perhaps slightly foolishly, I did not pay much attention to the electricity consumption and being on a fixed-rate tariff, nothing much happened… at first.
After the shocker of a bill arrived (and I set up a new plan with the electric supplier) I was determined to reduce my overall consumption, and of course I wanted to use technology to assist with this.

Standard programmable timer

 

 

 

 

My heating system was installed with a programmable timer only. Typically it was set to heat in the morning until I left for work and then again in the evening until bedtime. At the weekend the heating could potentially be on all day long. The place was comfortable but there was a huge amount of waste because variable conditions were not taken into account such as; the weather, internal temperature and if I was even at home.
The most obvious improvement was to replace the timer with a programmable thermostat or supplement the timer with a thermostat. I decided this should be a smart thermostat and settled on the Nest.

Nest Heatlink, replaces timer on mains controlled boilers, typical in the UK

Nest Thermostat

Installation was easy and the thing looks really nice! It is billed as a “learning thermostat” which basically means instead of manually setting times to switch the heating on and off, it learns from your manual control to build up a schedule and begins to factor in other variables such as the weather and how long it takes to heat your house to the desired temperature. So, on the first few days I would get up in the morning and the place was cold, ok that’s fine, it hasn’t yet learned my patterns. After two or three days of manually setting the desired temperature it began switching on before I got up with the place at the correct temperature. Great! It should also detect when you have left the building and switch the system off, however, I found this rather inconsistent, often taking two or three hours to realise I was gone. Not so good. But the worst problem was coming home from work in the evening in winter. The Nest simply will not switch itself on while there is no-one home to preheat. I wasn’t happy with this.

Step up: Home Assistant

My heating section in Home Assistant

This is a piece of software that runs on a Raspberry Pi or PC which essentially gives an interface between different types/manufacturers of smart devices. It can also automate things like switching lights on and off, notify you of things happening like someone ringing your smart doorbell when you’re not home and control unsupported devices with Alexa or Google Home. Many non-smart devices can also be programmed in making its use limited only by one’s imagination.
After a bit of research it transpired that if I was to install an app on my phone which uses GPS to report my real world physical location back to Home Assistant I could this this to control my heating.

A little background: typically I work in the same location every day, however, as a support engineer I am sent around the country which means my return time in the evening can be unpredictable. I finished work at 5.15pm and it usually takes me about 25 minutes to get home but sometimes this can be A LOT longer.

Tracking my location

Now I have Home Assistant running on a computer at home which is able to control the Nest thermostat and an app on my phone sending location data back to Home Assistant. Great. But we still need to calculate the time it will take me to get home. I’m sure we have all used Google Maps at some point to get directions and an idea of how long a journey will take, well this can be used programmatically from Home Assistant with the location data. One of the best parts of Google’s journey time is is also factors in live traffic conditions!

So, here’s what happens on a weekday evening:

  1. At 4.45pm Home Assistant checks my journey time to home
  2. If the journey time is less than 45 minutes, set the Nest to Heat at 21°C, or
  3. If more than 45 minutes, wait until the journey time decreases to 45 minutes, then set the Nest to Heat mode at 21°C , or
  4. If by 6.30pm the journey time is still above 45 minutes, abort (and send a message to my phone for manual intervention)

And that is the basis of my smart controlled heating system. It’s not quite foolproof, for example, if I don’t head straight home or if I’m working late in my usual office it will come on early and stay on. These are scenarios I’m working towards resolving but they happen so infrequently it’s not a big deal to me.
There are other bits and pieces it does to save energy, such as; it will only switch on in the morning if I’m actually at home and turns itself on or off automatically as I leave and return home, within minutes. Less energy conscious actions it performs are boost the temperature if it is very cold outside late in the evening and only switch off in the evening when the main living rooms are vacated, i.e. I’ve gone to bed!

I’ll go into the technical details in another post but hopefully this will illustrate that smart devices can indeed be very useful while saving energy but still require some thought, effort and skill to be used effectively. Perhaps in a few years when the technology has matured we will see this sort of control as standard.

Ubuntu Hyper-V Guest Console Resolution

Changing the Ubuntu console resolution when running as a Guest OS in Hyper-V can be a bit of a pain. Here’s how to do it in Ubuntu 14 – 16:

  1. Open Terminal if you are in your desktop environment
  2. Type
    sudo nano /etc/default/grub
  3. Look for the line
    GRUB_CMDLINE_LINUX_DEFAULT=""
    and append:
    video=hyperv_fb:(your_resolution_here)
    so that it looks something like:
    GRUB_CMDLINE_LINUX_DEFAULT="video=hyperv_fb:1024x768"
  4. Uncomment the line
    #GRUB_GFXMODE=
    and append your desired resolution with colour depth:
    1024x768x32
    So that it looks like:
    GRUB_GFXMODE=1024x768x32
    Note: there are no quote marks on this line.
  5. Immediately below
    GRUB_GFXMODE
    add a new line:
    GRUB_GFXPAYLOAD=1024x768x32
  6. Exit nano and save the file
  7. Now the important part is to update your GRUB configuration. Type:
    sudo update-grub
  8. Reboot the VM

At this point it wouldn’t be a bad idea to install the Hyper-V Integration Services for Linux.

  1. At the terminal type:
    sudo nano /etc/initramfs-tools/modules
  2. Add the following modules at the end of the file:

    hv_blkvsc
    hv_netvsc
    hv_storvsc
    hv_vmbus

  3. Save and exit the file.
  4. Next install the actual Integration Services packages by issuing the following commands:
    sudo apt-get install --install-recommends linux-tools-virtual-lts-xenial linux-cloud-tools-virtual-lts-xenial
  5. Then:
    update-initramfs -u
  6. Finally, reboot the VM once again.

Android Phones – Bulk Configuration

Recently I was tasked with configuring 27 Android smart phones for various people spread across the country. These phones were a mixture between Samsung Galaxy A3’s, A3 2006 version, S6 and S7 Edge models all supplied by EE.
Rather than hand out these phones un-configured and expect the users to set them up themselves I took it upon myself to have them as ready as possible. This involved removing or hiding the pre-installed bloatware and installing a few extra apps.

To do this on the cheap (read: free) you will need:

  • The Android Debug Bridge (ADB) from here.
  • Drivers for your phone. As we’ll have the phone in debug mode the normal Windows drivers aren’t enough. Google’s OEM device driver list.
  • A method of gaining the .apk file for the apps you want to install. An existing Android phone with an app backup app or a website such as APK Mirror will do.
  • A batch file you can run quickly and easily for each phone which I’ll go into later.

Next:

  1. Run through the phone’s initial configuration wizard. I skipped everything apart from joining the wifi.
  2. Make sure the phone is running the latest firmware version.
  3. Enable Developer Options by tapping repeatedly on the “Build Number” option under “About phone”.
  4. Turn on USB Debugging in the Developer Options menu, connect the phone to your computer and trust the device.

Now, open a command prompt and type: adb devices and you should get the phone’s serial number with “device” beside it. This means adb is working properly, if you don’t get anything listed check you’ve got the drivers installed properly. It’s always the drivers :).

adbdevices

Now we can start doing the fun stuff!

adb shell pm list packages -f

Lists all of the packages and their associated file. There will be masses of stuff here and may be truncated so you can output the results to a text file for easy searching:

adb shell pm list packages -f > packages.txt

In my case I wanted to uninstall various apps but unfortunately as carriers bake apps into their ROMs they can only be disabled/hidden. This has the effect of hiding the icon from the app drawer so your users should be none the wiser.
Once you’ve found the package’s name you can do the following:

adb shell pm hide com.facebook.katana

Which will hide the Facebook app.
Make a list of each package you want to hide but be careful not to hide any system packages as this can cause problems. Something to note here is that if you specify a package that does not exist or make a spelling mistake it will still return “hidden: true” so make sure it really is hidden!

Next, grab the .apk files of the apps you want to install. ADB should be in your environment path variable, otherwise put the apk’s in the folder beside ADB.

adb install AdobeAcrobat_16.2.apk

Will install Adobe Acrobat.

You can use: adb push file.ext /mnt/sdcard/directory/file.ext to copy files to the phone. I used this to copy our corporate branded wallpaper.

Finally, compile all the bits and pieces together into a simple Windows batch file, as below:

@ECHO OFF
adb devices
pause
REM This gives you a chance to ensure the phone
REM is properly detected and quit if not.

adb shell pm hide uk.co.ee.myee
adb shell pm hide com.amazon.mp3
adb shell pm hide com.dropbox.android
adb shell pm hide com.facebook.katana
adb shell pm hide com.instagram.android
adb shell pm hide com.amazon.kindle
adb shell pm hide com.lookout
adb shell pm hide uk.amazon.mShop.android
adb shell pm hide com.microsoft.skydrive
adb shell pm hide com.samsunguk.mygalaxy
adb shell pm hide com.sec.android.widgetapp.samsungapps
ECHO Bloatware hidden

adb install AdobeAcrobat_16.2.apk
adb install Excel_16.0.7127.1010.apk
adb install Outlook_2.1.43.apk
adb install Word_16.0.7127.1010.apk

adb push wallpaper.jpg /mnt/sdcard/directory/wallpaper.jpg

adb reboot

So there you go. It’s not elegant and still requires some manual intervention but it should save you a fair bit of time.

Windows Server Backup Checker PowerShell Script

This PowerShell script was written with the intention of automating the manual checking of Windows Server Backup on 10 or so physical Windows servers running Server 2012 and 2008 scattered across the country. Generally these backups run without issue so I decided it would be best to be alerted only to failures while keeping a log of every outcome.

The script will take a list of server names in two plain text files; one for servers running Windows Server 2012 and the other for those running 2008, aptly named 2012servers.txt and 2008servers.txt. It will then run the Get-WBSummary cmdlet against each of the servers in the text files and check the contents of LastBackupResultHR. 0 is a successful backup and anything else is a failure of some sort. If a failure is spotted the script will then email these results along with the error description (which may or may not be helpful) and the server’s name. A .csv is created and each outcome is appended to this log.

# Backup checker script
# Ross Sutherland 2016

$2012servers = Get-Content 2012servers.txt
$2008servers = Get-Content 2008servers.txt

$emailSMTP = "smtp.your.domain.com" 
$emailTo = "Your Name <your.name@your.domain.com>" 
$emailFrom = "Backup Admin <backups@your.domain.com>" 
$emailSubject = "Backup report"

foreach($2012server in $2012servers){    
        $backupResults = Invoke-Command -ScriptBlock { Get-WBSummary } -ComputerName $2012server -ErrorAction SilentlyContinue
        $backupResults | Export-Csv -Path .\$($2012server)_backuplog.csv -Append
    if($backupResults -eq $null){
        Write-Host "Something went wrong while retreiving backup summary from $2012server :(" -BackgroundColor Yellow -ForegroundColor Red
    }else{
        if($backupResults.LastBackupResultHR -ne 0){
            Write-Host "Backup on $($backupResults.PSComputerName) failed :(" -ForegroundColor Red
            Send-MailMessage -SmtpServer $emailSMTP -To $emailTo -From $emailFrom -Subject $emailSubject -Body `
            "Backup on $($backupResults.PSComputerName) failed with error: $($backupResults.DetailedMessage)" -BodyAsHtml -Priority high
        }else{
            Write-Host "Backup on $($backupResults.PSComputerName) completed successfully on $($backupResults.LastSuccessfulBackupTime) :)" -ForegroundColor Green
        }
    }
}

foreach($2008server in $2008servers){    
        $backupResults = Invoke-Command -ScriptBlock { add-pssnapin windows.serverbackup; Get-WBSummary } -ComputerName $2008server -ErrorAction SilentlyContinue
        $backupResults | Export-Csv -Path .\$($2008server)_backuplog.csv -Append
    if($backupResults -eq $null){
        Write-Host "Something went wrong while retreiving backup summary from $2008server :(" -BackgroundColor Yellow -ForegroundColor Red
    }else{
        if($backupResults.LastBackupResultHR -ne 0){
            Write-Host "Backup on $($backupResults.PSComputerName) failed :(" -ForegroundColor Red
            Send-MailMessage -SmtpServer $emailSMTP -To $emailTo -From $emailFrom -Subject $emailSubject -Body `
            "Backup on $($backupResults.PSComputerName) failed with error: $($backupResults.DetailedMessage)" -BodyAsHtml -Priority high
        }else{
            Write-Host "Backup on $($backupResults.PSComputerName) completed successfully on $($backupResults.LastSuccessfulBackupTime) :)" -ForegroundColor Green
        }
    }
}

As you can see the script essentially runs twice for each version of Windows Server. This is simply because the windows.serverbackup snappin must be loaded on Server 2008 for the Get-WBSummary cmdlet to run but loading this snappin on 2012 throws an error. There might be a nice way of having PowerShell detect the version of Windows the server is running before issuing the command but that’s a little beyond me at this stage.

backup_email

Backup failure sample email

If you’d like to run this in your own environment you must have the following:

  • An SMTP server to relay through (without authentication)
  • Permissions to administer backups

Ideas for improvement:

  • Ability to email through secure SMTP servers
  • Better error handling if Get-WBSummary fails
  • Rotate the log file after a certain amount of time or when it reaches a certain size
  • Detect the Windows version and run the appropriate command