Read Serial Input into Char Array - c++

So i've managed to wire up an ESP-01 module to my arduino, now im attempting to parse the +IPD responses the chip gives over a serial connection. Im not really all that handy with C++ but this is what i've managed to come up with after researching a bunch online:
#include <SoftwareSerial.h>
SoftwareSerial ESP8266(2, 3); // RX | TX
int baud = 9600;
void setup() {
ESP8266.begin(baud);
Serial.begin(baud);
Serial.println("--- Start ---");
}
void loop() {
if (ESP8266.available()) // check if the esp is sending a message
{
Serial.println("Something received");
delay(500);
if (ESP8266.find("%<"))
{
Serial.println("--------------- DEBUG ----------------A");
char temp = {char(ESP8266.read())};
while ((temp != '%') && (ESP8266.available())) {
Serial.print(temp);
temp = char(ESP8266.read());
}
Serial.println("\n--------------- END DEBUG ----------------");
}
}
}
The standard response the chip gives when receiving a message is as follows:
+IPD,<len>:<Message>
+IPD,0,14:%<255,128,0%
The data im trying to send - random RGB values (using '%<' and '%' as flags/markers):
%<255,128,0%
From here, i've managed to write the above code, which will print out the following over serial:
So i've managed to get it to print the values i need over Serial, but i cant seem to store them in an array of some sort to do things with the data.
Things i've tried:
using readString() instead of read(), coupled with indexOf to search/extract the data
Looping and appending to a char array
A bunch of array stuff, seems tricky though because you have to know the length when you declare it
Ideally, i'd like a function that reads the +IPD value, extracts the RGB data and then splits it into a 3 index array, like so:
rgbArray = {124, 234, 96};
Any and all help is super appreciated!

To store the input to an array, just allocate an array and store the data there.
Serial.println("--------------- DEBUG ----------------A");
int receivedLength = 0;
char data[16];
char temp = ESP8266.available();
while ((temp != '%') && (ESP8266.available())) {
Serial.print(temp);
if (receivedLength < 16) data[receivedLength++] = temp;
}
for (int i = 0; i < receivedLength; i++) Serial.print(data[i]);
Serial.println("\n--------------- END DEBUG ----------------");
Alternatively, you can do conversion to integers while reading like this:
Serial.println("--------------- DEBUG ----------------A");
int rgbSize = 0;
int rgbArray[3];
int currentValue = 0;
char temp = ESP8266.available();
while ((temp != '%') && (ESP8266.available())) {
Serial.print(temp);
if (temp == ',') {
if (rgbSize < 3) rgbArray[rgbSize++] = currentValue;
currentValue = 0;
} else {
currentValue = currentValue * 10 + (temp - '0');
}
}
if (rgbSize < 3) rgbArray[rgbSize++] = currentValue;
for (int i = 0; i < rgbSize; i++) {
if (i > 0) Serial.print(',');
Serial.print(rgbArray[i]);
}
Serial.println("\n--------------- END DEBUG ----------------");

Ended up going with a different way of doing things:
Managed to read about readStringUntil(''); in some dark corner of the web. So i came up with a super dirty implementation - but it works:
Assume your input string is:
+IPD,0,14:%<255,128,0%
Then do:
if (ESP8266.available()) // check if the esp is sending a message
{
delay(500);
if (ESP8266.find("%<"))
{
r = ESP8266.readStringUntil(',');
g = ESP8266.readStringUntil(',');
b = ESP8266.readStringUntil('%');
}
}

Related

Modifying integer value from another process using process_vm_readv

