jgillula / rpi-rfm69

Python RFM69 library for Raspberry Pi
GNU General Public License v3.0
31 stars 20 forks source link

Script hanging with 0.4.0 release #13

Open grote opened 3 years ago

grote commented 3 years ago

This is not a qualified bug report as I didn't have much time with debugging, but I tried all sorts of ways of using version 0.4.0 of this library and when I get lots of messages over MQTT (paho-mqtt) which cause lots of sends and responses from my nodes, the script hangs somewhere. Maybe related to the new thread-safety.

The only solution I found so far is going back to the 0.3.0 version which so far works fine. Sorry for not being able to provide more info, but I thought I'd let you know.

jgillula commented 2 years ago

Thanks! Any chance you could share the code so I could try to dive in myself?

grote commented 2 years ago

Here's the main script (without node classes) that hopefully is sufficient to find the issue:

#!/usr/bin/env python3

import asyncio
import logging
import os
import time

import paho.mqtt.client as mqtt
from RFM69 import Radio, FREQ_915MHZ

mqtt.Client._call_socket_register_write = lambda _self: None
mqtt.Client._call_socket_unregister_write = lambda _self, _sock=None: None

FORMAT = '%(asctime)s %(name)s:%(levelname)s: %(message)s'
logging.basicConfig(level=os.environ.get("LOGLEVEL", "INFO"), format=FORMAT)
mqttc = mqtt.Client(client_id="Gateway", clean_session=False)
radio = Radio(FREQ_915MHZ, nodeID=0, networkID=42, auto_acknowledge=True, isHighPower=False,
              interruptPin=22, resetPin=29, verbose=True)
topics = {}
sender_ids = {}

def main():
    mqttc.on_connect = on_connect
    mqttc.on_message = on_message
    mqttc.on_disconnect = on_disconnect
    mqttc.on_log = on_log
    mqttc.connect("127.0.0.1")
    mqttc.loop_start()

    loop = asyncio.get_event_loop()
    loop.create_task(receiver(radio))
    loop.run_forever()

    loop.close()

async def receiver(radio):
    while True:
        for packet in radio.get_packets():
            if packet.sender in sender_ids:
                await sender_ids[packet.sender].on_radio_message(packet)
            else:
                logging.warning("Received data from unknown sender: %s" % str(packet.data))
        await asyncio.sleep(0.1)

def on_message(client, userdata, message):
    logging.info("Received message '" + message.payload.decode() + "' on topic '" + message.topic +
                 "' with QoS " + str(message.qos))
    if message.topic in topics:
        topics[message.topic].on_mqtt_message(message)

def on_connect(client, userdata, flags, rc):
    logging.info("Connection returned result: " + str(rc))
    for topic in topics.keys():
        mqttc.subscribe(topic)

def on_disconnect(client, userdata, rc):
    if rc != 0:
        h.write("%s Unexpected disconnection." % h.get_time())

def on_log(client, userdata, level, buff):
    loggin.info(level + " " + buff)

if __name__ == "__main__":
    main()
jgillula commented 2 years ago

Do you know where the script hangs? I'm wondering if it's stuck in the call to radio.get_packets().

I fully admit that I didn't test how the thread-safety interacts with asyncio or coroutines, so I'll try to code up my own minimal test case and see how it works.