CarlD 12 Posted November 26, 2020 (edited) Vane is a script that displays METAR weather reports from airports and other locations around the world. I think the usage is self-explanatory: just enter the name of a location (City, STate|COuntry), or a substring thereof, or a 3-character IATA airport code, and hit Enter. Input is accepted on the command line or solicited interactively. Enjoy! expandcollapse popup#Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_Outfile=Vane.exe #AutoIt3Wrapper_UseUpx=y #AutoIt3Wrapper_Compile_Both=y #AutoIt3Wrapper_UseX64=y #AutoIt3Wrapper_AU3Check_Parameters=-w 3 -w 4 -w 5 -w 6 -d #AutoIt3Wrapper_Run_Au3Stripper=y #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** ; ; Vane.exe -- Get METAR weather reports from around the world ; CLD rev. 11/29/2020 ; #include <AutoItConstants.au3> #include <ButtonConstants.au3> #include <FileConstants.au3> #include <FontConstants.au3> #include <GUIConstants.au3> #include <GUIConstantsEx.au3> #include <ListBoxConstants.au3> #include <Misc.au3> #include <MsgBoxConstants.au3> #include <StringConstants.au3> #include <StructureConstants.au3> #include <WindowsConstants.au3> ; Global $X = -1, $Y = -1 Global $aIn[3], $aLout, $aLst, $aOut, $aW Global $hDLL, $hF, $hgGet, $hgList, $hgListA, _ $hgNG, $hgNGin, $hgRun, $hI, $hV Global $iB, $iH, $iHgt, $iM, $iTmp, $iW, $iWid, $iZ Global $sDFn = @ScriptDir & "\$0vane.txt", $sIn = "", _ $sLst = "", $sOut = "", $sReport, $sStaIn = "", $sStaOut, _ $sStationIn, $sTmF, $stmFb, $sTxt, $sURL, _ $sVal = "", $sValIn Global $hWndListA, $fAction, $sLastSel, $wProcHandle, $tagNHMDR, _ $hWndFrom, $iCode If $CmdLine[0] Then For $k = 1 To $CmdLine[0] $sIn &= $CmdLine[$k] If $k < $CmdLine[0] Then $sIn &= " " Next EndIf $sURL = "http://www.aviationweather.gov/docs/metar/stations.txt" $sTmF = @TempDir & "\stations.txt" $sTmFb = @TempDir & "\stations.tx0" If FileExists($sTmF) Then FileCopy($sTmF, $sTmFb, 1) $hI = InetGet($sURL, $sTmF, 1, 0) InetClose($hI) If Not $hI Then If FileExists($sTmFb) Then FileCopy($sTmFb, $sTmF, 1) Else Exit MsgBox($MB_SYSTEMMODAL, @ScriptName, "Data download failed", 4) EndIf EndIf $hF = FileOpen($sTmF) If $hF < 0 Then Exit MsgBox($MB_SYSTEMMODAL, @ScriptName, "Error opening data file", 4) $sLst = FileRead($hF) FileClose($hF) $sLst = StringTrimRight($sLst, 2 + StringInStr($sLst, @LF&@LF)) $aLst = StringSplit($sLst, @LF) If $sIn Then $sOut = _GetStations($sIn) If Not $sOut Then Exit MsgBox($MB_SYSTEMMODAL, @ScriptName, "Weather station not found") $sOut = StringReplace($sOut, "||", "|") If StringInStr($sOut, "|") = StringLen($sOut) Then $sOut = StringTrimRight($sOut, 1) If StringInStr($sOut, "|") Then GUISetState(@SW_HIDE, $hgNG) GUICtrlSetState(@SW_HIDE, $hgNGin) GUICtrlSetData($hgListA, $sOut) GUICtrlSetState(@SW_SHOW, $hgList) GUISetState(@SW_SHOW, $hgList) ControlSend("", "", $hgList, "{down}") EndIf EndIf If $sOut And Not StringInStr($sOut, "|") Then $sStaIn = $sOut $sOut = "" $sIn = "!" EndIf If Not $sStaIn And Not $sOut And $sIn And $sIn <> "!" Then $sStaIn = $sIn $sIn = "" EndIf If $sStaIn And StringInStr($sStaIn, "|") = 0 Then _Loc2Station($sStaIn) If $sStaIn = "" Or ($sIn And $sIn <> "!") Or $sOut Then ;------------------------------------- Start GUI $hgNG = GUICreate(@ScriptName, 700, 200, $X, $Y, $WS_EX_APPWINDOW) GUISetFont(16, $FW_MEDIUM, $GUI_FONTNORMAL, "", $hgNG, $ANTIALIASED_QUALITY) GUICtrlCreateLabel("Enter City[, STate|COuntry]|AIRport|sub$tring (""|""=OR):", 40, 25, 700, 35) $hgNGin = GUICtrlCreateInput($sIn, 40, 75, 600, 40, -1, $ES_RIGHT) If Not StringInStr($sOut, "|") Then GUICtrlSetData($hgNGin, $sOut, "") $hgRun = GUICtrlCreateButton("Enter", 450, 145, 110, 40, $BS_DEFPUSHBUTTON) GUICtrlSetState($hgRun, $GUI_HIDE) If Not StringInStr($sOut, "|") Then GUICtrlSetState($hgNGin, $GUI_SHOW) GUISetState(@SW_SHOW, $hgNG) Else GUISetState(@SW_HIDE, $hgNG) GUICtrlSetState($hgNGin, $GUI_HIDE) EndIf $hgList = GUICreate(@ScriptName & ": Select and hit Enter", 500, 350, -1, -1, $ES_CENTER) GUISetFont(14, $FW_SEMIBOLD, $GUI_FONTNORMAL, "", $hgList, $ANTIALIASED_QUALITY) $hgListA = GUICtrlCreateList ("", -1, -1, 500, 340) $hWndListA = GUICtrlGetHandle($hgListA) $hgGet = GUICtrlCreateButton("Get", 450, 175, 120, 40, $BS_DEFPUSHBUTTON) GUICtrlSetState($hgGet, $GUI_HIDE) If $sOut Then GUISetState(@SW_UNLOCK, $hgList) GUICtrlSetState(@SW_UNLOCK, $hgListA) GUICtrlSetData($hgListA, $sOut) GUICtrlSetState($hgListA, $GUI_SHOW) GUISetState(@SW_SHOW, $hgList) ControlSend("", "", $hgList, "{down}") EndIf GUIRegisterMsg($WM_COMMAND, "WM_COMMAND") $fAction = 0 $sLastSel = "" While 1 Switch GUIGetMsg() Case $hgRun If Not $sOut Then $sIn = GUICtrlRead($hgNGin) If $sIn Then $sOut = _GetStations($sIn) If Not $sOut Then GUISetState(@SW_HIDE, $hgNG) GUICtrlSetState(@SW_HIDE, $hgNGin) Exit MsgBox($MB_SYSTEMMODAL, @ScriptName, "No matching weather stations found") EndIf $sOut = StringReplace($sOut, "||", "|") If StringInStr($sOut, "|") Then GUISetState(@SW_HIDE, $hgNG) GUICtrlSetState(@SW_HIDE, $hgNGin) GUISetState(@SW_UNLOCK, $hgList) GUICtrlSetState($hgListA, @SW_UNLOCK) GUICtrlSetData($hgListA, $sOut) GUISetState(@SW_SHOW, $hgList) GUICtrlSetState($hgListA,@SW_SHOW) ControlSend("", "", $hgList, "{down}") ContinueLoop EndIf EndIf If $sOut And Not StringInStr($sOut, "|") Then $sStaIn = $sOut $sOut = "" $sIn = "!" _Loc2Station($sStaIn) Else GUICtrlSetState(@SW_HIDE, $hgNGin) GUISetState(@SW_HIDE, $hgNG) GUISetState(@SW_UNLOCK, $hgList) GUICtrlSetState($hgListA,@SW_UNLOCK) GUICtrlSetData($hgListA, $sOut) GUISetState(@SW_SHOW, $hgList) GUICtrlSetState(@SW_SHOW, $hgListA) ContinueLoop EndIf Else If GUICtrlRead($hgNGin) Then $sStaIn = GUICtrlRead($hgNGin) GUISetState(@SW_HIDE, $hgNG) _Loc2Station($sStaIn) EndIf Case $hgGet _ListAGet() Case $GUI_EVENT_CLOSE GUIDelete($hgNG) GUIDelete($hgList) DllCallbackFree($wProcHandle) Exit EndSwitch If GUICtrlRead($hgListA) <> $sLastSel Then $sLastSel = GUICtrlRead($hgListA) ; Wait to see if there is a double click Sleep(150) If $fAction = 1 Then _ListAGet() $fAction = 0 Else If $fAction = 1 Then _ListAGet() $fAction = 0 EndIf EndIf WEnd EndIf ;-------------------------------- End GUI ;-------------------------------- Function defs Func _ListAGet() If GUICtrlRead($hgListA) Then $sStaIn = GUICtrlRead($hgListA) GUISetState(@SW_HIDE, $hgList) _Loc2Station($sStaIn) If StringInStr($sOut, "|") Then GUISetState(@SW_SHOW, $hgList) GUICtrlSetState($hgListA, @SW_SHOW) EndIf EndIf Return EndFunc ;==>_ListAGet Func _Loc2Station($sStationIn) If $sStationIn Then Local $iZ = 0 $sVal = StringStripWS($sStaIn, $STR_STRIPLEADING + $STR_STRIPTRAILING) While 1 + StringLen($sVal) - StringInStr($sVal, " ", 0, -1) <> 5 $iZ += 1 If $iZ < 10 Then $sVal = StringTrimRight($sVal, 1 + StringLen($sVal) - StringInStr($sVal, " ", 0, -1)) Else ExitLoop EndIf WEnd $sVal = StringRight($sVal, 4) EndIf If Not StringIsAlNum($sVal) Then Return MsgBox($MB_SYSTEMMODAL, @ScriptName, "Weather station not found") Else Return _GetReport($sVal) EndIf EndFunc ;==>_Loc2Station Func _GetReport($sValIn) Local $iB = InetGet("https://tgftp.nws.noaa.gov/data/observations/metar/decoded/" & $sValIn & ".TXT", $sDFn, 3, 0) InetClose($iB) If Not $iB Then Return Msgbox($MB_SYSTEMMODAL, @ScriptName, "No data") Do Sleep(100) Until FileExists($sDFn) $hV = FileOpen($sDFn) If $hV > -1 Then $sReport = FileRead($hV) FileClose($hV) FileDelete($sDFn) EndIf $aW = StringSplit($sReport, @LF) $iW = 400 $iH = 30 * $aW[0] $iM = 14 $sReport = "" For $j = 1 To $aW[0] If StringInStr($aW[$j], "ob:") Then ExitLoop $sReport &= $aW[$j] & @LF If $iM * StringLen($aW[$j]) > $iW Then $iW = $iM * StringLen($aW[$j]) If $iW > 1200 Then $iW = 1100 EndIf Next Return _Splash($sReport, $iW, $iH) EndFunc ;==>_GetReport Func _GetStations($sIn) Local $sCity = $sIn, $sInn = "" Local $sState = "", $sStaOut = "", $aIn, $aOr[2] $aOr[0] = 1 $aOr[1] = $sIn If StringInStr($sIn, "|") Then $aOr = StringSplit($sIn, "|") FOR $n = 1 To $aOr[0] ;-------------------- $sInn = $aOr[$n] $sState = "" If StringInStr($sInn, ",") Then $aIn = StringSplit($sInn, ",") $sCity = StringStripWS($aIn[1], $STR_STRIPLEADING + _ $STR_STRIPTRAILING + $STR_STRIPSPACES) $sState = StringStripWS($aIn[2], $STR_STRIPLEADING + _ $STR_STRIPTRAILING + $STR_STRIPSPACES) EndIf If $sState Then For $i = 1 To $aLst[0] If StringInStr($aLst[$i], "!") = 1 Then ContinueLoop If StringInStr($aLst[$i], StringLeft($sState, 2)) = 1 Then If StringInStr($aLst[$i], $sCity) Then $sStaOut &= StringStripWS(StringLeft($aLst[$i], 32), $STR_STRIPTRAILING) & "|" EndIf If $sState = StringRight($aLst[$i], 2) Then If StringInStr($aLst[$i], $sCity) Then $sStaOut &= StringStripWS(StringLeft($aLst[$i], 32), $STR_STRIPTRAILING) & "|" EndIf Next Else For $i = 1 To $aLst[0] If StringInStr($aLst[$i], "!") = 1 Then ContinueLoop If StringLen($sInn) = 3 And StringInStr($aLst[$i], " "&$sInn&" ") > 1 Then If $aOr[0] = 1 Then Return StringStripWS(StringLeft($aLst[$i], 32), $STR_STRIPLEADING + $STR_STRIPTRAILING) & "|" Else $sStaOut &= StringStripWS(StringLeft($aLst[$i], 32), $STR_STRIPLEADING + $STR_STRIPTRAILING) & "|" ExitLoop 2 EndIf EndIf If StringInStr($aLst[$i], $sInn) Then _ $sStaOut &= StringStripWS(StringLeft($aLst[$i], 32), $STR_STRIPLEADING + $STR_STRIPTRAILING) & "|" Next EndIf #cs If StringInStr($sStaOut, "|") = StringLen($sStaOut) Then $sStaOut = StringTrimRight($sStaOut, 1) $sInn = "" EndIf #ce If StringInStr($sStaOut, "|") > 1 Then $aLOut = StringSplit($sStaOut, "|") $sInn = $aLOut[1] $sOut = "" If $aLOut[0] > 0 Then For $i = 1 To $aLOut[0] $sOut &= StringStripWS($aLOut[$i], $STR_STRIPLEADING) & "|" Next $sStaOut = $sOut Else $sStaIn = $sInn $sStaOut = "" EndIf EndIf If $sStaOut = "|" Then $sStaOut = "" NEXT ;=== Return $sStaOut EndFunc ;==>_GetStations Func _Splash($sTxt, $iWid = 800, $iHgt = 450) Local $hDLL = DLLOpen("user32.dll") SplashTextOn("Station " & $sVal & " | Esc quits", $sTxt, $iWid, $iHgt, -1, -1, $DLG_TEXTLEFT + $DLG_MOVEABLE + $DLG_TEXTVCENTER, "", 14) While 1 If _IsPressed("1B", $hDLL) Then SplashOff() ExitLoop EndIf WEnd DLLClose($hDLL) Return EndFunc ;==>_Splash Func WM_COMMAND($hWnd, $iMsg, $wParam, $lParam) ; Mouse-click handler for List box [credit: Melba23] #forceref $hWnd, $iMsg Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam) $hWndFrom = $lParam $iCode = BitShift($wParam, 16) ; Hi Word Switch $hWndFrom Case $hWndListA Switch $iCode Case $LBN_DBLCLK ; User double-clicks a string in a list box $fAction = 1 EndSwitch EndSwitch EndFunc ; Edited December 1, 2020 by CarlD Share this post Link to post Share on other sites
CarlD 12 Posted November 29, 2020 (edited) Added support for mouse double-click on List box items, using @Melba23's handler (thanks!). Edited November 29, 2020 by CarlD Share this post Link to post Share on other sites