Sending Quickstart Data To a Phone Via Twilio SMS

Hardware in use: Notecarrier F, Notecard, Swan MCU, Android phone

In a nutshell: I have completed the Quickstart up to the setion where the sensors.qo is sent to the Notehub. It shows up in the events page.

The sensors.qo data is controlled in the quickstart FW by the " J *body = JAddObjectToObject(req, “body”);" code fragment that is part of the Quickstart code as shown here:

J *req = notecard.newRequest(“note.add”);
if (req != NULL)
{
JAddStringToObject(req, “file”, “sensors.qo”);
JAddBoolToObject(req, “sync”, true);
J *body = JAddObjectToObject(req, “body”);
if (body)
{
JAddNumberToObject(body, “temp”, temperature);
JAddNumberToObject(body, “humidity”, humidity);
notecard.sendRequest(req);
}

I created a similar code fragment with which I intended to correspond with Twilio SMS:

J *req2 = notecard.newRequest(“note.add”);
if (req2 != NULL)
{
JAddStringToObject(req2, “file”, “twilio.qo”);
JAddBoolToObject(req2, “sync”, true);
J *body = JAddObjectToObject(req2, “body”);

if (body)
{         
  JAddStringToObject(body, "customUsername", "...USERNAME HERE");
  JAddStringToObject(body, "customMessage", "Coming From req2"); 
  JAddNumberToObject(body, "temp", temperature);
  JAddNumberToObject(body, "humidity", humidity);
 JAddStringToObject(body, "customFrom", "+1FROMPHONE HERE");
  JAddStringToObject(body, "customTo", "+1TOPHONE HERE");
}
notecard.sendRequest(req2);

So, what is happening is that both notes get to and show up at notehub.io. And Twilio is sending an SMS to my phone. The problem is that the title of the message is NOT the title that is in twilio.qo, it is the title that was put in on the “create route” page of notehub.io.

So it seems to me that both note.add commands are pushing the req and req2 data out to Notehub.io, and something is triggering notehub.io to send something to Twilio. However, none of the data appears to be being sent to Twilio, or if it is then Twilio doesn’t appear to know what to do with it. I don’t see anything in the tutorial that shows how to get the sensors.qo and twilio.qo DATA from notehub.io to Twilio.

Thanks,
Raymond

Hi @Raymond,

There is a separate Twilio SMS Guide that will walk you through generating an SMS from Notes sent to Notehub.

Rob

I don’t know how I missed it. I’ll check it out. Thank you.

It turns out that I actually didn’t miss it. I used it create my second “note.add” section of the code. However, the I missed the paragraph 2 about event attribute placeholders.

I fixed that and now I’m able to retrieve the To and From phone numbers from the FW rather than from the Notehub “create route” page.

However, I’m stuck on “customMessage”. As part of my testing I put in two separate messages:

JAddStringToObject(body, “customMessage”, “MESSAGE 1”);
and
JAddStringToObject(body, “customMessage”, “MESSAGE 2”);

I found that Twilio only sends “MESSAGE 2” to my phone. That tells me that I most likely need to combine both TEXTS as well as the sensor data that I want to transmit into one customMessage. My guess is that I need to use the “$contains” command, however the example is not clear as to how to use it, and Googling “$contains” yields nothing.

Here is what I would like to appear on my phone:
A text message
TEMPERATURE: temperature data here
HUMIDITY: humidity data here

I could use some advice.
Thanks,
Raymond

Hi @Raymond,

You’d have to send the temp and humidity data in a single Note. You can’t combine data from two Notes and then route that data to Twilio.

I think that’s what I was trying to do. My latest version looks like this:

J *req2 = notecard.newRequest(“note.add”);
if (req2 != NULL)
{
JAddStringToObject(req2, “file”, “twilio.qo”);
JAddBoolToObject(req2, “sync”, true);
J *body = JAddObjectToObject(req2, “body”);

if (body)
{ 
  JAddStringToObject(body, "customMessage", "TEXT MESSAGE");
  JAddNumberToObject(body, "customMessage", temperature);
  
  JAddNumberToObject(body, "temp", temperature);
  JAddNumberToObject(body, "humidity", humidity);

  JAddStringToObject(body, "customFrom", "+1FROM NUMBER"); 
  JAddStringToObject(body, "customTo", "+1TO NUMBER"); 
}
notecard.sendRequest(req2);

}

Here is my latest attempt:
J *req = notecard.newRequest(“note.add”);
if (req != NULL)
{
JAddStringToObject(req, “file”, “twilio.qo”);
JAddBoolToObject(req, “sync”, true);
J *body = JAddObjectToObject(req, “body”);
if (body)
{
// JAddNumberToObject(body, “temp”, temperature);
// JAddNumberToObject(body, “humidity”, humidity);
JAddStringToObject(body, “customFrom”, “+1855xxxxxxx”); // twilio created this number
JAddStringToObject(body, “customTo”, “+1424xxxxxxx”); // my phone
JAddNumberToObject(body, “customMessage”, temperature);
JAddNumberToObject(body, “customMessage”, humidity);
JAddStringToObject(body, “customMessage”, “THIS IS COMING FROM TWILIO.QO”); }
notecard.sendRequest(req);

And here is the result:
{
“customFrom”: “+1855xxxxxxx”,
“customMessage”: “THIS IS COMING FROM TWILIO.QO”,
“customTo”: “+1424xxxxxxx”
}

It’s clear that only the last data element is getting to Notehub. This implies that I am formatting the note incorrectly. It’s apparent to me that I need to concatenate the data elements into a single line of code, however i don’t know how to do that and have not been able to find an example that shows me how to do it.

Someone, please help me!
Thanks…

Hi @Raymond,

When you do this you are overwriting the previous value:

JAddNumberToObject(body, “customMessage”, temperature);
JAddNumberToObject(body, “customMessage”, humidity);
JAddStringToObject(body, “customMessage”, “THIS IS COMING FROM TWILIO.QO”); }

Instead you can concatenate temp and humidity values into a single string with whatever text you want. There are numerous different ways to concatenate strings with numbers in C, but some google searches will give you plenty of copy-and-paste examples.

Rob

Thank you for your reply. It took me forever to finally figure out that that’s what was happening. Your statement " Instead you can concatenate temp and humidity values into a single string with whatever text you want." is precisely what I’m looking for. I haven’t yet had any luck in finding out how to do it.

It’s becoming apparent to me that there is a giant hole in the Quickstart, relative to the process of creating a note that will be acceptable to Twilio, such that it will eventually show up on a phone. That hole seems to be that a “properly formatted” note that shows up in “Event > Body > Body” and even in the portion of “Event > Body” that is apparently Twilio’s response has no bearing on whether Twilio will actually forward that to a phone. And the fact that you stated in no uncertain terms that " Instead you can concatenate temp and humidity values into a single string with whatever text you want" shows me that you know PRECISELY what it is that I’m looking for.

Next, please understand that this is not a game to me–blues/Twilio are a small part of a much larger commercial effort. I’m not interested in learning how to improve my C programming skills–I AM interested in getting past this so that I can move on to the next element of the project.

So PLEASE, if you know how to format the relevant line or lines in the note request that will allow Twilio to forward my Text/Data/Data to a phone then I would be eternally grateful if you would just tell me rather than being coy.

Sincerely,
Ray Russell

Hi @Raymond,

I’m away from the office so don’t have a proper means of testing this code - but I’m pretty sure this is what you are looking for. Let me know if it doesn’t work:

char buffer[50];
int max_len = sizeof buffer;

snprintf(buffer, max_len, "Temperature: %d Humidity: %d.", temperature, humidity);

J *body = JAddObjectToObject(req, "body");
JAddStringToObject(body, "customMessage", buffer);

Thank you for your kind reply. I appreciate it.

I’m not having any luck with it–Even when I force temperature and humidity to 0 I get the following in Event > Body:

“customMessage”: “Temperature: 537526240 Humidity: 0.”,

I added the following in an attempt to clear the buffer just in case:

memset(buffer, 0, sizeof(buffer));

No luck…

Hi @Raymond - Can you post your full sketch here (or more of the code) so I can see how you’re gathering temp/humidity values and what the data type is?

Thanks,
Rob

Yes. I’m no longer actually capturing the temperature and humidity data. For the sake of simplicity I got rid of the two capture functions and simply set the two values to floating type numbers.

Here is the code in its entirety:

#include <Arduino.h>

#include <Notecard.h>

#include <NotecardPseudoSensor.h>

#define usbSerial Serial

#define productUID “com.XXXXXXXXXXXXXXXXXXXXXXXX”

int getSensorInterval();

using namespace blues;

Notecard notecard;

NotecardPseudoSensor sensor(notecard);

// the setup function runs once when you press reset or power the board
void setup()
{
delay(2500);
usbSerial.begin(115200);

notecard.begin();
notecard.setDebugOutputStream(usbSerial);

J *req = notecard.newRequest(“hub.set”);
JAddStringToObject(req, “product”, productUID);
JAddStringToObject(req, “mode”, “continuous”);
JAddBoolToObject(req, “sync”, true); // ADD THIS LINE
// “outbound”: 60,
// “inbound”: 120
notecard.sendRequest(req);
}

// the loop function runs over and over again forever
void loop()
{
// float temperature = sensor.temp();
// float humidity = sensor.humidity();

float temperature = 27.78; // I just made something up
float humidity = 63.246; // same here

// int temperature = 10;
// int humidity = 20;

usbSerial.print(“Temperature = “);
usbSerial.print(temperature);
usbSerial.println(” *C”);
usbSerial.print(“Humidity = “);
usbSerial.print(humidity);
usbSerial.println(” %”);

char buffer[100];
int max_len = sizeof buffer;

memset(buffer, 0, sizeof(buffer)); // Clear the buffer

// snprintf(buffer, max_len, “TEMPERATURE: %d HUMIDITY: %d.”, temperature, humidity);
snprintf(buffer, max_len, “HUMIDITY: %d TEMPERATURE: %d.”, humidity, temperature);

J *req = notecard.newRequest(“note.add”);
if (req != NULL)
{
JAddStringToObject(req, “file”, “sensors.qo”);
JAddBoolToObject(req, “sync”, true);
J *body = JAddObjectToObject(req, “body”);
if (body)
{
JAddNumberToObject(body, “TEMPERATURE”, temperature);
JAddNumberToObject(body, “HUMIDITY”, humidity);
JAddNumberToObject(body, “MAX_LEN”, max_len);
JAddStringToObject(body, “BUFFER”, buffer);

  JAddStringToObject(body, "customMessage", buffer);
}
  notecard.sendRequest(req);


delay(5000);

}

int sensorIntervalSeconds = getSensorInterval();
usbSerial.print(“Delaying “);
usbSerial.print(sensorIntervalSeconds);
usbSerial.println(” seconds”);
delay(sensorIntervalSeconds * 1000);
}

// This function assumes you’ll set the reading_interval environment variable to
// a positive integer. If the variable is not set, set to 0, or set to an invalid
// type, this function returns a default value of 60.
int getSensorInterval()
{
int sensorIntervalSeconds = 60;
J req = notecard.newRequest(“env.get”);
if (req != NULL) {
JAddStringToObject(req, “name”, “reading_interval”);
J
rsp = notecard.requestAndResponse(req);
int readingIntervalEnvVar = atoi(JGetString(rsp, “text”));
if (readingIntervalEnvVar > 0)
{
sensorIntervalSeconds = readingIntervalEnvVar;
}
notecard.deleteResponse(rsp);
}
return sensorIntervalSeconds;
}


Note that I turned off the twilio portion and am just looking at what’s coming out of notehub.

This is the notehub output:
{
“BUFFER”: “HUMIDITY: 537526232 TEMPERATURE: -536870912.”,
“HUMIDITY”: 63.24599838256836,
“MAX_LEN”: 100,
“TEMPERATURE”: 27.78000068664551,
“customMessage”: “HUMIDITY: 537526232 TEMPERATURE: -536870912.”
}


If I change the snprintf format specifiers from %d to %f then notehub outputs this:

{
“BUFFER”: “HUMIDITY: TEMPERATURE: .”,
“HUMIDITY”: 63.24599838256836,
“MAX_LEN”: 100,
“TEMPERATURE”: 27.78000068664551,
“customMessage”: “HUMIDITY: TEMPERATURE: .”
}


I’ve been beating my head against the wall thinking that this was a BLUES problem. Now I’m wondering whether this is some kind of compiler kink.

I FIGURED IT OUT! Well, someone else did actually. My last statement in my last post was correct–the issue is indeed with the compiler. That became obvious once I started actually THINKING about it.

Anyway, I googled something like “snprintf embedded float” and found this:

Using floats with sprintf() in embedded C - Stack Overflow

The author of the reply explained that (for reasons of space) compilers for embedded applications quite often don’t include “full feature” functions. He went on to show how he parsed the float data value and then processed each piece separately before eventually reassembling and making it available via sprintf.

Thank you for taking the time to help me with this. I appreciate it.

Raymond

3 Likes

For the sake of completeness here is what I did:

char buffer1[100];
char buffer2[100];
char buffer[200];
float sensor1 = 7.3;
float sensor2 = 8.5;
int max_len = sizeof buffer;

// SENSOR 1
const char *s1tmpSign = (sensor1 < 0) ? “-” : “”;
//char *s1tmpSign = (sensor1 < 0) ? “-” : “”;
float s1tmpVal = (sensor1 < 0) ? -sensor1 : sensor1;

int s1tmpInt1 = s1tmpVal; // Get the integer
float s1tmpFrac = s1tmpVal - s1tmpInt1; // Get fraction
int s1tmpInt2 = trunc(s1tmpFrac * 10000); // Turn into integer

sprintf (buffer1, "Sensor 1 = %s%d.%04d\n ", s1tmpSign, s1tmpInt1, s1tmpInt2); // Print as parts, note that you need 0-padding for fractional bit.

Serial.print("Buffer1 = ");
Serial.println(buffer1);

// SENSOR 2
const char *s2tmpSign = (sensor2 < 0) ? “-” : “”;
// char *s2tmpSign = (sensor2 < 0) ? “-” : “”;
float s2tmpVal = (sensor2 < 0) ? -sensor2 : sensor2;

int s2tmpInt1 = s2tmpVal; // Get the integer (678).
float s2tmpFrac = s2tmpVal - s2tmpInt1; // Get fraction (0.0123).
int s2tmpInt2 = trunc(s2tmpFrac * 10000); // Turn into integer (123).

sprintf (buffer2, “Sensor 2 = %s%d.%04d\n”, s2tmpSign, s2tmpInt1, s2tmpInt2); // Print as parts, note that you need 0-padding for fractional bit.

Serial.print("Buffer2 = ");
Serial.println(buffer2);

// OUTPUT

strcpy(buffer, “TEXT MESSAGE HERE \n” );
strcat(buffer, buffer1);
strcat(buffer, buffer2);

Serial.print("Buffer = ");
Serial.println(buffer);

// ******************* THE NEW ONE ***********************

J *req = notecard.newRequest(“note.add”);
if (req != NULL)
{
JAddStringToObject(req, “file”, “twilio.qo”);
JAddBoolToObject(req, “sync”, true);
J *body = JAddObjectToObject(req, “body”);
if (body)
{
JAddStringToObject(body, “customFrom”, “+1XXXXXXXXXX”);
JAddStringToObject(body, “customTo”, “+1YYYYYYYYYY”);
JAddStringToObject(body, “customMessage”, buffer);
}
notecard.sendRequest(req);
}

1 Like

Raymond,
Thank you for posting this. It really helped me out. Did this work for you? Were you able to send a message from blues to Twilio to a cell phone?
Tom

Yes. I was able to send an SMS from my embedded device > via Notecard > via Notehub > via Twilio to a cell phone. What I was unable to do was to get my embedded device to place a phone call via the same path, and I really need to do both. I think it’s possible to do it, I was just unable to get either blues.io or Twilio to provide me with a sample JSON structure that would allow me to code it in C–because C# is way too inefficient and uses up all of my embedded device storage.

I eventually gave up and went back to using a SIM7600A to do the same job. This is less desirable because it requires a monthly SIM card account, which is why I was interested in the Notecard in the first place.

I hope this helps.

Raymond,
Your post was exactly what I needed to see. I have been struggling with the 2g/3g shutdown because my application was focused on sms messaging. I had full 2-way control and didn’t need anything beyond a 3g device and a sim card. Now…wow. Thank you.