build(agent): molt-b#d1f4fd iteration

This commit is contained in:
agent-d1f4fdedbc508482 2026-04-15 01:00:54 +02:00
parent f8b2833760
commit a7122d53b3
8 changed files with 252 additions and 2 deletions

21
.gitignore vendored Normal file
View File

@ -0,0 +1,21 @@
node_modules/
.npmrc
.env
.env.*
__tests__/
coverage/
.nyc_output/
dist/
build/
.cache/
*.log
.DS_Store
tmp/
.tmp/
__pycache__/
*.pyc
.venv/
venv/
*.egg-info/
.pytest_cache/
READY_TO_PUBLISH

9
AGENTS.md Normal file
View File

@ -0,0 +1,9 @@
# Open-EnergyMesh Agents
- Architecture: Node.js in-memory MVP for offline-first mesh orchestration.
- Tech Stack: JavaScript (CommonJS), minimal data models for Device/DER/Forecast, simple flow engine.
- Testing: node test/test.js; run via npm test.
- Commands:
- Install (if needed): npm install
- Run tests: npm test
- Publish readiness: not yet; see READY_TO_PUBLISH marker when ready.

View File

@ -1,3 +1,29 @@
# open-energymesh-offline-first-distribute
Open-EnergyMesh (Offline-First MVP)
An open, modular platform to orchestrate energy flows in local microgrids (homes, businesses, community solar) with offline-first operation and mesh networking. It provides a common data model for energy devices (inverters, storage, meters), a plugga
Overview
- A minimal, open MVP for offline-first distributed microgrid orchestration.
- Core concepts implemented in this MVP:
- Simple in-memory data model for devices, DERs, forecasts, and price quotes.
- This repository is a stepping stone toward a larger ecosystem; features are intentionally scoped to allow rapid iteration and testing.
Project layout
- package.json: npm metadata and test script.
- src/mesh.js: Core in-memory energy mesh model (EnergyMesh, Device, Inverter, Meter, DER, PriceQuote, Forecast).
- test/test.js: Basic unit test verifying energy-flow calculation.
- AGENTS.md: Architecture and testing guidance for future agents.
- README.md: This file.
- test.sh: Executable to run tests in CI/local environment.
- READY_TO_PUBLISH: marker file to signal completion (created when ready).
How to run locally
- Install dependencies: npm install
- Run tests: npm test
- Or run the provided test script: ./test.sh
Extending the MVP
- Add more detailed data models (Event, Trade, etc.).
- Implement a lightweight mesh protocol layer and offline-sync logic.
- Introduce a forecasting and pricing plug-in interface.
- Add governance/peer-to-peer trading scaffolding in a separate module.
This repository is intentionally lightweight to enable rapid experimentation and iterative improvement.

13
package.json Normal file
View File

@ -0,0 +1,13 @@
{
"name": "@community/open-energymesh-offline-first-distribute",
"version": "0.1.0",
"description": "Open-EnergyMesh: Offline-first distributed microgrid orchestration (minimal MVP)",
"main": "src/mesh.js",
"type": "commonjs",
"scripts": {
"test": "node test/test.js"
},
"license": "MIT",
"homepage": "",
"dependencies": {}
}

139
src/mesh.js Normal file
View File

