natevw / node-nrf

Pure-JavaScript nRF24L01 driver library
117 stars 31 forks source link

How to handle structs? #18

Closed Mrono closed 10 years ago

Mrono commented 10 years ago

How can I do the following in node, note the absence of dynamic payload

#include <cstdlib>
#include <iostream>
#include <unistd.h>
#include "../RF24.h"

RF24 radio("/dev/spidev0.0", 8000000 , 25);

typedef struct {
  float curTemp;
  float voltage;
  int    setTemp;
  bool   activated;
} rpacket_s;

int main(int argc, char** argv)
{
 rpacket_s rpacket[5];
 radio.begin();
 radio.openReadingPipe(1, 0xF0F0F0A0A1LL);
 radio.startListening();

 while(true) {
    uint8_t pipeNo;
    if( radio.available(&pipeNo) ) {
       bool done = false;
       while( !done ) {
          done = radio.read( &rpacket[pipeNo-1], sizeof(rpacket_s));
             printf("Sensor: %d Temp: %f Voltage %f\r\n", pipeNo,
       rpacket[pipeNo-1].curTemp, 
       rpacket[pipeNo-1].voltage);
       }
    }
 }
 return 0;
}
natevw commented 10 years ago

Personally I would use https://github.com/natevw/struct-fu but I may be biased ;-)

With struct-fu you would do something like this (coded in-browser, untested):

var sf = require('struct-fu');
var rpacket = sf.struct([
    sf.float32le('curTemp'),
    sf.float32le('voltage'),
    sf.int32le('setTemp'),
    sf.uint8('activated')
]);

// …radio code…

pipe.on('data', function (_d) {
    var d = rpacket.valueFromBytes(_d);
    // use d.curTemp, d.voltage, etc.
});

(There are some other struct/binary conversion modules on npm if you like.)

natevw commented 10 years ago

(Oh, note that your C++ compiler(s) might be adding some padding to the struct, e.g. maybe between setTemp and activated fields, that you may need to explicitly consume with sf.bytes or sf.padTo…but you'll need to check your particular compiler's documentation or inspect some sample packets to see if this is the case.)

Mrono commented 10 years ago

This is what's sending it

#include <OneWire.h>
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"

#define  CE_PIN  4
#define  CSN_PIN 5
#define  DS18B20_PIN 7

typedef struct {
 float  curTemp;
 float  voltage;
 int    setTemp;
 bool   activated;
} rpacket_s;

RF24 radio(CE_PIN, CSN_PIN);
OneWire ds(DS18B20_PIN);

rpacket_s rpacket;

float readTemperature(void);
long readVcc(void);

void setup() {
 pinMode(CE_PIN, OUTPUT);
 pinMode(CSN_PIN, OUTPUT);
 radio.begin();
 radio.openWritingPipe( 0xF0F0F0A0B1LL);
 rpacket.setTemp = 70.0;
 rpacket.curTemp = 0.0;
 rpacket.activated = FALSE;
 rpacket.voltage = 0.0;
 Serial.begin(115200);
}

void loop() {
 rpacket.curTemp = readTemperature();
 rpacket.voltage = readVcc()/1000.0;
 radio.write(&rpacket, sizeof(rpacket));
}
Mrono commented 10 years ago

How do I prevent it from overrunning the buffer, i'm getting

buffer.js:582
    throw new RangeError('Trying to access beyond buffer length');

Edit: It didn't like the int

natevw commented 10 years ago

Ah, glad you figured it out. I forgot that int is 16-bit in Arduino. I think this is resolved, then, right?

Mrono commented 10 years ago

As far as I can tell, you've been a great help. Thank you very much :)