Collection system
A regional wastewater collection system: eight unmanned lift stations feeding one water reclamation facility, on DNP3. Nine devices and 274 tags, and the largest tag count of the set.
Operator view | port 4012 |
|---|---|
Protocol server | port 5022 |
Devices and tags | 9 devices, 274 points |
Litmus Edge driver | DNP3 Master |
Image | water-wastewater-demo |
Scenarios
- Pump efficiency as it degrades. Energy per million gallons drifts up long before anything alarms. The fleet view makes the worst station obvious, and the comparison against the others is what turns it into a work order.
- A sanitary sewer overflow, before it is reportable. Wet well level, pump availability and inflow together say an overflow is coming. Seeing it while there is still freeboard is the difference between a callout and a fine.
- The compliance report. An NPDES-style report assembled from what was actually measured, rather than transcribed at the end of the month.
Overview
Litmus Edge Manager manages Edges rather than devices, so a fleet of RTUs behind a single Edge is invisible to it. This solution is therefore designed to be split across two Litmus Edges managed from one Litmus Edge Manager, one per district, with a shared lift station Digital Twin model authored in LEM and pushed to both.
It also runs against a single Edge, which is the simpler setup and what the compose file below does. The two-district arrangement is worth showing when the question is fleet management rather than a single plant.
What it creates on Litmus Edge
Nine DeviceHub devices, eight lift stations and the treatment works, with 274 tags over DNP3. A shared lift station twin model with an instance per station. Analytics groups behind pump efficiency, overflow risk and permit compliance.
Requirements
- Litmus Edge 4.0.x, reachable over HTTPS from the host running the solution
- An API token for that Edge, or a username and password, or a client id and secret
- Docker, and Docker Compose for the compose deployment
- A network path in both directions: the solution reaches the Edge's API, and the Edge reaches this host on the protocol port
Deploy
The solution ships two ways. Use the registry if the host can reach Google Artifact Registry, and the downloaded archive if it cannot.
Option 1: pull from the registry
Requires a read-only registry credential, supplied by Litmus separately.
cat key.json | docker login -u _json_key --password-stdin https://us-docker.pkg.devSave this as docker-compose.yml:
services:
water-wastewater:
image: us-docker.pkg.dev/litmus-customer-facing/litmus-solutions/water-wastewater-demo:0.3.0
container_name: water-wastewater-demo
restart: unless-stopped
ports:
- target: 4012
published: 4012
protocol: tcp
- target: 5022
published: 5022
protocol: tcp
environment:
# Fill these in.
EDGE_URL: "${EDGE_URL:-}"
EDGE_API_TOKEN: "${EDGE_API_TOKEN:-}"
SIM_HOST: "${SIM_HOST:-auto}"
APPLY_ON_START: "${APPLY_ON_START:-1}"
EDGE_VERIFY_TLS: "${EDGE_VERIFY_TLS:-0}"
HTTP_PORT: "4012"
DNP3_PORT: "5022"
TIME_SCALE: "60"
START_HOUR: "5.0"
LOG_LEVEL: "INFO"EDGE_URL=https://10.0.0.5
EDGE_API_TOKEN=your-token
SIM_HOST=10.0.0.9docker compose up -dOpen http://localhost:4012.
The page stays on its waiting panel until the Edge carries this solution's devices. That is deliberate: the simulation does not tick and no value is shown until Litmus Edge is verified to hold the devices and poll them, so nothing on screen can be mistaken for data that never made the trip. With APPLY_ON_START at its default of 1 the solution configures the Edge itself on startup, which takes 30 to 60 seconds. If you set it to 0, or the apply failed, press Apply to Edge in the page header.
Option 2: load the downloaded archive
Download water-wastewater-demo-0.3.0-amd64.tar.gz from the solution's page on portal.litmus.io. The archive is the container image, not a source bundle, and needs no registry access.
docker load -i water-wastewater-demo-0.3.0-amd64.tar.gzdocker load prints the image it added:
Loaded image: us-docker.pkg.dev/litmus-customer-facing/litmus-solutions/water-wastewater-demo:0.3.0That reference is the one the compose file above already names, so the same docker-compose.yml and .env now work offline with no docker login:
docker compose up -dTo run it without Compose, pass the same three values on the command line:
docker run -d \
--name water-wastewater-demo \
--restart unless-stopped \
-p 4012:4012 \
-p 5022:5022 \
-e EDGE_URL=https://10.0.0.5 \
-e EDGE_API_TOKEN=your-token \
-e SIM_HOST=10.0.0.9 \
us-docker.pkg.dev/litmus-customer-facing/litmus-solutions/water-wastewater-demo:0.3.0Configuration
Variable | Default | What it does |
|---|---|---|
EDGE_URL | the Docker host | Litmus Edge to configure |
EDGE_API_TOKEN | unset | token for that Edge. Or a username and password, or a client id and secret |
SIM_HOST | auto | address the Edge polls to reach this solution |
APPLY_ON_START | 1 | configure the Edge on startup |
EDGE_VERIFY_TLS | 0 | 1 checks the Edge's certificate |
TIME_SCALE | 60 | one real second is a simulated minute, so a full day of diurnal flow passes in 24 minutes |
START_HOUR | 5.0 | hour of the day the simulation starts at |
All nine outstations answer on the one DNP3 port, addressed 1 to 9, which is how a real collection system is usually polled.
Operator view
Across the top, the fleet: worst station energy, overflow events, permit compliance and stations at risk.
Below, the collection system itself. Each lift station shows its wet well level against the lag, on and off setpoints, which pumps are running, and the flow down the trunk main to the treatment works.
Because the clock runs at 60x, the diurnal flow pattern is visible in a few minutes: the morning peak fills the wells, the pumps cycle harder, and the energy per million gallons moves with it.
Faults include a pump losing efficiency, a blockage, a wet well level sensor drifting and a storm inflow.
Apply and remove
docker compose downUse Clean up in the Solutions provisioner to remove what it created on the Edge. In the two-district arrangement, cleaning is scoped per site so one district can be removed without touching the other.