diff --git a/can_sniffer/deploy/can-sniffer.service b/can_sniffer/deploy/can-sniffer.service index 3d14439..02cda6f 100644 --- a/can_sniffer/deploy/can-sniffer.service +++ b/can_sniffer/deploy/can-sniffer.service @@ -41,8 +41,9 @@ StandardError=journal SyslogIdentifier=can-sniffer # Security hardening (RPI5 совместимо) -NoNewPrivileges=yes -ProtectSystem=strict +# NoNewPrivileges отключен для поддержки sudo (shutdown/reboot) +NoNewPrivileges=no +ProtectSystem=full ProtectHome=read-only PrivateTmp=yes ReadWritePaths=/opt/can_sniffer/data /opt/can_sniffer/logs @@ -51,9 +52,11 @@ ReadWritePaths=/opt/can_sniffer/data /opt/can_sniffer/logs CapabilityBoundingSet=CAP_NET_RAW CAP_NET_ADMIN AmbientCapabilities=CAP_NET_RAW CAP_NET_ADMIN -# Доступ к UART для Flipper Zero (/dev/ttyAMA0) -SupplementaryGroups=dialout +# Доступ к UART для Flipper Zero (/dev/ttyAMA0) и I2C для UPS +SupplementaryGroups=dialout i2c gpio DeviceAllow=/dev/ttyAMA0 rw +DeviceAllow=/dev/i2c-1 rw +DeviceAllow=/dev/gpiomem rw [Install] WantedBy=multi-user.target diff --git a/can_sniffer/requirements.txt b/can_sniffer/requirements.txt index a3bb901..e3cec48 100644 --- a/can_sniffer/requirements.txt +++ b/can_sniffer/requirements.txt @@ -3,4 +3,6 @@ pydantic-settings>=2.0.0 python-can>=4.0.0 psycopg2-binary>=2.9.0 pyserial>=3.5 +smbus2>=0.4.0 +gpiozero>=2.0.0 diff --git a/can_sniffer/src/flipper/providers/ups_provider.py b/can_sniffer/src/flipper/providers/ups_provider.py index 11cbbdd..0f8f14a 100644 --- a/can_sniffer/src/flipper/providers/ups_provider.py +++ b/can_sniffer/src/flipper/providers/ups_provider.py @@ -62,20 +62,32 @@ class UPSProvider(BaseProvider): import smbus2 self._bus = smbus2.SMBus(self.I2C_BUS) self._available = True - except ImportError: + logger.info(f"UPS I2C initialized on bus {self.I2C_BUS}, address 0x{self.I2C_ADDRESS:02X}") + except ImportError as e: self._last_error = "smbus2 not installed" self._available = False + logger.warning(f"UPS unavailable: smbus2 not installed. Install with: pip install smbus2") + except PermissionError as e: + self._last_error = f"I2C permission denied: {e}" + self._available = False + logger.error(f"UPS I2C permission denied. Add user to i2c group: sudo usermod -aG i2c $USER") + except FileNotFoundError as e: + self._last_error = f"I2C bus not found: {e}" + self._available = False + logger.error(f"I2C bus {self.I2C_BUS} not found. Enable I2C in raspi-config.") except Exception as e: self._last_error = f"I2C init failed: {e}" self._available = False + logger.error(f"UPS I2C init failed: {e}") try: from gpiozero import Button self._pld_button = Button(self.PLD_PIN) + logger.debug(f"UPS PLD GPIO {self.PLD_PIN} initialized") except ImportError: - pass # GPIO optional - except Exception: - pass # GPIO optional + logger.debug("gpiozero not installed, power loss detection disabled") + except Exception as e: + logger.debug(f"GPIO init failed (optional): {e}") def _read_voltage_and_capacity(self) -> Tuple[float, float]: """ @@ -131,10 +143,20 @@ class UPSProvider(BaseProvider): Input voltage in V """ try: - from subprocess import check_output - output = check_output(["vcgencmd", "pmic_read_adc", "EXT5V_V"]).decode("utf-8") - value_str = output.split("=")[1].strip().rstrip("V") - return float(value_str) + from subprocess import check_output, DEVNULL + # Try common vcgencmd paths + vcgencmd_paths = ["/usr/bin/vcgencmd", "/opt/vc/bin/vcgencmd", "vcgencmd"] + for vcgencmd in vcgencmd_paths: + try: + output = check_output( + [vcgencmd, "pmic_read_adc", "EXT5V_V"], + stderr=DEVNULL + ).decode("utf-8") + value_str = output.split("=")[1].strip().rstrip("V") + return float(value_str) + except FileNotFoundError: + continue + return 0.0 except Exception: return 0.0