Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,13 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@v7
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
persist-credentials: false

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v4
uses: github/codeql-action/init@ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
Expand All @@ -55,7 +57,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v4
uses: github/codeql-action/autobuild@ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd

# ℹ️ Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
Expand All @@ -68,4 +70,4 @@ jobs:
# ./location_of_script_within_repo/buildscript.sh

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v4
uses: github/codeql-action/analyze@ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd
6 changes: 4 additions & 2 deletions .github/workflows/hacs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ jobs:
name: HACS Action
runs-on: "ubuntu-latest"
steps:
- uses: "actions/checkout@v7"
- uses: "actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1"
with:
persist-credentials: false
- name: HACS Action
uses: "hacs/action@main"
uses: "hacs/action@1ebf01c408f29afcb6406bd431bc98fd8cbb15aa"
with:
category: "integration"
6 changes: 4 additions & 2 deletions .github/workflows/hassfest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,7 @@ jobs:
validate:
runs-on: "ubuntu-latest"
steps:
- uses: "actions/checkout@v7"
- uses: "home-assistant/actions/hassfest@master"
- uses: "actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1"
with:
persist-credentials: false
- uses: "home-assistant/actions/hassfest@a7c616ce81ccda50150bf1595786c71b1883fabb"
13 changes: 10 additions & 3 deletions .github/workflows/linter.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,24 @@ jobs:
statuses: write
steps:
- name: Checkout Code
uses: actions/checkout@v7
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
fetch-depth: 0
persist-credentials: false
- name: Lint Code Base
uses: github/super-linter@v7
uses: super-linter/super-linter@4ce20838b8ab83717e78138c5b3a1407148e0918
env:
VALIDATE_ALL_CODEBASE: false
VALIDATE_JSCPD: false
VALIDATE_PYTHON_MYPY: false
VALIDATE_PYTHON_PYLINT: false
VALIDATE_PYTHON_PYINK: false
VALIDATE_PYTHON_BLACK: false
VALIDATE_PYTHON_FLAKE8: false
VALIDATE_PYTHON_ISORT: false
VALIDATE_SPELL_CODESPELL: false
VALIDATE_BIOME_FORMAT: false
LINTER_RULES_PATH: .
PYTHON_RUFF_CONFIG_FILE: pyproject.toml
PYTHON_RUFF_FORMAT_CONFIG_FILE: pyproject.toml
DEFAULT_BRANCH: main
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
6 changes: 4 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v7
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@v7
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97
with:
python-version: "3.13"
- name: Install test dependencies
Expand Down
12 changes: 10 additions & 2 deletions custom_components/solaredge_modbus_multi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@

import voluptuous as vol
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_HOST, CONF_PORT, CONF_SCAN_INTERVAL, Platform
from homeassistant.const import (
CONF_HOST,
CONF_PORT,
CONF_SCAN_INTERVAL,
Platform,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import DeviceEntry
from homeassistant.helpers.typing import ConfigType
Expand Down Expand Up @@ -235,7 +240,10 @@ async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry) ->

