not sure about what to do here. For starters i modify Robin2 serial example to try and receive a char string and convert it to byte for storing ip address. my compiler complains about brace initializer and then cast from char* to byte.
The modified example code only has 4 new lines :
strtokIndx = strtok(NULL, ",");
byte IP_FROM_PC[4] = atoi(strtokIndx); // convert this part to array of 4 bytes ip address
Serial.print("IP ");
Serial.println(IP_FROM_PC);
an example of the input i would send is "in this case"<command,0,0.0,192.192.192.192>
please help
// Example 5 - Receive with start- and end-markers combined with parsing
const byte numChars = 32;
char receivedChars[numChars];
char tempChars[numChars]; // temporary array for use when parsing
// variables to hold the parsed data
char messageFromPC[numChars] = {0};
int integerFromPC = 0;
float floatFromPC = 0.0;
boolean newData = false;
//============
void setup() {
Serial.begin(9600);
Serial.println("This demo expects 3 pieces of data - text, an integer and a floating point value");
Serial.println("Enter data in this style <HelloWorld, 12, 24.7> ");
Serial.println();
}
//============
void loop() {
recvWithStartEndMarkers();
if (newData == true) {
strcpy(tempChars, receivedChars);
// this temporary copy is necessary to protect the original data
// because strtok() used in parseData() replaces the commas with \0
parseData();
showParsedData();
newData = false;
}
}
//============
void recvWithStartEndMarkers() {
static boolean recvInProgress = false;
static byte ndx = 0;
char startMarker = '<';
char endMarker = '>';
char rc;
while (Serial.available() > 0 && newData == false) {
rc = Serial.read();
if (recvInProgress == true) {
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
receivedChars[ndx] = '\0'; // terminate the string
recvInProgress = false;
ndx = 0;
newData = true;
}
}
else if (rc == startMarker) {
recvInProgress = true;
}
}
}
//============
void parseData() { // split the data into its parts
char * strtokIndx; // this is used by strtok() as an index
strtokIndx = strtok(tempChars, ","); // get the first part - the string
strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
integerFromPC = atoi(strtokIndx); // convert this part to an integer
strtokIndx = strtok(NULL, ",");
floatFromPC = atof(strtokIndx); // convert this part to a float
strtokIndx = strtok(NULL, ",");
byte IP_FROM_PC[4] = atoi(strtokIndx); // convert this part to array of 4 bytes ip address
}
//============
void showParsedData() {
Serial.print("Message ");
Serial.println(messageFromPC);
Serial.print("Integer ");
Serial.println(integerFromPC);
Serial.print("Float ");
Serial.println(floatFromPC);
Serial.print("IP ");
Serial.println(IP_FROM_PC);
}
What do you expect
byte IP_FROM_PC[4] = atoi(strtokIndx); // convert this part to a byte ip address
to do, even if it worked ?
I also see that IP_FROM_PC is being declared locally in the parseData() function so printing it in another function will not work unless you pass it to the other funcction
UKHeliBob:
What do you expect
byte IP_FROM_PC[4] = atoi(strtokIndx); // convert this part to a byte ip address
to do, even if it worked ?
I also see that IP_FROM_PC is being declared locally in the parseData() function so printing it in another function will not work unless you pass it to the other funcction
Sorry about that,
basically i want to change an ip address that will be stored in the EEPROM in an array of 4 bytes. I did not include the EEPROM code in the example sketch as i think i can handle that part. all i need "i think" is to be able to parse the specific chars into an array of 4 bytes.
I send <updateip,10.10.10.10> from serial and i need part 10.10.10.10 to be parsed into byte array. i dont need the integerPart or FloatFromPc and those parts can be ingnored for now.
My first question would be why convert to an array of bytes in the first place ? Where is the IP address coming from and how will it be used when loaded from the EEPROM later ?
UKHeliBob:
My first question would be why convert to an array of bytes in the first place ? Where is the IP address coming from and how will it be used when loaded from the EEPROM later ?
ip address will be coming from human input at serial port. I will be using the address to be stored in the EEPROM for Udp.beginPacket(); which accepts a char string or a ip address which is 4 bytes. i will simply be using it only for this purpose. since i cannot store a String object in the EEPROM i must think of something else. I'm open to different logic.
Also i realize my example of printing the byte array would not print the 4 byte ipaddres
since i cannot store a String object in the EEPROM
But using Robin's code you haven't got a String object, you have an array of chars and that can be stored directly into EEPROM with one call to EEPROM.put()
UKHeliBob:
But using Robin's code you haven't got a String object, you have an array of chars and that can be stored directly into EEPROM with one call to EEPROM.put()
Interesting. Did i do this right? this would leave me with a null terminated c_str _EEPROM.PC_IP that can be stored in eeprom?
#include <EEPROM.h>
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
// Example 5 - Receive with start- and end-markers combined with parsing
WiFiUDP Udp;
const byte numChars = 32;
char receivedChars[numChars];
char tempChars[numChars]; // temporary array for use when parsing
// variables to hold the parsed data
char messageFromPC[numChars] = {0};
int integerFromPC = 0;
float floatFromPC = 0.0;
boolean newData = false;
struct {
char PC_IP[20];
} _EEPROM;
//============
void setup() {
Serial.begin(9600);
Serial.println("This demo expects 3 pieces of data - text, an integer and a floating point value");
Serial.println("Enter data in this style <HelloWorld, 12, 24.7> ");
Serial.println();
}
//============
void loop() {
recvWithStartEndMarkers();
if (newData == true) {
strcpy(tempChars, receivedChars);
// this temporary copy is necessary to protect the original data
// because strtok() used in parseData() replaces the commas with \0
parseData();
showParsedData();
newData = false;
}
}
//============
void recvWithStartEndMarkers() {
static boolean recvInProgress = false;
static byte ndx = 0;
char startMarker = '<';
char endMarker = '>';
char rc;
while (Serial.available() > 0 && newData == false) {
rc = Serial.read();
if (recvInProgress == true) {
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
receivedChars[ndx] = '\0'; // terminate the string
recvInProgress = false;
ndx = 0;
newData = true;
}
}
else if (rc == startMarker) {
recvInProgress = true;
}
}
}
//============
void parseData() { // split the data into its parts
char * strtokIndx; // this is used by strtok() as an index
strtokIndx = strtok(tempChars, ","); // get the first part - the string
strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
integerFromPC = atoi(strtokIndx); // convert this part to an integer
strtokIndx = strtok(NULL, ",");
floatFromPC = atof(strtokIndx); // convert this part to a float
strtokIndx = strtok(NULL, ",");
strcpy(_EEPROM.PC_IP, strtokIndx); // convert this part to a byte ip address
Serial.println(_EEPROM.PC_IP);
}
//============
void showParsedData() {
Serial.print("Message ");
Serial.println(messageFromPC);
Serial.print("Integer ");
Serial.println(integerFromPC);
Serial.print("Float ");
Serial.println(floatFromPC);
// Udp.beginPacket(_EEPROM.PC_IP, 80);
//Udp.write("SOMETHING");
//Udp.endPacket();
}
I cannot make any sense of your attempt to parse the input. Why does it expect a float, for instance ?
Try this as an example
char * input = "<updateip,10.10.10.10>";
byte ip[4];
void setup()
{
Serial.begin(115200);
while (!Serial);
char * ptr;
ptr = strtok(input, ","); //skip until the comma
for (int b = 0; b < 4; b++) //next 4 characters delimited by full stops
{
ip[b] = atoi(strtok(NULL, ".")); //get chars and convert to byte
}
//
for (int b = 0; b < 4; b++) //show the result
{
Serial.print(ip[b]);
Serial.print("\t");
}
}
void loop()
{
}
UKHeliBob:
I cannot make any sense of your attempt to parse the input. Why does it expect a float, for instance ?
Try this as an example
char * input = "<updateip,10.10.10.10>";
byte ip[4];
void setup()
{
Serial.begin(115200);
while (!Serial);
char * ptr;
ptr = strtok(input, ","); //skip until the comma
for (int b = 0; b < 4; b++) //next 4 characters delimited by full stops
{
ip[b] = atoi(strtok(NULL, ".")); //get chars and convert to byte
}
//
for (int b = 0; b < 4; b++) //show the result
{
Serial.print(ip[b]);
Serial.print("\t");
}
}
void loop()
{
}
this is very helpful. my last attempt to collect chars into the char array for the eeprom worked "except for no null termination". i think my example was bad because its nothin like my program. my program does not use the floats or intFromPc variables sorry for the confusion. but looking at your example, i get it.
this part here is the most confusing part to me with the string tokens and atoi. the way you use the for loops really helped me visualize what i was trying to do. thanks!!!
ip[b] = atoi(strtok(NULL, ".")); //get chars and convert to byte
this part here is the most confusing part to me with the string tokens and atoi
Here is that broken into separate lines with comments
for (int b = 0; b < 4; b++) //next 4 characters delimited by full stops
{
char * value = strtok(NULL, "."); //get the next value as a char pointer
ip[b] = atoi(value); //convert char to integer and save to array
}