Table of Contents

24.2.4.1 HTTP client projects

Two HTTP client projects are presented in detail in the following chapters.

Web services can be used with the help of the HTTPClient class, whereby requests are sent to an HTTP server and its response is received. You can find suitable projects for this area of application in the Gambas documentation and in the software farm.

A good description of a web service can be found at www.bitfactory.io/de/blog: Web services make it possible for machines or applications to communicate with each other (M2M communication). They form the interface between client and server and enable the automatic exchange of data between these software systems. They provide their service via the Internet, where software applications can address them.

A web service as a service can be addressed via a unique Uniform Resource Identifier (URI) - similar to the URL of a website. HTTPS (Hypertext Transfer Protocol Secure) is predominantly used as a protocol to secure data exchange. A resource is accessed using the Get, Post and Put methods. The XML and JSON formats are often used as the data format.

24.2.4.1.1 Web service

To use different web services successfully, the following list of key points may be helpful:

The two projects are implemented according to the individual points in this list.

24.2.4.1.2 Project 1 - Weather data

In the first project, the 'Weather data' web service from https://openweathermap.org is used. Under the heading 'Pricing' you will also find the free offer. To use this, you need to create an account on the website with 'Get API key'. In return, you will receive an API key with which you can request current weather data from the server according to the specified conditions. The syntax of the request (query string) is well described at https://openweathermap.org/current.

For the location 'Osterburg' this API request can be used according to the above information:

https://api.openweathermap.org/data/2.5/weather?q=Osterburg,de&lang=de&units=metric&APPID=apikey

and it applies to the Get() method:

In a console, for example, you receive this weather data in response to the above query:

$ curl 'https://api.openweathermap.org/data/2.5/weather?q=Osterburg,de&lang=de&units=metric&APPID=APIKEY'
{"coord":{"lon":11.7667,"lat":52.7833},"weather":[{"id":804,"main":"Clouds","description":"Bedeckt",
"icon":"04d"}],"base":"stations","main":{"temp":6.74,"feels_like":3.71,"temp_min":6.72,"temp_max":8.45,
"pressure":994,"humidity":70,"sea_level":994,"grnd_level":992},"visibility":10000,"wind":{"speed":4.57,
"deg":264,"gust":8.52},"clouds":{"all":100},"dt":1649438025,"sys":{"type":2,"id":2000066,"country":"DE",
sunrise":1649392251,"sunset":1649440704},"timezone":7200,"id":2856639,"name":"Osterburg","cod":200}

For the projects, the use of a web browser can also be recommended for data viewing. This requires neither a command line nor a Gambas program with a Python tool and the output format is freely selectable:

B1

Figure 24.2.4.1.1: Display of selected (formatted) weather data in a web browser

Comment:

It is immediately noticeable in both displays that the weather data is delivered in JSON format - the standard format for weather data from openweathermap.org. If you format this in a suitable way, you can better recognize which data is contained in the response and determine which data should be selected and processed:

{
  "coord": {
    "lon": 11,7667,
    "lat": 52,7833
  },
  "weather": [
    {
      "id": 804,
      "main": "Clouds",
      "description": "Bedeckt",
      "icon": "04d"
    }
  ],
  "base": "stations",
  "main": {
    "temp": 6,74,
    "feels_like": 3,71,
    "temp_min": 6,72,
    "temp_max": 8,45,
    "pressure": 994,
    "humidity": 70,
    "sea_level": 994,
    "grnd_level": 992
  },
  "visibility": 10000,
  "wind": {
    "speed": 4,57,
    "deg": 264,
    "gust": 8,52
  },
  "clouds": {
    "all": 100
  },
  "dt": 1649438025,
  "sys": {
    "type": 2,
    "id": 2000066,
    "country": "DE",
    "sunrise": 1649392251,
    "sunset": 1649440704
  },
  "timezone": 7200,
  "id": 2856639,
  "name": "Osterburg",
  "cod": 200
}

In the project, the (raw) data marked in red is selected and further processed for display. The complete source code is specified and then commented:

[1] ' Gambas class file
[2]
[3] Public iTimeStampGMT As Integer
[4] Public sJSONData As String
[5] Public sAPIKey As String
[6] Public sCity As String
[7] Public hHTTPClientData As HttpClient
[8] Public hHTTPClientIcon As HttpClient
[9] Public hJSONCollection As JSONCollection
[10] Public cWind As Collection
[11] Public cClouds As Collection
[12] Public cMain As Collection
[13] Public cSys As Collection
[14] Public avWeather As Variant[]
[15]
[16] '-- Const APIKEY As String = "YOUR_API_KEY"
[17] '-- Const CITY As String = "YOUR_CITY"
[18] '-- Const COUNTRY As String = "YOUR_COUNTRY"
[19]
[20] Public Sub Form_Open()
[21]
[22]     Dim sMessage, sJSONFormatted As String
[23]
[24]     FMain.Title = ("Current weather data")
[25]     MAdditional.CheckNetwork()
[26]
[27]     sJSONData = GetWeatherData(COUNTRY, CITY, APIKEY)
[28] '-- Print "JSON_DATA —»  "; sJSONData
[29]
[30] '-- MAdditional.IsInstalled("python3")
[31] '-- Shell "echo '" & sJSONData & "' | python3 -m json.tool" To sJSONFormatted
[32] '-- Print sJSONFormatted
[33]
[34]     hJSONCollection = JSON.Decode(sJSONData, True)
[35]     If hJSONCollection["cod"] = 401 Then
[36]        sMessage = "The API key is empty, not activated or incorrect!<hr>"
[37]        sMessage &= "Sie können einen (kostenlosen) API-Key von<br>"
[38]        sMessage &= "<b>https://home.openweathermap.org/users/sign_up</b>"
[39]        sMessage &= "<br>anfordern, um die Wetter-Daten auslesen zu können!"
[40]        Message.Error(sMessage)
[41]        FMain.Close()
[42]     Else If hJSONCollection["cod"] = 404 Then
[43]        sMessage = "The specified city '" & CITY & "' was not found!<hr>"
[44]        sMessage &= "▸ The name of the city is wrong or<br>"
[45]        sMessage &= "▸ the city ID is incorrect or<br>"
[46]        sMessage &= "▸ the format of the API key request is incorrect."
[47]        Message.Error(sMessage)
[48]        FMain.Close()
[49]     Else
[50]        EditAndShowWeatherData()
[51]     Endif
[52]
[53] End
[54]
[55] Public Function GetWeatherData(argCountry As String, argCity As String, argAPIKey As String) As String
[56]
[57]     Dim sURL, sQuery, sURI, sRawData As String
[58]
[59]     sURL = "https://api.openweathermap.org/data/2.5/weather"
[60]     sQuery = "?"
[61]     sQuery &= "q=" & argCity & "," & argCountry
[62]     sQuery &= "&" & "lang=" & argCountry
[63]     sQuery &= "&" & "units=metric"
[64]     sQuery &= "&" & "APPID=" & argAPIKey
[65]     sURI = sURL & sQuery
[66] '-- Print sURI
[67]
[68]     hHTTPClientData = New HttpClient As "HTTPClientData"
[69]     hHTTPClientData.URL = sURI
[70]     hHTTPClientData.Async = False
[71]     hHTTPClientData.Timeout = 10
[72]
[73]     hHTTPClientData.Get()
[74]
[75]     If Lof(hHTTPClientData) Then sRawData = Read #hHTTPClientData, Lof(hHTTPClientData)
[76]     Return sRawData
[77]
[78] End
[79]
[80] Public Sub EditAndShowWeatherData()
[81]
[82]     Dim iLocalTimeStamp As Integer
[83]     Dim sCityName, sDate, sIconID, sDay, sDateDMY, sTime As String
[84]     Dim dDate As Date
[85]
[86]     sCityName = hJSONCollection["name"]
[87]
[88]     iLocalTimeStamp = hJSONCollection["dt"]
[89]     dDate = TimeStampToDate(iLocalTimeStamp)
[90]     sDay = Format$(dDate, "dddd")
[91]     sDateDMY = Format$(dDate, "d. mmmm yyyy")
[92]     sTime = Format$(dDate, "hh:nn") & " Uhr"
[93]     sDate = sDay & ", " & sDateDMY & " - " & sTime
[94]
[95]     FMain.Text = ("Current weather data") & (" for ") & sCityName & ": " & sDate
[96] '-- -------------------------------------------------------------------------------
[97]
[98]     cWind = hJSONCollection["wind"]
[99]     txbWindSpeed.Text = "   " & Round(cWind["speed"], -1)
[100]     txbWindDirection.Text = "   " & Round(cWind["deg"], 0)
[101] '-- ------------------------------------------------------------------------------
[102]
[103]     txbTemperature.Text = "   " & Round(hJSONCollection["main"]["temp"], -1)
[104]     txbPressure.Text = "   " & hJSONCollection["main"]["pressure"]
[105]     txbHumidity.Text = "   " & hJSONCollection["main"]["humidity"]
[106] '-- ------------------------------------------------------------------------------
[107]
[108]     cClouds = hJSONCollection["clouds"]
[109]     txbCloudiness.Text = "   " & cClouds["all"]
[110] '-- ------------------------------------------------------------------------------
[111]
[112]     cSys = hJSONCollection["sys"]
[113]     txbSunRise.Text = "   " & Format(TimeStampToDate(cSys["sunrise"]), "hh:nn")
[114]     txbSunSet.Text = "   " & Format(TimeStampToDate(cSys["sunset"]), "hh:nn")
[115] '-- ------------------------------------------------------------------------------
[116]     avWeather = hJSONCollection["weather"]
[117]     lblDescription.Text = "   " & avWeather[0]["description"]
[118]     sIconID = avWeather[0]["icon"]
[119] '-- Print sIconID
[120]
[121]     GetAndStoreWeatherIcon(sIconID)
[122]
[123]     pboxWeatherIcon.Picture = Picture[Application.Path &/ "WeatherIcon/weathericon.png"]
[124]
[125] End
[126]
[127] Public Sub GetAndStoreWeatherIcon(argIconID As String)
[128]
[129]     Dim sURIIcon As String
[130]
[131]     sURIIcon = "https://openweathermap.org/img/w/" & argIconID & ".png"
[132] '-- sURIIcon = "https://openweathermap.org/img/wn/" & argIconID & "@2x.png" '-- Alternative
[133]
[134]     hHTTPClientIcon = New HttpClient As "HTTPClientIcon"
[135]     hHTTPClientIcon.URL = sURIIcon
[136]     hHTTPClientIcon.Async = False
[137]     hHTTPClientIcon.Timeout = 10
[138]
[139]     hHTTPClientIcon.Get([], Application.Path &/ "WeatherIcon/weathericon.png")
[140]
[141] End
[142]
[143] Public Sub HTTPClientData_Error()
[144]     Message.Error("<b><font color='DarkRed'>DATA: ERROR</b></font><hr>" & hHTTPClientData.ErrorText)
[145] End
[146]
[147] Public Sub HTTPClientIcon_Error()
[148]     Message.Error("<b><font color='DarkRed'>ICON: ERROR</b></font><hr>" & hHTTPClientIcon.ErrorText)
[149] End
[150]
[151] Public Sub Form_Close()
[152]     If hHTTPClientData Then hHTTPClientData.Close()
[153]     If hHTTPClientIcon Then hHTTPClientIcon.Close()
[154]
[155]     If Exist(Application.Path &/ "WeatherIcon/weathericon.png") Then
[156]        Try Kill Application.Path &/ "WeatherIcon/weathericon.png"
[157]     Endif
[158]
[159] End
[160]
[161] Private Function TimeStampToDate(argTimeStamp As Integer) As Date
[162]     Return DateAdd(CDate("1/1/1970"), gb.Second, argTimeStamp)
[163] End

The result is impressive:

B2

Figure 24.2.4.1.2: Display of selected weather data

Comment:

B3

Figure 24.2.4.1.3: Display of error 1

B4

Figure 24.2.4.1.4: Display error 2

Download

Chapter & Projects

download