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

is fop.saj-electric.com deprecated? #65

Closed
santiagozky opened this issue Oct 7, 2023 · 36 comments
Closed

is fop.saj-electric.com deprecated? #65

santiagozky opened this issue Oct 7, 2023 · 36 comments

Comments

@santiagozky
Copy link
Contributor

I noticed that the integration was not working anymore for me. I accessed the esolar site and noticed that
-My plant was gone. no more data
-There is a button "new platform" taking me to https://esaj-home.saj-electric.com/index. That new site does shows my data.

Did anyone else experienced this?

A bit more info...

My R5 inversor and esolar module are rebranded with the "Greenheiss" brand (for Spain market). Their version of esolar (which is basically a reskin of SAJ's) still shows my plant https://inversores-style.greenheiss.com/cloud. if anyone's elses integration got killed it might be worth to check that domain.

My guess is they are deprecating the fop site but left Greenheiss users in the old one?

in any case, the integration is probably not working anymore for greenheiss users (and probably others rebranded units ) unless we point to their domain (maybe it can be configured? I'll try to check).

@santiagozky
Copy link
Contributor Author

I managed to make it work temporarily by:

  • replacing the domain in the sensor.py
  • forcing it not to verify SSL certificates (seems like the cert chain is broken and HASS rejects it):
    session = async_create_clientsession(hass,False).

@teamMOYA
Copy link

teamMOYA commented Oct 7, 2023

The same is happening to me. My plant is gone in the "old platform".

@miguelzx
Copy link

miguelzx commented Oct 7, 2023

I managed to make it work temporarily by:

* replacing the  domain in the sensor.py

* forcing it not to verify SSL certificates (seems like the cert chain is broken and HASS rejects it):
  session = async_create_clientsession(hass,False).

Hola puede explicarlo mejor, es que no lo pillo gracias

@santiagozky
Copy link
Contributor Author

@teamMOYA is your kit branded as SAJ or some other white label (eg. Greenheiss)?

@arnauplan
Copy link

Hi, the exact same thing is happening to me but I did what you said and it still doesn't work. Can you explain exactly what needs to be changed?
I have GreenHeiss.
Thanks!

@teamMOYA
Copy link

teamMOYA commented Oct 8, 2023

@teamMOYA is your kit branded as SAJ or some other white label (eg. Greenheiss)?

Mine are rebranded as "Solarprofit", but they don't have a web like Saj and Greenheiss. I'll have to wait for the new web access update.

@arnauplan
Copy link

I managed to make it work temporarily by:

  • replacing the domain in the sensor.py
  • forcing it not to verify SSL certificates (seems like the cert chain is broken and HASS rejects it):
    session = async_create_clientsession(hass,False).

Where do you change the domain to inside sensor.py?
Do you change https://fop.saj-electric.com/saj to https://esaj-home.saj-electric.com/ or something?

@miguelzx
Copy link

miguelzx commented Oct 8, 2023

Hello, I also had that problem.

My Greenheiss h1 inverter. I use an old integration 1.3.1 which I already have working.

Right now everything works perfectly for me

replacing the domain in the sensor.py

I leave a copy of my sensor.py, in case it helps you, but remember that I use 1.3.1

"""
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/
"""

import asyncio
from homeassistant.helpers.aiohttp_client import async_create_clientsession
from datetime import timedelta
import datetime
import calendar

from functools import reduce
import logging
from typing import Final

import aiohttp
import async_timeout
import voluptuous as vol

import re
from bs4 import BeautifulSoup

from homeassistant.components.sensor import (
    PLATFORM_SCHEMA,
    STATE_CLASS_TOTAL_INCREASING,
    SensorEntity,
    SensorEntityDescription,
)
from homeassistant.const import (
    CONF_RESOURCES,
    CONF_USERNAME,
    CONF_PASSWORD,
    CONF_SENSORS,
    CONF_DEVICE_ID,
    DEVICE_CLASS_ENERGY,
    DEVICE_CLASS_POWER,
    ENERGY_KILO_WATT_HOUR,
    POWER_WATT,
    PERCENTAGE,

)
from homeassistant.helpers.aiohttp_client import async_get_clientsession
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity import Entity
from homeassistant.util import Throttle, dt

def add_months(sourcedate, months):
    month = sourcedate.month - 1 + months
    year = sourcedate.year + month // 12
    month = month % 12 + 1
    day = min(sourcedate.day, calendar.monthrange(year,month)[1])
    return datetime.date(year, month, day)

def add_years(d, years):
    try:
        return d.replace(year = d.year + years)
    except ValueError:
        return d + (date(d.year + years, 1, 1) - date(d.year, 1, 1))

BASE_URL = 'https://inversores-style.greenheiss.com/cloud/login'
_LOGGER = logging.getLogger(__name__)

MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=3)

SENSOR_PREFIX = 'esolar '
ATTR_MEASUREMENT = "measurement"
ATTR_SECTION = "section"

SENSOR_LIST = {
    "nowPower",
    "runningState",
    "devOnlineNum",
    "todayElectricity",
    "monthElectricity",
    "yearElectricity",
    "totalElectricity",
    "todayGridIncome",
    "income",
    "lastUploadTime",
    "totalPlantTreeNum",
    "totalReduceCo2",
    "todayAlarmNum",
    "plantuid",
    "plantname",
    "currency",
    "address",
    "isOnline",
    "status",
    "peakPower",
    #sec & h1
    "pvElec",
    "useElec",
    "buyElec",
    "sellElec",
    "buyRate",
    "sellRate",
    "selfUseRate",
    "totalBuyElec",
    "totalConsumpElec",
    "totalSellElec",
    "selfConsumedRate1",
    "selfConsumedRate2",
    "selfConsumedEnergy1",
    "selfConsumedEnergy2",
    "plantTreeNum",
    "reduceCo2",
    "totalGridPower",
    "totalLoadPower",
    "totalPvgenPower",
    "totalPvEnergy",
    "totalLoadEnergy",
    "totalBuyEnergy",
    "totalSellEnergy",
    #h1
    "chargeElec",
    "dischargeElec",
    "batCapcity",
    "isAlarm",
    "batCurr",
    "batEnergyPercent",
    "batteryDirection",
    "batteryPower",
    "gridDirection",
    "gridPower",
    "h1Online",
    "outPower",
    "outPutDirection",
    "pvDirection",
    "pvPower",
    "solarPower",
    #h1s2
    "h1s2_pv_volt_1",
    "h1s2_pv_current_1",
    "h1s2_pv_power_1",
    "h1s2_pv_volt_2",
    "h1s2_pv_current_2",
    "h1s2_pv_power_2",
    "h1s2_pv_volt_3",
    "h1s2_pv_current_3",
    "h1s2_pv_power_3",
    "h1s2_bat_volt",
    "h1s2_bat_current",
    "h1s2_bat_power",
    "h1s2_bat_total_charge",
    "h1s2_bat_total_discharge",
    "h1s2_load_power",
    "h1s2_grid_volt_1",
    "h1s2_grid_current_1",
    "h1s2_grid_power_1",
    "h1s2_grid_volt_2",
    "h1s2_grid_current_2",
    "h1s2_grid_power_2",
    "h1s2_grid_volt_3",
    "h1s2_grid_current_3",
    "h1s2_grid_power_3",
}

SENSOR_TYPES: Final[tuple[SensorEntityDescription]] = (
    SensorEntityDescription(
        key="nowPower",
        name="nowPower",
        icon="mdi:solar-power",
        native_unit_of_measurement=POWER_WATT,
        device_class=DEVICE_CLASS_POWER,
    ),
    SensorEntityDescription(
        key="runningState",
        name="runningState",
        icon="mdi:solar-panel",
    ),
    SensorEntityDescription(
        key="devOnlineNum",
        name="devOnlineNum",
        icon="mdi:solar-panel",
    ),
    SensorEntityDescription(
        key="todayElectricity",
        name="todayElectricity",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement=ENERGY_KILO_WATT_HOUR,
        device_class=DEVICE_CLASS_ENERGY,
    ),
    SensorEntityDescription(
        key="monthElectricity",
        name="monthElectricity",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement=ENERGY_KILO_WATT_HOUR,
        device_class=DEVICE_CLASS_ENERGY,
    ),
    SensorEntityDescription(
        key="yearElectricity",
        name="yearElectricity",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement=ENERGY_KILO_WATT_HOUR,
        device_class=DEVICE_CLASS_ENERGY,
    ),
    SensorEntityDescription(
        key="totalElectricity",
        name="totalElectricity",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement=ENERGY_KILO_WATT_HOUR,
        device_class=DEVICE_CLASS_ENERGY,
        state_class=STATE_CLASS_TOTAL_INCREASING,
    ),
    SensorEntityDescription(
        key="selfUseRate",
        name="selfUseRate",
        icon="mdi:solar-panel",
    ),
    SensorEntityDescription(
        key="totalBuyElec",
        name="totalBuyElec",
        icon="mdi:solar-panel",
        native_unit_of_measurement=ENERGY_KILO_WATT_HOUR,
        device_class=DEVICE_CLASS_ENERGY,
        state_class=STATE_CLASS_TOTAL_INCREASING,
    ),
    SensorEntityDescription(
        key="totalConsumpElec",
        name="totalConsumpElec",
        icon="mdi:solar-panel",
        native_unit_of_measurement=ENERGY_KILO_WATT_HOUR,
        device_class=DEVICE_CLASS_ENERGY,
    ),
    SensorEntityDescription(
        key="totalSellElec",
        name="totalSellElec",
        icon="mdi:solar-panel",
        native_unit_of_measurement=ENERGY_KILO_WATT_HOUR,
        device_class=DEVICE_CLASS_ENERGY,
        state_class=STATE_CLASS_TOTAL_INCREASING,
    ),
    SensorEntityDescription(
        key="todayGridIncome",
        name="todayGridIncome",
        icon="mdi:currency-eur",
    ),
    SensorEntityDescription(
        key="income",
        name="income",
        icon="mdi:currency-eur",
    ),
    SensorEntityDescription(
        key="lastUploadTime",
        name="lastUploadTime",
        icon="mdi:timer-sand",
    ),
    SensorEntityDescription(
        key="totalPlantTreeNum",
        name="totalPlantTreeNum",
        icon="mdi:tree",
    ),
    SensorEntityDescription(
        key="totalReduceCo2",
        name="totalReduceCo2",
        icon="mdi:molecule-co2",
    ),
    SensorEntityDescription(
        key="todayAlarmNum",
        name="todayAlarmNum",
        icon="mdi:alarm",
    ),
    SensorEntityDescription(
        key="plantuid",
        name="plantuid",
        icon="mdi:api",
    ),
    SensorEntityDescription(
        key="plantname",
        name="plantname",
        icon="mdi:api",
    ),
    SensorEntityDescription(
        key="currency",
        name="currency",
        icon="mdi:solar-panel",
    ),
    SensorEntityDescription(
        key="address",
        name="address",
        icon="mdi:solar-panel",
    ),
    SensorEntityDescription(
        key="isOnline",
        name="isOnline",
        icon="mdi:api",
    ),
    SensorEntityDescription(
        key="status",
        name="status",
        icon="mdi:api",
    ),
    SensorEntityDescription(
        key="peakPower",
        name="peakPower",
        icon="mdi:solar-panel",
        native_unit_of_measurement=POWER_WATT,
        device_class=DEVICE_CLASS_POWER,
    ),
    SensorEntityDescription(
        key="pvElec",
        name="pvElec",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement=ENERGY_KILO_WATT_HOUR,
        device_class=DEVICE_CLASS_ENERGY,
    ),
    SensorEntityDescription(
        key="useElec",
        name="useElec",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement=ENERGY_KILO_WATT_HOUR,
        device_class=DEVICE_CLASS_ENERGY,
        state_class=STATE_CLASS_TOTAL_INCREASING,
    ),
    SensorEntityDescription(
        key="buyElec",
        name="buyElec",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement=ENERGY_KILO_WATT_HOUR,
        device_class=DEVICE_CLASS_ENERGY,
        state_class=STATE_CLASS_TOTAL_INCREASING,
    ),
    SensorEntityDescription(
        key="sellElec",
        name="sellElec",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement=ENERGY_KILO_WATT_HOUR,
        device_class=DEVICE_CLASS_ENERGY,
        state_class=STATE_CLASS_TOTAL_INCREASING,
    ),
    SensorEntityDescription(
        key="buyRate",
        name="buyRate",
        icon="mdi:solar-panel",
    ),
    SensorEntityDescription(
        key="sellRate",
        name="sellRate",
        icon="mdi:solar-panel",
    ),
    SensorEntityDescription(
        key="selfConsumedRate1",
        name="selfConsumedRate1",
        icon="mdi:solar-panel",
    ),
    SensorEntityDescription(
        key="selfConsumedRate2",
        name="selfConsumedRate2",
        icon="mdi:solar-panel",
    ),
    SensorEntityDescription(
        key="selfConsumedEnergy1",
        name="selfConsumedEnergy1",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement=ENERGY_KILO_WATT_HOUR,
        device_class=DEVICE_CLASS_ENERGY,
    ),
    SensorEntityDescription(
        key="selfConsumedEnergy2",
        name="selfConsumedEnergy2",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement=ENERGY_KILO_WATT_HOUR,
        device_class=DEVICE_CLASS_ENERGY,
    ),
    SensorEntityDescription(
        key="plantTreeNum",
        name="plantTreeNum",
        icon="mdi:tree",
    ),
    SensorEntityDescription(
        key="reduceCo2",
        name="reduceCo2",
        icon="mdi:molecule-co2",
    ),
    SensorEntityDescription(
        key="totalGridPower",
        name="totalGridPower",
        icon="mdi:solar-panel",
        native_unit_of_measurement=POWER_WATT,
    ),
    SensorEntityDescription(
        key="totalLoadPower",
        name="totalLoadPower",
        icon="mdi:solar-panel",
        native_unit_of_measurement=POWER_WATT,
        device_class=DEVICE_CLASS_POWER,
    ),
    SensorEntityDescription(
        key="totalPvgenPower",
        name="totalPvgenPower",
        icon="mdi:solar-panel",
        native_unit_of_measurement=POWER_WATT,
    ),
    SensorEntityDescription(
        key="totalPvEnergy",
        name="totalPvEnergy",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement=ENERGY_KILO_WATT_HOUR,
        device_class=DEVICE_CLASS_ENERGY,
        state_class=STATE_CLASS_TOTAL_INCREASING,
    ),
    SensorEntityDescription(
        key="totalLoadEnergy",
        name="totalLoadEnergy",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement=ENERGY_KILO_WATT_HOUR,
        device_class=DEVICE_CLASS_ENERGY,
        state_class=STATE_CLASS_TOTAL_INCREASING,
    ),
    SensorEntityDescription(
        key="totalBuyEnergy",
        name="totalBuyEnergy",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement=ENERGY_KILO_WATT_HOUR,
        device_class=DEVICE_CLASS_ENERGY,
        state_class=STATE_CLASS_TOTAL_INCREASING,
    ),
    SensorEntityDescription(
        key="totalSellEnergy",
        name="totalSellEnergy",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement=ENERGY_KILO_WATT_HOUR,
        device_class=DEVICE_CLASS_ENERGY,
        state_class=STATE_CLASS_TOTAL_INCREASING,
    ),
    #h1
    SensorEntityDescription(
        key="batCapcity",
        name="batCapcity",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement="A·h"
    ),
    SensorEntityDescription(
        key="isAlarm",
        name="isAlarm",
        icon="mdi:solar-panel-large",
    ),
    SensorEntityDescription(
        key="batCurr",
        name="batCurr",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement="A"
    ),
    SensorEntityDescription(
        key="batEnergyPercent",
        name="batEnergyPercent",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement=PERCENTAGE,
    ),
    SensorEntityDescription(
        key="batteryDirection",
        name="batteryDirection",
        icon="mdi:solar-panel-large",
    ),
    SensorEntityDescription(
        key="batteryPower",
        name="batteryPower",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement=POWER_WATT,
    ),
    SensorEntityDescription(
        key="gridPower",
        name="gridPower",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement=POWER_WATT,
    ),
    SensorEntityDescription(
        key="h1Online",
        name="h1Online",
        icon="mdi:solar-panel-large",
    ),
    SensorEntityDescription(
        key="outPower",
        name="outPower",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement=POWER_WATT,
    ),
    SensorEntityDescription(
        key="outPutDirection",
        name="outPutDirection",
        icon="mdi:solar-panel-large",
    ),
    SensorEntityDescription(
        key="pvPower",
        name="pvPower",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement=POWER_WATT,

    ),
    SensorEntityDescription(
        key="solarPower",
        name="solarPower",
        icon="mdi:solar-panel-large",
    ),
    SensorEntityDescription(
        key="chargeElec",
        name="chargeElec",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement=ENERGY_KILO_WATT_HOUR,
        device_class=DEVICE_CLASS_ENERGY,
        state_class=STATE_CLASS_TOTAL_INCREASING,
    ),
    SensorEntityDescription(
        key="dischargeElec",
        name="dischargeElec",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement=ENERGY_KILO_WATT_HOUR,
        device_class=DEVICE_CLASS_ENERGY,
        state_class=STATE_CLASS_TOTAL_INCREASING,
    ),
    #h1s2
    SensorEntityDescription(
        key="h1s2_pv_volt_1",
        name="h1s2_pv_volt_1",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement="V"
    ),
    SensorEntityDescription(
        key="h1s2_pv_current_1",
        name="h1s2_pv_current_1",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement="A"
    ),
    SensorEntityDescription(
        key="h1s2_pv_power_1",
        name="h1s2_pv_power_1",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement="W"
    ),
    SensorEntityDescription(
        key="h1s2_pv_volt_2",
        name="h1s2_pv_volt_2",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement="V"
    ),
    SensorEntityDescription(
        key="h1s2_pv_current_2",
        name="h1s2_pv_current_2",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement="A"
    ),
    SensorEntityDescription(
        key="h1s2_pv_power_2",
        name="h1s2_pv_power_2",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement="W"
    ),
    SensorEntityDescription(
        key="h1s2_pv_volt_3",
        name="h1s2_pv_volt_3",
        icon="mdi:solar-panel-large",
    ),
    SensorEntityDescription(
        key="h1s2_pv_current_3",
        name="h1s2_pv_current_3",
        icon="mdi:solar-panel-large",
    ),
    SensorEntityDescription(
        key="h1s2_pv_power_3",
        name="h1s2_pv_power_3",
        icon="mdi:solar-panel-large",
    ),
    SensorEntityDescription(
        key="h1s2_bat_volt",
        name="h1s2_bat_volt",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement="V"
    ),
    SensorEntityDescription(
        key="h1s2_bat_current",
        name="h1s2_bat_current",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement="A"
    ),
    SensorEntityDescription(
        key="h1s2_bat_power",
        name="h1s2_bat_power",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement="W"
    ),
    SensorEntityDescription(
        key="h1s2_bat_total_charge",
        name="h1s2_bat_total_charge",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement="Ah"
    ),
    SensorEntityDescription(
        key="h1s2_bat_total_discharge",
        name="h1s2_bat_total_discharge",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement="Ah"
    ),
    SensorEntityDescription(
        key="h1s2_load_power",
        name="h1s2_load_power",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement="W"
    ),
    SensorEntityDescription(
        key="h1s2_grid_volt_1",
        name="h1s2_grid_volt_1",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement="V"

    ),
    SensorEntityDescription(
        key="h1s2_grid_current_1",
        name="h1s2_grid_current_1",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement="A"

    ),
    SensorEntityDescription(
        key="h1s2_grid_power_1",
        name="h1s2_grid_power_1",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement="W"

    ),
    SensorEntityDescription(
        key="h1s2_grid_volt_2",
        name="h1s2_grid_volt_2",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement="V"

    ),
    SensorEntityDescription(
        key="h1s2_grid_current_2",
        name="h1s2_grid_current_2",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement="A"

    ),
    SensorEntityDescription(
        key="h1s2_grid_power_2",
        name="h1s2_grid_power_2",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement="W"

    ),
    SensorEntityDescription(
        key="h1s2_grid_volt_3",
        name="h1s2_grid_volt_3",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement="V"
    ),
    SensorEntityDescription(
        key="h1s2_grid_current_3",
        name="h1s2_grid_current_3",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement="A"

    ),
    SensorEntityDescription(
        key="h1s2_grid_power_3",
        name="h1s2_grid_power_3",
        icon="mdi:solar-panel-large",
        native_unit_of_measurement="W"

    ),
)

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
    {
        vol.Required(CONF_USERNAME): cv.string,
        vol.Required(CONF_PASSWORD): cv.string,
        vol.Required(CONF_RESOURCES, default=list(SENSOR_LIST)): vol.All(
            cv.ensure_list, [vol.In(SENSOR_LIST)]
        ),
        vol.Optional(CONF_SENSORS, default="None"): cv.string,
        vol.Optional(CONF_DEVICE_ID, default="None"): cv.string,
    }
)

