Convert byte string to normal string in C++ - c++

I have the following situation:
I'm actually trying to read streamdata from a server into a label in Visual Studio:
//Receive a reply from the server
if((recv_size = recv(ConnectSocket , server_reply , 2000 , 0)) == SOCKET_ERROR){
MessageBox::Show("recv failed","");
//exit(1);
}
this->label1->Text = Convert::ToString(server_reply[0]);
example result:
ANAG;FCA;11:20:27;NL0010877643;FIAT CHRYSLER AUTO;16.85;0.0;0
when I get it into my program, I have it like:
657865...
which I think is the byte representation of the corresponding characters (eg.: 65 = A, 78 = N, etc.).
Question is: How do I convert these bytecodes into a normal string of characters?
The server seems to be sending byte data
Thanks in advance

You just need to create a string from it.
#include <iostream>
#include <string>
using namespace std;
int main()
{
char byteArray[] = { 65, 78, 65, 71 }; // .... your input
std::string s(byteArray, sizeof(byteArray));
cout << s;
return 0;
}

Related

C - Extern struct

I'm using structure to process NMEA messages, but I don't know what, something goes wrong when processing it. So, I have NMEA_parse.h:
/* GPRMC */
#define TIME 2U
#define LAT 4U
#define LON 6U
#define SPD 8U
#define ANG 9U
#define DATE 10U
extern struct gprmc{
char time[10];
char latitude[10];
char longitude[10];
char speed[10];
char angle[10];
char date[10];
}gprmc_datas;
NMEA_parse.c:
#include "NMEA_parse.h"
struct gprmc gprmc_datas;
static void fill_data (char* param_in)
{
uint8_t i = 0U;
char* trunk;
char trunk_datas[20U][10U];
trunk = strtok(param_in, ",");
while(trunk != NULL)
{
i++;
if(i > 20) { i = 0; }
strcpy(trunk_datas[i],trunk);
trunk = strtok (NULL, ",");
}
if(memcmp(trunk_datas[1U],"GPRMC",6U) == 0U)
{
strcpy(gprmc_datas.time,trunk_datas[TIME]);
strcpy(gprmc_datas.latitude,trunk_datas[LAT]);
strcpy(gprmc_datas.longitude,trunk_datas[LON]);
strcpy(gprmc_datas.date,trunk_datas[DATE]);
strcpy(gprmc_datas.time,trunk_datas[TIME]);
}
}
main.c:
#include <stdio.h>
#include "NMEA_parse.h"
int main(void)
{
char *message = "$GPRMC,182127.00,A,4753.47678,N,02022.20259,E,0.837,,161019,,,A*7C\r\n";
char *mes = "$GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A";
proc_sentence(message);
printf("\ntime: %s\n", gprmc_datas.time);
printf("latitude: %s\n", gprmc_datas.latitude);
printf("longitude: %s\n", gprmc_datas.longitude);
}
proc_sentence function pass the data to fill_data(), if the message valid (checksum, etc)
When I'm using the mes as input, everything is correct, but when I switch to message, some abnormality is shown, because the result is the following:
time: 182127.00
latitude: 4753.4767802022.2025E
longitude: 02022.2025E
Do you have any idea what goes wrong?
If you change latitude[10] in the struct into latitude [12], the string "message" can also be used.
Unlike almost every other SO question about the use of scanf, yours is actually a problem that cries out for it. After all, if a machine wrote it, a machine can read it, right?
Using C's concatenation of string literals, I got pretty close to filling the struct with a single function:
int n = sscanf( message,
"%[^,],"
"%[^,],"
"%*[^,],%[^,],"
"%*[^,],%[^,],"
"%*[^,],%[^,],"
"%[^,],"
"%[^,],",
label,
gprmc.time,
gprmc.latitude,
gprmc.longitude,
gprmc.speed,
gprmc.angle,
gprmc.date );
This makes use of the little-used regex specifier, where we look for non-commas %[^] separated by commas. The %*[^] specifies to skip the field.

Adafruit Fona 3g Library; How exactly does this work?

