ComEdRTP 工具
用于监控 ComEd 电力实时价格的工具。
引言
这是一套工具,旨在更轻松地跟踪 ComEd 电力的实时价格。 作为该项目的一部分,一个用于从 AJAX 来源获取数据的 DLL 既用于 .NET 又用于 .NET CF,这样就不需要多个独立的来源。
背景
这个项目源于我需要能够监控电力的实时价格。 ComEd 没有提供任何此类工具来实现这一点。 当我开始这个项目时,我希望在我的手机和台式机上都有一个应用程序。 我只想为两个平台编写一次代码。 因此,我编写了一个模块,该模块轮询 ComEd 服务器,该服务器用于他们的 AJAX 网页,以获取定价信息。 该模块的编写方式使其可以编译为 .NET 或 .NET CF。
Using the Code
使用该代码非常简单。 简单地调用 GetRTP
将在名为 RTPData
的结构体中返回价格。 该结构体包含上次价格更新的时间、当前价格、预测时间和预测价格。
除了 GetRTP
函数之外,还有一个用于解析响应流的函数。 该函数非常基础,而 GetRTP
函数只是使用 WebRequest
从 ComEd 服务器获取定价数据。
Public Function GetRTP() As RTPData
Dim myRTPData As RTPData
Dim randomNumber As New Random
Dim myWebRequest As HttpWebRequest
Dim myResponseStream As System.IO.Stream = Nothing
Dim strRequest As String = "http://il.thewattspot.com/dwr/exec/rtp.getRTP?" & _
"callCount=1&c0-scriptName=rtp&c0-methodName=getRTP&c0-id=" & _
randomNumber.Next.ToString.Substring(0, 4) & _
"_" & DateTime.Now.Ticks.ToString.Substring(0, 13) & _
"&xml=true"
Dim objReader As System.IO.StreamReader = Nothing
Try
myWebRequest = WebRequest.Create(strRequest)
myResponseStream = myWebRequest.GetResponse.GetResponseStream
Dim strLine As String = ""
objReader = New System.IO.StreamReader(myResponseStream)
If objReader.Peek >= 0 Then
ParseResponse(objReader.ReadLine, myRTPData)
End If
myResponseStream.Close()
Catch ex As Exception
End Try
If myResponseStream IsNot Nothing Then myResponseStream.Close()
If objReader IsNot Nothing Then objReader.Close()
Return myRTPData
End Function
显示结果
该程序的 .NET 和 .NET CF 版本都以颜色编码的方式显示数据。 我以前从未尝试过动态创建图形,这是我第一次尝试。 我必须承认,代码中某个地方存在一个非常小的内存泄漏,我认为就在这里,但我找不到它。 这似乎无关紧要,因为我已经运行了几天代码而没有出现内存问题。
用于创建 .NET 程序版本使用的托盘图标的例程将绘制一对彩色框并在其上写入文本。
Private Sub CreateTextIcon(ByVal strPrice As String, _
ByVal sglPredictedPrice As Single)
tmrExtremePrice.Stop()
Dim fontPrice As Font = New Font("Microsoft Sans Serif", _
9, FontStyle.Regular, GraphicsUnit.Pixel)
Dim brushPrice As Brush = New SolidBrush(Color.Black)
Dim brushBackground As SolidBrush
Dim gIcon As Graphics = Drawing.Graphics.FromImage(bmpIcon)
Dim gAltIcon As Graphics = Drawing.Graphics.FromImage(bmpAltIcon)
Dim hIcon As IntPtr
Dim intTemp As Integer
Dim drawRectange As New Rectangle(0, 0, 16, 16)
Dim stringFormat As New StringFormat()
stringFormat.Alignment = StringAlignment.Center
stringFormat.LineAlignment = StringAlignment.Center
intTemp = strPrice * 32
If strPrice > 8 Then
If intTemp > 255 Then
brushBackground = New SolidBrush(Color.FromArgb(255, 255, 0, 0))
gIcon.FillRectangle(brushBackground, New Rectangle(0, 0, 16, 8))
brushBackground.Dispose()
brushBackground = New SolidBrush(Color.FromArgb(0, 255, 0, 0))
gAltIcon.FillRectangle(brushBackground, New Rectangle(0, 0, 16, 8))
brushBackground.Dispose()
tmrExtremePrice.Start()
Else
brushBackground = New SolidBrush(Color.FromArgb _
(255, 255, 255 - intTemp, 0))
gIcon.FillRectangle(brushBackground, New Rectangle(0, 0, 16, 8))
brushBackground.Dispose()
brushBackground = New SolidBrush(Color.FromArgb _
(255, 255, 255 - intTemp, 0))
gAltIcon.FillRectangle(brushBackground, New Rectangle(0, 0, 16, 8))
brushBackground.Dispose()
End If
ElseIf strPrice < 8 Then
brushBackground = New SolidBrush(Color.FromArgb(255, intTemp, 255, 0))
gIcon.FillRectangle(brushBackground, New Rectangle(0, 0, 16, 8))
brushBackground.Dispose()
brushBackground = New SolidBrush(Color.FromArgb(255, intTemp, 255, 0))
gAltIcon.FillRectangle(brushBackground, New Rectangle(0, 0, 16, 8))
brushBackground.Dispose()
Else
brushBackground = New SolidBrush(Color.FromArgb(255, 255, 255, 0))
gIcon.FillRectangle(brushBackground, New Rectangle(0, 0, 16, 8))
brushBackground.Dispose()
brushBackground = New SolidBrush(Color.FromArgb(255, 255, 255, 0))
gAltIcon.FillRectangle(brushBackground, New Rectangle(0, 0, 16, 8))
brushBackground.Dispose()
End If
intTemp = sglPredictedPrice * 32
If sglPredictedPrice > 8 Then
If intTemp > 255 Then
brushBackground = New SolidBrush(Color.FromArgb(255, 255, 0, 0))
gIcon.FillRectangle(brushBackground, New Rectangle(0, 8, 16, 8))
brushBackground.Dispose()
brushBackground = New SolidBrush(Color.FromArgb(0, 255, 0, 0))
gAltIcon.FillRectangle(brushBackground, New Rectangle(0, 8, 16, 8))
brushBackground.Dispose()
tmrExtremePrice.Start()
Else
brushBackground = New SolidBrush(Color.FromArgb _
(255, 255, 255 - intTemp, 0))
gIcon.FillRectangle(brushBackground, New Rectangle(0, 8, 16, 8))
brushBackground.Dispose()
brushBackground = New SolidBrush(Color.FromArgb _
(255, 255, 255 - intTemp, 0))
gAltIcon.FillRectangle(brushBackground, New Rectangle(0, 8, 16, 8))
brushBackground.Dispose()
End If
ElseIf sglPredictedPrice < 8 Then
brushBackground = New SolidBrush(Color.FromArgb(255, intTemp, 255, 0))
gIcon.FillRectangle(brushBackground, New Rectangle(0, 8, 16, 8))
brushBackground.Dispose()
brushBackground = New SolidBrush(Color.FromArgb(255, intTemp, 255, 0))
gAltIcon.FillRectangle(brushBackground, New Rectangle(0, 8, 16, 8))
brushBackground.Dispose()
Else
brushBackground = New SolidBrush(Color.FromArgb(255, 255, 255, 0))
gIcon.FillRectangle(brushBackground, New Rectangle(0, 8, 16, 8))
brushBackground.Dispose()
brushBackground = New SolidBrush(Color.FromArgb(255, 255, 255, 0))
gAltIcon.FillRectangle(brushBackground, New Rectangle(0, 8, 16, 8))
brushBackground.Dispose()
End If
gIcon.DrawString(strPrice, fontPrice, brushPrice, drawRectange, stringFormat)
gAltIcon.DrawString(strPrice, fontPrice, brushPrice, drawRectange, stringFormat)
hIcon = bmpIcon.GetHicon
notifyPrice.Icon = Drawing.Icon.FromHandle(hIcon)
DestroyIcon(hIcon)
fontPrice.Dispose()
brushPrice.Dispose()
gIcon.Dispose()
gAltIcon.Dispose()
stringFormat.Dispose()
End Sub
上述代码实际上创建了两个图标:一个用于显示,如果价格极高,则创建一个闪烁的图标。 两个图标都根据价格在其上显示两个颜色的矩形。 在颜色之上是一些文本。 这样,图标可以随着价格的变化而变化,从而提供了一种轻松跟踪电价的方式。
关注点
我在这个程序中遇到的最大障碍是找到内存泄漏。 在 .NET 中使用 GDI 是一项挑战。 人们会认为托管代码在跟踪分配的资源和清理自身方面会做得更好,或者至少 Visual Studio 会在无法清理自身时提醒你。
历史
- 2009年12月22日 - 初始发布(包含一些小错误)。