LukasPoque / s3i_flutter

A library that makes it easy to communicate with the S³I (Smart Systems Service Infrastructure of the KWH4.0)
https://pub.dev/packages/s3i_flutter
MIT License
4 stars 1 forks source link

Add S3I Event System #9

Closed LukasPoque closed 2 years ago

LukasPoque commented 2 years ago

The S3I Event System is an important feature of the S3I. It enables things/services to "observe" another thing without the cloud storage (ditto) and allows customized event messages which are not directly related to a specific value (like an emergency) and could store customized values.

LukasPoque commented 2 years ago

short summary of the current draft:

S3I Event System Concept

There are two different types of events, namedEvents which are defined by the publisher and customEvents which are defined by the subscriber and need to be accepted by the publisher.

All event messages are routed via a RabbitMQ Topic Exchange named eventExchange. To create/modify a new queue and bind to different event topics there is an endpoint in the S3I Config REST API.

Named Events

All namedEvents are predefined events that are described in the directory entry of the publishing thing. These events are published every time they are triggered, whether a queue is bound to the specific topic or not.

A namedEvent directory entry is a JSON object with the event topic as parent key and description and schema fields. The description stores a human-readable specification of this event. The schema contains a JSON schema that describes the content field of the emitted Event Message.

Example for THING_ID/attributes/, where the thing emits an event with the topic newMeasurement:

{
    "ownedBy": "USER_UUID",
    "name": "Awesom Thing Name",
    "type": "component",
    "allEndpoints": [
        "ENDPOINT_ID"
    ],
    "events": {
        "newMeasurement": {
            "description": "Contains the latest measurement including computed displacement",
            "schema": {
                "$schema": "http://json-schema.org/draft-07/schema#",
                "type": "object",
                "title": "newMeasurement",
                "description": "JSON Schema for content field of this EventMessage",
                "properties": {
                    "force": {
                        "type": "number"
                    },
                    "displacement": {
                        "type": "array",
                        "items": {
                            "type": "number"
                        }
                    }
                }
            }
        }
    }
}

Sequence: Receive Named Event Messages

  1. Get the topic from the events field of the publishers directory entry
  2. Bind a queue to the topic
  3. Receive Event Messages
  4. Unbind the queue from topic

Custom Events

A customEvent can be requested by another thing (subscriber) by sending a subscriptionRequest to the publisher via the normal direct exchange.

The request contains a filter field to specify when the event should be triggered. The RQL language is used to define the trigger condition, see here for more information on how to create complex queries. The attributePaths array defines what data should be included in the content field of the custom EventMessage. The values should be addressed as JSON pointers from the base of the thing (most times the pointer starts with attributes/).

The topic of a customEvent is always the md5 hash of the filter and attribute fields.

The event is emitted from the moment when subscriptionRequest is received until there are no queues bound to the event topic (the message returns unroutable). So it's important to bind the queue before sending the subscriptionRequest.

Subscription Request example:

{
    "identifier": "s3i:UUIDv4",
    "sender": "THING_ID",
    "messageType": "customEventRequest",
    "filter": "le(attributes/features/ml40::Force/force, 0)",
    "attributePaths": [
        "attributes/features/ml40::Force/force"
    ]
}

Subscription Response example:

{
    "identifier": "s3i:UUIDv4",
    "sender": "THING_ID",
    "messageType": "customEventReply",
    "topic": "THING_ID.eventTopic",
    "ok": true,
}

Sequence: Receive Custom Event Messages

  1. Compute the topic based on the fields: topic and attributePaths of the customEventRequest message
  2. Bind a queue to the topic
  3. Send the customEventRequest message via the direct exchange
  4. Receive Event Messages
  5. Unbind the queue from topic

Event Message

The event messages are equal for both types of events. An event message is a subclass of the S3I::B::Message and adds additional fields:

{
    "identifier": "s3i:UUIDv4",
    "sender": "THING_ID",
    "messageType": "eventMessage",
    "topic": "THING_ID.eventTopic",
    "timestamp": 10000, //millisecondsSinceEpocInt
    "content": {
        //EVENT_CONTENT
    }
}