{
  "manifestVersion": 1,
  "dataset": {
    "id": "cmteb-heating-bucharest",
    "name": "CMTEB Bucharest district-heating status",
    "description": "The operational status of the Bucharest district-heating network — every heating point (substation, thermal module or similar) in the city, and whether it is running normally, has a known deficiency, or is in fault — from the status map published by Compania Municipală Termoenergetica București (CMTEB). CMTEB shows only the current moment; this dataset turns hourly snapshots of it into a queryable outage history that does not otherwise exist.",
    "descriptions": {
      "ro": "Starea operațională a rețelei de termoficare a Municipiului București — fiecare punct termic sau modul termic din oraș, și dacă funcționează normal, are o deficiență sau este în avarie — preluată la fiecare oră de pe harta publicată de Compania Municipală Termoenergetica București (CMTEB). Sursa arată doar starea curentă; acest set de date construiește un istoric interogabil al avariilor prin acumularea instantaneelor orare.",
      "en": "The operational status of the Bucharest district-heating network — every heating point (substation, thermal module or similar) in the city, and whether it is running normally, has a known deficiency, or is in fault — from the status map published by Compania Municipală Termoenergetica București (CMTEB). CMTEB shows only the current moment; this dataset turns hourly snapshots of it into a queryable outage history that does not otherwise exist."
    },
    "names": {
      "ro": "Starea sistemului de termoficare din București (CMTEB)",
      "en": "CMTEB Bucharest district-heating status"
    },
    "sourceUrl": "https://www.cmteb.ro/harta_stare_sistem_termoficare_bucuresti.php",
    "license": {
      "id": "ro-official-acts-public-domain",
      "name": "Romanian official acts and public-interest information — outside copyright",
      "url": "https://legislatie.just.ro/Public/DetaliiDocument/7816",
      "attribution": "Date despre starea rețelei de termoficare publicate de CMTEB — cmteb.ro",
      "notes": "Legea 8/1996 privind dreptul de autor, art. 9, excludes from copyright both official texts of an administrative nature and simple facts and data. The heating-network status snapshots republished here are bare facts — the operational state of a public utility's facilities at a point in time — and the facility register itself is the official record CMTEB, a municipal company, maintains for that network. They are also public-interest information under Legea 544/2001 and re-usable public-sector information under Legea 179/2022, which transposes the EU Open Data Directive. HOWEVER, and a reuser must weigh this: checked cmteb.ro for a licence, terms or legal page and found none: the only footer text anywhere on the site is \"Compania Municipală Termoenergetica București S.A. • 2019 - 2026\", with no © notice and no link to any terms of use. This dataset therefore rests on the legal position above rather than on any grant from CMTEB, and anyone republishing it should make their own assessment. What it publishes is a DERIVED work: only facility_name, status (both the normalised value and the source's own Romanian `stare` text), tip, remediere, latitude/longitude and the snapshot timestamp are republished — no map imagery, no page markup, no other content from cmteb.ro. robots.txt (checked 2026-09-02) disallows exactly three paths: `/_incluse/`, `/_notes/` and `/files/CVs/istoric/`; the page this connector reads, `/harta_stare_sistem_termoficare_bucuresti.php`, is not covered by any of them. Finally: the snapshot history accumulated by this connector — the whole point of the dataset — is created here, run by run; CMTEB's own page shows only the current moment and keeps no archive, so a past snapshot in this table cannot be corroborated against the source after the fact."
    },
    "cadence": "hourly",
    "tags": [
      "heating",
      "district-heating",
      "bucharest",
      "romania",
      "infrastructure",
      "utilities",
      "cmteb",
      "energy",
      "outages"
    ],
    "sources": []
  },
  "ingest": {
    "id": "01M5K8MHJKVBMX5AB2XTE91MZ4",
    "startedAt": "2026-10-23T02:15:00.435Z",
    "snapshotDate": "2026-10-23",
    "catalogSnapshotId": 166,
    "params": {}
  },
  "baseUrl": "https://data-directory.fsn1.your-objectstorage.com/public/cmteb-heating-bucharest",
  "catalog": {
    "url": "https://data-directory.fsn1.your-objectstorage.com/catalog/cmteb-heating-bucharest/v/01M5K8MHJKVBMX5AB2XTE91MZ4/catalog.ducklake",
    "latestUrl": "https://data-directory.fsn1.your-objectstorage.com/catalog/cmteb-heating-bucharest/catalog.ducklake",
    "sha256": "2deb464e9f546e5f81b49dd108a42a327ed0fc4236f7490ae0a7a7c4ddd6f1da",
    "duckdbVersion": "v1.5.5",
    "attachExample": "ATTACH 'ducklake:https://data-directory.fsn1.your-objectstorage.com/catalog/cmteb-heating-bucharest/catalog.ducklake' AS lake (READ_ONLY); SELECT * FROM lake.main.heating_points LIMIT 5;"
  },
  "queryHints": {
    "examples": [
      {
        "title": "The network right now",
        "sql": "WITH latest AS (\n  SELECT max(snapshot_date) AS d, max(snapshot_hour) AS h\n  FROM heating_points\n  WHERE snapshot_date = (SELECT max(snapshot_date) FROM heating_points)\n)\nSELECT status, count(*) AS points\nFROM heating_points, latest\nWHERE snapshot_date = latest.d AND snapshot_hour = latest.h\nGROUP BY status\nORDER BY points DESC",
        "description": "Counts by status in the most recent snapshot."
      },
      {
        "title": "Outage history of one facility",
        "sql": "SELECT snapshot_date, snapshot_hour, status, stare, remediere\nFROM heating_points\nWHERE facility_name_lc LIKE '%barbu vacarescu%'\nORDER BY snapshot_date, snapshot_hour",
        "description": "facility_name_lc is searched, never lower(facility_name) — a function on a column cannot use parquet statistics."
      },
      {
        "title": "Which points were faulted this week, and for how many snapshots",
        "sql": "SELECT facility_name, count(*) AS faulted_snapshots\nFROM heating_points\nWHERE status = 'fault' AND snapshot_date >= current_date - INTERVAL 7 DAY\nGROUP BY facility_name\nORDER BY faulted_snapshots DESC\nLIMIT 20"
      }
    ]
  },
  "tables": [
    {
      "name": "heating_points",
      "description": "One row per heating point (substation, thermal module or similar) in the Bucharest district-heating network per hourly snapshot, as CMTEB's own status map shows it at that moment. CMTEB publishes only the current state; this table is what turns repeated snapshots of it into a queryable outage history.",
      "descriptions": {
        "ro": "Câte un rând pentru fiecare punct termic (modul termic, punct termic sau similar) din rețeaua de termoficare a Bucureștiului, la fiecare instantaneu orar, exact așa cum apărea în acel moment pe harta de stare a CMTEB. CMTEB publică doar starea curentă; acest tabel transformă instantaneele repetate într-un istoric interogabil al avariilor.",
        "en": "One row per heating point (substation, thermal module or similar) in the Bucharest district-heating network per hourly snapshot, as CMTEB's own status map shows it at that moment. CMTEB publishes only the current state; this table is what turns repeated snapshots of it into a queryable outage history."
      },
      "rowCount": 154062,
      "lastRunRows": 951,
      "totalBytes": 200788,
      "sortBy": [
        "snapshot_date",
        "snapshot_hour",
        "status",
        "facility_name"
      ],
      "searchColumns": [
        "facility_name"
      ],
      "primaryKey": [
        "snapshot_date",
        "snapshot_hour",
        "facility_name",
        "facility_seq"
      ],
      "writeMode": "snapshot_history",
      "storage": "lake",
      "columns": [
        {
          "name": "snapshot_date",
          "type": "DATE",
          "nullable": false,
          "description": "The calendar day (UTC) this snapshot was taken. Leading sort column and, together with snapshot_hour, the reload unit: re-ingesting the same (date, hour) pair replaces exactly those rows and nothing else.",
          "descriptions": {
            "ro": "Ziua calendaristică (UTC) în care a fost preluat acest instantaneu. Este prima coloană de sortare și, împreună cu snapshot_hour, formează unitatea de reîncărcare: reluarea aceleiași perechi (dată, oră) înlocuiește exact acele rânduri și nimic altceva.",
            "en": "The calendar day (UTC) this snapshot was taken. Leading sort column and, together with snapshot_hour, the reload unit: re-ingesting the same (date, hour) pair replaces exactly those rows and nothing else."
          },
          "min": "2026-09-02",
          "max": "2026-10-23",
          "distinctApprox": 12
        },
        {
          "name": "snapshot_hour",
          "type": "INTEGER",
          "nullable": false,
          "description": "The hour of day (0-23, UTC) this snapshot belongs to — the connector's own poll slot, not a value CMTEB publishes. Combined with snapshot_date it names the reload unit: this connector runs hourly, and keying on the hour (rather than the date alone) is what stops a later run in the same day from erasing an earlier one's outages before they are ever queried. See the file-level comment on this table for the full argument.",
          "descriptions": {
            "ro": "Ora din zi (0-23, UTC) căreia îi aparține acest instantaneu — un interval propriu conectorului, nu o valoare publicată de CMTEB. Împreună cu snapshot_date formează unitatea de reîncărcare: acest conector rulează o dată pe oră, iar cheia pe oră (nu doar pe zi) este ceea ce împiedică o rulare ulterioară din aceeași zi să șteargă avariile unei rulări anterioare înainte ca cineva să apuce să le interogheze.",
            "en": "The hour of day (0-23, UTC) this snapshot belongs to — the connector's own poll slot, not a value CMTEB publishes. Combined with snapshot_date it names the reload unit: this connector runs hourly, and keying on the hour (rather than the date alone) is what stops a later run in the same day from erasing an earlier one's outages before they are ever queried. See the file-level comment on this table for the full argument."
          },
          "unit": "hour of day (UTC)",
          "min": 0,
          "max": 23,
          "distinctApprox": 24
        },
        {
          "name": "snapshot_at",
          "type": "TIMESTAMPTZ",
          "nullable": false,
          "description": "The exact instant (UTC) this snapshot was fetched — ctx.runAt, unrounded. snapshot_date/snapshot_hour bucket a run into its reload unit; this column keeps the precise minute for anyone who needs it.",
          "descriptions": {
            "ro": "Momentul exact (UTC) în care a fost preluat acest instantaneu — ctx.runAt, neaproximat. snapshot_date/snapshot_hour încadrează o rulare în unitatea sa de reîncărcare; această coloană păstrează minutul exact pentru cine are nevoie de el.",
            "en": "The exact instant (UTC) this snapshot was fetched — ctx.runAt, unrounded. snapshot_date/snapshot_hour bucket a run into its reload unit; this column keeps the precise minute for anyone who needs it."
          }
        },
        {
          "name": "facility_name",
          "type": "VARCHAR",
          "nullable": false,
          "description": "The facility's name, exactly as CMTEB's `denumire` field gives it, trimmed of leading and trailing whitespace only (the source pads a number of names with a trailing space, e.g. \"VSNord \"). This is the practical key for finding one facility, but the source does NOT guarantee it is unique: two of the 951 points captured on 2026-09-02 are both named \"P.D.\" at different coordinates. Use facility_seq (and, where available, latitude/longitude) to tell such rows apart; do not assume one name is one place.",
          "descriptions": {
            "ro": "Numele punctului termic, exact așa cum îl dă câmpul `denumire` al CMTEB, curățat doar de spațiile de la început și de la sfârșit (sursa adaugă un spațiu final la o parte dintre nume, de exemplu \"VSNord \"). Este cheia practică pentru a găsi un punct anume, dar sursa NU garantează unicitatea lui: două dintre cele 951 de puncte preluate pe 2026-09-02 se numesc amândouă \"P.D.\", la coordonate diferite. Folosește facility_seq (și, unde există, latitude/longitude) ca să distingi astfel de rânduri; nu presupune că un nume înseamnă un singur loc.",
            "en": "The facility's name, exactly as CMTEB's `denumire` field gives it, trimmed of leading and trailing whitespace only (the source pads a number of names with a trailing space, e.g. \"VSNord \"). This is the practical key for finding one facility, but the source does NOT guarantee it is unique: two of the 951 points captured on 2026-09-02 are both named \"P.D.\" at different coordinates. Use facility_seq (and, where available, latitude/longitude) to tell such rows apart; do not assume one name is one place."
          },
          "min": "1 Alexandria",
          "max": "Școala Gimnazială Regina Maria nr. 198",
          "distinctApprox": 842
        },
        {
          "name": "facility_name_lc",
          "type": "VARCHAR",
          "nullable": false,
          "description": "facility_name, lowercased and accent-folded, for case- and accent-insensitive search. Query this, not lower(facility_name) — a function on a column cannot use parquet statistics.",
          "descriptions": {
            "ro": "facility_name, scris cu litere mici și fără diacritice, pentru căutare insensibilă la majuscule și diacritice. Interoghează această coloană, nu lower(facility_name) — o funcție aplicată unei coloane nu poate folosi statisticile parquet.",
            "en": "facility_name, lowercased and accent-folded, for case- and accent-insensitive search. Query this, not lower(facility_name) — a function on a column cannot use parquet statistics."
          }
        },
        {
          "name": "facility_seq",
          "type": "INTEGER",
          "nullable": false,
          "description": "Disambiguates a facility_name that repeats within the same snapshot — 0 for the (normal) case of a unique name. When a name is shared by more than one physical point in one fetch, every point sharing it is sorted deterministically by (longitude, latitude, tip, stare) as CMTEB reported them that hour, ascending, and numbered 0, 1, 2, … in that order — never by array position, which the source does not promise is stable. Because a physical heating point's coordinates do not move, the same point keeps the same facility_seq across snapshots as long as CMTEB keeps reporting a coordinate for it, which is what makes (facility_name, facility_seq) usable as a stable per-point key alongside the primary key's snapshot columns.",
          "descriptions": {
            "ro": "Distinge rândurile atunci când același facility_name apare de mai multe ori în același instantaneu — 0 pentru cazul (obișnuit) al unui nume unic. Când un nume este purtat de mai multe puncte fizice diferite într-o singură preluare, toate punctele cu acel nume sunt sortate determinist după (longitude, latitude, tip, stare) așa cum le-a raportat CMTEB în acea oră, crescător, și numerotate 0, 1, 2, … în această ordine — niciodată după poziția din tabloul sursă, pe care sursa nu o garantează stabilă. Pentru că un punct termic fizic nu își schimbă coordonatele, același punct păstrează același facility_seq de la un instantaneu la altul atâta timp cât CMTEB îi raportează în continuare o coordonată, ceea ce face ca perechea (facility_name, facility_seq) să funcționeze ca o cheie stabilă per punct, alături de coloanele de instantaneu din cheia primară.",
            "en": "Disambiguates a facility_name that repeats within the same snapshot — 0 for the (normal) case of a unique name. When a name is shared by more than one physical point in one fetch, every point sharing it is sorted deterministically by (longitude, latitude, tip, stare) as CMTEB reported them that hour, ascending, and numbered 0, 1, 2, … in that order — never by array position, which the source does not promise is stable. Because a physical heating point's coordinates do not move, the same point keeps the same facility_seq across snapshots as long as CMTEB keeps reporting a coordinate for it, which is what makes (facility_name, facility_seq) usable as a stable per-point key alongside the primary key's snapshot columns."
          },
          "distinctApprox": 2
        },
        {
          "name": "status",
          "type": "VARCHAR",
          "nullable": false,
          "description": "The facility's status, decoded from which of the three arrays the source page listed it in, never from its raw text: \"functional\" (from passedFeatures_verde, colour #008217 on the source map — running normally), \"deficient\" (passedFeatures_galben, #ffe53e — a known deficiency but still in service) or \"fault\" (passedFeatures_rosu, #e0002b — stopped / under repair). The `stare` column carries the source's own free text for the same row; this column is what is safe to filter and aggregate on.",
          "descriptions": {
            "ro": "Starea punctului termic, dedusă din care dintre cele trei tablouri ale paginii sursă îl conținea, niciodată din textul lui brut: \"functional\" (din passedFeatures_verde, culoarea #008217 pe harta sursă — funcționare normală), \"deficient\" (passedFeatures_galben, #ffe53e — o deficiență cunoscută, dar încă în funcțiune) sau \"fault\" (passedFeatures_rosu, #e0002b — oprit / în reparație). Coloana `stare` păstrează textul liber al sursei pentru același rând; această coloană este cea sigură pentru filtrare și agregare.",
            "en": "The facility's status, decoded from which of the three arrays the source page listed it in, never from its raw text: \"functional\" (from passedFeatures_verde, colour #008217 on the source map — running normally), \"deficient\" (passedFeatures_galben, #ffe53e — a known deficiency but still in service) or \"fault\" (passedFeatures_rosu, #e0002b — stopped / under repair). The `stare` column carries the source's own free text for the same row; this column is what is safe to filter and aggregate on."
          },
          "min": "deficient",
          "max": "functional"
        },
        {
          "name": "stare",
          "type": "VARCHAR",
          "nullable": true,
          "description": "The source's own Romanian status text, verbatim (CMTEB's `stare` field) — anything from the fixed phrase \"Functionare normala\" for every functional point to a free-text description of a specific fault or works order. Not normalised and not guaranteed to take any fixed set of values; read `status` for that.",
          "descriptions": {
            "ro": "Textul de stare, verbatim, așa cum îl dă sursa (câmpul `stare` al CMTEB) — de la formula fixă \"Functionare normala\" pentru orice punct funcțional, până la o descriere liberă a unei avarii sau lucrări anume. Nu este normalizat și nu ia neapărat un set fix de valori; pentru asta citește `status`.",
            "en": "The source's own Romanian status text, verbatim (CMTEB's `stare` field) — anything from the fixed phrase \"Functionare normala\" for every functional point to a free-text description of a specific fault or works order. Not normalised and not guaranteed to take any fixed set of values; read `status` for that."
          }
        },
        {
          "name": "tip",
          "type": "VARCHAR",
          "nullable": true,
          "description": "The kind of issue CMTEB records for this point (`tip`), e.g. \"Oprire ACC\" (hot-water supply stopped) or \"Deficienta ACC\" (hot-water supply deficiency). CMTEB writes the literal string \"-\" for a functional point with nothing to report, which is kept verbatim rather than converted to NULL: it is the source's own value for \"nothing wrong\", distinct from a genuinely missing field.",
          "descriptions": {
            "ro": "Tipul de problemă înregistrat de CMTEB pentru acest punct (`tip`), de exemplu \"Oprire ACC\" (apă caldă de consum oprită) sau \"Deficienta ACC\" (deficiență la apa caldă de consum). CMTEB scrie literal \"-\" pentru un punct funcțional fără nimic de raportat, valoare păstrată ca atare, nu transformată în NULL: este chiar valoarea sursei pentru \"nimic în neregulă\", distinctă de un câmp cu adevărat lipsă.",
            "en": "The kind of issue CMTEB records for this point (`tip`), e.g. \"Oprire ACC\" (hot-water supply stopped) or \"Deficienta ACC\" (hot-water supply deficiency). CMTEB writes the literal string \"-\" for a functional point with nothing to report, which is kept verbatim rather than converted to NULL: it is the source's own value for \"nothing wrong\", distinct from a genuinely missing field."
          }
        },
        {
          "name": "remediere",
          "type": "VARCHAR",
          "nullable": true,
          "description": "The source's own remediation / expected-fix note (`remediere`), verbatim. Present only on some deficient/fault rows in practice (never observed on a functional one) and, when present, usually but not reliably formatted \"DD.MM.YYYY HH:mm\" — kept as text rather than parsed into a date/time column because that format is CMTEB's convention, not a documented guarantee.",
          "descriptions": {
            "ro": "Nota proprie a sursei despre remediere / termenul estimat de rezolvare (`remediere`), verbatim. Prezentă în practică doar la o parte din rândurile cu deficiență sau avarie (niciodată observată la un punct funcțional) și, atunci când există, de obicei — dar nu garantat — în formatul \"DD.MM.YYYY HH:mm\"; păstrată ca text, nu transformată într-o coloană de dată/oră, pentru că acest format este o convenție a CMTEB, nu o garanție documentată.",
            "en": "The source's own remediation / expected-fix note (`remediere`), verbatim. Present only on some deficient/fault rows in practice (never observed on a functional one) and, when present, usually but not reliably formatted \"DD.MM.YYYY HH:mm\" — kept as text rather than parsed into a date/time column because that format is CMTEB's convention, not a documented guarantee."
          }
        },
        {
          "name": "latitude",
          "type": "DOUBLE",
          "nullable": true,
          "description": "The facility's latitude (WGS 84). NULL when CMTEB's coordinate for this row is missing, non-numeric, or falls outside a generous Bucharest-area bounding box (44.30-44.60°N, 25.90-26.30°E) — treated as a bad coordinate and discarded rather than published, because every one of the 951 points in the 2026-09-02 capture already falls well inside it (44.37-44.49°N observed). The row itself is always kept; only the coordinate pair is nulled. describeRun logs how many rows this affected on each run.",
          "descriptions": {
            "ro": "Latitudinea punctului termic (WGS 84). NULL atunci când coordonata CMTEB pentru acest rând lipsește, nu este numerică sau cade în afara unui dreptunghi generos în jurul Bucureștiului (44,30-44,60°N, 25,90-26,30°E) — tratată ca o coordonată greșită și eliminată, nu publicată, pentru că toate cele 951 de puncte din preluarea din 2026-09-02 se încadrează deja larg în acest dreptunghi (44,37-44,49°N observat). Rândul în sine este păstrat mereu; doar perechea de coordonate este anulată. describeRun raportează la fiecare rulare câte rânduri au fost afectate.",
            "en": "The facility's latitude (WGS 84). NULL when CMTEB's coordinate for this row is missing, non-numeric, or falls outside a generous Bucharest-area bounding box (44.30-44.60°N, 25.90-26.30°E) — treated as a bad coordinate and discarded rather than published, because every one of the 951 points in the 2026-09-02 capture already falls well inside it (44.37-44.49°N observed). The row itself is always kept; only the coordinate pair is nulled. describeRun logs how many rows this affected on each run."
          },
          "unit": "degrees"
        },
        {
          "name": "longitude",
          "type": "DOUBLE",
          "nullable": true,
          "description": "The facility's longitude (WGS 84), validated against the same bounding box as latitude (see its description) and nulled together with it — a coordinate pair is accepted or rejected as a pair, never independently.",
          "descriptions": {
            "ro": "Longitudinea punctului termic (WGS 84), validată cu același dreptunghi ca și latitudinea (vezi descrierea ei) și anulată împreună cu ea — o pereche de coordonate este acceptată sau respinsă ca pereche, niciodată separat.",
            "en": "The facility's longitude (WGS 84), validated against the same bounding box as latitude (see its description) and nulled together with it — a coordinate pair is accepted or rejected as a pair, never independently."
          },
          "unit": "degrees"
        }
      ],
      "files": [
        {
          "url": "https://data-directory.fsn1.your-objectstorage.com/public/cmteb-heating-bucharest/v/01M5K8MHJKVBMX5AB2XTE91MZ4/heating_points.parquet",
          "sizeBytes": 200788,
          "rowCount": 154062,
          "etag": "\"ca09883d2c97ea094e1c4a45646d78b3\"",
          "stats": {
            "snapshot_date": {
              "min": "2026-09-02",
              "max": "2026-10-23"
            },
            "snapshot_hour": {
              "min": 0,
              "max": 23
            },
            "status": {
              "min": "deficient",
              "max": "functional"
            },
            "facility_name": {
              "min": "1 Alexandria",
              "max": "Școala Gimnazială Regina Maria nr. 198"
            }
          }
        }
      ],
      "example": [
        {
          "snapshot_date": "2026-09-02T00:00:00.000Z",
          "snapshot_hour": 6,
          "snapshot_at": "2026-09-02T06:23:03.841Z",
          "facility_name": "1 C3/1",
          "facility_name_lc": "1 c3/1",
          "facility_seq": 0,
          "status": "deficient",
          "stare": "Oprire CTE Sud, alimentare din CTE Progresul, din punct de vedere hidraulic parametrii insuficienti.",
          "tip": "Deficienta ACC",
          "remediere": "18.09.2026 23:30",
          "latitude": 44.432576444788,
          "longitude": 26.164120976753
        },
        {
          "snapshot_date": "2026-09-02T00:00:00.000Z",
          "snapshot_hour": 6,
          "snapshot_at": "2026-09-02T06:23:03.841Z",
          "facility_name": "1 C5/1",
          "facility_name_lc": "1 c5/1",
          "facility_seq": 0,
          "status": "deficient",
          "stare": "Oprire CTE Sud, alimentare din CTE Progresul, din punct de vedere hidraulic parametrii insuficienti.",
          "tip": "Deficienta ACC",
          "remediere": "18.09.2026 23:30",
          "latitude": 44.422963473235,
          "longitude": 26.165034386053
        }
      ]
    }
  ],
  "generatedAt": "2026-10-23T02:15:40.644Z"
}
