nanopb encode always size 0 (but no encode failure) - nanopb

I have a very simple proto:
syntax = "proto2";
message TestMessage {
optional int32 val = 1;
optional string msg = 2; // I set max size to 40 in options, so TestMessage_size is defined.
}
...and I have the following code in my main loop for an arduino program:
TestMessage test_msg = TestMessage_init_zero;
test_msg.val = 123;
// Print message length.
size_t msg_length;
bool get_msg_length = pb_get_encoded_size(&msg_length, TestMessage_fields, &test_msg);
Serial.println(msg_length);
// Encode and print message.
uint8_t testbuffer[TestMessage_size];
pb_ostream_t teststream = pb_ostream_from_buffer(testbuffer, sizeof(testbuffer));
bool teststatus = pb_encode(&teststream, TestMessage_fields, &test_msg);
if (!teststatus) {
Serial.println("Failed to encode test message.");
return;
}
Serial.print("Message: ");
Serial.println(teststream.bytes_written);
for(size_t i = 0; i < teststream.bytes_written; i++){
Serial.print(testbuffer[i], OCT);
}
Serial.println("testbuffer flushed");
For some reason I can print test_msg.val and it will show 123 but when I try to encode it (following examples like this one) it always is empty / has size 0.
Is this a configuration issue with nanopb? I wonder if the encode method requires something that I am not using?

For optional fields, you also have to set the has_field:
TestMessage test_msg = TestMessage_init_zero;
test_msg.has_val = true;
test_msg.val = 123;
That's because otherwise there is no way to know if the optional field has been set or not. C++ handles this via setter methods, but C doesn't have those.

Related

Problem receiving data from bluetooth at very high speeds

I'm using the flutter_bluetooth_serial 0.4.0 package, it has a listen function that receives a function that returns the reading of the sending of a string (List Uint8), but for my case I need to carry out the communication at a very high speed, and when that it happens it does not understand where the end of a string is and it joins it until it overflows with 230 bytes and shows it as if it were a single string, I tried to solve this in several ways, but I can only receive the complete string (18 bytes) when I reduce the transmission speed, I've tried using some characters like '\n', to see if it understands where a string ends and another begins, but I wasn't successful either. If I could read character by character for me it would also solve it, because the messages have a sending pattern.
Do you have an idea how I could be solving this? Some package that works better than this one for this purpose or some way to determine where the end of the string is. I thank!
Here is the code snippet I get the data:
_dataSubscription = connection.input!.listen(_onDataReceived);
void _onDataReceived(Uint8List data) {
print('Data incoming: ${ascii.decode(data)}');
// Allocate buffer for parsed data
var backspacesCounter = 0;
for (var byte in data) {
if (byte == 8 || byte == 127) backspacesCounter++;
}
var buffer = Uint8List(data.length - backspacesCounter);
var bufferIndex = buffer.length;
// Apply backspace control character
backspacesCounter = 0;
for (int i = data.length - 1; i >= 0; i--) {
if (data[i] == 8 || data[i] == 127) {
backspacesCounter++;
} else {
if (backspacesCounter > 0) {
backspacesCounter--;
} else {
buffer[--bufferIndex] = data[i];
}
}
// print(backspacesCounter);
// print(buffer);
// print(bufferIndex);
}
I've tried using some characters like '\n', to see if it understands where a string ends and another begins, read character per character, but doesn't have function to do this.

Sending strings to BPF Map Space and printing them out

I have a small txt file that I would like to write to BPF here. Here is what my python code looks like for BPF but I am unable to print out anything as of now. I keep ending up with a Failed to load program: Invalid argument with a bunch of register errors. As of now my string basically says hello, world, hi
BPF_ARRAY(lookupTable, char, 512);
int helloworld2(void *ctx)
{
//print the values in the lookup table
#pragma clang loop unroll(full)
for (int i = 0; i < 512; i++) {
char *key = lookupTable.lookup(&i);
if (key) {
bpf_trace_printk("%s\n", key);
}
}
return 0;
}
Here is the Python code:
b = BPF(src_file="hello.c")
lookupTable = b["lookupTable"]
#add hello.csv to the lookupTable array
f = open("hello.csv","r")
file_contents = f.read()
#append file contents to the lookupTable array
b_string1 = file_contents.encode('utf-8')
b_string1 = ctypes.create_string_buffer(b_string1)
lookupTable[0] = b_string1
f.close()
b.attach_kprobe(event=b.get_syscall_fnname("clone"), fn_name="helloworld2")
b.trace_print()
I have the error linked in this pastebin since it's so long:
BPF Error
One notable error is the mention of infinite loop detected which is something I would need to check out.
The issue is that i is passed by pointer in bpf_map_lookup_elem, so the compiler can't actually unroll the loop (from its point of view, i may not linearly increase).
Using an intermediate variable is enough to fix this:
BPF_ARRAY(lookupTable, char, 512);
#define MAX_LENGTH 1
int helloworld2(void *ctx)
{
//print the values in the lookup table
#pragma clang loop unroll(full)
for (int i = 0; i < 1; i++) {
int k = i;
char *key = lookupTable.lookup(&k);
if (key) {
bpf_trace_printk("%s\n", key);
}
}
return 0;
}

Binary operator < cannot be applied to Clong in Swift

I am trying to implement the following code in swift. But my i variable refuse to talk to my MAXADDRS. It says binary operator < cannot be applied to Clong in Swift. If I use CInt the problem goes away, but then I get an error on the variable i when assiginin theAddr = ip_addrs[i]
InitAddresses();
GetIPAddresses();
GetHWAddresses();
var i = CLong()
var deviceIP = NSString()
for (i=0; i < MAXADDRS; ++i)
{
var localHost = 0x7F000001; // 127.0.0.1
var theAddr = CLong()
theAddr = ip_addrs[i]
if (theAddr == 0) {return}
if (theAddr == localHost){continue}
NSLog("Name: %s MAC: %s IP: %s\n", if_names[i], hw_addrs[i], ip_names[i]);
//decided what adapter you want details for
if (strncmp(if_names[i], "en", 2) == 0)
{
NSLog("Adapter en has a IP of %s", ip_names[i]);
}
}
// Do any additional setup after loading the view, typically from a nib.
}
The MAXADDRS it intends to compare relates to the following OBC header
Source files here
http://www.chrisandtennille.com/code/IPAddress.h
http://www.chrisandtennille.com/code/IPAddress.c
My bridging header
#include "IPAddress.h"
#include "IPAddress.c"
#define MAXADDRS 32
is imported to Swift as
public var MAXADDRS: Int32 { get }
On the other hand, CLong is an alias for Int ("The C 'long' type.")
Therefore you need to convert all values to a common type. Since
array subscripting requires an Int index, converting MAXADDRS
to Int might be the easiest solution:
var i = 0 // Int
for (i=0; i < Int(MAXADDRS); ++i) {
}
or more simply:
for i in 0 ..< Int(MAXADDRS) {
}

