Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Command line and automation API

FlowState can be driven without the mouse in two ways:

  • flowstate-cli, a command-line tool installed with the app, which reads and writes .flow files;
  • a local HTTP JSON API, served either by flowstate-cli serve or by the desktop app itself, which Excel, Power Query, Python or any HTTP client can call.

Both use the same variable paths to address any input or result.

Variable paths

A path names an element by its name (or index) inside a list. A procedure can also be named by its equipment tag.

PathValue
procedures/P-1/operations/REACT-1/duration/processProcess time of an operation, h
procedures/P-1/operations/REACT-1/kind/reactions/0/extentAn operation parameter
procedures/R-101/equipment/sizeEquipment size
streams/S-102/spec/AFeed amount of component A, kg/batch
components/A/pricePurchase price, $/kg
resources/agents/Steam/cost_per_tUtility price
economics/tax_rate, cycle_time, batches_per_yearPlant and economic settings
results/schedule/batch_time, results/economics/npvResults (read-only)
results/streams/Cake/composition/CStream contents, kg/batch

List the available paths with flowstate-cli vars my.flow [prefix], for example flowstate-cli vars my.flow results/economics. Values are checked before they are saved: a value of the wrong type, or an unknown field, is rejected and the file is left unchanged. In URLs, percent-encode names with spaces (Cooling%20Water).

flowstate-cli

flowstate-cli <command> [options]
CommandPurpose
simulate FILE [--json PATH] [--summary]Simulate and print batch time, cycle time, batches/year, unit cost, NPV and messages. --summary prints the key results as JSON; --json writes the full results. Exit code 0 = OK, 2 = simulation errors, 1 = usage or I/O error
get FILE PATHRead a variable
set FILE PATH VALUE [-o OUT]Write a variable (value in JSON; bare words are strings) and save
vars FILE [PREFIX]List variable paths
sweep FILE --var PATH --from X --to Y [--steps 5] [--out CSV] [--metric a,b]One-variable sensitivity sweep to CSV
monte-carlo FILE --var SPEC … [--runs 100] [--seed 42] [--out CSV] [--summary-out CSV] [--metric …]Monte Carlo study; SPEC is path:uniform:min,max, path:normal:mean,sd or path:triangular:min,mode,max
report FILE -o OUT [--docx | --rtf]Process report (HTML, Word or RTF)
batch-sheet FILE -o OUT [--markdown | --docx | --rtf]Electronic batch record
export-xlsx FILE -o OUTResults workbook (9 sheets)
chart FILE --kind gantt|occupancy|resources|cashflow -o OUT [--batches N] [--csv]Chart as SVG, or its data as CSV
templates FILE [--kind LABEL]Show batch-sheet templates and placeholders (JSON)
import FILE.spf -o OUT.flow [--check]Import an .spf project (see Importing .spf project files)
lca FILE [--simapro CSV] [--json] [--per-fu]LCA inventory and impacts; optionally write the SimaPro CSV
lca-import FILE CSV [-o OUT]Import a SimaPro process CSV into the LCA settings
serve FILE [--port 8765] [--allow-origin ORIGIN]…Serve the HTTP API for a file
excel-link SOURCE -o OUT [--port 8765] [--table NAME]Write Excel web-query (.iqy) files and Power Query code
samples DIRWrite the four built-in sample processes as .flow files

Metrics for sweep and monte-carlo are batch_time, cycle_time, min_cycle_time, batches_per_year, unit_production_cost, unit_revenue, npv, irr, roi, payback_years, gross_margin, net_profit, total_investment, annual_operating_cost, revenues, main_product_kg_per_year, e_factor, total_waste_kg, gwp and pmi, or any results/… path.

Examples

flowstate-cli samples samples/
flowstate-cli simulate samples/getting-started.flow
flowstate-cli set samples/getting-started.flow procedures/P-1/operations/REACT-1/duration/process 8 -o react8.flow
flowstate-cli sweep samples/getting-started.flow --var streams/S-102/spec/A --from 40 --to 60 --steps 5 \
    --out sweep.csv --metric unit_production_cost,npv,batch_time
flowstate-cli monte-carlo samples/getting-started.flow \
    --var components/A/price:triangular:8,10,14 --var economics/tax_rate:uniform:0.3,0.5 \
    --runs 500 --seed 1 --out mc.csv --summary-out mc-summary.csv
flowstate-cli export-xlsx samples/getting-started.flow -o results.xlsx

The HTTP API

