pax_global_header00006660000000000000000000000064141435445550014524gustar00rootroot0000000000000052 comment=f1065041445d3e066181f05c80a14d49a3ac21a7 Danielhiversen-pyOpenGarage-f106504/000077500000000000000000000000001414354455500173125ustar00rootroot00000000000000Danielhiversen-pyOpenGarage-f106504/.github/000077500000000000000000000000001414354455500206525ustar00rootroot00000000000000Danielhiversen-pyOpenGarage-f106504/.github/FUNDING.yml000066400000000000000000000001461414354455500224700ustar00rootroot00000000000000# These are supported funding model platforms github: Danielhiversen custom: http://paypal.me/dahoiv Danielhiversen-pyOpenGarage-f106504/.github/workflows/000077500000000000000000000000001414354455500227075ustar00rootroot00000000000000Danielhiversen-pyOpenGarage-f106504/.github/workflows/black.yaml000066400000000000000000000024111414354455500246450ustar00rootroot00000000000000name: Black Code Formatter on: push: pull_request: schedule: - cron: "0 0 * * *" jobs: validate: runs-on: "ubuntu-latest" steps: - uses: actions/checkout@v1 - name: black if: github.event.pull_request.head.repo.full_name == github.repository uses: lgeiger/black-action@master with: args: . - name: Check for modified files if: github.event.pull_request.head.repo.full_name == github.repository id: git-check run: echo ::set-output name=modified::$(if git diff-index --quiet HEAD --; then echo "false"; else echo "true"; fi) - name: Push changes if: github.event.pull_request.head.repo.full_name == github.repository && steps.git-check.outputs.modified == 'true' run: | git config --global user.name 'Daniel Hoyer' git config --global user.email 'mail@dahoiv.net' git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/$GITHUB_REPOSITORY git checkout $GITHUB_HEAD_REF git commit -am "fixup! Format Python code with black" git push - name: Flake8 Code Linter uses: jonasrk/flake8-action@master with: args: "--max-line-length=120 " Danielhiversen-pyOpenGarage-f106504/.github/workflows/code_checker.yml000066400000000000000000000020371414354455500260320ustar00rootroot00000000000000name: Code checker on: push: pull_request: schedule: - cron: "0 4 * * *" jobs: validate: runs-on: "ubuntu-latest" strategy: matrix: python-version: - "3.7" - "3.8" - "3.9" - "3.10" steps: - uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v2 with: python-version: ${{ matrix.python-version }} - uses: actions/cache@v2 with: path: ~/.cache/pip key: pip_cache - name: Install depencency run: | pip install aiohttp async_timeout pip install dlint flake8 flake8-bandit flake8-bugbear flake8-deprecated flake8-executable isort pylint - name: Flake8 Code Linter run: | flake8 opengarage/ --max-line-length=120 --extend-ignore=DUO102,DUO130,S303,S311 - name: isort run: | isort **/*.py - name: Pylint Code Linter run: | pylint opengarage Danielhiversen-pyOpenGarage-f106504/.github/workflows/python-publish.yml000066400000000000000000000015151414354455500264210ustar00rootroot00000000000000# This workflows will upload a Python Package using Twine when a release is created # For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries name: Upload Python Package on: release: types: [created] jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Set up Python uses: actions/setup-python@v2 with: python-version: '3.x' - name: Install dependencies run: | python -m pip install --upgrade pip pip install setuptools wheel twine - name: Build and publish env: TWINE_USERNAME: __token__ TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} run: | python setup.py sdist bdist_wheel twine upload dist/* Danielhiversen-pyOpenGarage-f106504/.gitignore000066400000000000000000000022631414354455500213050ustar00rootroot00000000000000# Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] *$py.class # C extensions *.so # Distribution / packaging .Python build/ develop-eggs/ dist/ downloads/ eggs/ .eggs/ lib/ lib64/ parts/ sdist/ var/ wheels/ *.egg-info/ .installed.cfg *.egg MANIFEST # PyInstaller # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. *.manifest *.spec # Installer logs pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ .coverage .coverage.* .cache nosetests.xml coverage.xml *.cover .hypothesis/ .pytest_cache/ # Translations *.mo *.pot # Django stuff: *.log local_settings.py db.sqlite3 # Flask stuff: instance/ .webassets-cache # Scrapy stuff: .scrapy # Sphinx documentation docs/_build/ # PyBuilder target/ # Jupyter Notebook .ipynb_checkpoints # pyenv .python-version # 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/ Danielhiversen-pyOpenGarage-f106504/LICENSE000066400000000000000000000020661414354455500203230ustar00rootroot00000000000000MIT License Copyright (c) 2019 Daniel Høyer Iversen Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Danielhiversen-pyOpenGarage-f106504/README.md000066400000000000000000000000601414354455500205650ustar00rootroot00000000000000# pyOpenGarage Python library for opengarage.io Danielhiversen-pyOpenGarage-f106504/opengarage/000077500000000000000000000000001414354455500214225ustar00rootroot00000000000000Danielhiversen-pyOpenGarage-f106504/opengarage/__init__.py000066400000000000000000000055361414354455500235440ustar00rootroot00000000000000"""Open garage""" import asyncio import logging import aiohttp import async_timeout DEFAULT_TIMEOUT = 10 _LOGGER = logging.getLogger(__name__) class OpenGarage: """Class to communicate with the Open Garage api.""" # pylint: disable=too-many-arguments def __init__( self, devip, devkey, verify_ssl=False, websession=None, timeout=DEFAULT_TIMEOUT, ): """Initialize the Open Garage connection.""" if websession is None: async def _create_session(): return aiohttp.ClientSession() loop = asyncio.get_event_loop() self.websession = loop.run_until_complete(_create_session()) else: self.websession = websession self._timeout = timeout self._devip = devip self._devkey = devkey self._verify_ssl = verify_ssl @property def device_url(self): """Device url.""" return self._devip async def close_connection(self): """Close the connection.""" await self.websession.close() async def update_state(self): """Update state.""" return await self._execute("jc") async def push_button(self): """Push button.""" result = await self._execute(f"cc?dkey={self._devkey}&click=1") if result is None: return None return result.get("result") async def reboot(self): """Reboot device.""" result = await self._execute(f"cc?dkey={self._devkey}&reboot=1") if result is None: return None return result.get("result") async def ap_mode(self): """Reset device in AP mode (to reconfigure WiFi settings).""" result = await self._execute(f"cc?dkey={self._devkey}&apmode=1") if result is None: return None return result.get("result") async def _execute(self, command, retry=2): """Execute command.""" url = f"{self._devip}/{command}" try: async with async_timeout.timeout(self._timeout): resp = await self.websession.get(url, verify_ssl=self._verify_ssl) if resp.status != 200: _LOGGER.error( "Error connecting to Open garage, resp code: %s", resp.status ) return None result = await resp.json(content_type=None) except aiohttp.ClientError as err: if retry > 0: return await self._execute(command, retry - 1) _LOGGER.error("Error connecting to Open garage: %s ", err, exc_info=True) raise except asyncio.TimeoutError: if retry > 0: return await self._execute(command, retry - 1) _LOGGER.error("Timed out when connecting to Open garage device") raise return result Danielhiversen-pyOpenGarage-f106504/setup.py000066400000000000000000000013431414354455500210250ustar00rootroot00000000000000from setuptools import setup setup( name="open_garage", packages=["opengarage"], install_requires=["aiohttp>=3.0.6", "async_timeout>=3.0.0"], version="0.2.0", description="A python3 library to communicate with Open Garage", python_requires=">=3.5.3", author="Daniel Hjelseth Høyer", author_email="mail@dahoiv.net", url="https://github.com/Danielhiversen/pyOpenGarage", license="MIT", classifiers=[ "Intended Audience :: Developers", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", "Topic :: Home Automation", "Topic :: Software Development :: Libraries :: Python Modules", ], )