ParadoxAlarmInterface / ParadoxAlarmInterface/pai
[Bug] ValueError: hour must be in 0-23 range in adapters.py v3.7.0 - Spectra/Magellan parsing
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 424
- Forks
- 118
- PR merge metrics
- No merged PRs in 30d
Description
GitHub Issue Report: PAI Paradox Alarm Interface - ValueError en parsing de fecha/hora
🐛 Descripción del Bug
PAI versión 3.7.0 está generando errores de ValueError al intentar parsear mensajes de eventos en vivo del panel Paradox, específicamente cuando intenta crear objetos datetime con valores de hora inválidos.
📋 Información del Entorno
Sistema Home Assistant
- Método de instalación: Home Assistant OS
- Core: 2025.7.1
- Supervisor: 2025.06.2
- Operating System: 15.2
- Frontend: 20250702.1
PAI Configuration
- Versión PAI: 3.7.0 (actualizado recientemente)
- Panel: Paradox Spectra/Magellan (basado en el stack trace)
- Conexión: [NECESITA CONFIRMACIÓN - Serial/IP/Ethernet]
🔥 Error Completo
2025-07-09 16:41:30,494 - ERROR - PAI.paradox.hardware.spectra_magellan.panel - Exception parsing message: b'e219070910280011000000000000476172616a652031372020202020202000000000001a20'
Traceback (most recent call last):
File "/usr/local/lib/python3.11/site-packages/paradox/hardware/spectra_magellan/panel.py", line 173, in parse_message
return parsers.LiveEvent.parse(message)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/construct/core.py", line 308, in parse
return self.parse_stream(io.BytesIO(data), **contextkw)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/construct/core.py", line 320, in parse_stream
return self._parsereport(stream, context, "(parsing)")
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/construct/core.py", line 332, in _parsereport
obj = self._parse(stream, context, path)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/construct/core.py", line 2000, in _parse
subobj = sc._parsereport(stream, context, path)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/construct/core.py", line 332, in _parsereport
obj = self._parse(stream, context, path)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/construct/core.py", line 2489, in _parse
return self.subcon._parsereport(stream, context, path)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/construct/core.py", line 332, in _parsereport
obj = self._parse(stream, context, path)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/construct/core.py", line 4368, in _parse
obj = self.subcon._parsereport(stream, context, path)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/construct/core.py", line 332, in _parsereport
obj = self._parse(stream, context, path)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/construct/core.py", line 2000, in _parse
subobj = sc._parsereport(stream, context, path)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/construct/core.py", line 332, in _parsereport
obj = self._parse(stream, context, path)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/construct/core.py", line 2489, in _parse
return self.subcon._parsereport(stream, context, path)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/construct/core.py", line 332, in _parsereport
obj = self._parse(stream, context, path)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/construct/core.py", line 719, in _parse
return self._decode(obj, context, path)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/paradox/hardware/spectra_magellan/adapters.py", line 9, in _decode
return datetime.datetime(obj[0] * 100 + obj[1], obj[2], obj[3], obj[4], obj[5])
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ValueError: hour must be in 0..
🔍 Análisis del Error
Mensaje Raw Parseado
b'e219070910280011000000000000476172616a652031372020202020202000000000001a20'
Ubicación del Error
- Archivo:
/usr/local/lib/python3.11/site-packages/paradox/hardware/spectra_magellan/adapters.py - Línea: 9
- Función:
_decode()
Problema Identificado
El error ocurre cuando PAI intenta crear un objeto datetime.datetime() en la línea:
return datetime.datetime(obj[0] * 100 + obj[1], obj[2], obj[3], obj[4], obj[5])
Los valores extraídos del mensaje del panel están produciendo un valor de hora (obj[4]) que es ≥ 24, lo cual es inválido para datetime.datetime().
🔄 Reproducibilidad
- Frecuencia: Ocurre de forma intermitente
- Desencadenante: Eventos de alarma del panel Paradox
- Momento: Aparentemente cuando el panel envía eventos en vivo
- Versión anterior: El problema comenzó después de actualizar a PAI 3.7.0
💡 Posibles Causas
- Configuración de hora en panel: El panel podría estar configurado en formato 12h y enviando valores AM/PM que PAI interpreta incorrectamente
- Zona horaria: Problemas de conversión de zona horaria
- Parsing de formato: Cambios en el protocolo de parsing en v3.7.0
- Bug de regresión: Nuevo bug introducido en la versión 3.7.0
🛠️ Solución Temporal Sugerida
Validación en adapters.py
def _decode(self, obj, context, path):
# Validar y limitar valores antes de crear datetime
year = obj[0] * 100 + obj[1] if obj[0] < 100 else obj[0]
month = max(1, min(12, obj[2]))
day = max(1, min(31, obj[3]))
hour = max(0, min(23, obj[4])) # Limitar hora a 0-23
minute = max(0, min(59, obj[5])) # Limitar minutos a 0-59
return datetime.datetime(year, month, day, hour, minute)
📊 Información Adicional Necesaria
Para ayudar en el diagnóstico, por favor proporciona:
- Modelo exacto del panel Paradox
- Configuración de fecha/hora del panel (12h/24h, zona horaria)
- Método de conexión (Serial, IP, etc.)
- Configuración PAI (archivo de configuración relevante)
- ¿Funcionaba correctamente en versión anterior? (¿cuál?)
🎯 Comportamiento Esperado
PAI debería:
- Parsear correctamente todos los mensajes de eventos del panel
- Manejar graciosamente valores de fecha/hora inválidos
- Registrar warnings en lugar de errores fatales para parsing fallido
- Continuar operando sin interrupciones
📋 Checklist para Desarrolladores
- Revisar cambios en adapters.py entre v3.6.x y v3.7.0
- Añadir validación de valores de fecha/hora antes de crear datetime
- Implementar logging detallado del parsing de mensajes
- Considerar modo de compatibilidad para paneles antiguos
- Añadir tests unitarios para casos de valores extremos
🔗 Enlaces Relevantes
#v3.7.0
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with paradox/hardware/spectra_magellan/adapters.py and the _decode() function at line 9, then compare the date/time parsing changes between v3.6.x and v3.7.0. Reproduce the failure with the reported raw message and verify the panel protocol before deciding how invalid values should be handled. Done means live event parsing no longer raises this ValueError and extreme date/time cases have regression coverage.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100