B4R Question Strange issue using custom types

max123

Active Member
Licensed User
Hi all,

I need to mantain this data globally inside a code module and accessible on main module:
B4X:
Type KeyValuePair(key() As Byte, val() As Byte)
Public field(10) As KeyValuePair
And write/read like this:
B4X:
Dim Title() As Byte = "This is the title"
Dim Message() As Byte = "This is the message"

'write
field(2).key = "title".GetBytes
field(2).val = Title
field(3).key = "message".GetBytes
field(3).val = Message

'read
Dim notificationTitle() As Byte = field(2).val
Dim notificationMessage() As Byte = field(3).val

Currently I write and read fields, but after a bit if I read just returns void byte array or strange characters, so can't get data I wrote and Log show me strange data.

I have same issue even with keys and values as strings:
B4X:
Type KeyValuePair(key As String, val As String)
Public field(10) As KeyValuePair
B4X:
Dim Title As String = "This is the title"
Dim Message As String = "This is the message"

'write
field(2).key = "title"
field(2).val = Title
field(3).key = "message"
field(3).val = Message

'read
Dim notificationTitle As String = field(2).val
Dim notificationMessage As String = field(3).val

Any suggestion on this?

Many thanks
 
Last edited:

Erel

B4X founder
Staff member
Licensed User
This is not really strange. Such structure cannot work (at least not without code that manages its memory usage).

You need to think where the data is stored.
Example:
B4X:
Sub SomeSub
 field(2).val = Array As Byte(1, 2, 3)
End Sub

The array of bytes was created on the stack. The pointer was copied to the global structure. The stack data is only valid until the sub ends. So you remain with a global array that points to a random point in the stack.

The only way for it to work is by using a global buffer, copying the data to the buffer and maintaining the structure pointers. My guess is that there are simpler ways to implement what you need.
 
Upvote 0

max123

Active Member
Licensed User
Yes, but I can do it with C++

I need to convert my FirebaseCloudMessaging library to B4R.

I already have this library working on many platforms, but no B4R, works on:
  • B4J UI (Desktop)
  • B4J_NONUI (Desktop, Raspberry PI via cmd line)
  • B4A
  • Arduino IDE 3 different libraries (ESP8266, Arduino + Ethernet Shield, Arduino + Wifi Shield)
I use like this field[3].key, field[3].val to be confortable to final end users, so simple to write and read fields and to mantain same syntax for all platforms.

Please, can point me to right direction with small code example? Or I can't release my library for B4R platform.

Many thanks

This is a C++ working code:
B4X:
typedef struct{
  String key;
  String value;
} keyValuePair;

keyValuePair field[30];

field[3].key = "FromMe"; field[3].value = String("ESP8266 ChipID: " + (String)ESP.getChipId());
field[4].key = "Title"; field[4].value =  "Report house automation state.";         // message title
field[5].key = "Message"; field[5].value = "Hi User,\n\n"                           // message body
                                           "this is your message sent from ESP8266 board,\n"
                                           "the user pressed the button on digital pin 2 to ground. \n\n"
                                           "As you can see, using this library, now we can send multilines notification \n"
                                           "messages from ESP8266 or Arduino boards, to Android devices.\n\n"
                                           "Best regards.\n\n"
                                           "Your development board";                              
field[6].key = "Data1"; field[6].value = String("ADC value: " + (String)analogRead(A0));   // notify ADC value
String D3_State = (digitalRead(0) == LOW) ? "LOW" : "HIGH";
String D4_State = (digitalRead(2) == LOW) ? "LOW" : "HIGH";
field[7].key = "Data2"; field[7].value = String("GPIO0: " + D3_State);   // notify GPIO0-D3 state
field[8].key = "Data3"; field[8].value = String("GPIO2: " + D4_State);   // notify GPIO2-D4 state
field[9].key = "Data4"; field[9].value = 23520000;
field[10].key = "Data5"; field[10].value = "This is data5 value in String format";
field[11].key = "Data6"; field[11].value = String("1356.2345 * 642.789 = " + (String)(1356.2345 * 642.789));
field[12].key = "Data7"; field[12].value = String("Latitude:  " + String(45.89098098,10));
field[13].key = "Data8"; field[13].value = String("Longitude:  " + String(54.99576546,10));
field[14].key = "Light"; field[14].value = "true";    // we can specify if want the devive to blink led on notifications. By default true if no called.
field[15].key = "Sound"; field[15].value = "true";    // we can specify if want the device to play sound on notifications. By default true if no called.
field[16].key = "Vibrate"; field[16].value = "true";  // we can specify if want the device to vibrate on notifications. By default true if no called.   

field[17].key = "SpeakLanguage"; field[17].value = "en";    // we can send voice notifications using Speak commands
field[18].key = "SpeakCountry"; field[18].value = "US";
field[19].key = "SpeakRate"; field[19].value = .8;
field[20].key = "SpeakPitch"; field[20].value = 1.0;
String msgToSpeak = field[5].value;
msgToSpeak.replace("\n", " ");   // we replace all \n with spaces to remove voice pause on every line of message
msgToSpeak.replace("ESP8266", "E S P 8 2 6 6");
field[21].key = "Speak"; field[21].value = msgToSpeak;

field[22].key = "Duration"; field[22].value = 25000;    // we can set the message popup duration measured in milliseconds (by default 3000ms = 3 secs)
// fcm.field[23].key = "Insistent"; fcm.field[23].value = "true";   // we can use insistent notification, this play notify sound repeatedly until the user
                                                                    // press on notification message, good for alarms

String Topics[] = {"general","mouse","cat"};
success = sendMessage(Topics, 3);
Serial.println((success == true) ? "Message sent successfully."
                                 : "Unable to send message"
 
Last edited:
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Arduino String class uses dynamic memory (malloc). This is considered bad practice when programming microcontrollers as the memory is limited and it can easily lead to memory fragmentation which will eventually crash your program.
B4R doesn't use dynamic memory. You can preallocate memory as done in GlobalStore or Queue and Stack modules (uploaded today) and carefully manage the memory yourself.

I'm not familiar with your FirebaseCloudMessaging library, but it is very simple for developers to send push messages with the various HttpUtils2 libraries.
 
Upvote 0

max123

Active Member
Licensed User
Yes Erel, it is very simple to send, but need to manage HttpUtils2, with my library the user no need to initialize and use HttpJob, just one line can send a notification message, then in addiction to this I developed an Android app with B4A (free source code on library package) that supports custom fields, speak messages and other things.

I will try your last modules, today I've already tried Queue module.

Many thanks
 
Upvote 0
Top