Pennyworth

Context Sensing for Mac OS X

Pennyworth + AppleScript

AppleScript is the primary technology used to communicate between Pennyworth and other applications. Applications can use AppleScript to log custom sensor readings (such as a game providing play/pause status) that Pennyworth can include in its context predictions. Likewise, Pennyworth can "command" other applications using AppleScript when the user's context changes.

Both techniques are described below.

Logging custom sensor readings

If you are developing a custom application and you would like to expose contextually-relevant information to Pennyworth, you can do so by using Pennyworth's built-in AppleScript support. The general form of these scripts is

	if application "Pennyworth" is running
		tell application "Pennyworth" to log OBSERVATION 
			with duration DURATION 
			from observer OBSERVER
	end if

If we were writing a context-aware e-mail application and wished to where whether the user was reading or writing a message, we would replace OBSERVATION with Reading or Writing.

The DURATION element would be replaced with the number of seconds Pennyworth should retain the sensor reading. If with duration is omitted, Pennyworth will keep the reading for 60 seconds.

To distinguish our mail client's reading from other observations, we would replace OBSERVER with something like My E-Mail Client: Status.

Thus, the code our e-mail client would call would look like this

	if application "Pennyworth" is running
		tell application "Pennyworth" to log "Writing" 
			with duration 600 
			from observer "My E-Mail Client: Status"
	end if

To erase an active reading (one whose duration has not elapsed), we would log another observation with a short duration of 0. This is a useful technique for clearing readings on application termination.

Note: This technique can be used to augment Pennyworth's sensors in two ways. When included with an application, such a script may be called using NSAppleScript or your environment's equivalent. If a custom sensor is needed independent of a running application, you can save a script such as the one above as a .scpt file and place that file in the

	~/Library/Application Support/Pennyworth/AppleScript/Sensors/

folder. Pennyworth will call these scripts automatically every 30 seconds. I use this technique to write sensors for applications such as Mail.app, Adium, Skype, and iChat. These scripts (and others) may be downloaded from the AppleScripts repository.

Controlling other applications with Pennyworth

If you're a developer wishing to create an application that reacts to changes in your users' context, the best way to accomplish this is to provide a full-featured AppleScript dictionary and implementation.

Pennyworth uses AppleScripts to control other applications. For example, if you want to listen to a particular playlist when you are reading, you can define an AppleScript that is called on context changes. These scripts follow the general form

	on prediction(type, prediction)
		if (type is equal to "Foo") then
			tell application "Bar"
				-- do something
			end tell
		end if
	end prediction

Pennyworth passes two arguments to a function called prediction defined in the AppleScript. The first argument is the type of the context change (Activity, Location, or Social Context) and the predicted context label (such as Playing a game). Your script is responsible for determining what it does with that information and what action it takes.

As an example, here is a script that updates your Adium status with your current activity:

	on prediction(type, prediction)
		if application "Adium" is running
			if (type is equal to "Activity") then
				tell application "Adium"
					set the status message of every 
						account to prediction
				end tell
			end if
		end if
	end prediction

The check to see if the application is running is important because Pennyworth will launch Adium if it is not running and this script is called. Also note that there is a small delay (5 seconds) between when Pennyworth generates a new context prediction and when that prediction is sent to the AppleScripts. This is used to throttle the number of AppleScript invocations when the learner is generating many different predictions in a short period of time.