I am using Ubuntu Linux to write two programs. I am attempting to change the value of an integer from another process. My first process (A) is a simple program that loops forever and displays the value to the screen. This program works as intended and simply displays the value -1430532899 (0xAABBCCDD) to the screen.
#include <stdio.h>
int main()
{
//The needle that I am looking for to change from another process
int x = 0xAABBCCDD;
//Loop forever printing out the value of x
int counter = 0;
while(1==1)
{
while(counter<100000000)
{
counter++;
}
counter = 0;
printf("%d",x);
fflush(stdout);
}
return 0;
}
In a separate terminal, I use the ps -e command to list the processes and note the process id for process (A). Next as root use (sudo) I run this next program (B) and enter in the process ID that I noted from process (A).
The program basically searches for the needle which is in memory backwards (DD CC BB AA) find the needle, and takes note of the address. It then goes and tries to write the hex value (0xEEEEEEEE) to that same location, but I get a bad address error when errno is set to 14. The strange thing is a little later in the address space, I am able to write the values successfully to the address (0x601000) but the address where the needle(0xAABBCCDD) is at 0x6005DF I cannot write there. (But can read obviously because that is where I found the needle)
#include <stdio.h>
#include <iostream>
#include <sys/uio.h>
#include <string>
#include <errno.h>
#include <vector>
using namespace std;
char getHex(char value);
string printHex(unsigned char* buffer, int length);
int getProcessId();
int main()
{
//Get the process ID of the process we want to read and write
int pid = getProcessId();
//Lists of addresses where we find our needle 0xAABBCCDD and the addresses where we simply cannot read
vector<long> needleAddresses;
vector<long> unableToReadAddresses;
unsigned char buf1[1000]; //buffer used to store memory values read from other process
//Number of bytes read, also is -1 if an error has occurred
ssize_t nread;
//Structures used in the process_vm_readv system call
struct iovec local[1];
struct iovec remote[1];
local[0].iov_base = buf1;
local[0].iov_len = 1000;
remote[0].iov_base = (void * ) 0x00000; //start at address 0 and work up
remote[0].iov_len = 1000;
for(int i=0;i<10000;i++)
{
nread = process_vm_readv(pid, local, 1, remote, 1 ,0);
if(nread == -1)
{
//errno is 14 then the problem is "bad address"
if(errno == 14)
unableToReadAddresses.push_back((long)remote[0].iov_base);
}
else
{
cout<<printHex(buf1,local[0].iov_len);
for(int j=0;j<1000-3;j++)
{
if(buf1[j] == 0xDD && buf1[j+1] == 0xCC && buf1[j+2] == 0xBB && buf1[j+3] == 0xAA)
{
needleAddresses.push_back((long)(remote[0].iov_base+j));
}
}
}
remote[0].iov_base += 1000;
}
cout<<"Addresses found at...";
for(int i=0;i<needleAddresses.size();i++)
{
cout<<needleAddresses[i]<<endl;
}
//How many bytes written
int nwrite = 0;
struct iovec local2[1];
struct iovec remote2[1];
unsigned char data[] = {0xEE,0xEE,0xEE,0xEE};
local2[0].iov_base = data;
local2[0].iov_len = 4;
remote2[0].iov_base = (void*)0x601000;
remote2[0].iov_len = 4;
for(int i=0;i<needleAddresses.size();i++)
{
cout<<"Attempting to write "<<printHex(data,4)<<" to address "<<needleAddresses[i]<<endl;
remote2[0].iov_base = (void*)needleAddresses[i];
nwrite = process_vm_writev(pid,local2,1,remote2,1,0);
if(nwrite == -1)
{
cout<<"Error writing to "<<needleAddresses[i]<<endl;
}
else
{
cout<<"Successfully wrote data";
}
}
//For some reason THIS will work
remote2[0].iov_base = (void*)0x601000;
nwrite = process_vm_writev(pid,local2,1,remote2,1,0);
cout<<"Wrote "<<nwrite<<" Bytes to the address "<<0x601000 <<" "<<errno;
return 0;
}
string printHex(unsigned char* buffer, int length)
{
string retval;
char temp;
for(int i=0;i<length;i++)
{
temp = buffer[i];
temp = temp>>4;
temp = temp & 0x0F;
retval += getHex(temp);
temp = buffer[i];
temp = temp & 0x0F;
retval += getHex(temp);
retval += ' ';
}
return retval;
}
char getHex(char value)
{
if(value < 10)
{
return value+'0';
}
else
{
value = value - 10;
return value+'A';
}
}
int getProcessId()
{
int data = 0;
printf("Please enter the process id...");
scanf("%d",&data);
return data;
}
Bottom line is that I cannot modify the repeating printed integer from another process.
I can see at least these problems.
No one guarantees there's 0xAABBCCDD anywhere in the writable memory of the process. The compiler can optimize it away entirely, or put in in a register. One way to enssure a variable will be placed in the main memory is to declare it volatile.
volatile int x = 0xAABBCCDDEE;
No one guarantees there's no 0xAABBCCDD somewhere in the read-only memory of the process. On the contrary, one could be quite certain there is in fact such a value there. Where else could the program possibly obtain it to initialise the variable? The initialisation probably translates to an assembly instruction similar to this
mov eax, 0xAABBCCDD
which, unsurprisingly, contains a bit pattern that matches 0xAABBCCDD. The address 0x6005DF could well be in the .text section. It is extremely unlikely it is on the stack, because stack addresses are typically close to the top of the address space.
The address space of a 64-bit process is huge. There is no hope to traverse it all in a reasonable amount of time. One needs to limit the range of addresses somehow.

