kk7ds / pynx584

Python library and server for talking to NX584/NX8E interfaces
GNU General Public License v3.0
29 stars 26 forks source link

Controller loop exited #84

Open tzavellas opened 1 year ago

tzavellas commented 1 year ago

Hello,

When trying to start a docker container with docker compose, I get the following log:

2023-08-28 20:53:05,103 main INFO Ready
2023-08-28 20:53:05,126 controller INFO Loaded extensions []
2023-08-28 20:53:05,138 _internal INFO  * Running on http://0.0.0.0:5007/ (Press CTRL+C to quit)
2023-08-28 20:53:05,149 controller INFO Connected
2023-08-28 20:53:05,149 controller INFO Connected
2023-08-28 20:53:05,678 controller ERROR Controller loop exited: cannot concatenate 'str' and 'int' objects
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/site-packages/nx584/controller.py", line 852, in controller_loop_safe
    self.controller_loop()
  File "/usr/local/lib/python2.7/site-packages/nx584/controller.py", line 810, in controller_loop
    frame = self.process_next()
  File "/usr/local/lib/python2.7/site-packages/nx584/controller.py", line 439, in process_next
    data = self._ser.read_frame_raw()
  File "/usr/local/lib/python2.7/site-packages/nx584/controller.py", line 317, in read_frame_raw
    return self.protocol.read_frame()
  File "/usr/local/lib/python2.7/site-packages/nx584/controller.py", line 225, in read_frame
    while (i <= length + 2):
TypeError: cannot concatenate 'str' and 'int' objects
2023-08-28 20:53:05,681 controller WARNING Waiting 10s before reconnecting...
2023-08-28 20:53:15,710 controller INFO Connected
2023-08-28 20:53:15,711 controller INFO Connected
2023-08-28 20:53:45,782 controller INFO No activity for a while, heartbeating

I tried looking at the code and it appears the error is caused at line 218 NXBinary.read_frame() when it tries to read the variable length and a string is assigned to it instead of an integer.

length = self.read(1)[0]

After that the code recovers and reconnects but no data stream ever arrives, even if I wait a bit.

This is very strange because it only happens when I run the server inside the docker container. I tried running it on the command line and I never got the error: on the contrary the server receives data from the NX module and I get the proper status of the module.

I will attach my docker-compose.py for your reference. FYI I have made a few changes on the entrypoint.sh in order to be able to pass nx584_server arguments such as config file in the container.

I have the NX590e (might not be relevant but I mention it), hence I can only run the nx584_server in binary mode and thus I need the config file in the docker container before running it.

tzavellas commented 1 year ago

.docker/entrypoint.sh

#!/bin/bash
args=()

if [ ! -z "$SERIAL" ]; then
    args+=(--serial $SERIAL)
fi

if [ ! -z "$BAUD" ]; then
    args+=(--baud $BAUD)
fi

if [ ! -z "$CONNECT" ]; then
    args+=(--connect $CONNECT)
fi

if [ ! -z "$CONFIG" ]; then
    args+=(--config $CONFIG)
fi

if [ ! -z "$LOG" ]; then
    args+=(--log $LOG)
    cat /dev/null > $LOG
fi

if [ ! -z "$DEBUG" ]; then
    args+=(--debug --debug-log $DEBUG)
    cat /dev/null > $DEBUG
fi

echo "Server args ${args[@]}"

nx584_server --listen $LISTEN "${args[@]}"
tzavellas commented 1 year ago

docker-compose.yml

version: "3.2"

services:
  pynx584:
    container_name: pynx584
    image: kk7ds/pynx584
    # Uncomment to expose tty device in container 
    #devices:
    #  - "/dev/ttyS0:/dev/ttyS0"
    build:
      context: .docker
      dockerfile: Dockerfile
    restart: unless-stopped
    ports:
      - 5007:5007
    environment:
      # Uncomment these as needed, depending on how you connect to the panel (via Serial or TCP Socket)
      # - SERIAL=/dev/ttyS0
      # - BAUD=38400
      - CONNECT=192.168.1.167:9997
      # Uncomment as needed, depending on the location of the config file
      - CONFIG=/app/config.ini
      # - DEBUG=/app/debug.log
      - LOG=/app/log
      - PUID=1000
      - PGID=1000
      - UMASK=007
    network_mode: bridge
    working_dir: /app
    volumes:
      - ./:/app
tzavellas commented 1 year ago

config.ini

[config]
# max_zone is the highest numbered zone you have populated
max_zone = 13

# Disable zone name updates from NX8 system. If your system doesn't set zone
# names and you prefer define them through pynx584, set this value to False.
# Defaults to True
zone_name_update = False

# Set to true if your unit sends DD/MM dates instead of MM/DD
#euro_date_format = True

# Set To true if using binary protocol
# Defaults to False
use_binary_protocol = True

# Length of idle time before sending heartbeat keep alive
# (This is useful with the NX590 as it disconnects idle connections in a
# short period of time)
# Defaults to 120 seconds
idle_time_heartbeat_seconds = 30

[email]
fromaddr = XYZ@gmail.com
smtphost = smtp.gmail.com

[zones]
# Zone names
1 = Front Door
2 = Office
3 = Main Bedroom
4 = Kitchen
5 = Living Room
6 = Bedroom 1
7 = Bedroom 2
8 = Fire Alarm
9 = Main Balcony
10= Other Balcony
11= Tamper Main Balcony
12= Tamper Other Balcony
13= Siren
kk7ds commented 1 year ago

length = self.read(1)[0]

This looks like maybe a latent bug, but I'd probably need to be able to reproduce it to tell. I imagine its because read returns a bytes and a single-element of a bytes is an int (but used to be a string in python2). Although then it should complain about concat'ing a bytes to a str. Maybe change it to self.read(1)[0:1] and see what happens?

This is very strange because it only happens when I run the server inside the docker container. I tried running it on the command line and I never got the error: on the contrary the server receives data from the NX module and I get the proper status of the module.

Surely you're not running python2 in the docker container (or outside) right? That might explain something. The only other thing I can think of is you're using the NX584 binary protocol in one place and ascii one in the other and they're running different code in the communication routines.

tzavellas commented 1 year ago

Surely you're not running python2 in the docker container (or outside) right?

Well.. I am running python2 in the container (I think). I use your .docker file directly and its contents are:

FROM python:2.7

ENV LISTEN=0.0.0.0

RUN pip install --no-cache-dir pynx584

ADD entrypoint.sh /usr/local/bin/entrypoint.sh

EXPOSE 5007

ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]

Should I change this to FROM python:3 ?

tzavellas commented 1 year ago

I changed the FROM directive in the Docker file as above and I no longer get the error. However, after accepting the initial status of the zones from the NX590e, I don't see any updates triggered in the logs. Do you think it's configuration of the NX590e or source code related?

kk7ds commented 1 year ago

Ah, that was contributed by a user, I've never run it myself. It definitely shouldn't be running on python2 anymore.

And yep, you need to configure the panel to send events to the serial device, otherwise it just responds to queries.