Files
ups/__pycache__/ups2rrd.cpython-313.pyc
T

303 lines
30 KiB
Plaintext
Raw Normal View History

2026-08-15 15:47:18 +02:00
ó
Ãm€jû}ãóSrSSKrSSKrSSKrSSKrSSKrSSKrSSKrSSKJ r SSK
J r SSK J
r
SSKJr SrSr\R$R'\S 5r\R$R'\S
5r\R,R/S S 5r\R,R/S
S5r\R,R/SS5r\R,R/SS5rSrSrSrSr\R$R'\S5r \R$R'\S5r!\R$R'\S5r"\R$R'\S5r#\R$R'\S5r$\R$R'\S5r%\R$R'\S5r&\R$R'\S5r'\R$R'\S5r(\R$R'\S 5r)\R$R'\S!5r*\R$R'\S"5r+\R$R'\S#5r,\R$R'\S$5r-\R$R'\S%5r.SS&S'S(S)S*.r/S+r0S,r1S-r2S.r3S/r4S0r5S1r6S2r7S3r8S4r9\\\\S54S6jr:S7r;S8r<S9r=S:r>S;r?S<r@S=rAS>rBS?rCS@rDSArESBrFSJSCjrGSDrHSErISFrJSGrKSHrL\MSI:Xa\L"5 gg)Ka@
APC Back-UPS BX950MI RRD monitor
Collects UPS information from NUT every minute and stores it in RRDTool.
Retention:
UPS status:
3 months @ 1 minute
Battery charge:
1 year @ 5 minutes
5 years @ 1 hour
Battery runtime:
1 year @ 5 minutes
5 years @ 1 hour
UPS load:
3 months @ 1 minute
Nominal power:
1 year @ 5 minutes
5 years @ 1 hour
Requirements:
pip install -r requirements.txt
NUT's server and USB driver must also be installed and running.
NUT UPS name:
BX950MI
éN)Ú
MessageBus)ÚBusType)ÚPyNUT)Úsend_notificationÚBX950MIz /var/lib/rrdz bx950mi.rrdzbx950mi-alert-state.jsonÚUPS_SHUTDOWN_HOSTz
plex.localÚUPS_SHUTDOWN_USERÚupsÚUPS_SHUTDOWN_KEYz/opt/ups/.ssh/plex_shutdownÚUPS_SHUTDOWN_KNOWN_HOSTSz/opt/ups/.ssh/known_hostszsudo /usr/sbin/shutdown -h nowé,éÈz/var/www/html/upsú
index.htmlú week.htmlz
status-1w.pngzbattery-1w.pngzruntime-1w.pngz load-1w.pngz power-1w.pngz
status-3m.pngzbattery-1y.pngzbattery-5y.pngzruntime-1y.pngzruntime-5y.pngz load-3m.pngz power-1y.pngz power-5y.pngéééé)ÚOLÚOBÚLBÚRBÚUNKNOWNcóUtp[[U5nU"U6$![a!n[SU3[R
S9 eSnAff=f)z(Call an RRDtool Python binding function.zRRDTool error: ©ÚfileN)ÚgetattrÚrrdtoolÚ ExceptionÚprintÚsysÚstderr)ÚargsÚ operationÚoperation_argsÚfunctionÚexcs Ú
ups2rrd.pyÚ run_rrdtoolr)ŠsTð
Ø%)Ð"ˆ Üœ7 IÓÙ˜Ð(øä óÜ
ؘc˜UÐ ò
ð ûð úsš
A¤AÁAc ó²[R"SSSS9nUR[5nUR 5VVs0sHTup#[ U[ 5(aURS5OU[ U[ 5(aURS5OU_MV snn$s snnf![a'n[SU3[RS9 0sSnA$SnAff=f) z*Read all values from the local NUT server.z 127.0.0.1i¥
é
)ÚhostÚportÚtimeoutúutf-8z NUT error: rN) rÚ PyNUTClientÚ
GetUPSVarsÚUPS_NAMEÚitemsÚ
isinstanceÚbytesÚdecoderr r!r")ÚclientÚvaluesÚkeyÚvaluer's r(Úget_ups_valuesr;žðÜרØñ
ˆð
×"¤8Ó,ˆð %Ÿl™lœnô
ò-
ô$.¨c´5×#9Ñ#9ˆCJ‰J ¸sÜ%/°´u×%=Ñ%=ˆEL‰L˜Ô !À5ò
Iá
ð
ùó
øô óÜ
˜C˜¯
©
Ò ûðús0>B%ÁABÂB%ÂB%Â%
CÂ/CÃ CÃCcóŽURS5nU(dgUR5nSU;agSU;agSU;agSU;agg)zr
Read UPS status.
NUT may return multiple flags, for example:
OB LB
We prioritize the more serious states.
z
ups.statusrrrrr)ÚgetÚsplit)r8r:Úflagss r(Ú
get_statusr@µsNð
J‰J $€Eæ Øà K‰K‹M€Eà ˆuƒ}Øà ˆuƒ}Øà ˆuƒ}Øà ˆuƒ}Øà ócó URU5nUcg[U5$![a! [SUSU3[R
S9 gf=f)zRead a numeric value from NUT.NzInvalid value for z: r)r=ÚfloatÚ
ValueErrorr r!r")r8Úfieldr:s r(Ú get_floatrFÖs\ð
J‰J €Eà ðÜU‹|Ðøä óÜ
Ø    r¨%¨Ð ò
ñð ús
"¢(A
Á A
cóD[RR[5(ag[R"[
SS9 [
[R"55nUS-
nS[S[U5SSS S
S S S
SSSS/n[U5 [S[35 g)
Create the RRD database.
The database is created only once.
IMPORTANT:
RRD databases cannot easily have their DS/RRA layout changed.
If you change this layout later, remove the RRD and recreate it.
NT©Úexist_okéxÚcreateú--startz--stepÚ60zDS:status:GAUGE:120:0:4z!DS:battery_charge:GAUGE:120:0:100z DS:battery_runtime:GAUGE:120:0:UzDS:ups_load:GAUGE:120:0:100z"DS:realpower_nominal:GAUGE:120:0:UzRRA:LAST:0.5:1:129600zRRA:AVERAGE:0.5:5:105120zRRA:AVERAGE:0.5:60:43800zRRA:AVERAGE:0.5:1:129600z
Created RRD: ) ÚosÚpathÚexistsÚRRD_FILEÚmakedirsÚRRD_DIRÚintÚtimeÚstrr)r )ÚnowÚstartÚcommands r(Ú
create_rrdrZíô
‡ww‡~~”h×ÑØä‡KK” $Ò
ŒdiŠi
€Cð
#‰I€Eð ÜàÜ ˆE‹
àØ ð ð #ðIE€GôNÔä ˆMœ(˜Ð
%rAc ó[5n[U5n[US5n[US5n[US5n[US5n[R U[S5nSn[ U5U"U5U"U5U"U5U"U5/n[
[R"55n U S3SRU5-n
[S[U
/5 [[R"S 5S
U3S U3S U3S
U3SU35 UUUS.$)zRead UPS values and update RRD.zbattery.chargezbattery.runtimezups.loadzups.realpower.nominalrcó Ucg[U5$)U)rV)r:s r(Úvalue_or_unknownÚ$update_rrd.<locals>.value_or_unknowntsØ ‰=Øä5rAÚupdatez%Y-%m-%d %H:%M:%Szstatus=zbattery=zruntime=zload=znominal=)ÚstatusÚbattery_chargeÚbattery_runtime)
r;r@rFÚ
STATUS_VALUESr=rVrTrUÚjoinr)rQr Ústrftime) Ú
ups_valuesrbrcrdÚups_loadÚrealpower_nominalÚ status_valuer^r8Ú timestampÚ
update_strings r(Ú
update_rrdrnTssô Ó!€Jä
˜
Ó
#€F䨨ó€Nô
 ØØó€Oô
ØØó€Hô
ØóÐô
Ü ó€Lò
ô ˆLÓáØ ó
ñ Ø ó
ñ Ø ó
ñ Ø ó
ð€Fô(”D—I’I“KÓ €Ið ˆ+Ø
(‰(
ñ ðô
à Ü Ø ð
ôô
Ü
Š
Ø ó
ð &ÐØ


ˆØ
Ð ðØ ðrAcó[[SS9n[R"U5sSSS5 $!,(df  g=f![a 0s$[
[ 4a'n[SU3[RS9 0sSnA$SnAff=f)z0Load values saved by the previous collector run.r/©ÚencodingNzCould not read alert state: r)
ÚopenÚALERT_STATE_FILEÚjsonÚloadÚFileNotFoundErrorÚOSErrorrDr r!r")Ú
state_filer's r(Úload_alert_statery³shðÜ
Ô"¨WÒ
Ü—9’9˜ZÓ
5×
5ûä óØŠ Ü ”ZÐ óÜ
Ð,¨S¨Eп¹Ò ûðús:A0¦ A°
>ºA¾AÁ BÁBÁBÁ:BÂBcóJ[S3n[USSS9n[R"XSSS9 UR S5 S S S 5 [
R "U[5 g !,(df  N*=f![a%n[S
U3[RS 9 S nAg S nAff=f) z2Atomically save values for the next collector run.z.tmpÚwr/rprT)ÚindentÚ sort_keysÚ
NzCould not save alert state: r) rsrrrtÚdumpÚwriterNÚreplacerwr r!r")ÚstateÚtemporary_filerxr's r(Úsave_alert_stater„ÀsôÐ.€NðEÜ
. Ò
8¸JÜ IŠI¸TÒ × Ñ ˜ 
Š
>Ô#3Õ
8ûô óEÜ
Ð,¨S¨Eп¹×DûðEús- A3(A"¾#A3Á"
A0Á,A3Á3
B"Á=BÂB"cóœ[U5 [SU35 g![a%n[SU3[RS9 SnAgSnAff=f)z>Send an alert without stopping UPS data collection on failure.zNotification sent: zNotification failed: rN)rr rr!r")Úmessager's r(Únotifyr‡ÎsEð˜
Ð# G .øÜ ó
Ð% c +´#·*±*×=ûð>úsœ
A ¦AÁA cóLUSL=(a USL=(a X=(a X:$)z9Return whether a numeric value crossed below a threshold.N©)ÚpreviousÚcurrentÚ thresholds r(Ú
crossed_belowrØs6ð ˜Ð÷ Ø ˜4Ð ÷ à Ñ  ð
Ñ ð rAr+c ó8[R"5nURU5 UR[R"55 UR UUUUUUSSS9 UR
[US9 UR5 g!UR5 f=f)z>Shut down a remote Linux server over restricted, verified SSH.F)ÚhostnameÚusernameÚ key_filenamer.Úbanner_timeoutÚ auth_timeoutÚ
look_for_keysÚ allow_agent)r.N) ÚparamikoÚ SSHClientÚload_host_keysÚset_missing_host_key_policyÚ RejectPolicyÚconnectÚ exec_commandÚSHUTDOWN_COMMANDÚclose)r,ÚuserÚkey_fileÚ known_hostsr.r7s r(Úshutdown_remote_serverr¢ãô×
Ò
Ó
!€FØ
×ј
×&¤x×'<Ò'<Ó'>Ô
ØØØØØ ØØð ñ
ð ×ÑÔ,°gÐÑ øˆ ús Á *BÂBcƒól# [[RS9R5IShvN nUR SS5IShvN nUR SSU5nUR
S5nURS5IShvN UR5 gNmNTN!UR5 f=f7f)z<Request a local power-off through systemd-logind over D-Bus.)Úbus_typeNzorg.freedesktop.login1z/org/freedesktop/login1zorg.freedesktop.login1.ManagerF) rrÚSYSTEMrÚ
introspectÚget_proxy_objectÚ
get_interfaceÚcall_power_offÚ
disconnect)ÚbusÚ
introspectionÚloginÚmanagers r(Úrequest_local_poweroffr¯éô¤G§N¡NÑ
=€Cð
Ø!Ÿn™nØ 
÷
ˆ
ð× ó
ˆð
×%Ð&FÓGˆØ×$  Õñ 
ñ ,øà ÕüsJ)B4«B¬B4±BÁBÁ<BÂBÂBÂB4ÂBÂBÂB1Â1B4có@[R"[55 g)z2Shut down the Linux server running this collector.N)ÚasyncioÚrunr¯r‰rAr(Úshutdown_local_serverr³sô ‡K)rAcóú[5nURS5nURS5nURS5nURS5nURS5nURS5nURSS5nURSS5n U(GaDU(aU(aX2:wa[SUSU35 [XES 5(a[S
US S 35 [XES
5(a[SUS S 35 [XgS5(a[SUS- S S35 US;=(a USL=(a U[:n
U
(a;U(d4[ 5 SnS[ SUS- S S3n [U 5 [U 5 US;=(a USL=(a U[:n
U
(a1U (d*SUSS3n [U 5 [5 Sn [U 5 US:XaSnSn U=(d UUbUOUUbUOUUU S .n[U5 g![a,n [S[ SU 3[RS9 Sn A NºSn A ff=f![a%n [SU 3[RS9 Sn A N”Sn A ff=f)!z<Notify on status changes and configured threshold crossings.rbrcrdÚremote_shutdown_sentFÚlocal_shutdown_sentzUPS status changed: z -> é2z!UPS battery charge is below 50%: z.1fÚz1UPS battery charge is critically low (below 5%): r
z(UPS battery runtime is below 5 minutes: é<z minutes>rrNTzRemote shutdown requested for z: UPS runtime is zRemote shutdown of z failed: rz0Raspberry Pi shutdown requested: UPS runtime is z.0fz secondszLocal shutdown failed: r)rbrcrd)ryr=r‡rÚREMOTE_SHUTDOWN_RUNTIME_SECONDSr¢Ú
SHUTDOWN_HOSTr rr!r"ÚLOCAL_SHUTDOWN_RUNTIME_SECONDSr³r„)rÚprevious_statusÚcurrent_statusÚprevious_chargeÚcurrent_chargeÚprevious_runtimeÚcurrent_runtimeÚ
shutdown_sentr¶Úshutdown_requiredr†r'Úlocal_shutdown_requiredrs r(Úprocess_alertsrÇô Ó!€HØ—l‘l 8Ó,€OØ—[‘[ Ó*€NØ—l‘lÐ#3Ó4€OØ—[‘[Ð!1Ó2€NØ—|‘|Ð$5ÓØ—kkÐ"3Ó4€OØ—LLÐ!7¸Ó?€MØ"Ÿ,™,Ð'<¸÷æ ÞØÓ Ø& Ð&7°t¸NÐ;KÐ
ô ˜¸"× Ø3°NÀ3Ð3GÀqÐ
ô ˜¸!× ðØ-¨cÐ2°!ð
ô
Ð)¸F× Ø" Ð,¨Hð
ð
˜ 
BØ 
BàÔ"AÑ ö ¦]ð
Ü(Ø $
à4´]°OðD&Ø&5¸Ñ&:¸3Ð%?¸Iðôg”Üw”ð
˜ 
AØ 
AàÔ"@Ñ ö #Ö+>à" ' 
ô
7ŒOð
Ü'Ø&*Ðg”ð˜Ó؈
Øð3 Oà8‰N¸:‰OÐ@Pà -Ø
€Eôøô]ó
ÜØ)¬-¨¸ À#ÀП÷ûð
ûô.ó
ÜØ-¨c¨UП÷ûð
ús0Å3HÇ
I È
IÈ"IÉIÉ
I:ÉI5É5I:cóÎ[[R"55n[S[S[ US-
5S[ U5SSSSS S
S S S
SSSSS[
S3SSSSSSS/5 g)z Create 3-month UPS status graph.ÚgraphrLé§vú--endú--widthÚ1000ú--heightÚ350ú--titlez#APC BX950MI - UPS Status (3 Months)ú--vertical-labelÚStatusú
--lower-limitÚ
--upper-limitÚ--rigidú DEF:status=ú :status:LASTúLINE2:status#0000FF:UPS statusú
COMMENT:\núCOMMENT:0 = On Line (OL)\núCOMMENT:1 = On Battery (OB)\núCOMMENT:2 = Low Battery (LB)\nú"COMMENT:3 = Replace Battery (RB)\núCOMMENT:4 = Unknown\nN)rTrUr)Ú GRAPH_STATUSrVrQ©rWs r(Ú graph_statusrãô ŒdiŠi‹kÓ
€Cäà Ü à Ü  Ó Ü ‹Hà Ø à Ø à Ø Ø à Ø à Ø à ð œ(˜ <Ð
à $ði5
õ7rAcóÆ[[R"55n[S[S[ US-
5S[ U5SSSSS S
S S S
SSSS[
S3SSSS/5 g)z#Battery charge, 1 year @ 5 minutes.rÉrLé€3áz%APC BX950MI - Battery Charge (1 Year)rÑú
Charge (%)rÓÚ100ú DEF:charge=ú:battery_charge:AVERAGEú"LINE2:charge#008000:Battery chargeú!GPRINT:charge:MIN:Minimum %.1lf%%ú%GPRINT:charge:AVERAGE:Average %.1lf%%ú!GPRINT:charge:MAX:Maximum %.1lf%%N)rTrUr)ÚGRAPH_BATTERY_1YrVrQs r(Úgraph_battery_1yrïÌô ŒdiŠi‹kÓ
€Cäà Ü à Ü  Ü ‹Hà Ø à Ø à Ø Ø à Ø à Ø à ܈jÐ


ð
ð
ðO)
õ+rAcóÆ[[R"55n[S[S[ US-
5S[ U5SSSSS S
S S S
SSSS[
S3SSSS/5 g)z!Battery charge, 5 years @ 1 hour.rÉrLé€f rËz&APC BX950MI - Battery Charge (5 Years)rÑN)rTrUr)ÚGRAPH_BATTERY_5YrVrQs r(Úgraph_battery_5yróÿô ŒdiŠi‹kÓ
€Cäà Ü à Ü  Ü ‹Hà Ø à Ø à Ø Ø à Ø à Ø à ܈jÐ


ð
ð
ðO)
õ+rAcóÀ[[R"55n[S[S[ US-
5S[ U5SSSSS S
S S S
[
S3SSSSS/5 g)z$Battery runtime, 1 year @ 5 minutes.rÉrLz&APC BX950MI - Battery Runtime (1 Year)rÑúRuntime (minutes)ú DEF:runtime=ú:battery_runtime:AVERAGEúCDEF:minutes=runtime,60,/ú$LINE2:minutes#800080:Battery runtimeú$GPRINT:minutes:MIN:Minimum %.1lf minú(GPRINT:minutes:AVERAGE:Average %.1lf minú$GPRINT:minutes:MAX:Maximum %.1lf minN)rTrUr)ÚGRAPH_RUNTIME_1YrVrQs r(Úgraph_runtime_1yrþ6sô ŒdiŠi‹kÓ
€Cäà Ü à Ü  Ü ‹Hà Ø à Ø à Ø Ø à ܈jÐ


ð
ð
ðO)
õ+rAcóÀ[[R"55n[S[S[ US-
5S[ U5SSSSS S
S S S
[
S3SSSSS/5 g)z"Battery runtime, 5 years @ 1 hour.rÉrLz'APC BX950MI - Battery Runtime (5 Years)rÑN)rTrUr)ÚGRAPH_RUNTIME_5YrVrQs r(Úgraph_runtime_5yrisô ŒdiŠi‹kÓ
€Cäà Ü à Ü  Ü ‹Hà Ø à Ø à Ø Ø à ܈jÐ


ð
ð
ðG%
õ'rAcóÆ[[R"55n[S[S[ US-
5S[ U5SSSSS S
S S S
SSSS[
S3SSSS/5 g)zUPS load, 3 months @ 1 minute.rÉrLz!APC BX950MI - UPS Load (3 Months)rÑúLoad (%)rÓú DEF:load=ú:ups_load:AVERAGEúLINE2:load#FF8000:UPS loadzGPRINT:load:MIN:Minimum %.1lf%%z#GPRINT:load:AVERAGE:Average %.1lf%%zGPRINT:load:MAX:Maximum %.1lf%%N)rTrUr)Ú
GRAPH_LOADrVrQs r(Ú
graph_loadrœs…ô ŒdiŠi‹kÓ
€Cäà Ü à Ü  Ó Ü ‹Hà Ø à Ø à Ø Ø à Ø à Ø àœzÐ!2Ð 
ð
ð
ðM(
õ*rAcó¾[[R"55n[S[S[ US-
5S[ U5SSSSS S
S S S
[
S3SSSS/5 g)z"Nominal power, 1 year @ 5 minutes.rÉrLz$APC BX950MI - Nominal Power (1 Year)rÑú Power (W)ú
DEF:power=ú:realpower_nominal:AVERAGEú LINE2:power#CC0000:Nominal powerú GPRINT:power:MIN:Minimum %.1lf Wú$GPRINT:power:AVERAGE:Average %.1lf Wú GPRINT:power:MAX:Maximum %.1lf WN)rTrUr)ÚGRAPH_POWER_1YrVrQs r(Úgraph_power_1yrÒs~ô ŒdiŠi
€Cäà Ü à Ü  Ü ‹Hà Ø à Ø à Ø Ø à ܈jÐ


ð
ð
ðC#
õ%rAcó¾[[R"55n[S[S[ US-