Skip to content

Commit

Permalink
Merge pull request #1070 from openWB/feature_rse
Browse files Browse the repository at this point in the history
Feature rse
  • Loading branch information
LKuemmel authored Aug 3, 2023
2 parents 95b1b85 + 06832d6 commit e480199
Show file tree
Hide file tree
Showing 10 changed files with 148 additions and 61 deletions.
1 change: 1 addition & 0 deletions data/config/configuration.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"openwb-version": 1, "ripple_control_receiver_configured": false, "max_c_socket": 32}
14 changes: 14 additions & 0 deletions packages/control/general.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
from typing import List, Optional

from control import data
from helpermodules import hardware_configuration
from helpermodules.pub import Pub
from helpermodules import timecheck
from modules import ripple_control_receiver

log = logging.getLogger(__name__)

Expand Down Expand Up @@ -179,3 +181,15 @@ def grid_protection(self):
"openWB/set/general/grid_protection_random_stop", 0)
except Exception:
log.exception("Fehler im General-Modul")

def check_ripple_control_receiver(self):
configured = hardware_configuration.get_hardware_configuration_setting(
"ripple_control_receiver_configured")
Pub().pub("openWB/set/general/ripple_control_receiver/configured", configured)
self.data.ripple_control_receiver.configured = configured
if configured:
r1_active, r2_active = ripple_control_receiver.read()
self.data.ripple_control_receiver.r1_active = r1_active
Pub().pub("openWB/set/general/ripple_control_receiver/r1_active", r1_active)
self.data.ripple_control_receiver.r2_active = r2_active
Pub().pub("openWB/set/general/ripple_control_receiver/r2_active", r2_active)
1 change: 1 addition & 0 deletions packages/control/prepare.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ def setup_algorithm(self) -> None:
""" bereitet die Daten für den Algorithmus vor und startet diesen.
"""
try:
data.data.general_data.check_ripple_control_receiver()
for cp in data.data.cp_data.values():
cp.reset_values_at_start()
data.data.bat_all_data.setup_bat()
Expand Down
135 changes: 97 additions & 38 deletions packages/helpermodules/data_migration/data_migration.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@
import shutil
import tarfile
from threading import Thread
from typing import Callable, Dict, List, Union
from typing import Callable, Dict, List, Optional, Union

from control import data, ev
from dataclass_utils import dataclass_from_dict
from helpermodules.data_migration.id_mapping import MapId
from helpermodules.hardware_configuration import update_hardware_configuration
from helpermodules.measurement_log import LegacySmartHomeLogData, get_names, get_totals, string_to_float, string_to_int
from helpermodules.utils import thread_handler
from helpermodules.pub import Pub
Expand Down Expand Up @@ -65,19 +66,44 @@ def __len__(self):


class MigrateData:
MAJOR_VERSION = 1
MINOR_VERSION = 9
PATCH_VERSION = 303
BACKUP_DATA_PATH = "./data/data_migration/var/www/html/openWB/web/logging/data"

def __init__(self, id_map: Dict) -> None:
self.id_map = dataclass_from_dict(MapId, id_map)

def migrate(self):
self.extract_files("ladelog")
self.extract_files("daily")
self.extract_files("monthly")
thread_handler(self.convert_csv_to_json_chargelog(), None)
thread_handler(self.convert_csv_to_json_measurement_log("daily"), None)
thread_handler(self.convert_csv_to_json_measurement_log("monthly"), None)
self.move_serial_number_cloud_data()
try:
self._extract()
self._check_version()
thread_handler(self.convert_csv_to_json_chargelog(), None)
thread_handler(self.convert_csv_to_json_measurement_log("daily"), None)
thread_handler(self.convert_csv_to_json_measurement_log("monthly"), None)
self._migrate_settings_from_openwb_conf()
except Exception as e:
raise e
finally:
self._remove_migration_data()

def _check_version(self):
with open("./data/data_migration/var/www/html/openWB/web/version") as f:
version = f.read().replace("\n", "")
sub_version = version.split(".")
if not (int(sub_version[0]) > self.MAJOR_VERSION or (
(int(sub_version[0]) == self.MAJOR_VERSION) and (
(int(sub_version[1]) > self.MINOR_VERSION) or
((int(sub_version[1]) == self.MINOR_VERSION) and
(int(sub_version[2]) >= self.PATCH_VERSION))
)
)):
self._remove_migration_data()
raise ValueError(f"Das Backup für die Datenübernahme muss mindestens mit Version {self.MAJOR_VERSION}."
f"{self.MINOR_VERSION}.{self.PATCH_VERSION} erstellt worden sein. "
f"Backup-Version ist {version}.")

def _remove_migration_data(self):
shutil.rmtree("./data/data_migration/var")
os.remove("./data/data_migration/data_migration.tar.gz")

