@open-charging-cloud/chargy-core 0.6.4 → 0.7.1
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 +1010 -800
- 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 +14 -12
- 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 +113 -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 +1010 -800
- 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,124 +9755,11 @@ 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, {
|
|
9875
9761
|
CreateError: () => CreateError,
|
|
9762
|
+
CreateWarning: () => CreateWarning,
|
|
9876
9763
|
CryptoAlgorithms: () => CryptoAlgorithms,
|
|
9877
9764
|
CryptoHashAlgorithms: () => CryptoHashAlgorithms,
|
|
9878
9765
|
DayOfWeek: () => DayOfWeek,
|
|
@@ -9881,7 +9768,7 @@ __export(chargyInterfaces_exports, {
|
|
|
9881
9768
|
IECCurves: () => IECCurves,
|
|
9882
9769
|
IEncoding: () => IEncoding,
|
|
9883
9770
|
InformationRelevance: () => InformationRelevance,
|
|
9884
|
-
|
|
9771
|
+
OIDInfo: () => OIDInfo,
|
|
9885
9772
|
SessionVerificationResult: () => SessionVerificationResult,
|
|
9886
9773
|
SignatureFormats: () => SignatureFormats,
|
|
9887
9774
|
VerificationResult: () => VerificationResult,
|
|
@@ -9889,23 +9776,9 @@ __export(chargyInterfaces_exports, {
|
|
|
9889
9776
|
isGeoLocation: () => isGeoLocation,
|
|
9890
9777
|
isICryptoResult: () => isICryptoResult,
|
|
9891
9778
|
isIFileInfo: () => isIFileInfo,
|
|
9892
|
-
isIPublicKeyXY: () => isIPublicKeyXY,
|
|
9893
9779
|
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
|
|
9780
|
+
isISessionCryptoResult2: () => isISessionCryptoResult2
|
|
9902
9781
|
});
|
|
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
9782
|
function isGeoLocation(data) {
|
|
9910
9783
|
if (!isObject(data))
|
|
9911
9784
|
return false;
|
|
@@ -9913,26 +9786,6 @@ function isGeoLocation(data) {
|
|
|
9913
9786
|
const longitude = data["lng"];
|
|
9914
9787
|
return (latitude === void 0 || typeof latitude === "number") && (longitude === void 0 || typeof longitude === "number");
|
|
9915
9788
|
}
|
|
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
9789
|
var IECCurves = /* @__PURE__ */ ((IECCurves2) => {
|
|
9937
9790
|
IECCurves2["secp192r1"] = "secp192r1";
|
|
9938
9791
|
IECCurves2["secp224k1"] = "secp224k1";
|
|
@@ -9947,11 +9800,6 @@ var IEncoding = /* @__PURE__ */ ((IEncoding2) => {
|
|
|
9947
9800
|
IEncoding2["base64"] = "base64";
|
|
9948
9801
|
return IEncoding2;
|
|
9949
9802
|
})(IEncoding || {});
|
|
9950
|
-
var PublicKeyFormats = /* @__PURE__ */ ((PublicKeyFormats2) => {
|
|
9951
|
-
PublicKeyFormats2["DER"] = "DER";
|
|
9952
|
-
PublicKeyFormats2["XY"] = "XY";
|
|
9953
|
-
return PublicKeyFormats2;
|
|
9954
|
-
})(PublicKeyFormats || {});
|
|
9955
9803
|
var SignatureFormats = /* @__PURE__ */ ((SignatureFormats2) => {
|
|
9956
9804
|
SignatureFormats2["DER"] = "DER";
|
|
9957
9805
|
SignatureFormats2["RS"] = "RS";
|
|
@@ -9987,6 +9835,12 @@ var ErrorLevel = /* @__PURE__ */ ((ErrorLevel2) => {
|
|
|
9987
9835
|
ErrorLevel2["high"] = "high";
|
|
9988
9836
|
return ErrorLevel2;
|
|
9989
9837
|
})(ErrorLevel || {});
|
|
9838
|
+
function CreateWarning(message, level = "low" /* low */) {
|
|
9839
|
+
return {
|
|
9840
|
+
level,
|
|
9841
|
+
message
|
|
9842
|
+
};
|
|
9843
|
+
}
|
|
9990
9844
|
function CreateError(message, level = "high" /* high */) {
|
|
9991
9845
|
return {
|
|
9992
9846
|
level,
|
|
@@ -10073,12 +9927,19 @@ var DayOfWeek = /* @__PURE__ */ ((DayOfWeek2) => {
|
|
|
10073
9927
|
DayOfWeek2[DayOfWeek2["Saturday"] = 6] = "Saturday";
|
|
10074
9928
|
return DayOfWeek2;
|
|
10075
9929
|
})(DayOfWeek || {});
|
|
9930
|
+
function OIDInfo(data) {
|
|
9931
|
+
if (typeof data === "string")
|
|
9932
|
+
return data;
|
|
9933
|
+
if (isOIDInfo(data))
|
|
9934
|
+
return data.name;
|
|
9935
|
+
return "";
|
|
9936
|
+
}
|
|
10076
9937
|
function isJSONLDObject(value) {
|
|
10077
9938
|
if (typeof value !== "object" || value === null) {
|
|
10078
9939
|
return false;
|
|
10079
9940
|
}
|
|
10080
9941
|
const obj = value;
|
|
10081
|
-
return typeof obj["@context"] === "string";
|
|
9942
|
+
return typeof obj["@context"] === "string" || Array.isArray(obj["@context"]);
|
|
10082
9943
|
}
|
|
10083
9944
|
function toArrayBuffer(data) {
|
|
10084
9945
|
if (data instanceof ArrayBuffer)
|
|
@@ -10538,36 +10399,6 @@ function pad(text, paddingValue) {
|
|
|
10538
10399
|
text ??= "";
|
|
10539
10400
|
return (text + Array(2 * paddingValue).join("0")).substring(0, 2 * paddingValue);
|
|
10540
10401
|
}
|
|
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
10402
|
function asJSONObject(value) {
|
|
10572
10403
|
return isMandatoryJSONObject(value) ? value : void 0;
|
|
10573
10404
|
}
|
|
@@ -10664,6 +10495,48 @@ function parseNumber(value) {
|
|
|
10664
10495
|
}
|
|
10665
10496
|
return null;
|
|
10666
10497
|
}
|
|
10498
|
+
function isObject(data) {
|
|
10499
|
+
return typeof data === "object" && data !== null;
|
|
10500
|
+
}
|
|
10501
|
+
function isI18NString(data) {
|
|
10502
|
+
return isObject(data) && Object.values(data).every((value) => typeof value === "string");
|
|
10503
|
+
}
|
|
10504
|
+
function isString(value) {
|
|
10505
|
+
return typeof value === "string";
|
|
10506
|
+
}
|
|
10507
|
+
function isStringArray(value) {
|
|
10508
|
+
return Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
10509
|
+
}
|
|
10510
|
+
function isStringOrStringArray(value) {
|
|
10511
|
+
return typeof value === "string" || isStringArray(value);
|
|
10512
|
+
}
|
|
10513
|
+
function isOIDInfo(data) {
|
|
10514
|
+
if (!isObject(data))
|
|
10515
|
+
return false;
|
|
10516
|
+
return typeof data["oid"] === "string" && typeof data["name"] === "string";
|
|
10517
|
+
}
|
|
10518
|
+
function isStringOrOIDInfo(value) {
|
|
10519
|
+
return typeof value === "string" || isOIDInfo(value);
|
|
10520
|
+
}
|
|
10521
|
+
function isOptionalStringArray(data) {
|
|
10522
|
+
return data === void 0 || Array.isArray(data) && data.every(isString);
|
|
10523
|
+
}
|
|
10524
|
+
function isOptionalStringOrOIDInfo(data) {
|
|
10525
|
+
return data === void 0 || isStringOrOIDInfo(data);
|
|
10526
|
+
}
|
|
10527
|
+
function isEncodedValue(data) {
|
|
10528
|
+
if (isString(data))
|
|
10529
|
+
return true;
|
|
10530
|
+
if (!isMandatoryJSONObject(data))
|
|
10531
|
+
return false;
|
|
10532
|
+
if (!isString(data["value"]))
|
|
10533
|
+
return false;
|
|
10534
|
+
if (!isOptionalString(data["format"]))
|
|
10535
|
+
return false;
|
|
10536
|
+
if (!isOptionalString(data["encoding"]))
|
|
10537
|
+
return false;
|
|
10538
|
+
return true;
|
|
10539
|
+
}
|
|
10667
10540
|
function InformationRelevanceToString(InfoRelevance) {
|
|
10668
10541
|
switch (InfoRelevance) {
|
|
10669
10542
|
case "Ignored" /* Ignored */:
|
|
@@ -10724,6 +10597,187 @@ function _jsonPrettyPrinter(value, indentLevel, path, keyLookup) {
|
|
|
10724
10597
|
html += String(value);
|
|
10725
10598
|
return html;
|
|
10726
10599
|
}
|
|
10600
|
+
function base64ToBytes(value) {
|
|
10601
|
+
if (typeof Buffer !== "undefined")
|
|
10602
|
+
return Uint8Array.from(Buffer.from(value, "base64"));
|
|
10603
|
+
const binary = atob(value);
|
|
10604
|
+
const bytes = new Uint8Array(binary.length);
|
|
10605
|
+
for (let i = 0; i < binary.length; i++)
|
|
10606
|
+
bytes[i] = binary.charCodeAt(i);
|
|
10607
|
+
return bytes;
|
|
10608
|
+
}
|
|
10609
|
+
function bytesToBase64(bytes) {
|
|
10610
|
+
if (typeof Buffer !== "undefined")
|
|
10611
|
+
return Buffer.from(bytes).toString("base64");
|
|
10612
|
+
let binary = "";
|
|
10613
|
+
for (const byte of bytes)
|
|
10614
|
+
binary += String.fromCharCode(byte);
|
|
10615
|
+
return btoa(binary);
|
|
10616
|
+
}
|
|
10617
|
+
function cleanHex(hex) {
|
|
10618
|
+
return hex.replace(/\s+/g, "");
|
|
10619
|
+
}
|
|
10620
|
+
function hexToBytes(hex) {
|
|
10621
|
+
const cleanedHex = cleanHex(hex);
|
|
10622
|
+
if (cleanedHex.length % 2 !== 0)
|
|
10623
|
+
throw new Error("Hex strings must have even length!");
|
|
10624
|
+
if (!/^[0-9a-fA-F]*$/.test(cleanedHex))
|
|
10625
|
+
throw new Error("Invalid hexadecimal string!");
|
|
10626
|
+
const bytes = new Uint8Array(cleanedHex.length / 2);
|
|
10627
|
+
for (let index = 0; index < cleanedHex.length; index += 2)
|
|
10628
|
+
bytes[index / 2] = Number.parseInt(cleanedHex.substring(index, index + 2), 16);
|
|
10629
|
+
return bytes;
|
|
10630
|
+
}
|
|
10631
|
+
function bytesToHex(bytes) {
|
|
10632
|
+
return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
10633
|
+
}
|
|
10634
|
+
async function sha256(message) {
|
|
10635
|
+
return bytesToHex(await sha256____(message));
|
|
10636
|
+
}
|
|
10637
|
+
async function sha384(message) {
|
|
10638
|
+
return bytesToHex(await sha384____(message));
|
|
10639
|
+
}
|
|
10640
|
+
async function sha512(message) {
|
|
10641
|
+
return bytesToHex(await sha512____(message));
|
|
10642
|
+
}
|
|
10643
|
+
async function sha256____(message) {
|
|
10644
|
+
let hashBuffer;
|
|
10645
|
+
if (typeof message === "string")
|
|
10646
|
+
hashBuffer = await crypto.subtle.digest("SHA-256", Buffer.from(message, "utf8"));
|
|
10647
|
+
else
|
|
10648
|
+
hashBuffer = await crypto.subtle.digest("SHA-256", message);
|
|
10649
|
+
return new Uint8Array(hashBuffer);
|
|
10650
|
+
}
|
|
10651
|
+
async function sha384____(message) {
|
|
10652
|
+
let hashBuffer;
|
|
10653
|
+
if (typeof message === "string")
|
|
10654
|
+
hashBuffer = await crypto.subtle.digest("SHA-384", Buffer.from(message, "utf8"));
|
|
10655
|
+
else
|
|
10656
|
+
hashBuffer = await crypto.subtle.digest("SHA-384", message);
|
|
10657
|
+
return new Uint8Array(hashBuffer);
|
|
10658
|
+
}
|
|
10659
|
+
async function sha512____(message) {
|
|
10660
|
+
let hashBuffer;
|
|
10661
|
+
if (typeof message === "string")
|
|
10662
|
+
hashBuffer = await crypto.subtle.digest("SHA-512", Buffer.from(message, "utf8"));
|
|
10663
|
+
else
|
|
10664
|
+
hashBuffer = await crypto.subtle.digest("SHA-512", message);
|
|
10665
|
+
return new Uint8Array(hashBuffer);
|
|
10666
|
+
}
|
|
10667
|
+
|
|
10668
|
+
// src/interfaces/secp224k1.ts
|
|
10669
|
+
var secp224k1 = class {
|
|
10670
|
+
// Pcurve = 2**224 - 2**32 - 2**12 - 2**11 - 2**9 - 2**7 - 2**4 - 2**1 - 1 or
|
|
10671
|
+
// FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFE56D
|
|
10672
|
+
Zero = BigInt("0");
|
|
10673
|
+
One = BigInt("1");
|
|
10674
|
+
Two = BigInt("2");
|
|
10675
|
+
Three = BigInt("3");
|
|
10676
|
+
Pcurve = BigInt("26959946667150639794667015087019630673637144422540572481099315275117");
|
|
10677
|
+
// The proven prime
|
|
10678
|
+
N = BigInt("0x010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7");
|
|
10679
|
+
// Number of points in the field
|
|
10680
|
+
Acurve = BigInt(0);
|
|
10681
|
+
// Defined on the elliptic curve. y^2 = x^3 + Acurve * x + 5
|
|
10682
|
+
Gx = BigInt("0xA1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C");
|
|
10683
|
+
Gy = BigInt("0x7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5");
|
|
10684
|
+
GPoint = [this.Gx, this.Gy];
|
|
10685
|
+
// This is our generator point. Trillions of dif ones possible
|
|
10686
|
+
Sign(hash, RandomNumber, privateKey) {
|
|
10687
|
+
const RandSignPoint = this.ECmultiply(this.GPoint, RandomNumber);
|
|
10688
|
+
if (RandSignPoint.length >= 1 && RandSignPoint[0] != null) {
|
|
10689
|
+
const r = this.modulo(RandSignPoint[0], this.N);
|
|
10690
|
+
const s = this.modulo((hash + r * privateKey) * this.modInv(RandomNumber, this.N), this.N);
|
|
10691
|
+
return [r, s];
|
|
10692
|
+
}
|
|
10693
|
+
return null;
|
|
10694
|
+
}
|
|
10695
|
+
validate(hash, signatureR, signatureS, PublicKey) {
|
|
10696
|
+
if (signatureR == this.Zero || signatureR >= this.N)
|
|
10697
|
+
throw new Error("Invalid R");
|
|
10698
|
+
if (signatureS == this.Zero || signatureS >= this.N)
|
|
10699
|
+
throw new Error("Invalid S");
|
|
10700
|
+
const w = this.modInv(signatureS, this.N);
|
|
10701
|
+
const u1 = this.ECmultiply(this.GPoint, this.modulo(w * hash, this.N));
|
|
10702
|
+
const u2 = this.ECmultiply(PublicKey, this.modulo(w * signatureR, this.N));
|
|
10703
|
+
const validation = this.ECadd(u1, u2);
|
|
10704
|
+
return validation[0] == signatureR;
|
|
10705
|
+
}
|
|
10706
|
+
modulo(n, m) {
|
|
10707
|
+
return (n % m + m) % m;
|
|
10708
|
+
}
|
|
10709
|
+
zfill(s) {
|
|
10710
|
+
while (s.length < 56) {
|
|
10711
|
+
s = "0" + s;
|
|
10712
|
+
}
|
|
10713
|
+
return s;
|
|
10714
|
+
}
|
|
10715
|
+
modInv(a, n = this.Pcurve) {
|
|
10716
|
+
let lm = BigInt(1), hm = BigInt(0), high = n, low = this.modulo(a, n);
|
|
10717
|
+
while (low > 1) {
|
|
10718
|
+
const ratio = high / low, nm = hm - ratio * lm, newm = high - ratio * low;
|
|
10719
|
+
hm = lm;
|
|
10720
|
+
lm = nm;
|
|
10721
|
+
high = low;
|
|
10722
|
+
low = newm;
|
|
10723
|
+
}
|
|
10724
|
+
return this.modulo(lm, n);
|
|
10725
|
+
}
|
|
10726
|
+
ECadd(a, b) {
|
|
10727
|
+
if (a[0] != void 0 && b[0] != void 0 && a[1] != void 0 && b[1] != void 0) {
|
|
10728
|
+
const LamAdd = this.modulo((b[1] - a[1]) * this.modInv(b[0] - a[0]), this.Pcurve);
|
|
10729
|
+
const x = this.modulo(LamAdd * LamAdd - a[0] - b[0], this.Pcurve);
|
|
10730
|
+
const y = this.modulo(LamAdd * (a[0] - x) - a[1], this.Pcurve);
|
|
10731
|
+
return [x, y];
|
|
10732
|
+
}
|
|
10733
|
+
throw new Error("Invalid EC Point Addition!");
|
|
10734
|
+
}
|
|
10735
|
+
ECdouble(a) {
|
|
10736
|
+
if (a[0] != void 0 && a[1] != void 0) {
|
|
10737
|
+
const Lam = this.modulo((a[0] * a[0] * this.Three + this.Acurve) * this.modInv(a[1] * this.Two), this.Pcurve);
|
|
10738
|
+
const x = this.modulo(Lam * Lam - a[0] * this.Two, this.Pcurve);
|
|
10739
|
+
const y = this.modulo(Lam * (a[0] - x) - a[1], this.Pcurve);
|
|
10740
|
+
return [x, y];
|
|
10741
|
+
}
|
|
10742
|
+
throw new Error("Invalid EC Point Doubling!");
|
|
10743
|
+
}
|
|
10744
|
+
ECmultiply(GenPoint, ScalarHex) {
|
|
10745
|
+
if (ScalarHex == this.Zero || ScalarHex >= this.N)
|
|
10746
|
+
throw new Error("Invalid Scalar/Private Key");
|
|
10747
|
+
const ScalarBinary = ScalarHex.toString(2);
|
|
10748
|
+
let Q = GenPoint;
|
|
10749
|
+
for (let i = 1; i < ScalarBinary.length; i++) {
|
|
10750
|
+
Q = this.ECdouble(Q);
|
|
10751
|
+
if (ScalarBinary[i] === "1") {
|
|
10752
|
+
Q = this.ECadd(Q, GenPoint);
|
|
10753
|
+
}
|
|
10754
|
+
}
|
|
10755
|
+
return Q;
|
|
10756
|
+
}
|
|
10757
|
+
// uncompressed is the accumulation of both the x and y points
|
|
10758
|
+
// compressed is the public key to share in transactions
|
|
10759
|
+
// address is the public address tho whom someone can send coin
|
|
10760
|
+
PublicKeyGenerate(PrivateKey) {
|
|
10761
|
+
if (typeof PrivateKey === "number")
|
|
10762
|
+
PrivateKey = BigInt(PrivateKey);
|
|
10763
|
+
if (typeof PrivateKey === "string")
|
|
10764
|
+
PrivateKey = BigInt(PrivateKey);
|
|
10765
|
+
const publicKey = this.ECmultiply(this.GPoint, PrivateKey);
|
|
10766
|
+
if (publicKey[0] !== void 0 && publicKey[1] !== void 0) {
|
|
10767
|
+
const Px = this.zfill(publicKey[0].toString(16));
|
|
10768
|
+
const Py = this.zfill(publicKey[1].toString(16));
|
|
10769
|
+
return {
|
|
10770
|
+
x: publicKey[0],
|
|
10771
|
+
y: publicKey[1],
|
|
10772
|
+
xy: [Px, Py],
|
|
10773
|
+
uncompressed: publicKey[0].toString(16) + publicKey[1].toString(16),
|
|
10774
|
+
compressed: "04" + Px + Py,
|
|
10775
|
+
address: this.modulo(publicKey[1], this.Two) == this.One ? "03" + Px : "02" + Px
|
|
10776
|
+
};
|
|
10777
|
+
}
|
|
10778
|
+
return void 0;
|
|
10779
|
+
}
|
|
10780
|
+
};
|
|
10727
10781
|
|
|
10728
10782
|
// src/ACrypt.ts
|
|
10729
10783
|
var ACrypt = class {
|
|
@@ -10955,8 +11009,8 @@ var Alfen = class {
|
|
|
10955
11009
|
"Signature": this.bufferToHex(Signature)
|
|
10956
11010
|
});
|
|
10957
11011
|
}
|
|
10958
|
-
const evseId =
|
|
10959
|
-
const chargingStationId =
|
|
11012
|
+
const evseId = ContainerInfos.chargingStations?.[0]?.EVSEs?.[0]?.["@id"] ?? "DE*GEF*EVSE*CHARGY*1";
|
|
11013
|
+
const chargingStationId = ContainerInfos.chargingStations?.[0]?.["@id"] ?? "DE*GEF*STATION*CHARGY*1";
|
|
10960
11014
|
const chargingSessionId = asString(chargingSession?.["@id"]);
|
|
10961
11015
|
const firstDataSet = getFirstArrayElement(common.dataSets, "Missing first Alfen data set");
|
|
10962
11016
|
const lastDataSet = getLastArrayElement(common.dataSets, "Missing last Alfen data set");
|
|
@@ -10981,10 +11035,18 @@ var Alfen = class {
|
|
|
10981
11035
|
"@id": chargingStationId,
|
|
10982
11036
|
// ToDo: The container infos are not validated yet!
|
|
10983
11037
|
"description": asJSONObject(chargingStation?.["description"]),
|
|
10984
|
-
"manufacturer":
|
|
10985
|
-
|
|
10986
|
-
|
|
10987
|
-
"
|
|
11038
|
+
"manufacturer": {
|
|
11039
|
+
"name": asString(chargingStation?.["manufacturer"])
|
|
11040
|
+
},
|
|
11041
|
+
"model": {
|
|
11042
|
+
"name": asString(chargingStation?.["type"])
|
|
11043
|
+
},
|
|
11044
|
+
"hardware": {
|
|
11045
|
+
"serialNumber": asString(chargingStation?.["serialNumber"])
|
|
11046
|
+
},
|
|
11047
|
+
"firmware": {
|
|
11048
|
+
"version": asString(chargingStation?.["softwareVersion"])
|
|
11049
|
+
},
|
|
10988
11050
|
"legalCompliance": asJSONObject(chargingStation?.["legalCompliance"]),
|
|
10989
11051
|
"geoLocation": asJSONObject(chargingStation?.["geoLocation"]),
|
|
10990
11052
|
"address": asJSONObject(chargingStation?.["address"]),
|
|
@@ -10994,18 +11056,29 @@ var Alfen = class {
|
|
|
10994
11056
|
"description": asJSONObject(evse?.["description"]),
|
|
10995
11057
|
"connectors": [{
|
|
10996
11058
|
"type": asString(connector?.["type"]) ?? "",
|
|
10997
|
-
"
|
|
11059
|
+
"cable": {
|
|
11060
|
+
"length": asNumber(connector?.["cableLength"]) ?? 0,
|
|
11061
|
+
"looses": asNumber(connector?.["cableLooses"]) ?? 0
|
|
11062
|
+
}
|
|
10998
11063
|
}],
|
|
10999
|
-
"
|
|
11064
|
+
"energyMeters": [
|
|
11000
11065
|
{
|
|
11001
11066
|
"@id": common.MeterId,
|
|
11002
|
-
"manufacturer":
|
|
11003
|
-
|
|
11004
|
-
|
|
11005
|
-
|
|
11006
|
-
"
|
|
11007
|
-
|
|
11008
|
-
|
|
11067
|
+
"manufacturer": {
|
|
11068
|
+
"name": asString(energyMeter?.["manufacturer"]),
|
|
11069
|
+
"contact": { "web": asString(energyMeter?.["manufacturerURL"]) }
|
|
11070
|
+
},
|
|
11071
|
+
"model": {
|
|
11072
|
+
"name": asString(energyMeter?.["model"]),
|
|
11073
|
+
"url": asString(energyMeter?.["modelURL"])
|
|
11074
|
+
},
|
|
11075
|
+
"hardware": {
|
|
11076
|
+
"revision": asString(energyMeter?.["hardwareVersion"])
|
|
11077
|
+
},
|
|
11078
|
+
"firmware": {
|
|
11079
|
+
"version": common.AdapterFWVersion,
|
|
11080
|
+
"checksum": common.AdapterFWChecksum
|
|
11081
|
+
},
|
|
11009
11082
|
"signatureFormat": "https://open.charging.cloud/contexts/EnergyMeterSignatureFormats/AlfenCrypt01",
|
|
11010
11083
|
"publicKeys": [
|
|
11011
11084
|
{
|
|
@@ -11085,6 +11158,8 @@ var Alfen = class {
|
|
|
11085
11158
|
);
|
|
11086
11159
|
}
|
|
11087
11160
|
_CTR["status"] = "Unvalidated" /* Unvalidated */;
|
|
11161
|
+
if (ContainerInfos.warnings !== void 0)
|
|
11162
|
+
_CTR.warnings = [..._CTR.warnings ?? [], ...ContainerInfos.warnings];
|
|
11088
11163
|
return _CTR;
|
|
11089
11164
|
} catch (exception) {
|
|
11090
11165
|
return {
|
|
@@ -11105,23 +11180,21 @@ var AlfenCrypt01 = class extends ACrypt {
|
|
|
11105
11180
|
}
|
|
11106
11181
|
async VerifyChargingSession(chargingSession) {
|
|
11107
11182
|
let sessionResult = "UnknownSessionFormat" /* UnknownSessionFormat */;
|
|
11108
|
-
{
|
|
11109
|
-
|
|
11110
|
-
|
|
11111
|
-
|
|
11112
|
-
|
|
11113
|
-
|
|
11114
|
-
|
|
11115
|
-
|
|
11116
|
-
|
|
11117
|
-
|
|
11118
|
-
|
|
11119
|
-
sessionResult = "InvalidSignature" /* InvalidSignature */;
|
|
11120
|
-
}
|
|
11183
|
+
for (const measurement of chargingSession.measurements ?? []) {
|
|
11184
|
+
measurement.chargingSession = chargingSession;
|
|
11185
|
+
if (measurement.values.length > 1) {
|
|
11186
|
+
for (const measurementValue of measurement.values) {
|
|
11187
|
+
measurementValue.measurement = measurement;
|
|
11188
|
+
await this.VerifyMeasurement(measurementValue);
|
|
11189
|
+
}
|
|
11190
|
+
sessionResult = "ValidSignature" /* ValidSignature */;
|
|
11191
|
+
for (const measurementValue of measurement.values) {
|
|
11192
|
+
if (sessionResult == "ValidSignature" /* ValidSignature */ && measurementValue.result?.status != "ValidSignature" /* ValidSignature */) {
|
|
11193
|
+
sessionResult = "InvalidSignature" /* InvalidSignature */;
|
|
11121
11194
|
}
|
|
11122
|
-
}
|
|
11123
|
-
|
|
11124
|
-
|
|
11195
|
+
}
|
|
11196
|
+
} else
|
|
11197
|
+
sessionResult = "AtLeastTwoMeasurementsRequired" /* AtLeastTwoMeasurementsRequired */;
|
|
11125
11198
|
}
|
|
11126
11199
|
return {
|
|
11127
11200
|
status: sessionResult,
|
|
@@ -11151,7 +11224,7 @@ var AlfenCrypt01 = class extends ACrypt {
|
|
|
11151
11224
|
unitEncoded: SetInt8(cryptoBuffer, measurementValue.measurement.unitEncoded ?? 0, 44),
|
|
11152
11225
|
scalar: SetInt8(cryptoBuffer, measurementValue.measurement.scale, 45),
|
|
11153
11226
|
value: SetUInt64D(cryptoBuffer, measurementValue.value, 46, true),
|
|
11154
|
-
uid: SetText(cryptoBuffer, measurementValue.measurement.chargingSession?.authorizationStart["@id"] ?? "", 54),
|
|
11227
|
+
uid: SetText(cryptoBuffer, measurementValue.measurement.chargingSession?.authorizationStart?.["@id"] ?? "", 54),
|
|
11155
11228
|
sessionId: SetUInt32(cryptoBuffer, parseInt(measurementValue.measurement.chargingSession?.internalSessionId ?? ""), 74, true),
|
|
11156
11229
|
paging: SetUInt32(cryptoBuffer, measurementValue.paginationId, 78, true)
|
|
11157
11230
|
};
|
|
@@ -11189,8 +11262,8 @@ var AlfenCrypt01 = class extends ACrypt {
|
|
|
11189
11262
|
cryptoResult.hashValue = hashValue224k1;
|
|
11190
11263
|
result = this.curve224k1.validate(
|
|
11191
11264
|
hashValue224k1,
|
|
11192
|
-
BigInt(
|
|
11193
|
-
BigInt(
|
|
11265
|
+
BigInt("0x" + signatureExpected.r),
|
|
11266
|
+
BigInt("0x" + signatureExpected.s),
|
|
11194
11267
|
[
|
|
11195
11268
|
BigInt("0x" + publicKey.substring(2, 58)),
|
|
11196
11269
|
BigInt("0x" + publicKey.substring(58))
|
|
@@ -11277,7 +11350,7 @@ var AlfenCrypt01 = class extends ACrypt {
|
|
|
11277
11350
|
this.CreateLocalizedLine("Unit (encoded)", measurementValue.measurement.unitEncoded ?? 0, result.unitEncoded ?? "", infoDiv, PlainTextDiv);
|
|
11278
11351
|
this.CreateLocalizedLine("Scaling", measurementValue.measurement.scale, result.scalar ?? "", infoDiv, PlainTextDiv);
|
|
11279
11352
|
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);
|
|
11353
|
+
this.CreateLocalizedLine("Authorization", (measurementValue.measurement.chargingSession?.authorizationStart?.["@id"] ?? "") + " hex", pad(result.uid, 20), infoDiv, PlainTextDiv);
|
|
11281
11354
|
this.CreateLocalizedLine("SessionId", measurementValue.measurement.chargingSession?.["@id"] ?? "", result.sessionId ?? "", infoDiv, PlainTextDiv);
|
|
11282
11355
|
this.CreateLocalizedLine("Pagination counter", measurementValue.paginationId, result.paging ?? "", infoDiv, PlainTextDiv);
|
|
11283
11356
|
}
|
|
@@ -11304,8 +11377,8 @@ var AlfenCrypt01 = class extends ACrypt {
|
|
|
11304
11377
|
signatureDiv.innerHTML = await this.chargy.CheckMeterPublicKeySignature(
|
|
11305
11378
|
measurementValue.measurement.chargingSession?.chargingStation,
|
|
11306
11379
|
measurementValue.measurement.chargingSession?.EVSE,
|
|
11307
|
-
measurementValue.measurement.chargingSession?.EVSE?.
|
|
11308
|
-
measurementValue.measurement.chargingSession?.EVSE?.
|
|
11380
|
+
measurementValue.measurement.chargingSession?.EVSE?.energyMeters?.[0],
|
|
11381
|
+
measurementValue.measurement.chargingSession?.EVSE?.energyMeters?.[0]?.publicKeys?.[0],
|
|
11309
11382
|
signature
|
|
11310
11383
|
);
|
|
11311
11384
|
} catch {
|
|
@@ -11317,7 +11390,7 @@ var AlfenCrypt01 = class extends ACrypt {
|
|
|
11317
11390
|
if (SignatureExpectedDiv.parentElement) {
|
|
11318
11391
|
getArrayLikeElement(SignatureExpectedDiv.parentElement.children, 0, "Missing expected signature header").innerHTML = this.chargy.GetLocalizedMessage("Expected signature") + " (" + (result.signature.format ?? "") + ", hex)";
|
|
11319
11392
|
}
|
|
11320
|
-
if (result.signature.r
|
|
11393
|
+
if (result.signature.r.length > 0 && result.signature.s.length > 0) {
|
|
11321
11394
|
const signatureR = result.signature.r.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "-";
|
|
11322
11395
|
const signatureS = result.signature.s.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "-";
|
|
11323
11396
|
SignatureExpectedDiv.innerHTML = "r: " + signatureR + "<br />s: " + signatureS;
|
|
@@ -11822,7 +11895,7 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
11822
11895
|
"@context": "https://open.charging.cloud/contexts/SessionSignatureFormats/bsm-ws36a-v0+json",
|
|
11823
11896
|
"begin": firstDataSet.time,
|
|
11824
11897
|
"end": lastDataSet.time,
|
|
11825
|
-
"EVSEId": CTR.chargingStationOperators?.[0]?.["chargingStations"]?.[0]?.["EVSEs"][0]?.["@id"],
|
|
11898
|
+
"EVSEId": CTR.chargingStationOperators?.[0]?.["chargingStations"]?.[0]?.["EVSEs"]?.[0]?.["@id"],
|
|
11826
11899
|
"authorizationStart": {
|
|
11827
11900
|
"@id": common.contract_id,
|
|
11828
11901
|
"@context": common.contract_type
|
|
@@ -11929,7 +12002,7 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
11929
12002
|
{
|
|
11930
12003
|
const firstChargingSession = getFirstArrayElement(CTR.chargingSessions, "Missing first BSM charging session");
|
|
11931
12004
|
const lastChargingSession = getLastArrayElement(CTR.chargingSessions, "Missing last BSM charging session");
|
|
11932
|
-
if (CTR.begin == void 0 || CTR.begin === "" || CTR.begin > firstChargingSession.begin) {
|
|
12005
|
+
if (firstChargingSession.begin !== void 0 && (CTR.begin == void 0 || CTR.begin === "" || CTR.begin > firstChargingSession.begin)) {
|
|
11933
12006
|
CTR.begin = firstChargingSession.begin;
|
|
11934
12007
|
}
|
|
11935
12008
|
if (lastChargingSession.end !== void 0) {
|
|
@@ -11937,21 +12010,22 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
11937
12010
|
CTR.end = lastChargingSession.end;
|
|
11938
12011
|
}
|
|
11939
12012
|
}
|
|
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({
|
|
12013
|
+
CTR.contracts = [{
|
|
12014
|
+
"@id": common.contract_id,
|
|
12015
|
+
"@context": common.contract_type
|
|
12016
|
+
}];
|
|
12017
|
+
CTR.chargingStationOperators?.[0]?.chargingStations?.[0]?.EVSEs?.[0]?.energyMeters?.push({
|
|
11950
12018
|
"@id": common.meterInfo_meterId,
|
|
11951
|
-
model: common.meterInfo_type,
|
|
11952
|
-
manufacturer:
|
|
11953
|
-
|
|
11954
|
-
|
|
12019
|
+
model: { name: common.meterInfo_type },
|
|
12020
|
+
manufacturer: {
|
|
12021
|
+
name: common.meterInfo_manufacturer,
|
|
12022
|
+
contact: {
|
|
12023
|
+
web: "https://www.bzr-bauer.de"
|
|
12024
|
+
}
|
|
12025
|
+
},
|
|
12026
|
+
firmware: {
|
|
12027
|
+
version: common.meterInfo_firmwareVersion
|
|
12028
|
+
},
|
|
11955
12029
|
//hardwareVersion?: string;
|
|
11956
12030
|
signatureInfos: {
|
|
11957
12031
|
hash: "SHA256" /* SHA256 */,
|
|
@@ -11986,7 +12060,7 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
11986
12060
|
async VerifyChargingSession(chargingSession) {
|
|
11987
12061
|
let sessionResult = "UnknownSessionFormat" /* UnknownSessionFormat */;
|
|
11988
12062
|
{
|
|
11989
|
-
for (const measurement of chargingSession.measurements) {
|
|
12063
|
+
for (const measurement of chargingSession.measurements ?? []) {
|
|
11990
12064
|
measurement.chargingSession = chargingSession;
|
|
11991
12065
|
if (measurement.values.length > 1) {
|
|
11992
12066
|
for (const measurementValue of measurement.values) {
|
|
@@ -12153,13 +12227,13 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
12153
12227
|
const signatureDiv = publicKeySignatureContainer?.appendChild(document.createElement("div"));
|
|
12154
12228
|
const chargingSession = measurementValue.measurement.chargingSession;
|
|
12155
12229
|
const evse = chargingSession?.EVSE;
|
|
12156
|
-
const
|
|
12157
|
-
const publicKey =
|
|
12158
|
-
if (signatureDiv != null && chargingSession != null && evse != null &&
|
|
12230
|
+
const energyMeter = evse?.energyMeters?.at(0);
|
|
12231
|
+
const publicKey = energyMeter?.publicKeys?.at(0);
|
|
12232
|
+
if (signatureDiv != null && chargingSession != null && evse != null && energyMeter != null && publicKey != null) {
|
|
12159
12233
|
signatureDiv.innerHTML = await this.chargy.CheckMeterPublicKeySignature(
|
|
12160
12234
|
chargingSession.chargingStation,
|
|
12161
12235
|
evse,
|
|
12162
|
-
|
|
12236
|
+
energyMeter,
|
|
12163
12237
|
publicKey,
|
|
12164
12238
|
signature
|
|
12165
12239
|
);
|
|
@@ -12174,7 +12248,7 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
12174
12248
|
if (SignatureExpectedDiv.parentElement) {
|
|
12175
12249
|
getArrayLikeElement(SignatureExpectedDiv.parentElement.children, 0, "Missing expected signature header").innerHTML = "Erwartete Signatur (" + (result.signature.format ?? "") + ", hex)";
|
|
12176
12250
|
}
|
|
12177
|
-
if (result.signature.r
|
|
12251
|
+
if (result.signature.r.length > 0 && result.signature.s.length > 0)
|
|
12178
12252
|
SignatureExpectedDiv.innerHTML = "r: " + (result.signature.r.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "-") + "<br />s: " + (result.signature.s.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "-");
|
|
12179
12253
|
else if (result.signature.value != null && result.signature.value.length > 0)
|
|
12180
12254
|
SignatureExpectedDiv.innerHTML = result.signature.value.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "-";
|
|
@@ -12312,97 +12386,7 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
12312
12386
|
// //#endregion
|
|
12313
12387
|
};
|
|
12314
12388
|
|
|
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
|
|
12389
|
+
// src/interfaces/CryptoUtils.ts
|
|
12406
12390
|
var import_elliptic = __toESM(require_elliptic());
|
|
12407
12391
|
var JSONSignatureVerificationStatus = /* @__PURE__ */ ((JSONSignatureVerificationStatus2) => {
|
|
12408
12392
|
JSONSignatureVerificationStatus2["True"] = "True";
|
|
@@ -12443,7 +12427,7 @@ async function signJSONMessage(JSONMessage, KeyPairs, options) {
|
|
|
12443
12427
|
continue;
|
|
12444
12428
|
const messageJSON = cloneMessageWithoutSignatures(JSONMessage);
|
|
12445
12429
|
const plainText = canonicalJSONBytes(messageJSON);
|
|
12446
|
-
const sha256Hash = await
|
|
12430
|
+
const sha256Hash = await sha256____(plainText);
|
|
12447
12431
|
JSONMessage.signatures ??= [];
|
|
12448
12432
|
const publicKeyBytes = Uint8Array.from(KeyPair.getPublic(false, "array"));
|
|
12449
12433
|
const signature = KeyPair.sign(sha256Hash, {
|
|
@@ -12490,7 +12474,7 @@ async function verifyJSONSignatureResult(JSONMessage, signature, options) {
|
|
|
12490
12474
|
try {
|
|
12491
12475
|
const messageJSON = cloneMessageWithoutSignatures(JSONMessage);
|
|
12492
12476
|
const plainText = canonicalJSONBytes(messageJSON);
|
|
12493
|
-
sha256Hash = await
|
|
12477
|
+
sha256Hash = await sha256____(plainText);
|
|
12494
12478
|
} catch (exception) {
|
|
12495
12479
|
return verificationResult(
|
|
12496
12480
|
"InvalidCanonicalJSON" /* InvalidCanonicalJSON */,
|
|
@@ -12598,7 +12582,7 @@ function parseSignedJSONMessage(JSONMessage) {
|
|
|
12598
12582
|
};
|
|
12599
12583
|
}
|
|
12600
12584
|
}
|
|
12601
|
-
if (!
|
|
12585
|
+
if (!isMandatoryJSONObject(parsedMessage))
|
|
12602
12586
|
return {
|
|
12603
12587
|
result: verificationResult(
|
|
12604
12588
|
"InvalidJSON" /* InvalidJSON */,
|
|
@@ -12617,7 +12601,7 @@ function parseSignedJSONMessage(JSONMessage) {
|
|
|
12617
12601
|
};
|
|
12618
12602
|
}
|
|
12619
12603
|
function isJSONSignature(value) {
|
|
12620
|
-
return
|
|
12604
|
+
return isMandatoryJSONObject(value) && typeof value["publicKey"] === "string" && typeof value["publicKeyHEX"] === "string" && typeof value["signature"] === "string" && typeof value["signatureHEX"] === "string";
|
|
12621
12605
|
}
|
|
12622
12606
|
function signatureEncodingsMatch(signature) {
|
|
12623
12607
|
try {
|
|
@@ -12641,32 +12625,93 @@ function verificationResult(status, description) {
|
|
|
12641
12625
|
function isVerificationTrue(result) {
|
|
12642
12626
|
return (typeof result === "string" ? result : result.status) === "True" /* True */;
|
|
12643
12627
|
}
|
|
12644
|
-
|
|
12645
|
-
|
|
12628
|
+
var CanonicalJSONError = class extends TypeError {
|
|
12629
|
+
constructor(message) {
|
|
12630
|
+
super(message);
|
|
12631
|
+
this.name = "CanonicalJSONError";
|
|
12632
|
+
}
|
|
12633
|
+
};
|
|
12634
|
+
function canonicalJSONStringify(value) {
|
|
12635
|
+
return serializeJSONValue(value, "$", /* @__PURE__ */ new WeakSet());
|
|
12646
12636
|
}
|
|
12647
|
-
|
|
12648
|
-
|
|
12649
|
-
return new Uint8Array(digest);
|
|
12637
|
+
function canonicalJSONBytes(value) {
|
|
12638
|
+
return new TextEncoder().encode(canonicalJSONStringify(value));
|
|
12650
12639
|
}
|
|
12651
|
-
function
|
|
12652
|
-
|
|
12640
|
+
function serializeJSONValue(value, path, seen) {
|
|
12641
|
+
switch (typeof value) {
|
|
12642
|
+
case "string":
|
|
12643
|
+
return JSON.stringify(value);
|
|
12644
|
+
case "number":
|
|
12645
|
+
if (!Number.isFinite(value))
|
|
12646
|
+
throw new CanonicalJSONError(`Non-finite number at ${path} is not valid JSON.`);
|
|
12647
|
+
return JSON.stringify(value);
|
|
12648
|
+
case "boolean":
|
|
12649
|
+
return value ? "true" : "false";
|
|
12650
|
+
case "object":
|
|
12651
|
+
if (value === null)
|
|
12652
|
+
return "null";
|
|
12653
|
+
return Array.isArray(value) ? serializeJSONArray(value, path, seen) : serializeJSONObject(value, path, seen);
|
|
12654
|
+
case "bigint":
|
|
12655
|
+
throw new CanonicalJSONError(`BigInt at ${path} is not valid JSON.`);
|
|
12656
|
+
case "undefined":
|
|
12657
|
+
throw new CanonicalJSONError(`Undefined value at ${path} is not valid JSON.`);
|
|
12658
|
+
case "function":
|
|
12659
|
+
throw new CanonicalJSONError(`Function at ${path} is not valid JSON.`);
|
|
12660
|
+
case "symbol":
|
|
12661
|
+
throw new CanonicalJSONError(`Symbol at ${path} is not valid JSON.`);
|
|
12662
|
+
}
|
|
12653
12663
|
}
|
|
12654
|
-
function
|
|
12655
|
-
if (
|
|
12656
|
-
|
|
12657
|
-
|
|
12658
|
-
const
|
|
12659
|
-
for (let i = 0; i <
|
|
12660
|
-
|
|
12661
|
-
|
|
12664
|
+
function serializeJSONArray(value, path, seen) {
|
|
12665
|
+
if (seen.has(value))
|
|
12666
|
+
throw new CanonicalJSONError(`Circular reference at ${path} is not valid JSON.`);
|
|
12667
|
+
seen.add(value);
|
|
12668
|
+
const indexedKeys = /* @__PURE__ */ new Set();
|
|
12669
|
+
for (let i = 0; i < value.length; i++) {
|
|
12670
|
+
if (!Object.prototype.hasOwnProperty.call(value, i))
|
|
12671
|
+
throw new CanonicalJSONError(`Sparse array slot at ${path}[${String(i)}] is not valid JSON.`);
|
|
12672
|
+
indexedKeys.add(String(i));
|
|
12673
|
+
}
|
|
12674
|
+
for (const key of Object.keys(value)) {
|
|
12675
|
+
if (!indexedKeys.has(key))
|
|
12676
|
+
throw new CanonicalJSONError(`Non-index array property ${formatPathProperty(key)} at ${path} is not valid JSON.`);
|
|
12677
|
+
}
|
|
12678
|
+
rejectEnumerableSymbolProperties(value, path);
|
|
12679
|
+
const serializedItems = value.map(
|
|
12680
|
+
(item, index) => serializeJSONValue(item, `${path}[${String(index)}]`, seen)
|
|
12681
|
+
);
|
|
12682
|
+
seen.delete(value);
|
|
12683
|
+
return `[${serializedItems.join(",")}]`;
|
|
12662
12684
|
}
|
|
12663
|
-
function
|
|
12664
|
-
if (
|
|
12665
|
-
|
|
12666
|
-
|
|
12667
|
-
|
|
12668
|
-
|
|
12669
|
-
|
|
12685
|
+
function serializeJSONObject(value, path, seen) {
|
|
12686
|
+
if (Object.prototype.toString.call(value) !== "[object Object]")
|
|
12687
|
+
throw new CanonicalJSONError(`Unsupported object at ${path} is not valid JSON.`);
|
|
12688
|
+
if (seen.has(value))
|
|
12689
|
+
throw new CanonicalJSONError(`Circular reference at ${path} is not valid JSON.`);
|
|
12690
|
+
seen.add(value);
|
|
12691
|
+
rejectEnumerableSymbolProperties(value, path);
|
|
12692
|
+
const serializedProperties = Object.keys(value).sort(compareOrdinal).map((key) => {
|
|
12693
|
+
const serializedKey = JSON.stringify(key);
|
|
12694
|
+
const serializedValue = serializeJSONValue(
|
|
12695
|
+
value[key],
|
|
12696
|
+
`${path}${formatPathProperty(key)}`,
|
|
12697
|
+
seen
|
|
12698
|
+
);
|
|
12699
|
+
return `${serializedKey}:${serializedValue}`;
|
|
12700
|
+
});
|
|
12701
|
+
seen.delete(value);
|
|
12702
|
+
return `{${serializedProperties.join(",")}}`;
|
|
12703
|
+
}
|
|
12704
|
+
function rejectEnumerableSymbolProperties(value, path) {
|
|
12705
|
+
for (const symbol of Object.getOwnPropertySymbols(value)) {
|
|
12706
|
+
if (Object.prototype.propertyIsEnumerable.call(value, symbol))
|
|
12707
|
+
throw new CanonicalJSONError(`Symbol property at ${path} is not valid JSON.`);
|
|
12708
|
+
}
|
|
12709
|
+
}
|
|
12710
|
+
function compareOrdinal(left, right) {
|
|
12711
|
+
return left < right ? -1 : left > right ? 1 : 0;
|
|
12712
|
+
}
|
|
12713
|
+
function formatPathProperty(propertyName) {
|
|
12714
|
+
return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(propertyName) ? `.${propertyName}` : `[${JSON.stringify(propertyName)}]`;
|
|
12670
12715
|
}
|
|
12671
12716
|
|
|
12672
12717
|
// src/EMHCrypt01.ts
|
|
@@ -12681,7 +12726,7 @@ var EMHCrypt01 = class extends ACrypt {
|
|
|
12681
12726
|
async VerifyChargingSession(chargingSession) {
|
|
12682
12727
|
let sessionResult = "UnknownSessionFormat" /* UnknownSessionFormat */;
|
|
12683
12728
|
{
|
|
12684
|
-
for (const measurement of chargingSession.measurements) {
|
|
12729
|
+
for (const measurement of chargingSession.measurements ?? []) {
|
|
12685
12730
|
measurement.chargingSession = chargingSession;
|
|
12686
12731
|
if (measurement.values.length > 1) {
|
|
12687
12732
|
for (const measurementValue of measurement.values) {
|
|
@@ -12729,8 +12774,8 @@ var EMHCrypt01 = class extends ACrypt {
|
|
|
12729
12774
|
scale: SetInt8(cryptoBuffer, measurementValue.measurement.scale, 30),
|
|
12730
12775
|
value: SetUInt64D(cryptoBuffer, measurementValue.value, 31, true),
|
|
12731
12776
|
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)
|
|
12777
|
+
authorizationStart: SetText(cryptoBuffer, measurementValue.measurement.chargingSession.authorizationStart?.["@id"] ?? "", 41),
|
|
12778
|
+
authorizationStartTimestamp: SetTimestamp32(cryptoBuffer, measurementValue.measurement.chargingSession.authorizationStart?.timestamp ?? measurementValue.timestamp, 169)
|
|
12734
12779
|
};
|
|
12735
12780
|
const firstSignature = measurementValue.signatures?.[0];
|
|
12736
12781
|
if (firstSignature != null) {
|
|
@@ -12749,7 +12794,7 @@ var EMHCrypt01 = class extends ACrypt {
|
|
|
12749
12794
|
if (meter.publicKeys != null && meter.publicKeys.length > 0) {
|
|
12750
12795
|
try {
|
|
12751
12796
|
const publicKey = meter.publicKeys.at(0);
|
|
12752
|
-
cryptoResult.publicKey = publicKey?.value
|
|
12797
|
+
cryptoResult.publicKey = publicKey?.value.toLowerCase();
|
|
12753
12798
|
cryptoResult.publicKeyFormat = publicKey?.format;
|
|
12754
12799
|
cryptoResult.publicKeySignatures = publicKey?.signatures;
|
|
12755
12800
|
try {
|
|
@@ -12777,7 +12822,7 @@ var EMHCrypt01 = class extends ACrypt {
|
|
|
12777
12822
|
return {};
|
|
12778
12823
|
}
|
|
12779
12824
|
async ViewMeasurement(measurementValue, _errorDiv, introDiv, infoDiv, PlainTextDiv, HashedPlainTextDiv, PublicKeyDiv, SignatureExpectedDiv, SignatureCheckDiv) {
|
|
12780
|
-
if (measurementValue.measurement?.chargingSession?.authorizationStart
|
|
12825
|
+
if (measurementValue.measurement?.chargingSession?.authorizationStart?.timestamp === void 0) {
|
|
12781
12826
|
return new Error("Invalid measurement!");
|
|
12782
12827
|
}
|
|
12783
12828
|
const result = measurementValue.result;
|
|
@@ -12828,8 +12873,8 @@ var EMHCrypt01 = class extends ACrypt {
|
|
|
12828
12873
|
signatureDiv.innerHTML = await this.chargy.CheckMeterPublicKeySignature(
|
|
12829
12874
|
measurementValue.measurement.chargingSession.chargingStation,
|
|
12830
12875
|
measurementValue.measurement.chargingSession.EVSE,
|
|
12831
|
-
measurementValue.measurement.chargingSession.EVSE?.
|
|
12832
|
-
measurementValue.measurement.chargingSession.EVSE?.
|
|
12876
|
+
measurementValue.measurement.chargingSession.EVSE?.energyMeters?.at(0),
|
|
12877
|
+
measurementValue.measurement.chargingSession.EVSE?.energyMeters?.at(0)?.publicKeys?.at(0),
|
|
12833
12878
|
signature
|
|
12834
12879
|
);
|
|
12835
12880
|
signatureDiv.onclick = () => {
|
|
@@ -12846,7 +12891,7 @@ var EMHCrypt01 = class extends ACrypt {
|
|
|
12846
12891
|
if (SignatureExpectedDiv.parentElement) {
|
|
12847
12892
|
getArrayLikeElement(SignatureExpectedDiv.parentElement.children, 0, "Missing expected signature header").innerHTML = "Erwartete Signatur (" + (result.signature.format ?? "") + ", hex)";
|
|
12848
12893
|
}
|
|
12849
|
-
if (result.signature.r
|
|
12894
|
+
if (result.signature.r.length > 0 && result.signature.s.length > 0)
|
|
12850
12895
|
SignatureExpectedDiv.innerHTML = "r: " + (result.signature.r.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "") + "<br />s: " + (result.signature.s.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "");
|
|
12851
12896
|
else if (result.signature.value != null && result.signature.value.length > 0)
|
|
12852
12897
|
SignatureExpectedDiv.innerHTML = result.signature.value.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "-";
|
|
@@ -12917,7 +12962,7 @@ var GDFCrypt01 = class extends ACrypt {
|
|
|
12917
12962
|
async VerifyChargingSession(chargingSession) {
|
|
12918
12963
|
let sessionResult = "UnknownSessionFormat" /* UnknownSessionFormat */;
|
|
12919
12964
|
{
|
|
12920
|
-
for (const measurement of chargingSession.measurements) {
|
|
12965
|
+
for (const measurement of chargingSession.measurements ?? []) {
|
|
12921
12966
|
measurement.chargingSession = chargingSession;
|
|
12922
12967
|
if (measurement.values.length > 1) {
|
|
12923
12968
|
for (const measurementValue of measurement.values) {
|
|
@@ -12961,8 +13006,8 @@ var GDFCrypt01 = class extends ACrypt {
|
|
|
12961
13006
|
unitEncoded: SetInt8(cryptoBuffer, measurementValue.measurement.unitEncoded ?? 0, 29),
|
|
12962
13007
|
scale: SetInt8(cryptoBuffer, measurementValue.measurement.scale, 30),
|
|
12963
13008
|
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
|
|
13009
|
+
authorizationStart: SetHex(cryptoBuffer, measurementValue.measurement.chargingSession.authorizationStart?.["@id"] ?? "", 41),
|
|
13010
|
+
authorizationStartTimestamp: SetTimestamp(cryptoBuffer, measurementValue.measurement.chargingSession.authorizationStart?.timestamp, 169)
|
|
12966
13011
|
};
|
|
12967
13012
|
const firstSignature = measurementValue.signatures?.[0];
|
|
12968
13013
|
if (firstSignature != null) {
|
|
@@ -12981,7 +13026,7 @@ var GDFCrypt01 = class extends ACrypt {
|
|
|
12981
13026
|
if (meter.publicKeys != null && meter.publicKeys.length > 0) {
|
|
12982
13027
|
try {
|
|
12983
13028
|
const publicKey = meter.publicKeys.at(0);
|
|
12984
|
-
cryptoResult.publicKey = publicKey?.value
|
|
13029
|
+
cryptoResult.publicKey = publicKey?.value.toLowerCase();
|
|
12985
13030
|
cryptoResult.publicKeyFormat = publicKey?.format;
|
|
12986
13031
|
cryptoResult.publicKeySignatures = publicKey?.signatures;
|
|
12987
13032
|
try {
|
|
@@ -13009,7 +13054,7 @@ var GDFCrypt01 = class extends ACrypt {
|
|
|
13009
13054
|
return {};
|
|
13010
13055
|
}
|
|
13011
13056
|
async ViewMeasurement(measurementValue, _errorDiv, introDiv, infoDiv, PlainTextDiv, HashedPlainTextDiv, PublicKeyDiv, SignatureExpectedDiv, SignatureCheckDiv) {
|
|
13012
|
-
if (measurementValue.measurement?.chargingSession?.authorizationStart
|
|
13057
|
+
if (measurementValue.measurement?.chargingSession?.authorizationStart?.timestamp === void 0) {
|
|
13013
13058
|
return new Error("Invalid measurement!");
|
|
13014
13059
|
}
|
|
13015
13060
|
const result = measurementValue.result;
|
|
@@ -13055,8 +13100,8 @@ var GDFCrypt01 = class extends ACrypt {
|
|
|
13055
13100
|
signatureDiv.innerHTML = await this.chargy.CheckMeterPublicKeySignature(
|
|
13056
13101
|
measurementValue.measurement.chargingSession.chargingStation,
|
|
13057
13102
|
measurementValue.measurement.chargingSession.EVSE,
|
|
13058
|
-
measurementValue.measurement.chargingSession.EVSE?.
|
|
13059
|
-
measurementValue.measurement.chargingSession.EVSE?.
|
|
13103
|
+
measurementValue.measurement.chargingSession.EVSE?.energyMeters?.at(0),
|
|
13104
|
+
measurementValue.measurement.chargingSession.EVSE?.energyMeters?.at(0)?.publicKeys?.at(0),
|
|
13060
13105
|
signature
|
|
13061
13106
|
);
|
|
13062
13107
|
} catch (exception) {
|
|
@@ -13069,7 +13114,7 @@ var GDFCrypt01 = class extends ACrypt {
|
|
|
13069
13114
|
if (SignatureExpectedDiv.parentElement) {
|
|
13070
13115
|
getArrayLikeElement(SignatureExpectedDiv.parentElement.children, 0, "Missing expected signature header").innerHTML = "Erwartete Signatur (" + (result.signature.format ?? "") + ", hex)";
|
|
13071
13116
|
}
|
|
13072
|
-
if (result.signature.r
|
|
13117
|
+
if (result.signature.r.length > 0 && result.signature.s.length > 0)
|
|
13073
13118
|
SignatureExpectedDiv.innerHTML = "r: " + (result.signature.r.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "") + "<br />s: " + (result.signature.s.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "");
|
|
13074
13119
|
else if (result.signature.value != null && result.signature.value.length > 0)
|
|
13075
13120
|
SignatureExpectedDiv.innerHTML = result.signature.value.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "-";
|
|
@@ -13101,7 +13146,118 @@ var GDFCrypt01 = class extends ACrypt {
|
|
|
13101
13146
|
}
|
|
13102
13147
|
return void 0;
|
|
13103
13148
|
}
|
|
13104
|
-
};
|
|
13149
|
+
};
|
|
13150
|
+
|
|
13151
|
+
// src/interfaces/IPublicKeyInfo.ts
|
|
13152
|
+
var IPublicKeyInfo_exports = {};
|
|
13153
|
+
__export(IPublicKeyInfo_exports, {
|
|
13154
|
+
IsAPublicKey: () => IsAPublicKey,
|
|
13155
|
+
IsAPublicKeyLookup: () => IsAPublicKeyLookup,
|
|
13156
|
+
IsAPublicKeySignature: () => IsAPublicKeySignature,
|
|
13157
|
+
IsAPublicKeyXY: () => IsAPublicKeyXY,
|
|
13158
|
+
PublicKeyFormats: () => PublicKeyFormats,
|
|
13159
|
+
isPublicKeySubject: () => isPublicKeySubject
|
|
13160
|
+
});
|
|
13161
|
+
var PublicKeyFormats = /* @__PURE__ */ ((PublicKeyFormats2) => {
|
|
13162
|
+
PublicKeyFormats2["DER"] = "DER";
|
|
13163
|
+
PublicKeyFormats2["XY"] = "XY";
|
|
13164
|
+
return PublicKeyFormats2;
|
|
13165
|
+
})(PublicKeyFormats || {});
|
|
13166
|
+
function IsAPublicKeyLookup(data) {
|
|
13167
|
+
if (!isMandatoryJSONObject(data))
|
|
13168
|
+
return false;
|
|
13169
|
+
return Array.isArray(data["publicKeys"]);
|
|
13170
|
+
}
|
|
13171
|
+
function IsAPublicKey(data) {
|
|
13172
|
+
if (!isMandatoryJSONObject(data))
|
|
13173
|
+
return false;
|
|
13174
|
+
if (data["@context"] !== void 0 && !isStringOrStringArray(data["@context"])) {
|
|
13175
|
+
return false;
|
|
13176
|
+
}
|
|
13177
|
+
if (!isPublicKeySubject(data["subject"]))
|
|
13178
|
+
return false;
|
|
13179
|
+
if (data["value"] !== void 0 && !isString(data["value"])) {
|
|
13180
|
+
return false;
|
|
13181
|
+
}
|
|
13182
|
+
if (data["value"] === void 0 && (data["x"] === void 0 || data["y"] === void 0)) {
|
|
13183
|
+
return false;
|
|
13184
|
+
}
|
|
13185
|
+
if (data["value"] !== void 0 && !isStringOrOIDInfo(data["algorithm"])) {
|
|
13186
|
+
return false;
|
|
13187
|
+
}
|
|
13188
|
+
if (data["certainty"] !== void 0 && (typeof data["certainty"] !== "number" || !Number.isFinite(data["certainty"]))) {
|
|
13189
|
+
return false;
|
|
13190
|
+
}
|
|
13191
|
+
if (data["type"] !== void 0 && !isStringOrOIDInfo(data["type"])) {
|
|
13192
|
+
return false;
|
|
13193
|
+
}
|
|
13194
|
+
if (data["encoding"] !== void 0 && typeof data["encoding"] !== "string") {
|
|
13195
|
+
return false;
|
|
13196
|
+
}
|
|
13197
|
+
if (data["signatures"] !== void 0 && (!Array.isArray(data["signatures"]) || !data["signatures"].every(IsAPublicKeySignature))) {
|
|
13198
|
+
return false;
|
|
13199
|
+
}
|
|
13200
|
+
return true;
|
|
13201
|
+
}
|
|
13202
|
+
function isPublicKeySubject(data) {
|
|
13203
|
+
if (data === void 0)
|
|
13204
|
+
return true;
|
|
13205
|
+
if (isStringOrStringArray(data))
|
|
13206
|
+
return true;
|
|
13207
|
+
if (!isMandatoryJSONObject(data))
|
|
13208
|
+
return false;
|
|
13209
|
+
return Object.values(data).every(
|
|
13210
|
+
(value) => typeof value === "string" || isStringOrStringArray(value)
|
|
13211
|
+
);
|
|
13212
|
+
}
|
|
13213
|
+
function IsAPublicKeySignature(data) {
|
|
13214
|
+
if (!isMandatoryJSONObject(data))
|
|
13215
|
+
return false;
|
|
13216
|
+
if (!isOptionalString(data["@id"]))
|
|
13217
|
+
return false;
|
|
13218
|
+
if (data["@context"] !== void 0 && !isStringOrStringArray(data["@context"]))
|
|
13219
|
+
return false;
|
|
13220
|
+
if (!isOptionalStringOrOIDInfo(data["algorithm"]))
|
|
13221
|
+
return false;
|
|
13222
|
+
if (!isOptionalString(data["format"]))
|
|
13223
|
+
return false;
|
|
13224
|
+
if (!isOptionalString(data["encoding"]))
|
|
13225
|
+
return false;
|
|
13226
|
+
if (data["value"] !== void 0 && !isString(data["value"]))
|
|
13227
|
+
return false;
|
|
13228
|
+
if (data["publicKey"] !== void 0 && !isEncodedValue(data["publicKey"]))
|
|
13229
|
+
return false;
|
|
13230
|
+
if (data["signature"] !== void 0 && !isEncodedValue(data["signature"]))
|
|
13231
|
+
return false;
|
|
13232
|
+
if (!isOptionalString(data["timestamp"]))
|
|
13233
|
+
return false;
|
|
13234
|
+
if (!isOptionalString(data["issuer"]))
|
|
13235
|
+
return false;
|
|
13236
|
+
if (!isOptionalString(data["signer"]))
|
|
13237
|
+
return false;
|
|
13238
|
+
if (!isOptionalString(data["notBefore"]))
|
|
13239
|
+
return false;
|
|
13240
|
+
if (!isOptionalString(data["notAfter"]))
|
|
13241
|
+
return false;
|
|
13242
|
+
if (!isOptionalStringArray(data["keyUsage"]))
|
|
13243
|
+
return false;
|
|
13244
|
+
if (data["operations"] !== void 0 && !isMandatoryJSONObject(data["operations"]))
|
|
13245
|
+
return false;
|
|
13246
|
+
if (data["comment"] !== void 0 && !isMandatoryJSONObject(data["comment"]))
|
|
13247
|
+
return false;
|
|
13248
|
+
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;
|
|
13249
|
+
}
|
|
13250
|
+
function IsAPublicKeyXY(data) {
|
|
13251
|
+
if (!IsAPublicKey(data))
|
|
13252
|
+
return false;
|
|
13253
|
+
if (!isString(data["x"])) {
|
|
13254
|
+
return false;
|
|
13255
|
+
}
|
|
13256
|
+
if (!isString(data["y"])) {
|
|
13257
|
+
return false;
|
|
13258
|
+
}
|
|
13259
|
+
return true;
|
|
13260
|
+
}
|
|
13105
13261
|
var MENNEKES_EDL40_XMLNS = "http://www.mennekes.de/Mennekes.EdlVerification.xsd";
|
|
13106
13262
|
var MENNEKES_EDL40_OBIS = "1-0:1.17.0*255";
|
|
13107
13263
|
var Mennekes = class {
|
|
@@ -13163,15 +13319,15 @@ var Mennekes = class {
|
|
|
13163
13319
|
return {
|
|
13164
13320
|
"@id": chargingStationId,
|
|
13165
13321
|
"description": { "en": "Mennekes EDL40 charging station" },
|
|
13166
|
-
"manufacturer": "MENNEKES",
|
|
13322
|
+
"manufacturer": { "name": "MENNEKES" },
|
|
13167
13323
|
"address": chargingProcess.siteAddress,
|
|
13168
13324
|
"EVSEs": [
|
|
13169
13325
|
{
|
|
13170
13326
|
"@id": evseId,
|
|
13171
|
-
"
|
|
13327
|
+
"energyMeters": [
|
|
13172
13328
|
{
|
|
13173
13329
|
"@id": meterId,
|
|
13174
|
-
"manufacturer": "MENNEKES",
|
|
13330
|
+
"manufacturer": { "name": "MENNEKES" },
|
|
13175
13331
|
"signatureFormat": "https://open.charging.cloud/contexts/EnergyMeterSignatureFormats/MennekesCrypt01",
|
|
13176
13332
|
"publicKeys": [
|
|
13177
13333
|
{
|
|
@@ -13249,7 +13405,7 @@ var MennekesCrypt01 = class extends ACrypt {
|
|
|
13249
13405
|
}
|
|
13250
13406
|
async VerifyChargingSession(chargingSession) {
|
|
13251
13407
|
let sessionResult = "UnknownSessionFormat" /* UnknownSessionFormat */;
|
|
13252
|
-
for (const measurement of chargingSession.measurements) {
|
|
13408
|
+
for (const measurement of chargingSession.measurements ?? []) {
|
|
13253
13409
|
measurement.chargingSession = chargingSession;
|
|
13254
13410
|
if (measurement.values.length >= 2) {
|
|
13255
13411
|
sessionResult = "ValidSignature" /* ValidSignature */;
|
|
@@ -13316,8 +13472,6 @@ var MennekesCrypt01 = class extends ACrypt {
|
|
|
13316
13472
|
if (meter.publicKeys == null || meter.publicKeys.length === 0)
|
|
13317
13473
|
return setResult("PublicKeyNotFound" /* PublicKeyNotFound */);
|
|
13318
13474
|
const signatureExpected = measurementValue.signatures?.[0];
|
|
13319
|
-
if (signatureExpected.r == null || signatureExpected.s == null)
|
|
13320
|
-
return setResult("InvalidSignature" /* InvalidSignature */);
|
|
13321
13475
|
const signedData = buildMennekesSignatureData(
|
|
13322
13476
|
{
|
|
13323
13477
|
serverId: measurement.serverId,
|
|
@@ -13339,7 +13493,7 @@ var MennekesCrypt01 = class extends ACrypt {
|
|
|
13339
13493
|
secondIndex: measurementValue.secondsIndex ?? 0
|
|
13340
13494
|
}
|
|
13341
13495
|
);
|
|
13342
|
-
cryptoResult.signedData =
|
|
13496
|
+
cryptoResult.signedData = bytesToHex(signedData);
|
|
13343
13497
|
cryptoResult.logBytes = cryptoResult.signedData.substring(78, 82);
|
|
13344
13498
|
const signedDataBuffer = signedData.buffer.slice(
|
|
13345
13499
|
signedData.byteOffset,
|
|
@@ -13377,7 +13531,7 @@ var MennekesCrypt01 = class extends ACrypt {
|
|
|
13377
13531
|
PublicKeyDiv.innerHTML = result.publicKey?.match(/.{1,8}/g)?.join(" ") ?? "";
|
|
13378
13532
|
if (SignatureExpectedDiv.parentElement?.children[0])
|
|
13379
13533
|
SignatureExpectedDiv.parentElement.children[0].innerHTML = this.chargy.GetLocalizedMessage("Expected signature") + " (rs, hex)";
|
|
13380
|
-
SignatureExpectedDiv.innerHTML = result.signature
|
|
13534
|
+
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
13535
|
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
13536
|
return Promise.resolve(void 0);
|
|
13383
13537
|
}
|
|
@@ -13439,23 +13593,6 @@ function dateToMennekesLocalEpochSeconds(isoTimestamp) {
|
|
|
13439
13593
|
const offsetSeconds = sign * (Number(offsetMatch[2]) * 3600 + Number(offsetMatch[3]) * 60);
|
|
13440
13594
|
return Math.floor(date.getTime() / 1e3) + offsetSeconds;
|
|
13441
13595
|
}
|
|
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
13596
|
function parseChargingProcessElement(chargingProcessElement) {
|
|
13460
13597
|
const siteAddressElement = child(chargingProcessElement, "SiteAddress");
|
|
13461
13598
|
return {
|
|
@@ -13593,7 +13730,7 @@ var OCMFv1_x = class extends ACrypt {
|
|
|
13593
13730
|
async VerifyChargingSession(chargingSession) {
|
|
13594
13731
|
let sessionResult = "Unvalidated" /* Unvalidated */;
|
|
13595
13732
|
{
|
|
13596
|
-
for (const measurement of chargingSession.measurements) {
|
|
13733
|
+
for (const measurement of chargingSession.measurements ?? []) {
|
|
13597
13734
|
measurement.chargingSession = chargingSession;
|
|
13598
13735
|
if (measurement.values.length > 1) {
|
|
13599
13736
|
for (const measurementValue of measurement.values) {
|
|
@@ -13741,7 +13878,7 @@ var OCMFv1_x = class extends ACrypt {
|
|
|
13741
13878
|
return new Error("Invalid measurement!");
|
|
13742
13879
|
}
|
|
13743
13880
|
{
|
|
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 + ") " : "");
|
|
13881
|
+
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
13882
|
}
|
|
13746
13883
|
{
|
|
13747
13884
|
if (PlainTextDiv.parentElement) {
|
|
@@ -13784,9 +13921,9 @@ var OCMFv1_x = class extends ACrypt {
|
|
|
13784
13921
|
}
|
|
13785
13922
|
if (measurementValue.ocmfDocument.publicKey != null) {
|
|
13786
13923
|
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 + ")";
|
|
13924
|
+
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
13925
|
}
|
|
13789
|
-
PublicKeyDiv.innerHTML = typeof measurementValue.ocmfDocument.publicKey === "string" ? measurementValue.ocmfDocument.publicKey : "der: " + (measurementValue.ocmfDocument.publicKey.value
|
|
13926
|
+
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
13927
|
}
|
|
13791
13928
|
const publicKeySignatureContainer = PublicKeyDiv.parentElement?.children[3];
|
|
13792
13929
|
if (publicKeySignatureContainer !== void 0) {
|
|
@@ -13799,8 +13936,8 @@ var OCMFv1_x = class extends ACrypt {
|
|
|
13799
13936
|
signatureDiv.innerHTML = await this.chargy.CheckMeterPublicKeySignature(
|
|
13800
13937
|
measurementValue.measurement.chargingSession.chargingStation,
|
|
13801
13938
|
measurementValue.measurement.chargingSession.EVSE,
|
|
13802
|
-
measurementValue.measurement.chargingSession.EVSE?.
|
|
13803
|
-
measurementValue.measurement.chargingSession.EVSE?.
|
|
13939
|
+
measurementValue.measurement.chargingSession.EVSE?.energyMeters?.at(0),
|
|
13940
|
+
measurementValue.measurement.chargingSession.EVSE?.energyMeters?.at(0)?.publicKeys?.at(0),
|
|
13804
13941
|
signature
|
|
13805
13942
|
);
|
|
13806
13943
|
} catch {
|
|
@@ -13813,7 +13950,7 @@ var OCMFv1_x = class extends ACrypt {
|
|
|
13813
13950
|
if (SignatureExpectedDiv.parentElement) {
|
|
13814
13951
|
getArrayLikeElement(SignatureExpectedDiv.parentElement.children, 0, "Missing expected signature header").innerHTML = this.chargy.GetLocalizedMessage("Expected signature") + " (rs, hex)";
|
|
13815
13952
|
}
|
|
13816
|
-
SignatureExpectedDiv.innerHTML = "der: " + (measurementValue.ocmfDocument.signature.SD.match(/.{1,8}/g)?.join(" ") ?? "-") + "<br /><br />r: " + (measurementValue.ocmfDocument.signatureRS?.r
|
|
13953
|
+
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
13954
|
}
|
|
13818
13955
|
if (measurementValue.measurement.chargingSession.verificationResult) {
|
|
13819
13956
|
switch (measurementValue.measurement.chargingSession.verificationResult.status) {
|
|
@@ -13858,15 +13995,6 @@ var OCMF = class {
|
|
|
13858
13995
|
//#region (private) tryToParseOCMFv1_0(OCMFDataList, ContainerInfos?)
|
|
13859
13996
|
tryToParseOCMFv1_0(OCMFJSONDocuments, ContainerInfos) {
|
|
13860
13997
|
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
13998
|
const firstOCMDJSONDocument = getFirstArrayElement(OCMFJSONDocuments, "Missing first OCMF JSON document");
|
|
13871
13999
|
const formatVersion = firstOCMDJSONDocument.payload.FV;
|
|
13872
14000
|
const gatewayInformation = firstOCMDJSONDocument.payload.GI ?? firstOCMDJSONDocument.payload.VI;
|
|
@@ -13939,49 +14067,71 @@ var OCMF = class {
|
|
|
13939
14067
|
"gatewayVersion": gatewayVersion
|
|
13940
14068
|
},
|
|
13941
14069
|
// "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
|
-
}
|
|
14070
|
+
// "chargingPools": [{
|
|
14071
|
+
// "@id": "DE*GEF*POOL*CHARGY*1",
|
|
14072
|
+
// "description": { "en": "GraphDefined CHARGY Virtual Charging Pool 1" },
|
|
14073
|
+
// "chargingStations": [{
|
|
14074
|
+
// "@id": chargingStationId,
|
|
14075
|
+
// "description": stationDescription && Object.keys(stationDescription).length > 0
|
|
14076
|
+
// ? stationDescription
|
|
14077
|
+
// : { "en": "GraphDefined CHARGY Virtual Charging Station 1" },
|
|
14078
|
+
// // "firmware": {
|
|
14079
|
+
// // "version": chargyLib.asString(chargingStationInfo?.["softwareVersion"])
|
|
14080
|
+
// // ?? chargyLib.asString(chargingStationInfo?.["firmwareVersion"])
|
|
14081
|
+
// // },
|
|
14082
|
+
// "geoLocation": chargyLib.asJSONObject(chargingStationInfo?.["geoLocation"]) as chargyInterfaces.IGeoLocation | undefined,
|
|
14083
|
+
// "address": chargyLib.asJSONObject(chargingStationInfo?.["address"]) as chargyInterfaces.IAddress | undefined,
|
|
14084
|
+
// "EVSEs": [{
|
|
14085
|
+
// "@id": evseId,
|
|
14086
|
+
// "description": evseDescription && Object.keys(evseDescription).length > 0
|
|
14087
|
+
// ? evseDescription
|
|
14088
|
+
// : { "en": "GraphDefined CHARGY Virtual EVSE 1" },
|
|
14089
|
+
// "connectors": connectorInfo
|
|
14090
|
+
// ? [{
|
|
14091
|
+
// "type": chargyLib.asString(connectorInfo["type"]) ?? "",
|
|
14092
|
+
// "cable": {
|
|
14093
|
+
// "length": chargyLib.asNumber(connectorInfo["length"]) ?? 0,
|
|
14094
|
+
// "looses": chargyLib.asNumber(connectorInfo["looses"]) ?? 0
|
|
14095
|
+
// }
|
|
14096
|
+
// }]
|
|
14097
|
+
// : [],
|
|
14098
|
+
// "energyMeters": [{
|
|
14099
|
+
// "@id": effectiveMeterSerial,
|
|
14100
|
+
// // The signed OCMF payload values always win,
|
|
14101
|
+
// // the container infos only fill the gaps!
|
|
14102
|
+
// "manufacturer": {
|
|
14103
|
+
// "name": meterVendor ?? chargyLib.asString(energyMeterInfo?.["manufacturer"]),
|
|
14104
|
+
// "contact": {
|
|
14105
|
+
// "web": chargyLib.asString(energyMeterInfo?.["manufacturerURL"])
|
|
14106
|
+
// }
|
|
14107
|
+
// },
|
|
14108
|
+
// "model": {
|
|
14109
|
+
// "name": meterModel ?? chargyLib.asString(energyMeterInfo?.["model"]),
|
|
14110
|
+
// "url": chargyLib.asString(energyMeterInfo?.["modelURL"])
|
|
14111
|
+
// },
|
|
14112
|
+
// "hardware": {
|
|
14113
|
+
// "revision": chargyLib.asString(energyMeterInfo?.["hardwareVersion"])
|
|
14114
|
+
// },
|
|
14115
|
+
// "firmware": {
|
|
14116
|
+
// "version": meterFirmware ?? chargyLib.asString(energyMeterInfo?.["firmwareVersion"])
|
|
14117
|
+
// },
|
|
14118
|
+
// "signatureFormat": "https://open.charging.cloud/contexts/EnergyMeterSignatureFormats/OCMFv1.0+json",
|
|
14119
|
+
// "publicKeys": [{
|
|
14120
|
+
// "algorithm": "?",
|
|
14121
|
+
// "encoding": "?",
|
|
14122
|
+
// "format": "?",
|
|
14123
|
+
// "value": "?",
|
|
14124
|
+
// }]
|
|
14125
|
+
// }]
|
|
14126
|
+
// }],
|
|
14127
|
+
// }]
|
|
14128
|
+
// }],
|
|
13979
14129
|
"chargingSessions": [{
|
|
13980
14130
|
"@id": "1554181214441:-1965658344385548683:2",
|
|
13981
14131
|
"@context": "https://open.charging.cloud/contexts/SessionSignatureFormats/OCMFv1.0+json",
|
|
13982
14132
|
"begin": "?",
|
|
13983
14133
|
"end": "?",
|
|
13984
|
-
"EVSEId":
|
|
14134
|
+
//"EVSEId": evseId,
|
|
13985
14135
|
"authorizationStart": {
|
|
13986
14136
|
"@id": identificationData ?? "?",
|
|
13987
14137
|
"type": identificationType ?? "?",
|
|
@@ -13994,6 +14144,8 @@ var OCMF = class {
|
|
|
13994
14144
|
}],
|
|
13995
14145
|
"certainty": 1
|
|
13996
14146
|
};
|
|
14147
|
+
if (ContainerInfos?.chargingStations !== void 0)
|
|
14148
|
+
CTR.chargingStations = ContainerInfos.chargingStations;
|
|
13997
14149
|
const measurementsByKey = /* @__PURE__ */ new Map();
|
|
13998
14150
|
for (const ocmfJSONDocument of OCMFJSONDocuments) {
|
|
13999
14151
|
let inheritedReading = {};
|
|
@@ -14126,6 +14278,10 @@ var OCMF = class {
|
|
|
14126
14278
|
}
|
|
14127
14279
|
}
|
|
14128
14280
|
}
|
|
14281
|
+
if (ContainerInfos?.chargingStations !== void 0)
|
|
14282
|
+
CTR.chargingStations = ContainerInfos.chargingStations;
|
|
14283
|
+
if (ContainerInfos?.warnings !== void 0)
|
|
14284
|
+
CTR.warnings = [...CTR.warnings ?? [], ...ContainerInfos.warnings];
|
|
14129
14285
|
CTR.status = OCMFJSONDocuments.every((ocmfJSONDocument) => ocmfJSONDocument.validationStatus === "ValidSignature" /* ValidSignature */) ? "ValidSignature" /* ValidSignature */ : "InvalidSignature" /* InvalidSignature */;
|
|
14130
14286
|
if (CTR.chargingSessions != null && CTR.chargingSessions.length > 0 && CTR.chargingSessions[0]) {
|
|
14131
14287
|
CTR.begin = CTR.chargingSessions[0].begin;
|
|
@@ -14372,7 +14528,7 @@ var OCMF = class {
|
|
|
14372
14528
|
x: publicKeyXY.x,
|
|
14373
14529
|
y: publicKeyXY.y
|
|
14374
14530
|
};
|
|
14375
|
-
} else if (
|
|
14531
|
+
} else if (IsAPublicKeyXY(OCMFJSONDocument.publicKey)) {
|
|
14376
14532
|
publicKey = curve.keyFromPublic({
|
|
14377
14533
|
x: OCMFJSONDocument.publicKey.x,
|
|
14378
14534
|
y: OCMFJSONDocument.publicKey.y
|
|
@@ -14482,17 +14638,17 @@ var OCMF = class {
|
|
|
14482
14638
|
// Not an OCMF standard!
|
|
14483
14639
|
case "ECDSA-secp384r1-SHA384":
|
|
14484
14640
|
hashAlgorithm = "SHA384, 384 Bits, hex";
|
|
14485
|
-
hashValue = await
|
|
14641
|
+
hashValue = await sha384(plaintext);
|
|
14486
14642
|
break;
|
|
14487
14643
|
// Not an OCMF standard!
|
|
14488
14644
|
case "ECDSA-brainpool384r1-SHA384":
|
|
14489
14645
|
hashAlgorithm = "SHA384, 384 Bits, hex";
|
|
14490
|
-
hashValue = await
|
|
14646
|
+
hashValue = await sha384(plaintext);
|
|
14491
14647
|
break;
|
|
14492
14648
|
// Not an OCMF standard!
|
|
14493
14649
|
case "ECDSA-secp521r1-SHA512":
|
|
14494
14650
|
hashAlgorithm = "SHA512, 512 Bits, hex";
|
|
14495
|
-
hashValue = await
|
|
14651
|
+
hashValue = await sha512(plaintext);
|
|
14496
14652
|
break;
|
|
14497
14653
|
// ECDSA-secp256r1-SHA256
|
|
14498
14654
|
default:
|
|
@@ -14574,7 +14730,12 @@ var OCMF = class {
|
|
|
14574
14730
|
//#endregion
|
|
14575
14731
|
//#region TryToParseOCMFDocument (OCMFDocument, PublicKey?, PublicKeyEncoding?, ContainerInfos?)
|
|
14576
14732
|
async TryToParseOCMFDocument(OCMFDocument, PublicKey, PublicKeyEncoding, ContainerInfos) {
|
|
14577
|
-
return this.TryToParseOCMFDocuments(
|
|
14733
|
+
return this.TryToParseOCMFDocuments(
|
|
14734
|
+
[OCMFDocument],
|
|
14735
|
+
PublicKey,
|
|
14736
|
+
PublicKeyEncoding,
|
|
14737
|
+
ContainerInfos
|
|
14738
|
+
);
|
|
14578
14739
|
}
|
|
14579
14740
|
//#endregion
|
|
14580
14741
|
//#region TryToParseOCMFDocuments(OCMFDocuments, PublicKey?, PublicKeyEncoding?, ContainerInfos?)
|
|
@@ -14695,13 +14856,16 @@ var OCPI = class {
|
|
|
14695
14856
|
const firstSignedData = asString(asJSONObject(signed_values[0])?.["signed_data"]);
|
|
14696
14857
|
if (firstSignedData != null && firstSignedData.length > 0) {
|
|
14697
14858
|
const placeInfo = asJSONObject(SomeJSON["placeInfo"]);
|
|
14859
|
+
const evseId = asString(placeInfo?.["evseId"]);
|
|
14860
|
+
const evseIdStr = asString(evseId) ?? "";
|
|
14698
14861
|
const geoLocation = asJSONObject(placeInfo?.["geoLocation"]);
|
|
14699
14862
|
const address = asJSONObject(placeInfo?.["address"]);
|
|
14700
14863
|
const geoLat = asNumber(geoLocation?.["lat"]);
|
|
14701
14864
|
const geoLon = asNumber(geoLocation?.["lon"]);
|
|
14702
14865
|
const containerInfos = {
|
|
14703
|
-
|
|
14704
|
-
|
|
14866
|
+
EVSEIds: [evseId],
|
|
14867
|
+
chargingStations: [{
|
|
14868
|
+
"@id": evseIdStr.substring(0, evseIdStr.lastIndexOf("*")),
|
|
14705
14869
|
geoLocation: geoLat !== void 0 && geoLon !== void 0 ? { lat: geoLat, lng: geoLon } : void 0,
|
|
14706
14870
|
address: address ? {
|
|
14707
14871
|
street: asString(address["street"]),
|
|
@@ -14709,8 +14873,8 @@ var OCPI = class {
|
|
|
14709
14873
|
city: asString(address["town"]),
|
|
14710
14874
|
country: asString(address["country"]) ?? ""
|
|
14711
14875
|
} : void 0
|
|
14712
|
-
}
|
|
14713
|
-
energyMeter:
|
|
14876
|
+
}]
|
|
14877
|
+
//energyMeter: chargyLib.asJSONObject(SomeJSON["meterInfo"])
|
|
14714
14878
|
};
|
|
14715
14879
|
return new OCMF(this.chargy).TryToParseOCMFDocument(
|
|
14716
14880
|
firstSignedData,
|
|
@@ -14725,7 +14889,7 @@ var OCPI = class {
|
|
|
14725
14889
|
const numberOfFormatChecks = 81;
|
|
14726
14890
|
let secondaryErrors = 0;
|
|
14727
14891
|
try {
|
|
14728
|
-
const chargingSessionId = SomeJSON["@id"];
|
|
14892
|
+
const chargingSessionId = asString(SomeJSON["@id"]);
|
|
14729
14893
|
const chargePointInfo = asJSONObject(SomeJSON["chargePointInfo"]);
|
|
14730
14894
|
const evseId = chargePointInfo?.["evseId"];
|
|
14731
14895
|
const placeInfo = asJSONObject(chargePointInfo?.["placeInfo"]);
|
|
@@ -14956,7 +15120,7 @@ var OCPI = class {
|
|
|
14956
15120
|
"value": "042313b9e469612b4ca06981bfdecb226e234632b01d84b6a814f63a114b7762c34ddce2e6853395b7a0f87275f63ffe3c",
|
|
14957
15121
|
"signatures": [
|
|
14958
15122
|
{
|
|
14959
|
-
"
|
|
15123
|
+
"@id": "...",
|
|
14960
15124
|
"algorithm": "secp192r1",
|
|
14961
15125
|
"format": "DER",
|
|
14962
15126
|
"value": "????"
|
|
@@ -15021,7 +15185,7 @@ var OCPI = class {
|
|
|
15021
15185
|
// "de": "GraphDefined EVSE - CI-Tests Pool 3 / Station A / EVSE 1"
|
|
15022
15186
|
// },
|
|
15023
15187
|
//"connectors": [ ],
|
|
15024
|
-
"
|
|
15188
|
+
"energyMeters": []
|
|
15025
15189
|
}
|
|
15026
15190
|
]
|
|
15027
15191
|
}
|
|
@@ -15036,29 +15200,29 @@ var OCPI = class {
|
|
|
15036
15200
|
return new Alfen(this.chargy).TryToParseALFENFormat(
|
|
15037
15201
|
signedMeterValues.map((value) => asString(asJSONObject(value)?.["payload"]) ?? ""),
|
|
15038
15202
|
{
|
|
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:
|
|
15203
|
+
// chargingSessions: [{
|
|
15204
|
+
// "@id": chargingSessionId ?? ""
|
|
15205
|
+
// }],
|
|
15206
|
+
// // EVSEId: evseId,
|
|
15207
|
+
// chargingStations: [{
|
|
15208
|
+
// manufacturer: chargingStation_manufacturer,
|
|
15209
|
+
// type: chargingStation_type,
|
|
15210
|
+
// serialNumber: chargingStation_serialNumber,
|
|
15211
|
+
// firmwareVersion: chargingStation_controllerSoftwareVersion,
|
|
15212
|
+
// legalCompliance: {
|
|
15213
|
+
// conformity: [{
|
|
15214
|
+
// freeText: chargingStation_compliance
|
|
15215
|
+
// }],
|
|
15216
|
+
// calibration: [{
|
|
15217
|
+
// freeText: chargingStation_calibration
|
|
15218
|
+
// }]
|
|
15219
|
+
// },
|
|
15220
|
+
// geoLocation: { "lat": geoLocation_lat, "lng": geoLocation_lon },
|
|
15221
|
+
// address: { "street": address_street, "postalCode": address_zipCode, "city": address_town, "country": address_country }
|
|
15222
|
+
// }],
|
|
15223
|
+
// energyMeter: meterInfo,
|
|
15224
|
+
// connector: connectorInfo,
|
|
15225
|
+
// chargingCosts: chargingCostsInfo
|
|
15062
15226
|
}
|
|
15063
15227
|
);
|
|
15064
15228
|
}
|
|
@@ -15309,7 +15473,7 @@ var PCDFCrypt01 = class extends ACrypt {
|
|
|
15309
15473
|
async VerifyChargingSession(chargingSession) {
|
|
15310
15474
|
let sessionResult = "ValidSignature" /* ValidSignature */;
|
|
15311
15475
|
let valueCount = 0;
|
|
15312
|
-
for (const measurement of chargingSession.measurements) {
|
|
15476
|
+
for (const measurement of chargingSession.measurements ?? []) {
|
|
15313
15477
|
measurement.chargingSession = chargingSession;
|
|
15314
15478
|
for (const measurementValue of measurement.values) {
|
|
15315
15479
|
valueCount++;
|
|
@@ -15408,10 +15572,10 @@ var PCDF = class {
|
|
|
15408
15572
|
"de": "Porsche Charging Data Format Ladevorgang",
|
|
15409
15573
|
"en": "Porsche Charging Data Format charging session"
|
|
15410
15574
|
},
|
|
15411
|
-
"
|
|
15575
|
+
"contracts": [{
|
|
15412
15576
|
"@id": data.session.idTag,
|
|
15413
15577
|
"type": data.session.idTagType
|
|
15414
|
-
},
|
|
15578
|
+
}],
|
|
15415
15579
|
"pcdf": {
|
|
15416
15580
|
"chargingSessionCounter": data.chargingSessionCounter,
|
|
15417
15581
|
"timeValid": data.timeValid,
|
|
@@ -15430,11 +15594,17 @@ var PCDF = class {
|
|
|
15430
15594
|
"EVSEs": [{
|
|
15431
15595
|
"@id": virtualEVSEId,
|
|
15432
15596
|
"description": { "en": "GraphDefined CHARGY Virtual EVSE 1" },
|
|
15433
|
-
"
|
|
15597
|
+
"energyMeters": [{
|
|
15434
15598
|
"@id": meterId,
|
|
15435
|
-
"manufacturer":
|
|
15436
|
-
|
|
15437
|
-
|
|
15599
|
+
"manufacturer": {
|
|
15600
|
+
"name": "Porsche"
|
|
15601
|
+
},
|
|
15602
|
+
"model": {
|
|
15603
|
+
"name": data.dcMeterType === 0 ? "PES DCMeter EU" : "Unknown DC Meter"
|
|
15604
|
+
},
|
|
15605
|
+
"firmware": {
|
|
15606
|
+
"checksum": data.softwareChecksum
|
|
15607
|
+
},
|
|
15438
15608
|
"signatureFormat": "https://open.charging.cloud/contexts/EnergyMeterSignatureFormats/PCDF+json",
|
|
15439
15609
|
"publicKeys": [{
|
|
15440
15610
|
"algorithm": "secp256r1",
|
|
@@ -15633,60 +15803,101 @@ var SAFEXML = class _SAFEXML {
|
|
|
15633
15803
|
constructor(chargy) {
|
|
15634
15804
|
this.chargy = chargy;
|
|
15635
15805
|
}
|
|
15636
|
-
static
|
|
15637
|
-
const
|
|
15638
|
-
|
|
15639
|
-
|
|
15640
|
-
|
|
15641
|
-
|
|
15642
|
-
|
|
15806
|
+
static ParseContainerInfos(XMLDocument, chargy) {
|
|
15807
|
+
const containerInfos = {};
|
|
15808
|
+
const addWarning = (message) => {
|
|
15809
|
+
containerInfos.warnings ??= [];
|
|
15810
|
+
containerInfos.warnings.push(
|
|
15811
|
+
CreateWarning(chargy.GetMultilanguageText(message))
|
|
15812
|
+
);
|
|
15813
|
+
};
|
|
15814
|
+
const chargingStationElements = getElementsByLocalName(XMLDocument, "chargingStation");
|
|
15815
|
+
if (chargingStationElements.length == 0)
|
|
15816
|
+
return containerInfos;
|
|
15817
|
+
if (chargingStationElements.length > 1)
|
|
15818
|
+
addWarning("Only one chargingStation element is allowed within the given SAFE XML container!");
|
|
15819
|
+
if (chargingStationElements[0] === void 0) {
|
|
15820
|
+
addWarning("The chargingStation element within the given SAFE XML container is invalid!");
|
|
15821
|
+
return containerInfos;
|
|
15822
|
+
}
|
|
15823
|
+
const chargingStationElement = chargingStationElements[0];
|
|
15824
|
+
const chargingStationId = chargingStationElement.getAttribute("id")?.trim();
|
|
15825
|
+
if (chargingStationId === void 0 || chargingStationId.length == 0) {
|
|
15826
|
+
addWarning("The chargingStation identifier within the given SAFE XML container is invalid!");
|
|
15827
|
+
return containerInfos;
|
|
15828
|
+
}
|
|
15829
|
+
const chargingStation = {
|
|
15830
|
+
"@id": chargingStationId
|
|
15831
|
+
};
|
|
15832
|
+
containerInfos.chargingStations = [chargingStation];
|
|
15833
|
+
const description = parseDescription(chargingStationElement);
|
|
15834
|
+
if (description !== void 0)
|
|
15835
|
+
chargingStation.description = description;
|
|
15836
|
+
const firmware = getDirectChildByLocalName(chargingStationElement, "firmware");
|
|
15837
|
+
if (firmware !== void 0) {
|
|
15838
|
+
chargingStation.firmware = {};
|
|
15839
|
+
const firmwareVersion = getTrimmedTextContent(getDirectChildByLocalName(firmware, "version"));
|
|
15840
|
+
if (firmwareVersion !== void 0)
|
|
15841
|
+
chargingStation.firmware.version = firmwareVersion;
|
|
15842
|
+
const firmwareChecksum = getTrimmedTextContent(getDirectChildByLocalName(firmware, "checksum"));
|
|
15843
|
+
if (firmwareChecksum !== void 0)
|
|
15844
|
+
chargingStation.firmware.checksum = firmwareChecksum;
|
|
15845
|
+
if (Object.keys(chargingStation.firmware).length === 0)
|
|
15846
|
+
delete chargingStation.firmware;
|
|
15847
|
+
}
|
|
15643
15848
|
const geoLocationElement = getDirectChildByLocalName(chargingStationElement, "geoLocation");
|
|
15644
|
-
|
|
15645
|
-
|
|
15646
|
-
|
|
15647
|
-
|
|
15648
|
-
|
|
15649
|
-
|
|
15849
|
+
if (geoLocationElement !== void 0) {
|
|
15850
|
+
const latitude = Number.parseFloat(getTrimmedTextContent(getDirectChildByLocalName(geoLocationElement, "latitude")) ?? "");
|
|
15851
|
+
const longitude = Number.parseFloat(getTrimmedTextContent(getDirectChildByLocalName(geoLocationElement, "longitude")) ?? "");
|
|
15852
|
+
const geoLocation = Number.isFinite(latitude) && Number.isFinite(longitude) ? { lat: latitude, lng: longitude } : void 0;
|
|
15853
|
+
if (geoLocation !== void 0)
|
|
15854
|
+
chargingStation.geoLocation = geoLocation;
|
|
15855
|
+
}
|
|
15856
|
+
const evseElements = getElementsByLocalName(chargingStationElement, "EVSE");
|
|
15650
15857
|
if (evseElements.length > 1)
|
|
15651
|
-
|
|
15652
|
-
|
|
15653
|
-
|
|
15654
|
-
|
|
15655
|
-
|
|
15656
|
-
const
|
|
15657
|
-
|
|
15658
|
-
|
|
15659
|
-
|
|
15660
|
-
|
|
15661
|
-
|
|
15662
|
-
|
|
15663
|
-
|
|
15664
|
-
|
|
15665
|
-
|
|
15666
|
-
"
|
|
15667
|
-
|
|
15668
|
-
|
|
15669
|
-
|
|
15670
|
-
|
|
15671
|
-
|
|
15672
|
-
|
|
15673
|
-
|
|
15674
|
-
|
|
15675
|
-
"
|
|
15676
|
-
|
|
15677
|
-
|
|
15678
|
-
"
|
|
15679
|
-
|
|
15680
|
-
|
|
15681
|
-
|
|
15682
|
-
|
|
15683
|
-
}
|
|
15858
|
+
addWarning("Only one EVSE element is allowed within the given SAFE XML chargingStation element!");
|
|
15859
|
+
if (evseElements[0] === void 0) {
|
|
15860
|
+
addWarning("The EVSE element within the given SAFE XML chargingStation element is invalid!");
|
|
15861
|
+
return containerInfos;
|
|
15862
|
+
}
|
|
15863
|
+
const evseElement = evseElements[0];
|
|
15864
|
+
const evseId = evseElement.getAttribute("id")?.trim();
|
|
15865
|
+
if (evseId !== void 0 && evseId.length > 0) {
|
|
15866
|
+
const evse = {
|
|
15867
|
+
"@id": evseId
|
|
15868
|
+
};
|
|
15869
|
+
chargingStation.EVSEs = [evse];
|
|
15870
|
+
const evseDescription = parseDescription(evseElement);
|
|
15871
|
+
if (evseDescription !== void 0)
|
|
15872
|
+
evse.description = evseDescription;
|
|
15873
|
+
const connectorElements = getElementsByLocalName(evseElement, "connector");
|
|
15874
|
+
if (connectorElements.length > 1)
|
|
15875
|
+
addWarning("Only one connector element is allowed within the given SAFE XML EVSE element!");
|
|
15876
|
+
if (connectorElements[0] === void 0) {
|
|
15877
|
+
addWarning("The connector element within the given SAFE XML EVSE element is invalid!");
|
|
15878
|
+
return containerInfos;
|
|
15879
|
+
}
|
|
15880
|
+
const connectorElement = connectorElements[0];
|
|
15881
|
+
const connector = {};
|
|
15882
|
+
const connectorId = connectorElement.getAttribute("id")?.trim();
|
|
15883
|
+
if (connectorId != null && connectorId.length > 0)
|
|
15884
|
+
connector["@id"] = connectorId;
|
|
15885
|
+
const connectorType = getTrimmedTextContent(getDirectChildByLocalName(connectorElement, "type"));
|
|
15886
|
+
if (connectorType !== void 0 && connectorType.length > 0)
|
|
15887
|
+
connector.type = connectorType;
|
|
15888
|
+
if (Object.keys(connector).length > 0)
|
|
15889
|
+
evse.connectors = [connector];
|
|
15890
|
+
}
|
|
15891
|
+
return containerInfos;
|
|
15684
15892
|
}
|
|
15685
15893
|
//#region tryToParseSAFEXML(XMLDocument)
|
|
15686
15894
|
async tryToParseSAFEXML(XMLDocument) {
|
|
15687
15895
|
try {
|
|
15688
15896
|
if (XMLDocument.documentElement.nodeName === "values" || XMLDocument.documentElement.localName === "values") {
|
|
15689
|
-
const safeXMLContext = _SAFEXML.
|
|
15897
|
+
const safeXMLContext = _SAFEXML.ParseContainerInfos(
|
|
15898
|
+
XMLDocument,
|
|
15899
|
+
this.chargy
|
|
15900
|
+
);
|
|
15690
15901
|
const signedDataValues = new Array();
|
|
15691
15902
|
let commonSignedDataFormat = "";
|
|
15692
15903
|
let commonSignedDataEncoding = "";
|
|
@@ -16082,10 +16293,10 @@ var ChargeIT = class {
|
|
|
16082
16293
|
CTR["@id"] = lastMeterValue["transactionId"];
|
|
16083
16294
|
CTR.begin = this.chargy.moment.unix(firstMeterValue["measuredValue"]["timestampLocal"]["timestamp"]).utc().format();
|
|
16084
16295
|
CTR.end = this.chargy.moment.unix(lastMeterValue["measuredValue"]["timestampLocal"]["timestamp"]).utc().format();
|
|
16085
|
-
CTR.
|
|
16296
|
+
CTR.contracts = [{
|
|
16086
16297
|
"@id": firstMeterValue["contract"]["id"],
|
|
16087
16298
|
"@context": firstMeterValue["contract"]["type"]
|
|
16088
|
-
};
|
|
16299
|
+
}];
|
|
16089
16300
|
CTR.chargingStationOperators = [{
|
|
16090
16301
|
"@id": "chargeITmobilityCSO",
|
|
16091
16302
|
"description": { "de": "chargeIT mobility GmbH - Charging Station Operator Services" },
|
|
@@ -16143,7 +16354,9 @@ var ChargeIT = class {
|
|
|
16143
16354
|
// "description": {
|
|
16144
16355
|
// "de": "GraphDefined Charging Station - CI-Tests Pool 3 / Station A"
|
|
16145
16356
|
// },
|
|
16146
|
-
"
|
|
16357
|
+
"firmware": {
|
|
16358
|
+
"version": firstMeterValue["chargePoint"]["softwareVersion"]
|
|
16359
|
+
},
|
|
16147
16360
|
"geoLocation": { "lat": asNumber(geoLocation["lat"]) ?? 0, "lng": asNumber(geoLocation["lon"]) ?? 0 },
|
|
16148
16361
|
"address": {
|
|
16149
16362
|
"street": asString(address["street"]),
|
|
@@ -16158,22 +16371,32 @@ var ChargeIT = class {
|
|
|
16158
16371
|
// "de": "GraphDefined EVSE - CI-Tests Pool 3 / Station A / EVSE 1"
|
|
16159
16372
|
// },
|
|
16160
16373
|
// "connectors": [{ }],
|
|
16161
|
-
"
|
|
16374
|
+
"energyMeters": [
|
|
16162
16375
|
{
|
|
16163
16376
|
"@id": firstMeterValue["meterInfo"]["meterId"],
|
|
16164
|
-
"manufacturer":
|
|
16165
|
-
|
|
16166
|
-
|
|
16167
|
-
|
|
16168
|
-
|
|
16377
|
+
"manufacturer": {
|
|
16378
|
+
"name": firstMeterValue["meterInfo"]["manufacturer"],
|
|
16379
|
+
"contact": {
|
|
16380
|
+
"web": "https://www.emh-metering.de"
|
|
16381
|
+
}
|
|
16382
|
+
},
|
|
16383
|
+
"model": {
|
|
16384
|
+
"name": firstMeterValue["meterInfo"]["type"]
|
|
16385
|
+
},
|
|
16386
|
+
"hardware": {
|
|
16387
|
+
"revision": "1.0"
|
|
16388
|
+
},
|
|
16389
|
+
"firmware": {
|
|
16390
|
+
"version": firstMeterValue["meterInfo"]["firmwareVersion"]
|
|
16391
|
+
},
|
|
16169
16392
|
"signatureFormat": "https://open.charging.cloud/contexts/EnergyMeterSignatureFormats/EMHCrypt01",
|
|
16170
16393
|
"publicKeys": [
|
|
16171
16394
|
{
|
|
16172
16395
|
"algorithm": "secp192r1",
|
|
16173
16396
|
"format": "DER",
|
|
16174
16397
|
"encoding": "hex",
|
|
16175
|
-
"value": firstMeterValue["meterInfo"]["publicKey"].startsWith("04") ? firstMeterValue["meterInfo"]["publicKey"] : "04" + firstMeterValue["meterInfo"]["publicKey"]
|
|
16176
|
-
"signatures":
|
|
16398
|
+
"value": firstMeterValue["meterInfo"]["publicKey"].startsWith("04") ? firstMeterValue["meterInfo"]["publicKey"] : "04" + firstMeterValue["meterInfo"]["publicKey"]
|
|
16399
|
+
//"signatures": firstMeterValue["meterInfo"]["publicKeySignatures"]
|
|
16177
16400
|
}
|
|
16178
16401
|
]
|
|
16179
16402
|
}
|
|
@@ -16482,10 +16705,10 @@ var ChargeIT = class {
|
|
|
16482
16705
|
"value": "042313b9e469612b4ca06981bfdecb226e234632b01d84b6a814f63a114b7762c34ddce2e6853395b7a0f87275f63ffe3c",
|
|
16483
16706
|
"signatures": [
|
|
16484
16707
|
{
|
|
16485
|
-
"
|
|
16708
|
+
"@id": "...",
|
|
16486
16709
|
"algorithm": "secp192r1",
|
|
16487
16710
|
"format": "DER",
|
|
16488
|
-
"value": "
|
|
16711
|
+
"value": "..."
|
|
16489
16712
|
}
|
|
16490
16713
|
]
|
|
16491
16714
|
},
|
|
@@ -16544,7 +16767,7 @@ var ChargeIT = class {
|
|
|
16544
16767
|
// "de": "GraphDefined EVSE - CI-Tests Pool 3 / Station A / EVSE 1"
|
|
16545
16768
|
// },
|
|
16546
16769
|
//"connectors": [ ],
|
|
16547
|
-
"
|
|
16770
|
+
"energyMeters": []
|
|
16548
16771
|
}
|
|
16549
16772
|
]
|
|
16550
16773
|
}
|
|
@@ -16566,11 +16789,15 @@ var ChargeIT = class {
|
|
|
16566
16789
|
return new Alfen(this.chargy).TryToParseALFENFormat(
|
|
16567
16790
|
signedMeterValues.map((value) => asString(asJSONObject(value)?.["payload"]) ?? ""),
|
|
16568
16791
|
{
|
|
16569
|
-
|
|
16570
|
-
|
|
16792
|
+
chargingStations: [{
|
|
16793
|
+
"@id": "?",
|
|
16571
16794
|
geoLocation: { "lat": geoLocation_lat, "lng": geoLocation_lon },
|
|
16572
|
-
address: { "street": address_street, "postalCode": address_zipCode, "city": address_town, "country": address_country }
|
|
16573
|
-
|
|
16795
|
+
address: { "street": address_street, "postalCode": address_zipCode, "city": address_town, "country": address_country },
|
|
16796
|
+
EVSEs: [{
|
|
16797
|
+
"@id": evseId,
|
|
16798
|
+
energyMeters: []
|
|
16799
|
+
}]
|
|
16800
|
+
}]
|
|
16574
16801
|
}
|
|
16575
16802
|
);
|
|
16576
16803
|
}
|
|
@@ -16578,11 +16805,15 @@ var ChargeIT = class {
|
|
|
16578
16805
|
return new Alfen(this.chargy).TryToParseALFENFormat(
|
|
16579
16806
|
signedMeterValues.map((value) => asString(asJSONObject(value)?.["payload"]) ?? ""),
|
|
16580
16807
|
{
|
|
16581
|
-
|
|
16582
|
-
|
|
16808
|
+
chargingStations: [{
|
|
16809
|
+
"@id": "?",
|
|
16583
16810
|
geoLocation: { "lat": geoLocation_lat, "lng": geoLocation_lon },
|
|
16584
|
-
address: { "street": address_street, "postalCode": address_zipCode, "city": address_town, "country": address_country }
|
|
16585
|
-
|
|
16811
|
+
address: { "street": address_street, "postalCode": address_zipCode, "city": address_town, "country": address_country },
|
|
16812
|
+
EVSEs: [{
|
|
16813
|
+
"@id": evseId,
|
|
16814
|
+
energyMeters: []
|
|
16815
|
+
}]
|
|
16816
|
+
}]
|
|
16586
16817
|
}
|
|
16587
16818
|
);
|
|
16588
16819
|
if (signedMeterValueContext === oldChargeITMeterValueFormat)
|
|
@@ -16657,7 +16888,6 @@ var ChargeIT = class {
|
|
|
16657
16888
|
const connectorInfo_type = connectorInfo?.["type"];
|
|
16658
16889
|
const connectorInfo_losses = connectorInfo?.["losses"];
|
|
16659
16890
|
const chargingTariffs = SomeJSON["chargingTariffs"];
|
|
16660
|
-
const chargingPeriods = SomeJSON["chargingPeriods"];
|
|
16661
16891
|
const totalCosts = asJSONObject(SomeJSON["totalCosts"]);
|
|
16662
16892
|
const totalCosts_total = totalCosts?.["total"];
|
|
16663
16893
|
const totalCosts_currency = totalCosts?.["currency"];
|
|
@@ -16850,10 +17080,10 @@ var ChargeIT = class {
|
|
|
16850
17080
|
"value": "042313b9e469612b4ca06981bfdecb226e234632b01d84b6a814f63a114b7762c34ddce2e6853395b7a0f87275f63ffe3c",
|
|
16851
17081
|
"signatures": [
|
|
16852
17082
|
{
|
|
16853
|
-
"
|
|
17083
|
+
"@id": "...",
|
|
16854
17084
|
"algorithm": "secp192r1",
|
|
16855
17085
|
"format": "DER",
|
|
16856
|
-
"value": "
|
|
17086
|
+
"value": "..."
|
|
16857
17087
|
}
|
|
16858
17088
|
]
|
|
16859
17089
|
},
|
|
@@ -16915,7 +17145,7 @@ var ChargeIT = class {
|
|
|
16915
17145
|
// "de": "GraphDefined EVSE - CI-Tests Pool 3 / Station A / EVSE 1"
|
|
16916
17146
|
// },
|
|
16917
17147
|
//"connectors": [ ],
|
|
16918
|
-
"
|
|
17148
|
+
"energyMeters": []
|
|
16919
17149
|
}
|
|
16920
17150
|
]
|
|
16921
17151
|
}
|
|
@@ -16932,31 +17162,31 @@ var ChargeIT = class {
|
|
|
16932
17162
|
return new Alfen(this.chargy).TryToParseALFENFormat(
|
|
16933
17163
|
signedMeterValues.map((value) => asString(asJSONObject(value)?.["payload"]) ?? ""),
|
|
16934
17164
|
{
|
|
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
|
|
17165
|
+
// chargingSession: {
|
|
17166
|
+
// "@id": chargingSessionId
|
|
17167
|
+
// },
|
|
17168
|
+
// EVSEId: evseId,
|
|
17169
|
+
// chargingStation: {
|
|
17170
|
+
// manufacturer: chargingStation_manufacturer,
|
|
17171
|
+
// type: chargingStation_type,
|
|
17172
|
+
// serialNumber: chargingStation_serialNumber,
|
|
17173
|
+
// firmwareVersion: chargingStation_controllerSoftwareVersion,
|
|
17174
|
+
// legalCompliance: {
|
|
17175
|
+
// conformity: [{
|
|
17176
|
+
// freeText: chargingStation_compliance
|
|
17177
|
+
// }],
|
|
17178
|
+
// calibration: [{
|
|
17179
|
+
// freeText: chargingStation_calibration
|
|
17180
|
+
// }]
|
|
17181
|
+
// },
|
|
17182
|
+
// geoLocation: { "lat": geoLocation_lat, "lng": geoLocation_lon },
|
|
17183
|
+
// address: { "street": address_street, "postalCode": address_zipCode, "city": address_town, "country": address_country }
|
|
17184
|
+
// },
|
|
17185
|
+
// energyMeter: meterInfo,
|
|
17186
|
+
// connector: connectorInfo,
|
|
17187
|
+
// chargingTariffs: chargingTariffs,
|
|
17188
|
+
// chargingPeriods: chargingPeriods,
|
|
17189
|
+
// totalCosts: totalCosts
|
|
16960
17190
|
}
|
|
16961
17191
|
);
|
|
16962
17192
|
}
|
|
@@ -17088,12 +17318,18 @@ var ChargePoint = class {
|
|
|
17088
17318
|
"address": asJSONObject(SomeJSON["address"]),
|
|
17089
17319
|
"EVSEs": [{
|
|
17090
17320
|
"@id": evseId,
|
|
17091
|
-
"
|
|
17321
|
+
"energyMeters": [{
|
|
17092
17322
|
"@id": meterSerial,
|
|
17093
|
-
"manufacturer":
|
|
17094
|
-
|
|
17095
|
-
|
|
17096
|
-
|
|
17323
|
+
"manufacturer": {
|
|
17324
|
+
"name": "Carlo Gavazzi",
|
|
17325
|
+
"contact": {
|
|
17326
|
+
"web": "https://www.gavazziautomation.com"
|
|
17327
|
+
}
|
|
17328
|
+
},
|
|
17329
|
+
"model": {
|
|
17330
|
+
"name": "EM340-DIN.AV2.3.X.S1.X",
|
|
17331
|
+
"url": "https://www.gavazziautomation.com/fileadmin/images/PIM/DATASHEET/ENG/EM340_DS_ENG.pdf"
|
|
17332
|
+
}
|
|
17097
17333
|
// "signatureFormat": "https://open.charging.cloud/contexts/EnergyMeterSignatureFormats/EMHCrypt01",
|
|
17098
17334
|
// "publicKeys": [
|
|
17099
17335
|
// {
|
|
@@ -17248,12 +17484,18 @@ var ChargePoint = class {
|
|
|
17248
17484
|
"address": asJSONObject(SomeJSON["address"]),
|
|
17249
17485
|
"EVSEs": [{
|
|
17250
17486
|
"@id": evseId,
|
|
17251
|
-
"
|
|
17487
|
+
"energyMeters": [{
|
|
17252
17488
|
"@id": meterSerial,
|
|
17253
|
-
"manufacturer":
|
|
17254
|
-
|
|
17255
|
-
|
|
17256
|
-
|
|
17489
|
+
"manufacturer": {
|
|
17490
|
+
"name": "Carlo Gavazzi",
|
|
17491
|
+
"contact": {
|
|
17492
|
+
"web": "https://www.gavazziautomation.com"
|
|
17493
|
+
}
|
|
17494
|
+
},
|
|
17495
|
+
"model": {
|
|
17496
|
+
"name": "EM340-DIN.AV2.3.X.S1.X",
|
|
17497
|
+
"url": "https://www.gavazziautomation.com/fileadmin/images/PIM/DATASHEET/ENG/EM340_DS_ENG.pdf"
|
|
17498
|
+
},
|
|
17257
17499
|
"signatureFormat": "https://open.charging.cloud/contexts/EnergyMeterSignatureFormats/EMHCrypt01",
|
|
17258
17500
|
"signatureInfos": {
|
|
17259
17501
|
"hash": "SHA256",
|
|
@@ -17265,7 +17507,8 @@ var ChargePoint = class {
|
|
|
17265
17507
|
"publicKeys": [{
|
|
17266
17508
|
"algorithm": "secp224k1",
|
|
17267
17509
|
"format": "DER",
|
|
17268
|
-
"encoding": "hex"
|
|
17510
|
+
"encoding": "hex",
|
|
17511
|
+
"value": "..."
|
|
17269
17512
|
}]
|
|
17270
17513
|
}]
|
|
17271
17514
|
}]
|
|
@@ -17367,7 +17610,7 @@ var ChargePointCrypt01 = class extends ACrypt {
|
|
|
17367
17610
|
s: ASN1Signature.s.toString(16)
|
|
17368
17611
|
};
|
|
17369
17612
|
}
|
|
17370
|
-
const publicKeyId = chargingSession.EVSEId
|
|
17613
|
+
const publicKeyId = chargingSession.EVSEId?.replace(/:/g, "").replace(/-/g, "_");
|
|
17371
17614
|
const publicKeys = [];
|
|
17372
17615
|
if (chargingSession.ctr.publicKeys != null) {
|
|
17373
17616
|
for (const publicKeyInfo of chargingSession.ctr.publicKeys) {
|
|
@@ -17398,8 +17641,8 @@ var ChargePointCrypt01 = class extends ACrypt {
|
|
|
17398
17641
|
sha225Value = sha225Value ?? (BigInt("0x" + await sha256(plainText)) >> BigInt(31)).toString(16);
|
|
17399
17642
|
sessionResult = this.curve224k1.validate(
|
|
17400
17643
|
BigInt("0x" + sha225Value),
|
|
17401
|
-
BigInt("0x" +
|
|
17402
|
-
BigInt("0x" +
|
|
17644
|
+
BigInt("0x" + chargingSession.signature.r),
|
|
17645
|
+
BigInt("0x" + chargingSession.signature.s),
|
|
17403
17646
|
[
|
|
17404
17647
|
BigInt("0x" + publicKey.value.slice(2, 58)),
|
|
17405
17648
|
BigInt("0x" + publicKey.value.slice(58, 114))
|
|
@@ -17447,7 +17690,7 @@ var ChargePointCrypt01 = class extends ACrypt {
|
|
|
17447
17690
|
}
|
|
17448
17691
|
}
|
|
17449
17692
|
}
|
|
17450
|
-
for (const measurement of chargingSession.measurements) {
|
|
17693
|
+
for (const measurement of chargingSession.measurements ?? []) {
|
|
17451
17694
|
measurement.chargingSession = chargingSession;
|
|
17452
17695
|
if (measurement.values.length > 1) {
|
|
17453
17696
|
for (const measurementValue of measurement.values) {
|
|
@@ -17590,8 +17833,8 @@ var ChargePointCrypt01 = class extends ACrypt {
|
|
|
17590
17833
|
signatureDiv.innerHTML = await this.chargy.CheckMeterPublicKeySignature(
|
|
17591
17834
|
measurementValue.measurement.chargingSession.chargingStation,
|
|
17592
17835
|
measurementValue.measurement.chargingSession.EVSE,
|
|
17593
|
-
measurementValue.measurement.chargingSession.EVSE?.
|
|
17594
|
-
measurementValue.measurement.chargingSession.EVSE?.
|
|
17836
|
+
measurementValue.measurement.chargingSession.EVSE?.energyMeters?.[0],
|
|
17837
|
+
measurementValue.measurement.chargingSession.EVSE?.energyMeters?.[0]?.publicKeys?.[0],
|
|
17595
17838
|
signature
|
|
17596
17839
|
);
|
|
17597
17840
|
} catch {
|
|
@@ -17604,7 +17847,7 @@ var ChargePointCrypt01 = class extends ACrypt {
|
|
|
17604
17847
|
getArrayLikeElement(SignatureExpectedDiv.parentElement.children, 0, "Missing expected signature header").innerHTML = "Erwartete Signatur (secrrct.sign, rs, hex)";
|
|
17605
17848
|
}
|
|
17606
17849
|
if (typeof chargingSession.signature != "string")
|
|
17607
|
-
SignatureExpectedDiv.innerHTML = "r: " + (chargingSession.signature.r
|
|
17850
|
+
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
17851
|
else if (chargingSession.signature)
|
|
17609
17852
|
SignatureExpectedDiv.innerHTML = chargingSession.signature.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "-";
|
|
17610
17853
|
}
|
|
@@ -17645,7 +17888,8 @@ var IChargeTransparencyRecord_exports = {};
|
|
|
17645
17888
|
__export(IChargeTransparencyRecord_exports, {
|
|
17646
17889
|
CloneCTR: () => CloneCTR,
|
|
17647
17890
|
IsAChargeTransparencyRecord: () => IsAChargeTransparencyRecord,
|
|
17648
|
-
IsASessionCryptoResult: () => IsASessionCryptoResult
|
|
17891
|
+
IsASessionCryptoResult: () => IsASessionCryptoResult,
|
|
17892
|
+
toSessionVerificationResults: () => toSessionVerificationResults
|
|
17649
17893
|
});
|
|
17650
17894
|
function IsAChargeTransparencyRecord(data) {
|
|
17651
17895
|
if (!isMandatoryJSONObject(data))
|
|
@@ -17663,7 +17907,7 @@ function CloneCTR(CTR) {
|
|
|
17663
17907
|
const clonedCTR = JSON.parse(JSON.stringify(CTR));
|
|
17664
17908
|
if (clonedCTR.chargingSessions) {
|
|
17665
17909
|
for (const session of clonedCTR.chargingSessions) {
|
|
17666
|
-
for (const measurement of session.measurements) {
|
|
17910
|
+
for (const measurement of session.measurements ?? []) {
|
|
17667
17911
|
for (const value of measurement.values) {
|
|
17668
17912
|
if (typeof value.value === "string" || typeof value.value === "number")
|
|
17669
17913
|
value.value = new Decimal(value.value);
|
|
@@ -17673,6 +17917,16 @@ function CloneCTR(CTR) {
|
|
|
17673
17917
|
}
|
|
17674
17918
|
return clonedCTR;
|
|
17675
17919
|
}
|
|
17920
|
+
function toSessionVerificationResults(CTR, noRecordsMessage = { "en": "No charge transparency records found!" }) {
|
|
17921
|
+
const verificationResults = (CTR.chargingSessions ?? []).map((session) => session.verificationResult).filter(isISessionCryptoResult1);
|
|
17922
|
+
if (verificationResults.length > 0)
|
|
17923
|
+
return verificationResults;
|
|
17924
|
+
return {
|
|
17925
|
+
status: "Unvalidated" /* Unvalidated */,
|
|
17926
|
+
message: noRecordsMessage,
|
|
17927
|
+
certainty: 0
|
|
17928
|
+
};
|
|
17929
|
+
}
|
|
17676
17930
|
|
|
17677
17931
|
// src/interfaces/IChargeTransparencyLiveLink.ts
|
|
17678
17932
|
var IChargeTransparencyLiveLink_exports = {};
|
|
@@ -17703,44 +17957,12 @@ function isTransport(data) {
|
|
|
17703
17957
|
function IsAChargeTransparencyLiveLink(data) {
|
|
17704
17958
|
if (!isMandatoryJSONObject(data))
|
|
17705
17959
|
return false;
|
|
17706
|
-
return data["@context"] === ChargeTransparencyLiveLinkContext && (data["timestamp"] === void 0 || data["timestamp"] === null || typeof data["timestamp"] === "string") && (data["description"] === void 0 ||
|
|
17960
|
+
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
17961
|
}
|
|
17708
17962
|
function isTOTPConfig(data) {
|
|
17709
17963
|
return isObject(data) && typeof data["initialSharedSecret"] === "string" && typeof data["timeStep"] === "number";
|
|
17710
17964
|
}
|
|
17711
17965
|
|
|
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
17966
|
// src/qrCodeReader.ts
|
|
17745
17967
|
var import_buffer = __toESM(require_buffer2());
|
|
17746
17968
|
function isRecord(value) {
|
|
@@ -18000,45 +18222,6 @@ var Chargy = class {
|
|
|
18000
18222
|
return fileName.substring(0, lastDot);
|
|
18001
18223
|
return fileName;
|
|
18002
18224
|
}
|
|
18003
|
-
tryExtractChargeTransparencyTextFromURL(qrText) {
|
|
18004
|
-
if (!qrText.startsWith("http://") && !qrText.startsWith("https://"))
|
|
18005
|
-
return qrText;
|
|
18006
|
-
try {
|
|
18007
|
-
const url = new URL(qrText);
|
|
18008
|
-
const candidates = [
|
|
18009
|
-
url.hash.startsWith("#") ? url.hash.substring(1) : url.hash,
|
|
18010
|
-
url.searchParams.get("data"),
|
|
18011
|
-
url.searchParams.get("content"),
|
|
18012
|
-
url.searchParams.get("ctr"),
|
|
18013
|
-
url.searchParams.get("record"),
|
|
18014
|
-
url.searchParams.get("payload"),
|
|
18015
|
-
url.searchParams.get("q")
|
|
18016
|
-
];
|
|
18017
|
-
for (const candidate of candidates) {
|
|
18018
|
-
const decodedCandidate = candidate != null ? decodeURIComponent(candidate).trim() : "";
|
|
18019
|
-
if (decodedCandidate.startsWith("<?xml") || decodedCandidate.startsWith("<values") || decodedCandidate.startsWith("{") || decodedCandidate.startsWith("[") || decodedCandidate.startsWith("OCMF") || decodedCandidate.startsWith("AP;")) {
|
|
18020
|
-
return decodedCandidate;
|
|
18021
|
-
}
|
|
18022
|
-
}
|
|
18023
|
-
} catch {
|
|
18024
|
-
console.log("Invalid URL in QR code: " + qrText);
|
|
18025
|
-
}
|
|
18026
|
-
return qrText;
|
|
18027
|
-
}
|
|
18028
|
-
tryExtractSignedDataTextFromXML(qrText) {
|
|
18029
|
-
const trimmedQRCodeText = qrText.trim();
|
|
18030
|
-
if (!trimmedQRCodeText.startsWith("<?xml") && !trimmedQRCodeText.startsWith("<"))
|
|
18031
|
-
return qrText;
|
|
18032
|
-
try {
|
|
18033
|
-
const xmlDocument = new DOMParser().parseFromString(trimmedQRCodeText, "text/xml");
|
|
18034
|
-
const signedDataValues = getElementsByLocalName(xmlDocument, "signedData").filter((signedData) => (signedData.getAttribute("format") ?? "").trim().toLowerCase() === "alfen").map((signedData) => signedData.textContent.trim()).filter((signedData) => signedData.startsWith("AP;"));
|
|
18035
|
-
if (signedDataValues.length > 0)
|
|
18036
|
-
return signedDataValues.join("\n");
|
|
18037
|
-
} catch {
|
|
18038
|
-
console.log("Error parsing XML content from QR code: " + qrText);
|
|
18039
|
-
}
|
|
18040
|
-
return qrText;
|
|
18041
|
-
}
|
|
18042
18225
|
//#region Public key methods...
|
|
18043
18226
|
PublicKeyIdFromFileName(fileName) {
|
|
18044
18227
|
return (fileName.includes(".") ? fileName.substring(0, fileName.indexOf(".")) : fileName).replace(/[-_]?public[-_]?key/i, "");
|
|
@@ -18124,25 +18307,70 @@ var Chargy = class {
|
|
|
18124
18307
|
}
|
|
18125
18308
|
//#endregion
|
|
18126
18309
|
//#region QR code image files...
|
|
18127
|
-
|
|
18128
|
-
|
|
18129
|
-
|
|
18130
|
-
|
|
18310
|
+
normalizeMIMEType(mimeType) {
|
|
18311
|
+
return mimeType?.split(";")[0]?.trim().toLowerCase();
|
|
18312
|
+
}
|
|
18313
|
+
getQRCodeImageMIMETypeFromFileName(fileName) {
|
|
18314
|
+
fileName = fileName.toLowerCase();
|
|
18315
|
+
if (fileName.endsWith(".png"))
|
|
18316
|
+
return "image/png";
|
|
18317
|
+
if (fileName.endsWith(".jpeg"))
|
|
18318
|
+
return "image/jpeg";
|
|
18319
|
+
if (fileName.endsWith(".jpg"))
|
|
18320
|
+
return "image/jpg";
|
|
18321
|
+
if (fileName.endsWith(".gif"))
|
|
18322
|
+
return "image/gif";
|
|
18323
|
+
if (fileName.endsWith(".webp"))
|
|
18324
|
+
return "image/webp";
|
|
18325
|
+
if (fileName.endsWith(".bmp"))
|
|
18326
|
+
return "image/bmp";
|
|
18327
|
+
if (fileName.endsWith(".svg"))
|
|
18328
|
+
return "image/svg+xml";
|
|
18329
|
+
return void 0;
|
|
18330
|
+
}
|
|
18331
|
+
getQRCodeImageMIMEType(fileInfo, mimeType) {
|
|
18332
|
+
const detectedMIMEType = this.normalizeMIMEType(mimeType);
|
|
18333
|
+
const declaredMIMEType = this.normalizeMIMEType(fileInfo.type);
|
|
18334
|
+
const fileNameMIMEType = this.getQRCodeImageMIMETypeFromFileName(fileInfo.name);
|
|
18335
|
+
if (this.isSupportedQRCodeImageFileType(detectedMIMEType))
|
|
18336
|
+
return detectedMIMEType;
|
|
18337
|
+
if (this.isSupportedQRCodeImageFileType(declaredMIMEType))
|
|
18338
|
+
return declaredMIMEType;
|
|
18339
|
+
if (fileNameMIMEType !== void 0)
|
|
18340
|
+
return fileNameMIMEType;
|
|
18341
|
+
return detectedMIMEType ?? declaredMIMEType;
|
|
18342
|
+
}
|
|
18343
|
+
isSupportedQRCodeImageFileType(MIMEType) {
|
|
18344
|
+
switch (MIMEType) {
|
|
18345
|
+
case void 0:
|
|
18346
|
+
return false;
|
|
18347
|
+
case "image/png":
|
|
18348
|
+
case "image/jpeg":
|
|
18349
|
+
case "image/jpg":
|
|
18350
|
+
case "image/gif":
|
|
18351
|
+
case "image/webp":
|
|
18352
|
+
case "image/bmp":
|
|
18353
|
+
case "image/svg":
|
|
18354
|
+
case "image/svg+xml":
|
|
18355
|
+
return true;
|
|
18356
|
+
}
|
|
18357
|
+
return false;
|
|
18131
18358
|
}
|
|
18132
18359
|
async expandQRCodeImageFiles(FileInfos) {
|
|
18133
18360
|
const expandedFileInfos = new Array();
|
|
18134
18361
|
for (const fileInfo of FileInfos) {
|
|
18135
|
-
|
|
18136
|
-
|
|
18362
|
+
const mimeType = this.getQRCodeImageMIMEType(fileInfo);
|
|
18363
|
+
if (fileInfo.data != null && this.isSupportedQRCodeImageFileType(mimeType)) {
|
|
18364
|
+
const qrText = await readQRCodeTextFromImage(
|
|
18365
|
+
fileInfo.data,
|
|
18366
|
+
mimeType
|
|
18367
|
+
);
|
|
18137
18368
|
if (qrText != null) {
|
|
18138
|
-
const extractedText = this.tryExtractSignedDataTextFromXML(
|
|
18139
|
-
this.tryExtractChargeTransparencyTextFromURL(qrText)
|
|
18140
|
-
);
|
|
18141
18369
|
expandedFileInfos.push({
|
|
18142
|
-
name: this.textFileNameForQRCodeContent(fileInfo.name,
|
|
18370
|
+
name: this.textFileNameForQRCodeContent(fileInfo.name, qrText),
|
|
18143
18371
|
path: fileInfo.path,
|
|
18144
18372
|
type: "text/plain",
|
|
18145
|
-
data: new TextEncoder().encode(
|
|
18373
|
+
data: new TextEncoder().encode(qrText),
|
|
18146
18374
|
info: "Text extracted from QR code image"
|
|
18147
18375
|
});
|
|
18148
18376
|
continue;
|
|
@@ -18292,11 +18520,13 @@ var Chargy = class {
|
|
|
18292
18520
|
"@id": evse["@id"],
|
|
18293
18521
|
"description": evse.description,
|
|
18294
18522
|
"sockets": evseView["sockets"],
|
|
18295
|
-
"
|
|
18523
|
+
"energyMeter": {
|
|
18296
18524
|
"@id": meter["@id"],
|
|
18297
18525
|
"vendor": meterView["vendor"],
|
|
18298
18526
|
"model": meter.model,
|
|
18299
|
-
"
|
|
18527
|
+
"firmware": {
|
|
18528
|
+
"version": meter.firmware?.version
|
|
18529
|
+
},
|
|
18300
18530
|
"signatureFormat": meter.signatureFormat,
|
|
18301
18531
|
"publicKey": {
|
|
18302
18532
|
"algorithm": publicKey.algorithm,
|
|
@@ -18339,55 +18569,42 @@ var Chargy = class {
|
|
|
18339
18569
|
if (FileInfo.data != null && FileInfo.data.byteLength > 0) {
|
|
18340
18570
|
try {
|
|
18341
18571
|
const filetype = await fileTypeFromBuffer(FileInfo.data);
|
|
18342
|
-
|
|
18343
|
-
|
|
18344
|
-
|
|
18345
|
-
|
|
18346
|
-
|
|
18347
|
-
|
|
18348
|
-
|
|
18349
|
-
|
|
18350
|
-
else if (FileInfo.name.endsWith(".chargy"))
|
|
18351
|
-
expandedFileInfos.push({
|
|
18352
|
-
name: FileInfo.name,
|
|
18353
|
-
data: FileInfo.data,
|
|
18354
|
-
info: ".chargy file"
|
|
18355
|
-
});
|
|
18356
|
-
else
|
|
18357
|
-
expandedFileInfos.push({
|
|
18358
|
-
name: FileInfo.name,
|
|
18359
|
-
data: FileInfo.data,
|
|
18360
|
-
exception: "Unknown file type!"
|
|
18361
|
-
});
|
|
18572
|
+
const mimeType = this.getQRCodeImageMIMEType(FileInfo, filetype?.mime);
|
|
18573
|
+
if (this.isSupportedQRCodeImageFileType(mimeType)) {
|
|
18574
|
+
expandedFileInfos.push({
|
|
18575
|
+
name: FileInfo.name,
|
|
18576
|
+
data: FileInfo.data,
|
|
18577
|
+
type: FileInfo.type ?? mimeType,
|
|
18578
|
+
info: "QR code image file"
|
|
18579
|
+
});
|
|
18362
18580
|
continue;
|
|
18363
|
-
} else if (
|
|
18581
|
+
} else if (FileInfo.name.endsWith(".chargy")) {
|
|
18364
18582
|
expandedFileInfos.push({
|
|
18365
18583
|
name: FileInfo.name,
|
|
18366
18584
|
data: FileInfo.data,
|
|
18367
|
-
info: "
|
|
18585
|
+
info: ".chargy file"
|
|
18368
18586
|
});
|
|
18369
18587
|
continue;
|
|
18370
|
-
} else if (
|
|
18588
|
+
} else if (mimeType === "text/xml" || mimeType === "application/xml") {
|
|
18371
18589
|
expandedFileInfos.push({
|
|
18372
18590
|
name: FileInfo.name,
|
|
18373
18591
|
data: FileInfo.data,
|
|
18374
|
-
info: "
|
|
18592
|
+
info: "XML file"
|
|
18375
18593
|
});
|
|
18376
18594
|
continue;
|
|
18377
|
-
} else if (
|
|
18595
|
+
} else if (mimeType === "text/json" || mimeType === "application/json") {
|
|
18378
18596
|
expandedFileInfos.push({
|
|
18379
18597
|
name: FileInfo.name,
|
|
18380
18598
|
data: FileInfo.data,
|
|
18381
|
-
|
|
18382
|
-
info: "QR code image file"
|
|
18599
|
+
info: "JSON file"
|
|
18383
18600
|
});
|
|
18384
18601
|
continue;
|
|
18385
|
-
} else if (
|
|
18602
|
+
} else if (mimeType === "application/zip" || mimeType === "application/x-bzip2" || mimeType === "application/gzip" || mimeType === "application/x-tar") {
|
|
18386
18603
|
try {
|
|
18387
18604
|
const compressedFiles = await this.extractArchive(
|
|
18388
18605
|
FileInfo.name,
|
|
18389
18606
|
FileInfo.data,
|
|
18390
|
-
|
|
18607
|
+
mimeType
|
|
18391
18608
|
);
|
|
18392
18609
|
if (compressedFiles.length == 0)
|
|
18393
18610
|
continue;
|
|
@@ -18459,6 +18676,12 @@ var Chargy = class {
|
|
|
18459
18676
|
}
|
|
18460
18677
|
continue;
|
|
18461
18678
|
}
|
|
18679
|
+
expandedFileInfos.push({
|
|
18680
|
+
name: FileInfo.name,
|
|
18681
|
+
data: FileInfo.data,
|
|
18682
|
+
exception: "Unknown file type!"
|
|
18683
|
+
});
|
|
18684
|
+
continue;
|
|
18462
18685
|
} catch (exception) {
|
|
18463
18686
|
expandedFileInfos.push({
|
|
18464
18687
|
name: FileInfo.name,
|
|
@@ -18614,11 +18837,12 @@ var Chargy = class {
|
|
|
18614
18837
|
//#endregion
|
|
18615
18838
|
//#region DetectAndConvertContentFormat(FileInfos)
|
|
18616
18839
|
async DetectAndConvertContentFormat(FileInfos) {
|
|
18617
|
-
if (FileInfos.length == 0)
|
|
18618
|
-
|
|
18619
|
-
|
|
18620
|
-
|
|
18621
|
-
|
|
18840
|
+
if (FileInfos.length == 0)
|
|
18841
|
+
return {
|
|
18842
|
+
status: "NoChargeTransparencyRecordsFound" /* NoChargeTransparencyRecordsFound */,
|
|
18843
|
+
message: this.GetMultilanguageText("No charge transparency records found!"),
|
|
18844
|
+
certainty: 0
|
|
18845
|
+
};
|
|
18622
18846
|
let expandedFiles = new Array();
|
|
18623
18847
|
const processedFiles = new Array();
|
|
18624
18848
|
if (FileInfos.length > 0) {
|
|
@@ -18791,42 +19015,40 @@ var Chargy = class {
|
|
|
18791
19015
|
} else if (textContent.startsWith("{") && textContent.endsWith("}")) {
|
|
18792
19016
|
try {
|
|
18793
19017
|
const JSONContent = JSON.parse(textContent);
|
|
18794
|
-
if (typeof JSONContent !== "object" || JSONContent
|
|
18795
|
-
throw new Error("Parsed JSON content is not
|
|
18796
|
-
|
|
18797
|
-
|
|
18798
|
-
|
|
18799
|
-
|
|
19018
|
+
if (JSONContent === null || typeof JSONContent !== "object" || !isMandatoryJSONObject(JSONContent))
|
|
19019
|
+
throw new Error("Parsed JSON content is not a JSON object!");
|
|
19020
|
+
const JSONContext = JSONContent["@context"];
|
|
19021
|
+
if (IsAChargeTransparencyLiveLink(JSONContent)) {
|
|
19022
|
+
JSONContent.timestamp ??= (/* @__PURE__ */ new Date()).toISOString();
|
|
19023
|
+
processedFile.result = JSONContent;
|
|
19024
|
+
} else if (isMandatoryString(JSONContext)) {
|
|
19025
|
+
if (JSONContext.startsWith("https://open.charging.cloud/contexts/CTR+json"))
|
|
18800
19026
|
processedFile.result = JSONContent;
|
|
18801
|
-
|
|
18802
|
-
|
|
18803
|
-
|
|
18804
|
-
|
|
18805
|
-
processedFile.result = JSONContent;
|
|
18806
|
-
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")) {
|
|
18807
|
-
processedFile.result = new ChargeIT(this).TryToParseChargeITContainerFormat(JSONContent);
|
|
18808
|
-
}
|
|
18809
|
-
} else {
|
|
18810
|
-
const results = [
|
|
18811
|
-
new ChargeIT(this).TryToParseChargeITContainerFormat(JSONContent),
|
|
18812
|
-
new ChargePoint(this).TryToParseChargepointFormat(JSONContent),
|
|
18813
|
-
await new OCPI(this).tryToParseOCPIFormat(JSONContent)
|
|
18814
|
-
];
|
|
18815
|
-
const filteredResults = results.filter((ctr) => {
|
|
18816
|
-
return isISessionCryptoResult1(ctr);
|
|
18817
|
-
});
|
|
18818
|
-
const sortedResults = filteredResults.sort((ctr1, ctr2) => {
|
|
18819
|
-
if (ctr1.certainty > ctr2.certainty) {
|
|
18820
|
-
return -1;
|
|
18821
|
-
}
|
|
18822
|
-
if (ctr1.certainty < ctr2.certainty) {
|
|
18823
|
-
return 1;
|
|
18824
|
-
}
|
|
18825
|
-
return 0;
|
|
18826
|
-
});
|
|
18827
|
-
if (sortedResults.length >= 1 && sortedResults[0])
|
|
18828
|
-
processedFile.result = sortedResults[0];
|
|
19027
|
+
else if (JSONContext.startsWith("https://open.charging.cloud/contexts/publicKey+json"))
|
|
19028
|
+
processedFile.result = JSONContent;
|
|
19029
|
+
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")) {
|
|
19030
|
+
processedFile.result = new ChargeIT(this).TryToParseChargeITContainerFormat(JSONContent);
|
|
18829
19031
|
}
|
|
19032
|
+
} else {
|
|
19033
|
+
const results = [
|
|
19034
|
+
new ChargeIT(this).TryToParseChargeITContainerFormat(JSONContent),
|
|
19035
|
+
new ChargePoint(this).TryToParseChargepointFormat(JSONContent),
|
|
19036
|
+
await new OCPI(this).tryToParseOCPIFormat(JSONContent)
|
|
19037
|
+
];
|
|
19038
|
+
const filteredResults = results.filter((ctr) => {
|
|
19039
|
+
return isISessionCryptoResult1(ctr);
|
|
19040
|
+
});
|
|
19041
|
+
const sortedResults = filteredResults.sort((ctr1, ctr2) => {
|
|
19042
|
+
if (ctr1.certainty > ctr2.certainty) {
|
|
19043
|
+
return -1;
|
|
19044
|
+
}
|
|
19045
|
+
if (ctr1.certainty < ctr2.certainty) {
|
|
19046
|
+
return 1;
|
|
19047
|
+
}
|
|
19048
|
+
return 0;
|
|
19049
|
+
});
|
|
19050
|
+
if (sortedResults.length >= 1 && sortedResults[0])
|
|
19051
|
+
processedFile.result = sortedResults[0];
|
|
18830
19052
|
}
|
|
18831
19053
|
} catch (exception) {
|
|
18832
19054
|
processedFile.result = {
|
|
@@ -18870,7 +19092,7 @@ var Chargy = class {
|
|
|
18870
19092
|
if (processedFileResult.end != null && processedFileResult.end.length > 0 && (mergedCTR.end == null || mergedCTR.end.length === 0 || mergedCTR.end < processedFileResult.end))
|
|
18871
19093
|
mergedCTR.end = processedFileResult.end;
|
|
18872
19094
|
mergedCTR.description ??= processedFileResult.description;
|
|
18873
|
-
mergedCTR.
|
|
19095
|
+
mergedCTR.contracts ??= processedFileResult.contracts;
|
|
18874
19096
|
if (!mergedCTR.chargingStationOperators)
|
|
18875
19097
|
mergedCTR.chargingStationOperators = processedFileResult.chargingStationOperators;
|
|
18876
19098
|
else if (processedFileResult.chargingStationOperators)
|
|
@@ -18901,7 +19123,7 @@ var Chargy = class {
|
|
|
18901
19123
|
else if (processedFileResult.mediationServices)
|
|
18902
19124
|
for (const mediationService of processedFileResult.mediationServices)
|
|
18903
19125
|
mergedCTR.mediationServices.push(mediationService);
|
|
18904
|
-
} else if (
|
|
19126
|
+
} else if (IsAPublicKey(processedFileResult)) {
|
|
18905
19127
|
mergedCTR.publicKeys ??= new Array();
|
|
18906
19128
|
mergedCTR.publicKeys.push(processedFileResult);
|
|
18907
19129
|
} else if (IsAPublicKeyLookup(processedFileResult)) {
|
|
@@ -18949,11 +19171,11 @@ var Chargy = class {
|
|
|
18949
19171
|
if (chargingPool.chargingStations) {
|
|
18950
19172
|
for (const chargingStation of chargingPool.chargingStations) {
|
|
18951
19173
|
this.chargingStations.push(chargingStation);
|
|
18952
|
-
for (const EVSE of chargingStation.EVSEs) {
|
|
19174
|
+
for (const EVSE of chargingStation.EVSEs ?? []) {
|
|
18953
19175
|
EVSE.chargingStation = chargingStation;
|
|
18954
19176
|
EVSE.chargingStationId = chargingStation["@id"];
|
|
18955
19177
|
this.EVSEs.push(EVSE);
|
|
18956
|
-
for (const meter of EVSE.
|
|
19178
|
+
for (const meter of EVSE.energyMeters ?? []) {
|
|
18957
19179
|
meter.EVSE = EVSE;
|
|
18958
19180
|
meter.EVSEId = EVSE["@id"];
|
|
18959
19181
|
meter.chargingStation = chargingStation;
|
|
@@ -18968,11 +19190,11 @@ var Chargy = class {
|
|
|
18968
19190
|
if (chargingStationOperator.chargingStations) {
|
|
18969
19191
|
for (const chargingStation of chargingStationOperator.chargingStations) {
|
|
18970
19192
|
this.chargingStations.push(chargingStation);
|
|
18971
|
-
for (const EVSE of chargingStation.EVSEs) {
|
|
19193
|
+
for (const EVSE of chargingStation.EVSEs ?? []) {
|
|
18972
19194
|
EVSE.chargingStation = chargingStation;
|
|
18973
19195
|
EVSE.chargingStationId = chargingStation["@id"];
|
|
18974
19196
|
this.EVSEs.push(EVSE);
|
|
18975
|
-
for (const meter of EVSE.
|
|
19197
|
+
for (const meter of EVSE.energyMeters ?? []) {
|
|
18976
19198
|
meter.EVSE = EVSE;
|
|
18977
19199
|
meter.EVSEId = EVSE["@id"];
|
|
18978
19200
|
meter.chargingStation = chargingStation;
|
|
@@ -18985,7 +19207,7 @@ var Chargy = class {
|
|
|
18985
19207
|
if (chargingStationOperator.EVSEs) {
|
|
18986
19208
|
for (const EVSE of chargingStationOperator.EVSEs) {
|
|
18987
19209
|
this.EVSEs.push(EVSE);
|
|
18988
|
-
for (const meter of EVSE.
|
|
19210
|
+
for (const meter of EVSE.energyMeters ?? []) {
|
|
18989
19211
|
meter.EVSE = EVSE;
|
|
18990
19212
|
meter.EVSEId = EVSE["@id"];
|
|
18991
19213
|
this.meters.push(meter);
|
|
@@ -19000,11 +19222,11 @@ var Chargy = class {
|
|
|
19000
19222
|
if (chargingPool.chargingStations) {
|
|
19001
19223
|
for (const chargingStation of chargingPool.chargingStations) {
|
|
19002
19224
|
this.chargingStations.push(chargingStation);
|
|
19003
|
-
for (const EVSE of chargingStation.EVSEs) {
|
|
19225
|
+
for (const EVSE of chargingStation.EVSEs ?? []) {
|
|
19004
19226
|
EVSE.chargingStation = chargingStation;
|
|
19005
19227
|
EVSE.chargingStationId = chargingStation["@id"];
|
|
19006
19228
|
this.EVSEs.push(EVSE);
|
|
19007
|
-
for (const meter of EVSE.
|
|
19229
|
+
for (const meter of EVSE.energyMeters ?? []) {
|
|
19008
19230
|
meter.EVSE = EVSE;
|
|
19009
19231
|
meter.EVSEId = EVSE["@id"];
|
|
19010
19232
|
meter.chargingStation = chargingStation;
|
|
@@ -19019,11 +19241,11 @@ var Chargy = class {
|
|
|
19019
19241
|
if (this.internalCTR.chargingStations) {
|
|
19020
19242
|
for (const chargingStation of this.internalCTR.chargingStations) {
|
|
19021
19243
|
this.chargingStations.push(chargingStation);
|
|
19022
|
-
for (const EVSE of chargingStation.EVSEs) {
|
|
19244
|
+
for (const EVSE of chargingStation.EVSEs ?? []) {
|
|
19023
19245
|
EVSE.chargingStation = chargingStation;
|
|
19024
19246
|
EVSE.chargingStationId = chargingStation["@id"];
|
|
19025
19247
|
this.EVSEs.push(EVSE);
|
|
19026
|
-
for (const meter of EVSE.
|
|
19248
|
+
for (const meter of EVSE.energyMeters ?? []) {
|
|
19027
19249
|
meter.EVSE = EVSE;
|
|
19028
19250
|
meter.EVSEId = EVSE["@id"];
|
|
19029
19251
|
meter.chargingStation = chargingStation;
|
|
@@ -19031,8 +19253,8 @@ var Chargy = class {
|
|
|
19031
19253
|
this.meters.push(meter);
|
|
19032
19254
|
}
|
|
19033
19255
|
}
|
|
19034
|
-
if (chargingStation.
|
|
19035
|
-
for (const meter of chargingStation.
|
|
19256
|
+
if (chargingStation.energyMeters) {
|
|
19257
|
+
for (const meter of chargingStation.energyMeters ?? []) {
|
|
19036
19258
|
meter.chargingStation = chargingStation;
|
|
19037
19259
|
meter.chargingStationId = chargingStation["@id"];
|
|
19038
19260
|
this.meters.push(meter);
|
|
@@ -19059,7 +19281,7 @@ var Chargy = class {
|
|
|
19059
19281
|
//#endregion
|
|
19060
19282
|
//#region (private) hasInplausibleChargingSessionTotalEnergyMeasurement(chargingSession)
|
|
19061
19283
|
hasInplausibleChargingSessionTotalEnergyMeasurement(chargingSession) {
|
|
19062
|
-
for (const measurement of chargingSession.measurements) {
|
|
19284
|
+
for (const measurement of chargingSession.measurements ?? []) {
|
|
19063
19285
|
if (measurement.name !== "ENERGY_TOTAL" || measurement.values.length < 2) {
|
|
19064
19286
|
continue;
|
|
19065
19287
|
}
|
|
@@ -19219,7 +19441,7 @@ var Chargy = class {
|
|
|
19219
19441
|
if (ctr.end != null && ctr.end.length > 0 && (mergedCTR.end == null || mergedCTR.end.length === 0 || mergedCTR.end < ctr.end))
|
|
19220
19442
|
mergedCTR.end = ctr.end;
|
|
19221
19443
|
mergedCTR.description ??= ctr.description;
|
|
19222
|
-
mergedCTR.
|
|
19444
|
+
mergedCTR.contracts ??= ctr.contracts;
|
|
19223
19445
|
if (!mergedCTR.chargingStationOperators)
|
|
19224
19446
|
mergedCTR.chargingStationOperators = ctr.chargingStationOperators;
|
|
19225
19447
|
else if (ctr.chargingStationOperators)
|
|
@@ -19254,18 +19476,6 @@ var Chargy = class {
|
|
|
19254
19476
|
return mergedCTR;
|
|
19255
19477
|
}
|
|
19256
19478
|
};
|
|
19257
|
-
|
|
19258
|
-
// src/verificationResults.ts
|
|
19259
|
-
function toSessionVerificationResults(CTR, noRecordsMessage = { "en": "No charge transparency records found!" }) {
|
|
19260
|
-
const verificationResults = (CTR.chargingSessions ?? []).map((session) => session.verificationResult).filter(isISessionCryptoResult1);
|
|
19261
|
-
if (verificationResults.length > 0)
|
|
19262
|
-
return verificationResults;
|
|
19263
|
-
return {
|
|
19264
|
-
status: "Unvalidated" /* Unvalidated */,
|
|
19265
|
-
message: noRecordsMessage,
|
|
19266
|
-
certainty: 0
|
|
19267
|
-
};
|
|
19268
|
-
}
|
|
19269
19479
|
/*! Bundled license information:
|
|
19270
19480
|
|
|
19271
19481
|
ieee754/index.js:
|
|
@@ -19280,6 +19490,6 @@ buffer/index.js:
|
|
|
19280
19490
|
*)
|
|
19281
19491
|
*/
|
|
19282
19492
|
|
|
19283
|
-
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,
|
|
19493
|
+
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, CreateWarning, 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 };
|
|
19284
19494
|
//# sourceMappingURL=index.js.map
|
|
19285
19495
|
//# sourceMappingURL=index.js.map
|