<p>Jednou z velmi užitečných vlastností platformy .NET je, že se neomezuje jenom na jeden typ aplikací. Ve stejném jazyce, vývojovém prostředí a stejnými technologiemi lze psát aplikace webové (Web Forms), desktopové (Windows Forms) i pro kapesní počítače (Compact Framework).</p>
<p>Ač to na první pohled nemusí být zřejmé, tato vlastnost je velice výhodná i pro čistokrevného webového programátora. Webové rozhraní prostě má svoje omezení a není vhodné pro všechny typy úkolů. Lze-li očekávat, že klient bude vybaven .NET Frameworkem, je možné řadu těchto omezení vyřešit napsáním jednoduché aplikace, která požadované operace provede. Se svým webovým protějškem pak může komunikovat například přes web service rozhraní.</p>
<p>Microsoft .NET 2.0 (Whidbey), toho času dostupný jako Beta 2, přináší řadu novinek, a to i pro vývoj desktopových aplikací. Rozhodl jsem se napsat v něm aplikaci, která bude schopna zobrazit aktuální teplotu, přičemž informace o ní bude čerpat jednak z veřejně dostupné webové služby, jednak z teplotního čidla připojeného na sériový port.</p>
<h2>Použité technologie</h2>
<ul>
<li>Komunikace s hardwarovým zařízením přes COM port a protokol RS-232. Obsluha sériových portů je novinkou ve verzi 2.0. </li>
<li>Komunikace s webovou službou třetí strany. </li>
<li>Využití <em>application frameworku</em>, tedy funkcí Whidbey pro snazší vývoj desktopových aplikací. </li>
<li>Využití <em>settings frameworku</em>, nástroje pro snadnou práci s konfigurací.</li>
</ul>
<h2>Teplotní čidlo TM</h2>
<p>Jako lokální teplotní čidlo jsem použil modul "TM" od firmy Papouch s. r. o. (viz <a href="http://www.papouch.com/shop/scripts/_detail.asp?katcislo=0038">papouch.com</a>). Stejný výrobce nabízí i celou řadu dalších čidel (nejen teplotních), včetně připojení na <a href="http://www.papouch.com/?cislo=0188">USB</a> nebo <a href="http://www.papouch.com/shop/scripts/_detail.asp?katcislo=0201">Ethernet</a>, ale pro naše účely bohatě postačí toto nejjednodušší a nejlacinější.</p>
<h3>Komunikační protokol a proof-of-concept</h3>
<p>Zapojuje se na sériový port a funguje tak, že po připojení (s parametry 9600-8-N-1) a nahození signálu DTR změří teplotu a pošle ji na výstup jako jednoduchý ASCII řetězec (např. <code>+025.5C</code>). Proof-of-concept kód pro načtení aktuální teploty do numerické proměnné vypadá takto:</p>
<pre class="sh-code-vb">' Connect to serial port
Dim Port As New System.IO.Ports.SerialPort() Port.PortName = "COM1" Port.BaudRate = 9600 Port.DataBits = 8 Port.StopBits = IO.Ports.StopBits.One Port.Parity = IO.Ports.Parity.None Port.ReadTimeout = 1000 Port.DtrEnable = True Port.Open() ' Get current value Dim S As String = Port.ReadTo("C") Dim T As Single = Single.Parse(S.Substring(0, 6), _ New System.Globalization.CultureInfo("en-US")) MsgBox(String.Format("Current temperature is: {0:N2} °C", T)) Port.Close() Port.Dispose()
Webová služba GlobalWeather
Vzhledem k významu počasí pro leteckou dopravu jsou ideálním zdrojem informací o počasí letecké systémy. Přístup do nich lze získat příkladně pomocí webové slyžby GlobalWeather, jejíž popis najdete na http://live.capescience.com/GlobalWeather/. Tato služba je zároveň důkazem interoperability technologie Web Services, protože neběží na platformě .NET, ale lze ji bez problémů z .NETu využívat.
Informace o počasí (nejen teplotě) je k dispozici pro každé mezinárodní letiště. Pro ČR lze využít následující:
- Praha (kód
LKPR
)
- Karlovy Vary (kód
LKKV
) - Brno (kód
LKTB
) - Holešov (kód
LKHO
) - Ostrava (kód
LKMT
)
Chcete-li tuto službu využívat, přidejte si Web reference na adresu http://live.capescience.com/wsdl/GlobalWeather.wsdl a nazvěte ji GlobalWeather
. Tato webová služba vystavuje dvě třídy, které nás budou zajímat, a to StationInfo
a GlobalWeather
.
Zjištění informací o lokaci
Ke zjištění informací o lokaci jest možno využít metodu getStation
třídy StationInfo
. Tato třída obsahuje ještě další zajímavé metody, jimiž jest možno prohledávat seznam stanic. Budete-li chtít, můžete s jejich použitím rozšířit aplikaci tak, aby umožňovala např. výběr ze seznamu či prohledávání.
V této fázi se spokojím s tím, že pomocí webové služby získám pro danou lokaci její název a zemi, kde je umístěna. V okně nastavení (FormServiceOptions
) tak identifikuji, zda byl zadán platný kód letiště:
Dim StationWS As New GlobalWeather.StationInfo() Dim Station As GlobalWeather.Station = StationWS.getStation(Me.TextBoxWebLocationCode.Text) If Station Is Nothing Then MsgBox("Location not found - check code", MsgBoxStyle.Exclamation) Else MsgBox(String.Format("{0} is {1}, {2}", Me.TextBoxWebLocationCode.Text, Station.name, Station.country), MsgBoxStyle.Information) End If StationWS.Dispose()
Zjištění aktuální meteo situace na lokaci
Chceme-li na dané lokaci zjistit aktuální meteorologickou situaci, jejíž součástí je i teplota, použijete k tomu metodu getWeatherReport
třídy GlobalWeather
. Ta vrátí informace o lokaci a její meteorologické situaci:
Dim WeatherWS As New GlobalWeather.GlobalWeather() Dim Report As GlobalWeather.WeatherReport = WeatherWS.getWeatherReport(My.Settings.ServiceLocationCode) If Not Report Is Nothing Then Me.LabelService.Text = String.Format("{0:N1}°C", Report.temperature.ambient) Me.GroupBoxService.Text = String.Format("{0} ({1})", Report.station.name, Report.station.country) Me.LabelUpdateService.Text = Report.timestamp.Value.ToShortDateString() & " " & Report.timestamp.Value.ToShortTimeString() End If WeatherWS.Dispose()
Application Framework
Okno vlastností projektu (ukáže se po dvojkliknutí na "My Project" v Solution Exploreru) je ve Whidbey mnohem zajímavější, než tomu bylo v předchozích verzích. Zastavme se pro tento ukamžik u záložky "Application":
Po povolení Enable Application Framework máte možnost pro svou aplikaci jednoduše nastavit způsob, jakým se celkově má chovat. Po klepnutí na View Application Events se vám otevře soubor ApplicationEvents.vb
(standardně skrytý ve složce My Project
), ve kterém můžete definovat event handlery pro události týkající se celé aplikace. Připomíná to mechanismus Global Application Class (alias global.asax
) známý z webových ASP.NET aplikací.
Můžete například reagovat na neošetřenou výjimku a pokud ve vaší aplikaci nastane, nějak ji vyřešit - například zobrazit chybové hlášení a vygenerovat log:
Namespace My Class MyApplication Private Sub MyApplication_UnhandledException(ByVal sender As Object, ByVal e As Microsoft.VisualBasic.ApplicationServices.UnhandledExceptionEventArgs) Handles Me.UnhandledException If MsgBox("The follofing exception occured:" & vbCrLf & e.Exception.Message & vbCrLf & "Do you want to create log file?", MsgBoxStyle.Critical Or MsgBoxStyle.YesNo) = MsgBoxResult.Yes Then Dim LogFileName As String = My.Computer.FileSystem.GetTempFileName() My.Computer.FileSystem.WriteAllText(LogFileName, e.Exception.ToString(), False) System.Diagnostics.Process.Start("notepad.exe", LogFileName) End If e.ExitApplication = True End Sub End Class End Namespace
Application Settings
Téměř každá aplikace má nějaká nastavení, která jest třeba někde ukládat. Obvykle v nějakém konfiguračním souboru, případně v registrech. Což s sebou nese nutnost se o tyto údaje starat a validovat je. Whidbey disponuje technologií, která tyto operace provádí transparentně a vystavuje je pro programátora ve formě strongly-typed třídy, dostupné jako My.Settings
.
Předtím, než začneme experimentovat s nastaveními, doporučuji ještě na záložce Application klepnout na tlačítko Assembly Information a nastavit metadata týkající se aplikace. V předchozí verzi se zapisovaly do souboru AssemblyInfo.vb
(ten je přítomen stále, ale je generován automaticky a skryt v adresář My Project
), nyní je na to i GUI.
Konfigurace totiž rozeznává dva druhy parametrů: per user a per application. Ty aplikační jsou uloženy klasicky v souboru jménoassembly.config
, ale uživatelské jsou uloženy do souboru v uživatelově profilu. Přesná cesta k němu se generuje právě na základě shora uvedených metadat.
Po dokončení nezbytných příprav jest nám vrhnouti se na genervání vlastních nastavení. Za tímto účelem se v okně My Project přepneme na záložku Settings, kdežtě můžeme určovat konfigurační proměnné, jejich typy a defaultní hodnoty:
Milé je, že jako typ konfigurační proměnné je možno použít cokoliv, nejenom primitivní typy jako String
nebo Integer
. Příkladem budiž Enum typy použité pro uložení nastavení sériového portu (např. System.IO.Ports.StopBits
a další). Načítání se pak v kódu děje způsobem, jež je až urážlivě jednoduchý:
Dim Port As New System.IO.Ports.SerialPort() Port.PortName = My.Settings.SensorPortName Port.BaudRate = My.Settings.SensorBaudRate Port.DataBits = My.Settings.SensorDataBits Port.StopBits = My.Settings.SensorStopBits Port.Parity = My.Settings.SensorParity Port.ReadTimeout = My.Settings.SensorTimeout Port.DtrEnable = True Port.Open()
Pokud se jedná o nastavení s user scope, je možno stejným způsobem hodnoty nejenom číst, ale i nastavovat (po dokončení nastavování zavolejte My.Settings.Save()
). Nastavení s application scope nelze za běhu aplikace měnit.
Ikonka v system tray a "Baloon tip" notifikace
Komponenta NotifyIcon
, reprezentující ikonu v system tray (lokace známá též jako "vedle hodin") byla k dispozici již v předchozích verzích .NET Frameworku. Její Whidbey verze obsahuje též podporu pro "Baloon tip" - notifikaci nově používanou ve Windows XP.
V souvislosti s NotifyIcon umí aplikace tři věci:
- Po minimalizaci se "schová" do ikonky.
- Po klepnutí na ikonku zobrazí baloon tip s aktuálními údaji o teplotě.
- Po klepnutí na ikonku pravým tlačítkem zobrazí okno aplikace.
Stará se o to následující kód:
Private Sub FormMain_Resize(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles Me.Resize
If Me.WindowState = FormWindowState.Minimized Then Me.Visible = False Me.TrayIcon.Visible = True End If End Sub
Private Sub TrayIcon_MouseClick(ByVal sender As Object, _ ByVal e As System.Windows.Forms.MouseEventArgs) _ Handles TrayIcon.MouseClick If e.Button = Windows.Forms.MouseButtons.Right Then Me.Visible = True Me.TrayIcon.Visible = False Me.WindowState = FormWindowState.Normal Else Dim Message As String = String.Format("{0}: {1}\n{2}: {3}", _ Me.GroupBoxSensor.Text, Me.LabelSensor.Text, _ Me.GroupBoxService.Text, Me.LabelService.Text) Me.TrayIcon.ShowBalloonTip(5, "Current temperature", _ Message.Replace("\n", vbCrLf), ToolTipIcon.Info) End If End Sub
Závěrem
Toto je funkční aplikace, která využívá některé nové možnosti, dostupné v Microsoft .NET Beta 2. K jejímu spuštění potřebujete Whidbey beta 2, projekt je pro VS.NET, ale měl by být kompatibilní i s Visual Basic Expressem.
Pracuji na obsáhlejším projektu, který bude umět centralizovaně monitorovat teplotu ve více bodech, včetně síťové komunikace a využití pokročilejších papouščích čidel. Dočkáte se ho během několika týdnů.