@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/node/index.js
CHANGED
|
@@ -8005,9 +8005,7 @@ var secp224k1 = class {
|
|
|
8005
8005
|
N = BigInt("0x010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7");
|
|
8006
8006
|
// Number of points in the field
|
|
8007
8007
|
Acurve = BigInt(0);
|
|
8008
|
-
//
|
|
8009
|
-
Bcurve = BigInt(5);
|
|
8010
|
-
// These two are defined on the elliptic curve. y^2 = x^3 + Acurve * x + Bcurve
|
|
8008
|
+
// Defined on the elliptic curve. y^2 = x^3 + Acurve * x + 5
|
|
8011
8009
|
Gx = BigInt("0xA1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C");
|
|
8012
8010
|
Gy = BigInt("0x7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5");
|
|
8013
8011
|
GPoint = [this.Gx, this.Gy];
|
|
@@ -8104,16 +8102,19 @@ var secp224k1 = class {
|
|
|
8104
8102
|
address: this.modulo(publicKey[1], this.Two) == this.One ? "03" + Px : "02" + Px
|
|
8105
8103
|
};
|
|
8106
8104
|
}
|
|
8105
|
+
return void 0;
|
|
8107
8106
|
}
|
|
8108
8107
|
};
|
|
8109
8108
|
|
|
8110
8109
|
// src/interfaces/chargyInterfaces.ts
|
|
8111
8110
|
var chargyInterfaces_exports = {};
|
|
8112
8111
|
__export(chargyInterfaces_exports, {
|
|
8112
|
+
CreateError: () => CreateError,
|
|
8113
8113
|
CryptoAlgorithms: () => CryptoAlgorithms,
|
|
8114
8114
|
CryptoHashAlgorithms: () => CryptoHashAlgorithms,
|
|
8115
8115
|
DayOfWeek: () => DayOfWeek,
|
|
8116
8116
|
DisplayPrefixes: () => DisplayPrefixes,
|
|
8117
|
+
ErrorLevel: () => ErrorLevel,
|
|
8117
8118
|
IECCurves: () => IECCurves,
|
|
8118
8119
|
IEncoding: () => IEncoding,
|
|
8119
8120
|
InformationRelevance: () => InformationRelevance,
|
|
@@ -8217,14 +8218,26 @@ var WarningLevel = /* @__PURE__ */ ((WarningLevel2) => {
|
|
|
8217
8218
|
WarningLevel2["high"] = "high";
|
|
8218
8219
|
return WarningLevel2;
|
|
8219
8220
|
})(WarningLevel || {});
|
|
8221
|
+
var ErrorLevel = /* @__PURE__ */ ((ErrorLevel2) => {
|
|
8222
|
+
ErrorLevel2["low"] = "low";
|
|
8223
|
+
ErrorLevel2["medium"] = "medium";
|
|
8224
|
+
ErrorLevel2["high"] = "high";
|
|
8225
|
+
return ErrorLevel2;
|
|
8226
|
+
})(ErrorLevel || {});
|
|
8227
|
+
function CreateError(message, level = "high" /* high */) {
|
|
8228
|
+
return {
|
|
8229
|
+
level,
|
|
8230
|
+
message
|
|
8231
|
+
};
|
|
8232
|
+
}
|
|
8220
8233
|
function isISessionCryptoResult1(obj) {
|
|
8221
|
-
return
|
|
8234
|
+
return isObject(obj) && obj["status"] !== void 0;
|
|
8222
8235
|
}
|
|
8223
8236
|
function isISessionCryptoResult2(obj) {
|
|
8224
|
-
return
|
|
8237
|
+
return isObject(obj) && obj["status"] !== void 0 && obj["status"] !== "InvalidSessionFormat" /* InvalidSessionFormat */;
|
|
8225
8238
|
}
|
|
8226
8239
|
function isICryptoResult(obj) {
|
|
8227
|
-
return
|
|
8240
|
+
return isObject(obj) && obj["status"] !== void 0;
|
|
8228
8241
|
}
|
|
8229
8242
|
var InformationRelevance = /* @__PURE__ */ ((InformationRelevance2) => {
|
|
8230
8243
|
InformationRelevance2["Unknown"] = "Unknown";
|
|
@@ -8312,6 +8325,26 @@ function toArrayBuffer(data) {
|
|
|
8312
8325
|
function toUint8Array(data) {
|
|
8313
8326
|
return data instanceof Uint8Array ? data : new Uint8Array(data);
|
|
8314
8327
|
}
|
|
8328
|
+
function getArrayElement(values, index, message = "Missing array element") {
|
|
8329
|
+
const value = values[index];
|
|
8330
|
+
if (value === void 0)
|
|
8331
|
+
throw new Error(message + " at index " + index.toString());
|
|
8332
|
+
return value;
|
|
8333
|
+
}
|
|
8334
|
+
function getFirstArrayElement(values, message = "Missing first array element") {
|
|
8335
|
+
return getArrayElement(values, 0, message);
|
|
8336
|
+
}
|
|
8337
|
+
function getLastArrayElement(values, message = "Missing last array element") {
|
|
8338
|
+
return getArrayElement(values, values.length - 1, message);
|
|
8339
|
+
}
|
|
8340
|
+
function getArrayLikeElement(values, index, message = "Missing array-like element") {
|
|
8341
|
+
if (index < 0 || index >= values.length)
|
|
8342
|
+
throw new Error(message + " at index " + index.toString());
|
|
8343
|
+
const value = values[index];
|
|
8344
|
+
if (value === void 0)
|
|
8345
|
+
throw new Error(message + " at index " + index.toString());
|
|
8346
|
+
return value;
|
|
8347
|
+
}
|
|
8315
8348
|
function normalizeXMLText(xmlText) {
|
|
8316
8349
|
return (xmlText ?? "").replace(/^\uFEFF/, "").replace(/\r\n?/g, "\n").replace(/>\s+</g, "><").trim();
|
|
8317
8350
|
}
|
|
@@ -8323,15 +8356,16 @@ function getDirectChildByLocalName(parent, localName) {
|
|
|
8323
8356
|
}
|
|
8324
8357
|
function getTrimmedTextContent(element) {
|
|
8325
8358
|
const text = element?.textContent.trim();
|
|
8326
|
-
return text && text.length > 0 ? text : void 0;
|
|
8359
|
+
return text != null && text.length > 0 ? text : void 0;
|
|
8327
8360
|
}
|
|
8328
8361
|
function parseDescription(parent) {
|
|
8329
8362
|
const descriptions = getDirectChildrenByLocalName(parent, "description");
|
|
8330
8363
|
const textMap = {};
|
|
8331
8364
|
for (const description of descriptions) {
|
|
8332
|
-
const
|
|
8365
|
+
const languageAttribute = description.getAttribute("language")?.trim();
|
|
8366
|
+
const language = languageAttribute != null && languageAttribute.length > 0 ? languageAttribute : "und";
|
|
8333
8367
|
const text = description.textContent.trim();
|
|
8334
|
-
if (text)
|
|
8368
|
+
if (text.length > 0)
|
|
8335
8369
|
textMap[language] = text;
|
|
8336
8370
|
}
|
|
8337
8371
|
return Object.keys(textMap).length > 0 ? textMap : void 0;
|
|
@@ -8367,12 +8401,14 @@ function ParseJSON_LD(Text, _Context = "") {
|
|
|
8367
8401
|
function firstKey(obj) {
|
|
8368
8402
|
for (const a in obj)
|
|
8369
8403
|
return a;
|
|
8404
|
+
return void 0;
|
|
8370
8405
|
}
|
|
8371
8406
|
function firstValue(obj) {
|
|
8372
8407
|
if (obj == void 0)
|
|
8373
8408
|
return void 0;
|
|
8374
8409
|
for (const a in obj)
|
|
8375
8410
|
return obj[a];
|
|
8411
|
+
return void 0;
|
|
8376
8412
|
}
|
|
8377
8413
|
var uiLocale = typeof window !== "undefined" ? window.navigator.language : "de";
|
|
8378
8414
|
function setUILocale(locale) {
|
|
@@ -8405,14 +8441,17 @@ function parseOBIS(OBIS) {
|
|
|
8405
8441
|
return `${String(media)}-${String(channel)}:${String(indicator)}.${String(mode)}.${String(quantities)}*${String(storage)}`;
|
|
8406
8442
|
}
|
|
8407
8443
|
var OBIS_RegExpr = new RegExp("((\\d+)\\-)?((\\d+):)?((\\d+)\\.)(\\d+)(\\.(\\d+))?(\\*(\\d+))?");
|
|
8444
|
+
function optionalOBISMatchValue(value) {
|
|
8445
|
+
return value ?? "0";
|
|
8446
|
+
}
|
|
8408
8447
|
function OBIS2Hex(OBIS) {
|
|
8409
8448
|
const OBISElements = OBIS.match(OBIS_RegExpr);
|
|
8410
|
-
return OBISElements == null ? "000000000000" : parseInt(OBISElements[2]).toString(16).padStart(2, "0") + // optional A
|
|
8411
|
-
parseInt(OBISElements[4]).toString(16).padStart(2, "0") + // optional B
|
|
8412
|
-
parseInt(OBISElements[6]).toString(16).padStart(2, "0") + // mandatory C
|
|
8413
|
-
parseInt(OBISElements[7]).toString(16).padStart(2, "0") + // mandatory D
|
|
8414
|
-
parseInt(OBISElements[9]).toString(16).padStart(2, "0") + // optional E
|
|
8415
|
-
parseInt(OBISElements[11]).toString(16).padStart(2, "0");
|
|
8449
|
+
return OBISElements == null ? "000000000000" : parseInt(optionalOBISMatchValue(OBISElements[2])).toString(16).padStart(2, "0") + // optional A
|
|
8450
|
+
parseInt(optionalOBISMatchValue(OBISElements[4])).toString(16).padStart(2, "0") + // optional B
|
|
8451
|
+
parseInt(optionalOBISMatchValue(OBISElements[6])).toString(16).padStart(2, "0") + // mandatory C
|
|
8452
|
+
parseInt(optionalOBISMatchValue(OBISElements[7])).toString(16).padStart(2, "0") + // mandatory D
|
|
8453
|
+
parseInt(optionalOBISMatchValue(OBISElements[9])).toString(16).padStart(2, "0") + // optional E
|
|
8454
|
+
parseInt(optionalOBISMatchValue(OBISElements[11])).toString(16).padStart(2, "0");
|
|
8416
8455
|
}
|
|
8417
8456
|
function OBIS2MeasurementName(OBISString) {
|
|
8418
8457
|
switch (OBISString) {
|
|
@@ -8455,15 +8494,15 @@ function measurementName2human(In) {
|
|
|
8455
8494
|
}
|
|
8456
8495
|
}
|
|
8457
8496
|
function IsNullOrEmpty(value) {
|
|
8458
|
-
return
|
|
8497
|
+
return value == null || value.length === 0;
|
|
8459
8498
|
}
|
|
8460
8499
|
function WhenNullOrEmpty(value, replacement) {
|
|
8461
|
-
if (
|
|
8500
|
+
if (value == null || value.length === 0)
|
|
8462
8501
|
return replacement;
|
|
8463
8502
|
return value;
|
|
8464
8503
|
}
|
|
8465
8504
|
function hex2bin(hex, Reverse) {
|
|
8466
|
-
if (Reverse) {
|
|
8505
|
+
if (Reverse === true) {
|
|
8467
8506
|
const reversed = [];
|
|
8468
8507
|
for (let i = 0; i < hex.length; i += 2)
|
|
8469
8508
|
reversed.push(hex.substring(i, i + 2));
|
|
@@ -8577,7 +8616,7 @@ function SetHex(dv, hex, offset, reverse) {
|
|
|
8577
8616
|
const bytes = parseHexString(hex);
|
|
8578
8617
|
const buffer = new ArrayBuffer(bytes.length);
|
|
8579
8618
|
const tv = new DataView(buffer);
|
|
8580
|
-
if (reverse)
|
|
8619
|
+
if (reverse === true)
|
|
8581
8620
|
bytes.reverse();
|
|
8582
8621
|
for (let i = 0; i < bytes.length; i++) {
|
|
8583
8622
|
dv.setUint8(offset + i, bytes[i] ?? 0);
|
|
@@ -8626,7 +8665,7 @@ function SetUInt32(dv, value, offset, reverse) {
|
|
|
8626
8665
|
const bytes = getInt32Bytes(value);
|
|
8627
8666
|
const buffer = new ArrayBuffer(bytes.length);
|
|
8628
8667
|
const tv = new DataView(buffer);
|
|
8629
|
-
if (reverse)
|
|
8668
|
+
if (reverse === true)
|
|
8630
8669
|
bytes.reverse();
|
|
8631
8670
|
for (let i = 0; i < bytes.length; i++) {
|
|
8632
8671
|
dv.setUint8(offset + i, bytes[i] ?? 0);
|
|
@@ -8638,7 +8677,7 @@ function SetUInt64(dv, value, offset, reverse) {
|
|
|
8638
8677
|
const bytes = getInt64Bytes(value);
|
|
8639
8678
|
const buffer = new ArrayBuffer(bytes.length);
|
|
8640
8679
|
const tv = new DataView(buffer);
|
|
8641
|
-
if (reverse)
|
|
8680
|
+
if (reverse === true)
|
|
8642
8681
|
bytes.reverse();
|
|
8643
8682
|
for (let i = 0; i < bytes.length; i++) {
|
|
8644
8683
|
dv.setUint8(offset + i, bytes[i] ?? 0);
|
|
@@ -8670,7 +8709,7 @@ function SetUInt32_withCode(dv, value, scale, obis, offset, reverse) {
|
|
|
8670
8709
|
const obisBytes = getInt8Bytes(obis);
|
|
8671
8710
|
const buffer = new ArrayBuffer(valueBytes.length + 2);
|
|
8672
8711
|
const tv = new DataView(buffer);
|
|
8673
|
-
if (reverse)
|
|
8712
|
+
if (reverse === true)
|
|
8674
8713
|
valueBytes.reverse();
|
|
8675
8714
|
for (let i = 0; i < valueBytes.length; i++) {
|
|
8676
8715
|
dv.setUint8(offset + i, valueBytes[i] ?? 0);
|
|
@@ -8733,8 +8772,7 @@ function CreateDiv2(ParentDiv, ChildClassName, ChildAInnerHTML, ChildBInnerHTML)
|
|
|
8733
8772
|
return childDiv;
|
|
8734
8773
|
}
|
|
8735
8774
|
function pad(text, paddingValue) {
|
|
8736
|
-
|
|
8737
|
-
text = "";
|
|
8775
|
+
text ??= "";
|
|
8738
8776
|
return (text + Array(2 * paddingValue).join("0")).substring(0, 2 * paddingValue);
|
|
8739
8777
|
}
|
|
8740
8778
|
async function sha256(message) {
|
|
@@ -8880,7 +8918,7 @@ function jsonPrettyPrinter(value, KeyLookup) {
|
|
|
8880
8918
|
value,
|
|
8881
8919
|
0,
|
|
8882
8920
|
"",
|
|
8883
|
-
KeyLookup ?? ((
|
|
8921
|
+
KeyLookup ?? ((_path, key) => key)
|
|
8884
8922
|
);
|
|
8885
8923
|
}
|
|
8886
8924
|
function _jsonPrettyPrinter(value, indentLevel, path, keyLookup) {
|
|
@@ -8959,13 +8997,15 @@ var ACrypt = class {
|
|
|
8959
8997
|
}
|
|
8960
8998
|
AddToVisualBuffer(valueHEX, bufferDiv, lineDiv) {
|
|
8961
8999
|
const newText = CreateDiv(bufferDiv, "entry", valueHEX);
|
|
9000
|
+
const lineId = getArrayLikeElement(lineDiv.children, 0, "Missing visual buffer line id");
|
|
9001
|
+
const lineHex = getArrayLikeElement(lineDiv.children, 1, "Missing visual buffer line hex");
|
|
8962
9002
|
newText.onmouseenter = function() {
|
|
8963
|
-
|
|
8964
|
-
|
|
9003
|
+
lineId.classList.add("overEntry");
|
|
9004
|
+
lineHex.classList.add("overEntry");
|
|
8965
9005
|
};
|
|
8966
9006
|
newText.onmouseleave = function() {
|
|
8967
|
-
|
|
8968
|
-
|
|
9007
|
+
lineId.classList.remove("overEntry");
|
|
9008
|
+
lineHex.classList.remove("overEntry");
|
|
8969
9009
|
};
|
|
8970
9010
|
lineDiv.onmouseenter = function() {
|
|
8971
9011
|
newText.classList.add("overEntry");
|
|
@@ -8981,7 +9021,7 @@ var Alfen = class {
|
|
|
8981
9021
|
this.chargy = chargy;
|
|
8982
9022
|
}
|
|
8983
9023
|
bufferToHex(buffer, Reverse) {
|
|
8984
|
-
return (Reverse ? Array.from(new Uint8Array(buffer)).reverse() : Array.from(new Uint8Array(buffer))).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
9024
|
+
return (Reverse === true ? Array.from(new Uint8Array(buffer)).reverse() : Array.from(new Uint8Array(buffer))).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
8985
9025
|
}
|
|
8986
9026
|
bufferToNumber(buffer) {
|
|
8987
9027
|
return parseInt(Array.from(new Uint8Array(buffer)).map((b) => b.toString(16).padStart(2, "0")).join(""), 16);
|
|
@@ -9016,31 +9056,32 @@ var Alfen = class {
|
|
|
9016
9056
|
signedValues = Content;
|
|
9017
9057
|
let previousTimestamp = "";
|
|
9018
9058
|
for (let i = 0; i < signedValues.length; i++) {
|
|
9019
|
-
const elements = signedValues
|
|
9020
|
-
if (elements
|
|
9059
|
+
const elements = getArrayElement(signedValues, i, "Missing Alfen signed value").split(";");
|
|
9060
|
+
if (elements.length != 6 && elements.length != 7)
|
|
9021
9061
|
return {
|
|
9022
9062
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
9023
|
-
message: this.chargy.
|
|
9063
|
+
message: this.chargy.GetMultilanguageText("Invalid number of signed meter values!"),
|
|
9024
9064
|
certainty: 0
|
|
9025
9065
|
};
|
|
9026
|
-
const FormatId = elements
|
|
9027
|
-
const Type = elements
|
|
9028
|
-
const BlobVersion = elements
|
|
9029
|
-
const
|
|
9030
|
-
const
|
|
9031
|
-
const
|
|
9066
|
+
const FormatId = getArrayElement(elements, 0, "Missing Alfen format id");
|
|
9067
|
+
const Type = getArrayElement(elements, 1, "Missing Alfen type");
|
|
9068
|
+
const BlobVersion = getArrayElement(elements, 2, "Missing Alfen blob version");
|
|
9069
|
+
const publicKeyValue = getArrayElement(elements, 3, "Missing Alfen public key");
|
|
9070
|
+
const PublicKey = this.chargy.base32Decode(publicKeyValue, "RFC4648");
|
|
9071
|
+
const DataSet = this.chargy.base32Decode(getArrayElement(elements, 4, "Missing Alfen data set"), "RFC4648");
|
|
9072
|
+
const Signature = this.chargy.base32Decode(getArrayElement(elements, 5, "Missing Alfen signature"), "RFC4648");
|
|
9032
9073
|
if (common.PublicKey === "")
|
|
9033
|
-
common.PublicKey =
|
|
9034
|
-
else if (
|
|
9074
|
+
common.PublicKey = publicKeyValue;
|
|
9075
|
+
else if (publicKeyValue !== common.PublicKey)
|
|
9035
9076
|
return {
|
|
9036
9077
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
9037
|
-
message: this.chargy.
|
|
9078
|
+
message: this.chargy.GetMultilanguageText("Inconsistent public keys!"),
|
|
9038
9079
|
certainty: 0
|
|
9039
9080
|
};
|
|
9040
|
-
if (FormatId !== "AP" || Type
|
|
9081
|
+
if (FormatId !== "AP" || Type.length !== 1 || BlobVersion.length !== 1 || BlobVersion !== "3" || PublicKey.byteLength !== 25 || DataSet.byteLength !== 82 || Signature.byteLength !== 48) {
|
|
9041
9082
|
return {
|
|
9042
9083
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
9043
|
-
message: this.chargy.
|
|
9084
|
+
message: this.chargy.GetMultilanguageText("Invalid charging session format!"),
|
|
9044
9085
|
certainty: 0
|
|
9045
9086
|
};
|
|
9046
9087
|
}
|
|
@@ -9065,7 +9106,7 @@ var Alfen = class {
|
|
|
9065
9106
|
else if (AdapterId !== common.AdapterId)
|
|
9066
9107
|
return {
|
|
9067
9108
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
9068
|
-
message: this.chargy.
|
|
9109
|
+
message: this.chargy.GetMultilanguageText("Inconsistent Alfen adapter identification!"),
|
|
9069
9110
|
certainty: 0
|
|
9070
9111
|
};
|
|
9071
9112
|
if (common.AdapterFWVersion === "")
|
|
@@ -9073,7 +9114,7 @@ var Alfen = class {
|
|
|
9073
9114
|
else if (AdapterFWVersion !== common.AdapterFWVersion)
|
|
9074
9115
|
return {
|
|
9075
9116
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
9076
|
-
message: this.chargy.
|
|
9117
|
+
message: this.chargy.GetMultilanguageText("Inconsistent Alfen adapter firmware version!"),
|
|
9077
9118
|
certainty: 0
|
|
9078
9119
|
};
|
|
9079
9120
|
if (common.AdapterFWChecksum === "")
|
|
@@ -9081,7 +9122,7 @@ var Alfen = class {
|
|
|
9081
9122
|
else if (AdapterFWChecksum !== common.AdapterFWChecksum)
|
|
9082
9123
|
return {
|
|
9083
9124
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
9084
|
-
message: this.chargy.
|
|
9125
|
+
message: this.chargy.GetMultilanguageText("Inconsistent Alfen adapter firmware checksum!"),
|
|
9085
9126
|
certainty: 0
|
|
9086
9127
|
};
|
|
9087
9128
|
if (common.MeterId === "")
|
|
@@ -9089,7 +9130,7 @@ var Alfen = class {
|
|
|
9089
9130
|
else if (MeterId !== common.MeterId)
|
|
9090
9131
|
return {
|
|
9091
9132
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
9092
|
-
message: this.chargy.
|
|
9133
|
+
message: this.chargy.GetMultilanguageText("Inconsistent meter identification!"),
|
|
9093
9134
|
certainty: 0
|
|
9094
9135
|
};
|
|
9095
9136
|
if (common.ObisId === "")
|
|
@@ -9097,7 +9138,7 @@ var Alfen = class {
|
|
|
9097
9138
|
else if (ObisId !== common.ObisId)
|
|
9098
9139
|
return {
|
|
9099
9140
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
9100
|
-
message: this.chargy.
|
|
9141
|
+
message: this.chargy.GetMultilanguageText("Inconsistent OBIS code!"),
|
|
9101
9142
|
certainty: 0
|
|
9102
9143
|
};
|
|
9103
9144
|
if (common.UnitEncoded === 0)
|
|
@@ -9105,7 +9146,7 @@ var Alfen = class {
|
|
|
9105
9146
|
else if (UnitEncoded !== common.UnitEncoded)
|
|
9106
9147
|
return {
|
|
9107
9148
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
9108
|
-
message: this.chargy.
|
|
9149
|
+
message: this.chargy.GetMultilanguageText("Inconsistent unit (encoded) value!"),
|
|
9109
9150
|
certainty: 0
|
|
9110
9151
|
};
|
|
9111
9152
|
if (common.Scalar === "")
|
|
@@ -9113,7 +9154,7 @@ var Alfen = class {
|
|
|
9113
9154
|
else if (Scalar !== common.Scalar)
|
|
9114
9155
|
return {
|
|
9115
9156
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
9116
|
-
message: this.chargy.
|
|
9157
|
+
message: this.chargy.GetMultilanguageText("Inconsistent measurement scalar!"),
|
|
9117
9158
|
certainty: 0
|
|
9118
9159
|
};
|
|
9119
9160
|
if (common.UID === "")
|
|
@@ -9121,7 +9162,7 @@ var Alfen = class {
|
|
|
9121
9162
|
else if (UID !== common.UID)
|
|
9122
9163
|
return {
|
|
9123
9164
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
9124
|
-
message: this.chargy.
|
|
9165
|
+
message: this.chargy.GetMultilanguageText("Inconsistent user identification!"),
|
|
9125
9166
|
certainty: 0
|
|
9126
9167
|
};
|
|
9127
9168
|
if (common.InternalSessionId === 0)
|
|
@@ -9129,13 +9170,13 @@ var Alfen = class {
|
|
|
9129
9170
|
else if (InternalSessionId !== common.InternalSessionId)
|
|
9130
9171
|
return {
|
|
9131
9172
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
9132
|
-
message: this.chargy.
|
|
9173
|
+
message: this.chargy.GetMultilanguageText("Inconsistent internal charging session identification!"),
|
|
9133
9174
|
certainty: 0
|
|
9134
9175
|
};
|
|
9135
9176
|
if (previousTimestamp !== "" && previousTimestamp > Timestamp)
|
|
9136
9177
|
return {
|
|
9137
9178
|
status: "InconsistentTimestamps" /* InconsistentTimestamps */,
|
|
9138
|
-
message: this.chargy.
|
|
9179
|
+
message: this.chargy.GetMultilanguageText("Inconsistent timestamps!"),
|
|
9139
9180
|
certainty: 0
|
|
9140
9181
|
};
|
|
9141
9182
|
else
|
|
@@ -9154,14 +9195,8 @@ var Alfen = class {
|
|
|
9154
9195
|
const evseId = asString(containerInfos["EVSEId"]) ?? "DE*GEF*EVSE*CHARGY*1";
|
|
9155
9196
|
const chargingStationId = asString(containerInfos["ChargingStationId"]) ?? "DE*GEF*STATION*CHARGY*1";
|
|
9156
9197
|
const chargingSessionId = asString(chargingSession?.["@id"]);
|
|
9157
|
-
const firstDataSet = common.dataSets
|
|
9158
|
-
const lastDataSet = common.dataSets
|
|
9159
|
-
if (firstDataSet === void 0 || lastDataSet === void 0)
|
|
9160
|
-
return {
|
|
9161
|
-
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
9162
|
-
message: this.chargy.GetLocalizedMessage("Invalid number of signed meter values!"),
|
|
9163
|
-
certainty: 0
|
|
9164
|
-
};
|
|
9198
|
+
const firstDataSet = getFirstArrayElement(common.dataSets, "Missing first Alfen data set");
|
|
9199
|
+
const lastDataSet = getLastArrayElement(common.dataSets, "Missing last Alfen data set");
|
|
9165
9200
|
const _CTR = {
|
|
9166
9201
|
"@id": chargingSessionId ?? common.InternalSessionId.toString(),
|
|
9167
9202
|
"@context": "https://open.charging.cloud/contexts/CTR+json",
|
|
@@ -9291,7 +9326,7 @@ var Alfen = class {
|
|
|
9291
9326
|
} catch (exception) {
|
|
9292
9327
|
return {
|
|
9293
9328
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
9294
|
-
message: this.chargy.
|
|
9329
|
+
message: this.chargy.GetMultilanguageText("Exception occured: " + (exception instanceof Error ? exception.message : String(exception))),
|
|
9295
9330
|
certainty: 0
|
|
9296
9331
|
};
|
|
9297
9332
|
}
|
|
@@ -9442,62 +9477,62 @@ var AlfenCrypt01 = class extends ACrypt {
|
|
|
9442
9477
|
}
|
|
9443
9478
|
return {};
|
|
9444
9479
|
}
|
|
9445
|
-
async ViewMeasurement(measurementValue,
|
|
9480
|
+
async ViewMeasurement(measurementValue, _errorDiv, introDiv, infoDiv, PlainTextDiv, HashedPlainTextDiv, PublicKeyDiv, SignatureExpectedDiv, SignatureCheckDiv) {
|
|
9446
9481
|
const result = measurementValue.result;
|
|
9447
9482
|
{
|
|
9448
9483
|
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);
|
|
9449
9484
|
}
|
|
9450
9485
|
{
|
|
9451
|
-
if (PlainTextDiv.parentElement
|
|
9452
|
-
PlainTextDiv.parentElement.children
|
|
9486
|
+
if (PlainTextDiv.parentElement) {
|
|
9487
|
+
getArrayLikeElement(PlainTextDiv.parentElement.children, 0, "Missing plain text header").innerHTML = this.chargy.GetLocalizedMessage("Plain text") + " (320 Bytes, hex)";
|
|
9453
9488
|
}
|
|
9454
9489
|
PlainTextDiv.style.fontFamily = "";
|
|
9455
9490
|
PlainTextDiv.style.whiteSpace = "";
|
|
9456
9491
|
PlainTextDiv.style.maxHeight = "";
|
|
9457
9492
|
PlainTextDiv.style.overflowY = "";
|
|
9458
|
-
this.CreateLocalizedLine("Adapter Id", measurementValue.measurement.adapterId, result.adapterId
|
|
9459
|
-
this.CreateLocalizedLine("Adapter Firmware Version", measurementValue.measurement.adapterFWVersion, result.adapterFWVersion
|
|
9460
|
-
this.CreateLocalizedLine("Adapter Firmware Checksum", measurementValue.measurement.adapterFWChecksum, result.adapterFWChecksum
|
|
9461
|
-
this.CreateLocalizedLine("Meter number", measurementValue.measurement.energyMeterId, result.meterId
|
|
9493
|
+
this.CreateLocalizedLine("Adapter Id", measurementValue.measurement.adapterId, result.adapterId ?? "", infoDiv, PlainTextDiv);
|
|
9494
|
+
this.CreateLocalizedLine("Adapter Firmware Version", measurementValue.measurement.adapterFWVersion, result.adapterFWVersion ?? "", infoDiv, PlainTextDiv);
|
|
9495
|
+
this.CreateLocalizedLine("Adapter Firmware Checksum", measurementValue.measurement.adapterFWChecksum, result.adapterFWChecksum ?? "", infoDiv, PlainTextDiv);
|
|
9496
|
+
this.CreateLocalizedLine("Meter number", measurementValue.measurement.energyMeterId, result.meterId ?? "", infoDiv, PlainTextDiv);
|
|
9462
9497
|
this.CreateLocalizedLine(
|
|
9463
9498
|
"Meter status",
|
|
9464
9499
|
hex2bin(measurementValue.statusMeter, true) + " (" + measurementValue.statusMeter + ' hex)<br /><span class="statusInfos">' + this.DecodeMeterStatus(measurementValue.statusMeter).join("<br />") + "</span>",
|
|
9465
|
-
result.statusMeter
|
|
9500
|
+
result.statusMeter ?? "",
|
|
9466
9501
|
infoDiv,
|
|
9467
9502
|
PlainTextDiv
|
|
9468
9503
|
);
|
|
9469
9504
|
this.CreateLocalizedLine(
|
|
9470
9505
|
"Adapter status",
|
|
9471
9506
|
hex2bin(measurementValue.statusAdapter, true) + " (" + measurementValue.statusAdapter + ' hex)<br /><span class="statusInfos">' + this.DecodeAdapterStatus(measurementValue.statusAdapter).join("<br />") + "</span>",
|
|
9472
|
-
result.statusAdapter
|
|
9507
|
+
result.statusAdapter ?? "",
|
|
9473
9508
|
infoDiv,
|
|
9474
9509
|
PlainTextDiv
|
|
9475
9510
|
);
|
|
9476
|
-
this.CreateLocalizedLine("Seconds index", measurementValue.secondsIndex, result.secondsIndex
|
|
9477
|
-
this.CreateLocalizedLine("Timestamp", UTC2human(measurementValue.timestamp), result.timestamp
|
|
9478
|
-
this.CreateLocalizedLine("OBIS code", measurementValue.measurement.obis, result.obisId
|
|
9479
|
-
this.CreateLocalizedLine("Unit (encoded)", measurementValue.measurement.unitEncoded ?? 0, result.unitEncoded
|
|
9480
|
-
this.CreateLocalizedLine("Scaling", measurementValue.measurement.scale, result.scalar
|
|
9481
|
-
this.CreateLocalizedLine("Measurement Value", measurementValue.value.toString() + " Wh", result.value
|
|
9482
|
-
this.CreateLocalizedLine("Authorization", (measurementValue.measurement.chargingSession?.authorizationStart["@id"] ?? "") + " hex", pad(result.uid, 20)
|
|
9483
|
-
this.CreateLocalizedLine("SessionId", measurementValue.measurement.chargingSession?.["@id"] ?? "", result.sessionId
|
|
9484
|
-
this.CreateLocalizedLine("Pagination counter", measurementValue.paginationId, result.paging
|
|
9511
|
+
this.CreateLocalizedLine("Seconds index", measurementValue.secondsIndex, result.secondsIndex ?? "", infoDiv, PlainTextDiv);
|
|
9512
|
+
this.CreateLocalizedLine("Timestamp", UTC2human(measurementValue.timestamp), result.timestamp ?? "", infoDiv, PlainTextDiv);
|
|
9513
|
+
this.CreateLocalizedLine("OBIS code", measurementValue.measurement.obis, result.obisId ?? "", infoDiv, PlainTextDiv);
|
|
9514
|
+
this.CreateLocalizedLine("Unit (encoded)", measurementValue.measurement.unitEncoded ?? 0, result.unitEncoded ?? "", infoDiv, PlainTextDiv);
|
|
9515
|
+
this.CreateLocalizedLine("Scaling", measurementValue.measurement.scale, result.scalar ?? "", infoDiv, PlainTextDiv);
|
|
9516
|
+
this.CreateLocalizedLine("Measurement Value", measurementValue.value.toString() + " Wh", result.value ?? "", infoDiv, PlainTextDiv);
|
|
9517
|
+
this.CreateLocalizedLine("Authorization", (measurementValue.measurement.chargingSession?.authorizationStart["@id"] ?? "") + " hex", pad(result.uid, 20), infoDiv, PlainTextDiv);
|
|
9518
|
+
this.CreateLocalizedLine("SessionId", measurementValue.measurement.chargingSession?.["@id"] ?? "", result.sessionId ?? "", infoDiv, PlainTextDiv);
|
|
9519
|
+
this.CreateLocalizedLine("Pagination counter", measurementValue.paginationId, result.paging ?? "", infoDiv, PlainTextDiv);
|
|
9485
9520
|
}
|
|
9486
9521
|
{
|
|
9487
|
-
if (HashedPlainTextDiv.parentElement
|
|
9488
|
-
HashedPlainTextDiv.parentElement.children
|
|
9522
|
+
if (HashedPlainTextDiv.parentElement) {
|
|
9523
|
+
getArrayLikeElement(HashedPlainTextDiv.parentElement.children, 0, "Missing hashed plain text header").innerHTML = this.chargy.GetLocalizedMessage("Hashed plain text") + " (SHA256, hex)";
|
|
9489
9524
|
}
|
|
9490
9525
|
const hashValueText = typeof result.hashValue === "string" ? result.hashValue : result.hashValue?.toString(16) ?? "";
|
|
9491
9526
|
HashedPlainTextDiv.innerHTML = hashValueText.match(/.{1,8}/g)?.join(" ") ?? "";
|
|
9492
9527
|
}
|
|
9493
|
-
if (result.publicKey && result.publicKey
|
|
9494
|
-
if (PublicKeyDiv.parentElement
|
|
9495
|
-
PublicKeyDiv.parentElement.children
|
|
9528
|
+
if (result.publicKey != null && result.publicKey.length > 0) {
|
|
9529
|
+
if (PublicKeyDiv.parentElement) {
|
|
9530
|
+
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)";
|
|
9496
9531
|
}
|
|
9497
9532
|
if (!IsNullOrEmpty(result.publicKey))
|
|
9498
9533
|
PublicKeyDiv.innerHTML = result.publicKey.match(/.{1,4}/g)?.join(" ") ?? "";
|
|
9499
9534
|
}
|
|
9500
|
-
if (PublicKeyDiv.parentElement
|
|
9535
|
+
if (PublicKeyDiv.parentElement?.children[3]) {
|
|
9501
9536
|
PublicKeyDiv.parentElement.children[3].innerHTML = "";
|
|
9502
9537
|
if (result.publicKeySignatures) {
|
|
9503
9538
|
for (const signature of result.publicKeySignatures) {
|
|
@@ -9516,14 +9551,14 @@ var AlfenCrypt01 = class extends ACrypt {
|
|
|
9516
9551
|
}
|
|
9517
9552
|
}
|
|
9518
9553
|
if (result.signature != null) {
|
|
9519
|
-
if (SignatureExpectedDiv.parentElement
|
|
9520
|
-
SignatureExpectedDiv.parentElement.children
|
|
9554
|
+
if (SignatureExpectedDiv.parentElement) {
|
|
9555
|
+
getArrayLikeElement(SignatureExpectedDiv.parentElement.children, 0, "Missing expected signature header").innerHTML = this.chargy.GetLocalizedMessage("Expected signature") + " (" + (result.signature.format ?? "") + ", hex)";
|
|
9521
9556
|
}
|
|
9522
|
-
if (result.signature.r && result.signature.s) {
|
|
9557
|
+
if (result.signature.r != null && result.signature.r.length > 0 && result.signature.s != null && result.signature.s.length > 0) {
|
|
9523
9558
|
const signatureR = result.signature.r.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "-";
|
|
9524
9559
|
const signatureS = result.signature.s.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "-";
|
|
9525
9560
|
SignatureExpectedDiv.innerHTML = "r: " + signatureR + "<br />s: " + signatureS;
|
|
9526
|
-
} else if (result.signature.value)
|
|
9561
|
+
} else if (result.signature.value != null && result.signature.value.length > 0)
|
|
9527
9562
|
SignatureExpectedDiv.innerHTML = result.signature.value.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "-";
|
|
9528
9563
|
}
|
|
9529
9564
|
{
|
|
@@ -9616,18 +9651,18 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
9616
9651
|
tryToParseBSM_WS36aMeasurements(CTR, ExpectedEVSEId, ExpectedCscSwVersion, Measurements) {
|
|
9617
9652
|
if (!Array.isArray(Measurements)) return {
|
|
9618
9653
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
9619
|
-
message: this.chargy.
|
|
9654
|
+
message: this.chargy.GetMultilanguageText("MissingOrInvalidSignedMeterValues"),
|
|
9620
9655
|
certainty: 0
|
|
9621
9656
|
};
|
|
9622
9657
|
if (Measurements.length < 2) return {
|
|
9623
9658
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
9624
|
-
message: this.chargy.
|
|
9659
|
+
message: this.chargy.GetMultilanguageText("AtLeastTwoSignedMeterValuesRequired"),
|
|
9625
9660
|
certainty: 0
|
|
9626
9661
|
};
|
|
9627
9662
|
const firstMeasurement = Measurements[0];
|
|
9628
9663
|
if (!isMandatoryJSONObject(firstMeasurement)) return {
|
|
9629
9664
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
9630
|
-
message: this.chargy.
|
|
9665
|
+
message: this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalidSignedMeterValueP", 1),
|
|
9631
9666
|
certainty: 0
|
|
9632
9667
|
};
|
|
9633
9668
|
const errors = new Array();
|
|
@@ -9636,51 +9671,51 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
9636
9671
|
let secondaryErrors = 0;
|
|
9637
9672
|
try {
|
|
9638
9673
|
if (!isMandatoryString(firstMeasurement["@context"]))
|
|
9639
|
-
errors.push(this.chargy.
|
|
9674
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_JSONContextP", 1)));
|
|
9640
9675
|
const meterInfo = firstMeasurement["meterInfo"];
|
|
9641
9676
|
if (!isMandatoryJSONObject(meterInfo)) {
|
|
9642
|
-
errors.push(this.chargy.
|
|
9677
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfoP", 1)));
|
|
9643
9678
|
secondaryErrors += 5;
|
|
9644
9679
|
} else {
|
|
9645
9680
|
if (!isMandatoryString(meterInfo["firmwareVersion"]))
|
|
9646
|
-
errors.push(this.chargy.
|
|
9681
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_FirmwareVersionP", 1)));
|
|
9647
9682
|
if (!isMandatoryString(meterInfo["publicKey"]))
|
|
9648
|
-
errors.push(this.chargy.
|
|
9683
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_PublicKeyP", 1)));
|
|
9649
9684
|
if (!isMandatoryString(meterInfo["meterId"]))
|
|
9650
|
-
errors.push(this.chargy.
|
|
9685
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_MeterIdP", 1)));
|
|
9651
9686
|
if (!isMandatoryString(meterInfo["manufacturer"]))
|
|
9652
|
-
errors.push(this.chargy.
|
|
9687
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_ManufacturerP", 1)));
|
|
9653
9688
|
if (!isMandatoryString(meterInfo["type"]))
|
|
9654
|
-
errors.push(this.chargy.
|
|
9689
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_TypeP", 1)));
|
|
9655
9690
|
}
|
|
9656
9691
|
const contract = firstMeasurement["contract"];
|
|
9657
9692
|
if (!isMandatoryJSONObject(contract)) {
|
|
9658
|
-
errors.push(this.chargy.
|
|
9693
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_ContractP", 1)));
|
|
9659
9694
|
secondaryErrors += 2;
|
|
9660
9695
|
} else {
|
|
9661
9696
|
if (!isMandatoryString(contract["id"]))
|
|
9662
|
-
errors.push(this.chargy.
|
|
9697
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_Contract_IdP", 1)));
|
|
9663
9698
|
if (!isOptionalString(contract["type"]))
|
|
9664
|
-
errors.push(this.chargy.
|
|
9699
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_Contract_TypeP", 1)));
|
|
9665
9700
|
}
|
|
9666
9701
|
const value = firstMeasurement["value"];
|
|
9667
9702
|
if (!isMandatoryJSONObject(value)) {
|
|
9668
|
-
errors.push(this.chargy.
|
|
9703
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_ValueP", 1)));
|
|
9669
9704
|
secondaryErrors += 8;
|
|
9670
9705
|
} else {
|
|
9671
9706
|
const measurand = value["measurand"];
|
|
9672
9707
|
if (!isMandatoryJSONObject(measurand)) {
|
|
9673
|
-
errors.push(this.chargy.
|
|
9708
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeasurandP", 1)));
|
|
9674
9709
|
secondaryErrors += 2;
|
|
9675
9710
|
} else {
|
|
9676
9711
|
if (!isMandatoryString(measurand["id"]))
|
|
9677
|
-
errors.push(this.chargy.
|
|
9712
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_Measurand_IdentificationP", 1)));
|
|
9678
9713
|
if (!isMandatoryString(measurand["name"]))
|
|
9679
|
-
errors.push(this.chargy.
|
|
9714
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_Measurand_NameP", 1)));
|
|
9680
9715
|
}
|
|
9681
9716
|
const measuredValue = value["measuredValue"];
|
|
9682
9717
|
if (!isMandatoryJSONObject(measuredValue)) {
|
|
9683
|
-
errors.push(this.chargy.
|
|
9718
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeasuredValueP", 1)));
|
|
9684
9719
|
secondaryErrors += 4;
|
|
9685
9720
|
} else {
|
|
9686
9721
|
}
|
|
@@ -9758,18 +9793,22 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
9758
9793
|
if (currentMeasurement === void 0)
|
|
9759
9794
|
throw new Error(`Invalid signed meter value #${String(measurementCounter)}!`);
|
|
9760
9795
|
if (currentMeasurement["@context"] !== common.context)
|
|
9761
|
-
currentErrors.push(this.chargy.
|
|
9796
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_JSONContextP", measurementCounter)));
|
|
9762
9797
|
const currentId = currentMeasurement["@id"];
|
|
9763
9798
|
if (previousId !== "" && typeof currentId === "string") {
|
|
9764
9799
|
if (typeof previousId !== "string")
|
|
9765
9800
|
throw new Error(`Invalid identification of signed meter value #${String(measurementCounter - 1)}!`);
|
|
9766
9801
|
const previousParts = previousId.split("-");
|
|
9767
9802
|
const currentParts = currentId.split("-");
|
|
9768
|
-
|
|
9803
|
+
const previousPrefix = previousParts.at(0);
|
|
9804
|
+
const previousCounter = previousParts.at(1);
|
|
9805
|
+
const currentPrefix = currentParts.at(0);
|
|
9806
|
+
const currentCounter = currentParts.at(1);
|
|
9807
|
+
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
|
|
9769
9808
|
// anything (not even NaN). This way we are checking that both counter values
|
|
9770
9809
|
// are numeric too.
|
|
9771
|
-
parseInt(
|
|
9772
|
-
currentErrors.push(this.chargy.
|
|
9810
|
+
parseInt(previousCounter, 10) >= parseInt(currentCounter, 10)) {
|
|
9811
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_MeasurementIdP", measurementCounter)));
|
|
9773
9812
|
}
|
|
9774
9813
|
}
|
|
9775
9814
|
previousId = currentId;
|
|
@@ -9778,11 +9817,11 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
9778
9817
|
const displayedFormatObj2 = asJSONObject(valueObj2?.["displayedFormat"]);
|
|
9779
9818
|
const currentTime = asString(currentMeasurement["time"]) ?? "";
|
|
9780
9819
|
if (previousTime !== "" && currentTime <= previousTime)
|
|
9781
|
-
currentErrors.push(this.chargy.
|
|
9820
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_TimestampP", measurementCounter)));
|
|
9782
9821
|
previousTime = currentTime;
|
|
9783
9822
|
const currentValue = asNumber(measuredValueObj2?.["value"]);
|
|
9784
9823
|
if (previousValue !== void 0 && currentValue !== void 0 && currentValue < previousValue)
|
|
9785
|
-
currentErrors.push(this.chargy.
|
|
9824
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_Measurement_ValueP", measurementCounter)));
|
|
9786
9825
|
previousValue = currentValue;
|
|
9787
9826
|
const additionalValuesRaw = currentMeasurement["additionalValues"];
|
|
9788
9827
|
if (!isMandatoryJSONArray(additionalValuesRaw))
|
|
@@ -9806,78 +9845,78 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
9806
9845
|
precision: asNumber(displayedFormat?.["precision"])
|
|
9807
9846
|
};
|
|
9808
9847
|
});
|
|
9809
|
-
if (currentMeasurement["meterInfo"]) {
|
|
9848
|
+
if (currentMeasurement["meterInfo"] != null) {
|
|
9810
9849
|
const meterInfoObj2 = asJSONObject(currentMeasurement["meterInfo"]);
|
|
9811
9850
|
if (meterInfoObj2?.["firmwareVersion"] !== common.meterInfo_firmwareVersion)
|
|
9812
|
-
currentErrors.push(this.chargy.
|
|
9851
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_MeterInfo_FirmwareVersionP", measurementCounter)));
|
|
9813
9852
|
if (meterInfoObj2?.["publicKey"] !== common.meterInfo_publicKey)
|
|
9814
|
-
currentErrors.push(this.chargy.
|
|
9853
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_MeterInfo_PublicKeyP", measurementCounter)));
|
|
9815
9854
|
if (meterInfoObj2?.["meterId"] !== common.meterInfo_meterId)
|
|
9816
|
-
currentErrors.push(this.chargy.
|
|
9817
|
-
if (meterInfoObj2?.["meterId"] !== additionalValues.
|
|
9818
|
-
currentErrors.push(this.chargy.
|
|
9855
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_MeterInfo_MeterIdP", measurementCounter)));
|
|
9856
|
+
if (meterInfoObj2?.["meterId"] !== additionalValues.find((element) => element.measurandName === "MA1")?.value)
|
|
9857
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_MeterInfo_MeterIdP", measurementCounter)));
|
|
9819
9858
|
if (meterInfoObj2?.["manufacturer"] !== common.meterInfo_manufacturer)
|
|
9820
|
-
currentErrors.push(this.chargy.
|
|
9859
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_MeterInfo_ManufacturerP", measurementCounter)));
|
|
9821
9860
|
if (meterInfoObj2?.["type"] !== common.meterInfo_type)
|
|
9822
|
-
currentErrors.push(this.chargy.
|
|
9861
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_MeterInfo_TypeP", measurementCounter)));
|
|
9823
9862
|
}
|
|
9824
|
-
if (currentMeasurement["contract"]) {
|
|
9863
|
+
if (currentMeasurement["contract"] != null) {
|
|
9825
9864
|
const contractObj2 = asJSONObject(currentMeasurement["contract"]);
|
|
9826
|
-
if (additionalValues.filter((element) => element.measurandName?.startsWith("Meta") && asString(element.value)?.startsWith("contract-id:")).length == 0)
|
|
9827
|
-
currentErrors.push(this.chargy.
|
|
9865
|
+
if (additionalValues.filter((element) => element.measurandName?.startsWith("Meta") === true && asString(element.value)?.startsWith("contract-id:") === true).length == 0)
|
|
9866
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_Contract_IdP", measurementCounter)));
|
|
9828
9867
|
if (contractObj2?.["id"] !== common.contract_id)
|
|
9829
|
-
currentErrors.push(this.chargy.
|
|
9868
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_Contract_IdP", measurementCounter)));
|
|
9830
9869
|
if (contractObj2?.["type"] !== common.contract_type)
|
|
9831
|
-
currentErrors.push(this.chargy.
|
|
9832
|
-
const contractInfo = additionalValues.
|
|
9870
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_Contract_TypeP", measurementCounter)));
|
|
9871
|
+
const contractInfo = additionalValues.find((element) => element.measurandName?.startsWith("Meta") === true && asString(element.value)?.startsWith("contract-id:") === true)?.value;
|
|
9833
9872
|
if (contractInfo != null) {
|
|
9834
|
-
if (contractObj2?.["type"] && contractInfo !== "contract-id: " + (common.contract_type ?? "-") + ":" + common.contract_id)
|
|
9835
|
-
currentErrors.push(this.chargy.
|
|
9836
|
-
if (
|
|
9837
|
-
currentErrors.push(this.chargy.
|
|
9873
|
+
if (contractObj2?.["type"] != null && contractInfo !== "contract-id: " + (common.contract_type ?? "-") + ":" + common.contract_id)
|
|
9874
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_Contract_IdP", measurementCounter)));
|
|
9875
|
+
if (contractObj2?.["type"] == null && contractInfo !== "contract-id: " + common.contract_id)
|
|
9876
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_Contract_IdP", measurementCounter)));
|
|
9838
9877
|
}
|
|
9839
9878
|
}
|
|
9840
9879
|
const rcrInAdditional = additionalValues.find((element) => element.measurandName == "RCR");
|
|
9841
9880
|
if (currentMeasurement["value"] == null)
|
|
9842
9881
|
throw new Error(`Missing value within signed meter value #${String(measurementCounter)}!`);
|
|
9843
|
-
if ((valueObj2?.["measurand"] || valueObj2?.["measuredValue"]) && rcrInAdditional === void 0)
|
|
9882
|
+
if ((valueObj2?.["measurand"] != null || valueObj2?.["measuredValue"] != null) && rcrInAdditional === void 0)
|
|
9844
9883
|
throw new Error(`Missing 'RCR' within the additional values of signed meter value #${String(measurementCounter)}!`);
|
|
9845
|
-
if (valueObj2?.["measurand"]) {
|
|
9884
|
+
if (valueObj2?.["measurand"] != null) {
|
|
9846
9885
|
const measurandObj2 = asJSONObject(valueObj2["measurand"]);
|
|
9847
9886
|
if (measurandObj2?.["id"] !== common.value_measurand_id || measurandObj2["id"] !== rcrInAdditional?.measurandId)
|
|
9848
|
-
currentErrors.push(this.chargy.
|
|
9887
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_Measurand_IdentificationP", measurementCounter)));
|
|
9849
9888
|
if (measurandObj2?.["name"] !== common.value_measurand_name || measurandObj2["name"] !== rcrInAdditional?.measurandName)
|
|
9850
|
-
currentErrors.push(this.chargy.
|
|
9889
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_Measurand_NameP", measurementCounter)));
|
|
9851
9890
|
}
|
|
9852
|
-
if (valueObj2?.["measuredValue"]) {
|
|
9891
|
+
if (valueObj2?.["measuredValue"] != null) {
|
|
9853
9892
|
if (measuredValueObj2?.["value"] !== rcrInAdditional?.value)
|
|
9854
|
-
currentErrors.push(this.chargy.
|
|
9893
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValueP", measurementCounter)));
|
|
9855
9894
|
if (measuredValueObj2?.["scale"] !== common.value_measuredValue_scale || measuredValueObj2?.["scale"] !== rcrInAdditional?.scale)
|
|
9856
|
-
currentErrors.push(this.chargy.
|
|
9895
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_ScaleP", measurementCounter)));
|
|
9857
9896
|
if (measuredValueObj2?.["unit"] !== common.value_measuredValue_unit || measuredValueObj2["unit"] !== rcrInAdditional?.unit)
|
|
9858
|
-
currentErrors.push(this.chargy.
|
|
9897
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_UnitP", measurementCounter)));
|
|
9859
9898
|
if (measuredValueObj2?.["unitEncoded"] !== common.value_measuredValue_unitEncoded || measuredValueObj2?.["unitEncoded"] !== rcrInAdditional?.unitEncoded)
|
|
9860
|
-
currentErrors.push(this.chargy.
|
|
9899
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_UnitEncodedP", measurementCounter)));
|
|
9861
9900
|
if (measuredValueObj2?.["valueType"] !== common.value_measuredValue_valueType || measuredValueObj2?.["valueType"] !== rcrInAdditional?.valueType)
|
|
9862
|
-
currentErrors.push(this.chargy.
|
|
9901
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_TypeP", measurementCounter)));
|
|
9863
9902
|
}
|
|
9864
|
-
if (currentMeasurement["chargePoint"] && asJSONObject(currentMeasurement["chargePoint"])?.["softwareVersion"] !== common.chargePoint_softwareVersion)
|
|
9865
|
-
currentErrors.push(this.chargy.
|
|
9866
|
-
const signedEVSEId = additionalValues.filter((element) => element.measurandName?.startsWith("Meta") && asString(element.value)?.startsWith("evse-id:"));
|
|
9903
|
+
if (currentMeasurement["chargePoint"] != null && asJSONObject(currentMeasurement["chargePoint"])?.["softwareVersion"] !== common.chargePoint_softwareVersion)
|
|
9904
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageText("Inconsistent_ChargingStation_FirmwareVersion")));
|
|
9905
|
+
const signedEVSEId = additionalValues.filter((element) => element.measurandName?.startsWith("Meta") === true && asString(element.value)?.startsWith("evse-id:") === true);
|
|
9867
9906
|
if (signedEVSEId.length == 1) {
|
|
9868
9907
|
const evse__id = (asString(signedEVSEId[0]?.value) ?? "").replace("evse-id:", "").trim();
|
|
9869
9908
|
if (evse__id !== "unknown" && ExpectedEVSEId !== evse__id)
|
|
9870
|
-
currentErrors.push(this.chargy.
|
|
9909
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageText("Inconsistent_EVSE_Identification")));
|
|
9871
9910
|
}
|
|
9872
|
-
const signedCSCSWVersion = additionalValues.filter((element) => element.measurandName?.startsWith("Meta") && asString(element.value)?.startsWith("csc-sw-version:"));
|
|
9911
|
+
const signedCSCSWVersion = additionalValues.filter((element) => element.measurandName?.startsWith("Meta") === true && asString(element.value)?.startsWith("csc-sw-version:") === true);
|
|
9873
9912
|
if (signedCSCSWVersion.length == 1) {
|
|
9874
9913
|
const csc_sw_version = asString(signedCSCSWVersion[0]?.value)?.replace("csc-sw-version:", "").trim() ?? null;
|
|
9875
9914
|
if (previousCscSwVersion !== null && previousCscSwVersion !== csc_sw_version)
|
|
9876
|
-
currentErrors.push(this.chargy.
|
|
9915
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageText("Inconsistent_ChargingStation_FirmwareVersion")));
|
|
9877
9916
|
if (ExpectedCscSwVersion !== null && ExpectedCscSwVersion !== csc_sw_version)
|
|
9878
9917
|
currentWarnings.push({
|
|
9879
9918
|
level: "medium" /* medium */,
|
|
9880
|
-
message: this.chargy.
|
|
9919
|
+
message: this.chargy.GetMultilanguageText("Inconsistent_ChargingStation_FirmwareVersion")
|
|
9881
9920
|
});
|
|
9882
9921
|
previousCscSwVersion = csc_sw_version;
|
|
9883
9922
|
}
|
|
@@ -9934,36 +9973,38 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
9934
9973
|
case "Evt":
|
|
9935
9974
|
Evt = asNumber(additionalValue.value) ?? NaN;
|
|
9936
9975
|
break;
|
|
9976
|
+
default:
|
|
9977
|
+
break;
|
|
9937
9978
|
}
|
|
9938
9979
|
}
|
|
9939
9980
|
const currentRCRValue = asNumber(RCR?.value) ?? NaN;
|
|
9940
9981
|
if (previousRCR !== -1 && currentRCRValue < previousRCR)
|
|
9941
|
-
currentErrors.push(this.chargy.
|
|
9982
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_Measurement_ValueP", measurementCounter)));
|
|
9942
9983
|
previousRCR = currentRCRValue;
|
|
9943
9984
|
if (RCnt !== currentMeasurement["measurementId"])
|
|
9944
|
-
currentErrors.push(this.chargy.
|
|
9985
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_MeasurementIdP", measurementCounter)));
|
|
9945
9986
|
if (previousRCnt !== -1 && RCnt != previousRCnt + 1)
|
|
9946
|
-
currentErrors.push(this.chargy.
|
|
9987
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_CounterP", measurementCounter)));
|
|
9947
9988
|
previousRCnt = RCnt;
|
|
9948
9989
|
if (previousOS !== -1 && OS <= previousOS)
|
|
9949
|
-
currentErrors.push(this.chargy.
|
|
9990
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_OperationSecondsCounterP", measurementCounter)));
|
|
9950
9991
|
previousOS = OS;
|
|
9951
9992
|
if (previousEpoch !== -1 && Epoch <= previousEpoch)
|
|
9952
|
-
currentErrors.push(this.chargy.
|
|
9993
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_UNIXEpochP", measurementCounter)));
|
|
9953
9994
|
previousEpoch = Epoch;
|
|
9954
9995
|
const measurementTimestamp1 = new Date(Epoch * 1e3 + TZO * 6e4).toISOString();
|
|
9955
9996
|
const measurementTimestamp2 = measurementTimestamp1.substring(0, measurementTimestamp1.indexOf("."));
|
|
9956
9997
|
const measurementTimestamp3 = measurementTimestamp2 + (TZO > 0 ? "+" : "-") + (Math.abs(TZO) / 60).toString().padStart(2, "0") + ":" + (Math.abs(TZO) % 60).toString().padStart(2, "0");
|
|
9957
9998
|
if (currentTime !== measurementTimestamp3)
|
|
9958
|
-
currentErrors.push(this.chargy.
|
|
9999
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_TimestampP", measurementCounter)));
|
|
9959
10000
|
if (common.MA1 !== null && MA1 !== common.MA1)
|
|
9960
|
-
currentErrors.push(this.chargy.
|
|
10001
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_MeterInfo_MeterIdP", measurementCounter)));
|
|
9961
10002
|
common.MA1 = MA1;
|
|
9962
10003
|
if (common.epochSetCnt !== -1 && EpochSetCnt !== common.epochSetCnt)
|
|
9963
|
-
currentErrors.push(this.chargy.
|
|
10004
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_EpochSet_CounterP", measurementCounter)));
|
|
9964
10005
|
common.epochSetCnt = EpochSetCnt;
|
|
9965
10006
|
if (common.epochSetOS !== -1 && EpochSetOS !== common.epochSetOS)
|
|
9966
|
-
currentErrors.push(this.chargy.
|
|
10007
|
+
currentErrors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_SignedMeterValue_EpochSet_OperationSecondsP", measurementCounter)));
|
|
9967
10008
|
common.epochSetOS = EpochSetOS;
|
|
9968
10009
|
common.dataSets.push({
|
|
9969
10010
|
Typ,
|
|
@@ -9996,18 +10037,17 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
9996
10037
|
});
|
|
9997
10038
|
}
|
|
9998
10039
|
const n = common.dataSets.length - 1;
|
|
9999
|
-
const firstDataSet = common.dataSets
|
|
10000
|
-
const lastDataSet = common.dataSets
|
|
10001
|
-
if (firstDataSet
|
|
10040
|
+
const firstDataSet = getFirstArrayElement(common.dataSets, "Missing first BSM data set");
|
|
10041
|
+
const lastDataSet = getArrayElement(common.dataSets, n, "Missing last BSM data set");
|
|
10042
|
+
if (firstDataSet.TypParsed !== "START" && firstDataSet.TypParsed !== "TURN ON")
|
|
10002
10043
|
throw new Error(this.chargy.GetLocalizedMessageWithParameter("Inconsistent_EnergyMeterValueP", 1));
|
|
10003
10044
|
for (let i = 1; i < common.dataSets.length - 1; i++) {
|
|
10004
10045
|
if (common.dataSets[i]?.TypParsed !== "CURRENT")
|
|
10005
|
-
errors.push(this.chargy.
|
|
10046
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Inconsistent_EnergyMeterValueP", measurementCounter + 1)));
|
|
10006
10047
|
}
|
|
10007
|
-
if (lastDataSet
|
|
10048
|
+
if (lastDataSet.TypParsed !== "END" && lastDataSet.TypParsed !== "TURN OFF")
|
|
10008
10049
|
throw new Error(this.chargy.GetLocalizedMessageWithParameter("Inconsistent_EnergyMeterValueP", n + 1));
|
|
10009
|
-
|
|
10010
|
-
CTR.chargingSessions = [];
|
|
10050
|
+
CTR.chargingSessions ??= [];
|
|
10011
10051
|
const ASN1_SignatureSchema = this.chargy.asn1.define("Signature", function() {
|
|
10012
10052
|
this.seq().obj(
|
|
10013
10053
|
this.key("r").int(),
|
|
@@ -10072,7 +10112,11 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
10072
10112
|
try {
|
|
10073
10113
|
ASN1Signature = ASN1_SignatureSchema.decode(Buffer.from(dataSet.signature, "hex"), "der");
|
|
10074
10114
|
} catch (exception) {
|
|
10075
|
-
|
|
10115
|
+
const signatureError = this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_SignatureP", 1);
|
|
10116
|
+
const exceptionText = ": " + (exception instanceof Error ? exception.message : String(exception));
|
|
10117
|
+
for (const language of Object.keys(signatureError))
|
|
10118
|
+
signatureError[language] = (signatureError[language] ?? "") + exceptionText;
|
|
10119
|
+
errors.push(CreateError(signatureError));
|
|
10076
10120
|
}
|
|
10077
10121
|
const bsmMeasurementValue = {
|
|
10078
10122
|
timestamp: dataSet.time,
|
|
@@ -10120,12 +10164,12 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
10120
10164
|
CTR.chargingSessions.push(session);
|
|
10121
10165
|
CTR["@id"] = common.meterInfo_meterId + "-" + String(firstDataSet.Epoch);
|
|
10122
10166
|
{
|
|
10123
|
-
const firstChargingSession = CTR.chargingSessions
|
|
10124
|
-
const lastChargingSession = CTR.chargingSessions
|
|
10125
|
-
if (
|
|
10167
|
+
const firstChargingSession = getFirstArrayElement(CTR.chargingSessions, "Missing first BSM charging session");
|
|
10168
|
+
const lastChargingSession = getLastArrayElement(CTR.chargingSessions, "Missing last BSM charging session");
|
|
10169
|
+
if (CTR.begin == void 0 || CTR.begin === "" || CTR.begin > firstChargingSession.begin) {
|
|
10126
10170
|
CTR.begin = firstChargingSession.begin;
|
|
10127
10171
|
}
|
|
10128
|
-
if (lastChargingSession
|
|
10172
|
+
if (lastChargingSession.end !== void 0) {
|
|
10129
10173
|
if (CTR.end == void 0 || CTR.end === "" || CTR.end < lastChargingSession.end)
|
|
10130
10174
|
CTR.end = lastChargingSession.end;
|
|
10131
10175
|
}
|
|
@@ -10165,7 +10209,9 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
10165
10209
|
CTR.certainty = 1 - errors.length / numberOfFormatChecks;
|
|
10166
10210
|
return CTR;
|
|
10167
10211
|
} catch (exception) {
|
|
10168
|
-
errors.push(
|
|
10212
|
+
errors.push(
|
|
10213
|
+
CreateError({ "en": "Exception occured: " + (exception instanceof Error ? exception.message : String(exception)) })
|
|
10214
|
+
);
|
|
10169
10215
|
}
|
|
10170
10216
|
return {
|
|
10171
10217
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
@@ -10295,58 +10341,63 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
10295
10341
|
}
|
|
10296
10342
|
return {};
|
|
10297
10343
|
}
|
|
10298
|
-
async ViewMeasurement(measurementValue,
|
|
10344
|
+
async ViewMeasurement(measurementValue, _errorDiv, introDiv, infoDiv, PlainTextDiv, HashedPlainTextDiv, PublicKeyDiv, SignatureExpectedDiv, SignatureCheckDiv) {
|
|
10299
10345
|
if (measurementValue.measurement === void 0)
|
|
10300
10346
|
return new Error("Invalid measurement!");
|
|
10301
10347
|
const result = measurementValue.result;
|
|
10302
10348
|
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);
|
|
10303
|
-
if (PlainTextDiv.parentElement
|
|
10304
|
-
PlainTextDiv.parentElement.children
|
|
10349
|
+
if (PlainTextDiv.parentElement) {
|
|
10350
|
+
getArrayLikeElement(PlainTextDiv.parentElement.children, 0, "Missing plain text header").innerHTML = "Plain text (" + measurementValue.result.ArraySize.toString() + " Bytes, hex)";
|
|
10305
10351
|
}
|
|
10306
10352
|
PlainTextDiv.style.fontFamily = "";
|
|
10307
10353
|
PlainTextDiv.style.whiteSpace = "";
|
|
10308
10354
|
PlainTextDiv.style.maxHeight = "";
|
|
10309
10355
|
PlainTextDiv.style.overflowY = "";
|
|
10310
|
-
this.CreateLine("Snapshot-Typ", this.ParseTyp(measurementValue.Typ), result.Typ
|
|
10311
|
-
this.CreateLine("RCR", (measurementValue.RCR * 10 ** measurementValue.RCR_SF).toString() + " " + measurementValue.RCR_Unit, result.RCR
|
|
10312
|
-
this.CreateLine("TotWhImp", (measurementValue.TotWhImp * 10 ** measurementValue.TotWhImp_SF).toString() + " " + measurementValue.TotWhImp_Unit, result.TotWhImp
|
|
10313
|
-
this.CreateLine("W", (measurementValue.W * 10 ** measurementValue.W_SF).toString() + " " + measurementValue.W_Unit, result.W
|
|
10314
|
-
this.CreateLine("MA1", measurementValue.MA1, result.MA1
|
|
10315
|
-
this.CreateLine("RCnt", measurementValue.RCnt, result.RCnt
|
|
10316
|
-
this.CreateLine("OS", measurementValue.OS, result.OS
|
|
10317
|
-
this.CreateLine("Zeitstempel", UTC2human(measurementValue.Epoch), result.Epoch
|
|
10318
|
-
this.CreateLine("TZO", measurementValue.TZO.toString() + " Minuten", result.TZO
|
|
10319
|
-
this.CreateLine("EpochSetCnt", measurementValue.EpochSetCnt, result.EpochSetCnt
|
|
10320
|
-
this.CreateLine("EpochSetOS", measurementValue.EpochSetOS, result.EpochSetOS
|
|
10321
|
-
this.CreateLine("DI", measurementValue.DI, result.DI
|
|
10322
|
-
this.CreateLine("DO", measurementValue.DO, result.DO
|
|
10323
|
-
this.CreateLine("Meta1", measurementValue.Meta1, result.Meta1
|
|
10324
|
-
this.CreateLine("Meta2", measurementValue.Meta2, result.Meta2
|
|
10325
|
-
this.CreateLine("Meta3", measurementValue.Meta3, result.Meta3
|
|
10326
|
-
this.CreateLine("Evt", this.ParseEvents(measurementValue.Evt).join("<br>"), result.Evt
|
|
10327
|
-
if (HashedPlainTextDiv.parentElement
|
|
10328
|
-
HashedPlainTextDiv.parentElement.children
|
|
10356
|
+
this.CreateLine("Snapshot-Typ", this.ParseTyp(measurementValue.Typ), result.Typ, infoDiv, PlainTextDiv);
|
|
10357
|
+
this.CreateLine("RCR", (measurementValue.RCR * 10 ** measurementValue.RCR_SF).toString() + " " + measurementValue.RCR_Unit, result.RCR, infoDiv, PlainTextDiv);
|
|
10358
|
+
this.CreateLine("TotWhImp", (measurementValue.TotWhImp * 10 ** measurementValue.TotWhImp_SF).toString() + " " + measurementValue.TotWhImp_Unit, result.TotWhImp, infoDiv, PlainTextDiv);
|
|
10359
|
+
this.CreateLine("W", (measurementValue.W * 10 ** measurementValue.W_SF).toString() + " " + measurementValue.W_Unit, result.W, infoDiv, PlainTextDiv);
|
|
10360
|
+
this.CreateLine("MA1", measurementValue.MA1, result.MA1, infoDiv, PlainTextDiv);
|
|
10361
|
+
this.CreateLine("RCnt", measurementValue.RCnt, result.RCnt, infoDiv, PlainTextDiv);
|
|
10362
|
+
this.CreateLine("OS", measurementValue.OS, result.OS, infoDiv, PlainTextDiv);
|
|
10363
|
+
this.CreateLine("Zeitstempel", UTC2human(measurementValue.Epoch), result.Epoch, infoDiv, PlainTextDiv);
|
|
10364
|
+
this.CreateLine("TZO", measurementValue.TZO.toString() + " Minuten", result.TZO, infoDiv, PlainTextDiv);
|
|
10365
|
+
this.CreateLine("EpochSetCnt", measurementValue.EpochSetCnt, result.EpochSetCnt, infoDiv, PlainTextDiv);
|
|
10366
|
+
this.CreateLine("EpochSetOS", measurementValue.EpochSetOS, result.EpochSetOS, infoDiv, PlainTextDiv);
|
|
10367
|
+
this.CreateLine("DI", measurementValue.DI, result.DI, infoDiv, PlainTextDiv);
|
|
10368
|
+
this.CreateLine("DO", measurementValue.DO, result.DO, infoDiv, PlainTextDiv);
|
|
10369
|
+
this.CreateLine("Meta1", measurementValue.Meta1, result.Meta1, infoDiv, PlainTextDiv);
|
|
10370
|
+
this.CreateLine("Meta2", measurementValue.Meta2, result.Meta2, infoDiv, PlainTextDiv);
|
|
10371
|
+
this.CreateLine("Meta3", measurementValue.Meta3, result.Meta3, infoDiv, PlainTextDiv);
|
|
10372
|
+
this.CreateLine("Evt", this.ParseEvents(measurementValue.Evt).join("<br>"), result.Evt, infoDiv, PlainTextDiv);
|
|
10373
|
+
if (HashedPlainTextDiv.parentElement) {
|
|
10374
|
+
getArrayLikeElement(HashedPlainTextDiv.parentElement.children, 0, "Missing hashed plain text header").innerHTML = "Hashed plain text (SHA256, hex)";
|
|
10329
10375
|
}
|
|
10330
10376
|
HashedPlainTextDiv.innerHTML = result.sha256value?.match(/.{1,8}/g)?.join(" ") ?? "";
|
|
10331
10377
|
if (result.publicKey != null && result.publicKey != "") {
|
|
10332
|
-
if (PublicKeyDiv.parentElement
|
|
10333
|
-
PublicKeyDiv.parentElement.children
|
|
10378
|
+
if (PublicKeyDiv.parentElement) {
|
|
10379
|
+
getArrayLikeElement(PublicKeyDiv.parentElement.children, 0, "Missing public key header").innerHTML = "Public Key (" + (result.publicKeyFormat != null && result.publicKeyFormat.length > 0 ? result.publicKeyFormat + ", " : "") + "hex)";
|
|
10334
10380
|
}
|
|
10335
10381
|
if (!IsNullOrEmpty(result.publicKey))
|
|
10336
10382
|
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(" ") ?? "-";
|
|
10337
|
-
|
|
10338
|
-
|
|
10383
|
+
const publicKeySignatureContainer = PublicKeyDiv.parentElement?.children[3];
|
|
10384
|
+
if (publicKeySignatureContainer !== void 0) {
|
|
10385
|
+
publicKeySignatureContainer.innerHTML = "";
|
|
10339
10386
|
}
|
|
10340
10387
|
if (result.publicKeySignatures) {
|
|
10341
10388
|
for (const signature of result.publicKeySignatures) {
|
|
10342
10389
|
try {
|
|
10343
|
-
const signatureDiv =
|
|
10344
|
-
|
|
10390
|
+
const signatureDiv = publicKeySignatureContainer?.appendChild(document.createElement("div"));
|
|
10391
|
+
const chargingSession = measurementValue.measurement.chargingSession;
|
|
10392
|
+
const evse = chargingSession?.EVSE;
|
|
10393
|
+
const meter = evse?.meters.at(0);
|
|
10394
|
+
const publicKey = meter?.publicKeys?.at(0);
|
|
10395
|
+
if (signatureDiv != null && chargingSession != null && evse != null && meter != null && publicKey != null) {
|
|
10345
10396
|
signatureDiv.innerHTML = await this.chargy.CheckMeterPublicKeySignature(
|
|
10346
|
-
|
|
10347
|
-
|
|
10348
|
-
|
|
10349
|
-
|
|
10397
|
+
chargingSession.chargingStation,
|
|
10398
|
+
evse,
|
|
10399
|
+
meter,
|
|
10400
|
+
publicKey,
|
|
10350
10401
|
signature
|
|
10351
10402
|
);
|
|
10352
10403
|
}
|
|
@@ -10357,12 +10408,12 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
10357
10408
|
}
|
|
10358
10409
|
}
|
|
10359
10410
|
if (result.signature != null) {
|
|
10360
|
-
if (SignatureExpectedDiv.parentElement
|
|
10361
|
-
SignatureExpectedDiv.parentElement.children
|
|
10411
|
+
if (SignatureExpectedDiv.parentElement) {
|
|
10412
|
+
getArrayLikeElement(SignatureExpectedDiv.parentElement.children, 0, "Missing expected signature header").innerHTML = "Erwartete Signatur (" + (result.signature.format ?? "") + ", hex)";
|
|
10362
10413
|
}
|
|
10363
|
-
if (result.signature.r && result.signature.s)
|
|
10414
|
+
if (result.signature.r != null && result.signature.r.length > 0 && result.signature.s != null && result.signature.s.length > 0)
|
|
10364
10415
|
SignatureExpectedDiv.innerHTML = "r: " + (result.signature.r.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "-") + "<br />s: " + (result.signature.s.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "-");
|
|
10365
|
-
else if (result.signature.value)
|
|
10416
|
+
else if (result.signature.value != null && result.signature.value.length > 0)
|
|
10366
10417
|
SignatureExpectedDiv.innerHTML = result.signature.value.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "-";
|
|
10367
10418
|
}
|
|
10368
10419
|
switch (result.status) {
|
|
@@ -10388,6 +10439,7 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
10388
10439
|
SignatureCheckDiv.innerHTML = '<i class="fas fa-times-circle"></i><div id="description">Ung\xFCltige Signatur</div>';
|
|
10389
10440
|
break;
|
|
10390
10441
|
}
|
|
10442
|
+
return void 0;
|
|
10391
10443
|
}
|
|
10392
10444
|
//#region Helper methods
|
|
10393
10445
|
PrefixConverter(input) {
|
|
@@ -10466,30 +10518,35 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
10466
10518
|
if ((value & 1 << 29) != 0) events.push("OEM 15");
|
|
10467
10519
|
return events;
|
|
10468
10520
|
}
|
|
10469
|
-
DecodeStatus(statusValue)
|
|
10470
|
-
|
|
10471
|
-
|
|
10472
|
-
|
|
10473
|
-
|
|
10474
|
-
|
|
10475
|
-
|
|
10476
|
-
|
|
10477
|
-
|
|
10478
|
-
|
|
10479
|
-
|
|
10480
|
-
|
|
10481
|
-
|
|
10482
|
-
|
|
10483
|
-
|
|
10484
|
-
|
|
10485
|
-
|
|
10486
|
-
|
|
10487
|
-
|
|
10488
|
-
|
|
10489
|
-
|
|
10490
|
-
|
|
10491
|
-
|
|
10492
|
-
|
|
10521
|
+
// private DecodeStatus(statusValue: string) : Array<string>
|
|
10522
|
+
// {
|
|
10523
|
+
// const statusArray:string[] = [];
|
|
10524
|
+
// try
|
|
10525
|
+
// {
|
|
10526
|
+
// const status = parseInt(statusValue);
|
|
10527
|
+
// if ((status & 1) == 1)
|
|
10528
|
+
// statusArray.push("Fehler erkannt");
|
|
10529
|
+
// if ((status & 2) == 2)
|
|
10530
|
+
// statusArray.push("Synchrone Messwertübermittlung");
|
|
10531
|
+
// // Bit 3 is reserved!
|
|
10532
|
+
// if ((status & 8) == 8)
|
|
10533
|
+
// statusArray.push("System-Uhr ist synchron");
|
|
10534
|
+
// else
|
|
10535
|
+
// statusArray.push("System-Uhr ist nicht synchron");
|
|
10536
|
+
// if ((status & 16) == 16)
|
|
10537
|
+
// statusArray.push("Rücklaufsperre aktiv");
|
|
10538
|
+
// if ((status & 32) == 32)
|
|
10539
|
+
// statusArray.push("Energierichtung -A");
|
|
10540
|
+
// if ((status & 64) == 64)
|
|
10541
|
+
// statusArray.push("Magnetfeld erkannt");
|
|
10542
|
+
// }
|
|
10543
|
+
// catch
|
|
10544
|
+
// {
|
|
10545
|
+
// statusArray.push("Invalid status!");
|
|
10546
|
+
// }
|
|
10547
|
+
// return statusArray;
|
|
10548
|
+
// }
|
|
10549
|
+
// //#endregion
|
|
10493
10550
|
};
|
|
10494
10551
|
|
|
10495
10552
|
// src/CanonicalJSON.ts
|
|
@@ -10889,7 +10946,7 @@ var EMHCrypt01 = class extends ACrypt {
|
|
|
10889
10946
|
measurementValue.result = cryptoResult;
|
|
10890
10947
|
return cryptoResult;
|
|
10891
10948
|
}
|
|
10892
|
-
if (measurementValue.measurement
|
|
10949
|
+
if (measurementValue.measurement?.chargingSession === void 0) {
|
|
10893
10950
|
return {
|
|
10894
10951
|
status: "InvalidMeasurement" /* InvalidMeasurement */
|
|
10895
10952
|
};
|
|
@@ -10928,9 +10985,10 @@ var EMHCrypt01 = class extends ACrypt {
|
|
|
10928
10985
|
cryptoResult.meter = meter;
|
|
10929
10986
|
if (meter.publicKeys != null && meter.publicKeys.length > 0) {
|
|
10930
10987
|
try {
|
|
10931
|
-
|
|
10932
|
-
cryptoResult.
|
|
10933
|
-
cryptoResult.
|
|
10988
|
+
const publicKey = meter.publicKeys.at(0);
|
|
10989
|
+
cryptoResult.publicKey = publicKey?.value?.toLowerCase();
|
|
10990
|
+
cryptoResult.publicKeyFormat = publicKey?.format;
|
|
10991
|
+
cryptoResult.publicKeySignatures = publicKey?.signatures;
|
|
10934
10992
|
try {
|
|
10935
10993
|
if (this.curve.keyFromPublic(cryptoResult.publicKey ?? "", "hex").verify(
|
|
10936
10994
|
cryptoResult.sha256value,
|
|
@@ -10955,59 +11013,60 @@ var EMHCrypt01 = class extends ACrypt {
|
|
|
10955
11013
|
}
|
|
10956
11014
|
return {};
|
|
10957
11015
|
}
|
|
10958
|
-
async ViewMeasurement(measurementValue,
|
|
10959
|
-
if (measurementValue.measurement
|
|
11016
|
+
async ViewMeasurement(measurementValue, _errorDiv, introDiv, infoDiv, PlainTextDiv, HashedPlainTextDiv, PublicKeyDiv, SignatureExpectedDiv, SignatureCheckDiv) {
|
|
11017
|
+
if (measurementValue.measurement?.chargingSession?.authorizationStart.timestamp === void 0) {
|
|
10960
11018
|
return new Error("Invalid measurement!");
|
|
10961
11019
|
}
|
|
10962
11020
|
const result = measurementValue.result;
|
|
10963
11021
|
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);
|
|
10964
11022
|
{
|
|
10965
|
-
if (PlainTextDiv.parentElement
|
|
10966
|
-
PlainTextDiv.parentElement.children
|
|
11023
|
+
if (PlainTextDiv.parentElement) {
|
|
11024
|
+
getArrayLikeElement(PlainTextDiv.parentElement.children, 0, "Missing plain text header").innerHTML = "Plain text (320 Bytes, hex)";
|
|
10967
11025
|
}
|
|
10968
11026
|
PlainTextDiv.style.fontFamily = "";
|
|
10969
11027
|
PlainTextDiv.style.whiteSpace = "";
|
|
10970
11028
|
PlainTextDiv.style.maxHeight = "";
|
|
10971
11029
|
PlainTextDiv.style.overflowY = "";
|
|
10972
|
-
this.CreateLine("Z\xE4hlernummer", measurementValue.measurement.energyMeterId, result.meterId
|
|
10973
|
-
this.CreateLine("Zeitstempel", UTC2human(measurementValue.timestamp), result.timestamp
|
|
10974
|
-
this.CreateLine("Status", hex2bin(measurementValue.infoStatus) + " (" + measurementValue.infoStatus + ' hex)<br /><span class="statusInfos">' + this.DecodeStatus(measurementValue.infoStatus).join("<br />") + "</span>", result.infoStatus
|
|
10975
|
-
this.CreateLine("Sekundenindex", measurementValue.secondsIndex, result.secondsIndex
|
|
10976
|
-
this.CreateLine("Paginierungsz\xE4hler", parseInt(measurementValue.paginationId, 16), result.paginationId
|
|
10977
|
-
this.CreateLine("OBIS-Kennzahl", measurementValue.measurement.obis, result.obis
|
|
10978
|
-
this.CreateLine("Einheit (codiert)", measurementValue.measurement.unitEncoded ?? 0, result.unitEncoded
|
|
10979
|
-
this.CreateLine("Skalierung", measurementValue.measurement.scale, result.scale
|
|
10980
|
-
this.CreateLine("Messwert", measurementValue.value.toString() + " Wh", result.value
|
|
10981
|
-
this.CreateLine("Logbuchindex", measurementValue.logBookIndex + " hex", result.logBookIndex
|
|
10982
|
-
this.CreateLine("Autorisierung", measurementValue.measurement.chargingSession.authorizationStart["@id"] + " hex", pad(result.authorizationStart, 128)
|
|
10983
|
-
this.CreateLine("Autorisierungszeitpunkt", UTC2human(measurementValue.measurement.chargingSession.authorizationStart.timestamp), pad(result.authorizationStartTimestamp, 151)
|
|
11030
|
+
this.CreateLine("Z\xE4hlernummer", measurementValue.measurement.energyMeterId, result.meterId ?? "", infoDiv, PlainTextDiv);
|
|
11031
|
+
this.CreateLine("Zeitstempel", UTC2human(measurementValue.timestamp), result.timestamp ?? "", infoDiv, PlainTextDiv);
|
|
11032
|
+
this.CreateLine("Status", hex2bin(measurementValue.infoStatus) + " (" + measurementValue.infoStatus + ' hex)<br /><span class="statusInfos">' + this.DecodeStatus(measurementValue.infoStatus).join("<br />") + "</span>", result.infoStatus ?? "", infoDiv, PlainTextDiv);
|
|
11033
|
+
this.CreateLine("Sekundenindex", measurementValue.secondsIndex, result.secondsIndex ?? "", infoDiv, PlainTextDiv);
|
|
11034
|
+
this.CreateLine("Paginierungsz\xE4hler", parseInt(measurementValue.paginationId, 16), result.paginationId ?? "", infoDiv, PlainTextDiv);
|
|
11035
|
+
this.CreateLine("OBIS-Kennzahl", measurementValue.measurement.obis, result.obis ?? "", infoDiv, PlainTextDiv);
|
|
11036
|
+
this.CreateLine("Einheit (codiert)", measurementValue.measurement.unitEncoded ?? 0, result.unitEncoded ?? "", infoDiv, PlainTextDiv);
|
|
11037
|
+
this.CreateLine("Skalierung", measurementValue.measurement.scale, result.scale ?? "", infoDiv, PlainTextDiv);
|
|
11038
|
+
this.CreateLine("Messwert", measurementValue.value.toString() + " Wh", result.value ?? "", infoDiv, PlainTextDiv);
|
|
11039
|
+
this.CreateLine("Logbuchindex", measurementValue.logBookIndex + " hex", result.logBookIndex ?? "", infoDiv, PlainTextDiv);
|
|
11040
|
+
this.CreateLine("Autorisierung", measurementValue.measurement.chargingSession.authorizationStart["@id"] + " hex", pad(result.authorizationStart, 128), infoDiv, PlainTextDiv);
|
|
11041
|
+
this.CreateLine("Autorisierungszeitpunkt", UTC2human(measurementValue.measurement.chargingSession.authorizationStart.timestamp), pad(result.authorizationStartTimestamp, 151), infoDiv, PlainTextDiv);
|
|
10984
11042
|
}
|
|
10985
11043
|
{
|
|
10986
|
-
if (HashedPlainTextDiv.parentElement
|
|
10987
|
-
HashedPlainTextDiv.parentElement.children
|
|
11044
|
+
if (HashedPlainTextDiv.parentElement) {
|
|
11045
|
+
getArrayLikeElement(HashedPlainTextDiv.parentElement.children, 0, "Missing hashed plain text header").innerHTML = "Hashed plain text (SHA256, 24 bytes, hex)";
|
|
10988
11046
|
}
|
|
10989
11047
|
HashedPlainTextDiv.innerHTML = result.sha256value?.match(/.{1,8}/g)?.join(" ") ?? "";
|
|
10990
11048
|
}
|
|
10991
11049
|
if (result.publicKey != null && result.publicKey != "") {
|
|
10992
|
-
if (PublicKeyDiv.parentElement
|
|
10993
|
-
PublicKeyDiv.parentElement.children
|
|
11050
|
+
if (PublicKeyDiv.parentElement) {
|
|
11051
|
+
getArrayLikeElement(PublicKeyDiv.parentElement.children, 0, "Missing public key header").innerHTML = "Public Key (" + (result.publicKeyFormat != null && result.publicKeyFormat.length > 0 ? result.publicKeyFormat + ", " : "") + "hex)";
|
|
10994
11052
|
}
|
|
10995
11053
|
if (!IsNullOrEmpty(result.publicKey))
|
|
10996
11054
|
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(" ") ?? "";
|
|
10997
|
-
|
|
10998
|
-
|
|
11055
|
+
const publicKeySignatureContainer = PublicKeyDiv.parentElement?.children[3];
|
|
11056
|
+
if (publicKeySignatureContainer !== void 0) {
|
|
11057
|
+
publicKeySignatureContainer.innerHTML = "";
|
|
10999
11058
|
}
|
|
11000
11059
|
if (result.publicKeySignatures) {
|
|
11001
11060
|
for (const signature of result.publicKeySignatures) {
|
|
11002
11061
|
try {
|
|
11003
|
-
const signatureDiv =
|
|
11062
|
+
const signatureDiv = publicKeySignatureContainer?.appendChild(document.createElement("div"));
|
|
11004
11063
|
if (signatureDiv) {
|
|
11005
11064
|
signatureDiv.classList.add("signature");
|
|
11006
11065
|
signatureDiv.innerHTML = await this.chargy.CheckMeterPublicKeySignature(
|
|
11007
11066
|
measurementValue.measurement.chargingSession.chargingStation,
|
|
11008
11067
|
measurementValue.measurement.chargingSession.EVSE,
|
|
11009
|
-
measurementValue.measurement.chargingSession.EVSE?.meters
|
|
11010
|
-
measurementValue.measurement.chargingSession.EVSE?.meters
|
|
11068
|
+
measurementValue.measurement.chargingSession.EVSE?.meters.at(0),
|
|
11069
|
+
measurementValue.measurement.chargingSession.EVSE?.meters.at(0)?.publicKeys?.at(0),
|
|
11011
11070
|
signature
|
|
11012
11071
|
);
|
|
11013
11072
|
signatureDiv.onclick = () => {
|
|
@@ -11021,12 +11080,12 @@ var EMHCrypt01 = class extends ACrypt {
|
|
|
11021
11080
|
}
|
|
11022
11081
|
}
|
|
11023
11082
|
if (result.signature != null) {
|
|
11024
|
-
if (SignatureExpectedDiv.parentElement
|
|
11025
|
-
SignatureExpectedDiv.parentElement.children
|
|
11083
|
+
if (SignatureExpectedDiv.parentElement) {
|
|
11084
|
+
getArrayLikeElement(SignatureExpectedDiv.parentElement.children, 0, "Missing expected signature header").innerHTML = "Erwartete Signatur (" + (result.signature.format ?? "") + ", hex)";
|
|
11026
11085
|
}
|
|
11027
|
-
if (result.signature.r && result.signature.s)
|
|
11086
|
+
if (result.signature.r != null && result.signature.r.length > 0 && result.signature.s != null && result.signature.s.length > 0)
|
|
11028
11087
|
SignatureExpectedDiv.innerHTML = "r: " + (result.signature.r.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "") + "<br />s: " + (result.signature.s.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "");
|
|
11029
|
-
else if (result.signature.value)
|
|
11088
|
+
else if (result.signature.value != null && result.signature.value.length > 0)
|
|
11030
11089
|
SignatureExpectedDiv.innerHTML = result.signature.value.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "-";
|
|
11031
11090
|
}
|
|
11032
11091
|
{
|
|
@@ -11054,6 +11113,7 @@ var EMHCrypt01 = class extends ACrypt {
|
|
|
11054
11113
|
break;
|
|
11055
11114
|
}
|
|
11056
11115
|
}
|
|
11116
|
+
return void 0;
|
|
11057
11117
|
}
|
|
11058
11118
|
//#region Helper methods
|
|
11059
11119
|
DecodeStatus(statusValue) {
|
|
@@ -11122,7 +11182,7 @@ var GDFCrypt01 = class extends ACrypt {
|
|
|
11122
11182
|
measurementValue.result = cryptoResult;
|
|
11123
11183
|
return cryptoResult;
|
|
11124
11184
|
}
|
|
11125
|
-
if (measurementValue.measurement
|
|
11185
|
+
if (measurementValue.measurement?.chargingSession === void 0) {
|
|
11126
11186
|
return {
|
|
11127
11187
|
status: "InvalidMeasurement" /* InvalidMeasurement */
|
|
11128
11188
|
};
|
|
@@ -11157,9 +11217,10 @@ var GDFCrypt01 = class extends ACrypt {
|
|
|
11157
11217
|
cryptoResult.meter = meter;
|
|
11158
11218
|
if (meter.publicKeys != null && meter.publicKeys.length > 0) {
|
|
11159
11219
|
try {
|
|
11160
|
-
|
|
11161
|
-
cryptoResult.
|
|
11162
|
-
cryptoResult.
|
|
11220
|
+
const publicKey = meter.publicKeys.at(0);
|
|
11221
|
+
cryptoResult.publicKey = publicKey?.value?.toLowerCase();
|
|
11222
|
+
cryptoResult.publicKeyFormat = publicKey?.format;
|
|
11223
|
+
cryptoResult.publicKeySignatures = publicKey?.signatures;
|
|
11163
11224
|
try {
|
|
11164
11225
|
if (this.curve.keyFromPublic(cryptoResult.publicKey ?? "", "hex").verify(
|
|
11165
11226
|
cryptoResult.sha256value,
|
|
@@ -11184,54 +11245,55 @@ var GDFCrypt01 = class extends ACrypt {
|
|
|
11184
11245
|
}
|
|
11185
11246
|
return {};
|
|
11186
11247
|
}
|
|
11187
|
-
async ViewMeasurement(measurementValue,
|
|
11188
|
-
if (measurementValue.measurement
|
|
11248
|
+
async ViewMeasurement(measurementValue, _errorDiv, introDiv, infoDiv, PlainTextDiv, HashedPlainTextDiv, PublicKeyDiv, SignatureExpectedDiv, SignatureCheckDiv) {
|
|
11249
|
+
if (measurementValue.measurement?.chargingSession?.authorizationStart.timestamp === void 0) {
|
|
11189
11250
|
return new Error("Invalid measurement!");
|
|
11190
11251
|
}
|
|
11191
11252
|
const result = measurementValue.result;
|
|
11192
11253
|
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);
|
|
11193
11254
|
{
|
|
11194
|
-
if (PlainTextDiv.parentElement
|
|
11195
|
-
PlainTextDiv.parentElement.children
|
|
11255
|
+
if (PlainTextDiv.parentElement) {
|
|
11256
|
+
getArrayLikeElement(PlainTextDiv.parentElement.children, 0, "Missing plain text header").innerHTML = "Plain text (320 Bytes, hex)";
|
|
11196
11257
|
}
|
|
11197
11258
|
PlainTextDiv.style.fontFamily = "";
|
|
11198
11259
|
PlainTextDiv.style.whiteSpace = "";
|
|
11199
11260
|
PlainTextDiv.style.maxHeight = "";
|
|
11200
11261
|
PlainTextDiv.style.overflowY = "";
|
|
11201
|
-
this.CreateLine("Z\xE4hlernummer", measurementValue.measurement.energyMeterId, result.meterId
|
|
11202
|
-
this.CreateLine("Zeitstempel", UTC2human(measurementValue.timestamp), result.timestamp
|
|
11203
|
-
this.CreateLine("OBIS-Kennzahl", measurementValue.measurement.obis, result.obis
|
|
11204
|
-
this.CreateLine("Einheit (codiert)", measurementValue.measurement.unitEncoded ?? 0, result.unitEncoded
|
|
11205
|
-
this.CreateLine("Skalierung", measurementValue.measurement.scale, result.scale
|
|
11206
|
-
this.CreateLine("Messwert", measurementValue.value.toString() + " Wh", result.value
|
|
11207
|
-
this.CreateLine("Autorisierung", measurementValue.measurement.chargingSession.authorizationStart["@id"] + " hex", pad(result.authorizationStart, 128)
|
|
11208
|
-
this.CreateLine("Autorisierungszeitpunkt", UTC2human(measurementValue.measurement.chargingSession.authorizationStart.timestamp), pad(result.authorizationStartTimestamp, 151)
|
|
11262
|
+
this.CreateLine("Z\xE4hlernummer", measurementValue.measurement.energyMeterId, result.meterId ?? "", infoDiv, PlainTextDiv);
|
|
11263
|
+
this.CreateLine("Zeitstempel", UTC2human(measurementValue.timestamp), result.timestamp ?? "", infoDiv, PlainTextDiv);
|
|
11264
|
+
this.CreateLine("OBIS-Kennzahl", measurementValue.measurement.obis, result.obis ?? "", infoDiv, PlainTextDiv);
|
|
11265
|
+
this.CreateLine("Einheit (codiert)", measurementValue.measurement.unitEncoded ?? 0, result.unitEncoded ?? "", infoDiv, PlainTextDiv);
|
|
11266
|
+
this.CreateLine("Skalierung", measurementValue.measurement.scale, result.scale ?? "", infoDiv, PlainTextDiv);
|
|
11267
|
+
this.CreateLine("Messwert", measurementValue.value.toString() + " Wh", result.value ?? "", infoDiv, PlainTextDiv);
|
|
11268
|
+
this.CreateLine("Autorisierung", measurementValue.measurement.chargingSession.authorizationStart["@id"] + " hex", pad(result.authorizationStart, 128), infoDiv, PlainTextDiv);
|
|
11269
|
+
this.CreateLine("Autorisierungszeitpunkt", UTC2human(measurementValue.measurement.chargingSession.authorizationStart.timestamp), pad(result.authorizationStartTimestamp, 151), infoDiv, PlainTextDiv);
|
|
11209
11270
|
}
|
|
11210
11271
|
{
|
|
11211
|
-
if (HashedPlainTextDiv.parentElement
|
|
11212
|
-
HashedPlainTextDiv.parentElement.children
|
|
11272
|
+
if (HashedPlainTextDiv.parentElement) {
|
|
11273
|
+
getArrayLikeElement(HashedPlainTextDiv.parentElement.children, 0, "Missing hashed plain text header").innerHTML = "Hashed plain text (SHA256, 24 bytes, hex)";
|
|
11213
11274
|
}
|
|
11214
11275
|
HashedPlainTextDiv.innerHTML = result.sha256value?.match(/.{1,8}/g)?.join(" ") ?? "";
|
|
11215
11276
|
}
|
|
11216
11277
|
if (result.publicKey != null && result.publicKey != "") {
|
|
11217
|
-
if (PublicKeyDiv.parentElement
|
|
11218
|
-
PublicKeyDiv.parentElement.children
|
|
11278
|
+
if (PublicKeyDiv.parentElement) {
|
|
11279
|
+
getArrayLikeElement(PublicKeyDiv.parentElement.children, 0, "Missing public key header").innerHTML = "Public Key (" + (result.publicKeyFormat != null && result.publicKeyFormat.length > 0 ? result.publicKeyFormat + ", " : "") + "hex)";
|
|
11219
11280
|
}
|
|
11220
11281
|
if (!IsNullOrEmpty(result.publicKey))
|
|
11221
11282
|
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(" ") ?? "";
|
|
11222
|
-
|
|
11223
|
-
|
|
11283
|
+
const publicKeySignatureContainer = PublicKeyDiv.parentElement?.children[3];
|
|
11284
|
+
if (publicKeySignatureContainer !== void 0) {
|
|
11285
|
+
publicKeySignatureContainer.innerHTML = "";
|
|
11224
11286
|
}
|
|
11225
11287
|
if (result.publicKeySignatures) {
|
|
11226
11288
|
for (const signature of result.publicKeySignatures) {
|
|
11227
11289
|
try {
|
|
11228
|
-
const signatureDiv =
|
|
11290
|
+
const signatureDiv = publicKeySignatureContainer?.appendChild(document.createElement("div"));
|
|
11229
11291
|
if (signatureDiv != null)
|
|
11230
11292
|
signatureDiv.innerHTML = await this.chargy.CheckMeterPublicKeySignature(
|
|
11231
11293
|
measurementValue.measurement.chargingSession.chargingStation,
|
|
11232
11294
|
measurementValue.measurement.chargingSession.EVSE,
|
|
11233
|
-
measurementValue.measurement.chargingSession.EVSE?.meters
|
|
11234
|
-
measurementValue.measurement.chargingSession.EVSE?.meters
|
|
11295
|
+
measurementValue.measurement.chargingSession.EVSE?.meters.at(0),
|
|
11296
|
+
measurementValue.measurement.chargingSession.EVSE?.meters.at(0)?.publicKeys?.at(0),
|
|
11235
11297
|
signature
|
|
11236
11298
|
);
|
|
11237
11299
|
} catch (exception) {
|
|
@@ -11241,12 +11303,12 @@ var GDFCrypt01 = class extends ACrypt {
|
|
|
11241
11303
|
}
|
|
11242
11304
|
}
|
|
11243
11305
|
if (result.signature != null) {
|
|
11244
|
-
if (SignatureExpectedDiv.parentElement
|
|
11245
|
-
SignatureExpectedDiv.parentElement.children
|
|
11306
|
+
if (SignatureExpectedDiv.parentElement) {
|
|
11307
|
+
getArrayLikeElement(SignatureExpectedDiv.parentElement.children, 0, "Missing expected signature header").innerHTML = "Erwartete Signatur (" + (result.signature.format ?? "") + ", hex)";
|
|
11246
11308
|
}
|
|
11247
|
-
if (result.signature.r && result.signature.s)
|
|
11309
|
+
if (result.signature.r != null && result.signature.r.length > 0 && result.signature.s != null && result.signature.s.length > 0)
|
|
11248
11310
|
SignatureExpectedDiv.innerHTML = "r: " + (result.signature.r.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "") + "<br />s: " + (result.signature.s.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "");
|
|
11249
|
-
else if (result.signature.value)
|
|
11311
|
+
else if (result.signature.value != null && result.signature.value.length > 0)
|
|
11250
11312
|
SignatureExpectedDiv.innerHTML = result.signature.value.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "-";
|
|
11251
11313
|
}
|
|
11252
11314
|
{
|
|
@@ -11274,6 +11336,7 @@ var GDFCrypt01 = class extends ACrypt {
|
|
|
11274
11336
|
break;
|
|
11275
11337
|
}
|
|
11276
11338
|
}
|
|
11339
|
+
return void 0;
|
|
11277
11340
|
}
|
|
11278
11341
|
};
|
|
11279
11342
|
var MENNEKES_EDL40_XMLNS = "http://www.mennekes.de/Mennekes.EdlVerification.xsd";
|
|
@@ -11290,14 +11353,14 @@ var Mennekes = class {
|
|
|
11290
11353
|
if (chargingProcesses.length === 0)
|
|
11291
11354
|
return {
|
|
11292
11355
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
11293
|
-
message: this.chargy.
|
|
11356
|
+
message: this.chargy.GetMultilanguageText("UnknownOrInvalidChargingSessionFormat"),
|
|
11294
11357
|
certainty: 0
|
|
11295
11358
|
};
|
|
11296
11359
|
return await Promise.resolve(this.toChargeTransparencyRecord(chargingProcesses));
|
|
11297
11360
|
} catch (exception) {
|
|
11298
11361
|
return {
|
|
11299
11362
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
11300
|
-
message: "Exception occured: " + (exception instanceof Error ? exception.message : String(exception)),
|
|
11363
|
+
message: this.chargy.GetMultilanguageText("Exception occured: " + (exception instanceof Error ? exception.message : String(exception))),
|
|
11301
11364
|
certainty: 0
|
|
11302
11365
|
};
|
|
11303
11366
|
}
|
|
@@ -11434,7 +11497,10 @@ var MennekesCrypt01 = class extends ACrypt {
|
|
|
11434
11497
|
sessionResult = "InvalidSignature" /* InvalidSignature */;
|
|
11435
11498
|
}
|
|
11436
11499
|
if (sessionResult === "ValidSignature" /* ValidSignature */) {
|
|
11437
|
-
const lawErrors = validateMennekesLawConformity(
|
|
11500
|
+
const lawErrors = validateMennekesLawConformity(
|
|
11501
|
+
measurement.values,
|
|
11502
|
+
this.chargy
|
|
11503
|
+
);
|
|
11438
11504
|
if (lawErrors.length > 0) {
|
|
11439
11505
|
measurement.verificationResult = {
|
|
11440
11506
|
status: "InvalidMeasurement" /* InvalidMeasurement */,
|
|
@@ -11517,7 +11583,7 @@ var MennekesCrypt01 = class extends ACrypt {
|
|
|
11517
11583
|
signedData.byteOffset + signedData.byteLength
|
|
11518
11584
|
);
|
|
11519
11585
|
cryptoResult.hashValue = (await sha256(new DataView(signedDataBuffer))).substring(0, 48);
|
|
11520
|
-
const publicKey = cleanHex(meter.publicKeys
|
|
11586
|
+
const publicKey = cleanHex(meter.publicKeys.at(0)?.value ?? measurement.publicKey);
|
|
11521
11587
|
if (publicKey.length !== 96)
|
|
11522
11588
|
return setResult("InvalidPublicKey" /* InvalidPublicKey */);
|
|
11523
11589
|
const result = this.curve192r1.keyFromPublic("04" + publicKey, "hex").verify(
|
|
@@ -11548,7 +11614,7 @@ var MennekesCrypt01 = class extends ACrypt {
|
|
|
11548
11614
|
PublicKeyDiv.innerHTML = result.publicKey?.match(/.{1,8}/g)?.join(" ") ?? "";
|
|
11549
11615
|
if (SignatureExpectedDiv.parentElement?.children[0])
|
|
11550
11616
|
SignatureExpectedDiv.parentElement.children[0].innerHTML = this.chargy.GetLocalizedMessage("Expected signature") + " (rs, hex)";
|
|
11551
|
-
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(" ") ?? "") : "";
|
|
11617
|
+
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(" ") ?? "") : "";
|
|
11552
11618
|
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>";
|
|
11553
11619
|
return Promise.resolve(void 0);
|
|
11554
11620
|
}
|
|
@@ -11567,10 +11633,7 @@ function parseMennekesXMLDocument(XMLDocument) {
|
|
|
11567
11633
|
throw new Error("No Mennekes ChargingProcess element found!");
|
|
11568
11634
|
if (isLocalName(XMLDocument.documentElement, "ChargingProcess")) {
|
|
11569
11635
|
if (chargingProcesses.length > 1) {
|
|
11570
|
-
|
|
11571
|
-
if (chargingProcess != void 0)
|
|
11572
|
-
return chargingProcess;
|
|
11573
|
-
throw new Error("No Mennekes ChargingProcess found!");
|
|
11636
|
+
return getFirstArrayElement(chargingProcesses, "No Mennekes ChargingProcess found!");
|
|
11574
11637
|
}
|
|
11575
11638
|
}
|
|
11576
11639
|
return {
|
|
@@ -11691,18 +11754,20 @@ function toMennekesMeasurementValue(measurement) {
|
|
|
11691
11754
|
"measurement": void 0
|
|
11692
11755
|
};
|
|
11693
11756
|
}
|
|
11694
|
-
function validateMennekesLawConformity(measurementValues) {
|
|
11757
|
+
function validateMennekesLawConformity(measurementValues, chargy) {
|
|
11695
11758
|
const errors = new Array();
|
|
11696
|
-
const start = measurementValues
|
|
11697
|
-
const end = measurementValues
|
|
11759
|
+
const start = measurementValues.at(0);
|
|
11760
|
+
const end = measurementValues.at(-1);
|
|
11698
11761
|
if (start == null || end == null)
|
|
11699
|
-
return [
|
|
11762
|
+
return [
|
|
11763
|
+
CreateError(chargy.GetMultilanguageText("Mennekes EDL40 requires at least two measurement values."))
|
|
11764
|
+
];
|
|
11700
11765
|
if (start.eventCounter !== end.eventCounter)
|
|
11701
|
-
errors.push("Event counter mismatch.");
|
|
11766
|
+
errors.push(CreateError(chargy.GetMultilanguageText("Event counter mismatch.")));
|
|
11702
11767
|
if (Number(start.paginationId) >= Number(end.paginationId))
|
|
11703
|
-
errors.push("Pagination must increase from start to end.");
|
|
11768
|
+
errors.push(CreateError(chargy.GetMultilanguageText("Pagination must increase from start to end.")));
|
|
11704
11769
|
if (start.value.gt(end.value))
|
|
11705
|
-
errors.push("Meter value must not decrease.");
|
|
11770
|
+
errors.push(CreateError(chargy.GetMultilanguageText("Meter value must not decrease.")));
|
|
11706
11771
|
return errors;
|
|
11707
11772
|
}
|
|
11708
11773
|
function child(parent, localName) {
|
|
@@ -11822,9 +11887,9 @@ var OCMFv1_x = class extends ACrypt {
|
|
|
11822
11887
|
}
|
|
11823
11888
|
async VerifyMeasurement(measurementValue) {
|
|
11824
11889
|
measurementValue.method = this;
|
|
11825
|
-
return {
|
|
11890
|
+
return Promise.resolve({
|
|
11826
11891
|
status: measurementValue.result?.status ?? "Unvalidated" /* Unvalidated */
|
|
11827
|
-
};
|
|
11892
|
+
});
|
|
11828
11893
|
}
|
|
11829
11894
|
PayloadDictionary(Path, Key) {
|
|
11830
11895
|
if (Path === "RD") {
|
|
@@ -11894,7 +11959,7 @@ var OCMFv1_x = class extends ACrypt {
|
|
|
11894
11959
|
return Key;
|
|
11895
11960
|
}
|
|
11896
11961
|
}
|
|
11897
|
-
SignatureDictionary(
|
|
11962
|
+
SignatureDictionary(_Path, Key) {
|
|
11898
11963
|
switch (Key) {
|
|
11899
11964
|
case "SA":
|
|
11900
11965
|
return "Signature Algorithm";
|
|
@@ -11908,16 +11973,16 @@ var OCMFv1_x = class extends ACrypt {
|
|
|
11908
11973
|
return Key;
|
|
11909
11974
|
}
|
|
11910
11975
|
}
|
|
11911
|
-
async ViewMeasurement(measurementValue,
|
|
11976
|
+
async ViewMeasurement(measurementValue, _errorDiv, introDiv, _infoDiv, PlainTextDiv, HashedPlainTextDiv, PublicKeyDiv, SignatureExpectedDiv, SignatureCheckDiv) {
|
|
11912
11977
|
if (!measurementValue.measurement || !measurementValue.ocmfDocument || !measurementValue.measurement.chargingSession) {
|
|
11913
11978
|
return new Error("Invalid measurement!");
|
|
11914
11979
|
}
|
|
11915
11980
|
{
|
|
11916
|
-
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 + ") " : "");
|
|
11981
|
+
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 + ") " : "");
|
|
11917
11982
|
}
|
|
11918
11983
|
{
|
|
11919
|
-
if (PlainTextDiv.parentElement
|
|
11920
|
-
PlainTextDiv.parentElement.children
|
|
11984
|
+
if (PlainTextDiv.parentElement) {
|
|
11985
|
+
getArrayLikeElement(PlainTextDiv.parentElement.children, 0, "Missing plain text header").innerHTML = this.chargy.GetLocalizedMessage("Plain text") + " (OCMF|<" + this.chargy.GetLocalizedMessage("payload") + ">|<" + this.chargy.GetLocalizedMessage("signature") + ">)";
|
|
11921
11986
|
}
|
|
11922
11987
|
PlainTextDiv.innerText = "";
|
|
11923
11988
|
const compactValueDiv = document.createElement("div");
|
|
@@ -11949,29 +12014,30 @@ var OCMFv1_x = class extends ACrypt {
|
|
|
11949
12014
|
};
|
|
11950
12015
|
}
|
|
11951
12016
|
{
|
|
11952
|
-
if (HashedPlainTextDiv.parentElement
|
|
11953
|
-
HashedPlainTextDiv.parentElement.children
|
|
12017
|
+
if (HashedPlainTextDiv.parentElement) {
|
|
12018
|
+
getArrayLikeElement(HashedPlainTextDiv.parentElement.children, 0, "Missing hashed payload header").innerHTML = this.chargy.GetLocalizedMessage("Hashed payload") + " (" + measurementValue.ocmfDocument.hashAlgorithm + ")";
|
|
11954
12019
|
}
|
|
11955
12020
|
HashedPlainTextDiv.innerHTML = measurementValue.ocmfDocument.hashValue.match(/.{1,8}/g)?.join(" ") ?? "0x00000000000000000000000000000000000";
|
|
11956
12021
|
}
|
|
11957
|
-
if (measurementValue.ocmfDocument.publicKey) {
|
|
11958
|
-
if (PublicKeyDiv.parentElement
|
|
11959
|
-
PublicKeyDiv.parentElement.children
|
|
12022
|
+
if (measurementValue.ocmfDocument.publicKey != null) {
|
|
12023
|
+
if (PublicKeyDiv.parentElement) {
|
|
12024
|
+
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 + ")";
|
|
11960
12025
|
}
|
|
11961
12026
|
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(" ") ?? "-");
|
|
11962
12027
|
}
|
|
11963
|
-
|
|
11964
|
-
|
|
12028
|
+
const publicKeySignatureContainer = PublicKeyDiv.parentElement?.children[3];
|
|
12029
|
+
if (publicKeySignatureContainer !== void 0) {
|
|
12030
|
+
publicKeySignatureContainer.innerHTML = "";
|
|
11965
12031
|
const result = measurementValue.result;
|
|
11966
12032
|
if (result.publicKeySignatures) {
|
|
11967
12033
|
for (const signature of result.publicKeySignatures) {
|
|
11968
12034
|
try {
|
|
11969
|
-
const signatureDiv =
|
|
12035
|
+
const signatureDiv = publicKeySignatureContainer.appendChild(document.createElement("div"));
|
|
11970
12036
|
signatureDiv.innerHTML = await this.chargy.CheckMeterPublicKeySignature(
|
|
11971
12037
|
measurementValue.measurement.chargingSession.chargingStation,
|
|
11972
12038
|
measurementValue.measurement.chargingSession.EVSE,
|
|
11973
|
-
measurementValue.measurement.chargingSession.EVSE?.meters
|
|
11974
|
-
measurementValue.measurement.chargingSession.EVSE?.meters
|
|
12039
|
+
measurementValue.measurement.chargingSession.EVSE?.meters.at(0),
|
|
12040
|
+
measurementValue.measurement.chargingSession.EVSE?.meters.at(0)?.publicKeys?.at(0),
|
|
11975
12041
|
signature
|
|
11976
12042
|
);
|
|
11977
12043
|
} catch {
|
|
@@ -11981,8 +12047,8 @@ var OCMFv1_x = class extends ACrypt {
|
|
|
11981
12047
|
}
|
|
11982
12048
|
}
|
|
11983
12049
|
if (measurementValue.ocmfDocument.signature.SD) {
|
|
11984
|
-
if (SignatureExpectedDiv.parentElement
|
|
11985
|
-
SignatureExpectedDiv.parentElement.children
|
|
12050
|
+
if (SignatureExpectedDiv.parentElement) {
|
|
12051
|
+
getArrayLikeElement(SignatureExpectedDiv.parentElement.children, 0, "Missing expected signature header").innerHTML = this.chargy.GetLocalizedMessage("Expected signature") + " (rs, hex)";
|
|
11986
12052
|
}
|
|
11987
12053
|
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(" ") ?? "-");
|
|
11988
12054
|
}
|
|
@@ -12005,6 +12071,7 @@ var OCMFv1_x = class extends ACrypt {
|
|
|
12005
12071
|
break;
|
|
12006
12072
|
}
|
|
12007
12073
|
}
|
|
12074
|
+
return void 0;
|
|
12008
12075
|
}
|
|
12009
12076
|
};
|
|
12010
12077
|
var OCMFTransactionTypes = /* @__PURE__ */ ((OCMFTransactionTypes2) => {
|
|
@@ -12037,274 +12104,276 @@ var OCMF = class {
|
|
|
12037
12104
|
const evseId = asString(containerInfos["EVSEId"]) ?? asString(evseInfo?.["@id"]) ?? "DE*GEF*EVSE*CHARGY*1";
|
|
12038
12105
|
const stationDescription = asJSONObject(chargingStationInfo?.["description"]);
|
|
12039
12106
|
const evseDescription = asJSONObject(evseInfo?.["description"]);
|
|
12040
|
-
const firstOCMDJSONDocument = OCMFJSONDocuments
|
|
12041
|
-
|
|
12042
|
-
|
|
12043
|
-
|
|
12044
|
-
|
|
12045
|
-
|
|
12046
|
-
|
|
12047
|
-
|
|
12048
|
-
|
|
12049
|
-
|
|
12050
|
-
|
|
12051
|
-
|
|
12052
|
-
|
|
12053
|
-
|
|
12054
|
-
|
|
12055
|
-
|
|
12056
|
-
|
|
12057
|
-
|
|
12058
|
-
|
|
12059
|
-
|
|
12060
|
-
|
|
12061
|
-
|
|
12062
|
-
|
|
12063
|
-
|
|
12064
|
-
|
|
12065
|
-
|
|
12066
|
-
|
|
12067
|
-
|
|
12068
|
-
|
|
12069
|
-
|
|
12070
|
-
|
|
12071
|
-
|
|
12072
|
-
|
|
12073
|
-
|
|
12074
|
-
|
|
12075
|
-
|
|
12076
|
-
|
|
12077
|
-
|
|
12078
|
-
|
|
12079
|
-
|
|
12080
|
-
|
|
12081
|
-
|
|
12082
|
-
|
|
12083
|
-
|
|
12084
|
-
|
|
12085
|
-
|
|
12086
|
-
|
|
12087
|
-
|
|
12088
|
-
|
|
12089
|
-
|
|
12090
|
-
|
|
12091
|
-
|
|
12092
|
-
|
|
12093
|
-
|
|
12094
|
-
|
|
12095
|
-
|
|
12096
|
-
|
|
12107
|
+
const firstOCMDJSONDocument = getFirstArrayElement(OCMFJSONDocuments, "Missing first OCMF JSON document");
|
|
12108
|
+
const formatVersion = firstOCMDJSONDocument.payload.FV;
|
|
12109
|
+
const gatewayInformation = firstOCMDJSONDocument.payload.GI ?? firstOCMDJSONDocument.payload.VI;
|
|
12110
|
+
const gatewaySerial = firstOCMDJSONDocument.payload.GS;
|
|
12111
|
+
const gatewayVersion = firstOCMDJSONDocument.payload.GV ?? firstOCMDJSONDocument.payload.VV;
|
|
12112
|
+
const paging = firstOCMDJSONDocument.payload.PG;
|
|
12113
|
+
const meterVendor = firstOCMDJSONDocument.payload.MV;
|
|
12114
|
+
const meterModel = firstOCMDJSONDocument.payload.MM;
|
|
12115
|
+
const meterSerial = firstOCMDJSONDocument.payload.MS;
|
|
12116
|
+
const effectiveMeterSerial = meterSerial ?? gatewaySerial;
|
|
12117
|
+
const meterFirmware = firstOCMDJSONDocument.payload.MF;
|
|
12118
|
+
const identificationStatus = firstOCMDJSONDocument.payload.IS;
|
|
12119
|
+
const identificationLevel = firstOCMDJSONDocument.payload.IL;
|
|
12120
|
+
const identificationFlags = firstOCMDJSONDocument.payload.IF;
|
|
12121
|
+
const identificationType = firstOCMDJSONDocument.payload.IT;
|
|
12122
|
+
const identificationData = firstOCMDJSONDocument.payload.ID;
|
|
12123
|
+
const tariffText = firstOCMDJSONDocument.payload.TT;
|
|
12124
|
+
const controlerFirmwareVersion = firstOCMDJSONDocument.payload.CF;
|
|
12125
|
+
const lossCompensation = firstOCMDJSONDocument.payload.LC;
|
|
12126
|
+
const chargePointIdType = firstOCMDJSONDocument.payload.CT;
|
|
12127
|
+
const chargePointId = firstOCMDJSONDocument.payload.CI;
|
|
12128
|
+
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,
|
|
12129
|
+
// Charge Point and Public Key" section makes the serial-number fields conditionally
|
|
12130
|
+
// mandatory. KEBA KCP30 records identify the signing gateway via GS and omit MS.
|
|
12131
|
+
// Therefore we keep meterSerial and gatewaySerial separate, but require at least one
|
|
12132
|
+
// usable serial number for the CTR meter identity.
|
|
12133
|
+
isMandatoryString(effectiveMeterSerial) && isOptionalString(meterFirmware) && // OCMF 1.x uses boolean IS values. OCMF 0.1 SAFE reference data used status strings
|
|
12134
|
+
// such as "VERIFIED", so accept both forms and preserve the original value in the CTR.
|
|
12135
|
+
(isMandatoryBoolean(identificationStatus) || isMandatoryString(identificationStatus)) && isOptionalString(identificationLevel) && //chargyLib.isMandatoryArrayOfStrings (identificationFlags) &&
|
|
12136
|
+
isOptionalArrayOfStrings(identificationFlags) && // Note: Some vendors do not use this MANDATORY field!
|
|
12137
|
+
// IT is 1..1 in the user-assignment table for transaction records. Some OCMF 1.0
|
|
12138
|
+
// implementations omit it when no user is assigned (IS=false, ID empty). We tolerate
|
|
12139
|
+
// this vendor compatibility case instead of rejecting otherwise valid signatures.
|
|
12140
|
+
isOptionalString(identificationType) && isOptionalString(identificationData) && isOptionalString(tariffText) && isOptionalString(controlerFirmwareVersion) && isOptionalJSONObject(lossCompensation) && isOptionalString(chargePointIdType) && isOptionalString(chargePointId)) {
|
|
12141
|
+
const paginationPrefix = paging.length > 0 ? paging.charAt(0).toLowerCase() : null;
|
|
12142
|
+
const transactionType = paginationPrefix === "t" ? "transaction" /* transaction */ : paginationPrefix === "f" ? "fiscal" /* fiscal */ : "undefined" /* undefined */;
|
|
12143
|
+
const pagination = paging.length > 1 ? parseNumber(paging.substring(1)) : null;
|
|
12144
|
+
if (transactionType === "undefined" /* undefined */) return {
|
|
12145
|
+
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
12146
|
+
message: this.chargy.GetMultilanguageText("The given OCMF data does not have a valid transaction type!"),
|
|
12147
|
+
certainty: 0
|
|
12148
|
+
};
|
|
12149
|
+
if (!isMandatoryNumber(pagination)) return {
|
|
12150
|
+
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
12151
|
+
message: this.chargy.GetMultilanguageText("The given OCMF data does not have a valid pagination counter!"),
|
|
12152
|
+
certainty: 0
|
|
12153
|
+
};
|
|
12154
|
+
if (firstOCMDJSONDocument.payload.RD.length == 0) return {
|
|
12155
|
+
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
12156
|
+
message: this.chargy.GetMultilanguageText("Each OCMF data set must have at least one meter reading!"),
|
|
12157
|
+
certainty: 0
|
|
12158
|
+
};
|
|
12159
|
+
const CTR = {
|
|
12160
|
+
"@id": "?",
|
|
12161
|
+
"@context": "https://open.charging.cloud/contexts/CTR+json",
|
|
12162
|
+
//"@context": [ "https://open.charging.cloud/contexts/CTR+json", "https://open.charging.cloud/contexts/CTR_OCMF+json" ],
|
|
12163
|
+
"begin": "?",
|
|
12164
|
+
"end": "?",
|
|
12165
|
+
"description": {
|
|
12166
|
+
"de": "Alle OCMF-Ladevorg\xE4nge"
|
|
12167
|
+
},
|
|
12168
|
+
"contract": {
|
|
12169
|
+
"@id": identificationData ?? "?",
|
|
12170
|
+
"type": identificationType ?? "?"
|
|
12171
|
+
},
|
|
12172
|
+
"ocmf": {
|
|
12173
|
+
"formatVersion": formatVersion,
|
|
12174
|
+
"gatewayInformation": gatewayInformation,
|
|
12175
|
+
"gatewaySerial": gatewaySerial,
|
|
12176
|
+
"gatewayVersion": gatewayVersion
|
|
12177
|
+
},
|
|
12178
|
+
// "chargingStationOperators": [{
|
|
12179
|
+
"chargingPools": [{
|
|
12180
|
+
"@id": "DE*GEF*POOL*CHARGY*1",
|
|
12181
|
+
"description": { "en": "GraphDefined CHARGY Virtual Charging Pool 1" },
|
|
12182
|
+
"chargingStations": [{
|
|
12183
|
+
"@id": chargingStationId,
|
|
12184
|
+
"description": stationDescription && Object.keys(stationDescription).length > 0 ? stationDescription : { "en": "GraphDefined CHARGY Virtual Charging Station 1" },
|
|
12185
|
+
"firmwareVersion": asString(chargingStationInfo?.["softwareVersion"]) ?? asString(chargingStationInfo?.["firmwareVersion"]),
|
|
12186
|
+
"geoLocation": asJSONObject(chargingStationInfo?.["geoLocation"]),
|
|
12187
|
+
"address": asJSONObject(chargingStationInfo?.["address"]),
|
|
12188
|
+
"EVSEs": [{
|
|
12189
|
+
"@id": evseId,
|
|
12190
|
+
"description": evseDescription && Object.keys(evseDescription).length > 0 ? evseDescription : { "en": "GraphDefined CHARGY Virtual EVSE 1" },
|
|
12191
|
+
"connectors": connectorInfo ? [{
|
|
12192
|
+
"type": asString(connectorInfo["type"]) ?? "",
|
|
12193
|
+
"looses": asNumber(connectorInfo["looses"]) ?? 0
|
|
12194
|
+
}] : void 0,
|
|
12195
|
+
"meters": [{
|
|
12196
|
+
"@id": effectiveMeterSerial,
|
|
12197
|
+
// The signed OCMF payload values always win,
|
|
12198
|
+
// the container infos only fill the gaps!
|
|
12199
|
+
"manufacturer": meterVendor ?? asString(energyMeterInfo?.["manufacturer"]),
|
|
12200
|
+
"manufacturerURL": asString(energyMeterInfo?.["manufacturerURL"]),
|
|
12201
|
+
"model": meterModel ?? asString(energyMeterInfo?.["model"]),
|
|
12202
|
+
"modelURL": asString(energyMeterInfo?.["modelURL"]),
|
|
12203
|
+
"hardwareVersion": asString(energyMeterInfo?.["hardwareVersion"]),
|
|
12204
|
+
"firmwareVersion": meterFirmware ?? asString(energyMeterInfo?.["firmwareVersion"]),
|
|
12205
|
+
"signatureFormat": "https://open.charging.cloud/contexts/EnergyMeterSignatureFormats/OCMFv1.0+json",
|
|
12206
|
+
"publicKeys": [{
|
|
12207
|
+
"algorithm": "?",
|
|
12208
|
+
"encoding": "?",
|
|
12209
|
+
"format": "?",
|
|
12210
|
+
"value": "?"
|
|
12211
|
+
}]
|
|
12212
|
+
}]
|
|
12213
|
+
}]
|
|
12214
|
+
}]
|
|
12215
|
+
}],
|
|
12216
|
+
"chargingSessions": [{
|
|
12217
|
+
"@id": "1554181214441:-1965658344385548683:2",
|
|
12218
|
+
"@context": "https://open.charging.cloud/contexts/SessionSignatureFormats/OCMFv1.0+json",
|
|
12097
12219
|
"begin": "?",
|
|
12098
12220
|
"end": "?",
|
|
12099
|
-
"
|
|
12100
|
-
|
|
12101
|
-
},
|
|
12102
|
-
"contract": {
|
|
12221
|
+
"EVSEId": evseId,
|
|
12222
|
+
"authorizationStart": {
|
|
12103
12223
|
"@id": identificationData ?? "?",
|
|
12104
|
-
"type": identificationType ?? "?"
|
|
12105
|
-
|
|
12106
|
-
|
|
12107
|
-
"
|
|
12108
|
-
|
|
12109
|
-
"gatewaySerial": gatewaySerial,
|
|
12110
|
-
"gatewayVersion": gatewayVersion
|
|
12224
|
+
"type": identificationType ?? "?",
|
|
12225
|
+
"identificationStatus": identificationStatus,
|
|
12226
|
+
"identificationLevel": identificationLevel,
|
|
12227
|
+
"identificationFlags": identificationFlags ?? []
|
|
12228
|
+
// Note: The OCMF documentation expects an empty array!
|
|
12111
12229
|
},
|
|
12112
|
-
|
|
12113
|
-
|
|
12114
|
-
|
|
12115
|
-
|
|
12116
|
-
|
|
12117
|
-
|
|
12118
|
-
|
|
12119
|
-
|
|
12120
|
-
|
|
12121
|
-
|
|
12122
|
-
|
|
12123
|
-
|
|
12124
|
-
|
|
12125
|
-
|
|
12126
|
-
|
|
12127
|
-
|
|
12128
|
-
|
|
12129
|
-
|
|
12130
|
-
|
|
12131
|
-
|
|
12132
|
-
|
|
12133
|
-
|
|
12134
|
-
|
|
12135
|
-
|
|
12136
|
-
|
|
12137
|
-
|
|
12138
|
-
|
|
12139
|
-
|
|
12140
|
-
|
|
12141
|
-
|
|
12142
|
-
|
|
12143
|
-
|
|
12144
|
-
|
|
12145
|
-
|
|
12146
|
-
|
|
12147
|
-
|
|
12148
|
-
|
|
12149
|
-
|
|
12150
|
-
|
|
12151
|
-
|
|
12152
|
-
|
|
12153
|
-
|
|
12154
|
-
|
|
12155
|
-
|
|
12156
|
-
|
|
12157
|
-
|
|
12158
|
-
|
|
12159
|
-
"
|
|
12160
|
-
|
|
12161
|
-
|
|
12162
|
-
|
|
12163
|
-
|
|
12164
|
-
|
|
12165
|
-
|
|
12166
|
-
|
|
12167
|
-
|
|
12168
|
-
|
|
12169
|
-
|
|
12170
|
-
|
|
12171
|
-
|
|
12172
|
-
|
|
12173
|
-
const time = effectiveReading.TM;
|
|
12174
|
-
const transaction = effectiveReading.TX;
|
|
12175
|
-
const readingValue = effectiveReading.RV;
|
|
12176
|
-
const readingIdentification = effectiveReading.RI;
|
|
12177
|
-
const readingUnit = effectiveReading.RU;
|
|
12178
|
-
const readingCurrentType = effectiveReading.RT;
|
|
12179
|
-
const cumulatedLoss = effectiveReading.CL;
|
|
12180
|
-
const errorFlags = effectiveReading.EF;
|
|
12181
|
-
const status = effectiveReading.ST;
|
|
12182
|
-
inheritedReading = effectiveReading;
|
|
12183
|
-
if (isMandatoryString(time) && isOptionalString(transaction) && isMandatoryDecimal(readingValue) && // Note: Some vendors use a JSON string here!
|
|
12184
|
-
isOptionalString(readingIdentification) && isMandatoryString(readingUnit) && isOptionalString(readingCurrentType) && isOptionalDecimal(cumulatedLoss) && isOptionalString(errorFlags) && isMandatoryString(status)) {
|
|
12185
|
-
const timeSplit = time.split(" ");
|
|
12186
|
-
if (timeSplit.length != 2) return {
|
|
12187
|
-
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
12188
|
-
message: this.chargy.GetLocalizedMessage("The given OCMF meter value does not have a valid time format!"),
|
|
12189
|
-
certainty: 0
|
|
12190
|
-
};
|
|
12191
|
-
const timeRegEx = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2},\d{3}[+-]\d{4}$/;
|
|
12192
|
-
const timeStamp = timeSplit[0];
|
|
12193
|
-
if (!isMandatoryString(timeStamp) || !timeRegEx.test(timeStamp)) return {
|
|
12194
|
-
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
12195
|
-
message: this.chargy.GetLocalizedMessage("The given OCMF meter value does not have a valid time sync format!"),
|
|
12196
|
-
certainty: 0
|
|
12197
|
-
};
|
|
12198
|
-
const timeStampISO8601 = this.convertToISO8601(timeStamp);
|
|
12199
|
-
const timeSyncText = timeSplit[1];
|
|
12200
|
-
let timeSync = "unknown" /* unknown */;
|
|
12201
|
-
if (!isMandatoryString(timeSyncText) || !["U", "I", "S", "R"].includes(timeSyncText)) return {
|
|
12202
|
-
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
12203
|
-
message: this.chargy.GetLocalizedMessage("The given OCMF meter value does not have a valid time sync format!"),
|
|
12204
|
-
certainty: 0
|
|
12205
|
-
};
|
|
12206
|
-
switch (timeSyncText) {
|
|
12207
|
-
case "U":
|
|
12208
|
-
timeSync = "unknown" /* unknown */;
|
|
12209
|
-
break;
|
|
12210
|
-
case "I":
|
|
12211
|
-
timeSync = "informative" /* informative */;
|
|
12212
|
-
break;
|
|
12213
|
-
case "S":
|
|
12214
|
-
timeSync = "syncronized" /* syncronized */;
|
|
12215
|
-
break;
|
|
12216
|
-
case "R":
|
|
12217
|
-
timeSync = "relative" /* relative */;
|
|
12218
|
-
break;
|
|
12219
|
-
default:
|
|
12220
|
-
return {
|
|
12221
|
-
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
12222
|
-
message: this.chargy.GetLocalizedMessage("The given OCMF meter value does not have a valid time sync format!"),
|
|
12223
|
-
certainty: 0
|
|
12224
|
-
};
|
|
12225
|
-
}
|
|
12226
|
-
if (transaction && !["B", "C", "X", "E", "L", "R", "A", "P", "S", "T"].includes(transaction)) return {
|
|
12227
|
-
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
12228
|
-
message: this.chargy.GetLocalizedMessage("The given OCMF meter value does not have a valid transaction type!"),
|
|
12229
|
-
certainty: 0
|
|
12230
|
-
};
|
|
12231
|
-
if (!["kWh", "Wh", "mOhm", "uOhm"].includes(readingUnit)) return {
|
|
12232
|
-
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
12233
|
-
message: this.chargy.GetLocalizedMessage("The given OCMF meter value does not have a valid current type!"),
|
|
12234
|
-
certainty: 0
|
|
12235
|
-
};
|
|
12236
|
-
if (readingCurrentType && !["AC", "DC"].includes(readingCurrentType)) return {
|
|
12237
|
-
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
12238
|
-
message: this.chargy.GetLocalizedMessage("The given OCMF meter value does not have a valid current type!"),
|
|
12239
|
-
certainty: 0
|
|
12240
|
-
};
|
|
12241
|
-
if (CTR.chargingSessions?.[0]?.begin === "?")
|
|
12242
|
-
CTR.chargingSessions[0].begin = timeStampISO8601;
|
|
12243
|
-
CTR.chargingSessions[0].end = timeStampISO8601;
|
|
12244
|
-
const measurementKey = [
|
|
12245
|
-
readingIdentification ?? "?",
|
|
12246
|
-
readingUnit,
|
|
12247
|
-
readingCurrentType ?? ""
|
|
12248
|
-
].join("|");
|
|
12249
|
-
let measurement = measurementsByKey.get(measurementKey);
|
|
12250
|
-
if (measurement == null) {
|
|
12251
|
-
measurement = {
|
|
12252
|
-
"name": OBIS2MeasurementName(readingIdentification ?? ""),
|
|
12253
|
-
"scale": 0,
|
|
12254
|
-
"energyMeterId": effectiveMeterSerial,
|
|
12255
|
-
"@context": "https://open.charging.cloud/contexts/EnergyMeterSignatureFormats/OCMFv1.0+json",
|
|
12256
|
-
"obis": readingIdentification ?? "?",
|
|
12257
|
-
// OBIS: "1-b:1.8.0"
|
|
12258
|
-
"unit": readingUnit,
|
|
12259
|
-
// "kWh"
|
|
12260
|
-
"currentType": readingCurrentType,
|
|
12261
|
-
// "AC"
|
|
12262
|
-
"values": []
|
|
12230
|
+
"measurements": []
|
|
12231
|
+
}],
|
|
12232
|
+
"certainty": 1
|
|
12233
|
+
};
|
|
12234
|
+
const measurementsByKey = /* @__PURE__ */ new Map();
|
|
12235
|
+
for (const ocmfJSONDocument of OCMFJSONDocuments) {
|
|
12236
|
+
let inheritedReading = {};
|
|
12237
|
+
for (const reading of ocmfJSONDocument.payload.RD) {
|
|
12238
|
+
const effectiveReading = { ...inheritedReading, ...reading };
|
|
12239
|
+
const time = effectiveReading.TM;
|
|
12240
|
+
const transaction = effectiveReading.TX;
|
|
12241
|
+
const readingValue = effectiveReading.RV;
|
|
12242
|
+
const readingIdentification = effectiveReading.RI;
|
|
12243
|
+
const readingUnit = effectiveReading.RU;
|
|
12244
|
+
const readingCurrentType = effectiveReading.RT;
|
|
12245
|
+
const cumulatedLoss = effectiveReading.CL;
|
|
12246
|
+
const errorFlags = effectiveReading.EF;
|
|
12247
|
+
const status = effectiveReading.ST;
|
|
12248
|
+
inheritedReading = effectiveReading;
|
|
12249
|
+
if (isMandatoryString(time) && isOptionalString(transaction) && isMandatoryDecimal(readingValue) && // Note: Some vendors use a JSON string here!
|
|
12250
|
+
isOptionalString(readingIdentification) && isMandatoryString(readingUnit) && isOptionalString(readingCurrentType) && // chargyLib.isOptionalDecimal (cumulatedLoss) &&
|
|
12251
|
+
isOptionalString(errorFlags) && isMandatoryString(status)) {
|
|
12252
|
+
const timeSplit = time.split(" ");
|
|
12253
|
+
if (timeSplit.length != 2) return {
|
|
12254
|
+
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
12255
|
+
message: this.chargy.GetMultilanguageText("The given OCMF meter value does not have a valid time format!"),
|
|
12256
|
+
certainty: 0
|
|
12257
|
+
};
|
|
12258
|
+
const timeRegEx = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2},\d{3}[+-]\d{4}$/;
|
|
12259
|
+
const timeStamp = timeSplit[0];
|
|
12260
|
+
if (!isMandatoryString(timeStamp) || !timeRegEx.test(timeStamp)) return {
|
|
12261
|
+
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
12262
|
+
message: this.chargy.GetMultilanguageText("The given OCMF meter value does not have a valid time sync format!"),
|
|
12263
|
+
certainty: 0
|
|
12264
|
+
};
|
|
12265
|
+
const timeStampISO8601 = this.convertToISO8601(timeStamp);
|
|
12266
|
+
const timeSyncText = timeSplit[1];
|
|
12267
|
+
let timeSync = "unknown" /* unknown */;
|
|
12268
|
+
if (!isMandatoryString(timeSyncText) || !["U", "I", "S", "R"].includes(timeSyncText)) return {
|
|
12269
|
+
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
12270
|
+
message: this.chargy.GetMultilanguageText("The given OCMF meter value does not have a valid time sync format!"),
|
|
12271
|
+
certainty: 0
|
|
12272
|
+
};
|
|
12273
|
+
switch (timeSyncText) {
|
|
12274
|
+
case "U":
|
|
12275
|
+
timeSync = "unknown" /* unknown */;
|
|
12276
|
+
break;
|
|
12277
|
+
case "I":
|
|
12278
|
+
timeSync = "informative" /* informative */;
|
|
12279
|
+
break;
|
|
12280
|
+
case "S":
|
|
12281
|
+
timeSync = "syncronized" /* syncronized */;
|
|
12282
|
+
break;
|
|
12283
|
+
case "R":
|
|
12284
|
+
timeSync = "relative" /* relative */;
|
|
12285
|
+
break;
|
|
12286
|
+
default:
|
|
12287
|
+
return {
|
|
12288
|
+
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
12289
|
+
message: this.chargy.GetMultilanguageText("The given OCMF meter value does not have a valid time sync format!"),
|
|
12290
|
+
certainty: 0
|
|
12263
12291
|
};
|
|
12264
|
-
measurementsByKey.set(measurementKey, measurement);
|
|
12265
|
-
CTR.chargingSessions[0].measurements.push(measurement);
|
|
12266
|
-
}
|
|
12267
|
-
measurement.values.push({
|
|
12268
|
-
"timestamp": timeStampISO8601,
|
|
12269
|
-
// "2019-06-26T08:57:44,337+0000"
|
|
12270
|
-
"timeSync": timeSync,
|
|
12271
|
-
// "U"|"I"|"S"|"R"
|
|
12272
|
-
"transaction": transaction,
|
|
12273
|
-
// "B"|"C"|"X"|"E"|"L"|"R"|"A"|"P"|"S"|"T"|null
|
|
12274
|
-
"value": new Decimal(readingValue),
|
|
12275
|
-
// 2935.6
|
|
12276
|
-
"transactionType": transactionType,
|
|
12277
|
-
// "T" ToDo: Serialize this to a string!
|
|
12278
|
-
"pagination": pagination,
|
|
12279
|
-
// "9289"
|
|
12280
|
-
"errorFlags": errorFlags,
|
|
12281
|
-
// ""
|
|
12282
|
-
"cumulatedLoss": cumulatedLoss ? new Decimal(cumulatedLoss) : void 0,
|
|
12283
|
-
"status": status,
|
|
12284
|
-
// "G"
|
|
12285
|
-
// "signatures": [{
|
|
12286
|
-
// "value": ocmfJSONDocument.signature["SD"]
|
|
12287
|
-
// }],
|
|
12288
|
-
"result": {
|
|
12289
|
-
"status": ocmfJSONDocument.validationStatus ?? "Unvalidated" /* Unvalidated */
|
|
12290
|
-
},
|
|
12291
|
-
"ocmfDocument": ocmfJSONDocument
|
|
12292
|
-
});
|
|
12293
12292
|
}
|
|
12293
|
+
if (transaction != null && transaction.length > 0 && !["B", "C", "X", "E", "L", "R", "A", "P", "S", "T"].includes(transaction)) return {
|
|
12294
|
+
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
12295
|
+
message: this.chargy.GetMultilanguageText("The given OCMF meter value does not have a valid transaction type!"),
|
|
12296
|
+
certainty: 0
|
|
12297
|
+
};
|
|
12298
|
+
if (!["kWh", "Wh", "mOhm", "uOhm"].includes(readingUnit)) return {
|
|
12299
|
+
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
12300
|
+
message: this.chargy.GetMultilanguageText("The given OCMF meter value does not have a valid current type!"),
|
|
12301
|
+
certainty: 0
|
|
12302
|
+
};
|
|
12303
|
+
if (readingCurrentType != null && readingCurrentType.length > 0 && !["AC", "DC"].includes(readingCurrentType)) return {
|
|
12304
|
+
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
12305
|
+
message: this.chargy.GetMultilanguageText("The given OCMF meter value does not have a valid current type!"),
|
|
12306
|
+
certainty: 0
|
|
12307
|
+
};
|
|
12308
|
+
if (CTR.chargingSessions?.[0]?.begin === "?")
|
|
12309
|
+
CTR.chargingSessions[0].begin = timeStampISO8601;
|
|
12310
|
+
if (CTR.chargingSessions?.[0] !== void 0)
|
|
12311
|
+
CTR.chargingSessions[0].end = timeStampISO8601;
|
|
12312
|
+
const measurementKey = [
|
|
12313
|
+
readingIdentification ?? "?",
|
|
12314
|
+
readingUnit,
|
|
12315
|
+
readingCurrentType ?? ""
|
|
12316
|
+
].join("|");
|
|
12317
|
+
let measurement = measurementsByKey.get(measurementKey);
|
|
12318
|
+
if (measurement == null) {
|
|
12319
|
+
measurement = {
|
|
12320
|
+
"name": OBIS2MeasurementName(readingIdentification ?? ""),
|
|
12321
|
+
"scale": 0,
|
|
12322
|
+
"energyMeterId": effectiveMeterSerial,
|
|
12323
|
+
"@context": "https://open.charging.cloud/contexts/EnergyMeterSignatureFormats/OCMFv1.0+json",
|
|
12324
|
+
"obis": readingIdentification ?? "?",
|
|
12325
|
+
// OBIS: "1-b:1.8.0"
|
|
12326
|
+
"unit": readingUnit,
|
|
12327
|
+
// "kWh"
|
|
12328
|
+
"currentType": readingCurrentType,
|
|
12329
|
+
// "AC"
|
|
12330
|
+
"values": []
|
|
12331
|
+
};
|
|
12332
|
+
measurementsByKey.set(measurementKey, measurement);
|
|
12333
|
+
const firstChargingSession = CTR.chargingSessions?.[0];
|
|
12334
|
+
if (firstChargingSession !== void 0)
|
|
12335
|
+
firstChargingSession.measurements.push(measurement);
|
|
12336
|
+
}
|
|
12337
|
+
measurement.values.push({
|
|
12338
|
+
"timestamp": timeStampISO8601,
|
|
12339
|
+
// "2019-06-26T08:57:44,337+0000"
|
|
12340
|
+
"timeSync": timeSync,
|
|
12341
|
+
// "U"|"I"|"S"|"R"
|
|
12342
|
+
"transaction": transaction,
|
|
12343
|
+
// "B"|"C"|"X"|"E"|"L"|"R"|"A"|"P"|"S"|"T"|null
|
|
12344
|
+
"value": new Decimal(readingValue),
|
|
12345
|
+
// 2935.6
|
|
12346
|
+
"transactionType": transactionType,
|
|
12347
|
+
// "T" ToDo: Serialize this to a string!
|
|
12348
|
+
"pagination": pagination,
|
|
12349
|
+
// "9289"
|
|
12350
|
+
"errorFlags": errorFlags,
|
|
12351
|
+
// ""
|
|
12352
|
+
"cumulatedLoss": cumulatedLoss != null && cumulatedLoss !== 0 ? new Decimal(cumulatedLoss) : void 0,
|
|
12353
|
+
"status": status,
|
|
12354
|
+
// "G"
|
|
12355
|
+
// "signatures": [{
|
|
12356
|
+
// "value": ocmfJSONDocument.signature["SD"]
|
|
12357
|
+
// }],
|
|
12358
|
+
"result": {
|
|
12359
|
+
"status": ocmfJSONDocument.validationStatus ?? "Unvalidated" /* Unvalidated */
|
|
12360
|
+
},
|
|
12361
|
+
"ocmfDocument": ocmfJSONDocument
|
|
12362
|
+
});
|
|
12294
12363
|
}
|
|
12295
12364
|
}
|
|
12296
|
-
|
|
12297
|
-
|
|
12298
|
-
|
|
12299
|
-
|
|
12300
|
-
|
|
12301
|
-
|
|
12365
|
+
}
|
|
12366
|
+
CTR.status = OCMFJSONDocuments.every((ocmfJSONDocument) => ocmfJSONDocument.validationStatus === "ValidSignature" /* ValidSignature */) ? "ValidSignature" /* ValidSignature */ : "InvalidSignature" /* InvalidSignature */;
|
|
12367
|
+
if (CTR.chargingSessions != null && CTR.chargingSessions.length > 0 && CTR.chargingSessions[0]) {
|
|
12368
|
+
CTR.begin = CTR.chargingSessions[0].begin;
|
|
12369
|
+
CTR.end = CTR.chargingSessions[0].end;
|
|
12370
|
+
return CTR;
|
|
12302
12371
|
}
|
|
12303
12372
|
}
|
|
12304
12373
|
} catch (exception) {
|
|
12305
12374
|
return {
|
|
12306
12375
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
12307
|
-
message: "Invalid OCMF data: " + (exception instanceof Error ? exception.message : String(exception)),
|
|
12376
|
+
message: this.chargy.GetMultilanguageText("Invalid OCMF data: " + (exception instanceof Error ? exception.message : String(exception))),
|
|
12308
12377
|
certainty: 0
|
|
12309
12378
|
};
|
|
12310
12379
|
}
|
|
@@ -12315,113 +12384,121 @@ var OCMF = class {
|
|
|
12315
12384
|
}
|
|
12316
12385
|
//#endregion
|
|
12317
12386
|
//#region (private) mergeOCMFSessions(CTRs)
|
|
12318
|
-
mergeOCMFSessions(CTRs)
|
|
12319
|
-
|
|
12320
|
-
|
|
12321
|
-
|
|
12322
|
-
|
|
12323
|
-
|
|
12324
|
-
|
|
12325
|
-
|
|
12326
|
-
|
|
12327
|
-
|
|
12328
|
-
|
|
12329
|
-
|
|
12330
|
-
|
|
12331
|
-
|
|
12332
|
-
|
|
12333
|
-
|
|
12334
|
-
|
|
12335
|
-
|
|
12336
|
-
|
|
12337
|
-
|
|
12338
|
-
|
|
12339
|
-
|
|
12340
|
-
|
|
12341
|
-
|
|
12342
|
-
|
|
12343
|
-
|
|
12344
|
-
|
|
12345
|
-
|
|
12346
|
-
|
|
12347
|
-
|
|
12348
|
-
|
|
12349
|
-
|
|
12350
|
-
|
|
12351
|
-
|
|
12352
|
-
|
|
12353
|
-
|
|
12354
|
-
|
|
12355
|
-
|
|
12356
|
-
|
|
12357
|
-
|
|
12358
|
-
|
|
12359
|
-
|
|
12360
|
-
|
|
12361
|
-
|
|
12362
|
-
|
|
12363
|
-
|
|
12364
|
-
|
|
12365
|
-
|
|
12366
|
-
|
|
12367
|
-
|
|
12368
|
-
|
|
12369
|
-
|
|
12387
|
+
// private mergeOCMFSessions(CTRs: Array<IOCMFChargeTransparencyRecord>): IOCMFChargeTransparencyRecord
|
|
12388
|
+
// {
|
|
12389
|
+
// const mergedCTR:IOCMFChargeTransparencyRecord = {
|
|
12390
|
+
// "@id": "",
|
|
12391
|
+
// "@context": "",
|
|
12392
|
+
// certainty: 1
|
|
12393
|
+
// };
|
|
12394
|
+
// for (const ctr of CTRs)
|
|
12395
|
+
// {
|
|
12396
|
+
// if (mergedCTR["@id"] === "")
|
|
12397
|
+
// mergedCTR["@id"] = ctr["@id"];
|
|
12398
|
+
// if (mergedCTR["@context"] === "")
|
|
12399
|
+
// mergedCTR["@context"] = ctr["@context"];
|
|
12400
|
+
// if (!mergedCTR.begin || (mergedCTR.begin && ctr.begin && mergedCTR.begin > ctr.begin))
|
|
12401
|
+
// mergedCTR.begin = ctr.begin;
|
|
12402
|
+
// if (!mergedCTR.end || (mergedCTR.end && ctr.end && mergedCTR.end < ctr.end))
|
|
12403
|
+
// mergedCTR.end = ctr.end;
|
|
12404
|
+
// if (!mergedCTR.description)
|
|
12405
|
+
// mergedCTR.description = ctr.description;
|
|
12406
|
+
// //ToDo: Is this a really good idea? Or should we fail, whenever this information is different?
|
|
12407
|
+
// if (!mergedCTR.contract)
|
|
12408
|
+
// mergedCTR.contract = ctr.contract;
|
|
12409
|
+
// if (!mergedCTR.chargingStationOperators)
|
|
12410
|
+
// mergedCTR.chargingStationOperators = ctr.chargingStationOperators;
|
|
12411
|
+
// else if (ctr.chargingStationOperators)
|
|
12412
|
+
// for (const chargingStationOperator of ctr.chargingStationOperators)
|
|
12413
|
+
// mergedCTR.chargingStationOperators.push(chargingStationOperator);
|
|
12414
|
+
// if (!mergedCTR.chargingPools)
|
|
12415
|
+
// mergedCTR.chargingPools = ctr.chargingPools;
|
|
12416
|
+
// else if (ctr.chargingPools)
|
|
12417
|
+
// for (const chargingPool of ctr.chargingPools)
|
|
12418
|
+
// mergedCTR.chargingPools.push(chargingPool);
|
|
12419
|
+
// if (!mergedCTR.chargingStations)
|
|
12420
|
+
// mergedCTR.chargingStations = ctr.chargingStations;
|
|
12421
|
+
// else if (ctr.chargingStations)
|
|
12422
|
+
// for (const chargingStation of ctr.chargingStations)
|
|
12423
|
+
// mergedCTR.chargingStations.push(chargingStation);
|
|
12424
|
+
// // publicKeys
|
|
12425
|
+
// if (!mergedCTR.chargingSessions)
|
|
12426
|
+
// mergedCTR.chargingSessions = ctr.chargingSessions;
|
|
12427
|
+
// else if (ctr.chargingSessions)
|
|
12428
|
+
// for (const chargingSession of ctr.chargingSessions)
|
|
12429
|
+
// mergedCTR.chargingSessions.push(chargingSession);
|
|
12430
|
+
// if (!mergedCTR.eMobilityProviders)
|
|
12431
|
+
// mergedCTR.eMobilityProviders = ctr.eMobilityProviders;
|
|
12432
|
+
// else if (ctr.eMobilityProviders)
|
|
12433
|
+
// for (const eMobilityProvider of ctr.eMobilityProviders)
|
|
12434
|
+
// mergedCTR.eMobilityProviders.push(eMobilityProvider);
|
|
12435
|
+
// if (!mergedCTR.mediationServices)
|
|
12436
|
+
// mergedCTR.mediationServices = ctr.mediationServices;
|
|
12437
|
+
// else if (ctr.mediationServices)
|
|
12438
|
+
// for (const mediationService of ctr.mediationServices)
|
|
12439
|
+
// mergedCTR.mediationServices.push(mediationService);
|
|
12440
|
+
// }
|
|
12441
|
+
// return mergedCTR;
|
|
12442
|
+
// }
|
|
12370
12443
|
//#endregion
|
|
12371
12444
|
//#region (private) mergeChargeTransparencyRecords(CTRs)
|
|
12372
|
-
mergeChargeTransparencyRecords(CTRs)
|
|
12373
|
-
|
|
12374
|
-
|
|
12375
|
-
|
|
12376
|
-
|
|
12377
|
-
|
|
12378
|
-
|
|
12379
|
-
|
|
12380
|
-
|
|
12381
|
-
|
|
12382
|
-
|
|
12383
|
-
|
|
12384
|
-
|
|
12385
|
-
|
|
12386
|
-
|
|
12387
|
-
|
|
12388
|
-
|
|
12389
|
-
|
|
12390
|
-
|
|
12391
|
-
|
|
12392
|
-
|
|
12393
|
-
|
|
12394
|
-
|
|
12395
|
-
|
|
12396
|
-
|
|
12397
|
-
|
|
12398
|
-
|
|
12399
|
-
|
|
12400
|
-
|
|
12401
|
-
|
|
12402
|
-
|
|
12403
|
-
|
|
12404
|
-
|
|
12405
|
-
|
|
12406
|
-
|
|
12407
|
-
|
|
12408
|
-
|
|
12409
|
-
|
|
12410
|
-
|
|
12411
|
-
|
|
12412
|
-
|
|
12413
|
-
|
|
12414
|
-
|
|
12415
|
-
|
|
12416
|
-
|
|
12417
|
-
|
|
12418
|
-
|
|
12419
|
-
|
|
12420
|
-
|
|
12421
|
-
|
|
12422
|
-
|
|
12423
|
-
|
|
12424
|
-
|
|
12445
|
+
// private mergeChargeTransparencyRecords(CTRs: Array<IOCMFChargeTransparencyRecord>): IOCMFChargeTransparencyRecord
|
|
12446
|
+
// {
|
|
12447
|
+
// const mergedCTR:IOCMFChargeTransparencyRecord = {
|
|
12448
|
+
// "@id": "",
|
|
12449
|
+
// "@context": "",
|
|
12450
|
+
// certainty: 1
|
|
12451
|
+
// };
|
|
12452
|
+
// for (const ctr of CTRs)
|
|
12453
|
+
// {
|
|
12454
|
+
// if (mergedCTR["@id"] === "")
|
|
12455
|
+
// mergedCTR["@id"] = ctr["@id"];
|
|
12456
|
+
// if (mergedCTR["@context"] === "")
|
|
12457
|
+
// mergedCTR["@context"] = ctr["@context"];
|
|
12458
|
+
// if (!mergedCTR.begin || (mergedCTR.begin && ctr.begin && mergedCTR.begin > ctr.begin))
|
|
12459
|
+
// mergedCTR.begin = ctr.begin;
|
|
12460
|
+
// if (!mergedCTR.end || (mergedCTR.end && ctr.end && mergedCTR.end < ctr.end))
|
|
12461
|
+
// mergedCTR.end = ctr.end;
|
|
12462
|
+
// if (!mergedCTR.description)
|
|
12463
|
+
// mergedCTR.description = ctr.description;
|
|
12464
|
+
// //ToDo: Is this a really good idea? Or should we fail, whenever this information is different?
|
|
12465
|
+
// if (!mergedCTR.contract)
|
|
12466
|
+
// mergedCTR.contract = ctr.contract;
|
|
12467
|
+
// if (!mergedCTR.chargingStationOperators)
|
|
12468
|
+
// mergedCTR.chargingStationOperators = ctr.chargingStationOperators;
|
|
12469
|
+
// else if (ctr.chargingStationOperators)
|
|
12470
|
+
// for (const chargingStationOperator of ctr.chargingStationOperators)
|
|
12471
|
+
// mergedCTR.chargingStationOperators.push(chargingStationOperator);
|
|
12472
|
+
// if (!mergedCTR.chargingPools)
|
|
12473
|
+
// mergedCTR.chargingPools = ctr.chargingPools;
|
|
12474
|
+
// else if (ctr.chargingPools)
|
|
12475
|
+
// for (const chargingPool of ctr.chargingPools)
|
|
12476
|
+
// mergedCTR.chargingPools.push(chargingPool);
|
|
12477
|
+
// if (!mergedCTR.chargingStations)
|
|
12478
|
+
// mergedCTR.chargingStations = ctr.chargingStations;
|
|
12479
|
+
// else if (ctr.chargingStations)
|
|
12480
|
+
// for (const chargingStation of ctr.chargingStations)
|
|
12481
|
+
// mergedCTR.chargingStations.push(chargingStation);
|
|
12482
|
+
// // publicKeys
|
|
12483
|
+
// if (!mergedCTR.chargingSessions)
|
|
12484
|
+
// mergedCTR.chargingSessions = ctr.chargingSessions;
|
|
12485
|
+
// else if (ctr.chargingSessions)
|
|
12486
|
+
// for (const chargingSession of ctr.chargingSessions)
|
|
12487
|
+
// mergedCTR.chargingSessions.push(chargingSession);
|
|
12488
|
+
// if (!mergedCTR.eMobilityProviders)
|
|
12489
|
+
// mergedCTR.eMobilityProviders = ctr.eMobilityProviders;
|
|
12490
|
+
// else if (ctr.eMobilityProviders)
|
|
12491
|
+
// for (const eMobilityProvider of ctr.eMobilityProviders)
|
|
12492
|
+
// mergedCTR.eMobilityProviders.push(eMobilityProvider);
|
|
12493
|
+
// if (!mergedCTR.mediationServices)
|
|
12494
|
+
// mergedCTR.mediationServices = ctr.mediationServices;
|
|
12495
|
+
// else if (ctr.mediationServices)
|
|
12496
|
+
// for (const mediationService of ctr.mediationServices)
|
|
12497
|
+
// mergedCTR.mediationServices.push(mediationService);
|
|
12498
|
+
// }
|
|
12499
|
+
// return mergedCTR;
|
|
12500
|
+
// }
|
|
12501
|
+
// //#endregion
|
|
12425
12502
|
//#region (private) validateOCMFSignature(OCMFJSONDocument, PublicKey, PublicKeyEncoding?)
|
|
12426
12503
|
async validateOCMFSignature(OCMFJSONDocument, PublicKey, PublicKeyEncoding) {
|
|
12427
12504
|
try {
|
|
@@ -12480,7 +12557,7 @@ var OCMF = class {
|
|
|
12480
12557
|
this.key("pubKey").bitstr()
|
|
12481
12558
|
);
|
|
12482
12559
|
});
|
|
12483
|
-
if (PublicKeyEncoding) {
|
|
12560
|
+
if (PublicKeyEncoding != null && PublicKeyEncoding.length > 0) {
|
|
12484
12561
|
switch (PublicKeyEncoding.toLowerCase()) {
|
|
12485
12562
|
case "hex":
|
|
12486
12563
|
publicKeyBytes = Buffer.from(OCMFJSONDocument.publicKey, "hex");
|
|
@@ -12508,11 +12585,12 @@ var OCMF = class {
|
|
|
12508
12585
|
publicKeyBytes = Buffer.from(OCMFJSONDocument.publicKey, "base64");
|
|
12509
12586
|
}
|
|
12510
12587
|
}
|
|
12511
|
-
if (
|
|
12588
|
+
if (publicKeyBytes == null) {
|
|
12512
12589
|
OCMFJSONDocument.validationStatus = "UnknownPublicKeyFormat" /* UnknownPublicKeyFormat */;
|
|
12513
12590
|
return OCMFJSONDocument.validationStatus;
|
|
12514
12591
|
}
|
|
12515
|
-
const
|
|
12592
|
+
const decodedPublicKeyASN1 = ECPoint.decode(publicKeyBytes, "der");
|
|
12593
|
+
const publicKeyASN1 = decodedPublicKeyASN1;
|
|
12516
12594
|
const coordinates = publicKeyASN1.pubKey.data.subarray(1);
|
|
12517
12595
|
const halfLength = coordinates.length / 2;
|
|
12518
12596
|
const publicKeyXY = {
|
|
@@ -12521,7 +12599,7 @@ var OCMF = class {
|
|
|
12521
12599
|
};
|
|
12522
12600
|
publicKey = curve.keyFromPublic(publicKeyXY, "hex");
|
|
12523
12601
|
OCMFJSONDocument.publicKey = {
|
|
12524
|
-
algorithm: OCMFJSONDocument.signature.SA ? OCMFJSONDocument.signature.SA.substring(
|
|
12602
|
+
algorithm: OCMFJSONDocument.signature.SA != null && OCMFJSONDocument.signature.SA.length > 0 ? OCMFJSONDocument.signature.SA.substring(
|
|
12525
12603
|
OCMFJSONDocument.signature.SA.indexOf("-") + 1,
|
|
12526
12604
|
OCMFJSONDocument.signature.SA.lastIndexOf("-")
|
|
12527
12605
|
) : "secp256r1",
|
|
@@ -12672,7 +12750,7 @@ var OCMF = class {
|
|
|
12672
12750
|
hashValue,
|
|
12673
12751
|
publicKey: PublicKey,
|
|
12674
12752
|
publicKeyEncoding: PublicKeyEncoding,
|
|
12675
|
-
validationStatus: validationStatus
|
|
12753
|
+
validationStatus: validationStatus ?? (PublicKey != null ? "Unvalidated" /* Unvalidated */ : "PublicKeyNotFound" /* PublicKeyNotFound */)
|
|
12676
12754
|
};
|
|
12677
12755
|
try {
|
|
12678
12756
|
const ECDSASignature = this.chargy.asn1.define("ECDSASignature", function() {
|
|
@@ -12694,7 +12772,8 @@ var OCMF = class {
|
|
|
12694
12772
|
default:
|
|
12695
12773
|
ocmfJSONDocument.validationStatus = "UnknownSignatureFormat" /* UnknownSignatureFormat */;
|
|
12696
12774
|
}
|
|
12697
|
-
const
|
|
12775
|
+
const decodedSignatureObj = ECDSASignature.decode(Buffer.from(ocmfJSONDocument.signature.SD, bufferEncoding), "der");
|
|
12776
|
+
const signatureObj = decodedSignatureObj;
|
|
12698
12777
|
ocmfJSONDocument.signatureRS = {
|
|
12699
12778
|
value: ocmfJSONDocument.signature.SD,
|
|
12700
12779
|
r: signatureObj.r.toString(16),
|
|
@@ -12703,7 +12782,7 @@ var OCMF = class {
|
|
|
12703
12782
|
} catch {
|
|
12704
12783
|
ocmfJSONDocument.validationStatus = "InvalidSignature" /* InvalidSignature */;
|
|
12705
12784
|
}
|
|
12706
|
-
if (PublicKey && ocmfJSONDocument.validationStatus === "Unvalidated" /* Unvalidated */)
|
|
12785
|
+
if (PublicKey != null && ocmfJSONDocument.validationStatus === "Unvalidated" /* Unvalidated */)
|
|
12707
12786
|
await this.validateOCMFSignature(
|
|
12708
12787
|
ocmfJSONDocument,
|
|
12709
12788
|
PublicKey,
|
|
@@ -12732,14 +12811,14 @@ var OCMF = class {
|
|
|
12732
12811
|
//#endregion
|
|
12733
12812
|
//#region TryToParseOCMFDocument (OCMFDocument, PublicKey?, PublicKeyEncoding?, ContainerInfos?)
|
|
12734
12813
|
async TryToParseOCMFDocument(OCMFDocument, PublicKey, PublicKeyEncoding, ContainerInfos) {
|
|
12735
|
-
return
|
|
12814
|
+
return this.TryToParseOCMFDocuments([OCMFDocument], PublicKey, PublicKeyEncoding, ContainerInfos);
|
|
12736
12815
|
}
|
|
12737
12816
|
//#endregion
|
|
12738
12817
|
//#region TryToParseOCMFDocuments(OCMFDocuments, PublicKey?, PublicKeyEncoding?, ContainerInfos?)
|
|
12739
12818
|
async TryToParseOCMFDocuments(OCMFDocuments, PublicKey, PublicKeyEncoding, ContainerInfos) {
|
|
12740
12819
|
if (OCMFDocuments.length == 0) return {
|
|
12741
12820
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
12742
|
-
message: this.chargy.GetLocalizedMessage("The given OCMF data could not be parsed") + "!",
|
|
12821
|
+
message: this.chargy.GetMultilanguageText(this.chargy.GetLocalizedMessage("The given OCMF data could not be parsed") + "!"),
|
|
12743
12822
|
certainty: 0
|
|
12744
12823
|
};
|
|
12745
12824
|
const ocmfJSONDocumentGroups = /* @__PURE__ */ new Map();
|
|
@@ -12752,20 +12831,21 @@ var OCMF = class {
|
|
|
12752
12831
|
if (typeof ocmfJSONDocuments !== "string") {
|
|
12753
12832
|
for (const ocmfJSONDocument of ocmfJSONDocuments) {
|
|
12754
12833
|
try {
|
|
12755
|
-
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 ?? "") + "|" +
|
|
12834
|
+
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 ?? "") + "|" +
|
|
12835
|
+
(ocmfJSONDocument.payload.IT ?? "") + "|" + (ocmfJSONDocument.payload.ID ?? "") + "|" + (ocmfJSONDocument.payload.TT ?? "") + "|" + (ocmfJSONDocument.payload.CF ?? "") + "|" + (ocmfJSONDocument.payload.CT ?? "") + "|" + (ocmfJSONDocument.payload.CI ?? "");
|
|
12756
12836
|
if (!ocmfJSONDocumentGroups.has(groupingKey))
|
|
12757
12837
|
ocmfJSONDocumentGroups.set(groupingKey, new Array());
|
|
12758
12838
|
ocmfJSONDocumentGroups.get(groupingKey)?.push(ocmfJSONDocument);
|
|
12759
12839
|
} catch (exception) {
|
|
12760
12840
|
return {
|
|
12761
12841
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
12762
|
-
message: this.chargy.GetLocalizedMessage("The given OCMF data could not be parsed") + ": " + (exception instanceof Error ? exception.message : String(exception)),
|
|
12842
|
+
message: this.chargy.GetMultilanguageText(this.chargy.GetLocalizedMessage("The given OCMF data could not be parsed") + ": " + (exception instanceof Error ? exception.message : String(exception))),
|
|
12763
12843
|
certainty: 0
|
|
12764
12844
|
};
|
|
12765
12845
|
}
|
|
12766
12846
|
}
|
|
12767
12847
|
for (const ocmfJSONDocumentGroup of ocmfJSONDocumentGroups.values()) {
|
|
12768
|
-
if (PublicKey) {
|
|
12848
|
+
if (PublicKey != null) {
|
|
12769
12849
|
for (const ocmfJSONDocument of ocmfJSONDocumentGroup)
|
|
12770
12850
|
if (ocmfJSONDocument.validationStatus === "Unvalidated" /* Unvalidated */)
|
|
12771
12851
|
await this.validateOCMFSignature(ocmfJSONDocument, PublicKey);
|
|
@@ -12787,7 +12867,7 @@ var OCMF = class {
|
|
|
12787
12867
|
default:
|
|
12788
12868
|
ocmfCTRs.push({
|
|
12789
12869
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
12790
|
-
message: this.chargy.
|
|
12870
|
+
message: this.chargy.GetMultilanguageText("Unknown OCMF version!"),
|
|
12791
12871
|
certainty: 0
|
|
12792
12872
|
});
|
|
12793
12873
|
break;
|
|
@@ -12799,7 +12879,7 @@ var OCMF = class {
|
|
|
12799
12879
|
}
|
|
12800
12880
|
return {
|
|
12801
12881
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
12802
|
-
message: this.chargy.GetLocalizedMessage("The given OCMF data could not be parsed") + (typeof ocmfJSONDocuments === "string" ? ": " + ocmfJSONDocuments : "!"),
|
|
12882
|
+
message: this.chargy.GetMultilanguageText(this.chargy.GetLocalizedMessage("The given OCMF data could not be parsed") + (typeof ocmfJSONDocuments === "string" ? ": " + ocmfJSONDocuments : "!")),
|
|
12803
12883
|
certainty: 0
|
|
12804
12884
|
};
|
|
12805
12885
|
}
|
|
@@ -12817,12 +12897,6 @@ var OCPI = class {
|
|
|
12817
12897
|
constructor(chargy) {
|
|
12818
12898
|
this.chargy = chargy;
|
|
12819
12899
|
}
|
|
12820
|
-
bufferToHex(buffer, Reverse) {
|
|
12821
|
-
return (Reverse ? Array.from(new Uint8Array(buffer)).reverse() : Array.from(new Uint8Array(buffer))).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
12822
|
-
}
|
|
12823
|
-
bufferToNumber(buffer) {
|
|
12824
|
-
return parseInt(Array.from(new Uint8Array(buffer)).map((b) => b.toString(16).padStart(2, "0")).join(""), 16);
|
|
12825
|
-
}
|
|
12826
12900
|
//#region tryToParseChargeITContainerFormat(SomeJSON)
|
|
12827
12901
|
// The chargeIT mobility data format does not always provide context information or format identifiers!
|
|
12828
12902
|
async tryToParseOCPIFormat(SomeJSON) {
|
|
@@ -12842,11 +12916,11 @@ var OCPI = class {
|
|
|
12842
12916
|
const public_key = SomeJSON["public_key"];
|
|
12843
12917
|
const signed_values = SomeJSON["signed_values"];
|
|
12844
12918
|
if (!isMandatoryString(encoding_method))
|
|
12845
|
-
errors.push(this.chargy.
|
|
12919
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidEncodingMethod")));
|
|
12846
12920
|
if (!isMandatoryString(public_key))
|
|
12847
|
-
errors.push(this.chargy.
|
|
12921
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidPublicKey")));
|
|
12848
12922
|
if (!isMandatoryJSONArray(signed_values))
|
|
12849
|
-
errors.push(this.chargy.
|
|
12923
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidSignedValues")));
|
|
12850
12924
|
if (errors.length > 0)
|
|
12851
12925
|
return {
|
|
12852
12926
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
@@ -12856,7 +12930,7 @@ var OCPI = class {
|
|
|
12856
12930
|
};
|
|
12857
12931
|
if (encoding_method === "OCMF" && isMandatoryJSONArray(signed_values) && signed_values.length > 0) {
|
|
12858
12932
|
const firstSignedData = asString(asJSONObject(signed_values[0])?.["signed_data"]);
|
|
12859
|
-
if (firstSignedData) {
|
|
12933
|
+
if (firstSignedData != null && firstSignedData.length > 0) {
|
|
12860
12934
|
const placeInfo = asJSONObject(SomeJSON["placeInfo"]);
|
|
12861
12935
|
const geoLocation = asJSONObject(placeInfo?.["geoLocation"]);
|
|
12862
12936
|
const address = asJSONObject(placeInfo?.["address"]);
|
|
@@ -12875,7 +12949,7 @@ var OCPI = class {
|
|
|
12875
12949
|
},
|
|
12876
12950
|
energyMeter: asJSONObject(SomeJSON["meterInfo"])
|
|
12877
12951
|
};
|
|
12878
|
-
return
|
|
12952
|
+
return new OCMF(this.chargy).TryToParseOCMFDocument(
|
|
12879
12953
|
firstSignedData,
|
|
12880
12954
|
asString(public_key),
|
|
12881
12955
|
encoding_method,
|
|
@@ -12948,138 +13022,138 @@ var OCPI = class {
|
|
|
12948
13022
|
const chargingCostsInfo_flat_cost = chargingCostsInfo_flat?.["cost"];
|
|
12949
13023
|
const signedMeterValues = SomeJSON["signedMeterValues"];
|
|
12950
13024
|
if (!isMandatoryString(chargingSessionId))
|
|
12951
|
-
errors.push(this.chargy.
|
|
13025
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid charge transparency record identification!")));
|
|
12952
13026
|
if (!isMandatoryJSONObject(chargePointInfo)) {
|
|
12953
|
-
errors.push(this.chargy.
|
|
13027
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidChargePointInfo")));
|
|
12954
13028
|
secondaryErrors += 19;
|
|
12955
13029
|
} else {
|
|
12956
13030
|
if (!isMandatoryString(evseId))
|
|
12957
|
-
errors.push(this.chargy.
|
|
13031
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidEVSEIdentification")));
|
|
12958
13032
|
if (!isMandatoryJSONObject(placeInfo)) {
|
|
12959
|
-
errors.push(this.chargy.
|
|
13033
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidPlaceInfo")));
|
|
12960
13034
|
secondaryErrors += 8;
|
|
12961
13035
|
} else {
|
|
12962
13036
|
if (!isMandatoryJSONObject(geoLocation)) {
|
|
12963
|
-
errors.push(this.chargy.
|
|
13037
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidGeoLocation")));
|
|
12964
13038
|
secondaryErrors += 2;
|
|
12965
13039
|
} else {
|
|
12966
13040
|
if (!isMandatoryNumber(geoLocation_lat))
|
|
12967
|
-
errors.push(this.chargy.
|
|
13041
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidGeoLocationLatitude")));
|
|
12968
13042
|
if (!isMandatoryNumber(geoLocation_lon))
|
|
12969
|
-
errors.push(this.chargy.
|
|
13043
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidGeoLocationLongitude")));
|
|
12970
13044
|
}
|
|
12971
13045
|
if (!isMandatoryJSONObject(address)) {
|
|
12972
|
-
errors.push(this.chargy.
|
|
13046
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidAddress")));
|
|
12973
13047
|
secondaryErrors += 4;
|
|
12974
13048
|
} else {
|
|
12975
13049
|
if (!isMandatoryString(address_street))
|
|
12976
|
-
errors.push(this.chargy.
|
|
13050
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidAddressStreetName")));
|
|
12977
13051
|
if (!isMandatoryString(address_zipCode))
|
|
12978
|
-
errors.push(this.chargy.
|
|
13052
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidAddressZIPCode")));
|
|
12979
13053
|
if (!isMandatoryString(address_town))
|
|
12980
|
-
errors.push(this.chargy.
|
|
13054
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidAddressCityName")));
|
|
12981
13055
|
if (!isMandatoryString(address_country))
|
|
12982
|
-
errors.push(this.chargy.
|
|
13056
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidAddressCountryName")));
|
|
12983
13057
|
}
|
|
12984
13058
|
}
|
|
12985
13059
|
}
|
|
12986
13060
|
if (!isMandatoryJSONObject(chargingStationInfo)) {
|
|
12987
|
-
errors.push(this.chargy.
|
|
13061
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidChargingStationInfo")));
|
|
12988
13062
|
secondaryErrors += 5;
|
|
12989
13063
|
} else {
|
|
12990
13064
|
if (!isOptionalString(chargingStation_manufacturer))
|
|
12991
|
-
errors.push(this.chargy.
|
|
13065
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station manufacturer!")));
|
|
12992
13066
|
if (!isOptionalString(chargingStation_type))
|
|
12993
|
-
errors.push(this.chargy.
|
|
13067
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station type!")));
|
|
12994
13068
|
if (!isOptionalString(chargingStation_serialNumber))
|
|
12995
|
-
errors.push(this.chargy.
|
|
13069
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station serial number!")));
|
|
12996
13070
|
if (!isOptionalString(chargingStation_controllerSoftwareVersion))
|
|
12997
|
-
errors.push(this.chargy.
|
|
13071
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station controller software version!")));
|
|
12998
13072
|
if (!isOptionalString(chargingStation_compliance))
|
|
12999
|
-
errors.push(this.chargy.
|
|
13073
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station compliance!")));
|
|
13000
13074
|
if (!isOptionalURL(chargingStation_complianceURL))
|
|
13001
|
-
errors.push(this.chargy.
|
|
13075
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station compliance URL!")));
|
|
13002
13076
|
if (!isOptionalString(chargingStation_conformity))
|
|
13003
|
-
errors.push(this.chargy.
|
|
13077
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station conformity!")));
|
|
13004
13078
|
if (!isOptionalURL(chargingStation_conformity_URL))
|
|
13005
|
-
errors.push(this.chargy.
|
|
13079
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station conformity URL!")));
|
|
13006
13080
|
if (!isOptionalURL(chargingStation_conformity_certificateId))
|
|
13007
|
-
errors.push(this.chargy.
|
|
13081
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station conformity certificate identification!")));
|
|
13008
13082
|
if (!isOptionalString(chargingStation_calibration))
|
|
13009
|
-
errors.push(this.chargy.
|
|
13083
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station calibration!")));
|
|
13010
13084
|
if (!isOptionalURL(chargingStation_calibration_URL))
|
|
13011
|
-
errors.push(this.chargy.
|
|
13085
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station calibration URL!")));
|
|
13012
13086
|
if (!isOptionalURL(chargingStation_calibration_certificateId))
|
|
13013
|
-
errors.push(this.chargy.
|
|
13087
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station calibration certificate identification!")));
|
|
13014
13088
|
}
|
|
13015
13089
|
if (meterInfo) {
|
|
13016
13090
|
if (!isOptionalString(meterInfo_meterId))
|
|
13017
|
-
errors.push(this.chargy.
|
|
13091
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_MeterIdP", 1)));
|
|
13018
13092
|
if (!isOptionalString(meterInfo_manufacturer))
|
|
13019
|
-
errors.push(this.chargy.
|
|
13093
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_ManufacturerP", 1)));
|
|
13020
13094
|
if (!isOptionalString(meterInfo_manufacturerURL))
|
|
13021
|
-
errors.push(this.chargy.
|
|
13095
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_ManufacturerP", 1)));
|
|
13022
13096
|
if (!isOptionalString(meterInfo_model))
|
|
13023
|
-
errors.push(this.chargy.
|
|
13097
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_ManufacturerP", 1)));
|
|
13024
13098
|
if (!isOptionalString(meterInfo_modelURL))
|
|
13025
|
-
errors.push(this.chargy.
|
|
13099
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_ManufacturerP", 1)));
|
|
13026
13100
|
if (!isOptionalString(meterInfo_firmwareVersion))
|
|
13027
|
-
errors.push(this.chargy.
|
|
13101
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_FirmwareVersionP", 1)));
|
|
13028
13102
|
if (!isOptionalString(meterInfo_hardwareVersion))
|
|
13029
|
-
errors.push(this.chargy.
|
|
13103
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_FirmwareVersionP", 1)));
|
|
13030
13104
|
if (!isOptionalString(meterInfo_publicKey))
|
|
13031
|
-
errors.push(this.chargy.
|
|
13105
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_PublicKeyP", 1)));
|
|
13032
13106
|
if (!isOptionalString(meterInfo_publicKeyFormat))
|
|
13033
|
-
errors.push(this.chargy.
|
|
13107
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_PublicKeyP", 1)));
|
|
13034
13108
|
if (!isOptionalString(meterInfo_publicKeyEncoding))
|
|
13035
|
-
errors.push(this.chargy.
|
|
13109
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_PublicKeyP", 1)));
|
|
13036
13110
|
if (!isOptionalString(meterInfo_signatureFormat))
|
|
13037
|
-
errors.push(this.chargy.
|
|
13111
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_PublicKeyP", 1)));
|
|
13038
13112
|
if (!isOptionalString(meterInfo_signatureEncoding))
|
|
13039
|
-
errors.push(this.chargy.
|
|
13113
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_PublicKeyP", 1)));
|
|
13040
13114
|
}
|
|
13041
13115
|
if (connectorInfo) {
|
|
13042
13116
|
if (!isOptionalString(connectorInfo_type))
|
|
13043
|
-
errors.push(this.chargy.
|
|
13117
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_MeterIdP", 1)));
|
|
13044
13118
|
if (!isOptionalString(connectorInfo_losses))
|
|
13045
|
-
errors.push(this.chargy.
|
|
13119
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_MeterIdP", 1)));
|
|
13046
13120
|
}
|
|
13047
13121
|
if (chargingCostsInfo) {
|
|
13048
13122
|
if (!isMandatoryNumber(chargingCostsInfo_total))
|
|
13049
|
-
errors.push(this.chargy.
|
|
13123
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid total costs within the charging costs!")));
|
|
13050
13124
|
if (!isMandatoryString(chargingCostsInfo_currency))
|
|
13051
|
-
errors.push(this.chargy.
|
|
13125
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid currency within the charging costs!")));
|
|
13052
13126
|
if (chargingCostsInfo_reservation) {
|
|
13053
13127
|
if (!isMandatoryNumber(chargingCostsInfo_reservation_cost))
|
|
13054
|
-
errors.push(this.chargy.
|
|
13128
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid reservation cost within the charging costs!")));
|
|
13055
13129
|
if (!isMandatoryString(chargingCostsInfo_reservation_unit))
|
|
13056
|
-
errors.push(this.chargy.
|
|
13130
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid reservation unit within the charging costs!")));
|
|
13057
13131
|
}
|
|
13058
13132
|
if (chargingCostsInfo_energy) {
|
|
13059
13133
|
if (!isMandatoryNumber(chargingCostsInfo_energy_cost))
|
|
13060
|
-
errors.push(this.chargy.
|
|
13134
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid energy cost within the charging costs!")));
|
|
13061
13135
|
if (!isMandatoryString(chargingCostsInfo_energy_unit))
|
|
13062
|
-
errors.push(this.chargy.
|
|
13136
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid energy unit within the charging costs!")));
|
|
13063
13137
|
}
|
|
13064
13138
|
if (chargingCostsInfo_time) {
|
|
13065
13139
|
if (!isMandatoryNumber(chargingCostsInfo_time_cost))
|
|
13066
|
-
errors.push(this.chargy.
|
|
13140
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid time cost within the charging costs!")));
|
|
13067
13141
|
if (!isMandatoryString(chargingCostsInfo_time_unit))
|
|
13068
|
-
errors.push(this.chargy.
|
|
13142
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid time unit within the charging costs!")));
|
|
13069
13143
|
}
|
|
13070
13144
|
if (chargingCostsInfo_idle) {
|
|
13071
13145
|
if (!isMandatoryNumber(chargingCostsInfo_idle_cost))
|
|
13072
|
-
errors.push(this.chargy.
|
|
13146
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid idle cost within the charging costs!")));
|
|
13073
13147
|
if (!isMandatoryString(chargingCostsInfo_idle_unit))
|
|
13074
|
-
errors.push(this.chargy.
|
|
13148
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid idle unit within the charging costs!")));
|
|
13075
13149
|
}
|
|
13076
13150
|
if (chargingCostsInfo_flat) {
|
|
13077
13151
|
if (!isMandatoryNumber(chargingCostsInfo_flat_cost))
|
|
13078
|
-
errors.push(this.chargy.
|
|
13152
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid flat cost within the charging costs!")));
|
|
13079
13153
|
}
|
|
13080
13154
|
}
|
|
13081
13155
|
if (!isMandatoryJSONArray(signedMeterValues) || signedMeterValues.length < 2) {
|
|
13082
|
-
errors.push(this.chargy.
|
|
13156
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidSignedMeterValues")));
|
|
13083
13157
|
secondaryErrors += 2 * 39;
|
|
13084
13158
|
} else {
|
|
13085
13159
|
const firstSMV = asJSONObject(signedMeterValues[0]);
|
|
@@ -13089,7 +13163,7 @@ var OCPI = class {
|
|
|
13089
13163
|
const context = asString(currentSMV?.["@context"])?.trim() ?? asString(currentSMV?.["format"])?.trim() ?? null;
|
|
13090
13164
|
if (smvContext !== context) return {
|
|
13091
13165
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
13092
|
-
message: "Inconsistent signed meter value format!",
|
|
13166
|
+
message: this.chargy.GetMultilanguageText("Inconsistent signed meter value format!"),
|
|
13093
13167
|
certainty: 1
|
|
13094
13168
|
};
|
|
13095
13169
|
}
|
|
@@ -13193,9 +13267,9 @@ var OCPI = class {
|
|
|
13193
13267
|
],
|
|
13194
13268
|
certainty: 0
|
|
13195
13269
|
};
|
|
13196
|
-
if (smvContext?.startsWith("https://www.chargeit-mobility.com/contexts/bsm-ws36a-json"))
|
|
13270
|
+
if (smvContext?.startsWith("https://www.chargeit-mobility.com/contexts/bsm-ws36a-json") === true)
|
|
13197
13271
|
return new BSMCrypt01(this.chargy).tryToParseBSM_WS36aMeasurements(CTR, evseIdStr, asString(chargingStation_controllerSoftwareVersion) ?? null, signedMeterValues);
|
|
13198
|
-
if (smvContext?.startsWith("ALFEN"))
|
|
13272
|
+
if (smvContext?.startsWith("ALFEN") === true)
|
|
13199
13273
|
return new Alfen(this.chargy).TryToParseALFENFormat(
|
|
13200
13274
|
signedMeterValues.map((value) => asString(asJSONObject(value)?.["payload"]) ?? ""),
|
|
13201
13275
|
{
|
|
@@ -13234,7 +13308,7 @@ var OCPI = class {
|
|
|
13234
13308
|
} catch (exception) {
|
|
13235
13309
|
return {
|
|
13236
13310
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
13237
|
-
message: "Exception occured: " + (exception instanceof Error ? exception.message : String(exception)),
|
|
13311
|
+
message: this.chargy.GetMultilanguageText("Exception occured: " + (exception instanceof Error ? exception.message : String(exception))),
|
|
13238
13312
|
errors,
|
|
13239
13313
|
warnings,
|
|
13240
13314
|
certainty: (numberOfFormatChecks - errors.length - secondaryErrors) / numberOfFormatChecks
|
|
@@ -13243,7 +13317,7 @@ var OCPI = class {
|
|
|
13243
13317
|
}
|
|
13244
13318
|
return {
|
|
13245
13319
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
13246
|
-
message: "No chargeIT charge transparency record",
|
|
13320
|
+
message: this.chargy.GetMultilanguageText("No chargeIT charge transparency record"),
|
|
13247
13321
|
errors,
|
|
13248
13322
|
warnings,
|
|
13249
13323
|
certainty: 0
|
|
@@ -13342,9 +13416,9 @@ function parsePCDFDocument(input) {
|
|
|
13342
13416
|
}
|
|
13343
13417
|
const fields = {};
|
|
13344
13418
|
for (let i = 0; i < PCDF_FIELD_ORDER.length; i++) {
|
|
13345
|
-
const value = match
|
|
13346
|
-
const field = PCDF_FIELD_ORDER
|
|
13347
|
-
if (
|
|
13419
|
+
const value = getArrayElement(match, i + 1, "Missing PCDF field value");
|
|
13420
|
+
const field = getArrayElement(PCDF_FIELD_ORDER, i, "Missing PCDF field name");
|
|
13421
|
+
if (value.length === 0)
|
|
13348
13422
|
throw new PCDFParseError("MISSING_FIELDS", "Missing fields in the data tuple", field);
|
|
13349
13423
|
fields[field] = value;
|
|
13350
13424
|
}
|
|
@@ -13529,7 +13603,7 @@ var PCDF = class {
|
|
|
13529
13603
|
if (externalPublicKey != null && normalizePCDFPublicKeyHex(externalPublicKey) !== publicKey) {
|
|
13530
13604
|
return {
|
|
13531
13605
|
status: "InvalidPublicKey" /* InvalidPublicKey */,
|
|
13532
|
-
message: "Wrong Public Key",
|
|
13606
|
+
message: this.chargy.GetMultilanguageText("Wrong Public Key"),
|
|
13533
13607
|
certainty: 1
|
|
13534
13608
|
};
|
|
13535
13609
|
}
|
|
@@ -13550,7 +13624,7 @@ var PCDF = class {
|
|
|
13550
13624
|
} catch (exception) {
|
|
13551
13625
|
return {
|
|
13552
13626
|
status: exception instanceof PCDFParseError ? "InvalidSessionFormat" /* InvalidSessionFormat */ : "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
13553
|
-
message: exception instanceof Error ? exception.message : String(exception),
|
|
13627
|
+
message: this.chargy.GetMultilanguageText(exception instanceof Error ? exception.message : String(exception)),
|
|
13554
13628
|
certainty: 0
|
|
13555
13629
|
};
|
|
13556
13630
|
}
|
|
@@ -13716,8 +13790,10 @@ function parsePCDFReadingValue(value, errors) {
|
|
|
13716
13790
|
errors.push("Session information is invalid");
|
|
13717
13791
|
return void 0;
|
|
13718
13792
|
}
|
|
13793
|
+
const integralPart = getArrayElement(match, 1, "Missing PCDF reading integral part");
|
|
13794
|
+
const fractionalPart = getArrayElement(match, 2, "Missing PCDF reading fractional part");
|
|
13719
13795
|
return {
|
|
13720
|
-
value: new Decimal(
|
|
13796
|
+
value: new Decimal(integralPart + "." + fractionalPart),
|
|
13721
13797
|
unit: "kWh"
|
|
13722
13798
|
};
|
|
13723
13799
|
}
|
|
@@ -13752,9 +13828,9 @@ function hexToBytes2(hex, errorMessage) {
|
|
|
13752
13828
|
}
|
|
13753
13829
|
function readDERLength(bytes, getOffset, setOffset) {
|
|
13754
13830
|
let offset = getOffset();
|
|
13755
|
-
|
|
13756
|
-
if (b == null)
|
|
13831
|
+
if (offset >= bytes.length)
|
|
13757
13832
|
throw new Error("Invalid signature");
|
|
13833
|
+
const b = getArrayElement(bytes, offset++, "Invalid signature");
|
|
13758
13834
|
if ((b & 128) === 0) {
|
|
13759
13835
|
setOffset(offset);
|
|
13760
13836
|
return b;
|
|
@@ -13764,9 +13840,9 @@ function readDERLength(bytes, getOffset, setOffset) {
|
|
|
13764
13840
|
throw new Error("Invalid signature");
|
|
13765
13841
|
let length = 0;
|
|
13766
13842
|
for (let i = 0; i < octets; i++) {
|
|
13767
|
-
|
|
13768
|
-
if (value == null)
|
|
13843
|
+
if (offset >= bytes.length)
|
|
13769
13844
|
throw new Error("Invalid signature");
|
|
13845
|
+
const value = getArrayElement(bytes, offset++, "Invalid signature");
|
|
13770
13846
|
length = (length << 8) + value;
|
|
13771
13847
|
}
|
|
13772
13848
|
setOffset(offset);
|
|
@@ -13795,30 +13871,33 @@ var SAFEXML = class _SAFEXML {
|
|
|
13795
13871
|
this.chargy = chargy;
|
|
13796
13872
|
}
|
|
13797
13873
|
static ParseChargingStationContext(XMLDocument) {
|
|
13798
|
-
const chargingStationElement = getElementsByLocalName(XMLDocument, "chargingStation")
|
|
13799
|
-
if (
|
|
13874
|
+
const chargingStationElement = getElementsByLocalName(XMLDocument, "chargingStation").at(0);
|
|
13875
|
+
if (chargingStationElement === void 0)
|
|
13800
13876
|
return {};
|
|
13801
|
-
const
|
|
13877
|
+
const chargingStationAttributeId = chargingStationElement.getAttribute("id")?.trim();
|
|
13878
|
+
const chargingStationId = chargingStationAttributeId != null && chargingStationAttributeId.length > 0 ? chargingStationAttributeId : getTrimmedTextContent(getDirectChildByLocalName(chargingStationElement, "id"));
|
|
13802
13879
|
const softwareVersion = getTrimmedTextContent(getDirectChildByLocalName(chargingStationElement, "softwareVersion"));
|
|
13803
13880
|
const geoLocationElement = getDirectChildByLocalName(chargingStationElement, "geoLocation");
|
|
13804
13881
|
const latitude = Number.parseFloat(getTrimmedTextContent(getDirectChildByLocalName(geoLocationElement ?? chargingStationElement, "latitude")) ?? "");
|
|
13805
13882
|
const longitude = Number.parseFloat(getTrimmedTextContent(getDirectChildByLocalName(geoLocationElement ?? chargingStationElement, "longitude")) ?? "");
|
|
13806
13883
|
const geoLocation = Number.isFinite(latitude) && Number.isFinite(longitude) ? { lat: latitude, lng: longitude } : void 0;
|
|
13807
|
-
if (getDirectChildByLocalName(chargingStationElement, "EVSEs"))
|
|
13884
|
+
if (getDirectChildByLocalName(chargingStationElement, "EVSEs") !== void 0)
|
|
13808
13885
|
throw new Error("The SAFE chargingStation XML element must contain EVSE directly and no EVSEs container element!");
|
|
13809
13886
|
const evseElements = getDirectChildrenByLocalName(chargingStationElement, "EVSE");
|
|
13810
13887
|
if (evseElements.length > 1)
|
|
13811
13888
|
throw new Error("The SAFE chargingStation XML element must not contain more than one EVSE element!");
|
|
13812
|
-
const evseElement = evseElements
|
|
13813
|
-
const
|
|
13814
|
-
const
|
|
13889
|
+
const evseElement = evseElements.at(0);
|
|
13890
|
+
const evseAttributeId = evseElement?.getAttribute("id")?.trim();
|
|
13891
|
+
const evseTextId = getTrimmedTextContent(getDirectChildByLocalName(evseElement ?? chargingStationElement, "id"));
|
|
13892
|
+
const evseId = evseAttributeId != null && evseAttributeId.length > 0 ? evseAttributeId : evseTextId ?? "";
|
|
13893
|
+
const connectorElements = evseElement !== void 0 ? getDirectChildrenByLocalName(evseElement, "connector") : [];
|
|
13815
13894
|
if (connectorElements.length > 1)
|
|
13816
13895
|
throw new Error("The SAFE EVSE XML element must not contain more than one connector element!");
|
|
13817
|
-
const connectorElement = connectorElements
|
|
13896
|
+
const connectorElement = connectorElements.at(0);
|
|
13818
13897
|
const connectorId = connectorElement?.getAttribute("id")?.trim();
|
|
13819
13898
|
const connectorType = getTrimmedTextContent(getDirectChildByLocalName(connectorElement ?? evseElement ?? chargingStationElement, "type"));
|
|
13820
|
-
const connector = connectorType ? { "@id": connectorId, type: connectorType, looses: 0 } : void 0;
|
|
13821
|
-
const parsedEVSE = evseElement ? {
|
|
13899
|
+
const connector = connectorType != null && connectorType.length > 0 ? { "@id": connectorId, type: connectorType, looses: 0 } : void 0;
|
|
13900
|
+
const parsedEVSE = evseElement !== void 0 ? {
|
|
13822
13901
|
"@id": evseId,
|
|
13823
13902
|
"description": parseDescription(evseElement),
|
|
13824
13903
|
"meters": [],
|
|
@@ -13856,7 +13935,7 @@ var SAFEXML = class _SAFEXML {
|
|
|
13856
13935
|
if (signedData == null)
|
|
13857
13936
|
return {
|
|
13858
13937
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
13859
|
-
message: "Each value within the given XML container must contain signed data!",
|
|
13938
|
+
message: this.chargy.GetMultilanguageText("Each value within the given XML container must contain signed data!"),
|
|
13860
13939
|
certainty: 0
|
|
13861
13940
|
};
|
|
13862
13941
|
const signedDataFormat = signedData.attributes.getNamedItem("format")?.value.trim().toLowerCase() ?? "";
|
|
@@ -13865,7 +13944,7 @@ var SAFEXML = class _SAFEXML {
|
|
|
13865
13944
|
else if (signedDataFormat !== commonSignedDataFormat)
|
|
13866
13945
|
return {
|
|
13867
13946
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
13868
|
-
message: "Invalid mixture of different signed data formats within the given XML container!",
|
|
13947
|
+
message: this.chargy.GetMultilanguageText("Invalid mixture of different signed data formats within the given XML container!"),
|
|
13869
13948
|
certainty: 0
|
|
13870
13949
|
};
|
|
13871
13950
|
const signedDataEncoding = signedData.attributes.getNamedItem("encoding")?.value.trim().toLowerCase() ?? "";
|
|
@@ -13874,14 +13953,14 @@ var SAFEXML = class _SAFEXML {
|
|
|
13874
13953
|
else if (signedDataEncoding !== commonSignedDataEncoding)
|
|
13875
13954
|
return {
|
|
13876
13955
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
13877
|
-
message: "Invalid mixture of different signed data encodings within the given XML container!",
|
|
13956
|
+
message: this.chargy.GetMultilanguageText("Invalid mixture of different signed data encodings within the given XML container!"),
|
|
13878
13957
|
certainty: 0
|
|
13879
13958
|
};
|
|
13880
13959
|
const signedDataValue = signedData.textContent.trim();
|
|
13881
13960
|
if (IsNullOrEmpty(signedDataValue))
|
|
13882
13961
|
return {
|
|
13883
13962
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
13884
|
-
message: "The signed data value within the given XML container must not be empty!",
|
|
13963
|
+
message: this.chargy.GetMultilanguageText("The signed data value within the given XML container must not be empty!"),
|
|
13885
13964
|
certainty: 0
|
|
13886
13965
|
};
|
|
13887
13966
|
const publicKeyEncoding = publicKey?.attributes.getNamedItem("encoding")?.value.trim().toLowerCase() ?? "";
|
|
@@ -13890,7 +13969,7 @@ var SAFEXML = class _SAFEXML {
|
|
|
13890
13969
|
else if (publicKeyEncoding !== commonPublicKeyEncoding)
|
|
13891
13970
|
return {
|
|
13892
13971
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
13893
|
-
message: "Invalid mixture of different public key encodings within the given XML container!",
|
|
13972
|
+
message: this.chargy.GetMultilanguageText("Invalid mixture of different public key encodings within the given XML container!"),
|
|
13894
13973
|
certainty: 0
|
|
13895
13974
|
};
|
|
13896
13975
|
const publicKeyValue = publicKey?.textContent.trim().replace(/\s+/g, "") ?? "";
|
|
@@ -13899,7 +13978,7 @@ var SAFEXML = class _SAFEXML {
|
|
|
13899
13978
|
else if (publicKeyValue !== commonPublicKey)
|
|
13900
13979
|
return {
|
|
13901
13980
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
13902
|
-
message: "Invalid mixture of different public keys within the given XML container!",
|
|
13981
|
+
message: this.chargy.GetMultilanguageText("Invalid mixture of different public keys within the given XML container!"),
|
|
13903
13982
|
certainty: 0
|
|
13904
13983
|
};
|
|
13905
13984
|
switch (commonSignedDataEncoding) {
|
|
@@ -13919,7 +13998,7 @@ var SAFEXML = class _SAFEXML {
|
|
|
13919
13998
|
default:
|
|
13920
13999
|
return {
|
|
13921
14000
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
13922
|
-
message: "Unkown signed data encoding within the given SAFE XML!",
|
|
14001
|
+
message: this.chargy.GetMultilanguageText("Unkown signed data encoding within the given SAFE XML!"),
|
|
13923
14002
|
certainty: 0
|
|
13924
14003
|
};
|
|
13925
14004
|
}
|
|
@@ -13941,7 +14020,7 @@ var SAFEXML = class _SAFEXML {
|
|
|
13941
14020
|
default:
|
|
13942
14021
|
return {
|
|
13943
14022
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
13944
|
-
message: this.chargy.
|
|
14023
|
+
message: this.chargy.GetMultilanguageText("UnknownOrInvalidChargingSessionFormat"),
|
|
13945
14024
|
certainty: 0
|
|
13946
14025
|
};
|
|
13947
14026
|
}
|
|
@@ -13950,13 +14029,13 @@ var SAFEXML = class _SAFEXML {
|
|
|
13950
14029
|
} catch (exception) {
|
|
13951
14030
|
return {
|
|
13952
14031
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
13953
|
-
message: "Exception occured: " + (exception instanceof Error ? exception.message : String(exception)),
|
|
14032
|
+
message: this.chargy.GetMultilanguageText("Exception occured: " + (exception instanceof Error ? exception.message : String(exception))),
|
|
13954
14033
|
certainty: 0
|
|
13955
14034
|
};
|
|
13956
14035
|
}
|
|
13957
14036
|
return {
|
|
13958
14037
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
13959
|
-
message: this.chargy.
|
|
14038
|
+
message: this.chargy.GetMultilanguageText("UnknownOrInvalidChargingSessionFormat"),
|
|
13960
14039
|
certainty: 0
|
|
13961
14040
|
};
|
|
13962
14041
|
}
|
|
@@ -13983,8 +14062,8 @@ var XMLContainer = class {
|
|
|
13983
14062
|
if (values.length == 1) {
|
|
13984
14063
|
const valueList = values[0]?.querySelectorAll("signedMeterValue");
|
|
13985
14064
|
if (valueList != null && valueList.length >= 1) {
|
|
13986
|
-
for (
|
|
13987
|
-
const publicKey =
|
|
14065
|
+
for (const valueElement of valueList) {
|
|
14066
|
+
const publicKey = valueElement.querySelector("publicKey");
|
|
13988
14067
|
if (publicKey != null) {
|
|
13989
14068
|
const publicKeyEncoding = publicKey.attributes.getNamedItem("encoding")?.value.trim().toLowerCase() ?? "";
|
|
13990
14069
|
let publicKeyValue = publicKey.textContent.trim();
|
|
@@ -14005,14 +14084,14 @@ var XMLContainer = class {
|
|
|
14005
14084
|
default:
|
|
14006
14085
|
return {
|
|
14007
14086
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
14008
|
-
message: "Unkown public key encoding within the given XML container!",
|
|
14087
|
+
message: this.chargy.GetMultilanguageText("Unkown public key encoding within the given XML container!"),
|
|
14009
14088
|
certainty: 0
|
|
14010
14089
|
};
|
|
14011
14090
|
}
|
|
14012
14091
|
if (IsNullOrEmpty(publicKeyValue))
|
|
14013
14092
|
return {
|
|
14014
14093
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
14015
|
-
message: "The public key within the given XML container must not be empty!",
|
|
14094
|
+
message: this.chargy.GetMultilanguageText("The public key within the given XML container must not be empty!"),
|
|
14016
14095
|
certainty: 0
|
|
14017
14096
|
};
|
|
14018
14097
|
else if (common.publicKey == "")
|
|
@@ -14020,11 +14099,11 @@ var XMLContainer = class {
|
|
|
14020
14099
|
else if (publicKeyValue != common.publicKey)
|
|
14021
14100
|
return {
|
|
14022
14101
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
14023
|
-
message: "Invalid mixture of different public keys within the given XML container!",
|
|
14102
|
+
message: this.chargy.GetMultilanguageText("Invalid mixture of different public keys within the given XML container!"),
|
|
14024
14103
|
certainty: 0
|
|
14025
14104
|
};
|
|
14026
14105
|
}
|
|
14027
|
-
const meterValueSignature =
|
|
14106
|
+
const meterValueSignature = valueElement.querySelector("meterValueSignature");
|
|
14028
14107
|
if (meterValueSignature != null) {
|
|
14029
14108
|
const meterValueSignatureEncoding = meterValueSignature.attributes.getNamedItem("encoding")?.value.trim().toLowerCase() ?? "";
|
|
14030
14109
|
let meterValueSignatureValue = meterValueSignature.textContent.trim();
|
|
@@ -14045,37 +14124,37 @@ var XMLContainer = class {
|
|
|
14045
14124
|
default:
|
|
14046
14125
|
return {
|
|
14047
14126
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
14048
|
-
message: "Unkown meter value signature encoding within the given XML container!",
|
|
14127
|
+
message: this.chargy.GetMultilanguageText("Unkown meter value signature encoding within the given XML container!"),
|
|
14049
14128
|
certainty: 0
|
|
14050
14129
|
};
|
|
14051
14130
|
}
|
|
14052
14131
|
if (IsNullOrEmpty(meterValueSignatureValue))
|
|
14053
14132
|
return {
|
|
14054
14133
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
14055
|
-
message: "The meter value signature within the given XML container must not be empty!",
|
|
14134
|
+
message: this.chargy.GetMultilanguageText("The meter value signature within the given XML container must not be empty!"),
|
|
14056
14135
|
certainty: 0
|
|
14057
14136
|
};
|
|
14058
14137
|
common.meterValueSignatures.push(meterValueSignatureValue);
|
|
14059
14138
|
}
|
|
14060
|
-
const signatureMethod =
|
|
14139
|
+
const signatureMethod = valueElement.querySelector("signatureMethod")?.textContent.trim().toLowerCase() ?? "";
|
|
14061
14140
|
if (common.signatureMethod == "")
|
|
14062
14141
|
common.signatureMethod = signatureMethod;
|
|
14063
14142
|
else if (common.signatureMethod != signatureMethod)
|
|
14064
14143
|
return {
|
|
14065
14144
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
14066
|
-
message: "Invalid mixture of different signature methods within the given XML container!",
|
|
14145
|
+
message: this.chargy.GetMultilanguageText("Invalid mixture of different signature methods within the given XML container!"),
|
|
14067
14146
|
certainty: 0
|
|
14068
14147
|
};
|
|
14069
|
-
const encodingMethod =
|
|
14148
|
+
const encodingMethod = valueElement.querySelector("encodingMethod")?.textContent.trim().toLowerCase() ?? "";
|
|
14070
14149
|
if (common.encodingMethod == "")
|
|
14071
14150
|
common.encodingMethod = encodingMethod;
|
|
14072
14151
|
else if (common.encodingMethod != encodingMethod)
|
|
14073
14152
|
return {
|
|
14074
14153
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
14075
|
-
message: "Invalid mixture of different signed data formats within the given XML container!",
|
|
14154
|
+
message: this.chargy.GetMultilanguageText("Invalid mixture of different signed data formats within the given XML container!"),
|
|
14076
14155
|
certainty: 0
|
|
14077
14156
|
};
|
|
14078
|
-
const encodedMeterValue =
|
|
14157
|
+
const encodedMeterValue = valueElement.querySelector("encodedMeterValue");
|
|
14079
14158
|
if (encodedMeterValue != null) {
|
|
14080
14159
|
const signedDataEncoding = encodedMeterValue.attributes.getNamedItem("encoding")?.value.trim() ?? "";
|
|
14081
14160
|
let signedDataValue = encodedMeterValue.textContent.trim();
|
|
@@ -14096,21 +14175,21 @@ var XMLContainer = class {
|
|
|
14096
14175
|
default:
|
|
14097
14176
|
return {
|
|
14098
14177
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
14099
|
-
message: "Unkown signed data encoding within the given XML container!",
|
|
14178
|
+
message: this.chargy.GetMultilanguageText("Unkown signed data encoding within the given XML container!"),
|
|
14100
14179
|
certainty: 0
|
|
14101
14180
|
};
|
|
14102
14181
|
}
|
|
14103
14182
|
if (IsNullOrEmpty(signedDataValue))
|
|
14104
14183
|
return {
|
|
14105
14184
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
14106
|
-
message: "The signed data value within the given XML container must not be empty!",
|
|
14185
|
+
message: this.chargy.GetMultilanguageText("The signed data value within the given XML container must not be empty!"),
|
|
14107
14186
|
certainty: 0
|
|
14108
14187
|
};
|
|
14109
14188
|
common.encodedMeterValues.push(signedDataValue);
|
|
14110
14189
|
} else
|
|
14111
14190
|
return {
|
|
14112
14191
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
14113
|
-
message: "The signed data tag within the given XML container must not be empty!",
|
|
14192
|
+
message: this.chargy.GetMultilanguageText("The signed data tag within the given XML container must not be empty!"),
|
|
14114
14193
|
certainty: 0
|
|
14115
14194
|
};
|
|
14116
14195
|
}
|
|
@@ -14118,13 +14197,13 @@ var XMLContainer = class {
|
|
|
14118
14197
|
}
|
|
14119
14198
|
return {
|
|
14120
14199
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
14121
|
-
message: this.chargy.
|
|
14200
|
+
message: this.chargy.GetMultilanguageText("UnknownOrInvalidChargingSessionFormat"),
|
|
14122
14201
|
certainty: 0
|
|
14123
14202
|
};
|
|
14124
14203
|
} catch (exception) {
|
|
14125
14204
|
return {
|
|
14126
14205
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
14127
|
-
message: "Exception occured: " + (exception instanceof Error ? exception.message : String(exception)),
|
|
14206
|
+
message: this.chargy.GetMultilanguageText("Exception occured: " + (exception instanceof Error ? exception.message : String(exception))),
|
|
14128
14207
|
certainty: 0
|
|
14129
14208
|
};
|
|
14130
14209
|
}
|
|
@@ -14136,12 +14215,6 @@ var ChargeIT = class {
|
|
|
14136
14215
|
constructor(chargy) {
|
|
14137
14216
|
this.chargy = chargy;
|
|
14138
14217
|
}
|
|
14139
|
-
bufferToHex(buffer, Reverse) {
|
|
14140
|
-
return (Reverse ? Array.from(new Uint8Array(buffer)).reverse() : Array.from(new Uint8Array(buffer))).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
14141
|
-
}
|
|
14142
|
-
bufferToNumber(buffer) {
|
|
14143
|
-
return parseInt(Array.from(new Uint8Array(buffer)).map((b) => b.toString(16).padStart(2, "0")).join(""), 16);
|
|
14144
|
-
}
|
|
14145
14218
|
//#region TryToParseOldChargeITMeterValuesFormat(CTR, evseId, address, geoLocation, signedMeterValues)
|
|
14146
14219
|
TryToParseOldChargeITMeterValuesFormat(CTR, evseId, address, geoLocation, signedMeterValues) {
|
|
14147
14220
|
const CTRArray = new Array();
|
|
@@ -14241,14 +14314,8 @@ var ChargeIT = class {
|
|
|
14241
14314
|
});
|
|
14242
14315
|
}
|
|
14243
14316
|
}
|
|
14244
|
-
const firstMeterValue = CTRArray
|
|
14245
|
-
const lastMeterValue = CTRArray
|
|
14246
|
-
if (firstMeterValue === void 0 || lastMeterValue === void 0)
|
|
14247
|
-
return {
|
|
14248
|
-
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
14249
|
-
message: this.chargy.GetLocalizedMessage("UnknownOrInvalidChargingSessionFormat"),
|
|
14250
|
-
certainty: 0
|
|
14251
|
-
};
|
|
14317
|
+
const firstMeterValue = getFirstArrayElement(CTRArray, "Missing first chargeIT meter value");
|
|
14318
|
+
const lastMeterValue = getLastArrayElement(CTRArray, "Missing last chargeIT meter value");
|
|
14252
14319
|
CTR["@id"] = lastMeterValue["transactionId"];
|
|
14253
14320
|
CTR.begin = this.chargy.moment.unix(firstMeterValue["measuredValue"]["timestampLocal"]["timestamp"]).utc().format();
|
|
14254
14321
|
CTR.end = this.chargy.moment.unix(lastMeterValue["measuredValue"]["timestampLocal"]["timestamp"]).utc().format();
|
|
@@ -14431,38 +14498,38 @@ var ChargeIT = class {
|
|
|
14431
14498
|
{
|
|
14432
14499
|
const placeInfo = asJSONObject(SomeJSON["placeInfo"]);
|
|
14433
14500
|
if (placeInfo === void 0) {
|
|
14434
|
-
errors.push(this.chargy.
|
|
14501
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidPlaceInfo")));
|
|
14435
14502
|
secondaryErrors += 13;
|
|
14436
14503
|
} else {
|
|
14437
14504
|
const evseId = placeInfo["evseId"];
|
|
14438
14505
|
if (!isMandatoryString(evseId))
|
|
14439
|
-
errors.push(this.chargy.
|
|
14506
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidEVSEId")));
|
|
14440
14507
|
const address = asJSONObject(placeInfo["address"]);
|
|
14441
14508
|
if (address === void 0) {
|
|
14442
|
-
errors.push(this.chargy.
|
|
14509
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidAddress")));
|
|
14443
14510
|
secondaryErrors += 3;
|
|
14444
14511
|
} else {
|
|
14445
14512
|
if (!isMandatoryString(address["street"]))
|
|
14446
|
-
errors.push(this.chargy.
|
|
14513
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidAddressStreetName")));
|
|
14447
14514
|
if (!isMandatoryString(address["zipCode"]))
|
|
14448
|
-
errors.push(this.chargy.
|
|
14515
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidAddressZIPCode")));
|
|
14449
14516
|
if (!isMandatoryString(address["town"]))
|
|
14450
|
-
errors.push(this.chargy.
|
|
14517
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidAddressCityName")));
|
|
14451
14518
|
}
|
|
14452
14519
|
const geoLocation = asJSONObject(placeInfo["geoLocation"]);
|
|
14453
14520
|
if (geoLocation === void 0) {
|
|
14454
|
-
errors.push(this.chargy.
|
|
14521
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidGeoLocation")));
|
|
14455
14522
|
secondaryErrors += 2;
|
|
14456
14523
|
} else {
|
|
14457
14524
|
if (!isMandatoryNumber(geoLocation["lat"]))
|
|
14458
|
-
errors.push(this.chargy.
|
|
14525
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidGeoLocationLatitude")));
|
|
14459
14526
|
if (!isMandatoryNumber(geoLocation["lon"]))
|
|
14460
|
-
errors.push(this.chargy.
|
|
14527
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidGeoLocationLongitude")));
|
|
14461
14528
|
}
|
|
14462
14529
|
}
|
|
14463
14530
|
const signedMeterValues = SomeJSON["signedMeterValues"];
|
|
14464
14531
|
if (!isMandatoryJSONArray(signedMeterValues) || signedMeterValues.length < 2) {
|
|
14465
|
-
errors.push(this.chargy.
|
|
14532
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidSignedMeterValues")));
|
|
14466
14533
|
secondaryErrors += 2 * 39;
|
|
14467
14534
|
} else {
|
|
14468
14535
|
numberOfFormatChecks += 39 * (signedMeterValues.length - 2);
|
|
@@ -14471,135 +14538,134 @@ var ChargeIT = class {
|
|
|
14471
14538
|
for (const signedMeterValue of signedMeterValues.map((smv) => asJSONObject(smv))) {
|
|
14472
14539
|
if ((signedMeterValue?.["@context"] ?? oldChargeITMeterValueFormat) !== signedMeterValueContext) {
|
|
14473
14540
|
if (consistent)
|
|
14474
|
-
errors.push(this.chargy.
|
|
14541
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("InconsistentJSONContextInformation")));
|
|
14475
14542
|
consistent = false;
|
|
14476
14543
|
}
|
|
14477
14544
|
}
|
|
14478
14545
|
if (consistent) {
|
|
14479
14546
|
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") {
|
|
14480
14547
|
} else if (signedMeterValueContext.startsWith("ALFEN")) {
|
|
14481
|
-
} else if (containerFormat === oldChargeITContainerFormat) {
|
|
14482
14548
|
} else if (signedMeterValueContext === oldChargeITMeterValueFormat) {
|
|
14483
14549
|
let measurementCounter = 0;
|
|
14484
14550
|
for (const signedMeterValue of signedMeterValues) {
|
|
14485
14551
|
measurementCounter++;
|
|
14486
14552
|
if (!isMandatoryJSONObject(signedMeterValue)) {
|
|
14487
|
-
errors.push(this.chargy.
|
|
14553
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalidSignedMeterValueP", measurementCounter)));
|
|
14488
14554
|
secondaryErrors += 38;
|
|
14489
14555
|
} else {
|
|
14490
14556
|
if (!isMandatoryString(signedMeterValue["measurementId"]))
|
|
14491
|
-
errors.push(this.chargy.
|
|
14557
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeasurementIdP", measurementCounter)));
|
|
14492
14558
|
if (!isMandatoryNumber(signedMeterValue["timestamp"]))
|
|
14493
|
-
errors.push(this.chargy.
|
|
14559
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_TimestampP", measurementCounter)));
|
|
14494
14560
|
if (!isMandatoryString(signedMeterValue["transactionId"]))
|
|
14495
|
-
errors.push(this.chargy.
|
|
14561
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_TransactionIdP", measurementCounter)));
|
|
14496
14562
|
if (!isMandatoryString(signedMeterValue["signature"]))
|
|
14497
|
-
errors.push(this.chargy.
|
|
14563
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_SignatureP", measurementCounter)));
|
|
14498
14564
|
const meterInfo = signedMeterValue["meterInfo"];
|
|
14499
14565
|
if (!isMandatoryJSONObject(meterInfo)) {
|
|
14500
|
-
errors.push(this.chargy.
|
|
14566
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfoP", measurementCounter)));
|
|
14501
14567
|
secondaryErrors += 5;
|
|
14502
14568
|
} else {
|
|
14503
14569
|
if (!isMandatoryString(meterInfo["meterId"]))
|
|
14504
|
-
errors.push(this.chargy.
|
|
14570
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_MeterIdP", measurementCounter)));
|
|
14505
14571
|
if (!isMandatoryString(meterInfo["type"]))
|
|
14506
|
-
errors.push(this.chargy.
|
|
14572
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_TypeP", measurementCounter)));
|
|
14507
14573
|
if (!isMandatoryString(meterInfo["firmwareVersion"]))
|
|
14508
|
-
errors.push(this.chargy.
|
|
14574
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_FirmwareVersionP", measurementCounter)));
|
|
14509
14575
|
if (!isMandatoryString(meterInfo["publicKey"]))
|
|
14510
|
-
errors.push(this.chargy.
|
|
14576
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_PublicKeyP", measurementCounter)));
|
|
14511
14577
|
if (!isMandatoryString(meterInfo["manufacturer"]))
|
|
14512
|
-
errors.push(this.chargy.
|
|
14578
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_ManufacturerP", measurementCounter)));
|
|
14513
14579
|
if (isOptionalJSONArrayError(meterInfo["publicKeySignatures"]))
|
|
14514
|
-
errors.push(this.chargy.
|
|
14580
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("Invalid_SignedMeterValue_MeterInfo_PublicKeySignaturesP", measurementCounter)));
|
|
14515
14581
|
}
|
|
14516
14582
|
const contract = signedMeterValue["contract"];
|
|
14517
14583
|
if (!isMandatoryJSONObject(contract)) {
|
|
14518
|
-
errors.push(this.chargy.
|
|
14584
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_ContractP", measurementCounter)));
|
|
14519
14585
|
secondaryErrors += 7;
|
|
14520
14586
|
} else {
|
|
14521
14587
|
if (!isMandatoryString(contract["id"]))
|
|
14522
|
-
errors.push(this.chargy.
|
|
14588
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_Contract_IdP", measurementCounter)));
|
|
14523
14589
|
if (!isMandatoryString(contract["type"]))
|
|
14524
|
-
errors.push(this.chargy.
|
|
14590
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_Contract_TypeP", measurementCounter)));
|
|
14525
14591
|
if (!isMandatoryNumber(contract["timestamp"]))
|
|
14526
|
-
errors.push(this.chargy.
|
|
14592
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_Contract_TimestampP", measurementCounter)));
|
|
14527
14593
|
const timestampLocal = contract["timestampLocal"];
|
|
14528
14594
|
if (!isMandatoryJSONObject(timestampLocal)) {
|
|
14529
|
-
errors.push(this.chargy.
|
|
14595
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_Contract_TimestampLocalP", measurementCounter)));
|
|
14530
14596
|
secondaryErrors += 3;
|
|
14531
14597
|
} else {
|
|
14532
14598
|
if (!isMandatoryNumber(timestampLocal["timestamp"]))
|
|
14533
|
-
errors.push(this.chargy.
|
|
14599
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_Contract_TimestampLocal_TimestampP", measurementCounter)));
|
|
14534
14600
|
if (!isMandatoryNumber(timestampLocal["localOffset"]))
|
|
14535
|
-
errors.push(this.chargy.
|
|
14601
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_Contract_TimestampLocal_LocalOffsetP", measurementCounter)));
|
|
14536
14602
|
if (!isMandatoryNumber(timestampLocal["seasonOffset"]))
|
|
14537
|
-
errors.push(this.chargy.
|
|
14603
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_Contract_TimestampLocal_SeasonOffsetP", measurementCounter)));
|
|
14538
14604
|
}
|
|
14539
14605
|
}
|
|
14540
14606
|
const measuredValue = signedMeterValue["measuredValue"];
|
|
14541
14607
|
if (!isMandatoryJSONObject(measuredValue)) {
|
|
14542
|
-
errors.push(this.chargy.
|
|
14608
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeasuredValueP", measurementCounter)));
|
|
14543
14609
|
secondaryErrors += 9;
|
|
14544
14610
|
} else {
|
|
14545
14611
|
if (!isMandatoryString(measuredValue["value"]))
|
|
14546
|
-
errors.push(this.chargy.
|
|
14612
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeasuredValue_ValueP", measurementCounter)));
|
|
14547
14613
|
if (!isMandatoryString(measuredValue["unit"]))
|
|
14548
|
-
errors.push(this.chargy.
|
|
14614
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeasuredValue_UnitP", measurementCounter)));
|
|
14549
14615
|
if (!isMandatoryNumber(measuredValue["scale"]))
|
|
14550
|
-
errors.push(this.chargy.
|
|
14616
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeasuredValue_ScaleP", measurementCounter)));
|
|
14551
14617
|
if (!isMandatoryString(measuredValue["valueType"]))
|
|
14552
|
-
errors.push(this.chargy.
|
|
14618
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeasuredValue_ValueTypeP", measurementCounter)));
|
|
14553
14619
|
if (!isMandatoryNumber(measuredValue["unitEncoded"]))
|
|
14554
|
-
errors.push(this.chargy.
|
|
14620
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeasuredValue_UnitEncodedP", measurementCounter)));
|
|
14555
14621
|
const timestampLocal = measuredValue["timestampLocal"];
|
|
14556
14622
|
if (!isMandatoryJSONObject(timestampLocal)) {
|
|
14557
|
-
errors.push(this.chargy.
|
|
14623
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalidMeasuredValueTimestampLocalP", measurementCounter)));
|
|
14558
14624
|
secondaryErrors += 3;
|
|
14559
14625
|
} else {
|
|
14560
14626
|
if (!isMandatoryNumber(timestampLocal["timestamp"]))
|
|
14561
|
-
errors.push(this.chargy.
|
|
14627
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalidMeasuredValueTimestampLocalTimestampP", measurementCounter)));
|
|
14562
14628
|
if (!isMandatoryNumber(timestampLocal["localOffset"]))
|
|
14563
|
-
errors.push(this.chargy.
|
|
14629
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalidMeasuredValueTimestampLocalOffsetP", measurementCounter)));
|
|
14564
14630
|
if (!isMandatoryNumber(timestampLocal["seasonOffset"]))
|
|
14565
|
-
errors.push(this.chargy.
|
|
14631
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalidMeasuredValueTimestampSeasonOffsetP", measurementCounter)));
|
|
14566
14632
|
}
|
|
14567
14633
|
}
|
|
14568
14634
|
const measurand = signedMeterValue["measurand"];
|
|
14569
14635
|
if (!isMandatoryJSONObject(measurand)) {
|
|
14570
|
-
errors.push(this.chargy.
|
|
14636
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeasurandP", measurementCounter)));
|
|
14571
14637
|
secondaryErrors += 2;
|
|
14572
14638
|
} else {
|
|
14573
14639
|
if (!isMandatoryString(measurand["id"]))
|
|
14574
|
-
errors.push(this.chargy.
|
|
14640
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_Measurand_IdP", measurementCounter)));
|
|
14575
14641
|
if (!isMandatoryString(measurand["name"]))
|
|
14576
|
-
errors.push(this.chargy.
|
|
14642
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_Measurand_NameP", measurementCounter)));
|
|
14577
14643
|
}
|
|
14578
14644
|
const additionalInfo = signedMeterValue["additionalInfo"];
|
|
14579
14645
|
if (!isMandatoryJSONObject(additionalInfo)) {
|
|
14580
|
-
errors.push(this.chargy.
|
|
14646
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_AdditionalInformationP", measurementCounter)));
|
|
14581
14647
|
secondaryErrors += 4;
|
|
14582
14648
|
} else {
|
|
14583
14649
|
if (!isMandatoryString(additionalInfo["status"]))
|
|
14584
|
-
errors.push(this.chargy.
|
|
14650
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_AdditionalInformation_StatusP", measurementCounter)));
|
|
14585
14651
|
const indexes = additionalInfo["indexes"];
|
|
14586
14652
|
if (!isMandatoryJSONObject(indexes)) {
|
|
14587
|
-
errors.push(this.chargy.
|
|
14653
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_AdditionalInformation_IndexesP", measurementCounter)));
|
|
14588
14654
|
secondaryErrors += 2;
|
|
14589
14655
|
} else {
|
|
14590
14656
|
if (!isMandatoryNumber(indexes["timer"]))
|
|
14591
|
-
errors.push(this.chargy.
|
|
14657
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_AdditionalInformation_Indexes_TimerP", measurementCounter)));
|
|
14592
14658
|
if (!isMandatoryString(indexes["logBook"]))
|
|
14593
|
-
errors.push(this.chargy.
|
|
14659
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_AdditionalInformation_Indexes_LogBookP", measurementCounter)));
|
|
14594
14660
|
}
|
|
14595
14661
|
}
|
|
14596
14662
|
const chargePoint = signedMeterValue["chargePoint"];
|
|
14597
|
-
if (!isMandatoryJSONObject(chargePoint)) {
|
|
14598
|
-
errors.push(this.chargy.
|
|
14663
|
+
if (chargePoint !== void 0 && !isMandatoryJSONObject(chargePoint)) {
|
|
14664
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_ChargePointInformationP", measurementCounter)));
|
|
14599
14665
|
secondaryErrors += 1;
|
|
14600
|
-
} else {
|
|
14666
|
+
} else if (isMandatoryJSONObject(chargePoint)) {
|
|
14601
14667
|
if (!isMandatoryString(chargePoint["softwareVersion"]))
|
|
14602
|
-
errors.push(this.chargy.
|
|
14668
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_ChargePointInformation_SoftwareVersionP", measurementCounter)));
|
|
14603
14669
|
}
|
|
14604
14670
|
}
|
|
14605
14671
|
}
|
|
@@ -14745,19 +14811,17 @@ var ChargeIT = class {
|
|
|
14745
14811
|
}
|
|
14746
14812
|
);
|
|
14747
14813
|
}
|
|
14748
|
-
if (
|
|
14749
|
-
|
|
14750
|
-
|
|
14751
|
-
|
|
14752
|
-
|
|
14753
|
-
|
|
14754
|
-
|
|
14755
|
-
|
|
14756
|
-
address: { "street": address_street, "postalCode": address_zipCode, "city": address_town, "country": address_country }
|
|
14757
|
-
}
|
|
14814
|
+
if (asJSONObject(signedMeterValues[0])?.["format"] == "ALFEN")
|
|
14815
|
+
return new Alfen(this.chargy).TryToParseALFENFormat(
|
|
14816
|
+
signedMeterValues.map((value) => asString(asJSONObject(value)?.["payload"]) ?? ""),
|
|
14817
|
+
{
|
|
14818
|
+
EVSEId: evseId,
|
|
14819
|
+
chargingStation: {
|
|
14820
|
+
geoLocation: { "lat": geoLocation_lat, "lng": geoLocation_lon },
|
|
14821
|
+
address: { "street": address_street, "postalCode": address_zipCode, "city": address_town, "country": address_country }
|
|
14758
14822
|
}
|
|
14759
|
-
|
|
14760
|
-
|
|
14823
|
+
}
|
|
14824
|
+
);
|
|
14761
14825
|
if (signedMeterValueContext === oldChargeITMeterValueFormat)
|
|
14762
14826
|
return this.TryToParseOldChargeITMeterValuesFormat(
|
|
14763
14827
|
CTR,
|
|
@@ -14777,7 +14841,7 @@ var ChargeIT = class {
|
|
|
14777
14841
|
} catch (exception) {
|
|
14778
14842
|
return {
|
|
14779
14843
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
14780
|
-
message: "Exception occured: " + (exception instanceof Error ? exception.message : String(exception)),
|
|
14844
|
+
message: this.chargy.GetMultilanguageText("Exception occured: " + (exception instanceof Error ? exception.message : String(exception))),
|
|
14781
14845
|
errors,
|
|
14782
14846
|
warnings,
|
|
14783
14847
|
certainty: (numberOfFormatChecks - errors.length - secondaryErrors) / numberOfFormatChecks
|
|
@@ -14850,142 +14914,140 @@ var ChargeIT = class {
|
|
|
14850
14914
|
const totalCosts_flat_cost = totalCosts_flat?.["cost"];
|
|
14851
14915
|
const signedMeterValues = SomeJSON["signedMeterValues"];
|
|
14852
14916
|
if (!isMandatoryString(chargingSessionId))
|
|
14853
|
-
errors.push(this.chargy.
|
|
14917
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid charge transparency record identification!")));
|
|
14854
14918
|
if (!isMandatoryJSONObject(chargePointInfo)) {
|
|
14855
|
-
errors.push(this.chargy.
|
|
14919
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidChargePointInfo")));
|
|
14856
14920
|
secondaryErrors += 19;
|
|
14857
14921
|
} else {
|
|
14858
14922
|
if (!isMandatoryString(evseId))
|
|
14859
|
-
errors.push(this.chargy.
|
|
14923
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidEVSEIdentification")));
|
|
14860
14924
|
if (!isMandatoryJSONObject(placeInfo)) {
|
|
14861
|
-
errors.push(this.chargy.
|
|
14925
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidPlaceInfo")));
|
|
14862
14926
|
secondaryErrors += 8;
|
|
14863
14927
|
} else {
|
|
14864
14928
|
if (!isMandatoryJSONObject(geoLocation)) {
|
|
14865
|
-
errors.push(this.chargy.
|
|
14929
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidGeoLocation")));
|
|
14866
14930
|
secondaryErrors += 2;
|
|
14867
14931
|
} else {
|
|
14868
14932
|
if (!isMandatoryNumber(geoLocation_lat))
|
|
14869
|
-
errors.push(this.chargy.
|
|
14933
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidGeoLocationLatitude")));
|
|
14870
14934
|
if (!isMandatoryNumber(geoLocation_lon))
|
|
14871
|
-
errors.push(this.chargy.
|
|
14935
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidGeoLocationLongitude")));
|
|
14872
14936
|
}
|
|
14873
14937
|
if (!isMandatoryJSONObject(address)) {
|
|
14874
|
-
errors.push(this.chargy.
|
|
14938
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidAddress")));
|
|
14875
14939
|
secondaryErrors += 4;
|
|
14876
14940
|
} else {
|
|
14877
14941
|
if (!isMandatoryString(address_street))
|
|
14878
|
-
errors.push(this.chargy.
|
|
14942
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidAddressStreetName")));
|
|
14879
14943
|
if (!isMandatoryString(address_zipCode))
|
|
14880
|
-
errors.push(this.chargy.
|
|
14944
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidAddressZIPCode")));
|
|
14881
14945
|
if (!isMandatoryString(address_town))
|
|
14882
|
-
errors.push(this.chargy.
|
|
14946
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidAddressCityName")));
|
|
14883
14947
|
if (!isMandatoryString(address_country))
|
|
14884
|
-
errors.push(this.chargy.
|
|
14948
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidAddressCountryName")));
|
|
14885
14949
|
}
|
|
14886
14950
|
}
|
|
14887
14951
|
}
|
|
14888
14952
|
if (!isMandatoryJSONObject(chargingStationInfo)) {
|
|
14889
|
-
errors.push(this.chargy.
|
|
14953
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidChargingStationInfo")));
|
|
14890
14954
|
secondaryErrors += 5;
|
|
14891
14955
|
} else {
|
|
14892
14956
|
if (!isOptionalString(chargingStation_manufacturer))
|
|
14893
|
-
errors.push(this.chargy.
|
|
14957
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station manufacturer!")));
|
|
14894
14958
|
if (!isOptionalString(chargingStation_type))
|
|
14895
|
-
errors.push(this.chargy.
|
|
14959
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station type!")));
|
|
14896
14960
|
if (!isOptionalString(chargingStation_serialNumber))
|
|
14897
|
-
errors.push(this.chargy.
|
|
14961
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station serial number!")));
|
|
14898
14962
|
if (!isOptionalString(chargingStation_controllerSoftwareVersion))
|
|
14899
|
-
errors.push(this.chargy.
|
|
14963
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station controller software version!")));
|
|
14900
14964
|
if (!isOptionalString(chargingStation_compliance))
|
|
14901
|
-
errors.push(this.chargy.
|
|
14965
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station compliance!")));
|
|
14902
14966
|
if (!isOptionalURL(chargingStation_complianceURL))
|
|
14903
|
-
errors.push(this.chargy.
|
|
14967
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station compliance URL!")));
|
|
14904
14968
|
if (!isOptionalString(chargingStation_conformity))
|
|
14905
|
-
errors.push(this.chargy.
|
|
14969
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station conformity!")));
|
|
14906
14970
|
if (!isOptionalURL(chargingStation_conformity_URL))
|
|
14907
|
-
errors.push(this.chargy.
|
|
14971
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station conformity URL!")));
|
|
14908
14972
|
if (!isOptionalURL(chargingStation_conformity_certificateId))
|
|
14909
|
-
errors.push(this.chargy.
|
|
14973
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station conformity certificate identification!")));
|
|
14910
14974
|
if (!isOptionalString(chargingStation_calibration))
|
|
14911
|
-
errors.push(this.chargy.
|
|
14975
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station calibration!")));
|
|
14912
14976
|
if (!isOptionalURL(chargingStation_calibration_URL))
|
|
14913
|
-
errors.push(this.chargy.
|
|
14977
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station calibration URL!")));
|
|
14914
14978
|
if (!isOptionalURL(chargingStation_calibration_certificateId))
|
|
14915
|
-
errors.push(this.chargy.
|
|
14979
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Invalid charging station calibration certificate identification!")));
|
|
14916
14980
|
}
|
|
14917
14981
|
if (meterInfo) {
|
|
14918
14982
|
if (!isOptionalString(meterInfo_meterId))
|
|
14919
|
-
errors.push(this.chargy.
|
|
14983
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_MeterIdP", 1)));
|
|
14920
14984
|
if (!isOptionalString(meterInfo_manufacturer))
|
|
14921
|
-
errors.push(this.chargy.
|
|
14985
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_ManufacturerP", 1)));
|
|
14922
14986
|
if (!isOptionalString(meterInfo_manufacturerURL))
|
|
14923
|
-
errors.push(this.chargy.
|
|
14987
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_ManufacturerP", 1)));
|
|
14924
14988
|
if (!isOptionalString(meterInfo_model))
|
|
14925
|
-
errors.push(this.chargy.
|
|
14989
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_ManufacturerP", 1)));
|
|
14926
14990
|
if (!isOptionalString(meterInfo_modelURL))
|
|
14927
|
-
errors.push(this.chargy.
|
|
14991
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_ManufacturerP", 1)));
|
|
14928
14992
|
if (!isOptionalString(meterInfo_firmwareVersion))
|
|
14929
|
-
errors.push(this.chargy.
|
|
14993
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_FirmwareVersionP", 1)));
|
|
14930
14994
|
if (!isOptionalString(meterInfo_hardwareVersion))
|
|
14931
|
-
errors.push(this.chargy.
|
|
14995
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_FirmwareVersionP", 1)));
|
|
14932
14996
|
if (!isOptionalString(meterInfo_publicKey))
|
|
14933
|
-
errors.push(this.chargy.
|
|
14997
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_PublicKeyP", 1)));
|
|
14934
14998
|
if (!isOptionalString(meterInfo_publicKeyFormat))
|
|
14935
|
-
errors.push(this.chargy.
|
|
14999
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_PublicKeyP", 1)));
|
|
14936
15000
|
if (!isOptionalString(meterInfo_publicKeyEncoding))
|
|
14937
|
-
errors.push(this.chargy.
|
|
15001
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_PublicKeyP", 1)));
|
|
14938
15002
|
if (!isOptionalString(meterInfo_signatureFormat))
|
|
14939
|
-
errors.push(this.chargy.
|
|
15003
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_PublicKeyP", 1)));
|
|
14940
15004
|
if (!isOptionalString(meterInfo_signatureEncoding))
|
|
14941
|
-
errors.push(this.chargy.
|
|
15005
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_PublicKeyP", 1)));
|
|
14942
15006
|
}
|
|
14943
15007
|
if (connectorInfo) {
|
|
14944
15008
|
if (!isOptionalString(connectorInfo_type))
|
|
14945
|
-
errors.push(this.chargy.
|
|
15009
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_MeterIdP", 1)));
|
|
14946
15010
|
if (!isOptionalString(connectorInfo_losses))
|
|
14947
|
-
errors.push(this.chargy.
|
|
15011
|
+
errors.push(CreateError(this.chargy.GetMultilanguageTextWithParameter("MissingOrInvalid_SignedMeterValue_MeterInfo_MeterIdP", 1)));
|
|
14948
15012
|
}
|
|
14949
15013
|
if (isMandatoryJSONArray(chargingTariffs)) {
|
|
14950
|
-
for (let i = 0; i < chargingTariffs.length; i++) {
|
|
14951
|
-
}
|
|
14952
15014
|
}
|
|
14953
15015
|
if (totalCosts) {
|
|
14954
15016
|
if (!isMandatoryNumber(totalCosts_total))
|
|
14955
|
-
errors.push(this.chargy.
|
|
15017
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid total costs within the charging costs!")));
|
|
14956
15018
|
if (!isMandatoryString(totalCosts_currency))
|
|
14957
|
-
errors.push(this.chargy.
|
|
15019
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid currency within the charging costs!")));
|
|
14958
15020
|
if (totalCosts_reservation) {
|
|
14959
15021
|
if (!isMandatoryNumber(totalCosts_reservation_cost))
|
|
14960
|
-
errors.push(this.chargy.
|
|
15022
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid reservation cost within the charging costs!")));
|
|
14961
15023
|
if (!isMandatoryString(totalCosts_reservation_unit))
|
|
14962
|
-
errors.push(this.chargy.
|
|
15024
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid reservation unit within the charging costs!")));
|
|
14963
15025
|
}
|
|
14964
15026
|
if (totalCosts_energy) {
|
|
14965
15027
|
if (!isMandatoryNumber(totalCosts_energy_cost))
|
|
14966
|
-
errors.push(this.chargy.
|
|
15028
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid energy cost within the charging costs!")));
|
|
14967
15029
|
if (!isMandatoryString(totalCosts_energy_unit))
|
|
14968
|
-
errors.push(this.chargy.
|
|
15030
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid energy unit within the charging costs!")));
|
|
14969
15031
|
}
|
|
14970
15032
|
if (totalCosts_time) {
|
|
14971
15033
|
if (!isMandatoryNumber(totalCosts_time_cost))
|
|
14972
|
-
errors.push(this.chargy.
|
|
15034
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid time cost within the charging costs!")));
|
|
14973
15035
|
if (!isMandatoryString(totalCosts_time_unit))
|
|
14974
|
-
errors.push(this.chargy.
|
|
15036
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid time unit within the charging costs!")));
|
|
14975
15037
|
}
|
|
14976
15038
|
if (totalCosts_idle) {
|
|
14977
15039
|
if (!isMandatoryNumber(totalCosts_idle_cost))
|
|
14978
|
-
errors.push(this.chargy.
|
|
15040
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid idle cost within the charging costs!")));
|
|
14979
15041
|
if (!isMandatoryString(totalCosts_idle_unit))
|
|
14980
|
-
errors.push(this.chargy.
|
|
15042
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid idle unit within the charging costs!")));
|
|
14981
15043
|
}
|
|
14982
15044
|
if (totalCosts_flat) {
|
|
14983
15045
|
if (!isMandatoryNumber(totalCosts_flat_cost))
|
|
14984
|
-
errors.push(this.chargy.
|
|
15046
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("Missing or invalid flat cost within the charging costs!")));
|
|
14985
15047
|
}
|
|
14986
15048
|
}
|
|
14987
15049
|
if (!isMandatoryJSONArray(signedMeterValues) || signedMeterValues.length < 2) {
|
|
14988
|
-
errors.push(this.chargy.
|
|
15050
|
+
errors.push(CreateError(this.chargy.GetMultilanguageText("MissingOrInvalidSignedMeterValues")));
|
|
14989
15051
|
secondaryErrors += 2 * 39;
|
|
14990
15052
|
} else {
|
|
14991
15053
|
const firstSMV = asJSONObject(signedMeterValues[0]);
|
|
@@ -14995,7 +15057,7 @@ var ChargeIT = class {
|
|
|
14995
15057
|
const context = asString(currentSMV?.["@context"])?.trim() ?? asString(currentSMV?.["format"])?.trim() ?? null;
|
|
14996
15058
|
if (smvContext !== context) return {
|
|
14997
15059
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
14998
|
-
message: "Inconsistent signed meter value format!",
|
|
15060
|
+
message: this.chargy.GetMultilanguageText("Inconsistent signed meter value format!"),
|
|
14999
15061
|
certainty: 1
|
|
15000
15062
|
};
|
|
15001
15063
|
}
|
|
@@ -15101,9 +15163,9 @@ var ChargeIT = class {
|
|
|
15101
15163
|
],
|
|
15102
15164
|
certainty: 0
|
|
15103
15165
|
};
|
|
15104
|
-
if (smvContext?.startsWith("https://www.chargeit-mobility.com/contexts/bsm-ws36a-json"))
|
|
15166
|
+
if (smvContext?.startsWith("https://www.chargeit-mobility.com/contexts/bsm-ws36a-json") === true)
|
|
15105
15167
|
return new BSMCrypt01(this.chargy).tryToParseBSM_WS36aMeasurements(CTR, evseIdStr, asString(chargingStation_controllerSoftwareVersion) ?? null, signedMeterValues);
|
|
15106
|
-
if (smvContext?.startsWith("ALFEN"))
|
|
15168
|
+
if (smvContext?.startsWith("ALFEN") === true)
|
|
15107
15169
|
return new Alfen(this.chargy).TryToParseALFENFormat(
|
|
15108
15170
|
signedMeterValues.map((value) => asString(asJSONObject(value)?.["payload"]) ?? ""),
|
|
15109
15171
|
{
|
|
@@ -15144,7 +15206,7 @@ var ChargeIT = class {
|
|
|
15144
15206
|
} catch (exception) {
|
|
15145
15207
|
return {
|
|
15146
15208
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
15147
|
-
message: "Exception occured: " + (exception instanceof Error ? exception.message : String(exception)),
|
|
15209
|
+
message: this.chargy.GetMultilanguageText("Exception occured: " + (exception instanceof Error ? exception.message : String(exception))),
|
|
15148
15210
|
errors,
|
|
15149
15211
|
warnings,
|
|
15150
15212
|
certainty: (numberOfFormatChecks - errors.length - secondaryErrors) / numberOfFormatChecks
|
|
@@ -15153,7 +15215,7 @@ var ChargeIT = class {
|
|
|
15153
15215
|
}
|
|
15154
15216
|
return {
|
|
15155
15217
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
15156
|
-
message: "No chargeIT charge transparency record",
|
|
15218
|
+
message: this.chargy.GetMultilanguageText("No chargeIT charge transparency record"),
|
|
15157
15219
|
errors,
|
|
15158
15220
|
warnings,
|
|
15159
15221
|
certainty: 0
|
|
@@ -15172,7 +15234,7 @@ var ChargePoint = class {
|
|
|
15172
15234
|
if (!isMandatoryJSONObject(SomeJSON))
|
|
15173
15235
|
return {
|
|
15174
15236
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
15175
|
-
message: this.chargy.
|
|
15237
|
+
message: this.chargy.GetMultilanguageText("UnknownOrInvalidChargingSessionFormat"),
|
|
15176
15238
|
certainty: 0
|
|
15177
15239
|
};
|
|
15178
15240
|
if (SomeJSON["company_name"] !== void 0 && SomeJSON["display_unit"] !== void 0 && //SomeJSON["energy"] !== undefined &&
|
|
@@ -15206,10 +15268,8 @@ var ChargePoint = class {
|
|
|
15206
15268
|
if (startTimeUTC !== void 0 && (parkingEnd === void 0 || startTimeUTC > parkingEnd))
|
|
15207
15269
|
parkingEnd = endTimeUTC;
|
|
15208
15270
|
}
|
|
15209
|
-
|
|
15210
|
-
|
|
15211
|
-
if (chargingEnd === void 0)
|
|
15212
|
-
chargingEnd = parkingEnd;
|
|
15271
|
+
chargingStart ??= parkingStart;
|
|
15272
|
+
chargingEnd ??= parkingEnd;
|
|
15213
15273
|
let sessionStart = parkingStart !== void 0 && (chargingStart === void 0 || parkingStart < chargingStart) ? parkingStart : chargingStart;
|
|
15214
15274
|
if (sessionStart === void 0 && parkingStart !== void 0)
|
|
15215
15275
|
sessionStart = parkingStart;
|
|
@@ -15358,7 +15418,7 @@ var ChargePoint = class {
|
|
|
15358
15418
|
"status": "Unvalidated" /* Unvalidated */
|
|
15359
15419
|
};
|
|
15360
15420
|
if (parking && parking.length > 0 && CTR.chargingSessions && CTR.chargingSessions.length > 0) {
|
|
15361
|
-
const chargingSession = CTR.chargingSessions
|
|
15421
|
+
const chargingSession = getFirstArrayElement(CTR.chargingSessions, "Missing ChargePoint charging session");
|
|
15362
15422
|
chargingSession.parking = [];
|
|
15363
15423
|
for (const parkingItem of parking) {
|
|
15364
15424
|
const parkingObj = asJSONObject(parkingItem);
|
|
@@ -15495,13 +15555,13 @@ var ChargePoint = class {
|
|
|
15495
15555
|
} catch (exception) {
|
|
15496
15556
|
return {
|
|
15497
15557
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
15498
|
-
message: "Exception occured: " + (exception instanceof Error ? exception.message : String(exception)),
|
|
15558
|
+
message: this.chargy.GetMultilanguageText("Exception occured: " + (exception instanceof Error ? exception.message : String(exception))),
|
|
15499
15559
|
certainty: 0
|
|
15500
15560
|
};
|
|
15501
15561
|
}
|
|
15502
15562
|
return {
|
|
15503
15563
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
15504
|
-
message: this.chargy.
|
|
15564
|
+
message: this.chargy.GetMultilanguageText("UnknownOrInvalidChargingSessionFormat"),
|
|
15505
15565
|
certainty: 0
|
|
15506
15566
|
};
|
|
15507
15567
|
}
|
|
@@ -15524,7 +15584,7 @@ var ChargePointCrypt01 = class extends ACrypt {
|
|
|
15524
15584
|
if (chargingSession.ctr === void 0) {
|
|
15525
15585
|
return {
|
|
15526
15586
|
status: "InvalidSignature" /* InvalidSignature */,
|
|
15527
|
-
message: this.chargy.
|
|
15587
|
+
message: this.chargy.GetMultilanguageText("InvalidSignature"),
|
|
15528
15588
|
certainty: 0
|
|
15529
15589
|
};
|
|
15530
15590
|
}
|
|
@@ -15560,7 +15620,7 @@ var ChargePointCrypt01 = class extends ACrypt {
|
|
|
15560
15620
|
if (publicKeys.length == 0)
|
|
15561
15621
|
return {
|
|
15562
15622
|
status: "PublicKeyNotFound" /* PublicKeyNotFound */,
|
|
15563
|
-
message: this.chargy.
|
|
15623
|
+
message: this.chargy.GetMultilanguageText("Public key notFound"),
|
|
15564
15624
|
certainty: 0
|
|
15565
15625
|
};
|
|
15566
15626
|
if (plainText !== "" && chargingSession.signature != null && chargingSession.signature !== "") {
|
|
@@ -15635,7 +15695,7 @@ var ChargePointCrypt01 = class extends ACrypt {
|
|
|
15635
15695
|
if (measurementValue.result?.status !== "ValidSignature" /* ValidSignature */ && measurementValue.result?.status !== "NoOperation" /* NoOperation */) {
|
|
15636
15696
|
return {
|
|
15637
15697
|
status: "InvalidSignature" /* InvalidSignature */,
|
|
15638
|
-
message: this.chargy.
|
|
15698
|
+
message: this.chargy.GetMultilanguageText("InvalidSignature"),
|
|
15639
15699
|
certainty: 0
|
|
15640
15700
|
};
|
|
15641
15701
|
}
|
|
@@ -15654,6 +15714,8 @@ var ChargePointCrypt01 = class extends ACrypt {
|
|
|
15654
15714
|
case "InvalidSignature" /* InvalidSignature */:
|
|
15655
15715
|
currentResult.status = "InvalidStartValue" /* InvalidStartValue */;
|
|
15656
15716
|
break;
|
|
15717
|
+
default:
|
|
15718
|
+
break;
|
|
15657
15719
|
}
|
|
15658
15720
|
} else if (i == measurement.values.length - 1) {
|
|
15659
15721
|
switch (currentResult.status) {
|
|
@@ -15666,6 +15728,8 @@ var ChargePointCrypt01 = class extends ACrypt {
|
|
|
15666
15728
|
case "InvalidSignature" /* InvalidSignature */:
|
|
15667
15729
|
currentResult.status = "InvalidStopValue" /* InvalidStopValue */;
|
|
15668
15730
|
break;
|
|
15731
|
+
default:
|
|
15732
|
+
break;
|
|
15669
15733
|
}
|
|
15670
15734
|
} else {
|
|
15671
15735
|
switch (currentResult.status) {
|
|
@@ -15678,6 +15742,8 @@ var ChargePointCrypt01 = class extends ACrypt {
|
|
|
15678
15742
|
case "InvalidSignature" /* InvalidSignature */:
|
|
15679
15743
|
currentResult.status = "InvalidStopValue" /* InvalidStopValue */;
|
|
15680
15744
|
break;
|
|
15745
|
+
default:
|
|
15746
|
+
break;
|
|
15681
15747
|
}
|
|
15682
15748
|
}
|
|
15683
15749
|
}
|
|
@@ -15692,7 +15758,7 @@ var ChargePointCrypt01 = class extends ACrypt {
|
|
|
15692
15758
|
} catch (exception) {
|
|
15693
15759
|
return {
|
|
15694
15760
|
status: "InvalidSignature" /* InvalidSignature */,
|
|
15695
|
-
message: "Exception occured: " + (exception instanceof Error ? exception.message : String(exception)),
|
|
15761
|
+
message: this.chargy.GetMultilanguageText("Exception occured: " + (exception instanceof Error ? exception.message : String(exception))),
|
|
15696
15762
|
certainty: 0
|
|
15697
15763
|
};
|
|
15698
15764
|
}
|
|
@@ -15707,9 +15773,9 @@ var ChargePointCrypt01 = class extends ACrypt {
|
|
|
15707
15773
|
const cryptoResult = {
|
|
15708
15774
|
status: "NoOperation" /* NoOperation */
|
|
15709
15775
|
};
|
|
15710
|
-
return
|
|
15776
|
+
return Promise.resolve(setResult("NoOperation" /* NoOperation */));
|
|
15711
15777
|
}
|
|
15712
|
-
async ViewMeasurement(measurementValue,
|
|
15778
|
+
async ViewMeasurement(measurementValue, _errorDiv, introDiv, _infoDiv, PlainTextDiv, HashedPlainTextDiv, PublicKeyDiv, SignatureExpectedDiv, SignatureCheckDiv) {
|
|
15713
15779
|
if (measurementValue.measurement?.chargingSession === void 0)
|
|
15714
15780
|
return new Error("Invalid measurement!");
|
|
15715
15781
|
const chargingSession = measurementValue.measurement.chargingSession;
|
|
@@ -15717,8 +15783,8 @@ var ChargePointCrypt01 = class extends ACrypt {
|
|
|
15717
15783
|
const algorithmName = typeof chargingSession.publicKey?.algorithm === "object" ? chargingSession.publicKey.algorithm.name : chargingSession.publicKey?.algorithm ?? "";
|
|
15718
15784
|
const algorithmType = typeof chargingSession.publicKey?.type === "object" ? chargingSession.publicKey.type.name : chargingSession.publicKey?.type;
|
|
15719
15785
|
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);
|
|
15720
|
-
if (PlainTextDiv.parentElement
|
|
15721
|
-
PlainTextDiv.parentElement.children
|
|
15786
|
+
if (PlainTextDiv.parentElement) {
|
|
15787
|
+
getArrayLikeElement(PlainTextDiv.parentElement.children, 0, "Missing plain text header").innerHTML = "Plain text (secrrct)";
|
|
15722
15788
|
}
|
|
15723
15789
|
PlainTextDiv.innerText = atob(chargingSession.original ?? "");
|
|
15724
15790
|
PlainTextDiv.style.fontFamily = "monospace";
|
|
@@ -15740,22 +15806,23 @@ var ChargePointCrypt01 = class extends ACrypt {
|
|
|
15740
15806
|
hashInfo = "(SHA512, 512 Bits, hex)";
|
|
15741
15807
|
break;
|
|
15742
15808
|
}
|
|
15743
|
-
if (HashedPlainTextDiv.parentElement
|
|
15744
|
-
HashedPlainTextDiv.parentElement.children
|
|
15809
|
+
if (HashedPlainTextDiv.parentElement) {
|
|
15810
|
+
getArrayLikeElement(HashedPlainTextDiv.parentElement.children, 0, "Missing hashed plain text header").innerHTML = "Hashed plain text " + hashInfo;
|
|
15745
15811
|
}
|
|
15746
15812
|
HashedPlainTextDiv.innerHTML = chargingSession.hashValue?.match(/.{1,8}/g)?.join(" ") ?? "0x00000000000000000000000000000000000";
|
|
15747
15813
|
if (chargingSession.publicKey != null) {
|
|
15748
|
-
if (PublicKeyDiv.parentElement
|
|
15749
|
-
PublicKeyDiv.parentElement.children
|
|
15814
|
+
if (PublicKeyDiv.parentElement) {
|
|
15815
|
+
getArrayLikeElement(PublicKeyDiv.parentElement.children, 0, "Missing public key header").innerHTML = "Public Key (" + (algorithmType != null && algorithmType.length > 0 ? algorithmType + ", " : "") + (algorithmName.length > 0 ? algorithmName + ", " : "") + "hex)";
|
|
15750
15816
|
}
|
|
15751
15817
|
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(" ") ?? "";
|
|
15752
|
-
|
|
15753
|
-
|
|
15818
|
+
const publicKeySignatureContainer = PublicKeyDiv.parentElement?.children[3];
|
|
15819
|
+
if (publicKeySignatureContainer !== void 0) {
|
|
15820
|
+
publicKeySignatureContainer.innerHTML = "";
|
|
15754
15821
|
}
|
|
15755
15822
|
if (result.publicKeySignatures) {
|
|
15756
15823
|
for (const signature of result.publicKeySignatures) {
|
|
15757
15824
|
try {
|
|
15758
|
-
const signatureDiv =
|
|
15825
|
+
const signatureDiv = publicKeySignatureContainer?.appendChild(document.createElement("div"));
|
|
15759
15826
|
if (signatureDiv != null)
|
|
15760
15827
|
signatureDiv.innerHTML = await this.chargy.CheckMeterPublicKeySignature(
|
|
15761
15828
|
measurementValue.measurement.chargingSession.chargingStation,
|
|
@@ -15770,8 +15837,8 @@ var ChargePointCrypt01 = class extends ACrypt {
|
|
|
15770
15837
|
}
|
|
15771
15838
|
}
|
|
15772
15839
|
if (chargingSession.signature != null) {
|
|
15773
|
-
if (SignatureExpectedDiv.parentElement
|
|
15774
|
-
SignatureExpectedDiv.parentElement.children
|
|
15840
|
+
if (SignatureExpectedDiv.parentElement) {
|
|
15841
|
+
getArrayLikeElement(SignatureExpectedDiv.parentElement.children, 0, "Missing expected signature header").innerHTML = "Erwartete Signatur (secrrct.sign, rs, hex)";
|
|
15775
15842
|
}
|
|
15776
15843
|
if (typeof chargingSession.signature != "string")
|
|
15777
15844
|
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(" ") ?? "");
|
|
@@ -15803,6 +15870,7 @@ var ChargePointCrypt01 = class extends ACrypt {
|
|
|
15803
15870
|
break;
|
|
15804
15871
|
}
|
|
15805
15872
|
}
|
|
15873
|
+
return void 0;
|
|
15806
15874
|
}
|
|
15807
15875
|
};
|
|
15808
15876
|
|
|
@@ -15823,8 +15891,7 @@ function IsAChargeTransparencyRecord(data) {
|
|
|
15823
15891
|
function IsASessionCryptoResult(data) {
|
|
15824
15892
|
if (!isMandatoryJSONObject(data))
|
|
15825
15893
|
return false;
|
|
15826
|
-
|
|
15827
|
-
return sessionCryptoResult.status !== void 0;
|
|
15894
|
+
return true;
|
|
15828
15895
|
}
|
|
15829
15896
|
function CloneCTR(CTR) {
|
|
15830
15897
|
const clonedCTR = JSON.parse(JSON.stringify(CTR));
|
|
@@ -16000,8 +16067,10 @@ async function imageDataFromNodeCanvas(data) {
|
|
|
16000
16067
|
if (!isCanvasModule(canvasLib))
|
|
16001
16068
|
return void 0;
|
|
16002
16069
|
const image = await canvasLib.loadImage(Buffer$1.from(toUint8Array(data)));
|
|
16003
|
-
const
|
|
16004
|
-
const
|
|
16070
|
+
const naturalWidth = image.naturalWidth ?? 0;
|
|
16071
|
+
const naturalHeight = image.naturalHeight ?? 0;
|
|
16072
|
+
const width = naturalWidth > 0 ? naturalWidth : image.width;
|
|
16073
|
+
const height = naturalHeight > 0 ? naturalHeight : image.height;
|
|
16005
16074
|
if (width <= 0 || height <= 0)
|
|
16006
16075
|
return void 0;
|
|
16007
16076
|
const canvas = canvasLib.createCanvas(width, height);
|
|
@@ -16072,22 +16141,22 @@ async function importOptionalNodeModule(moduleName) {
|
|
|
16072
16141
|
}
|
|
16073
16142
|
async function readQRCodeTextFromImage(data, mimeType) {
|
|
16074
16143
|
const imageDataSources = typeof document === "undefined" ? [
|
|
16075
|
-
() => imageDataFromNodeCanvas(data),
|
|
16076
|
-
() => imageDataFromPNGOrJPEG(data, mimeType),
|
|
16077
|
-
() => imageDataFromBrowserCanvas(data, mimeType),
|
|
16078
|
-
() => imageDataFromBrowserImageElement(data, mimeType)
|
|
16144
|
+
async () => imageDataFromNodeCanvas(data),
|
|
16145
|
+
async () => imageDataFromPNGOrJPEG(data, mimeType),
|
|
16146
|
+
async () => imageDataFromBrowserCanvas(data, mimeType),
|
|
16147
|
+
async () => imageDataFromBrowserImageElement(data, mimeType)
|
|
16079
16148
|
] : [
|
|
16080
|
-
() => imageDataFromBrowserCanvas(data, mimeType),
|
|
16081
|
-
() => imageDataFromBrowserImageElement(data, mimeType),
|
|
16082
|
-
() => imageDataFromNodeCanvas(data),
|
|
16083
|
-
() => imageDataFromPNGOrJPEG(data, mimeType)
|
|
16149
|
+
async () => imageDataFromBrowserCanvas(data, mimeType),
|
|
16150
|
+
async () => imageDataFromBrowserImageElement(data, mimeType),
|
|
16151
|
+
async () => imageDataFromNodeCanvas(data),
|
|
16152
|
+
async () => imageDataFromPNGOrJPEG(data, mimeType)
|
|
16084
16153
|
];
|
|
16085
16154
|
for (const imageDataSource of imageDataSources) {
|
|
16086
16155
|
const imageData = await imageDataSource();
|
|
16087
16156
|
if (imageData == null)
|
|
16088
16157
|
continue;
|
|
16089
16158
|
const qrText = readQRCodeTextFromImageData(imageData);
|
|
16090
|
-
if (qrText && qrText.length > 0)
|
|
16159
|
+
if (qrText != null && qrText.length > 0)
|
|
16091
16160
|
return qrText;
|
|
16092
16161
|
}
|
|
16093
16162
|
return void 0;
|
|
@@ -16100,7 +16169,7 @@ function readQRCodeTextFromImageData(imageData) {
|
|
|
16100
16169
|
{ inversionAttempts: "attemptBoth" }
|
|
16101
16170
|
);
|
|
16102
16171
|
const qrText = qrCode?.data.trim();
|
|
16103
|
-
return qrText && qrText.length > 0 ? qrText : void 0;
|
|
16172
|
+
return qrText != null && qrText.length > 0 ? qrText : void 0;
|
|
16104
16173
|
}
|
|
16105
16174
|
|
|
16106
16175
|
// src/pdfjs/node.ts
|
|
@@ -16121,10 +16190,15 @@ var validationRules_default = {
|
|
|
16121
16190
|
}
|
|
16122
16191
|
}
|
|
16123
16192
|
};
|
|
16193
|
+
function isPdfAttachment(value) {
|
|
16194
|
+
if (!isMandatoryJSONObject(value))
|
|
16195
|
+
return false;
|
|
16196
|
+
return typeof value["filename"] === "string" && (value["content"] instanceof ArrayBuffer || ArrayBuffer.isView(value["content"]));
|
|
16197
|
+
}
|
|
16124
16198
|
var Chargy = class {
|
|
16125
16199
|
//#region Data
|
|
16126
16200
|
i18n;
|
|
16127
|
-
|
|
16201
|
+
uiLanguages;
|
|
16128
16202
|
elliptic;
|
|
16129
16203
|
moment;
|
|
16130
16204
|
asn1;
|
|
@@ -16137,14 +16211,12 @@ var Chargy = class {
|
|
|
16137
16211
|
EVSEs = new Array();
|
|
16138
16212
|
meters = new Array();
|
|
16139
16213
|
chargingSessions = new Array();
|
|
16140
|
-
eMobilityProviders = new Array();
|
|
16141
|
-
mediationServices = new Array();
|
|
16142
16214
|
currentCTR = {};
|
|
16143
16215
|
internalCTR = {};
|
|
16144
16216
|
//#endregion
|
|
16145
|
-
constructor(i18n,
|
|
16217
|
+
constructor(i18n, UILanguages, elliptic, moment2, asn1, base32Decode, ShowPKIDetails, validationRules = validationRules_default) {
|
|
16146
16218
|
this.i18n = i18n;
|
|
16147
|
-
this.
|
|
16219
|
+
this.uiLanguages = this.NormalizeUILanguages(UILanguages);
|
|
16148
16220
|
this.elliptic = elliptic;
|
|
16149
16221
|
this.moment = moment2;
|
|
16150
16222
|
this.asn1 = asn1;
|
|
@@ -16152,11 +16224,41 @@ var Chargy = class {
|
|
|
16152
16224
|
this.showPKIDetails = ShowPKIDetails;
|
|
16153
16225
|
this.validationRules = validationRules;
|
|
16154
16226
|
}
|
|
16155
|
-
|
|
16156
|
-
this.
|
|
16227
|
+
SetUILanguages(UILanguages) {
|
|
16228
|
+
this.uiLanguages = this.NormalizeUILanguages(UILanguages);
|
|
16229
|
+
}
|
|
16230
|
+
NormalizeUILanguages(UILanguages) {
|
|
16231
|
+
const languages = new Array();
|
|
16232
|
+
for (const language of UILanguages) {
|
|
16233
|
+
const normalized = language.trim();
|
|
16234
|
+
if (normalized.length > 0 && !languages.includes(normalized)) {
|
|
16235
|
+
languages.push(normalized);
|
|
16236
|
+
}
|
|
16237
|
+
}
|
|
16238
|
+
return languages.length > 0 ? languages : ["en"];
|
|
16239
|
+
}
|
|
16240
|
+
FindBestMultilanguageText(Text) {
|
|
16241
|
+
for (const language of this.uiLanguages) {
|
|
16242
|
+
const localLanguage = Text[language];
|
|
16243
|
+
if (localLanguage !== void 0)
|
|
16244
|
+
return localLanguage;
|
|
16245
|
+
}
|
|
16246
|
+
const english = Text["en"];
|
|
16247
|
+
if (english !== void 0)
|
|
16248
|
+
return english;
|
|
16249
|
+
return Object.values(Text).find((value) => value !== void 0);
|
|
16250
|
+
}
|
|
16251
|
+
CompleteMultilanguageText(Text, fallbackText) {
|
|
16252
|
+
const result = {
|
|
16253
|
+
...Text ?? {}
|
|
16254
|
+
};
|
|
16255
|
+
const fallback = this.FindBestMultilanguageText(result) ?? fallbackText;
|
|
16256
|
+
for (const language of this.uiLanguages)
|
|
16257
|
+
result[language] ??= fallback;
|
|
16258
|
+
return result;
|
|
16157
16259
|
}
|
|
16158
16260
|
PublicKeyIdFromFileName(fileName) {
|
|
16159
|
-
return (fileName.
|
|
16261
|
+
return (fileName.includes(".") ? fileName.substring(0, fileName.indexOf(".")) : fileName).replace(/[-_]?public[-_]?key/i, "");
|
|
16160
16262
|
}
|
|
16161
16263
|
TryToParseDERPublicKey(keyId, publicKeyBuffer) {
|
|
16162
16264
|
const ASN1_OIDs = this.asn1.define("OIDs", function() {
|
|
@@ -16332,27 +16434,36 @@ var Chargy = class {
|
|
|
16332
16434
|
GetLocalizedMessage(Text) {
|
|
16333
16435
|
const multiLanguage = this.i18n[Text];
|
|
16334
16436
|
if (multiLanguage !== void 0) {
|
|
16335
|
-
const
|
|
16336
|
-
if (
|
|
16337
|
-
return
|
|
16338
|
-
const english = multiLanguage["en"];
|
|
16339
|
-
if (english !== void 0)
|
|
16340
|
-
return english;
|
|
16437
|
+
const localizedMessage = this.FindBestMultilanguageText(multiLanguage);
|
|
16438
|
+
if (localizedMessage !== void 0)
|
|
16439
|
+
return localizedMessage;
|
|
16341
16440
|
}
|
|
16342
16441
|
return Text;
|
|
16343
16442
|
}
|
|
16443
|
+
GetMultilanguageText(Text) {
|
|
16444
|
+
const multiLanguage = this.i18n[Text];
|
|
16445
|
+
return this.CompleteMultilanguageText(multiLanguage, Text);
|
|
16446
|
+
}
|
|
16344
16447
|
GetLocalizedMessageWithParameter(Text, Parameter) {
|
|
16345
16448
|
const multiLanguage = this.i18n[Text];
|
|
16346
16449
|
if (multiLanguage !== void 0) {
|
|
16347
|
-
const
|
|
16348
|
-
if (
|
|
16349
|
-
return
|
|
16350
|
-
const english = multiLanguage["en"];
|
|
16351
|
-
if (english !== void 0)
|
|
16352
|
-
return english.replace("%p", String(Parameter));
|
|
16450
|
+
const localizedMessage = this.FindBestMultilanguageText(multiLanguage);
|
|
16451
|
+
if (localizedMessage !== void 0)
|
|
16452
|
+
return localizedMessage.replace("%p", String(Parameter));
|
|
16353
16453
|
}
|
|
16354
16454
|
return Text.replace("%p", String(Parameter));
|
|
16355
16455
|
}
|
|
16456
|
+
GetMultilanguageTextWithParameter(Text, Parameter) {
|
|
16457
|
+
const multiLanguage = this.i18n[Text];
|
|
16458
|
+
const parameterizedText = {};
|
|
16459
|
+
if (multiLanguage !== void 0) {
|
|
16460
|
+
for (const [language, message] of Object.entries(multiLanguage)) {
|
|
16461
|
+
if (message !== void 0)
|
|
16462
|
+
parameterizedText[language] = message.replace("%p", String(Parameter));
|
|
16463
|
+
}
|
|
16464
|
+
}
|
|
16465
|
+
return this.CompleteMultilanguageText(parameterizedText, Text.replace("%p", String(Parameter)));
|
|
16466
|
+
}
|
|
16356
16467
|
//#endregion
|
|
16357
16468
|
//#region GetDevices...
|
|
16358
16469
|
GetChargingPool = (Id) => {
|
|
@@ -16503,7 +16614,7 @@ var Chargy = class {
|
|
|
16503
16614
|
if (compressedFiles.length == 0)
|
|
16504
16615
|
continue;
|
|
16505
16616
|
archiveFound = true;
|
|
16506
|
-
if (compressedFiles.length == 1
|
|
16617
|
+
if (compressedFiles.length == 1) {
|
|
16507
16618
|
expandedFileInfos.push({
|
|
16508
16619
|
name: FileInfo.name.substring(0, FileInfo.name.lastIndexOf(".")),
|
|
16509
16620
|
data: compressedFiles[0]?.data
|
|
@@ -16540,9 +16651,12 @@ var Chargy = class {
|
|
|
16540
16651
|
}
|
|
16541
16652
|
if (dataFile.length > 0 && signatureFile.length > 0) {
|
|
16542
16653
|
try {
|
|
16543
|
-
|
|
16544
|
-
|
|
16545
|
-
|
|
16654
|
+
const parsedCTRFile = JSON.parse(dataFile);
|
|
16655
|
+
if (!isMandatoryJSONObject(parsedCTRFile))
|
|
16656
|
+
throw new Error("Invalid chargepoint 'secrrct' JSON file!");
|
|
16657
|
+
CTRfile = parsedCTRFile;
|
|
16658
|
+
CTRfile["original"] = btoa(dataFile);
|
|
16659
|
+
CTRfile["signature"] = signatureFile;
|
|
16546
16660
|
expandedFileInfos.push({
|
|
16547
16661
|
name: FileInfo.name,
|
|
16548
16662
|
data: new TextEncoder().encode(JSON.stringify(CTRfile))
|
|
@@ -16585,7 +16699,7 @@ var Chargy = class {
|
|
|
16585
16699
|
async extractArchive(fileName, data, mimeType) {
|
|
16586
16700
|
const archiveData = this.toUint8Array(data);
|
|
16587
16701
|
if (mimeType === "application/zip")
|
|
16588
|
-
return
|
|
16702
|
+
return this.extractZipArchive(archiveData);
|
|
16589
16703
|
if (mimeType === "application/x-tar")
|
|
16590
16704
|
return this.extractTarArchive(archiveData);
|
|
16591
16705
|
if (mimeType === "application/gzip") {
|
|
@@ -16624,7 +16738,7 @@ var Chargy = class {
|
|
|
16624
16738
|
break;
|
|
16625
16739
|
const prefix = this.readTarString(header, 345, 155);
|
|
16626
16740
|
const path = prefix.length > 0 ? prefix + "/" + name : name;
|
|
16627
|
-
const typeFlag = String.fromCharCode(header
|
|
16741
|
+
const typeFlag = String.fromCharCode(getArrayElement(header, 156, "Missing tar header type flag"));
|
|
16628
16742
|
const dataStart = offset + 512;
|
|
16629
16743
|
const dataEnd = dataStart + size;
|
|
16630
16744
|
if (dataEnd > data.byteLength)
|
|
@@ -16724,7 +16838,7 @@ var Chargy = class {
|
|
|
16724
16838
|
async DetectAndConvertContentFormat(FileInfos) {
|
|
16725
16839
|
if (FileInfos.length == 0) return {
|
|
16726
16840
|
status: "NoChargeTransparencyRecordsFound" /* NoChargeTransparencyRecordsFound */,
|
|
16727
|
-
message: this.
|
|
16841
|
+
message: this.GetMultilanguageText("No charge transparency records found!"),
|
|
16728
16842
|
certainty: 0
|
|
16729
16843
|
};
|
|
16730
16844
|
let expandedFiles = new Array();
|
|
@@ -16733,45 +16847,48 @@ var Chargy = class {
|
|
|
16733
16847
|
for (const fileInfo of FileInfos) {
|
|
16734
16848
|
if (fileInfo.type === "application/pdf" || fileInfo.name.endsWith(".pdf")) {
|
|
16735
16849
|
const pdfjsLib = await importPdfJs();
|
|
16736
|
-
const pdfDocument = fileInfo.data ? await pdfjsLib.getDocument({ data: fileInfo.data }).promise : fileInfo.path ? await pdfjsLib.getDocument({ url: fileInfo.path }).promise : null;
|
|
16737
|
-
if (pdfDocument) {
|
|
16850
|
+
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;
|
|
16851
|
+
if (pdfDocument !== null) {
|
|
16738
16852
|
try {
|
|
16739
|
-
const
|
|
16740
|
-
|
|
16741
|
-
|
|
16742
|
-
|
|
16743
|
-
|
|
16744
|
-
|
|
16745
|
-
|
|
16746
|
-
|
|
16747
|
-
|
|
16748
|
-
|
|
16749
|
-
|
|
16750
|
-
|
|
16751
|
-
|
|
16752
|
-
|
|
16753
|
-
|
|
16754
|
-
|
|
16755
|
-
|
|
16756
|
-
|
|
16757
|
-
|
|
16758
|
-
|
|
16759
|
-
|
|
16760
|
-
|
|
16761
|
-
|
|
16762
|
-
|
|
16763
|
-
|
|
16764
|
-
|
|
16765
|
-
|
|
16766
|
-
|
|
16767
|
-
|
|
16768
|
-
|
|
16769
|
-
|
|
16770
|
-
|
|
16771
|
-
|
|
16772
|
-
|
|
16773
|
-
|
|
16774
|
-
|
|
16853
|
+
const attachmentsUnknown = await pdfDocument.getAttachments();
|
|
16854
|
+
if (isMandatoryJSONObject(attachmentsUnknown))
|
|
16855
|
+
Object.values(attachmentsUnknown).forEach((attachmentUnknown) => {
|
|
16856
|
+
if (!isPdfAttachment(attachmentUnknown))
|
|
16857
|
+
return;
|
|
16858
|
+
const attachment = attachmentUnknown;
|
|
16859
|
+
if (attachment.filename.endsWith(".chargy"))
|
|
16860
|
+
expandedFiles.push({
|
|
16861
|
+
name: attachment.filename,
|
|
16862
|
+
path: FileInfos[0]?.path,
|
|
16863
|
+
type: "application/chargy",
|
|
16864
|
+
data: attachment.content,
|
|
16865
|
+
info: "A CHARGY file extracted from a PDF/A-3 or newer attachment"
|
|
16866
|
+
});
|
|
16867
|
+
else if (attachment.filename.endsWith(".xml"))
|
|
16868
|
+
expandedFiles.push({
|
|
16869
|
+
name: attachment.filename,
|
|
16870
|
+
path: FileInfos[0]?.path,
|
|
16871
|
+
type: "application/xml",
|
|
16872
|
+
data: attachment.content,
|
|
16873
|
+
info: "A XML file extracted from a PDF/A-3 or newer attachment"
|
|
16874
|
+
});
|
|
16875
|
+
else if (attachment.filename.endsWith(".json"))
|
|
16876
|
+
expandedFiles.push({
|
|
16877
|
+
name: attachment.filename,
|
|
16878
|
+
path: FileInfos[0]?.path,
|
|
16879
|
+
type: "application/json",
|
|
16880
|
+
data: attachment.content,
|
|
16881
|
+
info: "A JSON file extracted from a PDF/A-3 or newer attachment"
|
|
16882
|
+
});
|
|
16883
|
+
else if (attachment.filename.endsWith(".csv"))
|
|
16884
|
+
expandedFiles.push({
|
|
16885
|
+
name: attachment.filename,
|
|
16886
|
+
path: FileInfos[0]?.path,
|
|
16887
|
+
type: "text/csv",
|
|
16888
|
+
data: attachment.content,
|
|
16889
|
+
info: "A CSV file extracted from a PDF/A-3 or newer attachment"
|
|
16890
|
+
});
|
|
16891
|
+
});
|
|
16775
16892
|
} catch (error) {
|
|
16776
16893
|
console.error(`Error extracting PDF/A-3 attachments: ${String(error)}`);
|
|
16777
16894
|
}
|
|
@@ -16817,7 +16934,7 @@ var Chargy = class {
|
|
|
16817
16934
|
break;
|
|
16818
16935
|
}
|
|
16819
16936
|
processedFile.result = await new SAFEXML(this).tryToParseSAFEXML(XMLDocument);
|
|
16820
|
-
if (processedFile.result.status && processedFile.result.status !== "Unvalidated" /* Unvalidated */ && getElementsByLocalName(XMLDocument, "chargingStation").length === 0) {
|
|
16937
|
+
if (processedFile.result.status != null && processedFile.result.status !== "Unvalidated" /* Unvalidated */ && getElementsByLocalName(XMLDocument, "chargingStation").length === 0) {
|
|
16821
16938
|
processedFile.result = new XMLContainer(this).tryToParseXMLContainer(XMLDocument);
|
|
16822
16939
|
}
|
|
16823
16940
|
break;
|
|
@@ -16834,7 +16951,7 @@ var Chargy = class {
|
|
|
16834
16951
|
} catch (exception) {
|
|
16835
16952
|
processedFile.result = {
|
|
16836
16953
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
16837
|
-
message: this.
|
|
16954
|
+
message: this.GetMultilanguageText("UnknownOrInvalidXMLChargeTransparencyFormat"),
|
|
16838
16955
|
exception,
|
|
16839
16956
|
certainty: 0
|
|
16840
16957
|
};
|
|
@@ -16874,7 +16991,7 @@ var Chargy = class {
|
|
|
16874
16991
|
} catch (exception) {
|
|
16875
16992
|
processedFile.result = {
|
|
16876
16993
|
status: "InvalidPublicKey" /* InvalidPublicKey */,
|
|
16877
|
-
message: this.
|
|
16994
|
+
message: this.GetMultilanguageText("UnknownOrInvalidPublicKeyFormat"),
|
|
16878
16995
|
exception,
|
|
16879
16996
|
certainty: 0
|
|
16880
16997
|
};
|
|
@@ -16888,7 +17005,7 @@ var Chargy = class {
|
|
|
16888
17005
|
} catch (exception) {
|
|
16889
17006
|
processedFile.result = {
|
|
16890
17007
|
status: "InvalidPublicKey" /* InvalidPublicKey */,
|
|
16891
|
-
message: this.
|
|
17008
|
+
message: this.GetMultilanguageText("UnknownOrInvalidPublicKeyFormat"),
|
|
16892
17009
|
exception,
|
|
16893
17010
|
certainty: 0
|
|
16894
17011
|
};
|
|
@@ -16901,8 +17018,7 @@ var Chargy = class {
|
|
|
16901
17018
|
if (isMandatoryJSONObject(JSONContent)) {
|
|
16902
17019
|
const JSONContext = JSONContent["@context"];
|
|
16903
17020
|
if (IsAChargeTransparencyLiveLink(JSONContent)) {
|
|
16904
|
-
|
|
16905
|
-
JSONContent.timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
17021
|
+
JSONContent.timestamp ??= (/* @__PURE__ */ new Date()).toISOString();
|
|
16906
17022
|
processedFile.result = JSONContent;
|
|
16907
17023
|
} else if (isMandatoryString(JSONContext)) {
|
|
16908
17024
|
if (JSONContext.startsWith("https://open.charging.cloud/contexts/CTR+json"))
|
|
@@ -16937,7 +17053,7 @@ var Chargy = class {
|
|
|
16937
17053
|
} catch (exception) {
|
|
16938
17054
|
processedFile.result = {
|
|
16939
17055
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
16940
|
-
message: this.
|
|
17056
|
+
message: this.GetMultilanguageText("UnknownOrInvalidJSONChargeTransparencyFormat"),
|
|
16941
17057
|
exception,
|
|
16942
17058
|
certainty: 0
|
|
16943
17059
|
};
|
|
@@ -16946,25 +17062,18 @@ var Chargy = class {
|
|
|
16946
17062
|
processedFiles.push(processedFile);
|
|
16947
17063
|
}
|
|
16948
17064
|
if (processedFiles.length == 1) {
|
|
16949
|
-
const processedFile = processedFiles
|
|
16950
|
-
if (processedFile)
|
|
16951
|
-
|
|
16952
|
-
|
|
16953
|
-
if (IsAChargeTransparencyLiveLink(processedFile.result))
|
|
16954
|
-
return processedFile.result;
|
|
16955
|
-
if (IsAPublicKeyLookup(processedFile.result))
|
|
16956
|
-
return {
|
|
16957
|
-
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
16958
|
-
message: this.GetLocalizedMessage("UnknownOrInvalidChargeTransparencyRecord"),
|
|
16959
|
-
certainty: 0
|
|
16960
|
-
};
|
|
17065
|
+
const processedFile = getFirstArrayElement(processedFiles, "Missing processed file");
|
|
17066
|
+
if (IsAChargeTransparencyRecord(processedFile.result))
|
|
17067
|
+
return this.processChargeTransparencyRecord(processedFile.result);
|
|
17068
|
+
if (IsAChargeTransparencyLiveLink(processedFile.result))
|
|
16961
17069
|
return processedFile.result;
|
|
16962
|
-
|
|
16963
|
-
|
|
16964
|
-
|
|
16965
|
-
|
|
16966
|
-
|
|
16967
|
-
|
|
17070
|
+
if (IsAPublicKeyLookup(processedFile.result))
|
|
17071
|
+
return {
|
|
17072
|
+
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
17073
|
+
message: this.GetMultilanguageText("UnknownOrInvalidChargeTransparencyRecord"),
|
|
17074
|
+
certainty: 0
|
|
17075
|
+
};
|
|
17076
|
+
return processedFile.result;
|
|
16968
17077
|
} else if (processedFiles.length > 1) {
|
|
16969
17078
|
const mergedCTR = {
|
|
16970
17079
|
"@id": "",
|
|
@@ -16978,14 +17087,12 @@ var Chargy = class {
|
|
|
16978
17087
|
mergedCTR["@id"] = processedFileResult["@id"];
|
|
16979
17088
|
if (mergedCTR["@context"] === "")
|
|
16980
17089
|
mergedCTR["@context"] = processedFileResult["@context"];
|
|
16981
|
-
if (
|
|
17090
|
+
if (processedFileResult.begin != null && processedFileResult.begin.length > 0 && (mergedCTR.begin == null || mergedCTR.begin.length === 0 || mergedCTR.begin > processedFileResult.begin))
|
|
16982
17091
|
mergedCTR.begin = processedFileResult.begin;
|
|
16983
|
-
if (
|
|
17092
|
+
if (processedFileResult.end != null && processedFileResult.end.length > 0 && (mergedCTR.end == null || mergedCTR.end.length === 0 || mergedCTR.end < processedFileResult.end))
|
|
16984
17093
|
mergedCTR.end = processedFileResult.end;
|
|
16985
|
-
|
|
16986
|
-
|
|
16987
|
-
if (!mergedCTR.contract)
|
|
16988
|
-
mergedCTR.contract = processedFileResult.contract;
|
|
17094
|
+
mergedCTR.description ??= processedFileResult.description;
|
|
17095
|
+
mergedCTR.contract ??= processedFileResult.contract;
|
|
16989
17096
|
if (!mergedCTR.chargingStationOperators)
|
|
16990
17097
|
mergedCTR.chargingStationOperators = processedFileResult.chargingStationOperators;
|
|
16991
17098
|
else if (processedFileResult.chargingStationOperators)
|
|
@@ -17017,17 +17124,14 @@ var Chargy = class {
|
|
|
17017
17124
|
for (const mediationService of processedFileResult.mediationServices)
|
|
17018
17125
|
mergedCTR.mediationServices.push(mediationService);
|
|
17019
17126
|
} else if (IsAPublicKeyInfo(processedFileResult)) {
|
|
17020
|
-
|
|
17021
|
-
mergedCTR.publicKeys = new Array();
|
|
17127
|
+
mergedCTR.publicKeys ??= new Array();
|
|
17022
17128
|
mergedCTR.publicKeys.push(processedFileResult);
|
|
17023
17129
|
} else if (IsAPublicKeyLookup(processedFileResult)) {
|
|
17024
|
-
|
|
17025
|
-
mergedCTR.publicKeys = new Array();
|
|
17130
|
+
mergedCTR.publicKeys ??= new Array();
|
|
17026
17131
|
for (const publicKey of processedFileResult.publicKeys)
|
|
17027
17132
|
mergedCTR.publicKeys.push(publicKey);
|
|
17028
17133
|
} else {
|
|
17029
|
-
|
|
17030
|
-
mergedCTR.invalidDataSets = new Array();
|
|
17134
|
+
mergedCTR.invalidDataSets ??= new Array();
|
|
17031
17135
|
mergedCTR.invalidDataSets.push(processedFile);
|
|
17032
17136
|
}
|
|
17033
17137
|
}
|
|
@@ -17036,7 +17140,7 @@ var Chargy = class {
|
|
|
17036
17140
|
}
|
|
17037
17141
|
return {
|
|
17038
17142
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
17039
|
-
message: this.
|
|
17143
|
+
message: this.GetMultilanguageText("No charge transparency records found!"),
|
|
17040
17144
|
certainty: 0
|
|
17041
17145
|
};
|
|
17042
17146
|
}
|
|
@@ -17046,7 +17150,7 @@ var Chargy = class {
|
|
|
17046
17150
|
if (!IsAChargeTransparencyRecord(CTR))
|
|
17047
17151
|
return {
|
|
17048
17152
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
17049
|
-
message: this.
|
|
17153
|
+
message: this.GetMultilanguageText("UnknownOrInvalidJSONChargeTransparencyFormat"),
|
|
17050
17154
|
certainty: 0
|
|
17051
17155
|
};
|
|
17052
17156
|
this.chargingStationOperators = [];
|
|
@@ -17055,8 +17159,6 @@ var Chargy = class {
|
|
|
17055
17159
|
this.EVSEs = [];
|
|
17056
17160
|
this.meters = [];
|
|
17057
17161
|
this.chargingSessions = [];
|
|
17058
|
-
this.eMobilityProviders = [];
|
|
17059
|
-
this.mediationServices = [];
|
|
17060
17162
|
try {
|
|
17061
17163
|
this.internalCTR = CloneCTR(CTR);
|
|
17062
17164
|
this.currentCTR = CTR;
|
|
@@ -17171,7 +17273,7 @@ var Chargy = class {
|
|
|
17171
17273
|
} catch (exception) {
|
|
17172
17274
|
return {
|
|
17173
17275
|
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
17174
|
-
message: "Exception occured: " + (exception instanceof Error ? exception.message : String(exception)),
|
|
17276
|
+
message: this.GetMultilanguageText("Exception occured: " + (exception instanceof Error ? exception.message : String(exception))),
|
|
17175
17277
|
certainty: 0
|
|
17176
17278
|
};
|
|
17177
17279
|
}
|
|
@@ -17183,9 +17285,9 @@ var Chargy = class {
|
|
|
17183
17285
|
if (measurement.name !== "ENERGY_TOTAL" || measurement.values.length < 2) {
|
|
17184
17286
|
continue;
|
|
17185
17287
|
}
|
|
17186
|
-
const firstValue2 = measurement.values
|
|
17187
|
-
const lastValue = measurement.values
|
|
17188
|
-
if (firstValue2
|
|
17288
|
+
const firstValue2 = measurement.values.at(0);
|
|
17289
|
+
const lastValue = measurement.values.at(-1);
|
|
17290
|
+
if (firstValue2 === void 0 || lastValue === void 0) {
|
|
17189
17291
|
continue;
|
|
17190
17292
|
}
|
|
17191
17293
|
const firstValueKWh = this.measurementValueInKWh(measurement, firstValue2);
|
|
@@ -17302,7 +17404,7 @@ var Chargy = class {
|
|
|
17302
17404
|
default:
|
|
17303
17405
|
verificationResult2 = {
|
|
17304
17406
|
status: "UnknownSessionFormat" /* UnknownSessionFormat */,
|
|
17305
|
-
message: this.
|
|
17407
|
+
message: this.GetMultilanguageText("UnknownOrInvalidChargingSessionFormat"),
|
|
17306
17408
|
certainty: 0
|
|
17307
17409
|
};
|
|
17308
17410
|
break;
|
|
@@ -17312,7 +17414,7 @@ var Chargy = class {
|
|
|
17312
17414
|
chargingSession.ctr,
|
|
17313
17415
|
{
|
|
17314
17416
|
level: this.getChargingSessionTotalEnergyWarningLevel(),
|
|
17315
|
-
message: this.
|
|
17417
|
+
message: this.GetMultilanguageText("InplausibleTotalEnergyMeasurementWarning")
|
|
17316
17418
|
}
|
|
17317
17419
|
);
|
|
17318
17420
|
return {
|
|
@@ -17334,14 +17436,12 @@ var Chargy = class {
|
|
|
17334
17436
|
mergedCTR["@id"] = ctr["@id"];
|
|
17335
17437
|
if (mergedCTR["@context"] === "")
|
|
17336
17438
|
mergedCTR["@context"] = ctr["@context"];
|
|
17337
|
-
if (
|
|
17439
|
+
if (ctr.begin != null && ctr.begin.length > 0 && (mergedCTR.begin == null || mergedCTR.begin.length === 0 || mergedCTR.begin > ctr.begin))
|
|
17338
17440
|
mergedCTR.begin = ctr.begin;
|
|
17339
|
-
if (
|
|
17441
|
+
if (ctr.end != null && ctr.end.length > 0 && (mergedCTR.end == null || mergedCTR.end.length === 0 || mergedCTR.end < ctr.end))
|
|
17340
17442
|
mergedCTR.end = ctr.end;
|
|
17341
|
-
|
|
17342
|
-
|
|
17343
|
-
if (!mergedCTR.contract)
|
|
17344
|
-
mergedCTR.contract = ctr.contract;
|
|
17443
|
+
mergedCTR.description ??= ctr.description;
|
|
17444
|
+
mergedCTR.contract ??= ctr.contract;
|
|
17345
17445
|
if (!mergedCTR.chargingStationOperators)
|
|
17346
17446
|
mergedCTR.chargingStationOperators = ctr.chargingStationOperators;
|
|
17347
17447
|
else if (ctr.chargingStationOperators)
|
|
@@ -17378,7 +17478,7 @@ var Chargy = class {
|
|
|
17378
17478
|
};
|
|
17379
17479
|
|
|
17380
17480
|
// src/verificationResults.ts
|
|
17381
|
-
function toSessionVerificationResults(CTR, noRecordsMessage = "No charge transparency records found!") {
|
|
17481
|
+
function toSessionVerificationResults(CTR, noRecordsMessage = { "en": "No charge transparency records found!" }) {
|
|
17382
17482
|
const verificationResults = (CTR.chargingSessions ?? []).map((session) => session.verificationResult).filter(isISessionCryptoResult1);
|
|
17383
17483
|
if (verificationResults.length > 0)
|
|
17384
17484
|
return verificationResults;
|
|
@@ -17389,6 +17489,6 @@ function toSessionVerificationResults(CTR, noRecordsMessage = "No charge transpa
|
|
|
17389
17489
|
};
|
|
17390
17490
|
}
|
|
17391
17491
|
|
|
17392
|
-
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 };
|
|
17492
|
+
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 };
|
|
17393
17493
|
//# sourceMappingURL=index.js.map
|
|
17394
17494
|
//# sourceMappingURL=index.js.map
|