{
  "name": "Voltcast Home — battery charge notification",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "days",
              "triggerAtHour": 14
            }
          ]
        }
      },
      "name": "After day-ahead publication",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [0, 0]
    },
    {
      "parameters": {
        "url": "https://voltcast.com/api/v1/prices/DE-LU",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "options": {}
      },
      "name": "Get published prices",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [260, 0],
      "notes": "Header Auth: Authorization = Bearer YOUR_VOLTCAST_KEY. Keep DE-LU equal to the zone selected on Home."
    },
    {
      "parameters": {
        "jsCode": "const rows = $json.data || [];\nconst hoursToCharge = 2;\nif (rows.length < 2) throw new Error('Price curve has too few intervals');\nconst stepMinutes = Math.max(1, Math.round((Date.parse(rows[1].delivery_start) - Date.parse(rows[0].delivery_start)) / 60000));\nconst intervalCount = Math.ceil((hoursToCharge * 60) / stepMinutes);\nconst selected = rows\n  .filter((row) => row.price_eur_mwh !== null && row.price_eur_mwh !== undefined)\n  .map((row) => ({ start: row.delivery_start, end: row.delivery_end, eur_mwh: Number(row.price_eur_mwh) }))\n  .sort((a, b) => a.eur_mwh - b.eur_mwh)\n  .slice(0, intervalCount)\n  .sort((a, b) => Date.parse(a.start) - Date.parse(b.start));\nreturn [{ json: {\n  zone: $json.meta?.zone || 'DE-LU',\n  notification_only: true,\n  charge_hours: hoursToCharge,\n  resolution_minutes: stepMinutes,\n  selected_intervals: selected,\n  average_eur_mwh: selected.length ? selected.reduce((sum, row) => sum + row.eur_mwh, 0) / selected.length : null,\n  source: 'Voltcast published day-ahead prices'\n} }];"
      },
      "name": "Draft low-price charge plan",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [530, 0],
      "notes": "This is a notification plan, not an inverter command. Add asset constraints before any physical control."
    }
  ],
  "connections": {
    "After day-ahead publication": {
      "main": [[{ "node": "Get published prices", "type": "main", "index": 0 }]]
    },
    "Get published prices": {
      "main": [[{ "node": "Draft low-price charge plan", "type": "main", "index": 0 }]]
    }
  },
  "pinData": {},
  "meta": {
    "templateCredsSetupCompleted": false,
    "voltcastCampaign": "home-battery-charge-plan",
    "signupUrl": "https://voltcast.com/register?plan=home&utm_source=n8n&utm_medium=workflow-template&utm_campaign=home-battery-charge-plan&task=n8n&zone=DE-LU"
  }
}
