Skip to content
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

Pieterzen get inverter info #5

Merged
merged 2 commits into from May 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Expand Up @@ -8,7 +8,7 @@
- platform: solaxcloud
username: USERNAME
password: PASSWORD
inverter_serial: SERIAL
inverter_number: NUMBER
site_id: SITE ID
```
- Verify that the custom entities are available in home assistant
- To obtain your site id. Login to solaxcloud.com and click on Sites in the left menu. Inspect the Site-name with your browser developer tools. You should see something like "showAnalysis('xxxxxxxxxxxxxx','Home')" in the html code.
- Verify that the custom entities are available in home assistant.
130 changes: 102 additions & 28 deletions sensor.py
@@ -1,5 +1,6 @@
import json
import requests
import logging
import voluptuous as vol
import homeassistant.helpers.config_validation as cv

Expand All @@ -14,60 +15,76 @@

CONF_USERNAME = "username"
CONF_PASSWORD = "password"
CONF_INVERTER_SERIAL = "inverter_serial"
CONF_INVERTER_NUMBER = "inverter_number"
CONF_SITE_ID = "site_id"

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_USERNAME): cv.string,
vol.Required(CONF_PASSWORD): cv.string,
vol.Required(CONF_INVERTER_SERIAL): cv.string,
vol.Required(CONF_INVERTER_NUMBER): cv.string,
vol.Required(CONF_SITE_ID): cv.string,
}
)

def setup_platform(hass, config, add_entities, discovery_info=None):
solax_cloud = SolaxCloud(hass, config[CONF_USERNAME], config[CONF_PASSWORD], config[CONF_INVERTER_SERIAL], config[CONF_INVERTER_NUMBER])
add_entities([SolarPowerSensor(hass, solax_cloud), GridPowerSensor(hass, solax_cloud), InverterTemperatureSensor(hass, solax_cloud), InverterTotalYieldSensor(hass, solax_cloud), InverterDailyYieldSensor(hass, solax_cloud)], True)
solax_cloud = SolaxCloud(hass, config[CONF_USERNAME], config[CONF_PASSWORD], config[CONF_SITE_ID])
add_entities([SolarPowerSensor(hass, solax_cloud),
GridPowerSensor(hass, solax_cloud),
InverterTemperatureSensor(hass, solax_cloud),
InverterTotalYieldSensor(hass, solax_cloud),
InverterDailyYieldSensor(hass, solax_cloud)
], True)

class SolaxCloud:
def __init__(self, hass, username, password, inverter_serial, inverter_ssid):
def __init__(self, hass, username, password, site_id):
self.hass = hass
self.logger = logging.getLogger(__name__)
self._username = username
self._password = password
self._inverter_serial = inverter_serial
self._inverter_ssid = inverter_ssid
self._base_url = 'http://47.254.152.24:6080'
self._site_id = site_id
self._base_url = 'http://www.solaxcloud.com:6080'
self._login_endpoint = '/proxy/login/login'
self._data_endpoint = '/proxy/inverter/getDailyInfo'
self._data_endpoint = '/proxy/mysite/getInverterInfo'
self.data = []
self.inverter_name = 'Solax'

def get_token_id(self):
resp = None
try:
uri = self._base_url + self._login_endpoint + '?userName=' + self._username + '&password=' + self._password
resp = requests.post(uri)
json_obj = resp.json()
return json_obj['result']['tokenId']

# {'exception': '用户名或密码输入错误!', 'result': None, 'success': False}
if json_obj['success'] == False:
if json_obj['exception'] == '用户名或密码输入错误!':
self.logger.error('Invalid Username or Password')
elif json_obj['exception'] != '用户名或密码输入错误!':
self.logger.error('Other error:\r\n%s', json_obj['exception'])

return json_obj
else:
return json_obj['result']['tokenId']
except requests.exceptions.ConnectionError:
return resp
self.logger.error('Connection Error:\r\n%s', resp)
raise ConnectionAbortedError


# http://www.solaxcloud.com:6080/proxy/mysite/getInverterInfo?siteId=<SiteId>&tokenId=<TokenId>
def get_data(self):
resp = None
try:
today = date.today()
current_date = today.strftime('%Y-%m-%d')
token_id = self.get_token_id()
uri = self._base_url + self._data_endpoint + '?inverterSn=' + self._inverter_serial + '&wifiSn=' + self._inverter_ssid + '&tokenId=' + token_id + '&today=' + current_date
uri = self._base_url + self._data_endpoint + '?siteId=' + self._site_id + '&tokenId=' + token_id
resp = requests.post(uri)
json_obj = resp.json()
self.data = json_obj['result'].pop()
self.inverter_name = self.data['inverterSN']
except requests.exceptions.ConnectionError:
return resp

class InverterTotalYieldSensor(Entity):
def __init__(self, hass, solax_cloud):
self._name = 'Total yield'
self._name = solax_cloud.inverter_name + ' Total yield'
self.hass = hass
self.solax_cloud = solax_cloud

Expand All @@ -78,23 +95,23 @@ def name(self):
@property
def state(self):
data = self.solax_cloud.data
return int(data['yieldtotal'])
return int(data['totalYield'])

@property
def unit_of_measurement(self):
return 'kW'

@property
def icon(self):
return 'mdi:gauge-full'
return 'mdi:solar-power'

@Throttle(MIN_TIME_BETWEEN_UPDATES)
def update(self):
self.solax_cloud.get_data()

class InverterDailyYieldSensor(Entity):
def __init__(self, hass, solax_cloud):
self._name = 'Daily yield'
self._name = solax_cloud.inverter_name + ' Daily yield'
self.hass = hass
self.solax_cloud = solax_cloud

Expand All @@ -105,23 +122,23 @@ def name(self):
@property
def state(self):
data = self.solax_cloud.data
return int(data['yieldtoday'])
return int(data['todayYield'])

@property
def unit_of_measurement(self):
return 'kW'

@property
def icon(self):
return 'mdi:gauge-low'
return 'mdi:solar-power'

@Throttle(MIN_TIME_BETWEEN_UPDATES)
def update(self):
self.solax_cloud.get_data()

class InverterTemperatureSensor(Entity):
def __init__(self, hass, solax_cloud):
self._name = 'Temperature'
self._name = solax_cloud.inverter_name + ' Temperature'
self.hass = hass
self.solax_cloud = solax_cloud

Expand Down Expand Up @@ -150,7 +167,7 @@ class SolarPowerSensor(Entity):
def __init__(self, hass, solax_cloud):
self._state = None
self.hass = hass
self._name = 'Solar power'
self._name = solax_cloud.inverter_name + ' PV power'
self.solax_cloud = solax_cloud

@property
Expand All @@ -168,7 +185,7 @@ def unit_of_measurement(self):

@property
def icon(self):
return 'mdi:gauge'
return 'mdi:solar-power'

@Throttle(MIN_TIME_BETWEEN_UPDATES)
def update(self):
Expand All @@ -178,7 +195,7 @@ class GridPowerSensor(Entity):
def __init__(self, hass, solax_cloud):
self._state = None
self.hass = hass
self._name = 'Grid power'
self._name = solax_cloud.inverter_name +' Grid power'
self.solax_cloud = solax_cloud

@property
Expand All @@ -188,16 +205,73 @@ def name(self):
@property
def state(self):
data = self.solax_cloud.data
return int(self.solax_cloud.data['gridpower'])
return int(self.solax_cloud.data['gridPower'])

@property
def unit_of_measurement(self):
return 'W'

@property
def icon(self):
return 'mdi:gauge'
return 'mdi:solar-power'

@Throttle(MIN_TIME_BETWEEN_UPDATES)
def update(self):
self.solax_cloud.get_data()

# Other setup with info on enumerating the type fields
# https://github.com/wills106/homeassistant-config/blob/master/packages/solax.yaml

# Response example:
# {
# "exception": "查询成功!",
# "result": [
# {
# "wifiSN": "SWSMMS9LCT",
# "deviceName": null,
# "inverterSN": "XBE502F0000000",
# "accessTime": 1588579594000,
# "lastUpdateTime": 1588683933442,
# "pv1Current": 0.0,
# "pv2Current": 0.0,
# "pv3Current": null,
# "pv4Current": null,
# "pv1Voltage": 81.8,
# "pv2Voltage": 79.1,
# "pv3Voltage": null,
# "pv4Voltage": null,
# "powerdc1": 0.0,
# "powerdc2": 0.0,
# "powerdc3": null,
# "powerdc4": null,
# "totalYield": 30.0,
# "todayYield": 27.7,
# "iac1": 0.2,
# "vac1": 228.7,
# "pac1": 0.0,
# "fac1": 49.97,
# "iac2": 0.0,
# "vac2": 0.0,
# "pac2": 0.0,
# "fac2": 0.0,
# "iac3": 0.0,
# "vac3": 0.0,
# "pac3": 0.0,
# "fac3": 0.0,
# "gridPower": 0.0,
# "feedinPower": 0.0,
# "temperature": 34.0,
# "hours": 28,
# "accessTimes": "2020-05-04 16:06:34",
# "lastUpdateTimes": "2020-05-05 21:05:33",
# "phaseFlag": 1,
# "batteryFlag": 0,
# "inverterType": "4",
# "enableFlag": "1",
# "workMode": 0,
# "pvCount": 2,
# "transportType": 2
# }
# ],
# "success": true
# }