Skip to content

Commit

Permalink
First trials for an integration
Browse files Browse the repository at this point in the history
  • Loading branch information
fiva committed Apr 5, 2019
1 parent 1eaedd8 commit e836c6b
Show file tree
Hide file tree
Showing 6,847 changed files with 631,684 additions and 687 deletions.
The diff you're trying to view is too large. We only load the first 3000 changed files.
4 changes: 4 additions & 0 deletions .idea/encodings.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .idea/hass-nhc2.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 19 additions & 0 deletions .idea/inspectionProfiles/Project_Default.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

755 changes: 720 additions & 35 deletions .idea/workspace.xml

Large diffs are not rendered by default.

22 changes: 22 additions & 0 deletions .translations/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"config": {
"abort": {
"already_configured": "NHC2 is already configured"
},
"error": {
"cannot_connect": "Unable to connect to the Connected Controller."
},
"step": {
"user": {
"data": {
"host": "Host",
"port": "TCP Port",
"username": "Username"
},
"description": "You can use an IP as host, but make sure it's static/fixed.",
"title": "Details to your Niko Connected Controller"
}
},
"title": "Niko Connected Controller"
}
}
135 changes: 135 additions & 0 deletions __init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
"""Support for NHC2."""
import logging
import os

import homeassistant.helpers.config_validation as cv
import voluptuous as vol
from homeassistant import config_entries
from homeassistant.const import CONF_HOST, CONF_PORT, CONF_USERNAME, CONF_PASSWORD
from homeassistant.const import EVENT_HOMEASSISTANT_STOP
from homeassistant.util.json import load_json

from .config_flow import Nhc2FlowHandler
from .const import DOMAIN

REQUIREMENTS = ['paho-mqtt==1.4.0']

_LOGGER = logging.getLogger(__name__)

DOMAIN = DOMAIN
CONFIG_FILE = '.nhc2_psk.conf'
KEY_GATEWAY = 'nhc2_gateway'

CONFIG_SCHEMA = vol.Schema({
DOMAIN: vol.Schema({
vol.Required(CONF_HOST): cv.string,
vol.Required(CONF_PORT): cv.port,
vol.Required(CONF_USERNAME): cv.string,
vol.Required(CONF_PASSWORD): cv.string
})
}, extra=vol.ALLOW_EXTRA)


async def async_setup(hass, config):
"""Set up the NHC2 component."""
conf = config.get(DOMAIN)

if conf is None:
return True

configured_hosts = [entry.data['host'] for entry in
hass.config_entries.async_entries(DOMAIN)]

legacy_hosts = await hass.async_add_executor_job(
load_json, hass.config.path(CONFIG_FILE))

for host, info in legacy_hosts.items():
if host in configured_hosts:
continue

info[CONF_HOST] = host

hass.async_create_task(hass.config_entries.flow.async_init(
DOMAIN, context={'source': config_entries.SOURCE_IMPORT},
data=info
))

host = conf.get(CONF_HOST)
port = conf.get(CONF_PORT)
username = conf.get(CONF_USERNAME)
password = conf.get(CONF_PASSWORD)

if host is None or host in configured_hosts or host in legacy_hosts:
return True

hass.async_create_task(hass.config_entries.flow.async_init(
DOMAIN, context={'source': config_entries.SOURCE_IMPORT},
data={CONF_HOST: host, CONF_PORT: port,
CONF_USERNAME: username,
CONF_PASSWORD: password}
))

return True


async def async_setup_entry(hass, entry):
def nhc2_get_sysinfo(loop, _nhc2):
fut = loop.create_future()
_nhc2.get_systeminfo(
lambda sys_info: fut.set_result(sys_info)
)
return fut
"""Create a NHC2 gateway."""
# host, identity, key, allow_tradfri_groups
from .nhc2 import NHC2

gateway = NHC2(
entry.data[CONF_HOST],
entry.data[CONF_PORT],
entry.data[CONF_USERNAME],
entry.data[CONF_PASSWORD],
os.path.dirname(os.path.realpath(__file__)) + '/niko_ca.pem'
)

async def on_hass_stop(event):
"""Close connection when hass stops."""
gateway.disconnect()

hass.data.setdefault(KEY_GATEWAY, {})[entry.entry_id] = gateway

hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, on_hass_stop)

_LOGGER.debug('NHC2 - Connecting to ' + entry.data[CONF_HOST] + ':' + str(entry.data[CONF_PORT]))
gateway.connect()

nhc2_sysinfo = await nhc2_get_sysinfo(hass.loop, gateway)

params = nhc2_sysinfo['Params']
system_info = next(filter((lambda x: x and 'SystemInfo' in x), params), None)['SystemInfo']
s_w_versions = next(filter((lambda x: x and 'SWversions' in x), system_info), None)['SWversions']
coco_image = next(filter((lambda x: x and 'CocoImage' in x), s_w_versions), None)['CocoImage']
nhc_version = next(filter((lambda x: x and 'NhcVersion' in x), s_w_versions), None)['NhcVersion']
# gateway.get_systeminfo(lambda x: _LOGGER.debug('got sysinfo ' + str(x)))
dev_reg = await hass.helpers.device_registry.async_get_registry()
dev_reg.async_get_or_create(
config_entry_id=entry.entry_id,
connections=set(),
identifiers={
(DOMAIN, entry.data[CONF_USERNAME])
},
manufacturer='Niko',
name='Home Control II',
model='Connected controller',
sw_version= nhc_version + ' - CoCo Image: '+ coco_image,
)