Expand All @@ -89,11 +115,19 @@ def _file_to_extract_generator(self, members, log_folder_name: str):
if tarinfo.name.startswith(f"var/www/html/openWB/web/logging/data/{log_folder_name}"):
yield tarinfo

def extract_files(self, log_folder_name: str):
def _extract_files(self, log_folder_name: str):
with tarfile.open('./data/data_migration/data_migration.tar.gz') as tar:
tar.extractall(members=self._file_to_extract_generator(
tar, log_folder_name), path="./data/data_migration")

def _extract(self):
self._extract_files("ladelog")
self._extract_files("daily")
self._extract_files("monthly")
with tarfile.open('./data/data_migration/data_migration.tar.gz') as tar:
tar.extract(member="var/www/html/openWB/openwb.conf", path="./data/data_migration")
tar.extract(member="var/www/html/openWB/web/version", path="./data/data_migration")

def convert_csv_to_json_chargelog(self) -> List[Thread]:
""" konvertiert die alten Lade-Log-Dateien in das neue Format für 2.x.
"""
Expand Down Expand Up @@ -487,37 +521,62 @@ def _monthly_log_entry(self, file: str):
log.exception(f"Fehler beim Konvertieren des Monats-Logs vom {file}, Reihe {row}")
return entries

def move_serial_number_cloud_data(self) -> None:
def strip_openwb_conf_entry(entry: str, key: str) -> str:
value = entry.replace(f"{key}=", "")
return value.rstrip("\n")
with tarfile.open('./data/data_migration/data_migration.tar.gz') as tar:
tar.extract(member="var/www/html/openWB/openwb.conf", path="./data/data_migration")
with open("./data/data_migration/var/www/html/openWB/openwb.conf", "r") as file:
serial_number = ""
openwb_conf = file.readlines()
for line in openwb_conf:
if "snnumber" in line:
serial_number = strip_openwb_conf_entry(line, "snnumber")
break
else:
log.debug("Keine Seriennummer gefunden.")
with open("/home/openwb/snnumber", "w") as file:
file.write(f"snnumber={serial_number}")
def _get_openwb_conf_value(self, key: str) -> Optional[str]:
value = None
for line in self.openwb_conf:
if key in line:
raw_value = line.replace(f"{key}=", "")
value = raw_value.rstrip("\n")
break
return value

def _migrate_settings_from_openwb_conf(self):
with open("./data/data_migration/var/www/html/openWB/openwb.conf", "r") as file:
cloud_user = ""
cloud_pw = ""
openwb_conf = file.readlines()
for line in openwb_conf:
if "clouduser" in line:
cloud_user = strip_openwb_conf_entry(line, "clouduser")
elif "cloudpw" in line:
cloud_pw = strip_openwb_conf_entry(line, "cloudpw")
if cloud_user == "":
log.debug("Keine Cloud-Zugangsdaten gefunden.")
Pub().pub("openWB/set/command/data_migration/todo",
{"command": "connectCloud", "data": {"username": cloud_user, "password": cloud_pw, "partner": 0}})
self.openwb_conf = file.readlines()
self._move_serial_number()
self._move_cloud_data()
self._move_rse()
self._move_max_c_socket()
self._move_pddate()

def _move_serial_number(self) -> None:
serial_number = self._get_openwb_conf_value("snnumber")
if serial_number:
with open("/home/openwb/snnumber", "w") as file:
file.write(f"snnumber={serial_number}")
else:
log.debug("Keine Seriennummer gefunden.")

def _move_cloud_data(self) -> None:
cloud_user = self._get_openwb_conf_value("clouduser")
cloud_pw = self._get_openwb_conf_value("cloudpw")
if cloud_user is not None and cloud_pw is not None:
Pub().pub("openWB/set/command/data_migration/todo",
{"command": "connectCloud", "data": {"username": cloud_user, "password": cloud_pw, "partner": 0}})
else:
log.debug("Keine Cloud-Zugangsdaten gefunden.")

def _move_rse(self) -> None:
rse = bool(self._get_openwb_conf_value("rseenabled"))
if rse is None:
log.debug("Keine Rundsteuerempfänger-Konfiguration gefunden. Setze auf False.")
rse = False
update_hardware_configuration({"ripple_control_receiver_configured": rse})

def _move_max_c_socket(self):
max_c_socket = self._get_openwb_conf_value("ppbuchse")
if max_c_socket is None:
log.debug("Keine max_c_socket-Konfiguration gefunden. Setze auf False.")
max_c_socket = 32
update_hardware_configuration({"max_c_socket": max_c_socket})

def _move_pddate(self) -> None:
pddate = self._get_openwb_conf_value("pddate")
if pddate is not None:
with open("/home/openwb/pddate", "w") as file:
file.write(f"pddate={pddate}")
else:
log.debug("Kein Produktionsdatum gefunden.")

NOT_CONFIGURED = " wurde in openWB software2 nicht konfiguriert."