class SolarEdgeCoordinator(TimestampDataUpdateCoordinator):
def __init__(
self, hass: HomeAssistant, hub: SolarEdgeModbusMultiHub, scan_interval: int
self,
hass: HomeAssistant,
hub: SolarEdgeModbusMultiHub,
scan_interval: int,
):
super().__init__(
hass,
Expand Down
8 changes: 6 additions & 2 deletions custom_components/solaredge_modbus_multi/button.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,9 @@ async def async_press(self) -> None:
await self._platform.write_registers(
address=61696,
payload=ModbusClientMixin.convert_to_registers(
1, data_type=ModbusClientMixin.DATATYPE.UINT16, word_order="little"
1,
data_type=ModbusClientMixin.DATATYPE.UINT16,
word_order="little",
),
)
await self.async_update()
Expand Down Expand Up @@ -148,7 +150,9 @@ async def async_press(self) -> None:
await self._platform.write_registers(
address=61697,
payload=ModbusClientMixin.convert_to_registers(
1, data_type=ModbusClientMixin.DATATYPE.UINT16, word_order="little"
1,
data_type=ModbusClientMixin.DATATYPE.UINT16,
word_order="little",
),
)
await self.async_update()
22 changes: 17 additions & 5 deletions custom_components/solaredge_modbus_multi/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,17 @@
import homeassistant.helpers.config_validation as cv
import voluptuous as vol
from homeassistant import config_entries
from homeassistant.config_entries import ConfigEntry, ConfigFlowResult, OptionsFlow
from homeassistant.const import CONF_HOST, CONF_NAME, CONF_PORT, CONF_SCAN_INTERVAL
from homeassistant.config_entries import (
ConfigEntry,
ConfigFlowResult,
OptionsFlow,
)
from homeassistant.const import (
CONF_HOST,
CONF_NAME,
CONF_PORT,
CONF_SCAN_INTERVAL,
)
from homeassistant.core import callback
from homeassistant.data_entry_flow import AbortFlow
from homeassistant.exceptions import HomeAssistantError
Expand Down Expand Up @@ -477,19 +486,22 @@ async def async_step_init(
CONF_SCAN_INTERVAL, ConfDefaultInt.SCAN_INTERVAL
),
ConfName.KEEP_MODBUS_OPEN: self.config_entry.options.get(
ConfName.KEEP_MODBUS_OPEN, bool(ConfDefaultFlag.KEEP_MODBUS_OPEN)
ConfName.KEEP_MODBUS_OPEN,
bool(ConfDefaultFlag.KEEP_MODBUS_OPEN),
),
ConfName.DETECT_METERS: self.config_entry.options.get(
ConfName.DETECT_METERS, bool(ConfDefaultFlag.DETECT_METERS)
),
ConfName.DETECT_BATTERIES: self.config_entry.options.get(
ConfName.DETECT_BATTERIES, bool(ConfDefaultFlag.DETECT_BATTERIES)
ConfName.DETECT_BATTERIES,
bool(ConfDefaultFlag.DETECT_BATTERIES),
),
ConfName.DETECT_EXTRAS: self.config_entry.options.get(
ConfName.DETECT_EXTRAS, bool(ConfDefaultFlag.DETECT_EXTRAS)
),
ConfName.ADV_PWR_CONTROL: self.config_entry.options.get(
ConfName.ADV_PWR_CONTROL, bool(ConfDefaultFlag.ADV_PWR_CONTROL)
ConfName.ADV_PWR_CONTROL,
bool(ConfDefaultFlag.ADV_PWR_CONTROL),
),
ConfName.SLEEP_AFTER_WRITE: self.config_entry.options.get(
ConfName.SLEEP_AFTER_WRITE, ConfDefaultInt.SLEEP_AFTER_WRITE
Expand Down
7 changes: 6 additions & 1 deletion custom_components/solaredge_modbus_multi/diagnostics.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@
REDACT_CONFIG = {"unique_id", "host"}
REDACT_INVERTER = {"identifiers", "C_SerialNumber", "serial_number"}
REDACT_METER = {"identifiers", "C_SerialNumber", "serial_number", "via_device"}
REDACT_BATTERY = {"identifiers", "B_SerialNumber", "serial_number", "via_device"}
REDACT_BATTERY = {
"identifiers",
"B_SerialNumber",
"serial_number",
"via_device",
}
REDACT_EVSE = {"identifiers", "C_SerialNumber", "serial_number"}


Expand Down
41 changes: 32 additions & 9 deletions custom_components/solaredge_modbus_multi/hub.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,8 @@ def __init__(
ConfName.KEEP_MODBUS_OPEN, bool(ConfDefaultFlag.KEEP_MODBUS_OPEN)
)
self._adv_storage_control = entry_options.get(
ConfName.ADV_STORAGE_CONTROL, bool(ConfDefaultFlag.ADV_STORAGE_CONTROL)
ConfName.ADV_STORAGE_CONTROL,
bool(ConfDefaultFlag.ADV_STORAGE_CONTROL),
)
self._adv_site_limit_control = entry_options.get(
ConfName.ADV_SITE_LIMIT_CONTROL,
Expand Down Expand Up @@ -406,7 +407,11 @@ async def _async_init_solaredge(self) -> None:
for evse in self.evses:
await evse.read_modbus_data()

except (ModbusReadError, ModbusIllegalFunction, ModbusIllegalValue) as e:
except (
ModbusReadError,
ModbusIllegalFunction,
ModbusIllegalValue,
) as e:
await self.disconnect()
raise HubInitFailed(f"Read error: {e}")

Expand Down Expand Up @@ -489,7 +494,11 @@ async def async_refresh_modbus_data(self) -> bool:
for evse in self.evses:
await evse.read_modbus_data()

except (ModbusReadError, ModbusIllegalFunction, ModbusIllegalValue) as e:
except (
ModbusReadError,
ModbusIllegalFunction,
ModbusIllegalValue,
) as e:
await self.disconnect()
raise DataUpdateFailed(f"Update failed: {e}")

Expand Down Expand Up @@ -593,11 +602,15 @@ async def modbus_read_holding_registers(self, unit, address, rcount):

if "device_id" in sig.parameters:
result = await self._client.read_holding_registers(
address=self._rr_address, count=self._rr_count, device_id=self._rr_unit
address=self._rr_address,
count=self._rr_count,
device_id=self._rr_unit,
)
else:
result = await self._client.read_holding_registers(
address=self._rr_address, count=self._rr_count, slave=self._rr_unit
address=self._rr_address,
count=self._rr_count,
slave=self._rr_unit,
)

_LOGGER.debug(f"unit={self._rr_unit}: result is error: {result.isError()} ")
Expand Down Expand Up @@ -1092,7 +1105,10 @@ async def init_device(self) -> None:
self._use_status_vendor4 = this_ver >= AwesomeVersion(
STATUS_VENDOR4_VERSION
)
except (AwesomeVersionCompareException, AwesomeVersionStrategyException) as e:
except (
AwesomeVersionCompareException,
AwesomeVersionStrategyException,
) as e:
_LOGGER.error(
f"Error checking inverter version: {e}. Please report this issue."
)
Expand Down Expand Up @@ -1265,7 +1281,9 @@ async def read_modbus_data(self) -> None:

try:
inverter_data = await self.hub.modbus_read_holding_registers(
unit=self.inverter_unit_id, address=40123, rcount=mmppt_registers
unit=self.inverter_unit_id,
address=40123,
rcount=mmppt_registers,
)

if self.decoded_mmppt["mmppt_Units"] in [2, 3]:
Expand Down Expand Up @@ -1993,7 +2011,10 @@ class SolarEdgeMMPPTUnit:
"""Defines a SolarEdge inverter MMPPT unit."""

def __init__(
self, inverter: SolarEdgeInverter, hub: SolarEdgeModbusMultiHub, unit: int
self,
inverter: SolarEdgeInverter,
hub: SolarEdgeModbusMultiHub,
unit: int,
) -> None:
self.inverter = inverter
self.hub = hub
Expand Down Expand Up @@ -2392,7 +2413,9 @@ def __init__(
async def init_device(self) -> None:
try:
battery_info = await self.hub.modbus_read_holding_registers(
unit=self.inverter_unit_id, address=self.start_address, rcount=68
unit=self.inverter_unit_id,
address=self.start_address,
rcount=68,
)

self.decoded_common = dict(
Expand Down
33 changes: 24 additions & 9 deletions custom_components/solaredge_modbus_multi/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,12 @@ def __init__(self, platform, config_entry, coordinator, phase: str = None):

if self._platform.decoded_model["C_SunSpec_DID"] in [101, 102, 103]:
self.SUNSPEC_NOT_IMPL = SunSpecNotImpl.UINT16
elif self._platform.decoded_model["C_SunSpec_DID"] in [201, 202, 203, 204]:
elif self._platform.decoded_model["C_SunSpec_DID"] in [
201,
202,
203,
204,
]:
self.SUNSPEC_NOT_IMPL = SunSpecNotImpl.INT16
else:
raise RuntimeError(
Expand Down Expand Up @@ -473,7 +478,12 @@ def __init__(self, platform, config_entry, coordinator, phase: str = None):

if self._platform.decoded_model["C_SunSpec_DID"] in [101, 102, 103]:
self.SUNSPEC_NOT_IMPL = SunSpecNotImpl.UINT16
elif self._platform.decoded_model["C_SunSpec_DID"] in [201, 202, 203, 204]:
elif self._platform.decoded_model["C_SunSpec_DID"] in [
201,
202,
203,
204,
]:
self.SUNSPEC_NOT_IMPL = SunSpecNotImpl.INT16
else:
raise RuntimeError(
Expand Down Expand Up @@ -2120,8 +2130,8 @@ def native_value(self):
):
_LOGGER.warning(
(
"Battery Export Energy went backwards: Current value " # noqa: B950
f"{self._platform.decoded_model['B_Export_Energy_WH']} " # noqa: B950
"Battery Export Energy went backwards: Current value "
f"{self._platform.decoded_model['B_Export_Energy_WH']} "
f"is less than last value of {self._last}"
)
)
Expand All @@ -2132,7 +2142,7 @@ def native_value(self):
_LOGGER.debug(
(
"B_Export_Energy went backwards: "
f"{self._platform.decoded_model['B_Export_Energy_WH']} " # noqa: B950
f"{self._platform.decoded_model['B_Export_Energy_WH']} "
f"< {self._last} cycle {self._count} of "
f"{self._platform.battery_energy_reset_cycles}"
)
Expand Down Expand Up @@ -2209,8 +2219,8 @@ def native_value(self):
):
_LOGGER.warning(
(
"Battery Import Energy went backwards: Current value " # noqa: B950
f"{self._platform.decoded_model['B_Import_Energy_WH']} " # noqa: B950
"Battery Import Energy went backwards: Current value "
f"{self._platform.decoded_model['B_Import_Energy_WH']} "
f"is less than last value of {self._last}"
)
)
Expand All @@ -2221,7 +2231,7 @@ def native_value(self):
_LOGGER.debug(
(
"B_Import_Energy went backwards: "
f"{self._platform.decoded_model['B_Import_Energy_WH']} " # noqa: B950
f"{self._platform.decoded_model['B_Import_Energy_WH']} "
f"< {self._last} cycle {self._count} of "
f"{self._platform.battery_energy_reset_cycles}"
)
Expand Down Expand Up @@ -2520,7 +2530,12 @@ def extra_state_attributes(self):

if self._platform.decoded_model["CommitPwrCtlSettings"] == 0x0:
attrs["status"] = "SUCCESS"
if self._platform.decoded_model["CommitPwrCtlSettings"] in [0x1, 0x2, 0x3, 0x4]:
if self._platform.decoded_model["CommitPwrCtlSettings"] in [
0x1,
0x2,
0x3,
0x4,
]:
attrs["status"] = "INTERNAL_ERROR"
if self._platform.decoded_model["CommitPwrCtlSettings"] == 0xFFFF:
attrs["status"] = "UNKNOWN_ERROR"
Expand Down
Loading
Loading