Cumulocity-IoT / cumulocity-dynamic-mapper

The ultimate Mapper for building the bridge between any Message Broker and Cumulocity IoT in a zero-code approach!
Apache License 2.0
10 stars 9 forks source link

Feature Request: Support Downstream mappings #24

Closed switschel closed 1 year ago

switschel commented 1 year ago

Currently the dynamic mqtt mapper is focusing on upstream data. It would be great if mappings could be define to send downstream data to the devices like commands & operations.

ck-c8y commented 1 year ago

In order to support this feature, the following has to be changed:

Message direction

So far the direction for the component was always from the external system to to C8Y over the additional mqtt broker: device (mqtt publisher)-> mqtt broker -> C8Y.

This requirements reverses the message flow: C8Y-> mqtt broker -> device (mqtt consumer). An operation is initiated in C8Y and has to be send over mqtt to the device. Thus an indicator for the direction is required: incoming , outgoing

Microservice needs to publish messages

So far the MS only listened to incoming mqtt mesages: public class AsynchronousDispatcher implements MqttCallback Now we need to publish mqtt messages to the respective topic

Define filter for C8Y operations

I propose to use the Notification 2.0 API to define a subscription for new operations.

A subscription is created for all devices in a group, here BUS_1, BUS_2:

POST request I
{
    "source": {
        "id": "<<DEVICE_ID_BUS_1"
    },
    "context": "mo",
    "subscription": "subscriptionOperationGroupBusses",
    "subscriptionFilter": {
        "apis": [
            "operations"
        ]
    }
}

POST request II
{
    "source": {
        "id": "<<DEVICE_ID_BUS_2"
    },
    "context": "mo",
    "subscription": "subscriptionOperationGroupBusses",
    "subscriptionFilter": {
        "apis": [
            "operations"
        ]
    }
}

Snooping for generated operations in C8Y

In order to use generated operations as templates, similar to the snooped mqtt payloads, an outgoing mapping can snoop the C8Y operations and recorde these. In a second step recordes payloads can then be used as templates to define the mapping.

Define outgoing mappings

The semantic of source and target will change for outgoing mappings, but the position source -left and target - right should be unchanged. So far:

Now in addition:

Custom target template

The custom target template, so how the operation should be send to the device over mqtt, has to be copied to the target editor. An sample could be:

C8Y operation
{
  "deviceId": "1234",
  "rear_WebCamDevice": {
    "name": "Take a picture",
    "parameters": {
      "duration": "5s",
      "quality": "HD"
    }
  }
}

is mapped to

custom operation to device
{
  "external_bus_id": "bus_909090",
  "rear_camera": {
      "action": "take_picture",
      "duration": "5s",
      "quality": "HD"
    }
}

As part of the mapping the internal source id is resolved using an external id type, e.g. c8y_Serial.

Topic name when publishing

The external id of the device, e.g. bus number, is either part of the json payload or it has to be added to topic name.

Open points to discuss

switschel commented 1 year ago

MQTTOutgoingMappingRestController:

C8YAPISubscriber:

AsyncDispatcherOutgoing:

MQTT Publish Topic: For operations we need to define the MQTT topic where the command should be published after mapping

MQTTClient: createMEAO publishTopic must be compatible to replace internal C8Y ID with external ID.

ProcessingContext: ResolvedPublishTopic

OperationStatusHandling: When to set EXECUTING,

switschel commented 1 year ago

Fixed with https://github.com/SoftwareAG/cumulocity-dynamic-mqtt-mapper/releases/tag/v3.0.0