-
-
Notifications
You must be signed in to change notification settings - Fork 37.7k
Add juicenet platform #7668
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
Add juicenet platform #7668
Changes from 5 commits
221c29c
fefa866
ee234a4
e62b243
884457c
d198aaa
243eadc
9448e85
eceadf7
34231a2
1a5bb9e
8b023b8
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,104 @@ | ||
| """ | ||
| Support for Juicenet cloud. | ||
|
|
||
| For more details about this component, please refer to the documentation at | ||
| https://home-assistant.io/components/juicenet | ||
| """ | ||
|
|
||
| import logging | ||
| import time | ||
|
|
||
| import voluptuous as vol | ||
|
|
||
| from homeassistant.helpers import discovery | ||
| from homeassistant.const import CONF_ACCESS_TOKEN | ||
| from homeassistant.helpers.entity import Entity | ||
| import homeassistant.helpers.config_validation as cv | ||
|
|
||
| REQUIREMENTS = ['python-juicenet==0.0.3'] | ||
|
|
||
| _LOGGER = logging.getLogger(__name__) | ||
|
|
||
| DOMAIN = 'juicenet' | ||
|
|
||
| SERVICE_ADD_NEW_DEVICES = 'add_new_devices' | ||
| SERVICE_REFRESH_STATES = 'refresh_state_from_juicenet' | ||
|
|
||
| CONFIG_SCHEMA = vol.Schema({ | ||
| DOMAIN: vol.Schema({ | ||
| vol.Required(CONF_ACCESS_TOKEN): cv.string | ||
| }) | ||
| }, extra=vol.ALLOW_EXTRA) | ||
|
|
||
|
|
||
| def setup(hass, 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. expected 2 blank lines, found 1 |
||
| """Set up the Juicenet component.""" | ||
| import pyjuicenet | ||
|
|
||
| hass.data[DOMAIN] = {} | ||
| hass.data[DOMAIN]['unique_ids'] = [] | ||
| hass.data[DOMAIN]['entities'] = {} | ||
|
Member
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're no longer using this?
Member
Author
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 |
||
|
|
||
| access_token = config[DOMAIN].get(CONF_ACCESS_TOKEN) | ||
|
|
||
| hass.data[DOMAIN]['api'] = pyjuicenet.Api(access_token) | ||
|
|
||
| def force_update(call): | ||
| """Force all devices to poll the Juicenet API.""" | ||
| _LOGGER.info("Refreshing Juicenet states from API") | ||
| for entity_list in hass[DOMAIN]['entities'].values(): | ||
| for entity in entity_list: | ||
| time.sleep(1) | ||
|
Member
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. Please don't use sleep. Can you fetch all the data at once and then notifiy the entities with new info? |
||
| entity.schedule_update_ha_state(True) | ||
| hass.services.register(DOMAIN, SERVICE_REFRESH_STATES, force_update) | ||
|
|
||
| def pull_new_devices(call): | ||
| """Pull new devices added to users Juicenet account since startup.""" | ||
| _LOGGER.info("Getting new devices from Juicenet API") | ||
| discovery.load_platform(hass, 'sensor', DOMAIN, {}, config) | ||
|
Member
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 a very weird way of "pulling" new devices. Why can't you talk to the API directly? |
||
| hass.services.register(DOMAIN, SERVICE_ADD_NEW_DEVICES, pull_new_devices) | ||
|
|
||
| hass.data[DOMAIN]['entities']['sensor'] = [] | ||
| discovery.load_platform(hass, 'sensor', DOMAIN, {}, config) | ||
|
|
||
| return True | ||
|
|
||
|
|
||
| class JuicenetDevice(Entity): | ||
|
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. expected 2 blank lines, found 1 |
||
| """Represent a base Juicenet device.""" | ||
|
|
||
| def __init__(self, device, sensor_type, hass): | ||
| """Initialise the sensor.""" | ||
| self.hass = hass | ||
| self.device = device | ||
| self.type = sensor_type | ||
| hass.data[DOMAIN]['unique_ids'].append(self.device.id()) | ||
|
|
||
| @property | ||
| def name(self): | ||
| """Return the name of the device.""" | ||
| return self.device.name() | ||
|
|
||
| def update(self): | ||
| """Update state of the device.""" | ||
| self.device.update_state() | ||
|
|
||
| @property | ||
| def device_state_attributes(self): | ||
| """Return the state attributes.""" | ||
| attributes = {} | ||
| if self.type == 'status': | ||
|
Member
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 shouldn't be in a generic JuiceNet entity. This is part of an implementation. |
||
| man_dev_id = self._manufacturer_device_id | ||
| if man_dev_id: | ||
| attributes["manufacturer_device_id"] = man_dev_id | ||
| return attributes | ||
|
|
||
| @property | ||
| def _manufacturer_device_id(self): | ||
| """Return the manufacturer device id.""" | ||
| return self.device.id() | ||
|
|
||
| @property | ||
| def _token(self): | ||
| """Return the device API token.""" | ||
| return self.device.token() | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,125 @@ | ||
| """ | ||
| Support for monitoring juicenet/juicepoint/juicebox based EVSE sensors. | ||
|
|
||
| For more details about this platform, please refer to the documentation at | ||
| at https://home-assistant.io/components/sensor.juicenet/ | ||
| """ | ||
|
|
||
| import asyncio | ||
|
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. 'asyncio' imported but unused |
||
| import logging | ||
|
|
||
| from homeassistant.const import TEMP_CELSIUS | ||
| from homeassistant.helpers.entity import Entity | ||
| from homeassistant.components.juicenet import JuicenetDevice, DOMAIN | ||
|
|
||
| DEPENDENCIES = ['juicenet'] | ||
| _LOGGER = logging.getLogger(__name__) | ||
|
|
||
| SENSOR_TYPES = { | ||
| 'status': ['Charging Status', None], | ||
| 'temperature': ['Temperature', TEMP_CELSIUS], | ||
| 'voltage': ['Voltage', 'V'], | ||
| 'amps': ['Amps', 'A'], | ||
| 'watts': ['Watts', 'W'], | ||
| 'charge_time': ['Charge time', 's'], | ||
| 'energy_added': ['Energy added', 'Wh'] | ||
| } | ||
|
|
||
|
|
||
| def setup_platform(hass, config, add_devices, discovery_info=None): | ||
| """Set up the Juicenet sensor.""" | ||
| api = hass.data[DOMAIN]['api'] | ||
|
|
||
| dev = [] | ||
| for device in api.get_devices(): | ||
| _id = device.id() | ||
| if _id not in hass.data[DOMAIN]['unique_ids']: | ||
|
Member
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 don't have to do this, Home Assistant does this automatically as long as you implement the property unique_id. |
||
| for variable in SENSOR_TYPES: | ||
| dev.append(JuicenetSensorDevice(device, variable, hass)) | ||
|
|
||
| add_devices(dev) | ||
|
|
||
|
|
||
| class JuicenetSensorDevice(JuicenetDevice, Entity): | ||
| """Implementation of a Juicenet sensor.""" | ||
|
|
||
| def __init__(self, device, sensor_type, hass): | ||
| """Initialise the sensor.""" | ||
| super().__init__(device, sensor_type, hass) | ||
| self._name = SENSOR_TYPES[sensor_type][0] | ||
| self._unit_of_measurement = SENSOR_TYPES[sensor_type][1] | ||
|
|
||
| @asyncio.coroutine | ||
| def async_added_to_hass(self): | ||
| """Callback when entity is added to hass.""" | ||
| self.hass.data[DOMAIN]['entities']['sensor'].append(self) | ||
|
Member
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 are you appending it, is this still necessary?
Member
Author
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 |
||
|
|
||
| @property | ||
| def name(self): | ||
| """Return the name of the device.""" | ||
| return '{} {}'.format(self.device.name(), self._name) | ||
|
|
||
| @property | ||
| def icon(self): | ||
| """Return the icon of the sensor.""" | ||
| icon = None | ||
| if self.type == 'status': | ||
| status = self.device.getStatus() | ||
| if status == 'standby': | ||
| icon = 'mdi:power-plug-off' | ||
| elif status == 'plugged': | ||
| icon = 'mdi:power-plug' | ||
| elif status == 'charging': | ||
| icon = 'mdi:battery-positive' | ||
| elif self.type == 'temperature': | ||
| icon = 'mdi:thermometer' | ||
| elif self.type == 'voltage': | ||
| icon = 'mdi:flash' | ||
| elif self.type == 'amps': | ||
| icon = 'mdi:flash' | ||
| elif self.type == 'watts': | ||
| icon = 'mdi:flash' | ||
| elif self.type == 'charge_time': | ||
| icon = 'mdi:timer' | ||
| elif self.type == 'energy_added': | ||
| icon = 'mdi:flash' | ||
| else: | ||
| icon = 'mdi:eye' | ||
|
Member
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 should return |
||
| return icon | ||
|
|
||
| @property | ||
| def unit_of_measurement(self): | ||
| """Return the unit the value is expressed in.""" | ||
| return self._unit_of_measurement | ||
|
|
||
| @property | ||
| def state(self): | ||
| """Return the state.""" | ||
| state = None | ||
| if self.type == 'status': | ||
| state = self.device.getStatus() | ||
| elif self.type == 'temperature': | ||
| state = self.device.getTemperature() | ||
| elif self.type == 'voltage': | ||
| state = self.device.getVoltage() | ||
| elif self.type == 'amps': | ||
| state = self.device.getAmps() | ||
| elif self.type == 'watts': | ||
| state = self.device.getWatts() | ||
| elif self.type == 'charge_time': | ||
| state = self.device.getChargeTime() | ||
| elif self.type == 'energy_added': | ||
| state = self.device.getEnergyAdded() | ||
| else: | ||
| state = 'Unknown' | ||
| return state | ||
|
|
||
| @property | ||
| def device_state_attributes(self): | ||
| """Return the state attributes.""" | ||
| attributes = super().device_state_attributes | ||
| if self.type == 'status': | ||
| man_dev_id = self.device.id() | ||
| if man_dev_id: | ||
|
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. undefined name 'man_dev_id' |
||
| attributes["manufacturer_device_id"] = man_dev_id | ||
|
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. undefined name 'man_dev_id' |
||
| return attributes | ||
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.
'time' imported but unused