Skip to main content
Version: Next

Overall architecture

At the heart of the manager, is the Container class that manages the life cycle of all the services, including loading and starting them at launch.
Those services are defined in manager/src/main/resources/META-INF/services/org.openremote.model.ContainerService

A service is a component whose lifecycle is managed by the Container, and that provides some functionality. All services implement the ContainerService interface.

Fundamentally, OpenRemote is a context broker, storing information about Assets in a database. Assets have a type (AssetDescriptor) that defines their schema. The schema defines the attributes assets have, along with meta information about them.

Event driven mechanism

The whole system is event driven. Different types of events can occur in the system, all inheriting from the root Event class.

Implementation note: Apache Camel is used as a basic building block of the system and used extensively in events routing.

AttributeEvent

One very important event type is AttributeEvent, which represents the value of an asset's attribute at a given point in time. It is through this event that the "live" value of an attribute (i.e. the value in the database) is updated.

Events ingress

Those events can enter the system through different channels.

From outside the system

See Manager APIs for information on the different APIs.

Via publishing on MQTT topics

Clients can post on writeattributevalue or writeattribute topics. This is handled in DefaultMQTTHandler.onPublish().

Via REST API

Several endpoints allow to add or update one or more attributes.

Write to a single attribute- PUT {assetId}/attribute/{attributeName}
Write to a single attribute with a timestamp - PUT {assetId}/attribute/{attributeName}/{timestamp}
Update attribute values - PUT attributes
Update attribute values with timestamps - PUT attributes/timestamp

All above end up being handled by AssetResourceImpl.doAttributeWrite().

Via WebSocket API

AttributeEvent arriving on WebSocket are handled by ClientEventService.

From inside the system

AssetProcessingService.sendAttributeEvent() can be used by any component in the system to post an AttributeEvent for processing.

Events processing

Regardless of how events enter the system, they are handled through a Camel Direct component with URI "direct://AttributeEventProcessor".
This is wired to the AssetProcessingService, that manages the processing chain all those events go through.

AssetProcessingService.processAttributeEvent() is really where all processing happens.

A lock is immediately taken on the asset (assetId based) and during this lock:

  • Asset is retrieved from DB
  • An enriched event is created with the attribute and the old value/timestamp
  • The event is validated (based on constraints defined on the attribute)
  • The event goes through a chain of interceptor (AttributeEventInterceptor). If an interceptor intercepts the event, it does not go further in the chain and its processing is stopped here.
    This is currently used by Agents and Gateways.
  • Unless the event is outdated, it's used to update the attribute's current value (persisted in the database) and is published to a series of subscribers (via ClientEventService).
  • If it is outdated, it's re-published as an OutdatedAttributeEvent instead, so AssetDatapointService can still store history data if required.