openapi: 3.0.3
info:
  title: Emission-0 Sensor API
  version: "3.0"
  description: |
    API voor het ophalen van sensordata uit het Emission-0 platform.

    ## Authenticatie

    Om toegang te krijgen tot de API moet een client-token aangevraagd worden via de `issue_api_client_token` RPC:

    Een token vraag je op met:

    ```http
    POST /rest/v1/rpc/issue_api_client_token
    apikey: <API KEY>
    Authorization: Bearer <API KEY>
    Content-Type: application/json

    {
      "p_client_id": "partner-app-1",
      "p_client_secret": "<secret>",
      "p_ttl_minutes": 60
    }
    ```

    Bij alle endpoints stuur je drie headers mee:

    | Header | Waarde |
    |--------|--------|
    | `apikey` | De geleverde API key. |
    | `Authorization` | `Bearer` gevolgd door dezelfde API key. |
    | `x-client-token` | Access token uit de hierboven getoonde `issue_api_client_token`-aanroep. |


    ## Request body

    Onderstaand een overzicht van argumenten.

    | Veld | Betekenis |
    |------|-----------|
    | `p_sensor_id` | Uniek nummer van de sensor (hetzelfde ID als in het platform en in `v3_sensors`). |
    | `p_from` | Start van de periode waarvoor je data wilt: datum en tijd in **ISO 8601** (bijv. `2025-01-01T00:00:00Z` = 1 januari 2025, UTC). |
    | `p_to` | Einde van die periode, zelfde notatie. Meetpunten vallen **tussen** `p_from` en `p_to` (inclusief). |

    Endpoints die een “drempel” gebruiken (werkdagen boven drempel, zomer/winter-gemiddelden) berekenen die met een vaste niet instelbare waarde: **20% van `battery_capacity`** van de sensor (kolom uit `v3_sensors`). Er is geen request-parameter om die drempel te overschrijven.

  contact:
    name: Emission-0
  license:
    name: Proprietary

servers:
  - url: https://aiquhtsgbguflfbahfhf.supabase.co
    description: Productie
  - url: https://batzjtoadtbfcqphziub.supabase.co
    description: Acceptatie

tags:
  - name: Sensoren
    description: Sensor-overzicht en metadata
  - name: Energieverbruik
    description: Energieverbruik per periode (dag / week / maand / totaal), gemiddelden, pieken en 10-minuten-intervallen
  - name: Energieprofielen
    description: Statistische energieprofielen en histogrammen, berekende drempelwaarden (gebruikt als filter voor profielen en seizoensgemiddelden) en seizoensvergelijkingen (zomer / winter)
  - name: GPS
    description: GPS-posities en trails

security:
  - apiKey: []
    bearerAuth: []
    clientToken: []