Start it in one of two ways:

  • From the desktop app: Tools ▸ Start automation server. The API serves the document open in the window. The menu then shows Stop automation server (…) and Copy server URL. Changes made through the API appear in the window at once, re-simulate as usual, and can be undone with Ctrl+Z.
  • Headless: flowstate-cli serve my.flow.

The server listens on http://127.0.0.1:8765 and nowhere else. It rejects requests whose Host is not a loopback address, and it refuses cross-origin browser requests unless you allow their exact origin (see Office Scripts).

RequestPurpose
GET /Endpoint index, with mode (file or desktop) and a revision counter
GET /vars?prefix=…List variable paths
GET /var/<path>Read a variable: {"path", "value"}
PUT /var/<path> (JSON body)Set a variable
POST /vars with {"path": value, …}Atomic batch update
POST /simulateSimulate and return {"summary", "results"}
GET /summary, GET /resultsKey results, or full results
GET /report.html, /report.docx, /report.rtfProcess report
GET /batch-sheet.html, .md, .docx, .rtfBatch record
GET /export.xlsxResults workbook
GET /table, GET /table/<name>?format=csv|htmlLive tables: summary, streams, equipment, schedule, economics, cashflow, utilities, profiles, environment
GET /chart/<kind>.svg or .csv (?batches=3)gantt, occupancy, resources, cashflow
GET /templatesBatch-sheet templates and placeholders
GET /lca, GET /lca.csvLCA results, or the SimaPro CSV
GET /project, PUT /projectThe whole .flow JSON
POST /saveSave to the open file
curl -s localhost:8765/var/economics/tax_rate
curl -s -X PUT localhost:8765/var/economics/tax_rate -d 0.35
curl -s -X POST localhost:8765/simulate

Excel and Power Query

The /table/… endpoints are plain web tables that spreadsheets can pull and refresh. Numbers use . as the decimal separator and have no thousands separators.

  1. Start the API (desktop app or flowstate-cli serve).
  2. Run flowstate-cli excel-link http://127.0.0.1:8765 -o FlowState.iqy. This writes one FlowState-<table>.iqy per table and FlowState.pq with Power Query (M) code. Add --table cashflow to write a single .iqy file.
  3. Then, in Excel, do one of the following:
    • Web query: go to Data ▸ Get Data ▸ Existing Connections ▸ Browse for More… and pick an .iqy file.
    • Power Query: go to Data ▸ Get Data ▸ From Other Sources ▸ From Web and enter http://127.0.0.1:8765/table/streams?format=csv. Alternatively, paste the queries from FlowState.pq into Blank Query ▸ Advanced Editor. Power BI Desktop uses the same code.
  4. In the query Properties, tick Refresh every N minutes or Refresh data when opening the file. With the desktop app’s server, every refresh shows what the window currently shows.

Writing values back from VBA:

Sub SetTaxRateAndRefresh()
    Dim http As Object, v As String
    v = Replace(CStr(Range("B2").Value), ",", ".")
    Set http = CreateObject("MSXML2.XMLHTTP")
    http.Open "PUT", "http://127.0.0.1:8765/var/economics/tax_rate", False
    http.setRequestHeader "Content-Type", "application/json"
    http.send v
    If http.Status <> 200 Then MsgBox http.responseText: Exit Sub
    ThisWorkbook.RefreshAll
End Sub

Office Scripts

Office Scripts run in a web page whose origin is not local. The API refuses such requests by default, so that no web page can drive your simulator. To allow them, add the exact origin:

  • with flowstate-cli serve my.flow --allow-origin https://…, or
  • in the app, under Tools ▸ Allowed web origins.

Wildcards are not accepted. When a request is refused, the app offers Allow …? in the Tools menu, and flowstate-cli prints the origin it refused. Allow an origin only while you need it.

Python

The API needs nothing beyond the Python standard library:

import json, urllib.request

BASE = "http://127.0.0.1:8765"

def call(method, path, body=None):
    data = None if body is None else json.dumps(body).encode()
    req = urllib.request.Request(BASE + path, data=data, method=method,
                                 headers={"Content-Type": "application/json"})
    with urllib.request.urlopen(req) as r:
        return json.loads(r.read())

path = "procedures/P-1/operations/REACT-1/duration/process"
original = call("GET", "/var/" + path)["value"]
for hours in (4, 6, 8):
    call("PUT", "/var/" + path, hours)
    s = call("POST", "/simulate")["summary"]
    print(hours, s)
call("PUT", "/var/" + path, original)       # restore

The example changes the reaction time of the Getting Started process, re-simulates and prints the key results. Against the desktop app’s server, you can watch the changes in the window as they happen.