Jump to content
CarlD

Vane (weather)

Recommended Posts

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!

#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 by CarlD

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...