GridWorks SpaceHeat SCADA

Intended for running a heat pump thermal storage space heating system in a house, and doing this transactively.
https://github.com/thegridelectric/gridworks-scada

Category: Consumption
Sub Category: Buildings and Heating

Last synced: about 9 hours ago
JSON representation

Repository metadata

GridWorks SCADA for space heating

README.md

GridWorks SCADA

Tests
Codecov

========

This repository is for GridWorks contributors developing SCADA software for transactive heat pump thermal storage systems.

The software runs residential heat-pump-based space-heating systems with thermal storage and coordinates operation with electric grid conditions. In practice, that means shifting energy use toward lower-cost or grid-favorable times while maintaining occupant comfort.

This repository is part of a larger GridWorks framework. It typically operates alongside a cloud-based actor called the LeafTransactiveNode, which provides higher-level dispatch and coordination. Internally, the code follows an actor-based architecture: many focused components communicate through messages, with each actor responsible for a limited operational domain.

This project is funded by Efficiency Maine.

Quick Start

For most contributors:

  1. Start with the Testing section. For many small changes, running tests locally is enough.
  2. Run SCADA locally with .env if needed. This is useful when debugging runtime behavior or configuration issues.
  3. Use RabbitMQ only for integration scenarios. This is typically needed when simulating upstream GridWorks/cloud behavior or multi-process local environments.

Testing

  1. Start the local test mosquitto broker Run from the repo root:
mosquitto -c tests/config/local_mosquitto.conf -v &

If you already run Mosquitto through Homebrew as a background service, stop that first so ports are not already in use.

  1. Create venv: Run ./tools/mkenv.sh. This creates gw_spaceheat/venv/
    • (On a Raspberry Pi use ./tools/mkenv-pi.sh.)
  2. Activate venv: source gw_spaceheat/venv/bin/activate
  3. Export pythonpath: include gw_spaceheat in the pythonpath
    • Linux/mac: export PYTHONPATH=[PATH TO]/gridworks-scada/gw_spaceheat:$PYTHONPATH
    • Windows in powershell: $env:PYTHONPATH="C:\Users\Joe\Coding\gridworks-scada\gw_spaceheat;$env:PYTHONPATH"
  4. Run tests: pytest -v

Test Environment Notes

Although the larger GridWorks ecosystem uses message-passing through a RabbitMQ broker, SCADA-only development and pytest runs do not require RabbitMQ.

The SCADA process conceptually talks to two MQTT brokers:

  • upstream / gridworks_mqtt — normally the cloud-side GridWorks broker
  • local / local_mqtt — the LAN-side broker used for local actors such as SCADA2

For local testing, both are replaced with a simple cleartext Mosquitto setup.

Tests assume a local MQTT broker with an upstream broker at localhost:1883
and a local/downstream broker at localhost:18831.

Optional Shell Alias

    alias gw="source $HOME/Coding/gridworks-scada/gw_spaceheat/venv/bin/activate \
    && cd $HOME/Coding/gridworks-scada \
    && export PYTHONPATH=$HOME/Coding/gridworks-scada/gw_spaceheat:$PYTHONPATH"

Test Bootstrap Behavior

pytest automatically uses repo-owned local defaults from:

  • tests/config/.env-local
  • tests/config/hardware-layout.json

Your normal .env file is not used during pytest unless a specific test explicitly opts into it.

CI Testing

The CI workflow uses a different broker/certificate setup in
.github/workflows/ci.yaml. It uses a separate broker/certificate setup and exercises TLS paths.

If you need to understand or regenerate the test CA, broker certs, or client certs,
look at the gridworks-cert repo first. This
repository relies on gwcert conventions and test CA paths from that toolchain.

CLI

SCADA includes a lightweight command-line tool called gws that is useful for both development and production tasks.

Install the CLI

./tools/install-gws.sh

Common Commands

Show the current resolved configuration:

gws config

This is often the fastest way to verify paths, environment variables, and active settings. For example:

hardware_layout=PosixPath('[HOME]/.config/gridworks/scada/hardware-layout.json')

Preview what SCADA would do without starting it:

gws run --dry-run

Start SCADA locally:

gws run

Practical Use

During development, gws config and gws run --dry-run are especially useful for confirming that your hardware layout, .env, and local broker settings are being picked up correctly.

Running SCADA Locally with .env

Scada is designed to operate with a .env variable and a hardware layout. You
may choose to use these while running locally. Be aware that they are NOT used in tests.

For development purposes I recommend updating the hardware layout location in your local .env file. To do this for the first time , **copy the existing .env-template over to .env. Then rerun gws config and confirm that the layout is now tests/config/hardware-layout.json.

Creating your own dev hardware layout

In a sibling directory clone the tlayouts directory. Then:

  • While in the virtual env for this repository, navigate to tlayouts.
  • Run gen_orange.py

This will generate a simulated hardware layout in outputs/orange.generated.json

  • Update your .env to include:
SCADA_PATHS__HARDWARE_LAYOUT="../tlayouts/output/orange.generated.json"
LTN_PATHS__HARDWARE_LAYOUT="../tlayouts/output/orange.generated.json"

Dependencies

Add package requirements in:

  • gw_spaceheat/requirements/dev.in — development / CI
  • gw_spaceheat/requirements/drivers.in — Raspberry Pi only
  • gw_spaceheat/requirements/base.in — all environments

Then run:

tools/pipc.sh

Advanced: Using RabbitMQ for Multi-Repo Integration

If you want to do cross-repo tests you may want to use the dev rabbit broker at https://github.com/thegridelectric/gridworks-base?tab=readme-ov-file#dev-rabbit-broker. Follow instructions there.

RabbitMQ must expose its MQTT plugin so SCADA can connect using MQTT. Three steps for getting the docker rabbit instance to enable mqtt:

docker exec -it gw-dev-rabbit rabbitmq-plugins enable rabbitmq_mqtt
docker exec -it gw-dev-rabbit rabbitmqctl restart_app
docker exec -it gw-dev-rabbit rabbitmq-plugins list

And confirm:
[E*] rabbitmq_mqtt 3.9.13

(Troubleshooting how to get this into the docker yaml file over in gridworks-base)

Test mqtt access via mqtt_sub:

mosquitto_sub -h localhost -p 1885 -u smqPublic -P smqPublic -t "#" -v

Should see an mqtt-subscription-XXX show up on the rabbit admin panel http://localhost:15672/#/queues.

Linting

Run:

ruff check

Ruff is advisory today and does not yet pass.

Admin

Install:

uv tool install gridworks-admin

Update:

uv tool update gridworks-admin

Run locally:

gwa watch

See the packages directory README.md for more information.

Raspberry Pi Service

Install:

./service/install

Status:

gwstatus

Start:

gwstart

Pause:

gwpause

Stop:

gwstop

Additional Documentation

For deployment, TLS, and editor setup details, see:

  • docs/tls.md
  • docs/provisioning.md
  • docs/editor-setup.md

License

Distributed under the terms of the MIT license,
this repository is free and open source software.


Owner metadata


GitHub Events

Total
Last Year

Committers metadata

Last synced: 2 days ago

Total Commits: 2,271
Total Committers: 6
Avg Commits per committer: 378.5
Development Distribution Score (DDS): 0.555

Commits in past year: 482
Committers in past year: 3
Avg Commits per committer in past year: 160.667
Development Distribution Score (DDS) in past year: 0.529

Name Email Commits
Jessica Millar j****r@g****m 1011
thdfw t****w@g****m 665
Andrew Schweitzer s****2@g****m 516
stickler-ci s****t@s****m 63
Preethi Vaidyanathan p****i@g****m 15
Jessica Millar j****a@j****l 1

Committer domains:


Issue and Pull Request metadata

Last synced: 2 days ago

Total issues: 7
Total pull requests: 151
Average time to close issues: 1 day
Average time to close pull requests: 2 days
Total issue authors: 2
Total pull request authors: 3
Average comments per issue: 0.57
Average comments per pull request: 0.16
Merged pull request: 100
Bot issues: 0
Bot pull requests: 0

Past year issues: 7
Past year pull requests: 121
Past year average time to close issues: 1 day
Past year average time to close pull requests: 3 days
Past year issue authors: 2
Past year pull request authors: 3
Past year average comments per issue: 0.57
Past year average comments per pull request: 0.18
Past year merged pull request: 75
Past year bot issues: 0
Past year bot pull requests: 0

More stats: https://issues.ecosyste.ms/repositories/lookup?url=https://github.com/thegridelectric/gridworks-scada

Top Issue Authors

  • anschweitzer (6)
  • jessicamillar (1)

Top Pull Request Authors

  • jessicamillar (65)
  • thdfw (47)
  • anschweitzer (39)

Top Issue Labels

  • admin (3)
  • ops (3)

Top Pull Request Labels

  • DRAFT PR (2)
  • admin (2)
  • ops (2)

Dependencies

gw_spaceheat/requirements/base.txt pypi
  • numpy ==1.22.4
  • paho-mqtt ==1.6.1
  • pendulum ==2.1.2
  • pika ==1.1.0
  • python-dateutil ==2.8.2
  • python-dotenv ==0.20.0
  • pytz ==2022.1
  • pytzdata ==2020.1
  • six ==1.16.0
gw_spaceheat/requirements/drivers.txt pypi
  • numpy ==1.22.4
  • paho-mqtt ==1.6.1
  • pendulum ==2.1.2
  • pika ==1.1.0
  • pymodbus ==2.5.3
  • pyserial ==3.5
  • python-dateutil ==2.8.2
  • python-dotenv ==0.20.0
  • pytz ==2022.1
  • pytzdata ==2020.1
  • six ==1.16.0
  • smbus2 ==0.4.1
.github/workflows/ci.yaml actions
  • actions/checkout v2 composite
  • actions/download-artifact v2 composite
  • actions/setup-python v2 composite
  • actions/upload-artifact v3 composite
  • canastro/copy-file-action master composite
  • codecov/codecov-action v3.1.0 composite
  • namoshek/mosquitto-github-action v1 composite
gw_spaceheat/requirements/dev.txt pypi
  • appnope ==0.1.3 development
  • asttokens ==2.0.5 development
  • attrs ==21.4.0 development
  • backcall ==0.2.0 development
  • black ==22.3.0 development
  • build ==0.8.0 development
  • certifi ==2022.9.14 development
  • charset-normalizer ==2.1.1 development
  • click ==8.1.3 development
  • commonmark ==0.9.1 development
  • coverage ==6.4.1 development
  • decorator ==5.1.1 development
  • docutils ==0.19 development
  • executing ==0.8.3 development
  • gridworks-protocol ==0.2.2 development
  • idna ==3.4 development
  • iniconfig ==1.1.1 development
  • ipython ==8.0.0 development
  • isort ==5.10.1 development
  • jedi ==0.18.1 development
  • matplotlib-inline ==0.1.3 development
  • mypy ==0.961 development
  • mypy-extensions ==0.4.3 development
  • nose ==1.3.7 development
  • numpy ==1.22.4 development
  • packaging ==21.3 development
  • paho-mqtt ==1.6.1 development
  • parso ==0.8.3 development
  • pathspec ==0.9.0 development
  • pendulum ==2.1.2 development
  • pep517 ==0.12.0 development
  • pexpect ==4.8.0 development
  • pickleshare ==0.7.5 development
  • pika ==1.1.0 development
  • pip-tools ==6.9.0 development
  • platformdirs ==2.5.2 development
  • pluggy ==1.0.0 development
  • prompt-toolkit ==3.0.29 development
  • ptyprocess ==0.7.0 development
  • pure-eval ==0.2.2 development
  • py ==1.11.0 development
  • pydantic ==1.10.2 development
  • pygments ==2.12.0 development
  • pymodbus ==2.5.3 development
  • pyparsing ==3.0.9 development
  • pyserial ==3.5 development
  • pytest ==7.1.2 development
  • pytest-asyncio ==0.19.0 development
  • pytest-sugar ==0.9.5 development
  • python-dateutil ==2.8.2 development
  • python-dotenv ==0.20.0 development
  • pytz ==2022.1 development
  • pytzdata ==2020.1 development
  • requests ==2.28.1 development
  • result ==0.8.0 development
  • rich ==12.5.1 development
  • rich-cli ==1.8.0 development
  • rich-rst ==1.1.7 development
  • six ==1.16.0 development
  • smbus2 ==0.4.1 development
  • stack-data ==0.2.0 development
  • termcolor ==1.1.0 development
  • textual ==0.1.18 development
  • tomli ==2.0.1 development
  • traitlets ==5.1.1 development
  • typing-extensions ==4.2.0 development
  • urllib3 ==1.26.12 development
  • wcwidth ==0.2.5 development
  • wheel ==0.37.1 development
  • xdg ==5.1.1 development
gw_spaceheat/requirements/test.txt pypi
  • attrs ==21.4.0 test
  • black ==22.3.0 test
  • click ==8.1.3 test
  • coverage ==6.4.1 test
  • iniconfig ==1.1.1 test
  • mypy ==0.961 test
  • mypy-extensions ==0.4.3 test
  • nose ==1.3.7 test
  • packaging ==21.3 test
  • pathspec ==0.9.0 test
  • platformdirs ==2.5.2 test
  • pluggy ==1.0.0 test
  • py ==1.11.0 test
  • pyparsing ==3.0.9 test
  • pytest ==7.1.2 test
  • pytest-asyncio ==0.19.0 test
  • tomli ==2.0.1 test
  • typing-extensions ==4.2.0 test
.github/workflows/release.yml actions
  • actions/checkout v4 composite
  • actions/setup-python v5.6.0 composite
  • astral-sh/setup-uv v6 composite
  • release-drafter/release-drafter v6.0.0 composite
  • salsify/action-detect-and-tag-new-version v2.0.3 composite
packages/gridworks-admin/pyproject.toml pypi
  • gridworks-proactor >=4.1.9
  • gridworks-scada-protocol >=1.2.0
  • numpy >=2.3.3
  • paho-mqtt >=2.1.0
  • pydantic >=2.11.9
  • python-dotenv >=1.1.1
  • result >=0.9.0
  • rich >=14.1.0
  • textual >=6.1.0
  • typer >=0.17.4
packages/gridworks-scada-protocol/pyproject.toml pypi
  • gridworks-protocol >=1.3.3,<2.0.0
  • transitions >=0.9.3
packages/gridworks-admin/uv.lock pypi
  • aiohappyeyeballs 2.6.1
  • aiohttp 3.12.15
  • aiosignal 1.4.0
  • annotated-types 0.7.0
  • attrs 25.3.0
  • click 8.2.1
  • colorama 0.4.6
  • frozenlist 1.7.0
  • gridworks 1.5.6
  • gridworks-admin 1.0.8
  • gridworks-proactor 4.1.9
  • gridworks-protocol 1.3.3
  • gridworks-scada-protocol 1.1.1
  • idna 3.10
  • linkify-it-py 2.0.3
  • markdown-it-py 4.0.0
  • mdit-py-plugins 0.5.0
  • mdurl 0.1.2
  • multidict 6.6.4
  • numpy 2.3.3
  • paho-mqtt 2.1.0
  • platformdirs 4.4.0
  • propcache 0.3.2
  • pydantic 2.11.9
  • pydantic-core 2.33.2
  • pydantic-extra-types 2.10.5
  • pydantic-settings 2.10.1
  • pygments 2.19.2
  • python-dotenv 1.1.1
  • pytz 2024.2
  • result 0.9.0
  • rich 14.1.0
  • shellingham 1.5.4
  • six 1.17.0
  • textual 6.1.0
  • transitions 0.9.3
  • typer 0.17.4
  • typing-extensions 4.15.0
  • typing-inspection 0.4.1
  • uc-micro-py 1.0.3
  • xdg 6.0.0
  • yarl 1.20.1
packages/gridworks-scada-protocol/uv.lock pypi
  • annotated-types 0.7.0
  • gridworks 1.5.6
  • gridworks-protocol 1.3.0
  • gridworks-scada-protocol 1.0.1
  • idna 3.10
  • multidict 6.6.4
  • propcache 0.3.2
  • pydantic 2.11.9
  • pydantic-core 2.33.2
  • pydantic-extra-types 2.10.5
  • python-dotenv 1.1.1
  • pytz 2024.2
  • six 1.17.0
  • transitions 0.9.3
  • typing-extensions 4.15.0
  • typing-inspection 0.4.1
  • yarl 1.20.1
pyproject.toml pypi

Score: 5.762051382780177