diff --git a/src/i18n.json b/src/i18n.json index 5712c6d..723d4ce 100644 --- a/src/i18n.json +++ b/src/i18n.json @@ -531,10 +531,22 @@ }, + "Charging Tariffs": { + "de": "Ladetarife", + "en": "Charging Tariffs" + }, + + "Charging Tariff Id": { + "de": "Ladetarif-Id", + "en": "Charging Tariff Id" + }, + + - "Costs and Tariffs": { - "de": "Kosten und Tarife", - "en": "Costs and Tariffs" + + "Total Costs": { + "de": "Gesamtkosten", + "en": "Total Costs" }, "Total": { @@ -731,6 +743,83 @@ "End value": { "de": "Endwert", "en": "End value" + }, + + + "Adapter Id": { + "de": "Adapter-Id", + "en": "Adapter Id" + }, + + "Adapter Firmware Version": { + "de": "Adapter-Firmware-Version", + "en": "Adapter Firmware Version" + }, + + "Adapter Firmware Checksum": { + "de": "Adapter-Firmware-Checksumme", + "en": "Adapter Firmware Checksum" + }, + + "Meter number": { + "de": "Zählernummer", + "en": "Meter number" + }, + + "Meter status": { + "de": "Zählerstatus", + "en": "Meter status" + }, + + "Adapter status": { + "de": "Adapterstatus", + "en": "Adapter status" + }, + + "Seconds index": { + "de": "Sekundenindex", + "en": "Seconds index" + }, + + "Timestamp": { + "de": "Zeitstempel", + "en": "Timestamp" + }, + + "Unit (encoded)": { + "de": "Einheit (kodiert)", + "en": "Unit (encoded)" + }, + + "Scaling": { + "de": "Skalierung", + "en": "Scaling" + }, + + "Measurement Value": { + "de": "Messwert", + "en": "Measurement Value" + }, + + "Authorization": { + "de": "Autorisierung", + "en": "Authorization" + }, + + "SessionId": { + "de": "SessionId", + "en": "SessionId" + }, + + "Pagination counter": { + "de": "Paginierungszähler", + "en": "Pagination counter" + }, + + + "Charging Periods": { + "de": "Ladeperioden", + "en": "Charging Periods" } } diff --git a/src/index.html b/src/index.html index 5c4c62f..28c14f4 100644 --- a/src/index.html +++ b/src/index.html @@ -42,7 +42,7 @@ - + @@ -295,8 +295,70 @@ -
-
+
+
+ +
+ +
+ +
+ Tariff informations: +
+ +
+ +
+
+ +
+ + + +
+
+ +
+
+ +
+ +
+ +
+ Charging Period +
+ +
+ +
+
+ +
+ + + +
+
+ +
+
@@ -345,19 +407,19 @@
-
-
+
+
Sie wollen einen oder mehrere Mängel melden? @@ -459,8 +521,8 @@

Datenschutzerklärung für diesen Mängelmelder

-
- +
diff --git a/src/scss/chargy.scss b/src/scss/chargy.scss index ced6004..7ea3402 100644 --- a/src/scss/chargy.scss +++ b/src/scss/chargy.scss @@ -1241,7 +1241,101 @@ body { } - .costsAndTariffInfos { + .chargingTariffsInfos { + + .headline2 { + margin-top: 0.6vh; + font-weight: bold; + } + + .tariffsTable { + + display: table-row-group; + + .chargingTariffRow { + + display: table-row; + cursor: zoom-in; + + + .shortName { + display: table-cell; + padding-left: 12px; + padding-right: 2vw; + border-radius: 4px 0px 0px 4px; + white-space: nowrap; + } + + .summary { + display: table-cell; + padding-left: 12px; + padding-right: 2vw; + border-radius: 0px 4px 4px 0px; + white-space: nowrap; + } + + .description { + display: table-cell; + padding-left: 12px; + padding-right: 2vw; + border-radius: 0px 4px 4px 0px; + white-space: nowrap; + } + + } + + .chargingTariffRow:hover { + background-color: #72b3e2; + } + + } + + } + + .chargingPeriodsInfos { + + .headline2 { + margin-top: 0.6vh; + font-weight: bold; + } + + .chargingPeriodsTable { + + display: table-row-group; + + .chargingPeriodRow { + + display: table-row; + cursor: zoom-in; + + + .startTimestamp { + display: table-cell; + padding-left: 12px; + padding-right: 2vw; + border-radius: 4px 0px 0px 4px; + white-space: nowrap; + } + + .duration { + display: table-cell; + padding-left: 12px; + padding-right: 2vw; + border-radius: 0px 4px 4px 0px; + white-space: nowrap; + } + + } + + .chargingPeriodRow:hover { + background-color: #72b3e2; + } + + } + + } + + .totalCosts { .headline2 { margin-top: 0.6vh; @@ -1449,9 +1543,8 @@ body { } - #overlay { + .overlay { - display: none; position: absolute; font-family: sans-serif; font-size: 90%; @@ -1460,7 +1553,7 @@ body { height: 100vh; margin: auto; - #overlayText { + .overlayText { position: relative; top: 5%; @@ -1496,6 +1589,60 @@ body { } + .spacer { + flex-grow: 1; + visibility: hidden; + } + + .footer { + + display: flex; + justify-content: space-between; + align-items: end; + + .overlayLeftButton { + border: 0; + outline: 0; + background-color: transparent; + color: #b6d8f1; + margin: 4px; + font-size: 280%; + } + + .overlayLeftButton:hover { + color: #519ad0; + } + + .overlayRightButton { + visibility: hidden; + border: 0; + outline: 0; + background-color: transparent; + color: #b6d8f1; + margin: 4px; + font-size: 280%; + } + + .overlayRightButton:hover { + color: #519ad0; + } + + } + + } + + #overlayText::-webkit-scrollbar { + display: none; + } + + } + + #chargingTariffDetails { + + display: none; + + .overlayText { + .data { #cryptoData { @@ -1670,30 +1817,43 @@ body { } - .spacer { - flex-grow: 1; - visibility: hidden; - } - .footer { - display: flex; - justify-content: space-between; - align-items: end; + #signatureCheck { + + margin: 4vh 0 2vh 0; + text-align: center; + font-size: 150%; + + i { + font-size: 200%; + } + + #description { + position: relative; + line-height: 200%; + } - #overlayLeftButton { - border: 0; - outline: 0; - background-color: transparent; - color: #b6d8f1; - margin: 4px; - font-size: 280%; } - #overlayLeftButton:hover { - color: #519ad0; + .overlayRightButton { + visibility: hidden; } + } + + } + + } + + #chargingPeriodDetails { + + display: none; + + .overlayText { + + .footer { + #signatureCheck { margin: 4vh 0 2vh 0; @@ -1711,55 +1871,230 @@ body { } - #overlayRightButton { + .overlayRightButton { visibility: hidden; - border: 0; - outline: 0; - background-color: transparent; - color: #b6d8f1; - margin: 4px; - font-size: 280%; } - #overlayRightButton:hover { - color: #519ad0; + } + + } + + } + + #measurementsDetails { + + display: none; + + .overlayText { + + .data { + + #cryptoData { + + display: table; + margin-bottom: 5px; + + .row { + + display: table-row; + + .id { + display: table-cell; + padding: 2px 10px 1px 8px; + font-weight: bold; + border-radius: 4px 0px 0px 4px; + } + + .value { + + display: table-cell; + padding: 2px 8px 1px 0px; + border-radius: 0px 4px 4px 0px; + + .statusInfos { + font-style: italic; + font-size: 90%; + } + + } + + } + + .row:hover { + background-color: orange; + } + + .overEntry { + background-color: orange; + } + + } + + .infoblock { + + font-family: monospace; + font-size: 110%; + margin-bottom: 10px; + + .description { + position: relative; + top: 8px; + left: 10px; + background-color: #98c3e2; + display: inline-block; + padding: 1px 6px; + border-radius: 4px; + font-size: 85%; + } + + .value { + overflow-wrap: break-word; + background-color: #E1E1E1; + border-radius: 4px; + padding: 11px 10px 6px 10px; + width: calc(100% - 20px); + } + + } + + .errorblock { + + display: none; + + .description { + background-color: #980000; + } + + .value { + background-color: #dfbcbc; + } + + } + + #buffer { + + .value { + + .entry { + display: inline; + padding: 1px 4px 1px 4px; + margin-left: -4px; + border-radius: 4px; + word-break: break-all; + } + + .entry:hover { + background-color: orange; + } + + .overEntry { + background-color: orange; + } + + .ocmfSeparator { + color: #e20000; + } + + .ocmfHighlight { + color: #5c7aa9; + } + + .compactValue { + display: block; + } + + .prettyValue { + + display: none; + + .jsonKey { + font-weight: bold; + } + + .jsonString { + color: rgb(56, 56, 144) + } + + .jsonNumber { + color: rgb(43, 110, 43) + } + + .jsonBoolean { + color: rgb(174, 45, 45) + } + + } + + } + + } + + #publicKey { + + .value { + .leadingFour { + color: #969696; + } + } + + .sigHead { + display: none; + padding: 5px 10px 0px 10px; + font-size: 80%; + } + + .signatures { + + display: flex; + padding: 3px 0px 0px 0px; + font-family: sans-serif; + font-size: 70%; + color: #6d6d6d; + + i { + padding: 0px 3px 0px 10px; + } + + } + } } - } + .footer { + + #signatureCheck { + + margin: 4vh 0 2vh 0; + text-align: center; + font-size: 150%; + + i { + font-size: 200%; + } + + #description { + position: relative; + line-height: 200%; + } + + } + + .overlayRightButton { + visibility: hidden; + } + + } - #overlayText::-webkit-scrollbar { - display: none; } } #issueTracker { - position: absolute; - font-family: sans-serif; - font-size: 90%; - background-color: rgba(0, 0, 0, 0.3); - width: 100vw; - height: 100vh; - margin: auto; - //border-radius: 8px; - - #issueTrackerText { + display: none; - position: relative; - top: 5%; - width: calc(90% - 20px); - height: calc(90% - 50px); - margin: auto; - padding: 1px; - background-color: #f5f5f5; - border: 10px solid #f5f5f5; - border-radius: 6px; - box-shadow: 2px 0 16px 0 rgba(0,0,0,.3); - overflow-y: scroll; - z-index: 9000; + .overlayText { #headline { padding: 8px 8px 0px 8px; @@ -1870,31 +2205,6 @@ body { } - #issueBackButtonDiv { - - // position: fixed; - // left: 6%; - // bottom: 10%; - - #issueBackButton { - border: 0; - outline: 0; - background-color: transparent; - color: #b6d8f1; - margin: 4px; - font-size: 280%; - } - - #issueBackButton:hover { - color: #519ad0; - } - - } - - } - - #issueTrackerText::-webkit-scrollbar { - display: none; } } diff --git a/src/ts/Alfen.ts b/src/ts/Alfen.ts index a5501d6..6963375 100644 --- a/src/ts/Alfen.ts +++ b/src/ts/Alfen.ts @@ -343,6 +343,8 @@ export class Alfen { } ], + "chargingTariffs": ContainerInfos.chargingTariffs, + "chargingSessions": [ { @@ -358,10 +360,11 @@ export class Alfen { "@id": common.UID, }, - "costs": ContainerInfos.chargingCosts, + "chargingTariffs": ContainerInfos.chargingTariffs, + "chargingPeriods": ContainerInfos.chargingPeriods, + "totalCosts": ContainerInfos.totalCosts, "measurements": [ - { "energyMeterId": common.MeterId, @@ -386,7 +389,6 @@ export class Alfen { "values": [ ] } - ] } diff --git a/src/ts/chargeIT.ts b/src/ts/chargeIT.ts index f18121a..f542c27 100644 --- a/src/ts/chargeIT.ts +++ b/src/ts/chargeIT.ts @@ -1142,23 +1142,27 @@ export class ChargeIT { const connectorInfo_type = SomeJSON.connectorInfo?.type; const connectorInfo_losses = SomeJSON.connectorInfo?.losses; - const chargingCostsInfo = SomeJSON.chargingCostsInfo; - const chargingCostsInfo_total = SomeJSON.chargingCostsInfo?.total; - const chargingCostsInfo_currency = SomeJSON.chargingCostsInfo?.currency; - const chargingCostsInfo_reservation = SomeJSON.chargingCostsInfo?.reservation; - const chargingCostsInfo_reservation_cost = SomeJSON.chargingCostsInfo?.reservation?.cost; - const chargingCostsInfo_reservation_unit = SomeJSON.chargingCostsInfo?.reservation?.unit; - const chargingCostsInfo_energy = SomeJSON.chargingCostsInfo?.energy; - const chargingCostsInfo_energy_cost = SomeJSON.chargingCostsInfo?.energy?.cost; - const chargingCostsInfo_energy_unit = SomeJSON.chargingCostsInfo?.energy?.unit; - const chargingCostsInfo_time = SomeJSON.chargingCostsInfo?.time; - const chargingCostsInfo_time_cost = SomeJSON.chargingCostsInfo?.time?.cost; - const chargingCostsInfo_time_unit = SomeJSON.chargingCostsInfo?.time?.unit; - const chargingCostsInfo_idle = SomeJSON.chargingCostsInfo?.idle; - const chargingCostsInfo_idle_cost = SomeJSON.chargingCostsInfo?.idle?.cost; - const chargingCostsInfo_idle_unit = SomeJSON.chargingCostsInfo?.idle?.unit; - const chargingCostsInfo_flat = SomeJSON.chargingCostsInfo?.flat; - const chargingCostsInfo_flat_cost = SomeJSON.chargingCostsInfo?.flat?.cost; + const chargingTariffs = SomeJSON.chargingTariffs; + + const chargingPeriods = SomeJSON.chargingPeriods; + + const totalCosts = SomeJSON.totalCosts; + const totalCosts_total = SomeJSON.totalCosts?.total; + const totalCosts_currency = SomeJSON.totalCosts?.currency; + const totalCosts_reservation = SomeJSON.totalCosts?.reservation; + const totalCosts_reservation_cost = SomeJSON.totalCosts?.reservation?.cost; + const totalCosts_reservation_unit = SomeJSON.totalCosts?.reservation?.unit; + const totalCosts_energy = SomeJSON.totalCosts?.energy; + const totalCosts_energy_cost = SomeJSON.totalCosts?.energy?.cost; + const totalCosts_energy_unit = SomeJSON.totalCosts?.energy?.unit; + const totalCosts_time = SomeJSON.totalCosts?.time; + const totalCosts_time_cost = SomeJSON.totalCosts?.time?.cost; + const totalCosts_time_unit = SomeJSON.totalCosts?.time?.unit; + const totalCosts_idle = SomeJSON.totalCosts?.idle; + const totalCosts_idle_cost = SomeJSON.totalCosts?.idle?.cost; + const totalCosts_idle_unit = SomeJSON.totalCosts?.idle?.unit; + const totalCosts_flat = SomeJSON.totalCosts?.flat; + const totalCosts_flat_cost = SomeJSON.totalCosts?.flat?.cost; const signedMeterValues = SomeJSON.signedMeterValues; @@ -1356,69 +1360,85 @@ export class ChargeIT { //#endregion - //#region chargingCostsInfo + //#region chargingTariffs - if (chargingCostsInfo) + if (chargingTariffs) { - if (!chargyLib.isMandatoryNumber(chargingCostsInfo_total)) + for (let i = 0; i < chargingTariffs.length; i++) + { + + const chargingTariff = chargingTariffs[i]; + + } + + } + + //#endregion + + //#region totalCosts + + if (totalCosts) + { + + if (!chargyLib.isMandatoryNumber(totalCosts_total)) errors.push(this.chargy.GetLocalizedMessage("Missing or invalid total costs within the charging costs!")); - if (!chargyLib.isMandatoryString(chargingCostsInfo_currency)) + if (!chargyLib.isMandatoryString(totalCosts_currency)) errors.push(this.chargy.GetLocalizedMessage("Missing or invalid currency within the charging costs!")); - if (chargingCostsInfo_reservation) + if (totalCosts_reservation) { - if (!chargyLib.isMandatoryNumber(chargingCostsInfo_reservation_cost)) + if (!chargyLib.isMandatoryNumber(totalCosts_reservation_cost)) errors.push(this.chargy.GetLocalizedMessage("Missing or invalid reservation cost within the charging costs!")); // ToDo: Check for valid reservation unit - if (!chargyLib.isMandatoryString(chargingCostsInfo_reservation_unit)) + if (!chargyLib.isMandatoryString(totalCosts_reservation_unit)) errors.push(this.chargy.GetLocalizedMessage("Missing or invalid reservation unit within the charging costs!")); } - if (chargingCostsInfo_energy) + if (totalCosts_energy) { - if (!chargyLib.isMandatoryNumber(chargingCostsInfo_energy_cost)) + if (!chargyLib.isMandatoryNumber(totalCosts_energy_cost)) errors.push(this.chargy.GetLocalizedMessage("Missing or invalid energy cost within the charging costs!")); // ToDo: Check for valid energy unit - if (!chargyLib.isMandatoryString(chargingCostsInfo_energy_unit)) + if (!chargyLib.isMandatoryString(totalCosts_energy_unit)) errors.push(this.chargy.GetLocalizedMessage("Missing or invalid energy unit within the charging costs!")); } - if (chargingCostsInfo_time) + if (totalCosts_time) { - if (!chargyLib.isMandatoryNumber(chargingCostsInfo_time_cost)) + if (!chargyLib.isMandatoryNumber(totalCosts_time_cost)) errors.push(this.chargy.GetLocalizedMessage("Missing or invalid time cost within the charging costs!")); // ToDo: Check for valid time unit - if (!chargyLib.isMandatoryString(chargingCostsInfo_time_unit)) + if (!chargyLib.isMandatoryString(totalCosts_time_unit)) errors.push(this.chargy.GetLocalizedMessage("Missing or invalid time unit within the charging costs!")); } - if (chargingCostsInfo_idle) + if (totalCosts_idle) { - if (!chargyLib.isMandatoryNumber(chargingCostsInfo_idle_cost)) + if (!chargyLib.isMandatoryNumber(totalCosts_idle_cost)) errors.push(this.chargy.GetLocalizedMessage("Missing or invalid idle cost within the charging costs!")); // ToDo: Check for valid idle unit - if (!chargyLib.isMandatoryString(chargingCostsInfo_idle_unit)) + if (!chargyLib.isMandatoryString(totalCosts_idle_unit)) errors.push(this.chargy.GetLocalizedMessage("Missing or invalid idle unit within the charging costs!")); } - if (chargingCostsInfo_flat) + if (totalCosts_flat) { - if (!chargyLib.isMandatoryNumber(chargingCostsInfo_flat_cost)) + if (!chargyLib.isMandatoryNumber(totalCosts_flat_cost)) errors.push(this.chargy.GetLocalizedMessage("Missing or invalid flat cost within the charging costs!")); } @@ -1562,7 +1582,9 @@ export class ChargeIT { } ] } - ] + ], + + "chargingTariffs": chargingTariffs } ], @@ -1591,7 +1613,6 @@ export class ChargeIT { firmwareVersion: chargingStation_controllerSoftwareVersion, legalCompliance: { conformity: [{ - freeText: chargingStation_compliance }], calibration: [{ @@ -1603,7 +1624,9 @@ export class ChargeIT { }, energyMeter: meterInfo, connector: connectorInfo, - chargingCosts: chargingCostsInfo + chargingTariffs: chargingTariffs, + chargingPeriods: chargingPeriods, + totalCosts: totalCosts }); } diff --git a/src/ts/chargyApp.ts b/src/ts/chargyApp.ts index d7ea356..e263d85 100644 --- a/src/ts/chargyApp.ts +++ b/src/ts/chargyApp.ts @@ -28,82 +28,89 @@ export class ChargyApp { //#region Data - private readonly leaflet: any; - private readonly map: L.Map; - - private readonly elliptic: any; - private readonly moment: any; - private readonly chargy: Chargy; - private readonly asn1: any; - private readonly base32Decode: any; - - public appEdition: string = ""; - public copyright: string = ""; - public versionsURL: string = ""; - public defaultFeedbackEMail: string[] = []; - public defaultFeedbackHotline: string[] = []; - public defaultIssueURL: string = ""; - public packageJson: any = {}; - public i18n: any = {}; - public UILanguage: string = "de"; - - private currentAppInfos: any = null; - private currentVersionInfos: any = null; - private currentPackage: any = null; - private applicationHash: string = ""; - - private markers: any = []; - private minlat: number = +1000; - private maxlat: number = -1000; - private minlng: number = +1000; - private maxlng: number = -1000; - - private appDiv: HTMLDivElement; - private headlineDiv: HTMLDivElement; - private verifyframeDiv: HTMLDivElement; - - private updateAvailableButton: HTMLButtonElement; - private aboutButton: HTMLButtonElement; - private fullScreenButton: HTMLButtonElement; - private appQuitButton: HTMLButtonElement; - - private updateAvailableScreen: HTMLDivElement; - private inputDiv: HTMLDivElement; - private inputInfosDiv: HTMLDivElement; - private aboutScreenDiv: HTMLDivElement; - private applicationHashDiv: HTMLDivElement; - private applicationHashValueDiv: HTMLDivElement; - private chargingSessionScreenDiv: HTMLDivElement; - private invalidDataSetsScreenDiv: HTMLDivElement; - private inputButtonsDiv: HTMLDivElement; - private backButton: HTMLButtonElement; - private exportButtonDiv: HTMLDivElement; - private exportButton: HTMLButtonElement; - private fileInputButton: HTMLButtonElement; - private fileInput: HTMLInputElement; - private pasteButton: HTMLButtonElement; - private detailedInfosDiv: HTMLDivElement; - private errorTextDiv: HTMLDivElement; - private feedbackDiv: HTMLDivElement; - private overlayDiv: HTMLDivElement; - private overlayLeftButton: HTMLButtonElement; - private overlayRightButton: HTMLButtonElement; - private issueTrackerDiv: HTMLDivElement; - private privacyStatement: HTMLDivElement; - - private showFeedbackSection: Boolean; - private feedbackMethodsDiv: HTMLDivElement; - private feedbackEMailAnchor: HTMLAnchorElement; - private feedbackHotlineAnchor: HTMLAnchorElement; - private showIssueTrackerButton: HTMLButtonElement; - private issueTrackerText: HTMLDivElement; - private sendIssueButton: HTMLButtonElement; - private issueBackButton: HTMLButtonElement; - - private showPrivacyStatement: HTMLButtonElement; - private privacyStatementAccepted: HTMLInputElement; - private softwareInfosDiv: HTMLDivElement; - private openSourceLibsDiv: HTMLDivElement; + private readonly leaflet: any; + private readonly map: L.Map; + + private readonly elliptic: any; + private readonly moment: any; + private readonly chargy: Chargy; + private readonly asn1: any; + private readonly base32Decode: any; + + public appEdition: string = ""; + public copyright: string = ""; + public versionsURL: string = ""; + public defaultFeedbackEMail: string[] = []; + public defaultFeedbackHotline: string[] = []; + public defaultIssueURL: string = ""; + public packageJson: any = {}; + public i18n: any = {}; + public UILanguage: string = "de"; + + private currentAppInfos: any = null; + private currentVersionInfos: any = null; + private currentPackage: any = null; + private applicationHash: string = ""; + + private markers: any = []; + private minlat: number = +1000; + private maxlat: number = -1000; + private minlng: number = +1000; + private maxlng: number = -1000; + + private appDiv: HTMLDivElement; + private headlineDiv: HTMLDivElement; + private verifyframeDiv: HTMLDivElement; + + private updateAvailableButton: HTMLButtonElement; + private aboutButton: HTMLButtonElement; + private fullScreenButton: HTMLButtonElement; + private appQuitButton: HTMLButtonElement; + + private updateAvailableScreen: HTMLDivElement; + private inputDiv: HTMLDivElement; + private inputInfosDiv: HTMLDivElement; + private aboutScreenDiv: HTMLDivElement; + private applicationHashDiv: HTMLDivElement; + private applicationHashValueDiv: HTMLDivElement; + private chargingSessionScreenDiv: HTMLDivElement; + private invalidDataSetsScreenDiv: HTMLDivElement; + private inputButtonsDiv: HTMLDivElement; + private backButton: HTMLButtonElement; + private exportButtonDiv: HTMLDivElement; + private exportButton: HTMLButtonElement; + private fileInputButton: HTMLButtonElement; + private fileInput: HTMLInputElement; + private pasteButton: HTMLButtonElement; + private detailedInfosDiv: HTMLDivElement; + private errorTextDiv: HTMLDivElement; + private feedbackDiv: HTMLDivElement; + + private chargingTariffDetailsDiv: HTMLDivElement; + private chargingTariffDetailsLeftButton: HTMLButtonElement; + + private chargingPeriodDetailsDiv: HTMLDivElement; + private chargingPeriodDetailsLeftButton: HTMLButtonElement; + + private measurementsDetailsDiv: HTMLDivElement; + private measurementsDetailsLeftButton: HTMLButtonElement; +// private measurementsDetailsButton: HTMLButtonElement; + private issueTrackerDiv: HTMLDivElement; + private privacyStatement: HTMLDivElement; + + private showFeedbackSection: Boolean; + private feedbackMethodsDiv: HTMLDivElement; + private feedbackEMailAnchor: HTMLAnchorElement; + private feedbackHotlineAnchor: HTMLAnchorElement; + private showIssueTrackerButton: HTMLButtonElement; + private issueTrackerText: HTMLDivElement; + private sendIssueButton: HTMLButtonElement; + private issueTrackerLeftButton: HTMLButtonElement; + + private showPrivacyStatement: HTMLButtonElement; + private privacyStatementAccepted: HTMLInputElement; + private softwareInfosDiv: HTMLDivElement; + private openSourceLibsDiv: HTMLDivElement; //#endregion @@ -138,72 +145,91 @@ export class ChargyApp { //#region Load JavaScript libraries - this.elliptic = require('elliptic'); - this.moment = require('moment'); - this.asn1 = require('asn1.js'); - this.base32Decode = require('base32-decode') + this.elliptic = require('elliptic'); + this.moment = require('moment'); + this.asn1 = require('asn1.js'); + this.base32Decode = require('base32-decode') //#endregion //#region GUI setup - this.appDiv = document.getElementById('app') as HTMLDivElement; - this.headlineDiv = document.getElementById('headline') as HTMLDivElement; - this.verifyframeDiv = document.getElementById('verifyframe') as HTMLDivElement; - - this.updateAvailableScreen = document.getElementById('updateAvailableScreen') as HTMLDivElement; - this.chargingSessionScreenDiv = document.getElementById('chargingSessionScreen') as HTMLDivElement; - this.invalidDataSetsScreenDiv = document.getElementById('invalidDataSetsScreen') as HTMLDivElement; - this.detailedInfosDiv = document.getElementById('detailedInfos') as HTMLDivElement; - this.inputDiv = document.getElementById('input') as HTMLDivElement; - this.inputInfosDiv = document.getElementById('inputInfos') as HTMLDivElement; - this.errorTextDiv = document.getElementById('errorText') as HTMLDivElement; - this.overlayDiv = document.getElementById('overlay') as HTMLDivElement; - - this.applicationHashDiv = document.getElementById('applicationHash') as HTMLDivElement; - this.applicationHashValueDiv = this.applicationHashDiv.querySelector("#value") as HTMLDivElement; - - this.feedbackDiv = document.getElementById('feedback') as HTMLDivElement; - this.feedbackMethodsDiv = this.feedbackDiv. querySelector("#feedbackMethods") as HTMLDivElement; - this.showIssueTrackerButton = this.feedbackMethodsDiv.querySelector("#showIssueTracker") as HTMLButtonElement; - this.feedbackEMailAnchor = this.feedbackMethodsDiv.querySelector("#eMail") as HTMLAnchorElement; - this.feedbackHotlineAnchor = this.feedbackMethodsDiv.querySelector("#hotline") as HTMLAnchorElement; - - this.issueTrackerDiv = document.getElementById('issueTracker') as HTMLDivElement; - this.issueTrackerText = this.issueTrackerDiv. querySelector("#issueTrackerText") as HTMLDivElement; - this.privacyStatement = this.issueTrackerDiv. querySelector("#privacyStatement") as HTMLDivElement; - this.issueBackButton = this.issueTrackerDiv. querySelector("#issueBackButton") as HTMLButtonElement; - this.showPrivacyStatement = this.issueTrackerDiv. querySelector("#showPrivacyStatement") as HTMLButtonElement; - this.privacyStatementAccepted = this.issueTrackerDiv. querySelector("#privacyStatementAccepted") as HTMLInputElement; - this.sendIssueButton = this.issueTrackerDiv. querySelector("#sendIssueButton") as HTMLButtonElement; - - this.aboutScreenDiv = document.getElementById('aboutScreen') as HTMLDivElement; - this.softwareInfosDiv = this.aboutScreenDiv. querySelector("#softwareInfos") as HTMLDivElement; - this.openSourceLibsDiv = this.aboutScreenDiv. querySelector("#openSourceLibs") as HTMLDivElement; - - this.updateAvailableButton = document.getElementById('updateAvailableButton') as HTMLButtonElement; - this.aboutButton = document.getElementById('aboutButton') as HTMLButtonElement; - this.fullScreenButton = document.getElementById('fullScreenButton') as HTMLButtonElement; - this.appQuitButton = document.getElementById('appQuitButton') as HTMLButtonElement; - this.overlayLeftButton = document.getElementById('overlayLeftButton') as HTMLButtonElement; - this.overlayRightButton = document.getElementById('overlayRightButton') as HTMLButtonElement; - this.fileInputButton = document.getElementById('fileInputButton') as HTMLButtonElement; - this.pasteButton = document.getElementById('pasteButton') as HTMLButtonElement; - - this.inputButtonsDiv = document.getElementById('inputButtons') as HTMLDivElement; - this.backButton = this.inputButtonsDiv. querySelector("#backButton") as HTMLButtonElement; - - this.exportButtonDiv = document.getElementById('exportButtonDiv') as HTMLDivElement; - this.exportButton = this.exportButtonDiv. querySelector("#exportButton") as HTMLButtonElement; + this.appDiv = document.getElementById('app') as HTMLDivElement; + this.headlineDiv = document.getElementById('headline') as HTMLDivElement; + this.verifyframeDiv = document.getElementById('verifyframe') as HTMLDivElement; + + this.updateAvailableScreen = document.getElementById('updateAvailableScreen') as HTMLDivElement; + this.chargingSessionScreenDiv = document.getElementById('chargingSessionScreen') as HTMLDivElement; + this.invalidDataSetsScreenDiv = document.getElementById('invalidDataSetsScreen') as HTMLDivElement; + this.detailedInfosDiv = document.getElementById('detailedInfos') as HTMLDivElement; + this.inputDiv = document.getElementById('input') as HTMLDivElement; + this.inputInfosDiv = document.getElementById('inputInfos') as HTMLDivElement; + this.errorTextDiv = document.getElementById('errorText') as HTMLDivElement; + + this.applicationHashDiv = document.getElementById('applicationHash') as HTMLDivElement; + this.applicationHashValueDiv = this.applicationHashDiv.querySelector("#value") as HTMLDivElement; + + this.feedbackDiv = document.getElementById('feedback') as HTMLDivElement; + this.feedbackMethodsDiv = this.feedbackDiv. querySelector("#feedbackMethods") as HTMLDivElement; + this.showIssueTrackerButton = this.feedbackMethodsDiv.querySelector("#showIssueTracker") as HTMLButtonElement; + this.feedbackEMailAnchor = this.feedbackMethodsDiv.querySelector("#eMail") as HTMLAnchorElement; + this.feedbackHotlineAnchor = this.feedbackMethodsDiv.querySelector("#hotline") as HTMLAnchorElement; + + this.aboutScreenDiv = document.getElementById('aboutScreen') as HTMLDivElement; + this.softwareInfosDiv = this.aboutScreenDiv. querySelector("#softwareInfos") as HTMLDivElement; + this.openSourceLibsDiv = this.aboutScreenDiv. querySelector("#openSourceLibs") as HTMLDivElement; + + this.updateAvailableButton = document.getElementById('updateAvailableButton') as HTMLButtonElement; + this.aboutButton = document.getElementById('aboutButton') as HTMLButtonElement; + this.fullScreenButton = document.getElementById('fullScreenButton') as HTMLButtonElement; + this.appQuitButton = document.getElementById('appQuitButton') as HTMLButtonElement; + + this.chargingTariffDetailsDiv = document.getElementById('chargingTariffDetails') as HTMLDivElement; + this.chargingTariffDetailsLeftButton = this.chargingTariffDetailsDiv.querySelector(".overlayLeftButton") as HTMLButtonElement; + this.chargingTariffDetailsLeftButton.onclick = () => { + this.chargingTariffDetailsDiv.style.display = 'none'; + } + + this.chargingPeriodDetailsDiv = document.getElementById('chargingPeriodDetails') as HTMLDivElement; + this.chargingPeriodDetailsLeftButton = this.chargingPeriodDetailsDiv.querySelector(".overlayLeftButton") as HTMLButtonElement; + this.chargingPeriodDetailsLeftButton.onclick = () => { + this.chargingPeriodDetailsDiv.style.display = 'none'; + } + + this.measurementsDetailsDiv = document.getElementById('measurementsDetails') as HTMLDivElement; + this.measurementsDetailsLeftButton = this.measurementsDetailsDiv.querySelector(".overlayLeftButton") as HTMLButtonElement; + this.measurementsDetailsLeftButton.onclick = () => { + this.measurementsDetailsDiv.style.display = 'none'; + } + + this.issueTrackerDiv = document.getElementById('issueTracker') as HTMLDivElement; + this.issueTrackerText = this.issueTrackerDiv. querySelector(".overlayText") as HTMLDivElement; + this.privacyStatement = this.issueTrackerDiv. querySelector("#privacyStatement") as HTMLDivElement; + this.showPrivacyStatement = this.issueTrackerDiv. querySelector("#showPrivacyStatement") as HTMLButtonElement; + this.privacyStatementAccepted = this.issueTrackerDiv. querySelector("#privacyStatementAccepted") as HTMLInputElement; + this.sendIssueButton = this.issueTrackerDiv. querySelector("#sendIssueButton") as HTMLButtonElement; + this.issueTrackerLeftButton = this.issueTrackerDiv. querySelector(".overlayLeftButton") as HTMLButtonElement; + this.issueTrackerLeftButton.onclick = () => { + this.issueTrackerDiv.style.display = 'none'; + } + + this.fileInputButton = document.getElementById('fileInputButton') as HTMLButtonElement; + this.pasteButton = document.getElementById('pasteButton') as HTMLButtonElement; + + this.inputButtonsDiv = document.getElementById('inputButtons') as HTMLDivElement; + this.backButton = this.inputButtonsDiv. querySelector("#backButton") as HTMLButtonElement; + + this.exportButtonDiv = document.getElementById('exportButtonDiv') as HTMLDivElement; + this.exportButton = this.exportButtonDiv. querySelector("#exportButton") as HTMLButtonElement; //#endregion - this.chargy = new Chargy(this.i18n, - this.UILanguage, - this.elliptic, - this.moment, - this.asn1, - this.base32Decode); + this.chargy = new Chargy(this.i18n, + this.UILanguage, + this.elliptic, + this.moment, + this.asn1, + this.base32Decode); //#region OnWindowResize @@ -231,7 +257,7 @@ export class ChargyApp { this.issueTrackerText.scrollTop = this.issueTrackerText.scrollHeight; } - this.privacyStatementAccepted.onchange = (ev: Event) => { + this.privacyStatementAccepted.onchange = () => { this.sendIssueButton.disabled = !this.privacyStatementAccepted.checked; } @@ -323,10 +349,6 @@ export class ChargyApp { } - this.issueBackButton.onclick = (ev: MouseEvent) => { - this.issueTrackerDiv.style.display = 'none'; - } - //#endregion @@ -428,13 +450,13 @@ export class ChargyApp { this.fullScreenButton.onclick = (ev: MouseEvent) => { if (d.fullScreen || d.mozFullScreen || d.webkitIsFullScreen) { - this.overlayDiv.classList.remove("fullScreen"); + this.measurementsDetailsDiv.classList.remove("fullScreen"); chargyLib.closeFullscreen(); this.fullScreenButton.innerHTML = ''; } else { - this.overlayDiv.classList.add("fullScreen"); + this.measurementsDetailsDiv.classList.add("fullScreen"); chargyLib.openFullscreen(); this.fullScreenButton.innerHTML = ''; } @@ -499,14 +521,6 @@ export class ChargyApp { //#endregion - //#region Handle the 'Overlay Left'-button - - this.overlayLeftButton.onclick = (ev: MouseEvent) => { - this.overlayDiv.style.display = 'none'; - } - - //#endregion - //#region Modify external links to be opened in the external web browser @@ -1196,8 +1210,8 @@ export class ChargyApp { if (chargingSession.end) { - let endUTC = chargyLib.parseUTC(chargingSession.end); - let duration = this.moment.duration(endUTC - chargyLib.parseUTC(chargingSession.begin)); + const endUTC = chargyLib.parseUTC(chargingSession.end); + const duration = this.moment.duration(endUTC - chargyLib.parseUTC(chargingSession.begin)); dateDiv.innerHTML += " - " + (Math.floor(duration.asDays()) > 0 ? endUTC.format("dddd") + " " : "") + @@ -1667,7 +1681,7 @@ export class ChargyApp { try { - if (chargingSession.costs != null) + if (chargingSession.totalCosts != null) { var costsInfoDiv = tableDiv.appendChild(document.createElement('div')); @@ -1683,7 +1697,7 @@ export class ChargyApp { var costsDiv = textDiv.appendChild(document.createElement('div')); costsDiv.classList.add("costs"); - if (chargingSession.costs.total != 0) + if (chargingSession.totalCosts.total != 0) { var totalCostsDiv = costsDiv.appendChild(document.createElement('div')); @@ -1691,11 +1705,11 @@ export class ChargyApp { var totalCostsCost = totalCostsDiv.appendChild(document.createElement('div')); totalCostsCost.classList.add("totalCost"); - totalCostsCost.innerHTML = chargingSession.costs.total.toString(); + totalCostsCost.innerHTML = chargingSession.totalCosts.total.toString(); var totalCostsCurrency = totalCostsDiv.appendChild(document.createElement('div')); totalCostsCurrency.classList.add("totalCostCurrency"); - totalCostsCurrency.innerHTML = chargingSession.costs.currency; + totalCostsCurrency.innerHTML = chargingSession.totalCosts.currency; } @@ -2149,19 +2163,112 @@ export class ChargyApp { //#endregion - //#region Show charging costs and tariffs... + //#region Show charging tariffs... + + if (chargingSession.chargingTariffs && chargingSession.chargingTariffs.length > 0) + { + + // Should we also test whether the charging periods are valid? + + const tariffInfosDiv = chargyLib.CreateDiv(this.detailedInfosDiv, "chargingTariffsInfos"); + chargyLib.CreateDiv(tariffInfosDiv, "headline2", + this.chargy.GetLocalizedMessage("Charging Tariffs")); + + var tariffTableDiv = tariffInfosDiv.appendChild(document.createElement('div')); + tariffTableDiv.classList.add("tariffsTable"); + + for (const tariff of chargingSession.chargingTariffs) + { + + var chargingPeriodRow = tariffTableDiv.appendChild(document.createElement('div')); + chargingPeriodRow.classList.add("chargingTariffRow"); + chargingPeriodRow.onclick = () => { + this.showChargingTariffDetails(tariff); + }; + + var tariffShortName = chargingPeriodRow.appendChild(document.createElement('div')); + tariffShortName.classList.add("shortName"); + tariffShortName.innerHTML = tariff.shortName && Object.keys(tariff.shortName).length > 0 + ? tariff.shortName[this.UILanguage] ?? tariff["@id"] ?? "" + : tariff["@id"] ?? ""; + + if (tariff.summary && Object.keys(tariff.summary).length > 0) + { + var tariffSummary = chargingPeriodRow.appendChild(document.createElement('div')); + tariffSummary.classList.add("summary"); + tariffSummary.innerText = tariff.summary[this.UILanguage] ?? ""; + } + + } + + } + + //#endregion + + //#region Show charging periods (when more than one exists) + + if (chargingSession.chargingPeriods && chargingSession.chargingPeriods.length > 1) + { + + const totalCostsDiv = chargyLib.CreateDiv(this.detailedInfosDiv, "chargingPeriodsInfos"); + chargyLib.CreateDiv(totalCostsDiv, "headline2", + this.chargy.GetLocalizedMessage("Charging Periods")); + + var chargingPeriodsTableDiv = totalCostsDiv.appendChild(document.createElement('div')); + chargingPeriodsTableDiv.classList.add("chargingPeriodsTable"); + + for (let i=0; i { + this.showChargingPeriodDetails(chargingPeriod); + }; + + const startTimestmapDiv = chargingPeriodRow.appendChild(document.createElement('div')); + startTimestmapDiv.classList.add("startTimestamp"); + startTimestmapDiv.innerHTML = chargyLib.parseUTC(chargingPeriod.startTimestamp).format('DD.MM.YYYY HH:mm:ss'); + + const duration = this.moment.duration( + chargyLib.parseUTC(chargingPeriod.endTimestamp ?? + chargingPeriod.stopTimestamp ?? + chargingSession.chargingPeriods[i+1]?.startTimestamp ?? + "") + - + chargyLib.parseUTC(chargingPeriod.startTimestamp) + ); + + const durationDiv = chargingPeriodRow.appendChild(document.createElement('div')); + durationDiv.classList.add("duration"); + durationDiv.innerHTML = duration.hours() + "h " + duration.minutes() + "m" + duration.seconds() + "s"; + + } + + } + + } + + //#endregion + + //#region Show charging total costs - if (chargingSession.costs) + if (chargingSession.totalCosts) { - const costsAndTariffInfosDiv = chargyLib.CreateDiv(this.detailedInfosDiv, "costsAndTariffInfos"); - chargyLib.CreateDiv(costsAndTariffInfosDiv, "headline2", - this.chargy.GetLocalizedMessage("Costs and Tariffs")); + const totalCostsDiv = chargyLib.CreateDiv(this.detailedInfosDiv, "totalCosts"); + chargyLib.CreateDiv(totalCostsDiv, "headline2", + this.chargy.GetLocalizedMessage("Total Costs")); - var costsTableDiv = costsAndTariffInfosDiv.appendChild(document.createElement('div')); + var costsTableDiv = totalCostsDiv.appendChild(document.createElement('div')); costsTableDiv.classList.add("costsTable"); - if (chargingSession.costs.reservation?.cost != null) + if (chargingSession.totalCosts.reservation?.cost != null) { var reservationCostsRow = costsTableDiv.appendChild(document.createElement('div')); @@ -2173,23 +2280,23 @@ export class ChargyApp { var reservationCostsAmount = reservationCostsRow.appendChild(document.createElement('div')); reservationCostsAmount.classList.add("amount"); - reservationCostsAmount.innerHTML = chargingSession.costs.reservation.amount.toString(); + reservationCostsAmount.innerHTML = chargingSession.totalCosts.reservation.amount.toString(); var reservationCostsUnit = reservationCostsRow.appendChild(document.createElement('div')); reservationCostsUnit.classList.add("unit"); - reservationCostsUnit.innerHTML = chargingSession.costs.reservation.unit; + reservationCostsUnit.innerHTML = chargingSession.totalCosts.reservation.unit; var reservationCostsCost = reservationCostsRow.appendChild(document.createElement('div')); reservationCostsCost.classList.add("cost"); - reservationCostsCost.innerHTML = chargingSession.costs.reservation.cost.toString(); + reservationCostsCost.innerHTML = chargingSession.totalCosts.reservation.cost.toString(); var reservationCostsCurrency = reservationCostsRow.appendChild(document.createElement('div')); reservationCostsCurrency.classList.add("currency"); - reservationCostsCurrency.innerHTML = chargingSession.costs.currency; + reservationCostsCurrency.innerHTML = chargingSession.totalCosts.currency; } - if (chargingSession.costs.energy?.cost != null) + if (chargingSession.totalCosts.energy?.cost != null) { var energyCostsRow = costsTableDiv.appendChild(document.createElement('div')); @@ -2201,23 +2308,23 @@ export class ChargyApp { var energyCostsAmount = energyCostsRow.appendChild(document.createElement('div')); energyCostsAmount.classList.add("amount"); - energyCostsAmount.innerHTML = chargingSession.costs.energy.amount.toString(); + energyCostsAmount.innerHTML = chargingSession.totalCosts.energy.amount.toString(); var energyCostsUnit = energyCostsRow.appendChild(document.createElement('div')); energyCostsUnit.classList.add("unit"); - energyCostsUnit.innerHTML = chargingSession.costs.energy.unit; + energyCostsUnit.innerHTML = chargingSession.totalCosts.energy.unit; var energyCostsCost = energyCostsRow.appendChild(document.createElement('div')); energyCostsCost.classList.add("cost"); - energyCostsCost.innerHTML = chargingSession.costs.energy.cost.toString(); + energyCostsCost.innerHTML = chargingSession.totalCosts.energy.cost.toString(); var energyCostsCurrency = energyCostsRow.appendChild(document.createElement('div')); energyCostsCurrency.classList.add("currency"); - energyCostsCurrency.innerHTML = chargingSession.costs.currency; + energyCostsCurrency.innerHTML = chargingSession.totalCosts.currency; } - if (chargingSession.costs.time?.cost != null) + if (chargingSession.totalCosts.time?.cost != null) { var timeCostsRow = costsTableDiv.appendChild(document.createElement('div')); @@ -2229,23 +2336,23 @@ export class ChargyApp { var timeCostsAmount = timeCostsRow.appendChild(document.createElement('div')); timeCostsAmount.classList.add("amount"); - timeCostsAmount.innerHTML = chargingSession.costs.time.amount.toString(); + timeCostsAmount.innerHTML = chargingSession.totalCosts.time.amount.toString(); var timeCostsUnit = timeCostsRow.appendChild(document.createElement('div')); timeCostsUnit.classList.add("unit"); - timeCostsUnit.innerHTML = chargingSession.costs.time.unit; + timeCostsUnit.innerHTML = chargingSession.totalCosts.time.unit; var timeCostsCost = timeCostsRow.appendChild(document.createElement('div')); timeCostsCost.classList.add("cost"); - timeCostsCost.innerHTML = chargingSession.costs.time.cost.toString(); + timeCostsCost.innerHTML = chargingSession.totalCosts.time.cost.toString(); var timeCostsCurrency = timeCostsRow.appendChild(document.createElement('div')); timeCostsCurrency.classList.add("currency"); - timeCostsCurrency.innerHTML = chargingSession.costs.currency; + timeCostsCurrency.innerHTML = chargingSession.totalCosts.currency; } - if (chargingSession.costs.idle?.cost != null) + if (chargingSession.totalCosts.idle?.cost != null) { var idleCostsRow = costsTableDiv.appendChild(document.createElement('div')); @@ -2257,23 +2364,23 @@ export class ChargyApp { var idleCostsAmount = idleCostsRow.appendChild(document.createElement('div')); idleCostsAmount.classList.add("amount"); - idleCostsAmount.innerHTML = chargingSession.costs.idle.amount.toString(); + idleCostsAmount.innerHTML = chargingSession.totalCosts.idle.amount.toString(); var idleCostsUnit = idleCostsRow.appendChild(document.createElement('div')); idleCostsUnit.classList.add("unit"); - idleCostsUnit.innerHTML = chargingSession.costs.idle.unit; + idleCostsUnit.innerHTML = chargingSession.totalCosts.idle.unit; var idleCostsCost = idleCostsRow.appendChild(document.createElement('div')); idleCostsCost.classList.add("cost"); - idleCostsCost.innerHTML = chargingSession.costs.idle.cost.toString(); + idleCostsCost.innerHTML = chargingSession.totalCosts.idle.cost.toString(); var idleCostsCurrency = idleCostsRow.appendChild(document.createElement('div')); idleCostsCurrency.classList.add("currency"); - idleCostsCurrency.innerHTML = chargingSession.costs.currency; + idleCostsCurrency.innerHTML = chargingSession.totalCosts.currency; } - if (chargingSession.costs.flat?.cost != null) + if (chargingSession.totalCosts.flat?.cost != null) { var flatCostsRow = costsTableDiv.appendChild(document.createElement('div')); @@ -2291,11 +2398,11 @@ export class ChargyApp { var flatCostsCost = flatCostsRow.appendChild(document.createElement('div')); flatCostsCost.classList.add("cost"); - flatCostsCost.innerHTML = chargingSession.costs.flat.cost.toString(); + flatCostsCost.innerHTML = chargingSession.totalCosts.flat.cost.toString(); var flatCostsCurrency = flatCostsRow.appendChild(document.createElement('div')); flatCostsCurrency.classList.add("currency"); - flatCostsCurrency.innerHTML = chargingSession.costs.currency; + flatCostsCurrency.innerHTML = chargingSession.totalCosts.currency; } @@ -2322,7 +2429,7 @@ export class ChargyApp { measurementValue.measurement = measurement; const measurementValueDiv = chargyLib.CreateDiv(measurementValuesDiv, "measurementValue"); - measurementValueDiv.onclick = (ev: MouseEvent) => { + measurementValueDiv.onclick = () => { this.showMeasurementCryptoDetails(measurementValue); }; @@ -2608,6 +2715,150 @@ export class ChargyApp { //#endregion + //#region showChargingTariffDetails + + private showChargingTariffDetails(measurementValue: chargyInterfaces.IChargingTariff) : void + { + + function doError(text: String) + { + errorDiv.innerHTML = ' ' + text; + introDiv.style.display = "none"; + } + + //#region Headline + + const headlineDiv = this.chargingTariffDetailsDiv.querySelector('.headline') as HTMLDivElement; + const errorDiv = headlineDiv. querySelector('.error') as HTMLDivElement; + const introDiv = headlineDiv. querySelector('.intro') as HTMLDivElement; + errorDiv.innerHTML = ""; + introDiv.style.display = "block"; + + //#endregion + + // if (!measurementValue?.measurement || + // !measurementValue.method) + // { + // doError(this.chargy.GetLocalizedMessage("Unknown meter data record format!")); + // return; + // } + + //#region Show data and result on overlay + + this.chargingTariffDetailsDiv.style.display = 'block'; + + // const dataDiv = this.overlayDiv.querySelector('.data') as HTMLDivElement; + // const cryptoDataDiv = dataDiv. querySelector('#cryptoData') as HTMLDivElement; + // const bufferDiv = dataDiv. querySelector('#buffer .value') as HTMLDivElement; + // const hashedBufferDiv = dataDiv. querySelector('#hashedBuffer .value') as HTMLDivElement; + // const publicKeyDiv = dataDiv. querySelector('#publicKey .value') as HTMLDivElement; + // const signatureExpectedDiv = dataDiv. querySelector('#signatureExpected .value') as HTMLDivElement; + + // cryptoDataDiv.innerHTML = ''; + // bufferDiv.innerHTML = ''; + // hashedBufferDiv.innerHTML = '0x00000000000000000000000000000000000'; + // publicKeyDiv.innerHTML = '0x00000000000000000000000000000000000'; + // signatureExpectedDiv.innerHTML = '0x00000000000000000000000000000000000'; + + //#endregion + + //#region Footer + + const footerDiv = this.measurementsDetailsDiv.querySelector('.footer') as HTMLDivElement; + const signatureCheckDiv = footerDiv. querySelector('#signatureCheck') as HTMLDivElement; + + signatureCheckDiv.innerHTML = ''; + + //#endregion + + // measurementValue.method.ViewMeasurement(measurementValue, + // errorDiv, + // introDiv, + + // cryptoDataDiv, + // bufferDiv, + // hashedBufferDiv, + // publicKeyDiv, + // signatureExpectedDiv, + + // signatureCheckDiv); + + } + + //#endregion + + //#region showChargingPeriodDetails + + private showChargingPeriodDetails(chargingPeriod: chargyInterfaces.IChargingPeriod) : void + { + + function doError(text: String) + { + errorDiv.innerHTML = ' ' + text; + introDiv.style.display = "none"; + } + + //#region Headline + + const headlineDiv = this.chargingTariffDetailsDiv.querySelector('.headline') as HTMLDivElement; + const errorDiv = headlineDiv. querySelector('.error') as HTMLDivElement; + const introDiv = headlineDiv. querySelector('.intro') as HTMLDivElement; + errorDiv.innerHTML = ""; + introDiv.style.display = "block"; + + //#endregion + + // if (!measurementValue?.measurement || + // !measurementValue.method) + // { + // doError(this.chargy.GetLocalizedMessage("Unknown meter data record format!")); + // return; + // } + + //#region Show data and result on overlay + + this.chargingPeriodDetailsDiv.style.display = 'block'; + + // const dataDiv = this.overlayDiv.querySelector('.data') as HTMLDivElement; + // const cryptoDataDiv = dataDiv. querySelector('#cryptoData') as HTMLDivElement; + // const bufferDiv = dataDiv. querySelector('#buffer .value') as HTMLDivElement; + // const hashedBufferDiv = dataDiv. querySelector('#hashedBuffer .value') as HTMLDivElement; + // const publicKeyDiv = dataDiv. querySelector('#publicKey .value') as HTMLDivElement; + // const signatureExpectedDiv = dataDiv. querySelector('#signatureExpected .value') as HTMLDivElement; + + // cryptoDataDiv.innerHTML = ''; + // bufferDiv.innerHTML = ''; + // hashedBufferDiv.innerHTML = '0x00000000000000000000000000000000000'; + // publicKeyDiv.innerHTML = '0x00000000000000000000000000000000000'; + // signatureExpectedDiv.innerHTML = '0x00000000000000000000000000000000000'; + + //#endregion + + //#region Footer + + const footerDiv = this.measurementsDetailsDiv.querySelector('.footer') as HTMLDivElement; + const signatureCheckDiv = footerDiv. querySelector('#signatureCheck') as HTMLDivElement; + + signatureCheckDiv.innerHTML = ''; + + //#endregion + + // measurementValue.method.ViewMeasurement(measurementValue, + // errorDiv, + // introDiv, + + // cryptoDataDiv, + // bufferDiv, + // hashedBufferDiv, + // publicKeyDiv, + // signatureExpectedDiv, + + // signatureCheckDiv); + + } + + //#endregion + //#region showMeasurementCryptoDetails private showMeasurementCryptoDetails(measurementValue: chargyInterfaces.IMeasurementValue) : void @@ -2621,7 +2872,7 @@ export class ChargyApp { //#region Headline - const headlineDiv = this.overlayDiv.querySelector('.headline') as HTMLDivElement; + const headlineDiv = this.measurementsDetailsDiv.querySelector('.headline') as HTMLDivElement; const errorDiv = headlineDiv. querySelector('.error') as HTMLDivElement; const introDiv = headlineDiv. querySelector('.intro') as HTMLDivElement; errorDiv.innerHTML = ""; @@ -2638,9 +2889,9 @@ export class ChargyApp { //#region Show data and result on overlay - this.overlayDiv.style.display = 'block'; + this.measurementsDetailsDiv.style.display = 'block'; - const dataDiv = this.overlayDiv.querySelector('.data') as HTMLDivElement; + const dataDiv = this.measurementsDetailsDiv.querySelector('.data') as HTMLDivElement; const cryptoDataDiv = dataDiv. querySelector('#cryptoData') as HTMLDivElement; const bufferDiv = dataDiv. querySelector('#buffer .value') as HTMLDivElement; const hashedBufferDiv = dataDiv. querySelector('#hashedBuffer .value') as HTMLDivElement; @@ -2657,7 +2908,7 @@ export class ChargyApp { //#region Footer - const footerDiv = this.overlayDiv.querySelector('.footer') as HTMLDivElement; + const footerDiv = this.measurementsDetailsDiv.querySelector('.footer') as HTMLDivElement; const signatureCheckDiv = footerDiv. querySelector('#signatureCheck') as HTMLDivElement; signatureCheckDiv.innerHTML = ''; diff --git a/src/ts/chargyInterfaces.ts b/src/ts/chargyInterfaces.ts index 69a5f54..94dfd6a 100644 --- a/src/ts/chargyInterfaces.ts +++ b/src/ts/chargyInterfaces.ts @@ -107,6 +107,7 @@ export interface IChargeTransparencyRecord chargingStationOperators?: Array; chargingPools?: Array; chargingStations?: Array; + chargingTariffs?: Array; publicKeys?: Array; chargingSessions?: Array; eMobilityProviders?: Array; @@ -203,11 +204,10 @@ export interface IChargingStationOperator chargingPools?: Array; chargingStations?: Array; EVSEs?: Array; - tariffs?: Array; publicKeys?: Array; - chargingTariffs?: Array; - parkingTariffs?: Array; + chargingTariffs?: Array; + parkingTariffs?: Array; } @@ -243,7 +243,7 @@ export interface IChargingPool geoLocation?: IGeoLocation; chargingStationOperator?: IChargingStationOperator; chargingStations?: Array; - tariffs?: Array; + chargingTariffs?: Array; publicKeys?: Array; } @@ -269,7 +269,7 @@ export interface IChargingStation EVSEs: Array; EVSEIds?: Array; meters?: Array; - tariffs?: Array; + chargingTariffs?: Array; publicKeys?: Array; } @@ -281,7 +281,7 @@ export interface IEVSE chargingStation?: IChargingStation; chargingStationId?: string; meters: Array; - tariffs?: Array; + chargingTariffs?: Array; publicKeys?: Array; connectors?: Array; } @@ -343,19 +343,10 @@ export interface IEMobilityProvider "@id": string; "@context"?: string; description: IMultilanguageText; - tariffs: Array; + chargingTariffs: Array; publicKeys?: Array; } -export interface ITariff -{ - "@id": string; - "@context"?: string; - description?: IMultilanguageText; - currency?: string; - taxes?: Array; -} - export interface ITaxes { "@id": string; @@ -395,8 +386,9 @@ export interface IChargingSession meter?: IMeter; publicKey?: IPublicKeyInfo; tariffId?: string; - tariff?: ITariff; - costs?: IChargingCosts; + chargingTariffs?: Array; + chargingPeriods?: Array; + totalCosts?: IChargingCosts; authorizationStart: IAuthorization; authorizationStop?: IAuthorization; product?: IChargingProduct; @@ -820,5 +812,103 @@ export function isIFileInfo(obj: any): obj is IFileInfo { } export interface IExtendedFileInfo extends IFileInfo { - result: IChargeTransparencyRecord|IPublicKeyLookup|ISessionCryptoResult + result: IChargeTransparencyRecord|IPublicKeyLookup|ISessionCryptoResult +} + +export interface IChargingPeriod +{ + startTimestamp: string, + stopTimestamp?: string, + endTimestamp?: string, + chargingTariffId: string, + activeChargingTariffElement?: IChargingTariffElement, + costs: IChargingCosts +} + +export enum DayOfWeek +{ + Sunday = 0, + Monday = 1, + Tuesday = 2, + Wednesday = 3, + Thursday = 4, + Friday = 5, + Saturday = 6 +} + +export interface ITariffRestriction { + start_time: string, + end_time: string, + start_date: string, + end_date: string, + min_kwh: Decimal, + max_kwh: Decimal, + min_power: Decimal, + max_power: Decimal, + min_duration: number, + max_duration: number, + day_of_week: Array +} + +export interface IPriceComponent { + type: string, + price: Decimal, + step_size: number +} + +export interface IChargingTariffElement { + price_components: Array, + restrictions: ITariffRestriction } + +export interface IDisplayText { + language: string, + text: string +} + +// OCPI v2.1.1 + extensions +export interface IChargingTariff { + + "@id": string; + "@context"?: string|Array, + country_code?: string, + party_id?: string, + shortName?: IMultilanguageText; + summary?: IMultilanguageText; + tariff_alt_url?: string, + currency?: string, + taxes?: Array; + elements?: Array + + //energy_mix?: IEnergyMix, + + not_before?: string, + not_after?: string, + created?: string, + last_updated?: string, + + signatures?: Array + +} + +export interface IParkingTariff { + + "@id": string; + "@context"?: string|Array, + country_code?: string, + party_id?: string, + description?: IMultilanguageText; + tariff_alt_text?: Array, + tariff_alt_url?: string, + currency?: string, + taxes?: Array; + elements?: Array + + not_before?: string, + not_after?: string, + created?: string, + last_updated?: string, + + signatures?: Array + +} \ No newline at end of file