I am trying to send a packet to a server over 3g and TCP connection. Below is a link to the .cpp and .h file I have found:
https://os.mbed.com/users/Nels885/code/Adafruit_FONA_3G/
More specifically, I am really confused on how TCPSend works under the Adafruit_FONA_3G class. I am trying to implement it but my code seems to get stuck at packet[0] = 0; under function bool Adafruit_FONA_3G::TCPsend(char *packet).
I have tried commenting out packet[0] = 0; and the code runs all the way through. I have also tried initializing char* packet[32]; before packet[0] = 0; and the code runs all the way through. I am assuming the function is not detecting the packet input.
Here is the specific function from the .cpp file:
bool Adafruit_FONA_3G::TCPsend(char *packet)
{
if (strlen(packet) > 0)
{
mySerial.printf("%s", packet);
//mySerial.printf("%s\r\n", packet);
readline();
packet[0] = 0;
return true;
}
else
return false;
}
Here is my main code:
#include "mbed.h"
#include "Adafruit_FONA.h"
#define FONA_RST D4
#define FONA_TX D1
#define FONA_RX D0
#define FONA_RI D7 //not used
char replybuffer[255];
Adafruit_FONA_3G fona(FONA_TX, FONA_RX, FONA_RST, FONA_RI);
Serial pc(USBTX, USBRX);
int main()
{
fona.TCPinitialize();
char Timeout[21];
fona.getTCPtimeout(Timeout);
char * Server = "52.14.99.26";
uint16_t Port = 10001;
fona.TCPconnect(Server,Port);
char *Packet = "Pick Up %";
fona.TCPsend(Packet);
fona.TCPclose();
}
Adafruit_FONA_3G::TCPsend() assumes that you pass it a writable buffer. You're passing a read-only buffer. So, replace
char *Packet = "Pick Up %";
with
char Packet[] = "Pick Up %";
The problem is really that your compiler allows you to initialize writable pointers with read-only values. This is a shortcoming of your compiler.

Lcd displaying old data with new data

I have interfaced a programmable xbee with a 16x2 character LCD. I transmit wireless frames with the the help of another xbee and display it on the recieving xbee.
The problem arises when I send two wireless frames one after another.
Consider that I send 24 characters in the first frame, that will be displayed normally as it should be(with a random extra character at the end of the display which I dont know why)
The problem arises when I send a second frame which is smaller than the first frame for eg. of 6 characters. The LCD displays the the 6 characters but adds further 18 characters that were there in the first frame after the 6 characters.
The display looks likes this:
Frame1 display : This is a check message.
Frame2 display : Hello!s a check message. (original message : Hello!)
I tried clearall() lcd function between frames at different positions but it does not work. I also different things you see in the code but they dont work.
The code currently looks like this;
enter code here
#include <xbee_config.h>
#include <types.h>
#include <string.h>
#include <ctype.h>
#define char_lcd_writ_str(a) char_lcd_writ(a, strlen(a))
static uint8_t test_stage = 0;
static uint8_t test_stage_done = 0;
static const char str[] = "abcdefghijklmnopqrstuvwxyz012345";
#if defined(RTC_ENABLE_PERIODIC_TASK)
void rtc_periodic_task(void)
{
test_stage++;
if (test_stage == 8)
test_stage = 0;
test_stage_done = 0;
}
#endif
#ifdef ENABLE_XBEE_HANDLE_RX
int xbee_transparent_rx(const wpan_envelope_t FAR *envelope, void FAR *context)
{
int c=0;
char addrbuf[ADDR64_STRING_LENGTH];
char_lcd_init(CHAR_LCD_CFG);
char_lcd_clear();
addr64_format(addrbuf, &envelope->ieee_address);
sys_watchdog_reset();
while (c<4)
{
char_lcd_writ_str(envelope->payload);
delay_ticks(2*HZ);
char_lcd_clear();
char_lcd_goto_xy(0, 0);
c++;
}
}
#endif
void main(void)
{
uint8_t i, j;
sys_hw_init();
sys_xbee_init();
sys_app_banner();
char_lcd_init(CHAR_LCD_CFG);
for (;;) {
if (!test_stage_done) {
switch (test_stage) {
case 0:
char_lcd_goto_xy(0, 0);
char_lcd_writ_str("All working fine");
break;
}
test_stage_done = 1;
}
sys_watchdog_reset();
sys_xbee_tick();
}
}
ssize_t char_lcd_writ(const uint8_t *data, size_t len)
{
size_t written = 0;
while (written < len) {
char_lcd_putchar(*data++);
written++;
if ( written == 32 || written == 64 || written == 96 || written == 128 || written == 160 || written == 192 )
{
delay_ticks(2*HZ);
char_lcd_clear();
char_lcd_goto_xy(0, 0);
}
}
while (written < len) {
written = 0;
memset(*data++, '\0', len);
written++;
}
return (ssize_t)written;
}
Could be as simple as envelope->payload not being null-terminated and actually containing those extra characters if you go beyond the payload length specified in the envelope. Try using your char_lcd_writ() function with the payload's length instead of char_lcd_writ_str() which will use strlen() to find the length.

Writing a typed array to a subprocess stdin isn't working correctly

