Reconnecting radio dongle results disables connections

I have several LCD modules connected to a Node Red flow via a radio dongle to receive MQTT messages.
When my modules are connected and I disconnect and reconnect the radio dongle the modules stop receiving MQTT messages. When I connect the modules via USB cable they start receiving messages again. How can I prevent that I have to restore the connection with a USB cable after reconnecting the radio dongle? Also this option of restoring the connection via usb cable is not always working.

Worse case is when NodeRed is run on the Raspberry hub and I use the remote NodeRed web interface the USB connection is not recognised and I don’t have all functions available to restore the connection.

My code is in https://github.com/robertrongen/bcf-lcd-qrcode.

Hello Robert,

I’ve responded on the same question over email on tuesday.

Answer:
Radio Dongle is able to recover custom topics if the node is sending some message. For example in our code we report temperature every 10 minutes. When Radio Dongle receives the temperature and realizes that this is the first message after power-reset and it asks node to re-send its custom MQTT topics.

Hello Martin,

I have not reported this problem earlier, maybe I have not explained it clearly.

All works well when I initially pair an LCD module to a Radio Dongle.
However when I disconnect the Radio Dongle and then reconnect the Radio Dongle the LCD module doesn’t receive any messages anymore.
The only solution that always works is that I have to flash the stock firmware, then my custom firmware and pair the module again.
How can I assure that the modules keep receiving messages after reconnecting the Radio Dongle?

I tried to re-initialize the connection between the dongle and the module by transmitting the battery level. The module transmits the battery level on three events:

  1. Power up
  2. Press button
  3. Battery level event

When I re-connect the Radio Dongle he receives the battery level immediately (as after the power-reset you mentioned), also when I press one of the buttons.

However the module still does not receive any message from the Radio Dongle (in specific the QR Code input that the module needs to receive).

Hi, I’ll take a look at your code later today and test the Radio Dongle disconnect event.
If you have any uncommited changes in your repository, please commit them so I could use the exact code you have.
Martin

Regarding the batteries. When you use BC_RADIO_MODE_NODE_LISTENING then the radio is turned on all time on for listening consuming more than 10mA. This is not suggested to be used with batteries.

More detailed explanation and option to make it more battery friendly are explained here https://developers.hardwario.com/interfaces/sub-ghz-radio#low-power-radio-communication

So if you do not need instant QR code update you can initiate update from the node (by some periodic message let’s say every minute) and use SDK to keep LISTEN mode turn of for few hundred milliseconds so your backend can send new QR code.

I’ve tested the code and it works fine.
Here is the way I’ve tested it.

I’ve used dongle with latest firmware v1.13.0

What is the required update period of QR code, is it few minutes, or is it ok to be updated by button press? Then I could also improve the power consumption but I would need more information so I could help you.

I’m on holidays the whole next week but don’t worry, someone else will help you here, but it would be best to know and fix the code by me this week because I’ve most familiar with it right now.

Ok, thanks, I will start testing it on my side

Still doesn’t work on my side.
When I flash the firmware the module only receives messages in the BC_RADIO_MODE_NODE_LISTENING mode.
When I reconnect the dongle it doesn’t activate after button press.

In BC_RADIO_MODE_NODE_SLEEPING mode no messages are received, even not after button press…

To be sure, I use these versions:

  • Dongle runs V1.13.0.
  • Playground V1.2.0.
  • LCD module R2.3.
  • Core module R2.4
  • Battery module R1.4

I’ve updated my Github, NodeRed flow is in the \flow folder.

Regarding the dongle, are you using Playground or Raspberry Pi?
For Rpi you have to reboot it - reconnecting might not work.

If you use anything else than BC_RADIO_MODE_NODE_LISTENING then you need to add more logic to your flow.
You also have to call bc_radio_set_rx_timeout_for_sleeping_node with value in milliseconds which says how long the node will listen on radio after the message is sent.

Then in node-red you need to create some logic which:

  • receives the battery/temperature packet which is send from node every N minutes node/bcf-qr-code:0/battery/-/voltage
  • creates new order_number
  • sends the new order number using mqtt topic node/bcf-qr-code:0/blokko/order/qr/0 to the node until the timeout from bc_radio_set_rx_timeout_for_sleeping_node expires.

