Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
applescript_snippit [2009/03/20 05:05] berkinetapplescript_snippit [2026/04/07 18:27] (current) – external edit 127.0.0.1
Line 1: Line 1:
 +====== AppleScript Snippits ======
 +<color red>Update</color>: AppleScript that targets the Indigo Server (**tell IndigoServer**) is no longer supported in Indigo 7.4 and beyond. To write scripts that interact with Indigo objects, you must use Python.
  
 +---------
 +
 +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. 
 +<code>
 +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
 +</code>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:
 +<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 
 +</code>
 +The new code:
 +<code applescript>
 +do shell script "/usr/bin/curl -s -S -m " & webQueryTimeout & " http://www.nws.noaa.gov/xml/current_obs/" & stationID & ".xml >" & myFile
 +</code> 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 [[http://curl.haxx.se/docs/manpage.html|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:
 +<code applescript>
 +-- 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
 +</code>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.
 +<code applescript>
 +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
 +</code>
 +\\
 +  * **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.
 +<code applescript>
 +set brightLevel to brightness of device "Device Name"
 +
 +if brightLevel > 50 then
 +     return true
 +else
 +    return false
 +end if
 +</code>
 +<code applescript>
 +set onState to on state of device "Device Name"
 +
 +if onState = true then
 +     return true
 +else
 +    return false
 +end if
 +</code>
 +\\
 +  * **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. 
 +<code applescript>
 +-- 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
 +</code>
 +\\
 +  * **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. 
 +<code applescript>
 +-- 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
 +</code>
 +\\
 +  * **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 for informational purposes.
 +
 +<code applescript>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
 +</code>