diff --git a/custom_components/saj_esolar/sensor.py b/custom_components/saj_esolar/sensor.py index 8bf82a3..a79374e 100644 --- a/custom_components/saj_esolar/sensor.py +++ b/custom_components/saj_esolar/sensor.py @@ -1,5 +1,5 @@ """ -Alternative for the SAJ local API sensor. Unfortunally there is no public api. +Alternative for the SAJ local API sensor. Unfortunally there is no public api. This Sensor will read the private api of the eSolar portal at https://fop.saj-electric.com/ """ @@ -25,8 +25,8 @@ ) from homeassistant.const import ( CONF_RESOURCES, - CONF_USERNAME, - CONF_PASSWORD, + CONF_USERNAME, + CONF_PASSWORD, CONF_SENSORS, CONF_DEVICE_ID, DEVICE_CLASS_ENERGY, @@ -76,7 +76,7 @@ def add_years(d, years): "lastUploadTime", "totalPlantTreeNum", "totalReduceCo2", - "todayAlarmNum", + "isAlarm", "plantuid", "plantname", "currency", @@ -144,7 +144,7 @@ def add_years(d, years): key="devOnlineNum", name="devOnlineNum", icon="mdi:solar-panel", - ), + ), SensorEntityDescription( key="todayElectricity", name="todayElectricity", @@ -228,8 +228,8 @@ def add_years(d, years): icon="mdi:molecule-co2", ), SensorEntityDescription( - key="todayAlarmNum", - name="todayAlarmNum", + key="isAlarm", + name="isAlarm", icon="mdi:alarm", ), SensorEntityDescription( @@ -435,6 +435,11 @@ def add_years(d, years): icon="mdi:solar-panel-large", native_unit_of_measurement=POWER_WATT, ), + SensorEntityDescription( + key="gridDirection", + name="gridDirection", + icon="mdi:solar-panel-large" + ), SensorEntityDescription( key="h1Online", name="h1Online", @@ -487,7 +492,7 @@ def add_years(d, years): cv.ensure_list, [vol.In(SENSOR_LIST)] ), vol.Optional(CONF_SENSORS, default="None"): cv.string, - vol.Optional(CONF_DEVICE_ID, default="None"): cv.string, + vol.Optional(CONF_DEVICE_ID, default=0): cv.positive_int, } ) @@ -528,7 +533,7 @@ async def async_update(self): try: today = datetime.date.today() - clientDate = today.strftime('%Y-%m-%d') + clientDate = today.strftime('%Y-%m-%d') # Login to eSolar API url = 'https://fop.saj-electric.com/saj/login' @@ -594,11 +599,12 @@ async def async_update(self): return plantInfo = await response2.json() - plantuid = plantInfo['plantList'][0]['plantuid'] + #_LOGGER.error(f"PlantInfo: {plantInfo}") + plantuid = plantInfo['plantList'][self.sec_sn]['plantuid'] + - # Get API Plant Solar Details - url3 = "https://fop.saj-electric.com/saj/monitor/site/getPlantDetailInfo" + url3 = "https://fop.saj-electric.com/saj/monitor/site/getPlantDetailInfo" payload3= f"plantuid={plantuid}&clientDate={clientDate}" response3 = await self._session.post(url3, headers=headers, data=payload3) @@ -608,14 +614,15 @@ async def async_update(self): return plantDetails = await response3.json() + #_LOGGER.error(f"PlantDetails: {plantDetails}") plantDetails.update(plantInfo) # getPlantDetailChart2 - plantuid = plantDetails['plantList'][0]['plantuid'] + plantuid = plantDetails['plantList'][self.sec_sn]['plantuid'] deviceSnArr = plantDetails['plantDetail']['snList'][0] - previousChartDay = today - timedelta(days=1) - nextChartDay = today + timedelta(days = 1) + previousChartDay = today - timedelta(days=1) + nextChartDay = today + timedelta(days = 1) chartDay = today.strftime('%Y-%m-%d') previousChartMonth = add_months(today,-1).strftime('%Y-%m') nextChartMonth = add_months(today, 1).strftime('%Y-%m') @@ -623,10 +630,10 @@ async def async_update(self): previousChartYear = add_years(today, -1).strftime('%Y') nextChartYear = add_years(today, 1).strftime('%Y') chartYear = today.strftime('%Y') - epochmilliseconds = round(int((datetime.datetime.utcnow() - datetime.datetime(1970, 1, 1)).total_seconds() * 1000)) - - url4 = f"https://fop.saj-electric.com/saj/monitor/site/getPlantDetailChart2?plantuid={plantuid}&chartDateType=1&energyType=0&clientDate={clientDate}&deviceSnArr={deviceSnArr}&chartCountType=2&previousChartDay={previousChartDay}&nextChartDay={nextChartDay}&chartDay={chartDay}&previousChartMonth={previousChartMonth}&nextChartMonth={nextChartMonth}&chartMonth={chartMonth}&previousChartYear={previousChartYear}&nextChartYear={nextChartYear}&chartYear={chartYear}&elecDevicesn=&_={epochmilliseconds}" + epochmilliseconds = round(int((datetime.datetime.utcnow() - datetime.datetime(1970, 1, 1)).total_seconds() * 1000)) + url4 = f"https://fop.saj-electric.com/saj/monitor/site/getPlantDetailChart2?plantuid={plantuid}&chartDateType=1&energyType=0&clientDate={clientDate}&deviceSnArr={deviceSnArr}&chartCountType=2&previousChartDay={previousChartDay}&nextChartDay={nextChartDay}&chartDay={chartDay}&previousChartMonth={previousChartMonth}&nextChartMonth={nextChartMonth}&chartMonth={chartMonth}&previousChartYear={previousChartYear}&nextChartYear={nextChartYear}&chartYear={chartYear}&chartEnergyType=0&elecDevicesn={deviceSnArr}&_={epochmilliseconds}" + #_LOGGER.error(f"PlantCharts URL: {url4}") response4 = await self._session.post(url4, headers=headers) if response4.status != 200: @@ -634,6 +641,7 @@ async def async_update(self): return plantcharts = await response4.json() + #_LOGGER.error(f"PlantCharts: {plantcharts}") plantDetails.update(plantcharts) @@ -649,6 +657,7 @@ async def async_update(self): return result_getStoreOrAcDevicePowerInfo = await response_getStoreOrAcDevicePowerInfo.json() + #_LOGGER.error(f"{result_getStoreOrAcDevicePowerInfo}") plantDetails.update(result_getStoreOrAcDevicePowerInfo) _LOGGER.debug(result_getStoreOrAcDevicePowerInfo) @@ -657,7 +666,7 @@ async def async_update(self): else: # Data = plantdetails self._data = plantDetails - + # Sec module @@ -669,7 +678,7 @@ async def async_update(self): payload_module = f"pageNo=&pageSize=&plantUid={plantuid}" response_module = await self._session.post(url_module, headers=headers, data=payload_module) - + if response_module.status != 200: _LOGGER.error(f"{response_module.url} returned {response_module.status}") return @@ -683,7 +692,7 @@ async def async_update(self): moduleSn = plantDetails["getPlantMeterModuleList"]['moduleList'][0]['moduleSn'] - # -Debug- Sec module serial number + # -Debug- Sec module serial number _LOGGER.debug(moduleSn) @@ -717,12 +726,12 @@ async def async_update(self): return getPlantMeterDetailInfo = await response_getPlantMeterDetailInfo.json() - + temp_getPlantMeterDetailInfo = dict() - temp_getPlantMeterDetailInfo["getPlantMeterDetailInfo"] = getPlantMeterDetailInfo + temp_getPlantMeterDetailInfo["getPlantMeterDetailInfo"] = getPlantMeterDetailInfo plantDetails.update(temp_getPlantMeterDetailInfo) - + # getPlantMeterEnergyPreviewInfo url_getPlantMeterEnergyPreviewInfo = f"https://fop.saj-electric.com/saj/monitor/site/getPlantMeterEnergyPreviewInfo?plantuid={plantuid}&moduleSn={moduleSn}&_={epochmilliseconds}" @@ -733,7 +742,7 @@ async def async_update(self): return getPlantMeterEnergyPreviewInfo = await response_getPlantMeterEnergyPreviewInfo.json() - + temp_getPlantMeterEnergyPreviewInfo = dict() temp_getPlantMeterEnergyPreviewInfo["getPlantMeterEnergyPreviewInfo"] = getPlantMeterEnergyPreviewInfo @@ -749,12 +758,12 @@ async def async_update(self): return getPlantMeterChartData = await response_getPlantMeterChartData.json() - + temp_getPlantMeterChartData = dict() temp_getPlantMeterChartData["getPlantMeterChartData"] = getPlantMeterChartData plantDetails.update(temp_getPlantMeterChartData) - + # Data = plantdetails including Sec module self._data = plantDetails elif self.sensors == "None": @@ -762,7 +771,7 @@ async def async_update(self): else: # Data = plantdetails Wtihout Sec module self._data = plantDetails - + # Error logging except aiohttp.ClientError: _LOGGER.error("Cannot poll eSolar using url: %s") @@ -784,7 +793,7 @@ async def async_update(self): # logout session url_logout = "https://fop.saj-electric.com/saj/logout" response_logout = await self._session.post(url_logout, headers=headers) - + if response_logout.status != 200: _LOGGER.error(f"{response_logout.url} returned {response_logout.status}") return @@ -839,7 +848,10 @@ async def async_update(self): if self._type == 'devOnlineNum': if 'devOnlineNum' in energy['plantDetail']: if energy['plantDetail']["devOnlineNum"] is not None: - self._state = int(energy['plantDetail']["devOnlineNum"]) + if int(energy['plantDetail']["devOnlineNum"]) is 0: + self._state = "No" + else: + self._state = "Yes" if self._type == 'nowPower': if 'nowPower' in energy['plantDetail']: if energy['plantDetail']["nowPower"] is not None: @@ -847,7 +859,10 @@ async def async_update(self): if self._type == 'runningState': if 'runningState' in energy['plantDetail']: if energy['plantDetail']["runningState"] is not None: - self._state = int(energy['plantDetail']["runningState"]) + if int(energy['plantDetail']["runningState"]) is 0: + self._state = "No" + else: + self._state = "Yes" if self._type == 'todayElectricity': if 'todayElectricity' in energy['plantDetail']: if energy['plantDetail']["todayElectricity"] is not None: @@ -889,18 +904,10 @@ async def async_update(self): if energy['plantDetail']["totalSellElec"] is not None: self._state = float(energy['plantDetail']["totalSellElec"]) - - - - - if self._type == 'todayAlarmNum': - if 'todayAlarmNum' in energy['plantDetail']: - if energy['plantDetail']["todayAlarmNum"] is not None: - self._state = (energy['plantDetail']["todayAlarmNum"]) - if self._type == 'todayAlarmNum': - if 'todayAlarmNum' in energy['plantDetail']: - if energy['plantDetail']["todayAlarmNum"] is not None: - self._state = (energy['plantDetail']["todayAlarmNum"]) + if self._type == 'isAlarm': + if 'isAlarm' in energy['plantDetail']: + if energy['plantDetail']["isAlarm"] is not None: + self._state = (energy['plantDetail']["isAlarm"]) if self._type == 'lastUploadTime': if 'lastUploadTime' in energy['plantDetail']: if energy['plantDetail']["lastUploadTime"] is not None: @@ -913,11 +920,6 @@ async def async_update(self): if 'totalReduceCo2' in energy['plantDetail']: if energy['plantDetail']["totalReduceCo2"] is not None: self._state = (energy['plantDetail']["totalReduceCo2"]) - if self._type == 'todayAlarmNum': - if 'todayAlarmNum' in energy['plantDetail']: - if energy['plantDetail']["todayAlarmNum"] is not None: - self._state = (energy['plantDetail']["todayAlarmNum"]) - if self._type == 'currency': if 'currency' in energy['plantList'][0]: @@ -1039,7 +1041,13 @@ async def async_update(self): if self._type == 'gridDirection': if 'gridDirection' in energy["storeDevicePower"]: if energy["storeDevicePower"]['gridDirection'] is not None: - self._state = float(energy["storeDevicePower"]["gridDirection"]) + if energy["storeDevicePower"]["gridDirection"] == 1: + self._state = "Exporting" + elif energy["storeDevicePower"]["gridDirection"] == -1: + self._state = "Importing" + else: + self._state = energy["storeDevicePower"]["gridDirection"] + _LOGGER.error(f"Grid Direction unknown value: {self._state}") if self._type == 'gridPower': if 'gridPower' in energy["storeDevicePower"]: if energy["storeDevicePower"]['gridPower'] is not None: @@ -1047,7 +1055,10 @@ async def async_update(self): if self._type == 'h1Online': if 'isOnline' in energy["storeDevicePower"]: if energy["storeDevicePower"]['isOnline'] is not None: - self._state = int(energy["storeDevicePower"]["isOnline"]) + if int(energy['storeDevicePower']["isOnline"]) is 0: + self._state = "No" + else: + self._state = "Yes" if self._type == 'outPower': if 'outPower' in energy["storeDevicePower"]: if energy["storeDevicePower"]['outPower'] is not None: @@ -1126,7 +1137,7 @@ async def async_update(self): if 'plantTreeNum' in energy["getPlantMeterChartData"]['viewBean']: if energy["getPlantMeterChartData"]['viewBean']["plantTreeNum"] is not None: self._state = (energy["getPlantMeterChartData"]['viewBean']["plantTreeNum"]) - + # dataCountList if self._type == 'totalGridPower': @@ -1141,7 +1152,7 @@ async def async_update(self): if 'dataCountList' in energy: if energy["getPlantMeterChartData"]['dataCountList'][4][-1] is not None: self._state = float(energy["getPlantMeterChartData"]['dataCountList'][4][-1]) - + # getPlantMeterDetailInfo if self._type == 'totalPvEnergy': @@ -1160,7 +1171,7 @@ async def async_update(self): if 'totalSellEnergy' in energy["getPlantMeterDetailInfo"]['plantDetail']: if energy["getPlantMeterDetailInfo"]['plantDetail']["totalSellEnergy"] is not None: self._state = (energy["getPlantMeterDetailInfo"]['plantDetail']["totalSellEnergy"]) - + # -Debug- adding sensor _LOGGER.debug(f"Device: {self._type} State: {self._state}")