-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
c839e42
commit 3b1c526
Showing
7 changed files
with
244 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
.DS_Store |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,57 @@ | ||
# Home Assistant Omnik Inverter | ||
The Omnik Inverter Sensor component will retrieve data from a local Omnik inverter. | ||
It has been tested and developed on an Omnik 4K TL2 and it is currently unknown if it works for other inverters. | ||
|
||
The values will be presented as sensors in [Home Assistant](https://home-assistant.io/). | ||
|
||
## Requirements | ||
|
||
Your Omnik Inverter needs to be connected to your local network, as this custom component will utilise the web interface of the Omnik inverter to read data. All you need to know is the IP address of the Omnik inverter and you are good to go. | ||
|
||
## How does it work? | ||
|
||
The web interface has a javascript file that contains the actual values. This is updated (afaik) every minute. You can visit it in your browser at http://your_omnik_ip_address/js/status.js | ||
|
||
Looking at the data it contains lots of information, but there's one part we're interested in: | ||
|
||
```js | ||
// ... Bunch of data | ||
var webData="NLBN1234567A1234,iv4-V6.5-140-4,V5.2-42819,omnik4000tl2,4000,1920,429,87419,,3,"; | ||
// ... Even more data. | ||
``` | ||
|
||
This line contains your serial number, firmware versions, hardware information _and_ the current power output (1920) in watts and the total energy generated today (429) in watts. | ||
|
||
This custom component basically requests the URL, looks for the _webData_ part and extracts the values as two sensors. | ||
- `sensor.solar_power_current` (Watt) | ||
- `sensor.solar_power_today` (kWh) | ||
|
||
For some reason my Omnik inverter reset the power today to 0.0 after 21:00, so the total power today is cached by the custom component until the 00:00 the next day. | ||
|
||
## Installation | ||
|
||
Create a directory called `omnik_inverter` in the `<config directory>/custom_components/` directory on your Home Assistant instance. | ||
Install this component by copying all files in `/custom_components/omnik_inverter/` folder from this repo into the new `<config directory>/custom_components/omnik_inverter/` directory you just created. | ||
|
||
This is how your custom_components directory should be: | ||
```bash | ||
custom_components | ||
├── omnik_inverter | ||
│ ├── __init__.py | ||
│ ├── manifest.json | ||
│ └── sensor.py | ||
``` | ||
|
||
## Configuration example | ||
|
||
To enable this sensor, add the following lines to your configuration.yaml file: | ||
|
||
``` YAML | ||
sensor: | ||
- platform: omnik_inverter | ||
host: 192.168.100.100 | ||
``` | ||
## References | ||
Got my inspiration from: https://community.home-assistant.io/t/omink-inverter-in-home-assistant/102455/36 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
"""The omnik inverter sensor integration.""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"domain": "omnik_inverter", | ||
"name": "Omnik Inverter", | ||
"documentation": "https://github.com/robbinjanssen/home-assistant-omnik-inverter/blob/master/README.md", | ||
"dependencies": [], | ||
"codeowners": [], | ||
"requirements": [] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
""" | ||
configuration.yaml | ||
sensor: | ||
- platform: omnik_inverter | ||
host: 192.168.100.100 | ||
""" | ||
import logging | ||
from datetime import timedelta | ||
from datetime import datetime | ||
|
||
import voluptuous as vol | ||
|
||
from homeassistant.components.sensor import PLATFORM_SCHEMA | ||
import homeassistant.helpers.config_validation as cv | ||
from homeassistant.const import (CONF_HOST) | ||
from homeassistant.util import Throttle | ||
from homeassistant.helpers.entity import Entity | ||
|
||
from urllib.request import urlopen | ||
|
||
import re | ||
import pickle | ||
|
||
VERSION = '0.0.1' | ||
|
||
BASE_URL = 'http://{0}/js/status.js' | ||
BASE_CACHE_NAME = '.{0}.pickle' | ||
|
||
_LOGGER = logging.getLogger(__name__) | ||
|
||
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=60) | ||
|
||
SENSOR_TYPES = { | ||
'powercurrent': ['Solar Power Current', 'Watt', 'mdi:weather-sunny'], | ||
'powertoday': ['Solar Power Today', 'kWh', 'mdi:flash'], | ||
} | ||
|
||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ | ||
vol.Required(CONF_HOST): cv.string, | ||
}) | ||
|
||
|
||
def setup_platform(hass, config, add_devices, discovery_info=None): | ||
"""Setup the Solar Portal sensors.""" | ||
host = config.get(CONF_HOST) | ||
|
||
try: | ||
data = OmnikInverterWeb(host) | ||
except RunTimeError: | ||
_LOGGER.error("Unable to connect fetch data from Omnik Inverter %s", | ||
host) | ||
return False | ||
|
||
entities = [] | ||
|
||
for sensor_type in SENSOR_TYPES: | ||
entities.append(OmnikInverterSensor(data, sensor_type)) | ||
|
||
add_devices(entities) | ||
|
||
|
||
class OmnikInverterWeb(object): | ||
"""Representation of the Omnik Inverter Web.""" | ||
|
||
def __init__(self, host): | ||
"""Initialize the inverter.""" | ||
self._host = host | ||
self.result = None | ||
|
||
@Throttle(MIN_TIME_BETWEEN_UPDATES) | ||
def update(self): | ||
"""Update the data from the omnik inverter.""" | ||
dataurl = BASE_URL.format(self._host) | ||
r = urlopen(dataurl).read() | ||
|
||
"""Remove strange characters from the result.""" | ||
result = r.decode('ascii', 'ignore') | ||
|
||
"""Find the webData.""" | ||
matches = re.search('webData="(.*),";function', result) | ||
|
||
"""Split the values.""" | ||
self.result = matches.group(1).split(',') | ||
|
||
_LOGGER.debug("Data = %s", self.result) | ||
|
||
|
||
class OmnikInverterSensor(Entity): | ||
"""Representation of a OmnikInverter sensor from the web data.""" | ||
|
||
def __init__(self, data, sensor_type): | ||
"""Initialize the sensor.""" | ||
self.data = data | ||
self.type = sensor_type | ||
self._name = SENSOR_TYPES[self.type][0] | ||
self._unit_of_measurement = SENSOR_TYPES[self.type][1] | ||
self._icon = SENSOR_TYPES[self.type][2] | ||
self._state = None | ||
self.update() | ||
|
||
@property | ||
def name(self): | ||
"""Return the name of the sensor.""" | ||
return self._name | ||
|
||
@property | ||
def icon(self): | ||
"""Icon to use in the frontend, if any.""" | ||
return self._icon | ||
|
||
@property | ||
def state(self): | ||
"""Return the state of the sensor.""" | ||
return self._state | ||
|
||
@property | ||
def unit_of_measurement(self): | ||
"""Return the unit of measurement of this entity, if any.""" | ||
return self._unit_of_measurement | ||
|
||
def update(self): | ||
"""Get the latest data and use it to update our sensor state.""" | ||
self.data.update() | ||
|
||
"""Get the result data.""" | ||
result = self.data.result | ||
|
||
if self.type == 'powercurrent': | ||
"""Update the sensor state.""" | ||
self._state = int(result[5]) | ||
elif self.type == 'powertoday': | ||
"""Define the cache name.""" | ||
cacheName = BASE_CACHE_NAME.format(self.type) | ||
|
||
"""Prepare the next values.""" | ||
nextValue = int(result[6]) | ||
nextTime = int(datetime.now().strftime('%H%M')) | ||
|
||
"""Fetch data from the cache.""" | ||
try: | ||
cache = pickle.load(open(cacheName, 'rb')) | ||
except (OSError, IOError, EOFError) as e: | ||
cache = [0, 0] | ||
|
||
"""Set the cache values.""" | ||
cacheValue = int(cache[0]) | ||
cacheTime = int(cache[1]) | ||
|
||
""" | ||
If somehow the currentPowerToday is lower than the cached | ||
version, keep the cached version. | ||
""" | ||
if (nextValue < cacheValue): | ||
nextValue = cacheValue | ||
|
||
""" | ||
If today has passed, use the actual value from the | ||
omnik inverter. | ||
""" | ||
if (cacheTime > nextTime): | ||
nextValue = int(result[6]) | ||
|
||
"""Store new stats.""" | ||
pickle.dump([nextValue, nextTime], open(cacheName, 'wb')) | ||
|
||
"""Update the sensor state, divide by 100 to make it kWh.""" | ||
self._state = (nextValue / 100) |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# Omnik Inverter Sensor Component for Home Assistant. | ||
|
||
The Omnik solar sensor component will retrieve data from an Omnik solar inverter. | ||
The values will be presented as sensors (or attributes of sensors) in Home Assistant. | ||
|
||
## Example | ||
![Omnik Inverter Sensor Entities](https://github.com/robbinjanssen/home-assistant-omnik-inverter/blob/master/images/entities.png) | ||
|
||
## Documentation | ||
Find the full documentation [here](https://github.com/robbinjanssen/home-assistant-omnik-inverter/blob/master/README.md). |