Print only changed values without the use of nested if statements

I have four different sensors and store the value they record in a struct. Now I want to print these values every minute. But only the values that changed compared to the last print!
struct SensorData{
uint8_t temp; //temperature
uint8_t pres; //presure
uint8_t hum; //humidity
uint8_t fuel; //fuel
};
I solved this with 15 ifs. But this is kinda hard to read and debug. So I wounder if there is a better and more elegant way to solve this problem.
A table of all posabilitys: 1 if the value is different to the value before and 0 if they are the same:
This is how I solved it with the ifs at the moment:
if(storeData.temp != sensorData.temp && storeData.pres != sensorData.pres && storeData.hum != sensorData.hum && storeData.fuel == sensorData.fuel){
//print case 1: temp,pres,hum
}
else{
if(storeData.temp != sensorData.temp && storeData.pres != sensorData.pres && storeData.hum == sensorData.hum && storeData.fuel != sensorData.fuel){
//print case 2: temp,pres,fuel
}
else{
if(storeData.temp != sensorData.temp && storeData.pres != sensorData.pres && storeData.hum == sensorData.hum && storeData.fuel == sensorData.fuel){
//print case 3: temp,pres,
}else{
if(storeData.temp != sensorData.temp && storeData.pres == sensorData.pres && storeData.hum != sensorData.hum && storeData.fuel != sensorData.fuel){
//print case 4: temp,hum,fuel
}else{
...
Like i mentioned I am looking for a way to solve this more elagant without the use of 15 ifs. Thank you for your help
Your table is just an enumeration of four bits representing the sensors. Hence you may have four comparisons and adjust the bits of a result accordingly:
#include <cstdint>
struct SensorData
{
enum Index
{
Temperature = 3,
Presure = 2,
Humidity = 1,
Fuel = 0
};
std::uint8_t temp; // temperature
std::uint8_t pres; // presure
std::uint8_t hum; // humidity
std::uint8_t fuel; // fuel
};
unsigned compare_sensors(const SensorData& a, const SensorData& b) {
unsigned result = 0;
result |= (a.temp != b.temp) << SensorData::Temperature;
result |= (a.pres != b.pres) << SensorData::Presure;
result |= (a.hum != b.hum) << SensorData::Humidity;
result |= (a.fuel != b.fuel) << SensorData::Fuel;
result = 15 - result; // adjust order
return result;
}
#include <iostream>
int main()
{
SensorData a = {};
SensorData b = {};
b.pres = 255;
b.fuel = 255;
std::cout << "Prssure/Fuel change is case " << compare_sensors(a, b) << ".\n";
}
I would use 4 ifs:
std::string output;
char delimiter = ',';
//Check if data changed
if (storeData.temp != sensorData.temp)
output += std::to_string(sensorData.temp) + delimiter;
if (storeData.pres != sensorData.pres)
output += std::to_string(sensorData.pres) + delimiter;
if (storeData.hum != sensorData.hum)
output += std::to_string(sensorData.hum) + delimiter;
if (storeData.fuel != sensorData.fuel)
output += std::to_string(sensorData.fuel) + delimiter;
//Check if nothing changed
if (output == "")
;//Skip using 'return'?
//Remove 'delimiter' from last case
output.erase(output.length() - 1, 1);
//Send 'output'
//....
You can just use 4 if statements.
Check change in each variable separately, use print statement inside each if block.
As per the constraints mentioned, I don't find any reason why you shouldn't do this.
If you want to print them in a single print statement:
Use 4 if statements as mentioned above, and use 4 variables to hold the values from each if statement. Finally, print it in a single line.
Another method will be to build 'printing string' or 'number' step by step(start with an empty string and build it inside each if statement).
You can use arrays for storing the values, and a loop to check which array elements have changed. Rough outline in C (may contain errors, did not run it through a compiler):
#include <stdbool.h>
char *sensorNames[] = {"temp", "pres", "hum", "fuel"};
uint8_t sensorData[4];
uint8_t storeData[4];
int i;
bool first
while (1) {
get_data(sensorData);
first = true;
for (i=0; i < sizeof(sensorData); i++) {
if (sensorData[i] != storeData[i]) {
// something changed
if (!first) puts(", "); // add a comma if not first item in line
printf("%s: %d -> %d", sensorNames[i], storeData[i], sensorData[i]);
storeData[i] = sensorData[i]; // remember value
first = false;
}
}
if (!first) puts("\n"); // add a line feed if there were any changes
}
Additional advantage: adding a 5th or 6th sensor is trivial :-)

Arrays giving me errors:: String subscript out of range; but everything seems to be in order

I've run into some problems with arrays, one while I was coding in Winsock and one in DirectX 11. In DirectX 11 its actually a texture array that I'm trying to release.
Here's the Winsock problem:
int retval;
retval = recv(hclientSocket, tempBuffer, sizeof(tempBuffer), 0);
if (retval == 0)
{
break; // Connection has been closed
}
else if (retval == SOCKET_ERROR)
{
throw ErrorHandler("Failed to receive due to socket");
}
else
{
Encyrption enc;
string done = enc.Cipher(tempBuffer, retval);
retval = retval * 3;
cout << retval; // it prints out 3
for (int i = 0; i < retval; i++) {
tempBuffer[i] = done[i]; //the error is being pointed here on the 6th time it runs through this, even though its only suppose to go through this 3 times
}
if (send(hclientSocket, tempBuffer, retval, 0) == SOCKET_ERROR)
throw ErrorHandler("Failed to send due to socket");
}
okay most of this code I got from a Winsock tutorial place, but I wanted to try a different encryption method.
Here's the call function, because originally intended to pass and return a string but this time I'm passing a char* and returning a string, which is converted in the above code.
The encryption takes in one character and turns it into a string of 3 for example a would become bca and c would become cba or something that's why I'm multiplying retval by 3. It prints out everything I want it to print out, but its giving an error after its done.
string pass = (string)message;
pass.resize(size);
for (int i = 0; i < size; i++) {
if (!isalnum(pass[i])) {
return "\n";
}
else {
return Cipher(pass);
}
}
Okay so here's the Directx11 problem
I recently learned how to use multitextures utilizing a texture array, and Im having trouble releasing it.
#define TEXTURE_ELEMENTS_COUNT 2
ID3D11ShaderResourceView* m_textures[TEXTURE_ELEMENTS_COUNT];
for (int i = 0; i <= TEXTURE_ELEMENTS_COUNT; i++) {
m_textures[i] = 0;
}
//some code here
for (int i = 1; i <= (TEXTURE_ELEMENTS_COUNT - 1); i++) {
m_textures[i]->Release(); //it throws an exception right here, but I can't figure out why, I tried change `i` to zero, but it still throws it.
m_textures[i] = 0;
}
Thanks for taking the time to look through my code, I have no idea what I'm doing wrong and arrays sometimes throw me off, because its suppose to start at zero and sometimes its hard for me to visualize. Anyway thanks for any input in advance.
Your element count is 2. Therefore you have an element at position 0 and at position 1.
So you have to start your loop at "i = 0" and end your loop after "i = 1". So start from 0 and run to "i < maxCount".
for (int i = 0; i < TEXTURE_ELEMENTS_COUNT; i++) { //FROM 0 TO i<MAXCOUNT
m_textures[i] = 0; // HERE YOU CREATE A NULLPTR TO EVERY SRV
}
//some code here
for (int i = 0; i < (TEXTURE_ELEMENTS_COUNT); i++) { //USE THE SAME LOOP
m_textures[i]->Release(); //IF THERE IS ALREADY A NULLPTR YOU HAVE AN INVALID ACCESS
m_textures[i] = 0;
}
Try to use the Safe_Release function if you use the SDK. Otherwise define it for yourself.
SAFE_RELEASE(m_textures[i])
There is an included test for nullptr:
#ifndef SAFE_RELEASE
#define SAFE_RELEASE(x)
if(x != NULL)
{
x->Release();
x = NULL;
}
#endif
Good Luck

Implementing a simple ring buffer for float values

I am trying to implement a very simple ring buffer, for holding a stream of audio samples in the form of float values.
I want to be able to take a snapshot of the audio input at any one time. I don't need to pop or delete any values, just keep a moving buffer of the last n samples.
I'd like to ask if there are any potential issues with this implementation for my purposes.
class RingBuffer
{
public:
RingBuffer (int bufferSize) : bufferSize (bufferSize), count (0), head (0)
{
buffer = static_cast<float *> (malloc(bufferSize * sizeof(float)));
readBuffer = static_cast<float *> (malloc(bufferSize * sizeof(float)));
}
~RingBuffer ()
{
if (buffer != nullptr) free(buffer);
buffer = nullptr;
if (readBuffer != nullptr) free(readBuffer);
readBuffer = nullptr;
}
void push (float value)
{
if (count < bufferSize && head == 0)
{
buffer[count++] = value;
}
else if (count == bufferSize)
{
// reset head to beginning if reached the end
if (head >= bufferSize)
{
head = 0;
buffer[head] = value;
}
else
{
buffer[head++] = value;
}
}
}
/**
* Return a snapshot of the buffer as a continous array
*/
const float* getSnapshot ()
{
// Set up read buffer as continuous stream
int writeIndex = 0;
for (int i = head; i < count; ++i)
{
readBuffer[writeIndex++] = buffer[i];
}
for (int i = 0; i < head; ++i)
{
readBuffer[writeIndex++] = buffer[i];
}
return readBuffer;
}
private:
int bufferSize, head, count;
float* buffer;
float* readBuffer;
};
Well, there are indeed several issues I can see. Sorry for the bad news :-/
Bugs
There is a bug here: buffer[head] = value;. You don't increment head, so the sample at this position will be lost (overwritten) when the next sample comes in.
In the constructor, you should initialize buffer and readBuffer to nullptr: if one of your mallocs failed, your destructor would try to free
Your 1st loop in getSnapshot is faulty: the end-point should be min(bufferSize,head+count) rather than count
Design issues
As pointed out by mathematician1975, you should allocate your arrays with new float[bufferSize], it's simpler and more readable than mallocs
You should hold each buffer using a std::unique_ptr, so that you would no longer need any destructor (and your code would be much safer)
As you are working on circular buffers, you should use modulo arithmetics, e.g. writeIndex = (writeIndex +1 ) % bufferSize. Your code will be much simpler that way, especially in getSnapshot (one loop instead of two)

Trash on Arduino serial monitor. How to fix it?

i'm working with I2C eeprom and Arduino. For now i tried to create simple keyboard that will start specific functions. I want to write to serial monitor potentiometer value, but i get trash instead it. How to fix it?
My functions:
int *readPot() ///read potentiometer value
{
int tempValue = analogRead(A0);
int *potValue = &tempValue;
return potValue;
}
void keyboardProcess() ///process keyboard input
{
int *potValue = readPot();
for(int i = 0; i < 2; i++)
{
btnReadings[i] = digitalRead(keysPins[i]);
}
if(btnReadings[0] == HIGH)
{
Serial.println("Potentiometer reading:" + *potValue);
}
}
One obvious problem is that you are returning the address to a local variable:
int *readPot() ///read potentiometer value
{
int tempValue = analogRead(A0);
int *potValue = &tempValue;
return potValue;
}
Here, the returned pointer points to the address of tempValue. This ceases to be valid once the function returns. Just use an int:
int readPot() ///read potentiometer value
{
return analogRead(A0);
}
Next, I doubt that this is a valid argument to Serial.println:
Serial.println("Potentiometer reading:" + *potValue);
but this should work:
int potValue = readPot();
Serial.print("Potentiometer reading: ");
Serial.println(potValue);