@open-charging-cloud/chargy-core 0.6.3 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/ACrypt.d.ts +2 -2
- package/dist/ACrypt.d.ts.map +1 -1
- package/dist/Alfen.d.ts +3 -3
- package/dist/Alfen.d.ts.map +1 -1
- package/dist/BSMCrypt01.d.ts +1 -1
- package/dist/BSMCrypt01.d.ts.map +1 -1
- package/dist/EMHCrypt01.d.ts +1 -1
- package/dist/EMHCrypt01.d.ts.map +1 -1
- package/dist/GDFCrypt01.d.ts +1 -1
- package/dist/GDFCrypt01.d.ts.map +1 -1
- package/dist/Mennekes.d.ts +0 -3
- package/dist/Mennekes.d.ts.map +1 -1
- package/dist/OCMF.d.ts +8 -7
- package/dist/OCMF.d.ts.map +1 -1
- package/dist/OCPI.d.ts +2 -1
- package/dist/OCPI.d.ts.map +1 -1
- package/dist/PCDF.d.ts +5 -4
- package/dist/PCDF.d.ts.map +1 -1
- package/dist/QIDigital_DCC.d.ts +20 -19
- package/dist/QIDigital_DCC.d.ts.map +1 -1
- package/dist/SAFE_XML.d.ts +1 -26
- package/dist/SAFE_XML.d.ts.map +1 -1
- package/dist/browser/index.js +947 -727
- package/dist/browser/index.js.map +1 -1
- package/dist/chargeIT.d.ts +2 -2
- package/dist/chargeIT.d.ts.map +1 -1
- package/dist/chargePoint.d.ts +1 -1
- package/dist/chargePoint.d.ts.map +1 -1
- package/dist/chargy.d.ts +10 -9
- package/dist/chargy.d.ts.map +1 -1
- package/dist/index.d.ts +3 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/{CryptoUtils.d.ts → interfaces/CryptoUtils.d.ts} +7 -2
- package/dist/interfaces/CryptoUtils.d.ts.map +1 -0
- package/dist/interfaces/IChargeTransparencyLiveLink.d.ts +2 -2
- package/dist/interfaces/IChargeTransparencyLiveLink.d.ts.map +1 -1
- package/dist/interfaces/IChargeTransparencyRecord.d.ts +43 -19
- package/dist/interfaces/IChargeTransparencyRecord.d.ts.map +1 -1
- package/dist/interfaces/IPublicKeyInfo.d.ts +49 -18
- package/dist/interfaces/IPublicKeyInfo.d.ts.map +1 -1
- package/dist/interfaces/chargyInterfaces.d.ts +111 -97
- package/dist/interfaces/chargyInterfaces.d.ts.map +1 -1
- package/dist/{chargyLib.d.ts → interfaces/chargyLib.d.ts} +50 -20
- package/dist/interfaces/chargyLib.d.ts.map +1 -0
- package/dist/interfaces/secp224k1.d.ts.map +1 -0
- package/dist/node/index.js +946 -726
- package/dist/node/index.js.map +1 -1
- package/dist/verificationResults.d.ts +1 -17
- package/dist/verificationResults.d.ts.map +1 -1
- package/i18n.json +30 -0
- package/package.json +1 -1
- package/dist/CanonicalJSON.d.ts +0 -14
- package/dist/CanonicalJSON.d.ts.map +0 -1
- package/dist/CryptoUtils.d.ts.map +0 -1
- package/dist/chargyLib.d.ts.map +0 -1
- package/dist/secp224k1.d.ts.map +0 -1
- /package/dist/{secp224k1.d.ts → interfaces/secp224k1.d.ts} +0 -0
package/dist/node/index.js
CHANGED
|
@@ -7992,120 +7992,6 @@ var require_elliptic = __commonJS({
|
|
|
7992
7992
|
}
|
|
7993
7993
|
});
|
|
7994
7994
|
|
|
7995
|
-
// src/secp224k1.ts
|
|
7996
|
-
var secp224k1 = class {
|
|
7997
|
-
// Pcurve = 2**224 - 2**32 - 2**12 - 2**11 - 2**9 - 2**7 - 2**4 - 2**1 - 1 or
|
|
7998
|
-
// FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFE56D
|
|
7999
|
-
Zero = BigInt("0");
|
|
8000
|
-
One = BigInt("1");
|
|
8001
|
-
Two = BigInt("2");
|
|
8002
|
-
Three = BigInt("3");
|
|
8003
|
-
Pcurve = BigInt("26959946667150639794667015087019630673637144422540572481099315275117");
|
|
8004
|
-
// The proven prime
|
|
8005
|
-
N = BigInt("0x010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7");
|
|
8006
|
-
// Number of points in the field
|
|
8007
|
-
Acurve = BigInt(0);
|
|
8008
|
-
// Defined on the elliptic curve. y^2 = x^3 + Acurve * x + 5
|
|
8009
|
-
Gx = BigInt("0xA1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C");
|
|
8010
|
-
Gy = BigInt("0x7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5");
|
|
8011
|
-
GPoint = [this.Gx, this.Gy];
|
|
8012
|
-
// This is our generator point. Trillions of dif ones possible
|
|
8013
|
-
Sign(hash, RandomNumber, privateKey) {
|
|
8014
|
-
const RandSignPoint = this.ECmultiply(this.GPoint, RandomNumber);
|
|
8015
|
-
if (RandSignPoint.length >= 1 && RandSignPoint[0] != null) {
|
|
8016
|
-
const r = this.modulo(RandSignPoint[0], this.N);
|
|
8017
|
-
const s = this.modulo((hash + r * privateKey) * this.modInv(RandomNumber, this.N), this.N);
|
|
8018
|
-
return [r, s];
|
|
8019
|
-
}
|
|
8020
|
-
return null;
|
|
8021
|
-
}
|
|
8022
|
-
validate(hash, signatureR, signatureS, PublicKey) {
|
|
8023
|
-
if (signatureR == this.Zero || signatureR >= this.N)
|
|
8024
|
-
throw new Error("Invalid R");
|
|
8025
|
-
if (signatureS == this.Zero || signatureS >= this.N)
|
|
8026
|
-
throw new Error("Invalid S");
|
|
8027
|
-
const w = this.modInv(signatureS, this.N);
|
|
8028
|
-
const u1 = this.ECmultiply(this.GPoint, this.modulo(w * hash, this.N));
|
|
8029
|
-
const u2 = this.ECmultiply(PublicKey, this.modulo(w * signatureR, this.N));
|
|
8030
|
-
const validation = this.ECadd(u1, u2);
|
|
8031
|
-
return validation[0] == signatureR;
|
|
8032
|
-
}
|
|
8033
|
-
modulo(n, m) {
|
|
8034
|
-
return (n % m + m) % m;
|
|
8035
|
-
}
|
|
8036
|
-
zfill(s) {
|
|
8037
|
-
while (s.length < 56) {
|
|
8038
|
-
s = "0" + s;
|
|
8039
|
-
}
|
|
8040
|
-
return s;
|
|
8041
|
-
}
|
|
8042
|
-
modInv(a, n = this.Pcurve) {
|
|
8043
|
-
let lm = BigInt(1), hm = BigInt(0), high = n, low = this.modulo(a, n);
|
|
8044
|
-
while (low > 1) {
|
|
8045
|
-
const ratio = high / low, nm = hm - ratio * lm, newm = high - ratio * low;
|
|
8046
|
-
hm = lm;
|
|
8047
|
-
lm = nm;
|
|
8048
|
-
high = low;
|
|
8049
|
-
low = newm;
|
|
8050
|
-
}
|
|
8051
|
-
return this.modulo(lm, n);
|
|
8052
|
-
}
|
|
8053
|
-
ECadd(a, b) {
|
|
8054
|
-
if (a[0] != void 0 && b[0] != void 0 && a[1] != void 0 && b[1] != void 0) {
|
|
8055
|
-
const LamAdd = this.modulo((b[1] - a[1]) * this.modInv(b[0] - a[0]), this.Pcurve);
|
|
8056
|
-
const x = this.modulo(LamAdd * LamAdd - a[0] - b[0], this.Pcurve);
|
|
8057
|
-
const y = this.modulo(LamAdd * (a[0] - x) - a[1], this.Pcurve);
|
|
8058
|
-
return [x, y];
|
|
8059
|
-
}
|
|
8060
|
-
throw new Error("Invalid EC Point Addition!");
|
|
8061
|
-
}
|
|
8062
|
-
ECdouble(a) {
|
|
8063
|
-
if (a[0] != void 0 && a[1] != void 0) {
|
|
8064
|
-
const Lam = this.modulo((a[0] * a[0] * this.Three + this.Acurve) * this.modInv(a[1] * this.Two), this.Pcurve);
|
|
8065
|
-
const x = this.modulo(Lam * Lam - a[0] * this.Two, this.Pcurve);
|
|
8066
|
-
const y = this.modulo(Lam * (a[0] - x) - a[1], this.Pcurve);
|
|
8067
|
-
return [x, y];
|
|
8068
|
-
}
|
|
8069
|
-
throw new Error("Invalid EC Point Doubling!");
|
|
8070
|
-
}
|
|
8071
|
-
ECmultiply(GenPoint, ScalarHex) {
|
|
8072
|
-
if (ScalarHex == this.Zero || ScalarHex >= this.N)
|
|
8073
|
-
throw new Error("Invalid Scalar/Private Key");
|
|
8074
|
-
const ScalarBinary = ScalarHex.toString(2);
|
|
8075
|
-
let Q = GenPoint;
|
|
8076
|
-
for (let i = 1; i < ScalarBinary.length; i++) {
|
|
8077
|
-
Q = this.ECdouble(Q);
|
|
8078
|
-
if (ScalarBinary[i] === "1") {
|
|
8079
|
-
Q = this.ECadd(Q, GenPoint);
|
|
8080
|
-
}
|
|
8081
|
-
}
|
|
8082
|
-
return Q;
|
|
8083
|
-
}
|
|
8084
|
-
// uncompressed is the accumulation of both the x and y points
|
|
8085
|
-
// compressed is the public key to share in transactions
|
|
8086
|
-
// address is the public address tho whom someone can send coin
|
|
8087
|
-
PublicKeyGenerate(PrivateKey) {
|
|
8088
|
-
if (typeof PrivateKey === "number")
|
|
8089
|
-
PrivateKey = BigInt(PrivateKey);
|
|
8090
|
-
if (typeof PrivateKey === "string")
|
|
8091
|
-
PrivateKey = BigInt(PrivateKey);
|
|
8092
|
-
const publicKey = this.ECmultiply(this.GPoint, PrivateKey);
|
|
8093
|
-
if (publicKey[0] !== void 0 && publicKey[1] !== void 0) {
|
|
8094
|
-
const Px = this.zfill(publicKey[0].toString(16));
|
|
8095
|
-
const Py = this.zfill(publicKey[1].toString(16));
|
|
8096
|
-
return {
|
|
8097
|
-
x: publicKey[0],
|
|
8098
|
-
y: publicKey[1],
|
|
8099
|
-
xy: [Px, Py],
|
|
8100
|
-
uncompressed: publicKey[0].toString(16) + publicKey[1].toString(16),
|
|
8101
|
-
compressed: "04" + Px + Py,
|
|
8102
|
-
address: this.modulo(publicKey[1], this.Two) == this.One ? "03" + Px : "02" + Px
|
|
8103
|
-
};
|
|
8104
|
-
}
|
|
8105
|
-
return void 0;
|
|
8106
|
-
}
|
|
8107
|
-
};
|
|
8108
|
-
|
|
8109
7995
|
// src/interfaces/chargyInterfaces.ts
|
|
8110
7996
|
var chargyInterfaces_exports = {};
|
|
8111
7997
|
__export(chargyInterfaces_exports, {
|
|
@@ -8118,7 +8004,7 @@ __export(chargyInterfaces_exports, {
|
|
|
8118
8004
|
IECCurves: () => IECCurves,
|
|
8119
8005
|
IEncoding: () => IEncoding,
|
|
8120
8006
|
InformationRelevance: () => InformationRelevance,
|
|
8121
|
-
|
|
8007
|
+
OIDInfo: () => OIDInfo,
|
|
8122
8008
|
SessionVerificationResult: () => SessionVerificationResult,
|
|
8123
8009
|
SignatureFormats: () => SignatureFormats,
|
|
8124
8010
|
VerificationResult: () => VerificationResult,
|
|
@@ -8126,23 +8012,9 @@ __export(chargyInterfaces_exports, {
|
|
|
8126
8012
|
isGeoLocation: () => isGeoLocation,
|
|
8127
8013
|
isICryptoResult: () => isICryptoResult,
|
|
8128
8014
|
isIFileInfo: () => isIFileInfo,
|
|
8129
|
-
isIPublicKeyXY: () => isIPublicKeyXY,
|
|
8130
8015
|
isISessionCryptoResult1: () => isISessionCryptoResult1,
|
|
8131
|
-
isISessionCryptoResult2: () => isISessionCryptoResult2
|
|
8132
|
-
isMultilanguageText: () => isMultilanguageText,
|
|
8133
|
-
isOIDInfo: () => isOIDInfo,
|
|
8134
|
-
isObject: () => isObject,
|
|
8135
|
-
isString: () => isString,
|
|
8136
|
-
isStringArray: () => isStringArray,
|
|
8137
|
-
isStringOrOIDInfo: () => isStringOrOIDInfo,
|
|
8138
|
-
isStringOrStringArray: () => isStringOrStringArray
|
|
8016
|
+
isISessionCryptoResult2: () => isISessionCryptoResult2
|
|
8139
8017
|
});
|
|
8140
|
-
function isObject(data) {
|
|
8141
|
-
return typeof data === "object" && data !== null;
|
|
8142
|
-
}
|
|
8143
|
-
function isMultilanguageText(data) {
|
|
8144
|
-
return isObject(data) && Object.values(data).every((value) => typeof value === "string");
|
|
8145
|
-
}
|
|
8146
8018
|
function isGeoLocation(data) {
|
|
8147
8019
|
if (!isObject(data))
|
|
8148
8020
|
return false;
|
|
@@ -8150,26 +8022,6 @@ function isGeoLocation(data) {
|
|
|
8150
8022
|
const longitude = data["lng"];
|
|
8151
8023
|
return (latitude === void 0 || typeof latitude === "number") && (longitude === void 0 || typeof longitude === "number");
|
|
8152
8024
|
}
|
|
8153
|
-
function isString(value) {
|
|
8154
|
-
return typeof value === "string";
|
|
8155
|
-
}
|
|
8156
|
-
function isStringArray(value) {
|
|
8157
|
-
return Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
8158
|
-
}
|
|
8159
|
-
function isStringOrStringArray(value) {
|
|
8160
|
-
return typeof value === "string" || isStringArray(value);
|
|
8161
|
-
}
|
|
8162
|
-
function isOIDInfo(data) {
|
|
8163
|
-
if (!isObject(data))
|
|
8164
|
-
return false;
|
|
8165
|
-
return typeof data["oid"] === "string" && typeof data["name"] === "string";
|
|
8166
|
-
}
|
|
8167
|
-
function isStringOrOIDInfo(value) {
|
|
8168
|
-
return typeof value === "string" || isOIDInfo(value);
|
|
8169
|
-
}
|
|
8170
|
-
function isIPublicKeyXY(obj) {
|
|
8171
|
-
return typeof obj === "object" && obj !== null && typeof obj.x === "string" && typeof obj.y === "string";
|
|
8172
|
-
}
|
|
8173
8025
|
var IECCurves = /* @__PURE__ */ ((IECCurves2) => {
|
|
8174
8026
|
IECCurves2["secp192r1"] = "secp192r1";
|
|
8175
8027
|
IECCurves2["secp224k1"] = "secp224k1";
|
|
@@ -8184,11 +8036,6 @@ var IEncoding = /* @__PURE__ */ ((IEncoding2) => {
|
|
|
8184
8036
|
IEncoding2["base64"] = "base64";
|
|
8185
8037
|
return IEncoding2;
|
|
8186
8038
|
})(IEncoding || {});
|
|
8187
|
-
var PublicKeyFormats = /* @__PURE__ */ ((PublicKeyFormats2) => {
|
|
8188
|
-
PublicKeyFormats2["DER"] = "DER";
|
|
8189
|
-
PublicKeyFormats2["XY"] = "XY";
|
|
8190
|
-
return PublicKeyFormats2;
|
|
8191
|
-
})(PublicKeyFormats || {});
|
|
8192
8039
|
var SignatureFormats = /* @__PURE__ */ ((SignatureFormats2) => {
|
|
8193
8040
|
SignatureFormats2["DER"] = "DER";
|
|
8194
8041
|
SignatureFormats2["RS"] = "RS";
|
|
@@ -8310,12 +8157,19 @@ var DayOfWeek = /* @__PURE__ */ ((DayOfWeek2) => {
|
|
|
8310
8157
|
DayOfWeek2[DayOfWeek2["Saturday"] = 6] = "Saturday";
|
|
8311
8158
|
return DayOfWeek2;
|
|
8312
8159
|
})(DayOfWeek || {});
|
|
8160
|
+
function OIDInfo(data) {
|
|
8161
|
+
if (typeof data === "string")
|
|
8162
|
+
return data;
|
|
8163
|
+
if (isOIDInfo(data))
|
|
8164
|
+
return data.name;
|
|
8165
|
+
return "";
|
|
8166
|
+
}
|
|
8313
8167
|
function isJSONLDObject(value) {
|
|
8314
8168
|
if (typeof value !== "object" || value === null) {
|
|
8315
8169
|
return false;
|
|
8316
8170
|
}
|
|
8317
8171
|
const obj = value;
|
|
8318
|
-
return typeof obj["@context"] === "string";
|
|
8172
|
+
return typeof obj["@context"] === "string" || Array.isArray(obj["@context"]);
|
|
8319
8173
|
}
|
|
8320
8174
|
function toArrayBuffer(data) {
|
|
8321
8175
|
if (data instanceof ArrayBuffer)
|
|
@@ -8775,36 +8629,6 @@ function pad(text, paddingValue) {
|
|
|
8775
8629
|
text ??= "";
|
|
8776
8630
|
return (text + Array(2 * paddingValue).join("0")).substring(0, 2 * paddingValue);
|
|
8777
8631
|
}
|
|
8778
|
-
async function sha256(message) {
|
|
8779
|
-
let hashBuffer;
|
|
8780
|
-
if (typeof message === "string")
|
|
8781
|
-
hashBuffer = await crypto.subtle.digest("SHA-256", Buffer.from(message, "utf8"));
|
|
8782
|
-
else
|
|
8783
|
-
hashBuffer = await crypto.subtle.digest("SHA-256", message);
|
|
8784
|
-
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
8785
|
-
const hashHex = hashArray.map((b) => ("00" + b.toString(16)).slice(-2)).join("").toLowerCase();
|
|
8786
|
-
return hashHex;
|
|
8787
|
-
}
|
|
8788
|
-
async function sha384(message) {
|
|
8789
|
-
let hashBuffer;
|
|
8790
|
-
if (typeof message === "string")
|
|
8791
|
-
hashBuffer = await crypto.subtle.digest("SHA-384", Buffer.from(message, "utf8"));
|
|
8792
|
-
else
|
|
8793
|
-
hashBuffer = await crypto.subtle.digest("SHA-384", message);
|
|
8794
|
-
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
8795
|
-
const hashHex = hashArray.map((b) => ("00" + b.toString(16)).slice(-2)).join("").toLowerCase();
|
|
8796
|
-
return hashHex;
|
|
8797
|
-
}
|
|
8798
|
-
async function sha512(message) {
|
|
8799
|
-
let hashBuffer;
|
|
8800
|
-
if (typeof message === "string")
|
|
8801
|
-
hashBuffer = await crypto.subtle.digest("SHA-512", Buffer.from(message, "utf8"));
|
|
8802
|
-
else
|
|
8803
|
-
hashBuffer = await crypto.subtle.digest("SHA-512", message);
|
|
8804
|
-
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
8805
|
-
const hashHex = hashArray.map((b) => ("00" + b.toString(16)).slice(-2)).join("").toLowerCase();
|
|
8806
|
-
return hashHex;
|
|
8807
|
-
}
|
|
8808
8632
|
function asJSONObject(value) {
|
|
8809
8633
|
return isMandatoryJSONObject(value) ? value : void 0;
|
|
8810
8634
|
}
|
|
@@ -8901,6 +8725,48 @@ function parseNumber(value) {
|
|
|
8901
8725
|
}
|
|
8902
8726
|
return null;
|
|
8903
8727
|
}
|
|
8728
|
+
function isObject(data) {
|
|
8729
|
+
return typeof data === "object" && data !== null;
|
|
8730
|
+
}
|
|
8731
|
+
function isI18NString(data) {
|
|
8732
|
+
return isObject(data) && Object.values(data).every((value) => typeof value === "string");
|
|
8733
|
+
}
|
|
8734
|
+
function isString(value) {
|
|
8735
|
+
return typeof value === "string";
|
|
8736
|
+
}
|
|
8737
|
+
function isStringArray(value) {
|
|
8738
|
+
return Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
8739
|
+
}
|
|
8740
|
+
function isStringOrStringArray(value) {
|
|
8741
|
+
return typeof value === "string" || isStringArray(value);
|
|
8742
|
+
}
|
|
8743
|
+
function isOIDInfo(data) {
|
|
8744
|
+
if (!isObject(data))
|
|
8745
|
+
return false;
|
|
8746
|
+
return typeof data["oid"] === "string" && typeof data["name"] === "string";
|
|
8747
|
+
}
|
|
8748
|
+
function isStringOrOIDInfo(value) {
|
|
8749
|
+
return typeof value === "string" || isOIDInfo(value);
|
|
8750
|
+
}
|
|
8751
|
+
function isOptionalStringArray(data) {
|
|
8752
|
+
return data === void 0 || Array.isArray(data) && data.every(isString);
|
|
8753
|
+
}
|
|
8754
|
+
function isOptionalStringOrOIDInfo(data) {
|
|
8755
|
+
return data === void 0 || isStringOrOIDInfo(data);
|
|
8756
|
+
}
|
|
8757
|
+
function isEncodedValue(data) {
|
|
8758
|
+
if (isString(data))
|
|
8759
|
+
return true;
|
|
8760
|
+
if (!isMandatoryJSONObject(data))
|
|
8761
|
+
return false;
|
|
8762
|
+
if (!isString(data["value"]))
|
|
8763
|
+
return false;
|
|
8764
|
+
if (!isOptionalString(data["format"]))
|
|
8765
|
+
return false;
|
|
8766
|
+
if (!isOptionalString(data["encoding"]))
|
|
8767
|
+
return false;
|
|
8768
|
+
return true;
|
|
8769
|
+
}
|
|
8904
8770
|
function InformationRelevanceToString(InfoRelevance) {
|
|
8905
8771
|
switch (InfoRelevance) {
|
|
8906
8772
|
case "Ignored" /* Ignored */:
|
|
@@ -8961,6 +8827,187 @@ function _jsonPrettyPrinter(value, indentLevel, path, keyLookup) {
|
|
|
8961
8827
|
html += String(value);
|
|
8962
8828
|
return html;
|
|
8963
8829
|
}
|
|
8830
|
+
function base64ToBytes(value) {
|
|
8831
|
+
if (typeof Buffer !== "undefined")
|
|
8832
|
+
return Uint8Array.from(Buffer.from(value, "base64"));
|
|
8833
|
+
const binary = atob(value);
|
|
8834
|
+
const bytes = new Uint8Array(binary.length);
|
|
8835
|
+
for (let i = 0; i < binary.length; i++)
|
|
8836
|
+
bytes[i] = binary.charCodeAt(i);
|
|
8837
|
+
return bytes;
|
|
8838
|
+
}
|
|
8839
|
+
function bytesToBase64(bytes) {
|
|
8840
|
+
if (typeof Buffer !== "undefined")
|
|
8841
|
+
return Buffer.from(bytes).toString("base64");
|
|
8842
|
+
let binary = "";
|
|
8843
|
+
for (const byte of bytes)
|
|
8844
|
+
binary += String.fromCharCode(byte);
|
|
8845
|
+
return btoa(binary);
|
|
8846
|
+
}
|
|
8847
|
+
function cleanHex(hex) {
|
|
8848
|
+
return hex.replace(/\s+/g, "");
|
|
8849
|
+
}
|
|
8850
|
+
function hexToBytes(hex) {
|
|
8851
|
+
const cleanedHex = cleanHex(hex);
|
|
8852
|
+
if (cleanedHex.length % 2 !== 0)
|
|
8853
|
+
throw new Error("Hex strings must have even length!");
|
|
8854
|
+
if (!/^[0-9a-fA-F]*$/.test(cleanedHex))
|
|
8855
|
+
throw new Error("Invalid hexadecimal string!");
|
|
8856
|
+
const bytes = new Uint8Array(cleanedHex.length / 2);
|
|
8857
|
+
for (let index = 0; index < cleanedHex.length; index += 2)
|
|
8858
|
+
bytes[index / 2] = Number.parseInt(cleanedHex.substring(index, index + 2), 16);
|
|
8859
|
+
return bytes;
|
|
8860
|
+
}
|
|
8861
|
+
function bytesToHex(bytes) {
|
|
8862
|
+
return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
8863
|
+
}
|
|
8864
|
+
async function sha256(message) {
|
|
8865
|
+
return bytesToHex(await sha256____(message));
|
|
8866
|
+
}
|
|
8867
|
+
async function sha384(message) {
|
|
8868
|
+
return bytesToHex(await sha384____(message));
|
|
8869
|
+
}
|
|
8870
|
+
async function sha512(message) {
|
|
8871
|
+
return bytesToHex(await sha512____(message));
|
|
8872
|
+
}
|
|
8873
|
+
async function sha256____(message) {
|
|
8874
|
+
let hashBuffer;
|
|
8875
|
+
if (typeof message === "string")
|
|
8876
|
+
hashBuffer = await crypto.subtle.digest("SHA-256", Buffer.from(message, "utf8"));
|
|
8877
|
+
else
|
|
8878
|
+
hashBuffer = await crypto.subtle.digest("SHA-256", message);
|
|
8879
|
+
return new Uint8Array(hashBuffer);
|
|
8880
|
+
}
|
|
8881
|
+
async function sha384____(message) {
|
|
8882
|
+
let hashBuffer;
|
|
8883
|
+
if (typeof message === "string")
|
|
8884
|
+
hashBuffer = await crypto.subtle.digest("SHA-384", Buffer.from(message, "utf8"));
|
|
8885
|
+
else
|
|
8886
|
+
hashBuffer = await crypto.subtle.digest("SHA-384", message);
|
|
8887
|
+
return new Uint8Array(hashBuffer);
|
|
8888
|
+
}
|
|
8889
|
+
async function sha512____(message) {
|
|
8890
|
+
let hashBuffer;
|
|
8891
|
+
if (typeof message === "string")
|
|
8892
|
+
hashBuffer = await crypto.subtle.digest("SHA-512", Buffer.from(message, "utf8"));
|
|
8893
|
+
else
|
|
8894
|
+
hashBuffer = await crypto.subtle.digest("SHA-512", message);
|
|
8895
|
+
return new Uint8Array(hashBuffer);
|
|
8896
|
+
}
|
|
8897
|
+
|
|
8898
|
+
// src/interfaces/secp224k1.ts
|
|
8899
|
+
var secp224k1 = class {
|
|
8900
|
+
// Pcurve = 2**224 - 2**32 - 2**12 - 2**11 - 2**9 - 2**7 - 2**4 - 2**1 - 1 or
|
|
8901
|
+
// FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFE56D
|
|
8902
|
+
Zero = BigInt("0");
|
|
8903
|
+
One = BigInt("1");
|
|
8904
|
+
Two = BigInt("2");
|
|
8905
|
+
Three = BigInt("3");
|
|
8906
|
+
Pcurve = BigInt("26959946667150639794667015087019630673637144422540572481099315275117");
|
|
8907
|
+
// The proven prime
|
|
8908
|
+
N = BigInt("0x010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7");
|
|
8909
|
+
// Number of points in the field
|
|
8910
|
+
Acurve = BigInt(0);
|
|
8911
|
+
// Defined on the elliptic curve. y^2 = x^3 + Acurve * x + 5
|
|
8912
|
+
Gx = BigInt("0xA1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C");
|
|
8913
|
+
Gy = BigInt("0x7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5");
|
|
8914
|
+
GPoint = [this.Gx, this.Gy];
|
|
8915
|
+
// This is our generator point. Trillions of dif ones possible
|
|
8916
|
+
Sign(hash, RandomNumber, privateKey) {
|
|
8917
|
+
const RandSignPoint = this.ECmultiply(this.GPoint, RandomNumber);
|
|
8918
|
+
if (RandSignPoint.length >= 1 && RandSignPoint[0] != null) {
|
|
8919
|
+
const r = this.modulo(RandSignPoint[0], this.N);
|
|
8920
|
+
const s = this.modulo((hash + r * privateKey) * this.modInv(RandomNumber, this.N), this.N);
|
|
8921
|
+
return [r, s];
|
|
8922
|
+
}
|
|
8923
|
+
return null;
|
|
8924
|
+
}
|
|
8925
|
+
validate(hash, signatureR, signatureS, PublicKey) {
|
|
8926
|
+
if (signatureR == this.Zero || signatureR >= this.N)
|
|
8927
|
+
throw new Error("Invalid R");
|
|
8928
|
+
if (signatureS == this.Zero || signatureS >= this.N)
|
|
8929
|
+
throw new Error("Invalid S");
|
|
8930
|
+
const w = this.modInv(signatureS, this.N);
|
|
8931
|
+
const u1 = this.ECmultiply(this.GPoint, this.modulo(w * hash, this.N));
|
|
8932
|
+
const u2 = this.ECmultiply(PublicKey, this.modulo(w * signatureR, this.N));
|
|
8933
|
+
const validation = this.ECadd(u1, u2);
|
|
8934
|
+
return validation[0] == signatureR;
|
|
8935
|
+
}
|
|
8936
|
+
modulo(n, m) {
|
|
8937
|
+
return (n % m + m) % m;
|
|
8938
|
+
}
|
|
8939
|
+
zfill(s) {
|
|
8940
|
+
while (s.length < 56) {
|
|
8941
|
+
s = "0" + s;
|
|
8942
|
+
}
|
|
8943
|
+
return s;
|
|
8944
|
+
}
|
|
8945
|
+
modInv(a, n = this.Pcurve) {
|
|
8946
|
+
let lm = BigInt(1), hm = BigInt(0), high = n, low = this.modulo(a, n);
|
|
8947
|
+
while (low > 1) {
|
|
8948
|
+
const ratio = high / low, nm = hm - ratio * lm, newm = high - ratio * low;
|
|
8949
|
+
hm = lm;
|
|
8950
|
+
lm = nm;
|
|
8951
|
+
high = low;
|
|
8952
|
+
low = newm;
|
|
8953
|
+
}
|
|
8954
|
+
return this.modulo(lm, n);
|
|
8955
|
+
}
|
|
8956
|
+
ECadd(a, b) {
|
|
8957
|
+
if (a[0] != void 0 && b[0] != void 0 && a[1] != void 0 && b[1] != void 0) {
|
|
8958
|
+
const LamAdd = this.modulo((b[1] - a[1]) * this.modInv(b[0] - a[0]), this.Pcurve);
|
|
8959
|
+
const x = this.modulo(LamAdd * LamAdd - a[0] - b[0], this.Pcurve);
|
|
8960
|
+
const y = this.modulo(LamAdd * (a[0] - x) - a[1], this.Pcurve);
|
|
8961
|
+
return [x, y];
|
|
8962
|
+
}
|
|
8963
|
+
throw new Error("Invalid EC Point Addition!");
|
|
8964
|
+
}
|
|
8965
|
+
ECdouble(a) {
|
|
8966
|
+
if (a[0] != void 0 && a[1] != void 0) {
|
|
8967
|
+
const Lam = this.modulo((a[0] * a[0] * this.Three + this.Acurve) * this.modInv(a[1] * this.Two), this.Pcurve);
|
|
8968
|
+
const x = this.modulo(Lam * Lam - a[0] * this.Two, this.Pcurve);
|
|
8969
|
+
const y = this.modulo(Lam * (a[0] - x) - a[1], this.Pcurve);
|
|
8970
|
+
return [x, y];
|
|
8971
|
+
}
|
|
8972
|
+
throw new Error("Invalid EC Point Doubling!");
|
|
8973
|
+
}
|
|
8974
|
+
ECmultiply(GenPoint, ScalarHex) {
|
|
8975
|
+
if (ScalarHex == this.Zero || ScalarHex >= this.N)
|
|
8976
|
+
throw new Error("Invalid Scalar/Private Key");
|
|
8977
|
+
const ScalarBinary = ScalarHex.toString(2);
|
|
8978
|
+
let Q = GenPoint;
|
|
8979
|
+
for (let i = 1; i < ScalarBinary.length; i++) {
|
|
8980
|
+
Q = this.ECdouble(Q);
|
|
8981
|
+
if (ScalarBinary[i] === "1") {
|
|
8982
|
+
Q = this.ECadd(Q, GenPoint);
|
|
8983
|
+
}
|
|
8984
|
+
}
|
|
8985
|
+
return Q;
|
|
8986
|
+
}
|
|
8987
|
+
// uncompressed is the accumulation of both the x and y points
|
|
8988
|
+
// compressed is the public key to share in transactions
|
|
8989
|
+
// address is the public address tho whom someone can send coin
|
|
8990
|
+
PublicKeyGenerate(PrivateKey) {
|
|
8991
|
+
if (typeof PrivateKey === "number")
|
|
8992
|
+
PrivateKey = BigInt(PrivateKey);
|
|
8993
|
+
if (typeof PrivateKey === "string")
|
|
8994
|
+
PrivateKey = BigInt(PrivateKey);
|
|
8995
|
+
const publicKey = this.ECmultiply(this.GPoint, PrivateKey);
|
|
8996
|
+
if (publicKey[0] !== void 0 && publicKey[1] !== void 0) {
|
|
8997
|
+
const Px = this.zfill(publicKey[0].toString(16));
|
|
8998
|
+
const Py = this.zfill(publicKey[1].toString(16));
|
|
8999
|
+
return {
|
|
9000
|
+
x: publicKey[0],
|
|
9001
|
+
y: publicKey[1],
|
|
9002
|
+
xy: [Px, Py],
|
|
9003
|
+
uncompressed: publicKey[0].toString(16) + publicKey[1].toString(16),
|
|
9004
|
+
compressed: "04" + Px + Py,
|
|
9005
|
+
address: this.modulo(publicKey[1], this.Two) == this.One ? "03" + Px : "02" + Px
|
|
9006
|
+
};
|
|
9007
|
+
}
|
|
9008
|
+
return void 0;
|
|
9009
|
+
}
|
|
9010
|
+
};
|
|
8964
9011
|
|
|
8965
9012
|
// src/ACrypt.ts
|
|
8966
9013
|
var ACrypt = class {
|
|
@@ -9192,8 +9239,8 @@ var Alfen = class {
|
|
|
9192
9239
|
"Signature": this.bufferToHex(Signature)
|
|
9193
9240
|
});
|
|
9194
9241
|
}
|
|
9195
|
-
const evseId =
|
|
9196
|
-
const chargingStationId =
|
|
9242
|
+
const evseId = ContainerInfos.chargingStations?.[0]?.EVSEs?.[0]?.["@id"] ?? "DE*GEF*EVSE*CHARGY*1";
|
|
9243
|
+
const chargingStationId = ContainerInfos.chargingStations?.[0]?.["@id"] ?? "DE*GEF*STATION*CHARGY*1";
|
|
9197
9244
|
const chargingSessionId = asString(chargingSession?.["@id"]);
|
|
9198
9245
|
const firstDataSet = getFirstArrayElement(common.dataSets, "Missing first Alfen data set");
|
|
9199
9246
|
const lastDataSet = getLastArrayElement(common.dataSets, "Missing last Alfen data set");
|
|
@@ -9218,10 +9265,18 @@ var Alfen = class {
|
|
|
9218
9265
|
"@id": chargingStationId,
|
|
9219
9266
|
// ToDo: The container infos are not validated yet!
|
|
9220
9267
|
"description": asJSONObject(chargingStation?.["description"]),
|
|
9221
|
-
"manufacturer":
|
|
9222
|
-
|
|
9223
|
-
|
|
9224
|
-
"
|
|
9268
|
+
"manufacturer": {
|
|
9269
|
+
"name": asString(chargingStation?.["manufacturer"])
|
|
9270
|
+
},
|
|
9271
|
+
"model": {
|
|
9272
|
+
"name": asString(chargingStation?.["type"])
|
|
9273
|
+
},
|
|
9274
|
+
"hardware": {
|
|
9275
|
+
"serialNumber": asString(chargingStation?.["serialNumber"])
|
|
9276
|
+
},
|
|
9277
|
+
"firmware": {
|
|
9278
|
+
"version": asString(chargingStation?.["softwareVersion"])
|
|
9279
|
+
},
|
|
9225
9280
|
"legalCompliance": asJSONObject(chargingStation?.["legalCompliance"]),
|
|
9226
9281
|
"geoLocation": asJSONObject(chargingStation?.["geoLocation"]),
|
|
9227
9282
|
"address": asJSONObject(chargingStation?.["address"]),
|
|
@@ -9231,18 +9286,29 @@ var Alfen = class {
|
|
|
9231
9286
|
"description": asJSONObject(evse?.["description"]),
|
|
9232
9287
|
"connectors": [{
|
|
9233
9288
|
"type": asString(connector?.["type"]) ?? "",
|
|
9234
|
-
"
|
|
9289
|
+
"cable": {
|
|
9290
|
+
"length": asNumber(connector?.["cableLength"]) ?? 0,
|
|
9291
|
+
"looses": asNumber(connector?.["cableLooses"]) ?? 0
|
|
9292
|
+
}
|
|
9235
9293
|
}],
|
|
9236
|
-
"
|
|
9294
|
+
"energyMeters": [
|
|
9237
9295
|
{
|
|
9238
9296
|
"@id": common.MeterId,
|
|
9239
|
-
"manufacturer":
|
|
9240
|
-
|
|
9241
|
-
|
|
9242
|
-
|
|
9243
|
-
"
|
|
9244
|
-
|
|
9245
|
-
|
|
9297
|
+
"manufacturer": {
|
|
9298
|
+
"name": asString(energyMeter?.["manufacturer"]),
|
|
9299
|
+
"contact": { "web": asString(energyMeter?.["manufacturerURL"]) }
|
|
9300
|
+
},
|
|
9301
|
+
"model": {
|
|
9302
|
+
"name": asString(energyMeter?.["model"]),
|
|
9303
|
+
"url": asString(energyMeter?.["modelURL"])
|
|
9304
|
+
},
|
|
9305
|
+
"hardware": {
|
|
9306
|
+
"revision": asString(energyMeter?.["hardwareVersion"])
|
|
9307
|
+
},
|
|
9308
|
+
"firmware": {
|
|
9309
|
+
"version": common.AdapterFWVersion,
|
|
9310
|
+
"checksum": common.AdapterFWChecksum
|
|
9311
|
+
},
|
|
9246
9312
|
"signatureFormat": "https://open.charging.cloud/contexts/EnergyMeterSignatureFormats/AlfenCrypt01",
|
|
9247
9313
|
"publicKeys": [
|
|
9248
9314
|
{
|
|
@@ -9342,23 +9408,21 @@ var AlfenCrypt01 = class extends ACrypt {
|
|
|
9342
9408
|
}
|
|
9343
9409
|
async VerifyChargingSession(chargingSession) {
|
|
9344
9410
|
let sessionResult = "UnknownSessionFormat" /* UnknownSessionFormat */;
|
|
9345
|
-
{
|
|
9346
|
-
|
|
9347
|
-
|
|
9348
|
-
|
|
9349
|
-
|
|
9350
|
-
|
|
9351
|
-
|
|
9352
|
-
|
|
9353
|
-
|
|
9354
|
-
|
|
9355
|
-
|
|
9356
|
-
sessionResult = "InvalidSignature" /* InvalidSignature */;
|
|
9357
|
-
}
|
|
9411
|
+
for (const measurement of chargingSession.measurements ?? []) {
|
|
9412
|
+
measurement.chargingSession = chargingSession;
|
|
9413
|
+
if (measurement.values.length > 1) {
|
|
9414
|
+
for (const measurementValue of measurement.values) {
|
|
9415
|
+
measurementValue.measurement = measurement;
|
|
9416
|
+
await this.VerifyMeasurement(measurementValue);
|
|
9417
|
+
}
|
|
9418
|
+
sessionResult = "ValidSignature" /* ValidSignature */;
|
|
9419
|
+
for (const measurementValue of measurement.values) {
|
|
9420
|
+
if (sessionResult == "ValidSignature" /* ValidSignature */ && measurementValue.result?.status != "ValidSignature" /* ValidSignature */) {
|
|
9421
|
+
sessionResult = "InvalidSignature" /* InvalidSignature */;
|
|
9358
9422
|
}
|
|
9359
|
-
}
|
|
9360
|
-
|
|
9361
|
-
|
|
9423
|
+
}
|
|
9424
|
+
} else
|
|
9425
|
+
sessionResult = "AtLeastTwoMeasurementsRequired" /* AtLeastTwoMeasurementsRequired */;
|
|
9362
9426
|
}
|
|
9363
9427
|
return {
|
|
9364
9428
|
status: sessionResult,
|
|
@@ -9388,7 +9452,7 @@ var AlfenCrypt01 = class extends ACrypt {
|
|
|
9388
9452
|
unitEncoded: SetInt8(cryptoBuffer, measurementValue.measurement.unitEncoded ?? 0, 44),
|
|
9389
9453
|
scalar: SetInt8(cryptoBuffer, measurementValue.measurement.scale, 45),
|
|
9390
9454
|
value: SetUInt64D(cryptoBuffer, measurementValue.value, 46, true),
|
|
9391
|
-
uid: SetText(cryptoBuffer, measurementValue.measurement.chargingSession?.authorizationStart["@id"] ?? "", 54),
|
|
9455
|
+
uid: SetText(cryptoBuffer, measurementValue.measurement.chargingSession?.authorizationStart?.["@id"] ?? "", 54),
|
|
9392
9456
|
sessionId: SetUInt32(cryptoBuffer, parseInt(measurementValue.measurement.chargingSession?.internalSessionId ?? ""), 74, true),
|
|
9393
9457
|
paging: SetUInt32(cryptoBuffer, measurementValue.paginationId, 78, true)
|
|
9394
9458
|
};
|
|
@@ -9426,8 +9490,8 @@ var AlfenCrypt01 = class extends ACrypt {
|
|
|
9426
9490
|
cryptoResult.hashValue = hashValue224k1;
|
|
9427
9491
|
result = this.curve224k1.validate(
|
|
9428
9492
|
hashValue224k1,
|
|
9429
|
-
BigInt(
|
|
9430
|
-
BigInt(
|
|
9493
|
+
BigInt("0x" + signatureExpected.r),
|
|
9494
|
+
BigInt("0x" + signatureExpected.s),
|
|
9431
9495
|
[
|
|
9432
9496
|
BigInt("0x" + publicKey.substring(2, 58)),
|
|
9433
9497
|
BigInt("0x" + publicKey.substring(58))
|
|
@@ -9514,7 +9578,7 @@ var AlfenCrypt01 = class extends ACrypt {
|
|
|
9514
9578
|
this.CreateLocalizedLine("Unit (encoded)", measurementValue.measurement.unitEncoded ?? 0, result.unitEncoded ?? "", infoDiv, PlainTextDiv);
|
|
9515
9579
|
this.CreateLocalizedLine("Scaling", measurementValue.measurement.scale, result.scalar ?? "", infoDiv, PlainTextDiv);
|
|
9516
9580
|
this.CreateLocalizedLine("Measurement Value", measurementValue.value.toString() + " Wh", result.value ?? "", infoDiv, PlainTextDiv);
|
|
9517
|
-
this.CreateLocalizedLine("Authorization", (measurementValue.measurement.chargingSession?.authorizationStart["@id"] ?? "") + " hex", pad(result.uid, 20), infoDiv, PlainTextDiv);
|
|
9581
|
+
this.CreateLocalizedLine("Authorization", (measurementValue.measurement.chargingSession?.authorizationStart?.["@id"] ?? "") + " hex", pad(result.uid, 20), infoDiv, PlainTextDiv);
|
|
9518
9582
|
this.CreateLocalizedLine("SessionId", measurementValue.measurement.chargingSession?.["@id"] ?? "", result.sessionId ?? "", infoDiv, PlainTextDiv);
|
|
9519
9583
|
this.CreateLocalizedLine("Pagination counter", measurementValue.paginationId, result.paging ?? "", infoDiv, PlainTextDiv);
|
|
9520
9584
|
}
|
|
@@ -9541,8 +9605,8 @@ var AlfenCrypt01 = class extends ACrypt {
|
|
|
9541
9605
|
signatureDiv.innerHTML = await this.chargy.CheckMeterPublicKeySignature(
|
|
9542
9606
|
measurementValue.measurement.chargingSession?.chargingStation,
|
|
9543
9607
|
measurementValue.measurement.chargingSession?.EVSE,
|
|
9544
|
-
measurementValue.measurement.chargingSession?.EVSE?.
|
|
9545
|
-
measurementValue.measurement.chargingSession?.EVSE?.
|
|
9608
|
+
measurementValue.measurement.chargingSession?.EVSE?.energyMeters?.[0],
|
|
9609
|
+
measurementValue.measurement.chargingSession?.EVSE?.energyMeters?.[0]?.publicKeys?.[0],
|
|
9546
9610
|
signature
|
|
9547
9611
|
);
|
|
9548
9612
|
} catch {
|
|
@@ -9554,7 +9618,7 @@ var AlfenCrypt01 = class extends ACrypt {
|
|
|
9554
9618
|
if (SignatureExpectedDiv.parentElement) {
|
|
9555
9619
|
getArrayLikeElement(SignatureExpectedDiv.parentElement.children, 0, "Missing expected signature header").innerHTML = this.chargy.GetLocalizedMessage("Expected signature") + " (" + (result.signature.format ?? "") + ", hex)";
|
|
9556
9620
|
}
|
|
9557
|
-
if (result.signature.r
|
|
9621
|
+
if (result.signature.r.length > 0 && result.signature.s.length > 0) {
|
|
9558
9622
|
const signatureR = result.signature.r.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "-";
|
|
9559
9623
|
const signatureS = result.signature.s.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "-";
|
|
9560
9624
|
SignatureExpectedDiv.innerHTML = "r: " + signatureR + "<br />s: " + signatureS;
|
|
@@ -10059,7 +10123,7 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
10059
10123
|
"@context": "https://open.charging.cloud/contexts/SessionSignatureFormats/bsm-ws36a-v0+json",
|
|
10060
10124
|
"begin": firstDataSet.time,
|
|
10061
10125
|
"end": lastDataSet.time,
|
|
10062
|
-
"EVSEId": CTR.chargingStationOperators?.[0]?.["chargingStations"]?.[0]?.["EVSEs"][0]?.["@id"],
|
|
10126
|
+
"EVSEId": CTR.chargingStationOperators?.[0]?.["chargingStations"]?.[0]?.["EVSEs"]?.[0]?.["@id"],
|
|
10063
10127
|
"authorizationStart": {
|
|
10064
10128
|
"@id": common.contract_id,
|
|
10065
10129
|
"@context": common.contract_type
|
|
@@ -10166,7 +10230,7 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
10166
10230
|
{
|
|
10167
10231
|
const firstChargingSession = getFirstArrayElement(CTR.chargingSessions, "Missing first BSM charging session");
|
|
10168
10232
|
const lastChargingSession = getLastArrayElement(CTR.chargingSessions, "Missing last BSM charging session");
|
|
10169
|
-
if (CTR.begin == void 0 || CTR.begin === "" || CTR.begin > firstChargingSession.begin) {
|
|
10233
|
+
if (firstChargingSession.begin !== void 0 && (CTR.begin == void 0 || CTR.begin === "" || CTR.begin > firstChargingSession.begin)) {
|
|
10170
10234
|
CTR.begin = firstChargingSession.begin;
|
|
10171
10235
|
}
|
|
10172
10236
|
if (lastChargingSession.end !== void 0) {
|
|
@@ -10174,21 +10238,22 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
10174
10238
|
CTR.end = lastChargingSession.end;
|
|
10175
10239
|
}
|
|
10176
10240
|
}
|
|
10177
|
-
|
|
10178
|
-
|
|
10179
|
-
|
|
10180
|
-
|
|
10181
|
-
|
|
10182
|
-
else {
|
|
10183
|
-
CTR.contract["@id"] = common.contract_id;
|
|
10184
|
-
CTR.contract["@context"] = common.contract_type;
|
|
10185
|
-
}
|
|
10186
|
-
CTR.chargingStationOperators?.[0]?.chargingStations?.[0]?.EVSEs[0]?.meters?.push({
|
|
10241
|
+
CTR.contracts = [{
|
|
10242
|
+
"@id": common.contract_id,
|
|
10243
|
+
"@context": common.contract_type
|
|
10244
|
+
}];
|
|
10245
|
+
CTR.chargingStationOperators?.[0]?.chargingStations?.[0]?.EVSEs?.[0]?.energyMeters?.push({
|
|
10187
10246
|
"@id": common.meterInfo_meterId,
|
|
10188
|
-
model: common.meterInfo_type,
|
|
10189
|
-
manufacturer:
|
|
10190
|
-
|
|
10191
|
-
|
|
10247
|
+
model: { name: common.meterInfo_type },
|
|
10248
|
+
manufacturer: {
|
|
10249
|
+
name: common.meterInfo_manufacturer,
|
|
10250
|
+
contact: {
|
|
10251
|
+
web: "https://www.bzr-bauer.de"
|
|
10252
|
+
}
|
|
10253
|
+
},
|
|
10254
|
+
firmware: {
|
|
10255
|
+
version: common.meterInfo_firmwareVersion
|
|
10256
|
+
},
|
|
10192
10257
|
//hardwareVersion?: string;
|
|
10193
10258
|
signatureInfos: {
|
|
10194
10259
|
hash: "SHA256" /* SHA256 */,
|
|
@@ -10223,7 +10288,7 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
10223
10288
|
async VerifyChargingSession(chargingSession) {
|
|
10224
10289
|
let sessionResult = "UnknownSessionFormat" /* UnknownSessionFormat */;
|
|
10225
10290
|
{
|
|
10226
|
-
for (const measurement of chargingSession.measurements) {
|
|
10291
|
+
for (const measurement of chargingSession.measurements ?? []) {
|
|
10227
10292
|
measurement.chargingSession = chargingSession;
|
|
10228
10293
|
if (measurement.values.length > 1) {
|
|
10229
10294
|
for (const measurementValue of measurement.values) {
|
|
@@ -10390,13 +10455,13 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
10390
10455
|
const signatureDiv = publicKeySignatureContainer?.appendChild(document.createElement("div"));
|
|
10391
10456
|
const chargingSession = measurementValue.measurement.chargingSession;
|
|
10392
10457
|
const evse = chargingSession?.EVSE;
|
|
10393
|
-
const
|
|
10394
|
-
const publicKey =
|
|
10395
|
-
if (signatureDiv != null && chargingSession != null && evse != null &&
|
|
10458
|
+
const energyMeter = evse?.energyMeters?.at(0);
|
|
10459
|
+
const publicKey = energyMeter?.publicKeys?.at(0);
|
|
10460
|
+
if (signatureDiv != null && chargingSession != null && evse != null && energyMeter != null && publicKey != null) {
|
|
10396
10461
|
signatureDiv.innerHTML = await this.chargy.CheckMeterPublicKeySignature(
|
|
10397
10462
|
chargingSession.chargingStation,
|
|
10398
10463
|
evse,
|
|
10399
|
-
|
|
10464
|
+
energyMeter,
|
|
10400
10465
|
publicKey,
|
|
10401
10466
|
signature
|
|
10402
10467
|
);
|
|
@@ -10411,7 +10476,7 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
10411
10476
|
if (SignatureExpectedDiv.parentElement) {
|
|
10412
10477
|
getArrayLikeElement(SignatureExpectedDiv.parentElement.children, 0, "Missing expected signature header").innerHTML = "Erwartete Signatur (" + (result.signature.format ?? "") + ", hex)";
|
|
10413
10478
|
}
|
|
10414
|
-
if (result.signature.r
|
|
10479
|
+
if (result.signature.r.length > 0 && result.signature.s.length > 0)
|
|
10415
10480
|
SignatureExpectedDiv.innerHTML = "r: " + (result.signature.r.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "-") + "<br />s: " + (result.signature.s.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "-");
|
|
10416
10481
|
else if (result.signature.value != null && result.signature.value.length > 0)
|
|
10417
10482
|
SignatureExpectedDiv.innerHTML = result.signature.value.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "-";
|
|
@@ -10549,97 +10614,7 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
10549
10614
|
// //#endregion
|
|
10550
10615
|
};
|
|
10551
10616
|
|
|
10552
|
-
// src/
|
|
10553
|
-
var CanonicalJSONError = class extends TypeError {
|
|
10554
|
-
constructor(message) {
|
|
10555
|
-
super(message);
|
|
10556
|
-
this.name = "CanonicalJSONError";
|
|
10557
|
-
}
|
|
10558
|
-
};
|
|
10559
|
-
function canonicalJSONStringify(value) {
|
|
10560
|
-
return serializeJSONValue(value, "$", /* @__PURE__ */ new WeakSet());
|
|
10561
|
-
}
|
|
10562
|
-
function canonicalJSONBytes(value) {
|
|
10563
|
-
return new TextEncoder().encode(canonicalJSONStringify(value));
|
|
10564
|
-
}
|
|
10565
|
-
function serializeJSONValue(value, path, seen) {
|
|
10566
|
-
switch (typeof value) {
|
|
10567
|
-
case "string":
|
|
10568
|
-
return JSON.stringify(value);
|
|
10569
|
-
case "number":
|
|
10570
|
-
if (!Number.isFinite(value))
|
|
10571
|
-
throw new CanonicalJSONError(`Non-finite number at ${path} is not valid JSON.`);
|
|
10572
|
-
return JSON.stringify(value);
|
|
10573
|
-
case "boolean":
|
|
10574
|
-
return value ? "true" : "false";
|
|
10575
|
-
case "object":
|
|
10576
|
-
if (value === null)
|
|
10577
|
-
return "null";
|
|
10578
|
-
return Array.isArray(value) ? serializeJSONArray(value, path, seen) : serializeJSONObject(value, path, seen);
|
|
10579
|
-
case "bigint":
|
|
10580
|
-
throw new CanonicalJSONError(`BigInt at ${path} is not valid JSON.`);
|
|
10581
|
-
case "undefined":
|
|
10582
|
-
throw new CanonicalJSONError(`Undefined value at ${path} is not valid JSON.`);
|
|
10583
|
-
case "function":
|
|
10584
|
-
throw new CanonicalJSONError(`Function at ${path} is not valid JSON.`);
|
|
10585
|
-
case "symbol":
|
|
10586
|
-
throw new CanonicalJSONError(`Symbol at ${path} is not valid JSON.`);
|
|
10587
|
-
}
|
|
10588
|
-
}
|
|
10589
|
-
function serializeJSONArray(value, path, seen) {
|
|
10590
|
-
if (seen.has(value))
|
|
10591
|
-
throw new CanonicalJSONError(`Circular reference at ${path} is not valid JSON.`);
|
|
10592
|
-
seen.add(value);
|
|
10593
|
-
const indexedKeys = /* @__PURE__ */ new Set();
|
|
10594
|
-
for (let i = 0; i < value.length; i++) {
|
|
10595
|
-
if (!Object.prototype.hasOwnProperty.call(value, i))
|
|
10596
|
-
throw new CanonicalJSONError(`Sparse array slot at ${path}[${String(i)}] is not valid JSON.`);
|
|
10597
|
-
indexedKeys.add(String(i));
|
|
10598
|
-
}
|
|
10599
|
-
for (const key of Object.keys(value)) {
|
|
10600
|
-
if (!indexedKeys.has(key))
|
|
10601
|
-
throw new CanonicalJSONError(`Non-index array property ${formatPathProperty(key)} at ${path} is not valid JSON.`);
|
|
10602
|
-
}
|
|
10603
|
-
rejectEnumerableSymbolProperties(value, path);
|
|
10604
|
-
const serializedItems = value.map(
|
|
10605
|
-
(item, index) => serializeJSONValue(item, `${path}[${String(index)}]`, seen)
|
|
10606
|
-
);
|
|
10607
|
-
seen.delete(value);
|
|
10608
|
-
return `[${serializedItems.join(",")}]`;
|
|
10609
|
-
}
|
|
10610
|
-
function serializeJSONObject(value, path, seen) {
|
|
10611
|
-
if (Object.prototype.toString.call(value) !== "[object Object]")
|
|
10612
|
-
throw new CanonicalJSONError(`Unsupported object at ${path} is not valid JSON.`);
|
|
10613
|
-
if (seen.has(value))
|
|
10614
|
-
throw new CanonicalJSONError(`Circular reference at ${path} is not valid JSON.`);
|
|
10615
|
-
seen.add(value);
|
|
10616
|
-
rejectEnumerableSymbolProperties(value, path);
|
|
10617
|
-
const serializedProperties = Object.keys(value).sort(compareOrdinal).map((key) => {
|
|
10618
|
-
const serializedKey = JSON.stringify(key);
|
|
10619
|
-
const serializedValue = serializeJSONValue(
|
|
10620
|
-
value[key],
|
|
10621
|
-
`${path}${formatPathProperty(key)}`,
|
|
10622
|
-
seen
|
|
10623
|
-
);
|
|
10624
|
-
return `${serializedKey}:${serializedValue}`;
|
|
10625
|
-
});
|
|
10626
|
-
seen.delete(value);
|
|
10627
|
-
return `{${serializedProperties.join(",")}}`;
|
|
10628
|
-
}
|
|
10629
|
-
function rejectEnumerableSymbolProperties(value, path) {
|
|
10630
|
-
for (const symbol of Object.getOwnPropertySymbols(value)) {
|
|
10631
|
-
if (Object.prototype.propertyIsEnumerable.call(value, symbol))
|
|
10632
|
-
throw new CanonicalJSONError(`Symbol property at ${path} is not valid JSON.`);
|
|
10633
|
-
}
|
|
10634
|
-
}
|
|
10635
|
-
function compareOrdinal(left, right) {
|
|
10636
|
-
return left < right ? -1 : left > right ? 1 : 0;
|
|
10637
|
-
}
|
|
10638
|
-
function formatPathProperty(propertyName) {
|
|
10639
|
-
return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(propertyName) ? `.${propertyName}` : `[${JSON.stringify(propertyName)}]`;
|
|
10640
|
-
}
|
|
10641
|
-
|
|
10642
|
-
// src/CryptoUtils.ts
|
|
10617
|
+
// src/interfaces/CryptoUtils.ts
|
|
10643
10618
|
var import_elliptic = __toESM(require_elliptic());
|
|
10644
10619
|
var JSONSignatureVerificationStatus = /* @__PURE__ */ ((JSONSignatureVerificationStatus2) => {
|
|
10645
10620
|
JSONSignatureVerificationStatus2["True"] = "True";
|
|
@@ -10680,7 +10655,7 @@ async function signJSONMessage(JSONMessage, KeyPairs, options) {
|
|
|
10680
10655
|
continue;
|
|
10681
10656
|
const messageJSON = cloneMessageWithoutSignatures(JSONMessage);
|
|
10682
10657
|
const plainText = canonicalJSONBytes(messageJSON);
|
|
10683
|
-
const sha256Hash = await
|
|
10658
|
+
const sha256Hash = await sha256____(plainText);
|
|
10684
10659
|
JSONMessage.signatures ??= [];
|
|
10685
10660
|
const publicKeyBytes = Uint8Array.from(KeyPair.getPublic(false, "array"));
|
|
10686
10661
|
const signature = KeyPair.sign(sha256Hash, {
|
|
@@ -10727,7 +10702,7 @@ async function verifyJSONSignatureResult(JSONMessage, signature, options) {
|
|
|
10727
10702
|
try {
|
|
10728
10703
|
const messageJSON = cloneMessageWithoutSignatures(JSONMessage);
|
|
10729
10704
|
const plainText = canonicalJSONBytes(messageJSON);
|
|
10730
|
-
sha256Hash = await
|
|
10705
|
+
sha256Hash = await sha256____(plainText);
|
|
10731
10706
|
} catch (exception) {
|
|
10732
10707
|
return verificationResult(
|
|
10733
10708
|
"InvalidCanonicalJSON" /* InvalidCanonicalJSON */,
|
|
@@ -10835,7 +10810,7 @@ function parseSignedJSONMessage(JSONMessage) {
|
|
|
10835
10810
|
};
|
|
10836
10811
|
}
|
|
10837
10812
|
}
|
|
10838
|
-
if (!
|
|
10813
|
+
if (!isMandatoryJSONObject(parsedMessage))
|
|
10839
10814
|
return {
|
|
10840
10815
|
result: verificationResult(
|
|
10841
10816
|
"InvalidJSON" /* InvalidJSON */,
|
|
@@ -10854,7 +10829,7 @@ function parseSignedJSONMessage(JSONMessage) {
|
|
|
10854
10829
|
};
|
|
10855
10830
|
}
|
|
10856
10831
|
function isJSONSignature(value) {
|
|
10857
|
-
return
|
|
10832
|
+
return isMandatoryJSONObject(value) && typeof value["publicKey"] === "string" && typeof value["publicKeyHEX"] === "string" && typeof value["signature"] === "string" && typeof value["signatureHEX"] === "string";
|
|
10858
10833
|
}
|
|
10859
10834
|
function signatureEncodingsMatch(signature) {
|
|
10860
10835
|
try {
|
|
@@ -10878,32 +10853,93 @@ function verificationResult(status, description) {
|
|
|
10878
10853
|
function isVerificationTrue(result) {
|
|
10879
10854
|
return (typeof result === "string" ? result : result.status) === "True" /* True */;
|
|
10880
10855
|
}
|
|
10881
|
-
|
|
10882
|
-
|
|
10856
|
+
var CanonicalJSONError = class extends TypeError {
|
|
10857
|
+
constructor(message) {
|
|
10858
|
+
super(message);
|
|
10859
|
+
this.name = "CanonicalJSONError";
|
|
10860
|
+
}
|
|
10861
|
+
};
|
|
10862
|
+
function canonicalJSONStringify(value) {
|
|
10863
|
+
return serializeJSONValue(value, "$", /* @__PURE__ */ new WeakSet());
|
|
10883
10864
|
}
|
|
10884
|
-
|
|
10885
|
-
|
|
10886
|
-
return new Uint8Array(digest);
|
|
10865
|
+
function canonicalJSONBytes(value) {
|
|
10866
|
+
return new TextEncoder().encode(canonicalJSONStringify(value));
|
|
10887
10867
|
}
|
|
10888
|
-
function
|
|
10889
|
-
|
|
10868
|
+
function serializeJSONValue(value, path, seen) {
|
|
10869
|
+
switch (typeof value) {
|
|
10870
|
+
case "string":
|
|
10871
|
+
return JSON.stringify(value);
|
|
10872
|
+
case "number":
|
|
10873
|
+
if (!Number.isFinite(value))
|
|
10874
|
+
throw new CanonicalJSONError(`Non-finite number at ${path} is not valid JSON.`);
|
|
10875
|
+
return JSON.stringify(value);
|
|
10876
|
+
case "boolean":
|
|
10877
|
+
return value ? "true" : "false";
|
|
10878
|
+
case "object":
|
|
10879
|
+
if (value === null)
|
|
10880
|
+
return "null";
|
|
10881
|
+
return Array.isArray(value) ? serializeJSONArray(value, path, seen) : serializeJSONObject(value, path, seen);
|
|
10882
|
+
case "bigint":
|
|
10883
|
+
throw new CanonicalJSONError(`BigInt at ${path} is not valid JSON.`);
|
|
10884
|
+
case "undefined":
|
|
10885
|
+
throw new CanonicalJSONError(`Undefined value at ${path} is not valid JSON.`);
|
|
10886
|
+
case "function":
|
|
10887
|
+
throw new CanonicalJSONError(`Function at ${path} is not valid JSON.`);
|
|
10888
|
+
case "symbol":
|
|
10889
|
+
throw new CanonicalJSONError(`Symbol at ${path} is not valid JSON.`);
|
|
10890
|
+
}
|
|
10890
10891
|
}
|
|
10891
|
-
function
|
|
10892
|
-
if (
|
|
10893
|
-
|
|
10894
|
-
|
|
10895
|
-
const
|
|
10896
|
-
for (let i = 0; i <
|
|
10897
|
-
|
|
10898
|
-
|
|
10892
|
+
function serializeJSONArray(value, path, seen) {
|
|
10893
|
+
if (seen.has(value))
|
|
10894
|
+
throw new CanonicalJSONError(`Circular reference at ${path} is not valid JSON.`);
|
|
10895
|
+
seen.add(value);
|
|
10896
|
+
const indexedKeys = /* @__PURE__ */ new Set();
|
|
10897
|
+
for (let i = 0; i < value.length; i++) {
|
|
10898
|
+
if (!Object.prototype.hasOwnProperty.call(value, i))
|
|
10899
|
+
throw new CanonicalJSONError(`Sparse array slot at ${path}[${String(i)}] is not valid JSON.`);
|
|
10900
|
+
indexedKeys.add(String(i));
|
|
10901
|
+
}
|
|
10902
|
+
for (const key of Object.keys(value)) {
|
|
10903
|
+
if (!indexedKeys.has(key))
|
|
10904
|
+
throw new CanonicalJSONError(`Non-index array property ${formatPathProperty(key)} at ${path} is not valid JSON.`);
|
|
10905
|
+
}
|
|
10906
|
+
rejectEnumerableSymbolProperties(value, path);
|
|
10907
|
+
const serializedItems = value.map(
|
|
10908
|
+
(item, index) => serializeJSONValue(item, `${path}[${String(index)}]`, seen)
|
|
10909
|
+
);
|
|
10910
|
+
seen.delete(value);
|
|
10911
|
+
return `[${serializedItems.join(",")}]`;
|
|
10899
10912
|
}
|
|
10900
|
-
function
|
|
10901
|
-
if (
|
|
10902
|
-
|
|
10903
|
-
|
|
10904
|
-
|
|
10905
|
-
|
|
10906
|
-
|
|
10913
|
+
function serializeJSONObject(value, path, seen) {
|
|
10914
|
+
if (Object.prototype.toString.call(value) !== "[object Object]")
|
|
10915
|
+
throw new CanonicalJSONError(`Unsupported object at ${path} is not valid JSON.`);
|
|
10916
|
+
if (seen.has(value))
|
|
10917
|
+
throw new CanonicalJSONError(`Circular reference at ${path} is not valid JSON.`);
|
|
10918
|
+
seen.add(value);
|
|
10919
|
+
rejectEnumerableSymbolProperties(value, path);
|
|
10920
|
+
const serializedProperties = Object.keys(value).sort(compareOrdinal).map((key) => {
|
|
10921
|
+
const serializedKey = JSON.stringify(key);
|
|
10922
|
+
const serializedValue = serializeJSONValue(
|
|
10923
|
+
value[key],
|
|
10924
|
+
`${path}${formatPathProperty(key)}`,
|
|
10925
|
+
seen
|
|
10926
|
+
);
|
|
10927
|
+
return `${serializedKey}:${serializedValue}`;
|
|
10928
|
+
});
|
|
10929
|
+
seen.delete(value);
|
|
10930
|
+
return `{${serializedProperties.join(",")}}`;
|
|
10931
|
+
}
|
|
10932
|
+
function rejectEnumerableSymbolProperties(value, path) {
|
|
10933
|
+
for (const symbol of Object.getOwnPropertySymbols(value)) {
|
|
10934
|
+
if (Object.prototype.propertyIsEnumerable.call(value, symbol))
|
|
10935
|
+
throw new CanonicalJSONError(`Symbol property at ${path} is not valid JSON.`);
|
|
10936
|
+
}
|
|
10937
|
+
}
|
|
10938
|
+
function compareOrdinal(left, right) {
|
|
10939
|
+
return left < right ? -1 : left > right ? 1 : 0;
|
|
10940
|
+
}
|
|
10941
|
+
function formatPathProperty(propertyName) {
|
|
10942
|
+
return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(propertyName) ? `.${propertyName}` : `[${JSON.stringify(propertyName)}]`;
|
|
10907
10943
|
}
|
|
10908
10944
|
|
|
10909
10945
|
// src/EMHCrypt01.ts
|
|
@@ -10918,7 +10954,7 @@ var EMHCrypt01 = class extends ACrypt {
|
|
|
10918
10954
|
async VerifyChargingSession(chargingSession) {
|
|
10919
10955
|
let sessionResult = "UnknownSessionFormat" /* UnknownSessionFormat */;
|
|
10920
10956
|
{
|
|
10921
|
-
for (const measurement of chargingSession.measurements) {
|
|
10957
|
+
for (const measurement of chargingSession.measurements ?? []) {
|
|
10922
10958
|
measurement.chargingSession = chargingSession;
|
|
10923
10959
|
if (measurement.values.length > 1) {
|
|
10924
10960
|
for (const measurementValue of measurement.values) {
|
|
@@ -10966,8 +11002,8 @@ var EMHCrypt01 = class extends ACrypt {
|
|
|
10966
11002
|
scale: SetInt8(cryptoBuffer, measurementValue.measurement.scale, 30),
|
|
10967
11003
|
value: SetUInt64D(cryptoBuffer, measurementValue.value, 31, true),
|
|
10968
11004
|
logBookIndex: SetHex(cryptoBuffer, measurementValue.logBookIndex, 39, false),
|
|
10969
|
-
authorizationStart: SetText(cryptoBuffer, measurementValue.measurement.chargingSession.authorizationStart["@id"], 41),
|
|
10970
|
-
authorizationStartTimestamp: SetTimestamp32(cryptoBuffer, measurementValue.measurement.chargingSession.authorizationStart.timestamp, 169)
|
|
11005
|
+
authorizationStart: SetText(cryptoBuffer, measurementValue.measurement.chargingSession.authorizationStart?.["@id"] ?? "", 41),
|
|
11006
|
+
authorizationStartTimestamp: SetTimestamp32(cryptoBuffer, measurementValue.measurement.chargingSession.authorizationStart?.timestamp ?? measurementValue.timestamp, 169)
|
|
10971
11007
|
};
|
|
10972
11008
|
const firstSignature = measurementValue.signatures?.[0];
|
|
10973
11009
|
if (firstSignature != null) {
|
|
@@ -10986,7 +11022,7 @@ var EMHCrypt01 = class extends ACrypt {
|
|
|
10986
11022
|
if (meter.publicKeys != null && meter.publicKeys.length > 0) {
|
|
10987
11023
|
try {
|
|
10988
11024
|
const publicKey = meter.publicKeys.at(0);
|
|
10989
|
-
cryptoResult.publicKey = publicKey?.value
|
|
11025
|
+
cryptoResult.publicKey = publicKey?.value.toLowerCase();
|
|
10990
11026
|
cryptoResult.publicKeyFormat = publicKey?.format;
|
|
10991
11027
|
cryptoResult.publicKeySignatures = publicKey?.signatures;
|
|
10992
11028
|
try {
|
|
@@ -11014,7 +11050,7 @@ var EMHCrypt01 = class extends ACrypt {
|
|
|
11014
11050
|
return {};
|
|
11015
11051
|
}
|
|
11016
11052
|
async ViewMeasurement(measurementValue, _errorDiv, introDiv, infoDiv, PlainTextDiv, HashedPlainTextDiv, PublicKeyDiv, SignatureExpectedDiv, SignatureCheckDiv) {
|
|
11017
|
-
if (measurementValue.measurement?.chargingSession?.authorizationStart
|
|
11053
|
+
if (measurementValue.measurement?.chargingSession?.authorizationStart?.timestamp === void 0) {
|
|
11018
11054
|
return new Error("Invalid measurement!");
|
|
11019
11055
|
}
|
|
11020
11056
|
const result = measurementValue.result;
|
|
@@ -11065,8 +11101,8 @@ var EMHCrypt01 = class extends ACrypt {
|
|
|
11065
11101
|
signatureDiv.innerHTML = await this.chargy.CheckMeterPublicKeySignature(
|
|
11066
11102
|
measurementValue.measurement.chargingSession.chargingStation,
|
|
11067
11103
|
measurementValue.measurement.chargingSession.EVSE,
|
|
11068
|
-
measurementValue.measurement.chargingSession.EVSE?.
|
|
11069
|
-
measurementValue.measurement.chargingSession.EVSE?.
|
|
11104
|
+
measurementValue.measurement.chargingSession.EVSE?.energyMeters?.at(0),
|
|
11105
|
+
measurementValue.measurement.chargingSession.EVSE?.energyMeters?.at(0)?.publicKeys?.at(0),
|
|
11070
11106
|
signature
|
|
11071
11107
|
);
|
|
11072
11108
|
signatureDiv.onclick = () => {
|
|
@@ -11083,7 +11119,7 @@ var EMHCrypt01 = class extends ACrypt {
|
|
|
11083
11119
|
if (SignatureExpectedDiv.parentElement) {
|
|
11084
11120
|
getArrayLikeElement(SignatureExpectedDiv.parentElement.children, 0, "Missing expected signature header").innerHTML = "Erwartete Signatur (" + (result.signature.format ?? "") + ", hex)";
|
|
11085
11121
|
}
|
|
11086
|
-
if (result.signature.r
|
|
11122
|
+
if (result.signature.r.length > 0 && result.signature.s.length > 0)
|
|
11087
11123
|
SignatureExpectedDiv.innerHTML = "r: " + (result.signature.r.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "") + "<br />s: " + (result.signature.s.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "");
|
|
11088
11124
|
else if (result.signature.value != null && result.signature.value.length > 0)
|
|
11089
11125
|
SignatureExpectedDiv.innerHTML = result.signature.value.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "-";
|
|
@@ -11154,7 +11190,7 @@ var GDFCrypt01 = class extends ACrypt {
|
|
|
11154
11190
|
async VerifyChargingSession(chargingSession) {
|
|
11155
11191
|
let sessionResult = "UnknownSessionFormat" /* UnknownSessionFormat */;
|
|
11156
11192
|
{
|
|
11157
|
-
for (const measurement of chargingSession.measurements) {
|
|
11193
|
+
for (const measurement of chargingSession.measurements ?? []) {
|
|
11158
11194
|
measurement.chargingSession = chargingSession;
|
|
11159
11195
|
if (measurement.values.length > 1) {
|
|
11160
11196
|
for (const measurementValue of measurement.values) {
|
|
@@ -11198,8 +11234,8 @@ var GDFCrypt01 = class extends ACrypt {
|
|
|
11198
11234
|
unitEncoded: SetInt8(cryptoBuffer, measurementValue.measurement.unitEncoded ?? 0, 29),
|
|
11199
11235
|
scale: SetInt8(cryptoBuffer, measurementValue.measurement.scale, 30),
|
|
11200
11236
|
value: SetUInt64D(cryptoBuffer, measurementValue.value, 31, true),
|
|
11201
|
-
authorizationStart: SetHex(cryptoBuffer, measurementValue.measurement.chargingSession.authorizationStart["@id"], 41),
|
|
11202
|
-
authorizationStartTimestamp: SetTimestamp(cryptoBuffer, measurementValue.measurement.chargingSession.authorizationStart
|
|
11237
|
+
authorizationStart: SetHex(cryptoBuffer, measurementValue.measurement.chargingSession.authorizationStart?.["@id"] ?? "", 41),
|
|
11238
|
+
authorizationStartTimestamp: SetTimestamp(cryptoBuffer, measurementValue.measurement.chargingSession.authorizationStart?.timestamp, 169)
|
|
11203
11239
|
};
|
|
11204
11240
|
const firstSignature = measurementValue.signatures?.[0];
|
|
11205
11241
|
if (firstSignature != null) {
|
|
@@ -11218,7 +11254,7 @@ var GDFCrypt01 = class extends ACrypt {
|
|
|
11218
11254
|
if (meter.publicKeys != null && meter.publicKeys.length > 0) {
|
|
11219
11255
|
try {
|
|
11220
11256
|
const publicKey = meter.publicKeys.at(0);
|
|
11221
|
-
cryptoResult.publicKey = publicKey?.value
|
|
11257
|
+
cryptoResult.publicKey = publicKey?.value.toLowerCase();
|
|
11222
11258
|
cryptoResult.publicKeyFormat = publicKey?.format;
|
|
11223
11259
|
cryptoResult.publicKeySignatures = publicKey?.signatures;
|
|
11224
11260
|
try {
|
|
@@ -11246,7 +11282,7 @@ var GDFCrypt01 = class extends ACrypt {
|
|
|
11246
11282
|
return {};
|
|
11247
11283
|
}
|
|
11248
11284
|
async ViewMeasurement(measurementValue, _errorDiv, introDiv, infoDiv, PlainTextDiv, HashedPlainTextDiv, PublicKeyDiv, SignatureExpectedDiv, SignatureCheckDiv) {
|
|
11249
|
-
if (measurementValue.measurement?.chargingSession?.authorizationStart
|
|
11285
|
+
if (measurementValue.measurement?.chargingSession?.authorizationStart?.timestamp === void 0) {
|
|
11250
11286
|
return new Error("Invalid measurement!");
|
|
11251
11287
|
}
|
|
11252
11288
|
const result = measurementValue.result;
|
|
@@ -11292,8 +11328,8 @@ var GDFCrypt01 = class extends ACrypt {
|
|
|
11292
11328
|
signatureDiv.innerHTML = await this.chargy.CheckMeterPublicKeySignature(
|
|
11293
11329
|
measurementValue.measurement.chargingSession.chargingStation,
|
|
11294
11330
|
measurementValue.measurement.chargingSession.EVSE,
|
|
11295
|
-
measurementValue.measurement.chargingSession.EVSE?.
|
|
11296
|
-
measurementValue.measurement.chargingSession.EVSE?.
|
|
11331
|
+
measurementValue.measurement.chargingSession.EVSE?.energyMeters?.at(0),
|
|
11332
|
+
measurementValue.measurement.chargingSession.EVSE?.energyMeters?.at(0)?.publicKeys?.at(0),
|
|
11297
11333
|
signature
|
|
11298
11334
|
);
|
|
11299
11335
|
} catch (exception) {
|
|
@@ -11306,7 +11342,7 @@ var GDFCrypt01 = class extends ACrypt {
|
|
|
11306
11342
|
if (SignatureExpectedDiv.parentElement) {
|
|
11307
11343
|
getArrayLikeElement(SignatureExpectedDiv.parentElement.children, 0, "Missing expected signature header").innerHTML = "Erwartete Signatur (" + (result.signature.format ?? "") + ", hex)";
|
|
11308
11344
|
}
|
|
11309
|
-
if (result.signature.r
|
|
11345
|
+
if (result.signature.r.length > 0 && result.signature.s.length > 0)
|
|
11310
11346
|
SignatureExpectedDiv.innerHTML = "r: " + (result.signature.r.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "") + "<br />s: " + (result.signature.s.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "");
|
|
11311
11347
|
else if (result.signature.value != null && result.signature.value.length > 0)
|
|
11312
11348
|
SignatureExpectedDiv.innerHTML = result.signature.value.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "-";
|
|
@@ -11338,7 +11374,118 @@ var GDFCrypt01 = class extends ACrypt {
|
|
|
11338
11374
|
}
|
|
11339
11375
|
return void 0;
|
|
11340
11376
|
}
|
|
11341
|
-
};
|
|
11377
|
+
};
|
|
11378
|
+
|
|
11379
|
+
// src/interfaces/IPublicKeyInfo.ts
|
|
11380
|
+
var IPublicKeyInfo_exports = {};
|
|
11381
|
+
__export(IPublicKeyInfo_exports, {
|
|
11382
|
+
IsAPublicKey: () => IsAPublicKey,
|
|
11383
|
+
IsAPublicKeyLookup: () => IsAPublicKeyLookup,
|
|
11384
|
+
IsAPublicKeySignature: () => IsAPublicKeySignature,
|
|
11385
|
+
IsAPublicKeyXY: () => IsAPublicKeyXY,
|
|
11386
|
+
PublicKeyFormats: () => PublicKeyFormats,
|
|
11387
|
+
isPublicKeySubject: () => isPublicKeySubject
|
|
11388
|
+
});
|
|
11389
|
+
var PublicKeyFormats = /* @__PURE__ */ ((PublicKeyFormats2) => {
|
|
11390
|
+
PublicKeyFormats2["DER"] = "DER";
|
|
11391
|
+
PublicKeyFormats2["XY"] = "XY";
|
|
11392
|
+
return PublicKeyFormats2;
|
|
11393
|
+
})(PublicKeyFormats || {});
|
|
11394
|
+
function IsAPublicKeyLookup(data) {
|
|
11395
|
+
if (!isMandatoryJSONObject(data))
|
|
11396
|
+
return false;
|
|
11397
|
+
return Array.isArray(data["publicKeys"]);
|
|
11398
|
+
}
|
|
11399
|
+
function IsAPublicKey(data) {
|
|
11400
|
+
if (!isMandatoryJSONObject(data))
|
|
11401
|
+
return false;
|
|
11402
|
+
if (data["@context"] !== void 0 && !isStringOrStringArray(data["@context"])) {
|
|
11403
|
+
return false;
|
|
11404
|
+
}
|
|
11405
|
+
if (!isPublicKeySubject(data["subject"]))
|
|
11406
|
+
return false;
|
|
11407
|
+
if (data["value"] !== void 0 && !isString(data["value"])) {
|
|
11408
|
+
return false;
|
|
11409
|
+
}
|
|
11410
|
+
if (data["value"] === void 0 && (data["x"] === void 0 || data["y"] === void 0)) {
|
|
11411
|
+
return false;
|
|
11412
|
+
}
|
|
11413
|
+
if (data["value"] !== void 0 && !isStringOrOIDInfo(data["algorithm"])) {
|
|
11414
|
+
return false;
|
|
11415
|
+
}
|
|
11416
|
+
if (data["certainty"] !== void 0 && (typeof data["certainty"] !== "number" || !Number.isFinite(data["certainty"]))) {
|
|
11417
|
+
return false;
|
|
11418
|
+
}
|
|
11419
|
+
if (data["type"] !== void 0 && !isStringOrOIDInfo(data["type"])) {
|
|
11420
|
+
return false;
|
|
11421
|
+
}
|
|
11422
|
+
if (data["encoding"] !== void 0 && typeof data["encoding"] !== "string") {
|
|
11423
|
+
return false;
|
|
11424
|
+
}
|
|
11425
|
+
if (data["signatures"] !== void 0 && (!Array.isArray(data["signatures"]) || !data["signatures"].every(IsAPublicKeySignature))) {
|
|
11426
|
+
return false;
|
|
11427
|
+
}
|
|
11428
|
+
return true;
|
|
11429
|
+
}
|
|
11430
|
+
function isPublicKeySubject(data) {
|
|
11431
|
+
if (data === void 0)
|
|
11432
|
+
return true;
|
|
11433
|
+
if (isStringOrStringArray(data))
|
|
11434
|
+
return true;
|
|
11435
|
+
if (!isMandatoryJSONObject(data))
|
|
11436
|
+
return false;
|
|
11437
|
+
return Object.values(data).every(
|
|
11438
|
+
(value) => typeof value === "string" || isStringOrStringArray(value)
|
|
11439
|
+
);
|
|
11440
|
+
}
|
|
11441
|
+
function IsAPublicKeySignature(data) {
|
|
11442
|
+
if (!isMandatoryJSONObject(data))
|
|
11443
|
+
return false;
|
|
11444
|
+
if (!isOptionalString(data["@id"]))
|
|
11445
|
+
return false;
|
|
11446
|
+
if (data["@context"] !== void 0 && !isStringOrStringArray(data["@context"]))
|
|
11447
|
+
return false;
|
|
11448
|
+
if (!isOptionalStringOrOIDInfo(data["algorithm"]))
|
|
11449
|
+
return false;
|
|
11450
|
+
if (!isOptionalString(data["format"]))
|
|
11451
|
+
return false;
|
|
11452
|
+
if (!isOptionalString(data["encoding"]))
|
|
11453
|
+
return false;
|
|
11454
|
+
if (data["value"] !== void 0 && !isString(data["value"]))
|
|
11455
|
+
return false;
|
|
11456
|
+
if (data["publicKey"] !== void 0 && !isEncodedValue(data["publicKey"]))
|
|
11457
|
+
return false;
|
|
11458
|
+
if (data["signature"] !== void 0 && !isEncodedValue(data["signature"]))
|
|
11459
|
+
return false;
|
|
11460
|
+
if (!isOptionalString(data["timestamp"]))
|
|
11461
|
+
return false;
|
|
11462
|
+
if (!isOptionalString(data["issuer"]))
|
|
11463
|
+
return false;
|
|
11464
|
+
if (!isOptionalString(data["signer"]))
|
|
11465
|
+
return false;
|
|
11466
|
+
if (!isOptionalString(data["notBefore"]))
|
|
11467
|
+
return false;
|
|
11468
|
+
if (!isOptionalString(data["notAfter"]))
|
|
11469
|
+
return false;
|
|
11470
|
+
if (!isOptionalStringArray(data["keyUsage"]))
|
|
11471
|
+
return false;
|
|
11472
|
+
if (data["operations"] !== void 0 && !isMandatoryJSONObject(data["operations"]))
|
|
11473
|
+
return false;
|
|
11474
|
+
if (data["comment"] !== void 0 && !isMandatoryJSONObject(data["comment"]))
|
|
11475
|
+
return false;
|
|
11476
|
+
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;
|
|
11477
|
+
}
|
|
11478
|
+
function IsAPublicKeyXY(data) {
|
|
11479
|
+
if (!IsAPublicKey(data))
|
|
11480
|
+
return false;
|
|
11481
|
+
if (!isString(data["x"])) {
|
|
11482
|
+
return false;
|
|
11483
|
+
}
|
|
11484
|
+
if (!isString(data["y"])) {
|
|
11485
|
+
return false;
|
|
11486
|
+
}
|
|
11487
|
+
return true;
|
|
11488
|
+
}
|
|
11342
11489
|
var MENNEKES_EDL40_XMLNS = "http://www.mennekes.de/Mennekes.EdlVerification.xsd";
|
|
11343
11490
|
var MENNEKES_EDL40_OBIS = "1-0:1.17.0*255";
|
|
11344
11491
|
var Mennekes = class {
|
|
@@ -11400,15 +11547,15 @@ var Mennekes = class {
|
|
|
11400
11547
|
return {
|
|
11401
11548
|
"@id": chargingStationId,
|
|
11402
11549
|
"description": { "en": "Mennekes EDL40 charging station" },
|
|
11403
|
-
"manufacturer": "MENNEKES",
|
|
11550
|
+
"manufacturer": { "name": "MENNEKES" },
|
|
11404
11551
|
"address": chargingProcess.siteAddress,
|
|
11405
11552
|
"EVSEs": [
|
|
11406
11553
|
{
|
|
11407
11554
|
"@id": evseId,
|
|
11408
|
-
"
|
|
11555
|
+
"energyMeters": [
|
|
11409
11556
|
{
|
|
11410
11557
|
"@id": meterId,
|
|
11411
|
-
"manufacturer": "MENNEKES",
|
|
11558
|
+
"manufacturer": { "name": "MENNEKES" },
|
|
11412
11559
|
"signatureFormat": "https://open.charging.cloud/contexts/EnergyMeterSignatureFormats/MennekesCrypt01",
|
|
11413
11560
|
"publicKeys": [
|
|
11414
11561
|
{
|
|
@@ -11486,7 +11633,7 @@ var MennekesCrypt01 = class extends ACrypt {
|
|
|
11486
11633
|
}
|
|
11487
11634
|
async VerifyChargingSession(chargingSession) {
|
|
11488
11635
|
let sessionResult = "UnknownSessionFormat" /* UnknownSessionFormat */;
|
|
11489
|
-
for (const measurement of chargingSession.measurements) {
|
|
11636
|
+
for (const measurement of chargingSession.measurements ?? []) {
|
|
11490
11637
|
measurement.chargingSession = chargingSession;
|
|
11491
11638
|
if (measurement.values.length >= 2) {
|
|
11492
11639
|
sessionResult = "ValidSignature" /* ValidSignature */;
|
|
@@ -11553,8 +11700,6 @@ var MennekesCrypt01 = class extends ACrypt {
|
|
|
11553
11700
|
if (meter.publicKeys == null || meter.publicKeys.length === 0)
|
|
11554
11701
|
return setResult("PublicKeyNotFound" /* PublicKeyNotFound */);
|
|
11555
11702
|
const signatureExpected = measurementValue.signatures?.[0];
|
|
11556
|
-
if (signatureExpected.r == null || signatureExpected.s == null)
|
|
11557
|
-
return setResult("InvalidSignature" /* InvalidSignature */);
|
|
11558
11703
|
const signedData = buildMennekesSignatureData(
|
|
11559
11704
|
{
|
|
11560
11705
|
serverId: measurement.serverId,
|
|
@@ -11576,7 +11721,7 @@ var MennekesCrypt01 = class extends ACrypt {
|
|
|
11576
11721
|
secondIndex: measurementValue.secondsIndex ?? 0
|
|
11577
11722
|
}
|
|
11578
11723
|
);
|
|
11579
|
-
cryptoResult.signedData =
|
|
11724
|
+
cryptoResult.signedData = bytesToHex(signedData);
|
|
11580
11725
|
cryptoResult.logBytes = cryptoResult.signedData.substring(78, 82);
|
|
11581
11726
|
const signedDataBuffer = signedData.buffer.slice(
|
|
11582
11727
|
signedData.byteOffset,
|
|
@@ -11614,7 +11759,7 @@ var MennekesCrypt01 = class extends ACrypt {
|
|
|
11614
11759
|
PublicKeyDiv.innerHTML = result.publicKey?.match(/.{1,8}/g)?.join(" ") ?? "";
|
|
11615
11760
|
if (SignatureExpectedDiv.parentElement?.children[0])
|
|
11616
11761
|
SignatureExpectedDiv.parentElement.children[0].innerHTML = this.chargy.GetLocalizedMessage("Expected signature") + " (rs, hex)";
|
|
11617
|
-
SignatureExpectedDiv.innerHTML = result.signature
|
|
11762
|
+
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(" ") ?? "") : "";
|
|
11618
11763
|
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>";
|
|
11619
11764
|
return Promise.resolve(void 0);
|
|
11620
11765
|
}
|
|
@@ -11676,23 +11821,6 @@ function dateToMennekesLocalEpochSeconds(isoTimestamp) {
|
|
|
11676
11821
|
const offsetSeconds = sign * (Number(offsetMatch[2]) * 3600 + Number(offsetMatch[3]) * 60);
|
|
11677
11822
|
return Math.floor(date.getTime() / 1e3) + offsetSeconds;
|
|
11678
11823
|
}
|
|
11679
|
-
function cleanHex(hex) {
|
|
11680
|
-
return hex.replace(/\s+/g, "");
|
|
11681
|
-
}
|
|
11682
|
-
function hexToBytes(hex) {
|
|
11683
|
-
const cleanedHex = cleanHex(hex);
|
|
11684
|
-
if (cleanedHex.length % 2 !== 0)
|
|
11685
|
-
throw new Error("Hex strings must have even length!");
|
|
11686
|
-
if (!/^[0-9a-fA-F]*$/.test(cleanedHex))
|
|
11687
|
-
throw new Error("Invalid hexadecimal string!");
|
|
11688
|
-
const bytes = new Uint8Array(cleanedHex.length / 2);
|
|
11689
|
-
for (let index = 0; index < cleanedHex.length; index += 2)
|
|
11690
|
-
bytes[index / 2] = Number.parseInt(cleanedHex.substring(index, index + 2), 16);
|
|
11691
|
-
return bytes;
|
|
11692
|
-
}
|
|
11693
|
-
function bytesToHex2(bytes) {
|
|
11694
|
-
return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
11695
|
-
}
|
|
11696
11824
|
function parseChargingProcessElement(chargingProcessElement) {
|
|
11697
11825
|
const siteAddressElement = child(chargingProcessElement, "SiteAddress");
|
|
11698
11826
|
return {
|
|
@@ -11830,7 +11958,7 @@ var OCMFv1_x = class extends ACrypt {
|
|
|
11830
11958
|
async VerifyChargingSession(chargingSession) {
|
|
11831
11959
|
let sessionResult = "Unvalidated" /* Unvalidated */;
|
|
11832
11960
|
{
|
|
11833
|
-
for (const measurement of chargingSession.measurements) {
|
|
11961
|
+
for (const measurement of chargingSession.measurements ?? []) {
|
|
11834
11962
|
measurement.chargingSession = chargingSession;
|
|
11835
11963
|
if (measurement.values.length > 1) {
|
|
11836
11964
|
for (const measurementValue of measurement.values) {
|
|
@@ -11978,7 +12106,7 @@ var OCMFv1_x = class extends ACrypt {
|
|
|
11978
12106
|
return new Error("Invalid measurement!");
|
|
11979
12107
|
}
|
|
11980
12108
|
{
|
|
11981
|
-
introDiv.innerHTML = this.chargy.GetLocalizedMessage("The following data of the charging session is relevant for metrological and legal metrological purposes and therefore part of the digital signature").replace("{methodName}", "OCMFCrypt01").replace("{cryptoAlgorithm}", measurementValue.ocmfDocument.publicKey != null && typeof measurementValue.ocmfDocument.publicKey !== "string" ? "(" + measurementValue.ocmfDocument.publicKey.algorithm + ") " : "");
|
|
12109
|
+
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) + ") " : "");
|
|
11982
12110
|
}
|
|
11983
12111
|
{
|
|
11984
12112
|
if (PlainTextDiv.parentElement) {
|
|
@@ -12021,9 +12149,9 @@ var OCMFv1_x = class extends ACrypt {
|
|
|
12021
12149
|
}
|
|
12022
12150
|
if (measurementValue.ocmfDocument.publicKey != null) {
|
|
12023
12151
|
if (PublicKeyDiv.parentElement) {
|
|
12024
|
-
getArrayLikeElement(PublicKeyDiv.parentElement.children, 0, "Missing public key header").innerHTML = typeof measurementValue.ocmfDocument.publicKey === "string" ? this.chargy.GetLocalizedMessage("Public Key") : this.chargy.GetLocalizedMessage("Public Key") + " (" + measurementValue.ocmfDocument.publicKey.algorithm + ", " + measurementValue.ocmfDocument.publicKey.encoding + ")";
|
|
12152
|
+
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 ?? "-") + ")";
|
|
12025
12153
|
}
|
|
12026
|
-
PublicKeyDiv.innerHTML = typeof measurementValue.ocmfDocument.publicKey === "string" ? measurementValue.ocmfDocument.publicKey : "der: " + (measurementValue.ocmfDocument.publicKey.value
|
|
12154
|
+
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(" ") ?? "-");
|
|
12027
12155
|
}
|
|
12028
12156
|
const publicKeySignatureContainer = PublicKeyDiv.parentElement?.children[3];
|
|
12029
12157
|
if (publicKeySignatureContainer !== void 0) {
|
|
@@ -12036,8 +12164,8 @@ var OCMFv1_x = class extends ACrypt {
|
|
|
12036
12164
|
signatureDiv.innerHTML = await this.chargy.CheckMeterPublicKeySignature(
|
|
12037
12165
|
measurementValue.measurement.chargingSession.chargingStation,
|
|
12038
12166
|
measurementValue.measurement.chargingSession.EVSE,
|
|
12039
|
-
measurementValue.measurement.chargingSession.EVSE?.
|
|
12040
|
-
measurementValue.measurement.chargingSession.EVSE?.
|
|
12167
|
+
measurementValue.measurement.chargingSession.EVSE?.energyMeters?.at(0),
|
|
12168
|
+
measurementValue.measurement.chargingSession.EVSE?.energyMeters?.at(0)?.publicKeys?.at(0),
|
|
12041
12169
|
signature
|
|
12042
12170
|
);
|
|
12043
12171
|
} catch {
|
|
@@ -12050,7 +12178,7 @@ var OCMFv1_x = class extends ACrypt {
|
|
|
12050
12178
|
if (SignatureExpectedDiv.parentElement) {
|
|
12051
12179
|
getArrayLikeElement(SignatureExpectedDiv.parentElement.children, 0, "Missing expected signature header").innerHTML = this.chargy.GetLocalizedMessage("Expected signature") + " (rs, hex)";
|
|
12052
12180
|
}
|
|
12053
|
-
SignatureExpectedDiv.innerHTML = "der: " + (measurementValue.ocmfDocument.signature.SD.match(/.{1,8}/g)?.join(" ") ?? "-") + "<br /><br />r: " + (measurementValue.ocmfDocument.signatureRS?.r
|
|
12181
|
+
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(" ") ?? "-");
|
|
12054
12182
|
}
|
|
12055
12183
|
if (measurementValue.measurement.chargingSession.verificationResult) {
|
|
12056
12184
|
switch (measurementValue.measurement.chargingSession.verificationResult.status) {
|
|
@@ -12095,15 +12223,6 @@ var OCMF = class {
|
|
|
12095
12223
|
//#region (private) tryToParseOCMFv1_0(OCMFDataList, ContainerInfos?)
|
|
12096
12224
|
tryToParseOCMFv1_0(OCMFJSONDocuments, ContainerInfos) {
|
|
12097
12225
|
try {
|
|
12098
|
-
const containerInfos = asJSONObject(ContainerInfos) ?? {};
|
|
12099
|
-
const chargingStationInfo = asJSONObject(containerInfos["chargingStation"]);
|
|
12100
|
-
const evseInfo = asJSONObject(containerInfos["EVSE"]);
|
|
12101
|
-
const connectorInfo = asJSONObject(containerInfos["connector"]);
|
|
12102
|
-
const energyMeterInfo = asJSONObject(containerInfos["energyMeter"]);
|
|
12103
|
-
const chargingStationId = asString(containerInfos["ChargingStationId"]) ?? asString(chargingStationInfo?.["@id"]) ?? "DE*GEF*STATION*CHARGY*1";
|
|
12104
|
-
const evseId = asString(containerInfos["EVSEId"]) ?? asString(evseInfo?.["@id"]) ?? "DE*GEF*EVSE*CHARGY*1";
|
|
12105
|
-
const stationDescription = asJSONObject(chargingStationInfo?.["description"]);
|
|
12106
|
-
const evseDescription = asJSONObject(evseInfo?.["description"]);
|
|
12107
12226
|
const firstOCMDJSONDocument = getFirstArrayElement(OCMFJSONDocuments, "Missing first OCMF JSON document");
|
|
12108
12227
|
const formatVersion = firstOCMDJSONDocument.payload.FV;
|
|
12109
12228
|
const gatewayInformation = firstOCMDJSONDocument.payload.GI ?? firstOCMDJSONDocument.payload.VI;
|
|
@@ -12176,49 +12295,71 @@ var OCMF = class {
|
|
|
12176
12295
|
"gatewayVersion": gatewayVersion
|
|
12177
12296
|
},
|
|
12178
12297
|
// "chargingStationOperators": [{
|
|
12179
|
-
"chargingPools":
|
|
12180
|
-
|
|
12181
|
-
|
|
12182
|
-
|
|
12183
|
-
|
|
12184
|
-
|
|
12185
|
-
|
|
12186
|
-
|
|
12187
|
-
|
|
12188
|
-
|
|
12189
|
-
|
|
12190
|
-
|
|
12191
|
-
|
|
12192
|
-
|
|
12193
|
-
|
|
12194
|
-
|
|
12195
|
-
|
|
12196
|
-
|
|
12197
|
-
|
|
12198
|
-
|
|
12199
|
-
|
|
12200
|
-
|
|
12201
|
-
|
|
12202
|
-
|
|
12203
|
-
|
|
12204
|
-
|
|
12205
|
-
|
|
12206
|
-
|
|
12207
|
-
|
|
12208
|
-
|
|
12209
|
-
|
|
12210
|
-
|
|
12211
|
-
|
|
12212
|
-
|
|
12213
|
-
|
|
12214
|
-
|
|
12215
|
-
}
|
|
12298
|
+
// "chargingPools": [{
|
|
12299
|
+
// "@id": "DE*GEF*POOL*CHARGY*1",
|
|
12300
|
+
// "description": { "en": "GraphDefined CHARGY Virtual Charging Pool 1" },
|
|
12301
|
+
// "chargingStations": [{
|
|
12302
|
+
// "@id": chargingStationId,
|
|
12303
|
+
// "description": stationDescription && Object.keys(stationDescription).length > 0
|
|
12304
|
+
// ? stationDescription
|
|
12305
|
+
// : { "en": "GraphDefined CHARGY Virtual Charging Station 1" },
|
|
12306
|
+
// // "firmware": {
|
|
12307
|
+
// // "version": chargyLib.asString(chargingStationInfo?.["softwareVersion"])
|
|
12308
|
+
// // ?? chargyLib.asString(chargingStationInfo?.["firmwareVersion"])
|
|
12309
|
+
// // },
|
|
12310
|
+
// "geoLocation": chargyLib.asJSONObject(chargingStationInfo?.["geoLocation"]) as chargyInterfaces.IGeoLocation | undefined,
|
|
12311
|
+
// "address": chargyLib.asJSONObject(chargingStationInfo?.["address"]) as chargyInterfaces.IAddress | undefined,
|
|
12312
|
+
// "EVSEs": [{
|
|
12313
|
+
// "@id": evseId,
|
|
12314
|
+
// "description": evseDescription && Object.keys(evseDescription).length > 0
|
|
12315
|
+
// ? evseDescription
|
|
12316
|
+
// : { "en": "GraphDefined CHARGY Virtual EVSE 1" },
|
|
12317
|
+
// "connectors": connectorInfo
|
|
12318
|
+
// ? [{
|
|
12319
|
+
// "type": chargyLib.asString(connectorInfo["type"]) ?? "",
|
|
12320
|
+
// "cable": {
|
|
12321
|
+
// "length": chargyLib.asNumber(connectorInfo["length"]) ?? 0,
|
|
12322
|
+
// "looses": chargyLib.asNumber(connectorInfo["looses"]) ?? 0
|
|
12323
|
+
// }
|
|
12324
|
+
// }]
|
|
12325
|
+
// : [],
|
|
12326
|
+
// "energyMeters": [{
|
|
12327
|
+
// "@id": effectiveMeterSerial,
|
|
12328
|
+
// // The signed OCMF payload values always win,
|
|
12329
|
+
// // the container infos only fill the gaps!
|
|
12330
|
+
// "manufacturer": {
|
|
12331
|
+
// "name": meterVendor ?? chargyLib.asString(energyMeterInfo?.["manufacturer"]),
|
|
12332
|
+
// "contact": {
|
|
12333
|
+
// "web": chargyLib.asString(energyMeterInfo?.["manufacturerURL"])
|
|
12334
|
+
// }
|
|
12335
|
+
// },
|
|
12336
|
+
// "model": {
|
|
12337
|
+
// "name": meterModel ?? chargyLib.asString(energyMeterInfo?.["model"]),
|
|
12338
|
+
// "url": chargyLib.asString(energyMeterInfo?.["modelURL"])
|
|
12339
|
+
// },
|
|
12340
|
+
// "hardware": {
|
|
12341
|
+
// "revision": chargyLib.asString(energyMeterInfo?.["hardwareVersion"])
|
|
12342
|
+
// },
|
|
12343
|
+
// "firmware": {
|
|
12344
|
+
// "version": meterFirmware ?? chargyLib.asString(energyMeterInfo?.["firmwareVersion"])
|
|
12345
|
+
// },
|
|
12346
|
+
// "signatureFormat": "https://open.charging.cloud/contexts/EnergyMeterSignatureFormats/OCMFv1.0+json",
|
|
12347
|
+
// "publicKeys": [{
|
|
12348
|
+
// "algorithm": "?",
|
|
12349
|
+
// "encoding": "?",
|
|
12350
|
+
// "format": "?",
|
|
12351
|
+
// "value": "?",
|
|
12352
|
+
// }]
|
|
12353
|
+
// }]
|
|
12354
|
+
// }],
|
|
12355
|
+
// }]
|
|
12356
|
+
// }],
|
|
12216
12357
|
"chargingSessions": [{
|
|
12217
12358
|
"@id": "1554181214441:-1965658344385548683:2",
|
|
12218
12359
|
"@context": "https://open.charging.cloud/contexts/SessionSignatureFormats/OCMFv1.0+json",
|
|
12219
12360
|
"begin": "?",
|
|
12220
12361
|
"end": "?",
|
|
12221
|
-
"EVSEId":
|
|
12362
|
+
//"EVSEId": evseId,
|
|
12222
12363
|
"authorizationStart": {
|
|
12223
12364
|
"@id": identificationData ?? "?",
|
|
12224
12365
|
"type": identificationType ?? "?",
|
|
@@ -12231,6 +12372,8 @@ var OCMF = class {
|
|
|
12231
12372
|
}],
|
|
12232
12373
|
"certainty": 1
|
|
12233
12374
|
};
|
|
12375
|
+
if (ContainerInfos?.chargingStations !== void 0)
|
|
12376
|
+
CTR.chargingStations = ContainerInfos.chargingStations;
|
|
12234
12377
|
const measurementsByKey = /* @__PURE__ */ new Map();
|
|
12235
12378
|
for (const ocmfJSONDocument of OCMFJSONDocuments) {
|
|
12236
12379
|
let inheritedReading = {};
|
|
@@ -12363,6 +12506,8 @@ var OCMF = class {
|
|
|
12363
12506
|
}
|
|
12364
12507
|
}
|
|
12365
12508
|
}
|
|
12509
|
+
if (ContainerInfos?.chargingStations !== void 0)
|
|
12510
|
+
CTR.chargingStations = ContainerInfos.chargingStations;
|
|
12366
12511
|
CTR.status = OCMFJSONDocuments.every((ocmfJSONDocument) => ocmfJSONDocument.validationStatus === "ValidSignature" /* ValidSignature */) ? "ValidSignature" /* ValidSignature */ : "InvalidSignature" /* InvalidSignature */;
|
|
12367
12512
|
if (CTR.chargingSessions != null && CTR.chargingSessions.length > 0 && CTR.chargingSessions[0]) {
|
|
12368
12513
|
CTR.begin = CTR.chargingSessions[0].begin;
|
|
@@ -12609,7 +12754,7 @@ var OCMF = class {
|
|
|
12609
12754
|
x: publicKeyXY.x,
|
|
12610
12755
|
y: publicKeyXY.y
|
|
12611
12756
|
};
|
|
12612
|
-
} else if (
|
|
12757
|
+
} else if (IsAPublicKeyXY(OCMFJSONDocument.publicKey)) {
|
|
12613
12758
|
publicKey = curve.keyFromPublic({
|
|
12614
12759
|
x: OCMFJSONDocument.publicKey.x,
|
|
12615
12760
|
y: OCMFJSONDocument.publicKey.y
|
|
@@ -12719,17 +12864,17 @@ var OCMF = class {
|
|
|
12719
12864
|
// Not an OCMF standard!
|
|
12720
12865
|
case "ECDSA-secp384r1-SHA384":
|
|
12721
12866
|
hashAlgorithm = "SHA384, 384 Bits, hex";
|
|
12722
|
-
hashValue = await
|
|
12867
|
+
hashValue = await sha384(plaintext);
|
|
12723
12868
|
break;
|
|
12724
12869
|
// Not an OCMF standard!
|
|
12725
12870
|
case "ECDSA-brainpool384r1-SHA384":
|
|
12726
12871
|
hashAlgorithm = "SHA384, 384 Bits, hex";
|
|
12727
|
-
hashValue = await
|
|
12872
|
+
hashValue = await sha384(plaintext);
|
|
12728
12873
|
break;
|
|
12729
12874
|
// Not an OCMF standard!
|
|
12730
12875
|
case "ECDSA-secp521r1-SHA512":
|
|
12731
12876
|
hashAlgorithm = "SHA512, 512 Bits, hex";
|
|
12732
|
-
hashValue = await
|
|
12877
|
+
hashValue = await sha512(plaintext);
|
|
12733
12878
|
break;
|
|
12734
12879
|
// ECDSA-secp256r1-SHA256
|
|
12735
12880
|
default:
|
|
@@ -12811,7 +12956,12 @@ var OCMF = class {
|
|
|
12811
12956
|
//#endregion
|
|
12812
12957
|
//#region TryToParseOCMFDocument (OCMFDocument, PublicKey?, PublicKeyEncoding?, ContainerInfos?)
|
|
12813
12958
|
async TryToParseOCMFDocument(OCMFDocument, PublicKey, PublicKeyEncoding, ContainerInfos) {
|
|
12814
|
-
return this.TryToParseOCMFDocuments(
|
|
12959
|
+
return this.TryToParseOCMFDocuments(
|
|
12960
|
+
[OCMFDocument],
|
|
12961
|
+
PublicKey,
|
|
12962
|
+
PublicKeyEncoding,
|
|
12963
|
+
ContainerInfos
|
|
12964
|
+
);
|
|
12815
12965
|
}
|
|
12816
12966
|
//#endregion
|
|
12817
12967
|
//#region TryToParseOCMFDocuments(OCMFDocuments, PublicKey?, PublicKeyEncoding?, ContainerInfos?)
|
|
@@ -12932,13 +13082,16 @@ var OCPI = class {
|
|
|
12932
13082
|
const firstSignedData = asString(asJSONObject(signed_values[0])?.["signed_data"]);
|
|
12933
13083
|
if (firstSignedData != null && firstSignedData.length > 0) {
|
|
12934
13084
|
const placeInfo = asJSONObject(SomeJSON["placeInfo"]);
|
|
13085
|
+
const evseId = asString(placeInfo?.["evseId"]);
|
|
13086
|
+
const evseIdStr = asString(evseId) ?? "";
|
|
12935
13087
|
const geoLocation = asJSONObject(placeInfo?.["geoLocation"]);
|
|
12936
13088
|
const address = asJSONObject(placeInfo?.["address"]);
|
|
12937
13089
|
const geoLat = asNumber(geoLocation?.["lat"]);
|
|
12938
13090
|
const geoLon = asNumber(geoLocation?.["lon"]);
|
|
12939
13091
|
const containerInfos = {
|
|
12940
|
-
|
|
12941
|
-
|
|
13092
|
+
EVSEIds: [evseId],
|
|
13093
|
+
chargingStations: [{
|
|
13094
|
+
"@id": evseIdStr.substring(0, evseIdStr.lastIndexOf("*")),
|
|
12942
13095
|
geoLocation: geoLat !== void 0 && geoLon !== void 0 ? { lat: geoLat, lng: geoLon } : void 0,
|
|
12943
13096
|
address: address ? {
|
|
12944
13097
|
street: asString(address["street"]),
|
|
@@ -12946,8 +13099,8 @@ var OCPI = class {
|
|
|
12946
13099
|
city: asString(address["town"]),
|
|
12947
13100
|
country: asString(address["country"]) ?? ""
|
|
12948
13101
|
} : void 0
|
|
12949
|
-
}
|
|
12950
|
-
energyMeter:
|
|
13102
|
+
}]
|
|
13103
|
+
//energyMeter: chargyLib.asJSONObject(SomeJSON["meterInfo"])
|
|
12951
13104
|
};
|
|
12952
13105
|
return new OCMF(this.chargy).TryToParseOCMFDocument(
|
|
12953
13106
|
firstSignedData,
|
|
@@ -12962,7 +13115,7 @@ var OCPI = class {
|
|
|
12962
13115
|
const numberOfFormatChecks = 81;
|
|
12963
13116
|
let secondaryErrors = 0;
|
|
12964
13117
|
try {
|
|
12965
|
-
const chargingSessionId = SomeJSON["@id"];
|
|
13118
|
+
const chargingSessionId = asString(SomeJSON["@id"]);
|
|
12966
13119
|
const chargePointInfo = asJSONObject(SomeJSON["chargePointInfo"]);
|
|
12967
13120
|
const evseId = chargePointInfo?.["evseId"];
|
|
12968
13121
|
const placeInfo = asJSONObject(chargePointInfo?.["placeInfo"]);
|
|
@@ -13193,7 +13346,7 @@ var OCPI = class {
|
|
|
13193
13346
|
"value": "042313b9e469612b4ca06981bfdecb226e234632b01d84b6a814f63a114b7762c34ddce2e6853395b7a0f87275f63ffe3c",
|
|
13194
13347
|
"signatures": [
|
|
13195
13348
|
{
|
|
13196
|
-
"
|
|
13349
|
+
"@id": "...",
|
|
13197
13350
|
"algorithm": "secp192r1",
|
|
13198
13351
|
"format": "DER",
|
|
13199
13352
|
"value": "????"
|
|
@@ -13258,7 +13411,7 @@ var OCPI = class {
|
|
|
13258
13411
|
// "de": "GraphDefined EVSE - CI-Tests Pool 3 / Station A / EVSE 1"
|
|
13259
13412
|
// },
|
|
13260
13413
|
//"connectors": [ ],
|
|
13261
|
-
"
|
|
13414
|
+
"energyMeters": []
|
|
13262
13415
|
}
|
|
13263
13416
|
]
|
|
13264
13417
|
}
|
|
@@ -13273,29 +13426,29 @@ var OCPI = class {
|
|
|
13273
13426
|
return new Alfen(this.chargy).TryToParseALFENFormat(
|
|
13274
13427
|
signedMeterValues.map((value) => asString(asJSONObject(value)?.["payload"]) ?? ""),
|
|
13275
13428
|
{
|
|
13276
|
-
|
|
13277
|
-
|
|
13278
|
-
},
|
|
13279
|
-
EVSEId:
|
|
13280
|
-
|
|
13281
|
-
|
|
13282
|
-
|
|
13283
|
-
|
|
13284
|
-
|
|
13285
|
-
|
|
13286
|
-
|
|
13287
|
-
|
|
13288
|
-
|
|
13289
|
-
|
|
13290
|
-
|
|
13291
|
-
|
|
13292
|
-
|
|
13293
|
-
|
|
13294
|
-
|
|
13295
|
-
},
|
|
13296
|
-
energyMeter:
|
|
13297
|
-
connector:
|
|
13298
|
-
chargingCosts:
|
|
13429
|
+
// chargingSessions: [{
|
|
13430
|
+
// "@id": chargingSessionId ?? ""
|
|
13431
|
+
// }],
|
|
13432
|
+
// // EVSEId: evseId,
|
|
13433
|
+
// chargingStations: [{
|
|
13434
|
+
// manufacturer: chargingStation_manufacturer,
|
|
13435
|
+
// type: chargingStation_type,
|
|
13436
|
+
// serialNumber: chargingStation_serialNumber,
|
|
13437
|
+
// firmwareVersion: chargingStation_controllerSoftwareVersion,
|
|
13438
|
+
// legalCompliance: {
|
|
13439
|
+
// conformity: [{
|
|
13440
|
+
// freeText: chargingStation_compliance
|
|
13441
|
+
// }],
|
|
13442
|
+
// calibration: [{
|
|
13443
|
+
// freeText: chargingStation_calibration
|
|
13444
|
+
// }]
|
|
13445
|
+
// },
|
|
13446
|
+
// geoLocation: { "lat": geoLocation_lat, "lng": geoLocation_lon },
|
|
13447
|
+
// address: { "street": address_street, "postalCode": address_zipCode, "city": address_town, "country": address_country }
|
|
13448
|
+
// }],
|
|
13449
|
+
// energyMeter: meterInfo,
|
|
13450
|
+
// connector: connectorInfo,
|
|
13451
|
+
// chargingCosts: chargingCostsInfo
|
|
13299
13452
|
}
|
|
13300
13453
|
);
|
|
13301
13454
|
}
|
|
@@ -13546,7 +13699,7 @@ var PCDFCrypt01 = class extends ACrypt {
|
|
|
13546
13699
|
async VerifyChargingSession(chargingSession) {
|
|
13547
13700
|
let sessionResult = "ValidSignature" /* ValidSignature */;
|
|
13548
13701
|
let valueCount = 0;
|
|
13549
|
-
for (const measurement of chargingSession.measurements) {
|
|
13702
|
+
for (const measurement of chargingSession.measurements ?? []) {
|
|
13550
13703
|
measurement.chargingSession = chargingSession;
|
|
13551
13704
|
for (const measurementValue of measurement.values) {
|
|
13552
13705
|
valueCount++;
|
|
@@ -13645,10 +13798,10 @@ var PCDF = class {
|
|
|
13645
13798
|
"de": "Porsche Charging Data Format Ladevorgang",
|
|
13646
13799
|
"en": "Porsche Charging Data Format charging session"
|
|
13647
13800
|
},
|
|
13648
|
-
"
|
|
13801
|
+
"contracts": [{
|
|
13649
13802
|
"@id": data.session.idTag,
|
|
13650
13803
|
"type": data.session.idTagType
|
|
13651
|
-
},
|
|
13804
|
+
}],
|
|
13652
13805
|
"pcdf": {
|
|
13653
13806
|
"chargingSessionCounter": data.chargingSessionCounter,
|
|
13654
13807
|
"timeValid": data.timeValid,
|
|
@@ -13667,11 +13820,17 @@ var PCDF = class {
|
|
|
13667
13820
|
"EVSEs": [{
|
|
13668
13821
|
"@id": virtualEVSEId,
|
|
13669
13822
|
"description": { "en": "GraphDefined CHARGY Virtual EVSE 1" },
|
|
13670
|
-
"
|
|
13823
|
+
"energyMeters": [{
|
|
13671
13824
|
"@id": meterId,
|
|
13672
|
-
"manufacturer":
|
|
13673
|
-
|
|
13674
|
-
|
|
13825
|
+
"manufacturer": {
|
|
13826
|
+
"name": "Porsche"
|
|
13827
|
+
},
|
|
13828
|
+
"model": {
|
|
13829
|
+
"name": data.dcMeterType === 0 ? "PES DCMeter EU" : "Unknown DC Meter"
|
|
13830
|
+
},
|
|
13831
|
+
"firmware": {
|
|
13832
|
+
"checksum": data.softwareChecksum
|
|
13833
|
+
},
|
|
13675
13834
|
"signatureFormat": "https://open.charging.cloud/contexts/EnergyMeterSignatureFormats/PCDF+json",
|
|
13676
13835
|
"publicKeys": [{
|
|
13677
13836
|
"algorithm": "secp256r1",
|
|
@@ -13870,60 +14029,124 @@ var SAFEXML = class _SAFEXML {
|
|
|
13870
14029
|
constructor(chargy) {
|
|
13871
14030
|
this.chargy = chargy;
|
|
13872
14031
|
}
|
|
13873
|
-
static
|
|
13874
|
-
const
|
|
13875
|
-
|
|
13876
|
-
|
|
13877
|
-
|
|
13878
|
-
|
|
13879
|
-
|
|
13880
|
-
|
|
13881
|
-
|
|
13882
|
-
|
|
13883
|
-
|
|
13884
|
-
|
|
13885
|
-
|
|
13886
|
-
|
|
13887
|
-
|
|
13888
|
-
|
|
13889
|
-
|
|
13890
|
-
|
|
13891
|
-
|
|
13892
|
-
const
|
|
13893
|
-
const
|
|
13894
|
-
if (
|
|
13895
|
-
|
|
13896
|
-
|
|
13897
|
-
|
|
13898
|
-
|
|
13899
|
-
|
|
13900
|
-
|
|
13901
|
-
"@id": evseId,
|
|
13902
|
-
"description": parseDescription(evseElement),
|
|
13903
|
-
"meters": [],
|
|
13904
|
-
"connector": connector
|
|
13905
|
-
} : void 0;
|
|
14032
|
+
static ParseContainerInfos(XMLDocument, chargy) {
|
|
14033
|
+
const containerInfos = {};
|
|
14034
|
+
const chargingStationElements = getElementsByLocalName(XMLDocument, "chargingStation");
|
|
14035
|
+
if (chargingStationElements.length == 0)
|
|
14036
|
+
return containerInfos;
|
|
14037
|
+
if (chargingStationElements.length > 1) {
|
|
14038
|
+
return {
|
|
14039
|
+
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
14040
|
+
message: chargy.GetMultilanguageText("Only one chargingStation element is allowed within the given SAFE XML container!"),
|
|
14041
|
+
certainty: 0
|
|
14042
|
+
};
|
|
14043
|
+
}
|
|
14044
|
+
if (chargingStationElements[0] === void 0) {
|
|
14045
|
+
return {
|
|
14046
|
+
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
14047
|
+
message: chargy.GetMultilanguageText("The chargingStation element within the given SAFE XML container is invalid!"),
|
|
14048
|
+
certainty: 0
|
|
14049
|
+
};
|
|
14050
|
+
}
|
|
14051
|
+
const chargingStationElement = chargingStationElements[0];
|
|
14052
|
+
const chargingStationId = chargingStationElement.getAttribute("id")?.trim();
|
|
14053
|
+
if (chargingStationId === void 0 || chargingStationId.length == 0) {
|
|
14054
|
+
return {
|
|
14055
|
+
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
14056
|
+
message: chargy.GetMultilanguageText("The chargingStation identifier within the given SAFE XML container is invalid!"),
|
|
14057
|
+
certainty: 0
|
|
14058
|
+
};
|
|
14059
|
+
}
|
|
13906
14060
|
const chargingStation = {
|
|
13907
|
-
"@id": chargingStationId
|
|
13908
|
-
"description": parseDescription(chargingStationElement),
|
|
13909
|
-
"firmwareVersion": softwareVersion,
|
|
13910
|
-
"softwareVersion": softwareVersion,
|
|
13911
|
-
"geoLocation": geoLocation,
|
|
13912
|
-
"EVSE": parsedEVSE
|
|
13913
|
-
};
|
|
13914
|
-
return {
|
|
13915
|
-
"ChargingStationId": chargingStationId,
|
|
13916
|
-
"EVSEId": parsedEVSE?.["@id"],
|
|
13917
|
-
"chargingStation": chargingStation,
|
|
13918
|
-
"EVSE": parsedEVSE,
|
|
13919
|
-
"connector": parsedEVSE?.connector
|
|
14061
|
+
"@id": chargingStationId
|
|
13920
14062
|
};
|
|
14063
|
+
containerInfos.chargingStations = [chargingStation];
|
|
14064
|
+
const description = parseDescription(chargingStationElement);
|
|
14065
|
+
if (description !== void 0)
|
|
14066
|
+
chargingStation.description = description;
|
|
14067
|
+
const firmware = getDirectChildByLocalName(chargingStationElement, "firmware");
|
|
14068
|
+
if (firmware !== void 0) {
|
|
14069
|
+
chargingStation.firmware = {};
|
|
14070
|
+
const firmwareVersion = getTrimmedTextContent(getDirectChildByLocalName(firmware, "version"));
|
|
14071
|
+
if (firmwareVersion !== void 0)
|
|
14072
|
+
chargingStation.firmware.version = firmwareVersion;
|
|
14073
|
+
const firmwareChecksum = getTrimmedTextContent(getDirectChildByLocalName(firmware, "checksum"));
|
|
14074
|
+
if (firmwareChecksum !== void 0)
|
|
14075
|
+
chargingStation.firmware.checksum = firmwareChecksum;
|
|
14076
|
+
if (Object.keys(chargingStation.firmware).length === 0)
|
|
14077
|
+
delete chargingStation.firmware;
|
|
14078
|
+
}
|
|
14079
|
+
const geoLocationElement = getDirectChildByLocalName(chargingStationElement, "geoLocation");
|
|
14080
|
+
if (geoLocationElement !== void 0) {
|
|
14081
|
+
const latitude = Number.parseFloat(getTrimmedTextContent(getDirectChildByLocalName(geoLocationElement, "latitude")) ?? "");
|
|
14082
|
+
const longitude = Number.parseFloat(getTrimmedTextContent(getDirectChildByLocalName(geoLocationElement, "longitude")) ?? "");
|
|
14083
|
+
const geoLocation = Number.isFinite(latitude) && Number.isFinite(longitude) ? { lat: latitude, lng: longitude } : void 0;
|
|
14084
|
+
if (geoLocation !== void 0)
|
|
14085
|
+
chargingStation.geoLocation = geoLocation;
|
|
14086
|
+
}
|
|
14087
|
+
const evseElements = getElementsByLocalName(chargingStationElement, "EVSE");
|
|
14088
|
+
if (evseElements.length > 1) {
|
|
14089
|
+
return {
|
|
14090
|
+
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
14091
|
+
message: chargy.GetMultilanguageText("Only one EVSE element is allowed within the given SAFE XML chargingStation element!"),
|
|
14092
|
+
certainty: 0
|
|
14093
|
+
};
|
|
14094
|
+
}
|
|
14095
|
+
if (evseElements[0] === void 0) {
|
|
14096
|
+
return {
|
|
14097
|
+
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
14098
|
+
message: chargy.GetMultilanguageText("The EVSE element within the given SAFE XML chargingStation element is invalid!"),
|
|
14099
|
+
certainty: 0
|
|
14100
|
+
};
|
|
14101
|
+
}
|
|
14102
|
+
const evseElement = evseElements[0];
|
|
14103
|
+
const evseId = evseElement.getAttribute("id")?.trim();
|
|
14104
|
+
if (evseId !== void 0 && evseId.length > 0) {
|
|
14105
|
+
const evse = {
|
|
14106
|
+
"@id": evseId
|
|
14107
|
+
};
|
|
14108
|
+
chargingStation.EVSEs = [evse];
|
|
14109
|
+
const evseDescription = parseDescription(evseElement);
|
|
14110
|
+
if (evseDescription !== void 0)
|
|
14111
|
+
evse.description = evseDescription;
|
|
14112
|
+
const connectorElements = getElementsByLocalName(evseElement, "connector");
|
|
14113
|
+
if (connectorElements.length > 1) {
|
|
14114
|
+
return {
|
|
14115
|
+
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
14116
|
+
message: chargy.GetMultilanguageText("Only one connector element is allowed within the given SAFE XML EVSE element!"),
|
|
14117
|
+
certainty: 0
|
|
14118
|
+
};
|
|
14119
|
+
}
|
|
14120
|
+
if (connectorElements[0] === void 0) {
|
|
14121
|
+
return {
|
|
14122
|
+
status: "InvalidSessionFormat" /* InvalidSessionFormat */,
|
|
14123
|
+
message: chargy.GetMultilanguageText("The connector element within the given SAFE XML EVSE element is invalid!"),
|
|
14124
|
+
certainty: 0
|
|
14125
|
+
};
|
|
14126
|
+
}
|
|
14127
|
+
const connectorElement = connectorElements[0];
|
|
14128
|
+
const connector = {};
|
|
14129
|
+
const connectorId = connectorElement.getAttribute("id")?.trim();
|
|
14130
|
+
if (connectorId != null && connectorId.length > 0)
|
|
14131
|
+
connector["@id"] = connectorId;
|
|
14132
|
+
const connectorType = getTrimmedTextContent(getDirectChildByLocalName(connectorElement, "type"));
|
|
14133
|
+
if (connectorType !== void 0 && connectorType.length > 0)
|
|
14134
|
+
connector.type = connectorType;
|
|
14135
|
+
if (Object.keys(connector).length > 0)
|
|
14136
|
+
evse.connectors = [connector];
|
|
14137
|
+
}
|
|
14138
|
+
return containerInfos;
|
|
13921
14139
|
}
|
|
13922
14140
|
//#region tryToParseSAFEXML(XMLDocument)
|
|
13923
14141
|
async tryToParseSAFEXML(XMLDocument) {
|
|
13924
14142
|
try {
|
|
13925
14143
|
if (XMLDocument.documentElement.nodeName === "values" || XMLDocument.documentElement.localName === "values") {
|
|
13926
|
-
const safeXMLContext = _SAFEXML.
|
|
14144
|
+
const safeXMLContext = _SAFEXML.ParseContainerInfos(
|
|
14145
|
+
XMLDocument,
|
|
14146
|
+
this.chargy
|
|
14147
|
+
);
|
|
14148
|
+
if (isISessionCryptoResult1(safeXMLContext))
|
|
14149
|
+
return safeXMLContext;
|
|
13927
14150
|
const signedDataValues = new Array();
|
|
13928
14151
|
let commonSignedDataFormat = "";
|
|
13929
14152
|
let commonSignedDataEncoding = "";
|
|
@@ -14319,10 +14542,10 @@ var ChargeIT = class {
|
|
|
14319
14542
|
CTR["@id"] = lastMeterValue["transactionId"];
|
|
14320
14543
|
CTR.begin = this.chargy.moment.unix(firstMeterValue["measuredValue"]["timestampLocal"]["timestamp"]).utc().format();
|
|
14321
14544
|
CTR.end = this.chargy.moment.unix(lastMeterValue["measuredValue"]["timestampLocal"]["timestamp"]).utc().format();
|
|
14322
|
-
CTR.
|
|
14545
|
+
CTR.contracts = [{
|
|
14323
14546
|
"@id": firstMeterValue["contract"]["id"],
|
|
14324
14547
|
"@context": firstMeterValue["contract"]["type"]
|
|
14325
|
-
};
|
|
14548
|
+
}];
|
|
14326
14549
|
CTR.chargingStationOperators = [{
|
|
14327
14550
|
"@id": "chargeITmobilityCSO",
|
|
14328
14551
|
"description": { "de": "chargeIT mobility GmbH - Charging Station Operator Services" },
|
|
@@ -14380,7 +14603,9 @@ var ChargeIT = class {
|
|
|
14380
14603
|
// "description": {
|
|
14381
14604
|
// "de": "GraphDefined Charging Station - CI-Tests Pool 3 / Station A"
|
|
14382
14605
|
// },
|
|
14383
|
-
"
|
|
14606
|
+
"firmware": {
|
|
14607
|
+
"version": firstMeterValue["chargePoint"]["softwareVersion"]
|
|
14608
|
+
},
|
|
14384
14609
|
"geoLocation": { "lat": asNumber(geoLocation["lat"]) ?? 0, "lng": asNumber(geoLocation["lon"]) ?? 0 },
|
|
14385
14610
|
"address": {
|
|
14386
14611
|
"street": asString(address["street"]),
|
|
@@ -14395,22 +14620,32 @@ var ChargeIT = class {
|
|
|
14395
14620
|
// "de": "GraphDefined EVSE - CI-Tests Pool 3 / Station A / EVSE 1"
|
|
14396
14621
|
// },
|
|
14397
14622
|
// "connectors": [{ }],
|
|
14398
|
-
"
|
|
14623
|
+
"energyMeters": [
|
|
14399
14624
|
{
|
|
14400
14625
|
"@id": firstMeterValue["meterInfo"]["meterId"],
|
|
14401
|
-
"manufacturer":
|
|
14402
|
-
|
|
14403
|
-
|
|
14404
|
-
|
|
14405
|
-
|
|
14626
|
+
"manufacturer": {
|
|
14627
|
+
"name": firstMeterValue["meterInfo"]["manufacturer"],
|
|
14628
|
+
"contact": {
|
|
14629
|
+
"web": "https://www.emh-metering.de"
|
|
14630
|
+
}
|
|
14631
|
+
},
|
|
14632
|
+
"model": {
|
|
14633
|
+
"name": firstMeterValue["meterInfo"]["type"]
|
|
14634
|
+
},
|
|
14635
|
+
"hardware": {
|
|
14636
|
+
"revision": "1.0"
|
|
14637
|
+
},
|
|
14638
|
+
"firmware": {
|
|
14639
|
+
"version": firstMeterValue["meterInfo"]["firmwareVersion"]
|
|
14640
|
+
},
|
|
14406
14641
|
"signatureFormat": "https://open.charging.cloud/contexts/EnergyMeterSignatureFormats/EMHCrypt01",
|
|
14407
14642
|
"publicKeys": [
|
|
14408
14643
|
{
|
|
14409
14644
|
"algorithm": "secp192r1",
|
|
14410
14645
|
"format": "DER",
|
|
14411
14646
|
"encoding": "hex",
|
|
14412
|
-
"value": firstMeterValue["meterInfo"]["publicKey"].startsWith("04") ? firstMeterValue["meterInfo"]["publicKey"] : "04" + firstMeterValue["meterInfo"]["publicKey"]
|
|
14413
|
-
"signatures":
|
|
14647
|
+
"value": firstMeterValue["meterInfo"]["publicKey"].startsWith("04") ? firstMeterValue["meterInfo"]["publicKey"] : "04" + firstMeterValue["meterInfo"]["publicKey"]
|
|
14648
|
+
//"signatures": firstMeterValue["meterInfo"]["publicKeySignatures"]
|
|
14414
14649
|
}
|
|
14415
14650
|
]
|
|
14416
14651
|
}
|
|
@@ -14719,10 +14954,10 @@ var ChargeIT = class {
|
|
|
14719
14954
|
"value": "042313b9e469612b4ca06981bfdecb226e234632b01d84b6a814f63a114b7762c34ddce2e6853395b7a0f87275f63ffe3c",
|
|
14720
14955
|
"signatures": [
|
|
14721
14956
|
{
|
|
14722
|
-
"
|
|
14957
|
+
"@id": "...",
|
|
14723
14958
|
"algorithm": "secp192r1",
|
|
14724
14959
|
"format": "DER",
|
|
14725
|
-
"value": "
|
|
14960
|
+
"value": "..."
|
|
14726
14961
|
}
|
|
14727
14962
|
]
|
|
14728
14963
|
},
|
|
@@ -14781,7 +15016,7 @@ var ChargeIT = class {
|
|
|
14781
15016
|
// "de": "GraphDefined EVSE - CI-Tests Pool 3 / Station A / EVSE 1"
|
|
14782
15017
|
// },
|
|
14783
15018
|
//"connectors": [ ],
|
|
14784
|
-
"
|
|
15019
|
+
"energyMeters": []
|
|
14785
15020
|
}
|
|
14786
15021
|
]
|
|
14787
15022
|
}
|
|
@@ -14803,11 +15038,15 @@ var ChargeIT = class {
|
|
|
14803
15038
|
return new Alfen(this.chargy).TryToParseALFENFormat(
|
|
14804
15039
|
signedMeterValues.map((value) => asString(asJSONObject(value)?.["payload"]) ?? ""),
|
|
14805
15040
|
{
|
|
14806
|
-
|
|
14807
|
-
|
|
15041
|
+
chargingStations: [{
|
|
15042
|
+
"@id": "?",
|
|
14808
15043
|
geoLocation: { "lat": geoLocation_lat, "lng": geoLocation_lon },
|
|
14809
|
-
address: { "street": address_street, "postalCode": address_zipCode, "city": address_town, "country": address_country }
|
|
14810
|
-
|
|
15044
|
+
address: { "street": address_street, "postalCode": address_zipCode, "city": address_town, "country": address_country },
|
|
15045
|
+
EVSEs: [{
|
|
15046
|
+
"@id": evseId,
|
|
15047
|
+
energyMeters: []
|
|
15048
|
+
}]
|
|
15049
|
+
}]
|
|
14811
15050
|
}
|
|
14812
15051
|
);
|
|
14813
15052
|
}
|
|
@@ -14815,11 +15054,15 @@ var ChargeIT = class {
|
|
|
14815
15054
|
return new Alfen(this.chargy).TryToParseALFENFormat(
|
|
14816
15055
|
signedMeterValues.map((value) => asString(asJSONObject(value)?.["payload"]) ?? ""),
|
|
14817
15056
|
{
|
|
14818
|
-
|
|
14819
|
-
|
|
15057
|
+
chargingStations: [{
|
|
15058
|
+
"@id": "?",
|
|
14820
15059
|
geoLocation: { "lat": geoLocation_lat, "lng": geoLocation_lon },
|
|
14821
|
-
address: { "street": address_street, "postalCode": address_zipCode, "city": address_town, "country": address_country }
|
|
14822
|
-
|
|
15060
|
+
address: { "street": address_street, "postalCode": address_zipCode, "city": address_town, "country": address_country },
|
|
15061
|
+
EVSEs: [{
|
|
15062
|
+
"@id": evseId,
|
|
15063
|
+
energyMeters: []
|
|
15064
|
+
}]
|
|
15065
|
+
}]
|
|
14823
15066
|
}
|
|
14824
15067
|
);
|
|
14825
15068
|
if (signedMeterValueContext === oldChargeITMeterValueFormat)
|
|
@@ -14894,7 +15137,6 @@ var ChargeIT = class {
|
|
|
14894
15137
|
const connectorInfo_type = connectorInfo?.["type"];
|
|
14895
15138
|
const connectorInfo_losses = connectorInfo?.["losses"];
|
|
14896
15139
|
const chargingTariffs = SomeJSON["chargingTariffs"];
|
|
14897
|
-
const chargingPeriods = SomeJSON["chargingPeriods"];
|
|
14898
15140
|
const totalCosts = asJSONObject(SomeJSON["totalCosts"]);
|
|
14899
15141
|
const totalCosts_total = totalCosts?.["total"];
|
|
14900
15142
|
const totalCosts_currency = totalCosts?.["currency"];
|
|
@@ -15087,10 +15329,10 @@ var ChargeIT = class {
|
|
|
15087
15329
|
"value": "042313b9e469612b4ca06981bfdecb226e234632b01d84b6a814f63a114b7762c34ddce2e6853395b7a0f87275f63ffe3c",
|
|
15088
15330
|
"signatures": [
|
|
15089
15331
|
{
|
|
15090
|
-
"
|
|
15332
|
+
"@id": "...",
|
|
15091
15333
|
"algorithm": "secp192r1",
|
|
15092
15334
|
"format": "DER",
|
|
15093
|
-
"value": "
|
|
15335
|
+
"value": "..."
|
|
15094
15336
|
}
|
|
15095
15337
|
]
|
|
15096
15338
|
},
|
|
@@ -15152,7 +15394,7 @@ var ChargeIT = class {
|
|
|
15152
15394
|
// "de": "GraphDefined EVSE - CI-Tests Pool 3 / Station A / EVSE 1"
|
|
15153
15395
|
// },
|
|
15154
15396
|
//"connectors": [ ],
|
|
15155
|
-
"
|
|
15397
|
+
"energyMeters": []
|
|
15156
15398
|
}
|
|
15157
15399
|
]
|
|
15158
15400
|
}
|
|
@@ -15169,31 +15411,31 @@ var ChargeIT = class {
|
|
|
15169
15411
|
return new Alfen(this.chargy).TryToParseALFENFormat(
|
|
15170
15412
|
signedMeterValues.map((value) => asString(asJSONObject(value)?.["payload"]) ?? ""),
|
|
15171
15413
|
{
|
|
15172
|
-
chargingSession: {
|
|
15173
|
-
|
|
15174
|
-
},
|
|
15175
|
-
EVSEId:
|
|
15176
|
-
chargingStation: {
|
|
15177
|
-
|
|
15178
|
-
|
|
15179
|
-
|
|
15180
|
-
|
|
15181
|
-
|
|
15182
|
-
|
|
15183
|
-
|
|
15184
|
-
|
|
15185
|
-
|
|
15186
|
-
|
|
15187
|
-
|
|
15188
|
-
|
|
15189
|
-
|
|
15190
|
-
|
|
15191
|
-
},
|
|
15192
|
-
energyMeter:
|
|
15193
|
-
connector:
|
|
15194
|
-
chargingTariffs,
|
|
15195
|
-
chargingPeriods,
|
|
15196
|
-
totalCosts
|
|
15414
|
+
// chargingSession: {
|
|
15415
|
+
// "@id": chargingSessionId
|
|
15416
|
+
// },
|
|
15417
|
+
// EVSEId: evseId,
|
|
15418
|
+
// chargingStation: {
|
|
15419
|
+
// manufacturer: chargingStation_manufacturer,
|
|
15420
|
+
// type: chargingStation_type,
|
|
15421
|
+
// serialNumber: chargingStation_serialNumber,
|
|
15422
|
+
// firmwareVersion: chargingStation_controllerSoftwareVersion,
|
|
15423
|
+
// legalCompliance: {
|
|
15424
|
+
// conformity: [{
|
|
15425
|
+
// freeText: chargingStation_compliance
|
|
15426
|
+
// }],
|
|
15427
|
+
// calibration: [{
|
|
15428
|
+
// freeText: chargingStation_calibration
|
|
15429
|
+
// }]
|
|
15430
|
+
// },
|
|
15431
|
+
// geoLocation: { "lat": geoLocation_lat, "lng": geoLocation_lon },
|
|
15432
|
+
// address: { "street": address_street, "postalCode": address_zipCode, "city": address_town, "country": address_country }
|
|
15433
|
+
// },
|
|
15434
|
+
// energyMeter: meterInfo,
|
|
15435
|
+
// connector: connectorInfo,
|
|
15436
|
+
// chargingTariffs: chargingTariffs,
|
|
15437
|
+
// chargingPeriods: chargingPeriods,
|
|
15438
|
+
// totalCosts: totalCosts
|
|
15197
15439
|
}
|
|
15198
15440
|
);
|
|
15199
15441
|
}
|
|
@@ -15325,12 +15567,18 @@ var ChargePoint = class {
|
|
|
15325
15567
|
"address": asJSONObject(SomeJSON["address"]),
|
|
15326
15568
|
"EVSEs": [{
|
|
15327
15569
|
"@id": evseId,
|
|
15328
|
-
"
|
|
15570
|
+
"energyMeters": [{
|
|
15329
15571
|
"@id": meterSerial,
|
|
15330
|
-
"manufacturer":
|
|
15331
|
-
|
|
15332
|
-
|
|
15333
|
-
|
|
15572
|
+
"manufacturer": {
|
|
15573
|
+
"name": "Carlo Gavazzi",
|
|
15574
|
+
"contact": {
|
|
15575
|
+
"web": "https://www.gavazziautomation.com"
|
|
15576
|
+
}
|
|
15577
|
+
},
|
|
15578
|
+
"model": {
|
|
15579
|
+
"name": "EM340-DIN.AV2.3.X.S1.X",
|
|
15580
|
+
"url": "https://www.gavazziautomation.com/fileadmin/images/PIM/DATASHEET/ENG/EM340_DS_ENG.pdf"
|
|
15581
|
+
}
|
|
15334
15582
|
// "signatureFormat": "https://open.charging.cloud/contexts/EnergyMeterSignatureFormats/EMHCrypt01",
|
|
15335
15583
|
// "publicKeys": [
|
|
15336
15584
|
// {
|
|
@@ -15485,12 +15733,18 @@ var ChargePoint = class {
|
|
|
15485
15733
|
"address": asJSONObject(SomeJSON["address"]),
|
|
15486
15734
|
"EVSEs": [{
|
|
15487
15735
|
"@id": evseId,
|
|
15488
|
-
"
|
|
15736
|
+
"energyMeters": [{
|
|
15489
15737
|
"@id": meterSerial,
|
|
15490
|
-
"manufacturer":
|
|
15491
|
-
|
|
15492
|
-
|
|
15493
|
-
|
|
15738
|
+
"manufacturer": {
|
|
15739
|
+
"name": "Carlo Gavazzi",
|
|
15740
|
+
"contact": {
|
|
15741
|
+
"web": "https://www.gavazziautomation.com"
|
|
15742
|
+
}
|
|
15743
|
+
},
|
|
15744
|
+
"model": {
|
|
15745
|
+
"name": "EM340-DIN.AV2.3.X.S1.X",
|
|
15746
|
+
"url": "https://www.gavazziautomation.com/fileadmin/images/PIM/DATASHEET/ENG/EM340_DS_ENG.pdf"
|
|
15747
|
+
},
|
|
15494
15748
|
"signatureFormat": "https://open.charging.cloud/contexts/EnergyMeterSignatureFormats/EMHCrypt01",
|
|
15495
15749
|
"signatureInfos": {
|
|
15496
15750
|
"hash": "SHA256",
|
|
@@ -15502,7 +15756,8 @@ var ChargePoint = class {
|
|
|
15502
15756
|
"publicKeys": [{
|
|
15503
15757
|
"algorithm": "secp224k1",
|
|
15504
15758
|
"format": "DER",
|
|
15505
|
-
"encoding": "hex"
|
|
15759
|
+
"encoding": "hex",
|
|
15760
|
+
"value": "..."
|
|
15506
15761
|
}]
|
|
15507
15762
|
}]
|
|
15508
15763
|
}]
|
|
@@ -15604,7 +15859,7 @@ var ChargePointCrypt01 = class extends ACrypt {
|
|
|
15604
15859
|
s: ASN1Signature.s.toString(16)
|
|
15605
15860
|
};
|
|
15606
15861
|
}
|
|
15607
|
-
const publicKeyId = chargingSession.EVSEId
|
|
15862
|
+
const publicKeyId = chargingSession.EVSEId?.replace(/:/g, "").replace(/-/g, "_");
|
|
15608
15863
|
const publicKeys = [];
|
|
15609
15864
|
if (chargingSession.ctr.publicKeys != null) {
|
|
15610
15865
|
for (const publicKeyInfo of chargingSession.ctr.publicKeys) {
|
|
@@ -15635,8 +15890,8 @@ var ChargePointCrypt01 = class extends ACrypt {
|
|
|
15635
15890
|
sha225Value = sha225Value ?? (BigInt("0x" + await sha256(plainText)) >> BigInt(31)).toString(16);
|
|
15636
15891
|
sessionResult = this.curve224k1.validate(
|
|
15637
15892
|
BigInt("0x" + sha225Value),
|
|
15638
|
-
BigInt("0x" +
|
|
15639
|
-
BigInt("0x" +
|
|
15893
|
+
BigInt("0x" + chargingSession.signature.r),
|
|
15894
|
+
BigInt("0x" + chargingSession.signature.s),
|
|
15640
15895
|
[
|
|
15641
15896
|
BigInt("0x" + publicKey.value.slice(2, 58)),
|
|
15642
15897
|
BigInt("0x" + publicKey.value.slice(58, 114))
|
|
@@ -15684,7 +15939,7 @@ var ChargePointCrypt01 = class extends ACrypt {
|
|
|
15684
15939
|
}
|
|
15685
15940
|
}
|
|
15686
15941
|
}
|
|
15687
|
-
for (const measurement of chargingSession.measurements) {
|
|
15942
|
+
for (const measurement of chargingSession.measurements ?? []) {
|
|
15688
15943
|
measurement.chargingSession = chargingSession;
|
|
15689
15944
|
if (measurement.values.length > 1) {
|
|
15690
15945
|
for (const measurementValue of measurement.values) {
|
|
@@ -15827,8 +16082,8 @@ var ChargePointCrypt01 = class extends ACrypt {
|
|
|
15827
16082
|
signatureDiv.innerHTML = await this.chargy.CheckMeterPublicKeySignature(
|
|
15828
16083
|
measurementValue.measurement.chargingSession.chargingStation,
|
|
15829
16084
|
measurementValue.measurement.chargingSession.EVSE,
|
|
15830
|
-
measurementValue.measurement.chargingSession.EVSE?.
|
|
15831
|
-
measurementValue.measurement.chargingSession.EVSE?.
|
|
16085
|
+
measurementValue.measurement.chargingSession.EVSE?.energyMeters?.[0],
|
|
16086
|
+
measurementValue.measurement.chargingSession.EVSE?.energyMeters?.[0]?.publicKeys?.[0],
|
|
15832
16087
|
signature
|
|
15833
16088
|
);
|
|
15834
16089
|
} catch {
|
|
@@ -15841,7 +16096,7 @@ var ChargePointCrypt01 = class extends ACrypt {
|
|
|
15841
16096
|
getArrayLikeElement(SignatureExpectedDiv.parentElement.children, 0, "Missing expected signature header").innerHTML = "Erwartete Signatur (secrrct.sign, rs, hex)";
|
|
15842
16097
|
}
|
|
15843
16098
|
if (typeof chargingSession.signature != "string")
|
|
15844
|
-
SignatureExpectedDiv.innerHTML = "r: " + (chargingSession.signature.r
|
|
16099
|
+
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(" ") ?? "");
|
|
15845
16100
|
else if (chargingSession.signature)
|
|
15846
16101
|
SignatureExpectedDiv.innerHTML = chargingSession.signature.toLowerCase().match(/.{1,8}/g)?.join(" ") ?? "-";
|
|
15847
16102
|
}
|
|
@@ -15879,7 +16134,8 @@ var IChargeTransparencyRecord_exports = {};
|
|
|
15879
16134
|
__export(IChargeTransparencyRecord_exports, {
|
|
15880
16135
|
CloneCTR: () => CloneCTR,
|
|
15881
16136
|
IsAChargeTransparencyRecord: () => IsAChargeTransparencyRecord,
|
|
15882
|
-
IsASessionCryptoResult: () => IsASessionCryptoResult
|
|
16137
|
+
IsASessionCryptoResult: () => IsASessionCryptoResult,
|
|
16138
|
+
toSessionVerificationResults: () => toSessionVerificationResults
|
|
15883
16139
|
});
|
|
15884
16140
|
function IsAChargeTransparencyRecord(data) {
|
|
15885
16141
|
if (!isMandatoryJSONObject(data))
|
|
@@ -15897,7 +16153,7 @@ function CloneCTR(CTR) {
|
|
|
15897
16153
|
const clonedCTR = JSON.parse(JSON.stringify(CTR));
|
|
15898
16154
|
if (clonedCTR.chargingSessions) {
|
|
15899
16155
|
for (const session of clonedCTR.chargingSessions) {
|
|
15900
|
-
for (const measurement of session.measurements) {
|
|
16156
|
+
for (const measurement of session.measurements ?? []) {
|
|
15901
16157
|
for (const value of measurement.values) {
|
|
15902
16158
|
if (typeof value.value === "string" || typeof value.value === "number")
|
|
15903
16159
|
value.value = new Decimal(value.value);
|
|
@@ -15907,6 +16163,16 @@ function CloneCTR(CTR) {
|
|
|
15907
16163
|
}
|
|
15908
16164
|
return clonedCTR;
|
|
15909
16165
|
}
|
|
16166
|
+
function toSessionVerificationResults(CTR, noRecordsMessage = { "en": "No charge transparency records found!" }) {
|
|
16167
|
+
const verificationResults = (CTR.chargingSessions ?? []).map((session) => session.verificationResult).filter(isISessionCryptoResult1);
|
|
16168
|
+
if (verificationResults.length > 0)
|
|
16169
|
+
return verificationResults;
|
|
16170
|
+
return {
|
|
16171
|
+
status: "Unvalidated" /* Unvalidated */,
|
|
16172
|
+
message: noRecordsMessage,
|
|
16173
|
+
certainty: 0
|
|
16174
|
+
};
|
|
16175
|
+
}
|
|
15910
16176
|
|
|
15911
16177
|
// src/interfaces/IChargeTransparencyLiveLink.ts
|
|
15912
16178
|
var IChargeTransparencyLiveLink_exports = {};
|
|
@@ -15937,43 +16203,11 @@ function isTransport(data) {
|
|
|
15937
16203
|
function IsAChargeTransparencyLiveLink(data) {
|
|
15938
16204
|
if (!isMandatoryJSONObject(data))
|
|
15939
16205
|
return false;
|
|
15940
|
-
return data["@context"] === ChargeTransparencyLiveLinkContext && (data["timestamp"] === void 0 || data["timestamp"] === null || typeof data["timestamp"] === "string") && (data["description"] === void 0 ||
|
|
16206
|
+
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"]));
|
|
15941
16207
|
}
|
|
15942
16208
|
function isTOTPConfig(data) {
|
|
15943
16209
|
return isObject(data) && typeof data["initialSharedSecret"] === "string" && typeof data["timeStep"] === "number";
|
|
15944
16210
|
}
|
|
15945
|
-
|
|
15946
|
-
// src/interfaces/IPublicKeyInfo.ts
|
|
15947
|
-
var IPublicKeyInfo_exports = {};
|
|
15948
|
-
__export(IPublicKeyInfo_exports, {
|
|
15949
|
-
IsAPublicKeyInfo: () => IsAPublicKeyInfo,
|
|
15950
|
-
IsAPublicKeyLookup: () => IsAPublicKeyLookup
|
|
15951
|
-
});
|
|
15952
|
-
function IsAPublicKeyLookup(data) {
|
|
15953
|
-
if (!isMandatoryJSONObject(data))
|
|
15954
|
-
return false;
|
|
15955
|
-
return Array.isArray(data["publicKeys"]);
|
|
15956
|
-
}
|
|
15957
|
-
function IsAPublicKeyInfo(data) {
|
|
15958
|
-
if (!isMandatoryJSONObject(data))
|
|
15959
|
-
return false;
|
|
15960
|
-
if (!isStringOrStringArray(data["@context"])) return false;
|
|
15961
|
-
if (!isString(data["value"])) return false;
|
|
15962
|
-
if (!isStringOrOIDInfo(data["algorithm"])) return false;
|
|
15963
|
-
if (data["certainty"] !== void 0 && (typeof data["certainty"] !== "number" || !Number.isFinite(data["certainty"]))) {
|
|
15964
|
-
return false;
|
|
15965
|
-
}
|
|
15966
|
-
if (data["type"] !== void 0 && !isStringOrOIDInfo(data["type"])) {
|
|
15967
|
-
return false;
|
|
15968
|
-
}
|
|
15969
|
-
if (data["encoding"] !== void 0 && typeof data["encoding"] !== "string") {
|
|
15970
|
-
return false;
|
|
15971
|
-
}
|
|
15972
|
-
if (data["signatures"] !== void 0 && !Array.isArray(data["signatures"])) {
|
|
15973
|
-
return false;
|
|
15974
|
-
}
|
|
15975
|
-
return true;
|
|
15976
|
-
}
|
|
15977
16211
|
function isRecord(value) {
|
|
15978
16212
|
return typeof value === "object" && value !== null;
|
|
15979
16213
|
}
|
|
@@ -16468,13 +16702,10 @@ var Chargy = class {
|
|
|
16468
16702
|
}
|
|
16469
16703
|
return this.CompleteMultilanguageText(parameterizedText, Text.replace("%p", String(Parameter)));
|
|
16470
16704
|
}
|
|
16471
|
-
|
|
16705
|
+
GetLocalizedText(data) {
|
|
16472
16706
|
if (data == null)
|
|
16473
16707
|
return void 0;
|
|
16474
|
-
|
|
16475
|
-
if (bestLanguage == null)
|
|
16476
|
-
return void 0;
|
|
16477
|
-
return data[bestLanguage];
|
|
16708
|
+
return this.FindBestMultilanguageText(data);
|
|
16478
16709
|
}
|
|
16479
16710
|
//#endregion
|
|
16480
16711
|
//#region GetDevices...
|
|
@@ -16526,11 +16757,13 @@ var Chargy = class {
|
|
|
16526
16757
|
"@id": evse["@id"],
|
|
16527
16758
|
"description": evse.description,
|
|
16528
16759
|
"sockets": evseView["sockets"],
|
|
16529
|
-
"
|
|
16760
|
+
"energyMeter": {
|
|
16530
16761
|
"@id": meter["@id"],
|
|
16531
16762
|
"vendor": meterView["vendor"],
|
|
16532
16763
|
"model": meter.model,
|
|
16533
|
-
"
|
|
16764
|
+
"firmware": {
|
|
16765
|
+
"version": meter.firmware?.version
|
|
16766
|
+
},
|
|
16534
16767
|
"signatureFormat": meter.signatureFormat,
|
|
16535
16768
|
"publicKey": {
|
|
16536
16769
|
"algorithm": publicKey.algorithm,
|
|
@@ -16848,11 +17081,12 @@ var Chargy = class {
|
|
|
16848
17081
|
//#endregion
|
|
16849
17082
|
//#region DetectAndConvertContentFormat(FileInfos)
|
|
16850
17083
|
async DetectAndConvertContentFormat(FileInfos) {
|
|
16851
|
-
if (FileInfos.length == 0)
|
|
16852
|
-
|
|
16853
|
-
|
|
16854
|
-
|
|
16855
|
-
|
|
17084
|
+
if (FileInfos.length == 0)
|
|
17085
|
+
return {
|
|
17086
|
+
status: "NoChargeTransparencyRecordsFound" /* NoChargeTransparencyRecordsFound */,
|
|
17087
|
+
message: this.GetMultilanguageText("No charge transparency records found!"),
|
|
17088
|
+
certainty: 0
|
|
17089
|
+
};
|
|
16856
17090
|
let expandedFiles = new Array();
|
|
16857
17091
|
const processedFiles = new Array();
|
|
16858
17092
|
if (FileInfos.length > 0) {
|
|
@@ -17025,42 +17259,40 @@ var Chargy = class {
|
|
|
17025
17259
|
} else if (textContent.startsWith("{") && textContent.endsWith("}")) {
|
|
17026
17260
|
try {
|
|
17027
17261
|
const JSONContent = JSON.parse(textContent);
|
|
17028
|
-
if (typeof JSONContent !== "object" || JSONContent
|
|
17029
|
-
throw new Error("Parsed JSON content is not
|
|
17030
|
-
|
|
17031
|
-
|
|
17032
|
-
|
|
17033
|
-
|
|
17262
|
+
if (JSONContent === null || typeof JSONContent !== "object" || !isMandatoryJSONObject(JSONContent))
|
|
17263
|
+
throw new Error("Parsed JSON content is not a JSON object!");
|
|
17264
|
+
const JSONContext = JSONContent["@context"];
|
|
17265
|
+
if (IsAChargeTransparencyLiveLink(JSONContent)) {
|
|
17266
|
+
JSONContent.timestamp ??= (/* @__PURE__ */ new Date()).toISOString();
|
|
17267
|
+
processedFile.result = JSONContent;
|
|
17268
|
+
} else if (isMandatoryString(JSONContext)) {
|
|
17269
|
+
if (JSONContext.startsWith("https://open.charging.cloud/contexts/CTR+json"))
|
|
17034
17270
|
processedFile.result = JSONContent;
|
|
17035
|
-
|
|
17036
|
-
|
|
17037
|
-
|
|
17038
|
-
|
|
17039
|
-
processedFile.result = JSONContent;
|
|
17040
|
-
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")) {
|
|
17041
|
-
processedFile.result = new ChargeIT(this).TryToParseChargeITContainerFormat(JSONContent);
|
|
17042
|
-
}
|
|
17043
|
-
} else {
|
|
17044
|
-
const results = [
|
|
17045
|
-
new ChargeIT(this).TryToParseChargeITContainerFormat(JSONContent),
|
|
17046
|
-
new ChargePoint(this).TryToParseChargepointFormat(JSONContent),
|
|
17047
|
-
await new OCPI(this).tryToParseOCPIFormat(JSONContent)
|
|
17048
|
-
];
|
|
17049
|
-
const filteredResults = results.filter((ctr) => {
|
|
17050
|
-
return isISessionCryptoResult1(ctr);
|
|
17051
|
-
});
|
|
17052
|
-
const sortedResults = filteredResults.sort((ctr1, ctr2) => {
|
|
17053
|
-
if (ctr1.certainty > ctr2.certainty) {
|
|
17054
|
-
return -1;
|
|
17055
|
-
}
|
|
17056
|
-
if (ctr1.certainty < ctr2.certainty) {
|
|
17057
|
-
return 1;
|
|
17058
|
-
}
|
|
17059
|
-
return 0;
|
|
17060
|
-
});
|
|
17061
|
-
if (sortedResults.length >= 1 && sortedResults[0])
|
|
17062
|
-
processedFile.result = sortedResults[0];
|
|
17271
|
+
else if (JSONContext.startsWith("https://open.charging.cloud/contexts/publicKey+json"))
|
|
17272
|
+
processedFile.result = JSONContent;
|
|
17273
|
+
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")) {
|
|
17274
|
+
processedFile.result = new ChargeIT(this).TryToParseChargeITContainerFormat(JSONContent);
|
|
17063
17275
|
}
|
|
17276
|
+
} else {
|
|
17277
|
+
const results = [
|
|
17278
|
+
new ChargeIT(this).TryToParseChargeITContainerFormat(JSONContent),
|
|
17279
|
+
new ChargePoint(this).TryToParseChargepointFormat(JSONContent),
|
|
17280
|
+
await new OCPI(this).tryToParseOCPIFormat(JSONContent)
|
|
17281
|
+
];
|
|
17282
|
+
const filteredResults = results.filter((ctr) => {
|
|
17283
|
+
return isISessionCryptoResult1(ctr);
|
|
17284
|
+
});
|
|
17285
|
+
const sortedResults = filteredResults.sort((ctr1, ctr2) => {
|
|
17286
|
+
if (ctr1.certainty > ctr2.certainty) {
|
|
17287
|
+
return -1;
|
|
17288
|
+
}
|
|
17289
|
+
if (ctr1.certainty < ctr2.certainty) {
|
|
17290
|
+
return 1;
|
|
17291
|
+
}
|
|
17292
|
+
return 0;
|
|
17293
|
+
});
|
|
17294
|
+
if (sortedResults.length >= 1 && sortedResults[0])
|
|
17295
|
+
processedFile.result = sortedResults[0];
|
|
17064
17296
|
}
|
|
17065
17297
|
} catch (exception) {
|
|
17066
17298
|
processedFile.result = {
|
|
@@ -17104,7 +17336,7 @@ var Chargy = class {
|
|
|
17104
17336
|
if (processedFileResult.end != null && processedFileResult.end.length > 0 && (mergedCTR.end == null || mergedCTR.end.length === 0 || mergedCTR.end < processedFileResult.end))
|
|
17105
17337
|
mergedCTR.end = processedFileResult.end;
|
|
17106
17338
|
mergedCTR.description ??= processedFileResult.description;
|
|
17107
|
-
mergedCTR.
|
|
17339
|
+
mergedCTR.contracts ??= processedFileResult.contracts;
|
|
17108
17340
|
if (!mergedCTR.chargingStationOperators)
|
|
17109
17341
|
mergedCTR.chargingStationOperators = processedFileResult.chargingStationOperators;
|
|
17110
17342
|
else if (processedFileResult.chargingStationOperators)
|
|
@@ -17135,7 +17367,7 @@ var Chargy = class {
|
|
|
17135
17367
|
else if (processedFileResult.mediationServices)
|
|
17136
17368
|
for (const mediationService of processedFileResult.mediationServices)
|
|
17137
17369
|
mergedCTR.mediationServices.push(mediationService);
|
|
17138
|
-
} else if (
|
|
17370
|
+
} else if (IsAPublicKey(processedFileResult)) {
|
|
17139
17371
|
mergedCTR.publicKeys ??= new Array();
|
|
17140
17372
|
mergedCTR.publicKeys.push(processedFileResult);
|
|
17141
17373
|
} else if (IsAPublicKeyLookup(processedFileResult)) {
|
|
@@ -17183,11 +17415,11 @@ var Chargy = class {
|
|
|
17183
17415
|
if (chargingPool.chargingStations) {
|
|
17184
17416
|
for (const chargingStation of chargingPool.chargingStations) {
|
|
17185
17417
|
this.chargingStations.push(chargingStation);
|
|
17186
|
-
for (const EVSE of chargingStation.EVSEs) {
|
|
17418
|
+
for (const EVSE of chargingStation.EVSEs ?? []) {
|
|
17187
17419
|
EVSE.chargingStation = chargingStation;
|
|
17188
17420
|
EVSE.chargingStationId = chargingStation["@id"];
|
|
17189
17421
|
this.EVSEs.push(EVSE);
|
|
17190
|
-
for (const meter of EVSE.
|
|
17422
|
+
for (const meter of EVSE.energyMeters ?? []) {
|
|
17191
17423
|
meter.EVSE = EVSE;
|
|
17192
17424
|
meter.EVSEId = EVSE["@id"];
|
|
17193
17425
|
meter.chargingStation = chargingStation;
|
|
@@ -17202,11 +17434,11 @@ var Chargy = class {
|
|
|
17202
17434
|
if (chargingStationOperator.chargingStations) {
|
|
17203
17435
|
for (const chargingStation of chargingStationOperator.chargingStations) {
|
|
17204
17436
|
this.chargingStations.push(chargingStation);
|
|
17205
|
-
for (const EVSE of chargingStation.EVSEs) {
|
|
17437
|
+
for (const EVSE of chargingStation.EVSEs ?? []) {
|
|
17206
17438
|
EVSE.chargingStation = chargingStation;
|
|
17207
17439
|
EVSE.chargingStationId = chargingStation["@id"];
|
|
17208
17440
|
this.EVSEs.push(EVSE);
|
|
17209
|
-
for (const meter of EVSE.
|
|
17441
|
+
for (const meter of EVSE.energyMeters ?? []) {
|
|
17210
17442
|
meter.EVSE = EVSE;
|
|
17211
17443
|
meter.EVSEId = EVSE["@id"];
|
|
17212
17444
|
meter.chargingStation = chargingStation;
|
|
@@ -17219,7 +17451,7 @@ var Chargy = class {
|
|
|
17219
17451
|
if (chargingStationOperator.EVSEs) {
|
|
17220
17452
|
for (const EVSE of chargingStationOperator.EVSEs) {
|
|
17221
17453
|
this.EVSEs.push(EVSE);
|
|
17222
|
-
for (const meter of EVSE.
|
|
17454
|
+
for (const meter of EVSE.energyMeters ?? []) {
|
|
17223
17455
|
meter.EVSE = EVSE;
|
|
17224
17456
|
meter.EVSEId = EVSE["@id"];
|
|
17225
17457
|
this.meters.push(meter);
|
|
@@ -17234,11 +17466,11 @@ var Chargy = class {
|
|
|
17234
17466
|
if (chargingPool.chargingStations) {
|
|
17235
17467
|
for (const chargingStation of chargingPool.chargingStations) {
|
|
17236
17468
|
this.chargingStations.push(chargingStation);
|
|
17237
|
-
for (const EVSE of chargingStation.EVSEs) {
|
|
17469
|
+
for (const EVSE of chargingStation.EVSEs ?? []) {
|
|
17238
17470
|
EVSE.chargingStation = chargingStation;
|
|
17239
17471
|
EVSE.chargingStationId = chargingStation["@id"];
|
|
17240
17472
|
this.EVSEs.push(EVSE);
|
|
17241
|
-
for (const meter of EVSE.
|
|
17473
|
+
for (const meter of EVSE.energyMeters ?? []) {
|
|
17242
17474
|
meter.EVSE = EVSE;
|
|
17243
17475
|
meter.EVSEId = EVSE["@id"];
|
|
17244
17476
|
meter.chargingStation = chargingStation;
|
|
@@ -17253,11 +17485,11 @@ var Chargy = class {
|
|
|
17253
17485
|
if (this.internalCTR.chargingStations) {
|
|
17254
17486
|
for (const chargingStation of this.internalCTR.chargingStations) {
|
|
17255
17487
|
this.chargingStations.push(chargingStation);
|
|
17256
|
-
for (const EVSE of chargingStation.EVSEs) {
|
|
17488
|
+
for (const EVSE of chargingStation.EVSEs ?? []) {
|
|
17257
17489
|
EVSE.chargingStation = chargingStation;
|
|
17258
17490
|
EVSE.chargingStationId = chargingStation["@id"];
|
|
17259
17491
|
this.EVSEs.push(EVSE);
|
|
17260
|
-
for (const meter of EVSE.
|
|
17492
|
+
for (const meter of EVSE.energyMeters ?? []) {
|
|
17261
17493
|
meter.EVSE = EVSE;
|
|
17262
17494
|
meter.EVSEId = EVSE["@id"];
|
|
17263
17495
|
meter.chargingStation = chargingStation;
|
|
@@ -17265,8 +17497,8 @@ var Chargy = class {
|
|
|
17265
17497
|
this.meters.push(meter);
|
|
17266
17498
|
}
|
|
17267
17499
|
}
|
|
17268
|
-
if (chargingStation.
|
|
17269
|
-
for (const meter of chargingStation.
|
|
17500
|
+
if (chargingStation.energyMeters) {
|
|
17501
|
+
for (const meter of chargingStation.energyMeters ?? []) {
|
|
17270
17502
|
meter.chargingStation = chargingStation;
|
|
17271
17503
|
meter.chargingStationId = chargingStation["@id"];
|
|
17272
17504
|
this.meters.push(meter);
|
|
@@ -17293,7 +17525,7 @@ var Chargy = class {
|
|
|
17293
17525
|
//#endregion
|
|
17294
17526
|
//#region (private) hasInplausibleChargingSessionTotalEnergyMeasurement(chargingSession)
|
|
17295
17527
|
hasInplausibleChargingSessionTotalEnergyMeasurement(chargingSession) {
|
|
17296
|
-
for (const measurement of chargingSession.measurements) {
|
|
17528
|
+
for (const measurement of chargingSession.measurements ?? []) {
|
|
17297
17529
|
if (measurement.name !== "ENERGY_TOTAL" || measurement.values.length < 2) {
|
|
17298
17530
|
continue;
|
|
17299
17531
|
}
|
|
@@ -17453,7 +17685,7 @@ var Chargy = class {
|
|
|
17453
17685
|
if (ctr.end != null && ctr.end.length > 0 && (mergedCTR.end == null || mergedCTR.end.length === 0 || mergedCTR.end < ctr.end))
|
|
17454
17686
|
mergedCTR.end = ctr.end;
|
|
17455
17687
|
mergedCTR.description ??= ctr.description;
|
|
17456
|
-
mergedCTR.
|
|
17688
|
+
mergedCTR.contracts ??= ctr.contracts;
|
|
17457
17689
|
if (!mergedCTR.chargingStationOperators)
|
|
17458
17690
|
mergedCTR.chargingStationOperators = ctr.chargingStationOperators;
|
|
17459
17691
|
else if (ctr.chargingStationOperators)
|
|
@@ -17489,18 +17721,6 @@ var Chargy = class {
|
|
|
17489
17721
|
}
|
|
17490
17722
|
};
|
|
17491
17723
|
|
|
17492
|
-
|
|
17493
|
-
function toSessionVerificationResults(CTR, noRecordsMessage = { "en": "No charge transparency records found!" }) {
|
|
17494
|
-
const verificationResults = (CTR.chargingSessions ?? []).map((session) => session.verificationResult).filter(isISessionCryptoResult1);
|
|
17495
|
-
if (verificationResults.length > 0)
|
|
17496
|
-
return verificationResults;
|
|
17497
|
-
return {
|
|
17498
|
-
status: "Unvalidated" /* Unvalidated */,
|
|
17499
|
-
message: noRecordsMessage,
|
|
17500
|
-
certainty: 0
|
|
17501
|
-
};
|
|
17502
|
-
}
|
|
17503
|
-
|
|
17504
|
-
export { ACrypt, Alfen, AlfenCrypt01, BSMCrypt01, CanonicalJSONError, ChargeIT, ChargePoint, ChargePointCrypt01, IChargeTransparencyLiveLink_exports as ChargeTransparencyLiveLink, ChargeTransparencyLiveLinkContext, IChargeTransparencyRecord_exports as ChargeTransparencyRecord, Chargy, chargyInterfaces_exports as ChargyInterfaces, Clone, CloneCTR, ConcatenateBuffers, CreateDiv, CreateDiv2, CreateError, CryptoAlgorithms, CryptoHashAlgorithms, DayOfWeek, DisplayPrefixes, EMHCrypt01, ErrorLevel, GDFCrypt01, IECCurves, IEncoding, InformationRelevance, InformationRelevanceToString, IsAChargeTransparencyLiveLink, IsAChargeTransparencyRecord, IsAPublicKeyInfo, IsAPublicKeyLookup, IsASessionCryptoResult, IsNullOrEmpty, JSONSignatureVerificationStatus, MENNEKES_EDL40_OBIS, MENNEKES_EDL40_XMLNS, Mennekes, MennekesCrypt01, OBIS2Hex, OBIS2MeasurementName, OBIS_RegExpr, OCMF, OCMFTransactionTypes, OCMFv1_x, OCPI, PCDF, PCDFCrypt01, PCDFParseError, PCDFValidationError, PCDF_FIELD_ORDER, PCDF_PREFIX, ParseJSON_LD, PublicKeyFormats, IPublicKeyInfo_exports as PublicKeyInfo, SAFEXML, SessionVerificationResult, SetHex, SetInt8, SetText, SetText_withLength, SetTimestamp, SetTimestamp32, SetUInt32, SetUInt32_withCode, SetUInt64, SetUInt64D, SignMessage, SignatureFormats, TimeStatusTypes, UTC2human, VerificationResult, VerifyJSONMessageSignatures, WarningLevel, WhenNullOrEmpty, XMLContainer, asJSONArray, asJSONObject, asNumber, asString, buf2hex, buildMennekesSignatureData, bytesToHex2 as bytesToHex, canonicalJSONBytes, canonicalJSONStringify, cleanHex, closeFullscreen, createHexString, dateToMennekesLocalEpochSeconds, extractMennekesChargingProcesses, firstKey, firstValue, getArrayElement, getArrayLikeElement, getDirectChildByLocalName, getDirectChildrenByLocalName, getElementsByLocalName, getFirstArrayElement, getInt16Bytes, getInt32Bytes, getInt64Bytes, getInt8Bytes, getLastArrayElement, getTrimmedTextContent, hashFile, hex2bin, hex32, hexToArrayBuffer, hexToBytes, intFromBytes, isGeoLocation, isICryptoResult, isIFileInfo, isIPublicKeyXY, isISessionCryptoResult1, isISessionCryptoResult2, isJSONLDObject, isMandatoryArrayOfStrings, isMandatoryBoolean, isMandatoryDecimal, isMandatoryJSONArray, isMandatoryJSONObject, isMandatoryNumber, isMandatoryString, isMandatoryURL, isMultilanguageText, isOIDInfo, isObject, isOptionalArrayOfStrings, isOptionalDecimal, isOptionalJSONArray, isOptionalJSONArrayError, isOptionalJSONArrayOk, isOptionalJSONObject, isOptionalNumber, isOptionalString, isOptionalURL, isPCDFText, isString, isStringArray, isStringOrOIDInfo, isStringOrStringArray, jsonPrettyPrinter, measurementName2human, normalizePCDFPublicKeyHex, normalizeXMLText, openFullscreen, pad, parseAndVerifyJSONSignatures, parseDescription, parseHexString, parseMennekesXMLDocument, parseNumber, parseOBIS, parsePCDFDocument, parsePCDFPublicKey, parsePCDFSignature, parseUTC, readQRCodeTextFromImage, readQRCodeTextFromImageData, secp224k1, setUILocale, sha256, sha384, sha512, signJSONMessage, signMessage, stripPCDFControlCharacters, time2human, toArrayBuffer, toSessionVerificationResults, toUint8Array, unquotePCDFText, validatePCDFFields, verifyJSONMessageSignatureResults, verifyJSONMessageSignatures, verifyJSONSignature, verifyJSONSignatureResult, verifyPCDFDocument };
|
|
17724
|
+
export { ACrypt, Alfen, AlfenCrypt01, BSMCrypt01, CanonicalJSONError, ChargeIT, ChargePoint, ChargePointCrypt01, IChargeTransparencyLiveLink_exports as ChargeTransparencyLiveLink, ChargeTransparencyLiveLinkContext, IChargeTransparencyRecord_exports as ChargeTransparencyRecord, Chargy, chargyInterfaces_exports as ChargyInterfaces, Clone, CloneCTR, ConcatenateBuffers, CreateDiv, CreateDiv2, CreateError, CryptoAlgorithms, CryptoHashAlgorithms, DayOfWeek, DisplayPrefixes, EMHCrypt01, ErrorLevel, GDFCrypt01, IECCurves, IEncoding, InformationRelevance, InformationRelevanceToString, IsAChargeTransparencyLiveLink, IsAChargeTransparencyRecord, IsAPublicKey, IsAPublicKeyLookup, IsAPublicKeySignature, IsAPublicKeyXY, IsASessionCryptoResult, IsNullOrEmpty, JSONSignatureVerificationStatus, MENNEKES_EDL40_OBIS, MENNEKES_EDL40_XMLNS, Mennekes, MennekesCrypt01, OBIS2Hex, OBIS2MeasurementName, OBIS_RegExpr, OCMF, OCMFTransactionTypes, OCMFv1_x, OCPI, OIDInfo, PCDF, PCDFCrypt01, PCDFParseError, PCDFValidationError, PCDF_FIELD_ORDER, PCDF_PREFIX, ParseJSON_LD, PublicKeyFormats, IPublicKeyInfo_exports as PublicKeyInfo, SAFEXML, SessionVerificationResult, SetHex, SetInt8, SetText, SetText_withLength, SetTimestamp, SetTimestamp32, SetUInt32, SetUInt32_withCode, SetUInt64, SetUInt64D, SignMessage, SignatureFormats, TimeStatusTypes, UTC2human, VerificationResult, VerifyJSONMessageSignatures, WarningLevel, WhenNullOrEmpty, XMLContainer, asJSONArray, asJSONObject, asNumber, asString, base64ToBytes, buf2hex, buildMennekesSignatureData, bytesToBase64, bytesToHex, canonicalJSONBytes, canonicalJSONStringify, cleanHex, closeFullscreen, createHexString, dateToMennekesLocalEpochSeconds, extractMennekesChargingProcesses, firstKey, firstValue, getArrayElement, getArrayLikeElement, getDirectChildByLocalName, getDirectChildrenByLocalName, getElementsByLocalName, getFirstArrayElement, getInt16Bytes, getInt32Bytes, getInt64Bytes, getInt8Bytes, getLastArrayElement, getTrimmedTextContent, hashFile, hex2bin, hex32, hexToArrayBuffer, hexToBytes, intFromBytes, isEncodedValue, isGeoLocation, isI18NString, isICryptoResult, isIFileInfo, isISessionCryptoResult1, isISessionCryptoResult2, isJSONLDObject, isMandatoryArrayOfStrings, isMandatoryBoolean, isMandatoryDecimal, isMandatoryJSONArray, isMandatoryJSONObject, isMandatoryNumber, isMandatoryString, isMandatoryURL, isOIDInfo, isObject, isOptionalArrayOfStrings, isOptionalDecimal, isOptionalJSONArray, isOptionalJSONArrayError, isOptionalJSONArrayOk, isOptionalJSONObject, isOptionalNumber, isOptionalString, isOptionalStringArray, isOptionalStringOrOIDInfo, isOptionalURL, isPCDFText, isPublicKeySubject, isString, isStringArray, isStringOrOIDInfo, isStringOrStringArray, jsonPrettyPrinter, measurementName2human, normalizePCDFPublicKeyHex, normalizeXMLText, openFullscreen, pad, parseAndVerifyJSONSignatures, parseDescription, parseHexString, parseMennekesXMLDocument, parseNumber, parseOBIS, parsePCDFDocument, parsePCDFPublicKey, parsePCDFSignature, parseUTC, readQRCodeTextFromImage, readQRCodeTextFromImageData, secp224k1, setUILocale, sha256, sha256____, sha384, sha384____, sha512, sha512____, signJSONMessage, signMessage, stripPCDFControlCharacters, time2human, toArrayBuffer, toSessionVerificationResults, toUint8Array, unquotePCDFText, validatePCDFFields, verifyJSONMessageSignatureResults, verifyJSONMessageSignatures, verifyJSONSignature, verifyJSONSignatureResult, verifyPCDFDocument };
|
|
17505
17725
|
//# sourceMappingURL=index.js.map
|
|
17506
17726
|
//# sourceMappingURL=index.js.map
|