---
# ----------------------------------------------------------------------------
# Service Commissioning File
# ----------------------------------------------------------------------------
# Copyright: Cybus GmbH
# Contact: support@cybus.io
# ----------------------------------------------------------------------------
# QuestDB Integration (Example)
# ----------------------------------------------------------------------------

description: >
  Service commissioning file for the integration between Connectware and
  QuestDB (Example)

metadata:
  name: QuestDB Integration
  provider: cybus
  homepage: https://www.cybus.io
  version: 1.0.0

parameters:
  questdbScheme:
    description: Transport scheme, use https if TLS is configured
    type: string
    allowedValues:
      - http
      - https
    default: http

  questdbHost:
    description: Hostname or IP address of the QuestDB instance
    type: string
    default: example.com

  questdbPort:
    description: Port of the QuestDB HTTP endpoints
    type: integer
    default: 9000

  pollingInterval:
    description: Interval in milliseconds between polling queries
    type: integer
    default: 10000

  topicRoot:
    description: Root of the MQTT topic hierarchy
    type: string
    default: enterprise

resources:
  # Connection to the QuestDB HTTP endpoints. QuestDB answers GET /ping
  # without touching any data, so we probe there.
  questdbConnection:
    type: Cybus::Connection
    properties:
      protocol: Http
      connection:
        scheme: !ref questdbScheme
        host: !ref questdbHost
        port: !ref questdbPort
        probePath: /ping
        probeMethod: GET

  # Sends one InfluxDB Line Protocol line per message to /write. Lines
  # without a timestamp receive the server time at ingestion.
  machineDataWrite:
    type: Cybus::Endpoint
    properties:
      protocol: Http
      connection: !ref questdbConnection
      write:
        path: /write
        headers:
          Content-Type: text/plain

  # Feeds the write endpoint from the ISA-95 topic hierarchy. The named
  # wildcards provide the topic levels in $context.vars, so the transform
  # rule can build the line: tags from the topic levels, fields from the
  # machine payload.
  machineDataMapping:
    type: Cybus::Mapping
    properties:
      mappings:
        - subscribe:
            topic: !sub '${topicRoot}/+site/+area/+line/+cell/machine-data'
          publish:
            endpoint: !ref machineDataWrite
          rules:
            - transform:
                expression: >-
                  {
                    "body": "machine_data,site=" & $context.vars.site
                    & ",area=" & $context.vars.area
                    & ",line=" & $context.vars.line
                    & ",cell=" & $context.vars.cell
                    & " temperature=" & $string(temperature)
                    & ",pressure=" & $string(pressure)
                  }

  # Polls a five-minute SAMPLE BY aggregation per site and line. Subscribe
  # endpoints poll with GET requests, and /exec executes the SQL statement
  # in the query URL parameter.
  aggregateQuery:
    type: Cybus::Endpoint
    properties:
      protocol: Http
      connection: !ref questdbConnection
      subscribe:
        path: /exec
        # Be careful with low values, they can overload the database
        # (the unit is milliseconds).
        interval: !ref pollingInterval
        query:
          query: >-
            SELECT ts, site, line, avg(temperature) AS avg_temperature,
            count() AS samples
            FROM machine_data
            WHERE ts > dateadd('m', -5, now())
            SAMPLE BY 1m

  aggregateMapping:
    type: Cybus::Mapping
    properties:
      mappings:
        - subscribe:
            endpoint: !ref aggregateQuery
          publish:
            topic: !sub '${topicRoot}/machine-data/temperature-per-line'
