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