@open-charging-cloud/chargy-core 0.4.0 → 0.5.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 +122 -102
- package/dist/BSMCrypt01.d.ts.map +1 -1
- package/dist/browser/index.js +145 -12
- package/dist/browser/index.js.map +1 -1
- package/dist/chargy.d.ts +9 -1
- package/dist/chargy.d.ts.map +1 -1
- package/dist/interfaces/IChargeTransparencyRecord.d.ts +2 -2
- package/dist/interfaces/IChargeTransparencyRecord.d.ts.map +1 -1
- package/dist/interfaces/chargyInterfaces.d.ts +27 -2
- package/dist/interfaces/chargyInterfaces.d.ts.map +1 -1
- package/dist/node/index.js +145 -12
- package/dist/node/index.js.map +1 -1
- package/i18n.json +5 -0
- package/package.json +3 -1
- package/validationRules.json +8 -0
package/README.md
CHANGED
|
@@ -1,102 +1,122 @@
|
|
|
1
|
-
# Chargy Core
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
##
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
npm
|
|
88
|
-
npm
|
|
89
|
-
npm
|
|
90
|
-
npm
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
1
|
+
# Chargy Core
|
|
2
|
+
|
|
3
|
+
Chargy Core is a transparency software library for the validation of secure and transparent e-mobility charging processes, as defined by the *German Calibration Law ("Eichrecht")* in combination with the [Alternative Fuels Infrastructure Regulation (AFIR)](https://transport.ec.europa.eu/transport-themes/clean-transport/alternative-fuels-sustainable-mobility-europe/alternative-fuels-infrastructure_en) and the new [Measuring instruments (MID)](https://single-market-economy.ec.europa.eu/single-market/goods/european-standards/harmonised-standards/measuring-instruments-mid_en) of the European Commission and the [European Digital Quality Infrastructure](https://www.qi-digital.de/en/). The software allows you to verify the cryptographic signatures of energy measurements within charge detail records and comes with a couple of useful extentions to simplify the entire process for endusers and operators.
|
|
4
|
+
|
|
5
|
+
This software is written as a modern ESM TypeScript package with generated declaration files, providing shared core functionality for the Chargy Desktop, Web & Mobile applications.
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
## Benefits of Chargy
|
|
9
|
+
|
|
10
|
+
1. Chargy comes with __*meta data*__. True charging transparency is more than just signed smart meter values. Chargy allows you to group multiple signed smart meter values to entire charging sessions and to add additional meta data like EVSE information, geo coordinates, tariffs, ... within your backend in order to improve the user experience for the ev drivers.
|
|
11
|
+
2. Chargy is __*secure*__. Chargy implements a public key infrastructure for managing certificates of smart meters, EVSEs, charging stations, charging station operators and e-mobility providers. By this the ev driver will always retrieve the correct public key to verify a charging process automatically and without complicated manual lookups in external databases.
|
|
12
|
+
3. Chargy is __*Open Source*__. In contrast to other vendors in e-mobility, we belief that true transparency is only trustworthy if the entire process and the required software is open and reusable under a fair copyleft license (AGPL).
|
|
13
|
+
4. Chargy is __*open for your contributions*__. We currently support adapters for the protocols of different charging station vendors like chargeIT mobility, ABL (OCMF), chargepoint. The certification at the Physikalisch-Technische Bundesanstalt (PTB) is provided by chargeIT mobility. If you want to add your protocol or a protocol adapter feel free to read the contributor license agreement and to send us a pull request.
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
## Supported Charge Transparency Data Formats
|
|
17
|
+
|
|
18
|
+
- Alfen
|
|
19
|
+
- Bauer energy meters
|
|
20
|
+
- EMH energy meters
|
|
21
|
+
- Mennekes XML
|
|
22
|
+
- OCMF v1.1 - v1.4
|
|
23
|
+
- Porsche
|
|
24
|
+
- chargeIT (2 versions)
|
|
25
|
+
- chargepoint
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
## Usage
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
import { Chargy } from "@open-charging-cloud/chargy-core";
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
## Runtime Architecture
|
|
36
|
+
|
|
37
|
+
ChargyCore is consumed in different JavaScript runtimes. The browser-based Chargy WebApp and Electron renderer processes have Web APIs such as `DOMParser`, `Blob`, `TextEncoder`, `ImageData`, `DOMMatrix`, `Path2D`, and browser worker loading semantics. Node.js-based tests, command line tools, server-side verification, and build-time checks do not provide the same environment.
|
|
38
|
+
|
|
39
|
+
For that reason the package ships two JavaScript builds behind one public import:
|
|
40
|
+
|
|
41
|
+
```text
|
|
42
|
+
dist/browser/index.js
|
|
43
|
+
dist/node/index.js
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
The runtime-specific file is selected through conditional package exports in `package.json`. Browser bundlers should resolve the `browser` condition and receive `dist/browser/index.js`. Node.js resolves the `node` condition and receives `dist/node/index.js`.
|
|
47
|
+
|
|
48
|
+
This split is especially important for PDF.js. Browser contexts should use the normal `pdfjs-dist` build, because the browser already provides the canvas and DOM APIs PDF.js expects. Node.js should use `pdfjs-dist/legacy/build/pdf.mjs`, because the legacy build contains Node-oriented setup for the missing canvas-related globals and avoids the modern browser-only assumptions.
|
|
49
|
+
|
|
50
|
+
Keeping these paths separate has several advantages:
|
|
51
|
+
|
|
52
|
+
- Browser bundles do not include the Node/legacy PDF.js path as an unused lazy chunk.
|
|
53
|
+
- Node tests and CLI-style usage do not depend on browser-only PDF.js behavior.
|
|
54
|
+
- Chargy apps do not need local Webpack aliases or test polyfills for ChargyCore internals.
|
|
55
|
+
- Bundle checks can verify that the browser build only references browser PDF.js imports and the Node build only references legacy PDF.js imports.
|
|
56
|
+
|
|
57
|
+
When adding runtime-sensitive dependencies, avoid branching on runtime inside shared source code if that would make bundlers see both implementations. Prefer a small adapter under `src/` and let the build or conditional exports select the runtime-specific implementation.
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
## Development
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
npm install
|
|
64
|
+
npm run typecheck
|
|
65
|
+
npm run lint
|
|
66
|
+
npm run build
|
|
67
|
+
npm run test:node
|
|
68
|
+
npm run test:bundle
|
|
69
|
+
npm run test:browser
|
|
70
|
+
npm test
|
|
71
|
+
npm run verify
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
The build emits the package into `dist/`.
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
### Expected Test Flow
|
|
78
|
+
|
|
79
|
+
For code changes, use the full verification flow before publishing or handing a package to the Chargy apps:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
npm run verify
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
`verify` runs the following checks:
|
|
86
|
+
|
|
87
|
+
- `npm run typecheck`: validates the TypeScript sources and test/config TypeScript files.
|
|
88
|
+
- `npm run lint`: runs the strict type-aware ESLint setup. Existing migration findings are warnings, new unused variables are errors.
|
|
89
|
+
- `npm test`: runs all runtime checks:
|
|
90
|
+
- `npm run test:node`: runs the Chargy fixture tests in Vitest's Node environment and uses the Node PDF.js adapter.
|
|
91
|
+
- `npm run build`: creates both package builds.
|
|
92
|
+
- `npm run test:bundle`: checks the generated bundles so the browser build only references the browser PDF.js path and the Node build only references the legacy PDF.js path.
|
|
93
|
+
- `npm run test:browser`: imports `dist/browser/index.js` in headless Chromium via Vitest Browser Mode and verifies the public browser entry can be loaded and instantiated.
|
|
94
|
+
- `npm run build`: recreates the final publishable `dist/` output.
|
|
95
|
+
|
|
96
|
+
For dependency, build, export, PDF.js, or browser-facing changes, run the individual steps while iterating and finish with `npm run verify`. The browser test requires Playwright's Chromium browser; if it is missing locally, run:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
npx playwright install chromium
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
npm version 0.5.0 --no-git-tag-version
|
|
105
|
+
npm run verify
|
|
106
|
+
npm pack --dry-run
|
|
107
|
+
npm pack
|
|
108
|
+
npm login
|
|
109
|
+
npm whoami
|
|
110
|
+
npm publish
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
## Funding
|
|
115
|
+
|
|
116
|
+
This Open Source project is partially funded by the [NGI Zero Commons Fund](https://nlnet.nl/commonsfund/) as part of our [EVQI project](https://nlnet.nl/project/EVQI/).
|
|
117
|
+
|
|
118
|
+
We also appreciate any additional funding and long-term support for the Chargy family, for example via [GitHub Sponsors](https://github.com/sponsors/GraphDefined), as it helps us keep the project sustainable, independent and useful for the entire e-mobility community.
|
|
119
|
+
|
|
120
|
+
<center>
|
|
121
|
+
<img src="images/NGI0_tag.svg" height="30">
|
|
122
|
+
</center>
|
package/dist/BSMCrypt01.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BSMCrypt01.d.ts","sourceRoot":"","sources":["../src/BSMCrypt01.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"BSMCrypt01.d.ts","sourceRoot":"","sources":["../src/BSMCrypt01.ts"],"names":[],"mappings":"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"}
|
package/dist/browser/index.js
CHANGED
|
@@ -9884,6 +9884,7 @@ __export(chargyInterfaces_exports, {
|
|
|
9884
9884
|
SessionVerificationResult: () => SessionVerificationResult,
|
|
9885
9885
|
SignatureFormats: () => SignatureFormats,
|
|
9886
9886
|
VerificationResult: () => VerificationResult,
|
|
9887
|
+
WarningLevel: () => WarningLevel,
|
|
9887
9888
|
isGeoLocation: () => isGeoLocation,
|
|
9888
9889
|
isICryptoResult: () => isICryptoResult,
|
|
9889
9890
|
isIFileInfo: () => isIFileInfo,
|
|
@@ -9973,6 +9974,12 @@ var DisplayPrefixes = /* @__PURE__ */ ((DisplayPrefixes2) => {
|
|
|
9973
9974
|
DisplayPrefixes2[DisplayPrefixes2["GIGA"] = 3] = "GIGA";
|
|
9974
9975
|
return DisplayPrefixes2;
|
|
9975
9976
|
})(DisplayPrefixes || {});
|
|
9977
|
+
var WarningLevel = /* @__PURE__ */ ((WarningLevel2) => {
|
|
9978
|
+
WarningLevel2["low"] = "low";
|
|
9979
|
+
WarningLevel2["medium"] = "medium";
|
|
9980
|
+
WarningLevel2["high"] = "high";
|
|
9981
|
+
return WarningLevel2;
|
|
9982
|
+
})(WarningLevel || {});
|
|
9976
9983
|
function isISessionCryptoResult1(obj) {
|
|
9977
9984
|
return typeof obj === "object" && obj !== null && obj.status !== void 0;
|
|
9978
9985
|
}
|
|
@@ -10004,6 +10011,7 @@ var SessionVerificationResult = /* @__PURE__ */ ((SessionVerificationResult2) =>
|
|
|
10004
10011
|
SessionVerificationResult2["InvalidStopValue"] = "InvalidStopValue";
|
|
10005
10012
|
SessionVerificationResult2["EnergyMeterNotFound"] = "EnergyMeterNotFound";
|
|
10006
10013
|
SessionVerificationResult2["InvalidMeasurement"] = "InvalidMeasurement";
|
|
10014
|
+
SessionVerificationResult2["InplausibleMeasurement"] = "InplausibleMeasurement";
|
|
10007
10015
|
SessionVerificationResult2["PublicKeyNotFound"] = "PublicKeyNotFound";
|
|
10008
10016
|
SessionVerificationResult2["UnknownPublicKeyFormat"] = "UnknownPublicKeyFormat";
|
|
10009
10017
|
SessionVerificationResult2["InvalidPublicKey"] = "InvalidPublicKey";
|
|
@@ -11630,7 +11638,10 @@ var BSMCrypt01 = class extends ACrypt {
|
|
|
11630
11638
|
if (previousCscSwVersion !== null && previousCscSwVersion !== csc_sw_version)
|
|
11631
11639
|
currentErrors.push(this.chargy.GetLocalizedMessage("Inconsistent_ChargingStation_FirmwareVersion"));
|
|
11632
11640
|
if (ExpectedCscSwVersion !== null && ExpectedCscSwVersion !== csc_sw_version)
|
|
11633
|
-
currentWarnings.push(
|
|
11641
|
+
currentWarnings.push({
|
|
11642
|
+
level: "medium" /* medium */,
|
|
11643
|
+
message: this.chargy.GetLocalizedMessage("Inconsistent_ChargingStation_FirmwareVersion")
|
|
11644
|
+
});
|
|
11634
11645
|
previousCscSwVersion = csc_sw_version;
|
|
11635
11646
|
}
|
|
11636
11647
|
for (const additionalValue of additionalValues) {
|
|
@@ -17869,6 +17880,16 @@ async function importPdfJs() {
|
|
|
17869
17880
|
pdfjsLib.GlobalWorkerOptions.workerSrc = pdfWorkerSrc.default;
|
|
17870
17881
|
return pdfjsLib;
|
|
17871
17882
|
}
|
|
17883
|
+
|
|
17884
|
+
// validationRules.json
|
|
17885
|
+
var validationRules_default = {
|
|
17886
|
+
chargingSession: {
|
|
17887
|
+
totalEnergy: {
|
|
17888
|
+
rule: [">", "500", "kWh"],
|
|
17889
|
+
level: "low"
|
|
17890
|
+
}
|
|
17891
|
+
}
|
|
17892
|
+
};
|
|
17872
17893
|
var Chargy = class {
|
|
17873
17894
|
//#region Data
|
|
17874
17895
|
i18n;
|
|
@@ -17878,6 +17899,7 @@ var Chargy = class {
|
|
|
17878
17899
|
asn1;
|
|
17879
17900
|
base32Decode;
|
|
17880
17901
|
showPKIDetails;
|
|
17902
|
+
validationRules;
|
|
17881
17903
|
chargingStationOperators = new Array();
|
|
17882
17904
|
chargingPools = new Array();
|
|
17883
17905
|
chargingStations = new Array();
|
|
@@ -17889,7 +17911,7 @@ var Chargy = class {
|
|
|
17889
17911
|
currentCTR = {};
|
|
17890
17912
|
internalCTR = {};
|
|
17891
17913
|
//#endregion
|
|
17892
|
-
constructor(i18n, UILanguage, elliptic, moment2, asn1, base32Decode, ShowPKIDetails) {
|
|
17914
|
+
constructor(i18n, UILanguage, elliptic, moment2, asn1, base32Decode, ShowPKIDetails, validationRules = validationRules_default) {
|
|
17893
17915
|
this.i18n = i18n;
|
|
17894
17916
|
this.UILanguage = UILanguage;
|
|
17895
17917
|
this.elliptic = elliptic;
|
|
@@ -17897,6 +17919,7 @@ var Chargy = class {
|
|
|
17897
17919
|
this.asn1 = asn1;
|
|
17898
17920
|
this.base32Decode = base32Decode;
|
|
17899
17921
|
this.showPKIDetails = ShowPKIDetails;
|
|
17922
|
+
this.validationRules = validationRules;
|
|
17900
17923
|
}
|
|
17901
17924
|
SetUILanguage(UILanguage) {
|
|
17902
17925
|
this.UILanguage = UILanguage;
|
|
@@ -18923,40 +18946,150 @@ var Chargy = class {
|
|
|
18923
18946
|
}
|
|
18924
18947
|
}
|
|
18925
18948
|
//#endregion
|
|
18949
|
+
//#region (private) hasInplausibleChargingSessionTotalEnergyMeasurement(chargingSession)
|
|
18950
|
+
hasInplausibleChargingSessionTotalEnergyMeasurement(chargingSession) {
|
|
18951
|
+
for (const measurement of chargingSession.measurements) {
|
|
18952
|
+
if (measurement.name !== "ENERGY_TOTAL" || measurement.values.length < 2) {
|
|
18953
|
+
continue;
|
|
18954
|
+
}
|
|
18955
|
+
const firstValue2 = measurement.values[0];
|
|
18956
|
+
const lastValue = measurement.values[measurement.values.length - 1];
|
|
18957
|
+
if (firstValue2 == null || lastValue == null) {
|
|
18958
|
+
continue;
|
|
18959
|
+
}
|
|
18960
|
+
const firstValueKWh = this.measurementValueInKWh(measurement, firstValue2);
|
|
18961
|
+
const lastValueKWh = this.measurementValueInKWh(measurement, lastValue);
|
|
18962
|
+
if (firstValueKWh == null || lastValueKWh == null) {
|
|
18963
|
+
continue;
|
|
18964
|
+
}
|
|
18965
|
+
if (this.isInplausibleChargingSessionTotalEnergy(lastValueKWh - firstValueKWh))
|
|
18966
|
+
return true;
|
|
18967
|
+
}
|
|
18968
|
+
return false;
|
|
18969
|
+
}
|
|
18970
|
+
isInplausibleChargingSessionTotalEnergy(totalEnergyKWh) {
|
|
18971
|
+
const totalEnergyRule = this.validationRules.chargingSession?.totalEnergy?.rule;
|
|
18972
|
+
if (totalEnergyRule == null)
|
|
18973
|
+
return false;
|
|
18974
|
+
const [operator, thresholdValue, thresholdUnit] = totalEnergyRule;
|
|
18975
|
+
const thresholdKWh = this.energyValueInKWh(thresholdValue, thresholdUnit);
|
|
18976
|
+
if (thresholdKWh == null)
|
|
18977
|
+
return false;
|
|
18978
|
+
switch (operator) {
|
|
18979
|
+
case ">":
|
|
18980
|
+
return totalEnergyKWh > thresholdKWh;
|
|
18981
|
+
case ">=":
|
|
18982
|
+
return totalEnergyKWh >= thresholdKWh;
|
|
18983
|
+
case "<":
|
|
18984
|
+
return totalEnergyKWh < thresholdKWh;
|
|
18985
|
+
case "<=":
|
|
18986
|
+
return totalEnergyKWh <= thresholdKWh;
|
|
18987
|
+
case "=":
|
|
18988
|
+
case "==":
|
|
18989
|
+
return totalEnergyKWh === thresholdKWh;
|
|
18990
|
+
default:
|
|
18991
|
+
return false;
|
|
18992
|
+
}
|
|
18993
|
+
}
|
|
18994
|
+
energyValueInKWh(value, unit) {
|
|
18995
|
+
const numericValue = typeof value === "number" ? value : Number.parseFloat(value);
|
|
18996
|
+
if (!Number.isFinite(numericValue))
|
|
18997
|
+
return void 0;
|
|
18998
|
+
switch (unit.trim().toLowerCase()) {
|
|
18999
|
+
case "wh":
|
|
19000
|
+
return numericValue / 1e3;
|
|
19001
|
+
case "kwh":
|
|
19002
|
+
return numericValue;
|
|
19003
|
+
case "mwh":
|
|
19004
|
+
return numericValue * 1e3;
|
|
19005
|
+
default:
|
|
19006
|
+
return void 0;
|
|
19007
|
+
}
|
|
19008
|
+
}
|
|
19009
|
+
measurementValueInKWh(measurement, measurementValue) {
|
|
19010
|
+
const value = measurementValue.value.toNumber();
|
|
19011
|
+
if (!Number.isFinite(value))
|
|
19012
|
+
return void 0;
|
|
19013
|
+
const unit = measurement.unit?.trim().toLowerCase();
|
|
19014
|
+
if (unit === "kwh")
|
|
19015
|
+
return value;
|
|
19016
|
+
if (unit === "wh" || measurement.unitEncoded === 30) {
|
|
19017
|
+
return value / 1e3;
|
|
19018
|
+
}
|
|
19019
|
+
return void 0;
|
|
19020
|
+
}
|
|
19021
|
+
getChargingSessionTotalEnergyWarningLevel() {
|
|
19022
|
+
return this.validationRules.chargingSession?.totalEnergy?.level ?? "low" /* low */;
|
|
19023
|
+
}
|
|
19024
|
+
addChargeTransparencyRecordWarning(CTR, warning) {
|
|
19025
|
+
if (CTR == null)
|
|
19026
|
+
return;
|
|
19027
|
+
CTR.warnings ??= [];
|
|
19028
|
+
if (!CTR.warnings.some((existingWarning) => this.isSameWarning(existingWarning, warning)))
|
|
19029
|
+
CTR.warnings.push(warning);
|
|
19030
|
+
}
|
|
19031
|
+
isSameWarning(left, right) {
|
|
19032
|
+
return left.level === right.level && left.message === right.message;
|
|
19033
|
+
}
|
|
19034
|
+
//#endregion
|
|
18926
19035
|
//#region (private) processChargingSession(chargingSession)
|
|
18927
19036
|
async processChargingSession(chargingSession) {
|
|
19037
|
+
let verificationResult2;
|
|
18928
19038
|
switch (chargingSession["@context"]) {
|
|
18929
19039
|
case "https://open.charging.cloud/contexts/SessionSignatureFormats/GDFCrypt01+json":
|
|
18930
19040
|
chargingSession.method = new GDFCrypt01(this);
|
|
18931
|
-
|
|
19041
|
+
verificationResult2 = await chargingSession.method.VerifyChargingSession(chargingSession);
|
|
19042
|
+
break;
|
|
18932
19043
|
case "https://open.charging.cloud/contexts/SessionSignatureFormats/EMHCrypt01+json":
|
|
18933
19044
|
chargingSession.method = new EMHCrypt01(this);
|
|
18934
|
-
|
|
19045
|
+
verificationResult2 = await chargingSession.method.VerifyChargingSession(chargingSession);
|
|
19046
|
+
break;
|
|
18935
19047
|
case "https://open.charging.cloud/contexts/SessionSignatureFormats/OCMFv1.0+json":
|
|
18936
19048
|
chargingSession.method = new OCMFv1_x(this);
|
|
18937
|
-
|
|
19049
|
+
verificationResult2 = await chargingSession.method.VerifyChargingSession(chargingSession);
|
|
19050
|
+
break;
|
|
18938
19051
|
case "https://open.charging.cloud/contexts/SessionSignatureFormats/ChargePointCrypt01+json":
|
|
18939
19052
|
chargingSession.method = new ChargePointCrypt01(this);
|
|
18940
|
-
|
|
19053
|
+
verificationResult2 = await chargingSession.method.VerifyChargingSession(chargingSession);
|
|
19054
|
+
break;
|
|
18941
19055
|
case "https://open.charging.cloud/contexts/SessionSignatureFormats/AlfenCrypt01+json":
|
|
18942
19056
|
chargingSession.method = new AlfenCrypt01(this);
|
|
18943
|
-
|
|
19057
|
+
verificationResult2 = await chargingSession.method.VerifyChargingSession(chargingSession);
|
|
19058
|
+
break;
|
|
18944
19059
|
case "https://open.charging.cloud/contexts/SessionSignatureFormats/MennekesCrypt01+json":
|
|
18945
19060
|
chargingSession.method = new MennekesCrypt01(this);
|
|
18946
|
-
|
|
19061
|
+
verificationResult2 = await chargingSession.method.VerifyChargingSession(chargingSession);
|
|
19062
|
+
break;
|
|
18947
19063
|
case "https://open.charging.cloud/contexts/SessionSignatureFormats/PCDF+json":
|
|
18948
19064
|
chargingSession.method = new PCDFCrypt01(this);
|
|
18949
|
-
|
|
19065
|
+
verificationResult2 = await chargingSession.method.VerifyChargingSession(chargingSession);
|
|
19066
|
+
break;
|
|
18950
19067
|
case "https://open.charging.cloud/contexts/SessionSignatureFormats/bsm-ws36a-v0+json":
|
|
18951
19068
|
chargingSession.method = new BSMCrypt01(this);
|
|
18952
|
-
|
|
19069
|
+
verificationResult2 = await chargingSession.method.VerifyChargingSession(chargingSession);
|
|
19070
|
+
break;
|
|
18953
19071
|
default:
|
|
18954
|
-
|
|
19072
|
+
verificationResult2 = {
|
|
18955
19073
|
status: "UnknownSessionFormat" /* UnknownSessionFormat */,
|
|
18956
19074
|
message: this.GetLocalizedMessage("UnknownOrInvalidChargingSessionFormat"),
|
|
18957
19075
|
certainty: 0
|
|
18958
19076
|
};
|
|
19077
|
+
break;
|
|
19078
|
+
}
|
|
19079
|
+
if (verificationResult2.status === "ValidSignature" /* ValidSignature */ && this.hasInplausibleChargingSessionTotalEnergyMeasurement(chargingSession)) {
|
|
19080
|
+
this.addChargeTransparencyRecordWarning(
|
|
19081
|
+
chargingSession.ctr,
|
|
19082
|
+
{
|
|
19083
|
+
level: this.getChargingSessionTotalEnergyWarningLevel(),
|
|
19084
|
+
message: this.GetLocalizedMessage("InplausibleTotalEnergyMeasurementWarning")
|
|
19085
|
+
}
|
|
19086
|
+
);
|
|
19087
|
+
return {
|
|
19088
|
+
...verificationResult2,
|
|
19089
|
+
status: "InplausibleMeasurement" /* InplausibleMeasurement */
|
|
19090
|
+
};
|
|
18959
19091
|
}
|
|
19092
|
+
return verificationResult2;
|
|
18960
19093
|
}
|
|
18961
19094
|
//#endregion
|
|
18962
19095
|
MergeChargeTransparencyRecords(CTRs) {
|
|
@@ -19038,6 +19171,6 @@ buffer/index.js:
|
|
|
19038
19171
|
*)
|
|
19039
19172
|
*/
|
|
19040
19173
|
|
|
19041
|
-
export { ACrypt, Alfen, AlfenCrypt01, BSMCrypt01, CanonicalJSONError, ChargeIT, ChargePoint, ChargePointCrypt01, IChargeTransparencyLiveLink_exports as ChargeTransparencyLiveLink, ChargeTransparencyLiveLinkContext, IChargeTransparencyRecord_exports as ChargeTransparencyRecord, Chargy, chargyInterfaces_exports as ChargyInterfaces, Clone, CloneCTR, ConcatenateBuffers, CreateDiv, CreateDiv2, CryptoAlgorithms, CryptoHashAlgorithms, DayOfWeek, DisplayPrefixes, EMHCrypt01, GDFCrypt01, IECCurves, IEncoding, InformationRelevance, InformationRelevanceToString, IsAChargeTransparencyLiveLink, IsAChargeTransparencyRecord, IsAPublicKeyInfo, IsAPublicKeyLookup, IsASessionCryptoResult, IsNullOrEmpty, JSONSignatureVerificationStatus, MENNEKES_EDL40_OBIS, MENNEKES_EDL40_XMLNS, Mennekes, MennekesCrypt01, OBIS2Hex, OBIS2MeasurementName, OBIS_RegExpr, OCMF, OCMFTransactionTypes, OCMFv1_x, OCPI, PCDF, PCDFCrypt01, PCDFParseError, PCDFValidationError, PCDF_FIELD_ORDER, PCDF_PREFIX, ParseJSON_LD, PublicKeyFormats, IPublicKeyInfo_exports as PublicKeyInfo, SAFEXML, SessionVerificationResult, SetHex, SetInt8, SetText, SetText_withLength, SetTimestamp, SetTimestamp32, SetUInt32, SetUInt32_withCode, SetUInt64, SetUInt64D, SignMessage, SignatureFormats, TimeStatusTypes, UTC2human, VerificationResult, VerifyJSONMessageSignatures, WhenNullOrEmpty, XMLContainer, asJSONArray, asJSONObject, asNumber, asString, buf2hex, buildMennekesSignatureData, bytesToHex2 as bytesToHex, canonicalJSONBytes, canonicalJSONStringify, cleanHex, closeFullscreen, createHexString, dateToMennekesLocalEpochSeconds, extractMennekesChargingProcesses, firstKey, firstValue, getDirectChildByLocalName, getDirectChildrenByLocalName, getElementsByLocalName, getInt16Bytes, getInt32Bytes, getInt64Bytes, getInt8Bytes, getTrimmedTextContent, hashFile, hex2bin, hex32, hexToArrayBuffer, hexToBytes, intFromBytes, isGeoLocation, isICryptoResult, isIFileInfo, isIPublicKeyXY, isISessionCryptoResult1, isISessionCryptoResult2, isJSONLDObject, isMandatoryArrayOfStrings, isMandatoryBoolean, isMandatoryDecimal, isMandatoryJSONArray, isMandatoryJSONObject, isMandatoryNumber, isMandatoryString, isMandatoryURL, isMultilanguageText, isOIDInfo, isObject, isOptionalArrayOfStrings, isOptionalDecimal, isOptionalJSONArray, isOptionalJSONArrayError, isOptionalJSONArrayOk, isOptionalJSONObject, isOptionalNumber, isOptionalString, isOptionalURL, isPCDFText, isString, isStringArray, isStringOrOIDInfo, isStringOrStringArray, jsonPrettyPrinter, measurementName2human, normalizePCDFPublicKeyHex, normalizeXMLText, openFullscreen, pad, parseAndVerifyJSONSignatures, parseDescription, parseHexString, parseMennekesXMLDocument, parseNumber, parseOBIS, parsePCDFDocument, parsePCDFPublicKey, parsePCDFSignature, parseUTC, readQRCodeTextFromImage, readQRCodeTextFromImageData, secp224k1, setUILocale, sha256, sha384, sha512, signJSONMessage, signMessage, stripPCDFControlCharacters, time2human, toArrayBuffer, toSessionVerificationResults, toUint8Array, unquotePCDFText, validatePCDFFields, verifyJSONMessageSignatureResults, verifyJSONMessageSignatures, verifyJSONSignature, verifyJSONSignatureResult, verifyPCDFDocument };
|
|
19174
|
+
export { ACrypt, Alfen, AlfenCrypt01, BSMCrypt01, CanonicalJSONError, ChargeIT, ChargePoint, ChargePointCrypt01, IChargeTransparencyLiveLink_exports as ChargeTransparencyLiveLink, ChargeTransparencyLiveLinkContext, IChargeTransparencyRecord_exports as ChargeTransparencyRecord, Chargy, chargyInterfaces_exports as ChargyInterfaces, Clone, CloneCTR, ConcatenateBuffers, CreateDiv, CreateDiv2, CryptoAlgorithms, CryptoHashAlgorithms, DayOfWeek, DisplayPrefixes, EMHCrypt01, GDFCrypt01, IECCurves, IEncoding, InformationRelevance, InformationRelevanceToString, IsAChargeTransparencyLiveLink, IsAChargeTransparencyRecord, IsAPublicKeyInfo, IsAPublicKeyLookup, IsASessionCryptoResult, IsNullOrEmpty, JSONSignatureVerificationStatus, MENNEKES_EDL40_OBIS, MENNEKES_EDL40_XMLNS, Mennekes, MennekesCrypt01, OBIS2Hex, OBIS2MeasurementName, OBIS_RegExpr, OCMF, OCMFTransactionTypes, OCMFv1_x, OCPI, PCDF, PCDFCrypt01, PCDFParseError, PCDFValidationError, PCDF_FIELD_ORDER, PCDF_PREFIX, ParseJSON_LD, PublicKeyFormats, IPublicKeyInfo_exports as PublicKeyInfo, SAFEXML, SessionVerificationResult, SetHex, SetInt8, SetText, SetText_withLength, SetTimestamp, SetTimestamp32, SetUInt32, SetUInt32_withCode, SetUInt64, SetUInt64D, SignMessage, SignatureFormats, TimeStatusTypes, UTC2human, VerificationResult, VerifyJSONMessageSignatures, WarningLevel, WhenNullOrEmpty, XMLContainer, asJSONArray, asJSONObject, asNumber, asString, buf2hex, buildMennekesSignatureData, bytesToHex2 as bytesToHex, canonicalJSONBytes, canonicalJSONStringify, cleanHex, closeFullscreen, createHexString, dateToMennekesLocalEpochSeconds, extractMennekesChargingProcesses, firstKey, firstValue, getDirectChildByLocalName, getDirectChildrenByLocalName, getElementsByLocalName, getInt16Bytes, getInt32Bytes, getInt64Bytes, getInt8Bytes, getTrimmedTextContent, hashFile, hex2bin, hex32, hexToArrayBuffer, hexToBytes, intFromBytes, isGeoLocation, isICryptoResult, isIFileInfo, isIPublicKeyXY, isISessionCryptoResult1, isISessionCryptoResult2, isJSONLDObject, isMandatoryArrayOfStrings, isMandatoryBoolean, isMandatoryDecimal, isMandatoryJSONArray, isMandatoryJSONObject, isMandatoryNumber, isMandatoryString, isMandatoryURL, isMultilanguageText, isOIDInfo, isObject, isOptionalArrayOfStrings, isOptionalDecimal, isOptionalJSONArray, isOptionalJSONArrayError, isOptionalJSONArrayOk, isOptionalJSONObject, isOptionalNumber, isOptionalString, isOptionalURL, isPCDFText, isString, isStringArray, isStringOrOIDInfo, isStringOrStringArray, jsonPrettyPrinter, measurementName2human, normalizePCDFPublicKeyHex, normalizeXMLText, openFullscreen, pad, parseAndVerifyJSONSignatures, parseDescription, parseHexString, parseMennekesXMLDocument, parseNumber, parseOBIS, parsePCDFDocument, parsePCDFPublicKey, parsePCDFSignature, parseUTC, readQRCodeTextFromImage, readQRCodeTextFromImageData, secp224k1, setUILocale, sha256, sha384, sha512, signJSONMessage, signMessage, stripPCDFControlCharacters, time2human, toArrayBuffer, toSessionVerificationResults, toUint8Array, unquotePCDFText, validatePCDFFields, verifyJSONMessageSignatureResults, verifyJSONMessageSignatures, verifyJSONSignature, verifyJSONSignatureResult, verifyPCDFDocument };
|
|
19042
19175
|
//# sourceMappingURL=index.js.map
|
|
19043
19176
|
//# sourceMappingURL=index.js.map
|