Expand Down
15 changes: 15 additions & 0 deletions packages/helpermodules/hardware_configuration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import json
from typing import Dict


def update_hardware_configuration(new_setting: Dict) -> None:
with open("/home/openwb/configuration.json", "r") as f:
data = json.loads(f.read())
with open("/home/openwb/configuration.json", "w") as f:
data.update(new_setting)
f.write(json.dumps(data))


def get_hardware_configuration_setting(name: str):
with open("/home/openwb/configuration.json", "r") as f:
return json.loads(f.read())[name]
2 changes: 1 addition & 1 deletion packages/helpermodules/subdata.py
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,7 @@ def process_general_topic(self, var: general.General, msg: mqtt.MQTTMessage):
try:
if re.search("/general/", msg.topic) is not None:
if re.search("/general/ripple_control_receiver/", msg.topic) is not None:
self.set_json_payload_class(var.data.ripple_control_receiver, msg)
return
elif re.search("/general/chargemode_config/", msg.topic) is not None:
if re.search("/general/chargemode_config/pv_charging/", msg.topic) is not None:
self.set_json_payload_class(var.data.chargemode_config.pv_charging, msg)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@
except ImportError:
log.info("failed to import RPi.GPIO! maybe we are not running on a pi")

SOCKET_MAX_CURRENT: int = 16


class UpdateValues:
def __init__(self, local_charge_point_num: int, parent_ip: str, parent_cp: str) -> None:
Expand Down Expand Up @@ -198,7 +196,7 @@ def __init__(self,
self.local_charge_point_num = local_charge_point_num
if local_charge_point_num == 0:
if mode == InternalChargepointMode.SOCKET.value:
self.module = Socket(SOCKET_MAX_CURRENT, local_charge_point_num, client_handler, global_data.parent_ip)
self.module = Socket(local_charge_point_num, client_handler, global_data.parent_ip)
else:
self.module = chargepoint_module.ChargepointModule(
local_charge_point_num, client_handler, global_data.parent_ip)
Expand Down
6 changes: 3 additions & 3 deletions packages/modules/internal_chargepoint_handler/socket.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import logging
import time
from typing import Callable, Tuple
from helpermodules.hardware_configuration import get_hardware_configuration_setting

from modules.common.component_context import SingleComponentUpdateContext
from modules.common.component_state import ChargepointState
Expand Down Expand Up @@ -45,12 +46,11 @@ class ActorState(IntEnum):

class Socket(ChargepointModule):
def __init__(self,
socket_max_current: int,
local_charge_point_num: int,
client_handler: ClientHandler,
parent_hostname: str) -> None:
log.debug("Konfiguration als Buchse.")
self.socket_max_current = socket_max_current
self.socket_max_current = get_hardware_configuration_setting("max_c_socket")
log.debug(f"Konfiguration als Buchse mit maximal {self.socket_max_current}A Ladestrom je Phase.")
super().__init__(local_charge_point_num, client_handler, parent_hostname)

def set_current(self, current: float) -> None:
Expand Down
26 changes: 10 additions & 16 deletions packages/modules/ripple_control_receiver.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import logging
import time
from helpermodules.pub import Pub
from typing import Tuple

log = logging.getLogger(__name__)
has_gpio = True
Expand All @@ -13,25 +12,20 @@
log.warning("RSE disabled!")


def read():
def read() -> Tuple[bool, bool]:
rse1: bool = False
rse2: bool = False

if has_gpio:
GPIO.setmode(GPIO.BCM)
GPIO.setup(8, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(9, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(24, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(21, GPIO.IN, pull_up_down=GPIO.PUD_UP)

try:
button1_state = GPIO.input(8)
button2_state = GPIO.input(9)

time.sleep(10.2)

rse1 = not button1_state
rse2 = not button2_state
rse1 = GPIO.input(24) == GPIO.LOW
rse2 = GPIO.input(21) == GPIO.LOW
except Exception:
GPIO.cleanup()
log.exception()
Pub().pub("openWB/set/general/ripple_control_receiver/r1_active", rse1)
Pub().pub("openWB/set/general/ripple_control_receiver/r2_active", rse2)
log.exception("Fehler beim Auslesen der Rundsteuer-Kontakte.")
log.debug(f"RSE1-Status: {rse1}, RSE2-Satus: {rse2}")
return rse1, rse2
5 changes: 5 additions & 0 deletions runs/atreboot.sh
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,11 @@ chmod 666 "$LOGFILE"
fi
echo "mosquitto done"

# check for home configuration
if [[ ! -f "/home/openwb/configuration.json" ]]; then
sudo cp -a "${OPENWBBASEDIR}/data/config/configuration.json" "/home/openwb/configuration.json"
fi

# check for python dependencies
echo "install required python packages with 'pip3'..."
pip3 install -r "${OPENWBBASEDIR}/requirements.txt"
Expand Down

0 comments on commit e480199

Please sign in to comment.