3
This file is part of nutmon for netware
4
Copyright (c) 2004 armin diehl (armin@freepascal.org)
6
Simple class to connect to the nut upsd, see
7
http://www.networkupstools.org for details about the
10
Tested with nut 2.0.1pre4
12
This program is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
**********************************************************************}
21
uses sysutils, ssockets;
24
NutDefaultPort = 3493;
26
NutDataStale = 'ERR DATA-STALE';
29
TNutException = class (Exception);
30
TUpsStat = (UPS_disconnected,UPS_stale,UPS_online,UPS_onBatt,UPS_lowBatt,UPS_FSD);
31
TUpsStatus = set of TUpsStat;
32
TNutConnection = class (TObject)
37
fUpsName,fUserName,fPassword : string;
40
fLastResponse : string;
42
function isConnected : boolean;
43
procedure doConnect (c : boolean);
44
procedure setHost (s : string);
45
procedure setPort (w : word);
46
procedure sendCommand (s : string);
47
function getOneLine : string;
48
function getVersion : string;
49
procedure setUpsName (s : string);
50
procedure checkConnected;
51
function getValue (name : string) : string;
52
function getUpsLoad : string;
53
function getUpsMfr : string;
54
function getUpsModel : string;
55
function getUpsRuntime : string;
56
function getUpsCharge : string;
57
function getUpsChargeInt : integer;
58
function getUpsTemperature : string;
59
function getInputFrequency : string;
60
function getInputVoltage : string;
61
function getOutputVoltage : string;
62
function getUpsStatus : TUpsStatus;
63
procedure setUserName (user : string);
64
procedure setPassword (pwd : string);
65
procedure doLogin (login : boolean);
66
function getNumLogins : string;
68
property connected : boolean read isConnected write doConnect;
69
property host : string read fHost write setHost;
70
property port : word read fPort write setPort;
71
property version : string read getVersion;
72
property upsName : string read fUpsName write setUpsName;
73
property upsload : string read getUpsLoad;
74
property upsMfr : string read getUpsMfr;
75
property upsModel : string read getUpsModel;
76
property upsRuntime : string read getUpsRuntime;
77
property upsCharge : string read getUpsCharge;
78
property upsChargeInt : integer read getUpsChargeInt;
79
property upsTemperature : string read getUpsTemperature;
80
property upsInputFrequency : string read getInputFrequency;
81
property upsInputVoltage : string read getInputVoltage;
82
property upsOutputVoltage : string read getOutputVoltage;
83
property upsStatus : TUpsStatus read getUpsStatus;
84
property Username : string read fUsername write setUsername;
85
property Password : string read fPassword write setPassword;
86
// in case login is set to true (and username,password are ok)
87
// upsd knows that this system gets power from the ups and
88
// will switch off only after login was set to false
89
property Login : boolean read fLogin write doLogin;
90
property Debug : boolean read fDebug write fDebug;
91
property LastResult : string read fLastResponse;
92
property numLogins : string read getNumLogins;
95
function UpsStatus2Txt (status : TUpsStatus) : string;
99
function TNutConnection.isConnected : boolean;
101
result := (fSock <> nil);
104
procedure TNutConnection.doConnect (c : boolean);
113
fSock := TInetSocket.Create (fHost, fPort);
117
procedure TNutConnection.setHost (s : string);
122
doConnect (isConnected);
126
procedure TNutConnection.setPort (w : word);
131
doConnect (isConnected);
135
procedure TNutConnection.checkConnected;
137
if not isConnected then
138
raise (TNutException.Create ('not connected'));
141
procedure TNutConnection.sendCommand (s : string);
146
writeln (stderr,'S: "'+s+'"');
148
len := fSock.Write (s[1],length(s));
149
if (len <> length(s)) then
152
writeln (stderr,'send error');
154
raise (TNutException.Create ('send failed, disconnected from upsd'));
158
function TNutConnection.getOneLine : string;
164
while (fSock.read (c,1) = 1) do
166
if c = NutLineEnd then
169
writeln (stderr,'R: "'+result+'"');
170
fLastResponse := result;
173
result := result + c;
177
function TNutConnection.getVersion : string;
180
result := getOneLine;
184
procedure TNutConnection.setUpsName (s : string);
188
sendCommand ('GET NUMLOGINS '+s);
190
if copy (res,1,10) <> 'NUMLOGINS ' then
191
Raise (TNutException.Create ('setUpsName, unknown response from upsd'));
195
function TNutConnection.getValue (name : string) : string;
198
if fUpsName = '' then
199
raise (TNutException.Create ('upsName not set'));
200
sendCommand ('GET VAR '+fUpsName+' '+name);
202
if s = 'ERR DATA-STALE' then
207
if copy (s,1,4) <> 'VAR ' then
208
raise (TNutException.Create ('result from GET VAR invalid, does not begin with "VAR "'));
210
if ansiUpperCase (copy (s,1,length(fUpsName))) <> ansiUpperCase (fUpsName) then
211
raise (TNutException.Create ('result from GET VAR invalid, second param was not upsName'));
212
delete (s,1,length(fUpsName)+1);
213
delete (s,1,length(name)+1);
214
if copy (s,1,1) = '"' then delete (s,1,1);
215
if copy (s,length(s),1) = '"' then delete (s,length(s),1);
219
function TNutConnection.getUpsLoad : string;
221
result := getValue ('ups.load');
224
function TNutConnection.getUpsMfr : string;
226
result := getValue ('ups.mfr');
229
function TNutConnection.getUpsModel : string;
231
result := getValue ('ups.model');
234
function TNutConnection.getUpsRuntime : string;
236
result := getValue ('battery.runtime');
239
function TNutConnection.getUpsCharge : string;
241
result := getValue ('battery.charge');
245
function TNutConnection.getUpsChargeInt : integer;
254
result := StrToInt (s);
260
function TNutConnection.getUpsTemperature : string;
262
result := getValue ('ups.temperature');
265
function TNutConnection.getInputFrequency : string;
267
result := getValue ('input.frequency');
270
function TNutConnection.getInputVoltage : string;
272
result := getValue ('input.voltage');
275
function TNutConnection.getOutputVoltage : string;
277
result := getValue ('output.voltage');
280
function TNutConnection.getNumLogins : string;
284
if fUpsName = '' then
285
Raise (TNutException.Create ('getNumLogins, upsName not set'));
286
sendCommand ('GET NUMLOGINS '+fUpsName);
288
if copy (res,1,10) <> 'NUMLOGINS ' then
289
Raise (TNutException.Create ('setUpsName, unknown response from upsd'));
297
function TNutConnection.getUpsStatus : TUpsStatus;
298
var s,value : string;
302
s := getValue ('ups.status');
304
if s = NutDataStale then
305
result := [UPS_stale]
311
value := trim(ansiuppercase(copy(s,1,i-1)));
312
delete (s,1,i); s:=trim(s);
315
value := trim(ansiuppercase(s));
319
result := result + [UPS_online]
320
else if value = 'OB' then
321
result := result + [UPS_onBatt]
322
else if value = 'LB' then
323
result := result + [UPS_LowBatt]
324
else if value = 'FSD' then
325
result := result + [UPS_FSD];
328
result := [UPS_disconnected];
333
procedure TNutConnection.setUserName (user : string);
337
if fUserName <> '' then
339
sendCommand ('USERNAME '+user);
342
raise (TNutException.Create (format ('username failed (%s)',[res])));
346
procedure TNutConnection.setPassword (pwd : string);
352
sendCommand ('PASSWORD '+pwd);
355
raise (TNutException.Create (format ('password failed (%s)',[res])));
359
procedure TNutConnection.doLogin (login : boolean);
365
raise (TNutException.Create ('already logged in'));
366
if (fUsername = '') or (fPassword = '') or (fUpsName = '') then
367
raise (TNutException.Create ('Login requires UpsName, Username and Password'));
368
sendCommand ('LOGIN '+fUpsName);
371
raise (TNutException.Create (format ('login failed (%s)',[res])));
376
sendCommand ('LOGOUT');
378
if (copy(res,1,2) <> 'OK') and (copy(res,1,6)<> 'Goodby') then
379
raise (TNutException.Create (format('logout failed, got "%s"',[res])));
385
function UpsStatus2Txt (status : TUpsStatus) : string;
388
if UPS_disconnected in status then result := result + 'disconnected ';
389
if UPS_stale in status then result := result + 'stale ';
390
if UPS_online in status then result := result + 'online ';
391
if UPS_onBatt in status then result := result + 'onBattery ';
392
if UPS_lowBatt in status then result := result + 'LowBattery ';
393
if UPS_FSD in status then result := result + 'ForeceShutdown ';
394
result := trim(result);