-
Notifications
You must be signed in to change notification settings - Fork 152
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RF24Mesh mesh.read() package size in python #184
Comments
Sorry for the late reply. header_in, msg_in = network.read()
size_of_received_payload = len(msg_in) + 8 # +8 bytes for the header The same technique could be used for outgoing payloads also. The only time I've ever come across a usefulness of |
Thanks for getting back with me. I'm actually in a time crunching mode getting this communication construct working between my arduino nano and raspberry pi. Here is what I am dealing with right now. I am trying to pass a C++ struct from my arduino to my raspberry pi. I have a struct that looks like this: struct node_status
{
char *node_type = "incubator";
char *sub_type; // set the type of incubator
int sub_type_id;
bool sleep = false; // set to sleep
int check_in_time = 1000; // set check in time
bool LOCK = false; // set if admin control is true/false
} nodeStatus; I tried using the python module named struct from RF24 import *
from RF24Network import *
from RF24Mesh import *
import RPi.GPIO as GPIO
import threading
from time import sleep, time
from struct import pack,unpack
# radio setup for RPi B Rev2: CS0=Pin 24
radio = RF24(22,0);
network = RF24Network(radio)
mesh = RF24Mesh(radio, network)
# # GPIO.cleanup()
# # CE Pin, CSN Pin, SPI Speed
# radio = RF24(22,0)
# radio.setChannel(3)
# network = RF24Network(radio)
# mesh = RF24Mesh(radio, network)
mesh.setNodeID(0) #MasterNode
mesh.begin()
radio.setPALevel(RF24_PA_MAX) # Power Amplifier
radio.printDetails()
def millis():
return int((time()-start)*1000) % (2 ** 32)
def delay(ms):
ms = ms % (2**32)
sleep(ms/1000.0)
class RF24_Monitor(threading.Thread):
def __init__(self):
print('init')
def check_network(self):
mesh.update()
mesh.DHCP()
while network.available():
print('checking network')
header, payload = network.read(10)
nodeID = oct(header.from_node)
if chr(header.type) == 127:
print("Rcvd ERROR msg from 0{:o}".format(header.from_node))
print("ERROR: {}".format(unpack("s",payload[0]))) #ERROR
ERROR= unpack("s",payload[0])
elif chr(header.type) == 126:
print("Rcvd Node Status msg from 0{:o}".format(header.from_node))
print("node_type: {}".format(unpack("10s",payload[0]))) #node_type
node_type = unpack("10s",payload[0])
print("sub_type: {}".format(unpack("10s",payload[1]), header.from_node)) #sub_type
sub_type = unpack("10s",payload[1])
print("sub_type_id: {}".format(unpack("b",payload[2])))
sub_type_id = unpack("b",payload[2])
print("sleep: {}".format(unpack("?",payload)[3])) #sleep
sleep = unpack("?",payload[3])
print("check_in_time: {}".format(unpack("l",payload[4]))) #check_in_time
check_in_time = unpack("l",payload[4])
print("Lock: {}".format(unpack("?",payload[5]))) #LOCK
Lock = unpack("?",payload[5])
elif chr(header.type) == 111:
print("Rcvd COUNT msg from 0{:o}".format(header.from_node))
print("Count: {}".format(unpack("b",payload[0]))) #Count
Count = unpack("b",payload[0])
print("start: {}".format(unpack("?",payload[1]))) #start
start = unpack("?",payload[1])
print("end: {}".format(unpack("?",payload[2]))) #end
end = unpack("?",payload[2])
elif chr(header.type) == 2:
print("Rcvd DHT msg from 0{:o}".format(header.from_node))
print("Temperature: {}".format(unpack("f",payload[0]))) #Temperature
Temperature = unpack("f",payload[0])
print("Fahreneit: {}".format(unpack("?",payload[1]))) #TempUnit
TempUnit = unpack("?",payload[1])
print("Humidity: {}".format(unpack("f",payload[2]))) #Humidity
Humidity = unpack("f",payload[2])
elif chr(header.type) == 1:
print("Rcvd PIR msg from 0{:o}".format(header.from_node))
print("Triggered: {".format(unpack("?",payload[0]))) #Triggered
Triggered = unpack("?",payload[0])
print("Silent: {".format(unpack("?",payload[1]))) #Silent
Silent = unpack("?",payload[1])
else:
print("Rcv bad type {} from 0{:o}".format(header.type,header.from_node))
def run(self):
while True:
self.check_network()
############################################################
# Main Entry
############################################################
if __name__ == "__main__":
RF24_Monitor_Controller = RF24_Monitor()
RF24_Monitor_Controller.run() but I am not having much luck. I was even looking at just using ctypes module but seem to not be going anywhere.. from ctypes import *
class interpret_nodes_status(Structure):
_fields_ = [('node_type',c_char_p),
('sub_type',c_char_p),
('sub_type_id',c_int),
('sleep',c_bool),
(check_in_time',c_int),
('LOCK',c_bool)]
nodestatus = translate_nodes_status(payload) but that just gives me an error
|
Firstly, it's important that you make sure the c-string transmitted ends in a null terminating char ( example: struct node_status
{
char node_type[10] = "incubator";
char sub_type[10]; // set the type of incubator
int sub_type_id;
bool sleep = false; // set to sleep
int check_in_time = 1000; // set check in time
bool LOCK = false; // set if admin control is true/false
} nodeStatus; could be unpacked in python like import struct
# let `payload` be the received message
(
node_type,
sub_type,
sub_type_id,
sleep,
check_in_time,
LOCK,
) = struct.unpack("<10s10si?i?", payload) Last time I looked into BTW, to covert a python bytes_obj = bytes(payload) # where `payload` would be a bytearray |
@hansendm It would help to know the exact error that you're trying to troubleshoot. Because I don't know this info, I'm guessing that |
@TMRh20 I think I figured out the actual question being posed here. It would seem that the This should easily be solved (for best backward compatibility) by making the @hansendm Is this what you were originally trying to ask? ps - on the C++ side, RF24Network could also use a new method similar to |
@hansendm have you tried using head = RF24NetworkHeader()
msg_size = network.peek(head)
head, payload = network.read(msg_size) If this works, then my previous comment should be disregarded. I can't seem to test the python wrapper for RF24Network on RPi OS (using latest stable release) for python3 because I keep getting
|
Oh hey Brandon, THANK YOU so much for replying and trying to figure this out. And yes, that was what I was originally trying to ask. We must be on different time zones, else I would have answered immediately. I was successful at using the latest stable release but I had to install the individual libraries in order of RF24, RF24Network, and then RF24Mesh. It was then a bit more complicated getting the SPI fully enabled. So, the struct would have string variables (node_type and sub_type) that I had made to length 10 bytes. The sub_type would vary ('chicken','turkey','quail','peacock', etc.). Are you saying that before I send out the message with the struct I need to add char ('\0') at the end of each string variable inside the struct? This is my code now: ////////////////////////////////////////////////////////////////////////////
// structure for current node status
struct node_status
{
char *node_type = "incubator";
char *sub_type; // set the type of incubator
int sub_type_id;
bool sleep = false; // set to sleep
int check_in_time = 1000; // set check in time
bool LOCK = false; // set if admin control is true/false
} nodeStatus;
// Payload from MASTER
struct MASTER_node_command
{
char *sub_type; // set the type of incubator
bool sleep = false; // set to sleep
int check_in_time = 10000; // set check in time
bool LOCK = false; // set if admin control is true/false
} MasterCommand;
/**
temp and humidity control points
*/
struct chicken_config
{
char *node_type = "incubator";
char *sub_type = "chicken"; // set the type of incubator
int sub_type_id = 1;
int hot = 102; //set hot parameter
float optimum_temp = 99.5; // set optimum_temp temp to go to b4 turning off
float cold = 89.9; //set cold parameter
int high_hum = 65; //set high humidity parameter
int optimum_hum = 60; // set optimum humidity parameter to go to b4 turning off
int low_hum = 55; // set low humidity parameter
} chickenConfig;
struct turkey_config
{
char *node_type = "incubator";
char *sub_type = "turkey"; // set the type of incubator
int sub_type_id = 2;
int hot = 102; //set hot parameter
float optimum_temp = 99.5; // set optimum_temp temp to go to b4 turning off
float cold = 89.9; //set cold parameter
int high_hum = 65; //set high humidity parameter
int optimum_hum = 60; // set optimum humidity parameter to go to b4 turning off
int low_hum = 55; // set low humidity parameter
} turkeyConfig;
struct peacock_config
{
char *node_type = "incubator";
char *sub_type = "peacock"; // set the type of incubator
int sub_type_id = 3;
int hot = 101; //set hot parameter
float optimum_temp = 99.5; // set optimum_temp temp to go to b4 turning off
float cold = 98.9; //set cold parameter
int high_hum = 65; //set high humidity parameter
int optimum_hum = 60; // set optimum humidity parameter to go to b4 turning off
int low_hum = 55; // set low humidity parameter
} peacockConfig;
struct chameleon_config
{
char *node_type = "incubator";
char *sub_type = "chameleon"; // set the type of incubator
int sub_type_id = 4;
int hot = 81; //set hot parameter
float optimum_temp = 77.5; // set optimum_temp temp to go to b4 turning off
float cold = 76.5; //set cold parameter
int high_hum = 95; //set high humidity parameter
int optimum_hum = 85; // set optimum humidity parameter to go to b4 turning off
int low_hum = 75; // set low humidity parameter
} chameleonConfig;
// structure for current incubator configuration
struct current_config
{
char *node_type = "incubator";
char *sub_type; // set the type of incubator
int sub_type_id;
int hot; //set hot parameter
float optimum_temp; // set optimum_temp temp to go to b4 turning off
float cold; //set cold parameter
int high_hum; //set high humidity parameter
int optimum_hum; // set optimum humidity parameter to go to b4 turning off
int low_hum; // set low humidity parameter
} currentConfig;
////////////////////////////////////////////////////////////////////////////////////
// setup directed sub-type
void switch_sub_type(int sub_type)
{
switch (sub_type)
{
// assign the bird type params
case 1:
currentConfig.sub_type = chickenConfig.sub_type;
currentConfig.sub_type_id = chickenConfig.sub_type_id;
currentConfig.hot = chickenConfig.hot;
currentConfig.optimum_temp = chickenConfig.optimum_temp;
currentConfig.cold = chickenConfig.cold;
currentConfig.high_hum = chickenConfig.high_hum;
currentConfig.optimum_hum = chickenConfig.optimum_hum;
currentConfig.low_hum = chickenConfig.low_hum;
break;
case 2:
currentConfig.sub_type = turkeyConfig.sub_type;
currentConfig.sub_type_id = turkeyConfig.sub_type_id;
currentConfig.hot = turkeyConfig.hot;
currentConfig.optimum_temp = turkeyConfig.optimum_temp;
currentConfig.cold = turkeyConfig.cold;
currentConfig.high_hum = turkeyConfig.high_hum;
currentConfig.optimum_hum = turkeyConfig.optimum_hum;
currentConfig.low_hum = turkeyConfig.low_hum;
break;
case 3:
currentConfig.sub_type = peacockConfig.sub_type;
currentConfig.sub_type_id = peacockConfig.sub_type_id;
currentConfig.hot = peacockConfig.hot;
currentConfig.optimum_temp = peacockConfig.optimum_temp;
currentConfig.cold = peacockConfig.cold;
currentConfig.high_hum = peacockConfig.high_hum;
currentConfig.optimum_hum = peacockConfig.optimum_hum;
currentConfig.low_hum = peacockConfig.low_hum;
break;
case 4:
currentConfig.sub_type = chameleonConfig.sub_type;
currentConfig.sub_type_id = chameleonConfig.sub_type_id;
currentConfig.hot = chameleonConfig.hot;
currentConfig.optimum_temp = chameleonConfig.optimum_temp;
currentConfig.cold = chameleonConfig.cold;
currentConfig.high_hum = chameleonConfig.high_hum;
currentConfig.optimum_hum = chameleonConfig.optimum_hum;
currentConfig.low_hum = chameleonConfig.low_hum;
break;
}
return;
}
bool send_node_status()
{
nodeStatus.sub_type = currentConfig.sub_type;
nodeStatus.sub_type_id = currentConfig.sub_type_id;
nodeStatus.sleep = MasterCommand.sleep;
nodeStatus.check_in_time = MasterCommand.check_in_time;
nodeStatus.LOCK = MasterCommand.LOCK;
RF24NetworkHeader header();
if (!mesh.write(&nodeStatus, /*type*/ 126, sizeof(nodeStatus), /*to node*/ 000))
{ // Send the data
if ( !mesh.checkConnection() )
{
Serial.println("Renewing Address");
mesh.renewAddress();
}
}
else
{
Serial.println("node status msg Sent");
return;
} Now, you're saying that I would have to change it to be like this: bool send_node_status()
{
nodeStatus.sub_type = currentConfig.sub_type +char ('\0');
nodeStatus.sub_type_id = currentConfig.sub_type_id +char ('\0');
nodeStatus.sleep = MasterCommand.sleep;
nodeStatus.check_in_time = MasterCommand.check_in_time;
nodeStatus.LOCK = MasterCommand.LOCK;
RF24NetworkHeader header();
if (!mesh.write(&nodeStatus, /*type*/ 126, sizeof(nodeStatus), /*to node*/ 000))
{ // Send the data
if ( !mesh.checkConnection() )
{
Serial.println("Renewing Address");
mesh.renewAddress();
}
}
else
{
Serial.println("node status msg Sent");
return;
} And on the python side I could use: import struct
head = RF24NetworkHeader()
msg_size = network.peek(head)
head, payload = network.read(msg_size)
# let `payload` be the received message
(
node_type,
sub_type,
sub_type_id,
sleep,
check_in_time,
LOCK,
) = struct.unpack("<10s10si?i?", payload) Is that correct? would the '<10s' formatting still work for the sub_type even though I may technically have different word lengths, like I mentioned before? I mean, I did set that variable length to be 10. |
BTW my full code is located at https://github.com/hansendm/DANA and I'm using the comms_test.py for the raspi side to figure this out. I hope that you can try my code out and maybe have some success. |
Just added my Node001 code. |
from the python docs about packing/unpacking
your I'm also interested in the actual error messages you're trying to resolve. |
|
I thought that was from the |
That was coming from the node_status interpreter on the python side whenever it got to
|
Actually...you might be right..I'm at work right now. So I can't verify whether I was getting the same message. I know I had multiple error messages depending on what changes I made to figure things out. I think I was having an error stating something about needing the correct byte length. |
oh, that's because |
you have to be kidding me.. so I would have done something like payload[0:10] ? |
yep. |
and that would be enough for the I'm still learning all of this. |
But I wouldn't have to worry about that if I were to break down the payloads like you mentioned?
|
yeah, I figured.
exactly why I posted the code like that |
You're awesome! I will test this out when I get home. |
But wait..you said I have to make the lengths of the subt_type string length equal to being 10.. would that mean I have to do something like:
|
Let me know how the I'm currently porting this lib to pure python (literally testing it now). We are definitely in different time zones (I should have gone to sleep a few hours ago). |
BTW the zeroes in |
I've been in AF and S.K. . I know how that can be. I will let you know about the Ok but you are saying that I have to fill up the strings to their max size? Then remove those characters on the python side? |
yes
I think |
If this works I'm sponsoring you |
did a quick test in python3 REPL: >>> b = b'turkey\0\0\0\0'
>>> struct.unpack("<10s", b)[0]
b'turkey\x00\x00\x00\x00'
>>> struct.unpack("<10s", b)[0].decode()
'turkey\x00\x00\x00\x00' looks like you have to remove the null bytes on the receiving end. |
Interesting, I did not think about using |
it converts UTF-8 encoded buffers to a |
tip: >>> 'turkey\x00\x00\x00\x00'.rstrip('\0')
'turkey' |
b.E.a.utiful. |
Hey, Sorry it took so long but I had to do a lot of doubles at work. It seems that |
Hey Brendan @2bndy5 ,
It seems that peek did not work. Any ideas on a work around?
Very Respectfully,
Daniel Hansen
|
Pass 144 to dir(network) # where `network` is the instantiated RF24Network object There is a couple |
it is saying when it comes to
Now, to be clear, I removed the
and instead placed
|
This is the peek() function that should exist. It should return the message size that can be used. If you run Unfortunately, it looks like Until we get a fix for this (which means I have to get the python wrapper working on my RPi), you'll have to slice the payload to only the length that # get the max sized payload despite what was actually received
head, payload = network.read(144)
# unpack 30 bytes
(
node_type,
sub_type,
sub_type_id,
sleep,
check_in_time,
LOCK,
) = struct.unpack("<10s10si?i?", payload[:30]) Alternatively, you could pass a number that would be the max sized payload that any of your network nodes transmit, but you still need to slice the payload to only what |
Unfortunately, it is still giving the same error. |
I tried
and that printed 18. Is this due to fracturing that you mentioned before? This is the message I'm sending:
when I
I get
and I printed |
I've said this before:
I see that you're still using As for the small payload size, I'm can"t say why that is without more context. |
I tried but then again I've never used that before. I kept getting an error. You are saying this is how it should look like?
|
yep. this is how I use c-strings in the RF24 lib's AckPayload examples If you're getting an error about the number in the square brackets while declaring the variable with a initial value, then you can leave out the number and just use char node_type[] = "incubator"; // has to be a 9 char string to allocate 10 bytes |
@hansendm I finally got the RF24Network python wrapper working! I had to link the librf24.so to the extension module (via setup.py). I can confirm that the RF24Network class has a (env) pi@rpi4:~/github/RF24Network/RPi/pyRF24Network $ python
Python 3.7.3 (default, Jan 22 2021, 20:04:44)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import RF24
>>> import RF24Network
>>> radio = RF24.RF24(22, 0)
>>> network = RF24Network.RF24Network(radio)
>>> "peek" in dir(network)
True
>>> help(network.peek)
Help on method peek in module RF24Network:
peek(...) method of RF24Network.RF24Network instance
peek( (RF24Network)arg1, (RF24NetworkHeader)header) -> int :
C++ signature :
unsigned short peek(RF24Network {lvalue},RF24NetworkHeader {lvalue})
peek( (RF24Network)arg1, (int)maxlen) -> tuple :
C++ signature :
boost::python::tuple peek(RF24Network {lvalue},unsigned int) press |
It worked! I had to get rid of the sub_type and just depend on the sub_type_id due to not being able to assign the
It seems that variable was blank after trying to add [10] to all of the variables. Other times it gave me an incompatible issue. |
Do you want to keep this issue open until the modifications of making the |
Awesome that you figured it out. Alternatively, I should've suggested a "coded" identifying number to replace the strings; meaning send the number
Nah. I will tag you in the release that follows the resolution of that issue. BTW, you can also keep the dialogue going after the issue is closed. |
I essentially did that with the sub_type_id. Thanks for all your help.
Sponsoring you starting next paycheck.
Very Respectfully,
Daniel Hansen
…On Fri, Jul 23, 2021 at 3:05 PM Brendan ***@***.***> wrote:
Closed #184 <#184>.
—
You are receiving this because you modified the open/close state.
Reply to this email directly, view it on GitHub
<#184 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AD4JEEWFXUEPVN34ABZNKJLTZG4QBANCNFSM45NPYDEQ>
.
|
I love the work you guys are doing. Thanks for everything!
My question is, why can we not use something like
sys.getsizeof
in order to figure out the package size that is being received just like what an arduino would do in C withsizeof(payload)
I did see a post done by Aaron Hall (see below) and was wondering if something like this would work if the above function wouldn't?
I'm building an intra-network and would have different sized payloads coming back and going out of the MasterNode. There has to be a more conventional way to dealing with the payload size than what I have been reading, which has been setting the sizes to be static.
Very Respectfully,
Daniel
The text was updated successfully, but these errors were encountered: