{"id":48495302,"url":"https://github.com/openedi/oedisi-components","last_synced_at":"2026-04-07T12:01:45.313Z","repository":{"id":70897258,"uuid":"480869981","full_name":"openEDI/oedisi-components","owner":"openEDI","description":"Minimum working example for oedisi API","archived":false,"fork":false,"pushed_at":"2026-04-02T20:05:29.000Z","size":54056,"stargazers_count":8,"open_issues_count":34,"forks_count":2,"subscribers_count":11,"default_branch":"main","last_synced_at":"2026-04-03T06:00:58.475Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/openEDI.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-04-12T15:33:48.000Z","updated_at":"2026-04-02T19:33:22.000Z","dependencies_parsed_at":null,"dependency_job_id":"31a08889-c7cf-4d78-b09d-31ceb41cd00d","html_url":"https://github.com/openEDI/oedisi-components","commit_stats":null,"previous_names":["openedi/oedisi-example"],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/openEDI/oedisi-components","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openEDI%2Foedisi-components","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openEDI%2Foedisi-components/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openEDI%2Foedisi-components/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openEDI%2Foedisi-components/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/openEDI","download_url":"https://codeload.github.com/openEDI/oedisi-components/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openEDI%2Foedisi-components/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31511784,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-07T03:10:19.677Z","status":"ssl_error","status_checked_at":"2026-04-07T03:10:13.982Z","response_time":105,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-04-07T12:01:40.203Z","updated_at":"2026-04-07T12:01:45.276Z","avatar_url":"https://github.com/openEDI.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# oedisi-example\n\n[![Main - Integration Tests](https://github.com/openEDI/oedisi-example/actions/workflows/test-api.yml/badge.svg)](https://github.com/openEDI/oedisi-example/actions/workflows/test-api.yml)\n[![Main - Docker Build Test](https://github.com/openEDI/oedisi-example/actions/workflows/docker-test.yml/badge.svg)](https://github.com/openEDI/oedisi-example/actions/workflows/docker-test.yml)\n[![Main - Unit Tests](https://github.com/openEDI/oedisi-example/actions/workflows/unit-test-federates.yml/badge.svg)](https://github.com/openEDI/oedisi-example/actions/workflows/unit-test-federates.yml)\n\nThis example shows how to use the GADAL api to manage simulations. We also\nuse it as a testing ground for the testing the combination of feeders,\nstate estimation, and distributed OPF.\n\n## Component Status\n\n| Component | Version | Tests | Config files | Docker | Maintainer |\n|-----------|---------|-------|--------------|--------|------------|\n| **Broker** | ![Version](https://img.shields.io/badge/dynamic/toml?url=https://raw.githubusercontent.com/openEDI/oedisi-example/main/Components/broker/pyproject.toml\u0026query=$.project.version\u0026label=version\u0026color=blue) | [![Test - Broker](https://github.com/openEDI/oedisi-example/actions/workflows/test-broker.yml/badge.svg)](https://github.com/openEDI/oedisi-example/actions/workflows/test-broker.yml) | [![Verify Components](https://github.com/openEDI/oedisi-example/actions/workflows/verify-components.yml/badge.svg)](https://github.com/openEDI/oedisi-example/actions/workflows/verify-components.yml) | [![Verify Dockerfiles](https://github.com/openEDI/oedisi-example/actions/workflows/verify-dockerfiles.yml/badge.svg)](https://github.com/openEDI/oedisi-example/actions/workflows/verify-dockerfiles.yml) | Joseph.McKinsey@nlr.gov |\n| **LinDistFlow** | ![Version](https://img.shields.io/badge/dynamic/toml?url=https://raw.githubusercontent.com/openEDI/oedisi-example/main/Components/lindistflow_federate/pyproject.toml\u0026query=$.project.version\u0026label=version\u0026color=blue) | [![Test - LinDistFlow](https://github.com/openEDI/oedisi-example/actions/workflows/test-lindistflow.yml/badge.svg)](https://github.com/openEDI/oedisi-example/actions/workflows/test-lindistflow.yml) | [![Verify Components](https://github.com/openEDI/oedisi-example/actions/workflows/verify-components.yml/badge.svg)](https://github.com/openEDI/oedisi-example/actions/workflows/verify-components.yml) | [![Verify Dockerfiles](https://github.com/openEDI/oedisi-example/actions/workflows/verify-dockerfiles.yml/badge.svg)](https://github.com/openEDI/oedisi-example/actions/workflows/verify-dockerfiles.yml) | Joseph.McKinsey@nlr.gov |\n| **LocalFeeder** | ![Version](https://img.shields.io/badge/dynamic/toml?url=https://raw.githubusercontent.com/openEDI/oedisi-example/main/Components/LocalFeeder/pyproject.toml\u0026query=$.project.version\u0026label=version\u0026color=blue) | [![Test - LocalFeeder](https://github.com/openEDI/oedisi-example/actions/workflows/test-localfeeder.yml/badge.svg)](https://github.com/openEDI/oedisi-example/actions/workflows/test-localfeeder.yml) | [![Verify Components](https://github.com/openEDI/oedisi-example/actions/workflows/verify-components.yml/badge.svg)](https://github.com/openEDI/oedisi-example/actions/workflows/verify-components.yml) | [![Verify Dockerfiles](https://github.com/openEDI/oedisi-example/actions/workflows/verify-dockerfiles.yml/badge.svg)](https://github.com/openEDI/oedisi-example/actions/workflows/verify-dockerfiles.yml) | Joseph.McKinsey@nlr.gov |\n| **Measuring** | ![Version](https://img.shields.io/badge/dynamic/toml?url=https://raw.githubusercontent.com/openEDI/oedisi-example/main/Components/measuring_federate/pyproject.toml\u0026query=$.project.version\u0026label=version\u0026color=blue) | [![Test - Measuring Federate](https://github.com/openEDI/oedisi-example/actions/workflows/test-measuring.yml/badge.svg)](https://github.com/openEDI/oedisi-example/actions/workflows/test-measuring.yml) | [![Verify Components](https://github.com/openEDI/oedisi-example/actions/workflows/verify-components.yml/badge.svg)](https://github.com/openEDI/oedisi-example/actions/workflows/verify-components.yml) | [![Verify Dockerfiles](https://github.com/openEDI/oedisi-example/actions/workflows/verify-dockerfiles.yml/badge.svg)](https://github.com/openEDI/oedisi-example/actions/workflows/verify-dockerfiles.yml) | Joseph.McKinsey@nlr.gov |\n| **OMOO** | ![Version](https://img.shields.io/badge/dynamic/toml?url=https://raw.githubusercontent.com/openEDI/oedisi-example/main/Components/omoo_federate/pyproject.toml\u0026query=$.project.version\u0026label=version\u0026color=blue) | [![Test - OMOO Federate](https://github.com/openEDI/oedisi-example/actions/workflows/test-omoo.yml/badge.svg)](https://github.com/openEDI/oedisi-example/actions/workflows/test-omoo.yml) | [![Verify Components](https://github.com/openEDI/oedisi-example/actions/workflows/verify-components.yml/badge.svg)](https://github.com/openEDI/oedisi-example/actions/workflows/verify-components.yml) | [![Verify Dockerfiles](https://github.com/openEDI/oedisi-example/actions/workflows/verify-dockerfiles.yml/badge.svg)](https://github.com/openEDI/oedisi-example/actions/workflows/verify-dockerfiles.yml) | Joseph.McKinsey@nlr.gov |\n| **Recorder** | ![Version](https://img.shields.io/badge/dynamic/toml?url=https://raw.githubusercontent.com/openEDI/oedisi-example/main/Components/recorder/pyproject.toml\u0026query=$.project.version\u0026label=version\u0026color=blue) | [![Test - Recorder](https://github.com/openEDI/oedisi-example/actions/workflows/test-recorder.yml/badge.svg)](https://github.com/openEDI/oedisi-example/actions/workflows/test-recorder.yml) | [![Verify Components](https://github.com/openEDI/oedisi-example/actions/workflows/verify-components.yml/badge.svg)](https://github.com/openEDI/oedisi-example/actions/workflows/verify-components.yml) | [![Verify Dockerfiles](https://github.com/openEDI/oedisi-example/actions/workflows/verify-dockerfiles.yml/badge.svg)](https://github.com/openEDI/oedisi-example/actions/workflows/verify-dockerfiles.yml) | Joseph.McKinsey@nlr.gov |\n| **WLS** | ![Version](https://img.shields.io/badge/dynamic/toml?url=https://raw.githubusercontent.com/openEDI/oedisi-example/main/Components/wls_federate/pyproject.toml\u0026query=$.project.version\u0026label=version\u0026color=blue) | [![Test - WLS Federate](https://github.com/openEDI/oedisi-example/actions/workflows/test-wls.yml/badge.svg)](https://github.com/openEDI/oedisi-example/actions/workflows/test-wls.yml) | [![Verify Components](https://github.com/openEDI/oedisi-example/actions/workflows/verify-components.yml/badge.svg)](https://github.com/openEDI/oedisi-example/actions/workflows/verify-components.yml) | [![Verify Dockerfiles](https://github.com/openEDI/oedisi-example/actions/workflows/verify-dockerfiles.yml/badge.svg)](https://github.com/openEDI/oedisi-example/actions/workflows/verify-dockerfiles.yml) | Joseph.McKinsey@nlr.gov |\n| [**PNNL-DOPF-ADMM**](https://github.com/openEDI/pnnl-dopf-admm) | ![Version](https://img.shields.io/badge/dynamic/toml?url=https://raw.githubusercontent.com/openEDI/pnnl-dopf-admm/main/pyproject.toml\u0026query=$.project.version\u0026label=version\u0026color=blue) | [![Unit Tests](https://github.com/openEDI/pnnl-dopf-admm/actions/workflows/tests.yml/badge.svg)](https://github.com/openEDI/pnnl-dopf-admm/actions/workflows/tests.yml) | [![Verify Components](https://github.com/openEDI/pnnl-dopf-admm/actions/workflows/verify-components.yml/badge.svg)](https://github.com/openEDI/pnnl-dopf-admm/actions/workflows/verify-components.yml) | [![Verify Dockerfiles](https://github.com/openEDI/pnnl-dopf-admm/actions/workflows/verify-dockerfiles.yml/badge.svg)](https://github.com/openEDI/pnnl-dopf-admm/actions/workflows/verify-dockerfiles.yml) | tylor.slay@pnnl.gov |\n\n\n## Repository Structure\n\nThis repository is organized as a Python repository containing  components for power system co-simulation. See the **Component Status** table above for test and Docker build status for each component.\n\n**Components:**\n- **[broker](Components/broker/README.md)** - Central orchestration service for HELICS federates\n- **[lindistflow_federate](Components/lindistflow_federate/README.md)** - Optimal power flow using linear distflow\n- **[localfeeder](Components/LocalFeeder/README.md)** - OpenDSS-based distribution feeder simulator\n- **[measuring_federate](Components/measuring_federate/README.md)** - Sensor simulation with noise injection\n- **[omoo_federate](Components/omoo_federate/README.md)** - Online model-based optimal operation\n- **[recorder](Components/recorder/README.md)** - Data recording for co-simulation outputs\n- **[wls_federate](Components/wls_federate/README.md)** - Weighted least squares state estimation\n\n**Each component includes:**\n- `pyproject.toml` for modern Python packaging (PEP 621)\n- Comprehensive test suite with pytest\n- Individual README documentation\n- Standardized code quality tools (mypy, pytest, black, isort)\n- Dockerfile for containerization\n- GitHub Actions workflow for automated testing\n\n### Continuous Integration\n\nEach component has its own GitHub Actions workflow that:\n- Runs tests on Python 3.10 and 3.11\n- Performs type checking with mypy\n- Generates code coverage reports\n- Triggers on changes to component code\n\nAdditionally:\n- **Dockerfile Verification**: Ensures all components have valid Dockerfiles\n- **Integration Tests**: End-to-end system testing\n- **Docker Build Tests**: Validates container builds\n\n### Quick Start - Development Installation\n\nInstall all components in editable mode from the repository root:\n\n```bash\n# Install all components for development\npip install -e Components/broker -e Components/lindistflow_federate -e Components/LocalFeeder \\\n            -e Components/measuring_federate -e Components/omoo_federate \\\n            -e Components/recorder -e Components/wls_federate\n\n# Or install with dev dependencies\npip install -e \"Components/broker[dev]\" -e \"Components/lindistflow_federate[dev]\" \\\n            -e \"Components/LocalFeeder[dev]\" -e \"Components/measuring_federate[dev]\" \\\n            -e \"Components/omoo_federate[dev]\" -e \"Components/recorder[dev]\" \\\n            -e \"Components/wls_federate[dev]\"\n```\n\n### Running Tests\n\nRun all tests from the repository root:\n```bash\npytest Components/\n```\n\nRun tests for a specific component:\n```bash\npytest Components/broker/tests/\npytest Components/wls_federate/tests/\n```\n\nRun with coverage:\n```bash\npytest --cov=Components --cov-report=html Components/\n```\n\n### Code Quality\n\nThe repository uses standardized code quality tools configured in [pyproject.toml](pyproject.toml):\n\n```bash\n# Format code\nblack Components/\nisort Components/\n\n# Type checking\nmypy Components/\n\n# Linting\nflake8 Components/\n\n# Check docstrings\npydocstyle Components/\n```\n\nInstall pre-commit hooks:\n```bash\npre-commit install\n```\n\n# Install and Running Locally\n\n## Installation\n\n1. Install component dependencies. You can either:\n\n   **Option A: Install all components in editable mode** (recommended for developers)\n   ```bash\n   pip install -e Components/broker \\\n               -e Components/LocalFeeder \\\n               -e Components/measuring_federate \\\n               -e Components/recorder \\\n               -e Components/wls_federate\n   ```\n\n3. **Verify Installation**\n development tools (optional):\n   ```bash\n   pip install pytest mypy black isort flake8 pydocstyle pre-commit\n   ```\n\n## Running Simulations\n\n1. Build the simulation system:\n```bash\noedisi build --system scenarios/docker_system.json\n```\n\nThis initializes the system defined in `scenarios/test_system.json` in a `build` directory.\n\nYou can specify your own directory with `--build-dir` and your own system json\nwith `--system`.\n\n2. Run `oedisi run`\n\n3. Analyze the results using `python post_analysis.py`\n\nThis computes some percentage relative errors in magnitude (MAPE) and angle (MAE),\nas well as plots in `errors.png`, `voltage_magnitudes_0.png`, `voltage_angles_0.png`, etc.\n\nIf you put your outputs in a separate directory, you can run `python post_analysis.py [output_directory]`.\n\n## Troubleshooting\n\nIf the simulation fails, you may **need** to kill the `helics_broker` manually before you can start a new simulation.\n\nWhen debugging, you should check the `.log` files for errors. Error code `-9` usually occurs\nwhen it is killed by the broker as opposed to failing directly.\n\nYou can use the `oedisi` CLI tools to help debug specific components or timing.\n\n- `oedisi run-with-pause`\n- `oedisi debug-component --foreground feeder`\n\n# Components\n\nAll the required components are defined in folders within this repo. Each component\npulls types from `oedisi.types.data_types`.\n\n![Block diagram of simulation](sgidal-example.png)\n\n## Component Overview\n\nEach component is a standalone Python package with its own documentation. Click the component name for detailed information:\n\n### **[Broker](Components/broker/README.md)**\nCentral orchestration service for HELICS federates. Provides REST API endpoints for federate coordination and HELICS broker management.\n\n### **[LinDistFlow Federate](Components/lindistflow_federate/README.md)**\nOptimal power flow using linear distflow formulation. Implements convex optimization (cvxpy) for three-phase distribution system control.\n\n### **[LocalFeeder](Components/LocalFeeder/README.md)** (AWSFeeder)\nOpenDSS-based distribution feeder simulator. Loads SMART-DS feeders and outputs:\n- Topology: Y-matrix, slack bus, initial phases\n- Powers and voltages for all nodes\n- Real-time power flow simulation\n\n### **[Measuring Federate](Components/measuring_federate/README.md)**\nSensor simulation with noise injection. Takes MeasurementArray inputs and outputs subsets at specified nodes with:\n- Additive Gaussian noise\n- Multiplicative (percentage) noise\n- Configurable per-sensor parameters\n\nThis federate is instantiated as multiple sensors for each type of measurement.\n\n### **[OMOO Federate](Components/omoo_federate/README.md)**\nOnline Model-based Optimal Operation for distribution systems with high PV penetration. Uses primal-dual optimization with linearized power flow sensitivity matrices for:\n- Voltage regulation via PV curtailment and reactive power control\n- Real-time optimal setpoint computation\n- Constraint enforcement (voltage limits)\n\n### **[WLS Federate](Components/wls_federate/README.md)**\nWeighted Least Squares state estimation. Reads topology from the feeder simulation and measurements from the measuring federates, then outputs estimated voltages and power with angles.\n\n### **[Recorder](Components/recorder/README.md)**\nData recording federate. Connects to HELICS subscriptions and saves data to:\n- `.feather` files (PyArrow columnar format - efficient)\n- `.csv` files (human-readable format)\n\nThis component is instantiated multiple times in the simulation for every subscription of interest.\nThis is similar to the HELICS observer functionality, but with more specific data types.\n\n## Component Package Structure\n\nEach component follows a standardized src-layout structure:\n```\nComponents/{component}/\n├── src/\n│   └── {package_name}/\n│       ├── __init__.py          # Package initialization with version\n│       ├── server.py            # FastAPI REST server with main() entry point\n│       └── {main_module}.py     # Core federate implementation\n├── tests/                       # Test suite (outside src for isolation)\n│   ├── __init__.py\n│   └── test_*.py\n├── pyproject.toml               # Modern Python packaging (PEP 621)\n├── README.md                    # Comprehensive component documentation\n├── pytest.ini                   # Test configuration\n├── mypy.ini                     # Type checking configuration\n├── .gitignore                   # Python gitignore patterns\n├── Dockerfile                   # Container image definition\n└── component_definition.json    # OEDISI component spec (inputs/outputs)\n```\n\n**Benefits of src-layout:**\n- Clear separation between source code and tests\n- Prevents accidental imports from development directory\n- Ensures tests run against installed package\n- Standard practice for modern Python packages\n\n## Component Definitions\n\nComponents use `component_definition.json` files in each directory to define their dynamic inputs and outputs. This allows the OEDISI framework to:\n- Configure connections between federates\n- Validate wiring diagrams\n- Generate appropriate subscriptions/publications\n- Build simulation systems declaratively\n\n# How was the example constructed?\n\nFor each component, you need a `component_description.json` with\ninformation about the inputs and outputs of each component.\nWe created component python scripts that matched these component\ndescriptions and followed the GADAL API for configuration.\n\nIn order to use the data types from other federates, the `oedisi.types`\nmodule is critical. If additional data is needed, then we recommend\nsubclassing the pydantic models and adding the data in the required federates\nas needed. This ensures that others should still be able to parse your types if\nnecessary. Using compatible types is usually the most difficult part of integrating\ninto a system.\n\nA basic system description with the `test_system.json` is also\nneeded for the simulation.\n\nIn `test_full_systems.py`, we load in the various `components_description`s and\nthe wiring diagram `test_system.json`. The system is initialized and then the\n`test_system_runner.json` is saved. During this process, directories are created\nfor each component with the right configuration.\n\n# Results\n\n![Error plot](errors.png)\n\n![Voltage angles at time 0](voltage_angles_0.png)\n![Voltage magnitudes at time 0](voltage_magnitudes_0.png)\n\n![Voltage angles at time 95](voltage_angles_95.png)\n![Voltage magnitudes at time 95](voltage_magnitudes_95.png)\n\n# Docker Container\n\n```bash\ndocker build -t oedisi-example:0.0.0 .\n```\n\nTo get a docker volume pointed at the right place locally, we have to run more commands\n```bash\nmkdir outputs_build\ndocker volume create --name oedisi_output --opt type=none --opt device=$(PWD)/outputs_build --opt o=bind\n```\n\nIf `pwd` is unavailable on your system, then you must specify the exact path. On windows, this will end up\nbeing `/c/Users/.../outputs_builds/`. You must use forward slashes.\n\nThen we can run the docker image:\n```bash\ndocker run --rm --mount source=oedisi_output,target=/simulation/outputs oedisi-example:0.0.0\n```\n\nYou can omit the docker volume parts as well as `--mount` if you do not care about the exact outputs.\n\n## Docker Containers on M1 or M2\n\nSince HELICS does not have linux ARM builds, you have to run with\n\n```bash\nexport DOCKER_DEFAULT_PLATFORM=linux/amd64\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenedi%2Foedisi-components","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopenedi%2Foedisi-components","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenedi%2Foedisi-components/lists"}