﻿{
  "Version": "2.25.10.12111",
  "TemplateId": "6AA600D5-93C4-4DB5-9490-7AB2CF6F19C2",
  "GUID": "dca8442b-1e07-425d-8c6b-7c36b5a9fba9",
  "Inputs": {
    "ENERGINET_TOKEN": {
      "Name": "ENERGINET_TOKEN",
      "Value": "ENTER TOKEN HERE",
      "Scaling": 1.0,
      "Unit": "",
      "Description": "Token for authentication",
      "Category": "",
      "Custom1": "",
      "Custom2": "",
      "Custom3": "",
      "TagLink": false
    }
  },
  "Parameters": {
    "useLegacyProcessing": "0",
    "processing": "//Updated 2026-01-21\n//To send history (Optional):\n/*\n\n     Create an Input named: SEND_HISTORY\n     Enter the start date (YYYY-MM-DD) in Custom1 of the input.\n     Enter the end date (YYYY-MM-DD) in Custom2 of the input. (if not filled in, today's date is used automatically)\n     Enter frequency 1H, 1D in Custom3 (1H = hourly values, 1D = one value per day)\n\n     Tip: Create a separate report and use a dedicated token for sending history data. \n     Token can only be used to send data once every 10 minutes.\n*/\n\nvar inputs = [INPUTS];\n\nlet historyFrequency = new TimeSpan(24, 0, 0);\n\nlet toDate = DateTime.Now;\n\nlet fromDate = \"\";\nlet sendHistory = false;\nconst decimals = 1;\n\nlet token = \"\";\n\nif (inputs[\"SEND_HISTORY\"]) {\n  if (inputs[\"SEND_HISTORY\"].Custom1) {\n    try {\n      fromDate = DateTime.ParseExact(\n        inputs[\"SEND_HISTORY\"].Custom1,\n        \"yyyy-MM-dd\",\n        CultureInfo.InvariantCulture\n      );\n\n      if (inputs[\"SEND_HISTORY\"].Custom2)\n        toDate = DateTime.ParseExact(\n          inputs[\"SEND_HISTORY\"].Custom2,\n          \"yyyy-MM-dd\",\n          CultureInfo.InvariantCulture\n        );\n\n      if (inputs[\"SEND_HISTORY\"].Custom3) {\n        switch (inputs[\"SEND_HISTORY\"].Custom3) {\n          case \"1H\":\n            historyFrequency = new TimeSpan(1, 0, 0);\n            break;\n          case \"1D\":\n          default:\n            historyFrequency = new TimeSpan(24, 0, 0);\n            break;\n        }\n      }\n\n      sendHistory = true;\n    } catch (e) {\n      debug(e);\n    }\n  }\n}\n\nconst jo = new JObject();\nconst ja = new JArray();\n\njo[\"fromDate\"] = fromDate;\njo[\"toDate\"] = toDate;\njo[\"historyFrequency\"] = historyFrequency;\njo[\"sendHistory\"] = sendHistory;\n\nif (inputs[\"ENERGINET_TOKEN\"] && inputs[\"ENERGINET_TOKEN\"].Value) {\n  token = inputs[\"ENERGINET_TOKEN\"].Value;\n}\n\nif (!token) {\n  return \"TOKEN MISSING\";\n}\n\njo[\"token\"] = token;\n\nfor (const input in inputs) {\n  if (tags.ContainsKey(input)) {\n    let meterId = input;\n\n    if (inputs[input].Custom2) {\n      meterId = inputs[input].Custom2;\n    }\n\n    const meter = new JObject();\n    meter.Add(\"meterID\", meterId);\n\n    const values = new JArray();\n    meter.Add(\"values\", values);\n\n    if (sendHistory) {\n      const trendData = getTrendData(input, fromDate, toDate);\n\n      let lastSendDate = null;\n      let lastSendHour = null;\n\n      for (let index = 0; index < trendData.Count; index++) {\n        const date = new DateTime(trendData[index].Key);\n\n        if (historyFrequency.Hours === 1) {\n          if (lastSendDate === null || date.Date > lastSendDate || date.Hour !== lastSendHour) {\n            lastSendDate = date.Date;\n            lastSendHour = date.Hour;\n\n            const value = new JArray();\n            value.Add(date.ToString(\"o\").replaceAll(\".\", \":\"));\n            value.Add(new JValue(formatValue(trendData[index].Value, decimals)));\n            values.Add(value);\n          }\n        } else {\n          if (!lastSendDate || date.Date > lastSendDate) {\n            lastSendDate = date.Date;\n\n            const value = new JArray();\n            value.Add(date.ToString(\"o\").replaceAll(\".\", \":\"));\n            value.Add(new JValue(formatValue(trendData[index].Value, decimals)));\n            values.Add(value);\n          }\n        }\n      }\n\n    } else {\n      const value = new JArray();\n      value.Add(tags[input].Timestamp.ToString(\"o\").replaceAll(\".\", \":\"));\n      value.Add(new JValue(formatValue(tags[input].Value, decimals)));\n      values.Add(value);\n    }\n\n    ja.Add(meter);\n  }\n}\n\njo.Add(\"meters\", ja);\n\nconst response = sendToEnergiNet(ja);\n\njo.Add(\"status\", response.StatusCode.ToString());\njo.Add(\"reason\", response.ReasonPhrase.ToString());\njo.Add(\"message\", response.RequestMessage.ToString());\n\nreturn jo;\n\nfunction formatValue(value, decimals) {\n  value = Number(value);\n  const adjustment = Math.pow(10, decimals);\n  value = Math.round((value + Number.EPSILON) * adjustment) / adjustment;\n  return value;\n}\n\nfunction sendToEnergiNet(body) {\n  var url = \"https://www.energinet.net/apiImport/data\";\n\n  var handler = new HttpClientHandler();\n  var client = new HttpClient(handler);\n\n  client.DefaultRequestHeaders.Add(\"Authorization\", \"Bearer \" + token);\n\n  var contentType = \"application/json\";\n\n  var content = new StringContent(\n    body,\n    Encoding.UTF8,\n    contentType\n  );\n\n  var response = client.PostAsync(url, content).GetAwaiter().GetResult();\n\n  debug(response.RequestMessage.ToString());\n  debug(response.ReasonPhrase.ToString());\n  debug(response.StatusCode.ToString());\n\n  return response;\n}",
    "presentation": "<style>\n\t#outlet,\n\t#outlet * {\n\t\tmargin: 0;\n\t\tpadding: 0;\n\t}\n\n\t#outlet {\n\t\tdisplay: grid;\n\t\tgap: 16px;\n\t\tpadding: 16px;\n\t}\n\n\t#outlet section {\n\t\tdisplay: grid;\n\t\tgap: 8px;\n\t}\n\n\t#outlet table {\n\t\twidth: 100%;\n\t\tborder-collapse: collapse;\n\t\ttable-layout: fixed;\n\t}\n\n\t#outlet th,\n\t#outlet td {\n\t\tborder: 1px solid #ccc;\n\t\tpadding: 12px 16px;\n\t\ttext-align: left;\n\t\toverflow: hidden;\n\t\ttext-overflow: ellipsis;\n\t\twhite-space: nowrap;\n\t\twidth: 50%;\n\t}\n\n\t#outlet th {\n\t\tbackground-color: #f5f5f5;\n\t\tfont-weight: 600;\n\t}\n\n\t#outlet tr:nth-child(even) {\n\t\tbackground-color: #fafafa;\n\t}\n</style>\n\n<script>\n\t$(document).ready(function () {\n\t\tconst output = [OUTPUT];\n\n\t\tconst { status, reason, message, meters } = output;\n\n\t\tif (message) {\n\t\t\tconst section = document.createElement(\"section\");\n\n\t\t\tconst statusElement = document.createElement(\"h2\");\n\t\t\tstatusElement.textContent = `Status: ${status} (${reason})`;\n\n\t\t\tsection.appendChild(statusElement);\n\n\t\t\tconst messageElement = document.createElement(\"p\");\n\t\t\tmessageElement.textContent = message;\n\t\t\tsection.appendChild(messageElement);\n\n\t\t\tdocument.getElementById(\"outlet\").appendChild(section);\n\t\t}\n\n\t\tif (meters?.length) {\n\t\t\tconst section = document.createElement(\"section\");\n\n\t\t\tconst title = document.createElement(\"h2\");\n\t\t\ttitle.textContent = \"Data sent to the server:\";\n\t\t\tsection.appendChild(title);\n\n\t\t\tmeters.forEach((meter) => {\n\t\t\t\tconst article = document.createElement(\"article\");\n\n\t\t\t\tconst meterID = document.createElement(\"h3\");\n\t\t\t\tmeterID.textContent = meter.meterID;\n\t\t\t\tarticle.appendChild(meterID);\n\n\t\t\t\tconst table = document.createElement(\"table\");\n\n\t\t\t\tconst headerRow = document.createElement(\"tr\");\n\t\t\t\tconst headerTimestamp = document.createElement(\"th\");\n\t\t\t\theaderTimestamp.textContent = \"Timestamp\";\n\t\t\t\theaderRow.appendChild(headerTimestamp);\n\t\t\t\tconst headerValue = document.createElement(\"th\");\n\t\t\t\theaderValue.textContent = \"Value\";\n\t\t\t\theaderRow.appendChild(headerValue);\n\t\t\t\ttable.appendChild(headerRow);\n\n\t\t\t\tmeter.values?.forEach(([timestamp, value]) => {\n\t\t\t\t\tconst row = document.createElement(\"tr\");\n\t\t\t\t\tconst timestampCell = document.createElement(\"td\");\n\t\t\t\t\ttimestampCell.textContent = timestamp;\n\t\t\t\t\trow.appendChild(timestampCell);\n\t\t\t\t\tconst valueCell = document.createElement(\"td\");\n\t\t\t\t\tvalueCell.textContent = value;\n\t\t\t\t\trow.appendChild(valueCell);\n\t\t\t\t\ttable.appendChild(row);\n\t\t\t\t});\n\n\t\t\t\tarticle.appendChild(table);\n\n\t\t\t\tsection.appendChild(article);\n\t\t\t});\n\n\t\t\tdocument.getElementById(\"outlet\").appendChild(section);\n\t\t}\n\t});\n</script>\n\n<output id=\"outlet\"></output>\n"
  },
  "Exports": {},
  "Sendings": {},
  "DataKey": "data",
  "NextRunTime": "2026-01-21T14:00:00",
  "Interval": "01:00:00",
  "RunType": 2,
  "RunOnView": false,
  "Active": true,
  "History": false,
  "ReadyToRun": false,
  "Running": false,
  "Alias": "",
  "Description": "",
  "Name": "newenerginetexport"
}