@open-charging-cloud/chargy-core 0.5.0 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/ACrypt.d.ts +2 -2
- package/dist/ACrypt.d.ts.map +1 -1
- package/dist/Alfen.d.ts +6 -6
- package/dist/Alfen.d.ts.map +1 -1
- package/dist/BSMCrypt01.d.ts +8 -9
- package/dist/BSMCrypt01.d.ts.map +1 -1
- package/dist/EMHCrypt01.d.ts +8 -8
- package/dist/EMHCrypt01.d.ts.map +1 -1
- package/dist/GDFCrypt01.d.ts +8 -8
- package/dist/GDFCrypt01.d.ts.map +1 -1
- package/dist/Mennekes.d.ts +22 -22
- package/dist/Mennekes.d.ts.map +1 -1
- package/dist/OCMF.d.ts +25 -27
- package/dist/OCMF.d.ts.map +1 -1
- package/dist/OCPI.d.ts +2 -4
- package/dist/OCPI.d.ts.map +1 -1
- package/dist/PCDF.d.ts +1 -1
- package/dist/PCDF.d.ts.map +1 -1
- package/dist/QIDigital_DCC.d.ts +1 -1
- package/dist/QIDigital_DCC.d.ts.map +1 -1
- package/dist/QIDigital_DCoA.d.ts +1 -1
- package/dist/QIDigital_DCoA.d.ts.map +1 -1
- package/dist/QIDigital_DCoC.d.ts +1 -1
- package/dist/QIDigital_DCoC.d.ts.map +1 -1
- package/dist/SAFE_XML.d.ts +16 -16
- package/dist/SAFE_XML.d.ts.map +1 -1
- package/dist/XMLContainer.d.ts +2 -2
- package/dist/XMLContainer.d.ts.map +1 -1
- package/dist/browser/index.js +1216 -1116
- package/dist/browser/index.js.map +1 -1
- package/dist/chargeIT.d.ts +1 -3
- package/dist/chargeIT.d.ts.map +1 -1
- package/dist/chargePoint.d.ts +3 -3
- package/dist/chargePoint.d.ts.map +1 -1
- package/dist/chargy.d.ts +11 -7
- package/dist/chargy.d.ts.map +1 -1
- package/dist/chargyLib.d.ts +4 -0
- package/dist/chargyLib.d.ts.map +1 -1
- package/dist/interfaces/IChargeTransparencyRecord.d.ts +76 -76
- package/dist/interfaces/IChargeTransparencyRecord.d.ts.map +1 -1
- package/dist/interfaces/chargyInterfaces.d.ts +116 -114
- package/dist/interfaces/chargyInterfaces.d.ts.map +1 -1
- package/dist/node/index.js +1216 -1116
- package/dist/node/index.js.map +1 -1
- package/dist/pdfjs/browser.d.ts +2 -1
- package/dist/pdfjs/browser.d.ts.map +1 -1
- package/dist/qrCodeReader.d.ts.map +1 -1
- package/dist/secp224k1.d.ts +10 -11
- package/dist/secp224k1.d.ts.map +1 -1
- package/dist/verificationResults.d.ts +2 -1
- package/dist/verificationResults.d.ts.map +1 -1
- package/i18n.json +40 -0
- package/package.json +3 -3
package/dist/browser/index.js
CHANGED
|
@@ -9768,9 +9768,7 @@ var secp224k1 = class {
|
|
|
9768
9768
|
N = BigInt("0x010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7");
|
|
9769
9769
|
// Number of points in the field
|
|
9770
9770
|
Acurve = BigInt(0);
|
|
9771
|
-
//
|
|
9772
|
-
Bcurve = BigInt(5);
|
|
9773
|
-
// These two are defined on the elliptic curve. y^2 = x^3 + Acurve * x + Bcurve
|
|
9771
|
+
// Defined on the elliptic curve. y^2 = x^3 + Acurve * x + 5
|
|
9774
9772
|
Gx = BigInt("0xA1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C");
|
|
9775
9773
|
Gy = BigInt("0x7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5");
|
|
9776
9774
|
GPoint = [this.Gx, this.Gy];
|
|
@@ -9867,16 +9865,19 @@ var secp224k1 = class {
|
|
|
9867
9865
|
address: this.modulo(publicKey[1], this.Two) == this.One ? "03" + Px : "02" + Px
|
|
9868
9866
|
};
|
|
9869
9867
|
}
|
|
9868
|
+
return void 0;
|
|
9870
9869
|
}
|
|
9871
9870
|
};
|
|
9872
9871
|
|
|
9873
9872
|
// src/interfaces/chargyInterfaces.ts
|
|
9874
9873
|
var chargyInterfaces_exports = {};
|
|
9875
9874
|
__export(chargyInterfaces_exports, {
|
|
9875
|
+
CreateError: () => CreateError,
|
|
9876
9876
|
CryptoAlgorithms: () => CryptoAlgorithms,
|
|
9877
9877
|
CryptoHashAlgorithms: () => CryptoHashAlgorithms,
|
|
9878
9878
|
DayOfWeek: () => DayOfWeek,
|
|
9879
9879
|
DisplayPrefixes: () => DisplayPrefixes,
|
|
9880
|
+
ErrorLevel: () => ErrorLevel,
|
|
9880
9881
|
IECCurves: () => IECCurves,
|
|
9881
9882
|
IEncoding: () => IEncoding,
|
|
9882
9883
|
InformationRelevance: () => InformationRelevance,
|
|
@@ -9980,14 +9981,26 @@ var WarningLevel = /* @__PURE__ */ ((WarningLevel2) => {
|
|
|
9980
9981
|
WarningLevel2["high"] = "high";
|
|
9981
9982
|
return WarningLevel2;
|
|
9982
9983
|
})(WarningLevel || {});
|
|
9984
|
+
var ErrorLevel = /* @__PURE__ */ ((ErrorLevel2) => {
|
|
9985
|
+
ErrorLevel2["low"] = "low";
|
|
9986
|
+
ErrorLevel2["medium"] = "medium";
|
|
9987
|
+
ErrorLevel2["high"] = "high";
|
|
9988
|
+
return ErrorLevel2;
|
|
9989
|
+
})(ErrorLevel || {});
|
|
9990
|
+
function CreateError(message, level = "high" /* high */) {
|
|
9991
|
+
return {
|
|
9992
|
+
level,
|
|
9993
|
+
message
|
|
9994
|
+
};
|
|
9995
|
+
}
|
|
9983
9996
|
function isISessionCryptoResult1(obj) {
|
|
9984
|
-
return
|
|
9997
|
+
return isObject(obj) && obj["status"] !== void 0;
|
|
9985
9998
|
}
|
|
9986
9999
|
function isISessionCryptoResult2(obj) {
|
|
9987
|
-
return
|
|
10000
|
+
return isObject(obj) && obj["status"] !== void 0 && obj["status"] !== "InvalidSessionFormat" /* InvalidSessionFormat */;
|
|
9988
10001
|
}
|
|
9989
10002
|
function isICryptoResult(obj) {
|
|
9990
|
-
return
|
|
10003
|
+
return isObject(obj) && obj["status"] !== void 0;
|
|
9991
10004
|
}
|
|
9992
10005
|
var InformationRelevance = /* @__PURE__ */ ((InformationRelevance2) => {
|
|
9993
10006
|
InformationRelevance2["Unknown"] = "Unknown";
|
|
@@ -10075,6 +10088,26 @@ function toArrayBuffer(data) {
|
|
|
10075
10088
|
function toUint8Array(data) {
|
|
10076
10089
|
return data instanceof Uint8Array ? data : new Uint8Array(data);
|
|
10077
10090
|
}
|
|
10091
|
+
function getArrayElement(values, index, message = "Missing array element") {
|
|
10092
|
+
const value = values[index];
|
|
10093
|
+
if (value === void 0)
|
|
10094
|
+
throw new Error(message + " at index " + index.toString());
|
|
10095
|
+
return value;
|
|
10096
|
+
}
|
|
10097
|
+
function getFirstArrayElement(values, message = "Missing first array element") {
|
|
10098
|
+
return getArrayElement(values, 0, message);
|
|
10099
|
+
}
|
|
10100
|
+
function getLastArrayElement(values, message = "Missing last array element") {
|
|
10101
|
+
return getArrayElement(values, values.length - 1, message);
|
|
10102
|
+
}
|
|
10103
|
+
function getArrayLikeElement(values, index, message = "Missing array-like element") {
|
|
10104
|
+
if (index < 0 || index >= values.length)
|
|
10105
|
+
throw new Error(message + " at index " + index.toString());
|
|
10106
|
+
const value = values[index];
|
|
10107
|
+
if (value === void 0)
|
|
10108
|
+
throw new Error(message + " at index " + index.toString());
|
|
10109
|
+
return value;
|
|
10110
|
+
}
|
|
10078
10111
|
function normalizeXMLText(xmlText) {
|
|
10079
10112
|
return (xmlText ?? "").replace(/^\uFEFF/, "").replace(/\r\n?/g, "\n").replace(/>\s+</g, "><").trim();
|
|
10080
10113
|
}
|
|
@@ -10086,15 +10119,16 @@ function getDirectChildByLocalName(parent, localName) {
|
|
|
10086
10119
|
}
|
|
10087
10120
|
function getTrimmedTextContent(element) {
|
|
10088
10121
|
const text = element?.textContent.trim();
|
|
10089
|
-
return text && text.length > 0 ? text : void 0;
|
|
10122
|
+
return text != null && text.length > 0 ? text : void 0;
|
|
10090
10123
|
}
|
|
10091
10124
|
function parseDescription(parent) {
|
|
10092
10125
|
const descriptions = getDirectChildrenByLocalName(parent, "description");
|
|
10093
10126
|
const textMap = {};
|
|
10094
10127
|
for (const description of descriptions) {
|
|
10095
|
-
const
|
|
10128
|
+
const languageAttribute = description.getAttribute("language")?.trim();
|
|
10129
|
+
const language = languageAttribute != null && languageAttribute.length > 0 ? languageAttribute : "und";
|
|
10096
10130
|
const text = description.textContent.trim();
|
|
10097
|
-
if (text)
|
|
10131
|
+
if (text.length > 0)
|
|
10098
10132
|
textMap[language] = text;
|
|
10099
10133
|
}
|
|
10100
10134
|
return Object.keys(textMap).length > 0 ? textMap : void 0;
|
|
@@ -10130,12 +10164,14 @@ function ParseJSON_LD(Text, _Context = "") {
|
|
|
10130
10164
|
function firstKey(obj) {
|
|
10131
10165
|
for (const a in obj)
|
|
10132
10166
|
return a;
|
|
10167
|
+
return void 0;
|
|
10133
10168
|
}
|
|
10134
10169
|
function firstValue(obj) {
|
|
10135
10170
|
if (obj == void 0)
|
|
10136
10171
|
return void 0;
|
|
10137
10172
|
for (const a in obj)
|
|
10138
10173
|
return obj[a];
|
|
10174
|
+
return void 0;
|
|
10139
10175
|
}
|
|
10140
10176
|
var uiLocale = typeof window !== "undefined" ? window.navigator.language : "de";
|
|
10141
10177
|
function setUILocale(locale) {
|
|
@@ -10168,14 +10204,17 @@ function parseOBIS(OBIS) {
|
|
|
10168
10204
|
return `${String(media)}-${String(channel)}:${String(indicator)}.${String(mode)}.${String(quantities)}*${String(storage)}`;
|
|
10169
10205
|
}
|
|
10170
10206
|
var OBIS_RegExpr = new RegExp("((\\d+)\\-)?((\\d+):)?((\\d+)\\.)(\\d+)(\\.(\\d+))?(\\*(\\d+))?");
|
|
10207
|
+
function optionalOBISMatchValue(value) {
|
|
10208
|
+
return value ?? "0";
|
|
10209
|
+
}
|
|
10171
10210
|
function OBIS2Hex(OBIS) {
|
|
10172
10211
|
const OBISElements = OBIS.match(OBIS_RegExpr);
|
|
10173
|
-
return OBISElements == null ? "000000000000" : parseInt(OBISElements[2]).toString(16).padStart(2, "0") + // optional A
|
|
10174
|
-
parseInt(OBISElements[4]).toString(16).padStart(2, "0") + // optional B
|
|
10175
|
-
parseInt(OBISElements[6]).toString(16).padStart(2, "0") + // mandatory C
|
|
10176
|
-
parseInt(OBISElements[7]).toString(16).padStart(2, "0") + // mandatory D
|
|
10177
|
-
parseInt(OBISElements[9]).toString(16).padStart(2, "0") + // optional E
|
|
10178
|
-
parseInt(OBISElements[11]).toString(16).padStart(2, "0");
|
|
10212
|
+
return OBISElements == null ? "000000000000" : parseInt(optionalOBISMatchValue(OBISElements[2])).toString(16).padStart(2, "0") + // optional A
|
|
10213
|
+
parseInt(optionalOBISMatchValue(OBISElements[4])).toString(16).padStart(2, "0") + // optional B
|
|
10214
|
+
parseInt(optionalOBISMatchValue(OBISElements[6])).toString(16).padStart(2, "0") + // mandatory C
|
|
10215
|
+
parseInt(optionalOBISMatchValue(OBISElements[7])).toString(16).padStart(2, "0") + // mandatory D
|
|
10216
|
+
parseInt(optionalOBISMatchValue(OBISElements[9])).toString(16).padStart(2, "0") + // optional E
|
|
10217
|
+
parseInt(optionalOBISMatchValue(OBISElements[11])).toString(16).padStart(2, "0");
|
|
10179
10218
|
}
|
|
10180
10219
|
function OBIS2MeasurementName(OBISString) {
|
|
10181
10220
|
switch (OBISString) {
|
|
@@ -10218,15 +10257,15 @@ function measurementName2human(In) {
|
|
|
10218
10257
|
}
|
|
10219
10258
|
}
|
|
10220
10259
|
function IsNullOrEmpty(value) {
|
|
10221
|
-
return
|
|
10260
|
+
return value == null || value.length === 0;
|
|
10222
10261
|
}
|
|
10223
10262
|
function WhenNullOrEmpty(value, replacement) {
|
|
10224
|
-
if (
|
|
10263
|
+
if (value == null || value.length === 0)
|
|
10225
10264
|
return replacement;
|
|
10226
10265
|
return value;
|
|
10227
10266
|
}
|
|
10228
10267
|
function hex2bin(hex, Reverse) {
|
|
10229
|
-
if (Reverse) {
|
|
10268
|
+
if (Reverse === true) {
|
|
10230
10269
|
const reversed = [];
|
|
10231
10270
|
for (let i = 0; i < hex.length; i += 2)
|
|
10232
10271
|
reversed.push(hex.substring(i, i + 2));
|
|
@@ -10340,7 +10379,7 @@ function SetHex(dv, hex, offset, reverse) {
|
|
|
10340
10379
|
const bytes = parseHexString(hex);
|
|
10341
10380
|
const buffer = new ArrayBuffer(bytes.length);
|
|
10342
10381
|
const tv = new DataView(buffer);
|
|
10343
|
-
if (reverse)
|
|
10382
|
+
if (reverse === true)
|
|
10344
10383
|
bytes.reverse();
|
|
10345
10384
|
for (let i = 0; i < bytes.length; i++) {
|
|
10346
10385
|
dv.setUint8(offset + i, bytes[i] ?? 0);
|
|
@@ -10389,7 +10428,7 @@ function SetUInt32(dv, value, offset, reverse) {
|
|
|
10389
10428
|
const bytes = getInt32Bytes(value);
|
|
10390
10429
|
const buffer = new ArrayBuffer(bytes.length);
|
|
10391
10430
|
const tv = new DataView(buffer);
|
|
10392
|
-
if (reverse)
|
|
10431
|
+
if (reverse === true)
|
|
10393
10432
|
bytes.reverse();
|
|
10394
10433
|
for (let i = 0; i < bytes.length; i++) {
|
|
10395
10434
|
dv.setUint8(offset + i, bytes[i] ?? 0);
|
|
@@ -10401,7 +10440,7 @@ function SetUInt64(dv, value, offset, reverse) {
|
|
|
10401
10440
|
const bytes = getInt64Bytes(value);
|
|
10402
10441
|
const buffer = new ArrayBuffer(bytes.length);
|
|
10403
10442
|
const tv = new DataView(buffer);
|
|
10404
|
-
if (reverse)
|
|
10443
|
+
if (reverse === true)
|
|
10405
10444
|
bytes.reverse();
|
|
10406
10445
|
for (let i = 0; i < bytes.length; i++) {
|
|
10407
10446
|
dv.setUint8(offset + i, bytes[i] ?? 0);
|
|
@@ -10433,7 +10472,7 @@ function SetUInt32_withCode(dv, value, scale, obis, offset, reverse) {
|
|
|
10433
10472
|
const obisBytes = getInt8Bytes(obis);
|
|
10434
10473
|
const buffer = new ArrayBuffer(valueBytes.length + 2);
|
|
10435
10474
|
const tv = new DataView(buffer);
|
|
10436
|
-
if (reverse)
|
|
10475
|
+
if (reverse === true)
|
|
10437
10476
|
valueBytes.reverse();
|
|
10438
10477
|
for (let i = 0; i < valueBytes.length; i++) {
|
|
10439
10478
|
dv.setUint8(offset + i, valueBytes[i] ?? 0);
|
|
@@ -10496,8 +10535,7 @@ function CreateDiv2(ParentDiv, ChildClassName, ChildAInnerHTML, ChildBInnerHTML)
|
|
|
10496
10535
|
return childDiv;
|
|
10497
10536
|
}
|
|
10498
10537
|
function pad(text, paddingValue) {
|
|
10499
|
-
|
|
10500
|
-
text = "";
|
|
10538
|
+
text ??= "";
|
|
10501
10539
|
return (text + Array(2 * paddingValue).join("0")).substring(0, 2 * paddingValue);
|
|
10502
10540
|
}
|
|
10503
10541
|
async function sha256(message) {
|
|
@@ -10643,7 +10681,7 @@ function jsonPrettyPrinter(value, KeyLookup) {
|
|
|
10643
10681
|
value,
|
|
10644
10682
|
0,
|
|
10645
10683
|
"",
|
|
10646
|
-
KeyLookup ?? ((
|
|
10684
|
+
KeyLookup ?? ((_path, key) => key)
|
|
10647
10685
|
);
|
|
10648
10686
|
}
|
|
10649
10687
|
function _jsonPrettyPrinter(value, indentLevel, path, keyLookup) {
|
|
@@ -10722,13 +10760,15 @@ var ACrypt = class {
|
|
|
10722
10760
|
}
|
|
10723
10761
|
AddToVisualBuffer(valueHEX, bufferDiv, lineDiv) {
|
|
10724
10762
|
const newText = CreateDiv(bufferDiv, "entry", valueHEX);
|
|
10763
|
+
const lineId = getArrayLikeElement(lineDiv.children, 0, "Missing visual buffer line id");
|
|
10764
|
+
const lineHex = getArrayLikeElement(lineDiv.children, 1, "Missing visual buffer line hex");
|
|
10725
10765
|
newText.onmouseenter = function() {
|
|
10726
|
-
|
|
10727
|
-
|
|
10766
|
+
lineId.classList.add("overEntry");
|
|
10767
|
+
lineHex.classList.add("overEntry");
|
|
10728
10768
|
};
|
|
10729
10769
|
newText.onmouseleave = function() {
|
|
10730
|
-
|
|
10731
|
-
|
|
10770
|
+
lineId.classList.remove("overEntry");
|
|
10771
|
+
lineHex.classList.remove("overEntry");
|
|
10732
10772
|
};
|
|
10733
10773
|
lineDiv.onmouseenter = function() {
|
|
10734
10774
|
newText.classList.add("overEntry");
|
|
@@ -10744,7 +10784,7 @@ var Alfen = class {
|
|
|
10744
10784
|
this.chargy = chargy;
|
|
10745
10785
|
}
|
|
10746
10786
|
bufferToHex(buffer, Reverse) {
|
|
10747
|
-
return (Reverse ? Array.from(new Uint8Array(buffer)).reverse() : Array.from(new Uint8Array(buffer))).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
10787
|
+
return (Reverse === true ? Array.from(new Uint8Array(buffer)).reverse() : Array.from(new Uint8Array(buffer))).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
10748
10788
|
}
|
|
10749
10789
|
bufferToNumber(buffer) {
|
|
10750
10790
|
return parseInt(Array.from(new Uint8Array(buffer)).map((b) => b.toString(16).padStart(2, "0")).join(""), 16);
|
|
@@ -10779,31 +10819,32 @@ var Alfen = class {
|
|
|
10779
10819
|
signedValues = Content;
|
|
10780
10820
|
let previousTimestamp = "";
|
|
10781
10821
|
for (let i = 0; i < signedValues.length; i++) {
|
|
10782
|
-
const elements = signedValues
|
|
10783
|
-
if (elements
|
|
10822
|
+
const elements = getArrayElement(signedValues, i, "Missing Alfen signed value").split(";");
|
|
10823
|
+
if (elements.length != 6 && elements.length != 7)
|
|
10784
10824
|
return {
|
|
10785
10825
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
10786
|
-
message: this.chargy.
|
|
10826
|
+
message: this.chargy.GetMultilanguageText("Invalid number of signed meter values!"),
|
|
10787
10827
|
certainty: 0
|
|
10788
10828
|
};
|
|
10789
|
-
const FormatId = elements
|
|
10790
|
-
const Type = elements
|
|
10791
|
-
const BlobVersion = elements
|
|
10792
|
-
const
|
|
10793
|
-
const
|
|
10794
|
-
const
|
|
10829
|
+
const FormatId = getArrayElement(elements, 0, "Missing Alfen format id");
|
|
10830
|
+
const Type = getArrayElement(elements, 1, "Missing Alfen type");
|
|
10831
|
+
const BlobVersion = getArrayElement(elements, 2, "Missing Alfen blob version");
|
|
10832
|
+
const publicKeyValue = getArrayElement(elements, 3, "Missing Alfen public key");
|
|
10833
|
+
const PublicKey = this.chargy.base32Decode(publicKeyValue, "RFC4648");
|
|
10834
|
+
const DataSet = this.chargy.base32Decode(getArrayElement(elements, 4, "Missing Alfen data set"), "RFC4648");
|
|
10835
|
+
const Signature = this.chargy.base32Decode(getArrayElement(elements, 5, "Missing Alfen signature"), "RFC4648");
|
|
10795
10836
|
if (common.PublicKey === "")
|
|
10796
|
-
common.PublicKey =
|
|
10797
|
-
else if (
|
|
10837
|
+
common.PublicKey = publicKeyValue;
|
|
10838
|
+
else if (publicKeyValue !== common.PublicKey)
|
|
10798
10839
|
return {
|
|
10799
10840
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
10800
|
-
message: this.chargy.
|
|
10841
|
+
message: this.chargy.GetMultilanguageText("Inconsistent public keys!"),
|
|
10801
10842
|
certainty: 0
|
|
10802
10843
|
};
|
|
10803
|
-
if (FormatId !== "AP" || Type
|
|
10844
|
+
if (FormatId !== "AP" || Type.length !== 1 || BlobVersion.length !== 1 || BlobVersion !== "3" || PublicKey.byteLength !== 25 || DataSet.byteLength !== 82 || Signature.byteLength !== 48) {
|
|
10804
10845
|
return {
|
|
10805
10846
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
10806
|
-
message: this.chargy.
|
|
10847
|
+
message: this.chargy.GetMultilanguageText("Invalid charging session format!"),
|
|
10807
10848
|
certainty: 0
|
|
10808
10849
|
};
|
|
10809
10850
|
}
|
|
@@ -10828,7 +10869,7 @@ var Alfen = class {
|
|
|
10828
10869
|
else if (AdapterId !== common.AdapterId)
|
|
10829
10870
|
return {
|
|
10830
10871
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
10831
|
-
message: this.chargy.
|
|
10872
|
+
message: this.chargy.GetMultilanguageText("Inconsistent Alfen adapter identification!"),
|
|
10832
10873
|
certainty: 0
|
|
10833
10874
|
};
|
|
10834
10875
|
if (common.AdapterFWVersion === "")
|
|
@@ -10836,7 +10877,7 @@ var Alfen = class {
|
|
|
10836
10877
|
else if (AdapterFWVersion !== common.AdapterFWVersion)
|
|
10837
10878
|
return {
|
|
10838
10879
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
10839
|
-
message: this.chargy.
|
|
10880
|
+
message: this.chargy.GetMultilanguageText("Inconsistent Alfen adapter firmware version!"),
|
|
10840
10881
|
certainty: 0
|
|
10841
10882
|
};
|
|
10842
10883
|
if (common.AdapterFWChecksum === "")
|
|
@@ -10844,7 +10885,7 @@ var Alfen = class {
|
|
|
10844
10885
|
else if (AdapterFWChecksum !== common.AdapterFWChecksum)
|
|
10845
10886
|
return {
|
|
10846
10887
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
10847
|
-
message: this.chargy.
|
|
10888
|
+
message: this.chargy.GetMultilanguageText("Inconsistent Alfen adapter firmware checksum!"),
|
|
10848
10889
|
certainty: 0
|
|
10849
10890
|
};
|
|
10850
10891
|
if (common.MeterId === "")
|
|
@@ -10852,7 +10893,7 @@ var Alfen = class {
|
|
|
10852
10893
|
else if (MeterId !== common.MeterId)
|
|
10853
10894
|
return {
|
|
10854
10895
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
10855
|
-
message: this.chargy.
|
|
10896
|
+
message: this.chargy.GetMultilanguageText("Inconsistent meter identification!"),
|
|
10856
10897
|
certainty: 0
|
|
10857
10898
|
};
|
|
10858
10899
|
if (common.ObisId === "")
|
|
@@ -10860,7 +10901,7 @@ var Alfen = class {
|
|
|
10860
10901
|
else if (ObisId !== common.ObisId)
|
|
10861
10902
|
return {
|
|
10862
10903
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
10863
|
-
message: this.chargy.
|
|
10904
|
+
message: this.chargy.GetMultilanguageText("Inconsistent OBIS code!"),
|
|
10864
10905
|
certainty: 0
|
|
10865
10906
|
};
|
|
10866
10907
|
if (common.UnitEncoded === 0)
|
|
@@ -10868,7 +10909,7 @@ var Alfen = class {
|
|
|
10868
10909
|
else if (UnitEncoded !== common.UnitEncoded)
|
|
10869
10910
|
return {
|
|
10870
10911
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
10871
|
-
message: this.chargy.
|
|
10912
|
+
message: this.chargy.GetMultilanguageText("Inconsistent unit (encoded) value!"),
|
|
10872
10913
|
certainty: 0
|
|
10873
10914
|
};
|
|
10874
10915
|
if (common.Scalar === "")
|
|
@@ -10876,7 +10917,7 @@ var Alfen = class {
|
|
|
10876
10917
|
else if (Scalar !== common.Scalar)
|
|
10877
10918
|
return {
|
|
10878
10919
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
10879
|
-
message: this.chargy.
|
|
10920
|
+
message: this.chargy.GetMultilanguageText("Inconsistent measurement scalar!"),
|
|
10880
10921
|
certainty: 0
|
|
10881
10922
|
};
|
|
10882
10923
|
if (common.UID === "")
|
|
@@ -10884,7 +10925,7 @@ var Alfen = class {
|
|
|
10884
10925
|
else if (UID !== common.UID)
|
|
10885
10926
|
return {
|
|
10886
10927
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
10887
|
-
message: this.chargy.
|
|
10928
|
+
message: this.chargy.GetMultilanguageText("Inconsistent user identification!"),
|
|
10888
10929
|
certainty: 0
|
|
10889
10930
|
};
|
|
10890
10931
|
if (common.InternalSessionId === 0)
|
|
@@ -10892,13 +10933,13 @@ var Alfen = class {
|
|
|
10892
10933
|
else if (InternalSessionId !== common.InternalSessionId)
|
|
10893
10934
|
return {
|
|
10894
10935
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
10895
|
-
message: this.chargy.
|
|
10936
|
+
message: this.chargy.GetMultilanguageText("Inconsistent internal charging session identification!"),
|
|
10896
10937
|
certainty: 0
|
|
10897
10938
|
};
|
|
10898
10939
|
if (previousTimestamp !== "" && previousTimestamp > Timestamp)
|
|
10899
10940
|
return {
|
|
10900
10941
|
status: "InconsistentTimestamps" /* InconsistentTimestamps */,
|
|
10901
|
-
message: this.chargy.
|
|
10942
|
+
message: this.chargy.GetMultilanguageText("Inconsistent timestamps!"),
|
|
10902
10943
|
certainty: 0
|
|
10903
10944
|
};
|
|
10904
10945
|
else
|
|
@@ -10917,14 +10958,8 @@ var Alfen = class {
|
|
|
10917
10958
|
const evseId = asString(containerInfos["EVSEId"]) ?? "DE*GEF*EVSE*CHARGY*1";
|
|
10918
10959
|
const chargingStationId = asString(containerInfos["ChargingStationId"]) ?? "DE*GEF*STATION*CHARGY*1";
|
|
10919
10960
|
const chargingSessionId = asString(chargingSession?.["@id"]);
|
|
10920
|
-
const firstDataSet = common.dataSets
|
|
10921
|
-
const lastDataSet = common.dataSets
|
|
10922
|
-
if (firstDataSet === void 0 || lastDataSet === void 0)
|
|
10923
|
-
return {
|
|
10924
|
-
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
10925
|
-
message: this.chargy.GetLocalizedMessage("Invalid number of signed meter values!"),
|
|
10926
|
-
certainty: 0
|
|
10927
|
-
};
|
|
10961
|
+
const firstDataSet = getFirstArrayElement(common.dataSets, "Missing first Alfen data set");
|
|
10962
|
+
const lastDataSet = getLastArrayElement(common.dataSets, "Missing last Alfen data set");
|
|
10928
10963
|
const _CTR = {
|
|
10929
10964
|
"@id": chargingSessionId ?? common.InternalSessionId.toString(),
|
|
10930
10965
|
"@context": "https://open.charging.cloud/contexts/CTR+json",
|
|
@@ -11054,7 +11089,7 @@ var Alfen = class {
|
|
|
11054
11089
|
} catch (exception) {
|
|
11055
11090
|
return {
|
|
11056
11091
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
11057
|
-
message: this.chargy.
|
|
11092
|
+
message: this.chargy.GetMultilanguageText("Exception occured: " + (exception instanceof Error ? exception.message : String(exception))),
|
|
11058
11093
|
certainty: 0
|
|
11059
11094
|
};
|
|
11060
11095
|
}
|
|
@@ -11205,62 +11240,62 @@ var AlfenCrypt01 = class extends ACrypt {
|
|
|
11205
11240
|
}
|
|
11206
11241
|
return {};
|
|
11207
11242
|
}
|
|
11208
|
-
async ViewMeasurement(measurementValue,
|
|
11243
|
+
async ViewMeasurement(measurementValue, _errorDiv, introDiv, infoDiv, PlainTextDiv, HashedPlainTextDiv, PublicKeyDiv, SignatureExpectedDiv, SignatureCheckDiv) {
|
|
11209
11244
|
const result = measurementValue.result;
|
|
11210
11245
|
{
|
|
11211
11246
|
introDiv.innerHTML = this.chargy.GetLocalizedMessage("The following data of the charging session is relevant for metrological and legal metrological purposes and therefore part of the digital signature").replace("{methodName}", "AlfenCrypt01").replace("{cryptoAlgorithm}", this.description);
|
|
11212
11247
|
}
|
|
11213
11248
|
{
|
|
11214
|
-
if (PlainTextDiv.parentElement
|
|
11215
|
-
PlainTextDiv.parentElement.children
|
|
11249
|
+
if (PlainTextDiv.parentElement) {
|
|
11250
|
+
getArrayLikeElement(PlainTextDiv.parentElement.children, 0, "Missing plain text header").innerHTML = this.chargy.GetLocalizedMessage("Plain text") + " (320 Bytes, hex)";
|
|
11216
11251
|
}
|
|
11217
11252
|
PlainTextDiv.style.fontFamily = "";
|
|
11218
11253
|
PlainTextDiv.style.whiteSpace = "";
|
|
11219
11254
|
PlainTextDiv.style.maxHeight = "";
|
|
11220
11255
|
PlainTextDiv.style.overflowY = "";
|
|
11221
|
-
this.CreateLocalizedLine("Adapter Id", measurementValue.measurement.adapterId, result.adapterId
|
|
11222
|
-
this.CreateLocalizedLine("Adapter Firmware Version", measurementValue.measurement.adapterFWVersion, result.adapterFWVersion
|
|
11223
|
-
this.CreateLocalizedLine("Adapter Firmware Checksum", measurementValue.measurement.adapterFWChecksum, result.adapterFWChecksum
|
|
11224
|
-
this.CreateLocalizedLine("Meter number", measurementValue.measurement.energyMeterId, result.meterId
|
|
11256
|
+
this.CreateLocalizedLine("Adapter Id", measurementValue.measurement.adapterId, result.adapterId ?? "", infoDiv, PlainTextDiv);
|
|
11257
|
+
this.CreateLocalizedLine("Adapter Firmware Version", measurementValue.measurement.adapterFWVersion, result.adapterFWVersion ?? "", infoDiv, PlainTextDiv);
|
|
11258
|
+
this.CreateLocalizedLine("Adapter Firmware Checksum", measurementValue.measurement.adapterFWChecksum, result.adapterFWChecksum ?? "", infoDiv, PlainTextDiv);
|
|
11259
|
+
this.CreateLocalizedLine("Meter number", measurementValue.measurement.energyMeterId, result.meterId ?? "", infoDiv, PlainTextDiv);
|
|
11225
11260
|
this.CreateLocalizedLine(
|
|
11226
11261
|
"Meter status",
|
|
11227
11262
|
hex2bin(measurementValue.statusMeter, true) + " (" + measurementValue.statusMeter + ' hex)<br /><span class="statusInfos">' + this.DecodeMeterStatus(measurementValue.statusMeter).join("<br />") + "</span>",
|
|
11228
|
-
result.statusMeter
|
|
11263
|
+
result.statusMeter ?? "",
|
|
11229
11264
|
infoDiv,
|
|
11230
11265
|
PlainTextDiv
|
|
11231
11266
|
);
|
|
11232
11267
|
this.CreateLocalizedLine(
|
|
11233
11268
|
"Adapter status",
|
|
11234
11269
|
hex2bin(measurementValue.statusAdapter, true) + " (" + measurementValue.statusAdapter + ' hex)<br /><span class="statusInfos">' + this.DecodeAdapterStatus(measurementValue.statusAdapter).join("<br />") + "</span>",
|
|
11235
|
-
result.statusAdapter
|
|
11270
|
+
result.statusAdapter ?? "",
|
|
11236
11271
|
infoDiv,
|
|
11237
11272
|
PlainTextDiv
|
|
11238
11273
|
);
|
|
11239
|
-
this.CreateLocalizedLine("Seconds index", measurementValue.secondsIndex, result.secondsIndex
|
|
11240
|
-
this.CreateLocalizedLine("Timestamp", UTC2human(measurementValue.timestamp), result.timestamp
|
|
11241
|
-
this.CreateLocalizedLine("OBIS code", measurementValue.measurement.obis, result.obisId
|
|
11242
|
-
this.CreateLocalizedLine("Unit (encoded)", measurementValue.measurement.unitEncoded ?? 0, result.unitEncoded
|
|
11243
|
-
this.CreateLocalizedLine("Scaling", measurementValue.measurement.scale, result.scalar
|
|
11244
|
-
this.CreateLocalizedLine("Measurement Value", measurementValue.value.toString() + " Wh", result.value
|
|
11245
|
-
this.CreateLocalizedLine("Authorization", (measurementValue.measurement.chargingSession?.authorizationStart["@id"] ?? "") + " hex", pad(result.uid, 20)
|
|
11246
|
-
this.CreateLocalizedLine("SessionId", measurementValue.measurement.chargingSession?.["@id"] ?? "", result.sessionId
|
|
11247
|
-
this.CreateLocalizedLine("Pagination counter", measurementValue.paginationId, result.paging
|
|
11274
|
+
this.CreateLocalizedLine("Seconds index", measurementValue.secondsIndex, result.secondsIndex ?? "", infoDiv, PlainTextDiv);
|
|
11275
|
+
this.CreateLocalizedLine("Timestamp", UTC2human(measurementValue.timestamp), result.timestamp ?? "", infoDiv, PlainTextDiv);
|
|
11276
|
+
this.CreateLocalizedLine("OBIS code", measurementValue.measurement.obis, result.obisId ?? "", infoDiv, PlainTextDiv);
|
|
11277
|
+
this.CreateLocalizedLine("Unit (encoded)", measurementValue.measurement.unitEncoded ?? 0, result.unitEncoded ?? "", infoDiv, PlainTextDiv);
|
|
11278
|
+
this.CreateLocalizedLine("Scaling", measurementValue.measurement.scale, result.scalar ?? "", infoDiv, PlainTextDiv);
|
|
11279
|
+
this.CreateLocalizedLine("Measurement Value", measurementValue.value.toString() + " Wh", result.value ?? "", infoDiv, PlainTextDiv);
|
|
11280
|
+
this.CreateLocalizedLine("Authorization", (measurementValue.measurement.chargingSession?.authorizationStart["@id"] ?? "") + " hex", pad(result.uid, 20), infoDiv, PlainTextDiv);
|
|
11281
|
+
this.CreateLocalizedLine("SessionId", measurementValue.measurement.chargingSession?.["@id"] ?? "", result.sessionId ?? "", infoDiv, PlainTextDiv);
|
|
11282
|
+
this.CreateLocalizedLine("Pagination counter", measurementValue.paginationId, result.paging ?? "", infoDiv, PlainTextDiv);
|
|
11248
11283
|
}
|
|
11249
11284
|
{
|
|
11250
|
-
if (HashedPlainTextDiv.parentElement
|
|
11251
|
-
HashedPlainTextDiv.parentElement.children
|
|
11285
|
+
if (HashedPlainTextDiv.parentElement) {
|
|
11286
|
+
getArrayLikeElement(HashedPlainTextDiv.parentElement.children, 0, "Missing hashed plain text header").innerHTML = this.chargy.GetLocalizedMessage("Hashed plain text") + " (SHA256, hex)";
|
|
11252
11287
|
}
|
|
11253
11288
|
const hashValueText = typeof result.hashValue === "string" ? result.hashValue : result.hashValue?.toString(16) ?? "";
|
|
11254
11289
|
HashedPlainTextDiv.innerHTML = hashValueText.match(/.{1,8}/g)?.join(" ") ?? "";
|
|
11255
11290
|
}
|
|
11256
|
-
if (result.publicKey && result.publicKey
|
|
11257
|
-
if (PublicKeyDiv.parentElement
|
|
11258
|
-
PublicKeyDiv.parentElement.children
|
|
11291
|
+
if (result.publicKey != null && result.publicKey.length > 0) {
|
|
11292
|
+
if (PublicKeyDiv.parentElement) {
|
|
11293
|
+
getArrayLikeElement(PublicKeyDiv.parentElement.children, 0, "Missing public key header").innerHTML = this.chargy.GetLocalizedMessage("Public Key") + " (" + (result.publicKeyFormat != null && result.publicKeyFormat.length > 0 ? result.publicKeyFormat + ", " : "") + "base32)";
|
|
11259
11294
|
}
|
|
11260
11295
|
if (!IsNullOrEmpty(result.publicKey))
|
|
11261
11296
|
PublicKeyDiv.innerHTML = result.publicKey.match(/.{1,4}/g)?.join(" ") ?? "";
|
|
11262
11297
|
}
|
|
11263
|
-
if (PublicKeyDiv.parentElement
|
|
11298
|
+
if (PublicKeyDiv.parentElement?.children[3]) {
|
|
11264
11299
|
PublicKeyDiv.parentElement.children[3].innerHTML = "";
|
|
11265
11300
|
if (result.publicKeySignatures) {
|
|
11266
11301
|
for (const signature of result.publicKeySignatures) {
|
|
@@ -11279,14 +11314,14 @@ var AlfenCrypt01 = class extends ACrypt {
|
|
|
11279
11314
|
}
|
|
11280
11315
|
}
|
|
11281
11316
|
if (result.signature != null) {
|
|
11282
|
-
if (SignatureExpectedDiv.parentElement
|
|
11283
|
-
SignatureExpectedDiv.parentElement.children
|
|
11317
|
+
if (SignatureExpectedDiv.parentElement) {
|
|
11318
|
+
getArrayLikeElement(SignatureExpectedDiv.parentElement.children, 0, "Missing expected signature header").innerHTML = this.chargy.GetLocalizedMessage("Expected signature") + " (" + (result.signature.format ?? "") + ", hex)";
|
|
11284
11319
|
}
|
|
11285
|
-
if (result.signature.r && result.signature.s) {
|
|
11320
|
+
if (result.signature.r != null && result.signature.r.length > 0 && result.signature.s != null && result.signature.s.length > 0) {
|
|
11286
11321
|
const signatureR = result.signature.r.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "-";
|
|
11287
11322
|
const signatureS = result.signature.s.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "-";
|
|
11288
11323
|
SignatureExpectedDiv.innerHTML = "r: " + signatureR + "<br />s: " + signatureS;
|
|
11289
|
-
} else if (result.signature.value)
|
|
11324
|
+
} else if (result.signature.value != null && result.signature.value.length > 0)
|
|
11290
11325
|
SignatureExpectedDiv.innerHTML = result.signature.value.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "-";
|
|
11291
11326
|
}
|
|
11292
11327
|
{
|
|
@@ -11379,18 +11414,18 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
11379
11414
|
tryToParseBSM_WS36aMeasurements(CTR, ExpectedEVSEId, ExpectedCscSwVersion, Measurements) {
|
|
11380
11415
|
if (!Array.isArray(Measurements)) return {
|
|
11381
11416
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
11382
|
-
message: this.chargy.
|
|
11417
|
+
message: this.chargy.GetMultilanguageText("MissingOrInvalidSignedMeterValues"),
|
|
11383
11418
|
certainty: 0
|
|
11384
11419
|
};
|
|
11385
11420
|
if (Measurements.length < 2) return {
|
|
11386
11421
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
11387
|
-
message: this.chargy.
|
|
11422
|
+
message: this.chargy.GetMultilanguageText("AtLeastTwoSignedMeterValuesRequired"),
|
|
11388
11423
|
certainty: 0
|
|
11389
11424
|
};
|
|
11390
11425
|
const firstMeasurement = Measurements[0];
|
|
11391
11426
|
if (!isMandatoryJSONObject(firstMeasurement)) return {
|
|
11392
11427
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
11393
|
-
message: this.chargy.
|
|
11428
|
+
message: this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalidSignedMeterValueP", 1),
|
|
11394
11429
|
certainty: 0
|
|
11395
11430
|
};
|
|
11396
11431
|
const errors = new Array();
|
|
@@ -11399,51 +11434,51 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
11399
11434
|
let secondaryErrors = 0;
|
|
11400
11435
|
try {
|
|
11401
11436
|
if (!isMandatoryString(firstMeasurement["@context"]))
|
|
11402
|
-
errors.push(this.chargy.
|
|
11437
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_JSONContextP", 1)));
|
|
11403
11438
|
const meterInfo = firstMeasurement["meterInfo"];
|
|
11404
11439
|
if (!isMandatoryJSONObject(meterInfo)) {
|
|
11405
|
-
errors.push(this.chargy.
|
|
11440
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfoP", 1)));
|
|
11406
11441
|
secondaryErrors += 5;
|
|
11407
11442
|
} else {
|
|
11408
11443
|
if (!isMandatoryString(meterInfo["firmwareVersion"]))
|
|
11409
|
-
errors.push(this.chargy.
|
|
11444
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_FirmwareVersionP", 1)));
|
|
11410
11445
|
if (!isMandatoryString(meterInfo["publicKey"]))
|
|
11411
|
-
errors.push(this.chargy.
|
|
11446
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_PublicKeyP", 1)));
|
|
11412
11447
|
if (!isMandatoryString(meterInfo["meterId"]))
|
|
11413
|
-
errors.push(this.chargy.
|
|
11448
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_MeterIdP", 1)));
|
|
11414
11449
|
if (!isMandatoryString(meterInfo["manufacturer"]))
|
|
11415
|
-
errors.push(this.chargy.
|
|
11450
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_ManufacturerP", 1)));
|
|
11416
11451
|
if (!isMandatoryString(meterInfo["type"]))
|
|
11417
|
-
errors.push(this.chargy.
|
|
11452
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_TypeP", 1)));
|
|
11418
11453
|
}
|
|
11419
11454
|
const contract = firstMeasurement["contract"];
|
|
11420
11455
|
if (!isMandatoryJSONObject(contract)) {
|
|
11421
|
-
errors.push(this.chargy.
|
|
11456
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_ContractP", 1)));
|
|
11422
11457
|
secondaryErrors += 2;
|
|
11423
11458
|
} else {
|
|
11424
11459
|
if (!isMandatoryString(contract["id"]))
|
|
11425
|
-
errors.push(this.chargy.
|
|
11460
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_Contract_IdP", 1)));
|
|
11426
11461
|
if (!isOptionalString(contract["type"]))
|
|
11427
|
-
errors.push(this.chargy.
|
|
11462
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_Contract_TypeP", 1)));
|
|
11428
11463
|
}
|
|
11429
11464
|
const value = firstMeasurement["value"];
|
|
11430
11465
|
if (!isMandatoryJSONObject(value)) {
|
|
11431
|
-
errors.push(this.chargy.
|
|
11466
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_ValueP", 1)));
|
|
11432
11467
|
secondaryErrors += 8;
|
|
11433
11468
|
} else {
|
|
11434
11469
|
const measurand = value["measurand"];
|
|
11435
11470
|
if (!isMandatoryJSONObject(measurand)) {
|
|
11436
|
-
errors.push(this.chargy.
|
|
11471
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeasurandP", 1)));
|
|
11437
11472
|
secondaryErrors += 2;
|
|
11438
11473
|
} else {
|
|
11439
11474
|
if (!isMandatoryString(measurand["id"]))
|
|
11440
|
-
errors.push(this.chargy.
|
|
11475
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_Measurand_IdentificationP", 1)));
|
|
11441
11476
|
if (!isMandatoryString(measurand["name"]))
|
|
11442
|
-
errors.push(this.chargy.
|
|
11477
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_Measurand_NameP", 1)));
|
|
11443
11478
|
}
|
|
11444
11479
|
const measuredValue = value["measuredValue"];
|
|
11445
11480
|
if (!isMandatoryJSONObject(measuredValue)) {
|
|
11446
|
-
errors.push(this.chargy.
|
|
11481
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeasuredValueP", 1)));
|
|
11447
11482
|
secondaryErrors += 4;
|
|
11448
11483
|
} else {
|
|
11449
11484
|
}
|
|
@@ -11521,18 +11556,22 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
11521
11556
|
if (currentMeasurement === void 0)
|
|
11522
11557
|
throw new Error(`Invalid signed meter value #${String(measurementCounter)}!`);
|
|
11523
11558
|
if (currentMeasurement["@context"] !== common.context)
|
|
11524
|
-
currentErrors.push(this.chargy.
|
|
11559
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_JSONContextP", measurementCounter)));
|
|
11525
11560
|
const currentId = currentMeasurement["@id"];
|
|
11526
11561
|
if (previousId !== "" && typeof currentId === "string") {
|
|
11527
11562
|
if (typeof previousId !== "string")
|
|
11528
11563
|
throw new Error(`Invalid identification of signed meter value #${String(measurementCounter - 1)}!`);
|
|
11529
11564
|
const previousParts = previousId.split("-");
|
|
11530
11565
|
const currentParts = currentId.split("-");
|
|
11531
|
-
|
|
11566
|
+
const previousPrefix = previousParts.at(0);
|
|
11567
|
+
const previousCounter = previousParts.at(1);
|
|
11568
|
+
const currentPrefix = currentParts.at(0);
|
|
11569
|
+
const currentCounter = currentParts.at(1);
|
|
11570
|
+
if (previousParts.length !== 2 || currentParts.length !== 2 || previousPrefix !== currentPrefix || previousCounter === void 0 || currentCounter === void 0 || // parseInt returns NaN in case parsing fails which in turn does not match
|
|
11532
11571
|
// anything (not even NaN). This way we are checking that both counter values
|
|
11533
11572
|
// are numeric too.
|
|
11534
|
-
parseInt(
|
|
11535
|
-
currentErrors.push(this.chargy.
|
|
11573
|
+
parseInt(previousCounter, 10) >= parseInt(currentCounter, 10)) {
|
|
11574
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_MeasurementIdP", measurementCounter)));
|
|
11536
11575
|
}
|
|
11537
11576
|
}
|
|
11538
11577
|
previousId = currentId;
|
|
@@ -11541,11 +11580,11 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
11541
11580
|
const displayedFormatObj2 = asJSONObject(valueObj2?.["displayedFormat"]);
|
|
11542
11581
|
const currentTime = asString(currentMeasurement["time"]) ?? "";
|
|
11543
11582
|
if (previousTime !== "" && currentTime <= previousTime)
|
|
11544
|
-
currentErrors.push(this.chargy.
|
|
11583
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_TimestampP", measurementCounter)));
|
|
11545
11584
|
previousTime = currentTime;
|
|
11546
11585
|
const currentValue = asNumber(measuredValueObj2?.["value"]);
|
|
11547
11586
|
if (previousValue !== void 0 && currentValue !== void 0 && currentValue < previousValue)
|
|
11548
|
-
currentErrors.push(this.chargy.
|
|
11587
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_Measurement_ValueP", measurementCounter)));
|
|
11549
11588
|
previousValue = currentValue;
|
|
11550
11589
|
const additionalValuesRaw = currentMeasurement["additionalValues"];
|
|
11551
11590
|
if (!isMandatoryJSONArray(additionalValuesRaw))
|
|
@@ -11569,78 +11608,78 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
11569
11608
|
precision: asNumber(displayedFormat?.["precision"])
|
|
11570
11609
|
};
|
|
11571
11610
|
});
|
|
11572
|
-
if (currentMeasurement["meterInfo"]) {
|
|
11611
|
+
if (currentMeasurement["meterInfo"] != null) {
|
|
11573
11612
|
const meterInfoObj2 = asJSONObject(currentMeasurement["meterInfo"]);
|
|
11574
11613
|
if (meterInfoObj2?.["firmwareVersion"] !== common.meterInfo_firmwareVersion)
|
|
11575
|
-
currentErrors.push(this.chargy.
|
|
11614
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_MeterInfo_FirmwareVersionP", measurementCounter)));
|
|
11576
11615
|
if (meterInfoObj2?.["publicKey"] !== common.meterInfo_publicKey)
|
|
11577
|
-
currentErrors.push(this.chargy.
|
|
11616
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_MeterInfo_PublicKeyP", measurementCounter)));
|
|
11578
11617
|
if (meterInfoObj2?.["meterId"] !== common.meterInfo_meterId)
|
|
11579
|
-
currentErrors.push(this.chargy.
|
|
11580
|
-
if (meterInfoObj2?.["meterId"] !== additionalValues.
|
|
11581
|
-
currentErrors.push(this.chargy.
|
|
11618
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_MeterInfo_MeterIdP", measurementCounter)));
|
|
11619
|
+
if (meterInfoObj2?.["meterId"] !== additionalValues.find((element) => element.measurandName === "MA1")?.value)
|
|
11620
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_MeterInfo_MeterIdP", measurementCounter)));
|
|
11582
11621
|
if (meterInfoObj2?.["manufacturer"] !== common.meterInfo_manufacturer)
|
|
11583
|
-
currentErrors.push(this.chargy.
|
|
11622
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_MeterInfo_ManufacturerP", measurementCounter)));
|
|
11584
11623
|
if (meterInfoObj2?.["type"] !== common.meterInfo_type)
|
|
11585
|
-
currentErrors.push(this.chargy.
|
|
11624
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_MeterInfo_TypeP", measurementCounter)));
|
|
11586
11625
|
}
|
|
11587
|
-
if (currentMeasurement["contract"]) {
|
|
11626
|
+
if (currentMeasurement["contract"] != null) {
|
|
11588
11627
|
const contractObj2 = asJSONObject(currentMeasurement["contract"]);
|
|
11589
|
-
if (additionalValues.filter((element) => element.measurandName?.startsWith("Meta") && asString(element.value)?.startsWith("contract-id:")).length == 0)
|
|
11590
|
-
currentErrors.push(this.chargy.
|
|
11628
|
+
if (additionalValues.filter((element) => element.measurandName?.startsWith("Meta") === true && asString(element.value)?.startsWith("contract-id:") === true).length == 0)
|
|
11629
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_Contract_IdP", measurementCounter)));
|
|
11591
11630
|
if (contractObj2?.["id"] !== common.contract_id)
|
|
11592
|
-
currentErrors.push(this.chargy.
|
|
11631
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_Contract_IdP", measurementCounter)));
|
|
11593
11632
|
if (contractObj2?.["type"] !== common.contract_type)
|
|
11594
|
-
currentErrors.push(this.chargy.
|
|
11595
|
-
const contractInfo = additionalValues.
|
|
11633
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_Contract_TypeP", measurementCounter)));
|
|
11634
|
+
const contractInfo = additionalValues.find((element) => element.measurandName?.startsWith("Meta") === true && asString(element.value)?.startsWith("contract-id:") === true)?.value;
|
|
11596
11635
|
if (contractInfo != null) {
|
|
11597
|
-
if (contractObj2?.["type"] && contractInfo !== "contract-id: " + (common.contract_type ?? "-") + ":" + common.contract_id)
|
|
11598
|
-
currentErrors.push(this.chargy.
|
|
11599
|
-
if (
|
|
11600
|
-
currentErrors.push(this.chargy.
|
|
11636
|
+
if (contractObj2?.["type"] != null && contractInfo !== "contract-id: " + (common.contract_type ?? "-") + ":" + common.contract_id)
|
|
11637
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_Contract_IdP", measurementCounter)));
|
|
11638
|
+
if (contractObj2?.["type"] == null && contractInfo !== "contract-id: " + common.contract_id)
|
|
11639
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_Contract_IdP", measurementCounter)));
|
|
11601
11640
|
}
|
|
11602
11641
|
}
|
|
11603
11642
|
const rcrInAdditional = additionalValues.find((element) => element.measurandName == "RCR");
|
|
11604
11643
|
if (currentMeasurement["value"] == null)
|
|
11605
11644
|
throw new Error(`Missing value within signed meter value #${String(measurementCounter)}!`);
|
|
11606
|
-
if ((valueObj2?.["measurand"] || valueObj2?.["measuredValue"]) && rcrInAdditional === void 0)
|
|
11645
|
+
if ((valueObj2?.["measurand"] != null || valueObj2?.["measuredValue"] != null) && rcrInAdditional === void 0)
|
|
11607
11646
|
throw new Error(`Missing 'RCR' within the additional values of signed meter value #${String(measurementCounter)}!`);
|
|
11608
|
-
if (valueObj2?.["measurand"]) {
|
|
11647
|
+
if (valueObj2?.["measurand"] != null) {
|
|
11609
11648
|
const measurandObj2 = asJSONObject(valueObj2["measurand"]);
|
|
11610
11649
|
if (measurandObj2?.["id"] !== common.value_measurand_id || measurandObj2["id"] !== rcrInAdditional?.measurandId)
|
|
11611
|
-
currentErrors.push(this.chargy.
|
|
11650
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_Measurand_IdentificationP", measurementCounter)));
|
|
11612
11651
|
if (measurandObj2?.["name"] !== common.value_measurand_name || measurandObj2["name"] !== rcrInAdditional?.measurandName)
|
|
11613
|
-
currentErrors.push(this.chargy.
|
|
11652
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_Measurand_NameP", measurementCounter)));
|
|
11614
11653
|
}
|
|
11615
|
-
if (valueObj2?.["measuredValue"]) {
|
|
11654
|
+
if (valueObj2?.["measuredValue"] != null) {
|
|
11616
11655
|
if (measuredValueObj2?.["value"] !== rcrInAdditional?.value)
|
|
11617
|
-
currentErrors.push(this.chargy.
|
|
11656
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValueP", measurementCounter)));
|
|
11618
11657
|
if (measuredValueObj2?.["scale"] !== common.value_measuredValue_scale || measuredValueObj2?.["scale"] !== rcrInAdditional?.scale)
|
|
11619
|
-
currentErrors.push(this.chargy.
|
|
11658
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_ScaleP", measurementCounter)));
|
|
11620
11659
|
if (measuredValueObj2?.["unit"] !== common.value_measuredValue_unit || measuredValueObj2["unit"] !== rcrInAdditional?.unit)
|
|
11621
|
-
currentErrors.push(this.chargy.
|
|
11660
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_UnitP", measurementCounter)));
|
|
11622
11661
|
if (measuredValueObj2?.["unitEncoded"] !== common.value_measuredValue_unitEncoded || measuredValueObj2?.["unitEncoded"] !== rcrInAdditional?.unitEncoded)
|
|
11623
|
-
currentErrors.push(this.chargy.
|
|
11662
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_UnitEncodedP", measurementCounter)));
|
|
11624
11663
|
if (measuredValueObj2?.["valueType"] !== common.value_measuredValue_valueType || measuredValueObj2?.["valueType"] !== rcrInAdditional?.valueType)
|
|
11625
|
-
currentErrors.push(this.chargy.
|
|
11664
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_TypeP", measurementCounter)));
|
|
11626
11665
|
}
|
|
11627
|
-
if (currentMeasurement["chargePoint"] && asJSONObject(currentMeasurement["chargePoint"])?.["softwareVersion"] !== common.chargePoint_softwareVersion)
|
|
11628
|
-
currentErrors.push(this.chargy.
|
|
11629
|
-
const signedEVSEId = additionalValues.filter((element) => element.measurandName?.startsWith("Meta") && asString(element.value)?.startsWith("evse-id:"));
|
|
11666
|
+
if (currentMeasurement["chargePoint"] != null && asJSONObject(currentMeasurement["chargePoint"])?.["softwareVersion"] !== common.chargePoint_softwareVersion)
|
|
11667
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageText("Inconsistent_ChargingStation_FirmwareVersion")));
|
|
11668
|
+
const signedEVSEId = additionalValues.filter((element) => element.measurandName?.startsWith("Meta") === true && asString(element.value)?.startsWith("evse-id:") === true);
|
|
11630
11669
|
if (signedEVSEId.length == 1) {
|
|
11631
11670
|
const evse__id = (asString(signedEVSEId[0]?.value) ?? "").replace("evse-id:", "").trim();
|
|
11632
11671
|
if (evse__id !== "unknown" && ExpectedEVSEId !== evse__id)
|
|
11633
|
-
currentErrors.push(this.chargy.
|
|
11672
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageText("Inconsistent_EVSE_Identification")));
|
|
11634
11673
|
}
|
|
11635
|
-
const signedCSCSWVersion = additionalValues.filter((element) => element.measurandName?.startsWith("Meta") && asString(element.value)?.startsWith("csc-sw-version:"));
|
|
11674
|
+
const signedCSCSWVersion = additionalValues.filter((element) => element.measurandName?.startsWith("Meta") === true && asString(element.value)?.startsWith("csc-sw-version:") === true);
|
|
11636
11675
|
if (signedCSCSWVersion.length == 1) {
|
|
11637
11676
|
const csc_sw_version = asString(signedCSCSWVersion[0]?.value)?.replace("csc-sw-version:", "").trim() ?? null;
|
|
11638
11677
|
if (previousCscSwVersion !== null && previousCscSwVersion !== csc_sw_version)
|
|
11639
|
-
currentErrors.push(this.chargy.
|
|
11678
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageText("Inconsistent_ChargingStation_FirmwareVersion")));
|
|
11640
11679
|
if (ExpectedCscSwVersion !== null && ExpectedCscSwVersion !== csc_sw_version)
|
|
11641
11680
|
currentWarnings.push({
|
|
11642
11681
|
level: "medium" /* medium */,
|
|
11643
|
-
message: this.chargy.
|
|
11682
|
+
message: this.chargy.GetMultilanguageText("Inconsistent_ChargingStation_FirmwareVersion")
|
|
11644
11683
|
});
|
|
11645
11684
|
previousCscSwVersion = csc_sw_version;
|
|
11646
11685
|
}
|
|
@@ -11697,36 +11736,38 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
11697
11736
|
case "Evt":
|
|
11698
11737
|
Evt = asNumber(additionalValue.value) ?? NaN;
|
|
11699
11738
|
break;
|
|
11739
|
+
default:
|
|
11740
|
+
break;
|
|
11700
11741
|
}
|
|
11701
11742
|
}
|
|
11702
11743
|
const currentRCRValue = asNumber(RCR?.value) ?? NaN;
|
|
11703
11744
|
if (previousRCR !== -1 && currentRCRValue < previousRCR)
|
|
11704
|
-
currentErrors.push(this.chargy.
|
|
11745
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_Measurement_ValueP", measurementCounter)));
|
|
11705
11746
|
previousRCR = currentRCRValue;
|
|
11706
11747
|
if (RCnt !== currentMeasurement["measurementId"])
|
|
11707
|
-
currentErrors.push(this.chargy.
|
|
11748
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_MeasurementIdP", measurementCounter)));
|
|
11708
11749
|
if (previousRCnt !== -1 && RCnt != previousRCnt + 1)
|
|
11709
|
-
currentErrors.push(this.chargy.
|
|
11750
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_CounterP", measurementCounter)));
|
|
11710
11751
|
previousRCnt = RCnt;
|
|
11711
11752
|
if (previousOS !== -1 && OS <= previousOS)
|
|
11712
|
-
currentErrors.push(this.chargy.
|
|
11753
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_OperationSecondsCounterP", measurementCounter)));
|
|
11713
11754
|
previousOS = OS;
|
|
11714
11755
|
if (previousEpoch !== -1 && Epoch <= previousEpoch)
|
|
11715
|
-
currentErrors.push(this.chargy.
|
|
11756
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_UNIXEpochP", measurementCounter)));
|
|
11716
11757
|
previousEpoch = Epoch;
|
|
11717
11758
|
const measurementTimestamp1 = new Date(Epoch * 1e3 + TZO * 6e4).toISOString();
|
|
11718
11759
|
const measurementTimestamp2 = measurementTimestamp1.substring(0, measurementTimestamp1.indexOf("."));
|
|
11719
11760
|
const measurementTimestamp3 = measurementTimestamp2 + (TZO > 0 ? "+" : "-") + (Math.abs(TZO) / 60).toString().padStart(2, "0") + ":" + (Math.abs(TZO) % 60).toString().padStart(2, "0");
|
|
11720
11761
|
if (currentTime !== measurementTimestamp3)
|
|
11721
|
-
currentErrors.push(this.chargy.
|
|
11762
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_TimestampP", measurementCounter)));
|
|
11722
11763
|
if (common.MA1 !== null && MA1 !== common.MA1)
|
|
11723
|
-
currentErrors.push(this.chargy.
|
|
11764
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_MeterInfo_MeterIdP", measurementCounter)));
|
|
11724
11765
|
common.MA1 = MA1;
|
|
11725
11766
|
if (common.epochSetCnt !== -1 && EpochSetCnt !== common.epochSetCnt)
|
|
11726
|
-
currentErrors.push(this.chargy.
|
|
11767
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_EpochSet_CounterP", measurementCounter)));
|
|
11727
11768
|
common.epochSetCnt = EpochSetCnt;
|
|
11728
11769
|
if (common.epochSetOS !== -1 && EpochSetOS !== common.epochSetOS)
|
|
11729
|
-
currentErrors.push(this.chargy.
|
|
11770
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_EpochSet_OperationSecondsP", measurementCounter)));
|
|
11730
11771
|
common.epochSetOS = EpochSetOS;
|
|
11731
11772
|
common.dataSets.push({
|
|
11732
11773
|
Typ,
|
|
@@ -11759,18 +11800,17 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
11759
11800
|
});
|
|
11760
11801
|
}
|
|
11761
11802
|
const n = common.dataSets.length - 1;
|
|
11762
|
-
const firstDataSet = common.dataSets
|
|
11763
|
-
const lastDataSet = common.dataSets
|
|
11764
|
-
if (firstDataSet
|
|
11803
|
+
const firstDataSet = getFirstArrayElement(common.dataSets, "Missing first BSM data set");
|
|
11804
|
+
const lastDataSet = getArrayElement(common.dataSets, n, "Missing last BSM data set");
|
|
11805
|
+
if (firstDataSet.TypParsed !== "START" && firstDataSet.TypParsed !== "TURN ON")
|
|
11765
11806
|
throw new Error(this.chargy.GetLocalizedMessageWithParameter("Inconsistent_EnergyMeterValueP", 1));
|
|
11766
11807
|
for (let i = 1; i < common.dataSets.length - 1; i++) {
|
|
11767
11808
|
if (common.dataSets[i]?.TypParsed !== "CURRENT")
|
|
11768
|
-
errors.push(this.chargy.
|
|
11809
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_EnergyMeterValueP", measurementCounter + 1)));
|
|
11769
11810
|
}
|
|
11770
|
-
if (lastDataSet
|
|
11811
|
+
if (lastDataSet.TypParsed !== "END" && lastDataSet.TypParsed !== "TURN OFF")
|
|
11771
11812
|
throw new Error(this.chargy.GetLocalizedMessageWithParameter("Inconsistent_EnergyMeterValueP", n + 1));
|
|
11772
|
-
|
|
11773
|
-
CTR.chargingSessions = [];
|
|
11813
|
+
CTR.chargingSessions ??= [];
|
|
11774
11814
|
const ASN1_SignatureSchema = this.chargy.asn1.define("Signature", function() {
|
|
11775
11815
|
this.seq().obj(
|
|
11776
11816
|
this.key("r").int(),
|
|
@@ -11835,7 +11875,11 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
11835
11875
|
try {
|
|
11836
11876
|
ASN1Signature = ASN1_SignatureSchema.decode(Buffer.from(dataSet.signature, "hex"), "der");
|
|
11837
11877
|
} catch (exception) {
|
|
11838
|
-
|
|
11878
|
+
const signatureError = this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_SignatureP", 1);
|
|
11879
|
+
const exceptionText = ": " + (exception instanceof Error ? exception.message : String(exception));
|
|
11880
|
+
for (const language of Object.keys(signatureError))
|
|
11881
|
+
signatureError[language] = (signatureError[language] ?? "") + exceptionText;
|
|
11882
|
+
errors.push(CreateError(signatureError));
|
|
11839
11883
|
}
|
|
11840
11884
|
const bsmMeasurementValue = {
|
|
11841
11885
|
timestamp: dataSet.time,
|
|
@@ -11883,12 +11927,12 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
11883
11927
|
CTR.chargingSessions.push(session);
|
|
11884
11928
|
CTR["@id"] = common.meterInfo_meterId + "-" + String(firstDataSet.Epoch);
|
|
11885
11929
|
{
|
|
11886
|
-
const firstChargingSession = CTR.chargingSessions
|
|
11887
|
-
const lastChargingSession = CTR.chargingSessions
|
|
11888
|
-
if (
|
|
11930
|
+
const firstChargingSession = getFirstArrayElement(CTR.chargingSessions, "Missing first BSM charging session");
|
|
11931
|
+
const lastChargingSession = getLastArrayElement(CTR.chargingSessions, "Missing last BSM charging session");
|
|
11932
|
+
if (CTR.begin == void 0 || CTR.begin === "" || CTR.begin > firstChargingSession.begin) {
|
|
11889
11933
|
CTR.begin = firstChargingSession.begin;
|
|
11890
11934
|
}
|
|
11891
|
-
if (lastChargingSession
|
|
11935
|
+
if (lastChargingSession.end !== void 0) {
|
|
11892
11936
|
if (CTR.end == void 0 || CTR.end === "" || CTR.end < lastChargingSession.end)
|
|
11893
11937
|
CTR.end = lastChargingSession.end;
|
|
11894
11938
|
}
|
|
@@ -11928,7 +11972,9 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
11928
11972
|
CTR.certainty = 1 - errors.length / numberOfFormatChecks;
|
|
11929
11973
|
return CTR;
|
|
11930
11974
|
} catch (exception) {
|
|
11931
|
-
errors.push(
|
|
11975
|
+
errors.push(
|
|
11976
|
+
CreateError({ "en": "Exception occured: " + (exception instanceof Error ? exception.message : String(exception)) })
|
|
11977
|
+
);
|
|
11932
11978
|
}
|
|
11933
11979
|
return {
|
|
11934
11980
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
@@ -12058,58 +12104,63 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
12058
12104
|
}
|
|
12059
12105
|
return {};
|
|
12060
12106
|
}
|
|
12061
|
-
async ViewMeasurement(measurementValue,
|
|
12107
|
+
async ViewMeasurement(measurementValue, _errorDiv, introDiv, infoDiv, PlainTextDiv, HashedPlainTextDiv, PublicKeyDiv, SignatureExpectedDiv, SignatureCheckDiv) {
|
|
12062
12108
|
if (measurementValue.measurement === void 0)
|
|
12063
12109
|
return new Error("Invalid measurement!");
|
|
12064
12110
|
const result = measurementValue.result;
|
|
12065
12111
|
introDiv.innerHTML = this.chargy.GetLocalizedMessage("The following data of the charging session is relevant for metrological and legal metrological purposes and therefore part of the digital signature").replace("{methodName}", "BSMCrypt01").replace("{cryptoAlgorithm}", this.description);
|
|
12066
|
-
if (PlainTextDiv.parentElement
|
|
12067
|
-
PlainTextDiv.parentElement.children
|
|
12112
|
+
if (PlainTextDiv.parentElement) {
|
|
12113
|
+
getArrayLikeElement(PlainTextDiv.parentElement.children, 0, "Missing plain text header").innerHTML = "Plain text (" + measurementValue.result.ArraySize.toString() + " Bytes, hex)";
|
|
12068
12114
|
}
|
|
12069
12115
|
PlainTextDiv.style.fontFamily = "";
|
|
12070
12116
|
PlainTextDiv.style.whiteSpace = "";
|
|
12071
12117
|
PlainTextDiv.style.maxHeight = "";
|
|
12072
12118
|
PlainTextDiv.style.overflowY = "";
|
|
12073
|
-
this.CreateLine("Snapshot-Typ", this.ParseTyp(measurementValue.Typ), result.Typ
|
|
12074
|
-
this.CreateLine("RCR", (measurementValue.RCR * 10 ** measurementValue.RCR_SF).toString() + " " + measurementValue.RCR_Unit, result.RCR
|
|
12075
|
-
this.CreateLine("TotWhImp", (measurementValue.TotWhImp * 10 ** measurementValue.TotWhImp_SF).toString() + " " + measurementValue.TotWhImp_Unit, result.TotWhImp
|
|
12076
|
-
this.CreateLine("W", (measurementValue.W * 10 ** measurementValue.W_SF).toString() + " " + measurementValue.W_Unit, result.W
|
|
12077
|
-
this.CreateLine("MA1", measurementValue.MA1, result.MA1
|
|
12078
|
-
this.CreateLine("RCnt", measurementValue.RCnt, result.RCnt
|
|
12079
|
-
this.CreateLine("OS", measurementValue.OS, result.OS
|
|
12080
|
-
this.CreateLine("Zeitstempel", UTC2human(measurementValue.Epoch), result.Epoch
|
|
12081
|
-
this.CreateLine("TZO", measurementValue.TZO.toString() + " Minuten", result.TZO
|
|
12082
|
-
this.CreateLine("EpochSetCnt", measurementValue.EpochSetCnt, result.EpochSetCnt
|
|
12083
|
-
this.CreateLine("EpochSetOS", measurementValue.EpochSetOS, result.EpochSetOS
|
|
12084
|
-
this.CreateLine("DI", measurementValue.DI, result.DI
|
|
12085
|
-
this.CreateLine("DO", measurementValue.DO, result.DO
|
|
12086
|
-
this.CreateLine("Meta1", measurementValue.Meta1, result.Meta1
|
|
12087
|
-
this.CreateLine("Meta2", measurementValue.Meta2, result.Meta2
|
|
12088
|
-
this.CreateLine("Meta3", measurementValue.Meta3, result.Meta3
|
|
12089
|
-
this.CreateLine("Evt", this.ParseEvents(measurementValue.Evt).join("<br>"), result.Evt
|
|
12090
|
-
if (HashedPlainTextDiv.parentElement
|
|
12091
|
-
HashedPlainTextDiv.parentElement.children
|
|
12119
|
+
this.CreateLine("Snapshot-Typ", this.ParseTyp(measurementValue.Typ), result.Typ, infoDiv, PlainTextDiv);
|
|
12120
|
+
this.CreateLine("RCR", (measurementValue.RCR * 10 ** measurementValue.RCR_SF).toString() + " " + measurementValue.RCR_Unit, result.RCR, infoDiv, PlainTextDiv);
|
|
12121
|
+
this.CreateLine("TotWhImp", (measurementValue.TotWhImp * 10 ** measurementValue.TotWhImp_SF).toString() + " " + measurementValue.TotWhImp_Unit, result.TotWhImp, infoDiv, PlainTextDiv);
|
|
12122
|
+
this.CreateLine("W", (measurementValue.W * 10 ** measurementValue.W_SF).toString() + " " + measurementValue.W_Unit, result.W, infoDiv, PlainTextDiv);
|
|
12123
|
+
this.CreateLine("MA1", measurementValue.MA1, result.MA1, infoDiv, PlainTextDiv);
|
|
12124
|
+
this.CreateLine("RCnt", measurementValue.RCnt, result.RCnt, infoDiv, PlainTextDiv);
|
|
12125
|
+
this.CreateLine("OS", measurementValue.OS, result.OS, infoDiv, PlainTextDiv);
|
|
12126
|
+
this.CreateLine("Zeitstempel", UTC2human(measurementValue.Epoch), result.Epoch, infoDiv, PlainTextDiv);
|
|
12127
|
+
this.CreateLine("TZO", measurementValue.TZO.toString() + " Minuten", result.TZO, infoDiv, PlainTextDiv);
|
|
12128
|
+
this.CreateLine("EpochSetCnt", measurementValue.EpochSetCnt, result.EpochSetCnt, infoDiv, PlainTextDiv);
|
|
12129
|
+
this.CreateLine("EpochSetOS", measurementValue.EpochSetOS, result.EpochSetOS, infoDiv, PlainTextDiv);
|
|
12130
|
+
this.CreateLine("DI", measurementValue.DI, result.DI, infoDiv, PlainTextDiv);
|
|
12131
|
+
this.CreateLine("DO", measurementValue.DO, result.DO, infoDiv, PlainTextDiv);
|
|
12132
|
+
this.CreateLine("Meta1", measurementValue.Meta1, result.Meta1, infoDiv, PlainTextDiv);
|
|
12133
|
+
this.CreateLine("Meta2", measurementValue.Meta2, result.Meta2, infoDiv, PlainTextDiv);
|
|
12134
|
+
this.CreateLine("Meta3", measurementValue.Meta3, result.Meta3, infoDiv, PlainTextDiv);
|
|
12135
|
+
this.CreateLine("Evt", this.ParseEvents(measurementValue.Evt).join("<br>"), result.Evt, infoDiv, PlainTextDiv);
|
|
12136
|
+
if (HashedPlainTextDiv.parentElement) {
|
|
12137
|
+
getArrayLikeElement(HashedPlainTextDiv.parentElement.children, 0, "Missing hashed plain text header").innerHTML = "Hashed plain text (SHA256, hex)";
|
|
12092
12138
|
}
|
|
12093
12139
|
HashedPlainTextDiv.innerHTML = result.sha256value?.match(/.{1,8}/g)?.join(" ") ?? "";
|
|
12094
12140
|
if (result.publicKey != null && result.publicKey != "") {
|
|
12095
|
-
if (PublicKeyDiv.parentElement
|
|
12096
|
-
PublicKeyDiv.parentElement.children
|
|
12141
|
+
if (PublicKeyDiv.parentElement) {
|
|
12142
|
+
getArrayLikeElement(PublicKeyDiv.parentElement.children, 0, "Missing public key header").innerHTML = "Public Key (" + (result.publicKeyFormat != null && result.publicKeyFormat.length > 0 ? result.publicKeyFormat + ", " : "") + "hex)";
|
|
12097
12143
|
}
|
|
12098
12144
|
if (!IsNullOrEmpty(result.publicKey))
|
|
12099
12145
|
PublicKeyDiv.innerHTML = result.publicKey.startsWith("04") ? '<span class="leadingFour">04</span> ' + (result.publicKey.substring(2).match(/.{1,8}/g)?.join(" ") ?? "-") : result.publicKey.match(/.{1,8}/g)?.join(" ") ?? "-";
|
|
12100
|
-
|
|
12101
|
-
|
|
12146
|
+
const publicKeySignatureContainer = PublicKeyDiv.parentElement?.children[3];
|
|
12147
|
+
if (publicKeySignatureContainer !== void 0) {
|
|
12148
|
+
publicKeySignatureContainer.innerHTML = "";
|
|
12102
12149
|
}
|
|
12103
12150
|
if (result.publicKeySignatures) {
|
|
12104
12151
|
for (const signature of result.publicKeySignatures) {
|
|
12105
12152
|
try {
|
|
12106
|
-
const signatureDiv =
|
|
12107
|
-
|
|
12153
|
+
const signatureDiv = publicKeySignatureContainer?.appendChild(document.createElement("div"));
|
|
12154
|
+
const chargingSession = measurementValue.measurement.chargingSession;
|
|
12155
|
+
const evse = chargingSession?.EVSE;
|
|
12156
|
+
const meter = evse?.meters.at(0);
|
|
12157
|
+
const publicKey = meter?.publicKeys?.at(0);
|
|
12158
|
+
if (signatureDiv != null && chargingSession != null && evse != null && meter != null && publicKey != null) {
|
|
12108
12159
|
signatureDiv.innerHTML = await this.chargy.CheckMeterPublicKeySignature(
|
|
12109
|
-
|
|
12110
|
-
|
|
12111
|
-
|
|
12112
|
-
|
|
12160
|
+
chargingSession.chargingStation,
|
|
12161
|
+
evse,
|
|
12162
|
+
meter,
|
|
12163
|
+
publicKey,
|
|
12113
12164
|
signature
|
|
12114
12165
|
);
|
|
12115
12166
|
}
|
|
@@ -12120,12 +12171,12 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
12120
12171
|
}
|
|
12121
12172
|
}
|
|
12122
12173
|
if (result.signature != null) {
|
|
12123
|
-
if (SignatureExpectedDiv.parentElement
|
|
12124
|
-
SignatureExpectedDiv.parentElement.children
|
|
12174
|
+
if (SignatureExpectedDiv.parentElement) {
|
|
12175
|
+
getArrayLikeElement(SignatureExpectedDiv.parentElement.children, 0, "Missing expected signature header").innerHTML = "Erwartete Signatur (" + (result.signature.format ?? "") + ", hex)";
|
|
12125
12176
|
}
|
|
12126
|
-
if (result.signature.r && result.signature.s)
|
|
12177
|
+
if (result.signature.r != null && result.signature.r.length > 0 && result.signature.s != null && result.signature.s.length > 0)
|
|
12127
12178
|
SignatureExpectedDiv.innerHTML = "r: " + (result.signature.r.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "-") + "<br />s: " + (result.signature.s.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "-");
|
|
12128
|
-
else if (result.signature.value)
|
|
12179
|
+
else if (result.signature.value != null && result.signature.value.length > 0)
|
|
12129
12180
|
SignatureExpectedDiv.innerHTML = result.signature.value.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "-";
|
|
12130
12181
|
}
|
|
12131
12182
|
switch (result.status) {
|
|
@@ -12151,6 +12202,7 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
12151
12202
|
SignatureCheckDiv.innerHTML = '<i class="fas fa-times-circle"></i><div id="description">Ung\xFCltige Signatur</div>';
|
|
12152
12203
|
break;
|
|
12153
12204
|
}
|
|
12205
|
+
return void 0;
|
|
12154
12206
|
}
|
|
12155
12207
|
//#region Helper methods
|
|
12156
12208
|
PrefixConverter(input) {
|
|
@@ -12229,30 +12281,35 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
12229
12281
|
if ((value & 1 << 29) != 0) events.push("OEM 15");
|
|
12230
12282
|
return events;
|
|
12231
12283
|
}
|
|
12232
|
-
DecodeStatus(statusValue)
|
|
12233
|
-
|
|
12234
|
-
|
|
12235
|
-
|
|
12236
|
-
|
|
12237
|
-
|
|
12238
|
-
|
|
12239
|
-
|
|
12240
|
-
|
|
12241
|
-
|
|
12242
|
-
|
|
12243
|
-
|
|
12244
|
-
|
|
12245
|
-
|
|
12246
|
-
|
|
12247
|
-
|
|
12248
|
-
|
|
12249
|
-
|
|
12250
|
-
|
|
12251
|
-
|
|
12252
|
-
|
|
12253
|
-
|
|
12254
|
-
|
|
12255
|
-
|
|
12284
|
+
// private DecodeStatus(statusValue: string) : Array<string>
|
|
12285
|
+
// {
|
|
12286
|
+
// const statusArray:string[] = [];
|
|
12287
|
+
// try
|
|
12288
|
+
// {
|
|
12289
|
+
// const status = parseInt(statusValue);
|
|
12290
|
+
// if ((status & 1) == 1)
|
|
12291
|
+
// statusArray.push("Fehler erkannt");
|
|
12292
|
+
// if ((status & 2) == 2)
|
|
12293
|
+
// statusArray.push("Synchrone Messwertübermittlung");
|
|
12294
|
+
// // Bit 3 is reserved!
|
|
12295
|
+
// if ((status & 8) == 8)
|
|
12296
|
+
// statusArray.push("System-Uhr ist synchron");
|
|
12297
|
+
// else
|
|
12298
|
+
// statusArray.push("System-Uhr ist nicht synchron");
|
|
12299
|
+
// if ((status & 16) == 16)
|
|
12300
|
+
// statusArray.push("Rücklaufsperre aktiv");
|
|
12301
|
+
// if ((status & 32) == 32)
|
|
12302
|
+
// statusArray.push("Energierichtung -A");
|
|
12303
|
+
// if ((status & 64) == 64)
|
|
12304
|
+
// statusArray.push("Magnetfeld erkannt");
|
|
12305
|
+
// }
|
|
12306
|
+
// catch
|
|
12307
|
+
// {
|
|
12308
|
+
// statusArray.push("Invalid status!");
|
|
12309
|
+
// }
|
|
12310
|
+
// return statusArray;
|
|
12311
|
+
// }
|
|
12312
|
+
// //#endregion
|
|
12256
12313
|
};
|
|
12257
12314
|
|
|
12258
12315
|
// src/CanonicalJSON.ts
|
|
@@ -12652,7 +12709,7 @@ var EMHCrypt01 = class extends ACrypt {
|
|
|
12652
12709
|
measurementValue.result = cryptoResult;
|
|
12653
12710
|
return cryptoResult;
|
|
12654
12711
|
}
|
|
12655
|
-
if (measurementValue.measurement
|
|
12712
|
+
if (measurementValue.measurement?.chargingSession === void 0) {
|
|
12656
12713
|
return {
|
|
12657
12714
|
status: "InvalidMeasurement" /* InvalidMeasurement */
|
|
12658
12715
|
};
|
|
@@ -12691,9 +12748,10 @@ var EMHCrypt01 = class extends ACrypt {
|
|
|
12691
12748
|
cryptoResult.meter = meter;
|
|
12692
12749
|
if (meter.publicKeys != null && meter.publicKeys.length > 0) {
|
|
12693
12750
|
try {
|
|
12694
|
-
|
|
12695
|
-
cryptoResult.
|
|
12696
|
-
cryptoResult.
|
|
12751
|
+
const publicKey = meter.publicKeys.at(0);
|
|
12752
|
+
cryptoResult.publicKey = publicKey?.value?.toLowerCase();
|
|
12753
|
+
cryptoResult.publicKeyFormat = publicKey?.format;
|
|
12754
|
+
cryptoResult.publicKeySignatures = publicKey?.signatures;
|
|
12697
12755
|
try {
|
|
12698
12756
|
if (this.curve.keyFromPublic(cryptoResult.publicKey ?? "", "hex").verify(
|
|
12699
12757
|
cryptoResult.sha256value,
|
|
@@ -12718,59 +12776,60 @@ var EMHCrypt01 = class extends ACrypt {
|
|
|
12718
12776
|
}
|
|
12719
12777
|
return {};
|
|
12720
12778
|
}
|
|
12721
|
-
async ViewMeasurement(measurementValue,
|
|
12722
|
-
if (measurementValue.measurement
|
|
12779
|
+
async ViewMeasurement(measurementValue, _errorDiv, introDiv, infoDiv, PlainTextDiv, HashedPlainTextDiv, PublicKeyDiv, SignatureExpectedDiv, SignatureCheckDiv) {
|
|
12780
|
+
if (measurementValue.measurement?.chargingSession?.authorizationStart.timestamp === void 0) {
|
|
12723
12781
|
return new Error("Invalid measurement!");
|
|
12724
12782
|
}
|
|
12725
12783
|
const result = measurementValue.result;
|
|
12726
12784
|
introDiv.innerHTML = this.chargy.GetLocalizedMessage("The following data of the charging session is relevant for metrological and legal metrological purposes and therefore part of the digital signature").replace("{methodName}", "EMHCrypt01").replace("{cryptoAlgorithm}", this.description);
|
|
12727
12785
|
{
|
|
12728
|
-
if (PlainTextDiv.parentElement
|
|
12729
|
-
PlainTextDiv.parentElement.children
|
|
12786
|
+
if (PlainTextDiv.parentElement) {
|
|
12787
|
+
getArrayLikeElement(PlainTextDiv.parentElement.children, 0, "Missing plain text header").innerHTML = "Plain text (320 Bytes, hex)";
|
|
12730
12788
|
}
|
|
12731
12789
|
PlainTextDiv.style.fontFamily = "";
|
|
12732
12790
|
PlainTextDiv.style.whiteSpace = "";
|
|
12733
12791
|
PlainTextDiv.style.maxHeight = "";
|
|
12734
12792
|
PlainTextDiv.style.overflowY = "";
|
|
12735
|
-
this.CreateLine("Z\xE4hlernummer", measurementValue.measurement.energyMeterId, result.meterId
|
|
12736
|
-
this.CreateLine("Zeitstempel", UTC2human(measurementValue.timestamp), result.timestamp
|
|
12737
|
-
this.CreateLine("Status", hex2bin(measurementValue.infoStatus) + " (" + measurementValue.infoStatus + ' hex)<br /><span class="statusInfos">' + this.DecodeStatus(measurementValue.infoStatus).join("<br />") + "</span>", result.infoStatus
|
|
12738
|
-
this.CreateLine("Sekundenindex", measurementValue.secondsIndex, result.secondsIndex
|
|
12739
|
-
this.CreateLine("Paginierungsz\xE4hler", parseInt(measurementValue.paginationId, 16), result.paginationId
|
|
12740
|
-
this.CreateLine("OBIS-Kennzahl", measurementValue.measurement.obis, result.obis
|
|
12741
|
-
this.CreateLine("Einheit (codiert)", measurementValue.measurement.unitEncoded ?? 0, result.unitEncoded
|
|
12742
|
-
this.CreateLine("Skalierung", measurementValue.measurement.scale, result.scale
|
|
12743
|
-
this.CreateLine("Messwert", measurementValue.value.toString() + " Wh", result.value
|
|
12744
|
-
this.CreateLine("Logbuchindex", measurementValue.logBookIndex + " hex", result.logBookIndex
|
|
12745
|
-
this.CreateLine("Autorisierung", measurementValue.measurement.chargingSession.authorizationStart["@id"] + " hex", pad(result.authorizationStart, 128)
|
|
12746
|
-
this.CreateLine("Autorisierungszeitpunkt", UTC2human(measurementValue.measurement.chargingSession.authorizationStart.timestamp), pad(result.authorizationStartTimestamp, 151)
|
|
12793
|
+
this.CreateLine("Z\xE4hlernummer", measurementValue.measurement.energyMeterId, result.meterId ?? "", infoDiv, PlainTextDiv);
|
|
12794
|
+
this.CreateLine("Zeitstempel", UTC2human(measurementValue.timestamp), result.timestamp ?? "", infoDiv, PlainTextDiv);
|
|
12795
|
+
this.CreateLine("Status", hex2bin(measurementValue.infoStatus) + " (" + measurementValue.infoStatus + ' hex)<br /><span class="statusInfos">' + this.DecodeStatus(measurementValue.infoStatus).join("<br />") + "</span>", result.infoStatus ?? "", infoDiv, PlainTextDiv);
|
|
12796
|
+
this.CreateLine("Sekundenindex", measurementValue.secondsIndex, result.secondsIndex ?? "", infoDiv, PlainTextDiv);
|
|
12797
|
+
this.CreateLine("Paginierungsz\xE4hler", parseInt(measurementValue.paginationId, 16), result.paginationId ?? "", infoDiv, PlainTextDiv);
|
|
12798
|
+
this.CreateLine("OBIS-Kennzahl", measurementValue.measurement.obis, result.obis ?? "", infoDiv, PlainTextDiv);
|
|
12799
|
+
this.CreateLine("Einheit (codiert)", measurementValue.measurement.unitEncoded ?? 0, result.unitEncoded ?? "", infoDiv, PlainTextDiv);
|
|
12800
|
+
this.CreateLine("Skalierung", measurementValue.measurement.scale, result.scale ?? "", infoDiv, PlainTextDiv);
|
|
12801
|
+
this.CreateLine("Messwert", measurementValue.value.toString() + " Wh", result.value ?? "", infoDiv, PlainTextDiv);
|
|
12802
|
+
this.CreateLine("Logbuchindex", measurementValue.logBookIndex + " hex", result.logBookIndex ?? "", infoDiv, PlainTextDiv);
|
|
12803
|
+
this.CreateLine("Autorisierung", measurementValue.measurement.chargingSession.authorizationStart["@id"] + " hex", pad(result.authorizationStart, 128), infoDiv, PlainTextDiv);
|
|
12804
|
+
this.CreateLine("Autorisierungszeitpunkt", UTC2human(measurementValue.measurement.chargingSession.authorizationStart.timestamp), pad(result.authorizationStartTimestamp, 151), infoDiv, PlainTextDiv);
|
|
12747
12805
|
}
|
|
12748
12806
|
{
|
|
12749
|
-
if (HashedPlainTextDiv.parentElement
|
|
12750
|
-
HashedPlainTextDiv.parentElement.children
|
|
12807
|
+
if (HashedPlainTextDiv.parentElement) {
|
|
12808
|
+
getArrayLikeElement(HashedPlainTextDiv.parentElement.children, 0, "Missing hashed plain text header").innerHTML = "Hashed plain text (SHA256, 24 bytes, hex)";
|
|
12751
12809
|
}
|
|
12752
12810
|
HashedPlainTextDiv.innerHTML = result.sha256value?.match(/.{1,8}/g)?.join(" ") ?? "";
|
|
12753
12811
|
}
|
|
12754
12812
|
if (result.publicKey != null && result.publicKey != "") {
|
|
12755
|
-
if (PublicKeyDiv.parentElement
|
|
12756
|
-
PublicKeyDiv.parentElement.children
|
|
12813
|
+
if (PublicKeyDiv.parentElement) {
|
|
12814
|
+
getArrayLikeElement(PublicKeyDiv.parentElement.children, 0, "Missing public key header").innerHTML = "Public Key (" + (result.publicKeyFormat != null && result.publicKeyFormat.length > 0 ? result.publicKeyFormat + ", " : "") + "hex)";
|
|
12757
12815
|
}
|
|
12758
12816
|
if (!IsNullOrEmpty(result.publicKey))
|
|
12759
12817
|
PublicKeyDiv.innerHTML = result.publicKey.startsWith("04") ? '<span class="leadingFour">04</span> ' + (result.publicKey.substring(2).match(/.{1,8}/g)?.join(" ") ?? "") : result.publicKey.match(/.{1,8}/g)?.join(" ") ?? "";
|
|
12760
|
-
|
|
12761
|
-
|
|
12818
|
+
const publicKeySignatureContainer = PublicKeyDiv.parentElement?.children[3];
|
|
12819
|
+
if (publicKeySignatureContainer !== void 0) {
|
|
12820
|
+
publicKeySignatureContainer.innerHTML = "";
|
|
12762
12821
|
}
|
|
12763
12822
|
if (result.publicKeySignatures) {
|
|
12764
12823
|
for (const signature of result.publicKeySignatures) {
|
|
12765
12824
|
try {
|
|
12766
|
-
const signatureDiv =
|
|
12825
|
+
const signatureDiv = publicKeySignatureContainer?.appendChild(document.createElement("div"));
|
|
12767
12826
|
if (signatureDiv) {
|
|
12768
12827
|
signatureDiv.classList.add("signature");
|
|
12769
12828
|
signatureDiv.innerHTML = await this.chargy.CheckMeterPublicKeySignature(
|
|
12770
12829
|
measurementValue.measurement.chargingSession.chargingStation,
|
|
12771
12830
|
measurementValue.measurement.chargingSession.EVSE,
|
|
12772
|
-
measurementValue.measurement.chargingSession.EVSE?.meters
|
|
12773
|
-
measurementValue.measurement.chargingSession.EVSE?.meters
|
|
12831
|
+
measurementValue.measurement.chargingSession.EVSE?.meters.at(0),
|
|
12832
|
+
measurementValue.measurement.chargingSession.EVSE?.meters.at(0)?.publicKeys?.at(0),
|
|
12774
12833
|
signature
|
|
12775
12834
|
);
|
|
12776
12835
|
signatureDiv.onclick = () => {
|
|
@@ -12784,12 +12843,12 @@ var EMHCrypt01 = class extends ACrypt {
|
|
|
12784
12843
|
}
|
|
12785
12844
|
}
|
|
12786
12845
|
if (result.signature != null) {
|
|
12787
|
-
if (SignatureExpectedDiv.parentElement
|
|
12788
|
-
SignatureExpectedDiv.parentElement.children
|
|
12846
|
+
if (SignatureExpectedDiv.parentElement) {
|
|
12847
|
+
getArrayLikeElement(SignatureExpectedDiv.parentElement.children, 0, "Missing expected signature header").innerHTML = "Erwartete Signatur (" + (result.signature.format ?? "") + ", hex)";
|
|
12789
12848
|
}
|
|
12790
|
-
if (result.signature.r && result.signature.s)
|
|
12849
|
+
if (result.signature.r != null && result.signature.r.length > 0 && result.signature.s != null && result.signature.s.length > 0)
|
|
12791
12850
|
SignatureExpectedDiv.innerHTML = "r: " + (result.signature.r.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "") + "<br />s: " + (result.signature.s.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "");
|
|
12792
|
-
else if (result.signature.value)
|
|
12851
|
+
else if (result.signature.value != null && result.signature.value.length > 0)
|
|
12793
12852
|
SignatureExpectedDiv.innerHTML = result.signature.value.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "-";
|
|
12794
12853
|
}
|
|
12795
12854
|
{
|
|
@@ -12817,6 +12876,7 @@ var EMHCrypt01 = class extends ACrypt {
|
|
|
12817
12876
|
break;
|
|
12818
12877
|
}
|
|
12819
12878
|
}
|
|
12879
|
+
return void 0;
|
|
12820
12880
|
}
|
|
12821
12881
|
//#region Helper methods
|
|
12822
12882
|
DecodeStatus(statusValue) {
|
|
@@ -12885,7 +12945,7 @@ var GDFCrypt01 = class extends ACrypt {
|
|
|
12885
12945
|
measurementValue.result = cryptoResult;
|
|
12886
12946
|
return cryptoResult;
|
|
12887
12947
|
}
|
|
12888
|
-
if (measurementValue.measurement
|
|
12948
|
+
if (measurementValue.measurement?.chargingSession === void 0) {
|
|
12889
12949
|
return {
|
|
12890
12950
|
status: "InvalidMeasurement" /* InvalidMeasurement */
|
|
12891
12951
|
};
|
|
@@ -12920,9 +12980,10 @@ var GDFCrypt01 = class extends ACrypt {
|
|
|
12920
12980
|
cryptoResult.meter = meter;
|
|
12921
12981
|
if (meter.publicKeys != null && meter.publicKeys.length > 0) {
|
|
12922
12982
|
try {
|
|
12923
|
-
|
|
12924
|
-
cryptoResult.
|
|
12925
|
-
cryptoResult.
|
|
12983
|
+
const publicKey = meter.publicKeys.at(0);
|
|
12984
|
+
cryptoResult.publicKey = publicKey?.value?.toLowerCase();
|
|
12985
|
+
cryptoResult.publicKeyFormat = publicKey?.format;
|
|
12986
|
+
cryptoResult.publicKeySignatures = publicKey?.signatures;
|
|
12926
12987
|
try {
|
|
12927
12988
|
if (this.curve.keyFromPublic(cryptoResult.publicKey ?? "", "hex").verify(
|
|
12928
12989
|
cryptoResult.sha256value,
|
|
@@ -12947,54 +13008,55 @@ var GDFCrypt01 = class extends ACrypt {
|
|
|
12947
13008
|
}
|
|
12948
13009
|
return {};
|
|
12949
13010
|
}
|
|
12950
|
-
async ViewMeasurement(measurementValue,
|
|
12951
|
-
if (measurementValue.measurement
|
|
13011
|
+
async ViewMeasurement(measurementValue, _errorDiv, introDiv, infoDiv, PlainTextDiv, HashedPlainTextDiv, PublicKeyDiv, SignatureExpectedDiv, SignatureCheckDiv) {
|
|
13012
|
+
if (measurementValue.measurement?.chargingSession?.authorizationStart.timestamp === void 0) {
|
|
12952
13013
|
return new Error("Invalid measurement!");
|
|
12953
13014
|
}
|
|
12954
13015
|
const result = measurementValue.result;
|
|
12955
13016
|
introDiv.innerHTML = this.chargy.GetLocalizedMessage("The following data of the charging session is relevant for metrological and legal metrological purposes and therefore part of the digital signature").replace("{methodName}", "GDFCrypt01").replace("{cryptoAlgorithm}", this.description);
|
|
12956
13017
|
{
|
|
12957
|
-
if (PlainTextDiv.parentElement
|
|
12958
|
-
PlainTextDiv.parentElement.children
|
|
13018
|
+
if (PlainTextDiv.parentElement) {
|
|
13019
|
+
getArrayLikeElement(PlainTextDiv.parentElement.children, 0, "Missing plain text header").innerHTML = "Plain text (320 Bytes, hex)";
|
|
12959
13020
|
}
|
|
12960
13021
|
PlainTextDiv.style.fontFamily = "";
|
|
12961
13022
|
PlainTextDiv.style.whiteSpace = "";
|
|
12962
13023
|
PlainTextDiv.style.maxHeight = "";
|
|
12963
13024
|
PlainTextDiv.style.overflowY = "";
|
|
12964
|
-
this.CreateLine("Z\xE4hlernummer", measurementValue.measurement.energyMeterId, result.meterId
|
|
12965
|
-
this.CreateLine("Zeitstempel", UTC2human(measurementValue.timestamp), result.timestamp
|
|
12966
|
-
this.CreateLine("OBIS-Kennzahl", measurementValue.measurement.obis, result.obis
|
|
12967
|
-
this.CreateLine("Einheit (codiert)", measurementValue.measurement.unitEncoded ?? 0, result.unitEncoded
|
|
12968
|
-
this.CreateLine("Skalierung", measurementValue.measurement.scale, result.scale
|
|
12969
|
-
this.CreateLine("Messwert", measurementValue.value.toString() + " Wh", result.value
|
|
12970
|
-
this.CreateLine("Autorisierung", measurementValue.measurement.chargingSession.authorizationStart["@id"] + " hex", pad(result.authorizationStart, 128)
|
|
12971
|
-
this.CreateLine("Autorisierungszeitpunkt", UTC2human(measurementValue.measurement.chargingSession.authorizationStart.timestamp), pad(result.authorizationStartTimestamp, 151)
|
|
13025
|
+
this.CreateLine("Z\xE4hlernummer", measurementValue.measurement.energyMeterId, result.meterId ?? "", infoDiv, PlainTextDiv);
|
|
13026
|
+
this.CreateLine("Zeitstempel", UTC2human(measurementValue.timestamp), result.timestamp ?? "", infoDiv, PlainTextDiv);
|
|
13027
|
+
this.CreateLine("OBIS-Kennzahl", measurementValue.measurement.obis, result.obis ?? "", infoDiv, PlainTextDiv);
|
|
13028
|
+
this.CreateLine("Einheit (codiert)", measurementValue.measurement.unitEncoded ?? 0, result.unitEncoded ?? "", infoDiv, PlainTextDiv);
|
|
13029
|
+
this.CreateLine("Skalierung", measurementValue.measurement.scale, result.scale ?? "", infoDiv, PlainTextDiv);
|
|
13030
|
+
this.CreateLine("Messwert", measurementValue.value.toString() + " Wh", result.value ?? "", infoDiv, PlainTextDiv);
|
|
13031
|
+
this.CreateLine("Autorisierung", measurementValue.measurement.chargingSession.authorizationStart["@id"] + " hex", pad(result.authorizationStart, 128), infoDiv, PlainTextDiv);
|
|
13032
|
+
this.CreateLine("Autorisierungszeitpunkt", UTC2human(measurementValue.measurement.chargingSession.authorizationStart.timestamp), pad(result.authorizationStartTimestamp, 151), infoDiv, PlainTextDiv);
|
|
12972
13033
|
}
|
|
12973
13034
|
{
|
|
12974
|
-
if (HashedPlainTextDiv.parentElement
|
|
12975
|
-
HashedPlainTextDiv.parentElement.children
|
|
13035
|
+
if (HashedPlainTextDiv.parentElement) {
|
|
13036
|
+
getArrayLikeElement(HashedPlainTextDiv.parentElement.children, 0, "Missing hashed plain text header").innerHTML = "Hashed plain text (SHA256, 24 bytes, hex)";
|
|
12976
13037
|
}
|
|
12977
13038
|
HashedPlainTextDiv.innerHTML = result.sha256value?.match(/.{1,8}/g)?.join(" ") ?? "";
|
|
12978
13039
|
}
|
|
12979
13040
|
if (result.publicKey != null && result.publicKey != "") {
|
|
12980
|
-
if (PublicKeyDiv.parentElement
|
|
12981
|
-
PublicKeyDiv.parentElement.children
|
|
13041
|
+
if (PublicKeyDiv.parentElement) {
|
|
13042
|
+
getArrayLikeElement(PublicKeyDiv.parentElement.children, 0, "Missing public key header").innerHTML = "Public Key (" + (result.publicKeyFormat != null && result.publicKeyFormat.length > 0 ? result.publicKeyFormat + ", " : "") + "hex)";
|
|
12982
13043
|
}
|
|
12983
13044
|
if (!IsNullOrEmpty(result.publicKey))
|
|
12984
13045
|
PublicKeyDiv.innerHTML = result.publicKey.startsWith("04") ? '<span class="leadingFour">04</span> ' + (result.publicKey.substring(2).match(/.{1,8}/g)?.join(" ") ?? "") : result.publicKey.match(/.{1,8}/g)?.join(" ") ?? "";
|
|
12985
|
-
|
|
12986
|
-
|
|
13046
|
+
const publicKeySignatureContainer = PublicKeyDiv.parentElement?.children[3];
|
|
13047
|
+
if (publicKeySignatureContainer !== void 0) {
|
|
13048
|
+
publicKeySignatureContainer.innerHTML = "";
|
|
12987
13049
|
}
|
|
12988
13050
|
if (result.publicKeySignatures) {
|
|
12989
13051
|
for (const signature of result.publicKeySignatures) {
|
|
12990
13052
|
try {
|
|
12991
|
-
const signatureDiv =
|
|
13053
|
+
const signatureDiv = publicKeySignatureContainer?.appendChild(document.createElement("div"));
|
|
12992
13054
|
if (signatureDiv != null)
|
|
12993
13055
|
signatureDiv.innerHTML = await this.chargy.CheckMeterPublicKeySignature(
|
|
12994
13056
|
measurementValue.measurement.chargingSession.chargingStation,
|
|
12995
13057
|
measurementValue.measurement.chargingSession.EVSE,
|
|
12996
|
-
measurementValue.measurement.chargingSession.EVSE?.meters
|
|
12997
|
-
measurementValue.measurement.chargingSession.EVSE?.meters
|
|
13058
|
+
measurementValue.measurement.chargingSession.EVSE?.meters.at(0),
|
|
13059
|
+
measurementValue.measurement.chargingSession.EVSE?.meters.at(0)?.publicKeys?.at(0),
|
|
12998
13060
|
signature
|
|
12999
13061
|
);
|
|
13000
13062
|
} catch (exception) {
|
|
@@ -13004,12 +13066,12 @@ var GDFCrypt01 = class extends ACrypt {
|
|
|
13004
13066
|
}
|
|
13005
13067
|
}
|
|
13006
13068
|
if (result.signature != null) {
|
|
13007
|
-
if (SignatureExpectedDiv.parentElement
|
|
13008
|
-
SignatureExpectedDiv.parentElement.children
|
|
13069
|
+
if (SignatureExpectedDiv.parentElement) {
|
|
13070
|
+
getArrayLikeElement(SignatureExpectedDiv.parentElement.children, 0, "Missing expected signature header").innerHTML = "Erwartete Signatur (" + (result.signature.format ?? "") + ", hex)";
|
|
13009
13071
|
}
|
|
13010
|
-
if (result.signature.r && result.signature.s)
|
|
13072
|
+
if (result.signature.r != null && result.signature.r.length > 0 && result.signature.s != null && result.signature.s.length > 0)
|
|
13011
13073
|
SignatureExpectedDiv.innerHTML = "r: " + (result.signature.r.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "") + "<br />s: " + (result.signature.s.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "");
|
|
13012
|
-
else if (result.signature.value)
|
|
13074
|
+
else if (result.signature.value != null && result.signature.value.length > 0)
|
|
13013
13075
|
SignatureExpectedDiv.innerHTML = result.signature.value.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "-";
|
|
13014
13076
|
}
|
|
13015
13077
|
{
|
|
@@ -13037,6 +13099,7 @@ var GDFCrypt01 = class extends ACrypt {
|
|
|
13037
13099
|
break;
|
|
13038
13100
|
}
|
|
13039
13101
|
}
|
|
13102
|
+
return void 0;
|
|
13040
13103
|
}
|
|
13041
13104
|
};
|
|
13042
13105
|
var MENNEKES_EDL40_XMLNS = "http://www.mennekes.de/Mennekes.EdlVerification.xsd";
|
|
@@ -13053,14 +13116,14 @@ var Mennekes = class {
|
|
|
13053
13116
|
if (chargingProcesses.length === 0)
|
|
13054
13117
|
return {
|
|
13055
13118
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
13056
|
-
message: this.chargy.
|
|
13119
|
+
message: this.chargy.GetMultilanguageText("UnknownOrInvalidChargingSessionFormat"),
|
|
13057
13120
|
certainty: 0
|
|
13058
13121
|
};
|
|
13059
13122
|
return await Promise.resolve(this.toChargeTransparencyRecord(chargingProcesses));
|
|
13060
13123
|
} catch (exception) {
|
|
13061
13124
|
return {
|
|
13062
13125
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
13063
|
-
message: "Exception occured: " + (exception instanceof Error ? exception.message : String(exception)),
|
|
13126
|
+
message: this.chargy.GetMultilanguageText("Exception occured: " + (exception instanceof Error ? exception.message : String(exception))),
|
|
13064
13127
|
certainty: 0
|
|
13065
13128
|
};
|
|
13066
13129
|
}
|
|
@@ -13197,7 +13260,10 @@ var MennekesCrypt01 = class extends ACrypt {
|
|
|
13197
13260
|
sessionResult = "InvalidSignature" /* InvalidSignature */;
|
|
13198
13261
|
}
|
|
13199
13262
|
if (sessionResult === "ValidSignature" /* ValidSignature */) {
|
|
13200
|
-
const lawErrors = validateMennekesLawConformity(
|
|
13263
|
+
const lawErrors = validateMennekesLawConformity(
|
|
13264
|
+
measurement.values,
|
|
13265
|
+
this.chargy
|
|
13266
|
+
);
|
|
13201
13267
|
if (lawErrors.length > 0) {
|
|
13202
13268
|
measurement.verificationResult = {
|
|
13203
13269
|
status: "InvalidMeasurement" /* InvalidMeasurement */,
|
|
@@ -13280,7 +13346,7 @@ var MennekesCrypt01 = class extends ACrypt {
|
|
|
13280
13346
|
signedData.byteOffset + signedData.byteLength
|
|
13281
13347
|
);
|
|
13282
13348
|
cryptoResult.hashValue = (await sha256(new DataView(signedDataBuffer))).substring(0, 48);
|
|
13283
|
-
const publicKey = cleanHex(meter.publicKeys
|
|
13349
|
+
const publicKey = cleanHex(meter.publicKeys.at(0)?.value ?? measurement.publicKey);
|
|
13284
13350
|
if (publicKey.length !== 96)
|
|
13285
13351
|
return setResult("InvalidPublicKey" /* InvalidPublicKey */);
|
|
13286
13352
|
const result = this.curve192r1.keyFromPublic("04" + publicKey, "hex").verify(
|
|
@@ -13311,7 +13377,7 @@ var MennekesCrypt01 = class extends ACrypt {
|
|
|
13311
13377
|
PublicKeyDiv.innerHTML = result.publicKey?.match(/.{1,8}/g)?.join(" ") ?? "";
|
|
13312
13378
|
if (SignatureExpectedDiv.parentElement?.children[0])
|
|
13313
13379
|
SignatureExpectedDiv.parentElement.children[0].innerHTML = this.chargy.GetLocalizedMessage("Expected signature") + " (rs, hex)";
|
|
13314
|
-
SignatureExpectedDiv.innerHTML = result.signature?.r && result.signature.s ? "r: " + (result.signature.r.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "") + "<br />s: " + (result.signature.s.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "") : "";
|
|
13380
|
+
SignatureExpectedDiv.innerHTML = result.signature?.r != null && result.signature.r.length > 0 && result.signature.s != null && result.signature.s.length > 0 ? "r: " + (result.signature.r.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "") + "<br />s: " + (result.signature.s.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "") : "";
|
|
13315
13381
|
SignatureCheckDiv.innerHTML = result.status === "ValidSignature" /* ValidSignature */ ? '<i class="fas fa-check-circle"></i><div id="description">' + this.chargy.GetLocalizedMessage("Valid signature") + "</div>" : '<i class="fas fa-times-circle"></i><div id="description">' + this.chargy.GetLocalizedMessage("Invalid signature") + "</div>";
|
|
13316
13382
|
return Promise.resolve(void 0);
|
|
13317
13383
|
}
|
|
@@ -13330,10 +13396,7 @@ function parseMennekesXMLDocument(XMLDocument) {
|
|
|
13330
13396
|
throw new Error("No Mennekes ChargingProcess element found!");
|
|
13331
13397
|
if (isLocalName(XMLDocument.documentElement, "ChargingProcess")) {
|
|
13332
13398
|
if (chargingProcesses.length > 1) {
|
|
13333
|
-
|
|
13334
|
-
if (chargingProcess != void 0)
|
|
13335
|
-
return chargingProcess;
|
|
13336
|
-
throw new Error("No Mennekes ChargingProcess found!");
|
|
13399
|
+
return getFirstArrayElement(chargingProcesses, "No Mennekes ChargingProcess found!");
|
|
13337
13400
|
}
|
|
13338
13401
|
}
|
|
13339
13402
|
return {
|
|
@@ -13454,18 +13517,20 @@ function toMennekesMeasurementValue(measurement) {
|
|
|
13454
13517
|
"measurement": void 0
|
|
13455
13518
|
};
|
|
13456
13519
|
}
|
|
13457
|
-
function validateMennekesLawConformity(measurementValues) {
|
|
13520
|
+
function validateMennekesLawConformity(measurementValues, chargy) {
|
|
13458
13521
|
const errors = new Array();
|
|
13459
|
-
const start = measurementValues
|
|
13460
|
-
const end = measurementValues
|
|
13522
|
+
const start = measurementValues.at(0);
|
|
13523
|
+
const end = measurementValues.at(-1);
|
|
13461
13524
|
if (start == null || end == null)
|
|
13462
|
-
return [
|
|
13525
|
+
return [
|
|
13526
|
+
CreateError(chargy.GetMultilanguageText("Mennekes EDL40 requires at least two measurement values."))
|
|
13527
|
+
];
|
|
13463
13528
|
if (start.eventCounter !== end.eventCounter)
|
|
13464
|
-
errors.push("Event counter mismatch.");
|
|
13529
|
+
errors.push(CreateError(chargy.GetMultilanguageText("Event counter mismatch.")));
|
|
13465
13530
|
if (Number(start.paginationId) >= Number(end.paginationId))
|
|
13466
|
-
errors.push("Pagination must increase from start to end.");
|
|
13531
|
+
errors.push(CreateError(chargy.GetMultilanguageText("Pagination must increase from start to end.")));
|
|
13467
13532
|
if (start.value.gt(end.value))
|
|
13468
|
-
errors.push("Meter value must not decrease.");
|
|
13533
|
+
errors.push(CreateError(chargy.GetMultilanguageText("Meter value must not decrease.")));
|
|
13469
13534
|
return errors;
|
|
13470
13535
|
}
|
|
13471
13536
|
function child(parent, localName) {
|
|
@@ -13585,9 +13650,9 @@ var OCMFv1_x = class extends ACrypt {
|
|
|
13585
13650
|
}
|
|
13586
13651
|
async VerifyMeasurement(measurementValue) {
|
|
13587
13652
|
measurementValue.method = this;
|
|
13588
|
-
return {
|
|
13653
|
+
return Promise.resolve({
|
|
13589
13654
|
status: measurementValue.result?.status ?? "Unvalidated" /* Unvalidated */
|
|
13590
|
-
};
|
|
13655
|
+
});
|
|
13591
13656
|
}
|
|
13592
13657
|
PayloadDictionary(Path, Key) {
|
|
13593
13658
|
if (Path === "RD") {
|
|
@@ -13657,7 +13722,7 @@ var OCMFv1_x = class extends ACrypt {
|
|
|
13657
13722
|
return Key;
|
|
13658
13723
|
}
|
|
13659
13724
|
}
|
|
13660
|
-
SignatureDictionary(
|
|
13725
|
+
SignatureDictionary(_Path, Key) {
|
|
13661
13726
|
switch (Key) {
|
|
13662
13727
|
case "SA":
|
|
13663
13728
|
return "Signature Algorithm";
|
|
@@ -13671,16 +13736,16 @@ var OCMFv1_x = class extends ACrypt {
|
|
|
13671
13736
|
return Key;
|
|
13672
13737
|
}
|
|
13673
13738
|
}
|
|
13674
|
-
async ViewMeasurement(measurementValue,
|
|
13739
|
+
async ViewMeasurement(measurementValue, _errorDiv, introDiv, _infoDiv, PlainTextDiv, HashedPlainTextDiv, PublicKeyDiv, SignatureExpectedDiv, SignatureCheckDiv) {
|
|
13675
13740
|
if (!measurementValue.measurement || !measurementValue.ocmfDocument || !measurementValue.measurement.chargingSession) {
|
|
13676
13741
|
return new Error("Invalid measurement!");
|
|
13677
13742
|
}
|
|
13678
13743
|
{
|
|
13679
|
-
introDiv.innerHTML = this.chargy.GetLocalizedMessage("The following data of the charging session is relevant for metrological and legal metrological purposes and therefore part of the digital signature").replace("{methodName}", "OCMFCrypt01").replace("{cryptoAlgorithm}", measurementValue.ocmfDocument.publicKey && typeof measurementValue.ocmfDocument.publicKey !== "string" ? "(" + measurementValue.ocmfDocument.publicKey.algorithm + ") " : "");
|
|
13744
|
+
introDiv.innerHTML = this.chargy.GetLocalizedMessage("The following data of the charging session is relevant for metrological and legal metrological purposes and therefore part of the digital signature").replace("{methodName}", "OCMFCrypt01").replace("{cryptoAlgorithm}", measurementValue.ocmfDocument.publicKey != null && typeof measurementValue.ocmfDocument.publicKey !== "string" ? "(" + measurementValue.ocmfDocument.publicKey.algorithm + ") " : "");
|
|
13680
13745
|
}
|
|
13681
13746
|
{
|
|
13682
|
-
if (PlainTextDiv.parentElement
|
|
13683
|
-
PlainTextDiv.parentElement.children
|
|
13747
|
+
if (PlainTextDiv.parentElement) {
|
|
13748
|
+
getArrayLikeElement(PlainTextDiv.parentElement.children, 0, "Missing plain text header").innerHTML = this.chargy.GetLocalizedMessage("Plain text") + " (OCMF|<" + this.chargy.GetLocalizedMessage("payload") + ">|<" + this.chargy.GetLocalizedMessage("signature") + ">)";
|
|
13684
13749
|
}
|
|
13685
13750
|
PlainTextDiv.innerText = "";
|
|
13686
13751
|
const compactValueDiv = document.createElement("div");
|
|
@@ -13712,29 +13777,30 @@ var OCMFv1_x = class extends ACrypt {
|
|
|
13712
13777
|
};
|
|
13713
13778
|
}
|
|
13714
13779
|
{
|
|
13715
|
-
if (HashedPlainTextDiv.parentElement
|
|
13716
|
-
HashedPlainTextDiv.parentElement.children
|
|
13780
|
+
if (HashedPlainTextDiv.parentElement) {
|
|
13781
|
+
getArrayLikeElement(HashedPlainTextDiv.parentElement.children, 0, "Missing hashed payload header").innerHTML = this.chargy.GetLocalizedMessage("Hashed payload") + " (" + measurementValue.ocmfDocument.hashAlgorithm + ")";
|
|
13717
13782
|
}
|
|
13718
13783
|
HashedPlainTextDiv.innerHTML = measurementValue.ocmfDocument.hashValue.match(/.{1,8}/g)?.join(" ") ?? "0x00000000000000000000000000000000000";
|
|
13719
13784
|
}
|
|
13720
|
-
if (measurementValue.ocmfDocument.publicKey) {
|
|
13721
|
-
if (PublicKeyDiv.parentElement
|
|
13722
|
-
PublicKeyDiv.parentElement.children
|
|
13785
|
+
if (measurementValue.ocmfDocument.publicKey != null) {
|
|
13786
|
+
if (PublicKeyDiv.parentElement) {
|
|
13787
|
+
getArrayLikeElement(PublicKeyDiv.parentElement.children, 0, "Missing public key header").innerHTML = typeof measurementValue.ocmfDocument.publicKey === "string" ? this.chargy.GetLocalizedMessage("Public Key") : this.chargy.GetLocalizedMessage("Public Key") + " (" + measurementValue.ocmfDocument.publicKey.algorithm + ", " + measurementValue.ocmfDocument.publicKey.encoding + ")";
|
|
13723
13788
|
}
|
|
13724
13789
|
PublicKeyDiv.innerHTML = typeof measurementValue.ocmfDocument.publicKey === "string" ? measurementValue.ocmfDocument.publicKey : "der: " + (measurementValue.ocmfDocument.publicKey.value?.match(/.{1,8}/g)?.join(" ") ?? "-") + "<br /><br />x: " + (measurementValue.ocmfDocument.publicKey.x.match(/.{1,8}/g)?.join(" ") ?? "-") + "<br />y: " + (measurementValue.ocmfDocument.publicKey.y.match(/.{1,8}/g)?.join(" ") ?? "-");
|
|
13725
13790
|
}
|
|
13726
|
-
|
|
13727
|
-
|
|
13791
|
+
const publicKeySignatureContainer = PublicKeyDiv.parentElement?.children[3];
|
|
13792
|
+
if (publicKeySignatureContainer !== void 0) {
|
|
13793
|
+
publicKeySignatureContainer.innerHTML = "";
|
|
13728
13794
|
const result = measurementValue.result;
|
|
13729
13795
|
if (result.publicKeySignatures) {
|
|
13730
13796
|
for (const signature of result.publicKeySignatures) {
|
|
13731
13797
|
try {
|
|
13732
|
-
const signatureDiv =
|
|
13798
|
+
const signatureDiv = publicKeySignatureContainer.appendChild(document.createElement("div"));
|
|
13733
13799
|
signatureDiv.innerHTML = await this.chargy.CheckMeterPublicKeySignature(
|
|
13734
13800
|
measurementValue.measurement.chargingSession.chargingStation,
|
|
13735
13801
|
measurementValue.measurement.chargingSession.EVSE,
|
|
13736
|
-
measurementValue.measurement.chargingSession.EVSE?.meters
|
|
13737
|
-
measurementValue.measurement.chargingSession.EVSE?.meters
|
|
13802
|
+
measurementValue.measurement.chargingSession.EVSE?.meters.at(0),
|
|
13803
|
+
measurementValue.measurement.chargingSession.EVSE?.meters.at(0)?.publicKeys?.at(0),
|
|
13738
13804
|
signature
|
|
13739
13805
|
);
|
|
13740
13806
|
} catch {
|
|
@@ -13744,8 +13810,8 @@ var OCMFv1_x = class extends ACrypt {
|
|
|
13744
13810
|
}
|
|
13745
13811
|
}
|
|
13746
13812
|
if (measurementValue.ocmfDocument.signature.SD) {
|
|
13747
|
-
if (SignatureExpectedDiv.parentElement
|
|
13748
|
-
SignatureExpectedDiv.parentElement.children
|
|
13813
|
+
if (SignatureExpectedDiv.parentElement) {
|
|
13814
|
+
getArrayLikeElement(SignatureExpectedDiv.parentElement.children, 0, "Missing expected signature header").innerHTML = this.chargy.GetLocalizedMessage("Expected signature") + " (rs, hex)";
|
|
13749
13815
|
}
|
|
13750
13816
|
SignatureExpectedDiv.innerHTML = "der: " + (measurementValue.ocmfDocument.signature.SD.match(/.{1,8}/g)?.join(" ") ?? "-") + "<br /><br />r: " + (measurementValue.ocmfDocument.signatureRS?.r?.toLowerCase().padStart(56, "0").match(/.{1,8}/g)?.join(" ") ?? "-") + "<br />s: " + (measurementValue.ocmfDocument.signatureRS?.s?.toLowerCase().padStart(56, "0").match(/.{1,8}/g)?.join(" ") ?? "-");
|
|
13751
13817
|
}
|
|
@@ -13768,6 +13834,7 @@ var OCMFv1_x = class extends ACrypt {
|
|
|
13768
13834
|
break;
|
|
13769
13835
|
}
|
|
13770
13836
|
}
|
|
13837
|
+
return void 0;
|
|
13771
13838
|
}
|
|
13772
13839
|
};
|
|
13773
13840
|
var OCMFTransactionTypes = /* @__PURE__ */ ((OCMFTransactionTypes2) => {
|
|
@@ -13800,274 +13867,276 @@ var OCMF = class {
|
|
|
13800
13867
|
const evseId = asString(containerInfos["EVSEId"]) ?? asString(evseInfo?.["@id"]) ?? "DE*GEF*EVSE*CHARGY*1";
|
|
13801
13868
|
const stationDescription = asJSONObject(chargingStationInfo?.["description"]);
|
|
13802
13869
|
const evseDescription = asJSONObject(evseInfo?.["description"]);
|
|
13803
|
-
const firstOCMDJSONDocument = OCMFJSONDocuments
|
|
13804
|
-
|
|
13805
|
-
|
|
13806
|
-
|
|
13807
|
-
|
|
13808
|
-
|
|
13809
|
-
|
|
13810
|
-
|
|
13811
|
-
|
|
13812
|
-
|
|
13813
|
-
|
|
13814
|
-
|
|
13815
|
-
|
|
13816
|
-
|
|
13817
|
-
|
|
13818
|
-
|
|
13819
|
-
|
|
13820
|
-
|
|
13821
|
-
|
|
13822
|
-
|
|
13823
|
-
|
|
13824
|
-
|
|
13825
|
-
|
|
13826
|
-
|
|
13827
|
-
|
|
13828
|
-
|
|
13829
|
-
|
|
13830
|
-
|
|
13831
|
-
|
|
13832
|
-
|
|
13833
|
-
|
|
13834
|
-
|
|
13835
|
-
|
|
13836
|
-
|
|
13837
|
-
|
|
13838
|
-
|
|
13839
|
-
|
|
13840
|
-
|
|
13841
|
-
|
|
13842
|
-
|
|
13843
|
-
|
|
13844
|
-
|
|
13845
|
-
|
|
13846
|
-
|
|
13847
|
-
|
|
13848
|
-
|
|
13849
|
-
|
|
13850
|
-
|
|
13851
|
-
|
|
13852
|
-
|
|
13853
|
-
|
|
13854
|
-
|
|
13855
|
-
|
|
13856
|
-
|
|
13857
|
-
|
|
13858
|
-
|
|
13859
|
-
|
|
13870
|
+
const firstOCMDJSONDocument = getFirstArrayElement(OCMFJSONDocuments, "Missing first OCMF JSON document");
|
|
13871
|
+
const formatVersion = firstOCMDJSONDocument.payload.FV;
|
|
13872
|
+
const gatewayInformation = firstOCMDJSONDocument.payload.GI ?? firstOCMDJSONDocument.payload.VI;
|
|
13873
|
+
const gatewaySerial = firstOCMDJSONDocument.payload.GS;
|
|
13874
|
+
const gatewayVersion = firstOCMDJSONDocument.payload.GV ?? firstOCMDJSONDocument.payload.VV;
|
|
13875
|
+
const paging = firstOCMDJSONDocument.payload.PG;
|
|
13876
|
+
const meterVendor = firstOCMDJSONDocument.payload.MV;
|
|
13877
|
+
const meterModel = firstOCMDJSONDocument.payload.MM;
|
|
13878
|
+
const meterSerial = firstOCMDJSONDocument.payload.MS;
|
|
13879
|
+
const effectiveMeterSerial = meterSerial ?? gatewaySerial;
|
|
13880
|
+
const meterFirmware = firstOCMDJSONDocument.payload.MF;
|
|
13881
|
+
const identificationStatus = firstOCMDJSONDocument.payload.IS;
|
|
13882
|
+
const identificationLevel = firstOCMDJSONDocument.payload.IL;
|
|
13883
|
+
const identificationFlags = firstOCMDJSONDocument.payload.IF;
|
|
13884
|
+
const identificationType = firstOCMDJSONDocument.payload.IT;
|
|
13885
|
+
const identificationData = firstOCMDJSONDocument.payload.ID;
|
|
13886
|
+
const tariffText = firstOCMDJSONDocument.payload.TT;
|
|
13887
|
+
const controlerFirmwareVersion = firstOCMDJSONDocument.payload.CF;
|
|
13888
|
+
const lossCompensation = firstOCMDJSONDocument.payload.LC;
|
|
13889
|
+
const chargePointIdType = firstOCMDJSONDocument.payload.CT;
|
|
13890
|
+
const chargePointId = firstOCMDJSONDocument.payload.CI;
|
|
13891
|
+
if (isOptionalString(formatVersion) && isOptionalString(gatewayInformation) && isOptionalString(gatewaySerial) && isOptionalString(gatewayVersion) && isMandatoryString(paging) && isOptionalString(meterVendor) && isOptionalString(meterModel) && // OCMF 1.0 table 3 lists MS as 1..1, but the later "Relation of Serial Numbers,
|
|
13892
|
+
// Charge Point and Public Key" section makes the serial-number fields conditionally
|
|
13893
|
+
// mandatory. KEBA KCP30 records identify the signing gateway via GS and omit MS.
|
|
13894
|
+
// Therefore we keep meterSerial and gatewaySerial separate, but require at least one
|
|
13895
|
+
// usable serial number for the CTR meter identity.
|
|
13896
|
+
isMandatoryString(effectiveMeterSerial) && isOptionalString(meterFirmware) && // OCMF 1.x uses boolean IS values. OCMF 0.1 SAFE reference data used status strings
|
|
13897
|
+
// such as "VERIFIED", so accept both forms and preserve the original value in the CTR.
|
|
13898
|
+
(isMandatoryBoolean(identificationStatus) || isMandatoryString(identificationStatus)) && isOptionalString(identificationLevel) && //chargyLib.isMandatoryArrayOfStrings (identificationFlags) &&
|
|
13899
|
+
isOptionalArrayOfStrings(identificationFlags) && // Note: Some vendors do not use this MANDATORY field!
|
|
13900
|
+
// IT is 1..1 in the user-assignment table for transaction records. Some OCMF 1.0
|
|
13901
|
+
// implementations omit it when no user is assigned (IS=false, ID empty). We tolerate
|
|
13902
|
+
// this vendor compatibility case instead of rejecting otherwise valid signatures.
|
|
13903
|
+
isOptionalString(identificationType) && isOptionalString(identificationData) && isOptionalString(tariffText) && isOptionalString(controlerFirmwareVersion) && isOptionalJSONObject(lossCompensation) && isOptionalString(chargePointIdType) && isOptionalString(chargePointId)) {
|
|
13904
|
+
const paginationPrefix = paging.length > 0 ? paging.charAt(0).toLowerCase() : null;
|
|
13905
|
+
const transactionType = paginationPrefix === "t" ? "transaction" /* transaction */ : paginationPrefix === "f" ? "fiscal" /* fiscal */ : "undefined" /* undefined */;
|
|
13906
|
+
const pagination = paging.length > 1 ? parseNumber(paging.substring(1)) : null;
|
|
13907
|
+
if (transactionType === "undefined" /* undefined */) return {
|
|
13908
|
+
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
13909
|
+
message: this.chargy.GetMultilanguageText("The given OCMF data does not have a valid transaction type!"),
|
|
13910
|
+
certainty: 0
|
|
13911
|
+
};
|
|
13912
|
+
if (!isMandatoryNumber(pagination)) return {
|
|
13913
|
+
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
13914
|
+
message: this.chargy.GetMultilanguageText("The given OCMF data does not have a valid pagination counter!"),
|
|
13915
|
+
certainty: 0
|
|
13916
|
+
};
|
|
13917
|
+
if (firstOCMDJSONDocument.payload.RD.length == 0) return {
|
|
13918
|
+
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
13919
|
+
message: this.chargy.GetMultilanguageText("Each OCMF data set must have at least one meter reading!"),
|
|
13920
|
+
certainty: 0
|
|
13921
|
+
};
|
|
13922
|
+
const CTR = {
|
|
13923
|
+
"@id": "?",
|
|
13924
|
+
"@context": "https://open.charging.cloud/contexts/CTR+json",
|
|
13925
|
+
//"@context": [ "https://open.charging.cloud/contexts/CTR+json", "https://open.charging.cloud/contexts/CTR_OCMF+json" ],
|
|
13926
|
+
"begin": "?",
|
|
13927
|
+
"end": "?",
|
|
13928
|
+
"description": {
|
|
13929
|
+
"de": "Alle OCMF-Ladevorg\xE4nge"
|
|
13930
|
+
},
|
|
13931
|
+
"contract": {
|
|
13932
|
+
"@id": identificationData ?? "?",
|
|
13933
|
+
"type": identificationType ?? "?"
|
|
13934
|
+
},
|
|
13935
|
+
"ocmf": {
|
|
13936
|
+
"formatVersion": formatVersion,
|
|
13937
|
+
"gatewayInformation": gatewayInformation,
|
|
13938
|
+
"gatewaySerial": gatewaySerial,
|
|
13939
|
+
"gatewayVersion": gatewayVersion
|
|
13940
|
+
},
|
|
13941
|
+
// "chargingStationOperators": [{
|
|
13942
|
+
"chargingPools": [{
|
|
13943
|
+
"@id": "DE*GEF*POOL*CHARGY*1",
|
|
13944
|
+
"description": { "en": "GraphDefined CHARGY Virtual Charging Pool 1" },
|
|
13945
|
+
"chargingStations": [{
|
|
13946
|
+
"@id": chargingStationId,
|
|
13947
|
+
"description": stationDescription && Object.keys(stationDescription).length > 0 ? stationDescription : { "en": "GraphDefined CHARGY Virtual Charging Station 1" },
|
|
13948
|
+
"firmwareVersion": asString(chargingStationInfo?.["softwareVersion"]) ?? asString(chargingStationInfo?.["firmwareVersion"]),
|
|
13949
|
+
"geoLocation": asJSONObject(chargingStationInfo?.["geoLocation"]),
|
|
13950
|
+
"address": asJSONObject(chargingStationInfo?.["address"]),
|
|
13951
|
+
"EVSEs": [{
|
|
13952
|
+
"@id": evseId,
|
|
13953
|
+
"description": evseDescription && Object.keys(evseDescription).length > 0 ? evseDescription : { "en": "GraphDefined CHARGY Virtual EVSE 1" },
|
|
13954
|
+
"connectors": connectorInfo ? [{
|
|
13955
|
+
"type": asString(connectorInfo["type"]) ?? "",
|
|
13956
|
+
"looses": asNumber(connectorInfo["looses"]) ?? 0
|
|
13957
|
+
}] : void 0,
|
|
13958
|
+
"meters": [{
|
|
13959
|
+
"@id": effectiveMeterSerial,
|
|
13960
|
+
// The signed OCMF payload values always win,
|
|
13961
|
+
// the container infos only fill the gaps!
|
|
13962
|
+
"manufacturer": meterVendor ?? asString(energyMeterInfo?.["manufacturer"]),
|
|
13963
|
+
"manufacturerURL": asString(energyMeterInfo?.["manufacturerURL"]),
|
|
13964
|
+
"model": meterModel ?? asString(energyMeterInfo?.["model"]),
|
|
13965
|
+
"modelURL": asString(energyMeterInfo?.["modelURL"]),
|
|
13966
|
+
"hardwareVersion": asString(energyMeterInfo?.["hardwareVersion"]),
|
|
13967
|
+
"firmwareVersion": meterFirmware ?? asString(energyMeterInfo?.["firmwareVersion"]),
|
|
13968
|
+
"signatureFormat": "https://open.charging.cloud/contexts/EnergyMeterSignatureFormats/OCMFv1.0+json",
|
|
13969
|
+
"publicKeys": [{
|
|
13970
|
+
"algorithm": "?",
|
|
13971
|
+
"encoding": "?",
|
|
13972
|
+
"format": "?",
|
|
13973
|
+
"value": "?"
|
|
13974
|
+
}]
|
|
13975
|
+
}]
|
|
13976
|
+
}]
|
|
13977
|
+
}]
|
|
13978
|
+
}],
|
|
13979
|
+
"chargingSessions": [{
|
|
13980
|
+
"@id": "1554181214441:-1965658344385548683:2",
|
|
13981
|
+
"@context": "https://open.charging.cloud/contexts/SessionSignatureFormats/OCMFv1.0+json",
|
|
13860
13982
|
"begin": "?",
|
|
13861
13983
|
"end": "?",
|
|
13862
|
-
"
|
|
13863
|
-
|
|
13864
|
-
},
|
|
13865
|
-
"contract": {
|
|
13984
|
+
"EVSEId": evseId,
|
|
13985
|
+
"authorizationStart": {
|
|
13866
13986
|
"@id": identificationData ?? "?",
|
|
13867
|
-
"type": identificationType ?? "?"
|
|
13868
|
-
|
|
13869
|
-
|
|
13870
|
-
"
|
|
13871
|
-
|
|
13872
|
-
"gatewaySerial": gatewaySerial,
|
|
13873
|
-
"gatewayVersion": gatewayVersion
|
|
13987
|
+
"type": identificationType ?? "?",
|
|
13988
|
+
"identificationStatus": identificationStatus,
|
|
13989
|
+
"identificationLevel": identificationLevel,
|
|
13990
|
+
"identificationFlags": identificationFlags ?? []
|
|
13991
|
+
// Note: The OCMF documentation expects an empty array!
|
|
13874
13992
|
},
|
|
13875
|
-
|
|
13876
|
-
|
|
13877
|
-
|
|
13878
|
-
|
|
13879
|
-
|
|
13880
|
-
|
|
13881
|
-
|
|
13882
|
-
|
|
13883
|
-
|
|
13884
|
-
|
|
13885
|
-
|
|
13886
|
-
|
|
13887
|
-
|
|
13888
|
-
|
|
13889
|
-
|
|
13890
|
-
|
|
13891
|
-
|
|
13892
|
-
|
|
13893
|
-
|
|
13894
|
-
|
|
13895
|
-
|
|
13896
|
-
|
|
13897
|
-
|
|
13898
|
-
|
|
13899
|
-
|
|
13900
|
-
|
|
13901
|
-
|
|
13902
|
-
|
|
13903
|
-
|
|
13904
|
-
|
|
13905
|
-
|
|
13906
|
-
|
|
13907
|
-
|
|
13908
|
-
|
|
13909
|
-
|
|
13910
|
-
|
|
13911
|
-
|
|
13912
|
-
|
|
13913
|
-
|
|
13914
|
-
|
|
13915
|
-
|
|
13916
|
-
|
|
13917
|
-
|
|
13918
|
-
|
|
13919
|
-
|
|
13920
|
-
|
|
13921
|
-
|
|
13922
|
-
"
|
|
13923
|
-
|
|
13924
|
-
|
|
13925
|
-
|
|
13926
|
-
|
|
13927
|
-
|
|
13928
|
-
|
|
13929
|
-
|
|
13930
|
-
|
|
13931
|
-
|
|
13932
|
-
|
|
13933
|
-
|
|
13934
|
-
|
|
13935
|
-
|
|
13936
|
-
const time = effectiveReading.TM;
|
|
13937
|
-
const transaction = effectiveReading.TX;
|
|
13938
|
-
const readingValue = effectiveReading.RV;
|
|
13939
|
-
const readingIdentification = effectiveReading.RI;
|
|
13940
|
-
const readingUnit = effectiveReading.RU;
|
|
13941
|
-
const readingCurrentType = effectiveReading.RT;
|
|
13942
|
-
const cumulatedLoss = effectiveReading.CL;
|
|
13943
|
-
const errorFlags = effectiveReading.EF;
|
|
13944
|
-
const status = effectiveReading.ST;
|
|
13945
|
-
inheritedReading = effectiveReading;
|
|
13946
|
-
if (isMandatoryString(time) && isOptionalString(transaction) && isMandatoryDecimal(readingValue) && // Note: Some vendors use a JSON string here!
|
|
13947
|
-
isOptionalString(readingIdentification) && isMandatoryString(readingUnit) && isOptionalString(readingCurrentType) && isOptionalDecimal(cumulatedLoss) && isOptionalString(errorFlags) && isMandatoryString(status)) {
|
|
13948
|
-
const timeSplit = time.split(" ");
|
|
13949
|
-
if (timeSplit.length != 2) return {
|
|
13950
|
-
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
13951
|
-
message: this.chargy.GetLocalizedMessage("The given OCMF meter value does not have a valid time format!"),
|
|
13952
|
-
certainty: 0
|
|
13953
|
-
};
|
|
13954
|
-
const timeRegEx = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2},\d{3}[+-]\d{4}$/;
|
|
13955
|
-
const timeStamp = timeSplit[0];
|
|
13956
|
-
if (!isMandatoryString(timeStamp) || !timeRegEx.test(timeStamp)) return {
|
|
13957
|
-
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
13958
|
-
message: this.chargy.GetLocalizedMessage("The given OCMF meter value does not have a valid time sync format!"),
|
|
13959
|
-
certainty: 0
|
|
13960
|
-
};
|
|
13961
|
-
const timeStampISO8601 = this.convertToISO8601(timeStamp);
|
|
13962
|
-
const timeSyncText = timeSplit[1];
|
|
13963
|
-
let timeSync = "unknown" /* unknown */;
|
|
13964
|
-
if (!isMandatoryString(timeSyncText) || !["U", "I", "S", "R"].includes(timeSyncText)) return {
|
|
13965
|
-
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
13966
|
-
message: this.chargy.GetLocalizedMessage("The given OCMF meter value does not have a valid time sync format!"),
|
|
13967
|
-
certainty: 0
|
|
13968
|
-
};
|
|
13969
|
-
switch (timeSyncText) {
|
|
13970
|
-
case "U":
|
|
13971
|
-
timeSync = "unknown" /* unknown */;
|
|
13972
|
-
break;
|
|
13973
|
-
case "I":
|
|
13974
|
-
timeSync = "informative" /* informative */;
|
|
13975
|
-
break;
|
|
13976
|
-
case "S":
|
|
13977
|
-
timeSync = "syncronized" /* syncronized */;
|
|
13978
|
-
break;
|
|
13979
|
-
case "R":
|
|
13980
|
-
timeSync = "relative" /* relative */;
|
|
13981
|
-
break;
|
|
13982
|
-
default:
|
|
13983
|
-
return {
|
|
13984
|
-
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
13985
|
-
message: this.chargy.GetLocalizedMessage("The given OCMF meter value does not have a valid time sync format!"),
|
|
13986
|
-
certainty: 0
|
|
13987
|
-
};
|
|
13988
|
-
}
|
|
13989
|
-
if (transaction && !["B", "C", "X", "E", "L", "R", "A", "P", "S", "T"].includes(transaction)) return {
|
|
13990
|
-
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
13991
|
-
message: this.chargy.GetLocalizedMessage("The given OCMF meter value does not have a valid transaction type!"),
|
|
13992
|
-
certainty: 0
|
|
13993
|
-
};
|
|
13994
|
-
if (!["kWh", "Wh", "mOhm", "uOhm"].includes(readingUnit)) return {
|
|
13995
|
-
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
13996
|
-
message: this.chargy.GetLocalizedMessage("The given OCMF meter value does not have a valid current type!"),
|
|
13997
|
-
certainty: 0
|
|
13998
|
-
};
|
|
13999
|
-
if (readingCurrentType && !["AC", "DC"].includes(readingCurrentType)) return {
|
|
14000
|
-
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
14001
|
-
message: this.chargy.GetLocalizedMessage("The given OCMF meter value does not have a valid current type!"),
|
|
14002
|
-
certainty: 0
|
|
14003
|
-
};
|
|
14004
|
-
if (CTR.chargingSessions?.[0]?.begin === "?")
|
|
14005
|
-
CTR.chargingSessions[0].begin = timeStampISO8601;
|
|
14006
|
-
CTR.chargingSessions[0].end = timeStampISO8601;
|
|
14007
|
-
const measurementKey = [
|
|
14008
|
-
readingIdentification ?? "?",
|
|
14009
|
-
readingUnit,
|
|
14010
|
-
readingCurrentType ?? ""
|
|
14011
|
-
].join("|");
|
|
14012
|
-
let measurement = measurementsByKey.get(measurementKey);
|
|
14013
|
-
if (measurement == null) {
|
|
14014
|
-
measurement = {
|
|
14015
|
-
"name": OBIS2MeasurementName(readingIdentification ?? ""),
|
|
14016
|
-
"scale": 0,
|
|
14017
|
-
"energyMeterId": effectiveMeterSerial,
|
|
14018
|
-
"@context": "https://open.charging.cloud/contexts/EnergyMeterSignatureFormats/OCMFv1.0+json",
|
|
14019
|
-
"obis": readingIdentification ?? "?",
|
|
14020
|
-
// OBIS: "1-b:1.8.0"
|
|
14021
|
-
"unit": readingUnit,
|
|
14022
|
-
// "kWh"
|
|
14023
|
-
"currentType": readingCurrentType,
|
|
14024
|
-
// "AC"
|
|
14025
|
-
"values": []
|
|
13993
|
+
"measurements": []
|
|
13994
|
+
}],
|
|
13995
|
+
"certainty": 1
|
|
13996
|
+
};
|
|
13997
|
+
const measurementsByKey = /* @__PURE__ */ new Map();
|
|
13998
|
+
for (const ocmfJSONDocument of OCMFJSONDocuments) {
|
|
13999
|
+
let inheritedReading = {};
|
|
14000
|
+
for (const reading of ocmfJSONDocument.payload.RD) {
|
|
14001
|
+
const effectiveReading = { ...inheritedReading, ...reading };
|
|
14002
|
+
const time = effectiveReading.TM;
|
|
14003
|
+
const transaction = effectiveReading.TX;
|
|
14004
|
+
const readingValue = effectiveReading.RV;
|
|
14005
|
+
const readingIdentification = effectiveReading.RI;
|
|
14006
|
+
const readingUnit = effectiveReading.RU;
|
|
14007
|
+
const readingCurrentType = effectiveReading.RT;
|
|
14008
|
+
const cumulatedLoss = effectiveReading.CL;
|
|
14009
|
+
const errorFlags = effectiveReading.EF;
|
|
14010
|
+
const status = effectiveReading.ST;
|
|
14011
|
+
inheritedReading = effectiveReading;
|
|
14012
|
+
if (isMandatoryString(time) && isOptionalString(transaction) && isMandatoryDecimal(readingValue) && // Note: Some vendors use a JSON string here!
|
|
14013
|
+
isOptionalString(readingIdentification) && isMandatoryString(readingUnit) && isOptionalString(readingCurrentType) && // chargyLib.isOptionalDecimal (cumulatedLoss) &&
|
|
14014
|
+
isOptionalString(errorFlags) && isMandatoryString(status)) {
|
|
14015
|
+
const timeSplit = time.split(" ");
|
|
14016
|
+
if (timeSplit.length != 2) return {
|
|
14017
|
+
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
14018
|
+
message: this.chargy.GetMultilanguageText("The given OCMF meter value does not have a valid time format!"),
|
|
14019
|
+
certainty: 0
|
|
14020
|
+
};
|
|
14021
|
+
const timeRegEx = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2},\d{3}[+-]\d{4}$/;
|
|
14022
|
+
const timeStamp = timeSplit[0];
|
|
14023
|
+
if (!isMandatoryString(timeStamp) || !timeRegEx.test(timeStamp)) return {
|
|
14024
|
+
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
14025
|
+
message: this.chargy.GetMultilanguageText("The given OCMF meter value does not have a valid time sync format!"),
|
|
14026
|
+
certainty: 0
|
|
14027
|
+
};
|
|
14028
|
+
const timeStampISO8601 = this.convertToISO8601(timeStamp);
|
|
14029
|
+
const timeSyncText = timeSplit[1];
|
|
14030
|
+
let timeSync = "unknown" /* unknown */;
|
|
14031
|
+
if (!isMandatoryString(timeSyncText) || !["U", "I", "S", "R"].includes(timeSyncText)) return {
|
|
14032
|
+
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
14033
|
+
message: this.chargy.GetMultilanguageText("The given OCMF meter value does not have a valid time sync format!"),
|
|
14034
|
+
certainty: 0
|
|
14035
|
+
};
|
|
14036
|
+
switch (timeSyncText) {
|
|
14037
|
+
case "U":
|
|
14038
|
+
timeSync = "unknown" /* unknown */;
|
|
14039
|
+
break;
|
|
14040
|
+
case "I":
|
|
14041
|
+
timeSync = "informative" /* informative */;
|
|
14042
|
+
break;
|
|
14043
|
+
case "S":
|
|
14044
|
+
timeSync = "syncronized" /* syncronized */;
|
|
14045
|
+
break;
|
|
14046
|
+
case "R":
|
|
14047
|
+
timeSync = "relative" /* relative */;
|
|
14048
|
+
break;
|
|
14049
|
+
default:
|
|
14050
|
+
return {
|
|
14051
|
+
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
14052
|
+
message: this.chargy.GetMultilanguageText("The given OCMF meter value does not have a valid time sync format!"),
|
|
14053
|
+
certainty: 0
|
|
14026
14054
|
};
|
|
14027
|
-
measurementsByKey.set(measurementKey, measurement);
|
|
14028
|
-
CTR.chargingSessions[0].measurements.push(measurement);
|
|
14029
|
-
}
|
|
14030
|
-
measurement.values.push({
|
|
14031
|
-
"timestamp": timeStampISO8601,
|
|
14032
|
-
// "2019-06-26T08:57:44,337+0000"
|
|
14033
|
-
"timeSync": timeSync,
|
|
14034
|
-
// "U"|"I"|"S"|"R"
|
|
14035
|
-
"transaction": transaction,
|
|
14036
|
-
// "B"|"C"|"X"|"E"|"L"|"R"|"A"|"P"|"S"|"T"|null
|
|
14037
|
-
"value": new Decimal(readingValue),
|
|
14038
|
-
// 2935.6
|
|
14039
|
-
"transactionType": transactionType,
|
|
14040
|
-
// "T" ToDo: Serialize this to a string!
|
|
14041
|
-
"pagination": pagination,
|
|
14042
|
-
// "9289"
|
|
14043
|
-
"errorFlags": errorFlags,
|
|
14044
|
-
// ""
|
|
14045
|
-
"cumulatedLoss": cumulatedLoss ? new Decimal(cumulatedLoss) : void 0,
|
|
14046
|
-
"status": status,
|
|
14047
|
-
// "G"
|
|
14048
|
-
// "signatures": [{
|
|
14049
|
-
// "value": ocmfJSONDocument.signature["SD"]
|
|
14050
|
-
// }],
|
|
14051
|
-
"result": {
|
|
14052
|
-
"status": ocmfJSONDocument.validationStatus ?? "Unvalidated" /* Unvalidated */
|
|
14053
|
-
},
|
|
14054
|
-
"ocmfDocument": ocmfJSONDocument
|
|
14055
|
-
});
|
|
14056
14055
|
}
|
|
14056
|
+
if (transaction != null && transaction.length > 0 && !["B", "C", "X", "E", "L", "R", "A", "P", "S", "T"].includes(transaction)) return {
|
|
14057
|
+
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
14058
|
+
message: this.chargy.GetMultilanguageText("The given OCMF meter value does not have a valid transaction type!"),
|
|
14059
|
+
certainty: 0
|
|
14060
|
+
};
|
|
14061
|
+
if (!["kWh", "Wh", "mOhm", "uOhm"].includes(readingUnit)) return {
|
|
14062
|
+
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
14063
|
+
message: this.chargy.GetMultilanguageText("The given OCMF meter value does not have a valid current type!"),
|
|
14064
|
+
certainty: 0
|
|
14065
|
+
};
|
|
14066
|
+
if (readingCurrentType != null && readingCurrentType.length > 0 && !["AC", "DC"].includes(readingCurrentType)) return {
|
|
14067
|
+
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
14068
|
+
message: this.chargy.GetMultilanguageText("The given OCMF meter value does not have a valid current type!"),
|
|
14069
|
+
certainty: 0
|
|
14070
|
+
};
|
|
14071
|
+
if (CTR.chargingSessions?.[0]?.begin === "?")
|
|
14072
|
+
CTR.chargingSessions[0].begin = timeStampISO8601;
|
|
14073
|
+
if (CTR.chargingSessions?.[0] !== void 0)
|
|
14074
|
+
CTR.chargingSessions[0].end = timeStampISO8601;
|
|
14075
|
+
const measurementKey = [
|
|
14076
|
+
readingIdentification ?? "?",
|
|
14077
|
+
readingUnit,
|
|
14078
|
+
readingCurrentType ?? ""
|
|
14079
|
+
].join("|");
|
|
14080
|
+
let measurement = measurementsByKey.get(measurementKey);
|
|
14081
|
+
if (measurement == null) {
|
|
14082
|
+
measurement = {
|
|
14083
|
+
"name": OBIS2MeasurementName(readingIdentification ?? ""),
|
|
14084
|
+
"scale": 0,
|
|
14085
|
+
"energyMeterId": effectiveMeterSerial,
|
|
14086
|
+
"@context": "https://open.charging.cloud/contexts/EnergyMeterSignatureFormats/OCMFv1.0+json",
|
|
14087
|
+
"obis": readingIdentification ?? "?",
|
|
14088
|
+
// OBIS: "1-b:1.8.0"
|
|
14089
|
+
"unit": readingUnit,
|
|
14090
|
+
// "kWh"
|
|
14091
|
+
"currentType": readingCurrentType,
|
|
14092
|
+
// "AC"
|
|
14093
|
+
"values": []
|
|
14094
|
+
};
|
|
14095
|
+
measurementsByKey.set(measurementKey, measurement);
|
|
14096
|
+
const firstChargingSession = CTR.chargingSessions?.[0];
|
|
14097
|
+
if (firstChargingSession !== void 0)
|
|
14098
|
+
firstChargingSession.measurements.push(measurement);
|
|
14099
|
+
}
|
|
14100
|
+
measurement.values.push({
|
|
14101
|
+
"timestamp": timeStampISO8601,
|
|
14102
|
+
// "2019-06-26T08:57:44,337+0000"
|
|
14103
|
+
"timeSync": timeSync,
|
|
14104
|
+
// "U"|"I"|"S"|"R"
|
|
14105
|
+
"transaction": transaction,
|
|
14106
|
+
// "B"|"C"|"X"|"E"|"L"|"R"|"A"|"P"|"S"|"T"|null
|
|
14107
|
+
"value": new Decimal(readingValue),
|
|
14108
|
+
// 2935.6
|
|
14109
|
+
"transactionType": transactionType,
|
|
14110
|
+
// "T" ToDo: Serialize this to a string!
|
|
14111
|
+
"pagination": pagination,
|
|
14112
|
+
// "9289"
|
|
14113
|
+
"errorFlags": errorFlags,
|
|
14114
|
+
// ""
|
|
14115
|
+
"cumulatedLoss": cumulatedLoss != null && cumulatedLoss !== 0 ? new Decimal(cumulatedLoss) : void 0,
|
|
14116
|
+
"status": status,
|
|
14117
|
+
// "G"
|
|
14118
|
+
// "signatures": [{
|
|
14119
|
+
// "value": ocmfJSONDocument.signature["SD"]
|
|
14120
|
+
// }],
|
|
14121
|
+
"result": {
|
|
14122
|
+
"status": ocmfJSONDocument.validationStatus ?? "Unvalidated" /* Unvalidated */
|
|
14123
|
+
},
|
|
14124
|
+
"ocmfDocument": ocmfJSONDocument
|
|
14125
|
+
});
|
|
14057
14126
|
}
|
|
14058
14127
|
}
|
|
14059
|
-
|
|
14060
|
-
|
|
14061
|
-
|
|
14062
|
-
|
|
14063
|
-
|
|
14064
|
-
|
|
14128
|
+
}
|
|
14129
|
+
CTR.status = OCMFJSONDocuments.every((ocmfJSONDocument) => ocmfJSONDocument.validationStatus === "ValidSignature" /* ValidSignature */) ? "ValidSignature" /* ValidSignature */ : "InvalidSignature" /* InvalidSignature */;
|
|
14130
|
+
if (CTR.chargingSessions != null && CTR.chargingSessions.length > 0 && CTR.chargingSessions[0]) {
|
|
14131
|
+
CTR.begin = CTR.chargingSessions[0].begin;
|
|
14132
|
+
CTR.end = CTR.chargingSessions[0].end;
|
|
14133
|
+
return CTR;
|
|
14065
14134
|
}
|
|
14066
14135
|
}
|
|
14067
14136
|
} catch (exception) {
|
|
14068
14137
|
return {
|
|
14069
14138
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
14070
|
-
message: "Invalid OCMF data: " + (exception instanceof Error ? exception.message : String(exception)),
|
|
14139
|
+
message: this.chargy.GetMultilanguageText("Invalid OCMF data: " + (exception instanceof Error ? exception.message : String(exception))),
|
|
14071
14140
|
certainty: 0
|
|
14072
14141
|
};
|
|
14073
14142
|
}
|
|
@@ -14078,113 +14147,121 @@ var OCMF = class {
|
|
|
14078
14147
|
}
|
|
14079
14148
|
//#endregion
|
|
14080
14149
|
//#region (private) mergeOCMFSessions(CTRs)
|
|
14081
|
-
mergeOCMFSessions(CTRs)
|
|
14082
|
-
|
|
14083
|
-
|
|
14084
|
-
|
|
14085
|
-
|
|
14086
|
-
|
|
14087
|
-
|
|
14088
|
-
|
|
14089
|
-
|
|
14090
|
-
|
|
14091
|
-
|
|
14092
|
-
|
|
14093
|
-
|
|
14094
|
-
|
|
14095
|
-
|
|
14096
|
-
|
|
14097
|
-
|
|
14098
|
-
|
|
14099
|
-
|
|
14100
|
-
|
|
14101
|
-
|
|
14102
|
-
|
|
14103
|
-
|
|
14104
|
-
|
|
14105
|
-
|
|
14106
|
-
|
|
14107
|
-
|
|
14108
|
-
|
|
14109
|
-
|
|
14110
|
-
|
|
14111
|
-
|
|
14112
|
-
|
|
14113
|
-
|
|
14114
|
-
|
|
14115
|
-
|
|
14116
|
-
|
|
14117
|
-
|
|
14118
|
-
|
|
14119
|
-
|
|
14120
|
-
|
|
14121
|
-
|
|
14122
|
-
|
|
14123
|
-
|
|
14124
|
-
|
|
14125
|
-
|
|
14126
|
-
|
|
14127
|
-
|
|
14128
|
-
|
|
14129
|
-
|
|
14130
|
-
|
|
14131
|
-
|
|
14132
|
-
|
|
14150
|
+
// private mergeOCMFSessions(CTRs: Array<IOCMFChargeTransparencyRecord>): IOCMFChargeTransparencyRecord
|
|
14151
|
+
// {
|
|
14152
|
+
// const mergedCTR:IOCMFChargeTransparencyRecord = {
|
|
14153
|
+
// "@id": "",
|
|
14154
|
+
// "@context": "",
|
|
14155
|
+
// certainty: 1
|
|
14156
|
+
// };
|
|
14157
|
+
// for (const ctr of CTRs)
|
|
14158
|
+
// {
|
|
14159
|
+
// if (mergedCTR["@id"] === "")
|
|
14160
|
+
// mergedCTR["@id"] = ctr["@id"];
|
|
14161
|
+
// if (mergedCTR["@context"] === "")
|
|
14162
|
+
// mergedCTR["@context"] = ctr["@context"];
|
|
14163
|
+
// if (!mergedCTR.begin || (mergedCTR.begin && ctr.begin && mergedCTR.begin > ctr.begin))
|
|
14164
|
+
// mergedCTR.begin = ctr.begin;
|
|
14165
|
+
// if (!mergedCTR.end || (mergedCTR.end && ctr.end && mergedCTR.end < ctr.end))
|
|
14166
|
+
// mergedCTR.end = ctr.end;
|
|
14167
|
+
// if (!mergedCTR.description)
|
|
14168
|
+
// mergedCTR.description = ctr.description;
|
|
14169
|
+
// //ToDo: Is this a really good idea? Or should we fail, whenever this information is different?
|
|
14170
|
+
// if (!mergedCTR.contract)
|
|
14171
|
+
// mergedCTR.contract = ctr.contract;
|
|
14172
|
+
// if (!mergedCTR.chargingStationOperators)
|
|
14173
|
+
// mergedCTR.chargingStationOperators = ctr.chargingStationOperators;
|
|
14174
|
+
// else if (ctr.chargingStationOperators)
|
|
14175
|
+
// for (const chargingStationOperator of ctr.chargingStationOperators)
|
|
14176
|
+
// mergedCTR.chargingStationOperators.push(chargingStationOperator);
|
|
14177
|
+
// if (!mergedCTR.chargingPools)
|
|
14178
|
+
// mergedCTR.chargingPools = ctr.chargingPools;
|
|
14179
|
+
// else if (ctr.chargingPools)
|
|
14180
|
+
// for (const chargingPool of ctr.chargingPools)
|
|
14181
|
+
// mergedCTR.chargingPools.push(chargingPool);
|
|
14182
|
+
// if (!mergedCTR.chargingStations)
|
|
14183
|
+
// mergedCTR.chargingStations = ctr.chargingStations;
|
|
14184
|
+
// else if (ctr.chargingStations)
|
|
14185
|
+
// for (const chargingStation of ctr.chargingStations)
|
|
14186
|
+
// mergedCTR.chargingStations.push(chargingStation);
|
|
14187
|
+
// // publicKeys
|
|
14188
|
+
// if (!mergedCTR.chargingSessions)
|
|
14189
|
+
// mergedCTR.chargingSessions = ctr.chargingSessions;
|
|
14190
|
+
// else if (ctr.chargingSessions)
|
|
14191
|
+
// for (const chargingSession of ctr.chargingSessions)
|
|
14192
|
+
// mergedCTR.chargingSessions.push(chargingSession);
|
|
14193
|
+
// if (!mergedCTR.eMobilityProviders)
|
|
14194
|
+
// mergedCTR.eMobilityProviders = ctr.eMobilityProviders;
|
|
14195
|
+
// else if (ctr.eMobilityProviders)
|
|
14196
|
+
// for (const eMobilityProvider of ctr.eMobilityProviders)
|
|
14197
|
+
// mergedCTR.eMobilityProviders.push(eMobilityProvider);
|
|
14198
|
+
// if (!mergedCTR.mediationServices)
|
|
14199
|
+
// mergedCTR.mediationServices = ctr.mediationServices;
|
|
14200
|
+
// else if (ctr.mediationServices)
|
|
14201
|
+
// for (const mediationService of ctr.mediationServices)
|
|
14202
|
+
// mergedCTR.mediationServices.push(mediationService);
|
|
14203
|
+
// }
|
|
14204
|
+
// return mergedCTR;
|
|
14205
|
+
// }
|
|
14133
14206
|
//#endregion
|
|
14134
14207
|
//#region (private) mergeChargeTransparencyRecords(CTRs)
|
|
14135
|
-
mergeChargeTransparencyRecords(CTRs)
|
|
14136
|
-
|
|
14137
|
-
|
|
14138
|
-
|
|
14139
|
-
|
|
14140
|
-
|
|
14141
|
-
|
|
14142
|
-
|
|
14143
|
-
|
|
14144
|
-
|
|
14145
|
-
|
|
14146
|
-
|
|
14147
|
-
|
|
14148
|
-
|
|
14149
|
-
|
|
14150
|
-
|
|
14151
|
-
|
|
14152
|
-
|
|
14153
|
-
|
|
14154
|
-
|
|
14155
|
-
|
|
14156
|
-
|
|
14157
|
-
|
|
14158
|
-
|
|
14159
|
-
|
|
14160
|
-
|
|
14161
|
-
|
|
14162
|
-
|
|
14163
|
-
|
|
14164
|
-
|
|
14165
|
-
|
|
14166
|
-
|
|
14167
|
-
|
|
14168
|
-
|
|
14169
|
-
|
|
14170
|
-
|
|
14171
|
-
|
|
14172
|
-
|
|
14173
|
-
|
|
14174
|
-
|
|
14175
|
-
|
|
14176
|
-
|
|
14177
|
-
|
|
14178
|
-
|
|
14179
|
-
|
|
14180
|
-
|
|
14181
|
-
|
|
14182
|
-
|
|
14183
|
-
|
|
14184
|
-
|
|
14185
|
-
|
|
14186
|
-
|
|
14187
|
-
|
|
14208
|
+
// private mergeChargeTransparencyRecords(CTRs: Array<IOCMFChargeTransparencyRecord>): IOCMFChargeTransparencyRecord
|
|
14209
|
+
// {
|
|
14210
|
+
// const mergedCTR:IOCMFChargeTransparencyRecord = {
|
|
14211
|
+
// "@id": "",
|
|
14212
|
+
// "@context": "",
|
|
14213
|
+
// certainty: 1
|
|
14214
|
+
// };
|
|
14215
|
+
// for (const ctr of CTRs)
|
|
14216
|
+
// {
|
|
14217
|
+
// if (mergedCTR["@id"] === "")
|
|
14218
|
+
// mergedCTR["@id"] = ctr["@id"];
|
|
14219
|
+
// if (mergedCTR["@context"] === "")
|
|
14220
|
+
// mergedCTR["@context"] = ctr["@context"];
|
|
14221
|
+
// if (!mergedCTR.begin || (mergedCTR.begin && ctr.begin && mergedCTR.begin > ctr.begin))
|
|
14222
|
+
// mergedCTR.begin = ctr.begin;
|
|
14223
|
+
// if (!mergedCTR.end || (mergedCTR.end && ctr.end && mergedCTR.end < ctr.end))
|
|
14224
|
+
// mergedCTR.end = ctr.end;
|
|
14225
|
+
// if (!mergedCTR.description)
|
|
14226
|
+
// mergedCTR.description = ctr.description;
|
|
14227
|
+
// //ToDo: Is this a really good idea? Or should we fail, whenever this information is different?
|
|
14228
|
+
// if (!mergedCTR.contract)
|
|
14229
|
+
// mergedCTR.contract = ctr.contract;
|
|
14230
|
+
// if (!mergedCTR.chargingStationOperators)
|
|
14231
|
+
// mergedCTR.chargingStationOperators = ctr.chargingStationOperators;
|
|
14232
|
+
// else if (ctr.chargingStationOperators)
|
|
14233
|
+
// for (const chargingStationOperator of ctr.chargingStationOperators)
|
|
14234
|
+
// mergedCTR.chargingStationOperators.push(chargingStationOperator);
|
|
14235
|
+
// if (!mergedCTR.chargingPools)
|
|
14236
|
+
// mergedCTR.chargingPools = ctr.chargingPools;
|
|
14237
|
+
// else if (ctr.chargingPools)
|
|
14238
|
+
// for (const chargingPool of ctr.chargingPools)
|
|
14239
|
+
// mergedCTR.chargingPools.push(chargingPool);
|
|
14240
|
+
// if (!mergedCTR.chargingStations)
|
|
14241
|
+
// mergedCTR.chargingStations = ctr.chargingStations;
|
|
14242
|
+
// else if (ctr.chargingStations)
|
|
14243
|
+
// for (const chargingStation of ctr.chargingStations)
|
|
14244
|
+
// mergedCTR.chargingStations.push(chargingStation);
|
|
14245
|
+
// // publicKeys
|
|
14246
|
+
// if (!mergedCTR.chargingSessions)
|
|
14247
|
+
// mergedCTR.chargingSessions = ctr.chargingSessions;
|
|
14248
|
+
// else if (ctr.chargingSessions)
|
|
14249
|
+
// for (const chargingSession of ctr.chargingSessions)
|
|
14250
|
+
// mergedCTR.chargingSessions.push(chargingSession);
|
|
14251
|
+
// if (!mergedCTR.eMobilityProviders)
|
|
14252
|
+
// mergedCTR.eMobilityProviders = ctr.eMobilityProviders;
|
|
14253
|
+
// else if (ctr.eMobilityProviders)
|
|
14254
|
+
// for (const eMobilityProvider of ctr.eMobilityProviders)
|
|
14255
|
+
// mergedCTR.eMobilityProviders.push(eMobilityProvider);
|
|
14256
|
+
// if (!mergedCTR.mediationServices)
|
|
14257
|
+
// mergedCTR.mediationServices = ctr.mediationServices;
|
|
14258
|
+
// else if (ctr.mediationServices)
|
|
14259
|
+
// for (const mediationService of ctr.mediationServices)
|
|
14260
|
+
// mergedCTR.mediationServices.push(mediationService);
|
|
14261
|
+
// }
|
|
14262
|
+
// return mergedCTR;
|
|
14263
|
+
// }
|
|
14264
|
+
// //#endregion
|
|
14188
14265
|
//#region (private) validateOCMFSignature(OCMFJSONDocument, PublicKey, PublicKeyEncoding?)
|
|
14189
14266
|
async validateOCMFSignature(OCMFJSONDocument, PublicKey, PublicKeyEncoding) {
|
|
14190
14267
|
try {
|
|
@@ -14243,7 +14320,7 @@ var OCMF = class {
|
|
|
14243
14320
|
this.key("pubKey").bitstr()
|
|
14244
14321
|
);
|
|
14245
14322
|
});
|
|
14246
|
-
if (PublicKeyEncoding) {
|
|
14323
|
+
if (PublicKeyEncoding != null && PublicKeyEncoding.length > 0) {
|
|
14247
14324
|
switch (PublicKeyEncoding.toLowerCase()) {
|
|
14248
14325
|
case "hex":
|
|
14249
14326
|
publicKeyBytes = Buffer.from(OCMFJSONDocument.publicKey, "hex");
|
|
@@ -14271,11 +14348,12 @@ var OCMF = class {
|
|
|
14271
14348
|
publicKeyBytes = Buffer.from(OCMFJSONDocument.publicKey, "base64");
|
|
14272
14349
|
}
|
|
14273
14350
|
}
|
|
14274
|
-
if (
|
|
14351
|
+
if (publicKeyBytes == null) {
|
|
14275
14352
|
OCMFJSONDocument.validationStatus = "UnknownPublicKeyFormat" /* UnknownPublicKeyFormat */;
|
|
14276
14353
|
return OCMFJSONDocument.validationStatus;
|
|
14277
14354
|
}
|
|
14278
|
-
const
|
|
14355
|
+
const decodedPublicKeyASN1 = ECPoint.decode(publicKeyBytes, "der");
|
|
14356
|
+
const publicKeyASN1 = decodedPublicKeyASN1;
|
|
14279
14357
|
const coordinates = publicKeyASN1.pubKey.data.subarray(1);
|
|
14280
14358
|
const halfLength = coordinates.length / 2;
|
|
14281
14359
|
const publicKeyXY = {
|
|
@@ -14284,7 +14362,7 @@ var OCMF = class {
|
|
|
14284
14362
|
};
|
|
14285
14363
|
publicKey = curve.keyFromPublic(publicKeyXY, "hex");
|
|
14286
14364
|
OCMFJSONDocument.publicKey = {
|
|
14287
|
-
algorithm: OCMFJSONDocument.signature.SA ? OCMFJSONDocument.signature.SA.substring(
|
|
14365
|
+
algorithm: OCMFJSONDocument.signature.SA != null && OCMFJSONDocument.signature.SA.length > 0 ? OCMFJSONDocument.signature.SA.substring(
|
|
14288
14366
|
OCMFJSONDocument.signature.SA.indexOf("-") + 1,
|
|
14289
14367
|
OCMFJSONDocument.signature.SA.lastIndexOf("-")
|
|
14290
14368
|
) : "secp256r1",
|
|
@@ -14435,7 +14513,7 @@ var OCMF = class {
|
|
|
14435
14513
|
hashValue,
|
|
14436
14514
|
publicKey: PublicKey,
|
|
14437
14515
|
publicKeyEncoding: PublicKeyEncoding,
|
|
14438
|
-
validationStatus: validationStatus
|
|
14516
|
+
validationStatus: validationStatus ?? (PublicKey != null ? "Unvalidated" /* Unvalidated */ : "PublicKeyNotFound" /* PublicKeyNotFound */)
|
|
14439
14517
|
};
|
|
14440
14518
|
try {
|
|
14441
14519
|
const ECDSASignature = this.chargy.asn1.define("ECDSASignature", function() {
|
|
@@ -14457,7 +14535,8 @@ var OCMF = class {
|
|
|
14457
14535
|
default:
|
|
14458
14536
|
ocmfJSONDocument.validationStatus = "UnknownSignatureFormat" /* UnknownSignatureFormat */;
|
|
14459
14537
|
}
|
|
14460
|
-
const
|
|
14538
|
+
const decodedSignatureObj = ECDSASignature.decode(Buffer.from(ocmfJSONDocument.signature.SD, bufferEncoding), "der");
|
|
14539
|
+
const signatureObj = decodedSignatureObj;
|
|
14461
14540
|
ocmfJSONDocument.signatureRS = {
|
|
14462
14541
|
value: ocmfJSONDocument.signature.SD,
|
|
14463
14542
|
r: signatureObj.r.toString(16),
|
|
@@ -14466,7 +14545,7 @@ var OCMF = class {
|
|
|
14466
14545
|
} catch {
|
|
14467
14546
|
ocmfJSONDocument.validationStatus = "InvalidSignature" /* InvalidSignature */;
|
|
14468
14547
|
}
|
|
14469
|
-
if (PublicKey && ocmfJSONDocument.validationStatus === "Unvalidated" /* Unvalidated */)
|
|
14548
|
+
if (PublicKey != null && ocmfJSONDocument.validationStatus === "Unvalidated" /* Unvalidated */)
|
|
14470
14549
|
await this.validateOCMFSignature(
|
|
14471
14550
|
ocmfJSONDocument,
|
|
14472
14551
|
PublicKey,
|
|
@@ -14495,14 +14574,14 @@ var OCMF = class {
|
|
|
14495
14574
|
//#endregion
|
|
14496
14575
|
//#region TryToParseOCMFDocument (OCMFDocument, PublicKey?, PublicKeyEncoding?, ContainerInfos?)
|
|
14497
14576
|
async TryToParseOCMFDocument(OCMFDocument, PublicKey, PublicKeyEncoding, ContainerInfos) {
|
|
14498
|
-
return
|
|
14577
|
+
return this.TryToParseOCMFDocuments([OCMFDocument], PublicKey, PublicKeyEncoding, ContainerInfos);
|
|
14499
14578
|
}
|
|
14500
14579
|
//#endregion
|
|
14501
14580
|
//#region TryToParseOCMFDocuments(OCMFDocuments, PublicKey?, PublicKeyEncoding?, ContainerInfos?)
|
|
14502
14581
|
async TryToParseOCMFDocuments(OCMFDocuments, PublicKey, PublicKeyEncoding, ContainerInfos) {
|
|
14503
14582
|
if (OCMFDocuments.length == 0) return {
|
|
14504
14583
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
14505
|
-
message: this.chargy.GetLocalizedMessage("The given OCMF data could not be parsed") + "!",
|
|
14584
|
+
message: this.chargy.GetMultilanguageText(this.chargy.GetLocalizedMessage("The given OCMF data could not be parsed") + "!"),
|
|
14506
14585
|
certainty: 0
|
|
14507
14586
|
};
|
|
14508
14587
|
const ocmfJSONDocumentGroups = /* @__PURE__ */ new Map();
|
|
@@ -14515,20 +14594,21 @@ var OCMF = class {
|
|
|
14515
14594
|
if (typeof ocmfJSONDocuments !== "string") {
|
|
14516
14595
|
for (const ocmfJSONDocument of ocmfJSONDocuments) {
|
|
14517
14596
|
try {
|
|
14518
|
-
const groupingKey = (ocmfJSONDocument.payload.FV ?? "") + "|" + (ocmfJSONDocument.payload.GI ?? "") + "|" + (ocmfJSONDocument.payload.GS ?? "") + "|" + (ocmfJSONDocument.payload.GV ?? "") + "|" + (ocmfJSONDocument.payload.MV ?? "") + "|" + (ocmfJSONDocument.payload.MM ?? "") + "|" + (ocmfJSONDocument.payload.MS ?? "") + "|" + (ocmfJSONDocument.payload.MF ?? "") + "|" + (ocmfJSONDocument.payload.IS ? "1|" : "0|") + (ocmfJSONDocument.payload.IL ?? "") + "|" + (ocmfJSONDocument.payload.IF ?? "") + "|" +
|
|
14597
|
+
const groupingKey = (ocmfJSONDocument.payload.FV ?? "") + "|" + (ocmfJSONDocument.payload.GI ?? "") + "|" + (ocmfJSONDocument.payload.GS ?? "") + "|" + (ocmfJSONDocument.payload.GV ?? "") + "|" + (ocmfJSONDocument.payload.MV ?? "") + "|" + (ocmfJSONDocument.payload.MM ?? "") + "|" + (ocmfJSONDocument.payload.MS ?? "") + "|" + (ocmfJSONDocument.payload.MF ?? "") + "|" + (ocmfJSONDocument.payload.IS === true ? "1|" : "0|") + (ocmfJSONDocument.payload.IL ?? "") + "|" + //(ocmfJSONDocument.payload.IF ?? "") + "|" +
|
|
14598
|
+
(ocmfJSONDocument.payload.IT ?? "") + "|" + (ocmfJSONDocument.payload.ID ?? "") + "|" + (ocmfJSONDocument.payload.TT ?? "") + "|" + (ocmfJSONDocument.payload.CF ?? "") + "|" + (ocmfJSONDocument.payload.CT ?? "") + "|" + (ocmfJSONDocument.payload.CI ?? "");
|
|
14519
14599
|
if (!ocmfJSONDocumentGroups.has(groupingKey))
|
|
14520
14600
|
ocmfJSONDocumentGroups.set(groupingKey, new Array());
|
|
14521
14601
|
ocmfJSONDocumentGroups.get(groupingKey)?.push(ocmfJSONDocument);
|
|
14522
14602
|
} catch (exception) {
|
|
14523
14603
|
return {
|
|
14524
14604
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
14525
|
-
message: this.chargy.GetLocalizedMessage("The given OCMF data could not be parsed") + ": " + (exception instanceof Error ? exception.message : String(exception)),
|
|
14605
|
+
message: this.chargy.GetMultilanguageText(this.chargy.GetLocalizedMessage("The given OCMF data could not be parsed") + ": " + (exception instanceof Error ? exception.message : String(exception))),
|
|
14526
14606
|
certainty: 0
|
|
14527
14607
|
};
|
|
14528
14608
|
}
|
|
14529
14609
|
}
|
|
14530
14610
|
for (const ocmfJSONDocumentGroup of ocmfJSONDocumentGroups.values()) {
|
|
14531
|
-
if (PublicKey) {
|
|
14611
|
+
if (PublicKey != null) {
|
|
14532
14612
|
for (const ocmfJSONDocument of ocmfJSONDocumentGroup)
|
|
14533
14613
|
if (ocmfJSONDocument.validationStatus === "Unvalidated" /* Unvalidated */)
|
|
14534
14614
|
await this.validateOCMFSignature(ocmfJSONDocument, PublicKey);
|
|
@@ -14550,7 +14630,7 @@ var OCMF = class {
|
|
|
14550
14630
|
default:
|
|
14551
14631
|
ocmfCTRs.push({
|
|
14552
14632
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
14553
|
-
message: this.chargy.
|
|
14633
|
+
message: this.chargy.GetMultilanguageText("Unknown OCMF version!"),
|
|
14554
14634
|
certainty: 0
|
|
14555
14635
|
});
|
|
14556
14636
|
break;
|
|
@@ -14562,7 +14642,7 @@ var OCMF = class {
|
|
|
14562
14642
|
}
|
|
14563
14643
|
return {
|
|
14564
14644
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
14565
|
-
message: this.chargy.GetLocalizedMessage("The given OCMF data could not be parsed") + (typeof ocmfJSONDocuments === "string" ? ": " + ocmfJSONDocuments : "!"),
|
|
14645
|
+
message: this.chargy.GetMultilanguageText(this.chargy.GetLocalizedMessage("The given OCMF data could not be parsed") + (typeof ocmfJSONDocuments === "string" ? ": " + ocmfJSONDocuments : "!")),
|
|
14566
14646
|
certainty: 0
|
|
14567
14647
|
};
|
|
14568
14648
|
}
|
|
@@ -14580,12 +14660,6 @@ var OCPI = class {
|
|
|
14580
14660
|
constructor(chargy) {
|
|
14581
14661
|
this.chargy = chargy;
|
|
14582
14662
|
}
|
|
14583
|
-
bufferToHex(buffer, Reverse) {
|
|
14584
|
-
return (Reverse ? Array.from(new Uint8Array(buffer)).reverse() : Array.from(new Uint8Array(buffer))).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
14585
|
-
}
|
|
14586
|
-
bufferToNumber(buffer) {
|
|
14587
|
-
return parseInt(Array.from(new Uint8Array(buffer)).map((b) => b.toString(16).padStart(2, "0")).join(""), 16);
|
|
14588
|
-
}
|
|
14589
14663
|
//#region tryToParseChargeITContainerFormat(SomeJSON)
|
|
14590
14664
|
// The chargeIT mobility data format does not always provide context information or format identifiers!
|
|
14591
14665
|
async tryToParseOCPIFormat(SomeJSON) {
|
|
@@ -14605,11 +14679,11 @@ var OCPI = class {
|
|
|
14605
14679
|
const public_key = SomeJSON["public_key"];
|
|
14606
14680
|
const signed_values = SomeJSON["signed_values"];
|
|
14607
14681
|
if (!isMandatoryString(encoding_method))
|
|
14608
|
-
errors.push(this.chargy.
|
|
14682
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidEncodingMethod")));
|
|
14609
14683
|
if (!isMandatoryString(public_key))
|
|
14610
|
-
errors.push(this.chargy.
|
|
14684
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidPublicKey")));
|
|
14611
14685
|
if (!isMandatoryJSONArray(signed_values))
|
|
14612
|
-
errors.push(this.chargy.
|
|
14686
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidSignedValues")));
|
|
14613
14687
|
if (errors.length > 0)
|
|
14614
14688
|
return {
|
|
14615
14689
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
@@ -14619,7 +14693,7 @@ var OCPI = class {
|
|
|
14619
14693
|
};
|
|
14620
14694
|
if (encoding_method === "OCMF" && isMandatoryJSONArray(signed_values) && signed_values.length > 0) {
|
|
14621
14695
|
const firstSignedData = asString(asJSONObject(signed_values[0])?.["signed_data"]);
|
|
14622
|
-
if (firstSignedData) {
|
|
14696
|
+
if (firstSignedData != null && firstSignedData.length > 0) {
|
|
14623
14697
|
const placeInfo = asJSONObject(SomeJSON["placeInfo"]);
|
|
14624
14698
|
const geoLocation = asJSONObject(placeInfo?.["geoLocation"]);
|
|
14625
14699
|
const address = asJSONObject(placeInfo?.["address"]);
|
|
@@ -14638,7 +14712,7 @@ var OCPI = class {
|
|
|
14638
14712
|
},
|
|
14639
14713
|
energyMeter: asJSONObject(SomeJSON["meterInfo"])
|
|
14640
14714
|
};
|
|
14641
|
-
return
|
|
14715
|
+
return new OCMF(this.chargy).TryToParseOCMFDocument(
|
|
14642
14716
|
firstSignedData,
|
|
14643
14717
|
asString(public_key),
|
|
14644
14718
|
encoding_method,
|
|
@@ -14711,138 +14785,138 @@ var OCPI = class {
|
|
|
14711
14785
|
const chargingCostsInfo_flat_cost = chargingCostsInfo_flat?.["cost"];
|
|
14712
14786
|
const signedMeterValues = SomeJSON["signedMeterValues"];
|
|
14713
14787
|
if (!isMandatoryString(chargingSessionId))
|
|
14714
|
-
errors.push(this.chargy.
|
|
14788
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid charge transparency record identification!")));
|
|
14715
14789
|
if (!isMandatoryJSONObject(chargePointInfo)) {
|
|
14716
|
-
errors.push(this.chargy.
|
|
14790
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidChargePointInfo")));
|
|
14717
14791
|
secondaryErrors += 19;
|
|
14718
14792
|
} else {
|
|
14719
14793
|
if (!isMandatoryString(evseId))
|
|
14720
|
-
errors.push(this.chargy.
|
|
14794
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidEVSEIdentification")));
|
|
14721
14795
|
if (!isMandatoryJSONObject(placeInfo)) {
|
|
14722
|
-
errors.push(this.chargy.
|
|
14796
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidPlaceInfo")));
|
|
14723
14797
|
secondaryErrors += 8;
|
|
14724
14798
|
} else {
|
|
14725
14799
|
if (!isMandatoryJSONObject(geoLocation)) {
|
|
14726
|
-
errors.push(this.chargy.
|
|
14800
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidGeoLocation")));
|
|
14727
14801
|
secondaryErrors += 2;
|
|
14728
14802
|
} else {
|
|
14729
14803
|
if (!isMandatoryNumber(geoLocation_lat))
|
|
14730
|
-
errors.push(this.chargy.
|
|
14804
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidGeoLocationLatitude")));
|
|
14731
14805
|
if (!isMandatoryNumber(geoLocation_lon))
|
|
14732
|
-
errors.push(this.chargy.
|
|
14806
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidGeoLocationLongitude")));
|
|
14733
14807
|
}
|
|
14734
14808
|
if (!isMandatoryJSONObject(address)) {
|
|
14735
|
-
errors.push(this.chargy.
|
|
14809
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidAddress")));
|
|
14736
14810
|
secondaryErrors += 4;
|
|
14737
14811
|
} else {
|
|
14738
14812
|
if (!isMandatoryString(address_street))
|
|
14739
|
-
errors.push(this.chargy.
|
|
14813
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidAddressStreetName")));
|
|
14740
14814
|
if (!isMandatoryString(address_zipCode))
|
|
14741
|
-
errors.push(this.chargy.
|
|
14815
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidAddressZIPCode")));
|
|
14742
14816
|
if (!isMandatoryString(address_town))
|
|
14743
|
-
errors.push(this.chargy.
|
|
14817
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidAddressCityName")));
|
|
14744
14818
|
if (!isMandatoryString(address_country))
|
|
14745
|
-
errors.push(this.chargy.
|
|
14819
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidAddressCountryName")));
|
|
14746
14820
|
}
|
|
14747
14821
|
}
|
|
14748
14822
|
}
|
|
14749
14823
|
if (!isMandatoryJSONObject(chargingStationInfo)) {
|
|
14750
|
-
errors.push(this.chargy.
|
|
14824
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidChargingStationInfo")));
|
|
14751
14825
|
secondaryErrors += 5;
|
|
14752
14826
|
} else {
|
|
14753
14827
|
if (!isOptionalString(chargingStation_manufacturer))
|
|
14754
|
-
errors.push(this.chargy.
|
|
14828
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station manufacturer!")));
|
|
14755
14829
|
if (!isOptionalString(chargingStation_type))
|
|
14756
|
-
errors.push(this.chargy.
|
|
14830
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station type!")));
|
|
14757
14831
|
if (!isOptionalString(chargingStation_serialNumber))
|
|
14758
|
-
errors.push(this.chargy.
|
|
14832
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station serial number!")));
|
|
14759
14833
|
if (!isOptionalString(chargingStation_controllerSoftwareVersion))
|
|
14760
|
-
errors.push(this.chargy.
|
|
14834
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station controller software version!")));
|
|
14761
14835
|
if (!isOptionalString(chargingStation_compliance))
|
|
14762
|
-
errors.push(this.chargy.
|
|
14836
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station compliance!")));
|
|
14763
14837
|
if (!isOptionalURL(chargingStation_complianceURL))
|
|
14764
|
-
errors.push(this.chargy.
|
|
14838
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station compliance URL!")));
|
|
14765
14839
|
if (!isOptionalString(chargingStation_conformity))
|
|
14766
|
-
errors.push(this.chargy.
|
|
14840
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station conformity!")));
|
|
14767
14841
|
if (!isOptionalURL(chargingStation_conformity_URL))
|
|
14768
|
-
errors.push(this.chargy.
|
|
14842
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station conformity URL!")));
|
|
14769
14843
|
if (!isOptionalURL(chargingStation_conformity_certificateId))
|
|
14770
|
-
errors.push(this.chargy.
|
|
14844
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station conformity certificate identification!")));
|
|
14771
14845
|
if (!isOptionalString(chargingStation_calibration))
|
|
14772
|
-
errors.push(this.chargy.
|
|
14846
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station calibration!")));
|
|
14773
14847
|
if (!isOptionalURL(chargingStation_calibration_URL))
|
|
14774
|
-
errors.push(this.chargy.
|
|
14848
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station calibration URL!")));
|
|
14775
14849
|
if (!isOptionalURL(chargingStation_calibration_certificateId))
|
|
14776
|
-
errors.push(this.chargy.
|
|
14850
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station calibration certificate identification!")));
|
|
14777
14851
|
}
|
|
14778
14852
|
if (meterInfo) {
|
|
14779
14853
|
if (!isOptionalString(meterInfo_meterId))
|
|
14780
|
-
errors.push(this.chargy.
|
|
14854
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_MeterIdP", 1)));
|
|
14781
14855
|
if (!isOptionalString(meterInfo_manufacturer))
|
|
14782
|
-
errors.push(this.chargy.
|
|
14856
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_ManufacturerP", 1)));
|
|
14783
14857
|
if (!isOptionalString(meterInfo_manufacturerURL))
|
|
14784
|
-
errors.push(this.chargy.
|
|
14858
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_ManufacturerP", 1)));
|
|
14785
14859
|
if (!isOptionalString(meterInfo_model))
|
|
14786
|
-
errors.push(this.chargy.
|
|
14860
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_ManufacturerP", 1)));
|
|
14787
14861
|
if (!isOptionalString(meterInfo_modelURL))
|
|
14788
|
-
errors.push(this.chargy.
|
|
14862
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_ManufacturerP", 1)));
|
|
14789
14863
|
if (!isOptionalString(meterInfo_firmwareVersion))
|
|
14790
|
-
errors.push(this.chargy.
|
|
14864
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_FirmwareVersionP", 1)));
|
|
14791
14865
|
if (!isOptionalString(meterInfo_hardwareVersion))
|
|
14792
|
-
errors.push(this.chargy.
|
|
14866
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_FirmwareVersionP", 1)));
|
|
14793
14867
|
if (!isOptionalString(meterInfo_publicKey))
|
|
14794
|
-
errors.push(this.chargy.
|
|
14868
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_PublicKeyP", 1)));
|
|
14795
14869
|
if (!isOptionalString(meterInfo_publicKeyFormat))
|
|
14796
|
-
errors.push(this.chargy.
|
|
14870
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_PublicKeyP", 1)));
|
|
14797
14871
|
if (!isOptionalString(meterInfo_publicKeyEncoding))
|
|
14798
|
-
errors.push(this.chargy.
|
|
14872
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_PublicKeyP", 1)));
|
|
14799
14873
|
if (!isOptionalString(meterInfo_signatureFormat))
|
|
14800
|
-
errors.push(this.chargy.
|
|
14874
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_PublicKeyP", 1)));
|
|
14801
14875
|
if (!isOptionalString(meterInfo_signatureEncoding))
|
|
14802
|
-
errors.push(this.chargy.
|
|
14876
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_PublicKeyP", 1)));
|
|
14803
14877
|
}
|
|
14804
14878
|
if (connectorInfo) {
|
|
14805
14879
|
if (!isOptionalString(connectorInfo_type))
|
|
14806
|
-
errors.push(this.chargy.
|
|
14880
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_MeterIdP", 1)));
|
|
14807
14881
|
if (!isOptionalString(connectorInfo_losses))
|
|
14808
|
-
errors.push(this.chargy.
|
|
14882
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_MeterIdP", 1)));
|
|
14809
14883
|
}
|
|
14810
14884
|
if (chargingCostsInfo) {
|
|
14811
14885
|
if (!isMandatoryNumber(chargingCostsInfo_total))
|
|
14812
|
-
errors.push(this.chargy.
|
|
14886
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid total costs within the charging costs!")));
|
|
14813
14887
|
if (!isMandatoryString(chargingCostsInfo_currency))
|
|
14814
|
-
errors.push(this.chargy.
|
|
14888
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid currency within the charging costs!")));
|
|
14815
14889
|
if (chargingCostsInfo_reservation) {
|
|
14816
14890
|
if (!isMandatoryNumber(chargingCostsInfo_reservation_cost))
|
|
14817
|
-
errors.push(this.chargy.
|
|
14891
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid reservation cost within the charging costs!")));
|
|
14818
14892
|
if (!isMandatoryString(chargingCostsInfo_reservation_unit))
|
|
14819
|
-
errors.push(this.chargy.
|
|
14893
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid reservation unit within the charging costs!")));
|
|
14820
14894
|
}
|
|
14821
14895
|
if (chargingCostsInfo_energy) {
|
|
14822
14896
|
if (!isMandatoryNumber(chargingCostsInfo_energy_cost))
|
|
14823
|
-
errors.push(this.chargy.
|
|
14897
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid energy cost within the charging costs!")));
|
|
14824
14898
|
if (!isMandatoryString(chargingCostsInfo_energy_unit))
|
|
14825
|
-
errors.push(this.chargy.
|
|
14899
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid energy unit within the charging costs!")));
|
|
14826
14900
|
}
|
|
14827
14901
|
if (chargingCostsInfo_time) {
|
|
14828
14902
|
if (!isMandatoryNumber(chargingCostsInfo_time_cost))
|
|
14829
|
-
errors.push(this.chargy.
|
|
14903
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid time cost within the charging costs!")));
|
|
14830
14904
|
if (!isMandatoryString(chargingCostsInfo_time_unit))
|
|
14831
|
-
errors.push(this.chargy.
|
|
14905
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid time unit within the charging costs!")));
|
|
14832
14906
|
}
|
|
14833
14907
|
if (chargingCostsInfo_idle) {
|
|
14834
14908
|
if (!isMandatoryNumber(chargingCostsInfo_idle_cost))
|
|
14835
|
-
errors.push(this.chargy.
|
|
14909
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid idle cost within the charging costs!")));
|
|
14836
14910
|
if (!isMandatoryString(chargingCostsInfo_idle_unit))
|
|
14837
|
-
errors.push(this.chargy.
|
|
14911
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid idle unit within the charging costs!")));
|
|
14838
14912
|
}
|
|
14839
14913
|
if (chargingCostsInfo_flat) {
|
|
14840
14914
|
if (!isMandatoryNumber(chargingCostsInfo_flat_cost))
|
|
14841
|
-
errors.push(this.chargy.
|
|
14915
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid flat cost within the charging costs!")));
|
|
14842
14916
|
}
|
|
14843
14917
|
}
|
|
14844
14918
|
if (!isMandatoryJSONArray(signedMeterValues) || signedMeterValues.length < 2) {
|
|
14845
|
-
errors.push(this.chargy.
|
|
14919
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidSignedMeterValues")));
|
|
14846
14920
|
secondaryErrors += 2 * 39;
|
|
14847
14921
|
} else {
|
|
14848
14922
|
const firstSMV = asJSONObject(signedMeterValues[0]);
|
|
@@ -14852,7 +14926,7 @@ var OCPI = class {
|
|
|
14852
14926
|
const context = asString(currentSMV?.["@context"])?.trim() ?? asString(currentSMV?.["format"])?.trim() ?? null;
|
|
14853
14927
|
if (smvContext !== context) return {
|
|
14854
14928
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
14855
|
-
message: "Inconsistent signed meter value format!",
|
|
14929
|
+
message: this.chargy.GetMultilanguageText("Inconsistent signed meter value format!"),
|
|
14856
14930
|
certainty: 1
|
|
14857
14931
|
};
|
|
14858
14932
|
}
|
|
@@ -14956,9 +15030,9 @@ var OCPI = class {
|
|
|
14956
15030
|
],
|
|
14957
15031
|
certainty: 0
|
|
14958
15032
|
};
|
|
14959
|
-
if (smvContext?.startsWith("https://www.chargeit-mobility.com/contexts/bsm-ws36a-json"))
|
|
15033
|
+
if (smvContext?.startsWith("https://www.chargeit-mobility.com/contexts/bsm-ws36a-json") === true)
|
|
14960
15034
|
return new BSMCrypt01(this.chargy).tryToParseBSM_WS36aMeasurements(CTR, evseIdStr, asString(chargingStation_controllerSoftwareVersion) ?? null, signedMeterValues);
|
|
14961
|
-
if (smvContext?.startsWith("ALFEN"))
|
|
15035
|
+
if (smvContext?.startsWith("ALFEN") === true)
|
|
14962
15036
|
return new Alfen(this.chargy).TryToParseALFENFormat(
|
|
14963
15037
|
signedMeterValues.map((value) => asString(asJSONObject(value)?.["payload"]) ?? ""),
|
|
14964
15038
|
{
|
|
@@ -14997,7 +15071,7 @@ var OCPI = class {
|
|
|
14997
15071
|
} catch (exception) {
|
|
14998
15072
|
return {
|
|
14999
15073
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
15000
|
-
message: "Exception occured: " + (exception instanceof Error ? exception.message : String(exception)),
|
|
15074
|
+
message: this.chargy.GetMultilanguageText("Exception occured: " + (exception instanceof Error ? exception.message : String(exception))),
|
|
15001
15075
|
errors,
|
|
15002
15076
|
warnings,
|
|
15003
15077
|
certainty: (numberOfFormatChecks - errors.length - secondaryErrors) / numberOfFormatChecks
|
|
@@ -15006,7 +15080,7 @@ var OCPI = class {
|
|
|
15006
15080
|
}
|
|
15007
15081
|
return {
|
|
15008
15082
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
15009
|
-
message: "No chargeIT charge transparency record",
|
|
15083
|
+
message: this.chargy.GetMultilanguageText("No chargeIT charge transparency record"),
|
|
15010
15084
|
errors,
|
|
15011
15085
|
warnings,
|
|
15012
15086
|
certainty: 0
|
|
@@ -15105,9 +15179,9 @@ function parsePCDFDocument(input) {
|
|
|
15105
15179
|
}
|
|
15106
15180
|
const fields = {};
|
|
15107
15181
|
for (let i = 0; i < PCDF_FIELD_ORDER.length; i++) {
|
|
15108
|
-
const value = match
|
|
15109
|
-
const field = PCDF_FIELD_ORDER
|
|
15110
|
-
if (
|
|
15182
|
+
const value = getArrayElement(match, i + 1, "Missing PCDF field value");
|
|
15183
|
+
const field = getArrayElement(PCDF_FIELD_ORDER, i, "Missing PCDF field name");
|
|
15184
|
+
if (value.length === 0)
|
|
15111
15185
|
throw new PCDFParseError("MISSING_FIELDS", "Missing fields in the data tuple", field);
|
|
15112
15186
|
fields[field] = value;
|
|
15113
15187
|
}
|
|
@@ -15292,7 +15366,7 @@ var PCDF = class {
|
|
|
15292
15366
|
if (externalPublicKey != null && normalizePCDFPublicKeyHex(externalPublicKey) !== publicKey) {
|
|
15293
15367
|
return {
|
|
15294
15368
|
status: "InvalidPublicKey" /* InvalidPublicKey */,
|
|
15295
|
-
message: "Wrong Public Key",
|
|
15369
|
+
message: this.chargy.GetMultilanguageText("Wrong Public Key"),
|
|
15296
15370
|
certainty: 1
|
|
15297
15371
|
};
|
|
15298
15372
|
}
|
|
@@ -15313,7 +15387,7 @@ var PCDF = class {
|
|
|
15313
15387
|
} catch (exception) {
|
|
15314
15388
|
return {
|
|
15315
15389
|
status: exception instanceof PCDFParseError ? "InvalidSessionFormat" /* InvalidSessionFormat */ : "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
15316
|
-
message: exception instanceof Error ? exception.message : String(exception),
|
|
15390
|
+
message: this.chargy.GetMultilanguageText(exception instanceof Error ? exception.message : String(exception)),
|
|
15317
15391
|
certainty: 0
|
|
15318
15392
|
};
|
|
15319
15393
|
}
|
|
@@ -15479,8 +15553,10 @@ function parsePCDFReadingValue(value, errors) {
|
|
|
15479
15553
|
errors.push("Session information is invalid");
|
|
15480
15554
|
return void 0;
|
|
15481
15555
|
}
|
|
15556
|
+
const integralPart = getArrayElement(match, 1, "Missing PCDF reading integral part");
|
|
15557
|
+
const fractionalPart = getArrayElement(match, 2, "Missing PCDF reading fractional part");
|
|
15482
15558
|
return {
|
|
15483
|
-
value: new Decimal(
|
|
15559
|
+
value: new Decimal(integralPart + "." + fractionalPart),
|
|
15484
15560
|
unit: "kWh"
|
|
15485
15561
|
};
|
|
15486
15562
|
}
|
|
@@ -15515,9 +15591,9 @@ function hexToBytes2(hex, errorMessage) {
|
|
|
15515
15591
|
}
|
|
15516
15592
|
function readDERLength(bytes, getOffset, setOffset) {
|
|
15517
15593
|
let offset = getOffset();
|
|
15518
|
-
|
|
15519
|
-
if (b == null)
|
|
15594
|
+
if (offset >= bytes.length)
|
|
15520
15595
|
throw new Error("Invalid signature");
|
|
15596
|
+
const b = getArrayElement(bytes, offset++, "Invalid signature");
|
|
15521
15597
|
if ((b & 128) === 0) {
|
|
15522
15598
|
setOffset(offset);
|
|
15523
15599
|
return b;
|
|
@@ -15527,9 +15603,9 @@ function readDERLength(bytes, getOffset, setOffset) {
|
|
|
15527
15603
|
throw new Error("Invalid signature");
|
|
15528
15604
|
let length = 0;
|
|
15529
15605
|
for (let i = 0; i < octets; i++) {
|
|
15530
|
-
|
|
15531
|
-
if (value == null)
|
|
15606
|
+
if (offset >= bytes.length)
|
|
15532
15607
|
throw new Error("Invalid signature");
|
|
15608
|
+
const value = getArrayElement(bytes, offset++, "Invalid signature");
|
|
15533
15609
|
length = (length << 8) + value;
|
|
15534
15610
|
}
|
|
15535
15611
|
setOffset(offset);
|
|
@@ -15558,30 +15634,33 @@ var SAFEXML = class _SAFEXML {
|
|
|
15558
15634
|
this.chargy = chargy;
|
|
15559
15635
|
}
|
|
15560
15636
|
static ParseChargingStationContext(XMLDocument) {
|
|
15561
|
-
const chargingStationElement = getElementsByLocalName(XMLDocument, "chargingStation")
|
|
15562
|
-
if (
|
|
15637
|
+
const chargingStationElement = getElementsByLocalName(XMLDocument, "chargingStation").at(0);
|
|
15638
|
+
if (chargingStationElement === void 0)
|
|
15563
15639
|
return {};
|
|
15564
|
-
const
|
|
15640
|
+
const chargingStationAttributeId = chargingStationElement.getAttribute("id")?.trim();
|
|
15641
|
+
const chargingStationId = chargingStationAttributeId != null && chargingStationAttributeId.length > 0 ? chargingStationAttributeId : getTrimmedTextContent(getDirectChildByLocalName(chargingStationElement, "id"));
|
|
15565
15642
|
const softwareVersion = getTrimmedTextContent(getDirectChildByLocalName(chargingStationElement, "softwareVersion"));
|
|
15566
15643
|
const geoLocationElement = getDirectChildByLocalName(chargingStationElement, "geoLocation");
|
|
15567
15644
|
const latitude = Number.parseFloat(getTrimmedTextContent(getDirectChildByLocalName(geoLocationElement ?? chargingStationElement, "latitude")) ?? "");
|
|
15568
15645
|
const longitude = Number.parseFloat(getTrimmedTextContent(getDirectChildByLocalName(geoLocationElement ?? chargingStationElement, "longitude")) ?? "");
|
|
15569
15646
|
const geoLocation = Number.isFinite(latitude) && Number.isFinite(longitude) ? { lat: latitude, lng: longitude } : void 0;
|
|
15570
|
-
if (getDirectChildByLocalName(chargingStationElement, "EVSEs"))
|
|
15647
|
+
if (getDirectChildByLocalName(chargingStationElement, "EVSEs") !== void 0)
|
|
15571
15648
|
throw new Error("The SAFE chargingStation XML element must contain EVSE directly and no EVSEs container element!");
|
|
15572
15649
|
const evseElements = getDirectChildrenByLocalName(chargingStationElement, "EVSE");
|
|
15573
15650
|
if (evseElements.length > 1)
|
|
15574
15651
|
throw new Error("The SAFE chargingStation XML element must not contain more than one EVSE element!");
|
|
15575
|
-
const evseElement = evseElements
|
|
15576
|
-
const
|
|
15577
|
-
const
|
|
15652
|
+
const evseElement = evseElements.at(0);
|
|
15653
|
+
const evseAttributeId = evseElement?.getAttribute("id")?.trim();
|
|
15654
|
+
const evseTextId = getTrimmedTextContent(getDirectChildByLocalName(evseElement ?? chargingStationElement, "id"));
|
|
15655
|
+
const evseId = evseAttributeId != null && evseAttributeId.length > 0 ? evseAttributeId : evseTextId ?? "";
|
|
15656
|
+
const connectorElements = evseElement !== void 0 ? getDirectChildrenByLocalName(evseElement, "connector") : [];
|
|
15578
15657
|
if (connectorElements.length > 1)
|
|
15579
15658
|
throw new Error("The SAFE EVSE XML element must not contain more than one connector element!");
|
|
15580
|
-
const connectorElement = connectorElements
|
|
15659
|
+
const connectorElement = connectorElements.at(0);
|
|
15581
15660
|
const connectorId = connectorElement?.getAttribute("id")?.trim();
|
|
15582
15661
|
const connectorType = getTrimmedTextContent(getDirectChildByLocalName(connectorElement ?? evseElement ?? chargingStationElement, "type"));
|
|
15583
|
-
const connector = connectorType ? { "@id": connectorId, type: connectorType, looses: 0 } : void 0;
|
|
15584
|
-
const parsedEVSE = evseElement ? {
|
|
15662
|
+
const connector = connectorType != null && connectorType.length > 0 ? { "@id": connectorId, type: connectorType, looses: 0 } : void 0;
|
|
15663
|
+
const parsedEVSE = evseElement !== void 0 ? {
|
|
15585
15664
|
"@id": evseId,
|
|
15586
15665
|
"description": parseDescription(evseElement),
|
|
15587
15666
|
"meters": [],
|
|
@@ -15619,7 +15698,7 @@ var SAFEXML = class _SAFEXML {
|
|
|
15619
15698
|
if (signedData == null)
|
|
15620
15699
|
return {
|
|
15621
15700
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
15622
|
-
message: "Each value within the given XML container must contain signed data!",
|
|
15701
|
+
message: this.chargy.GetMultilanguageText("Each value within the given XML container must contain signed data!"),
|
|
15623
15702
|
certainty: 0
|
|
15624
15703
|
};
|
|
15625
15704
|
const signedDataFormat = signedData.attributes.getNamedItem("format")?.value.trim().toLowerCase() ?? "";
|
|
@@ -15628,7 +15707,7 @@ var SAFEXML = class _SAFEXML {
|
|
|
15628
15707
|
else if (signedDataFormat !== commonSignedDataFormat)
|
|
15629
15708
|
return {
|
|
15630
15709
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
15631
|
-
message: "Invalid mixture of different signed data formats within the given XML container!",
|
|
15710
|
+
message: this.chargy.GetMultilanguageText("Invalid mixture of different signed data formats within the given XML container!"),
|
|
15632
15711
|
certainty: 0
|
|
15633
15712
|
};
|
|
15634
15713
|
const signedDataEncoding = signedData.attributes.getNamedItem("encoding")?.value.trim().toLowerCase() ?? "";
|
|
@@ -15637,14 +15716,14 @@ var SAFEXML = class _SAFEXML {
|
|
|
15637
15716
|
else if (signedDataEncoding !== commonSignedDataEncoding)
|
|
15638
15717
|
return {
|
|
15639
15718
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
15640
|
-
message: "Invalid mixture of different signed data encodings within the given XML container!",
|
|
15719
|
+
message: this.chargy.GetMultilanguageText("Invalid mixture of different signed data encodings within the given XML container!"),
|
|
15641
15720
|
certainty: 0
|
|
15642
15721
|
};
|
|
15643
15722
|
const signedDataValue = signedData.textContent.trim();
|
|
15644
15723
|
if (IsNullOrEmpty(signedDataValue))
|
|
15645
15724
|
return {
|
|
15646
15725
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
15647
|
-
message: "The signed data value within the given XML container must not be empty!",
|
|
15726
|
+
message: this.chargy.GetMultilanguageText("The signed data value within the given XML container must not be empty!"),
|
|
15648
15727
|
certainty: 0
|
|
15649
15728
|
};
|
|
15650
15729
|
const publicKeyEncoding = publicKey?.attributes.getNamedItem("encoding")?.value.trim().toLowerCase() ?? "";
|
|
@@ -15653,7 +15732,7 @@ var SAFEXML = class _SAFEXML {
|
|
|
15653
15732
|
else if (publicKeyEncoding !== commonPublicKeyEncoding)
|
|
15654
15733
|
return {
|
|
15655
15734
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
15656
|
-
message: "Invalid mixture of different public key encodings within the given XML container!",
|
|
15735
|
+
message: this.chargy.GetMultilanguageText("Invalid mixture of different public key encodings within the given XML container!"),
|
|
15657
15736
|
certainty: 0
|
|
15658
15737
|
};
|
|
15659
15738
|
const publicKeyValue = publicKey?.textContent.trim().replace(/\s+/g, "") ?? "";
|
|
@@ -15662,7 +15741,7 @@ var SAFEXML = class _SAFEXML {
|
|
|
15662
15741
|
else if (publicKeyValue !== commonPublicKey)
|
|
15663
15742
|
return {
|
|
15664
15743
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
15665
|
-
message: "Invalid mixture of different public keys within the given XML container!",
|
|
15744
|
+
message: this.chargy.GetMultilanguageText("Invalid mixture of different public keys within the given XML container!"),
|
|
15666
15745
|
certainty: 0
|
|
15667
15746
|
};
|
|
15668
15747
|
switch (commonSignedDataEncoding) {
|
|
@@ -15682,7 +15761,7 @@ var SAFEXML = class _SAFEXML {
|
|
|
15682
15761
|
default:
|
|
15683
15762
|
return {
|
|
15684
15763
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
15685
|
-
message: "Unkown signed data encoding within the given SAFE XML!",
|
|
15764
|
+
message: this.chargy.GetMultilanguageText("Unkown signed data encoding within the given SAFE XML!"),
|
|
15686
15765
|
certainty: 0
|
|
15687
15766
|
};
|
|
15688
15767
|
}
|
|
@@ -15704,7 +15783,7 @@ var SAFEXML = class _SAFEXML {
|
|
|
15704
15783
|
default:
|
|
15705
15784
|
return {
|
|
15706
15785
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
15707
|
-
message: this.chargy.
|
|
15786
|
+
message: this.chargy.GetMultilanguageText("UnknownOrInvalidChargingSessionFormat"),
|
|
15708
15787
|
certainty: 0
|
|
15709
15788
|
};
|
|
15710
15789
|
}
|
|
@@ -15713,13 +15792,13 @@ var SAFEXML = class _SAFEXML {
|
|
|
15713
15792
|
} catch (exception) {
|
|
15714
15793
|
return {
|
|
15715
15794
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
15716
|
-
message: "Exception occured: " + (exception instanceof Error ? exception.message : String(exception)),
|
|
15795
|
+
message: this.chargy.GetMultilanguageText("Exception occured: " + (exception instanceof Error ? exception.message : String(exception))),
|
|
15717
15796
|
certainty: 0
|
|
15718
15797
|
};
|
|
15719
15798
|
}
|
|
15720
15799
|
return {
|
|
15721
15800
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
15722
|
-
message: this.chargy.
|
|
15801
|
+
message: this.chargy.GetMultilanguageText("UnknownOrInvalidChargingSessionFormat"),
|
|
15723
15802
|
certainty: 0
|
|
15724
15803
|
};
|
|
15725
15804
|
}
|
|
@@ -15746,8 +15825,8 @@ var XMLContainer = class {
|
|
|
15746
15825
|
if (values.length == 1) {
|
|
15747
15826
|
const valueList = values[0]?.querySelectorAll("signedMeterValue");
|
|
15748
15827
|
if (valueList != null && valueList.length >= 1) {
|
|
15749
|
-
for (
|
|
15750
|
-
const publicKey =
|
|
15828
|
+
for (const valueElement of valueList) {
|
|
15829
|
+
const publicKey = valueElement.querySelector("publicKey");
|
|
15751
15830
|
if (publicKey != null) {
|
|
15752
15831
|
const publicKeyEncoding = publicKey.attributes.getNamedItem("encoding")?.value.trim().toLowerCase() ?? "";
|
|
15753
15832
|
let publicKeyValue = publicKey.textContent.trim();
|
|
@@ -15768,14 +15847,14 @@ var XMLContainer = class {
|
|
|
15768
15847
|
default:
|
|
15769
15848
|
return {
|
|
15770
15849
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
15771
|
-
message: "Unkown public key encoding within the given XML container!",
|
|
15850
|
+
message: this.chargy.GetMultilanguageText("Unkown public key encoding within the given XML container!"),
|
|
15772
15851
|
certainty: 0
|
|
15773
15852
|
};
|
|
15774
15853
|
}
|
|
15775
15854
|
if (IsNullOrEmpty(publicKeyValue))
|
|
15776
15855
|
return {
|
|
15777
15856
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
15778
|
-
message: "The public key within the given XML container must not be empty!",
|
|
15857
|
+
message: this.chargy.GetMultilanguageText("The public key within the given XML container must not be empty!"),
|
|
15779
15858
|
certainty: 0
|
|
15780
15859
|
};
|
|
15781
15860
|
else if (common.publicKey == "")
|
|
@@ -15783,11 +15862,11 @@ var XMLContainer = class {
|
|
|
15783
15862
|
else if (publicKeyValue != common.publicKey)
|
|
15784
15863
|
return {
|
|
15785
15864
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
15786
|
-
message: "Invalid mixture of different public keys within the given XML container!",
|
|
15865
|
+
message: this.chargy.GetMultilanguageText("Invalid mixture of different public keys within the given XML container!"),
|
|
15787
15866
|
certainty: 0
|
|
15788
15867
|
};
|
|
15789
15868
|
}
|
|
15790
|
-
const meterValueSignature =
|
|
15869
|
+
const meterValueSignature = valueElement.querySelector("meterValueSignature");
|
|
15791
15870
|
if (meterValueSignature != null) {
|
|
15792
15871
|
const meterValueSignatureEncoding = meterValueSignature.attributes.getNamedItem("encoding")?.value.trim().toLowerCase() ?? "";
|
|
15793
15872
|
let meterValueSignatureValue = meterValueSignature.textContent.trim();
|
|
@@ -15808,37 +15887,37 @@ var XMLContainer = class {
|
|
|
15808
15887
|
default:
|
|
15809
15888
|
return {
|
|
15810
15889
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
15811
|
-
message: "Unkown meter value signature encoding within the given XML container!",
|
|
15890
|
+
message: this.chargy.GetMultilanguageText("Unkown meter value signature encoding within the given XML container!"),
|
|
15812
15891
|
certainty: 0
|
|
15813
15892
|
};
|
|
15814
15893
|
}
|
|
15815
15894
|
if (IsNullOrEmpty(meterValueSignatureValue))
|
|
15816
15895
|
return {
|
|
15817
15896
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
15818
|
-
message: "The meter value signature within the given XML container must not be empty!",
|
|
15897
|
+
message: this.chargy.GetMultilanguageText("The meter value signature within the given XML container must not be empty!"),
|
|
15819
15898
|
certainty: 0
|
|
15820
15899
|
};
|
|
15821
15900
|
common.meterValueSignatures.push(meterValueSignatureValue);
|
|
15822
15901
|
}
|
|
15823
|
-
const signatureMethod =
|
|
15902
|
+
const signatureMethod = valueElement.querySelector("signatureMethod")?.textContent.trim().toLowerCase() ?? "";
|
|
15824
15903
|
if (common.signatureMethod == "")
|
|
15825
15904
|
common.signatureMethod = signatureMethod;
|
|
15826
15905
|
else if (common.signatureMethod != signatureMethod)
|
|
15827
15906
|
return {
|
|
15828
15907
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
15829
|
-
message: "Invalid mixture of different signature methods within the given XML container!",
|
|
15908
|
+
message: this.chargy.GetMultilanguageText("Invalid mixture of different signature methods within the given XML container!"),
|
|
15830
15909
|
certainty: 0
|
|
15831
15910
|
};
|
|
15832
|
-
const encodingMethod =
|
|
15911
|
+
const encodingMethod = valueElement.querySelector("encodingMethod")?.textContent.trim().toLowerCase() ?? "";
|
|
15833
15912
|
if (common.encodingMethod == "")
|
|
15834
15913
|
common.encodingMethod = encodingMethod;
|
|
15835
15914
|
else if (common.encodingMethod != encodingMethod)
|
|
15836
15915
|
return {
|
|
15837
15916
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
15838
|
-
message: "Invalid mixture of different signed data formats within the given XML container!",
|
|
15917
|
+
message: this.chargy.GetMultilanguageText("Invalid mixture of different signed data formats within the given XML container!"),
|
|
15839
15918
|
certainty: 0
|
|
15840
15919
|
};
|
|
15841
|
-
const encodedMeterValue =
|
|
15920
|
+
const encodedMeterValue = valueElement.querySelector("encodedMeterValue");
|
|
15842
15921
|
if (encodedMeterValue != null) {
|
|
15843
15922
|
const signedDataEncoding = encodedMeterValue.attributes.getNamedItem("encoding")?.value.trim() ?? "";
|
|
15844
15923
|
let signedDataValue = encodedMeterValue.textContent.trim();
|
|
@@ -15859,21 +15938,21 @@ var XMLContainer = class {
|
|
|
15859
15938
|
default:
|
|
15860
15939
|
return {
|
|
15861
15940
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
15862
|
-
message: "Unkown signed data encoding within the given XML container!",
|
|
15941
|
+
message: this.chargy.GetMultilanguageText("Unkown signed data encoding within the given XML container!"),
|
|
15863
15942
|
certainty: 0
|
|
15864
15943
|
};
|
|
15865
15944
|
}
|
|
15866
15945
|
if (IsNullOrEmpty(signedDataValue))
|
|
15867
15946
|
return {
|
|
15868
15947
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
15869
|
-
message: "The signed data value within the given XML container must not be empty!",
|
|
15948
|
+
message: this.chargy.GetMultilanguageText("The signed data value within the given XML container must not be empty!"),
|
|
15870
15949
|
certainty: 0
|
|
15871
15950
|
};
|
|
15872
15951
|
common.encodedMeterValues.push(signedDataValue);
|
|
15873
15952
|
} else
|
|
15874
15953
|
return {
|
|
15875
15954
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
15876
|
-
message: "The signed data tag within the given XML container must not be empty!",
|
|
15955
|
+
message: this.chargy.GetMultilanguageText("The signed data tag within the given XML container must not be empty!"),
|
|
15877
15956
|
certainty: 0
|
|
15878
15957
|
};
|
|
15879
15958
|
}
|
|
@@ -15881,13 +15960,13 @@ var XMLContainer = class {
|
|
|
15881
15960
|
}
|
|
15882
15961
|
return {
|
|
15883
15962
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
15884
|
-
message: this.chargy.
|
|
15963
|
+
message: this.chargy.GetMultilanguageText("UnknownOrInvalidChargingSessionFormat"),
|
|
15885
15964
|
certainty: 0
|
|
15886
15965
|
};
|
|
15887
15966
|
} catch (exception) {
|
|
15888
15967
|
return {
|
|
15889
15968
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
15890
|
-
message: "Exception occured: " + (exception instanceof Error ? exception.message : String(exception)),
|
|
15969
|
+
message: this.chargy.GetMultilanguageText("Exception occured: " + (exception instanceof Error ? exception.message : String(exception))),
|
|
15891
15970
|
certainty: 0
|
|
15892
15971
|
};
|
|
15893
15972
|
}
|
|
@@ -15899,12 +15978,6 @@ var ChargeIT = class {
|
|
|
15899
15978
|
constructor(chargy) {
|
|
15900
15979
|
this.chargy = chargy;
|
|
15901
15980
|
}
|
|
15902
|
-
bufferToHex(buffer, Reverse) {
|
|
15903
|
-
return (Reverse ? Array.from(new Uint8Array(buffer)).reverse() : Array.from(new Uint8Array(buffer))).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
15904
|
-
}
|
|
15905
|
-
bufferToNumber(buffer) {
|
|
15906
|
-
return parseInt(Array.from(new Uint8Array(buffer)).map((b) => b.toString(16).padStart(2, "0")).join(""), 16);
|
|
15907
|
-
}
|
|
15908
15981
|
//#region TryToParseOldChargeITMeterValuesFormat(CTR, evseId, address, geoLocation, signedMeterValues)
|
|
15909
15982
|
TryToParseOldChargeITMeterValuesFormat(CTR, evseId, address, geoLocation, signedMeterValues) {
|
|
15910
15983
|
const CTRArray = new Array();
|
|
@@ -16004,14 +16077,8 @@ var ChargeIT = class {
|
|
|
16004
16077
|
});
|
|
16005
16078
|
}
|
|
16006
16079
|
}
|
|
16007
|
-
const firstMeterValue = CTRArray
|
|
16008
|
-
const lastMeterValue = CTRArray
|
|
16009
|
-
if (firstMeterValue === void 0 || lastMeterValue === void 0)
|
|
16010
|
-
return {
|
|
16011
|
-
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
16012
|
-
message: this.chargy.GetLocalizedMessage("UnknownOrInvalidChargingSessionFormat"),
|
|
16013
|
-
certainty: 0
|
|
16014
|
-
};
|
|
16080
|
+
const firstMeterValue = getFirstArrayElement(CTRArray, "Missing first chargeIT meter value");
|
|
16081
|
+
const lastMeterValue = getLastArrayElement(CTRArray, "Missing last chargeIT meter value");
|
|
16015
16082
|
CTR["@id"] = lastMeterValue["transactionId"];
|
|
16016
16083
|
CTR.begin = this.chargy.moment.unix(firstMeterValue["measuredValue"]["timestampLocal"]["timestamp"]).utc().format();
|
|
16017
16084
|
CTR.end = this.chargy.moment.unix(lastMeterValue["measuredValue"]["timestampLocal"]["timestamp"]).utc().format();
|
|
@@ -16194,38 +16261,38 @@ var ChargeIT = class {
|
|
|
16194
16261
|
{
|
|
16195
16262
|
const placeInfo = asJSONObject(SomeJSON["placeInfo"]);
|
|
16196
16263
|
if (placeInfo === void 0) {
|
|
16197
|
-
errors.push(this.chargy.
|
|
16264
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidPlaceInfo")));
|
|
16198
16265
|
secondaryErrors += 13;
|
|
16199
16266
|
} else {
|
|
16200
16267
|
const evseId = placeInfo["evseId"];
|
|
16201
16268
|
if (!isMandatoryString(evseId))
|
|
16202
|
-
errors.push(this.chargy.
|
|
16269
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidEVSEId")));
|
|
16203
16270
|
const address = asJSONObject(placeInfo["address"]);
|
|
16204
16271
|
if (address === void 0) {
|
|
16205
|
-
errors.push(this.chargy.
|
|
16272
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidAddress")));
|
|
16206
16273
|
secondaryErrors += 3;
|
|
16207
16274
|
} else {
|
|
16208
16275
|
if (!isMandatoryString(address["street"]))
|
|
16209
|
-
errors.push(this.chargy.
|
|
16276
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidAddressStreetName")));
|
|
16210
16277
|
if (!isMandatoryString(address["zipCode"]))
|
|
16211
|
-
errors.push(this.chargy.
|
|
16278
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidAddressZIPCode")));
|
|
16212
16279
|
if (!isMandatoryString(address["town"]))
|
|
16213
|
-
errors.push(this.chargy.
|
|
16280
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidAddressCityName")));
|
|
16214
16281
|
}
|
|
16215
16282
|
const geoLocation = asJSONObject(placeInfo["geoLocation"]);
|
|
16216
16283
|
if (geoLocation === void 0) {
|
|
16217
|
-
errors.push(this.chargy.
|
|
16284
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidGeoLocation")));
|
|
16218
16285
|
secondaryErrors += 2;
|
|
16219
16286
|
} else {
|
|
16220
16287
|
if (!isMandatoryNumber(geoLocation["lat"]))
|
|
16221
|
-
errors.push(this.chargy.
|
|
16288
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidGeoLocationLatitude")));
|
|
16222
16289
|
if (!isMandatoryNumber(geoLocation["lon"]))
|
|
16223
|
-
errors.push(this.chargy.
|
|
16290
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidGeoLocationLongitude")));
|
|
16224
16291
|
}
|
|
16225
16292
|
}
|
|
16226
16293
|
const signedMeterValues = SomeJSON["signedMeterValues"];
|
|
16227
16294
|
if (!isMandatoryJSONArray(signedMeterValues) || signedMeterValues.length < 2) {
|
|
16228
|
-
errors.push(this.chargy.
|
|
16295
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidSignedMeterValues")));
|
|
16229
16296
|
secondaryErrors += 2 * 39;
|
|
16230
16297
|
} else {
|
|
16231
16298
|
numberOfFormatChecks += 39 * (signedMeterValues.length - 2);
|
|
@@ -16234,135 +16301,134 @@ var ChargeIT = class {
|
|
|
16234
16301
|
for (const signedMeterValue of signedMeterValues.map((smv) => asJSONObject(smv))) {
|
|
16235
16302
|
if ((signedMeterValue?.["@context"] ?? oldChargeITMeterValueFormat) !== signedMeterValueContext) {
|
|
16236
16303
|
if (consistent)
|
|
16237
|
-
errors.push(this.chargy.
|
|
16304
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("InconsistentJSONContextInformation")));
|
|
16238
16305
|
consistent = false;
|
|
16239
16306
|
}
|
|
16240
16307
|
}
|
|
16241
16308
|
if (consistent) {
|
|
16242
16309
|
if (signedMeterValueContext === "https://www.lichtblick.de/contexts/bsm-ws36a-json-v0" || signedMeterValueContext === "https://www.lichtblick.de/contexts/bsm-ws36a-json-v1" || signedMeterValueContext === "https://www.eneco.com/contexts/bsm-ws36a-json-v0" || signedMeterValueContext === "https://www.eneco.com/contexts/bsm-ws36a-json-v1" || signedMeterValueContext === "https://www.chargeit-mobility.com/contexts/bsm-ws36a-json-v0" || signedMeterValueContext === "https://www.chargeit-mobility.com/contexts/bsm-ws36a-json-v1") {
|
|
16243
16310
|
} else if (signedMeterValueContext.startsWith("ALFEN")) {
|
|
16244
|
-
} else if (containerFormat === oldChargeITContainerFormat) {
|
|
16245
16311
|
} else if (signedMeterValueContext === oldChargeITMeterValueFormat) {
|
|
16246
16312
|
let measurementCounter = 0;
|
|
16247
16313
|
for (const signedMeterValue of signedMeterValues) {
|
|
16248
16314
|
measurementCounter++;
|
|
16249
16315
|
if (!isMandatoryJSONObject(signedMeterValue)) {
|
|
16250
|
-
errors.push(this.chargy.
|
|
16316
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalidSignedMeterValueP", measurementCounter)));
|
|
16251
16317
|
secondaryErrors += 38;
|
|
16252
16318
|
} else {
|
|
16253
16319
|
if (!isMandatoryString(signedMeterValue["measurementId"]))
|
|
16254
|
-
errors.push(this.chargy.
|
|
16320
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeasurementIdP", measurementCounter)));
|
|
16255
16321
|
if (!isMandatoryNumber(signedMeterValue["timestamp"]))
|
|
16256
|
-
errors.push(this.chargy.
|
|
16322
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_TimestampP", measurementCounter)));
|
|
16257
16323
|
if (!isMandatoryString(signedMeterValue["transactionId"]))
|
|
16258
|
-
errors.push(this.chargy.
|
|
16324
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_TransactionIdP", measurementCounter)));
|
|
16259
16325
|
if (!isMandatoryString(signedMeterValue["signature"]))
|
|
16260
|
-
errors.push(this.chargy.
|
|
16326
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_SignatureP", measurementCounter)));
|
|
16261
16327
|
const meterInfo = signedMeterValue["meterInfo"];
|
|
16262
16328
|
if (!isMandatoryJSONObject(meterInfo)) {
|
|
16263
|
-
errors.push(this.chargy.
|
|
16329
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfoP", measurementCounter)));
|
|
16264
16330
|
secondaryErrors += 5;
|
|
16265
16331
|
} else {
|
|
16266
16332
|
if (!isMandatoryString(meterInfo["meterId"]))
|
|
16267
|
-
errors.push(this.chargy.
|
|
16333
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_MeterIdP", measurementCounter)));
|
|
16268
16334
|
if (!isMandatoryString(meterInfo["type"]))
|
|
16269
|
-
errors.push(this.chargy.
|
|
16335
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_TypeP", measurementCounter)));
|
|
16270
16336
|
if (!isMandatoryString(meterInfo["firmwareVersion"]))
|
|
16271
|
-
errors.push(this.chargy.
|
|
16337
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_FirmwareVersionP", measurementCounter)));
|
|
16272
16338
|
if (!isMandatoryString(meterInfo["publicKey"]))
|
|
16273
|
-
errors.push(this.chargy.
|
|
16339
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_PublicKeyP", measurementCounter)));
|
|
16274
16340
|
if (!isMandatoryString(meterInfo["manufacturer"]))
|
|
16275
|
-
errors.push(this.chargy.
|
|
16341
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_ManufacturerP", measurementCounter)));
|
|
16276
16342
|
if (isOptionalJSONArrayError(meterInfo["publicKeySignatures"]))
|
|
16277
|
-
errors.push(this.chargy.
|
|
16343
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Invalid_SignedMeterValue_MeterInfo_PublicKeySignaturesP", measurementCounter)));
|
|
16278
16344
|
}
|
|
16279
16345
|
const contract = signedMeterValue["contract"];
|
|
16280
16346
|
if (!isMandatoryJSONObject(contract)) {
|
|
16281
|
-
errors.push(this.chargy.
|
|
16347
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_ContractP", measurementCounter)));
|
|
16282
16348
|
secondaryErrors += 7;
|
|
16283
16349
|
} else {
|
|
16284
16350
|
if (!isMandatoryString(contract["id"]))
|
|
16285
|
-
errors.push(this.chargy.
|
|
16351
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_Contract_IdP", measurementCounter)));
|
|
16286
16352
|
if (!isMandatoryString(contract["type"]))
|
|
16287
|
-
errors.push(this.chargy.
|
|
16353
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_Contract_TypeP", measurementCounter)));
|
|
16288
16354
|
if (!isMandatoryNumber(contract["timestamp"]))
|
|
16289
|
-
errors.push(this.chargy.
|
|
16355
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_Contract_TimestampP", measurementCounter)));
|
|
16290
16356
|
const timestampLocal = contract["timestampLocal"];
|
|
16291
16357
|
if (!isMandatoryJSONObject(timestampLocal)) {
|
|
16292
|
-
errors.push(this.chargy.
|
|
16358
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_Contract_TimestampLocalP", measurementCounter)));
|
|
16293
16359
|
secondaryErrors += 3;
|
|
16294
16360
|
} else {
|
|
16295
16361
|
if (!isMandatoryNumber(timestampLocal["timestamp"]))
|
|
16296
|
-
errors.push(this.chargy.
|
|
16362
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_Contract_TimestampLocal_TimestampP", measurementCounter)));
|
|
16297
16363
|
if (!isMandatoryNumber(timestampLocal["localOffset"]))
|
|
16298
|
-
errors.push(this.chargy.
|
|
16364
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_Contract_TimestampLocal_LocalOffsetP", measurementCounter)));
|
|
16299
16365
|
if (!isMandatoryNumber(timestampLocal["seasonOffset"]))
|
|
16300
|
-
errors.push(this.chargy.
|
|
16366
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_Contract_TimestampLocal_SeasonOffsetP", measurementCounter)));
|
|
16301
16367
|
}
|
|
16302
16368
|
}
|
|
16303
16369
|
const measuredValue = signedMeterValue["measuredValue"];
|
|
16304
16370
|
if (!isMandatoryJSONObject(measuredValue)) {
|
|
16305
|
-
errors.push(this.chargy.
|
|
16371
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeasuredValueP", measurementCounter)));
|
|
16306
16372
|
secondaryErrors += 9;
|
|
16307
16373
|
} else {
|
|
16308
16374
|
if (!isMandatoryString(measuredValue["value"]))
|
|
16309
|
-
errors.push(this.chargy.
|
|
16375
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeasuredValue_ValueP", measurementCounter)));
|
|
16310
16376
|
if (!isMandatoryString(measuredValue["unit"]))
|
|
16311
|
-
errors.push(this.chargy.
|
|
16377
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeasuredValue_UnitP", measurementCounter)));
|
|
16312
16378
|
if (!isMandatoryNumber(measuredValue["scale"]))
|
|
16313
|
-
errors.push(this.chargy.
|
|
16379
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeasuredValue_ScaleP", measurementCounter)));
|
|
16314
16380
|
if (!isMandatoryString(measuredValue["valueType"]))
|
|
16315
|
-
errors.push(this.chargy.
|
|
16381
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeasuredValue_ValueTypeP", measurementCounter)));
|
|
16316
16382
|
if (!isMandatoryNumber(measuredValue["unitEncoded"]))
|
|
16317
|
-
errors.push(this.chargy.
|
|
16383
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeasuredValue_UnitEncodedP", measurementCounter)));
|
|
16318
16384
|
const timestampLocal = measuredValue["timestampLocal"];
|
|
16319
16385
|
if (!isMandatoryJSONObject(timestampLocal)) {
|
|
16320
|
-
errors.push(this.chargy.
|
|
16386
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalidMeasuredValueTimestampLocalP", measurementCounter)));
|
|
16321
16387
|
secondaryErrors += 3;
|
|
16322
16388
|
} else {
|
|
16323
16389
|
if (!isMandatoryNumber(timestampLocal["timestamp"]))
|
|
16324
|
-
errors.push(this.chargy.
|
|
16390
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalidMeasuredValueTimestampLocalTimestampP", measurementCounter)));
|
|
16325
16391
|
if (!isMandatoryNumber(timestampLocal["localOffset"]))
|
|
16326
|
-
errors.push(this.chargy.
|
|
16392
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalidMeasuredValueTimestampLocalOffsetP", measurementCounter)));
|
|
16327
16393
|
if (!isMandatoryNumber(timestampLocal["seasonOffset"]))
|
|
16328
|
-
errors.push(this.chargy.
|
|
16394
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalidMeasuredValueTimestampSeasonOffsetP", measurementCounter)));
|
|
16329
16395
|
}
|
|
16330
16396
|
}
|
|
16331
16397
|
const measurand = signedMeterValue["measurand"];
|
|
16332
16398
|
if (!isMandatoryJSONObject(measurand)) {
|
|
16333
|
-
errors.push(this.chargy.
|
|
16399
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeasurandP", measurementCounter)));
|
|
16334
16400
|
secondaryErrors += 2;
|
|
16335
16401
|
} else {
|
|
16336
16402
|
if (!isMandatoryString(measurand["id"]))
|
|
16337
|
-
errors.push(this.chargy.
|
|
16403
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_Measurand_IdP", measurementCounter)));
|
|
16338
16404
|
if (!isMandatoryString(measurand["name"]))
|
|
16339
|
-
errors.push(this.chargy.
|
|
16405
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_Measurand_NameP", measurementCounter)));
|
|
16340
16406
|
}
|
|
16341
16407
|
const additionalInfo = signedMeterValue["additionalInfo"];
|
|
16342
16408
|
if (!isMandatoryJSONObject(additionalInfo)) {
|
|
16343
|
-
errors.push(this.chargy.
|
|
16409
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_AdditionalInformationP", measurementCounter)));
|
|
16344
16410
|
secondaryErrors += 4;
|
|
16345
16411
|
} else {
|
|
16346
16412
|
if (!isMandatoryString(additionalInfo["status"]))
|
|
16347
|
-
errors.push(this.chargy.
|
|
16413
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_AdditionalInformation_StatusP", measurementCounter)));
|
|
16348
16414
|
const indexes = additionalInfo["indexes"];
|
|
16349
16415
|
if (!isMandatoryJSONObject(indexes)) {
|
|
16350
|
-
errors.push(this.chargy.
|
|
16416
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_AdditionalInformation_IndexesP", measurementCounter)));
|
|
16351
16417
|
secondaryErrors += 2;
|
|
16352
16418
|
} else {
|
|
16353
16419
|
if (!isMandatoryNumber(indexes["timer"]))
|
|
16354
|
-
errors.push(this.chargy.
|
|
16420
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_AdditionalInformation_Indexes_TimerP", measurementCounter)));
|
|
16355
16421
|
if (!isMandatoryString(indexes["logBook"]))
|
|
16356
|
-
errors.push(this.chargy.
|
|
16422
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_AdditionalInformation_Indexes_LogBookP", measurementCounter)));
|
|
16357
16423
|
}
|
|
16358
16424
|
}
|
|
16359
16425
|
const chargePoint = signedMeterValue["chargePoint"];
|
|
16360
|
-
if (!isMandatoryJSONObject(chargePoint)) {
|
|
16361
|
-
errors.push(this.chargy.
|
|
16426
|
+
if (chargePoint !== void 0 && !isMandatoryJSONObject(chargePoint)) {
|
|
16427
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_ChargePointInformationP", measurementCounter)));
|
|
16362
16428
|
secondaryErrors += 1;
|
|
16363
|
-
} else {
|
|
16429
|
+
} else if (isMandatoryJSONObject(chargePoint)) {
|
|
16364
16430
|
if (!isMandatoryString(chargePoint["softwareVersion"]))
|
|
16365
|
-
errors.push(this.chargy.
|
|
16431
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_ChargePointInformation_SoftwareVersionP", measurementCounter)));
|
|
16366
16432
|
}
|
|
16367
16433
|
}
|
|
16368
16434
|
}
|
|
@@ -16508,19 +16574,17 @@ var ChargeIT = class {
|
|
|
16508
16574
|
}
|
|
16509
16575
|
);
|
|
16510
16576
|
}
|
|
16511
|
-
if (
|
|
16512
|
-
|
|
16513
|
-
|
|
16514
|
-
|
|
16515
|
-
|
|
16516
|
-
|
|
16517
|
-
|
|
16518
|
-
|
|
16519
|
-
address: { "street": address_street, "postalCode": address_zipCode, "city": address_town, "country": address_country }
|
|
16520
|
-
}
|
|
16577
|
+
if (asJSONObject(signedMeterValues[0])?.["format"] == "ALFEN")
|
|
16578
|
+
return new Alfen(this.chargy).TryToParseALFENFormat(
|
|
16579
|
+
signedMeterValues.map((value) => asString(asJSONObject(value)?.["payload"]) ?? ""),
|
|
16580
|
+
{
|
|
16581
|
+
EVSEId: evseId,
|
|
16582
|
+
chargingStation: {
|
|
16583
|
+
geoLocation: { "lat": geoLocation_lat, "lng": geoLocation_lon },
|
|
16584
|
+
address: { "street": address_street, "postalCode": address_zipCode, "city": address_town, "country": address_country }
|
|
16521
16585
|
}
|
|
16522
|
-
|
|
16523
|
-
|
|
16586
|
+
}
|
|
16587
|
+
);
|
|
16524
16588
|
if (signedMeterValueContext === oldChargeITMeterValueFormat)
|
|
16525
16589
|
return this.TryToParseOldChargeITMeterValuesFormat(
|
|
16526
16590
|
CTR,
|
|
@@ -16540,7 +16604,7 @@ var ChargeIT = class {
|
|
|
16540
16604
|
} catch (exception) {
|
|
16541
16605
|
return {
|
|
16542
16606
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
16543
|
-
message: "Exception occured: " + (exception instanceof Error ? exception.message : String(exception)),
|
|
16607
|
+
message: this.chargy.GetMultilanguageText("Exception occured: " + (exception instanceof Error ? exception.message : String(exception))),
|
|
16544
16608
|
errors,
|
|
16545
16609
|
warnings,
|
|
16546
16610
|
certainty: (numberOfFormatChecks - errors.length - secondaryErrors) / numberOfFormatChecks
|
|
@@ -16613,142 +16677,140 @@ var ChargeIT = class {
|
|
|
16613
16677
|
const totalCosts_flat_cost = totalCosts_flat?.["cost"];
|
|
16614
16678
|
const signedMeterValues = SomeJSON["signedMeterValues"];
|
|
16615
16679
|
if (!isMandatoryString(chargingSessionId))
|
|
16616
|
-
errors.push(this.chargy.
|
|
16680
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid charge transparency record identification!")));
|
|
16617
16681
|
if (!isMandatoryJSONObject(chargePointInfo)) {
|
|
16618
|
-
errors.push(this.chargy.
|
|
16682
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidChargePointInfo")));
|
|
16619
16683
|
secondaryErrors += 19;
|
|
16620
16684
|
} else {
|
|
16621
16685
|
if (!isMandatoryString(evseId))
|
|
16622
|
-
errors.push(this.chargy.
|
|
16686
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidEVSEIdentification")));
|
|
16623
16687
|
if (!isMandatoryJSONObject(placeInfo)) {
|
|
16624
|
-
errors.push(this.chargy.
|
|
16688
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidPlaceInfo")));
|
|
16625
16689
|
secondaryErrors += 8;
|
|
16626
16690
|
} else {
|
|
16627
16691
|
if (!isMandatoryJSONObject(geoLocation)) {
|
|
16628
|
-
errors.push(this.chargy.
|
|
16692
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidGeoLocation")));
|
|
16629
16693
|
secondaryErrors += 2;
|
|
16630
16694
|
} else {
|
|
16631
16695
|
if (!isMandatoryNumber(geoLocation_lat))
|
|
16632
|
-
errors.push(this.chargy.
|
|
16696
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidGeoLocationLatitude")));
|
|
16633
16697
|
if (!isMandatoryNumber(geoLocation_lon))
|
|
16634
|
-
errors.push(this.chargy.
|
|
16698
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidGeoLocationLongitude")));
|
|
16635
16699
|
}
|
|
16636
16700
|
if (!isMandatoryJSONObject(address)) {
|
|
16637
|
-
errors.push(this.chargy.
|
|
16701
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidAddress")));
|
|
16638
16702
|
secondaryErrors += 4;
|
|
16639
16703
|
} else {
|
|
16640
16704
|
if (!isMandatoryString(address_street))
|
|
16641
|
-
errors.push(this.chargy.
|
|
16705
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidAddressStreetName")));
|
|
16642
16706
|
if (!isMandatoryString(address_zipCode))
|
|
16643
|
-
errors.push(this.chargy.
|
|
16707
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidAddressZIPCode")));
|
|
16644
16708
|
if (!isMandatoryString(address_town))
|
|
16645
|
-
errors.push(this.chargy.
|
|
16709
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidAddressCityName")));
|
|
16646
16710
|
if (!isMandatoryString(address_country))
|
|
16647
|
-
errors.push(this.chargy.
|
|
16711
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidAddressCountryName")));
|
|
16648
16712
|
}
|
|
16649
16713
|
}
|
|
16650
16714
|
}
|
|
16651
16715
|
if (!isMandatoryJSONObject(chargingStationInfo)) {
|
|
16652
|
-
errors.push(this.chargy.
|
|
16716
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidChargingStationInfo")));
|
|
16653
16717
|
secondaryErrors += 5;
|
|
16654
16718
|
} else {
|
|
16655
16719
|
if (!isOptionalString(chargingStation_manufacturer))
|
|
16656
|
-
errors.push(this.chargy.
|
|
16720
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station manufacturer!")));
|
|
16657
16721
|
if (!isOptionalString(chargingStation_type))
|
|
16658
|
-
errors.push(this.chargy.
|
|
16722
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station type!")));
|
|
16659
16723
|
if (!isOptionalString(chargingStation_serialNumber))
|
|
16660
|
-
errors.push(this.chargy.
|
|
16724
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station serial number!")));
|
|
16661
16725
|
if (!isOptionalString(chargingStation_controllerSoftwareVersion))
|
|
16662
|
-
errors.push(this.chargy.
|
|
16726
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station controller software version!")));
|
|
16663
16727
|
if (!isOptionalString(chargingStation_compliance))
|
|
16664
|
-
errors.push(this.chargy.
|
|
16728
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station compliance!")));
|
|
16665
16729
|
if (!isOptionalURL(chargingStation_complianceURL))
|
|
16666
|
-
errors.push(this.chargy.
|
|
16730
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station compliance URL!")));
|
|
16667
16731
|
if (!isOptionalString(chargingStation_conformity))
|
|
16668
|
-
errors.push(this.chargy.
|
|
16732
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station conformity!")));
|
|
16669
16733
|
if (!isOptionalURL(chargingStation_conformity_URL))
|
|
16670
|
-
errors.push(this.chargy.
|
|
16734
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station conformity URL!")));
|
|
16671
16735
|
if (!isOptionalURL(chargingStation_conformity_certificateId))
|
|
16672
|
-
errors.push(this.chargy.
|
|
16736
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station conformity certificate identification!")));
|
|
16673
16737
|
if (!isOptionalString(chargingStation_calibration))
|
|
16674
|
-
errors.push(this.chargy.
|
|
16738
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station calibration!")));
|
|
16675
16739
|
if (!isOptionalURL(chargingStation_calibration_URL))
|
|
16676
|
-
errors.push(this.chargy.
|
|
16740
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station calibration URL!")));
|
|
16677
16741
|
if (!isOptionalURL(chargingStation_calibration_certificateId))
|
|
16678
|
-
errors.push(this.chargy.
|
|
16742
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station calibration certificate identification!")));
|
|
16679
16743
|
}
|
|
16680
16744
|
if (meterInfo) {
|
|
16681
16745
|
if (!isOptionalString(meterInfo_meterId))
|
|
16682
|
-
errors.push(this.chargy.
|
|
16746
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_MeterIdP", 1)));
|
|
16683
16747
|
if (!isOptionalString(meterInfo_manufacturer))
|
|
16684
|
-
errors.push(this.chargy.
|
|
16748
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_ManufacturerP", 1)));
|
|
16685
16749
|
if (!isOptionalString(meterInfo_manufacturerURL))
|
|
16686
|
-
errors.push(this.chargy.
|
|
16750
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_ManufacturerP", 1)));
|
|
16687
16751
|
if (!isOptionalString(meterInfo_model))
|
|
16688
|
-
errors.push(this.chargy.
|
|
16752
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_ManufacturerP", 1)));
|
|
16689
16753
|
if (!isOptionalString(meterInfo_modelURL))
|
|
16690
|
-
errors.push(this.chargy.
|
|
16754
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_ManufacturerP", 1)));
|
|
16691
16755
|
if (!isOptionalString(meterInfo_firmwareVersion))
|
|
16692
|
-
errors.push(this.chargy.
|
|
16756
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_FirmwareVersionP", 1)));
|
|
16693
16757
|
if (!isOptionalString(meterInfo_hardwareVersion))
|
|
16694
|
-
errors.push(this.chargy.
|
|
16758
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_FirmwareVersionP", 1)));
|
|
16695
16759
|
if (!isOptionalString(meterInfo_publicKey))
|
|
16696
|
-
errors.push(this.chargy.
|
|
16760
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_PublicKeyP", 1)));
|
|
16697
16761
|
if (!isOptionalString(meterInfo_publicKeyFormat))
|
|
16698
|
-
errors.push(this.chargy.
|
|
16762
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_PublicKeyP", 1)));
|
|
16699
16763
|
if (!isOptionalString(meterInfo_publicKeyEncoding))
|
|
16700
|
-
errors.push(this.chargy.
|
|
16764
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_PublicKeyP", 1)));
|
|
16701
16765
|
if (!isOptionalString(meterInfo_signatureFormat))
|
|
16702
|
-
errors.push(this.chargy.
|
|
16766
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_PublicKeyP", 1)));
|
|
16703
16767
|
if (!isOptionalString(meterInfo_signatureEncoding))
|
|
16704
|
-
errors.push(this.chargy.
|
|
16768
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_PublicKeyP", 1)));
|
|
16705
16769
|
}
|
|
16706
16770
|
if (connectorInfo) {
|
|
16707
16771
|
if (!isOptionalString(connectorInfo_type))
|
|
16708
|
-
errors.push(this.chargy.
|
|
16772
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_MeterIdP", 1)));
|
|
16709
16773
|
if (!isOptionalString(connectorInfo_losses))
|
|
16710
|
-
errors.push(this.chargy.
|
|
16774
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_MeterIdP", 1)));
|
|
16711
16775
|
}
|
|
16712
16776
|
if (isMandatoryJSONArray(chargingTariffs)) {
|
|
16713
|
-
for (let i = 0; i < chargingTariffs.length; i++) {
|
|
16714
|
-
}
|
|
16715
16777
|
}
|
|
16716
16778
|
if (totalCosts) {
|
|
16717
16779
|
if (!isMandatoryNumber(totalCosts_total))
|
|
16718
|
-
errors.push(this.chargy.
|
|
16780
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid total costs within the charging costs!")));
|
|
16719
16781
|
if (!isMandatoryString(totalCosts_currency))
|
|
16720
|
-
errors.push(this.chargy.
|
|
16782
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid currency within the charging costs!")));
|
|
16721
16783
|
if (totalCosts_reservation) {
|
|
16722
16784
|
if (!isMandatoryNumber(totalCosts_reservation_cost))
|
|
16723
|
-
errors.push(this.chargy.
|
|
16785
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid reservation cost within the charging costs!")));
|
|
16724
16786
|
if (!isMandatoryString(totalCosts_reservation_unit))
|
|
16725
|
-
errors.push(this.chargy.
|
|
16787
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid reservation unit within the charging costs!")));
|
|
16726
16788
|
}
|
|
16727
16789
|
if (totalCosts_energy) {
|
|
16728
16790
|
if (!isMandatoryNumber(totalCosts_energy_cost))
|
|
16729
|
-
errors.push(this.chargy.
|
|
16791
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid energy cost within the charging costs!")));
|
|
16730
16792
|
if (!isMandatoryString(totalCosts_energy_unit))
|
|
16731
|
-
errors.push(this.chargy.
|
|
16793
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid energy unit within the charging costs!")));
|
|
16732
16794
|
}
|
|
16733
16795
|
if (totalCosts_time) {
|
|
16734
16796
|
if (!isMandatoryNumber(totalCosts_time_cost))
|
|
16735
|
-
errors.push(this.chargy.
|
|
16797
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid time cost within the charging costs!")));
|
|
16736
16798
|
if (!isMandatoryString(totalCosts_time_unit))
|
|
16737
|
-
errors.push(this.chargy.
|
|
16799
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid time unit within the charging costs!")));
|
|
16738
16800
|
}
|
|
16739
16801
|
if (totalCosts_idle) {
|
|
16740
16802
|
if (!isMandatoryNumber(totalCosts_idle_cost))
|
|
16741
|
-
errors.push(this.chargy.
|
|
16803
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid idle cost within the charging costs!")));
|
|
16742
16804
|
if (!isMandatoryString(totalCosts_idle_unit))
|
|
16743
|
-
errors.push(this.chargy.
|
|
16805
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid idle unit within the charging costs!")));
|
|
16744
16806
|
}
|
|
16745
16807
|
if (totalCosts_flat) {
|
|
16746
16808
|
if (!isMandatoryNumber(totalCosts_flat_cost))
|
|
16747
|
-
errors.push(this.chargy.
|
|
16809
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid flat cost within the charging costs!")));
|
|
16748
16810
|
}
|
|
16749
16811
|
}
|
|
16750
16812
|
if (!isMandatoryJSONArray(signedMeterValues) || signedMeterValues.length < 2) {
|
|
16751
|
-
errors.push(this.chargy.
|
|
16813
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidSignedMeterValues")));
|
|
16752
16814
|
secondaryErrors += 2 * 39;
|
|
16753
16815
|
} else {
|
|
16754
16816
|
const firstSMV = asJSONObject(signedMeterValues[0]);
|
|
@@ -16758,7 +16820,7 @@ var ChargeIT = class {
|
|
|
16758
16820
|
const context = asString(currentSMV?.["@context"])?.trim() ?? asString(currentSMV?.["format"])?.trim() ?? null;
|
|
16759
16821
|
if (smvContext !== context) return {
|
|
16760
16822
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
16761
|
-
message: "Inconsistent signed meter value format!",
|
|
16823
|
+
message: this.chargy.GetMultilanguageText("Inconsistent signed meter value format!"),
|
|
16762
16824
|
certainty: 1
|
|
16763
16825
|
};
|
|
16764
16826
|
}
|
|
@@ -16864,9 +16926,9 @@ var ChargeIT = class {
|
|
|
16864
16926
|
],
|
|
16865
16927
|
certainty: 0
|
|
16866
16928
|
};
|
|
16867
|
-
if (smvContext?.startsWith("https://www.chargeit-mobility.com/contexts/bsm-ws36a-json"))
|
|
16929
|
+
if (smvContext?.startsWith("https://www.chargeit-mobility.com/contexts/bsm-ws36a-json") === true)
|
|
16868
16930
|
return new BSMCrypt01(this.chargy).tryToParseBSM_WS36aMeasurements(CTR, evseIdStr, asString(chargingStation_controllerSoftwareVersion) ?? null, signedMeterValues);
|
|
16869
|
-
if (smvContext?.startsWith("ALFEN"))
|
|
16931
|
+
if (smvContext?.startsWith("ALFEN") === true)
|
|
16870
16932
|
return new Alfen(this.chargy).TryToParseALFENFormat(
|
|
16871
16933
|
signedMeterValues.map((value) => asString(asJSONObject(value)?.["payload"]) ?? ""),
|
|
16872
16934
|
{
|
|
@@ -16907,7 +16969,7 @@ var ChargeIT = class {
|
|
|
16907
16969
|
} catch (exception) {
|
|
16908
16970
|
return {
|
|
16909
16971
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
16910
|
-
message: "Exception occured: " + (exception instanceof Error ? exception.message : String(exception)),
|
|
16972
|
+
message: this.chargy.GetMultilanguageText("Exception occured: " + (exception instanceof Error ? exception.message : String(exception))),
|
|
16911
16973
|
errors,
|
|
16912
16974
|
warnings,
|
|
16913
16975
|
certainty: (numberOfFormatChecks - errors.length - secondaryErrors) / numberOfFormatChecks
|
|
@@ -16916,7 +16978,7 @@ var ChargeIT = class {
|
|
|
16916
16978
|
}
|
|
16917
16979
|
return {
|
|
16918
16980
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
16919
|
-
message: "No chargeIT charge transparency record",
|
|
16981
|
+
message: this.chargy.GetMultilanguageText("No chargeIT charge transparency record"),
|
|
16920
16982
|
errors,
|
|
16921
16983
|
warnings,
|
|
16922
16984
|
certainty: 0
|
|
@@ -16935,7 +16997,7 @@ var ChargePoint = class {
|
|
|
16935
16997
|
if (!isMandatoryJSONObject(SomeJSON))
|
|
16936
16998
|
return {
|
|
16937
16999
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
16938
|
-
message: this.chargy.
|
|
17000
|
+
message: this.chargy.GetMultilanguageText("UnknownOrInvalidChargingSessionFormat"),
|
|
16939
17001
|
certainty: 0
|
|
16940
17002
|
};
|
|
16941
17003
|
if (SomeJSON["company_name"] !== void 0 && SomeJSON["display_unit"] !== void 0 && //SomeJSON["energy"] !== undefined &&
|
|
@@ -16969,10 +17031,8 @@ var ChargePoint = class {
|
|
|
16969
17031
|
if (startTimeUTC !== void 0 && (parkingEnd === void 0 || startTimeUTC > parkingEnd))
|
|
16970
17032
|
parkingEnd = endTimeUTC;
|
|
16971
17033
|
}
|
|
16972
|
-
|
|
16973
|
-
|
|
16974
|
-
if (chargingEnd === void 0)
|
|
16975
|
-
chargingEnd = parkingEnd;
|
|
17034
|
+
chargingStart ??= parkingStart;
|
|
17035
|
+
chargingEnd ??= parkingEnd;
|
|
16976
17036
|
let sessionStart = parkingStart !== void 0 && (chargingStart === void 0 || parkingStart < chargingStart) ? parkingStart : chargingStart;
|
|
16977
17037
|
if (sessionStart === void 0 && parkingStart !== void 0)
|
|
16978
17038
|
sessionStart = parkingStart;
|
|
@@ -17121,7 +17181,7 @@ var ChargePoint = class {
|
|
|
17121
17181
|
"status": "Unvalidated" /* Unvalidated */
|
|
17122
17182
|
};
|
|
17123
17183
|
if (parking && parking.length > 0 && CTR.chargingSessions && CTR.chargingSessions.length > 0) {
|
|
17124
|
-
const chargingSession = CTR.chargingSessions
|
|
17184
|
+
const chargingSession = getFirstArrayElement(CTR.chargingSessions, "Missing ChargePoint charging session");
|
|
17125
17185
|
chargingSession.parking = [];
|
|
17126
17186
|
for (const parkingItem of parking) {
|
|
17127
17187
|
const parkingObj = asJSONObject(parkingItem);
|
|
@@ -17258,13 +17318,13 @@ var ChargePoint = class {
|
|
|
17258
17318
|
} catch (exception) {
|
|
17259
17319
|
return {
|
|
17260
17320
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
17261
|
-
message: "Exception occured: " + (exception instanceof Error ? exception.message : String(exception)),
|
|
17321
|
+
message: this.chargy.GetMultilanguageText("Exception occured: " + (exception instanceof Error ? exception.message : String(exception))),
|
|
17262
17322
|
certainty: 0
|
|
17263
17323
|
};
|
|
17264
17324
|
}
|
|
17265
17325
|
return {
|
|
17266
17326
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
17267
|
-
message: this.chargy.
|
|
17327
|
+
message: this.chargy.GetMultilanguageText("UnknownOrInvalidChargingSessionFormat"),
|
|
17268
17328
|
certainty: 0
|
|
17269
17329
|
};
|
|
17270
17330
|
}
|
|
@@ -17287,7 +17347,7 @@ var ChargePointCrypt01 = class extends ACrypt {
|
|
|
17287
17347
|
if (chargingSession.ctr === void 0) {
|
|
17288
17348
|
return {
|
|
17289
17349
|
status: "InvalidSignature" /* InvalidSignature */,
|
|
17290
|
-
message: this.chargy.
|
|
17350
|
+
message: this.chargy.GetMultilanguageText("InvalidSignature"),
|
|
17291
17351
|
certainty: 0
|
|
17292
17352
|
};
|
|
17293
17353
|
}
|
|
@@ -17323,7 +17383,7 @@ var ChargePointCrypt01 = class extends ACrypt {
|
|
|
17323
17383
|
if (publicKeys.length == 0)
|
|
17324
17384
|
return {
|
|
17325
17385
|
status: "PublicKeyNotFound" /* PublicKeyNotFound */,
|
|
17326
|
-
message: this.chargy.
|
|
17386
|
+
message: this.chargy.GetMultilanguageText("Public key notFound"),
|
|
17327
17387
|
certainty: 0
|
|
17328
17388
|
};
|
|
17329
17389
|
if (plainText !== "" && chargingSession.signature != null && chargingSession.signature !== "") {
|
|
@@ -17398,7 +17458,7 @@ var ChargePointCrypt01 = class extends ACrypt {
|
|
|
17398
17458
|
if (measurementValue.result?.status !== "ValidSignature" /* ValidSignature */ && measurementValue.result?.status !== "NoOperation" /* NoOperation */) {
|
|
17399
17459
|
return {
|
|
17400
17460
|
status: "InvalidSignature" /* InvalidSignature */,
|
|
17401
|
-
message: this.chargy.
|
|
17461
|
+
message: this.chargy.GetMultilanguageText("InvalidSignature"),
|
|
17402
17462
|
certainty: 0
|
|
17403
17463
|
};
|
|
17404
17464
|
}
|
|
@@ -17417,6 +17477,8 @@ var ChargePointCrypt01 = class extends ACrypt {
|
|
|
17417
17477
|
case "InvalidSignature" /* InvalidSignature */:
|
|
17418
17478
|
currentResult.status = "InvalidStartValue" /* InvalidStartValue */;
|
|
17419
17479
|
break;
|
|
17480
|
+
default:
|
|
17481
|
+
break;
|
|
17420
17482
|
}
|
|
17421
17483
|
} else if (i == measurement.values.length - 1) {
|
|
17422
17484
|
switch (currentResult.status) {
|
|
@@ -17429,6 +17491,8 @@ var ChargePointCrypt01 = class extends ACrypt {
|
|
|
17429
17491
|
case "InvalidSignature" /* InvalidSignature */:
|
|
17430
17492
|
currentResult.status = "InvalidStopValue" /* InvalidStopValue */;
|
|
17431
17493
|
break;
|
|
17494
|
+
default:
|
|
17495
|
+
break;
|
|
17432
17496
|
}
|
|
17433
17497
|
} else {
|
|
17434
17498
|
switch (currentResult.status) {
|
|
@@ -17441,6 +17505,8 @@ var ChargePointCrypt01 = class extends ACrypt {
|
|
|
17441
17505
|
case "InvalidSignature" /* InvalidSignature */:
|
|
17442
17506
|
currentResult.status = "InvalidStopValue" /* InvalidStopValue */;
|
|
17443
17507
|
break;
|
|
17508
|
+
default:
|
|
17509
|
+
break;
|
|
17444
17510
|
}
|
|
17445
17511
|
}
|
|
17446
17512
|
}
|
|
@@ -17455,7 +17521,7 @@ var ChargePointCrypt01 = class extends ACrypt {
|
|
|
17455
17521
|
} catch (exception) {
|
|
17456
17522
|
return {
|
|
17457
17523
|
status: "InvalidSignature" /* InvalidSignature */,
|
|
17458
|
-
message: "Exception occured: " + (exception instanceof Error ? exception.message : String(exception)),
|
|
17524
|
+
message: this.chargy.GetMultilanguageText("Exception occured: " + (exception instanceof Error ? exception.message : String(exception))),
|
|
17459
17525
|
certainty: 0
|
|
17460
17526
|
};
|
|
17461
17527
|
}
|
|
@@ -17470,9 +17536,9 @@ var ChargePointCrypt01 = class extends ACrypt {
|
|
|
17470
17536
|
const cryptoResult = {
|
|
17471
17537
|
status: "NoOperation" /* NoOperation */
|
|
17472
17538
|
};
|
|
17473
|
-
return
|
|
17539
|
+
return Promise.resolve(setResult("NoOperation" /* NoOperation */));
|
|
17474
17540
|
}
|
|
17475
|
-
async ViewMeasurement(measurementValue,
|
|
17541
|
+
async ViewMeasurement(measurementValue, _errorDiv, introDiv, _infoDiv, PlainTextDiv, HashedPlainTextDiv, PublicKeyDiv, SignatureExpectedDiv, SignatureCheckDiv) {
|
|
17476
17542
|
if (measurementValue.measurement?.chargingSession === void 0)
|
|
17477
17543
|
return new Error("Invalid measurement!");
|
|
17478
17544
|
const chargingSession = measurementValue.measurement.chargingSession;
|
|
@@ -17480,8 +17546,8 @@ var ChargePointCrypt01 = class extends ACrypt {
|
|
|
17480
17546
|
const algorithmName = typeof chargingSession.publicKey?.algorithm === "object" ? chargingSession.publicKey.algorithm.name : chargingSession.publicKey?.algorithm ?? "";
|
|
17481
17547
|
const algorithmType = typeof chargingSession.publicKey?.type === "object" ? chargingSession.publicKey.type.name : chargingSession.publicKey?.type;
|
|
17482
17548
|
introDiv.innerHTML = this.chargy.GetLocalizedMessage("The following data of the charging session is relevant for metrological and legal metrological purposes and therefore part of the digital signature").replace("{methodName}", "ChargePointCrypt01").replace("{cryptoAlgorithm}", algorithmName);
|
|
17483
|
-
if (PlainTextDiv.parentElement
|
|
17484
|
-
PlainTextDiv.parentElement.children
|
|
17549
|
+
if (PlainTextDiv.parentElement) {
|
|
17550
|
+
getArrayLikeElement(PlainTextDiv.parentElement.children, 0, "Missing plain text header").innerHTML = "Plain text (secrrct)";
|
|
17485
17551
|
}
|
|
17486
17552
|
PlainTextDiv.innerText = atob(chargingSession.original ?? "");
|
|
17487
17553
|
PlainTextDiv.style.fontFamily = "monospace";
|
|
@@ -17503,22 +17569,23 @@ var ChargePointCrypt01 = class extends ACrypt {
|
|
|
17503
17569
|
hashInfo = "(SHA512, 512 Bits, hex)";
|
|
17504
17570
|
break;
|
|
17505
17571
|
}
|
|
17506
|
-
if (HashedPlainTextDiv.parentElement
|
|
17507
|
-
HashedPlainTextDiv.parentElement.children
|
|
17572
|
+
if (HashedPlainTextDiv.parentElement) {
|
|
17573
|
+
getArrayLikeElement(HashedPlainTextDiv.parentElement.children, 0, "Missing hashed plain text header").innerHTML = "Hashed plain text " + hashInfo;
|
|
17508
17574
|
}
|
|
17509
17575
|
HashedPlainTextDiv.innerHTML = chargingSession.hashValue?.match(/.{1,8}/g)?.join(" ") ?? "0x00000000000000000000000000000000000";
|
|
17510
17576
|
if (chargingSession.publicKey != null) {
|
|
17511
|
-
if (PublicKeyDiv.parentElement
|
|
17512
|
-
PublicKeyDiv.parentElement.children
|
|
17577
|
+
if (PublicKeyDiv.parentElement) {
|
|
17578
|
+
getArrayLikeElement(PublicKeyDiv.parentElement.children, 0, "Missing public key header").innerHTML = "Public Key (" + (algorithmType != null && algorithmType.length > 0 ? algorithmType + ", " : "") + (algorithmName.length > 0 ? algorithmName + ", " : "") + "hex)";
|
|
17513
17579
|
}
|
|
17514
17580
|
PublicKeyDiv.innerHTML = chargingSession.publicKey.value.startsWith("04") ? '<span class="leadingFour">04</span> ' + (chargingSession.publicKey.value.substring(2).match(/.{1,8}/g)?.join(" ") ?? "") : chargingSession.publicKey.value.match(/.{1,8}/g)?.join(" ") ?? "";
|
|
17515
|
-
|
|
17516
|
-
|
|
17581
|
+
const publicKeySignatureContainer = PublicKeyDiv.parentElement?.children[3];
|
|
17582
|
+
if (publicKeySignatureContainer !== void 0) {
|
|
17583
|
+
publicKeySignatureContainer.innerHTML = "";
|
|
17517
17584
|
}
|
|
17518
17585
|
if (result.publicKeySignatures) {
|
|
17519
17586
|
for (const signature of result.publicKeySignatures) {
|
|
17520
17587
|
try {
|
|
17521
|
-
const signatureDiv =
|
|
17588
|
+
const signatureDiv = publicKeySignatureContainer?.appendChild(document.createElement("div"));
|
|
17522
17589
|
if (signatureDiv != null)
|
|
17523
17590
|
signatureDiv.innerHTML = await this.chargy.CheckMeterPublicKeySignature(
|
|
17524
17591
|
measurementValue.measurement.chargingSession.chargingStation,
|
|
@@ -17533,8 +17600,8 @@ var ChargePointCrypt01 = class extends ACrypt {
|
|
|
17533
17600
|
}
|
|
17534
17601
|
}
|
|
17535
17602
|
if (chargingSession.signature != null) {
|
|
17536
|
-
if (SignatureExpectedDiv.parentElement
|
|
17537
|
-
SignatureExpectedDiv.parentElement.children
|
|
17603
|
+
if (SignatureExpectedDiv.parentElement) {
|
|
17604
|
+
getArrayLikeElement(SignatureExpectedDiv.parentElement.children, 0, "Missing expected signature header").innerHTML = "Erwartete Signatur (secrrct.sign, rs, hex)";
|
|
17538
17605
|
}
|
|
17539
17606
|
if (typeof chargingSession.signature != "string")
|
|
17540
17607
|
SignatureExpectedDiv.innerHTML = "r: " + (chargingSession.signature.r?.toLowerCase().padStart(56, "0").match(/.{1,8}/g)?.join(" ") ?? "") + "<br />s: " + (chargingSession.signature.s?.toLowerCase().padStart(56, "0").match(/.{1,8}/g)?.join(" ") ?? "");
|
|
@@ -17566,6 +17633,7 @@ var ChargePointCrypt01 = class extends ACrypt {
|
|
|
17566
17633
|
break;
|
|
17567
17634
|
}
|
|
17568
17635
|
}
|
|
17636
|
+
return void 0;
|
|
17569
17637
|
}
|
|
17570
17638
|
};
|
|
17571
17639
|
|
|
@@ -17589,8 +17657,7 @@ function IsAChargeTransparencyRecord(data) {
|
|
|
17589
17657
|
function IsASessionCryptoResult(data) {
|
|
17590
17658
|
if (!isMandatoryJSONObject(data))
|
|
17591
17659
|
return false;
|
|
17592
|
-
|
|
17593
|
-
return sessionCryptoResult.status !== void 0;
|
|
17660
|
+
return true;
|
|
17594
17661
|
}
|
|
17595
17662
|
function CloneCTR(CTR) {
|
|
17596
17663
|
const clonedCTR = JSON.parse(JSON.stringify(CTR));
|
|
@@ -17769,8 +17836,10 @@ async function imageDataFromNodeCanvas(data) {
|
|
|
17769
17836
|
if (!isCanvasModule(canvasLib))
|
|
17770
17837
|
return void 0;
|
|
17771
17838
|
const image = await canvasLib.loadImage(import_buffer.Buffer.from(toUint8Array(data)));
|
|
17772
|
-
const
|
|
17773
|
-
const
|
|
17839
|
+
const naturalWidth = image.naturalWidth ?? 0;
|
|
17840
|
+
const naturalHeight = image.naturalHeight ?? 0;
|
|
17841
|
+
const width = naturalWidth > 0 ? naturalWidth : image.width;
|
|
17842
|
+
const height = naturalHeight > 0 ? naturalHeight : image.height;
|
|
17774
17843
|
if (width <= 0 || height <= 0)
|
|
17775
17844
|
return void 0;
|
|
17776
17845
|
const canvas = canvasLib.createCanvas(width, height);
|
|
@@ -17841,22 +17910,22 @@ async function importOptionalNodeModule(moduleName) {
|
|
|
17841
17910
|
}
|
|
17842
17911
|
async function readQRCodeTextFromImage(data, mimeType) {
|
|
17843
17912
|
const imageDataSources = typeof document === "undefined" ? [
|
|
17844
|
-
() => imageDataFromNodeCanvas(data),
|
|
17845
|
-
() => imageDataFromPNGOrJPEG(data, mimeType),
|
|
17846
|
-
() => imageDataFromBrowserCanvas(data, mimeType),
|
|
17847
|
-
() => imageDataFromBrowserImageElement(data, mimeType)
|
|
17913
|
+
async () => imageDataFromNodeCanvas(data),
|
|
17914
|
+
async () => imageDataFromPNGOrJPEG(data, mimeType),
|
|
17915
|
+
async () => imageDataFromBrowserCanvas(data, mimeType),
|
|
17916
|
+
async () => imageDataFromBrowserImageElement(data, mimeType)
|
|
17848
17917
|
] : [
|
|
17849
|
-
() => imageDataFromBrowserCanvas(data, mimeType),
|
|
17850
|
-
() => imageDataFromBrowserImageElement(data, mimeType),
|
|
17851
|
-
() => imageDataFromNodeCanvas(data),
|
|
17852
|
-
() => imageDataFromPNGOrJPEG(data, mimeType)
|
|
17918
|
+
async () => imageDataFromBrowserCanvas(data, mimeType),
|
|
17919
|
+
async () => imageDataFromBrowserImageElement(data, mimeType),
|
|
17920
|
+
async () => imageDataFromNodeCanvas(data),
|
|
17921
|
+
async () => imageDataFromPNGOrJPEG(data, mimeType)
|
|
17853
17922
|
];
|
|
17854
17923
|
for (const imageDataSource of imageDataSources) {
|
|
17855
17924
|
const imageData = await imageDataSource();
|
|
17856
17925
|
if (imageData == null)
|
|
17857
17926
|
continue;
|
|
17858
17927
|
const qrText = readQRCodeTextFromImageData(imageData);
|
|
17859
|
-
if (qrText && qrText.length > 0)
|
|
17928
|
+
if (qrText != null && qrText.length > 0)
|
|
17860
17929
|
return qrText;
|
|
17861
17930
|
}
|
|
17862
17931
|
return void 0;
|
|
@@ -17869,7 +17938,7 @@ function readQRCodeTextFromImageData(imageData) {
|
|
|
17869
17938
|
{ inversionAttempts: "attemptBoth" }
|
|
17870
17939
|
);
|
|
17871
17940
|
const qrText = qrCode?.data.trim();
|
|
17872
|
-
return qrText && qrText.length > 0 ? qrText : void 0;
|
|
17941
|
+
return qrText != null && qrText.length > 0 ? qrText : void 0;
|
|
17873
17942
|
}
|
|
17874
17943
|
|
|
17875
17944
|
// src/pdfjs/browser.ts
|
|
@@ -17890,10 +17959,15 @@ var validationRules_default = {
|
|
|
17890
17959
|
}
|
|
17891
17960
|
}
|
|
17892
17961
|
};
|
|
17962
|
+
function isPdfAttachment(value) {
|
|
17963
|
+
if (!isMandatoryJSONObject(value))
|
|
17964
|
+
return false;
|
|
17965
|
+
return typeof value["filename"] === "string" && (value["content"] instanceof ArrayBuffer || ArrayBuffer.isView(value["content"]));
|
|
17966
|
+
}
|
|
17893
17967
|
var Chargy = class {
|
|
17894
17968
|
//#region Data
|
|
17895
17969
|
i18n;
|
|
17896
|
-
|
|
17970
|
+
uiLanguages;
|
|
17897
17971
|
elliptic;
|
|
17898
17972
|
moment;
|
|
17899
17973
|
asn1;
|
|
@@ -17906,14 +17980,12 @@ var Chargy = class {
|
|
|
17906
17980
|
EVSEs = new Array();
|
|
17907
17981
|
meters = new Array();
|
|
17908
17982
|
chargingSessions = new Array();
|
|
17909
|
-
eMobilityProviders = new Array();
|
|
17910
|
-
mediationServices = new Array();
|
|
17911
17983
|
currentCTR = {};
|
|
17912
17984
|
internalCTR = {};
|
|
17913
17985
|
//#endregion
|
|
17914
|
-
constructor(i18n,
|
|
17986
|
+
constructor(i18n, UILanguages, elliptic, moment2, asn1, base32Decode, ShowPKIDetails, validationRules = validationRules_default) {
|
|
17915
17987
|
this.i18n = i18n;
|
|
17916
|
-
this.
|
|
17988
|
+
this.uiLanguages = this.NormalizeUILanguages(UILanguages);
|
|
17917
17989
|
this.elliptic = elliptic;
|
|
17918
17990
|
this.moment = moment2;
|
|
17919
17991
|
this.asn1 = asn1;
|
|
@@ -17921,11 +17993,41 @@ var Chargy = class {
|
|
|
17921
17993
|
this.showPKIDetails = ShowPKIDetails;
|
|
17922
17994
|
this.validationRules = validationRules;
|
|
17923
17995
|
}
|
|
17924
|
-
|
|
17925
|
-
this.
|
|
17996
|
+
SetUILanguages(UILanguages) {
|
|
17997
|
+
this.uiLanguages = this.NormalizeUILanguages(UILanguages);
|
|
17998
|
+
}
|
|
17999
|
+
NormalizeUILanguages(UILanguages) {
|
|
18000
|
+
const languages = new Array();
|
|
18001
|
+
for (const language of UILanguages) {
|
|
18002
|
+
const normalized = language.trim();
|
|
18003
|
+
if (normalized.length > 0 && !languages.includes(normalized)) {
|
|
18004
|
+
languages.push(normalized);
|
|
18005
|
+
}
|
|
18006
|
+
}
|
|
18007
|
+
return languages.length > 0 ? languages : ["en"];
|
|
18008
|
+
}
|
|
18009
|
+
FindBestMultilanguageText(Text) {
|
|
18010
|
+
for (const language of this.uiLanguages) {
|
|
18011
|
+
const localLanguage = Text[language];
|
|
18012
|
+
if (localLanguage !== void 0)
|
|
18013
|
+
return localLanguage;
|
|
18014
|
+
}
|
|
18015
|
+
const english = Text["en"];
|
|
18016
|
+
if (english !== void 0)
|
|
18017
|
+
return english;
|
|
18018
|
+
return Object.values(Text).find((value) => value !== void 0);
|
|
18019
|
+
}
|
|
18020
|
+
CompleteMultilanguageText(Text, fallbackText) {
|
|
18021
|
+
const result = {
|
|
18022
|
+
...Text ?? {}
|
|
18023
|
+
};
|
|
18024
|
+
const fallback = this.FindBestMultilanguageText(result) ?? fallbackText;
|
|
18025
|
+
for (const language of this.uiLanguages)
|
|
18026
|
+
result[language] ??= fallback;
|
|
18027
|
+
return result;
|
|
17926
18028
|
}
|
|
17927
18029
|
PublicKeyIdFromFileName(fileName) {
|
|
17928
|
-
return (fileName.
|
|
18030
|
+
return (fileName.includes(".") ? fileName.substring(0, fileName.indexOf(".")) : fileName).replace(/[-_]?public[-_]?key/i, "");
|
|
17929
18031
|
}
|
|
17930
18032
|
TryToParseDERPublicKey(keyId, publicKeyBuffer) {
|
|
17931
18033
|
const ASN1_OIDs = this.asn1.define("OIDs", function() {
|
|
@@ -18101,27 +18203,36 @@ var Chargy = class {
|
|
|
18101
18203
|
GetLocalizedMessage(Text) {
|
|
18102
18204
|
const multiLanguage = this.i18n[Text];
|
|
18103
18205
|
if (multiLanguage !== void 0) {
|
|
18104
|
-
const
|
|
18105
|
-
if (
|
|
18106
|
-
return
|
|
18107
|
-
const english = multiLanguage["en"];
|
|
18108
|
-
if (english !== void 0)
|
|
18109
|
-
return english;
|
|
18206
|
+
const localizedMessage = this.FindBestMultilanguageText(multiLanguage);
|
|
18207
|
+
if (localizedMessage !== void 0)
|
|
18208
|
+
return localizedMessage;
|
|
18110
18209
|
}
|
|
18111
18210
|
return Text;
|
|
18112
18211
|
}
|
|
18212
|
+
GetMultilanguageText(Text) {
|
|
18213
|
+
const multiLanguage = this.i18n[Text];
|
|
18214
|
+
return this.CompleteMultilanguageText(multiLanguage, Text);
|
|
18215
|
+
}
|
|
18113
18216
|
GetLocalizedMessageWithParameter(Text, Parameter) {
|
|
18114
18217
|
const multiLanguage = this.i18n[Text];
|
|
18115
18218
|
if (multiLanguage !== void 0) {
|
|
18116
|
-
const
|
|
18117
|
-
if (
|
|
18118
|
-
return
|
|
18119
|
-
const english = multiLanguage["en"];
|
|
18120
|
-
if (english !== void 0)
|
|
18121
|
-
return english.replace("%p", String(Parameter));
|
|
18219
|
+
const localizedMessage = this.FindBestMultilanguageText(multiLanguage);
|
|
18220
|
+
if (localizedMessage !== void 0)
|
|
18221
|
+
return localizedMessage.replace("%p", String(Parameter));
|
|
18122
18222
|
}
|
|
18123
18223
|
return Text.replace("%p", String(Parameter));
|
|
18124
18224
|
}
|
|
18225
|
+
GetMultilanguageTextWithParameter(Text, Parameter) {
|
|
18226
|
+
const multiLanguage = this.i18n[Text];
|
|
18227
|
+
const parameterizedText = {};
|
|
18228
|
+
if (multiLanguage !== void 0) {
|
|
18229
|
+
for (const [language, message] of Object.entries(multiLanguage)) {
|
|
18230
|
+
if (message !== void 0)
|
|
18231
|
+
parameterizedText[language] = message.replace("%p", String(Parameter));
|
|
18232
|
+
}
|
|
18233
|
+
}
|
|
18234
|
+
return this.CompleteMultilanguageText(parameterizedText, Text.replace("%p", String(Parameter)));
|
|
18235
|
+
}
|
|
18125
18236
|
//#endregion
|
|
18126
18237
|
//#region GetDevices...
|
|
18127
18238
|
GetChargingPool = (Id) => {
|
|
@@ -18272,7 +18383,7 @@ var Chargy = class {
|
|
|
18272
18383
|
if (compressedFiles.length == 0)
|
|
18273
18384
|
continue;
|
|
18274
18385
|
archiveFound = true;
|
|
18275
|
-
if (compressedFiles.length == 1
|
|
18386
|
+
if (compressedFiles.length == 1) {
|
|
18276
18387
|
expandedFileInfos.push({
|
|
18277
18388
|
name: FileInfo.name.substring(0, FileInfo.name.lastIndexOf(".")),
|
|
18278
18389
|
data: compressedFiles[0]?.data
|
|
@@ -18309,9 +18420,12 @@ var Chargy = class {
|
|
|
18309
18420
|
}
|
|
18310
18421
|
if (dataFile.length > 0 && signatureFile.length > 0) {
|
|
18311
18422
|
try {
|
|
18312
|
-
|
|
18313
|
-
|
|
18314
|
-
|
|
18423
|
+
const parsedCTRFile = JSON.parse(dataFile);
|
|
18424
|
+
if (!isMandatoryJSONObject(parsedCTRFile))
|
|
18425
|
+
throw new Error("Invalid chargepoint 'secrrct' JSON file!");
|
|
18426
|
+
CTRfile = parsedCTRFile;
|
|
18427
|
+
CTRfile["original"] = btoa(dataFile);
|
|
18428
|
+
CTRfile["signature"] = signatureFile;
|
|
18315
18429
|
expandedFileInfos.push({
|
|
18316
18430
|
name: FileInfo.name,
|
|
18317
18431
|
data: new TextEncoder().encode(JSON.stringify(CTRfile))
|
|
@@ -18354,7 +18468,7 @@ var Chargy = class {
|
|
|
18354
18468
|
async extractArchive(fileName, data, mimeType) {
|
|
18355
18469
|
const archiveData = this.toUint8Array(data);
|
|
18356
18470
|
if (mimeType === "application/zip")
|
|
18357
|
-
return
|
|
18471
|
+
return this.extractZipArchive(archiveData);
|
|
18358
18472
|
if (mimeType === "application/x-tar")
|
|
18359
18473
|
return this.extractTarArchive(archiveData);
|
|
18360
18474
|
if (mimeType === "application/gzip") {
|
|
@@ -18393,7 +18507,7 @@ var Chargy = class {
|
|
|
18393
18507
|
break;
|
|
18394
18508
|
const prefix = this.readTarString(header, 345, 155);
|
|
18395
18509
|
const path = prefix.length > 0 ? prefix + "/" + name : name;
|
|
18396
|
-
const typeFlag = String.fromCharCode(header
|
|
18510
|
+
const typeFlag = String.fromCharCode(getArrayElement(header, 156, "Missing tar header type flag"));
|
|
18397
18511
|
const dataStart = offset + 512;
|
|
18398
18512
|
const dataEnd = dataStart + size;
|
|
18399
18513
|
if (dataEnd > data.byteLength)
|
|
@@ -18493,7 +18607,7 @@ var Chargy = class {
|
|
|
18493
18607
|
async DetectAndConvertContentFormat(FileInfos) {
|
|
18494
18608
|
if (FileInfos.length == 0) return {
|
|
18495
18609
|
status: "NoChargeTransparencyRecordsFound" /* NoChargeTransparencyRecordsFound */,
|
|
18496
|
-
message: this.
|
|
18610
|
+
message: this.GetMultilanguageText("No charge transparency records found!"),
|
|
18497
18611
|
certainty: 0
|
|
18498
18612
|
};
|
|
18499
18613
|
let expandedFiles = new Array();
|
|
@@ -18502,45 +18616,48 @@ var Chargy = class {
|
|
|
18502
18616
|
for (const fileInfo of FileInfos) {
|
|
18503
18617
|
if (fileInfo.type === "application/pdf" || fileInfo.name.endsWith(".pdf")) {
|
|
18504
18618
|
const pdfjsLib = await importPdfJs();
|
|
18505
|
-
const pdfDocument = fileInfo.data ? await pdfjsLib.getDocument({ data: fileInfo.data }).promise : fileInfo.path ? await pdfjsLib.getDocument({ url: fileInfo.path }).promise : null;
|
|
18506
|
-
if (pdfDocument) {
|
|
18619
|
+
const pdfDocument = fileInfo.data ? await pdfjsLib.getDocument({ data: fileInfo.data }).promise : fileInfo.path != null && fileInfo.path.length > 0 ? await pdfjsLib.getDocument({ url: fileInfo.path }).promise : null;
|
|
18620
|
+
if (pdfDocument !== null) {
|
|
18507
18621
|
try {
|
|
18508
|
-
const
|
|
18509
|
-
|
|
18510
|
-
|
|
18511
|
-
|
|
18512
|
-
|
|
18513
|
-
|
|
18514
|
-
|
|
18515
|
-
|
|
18516
|
-
|
|
18517
|
-
|
|
18518
|
-
|
|
18519
|
-
|
|
18520
|
-
|
|
18521
|
-
|
|
18522
|
-
|
|
18523
|
-
|
|
18524
|
-
|
|
18525
|
-
|
|
18526
|
-
|
|
18527
|
-
|
|
18528
|
-
|
|
18529
|
-
|
|
18530
|
-
|
|
18531
|
-
|
|
18532
|
-
|
|
18533
|
-
|
|
18534
|
-
|
|
18535
|
-
|
|
18536
|
-
|
|
18537
|
-
|
|
18538
|
-
|
|
18539
|
-
|
|
18540
|
-
|
|
18541
|
-
|
|
18542
|
-
|
|
18543
|
-
|
|
18622
|
+
const attachmentsUnknown = await pdfDocument.getAttachments();
|
|
18623
|
+
if (isMandatoryJSONObject(attachmentsUnknown))
|
|
18624
|
+
Object.values(attachmentsUnknown).forEach((attachmentUnknown) => {
|
|
18625
|
+
if (!isPdfAttachment(attachmentUnknown))
|
|
18626
|
+
return;
|
|
18627
|
+
const attachment = attachmentUnknown;
|
|
18628
|
+
if (attachment.filename.endsWith(".chargy"))
|
|
18629
|
+
expandedFiles.push({
|
|
18630
|
+
name: attachment.filename,
|
|
18631
|
+
path: FileInfos[0]?.path,
|
|
18632
|
+
type: "application/chargy",
|
|
18633
|
+
data: attachment.content,
|
|
18634
|
+
info: "A CHARGY file extracted from a PDF/A-3 or newer attachment"
|
|
18635
|
+
});
|
|
18636
|
+
else if (attachment.filename.endsWith(".xml"))
|
|
18637
|
+
expandedFiles.push({
|
|
18638
|
+
name: attachment.filename,
|
|
18639
|
+
path: FileInfos[0]?.path,
|
|
18640
|
+
type: "application/xml",
|
|
18641
|
+
data: attachment.content,
|
|
18642
|
+
info: "A XML file extracted from a PDF/A-3 or newer attachment"
|
|
18643
|
+
});
|
|
18644
|
+
else if (attachment.filename.endsWith(".json"))
|
|
18645
|
+
expandedFiles.push({
|
|
18646
|
+
name: attachment.filename,
|
|
18647
|
+
path: FileInfos[0]?.path,
|
|
18648
|
+
type: "application/json",
|
|
18649
|
+
data: attachment.content,
|
|
18650
|
+
info: "A JSON file extracted from a PDF/A-3 or newer attachment"
|
|
18651
|
+
});
|
|
18652
|
+
else if (attachment.filename.endsWith(".csv"))
|
|
18653
|
+
expandedFiles.push({
|
|
18654
|
+
name: attachment.filename,
|
|
18655
|
+
path: FileInfos[0]?.path,
|
|
18656
|
+
type: "text/csv",
|
|
18657
|
+
data: attachment.content,
|
|
18658
|
+
info: "A CSV file extracted from a PDF/A-3 or newer attachment"
|
|
18659
|
+
});
|
|
18660
|
+
});
|
|
18544
18661
|
} catch (error) {
|
|
18545
18662
|
console.error(`Error extracting PDF/A-3 attachments: ${String(error)}`);
|
|
18546
18663
|
}
|
|
@@ -18586,7 +18703,7 @@ var Chargy = class {
|
|
|
18586
18703
|
break;
|
|
18587
18704
|
}
|
|
18588
18705
|
processedFile.result = await new SAFEXML(this).tryToParseSAFEXML(XMLDocument);
|
|
18589
|
-
if (processedFile.result.status && processedFile.result.status !== "Unvalidated" /* Unvalidated */ && getElementsByLocalName(XMLDocument, "chargingStation").length === 0) {
|
|
18706
|
+
if (processedFile.result.status != null && processedFile.result.status !== "Unvalidated" /* Unvalidated */ && getElementsByLocalName(XMLDocument, "chargingStation").length === 0) {
|
|
18590
18707
|
processedFile.result = new XMLContainer(this).tryToParseXMLContainer(XMLDocument);
|
|
18591
18708
|
}
|
|
18592
18709
|
break;
|
|
@@ -18603,7 +18720,7 @@ var Chargy = class {
|
|
|
18603
18720
|
} catch (exception) {
|
|
18604
18721
|
processedFile.result = {
|
|
18605
18722
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
18606
|
-
message: this.
|
|
18723
|
+
message: this.GetMultilanguageText("UnknownOrInvalidXMLChargeTransparencyFormat"),
|
|
18607
18724
|
exception,
|
|
18608
18725
|
certainty: 0
|
|
18609
18726
|
};
|
|
@@ -18643,7 +18760,7 @@ var Chargy = class {
|
|
|
18643
18760
|
} catch (exception) {
|
|
18644
18761
|
processedFile.result = {
|
|
18645
18762
|
status: "InvalidPublicKey" /* InvalidPublicKey */,
|
|
18646
|
-
message: this.
|
|
18763
|
+
message: this.GetMultilanguageText("UnknownOrInvalidPublicKeyFormat"),
|
|
18647
18764
|
exception,
|
|
18648
18765
|
certainty: 0
|
|
18649
18766
|
};
|
|
@@ -18657,7 +18774,7 @@ var Chargy = class {
|
|
|
18657
18774
|
} catch (exception) {
|
|
18658
18775
|
processedFile.result = {
|
|
18659
18776
|
status: "InvalidPublicKey" /* InvalidPublicKey */,
|
|
18660
|
-
message: this.
|
|
18777
|
+
message: this.GetMultilanguageText("UnknownOrInvalidPublicKeyFormat"),
|
|
18661
18778
|
exception,
|
|
18662
18779
|
certainty: 0
|
|
18663
18780
|
};
|
|
@@ -18670,8 +18787,7 @@ var Chargy = class {
|
|
|
18670
18787
|
if (isMandatoryJSONObject(JSONContent)) {
|
|
18671
18788
|
const JSONContext = JSONContent["@context"];
|
|
18672
18789
|
if (IsAChargeTransparencyLiveLink(JSONContent)) {
|
|
18673
|
-
|
|
18674
|
-
JSONContent.timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
18790
|
+
JSONContent.timestamp ??= (/* @__PURE__ */ new Date()).toISOString();
|
|
18675
18791
|
processedFile.result = JSONContent;
|
|
18676
18792
|
} else if (isMandatoryString(JSONContext)) {
|
|
18677
18793
|
if (JSONContext.startsWith("https://open.charging.cloud/contexts/CTR+json"))
|
|
@@ -18706,7 +18822,7 @@ var Chargy = class {
|
|
|
18706
18822
|
} catch (exception) {
|
|
18707
18823
|
processedFile.result = {
|
|
18708
18824
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
18709
|
-
message: this.
|
|
18825
|
+
message: this.GetMultilanguageText("UnknownOrInvalidJSONChargeTransparencyFormat"),
|
|
18710
18826
|
exception,
|
|
18711
18827
|
certainty: 0
|
|
18712
18828
|
};
|
|
@@ -18715,25 +18831,18 @@ var Chargy = class {
|
|
|
18715
18831
|
processedFiles.push(processedFile);
|
|
18716
18832
|
}
|
|
18717
18833
|
if (processedFiles.length == 1) {
|
|
18718
|
-
const processedFile = processedFiles
|
|
18719
|
-
if (processedFile)
|
|
18720
|
-
|
|
18721
|
-
|
|
18722
|
-
if (IsAChargeTransparencyLiveLink(processedFile.result))
|
|
18723
|
-
return processedFile.result;
|
|
18724
|
-
if (IsAPublicKeyLookup(processedFile.result))
|
|
18725
|
-
return {
|
|
18726
|
-
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
18727
|
-
message: this.GetLocalizedMessage("UnknownOrInvalidChargeTransparencyRecord"),
|
|
18728
|
-
certainty: 0
|
|
18729
|
-
};
|
|
18834
|
+
const processedFile = getFirstArrayElement(processedFiles, "Missing processed file");
|
|
18835
|
+
if (IsAChargeTransparencyRecord(processedFile.result))
|
|
18836
|
+
return this.processChargeTransparencyRecord(processedFile.result);
|
|
18837
|
+
if (IsAChargeTransparencyLiveLink(processedFile.result))
|
|
18730
18838
|
return processedFile.result;
|
|
18731
|
-
|
|
18732
|
-
|
|
18733
|
-
|
|
18734
|
-
|
|
18735
|
-
|
|
18736
|
-
|
|
18839
|
+
if (IsAPublicKeyLookup(processedFile.result))
|
|
18840
|
+
return {
|
|
18841
|
+
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
18842
|
+
message: this.GetMultilanguageText("UnknownOrInvalidChargeTransparencyRecord"),
|
|
18843
|
+
certainty: 0
|
|
18844
|
+
};
|
|
18845
|
+
return processedFile.result;
|
|
18737
18846
|
} else if (processedFiles.length > 1) {
|
|
18738
18847
|
const mergedCTR = {
|
|
18739
18848
|
"@id": "",
|
|
@@ -18747,14 +18856,12 @@ var Chargy = class {
|
|
|
18747
18856
|
mergedCTR["@id"] = processedFileResult["@id"];
|
|
18748
18857
|
if (mergedCTR["@context"] === "")
|
|
18749
18858
|
mergedCTR["@context"] = processedFileResult["@context"];
|
|
18750
|
-
if (
|
|
18859
|
+
if (processedFileResult.begin != null && processedFileResult.begin.length > 0 && (mergedCTR.begin == null || mergedCTR.begin.length === 0 || mergedCTR.begin > processedFileResult.begin))
|
|
18751
18860
|
mergedCTR.begin = processedFileResult.begin;
|
|
18752
|
-
if (
|
|
18861
|
+
if (processedFileResult.end != null && processedFileResult.end.length > 0 && (mergedCTR.end == null || mergedCTR.end.length === 0 || mergedCTR.end < processedFileResult.end))
|
|
18753
18862
|
mergedCTR.end = processedFileResult.end;
|
|
18754
|
-
|
|
18755
|
-
|
|
18756
|
-
if (!mergedCTR.contract)
|
|
18757
|
-
mergedCTR.contract = processedFileResult.contract;
|
|
18863
|
+
mergedCTR.description ??= processedFileResult.description;
|
|
18864
|
+
mergedCTR.contract ??= processedFileResult.contract;
|
|
18758
18865
|
if (!mergedCTR.chargingStationOperators)
|
|
18759
18866
|
mergedCTR.chargingStationOperators = processedFileResult.chargingStationOperators;
|
|
18760
18867
|
else if (processedFileResult.chargingStationOperators)
|
|
@@ -18786,17 +18893,14 @@ var Chargy = class {
|
|
|
18786
18893
|
for (const mediationService of processedFileResult.mediationServices)
|
|
18787
18894
|
mergedCTR.mediationServices.push(mediationService);
|
|
18788
18895
|
} else if (IsAPublicKeyInfo(processedFileResult)) {
|
|
18789
|
-
|
|
18790
|
-
mergedCTR.publicKeys = new Array();
|
|
18896
|
+
mergedCTR.publicKeys ??= new Array();
|
|
18791
18897
|
mergedCTR.publicKeys.push(processedFileResult);
|
|
18792
18898
|
} else if (IsAPublicKeyLookup(processedFileResult)) {
|
|
18793
|
-
|
|
18794
|
-
mergedCTR.publicKeys = new Array();
|
|
18899
|
+
mergedCTR.publicKeys ??= new Array();
|
|
18795
18900
|
for (const publicKey of processedFileResult.publicKeys)
|
|
18796
18901
|
mergedCTR.publicKeys.push(publicKey);
|
|
18797
18902
|
} else {
|
|
18798
|
-
|
|
18799
|
-
mergedCTR.invalidDataSets = new Array();
|
|
18903
|
+
mergedCTR.invalidDataSets ??= new Array();
|
|
18800
18904
|
mergedCTR.invalidDataSets.push(processedFile);
|
|
18801
18905
|
}
|
|
18802
18906
|
}
|
|
@@ -18805,7 +18909,7 @@ var Chargy = class {
|
|
|
18805
18909
|
}
|
|
18806
18910
|
return {
|
|
18807
18911
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
18808
|
-
message: this.
|
|
18912
|
+
message: this.GetMultilanguageText("No charge transparency records found!"),
|
|
18809
18913
|
certainty: 0
|
|
18810
18914
|
};
|
|
18811
18915
|
}
|
|
@@ -18815,7 +18919,7 @@ var Chargy = class {
|
|
|
18815
18919
|
if (!IsAChargeTransparencyRecord(CTR))
|
|
18816
18920
|
return {
|
|
18817
18921
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
18818
|
-
message: this.
|
|
18922
|
+
message: this.GetMultilanguageText("UnknownOrInvalidJSONChargeTransparencyFormat"),
|
|
18819
18923
|
certainty: 0
|
|
18820
18924
|
};
|
|
18821
18925
|
this.chargingStationOperators = [];
|
|
@@ -18824,8 +18928,6 @@ var Chargy = class {
|
|
|
18824
18928
|
this.EVSEs = [];
|
|
18825
18929
|
this.meters = [];
|
|
18826
18930
|
this.chargingSessions = [];
|
|
18827
|
-
this.eMobilityProviders = [];
|
|
18828
|
-
this.mediationServices = [];
|
|
18829
18931
|
try {
|
|
18830
18932
|
this.internalCTR = CloneCTR(CTR);
|
|
18831
18933
|
this.currentCTR = CTR;
|
|
@@ -18940,7 +19042,7 @@ var Chargy = class {
|
|
|
18940
19042
|
} catch (exception) {
|
|
18941
19043
|
return {
|
|
18942
19044
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
18943
|
-
message: "Exception occured: " + (exception instanceof Error ? exception.message : String(exception)),
|
|
19045
|
+
message: this.GetMultilanguageText("Exception occured: " + (exception instanceof Error ? exception.message : String(exception))),
|
|
18944
19046
|
certainty: 0
|
|
18945
19047
|
};
|
|
18946
19048
|
}
|
|
@@ -18952,9 +19054,9 @@ var Chargy = class {
|
|
|
18952
19054
|
if (measurement.name !== "ENERGY_TOTAL" || measurement.values.length < 2) {
|
|
18953
19055
|
continue;
|
|
18954
19056
|
}
|
|
18955
|
-
const firstValue2 = measurement.values
|
|
18956
|
-
const lastValue = measurement.values
|
|
18957
|
-
if (firstValue2
|
|
19057
|
+
const firstValue2 = measurement.values.at(0);
|
|
19058
|
+
const lastValue = measurement.values.at(-1);
|
|
19059
|
+
if (firstValue2 === void 0 || lastValue === void 0) {
|
|
18958
19060
|
continue;
|
|
18959
19061
|
}
|
|
18960
19062
|
const firstValueKWh = this.measurementValueInKWh(measurement, firstValue2);
|
|
@@ -19071,7 +19173,7 @@ var Chargy = class {
|
|
|
19071
19173
|
default:
|
|
19072
19174
|
verificationResult2 = {
|
|
19073
19175
|
status: "UnknownSessionFormat" /* UnknownSessionFormat */,
|
|
19074
|
-
message: this.
|
|
19176
|
+
message: this.GetMultilanguageText("UnknownOrInvalidChargingSessionFormat"),
|
|
19075
19177
|
certainty: 0
|
|
19076
19178
|
};
|
|
19077
19179
|
break;
|
|
@@ -19081,7 +19183,7 @@ var Chargy = class {
|
|
|
19081
19183
|
chargingSession.ctr,
|
|
19082
19184
|
{
|
|
19083
19185
|
level: this.getChargingSessionTotalEnergyWarningLevel(),
|
|
19084
|
-
message: this.
|
|
19186
|
+
message: this.GetMultilanguageText("InplausibleTotalEnergyMeasurementWarning")
|
|
19085
19187
|
}
|
|
19086
19188
|
);
|
|
19087
19189
|
return {
|
|
@@ -19103,14 +19205,12 @@ var Chargy = class {
|
|
|
19103
19205
|
mergedCTR["@id"] = ctr["@id"];
|
|
19104
19206
|
if (mergedCTR["@context"] === "")
|
|
19105
19207
|
mergedCTR["@context"] = ctr["@context"];
|
|
19106
|
-
if (
|
|
19208
|
+
if (ctr.begin != null && ctr.begin.length > 0 && (mergedCTR.begin == null || mergedCTR.begin.length === 0 || mergedCTR.begin > ctr.begin))
|
|
19107
19209
|
mergedCTR.begin = ctr.begin;
|
|
19108
|
-
if (
|
|
19210
|
+
if (ctr.end != null && ctr.end.length > 0 && (mergedCTR.end == null || mergedCTR.end.length === 0 || mergedCTR.end < ctr.end))
|
|
19109
19211
|
mergedCTR.end = ctr.end;
|
|
19110
|
-
|
|
19111
|
-
|
|
19112
|
-
if (!mergedCTR.contract)
|
|
19113
|
-
mergedCTR.contract = ctr.contract;
|
|
19212
|
+
mergedCTR.description ??= ctr.description;
|
|
19213
|
+
mergedCTR.contract ??= ctr.contract;
|
|
19114
19214
|
if (!mergedCTR.chargingStationOperators)
|
|
19115
19215
|
mergedCTR.chargingStationOperators = ctr.chargingStationOperators;
|
|
19116
19216
|
else if (ctr.chargingStationOperators)
|
|
@@ -19147,7 +19247,7 @@ var Chargy = class {
|
|
|
19147
19247
|
};
|
|
19148
19248
|
|
|
19149
19249
|
// src/verificationResults.ts
|
|
19150
|
-
function toSessionVerificationResults(CTR, noRecordsMessage = "No charge transparency records found!") {
|
|
19250
|
+
function toSessionVerificationResults(CTR, noRecordsMessage = { "en": "No charge transparency records found!" }) {
|
|
19151
19251
|
const verificationResults = (CTR.chargingSessions ?? []).map((session) => session.verificationResult).filter(isISessionCryptoResult1);
|
|
19152
19252
|
if (verificationResults.length > 0)
|
|
19153
19253
|
return verificationResults;
|
|
@@ -19171,6 +19271,6 @@ buffer/index.js:
|
|
|
19171
19271
|
*)
|
|
19172
19272
|
*/
|
|
19173
19273
|
|
|
19174
|
-
export { ACrypt, Alfen, AlfenCrypt01, BSMCrypt01, CanonicalJSONError, ChargeIT, ChargePoint, ChargePointCrypt01, IChargeTransparencyLiveLink_exports as ChargeTransparencyLiveLink, ChargeTransparencyLiveLinkContext, IChargeTransparencyRecord_exports as ChargeTransparencyRecord, Chargy, chargyInterfaces_exports as ChargyInterfaces, Clone, CloneCTR, ConcatenateBuffers, CreateDiv, CreateDiv2, CryptoAlgorithms, CryptoHashAlgorithms, DayOfWeek, DisplayPrefixes, EMHCrypt01, GDFCrypt01, IECCurves, IEncoding, InformationRelevance, InformationRelevanceToString, IsAChargeTransparencyLiveLink, IsAChargeTransparencyRecord, IsAPublicKeyInfo, IsAPublicKeyLookup, IsASessionCryptoResult, IsNullOrEmpty, JSONSignatureVerificationStatus, MENNEKES_EDL40_OBIS, MENNEKES_EDL40_XMLNS, Mennekes, MennekesCrypt01, OBIS2Hex, OBIS2MeasurementName, OBIS_RegExpr, OCMF, OCMFTransactionTypes, OCMFv1_x, OCPI, PCDF, PCDFCrypt01, PCDFParseError, PCDFValidationError, PCDF_FIELD_ORDER, PCDF_PREFIX, ParseJSON_LD, PublicKeyFormats, IPublicKeyInfo_exports as PublicKeyInfo, SAFEXML, SessionVerificationResult, SetHex, SetInt8, SetText, SetText_withLength, SetTimestamp, SetTimestamp32, SetUInt32, SetUInt32_withCode, SetUInt64, SetUInt64D, SignMessage, SignatureFormats, TimeStatusTypes, UTC2human, VerificationResult, VerifyJSONMessageSignatures, WarningLevel, WhenNullOrEmpty, XMLContainer, asJSONArray, asJSONObject, asNumber, asString, buf2hex, buildMennekesSignatureData, bytesToHex2 as bytesToHex, canonicalJSONBytes, canonicalJSONStringify, cleanHex, closeFullscreen, createHexString, dateToMennekesLocalEpochSeconds, extractMennekesChargingProcesses, firstKey, firstValue, getDirectChildByLocalName, getDirectChildrenByLocalName, getElementsByLocalName, getInt16Bytes, getInt32Bytes, getInt64Bytes, getInt8Bytes, getTrimmedTextContent, hashFile, hex2bin, hex32, hexToArrayBuffer, hexToBytes, intFromBytes, isGeoLocation, isICryptoResult, isIFileInfo, isIPublicKeyXY, isISessionCryptoResult1, isISessionCryptoResult2, isJSONLDObject, isMandatoryArrayOfStrings, isMandatoryBoolean, isMandatoryDecimal, isMandatoryJSONArray, isMandatoryJSONObject, isMandatoryNumber, isMandatoryString, isMandatoryURL, isMultilanguageText, isOIDInfo, isObject, isOptionalArrayOfStrings, isOptionalDecimal, isOptionalJSONArray, isOptionalJSONArrayError, isOptionalJSONArrayOk, isOptionalJSONObject, isOptionalNumber, isOptionalString, isOptionalURL, isPCDFText, isString, isStringArray, isStringOrOIDInfo, isStringOrStringArray, jsonPrettyPrinter, measurementName2human, normalizePCDFPublicKeyHex, normalizeXMLText, openFullscreen, pad, parseAndVerifyJSONSignatures, parseDescription, parseHexString, parseMennekesXMLDocument, parseNumber, parseOBIS, parsePCDFDocument, parsePCDFPublicKey, parsePCDFSignature, parseUTC, readQRCodeTextFromImage, readQRCodeTextFromImageData, secp224k1, setUILocale, sha256, sha384, sha512, signJSONMessage, signMessage, stripPCDFControlCharacters, time2human, toArrayBuffer, toSessionVerificationResults, toUint8Array, unquotePCDFText, validatePCDFFields, verifyJSONMessageSignatureResults, verifyJSONMessageSignatures, verifyJSONSignature, verifyJSONSignatureResult, verifyPCDFDocument };
|
|
19274
|
+
export { ACrypt, Alfen, AlfenCrypt01, BSMCrypt01, CanonicalJSONError, ChargeIT, ChargePoint, ChargePointCrypt01, IChargeTransparencyLiveLink_exports as ChargeTransparencyLiveLink, ChargeTransparencyLiveLinkContext, IChargeTransparencyRecord_exports as ChargeTransparencyRecord, Chargy, chargyInterfaces_exports as ChargyInterfaces, Clone, CloneCTR, ConcatenateBuffers, CreateDiv, CreateDiv2, CreateError, CryptoAlgorithms, CryptoHashAlgorithms, DayOfWeek, DisplayPrefixes, EMHCrypt01, ErrorLevel, GDFCrypt01, IECCurves, IEncoding, InformationRelevance, InformationRelevanceToString, IsAChargeTransparencyLiveLink, IsAChargeTransparencyRecord, IsAPublicKeyInfo, IsAPublicKeyLookup, IsASessionCryptoResult, IsNullOrEmpty, JSONSignatureVerificationStatus, MENNEKES_EDL40_OBIS, MENNEKES_EDL40_XMLNS, Mennekes, MennekesCrypt01, OBIS2Hex, OBIS2MeasurementName, OBIS_RegExpr, OCMF, OCMFTransactionTypes, OCMFv1_x, OCPI, PCDF, PCDFCrypt01, PCDFParseError, PCDFValidationError, PCDF_FIELD_ORDER, PCDF_PREFIX, ParseJSON_LD, PublicKeyFormats, IPublicKeyInfo_exports as PublicKeyInfo, SAFEXML, SessionVerificationResult, SetHex, SetInt8, SetText, SetText_withLength, SetTimestamp, SetTimestamp32, SetUInt32, SetUInt32_withCode, SetUInt64, SetUInt64D, SignMessage, SignatureFormats, TimeStatusTypes, UTC2human, VerificationResult, VerifyJSONMessageSignatures, WarningLevel, WhenNullOrEmpty, XMLContainer, asJSONArray, asJSONObject, asNumber, asString, buf2hex, buildMennekesSignatureData, bytesToHex2 as bytesToHex, canonicalJSONBytes, canonicalJSONStringify, cleanHex, closeFullscreen, createHexString, dateToMennekesLocalEpochSeconds, extractMennekesChargingProcesses, firstKey, firstValue, getArrayElement, getArrayLikeElement, getDirectChildByLocalName, getDirectChildrenByLocalName, getElementsByLocalName, getFirstArrayElement, getInt16Bytes, getInt32Bytes, getInt64Bytes, getInt8Bytes, getLastArrayElement, getTrimmedTextContent, hashFile, hex2bin, hex32, hexToArrayBuffer, hexToBytes, intFromBytes, isGeoLocation, isICryptoResult, isIFileInfo, isIPublicKeyXY, isISessionCryptoResult1, isISessionCryptoResult2, isJSONLDObject, isMandatoryArrayOfStrings, isMandatoryBoolean, isMandatoryDecimal, isMandatoryJSONArray, isMandatoryJSONObject, isMandatoryNumber, isMandatoryString, isMandatoryURL, isMultilanguageText, isOIDInfo, isObject, isOptionalArrayOfStrings, isOptionalDecimal, isOptionalJSONArray, isOptionalJSONArrayError, isOptionalJSONArrayOk, isOptionalJSONObject, isOptionalNumber, isOptionalString, isOptionalURL, isPCDFText, isString, isStringArray, isStringOrOIDInfo, isStringOrStringArray, jsonPrettyPrinter, measurementName2human, normalizePCDFPublicKeyHex, normalizeXMLText, openFullscreen, pad, parseAndVerifyJSONSignatures, parseDescription, parseHexString, parseMennekesXMLDocument, parseNumber, parseOBIS, parsePCDFDocument, parsePCDFPublicKey, parsePCDFSignature, parseUTC, readQRCodeTextFromImage, readQRCodeTextFromImageData, secp224k1, setUILocale, sha256, sha384, sha512, signJSONMessage, signMessage, stripPCDFControlCharacters, time2human, toArrayBuffer, toSessionVerificationResults, toUint8Array, unquotePCDFText, validatePCDFFields, verifyJSONMessageSignatureResults, verifyJSONMessageSignatures, verifyJSONSignature, verifyJSONSignatureResult, verifyPCDFDocument };
|
|
19175
19275
|
//# sourceMappingURL=index.js.map
|
|
19176
19276
|
//# sourceMappingURL=index.js.map
|