@charrold303, I believe you CAN do retained char dev_name[12] = "Tomato_1"
. However, that only initializes the c-string. I believe @ScruffR was guiding you to use snprintf() to produce your publish string and to avoid using (bad and evil) Arduino Strings.
Also not sure if the %.s
should be %s
or not. I think the decimal is just used on Floats where the number after the decimal on the float %f.
function just tells it how many zeros you want to display after the decimal.
For an Unsigned Integer, I just use %u
replaced the snprintf with the strcopy for the device name (dev_name) (thanks @ScruffR and @peekay123
removed the . in â%.sâ (thanks @RWB (interesting side note - compiled without errors with the â.â so maybe it ignored it either way? Just an interesting note))
Subthread!
I am trying to combine the ideas of the snprintf formatting and the incrementing array to the char array, and the compiler clearly doesnât like what I am doing. I suspect adding a string to my char array is not as simple as I think it is (or you illustrated here). Here is what I tried:
retained char offlinevals[1024];
retained int16_t globalindex = 0;
for(a = 0; a < 6; a = a + 1 ) {
int SMVolts = analogRead(as[a]);
if (SMVolts < 4000) {
String voltage = String(SMVolts);
String publishdata = publishdata + "S" + a + "::" + voltage + "::";
}
else {
String publishdata = publishdata + "S" + a + "::DC::";
}
}
// store the reading in the array
snprintf(offlinevals, sizeof(offlinevals), "%s", publishdata); <- this threw all sorts of nasty errors about copying things that shouldn't be copied... Also I know it is silly to create a formatted string and then create a string with formatting, but I am trying... *sigh*
}
It would be better to get rid of the String objects altogether. You canât use %s for String objects, itâs only for c-strings. Instead of this,
String voltage = String(SMVolts);
String publishdata = publishdata + "S" + a + "::" + voltage + "::";
Do something like this,
char publishdata[12];
snprintf(publishdata, sizeof(publishdata), "S%d::%d::", a, SMVolts);
Itâs not clear to me why you have publishdata on both sides of the equal sign, so what I wrote might not be what you want. If youâre using publishdata as the data argument in a Partilce.publish(), thatâs fine; you can pass a char array or a String object to that function.
the publishdata = publishdata + âother stuffâ was my attempt to concatenate the existing string with more data into a new string with the sam name. Is that not allowed?
If you want to use a String
object as %s
parameter in snprtintf()
you need to provide its contents as (const char*)
and my prefered way to do that is via type cast
snprintf(offlinevals, sizeof(offlinevals), "%s", (const char*)publishdata);
// but this would also work - less elegant IMHO
snprintf(offlinevals, sizeof(offlinevals), "%s", publishdata.c_str());
But this would defeat the whole purpose to use snprintf()
to get rid of the heap fragmentation effect String
objects have.
@Ric has shown how youâd do the string building the better way.
BTW, since you create a new instance of publishdata
with each iteration of your loop, your publishdata = publishdata + ...
will always ever add the new data to the newly created and hence empty string.
If you wanted to code what you verbally described, youâd do it this way
String publishdata = "Data:"; // create a new string only once
for (int i=0; i<10;i++) {
publishdata += String(i);
publishdata += ", ";
}
But as said, forget String
and try to understand the power of snprintf()
, strcpy()
and strcat()
.
I view String
objects as a crutch for non-technical coders but embedded programming calls for more skill and hence less âcomfortableâ but more powerful tools.
Hey guys! I think I figured out the whole string thing finally (at least my code compiles - testing will occur later today after I finish this last question)
particle.publish - max payload is 255.
my âoffline values char arrayâ is 254 (just to be safe) -> retained char offlinevals[254];
so my question is this:
@ScruffR said in an earlier posting:
if (newValue < 4000) { pubarray[globalIndex++] = newValue; if (globalIndex > 1023) globalIndex = 0; // when buffer is full overwrite old data }
With a char array does this work the same, or do I need to use the strlen()? Essentially the issue is, when I go through enough offline data collections (6.8 to be exact based on my âworst caseâ length of data stream) I do not want it to bomb out when it gets to the 7th loop in âoffline modeâ because there is no space left in the array.
My thought was to use something like:
if (strlen(offlinevals) > 244) { <- if my array is close to full then:
- do something to start at the beginning a-la what ScruffR said? Not sure this works since I am (finally) using strcpy() and strcat() to build up the contents of the char array
strcat(offlinevals, payload) but start from position 0 not the end?;
- switch to a second offline array? (I could conceivably have 3 or 4 before I create memory issues)
currentarray = offlinevals2[254]; (I know that's not correct, just illustrating the idea)
- nuke the array and start over? (least liked option, but possible)
strcpy(offlinevals, "");
- Something else that someone suggests?
}
Thanks for making me stick with the strxxx() commands, gang. It is not intuitive but it does work and I understand it a lot better nowâŚ
@RWB Thanks for introducing me to Losant! I was using Ubidots for a little while and gave Losant a try this week. Although getting data into Ubidots is a little easier, the extremely powerful workflow options and dashboards in Losant make up for it. Pushing numerous variables in a webhook and decoding the json in the workflow is awesome. Not to mention I can set up watch dog timers to trigger an even if a device doesnât report in x hours. My only complaint is a limit of 10 devices and 30 day data retention in the free version (compared to 20 devices and 90 days for Ubidots).
Thanks again
@adamg Yea man Losant is Superior to Ubidots, especially when it comes to âPushing numerous variables in a webhook and decoding the json in the workflowâ.
Their free tier of service is perfect for my testing, they give you 1 million publish events which allows me to send 220-byte updates every 15 seconds without coming close to running out of free data. Ubidots free account would run out way before that with their current offerings.
For others who have never used Losant here is a new tutorial that will show you how to get setup with Losant for the first time step by step.
@BrandonCannaday Is this the new Particle setup guide you were working on?
@RWB we actually have a more formal guide being written right now. That article is an awesome guest post by Kevin Sidwar. It does make use of the new Particle Integration, so definitely a good resource for learning how to use it!