As mentioned by chrisl in a comment, your best option is to to use the
regular WriteStr() method to print variables, and use WriteStrU() to
print Unicode string constants. For example:
float R = 12.34; // dummy resistance value.
genie.WriteStr(0, "R = ");
genie.WriteStr(0, R);
genie.WriteStrU(0, (uint16_t *) u" Ω");
should print:
R = 12.34 Ω
Note the use of the u string prefix to write UTF-16-encoded strings in
the source code.
Edit: You wrote
the WriteStr always replaces the text inside a String object instead
of adding on.
This makes things more complicated. The only option I see is to format
the whole message as UTF-16 beforehand, then send it with WriteStrU().
Here is a class that does simple UTF-16 formatting. It inherits from the
Print class, meaning you can print() to it anything you could print
to Serial. In addition, it can print UTF-16 strings:
template <size_t max_length>
class UTF16Writer : public Print {
public:
// Convert ASCII to UTF-16.
size_t write(uint8_t c) {
if (length >= max_length)
return 0; // buffer full
buffer[length++] = c;
buffer[length] = 0; // terminate string
return 1;
}
// Record UTF-16 data.
size_t print(const char16_t *s) {
size_t chars_written = 0;
while (*s && length < max_length) {
buffer[length++] = *s++;
chars_written++;
}
buffer[length] = 0; // terminate string
return chars_written;
}
using Print::print;
uint16_t buffer[max_length + 1];
private:
size_t length = 0;
};
The template parameter is the capacity of the buffer. Once you have
written the whole message as UTF-16 using this class, you can pass its
buffer member to WriteStrU(). For example:
float R = 12.34; // dummy resistance value.
UTF16Writer<16> writer;
writer.print("R = ");
writer.print(R);
writer.print(u" Ω");
genie.WriteStrU(0, writer.buffer);
Note: Do not forget the u prefix in the Unicode string, otherwise
the bytes of the string (UTF-8 in the source) would be interpreted as
latin1 by UTF16Writer::print(const char*). A message such as "martine écrit en UTF-8" would then be displayed as “martine écrit en UTF-8”.