components:
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: apikey
      description: API key
    bearerAuth:
      type: http
      scheme: bearer
      description: "Bearer token (dezelfde API key)"
    clientToken:
      type: apiKey
      in: header
      name: x-client-token
      description: |
        Kortlevend access token, verkregen via `POST /rest/v1/rpc/issue_api_client_token`
        (zie introductie). Vereist voor alle `v3_*`-endpoints in deze specificatie.

  schemas:
    SensorIdParam:
      type: object
      required: [p_sensor_id]
      description: |
        Voor welke sensor je de query uitvoert. Het ID vind je in de response van `v3_sensors`.
      example:
        p_sensor_id: 17725
      properties:
        p_sensor_id:
          type: integer
          format: int64
          description: |
            Uniek sensor-ID (geheel getal). Zelfde nummer als in het Emission-0 platform.
          example: 17725

    PeriodParams:
      type: object
      required: [p_sensor_id, p_from, p_to]
      description: |
        Periode + sensor: alle data wordt gefilterd op deze sensor en op tijdstempels
        vanaf `p_from` tot en met `p_to`.
      example:
        p_sensor_id: 17725
        p_from: "2025-01-01T00:00:00Z"
        p_to: "2025-06-01T00:00:00Z"
      properties:
        p_sensor_id:
          type: integer
          format: int64
          description: |
            Uniek sensor-ID (geheel getal). Zelfde nummer als in het Emission-0 platform.
          example: 17725
        p_from:
          type: string
          format: date-time
          description: |
            **Start** van de periode: datum en tijd in ISO 8601, bij voorkeur met tijdzone
            (bijv. `2025-01-01T00:00:00Z` = start 1 januari UTC).
          example: "2025-01-01T00:00:00Z"
        p_to:
          type: string
          format: date-time
          description: |
            **Einde** van de periode, zelfde notatie als `p_from`. Rijen met `timestamp`
            tussen `p_from` en `p_to` worden meegenomen.
          example: "2025-06-01T00:00:00Z"

    Sensor:
      type: object
      properties:
        id:
          type: integer
          format: int64
        name:
          type: string
        description:
          type: string
        eui:
          type: string
          nullable: true
          description: |
            Device EUI (bijv. Clickey/LoRa). Kan `null` zijn als niet bekend.
        voltage_v:
          type: number
          format: double
          nullable: true
          description: |
            Geconfigureerde spanning in **volt (V)** voor vermogen/energie-berekening op het platform.
            Kan `null` zijn als niet ingevuld.
        battery_capacity:
          type: number
          format: double
          nullable: true
          description: |
            Batterijcapaciteit zoals in de database (**Wh**). Gebruikt o.a. voor vaste drempels
            (20% van deze waarde, of 50 kWh fallback). Kan `null` zijn.

    TimeKwh:
      type: object
      properties:
        time:
          type: string
          format: date-time
        kwh:
          type: number
          format: double

    TotalKwh:
      type: object
      properties:
        total_kwh:
          type: number
          format: double

    AvgKwh10m:
      type: object
      properties:
        avg_kwh_10m:
          type: number
          format: double

    PeakKwh10m:
      type: object
      properties:
        peak_kwh_10m:
          type: number
          format: double

    ThresholdDay:
      type: object
      properties:
        min_kwh:
          type: number
          format: double

    ThresholdHour:
      type: object
      properties:
        min_kwh_hour:
          type: number
          format: double

    DaysAboveThreshold:
      type: object
      properties:
        days_above_threshold:
          type: integer
          format: int64

    ProfileDaily:
      type: object
      properties:
        avg_kwh_per_day:
          type: number
          format: double
        p95_kwh_per_day:
          type: number
          format: double
        p99_kwh_per_day:
          type: number
          format: double
          description: P97.5 percentiel

    ProfileWeekly:
      type: object
      properties:
        avg_kwh_per_week:
          type: number
          format: double
        p95_kwh_per_week:
          type: number
          format: double
        p99_kwh_per_week:
          type: number
          format: double
          description: P97.5 percentiel

    ProfileHourly:
      type: object
      properties:
        avg_kwh_per_hour:
          type: number
          format: double
        p95_kwh_per_hour:
          type: number
          format: double
        p99_kwh_per_hour:
          type: number
          format: double

    Dagverbruik:
      type: object
      properties:
        dagverbruik:
          type: number
          format: double

    HistogramHourBucket:
      type: object
      properties:
        uurverbruik:
          type: number
          format: double

    HistogramWeekBucket:
      type: object
      properties:
        weekverbruik:
          type: number
          format: double

    TotaalWerkuren:
      type: object
      properties:
        totaal_werkuren:
          type: number
          format: double

    WorkingHoursTotalPeriodParam:
      type: object
      required: [p_sensor_id]
      description: |
        `p_start` en `p_end` zijn optioneel. Weglaten = alle historie voor de sensor (zelfde als alleen `p_sensor_id`).
      example:
        p_sensor_id: 17725
        p_start: "2025-01-01T00:00:00Z"
        p_end: "2025-06-01T00:00:00Z"
      properties:
        p_sensor_id:
          type: integer
          format: int64
          description: Uniek sensor-ID.
          example: 17725
        p_start:
          type: string
          format: date-time
          nullable: true
          description: |
            Optioneel begin van het tijdsvenster (inclusief). Alleen rijen met `timestamp` ≥ `p_start` tellen mee.
          example: "2025-01-01T00:00:00Z"
        p_end:
          type: string
          format: date-time
          nullable: true
          description: |
            Optioneel einde van het tijdsvenster (inclusief). Alleen rijen met `timestamp` ≤ `p_end` tellen mee.
          example: "2025-06-01T00:00:00Z"

    WorkingHoursPerDayRow:
      type: object
      properties:
        day_time:
          type: string
          format: date-time
          description: Kalenderdag (middernacht UTC) als tijdstempel.
        werkuren:
          type: number
          format: double
          description: Aantal uren die dag waarin uurverbruik ≥ vaste uurdrempel.

    GemWerkurenPerDag:
      type: object
      properties:
        gem_werkuren_per_dag:
          type: number
          format: double
          description: |
            Gemiddeld aantal werkuren per dag, alleen over dagen met dagverbruik ≥ 20% van `battery_capacity`
            (geen fallback in deze RPC als capaciteit ontbreekt).

    SeasonWeekAvgSummer:
      type: object
      properties:
        avg_kwh_per_week_summer:
          type: number
          format: double

    SeasonWeekAvgWinter:
      type: object
      properties:
        avg_kwh_per_week_winter:
          type: number
          format: double

    SeasonHourAvgSummer:
      type: object
      properties:
        avg_kwh_per_hour_summer:
          type: number
          format: double

    SeasonHourAvgWinter:
      type: object
      properties:
        avg_kwh_per_hour_winter:
          type: number
          format: double

    AvgSummer:
      type: object
      properties:
        avg_kwh_per_day_summer:
          type: number
          format: double

    AvgWinter:
      type: object
      properties:
        avg_kwh_per_day_winter:
          type: number
          format: double

    SensorLocation:
      type: object
      properties:
        sensor_id:
          type: integer
          format: int64
        sensor_name:
          type: string
        latitude:
          type: number
          format: double
        longitude:
          type: number
          format: double
        last_seen:
          type: string
          format: date-time

    GpsTrailPoint:
      type: object
      properties:
        time:
          type: string
          format: date-time
        sensor_name:
          type: string
        latitude:
          type: number
          format: double
        longitude:
          type: number
          format: double
        kwh:
          type: number
          format: double

    Error:
      type: object
      properties:
        message:
          type: string
        code:
          type: string
        hint:
          type: string
        details:
          type: string

  responses:
    BadRequest:
      description: Ongeldige parameters
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
    Unauthorized:
      description: Ontbrekende of ongeldige apikey
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
    NotFound:
      description: Endpoint niet gevonden
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
    ServerError:
      description: Interne fout in de database
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"

