[
  {
    "id": "flow-solar",
    "type": "tab",
    "label": "Solar PV — panel degradation",
    "disabled": false,
    "info": "Discovers the panel-specific power curve P = f(irradiance, T_cell, wind) on a clean commissioning week, then weekly refits and flags panels whose coefficients drift > 2σ vs. the fleet baseline — an early signal of PID (potential-induced degradation), delamination, or hotspot formation months before the annual thermographic survey would catch it."
  },
  {
    "id": "solar-inject",
    "type": "inject",
    "z": "flow-solar",
    "name": "weekly kick @ Sun 02:00",
    "props": [{ "p": "payload" }],
    "crontab": "0 2 * * 0",
    "once": false,
    "topic": "",
    "payload": "",
    "payloadType": "date",
    "x": 200,
    "y": 100,
    "wires": [["solar-load"]]
  },
  {
    "id": "solar-load",
    "type": "function",
    "z": "flow-solar",
    "name": "load week from timeseries DB (stub)",
    "func": "// In production: replace with an influxdb / timescale / http node.\n// Stub returns 10 rows for local wiring test.\nconst X = [\n  [850, 42.1, 3.2],\n  [920, 44.5, 2.8],\n  [780, 39.8, 4.1],\n  [1010, 47.2, 1.9],\n  [640, 34.6, 5.3],\n  [890, 43.0, 3.0],\n  [960, 45.8, 2.4],\n  [700, 36.9, 4.8],\n  [820, 41.4, 3.5],\n  [980, 46.3, 2.2]\n];\nconst y = [280, 305, 258, 335, 210, 293, 316, 232, 271, 322];\nmsg.payload = {\n  X, y,\n  variables: ['irradiance', 'T_cell', 'wind']\n};\nreturn msg;\n",
    "outputs": 1,
    "x": 470,
    "y": 100,
    "wires": [["solar-route"]]
  },
  {
    "id": "solar-route",
    "type": "switch",
    "z": "flow-solar",
    "name": "have baseline?",
    "property": "baseline_id",
    "propertyType": "flow",
    "rules": [{ "t": "null" }, { "t": "nnull" }],
    "checkall": "false",
    "outputs": 2,
    "x": 720,
    "y": 100,
    "wires": [["solar-fit"], ["solar-shape-drift"]]
  },
  {
    "id": "solar-fit",
    "type": "formulize-fit",
    "z": "flow-solar",
    "name": "commissioning fit",
    "endpoint": "https://api.formulize.dev",
    "rateLimit": "free",
    "timeoutMs": 60000,
    "x": 920,
    "y": 60,
    "wires": [["solar-stash"]]
  },
  {
    "id": "solar-stash",
    "type": "function",
    "z": "flow-solar",
    "name": "stash baseline + expression",
    "func": "flow.set('baseline_id', msg.payload.formula_id);\nflow.set('baseline_expr', msg.payload.expression);\nnode.warn('Solar baseline: ' + msg.payload.expression + ' (r2=' + msg.payload.r2 + ')');\nreturn msg;\n",
    "outputs": 1,
    "x": 1150,
    "y": 60,
    "wires": [[]]
  },
  {
    "id": "solar-shape-drift",
    "type": "function",
    "z": "flow-solar",
    "name": "shape drift input",
    "func": "msg.payload = {\n  formula_id: flow.get('baseline_id'),\n  current_X: msg.payload.X,\n  current_y: msg.payload.y,\n  sigma_threshold: 2.0\n};\nreturn msg;\n",
    "outputs": 1,
    "x": 920,
    "y": 140,
    "wires": [["solar-drift"]]
  },
  {
    "id": "solar-drift",
    "type": "formulize-drift",
    "z": "flow-solar",
    "name": "degradation monitor",
    "endpoint": "https://api.formulize.dev",
    "rateLimit": "free",
    "timeoutMs": 60000,
    "sigmaThreshold": 2.0,
    "x": 1130,
    "y": 140,
    "wires": [["solar-alarm"]]
  },
  {
    "id": "solar-alarm",
    "type": "switch",
    "z": "flow-solar",
    "name": "alarm?",
    "property": "payload.drift_detected",
    "propertyType": "msg",
    "rules": [{ "t": "true" }],
    "checkall": "false",
    "outputs": 1,
    "x": 1330,
    "y": 140,
    "wires": [["solar-ticket"]]
  },
  {
    "id": "solar-ticket",
    "type": "http request",
    "z": "flow-solar",
    "name": "open ServiceNow ticket",
    "method": "POST",
    "ret": "obj",
    "url": "https://your-instance.service-now.com/api/now/table/incident",
    "x": 1550,
    "y": 140,
    "wires": [[]]
  }
]