How to convert a string to a variant in jscript under wsh?

I need to append a string of text to the end of a binary file.
This is what I'm trying:
inStream = WScript.CreateObject("ADODB.Stream") ;
inStream.type = 1 ;
inStream.open() ;
inStream.LoadFromFile('test.bin') ;
outStream = WScript.CreateObject("ADODB.Stream") ;
outStream.type = 1 ;
outStream.open() ;
outStream.write( inStream.read() ) ;
outStream.write( "\nCONTENT AT THE END" ) ; // this gives an error
outStream.SaveToFile('test2.bin',2) ;
The reported error is "wrong argument".
The documentation of that method says the argument must be of type variant.
How can I convert a string to a variant?
The solution is to use auxiliary ADODB.Stream instance .copyTo() method.
var inStream = WScript.CreateObject('ADODB.Stream'); // source stream
inStream.Type = 1; // adTypeBinary
inStream.Open();
inStream.LoadFromFile('C:\\Test\\src.bin');
var outStream = WScript.CreateObject('ADODB.Stream'); // target stream
outStream.Type = 1; // adTypeBinary
outStream.Open();
outStream.Write(inStream.read());
inStream.Close();
var bufStream = WScript.CreateObject('ADODB.Stream'); // auxiliary stream
bufStream.Type = 2; // adTypeText
bufStream.Open();
bufStream.WriteText('\nCONTENT AT THE END'); // strings held as Unicode in memory
bufStream.Position = 2; // skip BOM bytes FF FE
bufStream.CopyTo(outStream); // append to the end of target stream
bufStream.Close();
outStream.SaveToFile('C:\\Test\\dst.bin', 2);
outStream.Close();

error: lvalue required

// getline : empty string array and max length as input
// stores input stream to array and return its length
#include<stdio.h>
#define LENGTH 100
int getline1(char* , int );
int main(){
char *s;
int i;
s=(char*)malloc(LENGTH*sizeof(char));
i=getline1(s,LENGTH);
printf("%s %d",s,i);
return 0;
}
int getline1(char *s, int lim){
int c ,i;
i = 0;
printf("%u",s);
while(--lim >= 0 && (c=getchar()) != EOF && c = '\n'){
*(s+i)=c; //error : lvalue required
i++;
}
if(c=='\n'){
*(s+i)=c;
i++;
}
*(s+i)='\0';
return i;
}
I get the error mentioned in the mentioned line can any body tell whats wrong. code works fine if i use arrays.getline : empty string array and max length as input
stores input stream to array and return its length
It cannot assign the value to the *(s+i) expression. Understandably so since you dereference it, leaving the value at that position (which is a constant).
Try using s[i] instead.