paths:
  /rest/v1/rpc/v3_sensors:
    post:
      operationId: v3_sensors
      tags: [Sensoren]
      summary: Alle sensoren
      description: |
        Lijst van alle sensoren met ID, naam, omschrijving, **spanning (`voltage_v`)** en
        **batterijcapaciteit (`battery_capacity`, Wh)** — laatste twee voor inzicht in de
        configuratie en in de drempelberekening.
      requestBody:
        required: true
        description: Leeg JSON-object `{}` — geen parameters.
        content:
          application/json:
            schema:
              type: object
              description: Geen velden verplicht; stuur `{}`.
            example: {}
      responses:
        "200":
          description: Lijst van sensoren
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Sensor"
              example:
                - id: 17725
                  name: "Sensor Bouwplaats A"
                  description: "Kraan 1"
                  eui: "1122334455667788"
                  voltage_v: 630
                  battery_capacity: 50000
                - id: 18001
                  name: "Sensor Bouwplaats B"
                  description: "Kraan 2"
                  eui: null
                  voltage_v: 630
                  battery_capacity: null
        "401":
          $ref: "#/components/responses/Unauthorized"
        "500":
          $ref: "#/components/responses/ServerError"

  /rest/v1/rpc/v3_energy_daily:
    post:
      operationId: v3_energy_daily
      tags: [Energieverbruik]
      summary: Energieverbruik per dag
      description: Retourneert het totale energieverbruik in kWh per dag voor de opgegeven sensor en periode.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PeriodParams"
            example:
              p_sensor_id: 17725
              p_from: "2025-01-01T00:00:00Z"
              p_to: "2025-06-01T00:00:00Z"
      responses:
        "200":
          description: Verbruik per dag
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/TimeKwh"
              example:
                - time: "2025-01-01T00:00:00+00:00"
                  kwh: 32.4
                - time: "2025-01-02T00:00:00+00:00"
                  kwh: 38.1
                - time: "2025-01-03T00:00:00+00:00"
                  kwh: 27.6
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "500":
          $ref: "#/components/responses/ServerError"

  /rest/v1/rpc/v3_energy_weekly:
    post:
      operationId: v3_energy_weekly
      tags: [Energieverbruik]
      summary: Energieverbruik per week
      description: Retourneert het totale energieverbruik in kWh per week (ISO week, maandag t/m zondag).
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PeriodParams"
            example:
              p_sensor_id: 17725
              p_from: "2025-01-01T00:00:00Z"
              p_to: "2025-06-01T00:00:00Z"
      responses:
        "200":
          description: Verbruik per week
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/TimeKwh"
              example:
                - time: "2024-12-30T00:00:00+00:00"
                  kwh: 162.3
                - time: "2025-01-06T00:00:00+00:00"
                  kwh: 178.5
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "500":
          $ref: "#/components/responses/ServerError"

  /rest/v1/rpc/v3_energy_monthly:
    post:
      operationId: v3_energy_monthly
      tags: [Energieverbruik]
      summary: Energieverbruik per maand
      description: Retourneert het totale energieverbruik in kWh per kalendermaand.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PeriodParams"
            example:
              p_sensor_id: 17725
              p_from: "2025-01-01T00:00:00Z"
              p_to: "2025-06-01T00:00:00Z"
      responses:
        "200":
          description: Verbruik per maand
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/TimeKwh"
              example:
                - time: "2025-01-01T00:00:00+00:00"
                  kwh: 812.5
                - time: "2025-02-01T00:00:00+00:00"
                  kwh: 745.2
                - time: "2025-03-01T00:00:00+00:00"
                  kwh: 891.0
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "500":
          $ref: "#/components/responses/ServerError"

  /rest/v1/rpc/v3_energy_total:
    post:
      operationId: v3_energy_total
      tags: [Energieverbruik]
      summary: Totaalverbruik over periode
      description: Retourneert het totale energieverbruik in kWh over de volledige opgegeven periode.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PeriodParams"
            example:
              p_sensor_id: 17725
              p_from: "2025-01-01T00:00:00Z"
              p_to: "2025-06-01T00:00:00Z"
      responses:
        "200":
          description: Totaal verbruik
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/TotalKwh"
              example:
                - total_kwh: 3842.7
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "500":
          $ref: "#/components/responses/ServerError"

  /rest/v1/rpc/v3_energy_avg_10m:
    post:
      operationId: v3_energy_avg_10m
      tags: [Energieverbruik]
      summary: Gemiddeld verbruik per 10-min interval
      description: |
        Berekent het gemiddelde energieverbruik over 10-minuten-intervallen
        binnen de opgegeven periode. Geeft een enkele waarde terug.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PeriodParams"
            example:
              p_sensor_id: 17725
              p_from: "2025-01-01T00:00:00Z"
              p_to: "2025-06-01T00:00:00Z"
      responses:
        "200":
          description: Gemiddeld verbruik per 10-min bucket
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/AvgKwh10m"
              example:
                - avg_kwh_10m: 0.42
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "500":
          $ref: "#/components/responses/ServerError"

  /rest/v1/rpc/v3_energy_peak_10m:
    post:
      operationId: v3_energy_peak_10m
      tags: [Energieverbruik]
      summary: Piekverbruik (max 10-min interval)
      description: |
        Retourneert het maximale energieverbruik gemeten in een enkel
        10-minuten-interval binnen de opgegeven periode.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PeriodParams"
            example:
              p_sensor_id: 17725
              p_from: "2025-01-01T00:00:00Z"
              p_to: "2025-06-01T00:00:00Z"
      responses:
        "200":
          description: Piekverbruik per 10-min bucket
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/PeakKwh10m"
              example:
                - peak_kwh_10m: 2.85
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "500":
          $ref: "#/components/responses/ServerError"

  /rest/v1/rpc/v3_threshold_day:
    post:
      operationId: v3_threshold_day
      tags: [Energieprofielen]
      summary: Berekende dagdrempel (kWh)
      description: |
        Retourneert de minimale dagdrempel in kWh, berekend als 20% van de
        batterijcapaciteit van de sensor. Standaard 50 kWh als de capaciteit
        niet bekend is. Deze drempel wordt gebruikt voor het berekenen van
        de energieprofielen, seizoensgemiddelden en dagen boven drempel.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SensorIdParam"
            example:
              p_sensor_id: 17725
      responses:
        "200":
          description: Dagdrempel
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/ThresholdDay"
              example:
                - min_kwh: 50.0
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "500":
          $ref: "#/components/responses/ServerError"

  /rest/v1/rpc/v3_threshold_hour:
    post:
      operationId: v3_threshold_hour
      tags: [Energieprofielen]
      summary: Berekende uurdrempel (kWh)
      description: |
        Retourneert de minimale uurdrempel in kWh, berekend als 1% van de
        batterijcapaciteit van de sensor. Standaard 50 kWh als de capaciteit
        niet bekend is. Deze drempel wordt gebruikt voor het berekenen van
        het energieprofiel per uur (uren onder de drempel worden uitgefilterd).
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SensorIdParam"
            example:
              p_sensor_id: 17725
      responses:
        "200":
          description: Uurdrempel
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/ThresholdHour"
              example:
                - min_kwh_hour: 2.5
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "500":
          $ref: "#/components/responses/ServerError"

  /rest/v1/rpc/v3_days_above_threshold:
    post:
      operationId: v3_days_above_threshold
      tags: [Energieprofielen]
      summary: Aantal werkdagen boven drempel
      description: |
        Telt het aantal werkdagen (ma t/m vr) waarop het dagverbruik boven de **vaste server-drempel** lag:
        20% van `battery_capacity` van de sensor (uit `v3_sensors`), of 50 kWh als die capaciteit ontbreekt.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PeriodParams"
            example:
              p_sensor_id: 17725
              p_from: "2025-01-01T00:00:00Z"
              p_to: "2025-06-01T00:00:00Z"
      responses:
        "200":
          description: Aantal dagen boven drempel
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/DaysAboveThreshold"
              example:
                - days_above_threshold: 87
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "500":
          $ref: "#/components/responses/ServerError"

  /rest/v1/rpc/v3_energy_profile_daily:
    post:
      operationId: v3_energy_profile_daily
      tags: [Energieprofielen]
      summary: Energieprofiel per dag (gem / P95 / P97.5)
      description: |
        Statistische verdeling van dagverbruik: gemiddelde, 95e en 97.5e percentiel.
        Filtert automatisch dagen waarop het verbruik onder 20% van de batterijcapaciteit lag.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SensorIdParam"
            example:
              p_sensor_id: 17725
      responses:
        "200":
          description: Dagprofiel
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/ProfileDaily"
              example:
                - avg_kwh_per_day: 45.2
                  p95_kwh_per_day: 72.8
                  p99_kwh_per_day: 81.3
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "500":
          $ref: "#/components/responses/ServerError"

  /rest/v1/rpc/v3_energy_profile_weekly:
    post:
      operationId: v3_energy_profile_weekly
      tags: [Energieprofielen]
      summary: Energieprofiel per week (gem / P95 / P97.5)
      description: |
        Statistische verdeling van weekverbruik: gemiddelde, 95e en 97.5e percentiel.
        Weken starten op maandag (`date_trunc('week', …)`). Filtert weken waar het totaal
        onder 5× de dag-drempel lag (5 werkdagen × 20% van de batterijcapaciteit).
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SensorIdParam"
            example:
              p_sensor_id: 17725
      responses:
        "200":
          description: Weekprofiel
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/ProfileWeekly"
              example:
                - avg_kwh_per_week: 285.4
                  p95_kwh_per_week: 412.6
                  p99_kwh_per_week: 458.1
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "500":
          $ref: "#/components/responses/ServerError"

  /rest/v1/rpc/v3_energy_profile_hourly:
    post:
      operationId: v3_energy_profile_hourly
      tags: [Energieprofielen]
      summary: Energieprofiel per uur (gem / P95 / P99)
      description: |
        Statistische verdeling van uurverbruik: gemiddelde, 95e en 99e percentiel.
        Filtert automatisch uren waarop het verbruik onder 1% van de batterijcapaciteit lag.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SensorIdParam"
            example:
              p_sensor_id: 17725
      responses:
        "200":
          description: Uurprofiel
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/ProfileHourly"
              example:
                - avg_kwh_per_hour: 5.8
                  p95_kwh_per_hour: 9.2
                  p99_kwh_per_hour: 11.4
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "500":
          $ref: "#/components/responses/ServerError"

  /rest/v1/rpc/v3_energy_histogram_daily:
    post:
      operationId: v3_energy_histogram_daily
      tags: [Energieprofielen]
      summary: Histogram dagverbruik
      description: |
        Retourneert het dagverbruik per dag als losse rijen,
        bedoeld voor het opbouwen van een histogram.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SensorIdParam"
            example:
              p_sensor_id: 17725
      responses:
        "200":
          description: Dagverbruik per dag
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Dagverbruik"
              example:
                - dagverbruik: 32.4
                - dagverbruik: 38.1
                - dagverbruik: 27.6
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "500":
          $ref: "#/components/responses/ServerError"

  /rest/v1/rpc/v3_energy_histogram_hourly:
    post:
      operationId: v3_energy_histogram_hourly
      tags: [Energieprofielen]
      summary: Histogram uurverbruik (alle data)
      description: |
        Som `energy_total_kwh` per uur over **alle** meetdata van de sensor (geen tijdsfilter), analoog aan `v3_energy_histogram_daily`.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SensorIdParam"
            example:
              p_sensor_id: 17725
      responses:
        "200":
          description: Rijen met uurverbruik
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/HistogramHourBucket"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "500":
          $ref: "#/components/responses/ServerError"

  /rest/v1/rpc/v3_energy_histogram_weekly:
    post:
      operationId: v3_energy_histogram_weekly
      tags: [Energieprofielen]
      summary: Histogram weekverbruik (alle data)
      description: |
        Som `energy_total_kwh` per ISO-week over **alle** meetdata (week start maandag).
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SensorIdParam"
            example:
              p_sensor_id: 17725
      responses:
        "200":
          description: Rijen met weekverbruik
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/HistogramWeekBucket"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "500":
          $ref: "#/components/responses/ServerError"

  /rest/v1/rpc/v3_working_hours_total_period:
    post:
      operationId: v3_working_hours_total_period
      tags: [Energieprofielen]
      summary: Totaal werkuren (vaste uurdrempel, optioneel tijdsvenster)
      description: |
        Aantal uurbuckets waarin het uurverbruik ≥ vaste uurdrempel (`COALESCE(0.01 × battery_capacity, 50 kWh)`).
        Zonder `p_start`/`p_end`: over alle historie van de sensor. Met beide (of één) parameters: gefilterd op `timestamp`.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/WorkingHoursTotalPeriodParam"
            examples:
              alleHistorie:
                summary: Alle data
                value:
                  p_sensor_id: 17725
              metPeriode:
                summary: Met tijdsvenster
                value:
                  p_sensor_id: 17725
                  p_start: "2025-01-01T00:00:00Z"
                  p_end: "2025-06-01T00:00:00Z"
      responses:
        "200":
          description: Totaal werkuren
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/TotaalWerkuren"
              example:
                - totaal_werkuren: 412
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "500":
          $ref: "#/components/responses/ServerError"

  /rest/v1/rpc/v3_working_hours_per_day:
    post:
      operationId: v3_working_hours_per_day
      tags: [Energieprofielen]
      summary: Werkuren per dag (vaste uurdrempel, alle data)
      description: |
        Per kalenderdag het aantal uren waarin het uurverbruik ≥ vaste uurdrempel (`COALESCE(0.01 × battery_capacity, 50 kWh)`).
        **Geen** `p_from`/`p_to`; volledige historie van de sensor.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SensorIdParam"
            example:
              p_sensor_id: 17725
      responses:
        "200":
          description: Eén rij per dag met werkuren
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/WorkingHoursPerDayRow"
              example:
                - day_time: "2025-01-01T00:00:00+00:00"
                  werkuren: 8
                - day_time: "2025-01-02T00:00:00+00:00"
                  werkuren: 7
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "500":
          $ref: "#/components/responses/ServerError"

  /rest/v1/rpc/v3_working_hours_avg_per_day:
    post:
      operationId: v3_working_hours_avg_per_day
      tags: [Energieprofielen]
      summary: Gemiddeld werkuren per dag (vaste uur- + dagdrempel, alle data)
      description: |
        Gemiddeld aantal werkuren per dag (uurdrempel: `0.01 × battery_capacity`, zonder fallback).
        Alleen dagen meetellen waar het dagverbruik ≥ `0.2 × battery_capacity` (zonder fallback).
        **Geen** tijdsvenster.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SensorIdParam"
            example:
              p_sensor_id: 17725
      responses:
        "200":
          description: Gemiddelde werkuren per dag (gefilterde dagen)
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/GemWerkurenPerDag"
              example:
                - gem_werkuren_per_dag: 7.6
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "500":
          $ref: "#/components/responses/ServerError"

  /rest/v1/rpc/v3_energy_season_week_avg_summer:
    post:
      operationId: v3_energy_season_week_avg_summer
      tags: [Energieprofielen]
      summary: Gemiddelde week-som zomer (vaste dagdrempel, alle data)
      description: Zomer = apr–sep op kalenderdag; werkdagen boven drempel; **geen** `p_from`/`p_to`.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SensorIdParam"
            example:
              p_sensor_id: 17725
      responses:
        "200":
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/SeasonWeekAvgSummer"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "500":
          $ref: "#/components/responses/ServerError"

  /rest/v1/rpc/v3_energy_season_week_avg_winter:
    post:
      operationId: v3_energy_season_week_avg_winter
      tags: [Energieprofielen]
      summary: Gemiddelde week-som winter (vaste dagdrempel, alle data)
      description: Winter = okt–mrt; werkdagen boven drempel; **geen** tijdsvenster.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SensorIdParam"
            example:
              p_sensor_id: 17725
      responses:
        "200":
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/SeasonWeekAvgWinter"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "500":
          $ref: "#/components/responses/ServerError"

  /rest/v1/rpc/v3_energy_season_hour_avg_summer:
    post:
      operationId: v3_energy_season_hour_avg_summer
      tags: [Energieprofielen]
      summary: Gemiddeld uurverbruik zomer (vaste uurdrempel, alle data)
      description: Zomerwerkdagen; uren boven uurdrempel; **geen** tijdsvenster.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SensorIdParam"
            example:
              p_sensor_id: 17725
      responses:
        "200":
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/SeasonHourAvgSummer"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "500":
          $ref: "#/components/responses/ServerError"

  /rest/v1/rpc/v3_energy_season_hour_avg_winter:
    post:
      operationId: v3_energy_season_hour_avg_winter
      tags: [Energieprofielen]
      summary: Gemiddeld uurverbruik winter (vaste uurdrempel, alle data)
      description: Winterwerkdagen; uren boven uurdrempel; **geen** tijdsvenster.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SensorIdParam"
            example:
              p_sensor_id: 17725
      responses:
        "200":
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/SeasonHourAvgWinter"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "500":
          $ref: "#/components/responses/ServerError"

  /rest/v1/rpc/v3_energy_avg_summer:
    post:
      operationId: v3_energy_avg_summer
      tags: [Energieprofielen]
      summary: Gemiddeld dagverbruik zomer (vaste dagdrempel, alle data)
      description: |
        Zomer = april t/m september op kalenderdag; werkdagen boven vaste **dag**drempel (20% van `battery_capacity`, of 50 kWh fallback);
        gemiddeld **dag**verbruik (kWh/dag) over die dagen. **Geen** `p_from`/`p_to`.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SensorIdParam"
            example:
              p_sensor_id: 17725
      responses:
        "200":
          description: Gemiddeld zomerverbruik
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/AvgSummer"
              example:
                - avg_kwh_per_day_summer: 42.3
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "500":
          $ref: "#/components/responses/ServerError"

  /rest/v1/rpc/v3_energy_avg_winter:
    post:
      operationId: v3_energy_avg_winter
      tags: [Energieprofielen]
      summary: Gemiddeld dagverbruik winter (vaste dagdrempel, alle data)
      description: |
        Winter = oktober t/m maart op kalenderdag; werkdagen boven vaste **dag**drempel (20% van `battery_capacity`, of 50 kWh fallback);
        gemiddeld **dag**verbruik (kWh/dag) over die dagen. **Geen** tijdsvenster.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SensorIdParam"
            example:
              p_sensor_id: 17725
      responses:
        "200":
          description: Gemiddeld winterverbruik
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/AvgWinter"
              example:
                - avg_kwh_per_day_winter: 38.7
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "500":
          $ref: "#/components/responses/ServerError"

  /rest/v1/rpc/v3_sensor_locations:
    post:
      operationId: v3_sensor_locations
      tags: [GPS]
      summary: Laatst bekende sensorlocatie op kaart
      description: |
        Retourneert de laatst bekende GPS-positie. Zonder p_sensor_id worden
        alle sensoren geretourneerd; met p_sensor_id alleen die sensor.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              description: |
                Leeg `{}` = alle sensoren met GPS. Alleen `p_sensor_id` meesturen = filter op die ene sensor.
              properties:
                p_sensor_id:
                  type: integer
                  format: int64
                  description: |
                    **Optioneel.** Zelfde betekenis als elders: uniek sensor-ID. Weglaten of weg laten =
                    response bevat alle sensoren met een laatste bekende positie.
                  example: 17725
            example: { "p_sensor_id": 17725 }
      responses:
        "200":
          description: Lijst van sensorlocaties
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/SensorLocation"
              example:
                - sensor_id: 17725
                  sensor_name: "Sensor A"
                  latitude: 52.0907
                  longitude: 5.1214
                  last_seen: "2025-06-01T12:00:00+00:00"
                - sensor_id: 18001
                  sensor_name: "Sensor B"
                  latitude: 52.3676
                  longitude: 4.9041
                  last_seen: "2025-06-01T11:50:00+00:00"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "500":
          $ref: "#/components/responses/ServerError"

  /rest/v1/rpc/v3_sensor_gps_trail:
    post:
      operationId: v3_sensor_gps_trail
      tags: [GPS]
      summary: GPS-trail per sensor
      description: |
        Retourneert alle GPS-posities van een sensor binnen de opgegeven
        periode, inclusief het energieverbruik per meetpunt.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PeriodParams"
            example:
              p_sensor_id: 17725
              p_from: "2025-06-01T00:00:00Z"
              p_to: "2025-06-02T00:00:00Z"
      responses:
        "200":
          description: GPS-trail
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/GpsTrailPoint"
              example:
                - time: "2025-06-01T08:00:00+00:00"
                  sensor_name: "Sensor A"
                  latitude: 52.0907
                  longitude: 5.1214
                  kwh: 0.42
                - time: "2025-06-01T08:10:00+00:00"
                  sensor_name: "Sensor A"
                  latitude: 52.0908
                  longitude: 5.1215
                  kwh: 0.38
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "500":
          $ref: "#/components/responses/ServerError"
