{"id":21974259,"url":"https://github.com/frequenz-floss/frequenz-microgrid-formula-engine-rs","last_synced_at":"2026-02-04T22:33:40.425Z","repository":{"id":264659840,"uuid":"881408600","full_name":"frequenz-floss/frequenz-microgrid-formula-engine-rs","owner":"frequenz-floss","description":"A library to create formulas over streamed data","archived":false,"fork":false,"pushed_at":"2025-12-01T16:33:17.000Z","size":33,"stargazers_count":0,"open_issues_count":3,"forks_count":3,"subscribers_count":6,"default_branch":"v0.x.x","last_synced_at":"2025-12-04T01:44:52.925Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/frequenz-floss.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","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":"2024-10-31T14:12:57.000Z","updated_at":"2025-12-01T16:33:22.000Z","dependencies_parsed_at":"2025-03-22T23:26:01.205Z","dependency_job_id":"20de1fb5-f6db-428c-bfab-f2e4181bafda","html_url":"https://github.com/frequenz-floss/frequenz-microgrid-formula-engine-rs","commit_stats":null,"previous_names":["frequenz-floss/frequenz-microgrid-formula-engine-rs"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/frequenz-floss/frequenz-microgrid-formula-engine-rs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frequenz-floss%2Ffrequenz-microgrid-formula-engine-rs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frequenz-floss%2Ffrequenz-microgrid-formula-engine-rs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frequenz-floss%2Ffrequenz-microgrid-formula-engine-rs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frequenz-floss%2Ffrequenz-microgrid-formula-engine-rs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/frequenz-floss","download_url":"https://codeload.github.com/frequenz-floss/frequenz-microgrid-formula-engine-rs/tar.gz/refs/heads/v0.x.x","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frequenz-floss%2Ffrequenz-microgrid-formula-engine-rs/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29098234,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-04T21:05:08.033Z","status":"ssl_error","status_checked_at":"2026-02-04T21:04:53.031Z","response_time":62,"last_error":"SSL_read: 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":"2024-11-29T15:40:21.804Z","updated_at":"2026-02-04T22:33:40.419Z","avatar_url":"https://github.com/frequenz-floss.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# frequenz-microgrid-formula-engine-rs\n\n[\u003cimg alt=\"docs.rs\" src=\"https://img.shields.io/docsrs/frequenz-microgrid-formula-engine\"\u003e](https://docs.rs/frequenz-microgrid-formula-engine)\n[\u003cimg alt=\"Crates.io\" src=\"https://img.shields.io/crates/v/frequenz-microgrid-formula-engine\"\u003e](https://crates.io/crates/frequenz-microgrid-formula-engine)\n\nA library to create formulas over streamed data, primarily used for calculating and processing values within microgrid applications.\n\n## Usage\n\nThe `FormulaEngine` can *only* work with _resampled_ component data streams. It has been designed to work with the following libraries:\n- [frequenz-resampling-rs](https://github.com/frequenz-floss/frequenz-resampling-rs) - A resampling library, which sends `None` values when data is missing. See [Handling Nulls and Missing Values](#handling-nulls-and-missing-values).\n- [frequenz-microgrid-component-graph-rs](https://github.com/frequenz-floss/frequenz-microgrid-component-graph-rs) - A component graph library, for generating formulas.\n\nThe `FormulaEngine` can be created from a string formula using the `try_new` method. Formulas can contain component placeholders, represented by `#` followed by a number. To calculate the formula, provide an iterator of `Option` values where:\n- `None` represents a missing value\n- `Some(value)` represents a value\n\nThe result of the calculation will be an `Option` value.\n\n### Example:\n\n```rust\nuse frequenz_formula_engine::{FormulaEngine, FormulaError};\n\nfn main() -\u003e Result\u003c(), FormulaError\u003e {\n    let fe = FormulaEngine::try_new(\"#0 + #1\")?;\n    assert_eq!(fe.calculate(\u0026[Some(1.0), Some(2.0)])?, Some(3.0));\n    Ok(())\n}\n```\n\n### Handling Nulls and Missing Values\n\nWhen dealing with missing data, use `None` to indicate a missing value. If the formula requires a value for a placeholder but it is missing, the result will also be `None` unless a fallback function like `COALESCE` is used.\n\nExample:\n\n```\nCOALESCE(#1, 0)  // If #1 is None, it will return 0\n```\n\n### Error Handling\n\nThe FormulaEngine may return errors for invalid formulas, incorrect argument counts, or division by zero. These are returned as a FormulaError. Handle them gracefully for robust applications.\n\n```Rust\nmatch FormulaEngine::try_new(\"#0 / #1\") {\n    Ok(fe) =\u003e match fe.calculate(\u0026[Some(10.0), Some(0.0)]) {\n        Ok(result) =\u003e println!(\"Result: {:?}\", result),\n        Err(e) =\u003e println!(\"Calculation error: {:?}\", e),\n    },\n    Err(e) =\u003e println!(\"Invalid formula: {:?}\", e),\n}\n```\n\n## Formula Syntax Overview\n\nThe formula engine supports simple arithmetic expressions that combine numbers, references to components, mathematical operators, and basic functions.\n\n### Numbers\n\nYou can write integer or decimal numbers directly in formulas:\n\n```\n42\n3.14\n0.001\n```\n\n### Component References\n\nMicrogrid electrical component or sensor references are written as # followed by one or more digits:\n\n```\n#1     // Refers to component 1\n#42    // Refers to component 42\n```\n\n### Operators\n\nThe following standard arithmetic operators are supported:\n\n- Addition: `+`\n- Subtraction: `-` (also supports unary minus, e.g., `-5`)\n- Multiplication: `*`\n- Division: `/`\n\nExpressions follow standard precedence rules (multiplication/division before addition/subtraction). Use parentheses to override precedence as needed:\n\n```\n#1 + 3 * #2         // Multiplies #2 by 3, then adds #1\n(#1 + 3) * #2       // Adds #1 and 3, then multiplies the result by #2\n```\n\n### Functions\n\nFormulas support these functions that operate on a comma-separated list of expressions:\n\n- `COALESCE(a, b, ...)` — Returns the first non-null value from the list\n- `MIN(a, b, ...)` — Returns the smallest value\n- `MAX(a, b, ...)` — Returns the largest value\n\nExamples:\n\n```\nCOALESCE(#3, 0)         // Returns #3 if it's not null, otherwise 0\nMIN(#1, #2, 100)        // Returns the smaller value of component #1 and #2, but at most the value of 100\nMAX(#1 + 2, #4 * 5)     // Evaluates both expressions, returns the larger\n```\n\n### Whitespace\n\nWhitespace is ignored and can be used freely to improve readability:\n\n```\n( #1 + 4 ) * ( #2 - 1 )\n```\n\n### More Examples\n\nHere are some additional examples of the formula engine syntax:\n\n```\n#1 + 5\n-#2 / 3.0\n(#1 + #2) * 0.5\nCOALESCE(#5, #6, 0)\nMAX(0, #3 - 100)\n```\n\n## Installation\nTo add the library to your project, include the following in your Cargo.toml:\n\n```toml\n[dependencies]\nfrequenz-microgrid-formula-engine = \"0.1\"\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffrequenz-floss%2Ffrequenz-microgrid-formula-engine-rs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffrequenz-floss%2Ffrequenz-microgrid-formula-engine-rs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffrequenz-floss%2Ffrequenz-microgrid-formula-engine-rs/lists"}