diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 8dd5bb96..b59a76e0 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -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. @@ -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 @@ -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 diff --git a/.github/workflows/hacs.yaml b/.github/workflows/hacs.yaml index cb139837..e912832a 100644 --- a/.github/workflows/hacs.yaml +++ b/.github/workflows/hacs.yaml @@ -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" diff --git a/.github/workflows/hassfest.yaml b/.github/workflows/hassfest.yaml index 995fd132..a0ff1268 100644 --- a/.github/workflows/hassfest.yaml +++ b/.github/workflows/hassfest.yaml @@ -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" diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index 084220ae..c5df0fc7 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -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 }} diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 260f26bb..98b00a72 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -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 diff --git a/custom_components/solaredge_modbus_multi/__init__.py b/custom_components/solaredge_modbus_multi/__init__.py index 3a168559..5ca3320a 100644 --- a/custom_components/solaredge_modbus_multi/__init__.py +++ b/custom_components/solaredge_modbus_multi/__init__.py @@ -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 @@ -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, diff --git a/custom_components/solaredge_modbus_multi/button.py b/custom_components/solaredge_modbus_multi/button.py index e255cc92..754dcce6 100644 --- a/custom_components/solaredge_modbus_multi/button.py +++ b/custom_components/solaredge_modbus_multi/button.py @@ -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() @@ -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() diff --git a/custom_components/solaredge_modbus_multi/config_flow.py b/custom_components/solaredge_modbus_multi/config_flow.py index ae1d28e2..c017e6a8 100644 --- a/custom_components/solaredge_modbus_multi/config_flow.py +++ b/custom_components/solaredge_modbus_multi/config_flow.py @@ -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 @@ -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 diff --git a/custom_components/solaredge_modbus_multi/diagnostics.py b/custom_components/solaredge_modbus_multi/diagnostics.py index fb4cbe12..d30d4a26 100644 --- a/custom_components/solaredge_modbus_multi/diagnostics.py +++ b/custom_components/solaredge_modbus_multi/diagnostics.py @@ -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"} diff --git a/custom_components/solaredge_modbus_multi/hub.py b/custom_components/solaredge_modbus_multi/hub.py index d1a62c5e..fffe3b46 100644 --- a/custom_components/solaredge_modbus_multi/hub.py +++ b/custom_components/solaredge_modbus_multi/hub.py @@ -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, @@ -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}") @@ -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}") @@ -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()} ") @@ -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." ) @@ -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]: @@ -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 @@ -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( diff --git a/custom_components/solaredge_modbus_multi/sensor.py b/custom_components/solaredge_modbus_multi/sensor.py index 37a98d26..9ae4a058 100644 --- a/custom_components/solaredge_modbus_multi/sensor.py +++ b/custom_components/solaredge_modbus_multi/sensor.py @@ -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( @@ -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( @@ -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}" ) ) @@ -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}" ) @@ -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}" ) ) @@ -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}" ) @@ -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" diff --git a/custom_components/solaredge_modbus_multi/switch.py b/custom_components/solaredge_modbus_multi/switch.py index 299b40cd..c95e31d8 100644 --- a/custom_components/solaredge_modbus_multi/switch.py +++ b/custom_components/solaredge_modbus_multi/switch.py @@ -238,7 +238,9 @@ async def async_turn_on(self, **kwargs: Any) -> None: await self._platform.write_registers( address=61762, payload=ModbusClientMixin.convert_to_registers( - 0x1, data_type=ModbusClientMixin.DATATYPE.INT32, word_order="little" + 0x1, + data_type=ModbusClientMixin.DATATYPE.INT32, + word_order="little", ), ) await self.async_update() @@ -249,7 +251,9 @@ async def async_turn_off(self, **kwargs: Any) -> None: await self._platform.write_registers( address=61762, payload=ModbusClientMixin.convert_to_registers( - 0x0, data_type=ModbusClientMixin.DATATYPE.INT32, word_order="little" + 0x0, + data_type=ModbusClientMixin.DATATYPE.INT32, + word_order="little", ), ) await self.async_update() diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..a8b297ce --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,6 @@ +[tool.ruff] +line-length = 88 + +[tool.ruff.lint] +extend-select = ["I"] +ignore = ["E701"] diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index dd6412ad..00000000 --- a/setup.cfg +++ /dev/null @@ -1,7 +0,0 @@ -[flake8] -max-line-length = 80 -extend-select = B950 -extend-ignore = E203,E501,E701 - -[isort] -profile = black