async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):

    """Setup the SAJ eSolar sensors."""

    session = async_create_clientsession(hass,False)
    data = SAJeSolarMeterData(session, config.get(CONF_USERNAME), config.get(CONF_PASSWORD), config.get(CONF_SENSORS), config.get(CONF_DEVICE_ID))
    await data.async_update()

    entities = []
    for description in SENSOR_TYPES:
        if description.key in config[CONF_RESOURCES]:
            sensor = SAJeSolarMeterSensor(description, data, config.get(CONF_SENSORS))
            entities.append(sensor)
    async_add_entities(entities, True)
    return True

class SAJeSolarMeterData(object):
    """Handle eSolar object and limit updates."""

    def __init__(self, session, username, password, sensors, sec_sn):
        """Initialize the data object."""

        self._session = session
        self._url = BASE_URL
        self.username = username
        self.password = password
        self.sensors = sensors
        self.sec_sn = sec_sn
        self._data = None

    @Throttle(MIN_TIME_BETWEEN_UPDATES)
    async def async_update(self):
        """Download and update data from SAJeSolar."""

        try:

            today = datetime.date.today()
            clientDate = today.strftime('%Y-%m-%d')

            # Login to eSolar API
            url = 'https://inversores-style.greenheiss.com/cloud/login'
            payload = {
                'lang': 'en',
                'username': self.username,
                'password': self.password,
                'rememberMe': 'true'
            }
            headers_login = {
                'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
                'Accept-Encoding': 'gzip, deflate, br',
                'Accept-Language': 'nl-NL,nl;q=0.9,en-US;q=0.8,en;q=0.7',
                'Cache-Control': 'max-age=0',
                'Connection': 'keep-alive',
                'Content-Type': 'application/x-www-form-urlencoded',
                'Cookie': 'org.springframework.web.servlet.i18n.CookieLocaleResolver.LOCALE=en; op_esolar_lang=en',
                'DNT': '1',
                'Host': 'inversores-style.greenheiss.com',
                'Origin': 'https://inversores-style.greenheiss.com',
                'Referer': 'https://inversores-style.greenheiss.com/cloud/login',
                'sec-ch-ua': '" Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"',
                'sec-ch-ua-mobile': '?0',
                'Sec-Fetch-Dest': 'document',
                'Sec-Fetch-Mode': 'navigate',
                'Sec-Fetch-Site': 'same-origin',
                'Sec-Fetch-User': '?1',
                'Upgrade-Insecure-Requests': '1',
                'User-Agent'
                : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36'
            }
            response = await self._session.post(url, headers=headers_login, data=payload)

            if response.status != 200:
                _LOGGER.error(f"{response.url} returned {response.status}")
                return


            # Get API Plant info from Esolar Portal
            url2 = 'https://inversores-style.greenheiss.com/cloud/monitor/site/getUserPlantList'
            headers = {
                'Connection': 'keep-alive',
                'sec-ch-ua': '" Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"',
                'Accept': 'application/json, text/javascript, */*; q=0.01',
                'DNT': '1',
                'X-Requested-With': 'XMLHttpRequest',
                'sec-ch-ua-mobile': '?0',
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.106 Safari/537.36',
                'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
                'Origin': 'https://inversores-style.greenheiss.com',
                'Sec-Fetch-Site': 'same-origin',
                'Sec-Fetch-Mode': 'cors',
                'Sec-Fetch-Dest': 'empty',
                'Referer': 'https://inversores-style.greenheiss.com/cloud/monitor/home/index',
                'Accept-Language': 'nl-NL,nl;q=0.9,en-US;q=0.8,en;q=0.7'
            }

            payload2= f"pageNo=&pageSize=&orderByIndex=&officeId=&clientDate={clientDate}&runningState=&selectInputType=1&plantName=&deviceSn=&type=&countryCode=&isRename=&isTimeError=&systemPowerLeast=&systemPowerMost="
            response2 = await self._session.post(url2, headers=headers, data=payload2)

            if response2.status != 200:
                _LOGGER.error(f"{response2.url} returned {response2.status}")
                return

            plantInfo = await response2.json()
            plantuid = plantInfo['plantList'][0]['plantuid']


            # Get API Plant Solar Details
            url3 = "https://inversores-style.greenheiss.com/cloud/monitor/site/getPlantDetailInfo"
            payload3= f"plantuid={plantuid}&clientDate={clientDate}"

            response3 = await self._session.post(url3, headers=headers, data=payload3)

            if response3.status != 200:
                _LOGGER.error(f"{response3.url} returned {response3.status}")
                return

            plantDetails = await response3.json()
            plantDetails.update(plantInfo)


            # getPlantDetailChart2
            plantuid = plantDetails['plantList'][0]['plantuid']
            deviceSnArr = plantDetails['plantDetail']['snList'][0]
            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')
            chartMonth = today.strftime('%Y-%m')
            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://inversores-style.greenheiss.com/cloud/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}"

            response4 = await self._session.post(url4, headers=headers)

            if response4.status != 200:
                _LOGGER.error(f"{response4.url} returned {response4.status}")
                return

            plantcharts = await response4.json()
            plantDetails.update(plantcharts)


            # H1 Module
            if self.sensors == "h1":
                # getStoreOrAcDevicePowerInfo
                url_getStoreOrAcDevicePowerInfo = f"https://inversores-style.greenheiss.com/cloud/monitor/site/getStoreOrAcDevicePowerInfo?plantuid=&devicesn={deviceSnArr}&_={epochmilliseconds}"

                response_getStoreOrAcDevicePowerInfo = await self._session.post(url_getStoreOrAcDevicePowerInfo, headers=headers)

                if response_getStoreOrAcDevicePowerInfo.status != 200:
                    _LOGGER.error(f"{response_getStoreOrAcDevicePowerInfo.url} returned {response_getStoreOrAcDevicePowerInfo.status}")
                    return

                result_getStoreOrAcDevicePowerInfo = await response_getStoreOrAcDevicePowerInfo.json()
                plantDetails.update(result_getStoreOrAcDevicePowerInfo)
                _LOGGER.debug(result_getStoreOrAcDevicePowerInfo)

                url5 = f"https://inversores-style.greenheiss.com/cloud/cloudMonitor/deviceInfo?devicesn={deviceSnArr}"
                response5 = await self._session.get(url5, headers=headers)
                if response5.status != 200:
                    _LOGGER.error(f"{response5.url} returned {response5.status}")


                html = await response5.text()

                soup = BeautifulSoup(html, "lxml")
                span = soup.select(".real_num span")

                h1s2= {
                    "h1s2": {
                        "h1s2_pv_volt_1":re.sub(r'[^0-9.]', '', (span[0].text).split("/")[0]),
                        "h1s2_pv_current_1":re.sub(r'[^0-9.]', '', (span[0].text).split("/")[1]),
                        "h1s2_pv_power_1":re.sub(r'[^0-9.]', '', (span[0].text).split("/")[2]),

                        "h1s2_pv_volt_2":re.sub(r'[^0-9.]', '', (span[1].text).split("/")[0]),
                        "h1s2_pv_current_2":re.sub(r'[^0-9.]', '', (span[1].text).split("/")[1]),
                        "h1s2_pv_power_2":re.sub(r'[^0-9.]', '', (span[1].text).split("/")[2]),

                        "h1s2_pv_volt_3":re.sub(r'[^0-9.]', '', (span[2].text).split("/")[0]),
                        "h1s2_pv_current_3":re.sub(r'[^0-9.]', '', (span[2].text).split("/")[1]),
                        "h1s2_pv_power_3":re.sub(r'[^0-9.]', '', (span[2].text).split("/")[2]),

                        "h1s2_bat_volt":re.sub(r'[^0-9.]', '', (span[3].text).split("/")[0]),
                        "h1s2_bat_current":re.sub(r'[^0-9.\-]', '', (span[3].text).split("/")[1]),
                        "h1s2_bat_power":re.sub(r'[^0234567891.\-]', '', (span[3].text).split("/")[2]),

                        "h1s2_bat_total_charge":re.sub(r'[^0-9.]', '', (span[4].text).split("/")[0]),
                        "h1s2_bat_total_discharge":re.sub(r'[^0-9.]', '', (span[4].text).split("/")[1]),

                        "h1s2_load_power":re.sub(r'[^0-9.]', '', span[5].text),

                        "h1s2_grid_volt_1":re.sub(r'[^0-9.]', '', (span[6].text).split("/")[0]),
                        "h1s2_grid_current_1":re.sub(r'[^0-9.]', '', (span[6].text).split("/")[1]),
                        "h1s2_grid_power_1":re.sub(r'[^0-9.]', '', (span[6].text).split("/")[2]),

                        "h1s2_grid_volt_2":re.sub(r'[^0-9.]', '', (span[7].text).split("/")[0]),
                        "h1s2_grid_current_2":re.sub(r'[^0-9.]', '', (span[7].text).split("/")[1]),
                        "h1s2_grid_power_2":re.sub(r'[^0-9.]', '', (span[7].text).split("/")[2]),

                        "h1s2_grid_volt_3":re.sub(r'[^0-9.]', '', (span[8].text).split("/")[0]),
                        "h1s2_grid_current_3":re.sub(r'[^0-9.]', '', (span[8].text).split("/")[1]),
                        "h1s2_grid_power_3":re.sub(r'[^0-9.]', '', (span[8].text).split("/")[2]),

                        "h1s2_pv_volt_1":re.sub(r'[^0-9.]', '', (span[0].text).split("/")[0]),
                        "h1s2_pv_current_1":re.sub(r'[^0-9.]', '', (span[0].text).split("/")[1]),
                        "h1s2_pv_power_1":re.sub(r'[^0-9.]', '', (span[0].text).split("/")[2]),

                        "h1s2_pv_volt_2":re.sub(r'[^0-9.]', '', (span[1].text).split("/")[0]),
                        "h1s2_pv_current_2":re.sub(r'[^0-9.]', '', (span[1].text).split("/")[1]),
                        "h1s2_pv_power_2":re.sub(r'[^0-9.]', '', (span[1].text).split("/")[2]),

                        "h1s2_pv_volt_3":re.sub(r'[^0-9.]', '', (span[2].text).split("/")[0]),
                        "h1s2_pv_current_3":re.sub(r'[^0-9.]', '', (span[2].text).split("/")[1]),
                        "h1s2_pv_power_3":re.sub(r'[^0-9.]', '', (span[2].text).split("/")[2]),

                        "h1s2_bat_volt":re.sub(r'[^0-9.]', '', (span[3].text).split("/")[0]),
                        "h1s2_bat_current":re.sub(r'[^0-9.]', '', (span[3].text).split("/")[1]),
                        "h1s2_bat_power":re.sub(r'[^0-9.]', '', (span[3].text).split("/")[2]),

                        "h1s2_bat_total_charge":re.sub(r'[^0-9.]', '', (span[4].text).split("/")[0]),
                        "h1s2_bat_total_discharge":re.sub(r'[^0-9.]', '', (span[4].text).split("/")[1]),

                        "h1s2_load_power":re.sub(r'[^0-9.]', '', span[5].text),

                        "h1s2_grid_volt_1":re.sub(r'[^0-9.]', '', (span[6].text).split("/")[0]),
                        "h1s2_grid_current_1":re.sub(r'[^0-9.]', '', (span[6].text).split("/")[1]),
                        "h1s2_grid_power_1":re.sub(r'[^0-9.]', '', (span[6].text).split("/")[2]),

                        "h1s2_grid_volt_2":re.sub(r'[^0-9.]', '', (span[7].text).split("/")[0]),
                        "h1s2_grid_current_2":re.sub(r'[^0-9.]', '', (span[7].text).split("/")[1]),
                        "h1s2_grid_power_2":re.sub(r'[^0-9.]', '', (span[7].text).split("/")[2]),

                        "h1s2_grid_volt_3":re.sub(r'[^0-9.]', '', (span[8].text).split("/")[0]),
                        "h1s2_grid_current_3":re.sub(r'[^0-9.]', '', (span[8].text).split("/")[1]),
                        "h1s2_grid_power_3":re.sub(r'[^0-9.]', '', (span[8].text).split("/")[2])
                    }
                }

                plantDetails.update(h1s2)




            elif self.sensors == "None":
                self._data = plantDetails
            else:
                # Data = plantdetails
                self._data = plantDetails



            # Sec module
            if self.sensors == "saj_sec":

                # getPlantMeterModuleList
                url_module = "https://inversores-style.greenheiss.com/cloud/saj/cloudmonitor/plantMeterModule/getPlantMeterModuleList"

                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

                getPlantMeterModuleList = await response_module.json()

                temp_getPlantMeterModuleList = dict()
                temp_getPlantMeterModuleList["getPlantMeterModuleList"] = getPlantMeterModuleList

                plantDetails.update(temp_getPlantMeterModuleList)

                moduleSn = plantDetails["getPlantMeterModuleList"]['moduleList'][0]['moduleSn']

                # -Debug- Sec module serial number
                _LOGGER.debug(moduleSn)


                # findDevicePageList
                url_findDevicePageList = "https://inversores-style.greenheiss.com/cloud/cloudMonitor/device/findDevicePageList"

                payload_findDevicePageList = f"officeId=1&pageNo=&pageSize=&orderName=1&orderType=2&plantuid={plantuid}&deviceStatus=&localDate={chartMonth}&localMonth={chartMonth}"

                response_findDevicePageList = await self._session.post(url_findDevicePageList, headers=headers, data=payload_findDevicePageList)

                if response_findDevicePageList.status != 200:
                    _LOGGER.error(f"{response_findDevicePageList.url} returned {response_findDevicePageList.status}")
                    return

                findDevicePageList = await response_findDevicePageList.json()

                temp_findDevicePageList = dict()
                temp_findDevicePageList["findDevicePageList"] = findDevicePageList

                plantDetails.update(temp_findDevicePageList)

                # getPlantMeterDetailInfo
                url_getPlantMeterDetailInfo = "https://inversores-style.greenheiss.com/cloud/monitor/site/getPlantMeterDetailInfo"

                payload_getPlantMeterDetailInfo = f"plantuid={plantuid}&clientDate={clientDate}"

                response_getPlantMeterDetailInfo = await self._session.post(url_getPlantMeterDetailInfo, headers=headers, data=payload_getPlantMeterDetailInfo)

                if response_getPlantMeterDetailInfo.status != 200:
                    _LOGGER.error(f"{response_getPlantMeterDetailInfo.url} returned {response_getPlantMeterDetailInfo.status}")
                    return

                getPlantMeterDetailInfo = await response_getPlantMeterDetailInfo.json()

                temp_getPlantMeterDetailInfo = dict()
                temp_getPlantMeterDetailInfo["getPlantMeterDetailInfo"] = getPlantMeterDetailInfo

                plantDetails.update(temp_getPlantMeterDetailInfo)

                # getPlantMeterEnergyPreviewInfo
                url_getPlantMeterEnergyPreviewInfo = f"https://inversores-style.greenheiss.com/cloud/monitor/site/getPlantMeterEnergyPreviewInfo?plantuid={plantuid}&moduleSn={moduleSn}&_={epochmilliseconds}"

                response_getPlantMeterEnergyPreviewInfo = await self._session.get(url_getPlantMeterEnergyPreviewInfo, headers=headers)

                if response_getPlantMeterEnergyPreviewInfo.status != 200:
                    _LOGGER.error(f"{response_getPlantMeterEnergyPreviewInfo.url} returned {response_getPlantMeterEnergyPreviewInfo.status}")
                    return

                getPlantMeterEnergyPreviewInfo = await response_getPlantMeterEnergyPreviewInfo.json()

                temp_getPlantMeterEnergyPreviewInfo = dict()
                temp_getPlantMeterEnergyPreviewInfo["getPlantMeterEnergyPreviewInfo"] = getPlantMeterEnergyPreviewInfo

                plantDetails.update(temp_getPlantMeterEnergyPreviewInfo)

                # Get Sec Meter details
                url_getPlantMeterChartData = f"https://inversores-style.greenheiss.com/cloud/monitor/site/getPlantMeterChartData?plantuid={plantuid}&chartDateType=1&energyType=0&clientDate={clientDate}&deviceSnArr=&chartCountType=2&previousChartDay={previousChartDay}&nextChartDay={nextChartDay}&chartDay={chartDay}&previousChartMonth={previousChartMonth}&nextChartMonth={nextChartMonth}&chartMonth={chartMonth}&previousChartYear={previousChartYear}&nextChartYear={nextChartYear}&chartYear={chartYear}&moduleSn={moduleSn}&_={epochmilliseconds}"

                response_getPlantMeterChartData = await self._session.post(url_getPlantMeterChartData, headers=headers)

                if response_getPlantMeterChartData.status != 200:
                    _LOGGER.error(f"{response_getPlantMeterChartData.url} returned {response_getPlantMeterChartData.status}")
                    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":
                self._data = plantDetails
            else:
                # Data = plantdetails Wtihout Sec module
                self._data = plantDetails

        # Error logging
        except aiohttp.ClientError:
            _LOGGER.error("Cannot poll eSolar using url: %s")
            return
        except asyncio.TimeoutError:
            _LOGGER.error("Timeout error occurred while polling eSolar using url: %s")
            return
        except Exception as err:
            _LOGGER.error("Unknown error occurred while polling eSolar: %s", err)
            self._data = None
            return


        # -Debug- Cookies and Data
        _LOGGER.debug(self._session.cookie_jar.filter_cookies("https://inversores-style.greenheiss.com"))
        _LOGGER.debug(self._data)


        # logout session
        url_logout = "https://inversores-style.greenheiss.com/cloud/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


        # Clear session and cookies
        self._session.cookie_jar.clear()
        self._session.close()

    @property
    def latest_data(self):
        """Return the latest data object."""
        if self._data:
            return self._data

        _LOGGER.error("return data NONE")
        return None

