Send 4bytes floating point value through tcp From Dart to C++ - c++

I have a trouble with sending 4 bytes double value through tcp socket from Dart client to c++ server.
Below is flutter(Dart) code.
class DataPacket extends object{
String message = "some";
int ID = 1;
double x = 1.38;
#override
String toString() {
String value = message;
value += getCharCodeStringFromInt(ID);
value += getCharCodeStringFromDouble(x);
return value;
}
Uint8List _getInt16LittleEndianBytes(int value) =>
Uint8List(2)..buffer.asByteData().setInt16(0, value, Endian.little);
String getCharCodeStringFromInt(int value){
Uint8List message_id_list = _getInt16LittleEndianBytes(value);
return getCharCodeStringFromUint8List(message_id_list);
}
String getCharCodeStringFromDouble(double value) {
// List<double> temp = List<double>() ;
// temp.add(value);
// Float32List floatlist = Float32List.fromList(temp);
// Uint8List list = Uint8List.view(floatlist.buffer);
// Uint8List list = binaryCodec.encode(value);
Uint8List list = Uint8List(4)..buffer.asByteData().setFloat32(0, value);
print("Uint8List from double : ${list}");
print("Uint8List length from double : ${list.length}");
print("CharCodeString from double Length :
${getCharCodeStringFromUint8List(list).length}");
return getCharCodeStringFromUint8List(list);
}
String getCharCodeStringFromUint8List(Uint8List list){
String charCodeString = "";
list.forEach((charCode) => charCodeString += String.fromCharCode(charCode));
return charCodeString;
}
}
//Some Class
void sendMessage(){
print(DataPacket().toString().length);
List<int> data = _socket.encoding.encode(DataPacket().toString());
//utf8.encode(DataPacket().toString());
print(data.length);
_socket.add(data);
}
I can parse String and int in c++ by memcpy.
but can't double value.
When I checked the contents of Byte Data and Length,
Uint8List that was gotten from double has lengthened in encoding method of socket.
I mean, length of Uint8List from double was 4 before encoded.
However length of return value(List) becomes 7 after encoding.
so print result of DataPacket().toString().length and data.length is different each other.
I can't parse 7 bytes of float in c++..
Commented lines are ways I tried.
Is there any way?
Thank you.

The problem isn't how you are encoding the float as bytes, but rather what you do to it next trying to convert it to a string.
If you want to send 4 bytes through the socket (assuming you are referring to a dart:io Socket), just use the add method.
Socket s;
var floatValue = 1.38;
var bytes = Uint8List(4)
..buffer.asByteData().setFloat32(0, floatValue, Endian.little);
print(bytes); // prints [215, 163, 176, 63]
s.add(bytes);
In this example, you've started with the target byte array and then used it asByteData to set one value. This is a good way to build up a struct of mixed types - ints, floats, etc. If you just need to convert an array of floats to bytes you can do it slightly more simply with:
var bytes = Float32List.fromList([floatValue]).buffer.asUint8List();
I'm not sure you really need to be doing anything with strings. Is what you really want:
Socket s;
var message = 'some';
var id = 1;
var x = 1.38;
s.add(ascii.encode(message)); // choose the appropriate codec: ascii, utf8
s.add(Int16List.fromList([id]).buffer.asUint8List());
s.add(Float32List.fromList([x]).buffer.asUint8List());
// rather than adding each in turn, you could also form a longer byte array
// of the 3 elements and add that

Related

Serialize array char, int8_t and int16_t in protobuf for C++

In protobuf, how would you serialize an array of char's, (u)int8_t or (u)int16_t? Should the message look like this:
message ArrayWithNotSupportedTypes
{
int32 type = 1;
string byte_stream = 2;
}
where type could store some unique id of the element type stored in the array.
And then the byte_stream is populated with contents of an array, where values are of one of the types above?
Also,I have seen that there is a type called bytes in protobuf, that is translated to an std::string in the corresponding grpc.pb.h files. Is there any advantage of choosing bytes ahead of string?
If the array size is not big, you can waste some space to make the interface simpler.
message ArrayWithNotSupportedTypes
{
repeated int32 data = 1; // one data entry per one element
}
If the array size is big, you can use your solution to indicate the type
message ArrayWithNotSupportedTypes
{
enum Type {
CHAR = 0;
INT8 = 1;
INT16 = 2;
}
optional Type type = 1;
optional bytes data = 2;
}
bytes and string are similar in C++: why protocol buffer bytes is string in c++?
Reference: https://developers.google.com/protocol-buffers/docs/proto3#scalar

c++: Run a function 8 times and add each answer to an array or JSON it

I'm super new to C++ and am trying to build a json file that contains x0...x7 of the files that gets parsed from a pre-defined function so that it can compose a JSON string to give to R. so that it can open a socket to R and send this piece of JSON to it.
however, im kinda stuck here, here is what i have:
std::map<std::string,std::string>::const_iterator qIter;
std::string variable;
std::map<string,string> mymap;
variable = "x";
for (int i=1,i<=7,i++){
float variable+i = ( (qIter = request.getQuery().find(variable+i))
== request.getQuery().end()
)
? 0.0
: atof(qIter->second.c_str());
if ( !isLegalNumber(request.getQuery(),variable+i,variable+i) )
{
strcpy(filePath,"yourErrorFilename.html");
}
else
{
// I want to add the x0 or xn variable here into a json
// The value is now in variable 'x'of something
}
}
Any insights appreciated.
edit: here's my isLegalNumber() method
bool isLegalNumber (const std::map<std::string,std::string>&
map,
const std::string& varName,
float& value
)
{
float temp;
char* cPtr;
std::map<std::string,std::string>::const_iterator
iter = map.find(varName);
if (iter == map.end())
return(false);
temp = strtod(iter->second.c_str(),&cPtr);
if ( (*cPtr != '\0') || (cPtr == iter->second.c_str()) )
return(false);
value = temp;
return(true);
}
im trying to convert a string/ dictionary into a json,
the first question would be how to add it into a dictionary,
and second, how to convert that dictionary into JSON.
basically i want the json to look like
{
x1: value of x1,
x2: value of x2,
....
x7: value of x7
}
I'm not totally clear what you're trying to do in your example code. Specifically, I don't know what the string value variable is used for. I'm guessing you actually want to define an array of floats. You can also skip the first step where you're setting the value to either 0.0 or atof(...) since your isLegalNumber function sets it later anyway. e.g.
float x[8] = {0.0f};
// Note that arrays in C++ are zero-indexed, so your iteration variable should start at 0
for (int i=0; i<=7; i++) {
std::string varName = "x";
varName.push_back(std::to_string(i+1)); // Append the index
if ( !isLegalNumber(request.getQuery(), varName, x[i] ) {
// Error
} else {
// Add to JSON structure
}
}
Once you've got that sorted out, for working with JSON in C++, I would strongly recommend using an existing open-source library such as JSON for Modern C++, rather than rolling your own implementation. This will make it much easier to build the JSON structure you need and ensure that it is properly formatted.
That library has quite thorough documentation, and it allows you to define JSON structures using very similar syntax to the actual JSON you're trying to write, e.g.
json j2 = {
{"pi", 3.141},
{"happy", true},
{"name", "Niels"},
// ...
};
Or in your specific case, define json j; outside the loop, and then in your if case you can do:
j[varName] = x[i];
And then you can convert it to a string using std::string s = j.dump();.

Writing Char to Arduino EEPROM

I'm having a problem passing data to EEPROM. It seemed to be not accepting a char variable. I'm doing exactly what is told here: https://www.arduino.cc/en/Reference/EEPROMPut
So my this is my Object Structure
struct DeviceDataObject {
bool flag;
char data[20];
char data2[20];
int rate1;
int rate2;
int rate3;
};
So as I test with:
int RATES[3] = {300, 1500, 3600};
DeviceDataObject new_data = {true, "Data1Sample", "Sample2", RATES[0], RATES[1], RATES[2]};
WRITE_Device(new_data);
Here's my writing function
void WRITE_Device(DeviceDataObject data) {
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
int eeAddress = 0;
float f = 123.456f; //Variable to store in EEPROM.
EEPROM.put(eeAddress, f);
eeAddress += sizeof(float); //Move address to the next byte after float 'f'.
EEPROM.put(eeAddress, data);
//Serial.println("Memory Data Updated");
}
Everything seemed to be OK. But if I replace "Data1Sample" and "Sample2" with a variable, EEPROM's data seemed to be changed in incorrectly.
void ChangeValue(String value) {
int RATES[3] = {300, 1500, 3600};
char charBuf[20];
value.toCharArray(charBuf, 20); //Convert to char
DeviceDataObject new_data = {true, "", {charBuf}, RATES[0], RATES[1], RATES[2]}
WRITE_Device(new_data);
}
What could be the mistake?
Looks like a pointer problem, try this
void ChangeValue(String value) {
int RATES[3] = {300, 1500, 3600};
DeviceDataObject new_data = {true, "", "", RATES[0], RATES[1], RATES[2]}
value.toCharArray(new_data.data2, 20); //Convert to char
WRITE_Device(new_data);
}
(you were creating a string where the first character was the pointer to your stack variable charBuf, rather than copying the string)
A somewhat long-winded approach would be to write each element of the structure to EEPROM individually. The code would look something like this and should allow you to isolate any issues more effectively.
ee_address = 0;
EEPROM.put(ee_address, new_data.flag);
ee_address += sizeof(new_data.flag); // Update address to store next variable
EEPROM.put(ee_address, new_data.data);
ee_address += sizeof(new_data.data);
EEPROM.put(ee_address, new_data.data2);
ee_address += sizeof(rawdata.data2);
EEPROM.put(ee_address, new_data.rate1);
ee_address += sizeof(new_data.rate1);
EEPROM.put(ee_address, new_data.rate2);
ee_address += sizeof(new_data.rate2);
EEPROM.put(ee_address, new_data.rate3);
ee_address += sizeof(rawdata.rate3);
This will make it easier to troubleshoot whether variables are not being written to EEPROM correctly or whether the issue stems from something else.
This is the approach I typically take when storing structures which I have defined to the EEPROM, as it gives more control when retrieving this information from the EEPROM at a later point.
I'll be the first to admit this is perhaps not the most elegant solution, but it should help address your issues.

How to return a byte array of unknown size from method

I have a class that parses some incoming serial data. After the parsing a method should return a byte array with some of the parsed data. The incoming data is of unknown length so my return array will always be different.
So far my method allocates an array bigger than what I need to return and fills it up with my data bytes and I keep an index so that I know how much data I put in the byte array. My problem is that I don't know how to return this from an instance method.
void HEXParser::getParsedData()
{
byte data[HEX_PARSER_MAX_DATA_SIZE];
int dataIndex = 0;
// fetch data, do stuff
// etc, etc...
data[dataIndex] = incomingByte;
_dataIndex++;
// At the very end of the method I know that all the bytes I need to return
// are stored in data, and the data size is dataIndex - 1
}
On other languages this is trivial to do but I'm not very proficient in C++ and I'm completely stuck.
Thanks!
You are working on a microcontroller with just a little bit of RAM. You need to carefully evaluate if "unknown length" also implies unbounded length. You cannot deal with unbounded length. Your best approach for reliable operation is to use fixed buffers setup for the maximum size.
A common pattern for this type of action is to pass the buffer to the function, and return what has been used. Your function would then look much like many of the C character string functions:
const size_t HEX_PARSER_MAX_DATA_SIZE = 20;
byte data[HEX_PARSER_MAX_DATA_SIZE];
n = oHexP.getParsedData(data, HEX_PARSER_MAX_DATA_SIZE);
int HEXParser::getParsedData(byte* data, size_t sizeData)
{
int dataIndex = 0;
// fetch data, do stuff
// etc, etc...
data[dataIndex] = incomingByte;
dataIndex++;
if (dataIndex >= sizeData) {
// stop
}
// At the very end of the method I know that all the bytes I need to return
// are stored in data, and the data size is dataIndex - 1
return dataIndex;
}

Allocate chunk of memory for array of structs

I need an array of this struct allocated in one solid chunk of memory. The length of "char *extension" and "char *type" are not known at compile time.
struct MIMETYPE
{
char *extension;
char *type;
};
If I used the "new" operator to initialize each element by itself, the memory may be scattered. This is how I tried to allocate a single contiguous block of memory for it:
//numTypes = total elements of array
//maxExtension and maxType are the needed lengths for the (char*) in the struct
//std::string ext, type;
unsigned int size = (maxExtension+1 + maxType+1) * numTypes;
mimeTypes = (MIMETYPE*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
But, when I try to load the data in like this, the data is all out of order and scattered when I try to access it later.
for(unsigned int i = 0; i < numTypes; i++)
{
//get data from file
getline(fin, line);
stringstream parser.str(line);
parser >> ext >> type;
//point the pointers at a spot in the memory that I allocated
mimeTypes[i].extension = (char*)(&mimeTypes[i]);
mimeTypes[i].type = (char*)((&mimeTypes[i]) + maxExtension);
//copy the data into the elements
strcpy(mimeTypes[i].extension, ext.c_str());
strcpy(mimeTypes[i].type, type.c_str());
}
can anyone help me out?
EDIT:
unsigned int size = (maxExtension+1 + maxType+1);
mimeTypes = (MIMETYPE*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size * numTypes);
for(unsigned int i = 0; i < numTypes; i++)
strcpy((char*)(mimeTypes + (i*size)), ext.c_str());
strcpy((char*)(mimeTypes + (i*size) + (maxExtension+1)), type.c_str());
You mix 2 allocation:
1) manage array of MIMETYPE and
2) manage array of characters
May be (I don't really understand your objectives):
struct MIMETYPE
{
char extension[const_ofmaxExtension];
char type[maxType];
};
would be better to allocate linear items in form:
new MIMETYPE[numTypes];
I'll put aside the point that this is premature optimization (and that you ought to just use std::string, std::vector, etc), since others have already stated that.
The fundamental problem I'm seeing is that you're using the same memory for both the MIMETYPE structs and the strings that they'll point to. No matter how you allocate it, a pointer itself and the data it points to cannot occupy the exact same place in memory.
Lets say you needed an array of 3 types and had MIMETYPE* mimeTypes pointing to the memory you allocated for them.
That means you're treating that memory as if it contains:
8 bytes: mime type 0
8 bytes: mime type 1
8 bytes: mime type 2
Now, consider what you're doing in this next line of code:
mimeTypes[i].extension = (char*)(&mimeTypes[i]);
extension is being set to point to the same location in memory as the MIMETYPE struct itself. That is not going to work. When subsequent code writes to the location that extension points to, it overwrites the MIMETYPE structs.
Similarly, this code:
strcpy((char*)(mimeTypes + (i*size)), ext.c_str());
is writing the string data in the same memory that you otherwise want to MIMETYPE structs to occupy.
If you really want store all the necessary memory in one contiguous space, then doing so is a bit more complicated. You would need to allocate a block of memory to contain the MIMETYPE array at the start of it, and then the string data afterwards.
As an example, lets say you need 3 types. Lets also say the max length for an extension string (maxExtension) is 3 and the max length for a type string (maxType) is 10. In this case, your block of memory needs to be laid out as:
8 bytes: mime type 0
8 bytes: mime type 1
8 bytes: mime type 2
4 bytes: extension string 0
11 bytes: type string 0
4 bytes: extension string 1
11 bytes: type string 1
4 bytes: extension string 2
11 bytes: type string 2
So to allocate, setup, and fill it all correctly you would want to do something like:
unsigned int mimeTypeStringsSize = (maxExtension+1 + maxType+1);
unsigned int totalSize = (sizeof(MIMETYPE) + mimeTypeStringsSize) * numTypes;
char* data = (char*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, totalSize);
MIMETYPE* mimeTypes = (MIMETYPE*)data;
char* stringData = data + (sizeof(MIMETYPE) * numTypes);
for(unsigned int i = 0; i < numTypes; i++)
{
//get data from file
getline(fin, line);
stringstream parser.str(line);
parser >> ext >> type;
// set pointers to proper locations
mimeTypes[i].extension = stringData + (mimeTypeStringsSize * i);
mimeTypes[i].type = stringData + (mimeTypeStringsSize * i) + maxExtension+1;
//copy the data into the elements
strcpy(mimeTypes[i].extension, ext.c_str());
strcpy(mimeTypes[i].type, type.c_str());
}
(Note: I've based my byte layout explanations on typical behavior of 32-bit code. 64-bit code would have more space used for the pointers, but the principle is the same. Furthermore, the actual code I've written here should work regardless of 32/64-bit differences.)
What you need to do is get a garbage collector and manage the heap. A simple collector using RAII for object destruction is not that difficult to write. That way, you can simply allocate off the collector and know that it's going to be contiguous. However, you should really, REALLY profile before determining that this is a serious problem for you. When that happens, you can typedef many std types like string and stringstream to use your custom allocator, meaning that you can go back to just std::string instead of the C-style string horrors you have there.
You really have to know the length of extension and type in order to allocate MIMETYPEs contiguously (if "contiguously" means that extension and type are actually allocated within the object). Since you say that the length of extension and type are not known at compile time, you cannot do this in an array or a vector (the overall length of a vector can be set and changed at runtime, but the size of the individual elements must be known at compile time, and you can't know that size without knowing the length of extension and type).
I would personally recommend using a vector of MIMETYPEs, and making the extension and type fields both strings. You're requirements sound suspiciously like premature optimization guided by a gut feeling that dereferencing pointers is slow, especially if the pointers cause cache misses. I wouldn't worry about that until you have actual data that reading these fields is an actual bottleneck.
However, I can think of a possible "solution": you can allocate the extension and type strings inside the MIMETYPE object when they are shorter than a particular threshold and allocate them dynamically otherwise:
#include <algorithm>
#include <cstring>
#include <new>
template<size_t Threshold> class Kinda_contig_string {
char contiguous_buffer[Threshold];
char* value;
public:
Kinda_contig_string() : value(NULL) { }
Kinda_contig_string(const char* s)
{
size_t length = std::strlen(s);
if (s < Threshold) {
value = contiguous_buffer;
}
else {
value = new char[length];
}
std::strcpy(value, s);
}
void set(const char* s)
{
size_t length = std::strlen(s);
if (length < Threshold && value == contiguous_buffer) {
// simple case, both old and new string fit in contiguous_buffer
// and value points to contiguous_buffer
std::strcpy(contiguous_buffer, s);
return;
}
if (length >= Threshold && value == contiguous_buffer) {
// old string fit in contiguous_buffer, new string does not
value = new char[length];
std::strcpy(value, s);
return;
}
if (length < Threshold && value != contiguous_buffer) {
// old string did not fit in contiguous_buffer, but new string does
std::strcpy(contiguous_buffer, s);
delete[] value;
value = contiguous_buffer;
return;
}
// old and new strings both too long to fit in extension_buffer
// provide strong exception guarantee
char* temp_buffer = new char[length];
std::strcpy(temp_buffer, s);
std::swap(temp_buffer, value);
delete[] temp_buffer;
return;
}
const char* get() const
{
return value;
}
}
class MIMETYPE {
Kinda_contig_string<16> extension;
Kinda_contig_string<64> type;
public:
const char* get_extension() const
{
return extension.get();
}
const char* get_type() const
{
return type.get();
}
void set_extension(const char* e)
{
extension.set(e);
}
// t must be NULL terminated
void set_type(const char* t)
{
type.set(t);
}
MIMETYPE() : extension(), type() { }
MIMETYPE(const char* e, const char* t) : extension(e), type(t) { }
};
I really can't endorse this without feeling guilty.
Add one byte in between strings... extension and type are not \0-terminated the way do it.
here you allocate allowing for an extra \0 - OK
unsigned int size = (maxExtension+1 + maxType+1) * numTypes;
mimeTypes = (MIMETYPE*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
here you don't leave any room for extension's ending \0 (if string len == maxExtension)
//point the pointers at a spot in the memory that I allocated
mimeTypes[i].extension = (char*)(&mimeTypes[i]);
mimeTypes[i].type = (char*)((&mimeTypes[i]) + maxExtension);
instead i think it should be
mimeTypes[i].type = (char*)((&mimeTypes[i]) + maxExtension + 1);