gawindx / WinNUT-Client

This is a NUT windows client for monitoring your ups hooked up to your favorite linux server.
GNU General Public License v3.0
410 stars 70 forks source link

Connexion Perdue / Lost #9

Closed Elodie81 closed 4 years ago

Elodie81 commented 5 years ago

Hello,

Since several days, I can't log me anymore on my NUT Server (192.168.1.254 default port 3493) with the old project winnutclient@sourceforge and same with your fork gawindx/WinNUT-Client.

But ... it's working correctly with a telnet command from the same Windows (and firewall is OK) ... You can see a screenshot here : https://images.franceserv.fr/images/2019/10/29/5880b2f47cdfda1ea5f0015a11c1633f.png

Which could be the problem please ? Perhaps a "format" or a "Carriage return" problem ? I don't understand which could be problem and the package nut-client seem not be changed. I changed only the USB port and updated the device name into configuration file but all is working in local and in telnet in remote. But not form a nut-client GUI in remote.

On my "192.168.1.254" Debian Linux :

dpkg -l | grep nut-client

ii nut-client 2.7.4-5 amd64 network UPS tools - clients

telnet 127.0.0.1 3493

Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. list ups BEGIN LIST UPS UPS trust "Web server" END LIST UPS list var trust BEGIN LIST VAR trust VAR trust battery.charge "100" VAR trust battery.voltage "13.60" VAR trust battery.voltage.high "13.00" VAR trust battery.voltage.low "10.40" VAR trust battery.voltage.nominal "12.0" VAR trust device.type "ups" VAR trust driver.name "blazer_usb" VAR trust driver.parameter.pollinterval "20" VAR trust driver.parameter.port "/dev/bus/usb/001/006" VAR trust driver.parameter.synchronous "no" VAR trust driver.version "2.7.4" VAR trust driver.version.internal "0.12" VAR trust input.current.nominal "4.0" VAR trust input.frequency "49.9" VAR trust input.frequency.nominal "50" VAR trust input.voltage "232.9" VAR trust input.voltage.fault "232.9" VAR trust input.voltage.nominal "230" VAR trust output.voltage "232.9" VAR trust ups.beeper.status "enabled" VAR trust ups.delay.shutdown "30" VAR trust ups.delay.start "180" VAR trust ups.load "31" VAR trust ups.productid "0003" VAR trust ups.status "OL" VAR trust ups.temperature "25.0" VAR trust ups.type "offline / line interactive" VAR trust ups.vendorid "06da" END LIST VAR trust logout OK Goodbye Connection closed by foreign host.

/bin/upsc trust

Init SSL without certificate database battery.charge: 100 battery.voltage: 13.60 battery.voltage.high: 13.00 battery.voltage.low: 10.40 battery.voltage.nominal: 12.0 device.type: ups driver.name: blazer_usb driver.parameter.pollinterval: 20 driver.parameter.port: /dev/bus/usb/001/006 driver.parameter.synchronous: no driver.version: 2.7.4 driver.version.internal: 0.12 input.current.nominal: 4.0 input.frequency: 49.9 input.frequency.nominal: 50 input.voltage: 232.9 input.voltage.fault: 232.9 input.voltage.nominal: 230 output.voltage: 232.9 ups.beeper.status: enabled ups.delay.shutdown: 30 ups.delay.start: 180 ups.load: 32 ups.productid: 0003 ups.status: OL ups.temperature: 25.0 ups.type: offline / line interactive ups.vendorid: 06da

Thank you in advance ... Elodie

gawindx commented 4 years ago

Sorry for that late response, but I must admit I've been pretty busy lately.

I also do not understand where the problem can come from with the information you give me.

I do not think it comes from there, but have you tried to enable automatic reconnection (AutoReconnect = 0 in your ini file) to see if it works better. Since this is one of the last features I added, this may be the reason.

Elodie81 commented 4 years ago

Thank for your response but even with AutoReconnect = 0 (and AutoReconnect = 1) it's don't work.

But in Telnet it's working ...

"telnet 192.168.1.254 3493" then "list ups" give me the UPS name "trust", when I type "list var trust" it's give me all informations ....

But with NUT-Client nothing ... very strange indeed.

gawindx commented 4 years ago

I just put you available a version with some debug info and more.

it will not solve the problem but it will already allow to see when the connection crashes.

You can get the exe version here: Winnut Debug

