Skip to content

Commit

Permalink
Merge pull request #15 from JanJaapKo/addBattery
Browse files Browse the repository at this point in the history
add logging to file
  • Loading branch information
JanJaapKo authored Sep 6, 2022
2 parents ea1284c + f4351e6 commit a726756
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 90 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
*.pyc
*.pyc
*.log
45 changes: 30 additions & 15 deletions GoodWe.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
import requests
import time
import exceptions
import logging

try:
import Domoticz
debug = False
Expand Down Expand Up @@ -120,7 +122,7 @@ def createDevices(self, Devices):
"SelectorStyle": "1"}
Domoticz.Device(Name="Inverter state (SN: " + self.serialNumber + ")",
Unit=(self.inverterStateUnit), TypeName="Selector Switch", Image=1,
Options=Options).Create()
Options=Options, Used=1).Create()

if self.inputVoltage1Unit not in Devices:
Domoticz.Device(Name="Inverter input 1 voltage (SN: " + self.serialNumber + ")",
Expand Down Expand Up @@ -212,6 +214,7 @@ def __init__(self, stationData=None, id=None, firstDevice=0):
self._address = stationData["info"]["address"]
self._id = stationData["info"]["powerstation_id"]
Domoticz.Debug("create station with id: '" + self._id + "' and inverters: " + str(len(stationData["inverter"])) )
logging.debug("create station with id: '" + self._id + "' and inverters: " + str(len(stationData["inverter"])) )
self.createInverters(stationData["inverter"])

def __repr__(self):
Expand All @@ -221,6 +224,7 @@ def createInverters(self, inverterData):
for inverter in inverterData:
self.inverters[inverter['sn']] = Inverter(inverter, self._firstDevice)
Domoticz.Debug("inverter created: '" + str(inverter['sn']) + "'")
logging.debug("inverter created: '" + str(inverter['sn']) + "'")
self._firstDevice += self.inverters[inverter['sn']].domoticzDevices

@property
Expand Down Expand Up @@ -292,15 +296,16 @@ def createStation(self, key, stationData):
powerStation = PowerStation(stationData=stationData)
self.powerStationList.update({key : powerStation})
Domoticz.Log("PowerStation created: '" + powerStation.id + "' with key '" + str(key) + "'")
logging.info("PowerStation created: '" + powerStation.id + "' with key '" + str(key) + "'")

def createStationV2(self, stationData):
powerStation = PowerStation(stationData=stationData)
self.powerStationList.update({1 : powerStation})
Domoticz.Log("PowerStation created: '" + powerStation.id + "'")

logging.info("PowerStation created: '" + powerStation.id + "'")

def apiRequestHeaders(self):
Domoticz.Debug("build apiRequestHeaders with token: '" + json.dumps(self.token) + "'" )
logging.debug("build apiRequestHeaders with token: '" + json.dumps(self.token) + "'" )
return {
'Content-Type': 'application/json; charset=utf-8',
'Connection': 'keep-alive',
Expand All @@ -311,23 +316,30 @@ def apiRequestHeaders(self):
}

def apiRequestHeadersV2(self):
Domoticz.Debug("build apiRequestHeaders with token: '" + json.dumps(self.token) + "'" )
logging.debug("build apiRequestHeaders with token: '" + json.dumps(self.token) + "'" )
return {
'User-Agent': 'Domoticz/1.0',
'token': json.dumps(self.token)
}

def tokenRequest(self):
Domoticz.Debug("build tokenRequest with UN: '" + self.Username + "', pwd: '" + self.Password +"'")
logging.debug("build tokenRequest with UN: '" + self.Username + "', pwd: '" + self.Password +"'")
url = '/v2/Common/CrossLogin'
loginPayload = {
'account': self.Username,
'pwd': self.Password,
}

r = requests.post(self.base_url + url, headers=self.apiRequestHeadersV2(), data=loginPayload, timeout=5)
try:
r = requests.post(self.base_url + url, headers=self.apiRequestHeadersV2(), data=loginPayload, timeout=10)
except requests.exceptions.RequestException as exp:
logging.error("RequestException: " + str(exp))
Domoticz.Error("RequestException: " + str(exp))
self.tokenAvailable = False
return

#r.raise_for_status()
Domoticz.Debug("building token request on URL: " + r.url + " which returned status code: " + str(r.status_code) + " and response length = " + str(len(r.text)))
logging.debug("building token request on URL: " + r.url + " which returned status code: " + str(r.status_code) + " and response length = " + str(len(r.text)))
apiResponse = r.json()
if apiResponse["code"] == 100005:
raise exceptions.GoodweException("invalid password or username")
Expand All @@ -340,10 +352,11 @@ def tokenRequest(self):

if apiResponse == 'Null':
Domoticz.Log("SEMS API Token not received")
logging.info("SEMS API Token not received")
self.tokenAvailable = False
else:
self.token = apiResponse['data']
Domoticz.Debug("SEMS API Token received: " + json.dumps(self.token))
logging.debug("SEMS API Token received: " + json.dumps(self.token))
self.tokenAvailable = True
self.base_url = apiResponse['api']

Expand All @@ -362,16 +375,16 @@ def tokenRequest(self):
# }

def stationListRequest(self):
Domoticz.Debug("build stationListRequest")
logging.debug("build stationListRequest")
url = 'v2/HistoryData/QueryPowerStationByHistory'
r = requests.post(self.base_url + url, headers=self.apiRequestHeadersV2(), timeout=5)

Domoticz.Debug("building station list on URL: " + r.url + " which returned status code: " + str(r.status_code) + " and response length = " + str(len(r.text)))
logging.debug("building station list on URL: " + r.url + " which returned status code: " + str(r.status_code) + " and response length = " + str(len(r.text)))

return r.status_code

def stationDataRequestV1(self, stationIndex):
Domoticz.Debug("build stationDataRequest with number of stations (len powerStationList) = '" + str(self.numStations) + "' for PS index: '" + str(stationIndex) + "'")
logging.debug("build stationDataRequest with number of stations (len powerStationList) = '" + str(self.numStations) + "' for PS index: '" + str(stationIndex) + "'")
#powerStation = self.powerStationList[self.powerStationIndex]
powerStation = self.powerStationList[stationIndex]
return {
Expand All @@ -386,7 +399,7 @@ def stationDataRequestV1(self, stationIndex):
def stationDataRequestV2(self, stationId):
for i in range(1, 4):
try:
Domoticz.Debug("build stationDataRequest for 1 station, attempt: " + str(i))
logging.debug("build stationDataRequest for 1 station, attempt: " + str(i))

responseData = self.stationDataRequest(stationId)
try:
Expand All @@ -399,11 +412,13 @@ def stationDataRequestV2(self, stationId):
return responseData['data']
elif code == 100001 or code == 100002:
#token has expired or is not valid
logging.info("Failed to call GoodWe API (no valid token), will be refreshed")
Domoticz.Log("Failed to call GoodWe API (no valid token), will be refreshed")
self.tokenRequest()
else:
raise exceptions.FailureWithErrorCode(code)
except requests.exceptions.RequestException as exp:
logging.error("RequestException: " + str(exp))
Domoticz.Error("RequestException: " + str(exp))
time.sleep(i ** 3)
else:
Expand All @@ -415,8 +430,8 @@ def stationDataRequest(self, stationId):
'powerStationId' : stationId
}

r = requests.post(self.base_url + url, headers=self.apiRequestHeadersV2(), data=payload, timeout=5)
Domoticz.Debug("building station data request on URL: " + r.url + " which returned status code: " + str(r.status_code) + " and response length = " + str(len(r.text)))
#Domoticz.Debug("response station data request : " + json.dumps(r.json()))
r = requests.post(self.base_url + url, headers=self.apiRequestHeadersV2(), data=payload, timeout=10)
logging.debug("building station data request on URL: " + r.url + " which returned status code: " + str(r.status_code) + " and response length = " + str(len(r.text)))
logging.debug("response station data request : " + json.dumps(r.json()))
responseData = r.json()
return responseData
28 changes: 22 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,28 @@ Current features
1. Get all stations for a specific user account
2. Automatically get data for all inverters (for one station)
3. The following devices are added to Domoticz for each inverter:
- temperature: Inverter temperature (Celcius)
- power: Current and total output power (Watts)
- current - Output current (ampere)
- voltage - Output Voltage
- frequency - Output frequncy (Hz, first phase)
- input strings: Voltage, current and power per string

|Unit |Description |Type |Remark
|--- |--- |--- |---
|1 |(Hardware name) - Inverter temperature (SN: (your S/N)) |LaCrosse TX3 |
|2 |(Hardware name) - Inverter output current (SN: (your S/N)) |Current |
|3 |(Hardware name) - Inverter output voltage (SN: (your S/N)) |Voltage |
|4 |(Hardware name) - Inverter output power (SN: (your S/N)) |kWh | default: used
|5 |(Hardware name) - Inverter input 1 voltage (SN: (your S/N)) |Voltage |
|6 |(Hardware name) - Inverter input 1 Current (SN: (your S/N)) |Current |
|7 |(Hardware name) - Inverter input 2 voltage (SN: (your S/N)) |Voltage |
|8 |(Hardware name) - Inverter input 2 Current (SN: (your S/N)) |Current |
|9 |(Hardware name) - Inverter state (SN: (your S/N)) |Selector Switch | default: used
|10 |(Hardware name) - Solar inverter input 3 voltage (SN: (your S/N)) |Voltage|
|11 |(Hardware name) - Solar inverter input 3 Current (SN: (your S/N)) |Current|
|12 |(Hardware name) - Solar inverter input 4 voltage (SN: (your S/N)) |Voltage|
|13 |(Hardware name) - Solar inverter input 4 Current (SN: (your S/N)) |Current|
|14 |(Hardware name) - Inverter input 1 power (SN: (your S/N)) |kWh | default: used. calculated in plugin
|15 |(Hardware name) - Inverter input 2 power (SN: (your S/N)) |kWh | calculated in plugin
|16 |(Hardware name) - Inverter input 3 power (SN: (your S/N)) |kWh | calculated in plugin
|17 |(Hardware name) - Inverter input 4 power (SN: (your S/N)) |kWh | calculated in plugin
|18 |(Hardware name) - Inverter output frequency 1 |Custom Sensor |


There is a lot more information available trough the GoodWe API if you would like to have a specific feature added to this plugin please submit an issue as indicated in the paragraph above.

Expand Down
Loading

0 comments on commit a726756

Please sign in to comment.