class SAJeSolarMeterSensor(SensorEntity):
    """Collecting data and return sensor entity."""

    def __init__(self, description: SensorEntityDescription, data, sensors):
        """Initialize the sensor."""
        self.entity_description = description
        self._data = data

        self._state = None
        self.sensors = sensors
        self._type = self.entity_description.key
        self._attr_icon = self.entity_description.icon
        self._attr_name = SENSOR_PREFIX + self.entity_description.name
        self._attr_state_class = self.entity_description.state_class
        self._attr_native_unit_of_measurement = self.entity_description.native_unit_of_measurement
        self._attr_device_class = self.entity_description.device_class
        self._attr_unique_id = f"{SENSOR_PREFIX}_{self._type}"

        self._discovery = False
        self._dev_id = {}

    @property
    def state(self):
        """Return the state of the sensor. (total/current power consumption/production or total gas used)"""
        return self._state

    async def async_update(self):
        """Get the latest data and use it to update our sensor state."""

        await self._data.async_update()
        energy = self._data.latest_data

        if energy:
            if self._type == 'devOnlineNum':
                if 'devOnlineNum' in energy['plantDetail']:
                    if energy['plantDetail']["devOnlineNum"] is not None:
                        self._state = int(energy['plantDetail']["devOnlineNum"])
            if self._type == 'nowPower':
                if 'nowPower' in energy['plantDetail']:
                    if energy['plantDetail']["nowPower"] is not None:
                        self._state = float(energy['plantDetail']["nowPower"])
            if self._type == 'runningState':
                if 'runningState' in energy['plantDetail']:
                    if energy['plantDetail']["runningState"] is not None:
                        self._state = int(energy['plantDetail']["runningState"])
            if self._type == 'todayElectricity':
                if 'todayElectricity' in energy['plantDetail']:
                    if energy['plantDetail']["todayElectricity"] is not None:
                        self._state = float(energy['plantDetail']["todayElectricity"])
            if self._type == 'monthElectricity':
                if 'monthElectricity' in energy['plantDetail']:
                    if energy['plantDetail']["monthElectricity"] is not None:
                        self._state = float(energy['plantDetail']["monthElectricity"])
            if self._type == 'yearElectricity':
                if 'yearElectricity' in energy['plantDetail']:
                    if energy['plantDetail']["yearElectricity"] is not None:
                        self._state = float(energy['plantDetail']["yearElectricity"])
            if self._type == 'totalElectricity':
                if 'totalElectricity' in energy['plantDetail']:
                    if energy['plantDetail']["totalElectricity"] is not None:
                        self._state = float(energy['plantDetail']["totalElectricity"])
            if self._type == 'todayGridIncome':
                if 'todayGridIncome' in energy['plantDetail']:
                    if energy['plantDetail']["todayGridIncome"] is not None:
                        self._state = float(energy['plantDetail']["todayGridIncome"])
            if self._type == 'income':
                if 'income' in energy['plantDetail']:
                    if energy['plantDetail']["income"] is not None:
                        self._state = float(energy['plantDetail']["income"])
            if self._type == 'selfUseRate':
                if 'selfUseRate' in energy['plantDetail']:
                    if energy['plantDetail']["selfUseRate"] is not None:
                        self._state = energy['plantDetail']["selfUseRate"]
            if self._type == 'totalBuyElec':
                if 'totalBuyElec' in energy['plantDetail']:
                    if energy['plantDetail']["totalBuyElec"] is not None:
                        self._state = float(energy['plantDetail']["totalBuyElec"])
            if self._type == 'totalConsumpElec':
                if 'totalConsumpElec' in energy['plantDetail']:
                    if energy['plantDetail']["totalConsumpElec"] is not None:
                        self._state = float(energy['plantDetail']["totalConsumpElec"])
            if self._type == 'totalSellElec':
                if 'totalSellElec' in energy['plantDetail']:
                    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 == 'lastUploadTime':
                if 'lastUploadTime' in energy['plantDetail']:
                    if energy['plantDetail']["lastUploadTime"] is not None:
                        self._state = (energy['plantDetail']["lastUploadTime"])
            if self._type == 'totalPlantTreeNum':
                if 'totalPlantTreeNum' in energy['plantDetail']:
                    if energy['plantDetail']["totalPlantTreeNum"] is not None:
                        self._state = (energy['plantDetail']["totalPlantTreeNum"])
            if self._type == 'totalReduceCo2':
                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]:
                    if energy['plantList'][0]["currency"] is not None:
                        self._state = (energy['plantList'][0]["currency"])
            if self._type == 'plantuid':
                if 'plantuid' in energy['plantList'][0]:
                    if energy['plantList'][0]["plantuid"] is not None:
                        self._state = (energy['plantList'][0]["plantuid"])
            if self._type == 'plantname':
                if 'plantname' in energy['plantList'][0]:
                    if energy['plantList'][0]["plantname"] is not None:
                        self._state = (energy['plantList'][0]["plantname"])
            if self._type == 'currency':
                if 'currency' in energy['plantList'][0]:
                    if energy['plantList'][0]["currency"] is not None:
                        self._state = (energy['plantList'][0]["currency"])
            if self._type == 'isOnline':
                if 'isOnline' in energy['plantList'][0]:
                    if energy['plantList'][0]["isOnline"] is not None:
                        self._state = (energy['plantList'][0]["isOnline"])
            if self._type == 'address':
                if 'address' in energy['plantList'][0]:
                    if energy['plantList'][0]["address"] is not None:
                        self._state = (energy['plantList'][0]["address"])


            if self._type == 'peakPower':
                if 'peakPower' in energy:
                    if energy["peakPower"] is not None:
                        self._state = float(energy["peakPower"])
            if self._type == 'status':
                if 'status' in energy:
                    if energy["status"] is not None:
                        self._state = (energy["status"])

            ########################################################################## SAJ h1
            if self.sensors == "h1":
                if self._type == 'chargeElec':
                    if 'chargeElec' in energy['viewBean']:
                        if energy['viewBean']["chargeElec"] is not None:
                            self._state = float(energy['viewBean']["chargeElec"])
                if self._type == 'dischargeElec':
                    if 'dischargeElec' in energy['viewBean']:
                        if energy['viewBean']["dischargeElec"] is not None:
                            self._state = float(energy['viewBean']["dischargeElec"])
                if self._type == 'buyElec':
                    if 'pvElec' in energy['viewBean']:
                        if energy['viewBean']["buyElec"] is not None:
                            self._state = float(energy['viewBean']["buyElec"])
                if self._type == 'buyRate':
                    if 'buyRate' in energy['viewBean']:
                        if energy['viewBean']["buyRate"] is not None:
                            self._state = energy['viewBean']["buyRate"]
                if self._type == 'pvElec':
                    if 'pvElec' in energy['viewBean']:
                        if energy['viewBean']["pvElec"] is not None:
                            self._state = float(energy['viewBean']["pvElec"])
                if self._type == 'selfConsumedEnergy1':
                    if 'selfConsumedEnergy1' in energy['viewBean']:
                        if energy['viewBean']["selfConsumedEnergy1"] is not None:
                            self._state = float(energy['viewBean']["selfConsumedEnergy1"])
                if self._type == 'selfConsumedEnergy2':
                    if 'selfConsumedEnergy2' in energy['viewBean']:
                        if energy['viewBean']["selfConsumedEnergy2"] is not None:
                            self._state = float(energy['viewBean']["selfConsumedEnergy2"])
                if self._type == 'selfConsumedRate1':
                    if 'selfConsumedRate1' in energy['viewBean']:
                        if energy['viewBean']["selfConsumedRate1"] is not None:
                            self._state = energy['viewBean']["selfConsumedRate1"]
                if self._type == 'selfConsumedRate2':
                    if 'selfConsumedRate2' in energy['viewBean']:
                        if energy['viewBean']["selfConsumedRate2"] is not None:
                            self._state = energy['viewBean']["selfConsumedRate2"]
                if self._type == 'sellElec':
                    if 'sellElec' in energy['viewBean']:
                        if energy['viewBean']["sellElec"] is not None:
                            self._state = float(energy['viewBean']["sellElec"])
                if self._type == 'sellRate':
                    if 'sellRate' in energy['viewBean']:
                        if energy['viewBean']["sellRate"] is not None:
                            self._state = energy['viewBean']["sellRate"]
                if self._type == 'useElec':
                    if 'useElec' in energy['viewBean']:
                        if energy['viewBean']["useElec"] is not None:
                            self._state = float(energy['viewBean']["useElec"])
                # storeDevicePower
                if self._type == 'batCapcity':
                    if 'batCapcity' in energy["storeDevicePower"]:
                        if energy["storeDevicePower"]['batCapcity'] is not None:
                            self._state = float(energy["storeDevicePower"]["batCapcity"])
                if self._type == 'isAlarm':
                    if 'isAlarm' in energy["storeDevicePower"]:
                        if energy["storeDevicePower"]['isAlarm'] is not None:
                            self._state = int(energy["storeDevicePower"]["isAlarm"])
                if self._type == 'batCurr':
                    if 'batCurr' in energy["storeDevicePower"]:
                        if energy["storeDevicePower"]['batCurr'] is not None:
                            self._state = float(energy["storeDevicePower"]["batCurr"])
                if self._type == 'batEnergyPercent':
                    if 'batEnergyPercent' in energy["storeDevicePower"]:
                        if energy["storeDevicePower"]['batEnergyPercent'] is not None:
                            self._state = float(energy["storeDevicePower"]["batEnergyPercent"])
                if self._type == 'batteryDirection':
                    if 'batteryDirection' in energy["storeDevicePower"]:
                        if energy["storeDevicePower"]['batteryDirection'] is not None:
                            if energy["storeDevicePower"]["batteryDirection"] == 0:
                                self._state = "Standby"
                            elif energy["storeDevicePower"]["batteryDirection"] == 1:
                                self._state = "Descarga"
                            elif energy["storeDevicePower"]["batteryDirection"] == -1:
                                self._state = "Carga"
                            else:
                                self._state = f'Unknown: {energy["storeDevicePower"]["batteryDirection"]}'
                if self._type == 'batteryPower':
                    if 'batteryPower' in energy["storeDevicePower"]:
                        if energy["storeDevicePower"]['batteryPower'] is not None:
                            self._state = float(energy["storeDevicePower"]["batteryPower"])
                if self._type == 'gridDirection':
                    if 'gridDirection' in energy["storeDevicePower"]:
                        if energy["storeDevicePower"]['gridDirection'] is not None:
                            self._state = float(energy["storeDevicePower"]["gridDirection"])
                if self._type == 'gridPower':
                    if 'gridPower' in energy["storeDevicePower"]:
                        if energy["storeDevicePower"]['gridPower'] is not None:
                            self._state = float(energy["storeDevicePower"]["gridPower"])
                if self._type == 'h1Online':
                    if 'isOnline' in energy["storeDevicePower"]:
                        if energy["storeDevicePower"]['isOnline'] is not None:
                            self._state = int(energy["storeDevicePower"]["isOnline"])
                if self._type == 'outPower':
                    if 'outPower' in energy["storeDevicePower"]:
                        if energy["storeDevicePower"]['outPower'] is not None:
                            self._state = float(energy["storeDevicePower"]["outPower"])
                if self._type == 'outPutDirection':
                    if 'outPutDirection' in energy["storeDevicePower"]:
                        if energy["storeDevicePower"]['outPutDirection'] is not None:
                            self._state = float(energy["storeDevicePower"]["outPutDirection"])
                if self._type == 'pvDirection':
                    if 'pvDirection' in energy["storeDevicePower"]:
                        if energy["storeDevicePower"]['pvDirection'] is not None:
                            self._state = int(energy["storeDevicePower"]["pvDirection"])
                if self._type == 'pvPower':
                    if 'pvPower' in energy["storeDevicePower"]:
                        if energy["storeDevicePower"]['pvPower'] is not None:
                            self._state = float(energy["storeDevicePower"]["pvPower"])
                if self._type == 'solarPower':
                    if 'solarPower' in energy["storeDevicePower"]:
                        if energy["storeDevicePower"]['solarPower'] is not None:
                            self._state = float(energy["storeDevicePower"]["solarPower"])
                if self._type == 'totalLoadPower':
                    if 'totalLoadPower' in energy["storeDevicePower"]:
                        if energy["storeDevicePower"]['totalLoadPower'] is not None:
                            self._state = float(energy["storeDevicePower"]['totalLoadPower'])


                ########################################################################## CUSTOM SENSORS H1 S2

                if self._type == 'h1s2_pv_volt_1':
                    if 'h1s2_pv_volt_1' in energy["h1s2"]:
                        if energy["h1s2"]['h1s2_pv_volt_1'] is not None:
                            self._state = float(energy["h1s2"]["h1s2_pv_volt_1"])
                if self._type == 'h1s2_pv_current_1':
                    if 'h1s2_pv_current_1' in energy["h1s2"]:
                        if energy["h1s2"]['h1s2_pv_current_1'] is not None:
                            self._state = float(energy["h1s2"]["h1s2_pv_current_1"])
                if self._type == 'h1s2_pv_power_1':
                    if 'h1s2_pv_power_1' in energy["h1s2"]:
                        if energy["h1s2"]['h1s2_pv_power_1'] is not None:
                            self._state = float(energy["h1s2"]["h1s2_pv_power_1"])
                if self._type == 'h1s2_pv_volt_2':
                    if 'h1s2_pv_volt_2' in energy["h1s2"]:
                        if energy["h1s2"]['h1s2_pv_volt_2'] is not None:
                            self._state = float(energy["h1s2"]["h1s2_pv_volt_2"])
                if self._type == 'h1s2_pv_current_2':
                    if 'h1s2_pv_current_2' in energy["h1s2"]:
                        if energy["h1s2"]['h1s2_pv_current_2'] is not None:
                            self._state = float(energy["h1s2"]["h1s2_pv_current_2"])
                if self._type == 'h1s2_pv_power_2':
                    if 'h1s2_pv_power_2' in energy["h1s2"]:
                        if energy["h1s2"]['h1s2_pv_power_2'] is not None:
                            self._state = float(energy["h1s2"]["h1s2_pv_power_2"])
                if self._type == 'h1s2_pv_volt_3':
                    if 'h1s2_pv_volt_3' in energy["h1s2"]:
                        if energy["h1s2"]['h1s2_pv_volt_3'] is not None:
                            self._state = float(energy["h1s2"]["h1s2_pv_volt_3"])
                if self._type == 'h1s2_pv_current_3':
                    if 'h1s2_pv_current_3' in energy["h1s2"]:
                        if energy["h1s2"]['h1s2_pv_current_3'] is not None:
                            self._state = float(energy["h1s2"]["h1s2_pv_current_3"])
                if self._type == 'h1s2_pv_power_3':
                    if 'h1s2_pv_power_3' in energy["h1s2"]:
                        if energy["h1s2"]['h1s2_pv_power_3'] is not None:
                            self._state = float(energy["h1s2"]["h1s2_pv_power_3"])
                if self._type == 'h1s2_bat_volt':
                    if 'h1s2_bat_volt' in energy["h1s2"]:
                        if energy["h1s2"]['h1s2_bat_volt'] is not None:
                            self._state = float(energy["h1s2"]["h1s2_bat_volt"])
                if self._type == 'h1s2_bat_current':
                    if 'h1s2_bat_current' in energy["h1s2"]:
                        if energy["h1s2"]['h1s2_bat_current'] is not None:
                            self._state = float(energy["h1s2"]["h1s2_bat_current"])
                if self._type == 'h1s2_bat_power':
                    if 'h1s2_bat_power' in energy["h1s2"]:
                        if energy["h1s2"]['h1s2_bat_power'] is not None:
                            self._state = float(energy["h1s2"]["h1s2_bat_power"])
                if self._type == 'h1s2_bat_total_charge':
                    if 'h1s2_bat_total_charge' in energy["h1s2"]:
                        if energy["h1s2"]['h1s2_bat_total_charge'] is not None:
                            self._state = float(energy["h1s2"]["h1s2_bat_total_charge"])
                if self._type == 'h1s2_bat_total_discharge':
                    if 'h1s2_bat_total_discharge' in energy["h1s2"]:
                        if energy["h1s2"]['h1s2_bat_total_discharge'] is not None:
                            self._state = float(energy["h1s2"]["h1s2_bat_total_discharge"])
                if self._type == 'h1s2_load_power':
                    if 'h1s2_load_power' in energy["h1s2"]:
                        if energy["h1s2"]['h1s2_load_power'] is not None:
                            self._state = float(energy["h1s2"]["h1s2_load_power"])
                if self._type == 'h1s2_grid_volt_1':
                    if 'h1s2_grid_volt_1' in energy["h1s2"]:
                        if energy["h1s2"]['h1s2_grid_volt_1'] is not None:
                            self._state = float(energy["h1s2"]["h1s2_grid_volt_1"])
                if self._type == 'h1s2_grid_current_1':
                    if 'h1s2_grid_current_1' in energy["h1s2"]:
                        if energy["h1s2"]['h1s2_grid_current_1'] is not None:
                            self._state = float(energy["h1s2"]["h1s2_grid_current_1"])
                if self._type == 'h1s2_grid_power_1':
                    if 'h1s2_grid_power_1' in energy["h1s2"]:
                        if energy["h1s2"]['h1s2_grid_power_1'] is not None:
                            self._state = float(energy["h1s2"]["h1s2_grid_power_1"])
                if self._type == 'h1s2_grid_volt_2':
                    if 'h1s2_grid_volt_2' in energy["h1s2"]:
                        if energy["h1s2"]['h1s2_grid_volt_2'] is not None:
                            self._state = float(energy["h1s2"]["h1s2_grid_volt_2"])
                if self._type == 'h1s2_grid_current_2':
                    if 'h1s2_grid_current_2' in energy["h1s2"]:
                        if energy["h1s2"]['h1s2_grid_current_2'] is not None:
                            self._state = float(energy["h1s2"]["h1s2_grid_current_2"])
                if self._type == 'h1s2_grid_power_2':
                    if 'h1s2_grid_power_2' in energy["h1s2"]:
                        if energy["h1s2"]['h1s2_grid_power_2'] is not None:
                            self._state = float(energy["h1s2"]["h1s2_grid_power_2"])
                if self._type == 'h1s2_grid_volt_3':
                    if 'h1s2_grid_volt_3' in energy["h1s2"]:
                        if energy["h1s2"]['h1s2_grid_volt_3'] is not None:
                            self._state = float(energy["h1s2"]["h1s2_grid_volt_3"])
                if self._type == 'h1s2_grid_current_3':
                    if 'h1s2_grid_current_3' in energy["h1s2"]:
                        if energy["h1s2"]['h1s2_grid_current_3'] is not None:
                            self._state = float(energy["h1s2"]["h1s2_grid_current_3"])
                if self._type == 'h1s2_grid_power_3':
                    if 'h1s2_grid_power_3' in energy["h1s2"]:
                        if energy["h1s2"]['h1s2_grid_power_3'] is not None:
                            self._state = float(energy["h1s2"]["h1s2_grid_power_3"])

            ########################################################################## Sec module Sensors:
            if self.sensors == "saj_sec":
                # getPlantMeterChartData - viewBeam
                if self._type == 'pvElec':
                    if 'pvElec' in energy["getPlantMeterChartData"]['viewBean']:
                        if energy["getPlantMeterChartData"]['viewBean']["pvElec"] is not None:
                            self._state = float(energy["getPlantMeterChartData"]['viewBean']["pvElec"])
                if self._type == 'useElec':
                    if 'useElec' in energy["getPlantMeterChartData"]['viewBean']:
                        if energy["getPlantMeterChartData"]['viewBean']["useElec"] is not None:
                            self._state = float(energy["getPlantMeterChartData"]['viewBean']["useElec"])
                if self._type == 'buyElec':
                    if 'buyElec' in energy["getPlantMeterChartData"]['viewBean']:
                        if energy["getPlantMeterChartData"]['viewBean']["buyElec"] is not None:
                            self._state = float(energy["getPlantMeterChartData"]['viewBean']["buyElec"])
                if self._type == 'sellElec':
                    if 'sellElec' in energy["getPlantMeterChartData"]['viewBean']:
                        if energy["getPlantMeterChartData"]['viewBean']["sellElec"] is not None:
                            self._state = float(energy["getPlantMeterChartData"]['viewBean']["sellElec"])
                if self._type == 'selfConsumedEnergy1':
                    if 'selfConsumedEnergy1' in energy["getPlantMeterChartData"]['viewBean']:
                        if energy["getPlantMeterChartData"]['viewBean']["selfConsumedEnergy1"] is not None:
                            self._state = float(energy["getPlantMeterChartData"]['viewBean']["selfConsumedEnergy1"])
                if self._type == 'selfConsumedEnergy2':
                    if 'selfConsumedEnergy2' in energy["getPlantMeterChartData"]['viewBean']:
                        if energy["getPlantMeterChartData"]['viewBean']["selfConsumedEnergy2"] is not None:
                            self._state = float(energy["getPlantMeterChartData"]['viewBean']["selfConsumedEnergy2"])
                if self._type == 'reduceCo2':
                    if 'reduceCo2' in energy["getPlantMeterChartData"]['viewBean']:
                        if energy["getPlantMeterChartData"]['viewBean']["reduceCo2"] is not None:
                            self._state = float(energy["getPlantMeterChartData"]['viewBean']["reduceCo2"])


                if self._type == 'buyRate':
                    if 'buyRate' in energy["getPlantMeterChartData"]['viewBean']:
                        if energy["getPlantMeterChartData"]['viewBean']["buyRate"] is not None:
                            self._state = (energy["getPlantMeterChartData"]['viewBean']["buyRate"])
                if self._type == 'sellRate':
                    if 'sellRate' in energy["getPlantMeterChartData"]['viewBean']:
                        if energy["getPlantMeterChartData"]['viewBean']["sellRate"] is not None:
                            self._state = (energy["getPlantMeterChartData"]['viewBean']["sellRate"])
                if self._type == 'selfConsumedRate1':
                    if 'selfConsumedRate1' in energy["getPlantMeterChartData"]['viewBean']:
                        if energy["getPlantMeterChartData"]['viewBean']["selfConsumedRate1"] is not None:
                            self._state = (energy["getPlantMeterChartData"]['viewBean']["selfConsumedRate1"])
                if self._type == 'selfConsumedRate2':
                    if 'selfConsumedRate2' in energy["getPlantMeterChartData"]['viewBean']:
                        if energy["getPlantMeterChartData"]['viewBean']["selfConsumedRate2"] is not None:
                            self._state = (energy["getPlantMeterChartData"]['viewBean']["selfConsumedRate2"])
                if self._type == 'plantTreeNum':
                    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':
                    if 'dataCountList' in energy:
                        if energy["getPlantMeterChartData"]['dataCountList'][4][-1] is not None:
                            self._state = float(energy["getPlantMeterChartData"]['dataCountList'][3][-1])
                if self._type == 'totalLoadPower':
                    if 'dataCountList' in energy:
                        if energy["getPlantMeterChartData"]['dataCountList'][4][-1] is not None:
                            self._state = float(energy["getPlantMeterChartData"]['dataCountList'][2][-1])
                if self._type == 'totalPvgenPower':
                    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':
                    if 'totalPvEnergy' in energy["getPlantMeterDetailInfo"]['plantDetail']:
                        if energy["getPlantMeterDetailInfo"]['plantDetail']["totalPvEnergy"] is not None:
                            self._state = (energy["getPlantMeterDetailInfo"]['plantDetail']["totalPvEnergy"])
                if self._type == 'totalLoadEnergy':
                    if 'totalLoadEnergy' in energy["getPlantMeterDetailInfo"]['plantDetail']:
                        if energy["getPlantMeterDetailInfo"]['plantDetail']["totalLoadEnergy"] is not None:
                            self._state = (energy["getPlantMeterDetailInfo"]['plantDetail']["totalLoadEnergy"])
                if self._type == 'totalBuyEnergy':
                    if 'totalBuyEnergy' in energy["getPlantMeterDetailInfo"]['plantDetail']:
                        if energy["getPlantMeterDetailInfo"]['plantDetail']["totalBuyEnergy"] is not None:
                            self._state = (energy["getPlantMeterDetailInfo"]['plantDetail']["totalBuyEnergy"])
                if self._type == 'totalSellEnergy':
                    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}")

