httpStringToUtf8() - MappingTable

Ich kann leider in den Beschreibungen nicht genau rausfinden, wie die MappingTable für AsHttp - httpStringToUtf8() aufgebaut wird.

Ich hatte das mal so probiert:
VAR CONSTANT
MappingTable_DE : WSTRING[255] := “Ä=U+00C4;Ö=U+00D6;Ü=U+00DC;ä=U+00E4;ö=U+00F6;ü=U+00FC;ß=U+00DF;€=U+20AC;”;
END_VAR

Aber das scheint nicht zu stimmen…

Hat da vielleicht jemand einen Tipp ?

Hello @Thorsten_Bein,

I can share this with you..

Providing 0, no mapping is applied and only Unicode characters 0-255 are accepted.
You have to provide a WSTRING [0..255] or UINT [0..255] via a pointer, where the Unicode positions are entered.

  • CodePage : ARRAY[0..255] OF UINT := [16#2000,16#2001,16#2002,16#2003,16#2004,16#2005, .. ]

Be aware that after providing the mapping, other characters might not work as expected.

BR Fabian

1 Like

Hallo @fabian.pries ,
thank you for the reply, but i doesn’t understand this.
I have to exchange the Letters: äöüÄÖÜ߀, Space and i don’t know, some others.

Hello,

for the characters ‘ä ö ü Ä Ö Ü ß’ and SPACE, no mapping table is required.
These characters are part of the first 255 characters of the unicode table.
Might put this here as reference: Unicode/UTF-8-Zeichentabelle
Please note, that the Watch / MonitorWindow / Debugger Watch is not able to display UTF8 characters outside of the first 255 characters.
You are not allowed to put the characters in your source code since it is not supporting unicode.
I used the textsystem to present the values to my program.

For the ‘€’ you need the mapping table since its unicode representation is U+20AC.
This means the mapping table we have to provide is the “Currency Symbols” starting at U+20A0.
Extracted from the *.var file:
CodePage : ARRAY[0..255] OF UINT := [16#20A0,16#20A1,16#20A2,16#20A3,16#20A4,16#20A5,16#20A6,16#20A7,16#20A8,16#20A9,16#20AA,16#20AB,16#20AC,16#20AD,16#20AE,16#20AF,240(0)];

Now the functionblock converts the characters from the source using this mapping leading to the following:

Other characters are no longer supported, since the mapping fails.

You might want to switch to the httpUTF8ToWString conversion since there is no mapping table required. From the WSTRING it is easy to convert it back to a string using the WSTRING_TO_STRING function in ST.

BR Fabian

1 Like

Thank you for the new reply @fabian.pries: :grinning_face:

I pull the Information with this (Test-) Code:

PROGRAM _INIT
   RequestHeader.protocol := 'HTTP/1.1';
   RequestHeader.contentType := 'text/html';
   RequestHeader.contentLength := 0;
   RequestHeader.connection := 'Close';
   RequestHeader.keepAlive := 'timeout=5, max=100';
   RequestHeader.userLine[0].name := 'User-agent';
   RequestHeader.userLine[0].value := 'BuR Client';
   RequestHeader.host := 'localhost';

   Client.method             := httpMETHOD_GET;
   Client.option             := httpOPTION_HTTP_11;
   Client.pHost := ADR('nominatim.openstreetmap.org');
   Client.pUri := ADR('search?q=Mönckebergstraße%2090,8500%20Hamburg&format=json&limit=1');
   Client.pRequestHeader := ADR(RequestHeader);
   Client.hostPort         := 443;
   Client.pResponseData     := ADR(jsonString);
   Client.responseDataSize := SIZEOF(jsonString);
END_PROGRAM

PROGRAM _CYCLIC
    Client(enable := TRUE); (* Call httpClient() *)  
   
    IF Client.status <> 0 THEN
      Client.send := FALSE;
    END_IF

    IF Client.httpStatus = 200 THEN
         // place_id
        posStart := FIND(IN1 := jsonString, IN2 := '"place_id":') + LEN('"place_id":');
        restStr := MID(jsonString, LEN(jsonString), posStart);
        posEnd := FIND(IN1 := restStr, IN2 := ',');
        tempStr := MID(restStr, posEnd - 1, 1);
        PlaceData.place_id := STRING_TO_UDINT(tempStr);
       
        // licence
        posStart := FIND(IN1 := jsonString, IN2 := '"licence":"') + LEN('"licence":"');
        restStr := MID(jsonString, LEN(jsonString), posStart);
        posEnd := FIND(IN1 := restStr, IN2 := '"');
        PlaceData.licence := MID(restStr, posEnd - 1, 1);
       
        // osm_type
        posStart := FIND(IN1 := jsonString, IN2 := '"osm_type":"') + LEN('"osm_type":"');
        restStr := MID(jsonString, LEN(jsonString), posStart);
        posEnd := FIND(IN1 := restStr, IN2 := '"');
        PlaceData.osm_type := MID(restStr, posEnd - 1, 1);
       
        // osm_id
        posStart := FIND(IN1 := jsonString, IN2 := '"osm_id":') + LEN('"osm_id":');
        restStr := MID(jsonString, LEN(jsonString), posStart);
        posEnd := FIND(IN1 := restStr, IN2 := ',');
        tempStr := MID(restStr, posEnd - 1, 1);
        PlaceData.osm_id := STRING_TO_UDINT(tempStr);
       
        // lat
        posStart := FIND(IN1 := jsonString, IN2 := '"lat":"') + LEN('"lat":"');
        restStr := MID(jsonString, LEN(jsonString), posStart);
        posEnd := FIND(IN1 := restStr, IN2 := '"');
        tempStr := MID(restStr, posEnd - 1, 1);
        PlaceData.lat := STRING_TO_REAL(tempStr);
       
        // lon
        posStart := FIND(IN1 := jsonString, IN2 := '"lon":"') + LEN('"lon":"');
        restStr := MID(jsonString, LEN(jsonString), posStart);
        posEnd := FIND(IN1 := restStr, IN2 := '"');
        tempStr := MID(restStr, posEnd - 1, 1);
        PlaceData.lon := STRING_TO_REAL(tempStr);
       
        // class
        posStart := FIND(IN1 := jsonString, IN2 := '"class":"') + LEN('"class":"');
        restStr := MID(jsonString, LEN(jsonString), posStart);
        posEnd := FIND(IN1 := restStr, IN2 := '"');
        PlaceData.class := MID(restStr, posEnd - 1, 1);
       
        // type
        posStart := FIND(IN1 := jsonString, IN2 := '"type":"') + LEN('"type":"');
        restStr := MID(jsonString, LEN(jsonString), posStart);
        posEnd := FIND(IN1 := restStr, IN2 := '"');
        PlaceData.type := MID(restStr, posEnd - 1, 1);
       
        // place_rank
        posStart := FIND(IN1 := jsonString, IN2 := '"place_rank":') + LEN('"place_rank":');
        restStr := MID(jsonString, LEN(jsonString), posStart);
        posEnd := FIND(IN1 := restStr, IN2 := ',');
        tempStr := MID(restStr, posEnd - 1, 1);
        PlaceData.place_rank := STRING_TO_INT(tempStr);
       
        // importance
        posStart := FIND(IN1 := jsonString, IN2 := '"importance":') + LEN('"importance":');
        restStr := MID(jsonString, LEN(jsonString), posStart);
        posEnd := FIND(IN1 := restStr, IN2 := ',');
        tempStr := MID(restStr, posEnd - 1, 1);
        PlaceData.importance := STRING_TO_REAL(tempStr);
       
        // addresstype
        posStart := FIND(IN1 := jsonString, IN2 := '"addresstype":"') + LEN('"addresstype":"');
        restStr := MID(jsonString, LEN(jsonString), posStart);
        posEnd := FIND(IN1 := restStr, IN2 := '"');
        PlaceData.addresstype := MID(restStr, posEnd - 1, 1);
       
        // name
        posStart := FIND(IN1 := jsonString, IN2 := '"name":"') + LEN('"name":"');
        restStr := MID(jsonString, LEN(jsonString), posStart);
        posEnd := FIND(IN1 := restStr, IN2 := '"');
        PlaceData.name := MID(restStr, posEnd - 1, 1);
       
        // display_name
        posStart := FIND(IN1 := jsonString, IN2 := '"display_name":"') + LEN('"display_name":"');
        restStr := MID(jsonString, LEN(jsonString), posStart);
        posEnd := FIND(IN1 := restStr, IN2 := '"');
        PlaceData.display_name := MID(restStr, posEnd - 1, 1);
       
        // boundingbox[1] bis [4]
        posStart := FIND(IN1 := jsonString, IN2 := '"boundingbox":["') + LEN('"boundingbox":["');
        restStr := MID(jsonString, LEN(jsonString), posStart);
       
        // boundingbox[1]
        posEnd := FIND(IN1 := restStr, IN2 := '"');
        tempStr := MID(restStr, posEnd - 1, 1);
        PlaceData.boundingbox[1] := STRING_TO_REAL(tempStr);
       
        // boundingbox[2]
        restStr := MID(restStr, LEN(restStr), posEnd + 2);
        posEnd := FIND(IN1 := restStr, IN2 := '"');
        tempStr := MID(restStr, posEnd - 1, 1);
        PlaceData.boundingbox[2] := STRING_TO_REAL(tempStr);
       
        // boundingbox[3]
        restStr := MID(restStr, LEN(restStr), posEnd + 2);
        posEnd := FIND(IN1 := restStr, IN2 := '"');
        tempStr := MID(restStr, posEnd - 1, 1);
        PlaceData.boundingbox[3] := STRING_TO_REAL(tempStr);
       
        // boundingbox[4]
        restStr := MID(restStr, LEN(restStr), posEnd + 2);
        posEnd := FIND(IN1 := restStr, IN2 := '"');
        tempStr := MID(restStr, posEnd - 1, 1);
        PlaceData.boundingbox[4] := STRING_TO_REAL(tempStr);

    ELSE
        // GGF. FEHLERBEHANDLUNG
    END_IF

END_PROGRAM

PROGRAM _EXIT
    (* Release Client instance *)
    Client(enable := 0, send := 0);
END_PROGRAM

If there is a Space inside or a Character like ‘ö’ the result will be fail. Alse the Answer from Webserver with Space or äöü etc. will be wrong… And i have to find out a solution…

Hi there,

looks like you would need to write a method to replace umlauts (ä, ö, ü, ß) with their respective ascii representation: ä = ae, ö=oe, ü=ue, ß=ss
ADR('search?q=Moenckebergstrasse%2090,8500%20Hamburg&format=json&limit=1');
will work just fine


Edit:

	address_in := 'Mönckebergstraße 90,8500 Hamburg';
	FOR i := 1 TO LEN(address_in) DO
		chr := MID(address_in, 1, i);
		IF chr = 'ä' THEN
			brsstrcat(ADR(tmpStr), ADR('ae'));
		ELSIF chr = 'ö' THEN
			brsstrcat(ADR(tmpStr), ADR('oe'));
		ELSIF chr = 'ü' THEN
			brsstrcat(ADR(tmpStr), ADR('ue'));
		ELSIF chr = 'ß' THEN
			brsstrcat(ADR(tmpStr), ADR('ss'));
		ELSE
			brsstrcat(ADR(tmpStr), ADR(chr));
		END_IF
				
	END_FOR
	FB_EncodeUrl(enable := TRUE, pSrc := ADR(tmpStr), pDest := ADR(address_out), destSize := SIZEOF(address_out));

Does the job, FB_EncodeUrl is a FUB httpEncodeUrl() which converts stuff like the spaces for you.

1 Like

I think @michael_w is correct since it issues is not with UTF8 conversion but with the encoding of the URL.

Thank you that is a good idea… :slight_smile: