Features Overview

MediaSense is an Internet-of-Things platform for seamless, scalable data sharing, which works for peer-to-peer communication above heterogeneous network overlay, released under GNU Public General Licence Version_3. You can download this Tutorial from hereand you can find the sample code in the Tutorial. The MediaSense is capable with following functionalities:

(1) Avoid Central Failure Point.

Central point is the vital weakness for distributed communication. Any problem in the central point may cause the crash of the whole platform, especially for the data-intensive system. MediaSense fixes this problem by its fully distributed peer-to-peer architecture without any central point.

(2) Scalable for Sensor Data Sharing

With the amount of sensors increasing in the system, more and more sensors and nodes need to join the system. MediaSense gives a convenient approach to register ad include new sensors and nodes, by its distributed context exchange protocol (DCXP).

(3) Bi-directional Communication

As a per-to-peer communication, MediaSense support the data sharing and communication between each data sink in IoT, regardless different nature of the nodes and data sink. By this bi-directional communication functionality, we allow the caregiver to remotely trigger the actuators in the house and seamlessly collect sensor data.

Mechanism of MediaSense

This Chapter explains the working mechanism of MediaSense which can help the users to understand the source code during implementation. In current version, MediaSense is implemented on the RaspberryPi, and each RaspberryPi acts as a node in the peer-to-peer network. Sensors are attached to the RaspberryPi (host), with its own Universal Context ID (UCI) for communication. The MediaSense API is written in Java, which can run on any platform with Java Environment.

(1) Universal context ID

In MediaSense, each context source is regarded will be allocated an Universal Context ID (UCI), with which the sensors do not need to know about the IP address for communication. Instead, they just need to know the UCI of the sensors need to talk. MediaSense can resolve the UCIs and provide the IP addresses of the hosts, where the sensors are attached to, so as to start the data sharing.

(2) Distributed Hash table

MediaSense forms a distributed context storage based on distributed hash table (DHT), where the UCI will be stored. MediaSense is built on the overlay of Tomp2p which is an advanced implementation of DHT. With a hash function, the UCI is mapped to a closed space cycle. This space is segmented by the hosts (RaspberryPi) in a cycle, to make sure that adding and deleting a node will cause the minimum change to the platform.

(3) Distributed Context Exchange Protocol

Mediasense follows the distributed context exchange protocol (DCXP) for sensor data sharing and exchanging. This DCXP process is carried out on the space cycle provided by DHT.

Register: Each new sensor joining the Mediasense will register its UCI, using the class register.java.

Resolve: In order to locate the sensor data source, Mediasense needs to resolve the UCI of the sensor need to communicate, using the resolver.java.  IP address is one of the return result after Mediasense resolving.

Get: After resolving, Mediasense uses getter.java class to fetch the resource locates in the sensors.

(3) The Packages of MediaSense

Mediasense Infrastructure

Figure 1. Mediasense Infrastructure

There are seven main packages in MediaSense, as showing in figure 1. The top most layer is interface which get services from other layers under it. Distribution layer is the joint to connect with the Tomp2p overlay.

Interface Layer: The interface layer is the entry point to interact with the MediaSense platform. This layer provides all the necessary actions to interact with the other layers of the platform. This layer employs the Add-in layer to extend for new applications.

Add-in layer: This layer provides flexibility to make the MediaSense platform meet specific application requirements. Thus the add-in layer manages different extensible and pluggable add-ins, which can be loaded and unloaded in runtime when needed. The add-in layer can include two kinds of functionality: optimization components and extension components. The optimization components offer ways of optimizing the behavior and functionality of the system, and the extension components enables extended functionality which applications might demand.

Dissemination Layer: This package is responsible for the communication between entities, circulating information between entities and discovering entities. This layer helps to share  sensor data over a peer-to-peer network. It resolves a Universal Context Identifier (UCI) and transfers to other entities.

Distribution: The distribution layer acts as a bridge between MediaSense implementation and the tomP2P overlay. This is the place where the UCI from MediaSense and peer from tomP2P are mapped.  The MediaSense ID i.e. message, UCI is paired with a peer and communicates on the overlay by using tomP2P. This package is responsible for distributing UCI on the overlay and identifying as UCI-peer instead of UCI-IP address.

Util: This package contains some utility classes, for example, returning exception if registration or lookup fails. It contains a class to generate unique MediaSense ID and a class to serialize to and from JSON format to enable cross-platform communication.

