Firebase web hook

Good afternoon everyone. I am trying to take a data from a gyroscope and push that data to a database in Firebase. In my Boron code this is the output
Output data to dashboard

    Particle.publish("X-Axis of Rotation :",  String(xGyro));
    delay(1000);
    Particle.publish("Y-Axis of Rotation :",  String(yGyro));
    delay(1000);
    Particle.publish("Z-Axis of Rotation :",  String(zGyro));
    delay(1000);

In my webhook I have the json as follows

"X-Axis of Rotation :": "{{{PARTICLE_EVENT_VALUE}}}",
"Y-Axis of Rotation :": "{{{PARTICLE_EVENT_VALUE}}}",
"Z-Axis of Rotation :": "{{{PARTICLE_EVENT_VALUE}}}",
  "published_at": "{{{PARTICLE_PUBLISHED_AT}}}"

The data never gets pushed to the data base and when I hit the “Test” button i receive ""X-Axis of Rotation :":"test-event","Y-Axis of Rotation :":"test-event","Z-Axis of Rotation :":"test-event""published_at":"2019-10-08T22:49:53.095Z""

Any suggestions on what I am doing wrong? The event list updates every min in the particle console but does not push to firebase.

There are neater ways of doing the firmware side, but I simply do:

char publishString[240] = "empty"; // averaging around 104 chars
String s = "{";
    s.concat("\"x\":");
    s.concat(String(xGyro));
    s.concat(",\"yt\":");
    s.concat(String(yGyro));
    s.concat(",\"z\":");
    s.concat(String(zGyro));
    s.concat("}");
    s.toCharArray(publishString, 240);

    Particle.publish("FBpush", publishString);

{
    "eventName": "FBpush",
    "requestType": "POST",
    "url": "https://xxxxxxx.firebaseio.com/devices/{{PARTICLE_DEVICE_ID}}/events.json",
    "json": {
        "x": "{{x}}",
        "y": "{{y}}",
        "z": "{{z}}",
        "coreid": "{{PARTICLE_DEVICE_ID}}",
        "published_at": "{{PARTICLE_PUBLISHED_AT}}"
    },
    "noDefaults": true,
    "form": {},
    "query": {"auth": "firebasesecret"},
    "headers": {
        "Content-Type": "application/json"
    },
    "mydevices": true,
    "responseTopic": "hook-response/FBpush_{{PARTICLE_DEVICE_ID}}"
}

1 Like

ps, for extra credit you can use the advanced editor in particle console so it forwards the values to firebase as integers rather than strings.

doesn’t make a huge pile of difference where the conversion occurs.

The neater way would probably be to use snprintf:

// Char buffer
char publishString[240];
// Assuming the gyros are floating point, 5 decimal places
snprintf(publishString, sizeof(publishString), "{\"x\":%1.5f,\"y\":%1.5f,\"z\":%1.5f\"}", xGyro, yGyro, zGyro);

// If they are ints use this instead
snprintf(publishString, sizeof(publishString), "{\"x\":%d,\"y\":%d,\"z\":%d\"}", xGyro, yGyro, zGyro);

Particle.publish("FBpush", publishString, PRIVATE);
4 Likes

super neat.

All the old examples were sprintf then toCharArray.

One I’ve been using on other platforms and liking is: https://github.com/cesanta/frozen
Allows for flexible JSON formats for parsing and printing. If a variable isn’t there it doesn’t mind, if it’s out of order it doesn’t mind. Easy to check if a certain variable is present and valid in a given submitted json string.

1 Like

Thanks for all the replies and suggestions. I’ll give it a shot this afternoon when I get back to my hotel. My boron, it seems, has gone offline so i will have to wait till i get back to reset it.

Ok so I managed to get data to webhook to Firebase usting mterrills firmware code and the webhook code. But now I am not receiving the correct data. As you can tell I am not very good at coding…here is my current set code. This code currently crashes the Boron…took me awhile to get reset.

#include <application.h>
#include <spark_wiring_i2c.h>
//#include "lib1.h"

// BMG160 I2C address is 0x68(104)
#define Addr 0x68

