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

sequenceDiagram
  participant Vase as SmartVase Device
  participant MQTT as Mosquitto 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 Mosquitto 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