@santiagozky
Copy link
Contributor Author

@teamMOYA check if by any chance your credentials work on the greenheiss url mentioned in my first comment. you might be lucky and could use the modified version that @miguelzx posted (which I guess is the same I did)

@santiagozky
Copy link
Contributor Author

@teamMOYA seems like solar the profit login is at https://inversor.saj-electric.com/cloud?login

my credentials work as well there. pretty sure they just reskin the system with different logos and colors. you probably can use the greenheiss url or this one.

@miguelzx
Copy link

miguelzx commented Oct 8, 2023

@teamMOYA check if by any chance your credentials work on the greenheiss url mentioned in my first comment. you might be lucky and could use the modified version that @miguelzx posted (which I guess is the same I did)

Hello, yes that's correct, that's what you said, thanks for the help.

That is the file as I have it, in case it is of any help to you.

Since yesterday I spent a hellish afternoon. Restoring backups, and thinking that the problem is that I had updated home assistant

@djansen1987
Copy link
Owner

i have a couple of account to test and develop with but all of them seem to work on the original portal so i am guessing it is only the greenheiss that stopped working. If there is anyone willing to share their login details i will see if i can add a option to the configuration yaml to switch to the correct url.

@arnauplan
Copy link

arnauplan commented Oct 8, 2023

