commit fbb5ca762d5276e60a7b6553cde0f1bb99f911e0 Author: Tianyu Liu Date: Tue Jul 16 15:55:45 2024 +0200 WIP diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c27d48c --- /dev/null +++ b/.gitignore @@ -0,0 +1,150 @@ +# Python +*.pyc +__pycache__/ +*.pyo +*.pyd + +# Virtual Environment +venv/ +env/ +env.bak/ +env1/ +env2/ +.env + +# IDEs and Editors +.idea/ +*.sublime-project +*.sublime-workspace + +# Dependency directories +env/ +lib/ +libs/ +lib64/ +build/ +dist/ +egg-info/ +pip-wheel-metadata/ +*.egg-info/ +*.egg +*.whl + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# Testing +.pytest_cache/ +.coverage +.tox/ +.nox/ +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +.coverage +.tox/ +.nox/ +.cache +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +dist/ +docs/_build/ +target/ +.ipynb_checkpoints + +# Translations +*.mo +*.pot + +# Django +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask +instance/ +.webassets-cache + +# Scrapy +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints/ + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +.Pipfile.lock + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..9d1e703 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,14 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. + // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp + // List of extensions which should be recommended for users of this workspace. + "recommendations": [ + "ms-python.vscode-pylance", + "ms-python.python", + "ms-python.debugpy", + "charliermarsh.ruff", + "ms-azuretools.vscode-docker" + ], + // List of extensions recommended by VS Code that should not be recommended for users of this workspace. + "unwantedRecommendations": [] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..e64211a --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,10 @@ +{ + "[python]": { + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.fixAll": "explicit", + "source.organizeImports": "explicit" + }, + "editor.defaultFormatter": "charliermarsh.ruff" + } +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..da45ac1 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +Port 8881 \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..c68760a --- /dev/null +++ b/main.py @@ -0,0 +1,22 @@ +from contextlib import asynccontextmanager + +from fastapi import FastAPI + +from poo import PooRecorder + +recorder = PooRecorder() + + +@asynccontextmanager +async def _lifespan(_app: FastAPI): + await recorder.start() + yield + await recorder.stop() + + +app = FastAPI(lifespan=_lifespan) + + +@app.put("/record/s={status}") +async def record(status: str) -> dict: + return {"status": status} diff --git a/poo.py b/poo.py new file mode 100644 index 0000000..52ca26c --- /dev/null +++ b/poo.py @@ -0,0 +1,51 @@ +from datetime import datetime + +from fastapi_mqtt import FastMQTT, MQTTConfig + + +class PooRecorder: + mqtt_config = MQTTConfig(username="mqtt", password="mqtt") + mqtt = FastMQTT(config=mqtt_config) + + def __init__(self) -> None: + print("Initialization.") + + async def start(self) -> None: + print("Starting...") + await PooRecorder.mqtt.mqtt_startup() + + async def stop(self) -> None: + print("Stopping...") + await PooRecorder.mqtt.mqtt_shutdown() + + def record(self) -> None: + print("Recording...", self._status) + now = datetime.now(tz=datetime.now().astimezone().tzinfo) + formatted_time = now.strftime("%a | %Y-%m-%d | %H:%M") + + @mqtt.on_connect() + def on_connect(client, flags, rc, properties): + print("Connected") + config = PooRecorder.compose_config() + PooRecorder.mqtt.publish("homeassistant/text/poo_recorder/config", config) + + @staticmethod + def compose_config() -> dict: + return { + "device": { + "name": "Dog Poop Recorder", + "model": "poop-recorder-backend", + "sw_version": "0.2", + "identifiers": ["poo_recorder"], + "manufacturer": "Studio TJ", + }, + "unique_id": "poo_recorder", + "name": "Poop Recorder", + "availability_topic": "studiotj/poo_recorder/status", + "availability_template": "{{ value_json.availability }}", + "json_attributes_topic": "studiotj/poo_recorder/attributes", + "min": 0, + "max": 255, + "mode": "text", + "command_topic": "studiotj/poo_recorder/command", + } diff --git a/ruff.toml b/ruff.toml new file mode 100644 index 0000000..087e02c --- /dev/null +++ b/ruff.toml @@ -0,0 +1,7 @@ +target-version = "py39" +line-length = 144 + +[lint] +select = ["ALL"] +fixable = ["UP034", "I001"] +ignore = ["T201", "D", "ANN101"]