int xGyro = 0, yGyro = 0, zGyro = 0;
void setup() 
{
    // Set variable
    Particle.variable("i2cdevice","BMG160");
    Particle.variable("xGyro",xGyro);
    Particle.variable("yGyro",yGyro);
    Particle.variable("zGyro",zGyro);
 // Subscribe to the integration response event
  Particle.subscribe("hook-response/test2", myHandler, MY_DEVICES);
}

void myHandler(const char *event, const char *data) {
  // Handle the integration response
}
          

void loop()
{
    unsigned int data[6];
    // Start I2C Transmission
    Wire.beginTransmission(Addr);
    // Select data register
    Wire.write(0x02);
    // Stop I2C Transmission
    Wire.endTransmission();
    // Request 6 bytes of data
    Wire.requestFrom(Addr, 6);
    // Read 6 bytes of data
    // xGyro lsb, xGyro msb, yGyro lsb, yGyro msb, zGyro lsb, zGyro msb
    if(Wire.available() == 6)
    {
        data[0] = Wire.read();
        data[1] = Wire.read();
        data[2] = Wire.read();
        data[3] = Wire.read();
        data[4] = Wire.read();
        data[5] = Wire.read();
    }
    //delay(60000);

    // Convert the data
    xGyro = ((data[1] * 256) + data[0]);
    if (xGyro > 32767)
    {
       xGyro -= 65536;
    }
    yGyro = ((data[3] * 256) + data[2]);
    if (yGyro > 32767)
    {
        yGyro -= 65536;
    }
    zGyro = ((data[5] * 256) + data[4]);
    if (zGyro > 32767)
    {
        zGyro -= 65536;
    }
    
 char publishString[240] = "empty"; // averaging around 104 chars
String s = "{";
    s.concat("\"x\":");
    s.concat(String(xGyro));
    s.concat(",\"yt\":");
    s.concat(String(yGyro));
    s.concat(",\"z\":");
    s.concat(String(zGyro));
    s.concat("}");
    s.toCharArray(publishString, 240);

    Particle.publish("FBpush", publishString);
    delay(6000);
}

You have no Wire.begin() in your code (should be in setup()).
You also have no body to your myHandler().
You won’t need #include <application.h> nor #include <spark_wiring_i2c.h>. But if you want an include it should be #include <Particle.h>.
Also, you should use PRIVATE for your publishing call when subscribing for MY_DEVICES.

1 Like

Thanks that worked.

Ok well now everything uploads to Firebase only thing is, it is pretty much a random number generator. The sensor never moves but I get wild fluctuations in the readings. Here is my code for ease. I know there are easier and better ways of doing this, I just haven’t found them.

//This Code will send x,y,z data that is web hooked to Firebase.  
#include <Particle.h>
#define Addr 0x68

int xGyro = 0, yGyro = 0, zGyro = 0;
void setup() 
{
    Wire.begin();
    // Set variable
    Particle.variable("i2cdevice","BMG160");
    Particle.variable("xGyro",xGyro);
    Particle.variable("yGyro",yGyro);
    Particle.variable("zGyro",zGyro);
 // Subscribe to the integration response event
  Particle.subscribe("hook-response/test2", myHandler, MY_DEVICES);
}

void myHandler(const char *event, const char *data) {
   //Handle the integration response
}
          

void loop()
{
    unsigned int data[6];
    // Start I2C Transmission
    Wire.beginTransmission(Addr);
    // Select data register
    Wire.write(0x02);
    // Stop I2C Transmission
    Wire.endTransmission();
    // Request 6 bytes of data
    Wire.requestFrom(Addr, 6);
    // Read 6 bytes of data
    // xGyro lsb, xGyro msb, yGyro lsb, yGyro msb, zGyro lsb, zGyro msb
    if(Wire.available() == 6)
    {
        data[0] = Wire.read();
        data[1] = Wire.read();
        data[2] = Wire.read();
        data[3] = Wire.read();
        data[4] = Wire.read();
        data[5] = Wire.read();
    }
    //delay(60000);

    // Convert the data
    xGyro = ((data[1] * 256) + data[0]);
    if (xGyro > 32767)
    {
       xGyro -= 65536;
    }
    yGyro = ((data[3] * 256) + data[2]);
    if (yGyro > 32767)
    {
        yGyro -= 65536;
   }
    zGyro = ((data[5] * 256) + data[4]);
    if (zGyro > 32767)
    {
        zGyro -= 65536;
    }
    
 char publishString[240] = "empty"; // averaging around 104 chars
String s = "{";
    s.concat("\"x\":");
    s.concat(String(xGyro));
    s.concat(",\"y\":");
    s.concat(String(yGyro));
    s.concat(",\"z\":");
    s.concat(String(zGyro));
    s.concat("}");
    s.toCharArray(publishString, 240);

   Particle.publish("FBpush", publishString, PRIVATE);
   //delay is 1sec=1000
   delay(10000);
}