_LOGGER.debug('NHC2 - Preparing to capture devices.')
hass.async_create_task(hass.config_entries.async_forward_entry_setup(
entry, 'light'
))


hass.async_create_task(hass.config_entries.async_forward_entry_setup(
entry, 'switch'
))
return True
65 changes: 65 additions & 0 deletions config_flow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
"""Config flow to configure IPMA component."""
import voluptuous as vol

from homeassistant import config_entries, data_entry_flow
from homeassistant.const import CONF_HOST, CONF_PORT, CONF_USERNAME, CONF_PASSWORD
import homeassistant.helpers.config_validation as cv

from .const import DOMAIN


@config_entries.HANDLERS.register(DOMAIN)
class Nhc2FlowHandler(data_entry_flow.FlowHandler):
"""Config flow for NHC2 platform."""

VERSION = 1
CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_PUSH

def __init__(self):
"""Init NHC2FlowHandler."""
self._errors = {}

# async def async_step_import(self, user_input):
# """Import a config entry."""
# # if self._async_current_entries():
# # return self.async_abort(reason="single_instance_allowed")
#
# return self.async_create_entry(
# title="configuration.yaml", data=user_input
# )

async def async_step_user(self, user_input=None):
"""Handle a flow initialized by the user."""
self._errors = {}

if user_input is not None:
if user_input[CONF_USERNAME] not in\
self.hass.config_entries.async_entries(DOMAIN):
return self.async_create_entry(
title=user_input[CONF_USERNAME],
data=user_input,
)

self._errors[CONF_USERNAME] = 'name_exists'

# default location is set hass configuration
return await self._show_config_form(
host=None,
port=8883,
username=None,
password=None)

async def _show_config_form(self, host=None, port=None,
username=None,
password=None):
"""Show the configuration form to edit NHC2 data."""
return self.async_show_form(
step_id='user',
data_schema=vol.Schema({
vol.Required(CONF_HOST, default=host): str,
vol.Required(CONF_PORT, default=port): cv.port,
vol.Required(CONF_USERNAME, default=username): str,
vol.Required(CONF_PASSWORD, default=password): str
}),
errors=self._errors,
)
8 changes: 8 additions & 0 deletions const.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
"""Consts used by Tradfri."""
from homeassistant.const import CONF_HOST # noqa pylint: disable=unused-import

DOMAIN = 'nhc2'

BRAND = 'Niko'
LIGHT = 'Light'
SWITCH = 'Switch'
85 changes: 85 additions & 0 deletions light.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
"""Support for NHC2 switches."""
import logging
from typing import List
from homeassistant.components.light import Light
from homeassistant.core import callback

from .nhc2light import NHC2Light
from .nhc2 import NHC2
from .const import DOMAIN, BRAND, LIGHT

KEY_GATEWAY = 'nhc2_gateway'
KEY_LIGHTS = 'nhc2_lights'




async def async_setup_entry(hass, config_entry, async_add_entities):
"""Load NHC2 switches based on a config entry."""
hass.data.setdefault(KEY_LIGHTS, {})[config_entry.entry_id] : List[NHC2HassLight] = []

@callback
def process_lights(lights: List[NHC2Light]):
if len(hass.data[KEY_LIGHTS][config_entry.entry_id]) == 0:
for light in lights:
hass.data[KEY_LIGHTS][config_entry.entry_id].append(NHC2HassLight(light))
async_add_entities(hass.data[KEY_LIGHTS][config_entry.entry_id])

gateway: NHC2 = hass.data[KEY_GATEWAY][config_entry.entry_id]
gateway.get_lights(process_lights)


class NHC2HassLight(Light):
"""Representation of an NHC2 Light."""

def __init__(self, nhc2light: NHC2Light):
self._nhc2light = nhc2light

def on_change():
self.async_write_ha_state()

nhc2light.on_change = on_change


@property
def unique_id(self):
return self._nhc2light.uuid

@property
def should_poll(self):
return False

@property
def name(self):
return self._nhc2light.name

@property
def is_on(self):
return self._nhc2light.is_on()

@property
def device_info(self):
"""Return the device info."""


return {
'identifiers': {
(DOMAIN, self.unique_id)
},
'name': self.name,
'manufacturer': BRAND,
'model': LIGHT,
'sw_version': 'unknown',
'via_hub': (DOMAIN, self._nhc2light.profile_creation_id),
}
def turn_off(self, **kwargs) -> None:
pass

def turn_on(self, **kwargs) -> None:
pass

async def async_turn_on(self, **kwargs):
self._nhc2light.turn_on()

async def async_turn_off(self, **kwargs):
self._nhc2light.turn_off()
Loading

0 comments on commit e836c6b

Please sign in to comment.