Hello, I also had that problem.

My Greenheiss h1 inverter. I use an old integration 1.3.1 which I already have working.

Right now everything works perfectly for me

replacing the domain in the sensor.py

I leave a copy of my sensor.py, in case it helps you, but remember that I use 1.3.1

Thank you!!

@djansen1987
Copy link
Owner

djansen1987 commented Oct 8, 2023

@arnauplan @santiagozky @teamMOYA

Please be aware that the sensor.py above has more changes then only the domainname/url. !!Use at your own risk!!.

@miguelzx could you explain why you have change the H1 part and use beautiful soup to do this? Per my understanding the use of beautiful soup is not permitted by home assistant.

addition: the code used is a very old version of my custom integration. It still uses the old energy StateClass which are not supported by home assistant

@djansen1987
Copy link
Owner

djansen1987 commented Oct 8, 2023

@teamMOYA

The same is happening to me. My plant is gone in the "old platform".

Is your plant available in the new portal or do you have to go to the greenheiss portal ?

@teamMOYA
Copy link

teamMOYA commented Oct 8, 2023

Is your plant available in the new portal or do you have to go to the greenheiss portal ?

@elboletaire
Copy link

@teamMOYA is your kit branded as SAJ or some other white label (eg. Greenheiss)?

Mine are rebranded as "Solarprofit", but they don't have a web like Saj and Greenheiss. I'll have to wait for the new web access update.

