The Internet of Things can greatly benefit from mashup technology. The common functionality for a number of scenarios in a particular domain can be identified and isolated into single, language agnostic, and independent Web services that can be later combined into new applications. Mashups not only offer a solution for composition, they can be also used as a mean to delegate processing for data-mining or aggregation, and generate new resources that are more manageable and scalable. There are some studies that are starting to bring services in representation of physical entities into mashups. The terms ubiquitous computing mashups [1] and physical mashups [11] are being used to refer to those efforts. In a similar way, there are other works trying to bring the notion of time, place, and other contextual information into traditional Web applications (for instance, the W3C's UWA Group [12]). Our architecture offers a comprehensive solution for mashups in the Internet of Things as it not only features the access to physical entities, but also provides the means for service discovery, event notification, aggregation of resources, deployment of applications, and importantly it is designed around the an user-interaction model based on ambient-intelligence (AmI) applications, as described in Section 3.
As with any infrastructure that allows the creation of mashup applications, our architecture features the following set of mechanisms:
-
A way to describe each service in terms of their functionality.
-
A way to discover the services that are available in the environment the user is in.
-
A way for the services to communicate with interested peers when an event occurs.
-
An easy way to combine data and functionality from services.
Our framework consists of four main elements: services in representation of data, logic, and physical entities, a hub service used for notifications, a service-discovery mechanism, and execution engines (see Figure 1). The rest of this section describes each element in detail.
2.1 Services description
Each element in our architecture consists of a RESTful Web service. One of the reasons why this kind of service has been used in recent services-based platforms is that they are more suitable for ad hoc integration [13]. REST services do not need special proxy objects to handle service calls as they are accessed through simple HTTP requests; a feature available in most modern programming-languages. Interacting with a RESTful Web service is no different than opening a webpage, or sending a form. Services provide resources (e.g., webpage, data file, image, etc.) when receiving HTTP GET requests, and handle changes on the resource by receiving POST, PUT, or DELETE requests.
One of the main issues with RESTful interfaces is that they lack a well-defined standard description language because of their own architectural restrictions. A REST-based API should not define fixed resources names, so the complete interface of a service could not be acknowledged a priori. This architectural constraint states that "hypermedia should be the engine of the application state" [3]. This is, after an initial request, the content of the response must include a relationship of further URIs that can be used to continue requesting resources according to the application flow. For example, if a user is searched on a bank's database, the resource containing the user's information should contain URIs for each of his bank accounts. However, we do need to define what starting URIs the clients could use. In the bank example, we would need to know where to send the request for the user search.
In our framework, a service is described in terms of its functionality by using a WADL document [14] containing pointers to just the starting URIs for interaction. The same document describes how data will be shared, this is, how it should be parsed and consumed. A full service is not completely described by a single WADL document. Instead, a service can implement multiple interface specifications, each stored on individual documents (see Figure 2). The intention is to simplify the specification of service compositions and to bring flexibility by allowing a service to perform richer, composed tasks. The service also needs to be registered on the service discovery mechanism, and, in order to multiply the opportunities of interoperability; all the resources provided by services in the platform must be represented in most of the following formats:
-
HTML. A Web page designed to be used by a human user. This representation must provide access to all the functionality offered by the service.
-
XML. A valid representation in an XML schema related to the functionality provided by the service.
-
JSON. A JSON file containing the same data as the XML representation. Services featuring this data format must also provide a JSONP alternative.
-
ATOM. An Atom feed whose items are augmented with XML tags of the related XML schema.
2.2 Service discovery
The service discovery mechanism of our base platform should be based on any protocol that can identify networking services on a local network. During prototyping we used Zero configuration networking (Zeroconf) [15], a protocol originated on a IETF working group. We use the capabilities of Zeroconf to advertise services. To do so, once a service is ready to receive requests it must be registered in the environment by broadcasting its description through the Zeroconf implementation. The description of a service consists of the following attributes: the service name, a human-readable description, the host name and port number of the network resource, a base URI in which the REST endpoints are contained, the URL of the hub service that is used to broadcast event notifications (explained in Section 2.4.4), and the interfaces the service implements (URLs to WADL specifications). The Zeroconf protocol is currently used by many printer vendors, Wi-Fi cameras, and others. Users of the protocol are expected to find a device as soon as it joins the network, much like an USB device connecting to a computer.
2.3 Event notification
While not really part of RESTful architectures, our architecture defines as events the notifications about the update of a resource sent to interested entities. The event notification mechanism allows the interchange of context information and control messages by alerting services running in the platform when a resource containing such data is updated.
The design of the mechanism is based on the PubSubHubbub protocol [16], or Hubbub for short, which introduces a special entity called hub into the traditional publish/subscribe communication model. In Hubbub, once that a consumer makes its first request for a provider's resource, the response representation contains a link pointing to the hub service used by the provider to advertise resource updates; consumers interested in receiving notifications for that particular resource must send a subscription request to the linked hub. The hub stores a local copy of the representation that will be updated after it receives a ping request from the provider notifying him that new data is available. If this does not happen within a certain time window, the hub requests the resource by itself and updates its local copy; whenever the resource is updated, the hub notifies each of the subscribers which can then request the hub's updated representation.
At the moment, Hubbub only supports resource representations in the Atom and RSS feed formats as they allow the documents to contain links to related resources, in this case, to hub services. However, we extend these capabilities by adding support to other possible representations. References to hub services are expected as links within documents or as an attribute in service's descriptions. In this way, services that cannot include links in the representations because of limitations in data formats, can point to a hub in the service's description. Additionally, if a service declares to implement the Hubbub protocol but does not point to a hub in any ways, an execution engine will search for an available hub service in the environment to use it for event notifications during the application flow.
2.4 Execution language and engine
In mashup systems, an application is actually a composition of services put together to provide the logic needed for an application. In order to build such applications, we need first to describe the service composition using whatever language is available in the platform that will run the mashups. As stated before, the definition of a formal description for REST services has yet to be standardized; general composition languages such as WS-BPEL [17, 18] or EMML [19] which are highly dependent on the full service descriptions are having difficulties to offer an easy to use solution for unexperienced developers. Being general-purpose composition languages, they are very fine-grained systems so developers must be aware of how requests, representations, and the individual logic will be mixed up together. To confront all these issues, we propose a simple composition language in which the application logic is expressed by describing the dependencies between coarse-grained component services. Each composition step is performed accordingly to the interfaces that the involved services implement, so the full application logic can be expressed as a simple and straightforward pipelining logic graph. Applications in our framework are described by documents called application manifests, which define:
-
The services involved in the composition (which can be specific or generic) and their description.
-
The flow between the services.
-
The mashup outputs where the final data or functionality will be served.
-
Application control data such as execution schedule, authentication credentials, and other meta-data.
The scenario of use for traditional mashup systems is rather simple: once a composition is defined, it is sent for execution to a server; the server runs the composition and exposes any resources generated throughout the application flow. Systems providing ubiquitous or physical mashups, in the other hand, should integrate additional special characteristics. In our platform:
-
An application manifest is not only run on publicly available servers, they can run on local closed environments, personal mobile devices, and so on.
-
The user can be a part of the execution flow (e.g., to select between alternatives).
-
Composition could include previously unknown services that implement certain generic interfaces.
-
Notification events from physical devices or context providers are involved in the application flow.
-
The execution of applications can be scheduled.
-
Users can share and collaboratively design application manifests using the different available execution engines (with the appropriate permissions).
-
Services representing objects in the real world are managed through permissions and access control.
Application manifests are run by one of the special entities in the platform: the execution engine services. An execution engine is in charge of managing the described application flow by identifying providers, requesting resources, receiving related event notifications, and providing output resources to finally deliver the target functionality. Its architecture is composed of five main components (see Figure 3) which are in fact implementations of one or more of the core services interfaces. To further discuss the functionality of each component and the overall engine's scenario of use, lets consider as example an application that generates a map widget with the last sensor readings from two wireless sensor networks. Figure 4 shows the graphical representation of the services involved and the application flow that will end up in the generation of an output resource containing the representation of a events-enabled widget that can be embedded in Web pages.
The following sections detail how mashup applications are executed.
2.4.1 Deploying manifests
The scenario starts with the submission of the example application manifest (see Figure 5) to an execution engine. The manifest files deployed on an engine are managed through the/apps endpoint.
2.4.2 Running applications
Once an application has been deployed, the Scheduler component will start its execution at the time indicated in the manifest. Applications can be started immediately, at a certain time, or just put on hold. Also, for simple application flows, where real time notifications are not involved, the manifest can declare additional starting times or a repetition scheme. Whether the applications are running or not, they can be controlled by the direct interaction with the Scheduler component using the/engine endpoint.
2.4.3 Logical recipes
To actually "run" mashups, the application flow as described in the manifest is first transformed into a logical dependencies tree. Then, the Service Invoker component examines each node and tries to match its current conditions against the requirements of a logical recipe which is used to handle the actual processing required for that step in the mashing process. The conditions of a step refer to: the description of the service represented by the current node, the presence or availability of the same service, and the services used by this node. The requirements of a recipe declare: the interfaces that the target service must implement, the interfaces implemented by the services involved, and how recent a resource from such services must be in order to be used for processing the logic provided by the recipe. We based the concept of recipes on the fact that many of the composition tasks present very similar situations. For instance, in our example application, we could expect that the functionality expressed by the connection of every instance of the KML Generator interface to a Map Builder interface is to generate a map widget highlighting hotspots from the file. If that is not the case, we could easily add more recipes to an execution engine by posting a new recipe resource (which includes requirements and the script to handle the composition step) into the/recipes endpoint.
2.4.4 Handling requests and events
To fulfill the composition step accordingly to the recipe, the service invoker casts all the involved requests for resources. As responses arrive, they are mixed (by the recipe's scripting) into a new resource that will be stored in the current node of the full logical tree. To handle events, the Service Invoker subscribes itself to the resources for which it requires notifications by using an intermediary hub service. Here is where service discovery is used to find a hub in case one of the services declares to implement the push-subscriber interface but does not include a link to one. After subscription, event notifications arrive to the/callback endpoint of the execution engine, where the scheduler identifies the target application manifest and activates the execution of the node where the subscription was made. Whenever a step of the application flow is completed, service invocation is activated on every child node to possibly update any derived resources.
2.4.5 User inputs
It is handled by services whose resources represent user interactions. As other publisher services, they implement the push-publisher interface so they can halt the execution of an application manifest until a response from a user is received.
2.4.6 Output endpoints
The resources generated on each composition step are stored on the services dependency tree. Sometimes, the application's complete functionality is performed by the accumulation of each individual service request, other times, the final objective of a mashup is to provide new resources. To support this, the application manifest includes outputs declarations into the application flow. In the example application (see Figure 5), all connected services end up in an output which generates source code that users can copy and paste into Web pages. To interact with outputs, each execution engine exposes the outputs of the applications in the/outputs endpoint. Output resources are not just plain, simple documents. An application could be kept running and updating those resources. In the example, sensing readings will be constantly notified. Widgets on the platform are supposed to receive PubSubHubbub updates on the client's side, so outputs are always updated, living documents. Additionally, an output resource can be declared to implement interfaces, as a normal service, so the discovery mechanism can identify and include them into compositions.
2.4.7 Sharing applications
Multiple users can simultaneously use execution engines. To collaboratively design applications, they could update the same manifests by interacting with the/apps resources. We have included a special sharing alternative: the ability to export application manifests. Exported manifest contain along with the original document, the definition of all the recipes found suitable by the execution engine at hand. So, if a developer wants to take an application into another execution engine it will be executed on the same way (provided that both engines are implemented with the same scripting technology).
In the following section, we present our user-interaction model based on the framework described above. On section 4, we discuss a sample scenario with the settings of the architectural elements and the interaction following the complete model.