From fa2e3df8105fe1ddf4c110db71da8e27fd7a7317 Mon Sep 17 00:00:00 2001 From: Noe Date: Thu, 5 Jun 2025 11:28:02 +0200 Subject: [PATCH] Add VoltageDifference column in SodistoreMax --- typescript/frontend-marios2/package-lock.json | 558 ++++++++ typescript/frontend-marios2/package.json | 2 + typescript/frontend-marios2/src/App.css | 3 +- .../dashboards/BatteryView/BatteryView.tsx | 123 +- .../DetailedBatteryViewSodistore.tsx | 1169 +++++++++++++++++ .../dashboards/BatteryView/MainStats.tsx | 5 +- .../src/content/dashboards/Log/graph.util.tsx | 107 ++ .../frontend-marios2/src/interfaces/Chart.tsx | 12 +- 8 files changed, 1944 insertions(+), 35 deletions(-) create mode 100644 typescript/frontend-marios2/src/content/dashboards/BatteryView/DetailedBatteryViewSodistore.tsx diff --git a/typescript/frontend-marios2/package-lock.json b/typescript/frontend-marios2/package-lock.json index f8632153f..8658486f9 100644 --- a/typescript/frontend-marios2/package-lock.json +++ b/typescript/frontend-marios2/package-lock.json @@ -37,6 +37,7 @@ "react-cytoscapejs": "^2.0.0", "react-dom": "17.0.2", "react-flow-renderer": "^10.3.17", + "react-gauge-chart": "^0.5.1", "react-helmet-async": "1.3.0", "react-icons": "^4.11.0", "react-icons-converter": "^1.1.4", @@ -7737,6 +7738,51 @@ "resolved": "https://registry.npmjs.org/d3/-/d3-3.5.17.tgz", "integrity": "sha512-yFk/2idb8OHPKkbAL8QaOaqENNoMhIaSHZerk3oQsECwkObkCpJyjYwCe+OHiq6UEdhe1m8ZGARRRO3ljFjlKg==" }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-axis": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", + "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-brush": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", + "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "3", + "d3-transition": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-chord": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", + "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", + "dependencies": { + "d3-path": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/d3-color": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", @@ -7745,6 +7791,28 @@ "node": ">=12" } }, + "node_modules/d3-contour": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz", + "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", + "dependencies": { + "d3-array": "^3.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", + "dependencies": { + "delaunator": "5" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/d3-dispatch": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", @@ -7765,6 +7833,38 @@ "node": ">=12" } }, + "node_modules/d3-dsv": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", + "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", + "dependencies": { + "commander": "7", + "iconv-lite": "0.6", + "rw": "1" + }, + "bin": { + "csv2json": "bin/dsv2json.js", + "csv2tsv": "bin/dsv2dsv.js", + "dsv2dsv": "bin/dsv2dsv.js", + "dsv2json": "bin/dsv2json.js", + "json2csv": "bin/json2dsv.js", + "json2dsv": "bin/json2dsv.js", + "json2tsv": "bin/json2dsv.js", + "tsv2csv": "bin/dsv2dsv.js", + "tsv2json": "bin/dsv2json.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "engines": { + "node": ">= 10" + } + }, "node_modules/d3-ease": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", @@ -7773,6 +7873,57 @@ "node": ">=12" } }, + "node_modules/d3-fetch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", + "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", + "dependencies": { + "d3-dsv": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-force": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", + "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-quadtree": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-geo": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz", + "integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==", + "dependencies": { + "d3-array": "2.5.0 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-hierarchy": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", + "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", + "engines": { + "node": ">=12" + } + }, "node_modules/d3-interpolate": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", @@ -7784,6 +7935,65 @@ "node": ">=12" } }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-polygon": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", + "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-quadtree": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", + "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-random": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", + "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale-chromatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", + "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==", + "dependencies": { + "d3-color": "1 - 3", + "d3-interpolate": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/d3-selection": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", @@ -7792,6 +8002,39 @@ "node": ">=12" } }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/d3-timer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", @@ -8022,6 +8265,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delaunator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz", + "integrity": "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==", + "dependencies": { + "robust-predicates": "^3.0.2" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -11005,6 +11256,14 @@ "node": ">= 0.4" } }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "engines": { + "node": ">=12" + } + }, "node_modules/intl-messageformat": { "version": "10.5.14", "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.5.14.tgz", @@ -17037,6 +17296,58 @@ "react-dom": "16 || 17 || 18" } }, + "node_modules/react-gauge-chart": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/react-gauge-chart/-/react-gauge-chart-0.5.1.tgz", + "integrity": "sha512-Kd0pLIfHWOVEWJCz+xAxFfrKzCdOkLHNKR13V+O3h06ocyGT7fWjz2oevMXsPt3bVn1Du2od7gPrjUhqXKdASg==", + "dependencies": { + "d3": "^7.6.1" + }, + "peerDependencies": { + "react": "^16.8.2 || ^17.0 || ^18.x", + "react-dom": "^16.8.2 || ^17.0 || ^18.x" + } + }, + "node_modules/react-gauge-chart/node_modules/d3": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz", + "integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==", + "dependencies": { + "d3-array": "3", + "d3-axis": "3", + "d3-brush": "3", + "d3-chord": "3", + "d3-color": "3", + "d3-contour": "4", + "d3-delaunay": "6", + "d3-dispatch": "3", + "d3-drag": "3", + "d3-dsv": "3", + "d3-ease": "3", + "d3-fetch": "3", + "d3-force": "3", + "d3-format": "3", + "d3-geo": "3", + "d3-hierarchy": "3", + "d3-interpolate": "3", + "d3-path": "3", + "d3-polygon": "3", + "d3-quadtree": "3", + "d3-random": "3", + "d3-scale": "4", + "d3-scale-chromatic": "3", + "d3-selection": "3", + "d3-shape": "3", + "d3-time": "3", + "d3-time-format": "4", + "d3-timer": "3", + "d3-transition": "3", + "d3-zoom": "3" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/react-helmet-async": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-1.3.0.tgz", @@ -17652,6 +17963,11 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/robust-predicates": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", + "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==" + }, "node_modules/rollup": { "version": "2.79.1", "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", @@ -17750,6 +18066,11 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==" + }, "node_modules/rxjs": { "version": "7.8.1", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", @@ -26418,11 +26739,60 @@ "resolved": "https://registry.npmjs.org/d3/-/d3-3.5.17.tgz", "integrity": "sha512-yFk/2idb8OHPKkbAL8QaOaqENNoMhIaSHZerk3oQsECwkObkCpJyjYwCe+OHiq6UEdhe1m8ZGARRRO3ljFjlKg==" }, + "d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "requires": { + "internmap": "1 - 2" + } + }, + "d3-axis": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", + "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==" + }, + "d3-brush": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", + "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", + "requires": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "3", + "d3-transition": "3" + } + }, + "d3-chord": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", + "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", + "requires": { + "d3-path": "1 - 3" + } + }, "d3-color": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==" }, + "d3-contour": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz", + "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", + "requires": { + "d3-array": "^3.2.0" + } + }, + "d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", + "requires": { + "delaunator": "5" + } + }, "d3-dispatch": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", @@ -26437,11 +26807,64 @@ "d3-selection": "3" } }, + "d3-dsv": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", + "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", + "requires": { + "commander": "7", + "iconv-lite": "0.6", + "rw": "1" + }, + "dependencies": { + "commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==" + } + } + }, "d3-ease": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==" }, + "d3-fetch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", + "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", + "requires": { + "d3-dsv": "1 - 3" + } + }, + "d3-force": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", + "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", + "requires": { + "d3-dispatch": "1 - 3", + "d3-quadtree": "1 - 3", + "d3-timer": "1 - 3" + } + }, + "d3-format": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==" + }, + "d3-geo": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz", + "integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==", + "requires": { + "d3-array": "2.5.0 - 3" + } + }, + "d3-hierarchy": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", + "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==" + }, "d3-interpolate": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", @@ -26450,11 +26873,76 @@ "d3-color": "1 - 3" } }, + "d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==" + }, + "d3-polygon": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", + "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==" + }, + "d3-quadtree": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", + "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==" + }, + "d3-random": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", + "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==" + }, + "d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "requires": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + } + }, + "d3-scale-chromatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", + "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==", + "requires": { + "d3-color": "1 - 3", + "d3-interpolate": "1 - 3" + } + }, "d3-selection": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==" }, + "d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "requires": { + "d3-path": "^3.1.0" + } + }, + "d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "requires": { + "d3-array": "2 - 3" + } + }, + "d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "requires": { + "d3-time": "1 - 3" + } + }, "d3-timer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", @@ -26616,6 +27104,14 @@ "object-keys": "^1.1.1" } }, + "delaunator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz", + "integrity": "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==", + "requires": { + "robust-predicates": "^3.0.2" + } + }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -28819,6 +29315,11 @@ "side-channel": "^1.0.4" } }, + "internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==" + }, "intl-messageformat": { "version": "10.5.14", "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.5.14.tgz", @@ -33141,6 +33642,53 @@ "zustand": "^3.7.2" } }, + "react-gauge-chart": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/react-gauge-chart/-/react-gauge-chart-0.5.1.tgz", + "integrity": "sha512-Kd0pLIfHWOVEWJCz+xAxFfrKzCdOkLHNKR13V+O3h06ocyGT7fWjz2oevMXsPt3bVn1Du2od7gPrjUhqXKdASg==", + "requires": { + "d3": "^7.6.1" + }, + "dependencies": { + "d3": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz", + "integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==", + "requires": { + "d3-array": "3", + "d3-axis": "3", + "d3-brush": "3", + "d3-chord": "3", + "d3-color": "3", + "d3-contour": "4", + "d3-delaunay": "6", + "d3-dispatch": "3", + "d3-drag": "3", + "d3-dsv": "3", + "d3-ease": "3", + "d3-fetch": "3", + "d3-force": "3", + "d3-format": "3", + "d3-geo": "3", + "d3-hierarchy": "3", + "d3-interpolate": "3", + "d3-path": "3", + "d3-polygon": "3", + "d3-quadtree": "3", + "d3-random": "3", + "d3-scale": "4", + "d3-scale-chromatic": "3", + "d3-selection": "3", + "d3-shape": "3", + "d3-time": "3", + "d3-time-format": "4", + "d3-timer": "3", + "d3-transition": "3", + "d3-zoom": "3" + } + } + } + }, "react-helmet-async": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-1.3.0.tgz", @@ -33586,6 +34134,11 @@ "glob": "^7.1.3" } }, + "robust-predicates": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", + "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==" + }, "rollup": { "version": "2.79.1", "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", @@ -33653,6 +34206,11 @@ "queue-microtask": "^1.2.2" } }, + "rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==" + }, "rxjs": { "version": "7.8.1", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", diff --git a/typescript/frontend-marios2/package.json b/typescript/frontend-marios2/package.json index fb96cf903..e5a5a5d2f 100644 --- a/typescript/frontend-marios2/package.json +++ b/typescript/frontend-marios2/package.json @@ -16,6 +16,7 @@ "axios": "^1.5.0", "chart.js": "^4.4.0", "clsx": "1.1.1", + "crypto-js": "^4.2.0", "cytoscape": "^3.26.0", "date-fns": "^2.28.0", "dayjs": "^1.11.10", @@ -32,6 +33,7 @@ "react-cytoscapejs": "^2.0.0", "react-dom": "17.0.2", "react-flow-renderer": "^10.3.17", + "react-gauge-chart": "^0.5.1", "react-helmet-async": "1.3.0", "react-icons": "^4.11.0", "react-icons-converter": "^1.1.4", diff --git a/typescript/frontend-marios2/src/App.css b/typescript/frontend-marios2/src/App.css index c385c7151..c31814a6e 100644 --- a/typescript/frontend-marios2/src/App.css +++ b/typescript/frontend-marios2/src/App.css @@ -6,4 +6,5 @@ .apexcharts-toolbar { display: none !important; -} \ No newline at end of file +} + diff --git a/typescript/frontend-marios2/src/content/dashboards/BatteryView/BatteryView.tsx b/typescript/frontend-marios2/src/content/dashboards/BatteryView/BatteryView.tsx index efb2c1a12..6a2f0e44f 100644 --- a/typescript/frontend-marios2/src/content/dashboards/BatteryView/BatteryView.tsx +++ b/typescript/frontend-marios2/src/content/dashboards/BatteryView/BatteryView.tsx @@ -27,6 +27,7 @@ import CircularProgress from '@mui/material/CircularProgress'; import MainStats from './MainStats'; import DetailedBatteryView from './DetailedBatteryView'; import { ProductIdContext } from '../../../contexts/ProductIdContextProvider'; +import DetailedBatteryViewSodistore from './DetailedBatteryViewSodistore'; interface BatteryViewProps { values: JSONRecordData; @@ -175,23 +176,41 @@ function BatteryView(props: BatteryViewProps) { > } /> - {Object.entries(props.values.Battery.Devices).map( - ([BatteryId, battery]) => ( - - } - /> - ) - )} + {product === 0 + ? Object.entries(props.values.Battery.Devices).map( + ([BatteryId, battery]) => ( + + } + /> + ) + ) + : Object.entries(props.values.Battery.Devices).map( + ([BatteryId, battery]) => ( + + } + /> + ) + )} @@ -226,6 +245,9 @@ function BatteryView(props: BatteryViewProps) { ) : ( Max Cell Voltage )} + {product === 3 && ( + Voltage Difference + )} @@ -350,14 +372,21 @@ function BatteryView(props: BatteryViewProps) { : '#32CD32' }; } else { + const avgTemp = + (battery.BatteryDeligreenDataRecord.TemperaturesList + .CellTemperature1 + + battery.BatteryDeligreenDataRecord + .TemperaturesList.CellTemperature2 + + battery.BatteryDeligreenDataRecord + .TemperaturesList.CellTemperature3 + + battery.BatteryDeligreenDataRecord + .TemperaturesList.CellTemperature4) / + 4; return { width: '10%', textAlign: 'center', backgroundColor: - battery.BatteryDeligreenDataRecord - .TemperaturesList.EnvironmentTemperature > 50 || - battery.BatteryDeligreenDataRecord - .TemperaturesList.EnvironmentTemperature < 0 + avgTemp > 50 || avgTemp < 0 ? '#FF033E' : '#32CD32' }; @@ -459,13 +488,13 @@ function BatteryView(props: BatteryViewProps) { <> 3.94 + minVoltage < 2 ? '#FF033E' - : minVoltage < 2 || minVoltage > 3.8 + : minVoltage > 2 && minVoltage < 2.2 ? '#ffbf00' : '#32CD32', color: minVoltage != 0 ? 'black' : 'white' @@ -476,13 +505,13 @@ function BatteryView(props: BatteryViewProps) { 3.94 + maxVoltage > 3.9 ? '#FF033E' - : maxVoltage < 2 || maxVoltage > 3.8 + : maxVoltage < 3.9 && maxVoltage > 3.8 ? '#ffbf00' : '#32CD32', color: maxVoltage != 0 ? 'black' : 'white' @@ -495,6 +524,46 @@ function BatteryView(props: BatteryViewProps) { })()} )} + {product === 3 && ( + <> + {(() => { + const cellVoltagesString = + battery.BatteryDeligreenDataRecord.CellVoltage || + ''; + + const cellVoltagesArray: number[] = cellVoltagesString + .split(',') + .map((v) => parseFloat(v.trim())) + .filter((v) => !isNaN(v)); // Filter invalid numbers + + const minVoltage = Math.min(...cellVoltagesArray); + const maxVoltage = Math.max(...cellVoltagesArray); + + const voltage_diff = maxVoltage - minVoltage; + + return ( + <> + 0.2 + ? '#FF033E' + : voltage_diff > 0.1 && voltage_diff < 0.2 + ? '#ffbf00' + : '#32CD32', + color: voltage_diff != 0 ? 'black' : 'white' + }} + > + {voltage_diff.toFixed(3)} V{' '} + + + ); + })()} + + )} ))} diff --git a/typescript/frontend-marios2/src/content/dashboards/BatteryView/DetailedBatteryViewSodistore.tsx b/typescript/frontend-marios2/src/content/dashboards/BatteryView/DetailedBatteryViewSodistore.tsx new file mode 100644 index 000000000..bcbd57c8a --- /dev/null +++ b/typescript/frontend-marios2/src/content/dashboards/BatteryView/DetailedBatteryViewSodistore.tsx @@ -0,0 +1,1169 @@ +import React, { useEffect, useRef, useState } from 'react'; +import { I_S3Credentials } from '../../../interfaces/S3Types'; +import { + Box, + Card, + Grid, + IconButton, + Paper, + Table, + TableBody, + TableCell, + TableContainer, + TableRow, + Typography +} from '@mui/material'; +import { Device } from '../Log/graph.util'; +import { useNavigate } from 'react-router-dom'; +import ArrowBackIcon from '@mui/icons-material/ArrowBack'; +import GaugeChart from 'react-gauge-chart'; + +interface DetailedBatteryViewSodistoreProps { + batteryId: number; + s3Credentials: I_S3Credentials; + batteryData: Device; + installationId: number; + productNum: number; +} + +function DetailedBatteryViewSodistore( + props: DetailedBatteryViewSodistoreProps +) { + if (props.batteryData === null) { + return null; + } + + const navigate = useNavigate(); + + const handleBatteryViewButton = () => { + navigate(location.pathname.split('/').slice(0, -2).join('/')); + }; + + const batteryStyle = { + borderRadius: '15px', + padding: '10px', + backgroundColor: 'lightgray', + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + height: '150px' + }; + + const batteryStringStyle = { + flex: 1, + border: '1px solid #000', + height: '97%', + width: '30px', + borderRadius: '7px', + backgroundColor: '#bfbfbf' + }; + + const cellVoltagesArray: number[] = + props.batteryData.BatteryDeligreenDataRecord.CellVoltage.split(',') + .map((v) => parseFloat(v.trim())) + .filter((v) => !isNaN(v)); // Filter invalid numbers + + const minVoltage = Math.min(...cellVoltagesArray); + const maxVoltage = Math.max(...cellVoltagesArray); + + const SocGauge = ({ soc }: { soc: number }) => { + const [stableSoc, setStableSoc] = useState(soc); + const isFirstRender = useRef(true); + + useEffect(() => { + // On first render, don't animate — just set + if (isFirstRender.current) { + setStableSoc(soc); + isFirstRender.current = false; + } else { + // Only update if the change is significant enough to justify it + if (Math.abs(soc - stableSoc) > 0.1) { + setStableSoc(soc); + } + } + }, [soc]); + + return ( +
+ +
+
SOC: {stableSoc.toFixed(1)}%
+
+
+ ); + }; + + return ( + <> + + + + + + + + + + + Node {props.batteryId} + + + + + + Battery Information + + + + + + + + Total Battery Voltage + + + {props.batteryData.BatteryDeligreenDataRecord.BusVoltage + + ' V'} + + + + + Charge/Discharge Current + + + {props.batteryData.BatteryDeligreenDataRecord.BusCurrent + + ' A'} + + + + + Residual Capacity + + + {props.batteryData.BatteryDeligreenDataRecord + .ResidualCapacity + ' Ah'} + + + + + + Battery Capacity + + + {props.batteryData.BatteryDeligreenDataRecord + .BatteryCapacity + ' Ah'} + + + + + SoC + + + {props.batteryData.BatteryDeligreenDataRecord.Soc + ' %'} + + + + + Rated Capacity + + + {props.batteryData.BatteryDeligreenDataRecord + .RatedCapacity + ' Ah'} + + + + + + Number of Cycles + + + { + props.batteryData.BatteryDeligreenDataRecord + .NumberOfCycles + } + + + + + + SOH + + + {props.batteryData.BatteryDeligreenDataRecord.Soh + ' %'} + + + + + + Port Voltage + + + + +
+
+
+
+ {/*----------------------------------------------------------------------------------------------------------------------------------*/} + + {/* SOC Card */} + + + SOC + + + + + {/* On-Off State Card */} + {/*----------------------------------------------------------------------------------------------------------------------------------*/} + + + + On-Off State + + + + + + {[ + [ + 'Charge Switch State', + props.batteryData.BatteryDeligreenAlarmRecord.OnOffState + .ChargeSwitchState + ], + [ + 'Discharge Switch State', + props.batteryData.BatteryDeligreenAlarmRecord.OnOffState + .DischargeSwitchState + ], + [ + 'Current Limit Switch State', + props.batteryData.BatteryDeligreenAlarmRecord.OnOffState + .CurrentLimitSwitchStat + ], + [ + 'Heating Switch State', + props.batteryData.BatteryDeligreenAlarmRecord.OnOffState + .HeatingSwitchState + ] + ].map(([label, value]) => ( + + + {label} + + + {value} + + + ))} + +
+
+
+
+ {/*----------------------------------------------------------------------------------------------------------------------------------*/} + + + + + + + + Current + + + {props.batteryData.BatteryDeligreenDataRecord.BusCurrent.toFixed( + 3 + )}{' '} + A + + + + + + + + + 63 + ? '#FF033E' + : '#32CD32', + borderRadius: '10px 0 0 10px', + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center', + textAlign: 'center', + marginBottom: '15px' + }} + > + + Voltage + + + {props.batteryData.BatteryDeligreenDataRecord.TotalBatteryVoltage.toFixed( + 3 + )}{' '} + V + + + + + + + {/*----------------------------------------------------------------------------------------------------------------------------------*/} + + + + + + + + System State + + + {Object.entries( + props.batteryData.BatteryDeligreenAlarmRecord.SystemState + ).find(([_, value]) => value === 'True')?.[0] ?? 'Unknown'} + + + +
+
+
+ {/*----------------------------------------------------------------------------------------------------------------------------------*/} + {/*Temperature List*/} + + + + Battery Temperatures + + + + + + {Object.entries( + props.batteryData.BatteryDeligreenDataRecord + .TemperaturesList || {} + ).map(([label, value]) => ( + + + {label} + + + {value + ' °C'} + + + ))} + +
+
+
+
+ + {/*----------------------------------------------------------------------------------------------------------------------------------*/} + + + + {[0, 1].map((col) => ( + + + {cellVoltagesArray + .slice(col * 8, (col + 1) * 8) + .map((voltage, index) => ( + + + 3.94 + ? '#FF033E' + : voltage < 2 || voltage > 3.8 + ? '#ffbf00' + : '#32CD32', + padding: '8px', + minWidth: '145px', + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + borderRadius: '8px 0 0 8px' + }} + > + + Cell {col * 8 + index + 1 < 10 ? '0' : ''} + {col * 8 + index + 1} + + + {voltage.toFixed(3)} V + + + {/* Battery Cap */} + + + + ))} + + + ))} + + + + {/*Alarm events 1-3 */} + {/*----------------------------------------------------------------------------------------------------------------------------------*/} + + {[1, 2, 3].map((eventNum) => { + const activeAlarms = Object.entries( + props.batteryData.BatteryDeligreenAlarmRecord[ + `AlarmEvent${eventNum}` + ] || {} + ).filter(([_, value]) => value === 'True'); + + return ( + + + + Alarm Event {eventNum} + + + 0 ? 'auto' : 'visible', + width: '100%', + px: 1, + flex: 1 + }} + > + + + + {activeAlarms.length === 0 ? ( + + + No active alarms + + + ) : ( + activeAlarms.map(([label, value]) => ( + + + {label} + + + {value} + + + )) + )} + +
+
+
+
+
+ ); + })} +
+ + {/*Alarm events 4-6 */} + {/*----------------------------------------------------------------------------------------------------------------------------------*/} + + {[4, 5, 6].map((eventNum) => { + const activeAlarms = Object.entries( + props.batteryData.BatteryDeligreenAlarmRecord[ + `AlarmEvent${eventNum}` + ] || {} + ).filter(([_, value]) => value === 'True'); + + return ( + + + + Alarm Event {eventNum} + + + 0 ? 'auto' : 'visible', + width: '100%', + px: 1, + flex: 1 + }} + > + + + + {activeAlarms.length === 0 ? ( + + + No active alarms + + + ) : ( + activeAlarms.map(([label, value]) => ( + + + {label} + + + {value} + + + )) + )} + +
+
+
+
+
+ ); + })} +
+ + {/*Alarm events 7,8, CellsAlarms */} + {/*----------------------------------------------------------------------------------------------------------------------------------*/} + + {[7, 8].map((eventNum) => { + const activeAlarms = Object.entries( + props.batteryData.BatteryDeligreenAlarmRecord[ + `AlarmEvent${eventNum}` + ] || {} + ).filter(([_, value]) => value === 'True'); + + return ( + + + + Alarm Event {eventNum} + + + 0 ? 'auto' : 'visible', + width: '100%', + px: 1, + flex: 1 + }} + > + + + + {activeAlarms.length === 0 ? ( + + + No active alarms + + + ) : ( + activeAlarms.map(([label, value]) => ( + + + {label} + + + {value} + + + )) + )} + +
+
+
+
+
+ ); + })} + + {/* Third Column: CellAlarmList */} + + {(() => { + const cellAlarms = ( + props.batteryData.BatteryDeligreenAlarmRecord.CellAlarmList || '' + ) + .split(',') + .map((item) => item.trim()) + .map((value, index) => ({ + label: `Cell ${index + 1 < 10 ? '0' : ''}${index + 1}`, + value + })) + .filter( + ({ value }) => + value !== 'Normal, no alarm' && value !== 'Normal-no alarm' + ); // handles both formats + + return ( + + + Cell Alarms + + + 0 ? 'auto' : 'visible', + width: '100%', + px: 1, + flex: 1 + }} + > + + + + {cellAlarms.length === 0 ? ( + + + No active alarms + + + ) : ( + cellAlarms.map(({ label, value }) => ( + + + {label} + + + {value} + + + )) + )} + +
+
+
+
+ ); + })()} +
+
+ + {/*CellTemperatureAlarms */} + {/*----------------------------------------------------------------------------------------------------------------------------------*/} + + {/* Third Column: CellAlarmList */} + + {(() => { + const cellTemperatureAlarms = ( + props.batteryData.BatteryDeligreenAlarmRecord + .CellTemperatureAlarm || '' + ) + .split(',') + .map((item) => item.trim()) + .map((value, index) => ({ + label: `Cell ${index + 1 < 10 ? '0' : ''}${index + 1}`, + value + })) + .filter( + ({ value }) => + value !== 'Normal, no alarm' && value !== 'Normal-no alarm' + ); // handles both formats + + return ( + + + Cell Alarms + + + 0 ? 'auto' : 'visible', + width: '100%', + px: 1, + flex: 1 + }} + > + + + + {cellTemperatureAlarms.length === 0 ? ( + + + No active alarms + + + ) : ( + cellTemperatureAlarms.map(({ label, value }) => ( + + + {label} + + + {value} + + + )) + )} + +
+
+
+
+ ); + })()} +
+
+ + ); +} + +export default DetailedBatteryViewSodistore; diff --git a/typescript/frontend-marios2/src/content/dashboards/BatteryView/MainStats.tsx b/typescript/frontend-marios2/src/content/dashboards/BatteryView/MainStats.tsx index 62b0a3302..35be8866e 100644 --- a/typescript/frontend-marios2/src/content/dashboards/BatteryView/MainStats.tsx +++ b/typescript/frontend-marios2/src/content/dashboards/BatteryView/MainStats.tsx @@ -135,6 +135,8 @@ function MainStats(props: MainStatsProps) { function generateSeries(chartData, category, color) { const series = []; const pathsToSearch = [ + 'Node0', + 'Node1', 'Node2', 'Node3', 'Node4', @@ -143,8 +145,7 @@ function MainStats(props: MainStatsProps) { 'Node7', 'Node8', 'Node9', - 'Node10', - 'Node11' + 'Node10' ]; let i = 0; diff --git a/typescript/frontend-marios2/src/content/dashboards/Log/graph.util.tsx b/typescript/frontend-marios2/src/content/dashboards/Log/graph.util.tsx index aa4b6f948..9b192b300 100644 --- a/typescript/frontend-marios2/src/content/dashboards/Log/graph.util.tsx +++ b/typescript/frontend-marios2/src/content/dashboards/Log/graph.util.tsx @@ -68,6 +68,113 @@ export interface Device { TotalBatteryVoltage: number; }; + BatteryDeligreenAlarmRecord: { + OnOffState: { + ChargeSwitchState: string; + CurrentLimitSwitchStat: string; + DischargeSwitchState: string; + HeatingSwitchState: string; + }; + + AlarmEvent1: { + CellVoltageDropoutFault: string; + ChargeSwitchFault: string; + CurrentLimitSwitchFault: string; + CurrentSensorFault: string; + DischargeSwitchFault: string; + KeySwitchFault: string; + TemperatureSensorFault: string; + VoltageSensorFault: string; + }; + + AlarmEvent2: { + HighVoltageAlarmForTotalVoltage: string; + LowVoltageAlarmForTotalVoltage: string; + MonomerHighVoltageAlarm: string; + MonomerLowVoltageAlarm: string; + MonomerOvervoltageProtection: string; + MonomerUnderVoltageProtection: string; + OvervoltageProtectionForTotalVoltage: string; + UnderVoltageProtectionForTotalVoltage: string; + }; + + AlarmEvent3: { + ChargeHighTemperatureAlarm: string; + ChargeLowTemperatureAlarm: string; + ChargeOverTemperatureProtection: string; + ChargeUnderTemperatureProtection: string; + DischargeHighTemperatureAlarm: string; + DischargeLowTemperatureAlarm: string; + DischargeOverTemperatureProtection: string; + DischargeUnderTemperatureProtection: string; + }; + + AlarmEvent4: { + CellLowTemperatureHeating: string; + EnvironmentHighTemperatureAlarm: string; + EnvironmentLowTemperatureAlarm: string; + EnvironmentOverTemperatureProtection: string; + EnvironmentUnderTemperatureProtection: string; + PowerHighTemperatureAlarm: string; + PowerOverTemperatureProtection: string; + }; + + AlarmEvent5: { + ChargeOverCurrentAlarm: string; + ChargeOverCurrentProtection: string; + DischargeOverCurrentAlarm: string; + DischargeOverCurrentProtection: string; + OutputShortCircuitLockout: string; + OutputShortCircuitProtection: string; + TransientOverCurrentLockout: string; + TransientOverCurrentProtection: string; + }; + + AlarmEvent6: { + CellLowVoltageChargingProhibition: string; + ChargeHighVoltageProtection: string; + InsideBit: string; + IntermittentRechargeWaiting: string; + OutputConnectionFault: string; + OutputReversePolarityProtection: string; + ResidualCapacityAlarm: string; + ResidualCapacityProtection: string; + }; + + AlarmEvent7: { + AutomaticChargingWaiting: string; + InsideBit1: string; + InsideBit2: string; + InsideBit3: string; + InsideBit4: string; + InsideBit5: string; + InsideBit6: string; + ManualChargingWaiting: string; + }; + + AlarmEvent8: { + CurrentCalibrationNotPerformed: string; + EepStorageFault: string; + InsideBit1: string; + InsideBit2: string; + InsideBit3: string; + RtcError: string; + VoltageCalibrationNotPerformed: string; + ZeroCalibrationNotPerformed: string; + }; + + CellAlarmList: string; + CellTemperatureAlarm: string; + + SystemState: { + Charge: string; + Discharge: string; + FloatingCharge: string; + Shutdown: string; + Standby: string; + }; + }; + Leds: Leds; Eoc: boolean; Soc: number; diff --git a/typescript/frontend-marios2/src/interfaces/Chart.tsx b/typescript/frontend-marios2/src/interfaces/Chart.tsx index cd3e519ed..b3ccf5013 100644 --- a/typescript/frontend-marios2/src/interfaces/Chart.tsx +++ b/typescript/frontend-marios2/src/interfaces/Chart.tsx @@ -159,7 +159,7 @@ export const transformInputToBatteryViewDataJson = async ( ); const adjustedTimestamp = - product == 0 + product == 0 || product == 3 ? new Date(timestampArray[i] * 1000) : new Date(timestampArray[i] * 100000); //Timezone offset is negative, so we convert the timestamp to the current zone by subtracting the corresponding offset @@ -185,19 +185,21 @@ export const transformInputToBatteryViewDataJson = async ( const battery_nodes = result.Config.Devices.BatteryNodes.toString().split(','); - // console.log(battery_nodes); - //Initialize the chartData structure based on the node names extracted from the first result let old_length = pathsToSave.length; if (battery_nodes.length > old_length) { battery_nodes.forEach((node) => { - if (!pathsToSave.includes('Node' + node)) { - pathsToSave.push('Node' + node); + const node_number = + product == 3 ? Number(node) + 1 : Number(node) - 1; + if (!pathsToSave.includes('Node' + node_number)) { + pathsToSave.push('Node' + node_number); } }); } + // console.log(pathsToSave); + if (initialiation) { initialiation = false; categories.forEach((category) => {