diff --git a/WinNUT_V2/WinNUT-Client_Common/Common_Classes.vb b/WinNUT_V2/WinNUT-Client_Common/Common_Classes.vb index b8c501f..26bc3a5 100644 --- a/WinNUT_V2/WinNUT-Client_Common/Common_Classes.vb +++ b/WinNUT_V2/WinNUT-Client_Common/Common_Classes.vb @@ -36,6 +36,7 @@ Public Class Nut_Exception Inherits System.ApplicationException Public Property ExceptionValue As Nut_Exception_Value + Public Property ProtocolError As NUTResponse Public Sub New(ByVal Nut_Error_Lvl As Nut_Exception_Value) MyBase.New(StringEnum.GetStringValue(Nut_Error_Lvl)) @@ -45,6 +46,16 @@ Public Class Nut_Exception MyBase.New(StringEnum.GetStringValue(Nut_Error_Lvl) & Message, innerEx) ExceptionValue = Nut_Error_Lvl End Sub + + ''' + ''' Raise a Nut_Exception that resulted from an error as part of the NUT protocol. + ''' + ''' + ''' + Public Sub New(protocolError As NUTResponse, message As String) + MyBase.New(message) + Me.ProtocolError = protocolError + End Sub End Class Public Class Nut_Parameter diff --git a/WinNUT_V2/WinNUT-Client_Common/Nut_Socket.vb b/WinNUT_V2/WinNUT-Client_Common/Nut_Socket.vb index 86caf37..ecb0ec4 100644 --- a/WinNUT_V2/WinNUT-Client_Common/Nut_Socket.vb +++ b/WinNUT_V2/WinNUT-Client_Common/Nut_Socket.vb @@ -66,10 +66,9 @@ Public Class Nut_Socket 'Public Event OnNotice(Message As String, NoticeLvl As LogLvl, sender As Object, ReportToGui As Boolean) Public Event OnNotice(Message As String, NoticeLvl As LogLvl, sender As Object) 'Public Event OnError(Excep As Exception, NoticeLvl As LogLvl, sender As Object, ReportToGui As Boolean) - Public Event OnError(Excep As Exception, NoticeLvl As LogLvl, sender As Object) - Public Event OnNUTException(ex As Nut_Exception, NoticeLvl As LogLvl, sender As Object) + ' Public Event OnError(Excep As Exception, NoticeLvl As LogLvl, sender As Object) - Public Event Unknown_UPS() + ' Public Event Unknown_UPS() Public Event Socket_Broken() ''' @@ -88,51 +87,68 @@ Public Class Nut_Socket 'End With End Sub - Public Function Connect() As Boolean - Try - 'TODO: Use LIST UPS protocol command to get valid UPSs. - Dim Host = NutConfig.Host - Dim Port = NutConfig.Port - Dim Login = NutConfig.Login - Dim Password = NutConfig.Password - - If Not String.IsNullOrEmpty(Host) And Not IsNothing(Port) Then - Create_Socket(Host, Port) - - If ConnectionStatus Then - AuthLogin(Login, Password) - ' Bad login shouldn't necessarily preclude a successful connection (basic ops can still occur.) - 'If Not AuthLogin(Login, Password) Then - ' ' Throw New Nut_Exception(Nut_Exception_Value.INVALID_AUTH_DATA) - ' RaiseEvent OnNUTException() - 'End If - Dim Nut_Query = Query_Data("VER") - - If Nut_Query.Response = NUTResponse.OK Then - Nut_Ver = (Nut_Query.Data.Split(" "c))(4) - End If - Nut_Query = Query_Data("NETVER") - - If Nut_Query.Response = NUTResponse.OK Then - Net_Ver = Nut_Query.Data - End If - - LogFile.LogTracing(String.Format("NUT server reports VER: {0} NETVER: {1}", Nut_Ver, Net_Ver), LogLvl.LOG_NOTICE, Me) - Return True - End If - End If + Public Sub Connect() ' As Boolean + ' Try + 'TODO: Use LIST UPS protocol command to get valid UPSs. + Dim Host = NutConfig.Host + Dim Port = NutConfig.Port + Dim Login = NutConfig.Login + Dim Password = NutConfig.Password + + If String.IsNullOrEmpty(Host) Or IsNothing(Port) Then + Throw New InvalidOperationException("Host and Port must be specified to connect.") + End If - Catch nutEx As Nut_Exception - ' Handle NUT exceptions specifically, without variable boxing/unboxing - RaiseEvent OnNUTException(nutEx, LogLvl.LOG_ERROR, Me) - Return False + Try + ' NutSocket = New Socket(AddressFamily.InterNetwork, ProtocolType.IP) + NutSocket = New Socket(SocketType.Stream, ProtocolType.IP) + LogFile.LogTracing(String.Format("Attempting TCP socket connection to {0}:{1}...", Host, Port), LogLvl.LOG_NOTICE, Me) + NutSocket.Connect(Host, Port) + NutTCP = New TcpClient(Host, Port) + NutStream = NutTCP.GetStream + ReaderStream = New StreamReader(NutStream) + WriterStream = New StreamWriter(NutStream) + LogFile.LogTracing(String.Format("Connection established and streams ready for {0}:{1}", Host, Port), LogLvl.LOG_NOTICE, Me) Catch Excep As Exception - RaiseEvent OnError(Excep, LogLvl.LOG_ERROR, Me) - Return False + Disconnect(True, True) + Throw ' Pass exception on up to UPS + ' RaiseEvent EncounteredNUTException(New Nut_Exception(Nut_Exception_Value.CONNECT_ERROR, Excep.Message), LogLvl.LOG_ERROR, Me) End Try - Return False - End Function + If ConnectionStatus Then + AuthLogin(Login, Password) + ' Bad login shouldn't preclude a successful connection (basic ops can still occur.) + 'If Not AuthLogin(Login, Password) Then + ' ' Throw New Nut_Exception(Nut_Exception_Value.INVALID_AUTH_DATA) + ' RaiseEvent EncounteredNUTException() + 'End If + Dim Nut_Query = Query_Data("VER") + + If Nut_Query.Response = NUTResponse.OK Then + Nut_Ver = (Nut_Query.Data.Split(" "c))(4) + End If + Nut_Query = Query_Data("NETVER") + + If Nut_Query.Response = NUTResponse.OK Then + Net_Ver = Nut_Query.Data + End If + + LogFile.LogTracing(String.Format("NUT server reports VER: {0} NETVER: {1}", Nut_Ver, Net_Ver), LogLvl.LOG_NOTICE, Me) + ' Return True + End If + + 'Catch nutEx As Nut_Exception + ' ' Handle NUT exceptions specifically, without variable boxing/unboxing + ' RaiseEvent EncounteredNUTException(nutEx, LogLvl.LOG_ERROR, Me) + ' Return False + 'Catch Excep As Exception + ' 'RaiseEvent OnError(Excep, LogLvl.LOG_ERROR, Me) + ' 'Return False + + 'End Try + + ' Return False + End Sub ''' ''' Perform various functions necessary to disconnect the socket from the NUT server. @@ -157,38 +173,28 @@ Public Class Nut_Socket End Sub Private Sub Create_Socket(Host As String, Port As Integer) - Try - ' NutSocket = New Socket(AddressFamily.InterNetwork, ProtocolType.IP) - NutSocket = New Socket(SocketType.Stream, ProtocolType.IP) - LogFile.LogTracing(String.Format("Attempting TCP socket connection to {0}:{1}...", Host, Port), LogLvl.LOG_NOTICE, Me) - NutSocket.Connect(Host, Port) - NutTCP = New TcpClient(Host, Port) - NutStream = NutTCP.GetStream - ReaderStream = New StreamReader(NutStream) - WriterStream = New StreamWriter(NutStream) - LogFile.LogTracing(String.Format("Connection established and streams ready for {0}:{1}", Host, Port), LogLvl.LOG_NOTICE, Me) - Catch Excep As Exception - Disconnect(True) - RaiseEvent OnNUTException(New Nut_Exception(Nut_Exception_Value.CONNECT_ERROR, Excep.Message), LogLvl.LOG_ERROR, Me) - End Try + End Sub - Public ReadOnly Property IsKnownUPS(Test_UPSname As String) As Boolean - Get - If Not ConnectionStatus Then - Return False - Else - Dim IsKnow As Boolean = False - Dim ListOfUPSs = Query_List_Datas("LIST UPS") - For Each Known_UPS In ListOfUPSs - If Known_UPS.VarValue = Test_UPSname Then - IsKnow = True - End If - Next - Return IsKnow - End If - End Get - End Property + ''' + ''' Determines if the current UPS exists on the upsd server. + ''' An invalid UPS name isn't necessarily fatal. + ''' + ''' + 'Public ReadOnly Property ExistsOnServer(name As String) As Boolean + ' Get + ' If IsConnected Then + ' Dim ListOfUPSs = Query_List_Datas("LIST UPS") + ' For Each Known_UPS In ListOfUPSs + ' If Known_UPS.VarValue = name Then + ' Return True + ' End If + ' Next + ' End If + + ' Return False + ' End Get + 'End Property Public Function Query_Data(Query_Msg As String) As (Data As String, Response As NUTResponse) Dim Response As NUTResponse = NUTResponse.NORESPONSE @@ -214,156 +220,165 @@ Public Class Nut_Socket ' ' Try to safely shut everything down and notify listeners. ' ' Disconnect() ' RaiseEvent Socket_Broken() - ' RaiseEvent OnNUTException(New Nut_Exception(Nut_Exception_Value.SOCKET_BROKEN, Query_Msg, ioEx), LogLvl.LOG_ERROR, Me) + ' RaiseEvent EncounteredNUTException(New Nut_Exception(Nut_Exception_Value.SOCKET_BROKEN, Query_Msg, ioEx), LogLvl.LOG_ERROR, Me) ' ' Return (Nothing, NUTResponse.NORESPONSE) 'Catch Excep As Exception ' RaiseEvent OnError(Excep, LogLvl.LOG_ERROR, Me) ' Return (DataResult, Response) 'End Try End Function - Public Function Query_Desc(ByVal VarName As String) As String - Try - If Not Me.ConnectionStatus Then - Disconnect() - RaiseEvent Socket_Broken() - Throw New Nut_Exception(Nut_Exception_Value.SOCKET_BROKEN, VarName) - Else - Dim Nut_Query = Query_Data("GET DESC " & Me.NutConfig.UPSName & " " & VarName) - Select Case Nut_Query.Response - Case NUTResponse.OK - 'LogFile.LogTracing("Process Result With " & VarName & " : " & Nut_Query.Data, LogLvl.LOG_DEBUG, Me) - Return Nut_Query.Data - Case NUTResponse.UNKNOWNUPS - RaiseEvent Unknown_UPS() - Return Nothing - Case Else - 'LogFile.LogTracing("Error Result On Retrieving " & VarName & " : " & Nut_Query.Data, LogLvl.LOG_ERROR, Me) - Return Nothing - End Select - End If - Catch Excep As Exception - RaiseEvent OnError(Excep, LogLvl.LOG_ERROR, Me) - Return Nothing - End Try + + Public Function GetVarDescription(VarName As String) As String + ' Try + 'If Not Me.ConnectionStatus Then + ' Disconnect() + ' RaiseEvent Socket_Broken() + ' Throw New Nut_Exception(Nut_Exception_Value.SOCKET_BROKEN, VarName) + ' Else + + Dim Nut_Query = Query_Data("GET DESC " & NutConfig.UPSName & " " & VarName) + + If Nut_Query.Response = NUTResponse.OK Then + Return Nut_Query.Data + Else + Throw New Nut_Exception(Nut_Query.Response, "Protocol error encountered while getting variable description.") + End If + + 'Select Case Nut_Query.Response + ' Case NUTResponse.OK + ' 'LogFile.LogTracing("Process Result With " & VarName & " : " & Nut_Query.Data, LogLvl.LOG_DEBUG, Me) + ' Return Nut_Query.Data + ' Case NUTResponse.UNKNOWNUPS + ' RaiseEvent Unknown_UPS() + ' Return Nothing + ' Case Else + ' 'LogFile.LogTracing("Error Result On Retrieving " & VarName & " : " & Nut_Query.Data, LogLvl.LOG_ERROR, Me) + ' Return Nothing + 'End Select + ' End If + 'Catch Excep As Exception + ' RaiseEvent OnError(Excep, LogLvl.LOG_ERROR, Me) + ' Return Nothing + 'End Try End Function Public Function Query_List_Datas(Query_Msg As String) As List(Of UPS_List_Datas) Dim List_Datas As New List(Of String) Dim List_Result As New List(Of UPS_List_Datas) - Try - If Me.ConnectionStatus Then - Me.WriterStream.WriteLine(Query_Msg & vbCr) - Me.WriterStream.Flush() - Threading.Thread.Sleep(100) - Dim DataResult As String = "" - Dim start As DateTime = DateTime.Now - Do - DataResult = Me.ReaderStream.ReadLine() - List_Datas.Add(DataResult) - Loop Until (IsNothing(DataResult) Or (Me.ReaderStream.Peek < 0)) - - If (EnumResponse(List_Datas(0)) <> NUTResponse.OK) Or (List_Datas.Count = 0) Then - Throw New Nut_Exception(Nut_Exception_Value.SOCKET_BROKEN, Query_Msg) - End If - - Dim Key As String - Dim Value As String - For Each Line In List_Datas - Dim SplitString = Split(Line, " ", 4) + ' Try + If Me.ConnectionStatus Then + Me.WriterStream.WriteLine(Query_Msg & vbCr) + Me.WriterStream.Flush() + Threading.Thread.Sleep(100) + Dim DataResult As String = "" + Dim start As DateTime = DateTime.Now + Do + DataResult = Me.ReaderStream.ReadLine() + List_Datas.Add(DataResult) + Loop Until (IsNothing(DataResult) Or (Me.ReaderStream.Peek < 0)) + + If (EnumResponse(List_Datas(0)) <> NUTResponse.OK) Or (List_Datas.Count = 0) Then + Throw New Nut_Exception(Nut_Exception_Value.SOCKET_BROKEN, Query_Msg) + End If - Select Case SplitString(0) - Case "BEGIN" - Case "VAR" - 'Query - 'LIST VAR - 'Response List of var - 'VAR "" - Key = Strings.Replace(SplitString(2), """", "") - Value = Strings.Replace(SplitString(3), """", "") - Dim UPSName = SplitString(1) - Dim VarDESC = Query_Desc(Key) - If Not IsNothing(VarDESC) Then - List_Result.Add(New UPS_List_Datas With { - .VarKey = Key, - .VarValue = Trim(Value), - .VarDesc = Split(Strings.Replace(VarDESC, """", ""), " ", 4)(3)} - ) - Else - 'TODO: Convert to nut_exception error - Throw New Exception("error") - End If - Case "UPS" - 'Query - 'LIST UPS - 'List of ups - 'UPS "" + Dim Key As String + Dim Value As String + For Each Line In List_Datas + Dim SplitString = Split(Line, " ", 4) + + Select Case SplitString(0) + Case "BEGIN" + Case "VAR" + 'Query + 'LIST VAR + 'Response List of var + 'VAR "" + Key = Strings.Replace(SplitString(2), """", "") + Value = Strings.Replace(SplitString(3), """", "") + Dim UPSName = SplitString(1) + Dim VarDESC = GetVarDescription(Key) + If Not IsNothing(VarDESC) Then List_Result.Add(New UPS_List_Datas With { - .VarKey = "UPSNAME", - .VarValue = SplitString(1), - .VarDesc = Strings.Replace(SplitString(2), """", "")} - ) - Case "RW" - 'Query - 'LIST RW - 'List of RW var - 'RW "" - Key = Strings.Replace(SplitString(2), """", "") - Value = Strings.Replace(SplitString(3), """", "") - Dim UPSName = SplitString(1) - Dim VarDESC = Query_Desc(Key) - If Not IsNothing(VarDESC) Then - List_Result.Add(New UPS_List_Datas With { - .VarKey = Key, - .VarValue = Trim(Value), - .VarDesc = Split(Strings.Replace(VarDESC, """", ""), " ", 4)(3)} - ) - Else - 'TODO: Convert to nut_exception error - Throw New Exception("error") - End If - Case "CMD" + .VarKey = Key, + .VarValue = Trim(Value), + .VarDesc = Split(Strings.Replace(VarDESC, """", ""), " ", 4)(3)} + ) + Else + 'TODO: Convert to nut_exception error + Throw New Exception("error") + End If + Case "UPS" + 'Query + 'LIST UPS + 'List of ups + 'UPS "" + List_Result.Add(New UPS_List_Datas With { + .VarKey = "UPSNAME", + .VarValue = SplitString(1), + .VarDesc = Strings.Replace(SplitString(2), """", "")} + ) + Case "RW" + 'Query + 'LIST RW + 'List of RW var + 'RW "" + Key = Strings.Replace(SplitString(2), """", "") + Value = Strings.Replace(SplitString(3), """", "") + Dim UPSName = SplitString(1) + Dim VarDESC = GetVarDescription(Key) + If Not IsNothing(VarDESC) Then + List_Result.Add(New UPS_List_Datas With { + .VarKey = Key, + .VarValue = Trim(Value), + .VarDesc = Split(Strings.Replace(VarDESC, """", ""), " ", 4)(3)} + ) + Else + 'TODO: Convert to nut_exception error + Throw New Exception("error") + End If + Case "CMD" 'Query 'LIST CMD 'List of CMD 'CMD - Case "ENUM" - 'Query - 'LIST ENUM - 'List of Enum ?? - 'ENUM "" - Key = Strings.Replace(SplitString(2), """", "") - Value = Strings.Replace(SplitString(3), """", "") - Dim UPSName = SplitString(1) - Dim VarDESC = Query_Data("GET DESC " & UPSName & " " & Key) - If VarDESC.Response = NUTResponse.OK Then - List_Result.Add(New UPS_List_Datas With { - .VarKey = Key, - .VarValue = Value, - .VarDesc = Split(Strings.Replace(VarDESC.Data, """", ""), " ", 4)(3)} - ) - Else - 'TODO: Convert to nut_exception error - Throw New Exception("error") - End If - Case "RANGE" + Case "ENUM" + 'Query + 'LIST ENUM + 'List of Enum ?? + 'ENUM "" + Key = Strings.Replace(SplitString(2), """", "") + Value = Strings.Replace(SplitString(3), """", "") + Dim UPSName = SplitString(1) + Dim VarDESC = Query_Data("GET DESC " & UPSName & " " & Key) + If VarDESC.Response = NUTResponse.OK Then + List_Result.Add(New UPS_List_Datas With { + .VarKey = Key, + .VarValue = Value, + .VarDesc = Split(Strings.Replace(VarDESC.Data, """", ""), " ", 4)(3)} + ) + Else + 'TODO: Convert to nut_exception error + Throw New Exception("error") + End If + Case "RANGE" 'Query 'LIST RANGE 'List of Range 'RANGE "" "" - Case "CLIENT" - 'Query - 'LIST CLIENT - 'List of Range - 'CLIENT - End Select - Next - End If - Return List_Result - Catch Excep As Exception - RaiseEvent OnError(Excep, LogLvl.LOG_ERROR, Me) - Me.Disconnect() - Return Nothing - End Try + Case "CLIENT" + 'Query + 'LIST CLIENT + 'List of Range + 'CLIENT + End Select + Next + End If + Return List_Result + 'Catch Excep As Exception + ' RaiseEvent OnError(Excep, LogLvl.LOG_ERROR, Me) + ' Me.Disconnect() + ' Return Nothing + 'End Try End Function ' Parse and enumerate a NUT protocol response. @@ -393,48 +408,48 @@ Public Class Nut_Socket End Function Private Sub AuthLogin(Login As String, Password As String) - Try - LogFile.LogTracing("Attempting authentication...", LogLvl.LOG_NOTICE, Me) - Auth_Success = False - If Not String.IsNullOrEmpty(Login) AndAlso String.IsNullOrEmpty(Password) Then - Dim Nut_Query = Query_Data("USERNAME " & Login) - - If Nut_Query.Response <> NUTResponse.OK Then - If Nut_Query.Response = NUTResponse.INVALIDUSERNAME Then - Throw New Nut_Exception(Nut_Exception_Value.INVALID_USERNAME) - ElseIf Nut_Query.Response = NUTResponse.ACCESSDENIED Then - Throw New Nut_Exception(Nut_Exception_Value.ACCESS_DENIED) - Else - Throw New Nut_Exception(Nut_Exception_Value.UNKNOWN_LOGIN_ERROR, Nut_Query.Data) - End If + ' Try + LogFile.LogTracing("Attempting authentication...", LogLvl.LOG_NOTICE, Me) + Auth_Success = False + If Not String.IsNullOrEmpty(Login) AndAlso String.IsNullOrEmpty(Password) Then + Dim Nut_Query = Query_Data("USERNAME " & Login) + + If Nut_Query.Response <> NUTResponse.OK Then + If Nut_Query.Response = NUTResponse.INVALIDUSERNAME Then + Throw New Nut_Exception(Nut_Exception_Value.INVALID_USERNAME) + ElseIf Nut_Query.Response = NUTResponse.ACCESSDENIED Then + Throw New Nut_Exception(Nut_Exception_Value.ACCESS_DENIED) + Else + Throw New Nut_Exception(Nut_Exception_Value.UNKNOWN_LOGIN_ERROR, Nut_Query.Data) End If + End If - Nut_Query = Query_Data("PASSWORD " & Password) + Nut_Query = Query_Data("PASSWORD " & Password) - If Nut_Query.Response <> NUTResponse.OK Then - If Nut_Query.Response = NUTResponse.INVALIDPASSWORD Then - Throw New Nut_Exception(Nut_Exception_Value.INVALID_PASSWORD) - ElseIf Nut_Query.Response = NUTResponse.ACCESSDENIED Then - Throw New Nut_Exception(Nut_Exception_Value.ACCESS_DENIED) - Else - Throw New Nut_Exception(Nut_Exception_Value.UNKNOWN_LOGIN_ERROR, Nut_Query.Data) - End If + If Nut_Query.Response <> NUTResponse.OK Then + If Nut_Query.Response = NUTResponse.INVALIDPASSWORD Then + Throw New Nut_Exception(Nut_Exception_Value.INVALID_PASSWORD) + ElseIf Nut_Query.Response = NUTResponse.ACCESSDENIED Then + Throw New Nut_Exception(Nut_Exception_Value.ACCESS_DENIED) + Else + Throw New Nut_Exception(Nut_Exception_Value.UNKNOWN_LOGIN_ERROR, Nut_Query.Data) End If End If + End If - LogFile.LogTracing("Authenticated successfully.", LogLvl.LOG_NOTICE, Me) - Auth_Success = True - ' Return Me.Auth_Success - Catch nutEx As Nut_Exception - ' Auth issues aren't necessarily fatal - some interaction can still occur unauthenticated. - RaiseEvent OnNUTException(nutEx, LogLvl.LOG_ERROR, Me) - ' Auth_Success = False - ' Disconnect(True) - Catch Excep As Exception - RaiseEvent OnError(Excep, LogLvl.LOG_ERROR, Me) - Disconnect(True) - ' Auth_Success = False - End Try + LogFile.LogTracing("Authenticated successfully.", LogLvl.LOG_NOTICE, Me) + Auth_Success = True + ' Return Me.Auth_Success + 'Catch nutEx As Nut_Exception + ' ' Auth issues aren't necessarily fatal - some interaction can still occur unauthenticated. + ' RaiseEvent OnNUTException(nutEx, LogLvl.LOG_ERROR, Me) + ' ' Auth_Success = False + ' ' Disconnect(True) + 'Catch Excep As Exception + ' RaiseEvent OnError(Excep, LogLvl.LOG_ERROR, Me) + ' Disconnect(True) + ' ' Auth_Success = False + 'End Try End Sub Private Sub Event_WatchDog(sender As Object, e As EventArgs) diff --git a/WinNUT_V2/WinNUT-Client_Common/UPS_Device.vb b/WinNUT_V2/WinNUT-Client_Common/UPS_Device.vb index d603f7a..d373c71 100644 --- a/WinNUT_V2/WinNUT-Client_Common/UPS_Device.vb +++ b/WinNUT_V2/WinNUT-Client_Common/UPS_Device.vb @@ -108,7 +108,7 @@ Public Class UPS_Device 'Private Invalid_Auth_Data As Boolean = False 'Private Const CosPhi As Double = 0.6 - Public Event Unknown_UPS() + ' Public Event Unknown_UPS() Public Event DataUpdated() Public Event Connected(sender As UPS_Device) Public Event ReConnected(sender As UPS_Device) @@ -116,6 +116,9 @@ Public Class UPS_Device Public Event Disconnected() ' Notify of an unexpectedly lost connection (??) Public Event Lost_Connect() + ' Error encountered when trying to connect. + Public Event ConnectionError(innerException As Exception) + Public Event EncounteredNUTException(ex As Nut_Exception, sender As Object) Public Event New_Retry() Public Event Shutdown_Condition() Public Event Stop_Shutdown() @@ -145,23 +148,30 @@ Public Class UPS_Device End Sub Public Sub Connect_UPS() - ' Dim UPSName = Me.Nut_Config.UPSName LogFile.LogTracing("Beginning connection: " & Nut_Config.ToString(), LogLvl.LOG_DEBUG, Me) - If Nut_Socket.Connect() And Nut_Socket.IsConnected Then + Try + Nut_Socket.Connect() LogFile.LogTracing("TCP Socket Created", LogLvl.LOG_NOTICE, Me) - If Nut_Socket.IsKnownUPS(Nut_Config.UPSName) Then - UPS_Datas = GetUPSProductInfo() - Init_Constant(Nut_Socket) - Update_Data.Start() - RaiseEvent Connected(Me) - Else - LogFile.LogTracing("Given UPS Name is unknown", LogLvl.LOG_ERROR, Me) - RaiseEvent Unknown_UPS() - Disconnect(True, False, True) - End If - End If + ' If Nut_Socket.ExistsOnServer(Nut_Config.UPSName) Then + UPS_Datas = GetUPSProductInfo() + Init_Constant(Nut_Socket) + Update_Data.Start() + RaiseEvent Connected(Me) + ' Else + ' LogFile.LogTracing("Given UPS Name is unknown", LogLvl.LOG_ERROR, Me) + ' RaiseEvent Unknown_UPS() + ' Disconnect(True) + ' End If + Catch ex As Nut_Exception + ' This is how we determine if we have a valid UPS name entered, among other errors. + RaiseEvent EncounteredNUTException(ex, Me) + + Catch ex As Exception + RaiseEvent ConnectionError(ex) + + End Try End Sub 'Private Sub HandleDisconnectRequest(sender As Object, Optional cancelAutoReconnect As Boolean = True) Handles Me.RequestDisconnect @@ -252,13 +262,13 @@ Public Class UPS_Device End If End Sub - Private Sub NUTSocketError(nutEx As Nut_Exception, NoticeLvl As LogLvl, sender As Object) Handles Nut_Socket.OnNUTException - If nutEx.ExceptionValue = Nut_Exception_Value.SOCKET_BROKEN AndAlso nutEx.InnerException IsNot Nothing Then - LogFile.LogTracing("Socket_Broken event InnerException: " & nutEx.InnerException.ToString(), LogLvl.LOG_DEBUG, Me) - End If + 'Private Sub NUTSocketError(nutEx As Nut_Exception, NoticeLvl As LogLvl, sender As Object) Handles Nut_Socket.OnNUTException + ' If nutEx.ExceptionValue = Nut_Exception_Value.SOCKET_BROKEN AndAlso nutEx.InnerException IsNot Nothing Then + ' LogFile.LogTracing("Socket_Broken event InnerException: " & nutEx.InnerException.ToString(), LogLvl.LOG_DEBUG, Me) + ' End If - LogFile.LogTracing("[" & Nut_Config.UPSName & "] " & nutEx.ToString(), LogLvl.LOG_WARNING, Nut_Socket) - End Sub + ' LogFile.LogTracing("[" & Nut_Config.UPSName & "] " & nutEx.ToString(), LogLvl.LOG_WARNING, Nut_Socket) + 'End Sub #End Region @@ -416,7 +426,8 @@ Public Class UPS_Device ' Return Me.UPS_Datas End Sub - Public Function GetUPSVar(ByVal varName As String, ByVal UPSName As String, Optional ByVal Fallback_value As Object = Nothing) As String + Private Const MAX_VAR_RETRIES = 3 + Public Function GetUPSVar(ByVal varName As String, ByVal UPSName As String, Optional ByVal Fallback_value As Object = Nothing, Optional recursing As Boolean = False) As String ' Try ' LogFile.LogTracing("Enter GetUPSVar", LogLvl.LOG_DEBUG, Me) 'If Not Me.ConnectionStatus Then @@ -433,11 +444,12 @@ Public Class UPS_Device Case NUTResponse.UNKNOWNUPS 'Me.Invalid_Data = False 'Me.Unknown_UPS_Name = True - RaiseEvent Unknown_UPS() - Throw New Nut_Exception(Nut_Exception_Value.UNKNOWN_UPS) + ' RaiseEvent Unknown_UPS() + Throw New Nut_Exception(Nut_Exception_Value.UNKNOWN_UPS, "The UPS does not exist on the server.") Case NUTResponse.VARNOTSUPPORTED 'Me.Unknown_UPS_Name = False 'Me.Invalid_Data = False + If Not String.IsNullOrEmpty(Fallback_value) Then LogFile.LogTracing("Apply Fallback Value when retrieving " & varName, LogLvl.LOG_WARNING, Me) Dim FakeData = "VAR " & UPSName & " " & varName & " " & """" & Fallback_value & """" @@ -446,11 +458,34 @@ Public Class UPS_Device LogFile.LogTracing("Error Result On Retrieving " & varName & " : " & Nut_Query.Data, LogLvl.LOG_ERROR, Me) Return Nothing End If + ' upsd won't provide any value for the var, in case of false reading. Case NUTResponse.DATASTALE - 'Me.Invalid_Data = True - LogFile.LogTracing("Error Result On Retrieving " & varName & " : " & Nut_Query.Data, LogLvl.LOG_ERROR, Me) - Throw New System.Exception(varName & " : " & Nut_Query.Data) - Return Nothing + LogFile.LogTracing("DATA-STALE Error Result On Retrieving " & varName & " : " & Nut_Query.Data, LogLvl.LOG_ERROR, Me) + + If recursing Then + Return Nothing + Else + Dim retryNum = 1 + Dim returnString As String = Nothing + + While returnString Is Nothing AndAlso retryNum <= MAX_VAR_RETRIES + LogFile.LogTracing("Attempting retry " & retryNum & " to get variable.", LogLvl.LOG_NOTICE, Me) + returnString = GetUPSVar(varName, UPSName, Fallback_value, True) + End While + + If returnString Is Nothing Then + returnString = Fallback_value + RaiseEvent EncounteredNUTException(New Nut_Exception(NUTResponse.DATASTALE, + "Server reported that the data is stale after " & retryNum & " retries."), Me) + End If + + Return returnString + End If + + ' Throw New System.Exception(varName & " : " & Nut_Query.Data) + Throw New Nut_Exception(NUTResponse.DATASTALE, "Server reported that the data is stale.") + + ' Return NUTResponse.DATASTALE Case Else Return Nothing End Select @@ -464,24 +499,24 @@ Public Class UPS_Device Public Function GetUPS_ListVar() As List(Of UPS_List_Datas) Dim Response = New List(Of UPS_List_Datas) Dim Query = "LIST VAR " & Nut_Config.UPSName - Try - LogFile.LogTracing("Enter GetUPS_ListVar", LogLvl.LOG_DEBUG, Me) - 'If Not Me.ConnectionStatus Then - If Not IsConnected Then - Throw New Nut_Exception(Nut_Exception_Value.SOCKET_BROKEN, Query) - Return Nothing - Else - Dim List_Var = Nut_Socket.Query_List_Datas(Query) - If Not IsNothing(List_Var) Then - Response = List_Var - End If + ' Try + LogFile.LogTracing("Enter GetUPS_ListVar", LogLvl.LOG_DEBUG, Me) + 'If Not Me.ConnectionStatus Then + If Not IsConnected Then + Throw New InvalidOperationException("Attempted to list vars while disconnected.") + Else + Dim List_Var = Nut_Socket.Query_List_Datas(Query) + If Not IsNothing(List_Var) Then + Response = List_Var End If + End If - Catch Excep As Exception - 'RaiseEvent OnError(Excep, LogLvl.LOG_ERROR, Me) - End Try + 'Catch Excep As Exception + ' 'RaiseEvent OnError(Excep, LogLvl.LOG_ERROR, Me) + 'End Try Return Response End Function + Private Function ExtractData(ByVal Var_Data As String) As String Dim SanitisedVar As String Dim StringArray(Nothing) As String diff --git a/WinNUT_V2/WinNUT_GUI/List_Var_Gui.vb b/WinNUT_V2/WinNUT_GUI/List_Var_Gui.vb index daccf5b..b0cfcfa 100644 --- a/WinNUT_V2/WinNUT_GUI/List_Var_Gui.vb +++ b/WinNUT_V2/WinNUT_GUI/List_Var_Gui.vb @@ -24,7 +24,13 @@ Public Class List_Var_Gui Private Sub PopulateTreeView() Dim action As Action LogFile.LogTracing("Populate TreeView", LogLvl.LOG_DEBUG, Me) - List_Var_Datas = WinNUT.UPS_Device.GetUPS_ListVar() + Try + List_Var_Datas = WinNUT.UPS_Device.GetUPS_ListVar() + Catch ex As Exception + ' TODO: Internationalize? + MessageBox.Show("Error encountered trying to get variables from the UPS: " & vbNewLine & ex.Message, "Error Encountered") + Close() + End Try If List_Var_Datas Is Nothing Then LogFile.LogTracing("ListUPSVars return Nothing Value", LogLvl.LOG_DEBUG, Me) diff --git a/WinNUT_V2/WinNUT_GUI/WinNUT.vb b/WinNUT_V2/WinNUT_GUI/WinNUT.vb index a3ae3ed..c0d929e 100644 --- a/WinNUT_V2/WinNUT_GUI/WinNUT.vb +++ b/WinNUT_V2/WinNUT_GUI/WinNUT.vb @@ -567,12 +567,19 @@ Public Class WinNUT LogFile.LogTracing("Battery Status => " & Status, LogLvl.LOG_DEBUG, Me) End Sub - Public Sub Event_Unknown_UPS() Handles UPS_Device.Unknown_UPS, UPS_Device.Unknown_UPS + Sub HandleNUTException(ex As Nut_Exception, sender As Object) Handles UPS_Device.EncounteredNUTException + If ex.ExceptionValue = Nut_Exception_Value.UNKNOWN_UPS Then + Event_Unknown_UPS() + End If + + End Sub + + Public Sub Event_Unknown_UPS() ' Handles UPS_Device.Unknown_UPS ActualAppIconIdx = AppIconIdx.IDX_ICO_OFFLINE LogFile.LogTracing("Update Icon", LogLvl.LOG_DEBUG, Me) UpdateIcon_NotifyIcon() RaiseEvent UpdateNotifyIconStr("Unknown UPS", Nothing) - LogFile.LogTracing("Cannot Connect : Unknow UPS Name", LogLvl.LOG_DEBUG, Me, StrLog.Item(AppResxStr.STR_MAIN_UNKNOWN_UPS)) + LogFile.LogTracing("Unknow UPS Name", LogLvl.LOG_ERROR, Me, StrLog.Item(AppResxStr.STR_MAIN_UNKNOWN_UPS)) Menu_UPS_Var.Enabled = False End Sub @@ -609,9 +616,9 @@ Public Class WinNUT End Sub Public Shared Sub Event_ChangeStatus() Handles Me.On_Battery, Me.On_Line, - UPS_Device.Lost_Connect, UPS_Device.Connected, UPS_Device.Disconnected, UPS_Device.New_Retry, UPS_Device.Unknown_UPS, UPS_Device.ReConnected, - UPS_Device.Unknown_UPS - ', UPS_Device.InvalidLogin, + UPS_Device.Lost_Connect, UPS_Device.Connected, UPS_Device.Disconnected, UPS_Device.New_Retry, UPS_Device.ReConnected + ', UPS_Device.Unknown_UPS + ', UPS_Device.InvalidLogin WinNUT.NotifyIcon.BalloonTipText = WinNUT.NotifyIcon.Text If WinNUT.AllowToast And WinNUT.NotifyIcon.BalloonTipText <> "" Then