Architecture Deployment API

IoT Device Flows

1. Vase Registration

sequenceDiagram
  participant Tech as Technician
  participant API as REST API
  participant DB as PostgreSQL

  Tech->>API: POST /api/v1/smart-vases/register-by-technician {serialNumber, vendorId, location}
  API->>DB: Create SmartVase {status=PendingAssignment}
  API-->>Tech: 201 {vaseId, serialNumber}

  Tech->>API: POST /api/v1/smart-vases/{id}/activate
  API->>DB: SmartVase RegistrationStatus → Active
  API-->>Tech: 200 OK

2. MQTT Connect + Heartbeat

Broker: Mosquitto in development; HiveMQ Cloud (TLS, port 8883) in production.

sequenceDiagram
  participant Vase as SmartVase Device
  participant MQTT as MQTT Broker
  participant API as MqttDeviceCommunicationService
  participant DB as PostgreSQL
  participant Monitor as VaseHealthMonitoringService

  Vase->>MQTT: CONNECT (clientId=vaseId)
  MQTT->>API: MqttDeviceStartupService.OnConnectedAsync
  API->>DB: SmartVase.LastHeartbeat = now, status=Online
  API->>DB: Publish VaseCameOnlineEvent

  loop Every 30s
    Vase->>MQTT: PUBLISH vases/{vaseId}/heartbeat
    MQTT->>API: VaseDeviceServiceAdapter.HandleHeartbeat
    API->>DB: SmartVase.LastHeartbeat = now
  end

  Monitor->>DB: Poll: SmartVases where LastHeartbeat < now-1hr
  DB-->>Monitor: Stale vases
  Monitor->>DB: SmartVase status → Offline
  Monitor->>DB: Publish VaseWentOfflineEvent

  note over Vase,Monitor: Error path: missed heartbeat → Offline after 1hr

3. Sensor Data

sequenceDiagram
  participant Vase as SmartVase Device
  participant MQTT as MQTT Broker
  participant API as MqttDeviceCommunicationService
  participant DB as PostgreSQL

  Vase->>MQTT: PUBLISH vases/{vaseId}/sensor {temperature, humidity, waterLevel}
  MQTT->>API: HandleSensorData(vaseId, payload)
  API->>DB: Update SmartVase sensor fields
  API->>DB: Recalculate Bouquet.FreshnessScore (if bouquet assigned)
  API-->>Vase: ACK

4. SmartVase State Machine

stateDiagram-v2
  [*] --> PendingAssignment : SmartVase.Create()
  PendingAssignment --> Active : AssignToVendor(vendorId, vendorType)
  Active --> PendingAssignment : UnassignFromVendor()
  Active --> Inactive : Admin deactivates
  Active --> UnderMaintenance : Admin marks for maintenance
  UnderMaintenance --> Active : Maintenance complete
  Active --> Decommissioned : Admin decommissions
  Inactive --> Decommissioned : Admin decommissions
  Decommissioned --> [*]

  note right of Active : RegistrationStatus; ConnectionStatus (Online/Offline/Unstable) is tracked separately via heartbeat