0

Yet the url generated is exactly the same as the one generated by the NetAtmo documentation : This is the url generated by my program :

https://api.netatmo.com/api/getmeasure?device_id=70%3Aee%3A50%3A12%3A4d%3A12&module_id=02%3A00%3A00%3A12%3A86%3A30&scale=30min&type=temperature&date_begin=1690468462&date_end=1690469662&limit=1024&optimize=false&real_time=true

This the Netamo from the page https://dev.netatmo.com/apidocumentation/weather#getmeasure :

https://api.netatmo.com/api/getmeasure?device_id=70%3Aee%3A50%3A12%3A4d%3A12&module_id=02%3A00%3A00%3A12%3A86%3A30&scale=30min&type=temperature&date_begin=1690465917&date_end=1690467117&limit=1024&optimize=false&real_time=true

And this command is working:

curl -X GET "https://api.netatmo.com/api/getmeasure?device_id=70%3Aee%3A50%3A12%3A4d%3A12&scale=30min&type=temperature&date_begin=1690468462&date_end=1690469662&limit=1024&optimize=false&real_time=true" -H "accept: application/json" -H "Authorization: Bearer xxxxxxxxxxxxxxxxxxxxxx|xxxxxxxxxxxxxxxxxxxxxxxx"

the bearer is changed. What to do on httpClient.Get to have the same ? It seems that application/json is already there, however the authorization is not necessary it seems to me.

if I replace the URL with the one I generate and the CURL command works, it is therefore in the HttpClient.AsyncGet that there is a problem

The code is :

Public Class ClassHttpPostNetAtmo

  ReadOnly myClientHttp As HttpClient
  ReadOnly parametres As New Dictionary(Of String, String)
  Dim builder As UriBuilder
  Dim query As Specialized.NameValueCollection
  ReadOnly dateUnix As New DateTime(1970, 1, 1, 0, 0, 0, 0)
  Public Sub New()
    myClientHttp = New HttpClient()
  End Sub

  Public Sub ClearPostParametres()
    parametres.Clear()
  End Sub

  Public Sub AddPostParametre(ByVal key As String, ByVal value As String)
    parametres.Add(key, value)
  End Sub

  Public Async Function PostHttp(ByVal RequestUri As String) As Task(Of String)
    Dim content As New FormUrlEncodedContent(parametres)
    Dim response As HttpResponseMessage = Await myClientHttp.PostAsync(RequestUri, content)
    Dim responseString As String = Await response.Content.ReadAsStringAsync()
    Return responseString
  End Function

  Public Async Function RefreshToken(ByVal vRequestUri As String, ByVal vRefresh_token As String, ByVal vClient_id As String, ByVal vClient_secret As String) As Task(Of Dictionary(Of String, String))
    ClearPostParametres()
    AddPostParametre("grant_type", "refresh_token")
    AddPostParametre("refresh_token", vRefresh_token)
    AddPostParametre("client_id", vClient_id)
    AddPostParametre("client_secret", vClient_secret)
    Dim responseString As String = Await PostHttp(String.Concat(vRequestUri, "/oauth2/token"))
    Dim paramRep As New Dictionary(Of String, String)
    Dim str() As String = responseString.Replace("{", "").Replace("}", "").Split(",")
    For Each strPar As String In str
      Dim par() As String = strPar.Split(":")
      paramRep.Add(par(0).Replace("""", ""), par(1).Replace("""", ""))
    Next

    Return paramRep
  End Function


  Public Sub ClearGetParameter(ByVal vRequestUri As String)
    builder = New UriBuilder(vRequestUri) With {
      .Port = -1
    }
    query = HttpUtility.ParseQueryString(builder.Query)
  End Sub

  Public Sub AddGetParametre(ByVal key As String, ByVal value As String)
    If value IsNot Nothing Then
      If key = "type" Then
        Dim tvalue() As String = value.Split(",")
        For Each strVal As String In tvalue
          query.Add(key, strVal)
        Next
      Else
        query.Add(key, value)
      End If
    End If
  End Sub

  Public Async Function GetHttp() As Task(Of String)
    builder.Query = query.ToString()
    Dim url As String = builder.ToString()
    Dim response As HttpResponseMessage = Await myClientHttp.GetAsync(url)
    If response.ReasonPhrase = "ok" Then
      Dim responseString As String = Await response.Content.ReadAsStringAsync()
      Return responseString
    Else
      Throw New Exception(String.Concat("Erreur Http GET : ", response.ReasonPhrase, " Status code = ", response.StatusCode))
    End If

  End Function

  Public Async Function GetWeatherData(ByVal vRequestUri As String, ByVal vDeviceId As String, vDateBegin As DateTime, ByVal vDateEnd As DateTime, Optional ByVal vModuleId As String = Nothing, Optional ByVal vScale As String = "30min", Optional ByVal vType As String = "temperature", Optional ByVal vLimit As String = "1024", Optional ByVal vOptimize As String = "false", Optional ByVal vRealTime As String = "true") As Task
    ClearGetParameter(String.Concat(vRequestUri, "/api/getmeasure"))
    AddGetParametre("device_id", vDeviceId)
    AddGetParametre("module_id", vModuleId)
    AddGetParametre("scale", vScale)
    AddGetParametre("type", vType)
    AddGetParametre("date_begin", CType(((vDateBegin.Subtract(dateUnix)).TotalSeconds), Integer).ToString())
    AddGetParametre("date_end", CType(((vDateEnd.Subtract(dateUnix)).TotalSeconds), Integer).ToString())
    AddGetParametre("limit", vLimit)
    AddGetParametre("optimize", vOptimize)
    AddGetParametre("real_time", vRealTime)
    Dim responseString As String = Await GetHttp()

  End Function

End Class

The call is here :

Imports ClassLibraryHttpPostNetAtmo
Imports LibraryDivers
Public Class FrmTestMyLibraryNetAtmo
  Dim ClientId As String
  Dim ClientSecret As String
  Dim myNetAtmo As New ClassHttpPostNetAtmo
  Dim AccessToken As String
  Dim RefreshToken As String
  Private Sub FrmTestMyLibraryNetAtmo_Shown(sender As Object, e As EventArgs) Handles MyBase.Shown

  End Sub

  Private Async Sub BtnTest_Click(sender As Object, e As EventArgs) Handles BtnTest.Click
    If (My.Settings.AccessToken Is Nothing OrElse My.Settings.AccessToken = "") Or
       (My.Settings.RefreshToken Is Nothing OrElse My.Settings.RefreshToken = "") Or
       (My.Settings.DateRefreshToken < Now) Then
      ClientId = ClassDivers.Decode(My.Settings.ClientId, My.Settings.EncodeNumber)
      ClientSecret = ClassDivers.Decode(My.Settings.ClientSecret, My.Settings.EncodeNumber)

      Dim par As Dictionary(Of String, String) = Await myNetAtmo.RefreshToken(My.Settings.RequestUri, My.Settings.RefreshToken, ClientId, ClientSecret)
      AccessToken = par("access_token")
      RefreshToken = par("refresh_token")
      My.Settings.AccessToken = par("access_token")
      My.Settings.RefreshToken = par("refresh_token")
      My.Settings.DateRefreshToken = Now.AddSeconds(par("expire_in")).AddMinutes(-10)
      My.Settings.Save()
    End If
    Await myNetAtmo.GetWeatherData(My.Settings.RequestUri, "70:ee:50:12:4d:12", Now.AddMinutes(-20), Now, vModuleId:="02:00:00:12:86:30")
  End Sub
End Class

Well I'm 74 years old and I've never done any web, I don't even know the difference between HTTP GET and HTTP POST. The HTTP POST to get a refresh token worked fine. The HTTP POST on the other hand gets stuck. Well I doubt that this request on NetAtmo has little chance of succeeding but as I don't know how to make it work, I try anyway.

I tried to do an HTTP POST, same result, since I have the same url as the one generated by NetAtmo, I don't understand why it doesn't work and I don't know what to try. It seems to me that it is the protocol generated by the HTTP client that seems faulty, but why, I don't know. In any case, it is not an access token problem, because in this case we have the message in clear.

It works great your answer search, I have to try with System.Net.WebClient instead of HtppClient.

I was offered the link: HTTP GET in VB.NET which allows to make an HTTP GET with WebClient, but it is obsolete, you have to use HttpClient

frousset
  • 1
  • 4
  • First off, you say it's returning an error, yet you've not actually told us exactly what the error is, could you update the question with the response you're getting. Next typically where I've seen Access/Refresh tokens it implies an OAuth(or OAuth2) authorisation process to generate an Access token, where/how did you get that as it appears you're sending in effect a constant? – Hursey Jul 27 '23 at 20:21
  • If you've got a working solution using WebClient, might pay to update your question with that also, maybe we can spot the difference. Final thing to say, the difference between Get and Post requests is pretty fundamental when consuming Rest services. Some suggested reading on the different HTTP Request methods can be found [here](https://www.w3schools.com/tags/ref_httpmethods.asp) – Hursey Jul 27 '23 at 20:24
  • I have juste to add this parameter: AddGetParametre("access_token", vAccessToken) and it works fine – frousset Jul 28 '23 at 08:27
  • Yes, you are wright, i have to add the parameter access_token, think you very much Hursey – frousset Jul 28 '23 at 08:36

1 Answers1

0

I FIND THE SOLUTION : I have just to add this parameter to work:

AddGetParametre("access_token", vAccessToken)

Think you very much for all people who answer to this question.

This is the good code:

Public Class ClassHttpPostNetAtmo

  ReadOnly myClientHttp As HttpClient
  ReadOnly parametres As New Dictionary(Of String, String)
  Dim builder As UriBuilder
  Dim query As Specialized.NameValueCollection
  ReadOnly dateUnix As New DateTime(1970, 1, 1, 0, 0, 0, 0)
  Public Property AccessToken As String
  Public Sub New()
    myClientHttp = New HttpClient()
  End Sub

  Public Sub ClearPostParametres()
    parametres.Clear()
  End Sub

  Public Sub AddPostParametre(ByVal key As String, ByVal value As String)
    parametres.Add(key, value)
  End Sub

  Public Async Function PostHttp(ByVal RequestUri As String) As Task(Of String)
    Dim content As New FormUrlEncodedContent(parametres)
    Dim response As HttpResponseMessage = Await myClientHttp.PostAsync(RequestUri, content)
    Dim responseString As String = Await response.Content.ReadAsStringAsync()
    Return responseString
  End Function

  Public Async Function RefreshToken(ByVal vRequestUri As String, ByVal vRefresh_token As String, ByVal vClient_id As String, ByVal vClient_secret As String) As Task(Of Dictionary(Of String, String))
    ClearPostParametres()
    AddPostParametre("grant_type", "refresh_token")
    AddPostParametre("refresh_token", vRefresh_token)
    AddPostParametre("client_id", vClient_id)
    AddPostParametre("client_secret", vClient_secret)
    Dim responseString As String = Await PostHttp(String.Concat(vRequestUri, "/oauth2/token"))
    Dim paramRep As New Dictionary(Of String, String)
    Dim str() As String = responseString.Replace("{", "").Replace("}", "").Split(",")
    For Each strPar As String In str
      Dim par() As String = strPar.Split(":")
      paramRep.Add(par(0).Replace("""", ""), par(1).Replace("""", ""))
    Next

    Return paramRep
  End Function

  Public Sub ClearGetParameter(ByVal vRequestUri As String)
    builder = New UriBuilder(vRequestUri) With {
      .Port = -1
    }
    query = HttpUtility.ParseQueryString(builder.Query)
  End Sub

  Public Sub AddGetParametre(ByVal key As String, ByVal value As String)
    If value IsNot Nothing Then
      If key = "type" Then
        Dim tvalue() As String = value.Split(",")
        For Each strVal As String In tvalue
          query.Add(key, strVal)
        Next
      Else
        query.Add(key, value)
      End If
    End If
  End Sub

  Public Async Function GetHttp() As Task(Of String)
    builder.Query = query.ToString()
    Dim url As String = builder.ToString()
    myClientHttp.DefaultRequestHeaders.Accept.Clear()
    Dim response As HttpResponseMessage = Await myClientHttp.GetAsync(url)
    Dim str = Await response.Content.ReadAsStringAsync()
    If response.ReasonPhrase = "OK" Then
      Return str
    Else
      Throw New Exception(String.Concat("Erreur Http GET : ", response.ReasonPhrase, " Status code = ", response.StatusCode, vbCrLf, response.RequestMessage.RequestUri.OriginalString))
    End If

  End Function

  ' ,humidity,co2,pressure,noise,rain,windstrength,windangle

  Public Async Function GetWeatherData(ByVal vRequestUri As String, ByVal vDeviceId As String, vDateBegin As DateTime, ByVal vDateEnd As DateTime, Optional ByVal vModuleId As String = Nothing, Optional ByVal vScale As String = "max", Optional ByVal vType As String = "temperature", Optional ByVal vLimit As String = "1024", Optional ByVal vOptimize As String = "false", Optional ByVal vRealTime As String = "true") As Task
    ClearGetParameter(String.Concat(vRequestUri, "/api/getmeasure"))
    AddGetParametre("device_id", vDeviceId)
    AddGetParametre("module_id", vModuleId)
    AddGetParametre("scale", vScale)
    AddGetParametre("type", vType)
    AddGetParametre("date_begin", CType(((vDateBegin.Subtract(dateUnix)).TotalSeconds), Integer).ToString())
    AddGetParametre("date_end", CType(((vDateEnd.Subtract(dateUnix)).TotalSeconds), Integer).ToString())
    AddGetParametre("limit", vLimit)
    AddGetParametre("optimize", vOptimize)
    AddGetParametre("real_time", vRealTime)
    AddGetParametre("access_token", AccessToken)
    Dim responseString As String = Await GetHttp()

  End Function

  Public Async Function GetStationsData(ByVal vRequestUri As String, ByVal vDeviceId As String) As Task
    ClearGetParameter(String.Concat(vRequestUri, "/api/getstationsdata"))
    AddGetParametre("device_id", vDeviceId)
    AddGetParametre("get_favorites", "false")
    AddGetParametre("access_token", AccessToken)
    Dim responseString As String = Await GetHttp()
  End Function


Imports ClassLibraryHttpPostNetAtmo
Imports LibraryDivers
Public Class FrmTestMyLibraryNetAtmo
  Dim ClientId As String
  Dim ClientSecret As String
  Dim myNetAtmo As New ClassHttpPostNetAtmo
  Dim AccessToken As String
  Dim RefreshToken As String
  Private Sub FrmTestMyLibraryNetAtmo_Shown(sender As Object, e As EventArgs) Handles MyBase.Shown

  End Sub

  Private Async Sub BtnTest_Click(sender As Object, e As EventArgs) Handles BtnTest.Click
    If (My.Settings.AccessToken Is Nothing OrElse My.Settings.AccessToken = "") Or
       (My.Settings.RefreshToken Is Nothing OrElse My.Settings.RefreshToken = "") Or
       (My.Settings.DateRefreshToken < Now) Then
      ClientId = ClassDivers.Decode(My.Settings.ClientId, My.Settings.EncodeNumber)
      ClientSecret = ClassDivers.Decode(My.Settings.ClientSecret, My.Settings.EncodeNumber)

      Dim par As Dictionary(Of String, String) = Await myNetAtmo.RefreshToken(My.Settings.RequestUri, My.Settings.RefreshToken, ClientId, ClientSecret)
      AccessToken = par("access_token")
      RefreshToken = par("refresh_token")
      My.Settings.AccessToken = par("access_token")
      My.Settings.RefreshToken = par("refresh_token")
      My.Settings.DateRefreshToken = Now.AddSeconds(par("expire_in")).AddMinutes(-10)
      My.Settings.Save()
    End If
    Try
      myNetAtmo.AccessToken = My.Settings.AccessToken
      Await myNetAtmo.GetStationsData(My.Settings.RequestUri, "70:ee:50:12:4d:12")
      ' Await myNetAtmo.GetWeatherData(My.Settings.RequestUri, "70:ee:50:12:4d:12", Now.AddMinutes(-20), Now, vModuleId:="02:00:00:12:86:30")
    Catch ex As Exception
      MessageBox.Show(String.Concat(ex.Message, vbCr, ex.StackTrace))
    End Try
  End Sub
End Class
frousset
  • 1
  • 4