HTTP客户端在VB.Net中对网站api.netatmo.com的GET请求总是返回错误。

huangapple go评论85阅读模式
英文:

HTTP Client GET in VB.Net for the site api.netatmo.com always returns an error

问题

抱歉,以下是代码部分的翻译:

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

希望这有助于您的问题解决。如果您需要更多帮助,请随时提问。

英文:

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:
https://stackoverflow.com/questions/92522/http-get-in-vb-net
which allows to make an HTTP GET with WebClient, but it is obsolete, you have to use HttpClient

答案1

得分: 0

我找到了解决方案:
我只需添加这个参数即可正常工作:

AddGetParametre("access_token", vAccessToken)

非常感谢所有回答这个问题的人。

这是正确的代码:

Public Class ClassHttpPostNetAtmo
  ' ... (以下省略,未显示完整代码)
End Class

请注意,我已经将代码中的特殊字符(例如")保留在翻译中,以保持代码的完整性。

英文:

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

huangapple
  • 本文由 发表于 2023年7月28日 02:46:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/76782631.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定