frequenz-cs-reporting 0.4.0__tar.gz → 0.4.2__tar.gz
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.
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/Dockerfile +5 -1
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/PKG-INFO +7 -7
- frequenz_cs_reporting-0.4.2/RELEASE_NOTES.md +13 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/pyproject.toml +8 -8
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/app_pages/reporting.py +7 -1
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/services/client_factory.py +61 -2
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/services/data_service.py +43 -2
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/views/dashboard.py +32 -1
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/views/plot_renderers.py +36 -62
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz_cs_reporting.egg-info/PKG-INFO +7 -7
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz_cs_reporting.egg-info/requires.txt +6 -6
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz_cs_reporting.egg-info/scm_file_list.json +67 -67
- frequenz_cs_reporting-0.4.2/src/frequenz_cs_reporting.egg-info/scm_version.json +8 -0
- frequenz_cs_reporting-0.4.0/RELEASE_NOTES.md +0 -17
- frequenz_cs_reporting-0.4.0/src/frequenz_cs_reporting.egg-info/scm_version.json +0 -8
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/.streamlit/config.toml +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/LICENSE +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/MANIFEST.in +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/README.md +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/app.py +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/setup.cfg +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/__init__.py +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/app_pages/__init__.py +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/app_pages/home.py +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/app_pages/solar.py +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/assets/__init__.py +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/assets/neustrom_background.png +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/assets/neustrom_logo.png +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/components/__init__.py +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/components/inputs.py +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/components/plot_charts.py +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/components/sidebar_inputs.py +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/components/tables.py +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/components/ui.py +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/conftest.py +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/constants.py +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/py.typed +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/rep_cs_core/__init__.py +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/rep_cs_core/config.py +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/rep_cs_core/page_spec.py +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/services/__init__.py +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/services/solar_workflow.py +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/styles/dashboard.css +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/styles/home.css +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/styles/kpi.css +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/styles/plot_card.css +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/templates/dashboard_section_divider.html +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/templates/home_feature_grid.html +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/templates/home_feature_item.html +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/templates/home_footer.html +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/templates/home_hero.html +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/templates/home_logo.html +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/templates/home_stat_item.html +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/templates/home_stats.html +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/ui_resources.py +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/utils/__init__.py +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/utils/env.py +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/utils/time.py +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/views/__init__.py +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/views/metric_renderers.py +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/views/sections.py +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/views/solar_results.py +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/views/table_renderers.py +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz_cs_reporting.egg-info/SOURCES.txt +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz_cs_reporting.egg-info/dependency_links.txt +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz_cs_reporting.egg-info/top_level.txt +0 -0
- {frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/toml_directory/__init__.py +0 -0
|
@@ -29,4 +29,8 @@ RUN pip install --no-cache-dir \
|
|
|
29
29
|
"marshmallow-dataclass>=8.7.1,<9" \
|
|
30
30
|
"plotly>=6.0.0,<6.4.0" \
|
|
31
31
|
"kaleido>=0.2.1,<1.2.0" \
|
|
32
|
-
"marshmallow>=4.1.0,<5"
|
|
32
|
+
"marshmallow>=4.1.0,<5" \
|
|
33
|
+
"grpcio>=1.81.1,<2"
|
|
34
|
+
|
|
35
|
+
# Prefer packages installed in Deepnote's venv over Deepnote's toolkit server libs.
|
|
36
|
+
ENV PYTHONPATH="/root/venv/lib/python3.12/site-packages:${PYTHONPATH}"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: frequenz-cs-reporting
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.2
|
|
4
4
|
Summary: Streamlit Library for reporting and solar monitoring
|
|
5
5
|
Author-email: Frequenz Energy-as-a-Service GmbH <floss@frequenz.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -38,7 +38,7 @@ Requires-Dist: flake8==7.3.0; extra == "dev-flake8"
|
|
|
38
38
|
Requires-Dist: flake8-datetimez==20.10.0; extra == "dev-flake8"
|
|
39
39
|
Requires-Dist: flake8-docstrings==1.7.0; extra == "dev-flake8"
|
|
40
40
|
Requires-Dist: flake8-pyproject==1.2.4; extra == "dev-flake8"
|
|
41
|
-
Requires-Dist: pydoclint==0.9.
|
|
41
|
+
Requires-Dist: pydoclint==0.9.1; extra == "dev-flake8"
|
|
42
42
|
Requires-Dist: pydocstyle==6.3.0; extra == "dev-flake8"
|
|
43
43
|
Provides-Extra: dev-formatting
|
|
44
44
|
Requires-Dist: black==26.5.1; extra == "dev-formatting"
|
|
@@ -50,18 +50,18 @@ Requires-Dist: mike==2.2.0; extra == "dev-mkdocs"
|
|
|
50
50
|
Requires-Dist: mkdocs-gen-files==0.6.1; extra == "dev-mkdocs"
|
|
51
51
|
Requires-Dist: mkdocs-literate-nav==0.6.3; extra == "dev-mkdocs"
|
|
52
52
|
Requires-Dist: mkdocs-macros-plugin==1.5.0; extra == "dev-mkdocs"
|
|
53
|
-
Requires-Dist: mkdocs-material==9.7.
|
|
54
|
-
Requires-Dist: mkdocstrings[python]==1.0.
|
|
53
|
+
Requires-Dist: mkdocs-material==9.7.7; extra == "dev-mkdocs"
|
|
54
|
+
Requires-Dist: mkdocstrings[python]==1.0.6; extra == "dev-mkdocs"
|
|
55
55
|
Requires-Dist: mkdocstrings-python==2.0.5; extra == "dev-mkdocs"
|
|
56
56
|
Requires-Dist: frequenz-repo-config[lib]==0.18.0; extra == "dev-mkdocs"
|
|
57
57
|
Provides-Extra: dev-mypy
|
|
58
|
-
Requires-Dist: mypy==2.
|
|
59
|
-
Requires-Dist: types-Markdown==3.10.2.
|
|
58
|
+
Requires-Dist: mypy==2.3.0; extra == "dev-mypy"
|
|
59
|
+
Requires-Dist: types-Markdown==3.10.2.20260712; extra == "dev-mypy"
|
|
60
60
|
Requires-Dist: types-pytz; extra == "dev-mypy"
|
|
61
61
|
Requires-Dist: pandas-stubs; extra == "dev-mypy"
|
|
62
62
|
Requires-Dist: frequenz-cs-reporting[dev-mkdocs,dev-noxfile,dev-pytest]; extra == "dev-mypy"
|
|
63
63
|
Provides-Extra: dev-noxfile
|
|
64
|
-
Requires-Dist: nox==2026.
|
|
64
|
+
Requires-Dist: nox==2026.7.11; extra == "dev-noxfile"
|
|
65
65
|
Requires-Dist: frequenz-repo-config[lib]==0.18.0; extra == "dev-noxfile"
|
|
66
66
|
Provides-Extra: dev-pylint
|
|
67
67
|
Requires-Dist: frequenz-cs-reporting[dev-mkdocs,dev-noxfile,dev-pytest]; extra == "dev-pylint"
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
|
|
4
4
|
[build-system]
|
|
5
5
|
requires = [
|
|
6
|
-
"setuptools ==
|
|
7
|
-
"setuptools_scm[toml] == 10.2.
|
|
6
|
+
"setuptools == 83.0.0",
|
|
7
|
+
"setuptools_scm[toml] == 10.2.1",
|
|
8
8
|
"frequenz-repo-config[lib] == 0.18.0",
|
|
9
9
|
]
|
|
10
10
|
build-backend = "setuptools.build_meta"
|
|
@@ -54,7 +54,7 @@ dev-flake8 = [
|
|
|
54
54
|
"flake8-datetimez == 20.10.0",
|
|
55
55
|
"flake8-docstrings == 1.7.0",
|
|
56
56
|
"flake8-pyproject == 1.2.4", # For reading the flake8 config from pyproject.toml
|
|
57
|
-
"pydoclint == 0.9.
|
|
57
|
+
"pydoclint == 0.9.1",
|
|
58
58
|
"pydocstyle == 6.3.0",
|
|
59
59
|
]
|
|
60
60
|
dev-formatting = ["black == 26.5.1", "isort == 8.0.1"]
|
|
@@ -65,21 +65,21 @@ dev-mkdocs = [
|
|
|
65
65
|
"mkdocs-gen-files == 0.6.1",
|
|
66
66
|
"mkdocs-literate-nav == 0.6.3",
|
|
67
67
|
"mkdocs-macros-plugin == 1.5.0",
|
|
68
|
-
"mkdocs-material == 9.7.
|
|
69
|
-
"mkdocstrings[python] == 1.0.
|
|
68
|
+
"mkdocs-material == 9.7.7",
|
|
69
|
+
"mkdocstrings[python] == 1.0.6",
|
|
70
70
|
"mkdocstrings-python == 2.0.5",
|
|
71
71
|
"frequenz-repo-config[lib] == 0.18.0",
|
|
72
72
|
]
|
|
73
73
|
dev-mypy = [
|
|
74
|
-
"mypy == 2.
|
|
75
|
-
"types-Markdown == 3.10.2.
|
|
74
|
+
"mypy == 2.3.0",
|
|
75
|
+
"types-Markdown == 3.10.2.20260712",
|
|
76
76
|
"types-pytz",
|
|
77
77
|
"pandas-stubs",
|
|
78
78
|
# For checking the noxfile, docs/ script, and tests
|
|
79
79
|
"frequenz-cs-reporting[dev-mkdocs,dev-noxfile,dev-pytest]",
|
|
80
80
|
]
|
|
81
81
|
dev-noxfile = [
|
|
82
|
-
"nox == 2026.
|
|
82
|
+
"nox == 2026.7.11",
|
|
83
83
|
"frequenz-repo-config[lib] == 0.18.0",
|
|
84
84
|
]
|
|
85
85
|
dev-pylint = [
|
|
@@ -162,7 +162,13 @@ def render() -> None:
|
|
|
162
162
|
|
|
163
163
|
# Build and render dashboard
|
|
164
164
|
mapper = ColumnMapper.from_default()
|
|
165
|
-
master_df = build_master_df(
|
|
165
|
+
master_df = build_master_df(
|
|
166
|
+
df_prepared,
|
|
167
|
+
component_types,
|
|
168
|
+
mcfg,
|
|
169
|
+
mapper,
|
|
170
|
+
timezone=timezone,
|
|
171
|
+
)
|
|
166
172
|
render_dashboard(
|
|
167
173
|
master_df,
|
|
168
174
|
resolution=resolution,
|
|
@@ -5,12 +5,15 @@
|
|
|
5
5
|
|
|
6
6
|
from __future__ import annotations
|
|
7
7
|
|
|
8
|
+
import asyncio
|
|
8
9
|
import os
|
|
9
10
|
from pathlib import Path
|
|
10
11
|
|
|
11
12
|
import streamlit as st
|
|
13
|
+
from frequenz.client.assets import AssetsApiClient
|
|
14
|
+
from frequenz.client.common.microgrid import MicrogridId
|
|
12
15
|
from frequenz.data.microgrid import component_data
|
|
13
|
-
from frequenz.gridpool import MicrogridConfig
|
|
16
|
+
from frequenz.gridpool import MicrogridConfig, load_configs
|
|
14
17
|
|
|
15
18
|
from frequenz.cs_reporting.utils.env import require_env
|
|
16
19
|
|
|
@@ -28,7 +31,28 @@ def _load_microgrid_configs() -> dict[str, MicrogridConfig]:
|
|
|
28
31
|
config_root = Path(os.getenv("MICROGRID_CONFIG_DIR", "toml_directory/"))
|
|
29
32
|
if not config_root.is_dir():
|
|
30
33
|
raise RuntimeError(f"Microgrid config directory not found: {config_root}")
|
|
31
|
-
|
|
34
|
+
config_files: list[str | Path] = sorted(config_root.glob("*.toml"))
|
|
35
|
+
if not config_files:
|
|
36
|
+
raise RuntimeError(f"No microgrid config files found in: {config_root}")
|
|
37
|
+
auth_key = require_env("API_KEY")
|
|
38
|
+
sign_secret = require_env("API_SECRET")
|
|
39
|
+
assets_api_url = require_env("ASSETS_API_URL")
|
|
40
|
+
|
|
41
|
+
async def load() -> dict[str, MicrogridConfig]:
|
|
42
|
+
assets_client = AssetsApiClient(
|
|
43
|
+
assets_api_url,
|
|
44
|
+
auth_key=auth_key,
|
|
45
|
+
sign_secret=sign_secret,
|
|
46
|
+
)
|
|
47
|
+
try:
|
|
48
|
+
return await load_configs(
|
|
49
|
+
default_files=config_files,
|
|
50
|
+
assets_client=assets_client,
|
|
51
|
+
)
|
|
52
|
+
finally:
|
|
53
|
+
await assets_client.disconnect()
|
|
54
|
+
|
|
55
|
+
return asyncio.run(load())
|
|
32
56
|
|
|
33
57
|
|
|
34
58
|
def get_microgrid_client(microgrid_id: int) -> component_data.MicrogridData:
|
|
@@ -95,3 +119,38 @@ def get_microgrid_ids() -> list[int]:
|
|
|
95
119
|
List of configured microgrid IDs.
|
|
96
120
|
"""
|
|
97
121
|
return sorted(int(mid.replace("iot", "")) for mid in _load_microgrid_configs())
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
@st.cache_data(show_spinner=False)
|
|
125
|
+
def get_meter_display_names(microgrid_id: int) -> dict[str, str]:
|
|
126
|
+
"""Return component display names for a microgrid from the Assets API.
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
microgrid_id: Identifier for the target microgrid.
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
Mapping of component ID strings to display names.
|
|
133
|
+
"""
|
|
134
|
+
auth_key = require_env("API_KEY")
|
|
135
|
+
sign_secret = require_env("API_SECRET")
|
|
136
|
+
assets_api_url = require_env("ASSETS_API_URL")
|
|
137
|
+
|
|
138
|
+
async def load() -> dict[str, str]:
|
|
139
|
+
assets_client = AssetsApiClient(
|
|
140
|
+
assets_api_url,
|
|
141
|
+
auth_key=auth_key,
|
|
142
|
+
sign_secret=sign_secret,
|
|
143
|
+
)
|
|
144
|
+
try:
|
|
145
|
+
components = await assets_client.list_microgrid_electrical_components(
|
|
146
|
+
MicrogridId(microgrid_id)
|
|
147
|
+
)
|
|
148
|
+
return {
|
|
149
|
+
str(component.id): component.name
|
|
150
|
+
for component in components
|
|
151
|
+
if component.name
|
|
152
|
+
}
|
|
153
|
+
finally:
|
|
154
|
+
await assets_client.disconnect()
|
|
155
|
+
|
|
156
|
+
return asyncio.run(load())
|
|
@@ -6,10 +6,15 @@
|
|
|
6
6
|
from __future__ import annotations
|
|
7
7
|
|
|
8
8
|
import asyncio
|
|
9
|
+
import logging
|
|
10
|
+
import warnings
|
|
11
|
+
from collections.abc import Iterator
|
|
12
|
+
from contextlib import contextmanager
|
|
9
13
|
from datetime import datetime, timedelta
|
|
10
14
|
|
|
11
15
|
import pandas as pd
|
|
12
16
|
import streamlit as st
|
|
17
|
+
from pandas.errors import PerformanceWarning
|
|
13
18
|
|
|
14
19
|
from frequenz.cs_reporting.services.client_factory import (
|
|
15
20
|
get_component_types,
|
|
@@ -17,6 +22,41 @@ from frequenz.cs_reporting.services.client_factory import (
|
|
|
17
22
|
)
|
|
18
23
|
from frequenz.cs_reporting.utils.time import validate_range
|
|
19
24
|
|
|
25
|
+
_COMPONENT_DATA_LOGGER = "frequenz.data.microgrid.component_data"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class _MissingComponentFilter(logging.Filter):
|
|
29
|
+
"""Filter expected missing-component warnings from the data client."""
|
|
30
|
+
|
|
31
|
+
def filter(self, record: logging.LogRecord) -> bool:
|
|
32
|
+
"""Return whether a log record should be emitted."""
|
|
33
|
+
if record.name != _COMPONENT_DATA_LOGGER:
|
|
34
|
+
return True
|
|
35
|
+
message = record.getMessage()
|
|
36
|
+
return not (
|
|
37
|
+
message.startswith("Component ID ")
|
|
38
|
+
and message.endswith(" not found in data, setting zero")
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@contextmanager
|
|
43
|
+
def _quiet_expected_component_data_warnings() -> Iterator[None]:
|
|
44
|
+
"""Suppress expected noisy warnings emitted while building component data."""
|
|
45
|
+
logger = logging.getLogger(_COMPONENT_DATA_LOGGER)
|
|
46
|
+
component_filter = _MissingComponentFilter()
|
|
47
|
+
logger.addFilter(component_filter)
|
|
48
|
+
try:
|
|
49
|
+
with warnings.catch_warnings():
|
|
50
|
+
warnings.filterwarnings(
|
|
51
|
+
"ignore",
|
|
52
|
+
category=PerformanceWarning,
|
|
53
|
+
message="DataFrame is highly fragmented.*",
|
|
54
|
+
module=r"frequenz\.data\.microgrid\.component_data",
|
|
55
|
+
)
|
|
56
|
+
yield
|
|
57
|
+
finally:
|
|
58
|
+
logger.removeFilter(component_filter)
|
|
59
|
+
|
|
20
60
|
|
|
21
61
|
async def fetch_microgrid_data(
|
|
22
62
|
microgrid_id: int,
|
|
@@ -51,11 +91,12 @@ async def fetch_microgrid_data(
|
|
|
51
91
|
keep_components=True,
|
|
52
92
|
splits=True,
|
|
53
93
|
)
|
|
54
|
-
|
|
94
|
+
with _quiet_expected_component_data_warnings():
|
|
95
|
+
df = await asyncio.wait_for(coro, timeout)
|
|
55
96
|
|
|
56
97
|
if df is None or (hasattr(df, "empty") and df.empty):
|
|
57
98
|
return pd.DataFrame()
|
|
58
|
-
return df
|
|
99
|
+
return df.copy()
|
|
59
100
|
|
|
60
101
|
|
|
61
102
|
# Cached sync wrapper for Streamlit pages
|
|
@@ -5,13 +5,18 @@
|
|
|
5
5
|
|
|
6
6
|
from __future__ import annotations
|
|
7
7
|
|
|
8
|
+
import asyncio
|
|
8
9
|
from datetime import timedelta
|
|
9
10
|
from typing import Any, Iterable
|
|
10
11
|
|
|
11
12
|
import pandas as pd
|
|
12
13
|
import streamlit as st
|
|
14
|
+
from frequenz.lib.notebooks.reporting.asset_optimization.data import (
|
|
15
|
+
merge_day_ahead_prices,
|
|
16
|
+
)
|
|
13
17
|
from frequenz.lib.notebooks.reporting.data_processing import create_energy_report_df
|
|
14
18
|
from frequenz.lib.notebooks.reporting.utils.column_mapper import ColumnMapper
|
|
19
|
+
from frequenz.lib.notebooks.reporting.utils.helpers import get_meter_display_names
|
|
15
20
|
from frequenz.lib.notebooks.reporting.utils.reporting_nb_functions import (
|
|
16
21
|
aggregate_metrics,
|
|
17
22
|
build_component_analysis,
|
|
@@ -100,6 +105,12 @@ def _build_tables(
|
|
|
100
105
|
}
|
|
101
106
|
|
|
102
107
|
overview_df = build_overview_df(master_df, component_types)
|
|
108
|
+
if "day_ahead_price" in master_df.columns and "timestamp" in overview_df.columns:
|
|
109
|
+
overview_df = overview_df.merge(
|
|
110
|
+
master_df[["timestamp", "day_ahead_price"]],
|
|
111
|
+
on="timestamp",
|
|
112
|
+
how="left",
|
|
113
|
+
)
|
|
103
114
|
|
|
104
115
|
return {
|
|
105
116
|
"power_table": power_table,
|
|
@@ -118,6 +129,7 @@ def build_master_df(
|
|
|
118
129
|
component_types: Iterable[str],
|
|
119
130
|
mcfg: Any,
|
|
120
131
|
mapper: ColumnMapper,
|
|
132
|
+
timezone: str = "Europe/Berlin",
|
|
121
133
|
) -> pd.DataFrame:
|
|
122
134
|
"""Transform raw microgrid data into master analysis dataframe.
|
|
123
135
|
|
|
@@ -133,6 +145,7 @@ def build_master_df(
|
|
|
133
145
|
mcfg: Microgrid configuration object containing component metadata and
|
|
134
146
|
site-specific settings.
|
|
135
147
|
mapper: Column name mapper for converting internal names to display names.
|
|
148
|
+
timezone: Timezone name to use for the report timestamps.
|
|
136
149
|
|
|
137
150
|
Returns:
|
|
138
151
|
Master dataframe with processed and aggregated component data, ready for
|
|
@@ -147,7 +160,25 @@ def build_master_df(
|
|
|
147
160
|
for c in component_types
|
|
148
161
|
if pd.to_numeric(raw_df[c], errors="coerce").fillna(0).sum() != 0
|
|
149
162
|
]
|
|
150
|
-
|
|
163
|
+
component_display_names = asyncio.run(
|
|
164
|
+
get_meter_display_names(mcfg.meta.microgrid_id)
|
|
165
|
+
)
|
|
166
|
+
master_df = create_energy_report_df(
|
|
167
|
+
raw_df,
|
|
168
|
+
component_types,
|
|
169
|
+
mcfg,
|
|
170
|
+
mapper=mapper,
|
|
171
|
+
tz_name=timezone,
|
|
172
|
+
assume_tz="UTC",
|
|
173
|
+
component_display_names=component_display_names,
|
|
174
|
+
)
|
|
175
|
+
try:
|
|
176
|
+
master_df = merge_day_ahead_prices(
|
|
177
|
+
master_df.set_index("timestamp"),
|
|
178
|
+
dayahead_country_code="DE_LU",
|
|
179
|
+
).reset_index()
|
|
180
|
+
except (ModuleNotFoundError, ValueError) as exc:
|
|
181
|
+
st.warning(f"Day-ahead prices could not be loaded: {exc}")
|
|
151
182
|
return master_df
|
|
152
183
|
|
|
153
184
|
|
|
@@ -13,41 +13,17 @@ import streamlit as st
|
|
|
13
13
|
from frequenz.lib.notebooks.reporting.plotter import (
|
|
14
14
|
plot_energy_pie_chart,
|
|
15
15
|
plot_time_series,
|
|
16
|
+
plot_time_series_battery_usecase,
|
|
16
17
|
)
|
|
17
18
|
from frequenz.lib.notebooks.reporting.utils.column_mapper import ColumnMapper
|
|
18
19
|
|
|
19
20
|
from frequenz.cs_reporting.components.ui import render_plot_card
|
|
20
21
|
from frequenz.cs_reporting.constants import (
|
|
21
22
|
COLOR_DICT,
|
|
22
|
-
COLUMN_RENAME_MAP,
|
|
23
23
|
COMPONENT_CONFIGS,
|
|
24
24
|
TablesResult,
|
|
25
25
|
)
|
|
26
26
|
|
|
27
|
-
_DEFAULT_PLOT_ORDER = [
|
|
28
|
-
"Zeitpunkt",
|
|
29
|
-
"MID Gesamtverbrauch",
|
|
30
|
-
"Netzbezug",
|
|
31
|
-
"Netzeinspeisung",
|
|
32
|
-
"PV-Erzeugung",
|
|
33
|
-
"KWK-Erzeugung",
|
|
34
|
-
"Wind-Erzeugung",
|
|
35
|
-
"Batterie Leistungsfluss",
|
|
36
|
-
]
|
|
37
|
-
|
|
38
|
-
_DEFAULT_DOTTED_COLS = ["Netzbezug"]
|
|
39
|
-
_FILL_EXCLUDE = {
|
|
40
|
-
"Zeitpunkt",
|
|
41
|
-
"MID Gesamtverbrauch",
|
|
42
|
-
"Netzbezug",
|
|
43
|
-
"Netzeinspeisung",
|
|
44
|
-
"Netz Einspeisung",
|
|
45
|
-
}
|
|
46
|
-
_OVERVIEW_ALIASES = {
|
|
47
|
-
"BHKW-Erzeugung": "KWK-Erzeugung",
|
|
48
|
-
"CHP": "KWK-Erzeugung",
|
|
49
|
-
"Netz Einspeisung": "Netzeinspeisung",
|
|
50
|
-
}
|
|
51
27
|
_COMPONENT_TABS = [
|
|
52
28
|
("PV Leistung", "pv"),
|
|
53
29
|
("Batterie", "batt"),
|
|
@@ -55,6 +31,9 @@ _COMPONENT_TABS = [
|
|
|
55
31
|
("KWK", "chp"),
|
|
56
32
|
("EV", "ev"),
|
|
57
33
|
]
|
|
34
|
+
_BATTERY_OVERVIEW_HEIGHT = 580
|
|
35
|
+
_BATTERY_OVERVIEW_MARGIN = {"t": 150, "r": 56, "b": 96, "l": 64}
|
|
36
|
+
_BATTERY_OVERVIEW_RANGE_SLIDER_THICKNESS = 0.15
|
|
58
37
|
|
|
59
38
|
|
|
60
39
|
# pylint: disable=too-many-arguments
|
|
@@ -206,43 +185,27 @@ def _render_component_tab(
|
|
|
206
185
|
)
|
|
207
186
|
|
|
208
187
|
|
|
209
|
-
def
|
|
210
|
-
|
|
211
|
-
) -> pd.DataFrame | None:
|
|
212
|
-
"""Return overview dataframe with display-ready column names.
|
|
188
|
+
def _prepare_battery_usecase_df(tables: TablesResult) -> pd.DataFrame | None:
|
|
189
|
+
"""Return the overview dataframe prepared for the battery-usecase plot.
|
|
213
190
|
|
|
214
191
|
Args:
|
|
215
192
|
tables: Dictionary containing precomputed tables.
|
|
216
|
-
mapper: Column mapper for converting internal names to display names.
|
|
217
193
|
|
|
218
194
|
Returns:
|
|
219
|
-
|
|
220
|
-
when unavailable.
|
|
195
|
+
Battery-usecase dataframe, or ``None`` when unavailable.
|
|
221
196
|
"""
|
|
222
197
|
overview_df = tables.get("overview_df")
|
|
223
198
|
if overview_df is None or overview_df.empty:
|
|
224
199
|
return None
|
|
225
200
|
|
|
226
|
-
overview_df =
|
|
227
|
-
# Compatibility shim until the latest lib notebooks update rolls out
|
|
228
|
-
overview_df = overview_df.rename(columns=COLUMN_RENAME_MAP)
|
|
229
|
-
|
|
230
|
-
# Normalize known legacy aliases so plot ordering always includes key series.
|
|
231
|
-
for source, target in _OVERVIEW_ALIASES.items():
|
|
232
|
-
if source in overview_df.columns and target not in overview_df.columns:
|
|
233
|
-
overview_df = overview_df.rename(columns={source: target})
|
|
201
|
+
return overview_df.drop(columns={"grid_feed_in"}, errors="ignore")
|
|
234
202
|
|
|
235
|
-
return overview_df
|
|
236
203
|
|
|
237
|
-
|
|
238
|
-
def _render_overview_plot(
|
|
239
|
-
overview_df: pd.DataFrame | None, color_dict: dict[str, str] | None
|
|
240
|
-
) -> None:
|
|
204
|
+
def _render_overview_plot(overview_df: pd.DataFrame | None) -> None:
|
|
241
205
|
"""Render the main time-series overview plot.
|
|
242
206
|
|
|
243
207
|
Args:
|
|
244
|
-
overview_df:
|
|
245
|
-
color_dict: Optional color mapping for plot series.
|
|
208
|
+
overview_df: Battery-usecase dataframe in canonical naming convention.
|
|
246
209
|
|
|
247
210
|
Returns:
|
|
248
211
|
Streamlit components are rendered directly.
|
|
@@ -251,19 +214,32 @@ def _render_overview_plot(
|
|
|
251
214
|
st.info("Keine Übersichtsdaten zum Plotten verfügbar.")
|
|
252
215
|
return
|
|
253
216
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
217
|
+
helper_cols = {"battery_charge", "battery_discharge"}
|
|
218
|
+
cols_list = [col for col in overview_df.columns if col not in helper_cols]
|
|
219
|
+
secondary_y_cols = (
|
|
220
|
+
["day_ahead_price"] if "day_ahead_price" in overview_df.columns else None
|
|
221
|
+
)
|
|
222
|
+
fig = plot_time_series_battery_usecase(
|
|
260
223
|
overview_df,
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
224
|
+
time_col="timestamp",
|
|
225
|
+
cols=cols_list,
|
|
226
|
+
legend_title=None,
|
|
227
|
+
secondary_y_cols=secondary_y_cols,
|
|
228
|
+
secondary_y_title="EUR/MWh" if secondary_y_cols else None,
|
|
229
|
+
title="",
|
|
230
|
+
dotted_cols=[
|
|
231
|
+
"grid_consumption_without_battery",
|
|
232
|
+
"peak_before_optimization",
|
|
233
|
+
"day_ahead_price",
|
|
234
|
+
],
|
|
235
|
+
stack_mode="psc",
|
|
236
|
+
)
|
|
237
|
+
fig.update_layout(
|
|
238
|
+
height=_BATTERY_OVERVIEW_HEIGHT,
|
|
239
|
+
margin=_BATTERY_OVERVIEW_MARGIN,
|
|
240
|
+
xaxis_rangeslider_thickness=_BATTERY_OVERVIEW_RANGE_SLIDER_THICKNESS,
|
|
266
241
|
)
|
|
242
|
+
render_plot_card("Lastgang Übersicht", fig)
|
|
267
243
|
|
|
268
244
|
|
|
269
245
|
def _get_active_tabs(
|
|
@@ -273,11 +249,9 @@ def _get_active_tabs(
|
|
|
273
249
|
tabs = []
|
|
274
250
|
|
|
275
251
|
# 1. Overview Tab
|
|
276
|
-
overview_df =
|
|
252
|
+
overview_df = _prepare_battery_usecase_df(tables)
|
|
277
253
|
if overview_df is not None and not overview_df.empty:
|
|
278
|
-
tabs.append(
|
|
279
|
-
("Zeitreihen-Plot", lambda: _render_overview_plot(overview_df, palette))
|
|
280
|
-
)
|
|
254
|
+
tabs.append(("Zeitreihen-Plot", lambda: _render_overview_plot(overview_df)))
|
|
281
255
|
|
|
282
256
|
# 2. Energy Mix Tab
|
|
283
257
|
power_table = tables.get("power_table")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: frequenz-cs-reporting
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.2
|
|
4
4
|
Summary: Streamlit Library for reporting and solar monitoring
|
|
5
5
|
Author-email: Frequenz Energy-as-a-Service GmbH <floss@frequenz.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -38,7 +38,7 @@ Requires-Dist: flake8==7.3.0; extra == "dev-flake8"
|
|
|
38
38
|
Requires-Dist: flake8-datetimez==20.10.0; extra == "dev-flake8"
|
|
39
39
|
Requires-Dist: flake8-docstrings==1.7.0; extra == "dev-flake8"
|
|
40
40
|
Requires-Dist: flake8-pyproject==1.2.4; extra == "dev-flake8"
|
|
41
|
-
Requires-Dist: pydoclint==0.9.
|
|
41
|
+
Requires-Dist: pydoclint==0.9.1; extra == "dev-flake8"
|
|
42
42
|
Requires-Dist: pydocstyle==6.3.0; extra == "dev-flake8"
|
|
43
43
|
Provides-Extra: dev-formatting
|
|
44
44
|
Requires-Dist: black==26.5.1; extra == "dev-formatting"
|
|
@@ -50,18 +50,18 @@ Requires-Dist: mike==2.2.0; extra == "dev-mkdocs"
|
|
|
50
50
|
Requires-Dist: mkdocs-gen-files==0.6.1; extra == "dev-mkdocs"
|
|
51
51
|
Requires-Dist: mkdocs-literate-nav==0.6.3; extra == "dev-mkdocs"
|
|
52
52
|
Requires-Dist: mkdocs-macros-plugin==1.5.0; extra == "dev-mkdocs"
|
|
53
|
-
Requires-Dist: mkdocs-material==9.7.
|
|
54
|
-
Requires-Dist: mkdocstrings[python]==1.0.
|
|
53
|
+
Requires-Dist: mkdocs-material==9.7.7; extra == "dev-mkdocs"
|
|
54
|
+
Requires-Dist: mkdocstrings[python]==1.0.6; extra == "dev-mkdocs"
|
|
55
55
|
Requires-Dist: mkdocstrings-python==2.0.5; extra == "dev-mkdocs"
|
|
56
56
|
Requires-Dist: frequenz-repo-config[lib]==0.18.0; extra == "dev-mkdocs"
|
|
57
57
|
Provides-Extra: dev-mypy
|
|
58
|
-
Requires-Dist: mypy==2.
|
|
59
|
-
Requires-Dist: types-Markdown==3.10.2.
|
|
58
|
+
Requires-Dist: mypy==2.3.0; extra == "dev-mypy"
|
|
59
|
+
Requires-Dist: types-Markdown==3.10.2.20260712; extra == "dev-mypy"
|
|
60
60
|
Requires-Dist: types-pytz; extra == "dev-mypy"
|
|
61
61
|
Requires-Dist: pandas-stubs; extra == "dev-mypy"
|
|
62
62
|
Requires-Dist: frequenz-cs-reporting[dev-mkdocs,dev-noxfile,dev-pytest]; extra == "dev-mypy"
|
|
63
63
|
Provides-Extra: dev-noxfile
|
|
64
|
-
Requires-Dist: nox==2026.
|
|
64
|
+
Requires-Dist: nox==2026.7.11; extra == "dev-noxfile"
|
|
65
65
|
Requires-Dist: frequenz-repo-config[lib]==0.18.0; extra == "dev-noxfile"
|
|
66
66
|
Provides-Extra: dev-pylint
|
|
67
67
|
Requires-Dist: frequenz-cs-reporting[dev-mkdocs,dev-noxfile,dev-pytest]; extra == "dev-pylint"
|
|
@@ -21,7 +21,7 @@ flake8==7.3.0
|
|
|
21
21
|
flake8-datetimez==20.10.0
|
|
22
22
|
flake8-docstrings==1.7.0
|
|
23
23
|
flake8-pyproject==1.2.4
|
|
24
|
-
pydoclint==0.9.
|
|
24
|
+
pydoclint==0.9.1
|
|
25
25
|
pydocstyle==6.3.0
|
|
26
26
|
|
|
27
27
|
[dev-formatting]
|
|
@@ -35,20 +35,20 @@ mike==2.2.0
|
|
|
35
35
|
mkdocs-gen-files==0.6.1
|
|
36
36
|
mkdocs-literate-nav==0.6.3
|
|
37
37
|
mkdocs-macros-plugin==1.5.0
|
|
38
|
-
mkdocs-material==9.7.
|
|
39
|
-
mkdocstrings[python]==1.0.
|
|
38
|
+
mkdocs-material==9.7.7
|
|
39
|
+
mkdocstrings[python]==1.0.6
|
|
40
40
|
mkdocstrings-python==2.0.5
|
|
41
41
|
frequenz-repo-config[lib]==0.18.0
|
|
42
42
|
|
|
43
43
|
[dev-mypy]
|
|
44
|
-
mypy==2.
|
|
45
|
-
types-Markdown==3.10.2.
|
|
44
|
+
mypy==2.3.0
|
|
45
|
+
types-Markdown==3.10.2.20260712
|
|
46
46
|
types-pytz
|
|
47
47
|
pandas-stubs
|
|
48
48
|
frequenz-cs-reporting[dev-mkdocs,dev-noxfile,dev-pytest]
|
|
49
49
|
|
|
50
50
|
[dev-noxfile]
|
|
51
|
-
nox==2026.
|
|
51
|
+
nox==2026.7.11
|
|
52
52
|
frequenz-repo-config[lib]==0.18.0
|
|
53
53
|
|
|
54
54
|
[dev-pylint]
|
|
@@ -1,93 +1,93 @@
|
|
|
1
1
|
{
|
|
2
2
|
"files": [
|
|
3
|
-
".
|
|
4
|
-
"
|
|
3
|
+
"mkdocs.yml",
|
|
4
|
+
"app.py",
|
|
5
|
+
"MANIFEST.in",
|
|
5
6
|
"CONTRIBUTING.md",
|
|
6
|
-
".editorconfig",
|
|
7
|
-
".cookiecutter-replay.json",
|
|
8
7
|
"Dockerfile",
|
|
8
|
+
".editorconfig",
|
|
9
9
|
"pyproject.toml",
|
|
10
|
-
"
|
|
11
|
-
"app.py",
|
|
12
|
-
"RELEASE_NOTES.md",
|
|
13
|
-
"LICENSE",
|
|
14
|
-
"mkdocs.yml",
|
|
15
|
-
"CODEOWNERS",
|
|
10
|
+
".cookiecutter-replay.json",
|
|
16
11
|
"noxfile.py",
|
|
12
|
+
"CODEOWNERS",
|
|
13
|
+
"LICENSE",
|
|
14
|
+
"RELEASE_NOTES.md",
|
|
15
|
+
"README.md",
|
|
16
|
+
".gitignore",
|
|
17
|
+
".github/RELEASE_NOTES.template.md",
|
|
18
|
+
".github/labeler.yml",
|
|
19
|
+
".github/dependabot.yml",
|
|
20
|
+
".github/keylabeler.yml",
|
|
21
|
+
".github/ISSUE_TEMPLATE/config.yml",
|
|
22
|
+
".github/ISSUE_TEMPLATE/bug.yml",
|
|
23
|
+
".github/ISSUE_TEMPLATE/feature.yml",
|
|
24
|
+
".github/workflows/dco-merge-queue.yml",
|
|
25
|
+
".github/workflows/ci.yaml",
|
|
26
|
+
".github/workflows/isort-migration.yaml",
|
|
27
|
+
".github/workflows/release.yaml",
|
|
28
|
+
".github/workflows/labeler.yml",
|
|
29
|
+
".github/workflows/repo-config-migration.yaml",
|
|
30
|
+
".github/workflows/auto-dependabot.yaml",
|
|
31
|
+
".github/workflows/black-migration.yaml",
|
|
32
|
+
".github/workflows/release-notes-check.yml",
|
|
33
|
+
".github/workflows/ci-pr.yaml",
|
|
34
|
+
"tests/test_frequenz_cs_reporting.py",
|
|
17
35
|
"toml_directory/__init__.py",
|
|
18
|
-
"
|
|
19
|
-
"src/frequenz/cs_reporting/ui_resources.py",
|
|
20
|
-
"src/frequenz/cs_reporting/constants.py",
|
|
36
|
+
".streamlit/config.toml",
|
|
21
37
|
"src/frequenz/cs_reporting/py.typed",
|
|
22
38
|
"src/frequenz/cs_reporting/__init__.py",
|
|
23
|
-
"src/frequenz/cs_reporting/
|
|
24
|
-
"src/frequenz/cs_reporting/
|
|
25
|
-
"src/frequenz/cs_reporting/
|
|
26
|
-
"src/frequenz/cs_reporting/
|
|
39
|
+
"src/frequenz/cs_reporting/ui_resources.py",
|
|
40
|
+
"src/frequenz/cs_reporting/conftest.py",
|
|
41
|
+
"src/frequenz/cs_reporting/constants.py",
|
|
42
|
+
"src/frequenz/cs_reporting/utils/__init__.py",
|
|
27
43
|
"src/frequenz/cs_reporting/utils/env.py",
|
|
28
44
|
"src/frequenz/cs_reporting/utils/time.py",
|
|
29
|
-
"src/frequenz/cs_reporting/
|
|
30
|
-
"src/frequenz/cs_reporting/
|
|
45
|
+
"src/frequenz/cs_reporting/app_pages/__init__.py",
|
|
46
|
+
"src/frequenz/cs_reporting/app_pages/solar.py",
|
|
47
|
+
"src/frequenz/cs_reporting/app_pages/reporting.py",
|
|
48
|
+
"src/frequenz/cs_reporting/app_pages/home.py",
|
|
49
|
+
"src/frequenz/cs_reporting/services/__init__.py",
|
|
50
|
+
"src/frequenz/cs_reporting/services/client_factory.py",
|
|
51
|
+
"src/frequenz/cs_reporting/services/solar_workflow.py",
|
|
52
|
+
"src/frequenz/cs_reporting/services/data_service.py",
|
|
53
|
+
"src/frequenz/cs_reporting/styles/plot_card.css",
|
|
54
|
+
"src/frequenz/cs_reporting/styles/home.css",
|
|
55
|
+
"src/frequenz/cs_reporting/styles/dashboard.css",
|
|
56
|
+
"src/frequenz/cs_reporting/styles/kpi.css",
|
|
57
|
+
"src/frequenz/cs_reporting/views/metric_renderers.py",
|
|
58
|
+
"src/frequenz/cs_reporting/views/sections.py",
|
|
59
|
+
"src/frequenz/cs_reporting/views/plot_renderers.py",
|
|
60
|
+
"src/frequenz/cs_reporting/views/__init__.py",
|
|
61
|
+
"src/frequenz/cs_reporting/views/solar_results.py",
|
|
62
|
+
"src/frequenz/cs_reporting/views/dashboard.py",
|
|
63
|
+
"src/frequenz/cs_reporting/views/table_renderers.py",
|
|
64
|
+
"src/frequenz/cs_reporting/templates/home_stats.html",
|
|
65
|
+
"src/frequenz/cs_reporting/templates/home_hero.html",
|
|
31
66
|
"src/frequenz/cs_reporting/templates/home_feature_grid.html",
|
|
67
|
+
"src/frequenz/cs_reporting/templates/dashboard_section_divider.html",
|
|
32
68
|
"src/frequenz/cs_reporting/templates/home_feature_item.html",
|
|
33
|
-
"src/frequenz/cs_reporting/templates/home_hero.html",
|
|
34
|
-
"src/frequenz/cs_reporting/templates/home_stats.html",
|
|
35
69
|
"src/frequenz/cs_reporting/templates/home_logo.html",
|
|
36
70
|
"src/frequenz/cs_reporting/templates/home_stat_item.html",
|
|
37
|
-
"src/frequenz/cs_reporting/templates/
|
|
38
|
-
"src/frequenz/cs_reporting/
|
|
39
|
-
"src/frequenz/cs_reporting/
|
|
40
|
-
"src/frequenz/cs_reporting/
|
|
41
|
-
"src/frequenz/cs_reporting/
|
|
42
|
-
"src/frequenz/cs_reporting/components/
|
|
71
|
+
"src/frequenz/cs_reporting/templates/home_footer.html",
|
|
72
|
+
"src/frequenz/cs_reporting/rep_cs_core/page_spec.py",
|
|
73
|
+
"src/frequenz/cs_reporting/rep_cs_core/config.py",
|
|
74
|
+
"src/frequenz/cs_reporting/rep_cs_core/__init__.py",
|
|
75
|
+
"src/frequenz/cs_reporting/components/plot_charts.py",
|
|
76
|
+
"src/frequenz/cs_reporting/components/__init__.py",
|
|
43
77
|
"src/frequenz/cs_reporting/components/tables.py",
|
|
78
|
+
"src/frequenz/cs_reporting/components/sidebar_inputs.py",
|
|
44
79
|
"src/frequenz/cs_reporting/components/ui.py",
|
|
45
80
|
"src/frequenz/cs_reporting/components/inputs.py",
|
|
46
|
-
"src/frequenz/cs_reporting/components/plot_charts.py",
|
|
47
|
-
"src/frequenz/cs_reporting/components/__init__.py",
|
|
48
|
-
"src/frequenz/cs_reporting/app_pages/home.py",
|
|
49
|
-
"src/frequenz/cs_reporting/app_pages/reporting.py",
|
|
50
|
-
"src/frequenz/cs_reporting/app_pages/solar.py",
|
|
51
|
-
"src/frequenz/cs_reporting/app_pages/__init__.py",
|
|
52
81
|
"src/frequenz/cs_reporting/assets/neustrom_logo.png",
|
|
53
|
-
"src/frequenz/cs_reporting/assets/neustrom_background.png",
|
|
54
82
|
"src/frequenz/cs_reporting/assets/__init__.py",
|
|
55
|
-
"src/frequenz/cs_reporting/
|
|
56
|
-
"src/frequenz/cs_reporting/rep_cs_core/page_spec.py",
|
|
57
|
-
"src/frequenz/cs_reporting/rep_cs_core/__init__.py",
|
|
58
|
-
"src/frequenz/cs_reporting/views/plot_renderers.py",
|
|
59
|
-
"src/frequenz/cs_reporting/views/metric_renderers.py",
|
|
60
|
-
"src/frequenz/cs_reporting/views/table_renderers.py",
|
|
61
|
-
"src/frequenz/cs_reporting/views/sections.py",
|
|
62
|
-
"src/frequenz/cs_reporting/views/solar_results.py",
|
|
63
|
-
"src/frequenz/cs_reporting/views/dashboard.py",
|
|
64
|
-
"src/frequenz/cs_reporting/views/__init__.py",
|
|
65
|
-
".github/labeler.yml",
|
|
66
|
-
".github/dependabot.yml",
|
|
67
|
-
".github/keylabeler.yml",
|
|
68
|
-
".github/RELEASE_NOTES.template.md",
|
|
69
|
-
".github/workflows/isort-migration.yaml",
|
|
70
|
-
".github/workflows/labeler.yml",
|
|
71
|
-
".github/workflows/repo-config-migration.yaml",
|
|
72
|
-
".github/workflows/ci-pr.yaml",
|
|
73
|
-
".github/workflows/ci.yaml",
|
|
74
|
-
".github/workflows/black-migration.yaml",
|
|
75
|
-
".github/workflows/dco-merge-queue.yml",
|
|
76
|
-
".github/workflows/release-notes-check.yml",
|
|
77
|
-
".github/workflows/auto-dependabot.yaml",
|
|
78
|
-
".github/workflows/release.yaml",
|
|
79
|
-
".github/ISSUE_TEMPLATE/config.yml",
|
|
80
|
-
".github/ISSUE_TEMPLATE/feature.yml",
|
|
81
|
-
".github/ISSUE_TEMPLATE/bug.yml",
|
|
82
|
-
".streamlit/config.toml",
|
|
83
|
-
"tests/test_frequenz_cs_reporting.py",
|
|
84
|
-
"docs/SUMMARY.md",
|
|
83
|
+
"src/frequenz/cs_reporting/assets/neustrom_background.png",
|
|
85
84
|
"docs/CONTRIBUTING.md",
|
|
85
|
+
"docs/SUMMARY.md",
|
|
86
86
|
"docs/index.md",
|
|
87
|
-
"docs/_img/logo.png",
|
|
88
87
|
"docs/_css/mkdocstrings.css",
|
|
89
88
|
"docs/_css/style.css",
|
|
90
|
-
"docs/
|
|
91
|
-
"docs/_overrides/main.html"
|
|
89
|
+
"docs/_img/logo.png",
|
|
90
|
+
"docs/_overrides/main.html",
|
|
91
|
+
"docs/_scripts/mkdocstrings_autoapi.py"
|
|
92
92
|
]
|
|
93
93
|
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
# Frequenz CS Reporting Library Release Notes
|
|
2
|
-
|
|
3
|
-
## Summary
|
|
4
|
-
|
|
5
|
-
## Upgrading
|
|
6
|
-
|
|
7
|
-
- Updating the minimum frequenz-lib-notebooks requirement to v0.16.0
|
|
8
|
-
|
|
9
|
-
## New Features
|
|
10
|
-
|
|
11
|
-
- Update the radio button navigation for streamlit in deepnote.
|
|
12
|
-
- Add KWK aliases in the line plot.
|
|
13
|
-
- Update the KPIs to german format.
|
|
14
|
-
`- Replace the solar monitoring `Produktionsstatistiken` table with the
|
|
15
|
-
`MicrogridOverviewDashboard` view from `frequenz.lib.notebooks`.
|
|
16
|
-
|
|
17
|
-
## Bug Fixes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/conftest.py
RENAMED
|
File without changes
|
{frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/constants.py
RENAMED
|
File without changes
|
{frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/py.typed
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/styles/kpi.css
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/utils/env.py
RENAMED
|
File without changes
|
{frequenz_cs_reporting-0.4.0 → frequenz_cs_reporting-0.4.2}/src/frequenz/cs_reporting/utils/time.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|