I'm doing a little widget that shows the price of bitcoin using Binance API here
I'm not using Json format as I Just need to parse one string, eventhough I know many of you will say to use json. Anyway, I want to keep the software as simple as possible, but there is a little problem.
I'm downloading the source with webclient and Updating it using a timer.
I think I'm doing a mistake creating every time the new webclient because when I want to move the form, Is not properly mooving even if its not freezing.
The code I'm using is:
Private Sub webclientbtc()
Dim wc As New Net.WebClient
Dim WBTC As IO.Stream = Nothing
wc.Encoding = Encoding.UTF8
WBTC = wc.OpenRead("https://api.binance.com/api/v1/ticker/24hr?symbol=BTCEUR")
Dim btc As String
Using rd As New IO.StreamReader(WBTC)
btc = rd.ReadToEnd
End Using
'---------BTC PRICE---------'
Dim textBefore As String = """lastPrice"":"""
Dim textAfter As String = ""","
Dim startPosition As Integer = btc.IndexOf(textBefore)
startPosition += textBefore.Length
Dim endPosition As Integer = btc.IndexOf(textAfter, startPosition)
Dim textFound As String = btc.Substring(startPosition, endPosition - startPosition)
Dim dNumber As Double = Val(textFound.ToString)
Label1.Text = dNumber.ToString("n2")
'-------------------------------------'
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
webclientbtc()
End Sub
Timer interval is on 1000 ms, which is great to keep me update.
Any idea on how I can avoid the creations of new webclient at every update?
Thanks
Simplified, and using TAP:
Private wc as New WebClient()
Private Async Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
Dim s = Await wc.DownloadStringTaskAsync("https://api.binance.com/api/v1/ticker/24hr?symbol=BTCEUR")
Dim d = JsonConvert.DeserializeObject(Of Dictionary(Of String, String))(s)
Label1.Text = d("lastPrice")
End Sub
You need to reference newtonsoft json package and imports it, as well as imports system.collections.generic
If the answer by Caius Jard is too good, you can avoid the use of a JSON deserialiser by using a regex:
Imports System.Net
Imports System.Text.RegularExpressions
Public Class Form1
Dim tim As New Timer()
Private Async Sub UpdateBtc(sender As Object, e As EventArgs)
' temporarily disable the timer in case the web request takes a long time
tim.Enabled = False
' using New Uri() makes sure it is a proper URI:
Dim url = New Uri("https://api.binance.com/api/v1/ticker/24hr?symbol=BTCEUR")
Dim rawJson As String
Using wb As New WebClient()
rawJson = Await wb.DownloadStringTaskAsync(url)
End Using
Dim re = New Regex("""lastPrice"":\s*""([0-9.-]+)""")
Dim lastPrice = re.Match(rawJson)?.Groups(1)?.Value
Dim p As Decimal
lblLastPrice.Text = If(Decimal.TryParse(lastPrice, p), p.ToString("N2"), "Fetch error.")
tim.Enabled = True
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
UpdateBtc(Nothing, EventArgs.Empty)
tim.Interval = 3000
AddHandler tim.Tick, AddressOf UpdateBtc
tim.Start()
End Sub
Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
If tim IsNot Nothing Then
tim.Stop()
RemoveHandler tim.Tick, AddressOf UpdateBtc
tim.Dispose()
End If
End Sub
End Class
There's no need to re-use the WebClient, creating it is not what is taking up the time.
I prefer to instantiate timers myself: there is no requirement to do so.
It is better to use descriptive names for controls: "Label1" tells you nothing.
Related
Public Class Form1
For i As Integer = 0 To RichTextBox1.Lines.Length - 1
wreq=System.Net.WebRequest.Create("i th Internet address")
wreq.AutomaticDecompression = Net.DecompressionMethods.GZip
wres = wreq.GetResponse
Dim s As System.IO.Stream = wres.GetResponseStream
Dim sr As New System.IO.StreamReader(s)
html = sr.ReadToEnd
s = html.Split(";")
'here is other codes
Next
End Class
this is part of my program.
When I use this, it takes a long time for everyone to download. How can I download all the addresses at the same time?
I found the following code on the internet enter code here to do this, but I do not know how to use it in the my program. Please help. Thank you.
Imports System.Threading.Tasks
Imports System.Net
Imports System.IO
Public Class Form1
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
'Start a background task so as not to freeze up the UI.
Me.BackgroundWorker1.RunWorkerAsync()
End Sub
Private Sub BackgroundWorker1_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Dim files As String() 'Get file paths.
'Download multiple files simultaneously.
Parallel.ForEach(files,
Sub(f) Call New WebClient().DownloadFile(f,
Path.Combine("local folder here",
Path.GetFileName(f))))
End Sub
Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
MessageBox.Show("All files downloaded")
End Sub
End Class
Take a look on this. Might be a good start (part of your code implemented on each method).
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim urls() As String = RichTextBox1.Lines.Select(Function(url) Trim(url))
Parallel.ForEach(urls, Sub(f)
If Not String.IsNullOrEmpty(f) Then
DownloadAsync(f)
End If
End Sub)
End Sub
Function DownloadAsync(URL As String) As Task(Of Boolean)
Try
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
Dim html As String = ""
Dim result As Boolean
Dim request As HttpWebRequest = HttpWebRequest.Create(URL)
request.AutomaticDecompression = DecompressionMethods.GZip
request.Timeout = 500
request.Method = "GET"
request.UserAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X x.y; rv:42.0) Gecko/20100101 Firefox/42.0"
Using response As Task(Of WebResponse) = request.GetResponseAsync
If response.Result IsNot Nothing Then
Using ioStream As IO.Stream = response.Result.GetResponseStream
Using sr As New System.IO.StreamReader(ioStream)
html = sr.ReadToEnd
Dim s() As String = html.Split(";"c)
For Each sl In s
Debug.WriteLine(sl)
Next
End Using
result = True
End Using
End If
End Using
Return Task.FromResult(result)
Catch ex As Exception
Debug.WriteLine(ex.Message)
End Try
Return Task.FromResult(False)
End Function
I'm trying to create an application that works with voice commands with vb.net. I want it to work as "Alexa" and therefore have a keyword and then the commands, but the keyword and commands must be written by the user.
How do I add strings to the grammar without having to first pass them to the rule? (sorry for bad english i'm italian)
Here's my code so far:
Imports System.Speech
Public Class Form1
Dim WithEvents reco As New Recognition.SpeechRecognitionEngine
Dim WithEvents reco2 As New Recognition.SpeechRecognitionEngine
Dim recallWord As String
Dim c As Integer = 0
Dim comandoWord(c) As String
Dim comandoV As New Recognition.SrgsGrammar.SrgsOneOf
Dim recallV As New Recognition.SrgsGrammar.SrgsOneOf
Dim gram As New Recognition.SrgsGrammar.SrgsDocument
Dim rules As New Recognition.SrgsGrammar.SrgsRule("a")
Dim rules2 As New Recognition.SrgsGrammar.SrgsRule("b")
Dim recording As Boolean
Dim gram2 As New Recognition.SrgsGrammar.SrgsDocument
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
reco.SetInputToDefaultAudioDevice()
reco2.SetInputToDefaultAudioDevice()
End Sub
Private Sub btIns_Click(sender As Object, e As EventArgs) Handles btIns.Click
c = c + 1
ReDim comandoWord(c)
recallWord = txtRecall.Text
comandoWord(c) = txtComando.Text
Dim recallC As New Recognition.SrgsGrammar.SrgsItem(recallWord)
recallV.Items.Add(recallC)
rules.Add(recallV)
gram.Rules.Add(rules)
gram.Root = rules
reco.LoadGrammar(New Recognition.Grammar(gram))
Dim comandoC As New Recognition.SrgsGrammar.SrgsItem(comandoWord(c))
comandoV.Items.Add(comandoC)
rules2.Add(comandoV)
gram2.Rules.Add(rules2)
gram2.Root = rules2
reco2.LoadGrammar(New Recognition.Grammar(gram2))
reco.RecognizeAsync()
reco2.RecognizeAsync()
End Sub
Private Sub reco_speechRecognized(ByVal sender As Object, e As System.Speech.Recognition.RecognitionEventArgs) Handles reco.SpeechRecognized
If e.Result.Text = recallWord Then
MsgBox(e.Result.Text)
recording = True
End If
End Sub
Private Sub reco2_speechRecognized(ByVal sender As Object, e As System.Speech.Recognition.RecognitionEventArgs) Handles reco2.SpeechRecognized
If recording = True Then
If e.Result.Text = comandoWord(1) Then
MsgBox(e.Result.Text)
recording = False
End If
End If
End Sub
Private Sub reco_recognizecompleted(ByVal sender As Object, e As System.Speech.Recognition.RecognizeCompletedEventArgs) Handles reco.RecognizeCompleted
reco.RecognizeAsync()
End Sub
Private Sub reco2_recognizecompleted(ByVal sender As Object, e As System.Speech.Recognition.RecognizeCompletedEventArgs) Handles reco2.RecognizeCompleted
reco2.RecognizeAsync()
End Sub
End Class
Also, you mentioned you are Italian, so I am going to assume you are in Italy. If this is the case make this adjustment to:
Thread.CurrentThread.CurrentCulture = New CultureInfo("en-EN")
Change to:
Thread.CurrentThread.CurrentCulture = New CultureInfo("it-IT")
If I am understanding you correctly, you are looking to create an object called "Choices" which represents a component of a phrase that can have one of several values. This is vital for speech recognition "GrammarBuilder". The following is an example of an established Grammar in VB.NET that I tested and compiled for you. I only have one command in it.If you wish to add more, do this: ("Activate Scarlett", "Run Notepad")) Just be sure you last word doesn't have a comma. I hope it will suffice.
Imports System.Globalization
Imports System.Speech
Imports System.Speech.Recognition
Imports System.Threading
Public Class Sentinal
Private WithEvents Sentinal As New SpeechRecognitionEngine
Public synth As New Synthesis.SpeechSynthesizer
Dim grammerBuilder As New DictationGrammar()
Private Sub Sentinal_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Try
Dim commandChoices As New Choices
Dim grammarBuilder As New GrammarBuilder
Thread.CurrentThread.CurrentCulture = New CultureInfo("en-EN")
commandChoices.Add(New String("Activate Scarlett")) '<add more
grammarBuilder.Append(commandChoices)
Sentinal.RequestRecognizerUpdate()
Dim gr As New Grammar(grammarBuilder)
Sentinal.LoadGrammarAsync(gr)
Sentinal.SetInputToDefaultAudioDevice()
Sentinal.RecognizeAsync()
Catch ex As Exception
MessageBox.Show(ex.Message, "Error!", MessageBoxButtons.OK, MessageBoxIcon.Information)
End Try
End Sub
Private Sub Sentinal_RecognizeCompleted(sender As Object, e As RecognizeCompletedEventArgs) Handles Sentinal.RecognizeCompleted
Sentinal.RecognizeAsync()
End Sub
Private Sub Sentinal_SpeechRecognized(sender As Object, e As SpeechRecognizedEventArgs) Handles Sentinal.SpeechRecognized
Select Case e.Result.Text
Case "Activate Scarlett"
'Place your event here
Case "Run Notepad"
'Event Here
End Select
End Sub
End Class
Choices Example
I designed Scarlett's program that you are asking about.
You can easily create a text file that holds your commands from Choices:
recEngine.LoadGrammar(New Grammar(New GrammarBuilder(New
Choices(File.ReadAllLines("C:\Users\justin.ross\source\repos\ScarlettCenturium\Scarlett
Centurium\Scarlett Centurium\Commands.txt")))))
I left the link to my repository. Just locate Form1.vb and open it. It will answer your question.
https://github.com/Rythorian77/Scarlett-Centurium-XI1/commit/6745552659f935881852151d5f880d2e6886f6cd
I would like to know how long the PC has been started.
That's why I made the following routine:
Public Function LipPCIsOn() As String
Dim iTempoPC As Integer
Dim tTempoPC As TimeSpan
Dim strTempoPC As String
iTempoPC = System.Environment.TickCount
tTempoPC = TimeSpan.FromMilliseconds(iTimePC)
strTempoPC = tTempoPC.Duration.ToString("hh:mm:ss")
Return strTempoPC
End Function
But I do not understand, the PC despite having been started by 3 minutes it tells me:
7:54:36
Where's the mistake?
Thank you all
There may be some other source of the last power-on time, but you can use the Windows System Event Log to get the last event from Kernel-Boot:
Function GetLastPowerOn() As DateTime?
Dim systemEventLog = New EventLog()
systemEventLog.Log = "System"
Dim lastPowerOn = systemEventLog.Entries.Cast(Of EventLogEntry).
Where(Function(eu) eu.Source = "Microsoft-Windows-Kernel-Boot").
OrderByDescending(Function(ev) ev.TimeGenerated).FirstOrDefault()
Return lastPowerOn?.TimeGenerated
End Function
I do not know the behaviour for if there is no entry, so I assumed that a Nullable(Of DateTime) would do. If you want to clear your System event log, you could let us know what happens; I don't want to do that.
Unfortunately, it takes ages to return a value (e.g. about 7 seconds on this computer), so you might want to call it asynchronously. Here is an example which uses one button and two labels on a form:
Public Class Form1
Dim tim As Timer
Friend Async Function GetLastPowerOnAsync() As Task(Of DateTime?)
Dim systemEventLog = New EventLog() With {.Log = "System"}
Dim tsk = Await Task.Factory.StartNew(Function()
Return systemEventLog.Entries.Cast(Of EventLogEntry).
Where(Function(eu) eu.Source = "Microsoft-Windows-Kernel-Boot").
OrderByDescending(Function(ev) ev.TimeGenerated).
FirstOrDefault()
End Function)
Return tsk?.TimeGenerated
End Function
Sub timTick(sender As Object, e As EventArgs)
Label1.Text = DateTime.Now.ToString("HH:mm:ss")
End Sub
Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim lpo = Await GetLastPowerOnAsync()
If lpo.HasValue Then
Label2.Text = lpo.Value.ToString("yyyy-MM-dd HH:mm:ss")
Else
Label2.Text = "No System event log entry with a source of Microsoft-Windows-Kernel-Boot entry found."
End If
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
tim = New Timer() With {.Interval = 500}
AddHandler tim.Tick, AddressOf timTick
tim.Start()
End Sub
Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
RemoveHandler tim.Tick, AddressOf timTick
tim.Dispose()
End Sub
End Class
Thank you all.
I just wanted to point out that:
1) my PC did not make a real shutdown but a suspension;
2) the correct code I rewrote is:
Public Function LipPCIsOnNew() As String
Dim EventoLogApp As New System.Diagnostics.EventLog("System")
Dim OraACCENSIONE As Date, stMachineName As String
' search from the end, to find the last boot faster
For i = EventoLogApp.Entries.Count - 1 To 1 Step -1
If EventoLogApp.Entries(i).InstanceId.ToString = 1 Then
OraACCENSIONE = EventoLogApp.Entries(i).TimeGenerated
stMachineName = EventoLogApp.Entries(i).MachineName.ToString
Exit For
End If
Next
Return OraACCENSIONE.ToString
End Function
Now everything is ok
Thank you all
I have a simple button which sends a get request to retrieve a txt file on my website. Problem is it freezes the application while retrieving the info. How can I make it so the application doesn't freeze while waiting for the result?
Private Sub cmd_ClickMe_Click(sender As Object, e As EventArgs) Handles cmd_ClickMe.Click
Dim request As String = String.Format("http://www.*****/database/test.txt")
Dim webClient As New System.Net.WebClient
Dim result As String = webClient.DownloadString(request)
MessageBox.Show(result)
End Sub
I've also tried the following but it doesn't work (says "webClient.DownloadStringAsync(myUri)" does not produce a value:
Private Sub cmd_ClickMe_Click_1(sender As Object, e As EventArgs) Handles cmd_ClickMe.Click
Dim request As String = String.Format("http://www.****.com/database/test.txt")
Dim webClient As New System.Net.WebClient
Dim myUri As Uri = New Uri(request)
Dim result As String = webClient.DownloadStringAsync(myUri)
MessageBox.Show(result)
End Sub
Use DownloadStringAsync(Uri) instead of the DownloadString(uri).
The DownloadStringAsync method does not block the calling thread.
Here is an example how to use it:
Dim wc As New WebClient
' Specify that you get alerted
' when the download completes.
AddHandler wc.DownloadStringCompleted, AddressOf AlertStringDownloaded
Dim uri As New Uri("http:\\changeMe.com") 'Pass the URL to here. This is just an example
wc.DownloadStringAsync(uri)
End Sub
Public Shared Sub AlertStringDownloaded(ByVal sender As Object, ByVal e As DownloadStringCompletedEventArgs)
' If the string request went as planned and wasn't cancelled:
If e.Cancelled = False AndAlso e.Error Is Nothing Then
Dim myString As String = CStr(e.Result) 'Use e.Result to get the String
MessageBox.Show(myString)
End If
End Sub
I am trying to create a Windows Phone 7.1 application, basically a currency converter. I am using DownloadStringAsync method to get a short string containing the exchange rate from a specific website. I tested in Visual Studio 2010, DownloadString worked just fine. But not for the phone application. What do I need to do here? I can't really make much sense of it.
Partial Public Class MainPage
Inherits PhoneApplicationPage
Dim webClient As New System.Net.WebClient
Dim a As String
Dim b As String
Dim result As String = Nothing
' Constructor
Public Sub New()
InitializeComponent()
End Sub
Private Sub Button1_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles Button1.Click
a = "USD"
b = "GBP"
webClient = New WebClient
Dim result As String = webClient.DownloadStringAsync(New Uri("http://rate-exchange.appspot.com/currency?from=" + a + "&to=" + b) as String)
TextBox1.Text = result
End Sub
End Class
A few things wrong here:
DownloadStringAsync does not return a value (void method in C# terms)
You need to handle the DownloadStringCompleted event for WebClient variable. You can get the result in the event handler.
You can change your code to something like this to get the above to work:
Private Sub Button1_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles Button1.Click
a = "USD"
b = "GBP"
webClient = New WebClient
'Add the event handler here
AddHandler webClient.DownloadStringCompleted, AddressOf webClient_DownloadStringCompleted
Dim url As String = "http://rate-exchange.appspot.com/currency?from=" & a & "&to=" & b
webClient.DownloadStringAsync(New Uri(url))
End Sub
Private Sub webClient_DownloadStringCompleted(ByVal sender as Object,ByVal e as DownloadStringCompletedEventArgs)
TextBox1.Text = e.result
End Sub
Just use DownloadStringTaskAsync:
Using WebClient As WebClient = New WebClient
Return Await WebClient.DownloadStringTaskAsync(New Uri(myurl))
End Using