Building A Simple Solution

From wiki.gpii
Jump to: navigation, search

This document explains how to integrate an existing application into the GPII as a solution. We describe declaring a new solution to GPII, including its life cycle. We also show how to add user profiles so a user preferred settings get set when they login.

GPII solution lifecycle

  • login user to preferences server
  • GPII retrieves user settings
  • set solution settings and pass current settings back to GPII
  • launch solution
  • logout user
  • GPII retrieves user settings
  • set previous settings

Our Example application

Maavis is a Windows application providing ultra simple user interfaces. Maavis provides both a colour and a black-and-white theme with user configuration persisted in settings file. We will create 2 GPII profiles, Bert and Ethel. Bert's GPII profile will use the Black-and-white theme. Thus when Bert is identified as the user the GPII system will run Maavis with his BW theme setting.

The Maavis settings file is simple subset of JSON so we will developed a generic JSON settings handler which can be used with other solutions. There's documentation on running and configuring Maavis programmtically in the Maavis dev docs.

In practice

Install and test gpii code

See the Install and build instructions. For this example the installed location is written as ...\gpii

Login users

Write two gpii user profile files

We have two test users, Bert and Ethel. When either of these users are identified by GPII we want a personally configured instance of MAAVIS to start up. In order to do this we need to create user profiles for each user that tell GPII to start MAAVIS with a given configuration.

Initially we will use a minimal profile with basic configuration options:

  • Bert prefers a black-and-white display
  • Ethel prefers a colour display

The following two sections show the configuration files you need for Bert and Ethel. They differ only in the theme configuration (black and white for Bert, colour for Ethel) and are stored in ...\gpii\node_modules\universal\testData\preferences. Note here we are using solution specific settings; a set of standard settings are also supported by gpii

  • bert.json
{
    "http://registry.gpii.org/applications/net.opendirective.maavis": [{
        "value": {
            "theme": "bw"
        }
    }]
}
  • ethel.json
{
    "http://registry.gpii.org/applications/net.opendirective.maavis": [{
        "value": {
            "theme": "colour"
        }
    }]
}
Create a solutions manager entry for MAAVIS

You need to tell GPII about the solution you defined in the previous user settings. This is identified as "net.opendirective.maavis" in our example. To identify this solution you need to add an object declaration to ...\gpii\node_modules\universal\testData\solutions\win32.json

At this point we will not be passing settings to the MAAVIS instance so we'll use the supplied "noSettings" handler. Later we'll be implementing our own settings handler.

The entry you need is...

    {
        "name": "maavis",
        "id": "net.opendirective.maavis",
        "contexts": {
            "OS": [
                {
                    "id": "win32",
                    "version": ">=5.0"
                }
            ]
        },
		
        "settingsHandlers": [
            {
                "type": "gpii.settingsHandlers.noSettings",
                "capabilities": [
                    "applications.net\\.opendirective\\.maavis.id"
                ]
            }
        ],
        "lifecycleManager": {
            "start": [ 
                {
                    "type": "gpii.launch.exec",
		    "command": "${{environment}.ComSpec} /c \"cd ${{environment}.MAAVIS_HOME} && MaavisPortable.cmd\""
                }
            ],
            "stop": [ 
                {
                    "type": "gpii.launch.exec",
                    "command": "${{environment}.SystemRoot}\\System32\\taskkill.exe /f /im firefox.exe"
                }
            ]
        }
   }

Note that MAAVIS_HOME is an environment variable set by the Maavis installer.

In order for this entry to get accepted in the GPII repository, you also need to write acceptance tests, but this is not necessary when trying out the GPII integration locally.

Installing your solution

You also need to tell GPII that it should install this solution. This is done by adding an entry to gpii\node_modules\universal\testData\deviceReporter\win32_installedSolutions.json in the following format:

{
    "id": "net.opendirective.maavis"
}
Verify you can log in as both users

Start the GPII server:

  cd ..\gpii\windows
  node gpii.js

In your browser or using curl visit http://localhost:8081/user/bert/login to log in as Bert, this should return "User was successfully logged in.". In additon MAAVIS should start up.

Now visit http://localhost:8081/user/bert/logout to logout as Bert. MAAVIS should close down at this point.

You can repeat this with the ethel user by replacing "bert" in the above URLs with "ethel".

Configuring MAAVIS

Now that we can start MAAVIS for a user we need to be able to configure the application according to user preferences. MAAVIS is configured by a simple JSON file contianing key and value pairs. This means that we can simply record application specific configuration options in the user profile and pass these directly to the application. In the case of MAAVIS we pass the settings to the application by writing a settings file to disk that will be read when the application starts.

When we created the user profiles above we added a settings section to set the theme for each user. Now we need to tell GPII how to use these settings to configure the application.