Instead of if (Wire.available() == 6) { ... } I’d rather use Wire.readBytes() like this

  uint8_t data[6];
  Wire.beginTransmission(Addr);
  Wire.write(0x02);
  Wire.endTransmission();
  Wire.requestFrom(Addr, sizeof(data));
  Wire.readBytes((char*)data, sizeof(data));
  // optionally you could flush any residual bytes - if there are any left
  while(Wire.available()) Wire.read();

This will wait for up 1 second for the data to arrive.

BTW, does that sensor not need any setup before first use?

It looks like it does need to either calabrate or setup as the out put is not correct. Now to try and figure that part out.

I’d also change the string building to that

  snprintf(publishString, sizeof(publishString)
          , "{\"x\":%d,\"y\":%d,\"z\":%d}"
          , xGyro, yGyro, zGyro);

BTW, have a look at this

They usually have demo code and/or libraries to run their sensor boards with Particle devices too.

1 Like

Thanks for the link. That is the video that initially got me to purchase that sensor. The code on github is what I used. It also does not have a calibration step. I used just the raw code and it does the same as mine as far as the readings being off.

But the code in their repo does have some extra instructions in setup() which you have not got in your code shown above (Wire.begin() was one of them as pointed out in this post)

This is my current code. I had made some of the changes you suggested but I got errors when I tried to compile.

//This Code will send x,y,z data that is web hooked to Firebase.  Currently set for every 30 mins
#include <Particle.h>
#define Addr 0x68

#include <application.h>
#include <spark_wiring_i2c.h>

// BMG160 I2C address is 0x68(104)
#define Addr 0x68

int xGyro = 0, yGyro = 0, zGyro = 0;
void setup() 
{
    // Set variable
    Particle.variable("i2cdevice","BMG160");
    Particle.variable("xGyro",xGyro);
    Particle.variable("yGyro",yGyro);
    Particle.variable("zGyro",zGyro);

    // Initialise I2C communication as MASTER 
    Wire.begin();
    // Initialise Serial Communication
    Serial.begin(9600);
    
    // Start I2C Transmission
    Wire.beginTransmission(Addr);
    // Select Range register
    Wire.write(0x0F);
    // Configure full scale 2000 dps
    Wire.write(0x80);
    // Stop I2C Transmission
    Wire.endTransmission();
    
    // Start I2C Transmission
    Wire.beginTransmission(Addr);
    // Select Bandwidth register
    Wire.write(0x10);
    // Set Bandwidth = 200 Hz
    Wire.write(0x04);
    // Stop I2C Transmission
    Wire.endTransmission();
    delay(300);
// Subscribe to the integration response event
  Particle.subscribe("hook-response/test2", myHandler, MY_DEVICES);
}

void myHandler(const char *event, const char *data) {
   //Handle the integration response
}
          

