convert latin1 chars to utf8

This commit is contained in:
MichaelDvP
2025-10-22 17:24:20 +02:00
parent 09c750e622
commit 6fb8fbba18
4 changed files with 101 additions and 13 deletions

View File

@@ -857,7 +857,7 @@ void EMSdevice::publish_value(void * value_p) const {
break; break;
case DeviceValueType::STRING: case DeviceValueType::STRING:
if (Helpers::hasValue((char *)(value_p))) { if (Helpers::hasValue((char *)(value_p))) {
strlcpy(payload, (char *)(value_p), sizeof(payload)); Helpers::render_string(payload, (char *)(value_p), sizeof(payload));
} }
break; break;
default: default:
@@ -967,7 +967,8 @@ void EMSdevice::generate_values_web(JsonObject output, const bool is_dashboard)
// handle TEXT strings // handle TEXT strings
else if (dv.type == DeviceValueType::STRING) { else if (dv.type == DeviceValueType::STRING) {
obj["v"] = (char *)(dv.value_p); char s[55];
obj["v"] = Helpers::render_string(s, (char *)(dv.value_p), sizeof(s));
} }
// handle ENUMs // handle ENUMs
@@ -1079,7 +1080,8 @@ void EMSdevice::generate_values_web_customization(JsonArray output) {
// handle TEXT strings // handle TEXT strings
else if (dv.type == DeviceValueType::STRING) { else if (dv.type == DeviceValueType::STRING) {
obj["v"] = (char *)(dv.value_p); char s[55];
obj["v"] = Helpers::render_string(s, (char *)(dv.value_p), sizeof(s));
} }
// handle ENUMs // handle ENUMs
@@ -1648,7 +1650,8 @@ void EMSdevice::get_value_json(JsonObject json, DeviceValue & dv) {
case DeviceValueType::STRING: case DeviceValueType::STRING:
if (Helpers::hasValue((char *)(dv.value_p))) { if (Helpers::hasValue((char *)(dv.value_p))) {
json[value] = (char *)(dv.value_p); char s[55];
json[value] = Helpers::render_string(s, (char *)(dv.value_p), sizeof(s));
} }
json[type] = ("string"); json[type] = ("string");
break; break;
@@ -1782,7 +1785,8 @@ bool EMSdevice::generate_values(JsonObject output, const int8_t tag_filter, cons
// handle TEXT strings // handle TEXT strings
else if (dv.type == DeviceValueType::STRING) { else if (dv.type == DeviceValueType::STRING) {
json[name] = (char *)(dv.value_p); char s[55];
json[name] = Helpers::render_string(s, (char *)(dv.value_p), sizeof(s));
} }
// handle ENUMs // handle ENUMs

View File

@@ -381,6 +381,91 @@ char * Helpers::render_value(char * result, const uint32_t value, const int8_t f
return result; return result;
} }
// convert special Latin1 characters to UTF8
char * Helpers::render_string(char * result, const char * c, const uint8_t len) {
char * p = result;
while (*c != '\0' && (p - result < len)) {
switch (*c) {
case 0xC4: // Ä
*p = 0xC3;
*(++p) = 0x84;
break;
case 0xD6: // Ö
*p = 0xC3;
*(++p) = 0x96;
break;
case 0xDC: // Ü
*p = 0xC3;
*(++p) = 0x9C;
break;
case 0xDF: // ß
*p = 0xC3;
*(++p) = 0x9F;
break;
case 0xE4: // ä
*p = 0xC3;
*(++p) = 0xA4;
break;
case 0xF6: // ö
*p = 0xC3;
*(++p) = 0xB6;
break;
case 0xFC: // ü
*p = 0xC3;
*(++p) = 0xBC;
break;
default:
*p = (*c & 0x80) ? '?' : *c;
break;
}
c++;
p++;
}
*p = '\0'; // terminat result
return result;
}
char * Helpers::utf8tolatin1(char * result, const char * c, const uint8_t len) {
char * p = result;
while (*c != '\0' && (p - result < len)) {
if (*c == 0xC3) {
c++;
switch (*c) {
case 0x84: // Ä
*p = 0xC4;
break;
case 0x96: // Ö
*p = 0xD6;
break;
case 0x9C: // Ü
*p = 0xDC;
break;
case 0x9F: // ß
*p = 0xDF;
break;
case 0xA4: // ä
*p = 0xE4;
break;
case 0xB6: // ö
*p = 0xF6;
break;
case 0xBC: // ü
*p = 0xFC;
break;
default:
break;
}
} else if (*c > 127) {
*p = '?';
} else {
*p = *c;
}
c++;
p++;
}
*p = '\0'; // terminat result
return result;
}
// creates string of hex values from an array of bytes // creates string of hex values from an array of bytes
std::string Helpers::data_to_hex(const uint8_t * data, const uint8_t length) { std::string Helpers::data_to_hex(const uint8_t * data, const uint8_t length) {
if (length == 0) { if (length == 0) {

View File

@@ -34,6 +34,8 @@ class Helpers {
static char * render_value(char * result, const int16_t value, const int8_t format, const uint8_t fahrenheit = 0); static char * render_value(char * result, const int16_t value, const int8_t format, const uint8_t fahrenheit = 0);
static char * render_value(char * result, const int32_t value, const int8_t format, const uint8_t fahrenheit = 0); static char * render_value(char * result, const int32_t value, const int8_t format, const uint8_t fahrenheit = 0);
static char * render_boolean(char * result, const bool value, const bool dashboard = false); static char * render_boolean(char * result, const bool value, const bool dashboard = false);
static char * render_string(char * result, const char * s, const uint8_t len);
static char * utf8tolatin1(char * result, const char * s, const uint8_t len);
static char * hextoa(char * result, const uint8_t value); static char * hextoa(char * result, const uint8_t value);
static char * hextoa(char * result, const uint16_t value); static char * hextoa(char * result, const uint16_t value);

View File

@@ -145,8 +145,7 @@ void Connect::process_roomThermostatName(std::shared_ptr<const Telegram> telegra
has_update(telegram, rc->icon_, 0); has_update(telegram, rc->icon_, 0);
for (uint8_t i = telegram->offset; i < telegram->message_length + telegram->offset && i < 100; i++) { for (uint8_t i = telegram->offset; i < telegram->message_length + telegram->offset && i < 100; i++) {
if ((i > 1) && (i % 2) == 0) { if ((i > 1) && (i % 2) == 0) {
// replace ISOLatin1 characters with questionmark rc->name_[(i - 2) / 2] = telegram->message_data[i - telegram->offset];
rc->name_[(i - 2) / 2] = telegram->message_data[i - telegram->offset] & 0x80 ? '?' : telegram->message_data[i - telegram->offset];
} }
} }
rc->name_[50] = '\0'; // make sure name is terminated rc->name_[50] = '\0'; // make sure name is terminated
@@ -229,14 +228,12 @@ bool Connect::set_name(const char * value, const int8_t id) {
if (rc == nullptr || value == nullptr || strlen(value) > 50) { if (rc == nullptr || value == nullptr || strlen(value) > 50) {
return false; return false;
} }
uint8_t len = strlen(value) * 2 + 2; Helpers::utf8tolatin1(rc->name_, value, sizeof(rc->name_));
uint8_t len = strlen(rc->name_) * 2 + 2;
uint8_t data[len]; uint8_t data[len];
for (uint8_t i = 0; i < strlen(value) + 1; i++) { // include terminating '\0' for (uint8_t i = 0; i < strlen(rc->name_) + 1; i++) { // include terminating '\0'
data[2 * i] = 0; data[2 * i] = 0;
data[2 * i + 1] = value[i]; data[2 * i + 1] = rc->name_[i];
if (value[i] & 0x80) { // accept only ascii names
return false;
}
} }
uint8_t ofs = 0; uint8_t ofs = 0;
while (len > 0) { while (len > 0) {