From 0102eeae8df5c93bf623917459b215b4985511dc Mon Sep 17 00:00:00 2001
From: Julian Leucker <leuckerj@gmail.com>
Date: Fri, 10 Jul 2020 18:11:37 +0200
Subject: [PATCH 1/4] Add a YAML-Button

---
 fpga_device_manager/res/ui/main.ui         |  7 ++++
 fpga_device_manager/windows/main_window.py | 39 ++++++++++++++++++++++
 2 files changed, 46 insertions(+)

diff --git a/fpga_device_manager/res/ui/main.ui b/fpga_device_manager/res/ui/main.ui
index 6c15309..4714cac 100755
--- a/fpga_device_manager/res/ui/main.ui
+++ b/fpga_device_manager/res/ui/main.ui
@@ -340,6 +340,13 @@
            </property>
           </widget>
          </item>
+         <item row="1" column="1">
+          <widget class="QPushButton" name="btn_yaml">
+           <property name="text">
+            <string>Export YAML…</string>
+           </property>
+          </widget>
+         </item>
         </layout>
        </widget>
       </item>
diff --git a/fpga_device_manager/windows/main_window.py b/fpga_device_manager/windows/main_window.py
index 7854b82..c923ac7 100755
--- a/fpga_device_manager/windows/main_window.py
+++ b/fpga_device_manager/windows/main_window.py
@@ -90,6 +90,7 @@ class MainWindow(BaseWindow):
         """Updates the window's buttons."""
         self.btn_save.setEnabled(Config.outputs().has_devices() or Config.inputs().has_devices())
         self.btn_export.setEnabled(Config.outputs().has_devices() and Config.inputs().has_devices())
+        self.btn_yaml.setEnabled(Config.outputs().has_devices() and Config.inputs().has_devices())
         self.btn_clear.setEnabled(Config.outputs().has_devices() or Config.inputs().has_devices())
         self.btn_add_device.setEnabled(not Config.outputs().has_max_devices())
         self.btn_add_input.setEnabled(not Config.inputs().has_max_devices())
@@ -152,6 +153,21 @@ class MainWindow(BaseWindow):
             Popup.alert(title=f"Failed to export",
                         message=str(e))
 
+    def export_yaml(self, file_path: str) -> None:
+        """
+        Exports the current device configuration to a YAML Home Assistant configuration.
+        :param file_path: Path to output the YAML file to
+        """
+
+        try:
+            Config.export_yaml(file_path)
+            Popup.info(title="Successfully generated",
+                       message=f"The YAML configuration file has been successfully written to {file_path}.")
+
+        except InvalidConfigError as e:
+            Popup.alert(title=f"YAML generation failed",
+                        message=str(e))
+
     def reset(self) -> None:
         """Resets the configuration and window."""
         Config.clear()
@@ -310,3 +326,26 @@ class MainWindow(BaseWindow):
                         message="\n".join(e.errors),
                         additional_text="Please check your configuration and try again.")
             return
+
+    @Slot()
+    def on_btn_yaml_clicked(self):
+        """Handler for clicking the YAML button. This performs some sanity checks on the current configuration,
+        and if passed opens a directory selection dialog for exporting the .yaml file for Home Assistant.
+        """
+        # Verify device settings
+        try:
+            Config.check()
+            file_path = QFileDialog.getSaveFileName(parent=self,
+                                                    caption="Generate YAML",
+                                                    dir="./generated/smarthome.yaml",
+                                                    filter="YAML files (*.yaml)"
+                                                    )
+
+            if file_path != '':
+                self.export_yaml(file_path)
+
+        except InvalidConfigError as e:
+            Popup.alert(title="YAML generation failed",
+                        message="\n".join(e.errors),
+                        additional_text="Please check your configuration and try again.")
+            return
-- 
GitLab


From 298793a610138d4b2b6ed6e50610e22398ef2e67 Mon Sep 17 00:00:00 2001
From: Julian Leucker <leuckerj@gmail.com>
Date: Fri, 10 Jul 2020 18:52:06 +0200
Subject: [PATCH 2/4] Update Config, create YAML

---
 fpga_device_manager/Config.py | 26 ++++++++++++++++++++++++++
 fpga_device_manager/hass.py   | 15 +++++++++++++++
 2 files changed, 41 insertions(+)
 create mode 100644 fpga_device_manager/hass.py

diff --git a/fpga_device_manager/Config.py b/fpga_device_manager/Config.py
index 50b9ee3..5f4fd73 100644
--- a/fpga_device_manager/Config.py
+++ b/fpga_device_manager/Config.py
@@ -188,3 +188,29 @@ def export(out_path: str) -> None:
         print(f"Writing to {filepath}...")
         with open(filepath, "w") as file:
             file.write(text)
