@open-charging-cloud/chargy-core 0.6.3 → 0.7.0
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 +1 -1
- package/dist/ACrypt.d.ts +2 -2
- package/dist/ACrypt.d.ts.map +1 -1
- package/dist/Alfen.d.ts +3 -3
- package/dist/Alfen.d.ts.map +1 -1
- package/dist/BSMCrypt01.d.ts +1 -1
- package/dist/BSMCrypt01.d.ts.map +1 -1
- package/dist/EMHCrypt01.d.ts +1 -1
- package/dist/EMHCrypt01.d.ts.map +1 -1
- package/dist/GDFCrypt01.d.ts +1 -1
- package/dist/GDFCrypt01.d.ts.map +1 -1
- package/dist/Mennekes.d.ts +0 -3
- package/dist/Mennekes.d.ts.map +1 -1
- package/dist/OCMF.d.ts +8 -7
- package/dist/OCMF.d.ts.map +1 -1
- package/dist/OCPI.d.ts +2 -1
- package/dist/OCPI.d.ts.map +1 -1
- package/dist/PCDF.d.ts +5 -4
- package/dist/PCDF.d.ts.map +1 -1
- package/dist/QIDigital_DCC.d.ts +20 -19
- package/dist/QIDigital_DCC.d.ts.map +1 -1
- package/dist/SAFE_XML.d.ts +1 -26
- package/dist/SAFE_XML.d.ts.map +1 -1
- package/dist/browser/index.js +947 -727
- package/dist/browser/index.js.map +1 -1
- package/dist/chargeIT.d.ts +2 -2
- package/dist/chargeIT.d.ts.map +1 -1
- package/dist/chargePoint.d.ts +1 -1
- package/dist/chargePoint.d.ts.map +1 -1
- package/dist/chargy.d.ts +10 -9
- package/dist/chargy.d.ts.map +1 -1
- package/dist/index.d.ts +3 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/{CryptoUtils.d.ts → interfaces/CryptoUtils.d.ts} +7 -2
- package/dist/interfaces/CryptoUtils.d.ts.map +1 -0
- package/dist/interfaces/IChargeTransparencyLiveLink.d.ts +2 -2
- package/dist/interfaces/IChargeTransparencyLiveLink.d.ts.map +1 -1
- package/dist/interfaces/IChargeTransparencyRecord.d.ts +43 -19
- package/dist/interfaces/IChargeTransparencyRecord.d.ts.map +1 -1
- package/dist/interfaces/IPublicKeyInfo.d.ts +49 -18
- package/dist/interfaces/IPublicKeyInfo.d.ts.map +1 -1
- package/dist/interfaces/chargyInterfaces.d.ts +111 -97
- package/dist/interfaces/chargyInterfaces.d.ts.map +1 -1
- package/dist/{chargyLib.d.ts → interfaces/chargyLib.d.ts} +50 -20
- package/dist/interfaces/chargyLib.d.ts.map +1 -0
- package/dist/interfaces/secp224k1.d.ts.map +1 -0
- package/dist/node/index.js +946 -726
- package/dist/node/index.js.map +1 -1
- package/dist/verificationResults.d.ts +1 -17
- package/dist/verificationResults.d.ts.map +1 -1
- package/i18n.json +30 -0
- package/package.json +1 -1
- package/dist/CanonicalJSON.d.ts +0 -14
- package/dist/CanonicalJSON.d.ts.map +0 -1
- package/dist/CryptoUtils.d.ts.map +0 -1
- package/dist/chargyLib.d.ts.map +0 -1
- package/dist/secp224k1.d.ts.map +0 -1
- /package/dist/{secp224k1.d.ts → interfaces/secp224k1.d.ts} +0 -0
package/dist/browser/index.js
CHANGED
|
@@ -9755,120 +9755,6 @@ var require_buffer2 = __commonJS({
|
|
|
9755
9755
|
}
|
|
9756
9756
|
});
|
|
9757
9757
|
|
|
9758
|
-
// src/secp224k1.ts
|
|
9759
|
-
var secp224k1 = class {
|
|
9760
|
-
// Pcurve = 2**224 - 2**32 - 2**12 - 2**11 - 2**9 - 2**7 - 2**4 - 2**1 - 1 or
|
|
9761
|
-
// FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFE56D
|
|
9762
|
-
Zero = BigInt("0");
|
|
9763
|
-
One = BigInt("1");
|
|
9764
|
-
Two = BigInt("2");
|
|
9765
|
-
Three = BigInt("3");
|
|
9766
|
-
Pcurve = BigInt("26959946667150639794667015087019630673637144422540572481099315275117");
|
|
9767
|
-
// The proven prime
|
|
9768
|
-
N = BigInt("0x010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7");
|
|
9769
|
-
// Number of points in the field
|
|
9770
|
-
Acurve = BigInt(0);
|
|
9771
|
-
// Defined on the elliptic curve. y^2 = x^3 + Acurve * x + 5
|
|
9772
|
-
Gx = BigInt("0xA1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C");
|
|
9773
|
-
Gy = BigInt("0x7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5");
|
|
9774
|
-
GPoint = [this.Gx, this.Gy];
|
|
9775
|
-
// This is our generator point. Trillions of dif ones possible
|
|
9776
|
-
Sign(hash, RandomNumber, privateKey) {
|
|
9777
|
-
const RandSignPoint = this.ECmultiply(this.GPoint, RandomNumber);
|
|
9778
|
-
if (RandSignPoint.length >= 1 && RandSignPoint[0] != null) {
|
|
9779
|
-
const r = this.modulo(RandSignPoint[0], this.N);
|
|
9780
|
-
const s = this.modulo((hash + r * privateKey) * this.modInv(RandomNumber, this.N), this.N);
|
|
9781
|
-
return [r, s];
|
|
9782
|
-
}
|
|
9783
|
-
return null;
|
|
9784
|
-
}
|
|
9785
|
-
validate(hash, signatureR, signatureS, PublicKey) {
|
|
9786
|
-
if (signatureR == this.Zero || signatureR >= this.N)
|
|
9787
|
-
throw new Error("Invalid R");
|
|
9788
|
-
if (signatureS == this.Zero || signatureS >= this.N)
|
|
9789
|
-
throw new Error("Invalid S");
|
|
9790
|
-
const w = this.modInv(signatureS, this.N);
|
|
9791
|
-
const u1 = this.ECmultiply(this.GPoint, this.modulo(w * hash, this.N));
|
|
9792
|
-
const u2 = this.ECmultiply(PublicKey, this.modulo(w * signatureR, this.N));
|
|
9793
|
-
const validation = this.ECadd(u1, u2);
|
|
9794
|
-
return validation[0] == signatureR;
|
|
9795
|
-
}
|
|
9796
|
-
modulo(n, m) {
|
|
9797
|
-
return (n % m + m) % m;
|
|
9798
|
-
}
|
|
9799
|
-
zfill(s) {
|
|
9800
|
-
while (s.length < 56) {
|
|
9801
|
-
s = "0" + s;
|
|
9802
|
-
}
|
|
9803
|
-
return s;
|
|
9804
|
-
}
|
|
9805
|
-
modInv(a, n = this.Pcurve) {
|
|
9806
|
-
let lm = BigInt(1), hm = BigInt(0), high = n, low = this.modulo(a, n);
|
|
9807
|
-
while (low > 1) {
|
|
9808
|
-
const ratio = high / low, nm = hm - ratio * lm, newm = high - ratio * low;
|
|
9809
|
-
hm = lm;
|
|
9810
|
-
lm = nm;
|
|
9811
|
-
high = low;
|
|
9812
|
-
low = newm;
|
|
9813
|
-
}
|
|
9814
|
-
return this.modulo(lm, n);
|
|
9815
|
-
}
|
|
9816
|
-
ECadd(a, b) {
|
|
9817
|
-
if (a[0] != void 0 && b[0] != void 0 && a[1] != void 0 && b[1] != void 0) {
|
|
9818
|
-
const LamAdd = this.modulo((b[1] - a[1]) * this.modInv(b[0] - a[0]), this.Pcurve);
|
|
9819
|
-
const x = this.modulo(LamAdd * LamAdd - a[0] - b[0], this.Pcurve);
|
|
9820
|
-
const y = this.modulo(LamAdd * (a[0] - x) - a[1], this.Pcurve);
|
|
9821
|
-
return [x, y];
|
|
9822
|
-
}
|
|
9823
|
-
throw new Error("Invalid EC Point Addition!");
|
|
9824
|
-
}
|
|
9825
|
-
ECdouble(a) {
|
|
9826
|
-
if (a[0] != void 0 && a[1] != void 0) {
|
|
9827
|
-
const Lam = this.modulo((a[0] * a[0] * this.Three + this.Acurve) * this.modInv(a[1] * this.Two), this.Pcurve);
|
|
9828
|
-
const x = this.modulo(Lam * Lam - a[0] * this.Two, this.Pcurve);
|
|
9829
|
-
const y = this.modulo(Lam * (a[0] - x) - a[1], this.Pcurve);
|
|
9830
|
-
return [x, y];
|
|
9831
|
-
}
|
|
9832
|
-
throw new Error("Invalid EC Point Doubling!");
|
|
9833
|
-
}
|
|
9834
|
-
ECmultiply(GenPoint, ScalarHex) {
|
|
9835
|
-
if (ScalarHex == this.Zero || ScalarHex >= this.N)
|
|
9836
|
-
throw new Error("Invalid Scalar/Private Key");
|
|
9837
|
-
const ScalarBinary = ScalarHex.toString(2);
|
|
9838
|
-
let Q = GenPoint;
|
|
9839
|
-
for (let i = 1; i < ScalarBinary.length; i++) {
|
|
9840
|
-
Q = this.ECdouble(Q);
|
|
9841
|
-
if (ScalarBinary[i] === "1") {
|
|
9842
|
-
Q = this.ECadd(Q, GenPoint);
|
|
9843
|
-
}
|
|
9844
|
-
}
|
|
9845
|
-
return Q;
|
|
9846
|
-
}
|
|
9847
|
-
// uncompressed is the accumulation of both the x and y points
|
|
9848
|
-
// compressed is the public key to share in transactions
|
|
9849
|
-
// address is the public address tho whom someone can send coin
|
|
9850
|
-
PublicKeyGenerate(PrivateKey) {
|
|
9851
|
-
if (typeof PrivateKey === "number")
|
|
9852
|
-
PrivateKey = BigInt(PrivateKey);
|
|
9853
|
-
if (typeof PrivateKey === "string")
|
|
9854
|
-
PrivateKey = BigInt(PrivateKey);
|
|
9855
|
-
const publicKey = this.ECmultiply(this.GPoint, PrivateKey);
|
|
9856
|
-
if (publicKey[0] !== void 0 && publicKey[1] !== void 0) {
|
|
9857
|
-
const Px = this.zfill(publicKey[0].toString(16));
|
|
9858
|
-
const Py = this.zfill(publicKey[1].toString(16));
|
|
9859
|
-
return {
|
|
9860
|
-
x: publicKey[0],
|
|
9861
|
-
y: publicKey[1],
|
|
9862
|
-
xy: [Px, Py],
|
|
9863
|
-
uncompressed: publicKey[0].toString(16) + publicKey[1].toString(16),
|
|
9864
|
-
compressed: "04" + Px + Py,
|
|
9865
|
-
address: this.modulo(publicKey[1], this.Two) == this.One ? "03" + Px : "02" + Px
|
|
9866
|
-
};
|
|
9867
|
-
}
|
|
9868
|
-
return void 0;
|
|
9869
|
-
}
|
|
9870
|
-
};
|
|
9871
|
-
|
|
9872
9758
|
// src/interfaces/chargyInterfaces.ts
|
|
9873
9759
|
var chargyInterfaces_exports = {};
|
|
9874
9760
|
__export(chargyInterfaces_exports, {
|
|
@@ -9881,7 +9767,7 @@ __export(chargyInterfaces_exports, {
|
|
|
9881
9767
|
IECCurves: () => IECCurves,
|
|
9882
9768
|
IEncoding: () => IEncoding,
|
|
9883
9769
|
InformationRelevance: () => InformationRelevance,
|
|
9884
|
-
|
|
9770
|
+
OIDInfo: () => OIDInfo,
|
|
9885
9771
|
SessionVerificationResult: () => SessionVerificationResult,
|
|
9886
9772
|
SignatureFormats: () => SignatureFormats,
|
|
9887
9773
|
VerificationResult: () => VerificationResult,
|
|
@@ -9889,23 +9775,9 @@ __export(chargyInterfaces_exports, {
|
|
|
9889
9775
|
isGeoLocation: () => isGeoLocation,
|
|
9890
9776
|
isICryptoResult: () => isICryptoResult,
|
|
9891
9777
|
isIFileInfo: () => isIFileInfo,
|
|
9892
|
-
isIPublicKeyXY: () => isIPublicKeyXY,
|
|
9893
9778
|
isISessionCryptoResult1: () => isISessionCryptoResult1,
|
|
9894
|
-
isISessionCryptoResult2: () => isISessionCryptoResult2
|
|
9895
|
-
isMultilanguageText: () => isMultilanguageText,
|
|
9896
|
-
isOIDInfo: () => isOIDInfo,
|
|
9897
|
-
isObject: () => isObject,
|
|
9898
|
-
isString: () => isString,
|
|
9899
|
-
isStringArray: () => isStringArray,
|
|
9900
|
-
isStringOrOIDInfo: () => isStringOrOIDInfo,
|
|
9901
|
-
isStringOrStringArray: () => isStringOrStringArray
|
|
9779
|
+
isISessionCryptoResult2: () => isISessionCryptoResult2
|
|
9902
9780
|
});
|
|
9903
|
-
function isObject(data) {
|
|
9904
|
-
return typeof data === "object" && data !== null;
|
|
9905
|
-
}
|
|
9906
|
-
function isMultilanguageText(data) {
|
|
9907
|
-
return isObject(data) && Object.values(data).every((value) => typeof value === "string");
|
|
9908
|
-
}
|
|
9909
9781
|
function isGeoLocation(data) {
|
|
9910
9782
|
if (!isObject(data))
|
|
9911
9783
|
return false;
|
|
@@ -9913,26 +9785,6 @@ function isGeoLocation(data) {
|
|
|
9913
9785
|
const longitude = data["lng"];
|
|
9914
9786
|
return (latitude === void 0 || typeof latitude === "number") && (longitude === void 0 || typeof longitude === "number");
|
|
9915
9787
|
}
|
|
9916
|
-
function isString(value) {
|
|
9917
|
-
return typeof value === "string";
|
|
9918
|
-
}
|
|
9919
|
-
function isStringArray(value) {
|
|
9920
|
-
return Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
9921
|
-
}
|
|
9922
|
-
function isStringOrStringArray(value) {
|
|
9923
|
-
return typeof value === "string" || isStringArray(value);
|
|
9924
|
-
}
|
|
9925
|
-
function isOIDInfo(data) {
|
|
9926
|
-
if (!isObject(data))
|
|
9927
|
-
return false;
|
|
9928
|
-
return typeof data["oid"] === "string" && typeof data["name"] === "string";
|
|
9929
|
-
}
|
|
9930
|
-
function isStringOrOIDInfo(value) {
|
|
9931
|
-
return typeof value === "string" || isOIDInfo(value);
|
|
9932
|
-
}
|
|
9933
|
-
function isIPublicKeyXY(obj) {
|
|
9934
|
-
return typeof obj === "object" && obj !== null && typeof obj.x === "string" && typeof obj.y === "string";
|
|
9935
|
-
}
|
|
9936
9788
|
var IECCurves = /* @__PURE__ */ ((IECCurves2) => {
|
|
9937
9789
|
IECCurves2["secp192r1"] = "secp192r1";
|
|
9938
9790
|
IECCurves2["secp224k1"] = "secp224k1";
|
|
@@ -9947,11 +9799,6 @@ var IEncoding = /* @__PURE__ */ ((IEncoding2) => {
|
|
|
9947
9799
|
IEncoding2["base64"] = "base64";
|
|
9948
9800
|
return IEncoding2;
|
|
9949
9801
|
})(IEncoding || {});
|
|
9950
|
-
var PublicKeyFormats = /* @__PURE__ */ ((PublicKeyFormats2) => {
|
|
9951
|
-
PublicKeyFormats2["DER"] = "DER";
|
|
9952
|
-
PublicKeyFormats2["XY"] = "XY";
|
|
9953
|
-
return PublicKeyFormats2;
|
|
9954
|
-
})(PublicKeyFormats || {});
|
|
9955
9802
|
var SignatureFormats = /* @__PURE__ */ ((SignatureFormats2) => {
|
|
9956
9803
|
SignatureFormats2["DER"] = "DER";
|
|
9957
9804
|
SignatureFormats2["RS"] = "RS";
|
|
@@ -10073,12 +9920,19 @@ var DayOfWeek = /* @__PURE__ */ ((DayOfWeek2) => {
|
|
|
10073
9920
|
DayOfWeek2[DayOfWeek2["Saturday"] = 6] = "Saturday";
|
|
10074
9921
|
return DayOfWeek2;
|
|
10075
9922
|
})(DayOfWeek || {});
|
|
9923
|
+
function OIDInfo(data) {
|
|
9924
|
+
if (typeof data === "string")
|
|
9925
|
+
return data;
|
|
9926
|
+
if (isOIDInfo(data))
|
|
9927
|
+
return data.name;
|
|
9928
|
+
return "";
|
|
9929
|
+
}
|
|
10076
9930
|
function isJSONLDObject(value) {
|
|
10077
9931
|
if (typeof value !== "object" || value === null) {
|
|
10078
9932
|
return false;
|
|
10079
9933
|
}
|
|
10080
9934
|
const obj = value;
|
|
10081
|
-
return typeof obj["@context"] === "string";
|
|
9935
|
+
return typeof obj["@context"] === "string" || Array.isArray(obj["@context"]);
|
|
10082
9936
|
}
|
|
10083
9937
|
function toArrayBuffer(data) {
|
|
10084
9938
|
if (data instanceof ArrayBuffer)
|
|
@@ -10538,36 +10392,6 @@ function pad(text, paddingValue) {
|
|
|
10538
10392
|
text ??= "";
|
|
10539
10393
|
return (text + Array(2 * paddingValue).join("0")).substring(0, 2 * paddingValue);
|
|
10540
10394
|
}
|
|
10541
|
-
async function sha256(message) {
|
|
10542
|
-
let hashBuffer;
|
|
10543
|
-
if (typeof message === "string")
|
|
10544
|
-
hashBuffer = await crypto.subtle.digest("SHA-256", Buffer.from(message, "utf8"));
|
|
10545
|
-
else
|
|
10546
|
-
hashBuffer = await crypto.subtle.digest("SHA-256", message);
|
|
10547
|
-
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
10548
|
-
const hashHex = hashArray.map((b) => ("00" + b.toString(16)).slice(-2)).join("").toLowerCase();
|
|
10549
|
-
return hashHex;
|
|
10550
|
-
}
|
|
10551
|
-
async function sha384(message) {
|
|
10552
|
-
let hashBuffer;
|
|
10553
|
-
if (typeof message === "string")
|
|
10554
|
-
hashBuffer = await crypto.subtle.digest("SHA-384", Buffer.from(message, "utf8"));
|
|
10555
|
-
else
|
|
10556
|
-
hashBuffer = await crypto.subtle.digest("SHA-384", message);
|
|
10557
|
-
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
10558
|
-
const hashHex = hashArray.map((b) => ("00" + b.toString(16)).slice(-2)).join("").toLowerCase();
|
|
10559
|
-
return hashHex;
|
|
10560
|
-
}
|
|
10561
|
-
async function sha512(message) {
|
|
10562
|
-
let hashBuffer;
|
|
10563
|
-
if (typeof message === "string")
|
|
10564
|
-
hashBuffer = await crypto.subtle.digest("SHA-512", Buffer.from(message, "utf8"));
|
|
10565
|
-
else
|
|
10566
|
-
hashBuffer = await crypto.subtle.digest("SHA-512", message);
|
|
10567
|
-
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
10568
|
-
const hashHex = hashArray.map((b) => ("00" + b.toString(16)).slice(-2)).join("").toLowerCase();
|
|
10569
|
-
return hashHex;
|
|
10570
|
-
}
|
|
10571
10395
|
function asJSONObject(value) {
|
|
10572
10396
|
return isMandatoryJSONObject(value) ? value : void 0;
|
|
10573
10397
|
}
|
|
@@ -10664,6 +10488,48 @@ function parseNumber(value) {
|
|
|
10664
10488
|
}
|
|
10665
10489
|
return null;
|
|
10666
10490
|
}
|
|
10491
|
+
function isObject(data) {
|
|
10492
|
+
return typeof data === "object" && data !== null;
|
|
10493
|
+
}
|
|
10494
|
+
function isI18NString(data) {
|
|
10495
|
+
return isObject(data) && Object.values(data).every((value) => typeof value === "string");
|
|
10496
|
+
}
|
|
10497
|
+
function isString(value) {
|
|
10498
|
+
return typeof value === "string";
|
|
10499
|
+
}
|
|
10500
|
+
function isStringArray(value) {
|
|
10501
|
+
return Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
10502
|
+
}
|
|
10503
|
+
function isStringOrStringArray(value) {
|
|
10504
|
+
return typeof value === "string" || isStringArray(value);
|
|
10505
|
+
}
|
|
10506
|
+
function isOIDInfo(data) {
|
|
10507
|
+
if (!isObject(data))
|
|
10508
|
+
return false;
|
|
10509
|
+
return typeof data["oid"] === "string" && typeof data["name"] === "string";
|
|
10510
|
+
}
|
|
10511
|
+
function isStringOrOIDInfo(value) {
|
|
10512
|
+
return typeof value === "string" || isOIDInfo(value);
|
|
10513
|
+
}
|
|
10514
|
+
function isOptionalStringArray(data) {
|
|
10515
|
+
return data === void 0 || Array.isArray(data) && data.every(isString);
|
|
10516
|
+
}
|
|
10517
|
+
function isOptionalStringOrOIDInfo(data) {
|
|
10518
|
+
return data === void 0 || isStringOrOIDInfo(data);
|
|
10519
|
+
}
|
|
10520
|
+
function isEncodedValue(data) {
|
|
10521
|
+
if (isString(data))
|
|
10522
|
+
return true;
|
|
10523
|
+
if (!isMandatoryJSONObject(data))
|
|
10524
|
+
return false;
|
|
10525
|
+
if (!isString(data["value"]))
|
|
10526
|
+
return false;
|
|
10527
|
+
if (!isOptionalString(data["format"]))
|
|
10528
|
+
return false;
|
|
10529
|
+
if (!isOptionalString(data["encoding"]))
|
|
10530
|
+
return false;
|
|
10531
|
+
return true;
|
|
10532
|
+
}
|
|
10667
10533
|
function InformationRelevanceToString(InfoRelevance) {
|
|
10668
10534
|
switch (InfoRelevance) {
|
|
10669
10535
|
case "Ignored" /* Ignored */:
|
|
@@ -10724,6 +10590,187 @@ function _jsonPrettyPrinter(value, indentLevel, path, keyLookup) {
|
|
|
10724
10590
|
html += String(value);
|
|
10725
10591
|
return html;
|
|
10726
10592
|
}
|
|
10593
|
+
function base64ToBytes(value) {
|
|
10594
|
+
if (typeof Buffer !== "undefined")
|
|
10595
|
+
return Uint8Array.from(Buffer.from(value, "base64"));
|
|
10596
|
+
const binary = atob(value);
|
|
10597
|
+
const bytes = new Uint8Array(binary.length);
|
|
10598
|
+
for (let i = 0; i < binary.length; i++)
|
|
10599
|
+
bytes[i] = binary.charCodeAt(i);
|
|
10600
|
+
return bytes;
|
|
10601
|
+
}
|
|
10602
|
+
function bytesToBase64(bytes) {
|
|
10603
|
+
if (typeof Buffer !== "undefined")
|
|
10604
|
+
return Buffer.from(bytes).toString("base64");
|
|
10605
|
+
let binary = "";
|
|
10606
|
+
for (const byte of bytes)
|
|
10607
|
+
binary += String.fromCharCode(byte);
|
|
10608
|
+
return btoa(binary);
|
|
10609
|
+
}
|
|
10610
|
+
function cleanHex(hex) {
|
|
10611
|
+
return hex.replace(/\s+/g, "");
|
|
10612
|
+
}
|
|
10613
|
+
function hexToBytes(hex) {
|
|
10614
|
+
const cleanedHex = cleanHex(hex);
|
|
10615
|
+
if (cleanedHex.length % 2 !== 0)
|
|
10616
|
+
throw new Error("Hex strings must have even length!");
|
|
10617
|
+
if (!/^[0-9a-fA-F]*$/.test(cleanedHex))
|
|
10618
|
+
throw new Error("Invalid hexadecimal string!");
|
|
10619
|
+
const bytes = new Uint8Array(cleanedHex.length / 2);
|
|
10620
|
+
for (let index = 0; index < cleanedHex.length; index += 2)
|
|
10621
|
+
bytes[index / 2] = Number.parseInt(cleanedHex.substring(index, index + 2), 16);
|
|
10622
|
+
return bytes;
|
|
10623
|
+
}
|
|
10624
|
+
function bytesToHex(bytes) {
|
|
10625
|
+
return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
10626
|
+
}
|
|
10627
|
+
async function sha256(message) {
|
|
10628
|
+
return bytesToHex(await sha256____(message));
|
|
10629
|
+
}
|
|
10630
|
+
async function sha384(message) {
|
|
10631
|
+
return bytesToHex(await sha384____(message));
|
|
10632
|
+
}
|
|
10633
|
+
async function sha512(message) {
|
|
10634
|
+
return bytesToHex(await sha512____(message));
|
|
10635
|
+
}
|
|
10636
|
+
async function sha256____(message) {
|
|
10637
|
+
let hashBuffer;
|
|
10638
|
+
if (typeof message === "string")
|
|
10639
|
+
hashBuffer = await crypto.subtle.digest("SHA-256", Buffer.from(message, "utf8"));
|
|
10640
|
+
else
|
|
10641
|
+
hashBuffer = await crypto.subtle.digest("SHA-256", message);
|
|
10642
|
+
return new Uint8Array(hashBuffer);
|
|
10643
|
+
}
|
|
10644
|
+
async function sha384____(message) {
|
|
10645
|
+
let hashBuffer;
|
|
10646
|
+
if (typeof message === "string")
|
|
10647
|
+
hashBuffer = await crypto.subtle.digest("SHA-384", Buffer.from(message, "utf8"));
|
|
10648
|
+
else
|
|
10649
|
+
hashBuffer = await crypto.subtle.digest("SHA-384", message);
|
|
10650
|
+
return new Uint8Array(hashBuffer);
|
|
10651
|
+
}
|
|
10652
|
+
async function sha512____(message) {
|
|
10653
|
+
let hashBuffer;
|
|
10654
|
+
if (typeof message === "string")
|
|
10655
|
+
hashBuffer = await crypto.subtle.digest("SHA-512", Buffer.from(message, "utf8"));
|
|
10656
|
+
else
|
|
10657
|
+
hashBuffer = await crypto.subtle.digest("SHA-512", message);
|
|
10658
|
+
return new Uint8Array(hashBuffer);
|
|
10659
|
+
}
|
|
10660
|
+
|
|
10661
|
+
// src/interfaces/secp224k1.ts
|
|
10662
|
+
var secp224k1 = class {
|
|
10663
|
+
// Pcurve = 2**224 - 2**32 - 2**12 - 2**11 - 2**9 - 2**7 - 2**4 - 2**1 - 1 or
|
|
10664
|
+
// FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFE56D
|
|
10665
|
+
Zero = BigInt("0");
|
|
10666
|
+
One = BigInt("1");
|
|
10667
|
+
Two = BigInt("2");
|
|
10668
|
+
Three = BigInt("3");
|
|
10669
|
+
Pcurve = BigInt("26959946667150639794667015087019630673637144422540572481099315275117");
|
|
10670
|
+
// The proven prime
|
|
10671
|
+
N = BigInt("0x010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7");
|
|
10672
|
+
// Number of points in the field
|
|
10673
|
+
Acurve = BigInt(0);
|
|
10674
|
+
// Defined on the elliptic curve. y^2 = x^3 + Acurve * x + 5
|
|
10675
|
+
Gx = BigInt("0xA1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C");
|
|
10676
|
+
Gy = BigInt("0x7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5");
|
|
10677
|
+
GPoint = [this.Gx, this.Gy];
|
|
10678
|
+
// This is our generator point. Trillions of dif ones possible
|
|
10679
|
+
Sign(hash, RandomNumber, privateKey) {
|
|
10680
|
+
const RandSignPoint = this.ECmultiply(this.GPoint, RandomNumber);
|
|
10681
|
+
if (RandSignPoint.length >= 1 && RandSignPoint[0] != null) {
|
|
10682
|
+
const r = this.modulo(RandSignPoint[0], this.N);
|
|
10683
|
+
const s = this.modulo((hash + r * privateKey) * this.modInv(RandomNumber, this.N), this.N);
|
|
10684
|
+
return [r, s];
|
|
10685
|
+
}
|
|
10686
|
+
return null;
|
|
10687
|
+
}
|
|
10688
|
+
validate(hash, signatureR, signatureS, PublicKey) {
|
|
10689
|
+
if (signatureR == this.Zero || signatureR >= this.N)
|
|
10690
|
+
throw new Error("Invalid R");
|
|
10691
|
+
if (signatureS == this.Zero || signatureS >= this.N)
|
|
10692
|
+
throw new Error("Invalid S");
|
|
10693
|
+
const w = this.modInv(signatureS, this.N);
|
|
10694
|
+
const u1 = this.ECmultiply(this.GPoint, this.modulo(w * hash, this.N));
|
|
10695
|
+
const u2 = this.ECmultiply(PublicKey, this.modulo(w * signatureR, this.N));
|
|
10696
|
+
const validation = this.ECadd(u1, u2);
|
|
10697
|
+
return validation[0] == signatureR;
|
|
10698
|
+
}
|
|
10699
|
+
modulo(n, m) {
|
|
10700
|
+
return (n % m + m) % m;
|
|
10701
|
+
}
|
|
10702
|
+
zfill(s) {
|
|
10703
|
+
while (s.length < 56) {
|
|
10704
|
+
s = "0" + s;
|
|
10705
|
+
}
|
|
10706
|
+
return s;
|
|
10707
|
+
}
|
|
10708
|
+
modInv(a, n = this.Pcurve) {
|
|
10709
|
+
let lm = BigInt(1), hm = BigInt(0), high = n, low = this.modulo(a, n);
|
|
10710
|
+
while (low > 1) {
|
|
10711
|
+
const ratio = high / low, nm = hm - ratio * lm, newm = high - ratio * low;
|
|
10712
|
+
hm = lm;
|
|
10713
|
+
lm = nm;
|
|
10714
|
+
high = low;
|
|
10715
|
+
low = newm;
|
|
10716
|
+
}
|
|
10717
|
+
return this.modulo(lm, n);
|
|
10718
|
+
}
|
|
10719
|
+
ECadd(a, b) {
|
|
10720
|
+
if (a[0] != void 0 && b[0] != void 0 && a[1] != void 0 && b[1] != void 0) {
|
|
10721
|
+
const LamAdd = this.modulo((b[1] - a[1]) * this.modInv(b[0] - a[0]), this.Pcurve);
|
|
10722
|
+
const x = this.modulo(LamAdd * LamAdd - a[0] - b[0], this.Pcurve);
|
|
10723
|
+
const y = this.modulo(LamAdd * (a[0] - x) - a[1], this.Pcurve);
|
|
10724
|
+
return [x, y];
|
|
10725
|
+
}
|
|
10726
|
+
throw new Error("Invalid EC Point Addition!");
|
|
10727
|
+
}
|
|
10728
|
+
ECdouble(a) {
|
|
10729
|
+
if (a[0] != void 0 && a[1] != void 0) {
|
|
10730
|
+
const Lam = this.modulo((a[0] * a[0] * this.Three + this.Acurve) * this.modInv(a[1] * this.Two), this.Pcurve);
|
|
10731
|
+
const x = this.modulo(Lam * Lam - a[0] * this.Two, this.Pcurve);
|
|
10732
|
+
const y = this.modulo(Lam * (a[0] - x) - a[1], this.Pcurve);
|
|
10733
|
+
return [x, y];
|
|
10734
|
+
}
|
|
10735
|
+
throw new Error("Invalid EC Point Doubling!");
|
|
10736
|
+
}
|
|
10737
|
+
ECmultiply(GenPoint, ScalarHex) {
|
|
10738
|
+
if (ScalarHex == this.Zero || ScalarHex >= this.N)
|
|
10739
|
+
throw new Error("Invalid Scalar/Private Key");
|
|
10740
|
+
const ScalarBinary = ScalarHex.toString(2);
|
|
10741
|
+
let Q = GenPoint;
|
|
10742
|
+
for (let i = 1; i < ScalarBinary.length; i++) {
|
|
10743
|
+
Q = this.ECdouble(Q);
|
|
10744
|
+
if (ScalarBinary[i] === "1") {
|
|
10745
|
+
Q = this.ECadd(Q, GenPoint);
|
|
10746
|
+
}
|
|
10747
|
+
}
|
|
10748
|
+
return Q;
|
|
10749
|
+
}
|
|
10750
|
+
// uncompressed is the accumulation of both the x and y points
|
|
10751
|
+
// compressed is the public key to share in transactions
|
|
10752
|
+
// address is the public address tho whom someone can send coin
|
|
10753
|
+
PublicKeyGenerate(PrivateKey) {
|
|
10754
|
+
if (typeof PrivateKey === "number")
|
|
10755
|
+
PrivateKey = BigInt(PrivateKey);
|
|
10756
|
+
if (typeof PrivateKey === "string")
|
|
10757
|
+
PrivateKey = BigInt(PrivateKey);
|
|
10758
|
+
const publicKey = this.ECmultiply(this.GPoint, PrivateKey);
|
|
10759
|
+
if (publicKey[0] !== void 0 && publicKey[1] !== void 0) {
|
|
10760
|
+
const Px = this.zfill(publicKey[0].toString(16));
|
|
10761
|
+
const Py = this.zfill(publicKey[1].toString(16));
|
|
10762
|
+
return {
|
|
10763
|
+
x: publicKey[0],
|
|
10764
|
+
y: publicKey[1],
|
|
10765
|
+
xy: [Px, Py],
|
|
10766
|
+
uncompressed: publicKey[0].toString(16) + publicKey[1].toString(16),
|
|
10767
|
+
compressed: "04" + Px + Py,
|
|
10768
|
+
address: this.modulo(publicKey[1], this.Two) == this.One ? "03" + Px : "02" + Px
|
|
10769
|
+
};
|
|
10770
|
+
}
|
|
10771
|
+
return void 0;
|
|
10772
|
+
}
|
|
10773
|
+
};
|
|
10727
10774
|
|
|
10728
10775
|
// src/ACrypt.ts
|
|
10729
10776
|
var ACrypt = class {
|
|
@@ -10955,8 +11002,8 @@ var Alfen = class {
|
|
|
10955
11002
|
"Signature": this.bufferToHex(Signature)
|
|
10956
11003
|
});
|
|
10957
11004
|
}
|
|
10958
|
-
const evseId =
|
|
10959
|
-
const chargingStationId =
|
|
11005
|
+
const evseId = ContainerInfos.chargingStations?.[0]?.EVSEs?.[0]?.["@id"] ?? "DE*GEF*EVSE*CHARGY*1";
|
|
11006
|
+
const chargingStationId = ContainerInfos.chargingStations?.[0]?.["@id"] ?? "DE*GEF*STATION*CHARGY*1";
|
|
10960
11007
|
const chargingSessionId = asString(chargingSession?.["@id"]);
|
|
10961
11008
|
const firstDataSet = getFirstArrayElement(common.dataSets, "Missing first Alfen data set");
|
|
10962
11009
|
const lastDataSet = getLastArrayElement(common.dataSets, "Missing last Alfen data set");
|
|
@@ -10981,10 +11028,18 @@ var Alfen = class {
|
|
|
10981
11028
|
"@id": chargingStationId,
|
|
10982
11029
|
// ToDo: The container infos are not validated yet!
|
|
10983
11030
|
"description": asJSONObject(chargingStation?.["description"]),
|
|
10984
|
-
"manufacturer":
|
|
10985
|
-
|
|
10986
|
-
|
|
10987
|
-
"
|
|
11031
|
+
"manufacturer": {
|
|
11032
|
+
"name": asString(chargingStation?.["manufacturer"])
|
|
11033
|
+
},
|
|
11034
|
+
"model": {
|
|
11035
|
+
"name": asString(chargingStation?.["type"])
|
|
11036
|
+
},
|
|
11037
|
+
"hardware": {
|
|
11038
|
+
"serialNumber": asString(chargingStation?.["serialNumber"])
|
|
11039
|
+
},
|
|
11040
|
+
"firmware": {
|
|
11041
|
+
"version": asString(chargingStation?.["softwareVersion"])
|
|
11042
|
+
},
|
|
10988
11043
|
"legalCompliance": asJSONObject(chargingStation?.["legalCompliance"]),
|
|
10989
11044
|
"geoLocation": asJSONObject(chargingStation?.["geoLocation"]),
|
|
10990
11045
|
"address": asJSONObject(chargingStation?.["address"]),
|
|
@@ -10994,18 +11049,29 @@ var Alfen = class {
|
|
|
10994
11049
|
"description": asJSONObject(evse?.["description"]),
|
|
10995
11050
|
"connectors": [{
|
|
10996
11051
|
"type": asString(connector?.["type"]) ?? "",
|
|
10997
|
-
"
|
|
11052
|
+
"cable": {
|
|
11053
|
+
"length": asNumber(connector?.["cableLength"]) ?? 0,
|
|
11054
|
+
"looses": asNumber(connector?.["cableLooses"]) ?? 0
|
|
11055
|
+
}
|
|
10998
11056
|
}],
|
|
10999
|
-
"
|
|
11057
|
+
"energyMeters": [
|
|
11000
11058
|
{
|
|
11001
11059
|
"@id": common.MeterId,
|
|
11002
|
-
"manufacturer":
|
|
11003
|
-
|
|
11004
|
-
|
|
11005
|
-
|
|
11006
|
-
"
|
|
11007
|
-
|
|
11008
|
-
|
|
11060
|
+
"manufacturer": {
|
|
11061
|
+
"name": asString(energyMeter?.["manufacturer"]),
|
|
11062
|
+
"contact": { "web": asString(energyMeter?.["manufacturerURL"]) }
|
|
11063
|
+
},
|
|
11064
|
+
"model": {
|
|
11065
|
+
"name": asString(energyMeter?.["model"]),
|
|
11066
|
+
"url": asString(energyMeter?.["modelURL"])
|
|
11067
|
+
},
|
|
11068
|
+
"hardware": {
|
|
11069
|
+
"revision": asString(energyMeter?.["hardwareVersion"])
|
|
11070
|
+
},
|
|
11071
|
+
"firmware": {
|
|
11072
|
+
"version": common.AdapterFWVersion,
|
|
11073
|
+
"checksum": common.AdapterFWChecksum
|
|
11074
|
+
},
|
|
11009
11075
|
"signatureFormat": "https://open.charging.cloud/contexts/EnergyMeterSignatureFormats/AlfenCrypt01",
|
|
11010
11076
|
"publicKeys": [
|
|
11011
11077
|
{
|
|
@@ -11105,23 +11171,21 @@ var AlfenCrypt01 = class extends ACrypt {
|
|
|
11105
11171
|
}
|
|
11106
11172
|
async VerifyChargingSession(chargingSession) {
|
|
11107
11173
|
let sessionResult = "UnknownSessionFormat" /* UnknownSessionFormat */;
|
|
11108
|
-
{
|
|
11109
|
-
|
|
11110
|
-
|
|
11111
|
-
|
|
11112
|
-
|
|
11113
|
-
|
|
11114
|
-
|
|
11115
|
-
|
|
11116
|
-
|
|
11117
|
-
|
|
11118
|
-
|
|
11119
|
-
sessionResult = "InvalidSignature" /* InvalidSignature */;
|
|
11120
|
-
}
|
|
11174
|
+
for (const measurement of chargingSession.measurements ?? []) {
|
|
11175
|
+
measurement.chargingSession = chargingSession;
|
|
11176
|
+
if (measurement.values.length > 1) {
|
|
11177
|
+
for (const measurementValue of measurement.values) {
|
|
11178
|
+
measurementValue.measurement = measurement;
|
|
11179
|
+
await this.VerifyMeasurement(measurementValue);
|
|
11180
|
+
}
|
|
11181
|
+
sessionResult = "ValidSignature" /* ValidSignature */;
|
|
11182
|
+
for (const measurementValue of measurement.values) {
|
|
11183
|
+
if (sessionResult == "ValidSignature" /* ValidSignature */ && measurementValue.result?.status != "ValidSignature" /* ValidSignature */) {
|
|
11184
|
+
sessionResult = "InvalidSignature" /* InvalidSignature */;
|
|
11121
11185
|
}
|
|
11122
|
-
}
|
|
11123
|
-
|
|
11124
|
-
|
|
11186
|
+
}
|
|
11187
|
+
} else
|
|
11188
|
+
sessionResult = "AtLeastTwoMeasurementsRequired" /* AtLeastTwoMeasurementsRequired */;
|
|
11125
11189
|
}
|
|
11126
11190
|
return {
|
|
11127
11191
|
status: sessionResult,
|
|
@@ -11151,7 +11215,7 @@ var AlfenCrypt01 = class extends ACrypt {
|
|
|
11151
11215
|
unitEncoded: SetInt8(cryptoBuffer, measurementValue.measurement.unitEncoded ?? 0, 44),
|
|
11152
11216
|
scalar: SetInt8(cryptoBuffer, measurementValue.measurement.scale, 45),
|
|
11153
11217
|
value: SetUInt64D(cryptoBuffer, measurementValue.value, 46, true),
|
|
11154
|
-
uid: SetText(cryptoBuffer, measurementValue.measurement.chargingSession?.authorizationStart["@id"] ?? "", 54),
|
|
11218
|
+
uid: SetText(cryptoBuffer, measurementValue.measurement.chargingSession?.authorizationStart?.["@id"] ?? "", 54),
|
|
11155
11219
|
sessionId: SetUInt32(cryptoBuffer, parseInt(measurementValue.measurement.chargingSession?.internalSessionId ?? ""), 74, true),
|
|
11156
11220
|
paging: SetUInt32(cryptoBuffer, measurementValue.paginationId, 78, true)
|
|
11157
11221
|
};
|
|
@@ -11189,8 +11253,8 @@ var AlfenCrypt01 = class extends ACrypt {
|
|
|
11189
11253
|
cryptoResult.hashValue = hashValue224k1;
|
|
11190
11254
|
result = this.curve224k1.validate(
|
|
11191
11255
|
hashValue224k1,
|
|
11192
|
-
BigInt(
|
|
11193
|
-
BigInt(
|
|
11256
|
+
BigInt("0x" + signatureExpected.r),
|
|
11257
|
+
BigInt("0x" + signatureExpected.s),
|
|
11194
11258
|
[
|
|
11195
11259
|
BigInt("0x" + publicKey.substring(2, 58)),
|
|
11196
11260
|
BigInt("0x" + publicKey.substring(58))
|
|
@@ -11277,7 +11341,7 @@ var AlfenCrypt01 = class extends ACrypt {
|
|
|
11277
11341
|
this.CreateLocalizedLine("Unit (encoded)", measurementValue.measurement.unitEncoded ?? 0, result.unitEncoded ?? "", infoDiv, PlainTextDiv);
|
|
11278
11342
|
this.CreateLocalizedLine("Scaling", measurementValue.measurement.scale, result.scalar ?? "", infoDiv, PlainTextDiv);
|
|
11279
11343
|
this.CreateLocalizedLine("Measurement Value", measurementValue.value.toString() + " Wh", result.value ?? "", infoDiv, PlainTextDiv);
|
|
11280
|
-
this.CreateLocalizedLine("Authorization", (measurementValue.measurement.chargingSession?.authorizationStart["@id"] ?? "") + " hex", pad(result.uid, 20), infoDiv, PlainTextDiv);
|
|
11344
|
+
this.CreateLocalizedLine("Authorization", (measurementValue.measurement.chargingSession?.authorizationStart?.["@id"] ?? "") + " hex", pad(result.uid, 20), infoDiv, PlainTextDiv);
|
|
11281
11345
|
this.CreateLocalizedLine("SessionId", measurementValue.measurement.chargingSession?.["@id"] ?? "", result.sessionId ?? "", infoDiv, PlainTextDiv);
|
|
11282
11346
|
this.CreateLocalizedLine("Pagination counter", measurementValue.paginationId, result.paging ?? "", infoDiv, PlainTextDiv);
|
|
11283
11347
|
}
|
|
@@ -11304,8 +11368,8 @@ var AlfenCrypt01 = class extends ACrypt {
|
|
|
11304
11368
|
signatureDiv.innerHTML = await this.chargy.CheckMeterPublicKeySignature(
|
|
11305
11369
|
measurementValue.measurement.chargingSession?.chargingStation,
|
|
11306
11370
|
measurementValue.measurement.chargingSession?.EVSE,
|
|
11307
|
-
measurementValue.measurement.chargingSession?.EVSE?.
|
|
11308
|
-
measurementValue.measurement.chargingSession?.EVSE?.
|
|
11371
|
+
measurementValue.measurement.chargingSession?.EVSE?.energyMeters?.[0],
|
|
11372
|
+
measurementValue.measurement.chargingSession?.EVSE?.energyMeters?.[0]?.publicKeys?.[0],
|
|
11309
11373
|
signature
|
|
11310
11374
|
);
|
|
11311
11375
|
} catch {
|
|
@@ -11317,7 +11381,7 @@ var AlfenCrypt01 = class extends ACrypt {
|
|
|
11317
11381
|
if (SignatureExpectedDiv.parentElement) {
|
|
11318
11382
|
getArrayLikeElement(SignatureExpectedDiv.parentElement.children, 0, "Missing expected signature header").innerHTML = this.chargy.GetLocalizedMessage("Expected signature") + " (" + (result.signature.format ?? "") + ", hex)";
|
|
11319
11383
|
}
|
|
11320
|
-
if (result.signature.r
|
|
11384
|
+
if (result.signature.r.length > 0 && result.signature.s.length > 0) {
|
|
11321
11385
|
const signatureR = result.signature.r.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "-";
|
|
11322
11386
|
const signatureS = result.signature.s.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "-";
|
|
11323
11387
|
SignatureExpectedDiv.innerHTML = "r: " + signatureR + "<br />s: " + signatureS;
|
|
@@ -11822,7 +11886,7 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
11822
11886
|
"@context": "https://open.charging.cloud/contexts/SessionSignatureFormats/bsm-ws36a-v0+json",
|
|
11823
11887
|
"begin": firstDataSet.time,
|
|
11824
11888
|
"end": lastDataSet.time,
|
|
11825
|
-
"EVSEId": CTR.chargingStationOperators?.[0]?.["chargingStations"]?.[0]?.["EVSEs"][0]?.["@id"],
|
|
11889
|
+
"EVSEId": CTR.chargingStationOperators?.[0]?.["chargingStations"]?.[0]?.["EVSEs"]?.[0]?.["@id"],
|
|
11826
11890
|
"authorizationStart": {
|
|
11827
11891
|
"@id": common.contract_id,
|
|
11828
11892
|
"@context": common.contract_type
|
|
@@ -11929,7 +11993,7 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
11929
11993
|
{
|
|
11930
11994
|
const firstChargingSession = getFirstArrayElement(CTR.chargingSessions, "Missing first BSM charging session");
|
|
11931
11995
|
const lastChargingSession = getLastArrayElement(CTR.chargingSessions, "Missing last BSM charging session");
|
|
11932
|
-
if (CTR.begin == void 0 || CTR.begin === "" || CTR.begin > firstChargingSession.begin) {
|
|
11996
|
+
if (firstChargingSession.begin !== void 0 && (CTR.begin == void 0 || CTR.begin === "" || CTR.begin > firstChargingSession.begin)) {
|
|
11933
11997
|
CTR.begin = firstChargingSession.begin;
|
|
11934
11998
|
}
|
|
11935
11999
|
if (lastChargingSession.end !== void 0) {
|
|
@@ -11937,21 +12001,22 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
11937
12001
|
CTR.end = lastChargingSession.end;
|
|
11938
12002
|
}
|
|
11939
12003
|
}
|
|
11940
|
-
|
|
11941
|
-
|
|
11942
|
-
|
|
11943
|
-
|
|
11944
|
-
|
|
11945
|
-
else {
|
|
11946
|
-
CTR.contract["@id"] = common.contract_id;
|
|
11947
|
-
CTR.contract["@context"] = common.contract_type;
|
|
11948
|
-
}
|
|
11949
|
-
CTR.chargingStationOperators?.[0]?.chargingStations?.[0]?.EVSEs[0]?.meters?.push({
|
|
12004
|
+
CTR.contracts = [{
|
|
12005
|
+
"@id": common.contract_id,
|
|
12006
|
+
"@context": common.contract_type
|
|
12007
|
+
}];
|
|
12008
|
+
CTR.chargingStationOperators?.[0]?.chargingStations?.[0]?.EVSEs?.[0]?.energyMeters?.push({
|
|
11950
12009
|
"@id": common.meterInfo_meterId,
|
|
11951
|
-
model: common.meterInfo_type,
|
|
11952
|
-
manufacturer:
|
|
11953
|
-
|
|
11954
|
-
|
|
12010
|
+
model: { name: common.meterInfo_type },
|
|
12011
|
+
manufacturer: {
|
|
12012
|
+
name: common.meterInfo_manufacturer,
|
|
12013
|
+
contact: {
|
|
12014
|
+
web: "https://www.bzr-bauer.de"
|
|
12015
|
+
}
|
|
12016
|
+
},
|
|
12017
|
+
firmware: {
|
|
12018
|
+
version: common.meterInfo_firmwareVersion
|
|
12019
|
+
},
|
|
11955
12020
|
//hardwareVersion?: string;
|
|
11956
12021
|
signatureInfos: {
|
|
11957
12022
|
hash: "SHA256" /* SHA256 */,
|
|
@@ -11986,7 +12051,7 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
11986
12051
|
async VerifyChargingSession(chargingSession) {
|
|
11987
12052
|
let sessionResult = "UnknownSessionFormat" /* UnknownSessionFormat */;
|
|
11988
12053
|
{
|
|
11989
|
-
for (const measurement of chargingSession.measurements) {
|
|
12054
|
+
for (const measurement of chargingSession.measurements ?? []) {
|
|
11990
12055
|
measurement.chargingSession = chargingSession;
|
|
11991
12056
|
if (measurement.values.length > 1) {
|
|
11992
12057
|
for (const measurementValue of measurement.values) {
|
|
@@ -12153,13 +12218,13 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
12153
12218
|
const signatureDiv = publicKeySignatureContainer?.appendChild(document.createElement("div"));
|
|
12154
12219
|
const chargingSession = measurementValue.measurement.chargingSession;
|
|
12155
12220
|
const evse = chargingSession?.EVSE;
|
|
12156
|
-
const
|
|
12157
|
-
const publicKey =
|
|
12158
|
-
if (signatureDiv != null && chargingSession != null && evse != null &&
|
|
12221
|
+
const energyMeter = evse?.energyMeters?.at(0);
|
|
12222
|
+
const publicKey = energyMeter?.publicKeys?.at(0);
|
|
12223
|
+
if (signatureDiv != null && chargingSession != null && evse != null && energyMeter != null && publicKey != null) {
|
|
12159
12224
|
signatureDiv.innerHTML = await this.chargy.CheckMeterPublicKeySignature(
|
|
12160
12225
|
chargingSession.chargingStation,
|
|
12161
12226
|
evse,
|
|
12162
|
-
|
|
12227
|
+
energyMeter,
|
|
12163
12228
|
publicKey,
|
|
12164
12229
|
signature
|
|
12165
12230
|
);
|
|
@@ -12174,7 +12239,7 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
12174
12239
|
if (SignatureExpectedDiv.parentElement) {
|
|
12175
12240
|
getArrayLikeElement(SignatureExpectedDiv.parentElement.children, 0, "Missing expected signature header").innerHTML = "Erwartete Signatur (" + (result.signature.format ?? "") + ", hex)";
|
|
12176
12241
|
}
|
|
12177
|
-
if (result.signature.r
|
|
12242
|
+
if (result.signature.r.length > 0 && result.signature.s.length > 0)
|
|
12178
12243
|
SignatureExpectedDiv.innerHTML = "r: " + (result.signature.r.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "-") + "<br />s: " + (result.signature.s.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "-");
|
|
12179
12244
|
else if (result.signature.value != null && result.signature.value.length > 0)
|
|
12180
12245
|
SignatureExpectedDiv.innerHTML = result.signature.value.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "-";
|
|
@@ -12312,97 +12377,7 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
12312
12377
|
// //#endregion
|
|
12313
12378
|
};
|
|
12314
12379
|
|
|
12315
|
-
// src/
|
|
12316
|
-
var CanonicalJSONError = class extends TypeError {
|
|
12317
|
-
constructor(message) {
|
|
12318
|
-
super(message);
|
|
12319
|
-
this.name = "CanonicalJSONError";
|
|
12320
|
-
}
|
|
12321
|
-
};
|
|
12322
|
-
function canonicalJSONStringify(value) {
|
|
12323
|
-
return serializeJSONValue(value, "$", /* @__PURE__ */ new WeakSet());
|
|
12324
|
-
}
|
|
12325
|
-
function canonicalJSONBytes(value) {
|
|
12326
|
-
return new TextEncoder().encode(canonicalJSONStringify(value));
|
|
12327
|
-
}
|
|
12328
|
-
function serializeJSONValue(value, path, seen) {
|
|
12329
|
-
switch (typeof value) {
|
|
12330
|
-
case "string":
|
|
12331
|
-
return JSON.stringify(value);
|
|
12332
|
-
case "number":
|
|
12333
|
-
if (!Number.isFinite(value))
|
|
12334
|
-
throw new CanonicalJSONError(`Non-finite number at ${path} is not valid JSON.`);
|
|
12335
|
-
return JSON.stringify(value);
|
|
12336
|
-
case "boolean":
|
|
12337
|
-
return value ? "true" : "false";
|
|
12338
|
-
case "object":
|
|
12339
|
-
if (value === null)
|
|
12340
|
-
return "null";
|
|
12341
|
-
return Array.isArray(value) ? serializeJSONArray(value, path, seen) : serializeJSONObject(value, path, seen);
|
|
12342
|
-
case "bigint":
|
|
12343
|
-
throw new CanonicalJSONError(`BigInt at ${path} is not valid JSON.`);
|
|
12344
|
-
case "undefined":
|
|
12345
|
-
throw new CanonicalJSONError(`Undefined value at ${path} is not valid JSON.`);
|
|
12346
|
-
case "function":
|
|
12347
|
-
throw new CanonicalJSONError(`Function at ${path} is not valid JSON.`);
|
|
12348
|
-
case "symbol":
|
|
12349
|
-
throw new CanonicalJSONError(`Symbol at ${path} is not valid JSON.`);
|
|
12350
|
-
}
|
|
12351
|
-
}
|
|
12352
|
-
function serializeJSONArray(value, path, seen) {
|
|
12353
|
-
if (seen.has(value))
|
|
12354
|
-
throw new CanonicalJSONError(`Circular reference at ${path} is not valid JSON.`);
|
|
12355
|
-
seen.add(value);
|
|
12356
|
-
const indexedKeys = /* @__PURE__ */ new Set();
|
|
12357
|
-
for (let i = 0; i < value.length; i++) {
|
|
12358
|
-
if (!Object.prototype.hasOwnProperty.call(value, i))
|
|
12359
|
-
throw new CanonicalJSONError(`Sparse array slot at ${path}[${String(i)}] is not valid JSON.`);
|
|
12360
|
-
indexedKeys.add(String(i));
|
|
12361
|
-
}
|
|
12362
|
-
for (const key of Object.keys(value)) {
|
|
12363
|
-
if (!indexedKeys.has(key))
|
|
12364
|
-
throw new CanonicalJSONError(`Non-index array property ${formatPathProperty(key)} at ${path} is not valid JSON.`);
|
|
12365
|
-
}
|
|
12366
|
-
rejectEnumerableSymbolProperties(value, path);
|
|
12367
|
-
const serializedItems = value.map(
|
|
12368
|
-
(item, index) => serializeJSONValue(item, `${path}[${String(index)}]`, seen)
|
|
12369
|
-
);
|
|
12370
|
-
seen.delete(value);
|
|
12371
|
-
return `[${serializedItems.join(",")}]`;
|
|
12372
|
-
}
|
|
12373
|
-
function serializeJSONObject(value, path, seen) {
|
|
12374
|
-
if (Object.prototype.toString.call(value) !== "[object Object]")
|
|
12375
|
-
throw new CanonicalJSONError(`Unsupported object at ${path} is not valid JSON.`);
|
|
12376
|
-
if (seen.has(value))
|
|
12377
|
-
throw new CanonicalJSONError(`Circular reference at ${path} is not valid JSON.`);
|
|
12378
|
-
seen.add(value);
|
|
12379
|
-
rejectEnumerableSymbolProperties(value, path);
|
|
12380
|
-
const serializedProperties = Object.keys(value).sort(compareOrdinal).map((key) => {
|
|
12381
|
-
const serializedKey = JSON.stringify(key);
|
|
12382
|
-
const serializedValue = serializeJSONValue(
|
|
12383
|
-
value[key],
|
|
12384
|
-
`${path}${formatPathProperty(key)}`,
|
|
12385
|
-
seen
|
|
12386
|
-
);
|
|
12387
|
-
return `${serializedKey}:${serializedValue}`;
|
|
12388
|
-
});
|
|
12389
|
-
seen.delete(value);
|
|
12390
|
-
return `{${serializedProperties.join(",")}}`;
|
|
12391
|
-
}
|
|
12392
|
-
function rejectEnumerableSymbolProperties(value, path) {
|
|
12393
|
-
for (const symbol of Object.getOwnPropertySymbols(value)) {
|
|
12394
|
-
if (Object.prototype.propertyIsEnumerable.call(value, symbol))
|
|
12395
|
-
throw new CanonicalJSONError(`Symbol property at ${path} is not valid JSON.`);
|
|
12396
|
-
}
|
|
12397
|
-
}
|
|
12398
|
-
function compareOrdinal(left, right) {
|
|
12399
|
-
return left < right ? -1 : left > right ? 1 : 0;
|
|
12400
|
-
}
|
|
12401
|
-
function formatPathProperty(propertyName) {
|
|
12402
|
-
return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(propertyName) ? `.${propertyName}` : `[${JSON.stringify(propertyName)}]`;
|
|
12403
|
-
}
|
|
12404
|
-
|
|
12405
|
-
// src/CryptoUtils.ts
|
|
12380
|
+
// src/interfaces/CryptoUtils.ts
|
|
12406
12381
|
var import_elliptic = __toESM(require_elliptic());
|
|
12407
12382
|
var JSONSignatureVerificationStatus = /* @__PURE__ */ ((JSONSignatureVerificationStatus2) => {
|
|
12408
12383
|
JSONSignatureVerificationStatus2["True"] = "True";
|
|
@@ -12443,7 +12418,7 @@ async function signJSONMessage(JSONMessage, KeyPairs, options) {
|
|
|
12443
12418
|
continue;
|
|
12444
12419
|
const messageJSON = cloneMessageWithoutSignatures(JSONMessage);
|
|
12445
12420
|
const plainText = canonicalJSONBytes(messageJSON);
|
|
12446
|
-
const sha256Hash = await
|
|
12421
|
+
const sha256Hash = await sha256____(plainText);
|
|
12447
12422
|
JSONMessage.signatures ??= [];
|
|
12448
12423
|
const publicKeyBytes = Uint8Array.from(KeyPair.getPublic(false, "array"));
|
|
12449
12424
|
const signature = KeyPair.sign(sha256Hash, {
|
|
@@ -12490,7 +12465,7 @@ async function verifyJSONSignatureResult(JSONMessage, signature, options) {
|
|
|
12490
12465
|
try {
|
|
12491
12466
|
const messageJSON = cloneMessageWithoutSignatures(JSONMessage);
|
|
12492
12467
|
const plainText = canonicalJSONBytes(messageJSON);
|
|
12493
|
-
sha256Hash = await
|
|
12468
|
+
sha256Hash = await sha256____(plainText);
|
|
12494
12469
|
} catch (exception) {
|
|
12495
12470
|
return verificationResult(
|
|
12496
12471
|
"InvalidCanonicalJSON" /* InvalidCanonicalJSON */,
|
|
@@ -12598,7 +12573,7 @@ function parseSignedJSONMessage(JSONMessage) {
|
|
|
12598
12573
|
};
|
|
12599
12574
|
}
|
|
12600
12575
|
}
|
|
12601
|
-
if (!
|
|
12576
|
+
if (!isMandatoryJSONObject(parsedMessage))
|
|
12602
12577
|
return {
|
|
12603
12578
|
result: verificationResult(
|
|
12604
12579
|
"InvalidJSON" /* InvalidJSON */,
|
|
@@ -12617,7 +12592,7 @@ function parseSignedJSONMessage(JSONMessage) {
|
|
|
12617
12592
|
};
|
|
12618
12593
|
}
|
|
12619
12594
|
function isJSONSignature(value) {
|
|
12620
|
-
return
|
|
12595
|
+
return isMandatoryJSONObject(value) && typeof value["publicKey"] === "string" && typeof value["publicKeyHEX"] === "string" && typeof value["signature"] === "string" && typeof value["signatureHEX"] === "string";
|
|
12621
12596
|
}
|
|
12622
12597
|
function signatureEncodingsMatch(signature) {
|
|
12623
12598
|
try {
|
|
@@ -12641,32 +12616,93 @@ function verificationResult(status, description) {
|
|
|
12641
12616
|
function isVerificationTrue(result) {
|
|
12642
12617
|
return (typeof result === "string" ? result : result.status) === "True" /* True */;
|
|
12643
12618
|
}
|
|
12644
|
-
|
|
12645
|
-
|
|
12619
|
+
var CanonicalJSONError = class extends TypeError {
|
|
12620
|
+
constructor(message) {
|
|
12621
|
+
super(message);
|
|
12622
|
+
this.name = "CanonicalJSONError";
|
|
12623
|
+
}
|
|
12624
|
+
};
|
|
12625
|
+
function canonicalJSONStringify(value) {
|
|
12626
|
+
return serializeJSONValue(value, "$", /* @__PURE__ */ new WeakSet());
|
|
12646
12627
|
}
|
|
12647
|
-
|
|
12648
|
-
|
|
12649
|
-
return new Uint8Array(digest);
|
|
12628
|
+
function canonicalJSONBytes(value) {
|
|
12629
|
+
return new TextEncoder().encode(canonicalJSONStringify(value));
|
|
12650
12630
|
}
|
|
12651
|
-
function
|
|
12652
|
-
|
|
12631
|
+
function serializeJSONValue(value, path, seen) {
|
|
12632
|
+
switch (typeof value) {
|
|
12633
|
+
case "string":
|
|
12634
|
+
return JSON.stringify(value);
|
|
12635
|
+
case "number":
|
|
12636
|
+
if (!Number.isFinite(value))
|
|
12637
|
+
throw new CanonicalJSONError(`Non-finite number at ${path} is not valid JSON.`);
|
|
12638
|
+
return JSON.stringify(value);
|
|
12639
|
+
case "boolean":
|
|
12640
|
+
return value ? "true" : "false";
|
|
12641
|
+
case "object":
|
|
12642
|
+
if (value === null)
|
|
12643
|
+
return "null";
|
|
12644
|
+
return Array.isArray(value) ? serializeJSONArray(value, path, seen) : serializeJSONObject(value, path, seen);
|
|
12645
|
+
case "bigint":
|
|
12646
|
+
throw new CanonicalJSONError(`BigInt at ${path} is not valid JSON.`);
|
|
12647
|
+
case "undefined":
|
|
12648
|
+
throw new CanonicalJSONError(`Undefined value at ${path} is not valid JSON.`);
|
|
12649
|
+
case "function":
|
|
12650
|
+
throw new CanonicalJSONError(`Function at ${path} is not valid JSON.`);
|
|
12651
|
+
case "symbol":
|
|
12652
|
+
throw new CanonicalJSONError(`Symbol at ${path} is not valid JSON.`);
|
|
12653
|
+
}
|
|
12653
12654
|
}
|
|
12654
|
-
function
|
|
12655
|
-
if (
|
|
12656
|
-
|
|
12657
|
-
|
|
12658
|
-
const
|
|
12659
|
-
for (let i = 0; i <
|
|
12660
|
-
|
|
12661
|
-
|
|
12655
|
+
function serializeJSONArray(value, path, seen) {
|
|
12656
|
+
if (seen.has(value))
|
|
12657
|
+
throw new CanonicalJSONError(`Circular reference at ${path} is not valid JSON.`);
|
|
12658
|
+
seen.add(value);
|
|
12659
|
+
const indexedKeys = /* @__PURE__ */ new Set();
|
|
12660
|
+
for (let i = 0; i < value.length; i++) {
|
|
12661
|
+
if (!Object.prototype.hasOwnProperty.call(value, i))
|
|
12662
|
+
throw new CanonicalJSONError(`Sparse array slot at ${path}[${String(i)}] is not valid JSON.`);
|
|
12663
|
+
indexedKeys.add(String(i));
|
|
12664
|
+
}
|
|
12665
|
+
for (const key of Object.keys(value)) {
|
|
12666
|
+
if (!indexedKeys.has(key))
|
|
12667
|
+
throw new CanonicalJSONError(`Non-index array property ${formatPathProperty(key)} at ${path} is not valid JSON.`);
|
|
12668
|
+
}
|
|
12669
|
+
rejectEnumerableSymbolProperties(value, path);
|
|
12670
|
+
const serializedItems = value.map(
|
|
12671
|
+
(item, index) => serializeJSONValue(item, `${path}[${String(index)}]`, seen)
|
|
12672
|
+
);
|
|
12673
|
+
seen.delete(value);
|
|
12674
|
+
return `[${serializedItems.join(",")}]`;
|
|
12662
12675
|
}
|
|
12663
|
-
function
|
|
12664
|
-
if (
|
|
12665
|
-
|
|
12666
|
-
|
|
12667
|
-
|
|
12668
|
-
|
|
12669
|
-
|
|
12676
|
+
function serializeJSONObject(value, path, seen) {
|
|
12677
|
+
if (Object.prototype.toString.call(value) !== "[object Object]")
|
|
12678
|
+
throw new CanonicalJSONError(`Unsupported object at ${path} is not valid JSON.`);
|
|
12679
|
+
if (seen.has(value))
|
|
12680
|
+
throw new CanonicalJSONError(`Circular reference at ${path} is not valid JSON.`);
|
|
12681
|
+
seen.add(value);
|
|
12682
|
+
rejectEnumerableSymbolProperties(value, path);
|
|
12683
|
+
const serializedProperties = Object.keys(value).sort(compareOrdinal).map((key) => {
|
|
12684
|
+
const serializedKey = JSON.stringify(key);
|
|
12685
|
+
const serializedValue = serializeJSONValue(
|
|
12686
|
+
value[key],
|
|
12687
|
+
`${path}${formatPathProperty(key)}`,
|
|
12688
|
+
seen
|
|
12689
|
+
);
|
|
12690
|
+
return `${serializedKey}:${serializedValue}`;
|
|
12691
|
+
});
|
|
12692
|
+
seen.delete(value);
|
|
12693
|
+
return `{${serializedProperties.join(",")}}`;
|
|
12694
|
+
}
|
|
12695
|
+
function rejectEnumerableSymbolProperties(value, path) {
|
|
12696
|
+
for (const symbol of Object.getOwnPropertySymbols(value)) {
|
|
12697
|
+
if (Object.prototype.propertyIsEnumerable.call(value, symbol))
|
|
12698
|
+
throw new CanonicalJSONError(`Symbol property at ${path} is not valid JSON.`);
|
|
12699
|
+
}
|
|
12700
|
+
}
|
|
12701
|
+
function compareOrdinal(left, right) {
|
|
12702
|
+
return left < right ? -1 : left > right ? 1 : 0;
|
|
12703
|
+
}
|
|
12704
|
+
function formatPathProperty(propertyName) {
|
|
12705
|
+
return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(propertyName) ? `.${propertyName}` : `[${JSON.stringify(propertyName)}]`;
|
|
12670
12706
|
}
|
|
12671
12707
|
|
|
12672
12708
|
// src/EMHCrypt01.ts
|
|
@@ -12681,7 +12717,7 @@ var EMHCrypt01 = class extends ACrypt {
|
|
|
12681
12717
|
async VerifyChargingSession(chargingSession) {
|
|
12682
12718
|
let sessionResult = "UnknownSessionFormat" /* UnknownSessionFormat */;
|
|
12683
12719
|
{
|
|
12684
|
-
for (const measurement of chargingSession.measurements) {
|
|
12720
|
+
for (const measurement of chargingSession.measurements ?? []) {
|
|
12685
12721
|
measurement.chargingSession = chargingSession;
|
|
12686
12722
|
if (measurement.values.length > 1) {
|
|
12687
12723
|
for (const measurementValue of measurement.values) {
|
|
@@ -12729,8 +12765,8 @@ var EMHCrypt01 = class extends ACrypt {
|
|
|
12729
12765
|
scale: SetInt8(cryptoBuffer, measurementValue.measurement.scale, 30),
|
|
12730
12766
|
value: SetUInt64D(cryptoBuffer, measurementValue.value, 31, true),
|
|
12731
12767
|
logBookIndex: SetHex(cryptoBuffer, measurementValue.logBookIndex, 39, false),
|
|
12732
|
-
authorizationStart: SetText(cryptoBuffer, measurementValue.measurement.chargingSession.authorizationStart["@id"], 41),
|
|
12733
|
-
authorizationStartTimestamp: SetTimestamp32(cryptoBuffer, measurementValue.measurement.chargingSession.authorizationStart.timestamp, 169)
|
|
12768
|
+
authorizationStart: SetText(cryptoBuffer, measurementValue.measurement.chargingSession.authorizationStart?.["@id"] ?? "", 41),
|
|
12769
|
+
authorizationStartTimestamp: SetTimestamp32(cryptoBuffer, measurementValue.measurement.chargingSession.authorizationStart?.timestamp ?? measurementValue.timestamp, 169)
|
|
12734
12770
|
};
|
|
12735
12771
|
const firstSignature = measurementValue.signatures?.[0];
|
|
12736
12772
|
if (firstSignature != null) {
|
|
@@ -12749,7 +12785,7 @@ var EMHCrypt01 = class extends ACrypt {
|
|
|
12749
12785
|
if (meter.publicKeys != null && meter.publicKeys.length > 0) {
|
|
12750
12786
|
try {
|
|
12751
12787
|
const publicKey = meter.publicKeys.at(0);
|
|
12752
|
-
cryptoResult.publicKey = publicKey?.value
|
|
12788
|
+
cryptoResult.publicKey = publicKey?.value.toLowerCase();
|
|
12753
12789
|
cryptoResult.publicKeyFormat = publicKey?.format;
|
|
12754
12790
|
cryptoResult.publicKeySignatures = publicKey?.signatures;
|
|
12755
12791
|
try {
|
|
@@ -12777,7 +12813,7 @@ var EMHCrypt01 = class extends ACrypt {
|
|
|
12777
12813
|
return {};
|
|
12778
12814
|
}
|
|
12779
12815
|
async ViewMeasurement(measurementValue, _errorDiv, introDiv, infoDiv, PlainTextDiv, HashedPlainTextDiv, PublicKeyDiv, SignatureExpectedDiv, SignatureCheckDiv) {
|
|
12780
|
-
if (measurementValue.measurement?.chargingSession?.authorizationStart
|
|
12816
|
+
if (measurementValue.measurement?.chargingSession?.authorizationStart?.timestamp === void 0) {
|
|
12781
12817
|
return new Error("Invalid measurement!");
|
|
12782
12818
|
}
|
|
12783
12819
|
const result = measurementValue.result;
|
|
@@ -12828,8 +12864,8 @@ var EMHCrypt01 = class extends ACrypt {
|
|
|
12828
12864
|
signatureDiv.innerHTML = await this.chargy.CheckMeterPublicKeySignature(
|
|
12829
12865
|
measurementValue.measurement.chargingSession.chargingStation,
|
|
12830
12866
|
measurementValue.measurement.chargingSession.EVSE,
|
|
12831
|
-
measurementValue.measurement.chargingSession.EVSE?.
|
|
12832
|
-
measurementValue.measurement.chargingSession.EVSE?.
|
|
12867
|
+
measurementValue.measurement.chargingSession.EVSE?.energyMeters?.at(0),
|
|
12868
|
+
measurementValue.measurement.chargingSession.EVSE?.energyMeters?.at(0)?.publicKeys?.at(0),
|
|
12833
12869
|
signature
|
|
12834
12870
|
);
|
|
12835
12871
|
signatureDiv.onclick = () => {
|
|
@@ -12846,7 +12882,7 @@ var EMHCrypt01 = class extends ACrypt {
|
|
|
12846
12882
|
if (SignatureExpectedDiv.parentElement) {
|
|
12847
12883
|
getArrayLikeElement(SignatureExpectedDiv.parentElement.children, 0, "Missing expected signature header").innerHTML = "Erwartete Signatur (" + (result.signature.format ?? "") + ", hex)";
|
|
12848
12884
|
}
|
|
12849
|
-
if (result.signature.r
|
|
12885
|
+
if (result.signature.r.length > 0 && result.signature.s.length > 0)
|
|
12850
12886
|
SignatureExpectedDiv.innerHTML = "r: " + (result.signature.r.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "") + "<br />s: " + (result.signature.s.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "");
|
|
12851
12887
|
else if (result.signature.value != null && result.signature.value.length > 0)
|
|
12852
12888
|
SignatureExpectedDiv.innerHTML = result.signature.value.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "-";
|
|
@@ -12917,7 +12953,7 @@ var GDFCrypt01 = class extends ACrypt {
|
|
|
12917
12953
|
async VerifyChargingSession(chargingSession) {
|
|
12918
12954
|
let sessionResult = "UnknownSessionFormat" /* UnknownSessionFormat */;
|
|
12919
12955
|
{
|
|
12920
|
-
for (const measurement of chargingSession.measurements) {
|
|
12956
|
+
for (const measurement of chargingSession.measurements ?? []) {
|
|
12921
12957
|
measurement.chargingSession = chargingSession;
|
|
12922
12958
|
if (measurement.values.length > 1) {
|
|
12923
12959
|
for (const measurementValue of measurement.values) {
|
|
@@ -12961,8 +12997,8 @@ var GDFCrypt01 = class extends ACrypt {
|
|
|
12961
12997
|
unitEncoded: SetInt8(cryptoBuffer, measurementValue.measurement.unitEncoded ?? 0, 29),
|
|
12962
12998
|
scale: SetInt8(cryptoBuffer, measurementValue.measurement.scale, 30),
|
|
12963
12999
|
value: SetUInt64D(cryptoBuffer, measurementValue.value, 31, true),
|
|
12964
|
-
authorizationStart: SetHex(cryptoBuffer, measurementValue.measurement.chargingSession.authorizationStart["@id"], 41),
|
|
12965
|
-
authorizationStartTimestamp: SetTimestamp(cryptoBuffer, measurementValue.measurement.chargingSession.authorizationStart
|
|
13000
|
+
authorizationStart: SetHex(cryptoBuffer, measurementValue.measurement.chargingSession.authorizationStart?.["@id"] ?? "", 41),
|
|
13001
|
+
authorizationStartTimestamp: SetTimestamp(cryptoBuffer, measurementValue.measurement.chargingSession.authorizationStart?.timestamp, 169)
|
|
12966
13002
|
};
|
|
12967
13003
|
const firstSignature = measurementValue.signatures?.[0];
|
|
12968
13004
|
if (firstSignature != null) {
|
|
@@ -12981,7 +13017,7 @@ var GDFCrypt01 = class extends ACrypt {
|
|
|
12981
13017
|
if (meter.publicKeys != null && meter.publicKeys.length > 0) {
|
|
12982
13018
|
try {
|
|
12983
13019
|
const publicKey = meter.publicKeys.at(0);
|
|
12984
|
-
cryptoResult.publicKey = publicKey?.value
|
|
13020
|
+
cryptoResult.publicKey = publicKey?.value.toLowerCase();
|
|
12985
13021
|
cryptoResult.publicKeyFormat = publicKey?.format;
|
|
12986
13022
|
cryptoResult.publicKeySignatures = publicKey?.signatures;
|
|
12987
13023
|
try {
|
|
@@ -13009,7 +13045,7 @@ var GDFCrypt01 = class extends ACrypt {
|
|
|
13009
13045
|
return {};
|
|
13010
13046
|
}
|
|
13011
13047
|
async ViewMeasurement(measurementValue, _errorDiv, introDiv, infoDiv, PlainTextDiv, HashedPlainTextDiv, PublicKeyDiv, SignatureExpectedDiv, SignatureCheckDiv) {
|
|
13012
|
-
if (measurementValue.measurement?.chargingSession?.authorizationStart
|
|
13048
|
+
if (measurementValue.measurement?.chargingSession?.authorizationStart?.timestamp === void 0) {
|
|
13013
13049
|
return new Error("Invalid measurement!");
|
|
13014
13050
|
}
|
|
13015
13051
|
const result = measurementValue.result;
|
|
@@ -13055,8 +13091,8 @@ var GDFCrypt01 = class extends ACrypt {
|
|
|
13055
13091
|
signatureDiv.innerHTML = await this.chargy.CheckMeterPublicKeySignature(
|
|
13056
13092
|
measurementValue.measurement.chargingSession.chargingStation,
|
|
13057
13093
|
measurementValue.measurement.chargingSession.EVSE,
|
|
13058
|
-
measurementValue.measurement.chargingSession.EVSE?.
|
|
13059
|
-
measurementValue.measurement.chargingSession.EVSE?.
|
|
13094
|
+
measurementValue.measurement.chargingSession.EVSE?.energyMeters?.at(0),
|
|
13095
|
+
measurementValue.measurement.chargingSession.EVSE?.energyMeters?.at(0)?.publicKeys?.at(0),
|
|
13060
13096
|
signature
|
|
13061
13097
|
);
|
|
13062
13098
|
} catch (exception) {
|
|
@@ -13069,7 +13105,7 @@ var GDFCrypt01 = class extends ACrypt {
|
|
|
13069
13105
|
if (SignatureExpectedDiv.parentElement) {
|
|
13070
13106
|
getArrayLikeElement(SignatureExpectedDiv.parentElement.children, 0, "Missing expected signature header").innerHTML = "Erwartete Signatur (" + (result.signature.format ?? "") + ", hex)";
|
|
13071
13107
|
}
|
|
13072
|
-
if (result.signature.r
|
|
13108
|
+
if (result.signature.r.length > 0 && result.signature.s.length > 0)
|
|
13073
13109
|
SignatureExpectedDiv.innerHTML = "r: " + (result.signature.r.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "") + "<br />s: " + (result.signature.s.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "");
|
|
13074
13110
|
else if (result.signature.value != null && result.signature.value.length > 0)
|
|
13075
13111
|
SignatureExpectedDiv.innerHTML = result.signature.value.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "-";
|
|
@@ -13101,7 +13137,118 @@ var GDFCrypt01 = class extends ACrypt {
|
|
|
13101
13137
|
}
|
|
13102
13138
|
return void 0;
|
|
13103
13139
|
}
|
|
13104
|
-
};
|
|
13140
|
+
};
|
|
13141
|
+
|
|
13142
|
+
// src/interfaces/IPublicKeyInfo.ts
|
|
13143
|
+
var IPublicKeyInfo_exports = {};
|
|
13144
|
+
__export(IPublicKeyInfo_exports, {
|
|
13145
|
+
IsAPublicKey: () => IsAPublicKey,
|
|
13146
|
+
IsAPublicKeyLookup: () => IsAPublicKeyLookup,
|
|
13147
|
+
IsAPublicKeySignature: () => IsAPublicKeySignature,
|
|
13148
|
+
IsAPublicKeyXY: () => IsAPublicKeyXY,
|
|
13149
|
+
PublicKeyFormats: () => PublicKeyFormats,
|
|
13150
|
+
isPublicKeySubject: () => isPublicKeySubject
|
|
13151
|
+
});
|
|
13152
|
+
var PublicKeyFormats = /* @__PURE__ */ ((PublicKeyFormats2) => {
|
|
13153
|
+
PublicKeyFormats2["DER"] = "DER";
|
|
13154
|
+
PublicKeyFormats2["XY"] = "XY";
|
|
13155
|
+
return PublicKeyFormats2;
|
|
13156
|
+
})(PublicKeyFormats || {});
|
|
13157
|
+
function IsAPublicKeyLookup(data) {
|
|
13158
|
+
if (!isMandatoryJSONObject(data))
|
|
13159
|
+
return false;
|
|
13160
|
+
return Array.isArray(data["publicKeys"]);
|
|
13161
|
+
}
|
|
13162
|
+
function IsAPublicKey(data) {
|
|
13163
|
+
if (!isMandatoryJSONObject(data))
|
|
13164
|
+
return false;
|
|
13165
|
+
if (data["@context"] !== void 0 && !isStringOrStringArray(data["@context"])) {
|
|
13166
|
+
return false;
|
|
13167
|
+
}
|
|
13168
|
+
if (!isPublicKeySubject(data["subject"]))
|
|
13169
|
+
return false;
|
|
13170
|
+
if (data["value"] !== void 0 && !isString(data["value"])) {
|
|
13171
|
+
return false;
|
|
13172
|
+
}
|
|
13173
|
+
if (data["value"] === void 0 && (data["x"] === void 0 || data["y"] === void 0)) {
|
|
13174
|
+
return false;
|
|
13175
|
+
}
|
|
13176
|
+
if (data["value"] !== void 0 && !isStringOrOIDInfo(data["algorithm"])) {
|
|
13177
|
+
return false;
|
|
13178
|
+
}
|
|
13179
|
+
if (data["certainty"] !== void 0 && (typeof data["certainty"] !== "number" || !Number.isFinite(data["certainty"]))) {
|
|
13180
|
+
return false;
|
|
13181
|
+
}
|
|
13182
|
+
if (data["type"] !== void 0 && !isStringOrOIDInfo(data["type"])) {
|
|
13183
|
+
return false;
|
|
13184
|
+
}
|
|
13185
|
+
if (data["encoding"] !== void 0 && typeof data["encoding"] !== "string") {
|
|
13186
|
+
return false;
|
|
13187
|
+
}
|
|
13188
|
+
if (data["signatures"] !== void 0 && (!Array.isArray(data["signatures"]) || !data["signatures"].every(IsAPublicKeySignature))) {
|
|
13189
|
+
return false;
|
|
13190
|
+
}
|
|
13191
|
+
return true;
|
|
13192
|
+
}
|
|
13193
|
+
function isPublicKeySubject(data) {
|
|
13194
|
+
if (data === void 0)
|
|
13195
|
+
return true;
|
|
13196
|
+
if (isStringOrStringArray(data))
|
|
13197
|
+
return true;
|
|
13198
|
+
if (!isMandatoryJSONObject(data))
|
|
13199
|
+
return false;
|
|
13200
|
+
return Object.values(data).every(
|
|
13201
|
+
(value) => typeof value === "string" || isStringOrStringArray(value)
|
|
13202
|
+
);
|
|
13203
|
+
}
|
|
13204
|
+
function IsAPublicKeySignature(data) {
|
|
13205
|
+
if (!isMandatoryJSONObject(data))
|
|
13206
|
+
return false;
|
|
13207
|
+
if (!isOptionalString(data["@id"]))
|
|
13208
|
+
return false;
|
|
13209
|
+
if (data["@context"] !== void 0 && !isStringOrStringArray(data["@context"]))
|
|
13210
|
+
return false;
|
|
13211
|
+
if (!isOptionalStringOrOIDInfo(data["algorithm"]))
|
|
13212
|
+
return false;
|
|
13213
|
+
if (!isOptionalString(data["format"]))
|
|
13214
|
+
return false;
|
|
13215
|
+
if (!isOptionalString(data["encoding"]))
|
|
13216
|
+
return false;
|
|
13217
|
+
if (data["value"] !== void 0 && !isString(data["value"]))
|
|
13218
|
+
return false;
|
|
13219
|
+
if (data["publicKey"] !== void 0 && !isEncodedValue(data["publicKey"]))
|
|
13220
|
+
return false;
|
|
13221
|
+
if (data["signature"] !== void 0 && !isEncodedValue(data["signature"]))
|
|
13222
|
+
return false;
|
|
13223
|
+
if (!isOptionalString(data["timestamp"]))
|
|
13224
|
+
return false;
|
|
13225
|
+
if (!isOptionalString(data["issuer"]))
|
|
13226
|
+
return false;
|
|
13227
|
+
if (!isOptionalString(data["signer"]))
|
|
13228
|
+
return false;
|
|
13229
|
+
if (!isOptionalString(data["notBefore"]))
|
|
13230
|
+
return false;
|
|
13231
|
+
if (!isOptionalString(data["notAfter"]))
|
|
13232
|
+
return false;
|
|
13233
|
+
if (!isOptionalStringArray(data["keyUsage"]))
|
|
13234
|
+
return false;
|
|
13235
|
+
if (data["operations"] !== void 0 && !isMandatoryJSONObject(data["operations"]))
|
|
13236
|
+
return false;
|
|
13237
|
+
if (data["comment"] !== void 0 && !isMandatoryJSONObject(data["comment"]))
|
|
13238
|
+
return false;
|
|
13239
|
+
return data["value"] !== void 0 || data["signature"] !== void 0 || data["algorithm"] !== void 0 || data["timestamp"] !== void 0 || data["issuer"] !== void 0 || data["signer"] !== void 0 || data["keyUsage"] !== void 0;
|
|
13240
|
+
}
|
|
13241
|
+
function IsAPublicKeyXY(data) {
|
|
13242
|
+
if (!IsAPublicKey(data))
|
|
13243
|
+
return false;
|
|
13244
|
+
if (!isString(data["x"])) {
|
|
13245
|
+
return false;
|
|
13246
|
+
}
|
|
13247
|
+
if (!isString(data["y"])) {
|
|
13248
|
+
return false;
|
|
13249
|
+
}
|
|
13250
|
+
return true;
|
|
13251
|
+
}
|
|
13105
13252
|
var MENNEKES_EDL40_XMLNS = "http://www.mennekes.de/Mennekes.EdlVerification.xsd";
|
|
13106
13253
|
var MENNEKES_EDL40_OBIS = "1-0:1.17.0*255";
|
|
13107
13254
|
var Mennekes = class {
|
|
@@ -13163,15 +13310,15 @@ var Mennekes = class {
|
|
|
13163
13310
|
return {
|
|
13164
13311
|
"@id": chargingStationId,
|
|
13165
13312
|
"description": { "en": "Mennekes EDL40 charging station" },
|
|
13166
|
-
"manufacturer": "MENNEKES",
|
|
13313
|
+
"manufacturer": { "name": "MENNEKES" },
|
|
13167
13314
|
"address": chargingProcess.siteAddress,
|
|
13168
13315
|
"EVSEs": [
|
|
13169
13316
|
{
|
|
13170
13317
|
"@id": evseId,
|
|
13171
|
-
"
|
|
13318
|
+
"energyMeters": [
|
|
13172
13319
|
{
|
|
13173
13320
|
"@id": meterId,
|
|
13174
|
-
"manufacturer": "MENNEKES",
|
|
13321
|
+
"manufacturer": { "name": "MENNEKES" },
|
|
13175
13322
|
"signatureFormat": "https://open.charging.cloud/contexts/EnergyMeterSignatureFormats/MennekesCrypt01",
|
|
13176
13323
|
"publicKeys": [
|
|
13177
13324
|
{
|
|
@@ -13249,7 +13396,7 @@ var MennekesCrypt01 = class extends ACrypt {
|
|
|
13249
13396
|
}
|
|
13250
13397
|
async VerifyChargingSession(chargingSession) {
|
|
13251
13398
|
let sessionResult = "UnknownSessionFormat" /* UnknownSessionFormat */;
|
|
13252
|
-
for (const measurement of chargingSession.measurements) {
|
|
13399
|
+
for (const measurement of chargingSession.measurements ?? []) {
|
|
13253
13400
|
measurement.chargingSession = chargingSession;
|
|
13254
13401
|
if (measurement.values.length >= 2) {
|
|
13255
13402
|
sessionResult = "ValidSignature" /* ValidSignature */;
|
|
@@ -13316,8 +13463,6 @@ var MennekesCrypt01 = class extends ACrypt {
|
|
|
13316
13463
|
if (meter.publicKeys == null || meter.publicKeys.length === 0)
|
|
13317
13464
|
return setResult("PublicKeyNotFound" /* PublicKeyNotFound */);
|
|
13318
13465
|
const signatureExpected = measurementValue.signatures?.[0];
|
|
13319
|
-
if (signatureExpected.r == null || signatureExpected.s == null)
|
|
13320
|
-
return setResult("InvalidSignature" /* InvalidSignature */);
|
|
13321
13466
|
const signedData = buildMennekesSignatureData(
|
|
13322
13467
|
{
|
|
13323
13468
|
serverId: measurement.serverId,
|
|
@@ -13339,7 +13484,7 @@ var MennekesCrypt01 = class extends ACrypt {
|
|
|
13339
13484
|
secondIndex: measurementValue.secondsIndex ?? 0
|
|
13340
13485
|
}
|
|
13341
13486
|
);
|
|
13342
|
-
cryptoResult.signedData =
|
|
13487
|
+
cryptoResult.signedData = bytesToHex(signedData);
|
|
13343
13488
|
cryptoResult.logBytes = cryptoResult.signedData.substring(78, 82);
|
|
13344
13489
|
const signedDataBuffer = signedData.buffer.slice(
|
|
13345
13490
|
signedData.byteOffset,
|
|
@@ -13377,7 +13522,7 @@ var MennekesCrypt01 = class extends ACrypt {
|
|
|
13377
13522
|
PublicKeyDiv.innerHTML = result.publicKey?.match(/.{1,8}/g)?.join(" ") ?? "";
|
|
13378
13523
|
if (SignatureExpectedDiv.parentElement?.children[0])
|
|
13379
13524
|
SignatureExpectedDiv.parentElement.children[0].innerHTML = this.chargy.GetLocalizedMessage("Expected signature") + " (rs, hex)";
|
|
13380
|
-
SignatureExpectedDiv.innerHTML = result.signature
|
|
13525
|
+
SignatureExpectedDiv.innerHTML = result.signature != null && result.signature.r.length > 0 && 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(" ") ?? "") : "";
|
|
13381
13526
|
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>";
|
|
13382
13527
|
return Promise.resolve(void 0);
|
|
13383
13528
|
}
|
|
@@ -13439,23 +13584,6 @@ function dateToMennekesLocalEpochSeconds(isoTimestamp) {
|
|
|
13439
13584
|
const offsetSeconds = sign * (Number(offsetMatch[2]) * 3600 + Number(offsetMatch[3]) * 60);
|
|
13440
13585
|
return Math.floor(date.getTime() / 1e3) + offsetSeconds;
|
|
13441
13586
|
}
|
|
13442
|
-
function cleanHex(hex) {
|
|
13443
|
-
return hex.replace(/\s+/g, "");
|
|
13444
|
-
}
|
|
13445
|
-
function hexToBytes(hex) {
|
|
13446
|
-
const cleanedHex = cleanHex(hex);
|
|
13447
|
-
if (cleanedHex.length % 2 !== 0)
|
|
13448
|
-
throw new Error("Hex strings must have even length!");
|
|
13449
|
-
if (!/^[0-9a-fA-F]*$/.test(cleanedHex))
|
|
13450
|
-
throw new Error("Invalid hexadecimal string!");
|
|
13451
|
-
const bytes = new Uint8Array(cleanedHex.length / 2);
|
|
13452
|
-
for (let index = 0; index < cleanedHex.length; index += 2)
|
|
13453
|
-
bytes[index / 2] = Number.parseInt(cleanedHex.substring(index, index + 2), 16);
|
|
13454
|
-
return bytes;
|
|
13455
|
-
}
|
|
13456
|
-
function bytesToHex2(bytes) {
|
|
13457
|
-
return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
13458
|
-
}
|
|
13459
13587
|
function parseChargingProcessElement(chargingProcessElement) {
|
|
13460
13588
|
const siteAddressElement = child(chargingProcessElement, "SiteAddress");
|
|
13461
13589
|
return {
|
|
@@ -13593,7 +13721,7 @@ var OCMFv1_x = class extends ACrypt {
|
|
|
13593
13721
|
async VerifyChargingSession(chargingSession) {
|
|
13594
13722
|
let sessionResult = "Unvalidated" /* Unvalidated */;
|
|
13595
13723
|
{
|
|
13596
|
-
for (const measurement of chargingSession.measurements) {
|
|
13724
|
+
for (const measurement of chargingSession.measurements ?? []) {
|
|
13597
13725
|
measurement.chargingSession = chargingSession;
|
|
13598
13726
|
if (measurement.values.length > 1) {
|
|
13599
13727
|
for (const measurementValue of measurement.values) {
|
|
@@ -13741,7 +13869,7 @@ var OCMFv1_x = class extends ACrypt {
|
|
|
13741
13869
|
return new Error("Invalid measurement!");
|
|
13742
13870
|
}
|
|
13743
13871
|
{
|
|
13744
|
-
introDiv.innerHTML = this.chargy.GetLocalizedMessage("The following data of the charging session is relevant for metrological and legal metrological purposes and therefore part of the digital signature").replace("{methodName}", "OCMFCrypt01").replace("{cryptoAlgorithm}", measurementValue.ocmfDocument.publicKey != null && typeof measurementValue.ocmfDocument.publicKey !== "string" ? "(" + measurementValue.ocmfDocument.publicKey.algorithm + ") " : "");
|
|
13872
|
+
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" ? "(" + OIDInfo(measurementValue.ocmfDocument.publicKey.algorithm) + ") " : "");
|
|
13745
13873
|
}
|
|
13746
13874
|
{
|
|
13747
13875
|
if (PlainTextDiv.parentElement) {
|
|
@@ -13784,9 +13912,9 @@ var OCMFv1_x = class extends ACrypt {
|
|
|
13784
13912
|
}
|
|
13785
13913
|
if (measurementValue.ocmfDocument.publicKey != null) {
|
|
13786
13914
|
if (PublicKeyDiv.parentElement) {
|
|
13787
|
-
getArrayLikeElement(PublicKeyDiv.parentElement.children, 0, "Missing public key header").innerHTML = typeof measurementValue.ocmfDocument.publicKey === "string" ? this.chargy.GetLocalizedMessage("Public Key") : this.chargy.GetLocalizedMessage("Public Key") + " (" + measurementValue.ocmfDocument.publicKey.algorithm + ", " + measurementValue.ocmfDocument.publicKey.encoding + ")";
|
|
13915
|
+
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") + " (" + OIDInfo(measurementValue.ocmfDocument.publicKey.algorithm) + ", " + (measurementValue.ocmfDocument.publicKey.encoding ?? "-") + ")";
|
|
13788
13916
|
}
|
|
13789
|
-
PublicKeyDiv.innerHTML = typeof measurementValue.ocmfDocument.publicKey === "string" ? measurementValue.ocmfDocument.publicKey : "der: " + (measurementValue.ocmfDocument.publicKey.value
|
|
13917
|
+
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(" ") ?? "-");
|
|
13790
13918
|
}
|
|
13791
13919
|
const publicKeySignatureContainer = PublicKeyDiv.parentElement?.children[3];
|
|
13792
13920
|
if (publicKeySignatureContainer !== void 0) {
|
|
@@ -13799,8 +13927,8 @@ var OCMFv1_x = class extends ACrypt {
|
|
|
13799
13927
|
signatureDiv.innerHTML = await this.chargy.CheckMeterPublicKeySignature(
|
|
13800
13928
|
measurementValue.measurement.chargingSession.chargingStation,
|
|
13801
13929
|
measurementValue.measurement.chargingSession.EVSE,
|
|
13802
|
-
measurementValue.measurement.chargingSession.EVSE?.
|
|
13803
|
-
measurementValue.measurement.chargingSession.EVSE?.
|
|
13930
|
+
measurementValue.measurement.chargingSession.EVSE?.energyMeters?.at(0),
|
|
13931
|
+
measurementValue.measurement.chargingSession.EVSE?.energyMeters?.at(0)?.publicKeys?.at(0),
|
|
13804
13932
|
signature
|
|
13805
13933
|
);
|
|
13806
13934
|
} catch {
|
|
@@ -13813,7 +13941,7 @@ var OCMFv1_x = class extends ACrypt {
|
|
|
13813
13941
|
if (SignatureExpectedDiv.parentElement) {
|
|
13814
13942
|
getArrayLikeElement(SignatureExpectedDiv.parentElement.children, 0, "Missing expected signature header").innerHTML = this.chargy.GetLocalizedMessage("Expected signature") + " (rs, hex)";
|
|
13815
13943
|
}
|
|
13816
|
-
SignatureExpectedDiv.innerHTML = "der: " + (measurementValue.ocmfDocument.signature.SD.match(/.{1,8}/g)?.join(" ") ?? "-") + "<br /><br />r: " + (measurementValue.ocmfDocument.signatureRS?.r
|
|
13944
|
+
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(" ") ?? "-");
|
|
13817
13945
|
}
|
|
13818
13946
|
if (measurementValue.measurement.chargingSession.verificationResult) {
|
|
13819
13947
|
switch (measurementValue.measurement.chargingSession.verificationResult.status) {
|
|
@@ -13858,15 +13986,6 @@ var OCMF = class {
|
|
|
13858
13986
|
//#region (private) tryToParseOCMFv1_0(OCMFDataList, ContainerInfos?)
|
|
13859
13987
|
tryToParseOCMFv1_0(OCMFJSONDocuments, ContainerInfos) {
|
|
13860
13988
|
try {
|
|
13861
|
-
const containerInfos = asJSONObject(ContainerInfos) ?? {};
|
|
13862
|
-
const chargingStationInfo = asJSONObject(containerInfos["chargingStation"]);
|
|
13863
|
-
const evseInfo = asJSONObject(containerInfos["EVSE"]);
|
|
13864
|
-
const connectorInfo = asJSONObject(containerInfos["connector"]);
|
|
13865
|
-
const energyMeterInfo = asJSONObject(containerInfos["energyMeter"]);
|
|
13866
|
-
const chargingStationId = asString(containerInfos["ChargingStationId"]) ?? asString(chargingStationInfo?.["@id"]) ?? "DE*GEF*STATION*CHARGY*1";
|
|
13867
|
-
const evseId = asString(containerInfos["EVSEId"]) ?? asString(evseInfo?.["@id"]) ?? "DE*GEF*EVSE*CHARGY*1";
|
|
13868
|
-
const stationDescription = asJSONObject(chargingStationInfo?.["description"]);
|
|
13869
|
-
const evseDescription = asJSONObject(evseInfo?.["description"]);
|
|
13870
13989
|
const firstOCMDJSONDocument = getFirstArrayElement(OCMFJSONDocuments, "Missing first OCMF JSON document");
|
|
13871
13990
|
const formatVersion = firstOCMDJSONDocument.payload.FV;
|
|
13872
13991
|
const gatewayInformation = firstOCMDJSONDocument.payload.GI ?? firstOCMDJSONDocument.payload.VI;
|
|
@@ -13939,49 +14058,71 @@ var OCMF = class {
|
|
|
13939
14058
|
"gatewayVersion": gatewayVersion
|
|
13940
14059
|
},
|
|
13941
14060
|
// "chargingStationOperators": [{
|
|
13942
|
-
"chargingPools":
|
|
13943
|
-
|
|
13944
|
-
|
|
13945
|
-
|
|
13946
|
-
|
|
13947
|
-
|
|
13948
|
-
|
|
13949
|
-
|
|
13950
|
-
|
|
13951
|
-
|
|
13952
|
-
|
|
13953
|
-
|
|
13954
|
-
|
|
13955
|
-
|
|
13956
|
-
|
|
13957
|
-
|
|
13958
|
-
|
|
13959
|
-
|
|
13960
|
-
|
|
13961
|
-
|
|
13962
|
-
|
|
13963
|
-
|
|
13964
|
-
|
|
13965
|
-
|
|
13966
|
-
|
|
13967
|
-
|
|
13968
|
-
|
|
13969
|
-
|
|
13970
|
-
|
|
13971
|
-
|
|
13972
|
-
|
|
13973
|
-
|
|
13974
|
-
|
|
13975
|
-
|
|
13976
|
-
|
|
13977
|
-
|
|
13978
|
-
}
|
|
14061
|
+
// "chargingPools": [{
|
|
14062
|
+
// "@id": "DE*GEF*POOL*CHARGY*1",
|
|
14063
|
+
// "description": { "en": "GraphDefined CHARGY Virtual Charging Pool 1" },
|
|
14064
|
+
// "chargingStations": [{
|
|
14065
|
+
// "@id": chargingStationId,
|
|
14066
|
+
// "description": stationDescription && Object.keys(stationDescription).length > 0
|
|
14067
|
+
// ? stationDescription
|
|
14068
|
+
// : { "en": "GraphDefined CHARGY Virtual Charging Station 1" },
|
|
14069
|
+
// // "firmware": {
|
|
14070
|
+
// // "version": chargyLib.asString(chargingStationInfo?.["softwareVersion"])
|
|
14071
|
+
// // ?? chargyLib.asString(chargingStationInfo?.["firmwareVersion"])
|
|
14072
|
+
// // },
|
|
14073
|
+
// "geoLocation": chargyLib.asJSONObject(chargingStationInfo?.["geoLocation"]) as chargyInterfaces.IGeoLocation | undefined,
|
|
14074
|
+
// "address": chargyLib.asJSONObject(chargingStationInfo?.["address"]) as chargyInterfaces.IAddress | undefined,
|
|
14075
|
+
// "EVSEs": [{
|
|
14076
|
+
// "@id": evseId,
|
|
14077
|
+
// "description": evseDescription && Object.keys(evseDescription).length > 0
|
|
14078
|
+
// ? evseDescription
|
|
14079
|
+
// : { "en": "GraphDefined CHARGY Virtual EVSE 1" },
|
|
14080
|
+
// "connectors": connectorInfo
|
|
14081
|
+
// ? [{
|
|
14082
|
+
// "type": chargyLib.asString(connectorInfo["type"]) ?? "",
|
|
14083
|
+
// "cable": {
|
|
14084
|
+
// "length": chargyLib.asNumber(connectorInfo["length"]) ?? 0,
|
|
14085
|
+
// "looses": chargyLib.asNumber(connectorInfo["looses"]) ?? 0
|
|
14086
|
+
// }
|
|
14087
|
+
// }]
|
|
14088
|
+
// : [],
|
|
14089
|
+
// "energyMeters": [{
|
|
14090
|
+
// "@id": effectiveMeterSerial,
|
|
14091
|
+
// // The signed OCMF payload values always win,
|
|
14092
|
+
// // the container infos only fill the gaps!
|
|
14093
|
+
// "manufacturer": {
|
|
14094
|
+
// "name": meterVendor ?? chargyLib.asString(energyMeterInfo?.["manufacturer"]),
|
|
14095
|
+
// "contact": {
|
|
14096
|
+
// "web": chargyLib.asString(energyMeterInfo?.["manufacturerURL"])
|
|
14097
|
+
// }
|
|
14098
|
+
// },
|
|
14099
|
+
// "model": {
|
|
14100
|
+
// "name": meterModel ?? chargyLib.asString(energyMeterInfo?.["model"]),
|
|
14101
|
+
// "url": chargyLib.asString(energyMeterInfo?.["modelURL"])
|
|
14102
|
+
// },
|
|
14103
|
+
// "hardware": {
|
|
14104
|
+
// "revision": chargyLib.asString(energyMeterInfo?.["hardwareVersion"])
|
|
14105
|
+
// },
|
|
14106
|
+
// "firmware": {
|
|
14107
|
+
// "version": meterFirmware ?? chargyLib.asString(energyMeterInfo?.["firmwareVersion"])
|
|
14108
|
+
// },
|
|
14109
|
+
// "signatureFormat": "https://open.charging.cloud/contexts/EnergyMeterSignatureFormats/OCMFv1.0+json",
|
|
14110
|
+
// "publicKeys": [{
|
|
14111
|
+
// "algorithm": "?",
|
|
14112
|
+
// "encoding": "?",
|
|
14113
|
+
// "format": "?",
|
|
14114
|
+
// "value": "?",
|
|
14115
|
+
// }]
|
|
14116
|
+
// }]
|
|
14117
|
+
// }],
|
|
14118
|
+
// }]
|
|
14119
|
+
// }],
|
|
13979
14120
|
"chargingSessions": [{
|
|
13980
14121
|
"@id": "1554181214441:-1965658344385548683:2",
|
|
13981
14122
|
"@context": "https://open.charging.cloud/contexts/SessionSignatureFormats/OCMFv1.0+json",
|
|
13982
14123
|
"begin": "?",
|
|
13983
14124
|
"end": "?",
|
|
13984
|
-
"EVSEId":
|
|
14125
|
+
//"EVSEId": evseId,
|
|
13985
14126
|
"authorizationStart": {
|
|
13986
14127
|
"@id": identificationData ?? "?",
|
|
13987
14128
|
"type": identificationType ?? "?",
|
|
@@ -13994,6 +14135,8 @@ var OCMF = class {
|
|
|
13994
14135
|
}],
|
|
13995
14136
|
"certainty": 1
|
|
13996
14137
|
};
|
|
14138
|
+
if (ContainerInfos?.chargingStations !== void 0)
|
|
14139
|
+
CTR.chargingStations = ContainerInfos.chargingStations;
|
|
13997
14140
|
const measurementsByKey = /* @__PURE__ */ new Map();
|
|
13998
14141
|
for (const ocmfJSONDocument of OCMFJSONDocuments) {
|
|
13999
14142
|
let inheritedReading = {};
|
|
@@ -14126,6 +14269,8 @@ var OCMF = class {
|
|
|
14126
14269
|
}
|
|
14127
14270
|
}
|
|
14128
14271
|
}
|
|
14272
|
+
if (ContainerInfos?.chargingStations !== void 0)
|
|
14273
|
+
CTR.chargingStations = ContainerInfos.chargingStations;
|
|
14129
14274
|
CTR.status = OCMFJSONDocuments.every((ocmfJSONDocument) => ocmfJSONDocument.validationStatus === "ValidSignature" /* ValidSignature */) ? "ValidSignature" /* ValidSignature */ : "InvalidSignature" /* InvalidSignature */;
|
|
14130
14275
|
if (CTR.chargingSessions != null && CTR.chargingSessions.length > 0 && CTR.chargingSessions[0]) {
|
|
14131
14276
|
CTR.begin = CTR.chargingSessions[0].begin;
|
|
@@ -14372,7 +14517,7 @@ var OCMF = class {
|
|
|
14372
14517
|
x: publicKeyXY.x,
|
|
14373
14518
|
y: publicKeyXY.y
|
|
14374
14519
|
};
|
|
14375
|
-
} else if (
|
|
14520
|
+
} else if (IsAPublicKeyXY(OCMFJSONDocument.publicKey)) {
|
|
14376
14521
|
publicKey = curve.keyFromPublic({
|
|
14377
14522
|
x: OCMFJSONDocument.publicKey.x,
|
|
14378
14523
|
y: OCMFJSONDocument.publicKey.y
|
|
@@ -14482,17 +14627,17 @@ var OCMF = class {
|
|
|
14482
14627
|
// Not an OCMF standard!
|
|
14483
14628
|
case "ECDSA-secp384r1-SHA384":
|
|
14484
14629
|
hashAlgorithm = "SHA384, 384 Bits, hex";
|
|
14485
|
-
hashValue = await
|
|
14630
|
+
hashValue = await sha384(plaintext);
|
|
14486
14631
|
break;
|
|
14487
14632
|
// Not an OCMF standard!
|
|
14488
14633
|
case "ECDSA-brainpool384r1-SHA384":
|
|
14489
14634
|
hashAlgorithm = "SHA384, 384 Bits, hex";
|
|
14490
|
-
hashValue = await
|
|
14635
|
+
hashValue = await sha384(plaintext);
|
|
14491
14636
|
break;
|
|
14492
14637
|
// Not an OCMF standard!
|
|
14493
14638
|
case "ECDSA-secp521r1-SHA512":
|
|
14494
14639
|
hashAlgorithm = "SHA512, 512 Bits, hex";
|
|
14495
|
-
hashValue = await
|
|
14640
|
+
hashValue = await sha512(plaintext);
|
|
14496
14641
|
break;
|
|
14497
14642
|
// ECDSA-secp256r1-SHA256
|
|
14498
14643
|
default:
|
|
@@ -14574,7 +14719,12 @@ var OCMF = class {
|
|
|
14574
14719
|
//#endregion
|
|
14575
14720
|
//#region TryToParseOCMFDocument (OCMFDocument, PublicKey?, PublicKeyEncoding?, ContainerInfos?)
|
|
14576
14721
|
async TryToParseOCMFDocument(OCMFDocument, PublicKey, PublicKeyEncoding, ContainerInfos) {
|
|
14577
|
-
return this.TryToParseOCMFDocuments(
|
|
14722
|
+
return this.TryToParseOCMFDocuments(
|
|
14723
|
+
[OCMFDocument],
|
|
14724
|
+
PublicKey,
|
|
14725
|
+
PublicKeyEncoding,
|
|
14726
|
+
ContainerInfos
|
|
14727
|
+
);
|
|
14578
14728
|
}
|
|
14579
14729
|
//#endregion
|
|
14580
14730
|
//#region TryToParseOCMFDocuments(OCMFDocuments, PublicKey?, PublicKeyEncoding?, ContainerInfos?)
|
|
@@ -14695,13 +14845,16 @@ var OCPI = class {
|
|
|
14695
14845
|
const firstSignedData = asString(asJSONObject(signed_values[0])?.["signed_data"]);
|
|
14696
14846
|
if (firstSignedData != null && firstSignedData.length > 0) {
|
|
14697
14847
|
const placeInfo = asJSONObject(SomeJSON["placeInfo"]);
|
|
14848
|
+
const evseId = asString(placeInfo?.["evseId"]);
|
|
14849
|
+
const evseIdStr = asString(evseId) ?? "";
|
|
14698
14850
|
const geoLocation = asJSONObject(placeInfo?.["geoLocation"]);
|
|
14699
14851
|
const address = asJSONObject(placeInfo?.["address"]);
|
|
14700
14852
|
const geoLat = asNumber(geoLocation?.["lat"]);
|
|
14701
14853
|
const geoLon = asNumber(geoLocation?.["lon"]);
|
|
14702
14854
|
const containerInfos = {
|
|
14703
|
-
|
|
14704
|
-
|
|
14855
|
+
EVSEIds: [evseId],
|
|
14856
|
+
chargingStations: [{
|
|
14857
|
+
"@id": evseIdStr.substring(0, evseIdStr.lastIndexOf("*")),
|
|
14705
14858
|
geoLocation: geoLat !== void 0 && geoLon !== void 0 ? { lat: geoLat, lng: geoLon } : void 0,
|
|
14706
14859
|
address: address ? {
|
|
14707
14860
|
street: asString(address["street"]),
|
|
@@ -14709,8 +14862,8 @@ var OCPI = class {
|
|
|
14709
14862
|
city: asString(address["town"]),
|
|
14710
14863
|
country: asString(address["country"]) ?? ""
|
|
14711
14864
|
} : void 0
|
|
14712
|
-
}
|
|
14713
|
-
energyMeter:
|
|
14865
|
+
}]
|
|
14866
|
+
//energyMeter: chargyLib.asJSONObject(SomeJSON["meterInfo"])
|
|
14714
14867
|
};
|
|
14715
14868
|
return new OCMF(this.chargy).TryToParseOCMFDocument(
|
|
14716
14869
|
firstSignedData,
|
|
@@ -14725,7 +14878,7 @@ var OCPI = class {
|
|
|
14725
14878
|
const numberOfFormatChecks = 81;
|
|
14726
14879
|
let secondaryErrors = 0;
|
|
14727
14880
|
try {
|
|
14728
|
-
const chargingSessionId = SomeJSON["@id"];
|
|
14881
|
+
const chargingSessionId = asString(SomeJSON["@id"]);
|
|
14729
14882
|
const chargePointInfo = asJSONObject(SomeJSON["chargePointInfo"]);
|
|
14730
14883
|
const evseId = chargePointInfo?.["evseId"];
|
|
14731
14884
|
const placeInfo = asJSONObject(chargePointInfo?.["placeInfo"]);
|
|
@@ -14956,7 +15109,7 @@ var OCPI = class {
|
|
|
14956
15109
|
"value": "042313b9e469612b4ca06981bfdecb226e234632b01d84b6a814f63a114b7762c34ddce2e6853395b7a0f87275f63ffe3c",
|
|
14957
15110
|
"signatures": [
|
|
14958
15111
|
{
|
|
14959
|
-
"
|
|
15112
|
+
"@id": "...",
|
|
14960
15113
|
"algorithm": "secp192r1",
|
|
14961
15114
|
"format": "DER",
|
|
14962
15115
|
"value": "????"
|
|
@@ -15021,7 +15174,7 @@ var OCPI = class {
|
|
|
15021
15174
|
// "de": "GraphDefined EVSE - CI-Tests Pool 3 / Station A / EVSE 1"
|
|
15022
15175
|
// },
|
|
15023
15176
|
//"connectors": [ ],
|
|
15024
|
-
"
|
|
15177
|
+
"energyMeters": []
|
|
15025
15178
|
}
|
|
15026
15179
|
]
|
|
15027
15180
|
}
|
|
@@ -15036,29 +15189,29 @@ var OCPI = class {
|
|
|
15036
15189
|
return new Alfen(this.chargy).TryToParseALFENFormat(
|
|
15037
15190
|
signedMeterValues.map((value) => asString(asJSONObject(value)?.["payload"]) ?? ""),
|
|
15038
15191
|
{
|
|
15039
|
-
|
|
15040
|
-
|
|
15041
|
-
},
|
|
15042
|
-
EVSEId:
|
|
15043
|
-
|
|
15044
|
-
|
|
15045
|
-
|
|
15046
|
-
|
|
15047
|
-
|
|
15048
|
-
|
|
15049
|
-
|
|
15050
|
-
|
|
15051
|
-
|
|
15052
|
-
|
|
15053
|
-
|
|
15054
|
-
|
|
15055
|
-
|
|
15056
|
-
|
|
15057
|
-
|
|
15058
|
-
},
|
|
15059
|
-
energyMeter:
|
|
15060
|
-
connector:
|
|
15061
|
-
chargingCosts:
|
|
15192
|
+
// chargingSessions: [{
|
|
15193
|
+
// "@id": chargingSessionId ?? ""
|
|
15194
|
+
// }],
|
|
15195
|
+
// // EVSEId: evseId,
|
|
15196
|
+
// chargingStations: [{
|
|
15197
|
+
// manufacturer: chargingStation_manufacturer,
|
|
15198
|
+
// type: chargingStation_type,
|
|
15199
|
+
// serialNumber: chargingStation_serialNumber,
|
|
15200
|
+
// firmwareVersion: chargingStation_controllerSoftwareVersion,
|
|
15201
|
+
// legalCompliance: {
|
|
15202
|
+
// conformity: [{
|
|
15203
|
+
// freeText: chargingStation_compliance
|
|
15204
|
+
// }],
|
|
15205
|
+
// calibration: [{
|
|
15206
|
+
// freeText: chargingStation_calibration
|
|
15207
|
+
// }]
|
|
15208
|
+
// },
|
|
15209
|
+
// geoLocation: { "lat": geoLocation_lat, "lng": geoLocation_lon },
|
|
15210
|
+
// address: { "street": address_street, "postalCode": address_zipCode, "city": address_town, "country": address_country }
|
|
15211
|
+
// }],
|
|
15212
|
+
// energyMeter: meterInfo,
|
|
15213
|
+
// connector: connectorInfo,
|
|
15214
|
+
// chargingCosts: chargingCostsInfo
|
|
15062
15215
|
}
|
|
15063
15216
|
);
|
|
15064
15217
|
}
|
|
@@ -15309,7 +15462,7 @@ var PCDFCrypt01 = class extends ACrypt {
|
|
|
15309
15462
|
async VerifyChargingSession(chargingSession) {
|
|
15310
15463
|
let sessionResult = "ValidSignature" /* ValidSignature */;
|
|
15311
15464
|
let valueCount = 0;
|
|
15312
|
-
for (const measurement of chargingSession.measurements) {
|
|
15465
|
+
for (const measurement of chargingSession.measurements ?? []) {
|
|
15313
15466
|
measurement.chargingSession = chargingSession;
|
|
15314
15467
|
for (const measurementValue of measurement.values) {
|
|
15315
15468
|
valueCount++;
|
|
@@ -15408,10 +15561,10 @@ var PCDF = class {
|
|
|
15408
15561
|
"de": "Porsche Charging Data Format Ladevorgang",
|
|
15409
15562
|
"en": "Porsche Charging Data Format charging session"
|
|
15410
15563
|
},
|
|
15411
|
-
"
|
|
15564
|
+
"contracts": [{
|
|
15412
15565
|
"@id": data.session.idTag,
|
|
15413
15566
|
"type": data.session.idTagType
|
|
15414
|
-
},
|
|
15567
|
+
}],
|
|
15415
15568
|
"pcdf": {
|
|
15416
15569
|
"chargingSessionCounter": data.chargingSessionCounter,
|
|
15417
15570
|
"timeValid": data.timeValid,
|
|
@@ -15430,11 +15583,17 @@ var PCDF = class {
|
|
|
15430
15583
|
"EVSEs": [{
|
|
15431
15584
|
"@id": virtualEVSEId,
|
|
15432
15585
|
"description": { "en": "GraphDefined CHARGY Virtual EVSE 1" },
|
|
15433
|
-
"
|
|
15586
|
+
"energyMeters": [{
|
|
15434
15587
|
"@id": meterId,
|
|
15435
|
-
"manufacturer":
|
|
15436
|
-
|
|
15437
|
-
|
|
15588
|
+
"manufacturer": {
|
|
15589
|
+
"name": "Porsche"
|
|
15590
|
+
},
|
|
15591
|
+
"model": {
|
|
15592
|
+
"name": data.dcMeterType === 0 ? "PES DCMeter EU" : "Unknown DC Meter"
|
|
15593
|
+
},
|
|
15594
|
+
"firmware": {
|
|
15595
|
+
"checksum": data.softwareChecksum
|
|
15596
|
+
},
|
|
15438
15597
|
"signatureFormat": "https://open.charging.cloud/contexts/EnergyMeterSignatureFormats/PCDF+json",
|
|
15439
15598
|
"publicKeys": [{
|
|
15440
15599
|
"algorithm": "secp256r1",
|
|
@@ -15633,60 +15792,124 @@ var SAFEXML = class _SAFEXML {
|
|
|
15633
15792
|
constructor(chargy) {
|
|
15634
15793
|
this.chargy = chargy;
|
|
15635
15794
|
}
|
|
15636
|
-
static
|
|
15637
|
-
const
|
|
15638
|
-
|
|
15639
|
-
|
|
15640
|
-
|
|
15641
|
-
|
|
15642
|
-
|
|
15643
|
-
|
|
15644
|
-
|
|
15645
|
-
|
|
15646
|
-
|
|
15647
|
-
|
|
15648
|
-
|
|
15649
|
-
|
|
15650
|
-
|
|
15651
|
-
|
|
15652
|
-
|
|
15653
|
-
|
|
15654
|
-
|
|
15655
|
-
const
|
|
15656
|
-
const
|
|
15657
|
-
if (
|
|
15658
|
-
|
|
15659
|
-
|
|
15660
|
-
|
|
15661
|
-
|
|
15662
|
-
|
|
15663
|
-
|
|
15664
|
-
"@id": evseId,
|
|
15665
|
-
"description": parseDescription(evseElement),
|
|
15666
|
-
"meters": [],
|
|
15667
|
-
"connector": connector
|
|
15668
|
-
} : void 0;
|
|
15795
|
+
static ParseContainerInfos(XMLDocument, chargy) {
|
|
15796
|
+
const containerInfos = {};
|
|
15797
|
+
const chargingStationElements = getElementsByLocalName(XMLDocument, "chargingStation");
|
|
15798
|
+
if (chargingStationElements.length == 0)
|
|
15799
|
+
return containerInfos;
|
|
15800
|
+
if (chargingStationElements.length > 1) {
|
|
15801
|
+
return {
|
|
15802
|
+
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
15803
|
+
message: chargy.GetMultilanguageText("Only one chargingStation element is allowed within the given SAFE XML container!"),
|
|
15804
|
+
certainty: 0
|
|
15805
|
+
};
|
|
15806
|
+
}
|
|
15807
|
+
if (chargingStationElements[0] === void 0) {
|
|
15808
|
+
return {
|
|
15809
|
+
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
15810
|
+
message: chargy.GetMultilanguageText("The chargingStation element within the given SAFE XML container is invalid!"),
|
|
15811
|
+
certainty: 0
|
|
15812
|
+
};
|
|
15813
|
+
}
|
|
15814
|
+
const chargingStationElement = chargingStationElements[0];
|
|
15815
|
+
const chargingStationId = chargingStationElement.getAttribute("id")?.trim();
|
|
15816
|
+
if (chargingStationId === void 0 || chargingStationId.length == 0) {
|
|
15817
|
+
return {
|
|
15818
|
+
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
15819
|
+
message: chargy.GetMultilanguageText("The chargingStation identifier within the given SAFE XML container is invalid!"),
|
|
15820
|
+
certainty: 0
|
|
15821
|
+
};
|
|
15822
|
+
}
|
|
15669
15823
|
const chargingStation = {
|
|
15670
|
-
"@id": chargingStationId
|
|
15671
|
-
|
|
15672
|
-
|
|
15673
|
-
|
|
15674
|
-
|
|
15675
|
-
|
|
15676
|
-
|
|
15677
|
-
|
|
15678
|
-
|
|
15679
|
-
|
|
15680
|
-
|
|
15681
|
-
|
|
15682
|
-
"
|
|
15683
|
-
|
|
15824
|
+
"@id": chargingStationId
|
|
15825
|
+
};
|
|
15826
|
+
containerInfos.chargingStations = [chargingStation];
|
|
15827
|
+
const description = parseDescription(chargingStationElement);
|
|
15828
|
+
if (description !== void 0)
|
|
15829
|
+
chargingStation.description = description;
|
|
15830
|
+
const firmware = getDirectChildByLocalName(chargingStationElement, "firmware");
|
|
15831
|
+
if (firmware !== void 0) {
|
|
15832
|
+
chargingStation.firmware = {};
|
|
15833
|
+
const firmwareVersion = getTrimmedTextContent(getDirectChildByLocalName(firmware, "version"));
|
|
15834
|
+
if (firmwareVersion !== void 0)
|
|
15835
|
+
chargingStation.firmware.version = firmwareVersion;
|
|
15836
|
+
const firmwareChecksum = getTrimmedTextContent(getDirectChildByLocalName(firmware, "checksum"));
|
|
15837
|
+
if (firmwareChecksum !== void 0)
|
|
15838
|
+
chargingStation.firmware.checksum = firmwareChecksum;
|
|
15839
|
+
if (Object.keys(chargingStation.firmware).length === 0)
|
|
15840
|
+
delete chargingStation.firmware;
|
|
15841
|
+
}
|
|
15842
|
+
const geoLocationElement = getDirectChildByLocalName(chargingStationElement, "geoLocation");
|
|
15843
|
+
if (geoLocationElement !== void 0) {
|
|
15844
|
+
const latitude = Number.parseFloat(getTrimmedTextContent(getDirectChildByLocalName(geoLocationElement, "latitude")) ?? "");
|
|
15845
|
+
const longitude = Number.parseFloat(getTrimmedTextContent(getDirectChildByLocalName(geoLocationElement, "longitude")) ?? "");
|
|
15846
|
+
const geoLocation = Number.isFinite(latitude) && Number.isFinite(longitude) ? { lat: latitude, lng: longitude } : void 0;
|
|
15847
|
+
if (geoLocation !== void 0)
|
|
15848
|
+
chargingStation.geoLocation = geoLocation;
|
|
15849
|
+
}
|
|
15850
|
+
const evseElements = getElementsByLocalName(chargingStationElement, "EVSE");
|
|
15851
|
+
if (evseElements.length > 1) {
|
|
15852
|
+
return {
|
|
15853
|
+
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
15854
|
+
message: chargy.GetMultilanguageText("Only one EVSE element is allowed within the given SAFE XML chargingStation element!"),
|
|
15855
|
+
certainty: 0
|
|
15856
|
+
};
|
|
15857
|
+
}
|
|
15858
|
+
if (evseElements[0] === void 0) {
|
|
15859
|
+
return {
|
|
15860
|
+
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
15861
|
+
message: chargy.GetMultilanguageText("The EVSE element within the given SAFE XML chargingStation element is invalid!"),
|
|
15862
|
+
certainty: 0
|
|
15863
|
+
};
|
|
15864
|
+
}
|
|
15865
|
+
const evseElement = evseElements[0];
|
|
15866
|
+
const evseId = evseElement.getAttribute("id")?.trim();
|
|
15867
|
+
if (evseId !== void 0 && evseId.length > 0) {
|
|
15868
|
+
const evse = {
|
|
15869
|
+
"@id": evseId
|
|
15870
|
+
};
|
|
15871
|
+
chargingStation.EVSEs = [evse];
|
|
15872
|
+
const evseDescription = parseDescription(evseElement);
|
|
15873
|
+
if (evseDescription !== void 0)
|
|
15874
|
+
evse.description = evseDescription;
|
|
15875
|
+
const connectorElements = getElementsByLocalName(evseElement, "connector");
|
|
15876
|
+
if (connectorElements.length > 1) {
|
|
15877
|
+
return {
|
|
15878
|
+
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
15879
|
+
message: chargy.GetMultilanguageText("Only one connector element is allowed within the given SAFE XML EVSE element!"),
|
|
15880
|
+
certainty: 0
|
|
15881
|
+
};
|
|
15882
|
+
}
|
|
15883
|
+
if (connectorElements[0] === void 0) {
|
|
15884
|
+
return {
|
|
15885
|
+
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
15886
|
+
message: chargy.GetMultilanguageText("The connector element within the given SAFE XML EVSE element is invalid!"),
|
|
15887
|
+
certainty: 0
|
|
15888
|
+
};
|
|
15889
|
+
}
|
|
15890
|
+
const connectorElement = connectorElements[0];
|
|
15891
|
+
const connector = {};
|
|
15892
|
+
const connectorId = connectorElement.getAttribute("id")?.trim();
|
|
15893
|
+
if (connectorId != null && connectorId.length > 0)
|
|
15894
|
+
connector["@id"] = connectorId;
|
|
15895
|
+
const connectorType = getTrimmedTextContent(getDirectChildByLocalName(connectorElement, "type"));
|
|
15896
|
+
if (connectorType !== void 0 && connectorType.length > 0)
|
|
15897
|
+
connector.type = connectorType;
|
|
15898
|
+
if (Object.keys(connector).length > 0)
|
|
15899
|
+
evse.connectors = [connector];
|
|
15900
|
+
}
|
|
15901
|
+
return containerInfos;
|
|
15684
15902
|
}
|
|
15685
15903
|
//#region tryToParseSAFEXML(XMLDocument)
|
|
15686
15904
|
async tryToParseSAFEXML(XMLDocument) {
|
|
15687
15905
|
try {
|
|
15688
15906
|
if (XMLDocument.documentElement.nodeName === "values" || XMLDocument.documentElement.localName === "values") {
|
|
15689
|
-
const safeXMLContext = _SAFEXML.
|
|
15907
|
+
const safeXMLContext = _SAFEXML.ParseContainerInfos(
|
|
15908
|
+
XMLDocument,
|
|
15909
|
+
this.chargy
|
|
15910
|
+
);
|
|
15911
|
+
if (isISessionCryptoResult1(safeXMLContext))
|
|
15912
|
+
return safeXMLContext;
|
|
15690
15913
|
const signedDataValues = new Array();
|
|
15691
15914
|
let commonSignedDataFormat = "";
|
|
15692
15915
|
let commonSignedDataEncoding = "";
|
|
@@ -16082,10 +16305,10 @@ var ChargeIT = class {
|
|
|
16082
16305
|
CTR["@id"] = lastMeterValue["transactionId"];
|
|
16083
16306
|
CTR.begin = this.chargy.moment.unix(firstMeterValue["measuredValue"]["timestampLocal"]["timestamp"]).utc().format();
|
|
16084
16307
|
CTR.end = this.chargy.moment.unix(lastMeterValue["measuredValue"]["timestampLocal"]["timestamp"]).utc().format();
|
|
16085
|
-
CTR.
|
|
16308
|
+
CTR.contracts = [{
|
|
16086
16309
|
"@id": firstMeterValue["contract"]["id"],
|
|
16087
16310
|
"@context": firstMeterValue["contract"]["type"]
|
|
16088
|
-
};
|
|
16311
|
+
}];
|
|
16089
16312
|
CTR.chargingStationOperators = [{
|
|
16090
16313
|
"@id": "chargeITmobilityCSO",
|
|
16091
16314
|
"description": { "de": "chargeIT mobility GmbH - Charging Station Operator Services" },
|
|
@@ -16143,7 +16366,9 @@ var ChargeIT = class {
|
|
|
16143
16366
|
// "description": {
|
|
16144
16367
|
// "de": "GraphDefined Charging Station - CI-Tests Pool 3 / Station A"
|
|
16145
16368
|
// },
|
|
16146
|
-
"
|
|
16369
|
+
"firmware": {
|
|
16370
|
+
"version": firstMeterValue["chargePoint"]["softwareVersion"]
|
|
16371
|
+
},
|
|
16147
16372
|
"geoLocation": { "lat": asNumber(geoLocation["lat"]) ?? 0, "lng": asNumber(geoLocation["lon"]) ?? 0 },
|
|
16148
16373
|
"address": {
|
|
16149
16374
|
"street": asString(address["street"]),
|
|
@@ -16158,22 +16383,32 @@ var ChargeIT = class {
|
|
|
16158
16383
|
// "de": "GraphDefined EVSE - CI-Tests Pool 3 / Station A / EVSE 1"
|
|
16159
16384
|
// },
|
|
16160
16385
|
// "connectors": [{ }],
|
|
16161
|
-
"
|
|
16386
|
+
"energyMeters": [
|
|
16162
16387
|
{
|
|
16163
16388
|
"@id": firstMeterValue["meterInfo"]["meterId"],
|
|
16164
|
-
"manufacturer":
|
|
16165
|
-
|
|
16166
|
-
|
|
16167
|
-
|
|
16168
|
-
|
|
16389
|
+
"manufacturer": {
|
|
16390
|
+
"name": firstMeterValue["meterInfo"]["manufacturer"],
|
|
16391
|
+
"contact": {
|
|
16392
|
+
"web": "https://www.emh-metering.de"
|
|
16393
|
+
}
|
|
16394
|
+
},
|
|
16395
|
+
"model": {
|
|
16396
|
+
"name": firstMeterValue["meterInfo"]["type"]
|
|
16397
|
+
},
|
|
16398
|
+
"hardware": {
|
|
16399
|
+
"revision": "1.0"
|
|
16400
|
+
},
|
|
16401
|
+
"firmware": {
|
|
16402
|
+
"version": firstMeterValue["meterInfo"]["firmwareVersion"]
|
|
16403
|
+
},
|
|
16169
16404
|
"signatureFormat": "https://open.charging.cloud/contexts/EnergyMeterSignatureFormats/EMHCrypt01",
|
|
16170
16405
|
"publicKeys": [
|
|
16171
16406
|
{
|
|
16172
16407
|
"algorithm": "secp192r1",
|
|
16173
16408
|
"format": "DER",
|
|
16174
16409
|
"encoding": "hex",
|
|
16175
|
-
"value": firstMeterValue["meterInfo"]["publicKey"].startsWith("04") ? firstMeterValue["meterInfo"]["publicKey"] : "04" + firstMeterValue["meterInfo"]["publicKey"]
|
|
16176
|
-
"signatures":
|
|
16410
|
+
"value": firstMeterValue["meterInfo"]["publicKey"].startsWith("04") ? firstMeterValue["meterInfo"]["publicKey"] : "04" + firstMeterValue["meterInfo"]["publicKey"]
|
|
16411
|
+
//"signatures": firstMeterValue["meterInfo"]["publicKeySignatures"]
|
|
16177
16412
|
}
|
|
16178
16413
|
]
|
|
16179
16414
|
}
|
|
@@ -16482,10 +16717,10 @@ var ChargeIT = class {
|
|
|
16482
16717
|
"value": "042313b9e469612b4ca06981bfdecb226e234632b01d84b6a814f63a114b7762c34ddce2e6853395b7a0f87275f63ffe3c",
|
|
16483
16718
|
"signatures": [
|
|
16484
16719
|
{
|
|
16485
|
-
"
|
|
16720
|
+
"@id": "...",
|
|
16486
16721
|
"algorithm": "secp192r1",
|
|
16487
16722
|
"format": "DER",
|
|
16488
|
-
"value": "
|
|
16723
|
+
"value": "..."
|
|
16489
16724
|
}
|
|
16490
16725
|
]
|
|
16491
16726
|
},
|
|
@@ -16544,7 +16779,7 @@ var ChargeIT = class {
|
|
|
16544
16779
|
// "de": "GraphDefined EVSE - CI-Tests Pool 3 / Station A / EVSE 1"
|
|
16545
16780
|
// },
|
|
16546
16781
|
//"connectors": [ ],
|
|
16547
|
-
"
|
|
16782
|
+
"energyMeters": []
|
|
16548
16783
|
}
|
|
16549
16784
|
]
|
|
16550
16785
|
}
|
|
@@ -16566,11 +16801,15 @@ var ChargeIT = class {
|
|
|
16566
16801
|
return new Alfen(this.chargy).TryToParseALFENFormat(
|
|
16567
16802
|
signedMeterValues.map((value) => asString(asJSONObject(value)?.["payload"]) ?? ""),
|
|
16568
16803
|
{
|
|
16569
|
-
|
|
16570
|
-
|
|
16804
|
+
chargingStations: [{
|
|
16805
|
+
"@id": "?",
|
|
16571
16806
|
geoLocation: { "lat": geoLocation_lat, "lng": geoLocation_lon },
|
|
16572
|
-
address: { "street": address_street, "postalCode": address_zipCode, "city": address_town, "country": address_country }
|
|
16573
|
-
|
|
16807
|
+
address: { "street": address_street, "postalCode": address_zipCode, "city": address_town, "country": address_country },
|
|
16808
|
+
EVSEs: [{
|
|
16809
|
+
"@id": evseId,
|
|
16810
|
+
energyMeters: []
|
|
16811
|
+
}]
|
|
16812
|
+
}]
|
|
16574
16813
|
}
|
|
16575
16814
|
);
|
|
16576
16815
|
}
|
|
@@ -16578,11 +16817,15 @@ var ChargeIT = class {
|
|
|
16578
16817
|
return new Alfen(this.chargy).TryToParseALFENFormat(
|
|
16579
16818
|
signedMeterValues.map((value) => asString(asJSONObject(value)?.["payload"]) ?? ""),
|
|
16580
16819
|
{
|
|
16581
|
-
|
|
16582
|
-
|
|
16820
|
+
chargingStations: [{
|
|
16821
|
+
"@id": "?",
|
|
16583
16822
|
geoLocation: { "lat": geoLocation_lat, "lng": geoLocation_lon },
|
|
16584
|
-
address: { "street": address_street, "postalCode": address_zipCode, "city": address_town, "country": address_country }
|
|
16585
|
-
|
|
16823
|
+
address: { "street": address_street, "postalCode": address_zipCode, "city": address_town, "country": address_country },
|
|
16824
|
+
EVSEs: [{
|
|
16825
|
+
"@id": evseId,
|
|
16826
|
+
energyMeters: []
|
|
16827
|
+
}]
|
|
16828
|
+
}]
|
|
16586
16829
|
}
|
|
16587
16830
|
);
|
|
16588
16831
|
if (signedMeterValueContext === oldChargeITMeterValueFormat)
|
|
@@ -16657,7 +16900,6 @@ var ChargeIT = class {
|
|
|
16657
16900
|
const connectorInfo_type = connectorInfo?.["type"];
|
|
16658
16901
|
const connectorInfo_losses = connectorInfo?.["losses"];
|
|
16659
16902
|
const chargingTariffs = SomeJSON["chargingTariffs"];
|
|
16660
|
-
const chargingPeriods = SomeJSON["chargingPeriods"];
|
|
16661
16903
|
const totalCosts = asJSONObject(SomeJSON["totalCosts"]);
|
|
16662
16904
|
const totalCosts_total = totalCosts?.["total"];
|
|
16663
16905
|
const totalCosts_currency = totalCosts?.["currency"];
|
|
@@ -16850,10 +17092,10 @@ var ChargeIT = class {
|
|
|
16850
17092
|
"value": "042313b9e469612b4ca06981bfdecb226e234632b01d84b6a814f63a114b7762c34ddce2e6853395b7a0f87275f63ffe3c",
|
|
16851
17093
|
"signatures": [
|
|
16852
17094
|
{
|
|
16853
|
-
"
|
|
17095
|
+
"@id": "...",
|
|
16854
17096
|
"algorithm": "secp192r1",
|
|
16855
17097
|
"format": "DER",
|
|
16856
|
-
"value": "
|
|
17098
|
+
"value": "..."
|
|
16857
17099
|
}
|
|
16858
17100
|
]
|
|
16859
17101
|
},
|
|
@@ -16915,7 +17157,7 @@ var ChargeIT = class {
|
|
|
16915
17157
|
// "de": "GraphDefined EVSE - CI-Tests Pool 3 / Station A / EVSE 1"
|
|
16916
17158
|
// },
|
|
16917
17159
|
//"connectors": [ ],
|
|
16918
|
-
"
|
|
17160
|
+
"energyMeters": []
|
|
16919
17161
|
}
|
|
16920
17162
|
]
|
|
16921
17163
|
}
|
|
@@ -16932,31 +17174,31 @@ var ChargeIT = class {
|
|
|
16932
17174
|
return new Alfen(this.chargy).TryToParseALFENFormat(
|
|
16933
17175
|
signedMeterValues.map((value) => asString(asJSONObject(value)?.["payload"]) ?? ""),
|
|
16934
17176
|
{
|
|
16935
|
-
chargingSession: {
|
|
16936
|
-
|
|
16937
|
-
},
|
|
16938
|
-
EVSEId:
|
|
16939
|
-
chargingStation: {
|
|
16940
|
-
|
|
16941
|
-
|
|
16942
|
-
|
|
16943
|
-
|
|
16944
|
-
|
|
16945
|
-
|
|
16946
|
-
|
|
16947
|
-
|
|
16948
|
-
|
|
16949
|
-
|
|
16950
|
-
|
|
16951
|
-
|
|
16952
|
-
|
|
16953
|
-
|
|
16954
|
-
},
|
|
16955
|
-
energyMeter:
|
|
16956
|
-
connector:
|
|
16957
|
-
chargingTariffs,
|
|
16958
|
-
chargingPeriods,
|
|
16959
|
-
totalCosts
|
|
17177
|
+
// chargingSession: {
|
|
17178
|
+
// "@id": chargingSessionId
|
|
17179
|
+
// },
|
|
17180
|
+
// EVSEId: evseId,
|
|
17181
|
+
// chargingStation: {
|
|
17182
|
+
// manufacturer: chargingStation_manufacturer,
|
|
17183
|
+
// type: chargingStation_type,
|
|
17184
|
+
// serialNumber: chargingStation_serialNumber,
|
|
17185
|
+
// firmwareVersion: chargingStation_controllerSoftwareVersion,
|
|
17186
|
+
// legalCompliance: {
|
|
17187
|
+
// conformity: [{
|
|
17188
|
+
// freeText: chargingStation_compliance
|
|
17189
|
+
// }],
|
|
17190
|
+
// calibration: [{
|
|
17191
|
+
// freeText: chargingStation_calibration
|
|
17192
|
+
// }]
|
|
17193
|
+
// },
|
|
17194
|
+
// geoLocation: { "lat": geoLocation_lat, "lng": geoLocation_lon },
|
|
17195
|
+
// address: { "street": address_street, "postalCode": address_zipCode, "city": address_town, "country": address_country }
|
|
17196
|
+
// },
|
|
17197
|
+
// energyMeter: meterInfo,
|
|
17198
|
+
// connector: connectorInfo,
|
|
17199
|
+
// chargingTariffs: chargingTariffs,
|
|
17200
|
+
// chargingPeriods: chargingPeriods,
|
|
17201
|
+
// totalCosts: totalCosts
|
|
16960
17202
|
}
|
|
16961
17203
|
);
|
|
16962
17204
|
}
|
|
@@ -17088,12 +17330,18 @@ var ChargePoint = class {
|
|
|
17088
17330
|
"address": asJSONObject(SomeJSON["address"]),
|
|
17089
17331
|
"EVSEs": [{
|
|
17090
17332
|
"@id": evseId,
|
|
17091
|
-
"
|
|
17333
|
+
"energyMeters": [{
|
|
17092
17334
|
"@id": meterSerial,
|
|
17093
|
-
"manufacturer":
|
|
17094
|
-
|
|
17095
|
-
|
|
17096
|
-
|
|
17335
|
+
"manufacturer": {
|
|
17336
|
+
"name": "Carlo Gavazzi",
|
|
17337
|
+
"contact": {
|
|
17338
|
+
"web": "https://www.gavazziautomation.com"
|
|
17339
|
+
}
|
|
17340
|
+
},
|
|
17341
|
+
"model": {
|
|
17342
|
+
"name": "EM340-DIN.AV2.3.X.S1.X",
|
|
17343
|
+
"url": "https://www.gavazziautomation.com/fileadmin/images/PIM/DATASHEET/ENG/EM340_DS_ENG.pdf"
|
|
17344
|
+
}
|
|
17097
17345
|
// "signatureFormat": "https://open.charging.cloud/contexts/EnergyMeterSignatureFormats/EMHCrypt01",
|
|
17098
17346
|
// "publicKeys": [
|
|
17099
17347
|
// {
|
|
@@ -17248,12 +17496,18 @@ var ChargePoint = class {
|
|
|
17248
17496
|
"address": asJSONObject(SomeJSON["address"]),
|
|
17249
17497
|
"EVSEs": [{
|
|
17250
17498
|
"@id": evseId,
|
|
17251
|
-
"
|
|
17499
|
+
"energyMeters": [{
|
|
17252
17500
|
"@id": meterSerial,
|
|
17253
|
-
"manufacturer":
|
|
17254
|
-
|
|
17255
|
-
|
|
17256
|
-
|
|
17501
|
+
"manufacturer": {
|
|
17502
|
+
"name": "Carlo Gavazzi",
|
|
17503
|
+
"contact": {
|
|
17504
|
+
"web": "https://www.gavazziautomation.com"
|
|
17505
|
+
}
|
|
17506
|
+
},
|
|
17507
|
+
"model": {
|
|
17508
|
+
"name": "EM340-DIN.AV2.3.X.S1.X",
|
|
17509
|
+
"url": "https://www.gavazziautomation.com/fileadmin/images/PIM/DATASHEET/ENG/EM340_DS_ENG.pdf"
|
|
17510
|
+
},
|
|
17257
17511
|
"signatureFormat": "https://open.charging.cloud/contexts/EnergyMeterSignatureFormats/EMHCrypt01",
|
|
17258
17512
|
"signatureInfos": {
|
|
17259
17513
|
"hash": "SHA256",
|
|
@@ -17265,7 +17519,8 @@ var ChargePoint = class {
|
|
|
17265
17519
|
"publicKeys": [{
|
|
17266
17520
|
"algorithm": "secp224k1",
|
|
17267
17521
|
"format": "DER",
|
|
17268
|
-
"encoding": "hex"
|
|
17522
|
+
"encoding": "hex",
|
|
17523
|
+
"value": "..."
|
|
17269
17524
|
}]
|
|
17270
17525
|
}]
|
|
17271
17526
|
}]
|
|
@@ -17367,7 +17622,7 @@ var ChargePointCrypt01 = class extends ACrypt {
|
|
|
17367
17622
|
s: ASN1Signature.s.toString(16)
|
|
17368
17623
|
};
|
|
17369
17624
|
}
|
|
17370
|
-
const publicKeyId = chargingSession.EVSEId
|
|
17625
|
+
const publicKeyId = chargingSession.EVSEId?.replace(/:/g, "").replace(/-/g, "_");
|
|
17371
17626
|
const publicKeys = [];
|
|
17372
17627
|
if (chargingSession.ctr.publicKeys != null) {
|
|
17373
17628
|
for (const publicKeyInfo of chargingSession.ctr.publicKeys) {
|
|
@@ -17398,8 +17653,8 @@ var ChargePointCrypt01 = class extends ACrypt {
|
|
|
17398
17653
|
sha225Value = sha225Value ?? (BigInt("0x" + await sha256(plainText)) >> BigInt(31)).toString(16);
|
|
17399
17654
|
sessionResult = this.curve224k1.validate(
|
|
17400
17655
|
BigInt("0x" + sha225Value),
|
|
17401
|
-
BigInt("0x" +
|
|
17402
|
-
BigInt("0x" +
|
|
17656
|
+
BigInt("0x" + chargingSession.signature.r),
|
|
17657
|
+
BigInt("0x" + chargingSession.signature.s),
|
|
17403
17658
|
[
|
|
17404
17659
|
BigInt("0x" + publicKey.value.slice(2, 58)),
|
|
17405
17660
|
BigInt("0x" + publicKey.value.slice(58, 114))
|
|
@@ -17447,7 +17702,7 @@ var ChargePointCrypt01 = class extends ACrypt {
|
|
|
17447
17702
|
}
|
|
17448
17703
|
}
|
|
17449
17704
|
}
|
|
17450
|
-
for (const measurement of chargingSession.measurements) {
|
|
17705
|
+
for (const measurement of chargingSession.measurements ?? []) {
|
|
17451
17706
|
measurement.chargingSession = chargingSession;
|
|
17452
17707
|
if (measurement.values.length > 1) {
|
|
17453
17708
|
for (const measurementValue of measurement.values) {
|
|
@@ -17590,8 +17845,8 @@ var ChargePointCrypt01 = class extends ACrypt {
|
|
|
17590
17845
|
signatureDiv.innerHTML = await this.chargy.CheckMeterPublicKeySignature(
|
|
17591
17846
|
measurementValue.measurement.chargingSession.chargingStation,
|
|
17592
17847
|
measurementValue.measurement.chargingSession.EVSE,
|
|
17593
|
-
measurementValue.measurement.chargingSession.EVSE?.
|
|
17594
|
-
measurementValue.measurement.chargingSession.EVSE?.
|
|
17848
|
+
measurementValue.measurement.chargingSession.EVSE?.energyMeters?.[0],
|
|
17849
|
+
measurementValue.measurement.chargingSession.EVSE?.energyMeters?.[0]?.publicKeys?.[0],
|
|
17595
17850
|
signature
|
|
17596
17851
|
);
|
|
17597
17852
|
} catch {
|
|
@@ -17604,7 +17859,7 @@ var ChargePointCrypt01 = class extends ACrypt {
|
|
|
17604
17859
|
getArrayLikeElement(SignatureExpectedDiv.parentElement.children, 0, "Missing expected signature header").innerHTML = "Erwartete Signatur (secrrct.sign, rs, hex)";
|
|
17605
17860
|
}
|
|
17606
17861
|
if (typeof chargingSession.signature != "string")
|
|
17607
|
-
SignatureExpectedDiv.innerHTML = "r: " + (chargingSession.signature.r
|
|
17862
|
+
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(" ") ?? "");
|
|
17608
17863
|
else if (chargingSession.signature)
|
|
17609
17864
|
SignatureExpectedDiv.innerHTML = chargingSession.signature.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "-";
|
|
17610
17865
|
}
|
|
@@ -17645,7 +17900,8 @@ var IChargeTransparencyRecord_exports = {};
|
|
|
17645
17900
|
__export(IChargeTransparencyRecord_exports, {
|
|
17646
17901
|
CloneCTR: () => CloneCTR,
|
|
17647
17902
|
IsAChargeTransparencyRecord: () => IsAChargeTransparencyRecord,
|
|
17648
|
-
IsASessionCryptoResult: () => IsASessionCryptoResult
|
|
17903
|
+
IsASessionCryptoResult: () => IsASessionCryptoResult,
|
|
17904
|
+
toSessionVerificationResults: () => toSessionVerificationResults
|
|
17649
17905
|
});
|
|
17650
17906
|
function IsAChargeTransparencyRecord(data) {
|
|
17651
17907
|
if (!isMandatoryJSONObject(data))
|
|
@@ -17663,7 +17919,7 @@ function CloneCTR(CTR) {
|
|
|
17663
17919
|
const clonedCTR = JSON.parse(JSON.stringify(CTR));
|
|
17664
17920
|
if (clonedCTR.chargingSessions) {
|
|
17665
17921
|
for (const session of clonedCTR.chargingSessions) {
|
|
17666
|
-
for (const measurement of session.measurements) {
|
|
17922
|
+
for (const measurement of session.measurements ?? []) {
|
|
17667
17923
|
for (const value of measurement.values) {
|
|
17668
17924
|
if (typeof value.value === "string" || typeof value.value === "number")
|
|
17669
17925
|
value.value = new Decimal(value.value);
|
|
@@ -17673,6 +17929,16 @@ function CloneCTR(CTR) {
|
|
|
17673
17929
|
}
|
|
17674
17930
|
return clonedCTR;
|
|
17675
17931
|
}
|
|
17932
|
+
function toSessionVerificationResults(CTR, noRecordsMessage = { "en": "No charge transparency records found!" }) {
|
|
17933
|
+
const verificationResults = (CTR.chargingSessions ?? []).map((session) => session.verificationResult).filter(isISessionCryptoResult1);
|
|
17934
|
+
if (verificationResults.length > 0)
|
|
17935
|
+
return verificationResults;
|
|
17936
|
+
return {
|
|
17937
|
+
status: "Unvalidated" /* Unvalidated */,
|
|
17938
|
+
message: noRecordsMessage,
|
|
17939
|
+
certainty: 0
|
|
17940
|
+
};
|
|
17941
|
+
}
|
|
17676
17942
|
|
|
17677
17943
|
// src/interfaces/IChargeTransparencyLiveLink.ts
|
|
17678
17944
|
var IChargeTransparencyLiveLink_exports = {};
|
|
@@ -17703,44 +17969,12 @@ function isTransport(data) {
|
|
|
17703
17969
|
function IsAChargeTransparencyLiveLink(data) {
|
|
17704
17970
|
if (!isMandatoryJSONObject(data))
|
|
17705
17971
|
return false;
|
|
17706
|
-
return data["@context"] === ChargeTransparencyLiveLinkContext && (data["timestamp"] === void 0 || data["timestamp"] === null || typeof data["timestamp"] === "string") && (data["description"] === void 0 ||
|
|
17972
|
+
return data["@context"] === ChargeTransparencyLiveLinkContext && (data["timestamp"] === void 0 || data["timestamp"] === null || typeof data["timestamp"] === "string") && (data["description"] === void 0 || isI18NString(data["description"])) && (data["imageURLs"] === void 0 || Array.isArray(data["imageURLs"]) && data["imageURLs"].every((value) => typeof value === "string")) && (data["geoLocation"] === void 0 || isGeoLocation(data["geoLocation"])) && (data["connector"] === void 0 || isConnector(data["connector"])) && (data["transports"] === void 0 || Array.isArray(data["transports"]) && data["transports"].every(isTransport)) && (data["signatures"] === void 0 || Array.isArray(data["signatures"]));
|
|
17707
17973
|
}
|
|
17708
17974
|
function isTOTPConfig(data) {
|
|
17709
17975
|
return isObject(data) && typeof data["initialSharedSecret"] === "string" && typeof data["timeStep"] === "number";
|
|
17710
17976
|
}
|
|
17711
17977
|
|
|
17712
|
-
// src/interfaces/IPublicKeyInfo.ts
|
|
17713
|
-
var IPublicKeyInfo_exports = {};
|
|
17714
|
-
__export(IPublicKeyInfo_exports, {
|
|
17715
|
-
IsAPublicKeyInfo: () => IsAPublicKeyInfo,
|
|
17716
|
-
IsAPublicKeyLookup: () => IsAPublicKeyLookup
|
|
17717
|
-
});
|
|
17718
|
-
function IsAPublicKeyLookup(data) {
|
|
17719
|
-
if (!isMandatoryJSONObject(data))
|
|
17720
|
-
return false;
|
|
17721
|
-
return Array.isArray(data["publicKeys"]);
|
|
17722
|
-
}
|
|
17723
|
-
function IsAPublicKeyInfo(data) {
|
|
17724
|
-
if (!isMandatoryJSONObject(data))
|
|
17725
|
-
return false;
|
|
17726
|
-
if (!isStringOrStringArray(data["@context"])) return false;
|
|
17727
|
-
if (!isString(data["value"])) return false;
|
|
17728
|
-
if (!isStringOrOIDInfo(data["algorithm"])) return false;
|
|
17729
|
-
if (data["certainty"] !== void 0 && (typeof data["certainty"] !== "number" || !Number.isFinite(data["certainty"]))) {
|
|
17730
|
-
return false;
|
|
17731
|
-
}
|
|
17732
|
-
if (data["type"] !== void 0 && !isStringOrOIDInfo(data["type"])) {
|
|
17733
|
-
return false;
|
|
17734
|
-
}
|
|
17735
|
-
if (data["encoding"] !== void 0 && typeof data["encoding"] !== "string") {
|
|
17736
|
-
return false;
|
|
17737
|
-
}
|
|
17738
|
-
if (data["signatures"] !== void 0 && !Array.isArray(data["signatures"])) {
|
|
17739
|
-
return false;
|
|
17740
|
-
}
|
|
17741
|
-
return true;
|
|
17742
|
-
}
|
|
17743
|
-
|
|
17744
17978
|
// src/qrCodeReader.ts
|
|
17745
17979
|
var import_buffer = __toESM(require_buffer2());
|
|
17746
17980
|
function isRecord(value) {
|
|
@@ -18237,13 +18471,10 @@ var Chargy = class {
|
|
|
18237
18471
|
}
|
|
18238
18472
|
return this.CompleteMultilanguageText(parameterizedText, Text.replace("%p", String(Parameter)));
|
|
18239
18473
|
}
|
|
18240
|
-
|
|
18474
|
+
GetLocalizedText(data) {
|
|
18241
18475
|
if (data == null)
|
|
18242
18476
|
return void 0;
|
|
18243
|
-
|
|
18244
|
-
if (bestLanguage == null)
|
|
18245
|
-
return void 0;
|
|
18246
|
-
return data[bestLanguage];
|
|
18477
|
+
return this.FindBestMultilanguageText(data);
|
|
18247
18478
|
}
|
|
18248
18479
|
//#endregion
|
|
18249
18480
|
//#region GetDevices...
|
|
@@ -18295,11 +18526,13 @@ var Chargy = class {
|
|
|
18295
18526
|
"@id": evse["@id"],
|
|
18296
18527
|
"description": evse.description,
|
|
18297
18528
|
"sockets": evseView["sockets"],
|
|
18298
|
-
"
|
|
18529
|
+
"energyMeter": {
|
|
18299
18530
|
"@id": meter["@id"],
|
|
18300
18531
|
"vendor": meterView["vendor"],
|
|
18301
18532
|
"model": meter.model,
|
|
18302
|
-
"
|
|
18533
|
+
"firmware": {
|
|
18534
|
+
"version": meter.firmware?.version
|
|
18535
|
+
},
|
|
18303
18536
|
"signatureFormat": meter.signatureFormat,
|
|
18304
18537
|
"publicKey": {
|
|
18305
18538
|
"algorithm": publicKey.algorithm,
|
|
@@ -18617,11 +18850,12 @@ var Chargy = class {
|
|
|
18617
18850
|
//#endregion
|
|
18618
18851
|
//#region DetectAndConvertContentFormat(FileInfos)
|
|
18619
18852
|
async DetectAndConvertContentFormat(FileInfos) {
|
|
18620
|
-
if (FileInfos.length == 0)
|
|
18621
|
-
|
|
18622
|
-
|
|
18623
|
-
|
|
18624
|
-
|
|
18853
|
+
if (FileInfos.length == 0)
|
|
18854
|
+
return {
|
|
18855
|
+
status: "NoChargeTransparencyRecordsFound" /* NoChargeTransparencyRecordsFound */,
|
|
18856
|
+
message: this.GetMultilanguageText("No charge transparency records found!"),
|
|
18857
|
+
certainty: 0
|
|
18858
|
+
};
|
|
18625
18859
|
let expandedFiles = new Array();
|
|
18626
18860
|
const processedFiles = new Array();
|
|
18627
18861
|
if (FileInfos.length > 0) {
|
|
@@ -18794,42 +19028,40 @@ var Chargy = class {
|
|
|
18794
19028
|
} else if (textContent.startsWith("{") && textContent.endsWith("}")) {
|
|
18795
19029
|
try {
|
|
18796
19030
|
const JSONContent = JSON.parse(textContent);
|
|
18797
|
-
if (typeof JSONContent !== "object" || JSONContent
|
|
18798
|
-
throw new Error("Parsed JSON content is not
|
|
18799
|
-
|
|
18800
|
-
|
|
18801
|
-
|
|
18802
|
-
|
|
19031
|
+
if (JSONContent === null || typeof JSONContent !== "object" || !isMandatoryJSONObject(JSONContent))
|
|
19032
|
+
throw new Error("Parsed JSON content is not a JSON object!");
|
|
19033
|
+
const JSONContext = JSONContent["@context"];
|
|
19034
|
+
if (IsAChargeTransparencyLiveLink(JSONContent)) {
|
|
19035
|
+
JSONContent.timestamp ??= (/* @__PURE__ */ new Date()).toISOString();
|
|
19036
|
+
processedFile.result = JSONContent;
|
|
19037
|
+
} else if (isMandatoryString(JSONContext)) {
|
|
19038
|
+
if (JSONContext.startsWith("https://open.charging.cloud/contexts/CTR+json"))
|
|
18803
19039
|
processedFile.result = JSONContent;
|
|
18804
|
-
|
|
18805
|
-
|
|
18806
|
-
|
|
18807
|
-
|
|
18808
|
-
processedFile.result = JSONContent;
|
|
18809
|
-
else if (JSONContext.startsWith("https://www.lichtblick.de/contexts/charging-station-json") || JSONContext.startsWith("https://www.eneco.com/contexts/charging-station-json") || JSONContext.startsWith("https://www.chargeit-mobility.com/contexts/charging-station-json")) {
|
|
18810
|
-
processedFile.result = new ChargeIT(this).TryToParseChargeITContainerFormat(JSONContent);
|
|
18811
|
-
}
|
|
18812
|
-
} else {
|
|
18813
|
-
const results = [
|
|
18814
|
-
new ChargeIT(this).TryToParseChargeITContainerFormat(JSONContent),
|
|
18815
|
-
new ChargePoint(this).TryToParseChargepointFormat(JSONContent),
|
|
18816
|
-
await new OCPI(this).tryToParseOCPIFormat(JSONContent)
|
|
18817
|
-
];
|
|
18818
|
-
const filteredResults = results.filter((ctr) => {
|
|
18819
|
-
return isISessionCryptoResult1(ctr);
|
|
18820
|
-
});
|
|
18821
|
-
const sortedResults = filteredResults.sort((ctr1, ctr2) => {
|
|
18822
|
-
if (ctr1.certainty > ctr2.certainty) {
|
|
18823
|
-
return -1;
|
|
18824
|
-
}
|
|
18825
|
-
if (ctr1.certainty < ctr2.certainty) {
|
|
18826
|
-
return 1;
|
|
18827
|
-
}
|
|
18828
|
-
return 0;
|
|
18829
|
-
});
|
|
18830
|
-
if (sortedResults.length >= 1 && sortedResults[0])
|
|
18831
|
-
processedFile.result = sortedResults[0];
|
|
19040
|
+
else if (JSONContext.startsWith("https://open.charging.cloud/contexts/publicKey+json"))
|
|
19041
|
+
processedFile.result = JSONContent;
|
|
19042
|
+
else if (JSONContext.startsWith("https://www.lichtblick.de/contexts/charging-station-json") || JSONContext.startsWith("https://www.eneco.com/contexts/charging-station-json") || JSONContext.startsWith("https://www.chargeit-mobility.com/contexts/charging-station-json")) {
|
|
19043
|
+
processedFile.result = new ChargeIT(this).TryToParseChargeITContainerFormat(JSONContent);
|
|
18832
19044
|
}
|
|
19045
|
+
} else {
|
|
19046
|
+
const results = [
|
|
19047
|
+
new ChargeIT(this).TryToParseChargeITContainerFormat(JSONContent),
|
|
19048
|
+
new ChargePoint(this).TryToParseChargepointFormat(JSONContent),
|
|
19049
|
+
await new OCPI(this).tryToParseOCPIFormat(JSONContent)
|
|
19050
|
+
];
|
|
19051
|
+
const filteredResults = results.filter((ctr) => {
|
|
19052
|
+
return isISessionCryptoResult1(ctr);
|
|
19053
|
+
});
|
|
19054
|
+
const sortedResults = filteredResults.sort((ctr1, ctr2) => {
|
|
19055
|
+
if (ctr1.certainty > ctr2.certainty) {
|
|
19056
|
+
return -1;
|
|
19057
|
+
}
|
|
19058
|
+
if (ctr1.certainty < ctr2.certainty) {
|
|
19059
|
+
return 1;
|
|
19060
|
+
}
|
|
19061
|
+
return 0;
|
|
19062
|
+
});
|
|
19063
|
+
if (sortedResults.length >= 1 && sortedResults[0])
|
|
19064
|
+
processedFile.result = sortedResults[0];
|
|
18833
19065
|
}
|
|
18834
19066
|
} catch (exception) {
|
|
18835
19067
|
processedFile.result = {
|
|
@@ -18873,7 +19105,7 @@ var Chargy = class {
|
|
|
18873
19105
|
if (processedFileResult.end != null && processedFileResult.end.length > 0 && (mergedCTR.end == null || mergedCTR.end.length === 0 || mergedCTR.end < processedFileResult.end))
|
|
18874
19106
|
mergedCTR.end = processedFileResult.end;
|
|
18875
19107
|
mergedCTR.description ??= processedFileResult.description;
|
|
18876
|
-
mergedCTR.
|
|
19108
|
+
mergedCTR.contracts ??= processedFileResult.contracts;
|
|
18877
19109
|
if (!mergedCTR.chargingStationOperators)
|
|
18878
19110
|
mergedCTR.chargingStationOperators = processedFileResult.chargingStationOperators;
|
|
18879
19111
|
else if (processedFileResult.chargingStationOperators)
|
|
@@ -18904,7 +19136,7 @@ var Chargy = class {
|
|
|
18904
19136
|
else if (processedFileResult.mediationServices)
|
|
18905
19137
|
for (const mediationService of processedFileResult.mediationServices)
|
|
18906
19138
|
mergedCTR.mediationServices.push(mediationService);
|
|
18907
|
-
} else if (
|
|
19139
|
+
} else if (IsAPublicKey(processedFileResult)) {
|
|
18908
19140
|
mergedCTR.publicKeys ??= new Array();
|
|
18909
19141
|
mergedCTR.publicKeys.push(processedFileResult);
|
|
18910
19142
|
} else if (IsAPublicKeyLookup(processedFileResult)) {
|
|
@@ -18952,11 +19184,11 @@ var Chargy = class {
|
|
|
18952
19184
|
if (chargingPool.chargingStations) {
|
|
18953
19185
|
for (const chargingStation of chargingPool.chargingStations) {
|
|
18954
19186
|
this.chargingStations.push(chargingStation);
|
|
18955
|
-
for (const EVSE of chargingStation.EVSEs) {
|
|
19187
|
+
for (const EVSE of chargingStation.EVSEs ?? []) {
|
|
18956
19188
|
EVSE.chargingStation = chargingStation;
|
|
18957
19189
|
EVSE.chargingStationId = chargingStation["@id"];
|
|
18958
19190
|
this.EVSEs.push(EVSE);
|
|
18959
|
-
for (const meter of EVSE.
|
|
19191
|
+
for (const meter of EVSE.energyMeters ?? []) {
|
|
18960
19192
|
meter.EVSE = EVSE;
|
|
18961
19193
|
meter.EVSEId = EVSE["@id"];
|
|
18962
19194
|
meter.chargingStation = chargingStation;
|
|
@@ -18971,11 +19203,11 @@ var Chargy = class {
|
|
|
18971
19203
|
if (chargingStationOperator.chargingStations) {
|
|
18972
19204
|
for (const chargingStation of chargingStationOperator.chargingStations) {
|
|
18973
19205
|
this.chargingStations.push(chargingStation);
|
|
18974
|
-
for (const EVSE of chargingStation.EVSEs) {
|
|
19206
|
+
for (const EVSE of chargingStation.EVSEs ?? []) {
|
|
18975
19207
|
EVSE.chargingStation = chargingStation;
|
|
18976
19208
|
EVSE.chargingStationId = chargingStation["@id"];
|
|
18977
19209
|
this.EVSEs.push(EVSE);
|
|
18978
|
-
for (const meter of EVSE.
|
|
19210
|
+
for (const meter of EVSE.energyMeters ?? []) {
|
|
18979
19211
|
meter.EVSE = EVSE;
|
|
18980
19212
|
meter.EVSEId = EVSE["@id"];
|
|
18981
19213
|
meter.chargingStation = chargingStation;
|
|
@@ -18988,7 +19220,7 @@ var Chargy = class {
|
|
|
18988
19220
|
if (chargingStationOperator.EVSEs) {
|
|
18989
19221
|
for (const EVSE of chargingStationOperator.EVSEs) {
|
|
18990
19222
|
this.EVSEs.push(EVSE);
|
|
18991
|
-
for (const meter of EVSE.
|
|
19223
|
+
for (const meter of EVSE.energyMeters ?? []) {
|
|
18992
19224
|
meter.EVSE = EVSE;
|
|
18993
19225
|
meter.EVSEId = EVSE["@id"];
|
|
18994
19226
|
this.meters.push(meter);
|
|
@@ -19003,11 +19235,11 @@ var Chargy = class {
|
|
|
19003
19235
|
if (chargingPool.chargingStations) {
|
|
19004
19236
|
for (const chargingStation of chargingPool.chargingStations) {
|
|
19005
19237
|
this.chargingStations.push(chargingStation);
|
|
19006
|
-
for (const EVSE of chargingStation.EVSEs) {
|
|
19238
|
+
for (const EVSE of chargingStation.EVSEs ?? []) {
|
|
19007
19239
|
EVSE.chargingStation = chargingStation;
|
|
19008
19240
|
EVSE.chargingStationId = chargingStation["@id"];
|
|
19009
19241
|
this.EVSEs.push(EVSE);
|
|
19010
|
-
for (const meter of EVSE.
|
|
19242
|
+
for (const meter of EVSE.energyMeters ?? []) {
|
|
19011
19243
|
meter.EVSE = EVSE;
|
|
19012
19244
|
meter.EVSEId = EVSE["@id"];
|
|
19013
19245
|
meter.chargingStation = chargingStation;
|
|
@@ -19022,11 +19254,11 @@ var Chargy = class {
|
|
|
19022
19254
|
if (this.internalCTR.chargingStations) {
|
|
19023
19255
|
for (const chargingStation of this.internalCTR.chargingStations) {
|
|
19024
19256
|
this.chargingStations.push(chargingStation);
|
|
19025
|
-
for (const EVSE of chargingStation.EVSEs) {
|
|
19257
|
+
for (const EVSE of chargingStation.EVSEs ?? []) {
|
|
19026
19258
|
EVSE.chargingStation = chargingStation;
|
|
19027
19259
|
EVSE.chargingStationId = chargingStation["@id"];
|
|
19028
19260
|
this.EVSEs.push(EVSE);
|
|
19029
|
-
for (const meter of EVSE.
|
|
19261
|
+
for (const meter of EVSE.energyMeters ?? []) {
|
|
19030
19262
|
meter.EVSE = EVSE;
|
|
19031
19263
|
meter.EVSEId = EVSE["@id"];
|
|
19032
19264
|
meter.chargingStation = chargingStation;
|
|
@@ -19034,8 +19266,8 @@ var Chargy = class {
|
|
|
19034
19266
|
this.meters.push(meter);
|
|
19035
19267
|
}
|
|
19036
19268
|
}
|
|
19037
|
-
if (chargingStation.
|
|
19038
|
-
for (const meter of chargingStation.
|
|
19269
|
+
if (chargingStation.energyMeters) {
|
|
19270
|
+
for (const meter of chargingStation.energyMeters ?? []) {
|
|
19039
19271
|
meter.chargingStation = chargingStation;
|
|
19040
19272
|
meter.chargingStationId = chargingStation["@id"];
|
|
19041
19273
|
this.meters.push(meter);
|
|
@@ -19062,7 +19294,7 @@ var Chargy = class {
|
|
|
19062
19294
|
//#endregion
|
|
19063
19295
|
//#region (private) hasInplausibleChargingSessionTotalEnergyMeasurement(chargingSession)
|
|
19064
19296
|
hasInplausibleChargingSessionTotalEnergyMeasurement(chargingSession) {
|
|
19065
|
-
for (const measurement of chargingSession.measurements) {
|
|
19297
|
+
for (const measurement of chargingSession.measurements ?? []) {
|
|
19066
19298
|
if (measurement.name !== "ENERGY_TOTAL" || measurement.values.length < 2) {
|
|
19067
19299
|
continue;
|
|
19068
19300
|
}
|
|
@@ -19222,7 +19454,7 @@ var Chargy = class {
|
|
|
19222
19454
|
if (ctr.end != null && ctr.end.length > 0 && (mergedCTR.end == null || mergedCTR.end.length === 0 || mergedCTR.end < ctr.end))
|
|
19223
19455
|
mergedCTR.end = ctr.end;
|
|
19224
19456
|
mergedCTR.description ??= ctr.description;
|
|
19225
|
-
mergedCTR.
|
|
19457
|
+
mergedCTR.contracts ??= ctr.contracts;
|
|
19226
19458
|
if (!mergedCTR.chargingStationOperators)
|
|
19227
19459
|
mergedCTR.chargingStationOperators = ctr.chargingStationOperators;
|
|
19228
19460
|
else if (ctr.chargingStationOperators)
|
|
@@ -19257,18 +19489,6 @@ var Chargy = class {
|
|
|
19257
19489
|
return mergedCTR;
|
|
19258
19490
|
}
|
|
19259
19491
|
};
|
|
19260
|
-
|
|
19261
|
-
// src/verificationResults.ts
|
|
19262
|
-
function toSessionVerificationResults(CTR, noRecordsMessage = { "en": "No charge transparency records found!" }) {
|
|
19263
|
-
const verificationResults = (CTR.chargingSessions ?? []).map((session) => session.verificationResult).filter(isISessionCryptoResult1);
|
|
19264
|
-
if (verificationResults.length > 0)
|
|
19265
|
-
return verificationResults;
|
|
19266
|
-
return {
|
|
19267
|
-
status: "Unvalidated" /* Unvalidated */,
|
|
19268
|
-
message: noRecordsMessage,
|
|
19269
|
-
certainty: 0
|
|
19270
|
-
};
|
|
19271
|
-
}
|
|
19272
19492
|
/*! Bundled license information:
|
|
19273
19493
|
|
|
19274
19494
|
ieee754/index.js:
|
|
@@ -19283,6 +19503,6 @@ buffer/index.js:
|
|
|
19283
19503
|
*)
|
|
19284
19504
|
*/
|
|
19285
19505
|
|
|
19286
|
-
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,
|
|
19506
|
+
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, IsAPublicKey, IsAPublicKeyLookup, IsAPublicKeySignature, IsAPublicKeyXY, IsASessionCryptoResult, IsNullOrEmpty, JSONSignatureVerificationStatus, MENNEKES_EDL40_OBIS, MENNEKES_EDL40_XMLNS, Mennekes, MennekesCrypt01, OBIS2Hex, OBIS2MeasurementName, OBIS_RegExpr, OCMF, OCMFTransactionTypes, OCMFv1_x, OCPI, OIDInfo, 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, base64ToBytes, buf2hex, buildMennekesSignatureData, bytesToBase64, 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, isEncodedValue, isGeoLocation, isI18NString, isICryptoResult, isIFileInfo, isISessionCryptoResult1, isISessionCryptoResult2, isJSONLDObject, isMandatoryArrayOfStrings, isMandatoryBoolean, isMandatoryDecimal, isMandatoryJSONArray, isMandatoryJSONObject, isMandatoryNumber, isMandatoryString, isMandatoryURL, isOIDInfo, isObject, isOptionalArrayOfStrings, isOptionalDecimal, isOptionalJSONArray, isOptionalJSONArrayError, isOptionalJSONArrayOk, isOptionalJSONObject, isOptionalNumber, isOptionalString, isOptionalStringArray, isOptionalStringOrOIDInfo, isOptionalURL, isPCDFText, isPublicKeySubject, 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, sha256____, sha384, sha384____, sha512, sha512____, signJSONMessage, signMessage, stripPCDFControlCharacters, time2human, toArrayBuffer, toSessionVerificationResults, toUint8Array, unquotePCDFText, validatePCDFFields, verifyJSONMessageSignatureResults, verifyJSONMessageSignatures, verifyJSONSignature, verifyJSONSignatureResult, verifyPCDFDocument };
|
|
19287
19507
|
//# sourceMappingURL=index.js.map
|
|
19288
19508
|
//# sourceMappingURL=index.js.map
|