WIP
This commit is contained in:
150
.gitignore
vendored
Normal file
150
.gitignore
vendored
Normal file
@@ -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/
|
||||||
14
.vscode/extensions.json
vendored
Normal file
14
.vscode/extensions.json
vendored
Normal file
@@ -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": []
|
||||||
|
}
|
||||||
10
.vscode/settings.json
vendored
Normal file
10
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"[python]": {
|
||||||
|
"editor.formatOnSave": true,
|
||||||
|
"editor.codeActionsOnSave": {
|
||||||
|
"source.fixAll": "explicit",
|
||||||
|
"source.organizeImports": "explicit"
|
||||||
|
},
|
||||||
|
"editor.defaultFormatter": "charliermarsh.ruff"
|
||||||
|
}
|
||||||
|
}
|
||||||
22
main.py
Normal file
22
main.py
Normal file
@@ -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}
|
||||||
51
poo.py
Normal file
51
poo.py
Normal file
@@ -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",
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user