From 481a27c3e2207fab1b3ddf85e5ec03f021d1b2d0 Mon Sep 17 00:00:00 2001
From: Max <max@dasmaexle.de>
Date: Sun, 29 May 2022 22:30:39 +0200
Subject: [PATCH] created folder structure

---
 Dockerfile               |  2 +-
 README.md                | 17 ++++++++++-
 base.py                  | 17 +++++++++++
 main.py                  | 66 ++++++----------------------------------
 models/mystrom_device.py | 16 ++++++++++
 models/mystrom_result.py | 22 ++++++++++++++
 6 files changed, 81 insertions(+), 59 deletions(-)
 create mode 100644 base.py
 create mode 100644 models/mystrom_device.py
 create mode 100644 models/mystrom_result.py

diff --git a/Dockerfile b/Dockerfile
index 6515679..39816f3 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -8,4 +8,4 @@ RUN pip install --no-cache-dir --upgrade pip && \
     pip install --no-cache-dir -r requirements.txt
 
 COPY . .
-CMD ["python", "./main.py"]
\ No newline at end of file
+CMD ["python", "-m", "main"]
\ No newline at end of file
diff --git a/README.md b/README.md
index b63008c..11f81d7 100644
--- a/README.md
+++ b/README.md
@@ -2,4 +2,19 @@
 Requests data from MyStrom switch and stores in sql database.
 
 ## Environment Variables
-`SQL_URL` - the URL for database, e.g. `mysql+pymysql://user:password@host:3306/databsae`
+`SQL_URL` - the URL for database, e.g. `mysql+pymysql://user:password@host:3306/database`
+
+## Run
+### With python
+```sh
+export SQL_URL=mysql+pymysql://user:password@host:3306/database
+python -m main
+```
+
+### With Docker Container
+```sh
+docker run \
+    --name mystrom-python \
+    -e "SQL_URL=mysql+pymysql://user:password@host:3306/database" \
+    ghcr.io/maexled/mystrom-python:master
+```
diff --git a/base.py b/base.py
new file mode 100644
index 0000000..7de8322
--- /dev/null
+++ b/base.py
@@ -0,0 +1,17 @@
+import os
+
+from sqlalchemy import create_engine
+from sqlalchemy.ext.declarative import declarative_base
+from sqlalchemy.orm import sessionmaker
+
+sql_url = os.environ['SQL_URL']
+engine = create_engine(sql_url)
+# use session_factory() to get a new Session
+_SessionFactory = sessionmaker(bind=engine)
+
+Base = declarative_base()
+
+
+def session_factory():
+    Base.metadata.create_all(engine)
+    return _SessionFactory()
\ No newline at end of file
diff --git a/main.py b/main.py
index f113011..e120a39 100644
--- a/main.py
+++ b/main.py
@@ -1,50 +1,16 @@
 import schedule
 import time
-from datetime import datetime, timezone, timedelta
 import requests
 import json
-import os
 
-from sqlalchemy import Column, Integer, Float, String, DateTime, ForeignKey
-import sqlalchemy as db
-from sqlalchemy.ext.declarative import declarative_base
-from sqlalchemy.orm import relationship, backref, sessionmaker, joinedload
+import threading
 
-Base = declarative_base()
+from base import Base, session_factory
 
-class MystromDevice(Base):
-
-  __tablename__ = 'devices'
-
-  id = Column(Integer, primary_key=True)
-
-  name = Column(String(16))
-  ip = Column(String(16))
-
-  # Lets us print out a user object conveniently.
-  def __repr__(self):
-    return "<Device(id='%s', name='%s', ip='%s')>" % (
-            self.id, self.name, self.ip)
-
-class MystromResult(Base):
-
-  __tablename__ = 'results'
-
-  id = Column(Integer, primary_key=True)
-
-  device_id = Column(Integer, ForeignKey('devices.id'))
-
-  power = Column(Float)
-  ws = Column(Float)
-  relay = Column(Integer)
-  temperature = Column(Float)
-  date = Column(DateTime(timezone=True), default=datetime.now)
-
-  # Lets us print out a user object conveniently.
-  def __repr__(self):
-    return "<Result(deivce_id='%s', power='%s', ws='%s', relay='%s', temperature='%s', date='%s')>" % (
-            self.device_id, self.power, self.ws, self.relay, self.temperature, self.date)
+from models.mystrom_device import MystromDevice
+from models. mystrom_result import MystromResult
 
+@schedule.repeat(schedule.every(1).minutes)
 def trigger():
     for device in devices:
         request_data_and_store(device)
@@ -55,32 +21,18 @@ def get_devices():
 
 def request_data_and_store(device):
     response = requests.get(f'http://{device.ip}/report')
-    json_response = json.loads(response.text)
-    mystrom_result = json_result_to_object(json_response, device)
+    response = json.loads(response.text)
+    mystrom_result = MystromResult(device_id=device.id, power=response["power"], ws=response["Ws"], relay=response["relay"], temperature=response["temperature"])
 
     session.add(mystrom_result, device)
     session.commit()
 
-def json_result_to_object(json, device):
-    return MystromResult(device_id=device.id, power=json["power"], ws=json["Ws"], relay=json["relay"], temperature=json["temperature"])
-
 if __name__ == '__main__':
-    sql_url = os.environ['SQL_URL']
-    engine = db.create_engine(sql_url)
-    connection = engine.connect()
-
-    Base.metadata.create_all(engine) 
-
-    Session = sessionmaker(bind=engine)
-    session = Session()
-    
+    session = session_factory()
     devices = get_devices()
 
-    schedule.every(1).minutes.do(trigger)
-
     while True:
-
         # Checks whether a scheduled task
         # is pending to run or not
         schedule.run_pending()
-        time.sleep(1)
\ No newline at end of file
+        time.sleep(1)
diff --git a/models/mystrom_device.py b/models/mystrom_device.py
new file mode 100644
index 0000000..51ff929
--- /dev/null
+++ b/models/mystrom_device.py
@@ -0,0 +1,16 @@
+from base import Base
+from sqlalchemy import Column, Integer, String
+
+class MystromDevice(Base):
+
+  __tablename__ = 'devices'
+
+  id = Column(Integer, primary_key=True)
+
+  name = Column(String(16))
+  ip = Column(String(16))
+
+  # Lets us print out a user object conveniently.
+  def __repr__(self):
+    return "<Device(id='%s', name='%s', ip='%s')>" % (
+            self.id, self.name, self.ip)
\ No newline at end of file
diff --git a/models/mystrom_result.py b/models/mystrom_result.py
new file mode 100644
index 0000000..c83bef5
--- /dev/null
+++ b/models/mystrom_result.py
@@ -0,0 +1,22 @@
+from base import Base
+from sqlalchemy import Column, Integer, Float, DateTime, ForeignKey
+from datetime import datetime
+
+class MystromResult(Base):
+
+  __tablename__ = 'results'
+
+  id = Column(Integer, primary_key=True)
+
+  device_id = Column(Integer, ForeignKey('devices.id'))
+
+  power = Column(Float)
+  ws = Column(Float)
+  relay = Column(Integer)
+  temperature = Column(Float)
+  date = Column(DateTime(timezone=True), default=datetime.now)
+
+  # Lets us print out a user object conveniently.
+  def __repr__(self):
+    return "<Result(deivce_id='%s', power='%s', ws='%s', relay='%s', temperature='%s', date='%s')>" % (
+            self.device_id, self.power, self.ws, self.relay, self.temperature, self.date)
\ No newline at end of file