Netgate Discussion Forum
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Search
    • Register
    • Login

    NUT dashboard widget

    Scheduled Pinned Locked Moved UPS Tools
    43 Posts 5 Posters 4.3k Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic was forked from QNAP recognizing NUT dennypage
    This topic has been deleted. Only users with topic management privileges can see it.
    • dennypageD
      dennypage @FrankZappa
      last edited by

      @FrankZappa said in QNAP recognizing NUT:

      It would be nice if pfSense made a nice-looking widget for NUT, but that's a discussion for another time.

      Can you explain more please?

      F 1 Reply Last reply Reply Quote 0
      • F
        FrankZappa @dennypage
        last edited by

        @dennypage On the APCUPSD Widget, it has a nice graphic interface and it lets you know about the last battery transfer. That said, I'll take function over fashion. Sticking with NUT.
        5b939ffd-0c7b-4871-8c63-9300f24417d1-image.png

        dennypageD 1 Reply Last reply Reply Quote 0
        • dennypageD
          dennypage @FrankZappa
          last edited by dennypage

          @FrankZappa Okay, thanks. Appreciate the feedback.

          FWIW, here are my initial thoughts:

          • I can see how coloring and an icon in the Summary status line would be helpful visually. I will look at this.
          • Not sure why Host would be in a status widget as it is a static configuration item. Not a good use of space.
          • While line input/output voltage isn't reported by most UPSs, it might be nice. Possibly actionable. Not sure it's worth the space in a status widget though.
          • Last transfer isn't actionable as it does not include any date information. It isn't available for most UPSs, including APC UPSs using the SNMP driver. All you get is "noTransfer".
          • I can see value in battery voltage for Battery charge, and it won't take any additional space. I will look at that.
          • I will look at battery date and test date. This is definitely valuable and actionable information.
          F 1 Reply Last reply Reply Quote 1
          • F
            FrankZappa @dennypage
            last edited by

            @dennypage Cool. Thanks for taking a look. Look forward to your creation.

            1 Reply Last reply Reply Quote 0
            • dennypageD
              dennypage
              last edited by dennypage

              @FrankZappa Below is an enhanced dashboard widget to try out. Please let me know what you think.

              Screenshot 2024-05-17 at 22.12.38.png

              /usr/local/www/widgets/widgets/nut_status.widget.php:

              <?php
              /*
               * nut_status.widget.php
               *
               * part of pfSense (https://www.pfsense.org)
               * Copyright (c) 2004-2024 Rubicon Communications, LLC (Netgate)
               * Copyright (c) 2016-2024 Denny Page
               * All rights reserved.
               *
               * Licensed under the Apache License, Version 2.0 (the "License");
               * you may not use this file except in compliance with the License.
               * You may obtain a copy of the License at
               *
               * http://www.apache.org/licenses/LICENSE-2.0
               *
               * Unless required by applicable law or agreed to in writing, software
               * distributed under the License is distributed on an "AS IS" BASIS,
               * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
               * See the License for the specific language governing permissions and
               * limitations under the License.
               */
              
              
              require_once("/usr/local/www/widgets/include/nut_status.inc");
              require_once("/usr/local/pkg/nut/nut.inc");
              
              
              if ($_REQUEST && $_REQUEST['ajax']) {
              	print_table();
              	exit;
              }
              
              
              function print_row($desc, $value) {
              	print '<tr>';
              	print '  <th style="width:19%">' . $desc . '</th>';
              	print '  <td>' . $value . '</td>';
              	print '</tr>';
              }
              
              function print_row_progressbar($desc, $type, $progress, $txt) {
              	print '<tr>';
              	print '  <th style="width:19%">' . $desc . '</td>';
              	print '  <td>';
              	print '    <div class="progress" style="max-width:99%">';
              	print '      <div class="progress-bar progress-bar-' . $type . ' progress-bar-striped" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="' . $progress . '" style="width: ' . $progress . '%"></div>';
              	print '    </div>';
              	print '    <div style="max-width:99%">';
              	print        $txt;
              	print '    </div>';
              	print '  </td>';
              	print '</tr>';
              }
              
              function print_table() {
              	$status = nut_ups_status();
              
              	if ($status['_alert']) {
              		print '<tr>';
              		print '<th class="danger">' . gettext("Alert") . '</td>';
              		print '<td class="danger"><b>' . gettext("The UPS requires attention") . '</b></td>';
              		print '</tr>';
              	}
              
              	if (isset($status['ups.status'])) {
              		$statwords = $status['ups.status'];
              
              		if (isset($status['battery.charge'])) {
              			$battery = $status['battery.charge'];
              		} else {
              			$battery = 0;
              		}
              
              		if (str_contains($statwords, 'OL')) {
              			$icon_name = 'plug';
              			if ($battery < 50 || str_contains($statwords, 'RB') || str_contains($statwords, 'LB') || str_contains($statwords, 'OVER')) {
              				$icon_color = 'red';
              			} elseif ($battery < 75 || str_contains($statwords, 'BOOST')) {
              				$icon_color = 'orange';
              			} else {
              				$icon_color = 'green';
              			}
              		} elseif (str_contains($statwords, 'OB')) {
              			if ($battery < 25) {
              				$icon_name = 'battery-empty';
              				$icon_color = 'red';
              			} elseif ($battery < 50) {
              				$icon_name = 'battery-quarter';
              				$icon_color = 'red';
              			} elseif ($battery < 75) {
              				$icon_name = 'battery-half';
              				$icon_color = 'orange';
              			} else {
              				$icon_name = 'battery-three-quarters';
              				$icon_color = 'orange';
              			}
              		} else {
              			$icon_name = 'question-circle';
              			$icon_color = 'red';
              		}
              	} else {
              		$icon_name = 'times-circle';
              		$icon_color = 'red';
              	}
              
              	$icon = '<span class="fa-solid fa-' . $icon_name . '" style="color:' . $icon_color . ';width:25px;font-size:1.3em;"></span>';
              	print_row("Summary", $icon . '<span style="font-size:1.1em;">' . htmlspecialchars($status['_summary']) . '</span>');
              
              
              	if (isset($status['ups.alarm'])) {
              		print_row(gettext("Alarm"), htmlspecialchars($status['ups.alarm']));
              	}
              	if (isset($status['_hms'])) {
              		print_row(gettext("Runtime"), htmlspecialchars($status['_hms']) . '&nbsp;&nbsp;(H:M:S)');
              	}
              	if (isset($status['ups.load'])) {
              		$load = htmlspecialchars($status['ups.load']);
              		if ($load < 95) {
              			$type = 'success';
              		} elseif ($load < 99) {
              			$type = 'warning';
              		} else {
              			$type = 'danger';
              		}
              		$txt = '<span style="width:30%;float:left;">' . $load . '%</span>';
              
              		if (isset($status['input.voltage'])) {
              			$txt .= '<span style="width:30%;float:left;"> Vin ' . htmlspecialchars($status['input.voltage']) . 'V</span>';
              			if (isset($status['output.voltage'])) {
              				$txt .= 'Vout ' . htmlspecialchars($status['output.voltage']) . 'V';
              			}
              		}
              
              		print_row_progressbar(gettext("Load"), $type, $load, $txt);
              	}
              
              	if (isset($status['battery.charge'])) {
              		$battery = htmlspecialchars($status['battery.charge']);
              		if ($battery < 50) {
              			$type = 'danger';
              		} elseif ($battery < 75) {
              			$type = 'warning';
              		} else {
              			$type = 'success';
              		}
              
              		$txt = '<span style="width:30%;float:left;">' . $battery . '%</span>';
              		if (isset($status['battery.voltage'])) {
              			$txt .= '<span style="width:30%;float:left;">' . htmlspecialchars($status['battery.voltage']) . 'V</span>';
              		}
              		if (isset($status['battery.date'])) {
              			$txt .= 'Installed ' . htmlspecialchars($status['battery.date']);
              		}
              		print_row_progressbar(gettext("Battery"), $type, $battery, $txt);
              	}
              
              	if (isset($status['ups.test.date'])) {
              		$txt = '<span style="width:30%;float:left;">' . htmlspecialchars($status['ups.test.date']) . '</span>';
              		if (isset($status['ups.test.result'])) {
              			$txt .= 'Result ' . htmlspecialchars($status['ups.test.result']);
              		}
              		print_row(gettext("Last test"), $txt);
              	}
              }
              ?>
              
              
              <div class="table-responsive">
              	<table class="table table-striped table-hover table-condensed">
              		<tbody id="nuttable">
              			<?php print_table(); ?>
              		</tbody>
              	</table>
              </div>
              
              
              <script type="text/javascript">
              //<![CDATA[
                  function update_nut() {
                      var ajaxRequest;
                  
                      ajaxRequest = $.ajax({
                              url: "/widgets/widgets/nut_status.widget.php",
                              type: "post",
                              data: { ajax: "ajax"}
                          });
              
                      // Deal with the results of the above ajax call
                      ajaxRequest.done(function (response, textStatus, jqXHR) {
                          $('#nuttable').html(response);
                          // and do it again
                          setTimeout(update_nut, 10000);
                      });
                  }
              
                  events.push(function(){
                      update_nut();
                  });
              //]]>
              </script>
              
              
              GertjanG F 2 Replies Last reply Reply Quote 1
              • GertjanG
                Gertjan @dennypage
                last edited by

                @dennypage

                Backed up the original file, and put yours in place.
                Looks fine to me 👍

                No "help me" PM's please. Use the forum, the community will thank you.
                Edit : and where are the logs ??

                1 Reply Last reply Reply Quote 0
                • demD
                  dem
                  last edited by

                  Some older CyberPower units report bogus data for items such as output voltage. One of mine says this:

                  input.voltage: 121.0
                  input.voltage.nominal: 120
                  output.voltage: 137.0
                  

                  On an even older one I recall the battery voltage being nonsensical as well.

                  It would be nice to be able to keep such incorrect values from being shown as they can be annoying.

                  dennypageD 1 Reply Last reply Reply Quote 0
                  • dennypageD
                    dennypage @dem
                    last edited by

                    @dem said in NUT dashboard widget:

                    On an even older one I recall the battery voltage being nonsensical as well.

                    The widget (and status page) can only report what it sees reported by upsc. A nonsensical value indicates either a bad value coming out of the UPS, or broken interpretation by the driver. I'm afraid I cannot fix that.

                    demD 1 Reply Last reply Reply Quote 0
                    • demD
                      dem @dennypage
                      last edited by

                      Then perhaps an option not to show the new "extended" information. Fortunately the UPS I'm currently using with pfSense shows the output voltage correctly, but I don't need to be reminded that I never bother with self-tests. 🙂

                      Lately the power utility has been regularly testing the UPS for me anyway. 😠

                      dennypageD 1 Reply Last reply Reply Quote 0
                      • dennypageD
                        dennypage @dem
                        last edited by

                        @dem said in NUT dashboard widget:

                        I don't need to be reminded that I never bother with self-tests.

                        I think it is good to be reminded, however I would expect that if you can ignore self tests for the UPS you can also ignore the last test info. 🙂

                        A UPS is critical infrastructure. You want to know if there are issues with it. The last test date and test result are important. This and the battery date are the big reasons that I am updating the widget. The colorization is a nice to have.

                        1 Reply Last reply Reply Quote 0
                        • F
                          FrankZappa @dennypage
                          last edited by

                          @dennypage Wow! Didn't expect it that fast. Love it! Is there any way to display when and why UPS went to battery last time?

                          Thanks for making this.

                          F dennypageD 2 Replies Last reply Reply Quote 0
                          • F
                            FrankZappa @FrankZappa
                            last edited by

                            @FrankZappa Also, I really like the colors to make it pop in the dashboard. If the battery is not charged to 100% does the bar graph change to yellow, and maybe once it gets down to 50% can it turn red? Just thought it would look cool (not that I want my battery to ever get down to 50%). Thanks

                            F 1 Reply Last reply Reply Quote 0
                            • F
                              FrankZappa @FrankZappa
                              last edited by

                              @FrankZappa Mine is showing the wrong battery date and I don't have the last test. Other than that, it looks great.
                              3f5f1d26-ee48-4a60-ba8a-dfc70be37953-image.png

                              1 Reply Last reply Reply Quote 0
                              • dennypageD
                                dennypage @FrankZappa
                                last edited by

                                @FrankZappa said in NUT dashboard widget:

                                Wow! Didn't expect it that fast. Love it!

                                Glad you like it. I had some time...

                                @FrankZappa said in NUT dashboard widget:

                                Is there any way to display when and why UPS went to battery last time?

                                I don't believe this is reported. I have a fairly high end APC, and I don't have it. Best alternative is enabling notifications and then you'll get a real-time notification of transfers.

                                @FrankZappa said in NUT dashboard widget:

                                I really like the colors to make it pop in the dashboard. If the battery is not charged to 100% does the bar graph change to yellow, and maybe once it gets down to 50% can it turn red?

                                The battery bar is red below 50%, yellow below 75%, otherwise green. Same for the summary icon, which shows plug, battery (with levels), and unknown. Even if the UPS is on line, if the UPS reports that the battery needs replacing, or if the UPS is overloaded, the plug icon will remain red.

                                The load bar is green below 95%, yellow below 99%, and red above.

                                @FrankZappa said in NUT dashboard widget:

                                Mine is showing the wrong battery date and I don't have the last test.

                                The 2001/09/25 date kinda looks like a "never been set" value. Look for "battery.date" in Services / UPS / UPS Status. This is what is reported to/by NUT. What do you see there?

                                For test info, look for "ups.test.date" and/or "ups.test.result" in Services / UPS /UPS Status. Are these being reported by the UPS to NUT?

                                F T 2 Replies Last reply Reply Quote 0
                                • F
                                  FrankZappa @dennypage
                                  last edited by

                                  @dennypage Thanks dennypage. Here's a screenshot of everything I have.
                                  7074717a-e238-4700-b97b-7799530905d3-image.png

                                  dennypageD 2 Replies Last reply Reply Quote 0
                                  • T
                                    tgl
                                    last edited by

                                    I'm not sure what "battery.date" is really meant to be, but it reads as 2001/09/25 on my APC UPSes too. Maybe it identifies the age of the design? Anyway, these fields seem considerably more plausible as the real age of the one I'm looking at:

                                    battery.mfr.date: 2022/04/13
                                    ups.mfr.date: 2022/04/13

                                    dennypageD 1 Reply Last reply Reply Quote 0
                                    • T
                                      tgl @dennypage
                                      last edited by

                                      @dennypage said in NUT dashboard widget:

                                      For test info, look for "ups.test.date" and/or "ups.test.result" in Services / UPS /UPS Status. Are these being reported by the UPS to NUT?

                                      A field like "ups.test.date" could only get populated accurately if the UPS contains an RTC. I've owned a lot of UPSes over the years, and never seen any indication that they have settable clocks. The date fields they do output all look like burned-in-at-the-factory values.

                                      1 Reply Last reply Reply Quote 0
                                      • dennypageD
                                        dennypage @FrankZappa
                                        last edited by

                                        @FrankZappa So, your battery date really does show as 2001/09/25. I believe this means that it was not set at the factory. Looks like the apcupsd widget was reporting the UPS manufacture date rather than the battery install date.

                                        To set the battery date, you can (hopefully) use upsrw.

                                        Use

                                        upsrw -l UPSNAME
                                        

                                        to see what variables you can write in the UPS. The variable you are looking for is "battery.date".

                                        Your "ups.test.result" shows that no self test has been run on the UPS. For higher end APC UPSs, this is done by automatic timer. For lower end UPSs, you have to trigger it manually. If you do that, you will have to write the test date yourself--look for variable "ups.test.date" in the upsrw output.

                                        F 1 Reply Last reply Reply Quote 0
                                        • dennypageD
                                          dennypage @tgl
                                          last edited by

                                          @tgl said in NUT dashboard widget:

                                          I'm not sure what "battery.date" is really meant to be, but it reads as 2001/09/25 on my APC UPSes too.

                                          See note above. It just means that it wasn't set at factory or at the point of initial install (which requires a UPS that has time capability).

                                          If the UPS doesn't have time capability, then you are responsible for maintaining this field by hand when you initially install and/or change batteries.

                                          If your UPS has a network management card, this would be handled automatically. My current APC is like this.

                                          T 1 Reply Last reply Reply Quote 0
                                          • dennypageD
                                            dennypage @FrankZappa
                                            last edited by

                                            @FrankZappa Forgot to mention. To run a self-test, would use upscmd. To see a list of commands the UPS will accept, use:

                                            upscmd -l UPSNAME
                                            

                                            Most likely, the command will be:

                                            upscmd UPSNAME test.battery.start
                                            
                                            1 Reply Last reply Reply Quote 0
                                            • First post
                                              Last post
                                            Copyright 2025 Rubicon Communications LLC (Netgate). All rights reserved.