-
-
Notifications
You must be signed in to change notification settings - Fork 30.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Iota wallet #11398
Iota wallet #11398
Changes from 6 commits
e3ea17b
6ddaa34
8f07362
a1c0bf2
4845cb7
6cbdb9b
e06b875
9890675
667146e
32db13a
aa761ce
676b800
8b3d767
d7f1f10
1fae91a
03347dc
9290828
87224b2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
""" | ||
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 | ||
|
||
DOMAIN = 'iota' | ||
|
||
REQUIREMENTS = ['pyota==2.0.3'] | ||
|
||
IOTA_PLATFORMS = ['sensor'] | ||
|
||
SCAN_INTERVAL = timedelta(minutes=10) | ||
|
||
CONF_IRI = 'iri' | ||
CONF_TESTNET = 'testnet' | ||
CONF_WALLETS = 'wallets' | ||
CONF_WALLET_NAME = 'name' | ||
CONF_WALLET_SEED = 'seed' | ||
|
||
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): vol.All(str), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can remove There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
vol.Optional(CONF_TESTNET, default=False): cv.boolean, | ||
vol.Required(CONF_WALLETS): vol.All(cv.ensure_list, [WALLET_CONFIG]) | ||
}) | ||
}, extra=vol.ALLOW_EXTRA) | ||
|
||
_LOGGER = logging.getLogger(__name__) | ||
|
||
|
||
def setup(hass, config): | ||
"""Setup IOTA component.""" | ||
# Set domain sepecific data | ||
iota_config = config[DOMAIN] | ||
hass.data[DOMAIN] = { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Configuration is supposed to be past in discovery info dict, ie fourth parameter of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thx. Changed it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So now you don't need to store the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
'iri': iota_config[CONF_IRI], | ||
'is_testnet': iota_config[CONF_TESTNET], | ||
'wallets': iota_config[CONF_WALLETS] | ||
} | ||
|
||
# Set states of IRI config | ||
hass.states.set('iota.iri', hass.data[DOMAIN]['iri']) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do you want to set these states? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the URL of the IOTA node to connect to, which may change. It is a separate state in order to see current URL of the node in the UI. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Report it as a state attribute on the node sensor entity instead. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
hass.states.set('iota.is_testnet', hass.data[DOMAIN]['is_testnet']) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done ;) |
||
|
||
# Load platforms | ||
for platform in IOTA_PLATFORMS: | ||
load_platform(hass, platform, DOMAIN, {}, iota_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 should_poll(self): | ||
"""Get polling requirement from IOTA device.""" | ||
return True | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the default. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thx. removed it |
||
|
||
@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) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 homeassistant.components.iota import DOMAIN as IOTA_DOMAIN, IotaDevice | ||
|
||
_LOGGER = logging.getLogger(__name__) | ||
|
||
DEPENDENCIES = ['iota'] | ||
|
||
|
||
def setup_platform(hass, config, add_devices, discovery_info=None): | ||
"""Set up the IOTA sensor.""" | ||
# Add sensors for wallet balance | ||
iota_config = hass.data[IOTA_DOMAIN] | ||
balance_sensors = [IotaBalanceSensor(wallet, iota_config) | ||
for wallet in iota_config['wallets']] | ||
add_devices(balance_sensors) | ||
|
||
# Add sensor for node information | ||
add_devices([IotaNodeSensor(iota_config=iota_config)]) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add all devices in one go. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
|
||
|
||
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['is_testnet']) | ||
self._state = 0 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Set it to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
|
||
@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): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I assume that this should be a binary sensor. A node can be offline or online. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nope, a node can have multiple attributes, which are changing over time (https://iota.readme.io/v1.2.0/reference#getnodeinfo) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Attributes and state are not the same. A binary sensor can have attributes as well. If a node is always present then it's doesn't make sense. There are a dozen values available from getNodeInfo. Those details should be exposed as attributes. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Information about the node is part of the attributes of the node sensor and should be part of the wallet. |
||
"""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['is_testnet']) | ||
self._state = "" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unknown state should be initialized with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
self._attr = dict() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Init with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
|
||
@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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. At the moment this will stay empty. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missed that line. |
||
|
||
@property | ||
def unit_of_measurement(self): | ||
"""Return the unit of measurement.""" | ||
return '' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not a valid unit of measurement. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. removed it |
||
|
||
def update(self): | ||
"""Fetch new attribures IRI node.""" | ||
node_info = self.api.get_node_info() | ||
self._state = node_info.get('appVersion') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How is it useful to know the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The value of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would still require an additional part because it only shows the version and not if the node is up-to-date. |
||
# convert values to raw string formats | ||
self._attr = {k: str(v) for k, v in node_info.items()} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is only a sensor. This doesn't require to include a component.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey, not yet. I am going to add more features to this component. Is it necessary to be a sensor only PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, it's the right way to create a component if there is coming a binary sensor or switch platform which can share the common stuff. Otherwise everything can be handled in the platform itself as no sharing is needed.