diff --git a/.coveragerc b/.coveragerc index 63805e6e428..0f17fa04339 100644 --- a/.coveragerc +++ b/.coveragerc @@ -109,6 +109,9 @@ omit = homeassistant/components/ios.py homeassistant/components/*/ios.py + homeassistant/components/iota.py + homeassistant/components/*/iota.py + homeassistant/components/isy994.py homeassistant/components/*/isy994.py diff --git a/homeassistant/components/iota.py b/homeassistant/components/iota.py new file mode 100644 index 00000000000..237493c7919 --- /dev/null +++ b/homeassistant/components/iota.py @@ -0,0 +1,81 @@ +""" +Support for IOTA wallets. + +For more details about this component, please refer to the documentation at +https://home-assistant.io/components/iota/ +""" +import logging +from datetime import timedelta + +import voluptuous as vol + +import homeassistant.helpers.config_validation as cv +from homeassistant.helpers.discovery import load_platform +from homeassistant.helpers.entity import Entity + +REQUIREMENTS = ['pyota==2.0.3'] + +_LOGGER = logging.getLogger(__name__) + +CONF_IRI = 'iri' +CONF_TESTNET = 'testnet' +CONF_WALLET_NAME = 'name' +CONF_WALLET_SEED = 'seed' +CONF_WALLETS = 'wallets' + +DOMAIN = 'iota' + +IOTA_PLATFORMS = ['sensor'] + +SCAN_INTERVAL = timedelta(minutes=10) + +WALLET_CONFIG = vol.Schema({ + vol.Required(CONF_WALLET_NAME): cv.string, + vol.Required(CONF_WALLET_SEED): cv.string, +}) + +CONFIG_SCHEMA = vol.Schema({ + DOMAIN: vol.Schema({ + vol.Required(CONF_IRI): cv.string, + vol.Optional(CONF_TESTNET, default=False): cv.boolean, + vol.Required(CONF_WALLETS): vol.All(cv.ensure_list, [WALLET_CONFIG]), + }) +}, extra=vol.ALLOW_EXTRA) + + +def setup(hass, config): + """Set up the IOTA component.""" + iota_config = config[DOMAIN] + + for platform in IOTA_PLATFORMS: + load_platform(hass, platform, DOMAIN, iota_config, config) + + return True + + +class IotaDevice(Entity): + """Representation of a IOTA device.""" + + def __init__(self, name, seed, iri, is_testnet=False): + """Initialisation of the IOTA device.""" + self._name = name + self._seed = seed + self.iri = iri + self.is_testnet = is_testnet + + @property + def name(self): + """Return the default name of the device.""" + return self._name + + @property + def device_state_attributes(self): + """Return the state attributes of the device.""" + attr = {CONF_WALLET_NAME: self._name} + return attr + + @property + def api(self): + """Construct API object for interaction with the IRI node.""" + from iota import Iota + return Iota(adapter=self.iri, seed=self._seed) diff --git a/homeassistant/components/sensor/iota.py b/homeassistant/components/sensor/iota.py new file mode 100644 index 00000000000..c973fa83148 --- /dev/null +++ b/homeassistant/components/sensor/iota.py @@ -0,0 +1,94 @@ +""" +Support for IOTA wallets. + +For more details about this component, please refer to the documentation at +https://home-assistant.io/components/iota +""" +import logging +from datetime import timedelta + +from homeassistant.components.iota import IotaDevice + +_LOGGER = logging.getLogger(__name__) + +DEPENDENCIES = ['iota'] + +SCAN_INTERVAL = timedelta(minutes=3) + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Set up the IOTA sensor.""" + # Add sensors for wallet balance + iota_config = discovery_info + sensors = [IotaBalanceSensor(wallet, iota_config) + for wallet in iota_config['wallets']] + + # Add sensor for node information + sensors.append(IotaNodeSensor(iota_config=iota_config)) + + add_devices(sensors) + + +class IotaBalanceSensor(IotaDevice): + """Implement an IOTA sensor for displaying wallets balance.""" + + def __init__(self, wallet_config, iota_config): + """Initialize the sensor.""" + super().__init__(name=wallet_config['name'], + seed=wallet_config['seed'], + iri=iota_config['iri'], + is_testnet=iota_config['testnet']) + self._state = None + + @property + def name(self): + """Return the name of the sensor.""" + return '{} Balance'.format(self._name) + + @property + def state(self): + """Return the state of the sensor.""" + return self._state + + @property + def unit_of_measurement(self): + """Return the unit of measurement.""" + return 'IOTA' + + def update(self): + """Fetch new balance from IRI.""" + self._state = self.api.get_inputs()['totalBalance'] + + +class IotaNodeSensor(IotaDevice): + """Implement an IOTA sensor for displaying attributes of node.""" + + def __init__(self, iota_config): + """Initialize the sensor.""" + super().__init__(name='Node Info', seed=None, iri=iota_config['iri'], + is_testnet=iota_config['testnet']) + self._state = None + self._attr = {'url': self.iri, 'testnet': self.is_testnet} + + @property + def name(self): + """Return the name of the sensor.""" + return 'IOTA Node' + + @property + def state(self): + """Return the state of the sensor.""" + return self._state + + @property + def device_state_attributes(self): + """Return the state attributes of the device.""" + return self._attr + + def update(self): + """Fetch new attributes IRI node.""" + node_info = self.api.get_node_info() + self._state = node_info.get('appVersion') + + # convert values to raw string formats + self._attr.update({k: str(v) for k, v in node_info.items()}) diff --git a/requirements_all.txt b/requirements_all.txt index fba7605d688..17d591161e4 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -820,6 +820,9 @@ pynut2==2.1.2 # homeassistant.components.binary_sensor.nx584 pynx584==0.4 +# homeassistant.components.iota +pyota==2.0.3 + # homeassistant.components.sensor.otp pyotp==2.2.6