-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 0328d26
Showing
13 changed files
with
333 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
repos: | ||
- repo: https://github.com/asottile/pyupgrade | ||
rev: v2.3.0 | ||
hooks: | ||
- id: pyupgrade | ||
args: [--py37-plus] | ||
- repo: https://github.com/psf/black | ||
rev: 19.10b0 | ||
hooks: | ||
- id: black | ||
args: | ||
- --safe | ||
- --quiet | ||
files: ^((homeassistant|script|tests)/.+)?[^/]+\.py$ | ||
- repo: https://github.com/codespell-project/codespell | ||
rev: v1.16.0 | ||
hooks: | ||
- id: codespell | ||
args: | ||
- --ignore-words-list=hass,alot,datas,dof,dur,farenheit,hist,iff,ines,ist,lightsensor,mut,nd,pres,referer,ser,serie,te,technik,ue,uint,visability,wan,wanna,withing | ||
- --skip="./.*,*.csv,*.json" | ||
- --quiet-level=2 | ||
exclude_types: [csv, json] | ||
- repo: https://gitlab.com/pycqa/flake8 | ||
rev: 3.8.1 | ||
hooks: | ||
- id: flake8 | ||
additional_dependencies: | ||
- flake8-docstrings==1.5.0 | ||
- pydocstyle==5.0.2 | ||
files: ^(homeassistant|script|tests)/.+\.py$ | ||
- repo: https://github.com/PyCQA/bandit | ||
rev: 1.6.2 | ||
hooks: | ||
- id: bandit | ||
args: | ||
- --quiet | ||
- --format=custom | ||
- --configfile=tests/bandit.yaml | ||
files: ^(homeassistant|script|tests)/.+\.py$ | ||
- repo: https://github.com/pre-commit/mirrors-isort | ||
rev: v4.3.21 | ||
hooks: | ||
- id: isort | ||
- repo: https://github.com/pre-commit/pre-commit-hooks | ||
rev: v2.4.0 | ||
hooks: | ||
- id: check-executables-have-shebangs | ||
stages: [manual] | ||
- id: check-json | ||
- repo: https://github.com/pre-commit/mirrors-mypy | ||
rev: v0.770 | ||
hooks: | ||
- id: mypy | ||
args: | ||
- --pretty | ||
- --show-error-codes | ||
- --show-error-context |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# PJLink2 for Home Assistant | ||
|
||
## Installation |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
"""PJLink2 Custom Component.""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
"""Provides the constants needed for component.""" | ||
from enum import StrEnum | ||
|
||
DOMAIN = "pjlink2" | ||
|
||
CONF_ENCODING = "encoding" | ||
DEFAULT_ENCODING = "utf-8" | ||
DEFAULT_PORT = 4352 | ||
DEFAULT_TIMEOUT = 4 | ||
|
||
ATTR_PRODUCT_NAME = "product_name" | ||
ATTR_MANUFACTURER_NAME = "manufacturer_name" | ||
ATTR_PROJECTOR_NAME = "projector_name" | ||
ATTR_RESOLUTION_X = "x_resolution" | ||
ATTR_RESOLUTION_Y = "y_resolution" | ||
|
||
class ProjectorState(StrEnum): | ||
OFF = "off" | ||
ON = "on" | ||
COOLING = "cooling" | ||
WARMING = "warming" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{ | ||
"codeowners": ["@TheRealKillaruna"], | ||
"config_flow": false, | ||
"dependencies": [], | ||
"documentation": "https://github.com/TheRealKillaruna/pjlink2", | ||
"domain": "pjlink2", | ||
"iot_class": "calculated", | ||
"name": "PJLink2", | ||
"requirements": ["aiopjlink==1.0.5"], | ||
"version": "0.1" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
"""GitHub sensor platform.""" | ||
from __future__ import annotations | ||
|
||
from collections.abc import Callable | ||
from datetime import timedelta | ||
import logging | ||
from typing import Any | ||
|
||
from aiopjlink import PJLink, PJLinkException, PJLinkProjectorError, Power, Sources, Lamp, Information | ||
|
||
from homeassistant import config_entries, core | ||
from homeassistant.components.sensor import PLATFORM_SCHEMA | ||
from homeassistant.const import CONF_HOST, CONF_PORT, CONF_NAME, CONF_PASSWORD, CONF_TIMEOUT | ||
|
||
import homeassistant.helpers.config_validation as cv | ||
from homeassistant.helpers.entity import Entity | ||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType, HomeAssistantType | ||
|
||
import voluptuous as vol | ||
|
||
from .const import DOMAIN, CONF_ENCODING, DEFAULT_ENCODING, DEFAULT_PORT, DEFAULT_TIMEOUT, ATTR_PRODUCT_NAME, ATTR_MANUFACTURER_NAME, ATTR_PROJECTOR_NAME, ATTR_RESOLUTION_X, ATTR_RESOLUTION_Y, ProjectorState | ||
|
||
|
||
_LOGGER = logging.getLogger(__name__) | ||
# Time between updating data from projector | ||
SCAN_INTERVAL = timedelta(seconds=3) | ||
|
||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( | ||
{ | ||
vol.Required(CONF_HOST): cv.string, | ||
vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, | ||
vol.Optional(CONF_NAME): cv.string, | ||
vol.Optional(CONF_ENCODING, default=DEFAULT_ENCODING): cv.string, | ||
vol.Optional(CONF_PASSWORD) : cv.string, | ||
vol.Optional(CONF_TIMEOUT, default=DEFAULT_TIMEOUT) : cv.positive_float | ||
} | ||
) | ||
|
||
|
||
async def async_setup_platform( | ||
hass: HomeAssistantType, | ||
config: ConfigType, | ||
async_add_entities: Callable, | ||
discovery_info: DiscoveryInfoType | None = None, | ||
) -> None: | ||
"""Set up the sensor platform.""" | ||
host = config.get(CONF_HOST) | ||
port = config.get(CONF_PORT) | ||
password = config.get(CONF_PASSWORD) | ||
timeout = config.get(CONF_TIMEOUT) | ||
name = config.get(CONF_NAME) | ||
pjl = PJLink(host, port, password, timeout) | ||
sensors = [PJLink2Sensor(pjl, name)] | ||
async_add_entities(sensors, update_before_add=True) | ||
|
||
|
||
class PJLink2Sensor(Entity): | ||
"""Representation of a PJLink2 sensor.""" | ||
|
||
def __init__(self, pjl, name): | ||
super().__init__() | ||
self._projector = pjl | ||
self.attrs: dict[str, Any] = {} | ||
self._name = name | ||
self._state = None | ||
self._available = False | ||
|
||
async def async_will_remove_from_hass(self) -> None: | ||
"""Close connection.""" | ||
await super().async_will_remove_from_hass() | ||
try: | ||
await self._projector.__aexit__(0,0,0) | ||
except PJLinkException as err: | ||
_LOGGER.exception("PJLink2 ERROR for %s: %s", self._name, repr(err)) | ||
else: | ||
_LOGGER.info("PJLink2 INFO for %s: Connection closed.", self._name) | ||
|
||
@property | ||
def name(self) -> str: | ||
"""Return the name of the entity.""" | ||
return self._name | ||
|
||
@property | ||
def unique_id(self) -> str: | ||
"""Return the unique ID of the sensor.""" | ||
return self._projector._address | ||
|
||
@property | ||
def available(self) -> bool: | ||
"""Return True if entity is available.""" | ||
return self._available | ||
|
||
@property | ||
def state(self) -> str | None: | ||
return self._state | ||
|
||
@property | ||
def extra_state_attributes(self) -> dict[str, Any]: | ||
return self.attrs | ||
|
||
async def async_update(self) -> None: | ||
"""Update all sensors.""" | ||
try: | ||
if not self._available: | ||
# connect and init static information | ||
await self._projector.__aenter__() | ||
self._available = True | ||
info = await Information(self._projector).table() | ||
self.attrs[ATTR_PRODUCT_NAME] = info["product_name"] | ||
self.attrs[ATTR_MANUFACTURER_NAME] = info["manufacturer_name"] | ||
self.attrs[ATTR_PROJECTOR_NAME] = info["projector_name"] | ||
if self._name == None: self._name = info["projector_name"] | ||
_LOGGER.info("PJLink2 INFO for %s: Connection opened.", self._name) | ||
|
||
pwr = await Power(self._projector).get() | ||
if pwr == Power.State.OFF: self._state = ProjectorState.OFF | ||
elif pwr == Power.State.ON: self._state = ProjectorState.ON | ||
elif pwr == Power.State.COOLING: self._state = ProjectorState.COOLING | ||
elif pwr == Power.State.WARMING: self._state = ProjectorState.WARMING | ||
|
||
if pwr==Power.ON: | ||
res = await Sources(self._projector).resolution() | ||
self.attrs[ATTR_RESOLUTION_X] = res[0] | ||
self.attrs[ATTR_RESOLUTION_Y] = res[1] | ||
else: | ||
if ATTR_RESOLUTION_X in self.attrs: del self.attrs[ATTR_RESOLUTION_X] | ||
if ATTR_RESOLUTION_Y in self.attrs: del self.attrs[ATTR_RESOLUTION_Y] | ||
|
||
except PJLinkProjectorError: | ||
# resolution cannot be queried due to no input | ||
if ATTR_RESOLUTION_X in self.attrs: del self.attrs[ATTR_RESOLUTION_X] | ||
if ATTR_RESOLUTION_Y in self.attrs: del self.attrs[ATTR_RESOLUTION_Y] | ||
_LOGGER.info("PJLink2 INFO for %s: Cannot get resolution", self._name) | ||
except PJLinkException as err: | ||
self._state = None | ||
self._available = False | ||
_LOGGER.exception("PJLink2 ERROR for %s: %s", self._name, repr(err)) | ||
try: | ||
await self._projector.__aexit__(0,0,0) | ||
except PJLinkException as err: | ||
_LOGGER.exception("PJLink2 ERROR for %s: %s", self._name, repr(err)) | ||
else: | ||
_LOGGER.info("PJLink2 INFO for %s: Connection closed.", self._name) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"name": "PJLink2", | ||
"render_readme": true, | ||
"iot_class": "calculated" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
pytest | ||
pytest-cov==2.9.0 | ||
pytest-homeassistant-custom-component |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
[coverage:run] | ||
source = | ||
custom_components | ||
|
||
[coverage:report] | ||
exclude_lines = | ||
pragma: no cover | ||
raise NotImplemented() | ||
if __name__ == '__main__': | ||
main() | ||
show_missing = true | ||
|
||
[tool:pytest] | ||
testpaths = tests | ||
norecursedirs = .git | ||
addopts = | ||
--strict | ||
--cov=custom_components | ||
|
||
[flake8] | ||
# https://github.com/ambv/black#line-length | ||
max-line-length = 88 | ||
# E501: line too long | ||
# W503: Line break occurred before a binary operator | ||
# E203: Whitespace before ':' | ||
# D202 No blank lines allowed after function docstring | ||
# W504 line break after binary operator | ||
ignore = | ||
E501, | ||
W503, | ||
E203, | ||
D202, | ||
W504 | ||
|
||
[isort] | ||
# https://github.com/timothycrosley/isort | ||
# https://github.com/timothycrosley/isort/wiki/isort-Settings | ||
# splits long import on multiple lines indented by 4 spaces | ||
multi_line_output = 3 | ||
include_trailing_comma=True | ||
force_grid_wrap=0 | ||
use_parentheses=True | ||
line_length=88 | ||
indent = " " | ||
# by default isort don't check module indexes | ||
not_skip = __init__.py | ||
# will group `import x` and `from x import` of the same module. | ||
force_sort_within_sections = true | ||
sections = FUTURE,STDLIB,INBETWEENS,THIRDPARTY,FIRSTPARTY,LOCALFOLDER | ||
default_section = THIRDPARTY | ||
known_first_party = custom_components,tests | ||
forced_separate = tests | ||
combine_as_imports = true | ||
|
||
[mypy] | ||
python_version = 3.7 | ||
ignore_errors = true | ||
follow_imports = silent | ||
ignore_missing_imports = true | ||
warn_incomplete_stub = true | ||
warn_redundant_casts = true | ||
warn_unused_configs = true |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# https://bandit.readthedocs.io/en/latest/config.html | ||
|
||
tests: | ||
- B108 | ||
- B306 | ||
- B307 | ||
- B313 | ||
- B314 | ||
- B315 | ||
- B316 | ||
- B317 | ||
- B318 | ||
- B319 | ||
- B320 | ||
- B325 | ||
- B602 | ||
- B604 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
"""Test component setup.""" | ||
from homeassistant.setup import async_setup_component | ||
|
||
from custom_components.pjlink2.const import DOMAIN | ||
|
||
|
||
async def test_async_setup(hass): | ||
"""Test the component gets setup.""" | ||
assert await async_setup_component(hass, DOMAIN, {}) is True |