petzval/btferret

Broadcast data and Listen for data at the same time (mesh)

Closed this issue · 14 comments

Hi petzval, I am trying to make a mesh from 3 Raspberry Pis. One node will broadcast data to the two other nodes, this part works, but at the same time, I want them to also listen to the other Raspberry Pis for data. However, I am having a problem with the latter. For example, when the mesh server starts listening in raspi A, I tried to send data to other raspi but there is an error like this.

Initialising...
Bluez down failed
Bind failed
HCI socket ERROR - no Bluetooth?

Is it possible to make the node broadcast data and listen for data from the other nodes at the same time? If possible, How can I do it? I'm sorry I am a beginner at this topic. Thank you so much!

Another issue I am facing right now is I tried to code the MESH BROADCASTER but when I try to run it, I cannot receive the data that it sends to other nodes. This is my code:

#include <stdio.h>
#include <stdlib.h>
#include "btlib.h"

int main()
  {
  if(init_blue("devices.txt") == 0)
    return(0);
  
  char buf[4];

  buf[0] = 0x12;
  buf[1] = 0x34;
   // broadcast two-byte mesh packet
  write_mesh(buf,2);
   // broadcast D disconnect command
  write_mesh("D",1);
  return(0);
  }

I've checked the code and the mesh packet repeat rate should be about 3 per second, so a one second delay should be OK. For hackers, this rate is set in btlib.c - leadparam[32] around line 532. This sets the rate to 0200 (multiplied by 0.625ms = 320ms).

  1. The broadcasting is done via mesh packets. So, Node 1 uses the mesh broadcasting code with write_mesh on it. Then, 2 and 3 were able to receive it since it is running the mesh server code.

  2. Yes, I also want node 1 to listen for data from 2 and 3. So, I also tried running the mesh server code in node 1 and it runs without error. Now, nodes 1,2, and 3 are listening for data. But when I try to run the mesh broadcasting code with sudo in node 1 or in any node, the error above still came out. Is this logic possible?

  3. I saw sample.c code but do you think number 2 can be used instead? So every node (1&2&3) is listening (mesh server running). Then, if I want to send data from 1 to 2 and 3, or 2 to 1 and 3, or 3 to 1 and 2, I will just run the mesh broadcasting code to send the data. Is this likely to be achieved?

The other issue is now working! It needed the delay for it to work. Thank you so much for your assistance. I appreciate it.

If all devices are mesh servers, they are all listening for a mesh packet - so there is no way to initiate a process. Something
has to take charge and send an initial mesh packet. Node 1 could tell 2 and 3 to connect and exchange data for example. But you could construct your own mesh server using read_mesh - then because you have written the listening code it can now initiate a process and all devices can be servers, and any pair can decide to exchange data.
Here's how to return data from 2 to 1 (but 3 will also receive the reply). This same code runs on all devices.

#include <stdio.h>
#include <stdlib.h>
#include "btlib.h"
#include <unistd.h>
#include <string.h>

int callback(int clientnode,unsigned char *dat,int len);

int main()
  {
  int node;
  char buf[32];
  
  if(init_blue("devices.txt") == 0)
    {
    printf("FAIL\n");
    return(0);
    }


 if(localnode() == 1)
   {  
    buf[0] = 0x12;
    buf[1] = 0x34;  
    write_mesh(buf,2);
    sleep(1);
      // wait 3 seconds for reply
    if(read_mesh(&node,buf,32,EXIT_TIMEOUT,3000) != 0)
      printf("GOT reply from node %d = %s\n",node,buf);
    sleep(5);
    write_mesh("D",1);     
    sleep(1);
    }
  else
   {
   mesh_server(callback);
   }
     
  close_all();
  
  return(0);
  }

int callback(int clientnode,unsigned char *dat,int len)
  {
  int n;
  char buf[32];
  
  if(dat[0] == 0x12)
    {
    sprintf(buf,"OK from %d",localnode());
    write_mesh(buf,strlen(buf));
    }
  if(dat[0] == 'D')
    return(SERVER_EXIT);
  return(SERVER_CONTINUE);
  }

Thank you for that and I will try that one. But what I did in my setup is I ran the mesh server code in the terminal for all the pis. Then, if I try to run the mesh broadcasting code in any of the pis while the mesh server code is listening, it won't run. These errors came out.

Initialising...
Bluez down failed
Bind failed
HCI socket ERROR - no Bluetooth?

Is there a fix for this? Could I run the two codes simultaneously in a separate terminal? or this setup cannot be done?

It sounds like you might be running init_blue twice - this will trigger those errors. It only needs to be run once on program entry.

I tried removing it on the mesh broadcasting code but it throws a segmentation fault error. Do you think that is possible?

I haven't understood the set up. If all the Pis are running as mesh servers (mesh_server has been called and has not returned) how is it possible to run the mesh broadcaster code? - mesh_server has tied up all the devices waiting for packets.

I will implement this in python since I am not familiar with C and I am thinking that it could use multi threading so that it can run the mesh server thread and for example every 5 second the mesh broadcasting thread will be executed. But I am not sure if that is possible.

OK, it is not possible to run two programs at the same time. The code monopolises the Bluetooth adapter and nothing else can use it - including another thread. It is easy to have a mesh server running and execute other code every 5 seconds. You just need your own custom version of mesh_server as follows.

void my_mesh_server(int(*callback)())
  {
  int nread,retval,clientnode;
  char buf[32];

  mesh_on(); 
 
  printf("Mesh server listening (x=stop)\n");
  do
    {
    nread = read_mesh(&clientnode,buf,32,EXIT_TIMEOUT | EXIT_KEY,5000);
    if(read_error() == ERROR_KEY)
      retval = SERVER_EXIT;
    else if(nread > 0)
      {
      retval = (*callback)(clientnode,buf,nread);
      }
    else
      {
      printf("5 seconds\n");
      // 5 second code here
      retval = SERVER_CONTINUE;
      }
    }
  while(retval == SERVER_CONTINUE);
  }

Thank you so much for that!

Hello Sir, I tried using multithreading with python and it worked! I can send and receive simultaneously. Thank you for your repository! God bless you!

I'm surprised, but that's useful information. Thanks.