init
This commit is contained in:
@@ -0,0 +1,171 @@
|
||||
import aiofiles
|
||||
import aiohttp
|
||||
import asyncio
|
||||
import binascii
|
||||
from distutils.version import StrictVersion
|
||||
import json
|
||||
import logging
|
||||
import os.path
|
||||
import requests
|
||||
import struct
|
||||
import voluptuous as vol
|
||||
|
||||
from aiohttp import ClientSession
|
||||
from homeassistant.const import (
|
||||
ATTR_FRIENDLY_NAME, __version__ as current_ha_version)
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.typing import ConfigType
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
DOMAIN = 'smartir'
|
||||
VERSION = '1.18.1'
|
||||
MANIFEST_URL = (
|
||||
"https://raw.githubusercontent.com/"
|
||||
"smartHomeHub/SmartIR/{}/"
|
||||
"custom_components/smartir/manifest.json")
|
||||
REMOTE_BASE_URL = (
|
||||
"https://raw.githubusercontent.com/"
|
||||
"smartHomeHub/SmartIR/{}/"
|
||||
"custom_components/smartir/")
|
||||
COMPONENT_ABS_DIR = os.path.dirname(
|
||||
os.path.abspath(__file__))
|
||||
|
||||
CONF_CHECK_UPDATES = 'check_updates'
|
||||
CONF_UPDATE_BRANCH = 'update_branch'
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
DOMAIN: vol.Schema({
|
||||
vol.Optional(CONF_CHECK_UPDATES, default=True): cv.boolean,
|
||||
vol.Optional(CONF_UPDATE_BRANCH, default='master'): vol.In(
|
||||
['master', 'rc'])
|
||||
})
|
||||
}, extra=vol.ALLOW_EXTRA)
|
||||
|
||||
async def async_setup(hass, config):
|
||||
"""Set up the SmartIR component."""
|
||||
conf = config.get(DOMAIN)
|
||||
|
||||
if conf is None:
|
||||
return True
|
||||
|
||||
check_updates = conf[CONF_CHECK_UPDATES]
|
||||
update_branch = conf[CONF_UPDATE_BRANCH]
|
||||
|
||||
async def _check_updates(service):
|
||||
await _update(hass, update_branch)
|
||||
|
||||
async def _update_component(service):
|
||||
await _update(hass, update_branch, True)
|
||||
|
||||
hass.services.async_register(DOMAIN, 'check_updates', _check_updates)
|
||||
hass.services.async_register(DOMAIN, 'update_component', _update_component)
|
||||
|
||||
if check_updates:
|
||||
await _update(hass, update_branch, False, False)
|
||||
|
||||
return True
|
||||
|
||||
async def _update(hass, branch, do_update=False, notify_if_latest=True):
|
||||
try:
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(MANIFEST_URL.format(branch)) as response:
|
||||
if response.status == 200:
|
||||
|
||||
data = await response.json(content_type='text/plain')
|
||||
min_ha_version = data['homeassistant']
|
||||
last_version = data['updater']['version']
|
||||
release_notes = data['updater']['releaseNotes']
|
||||
|
||||
if StrictVersion(last_version) <= StrictVersion(VERSION):
|
||||
if notify_if_latest:
|
||||
hass.components.persistent_notification.async_create(
|
||||
"You're already using the latest version!",
|
||||
title='SmartIR')
|
||||
return
|
||||
|
||||
if StrictVersion(current_ha_version) < StrictVersion(min_ha_version):
|
||||
hass.components.persistent_notification.async_create(
|
||||
"There is a new version of SmartIR integration, but it is **incompatible** "
|
||||
"with your system. Please first update Home Assistant.", title='SmartIR')
|
||||
return
|
||||
|
||||
if do_update is False:
|
||||
hass.components.persistent_notification.async_create(
|
||||
"A new version of SmartIR integration is available ({}). "
|
||||
"Call the ``smartir.update_component`` service to update "
|
||||
"the integration. \n\n **Release notes:** \n{}"
|
||||
.format(last_version, release_notes), title='SmartIR')
|
||||
return
|
||||
|
||||
# Begin update
|
||||
files = data['updater']['files']
|
||||
has_errors = False
|
||||
|
||||
for file in files:
|
||||
try:
|
||||
source = REMOTE_BASE_URL.format(branch) + file
|
||||
dest = os.path.join(COMPONENT_ABS_DIR, file)
|
||||
os.makedirs(os.path.dirname(dest), exist_ok=True)
|
||||
await Helper.downloader(source, dest)
|
||||
except Exception:
|
||||
has_errors = True
|
||||
_LOGGER.error("Error updating %s. Please update the file manually.", file)
|
||||
|
||||
if has_errors:
|
||||
hass.components.persistent_notification.async_create(
|
||||
"There was an error updating one or more files of SmartIR. "
|
||||
"Please check the logs for more information.", title='SmartIR')
|
||||
else:
|
||||
hass.components.persistent_notification.async_create(
|
||||
"Successfully updated to {}. Please restart Home Assistant."
|
||||
.format(last_version), title='SmartIR')
|
||||
except Exception:
|
||||
_LOGGER.error("An error occurred while checking for updates.")
|
||||
|
||||
class Helper():
|
||||
@staticmethod
|
||||
async def downloader(source, dest):
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(source) as response:
|
||||
if response.status == 200:
|
||||
async with aiofiles.open(dest, mode='wb') as f:
|
||||
await f.write(await response.read())
|
||||
else:
|
||||
raise Exception("File not found")
|
||||
|
||||
@staticmethod
|
||||
def pronto2lirc(pronto):
|
||||
codes = [int(binascii.hexlify(pronto[i:i+2]), 16) for i in range(0, len(pronto), 2)]
|
||||
|
||||
if codes[0]:
|
||||
raise ValueError("Pronto code should start with 0000")
|
||||
if len(codes) != 4 + 2 * (codes[2] + codes[3]):
|
||||
raise ValueError("Number of pulse widths does not match the preamble")
|
||||
|
||||
frequency = 1 / (codes[1] * 0.241246)
|
||||
return [int(round(code / frequency)) for code in codes[4:]]
|
||||
|
||||
@staticmethod
|
||||
def lirc2broadlink(pulses):
|
||||
array = bytearray()
|
||||
|
||||
for pulse in pulses:
|
||||
pulse = int(pulse * 269 / 8192)
|
||||
|
||||
if pulse < 256:
|
||||
array += bytearray(struct.pack('>B', pulse))
|
||||
else:
|
||||
array += bytearray([0x00])
|
||||
array += bytearray(struct.pack('>H', pulse))
|
||||
|
||||
packet = bytearray([0x26, 0x00])
|
||||
packet += bytearray(struct.pack('<H', len(array)))
|
||||
packet += array
|
||||
packet += bytearray([0x0d, 0x05])
|
||||
|
||||
# Add 0s to make ultimate packet size a multiple of 16 for 128-bit AES encryption.
|
||||
remainder = (len(packet) + 4) % 16
|
||||
if remainder:
|
||||
packet += bytearray(16 - remainder)
|
||||
return packet
|
||||
Reference in New Issue
Block a user