Create a settings handler for MAAVIS

The settings handler needs to extract the settings from the user profile. This gives us the path to which the settings file should be written along with the settings in the same format that MAAVIS expects them. We also need to record the value of any settings we are going to change so that we can restore the original state when the application is closed.

All this is achieved in a new .../gpii/node_modules/universal/gpii/node_modules/settingsHandlers/src/js/JSONSettingsHandler.js file.

NOTE: We chose to call this JSONSettingsHandler as it will, in time, be generalised to provide a generic settings handler to work with arbitrary JSON files.

The payload passed to the set function is generated by the gpii system and the function returns the current applications settings (to be reset by gpii later). See the example payloads PUT request and PUT response.

(function () {

    "use strict";

    var fluid = require("infusion"),
        fs = require("fs"),
        gpii = fluid.registerNamespace("gpii");

    fluid.registerNamespace("gpii.settingsHandlers.JSONSettingsHandler");

    gpii.settingsHandlers.JSONSettingsHandler.set = function(profile) {
	var app = fluid.copy(profile); 
	for (var appId in app) {
	    for (var j = 0; j < app[appId].length; j++) { 
		// load the default settings used by MAAVIS
                var path = app[appId][j].options.path; 
		var defaultSettings = require(path);

		// record differences between required and default settings
		// so that they default settings can be restored
		var requiredSettings = app[appId][j].settings;
		var changedSettings = fluid.copy(requiredSettings);
		for (var settingKey in requiredSettings) {
		    var oldValue = defaultSettings[settingKey];
		    var newValue = requiredSettings[settingKey];
		    changedSettings[settingKey] = {
			"oldValue": oldValue,
			"newValue": newValue
		    };
		}
		app[appId][j].settings = changedSettings;
		
		// merge the required settings and default settings
		// this means required settings overwrite default settings
		fluid.merge(null, defaultSettings,  requiredSettings);

		// Write the new settings to a file for MAAVIS to read
		fs.writeFileSync(path, JSON.stringify(defaultSettings));
	    } 
	}
	console.log(app);
	return app;
    }

}());
Tell GPII to use the new settings handler

To tell GPII which settings handler to use we need to change the "settingsHandlers" section of the "...\gpii\node_modules\universal\testData\solutions\win32.json" so that it says the same as follows:

    "settingsHandlers": [{
        "type": "gpii.settingsHandlers.JSONSettingsHandler.set",
        "options": { "path": "${{environment}.MAAVIS_HOME}\\MaavisMedia\\Users\\Default\\userconfig.json"},
        "capabilities": [ "applications.net\\.opendirective\\.maavis.id" ]
    }],

NOTE: this code has a fixed path in it, this is obviously a bad idea and needs to be fixed. We've noted this in https://github.com/rgardler/universal/issues/1

We also need to to tell GPII to load this settingsHandler so that it can be used. This is done in "gpii/node_modules/settingsHandlers/index.js" where we add the following line:

loader.require("./src/js/JSONSettingsHandler.js");

We also need to tell GPII when to execute the settingsHandler. In the case of MAAVIS we set the settings by saving a file which will be loaded by MAAVIS when it runs. We want to restore the settings once the user logs out. This is done in the "lifeycleManager" section of the "...\gpii\node_modules\universal\testData\solutions\win32.json" by adding "setSettings". This section now becomes:

"lifecycleManager": {
    "start": [ 
         "setSettings",
         {
             "type": "gpii.launch.exec",
             "command": "${{environment}.ComSpec} /c \"cd ${{environment}.MAAVIS_HOME} && MaavisPortable.cmd\""
         } 
    ],
    "stop": [ 
         {
             "type": "gpii.launch.exec",
             "command": "${{environment}.SystemRoot}\\System32\\taskkill.exe /f /im firefox.exe"
         },
         "restoreSettings"
     ]
}

Adding USB stick log-in

A USB memory stick may be used to login a user on insertion and logout on removal. All that is required is that the USB listener is running and the USB stick has the user name entered as text (e.g bert') in a file "/.gpii-user-token.txt". This is easiest done with a by saving a new file from Notepad (due to a long standing bug in Windows Explorer it is impossible to create a file with a name starting with a '.'). More details on the page User Listener.

Using the USB listener to detect login

  • Build the listener by running the Windows cmd file gpii\windows\build
  • Run the listener by launching gpii with the Windows cmd file gpii\windows\start.cmd (extension needed) rather than "node gpii.js"
  • Save user name in a text file "\.gpii-user-token.txt" on the stick
  • Insert USB stick to log in
  • Remove USB stick to log out

Adding NFC tag log-in

See Using the NFC Listener.