|
| 1 | +--- |
| 2 | +sidebar_position: 1 |
| 3 | +--- |
| 4 | + |
| 5 | +# Overall architecture |
| 6 | + |
| 7 | +At the heart of the manager, is the [Container](https://www.javadoc.io/doc/io.openremote/openremote-container/latest/org/openremote/container/Container.html) class that manages the life cycle of all the services, including loading and starting them at launch. |
| 8 | +Those services are defined in [manager/src/main/resources/META-INF/services/org.openremote.model.ContainerService](https://github.com/openremote/openremote/blob/master/manager/src/main/resources/META-INF/services/org.openremote.model.ContainerService) |
| 9 | + |
| 10 | +A service is a component whose lifecycle is managed by the Container, and that provides some functionality. All services implement the [ContainerService](https://www.javadoc.io/doc/io.openremote/openremote-model/latest/org/openremote/model/ContainerService.html) interface. |
| 11 | + |
| 12 | +Fundamentally, OpenRemote is a context broker, storing information about [Asset](https://www.javadoc.io/doc/io.openremote/openremote-model/latest/org/openremote/model/asset/Asset.html)s in a database. Assets have a type ([AssetDescriptor](https://www.javadoc.io/doc/io.openremote/openremote-model/latest/org/openremote/model/asset/AssetDescriptor.html)) that defines their schema. The schema defines the attributes assets have, along with meta information about them. |
| 13 | +# Event driven mechanism |
| 14 | + |
| 15 | +The whole system is event driven. Different types of events can occur in the system, all inheriting from the root [Event](https://www.javadoc.io/doc/io.openremote/openremote-model/latest/org/openremote/model/event/Event.html) class. |
| 16 | + |
| 17 | + |
| 18 | +```mermaid |
| 19 | +--- |
| 20 | +title: Key Event classes |
| 21 | +--- |
| 22 | +classDiagram |
| 23 | +
|
| 24 | + Event <|-- SharedEvent |
| 25 | + SharedEvent <|-- AttributeEvent |
| 26 | + SharedEvent <|-- ReadAssetTreeEvent |
| 27 | + SharedEvent <|-- ReadAssetsEvent |
| 28 | + SharedEvent <|-- AssetsEvent |
| 29 | + SharedEvent <|-- RulesEngineStatusEvent |
| 30 | + SharedEvent <|-- AssetTreeEvent |
| 31 | + SharedEvent <|-- ReadAssetEvent |
| 32 | + SharedEvent <|-- AssetEvent |
| 33 | + SharedEvent <|-- ReadAttributeEvent |
| 34 | + Event <|-- OutdatedAttributeEvent |
| 35 | +``` |
| 36 | + |
| 37 | +Implementation note: Apache [Camel](https://camel.apache.org) is used as a basic building block of the system and used extensively in events routing. |
| 38 | + |
| 39 | +## AttributeEvent |
| 40 | + |
| 41 | +One very important event type is [AttributeEvent](https://www.javadoc.io/doc/io.openremote/openremote-model/latest/org/openremote/model/attribute/AttributeEvent.html), 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. |
| 42 | + |
| 43 | +### Events ingress |
| 44 | + |
| 45 | +Those events can enter the system through different channels. |
| 46 | + |
| 47 | +#### From outside the system |
| 48 | + |
| 49 | +See [Manager APIs](https://docs.openremote.io/docs/user-guide/manager-apis/) for information on the different APIs. |
| 50 | + |
| 51 | +##### Via publishing on MQTT topics |
| 52 | + |
| 53 | +Clients can post on `writeattributevalue` or `writeattribute` topics. |
| 54 | +This is handled in [DefaultMQTTHandler.onPublish()](https://github.com/openremote/openremote/blob/151af17d0e502f0fa7a377cd34b8416350bc1794/manager/src/main/java/org/openremote/manager/mqtt/DefaultMQTTHandler.java#L342). |
| 55 | + |
| 56 | +##### Via REST API |
| 57 | + |
| 58 | +Several endpoints allow to add or update one or more attributes. |
| 59 | + |
| 60 | +[Write to a single attribute](https://docs.openremote.io/docs/rest-api/write-attribute-value)- `PUT {assetId}/attribute/{attributeName}` |
| 61 | +[Write to a single attribute with a timestamp](https://docs.openremote.io/docs/rest-api/write-attribute-value-1) - `PUT {assetId}/attribute/{attributeName}/{timestamp}` |
| 62 | +[Update attribute values](https://docs.openremote.io/docs/rest-api/write-attribute-values) - `PUT attributes` |
| 63 | +[Update attribute values with timestamps](https://docs.openremote.io/docs/rest-api/write-attribute-events) - `PUT attributes/timestamp` |
| 64 | + |
| 65 | +All above end up being handled by [AssetResourceImpl.doAttributeWrite()](https://github.com/openremote/openremote/blob/151af17d0e502f0fa7a377cd34b8416350bc1794/manager/src/main/java/org/openremote/manager/asset/AssetResourceImpl.java#L580). |
| 66 | + |
| 67 | +##### Via WebSocket API |
| 68 | + |
| 69 | +[AttributeEvent](https://www.javadoc.io/doc/io.openremote/openremote-model/latest/org/openremote/model/attribute/AttributeEvent.html) arriving on WebSocket are handled by [ClientEventService](https://www.javadoc.io/doc/io.openremote/openremote-manager/latest/org/openremote/manager/event/ClientEventService.html). |
| 70 | + |
| 71 | +#### From inside the system |
| 72 | + |
| 73 | +[AssetProcessingService.sendAttributeEvent()](https://github.com/openremote/openremote/blob/151af17d0e502f0fa7a377cd34b8416350bc1794/manager/src/main/java/org/openremote/manager/asset/AssetProcessingService.java#L317) can be used by any component in the system to post an [AttributeEvent](https://www.javadoc.io/doc/io.openremote/openremote-model/latest/org/openremote/model/attribute/AttributeEvent.html) for processing. |
| 74 | + |
| 75 | +### Events processing |
| 76 | + |
| 77 | +Regardless of how events enter the system, they are handled through a Camel Direct component with URI "direct://AttributeEventProcessor". |
| 78 | +This is wired to the [AssetProcessingService](https://www.javadoc.io/doc/io.openremote/openremote-manager/latest/org/openremote/manager/asset/AssetProcessingService.html), that manages the processing chain all those events go through. |
| 79 | + |
| 80 | +[AssetProcessingService.processAttributeEvent()](https://github.com/openremote/openremote/blob/151af17d0e502f0fa7a377cd34b8416350bc1794/manager/src/main/java/org/openremote/manager/asset/AssetProcessingService.java#L341) is really where all processing happens. |
| 81 | + |
| 82 | +A lock is immediately taken on the asset (assetId based) and during this lock: |
| 83 | +- [Asset](https://www.javadoc.io/doc/io.openremote/openremote-model/latest/org/openremote/model/asset/Asset.html) is retrieved from DB |
| 84 | +- An enriched event is created with the attribute and the old value/timestamp |
| 85 | +- The event is validated (based on constraints defined on the attribute) |
| 86 | +- The event goes through a chain of interceptor ([AttributeEventInterceptor](https://www.javadoc.io/doc/io.openremote/openremote-manager/latest/org/openremote/manager/event/AttributeEventInterceptor.html)). If an interceptor intercepts the event, it does not go further in the chain and its processing is stopped here. |
| 87 | + This is currently used by [Agent](https://www.javadoc.io/doc/io.openremote/openremote-model/latest/org/openremote/model/asset/agent/Agent.html)s and Gateways. |
| 88 | +- 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](https://www.javadoc.io/doc/io.openremote/openremote-manager/latest/org/openremote/manager/event/ClientEventService.html)). |
| 89 | +- If it is outdated, it's re-published as an [OutdatedAttributeEvent](https://www.javadoc.io/doc/io.openremote/openremote-manager/latest/org/openremote/manager/asset/OutdatedAttributeEvent.html) instead, so [AssetDatapointService](https://www.javadoc.io/doc/io.openremote/openremote-manager/latest/org/openremote/manager/datapoint/AssetDatapointService.html) can still store history data if required. |
0 commit comments