You can still use any of the saj websites with your Solarprofit credentials.

So I guess having a way to configure our endpoint in the addon should suffice, although some websites may have different structure or calls, and that could complicate things.

@santiagozky
Copy link
Contributor Author

@djansen1987 I could provide you my credentials if that would help

@Txetxo1979
Copy link

Has the easiest way been found to be able to see the sensors again? I am new to home assistant.

@santiagozky
Copy link
Contributor Author

@Txetxo1979 so far, it seems to find out in which portal you can find your info (greenheiss, solarprofit, etc) and then modify the sensor.py file of the extension to replace the SAJ url with the one that works for you.

@djansen1987
Copy link
Owner

@djansen1987 I could provide you my credentials if that would help

That would help a lot. Could you send it to github@djansen.nl promise to handle it with care!

@Txetxo1979
Copy link

@Txetxo1979 so far, it seems to find out in which portal you can find your info (greenheiss, solarprofit, etc) and then modify the sensor.py file of the extension to replace the SAJ url with the one that works for you.

My URL is https://esaj-home.saj-electric.com/login
but I don't know where I can go to change the extension in sensor.py

@djansen1987
Copy link
Owner

@Txetxo1979 so far, it seems to find out in which portal you can find your info (greenheiss, solarprofit, etc) and then modify the sensor.py file of the extension to replace the SAJ url with the one that works for you.

