Tutorial: Light Follow Me
The principle of the Light Follow Me application is to switch on/off the lights in the different rooms if there is somebody or anybody. The following screenshot is an example of the application in action:
1. Prerequisite
- Install Java Development Kit 6 (Avoid Java 7 that may cause troubles).
- Install iCasa-IDE following installation instructions on iCasa-IDE website.
- Install an iCasa distribution. We recommend to use the iCasa Teaching distribution (See download page).
2. Application Development
2.1. Project Creation and Skeleton Generation
You need to create and generate the skeleton of the unique class of your application.
Create a new iPOJO Project.
Configure the iPOJO Preferences. Go to Windows -> Preferences -> iPOJO Preferences.
Create a new component BinaryFollowMe. Open the
metadata.xml
file with the iPOJO Metadata Editor.Click Add and change the component name to BinaryFollowMe.
Add to service dependencies (i.e. required services) with Multiple and Optional characteristics:
- one dependency to
BinaryLight
with a fieldbinaryLights
and bind/unbind methods named respectivelybindBinaryLight
andunbindBinaryLight
; - one dependency to
PresenceSensor
with a fieldpresenceSensors
and bind/unbind methods named respectivelybindPresenceSensor
andunbindPresenceSensor
.
- one dependency to
Add new methods
start
andstop
for the Component Lifecycle Callbacks.Generate the class with right click on your component.
Complete the package field.
If you have done that successfully, you will have a skeleton like this:
package com.example.binary.follow.me; import fr.liglab.adele.icasa.device.light.BinaryLight; import fr.liglab.adele.icasa.device.presence.PresenceSensor; import java.util.Map; public class BinaryLightFollowMeImpl { /** Field for binaryLights dependency */ private BinaryLight[] binaryLights; /** Field for presenceSensors dependency */ private PresenceSensor[] presenceSensors; /** Bind Method for null dependency */ public void bindBinaryLight(BinaryLight binaryLight, Map properties) { // TODO: Add your implementation code here } /** Unbind Method for null dependency */ public void unbindBinaryLight(BinaryLight binaryLight, Map properties) { // TODO: Add your implementation code here } /** Bind Method for null dependency */ public void bindPresenceSensor(PresenceSensor presenceSensor, Map properties) { // TODO: Add your implementation code here } /** Unbind Method for null dependency */ public void unbindPresenceSensor(PresenceSensor presenceSensor, Map properties) { // TODO: Add your implementation code here } /** Component Lifecycle Method */ public void stop() { // TODO: Add your implementation code here } /** Component Lifecycle Method */ public void start() { // TODO: Add your implementation code here } }
2.2. Complete the Code Skeleton
In order to be notified when something is modified in the environment, the
BinaryLightFollowMeImpl
class must implementDeviceListener
interface.public class BinaryLightFollowMeImpl implements DeviceListener
Add two attributes in this
BinaryLightFollowMeImpl
class:listBinaryLight
is a list containing all the lights available in the environment;mapPresenceSensor
is a map containing all the presence sensors available in the environment./** List containing all the lights in the house */ private List
listBinaryLights; /** Map containing all the presenceSensors in the house */ private Map mapPresenceSensors;
Complete the code of
bind
andunbind
methods by adding and removing devices from their respective sets./** Bind Method for null dependency */ public void bindBinaryLight(BinaryLight binaryLight, Map properties) { listBinaryLights.add(binaryLight); } /** Unbind Method for null dependency */ public void unbindBinaryLight(BinaryLight binaryLight, Map properties) { listBinaryLights.remove(binaryLight); } /** Bind Method for null dependency */ public void bindPresenceSensor(PresenceSensor presenceSensor, Map properties) { mapPresenceSensors.put(presenceSensor.getSerialNumber(), presenceSensor); } /** Unbind Method for null dependency */ public void unbindPresenceSensor(PresenceSensor presenceSensor, Map properties) { mapPresenceSensors.remove(presenceSensor.getSerialNumber()); }
Attach the listener to the interesting devices (in our case all the presence sensors) in the
bind
method. Also unregister the listener when the sensor is leaving in theunbind
method./** Bind Method for null dependency */ public void bindPresenceSensor(PresenceSensor presenceSensor, Map properties) { presenceSensor.addListener(this); mapPresenceSensors.put(presenceSensor.getSerialNumber(), presenceSensor); } /** Unbind Method for null dependency */ public void unbindPresenceSensor(PresenceSensor presenceSensor, Map properties) { presenceSensor.removeListener(this); mapPresenceSensors.remove(presenceSensor.getSerialNumber()); }
Complete the
start
andstop
lifecycle methods with a message. Initialize the required fields at validate and clear those fields at invalidate./** Component Lifecycle Method */ public void stop() { System.out.println("Component is stopping..."); listBinaryLights = null; mapPresenceSensors = null; } /** Component Lifecycle Method */ public void start() { System.out.println("Component is starting..."); listBinaryLights = new ArrayList
(); mapPresenceSensors = new HashMap (); } Create a method named
getBinaryLightFromLocation
. This method will create a list of all binary lights from a location./**
- Method which catches all BinaryLights from a location
- @param location
@return List of BinaryLights */ private List<BinaryLight> getBinaryLightFromLocation(String location) { List<BinaryLight> binaryLightsLocation = new ArrayList<BinaryLight>();
for(BinaryLight binaryLight : listBinaryLights) { if(binaryLight.getPropertyValue(LOCATIONPROPERTYNAME).equals(location)) { binaryLightsLocation.add(binaryLight); } } return binaryLightsLocation; }
LOCATION_PROPERTY_NAME
is a constant defined and intialized previously in this class:public static String LOCATIONPROPERTYNAME = "Location";
Manage the light(s) if a presence is sensed in a location. In the method
devicePropertyModified
, there is the core of the application: if the device is an instance ofPresenceSensor
, the device is identified by its serial number. According to its location, all the lights in the same location are turn on or off.@Override public void devicePropertyModified(GenericDevice device, String propertyName, Object oldValue, Object newValue) { if(device instanceof PresenceSensor) { PresenceSensor activSensor = mapPresenceSensors.get(device.getSerialNumber()); if(activSensor != null && propertyName.equals(PresenceSensor.PRESENCE_SENSOR_SENSED_PRESENCE)) { String detectorLocation = (String) activSensor.getPropertyValue(LOCATION_PROPERTY_NAME); if(!detectorLocation.equals(LOCATION_UNKNOW)) { List
sameLocationLights = getBinaryLightFromLocation(detectorLocation); for(BinaryLight binaryLight : sameLocationLights) { binaryLight.setPowerStatus(!(Boolean) oldValue); } } } } } LOCATION_UNKNOWN
is a constant defined and intialized previously in this class:public static String LOCATION_UNKNOWN = "unknown";
Create a component instance from the metadata.xml file with the iPOJO Metadata Editor. Open the second tab Component Configuration. Right click on BinaryLightFollowMe bundle -> New Instance Declaration.
3. Application Deployment and Test
Right click on your project: iCasa -> iCasa Bundle Deployment
Test your application with iCasa Simulator.