Applescript App to Install RemoteHD on 1st-gen AppleTV

Occasionally people ask about a simple way to install RemoteHD on their first-gen AppleTVs without having to run any terminal commands. For those with access to a Mac I created a simple AppleScript app that ssh’s into the AppleTV and does the job for you. You can download it below but for those interested in learning a little bit about how it works read on…

The 2 Parts
The app is broken down into 2 simple parts – the Applescript script, which handles the GUI side of things, and a separate expect shell script that does the dirty work.  Both are accessible via ctrl-clicking the app and choosing to “Show Package Contents”.   The files in question are under Contents/Resources/Scripts.

main.scpt

main.scpt is the Applescript part.  It contains the following code:

# List of variables that could need localization
set appletvAddress to "appletv.local"
set appletvUsername to "frontrow"
set appletvPassword to "frontrow"
set dialogPrefix to ""

# Output a dialog to get the AppleTV's network address
repeat
	display dialog dialogPrefix & "What is your AppleTV's broadcast address or IP?  The default usually works.  If there's a problem get your AppleTV's IP Address from General/About and enter that here..." default answer appletvAddress
	set appletvAddress to text returned of result
	try
		if appletvAddress = "" then error
		exit repeat
	on error
		set dialogPrefix to "YOU NEED TO ENTER SOMETHING! "
	end try
end repeat

# Output a dialog to get the AppleTV's default username
set dialogPrefix to ""
repeat
	display dialog dialogPrefix & "What is your AppleTV's default username? Unless you changed it the default is likely correct..." default answer appletvUsername
	set appletvUsername to text returned of result
	try
		if appletvUsername = "" then error
		exit repeat
	on error
		set dialogPrefix to "YOU NEED TO ENTER SOMETHING! "
	end try
end repeat

# Output a dialog to get the AppleTV's default password
set dialogPrefix to ""
repeat
	display dialog dialogPrefix & "What is that user's password? Unless you changed it the default is likely correct..." buttons {"Cancel", "Install RemoteHD"} default button "Install RemoteHD" default answer appletvPassword
	set appletvPassword to text returned of result
	try
		if appletvPassword = "" then error
		exit repeat
	on error
		set dialogPrefix to "YOU NEED TO ENTER SOMETHING! "
	end try
end repeat

# get full path to the script
set myScript to POSIX path of (path to resource "remotehdinstall.scp" in directory "Scripts")

# try running the script and output if there was an error
set isError to "false"
try
	do shell script myScript & space & appletvAddress & space & appletvUsername & space & appletvPassword
on error
	display dialog "There was an error.  Are you sure that address was right?" buttons {"Quit"} default button 1
	set isError to "true"
end try
if isError = "false" then display dialog "Looks like it worked!  Enjoy!" buttons {"Done!"} default button 1

Here’s a basic description of what we’re doing:

First we have a few variables to deal with.  We know that it’s possible that the typical network multicast address of an appletv, appletv.local, to not be accessible or correct.  For instance, if multicast is blocked on the network you won’t see appletv.local, and if you have multiple Apple TVs you may have appletv.local, appletv-2.local, appletv-3.local, etc.  So we need to be able to change that option.

It’s also possible to change the username and password from ‘frontrow’, though it’s not a common thing to do and it’s not really a good idea either as it will cause a number of issues with built-in software (if you’re worried about security it would be much better to control access to the unit via your network’s access controls/firewall).  So we want to give the option to change this as well.

The dialogPrefix variable is simply for error messages if someone leaves an option blank.  We don’t do any other validation of the entered values (as there’s really no risk to getting it wrong – it simply won’t work and will give an error).

We then have 3 GUI dialogs asking for input from the user to get the address, username and password, respectively.  We set the default answer to the values of the variables defined earlier.

Then we get to the actual meat-and-potatoes of this script.  First, in order to run the shell script that will do the bulk of the work we need to know exactly where it is.   That path changes depending on where you save RemoteHDInstaller.app.  For instance, if you have it on your desktop the script file will be located at /Users/YourUserName/Desktop/RemoteHDInstaller.app/Contents/Resources/Scripts/remotehdinstall.scp  But if you have it in the root directory it will be at /RemoteHDInstaller.app/Contents/Resources/Scripts/remotehdinstall.scp  So we need the proper path to be able to run the script.  To get that path we create another variable, myScript, and set it’s value to the POSIX path (POSIX path will use the common slash ‘/’ path address, which we need) of the script, which we know is in the Scripts subdirectory of resources, ergo path to resource “remotehdinstall.scp” in directory “Scripts”.

We then want to run the shell script and pass the values that we received from user input.  But if we simply perform a do shell script command we will get no warning if there’s an error.  There are a number of ways of dealing with this issue, but I chose the simplest – a try/on error loop.

First, we create a variable called isError and set it to “false”.  We try to run the shell script (appending the variables with spaces in between after the script path) and if there’s an error we pop up a simple output telling us that and giving us a button to quit the program. If there isn’t an error we output a message saying it seems to have worked.  Simple!

remotehdinstall.scp

Next we have the expect script.  This does the work of ssh’ing to the AppleTV and executing the commands.  The code is below:


#!/usr/bin/expect

# set passed variables

set address [lindex $argv 0]

set username [lindex $argv 1]

set password [lindex $argv 2]

# ssh to AppleTV

spawn ssh -l $username $address

# set infinite timeout for expect so it doesn't stop during download

set timeout -1

# run through necessary commands (note: frontrow is sent as a password to ssh.remotehd.com as that's what they're expecting)

expect "*?ssword:*"

send -- "$password\r"

expect "*?2.05b$*"

send -- "sudo mount -uw /\r"

expect "*?ssword:*"

send -- "$password\r"

expect "*?2.05b$*"

send -- "scp ssh.remotehd.com:RemoteHelper.tar .\r"

expect "*?ssword:*"

send -- "frontrow\r"

expect "*?2.05b$*"

send -- "tar xvf RemoteHelper.tar\r"

expect "*?2.05b$*"

send "./install-RemoteHelper\r"

expect "*?2.05b$*"

exit 0

ssh is a real pain to script for if you don’t have keys set up, which we assume the users in this case don’t.  There’s no simple way to pass the password through a bash script, so the only way I’ve found to deal with the problem is by using an expect script.  It works, but isn’t as elegant as one might prefer.

What we’re doing is fairly simple:  First, we set the passed values to variable names.  Then we spawn an ssh session using the passed username & address.  Then, before starting any expect statements, we set the timeout to infinite.  By default expect has a timeout of something like 30 seconds, which may or may not be long enough for the download to complete.  Setting it to infinite fixes this.

The rest of the code is straight forward.  We expect to be asked for the password and we supply it.  We expect the default AppleTV prompt (2.05b$) and then start issuing commands.  The scp command wants a password of frontrow so we hard-coded that in there.  It then finishes up the rest of the commands and exits out.

Putting it together

That’s it.  A simple script to make things easier for those who find command-line work intimidating.  Hopefully this will help some others who have a similar need.

For those looking for the script itself you can download it below. Simply unzip and double-click.

RemoteHDInstaller