AppleScript Snippits

This page is intended to provide a library of Indigo related AppleScript handlers (functions), hints, algorithms and other ideas to help you with your AppleScripting projects. Send submissions to berkinet (via PM) on the Indigo Forum.


  • Make sure only one instance of an AppleScript is running at a time.

The following code accomplishes the goal quite simply. If the script is already running, the new instantiation will push the count over 1, the script tells Indigo, and quits. By logically ANDing “osascript” and the script name this should avoid false hits. You could, of course, use Indigo or Perceptive as well.

set myName to "myTest.scpt" 
set procCount to do shell script "ps axww|grep -e \"osascript.*" & myName & "\"|grep -v grep|wc -l" 

if procCount as integer is greater than 1 then 
   tell application "IndigoServer" 
      log "cannot start" 
   end tell 
   return false 
end if 

-- Since we got here, we are not already running, we can now do something useful

Explanation: The ps command lists running processes. The axww arguments cause ps to list all running processes and to not chop off the listing. grep look for lines in the ps output that contain the string osascript followed by zero or more characters, followed by the value of the variable myName, in this case, myTest.scpt

  • Using curl to replace URL Access Scripting

Many user have experienced problems with AppleScript's URL Access Scripting for connecting to web services. OS-X offers another option with the curl program. Since curl is only available from the shell, it is necessary to use AppleScript's do shell script command. Note the following example is specific to the noaa script and makes use of variables defined in that script, but you can easily modify this to replace most calls to URL Access Scripting.
The original code:

tell application "URL Access Scripting" 
   download "http://www.nws.noaa.gov/data/current_obs/" & stationID & ".xml" to file myFile replacing yes 
          
   -- work around -31040 error: 
   tell application "URL Access Scripting" to quit 
end tell 

The new code:

do shell script "/usr/bin/curl -s -S -m " & webQueryTimeout & " http://www.nws.noaa.gov/xml/current_obs/" & stationID & ".xml >" & myFile

Note the -s option to curl stops screen display of the progress meter, -S makes sure errors are reported and -m controls the maximum time curl can take to complete the connection and download. See the curl man page for more information.

  • Converting seconds to minutes and hours

Scripts that maintain time counters, like total ON time for a HVAC unit, often need to convert from seconds to hours, minutes and seconds for a useful display. This snippet will do just that:

-- starttime and endtime are AppleScript dates
set totalSeconds to endtime - starttime 
 
set theHours to (totalSeconds div hours) 
set theRemainderSeconds to (totalSeconds mod hours) 
set theMinutes to (theRemainderSeconds div minutes) 
set theRemainderSeconds to (theRemainderSeconds mod minutes) 
 
set theTimeString to theHours & ":" & theMinutes & ":" & theRemainderSeconds as text

theTimeString will come back something like 5:3:4 (You could also pad the single digit numbers if you wanted).

  • Testing for a time range

This little snippet checks to see if the time is between a start and end time. This might be useful in a Trigger Condition.

set startTime to "09:50:00 PM"
set endTime to "08:00:00 AM"
 
if (current date) is greater than date startTime and (current date) is less than date endTime then
    return true
else
    return false
end if


  • Testing a device state

Indigo spends a lot of effort making sure that its record of a device state is accurate for built-in devices (getting state information from plugin defined devices requires you to use Python). So, it is usually better to rely on Indigo's state instead of going to the bother of querying the device directly. The following two snippets could be used as Trigger conditions, and would help avoid maintaining a variable just to maintain state. The first checks for the Brightness of a device and returns true or false depending on the level. The second does the same thing, based on the On/Off state of the device.

set brightLevel to brightness of device "Device Name"
 
if brightLevel > 50 then
     return true
else
    return false
end if
set onState to on state of device "Device Name"
 
if onState = true then
     return true
else
    return false
end if


  • A handler to simplify creating and setting Indigo variables

Setting Indigo variables is a common task in scripts. This task is made especially more complex if you are developing a script that may be run by others. It is often the case the users forget to create the variables needed for a script, or use incorrect names. This handler solves all of that.

-- Set the value of a variable. 
-- If the variable doesn't exist, create it.
on setVariable(theVariable, theValue)
	tell application "IndigoServer"
		if variable theVariable exists then
			set value of variable theVariable to theValue
		else
			make new variable with properties {name:theVariable, value:theValue}
		end if
	end tell
end setVariable


  • A handler to convert HVAC modes to strings

HVAC modes from a thermostat are enumerations in AppleScript that can't be coerced into strings. So, use this handler to convert an HVAC mode into the equivalent string.

-- Set the value of a variable. 
-- If the variable doesn't exist, create it.
on stringForHVACMode(inMode)
	if (inMode = offMode) then
		return "offMode"
	else if (inMode = heatOn) then
		return "heatOn"
	else if (inMode = coolOn) then
		return "coolOn"
	else if (inMode = heatCoolOn) then
		return "heatCoolOn"
	else if (inMode = runProgramHeat) then
		return "runProgramHeat"
	else if (inMode = runProgramCool) then
		return "runProgramCool"
	else if (inMode = runProgramAuto) then
		return "runProgramAuto"
	end if
end stringForHVACMode


  • Calculating Moon Phase

This snippit of AppleScript will calculate the phase of the moon. It sets a variable named moonPhase (create it yourself first) to a number between 0 and 7. 0 is the new moon and 4 is a full moon. You could then create images for a control page starting with 0 as the new moon, progressing from 1-3 as the moon waxing, 4 as a full moon, and finally 5-7 as the moon in various stages of waning until you get back to 0 (new moon). It may be a day or two off and doesn't account for leap years, but it's going to be accurate enough to for informational purposes.

set theYear to year of (current date)
set theMonth to month of (current date) as integer
set theDay to day of (current date)
 
if (theMonth = 1) then
    set theDay to theDay - 1
else if (theMonth = 2) then
    set theDay to theDay + 30
else
    set theDay to theDay + 28 + (theMonth - 2) * 3059 / 100
end if
set g to (theYear - 1900) mod 19 + 1
set e to (11 * g + 18) mod 30
if (((e = 25) and (g > 11)) or (e = 24)) then
    set e to e + 1
end if
set fullness to ((((e + theDay) * 6 + 11) mod 177) / 22) as integer
if (fullness = 8) then set fullness to 0
set value of variable "moonPhase" to fullness
applescript_snippit.txt · Last modified: 2014/05/28 16:15 (external edit)
 

© Perceptive Automation, LLC. · Privacy