void loop()
{
    unsigned int data[6];
    // Start I2C Transmission
    Wire.beginTransmission(Addr);
    // Select data register
    Wire.write(0x02);
    // Stop I2C Transmission
    Wire.endTransmission();
    // Request 6 bytes of data
    Wire.requestFrom(Addr, 6);
    // Read 6 bytes of data
    // xGyro lsb, xGyro msb, yGyro lsb, yGyro msb, zGyro lsb, zGyro msb
    if(Wire.available() == 6)
    {
        data[0] = Wire.read();
        data[1] = Wire.read();
        data[2] = Wire.read();
        data[3] = Wire.read();
        data[4] = Wire.read();
        data[5] = Wire.read();
    }
    delay(300);

    // Convert the data
    xGyro = ((data[1] * 256) + data[0]);
    if (xGyro > 32767)
    {
       xGyro -= 65536;
    }
    yGyro = ((data[3] * 256) + data[2]);
    if (yGyro > 32767)
    {
        yGyro -= 65536;
   }
    zGyro = ((data[5] * 256) + data[4]);
    if (zGyro > 32767)
    {
        zGyro -= 65536;
    }
    
 char publishString[240] = "empty"; // averaging around 104 chars
String s = "{";
    s.concat("\"x\":");
    s.concat(String(xGyro));
    s.concat(",\"y\":");
    s.concat(String(yGyro));
    s.concat(",\"z\":");
    s.concat(String(zGyro));
    s.concat("}");
    s.toCharArray(publishString, 240);

   Particle.publish("FBpush", publishString, PRIVATE);
   //delay is 1sec=1000
   delay(1800000);
   }
'''

And which?

This one. I will have to change it back to get the errors.

uint8_t data[6];
  Wire.beginTransmission(Addr);
  Wire.write(0x02);
  Wire.endTransmission();
  Wire.requestFrom(Addr, sizeof(data));
  Wire.readBytes((char*)data, sizeof(data));
  // optionally you could flush any residual bytes - if there are any left
  while(Wire.available()) Wire.read();

Ok I have my firmware doing what I want it to do. It is sending proper data to the console.

void loop()
{
        /* Get a new sensor event */
        sensors_event_t event;
        bno.getEvent(&event);
                char publishString[240] = "empty"; // averaging around 104 chars
    String s = "{";
    s.concat("\"x\":");
    s.concat(String(event.orientation.x, 4));
    s.concat(",\"y\":");
    s.concat(String(event.orientation.y, 4));
    s.concat(",\"z\":");
    s.concat(String(event.orientation.z, 4));
    s.concat("\"c\":");
    s.concat(String( lastPowerSource));  
    s.concat("\"s\":");
    s.concat(String( Fuel.getSoC()));
    s.concat("}");
    s.toCharArray(publishString, 240);
   Particle.publish("FBpush", publishString, PRIVATE);
     
   //delay is 1sec=1000
   delay(100000);
   }

Console receives this data {“x”:0.0000,“y”:-1.1250,“z”:-0.7500"c":-1"s":80.421875}
then my web hook to Fire base

{
    "event": "FBpush",
    "responseTopic": "hook-response/FBpush_{{PARTICLE_DEVICE_ID}}",
    "url": "https://listtender-f5aa9.firebaseio.com/devices/EDITEDOUT0001c9b6d2/events.json",
    "requestType": "POST",
    "noDefaults": true,
    "rejectUnauthorized": false,
    "headers": {
        "Content-Type": "application/json"
    },
    "json": {
        "c": "{{c}}",
        "s": "{{s}}",
        "x": "{{x}}",
        "y": "{{y}}",
        "z": "{{z}}",
        "id": "{{PARTICLE_DEVICE_ID}}",
        "dts": "{{PARTICLE_PUBLISHED_AT}}"
    },
    "query": {
        "auth": "####Editedout###########"
    }
}

posts this “-LrnnUj1e4FT3RBkWOW4”:{“c”:"",“dts”:“2019-10-22T14:10:25.623Z”,“id”:“e00fce6802b8be014e2a91f9”,“s”:"",“x”:"",“y”:"",“z”:""}}

Any ideas as to why my data not showing up in the firebase data base?
Also there was mention by @mterrill to use the advanced editor to forward the values as integers…I have looked for how to do this, but can not locate how to. I would like to round the values to 2 decimal places. Thanks in advance.

As I mentioned in this post it’s better to use snprintf() instead of String concatenations.

With your float values this would look like this

snprintf(publishString
        , sizeof(publishString)
        , "{\"x\":%.2f,\"y\":%.2f,\"z\":%.2f,\"c\":%d,\"s\":%.2f}"
        , event.orientation.x
        , event.orientation.y
        , event.orientation.z
        , lastPowerSource
        , Fuel.getSoC()
        );

In console.particle.io/integrations you can select Custom Body as Request Format instead of JSON which lets you have “un-quoted” values in your request.

1 Like