Turn on/off any PC with an ATX PSU and InfraRed remote

My HTPC has/had a CIR which allowed me to turn it on via my Harmony remote, but one day it stopped working and my attempts to fix it totally broke it.
So my 1st idea was I'll buy a new CIR device, but I couldn't find any.
My 2nd idea was get a new Motherboard, but that meant new CPU (Skylake i7-6700k) + RAM (DDR4) bcos there's no point getting a new Mobo if your not getting the latest and greatest, and I couldn't find any which turned on via IR.
My 3rd idea was build something :), this turned out to be ridiculously easy.

What would I need? Some way of automating pressing the button for 2 seconds, bcos that turns the PC on and off, and something to accept an IR signal.
I knew ATX PSU's have a 5v standby power supply, so IR relay would need to operate on 5v.

A quick google didn't help, so I went to Alibaba and found exactly what I was looking for, a 5v IR relay with timer function. I then went to eBay bcos I prefer the buying experience. Found the same 5v Programmable relay for $5 how awesome is that!?
3 weeks later it arrives and I proceed to install it. 

  1. Test relay to ensure it works.
  2. Program your universal IR remote unless you want to use the included one. My Harmony Elite had a really hard time learning the IR command, and even when it did it wouldn't work the 1st time, but it eventually learnt the command.
  3. Set relay time to 2 seconds, shorter will turn it on, but may not turn it off. 4 seconds will force a power cut.
  4. If required extend the infrared phototransistor, black shiny thing with 3 pins. I extended mine by 30cm to have it sit outside the case.
  5. Either find 5v on a motherboard USB pin header (I used the USB2 header as pictured and I had to enable Asmedia USB 3.1 battery in the BIOS to have 5v constantly supplied to the relay) or get it directly from the ATX connector.
  6. Supply 5v to the IR relay power input.
  7. Run 2 wires from relay output NO (normally open) + COM to the Power Switch pins on your motherboard front panel pins.
  8. T join the case front panel power switch to the Power Switch pins on your motherboard or join them on the relay (pictured) so you can still use the normal power switch.
  9. Test. Apart from the Harmony learning command issue, it has worked flawlessly for the past 2 weeks (update: +2 years) and I like that it turns off instead of the Alt+F4 I used to do. I even use an Amazon Echo + Harmony to voice control it with; Alexa, turn PC on/off.
Relay with extended phototransistor

T/Y join of front panel I/O + Relay NC/COM

The relay on top of the PSU in the case


Microsoft SharePoint (Unreleased) for Android.

Some of us can't stand iOS but there's no denying it's the primary mobile platform and it has a SharePoint. Microsoft's just released an early access version of the Andoird app on the Play Store.
The SharePoint app includes all the things you'd expect to find - managing team sites, document storage, Office 365 integration, and collaboration features with other team members. Documents can be edited with the Office Mobile apps (Word, Excel, PowerPoint, and OneNote), making for easy updating on your Android phone or tablet. The app is powered by Microsoft Graph, which "makes it faster to get to content and people you work with".

 Microsoft SharePoint (Unreleased)- screenshot thumbnail   Microsoft SharePoint (Unreleased)- screenshot thumbnail   Microsoft SharePoint (Unreleased)- screenshot thumbnail   Microsoft SharePoint (Unreleased)- screenshot thumbnail   Microsoft SharePoint (Unreleased)- screenshot thumbnail   Microsoft SharePoint (Unreleased)- screenshot thumbnail


PowerShell function to create Azure ARM VM with Public IP

This function is intended to reside within the logic of a larger script for deploying an entire resource group. The function should ideally be fed from a JSON or XML configuration file.
It takes a whole bunch of inputs relating to Azure VMs and provisions a VM within a resource group and VNet with a public IP. The Network Security Group settings need to be amended as required.
I've extracted some of the required variables, but these could also be passed as parameters.

[string]$resGroup = "IIOS" [string]$location = "australiaeast" [int]$script:ipStart = 4 [string]$saName = $($saName -creplace '[^a-zA-Z0-9]','').ToLower() [string]$vnName = $($resGroup +"-vNet1") function Create_VMRole([string]$vmName, [string]$vmSize, [string]$vmDesc, [int]$dataDiskSize, [string]$PublisherName, [string]$Offer, [string]$Skus) { while(($vmName.length -gt 15) -or !$vmName){ Write-Host "Virtual Machine Name '$vmName' is too long or empty" "Yellow" [string]$vmName = read-host "Please enter a valid Virtual Machine Name..." Write-Host "`nYou entered '$vmName'`n" "Yellow" } Write-Host "[CREATING] $vmDesc Virtual Machine '$vmName'" $vmAvailabilitySet = $($vmName +"AvailabilitySet") if(!($vmSet = Get-AzureRMAvailabilitySet -Name $vmAvailabilitySet -ResourceGroupName $resGroup)) { Write-Host "[CREATING] AvailabilitySet '$vmAvailabilitySet' for $vmDesc Virtual Machine '$vmName'" $vmSet = New-AzureRMAvailabilitySet -Name $vmAvailabilitySet -ResourceGroupName $resGroup -Location $location } $vnet = Get-AzureRMVirtualNetwork -Name $vnName -ResourceGroupName $resGroup Write-Host "[CREATING] PublicIpAddress for '$vmName'" $pip = New-AzureRMPublicIpAddress -Name $($vmName +"-PublicIP1") -ResourceGroupName $resGroup -Location $location -AllocationMethod Dynamic $nicIP = $("10.0.0." + $script:ipStart++) Write-Host "[CREATING] NetworkInterface with PrivateIP '$nicIP' for '$vmName'" $nic = New-AzureRMNetworkInterface -Name $($vmName +"-NIC1") -ResourceGroupName $resGroup -Location $location -SubnetId $vnet.Subnets[0].Id -PublicIpAddressId $pip.Id -PrivateIpAddress $nicIP $vm = New-AzureRMVMConfig -VMName $vmName -VMSize $vmSize -AvailabilitySetId $vmSet.Id $storageAcc = Get-AzureRMStorageAccount -ResourceGroupName $resGroup -Name $saName if($dataDiskSize -gt 0) { $vhdURI = $($storageAcc.PrimaryEndpoints.Blob.ToString() + "vhds/" + $vnName +"-"+ $vmName +"-Data1.vhd") Add-AzureRMVMDataDisk -VM $vm -Name "Data1" -DiskSizeInGB $dataDiskSize -VhdUri $vhdURI -CreateOption empty } $vm = Set-AzureRMVMOperatingSystem -VM $vm -Windows -ComputerName $vmName -Credential $vmCred -ProvisionVMAgent -EnableAutoUpdate #-TimeZone $TimeZone $vm = Set-AzureRMVMSourceImage -VM $vm -PublisherName $PublisherName -Offer $Offer -Skus $Skus -Version "latest" $vm = Add-AzureRMVMNetworkInterface -VM $vm -Id $nic.Id $osDiskUri = $($storageAcc.PrimaryEndpoints.Blob.ToString() + "vhds/" + $vnName +"-"+ $vmName +"-System.vhd") $vm = Set-AzureRMVMOSDisk -VM $vm -Name "System" -VhdUri $osDiskUri -CreateOption fromImage $newVM = New-AzureRMVM -ResourceGroupName $resGroup -Location $location -VM $vm return $newVM } Example usage: Create_VMRole "dbVM1" "Standard_D3_V2" "SQL Server Primary" 300 "MicrosoftSQLServer" "SQL2014SP1-WS2012R2" "Standard"


PowerShell function to Get Term from SharePoint Term Store

Very useful if you're updating taxonomy fields.
Takes 3 inputs; the Site URL, the Taxonomy field object and the Term string.
The function gets a reference to the site's term store and then executes the GetTerm method, (more info here: TermSet.GetTerms) and finally return a Term object.

function GetTerm([string]$siteUrl, [Microsoft.SharePoint.Taxonomy.TaxonomyField]$oField, [string]$termStr) { if(!$oField.IsTermSetValid) { Write-Host "[ERROR] $($oField.Title) IsTermSetValid is FALSE" return $null; } $taxonomySession = Get-SPTaxonomySession -Site $siteUrl; if(($taxonomySession -eq $null) -or ($taxonomySession -eq $null)) { Write-Host "[ERROR] Taxonomy Session is null, Metadata Service App Proxy default storage location for column specific term sets is CHECKED and the user account has access" return $null } $oTermStore = $taxonomySession.DefaultSiteCollectionTermStore; if($oTermStore -eq $null) { $oTermStore = $taxonomySession.TermStores[0]; } if($oTermStore -eq $null) { Write-Host "[ERROR] Unable to get a valid Term Store.`nEnsure $(whoami) is a Term Store administrator.`nEnsure the Managed Metadata Service Proxy property 'This service application is the default storage location for column specific term sets.' is checked." Red exit } $oTermSet = $oTermStore.GetTermSet($oField.TermSetId); [System.Guid]$gTermId = $oField.AnchorId; [int]$LCID = 1033; if(($gTermId.ToString() -eq "00000000-0000-0000-0000-000000000000") -or ($gTermId -eq $null)) { $oTerm = $oTermSet.GetTerms($termStr, $LCID, $true)[0]; if($oTerm -eq $null) { Write-Host "[ERROR] Term value: $termStr not found in TermSet $($oTermSet.Name)" Red } } else { $oAnchorTerm = $oTermSet.GetTerm($gTermId); $oTerm = $oAnchorTerm.Terms[$termStr]; if($oTerm -eq $null) { Write-Host "[ERROR] Term value: $termStr not found in $($oTermSet.Name);$($oAnchorTerm.GetPath())" Red } } return $oTerm }
Below is an example of how to use the function and the returned Term object to set the default value for a field.

$oField = $oWeb.Fields.GetField("Document Type") $oTerm = GetTerm $oWeb.Site.Url $oField "Proposal" if($oTerm -ne $null) { $taxonomyValue = New-Object Microsoft.SharePoint.Taxonomy.TaxonomyFieldValue($oField); $taxonomyValue.TermGuid = $oTerm.Id.ToString(); $taxonomyValue.Label = $oTerm.Name; $oField.DefaultValue = $taxonomyValue.ValidatedString; $oField.PushChangesToLists = $true $oField.Update($true) Write-Host "Setting Default Value $($oField.TypeAsString):$($oField.Title) : '$($taxonomyValue.ValidatedString)'" Yellow }