Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion data/config/mosquitto/public/default-dynamic-security.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
"anonymousGroup": "anonymous",
"roles": [
{
"rolename": "openwb-version:3",
"rolename": "openwb-version:4",
"textname": "openWB Versionsnummer",
"textdescription": "Diese Rolle ist ein Platzhalter für die openWB Versionsnummer und wird automatisch aktualisiert. Sie hat keine direkten Berechtigungen.",
"acls": []
Expand Down Expand Up @@ -291,6 +291,12 @@
"topic": "openWB/vehicle/+/name",
"priority": 0,
"allow": true
},
{
"acltype": "publishClientReceive",
"topic": "openWB/vehicle/+/color",
"priority": 0,
"allow": true
}
]
},
Expand Down Expand Up @@ -1780,6 +1786,12 @@
"priority": 0,
"allow": true
},
{
"acltype": "publishClientSend",
"topic": "openWB/set/vehicle/+/color",
"priority": 0,
"allow": true
},
{
"acltype": "publishClientSend",
"topic": "openWB/set/vehicle/+/charge_template",
Expand Down Expand Up @@ -1858,6 +1870,12 @@
"priority": 0,
"allow": true
},
{
"acltype": "publishClientReceive",
"topic": "openWB/vehicle/+/color",
"priority": 0,
"allow": true
},
{
"acltype": "publishClientReceive",
"topic": "openWB/vehicle/+/charge_template",
Expand Down
15 changes: 9 additions & 6 deletions docs/samples/sample_modbus/sample_modbus/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ def __init__(self,
name: str = "Sample Speicher",
type: str = "bat",
id: int = 0,
configuration: SampleBatConfiguration = None) -> None:
super().__init__(name, type, id, configuration or SampleBatConfiguration())
configuration: SampleBatConfiguration = None,
**kwargs) -> None:
super().__init__(name, type, id, configuration or SampleBatConfiguration(), **kwargs)


@auto_str
Expand All @@ -54,8 +55,9 @@ def __init__(self,
name: str = "Sample Zähler",
type: str = "counter",
id: int = 0,
configuration: SampleCounterConfiguration = None) -> None:
super().__init__(name, type, id, configuration or SampleCounterConfiguration())
configuration: SampleCounterConfiguration = None,
**kwargs) -> None:
super().__init__(name, type, id, configuration or SampleCounterConfiguration(), **kwargs)


@auto_str
Expand All @@ -70,5 +72,6 @@ def __init__(self,
name: str = "Sample Wechselrichter",
type: str = "inverter",
id: int = 0,
configuration: SampleInverterConfiguration = None) -> None:
super().__init__(name, type, id, configuration or SampleInverterConfiguration())
configuration: SampleInverterConfiguration = None,
**kwargs) -> None:
super().__init__(name, type, id, configuration or SampleInverterConfiguration(), **kwargs)
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,9 @@ def __init__(self,
name: str = "Sample Speicher",
type: str = "bat",
id: int = 0,
configuration: SampleBatConfiguration = None) -> None:
super().__init__(name, type, id, configuration or SampleBatConfiguration())
configuration: SampleBatConfiguration = None,
**kwargs) -> None:
super().__init__(name, type, id, configuration or SampleBatConfiguration(), **kwargs)


@auto_str
Expand All @@ -53,8 +54,9 @@ def __init__(self,
name: str = "Sample Zähler",
type: str = "counter",
id: int = 0,
configuration: SampleCounterConfiguration = None) -> None:
super().__init__(name, type, id, configuration or SampleCounterConfiguration())
configuration: SampleCounterConfiguration = None,
**kwargs) -> None:
super().__init__(name, type, id, configuration or SampleCounterConfiguration(), **kwargs)


@auto_str
Expand All @@ -69,5 +71,6 @@ def __init__(self,
name: str = "Sample Wechselrichter",
type: str = "inverter",
id: int = 0,
configuration: SampleInverterConfiguration = None) -> None:
super().__init__(name, type, id, configuration or SampleInverterConfiguration())
configuration: SampleInverterConfiguration = None,
**kwargs) -> None:
super().__init__(name, type, id, configuration or SampleInverterConfiguration(), **kwargs)
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,9 @@ def __init__(self,
name: str = "Sample Speicher",
type: str = "bat",
id: int = 0,
configuration: SampleBatConfiguration = None) -> None:
super().__init__(name, type, id, configuration or SampleBatConfiguration())
configuration: SampleBatConfiguration = None,
**kwargs) -> None:
super().__init__(name, type, id, configuration or SampleBatConfiguration(), **kwargs)