Please answer these important questions:

  • What/who triggers the QR code change?
  • Is it based on time, button press or some event?
  • In case of time is the trigger, how often the QR code is replaced?
  • Does the QR code on LCD Module need to be changed immediatelly after the trigger event occurs or could it be updated in a let’s say few seconds (5-15)?

In code for embedded device is not recommended to use dynamic memory allocation. You use function calloc which needs also related free function to release the memory.
The way the code is right now it is constantly allocating memory with every orderID update and after some time the MCU code crashes of low memory.

I would suggest to use completely static strings

(i’ve commented out your previous code in the code below)
Define static variables in teh begining of the file

//char *qr_text = "";
char qr_text[255];
char order_url[255];

This function now becomes simplier with snprintf.

void create_qr_text(const char *container, const char *order) 
{
    snprintf(qr_text, sizeof(qr_text), "Blokko CTR%s, SO: %s", container, order);
    /*const char *container_text= "Blokko CTR";
    char *container_number = (char*)container;
    const char *order_text=", SO: ";
    char *order_number = (char*)order;
    //qr_text = calloc(strlen(container_text) + strlen(container_number) + strlen(order_text) + strlen(order_number) + 1, sizeof(char));
    strncpy(qr_text, container_text, sizeof(buffer));
    strncat(qr_text, container_number, sizeof(buffer));
    strncat(qr_text, order_text, sizeof(buffer));
    strncat(qr_text, order_number, sizeof(buffer));*/
}

Again, calloc could be removed here:

void bc_change_qr_value(uint64_t *id, const char *topic, void *value, void *param)
{
    bc_log_info("bc_change_qr_value triggered.");

    bc_led_pulse(&led_lcd_blue, 2000);
/*
   const char *url="http://blokko.blockchainadvies.nu/receive-order.html?order=";
    char *orderId = (char*)value;
    char *order_url = calloc(strlen(orderIdUrl) + strlen(url) + 1, sizeof(char));
    strcat(order_url, url);
    strcat(order_url, orderId);
*/
    snprintf(order_url, sizeof(order_url), "http://blokko.blockchainadvies.nu/receive-order.html?order=%s", (char*)value);

    bc_log_info("New URL set to %s.", order_url);
    
    create_qr_text(container_id, (char*)value);

    qrcode_project(order_url, qr_text);
}

I’ve created another improvement and video which might help you conserve battery life.

First I’ve set node to sleep with 500ms receive timeout

bc_radio_init(BC_RADIO_MODE_NODE_SLEEPING);
bc_radio_set_rx_timeout_for_sleeping_node(500);

Then to wake-up the module I need to send beacon every 10 seconds, so I’ve added this periodic function (application_task is called internally, no need to call it from anywhere)

void application_task()
{
    bool parameter = true;
    bc_radio_pub_bool("update_request", &parameter);

    // increase when more nodes will be connected!
    bc_scheduler_plan_current_relative(10000);
}

Then I’ve created this flow which will be triggered by MQTT message update_request , then the message is created with latest orderID and immediatelly send to the node until the 500ms receive timeout window closes.

Import to node-red

