Appearance
Remote Connection Management
Business Context
Business-Level Definition
A remote connection (DO — dálkový odečet / remote meter reading) is a configured remote data-acquisition channel that pulls readings automatically from a physical meter or external source, replacing manual entry for connected gauges. It produces the same underlying Reading records as manual entry (see Reading Management). The same mechanism also serves weather stations for automated climate-data ingestion. Actual data acquisition from meters and external sources is performed by a separate aggregator service; EM3 connects to it and periodically ingests what it has collected — it does not talk to meters directly.
Requirements Definition
Remote acquisition removes manual transcription for connected metering points, which is both the slowest and the most error-prone part of data collection. The value depends entirely on the data being trustworthy without a human reviewing every row, so the feature pairs automated ingestion with deterministic validation at write time, and makes visible the one event that otherwise goes unnoticed — a replaced meter starting to deliver on a new channel that nobody has connected yet.
Manual pairing of an endpoint to a gauge and client-managed connector setup are covered by separate features (Client Management's API Connectors area; Data Aggregator Administration). Recording a meter replacement is covered by Meter Replacement Flow; this feature only surfaces the candidates. Deriving consumption from power readings is covered by consumption calculation, not here.
Acceptance Criteria
- An endpoint can be paired to a gauge or to a weather station, and an attempt to pair it to both at once is rejected.
- A weather station with three endpoints (temperature, humidity, precipitation) records all three quantities, distinguished by measurement type.
- A reading collected by the aggregator for a paired endpoint appears in EM3 within one ingestion cycle, with the correct type, direction, tariff and format.
- The same segment collected on an electricity gauge and on a water gauge is stored with the type appropriate to that gauge's medium.
- Running ingestion twice over the same period does not create duplicate readings.
- Readings collected for an unpaired endpoint do not appear anywhere in the application.
- A reading whose segment is not among those expected for the paired gauge is rejected and reported, not stored.
- A zero or negative value on a cumulative series is rejected with a distinguishable error, and no partial data is written. A zero power reading is accepted, since no consumption in an interval is a legitimate measurement.
- A power reading is stored as a power reading; it is not converted into a consumption reading during ingestion.
- A user who may record readings elsewhere in the application can add a missing reading for a remote endpoint; a user who may not, cannot.
- Only the platform superadmin can bulk-delete a remote endpoint's readings — a client administrator who may delete individual readings cannot.
- An unpaired channel reporting the same installation point as an already-paired channel, but a different device serial, is flagged for review together with the channel and gauge it resembles.
- Nothing is paired, written or renamed as a result of that flag — acting on it is always a user action.
- Connecting the new channel to a gauge that still holds the retired one succeeds in a single step, leaving the gauge with exactly one live channel and no interval in which it has none.
- Readings from a production source (e.g. photovoltaic) are stored and displayed as production, not as consumption.
Loom Link
N/A — not available in the source material.
Technical Context
User Stories / Use Cases
- As an energy manager, I want readings from connected meters to arrive automatically, so that I don't transcribe them by hand.
- As an energy manager, I want an implausible value to be refused at the moment it is written, so that a broken meter doesn't quietly distort a consumption series.
- As an energy manager, I want to add a missing reading myself when the connection was down, so that a gap doesn't stay in the series until the next cycle.
- As an administrator, I want to delete a range of readings for one endpoint at once, so that I can clear out a batch that arrived wrong without deleting them one by one.
- As an administrator, I want to be told when a new channel appears that looks like a replacement for a meter already being tracked, so that its data doesn't sit unconnected while the series quietly goes dead.
- As an administrator, I want to move a gauge from its retired channel to the new one in a single step, so that I don't have to remember to disconnect the old one first and risk leaving the gauge with no channel at all.
- As a platform administrator, I want to attach a shared reference weather station to a connector once, so that every tenant using it gets the same climate data.
UI/UX Design
Ingestion itself is a background process with no user interface. Screens affected by this feature are the remote endpoint detail (manual reading entry, bulk deletion) and the unmatched endpoints panel, where a channel that looks like a replacement is flagged alongside the channel and gauge it resembles, and where connecting it is offered as a replacement rather than a plain pairing.
Pending design. Screen layouts, the confirmation pattern for bulk deletion, how validation errors are surfaced on manual entry, and how a replacement flag is presented, acted on and dismissed are not yet specified.
Functional Requirements
FR1 — Endpoint pairing
- An endpoint pairs to exactly one target — either a gauge or a weather station — never both.
- Stored data allows a target to hold several endpoints at once, and real data routinely does: after a meter replacement a gauge holds both its retired channel and its current one. Nothing in storage limits a target to one endpoint, and nothing may be built on the assumption that it does.
- Establishing a pairing is narrower than storage allows. A gauge that already holds a live pairing does not accept a second one as a plain pairing — that would silently split the gauge's incoming data across two channels. Connecting a channel to such a gauge is done as a replacement instead (FR8).
- The referenced target must exist. This is validated at the application layer, with no database foreign key, consistently for both target kinds.
FR2 — Weather station channels
A weather station may have one endpoint per measured quantity (e.g. temperature, humidity, precipitation). The quantities are distinguished by the measurement type recorded on each endpoint's readings, not by a dedicated column per quantity. Because each channel carries a different quantity, these are parallel pairings rather than competing ones, and the single-live-pairing rule in FR1 does not apply to them.
FR3 — Ownership and assignment authority
- Connectors serving weather stations with no tenant owner (globally shared reference stations) are represented through a dedicated system-level tenant, so the same connector and reading pipeline applies uniformly to tenant-owned and global stations alike.
- Pairing a connection to a tenant-owned weather station is restricted to the platform superadmin (Porsenna admin); tenants cannot self-assign a connection to their own stations. This is deliberately conservative and may be relaxed if a need for tenant-level self-service emerges.
FR4 — Automatic ingestion
- Readings collected by the aggregator for a paired endpoint are ingested automatically and periodically — not on demand, and not by the aggregator pushing into EM3.
- Each collected record is written through the same reading write path used for manual entry, so it is subject to the same validation rules.
- Re-ingesting an already-processed record produces no duplicate reading.
- Readings collected for an endpoint that is not currently paired to any target are not ingested.
FR5 — Segment mapping and expected segments
- Each collected record carries a segment code. The segment determines the reading's direction, tariff and format; the measured quantity (type) additionally depends on the paired gauge's medium — the same segment on an electricity gauge and on a water gauge yields a different type. The canonical mapping is documented on a shared reference page (see Data below).
- A gauge declares, through its purpose and medium, which segments are expected for it. A reading whose segment is not among those expected for the paired gauge is refused rather than stored, so a misconfigured pairing surfaces immediately instead of producing a plausible-looking but wrong series.
- For an endpoint paired to a
kvpgauge or to a weather station,purposeis null, so the expected-segment check cannot be driven by it. For these targets the expected set is fixed by the target itself — temperature, humidity and CO₂ (and, once defined, rainfall) — rather than by a configured purpose. A segment outside this set is refused the same way as for any other gauge. - Because of the above, gauge configuration is a prerequisite for ingesting that gauge's readings.
- Segments representing own production and grid delivery are mutually exclusive on any one gauge — a gauge measuring its own production never also reports delivery, and vice versa. The expected-segment rule above is what keeps them apart.
FR6 — A reading is rejected when
- its value is zero on a cumulative series,
- its value is negative on a cumulative series — independent of whether an earlier reading exists in that series,
- its segment is not expected for the paired gauge (FR5),
- its segment has no mapping at all.
Non-cumulative quantities, notably power, are not subject to the zero check — a zero reading there is a legitimate measurement. Every rejection is reported (see Logging); nothing is discarded silently.
This rejection is unconditional and takes precedence over gauge-level anomaly flagging (gauge.allowsNegative): on a cumulative series, a negative value never reaches the anomaly-detection stage, and allowsNegative cannot re-admit it. allowsNegative governs anomaly flagging only for non-cumulative readings, where a negative value is not a data-integrity impossibility.
FR7 — Measured quantities are stored as measured
- Readings from energy-production sources (photovoltaic and similar) follow the same path and rules as consumption readings. A production source is a gauge carrying export direction on the building node — neither a separate entity nor a separate ingestion branch.
- Power readings are stored as power, with their own measurement format. They are not converted into consumption during ingestion; deriving consumption from power, and handling metering points that report power only, belongs to consumption calculation.
FR8 — Surfacing and acting on a likely meter replacement
A physical meter replacement does not show up as a changed value on the existing channel. The retired meter's channel simply stops delivering, and a new, unpaired channel appears reporting the same installation point under a different device serial. Until somebody connects that new channel, its data is collected but never reaches the application, and the gauge's series silently ends.
- An unpaired channel whose reported installation point matches that of an already-paired channel on the same connector, and whose device serial differs from it, is flagged as a likely replacement. The flag names the channel it resembles and the gauge that one is paired to.
- The flag is advisory. Nothing is paired, no reading is written, and no serial number changes as a result of it. Acting on it is a user action.
- Acting on it means moving the gauge from its retired channel to the new one. This is a single operation — the existing pairing is released and the new one established together — not a disconnect followed by a separate connect. Done in two steps the gauge would be left with no channel in between, and a forgotten second step would leave it worse off than before the flag was raised.
- The released channel is not deleted. It keeps the readings already collected through it, and the gauge keeps its full history across both channels (FR1).
- A shared installation point is not proof of a replacement — one installation point legitimately carries several meters, and two channels of the same meter may run in parallel during a handover. The flag is a prompt to look, never a decision.
- Only sources that report both a device serial and an installation-point identifier can produce this flag. For every other source a replacement is noticed and handled entirely manually, exactly as before.
- Recording the replacement itself — the retired meter's closing value, the new serial number and the new meter's opening value — remains the separate, explicit step described in Meter Replacement Flow. Moving the channel does not perform it.
FR9 — Working with an endpoint's readings by hand
- A user may manually record a reading against a specific remote endpoint if they may record readings elsewhere in the application. This is the same binary gate already used for recording, editing and deleting readings — either a user may, or may not, with no per-gauge or per-endpoint gradation. The reading is subject to exactly the same validation as any other (FR5, FR6).
- A gauge with
allowsManualReading = falserejects a manual reading submission outright, before FR5/FR6 validation runs — manual entry is unavailable for that gauge regardless of the submitter's permission. - Bulk deletion of an endpoint's readings over a given time range is restricted to the platform superadmin (Porsenna admin) — the same authority level as connection assignment in FR3, and deliberately narrower than manual entry, because the action is irreversible and spans a whole range at once. A client administrator who may delete individual readings cannot bulk-delete an endpoint's.
- Both gates are deliberately conservative for the first version and may be revisited once the roles and permissions model is designed.
Non-Functional Requirements
Ingestion of collected readings runs on a periodic cycle rather than in real time, in line with how the aggregator itself collects data — daily to several times a day per source, never real-time. Reading a batch and writing it must be atomic per batch: a batch that fails validation partway leaves no partial rows behind. Replacement flagging (FR8) is read-only: it derives its result from endpoint metadata already held and never writes to reading or gauge data, so it introduces no coupling from ingestion into the asset domain. Moving a gauge between channels is atomic — the gauge is never left holding none, and never holding two live ones.
API Analysis
Ingestion of collected readings (FR4) has no external API — it is an internal, scheduled process. Pairing endpoints, including moving a gauge to a replacement channel, are documented under the Client Management (API Connectors) and Data Aggregator Administration features.
POST /v1/remote-connections/:endpointId/readings Manually record a reading for an endpoint
DELETE /v1/remote-connections/:endpointId/readings Bulk-delete readings in a date range (platform superadmin only)Domain Model (ER diagram) & Data Attribute Table
No ER diagram in source material. A remote connection has no dedicated entity of its own — it is realised through the endpoint and its parent connector. Related entity pages (Confluence, not yet migrated into this repo's Entity DAT catalog):
- remoteEndPoint — the paired channel;
.gaugeIdand.weatherStationIdare the two mutually exclusive pairing targets (FR1); the device serial and installation-point identifier reported by the source are what FR8 matches on. - remoteSource — the registered connector the endpoint belongs to.
- reading (gauge reading entity) — where ingested values land;
.sourceidentifies them as remotely acquired, and.type,.direction,.tariffand.formatare the attributes set by segment mapping. - gauge — the metering point a reading belongs to;
.mediumdetermines the reading's type (FR5). - weatherStation — the alternative pairing target.
- Segment/value mapping lookup tables assigning the mapping described under Data below.
Data
Each collected reading arrives from the aggregator as a segment code, a value and a timestamp, scoped to an endpoint. The segment is an integer drawn from a catalogue shared across all connectors; every connector selects its values from that same catalogue.
The canonical segment mapping (segment → type, direction, tariff) is defined on a shared reference page and is not repeated here. Ingestion uses that mapping as-is. Two things it does not resolve on its own:
- Type depends on the gauge's medium. The canonical mapping notes this for the basic-consumption segment: the same segment is an energy quantity on an electricity, gas or heat gauge, and a volume quantity on a water or fuel gauge. Ingestion therefore reads the paired gauge's medium, not the segment alone.
- Non-energy quantities are not covered. The canonical mapping covers only energy and power segments. Segments for indoor-environment and climate quantities — temperature, humidity, CO₂ and rainfall — reach EM3 through the same pipeline but have no entry there. They carry no direction or tariff, and their format is average. Which target they land on (weather station or indoor-environment gauge) follows from the endpoint's pairing, not from the segment.
Identity metadata — the device serial and the identifier of the installation point — arrives on the endpoint rather than on individual readings, and only from sources that report it. It is what FR8 matches on.
Open items on the mapping
- Rainfall has no measurement type. The existing set (energy, power, volume, temperature, humidity, CO₂) has no value that fits — rainfall is measured as a depth, so volume would be both semantically wrong and confusable with water metering. A new value is needed before rainfall can be ingested. Until then, rainfall segments have no mapping and are refused under FR6.
- Grid-delivery segment is mapped as power on the canonical page. The acquisition catalogue and the legacy system both define that segment as delivered energy (dodávka / přetoky — grid delivery / feed-in, in kWh), measured on a bidirectional meter — not as power. This looks like an error on the canonical page rather than a decision. Needs confirming and correcting there, not here. Low urgency for ingestion specifically: no connector currently produces that segment automatically; it arises only from manual import.
Not every segment appears on every source. The table below records which segments each source can currently deliver, and which of them report identity metadata, as an aid to testing rather than as a constraint on the mapping.
| Source | Segments delivered | Reports identity (FR8) |
|---|---|---|
| Softlink | 1, 2, 3, 6, 7, 8, 9, 11 | Yes — serial and installation point |
| OICT | 2, 3, 7, 8, 9 | No |
| EGD | 11, 14 | No |
| Meteo | 6, 7, 8 | No |
| PLC | 1, 2 | No |
| Scvk | 1, 7 | No |
| SolarEdge | 4 | No |
| Mervis, Miko, Satt, Slavos | 1 | No |
Test Data
N/A — not covered in source material.
Logging
Logged at .info:
- Start and completion of each ingestion cycle, with the number of records read, written and skipped as already-present.
- Every rejected reading, with the endpoint and the reason for rejection.
- Every segment that cannot be mapped, or that is not expected for the paired gauge, with the endpoint and the segment code — either indicates a source or a gauge configuration that has drifted.
- Every channel newly flagged as a likely replacement, naming both channels and the gauge involved.
- Every move of a gauge from one channel to another, naming both channels, the gauge and the acting user.
- Manual reading entry and bulk deletion, with the acting user and the affected range.
Logged at .debug: per-record segment-to-attribute mapping decisions, and the resolved endpoint pairing used for each batch.
Monitoring
An ingestion cycle that fails, or a source that stops delivering, must be visible without a user noticing missing data first. A paired channel that goes quiet while an unpaired one on the same installation point starts delivering is the signature of an unhandled replacement and should be visible the same way.
Caching
N/A — not covered in source material.
Backward Compatibility and Migration
Weather stations previously stored a free-standing, unvalidated connection reference. Existing values are reconciled during migration:
- Each existing value is resolved against the registered connectors.
- Resolvable → migrated to the corresponding endpoint pairing under the current model.
- Unresolvable (no matching connector) → cleared, and the station is flagged in a migration report for manual review.
Readings already stored against a gauge are unaffected — remote ingestion adds rows to the same series rather than replacing it, so existing consumption history stays intact.
Migrated pairings routinely include gauges carrying more than one channel — a retired one and a current one. Any assumption of a single channel per gauge would fail on existing data (FR1).
Legal Context
N/A — not addressed in the source Confluence page; migrated as a reference copy without new legal analysis.
Cybersecurity Considerations
N/A — not addressed in the source Confluence page; migrated as a reference copy without new security analysis.
Risk Assessment
N/A — not addressed in the source Confluence page; migrated as a reference copy without new risk analysis.
Auditing, Reporting & Measurement
N/A — not addressed in the source Confluence page beyond the Logging entries above.
Migrated as a reference copy from Confluence page "Remote Connection Management" (id 676036610). Content reorganized to fit this repo's feature-doc template; not re-analyzed against the current codebase. Two open items on the canonical segment mapping (rainfall measurement type; grid-delivery segment mapping) are carried over unresolved, as flagged in the source.