I'm sending some data to a subprocess's stdin. The data comes from a typed array. If the Data from the typed array is changed, sending to the subprocess is truncated. I've a small example showing this problem.
The Subprocess is a simple C++ App. Reading all Data from stdin and output the number of read bytes to stdout. (C++ App is compiled with x86_64-w64-mingw32-g++ test.cpp) Code Of the Subprocess in c++:
#include <iostream>
#include <limits>
int main(int argc, char **args) {
std::cin.ignore(std::numeric_limits<std::streamsize>::max());
std::cout << std::cin.gcount() << std::flush;
return 0;
}
The nodejs App will call cyclic the exe. Passes 128 Bytes of Data to the stdin and checks if the response (from stdout of the childprocess) is the String "128". Code of the nodejs App:
const execFile = require('child_process').execFile;
var data = new Float64Array(16);
var generateError = true;
generateError && setInterval(_ => {
for (var i = 0; i < 16; i++) {
data[i] = Math.random();
}
}, 1);
setInterval(_ => {
var subproc = execFile('a.exe', [ '-c' ], (error, stdout, stderr) => {
if (stdout.trim() !== '128' || error) {
console.log('ERR: ' + stdout);
} else {
console.log('OK');
}
});
subproc.stdin.write(Buffer.from(data.buffer)) || console.log('Use drain'); // Write Binary Data (128Byte)
subproc.stdin.end();
}, 100);
This gives me some output like:
OK
OK
OK
OK
OK
OK
ERR: 69
ERR: 114
OK
OK
OK
ERR: 41
What makes me crazy:
When I set the generateError to false, everything works as expected.
When I use "wc.exe -c" (Word/Bytecount Tool from cgywin) everything works as expected, even when generateError is set to true.
So the Question: Whats wrong? C++ Code? Node Code? Is it not allowed to change the buffer after passing it to subproc.stdin.write? If not allowed: Why works the variant with wc.exe?
Under Windows there are different type of streams: binary streams and some sorts of text streams. Changing the input stream of the c++ App to a binary stream will solve the problem. (I guess that wc.exe will use the input stream as a binary stream. This would explain why the variant with wc.exe is working):
#include <iostream>
#include <limits>
#include <fcntl.h>
#include <io.h>
int main(int argc, char **args) {
_setmode(_fileno(stdin), _O_BINARY);
std::cin.ignore(std::numeric_limits<std::streamsize>::max());
std::cout << std::cin.gcount() << std::flush;
return 0;
}
See also Read binary data from std::cin

Trouble with boolean value returning twice (Arduino)

I'm working with a project that involves a Arduino UNO card and JAVA. The Arduino UNO would be the client and JAVA the server.
The problem is that my verify function is returning 0 twice when it's false, why does it do that and if true it returns 1 and 0 which is weird.
I just want it to return once, and not false false like the example here:
#include <SPI.h>
#include <Ethernet.h>
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0F, 0x50, 0x35 };
IPAddress arduino(192,168,0,12);
IPAddress server(192,168,0,15);
EthernetClient client;
String username[] = {"Admin","Skut","Arbek","Kubda"};
String password[] = {"12344","stra","124ssgra","!#ยค%"};
String readString;
void setup() {
Serial.begin(9600);
Ethernet.begin(mac,arduino);
Serial.println("Connecting...");
if (client.connect(server, 8888)){
Serial.println("Connected to Server");
}
else {
Serial.println("Connecting failed");
}
}
boolean verify(String firstText, String secondText){
for(int i = 0; i <= 3 ; i++){
if((username[i] == firstText ) && (password[i] == secondText)){
return true;
}
}
return false;
}
void clientRead() {
while (client.available()) {
//delay(10);
if (client.available() >0) {
char c = client.read();
readString += c;
}
}
}
void loop(){
if (client.available() > 0){
readString = "";
clientRead();
Serial.println(readString);
int n = readString.length();
int commaIndex = readString.indexOf(';');
int lastIndex = readString.lastIndexOf(n);
String firstText = readString.substring(0, commaIndex);
String secondText = readString.substring(commaIndex + 1 , lastIndex);
Serial.println(firstText);
Serial.println(secondText);
Serial.println(verify(firstText, secondText));
}
if (!client.connected()){
Serial.println("Server disconnected!");
client.stop();
client.flush();
while(true);
}
}
I've tried sending ( Admin;12344 ) to the arduino from the server and this is what I get:
Connecting...
Connected to Server
Admin;12344
Admin
12344
1
0
while (client.available())
is not reliable. It might terminate earlier than what you expect depending on the relative speed of the device. Most probably you are getting partial data on the first try and another batch on second one (probably only \n). Instead of relying on available, use a marker to end the data.
The problem lies with what is being sent. If you look at the hex values of your output you will notice 7 CRLF between the 1 and 0. One of those belongs to the println of 1. The next 6 is exactly the output of 3 println. What is being printed 3 times? One CRLF, thats all. Because of the way you do the substrings all three outputs:
Serial.println(readString);
Serial.println(firstText);
Serial.println(secondText);
will print the very same CRLF along with their respective CRLF of the println.
So your answer is that you are sending a CRLF at the end of the line which is sent to the Arduino. Consider Cem Kalyoncu's answer about how to properly handle the reading and also do not send a CRLF to the Arduino at the end of the authentication line and you will most probably be fine.
I also suggest you read up on why not to use String in arduino. It is a world of memory and space problems you bring forth if you keep on using it.
Instead of if((username[i] == firstText ) && (password[i] == secondText)), try to use if(( firstText.equals(username[i]) ) && ( secondText.equals(password[i]) ))
I think the == don't compare the value of strings.