asyncapi: 3.0.0
id: urn:ie:ai:assetmanager
info:
  title: AI Asset Manager Azure Cloud Package Delivery API
  version: "2.3.0"
  description: |
    AI Asset Manager Azure Cloud Package Delivery API defines the channels and messages used for a package delivery from cloud
    clients to the AI Asset Manager.

    **Package delivery flow**
    - Prerequisites: Azure cloud integration workspace in AIMM, a package ready to download via HTTP(S)
    - The delivery is initiated from the cloud side with the #New Delivery operation.
    - After AIMM received the new delivery request, then it makes a request for the url to the downloadable package with #Presigned URL Link Request (in the context of this document Presigned url means "Shared Access Signature" link.)
    - The cloud side user reply to the url request with #Presigned URL Link Response. AIMM waits a configurable amount of time (default 10s) to the url response before times out. In that case AIMM try to request a new url (up to a configurable amount of times, default is 3)
    - If AIMM received the url, it tries to download that and publishes the "Downloading" state, if the download has some kind of retryable error a new url request will be made (with the same retry count configuration as before).
    - If the package is downloaded, a package import will be attempted to the AIMM workspace, the "Importing" state is published.
    - If everything is completed, "Success" state will published, otherwise "Error" state, in both case the delivery flow is terminated.

    **General**
    - All channels (topics) listed in this document are prefixed with a server dependent part marked as `{channelPrefix}`.
    The actual value of the {channelPrefix} is specified under the "URL variables" section of the given server.

    **Publish messages from the cloud**
    - AI Asset Manager subscribes to a (single) wild card channel `{channelPrefix}/messages/devicebound/#` in order to receive all messages published by Producers.
    - Actual channels contain a Property Bag in last section of the channel,
    composed of one or more key-value pairs i.e. `{channelPrefix}/messages/devicebound/{property_bag}`.
    - Property Bag is formed as: `RFC2396-encoded(<PropertyName1>)=RFC2396-encoded(<PropertyValue1>)&RFC2396-encoded(<PropertyName2>)=RFC2396-encoded(<PropertyValue2>)...`
    Each property (key) is allowed to have a single value.
    Example: {channelPrefix}/messages/devicebound/resourceType=deployment&operation=list
    - Topics listed below depicts the minimum set of key-value pairs. AI Asset Manager handles further not listed pairs gracefully
    (i.e. ignores them).
    - AI Asset Manager distinguishes received messages by checking received key-value pairs against pairs described in this document.
    - The channel structure described below is adapted to the requirements and capabilities of Azure IoT Hub.
    In case of sending cloud-to-device messages from an IoT hub, parameters of the property bag can be set as user-defined properties of the message.

    **Receiving messages emitted from AI Asset Manager**
    A Client in Azure can use the Event-Hub compatible endpoint of IoT Hub to get messages sent by AI Asset Manager.

servers:
  azure-tls:
    host: "<azure-iot-hub-name>.azure-devices.net:8883"
    protocol: tls
    protocolVersion: 3.1.1
    description: Azure IoTHub
    bindings:
      mqtt:
        clientId: "{deviceId}"
    variables:
      channelPrefix:
        default: devices/{deviceId}
  azure-wss:
    host: "<azure-iot-hub-name>.azure-devices.net:443/$iothub/websocket"
    protocol: wss
    protocolVersion: 3.1.1
    description: Azure IoTHub
    bindings:
      mqtt:
        clientId: "{deviceId}"
    variables:
      channelPrefix:
        default: devices/<deviceId>

channels:
  "{channelPrefix}/messages/devicebound/type=event&kind=newDelivery&deliveryId=${deliveryId}&projectId=${projectId}":
    parameters:
      $ref: '#/components/schemas/DefaultChannelPrefixParameter'
      deliveryId:
        $ref: '#/components/schemas/DeliveryId'
      projectId:
        $ref: '#/components/schemas/ProjectId'
    # publish:
    #   summary: Initiate a Delivery
    #   description: A client can publish a message on this channel to initiate the Delivery
    #   tags:
    #     - name: New Delivery
    #   message:
    #     $ref: '#/components/messages/NewDelivery'

  "{channelPrefix}/messages/events/type=event&kind=presignedUrlRequest&deliveryId=${deliveryId}&projectId=${projectId}":
    parameters:
      $ref: '#/components/schemas/DefaultChannelPrefixParameter'
      deliveryId:
        $ref: '#/components/schemas/DeliveryId'
      projectId:
        $ref: '#/components/schemas/ProjectId'
    # subscribe:
    #   summary: Presigned URL request for edge configuration package
    #   description: A client can subscribe on this channel to receive Presigned URL requests for edge configuration packages.
    #   tags:
    #     - name: Presigned URL Link Request
    #   message:
    #     $ref: '#/components/messages/PresignedUrlLinkRequest'

  "{channelPrefix}/messages/devicebound/type=data&kind=presignedUrlResponse&deliveryId=${deliveryId}&projectId=${projectId}":
    parameters:
      $ref: '#/components/schemas/DefaultChannelPrefixParameter'
      deliveryId:
        $ref: '#/components/schemas/DeliveryId'
      projectId:
        $ref: '#/components/schemas/ProjectId'
    # publish:
    #   summary: Response to the Presigned URL Request from AI Asset Manager
    #   description: A client can publish a response message on this channel with the Presigned URL Link to the edge configuration package.
    #   tags:
    #     - name: Presigned URL Link Response
    #   message:
    #     $ref: '#/components/messages/PresignedUrlLinkResponse'

  "{channelPrefix}/messages/events/type=state&deliveryId=${deliveryId}&projectId=${projectId}":
    parameters:
      $ref: '#/components/schemas/DefaultChannelPrefixParameter'
      deliveryId:
        $ref: '#/components/schemas/DeliveryId'
      projectId:
        $ref: '#/components/schemas/ProjectId'
    # subscribe:
    #   summary: State of the Delivery flow
    #   description: A client can subscribe on this channel to receive messages upon delivery flow state changes. Only Downloading, Importing, Success and Error states are published.
    #   tags:
    #     - name: Delivery State
    #   message:
    #     $ref: '#/components/messages/DeliveryState'

components:
  messages:
    NewDelivery:
      name: NewDeliveryMsg
      contentType: application/json
      payload:
        $ref: '#/components/schemas/NewDeliveryMsgPayload'

    PresignedUrlLinkRequest:
      name: PresignedUrlLinkRequestMsg
      contentType: application/json
      payload:
        $ref: '#/components/schemas/PresignedUrlLinkRequestMsgPayload'

    PresignedUrlLinkResponse:
      name: PresignedUrlLinkResponseMsg
      contentType: application/json
      payload:
        $ref: '#/components/schemas/PresignedUrlLinkResponseMsgPayload'

    DeliveryState:
      name: DeliveryStateInAimmMsg
      contentType: application/json
      payload:
        $ref: '#/components/schemas/DeliveryStateMsgPayload'

  schemas:
    DefaultChannelPrefixParameter:
      channelPrefix:
        description: Server dependent parameter, actual value is specified under the "URL variables" section of the server block.

    ProjectId:
      description: Identifier generated by the client in order to uniquely identify the project on the Cloud Side.

    DeviceId:
      description: Identifier generated by the client in order to uniquely identify one AIMM workspace by ID on the cloud side.  1-project_N-targets.

    DeliveryId:
      description: Identifier generated by the client in order to uniquely identify the package delivery flow.

    Timestamp:
      type: string
      format: dateTime
      description: Timestamp when the message was sent using RFC3339 standard date-time format.

    PackageId:
      type: string
      format: uuid
      description: Identifier generated by the client in order to uniquely identify the Package.

    EventId:
      type: string
      format: uuid
      description: Identifier generated by the client in order to uniquely identify the Event.

    PackageVersion:
      type: string
      description: Version number of the uniquely identifiable Package.

    NewDeliveryMsgPayload:
      type: object
      required: [ packageId, eventId, timestamp, packageVersion ]
      properties:
        packageId:
          $ref: '#/components/schemas/PackageId'
        eventId:
          $ref: '#/components/schemas/EventId'
        timestamp:
          $ref: '#/components/schemas/Timestamp'
        packageVersion:
          $ref: '#/components/schemas/PackageVersion'

    PresignedUrlLinkRequestMsgPayload:
      type: object
      required: [ eventId, timestamp ]
      properties:
        eventId:
          $ref: '#/components/schemas/EventId'
        timestamp:
          $ref: '#/components/schemas/Timestamp'
        packageVersion:
          $ref: '#/components/schemas/PackageVersion'

    PresignedUrlLinkResponseMsgPayload:
      type: object
      required: [ timestamp, attributes ]
      properties:
        timestamp:
          $ref: '#/components/schemas/Timestamp'
        attributes:
          type: object
          required: [ presignedUrl ]
          properties:
            presignedUrl:
              type: string
              format: url

    DeliveryStateMsgPayload:
      type: object
      required: [ timestamp, state, attributes ]
      properties:
        timestamp:
          $ref: '#/components/schemas/Timestamp'
        state:
          type: string
          enum:
            - Downloading
            - Importing
            - Success
            - Error
        attributes:
          type: object
          properties:
            code:
              type: string
              description: Short error code of the error that may have occurred
            message:
              type: string
              description: Descriptive message of the Error that may have occurred
        packageVersion:
          $ref: '#/components/schemas/PackageVersion'