My URL is https://esaj-home.saj-electric.com/login but I don't know where I can go to change the extension in sensor.py

This is the new portal, the api is completely changed on that site. Implementing that is almost like starting from scratch.. don't know if i got time for this soon.

@miguelzx
Copy link

@arnauplan @santiagozky @teamMOYA

Please be aware that the sensor.py above has more changes then only the domainname/url. !!Use at your own risk!!.

@miguelzx could you explain why you have change the H1 part and use beautiful soup to do this? Per my understanding the use of beautiful soup is not permitted by home assistant.

addition: the code used is a very old version of my custom integration. It still uses the old energy StateClass which are not supported by home assistant

Hello, my language is not English, so I hope the translator works well.

The version that is theirs, which as I mentioned is 1.3.1, which has worked well for me, until that happened. I use the latest version of home assistan and with my inverter, which is a saj clone, it works perfectly.

What I did was put it in sensor.py, it was replace

https://inversor.saj-electric.com/cloud?login, by https://inversores-style.greenheiss.com/cloud/logou.

and this session = async_create_clientsession(hass,False)

What did the previous colleague say?

@Txetxo1979
Copy link

@Txetxo1979 so far, it seems to find out in which portal you can find your info (greenheiss, solarprofit, etc) and then modify the sensor.py file of the extension to replace the SAJ url with the one that works for you.