@auto_str
Expand All @@ -53,8 +54,9 @@ def __init__(self,
name: str = "Sample Zähler",
type: str = "counter",
id: int = 0,
configuration: SampleCounterConfiguration = None) -> None:
super().__init__(name, type, id, configuration or SampleCounterConfiguration())
configuration: SampleCounterConfiguration = None,
**kwargs) -> None:
super().__init__(name, type, id, configuration or SampleCounterConfiguration(), **kwargs)


@auto_str
Expand All @@ -69,5 +71,6 @@ def __init__(self,
name: str = "Sample Wechselrichter",
type: str = "inverter",
id: int = 0,
configuration: SampleInverterConfiguration = None) -> None:
super().__init__(name, type, id, configuration or SampleInverterConfiguration())
configuration: SampleInverterConfiguration = None,
**kwargs) -> None:
super().__init__(name, type, id, configuration or SampleInverterConfiguration(), **kwargs)
1 change: 1 addition & 0 deletions packages/control/chargepoint/chargepoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ def get_chargepoint_config_default() -> dict:
"name": "neuer Ladepunkt",
"type": None,
"ev": 0,
"color": "#007bff",
"template": 0,
"connected_phases": 3,
"phase_1": 1,
Expand Down
1 change: 1 addition & 0 deletions packages/control/chargepoint/chargepoint_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ class Config:
configuration: Dict = field(default_factory=empty_dict_factory)
ev: int = 0
name: str = "neuer Ladepunkt"
color: str = "#007bff"
type: Optional[str] = None
Comment thread
benderl marked this conversation as resolved.
template: int = 0
connected_phases: int = 3
Expand Down
2 changes: 2 additions & 0 deletions packages/control/ev/ev.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ def get_vehicle_default() -> dict:
"charge_template": 0,
"ev_template": 0,
"name": "Fahrzeug",
"color": "#17a2b8",
"info": {
"manufacturer": None,
"model": None,
Expand Down Expand Up @@ -78,6 +79,7 @@ class EvData:
charge_template: int = field(default=0, metadata={"topic": "charge_template"})
ev_template: int = field(default=0, metadata={"topic": "ev_template"})
name: str = field(default="neues Fahrzeug", metadata={"topic": "name"})
color: str = field(default="#17a2b8", metadata={"topic": "color"})
tag_id: List[str] = field(default_factory=empty_list_factory, metadata={
Comment thread
benderl marked this conversation as resolved.
"topic": "tag_id"})
get: Get = field(default_factory=get_factory)
Expand Down
161 changes: 96 additions & 65 deletions packages/helpermodules/measurement_logging/write_log.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,83 +14,86 @@
from helpermodules import timecheck
from helpermodules.utils.json_file_handler import write_and_check
from helpermodules.utils.topic_parser import decode_payload, get_index
from modules.common.utils.component_parser import get_component_name_by_id
from modules.common.utils.component_parser import get_component_name_by_id, get_component_color_by_id

log = logging.getLogger(__name__)

# erstellt für jeden Tag eine Datei, die die Daten für den Langzeitgraph enthält.
# Dazu werden alle 5 Min folgende Daten als json-Liste gespeichert:
# {"entries": [
# {
# "timestamp": int,
# "date": str,
# "prices": {
# "grid": Preis für Netzbezug,
# "pv": Preis für PV-Strom,
# "bat": Preis für Speicherstrom
# }
# "cp": {
# "cp1": {
# "imported": Zählerstand in Wh,
# "exported": Zählerstand in Wh
# }
# ... (dynamisch, je nach konfigurierter Anzahl)
# "all": {
# "imported": Zählerstand in Wh,
# "exported": Zählerstand in Wh
# }
# }
# "ev": {
# "ev1": {
# "soc": int in %
# {
# "entries": [
# {
# "timestamp": int,
# "date": str,
# "prices": {
# "grid": Preis für Netzbezug,
# "pv": Preis für PV-Strom,
# "bat": Preis für Speicherstrom
# }
# ... (dynamisch, je nach konfigurierter Anzahl)
# }
# "counter": {
# "counter0": {
# "grid": bool,
# "imported": Wh,
# "exported": Wh
# "cp": {
# "cp1": {
# "imported": Zählerstand in Wh,
# "exported": Zählerstand in Wh
# }
# ... (dynamisch, je nach konfigurierter Anzahl)
# "all": {
# "imported": Zählerstand in Wh,
# "exported": Zählerstand in Wh
# }
# }
# ... (dynamisch, je nach konfigurierter Anzahl)
# }
# "pv": {
# "all": {
# "exported": Wh
# "ev": {
# "ev1": {
# "soc": int in %
# }
# ... (dynamisch, je nach konfigurierter Anzahl)
# }
# "pv0": {
# "exported": Wh
# "counter": {
# "counter0": {
# "grid": bool,
# "imported": Wh,
# "exported": Wh
# }
# ... (dynamisch, je nach konfigurierter Anzahl)
# }
# ... (dynamisch, je nach konfigurierter Anzahl)
# }
# "bat": {
# "all": {
# "imported": Wh,
# "exported": Wh,
# "soc": int in %
# "pv": {
# "all": {
# "exported": Wh
# }
# "pv0": {
# "exported": Wh
# }
# ... (dynamisch, je nach konfigurierter Anzahl)
# }
# "bat0": {
# "imported": Wh,
# "exported": Wh,
# "soc": int in %
# "bat": {
# "all": {
# "imported": Wh,
# "exported": Wh,
# "soc": int in %
# }
# "bat0": {
# "imported": Wh,
# "exported": Wh,
# "soc": int in %
# }
# ... (dynamisch, je nach konfigurierter Anzahl)
# }
# ... (dynamisch, je nach konfigurierter Anzahl)
# }
# "sh": {
# "sh1": {
# "exported": Wh,
# "imported": Wh,
# wenn konfiguriert:
# "temp1": int in °C,
# "temp2": int in °C,
# "temp3": int in °C
# "sh": {
# "sh1": {
# "exported": Wh,
# "imported": Wh,
# wenn konfiguriert:
# "temp1": int in °C,
# "temp2": int in °C,
# "temp3": int in °C
# },
# ... (dynamisch, je nach Anzahl konfigurierter Geräte)
# },
# ... (dynamisch, je nach Anzahl konfigurierter Geräte)
# },
# "hc": {"all": {"imported": Wh # Hausverbrauch}}
# }],
# "names": "names": {"sh1": "", "cp1": "", "counter2": "", "pv3": ""}
# }
# "hc": {"all": {"imported": Wh # Hausverbrauch}}
# }
# ],
# "names": {"cp1": "", "counter2": "", "pv3": ""},
# "colors": {"cp1": "", "counter2": "", "pv3": ""},
# }


class LogType(Enum):
Expand Down Expand Up @@ -165,6 +168,7 @@ def save_log(log_type: LogType):
entries = content["entries"]
entries.append(new_entry)
content["names"] = get_names(content["entries"][-1], sh_log_data.sh_names)
content["colors"] = get_colors(content["entries"][-1])
write_and_check(filepath, content)
return content["entries"]
except Exception:
Expand Down Expand Up @@ -357,3 +361,30 @@ def get_names(elements: Dict, sh_names: Dict, valid_names: Optional[Dict] = None
except (ValueError, KeyError, AttributeError):
names.update({entry: entry})
return names


def get_colors(elements: Dict) -> Dict:
""" Ermittelt die Farben der Fahrzeuge, Ladepunkte und Komponenten, welche
in elements vorhanden sind und gibt diese als Dictionary zurück.
Parameter
---------
elements: dict
Dictionary, das die Messwerte enthält.
"""
Comment on lines +366 to +373
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get_colors() is new logic that affects the persisted measurement log format (content["colors"]). This module already has unit tests (write_log_test.py) for related helpers like get_names, but there are no tests for get_colors (including fallbacks to default color when data lookups fail). Add tests similar to test_get_names by monkeypatching get_component_color_by_id and/or data.data accessors.

Copilot uses AI. Check for mistakes.
colors = {}
for group in elements.items():
if group[0] not in ("ev", "cp", "counter", "pv", "bat"):
continue
for entry in group[1]:
Comment thread
benderl marked this conversation as resolved.
if "all" != entry:
try:
if "ev" in entry:
colors.update({entry: data.data.ev_data[entry].data.color})
elif "cp" in entry:
colors.update({entry: data.data.cp_data[entry].data.config.color})
else:
id = entry.strip(string.ascii_letters)
colors.update({entry: get_component_color_by_id(int(id))})
except (ValueError, KeyError, AttributeError):
colors.update({entry: "#000000"})
return colors
2 changes: 2 additions & 0 deletions packages/helpermodules/setdata.py
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,8 @@ def process_vehicle_topic(self, msg: mqtt.MQTTMessage):
try:
if "/name" in msg.topic:
self._validate_value(msg, str)
elif "/color" in msg.topic:
self._validate_value(msg, str)
elif "/info" in msg.topic:
self._validate_value(msg, "json")
elif "openWB/set/vehicle/set/vehicle_update_completed" in msg.topic:
Expand Down
Loading
Loading