diff --git a/README.md b/README.md index 6eb860e..b2f8845 100644 --- a/README.md +++ b/README.md @@ -34,3 +34,11 @@ Notes - This repository emphasizes minimal, pragmatic changes; the goal is to establish a safe, extensible MVP while keeping the codebase approachable for contributors. See AGENTS.md for architectural guidance and testing rules. + +EnergiBridge interoperability (beta) +- Added a minimal EnergiBridge scaffold to map Open-EnergyMesh primitives to a canonical, vendor-agnostic contract representation and a Graph-of-Contracts registry. +- Included toy adapters to bootstrap cross-ecosystem interoperability: + - adapters/energi_bridge/inverter_bridge_adapter.js + - adapters/energi_bridge/der_bridge_adapter.js +- These adapters integrate with the existing MVP via the ADMM-lite path and demonstrate how to plug in device-specific models. +- This work lays the groundwork for Phase 0 protocol skeleton, registry of adapters, and TLS-based transport in future iterations. diff --git a/adapters/energi_bridge/der_bridge_adapter.js b/adapters/energi_bridge/der_bridge_adapter.js new file mode 100644 index 0000000..4bdd268 --- /dev/null +++ b/adapters/energi_bridge/der_bridge_adapter.js @@ -0,0 +1,24 @@ +// Toy DER/Storage bridge adapter for EnergiBridge canonical path +class DerBridgeAdapter { + constructor(id) { + this.id = id; + } + + // Simple solve that models a local demand/consumption signal + solve(localProblem, /* sharedVariables */) { + const target = (localProblem && localProblem.vars && typeof localProblem.vars.value === 'number') + ? localProblem.vars.value + : 0; + // Produce a modest consumption to demonstrate delta-sync behavior + const consumptionW = Math.max(0, target * 0.2); + return { + generationW: 0, + consumptionW, + netFlowW: -consumptionW + }; + } +} + +module.exports = { + DerBridgeAdapter +}; diff --git a/adapters/energi_bridge/inverter_bridge_adapter.js b/adapters/energi_bridge/inverter_bridge_adapter.js new file mode 100644 index 0000000..fd98eca --- /dev/null +++ b/adapters/energi_bridge/inverter_bridge_adapter.js @@ -0,0 +1,27 @@ +// Toy inverter bridge adapter for EnergiBridge canonical path +class InverterBridgeAdapter { + constructor(id) { + this.id = id; + } + + // Lightweight solve() method compatible with EnergyMesh.admmAdapter usage + // Computes a simple plan targeting the current localProblem value + solve(localProblem, /* sharedVariables */) { + const target = (localProblem && localProblem.vars && typeof localProblem.vars.value === 'number') + ? localProblem.vars.value + : 0; + // Simple heuristic: approach target as generation; no load signal here + const generationW = Math.max(0, target * 0.95); + const result = { + generationW, + // Keep consumption at 0 in this toy adapter; focus is demonstrating path + consumptionW: 0, + netFlowW: generationW + }; + return result; + } +} + +module.exports = { + InverterBridgeAdapter +}; diff --git a/src/energi_bridge.js b/src/energi_bridge.js new file mode 100644 index 0000000..fcf455c --- /dev/null +++ b/src/energi_bridge.js @@ -0,0 +1,56 @@ +// EnergiBridge: Lightweight canonical bridge for interoperability in Open-EnergyMesh MVP +// This module provides minimal scaffolding for a CatOpt-like bridge that maps +// primitives to a vendor-agnostic contract representation and a Graph-of-Contracts +// registry for adapters and data schemas. + +class GraphOfContracts { + constructor() { + this.contracts = new Map(); // contractName -> schema + this.adapters = new Map(); // adapterName -> { contractName, adapter } + } + + registerContract(contractName, schema) { + this.contracts.set(contractName, schema); + } + + getContract(contractName) { + return this.contracts.get(contractName); + } + + registerAdapter(adapterName, contractName, adapter) { + this.adapters.set(adapterName, { contractName, adapter }); + } + + getAdapter(adapterName) { + return this.adapters.get(adapterName); + } +} + +class EnergiBridge { + constructor() { + this.registry = new GraphOfContracts(); + } + + // Minimal canonical mapping from a local Open-EnergyMesh primitive to a + // CatOpt-like canonical object. The real project would implement richer + // mappings; this is a skeleton to bootstrap adapters. + static toCanonical(primitive) { + if (!primitive) return null; + // Heuristic-based mapping: detect common shapes + if (primitive.localProblem || primitive.LocalProblem) { + const lp = primitive.localProblem || primitive.LocalProblem; + return { Objects: 'LocalProblem', payload: lp }; + } + if (primitive.sharedVariables || primitive.SharedVariables) { + const sv = primitive.sharedVariables || primitive.SharedVariables; + return { Morphisms: 'SharedVariables', payload: sv }; + } + // Fallback: wrap as a generic contract element + return { Objects: 'Unknown', payload: primitive }; + } +} + +module.exports = { + EnergiBridge, + GraphOfContracts +};