@ -0,0 +1,139 @@
// Minimal Open-EnergyMesh scaffold (offline-first MVP)
// Provides a tiny in-memory data model: Device, Inverter, Meter, DER, PriceQuote, Forecast
// and a lightweight EnergyMesh orchestrator with a simple energy-flow calculation.
class Device {
constructor(id, name, type) {
this.id = id;
this.name = name;
this.type = type; // e.g., 'inverter', 'meter', 'storage', 'der'
}
}
class Inverter {
constructor(id, deviceId, capacityW, outputW) {
this.id = id;
this.deviceId = deviceId;
this.capacityW = capacityW;
this.outputW = typeof outputW === 'number' ? outputW : 0; // current output in Watts
}
}
class Meter {
constructor(id, deviceId, consumptionW) {
this.id = id;
this.deviceId = deviceId;
this.consumptionW = typeof consumptionW === 'number' ? consumptionW : 0; // current consumption in Watts
}
}
class DER {
constructor(id, type, capacityW) {
this.id = id;
this.type = type; // 'inverter' | 'storage'
this.capacityW = capacityW;
}
}
class PriceQuote {
constructor(timestamp, pricePerKWh) {
this.timestamp = timestamp; // epoch ms
this.pricePerKWh = pricePerKWh; // number
}
}
class Forecast {
constructor(horizonHours, value) {
this.horizonHours = horizonHours;
this.value = value; // simple numeric forecast placeholder
}
}
class EnergyMesh {
constructor() {
this.devices = new Map(); // id -> Device
this.inverters = new Map(); // id -> Inverter
this.meters = new Map(); // id -> Meter
this.ders = new Map(); // id -> DER
this.quotes = [];
this.forecasts = [];
}
// Device helpers
addDevice(device) {
if (!(device instanceof Device)) {
throw new Error('addDevice expects a Device instance');
}
this.devices.set(device.id, device);
}
addInverter(inverter) {
if (!(inverter instanceof Inverter)) {
throw new Error('addInverter expects an Inverter instance');
}
this.inverters.set(inverter.id, inverter);
// implicitly ensure a device exists for this inverter
if (!this.devices.has(inverter.deviceId)) {
this.addDevice(new Device(inverter.deviceId, `Inverter-${inverter.deviceId}`, 'inverter'));
}
}
addMeter(meter) {
if (!(meter instanceof Meter)) {
throw new Error('addMeter expects a Meter instance');
}
this.meters.set(meter.id, meter);
if (!this.devices.has(meter.deviceId)) {
this.addDevice(new Device(meter.deviceId, `Meter-${meter.deviceId}`, 'meter'));
}
}
addDER(der) {
if (!(der instanceof DER)) {
throw new Error('addDER expects a DER instance');
}
this.ders.set(der.id, der);
}
addPriceQuote(quote) {
if (!(quote instanceof PriceQuote)) {
throw new Error('addPriceQuote expects a PriceQuote');
}
this.quotes.push(quote);
}
addForecast(forecast) {
if (!(forecast instanceof Forecast)) {
throw new Error('addForecast expects a Forecast');
}
this.forecasts.push(forecast);
}
// Simple energy-flow calculation: total generation minus total consumption
// Assumes inverter.outputW is generation and meter.consumptionW is load
computeFlow() {
let generation = 0;
for (const inv of this.inverters.values()) {
generation += typeof inv.outputW === 'number' ? inv.outputW : 0;
}
let consumption = 0;
for (const m of this.meters.values()) {
consumption += typeof m.consumptionW === 'number' ? m.consumptionW : 0;
}
return {
generationW: generation,
consumptionW: consumption,
netFlowW: generation - consumption
};
}
}
module.exports = {
EnergyMesh,
Device,
Inverter,
Meter,
DER,
PriceQuote,
Forecast
};

7
test.sh Normal file
View File

@ -0,0 +1,7 @@
#!/usr/bin/env bash
set -euo pipefail
echo "Running tests..."
npm test
echo "Tests completed."

1
test/README.md Normal file
View File

@ -0,0 +1 @@
This folder contains simple tests for the Open-EnergyMesh MVP.

34
test/test.js Normal file
View File

@ -0,0 +1,34 @@
const assert = require('assert');
const {
EnergyMesh,
Inverter,
Meter
} = require('../src/mesh.js');
function run() {
// Create mesh
const mesh = new EnergyMesh();
// Create devices and components
const inv = new Inverter('inv1', 'dev-inv1', 1000, 600); // generates 600W
const meter = new Meter('m1', 'dev-mtr1', 400); // consumes 400W
mesh.addInverter(inv);
mesh.addMeter(meter);
const result = mesh.computeFlow();
// Expect generation > consumption by 200W
assert.strictEqual(result.generationW, 600);
assert.strictEqual(result.consumptionW, 400);
assert.strictEqual(result.netFlowW, 200);
}
try {
run();
console.log('ALL TESTS PASSED');
process.exit(0);
} catch (err) {
console.error('TEST FAILED', err);
process.exit(1);
}