@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 CHANGED
@@ -1,102 +1,122 @@
1
- # Chargy Core
2
-
3
- The ChargyCore TypeScript library shared between Chargy Desktop, Web & Mobile applications.
4
-
5
- The package is published as modern ESM and ships generated TypeScript declarations.
6
-
7
-
8
- ## Usage
9
-
10
- ```ts
11
- import { Chargy } from "@open-charging-cloud/chargy-core";
12
- ```
13
-
14
-
15
- ## Runtime Architecture
16
-
17
- 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.
18
-
19
- For that reason the package ships two JavaScript builds behind one public import:
20
-
21
- ```text
22
- dist/browser/index.js
23
- dist/node/index.js
24
- ```
25
-
26
- 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`.
27
-
28
- 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.
29
-
30
- Keeping these paths separate has several advantages:
31
-
32
- - Browser bundles do not include the Node/legacy PDF.js path as an unused lazy chunk.
33
- - Node tests and CLI-style usage do not depend on browser-only PDF.js behavior.
34
- - Chargy apps do not need local Webpack aliases or test polyfills for ChargyCore internals.
35
- - Bundle checks can verify that the browser build only references browser PDF.js imports and the Node build only references legacy PDF.js imports.
36
-
37
- 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.
38
-
39
-
40
- ## Development
41
-
42
- ```bash
43
- npm install
44
- npm run typecheck
45
- npm run lint
46
- npm run build
47
- npm run test:node
48
- npm run test:bundle
49
- npm run test:browser
50
- npm test
51
- npm run verify
52
- ```
53
-
54
- The build emits the package into `dist/`.
55
-
56
-
57
- ### Expected Test Flow
58
-
59
- For code changes, use the full verification flow before publishing or handing a package to the Chargy apps:
60
-
61
- ```bash
62
- npm run verify
63
- ```
64
-
65
- `verify` runs the following checks:
66
-
67
- - `npm run typecheck`: validates the TypeScript sources and test/config TypeScript files.
68
- - `npm run lint`: runs the strict type-aware ESLint setup. Existing migration findings are warnings, new unused variables are errors.
69
- - `npm test`: runs all runtime checks:
70
- - `npm run test:node`: runs the Chargy fixture tests in Vitest's Node environment and uses the Node PDF.js adapter.
71
- - `npm run build`: creates both package builds.
72
- - `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.
73
- - `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.
74
- - `npm run build`: recreates the final publishable `dist/` output.
75
-
76
- 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:
77
-
78
- ```bash
79
- npx playwright install chromium
80
- ```
81
-
82
-
83
- ```bash
84
- npm version 0.4.0 --no-git-tag-version
85
- npm run verify
86
- npm pack --dry-run
87
- npm pack
88
- npm login
89
- npm whoami
90
- npm publish
91
- ```
92
-
93
-
94
- ## Funding
95
-
96
- 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/).
97
-
98
- 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.
99
-
100
- <center>
101
- <img src="images/NGI0_tag.svg" height="30">
102
- </center>
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>
@@ -1 +1 @@
1
- {"version":3,"file":"BSMCrypt01.d.ts","sourceRoot":"","sources":["../src/BSMCrypt01.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,MAAM,EAAE,MAA0B,UAAU,CAAA;AACrD,OAAO,EAAE,MAAM,EAAE,MAA0B,UAAU,CAAA;AACrD,OAAO,KAAK,gBAAgB,MAAe,+BAA+B,CAAA;AAC1E,OAAO,KAAK,wBAAwB,MAAO,wCAAwC,CAAA;AAWnF,MAAM,WAAW,oBAAqB,SAAQ,wBAAwB,CAAC,iBAAiB;IAGpF,GAAG,EAAyB,MAAM,CAAC;IAEnC,GAAG,EAAyB,MAAM,CAAC;IACnC,MAAM,EAAsB,MAAM,CAAC;IACnC,QAAQ,EAAoB,MAAM,CAAC;IACnC,UAAU,EAAkB,gBAAgB,CAAC,eAAe,CAAC;IAC7D,aAAa,EAAe,MAAM,CAAC;IAEnC,QAAQ,EAAoB,MAAM,CAAC;IACnC,WAAW,EAAiB,MAAM,CAAC;IACnC,aAAa,EAAe,MAAM,CAAC;IACnC,eAAe,EAAa,gBAAgB,CAAC,eAAe,CAAC;IAC7D,kBAAkB,EAAU,MAAM,CAAC;IAEnC,CAAC,EAA2B,MAAM,CAAC;IACnC,IAAI,EAAwB,MAAM,CAAC;IACnC,MAAM,EAAsB,MAAM,CAAC;IACnC,QAAQ,EAAoB,gBAAgB,CAAC,eAAe,CAAC;IAC7D,WAAW,EAAiB,MAAM,CAAC;IAEnC,GAAG,EAAyB,MAAM,CAAC;IACnC,IAAI,EAAwB,MAAM,CAAC;IACnC,EAAE,EAA0B,MAAM,CAAC;IACnC,KAAK,EAAuB,MAAM,CAAC;IACnC,GAAG,EAAyB,MAAM,CAAC;IACnC,WAAW,EAAiB,MAAM,CAAC;IACnC,UAAU,EAAkB,MAAM,CAAC;IACnC,EAAE,EAA0B,MAAM,CAAC;IACnC,EAAE,EAA0B,MAAM,CAAC;IACnC,KAAK,EAAuB,MAAM,CAAC;IACnC,KAAK,EAAuB,MAAM,CAAC;IACnC,KAAK,EAAuB,MAAM,CAAC;IACnC,GAAG,EAAyB,MAAM,CAAA;CAErC;AAiDD,MAAM,WAAW,iBAAkB,SAAQ,gBAAgB,CAAC,aAAa;IAErE,WAAW,CAAC,EAAmB,MAAM,CAAC;IACtC,OAAO,CAAC,EAAuB,MAAM,CAAC;IACtC,KAAK,CAAC,EAAyB,gBAAgB,CAAC,MAAM,CAAC;IACvD,SAAS,CAAC,EAAqB,MAAM,CAAC;IAEtC,SAAS,EAAsB,MAAM,CAAC;IACtC,GAAG,EAA4B,MAAM,CAAC;IACtC,GAAG,EAA4B,MAAM,CAAC;IACtC,QAAQ,EAAuB,MAAM,CAAC;IACtC,CAAC,EAA8B,MAAM,CAAC;IACtC,GAAG,EAA4B,MAAM,CAAC;IACtC,IAAI,EAA2B,MAAM,CAAC;IACtC,EAAE,EAA6B,MAAM,CAAC;IACtC,KAAK,EAA0B,MAAM,CAAC;IACtC,GAAG,EAA4B,MAAM,CAAC;IACtC,WAAW,EAAoB,MAAM,CAAC;IACtC,UAAU,EAAqB,MAAM,CAAC;IACtC,EAAE,EAA6B,MAAM,CAAC;IACtC,EAAE,EAA6B,MAAM,CAAC;IACtC,KAAK,EAA0B,MAAM,CAAC;IACtC,KAAK,EAA0B,MAAM,CAAC;IACtC,KAAK,EAA0B,MAAM,CAAC;IACtC,GAAG,EAA4B,MAAM,CAAC;IActC,SAAS,CAAC,EAAqB,MAAM,CAAC;IACtC,eAAe,CAAC,EAAe,MAAM,CAAC;IACtC,mBAAmB,CAAC,EAAW,KAAK,CAAC,OAAO,CAAC,CAAC;IAC9C,SAAS,CAAC,EAAqB,gBAAgB,CAAC,YAAY,CAAA;CAC/D;AAGD,qBAAa,UAAW,SAAQ,MAAM;IAElC,QAAQ,CAAC,KAAK,mCAAuC;gBAEzC,MAAM,EAAE,MAAM;IAMnB,+BAA+B,CAAC,GAAG,EAAoB,wBAAwB,CAAC,yBAAyB,EACzE,cAAc,EAAS,MAAM,EAC7B,oBAAoB,EAAG,MAAM,GAAC,IAAI,EAClC,YAAY,EAAW,KAAK,CAAC,OAAO,CAAC,GAEtE,wBAAwB,CAAC,yBAAyB,GAClD,gBAAgB,CAAS,oBAAoB;IAk1B7C,qBAAqB,CAAC,eAAe,EAAE,wBAAwB,CAAC,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC,oBAAoB,CAAC;IAiDjI,iBAAiB,CAAC,gBAAgB,EAAE,oBAAoB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAuOrF,eAAe,CAAC,gBAAgB,EAAO,oBAAoB,EAC3C,QAAQ,EAAe,cAAc,EACrC,QAAQ,EAAe,cAAc,EACrC,OAAO,EAAgB,cAAc,EACrC,YAAY,EAAW,cAAc,EACrC,kBAAkB,EAAK,cAAc,EACrC,YAAY,EAAW,cAAc,EACrC,oBAAoB,EAAG,cAAc,EACrC,iBAAiB,EAAM,cAAc,GAAI,OAAO,CAAC,KAAK,GAAG,SAAS,CAAC;IAiNzF,OAAO,CAAC,eAAe;IASvB,OAAO,CAAC,aAAa;IAQd,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAI,MAAM;IAahC,WAAW,CAAC,KAAK,EAAE,MAAM,GAAI,MAAM,EAAE;IA0C5C,OAAO,CAAC,YAAY;CA4CvB"}
1
+ {"version":3,"file":"BSMCrypt01.d.ts","sourceRoot":"","sources":["../src/BSMCrypt01.ts"],"names":[],"mappings":"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"}
@@ -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(this.chargy.GetLocalizedMessage("Inconsistent_ChargingStation_FirmwareVersion"));
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
- return await chargingSession.method.VerifyChargingSession(chargingSession);
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
- return await chargingSession.method.VerifyChargingSession(chargingSession);
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
- return await chargingSession.method.VerifyChargingSession(chargingSession);
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
- return await chargingSession.method.VerifyChargingSession(chargingSession);
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
- return await chargingSession.method.VerifyChargingSession(chargingSession);
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
- return await chargingSession.method.VerifyChargingSession(chargingSession);
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
- return await chargingSession.method.VerifyChargingSession(chargingSession);
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
- return await chargingSession.method.VerifyChargingSession(chargingSession);
19069
+ verificationResult2 = await chargingSession.method.VerifyChargingSession(chargingSession);
19070
+ break;
18953
19071
  default:
18954
- return {
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