Messages: This particular package is dedicated to messaging between MediaSense hosts.


Programming Interface Specification

The “interface” package in MediaSense provides an interface for the users of MediaSense. This layer provides all the methods to talk with other layers. In the interface layer, there exist two classes: MediaSenseApplication.java and MediaSensePlatform.java. The MediaSenseApplication.java enables the sensors to create its own UCI and return an unique string to distinguish from other applications.  The MediaSensePlatform.java provides the interface to use MediaSense, where all the user implementation should start with.

As the interface of MediaSense, the most important method is MediasensePlatform(). It is the only MediaSense API constructor, without initialization.   The shutdown() can be used to de-register the enter platform and all the network connect. After construction, we need to initialize the platform by calling the init() method. We can provide the parameters of ourselves, otherwise it will take the default parameters.  The initialized status can be check by using the method isInitialized(), which will return a boolean value. The RegisterUCI() and ResolveUCI() are used to register and resolve the UCI as explained above. There are some other methods are provided to interact with other class packages. The following examples are given to show how to use MediaSense.

(1) Implementing a basic MediaSense application

The following code demonstrates how we can create a simple application using the MediaSense platform. In order to create an application, it must extend the MediaSenseApplication class and create an instance of MediaSensePlatform. Therefore, we need to import the interface layer which is the entry point for application development using the MediaSense platform. The following examples create an instance of MediaSensePlatform.

import se.mediasense.interfacelayer.MediaSenseApplication;

import se.mediasense.interfacelayer.MediaSensePlatform;

import se.mediasense.messages.MediaSenseMessage;

public class MediaSenseApp extends MediaSenseApplication{

MediaSensePlatform m = null;

public MediaSenseApp(){

//Instantiate platform with the MediaSenseListener

m = new MediaSensePlatform(this);


public String messageGet(String s)



// your code to generate data associated with the UCI


return s;


public void run(){

System.out.println("Your first MediaSense application!");


public static void main(String [] args){

// Instantiate the application

MediaSenseApp app = new MediaSenseApp();

//Run the example application




public void handleMessage(MediaSenseMessage msm) {

throw new UnsupportedOperationException("Not supported yet.");



(2) Starting the local node

The local node can be started by calling the init method of MediaSensePlatform. If no argument is passed then the default boostrap and port are used. Add the following code to the MediaSenseApp constructor.


(3) Adding the appropriate listeners

The listener can be added by utilizing the following code. The listener is retrieved as a MediaSense message and passed as argument to the registerListener method from MediaSensePlatform.

//Add this to the MediaSenseApp constructor

m.getDisseminationCore().registerListener(se.mediasense.messages.GetMessage.TYPE, this);

(4) Registering UCIs

A UCI can be registered by employing the Registrator class. The following example shows how to register a UCI. We first create an object for Registrator and then registerUCI method is called from the MediaSensePlatform. The UCI to be registered is passed as an argument to the registerUCI method. The UCI can be registered as either synchronous or asynchronous.

//Add this to method run()

se.mediasense.distribution.Registrator reg;

reg = m.registerUCI("app1@dsv.su.se");


(5) Resolving UCIs

The registered UCI can be resolved by instantiating the Resolver class and calling the resolveUCI method from the MediaSensePlatform. The UCI is registered either as synchronous or asynchronous.

//Add this to method run()

se.mediasense.distribution.Resolver resolve;

resolve = m.resolveUCI("app1@dsv.su.se");


(6) Deleting UCIs

The registered UCI can be deleted by instantiating the Delete class and calling the delete method from the MediaSensePlatform.

//Add this to method run() 

se.mediasense.distribution.Deleter delete;

delete = m.delete(resolve.getUci());


(7) Retrieving data associated with a UCI

The data associated with UCI can be retrieved by instantiating the Getter class and calling the get method from the MediaSensePlatform. The below code will retrieve data from the messageGet method. The implementation of this method is application dependent.

//Add this to method run()

 se.mediasense.distribution.Getter getter;

getter = m.get("app1@dsv.su.se");



(8) Notifying with new data

Whenever there is new data in the MediaSense nodes, others should be notified about this new data. This can be done by calling the notify method from MediaSensePlatform. The UCI, message associated with the UCI and message source should be passed as arguments.

//Add this to method handleMessage()

m.notify(((GetMessage)_msg).getUCI(), messageGet(((GetMessage)_msg).getUCI().toString()), _msg.getSource());