My URL is https://esaj-home.saj-electric.com/login but I don't know where I can go to change the extension in sensor.py

This is the new portal, the api is completely changed on that site. Implementing that is almost like starting from scratch.. don't know if i got time for this soon.

Thank you so much.
I just saw that I also have the information at https://inversor.saj-electric.com/cloud?login
What should I do then to be able to have the information in home assistant?

@santiagozky
Copy link
Contributor Author

@miguelzx
Hola Miguel,
Yo tambien uso 1.3.1. no he actualizado a la nueva version.
el codigo tiene puesto directamente el dominio de saj en varios lugares. Tengo una version que lo actualiza con el dominio de greenheiss.

CUIDADO:tiene algunos cambios mas porque en mi caso que no tengo bateria, reportaba algunos valores en el sensor equivocado (despues de la linea 1136).
Anexo mi fichero tal cual lo tengo. Compararlo con el fichero que tienes en custom_components/saj_esolar/sensor.py de tu instalación de Home Assistant.
mi sensor.py tal cual lo tengo. it https://gist.github.com/santiagozky/311e830cffd0b54d2fa115162c5ad73c

@santiagozky
Copy link
Contributor Author

@Txetxo1979 if you dont mind reverting to 1.3.1. (which is what I still use), you could adjust my gist above to point to your url. just adjust these lines:

BASE_HOST = 'inversores-style.greenheiss.com'
BASE_DOMAIN = 'https://'+BASE_HOST
BASE_URL = BASE_DOMAIN+'/cloud'

caution: I did additional changes between lines 1138 and 1150 because of a mismatch in my data, probably because I dont have a battery (see #41), you could skip those changes.

@elboletaire
Copy link

@santiagozky why are you recommending people downgrading and updating a lower version? Latest version can be changed and fixed the same way 😕

@santiagozky
Copy link
Contributor Author

@elboletaire I havent recommended anyone to downgrade. Im merely offering the solution I have for myself. Im on 1.3.1 because I had previous changes that I dont want to reapply on newer versions.

@78lobo78
Copy link

Hello, when will the esolar platform be updated so that the sensors work well?

@djansen1987
Copy link
Owner

Hi all, sorry for the late response. Currently (still) sick and there for do not have time and energy to work on it. Maybe someone can make a pull request and test it with an SAJ portal user. I am okay to merge it. Otherwise somewhere next weekend I might be able to work on it.

@santiagozky
Copy link
Contributor Author

santiagozky commented Oct 16, 2023

I tried making a change but I've never done anything in python or HASS, so it's taking me quite a long.
I might keep giving it a shot, but I cannot make promises on how long it will take me. for those waiting, if you have a minimum programming experience you might be able to adjust it manually replacing all the urls in the sensor.py file.

@santiagozky
Copy link
Contributor Author

I opened a PR for this. @djansen1987 feel free to make any adjustment or recommendation you wish. particularly the configuration part.
#67

@matly006
Copy link

Good evening. I have an h1 inverter and valid credentials for both the https://esaj-home.saj-electric.com/index portal and for the old https://fop.saj-electric.com/saj.

If I can help, I'd be happy to help

@djansen1987
Copy link
Owner

Hi All, thanks to the work of @santiagozky this should now working in the latest version. Please read the release notes to known what to do. Thanks all for the input and patients!

https://github.com/djansen1987/SAJeSolar/releases/tag/v1.5.1

@santiagozky
Copy link
Contributor Author

thank you for merging and releasing @djansen1987

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants