Skip to content

System Services

Elia Traore edited this page Jul 2, 2017 · 14 revisions

The Smarthouse system offers developers various services that will allow the developer's application to connect to sensors, send alerts, and more.

In order to use a service, call the function getService from the SmarthouseApplication class.

The system offers the following services:

(click a link to jump to the section describing the service you want to read about)


SENSORS_SERVICE

SensorsService

getService(ServiceType.SENSORS_SERVICE) returns a SensorsService object:

public final class SensorsService extends Service {
    public <T extends SensorData> SensorApi<T> getSensor(final String commercialName, final Class<T> sensorDataClass, final String sensorAlias);
    public <T extends SensorData> SensorApi<T> getSensor(final String commercialName, final Class<T> sensorDataClass);
    public List<String> getCommercialNames();
}

This service allows the developer to get an sensor handler API object, called SensorApi.

Sensors have a commercial name that was defined by the sensor's manufacturer. For example: iSos, iVitals, SuperStove, and etc.
When calling for a SensorApi, you must specify a commercial name that will be bind the API to an actual sensor. If a sensor with the given commercial name is connected to the system, the API will bind to it. Otherwise, the API will wait for such sensor to connect, and then it will bind to it.

Sensors also have an alias name, like: Jane's Vitals Watch, Bob's SmartTV, Alice's Toster, and etc.
The alias is given by the sensor's owner. It can be configured on the sensor's hardware, and send to the Smarthouse when the sensor connects to it.
When calling for a SensorApi, you can specify an alias if you want. If you do, the API will bind to the sensor with the given alias, or wait for such sensor to connect to the house. Otherwise, the API will bind to one of the sensors with the given commercial name, disregarding the alias.

The SensorsService can also give you the available commercial names (commercial names of the sensors that are currently connected to the system), with getCommercialNames().

sensorDataClass

Note that when calling for a SensorApi from the SensorsService, you must pass a Class<T extends SensorData> sensorDataClass. This is a class that defines the interaction with the sensor's data.

We will start with an example:
Assume we have a stove sensor connected, that sends data on 2 paths (Recall that sensors send their data on paths in the File System. In the background the SensorApi interacts with the File System and not directly with the sensor):

  • stove.is_on - sends boolean data on this path
  • stove.temperature - sends an integer data on this path

On every sensor update, we would like to retrieve information from all of the paths that it writes on.
In order to do this, we will implement a class that extends SensorData. This class will have at least 2 fields, one for each path. Now, in order to bind a parameter in the class to a File System path, use the @SystemPath annotation in the following way:

public class StoveSensor extends SensorData {
	@SystemPath("stove.is_on")
	private boolean on;

	@SystemPath("stove.temperature")
	private int temperature;

	boolean isOn() { return on; }
	int getTemperture() { return temperature; }
}

This class must be passed to the SensorsService when calling for a SensorApi! Now, on every data update, the SensorApi will pass a StoveSensor object to our functions. This object will be filled in with the new parameters from the sensor. Here is a use example:

SensorApi<StoveSensor> myStove = super.<SensorsService>getService(ServiceType.SENSORS_SERVICE)
                .getSensor("iStoves", StoveSensor.class);

myStove.subscribe(stoveDataObj -> someTextFieldForTheTemperture
                .setData(!stoveDataObj.isOn() ? 0 : stoveDataObj.getTemperture()));

SensorApi

Lets dive right in:

public interface SensorApi<T extends SensorData> {
    String getCommercialName();
    String getSensorAlias();
    String getSensorLocation();
	
    /** select a different alias of the commercial name */
    void reselectSensorByAlias(String alias);
	
    /** get all aliases of the commercial name */
    List<String> getAllAliases();
    
    /** place a listener for new aliases of the commercial name */
    String listenForNewAliases(Consumer<String> functionToRun);
    
    /** returns true if an alias was found (the sensor has connected) */
    boolean isConnected();
    
    // subscribe functions - return the subscriberID (you can unsubscribe with it)
    String subscribe(Consumer<T> functionToRun);
    String subscribeOnTime(Consumer<T> functionToRun, LocalTime timeToStartOn);
    String subscribeOnTime(Consumer<T> functionToRun, LocalTime timeToStartOn, long milliseconds);
    String subscribeOnTime(Consumer<T> functionToRun, long milliseconds);
    String runWhenSensorIsFound(Consumer<T> functionToRun);
    
    void unsubscribe(String listenerId);
	
    /** send an instruction to the sensor on the given path */
    void instruct(String instruction, String... path);
}

The API allows you to subscribe to new events from the sensor, subscribe on time, and to run a function when the sensor is available.
If the sensor is bi-directional, you can also send it instructions.

Important note: the SensorApi is created with a specific commercial name, but not with a specific alias. The alias can change if you want. The commercial name can't (you must ask the SensorsService for a new SensorApi).


FILE_SYSTEM_SERVICE

getService(ServiceType.FILE_SYSTEM_SERVICE) returns a FileSystemService object:

public class FileSystemService extends Service {
    public String subscribe(final BiConsumer<String, Object> eventHandler, final String... path);
    public void unsubscribe(final String subscriberId);
    public <T> T getData(final String... path);
}

Read more about the File System here


ALERTS_SERVICE

getService(ServiceType.ALERTS_SERVICE) returns a AlertsManager object:

public class AlertsManager extends Service {
    /**
     * Report an abnormality in the expected schedule. The system will contact
     * the needed personal, according to the urgency level
     * 
     * @param message
     *            Specify the abnormality, will be presented to the contacted
     *            personal
     * @param eLevel
     *            The level of personnel needed in the situation
     */
    public final void sendAlert(final String senderName, final String message, final EmergencyLevel eLevel);
}

EMAIL_SERVICE

getService(ServiceType.EMAIL_SERVICE) returns a EmailService object:

public class EmailService extends CommunicationService {
    public String sendMsg(final String destEmail, final String msg);
}

PHONE_SERVICE

getService(ServiceType.PHONE_SERVICE) returns a PhoneService object:

public class PhoneService extends CommunicationService {
    public String makeCall(final String phoneNumber);
}

SMS_SERVICE

getService(ServiceType.SMS_SERVICE) returns a SmsService object:

public class SmsService extends CommunicationService {
    public String sendMsg(final String destPhoneNumber, final String msg);
}

Clone this wiki locally