Elodie81 commented 4 years ago

Thank you very much for the verbose feature, perhaps it will help us to understand and it seem the problem is not on the connection and the query, but at the receive of the Vars "GetUPSVar TCP Rcv" :

https://i.imgur.com/6vNIU1V.png

gawindx commented 4 years ago

I added a little more info in the part of the code concerned and I increased the maximum size of the return value (in case your UPS returns too much data)

The exe is also updated and available with the same link as before.

Elodie81 commented 4 years ago

Thank you.

https://i.imgur.com/lobScBT.png

A problem come after this query : "get var trust ups.mfr" with the response : "ERR var-not-supported", same in telnet. But "get var trust ups.status" return "OL", so "MFR" (Device manufacturer") can't reply. But MFR have never worked and I don't think the problem come from this.

But strange "Data" is empty.

gawindx commented 4 years ago

okay But if you look at the logs, it's "ups.model" which returns an empty value ("Data:;" on the penultimate line).

I will think about a solution to manage a default value in this case so that it does not block the operation.

Elodie81 commented 4 years ago

Hello again,

I checked the source code and made few test and few compilations.

When I fake the ups.model inside nutNetwork.au3 line 126 after "$data = TCPRecv($socket , 4096)" with this :

if $varName == "ups.model" Then
       $data = "VAR $upsId $varName ""fake"""
    EndIf

It's continue with a ups.name "fake", but all following requests have a result with N -1 :

Then I request "load", it's give me "output.voltage", when I request "status" it's give me "ups.load, when I request "ups.realpower.nominal" it's give me "ups.status" when I request "battery.voltage" it's give me "battery.charge" when I request "battery.runtime" it's give me "battery.voltage"

and so on ...

For my tests, I added some WriteLog around ProcessData($data) like this :

WriteLog($varName)
WriteLog($data)
$upsVar = ProcessData($data)
WriteLog($upsVar)

And it's given me that : https://i.imgur.com/qclZJ4U.png

All result are given with a delay of N -1, the GUI of course give strange result like 234% : https://i.imgur.com/daPSPGB.png

Do you have an idea please ?

Elodie81 commented 4 years ago

Solved with a "Sleep(50)" and a faked empty ups.model result :

Func GetUPSVar($upsId , $varName , byref $upsVar)
    Local $sendstring , $sent , $data
    if $socket == 0 then
        $upsVar = "0"
        return -1
    EndIf
    $sendstring ="GET VAR " & $upsID & " " & $varName & @CRLF
    $sent = TCPSend($socket , $sendstring )
    if $sent == 0 Then ;connection lost
        $errorstring = __("Connection lost")
        WriteLog($errorstring)
        $socket = 0
        $upsVar = "0"
        return -1
     EndIf
     Sleep(50)
    $data = TCPRecv($socket , 4096)
    if $varName == "ups.model" Then
       $data = "VAR " & $upsId & " ups.model """""
      Else
    if $data == "" Then ;connection lost
        $errorstring = __("Connection lost at " & $varName)
        WriteLog($errorstring)
        $socket = 0
        $upsVar = "0"
        return -1
    EndIf
    $err = CheckErr($data)
    if $err <> "OK" Then
        $errorstring = $err
        if StringInStr($errorstring,"UNKNOWN-UPS") <> 0 Then
            WriteLog(StringFormat(__("UPS %s doesn't exist"), $upsId))
        EndIf
        $upsVar = "0"
        return -1
     EndIf
     EndIf
    $upsVar = ProcessData($data)
    return 0
EndFunc
Elodie81 commented 4 years ago

Seem a Sleep is needed only for the first value, perhaps a delay of connection ?

     if $varName == "battery.charge" Then
     Sleep(50)
     EndIf
gawindx commented 4 years ago

I was not available, sorry.

Your solution seems to work but I propose another approach.

To test on your side to see how it behaves. On my side, with an inverter that seems better supported than yours, everything seems to work properly.

As for the bad values ​​reported, I have no ideas like that.

I'm going back to the code and see if I can find.

Tell me if this solution works and I can publish it.

Elodie81 commented 4 years ago

Tell me if this solution works and I can publish it.

I have an error with your new .exe :

RiUHeqA

gawindx commented 4 years ago

I have no problem on my side.

Can you run it from the script directly and give me the exact location of the error?

Elodie81 commented 4 years ago

Can you run it from the script directly and give me the exact location of the error?

>"C:\Program Files (x86)\AutoIt3\SciTE\..\autoit3.exe" /ErrorStdOut "C:\Applications\WinNUT-Client-error_lost_connect\WinNUT-Client-error_lost_connect\upsclient.au3"    
"C:\Applications\WinNUT-Client-error_lost_connect\WinNUT-Client-error_lost_connect\nutNetwork.au3" (11) : ==> Array variable has incorrect number of subscripts or subscript dimension range exceeded.:
if StringLeft($strs[2],1) == "0" Then
if StringLeft(^ ERROR
>Exit code: 1    Time: 4.639
gawindx commented 4 years ago

Ok I see

I think I corrected it, it should be better.

Elodie81 commented 4 years ago

New error :

>"C:\Program Files (x86)\AutoIt3\SciTE\..\autoit3.exe" /ErrorStdOut "C:\Applications\WinNUT-Client-error_lost_connect\WinNUT-Client-error_lost_connect\upsclient.au3"    
"C:\Applications\WinNUT-Client-error_lost_connect\WinNUT-Client-error_lost_connect\nutGui.au3" (521) : ==> Variable used without being declared.:
Case $nMsg3 = $Shutdown_btn or $en_cours = 0
Case $nMsg3 = $Shutdown_btn or ^ ERROR
>Exit code: 1    Time: 6.557

And it's tried to shut down my computer because values are still received with N-1 (example : 231% of charge (whereas it's 231 Volt) :

2019-11-12 14_18_45-Window

gawindx commented 4 years ago

That's good, you find bug that never happened to me and yet I thought I had triturated the code in all directions .... it's ironic, sorry.

For the missing declaration, it is updated.

For your problem of missing or offset value, the problem that happens to you is not logical compared to the catches transmitted in your first post.

gawindx commented 4 years ago

In fact, your problem of offset / missing value seems logical if one considers that the values ​​are not expressed with the same unit as for my UPS ...

I'll see what I can do to help choose the right units

Elodie81 commented 4 years ago

Yes very strange ... and with my quick hack and a Sleep(50) before TCPRecv() all is working ...

gawindx commented 4 years ago

I do not want to go too far but I think this version should solve your problem of missing value.

In the case of your UPS, the driver "blazer_usb" does not contain all the variables that I use in the code. To be able to manage your case (and surely not only yours), I implemented some default values ​​in order to be able to determine the different missing information.

In this logic, I applied the principle of "worst case" so as not to risk a late shutdown of the system.

For information, here are the missing information on your UPS and that I normally use:

Elodie81 commented 4 years ago

No error but responses values still N-1, I'm really sorry :)

2019-11-13 19_26_54-Paramètres

I'm using this nutNetwork.au3 and all is working correctly for me :

Global $socket = 0

Func ProcessData($data)

    Local $strs

    $strs = StringSplit($data , '"')
    if UBound($strs)<2 Then ;ERROR string returned or other unexpected condition
        return -1 ;return -1 which means the something bad happened and value
    EndIf ;returned from NUT is unusable
    if StringLeft($strs[2],1) == "0" Then
        return StringTrimLeft($strs[2],1)
    Else
        return $strs[2]
    EndIf

EndFunc

Func CheckErr($upsresp)
    Local $strs
    if StringLeft($upsresp,3)=="ERR" Then
        $strs = StringSplit($upsresp , " ")
        if UBound($strs)<2 Then
            return "Uknown Error"
        EndIf
        return $strs[2]
    Else
        return "OK"
    EndIf

EndFunc

Func ListUPSVars($upsId , byref $upsVar)

    Local $sendstring , $sent , $data
    if $socket == 0 then
        $upsVar = "0"
        return -1
    EndIf
    $sendstring ="LIST VAR " & $upsID  & @CRLF
    $sent = TCPSend($socket , $sendstring )
    if $sent == 0 Then ;connection lost
        $errorstring = __("Connection lost")
        WriteLog($errorstring)
        $socket = 0
        $upsVar = "0"
        return -1
    EndIf
    Sleep(500)
    $data = TCPRecv($socket , 4096)
    if $data == "" Then ;connection lost
        $errorstring = __("Connection lost")
        WriteLog($errorstring)
        $socket = 0
        $upsVar = "0"
        return -1
    EndIf
    $err = CheckErr($data)
    if $err <> "OK" Then
        $errorstring = $err
        if StringInStr($errorstring,"UNKNOWN-UPS") <> 0 Then
            WriteLog(StringFormat(__("UPS %s doesn't exist"), $upsId))
        EndIf
        $upsVar = "0"
        return -1
    EndIf
    $upsVar = $data
    return 0
EndFunc

Func GetUPSDescVar($upsId , $varName , byref $upsVar)

    Local $sendstring , $sent , $data
    if $socket == 0 then
        $upsVar = "0"
        return -1
    EndIf
    $sendstring ="GET DESC " & $upsID & " " & $varName & @CRLF
    $sent = TCPSend($socket , $sendstring )
    if $sent == 0 Then ;connection lost
        $errorstring = __("Connection lost")
        WriteLog($errorstring)
        $socket = 0
        $upsVar = "0"
        return -1
    EndIf
    $data = TCPRecv($socket , 4096)
    if $data == "" Then ;connection lost
        $errorstring = __("Connection lost")
        WriteLog($errorstring)
        $socket = 0
        $upsVar = "0"
        return -1
    EndIf
    $err = CheckErr($data)
    if $err <> "OK" Then
        $errorstring = $err
        if StringInStr($errorstring,"UNKNOWN-UPS") <> 0 Then
            WriteLog(StringFormat(__("UPS %s doesn't exist"), $upsId))
        EndIf
        $upsVar = "0"
        return -1
    EndIf
    $upsVar = ProcessData($data)
    return 0

EndFunc

Func GetUPSVar($upsId , $varName , byref $upsVar)
    Local $sendstring , $sent , $data
    if $socket == 0 then
        $upsVar = "0"
        return -1
    EndIf
    $sendstring ="GET VAR " & $upsID & " " & $varName & @CRLF
    $sent = TCPSend($socket , $sendstring )
    if $sent == 0 Then ;connection lost
        $errorstring = __("Connection lost")
        WriteLog($errorstring)
        $socket = 0
        $upsVar = "0"
        return -1
     EndIf
     if $varName == "battery.charge" Then
     Sleep(50)
     EndIf
    $data = TCPRecv($socket , 4096)
    if $varName == "ups.model" Then
        if $data == "" Then
          $data = "VAR " & $upsId & " ups.model """""
          EndIf
      Else
    if $data == "" Then ;connection lost
        $errorstring = __("Connection lost at " & $varName)
        WriteLog($errorstring)
        $socket = 0
        $upsVar = "0"
        return -1
    EndIf
    $err = CheckErr($data)
    if $err <> "OK" Then
        $errorstring = $err
        if StringInStr($errorstring,"UNKNOWN-UPS") <> 0 Then
            WriteLog(StringFormat(__("UPS %s doesn't exist"), $upsId))
        EndIf
        $upsVar = "0"
        return -1
     EndIf
     EndIf
    $upsVar = ProcessData($data)
    return 0
EndFunc

Func ConnectServer()
    if $socket <> 0 then ;already connected
        WriteLog(__("Disconnecting from server"))
        TCPSend($socket,"LOGOUT")
        TCPCloseSocket($socket) ;disconnect first
        $socket = 0
    EndIf
    Opt("TCPTimeout",10)
    WriteLog(__("Connecting to NUT Server"))
    $ipaddr = TCPNameToIP(GetOption("ipaddr"))
    $socket = TCPConnect($ipaddr, GetOption("port"))
    if $socket == -1 Then;connection failed
        $haserror = 1
        $errorstring = __("Connection failed")
        WriteLog($errorstring)
        return -1
    Else
        WriteLog(__("Connection Established"))
        return 0
    EndIf
EndFunc
gawindx commented 4 years ago

I applied a derived part of your code regarding the delay when calling "battery.charge". To make the function reusable, I applied it as optional call parameters.

No problem on my side with this version. I have not touched the code previously added to determine the information not reported by your UPS so it is possible that stuck on this part.

gawindx commented 4 years ago

I pushed a little more tests on the last version online and I fixed some malfunctions. I was also able to realize that the estimate of autonomy was completely wrong (the formula worked quite well with my UPS but by simulating the values returned by yours, it gave a catastrophic result). So I corrected by applying a formula that gives a more acceptable result as well by simulating the values of your first post using the values of mine).

If you can give me a feedback on these changes and tell me if the autonomy time reported seems consistent.