+
+
+def export_yaml(out_file_path: str) -> None:
+    """
+    Exports the current device configuration to a Home Assistant YAML file.
+    :param out_file_path: Path to write the YAML file to
+    """
+
+    x = {
+            'alias': 'Rule 1 Light on in the evening',
+            'trigger': [
+                {'platform': 'sun', 'event': 'sunset', 'offset': '-01:00:00'},
+                {'platform': 'state', 'entity_id': 'all', 'to': 'home'}
+            ],
+            'condition': [
+                {'condition': 'state', 'entity_id': 'all', 'state': 'home'},
+                {'condition': 'time', 'after': '16:00:00', 'before': '23:00:00'}
+            ],
+            'action': {'service': 'homeassistant.turn_on', 'entity_id': 'group.living_room'}
+        },
+
+    # for filename, text in exports.items():
+    #     filepath = os.file_path.join(out_file_path, filename)
+    #     print(f"Writing to {filepath}...")
+    #     with open(filepath, "w") as file:
+    #         file.write(text)
diff --git a/fpga_device_manager/hass.py b/fpga_device_manager/hass.py
new file mode 100644
index 0000000..1083402
--- /dev/null
+++ b/fpga_device_manager/hass.py
@@ -0,0 +1,15 @@
+class Trigger:
+    pass
+
+
+class Action:
+    pass
+
+
+class Condition:
+    pass
+
+
+class Automation:
+    def __init__(self):
+        pass
-- 
GitLab


From 21b984d58c86700fd93bfa75b132f2b56a6e24ce Mon Sep 17 00:00:00 2001
From: Julian Leucker <leuckerj@gmail.com>
Date: Fri, 10 Jul 2020 19:28:07 +0200
Subject: [PATCH 3/4] Update Hass classes

---
 fpga_device_manager/hass.py | 33 +++++++++++++++++++++++++--------
 1 file changed, 25 insertions(+), 8 deletions(-)

diff --git a/fpga_device_manager/hass.py b/fpga_device_manager/hass.py
index 1083402..257f6ff 100644
--- a/fpga_device_manager/hass.py
+++ b/fpga_device_manager/hass.py
@@ -1,15 +1,32 @@
-class Trigger:
-    pass
+from typing import Iterable, Dict
+from dataclasses import dataclass
 
 
+@dataclass
 class Action:
-    pass
+    service: str
+    entity_id: str
 
 
-class Condition:
-    pass
+@dataclass
+class Automation:
+    alias: str
+    triggers: Iterable[Dict]
+    actions: Iterable[Action]
+    conditions: Iterable[Dict] = None
+    description: str = ""
 
+    @property
+    def dict(self):
+        dict_ = {"alias": self.alias,
+                 "triggers": self.triggers,
+                 "actions": [action.__dict__ for action in self.actions]
+                 }
 
-class Automation:
-    def __init__(self):
-        pass
+        if self.conditions:
+            dict_["conditions"] = self.conditions
+
+        if self.description:
+            dict_["description"] = self.description
+
+        return dict_
-- 
GitLab


From 2535603d122e1af0a5566446f3591aa21a92caed Mon Sep 17 00:00:00 2001
From: Julian Leucker <leuckerj@gmail.com>
Date: Mon, 3 Aug 2020 17:50:57 +0200
Subject: [PATCH 4/4] Work on YAML stuff

---
 fpga_device_manager/Config.py                  | 12 +++++++++++-
 fpga_device_manager/res/data/device_types.json |  3 ++-
 2 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/fpga_device_manager/Config.py b/fpga_device_manager/Config.py
index 5f4fd73..71f9167 100644
--- a/fpga_device_manager/Config.py
+++ b/fpga_device_manager/Config.py
@@ -13,6 +13,7 @@ from fpga_device_manager.Devices import Output
 from fpga_device_manager.Inputs import Input
 from fpga_device_manager.device_manager import DeviceManager
 from fpga_device_manager.exceptions import DeviceInvalidError, InvalidConfigError
+from fpga_device_manager.hass import Action, Automation
 
 _output_mgr = DeviceManager(device_class=Output)
 _input_mgr = DeviceManager(device_class=Input)
@@ -207,7 +208,16 @@ def export_yaml(out_file_path: str) -> None:
                 {'condition': 'time', 'after': '16:00:00', 'before': '23:00:00'}
             ],
             'action': {'service': 'homeassistant.turn_on', 'entity_id': 'group.living_room'}
-        },
+        }
+    output_devices = list(_output_mgr.all_devices())
+    input_devices = list(_input_mgr.all_devices())
+
+    for device in input_devices:
+        input_ = device.dev_id
+        target = device.associated_device.dev_id
+
+        if device.type is None:
+            pass
 
     # for filename, text in exports.items():
     #     filepath = os.file_path.join(out_file_path, filename)
diff --git a/fpga_device_manager/res/data/device_types.json b/fpga_device_manager/res/data/device_types.json
index 3083245..e2c09c0 100755
--- a/fpga_device_manager/res/data/device_types.json
+++ b/fpga_device_manager/res/data/device_types.json
@@ -7,7 +7,8 @@
     "pins": {
       "signal": {
         "requires_pwm": false,
-        "active_low": false
+        "active_low": false,
+        "action":
       }
     }
   },
-- 
GitLab