[{"id":"c49c9358.c5d8f","type":"inject","z":"2c41a2bd.aa36ae","name":"","topic":"node/bcf-qr-code:0/blokko/order/qr/0","payload":"\"000\"","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":350,"y":180,"wires":[["4b14d3ab.83af1c"]]},{"id":"9eb8c94d.85d638","type":"mqtt out","z":"2c41a2bd.aa36ae","name":"","topic":"node/bcf-qr-code:0/blokko/order/qr/0","qos":"","retain":"","broker":"29fba84a.b2af58","x":910,"y":360,"wires":[]},{"id":"2b238f66.d486e","type":"inject","z":"2c41a2bd.aa36ae","name":"","topic":"node/bcf-qr-code:0/blokko/order/qr/0","payload":"\"123\"","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":350,"y":220,"wires":[["4b14d3ab.83af1c"]]},{"id":"a8ad18d8.04a868","type":"mqtt in","z":"2c41a2bd.aa36ae","name":"","topic":"node/bcf-qr-code:0/update_request","qos":"2","datatype":"auto","broker":"29fba84a.b2af58","x":300,"y":360,"wires":[["2d61e655.003d1a"]]},{"id":"4b14d3ab.83af1c","type":"change","z":"2c41a2bd.aa36ae","name":"","rules":[{"t":"set","p":"orderId","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":610,"y":200,"wires":[[]]},{"id":"2d61e655.003d1a","type":"change","z":"2c41a2bd.aa36ae","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"orderId","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":610,"y":360,"wires":[["9eb8c94d.85d638"]]},{"id":"e6748dc.13b8a7","type":"mqtt in","z":"2c41a2bd.aa36ae","name":"","topic":"node/bcf-qr-code:0/battery/-/voltage","qos":"2","datatype":"auto","broker":"29fba84a.b2af58","x":300,"y":440,"wires":[[]]},{"id":"29fba84a.b2af58","type":"mqtt-broker","z":"","broker":"127.0.0.1","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","willTopic":"","willQos":"0","willPayload":""}]

I’ve also noticed that after node-red Deploy I always see messages node/bcf-qr-code:0/blokko/order/qr/0. Not sure why they are started to appear after I imported your flow. It could be maybe because he messages were “retained”. You don’t need retained messages in case you was using them.

  • What/who triggers the QR code change?
    manual entry in a form on a web page which sends orderID and LCD Module ID to MQTT

  • Is it based on time, button press or some event?
    button press on website

  • In case of time is the trigger, how often the QR code is replaced?
    not applicable, probably every 1 to 5 minutes a new order is ready and a QR code needs to be displayed on one of the 10 displays

  • Does the QR code on LCD Module need to be changed immediatelly after the trigger event occurs or could it be updated in a let’s say few seconds (5-15)?
    most user friendly will be immediately but some delay is plausible. Students are preparing an order, place the order in a container and use the website interface to send the ID to the LCD module on the container which has to display the corresponding QR Code (which has the order ID in the URL)

Thanks for answers. It seems like it would be possible to use the sleep mode and rx_timeout.
It could work if the LCD node request is send every 5 seconds but needs to be tested in practice.

I’ll leave you to test my suggestions and let me know how it worked for you.

Regarding the Dongle - you have to reset Rpi, not disconnecting Dongle

are you using Playground or Raspberry Pi?
For Rpi you have to reboot it - reconnecting might not work.

The video and code are very helpfull, I got the battery saving part working!
Only remaining issue seems to be reconnecting the radio dongle.
The messages from the module are received periodically and after button press but no message arrives at the module (see picture). I’ve updated the github repository.

I’m testing now from my Windows machine but next week we will use the RPi.
In the RPi the module automatically reconnects after I unplug and replug the Dongle.
So the problem seems to be isolated to the Windows Playground.

In case of Playground this is a normal behavior - after connecting the Radio Dongle do USB you always have to go to the Devices tab and press Connect button. Is this what you meant by “reconnection is not working”? There is no automatic reconnection in Playground.

In bc-raspbian we added automatic raconnection because Rpi does not have any UI and most probably the Radio Dongle will be the only device connected to it.

In my videos I’ve showed you that I clicked on that button. I thought that you are refering to some other issue.

So could I take this thread as a solved?

With reconnect I mean connect the dongle to the USB port AND press connect button in Playground.
Also first disconnect the dongle in Playground and then press connect.

So in Windows the module is able to send messages after reconnect but does not receive messages anymore.

The only way to resolve it is to remove the device in Playground, remove the batteries form the module and start the pairing process.

I tested this with all other USB devices removed with the same result. I also don’t see conflicts with usb ports in the windows device manager .

I’ll test Playground 1.2.0 on Windows and try to reproduce that.

1 Like

Seem like that reconnection that forgets custom MQTT topics is a bug. It has issues on Windows 10. I use Ubuntu and there it is working fine.

I’ve tested that behavior also older Playground v1.1.0 and it has this bug too. I’ll report it and we’ll fix that in new build. So if you use Raspberry Pi as a hub or other Linux PC/Laptop, it should work ok.

Ok, we’re lucky then that we also ordered the RPi :sweat_smile: