diff --git a/.gitignore b/.gitignore index 27df0d4cc4..c067fadad1 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ .deps/ .libs/ .inst/ +/_install_pkgprotodir/ Makefile Makefile.in ## Parent directory only @@ -19,6 +20,7 @@ Makefile.in /config.log /config.status /config.sub +/config.cache /configure /cscope.* /depcomp @@ -33,6 +35,10 @@ common/.dirstamp # Dist /nut-*.*.*/ /nut-*.tar.gz +/nut*.rpm +/NUT*.local.gz +/NUT*.p5i +/NUT*.depot # Official dist /nut-*.tar.gz.md5 diff --git a/.travis.yml b/.travis.yml index b65ff9cd54..a8b9e7c184 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,9 +14,11 @@ os: sudo: false -# Tests for cppunit require C++11 which requires gcc-4.8 or newer -# This is available in either "trusty" or newer distros, or in "docker" envs -#dist: trusty +# Tests for cppunit require C++11 which requires gcc-4.8 or newer. +# This is available in either "trusty" or newer distros (e.g. "xenial" +# which we also reference explicitly for additional repositories below), +# or in "docker" envs. +dist: xenial services: - docker @@ -57,23 +59,119 @@ addons: - libxml2-utils - libmodbus-dev -# Define one job in the matrix, to avoid a failing job -# with "no environment variables set"; but others are -# listed below to prioritize the longer jobs to start first. +# Common settings for jobs in the matrix built below env: global: - CI_TIME=true - CI_TRACE=false - matrix: - - BUILD_TYPE=default + - CI_DEFAULT_HOMEBREW_NO_AUTO_UPDATE=1 + # By default, avoid updating (including cleaning) osx worker beside what + # we require to install, compared to what Travis provides. Technically + # we can call master branch builds sometimes to update the workers cache + # of packages by manual or timer-driven runs with explicit setting like + # HOMEBREW_NO_AUTO_UPDATE=0 # Builds with customized setups # Note that doc-related builds take the longest, and Travis CI cloud # runs only a few sub-jobs in parallel, so we want the withdoc and # perhaps spellcheck jobs to start first, and while they are still in # progress, others are spawned and finished - reducing overall job TTL. -matrix: - include: +# Note that the nut-driver-enumerator tests should be tried in at least +# the shell interpreters reasonable for default setups of Solaris/illumos +# (ksh) and Linux (bash, dash, etc.) common distros. + +# First pass is a few default compilations that normally happen +# early in Travis CI build chain +_matrix_required_linux_pass1_quick: + include: &_matrix_required_linux_pass1_quick + - env: BUILD_TYPE=default-nodoc + os: linux + addons: + apt: + packages: + - *deps_driverlibs + + - env: BUILD_TYPE=default-spellcheck + os: linux + addons: + apt: + packages: &deps_aspell + - aspell + - aspell-en + + - env: BUILD_TYPE=default + os: linux + addons: + apt: + packages: + - *deps_driverlibs + + - env: BUILD_TYPE=default-tgt:distcheck-light + os: linux + addons: + apt: + packages: + - *deps_driverlibs + +# Second pass is a number of shell script syntax checks in standard env: +_matrix_required_linux_pass2_shell: + include: &_matrix_required_linux_pass2_shell + - env: BUILD_TYPE=default-shellcheck + os: linux + addons: + apt: + packages: + - coreutils + - file + #TBD# - shellcheck + + - env: BUILD_TYPE=nut-driver-enumerator-test SHELL_PROGS=bash + os: linux + services: + - docker + addons: + apt: + packages: + - bash + - env: BUILD_TYPE=nut-driver-enumerator-test SHELL_PROGS=ksh + os: linux + services: + - docker + addons: + apt: + packages: + - ksh + - env: BUILD_TYPE=nut-driver-enumerator-test SHELL_PROGS=dash + os: linux + services: + - docker + addons: + apt: + packages: + - dash + - env: BUILD_TYPE=nut-driver-enumerator-test SHELL_PROGS=ash + os: linux + services: + - docker + addons: + apt: + packages: + - ash + +# Third pass is a number of larger builds that confirm non-core code is clean: +_matrix_required_linux_pass3_large: + include: &_matrix_required_linux_pass3_large + - env: BUILD_TYPE=default-tgt:distcheck-valgrind + os: linux + sudo: false + services: + - docker + addons: + apt: + packages: + - *deps_driverlibs + - valgrind + - env: BUILD_TYPE=default-withdoc os: linux addons: @@ -86,51 +184,729 @@ matrix: - docbook-xsl-ns - source-highlight - libxml2-utils - - env: BUILD_TYPE=default-spellcheck + + - env: BUILD_TYPE=default-alldrv os: linux + sudo: false + services: + - docker addons: apt: - packages: &deps_aspell - - aspell - - aspell-en - - env: BUILD_TYPE=default-tgt:distcheck-valgrind + packages: + - *deps_driverlibs + + - env: + - BUILD_TYPE=default-tgt:distcheck-light + - NO_PKG_CONFIG=true + os: linux + sudo: true + addons: + apt: + packages: + - *deps_driverlibs + +# Re-run the build of all binaries we can make, with +# varied compiler and C/C++ standard implementations +# and different lenience against warnings. Many of +# these blocks look similar and all should have unique +# "env" field to use some with allowed_failure below. +# For a list of standards supported, see: +# https://gcc.gnu.org/onlinedocs/gcc/Standards.html +# https://gcc.gnu.org/projects/cxx-status.html +# https://clang.llvm.org/cxx_status.html +# Note that while there is C++14 there is no C14: +# https://en.wikipedia.org/wiki/C_(programming_language)#History +# +# The leading NUT_MATRIX_TAG allows humans to understand +# what a test case is about in Travis CI dashboard table +# of jobs, but otherwise it is not used by script code. +# +# Note that passing multi-token C*FLAGS may be problematic +# for sub-makes like distcheck; verify thoroughly before +# trying to enable those if that would make sense anytime. +# +# Ordered by variants expected to succeed to run first, +# although with current Travis CI implementation, the env +# blocks listed in allowed_failures only run after all +# those not listed: +# + +_matrix_linux_gnustd_nowarn: + include: &_matrix_linux_gnustd_nowarn + - env: NUT_MATRIX_TAG="gnu99-gcc-default-nowarn" BUILD_TYPE=default-all-errors CFLAGS="-std=gnu99" CXXFLAGS="-std=gnu++99" os: linux sudo: false services: - docker + compiler: gcc addons: apt: packages: - *deps_driverlibs - - valgrind -# Other quicker builds in standard env follow: - - env: BUILD_TYPE=default-nodoc + + - env: NUT_MATRIX_TAG="gnu99-gcc-7-nowarn" BUILD_TYPE=default-all-errors CFLAGS="-std=gnu99" CXXFLAGS="-std=gnu++99" CC=gcc-7 CXX=g++-7 + os: linux + sudo: false + services: + - docker + compiler: gcc + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-7 + - gcc-7 + - *deps_driverlibs + + - env: NUT_MATRIX_TAG="gnu11-gcc-7-nowarn" BUILD_TYPE=default-all-errors CFLAGS="-std=gnu11" CXXFLAGS="-std=gnu++11" CC=gcc-7 CXX=g++-7 os: linux + sudo: false + services: + - docker + compiler: gcc addons: apt: + sources: + - ubuntu-toolchain-r-test packages: + - g++-7 + - gcc-7 - *deps_driverlibs - - env: BUILD_TYPE=default-alldrv + + - env: NUT_MATRIX_TAG="gnu17-gcc-9-nowarn" BUILD_TYPE=default-all-errors CFLAGS="-std=gnu17" CXXFLAGS="-std=gnu++17" CC=gcc-9 CXX=g++-9 os: linux sudo: false services: - docker + compiler: gcc addons: apt: + sources: + - ubuntu-toolchain-r-test packages: + - g++-9 + - gcc-9 - *deps_driverlibs - - env: BUILD_TYPE=default-tgt:distcheck-light + + - env: NUT_MATRIX_TAG="gnu99-clang-5.0-nowarn" BUILD_TYPE=default-all-errors CFLAGS="-std=gnu99" CXXFLAGS="-std=gnu++99" CC=clang CXX=clang++ + os: linux + dist: xenial + sudo: false + services: + - docker + compiler: clang + addons: + apt: + sources: + - llvm-toolchain-xenial-5.0 + packages: + - clang-5.0 + - clang-format-5.0 + - *deps_driverlibs + + - env: NUT_MATRIX_TAG="gnu17-clang-8-nowarn" BUILD_TYPE=default-all-errors CFLAGS="-std=gnu17" CXXFLAGS="-std=gnu++17" CC=clang-8 CXX=clang++-8 + os: linux + dist: xenial + sudo: false + services: + - docker + compiler: clang + addons: + apt: + sources: + - llvm-toolchain-xenial-8 + packages: + - clang-8 + - clang-format-8 + - *deps_driverlibs + +# Note: some of the warnings that are hidden in this case seem to be serious +# issues that may impact viability of binaries built by C89 mode compilers! + - env: NUT_MATRIX_TAG="gnu89-gcc-default-nowarn" BUILD_TYPE=default-all-errors CFLAGS="-std=gnu89" CXXFLAGS="-std=gnu++89" + os: linux + sudo: false + services: + - docker + compiler: gcc + addons: + apt: + packages: + - *deps_driverlibs + +# At this time, anything with strict C standard fails on Linux, even "nowarn" cases: +_matrix_linux_cstd_nowarn: + include: &_matrix_linux_cstd_nowarn + - env: NUT_MATRIX_TAG="c99-clang-3.5-nowarn" BUILD_TYPE=default-all-errors CFLAGS="-std=c99" CXXFLAGS="-std=c++99" CC=clang-3.5 CXX=clang++-3.5 + os: linux + dist: xenial + sudo: false + services: + - docker + compiler: clang + addons: + apt: + sources: + - llvm-toolchain-xenial-3.5 + packages: + - clang-3.5 + - clang-format-3.5 + - *deps_driverlibs + + - env: NUT_MATRIX_TAG="c99-clang-5.0-nowarn" BUILD_TYPE=default-all-errors CFLAGS="-std=c99" CXXFLAGS="-std=c++99" CC=clang CXX=clang++ + os: linux + dist: xenial + sudo: false + services: + - docker + compiler: clang + addons: + apt: + sources: + - llvm-toolchain-xenial-5.0 + packages: + - clang-5.0 + - clang-format-5.0 + - *deps_driverlibs + + - env: NUT_MATRIX_TAG="c11-clang-5.0-nowarn" BUILD_TYPE=default-all-errors CFLAGS="-std=c11" CXXFLAGS="-std=c++11" CC=clang CXX=clang++ + os: linux + dist: xenial + sudo: false + services: + - docker + compiler: clang + addons: + apt: + sources: + - llvm-toolchain-xenial-5.0 + packages: + - clang-5.0 + - clang-format-5.0 + - *deps_driverlibs + + - env: NUT_MATRIX_TAG="c17-clang-8-nowarn" BUILD_TYPE=default-all-errors CFLAGS="-std=c17" CXXFLAGS="-std=c++17" CC=clang-8 CXX=clang++-8 + os: linux + dist: xenial + sudo: false + services: + - docker + compiler: clang + addons: + apt: + sources: + - llvm-toolchain-xenial-8 + packages: + - clang-8 + - clang-format-8 + - *deps_driverlibs + +# Stuff with warnings made fatal... well, is usually fatal so far: +_matrix_linux_gnustd_warn: + include: &_matrix_linux_gnustd_warn + - env: NUT_MATRIX_TAG="cDefault-gcc-default-warn" BUILD_TYPE=default-all-errors CFLAGS="-Wall -Werror -pedantic" CXXFLAGS="-Wall -Werror" os: linux sudo: false services: - docker + compiler: gcc addons: apt: packages: - *deps_driverlibs + - env: NUT_MATRIX_TAG="gnu99-gcc-default-warn" BUILD_TYPE=default-all-errors CFLAGS="-Wall -Werror -pedantic -std=gnu99" CXXFLAGS="-Wall -Werror -std=gnu++99" + os: linux + sudo: false + services: + - docker + compiler: gcc + addons: + apt: + packages: + - *deps_driverlibs + + - env: NUT_MATRIX_TAG="gnu11-gcc-default-warn" BUILD_TYPE=default-all-errors CFLAGS="-Wall -Werror -pedantic -std=gnu11" CXXFLAGS="-Wall -Werror -std=gnu++11" + os: linux + sudo: false + services: + - docker + compiler: gcc + addons: + apt: + packages: + - *deps_driverlibs + + - env: NUT_MATRIX_TAG="gnu99-gcc-7-warn" BUILD_TYPE=default-all-errors CFLAGS="-Wall -Werror -pedantic -std=gnu99" CXXFLAGS="-Wall -Werror -std=gnu++99" CC=gcc-7 CXX=g++-7 + os: linux + sudo: false + services: + - docker + compiler: gcc + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-7 + - gcc-7 + - *deps_driverlibs + + - env: NUT_MATRIX_TAG="gnu17-gcc-9-warn" BUILD_TYPE=default-all-errors CFLAGS="-Wall -Werror -pedantic -std=gnu17" CXXFLAGS="-Wall -Werror -std=gnu++17" CC=gcc-9 CXX=g++-9 + os: linux + sudo: false + services: + - docker + compiler: gcc + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-9 + - gcc-9 + - *deps_driverlibs + +# Note: Fixing these would make NUT viable again on platforms with only ANSI C! + - env: NUT_MATRIX_TAG="gnu89-gcc-default-warn" BUILD_TYPE=default-all-errors CFLAGS="-Wall -Werror -pedantic -std=gnu89" CXXFLAGS="-Wall -Werror -std=gnu++89" + os: linux + sudo: false + services: + - docker + compiler: gcc + addons: + apt: + packages: + - *deps_driverlibs + +# The hardest of two worlds: both strict C standards on Linux and fatal warnings: +_matrix_linux_cstd_warn: + include: &_matrix_linux_cstd_warn + - env: NUT_MATRIX_TAG="c99-gcc-default-warn" BUILD_TYPE=default-all-errors CFLAGS="-Wall -Werror -pedantic -std=c99" CXXFLAGS="-Wall -Werror -std=c++99" + os: linux + sudo: false + services: + - docker + compiler: gcc + addons: + apt: + packages: + - *deps_driverlibs + + - env: NUT_MATRIX_TAG="c99-clang-5.0-warn" BUILD_TYPE=default-all-errors CFLAGS="-Wall -Werror -pedantic -std=c99" CXXFLAGS="-Wall -Werror -std=c++99" CC=clang CXX=clang++ + os: linux + dist: xenial + sudo: false + services: + - docker + compiler: clang + addons: + apt: + sources: + - llvm-toolchain-xenial-5.0 + packages: + - clang-5.0 + - clang-format-5.0 + - *deps_driverlibs + + - env: NUT_MATRIX_TAG="c11-clang-5.0-warn" BUILD_TYPE=default-all-errors CFLAGS="-Wall -Werror -pedantic -std=c11" CXXFLAGS="-Wall -Werror -std=c++11" CC=clang CXX=clang++ + os: linux + dist: xenial + sudo: false + services: + - docker + compiler: clang + addons: + apt: + sources: + - llvm-toolchain-xenial-5.0 + packages: + - clang-5.0 + - clang-format-5.0 + - *deps_driverlibs + + - env: NUT_MATRIX_TAG="c17-clang-8-warn" BUILD_TYPE=default-all-errors CFLAGS="-Wall -Werror -pedantic -std=c17" CXXFLAGS="-Wall -Werror -std=c++17" CC=clang-8 CXX=clang++-8 + os: linux + dist: xenial + sudo: false + services: + - docker + compiler: clang + addons: + apt: + sources: + - llvm-toolchain-xenial-8 + packages: + - clang-8 + - clang-format-8 + - *deps_driverlibs + + - env: NUT_MATRIX_TAG="c11-gcc-default-warn" BUILD_TYPE=default-all-errors CFLAGS="-Wall -Werror -pedantic -std=c11" CXXFLAGS="-Wall -Werror -std=c++11" + os: linux + sudo: false + services: + - docker + compiler: gcc + addons: + apt: + packages: + - *deps_driverlibs + + - env: NUT_MATRIX_TAG="c89-gcc-default-warn" BUILD_TYPE=default-all-errors CFLAGS="-Wall -Werror -pedantic -std=c89" CXXFLAGS="-Wall -Werror -std=c++89" + os: linux + sudo: false + services: + - docker + compiler: gcc + addons: + apt: + packages: + - *deps_driverlibs + +# Try also a range of platforms for MacOS X builds +# Inspired by https://github.com/taocpp/operators/blob/master/.travis.yml +_matrix_osx_gnustd_nowarn: + include: &_matrix_osx_gnustd_nowarn + - env: NUT_MATRIX_TAG="gnu99-clang-xcode10.2-nowarn" BUILD_TYPE=default-all-errors CFLAGS="-std=gnu99" CXXFLAGS="-std=gnu++99" CC=clang CXX=clang++ + os: osx + osx_image: xcode10.2 + compiler: clang + cache: + directories: + - $HOME/Library/Caches/Homebrew + - $HOME/.ccache + + - env: NUT_MATRIX_TAG="gnu17-clang-xcode10.2-nowarn" BUILD_TYPE=default-all-errors CFLAGS="-std=gnu17" CXXFLAGS="-std=gnu++17" CC=clang CXX=clang++ + os: osx + osx_image: xcode10.2 + compiler: clang + cache: + directories: + - $HOME/Library/Caches/Homebrew + - $HOME/.ccache + + - env: NUT_MATRIX_TAG="gnu99-clang-xcode7.3-nowarn" BUILD_TYPE=default-all-errors CFLAGS="-std=gnu99" CXXFLAGS="-std=gnu++99" CC=clang CXX=clang++ + os: osx + osx_image: xcode7.3 + compiler: clang + cache: + directories: + - $HOME/Library/Caches/Homebrew + - $HOME/.ccache + +_matrix_osx_gnustd_warn: + include: &_matrix_osx_gnustd_warn + - env: NUT_MATRIX_TAG="gnu99-clang-xcode10.2-warn" BUILD_TYPE=default-all-errors CFLAGS="-Wall -Werror -pedantic -std=gnu99" CXXFLAGS="-Wall -Werror -std=gnu++99" CC=clang CXX=clang++ + os: osx + osx_image: xcode10.2 + compiler: clang + cache: + directories: + - $HOME/Library/Caches/Homebrew + - $HOME/.ccache + + - env: NUT_MATRIX_TAG="gnu17-clang-xcode10.2-warn" BUILD_TYPE=default-all-errors CFLAGS="-Wall -Werror -pedantic -std=gnu17" CXXFLAGS="-Wall -Werror -std=gnu++17" CC=clang CXX=clang++ + os: osx + osx_image: xcode10.2 + compiler: clang + cache: + directories: + - $HOME/Library/Caches/Homebrew + - $HOME/.ccache + +_matrix_osx_cstd_nowarn: + include: &_matrix_osx_cstd_nowarn + - env: NUT_MATRIX_TAG="c99-clang-xcode10.2-nowarn" BUILD_TYPE=default-all-errors CFLAGS="-std=c99" CXXFLAGS="-std=c++99" CC=clang CXX=clang++ + os: osx + osx_image: xcode10.2 + compiler: clang + cache: + directories: + - $HOME/Library/Caches/Homebrew + - $HOME/.ccache + + - env: NUT_MATRIX_TAG="c17-clang-xcode10.2-nowarn" BUILD_TYPE=default-all-errors CFLAGS="-std=c17" CXXFLAGS="-std=c++17" CC=clang CXX=clang++ + os: osx + osx_image: xcode10.2 + compiler: clang + cache: + directories: + - $HOME/Library/Caches/Homebrew + - $HOME/.ccache + +_matrix_osx_cstd_warn: + include: &_matrix_osx_cstd_warn + - env: NUT_MATRIX_TAG="c99-clang-xcode10.2-warn" BUILD_TYPE=default-all-errors CFLAGS="-Wall -Werror -pedantic -std=c99" CXXFLAGS="-Wall -Werror -std=c++99" CC=clang CXX=clang++ + os: osx + osx_image: xcode10.2 + compiler: clang + cache: + directories: + - $HOME/Library/Caches/Homebrew + - $HOME/.ccache + + - env: NUT_MATRIX_TAG="c17-clang-xcode10.2-warn" BUILD_TYPE=default-all-errors CFLAGS="-Wall -Werror -pedantic -std=c17" CXXFLAGS="-Wall -Werror -std=c++17" CC=clang CXX=clang++ + os: osx + osx_image: xcode10.2 + compiler: clang + cache: + directories: + - $HOME/Library/Caches/Homebrew + - $HOME/.ccache + + - env: NUT_MATRIX_TAG="c17-clang-xcode7.3-warn" BUILD_TYPE=default-all-errors CFLAGS="-Wall -Werror -pedantic -std=c17" CXXFLAGS="-Wall -Werror -std=c++17" CC=clang CXX=clang++ + os: osx + osx_image: xcode7.3 + compiler: clang + cache: + directories: + - $HOME/Library/Caches/Homebrew + - $HOME/.ccache + +# Try also a build on Windows to see our horizons +# https://docs.travis-ci.com/user/reference/windows/ +# says we have clang-9 there by default (and there is +# a complex routine to add gcc if we'd need that) +# and a Git Bash as default shell, but no ccache. +# TODO: Eventually try native visualstudio compilers? +_matrix_windows_gnustd_nowarn: + include: &_matrix_windows_gnustd_nowarn + - env: NUT_MATRIX_TAG="gnu99-clang-win-nowarn" BUILD_TYPE=default-all-errors CPPFLAGS="-fms-extensions" CFLAGS="-std=gnu99" CXXFLAGS="-std=gnu++99" CC=clang CXX=clang++ + os: windows + compiler: clang + cache: + directories: + - $HOME/AppData/Local/Temp/chocolatey + - $HOME/.ccache + - /C/tools + +_matrix_windows_cstd_nowarn: + include: &_matrix_windows_cstd_nowarn + - env: NUT_MATRIX_TAG="c99-clang-win-nowarn" BUILD_TYPE=default-all-errors CPPFLAGS="-fms-extensions" CFLAGS="-std=c99" CXXFLAGS="-std=c++99" CC=clang CXX=clang++ + os: windows + compiler: clang + cache: + directories: + - $HOME/AppData/Local/Temp/chocolatey + - $HOME/.ccache + - /C/tools + +_matrix_windows_cstd_warn: + include: &_matrix_windows_cstd_warn + - env: NUT_MATRIX_TAG="c99-clang-win-warn" BUILD_TYPE=default-all-errors CPPFLAGS="-fms-extensions" CFLAGS="-Wall -Werror -pedantic -std=c99" CXXFLAGS="-Wall -Werror -std=c++99" CC=clang CXX=clang++ + os: windows + compiler: clang + cache: + directories: + - $HOME/AppData/Local/Temp/chocolatey + - $HOME/.ccache + - /C/tools + +# Incidentally, this is one platform we know to have clang-9, +# the version which has (at least partial) C++20 support + - env: NUT_MATRIX_TAG="c20-clang-win-warn" BUILD_TYPE=default-all-errors CPPFLAGS="-fms-extensions" CFLAGS="-Wall -Werror -pedantic -std=c20" CXXFLAGS="-Wall -Werror -std=c++20" CC=clang CXX=clang++ + os: windows + compiler: clang + cache: + directories: + - $HOME/AppData/Local/Temp/chocolatey + - $HOME/.ccache + - /C/tools + +################################################################################### +# Summarize the matrix blocks above to quickly enable/disable subsets +# of tests in development (e.g. to focus on fixing bugs and not wasting +# resources on rebuilding green codebase over and over) + +# The original set of tests that are required for master branch CI +# ...and also the set of builds with various compilers and C standards +# that should survive at least without warnings made fatal... + +_matrix_required_linux: + include: &_matrix_required_linux + - *_matrix_required_linux_pass1_quick + - *_matrix_required_linux_pass2_shell + - *_matrix_required_linux_pass3_large + - *_matrix_linux_gnustd_nowarn + +_matrix_allowfail_linux: + include: &_matrix_allowfail_linux + - *_matrix_linux_cstd_nowarn + - *_matrix_linux_gnustd_warn + - *_matrix_linux_cstd_warn + +_matrix_linux: + include: &_matrix_linux + - *_matrix_required_linux + - *_matrix_allowfail_linux + +_matrix_allowfail_osx: + include: &_matrix_allowfail_osx + - *_matrix_osx_cstd_nowarn + - *_matrix_osx_gnustd_warn + - *_matrix_osx_cstd_warn + +_matrix_required_osx: + include: &_matrix_required_osx + - *_matrix_osx_gnustd_nowarn + +_matrix_osx: + include: &_matrix_osx + - *_matrix_required_osx + - *_matrix_allowfail_osx + +# Nothing this good yet +#_matrix_required_windows: +# include: &_matrix_required_windows + +_matrix_allowfail_windows: + include: &_matrix_allowfail_windows + - *_matrix_windows_gnustd_nowarn + - *_matrix_windows_cstd_nowarn + - *_matrix_windows_cstd_warn + +_matrix_windows: + include: &_matrix_windows +# - *_matrix_required_windows + - *_matrix_allowfail_windows + +# Different dissections of interest to fixers: +_matrix_cstd_nowarn: + include: &_matrix_cstd_nowarn + - *_matrix_linux_cstd_nowarn + - *_matrix_osx_cstd_nowarn + - *_matrix_windows_cstd_nowarn +### - *_matrix_osx_gnustd_nowarn +### - *_matrix_linux_gnustd_nowarn + +_matrix_warn: + include: &_matrix_warn + - *_matrix_linux_gnustd_warn + - *_matrix_linux_cstd_warn + - *_matrix_osx_gnustd_warn + - *_matrix_osx_cstd_warn + - *_matrix_windows_cstd_warn + +# Default "jobs:" matrix should reference at least this for master branches +_matrix_required: + include: &_matrix_required + - *_matrix_required_linux + - *_matrix_required_osx +# - *_matrix_required_windows + +_matrix_all: + include: &_matrix_all + - *_matrix_linux + - *_matrix_osx + - *_matrix_windows + +_matrix_master: + include: &_matrix_master + - *_matrix_required +### Enable for branch builds that intend to fix the issues which preclude +### following items from becoming green: +# - *_matrix_allowfail_linux +# - *_matrix_allowfail_osx +# - *_matrix_windows + +_matrix_fixbugs: + include: &_matrix_fixbugs + - *_matrix_cstd_nowarn + - *_matrix_warn + +################################################################################### +# Developers can import some of the definitions above (e.g. _matrix-fixbugs +# instead of _matrix-master) to get more relevant runs of Travis CI against +# their branches for their iterations trying to fix stuff. +# +# DO NOT COMMIT TO MASTER BRANCH TEST-MATRICES THAT ARE NOT _matrix-master! +# +# These days, "jobs" and "matrix" are same thing... at least, ours is an explicit list. +# By "fast_finish" we allow to assign a verdict based on completion of required +# test cases. The "allow_failures" will proceed to run for our information +# but not block nor delay PR considerations etc. +jobs: + fast_finish: true + include: + - *_matrix_master + +################################################################################### +# Note: "env" lines below must exactly describe a matrix option defined above + allow_failures: +#OK# - env: NUT_MATRIX_TAG="gnu99-gcc-default-nowarn" BUILD_TYPE=default-all-errors CFLAGS="-std=gnu99" CXXFLAGS="-std=gnu++99" +#OK# - env: NUT_MATRIX_TAG="gnu99-gcc-7-nowarn" BUILD_TYPE=default-all-errors CFLAGS="-std=gnu99" CXXFLAGS="-std=gnu++99" CC=gcc-7 CXX=g++-7 +#OK# - env: NUT_MATRIX_TAG="gnu11-gcc-7-nowarn" BUILD_TYPE=default-all-errors CFLAGS="-std=gnu11" CXXFLAGS="-std=gnu++11" CC=gcc-7 CXX=g++-7 +#OK# - env: NUT_MATRIX_TAG="gnu17-gcc-9-nowarn" BUILD_TYPE=default-all-errors CFLAGS="-std=gnu17" CXXFLAGS="-std=gnu++17" CC=gcc-9 CXX=g++-9 +#OK# - env: NUT_MATRIX_TAG="gnu99-clang-5.0-nowarn" BUILD_TYPE=default-all-errors CFLAGS="-std=gnu99" CXXFLAGS="-std=gnu++99" CC=clang CXX=clang++ +#OK# - env: NUT_MATRIX_TAG="gnu17-clang-8-nowarn" BUILD_TYPE=default-all-errors CFLAGS="-std=gnu17" CXXFLAGS="-std=gnu++17" CC=clang-8 CXX=clang++-8 + - env: NUT_MATRIX_TAG="gnu17-gcc-9-warn" BUILD_TYPE=default-all-errors CFLAGS="-Wall -Werror -pedantic -std=gnu17" CXXFLAGS="-Wall -Werror -std=gnu++17" CC=gcc-9 CXX=g++-9 + - env: NUT_MATRIX_TAG="c99-clang-3.5-nowarn" BUILD_TYPE=default-all-errors CFLAGS="-std=c99" CXXFLAGS="-std=c++99" CC=clang-3.5 CXX=clang++-3.5 + - env: NUT_MATRIX_TAG="c99-clang-5.0-nowarn" BUILD_TYPE=default-all-errors CFLAGS="-std=c99" CXXFLAGS="-std=c++99" CC=clang CXX=clang++ + - env: NUT_MATRIX_TAG="c11-clang-5.0-nowarn" BUILD_TYPE=default-all-errors CFLAGS="-std=c11" CXXFLAGS="-std=c++11" CC=clang CXX=clang++ + - env: NUT_MATRIX_TAG="c17-clang-8-nowarn" BUILD_TYPE=default-all-errors CFLAGS="-std=c17" CXXFLAGS="-std=c++17" CC=clang-8 CXX=clang++-8 + - env: NUT_MATRIX_TAG="c17-clang-8-warn" BUILD_TYPE=default-all-errors CFLAGS="-Wall -Werror -pedantic -std=c17" CXXFLAGS="-Wall -Werror -std=c++17" CC=clang-8 CXX=clang++-8 + - env: NUT_MATRIX_TAG="cDefault-gcc-default-warn" BUILD_TYPE=default-all-errors CFLAGS="-Wall -Werror -pedantic" CXXFLAGS="-Wall -Werror" + - env: NUT_MATRIX_TAG="gnu99-gcc-default-warn" BUILD_TYPE=default-all-errors CFLAGS="-Wall -Werror -pedantic -std=gnu99" CXXFLAGS="-Wall -Werror -std=gnu++99" + - env: NUT_MATRIX_TAG="c99-gcc-default-warn" BUILD_TYPE=default-all-errors CFLAGS="-Wall -Werror -pedantic -std=c99" CXXFLAGS="-Wall -Werror -std=c++99" + - env: NUT_MATRIX_TAG="gnu99-gcc-7-warn" BUILD_TYPE=default-all-errors CFLAGS="-Wall -Werror -pedantic -std=gnu99" CXXFLAGS="-Wall -Werror -std=gnu++99" CC=gcc-7 CXX=g++-7 + - env: NUT_MATRIX_TAG="c99-clang-5.0-warn" BUILD_TYPE=default-all-errors CFLAGS="-Wall -Werror -pedantic -std=c99" CXXFLAGS="-Wall -Werror -std=c++99" CC=clang CXX=clang++ + - env: NUT_MATRIX_TAG="c11-clang-5.0-warn" BUILD_TYPE=default-all-errors CFLAGS="-Wall -Werror -pedantic -std=c11" CXXFLAGS="-Wall -Werror -std=c++11" CC=clang CXX=clang++ + - env: NUT_MATRIX_TAG="c11-gcc-default-warn" BUILD_TYPE=default-all-errors CFLAGS="-Wall -Werror -pedantic -std=c11" CXXFLAGS="-Wall -Werror -std=c++11" + - env: NUT_MATRIX_TAG="gnu11-gcc-default-warn" BUILD_TYPE=default-all-errors CFLAGS="-Wall -Werror -pedantic -std=gnu11" CXXFLAGS="-Wall -Werror -std=gnu++11" +#OK# - env: NUT_MATRIX_TAG="gnu89-gcc-default-nowarn" BUILD_TYPE=default-all-errors CFLAGS="-std=gnu89" CXXFLAGS="-std=gnu++89" + - env: NUT_MATRIX_TAG="c89-gcc-default-warn" BUILD_TYPE=default-all-errors CFLAGS="-Wall -Werror -pedantic -std=c89" CXXFLAGS="-Wall -Werror -std=c++89" + - env: NUT_MATRIX_TAG="gnu89-gcc-default-warn" BUILD_TYPE=default-all-errors CFLAGS="-Wall -Werror -pedantic -std=gnu89" CXXFLAGS="-Wall -Werror -std=gnu++89" +### macosx +#OK# - env: NUT_MATRIX_TAG="gnu99-clang-xcode10.2-nowarn" BUILD_TYPE=default-all-errors CFLAGS="-std=gnu99" CXXFLAGS="-std=gnu++99" CC=clang CXX=clang++ +#OK# - env: NUT_MATRIX_TAG="gnu17-clang-xcode10.2-nowarn" BUILD_TYPE=default-all-errors CFLAGS="-std=gnu17" CXXFLAGS="-std=gnu++17" CC=clang CXX=clang++ +#OK# - env: NUT_MATRIX_TAG="gnu99-clang-xcode7.3-nowarn" BUILD_TYPE=default-all-errors CFLAGS="-std=gnu99" CXXFLAGS="-std=gnu++99" CC=clang CXX=clang++ + - env: NUT_MATRIX_TAG="gnu99-clang-xcode10.2-warn" BUILD_TYPE=default-all-errors CFLAGS="-Wall -Werror -pedantic -std=gnu99" CXXFLAGS="-Wall -Werror -std=gnu++99" CC=clang CXX=clang++ + - env: NUT_MATRIX_TAG="gnu17-clang-xcode10.2-warn" BUILD_TYPE=default-all-errors CFLAGS="-Wall -Werror -pedantic -std=gnu17" CXXFLAGS="-Wall -Werror -std=gnu++17" CC=clang CXX=clang++ + - env: NUT_MATRIX_TAG="c99-clang-xcode10.2-nowarn" BUILD_TYPE=default-all-errors CFLAGS="-std=c99" CXXFLAGS="-std=c++99" CC=clang CXX=clang++ + - env: NUT_MATRIX_TAG="c99-clang-xcode10.2-warn" BUILD_TYPE=default-all-errors CFLAGS="-Wall -Werror -pedantic -std=c99" CXXFLAGS="-Wall -Werror -std=c++99" CC=clang CXX=clang++ + - env: NUT_MATRIX_TAG="c17-clang-xcode10.2-nowarn" BUILD_TYPE=default-all-errors CFLAGS="-std=c17" CXXFLAGS="-std=c++17" CC=clang CXX=clang++ + - env: NUT_MATRIX_TAG="c17-clang-xcode10.2-warn" BUILD_TYPE=default-all-errors CFLAGS="-Wall -Werror -pedantic -std=c17" CXXFLAGS="-Wall -Werror -std=c++17" CC=clang CXX=clang++ + - env: NUT_MATRIX_TAG="c17-clang-xcode7.3-warn" BUILD_TYPE=default-all-errors CFLAGS="-Wall -Werror -pedantic -std=c17" CXXFLAGS="-Wall -Werror -std=c++17" CC=clang CXX=clang++ +### windows + - env: NUT_MATRIX_TAG="gnu99-clang-win-nowarn" BUILD_TYPE=default-all-errors CPPFLAGS="-fms-extensions" CFLAGS="-std=gnu99" CXXFLAGS="-std=gnu++99" CC=clang CXX=clang++ + - env: NUT_MATRIX_TAG="c99-clang-win-nowarn" BUILD_TYPE=default-all-errors CPPFLAGS="-fms-extensions" CFLAGS="-std=c99" CXXFLAGS="-std=c++99" CC=clang CXX=clang++ + - env: NUT_MATRIX_TAG="c99-clang-win-warn" BUILD_TYPE=default-all-errors CPPFLAGS="-fms-extensions" CFLAGS="-Wall -Werror -pedantic -std=c99" CXXFLAGS="-Wall -Werror -std=c++99" CC=clang CXX=clang++ + - env: NUT_MATRIX_TAG="c20-clang-win-warn" BUILD_TYPE=default-all-errors CPPFLAGS="-fms-extensions" CFLAGS="-Wall -Werror -pedantic -std=c20" CXXFLAGS="-Wall -Werror -std=c++20" CC=clang CXX=clang++ + before_install: -- if [ $TRAVIS_OS_NAME == "osx" ] ; then brew update; brew install binutils asciidoc docbook-xsl ; XML_CATALOG_FILES=/usr/local/etc/xml/catalog ; export XML_CATALOG_FILES ; fi +- |- + if [ $TRAVIS_OS_NAME = "osx" ] ; then + [ -n "$HOMEBREW_NO_AUTO_UPDATE" ] || HOMEBREW_NO_AUTO_UPDATE="$CI_DEFAULT_HOMEBREW_NO_AUTO_UPDATE" + if [ "$HOMEBREW_NO_AUTO_UPDATE" = 1 ] ; then + echo "NOT CALLING 'brew update' as it takes too long and cleans up preinstalled env" + export HOMEBREW_NO_AUTO_UPDATE + else + unset HOMEBREW_NO_AUTO_UPDATE + brew update + fi + brew install binutils ccache gd + if [ "$BUILD_TYPE" = default-withdoc ] ; then + brew install asciidoc docbook-xsl + XML_CATALOG_FILES=/usr/local/etc/xml/catalog + export XML_CATALOG_FILES + fi + fi +- |- + if [[ $TRAVIS_OS_NAME == "windows" ]] ; then + if [[ ! -s C:/tools/bin/ccache.exe ]] ; then + mkdir -p C:/tools/bin/ + pushd C:/tools/bin/ || exit + wget https://github.com/ccache/ccache/releases/download/v3.7.12/ccache-3.7.12-windows-64.zip || exit + 7z e -y ccache-3.7.12-windows-64.zip || exit + rm -f ccache-3.7.12-windows-64.zip + popd + fi + export PATH=/C/tools/bin:$PATH + CI_TRACE=true + CI_TIME=false + export CI_TRACE CI_TIME + fi +- if [ -n "${NUT_MATRIX_TAG}" ] ; then export CFLAGS CXXFLAGS ; [ -z "$CC" ] || export CC ; [ -z "$CXX" ] || export CXX ; fi # Hand off to generated script for each BUILD_TYPE script: ./ci_build.sh diff --git a/INSTALL.nut b/INSTALL.nut index 202d1af05d..4708b56684 100644 --- a/INSTALL.nut +++ b/INSTALL.nut @@ -292,25 +292,47 @@ You can either install NUT as a binary package or as a port. Binary package ^^^^^^^^^^^^^^ -To install the main component, use the following command: +To install NUT as a package execute: - # pkg_add -r nut + # pkg install nut Port ^^^^ -The port is located under /usr/ports/sysutils/nut. -To install it, use the following command: +The port is located under +sysutils/nut+. +Use +make config+ to select configuration options, e.g. to build the optional CGI scripts. +To install it, use: - # cd /usr/ports/sysutils/nut/ && make install clean + # make install clean -You have to define WITH_NUT_CGI to build the optional CGI scripts. +USB UPS on FreeBSD +^^^^^^^^^^^^^^^^^^ + +For USB UPS devices the NUT package/port installs devd rules in +/usr/local/etc/devd/nut-usb.conf+ to set USB device permissions. 'devd' needs to be restarted for these rules to apply: + + # service devd restart + +(Re-)connect the device after restarting 'devd' and check that the USB device has the proper +permissions. Check the last entries of the system message buffer. You should +find an entry like + + # dmesg | tail + [...] + ugen0.2: at usbus0 + +The device file must be owned by group +uucp+ and must be group +read-/writable. In the example from above this would be + + # ls -Ll /dev/ugen0.2 + crw-rw---- 1 root uucp 0xa5 Mar 12 10:33 /dev/ugen0.2 + +If the permissions are not correct, verify that your device is registered in ++/usr/local/etc/devd/nut-usb.conf+. The vendor and product id can be found +using: -Optionally, you can also install the following ports: + # usbconfig -u 0 -a 2 dump_device_desc -- sysutils/nut-snmp, for the SNMP driver, -- sysutils/nut-usb, for the USB drivers, -- sysutils/nut-libupsclient, for the upsclient library. +where +-u+ specifies the USB bus number and +-a+ specifies the USB device index. You are now ready to configure NUT, and start testing and using it. diff --git a/Makefile.am b/Makefile.am index 7c35d2e124..0c3dbceb7c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5,7 +5,7 @@ ACLOCAL_AMFLAGS = -I m4 # subdirectories to build and distribute. The order matters, as # several subdirectories depend on stuff in "common" or tools being built first -SUBDIRS = include common clients conf data tools docs drivers \ +SUBDIRS = include common clients conf data docs drivers tools \ lib scripts server tests # COPYING is included automatically. @@ -57,6 +57,37 @@ spellcheck spellcheck-interactive: doc spellcheck-sortdict: cd $(srcdir)/docs && $(MAKE) $@ +# This target adds syntax-checking for committed shell script files, +# to avoid surprises and delays in finding fatal typos after packaging +### +### Note: currently, shellcheck target calls check-scripts-syntax +### so when both are invoked at once, in the end the check is only +### executed once. Later it is anticipated that shellcheck would +### be implemented by requiring, configuring and calling the tool +### named "shellcheck" for even more code inspection and details. +### Still, there remains value in also checking the script syntax +### by the very version of the shell interpreter that would run +### these scripts in production usage of the resulting packages. +### +check-scripts-syntax: + @echo 'NOTE: modern bash complains about scripts using backticks (warning not error), which we ignore in NUT codebase for portability reasons: `...` obsolete, use $$(...)' + for F in `git ls-files || find . -type f` ; do \ + case "`file "$$F"`" in \ + *"Bourne-Again shell script"*) ( set -x ; /bin/bash -n "$$F" ; ) ;; \ + *"POSIX shell script"*|*"shell script"*) ( set -x ; /bin/sh -n "$$F" ; ) ;; \ + esac || { RES=$$? ; echo "ERROR: Syntax check failed for script file: $$F" >&2 ; exit $$RES ; } ; \ + done + @echo 'SUCCESS: Shell scripts syntax is acceptable, no fatal issues were found' + +shellcheck-disclaimer: + @echo "===============================================================================" + @echo "NOTICE: 'make shellcheck' is currently an alias for 'make check-scripts-syntax'" + @echo "Later it may become a call to the real shellcheck tool (if available on the" + @echo "build system during the configure phase)" + @echo "===============================================================================" + +shellcheck: shellcheck-disclaimer check-scripts-syntax + # ---------------------------------------------------------------------- # Automatically generate the ChangeLog from Git logs: MAINTAINERCLEAN_FILES = ChangeLog @@ -121,7 +152,7 @@ install-dirs: @echo "Warning: 'make install-dirs' is deprecated." @echo "Use 'make installdirs' instead." @echo $(WARN) - make installdirs + $(MAKE) installdirs cgi build-cgi install-cgi install-cgi-dir install-cgi-bin \ install-cgi-man install-cgi-conf install-cgi-html: @echo "Error: 'make $@' no longer exists." @@ -137,23 +168,30 @@ snmp build-snmp install-snmp install-snmp-mgr install-snmp-man: @echo "Use './configure --with-snmp' instead." setver: @echo "Error: 'make setver' no longer exists." - @echo "Edit configure.in to set version number." + @echo "Edit configure.ac to set version number." package: - if test `uname -s` = "HP-UX"; then \ - cd scripts/HP-UX; \ - make package; \ - mv NUT_HPUX_package.depot NUT_HPUX_package@PACKAGE_VERSION@.depot; \ - elif test `uname -s` = "SunOS"; then \ - make; \ - rm -rf @prefix@; \ - make install; \ - cd scripts/Solaris; \ - make package; \ - make uninstall; \ - rm -rf @prefix@; \ - elif test `uname -s` = "AIX"; then \ - make dist; \ - cp scripts/Aix/nut-aix.spec /usr/src/packages/SPECS; \ - cp scripts/Aix/nut.init nut-@PACKAGE_VERSION@.tar.gz /usr/src/packages/SOURCES; \ - rpm -ba /usr/src/packages/SPECS/nut-aix.spec; \ - fi; + DESTDIR="$(abs_builddir)/_install_pkgprotodir" ; export DESTDIR; \ + rm -rf "$$DESTDIR"; \ + case "`uname -s`" in \ + "HP-UX") \ + ( cd scripts/HP-UX && \ + $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$DESTDIR" package && \ + mv NUT_HPUX_package.depot $(abs_top_builddir)/NUT_HPUX_package@PACKAGE_VERSION@.depot ) ;; \ + "SunOS") \ + $(MAKE) $(AM_MAKEFLAGS) && \ + $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$DESTDIR" install && \ + ( cd scripts/Solaris && \ + $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$DESTDIR" package ) && \ + $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$DESTDIR" uninstall && \ + rm -rf "$$DESTDIR" || \ + { echo "FAILED to produce SunOS packages, inspect '$$DESTDIR' for clues" >&2 ; exit 1; } ;; \ + "AIX") \ + if test -d /usr/src/packages/SPECS -a -w /usr/src/packages/SPECS ; then : ; else echo "Can not write to /usr/src/packages/SPECS" >&2 ; exit 1; fi ; \ + if test -d /usr/src/packages/SOURCES -a -w /usr/src/packages/SOURCES ; then : ; else echo "Can not write to /usr/src/packages/SOURCES" >&2 ; exit 1; fi ; \ + $(MAKE) $(AM_MAKEFLAGS) dist && \ + cp scripts/Aix/nut-aix.spec /usr/src/packages/SPECS && \ + cp scripts/Aix/nut.init nut-@PACKAGE_VERSION@.tar.gz /usr/src/packages/SOURCES && \ + rpm -ba /usr/src/packages/SPECS/nut-aix.spec && \ + mv /usr/src/packages/RPMS/nut*rpm $(abs_top_builddir)/ ;; \ + *) echo "Unsupported OS for 'make $@' (no recipe bound)" >&2; exit 1;; \ + esac diff --git a/README b/README index 247dc0a166..685bdbd9d4 100644 --- a/README +++ b/README @@ -120,8 +120,9 @@ The entry in `ups.conf` looks like this: driver = apcsmart port = /dev/ttyS1 -To start and stop drivers, use upsdrvctl. By default, it will start or -stop every UPS in the config file: +To start and stop drivers, use upsdrvctl of upsdrvsvcctl (installed on +operating systems with a service management framework supported by NUT). +By default, it will start or stop every UPS in the config file: /usr/local/ups/sbin/upsdrvctl start /usr/local/ups/sbin/upsdrvctl stop @@ -131,6 +132,17 @@ However, you can also just start or stop one by adding its name: /usr/local/ups/sbin/upsdrvctl start sparky /usr/local/ups/sbin/upsdrvctl stop sparky +On operating systems with a supported service management framework, +you might wrap your NUT drivers into individual services instances +with: + + /usr/local/ups/sbin/upsdrvsvcctl resync + +and then manage those service instances with commands like: + + /usr/local/ups/sbin/upsdrvsvcctl start sparky + /usr/local/ups/sbin/upsdrvsvcctl stop sparky + To find the driver name for your device, refer to the section below called "HARDWARE SUPPORT TABLE". diff --git a/builds/nut-driver-enumerator-test/ci_build.sh b/builds/nut-driver-enumerator-test/ci_build.sh new file mode 100755 index 0000000000..8d8ff05c54 --- /dev/null +++ b/builds/nut-driver-enumerator-test/ci_build.sh @@ -0,0 +1,33 @@ +#!/bin/sh + +# This is a CI test for nut-driver-enumerator-test.sh +# using chosen SHELL_PROGS (passed from caller envvars) + +cd "${REPO_DIR}/tests" || exit +BUILDDIR="`pwd`" +SRCDIR="`pwd`" +export BUILDDIR SRCDIR + +# Travis uses Ubuntu 14.04 which does not yet have systemd (16.04 should) +# The self-tests do not (yet) use the actual OS framework, so just let them run +if [ ! -x /bin/systemctl ] ; then + SERVICE_FRAMEWORK="selftest" + export SERVICE_FRAMEWORK +fi + +printf "\n=== `date -u` : Will test nut-driver-enumerator interpreted by: " +if [ -n "${SHELL_PROGS}" ] ; then + echo "$SHELL_PROGS" +else + echo "default system '/bin/sh'" +fi + +# Set this to enable verbose tracing +case "${CI_TRACE-}" in + [Yy][Ee][Ss]|[Oo][Nn]|[Tt][Rr][Uu][Ee]) + ls -la + DEBUG=trace ; export DEBUG + ;; +esac + +$CI_TIME ./nut-driver-enumerator-test.sh diff --git a/ci_build.sh b/ci_build.sh index dd7b3f9ab0..1f0de7d4f5 100755 --- a/ci_build.sh +++ b/ci_build.sh @@ -24,8 +24,9 @@ case "$CI_TRACE" in set -x ;; esac +echo "Processing BUILD_TYPE='${BUILD_TYPE}' ..." case "$BUILD_TYPE" in -default|default-alldrv|default-spellcheck|default-nodoc|default-withdoc|"default-tgt:"*) +default|default-alldrv|default-all-errors|default-spellcheck|default-shellcheck|default-nodoc|default-withdoc|"default-tgt:"*) LANG=C LC_ALL=C export LANG LC_ALL @@ -40,7 +41,21 @@ default|default-alldrv|default-spellcheck|default-nodoc|default-withdoc|"default BUILD_PREFIX=$PWD/tmp INST_PREFIX=$PWD/.inst - PATH="`echo "$PATH" | sed -e 's,^/usr/lib/ccache/?:,,' -e 's,:/usr/lib/ccache/?:,,' -e 's,:/usr/lib/ccache/?$,,' -e 's,^/usr/lib/ccache/?$,,'2`" + echo "PATH='$PATH' before possibly applying CCACHE into the mix" + ( echo "$PATH" | grep ccache ) >/dev/null && echo "WARNING: ccache is already in PATH" + if [ -n "$CC" ]; then + echo "CC='$CC' before possibly applying CCACHE into the mix" + $CC --version $CFLAGS || \ + $CC --version || true + fi + + if [ -n "$CXX" ]; then + echo "CXX='$CXX' before possibly applying CCACHE into the mix" + $CXX --version $CXXFLAGS || \ + $CXX --version || true + fi + + PATH="`echo "$PATH" | sed -e 's,^/usr/lib/ccache/?:,,' -e 's,:/usr/lib/ccache/?:,,' -e 's,:/usr/lib/ccache/?$,,' -e 's,^/usr/lib/ccache/?$,,'`" CCACHE_PATH="$PATH" CCACHE_DIR="${HOME}/.ccache" export CCACHE_PATH CCACHE_DIR PATH @@ -48,12 +63,12 @@ default|default-alldrv|default-spellcheck|default-nodoc|default-withdoc|"default if which ccache && ls -la /usr/lib/ccache ; then HAVE_CCACHE=yes fi + mkdir -p "${CCACHE_DIR}" || HAVE_CCACHE=no if [ "$HAVE_CCACHE" = yes ] && [ -d "$CCACHE_DIR" ]; then echo "CCache stats before build:" ccache -s || true fi - mkdir -p "${HOME}/.ccache" CONFIG_OPTS=() COMMON_CFLAGS="" @@ -65,11 +80,18 @@ default|default-alldrv|default-spellcheck|default-nodoc|default-withdoc|"default if [ -n "$1" ] && "$1" --version 2>&1 | grep 'Free Software Foundation' > /dev/null ; then true ; else false ; fi } + is_clang() { + if [ -n "$1" ] && "$1" --version 2>&1 | grep 'clang version' > /dev/null ; then true ; else false ; fi + } + COMPILER_FAMILY="" if [ -n "$CC" -a -n "$CXX" ]; then if is_gnucc "$CC" && is_gnucc "$CXX" ; then COMPILER_FAMILY="GCC" export CC CXX + elif is_clang "$CC" && is_clang "$CXX" ; then + COMPILER_FAMILY="CLANG" + export CC CXX fi else if is_gnucc "gcc" && is_gnucc "g++" ; then @@ -83,6 +105,17 @@ default|default-alldrv|default-spellcheck|default-nodoc|default-withdoc|"default [ -n "$CC" ] || CC=cc [ -n "$CXX" ] || CXX=c++ export CC CXX + elif is_clang "clang" && is_clang "clang++" ; then + # Autoconf would pick this by default + COMPILER_FAMILY="CLANG" + [ -n "$CC" ] || CC=clang + [ -n "$CXX" ] || CXX=clang++ + export CC CXX + elif is_clang "cc" && is_clang "c++" ; then + COMPILER_FAMILY="CLANG" + [ -n "$CC" ] || CC=cc + [ -n "$CXX" ] || CXX=c++ + export CC CXX fi fi @@ -94,9 +127,12 @@ default|default-alldrv|default-spellcheck|default-nodoc|default-withdoc|"default fi fi - CONFIG_OPTS+=("CFLAGS=-I${BUILD_PREFIX}/include") - CONFIG_OPTS+=("CPPFLAGS=-I${BUILD_PREFIX}/include") - CONFIG_OPTS+=("CXXFLAGS=-I${BUILD_PREFIX}/include") + # Note: Potentially there can be spaces in entries for multiple + # *FLAGS here; this should be okay as long as entry expands to + # one token when calling shell (may not be the case for distcheck) + CONFIG_OPTS+=("CFLAGS=-I${BUILD_PREFIX}/include ${CFLAGS}") + CONFIG_OPTS+=("CPPFLAGS=-I${BUILD_PREFIX}/include ${CPPFLAGS}") + CONFIG_OPTS+=("CXXFLAGS=-I${BUILD_PREFIX}/include ${CXXFLAGS}") CONFIG_OPTS+=("LDFLAGS=-L${BUILD_PREFIX}/lib") CONFIG_OPTS+=("PKG_CONFIG_PATH=${BUILD_PREFIX}/lib/pkgconfig") CONFIG_OPTS+=("--prefix=${BUILD_PREFIX}") @@ -111,15 +147,30 @@ default|default-alldrv|default-spellcheck|default-nodoc|default-withdoc|"default CONFIG_OPTS+=("--with-doc=no") DO_DISTCHECK=no ;; - "default-spellcheck") + "default-spellcheck"|"default-shellcheck") CONFIG_OPTS+=("--with-all=no") CONFIG_OPTS+=("--with-libltdl=no") CONFIG_OPTS+=("--with-doc=man=skip") + #TBD# CONFIG_OPTS+=("--with-shellcheck=yes") DO_DISTCHECK=no ;; "default-withdoc") CONFIG_OPTS+=("--with-doc=yes") ;; + "default-all-errors") + # Do not build the docs as we are interested in binary code + CONFIG_OPTS+=("--with-doc=skip") + # Enable as many binaries to build as current worker setup allows + CONFIG_OPTS+=("--with-all=auto") + if [[ "$TRAVIS_OS_NAME" != "windows" ]] ; then + # Currently --with-all implies this, but better be sure to + # really build everything we can to be certain it builds: + CONFIG_OPTS+=("--with-cgi=yes") + else + # No prereq dll and headers on win so far + CONFIG_OPTS+=("--with-cgi=auto") + fi + ;; "default-alldrv") # Do not build the docs and make possible a distcheck below CONFIG_OPTS+=("--with-doc=skip") @@ -131,10 +182,11 @@ default|default-alldrv|default-spellcheck|default-nodoc|default-withdoc|"default ;; esac - if [ "$HAVE_CCACHE" = yes ] && [ "${COMPILER_FAMILY}" = GCC ]; then + if [ "$HAVE_CCACHE" = yes ] && [ "${COMPILER_FAMILY}" = GCC -o "${COMPILER_FAMILY}" = CLANG ]; then PATH="/usr/lib/ccache:$PATH" export PATH - if [ -n "$CC" ] && [ -x "/usr/lib/ccache/`basename "$CC"`" ]; then + if [ -n "$CC" ]; then + if [ -x "/usr/lib/ccache/`basename "$CC"`" ]; then case "$CC" in *ccache*) ;; */*) DIR_CC="`dirname "$CC"`" && [ -n "$DIR_CC" ] && DIR_CC="`cd "$DIR_CC" && pwd `" && [ -n "$DIR_CC" ] && [ -d "$DIR_CC" ] || DIR_CC="" @@ -145,10 +197,12 @@ default|default-alldrv|default-spellcheck|default-nodoc|default-withdoc|"default ;; esac CC="/usr/lib/ccache/`basename "$CC"`" - else - : # CC="ccache $CC" + else + CC="ccache $CC" + fi fi - if [ -n "$CXX" ] && [ -x "/usr/lib/ccache/`basename "$CXX"`" ]; then + if [ -n "$CXX" ]; then + if [ -x "/usr/lib/ccache/`basename "$CXX"`" ]; then case "$CXX" in *ccache*) ;; */*) DIR_CXX="`dirname "$CXX"`" && [ -n "$DIR_CXX" ] && DIR_CXX="`cd "$DIR_CXX" && pwd `" && [ -n "$DIR_CXX" ] && [ -d "$DIR_CXX" ] || DIR_CXX="" @@ -159,8 +213,9 @@ default|default-alldrv|default-spellcheck|default-nodoc|default-withdoc|"default ;; esac CXX="/usr/lib/ccache/`basename "$CXX"`" - else - : # CXX="ccache $CXX" + else + CXX="ccache $CXX" + fi fi if [ -n "$CPP" ] && [ -x "/usr/lib/ccache/`basename "$CPP"`" ]; then case "$CPP" in @@ -177,6 +232,9 @@ default|default-alldrv|default-spellcheck|default-nodoc|default-withdoc|"default : # CPP="ccache $CPP" fi + # Note: Potentially there can be spaces in entries for multiword + # "ccache gcc" here; this should be okay as long as entry expands to + # one token when calling shell (may not be the case for distcheck) CONFIG_OPTS+=("CC=${CC}") CONFIG_OPTS+=("CXX=${CXX}") CONFIG_OPTS+=("CPP=${CPP}") @@ -184,13 +242,30 @@ default|default-alldrv|default-spellcheck|default-nodoc|default-withdoc|"default # Build and check this project; note that zprojects always have an autogen.sh [ -z "$CI_TIME" ] || echo "`date`: Starting build of currently tested project..." - CCACHE_BASEDIR=${PWD} + CCACHE_BASEDIR="${PWD}" export CCACHE_BASEDIR - $CI_TIME ./autogen.sh 2> /dev/null + + # Note: modern auto(re)conf requires pkg-config to generate the configure + # script, so to stage the situation of building without one (as if on an + # older system) we have to remove it when we already have the script. + # This matches the use-case of distro-building from release tarballs that + # include all needed pre-generated files to rely less on OS facilities. + if [ "$TRAVIS_OS_NAME" = "windows" ] ; then + $CI_TIME ./autogen.sh || true + else + $CI_TIME ./autogen.sh 2>/dev/null + fi + if [ "$NO_PKG_CONFIG" == "true" ] && [ "$TRAVIS_OS_NAME" = "linux" ] ; then + echo "NO_PKG_CONFIG==true : BUTCHER pkg-config for this test case" >&2 + sudo dpkg -r --force all pkg-config + fi + + echo "=== CONFIGURING NUT: ./configure ${CONFIG_OPTS[*]}" + echo "=== CC='$CC' CXX='$CXX' CPP='$CPP'" $CI_TIME ./configure "${CONFIG_OPTS[@]}" case "$BUILD_TYPE" in - default-tgt:*) # Hook for matrix of custom distchecks primarily + "default-tgt:"*) # Hook for matrix of custom distchecks primarily BUILD_TGT="`echo "$BUILD_TYPE" | sed 's,^default-tgt:,,'`" echo "`date`: Starting the sequential build attempt for singular target $BUILD_TGT..." export DISTCHECK_CONFIGURE_FLAGS="${CONFIG_OPTS[@]}" @@ -216,6 +291,26 @@ default|default-alldrv|default-spellcheck|default-nodoc|default-withdoc|"default ( $CI_TIME make VERBOSE=1 SPELLCHECK_ERROR_FATAL=yes spellcheck ) exit 0 ;; + "default-shellcheck") + [ -z "$CI_TIME" ] || echo "`date`: Trying to check shell script syntax validity of the currently tested project..." + ### Note: currently, shellcheck target calls check-scripts-syntax + ### so when both are invoked at once, in the end the check is only + ### executed once. Later it is anticipated that shellcheck would + ### be implemented by requiring, configuring and calling the tool + ### named "shellcheck" for even more code inspection and details. + ### Still, there remains value in also checking the script syntax + ### by the very version of the shell interpreter that would run + ### these scripts in production usage of the resulting packages. + ( $CI_TIME make VERBOSE=1 shellcheck check-scripts-syntax ) + exit $? + ;; + "default-all-errors") + ( echo "`date`: Starting the parallel build attempt (quietly to build what we can)..."; \ + $CI_TIME make VERBOSE=0 -k -j8 all >/dev/null 2>&1 ; ) || \ + ( echo "`date`: Starting the sequential build attempt (to list remaining files with errors considered fatal for this build configuration)..."; \ + $CI_TIME make VERBOSE=1 all -k ) + exit $? + ;; esac ( echo "`date`: Starting the parallel build attempt..."; \ @@ -254,6 +349,12 @@ default|default-alldrv|default-spellcheck|default-nodoc|default-withdoc|"default bindings) pushd "./bindings/${BINDING}" && ./ci_build.sh ;; +"") + echo "ERROR: No BUILD_TYPE was specified, doing a minimal default ritual" + ./autogen.sh + ./configure + make all && make check + ;; *) pushd "./builds/${BUILD_TYPE}" && REPO_DIR="$(dirs -l +1)" ./ci_build.sh ;; diff --git a/clients/Makefile.am b/clients/Makefile.am index 5c7abf968f..aba351a3f7 100644 --- a/clients/Makefile.am +++ b/clients/Makefile.am @@ -1,4 +1,5 @@ # Network UPS Tools: clients +EXTRA_DIST = # by default, link programs in this directory with libcommon.a LDADD = ../common/libcommon.la libupsclient.la $(NETLIBS) @@ -20,7 +21,10 @@ endif bin_PROGRAMS = upsc upslog upsrw upscmd dist_bin_SCRIPTS = upssched-cmd sbin_PROGRAMS = upsmon upssched -lib_LTLIBRARIES = libupsclient.la libnutclient.la +lib_LTLIBRARIES = libupsclient.la +if HAVE_CXX11 + lib_LTLIBRARIES += libnutclient.la +endif if WITH_DEV include_HEADERS = upsclient.h ../include/parseconf.h nutclient.h endif @@ -51,10 +55,18 @@ if WITH_SSL libupsclient_la_LIBADD += $(LIBSSL_LIBS) endif -# libupsclient version information +# Below we set API versions of public libraries # http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html -libupsclient_la_LDFLAGS = -version-info 4:0:0 +# Note that changes here may have to be reflected in packaging (the shared +# object .so names would differ) -libnutclient_la_SOURCES = nutclient.h nutclient.cpp -libnutclient_la_LDFLAGS = -version-info 0:0:0 +# libupsclient version information +libupsclient_la_LDFLAGS = -version-info 5:0:0 -export-symbols-regex ^upscli_ +if HAVE_CXX11 +# libnutclient version information and build +libnutclient_la_SOURCES = nutclient.h nutclient.cpp +libnutclient_la_LDFLAGS = -version-info 1:0:0 +else +EXTRA_DIST += nutclient.h nutclient.cpp +endif diff --git a/clients/nutclient.cpp b/clients/nutclient.cpp index 3d4b6dac90..eb2be2a280 100644 --- a/clients/nutclient.cpp +++ b/clients/nutclient.cpp @@ -97,18 +97,18 @@ class Socket Socket(); ~Socket(); - void connect(const std::string& host, int port)throw(nut::IOException); + void connect(const std::string& host, int port); void disconnect(); bool isConnected()const; void setTimeout(long timeout); bool hasTimeout()const{return _tv.tv_sec>=0;} - size_t read(void* buf, size_t sz)throw(nut::IOException); - size_t write(const void* buf, size_t sz)throw(nut::IOException); + size_t read(void* buf, size_t sz); + size_t write(const void* buf, size_t sz); - std::string read()throw(nut::IOException); - void write(const std::string& str)throw(nut::IOException); + std::string read(); + void write(const std::string& str); private: @@ -135,7 +135,7 @@ void Socket::setTimeout(long timeout) _tv.tv_sec = timeout; } -void Socket::connect(const std::string& host, int port)throw(nut::IOException) +void Socket::connect(const std::string& host, int port) { int sock_fd; struct addrinfo hints, *res, *ai; @@ -304,7 +304,7 @@ bool Socket::isConnected()const return _sock!=INVALID_SOCKET; } -size_t Socket::read(void* buf, size_t sz)throw(nut::IOException) +size_t Socket::read(void* buf, size_t sz) { if(!isConnected()) { @@ -331,7 +331,7 @@ size_t Socket::read(void* buf, size_t sz)throw(nut::IOException) return (size_t) res; } -size_t Socket::write(const void* buf, size_t sz)throw(nut::IOException) +size_t Socket::write(const void* buf, size_t sz) { if(!isConnected()) { @@ -358,7 +358,7 @@ size_t Socket::write(const void* buf, size_t sz)throw(nut::IOException) return (size_t) res; } -std::string Socket::read()throw(nut::IOException) +std::string Socket::read() { std::string res; char buff[256]; @@ -389,7 +389,7 @@ std::string Socket::read()throw(nut::IOException) } } -void Socket::write(const std::string& str)throw(nut::IOException) +void Socket::write(const std::string& str) { // write(str.c_str(), str.size()); // write("\n", 1); @@ -406,6 +406,8 @@ void Socket::write(const std::string& str)throw(nut::IOException) * */ +const Feature Client::TRACKING = "TRACKING"; + Client::Client() { } @@ -414,13 +416,13 @@ Client::~Client() { } -bool Client::hasDevice(const std::string& dev)throw(NutException) +bool Client::hasDevice(const std::string& dev) { std::set devs = getDeviceNames(); return devs.find(dev) != devs.end(); } -Device Client::getDevice(const std::string& name)throw(NutException) +Device Client::getDevice(const std::string& name) { if(hasDevice(name)) return Device(this, name); @@ -428,7 +430,7 @@ Device Client::getDevice(const std::string& name)throw(NutException) return Device(NULL, ""); } -std::set Client::getDevices()throw(NutException) +std::set Client::getDevices() { std::set res; @@ -441,13 +443,13 @@ std::set Client::getDevices()throw(NutException) return res; } -bool Client::hasDeviceVariable(const std::string& dev, const std::string& name)throw(NutException) +bool Client::hasDeviceVariable(const std::string& dev, const std::string& name) { std::set names = getDeviceVariableNames(dev); return names.find(name) != names.end(); } -std::map > Client::getDeviceVariableValues(const std::string& dev)throw(NutException) +std::map > Client::getDeviceVariableValues(const std::string& dev) { std::map > res; @@ -461,12 +463,37 @@ std::map > Client::getDeviceVariableValues( return res; } -bool Client::hasDeviceCommand(const std::string& dev, const std::string& name)throw(NutException) +std::map > > Client::getDevicesVariableValues(const std::set& devs) +{ + std::map > > res; + + for(std::set::const_iterator it=devs.cbegin(); it!=devs.cend(); ++it) + { + res[*it] = getDeviceVariableValues(*it); + } + + return res; +} + +bool Client::hasDeviceCommand(const std::string& dev, const std::string& name) { std::set names = getDeviceCommandNames(dev); return names.find(name) != names.end(); } +bool Client::hasFeature(const Feature& feature) +{ + try + { + // If feature is known, querying it won't throw an exception. + isFeatureEnabled(feature); + return true; + } + catch(...) + { + return false; + } +} /* * @@ -483,7 +510,7 @@ _socket(new internal::Socket) // Do not connect now } -TcpClient::TcpClient(const std::string& host, int port)throw(IOException): +TcpClient::TcpClient(const std::string& host, int port): Client(), _socket(new internal::Socket) { @@ -495,14 +522,14 @@ TcpClient::~TcpClient() delete _socket; } -void TcpClient::connect(const std::string& host, int port)throw(IOException) +void TcpClient::connect(const std::string& host, int port) { _host = host; _port = port; connect(); } -void TcpClient::connect()throw(nut::IOException) +void TcpClient::connect() { _socket->connect(_host, _port); } @@ -538,19 +565,18 @@ long TcpClient::getTimeout()const } void TcpClient::authenticate(const std::string& user, const std::string& passwd) - throw(NutException) { detectError(sendQuery("USERNAME " + user)); detectError(sendQuery("PASSWORD " + passwd)); } -void TcpClient::logout()throw(NutException) +void TcpClient::logout() { detectError(sendQuery("LOGOUT")); _socket->disconnect(); } -Device TcpClient::getDevice(const std::string& name)throw(NutException) +Device TcpClient::getDevice(const std::string& name) { try { @@ -566,7 +592,7 @@ Device TcpClient::getDevice(const std::string& name)throw(NutException) return Device(this, name); } -std::set TcpClient::getDeviceNames()throw(NutException) +std::set TcpClient::getDeviceNames() { std::set res; @@ -582,12 +608,12 @@ std::set TcpClient::getDeviceNames()throw(NutException) return res; } -std::string TcpClient::getDeviceDescription(const std::string& name)throw(NutException) +std::string TcpClient::getDeviceDescription(const std::string& name) { return get("UPSDESC", name)[0]; } -std::set TcpClient::getDeviceVariableNames(const std::string& dev)throw(NutException) +std::set TcpClient::getDeviceVariableNames(const std::string& dev) { std::set set; @@ -600,7 +626,7 @@ std::set TcpClient::getDeviceVariableNames(const std::string& dev)t return set; } -std::set TcpClient::getDeviceRWVariableNames(const std::string& dev)throw(NutException) +std::set TcpClient::getDeviceRWVariableNames(const std::string& dev) { std::set set; @@ -613,17 +639,17 @@ std::set TcpClient::getDeviceRWVariableNames(const std::string& dev return set; } -std::string TcpClient::getDeviceVariableDescription(const std::string& dev, const std::string& name)throw(NutException) +std::string TcpClient::getDeviceVariableDescription(const std::string& dev, const std::string& name) { return get("DESC", dev + " " + name)[0]; } -std::vector TcpClient::getDeviceVariableValue(const std::string& dev, const std::string& name)throw(NutException) +std::vector TcpClient::getDeviceVariableValue(const std::string& dev, const std::string& name) { return get("VAR", dev + " " + name); } -std::map > TcpClient::getDeviceVariableValues(const std::string& dev)throw(NutException) +std::map > TcpClient::getDeviceVariableValues(const std::string& dev) { std::map > map; @@ -640,23 +666,72 @@ std::map > TcpClient::getDeviceVariableValu return map; } -void TcpClient::setDeviceVariable(const std::string& dev, const std::string& name, const std::string& value)throw(NutException) +std::map > > TcpClient::getDevicesVariableValues(const std::set& devs) +{ + std::map > > map; + + if (devs.empty()) + { + // This request might come from processing the empty valid + // response of an upsd server which was allowed to start + // with no device sections in its ups.conf + return map; + } + + std::vector queries; + for (std::set::const_iterator it=devs.cbegin(); it!=devs.cend(); ++it) + { + queries.push_back("LIST VAR " + *it); + } + sendAsyncQueries(queries); + + for (std::set::const_iterator it=devs.cbegin(); it!=devs.cend(); ++it) + { + try + { + std::map > map2; + std::vector > res = parseList("VAR " + *it); + for (std::vector >::iterator it2=res.begin(); it2!=res.end(); ++it2) + { + std::vector& vals = *it2; + std::string var = vals[0]; + vals.erase(vals.begin()), + map2[var] = vals; + } + map[*it] = map2; + } + catch (NutException&) + { + // We sent a bunch of queries, we need to process them all to clear up the backlog. + } + } + + if (map.empty()) + { + // We may fail on some devices, but not on ALL devices. + throw NutException("Invalid device"); + } + + return map; +} + +TrackingID TcpClient::setDeviceVariable(const std::string& dev, const std::string& name, const std::string& value) { std::string query = "SET VAR " + dev + " " + name + " " + escape(value); - detectError(sendQuery(query)); + return sendTrackingQuery(query); } -void TcpClient::setDeviceVariable(const std::string& dev, const std::string& name, const std::vector& values)throw(NutException) +TrackingID TcpClient::setDeviceVariable(const std::string& dev, const std::string& name, const std::vector& values) { std::string query = "SET VAR " + dev + " " + name; for(size_t n=0; n TcpClient::getDeviceCommandNames(const std::string& dev)throw(NutException) +std::set TcpClient::getDeviceCommandNames(const std::string& dev) { std::set cmds; @@ -669,40 +744,94 @@ std::set TcpClient::getDeviceCommandNames(const std::string& dev)th return cmds; } -std::string TcpClient::getDeviceCommandDescription(const std::string& dev, const std::string& name)throw(NutException) +std::string TcpClient::getDeviceCommandDescription(const std::string& dev, const std::string& name) { return get("CMDDESC", dev + " " + name)[0]; } -void TcpClient::executeDeviceCommand(const std::string& dev, const std::string& name)throw(NutException) +TrackingID TcpClient::executeDeviceCommand(const std::string& dev, const std::string& name, const std::string& param) { - detectError(sendQuery("INSTCMD " + dev + " " + name)); + return sendTrackingQuery("INSTCMD " + dev + " " + name + " " + param); } -void TcpClient::deviceLogin(const std::string& dev)throw(NutException) +void TcpClient::deviceLogin(const std::string& dev) { detectError(sendQuery("LOGIN " + dev)); } -void TcpClient::deviceMaster(const std::string& dev)throw(NutException) +void TcpClient::deviceMaster(const std::string& dev) { detectError(sendQuery("MASTER " + dev)); } -void TcpClient::deviceForcedShutdown(const std::string& dev)throw(NutException) +void TcpClient::deviceForcedShutdown(const std::string& dev) { detectError(sendQuery("FSD " + dev)); } -int TcpClient::deviceGetNumLogins(const std::string& dev)throw(NutException) +int TcpClient::deviceGetNumLogins(const std::string& dev) { std::string num = get("NUMLOGINS", dev)[0]; return atoi(num.c_str()); } +TrackingResult TcpClient::getTrackingResult(const TrackingID& id) +{ + if (id.empty()) + { + return TrackingResult::SUCCESS; + } + + std::string result = sendQuery("GET TRACKING " + id); + + if (result == "PENDING") + { + return TrackingResult::PENDING; + } + else if (result == "SUCCESS") + { + return TrackingResult::SUCCESS; + } + else if (result == "ERR UNKNOWN") + { + return TrackingResult::UNKNOWN; + } + else if (result == "ERR INVALID-ARGUMENT") + { + return TrackingResult::INVALID_ARGUMENT; + } + else + { + return TrackingResult::FAILURE; + } +} + +bool TcpClient::isFeatureEnabled(const Feature& feature) +{ + std::string result = sendQuery("GET " + feature); + detectError(result); + + if (result == "ON") + { + return true; + } + else if (result == "OFF") + { + return false; + } + else + { + throw NutException("Unknown feature result " + result); + } +} +void TcpClient::setFeature(const Feature& feature, bool status) +{ + std::string result = sendQuery("SET " + feature + " " + (status ? "ON" : "OFF")); + detectError(result); +} std::vector TcpClient::get - (const std::string& subcmd, const std::string& params) throw(NutException) + (const std::string& subcmd, const std::string& params) { std::string req = subcmd; if(!params.empty()) @@ -720,14 +849,23 @@ std::vector TcpClient::get } std::vector > TcpClient::list - (const std::string& subcmd, const std::string& params) throw(NutException) + (const std::string& subcmd, const std::string& params) { std::string req = subcmd; if(!params.empty()) { req += " " + params; } - std::string res = sendQuery("LIST " + req); + std::vector query; + query.push_back("LIST " + req); + sendAsyncQueries(query); + return parseList(req); +} + +std::vector > TcpClient::parseList + (const std::string& req) +{ + std::string res = _socket->read(); detectError(res); if(res != ("BEGIN LIST " + req)) { @@ -754,13 +892,21 @@ std::vector > TcpClient::list } } -std::string TcpClient::sendQuery(const std::string& req)throw(IOException) +std::string TcpClient::sendQuery(const std::string& req) { _socket->write(req); return _socket->read(); } -void TcpClient::detectError(const std::string& req)throw(NutException) +void TcpClient::sendAsyncQueries(const std::vector& req) +{ + for (std::vector::const_iterator it = req.cbegin(); it != req.cend(); it++) + { + _socket->write(*it); + } +} + +void TcpClient::detectError(const std::string& req) { if(req.substr(0,3)=="ERR") { @@ -898,6 +1044,26 @@ std::string TcpClient::escape(const std::string& str) return res; } +TrackingID TcpClient::sendTrackingQuery(const std::string& req) +{ + std::string reply = sendQuery(req); + detectError(reply); + std::vector res = explode(reply); + + if (res.size() == 1 && res[0] == "OK") + { + return TrackingID(""); + } + else if (res.size() == 3 && res[0] == "OK" && res[1] == "TRACKING") + { + return TrackingID(res[2]); + } + else + { + throw NutException("Unknown query result"); + } +} + /* * * Device implementation @@ -960,46 +1126,43 @@ bool Device::operator<(const Device& dev)const return getName()getDeviceDescription(getName()); } std::vector Device::getVariableValue(const std::string& name) - throw(NutException) { if (!isOk()) throw NutException("Invalid device"); return getClient()->getDeviceVariableValue(getName(), name); } std::map > Device::getVariableValues() - throw(NutException) { if (!isOk()) throw NutException("Invalid device"); return getClient()->getDeviceVariableValues(getName()); } -std::set Device::getVariableNames()throw(NutException) +std::set Device::getVariableNames() { if (!isOk()) throw NutException("Invalid device"); return getClient()->getDeviceVariableNames(getName()); } -std::set Device::getRWVariableNames()throw(NutException) +std::set Device::getRWVariableNames() { if (!isOk()) throw NutException("Invalid device"); return getClient()->getDeviceRWVariableNames(getName()); } -void Device::setVariable(const std::string& name, const std::string& value)throw(NutException) +void Device::setVariable(const std::string& name, const std::string& value) { if (!isOk()) throw NutException("Invalid device"); getClient()->setDeviceVariable(getName(), name, value); } void Device::setVariable(const std::string& name, const std::vector& values) - throw(NutException) { if (!isOk()) throw NutException("Invalid device"); getClient()->setDeviceVariable(getName(), name, values); @@ -1007,7 +1170,7 @@ void Device::setVariable(const std::string& name, const std::vector -Variable Device::getVariable(const std::string& name)throw(NutException) +Variable Device::getVariable(const std::string& name) { if (!isOk()) throw NutException("Invalid device"); if(getClient()->hasDeviceVariable(getName(), name)) @@ -1016,7 +1179,7 @@ Variable Device::getVariable(const std::string& name)throw(NutException) return Variable(NULL, ""); } -std::set Device::getVariables()throw(NutException) +std::set Device::getVariables() { std::set set; if (!isOk()) throw NutException("Invalid device"); @@ -1030,7 +1193,7 @@ std::set Device::getVariables()throw(NutException) return set; } -std::set Device::getRWVariables()throw(NutException) +std::set Device::getRWVariables() { std::set set; if (!isOk()) throw NutException("Invalid device"); @@ -1044,13 +1207,13 @@ std::set Device::getRWVariables()throw(NutException) return set; } -std::set Device::getCommandNames()throw(NutException) +std::set Device::getCommandNames() { if (!isOk()) throw NutException("Invalid device"); return getClient()->getDeviceCommandNames(getName()); } -std::set Device::getCommands()throw(NutException) +std::set Device::getCommands() { std::set cmds; @@ -1063,7 +1226,7 @@ std::set Device::getCommands()throw(NutException) return cmds; } -Command Device::getCommand(const std::string& name)throw(NutException) +Command Device::getCommand(const std::string& name) { if (!isOk()) throw NutException("Invalid device"); if(getClient()->hasDeviceCommand(getName(), name)) @@ -1072,29 +1235,29 @@ Command Device::getCommand(const std::string& name)throw(NutException) return Command(NULL, ""); } -void Device::executeCommand(const std::string& name)throw(NutException) +TrackingID Device::executeCommand(const std::string& name, const std::string& param) { if (!isOk()) throw NutException("Invalid device"); - getClient()->executeDeviceCommand(getName(), name); + return getClient()->executeDeviceCommand(getName(), name, param); } -void Device::login()throw(NutException) +void Device::login() { if (!isOk()) throw NutException("Invalid device"); getClient()->deviceLogin(getName()); } -void Device::master()throw(NutException) +void Device::master() { if (!isOk()) throw NutException("Invalid device"); getClient()->deviceMaster(getName()); } -void Device::forcedShutdown()throw(NutException) +void Device::forcedShutdown() { } -int Device::getNumLogins()throw(NutException) +int Device::getNumLogins() { if (!isOk()) throw NutException("Invalid device"); return getClient()->deviceGetNumLogins(getName()); @@ -1163,22 +1326,22 @@ bool Variable::operator<(const Variable& var)const return getName() Variable::getValue()throw(NutException) +std::vector Variable::getValue() { return getDevice()->getClient()->getDeviceVariableValue(getDevice()->getName(), getName()); } -std::string Variable::getDescription()throw(NutException) +std::string Variable::getDescription() { return getDevice()->getClient()->getDeviceVariableDescription(getDevice()->getName(), getName()); } -void Variable::setValue(const std::string& value)throw(NutException) +void Variable::setValue(const std::string& value) { getDevice()->setVariable(getName(), value); } -void Variable::setValues(const std::vector& values)throw(NutException) +void Variable::setValues(const std::vector& values) { getDevice()->setVariable(getName(), values); } @@ -1247,14 +1410,14 @@ bool Command::operator<(const Command& cmd)const return getName()getClient()->getDeviceCommandDescription(getDevice()->getName(), getName()); } -void Command::execute()throw(NutException) +void Command::execute(const std::string& param) { - getDevice()->executeCommand(getName()); + getDevice()->executeCommand(getName(), param); } } /* namespace nut */ @@ -1734,7 +1897,7 @@ char* nutclient_get_device_command_description(NUTCLIENT_t client, const char* d return NULL; } -void nutclient_execute_device_command(NUTCLIENT_t client, const char* dev, const char* cmd) +void nutclient_execute_device_command(NUTCLIENT_t client, const char* dev, const char* cmd, const char* param) { if(client) { @@ -1743,7 +1906,7 @@ void nutclient_execute_device_command(NUTCLIENT_t client, const char* dev, const { try { - cl->executeDeviceCommand(dev, cmd); + cl->executeDeviceCommand(dev, cmd, param); } catch(...){} } diff --git a/clients/nutclient.h b/clients/nutclient.h index 0eea1ccd53..4abf8a47ab 100644 --- a/clients/nutclient.h +++ b/clients/nutclient.h @@ -51,9 +51,9 @@ class NutException : public std::exception { public: NutException(const std::string& msg):_msg(msg){} - virtual ~NutException() throw() {} - virtual const char * what() const throw() {return this->_msg.c_str();} - virtual std::string str() const throw() {return this->_msg;} + virtual ~NutException() {} + virtual const char * what() const noexcept {return this->_msg.c_str();} + virtual std::string str() const noexcept {return this->_msg;} private: std::string _msg; }; @@ -65,7 +65,7 @@ class SystemException : public NutException { public: SystemException(); - virtual ~SystemException() throw() {} + virtual ~SystemException() {} private: static std::string err(); }; @@ -78,7 +78,7 @@ class IOException : public NutException { public: IOException(const std::string& msg):NutException(msg){} - virtual ~IOException() throw() {} + virtual ~IOException() {} }; /** @@ -88,7 +88,7 @@ class UnknownHostException : public IOException { public: UnknownHostException():IOException("Unknown host"){} - virtual ~UnknownHostException() throw() {} + virtual ~UnknownHostException() {} }; /** @@ -98,7 +98,7 @@ class NotConnectedException : public IOException { public: NotConnectedException():IOException("Not connected"){} - virtual ~NotConnectedException() throw() {} + virtual ~NotConnectedException() {} }; /** @@ -108,9 +108,28 @@ class TimeoutException : public IOException { public: TimeoutException():IOException("Timeout"){} - virtual ~TimeoutException() throw() {} + virtual ~TimeoutException() {} }; +/** + * Cookie given when performing async action, used to redeem result at a later date. + */ +typedef std::string TrackingID; + +/** + * Result of an async action. + */ +typedef enum +{ + UNKNOWN, + PENDING, + SUCCESS, + INVALID_ARGUMENT, + FAILURE, +} TrackingResult; + +typedef std::string Feature; + /** * A nut client is the starting point to dialog to NUTD. * It can connect to an NUTD then retrieve its device list. @@ -132,13 +151,13 @@ class Client * \todo Is his method is global to all connection protocol or is it specific to TCP ? * \note Actually, authentication fails only if already set, not if bad values are sent. */ - virtual void authenticate(const std::string& user, const std::string& passwd)throw(NutException)=0; + virtual void authenticate(const std::string& user, const std::string& passwd)=0; /** * Disconnect from the NUTD server. * \todo Is his method is global to all connection protocol or is it specific to TCP ? */ - virtual void logout()throw(NutException)=0; + virtual void logout()=0; /** * Device manipulations. @@ -151,29 +170,29 @@ class Client * \param name Name of the device. * \return The device. */ - virtual Device getDevice(const std::string& name)throw(NutException); + virtual Device getDevice(const std::string& name); /** * Retrieve the list of all devices supported by UPSD server. * \return The set of supported devices. */ - virtual std::set getDevices()throw(NutException); + virtual std::set getDevices(); /** * Test if a device is supported by the NUTD server. * \param dev Device name. * \return true if supported, false otherwise. */ - virtual bool hasDevice(const std::string& dev)throw(NutException); + virtual bool hasDevice(const std::string& dev); /** * Retrieve names of devices supported by NUTD server. * \return The set of names of supported devices. */ - virtual std::set getDeviceNames()throw(NutException)=0; + virtual std::set getDeviceNames()=0; /** * Retrieve the description of a device. * \param name Device name. * \return Device description. */ - virtual std::string getDeviceDescription(const std::string& name)throw(NutException)=0; + virtual std::string getDeviceDescription(const std::string& name)=0; /** \} */ /** @@ -186,54 +205,60 @@ class Client * \param dev Device name * \return Variable names */ - virtual std::set getDeviceVariableNames(const std::string& dev)throw(NutException)=0; + virtual std::set getDeviceVariableNames(const std::string& dev)=0; /** * Retrieve names of read/write variables supported by a device. * \param dev Device name * \return RW variable names */ - virtual std::set getDeviceRWVariableNames(const std::string& dev)throw(NutException)=0; + virtual std::set getDeviceRWVariableNames(const std::string& dev)=0; /** * Test if a variable is supported by a device. * \param dev Device name * \param name Variable name * \return true if the variable is supported. */ - virtual bool hasDeviceVariable(const std::string& dev, const std::string& name)throw(NutException); + virtual bool hasDeviceVariable(const std::string& dev, const std::string& name); /** * Retrieve the description of a variable. * \param dev Device name * \param name Variable name * \return Variable description if provided. */ - virtual std::string getDeviceVariableDescription(const std::string& dev, const std::string& name)throw(NutException)=0; + virtual std::string getDeviceVariableDescription(const std::string& dev, const std::string& name)=0; /** * Retrieve values of a variable. * \param dev Device name * \param name Variable name * \return Variable values (usually one) if available. */ - virtual std::vector getDeviceVariableValue(const std::string& dev, const std::string& name)throw(NutException)=0; + virtual std::vector getDeviceVariableValue(const std::string& dev, const std::string& name)=0; /** * Retrieve values of all variables of a device. * \param dev Device name * \return Variable values indexed by variable names. */ - virtual std::map > getDeviceVariableValues(const std::string& dev)throw(NutException); + virtual std::map > getDeviceVariableValues(const std::string& dev); + /** + * Retrieve values of all variables of a set of devices. + * \param devs Device names + * \return Variable values indexed by variable names, indexed by device names. + */ + virtual std::map > > getDevicesVariableValues(const std::set& devs); /** * Intend to set the value of a variable. * \param dev Device name * \param name Variable name * \param value Variable value - */ - virtual void setDeviceVariable(const std::string& dev, const std::string& name, const std::string& value)throw(NutException)=0; + */ + virtual TrackingID setDeviceVariable(const std::string& dev, const std::string& name, const std::string& value)=0; /** * Intend to set the value of a variable. * \param dev Device name * \param name Variable name * \param value Variable value - */ - virtual void setDeviceVariable(const std::string& dev, const std::string& name, const std::vector& values)throw(NutException)=0; + */ + virtual TrackingID setDeviceVariable(const std::string& dev, const std::string& name, const std::vector& values)=0; /** \} */ /** @@ -246,27 +271,28 @@ class Client * \param dev Device name * \return Command names */ - virtual std::set getDeviceCommandNames(const std::string& dev)throw(NutException)=0; + virtual std::set getDeviceCommandNames(const std::string& dev)=0; /** * Test if a command is supported by a device. * \param dev Device name * \param name Command name * \return true if the command is supported. */ - virtual bool hasDeviceCommand(const std::string& dev, const std::string& name)throw(NutException); + virtual bool hasDeviceCommand(const std::string& dev, const std::string& name); /** * Retrieve the description of a command. * \param dev Device name * \param name Command name * \return Command description if provided. */ - virtual std::string getDeviceCommandDescription(const std::string& dev, const std::string& name)throw(NutException)=0; + virtual std::string getDeviceCommandDescription(const std::string& dev, const std::string& name)=0; /** * Intend to execute a command. * \param dev Device name * \param name Command name + * \param param Additional command parameter */ - virtual void executeDeviceCommand(const std::string& dev, const std::string& name)throw(NutException)=0; + virtual TrackingID executeDeviceCommand(const std::string& dev, const std::string& name, const std::string& param="")=0; /** \} */ /** @@ -277,15 +303,27 @@ class Client * Log the current user (if authenticated) for a device. * \param dev Device name. */ - virtual void deviceLogin(const std::string& dev)throw(NutException)=0; + virtual void deviceLogin(const std::string& dev)=0; /** * Retrieve the number of user longged in the specified device. * \param dev Device name. * \return Number of logged-in users. */ - virtual int deviceGetNumLogins(const std::string& dev)throw(NutException)=0; - virtual void deviceMaster(const std::string& dev)throw(NutException)=0; - virtual void deviceForcedShutdown(const std::string& dev)throw(NutException)=0; + virtual int deviceGetNumLogins(const std::string& dev)=0; + virtual void deviceMaster(const std::string& dev)=0; + virtual void deviceForcedShutdown(const std::string& dev)=0; + + /** + * Retrieve the result of a tracking ID. + * \param id Tracking ID. + */ + virtual TrackingResult getTrackingResult(const TrackingID& id)=0; + + virtual bool hasFeature(const Feature& feature); + virtual bool isFeatureEnabled(const Feature& feature)=0; + virtual void setFeature(const Feature& feature, bool status)=0; + + static const Feature TRACKING; protected: Client(); @@ -309,7 +347,7 @@ class TcpClient : public Client * \param host Server host name. * \param port Server port. */ - TcpClient(const std::string& host, int port = 3493)throw(nut::IOException); + TcpClient(const std::string& host, int port = 3493); ~TcpClient(); /** @@ -317,13 +355,13 @@ class TcpClient : public Client * \param host Server host name. * \param port Server port. */ - void connect(const std::string& host, int port = 3493)throw(nut::IOException); + void connect(const std::string& host, int port = 3493); /** * Connect to the server. * Host name and ports must have already set (usefull for reconnection). */ - void connect()throw(nut::IOException); + void connect(); /** * Test if the connection is active. @@ -358,39 +396,47 @@ class TcpClient : public Client */ int getPort()const; - virtual void authenticate(const std::string& user, const std::string& passwd)throw(NutException); - virtual void logout()throw(NutException); - - virtual Device getDevice(const std::string& name)throw(NutException); - virtual std::set getDeviceNames()throw(NutException); - virtual std::string getDeviceDescription(const std::string& name)throw(NutException); - - virtual std::set getDeviceVariableNames(const std::string& dev)throw(NutException); - virtual std::set getDeviceRWVariableNames(const std::string& dev)throw(NutException); - virtual std::string getDeviceVariableDescription(const std::string& dev, const std::string& name)throw(NutException); - virtual std::vector getDeviceVariableValue(const std::string& dev, const std::string& name)throw(NutException); - virtual std::map > getDeviceVariableValues(const std::string& dev)throw(NutException); - virtual void setDeviceVariable(const std::string& dev, const std::string& name, const std::string& value)throw(NutException); - virtual void setDeviceVariable(const std::string& dev, const std::string& name, const std::vector& values)throw(NutException); - - virtual std::set getDeviceCommandNames(const std::string& dev)throw(NutException); - virtual std::string getDeviceCommandDescription(const std::string& dev, const std::string& name)throw(NutException); - virtual void executeDeviceCommand(const std::string& dev, const std::string& name)throw(NutException); - - virtual void deviceLogin(const std::string& dev)throw(NutException); - virtual void deviceMaster(const std::string& dev)throw(NutException); - virtual void deviceForcedShutdown(const std::string& dev)throw(NutException); - virtual int deviceGetNumLogins(const std::string& dev)throw(NutException); + virtual void authenticate(const std::string& user, const std::string& passwd); + virtual void logout(); + + virtual Device getDevice(const std::string& name); + virtual std::set getDeviceNames(); + virtual std::string getDeviceDescription(const std::string& name); + + virtual std::set getDeviceVariableNames(const std::string& dev); + virtual std::set getDeviceRWVariableNames(const std::string& dev); + virtual std::string getDeviceVariableDescription(const std::string& dev, const std::string& name); + virtual std::vector getDeviceVariableValue(const std::string& dev, const std::string& name); + virtual std::map > getDeviceVariableValues(const std::string& dev); + virtual std::map > > getDevicesVariableValues(const std::set& devs); + virtual TrackingID setDeviceVariable(const std::string& dev, const std::string& name, const std::string& value); + virtual TrackingID setDeviceVariable(const std::string& dev, const std::string& name, const std::vector& values); + + virtual std::set getDeviceCommandNames(const std::string& dev); + virtual std::string getDeviceCommandDescription(const std::string& dev, const std::string& name); + virtual TrackingID executeDeviceCommand(const std::string& dev, const std::string& name, const std::string& param=""); + + virtual void deviceLogin(const std::string& dev); + virtual void deviceMaster(const std::string& dev); + virtual void deviceForcedShutdown(const std::string& dev); + virtual int deviceGetNumLogins(const std::string& dev); + + virtual TrackingResult getTrackingResult(const TrackingID& id); + + virtual bool isFeatureEnabled(const Feature& feature); + virtual void setFeature(const Feature& feature, bool status); protected: - std::string sendQuery(const std::string& req)throw(nut::IOException); - static void detectError(const std::string& req)throw(nut::NutException); + std::string sendQuery(const std::string& req); + void sendAsyncQueries(const std::vector& req); + static void detectError(const std::string& req); + TrackingID sendTrackingQuery(const std::string& req); + + std::vector get(const std::string& subcmd, const std::string& params = ""); - std::vector get(const std::string& subcmd, const std::string& params = "") - throw(nut::NutException); + std::vector > list(const std::string& subcmd, const std::string& params = ""); - std::vector > list(const std::string& subcmd, const std::string& params = "") - throw(nut::NutException); + std::vector > parseList(const std::string& req); static std::vector explode(const std::string& str, size_t begin=0); static std::string escape(const std::string& str); @@ -455,92 +501,93 @@ class Device /** * Retrieve the description of the devce if specified. */ - std::string getDescription()throw(NutException); + std::string getDescription(); /** * Intend to retrieve the value of a variable of the device. * \param name Name of the variable to get. * \return Value of the variable, if available. */ - std::vector getVariableValue(const std::string& name)throw(NutException); + std::vector getVariableValue(const std::string& name); /** * Intend to retrieve values of all variables of the devices. * \return Map of all variables values indexed by their names. */ - std::map > getVariableValues()throw(NutException); + std::map > getVariableValues(); /** * Retrieve all variables names supported by the device. * \return Set of available variable names. */ - std::set getVariableNames()throw(NutException); + std::set getVariableNames(); /** * Retrieve all Read/Write variables names supported by the device. * \return Set of available Read/Write variable names. */ - std::set getRWVariableNames()throw(NutException); + std::set getRWVariableNames(); /** * Intend to set the value of a variable of the device. * \param name Variable name. * \param value New variable value. */ - void setVariable(const std::string& name, const std::string& value)throw(NutException); + void setVariable(const std::string& name, const std::string& value); /** * Intend to set values of a variable of the device. * \param name Variable name. * \param value New variable values. */ - void setVariable(const std::string& name, const std::vector& values)throw(NutException); + void setVariable(const std::string& name, const std::vector& values); /** * Retrieve a Variable object representing the specified variable. * \param name Variable name. * \return Variable object. */ - Variable getVariable(const std::string& name)throw(NutException); + Variable getVariable(const std::string& name); /** * Retrieve Variable objects representing all variables available for the device. * \return Set of Variable objects. */ - std::set getVariables()throw(NutException); + std::set getVariables(); /** * Retrieve Variable objects representing all Read/Write variables available for the device. * \return Set of Variable objects. */ - std::set getRWVariables()throw(NutException); + std::set getRWVariables(); /** * Retrieve names of all commands supported by the device. * \return Set of available command names. */ - std::set getCommandNames()throw(NutException); + std::set getCommandNames(); /** * Retrieve objects for all commands supported by the device. * \return Set of available Command objects. */ - std::set getCommands()throw(NutException); + std::set getCommands(); /** * Retrieve an object representing a command of the device. * \param name Command name. * \return Command object. */ - Command getCommand(const std::string& name)throw(NutException); + Command getCommand(const std::string& name); /** * Intend to execute a command on the device. * \param name Command name. + * \param param Additional command parameter */ - void executeCommand(const std::string& name)throw(NutException); + TrackingID executeCommand(const std::string& name, const std::string& param=""); /** * Login current client's user for the device. */ - void login()throw(NutException); - void master()throw(NutException); - void forcedShutdown()throw(NutException); + void login(); + void master(); + void forcedShutdown(); /** * Retrieve the number of logged user for the device. * \return Number of users. */ - int getNumLogins()throw(NutException); + int getNumLogins(); protected: Device(Client* client, const std::string& name); @@ -603,23 +650,23 @@ class Variable * Intend to retrieve variable value. * \return Value of the variable. */ - std::vector getValue()throw(NutException); + std::vector getValue(); /** * Intend to retireve variable description. * \return Variable description if provided. */ - std::string getDescription()throw(NutException); + std::string getDescription(); /** * Intend to set a value to the variable. * \param value New variable value. */ - void setValue(const std::string& value)throw(NutException); + void setValue(const std::string& value); /** * Intend to set (multiple) values to the variable. * \param value New variable values. */ - void setValues(const std::vector& values)throw(NutException); + void setValues(const std::vector& values); protected: Variable(Device* dev, const std::string& name); @@ -683,13 +730,14 @@ class Command * Intend to retireve command description. * \return Command description if provided. */ - std::string getDescription()throw(NutException); + std::string getDescription(); /** * Intend to retrieve command description. + * \param param Additional command parameter * \return Command description if provided. */ - void execute()throw(NutException); + void execute(const std::string& param=""); protected: Command(Device* dev, const std::string& name); @@ -901,7 +949,7 @@ char* nutclient_get_device_command_description(NUTCLIENT_t client, const char* d * \param dev Device name. * \param cmd Command name. */ -void nutclient_execute_device_command(NUTCLIENT_t client, const char* dev, const char* cmd); +void nutclient_execute_device_command(NUTCLIENT_t client, const char* dev, const char* cmd, const char* param=""); /** \} */ diff --git a/clients/upsclient.c b/clients/upsclient.c index b90587b001..50042ac7af 100644 --- a/clients/upsclient.c +++ b/clients/upsclient.c @@ -299,11 +299,6 @@ int upscli_init(int certverify, const char *certpath, { #ifdef WITH_OPENSSL int ret, ssl_mode = SSL_VERIFY_NONE; -#if OPENSSL_VERSION_NUMBER >= 0x10000000L - const SSL_METHOD *ssl_method; -#else - SSL_METHOD *ssl_method; -#endif #elif defined(WITH_NSS) /* WITH_OPENSSL */ SECStatus status; #endif /* WITH_OPENSSL | WITH_NSS */ @@ -315,22 +310,32 @@ int upscli_init(int certverify, const char *certpath, } #ifdef WITH_OPENSSL - - SSL_library_init(); - SSL_load_error_strings(); - ssl_method = TLSv1_client_method(); +#if OPENSSL_VERSION_NUMBER < 0x10100000L + SSL_load_error_strings(); + SSL_library_init(); - if (!ssl_method) { - return 0; - } + ssl_ctx = SSL_CTX_new(SSLv23_client_method()); +#else + ssl_ctx = SSL_CTX_new(TLS_client_method()); +#endif - ssl_ctx = SSL_CTX_new(ssl_method); if (!ssl_ctx) { upslogx(LOG_ERR, "Can not initialize SSL context"); return -1; } +#if OPENSSL_VERSION_NUMBER < 0x10100000L + /* set minimum protocol TLSv1 */ + SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); +#else + ret = SSL_CTX_set_min_proto_version(ssl_ctx, TLS1_VERSION); + if (ret != 1) { + upslogx(LOG_ERR, "Can not set minimum protocol to TLSv1"); + return -1; + } +#endif + if (!certpath) { if (certverify == 1) { upslogx(LOG_ERR, "Can not verify certificate if any is specified"); @@ -442,7 +447,7 @@ static HOST_CERT_t* upscli_find_host_cert(const char* hostname) return NULL; } -int upscli_cleanup() +int upscli_cleanup(void) { #ifdef WITH_OPENSSL if (ssl_ctx) { @@ -567,7 +572,7 @@ static int upscli_select_read(const int fd, void *buf, const size_t buflen, cons } /* internal: abstract the SSL calls for the other functions */ -static int net_read(UPSCONN_t *ups, char *buf, size_t buflen) +static int net_read(UPSCONN_t *ups, char *buf, size_t buflen, unsigned int timeout) { int ret = -1; @@ -587,7 +592,7 @@ static int net_read(UPSCONN_t *ups, char *buf, size_t buflen) } #endif - ret = upscli_select_read(ups->fd, buf, buflen, 5, 0); + ret = upscli_select_read(ups->fd, buf, buflen, timeout, 0); /* error reading data, server disconnected? */ if (ret < 0) { @@ -628,7 +633,7 @@ static int upscli_select_write(const int fd, const void *buf, const size_t bufle } /* internal: abstract the SSL calls for the other functions */ -static int net_write(UPSCONN_t *ups, const char *buf, size_t buflen) +static int net_write(UPSCONN_t *ups, const char *buf, size_t buflen, unsigned int timeout) { int ret = -1; @@ -648,7 +653,7 @@ static int net_write(UPSCONN_t *ups, const char *buf, size_t buflen) } #endif - ret = upscli_select_write(ups->fd, buf, buflen, 0, 0); + ret = upscli_select_write(ups->fd, buf, buflen, timeout, 0); /* error writing data, server disconnected? */ if (ret < 0) { @@ -737,7 +742,7 @@ static int upscli_sslinit(UPSCONN_t *ups, int verifycert) switch(res) { case 1: - upsdebugx(3, "SSL connected"); + upsdebugx(3, "SSL connected (%s)", SSL_get_version(ups->ssl)); break; case 0: upslog_with_errno(1, "SSL_connect do not accept handshake."); @@ -1034,7 +1039,7 @@ int upscli_tryconnect(UPSCONN_t *ups, const char *host, int port, int flags,stru upscli_disconnect(ups); return -1; } - upsdebugx(3, "Can not connect to %s in SSL, continue uncrypted", host); + upsdebugx(3, "Can not connect to %s in SSL, continue unencrypted", host); } else { upslogx(LOG_INFO, "Connected to %s in SSL", host); if (certverify == 0) { @@ -1326,7 +1331,7 @@ int upscli_list_next(UPSCONN_t *ups, unsigned int numq, const char **query, return 1; } -int upscli_sendline(UPSCONN_t *ups, const char *buf, size_t buflen) +int upscli_sendline_timeout(UPSCONN_t *ups, const char *buf, size_t buflen, unsigned int timeout) { int ret; @@ -1349,7 +1354,7 @@ int upscli_sendline(UPSCONN_t *ups, const char *buf, size_t buflen) return -1; } - ret = net_write(ups, buf, buflen); + ret = net_write(ups, buf, buflen, timeout); if (ret < 1) { upscli_disconnect(ups); @@ -1359,7 +1364,12 @@ int upscli_sendline(UPSCONN_t *ups, const char *buf, size_t buflen) return 0; } -int upscli_readline(UPSCONN_t *ups, char *buf, size_t buflen) +int upscli_sendline(UPSCONN_t *ups, const char *buf, size_t buflen) +{ + return upscli_sendline_timeout(ups, buf, buflen, 0); +} + +int upscli_readline_timeout(UPSCONN_t *ups, char *buf, size_t buflen, unsigned int timeout) { int ret; size_t recv; @@ -1387,7 +1397,7 @@ int upscli_readline(UPSCONN_t *ups, char *buf, size_t buflen) if (ups->readidx == ups->readlen) { - ret = net_read(ups, ups->readbuf, sizeof(ups->readbuf)); + ret = net_read(ups, ups->readbuf, sizeof(ups->readbuf), timeout); if (ret < 1) { upscli_disconnect(ups); @@ -1409,6 +1419,11 @@ int upscli_readline(UPSCONN_t *ups, char *buf, size_t buflen) return 0; } +int upscli_readline(UPSCONN_t *ups, char *buf, size_t buflen) +{ + return upscli_readline_timeout(ups, buf, buflen, DEFAULT_NETWORK_TIMEOUT); +} + /* split upsname[@hostname[:port]] into separate components */ int upscli_splitname(const char *buf, char **upsname, char **hostname, int *port) { @@ -1518,7 +1533,7 @@ int upscli_disconnect(UPSCONN_t *ups) return 0; } - net_write(ups, "LOGOUT\n", 7); + net_write(ups, "LOGOUT\n", 7, 0); #ifdef WITH_OPENSSL if (ups->ssl) { diff --git a/clients/upsclient.h b/clients/upsclient.h index ac5fb5d567..d3da201bf1 100644 --- a/clients/upsclient.h +++ b/clients/upsclient.h @@ -69,7 +69,7 @@ typedef struct { const char *upscli_strerror(UPSCONN_t *ups); int upscli_init(int certverify, const char *certpath, const char *certname, const char *certpasswd); -int upscli_cleanup(); +int upscli_cleanup(void); int upscli_tryconnect(UPSCONN_t *ups, const char *host, int port, int flags, struct timeval *tv); int upscli_connect(UPSCONN_t *ups, const char *host, int port, int flags); @@ -86,8 +86,10 @@ int upscli_list_start(UPSCONN_t *ups, unsigned int numq, const char **query); int upscli_list_next(UPSCONN_t *ups, unsigned int numq, const char **query, unsigned int *numa, char ***answer); +int upscli_sendline_timeout(UPSCONN_t *ups, const char *buf, size_t buflen, unsigned int timeout); int upscli_sendline(UPSCONN_t *ups, const char *buf, size_t buflen); +int upscli_readline_timeout(UPSCONN_t *ups, char *buf, size_t buflen, unsigned int timeout); int upscli_readline(UPSCONN_t *ups, char *buf, size_t buflen); int upscli_splitname(const char *buf, char **upsname, char **hostname, diff --git a/clients/upscmd.c b/clients/upscmd.c index f4990a872c..f8e237d429 100644 --- a/clients/upscmd.c +++ b/clients/upscmd.c @@ -1,6 +1,8 @@ /* upscmd - simple "client" to test instant commands via upsd - Copyright (C) 2000 Russell Kroll + Copyright (C) + 2000 Russell Kroll + 2019 EATON (author: Arnaud Quette ) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -28,8 +30,10 @@ #include "upsclient.h" -static char *upsname = NULL, *hostname = NULL; +static char *upsname = NULL, *hostname = NULL; static UPSCONN_t *ups = NULL; +static int tracking_enabled = 0; +static unsigned int timeout = DEFAULT_TRACKING_TIMEOUT; struct list_t { char *name; @@ -41,13 +45,16 @@ static void usage(const char *prog) printf("Network UPS Tools upscmd %s\n\n", UPS_VERSION); printf("usage: %s [-h]\n", prog); printf(" %s [-l ]\n", prog); - printf(" %s [-u ] [-p ] []\n\n", prog); + printf(" %s [-u ] [-p ] [-w] [-t ] []\n\n", prog); printf("Administration program to initiate instant commands on UPS hardware.\n"); printf("\n"); printf(" -h display this help text\n"); printf(" -l show available commands on UPS \n"); printf(" -u set username for command authentication\n"); printf(" -p set password for command authentication\n"); + printf(" -w wait for the completion of command by the driver\n"); + printf(" and return its actual result from the device\n"); + printf(" -t set a timeout when using -w (in seconds, default: %u)\n", DEFAULT_TRACKING_TIMEOUT); printf("\n"); printf(" UPS identifier - [@[:]]\n"); printf(" Valid instant command - test.panel.start, etc.\n"); @@ -138,7 +145,10 @@ static void listcmds(void) static void do_cmd(char **argv, const int argc) { + int cmd_complete = 0; char buf[SMALLBUF]; + char tracking_id[UUID4_LEN]; + time_t start, now; if (argc > 1) { snprintf(buf, sizeof(buf), "INSTCMD %s %s %s\n", upsname, argv[0], argv[1]); @@ -154,11 +164,49 @@ static void do_cmd(char **argv, const int argc) fatalx(EXIT_FAILURE, "Instant command failed: %s", upscli_strerror(ups)); } - /* FUTURE: status cookies will tie in here */ + /* verify answer */ if (strncmp(buf, "OK", 2) != 0) { fatalx(EXIT_FAILURE, "Unexpected response from upsd: %s", buf); } + /* check for status tracking id */ + if ( + !tracking_enabled || + /* sanity check on the size: "OK TRACKING " + UUID4_LEN */ + strlen(buf) != (UUID4_LEN - 1 + strlen("OK TRACKING ")) + ) { + /* reply as usual */ + fprintf(stderr, "%s\n", buf); + return; + } + + snprintf(tracking_id, sizeof(tracking_id), "%s", buf + strlen("OK TRACKING ")); + time(&start); + + /* send status tracking request, looping if status is PENDING */ + while (!cmd_complete) { + + /* check for timeout */ + time(&now); + if (difftime(now, start) >= timeout) + fatalx(EXIT_FAILURE, "Can't receive status tracking information: timeout"); + + snprintf(buf, sizeof(buf), "GET TRACKING %s\n", tracking_id); + + if (upscli_sendline(ups, buf, strlen(buf)) < 0) + fatalx(EXIT_FAILURE, "Can't send status tracking request: %s", upscli_strerror(ups)); + + /* and get status tracking reply */ + if (upscli_readline_timeout(ups, buf, sizeof(buf), timeout) < 0) + fatalx(EXIT_FAILURE, "Can't receive status tracking information: %s", upscli_strerror(ups)); + + if (strncmp(buf, "PENDING", 7)) + cmd_complete = 1; + else + /* wait a second before retrying */ + sleep(1); + } + fprintf(stderr, "%s\n", buf); } @@ -180,7 +228,7 @@ int main(int argc, char **argv) char buf[SMALLBUF], username[SMALLBUF], password[SMALLBUF]; const char *prog = xbasename(argv[0]); - while ((i = getopt(argc, argv, "+lhu:p:V")) != -1) { + while ((i = getopt(argc, argv, "+lhu:p:t:wV")) != -1) { switch (i) { @@ -198,6 +246,15 @@ int main(int argc, char **argv) have_pw = 1; break; + case 't': + if (!str_to_uint(optarg, &timeout, 10)) + fatal_with_errno(EXIT_FAILURE, "Could not convert the provided value for timeout ('-t' option) to unsigned int"); + break; + + case 'w': + tracking_enabled = 1; + break; + case 'V': fatalx(EXIT_SUCCESS, "Network UPS Tools upscmd %s", UPS_VERSION); @@ -313,6 +370,25 @@ int main(int argc, char **argv) fatalx(EXIT_FAILURE, "Set password failed: %s", upscli_strerror(ups)); } + /* enable status tracking ID */ + if (tracking_enabled) { + + snprintf(buf, sizeof(buf), "SET TRACKING ON\n"); + + if (upscli_sendline(ups, buf, strlen(buf)) < 0) { + fatalx(EXIT_FAILURE, "Can't enable command status tracking: %s", upscli_strerror(ups)); + } + + if (upscli_readline(ups, buf, sizeof(buf)) < 0) { + fatalx(EXIT_FAILURE, "Enabling command status tracking failed: %s", upscli_strerror(ups)); + } + + /* Verify the result */ + if (strncmp(buf, "OK", 2) != 0) { + fatalx(EXIT_FAILURE, "Enabling command status tracking failed. upsd answered: %s", buf); + } + } + do_cmd(&argv[1], argc - 1); exit(EXIT_SUCCESS); diff --git a/clients/upsmon.c b/clients/upsmon.c index 12823fa1ee..a08a453888 100644 --- a/clients/upsmon.c +++ b/clients/upsmon.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include "upsclient.h" #include "upsmon.h" @@ -655,6 +657,19 @@ static int is_ups_critical(utype_t *ups) /* must be OB+LB now */ + /* if UPS is calibrating, don't declare it critical */ + /* FIXME: Consider UPSes where we can know if they have other power + * circuits (bypass, etc.) and whether those do currently provide + * wall power to the host - and that we do not have both calibration + * and a real outage, when we still should shut down right now. + */ + if (flag_isset(ups->status, ST_CAL)) { + upslogx(LOG_WARNING, "%s: seems that UPS [%s] is OB+LB now, but " + "it is also calibrating - not declaring a critical state", + __func__, ups->upsname); + return 0; + } + /* if we're a master, declare it critical so we set FSD on it */ if (flag_isset(ups->status, ST_MASTER)) return 1; @@ -741,6 +756,21 @@ static void upsreplbatt(utype_t *ups) } } +static void ups_cal(utype_t *ups) +{ + if (flag_isset(ups->status, ST_CAL)) { /* no change */ + upsdebugx(4, "%s: %s (no change)", __func__, ups->sys); + return; + } + + upsdebugx(3, "%s: %s (first time)", __func__, ups->sys); + + /* must have changed from !CAL to CAL, so notify */ + + do_notify(ups, NOTIFY_CAL); + setflag(&ups->status, ST_CAL); +} + static void ups_fsd(utype_t *ups) { if (flag_isset(ups->status, ST_FSD)) { /* no change */ @@ -1370,9 +1400,10 @@ static void setup_signals(void) /* remember the last time the ups was not critical (OB + LB) */ static void update_crittimer(utype_t *ups) { - /* if !OB or !LB, then it's not critical, so log the time */ - if ((!flag_isset(ups->status, ST_ONBATT)) || - (!flag_isset(ups->status, ST_LOWBATT))) { + /* if !OB, !LB, or CAL, then it's not critical, so log the time */ + if ((!flag_isset(ups->status, ST_ONBATT)) || + (!flag_isset(ups->status, ST_LOWBATT)) || + (flag_isset(ups->status, ST_CAL))) { time(&ups->lastnoncrit); return; @@ -1432,6 +1463,9 @@ static int try_connect(utype_t *ups) /* we're definitely connected now */ setflag(&ups->status, ST_CONNECTED); + /* prevent connection leaking to NOTIFYCMD */ + fcntl(upscli_fd(&ups->conn), F_SETFD, FD_CLOEXEC); + /* now try to authenticate to upsd */ ret = do_upsd_auth(ups); @@ -1487,6 +1521,8 @@ static void parse_status(utype_t *ups, char *status) ups_low_batt(ups); if (!strcasecmp(statword, "RB")) upsreplbatt(ups); + if (!strcasecmp(statword, "CAL")) + ups_cal(ups); /* do it last to override any possible OL */ if (!strcasecmp(statword, "FSD")) @@ -1714,6 +1750,9 @@ static void start_pipe(void) } close(pipefd[0]); + + /* prevent pipe leaking to NOTIFYCMD */ + fcntl(pipefd[1], F_SETFD, FD_CLOEXEC); } static void delete_ups(utype_t *target) @@ -1814,7 +1853,7 @@ static void reload_conf(void) upslogx(LOG_CRIT, "Fatal error: total power value (%d) less " "than MINSUPPLIES (%d)", totalpv, minsupplies); - fatalx(EXIT_FAILURE, "Impossible power configuation, unable to continue"); + fatalx(EXIT_FAILURE, "Impossible power configuration, unable to continue"); } /* finally clear the flag */ diff --git a/clients/upsmon.h b/clients/upsmon.h index 2504370cf1..7fe98eb827 100644 --- a/clients/upsmon.h +++ b/clients/upsmon.h @@ -26,6 +26,7 @@ #define ST_MASTER (1 << 4) /* we are the master on this UPS */ #define ST_LOGIN (1 << 5) /* we are logged into this UPS */ #define ST_CONNECTED (1 << 6) /* upscli_connect returned OK */ +#define ST_CAL (1 << 7) /* UPS calibration in progress (CAL) */ /* required contents of flag file */ #define SDMAGIC "upsmon-shutdown-file" @@ -75,6 +76,7 @@ typedef struct { #define NOTIFY_REPLBATT 7 /* UPS battery needs to be replaced */ #define NOTIFY_NOCOMM 8 /* UPS hasn't been contacted in awhile */ #define NOTIFY_NOPARENT 9 /* privileged parent process died */ +#define NOTIFY_CAL 10 /* UPS is performing calibration */ /* notify flag values */ @@ -104,6 +106,7 @@ struct { { NOTIFY_REPLBATT, "REPLBATT", NULL, "UPS %s battery needs to be replaced", NOTIFY_SYSLOG | NOTIFY_WALL }, { NOTIFY_NOCOMM, "NOCOMM", NULL, "UPS %s is unavailable", NOTIFY_SYSLOG | NOTIFY_WALL }, { NOTIFY_NOPARENT, "NOPARENT", NULL, "upsmon parent process died - shutdown impossible", NOTIFY_SYSLOG | NOTIFY_WALL }, + { NOTIFY_CAL, "CAL", NULL, "UPS %s: calibration in progress", NOTIFY_SYSLOG }, { 0, NULL, NULL, NULL, 0 } }; diff --git a/clients/upsrw.c b/clients/upsrw.c index dd388e1702..0d1906de51 100644 --- a/clients/upsrw.c +++ b/clients/upsrw.c @@ -1,6 +1,8 @@ /* upsrw - simple client for read/write variable access (formerly upsct2) - Copyright (C) 1999 Russell Kroll + Copyright (C) + 1999 Russell Kroll + 2019 EATON (author: Arnaud Quette ) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -28,8 +30,10 @@ #include "upsclient.h" #include "extstate.h" -static char *upsname = NULL, *hostname = NULL; +static char *upsname = NULL, *hostname = NULL; static UPSCONN_t *ups = NULL; +static int tracking_enabled = 0; +static unsigned int timeout = DEFAULT_TRACKING_TIMEOUT; struct list_t { char *name; @@ -40,7 +44,7 @@ static void usage(const char *prog) { printf("Network UPS Tools %s %s\n\n", prog, UPS_VERSION); printf("usage: %s [-h]\n", prog); - printf(" %s [-s ] [-u ] [-p ] \n\n", prog); + printf(" %s [-s ] [-u ] [-p ] [-w] [-t ] \n\n", prog); printf("Demo program to set variables within UPS hardware.\n"); printf("\n"); printf(" -h display this help text\n"); @@ -48,6 +52,9 @@ static void usage(const char *prog) printf(" use -s VAR=VALUE to avoid prompting for value\n"); printf(" -u set username for command authentication\n"); printf(" -p set password for command authentication\n"); + printf(" -w wait for the completion of setting by the driver\n"); + printf(" and return its actual result from the device\n"); + printf(" -t set a timeout when using -w (in seconds, default: %u)\n", DEFAULT_TRACKING_TIMEOUT); printf("\n"); printf(" UPS identifier - [@[:]]\n"); printf("\n"); @@ -67,7 +74,10 @@ static void clean_exit(void) static void do_set(const char *varname, const char *newval) { + int cmd_complete = 0; char buf[SMALLBUF], enc[SMALLBUF]; + char tracking_id[UUID4_LEN]; + time_t start, now; snprintf(buf, sizeof(buf), "SET VAR %s %s \"%s\"\n", upsname, varname, pconf_encode(newval, enc, sizeof(enc))); @@ -79,11 +89,49 @@ static void do_set(const char *varname, const char *newval) fatalx(EXIT_FAILURE, "Set variable failed: %s", upscli_strerror(ups)); } - /* FUTURE: status cookies will tie in here */ + /* verify answer */ if (strncmp(buf, "OK", 2) != 0) { fatalx(EXIT_FAILURE, "Unexpected response from upsd: %s", buf); } + /* check for status tracking id */ + if ( + !tracking_enabled || + /* sanity check on the size: "OK TRACKING " + UUID4_LEN */ + strlen(buf) != (UUID4_LEN - 1 + strlen("OK TRACKING ")) + ) { + /* reply as usual */ + fprintf(stderr, "%s\n", buf); + return; + } + + snprintf(tracking_id, sizeof(tracking_id), "%s", buf + strlen("OK TRACKING ")); + time(&start); + + /* send status tracking request, looping if status is PENDING */ + while (!cmd_complete) { + + /* check for timeout */ + time(&now); + if (difftime(now, start) >= timeout) + fatalx(EXIT_FAILURE, "Can't receive status tracking information: timeout"); + + snprintf(buf, sizeof(buf), "GET TRACKING %s\n", tracking_id); + + if (upscli_sendline(ups, buf, strlen(buf)) < 0) + fatalx(EXIT_FAILURE, "Can't send status tracking request: %s", upscli_strerror(ups)); + + /* and get status tracking reply */ + if (upscli_readline_timeout(ups, buf, sizeof(buf), timeout) < 0) + fatalx(EXIT_FAILURE, "Can't receive status tracking information: %s", upscli_strerror(ups)); + + if (strncmp(buf, "PENDING", 7)) + cmd_complete = 1; + else + /* wait a second before retrying */ + sleep(1); + } + fprintf(stderr, "%s\n", buf); } @@ -178,6 +226,25 @@ static void do_setvar(const char *varname, char *uin, const char *pass) fatalx(EXIT_FAILURE, "Error: old variable names are not supported"); } + /* enable status tracking ID */ + if (tracking_enabled) { + + snprintf(temp, sizeof(temp), "SET TRACKING ON\n"); + + if (upscli_sendline(ups, temp, strlen(temp)) < 0) { + fatalx(EXIT_FAILURE, "Can't enable set variable status tracking: %s", upscli_strerror(ups)); + } + + if (upscli_readline(ups, temp, sizeof(temp)) < 0) { + fatalx(EXIT_FAILURE, "Enabling set variable status tracking failed: %s", upscli_strerror(ups)); + } + + /* Verify the result */ + if (strncmp(temp, "OK", 2) != 0) { + fatalx(EXIT_FAILURE, "Enabling set variable status tracking failed. upsd answered: %s", temp); + } + } + do_set(varname, newval); } @@ -369,7 +436,7 @@ static void do_type(const char *varname) ret = upscli_get(ups, numq, query, &numa, &answer); if ((ret < 0) || (numa < numq)) { - printf("Unknown type\n"); + printf("Unknown type\n"); return; } @@ -519,7 +586,7 @@ int main(int argc, char **argv) const char *prog = xbasename(argv[0]); char *password = NULL, *username = NULL, *setvar = NULL; - while ((i = getopt(argc, argv, "+hs:p:u:V")) != -1) { + while ((i = getopt(argc, argv, "+hs:p:t:u:wV")) != -1) { switch (i) { case 's': @@ -528,9 +595,16 @@ int main(int argc, char **argv) case 'p': password = optarg; break; + case 't': + if (!str_to_uint(optarg, &timeout, 10)) + fatal_with_errno(EXIT_FAILURE, "Could not convert the provided value for timeout ('-t' option) to unsigned int"); + break; case 'u': username = optarg; break; + case 'w': + tracking_enabled = 1; + break; case 'V': printf("Network UPS Tools %s %s\n", prog, UPS_VERSION); exit(EXIT_SUCCESS); diff --git a/clients/upssched.c b/clients/upssched.c index 97b3ed42db..c0484ee159 100644 --- a/clients/upssched.c +++ b/clients/upssched.c @@ -46,6 +46,8 @@ #include #include #include +#include +#include #include "upssched.h" #include "timehead.h" @@ -297,6 +299,9 @@ static int open_sock(void) if (ret < 0) fatal_with_errno(EXIT_FAILURE, "listen(%d, %d) failed", fd, US_LISTEN_BACKLOG); + /* don't leak socket to CMDSCRIPT */ + fcntl(fd, F_SETFD, FD_CLOEXEC); + return fd; } @@ -370,6 +375,9 @@ static void conn_add(int sockfd) return; } + /* don't leak connection to CMDSCRIPT */ + fcntl(acc, F_SETFD, FD_CLOEXEC); + /* enable nonblocking I/O */ ret = fcntl(acc, F_GETFL, 0); @@ -794,7 +802,7 @@ static void parse_at(const char *ntype, const char *un, const char *cmd, } if (!strcmp(cmd, "EXECUTE")) { - if (ca1 == '\0') { + if (ca1[0] == '\0') { upslogx(LOG_ERR, "Empty EXECUTE command argument"); return; } diff --git a/common/Makefile.am b/common/Makefile.am index 2bfc6e0dc9..e2a4acb697 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -12,6 +12,6 @@ libparseconf_la_SOURCES = parseconf.c libcommon_la_SOURCES = common.c state.c str.c upsconf.c libcommonclient_la_SOURCES = common.c state.c str.c # ensure inclusion of local implementation of missing systems functions -# using LTLIBOBJS. Refer to configure.in -> AC_REPLACE_FUNCS +# using LTLIBOBJS. Refer to configure.in/.ac -> AC_REPLACE_FUNCS libcommon_la_LIBADD = libparseconf.la @LTLIBOBJS@ libcommonclient_la_LIBADD = libparseconf.la @LTLIBOBJS@ diff --git a/common/common.c b/common/common.c index 85f871880a..e27b85eab7 100644 --- a/common/common.c +++ b/common/common.c @@ -33,6 +33,16 @@ #include "nut_version.h" const char *UPS_VERSION = NUT_VERSION_MACRO; +#include +#include + +/* Know which bitness we were built for, + * to adjust the search paths for get_libname() */ +#include "nut_stdint.h" +#if UINTPTR_MAX == 0xffffffffffffffffULL +# define BUILD_64 1 +#endif + int nut_debug_level = 0; int nut_log_level = 0; static int upslog_flags = UPSLOG_STDERR; @@ -680,15 +690,32 @@ int select_write(const int fd, const void *buf, const size_t buflen, const long } -/* FIXME: would be good to get more from /etc/ld.so.conf[.d] and/or LD_LIBRARY_PATH */ +/* FIXME: would be good to get more from /etc/ld.so.conf[.d] and/or + * LD_LIBRARY_PATH and a smarter dependency on build bitness; also + * note that different OSes can have their pathnames set up differently + * with regard to default/preferred bitness (maybe a "32" in the name + * should also be searched explicitly - again, IFF our build is 32-bit). + */ const char * search_paths[] = { + // Use the library path (and bitness) provided during ./configure first LIBDIR, "/usr"LIBDIR, + "/usr/local"LIBDIR, +#if BUILD_64 + // Fall back to explicit preference of 64-bit paths as named on some OSes + "/usr/lib/64", "/usr/lib64", - "/lib64", +#endif "/usr/lib", +#if BUILD_64 + "/lib/64", + "/lib64", +#endif "/lib", +#if BUILD_64 + "/usr/local/lib/64", "/usr/local/lib64", +#endif "/usr/local/lib", #ifdef AUTOTOOLS_TARGET_SHORT_ALIAS "/usr/lib/" AUTOTOOLS_TARGET_SHORT_ALIAS, diff --git a/common/parseconf.c b/common/parseconf.c index 005fc8eb76..1193a2f9ca 100644 --- a/common/parseconf.c +++ b/common/parseconf.c @@ -83,6 +83,7 @@ #include #include #include +#include #include "parseconf.h" @@ -443,6 +444,9 @@ int pconf_file_begin(PCONF_CTX_t *ctx, const char *fn) return 0; } + /* prevent fd leaking to child processes */ + fcntl(fileno(ctx->f), F_SETFD, FD_CLOEXEC); + return 1; /* OK */ } diff --git a/common/snprintf.c b/common/snprintf.c index 62c8c14182..be7785266f 100644 --- a/common/snprintf.c +++ b/common/snprintf.c @@ -54,7 +54,7 @@ #include "config.h" #include -# include +#include #include #if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) diff --git a/common/state.c b/common/state.c index ed9654d092..93107114ff 100644 --- a/common/state.c +++ b/common/state.c @@ -124,7 +124,10 @@ static void st_tree_node_add(st_tree_t **nptr, st_tree_t *sptr) *nptr = sptr; } -/* remove a variable from a tree */ +/* remove a variable from a tree + * except for variables with ST_FLAG_IMMUTABLE + * (for override.* to survive) per issue #737 + */ int state_delinfo(st_tree_t **nptr, const char *var) { while (*nptr) { @@ -141,6 +144,11 @@ int state_delinfo(st_tree_t **nptr, const char *var) continue; } + if (node->flags & ST_FLAG_IMMUTABLE) { + upsdebugx(6, "%s: not deleting immutable variable [%s]", __func__, var); + return 0; + } + /* whatever is on the left, hang it off current right */ st_tree_node_add(&node->right, node->left); diff --git a/conf/nut.conf.sample b/conf/nut.conf.sample index b0c2685c7d..ebf6c04b96 100644 --- a/conf/nut.conf.sample +++ b/conf/nut.conf.sample @@ -26,7 +26,14 @@ # - netclient: this mode only requires upsmon. # # IMPORTANT NOTE: -# This file is intended to be sourced by shell scripts. +# This file is intended to be sourced by standard POSIX shell scripts (so +# there is no guaranteed `export VAR=VAL` syntax) and by systemd on Linux. # You MUST NOT use spaces around the equal sign! MODE=none + +# Uncomment this to allow starting the service even if ups.conf has no device +# sections at the moment. This environment variable overrides the built-in +# "false" and an optional same-named default flag that can be set in upsd.conf: +#ALLOW_NO_DEVICE=true +#export ALLOW_NO_DEVICE diff --git a/conf/upsd.conf.sample b/conf/upsd.conf.sample index e7328f6865..b12dd1c5e7 100644 --- a/conf/upsd.conf.sample +++ b/conf/upsd.conf.sample @@ -21,6 +21,29 @@ # the data fresh within the normal 15 second interval. Watch the syslog # for notifications from upsd about staleness. +# ======================================================================= +# TRACKINGDELAY +# TRACKINGDELAY 3600 +# +# This defaults to 1 hour. When instant commands and variables setting status +# tracking is enabled, status execution information are kept during this +# amount of time, and then cleaned up. + +# ======================================================================= +# ALLOW_NO_DEVICE +# ALLOW_NO_DEVICE true +# +# Normally upsd requires that at least one device section is defined in ups.conf +# when the daemon starts, to serve its data. For automatically managed services +# it may be preferred to have upsd always running, and reload the configuration +# when power devices become defined. +# +# Boolean values 'true', 'yes', 'on' and '1' mean that the server would not +# refuse to start with zero device sections found in ups.conf. +# +# Boolean values 'false', 'no', 'off' and '0' mean that the server should refuse +# to start if zero device sections were found in ups.conf. This is the default. + # ======================================================================= # STATEPATH # STATEPATH /var/run/nut diff --git a/configure.ac b/configure.ac index 93a2d33dba..db1de0fce6 100644 --- a/configure.ac +++ b/configure.ac @@ -27,7 +27,23 @@ dnl Use "./configure --enable-maintainer-mode" to keep Makefile.in and Makefile dnl in sync after Git updates. AM_MAINTAINER_MODE -dnl PKG_PROG_PKG_CONFIG +dnl Some systems have older autotools without direct macro support for PKG_CONF* +have_PKG_CONFIG=yes +AC_PATH_PROG(dummy_PKG_CONFIG, pkg-config) +AS_IF([test x"$dummy_PKG_CONFIG" = xno || test -z "$dummy_PKG_CONFIG"], + [have_PKG_CONFIG=no], + [AC_MSG_NOTICE([checking for autoconf macro support of pkg-config]) + PKG_PROG_PKG_CONFIG + dummy_RES=$? + AS_IF([test $dummy_RES = 0], + [AC_MSG_NOTICE([checking for autoconf macro support of pkg-config module checker]) + PKG_CHECK_MODULES([dummy_PKG_CONFIG], [pkg-config], + [], [have_PKG_CONFIG=no]) + ], [have_PKG_CONFIG=no])] +) +AS_IF([test x"$have_PKG_CONFIG" = xno], + [AC_MSG_WARN([pkg-config is needed to look for further dependencies (will be skipped)])]) + dnl Various version related processing dnl ---------------------------------- @@ -132,8 +148,8 @@ dnl We need to relative-symlink some files. Or hardlink. Or copy... LN_S_R="cp -pR" if test "$as_ln_s" = "ln -s" ; then LN_S_R="ln" - DIR1="$(mktemp -d "dir1.XXXXX")" && \ - DIR2="$(mktemp -d "dir2.XXXXX")" && \ + DIR1="$(mktemp -d "dir1.XXXXXXX")" && \ + DIR2="$(mktemp -d "dir2.XXXXXXX")" && \ touch "${DIR1}/a" && \ $as_ln_s -r "${DIR1}/a" "${DIR2}/b" && \ ls -la "${DIR2}/b" | grep '\.\./' > /dev/null && \ @@ -311,16 +327,18 @@ dnl Solaris 10/11 USB handling (need librt and libusb runtime path) dnl HPUX, since v11, needs an explicit activation of pthreads case ${target_os} in solaris2.1* ) - echo Checking for Solaris 10 / 11 specific configuration for usb drivers + AC_MSG_CHECKING([for Solaris 10 / 11 specific configuration for usb drivers]) AC_SEARCH_LIBS(nanosleep, rt) LIBUSB_LIBS="-R/usr/sfw/lib ${LIBUSB_LIBS}" dnl FIXME: Sun's libusb doesn't support timeout (so blocks notification) dnl and need to call libusb close upon reconnection AC_DEFINE(SUN_LIBUSB, 1, [Define to 1 for Sun version of the libusb.]) SUN_LIBUSB=1 + AC_MSG_RESULT([${LIBUSB_LIBS}]) ;; hpux11*) CFLAGS="${CFLAGS} -lpthread" + ;; esac @@ -340,7 +358,7 @@ dnl checks related to --with-usb dnl ${nut_with_usb}: any value except "yes" or "no" is treated as "auto". if test "${nut_with_usb}" = "yes" -a "${nut_have_libusb}" != "yes"; then - AC_MSG_ERROR(["USB drivers requested, but libusb not found."]) + AC_MSG_ERROR([USB drivers requested, but libusb not found.]) fi if test "${nut_with_usb}" != "no"; then @@ -355,7 +373,7 @@ dnl checks related to --with-neon dnl ${nut_with_neon}: any value except "yes" or "no" is treated as "auto". if test "${nut_with_neon}" = "yes" -a "${nut_have_neon}" != "yes"; then - AC_MSG_ERROR(["neon libraries not found, required for neon based XML/HTTP driver"]) + AC_MSG_ERROR([neon libraries not found, required for neon based XML/HTTP driver]) fi if test "${nut_with_neon}" != "no"; then @@ -371,7 +389,7 @@ dnl checks related to --with-avahi dnl ${nut_with_avahi}: any value except "yes" or "no" is treated as "auto". if test "${nut_with_avahi}" = "yes" -a "${nut_have_avahi}" != "yes"; then - AC_MSG_ERROR(["avahi libraries not found"]) + AC_MSG_ERROR([avahi libraries not found]) fi if test "${nut_with_avahi}" != "no"; then @@ -387,7 +405,7 @@ dnl checks related to --with-powerman dnl ${nut_with_powerman}: any value except "yes" or "no" is treated as "auto". if test "${nut_with_powerman}" = "yes" -a "${nut_have_libpowerman}" != "yes"; then - AC_MSG_ERROR(["Powerman client libraries not found, required for Powerman PDU client driver"]) + AC_MSG_ERROR([Powerman client libraries not found, required for Powerman PDU client driver]) fi if test "${nut_with_powerman}" != "no"; then @@ -402,7 +420,7 @@ dnl checks related to --with-modbus dnl ${nut_with_modbus}: any value except "yes" or "no" is treated as "auto". if test "${nut_with_modbus}" = "yes" -a "${nut_have_libmodbus}" != "yes"; then - AC_MSG_ERROR(["modbus library not found, required for Modbus driver"]) + AC_MSG_ERROR([modbus library not found, required for Modbus driver]) fi if test "${nut_with_modbus}" != "no"; then @@ -428,15 +446,15 @@ if test "${nut_with_ipmi}" != "no"; then if test "${nut_with_freeipmi}" = "yes"; then NUT_CHECK_LIBFREEIPMI if test "${nut_have_freeipmi}" != "yes"; then - AC_MSG_ERROR(["FreeIPMI not found, required for IPMI support"]) + AC_MSG_ERROR([FreeIPMI not found, required for IPMI support]) fi dnl Implies --with-ipmi nut_with_ipmi="yes" dnl elif test "${nut_with_openipmi}" = "yes"; then - dnl AC_MSG_ERROR(["OpenIPMI is not yet supported"]) + dnl AC_MSG_ERROR([OpenIPMI is not yet supported]) dnl NUT_CHECK_LIBOPENIPMI dnl if test "${nut_have_openipmi}" != "yes"; then - dnl AC_MSG_ERROR(["OpenIPMI not found, required for IPMI support"]) + dnl AC_MSG_ERROR([OpenIPMI not found, required for IPMI support]) dnl fi dnl Implies --with-ipmi dnl nut_with_ipmi="yes" @@ -446,13 +464,13 @@ if test "${nut_with_ipmi}" != "no"; then NUT_CHECK_LIBFREEIPMI if test "${nut_have_freeipmi}" != "yes"; then if test "${nut_with_ipmi}" = "yes"; then - AC_MSG_ERROR(["FreeIPMI not found, required for IPMI support"]) + AC_MSG_ERROR([FreeIPMI not found, required for IPMI support]) fi nut_with_ipmi="no" dnl NUT_CHECK_OPENIPMI dnl if test "${nut_have_openipmi}" != "yes"; then dnl if test "${nut_with_ipmi}" = "yes"; then - dnl AC_MSG_ERROR(["GNU FreeIPMI and OpenIPMI neither found, required for IPMI support"]) + dnl AC_MSG_ERROR([Neither GNU FreeIPMI nor OpenIPMI was found (required for IPMI support)]) dnl fi dnl nut_with_ipmi="no" dnl else @@ -505,14 +523,30 @@ NUT_ARG_WITH([linux_i2c], [build and install i2c drivers], [auto]) if test "${nut_with_linux_i2c}" != no; then case ${target_os} in linux* ) + AC_CHECK_HEADER( + [linux/i2c-dev.h], + [AC_DEFINE([HAVE_LINUX_I2C_DEV_H], [1], + [Define to 1 if you have .])] + ) + AC_CHECK_HEADER( + [i2c/smbus.h], + [AC_DEFINE([HAVE_LINUX_SMBUS_H], [1], + [Define to 1 if you have .])] + ) AC_CHECK_DECLS( - [i2c_smbus_read_word_data, i2c_smbus_write_word_data, i2c_smbus_read_block_data], + [i2c_smbus_access, i2c_smbus_read_byte_data, i2c_smbus_write_byte_data, i2c_smbus_read_word_data, i2c_smbus_write_word_data, i2c_smbus_read_block_data], [nut_with_linux_i2c="yes"], [nut_with_linux_i2c="no"], [#include + #ifdef HAVE_LINUX_I2C_DEV_H #include + #endif + #ifdef HAVE_LINUX_SMBUS_H + #include + #endif ] ) + AC_SEARCH_LIBS([i2c_smbus_read_byte], [i2c]) ;; * ) nut_with_linux_i2c="no" @@ -544,12 +578,12 @@ if test "${nut_with_ssl}" != "no"; then if test "${nut_with_nss}" = "yes"; then NUT_CHECK_LIBNSS if test "${nut_have_libnss}" != "yes"; then - AC_MSG_ERROR(["Mozilla NSS not found, required for SSL support"]) + AC_MSG_ERROR([Mozilla NSS not found (required for SSL support)]) fi elif test "${nut_with_openssl}" = "yes"; then NUT_CHECK_LIBOPENSSL if test "${nut_have_openssl}" != "yes"; then - AC_MSG_ERROR(["OpenSSL not found, required for SSL support"]) + AC_MSG_ERROR([OpenSSL not found (required for SSL support)]) fi else dnl Prefer OpenSSL over NSS otherwise @@ -559,9 +593,9 @@ if test "${nut_with_ssl}" != "no"; then if test "${nut_have_libnss}" != "yes"; then dnl Only abort if SSL has been explicitly requested by the user if test "${nut_with_ssl}" = "yes"; then - AC_MSG_ERROR(["Mozilla NSS and OpenSSL neither found, but are needed for the requested SSL support"]) + AC_MSG_ERROR([Neither Mozilla NSS nor OpenSSL was found, but one is needed for the requested SSL support.]) else - AC_MSG_WARN(["Mozilla NSS and OpenSSL neither found, required for SSL support"]) + AC_MSG_WARN([Neither Mozilla NSS nor OpenSSL was found (required for SSL support)]) fi nut_with_ssl="no" else @@ -591,7 +625,7 @@ if test "${nut_with_wrap}" != "no"; then fi if test "${nut_with_wrap}" = "yes" -a "${nut_have_libwrap}" != "yes"; then - AC_MSG_ERROR(["libwrap not found"]) + AC_MSG_ERROR([libwrap not found]) fi if test "${nut_with_wrap}" != "no"; then @@ -614,7 +648,7 @@ if test "${nut_with_libltdl}" != "no"; then fi if test "${nut_with_libltdl}" = "yes" -a "${nut_have_libltdl}" != "yes"; then - AC_MSG_ERROR(["libltdl not found"]) + AC_MSG_ERROR([libltdl not found]) fi if test "${nut_with_libltdl}" != "no"; then @@ -814,12 +848,12 @@ dnl not fail if we have no tools to generate it (so add to SKIP list). else DOC_SKIPBUILD_LIST="${DOC_SKIPBUILD_LIST} ${nut_doc_build_target_base}" if test "${nut_doc_build_target_flag}" = "auto" ; then -dnl Test that groff files exist (building from dist'ed tarball, not git repo) +dnl Test that groff files exist (building from distributed tarball, not git repo) if test -s "${abs_srcdir}"/docs/man/snmp-ups.8 ; then - AC_MSG_WARN([Unable to build ${nut_doc_build_target_base} documentation, but can install pre-built dist'ed copies]) + AC_MSG_WARN([Unable to build ${nut_doc_build_target_base} documentation, but can install pre-built distributed copies]) DOC_INSTALL_DISTED_MANS="yes" else - AC_MSG_WARN([Unable to build ${nut_doc_build_target_base} documentation, and unable to install pre-built dist'ed copies because they are absent]) + AC_MSG_WARN([Unable to build ${nut_doc_build_target_base} documentation, and unable to install pre-built distributed copies because they are absent]) fi fi # Other variants include "no", "skip"... fi @@ -1071,9 +1105,9 @@ AC_MSG_RESULT(${RUN_AS_GROUP}) dnl check that --with-user is given if --with-group is given. if test "${nut_user_given}" = "yes" -a "${nut_group_given}" = "no"; then - AC_MSG_ERROR(["If you specify --with-user, you also must specify --with-group"]) + AC_MSG_ERROR([If you specify --with-user, you also must specify --with-group]) elif test "${nut_user_given}" = "no" -a "${nut_group_given}" = "yes"; then - AC_MSG_ERROR(["If you specify --with-group, you also must specify --with-user"]) + AC_MSG_ERROR([If you specify --with-group, you also must specify --with-user]) fi AC_MSG_CHECKING(facility for syslog) @@ -1180,7 +1214,90 @@ else fi AM_CONDITIONAL(WITH_PKG_CONFIG, test -n "${pkgconfigdir}") -PKG_PROG_PKG_CONFIG +AC_MSG_CHECKING(whether to install Solaris SMF files) +solarissmf="auto" +AC_ARG_WITH([solaris-smf], + AS_HELP_STRING([--with-solaris-smf=(yes|auto|no)], [Enable installation of NUT scripts and manifests for Solaris Service Management Framework (auto)]), +[ + case "${withval}" in + auto|"") + solarissmf="auto" + ;; + yes|no) + solarissmf="${withval}" + ;; + *) + AC_MSG_ERROR([Unexpected argument for --with-solaris-smf=${withval}]) + ;; + esac +], []) + +if test x"$solarissmf" = xauto ; then + if test -x /usr/sbin/svcadm && test -x /usr/sbin/svccfg && test -x /usr/bin/svcs ; then + solarissmf="yes" + else + solarissmf="no" + fi +fi +AC_MSG_RESULT([${solarissmf}]) +AM_CONDITIONAL(WITH_SOLARIS_SMF, test x"$solarissmf" = x"yes") + +AC_MSG_CHECKING(whether to make Solaris SVR4 packages) +solarispkg_svr4="auto" +AC_ARG_WITH([solaris-pkg-svr4], + AS_HELP_STRING([--with-solaris-pkg-svr4=(yes|auto|no)], [Enable construction of Solaris SVR4 packages (auto)]), +[ + case "${withval}" in + auto|"") + solarispkg_svr4="auto" + ;; + yes|no) + solarispkg_svr4="${withval}" + ;; + *) + AC_MSG_ERROR([Unexpected argument for --with-solaris-pkg-svr4=${withval}]) + ;; + esac +], []) + +if test x"$solarispkg_svr4" = xauto ; then + if test -x /usr/bin/pkgtrans && test -x /usr/bin/pkgmk && test -x /usr/bin/pkgproto ; then + solarispkg_svr4="yes" + else + solarispkg_svr4="no" + fi +fi +AC_MSG_RESULT([${solarispkg_svr4}]) +AM_CONDITIONAL(WITH_SOLARIS_PKG_SVR4, test x"$solarispkg_svr4" = x"yes") + +AC_MSG_CHECKING(whether to make Solaris IPS packages) +solarispkg_ips="auto" +AC_ARG_WITH([solaris-pkg-ips], + AS_HELP_STRING([--with-solaris-pkg-ips=(yes|auto|no)], [Enable construction of Solaris IPS packages (auto)]), +[ + case "${withval}" in + auto|"") + solarispkg_ips="auto" + ;; + yes|no) + solarispkg_ips="${withval}" + ;; + *) + AC_MSG_ERROR([Unexpected argument for --with-solaris-pkg-ips=${withval}]) + ;; + esac +], []) + +if test x"$solarispkg_ips" = xauto ; then + if test -x /usr/bin/pkg && test -x /usr/bin/pkgmogrify && test -x /usr/bin/pkgdepend ; then + solarispkg_ips="yes" + else + solarispkg_ips="no" + fi +fi +AC_MSG_RESULT([${solarispkg_ips}]) +AM_CONDITIONAL(WITH_SOLARIS_PKG_IPS, test x"$solarispkg_ips" = x"yes") + AC_MSG_CHECKING(whether to install systemd files) AC_ARG_WITH([systemdsystemunitdir], AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files (auto)]), @@ -1229,47 +1346,57 @@ dnl # Could use `AX_CXX_COMPILE_STDCXX_11([noext], [optional])` if it were dnl # available everywhere. Or AX_CHECK_COMPILE_FLAG if it was ubiquitous: dnl ###AX_CHECK_COMPILE_FLAG([-std=c++11], dnl ### [CXXFLAGS="$CXXFLAGS -std=c++11" -dnl ### HAVE_CXX11=1], -dnl ### [HAVE_CXX11=0]) +dnl ### have_cxx11=yes], +dnl ### [have_cxx11=no]) AC_MSG_CHECKING(for C++11 support in current compiler) +have_cxx11=unknown my_CXXFLAGS="$CXXFLAGS" AC_LANG_PUSH([C++]) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +CPLUSPLUS_DECL=' #include #if __cplusplus < 201103L #error This library needs at least a C++11 compliant compiler #endif -]], [[printf("%ld\n", __cplusplus);]]) -], +' +CPLUSPLUS_MAIN='printf("%ld\n", __cplusplus);' + +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[${CPLUSPLUS_DECL}]], [[${CPLUSPLUS_MAIN}]])], [AC_MSG_RESULT([yes, out of the box]) - HAVE_CXX11=1], + have_cxx11=yes], [CXXFLAGS="$CXXFLAGS -std=c++11" - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ -#include -#if __cplusplus < 201103L - #error This library needs at least a C++11 compliant compiler -#endif - ]], [[printf("%ld\n", __cplusplus);]]) - ], - [AC_MSG_RESULT([yes, GCC-style]) - HAVE_CXX11=1], + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[${CPLUSPLUS_DECL}]], [[${CPLUSPLUS_MAIN}]])], + [AC_MSG_RESULT([yes, GCC-style (as C++11)]) + have_cxx11=yes], + [CXXFLAGS="$CXXFLAGS -std=c++0x" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[${CPLUSPLUS_DECL}]], [[${CPLUSPLUS_MAIN}]])], + [AC_MSG_RESULT([yes, GCC-style (as C++0X)]) + have_cxx11=yes], [AC_MSG_RESULT([no]) CXXFLAGS="$my_CXXFLAGS" - HAVE_CXX11=0])]) + have_cxx11=no])])]) +AM_CONDITIONAL(HAVE_CXX11, test "${have_cxx11}" = "yes") AC_LANG_POP([C++]) +unset CPLUSPLUS_MAIN +unset CPLUSPLUS_DECL have_cppunit="no" CPPUNIT_NUT_CXXFLAGS="" -AS_IF([test "${HAVE_CXX11}" = 1], - [PKG_CHECK_MODULES(CPPUNIT, cppunit, have_cppunit=yes, have_cppunit=no) - if test "${have_cppunit}" != "yes" ; then - AC_MSG_WARN([libcppunit not found - those C++ tests will not be built.]) - else - AS_IF([test -n "$CXX"],[AS_IF([$CXX --version 2>&1 | grep 'Free Software Foundation' > /dev/null], - [CPPUNIT_NUT_CXXFLAGS="-g -O0"])]) - fi]) +AS_IF([test x"$have_PKG_CONFIG" = xyes], + [AS_IF([test x"${have_cxx11}" = xyes], + [PKG_CHECK_MODULES(CPPUNIT, cppunit, have_cppunit=yes, have_cppunit=no) + AS_IF([test "${have_cppunit}" != "yes"], + [AC_MSG_WARN([libcppunit not found - those C++ tests will not be built.]) + have_cppunit=no], + [AS_IF([test -n "$CXX"], + [AS_IF([$CXX --version 2>&1 | grep 'Free Software Foundation' > /dev/null], + [CPPUNIT_NUT_CXXFLAGS="-g -O0"])]) + ]) + ]) + ], [AC_MSG_WARN([pkg-config not found, can not look properly for libcppunit - those C++ tests will not be built.]) + have_cppunit=no] +) AM_CONDITIONAL(HAVE_CPPUNIT, test "${have_cppunit}" = "yes") AC_DEFINE_UNQUOTED(CPPUNIT_NUT_CXXFLAGS, $CPPUNIT_NUT_CXXFLAGS, [Compiler flags for cppunit tests]) @@ -1281,7 +1408,7 @@ AC_ARG_WITH(augeas-lenses-dir, yes) if test -z "${auglensdir}"; then AC_MSG_RESULT(no) - AC_MSG_ERROR(["augeas lenses directory requested but not found in default location"]) + AC_MSG_ERROR([augeas lenses directory requested but not found in default location]) fi ;; auto) @@ -1301,6 +1428,16 @@ else fi AM_CONDITIONAL(WITH_AUGLENS, test -n "${auglensdir}") +AC_PATH_PROGS([AUGPARSE], [augparse], [none]) +AM_CONDITIONAL([HAVE_AUGPARSE], [test "x${AUGPARSE}" != "xnone"]) +AC_MSG_CHECKING([whether to enable Augeas configuration-management lenses tests]) +if test "x${AUGPARSE}" != xnone ; then + AC_MSG_RESULT(yes) +else + AC_MSG_RESULT(no) +fi + + AC_MSG_CHECKING(whether to install hotplug rules) AC_ARG_WITH(hotplug-dir, AS_HELP_STRING([--with-hotplug-dir=PATH], [where to install hotplug rules (/etc/hotplug)]), @@ -1309,7 +1446,7 @@ AC_ARG_WITH(hotplug-dir, yes) if test -z "${hotplugdir}"; then AC_MSG_RESULT(no) - AC_MSG_ERROR(["hotplug directory requested but not found"]) + AC_MSG_ERROR([hotplug directory requested but not found]) fi ;; auto) @@ -1337,7 +1474,7 @@ AC_ARG_WITH(udev-dir, yes) if test -z "${udevdir}"; then AC_MSG_RESULT(no) - AC_MSG_ERROR(["udev directory requested but not found"]) + AC_MSG_ERROR([udev directory requested but not found]) fi ;; auto) @@ -1367,7 +1504,7 @@ AC_ARG_WITH(devd-dir, yes) if test -z "${devddir}"; then AC_MSG_RESULT(no) - AC_MSG_ERROR(["devd directory requested but not found"]) + AC_MSG_ERROR([devd directory requested but not found]) fi ;; auto) @@ -1406,7 +1543,7 @@ AC_ARG_WITH(valgrind, yes) if test "x$VALGRIND" = "xnone"; then AC_MSG_RESULT(no) - AC_MSG_ERROR(["valgrind requested but not found"]) + AC_MSG_ERROR([valgrind requested but not found]) fi with_valgrind="yes" ;; @@ -1420,7 +1557,7 @@ AC_ARG_WITH(valgrind, AC_PATH_PROGS([VALGRIND], ["${withval}"], [none]) if test "x$VALGRIND" = "xnone"; then AC_MSG_RESULT(no) - AC_MSG_ERROR(["valgrind requested but not found"]) + AC_MSG_ERROR([valgrind requested but not found]) fi with_valgrind="yes" ;; @@ -1451,7 +1588,9 @@ else AC_MSG_RESULT(no) fi -dnl expand ${sysconfdir} and write it out +dnl expand ${sysconfdir} and write it out - note that most packages +dnl override it to be /etc/nut, /etc/ups or similar, while the +dnl autotools default would be $prefix/etc conftemp="${sysconfdir}" eval conftemp=\"${conftemp}\" eval conftemp=\"${conftemp}\" @@ -1463,6 +1602,7 @@ conftemp="${datadir}" eval conftemp=\"${conftemp}\" eval conftemp=\"${conftemp}\" DATADIR=${conftemp} +NUT_DATADIR=${conftemp} AC_DEFINE_UNQUOTED(DATADIR, "${conftemp}", [Default path for data files]) dnl same for bindir @@ -1486,12 +1626,19 @@ eval conftemp=\"${conftemp}\" LIBDIR=${conftemp} AC_DEFINE_UNQUOTED(LIBDIR, "${conftemp}", [Default path for system libraries]) +dnl same for libexecdir +conftemp="${libexecdir}" +eval conftemp=\"${conftemp}\" +eval conftemp=\"${conftemp}\" +LIBEXECDIR=${conftemp} +AC_DEFINE_UNQUOTED(LIBEXECDIR, "${conftemp}", [Default path for system exec-libraries]) + dnl checks related to --with-snmp enabled on command-line dnl ${nut_with_snmp}: any value except "yes" or "no" is treated as "auto". if test "${nut_with_snmp}" = "yes" -a "${nut_have_libnetsnmp}" != "yes"; then - AC_MSG_ERROR(["Net-SNMP libraries not found, required for SNMP drivers"]) + AC_MSG_ERROR([Net-SNMP libraries not found, required for SNMP drivers]) fi if test "${nut_with_snmp}" != "no"; then @@ -1546,6 +1693,7 @@ AC_SUBST(TREE_VERSION) AC_SUBST(NUT_NETVERSION) AC_SUBST(LIBSSL_CFLAGS) AC_SUBST(LIBSSL_LIBS) +AC_SUBST(LIBSSL_REQUIRES) AC_SUBST(LIBGD_CFLAGS) AC_SUBST(LIBGD_LDFLAGS) AC_SUBST(LIBNETSNMP_CFLAGS) @@ -1577,6 +1725,8 @@ AC_SUBST(STATEPATH) AC_SUBST(CONFPATH) AC_SUBST(BINDIR) AC_SUBST(LIBDIR) +AC_SUBST(NUT_DATADIR, [`eval echo "${DATADIR}"`]) +AC_SUBST(NUT_LIBEXECDIR, [`eval echo "${LIBEXECDIR}"`]) AC_SUBST(DRVPATH) AC_SUBST(SBINDIR) AC_SUBST(PORT) @@ -1630,19 +1780,35 @@ AC_OUTPUT([ scripts/devd/nut-usb.conf scripts/hotplug/Makefile scripts/hotplug/libhidups + scripts/Aix/nut.init scripts/HP-UX/nut.psf scripts/HP-UX/postinstall scripts/python/Makefile + scripts/upsdrvsvcctl/Makefile + scripts/upsdrvsvcctl/nut-driver-enumerator.sh + scripts/upsdrvsvcctl/upsdrvsvcctl scripts/systemd/Makefile - scripts/systemd/nut-driver.service + scripts/systemd/nut-driver@.service scripts/systemd/nut-monitor.service scripts/systemd/nut-server.service + scripts/systemd/nut-driver-enumerator.service + scripts/systemd/nut-driver-enumerator.path scripts/systemd/nutshutdown + scripts/Solaris/nut-driver-enumerator.xml + scripts/Solaris/nut-driver.xml + scripts/Solaris/nut-monitor.xml + scripts/Solaris/nut-server.xml + scripts/Solaris/nut.xml + scripts/Solaris/svc-nut-server + scripts/Solaris/svc-nut-monitor scripts/Solaris/Makefile scripts/Solaris/pkginfo + scripts/Solaris/preinstall scripts/Solaris/postinstall scripts/Solaris/preremove - scripts/Solaris/nut + scripts/Solaris/postremove + scripts/Solaris/preproto.pl + scripts/Solaris/nut scripts/udev/Makefile scripts/udev/nut-ipmipsu.rules scripts/udev/nut-usbups.rules diff --git a/data/cmdvartab b/data/cmdvartab index e807661529..b748914544 100644 --- a/data/cmdvartab +++ b/data/cmdvartab @@ -94,6 +94,7 @@ VARDESC output.current "Output current (A)" VARDESC output.current.nominal "Nominal output current (A)" VARDESC battery.charge "Battery charge (percent of full)" +VARDESC battery.charge.approx "Rough approximation of battery charge" VARDESC battery.charge.low "Remaining battery level when UPS switches to LB (percent)" VARDESC battery.charge.restart "Minimum battery level for restart after power off (percent)" VARDESC battery.charge.warning "Battery level when UPS switches to Warning state (percent)" diff --git a/data/driver.list.in b/data/driver.list.in index b5a315e08c..2c9d8bda8d 100644 --- a/data/driver.list.in +++ b/data/driver.list.in @@ -348,6 +348,8 @@ "Electrys" "ups" "2" "UPS 2500" "" "nutdrv_qx or blazer_ser" +"Emerson" "pdu" "3" "PM3000 metered & switched" "" "snmp-ups" + "Energy Sistem" "ups" "2" "(various)" "" "blazer_ser" "ETA" "ups" "1" "mini+UPS" "WinNT/Upsoft cable" "genericups upstype=7" @@ -446,6 +448,8 @@ "HP" "ups" "4" "Various (SNMP mode)" "HP UPS Management Module" "snmp-ups" "HP" "pdu" "1" "HP3488 Switch/Control Unit" "" "powerman-pdu (experimental)" +"HPE" "pdu" "5" "Various (SNMP mode)" "" "snmp-ups" + "Huawei" "ups" "4" "UPS5000-E" "" "snmp-ups" "IBM" "ups" "5" "Various" "USB port" "usbhid-ups" @@ -859,6 +863,7 @@ "PowerWalker" "ups" "2" "Line-Interactive VI 850 LCD" "" "blazer_usb" "PowerWalker" "ups" "2" "Online VFI 1000RT/1500RT/2000RT/3000RT/6000RT/10000RT LCD" "" "blazer_usb" "PowerWalker" "ups" "2" "Line-Interactive VI 1000RT/1500RT/2000RT/3000RT LCD" "" "blazer_usb" +"PowerWalker" "ups" "2" "VFI 1000 CG PF1" "" "nutdrv_qx" # https://powerwalker.com/?page=product&item=10122108&lang=en "Powerware" "ups" "4" "3110" "" "genericups upstype=7" "Powerware" "ups" "4" "3115" "" "genericups upstype=11" @@ -939,6 +944,9 @@ "Rucelf" "ups" "2" "Rucelf UPOII-3000-96-EL" "" "blazer_ser" # http://www.rucelf.ua/en/catalog/upoii-3000-96-el/ +"Siemens" "ups" "4" "SITOP UPS500" "serial" "nutdrv_siemens_sitop (experimental, untested)" +"Siemens" "ups" "4" "SITOP UPS500" "USB" "nutdrv_siemens_sitop (experimental)" + "SmartLabs" "pdu" "1" "2412S Power Line Modem" "for X10/Insteon" "powerman-pdu (experimental)" "SMS (Brazil)" "ups" "2" "Manager III" "" "blazer_ser" diff --git a/docs/FAQ.txt b/docs/FAQ.txt index 6649bed64b..21f0c372a3 100644 --- a/docs/FAQ.txt +++ b/docs/FAQ.txt @@ -4,8 +4,8 @@ NUT Frequently Asked Questions endif::external_title[] == I just upgraded, and ... -You have read link:UPGRADING[UPGRADING] in the base directory of the distribution, -right? +You have read link:UPGRADING[UPGRADING] in the base directory of the +distribution, right? If not, go read it now, then come back to this file if your question wasn't answered in there. @@ -38,7 +38,7 @@ already been done in the old version. The drivers drop root privileges long before the serial port is opened. You'll need to change the permissions on that port so that -their new user id can access it. Normally this is "nobody", but it +their new user id can access it. Normally this is "nobody", but it may be changed at compile-time by using configure --with-user. Read the error message. If you have a permissions mismatch, then @@ -47,12 +47,12 @@ you'll see something like this: Network UPS Tools - APC Smart protocol driver 0.60 (1.1.7) This program is currently running as youruid (UID 1234) /dev/ttyS2 is owned by user root (UID 0), mode 0600 - Change the port name, or fix the permissions or ownership + Change the port name, or fix the permissions or ownership of /dev/ttyS2 and try again. Unable to open /dev/ttyS2: Permission denied Now is a good time to point out that using "nobody" is a bad idea, -since it's a hack for NFS access. You should create a new role +since it's a hack for NFS access. You should create a new role account (perhaps called "ups" or "nut"), and use that instead. Also, scroll down to the "security domains" question to see an @@ -88,16 +88,16 @@ Refer to the upsd(8) and upsd.conf(5) manpages for more information. == I get a 'not listening on...' error from upsd. -Verify your LISTEN directive. It should be one of the valid IP addresses for -the computer running upsd (or 0.0.0.0, which is INADDR_ANY), not an address for -a client. +Verify your LISTEN directive. It should be one of the valid IP addresses +for the computer running `upsd` (or `0.0.0.0`, which is `INADDR_ANY`), not +an address for a client. -The LISTEN directive lets you pick which interface upsd listens on. If you are -trying to limit the clients which can connect to upsd, you either need to use -tcp-wrappers or kernel firewall rules. +The LISTEN directive lets you pick which interface `upsd` listens on. +If you are trying to limit the clients which can connect to `upsd`, +you either need to use tcp-wrappers or kernel firewall rules. -This isn't a NUT-specific limitation - it applies equally to your web server or -mailer daemon. +This isn't a NUT-specific limitation -- it applies equally to your web server +or mailer daemon. == Which UPS should I buy? @@ -112,13 +112,13 @@ hardware for testing, results of their testing efforts, or protocol specifications. We try to publish this information on the NUT website, so you can take this into consideration when selecting an UPS brand. -== I have an APC Smart-UPS connected with a grey APC serial cable and it won't work. +== I have an APC Smart-UPS connected with a grey APC serial cable and it won't work. The Back-UPS type in the genericups driver works but then I don't get to use all the nifty features in there. Why doesn't the right driver work? The problem lies in your choice of cable. APC's grey cables -generally only do "dumb" signalling - very basic yes/no info about +generally only do "dumb" signalling -- very basic yes/no info about the battery and line status. While that is sufficient to detect a low battery condition while on battery, you miss out on all the goodies that you paid for. @@ -138,9 +138,10 @@ If your grey cable isn't the 940-0095B, the solution is to dump that cable and find one that supports APC's "smart" signalling. Typically these come with the UPS and are black. If your smart cable has wandered off, one can be built rather easily with some connectors and -cable - there's no fancy wiring or resistors. +cable -- there's no fancy wiring or resistors. -See this URL for a handy diagram: http://www.networkupstools.org/cables/940-0024C.jpg +See this URL for a handy diagram: +http://www.networkupstools.org/cables/940-0024C.jpg There is also a text version of that diagram in the docs/cables directory of the NUT source distribution. Either one should allow @@ -185,7 +186,7 @@ If this really bothers you, roll up your sleeves and use the sockdebug code to write a "upsmon" type program that sits on top of the state sockets. It won't work over the network, but it means you don't need upsd. It also means only one host can monitor the -UPS. +UPS. This is also a good option to consider if you can't use networked monitoring code for security or safety reasons. @@ -206,7 +207,7 @@ It is also coherent with the answer to the previous question. *Answer 1* New versions of the init man page taken from the sysvinit package -are saying that usage of SIGPWR is discouraged, since /dev/initctl +are saying that usage of SIGPWR is discouraged, since /dev/initctl control channel is the preferred way of communication. *Answer 2* @@ -253,16 +254,16 @@ directly affects how long you run on battery without knowing what's going on with the UPS. Note: some drivers occasionally need more time to update than the -default value of MAXAGE (in upsd.conf) allows. As a result, they +default value of MAXAGE (in upsd.conf) allows. As a result, they are temporarily marked stale even though everything is fine. This -can happen with MGE Ellipse equipment - see the mge-shut or usbhid-ups man +can happen with MGE Ellipse equipment -- see the mge-shut or usbhid-ups man pages. In such cases, you can raise the value of MAXAGE to avoid these warnings; try a value like 25 or 30. == Why do the client programs say 'Driver not connected' when I try to run them? This means that upsd can't connect to the driver for some reason. -Your ups.conf entry might be wrong, or the driver might not be +Your ups.conf entry might be wrong, or the driver might not be running. Maybe your state path is not configured properly. Check your syslog. upsd will complain regularly if it can't @@ -272,6 +273,12 @@ Note: if you jumped in with both feet and didn't follow the INSTALL.nut document, you probably started upsd by itself. You have to run 'upsdrvctl start' to start the drivers after configuring ups.conf. +On operating systems with a supported service management framework, +you might wrap your NUT drivers into individual services instances +with 'upsdrvsvcctl resync' and then manage those with commands like +'upsdrvsvcctl stop' and 'upsdrvsvcctl start' (note that on other +systems this tool may be not pre-installed via packaging). + == Why don't the pathnames in your documentation match the package I installed? Each distribution has conventions for where specific file types should be @@ -302,7 +309,7 @@ might look like this: if (test -f /etc/killpower) then - /usr/local/ups/sbin/upsdrvctl shutdown + /sbin/upsdrvctl shutdown sleep 600 # this should never return @@ -323,8 +330,8 @@ things depending on what's supported: - Set a jumper on the motherboard that means "return after outage" - Set something in the BIOS that says "power up after power failure" -- Try using something (like a capacitor) across the power button - to "push" it for you - this might not work if it needs a delay +- Try using something (like a capacitor) across the power button + to "push" it for you -- this might not work if it needs a delay - Hack the cable between the power supply and the motherboard to fool it into powering up whenever line power is present - Teach a monkey to watch the machine and press the power button @@ -363,11 +370,11 @@ use of `setpci`, and are highly model-specific: - http://superuser.com/questions/212434/reboot-after-power-failure-for-mac-running-ubuntu - http://ubuntuforums.org/showthread.php?t=1209576 -Note: this question has been in the FAQ for several years now, and +Note: this question has been in the FAQ for several years now, and there's still no clean answer. Let me guess: everyone who runs a server on Mac hardware has a team of trained monkeys, and feeds them by growing bananas in the tropical environment formed by waste heat -from the equipment. +from the equipment. The rest of us are still waiting for the answer. Booting into the Mac OS to frob the "file server" panel is not an acceptable @@ -404,7 +411,7 @@ For my development system this yields the following /dev entries: - Switch to root, then start the drivers: - # /usr/local/ups/sbin/upsdrvctl -u nutdev start + # upsdrvctl -u nutdev start - The listing for /var/state/ups then looks like this: @@ -428,7 +435,7 @@ make the files owned by root.nut, with mode 0640. Once the config files are ready, start upsd: - # /usr/local/ups/sbin/upsd -u nutsrv + # upsd -u nutsrv Check your syslog to be sure everything's happy, then be sure to update your startup scripts so it uses this procedure on your next @@ -445,12 +452,12 @@ to that one user account. Direct access to the serial device is not possible, since that is owned by another user. There is also the possibility of running the drivers and upsd in a -chroot jail. See the chroot.txt provided in the source -distribution for an example implementation. +chroot jail. See the chroot.txt provided in the source +distribution for an example implementation. Why give would-be vandals any sort of help? -Put it this way - I *wrote* good chunks of this stuff, and I still +Put it this way -- I *wrote* good chunks of this stuff, and I still run the programs this way locally. You should definitely consider using this technique. @@ -490,14 +497,14 @@ service by bringing down the box. See upssched.txt for information on how you can shutdown early if this is what you really want to do. -== The CGI programs report 'access to that host is not authorized' - what's going on? +== The CGI programs report 'access to that host is not authorized' -- what's going on? Those programs need to see a host in your hosts.conf before they will attempt communications. This keeps people from feeding it random "host=" settings, which would annoy others with outgoing connection attempts from your system. -If your hosts.conf turns out to be configured correctly with +If your hosts.conf turns out to be configured correctly with MONITOR entries and all that, check the permissions. Your web server may be running the CGI programs as a user that can't read the file. @@ -505,7 +512,7 @@ the file. If you run your web server in a chroot jail, make sure the programs can still read hosts.conf. You may have to copy it into the jail for this to work. If you do that, make sure it's not writable by -any of the user accounts which run inside the jail. +any of the user accounts which run inside the jail. == upsd is running, so why can't I connect to it? @@ -546,8 +553,9 @@ http://www.networkupstools.org/stable-hcl.html?connection=USB == My USB UPS is supported but doesn't work! -On Linux, udev rules are provided to set the correct permissions on device file. -This allows the NUT driver to communicate with the UPS, through this device file. +On Linux, udev rules are provided to set the correct permissions on device +file. This allows the NUT driver to communicate with the UPS, through this +device file. However, the driver may still fail to start and support the device, with a message like: @@ -635,7 +643,7 @@ incidentally what the official FreeBSD port of NUT does for all builds. == I have 'some problem' with 'some old version' ... Get the latest stable release, and see if it still happens. If it -goes away, it means someone else reported it and got it fixed a +goes away, it means someone else reported it and got it fixed a long time ago. You may want to search the mailing lists to see if someone else has @@ -645,7 +653,7 @@ into your distribution (potentially with unofficial packages). Some OS distributions contain old versions of NUT. If your hardware is newer than the NUT release, there is a good chance that support has not been added -yet. Please do not tell us you have the "latest version for Distro XYZ" - even +yet. Please do not tell us you have the "latest version for Distro XYZ" -- even if the developers are familiar with that distribution, it helps others if you quote the exact package version. @@ -673,7 +681,7 @@ and also SNMP and XML/HTTP (Eaton and MGE) communications. Since NUT is very extensible, support for a new communication bus can be added easily. - + Any time there is a gap in features, it's usually because the group of people who own that hardware and the group of people who write code don't overlap. The fix is to make them overlap - @@ -705,7 +713,7 @@ has already handled it successfully. == I replaced the battery in my APC Smart-UPS and now it thinks the battery is low all the time. How do you fix this? Or a variation like... - + == My APC UPS keeps reporting 'OL LB', even after it's been charging for many hours. What can I do about this? This happened to me, and some other people too. The combination of @@ -723,7 +731,7 @@ disconnect it from the computer so this software won't shut it down. The easiest way to do this is to first unplug your computer(s) from -it, and plug in a token load like a lamp. Also, move the UPS to a +it, and plug in a token load like a lamp. Also, move the UPS to a power strip that doesn't switch the ground line or an outlet that you can switch off at your panel. @@ -793,7 +801,7 @@ It's a kind of Magic. It's both that and a frequently *anticipated* questions file, too. The idea is to write it up in here so that nobody asks the mailing -list when it finally does get released. +list when it finally does get released. == My UPS powers up immediately after a power failure instead of waiting for the batteries to recharge! @@ -812,8 +820,8 @@ where there's not enough battery capacity left for upsmon to do its thing. Exactly how long to wait is a function of your UPS hardware, and will require careful testing. -If this is too evil for you, buy another kind of UPS that will either wait for a -minimum amount of charge, a minimum amount of time, or both. +If this is too evil for you, buy another kind of UPS that will either wait for +a minimum amount of charge, a minimum amount of time, or both. == I'm facing a power race Or a variation like... @@ -840,7 +848,7 @@ Implement this by modifying your shutdown script like this: if (test -f /etc/killpower) then - /usr/local/ups/sbin/upsdrvctl shutdown + /sbin/upsdrvctl shutdown sleep 120 diff --git a/docs/Makefile.am b/docs/Makefile.am index cb04e88ea7..ede141b5d9 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -40,7 +40,8 @@ CABLES_IMAGES = images/cables/73-0724.png images/cables/940-0024C.jpg \ ALL_TXT_SRC = nut-names.txt daisychain.txt \ $(USER_MANUAL_DEPS) $(DEVELOPER_GUIDE_DEPS) \ - $(CABLES_DEPS) FAQ.txt nut-qa.txt packager-guide.txt snmp.txt + $(CABLES_DEPS) FAQ.txt nut-qa.txt packager-guide.txt snmp.txt \ + solaris-usb.txt NUT_SPELL_DICT = nut.dict EXTRA_DIST += $(ALL_TXT_SRC) $(SHARED_DEPS) $(IMAGE_FILES) \ @@ -50,18 +51,21 @@ EXTRA_DIST += $(ALL_TXT_SRC) $(SHARED_DEPS) $(IMAGE_FILES) \ ASCIIDOC_HTML_SINGLE = user-manual.html \ developer-guide.html \ packager-guide.html \ + solaris-usb.html \ cables.html \ FAQ.html ASCIIDOC_HTML_CHUNKED = user-manual.chunked \ developer-guide.chunked \ packager-guide.chunked \ + solaris-usb.chunked \ cables.chunked \ FAQ.chunked ASCIIDOC_PDF = user-manual.pdf \ developer-guide.pdf \ packager-guide.pdf \ + solaris-usb.pdf \ cables.pdf \ FAQ.pdf @@ -91,6 +95,7 @@ FULL_DEVELOPER_GUIDE_DEPS = $(DEVELOPER_GUIDE_DEPS) $(SHARED_DEPS) \ user-manual.html user-manual.chunked user-manual.pdf: $(FULL_USER_MANUAL_DEPS) developer-guide.html developer-guide.chunked developer-guide.pdf: $(FULL_DEVELOPER_GUIDE_DEPS) packager-guide.html packager-guide.chunked packager-guide.pdf: packager-guide.txt asciidoc.conf +solaris-usb.html solaris-usb.chunked solaris-usb.pdf: solaris-usb.txt asciidoc.conf # Note: without the "-v", asciidoc (circa 8.6.2) sometimes hangs when # generating the chunked HTML. In this case, export the environment diff --git a/docs/acknowledgements.txt b/docs/acknowledgements.txt index ce1c03a497..49083d57ee 100644 --- a/docs/acknowledgements.txt +++ b/docs/acknowledgements.txt @@ -53,7 +53,7 @@ blazer_ser and blazer_usb - Martin Loyer: has worked a bit on mge-utalk - Jonathan Dion: MGE internship (summer 2006), who has worked on configuration - Doug Reynolds: has worked on CyberPower support (powerpanel driver) -- Jon Gough: has worked on porting the megatec driver to USB (megatec_usb) +- Jon Gough: has worked on porting the megatec driver to USB (megatec_usb) - Dominique Lallement: Consultant (chairman of the USB/HID PDC Forum) - Julius Malkiewicz: junior developer - Tomas Smetana: former Redhat packager (2007-2008) @@ -93,8 +93,8 @@ revived the 'sec' driver (as gamatronic), and expanded a bit genericups for its UPSs with alarm interface. * link:http://www.microdowell.com[Microdowell], through Elio Corbolante, has -created the 'microdowell' driver to support the Enterprise Nxx/Bxx serial devices. -They also proposes NUT as an alternative to its software for +created the 'microdowell' driver to support the Enterprise Nxx/Bxx serial +devices. The company also proposes NUT as an alternative to its software for link:http://www.microdowell.com/fra/download.html[Linux / Unix]. * link:http://pcmups.com.tw[Powercom], through Alexey Morozov, has provided @@ -144,20 +144,21 @@ the libhid projects, ... through Arnaud Quette (who was also an MGE employee). All the MGE supporters have gone with Eaton (through MGE Office Protection Systems), which was temporarily the new NUT sponsor. -- Fenton Technologies contributed a PowerPal 660 to the project. Their open -stance and quick responses to technical inquiries were appreciated for +- Fenton Technologies contributed a PowerPal 660 to the project. Their open +stance and quick responses to technical inquiries were appreciated for making the development of the fentonups driver possible. -Fenton has since been acquired by link:http://www.metapo.com[Metapo]. +Fenton has since been acquired by link:http://www.metapo.com[Metapo]. -- Bo Kersey of link:http://www.vircio.com[VirCIO] provided a Best Power Fortress -750 to facilitate the bestups driver. +- Bo Kersey of link:http://www.vircio.com[VirCIO] provided a Best Power +Fortress 750 to facilitate the bestups driver. - Invensys Energy Systems provided the SOLA/Best "Phoenixtec" protocol document. SOLA has since been acquired by Eaton. - PowerKinetics technical support provided documentation on their MiniCOL protocol, which is archived in the NUT protocol library. -PowerKinetics was acquired by the link:http://www.jst.cc[JST Group] in June 2003. +PowerKinetics was acquired by the link:http://www.jst.cc[JST Group] +in June 2003. - link:http://www.cyberpowersystems.com[Cyber Power Systems] contributed a 700AVR model for testing and development of the cyberpower driver. @@ -167,7 +168,12 @@ and a UPStation GXT2 with the Web/SNMP card for development of the liebert driver and expansion of the existing snmp-ups driver. Liebert has since been acquired by link:http://www.emerson.com[Emerson]. -NOTE: If a company or individual isn't listed here, then we probably don't have -enough information about the situation. Developers are requested to report vendor -contributions to the NUT team so this list may reflect their help. -If we have left you out, send us some mail. +NOTE: If a company or individual isn't listed here, then we probably don't +have enough information about the situation. Developers are kindly requested +to report vendor contributions to the NUT team so this list may reflect their +help, as well as convey a sense of official support (at least, that drivers +were proposed according to the know-how coming from specs and knowledge about +hardware and firmware capabilities, and not acquired via reverse engineering +with a certain degree of unreliability and incompleteness). If we have left +you out, please send us some mail or post a pull request to update this +document in GitHub. diff --git a/docs/asciidoc.txt b/docs/asciidoc.txt index 6fff26ec7f..6977051524 100644 --- a/docs/asciidoc.txt +++ b/docs/asciidoc.txt @@ -6,7 +6,8 @@ Charles Lepple Intro ----- -See http://www.methods.co.nz/asciidoc/[The AsciiDoc Manual] for more information. +See http://www.methods.co.nz/asciidoc/[The AsciiDoc Manual] for more +information. Works in Progress ----------------- diff --git a/docs/cables.txt b/docs/cables.txt index afc2c298d4..df4ca78204 100644 --- a/docs/cables.txt +++ b/docs/cables.txt @@ -37,20 +37,20 @@ OmniGuard F6C***-RKM *From "Daniel"* -A straight-through RS-232 cable (with pins 2-7 connected through) should work -with the following models: +A straight-through RS-232 cable (with pins 2-7 connected through) should +work with the following models: - F6C110-RKM-2U - F6C150-RKM-2U - F6C230-RKM-2U -- F6C320-RKM-3U +- F6C320-RKM-3U image::images/cables/belkin-f6cx-rkm-xu-cable.jpg[Belkin OmniGuard F6C***-RKM cable] Eaton ----- -Documents in this section are provided courtesy of Eaton. +Documents in this section are provided courtesy of Eaton. MGE Office Protection Systems ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -127,7 +127,7 @@ This cable can be used with the following models: T700, T1000, T1500, T1500j, T700h, T1000h, T1500h, R1500, R1500j, R1500h, T2000, T2000j, T2400h, T2400h-NA, R3000 / R3000j, R3000h, -R3000h-International, R3000h-NA, R6000h-NA, R6000i, R6000j. +R3000h-International, R3000h-NA, R6000h-NA, R6000i, R6000j. UPS PC 9 pin connector @@ -143,8 +143,8 @@ Contributed by Kjell Claesson and Arnaud Quette. Phoenixtec (Best Power) ----------------------- -Many Best Power units (including the Patriot Pro II) have a female DB-9 socket -with a non-standard pinout. +Many Best Power units (including the Patriot Pro II) have a female DB-9 +socket with a non-standard pinout. |==== |Signal | PC | UPS @@ -166,7 +166,7 @@ Tripp-Lite *From Tripp-Lite, via Bryan Kolodziej* -This cable (black 73-0844 cable) is used on various models, using the "Lan 2.2 interface" -and the genericups driver (upstype=5). +This cable (black 73-0844 cable) is used on various models, using the +"Lan 2.2 interface" and the genericups driver (upstype=5). image::images/cables/73-0724.png[73-0724 cable] diff --git a/docs/config-notes.txt b/docs/config-notes.txt index 822b6da046..8edb6580e4 100644 --- a/docs/config-notes.txt +++ b/docs/config-notes.txt @@ -13,8 +13,8 @@ NOTE: NUT does not currently provide proper graphical configuration tools. However, there is now support for linkdoc:developer-guide[Augeas,augeas_user], which will enable the easier creation of configuration tools. Moreover, linkman:nut-scanner[8] is available to discover supported devices -(USB, SNMP, Eaton XML/HTTP and IPMI) and NUT servers (using Avahi or the classic -connection method). +(USB, SNMP, Eaton XML/HTTP and IPMI) and NUT servers (using Avahi or the +classic connection method). Details about the configuration files ------------------------------------- @@ -104,7 +104,7 @@ quotes spanning multiple lines. Basic configuration ------------------- -This chapter describe the base configuration to establish communication with +This chapter describes the base configuration to establish communication with the device. This will be sufficient for PDU. But for UPS and SCD, you will also need to @@ -112,17 +112,28 @@ configure <>. image:images/simple.png[] +On operating systems with service management frameworks (such as Linux systemd +and Solaris/illumos SMF), the driver, data server and monitoring client daemons' +life-cycle is managed respectively by `nut-driver` (multi-instance), `nut-server` +and `nut-monitor` services. These are in turn wrapped by an "umbrella" service +(or systemd "target") conveniently called `nut` which allows to start or stop +those of the bundled services, which are enabled on a particular deployment. + [[Driver_configuration]] Driver configuration ~~~~~~~~~~~~~~~~~~~~ -Create one section per UPS in /usr/local/ups/etc/ups.conf +Create one section per UPS in ups.conf + +NOTE: The default path for a source installation is `/usr/local/ups/etc`, while +packaged installation will vary. For example, `/etc/nut` is used on Debian and +derivatives, while `/etc/ups` or `/etc/upsd` is used on RedHat and derivatives. To find out which driver to use, check the <>, -or data/driver.list. +or `data/driver.list`. Once you have picked a driver, create a section for your UPS in -ups.conf. You must supply values for "driver" and "port". +`ups.conf`. You must supply values for "driver" and "port". Some drivers may require other flags or settings. The "desc" value is optional, but is recommended to provide a better description of @@ -156,16 +167,17 @@ linkman:usbhid-ups[8] Starting the driver(s) ~~~~~~~~~~~~~~~~~~~~~~ -Start the driver(s) for your hardware: +Generally, you can just start the driver(s) for your hardware (all sections +defined in 'ups.conf') using the following command: - /usr/local/ups/sbin/upsdrvctl start + upsdrvctl start Make sure the driver doesn't report any errors. It should show a few details about the hardware and then enter the background. You should get back to the command prompt a few seconds later. For reference, a successful start of the `usbhid-ups` driver looks like this: - # /usr/local/ups/sbin/upsdrvctl start + # upsdrvctl start Network UPS Tools - Generic HID driver 0.34 (2.4.1) USB communication driver 0.31 Using subdriver: MGE HID 1.12 @@ -184,6 +196,67 @@ state path probably isn't writable by the driver. Check the After making changes, try the <> step again. +On operating systems with init-scripts managing life-cycle of the operating +environment, the `upsdrvctl` program is also commonly used in those scripts. +It has a few downsides, such as that if the device was not accessible during +OS startup and the driver connection timed out, it would remain not-started +until an administrator (or some other script) "kicks" the driver to retry +startup. Also, startup of the `upsd` data server daemon and its clients +like `upsmon` is delayed until all the NUT drivers complete their startup +(or time out trying). + +This can be a big issue on systems which monitor multiple devices, such as +big servers with multiple power sources, or administrative workstations +which monitor a datacenter full of UPSes. + +For this reason, NUT starting with version 2.7.5 supports startup of its +drivers as independent instances of a `nut-driver` service under the Linux +systemd and Solaris/illumos SMF service-management frameworks (corresponding +files and scripts may be not pre-installed in packaging for other systems). + +Such service instances have their own and independent life-cycle, including +parallel driver start and stop processing, and retries of startup in case of +failure as implemented by the service framework in the OS. The Linux systemd +solution also includes a `nut-driver.target` as a checkpoint that all defined +drivers have indeed started up (as well as being a singular way to enable or +disable startup of drivers). + +In both cases, a service named `nut-driver-enumerator` is registered, and +when it is (re-)started it scans the currently defined device sections in +`ups.conf` and the currently defined instances of `nut-driver` service, +and brings them in sync (adding or removing service instances), and if +there were changes -- it restarts the corresponding drivers (via service +instances) as well as the data server which only reads the list of sections +at its startup. This helper service should be triggered whenever your system +(re-)starts the `nut-server` service, so that it runs against an up-to-date +list of NUT driver processes. + +A service-oriented solution also allows to consider that different drivers +have different dependencies -- such as that networked drivers should begin +startup after IP addresses have been assigned, while directly-connected +devices might need nothing beside a mounted filesystem (or an activated +USB stack service or device rule, in case of Linux). Likewise, systems +administrators can define further local dependencies between services and +their instances as needed on particular deployments. + +This solution also adds the `upsdrvsvcctl` script to manage NUT drivers as +system service instances, whose CLI mimics that of `upsdrvctl` program. +One addition is the `resync` argument to trigger `nut-driver-enumerator`, +another is a `list` argument to display current mappings of service +instances to NUT driver sections. Also, original tool's arguments such +as the `-u` (user to run the driver as) or `-D` (debug of the driver) +do not make sense in the service context -- the accounts to use and +other arguments to the driver process are part of service setup (and +an administrator can manage it there). + +Note that while this solution tries to register service instances with same +names as NUT configuration sections for the devices, this can not always be +possible due to constraints such as syntax supported by a particular service +management framework. In this case, the enumerator falls back to MD5 hashes +of such section names, and the `upsdrvsvcctl` script supports this to map +the user-friendly NUT configuration section names to actual service names +that it would manage. + References: man pages: linkman:nutupsdrv[8], linkman:upsdrvctl[8] @@ -227,12 +300,12 @@ Starting the data server Start the network data server: - /usr/local/ups/sbin/upsd + upsd Make sure it is able to connect to the driver(s) on your system. A successful run looks like this: - # /usr/local/ups/sbin/upsd + # upsd Network UPS Tools upsd 2.4.1 listening on 127.0.0.1 port 3493 listening on ::1 port 3493 @@ -247,6 +320,9 @@ is stale, then your ups.conf is not configured correctly, or you have a driver that isn't working properly. You must fix this before going on to the next step. +On operating systems with service management frameworks, the data server +life-cycle is managed by `nut-server` service. + Reference: man page: linkman:upsd[8] Check the UPS data @@ -257,14 +333,14 @@ Status data Make sure that the UPS is providing good status data. - /usr/local/ups/bin/upsc myupsname@localhost ups.status + upsc myupsname@localhost ups.status You should see just one line in response: OL OL means your system is running on line power. If it says something -else (like OB - on battery, or LB - low battery), your driver was +else (like OB -- on battery, or LB -- low battery), your driver was probably misconfigured during the <> step. If you reconfigure the driver, use `upsdrvctl stop` to stop it, then start it again as shown in the <> step. @@ -277,7 +353,7 @@ All data Look at all of the status data which is being monitored. - /usr/local/ups/bin/upsc myupsname@localhost + upsc myupsname@localhost What happens now depends on the kind of device and driver you have. In the list, you should see ups.status with the same value you got @@ -337,8 +413,11 @@ Startup scripts NOTE: This step is not necessary if you installed from packages. -Edit your startup scripts, and make sure upsdrvctl and upsd are run every time -your system starts. +Edit your startup scripts, and make sure `upsdrvctl` and `upsd` are run +every time your system starts. In newer versions of NUT, you may have a +`nut.conf` file which sets the `MODE` variable for bundled init-scripts, +to facilitate enabling of certain features in the specific end-user +deployments. [[UPS_shutdown]] Configuring automatic shutdowns for low battery events @@ -372,7 +451,7 @@ The exact behavior depends on the specific device, and is related to: - battery.charge and battery.charge.low - battery.runtime and battery.runtime.low -3. The upsmon master notices and sets "FSD" - the "forced shutdown" +3. The upsmon master notices and sets "FSD" -- the "forced shutdown" flag to tell all slave systems that it will soon power down the load. + (If you have no slaves, skip to step 6) @@ -380,7 +459,7 @@ The exact behavior depends on the specific device, and is related to: 4. upsmon slave systems see "FSD" and: - generate a NOTIFY_SHUTDOWN event - - wait FINALDELAY seconds - typically 5 + - wait FINALDELAY seconds -- typically 5 - call their SHUTDOWNCMD - disconnect from upsd @@ -392,8 +471,8 @@ The exact behavior depends on the specific device, and is related to: 6. The upsmon master: - generates a NOTIFY_SHUTDOWN event - - waits FINALDELAY seconds - typically 5 - - creates the POWERDOWNFLAG file - usually /etc/killpower + - waits FINALDELAY seconds -- typically 5 + - creates the POWERDOWNFLAG file -- usually `/etc/killpower` - calls the SHUTDOWNCMD 7. On most systems, init takes over, kills your processes, syncs and @@ -436,12 +515,12 @@ Reloading the data server Reload upsd. Depending on your configuration, you may be able to do this without stopping upsd: - /usr/local/ups/sbin/upsd -c reload + upsd -c reload If that doesn't work (check the syslog), just restart it: - /usr/local/ups/sbin/upsd -c stop - /usr/local/ups/sbin/upsd + upsd -c stop + upsd NOTE: if you want to make reloading work later, see the entry in the link:FAQ.html[FAQ] about starting upsd as a different user. @@ -518,10 +597,13 @@ does local shutdown tasks before calling init. Start upsmon ^^^^^^^^^^^^ - /usr/local/ups/sbin/upsmon + upsmon If it complains about something, then check your configuration. +On operating systems with service management frameworks, the monitoring client +life-cycle is managed by `nut-monitor` service. + Checking upsmon ^^^^^^^^^^^^^^^ @@ -560,16 +642,16 @@ NOTE: This step is not need if you installed from packages. Edit your shutdown scripts, and add `upsdrvctl shutdown`. -You should configure your system to power down the UPS after the filesystems are -remounted read-only. Have it look for the presence of the POWERDOWNFLAG (from -linkman:upsmon.conf[5]), using this as an example: +You should configure your system to power down the UPS after the filesystems +are remounted read-only. Have it look for the presence of the POWERDOWNFLAG +(from linkman:upsmon.conf[5]), using this as an example: --------------------------------------------------------------------------------- +------------------------------------------------------------------------------ if (test -f /etc/killpower) then echo "Killing the power, bye!" - /usr/local/ups/bin/upsdrvctl shutdown + /sbin/upsdrvctl shutdown sleep 120 @@ -578,18 +660,18 @@ linkman:upsmon.conf[5]), using this as an example: # *** see also the section on power races in the FAQ! *** fi --------------------------------------------------------------------------------- +------------------------------------------------------------------------------ [WARNING] -================================================================================ +============================================================================== - Be careful that upsdrvctl command will probably power off your machine. Don't use it unless your system is ready to be halted by force. If you run RAID, read the <<_raid_warning,RAID warning>> below! - Make sure the filesystem(s) containing upsdrvctl, ups.conf and your UPS -driver(s) are mounted (possibly in read-only mode) when the system gets to this -point. Otherwise it won't be able to figure out what to do. -================================================================================ +driver(s) are mounted (possibly in read-only mode) when the system gets to +this point. Otherwise it won't be able to figure out what to do. +============================================================================== [[Testing_shutdowns]] @@ -602,17 +684,17 @@ on your systems before leaving them unattended. A successful sequence is one where the OS halts before the battery runs out, and the system restarts when power returns. -The first step is to see how upsdrvctl will behave without actually turning off -power. To do so, use the '-t' argument: +The first step is to see how upsdrvctl will behave without actually +turning off the power. To do so, use the '-t' argument: - /usr/local/ups/bin/upsdrvctl -t shutdown + upsdrvctl -t shutdown It will display the sequence without actually calling the drivers. You can finally test a forced shutdown sequence (FSD) using: - /usr/local/ups/sbin/upsmon -c fsd + upsmon -c fsd This will execute a full shutdown sequence, as presented in <>, starting from the 3rd step. @@ -728,7 +810,7 @@ programs need to be run for monitoring: To further complicate things, you can have a system that is hooked to multiple UPSes, but only depends on one for power. This particular situation makes it an "A" relative to one UPS, and a "C" relative to the -other. The software can handle this - you just have to tell it what to do. +other. The software can handle this -- you just have to tell it what to do. NOTE: NUT can also serve as a data proxy to increase the number of clients, or share the communication load between several upsd instances. diff --git a/docs/configure.txt b/docs/configure.txt index 8824349bf4..e8530c6469 100644 --- a/docs/configure.txt +++ b/docs/configure.txt @@ -3,8 +3,9 @@ Configure options ================= endif::website[] -There are a few options that can be given to configure to tweak compiles. -See also "./configure --help" for a current and complete listing. +There are a few options reviewed below that can be given to `configure` +script to tweak your compilations. See also `./configure --help` for a +current and complete listing for the current version of the codebase. Driver selection ---------------- @@ -125,7 +126,7 @@ Example valid formats of this flag: --with-dev (default: no) -Build and install the upsclient and nutclient library and header files. +Build and install the upsclient and nutclient library and header files. --with-all (no default) @@ -154,7 +155,7 @@ Enable IPv6 support. Build and install Avahi support, to publish NUT server availability using mDNS protocol. This requires Avahi development files for the -Core and Client parts. +Core and Client parts. --with-libltdl (default: auto-detect) @@ -169,7 +170,7 @@ Other configuration options Change the TCP port used by the network code. Default is 3493. Ancient versions of upsd used port 3305. NUT 2.0 and up use a -substantially different network protocol and are not able to +substantially different network protocol and are not able to communicate with anything older than the 1.4 series. If you have to monitor a mixed environment, use the last 1.4 version, @@ -202,7 +203,7 @@ hack for NFS access. You should create at least one separate user for this software. If you use one of the --with-user and --with-group options, then -you have to use the other one too. +you have to use the other one too. See the INSTALL.nut document and the FAQ for more on this topic. @@ -251,7 +252,7 @@ to bindir. The defaults are /bin and /sbin. Change the data directory, i.e., where architecture independent read-only data is installed. By default this is /share, i.e., /usr/local/ups/share. At the moment, this directory only -holds two files - the optional cmdvartab and driver.list. +holds two files -- the optional cmdvartab and driver.list. --mandir=PATH @@ -282,8 +283,8 @@ at run time. The CGI programs will be installed to this path. By default, they install to "/cgi-bin", which is usually /usr/local/ups/cgi-bin. -If you set the prefix to something like /usr, you should set the -cgipath to something else, because /usr/cgi-bin is pretty ugly and +If you set the prefix to something like /usr, you should set the +cgipath to something else, because /usr/cgi-bin is pretty ugly and non-standard. The CGI programs are not built or installed by default. Use @@ -303,7 +304,7 @@ effect if `--with-dev` is selected, and causes a pkg-config file to be installed in the named location. The default is /pkgconfig. -Use --without-pkgconfig-dir to disable this feature altogether. +Use --without-pkgconfig-dir to disable this feature altogether. --with-hotplug-dir=PATH @@ -313,7 +314,7 @@ otherwise. Note that this installation directory is not a subdirectory of by default. When installing NUT as a non-root user, you may have to override this option. -Use --without-hotplug-dir to disable this feature altogether. +Use --without-hotplug-dir to disable this feature altogether. --with-udev-dir=PATH @@ -324,7 +325,7 @@ installation directory is not a subdirectory of by default. When installing NUT as a non-root user, you may have to override this option. -Use --without-udev-dir to disable this feature altogether. +Use --without-udev-dir to disable this feature altogether. --with-systemdsystemunitdir=PATH @@ -384,8 +385,8 @@ If your copy of gd isn't linking properly, use this to give the proper -L and -l flags to make it work. See LIBS= in gd's Makefile. NOTE: the --with-gd switches are not necessary if you have gd 2.0.8 -or higher installed properly. The gdlib-config script will be -detected and used by default in that situation. +or higher installed properly. The gdlib-config script or pkgconfig +manifest will be detected and used by default in that situation. --with-gdlib-config diff --git a/docs/contact-closure.txt b/docs/contact-closure.txt index deba8b9a50..80578bcd0f 100644 --- a/docs/contact-closure.txt +++ b/docs/contact-closure.txt @@ -74,7 +74,7 @@ When editing the genericups.h, the values have the following meanings: Outgoing lines: -- line_norm = what to set to make the line "normal" - i.e. cable power +- line_norm = what to set to make the line "normal" -- i.e. cable power - line_sd = what to set to make the UPS shut down the load Incoming lines: @@ -91,7 +91,7 @@ with the value of the serial port whenever a poll occurs. If that flag exists, then the result of the and will be 0x80. If it does not exist, the result will be 0. -So, if line_ol = foo, then val_ol can only be foo or 0. +So, if line_ol = foo, then val_ol can only be foo or 0. As a general case, if 'line_ol == val_ol', then the value you're reading is active high. Otherwise, it's active low. Check out the guts of diff --git a/docs/daisychain.txt b/docs/daisychain.txt index b78a66a79a..f752839541 100644 --- a/docs/daisychain.txt +++ b/docs/daisychain.txt @@ -8,21 +8,22 @@ NUT supports daisychained devices for any kind of device that proposes it. This chapter introduces: * for developers: how to implement such mechanism, -* for users: how to manage and use daisychained devices in NUT in general, and -how to take advantage of the provided features. +* for users: how to manage and use daisychained devices in NUT in general, + and how to take advantage of the provided features. Introduction ------------ -It's not unusual to see some daisy-chained PDUs or UPSs, connected together in -master-slave mode, to only consume 1 IP address for their communication -interface (generally, network card exposing SNMP data) and expose only one point -of communication to manage several devices, through the daisychain master. +It's not unusual to see some daisy-chained PDUs or UPSs, connected together +in master-slave mode, to only consume 1 IP address for their communication +interface (generally, network card exposing SNMP data) and expose only one +point of communication to manage several devices, through the daisy-chain +master. -This breaks the historical consideration of NUT that one driver provides data -for one unique device. -However, there is an actual need, and a smart approach was considered to -fulfill this, while not breaking the standard scope (for base compatibility). +This breaks the historical consideration of NUT that one driver provides +data for one unique device. However, there is an actual need, and a smart +approach was considered to fulfill this, while not breaking the standard +scope (for base compatibility). Implementation notes @@ -31,31 +32,32 @@ Implementation notes General specification ~~~~~~~~~~~~~~~~~~~~~ -The daisychain support uses the device collection to extend the historical NUT -scope (1 driver - 1 device), and provide data from the additional devices. +The daisychain support uses the device collection to extend the historical +NUT scope (1 driver -- 1 device), and provides data from the additional +devices accessible through a single management interface. -A new variable was introduced to provide the number of devices exposed: device.count - -device.count: +A new variable was introduced to provide the number of devices exposed: the +`device.count`, which: * defaults to 1 -* if higher than 1, enable daisychain support and access devices data through -device.X.{...} +* if higher than 1, enables daisychain support and access to data of each +individual device through `device.X.{...}` -To ensure backward compatibility in NUT, the data of the various devices are -exposed the following way: +To ensure backward compatibility in NUT, the data of the various devices +are exposed the following way: -* "device.0" is a special case, for the whole set of devices (the whole -daisychain). It is equivalent to "device" (without ".X" index) and root -collections. The idea is to be able to get visibility and control over the whole -daisychain from a single point. -* daisy chained devices are available from "device.1" (master) to "device.N" +* `device.0` is a special case, for the whole set of devices (the whole +daisychain). It is equivalent to `device` (without `.X` index) and root +collections. The idea is to be able to get visibility and control over the +whole daisychain from a single point. +* daisy-chained devices are available from `device.1` (master) to `device.N` (slaves). -That way, client application that are unaware of the daisychain support, will -only see the whole daisychain, as it would normally see, and not nothing at all. +That way, client applications that are unaware of the daisychain support, +will only see the whole daisychain, as it would normally seem, and not +nothing at all. -Moreover, this solution is generic, and not specific to the PDU use case +Moreover, this solution is generic, and not specific to the ePDU use case currently considered. It thus support both the current NUT scope, along with other use cases (parallel / serial UPS setups), and potential evolution and technology change (hybrid chain with UPS and PDU for example). @@ -70,18 +72,18 @@ To be clarified... Devices alarms handling ^^^^^^^^^^^^^^^^^^^^^^^ -Devices (master and slaves) alarms are published in "device.X.ups.alarm", which -may evolve into "device.X.alarm". If any of the device has an alarm, the main -ups.status will publish an "ALARM" flag. This flag is be cleared once all -devices have no alarms anymore. +Devices (master and slaves) alarms are published in `device.X.ups.alarm`, +which may evolve into `device.X.alarm`. If any of the devices has an alarm, +the main `ups.status` will publish an `ALARM` flag. This flag is be cleared +once all devices have no alarms anymore. -NOTE: ups.alarm behavior is not yet defined (all devices alarms Vs list of -device(s) that have alarms Vs nothing?) +NOTE: ups.alarm behavior is not yet defined (all devices alarms vs. list of +device(s) that have alarms vs. nothing?) Example ^^^^^^^ -Here is an example excerpt of three PDUs, connected in daisychain mode, with one -master and two slaves: +Here is an example excerpt of three PDUs, connected in daisychain mode, with +one master and two slaves: device.count: 3 device.mfr: EATON @@ -112,18 +114,18 @@ master and two slaves: Information for developers ~~~~~~~~~~~~~~~~~~~~~~~~~~ -NOTE: these information are dedicated to the snmp-ups driver! +NOTE: these details are dedicated to the `snmp-ups` driver! -In order to enable daisychain support for a range of devices, developers have to -do two things: +In order to enable daisychain support for a range of devices, developers +have to do two things: -* Add a "device.count" entry in a mapping file (-mib.c) +* Add a `device.count` entry in a mapping file (see `*-mib.c`) * Modify mapping entries to include a format string for the daisychain index -Optionally, if there is support for outlets and / or outlets groups, there is -already a template formatting string. So you have to tag such templates with -multiple definitions, to point if the daisychain index is the first or second -formatting string. +Optionally, if there is support for outlets and / or outlet-groups, there +is already a template formatting string. So you have to tag such templates +with multiple definitions, to point if the daisychain index is the first +or second formatting string. Base support ^^^^^^^^^^^^ @@ -137,42 +139,48 @@ To achieve this, use one of the following type of declarations: + a) point at an OID which provides the number of devices: - { "device.count", 0, 1, ".1.3.6.1.4.1.13742.6.3.1.0", "1", SU_FLAG_STATIC, NULL }, + { "device.count", 0, 1, ".1.3.6.1.4.1.13742.6.3.1.0", "1", + SU_FLAG_STATIC, NULL }, + b) point at a template OID to guesstimate the number of devices, by walking through this template, until it fails: + - { "device.count", 0, 1, ".1.3.6.1.4.1.534.6.6.7.1.2.1.2.%i", "1", SU_FLAG_STATIC, NULL, NULL }, + { "device.count", 0, 1, ".1.3.6.1.4.1.534.6.6.7.1.2.1.2.%i", "1", + SU_FLAG_STATIC, NULL, NULL }, * Modify all entries so that OIDs include the formatting string for the daisychain index. For example, if you have the following entry: + - { "device.model", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.1.2.1.2.0", ... }, + { "device.model", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.534.6.6.7.1.2.1.2.0", ... }, + -And if the last "0" of the the 4th field represents the index of the device in -the daisychain, then you would have to adapt it the following way: +And if the last "0" of the the 4th field represents the index of the device +in the daisychain, then you would have to adapt it the following way: + - { "device.model", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.1.2.1.2.%i", ... }, + { "device.model", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.534.6.6.7.1.2.1.2.%i", ... }, Templates with multiple definitions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -If there exist already templates in the mapping structure, such as for outlets -and outlets groups, you also need to specify the position of the daisychain -device index in the OID strings for all entries in the mapping table, to -indicate where the daisychain insertion point is exactly. +If there exist already templates in the mapping structure, such as for +single outlets and outlet-groups, you also need to specify the position +of the daisychain device index in the OID strings for all entries in the +mapping table, to indicate where the daisychain insertion point is exactly. For example, using the following entry: - { "outlet.%i.current", 0, 0.001, ".1.3.6.1.4.1.534.6.6.7.6.4.1.3.0.%i", NULL, SU_OUTLET, NULL, NULL }, + { "outlet.%i.current", 0, 0.001, ".1.3.6.1.4.1.534.6.6.7.6.4.1.3.0.%i", + NULL, SU_OUTLET, NULL, NULL }, You would have to translate it to: - { "outlet.%i.current", 0, 0.001, ".1.3.6.1.4.1.534.6.6.7.6.4.1.3.%i.%i", NULL, SU_OUTLET | SU_TYPE_DAISY_1, NULL, NULL }, + { "outlet.%i.current", 0, 0.001, ".1.3.6.1.4.1.534.6.6.7.6.4.1.3.%i.%i", + NULL, SU_OUTLET | SU_TYPE_DAISY_1, NULL, NULL }, -SU_TYPE_DAISY_1 indicates that the daisychain index is the 1st specifier ("%i") -in the string. If it is the second one, use SU_TYPE_DAISY_2. +SU_TYPE_DAISY_1 indicates that the daisychain index is the 1st specifier +("%i") in the string. If it is the second one, use SU_TYPE_DAISY_2. Devices alarms handling @@ -182,23 +190,25 @@ Two functions are available to handle alarms on daisychain devices in your driver: * device_alarm_init(): clear the current alarm buffer -* device_alarm_commit(const int device_number): commit the current alarm buffer -to "device..ups.alarm", and increase the count of alarms. If the -current alarms buffer is empty, the count of alarm is decreased, and the -variable "device..ups.alarm" is removed from publication. Once -the alarm count reaches "0", the main (device.0) ups.status will also remove the -"ALARM" flag. - -NOTE: when implementing a new driver, the following functions have to be called: +* device_alarm_commit(const int device_number): commit the current alarm +buffer to "device..ups.alarm", and increase the count of +alarms. If the current alarms buffer is empty, the count of alarm is +decreased, and the variable "device..ups.alarm" is removed +from publication. Once the alarm count reaches "0", the main (device.0) +ups.status will also remove the "ALARM" flag. + +NOTE: when implementing a new driver, the following functions have to be +called: * "alarm_init()" at the beginning of the main update loop, for the whole -daisychain. This will set the alarm count to "0", and reinitialize all alarms, +daisychain. This will set the alarm count to "0", and reinitialize all +alarms, * "device_alarm_init()" at the beginning of the per-device update loop. This will only clear the alarms for the current device, -* "device_alarm_commit()" at the end of the per-device update loop. This will -flush the current alarms for the current device, -* also "device_alarm_init()" at the end of the per-device update loop. This will -clear the current alarms, and ensure that this buffer will not be considered by -other subsequent devices, -- "alarm_commit()" at the end of the main update loop, for the whole daisychain. -This will take care of publishing or not the "ALARM" flag in the main ups.status -(device.0, root collection). +* "device_alarm_commit()" at the end of the per-device update loop. +This will flush the current alarms for the current device, +* also "device_alarm_init()" at the end of the per-device update loop. +This will clear the current alarms, and ensure that this buffer will not +be considered by other subsequent devices, +- "alarm_commit()" at the end of the main update loop, for the whole +daisychain. This will take care of publishing or not the "ALARM" flag +in the main ups.status (device.0, root collection). diff --git a/docs/design.txt b/docs/design.txt index 4e39ecac04..c02c3b9ee0 100644 --- a/docs/design.txt +++ b/docs/design.txt @@ -1,7 +1,7 @@ NUT design document =================== -This software is designed around a layered scheme with drivers, a +This software is designed around a layered scheme with drivers, a server and clients. These layers communicate with text-based protocols for easier maintenance and diagnostics. @@ -26,7 +26,7 @@ From the driver ~~~~~~~~~~~~~~~ The core of all DRIVERS maintains internal storage for every variable -that is known along with the auxiliary data for those variables. It +that is known along with the auxiliary data for those variables. It sends updates to this data to any process which connects to the Unix domain socket. @@ -62,7 +62,7 @@ test the front panel of the UPS. They are passed to the SERVER from a CLIENT using an authenticated network connection. The SERVER first checks to make sure that the instant -command is valid for the DRIVER. If it's supported, a message is sent +command is valid for the DRIVER. If it's supported, a message is sent via a socket to the DRIVER containing the command and any auxiliary information. @@ -100,8 +100,8 @@ delivering the alpha message to the admin. 2. DRIVER notices this flag and stores it in the ups.status variable as OB. This update gets pushed out to any listeners via the sockets. -3. SERVER upsd sees activity on the socket, reads it, parses it, and - commits the new data to its local version of the status variable. +3. SERVER upsd sees activity on the socket, reads it, parses it, and + commits the new data to its local version of the status variable. 4. CLIENT upsmon does a routine poll of SERVER for "ups.status" and gets "OB". @@ -138,7 +138,7 @@ This scenario requires some configuration, obviously: upsmon master 4. upsmon is set to monitor this UPS in upsmon.conf. - + MONITOR myups@localhost 1 monuser somepass master 5. upsmon is set to EXEC the NOTIFYCMD for the ONBATT condition in @@ -200,6 +200,6 @@ active, it reads the fd and parses the results. Updates from the hardware now get to upsd about as fast as they possibly can. Drivers used to call setinfo() to change the local array, and then would -call writeinfo() to push the array onto the disk, or into the +call writeinfo() to push the array onto the disk, or into the mmap/shared memory space. This introduced a lag since many drivers poll quite a few variables during an update. diff --git a/docs/developer-guide.txt b/docs/developer-guide.txt index e6fe477e2f..b40629f56b 100644 --- a/docs/developer-guide.txt +++ b/docs/developer-guide.txt @@ -110,7 +110,7 @@ link:http://anonscm.debian.org/viewvc/nut/trunk/data/evolution500.seq?revision=2 only apply according to the TIMER events and the current position in the sequence. -For more information, refer to linkman:dummy-ups[8] manual page. +For more information, refer to linkman:dummy-ups[8] manual page. [[dev-recording]] diff --git a/docs/developers.txt b/docs/developers.txt index f989aa9970..63fb911b32 100644 --- a/docs/developers.txt +++ b/docs/developers.txt @@ -4,50 +4,51 @@ Information for developers This document is intended to explain some of the more useful things within the tree, and provide a standard for working on the code. -General stuff - common subdirectory ------------------------------------ +General stuff -- common subdirectory +------------------------------------ String handling ~~~~~~~~~~~~~~~ -Use snprintf(). It's even provided with a compatibility module if the +Use `snprintf()`. It's even provided with a compatibility module if the target system doesn't have it natively. -If you use snprintf() to load some value into a buffer, make sure you +If you use `snprintf()` to load some value into a buffer, make sure you provide the format string. Don't use user-provided format strings, since that's an easy way to open yourself up to an exploit. -Don't use strcat(). We have a neat wrapper for snprintf() called snprintfcat() -that allows you to append to char * with a format string and all the usual -string length checking of snprintf(). +Don't use `strcat()`. We have a neat wrapper for `snprintf()` called +`snprintfcat()` that allows you to append to `char *` with a format +string and all the usual string length checking of `snprintf()` routine. Error reporting ~~~~~~~~~~~~~~~ -Don't call syslog() directly. Use upslog_with_errno() and upslogx(). +Don't call `syslog()` directly. Use `upslog_with_errno()` and `upslogx()`. They may write to the syslog, stderr, or both as appropriate. This means you don't have to worry about whether you're running in the background or not. -upslog_with_errno prints your message plus the string expansion of -errno. upslogx just prints the message. +The `upslog_with_errno()` routine prints your message plus the string +expansion of `errno`. The `upslogx()` just prints the message. -fatal_with_errno and fatalx work the same way, but they -exit(EXIT_FAILURE) afterwards. Don't call exit() directly. +`fatal_with_errno()` and `fatalx()` work the same way, but they +also `exit(EXIT_FAILURE)` afterwards. Don't call `exit()` directly. Debugging information ~~~~~~~~~~~~~~~~~~~~~ -upsdebug_with_errno(), upsdebugx(), upsdebug_hex() and upsdebug_ascii() -use the global `nut_debug_level` so you don't have to mess around with -printf()s yourself. Use them. +The `upsdebug_with_errno()`, `upsdebugx()`, `upsdebug_hex()` and +`upsdebug_ascii()` routines use the global `nut_debug_level`, so you +don't have to mess around with `printf()`s and `if`s yourself. +Use them. Memory allocation ~~~~~~~~~~~~~~~~~ -xmalloc, xcalloc, xrealloc and xstrdup all check the results of the base -calls before continuing, so you don't have to. Don't use the raw calls -directly. +`xmalloc()`, `xcalloc()`, `xrealloc()` and `xstrdup()` all check the +results of the base calls before continuing, so you don't have to. +Don't use the raw calls directly. Config file parsing ~~~~~~~~~~~~~~~~~~~ @@ -66,8 +67,8 @@ handled by the state machine. Using the same code for all config files avoids code duplication. NOTE: this does not apply to drivers. Driver authors should use the -upsdrv_makevartable() scheme to pick up values from ups.conf. Drivers -should not have their own config files. +`upsdrv_makevartable()` scheme to pick up values from ups.conf. +Drivers should not have their own config files. Drivers may have their own data files, such as lists of hardware, mapping tables, or similar. The difference between a data file and a @@ -81,8 +82,8 @@ hardware support to a driver without recompiling. This is already handled by autoconf, so just include "timehead.h" and you will get the right headers on every system. -Device drivers - main.c ------------------------ +Device drivers -- main.c +------------------------ The device drivers use main.c as their core. @@ -108,9 +109,9 @@ There are still older systems out there that don't do C++ style comments. -------------------------------------- Newer versions of gcc allow you to declare a variable inside a function -somewhat like the way C++ operates, like this: +after code, somewhat like the way C++ operates, like this: --------------------------------------------------------------------------------- +------------------------------------------------------------------------------- function do_stuff(void) { check_something(); @@ -119,18 +120,49 @@ function do_stuff(void) a = do_something_else(); } --------------------------------------------------------------------------------- +------------------------------------------------------------------------------- While this will compile and run on these newer versions, it will fail miserably for anyone on an older system. That means you must not use it. gcc only warns about this with -pedantic. +Another feature that does not work on some compilers (e.g. conforming +to ANSI C / C89 standard) is initial variable declaration inside a +'for loop' block, like this: +-------------------------------------------------------------------------------- +function do_stuff(void) +{ + /* This should declare "int i;" first, then use it in "for" loop: */ + for (int i = 0; i < INT_MAX; ++i) { ... } + + /* Additional loops cause also an error about re-declaring a variable: */ + for (int i = 10; i < 15; ++i) { ... } +} +-------------------------------------------------------------------------------- + +At this point NUT is expected to work correctly when built with a C99 +(or GNU99 on Linux) or newer standard. + +The NUT codebase may build in a mode without warnings made fatal on C89 +(GNU89), but the emitted warnings indicate that those binaries may crash. +If somebody in the community requires to build and run NUT on systems +that old, pull requests to fix the offending coding issues are welcome. + +The NUT project on GitHub has integration with Travis CI to test a large +set of compiler and option combinations, covering different versions of +gcc and clang, C standards, and requiring to pass builds at least in a +mode without warnings (and checking the other cases where any warnings +are made fatal). Developers can use the scripts involved to fix existing +code or ensure support for new compilers and C standard revisions. + +* https://github.com/networkupstools/nut/issues/823 + Coding style ------------ This is how we do things: --------------------------------------------------------------------------------- +------------------------------------------------------------------------------- int open_subspace(char *ship, int privacy) { if (!privacy) @@ -141,7 +173,7 @@ int open_subspace(char *ship, int privacy) return secure_channel(ship); } --------------------------------------------------------------------------------- +------------------------------------------------------------------------------- The basic idea is that we try to group things into functions, and then find ways to drop out of them when we can't go any further. There's @@ -174,16 +206,33 @@ non-tab character has appeared on the line must be done by spaces in order for it to remain at the same alignment when someone views tabs at a different widths. -If you write something that uses spaces, you may get away with it in a -driver that's relatively secluded. However, if we have to work on that -code, expect it to get reformatted according to the above. +One common example for this is multi-line if condition: + +-------------------------------------------------------------------------------- + if (something && + something_else) { +-------------------------------------------------------------------------------- + +Another example is tables of definitions that are better aligned with +(non-leading) spaces at least between names and values not too many +characters wide; it still helps to align the columns with spaces at +offsets divisible by 4 or 8 (consistently for the whole table): + +-------------------------------------------------------------------------------- +#define SHORT_MACRO 1 /* flag comment */ +#define SOMETHING_WITH_A_VERY_LONG_NAME 255 /* flag comment */ +-------------------------------------------------------------------------------- + +If you write something that uses leading spaces, you may get away with +it in a driver that's relatively secluded. However, if we have to work +on that code, expect it to get reformatted according to the above. Patches to existing code that don't conform to the coding style being used in that file will probably be dropped. If it's something we really need, it will be grudgingly reformatted before being included. When in doubt, have a look at Linus's take on this topic in the Linux -kernel - Documentation/CodingStyle. He's done a far better job of +kernel -- Documentation/CodingStyle. He's done a far better job of explaining this. Line breaks @@ -200,17 +249,17 @@ long when there is a better alternative (see the note on pretentiousVariableNamingSchemes above). Certainly there should not be more than one statement per line. Please do not use --------------------------------------------------------------------------------- +------------------------------------------------------------------------------- if (condition) break; --------------------------------------------------------------------------------- +------------------------------------------------------------------------------- but use the following: --------------------------------------------------------------------------------- +------------------------------------------------------------------------------- if (condition) { break; } --------------------------------------------------------------------------------- +------------------------------------------------------------------------------- Miscellaneous coding style tools -------------------------------- @@ -233,7 +282,7 @@ rendered on screen). It is even possible to set this on a per-directory basis, by putting something like this into your .emacs file: --------------------------------------------------------------------------------- +------------------------------------------------------------------------------- ;; NUT style (defun nut-c-mode () @@ -248,7 +297,7 @@ file: (setq auto-mode-alist (cons '(".*/nut/.*\\.[ch]$". nut-c-mode) auto-mode-alist)) --------------------------------------------------------------------------------- +------------------------------------------------------------------------------- Finishing touches ~~~~~~~~~~~~~~~~~ @@ -270,7 +319,7 @@ Spaghetti If you use a goto, expect us to drop it when our head stops spinning. It gives us flashbacks to the very old code we wrote. We've tried to clean up our act, and you should make the effort -as well. +as well. We're not making a blanket statement about gotos, since everything probably has at least one good use. There are a few cases where a goto @@ -285,18 +334,18 @@ There are parts of the source tree that do not yet conform to these specs. Part of this is due to the fact that the coding style has been evolving slightly over the course of the project. Some of the code you see in these directories is 5 years old, and things have gotten cleaner -since then. Don't worry - it'll get cleaned up the next time something +since then. Don't worry -- it'll get cleaned up the next time something in the vicinity gets a visit. Memory leak checking ~~~~~~~~~~~~~~~~~~~~ We can't say enough good things about valgrind. If you do anything with -dynamic memory in your code, you need to use this. Just compile with -g -and start the program inside valgrind. Run it through the suspected -area and then exit cleanly. valgrind will tell you if you've done -anything dodgy like freeing regions twice, reading uninitialized memory, -or if you've leaked memory anywhere. +dynamic memory in your code, you need to use this. Just compile with +`gcc -g` and start the program inside `valgrind`. Run it through the +suspected area and then exit cleanly. valgrind will tell you if you've +done anything dodgy like freeing regions twice, reading uninitialized +memory, or if you've leaked memory anywhere. For more information, refer to the link:http://valgrind.kde.org[Valgrind] project. @@ -310,19 +359,21 @@ and many people have put a lot of time and energy to improve it. Submitting patches ------------------ -Small patches that arrive in unified format (diff -u) as plain text attachments -with no HTML and a brief summary at the top are the easiest to handle. +Small patches that arrive in unified format (diff -u) as plain text +attachments with no HTML and a brief summary at the top are the easiest +to handle. -If a patch is sent to the nut-upsdev mailing list, it stands a better chance of -being seen immediately. However, it is likely to be dropped if any issues -cannot be resolved quickly. If your code might not work for others, or if it is -a large change, your best bet is to submit a pull request or create an +If a patch is sent to the nut-upsdev mailing list, it stands a better +chance of being seen immediately. However, it is likely to be dropped +if any issues cannot be resolved quickly. If your code might not work +for others, or if it is a large change, your best bet is to submit a +pull request or create an link:https://github.com/networkupstools/nut/issues[issue on GitHub]. -The issue tracker allows us to track the patches over a longer period of time, -and it is less likely that a patch will fall through the cracks. Posting a -reminder to the developers (via the nut-upsdev list) about a patch on GitHub is -fair game. +The issue tracker allows us to track the patches over a longer period +of time, and it is less likely that a patch will fall through the cracks. +Posting a reminder to the developers (via the nut-upsdev list) about a +patch on GitHub is fair game. Patch cohesion -------------- @@ -338,7 +389,7 @@ evaluated separately, assuming the core developers care enough to do that instead of just dropping it. If you have to make big changes in lots of places, send multiple -patches - one per item. +patches -- one per item. The finishing touches: manual pages and device entry in HCL ----------------------------------------------------------- @@ -360,32 +411,35 @@ HTML and dynamic searchable HTML for the website. Source code management ---------------------- -We currently use a Git repository hosted at GitHub (with a mirror at Alioth) to track -changes to the NUT source code. This allows you to clone the repository (or -fork, in GitHub parlance), make changes, and post them online for review prior -to integration. - -To obtain permission to commit directly to the master NUT repository, you must -be prepared to spend a fair amount of time contributing to the NUT codebase. -Most developers will be well served by committing to their own Git repository, -and having the NUT team merge their changes. - -Git offers a little more flexibility than the +svn update+ command. You may -fetch other developers' changes into your repository, but hold off on -actually combining them with your branch until you have compared the two -branches (for instance, with `gitk --all`). Git also allows you to accumulate -more than one commit worth of changes before pushing to another repository. -This allows development to continue without a constant network connection. - -For a quick change to a file in the Git working copy, you can use `git diff` to -generate a patch to send to the nut-upsdev mailing list. If you have more -extensive changes, you can use `git format-patch` on a complete commit or -branch, and send the resulting series of patches to the list. - -If you use GitHub's web-based editor to make changes, it tends to create lots -of small commits, one per change per file. Unless there is reason to keep the -intermediate history, we will probably collapse the entire branch into one -commit with `git rebase -i` before merging. +We currently use a Git repository hosted at GitHub (with a mirror at +Alioth) to track changes to the NUT source code. This allows you to +clone the repository (or fork, in GitHub parlance), make changes, and +post them online for review prior to integration. + +To obtain permission to commit directly to the master NUT repository, +you must be prepared to spend a fair amount of time contributing to the +NUT codebase. Most developers will be well served by committing to their +own Git repository, and having the NUT team merge their changes. + +Git offers a little more flexibility than the +svn update+ command. +You may fetch other developers' changes into your repository, but hold +off on actually combining them with your branch until you have compared +the two branches (for instance, with `gitk --all`). Git also allows you +to accumulate more than one commit worth of changes before pushing to +another repository. This allows development to continue without a constant +network connection. + +For a quick change to a file in the Git working copy, you can use +`git diff` to generate a patch to send to the nut-upsdev mailing list. +If you have more extensive changes, you can use `git format-patch` on +a complete commit or branch, and send the resulting series of patches +to the list. + +If you use GitHub's web-based editor to make changes, it tends to create +lots of small commits, one per change per file. Unless there is reason to +keep the intermediate history, we will probably collapse (or "squash" in +Git parlance) the entire branch into one commit with a `git rebase -i` +before merging. The link:https://git.wiki.kernel.org/index.php/GitSvnCrashCourse[GitSvnCrashCourse] wiki page has some useful information for long-time users of Subversion. @@ -401,18 +455,18 @@ or git clone https://github.com/networkupstools/nut.git -if it is necessary to get around a pesky firewall that blocks the native Git -protocol. +if it is necessary to get around a pesky firewall that blocks the native +Git protocol. For a quicker checkout (when you don't need the entire repository history), you can limit the depth of the clone: git clone --depth 1 git://github.com/networkupstools/nut.git -In case the GitHub repository is temporarily unavailable for any reason, we -also plan to push to Alioth's -link:https://alioth.debian.org/scm/?group_id=30602[Git server] as well. You can -add a remote reference to your local repository: +In case the GitHub repository is temporarily unavailable for any reason, +we also plan to push to Alioth's +link:https://alioth.debian.org/scm/?group_id=30602[Git server] as well. +You can add a remote reference to your local repository: cd path/to/nut git remote add -f alioth git://anonscm.debian.org/nut/nut.git @@ -420,27 +474,27 @@ add a remote reference to your local repository: Mercurial (hg) access ~~~~~~~~~~~~~~~~~~~~~ -There are those who prefer the simplicity and self-consistency of the Mercurial -SCM client over the hodgepodge of unique commands which make up Git. Rather -than debate the merits of each system, we will gently guide you towards the -link:http://hg-git.github.com/[hg-git project] which would theoretically be a -transparent bridge between the central Git repository, and your local Mercurial -working copy. +There are those who prefer the simplicity and self-consistency of the +Mercurial SCM client over the hodgepodge of unique commands which make +up Git. Rather than debate the merits of each system, we will gently +guide you towards the link:http://hg-git.github.com/[hg-git project] +which would theoretically be a transparent bridge between the central +Git repository, and your local Mercurial working copy. -Other tools for hg/git interoperability are sure to exist. We would welcome any -feedback about this process on the nut-upsdev mailing list. +Other tools for hg/git interoperability are sure to exist. We would +welcome any feedback about this process on the nut-upsdev mailing list. Subversion (SVN) access ~~~~~~~~~~~~~~~~~~~~~~~ If you prefer to check out the NUT source code using an SVN client, GitHub has a link:https://github.com/blog/966-improved-subversion-client-support[SVN -interface to Git repositories] hosted on their servers. You can fork a copy of -the NUT repository and commit to your fork with SVN. +interface to Git repositories] hosted on their servers. You can fork a copy +of the NUT repository and commit to your fork with SVN. -Be aware that the examples in the GitHub blog post might result in a checkout -that includes all of the current branches, as well as the trunk. You are most -likely interested in a command line similar to the following: +Be aware that the examples in the GitHub blog post might result in a +checkout that includes all of the current branches, as well as the trunk. +You are most likely interested in a command line similar to the following: svn co https://github.com/networkupstools/nut/trunk nut-trunk-svn @@ -451,12 +505,13 @@ The NUT repository generally only holds files which are not generated from other files. This prevents spurious differences from being recorded in the repository history. -If you add a driver, it is recommended that you add the driver executable name -to the .gitignore file in that directory. Similarly, files generated from *.in -and *.am sources should be ignored as well. We try to include a number of -generated files in the tarball releases with `make dist` hooks in order to -minimize the number of dependencies for end users, but the assumption is that -a developer can install the packages needed to regenerate those files. +If you add a driver, it is recommended that you add the driver executable +name to the `.gitignore` file in that directory. Similarly, files generated +from `*.in` and `*.am` source templates should be ignored as well. +We try to include a number of generated files in the tarball releases with +`make dist` hooks in order to minimize the number of dependencies for end +users, but the assumption is that a developer can install the packages +needed to regenerate those files. Commit message formatting ------------------------- @@ -464,11 +519,11 @@ Commit message formatting From the `git commit` man page: [quote] -Though not required, it's a good idea to begin the commit message with a single -short (less than 50 character) line summarizing the change, followed by a blank -line and then a more thorough description. The text up to the first blank line -in a commit message is treated as the commit title, and that title is used -throughout git. +Though not required, it's a good idea to begin the commit message with a +single short (less than 50 character) line summarizing the change, followed +by a blank line and then a more thorough description. The text up to the +first blank line in a commit message is treated as the commit title, and +that title is used throughout git. If your commit is just a change to one component, such as the HCL, upsd or a specific driver, prefix your commit message in a way that matches similar @@ -499,7 +554,8 @@ back into master once they are complete. You are encouraged to use `git rebase -i` on your private Git branches to separate your changes into <<_patch_cohesion,logical changes>>. -From there, you can generate patches for the issue tracker, or the nut-upsdev list. +From there, you can generate patches for the issue tracker, or the nut-upsdev +mailing list. Note that once you rebase a branch, anyone else who has a copy of this branch will need to rebase on top of your rebased branch. Obviously, this hinders @@ -516,7 +572,7 @@ stash pop+ to apply your saved changes. Here is an example workflow: --------------------------------------------------------------------------------- +------------------------------------------------------------------------------ git clone -o central git://github.com/networkupstools/nut.git cd nut @@ -543,7 +599,7 @@ Here is an example workflow: # Publish your branch to your GitHub repository: git push username my-new-feature --------------------------------------------------------------------------------- +------------------------------------------------------------------------------ If you are new to Git, but are familiar with SVN, the link:http://git-scm.com/course/svn.html[following link] may be of use. @@ -581,7 +637,7 @@ to be locally installed on your system, including asciidoc, a2x, xsltproc, dblatex and any additional XSL stylesheets. Running +make distcheck-light+ is especially important if you have added or -removed files, or updated configure.in or some Makefile.am. Remember: simply +removed files, or updated configure.ac or some Makefile.am. Remember: simply adding a file to Git does not mean it will be distributed. To distribute a file, you must update the corresponding Makefile.am. diff --git a/docs/documentation.txt b/docs/documentation.txt index ab3bd2c2e2..b8d7800b31 100644 --- a/docs/documentation.txt +++ b/docs/documentation.txt @@ -13,6 +13,7 @@ ifdef::website[] - Cables information (link:cables.html[online]) (link:docs/cables.pdf[PDF]) - link:docs/man/index.html#User_man[User manual pages] - link:ddl/index.html#_supported_devices[Devices Dumps Library (DDL)]: Provides information on how devices are supported +- link:docs/solaris-usb.html[Notes on NUT monitoring of USB devices in Solaris and related operating systems] endif::website[] ifndef::website[] - link:../FAQ.html[FAQ - Frequently Asked Questions] @@ -20,6 +21,7 @@ ifndef::website[] - <> - link:../man/index.html#User_man[User manual pages] - link:http://www.networkupstools.org/ddl/index.html#_supported_devices[Devices Dumps Library (DDL)]: Provides information on how devices are supported +- link:../solaris-usb.html[Notes on NUT monitoring of USB devices in Solaris and related operating systems] endif::website[] Developer Documentation @@ -59,7 +61,7 @@ These are general information about UPS, PDU, ATS, PSU and SCD: These are writeups by users of the software. - link:http://rogerprice.org/NUT.html[NUT Setup with openSUSE] '(Roger Price)' -- link:http://www.dimat.unina2.it/LCS/MonitoraggioUpsNutUbuntu10-eng.htm[Deploying NUT on an Ubuntu 10.04 cluster] '(Stefano Angelone)' +- link:http://www.dimat.unina2.it/LCS/MonitoraggioUpsNutUbuntu10-eng.htm[Deploying NUT on an Ubuntu 10.04 cluster] '(Stefano Angelone)' - link:http://blog.shadypixel.com/monitoring-a-ups-with-nut-on-debian-or-ubuntu-linux[Monitoring a UPS with nut on Debian or Ubuntu Linux] '(Avery Fay)' - link:http://linux.developpez.com/cours/upsusb/[Installation et gestion d'un UPS USB en réseau sous linux] '(Olivier Van Hoof, french)' - link:http://trac.networkupstools.org/projects/nut/wiki/NutOnMacOSX[Network UPS Tools (NUT) on Mac OS X (10.4.10)] '(Andy Poush)' diff --git a/docs/download.txt b/docs/download.txt index f61e5abe5c..2aa3282b5a 100644 --- a/docs/download.txt +++ b/docs/download.txt @@ -10,7 +10,7 @@ Source code ================================================================================ You should always use PGP/GPG to verify the signatures before using any source code. -You can use the +You can use the ifdef::website[] link:docs/user-manual.chunked/ar01s09.html#verifySourceSig[following procedure] endif::website[] @@ -51,7 +51,7 @@ following script in the directory you just checked out: $ ./autogen.sh -Then refer to the +Then refer to the ifdef::website[] link:docs/user-manual.chunked/index.html[NUT user manual] endif::website[] @@ -59,7 +59,7 @@ ifndef::website[] linkdoc:user-manual[NUT user manual] endif::website[] for more information. - + ////////////////////////// NOTE: Users that need the latest developments to support new devices *must* use Git or <>. @@ -102,7 +102,7 @@ NOTE: The only official releases from this project are source code. NUT is already available in the following systems: -- Linux: +- Linux: link:https://aur.archlinux.org/packages/network-ups-tools[Arch Linux], link:http://packages.debian.org/nut[Debian], link:http://packages.gentoo.org/package/sys-power/nut[Gentoo Linux], @@ -131,7 +131,8 @@ link:http://www.networkupstools.org/package/windows/NUT-Installer-2.6.5-6.msi[Wi Java packages ------------- -The jNut package has been split into its own link:https://github.com/networkupstools/jNut[GitHub repository]. +The jNut package has been split into its own +link:https://github.com/networkupstools/jNut[GitHub repository]. - NUT Java support (client side, Beta) link:http://www.networkupstools.org/package/java/jNut-0.2-SNAPSHOT.tar.gz[jNUT 0.2-SNAPSHOT] diff --git a/docs/features.txt b/docs/features.txt index eef38b6d21..4d8ad87b46 100644 --- a/docs/features.txt +++ b/docs/features.txt @@ -19,7 +19,7 @@ Multiple manufacturer and device support ---------------------------------------- - Monitors many UPS, PDU, ATS, PSU and SCD models from more than 140 -manufacturers with a unified interface +manufacturers with a unified interface (link:stable-hcl.html[Hardware Compatibility List]). - Various communication types and many protocols are supported with the same @@ -31,11 +31,12 @@ common interface: Multiple architecture support ----------------------------- -- Cross-platform - different flavors of Unix can be managed together with a +- Cross-platform -- different flavors of Unix can be managed together with a common set of tools, even crossing architectures. -- This software has been reported to run on Linux distributions, the BSDs, Apple's -OS X, Solaris, IRIX, HP/UX, Tru64 Unix, and AIX. +- This software has been reported to run on Linux distributions, the BSDs, +Apple's OS X, commercial Solaris and open-source illumos distros, IRIX, +HP/UX, Tru64 Unix, and AIX. - Windows users may be able to build it directly with Cygwin. There is also a port of the client-side monitoring to Windows called WinNUT. @@ -60,8 +61,8 @@ WARNING: Be sure to plug your network's physical hardware (switches, hubs, routers, bridges, ...) into the UPS! -Redundancy support - Hot swap/high availability power supplies --------------------------------------------------------------- +Redundancy support -- Hot swap/high availability power supplies +--------------------------------------------------------------- - upsmon can handle high-end servers which receive power from multiple UPSes simultaneously. @@ -70,14 +71,18 @@ simultaneously. source UPSes becomes critical (on battery and low battery). - You can lose a UPS completely as long as you still have at least the minimum -number of sources available. The minimum value is configurable. +number of sources available. The minimum value is configurable. Security and access control --------------------------- - Manager functions are granted with per-user granularity. The admin can have -full powers, while the admin's helper can only do specific non-destructive tasks -such as a battery test. +full powers, while the admin's helper can only do specific non-destructive +tasks such as a battery test (beware that with a worn-out battery whose +replacement is a few years overdue, a "capacity/remaining runtime" test can +still be destructive by powering off the load abruptly -- and also such a +test can cause hosts to hide into graceful shutdowns when the battery state +does get critical as part of the test). - The drivers, server, and monitoring client (upsmon) can all run as separate user IDs if this is desired for privilege separation. @@ -91,8 +96,8 @@ shutdown command. In any other case, the privileged process exits. This was inspired by the auth mechanism in Solar Designer's excellent popa3d. - The drivers and network server may be run in a chroot jail for further -security benefits. This is supported directly since version 1.4 and beyond with -the 'chroot=' configuration directive. +security benefits. This is supported directly since version 1.4 and beyond +with the 'chroot=' configuration directive. - IP-based access control relies on the local firewall and link:http://en.wikipedia.org/wiki/TCP_Wrapper[TCP Wrapper]. @@ -106,9 +111,9 @@ Web-based monitoring - Comes stock with CGI-based web interface tools for UPS monitoring and management, including graphical status displays. -- Custom status web pages may be generated with the CGI programs, since they use -templates to create the pages. This allows you to have status pages which fit -the look and feel of the rest of your site. +- Custom status web pages may be generated with the CGI programs, since they +use templates to create the pages. This allows you to have status pages which +fit the look and feel of the rest of your site. Free software ------------- @@ -116,39 +121,48 @@ Free software - That's free beer and free speech. Licensed under the GNU General Public License version 2 or later. -- Know your systems - all source code is available for inspection, so there are -no mysteries or secrets in your critical monitoring tools. +- Know your systems -- all source code is available for inspection, so there are +no mysteries or secrets in your critical monitoring tools. UPS management and control -------------------------- -- Writable variables may be edited on higher end equipment for local customization +- Writable variables may be edited on higher end equipment for local +customization -- Status monitoring can generate notifications (email/pager/SMS/...) on alert conditions +- Status monitoring can generate notifications (email/pager/SMS/...) on alert +conditions -- Alert notices may be dampened to only trigger after a condition persists. This -avoids the usual pager meltdown when something happens and no delay is used. +- Alert notices may be dampened to only trigger after a condition persists. +This avoids the usual pager meltdown when something happens and no delay +is used. - Maintenance actions such as battery runtime calibration are available where supported by the UPS hardware. -- Power statistics can be logged in custom formats for later retrieval and analysis +- Power statistics can be logged in custom formats for later retrieval and +analysis -- All drivers are started and stopped with one common program. Starting one is -as easy as starting ten: 'upsdrvctl start'. +- All drivers are started and stopped with one common program. Starting one +is as easy as starting ten: `upsdrvctl start`. + +- For operating systems with a supported service management framework, you can +manage the NUT drivers wrapped into independent service instances using the +'upsdrvsvcctl' instead, and gain the benefits of automated restart as well as +possibility to define further dependencies between your OS components. - Shutdowns and other procedures may be tested without stressing actual UPS -hardware by simulating status values with the dummy-ups pseudo-driver. Anything -which can happen in a driver can be replicated with dummy-ups. +hardware by simulating status values with the dummy-ups pseudo-driver. +Anything that can happen in a driver can be replicated with dummy-ups. Monitoring diagrams ------------------- -These are the most common situations for monitoring UPS hardware. Other ways are -possible, but they are mostly variants on these four. +These are the most common situations for monitoring UPS hardware. Other ways +are possible, but they are mostly variations of these four. -NOTE: these examples show serial communications for simplicity, but USB or SNMP -or any other monitoring is also possible. +NOTE: these examples show serial communications for simplicity, but USB or +SNMP or any other monitoring is also possible. "Simple" configuration ~~~~~~~~~~~~~~~~~~~~~~ @@ -157,8 +171,8 @@ image:images/simple.png[] One UPS, one computer. This is also known as "Standalone" configuration. -This is the configuration that most users will use. You need at least a driver, -upsd, and upsmon running. +This is the configuration that most users will use. You need at least a +driver, `upsd`, and `upsmon` running. "Advanced" configuration ~~~~~~~~~~~~~~~~~~~~~~~~ @@ -166,60 +180,70 @@ upsd, and upsmon running. image:images/advanced.png[] One UPS, multiple computers. Only one of them can actually talk to the UPS -directly. That's where the network comes in. The Master system runs the driver, -upsd, and upsmon in master mode. The Slave systems only run upsmon in slave mode. +directly. That's where the network comes in. The Master system runs the +relevant driver, `upsd`, and `upsmon` in master mode. The Slave systems +only run `upsmon` in slave mode. -This is useful when you have a very large UPS that's capable of running multiple -systems simultaneously. There is no longer the need to buy a bunch of individual -UPSes or "sharing" hardware, since this software will handle the sharing for you. +This is useful when you have a very large UPS that's capable of running +multiple systems simultaneously. There is no longer the need to buy a bunch +of individual UPSes or "sharing" hardware, since this software will handle +the sharing for you. -//////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// *FIXME* remainder === One UPS, many clients === -- Multiple systems may monitor a single UPS using only their network connections - no special "UPS sharing" hardware is required. +- Multiple systems may monitor a single UPS using only their network +connections -- no special "UPS sharing" hardware is required. -- "Slave and master" monitoring design synchronizes shutdowns so that slaves can bring down their operating systems cleanly before the master switches off the power. +- "Slave and master" monitoring design synchronizes shutdowns so that +slaves can bring down their operating systems cleanly before the master +switches off the power. === Many UPSes, many clients === - Each upsd process can serve status data for multiple UPSes to many clients. -- Each upsmon process can monitor multiple UPSes for status data. +- Each upsmon process can monitor multiple UPSes for status data. -//////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// "Big Box" configuration ~~~~~~~~~~~~~~~~~~~~~~~ image:images/bigbox.png[] -Some systems have multiple power supplies and cords. You typically find this on -high-end servers that allow hot-swap and other fun features. In this case, you -run multiple drivers (one per UPS), a single upsd, and a single upsmon (as -master for both UPS 1 and UPS 2) +Some systems have multiple power supplies and cords. You typically find +this on high-end servers that allow hot-swap and other fun features. +In this case, you run multiple drivers (one per UPS), a single `upsd`, +and a single `upsmon` (as a master for both UPS 1 and UPS 2) + +This software understands that some of these servers can also run with +some of the supplies gone. For this reason, every UPS is assigned a +"power value" -- the quantity of power supplies that it feeds on this +system. + +The total available "power value" is compared to the minimum that is +required for that hardware. For example, if you have 3 power supplies +and 3 UPSes, but only 2 supplies must be running at any given moment, +the minimum would be 2. -This software understands that some of these servers can also run with some of -the supplies gone. For this reason, every UPS is assigned a "power value" - the -quantity of power supplies that it feeds on a system. -The total available "power value" is compared to the minimum that is required -for that hardware. For example, if you have 3 power supplies and 3 UPSes, but -only 2 supplies must be running at any given moment, the minimum would be 2. -This means that you can safely lose any one UPS and the software will handle it -properly by remaining online. +This means that you can safely lose any one UPS and the software will +handle it properly by remaining online and not causing a shut down. "Bizarre" configuration ~~~~~~~~~~~~~~~~~~~~~~~ image:images/bizarre.png[] -You can even have a UPS that has the serial port connected to a system that it's -not feeding. Sometimes a PC will be close to a UPS that needs to be monitored, -so it's drafted to supply a serial port for the purpose. This PC may in fact be -getting power from some other UPS. This is not a problem. +You can even have a UPS that has the serial port connected to a system that +it's not feeding. Sometimes a PC will be close to a UPS that needs to be +monitored, so it's drafted to supply a serial port for the purpose. +This PC may in fact be getting its own power from some other UPS. This is +not a problem for the set-up. -The first system ("mixed") is a Master for UPS 1, but is only monitoring UPS 2. -The other systems are Slaves of UPS 2. +The first system ("mixed") is a Master for UPS 1, but is only monitoring +UPS 2. The other systems are Slaves of UPS 2. Image credits ------------- diff --git a/docs/hid-subdrivers.txt b/docs/hid-subdrivers.txt index 2a1b79e1ff..e48ecf7b95 100644 --- a/docs/hid-subdrivers.txt +++ b/docs/hid-subdrivers.txt @@ -116,7 +116,7 @@ example Belkin defines `00860040` = ConfigVoltage (which is incidentally a violation of the USB PDC specification, as `00860040` is reserved for future use). -Thus, subdrivers generally need to provide: +Thus, subdrivers generally need to provide: - manufacturer-specific usage definitions, - a mapping of HID variables to NUT variables. @@ -133,17 +133,17 @@ Writing a subdriver In preparation for writing a subdriver for a device that is currently unsupported, run usbhid-ups with the following command line: - drivers/usbhid-ups -DD -u root -x explore -x vendorid=XXXX -x port=auto -s ups + drivers/usbhid-ups -DD -u root -x explore -x vendorid=XXXX -x port=auto -s ups -(substitute your device's 4-digit VendorID instead of "XXXX"). -This will produce a bunch of debugging information, including a number -of lines starting with "Path:" that describe the device's usage tree. -This information forms the initial basis for a new subdriver. +(substitute your device's 4-digit VendorID instead of "XXXX"). +This will produce a bunch of debugging information, including a number +of lines starting with "Path:" that describe the device's usage tree. +This information forms the initial basis for a new subdriver. -You should save this information to a file, e.g. +You should save this information to a file, e.g.: - drivers/usbhid-ups -DD -u root -x explore -x vendorid=XXXX \ - -x port=auto -s ups 2>&1 | tee /tmp/info + drivers/usbhid-ups -DD -u root -x explore -x vendorid=XXXX \ + -x port=auto -s ups 2>&1 | tee /tmp/info You can create an initial "stub" subdriver for your device by using script scripts/subdriver/gen-usbhid-subdriver.sh. Note: this only creates diff --git a/docs/history.txt b/docs/history.txt index e31c933390..be308675ba 100644 --- a/docs/history.txt +++ b/docs/history.txt @@ -8,7 +8,7 @@ This page is an attempt to document how everything came together. The Network UPS Tools team would like to warmly thank Russell Kroll. Russell initially started this project, maintaining and improving it for -over 8 years (1996 - mid 2005). +over 8 years (1996 -- mid 2005). Prototypes and experiments -------------------------- @@ -144,15 +144,15 @@ September 1999: new name, new URL Several visitors to the web page and subscribers to the mailing lists provided suggestions to rename the project. The old name no longer accurately described -it, and it was perilously close to APC's "Smart-UPS" trademark. Rather than risk -problems in the future, the name was changed. Kern Sibbald provided the winner: -Network UPS Tools, which captures the essence of the project and makes for great -short tarball filenames: nut-x.y.z.tar.gz. +it, and it was perilously close to APC's "Smart-UPS" trademark. Rather than +risk problems in the future, the name was changed. Kern Sibbald provided the +winner: Network UPS Tools, which captures the essence of the project and makes +for great short tarball filenames: nut-x.y.z.tar.gz. -The new name was first applied to 0.42.0, released October 31, 1999. This is -also when the web pages moved from the old `http://www.exploits.org/~rkroll/smartupstools/` -URL to the replacement at `http://www.exploits.org/nut/` to coincide with the -name change. +The new name was first applied to 0.42.0, released October 31, 1999. +This is also when the web pages moved from the old +`http://www.exploits.org/~rkroll/smartupstools/` URL to the replacement +at `http://www.exploits.org/nut/` to coincide with the name change. More drivers were written and the hardware support continued to grow. upsmon picked up the concepts of "master" and "slave", and could now handle @@ -165,28 +165,52 @@ June 2001: common driver core Up to this point, all of the drivers compiled into freestanding programs, each providing their own implementation of main(). This meant they all had to check -the incoming arguments and act uniformly. Unfortunately, not all of the programs -behaved the same way, and it was hard to document and use consistently. It also -meant that startup scripts had to be edited depending on what kind of hardware -was attached. - -Starting in 0.45.0, released June 11, 2001, there was a new common core for all drivers called main.c. It provided the main function and called back to the upsdrv_* functions provided by the hardware-specific part of the drivers. This allowed driver authors to focus on the UPS hardware without worrying about the housekeeping stuff that needs to happen. - -This new design provided an obvious way to configure drivers from one file, and ups.conf was born. This eventually spawned upsdrvctl, and now all drivers based on this common core could be started or stopped with one command. Startup scripts now could contain "upsdrvctl start", and it didn't matter what kind of hardware or how many UPSes you had on one system. - -Interestingly, at the end of this month, Arnaud Quette entered the UPS world, as a subcontractor of the now defunct MGE UPS SYSTEMS. -This marks the start of a future successful collaboration. +the incoming arguments and act uniformly. Unfortunately, not all of the +programs behaved the same way, and it was hard to document and use consistently. +It also meant that startup scripts had to be edited depending on what kind of +hardware was attached. + +Starting in 0.45.0, released June 11, 2001, there was a new common core for +all drivers called `main.c`. It provided the main function and called back to +the `upsdrv_*` functions provided by the hardware-specific part of the drivers. +This allowed driver authors to focus on the UPS hardware without worrying about +the housekeeping stuff that needs to happen. + +This new design provided an obvious way to configure drivers from one file, and +so `ups.conf` was born. This eventually spawned upsdrvctl, and now all drivers +based on this common core could be started or stopped with one command. Startup +scripts now could contain "upsdrvctl start", and it didn't matter what kind of +hardware or how many UPSes you had on one system. + +Interestingly, at the end of this month, Arnaud Quette entered the UPS world, +as a subcontractor of the now defunct MGE UPS SYSTEMS. This marked the start of +a future successful collaboration. May 2002: casting off old drivers, IANA port, towards 1.0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -During the 0.45.x series, both the old standalone drivers and the ones which had been converted to the common core were released together. Before the release of 0.50.0 on May 24, 2002, all of the old drivers were removed. While this shrank the list of supported hardware, it set the precedent for removing code which isn't receiving regular maintenance. The assumption is that the code will be brought back up to date by someone if they actually need it. Otherwise, it's just dead weight in the tree. - -This change meant that all drivers could be controlled with upsdrvctl and ups.conf, allowing the documentation to be greatly simplified. There was no longer any reason to say "do this, unless you have this driver, then do this". - -IANA granted an official port number to the project, and the network code switched to port 3493. It had previously been on 3305 which is assigned to odette-ftp. 3305 was probably picked in 1997 because it was the fifth project to spawn from some common UDP server code. - -After 0.50.1, the 0.99 tree was created to provide a tree which would receive nothing but bug fixes in preparation for the release of 1.0. As it turned out, very few things required fixing, and there were only three releases in this tree. +During the 0.45.x series, both the old standalone drivers and the ones which +had been converted to the common core were released together. Before the +release of 0.50.0 on May 24, 2002, all of the old drivers were removed. +While this shrank the list of supported hardware, it set the precedent for +removing code which isn't receiving regular maintenance. The assumption is +that the code will be brought back up to date by someone if they actually +need it. Otherwise, it's just dead weight in the tree. + +This change meant that all remaining drivers could be controlled with the +`upsdrvctl` and `ups.conf`, allowing the documentation to be greatly +simplified. There was no longer any reason to say "do this, unless you +have this driver, then do this". + +IANA granted an official port number to the project, and the network code +switched to port 3493. It had previously been on 3305 which is assigned to +`odette-ftp`. 3305 was probably picked in 1997 because it was the fifth +project to spawn from some common UDP server code. + +After 0.50.1, the 0.99 tree was created to provide a tree which would receive +nothing but bug fixes in preparation for the release of 1.0. As it turned out, +very few things required fixing, and there were only three releases in this +tree. Leaving 0.x territory --------------------- @@ -194,51 +218,119 @@ Leaving 0.x territory August 2002: first stable tree: NUT 1.0.0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -After nearly 5 years of having a 0.x version number, 1.0.0 was released on August 19, 2002. This milestone meant that all of the base features that you would expect to find were intact: good hardware support, a network server with security controls, and system shutdowns that worked. +After nearly 5 years of having a 0.x version number, 1.0.0 was released on +August 19, 2002. This milestone meant that all of the base features that +you would expect to find were intact: good hardware support, a network +server with security controls, and system shutdowns that worked. -The design was showing signs of wear from the rapid expansion, but this was intentionally ignored for the moment. The focus was on getting a good version out that would provide a reasonable base while the design issues could be addressed in the future, and I'm confident that we succeeded. +The design was showing signs of wear from the rapid expansion, but this was +intentionally ignored for the moment. The focus was on getting a good version +out that would provide a reasonable base while the design issues could be +addressed in the future, and I'm confident that we succeeded. November 2002: second stable tree: NUT 1.2.0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -One day after the release of 1.0.0, 1.1.0 started the new development tree. During that development cycle, the CGI programs were rewritten to use templates instead of hard-coded HTML, thus bringing back the flexibility of the original unreleased prototype from 5 years before. multimon was removed from the tree, as the new upsstats could do both jobs by loading different templates. +One day after the release of 1.0.0, 1.1.0 started the new development tree. +During that development cycle, the CGI programs were rewritten to use template +files instead of hard-coded HTML, thus bringing back the flexibility of the +original unreleased prototype from 5 years before. The `multimon` was removed +from the tree, as the new `upsstats` could do both jobs by loading different +templates. -A new client library called upsclient was created, and it replaced upsfetch. This new library only supported TCP connections, and used an opaque context struct to keep state for each connection. As a result, client programs could now do things that used multiple connections without any conflicts. This was done primarily to allow OpenSSL support, but there were other benefits from the redesign. +A new client library called upsclient was created, and it replaced upsfetch. +This new library only supported TCP connections, and used an opaque context +struct to keep state for each connection. As a result, client programs could +now do things that used multiple connections without any conflicts. This was +done primarily to allow OpenSSL support, but there were other benefits from +the redesign. -upsd and the clients could now use OpenSSL for basic authentication and encryption, but this was not included by default. This was provided as a bonus feature for those users who cared to read about it and enable the option, as the initial setup was complex. +upsd and the clients could now use OpenSSL for basic authentication and +encryption, but this was not included by default. This was provided as +a bonus feature for those users who cared to read about it and enable +the option, as the initial setup was complex. -After the 1.1 tree was frozen and deemed complete, it became the second stable tree with the release of 1.2.0 on November 5, 2002. +After the 1.1 tree was frozen and deemed complete, it became the second +stable tree with the release of 1.2.0 on November 5, 2002. April 2003: new naming scheme, better driver glue, and an overhauled protocol ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Following an extended period with no development tree, 1.3.0 got things moving again on April 13, 2003. The focus of this tree was to rewrite the driver-server communication layer and replace the static naming scheme for variables and commands. - -Up to this point, all variables had names like STATUS, UTILITY, and OUTVOLT. They had been created as drivers were added to the tree, and there was little consistency. For example, it probably should have been INVOLT and OUTVOLT, but there was no OUTVOLT originally, so UTILITY was all we had. This same pattern repeated with ACFREQ - is it incoming or outgoing? - and many more. - -To solve this problem, all variables and commands were renamed to a hierarchical scheme that had obvious grouping. STATUS became ups.status. UTILITY turned into input.voltage, and OUTVOLT is output.voltage. ACFREQ is input.frequency, and the new output.frequency is also now supported. Every other variable or command was renamed in this fashion. - -These variables had been shared between the drivers and upsd as values. That is, for each name like STATUS, there was a #define somewhere in the tree with an INFO_ prefix that gave it a number. INFO_STATUS was 0x0006, INFO_UTILITY was 0x0004, and so on, with each name having a matching number. This number was stored in an int within a structure which was part of the array that was either written to disk or shared memory. - -That structure had several restrictions on expansion and was dropped as the data sharing method between the drivers and the server. It was replaced by a new system of text-based messages over Unix domain sockets. Drivers now accepted a short list of commands from upsd, and would push out updates asynchronously. upsd no longer had to poll the state files or shared memory. It could just select all of the driver and client fds and act on events. - -At the same time, the network protocol on port 3493 was overhauled to take advantage of the new naming scheme. The existing "REQ STATUS@su700", "ANS STATUS@su700 OL" scheme was showing signs of age, and it really only supported the UPS name (@su700) as an afterthought. The new protocol would now use commands like GET and LIST, leading to exchanges like "GET VAR su700 ups.status" and "VAR su700 ups.status OL". The responses contain enough data to stand alone, so clients can now handle them asynchronously. +Following an extended period with no development tree, 1.3.0 got things +moving again on April 13, 2003. The focus of this tree was to rewrite +the driver-server communication layer and replace the static naming +scheme for variables and commands. + +Up to this point, all variables had names like STATUS, UTILITY, and OUTVOLT. +They had been created as drivers were added to the tree, and there was little +consistency. For example, it probably should have been INVOLT and OUTVOLT, +but there was no OUTVOLT originally, so UTILITY was all we had. This same +pattern repeated with ACFREQ -- is it incoming or outgoing? -- and many more. + +To solve this problem, all variables and commands were renamed to a +hierarchical scheme that had obvious grouping. STATUS became ups.status. +UTILITY turned into input.voltage, and OUTVOLT is output.voltage. +ACFREQ is input.frequency, and the new output.frequency is also now +supported. Every other variable or command was renamed in this fashion. + +These variables had been shared between the drivers and upsd as values. +That is, for each name like STATUS, there was a #define somewhere in the +tree with an INFO_ prefix that gave it a number. INFO_STATUS was 0x0006, +INFO_UTILITY was 0x0004, and so on, with each name having a matching number. +This number was stored in an int within a structure which was part of the +array that was either written to disk or shared memory. + +That structure had several restrictions on expansion and was dropped as the +data sharing method between the drivers and the server. It was replaced by +a new system of text-based messages over Unix domain sockets. Drivers now +accepted a short list of commands from upsd, and would push out updates +asynchronously. upsd no longer had to poll the state files or shared memory. +It could just select all of the driver and client fds and act on events. + +At the same time, the network protocol on port 3493 was overhauled to take +advantage of the new naming scheme. The existing "REQ STATUS@su700", +"ANS STATUS@su700 OL" scheme was showing signs of age, and it really +only supported the UPS name (@su700) as an afterthought. The new protocol +would now use commands like GET and LIST, leading to exchanges like +"GET VAR su700 ups.status" and "VAR su700 ups.status OL". These responses +contain enough data to stand alone, so clients can now handle them +asynchronously. July 2003: third stable tree: NUT 1.4.0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -On July 25, 2003, 1.4.0 was released. It contained support for both the old "REQ" style protocol (with names like STATUS), and the new "GET" style protocol (with names like ups.status). This tree is provided to bridge the gap between all of the old releases and the upcoming 2.0. +On July 25, 2003, 1.4.0 was released. It contained support for both the +old "REQ" style protocol (with names like STATUS), and the new "GET" style +protocol (with names like ups.status). This tree is provided to bridge the +gap between all of the old releases and the upcoming 2.0. -2.0 will be released without support for the old REQ/STATUS protocol. The hope is that client authors and those who have implemented their own monitoring software will use the 1.4 cycle to change to the new protocol. The 1.4 releases contain a lot of compatibility code to make sure both work at the same time. +2.0 will be released without support for the old REQ/STATUS protocol. +The hope is that client authors and those who have implemented their own +monitoring software will use the 1.4 cycle to change to the new protocol. +The 1.4 releases contain a lot of compatibility code to make sure both +work at the same time. July 2003: pushing towards 2.0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -1.5.0 forked from 1.4.0 and was released on July 29, 2003. The first changes were to throw out anything which was providing compatibility with the older versions of the software. This means that 1.5 and the eventual 2.0 will not talk to anything older than 1.4. - -This tree continues to evolve with new serial routines for the drivers which are intended to replace the aging upscommon code which dates back to the early 0.x releases. The original routines would call alarm and read in a tight loop while fetching characters. The new functions are much cleaner, and wait for data with select. This makes for much cleaner code and easier strace/ktrace logs, since the number of syscalls has been greatly reduced. - -There has also been a push to make sure the data from the UPS is well-formed and is actually usable before sending updates out to upsd. This started during 1.3 as drivers were adapted to use the dstate functions and the new variable/command names. Some drivers which were not converted to the new naming scheme or didn't do sanity checks on the incoming UPS data from the serial port were dropped from the tree. +1.5.0 forked from 1.4.0 and was released on July 29, 2003. The first changes +were to throw out anything which was providing compatibility with the older +versions of the software. This means that 1.5 and the eventual 2.0 will not +talk to anything older than 1.4. + +This tree continues to evolve with new serial routines for the drivers which +are intended to replace the aging upscommon code which dates back to the early +0.x releases. The original routines would call alarm and read in a tight loop +while fetching characters. The new functions are much cleaner, and wait for +data with select. This makes for much cleaner code and easier strace/ktrace +logs, since the number of syscalls has been greatly reduced. + +There has also been a push to make sure the data from the UPS is well-formed +and is actually usable before sending updates out to upsd. This started +during 1.3 as drivers were adapted to use the dstate functions and the +new variable/command names. Some drivers which were not converted to the +new naming scheme or didn't do sanity checks on the incoming UPS data from +the serial port were dropped from the tree. This tree was released as 2.0.0. @@ -248,11 +340,23 @@ networkupstools.org November 2003: a new URL ~~~~~~~~~~~~~~~~~~~~~~~~ -The bandwidth demands of a project like this have slowly been forcing me to offload certain parts to other servers. The download links have pointed offsite for many months, and other large things like certain UPS protocols have followed. As the traffic grows, it's clear that having the project attached to exploits.org is not going to work. +The bandwidth demands of a project like this have slowly been forcing me to +offload certain parts to other servers. The download links have pointed +offsite for many months, and other large things like certain UPS protocols +have followed. As the traffic grows, it's clear that having the project +attached to exploits.org is not going to work. -The solution was to register a new domain and set up mirrors. There are two initial web servers, with more on the way. The main project URL has changed from `http://www.exploits.org/nut/` to http://www.networkupstools.org. The actual content is hosted on various mirrors which are updated regularly with rsync, so the days of dribbling bits through my DSL should be over. +The solution was to register a new domain and set up mirrors. There are two +initial web servers, with more on the way. The main project URL has changed +from `http://www.exploits.org/nut/` to http://www.networkupstools.org. +The actual content is hosted on various mirrors which are updated regularly +with rsync, so the days of dribbling bits through my DSL should be over. -This is also when all of the web pages were redesigned to have a simpler look with fewer links on the left side. The old web pages used to have 30 or more links on the top page, and most of them vanished when you dropped down one level. The links are now constant on the entire site, and the old links now live in their own groups in separate directories. +This is also when all of the web pages were redesigned to have a simpler +look with fewer links on the left side. The old web pages used to have 30 +or more links on the top page, and most of them vanished when you dropped +down one level. The links are now constant on the entire site, and the old +links now live in their own groups in separate directories. Second major version -------------------- @@ -279,7 +383,7 @@ At that time, the development process was still centralized. There was no revision control system (like the current Subversion repository), nor trackers to interact with NUT development. Russell was receiving all the patches and requests, and doing all the work on -his own, including releases. +his own, including releases. Russell was more and more thinking about giving the project leadership to Arnaud Quette, which finally happened with the 2.0.1 release in February 2005. @@ -287,10 +391,11 @@ Arnaud Quette, which finally happened with the 2.0.1 release in February 2005. This marked a new era for NUT... First, Arnaud aimed at opening up the development by creating a project on the -http://www.debian.org/[Debian] http://alioth.debian.org/projects/nut/[Alioth Forge]. +http://www.debian.org/[Debian] +http://alioth.debian.org/projects/nut/[Alioth Forge]. This allowed to build the team of hackers that Russell dreamed about. It also allows to ensure NUT's continuation, whatever happens to -the leader. And that would most of all boost the projects contributions. +the leader. And that would most of all boost the projects contributions. //////////////////////////////////////////////////////////////////////// diff --git a/docs/macros.txt b/docs/macros.txt index efd9dd75b8..b32da5b6db 100644 --- a/docs/macros.txt +++ b/docs/macros.txt @@ -44,11 +44,11 @@ directory. - NUT_CHECK_OS Check for the exact system name and type. - This was only used in the past to determine the packaging rule to be used - through the OS_NAME variable, but may be useful for other purposes in the - future. + This was only used in the past to determine the packaging rule to be + used through the OS_NAME variable, but may be useful for other purposes + in the future. -- NUT_REPORT_FEATURE(FEATURE, VALUE, VARIABLE, DESCRIPTION) +- NUT_REPORT_FEATURE(FEATURE, VALUE, VARIABLE, DESCRIPTION) Schedule a line for the end-of-configuration feature summary. The FEATURE is a descriptive string such that the sentence "Checking @@ -62,7 +62,7 @@ directory. - NUT_REPORT(FEATURE, VALUE) Schedule a line for the end-of-configuration feature summary, without - printing anything to the terminal immediately. + printing anything to the terminal immediately. - NUT_PRINT_FEATURE_REPORT diff --git a/docs/maintainer-guide.txt b/docs/maintainer-guide.txt index e3e5268ff4..3c16955a67 100644 --- a/docs/maintainer-guide.txt +++ b/docs/maintainer-guide.txt @@ -49,16 +49,16 @@ message explaining the reason. The following can serve as a base: Your message to the nut-upsXXX mailing was rejected because you must suscribe to the mailing list. This is just to eradicate spam noise from the mailing list. - + Use the following link to subscribe to this mailing list: https://lists.alioth.debian.org/mailman/listinfo/nut-upsXXX - + where 'XXX' can be replaced by 'user', 'dev' or 'packaging'. NUT maintainers -/////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// !! DRAFT !! Release process @@ -80,13 +80,13 @@ process. SANDBOX (to be completed and pushed) -• update version to (ex: 2.7.3) in nut/configure.ac -• create a GPG-signed tag v (ex: v2.7.3) -• make dist -• maybe update nut/configure.ac version to .1 (ex: 2.7.3.1) -• push commits and tag -• update nut/ and ddl/ submodules in nut-website/ (this should update the website's version as well) -• add download hashes for tarball +* update version to (ex: 2.7.3) in nut/configure.ac +* create a GPG-signed tag v (ex: v2.7.3) +* `make dist` +* maybe update nut/configure.ac version to .1 (ex: 2.7.3.1) +* push commits and tag +* update nut/ and ddl/ submodules in nut-website/ (this should update the website's version as well) +* add download hashes for tarball -/////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// diff --git a/docs/man/Makefile.am b/docs/man/Makefile.am index 94a16b4d9c..86434fb33d 100644 --- a/docs/man/Makefile.am +++ b/docs/man/Makefile.am @@ -47,10 +47,12 @@ HTML_CONF_MANS = \ SRC_CLIENT_PAGES = \ nutupsdrv.txt \ + nut-driver-enumerator.txt \ upsc.txt \ upscmd.txt \ upsd.txt \ upsdrvctl.txt \ + upsdrvsvcctl.txt \ upslog.txt \ upsmon.txt \ upsrw.txt \ @@ -59,10 +61,12 @@ SRC_CLIENT_PAGES = \ if WITH_MANS MAN_CLIENT_PAGES = \ nutupsdrv.8 \ + nut-driver-enumerator.8 \ upsc.8 \ upscmd.8 \ upsd.8 \ upsdrvctl.8 \ + upsdrvsvcctl.8 \ upslog.8 \ upsmon.8 \ upsrw.8 \ @@ -73,10 +77,12 @@ man8_MANS = $(MAN_CLIENT_PAGES) HTML_CLIENT_MANS = \ nutupsdrv.html \ + nut-driver-enumerator.html \ upsc.html \ upscmd.html \ upsd.html \ upsdrvctl.html \ + upsdrvsvcctl.html \ upslog.html \ upsmon.html \ upsrw.html \ @@ -177,7 +183,7 @@ SRC_DEV_PAGES = \ if WITH_MANS # NOTE: nutclient_*.3 has no source counterpart (libnutclient_*.txt) -LIBNUTCLIENT_MISC_DEPS= +LIBNUTCLIENT_MISC_DEPS= \ nutclient_authenticate.3 \ nutclient_logout.3 \ nutclient_device_login.3 \ @@ -185,6 +191,55 @@ LIBNUTCLIENT_MISC_DEPS= nutclient_device_master.3 \ nutclient_device_forced_shutdown.3 +$(LIBNUTCLIENT_MISC_DEPS): libnutclient_misc.3 + touch $@ + +LIBNUTCLIENT_TCP_DEPS= \ + nutclient_tcp_create_client.3 \ + nutclient_tcp_disconnect.3 \ + nutclient_tcp_get_timeout.3 \ + nutclient_tcp_is_connected.3 \ + nutclient_tcp_reconnect.3 \ + nutclient_tcp_set_timeout.3 + +$(LIBNUTCLIENT_TCP_DEPS): libnutclient_tcp.3 + touch $@ + +LIBNUTCLIENT_GENERAL_DEPS= \ + nutclient_destroy.3 + +$(LIBNUTCLIENT_GENERAL_DEPS): libnutclient_general.3 + touch $@ + +LIBNUTCLIENT_VARIABLES_DEPS= \ + nutclient_get_device_rw_variables.3 \ + nutclient_get_device_variable_description.3 \ + nutclient_get_device_variables.3 \ + nutclient_get_device_variable_values.3 \ + nutclient_has_device_variable.3 \ + nutclient_set_device_variable_value.3 \ + nutclient_set_device_variable_values.3 + +$(LIBNUTCLIENT_VARIABLES_DEPS): libnutclient_variables.3 + touch $@ + +LIBNUTCLIENT_COMMANDS_DEPS= \ + nutclient_execute_device_command.3 \ + nutclient_get_device_command_description.3 \ + nutclient_get_device_commands.3 \ + nutclient_has_device_command.3 + +$(LIBNUTCLIENT_COMMANDS_DEPS): libnutclient_commands.3 + touch $@ + +LIBNUTCLIENT_DEVICES_DEPS= \ + nutclient_get_device_description.3 \ + nutclient_get_devices.3 \ + nutclient_has_device.3 + +$(LIBNUTCLIENT_DEVICES_DEPS): libnutclient_devices.3 + touch $@ + MAN3_DEV_PAGES = \ upsclient.3 \ upscli_add_host_cert.3 \ @@ -197,7 +252,9 @@ MAN3_DEV_PAGES = \ upscli_list_next.3 \ upscli_list_start.3 \ upscli_readline.3 \ + upscli_readline_timeout.3 \ upscli_sendline.3 \ + upscli_sendline_timeout.3 \ upscli_splitaddr.3 \ upscli_splitname.3 \ upscli_ssl.3 \ @@ -205,33 +262,17 @@ MAN3_DEV_PAGES = \ upscli_upserror.3 \ libnutclient.3 \ libnutclient_commands.3 \ + $(LIBNUTCLIENT_COMMANDS_DEPS) \ libnutclient_devices.3 \ + $(LIBNUTCLIENT_DEVICES_DEPS) \ libnutclient_general.3 \ + $(LIBNUTCLIENT_GENERAL_DEPS) \ libnutclient_misc.3 \ + $(LIBNUTCLIENT_MISC_DEPS) \ libnutclient_tcp.3 \ + $(LIBNUTCLIENT_TCP_DEPS) \ libnutclient_variables.3 \ - $(LIBNUTCLIENT_MISC_DEPS) - nutclient_destroy.3 \ - nutclient_execute_device_command.3 \ - nutclient_get_device_command_description.3 \ - nutclient_get_device_commands.3 \ - nutclient_get_device_description.3 \ - nutclient_get_device_rw_variables.3 \ - nutclient_get_devices.3 \ - nutclient_get_device_variable_description.3 \ - nutclient_get_device_variables.3 \ - nutclient_get_device_variable_values.3 \ - nutclient_has_device.3 \ - nutclient_has_device_command.3 \ - nutclient_has_device_variable.3 \ - nutclient_set_device_variable_value.3 \ - nutclient_set_device_variable_values.3 \ - nutclient_tcp_create_client.3 \ - nutclient_tcp_disconnect.3 \ - nutclient_tcp_get_timeout.3 \ - nutclient_tcp_is_connected.3 \ - nutclient_tcp_reconnect.3 \ - nutclient_tcp_set_timeout.3 \ + $(LIBNUTCLIENT_VARIABLES_DEPS) \ nutscan.3 \ nutscan_scan_snmp.3 \ nutscan_scan_usb.3 \ @@ -250,7 +291,10 @@ MAN3_DEV_PAGES = \ nutscan_get_serial_ports_list.3 \ nutscan_init.3 -$(LIBNUTCLIENT_MISC_DEPS): libnutclient_misc.3 +upscli_readline_timeout.3: upscli_readline.3 + touch $@ + +upscli_sendline_timeout.3: upscli_sendline.3 touch $@ MAN1_DEV_PAGES = \ @@ -350,7 +394,6 @@ SRC_SERIAL_PAGES = \ mge-utalk.txt \ oneac.txt \ microdowell.txt \ - nutdrv_qx.txt \ optiups.txt \ powercom.txt \ powerpanel.txt \ @@ -391,7 +434,6 @@ MAN_SERIAL_PAGES = \ metasys.8 \ mge-shut.8 \ mge-utalk.8 \ - nutdrv_qx.8 \ oneac.8 \ microdowell.8 \ optiups.8 \ @@ -438,7 +480,6 @@ HTML_SERIAL_MANS = \ metasys.html \ mge-shut.html \ mge-utalk.html \ - nutdrv_qx.html \ oneac.html \ microdowell.html \ optiups.html \ @@ -472,7 +513,6 @@ SRC_USB_LIBUSB_PAGES = \ blazer-common.txt \ blazer_usb.txt \ nutdrv_atcl_usb.txt \ - nutdrv_qx.txt \ richcomm_usb.txt \ riello_usb.txt \ tripplite_usb.txt \ @@ -483,7 +523,6 @@ MAN_USB_LIBUSB_PAGES = \ bcmxcp_usb.8 \ blazer_usb.8 \ nutdrv_atcl_usb.8 \ - nutdrv_qx.8 \ richcomm_usb.8 \ riello_usb.8 \ tripplite_usb.8 \ @@ -497,13 +536,32 @@ endif HTML_USB_LIBUSB_MANS = \ bcmxcp_usb.html \ blazer_usb.html \ - nutdrv_qx.html \ nutdrv_atcl_usb.html \ richcomm_usb.html \ riello_usb.html \ tripplite_usb.html \ usbhid-ups.html +# (--with-serial / --with-usb) +SRC_SERIAL_USB_PAGES = \ + nutdrv_qx.txt + +if WITH_MANS +MAN_SERIAL_USB_PAGES = \ + nutdrv_qx.8 +endif + +if WITH_SERIAL + man8_MANS += $(MAN_SERIAL_USB_PAGES) +else +if WITH_USB + man8_MANS += $(MAN_SERIAL_USB_PAGES) +endif +endif + +HTML_SERIAL_USB_MANS = \ + nutdrv_qx.html + # (--with-neon) SRC_NETXML_PAGES = netxml-ups.txt if WITH_MANS @@ -562,16 +620,16 @@ endif HTML_MODBUS_MANS = phoenixcontact_modbus.html -SRC_LINUX_I2C_PAGES = asem.txt +SRC_LINUX_I2C_PAGES = asem.txt pijuice.txt if WITH_MANS -MAN_LINUX_I2C_PAGES = asem.8 +MAN_LINUX_I2C_PAGES = asem.8 pijuice.8 endif if WITH_LINUX_I2C - man8_MANS += $(LINUX_I2C_PAGES) + man8_MANS += $(MAN_LINUX_I2C_PAGES) endif -HTML_LINUX_I2C_MANS = asem.html +HTML_LINUX_I2C_MANS = asem.html pijuice.html # SOME_DRIVERS endif @@ -589,6 +647,7 @@ MAN_MANS += \ $(MAN_SERIAL_PAGES) \ $(MAN_SNMP_PAGES) \ $(MAN_USB_LIBUSB_PAGES) \ + $(MAN_SERIAL_USB_PAGES) \ $(MAN_NETXML_PAGES) \ $(MAN_POWERMAN_PAGES) \ $(MAN_IPMIPSU_PAGES) \ @@ -608,6 +667,7 @@ SRC_ALL_PAGES = \ $(SRC_SERIAL_PAGES) \ $(SRC_SNMP_PAGES) \ $(SRC_USB_LIBUSB_PAGES) \ + $(SRC_SERIAL_USB_PAGES) \ $(SRC_NETXML_PAGES) \ $(SRC_POWERMAN_PAGES) \ $(SRC_IPMIPSU_PAGES) \ @@ -647,6 +707,7 @@ HTML_MANS = \ $(HTML_SERIAL_MANS) \ $(HTML_SNMP_MANS) \ $(HTML_USB_LIBUSB_MANS) \ + $(HTML_SERIAL_USB_MANS) \ $(HTML_NETXML_MANS) \ $(HTML_POWERMAN_MANS) \ $(HTML_IPMIPSU_MANS) \ diff --git a/docs/man/index.txt b/docs/man/index.txt index 4121178186..b15c6a4518 100644 --- a/docs/man/index.txt +++ b/docs/man/index.txt @@ -51,6 +51,8 @@ Drivers ~~~~~~~ - linkman:upsdrvctl[8] +- linkman:upsdrvsvcctl[8] +- linkman:nut-driver-enumerator[8] - linkman:al175[8] - linkman:apcsmart[8] @@ -89,6 +91,7 @@ Drivers - linkman:oneac[8] - linkman:optiups[8] - linkman:phoenixcontact_modbus[8] +- linkman:pijuice[8] - linkman:powercom[8] - linkman:powerman-pdu[8] - linkman:powerpanel[8] diff --git a/docs/man/nut-driver-enumerator.txt b/docs/man/nut-driver-enumerator.txt new file mode 100644 index 0000000000..72e50df3c3 --- /dev/null +++ b/docs/man/nut-driver-enumerator.txt @@ -0,0 +1,142 @@ +NUT-DRIVER-ENUMERATOR(8) +======================== + +NAME +---- + +nut-driver-enumerator - tool to map NUT device entries to service instances + +SYNOPSIS +-------- +*nut-driver-enumerator.sh* -h + +*nut-driver-enumerator.sh* (no args) + +*nut-driver-enumerator.sh* [--COMMAND] + + +DESCRIPTION +----------- + +*nut-driver-enumerator.sh* implements the set-up and querying of the +mapping between NUT driver configuration sections for each individual +monitored device, and the operating system service management framework +service instances into which such drivers are wrapped for independent +execution and management (on platforms where NUT currently supports +this integration -- currently this covers Linux distributions with +systemd and systems derived from Solaris 10 codebase, including +proprietary Sun/Oracle Solaris and numerous open-source illumos +distributions with SMF). It may be not installed in packaging for +other operating systems. + +This script provides a uniform interface for further NUT tools +such as linkman:upsdrvsvcctl[8] to implement their logic as +platform-independently as was possible and practical. It is not +currently intended for end-user consumption (and so is located in +the 'libexec' directory), with *upsdrvsvcctl* exposing the most +useful data and actions with its 'list' and 'resync' arguments. + +One part of the platform complexity that *nut-driver-enumerator.sh* +hides is the difference of rules for valid service instance names +in various frameworks, as well as system tools and naming patterns +involved. + +COMMANDS +-------- + +*nut-driver-enumerator.sh (no args)*:: +Update wrapping of devices into services + +*nut-driver-enumerator.sh --daemon(=freq)*:: +Update wrapping of devices into services in an infinite loop; +Default freq is 60 sec. + +*nut-driver-enumerator.sh --reconfigure*:: +Stop and un-register all service instances and recreate them +(e.g. if new dependency template was defined in a new +version of the script or package) + +*nut-driver-enumerator.sh --get-service-framework*:: +Print the detected service management framework in this OS + +*nut-driver-enumerator.sh --list-devices*:: +Print list of devices in NUT config + +*nut-driver-enumerator.sh --list-services*:: +Print list of service instances which wrap registered +NUT devices (full name of service unit) + +*nut-driver-enumerator.sh --list-instances*:: +Print list of service instances which wrap registered +NUT devices (just instance suffix) + +*nut-driver-enumerator.sh --get-service-for-device DEV*:: +Print the full name of service unit which wraps a NUT +device named `DEV` + +*nut-driver-enumerator.sh --get-device-for-service SVC*:: +Print the NUT device name for full or instance-suffix name of +a service unit `SVC` which wraps it + +*nut-driver-enumerator.sh --list-services-for-devices*:: +Print a TAB-separated list of service units and corresponding +NUT device names which each such unit wraps + +*nut-driver-enumerator.sh --show-all-configs*:: +Show the complete normalized list of device configuration blocks +(same as used later by the parser in the script to make decisions) + +*nut-driver-enumerator.sh --show-device-config DEV*:: +Show configuration block of the specified NUT device + +*nut-driver-enumerator.sh --show-device-config-value DEV KEY*:: +Show single configuration key of the specified NUT device + +ENVIRONMENT VARIABLES +--------------------- + +By default *nut-driver-enumerator.sh* executed without arguments would +automatically start any newly registered service instances wrapping the +NUT devices, and would also restart the `nut-server` service if the +configuration was changed. Environment variable `AUTO_START=no` disables +this default part of the action. + +Also see below for environment variable `REPORT_RESTART_42=no` value. + +DIAGNOSTICS +----------- + +*nut-driver-enumerator.sh* will return a zero exit code if it had nothing +to do (all currently defined drivers match all of the currently defined +service instances, one-to-one) and if it had no errors in its operation. + +Other codes can be returned as a result of re-synchronization of mappings: + +*42*:: +NUT device sections and system service instances differed before, but +now match up -- so now the caller should likely restart some services. +Note that the drivers' service instances may have been started or stopped +as required (by `AUTO_START=yes`) -- but maybe the upsmon or upssched +services should restart. +If you pass environment variable `REPORT_RESTART_42=no` then +this codepath would return 0 (as a non-error exit code). +In default mode, such non-null reconfiguration should cause +the nut-driver-enumerator service to restart and this would +propagate to other NUT services that depend on it. + +*13*:: +Sections and services differed, and still do not match up + +*1*:: +Bad inputs, e.g. unrecognized service management framework + +*2*:: +Absent or unreadable `ups.conf` file + +SEE ALSO +-------- +linkman:upsdrvsvcctl[8], linkman:ups.conf[5] + +Internet resources: +~~~~~~~~~~~~~~~~~~~ +The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ diff --git a/docs/man/nutdrv_siemens_sitop.txt b/docs/man/nutdrv_siemens_sitop.txt new file mode 100644 index 0000000000..291096130b --- /dev/null +++ b/docs/man/nutdrv_siemens_sitop.txt @@ -0,0 +1,188 @@ +NUTDRV_SIEMENS_SITOP(8) +======================= + +NAME +---- +nutdrv_siemens_sitop - driver for the Siemens SITOP UPS500 series UPS + +NOTE +---- +This man page only documents the hardware-specific features of the +*nutdrv_siemens_sitop* driver. For information about the core driver, see +linkman:nutupsdrv[8]. + +SUPPORTED HARDWARE +------------------ +*nutdrv_siemens_sitop* supports Siemens UPS models from the SITOP UPS500 series. +Some models have a serial port, others have a USB port. +The models with USB port actually contain a serial-over-USB chip, +so as far as this driver is concerned, all models are serial models. +This driver should work with all models in the SITOP UPS500 series, +as long as your kernel has support for the serial port device +(see section *USB driver* below). + +NOTE: This driver has only been tested with the SITOP UPS500S-2.5 +with USB port (Siemens product number 6EP1933-2EC41). + +DEVICE SETTINGS +--------------- +The UPS is configured via DIP-switches. +For correct functioning in combination with NUT, set the DIP-switches +to the following: + +*switch 1-4*:: +Choose whatever suits your situation. Any combination will work with NUT. + +*switch 5* (=> / t):: +Set to OFF (t). This ensures that the UPS will not cut power unless NUT +tells it to do so (or unless the batteries are exhausted). + +*switch 6-10* (delay):: +Set to OFF (minimum delay). Setting a higher delay will actually also work, +but any command from NUT will be delayed as well before being executed +by the UPS. With the minimum setting, it will already take 5 seconds +before a command from NUT is executed. + +*switch 11* (INTERR.):: +Set to ON (interrupt the output after the timer expires). This ensures that +the UPS briefly interrupts the output power in response to the shutdown.return +command. See the section *Instant Commands* below. + +*switch 12* (ON/OFF):: +set to ON (enable the UPS functionality). Without this, the UPS will never +supply power from its batteries. + +USB driver +---------- +The USB-versions of the UPS contain an FTDI USB-to-serial converter chip. +It is programmed with a non-standard product ID (for example _0403:e0e3_), +but can still be used with the normal ftdi_sio driver. + +NOTE: The following hints may be specific to GNU/Linux. + +Use *lsusb* to figure out which product ID is used in your model, and +replace all occurrences of _e0e3_ in the following examples with the actual +Product ID. + +.... +modprobe ftdi_sio +echo 0403 e0e3 > /sys/bus/usb-serial/drivers/ftdi_sio/new_id +.... + +If your system uses *udev*, this can be automated via a udev rule: + +---- +ACTION=="add", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="e0e3", \ + RUN+="/sbin/modprobe ftdi_sio", \ + RUN+="/bin/sh -c 'echo 0403 e0e3 > /sys/bus/usb-serial/drivers/ftdi_sio/new_id'" +---- + +You can use the following udev rule to obtain a predictable device name, +for example _/dev/ttyUPS_: +---- +SUBSYSTEM=="tty" ATTRS{idVendor}=="0403", ATTRS{idProduct}=="e0e3" SYMLINK+="ttyUPS" +---- + +POLLING +------- +The UPS does not have a special 'get status' command. Instead, it continuously +sends out status update messages (tens of messages per second). +Every *pollinterval*, these messages are read from the serial port buffer. +In order to react quickly on status changes from the UPS, and to prevent the serial buffer +from overflowing, *pollinterval* should be set to a relatively low value. The recommended +value is 1 (second). + +EXTRA ARGUMENTS +--------------- +This driver supports the following optional settings: + +*max_polls_without_data*='num':: +The serial port is polled periodically for new data (see *Polling*). +If there is no valid new data after 'num' polls, it is assumed that communication +with the UPS is lost. +The default value is 2. Lower values may cause spurious 'Data stale' messages, +especially at startup. + +INSTANT COMMANDS +---------------- + +*shutdown.return*:: +The behavior of this command depends on the line state: + +* *on line*: after 5 seconds (or longer, if DIP switches 6-10 are not OFF), +the UPS will shut off its output. After another 5 seconds, the output is +activated again. +* *on battery*: after 5 seconds (or longer, if DIP switches 6-10 are not OFF), +the UPS will shut off its output. The output will stay off, until the +line voltage has returned. + +*shutdown.stayoff*:: +The behavior of this command depends on the line state: + +* *on line*: after 5 seconds (or longer, if DIP switches 6-10 are not OFF), +the UPS will shut off its output. The output stays off, until the line voltage +has been removed for at least 1 second, and has been re-applied. +* *on battery*: this command behaves the same as *shutdown.return*. + +INSTALLATION +------------ +Make sure that your operating system has created a serial device for the UPS. +See the section *USB driver* for more information. + +Next, make sure that NUT has access rights to this device file. +For example, by creating a udev rule that grants permission to the NUT user, +or by adding the NUT user to a user group that can access serial devices +(e.g. the *dialout* group on Debian-based systems). + +DIAGNOSTICS +----------- +You can verify the correct functioning of the hardware, by monitoring the +serial port with a terminal program, for example picocom: + +.... +picocom -b 9600 -d 8 -p n /dev/ttyUPS +.... + +NUT must not be running when you do this. +You should now see a continuous stream of 5-character texts coming in, +for example: + +.... +BUFRD +BA>85 +DC_OK +.... +To exit picocom, use Ctrl-A Ctrl-X. + +KNOWN ISSUES AND BUGS +--------------------- +*Untested models*:: +As mentioned under *Supported hardware*, this driver has not been tested +with all models in the SITOP UPS500 series. + +*Data stale messages*:: +The firmware in these UPSes is quite buggy. After sending data to the UPS, +it sometimes stops sending status updates. This driver tries to prevent this +(e.g. by sending commands twice, and by sending additional LF characters after +each command). +Once the UPS is in this state, communication can only be restored by rebooting +the UPS, or by unplugging and reconnecting the USB cable. +During normal operation, no commands are sent to the UPS at all +(only at shutdown), so this issue is expected to have little impact on +usability. +It is not sure if the serial models are affected by this issue as well. + +AUTHORS +------- +Matthijs H. ten Berge + +SEE ALSO +-------- + +The core driver: +~~~~~~~~~~~~~~~~ +linkman:nutupsdrv[8] + +Internet resources: +~~~~~~~~~~~~~~~~~~~ +The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ diff --git a/docs/man/nutupsdrv.txt b/docs/man/nutupsdrv.txt index 910c2ac0e2..015dba5f5b 100644 --- a/docs/man/nutupsdrv.txt +++ b/docs/man/nutupsdrv.txt @@ -117,12 +117,20 @@ opened before the chroot call, so you do not need to create them inside the jail. In fact, it is somewhat safer if you do not. *-u* 'username':: -If started as root, the driver will setuid(2) to the user id -associated with 'username'. +Override the unprivileged username that the driver may use after startup. If +started as root, after opening configuration files (and optionally calling +chroot(2), as described in the previous option), the driver will look up +'username' in the `passwd` database, then change to the user and group +identities associated with 'username'. (If started with a nonzero UID or +effective UID, the driver will silently ignore this option.) + -If you do not specify this value and start it as root, the driver will -switch to the default value that was compiled into the code. This is -typically 'nobody', and is far from ideal. +When compiling NUT from source, the default username is typically `nobody`, and +this may cause permission errors when the driver opens the UPS device node. You +can use this option to temporarily override the defaults. For testing purposes, +you can set this option to `root` to bypass permission errors, especially with +USB-based drivers. However, you will want to remove this option later in order +to avoid permission conflicts between the driver and the unprivileged copy of +linkman:upsd[8]. *-x* 'var'='val':: Define a variable called 'var' with the value of 'var' in the diff --git a/docs/man/pijuice.txt b/docs/man/pijuice.txt new file mode 100644 index 0000000000..1643208f34 --- /dev/null +++ b/docs/man/pijuice.txt @@ -0,0 +1,81 @@ +PIJUICE(8) +========== + +NAME +---- +pijuice - driver for UPS in PiJuice HAT + +NOTE +---- +This man page only documents the hardware-specific features of the +*pijuice* driver. For information about the core driver, see +linkman:nutupsdrv[8]. + +NOTE: This manual page was hastily adapted from related `asem` driver +manpage based on information from the original pull request, and so +may not fully apply to PiJuice HAT, patches from experts are welcome. + +SUPPORTED HARDWARE +------------------ +The *pijuice* driver supports the portable PiJuice HAT UPS for Raspberry Pi +embedded PCs. + +EXTRA ARGUMENTS +--------------- + +The required parameter for this driver is the I2C bus name: + +*port*='dev-node':: +On the PiJuice HAT, this should be `/dev/i2c-1`. + +INSTALLATION +------------ +NOTE: This section was copied from `asem` driver manpage and may not fully +apply to PiJuice HAT, patches are welcome. + +This driver is specific to the Linux I2C API, and requires the lm_sensors +libi2c-dev or its equivalent to compile. + +Beware that the SystemIO memory used by the I2C controller is reserved by ACPI. +If only a native I2C driver (e.g. i2c_i801, as of 3.5.X Linux kernels) is +available, then you'll need to relax the ACPI resources check. For example, you +can boot with the `acpi_enforce_resources=lax` option. + +////////////////////////////////////////// +Optional: use DIAGNOSTICS to describe troubleshooting techniques that are +longer than what can be conveniently described in the driver error messages. + +DIAGNOSTICS +----------- + +////////////////////////////////////////// + +KNOWN ISSUES AND BUGS +--------------------- +NOTE: This section was copied from `asem` driver manpage and may not fully +apply to PiJuice HAT, patches are welcome. + +The driver shutdown function is not implemented, so other arrangements must be +made to turn off the UPS. + +AUTHORS +------- +Andrew Anderson + +SEE ALSO +-------- + +The core driver: +~~~~~~~~~~~~~~~~ +linkman:nutupsdrv[8] + +Internet resources: +~~~~~~~~~~~~~~~~~~~ +Initial pull requests adding this driver: + +* https://github.com/networkupstools/nut/pull/730 +* https://github.com/PiSupply/PiJuice/issues/124 + +Product home page: https://uk.pi-supply.com/products/pijuice-standard + +The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ diff --git a/docs/man/snmp-ups.txt b/docs/man/snmp-ups.txt index 8f1683328b..c6010be7da 100644 --- a/docs/man/snmp-ups.txt +++ b/docs/man/snmp-ups.txt @@ -90,7 +90,7 @@ With "auto", the driver will try a select set of SNMP objects until it finds one that the device responds to. Note that since NUT 2.6.2, snmp-ups has a new method that uses sysObjectID (which is a pointer to the preferred MIB of the device) to detect supported devices. This renders void the use of "mibs" option. - + *community*='name':: Set community name (default = public). Note that a RW community name is required to change UPS settings (as for a powerdown). @@ -104,6 +104,11 @@ Specifies the number of Net-SNMP retries to be used in the requests (default=5) *snmp_timeout*='timeout':: Specifies the Net-SNMP timeout in seconds between retries (default=1) +*symmetrathreephase*:: +Enable APCC three phase Symmetra quirks (use on APCC three phase Symmetras): +Convert from three phase line-to-line voltage to line-to-neutral voltage +(default: not enabled) + *pollfreq*='num':: Set polling interval for full updates, in seconds, to reduce SNMP network traffic relative to the quick updates performed every "pollinterval" (the diff --git a/docs/man/ups.conf.txt b/docs/man/ups.conf.txt index ec8d393647..d742a9c346 100644 --- a/docs/man/ups.conf.txt +++ b/docs/man/ups.conf.txt @@ -113,8 +113,8 @@ of the driver behavior. *user*:: -Optional. If started as root, the driver will setuid(2) to the user id -associated with 'username'. +Optional. Overrides the compiled-in default unprivileged username. See the +discussion of the `-u` option in linkman:nutupsdrv[8] for details. UPS FIELDS ---------- diff --git a/docs/man/upscli_cleanup.txt b/docs/man/upscli_cleanup.txt index cd88a518e1..611c3de051 100644 --- a/docs/man/upscli_cleanup.txt +++ b/docs/man/upscli_cleanup.txt @@ -11,7 +11,7 @@ SYNOPSIS #include - int upscli_cleanup(); + int upscli_cleanup(void); DESCRIPTION ----------- diff --git a/docs/man/upscli_readline.txt b/docs/man/upscli_readline.txt index 52106ade43..06db9c62c3 100644 --- a/docs/man/upscli_readline.txt +++ b/docs/man/upscli_readline.txt @@ -4,7 +4,7 @@ UPSCLI_READLINE(3) NAME ---- -upscli_readline - read a single response from a UPS +upscli_readline, upscli_readline_timeout - read a single response from a UPS SYNOPSIS -------- @@ -12,23 +12,28 @@ SYNOPSIS #include int upscli_readline(UPSCONN_t *ups, char *buf, size_t buflen); + int upscli_readline_timeout(UPSCONN_t *ups, char *buf, size_t buflen, unsigned int timeout); DESCRIPTION ----------- -The *upscli_readline()* function takes the pointer 'ups' to a -`UPSCONN_t` state structure, receives a single line from the server, and -copies up to 'buflen' bytes of the response into the buffer -'buf'. +The *upscli_readline()* and *upscli_readline_timeout()* functions take the +pointer 'ups' to a `UPSCONN_t` state structure, receive a single line from the +server, and copy up to 'buflen' bytes of the response into the buffer 'buf'. Some parsing of the string occurs during reception. In particular, ERR messages from linkman:upsd[8] are detected and will cause this function to return -1. +The difference between the two functions is that *upscli_readline_timeout()* +lets the caller decide the amount of time ('timeout' seconds) after which it +should give up and return, whereas *upscli_readline()* does not offer this +freedom, and uses NUT default network timeout (5 seconds). + RETURN VALUE ------------ -The *upscli_readline()* function returns 0 on success, or -1 if an -error occurs. +The *upscli_readline()* and *upscli_readline_timeout()* functions return 0 on +success, or -1 if an error occurs. SEE ALSO -------- diff --git a/docs/man/upscli_sendline.txt b/docs/man/upscli_sendline.txt index c449c6dd5d..cefa264538 100644 --- a/docs/man/upscli_sendline.txt +++ b/docs/man/upscli_sendline.txt @@ -4,7 +4,7 @@ UPSCLI_SENDLINE(3) NAME ---- -upscli_sendline - send a single command to a UPS +upscli_sendline, upscli_sendline_timeout - send a single command to a UPS SYNOPSIS -------- @@ -13,22 +13,28 @@ SYNOPSIS #include int upscli_sendline(UPSCONN_t *ups, const char *buf, size_t buflen); + int upscli_sendline_timeout(UPSCONN_t *ups, const char *buf, size_t buflen, unsigned int timeout); DESCRIPTION ----------- -The *upscli_sendline()* function takes the pointer 'ups' to a -`UPSCONN_t` state structure and transmits a buffer 'buf' of size -'buflen' to the server. +The *upscli_sendline()* and *upscli_sendline_timeout()* functions take the +pointer 'ups' to a `UPSCONN_t` state structure and transmit a buffer 'buf' of +size 'buflen' to the server. The data in 'buf' must be a fully formatted protocol command as no parsing of the buffer occurs within this function. +The difference between the two functions is that *upscli_sendline_timeout()* +lets the caller decide the amount of time ('timeout' seconds) after which it +should give up and return, whereas *upscli_sendline()* does not offer this +freedom, and uses an immediate timeout (0 second). + RETURN VALUE ------------ -The *upscli_sendline()* function returns 0 on success, or -1 if an -error occurs. +The *upscli_sendline()* and *upscli_sendline_timeout()* functions return 0 on +success, or -1 if an error occurs. SEE ALSO -------- diff --git a/docs/man/upscmd.txt b/docs/man/upscmd.txt index 8083fece02..a66d0f1399 100644 --- a/docs/man/upscmd.txt +++ b/docs/man/upscmd.txt @@ -11,7 +11,7 @@ SYNOPSIS *upscmd* -l 'ups' -*upscmd* [-u 'username'] [-p 'password'] 'ups' 'command' +*upscmd* [-u 'username'] [-p 'password'] [-w] [-t ] 'ups' 'command' DESCRIPTION ----------- @@ -42,6 +42,17 @@ you will be prompted for this when invoking a command if -u is not used. Set the password to authenticate to the server. This is also optional like -u, and you will be prompted for it if necessary. +*-w*:: +Wait for the completion of command execution by the driver and return its +actual result from the device. Note that this feature requires that both upsd +and the driver support TRACKING (NUT version 2.7.5 or higher) or it will +otherwise fail. +The command will also block until an actual result is provided from the driver, +or the timeout is reached (see *-t*). + +*-t* 'seconds':: +Set a timeout when using *-w*. Defaults to 10 seconds. + 'ups':: Connect to this UPS. The format is `upsname[@hostname[:port]]`. The default hostname is "localhost". @@ -84,8 +95,7 @@ BUGS ---- There is currently no way to tell the user when the driver requires -confirmation to invoke a command such as `load.off`. Similarly, there is -not yet a way to tell the user if a command succeeds or fails. +confirmation to invoke a command such as `load.off`. This is on the list of things to fix in the future, so don't despair. It involves magic cookies. diff --git a/docs/man/upsd.conf.txt b/docs/man/upsd.conf.txt index ebdfef6024..efa5032386 100644 --- a/docs/man/upsd.conf.txt +++ b/docs/man/upsd.conf.txt @@ -26,6 +26,28 @@ to make upsd wait longer. + Most users should leave this at the default value. +"TRACKINGDELAY 'seconds'":: + +When instant commands and variables setting status tracking is enabled, status +execution information are kept during this amount of time, and then cleaned up. +This defaults to 3600 (1 hour). + +"ALLOW_NO_DEVICE 'Boolean'":: + +Normally upsd requires that at least one device section is defined in ups.conf +when the daemon starts, to serve its data. For automatically managed services +it may be preferred to have upsd always running, and reload the configuration +when power devices become defined. ++ +Boolean values 'true', 'yes', 'on' and '1' mean that the server would not +refuse to start with zero device sections found in ups.conf. ++ +Boolean values 'false', 'no', 'off' and '0' mean that the server should refuse +to start if zero device sections were found in ups.conf. This is the default, +unless the calling environment sets a same-named variable to enforce a value +for the current run. One way this can happen is somebody un-commenting it in +the 'nut.conf' file used by init-scripts and service unit method scripts. + "STATEPATH 'path'":: Tell upsd to look for the driver state sockets in 'path' rather diff --git a/docs/man/upsdrvctl.txt b/docs/man/upsdrvctl.txt index 68a4b8c473..7a788c41c6 100644 --- a/docs/man/upsdrvctl.txt +++ b/docs/man/upsdrvctl.txt @@ -22,6 +22,9 @@ whenever possible. When used properly, upsdrvctl lets you maintain identical startup scripts across multiple systems with different UPS configurations. +Note: For operating systems with service management frameworks, such as +Solaris SMF or Linux systemd, the *upsdrvsvcctl* may be a better choice. + OPTIONS ------- @@ -97,7 +100,7 @@ background. SEE ALSO -------- -linkman:nutupsdrv[8], linkman:upsd[8], linkman:ups.conf[5] +linkman:upsdrvsvcctl[8], linkman:nutupsdrv[8], linkman:upsd[8], linkman:ups.conf[5] Internet resources: ~~~~~~~~~~~~~~~~~~~ diff --git a/docs/man/upsdrvsvcctl.txt b/docs/man/upsdrvsvcctl.txt new file mode 100644 index 0000000000..89cdded97b --- /dev/null +++ b/docs/man/upsdrvsvcctl.txt @@ -0,0 +1,197 @@ +UPSDRVSVCCTL(8) +=============== + +NAME +---- + +upsdrvsvcctl - UPS driver service instance controller + +SYNOPSIS +-------- +*upsdrvsvcctl* -h + +*upsdrvsvcctl* ['OPTIONS'] {start | stop } ['ups'] + +DESCRIPTION +----------- + +*upsdrvsvcctl* provides a uniform interface for controlling your UPS +drivers wrapped into service instances on platforms which support that +(currently this covers Linux distributions with systemd and systems +derived from Solaris 10 codebase, including proprietary Sun/Oracle +Solaris and numerous open-source illumos distributions with SMF). +It may be not installed in packaging for other operating systems. + +When used properly, upsdrvsvcctl lets you maintain identical startup +scripts across multiple systems with different UPS configurations. + +The goal of this solution is to allow the services of *upsd* data +server to start up even if some of the power devices are currently +not accessible, and for NUT drivers to be automatically restarted +by the system in case of problems (driver bug, startup failure). +It also allows for faster startup of systems which monitor several +devices, by letting each driver to start in parallel with others, +and not with a sequential loop like was done previously. + +Independent service instances for each NUT driver also allow one +to configure further dependencies, such as that networking must be +available for SNMP and similar drivers (but is not needed for +local-medium drivers such as serial or USB). + +The old monolithic "all or nothing" solution requiring that all +drivers must be running, which sufficed for deployments with a few +UPSes, did not really work well for monitoring larger deployments. +It was also not easy to strike a pre-packaged balance between early +UPS protection for USB/serial home setups vs. waiting for network +on larger ones. + +*upsdrvsvcctl* is a script which mimics the operation of *upsdrvctl* +program (where possible) to provide similar end-user experience when +manipulating drivers wrapped into service instances rather than as +directly executed daemons. It relies on *nut-driver-enumerator.sh* +for a large part of actual operations. + +You should use upsdrvsvcctl instead of direct calls to the drivers +and daemon-based management with *upsdrvctl* whenever possible (that +is, for "production" use on compatible OSes). Otherwise (testing, +other OSes) the *upsdrvctl* is a recommended option. + +OPTIONS +------- + +*-h*:: +Display the help text. + +*-t*:: +Enable testing mode. Testing mode makes upsdrvsvcctl display the actions +it would execute without actually doing them. + + + +OPTIONS OF UPSDRVCTL NOT (CURRENTLY) APPLICABLE TO UPSDRVSVCCTL +--------------------------------------------------------------- + +Options like '-r', '-u' or '-D' could be handled by properties of the +service instances themselves, with this script helping to configure +them (assuming proper privileges of the user who called it). This is +not a "production" use case, though, to change such options on a +configured system -- so for experiments and troubleshooting, it may +be better to stop the service instance and play with *upsdrvctl* +directly. + +*-r* 'directory':: +If starting a driver, this value will direct it to *chroot*(2) into +'directory'. This can be useful when securing systems. + +This may be set in the ups.conf with "chroot" in the global section. + +*-u* 'username':: +If starting a driver, this value will direct it to *setuid*(2) to +the user id associated with 'username'. + +If the driver is started as root without specifying this value, it will +use the username that was compiled into the binary. This defaults to +"nobody", and is far from ideal. + +This may be set in ups.conf with "user" in the global section. + +*-D*:: +Raise the driver debug level. Use this multiple times for additional +details. + +COMMANDS +-------- + +*upsdrvsvcctl* supports three of the commands processed by *upsdrvctl* -- +start, stop and shutdown. They take an optional argument which is a UPS +name from linkman:ups.conf[5]. Without that argument, they operate on +every UPS that is currently configured. + +Note: shutdown is currently supported by stopping the driver service +instances to release the potentially held ports etc., calling the +*upsdrvctl* directly for issuing the shutdown command, and restarting +the driver service instances to reconnect when the device comes back +online. + +*start*:: +Start the UPS driver(s). In case of failure, further attempts may be executed +by using the 'maxretry' and 'retrydelay' options - see linkman:ups.conf[5]. + +*stop*:: +Stop the UPS driver(s). + +*upsdrvsvcctl* also supports further operations for troubleshooting the +mapping of NUT driver section names to the service instance names (which +may differ due to limitations of various systems). + +*list*:: +list the currently active mapping of service instances to device sections + +*resync*:: +update the mapping of service instances for NUT drivers to device section +names used in 'ups.conf' (register new instances, tear down obsoleted ones). + + +COMMANDS OF UPSDRVCTL NOT (CURRENTLY) APPLICABLE TO UPSDRVSVCCTL +---------------------------------------------------------------- + +*shutdown*:: +Command the UPS driver(s) to run their shutdown sequence. Drivers are +stopped according to their sdorder value - see linkman:ups.conf[5]. + +WARNING: this will probably power off your computers, so don't +play around with this option. Only use it when your systems are prepared +to lose power. + +NOTE: refer to linkman:ups.conf[5] for using the *nowait* parameter. + +ENVIRONMENT VARIABLES +--------------------- + +*NUT_CONFPATH* is the path name of the directory that contains +`upsd.conf` and other configuration files. If this variable is not set, +*upsdrvsvcctl* (or rather *nut-driver-enumerator.sh*) would use a built-in +default, which is often `/usr/local/ups/etc`. + +DIAGNOSTICS +----------- + +upsdrvsvcctl will return a nonzero exit code if it encounters an error +while performing the desired operation. This will also happen if a +driver takes longer than the 'maxstartdelay' period to enter the +background. + +Any messages issued by the *upsdrvctl* program used to start the NUT +drivers as part of the service instances' implementations, or by the +drivers themselves, will be logged by the service management framework +facilities and will not appear in your interactive terminal used to +manage the driver. + +Use `upsdrvsvcctl list` or `upsdrvsvcctl list NUT-device` to find out +the service instance name for the NUT driver (section name) you are +interested in. Then look up the service logs (where the outputs of the +service implementation program as well as the framework messages about +this service are stored), as suggested below: + +*Linux systemd*:: +Messages will normally be kept in the service journal, so: + + journalctl -lu nut-driver@instance-name + +Note that your local system configuration may be impacted by such +nuances as passing the journal data to a standard syslog server, +and/or by having a small cache for locally stored journal messages +(so older entries would disappear). There may also be or not be a +copy of the journals stored in the filesystem. + +*Solaris SMF*:: +Look for `/var/svc/log/system-power-nut-driver:instance-name.log` file. + +SEE ALSO +-------- +linkman:upsdrvctl[8], linkman:nutupsdrv[8], linkman:upsd[8], +linkman:nut-driver-enumerator[8], linkman:ups.conf[5] + +Internet resources: +~~~~~~~~~~~~~~~~~~~ +The NUT (Network UPS Tools) home page: http://www.networkupstools.org/ diff --git a/docs/man/upsrw.txt b/docs/man/upsrw.txt index 8053364104..eb4ed351f8 100644 --- a/docs/man/upsrw.txt +++ b/docs/man/upsrw.txt @@ -13,7 +13,7 @@ SYNOPSIS *upsrw* -h -*upsrw* -s 'variable' [-u 'username'] [-p 'password'] 'ups' +*upsrw* -s 'variable' [-u 'username'] [-p 'password'] [-w] [-t ] 'ups' DESCRIPTION ----------- @@ -58,6 +58,17 @@ linkman:upsd.users[5], and are not linked to system usernames. Set the password to authenticate to the server. This is also optional like -u, and you will be prompted for it if necessary. +*-w*:: +Wait for the completion of setting execution by the driver and return its +actual result from the device. Note that this feature requires that both upsd +and the driver support TRACKING (NUT version 2.7.5 or higher) or it will +otherwise fail. +The command will also block until an actual result is provided from the driver, +or the timeout is reached (see *-t*). + +*-t* 'seconds':: +Set a timeout when using *-w*. Defaults to 10 seconds. + 'ups':: View or change the settings on this UPS. The format for this option is `upsname[@hostname[:port]]`. The default hostname is "localhost". diff --git a/docs/net-protocol.txt b/docs/net-protocol.txt index 17ecf094a1..09c0acb113 100644 --- a/docs/net-protocol.txt +++ b/docs/net-protocol.txt @@ -25,7 +25,7 @@ an older version of the software. Command reference ----------------- -Multi-word elements are contained within "quotes" for easier parsing. +Multi-word elements are contained within "quotes" for easier parsing. Embedded quotes are escaped with backslashes. Embedded backslashes are also escaped by representing them as \\. This protocol is intended to be interpreted with parseconf (NUT parser) or something similar. @@ -44,10 +44,12 @@ NUT network protocol, over the time: |1.1 |>= 1.5.0 |Original protocol (without old commands) .2+|1.2 .2+|>= 2.6.4 |Add "LIST CLIENTS" and "NETVER" commands |Add ranges of values for writable variables +.2+|1.3 .2+|>= 2.7.5 |Add "cmdparam" to "INSTCMD" + |Add "TRACKING" commands (GET, SET) |=============================================================================== NOTE: any new version of the protocol implies an update of NUT_NETVERSION -in *configure.in*. +in *configure.ac*. GET @@ -132,12 +134,14 @@ Response: - 'RW': this variable may be set to another value with SET - 'ENUM': an enumerated type, which supports a few specific values - 'STRING:n': this is a string of maximum length n -- 'RANGE': this is an numeric, either integer or float, comprised in the range (see LIST RANGE) +- 'RANGE': this is an numeric, either integer or float, comprised in the +range (see LIST RANGE) - 'NUMBER': this is a simple numeric value, either integer or float ENUM, STRING and RANGE are usually associated with RW, but not always. -The default , when omitted, is numeric, so either integer or float. Each -driver is then responsible for handling values as either integer or float. +The default , when omitted, is numeric, so either integer or float. +Each driver is then responsible for handling values as either integer or +float. Note that float values are expressed using decimal (base 10) english-based representation, so using a dot, in non-scientific notation. So hexadecimal, @@ -189,6 +193,26 @@ This is like DESC above, but it applies to the instant commands. This replaces the old "INSTCMDDESC" command. +TRACKING +~~~~~~~~ + +Form: + + GET TRACKING (activation status of TRACKING) + GET TRACKING (execution status of a command / setvar) + GET TRACKING 1bd31808-cb49-4aec-9d75-d056e6f018d2 + +Response: + + ON (TRACKING feature is enabled) + OFF (TRACKING feature is disabled) + PENDING (command execution is pending) + SUCCESS (command was successfully executed) + ERR UNKNOWN (command execution failed with unknown error) + ERR INVALID-ARGUMENT (command execution failed due to missing or invalid argument) + ERR FAILED (command execution failed) + + LIST ---- @@ -377,19 +401,54 @@ Response: SET --- +VAR +~~~ + Form: SET VAR "" SET VAR su700 ups.id "My UPS" +Response: + + OK (if TRACKING is not enabled) + OK TRACKING (if TRACKING is enabled) + ERR [...] (see Error responses) + + +TRACKING +~~~~~~~~ + +Form: + + SET TRACKING + SET TRACKING ON + SET TRACKING OFF + +Response: + + OK + ERR INVALID-ARGUMENT (if is not "ON" or "OFF") + ERR USERNAME-REQUIRED (if not yet authenticated) + ERR PASSWORD-REQUIRED (if not yet authenticated) + INSTCMD ------- Form: - INSTCMD + INSTCMD [] INSTCMD su700 test.panel.start + INSTCMD su700 load.off.delay 120 + +NOTE: is an additional and optional parameter for the command. + +Response: + + OK (if TRACKING is not enabled) + OK TRACKING (if TRACKING is enabled) + ERR [...] (see Error responses) LOGOUT @@ -424,7 +483,7 @@ NOTE: This requires "upsmon slave" or "upsmon master" in upsd.users Use this to log the fact that a system is drawing power from this UPS. The upsmon master will wait until the count of attached systems reaches -1 - itself. This allows the slaves to shut down first. +1 -- itself. This allows the slaves to shut down first. NOTE: You probably shouldn't send this command unless you are upsmon, or a upsmon replacement. @@ -473,7 +532,7 @@ power disappears. Setting this flag makes "FSD" appear in a STATUS request for this UPS. Finding "FSD" in a status request should be treated just like a "OB LB". -It should be noted that FSD is currently a latch - once set, there is +It should be noted that FSD is currently a latch -- once set, there is no way to clear it short of restarting upsd or dropping then re-adding it in the ups.conf. This may cause issues when upsd is running on a system that is not shut down due to the UPS event. @@ -587,13 +646,13 @@ sending a valid command like GET with an invalid subcommand. - 'INSTCMD-FAILED' + -upsd failed to deliver the instant command request to the driver. +upsd failed to deliver the instant command request to the driver. No further information is available to the client. This typically indicates a dead or broken driver. - 'SET-FAILED' + -upsd failed to deliver the set request to the driver. This is +upsd failed to deliver the set request to the driver. This is just like INSTCMD-FAILED above. - 'READONLY' @@ -622,7 +681,7 @@ start it again. - 'DRIVER-NOT-CONNECTED' + upsd can't perform the requested command, since the driver for that -UPS is not connected. This usually means that the driver is not +UPS is not connected. This usually means that the driver is not running, or if it is, the ups.conf is misconfigured. - 'DATA-STALE' @@ -643,7 +702,7 @@ There is presently a limit of one LOGIN record per connection. - 'INVALID-PASSWORD' + -The client sent an invalid PASSWORD - perhaps an empty one. +The client sent an invalid PASSWORD -- perhaps an empty one. - 'ALREADY-SET-PASSWORD' + @@ -679,7 +738,7 @@ receiving this response. - 'INVALID-VALUE' + -The value specified in the request is not valid. This usually +The value specified in the request is not valid. This usually applies to a SET of an ENUM type which is using a value which is not in the list of allowed values. @@ -696,13 +755,6 @@ For example, "LIST VARS +DESC" would return the current value like now, but it would also append the description of that variable. -Command status -~~~~~~~~~~~~~~ - -After sending an INSTCMD or SET, a client will eventually be able to -poll to see whether it was completed successfully by the driver. - - Get collection ~~~~~~~~~~~~~~ diff --git a/docs/new-clients.txt b/docs/new-clients.txt index 7b41364c9a..6c4c073346 100644 --- a/docs/new-clients.txt +++ b/docs/new-clients.txt @@ -52,28 +52,84 @@ and commands with an object-oriented API in C++ and C. For more information, refer to the linkman:libnutclient[3] manual page. #include + #include + #include + #include + using namespace nut; using namespace std; - - int main(int argc, char** argv) + + /* argv[1] is the mandatory NUT device name (@localhost), + * used to list variables from + * argv[2] is an optional command. When provided, it will be + * executed and possibly with status tracking enabled + */ + int main(int argc, char **argv) { + Client *client; try { // Connection - Client* client = new TcpClient("localhost", 3493); - Device mydev = client->getDevice("myups"); - cout << mydev.getDescription() << endl; - Variable var = mydev.getVariable("device.model"); - cout << var.getValue()[0] << endl; + client = new TcpClient("localhost", 3493); + + if (argc >= 2) + { + // Reading data from device + Device mydev = client->getDevice(argv[1]); + cout << "Description: " << mydev.getDescription() << endl; + Variable var = mydev.getVariable("device.model"); + cout << "Model: " << var.getValue()[0] << endl; + + if (argc >= 3) + { + // Authenticate to NUT server + const char *user = getenv("NUT_USER"); + const char *password = getenv("NUT_PASSWD"); + client->authenticate(user ? user : "", password ? password : ""); + + // Enable command tracking, if available + if (client->hasFeature(Client::TRACKING)) + { + cout << "Server can do command tracking" << std::endl; + client->setFeature(Client::TRACKING, true); + } + else + { + std::cout << "Server can't do command tracking" << std::endl; + } + + // Perform an asynchronous command + TrackingID id = mydev.executeCommand(argv[2]); + TrackingResult result; + do + { + sleep(1); + result = client->getTrackingResult(id); + } + while (result == PENDING); + + // Display result of command + const char *output = ""; + switch (result) + { + case SUCCESS: output = "SUCCESS"; break; + case FAILURE: output = "FAILURE"; break; + case UNKNOWN: output = "UNKNOWN"; break; + } + cout << "Command sent, result=" << output << endl; + } + } } - catch(NutException& ex) + catch (NutException &ex) { cerr << "Unexpected problem : " << ex.str() << endl; } + delete client; return 0; } + Configuration helpers ~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/new-drivers.txt b/docs/new-drivers.txt index a8770c9d77..97fd4e249c 100644 --- a/docs/new-drivers.txt +++ b/docs/new-drivers.txt @@ -76,8 +76,9 @@ This structure tracks several description information about the driver: * *version*: the driver's own version. For sub driver information, refer below to sub_upsdrv_info. This value has the form "X.YZ", and is published by main as "driver.version.internal". - * *authors*: the driver's author(s) name. If multiple authors are listed, separate - them with a newline character so that it can be broken up by author if needed. + * *authors*: the driver's author(s) name. If multiple authors are listed, + separate them with a newline character so that it can be broken + up by author if needed. * *status*: the driver development status. The following values are allowed: - DRV_BROKEN: setting this value will cause main to print an error and exit. This is only used during conversions of the driver core @@ -89,10 +90,10 @@ This structure tracks several description information about the driver: doesn't take it for granted. - DRV_BETA: this value means that the driver is more stable and complete. But it is still not recommended for production systems. - - DRV_STABLE: the driver is suitable for production systems, but not - 100 % feature complete. - - DRV_COMPLETE: this is the gold level! It implies that 100 % of the - protocol is implemented, and a full QA pass. + - DRV_STABLE: the driver is suitable for production systems, but + not 100 % feature complete. + - DRV_COMPLETE: this is the gold level! It implies that 100 % of + the protocol is implemented, and a full QA pass. * *subdrv_info*: array of upsdrv_info_t for sub driver(s) information. For example, this is used by usbhid-ups. @@ -206,35 +207,35 @@ UPS status flags like on line (OL) and on battery (OB) live in ups.status. Don't manipulate this by hand. There are functions which will do this for you. - status_init() - before doing anything else + status_init() -- before doing anything else - status_set(val) - add a status word (OB, OL, etc) + status_set(val) -- add a status word (OB, OL, etc) - status_commit() - push out the update + status_commit() -- push out the update Possible values for status_set: - OL - On line (mains is present) - OB - On battery (mains is not present) - LB - Low battery - HB - High battery - RB - The battery needs to be replaced - CHRG - The battery is charging - DISCHRG - The battery is discharging (inverter is providing load power) - BYPASS - UPS bypass circuit is active - no battery protection is available - CAL - UPS is currently performing runtime calibration (on battery) - OFF - UPS is offline and is not supplying power to the load - OVER - UPS is overloaded - TRIM - UPS is trimming incoming voltage (called "buck" in some hardware) - BOOST - UPS is boosting incoming voltage - FSD - Forced Shutdown (restricted use, see the note below) + OL -- On line (mains is present) + OB -- On battery (mains is not present) + LB -- Low battery + HB -- High battery + RB -- The battery needs to be replaced + CHRG -- The battery is charging + DISCHRG -- The battery is discharging (inverter is providing load power) + BYPASS -- UPS bypass circuit is active -- no battery protection is available + CAL -- UPS is currently performing runtime calibration (on battery) + OFF -- UPS is offline and is not supplying power to the load + OVER -- UPS is overloaded + TRIM -- UPS is trimming incoming voltage (called "buck" in some hardware) + BOOST -- UPS is boosting incoming voltage + FSD -- Forced Shutdown (restricted use, see the note below) Anything else will not be recognized by the usual clients. Coordinate with the nut-upsdev list before creating something new, since there will be duplication and ugliness otherwise. [NOTE] -================================================================================ +============================================================================== - upsd injects `FSD` by itself following that command by a master upsmon process. Drivers must not set that value, apart from specific cases (see @@ -249,7 +250,7 @@ met. Otherwise, setting status to `OB LB` should be preferred. - the `CHRG` and `DISCHRG` flags are being replaced with `battery.charger.status`. See the linkdoc:user-manual[NUT command and variable naming scheme,nut-names] for more information. -================================================================================ +============================================================================== UPS alarms ---------- @@ -257,11 +258,11 @@ UPS alarms These work like ups.status, and have three special functions which you must use to manage them. - alarm_init() - before doing anything else + alarm_init() -- before doing anything else - alarm_set() - add an alarm word + alarm_set() -- add an alarm word - alarm_commit() - push the value into ups.alarm + alarm_commit() -- push the value into ups.alarm NOTE: the ALARM flag in ups.status is automatically set whenever you use alarm_set. To remove that flag from ups.status, call alarm_init and @@ -290,7 +291,7 @@ else to ensure that it is really available. If the attempts to contact the UPS fail, you must call dstate_datastale() to inform the server and clients. -- dstate_dataok() +- dstate_dataok() + You must call this if polls are succeeding. A good place to call this is the bottom of upsdrv_updateinfo(). @@ -367,7 +368,8 @@ This attempts to write one character and returns the return value from write. You could call write directly, but using this function allows for future error handling in one place. - - int ser_send_pace(int fd, unsigned long d_usec, const char *fmt, ...) + - int ser_send_pace(int fd, unsigned long d_usec, + const char *fmt, ...) If you need to send a formatted buffer with an intercharacter delay, use this function. There are a number of UPS controllers which can't take @@ -388,7 +390,8 @@ that your UPS can handle characters at the full line rate. This sends a raw buffer to the fd. It is typically used for binary transmissions. It returns the results of the call to write. - - int ser_send_buf_pace(int fd, unsigned long d_usec, const char *buf, size_t buflen) + - int ser_send_buf_pace(int fd, unsigned long d_usec, + const char *buf, size_t buflen) This is just ser_send_buf with an intercharacter delay. @@ -434,25 +437,25 @@ failure and 0 on a timeout. If the character matches the ignset with strchr(), it will not be added to the buffer. If you don't need to ignore any characters, just pass it -an empty string - "". +an empty string -- `""`. -The buffer is always cleared and is always null-terminated. It does -this by reading at most (buflen - 1) bytes. +The buffer is always cleared and is always `null`-terminated. It does +this by reading at most `(buflen - 1)` bytes. NOTE: any other data which is read after the endchar in the serial -buffer will be lost forever. As a result, you should not use this +buffer will be lost forever. As a result, you should not use this unless your UPS uses a polled protocol. -Let's say your endchar is \n and your UPS sends "OK\n1234\nabcd\n". -This function will read() all of that, find the first \n, and stop -there. Your driver will get "OK", and the rest is gone forever. +Let's say your endchar is `\n` and your UPS sends `"OK\n1234\nabcd\n"`. +This function will `read()` all of that, find the first `\n`, and stop +there. Your driver will get `"OK"`, and the rest is gone forever. This also means that you should not "pipeline" commands to the UPS. Send a query, then read the response, then send the next query. - - int ser_get_line_alert(int fd, char *buf, size_t buflen, - char endchar, const char *ignset, const char *alertset, + - int ser_get_line_alert(int fd, char *buf, size_t buflen, + char endchar, const char *ignset, const char *alertset, void handler(char ch), long d_sec, long d_usec) This is just like ser_get_line, but it allows you to specify a set of @@ -516,7 +519,7 @@ Drivers which use USB functions should include usb-common.h and use these: Structure and macro ~~~~~~~~~~~~~~~~~~~ - + You should us the usb_device_id structure, and the USB_DEVICE macro to declare the supported devices. This allows the automatic extraction of USB information, to generate the Hotplug, udev and UPower support files. @@ -542,16 +545,17 @@ static usb_device_id sv_usb_device_table [] = { Function ~~~~~~~~ - - is_usb_device_supported(usb_device_id **usb_device_id_list, - int dev_VendorID, int dev_ProductID) + - is_usb_device_supported(usb_device_id **usb_device_id_list, + int dev_VendorID, int dev_ProductID) Call this in your device opening / matching function. Pass your usb_device_id structure, and a set of VendorID / DeviceID. -This function returns one of the following value: +This function returns one of the following value: - NOT_SUPPORTED (0), -- POSSIBLY_SUPPORTED (1, returned when the VendorID is matched, but the DeviceID is unknown), +- POSSIBLY_SUPPORTED (1, returned when the VendorID is matched, but the +DeviceID is unknown), - or SUPPORTED (2). For implementation examples, refer to the various USB drivers, and search for @@ -591,15 +595,15 @@ function. Right now, there are only two possibilities: SET ~~~ -If your driver's function for handling variable set events is called +If your driver's function for handling variable set events is called my_ups_set(), then you'd do this to add the pointer: upsh.setvar = my_ups_set; my_ups_set() will receive two parameters: - const char * - the variable being changed - const char * - the new value + const char * -- the variable being changed + const char * -- the new value You should return either STAT_SET_HANDLED if your driver recognizes the command, or STAT_SET_UNKNOWN if it doesn't. Other possibilities will be @@ -615,8 +619,8 @@ arriving from the server. Your function will receive two args: - const char * - the command name - const char * - (reserved) + const char * -- the command name + const char * -- (reserved) You should return either STAT_INSTCMD_HANDLED or STAT_INSTCMD_UNKNOWN depending on whether your driver can handle the requested command. diff --git a/docs/nut-names.txt b/docs/nut-names.txt index e7f4d86a1b..5b33b540a9 100644 --- a/docs/nut-names.txt +++ b/docs/nut-names.txt @@ -37,7 +37,7 @@ during a transition period. The ups.* data will then be removed. | device.contact | Device administrator name (opaque string) | John Doe | device.location | Device physical location (opaque string) | 1st floor | device.part | Device part number (opaque string) | 123456789 -| device.macaddr | Physical network address of the device | 68:b5:99:f5:89:27 +| device.macaddr | Physical network address of the device | 68:b5:99:f5:89:27 | device.uptime | Device uptime in seconds | 1782 | device.count | Total number of daisychained devices | 1 |===================================================================================== @@ -62,7 +62,7 @@ ups: General unit information | ups.mfr | UPS manufacturer | APC | ups.mfr.date | UPS manufacturing date (opaque string) | 10/17/96 -| ups.serial | UPS serial number (opaque +| ups.serial | UPS serial number (opaque string) | WS9643050926 | ups.vendorid | Vendor ID for USB devices | 0463 | ups.productid | Product ID for USB devices | 0001 @@ -260,17 +260,17 @@ Example: `input.L1.current` Valid CONTEXTs ^^^^^^^^^^^^^^ - L1-L2 \ - L2-L3 \ - L3-L1 for voltage measurements - L1-N / - L2-N / - L3-N / + L1-L2 \ + L2-L3 \ + L3-L1 for voltage measurements + L1-N / + L2-N / + L3-N / - L1 \ - L2 for current and power measurements - L3 / - N - for current measurement + L1 \ + L2 for current and power measurements + L3 / + N - for current measurement Valid SPECs ^^^^^^^^^^^ @@ -294,7 +294,7 @@ Valid with/without context (i.e. per phase or aggregated/averaged) | voltage.nominal | Nominal voltage (V) | voltage.maximum | Maximum seen voltage (V) | voltage.minimum | Minimum seen voltage (V) -| voltage.status | Status relative to the thresholds +| voltage.status | Status relative to the thresholds | voltage.low.warning | Low warning threshold (V) | voltage.low.critical | Low critical threshold (V) | voltage.high.warning | High warning threshold (V) @@ -325,7 +325,7 @@ Valid without context (i.e. aggregation of all phases): EXAMPLES ~~~~~~~~ -Partial Three phase - Three phase example: +Partial Three phase -- Three phase example: input.phases: 3 input.frequency: 50.0 @@ -335,7 +335,7 @@ Partial Three phase - Three phase example: output.L1.power: 35700 output.powerfactor: 0.82 -Partial Three phase - One phase example: +Partial Three phase -- One phase example: input.phases: 3 input.L2.current: 48.2 @@ -354,6 +354,8 @@ battery: Any battery details |=============================================================================== | Name | Description | Example value | battery.charge | Battery charge (percent) | 100.0 +| battery.charge.approx | Rough approximation of battery + charge (opaque, percent) | <85 | battery.charge.low | Remaining battery level when UPS switches to LB (percent) | 20 | battery.charge.restart | Minimum battery level for @@ -379,7 +381,7 @@ battery: Any battery details restart after power-off (seconds) | 120 | battery.alarm.threshold | Battery alarm threshold | 0 (immediate) | battery.date | Battery change date (opaque string) | 11/14/00 -| battery.mfr.date | Battery manufacturing date +| battery.mfr.date | Battery manufacturing date (opaque string) | 2005/04/02 | battery.packs | Number of battery packs | 001 | battery.packs.bad | Number of bad battery packs | 000 @@ -549,7 +551,7 @@ outlet.group: groups of smart outlets This is a refinement of the outlet collection, providing grouped management for a set of outlets. The same principles and data than the outlet collection apply to outlet.group, especially for the indexing 'n' -and "outlet.group.count". +and "outlet.group.count". Most of the data published for outlets also apply to outlet.group, including: id, name (similar as outlet "desc"), status, current and @@ -625,9 +627,9 @@ Instant commands | Name | Description | load.off | Turn off the load immediately | load.on | Turn on the load immediately -| load.off.delay | Turn off the load possibly after a delay -| load.on.delay | Turn on the load possibly after a delay -| shutdown.return | Turn off the load possibly after a delay +| load.off.delay | Turn off the load possibly after a delay +| load.on.delay | Turn on the load possibly after a delay +| shutdown.return | Turn off the load possibly after a delay and return when power is back | shutdown.stayoff | Turn off the load possibly after a delay and remain off even if power returns @@ -654,7 +656,7 @@ Instant commands | beeper.disable | Disable UPS beeper/buzzer | beeper.mute | Temporarily mute UPS beeper/buzzer | beeper.toggle | Toggle UPS beeper/buzzer -| outlet.n.shutdown.return | Turn off the outlet possibly after a delay +| outlet.n.shutdown.return | Turn off the outlet possibly after a delay and return when power is back | outlet.n.load.off | Turn off the outlet immediately | outlet.n.load.on | Turn on the outlet immediately diff --git a/docs/nut-qa.txt b/docs/nut-qa.txt index 7cc39bb559..147e56d9b6 100644 --- a/docs/nut-qa.txt +++ b/docs/nut-qa.txt @@ -15,7 +15,7 @@ link:http://www.methods.co.nz/asciidoc/[AsciiDoc] to output both HTML pages and manual pages (troff). This single point of control fills many gaps, suppresses many redundancies, and optimizes documentation management in general. - + - The NUT website and HTML documentation are tested for W3C XHTML 1.1 and CSS compliance. This can be counter verified by clicking the W3C XHTML 1.1 and CSS icons, at the bottom of each page. @@ -103,7 +103,7 @@ FIXME (POST): the installation, upgrade and removal testing processes. - a runtime testing suite, which automates the inter-layer communication testing -(driver - upsd - upsmon / clients), that is part of Ubuntu. +(driver -- upsd -- upsmon / clients), that is part of Ubuntu. link:http://bazaar.launchpad.net/~ubuntu-bugcontrol/qa-regression-testing/master/view/head:/scripts/test-nut.py[The NUT testing script] is available in the link:https://code.edge.launchpad.net/qa-regression-testing[Ubuntu QA Regression Testing suite]. It installs NUT, configures it with the dummy-ups driver, changes a few data and @@ -111,7 +111,7 @@ checks that these are well propagated with upsc. - link:https://bugzilla.redhat.com/buglist.cgi?component=nut[Redhat / Fedora Bug tracker] -- link:https://www.openhub.net/p/nut[Black Duck Open Hub] (formerly Ohloh.net) +- link:https://www.openhub.net/p/nut[Black Duck Open Hub] (formerly Ohloh.net) provides metrics on NUT source code base and activity. Runtime quality diff --git a/docs/nut.dict b/docs/nut.dict index 28b18ff2d1..5573685da3 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 2412 utf-8 +personal_ws-1.1 en 2491 utf-8 AAS ACFAIL ACFREQ @@ -27,6 +27,7 @@ ARS ATEK ATR ATT +ATTRS ATX ATs AVL @@ -92,6 +93,7 @@ BTIntervl BTS BTTime BTV +BUFRD BUZ BYP BZ @@ -112,6 +114,7 @@ BayTech BeepTone Belkin's Benedikt +Berge BestPort BiWeekly Bieringer @@ -145,6 +148,7 @@ CERTREQUEST CERTVERIF CEST CHRG +CLI CLOCAL CMDDESC CMDSCRIPT @@ -283,6 +287,7 @@ Eriksson FEMEA FFF FH +FHS FINALDELAY FIPS FIXME @@ -397,8 +402,10 @@ IMG INADDR INFOSIZE INIGO +INNO INSTCMDDESC INTERNETOFFICE +INTERR INTL INV INVOLT @@ -437,8 +444,8 @@ KNutClient KNutSetting KOLFF KRT -Kaminski Kain +Kaminski Kanji Kazutoshi Kebo @@ -546,6 +553,7 @@ Martinezgarza Martín Marzouk Massimo +Matthijs MaxACVI MaxACVO MaxDCV @@ -584,6 +592,7 @@ MyState NAK NAS NBF +NConfigs NETVER NETVERSION NFS @@ -599,6 +608,7 @@ NNNNNNNNNNNNNNNNNNN NOAUTH NOCOMM NOCOMMWARNTIME +NOCONF NOMBATTV NOMINV NOMOUTV @@ -614,6 +624,7 @@ NOTIFYMSG NQA NTP NUT's +NUTSRC NVA NX Nadav @@ -663,6 +674,7 @@ Oldworld Olli Omni OmniGuard +OmniOS OmniSmart OnLine OnTime @@ -706,6 +718,7 @@ PLL PLVn POLLFREQALERT POMode +POSIX POWERDOWNFLAG POWEREX POWERLINE @@ -741,6 +754,8 @@ PhaseWin PhoenixContact PhoenixTec Phoenixtec +Pi +PiJuice Plesser PnP Pohle @@ -897,6 +912,7 @@ SKU SL SMALLBUF SMBUS +SMF SMK SMT SMTP @@ -919,6 +935,9 @@ STESTI STI STO STP +SUNWlibusbugen +SUNWugen +SUNWusb SURTD SUSE SX @@ -978,6 +997,7 @@ Suatoni SuperPower Sweex Symmetra +Symmetras Synology SysHrs Sysgration @@ -996,6 +1016,7 @@ TIOCMBIC TIOCMBIS TLS TODO +TRACKINGDELAY TRYSSL TSR TST @@ -1024,6 +1045,8 @@ Tnn Tomek TopGuard Toth +TrackingID +TrackingResult Tripp TrippLite Tru @@ -1060,6 +1083,7 @@ UTalk UUU UX Ulf +Uncomment Unices Unitek Upsonic @@ -1148,10 +1172,12 @@ addenum addinfo addrange adkorte +adm admin's adminbox advorder ae +aec af aggregator ai @@ -1183,6 +1209,7 @@ apctest apcupsd aphel ar +arg argc args argv @@ -1264,6 +1291,7 @@ bindir bitmapped bitwise bn +boolean boostvoolts bootable bp @@ -1284,6 +1312,7 @@ bypassvolts byv cablepower calloc +cb cbl cblimit cd @@ -1302,6 +1331,8 @@ cfacvod cfacvon cfdcvd cfdcvn +cfg +cfgadm cflag cflags cgi @@ -1312,8 +1343,10 @@ chargetime charset checksum chgrp +chipset chmod chown +chr christoph chroot chrooted @@ -1335,9 +1368,11 @@ clueful cmd cmdline cmdname +cmdparam cmds cmdvartab codebase +codepath coldstarts collectd colspan @@ -1346,6 +1381,7 @@ commandlen compat conf config +configs configureaz configureaza confpath @@ -1399,23 +1435,27 @@ debouncing deci decrement decrypt +dedb defun dep dephasing deps desc deschis +descr desde dev devd devel devscan dfl +dialout dipsw dir disp distcheck distro +distros dl dll dlopen @@ -1484,6 +1524,7 @@ everyone's everything's evilhack executables +executeCommand execve extendedhistory extradata @@ -1509,6 +1550,7 @@ filenames filesystem filesystems firewalling +firmwares flts fmt footnoteref @@ -1522,6 +1564,7 @@ frob frontends fs fsd +ftdi fuji fullload gamatronic @@ -1537,8 +1580,10 @@ gentoo gestion getDescription getDevice +getTrackingResult getValue getVariable +getenv getopt getvar gitignore @@ -1561,6 +1606,7 @@ gz gzip hal hardcoded +hasFeature hb hcl hg @@ -1651,6 +1697,7 @@ ivtscd jNUT jNut jNutWebAPI +journalctl jpg jpgraph json @@ -1677,6 +1724,7 @@ libaugeas libc libcommon libdir +libexec libhid libhidups libi @@ -1728,6 +1776,8 @@ lowruntime lowvoltsout lr lsusb +lu +lv lvo lxml lxyz @@ -1762,6 +1812,7 @@ mecer megatec memset merchantability +metadata metasys methodOfFlowControl mge @@ -1793,11 +1844,13 @@ mmddyyyy mn modbus modelname +modprobe monmaster monpasswd monslave monuser morbo +msec multi multilink multimeter @@ -1933,12 +1986,15 @@ pe peername pem perl +pfexec pfy ph phasewindow phoenixcontact +picocom pid pidpath +pijuice pinout pinouts pkg @@ -1990,6 +2046,8 @@ privProtocol probu proc productid +prog +prtconf psu pw pwl @@ -2091,8 +2149,10 @@ sendline sendmail ser seria +serialno serialnumber servicebypass +setFeature setaux setflags setgid @@ -2111,11 +2171,14 @@ shutdownpolarity shutdowntime shutup si +siemens sigaction sigmask simplejson simu +sio sitesearch +sitop sizeof skel slavesync @@ -2131,11 +2194,13 @@ snmpwalk snprintf snprintfcat sockdebug +solaris solis somepass something's sp spanish +spectype spellcheck splitaddr splitname @@ -2185,11 +2250,13 @@ sudo suid superset sv +svc svn sw symlink symlinking symlinks +symmetrathreephase sys sysDescr sysOID @@ -2199,6 +2266,7 @@ syscalls sysconfdir sysconfig syslog +systemctl systemd systemdsystemunitdir systemhours @@ -2241,6 +2309,7 @@ tsd tty ttyS ttySx +ttyUPS ttyUSB ttya ttyb @@ -2261,9 +2330,12 @@ uc udev udevadm ufw +ugen ukUNV ul un +uncomment +unconfigured undefine undervoltage unescaped @@ -2298,10 +2370,12 @@ upsdebugx upsdev upsdrv upsdrvctl +upsdrvsvcctl upserror upsfetch upsgone upsh +upshandler upsidentmodel upsimage upsload @@ -2323,10 +2397,13 @@ upsuser uptime urpmi usb +usbconfig usbfs usbhid +usbif usbmisc usbups +usbus usd usec userid @@ -2338,6 +2415,7 @@ usleep usr utalk uu +uucp va valgrind validationSequence @@ -2351,6 +2429,7 @@ varlow varname varvalue vbatt +vc vendorid verifySourceSig versa diff --git a/docs/nutdrv_qx-subdrivers.txt b/docs/nutdrv_qx-subdrivers.txt index 49f5d60b7a..88025248e7 100644 --- a/docs/nutdrv_qx-subdrivers.txt +++ b/docs/nutdrv_qx-subdrivers.txt @@ -15,7 +15,7 @@ Adding support for a new UPS device is easy, because it requires only the creati Creating a subdriver ~~~~~~~~~~~~~~~~~~~~ -In order to develop a new subdriver for a specific UPS you have to know the idiom spoken by that device. +In order to develop a new subdriver for a specific UPS you have to know the "idiom" (dialect of the protocol) spoken by that device. This kind of devices speaks idioms that can be summed up as follows: @@ -56,7 +56,7 @@ typedef struct { Where: *+name+*:: -Name of this subdriver: name of the +protocol+ that will need to be set in +ups.conf+ to use this subdriver plus the internal version of it separated by a space (e.g. "++Megatec 0.01++"). +Name of this subdriver: name of the +protocol+ that will need to be set in the +ups.conf+ file to use this subdriver plus the internal version of it separated by a space (e.g. "++Megatec 0.01++"). *+claim+*:: This function allows the subdriver to "claim" a device: return +1+ if the device is supported by this subdriver, else +0+. @@ -183,7 +183,7 @@ This function will be given +value+ and its +size_t+ and must return either +0+ -- *+command+*:: -Command sent to the UPS to get answer/to execute a instant command/to set a variable. +Command sent to the UPS to get answer, or to execute an instant command, or to set a variable. *+answer+*:: Answer from the UPS, filled at runtime. @@ -402,11 +402,11 @@ Filled at runtime +dfl+:: +%s+ + -Since a +preprocess+ function is defined for this item, this could have been +NULL+, however, if we want - like here -, we can use it in our +preprocess+ function. +Since a +preprocess+ function is defined for this item, this could have been +NULL+, however, if we want -- like here -- we can use it in our +preprocess+ function. +qxflags+:: +QX_FLAG_QUICK_POLL+ -> this item will be polled every time the driver will check for updates. -Since this item is mandatory to run the driver, if a problem arises in +QX_WALKMODE_INIT+ the driver won't skip it an it'll set +datastale+. +Since this item is mandatory to run the driver, if a problem arises in +QX_WALKMODE_INIT+ the driver won't skip it and it will set +datastale+. +preprocess_command+:: +NULL+ @@ -475,10 +475,10 @@ Filled at runtime +dfl+:: +%s+ + -Since a +preprocess+ function is defined for this item, this could have been +NULL+, however, if we want - like here -, we can use it in our +preprocess+ function. +Since a +preprocess+ function is defined for this item, this could have been +NULL+, however, if we want -- like here -- we can use it in our +preprocess+ function. +qxflags+:: -+QX_FLAG_SEMI_STATIC+ -> this item changes - and will therefore updated - only when we send a command/setvar to the UPS ++QX_FLAG_SEMI_STATIC+ -> this item changes -- and will therefore be updated -- only when we send a command/setvar to the UPS + +QX_FLAG_ENUM+ -> this r/w variable is of the enumerated type and the enumerated values are listed in the +info_rw+ structure (i.e. +voltronic_e_batt_type+) @@ -519,7 +519,7 @@ Here's the +item_t+: +info_rw+:: +voltronic_e_batt_type+ + -The value provided by the user will be automagically checked by the core nutdrv_qx driver against the enumerated values already set by the non setvar item (i.e. +Li+, +Flooded+ or +AGM+), so this could have been +NULL+, however if we want - like here - we can use it in our +preprocess+ function. +The value provided by the user will be automagically checked by the core nutdrv_qx driver against the enumerated values already set by the non setvar item (i.e. +Li+, +Flooded+ or +AGM+), so this could have been +NULL+, however if we want -- like here -- we can use it in our +preprocess+ function. +command+:: +PBT%02.0f\r+ @@ -704,7 +704,7 @@ So we know that the UPS reports actual input/output phase angles when queried fo ---- > [QPD\r] -< [(000 120\r] <- Input Phase Angle - Output Phase Angle +< [(000 120\r] <- Input Phase Angle -- Output Phase Angle 012345678 0 ---- @@ -787,7 +787,7 @@ This information will be used to print the value we got back from the UPS in the +info_flags+:: +ST_FLAG_RW+ + -This could also be +0+ (it's not really used by the driver), but it's set to +ST_FLAG_RW+ for cohesion with other rw vars - also, if ever a NUT variable would become available for this item, it'll be easier to change this item and its +QX_FLAG_SETVAR+ counterpart to use it. +This could also be +0+ (it's not really used by the driver), but it's set to +ST_FLAG_RW+ for cohesion with other rw vars -- also, if ever a NUT variable would become available for this item, it'll be easier to change this item and its +QX_FLAG_SETVAR+ counterpart to use it. +info_rw+:: +voltronic_e_phase+ @@ -823,7 +823,7 @@ If there's no +preprocess+ function, the format is used to print the value to th Here instead it's used by the +preprocess+ function. +qxflags+:: -+QX_FLAG_SEMI_STATIC+ -> this item changes - and will therefore updated - only when we send a command/setvar to the UPS ++QX_FLAG_SEMI_STATIC+ -> this item changes -- and will therefore be updated -- only when we send a command/setvar to the UPS + +QX_FLAG_ENUM+ -> this r/w variable is of the enumerated type and the enumerated values are listed in the +info_rw+ structure (i.e. +voltronic_e_phase+). + @@ -964,9 +964,10 @@ Notes ~~~~~ You must put the generated files into the +drivers/+ subdirectory, with the name of your subdriver preceded by +nutdrv_qx_+, and update +nutdrv_qx.c+ by adding the appropriate +#include+ line and by updating the definition of +subdriver_list+. + Please, make sure to add your driver in that list in a smart way: if your device supports also the basic commands used by the other subdrivers to claim a device, add something that is unique (i.e. not supported by the other subdrivers) to your device in your claim function and then add it on top of the slightly supported ones in that list. -You must also add the subdriver to +NUTDRV_QX_SUBDRIVERS+ in +drivers/Makefile.am+ and call "++autoreconf++" and/or "++./configure++" from the top level NUT directory. +You must also add the subdriver to +NUTDRV_QX_SUBDRIVERS+ list variable in the +drivers/Makefile.am+ and call "++autoreconf++" and/or "++./configure++" from the top level NUT directory. You can then recompile +nutdrv_qx+, and start experimenting with the new subdriver. diff --git a/docs/outlets.txt b/docs/outlets.txt index 853f6ae353..ee59df1ac9 100644 --- a/docs/outlets.txt +++ b/docs/outlets.txt @@ -44,7 +44,7 @@ For a complete list of outlet data and commands, refer to the An example upsc output (data/epdu-managed.dev) is available in the source archive. -NOTE: The variables supported depend on the exact device type. +NOTE: The variables supported depend on the exact device type. Outlets on PDU @@ -68,8 +68,8 @@ This also allows the same remote electrical management of devices provided by PDUs, which can be very interesting in Data Centers. For example, on small setup, you can plug printers, USB devices, hubs, (...) -into managed outlets. Depending on your UPS's capabilities, you will be able to -turn off those loads: +into managed outlets. Depending on your UPS's capabilities, you will be able +to turn off those loads: - after some minutes of back-up time using 'outlet.n.delay.start', - when reaching a percentage battery charge using @@ -84,17 +84,19 @@ NOTE: If you need the scheduling function and your device doesn't support it, you can still use <>. -WARNING: don't plug the UPS's communication cable (USB or network) on a managed outlet. -Otherwise, all computers will be stopped as soon as the communication is lost. +WARNING: don't plug the UPS's communication cable (USB or network) on a +managed outlet. Otherwise, all computers will be stopped as soon as the +communication is lost. Other type of devices --------------------- -As mentioned in the introduction, some other devices can be considered and managed like -PDUs. This is the case in most blade systems, where the blade chassis offers -power management services. +As mentioned in the introduction, some other devices can be considered and +managed like PDUs. This is the case in most blade systems, where the blade +chassis offers power management services. This way, you can control remotely each blade server as if it were a PDU outlet. -This category of devices is generally called Remote Power Controls - RPC in NUT. +This category of devices is generally called Remote Power Controls -- +or "RPC" in NUT. diff --git a/docs/packager-guide.txt b/docs/packager-guide.txt index a32209392e..e0eae41be9 100644 --- a/docs/packager-guide.txt +++ b/docs/packager-guide.txt @@ -84,7 +84,7 @@ wizards broken due to hiddev dependencies, and usb support still included in the core package. -[2] +[2] - snmp-ups driver is not available under Mandrake GNU/Linux, but its man is present. See http://rpms.mandrakeclub.com/rpms/mandrake/9.1/i586/Mandrake/RPMS/nut-server-1.2.1-4mdk.i586.html @@ -109,7 +109,7 @@ The following packagers are working on this subject: - SUSE/Novell: Stanislav Brabec NOTE: the people below should be contacted to (re)launch discussions! - + The following packagers should be interested in working on this subject: - FreeBSD: Thierry Thomas? <> @@ -207,15 +207,15 @@ nut ^^^ - Desc: - Files: dummy/serial/USB drivers + upsd + upslog -- Size: -- Deps: +- Size: +- Deps: [[pkg-libupsclient1]] libupsclient1 ^^^^^^^^^^^^^ - Desc: - Files: -- Size: +- Size: - Deps: [[pkg-libupsclient1-dev]] @@ -223,7 +223,7 @@ libupsclient1-dev ^^^^^^^^^^^^^^^^^ - Desc: - Files: -- Size: +- Size: - Deps: NOTE: the "-dev" suffix is to be replaced by "-devel" on RPM based platforms. @@ -233,7 +233,7 @@ nut-cgi ^^^^^^^ - Desc: - Files: -- Size: +- Size: - Deps: @@ -242,7 +242,7 @@ nut-powerman-pdu ^^^^^^^^^^^^^^^^ - Desc: - Files: -- Size: +- Size: - Deps: [[pkg-nut-snmp]] @@ -250,7 +250,7 @@ nut-snmp ^^^^^^^^ - Desc: - Files: -- Size: +- Size: - Deps: [[pkg-nut-xml]] @@ -258,7 +258,7 @@ nut-xml ^^^^^^^ - Desc: - Files: -- Size: +- Size: - Deps: [[pkg-nut-clients]] @@ -266,7 +266,7 @@ nut-clients ^^^^^^^^^^^ - Desc: - Files: -- Size: +- Size: - Deps: [[pkg-python-pynut]] @@ -274,7 +274,7 @@ python-pynut ^^^^^^^^^^^^ - Desc: - Files: -- Size: +- Size: - Deps: [[pkg-python-nut-gui]] @@ -284,7 +284,7 @@ python-nut-gui - Desc: - Files: -- Size: +- Size: - Deps: [[pkg-nut-doc]] @@ -292,7 +292,7 @@ nut-doc ^^^^^^^ - Desc: - Files: -- Size: +- Size: - Deps: @@ -302,7 +302,7 @@ nut-server ^^^^^^^^^^ Desc: Files: dummy/serial/USB drivers + upsd + upslog - Size: + Size: Deps: nut-client, libusb, libc/ld B) nut-snmp @@ -318,7 +318,7 @@ nut-server Deps: libc/ld E) nut-cgi - + Deps: Files: snmp-ups and powernet + manpages diff --git a/docs/scheduling.txt b/docs/scheduling.txt index 77b74d4dd9..28e12b3ff6 100644 --- a/docs/scheduling.txt +++ b/docs/scheduling.txt @@ -3,7 +3,7 @@ Advanced usage and scheduling notes upsmon can call out to a helper script or program when the device changes state. The example upsmon.conf has a full list of which state changes -are available - ONLINE, ONBATT, LOWBATT, and more. +are available -- ONLINE, ONBATT, LOWBATT, and more. There are two options, that will be presented in details: @@ -23,7 +23,7 @@ Your command will be called with the full text of the message as one argument. For the default values, refer to the sample upsmon.conf file. The environment string NOTIFYTYPE will contain the type string of whatever -caused this event to happen - ONLINE, ONBATT, LOWBATT, ... +caused this event to happen -- ONLINE, ONBATT, LOWBATT, ... Making this some sort of shell script might be a good idea, but the helper can be in any programming or scripting language. @@ -52,7 +52,7 @@ You get the idea. NOTIFYCMD /path/to/my/script -- Make a simple script like this at that location: +- Make a simple script like this at that location: #! /bin/bash echo "$*" | sendmail -F"ups@mybox" bofh@pager.example.com @@ -66,7 +66,7 @@ alert in the body of the message, since upsmon passes the alert text Using more advanced features ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Your helper script will be run with a few environment variables set. +Your helper script will be run with a few environment variables set. - UPSNAME: the name of the system that generated the change. + @@ -165,7 +165,7 @@ for an ONBATT condition. This means "when any UPS (the *) goes on battery, start a timer called onbattwarn that will trigger in 30 seconds". We'll come back to the -onbattwarn part in a moment. Right now we need to make sure that we +onbattwarn part in a moment. Right now we need to make sure that we don't trigger that timer if the UPS happens to come back before the time is up. In essence, if it goes back on line, we need to cancel it. So, let's tell upssched that. @@ -180,7 +180,7 @@ Executing commands immediately ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ As an example, consider the scenario where a UPS goes onto battery power. -However, the users are not informed until 60 seconds later - using a timer as +However, the users are not informed until 60 seconds later -- using a timer as described above. Whilst this may let the *logged in* users know that the UPS is on battery power, it does not inform any users subsequently logging in. To enable this we could, at the same time, create a file which is read and @@ -235,7 +235,7 @@ names, you will need to test for each possibility and handle it according to your desires. NOTE: You can invoke just about anything from inside the CMDSCRIPT. It doesn't -need to be a shell script, either - that's just an example. If you want to +need to be a shell script, either -- that's just an example. If you want to write a program that will parse argv[1] and deal with the possibilities, that will work too. @@ -253,9 +253,15 @@ make upsmon set the "forced shutdown" (FSD) flag on the upsd so your slave systems shut down early too. Just do something like this in your CMDSCRIPT: - /usr/local/ups/sbin/upsmon -c fsd + /sbin/upsmon -c fsd -It's not a good idea to call your system's shutdown routine directly +NOTE: the path to `upsmon` must be provided. The default for an installation +built from sources is `/usr/local/ups` (so `/usr/local/ups/sbin/upsmon`), +while packaged installations will generally comply to +link:http://refspecs.linuxfoundation.org/fhs.shtml[FHS -- Filesystem Hierarchy Standard] +(so `/sbin/upsmon`). + +It's not a good idea to call your system's shutdown routine directly from the CMDSCRIPT, since there's no synchronization with the slave systems hooked to the same UPS. FSD is the master's way of saying "we're shutting down *now* like it or not, so you'd better get ready". @@ -284,7 +290,7 @@ no timers are present in the queue, the background process exits. This means that you will only see upssched running when one of two things is happening: - 1. There's a timer of some sort currently running + 1. There's a timer of some sort currently running 2. upsmon just called it, and you managed to catch the brief instance The final optimization handles the possibility of trying to cancel a timer diff --git a/docs/security.txt b/docs/security.txt index fd6b747cda..c335c06b6b 100644 --- a/docs/security.txt +++ b/docs/security.txt @@ -4,8 +4,8 @@ Notes on securing NUT The NUT Team is very interested in providing the highest security level to its users. -Many internal and external mechanisms exist to secure NUT. And several steps are -needed to ensure that your NUT setup meets your security requirements. +Many internal and external mechanisms exist to secure NUT. And several steps +are needed to ensure that your NUT setup meets your security requirements. This chapter will present you these mechanisms, by increasing order of security level. This means that the more security you need, the more mechanisms you will @@ -19,14 +19,17 @@ topics are related to NUT security and reliability. How to verify the NUT source code signature ------------------------------------------- -In order to verify the NUT source code signature for releases, perform the following steps: +In order to verify the NUT source code signature for releases, perform the +following steps: -- Retrieve the link:http://www.networkupstools.org/download.html[NUT source code] (nut-X.Y.Z.tar.gz) and the matching signature (nut-X.Y.Z.tar.gz.sig) +- Retrieve the link:http://www.networkupstools.org/download.html[NUT source code] + (nut-X.Y.Z.tar.gz) and the matching signature (nut-X.Y.Z.tar.gz.sig) - Retrieve the link:http://www.networkupstools.org/source/nut-key.gpg[NUT maintainer's signature]: $ gpg --fetch-keys http://www.networkupstools.org/source/nut-key.gpg -NOTE: As of NUT 2.7.3, a new release key is used. In order to verify previous release, please use +NOTE: As of NUT 2.7.3, a new release key is used. In order to verify a previous +release, please use link:http://www.networkupstools.org/source/nut-old-key.gpg[NUT old maintainer's signature] - Launch the GPG checking using the following command: @@ -56,7 +59,7 @@ Use the following commands to accomplish this: Finally, the <> directory, which holds the -communication between the driver(s) and upsd, should also be secured. +communication between the driver(s) and `upsd`, should also be secured. chown root:nut /var/state/ups chmod 0770 /var/state/ups @@ -74,9 +77,9 @@ linkman:upsd.users[5]. This file defines who may access instant commands and settings, and what is available. -During the initial +During the initial <>, we have created a -monitoring user for upsmon. +monitoring user for `upsmon`. You can also create an 'administrator' user with full power using: @@ -96,7 +99,7 @@ Network access control ---------------------- If you are not using NUT on a standalone setup, you will need to enforce -network access to upsd. +network access to `upsd`. There are various ways to do so. @@ -105,10 +108,10 @@ NUT LISTEN directive linkman:upsd.conf[5]. - LISTEN interface port + LISTEN interface port -Bind a listening port to the interface specified by its Internet address. This -may be useful on hosts with multiple interfaces. You should not rely +Bind a listening port to the interface specified by its Internet address. +This may be useful on hosts with multiple interfaces. You should not rely exclusively on this for security, as it can be subverted on many systems. Listen on TCP port `port` instead of the default value which was compiled into @@ -117,7 +120,7 @@ the code. This overrides any value you may have set with `configure listen on port 3493 for this interface. Multiple LISTEN addresses may be specified. The default is to bind to -127.0.0.1 if no LISTEN addresses are specified (and ::1 if IPv6 support is +`127.0.0.1` if no LISTEN addresses are specified (and `::1` if IPv6 support is compiled in). LISTEN 127.0.0.1 @@ -157,8 +160,8 @@ into the server. `hosts.allow`: - ups : admin@127.0.0.1/32 - ups : monslave@127.0.0.1/32 monslave@192.168.1.0/24 + upsd : admin@127.0.0.1/32 + upsd : monslave@127.0.0.1/32 monslave@192.168.1.0/24 `hosts.deny`: @@ -210,7 +213,7 @@ Create a certificate and key for upsd ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ openssl (the program) should be in your PATH, unless you installed it from -source yourself, in which case it may be in /usr/local/ssl/bin. +source yourself, in which case it may be in `/usr/local/ssl/bin`. Use the following command to create the certificate: @@ -218,7 +221,7 @@ Use the following command to create the certificate: You can also put a `-days nnn` in there to set the expiration. If you skip this, it may default to 30 days. This is probably not what -you want. +you want. It will ask several questions. What you put in there doesn't matter a whole lot, since nobody is going to see it for now. Future versions of the @@ -240,7 +243,7 @@ Install the client-side certificate ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use the following commands to install the client-side certificate: - + mkdir chmod 0755 cp upsd.crt /.0 @@ -259,7 +262,7 @@ to install this file on them as well. We recommend making a directory under your existing confpath to keep everything in the same place. Remember the path you created, -since you will need to put it in upsmon.conf later. +since you will need to put it in upsmon.conf later. It must not be writable by unprivileged users, since someone could insert a new client certificate and fool upsmon into trusting a @@ -280,8 +283,9 @@ hold of port 3493. Having it be owned by 'root' and readable by group 'nut' allows upsd to read the file without being able to change the contents. This -is done to minimize the impact if someone should break into upsd. NUT reads the -key and certificate files after dropping privileges and forking. +is done to minimize the impact if someone should break into upsd. +NUT reads the key and certificate files after dropping privileges +and forking. Note on certification authorities (CAs) and signed keys ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -300,7 +304,7 @@ Example: mv upsd.pem /usr/local/ups/etc/upsd.pem -After that, edit your upsd.conf and tell it where to find it: +After that, edit your `upsd.conf` and tell it where to find it: CERTFILE /usr/local/ups/etc/upsd.pem @@ -364,9 +368,9 @@ link:http://www.mozilla.org/projects/security/pki/nss/[Mozilla NSS]. Install NSS ^^^^^^^^^^^ -Install link:http://www.mozilla.org/projects/security/pki/nss/[Mozilla NSS] as -usual, either from source or binary packages. If using binary packages, be sure -to include the developer libraries, and nss-tools (for `certutil`). +Install link:http://www.mozilla.org/projects/security/pki/nss/[Mozilla NSS] +as usual, either from source or binary packages. If using binary packages, +be sure to include the developer libraries, and nss-tools (for `certutil`). Recompile and install NUT ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -378,13 +382,13 @@ Then install everything as usual. Create certificate and key for the host ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -NSS (package generally called libnss3-tools) will install a tool called +NSS (package generally called libnss3-tools) will install a tool called `certutil`. It will be used to generate certificates and manage certificate database. Certificates should be signed by a certification authorities (CAs). -Following commands are typical samples, contact your SSL guru or security officer -to follow your company procedures. +Following commands are typical samples, contact your SSL guru or security +officer to follow your company procedures. .Generate a server certificate for upsd: - Create a directory where store the certificate database: `mkdir cert_db` @@ -399,12 +403,12 @@ to follow your company procedures. - Display the content of certificate server: `certutil -L -d cert_db` -Clients and servers in the same host could share the same certificate to authenticate them -or use different ones in same or different databases. +Clients and servers in the same host could share the same certificate to +authenticate them or use different ones in same or different databases. The same operation can be done in same or different databases to generate other certificates. -Create a self-signed CA certificate +Create a self-signed CA certificate ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ NSS provides a way to create self-signed certificate which can acting as @@ -419,11 +423,13 @@ an "official" certificate authority. - Generate a certificate for CA: `certutil -S -d CA_db -n "My Root CA" -s "CN=My CA,O=MyCompany,ST=MyState,C=US" -t "CT,," -x -2` (Do not forget to answer 'Yes' to the question 'Is this a CA certificate [y/N]?') -- Extract the CA certificate to be able to import it in upsd (or upsmon) certificate database: +- Extract the CA certificate to be able to import it in upsd (or upsmon) +certificate database: `certutil -L -d CA_db -n "My Root CA" -a -o rootca.crt` -- Sign a certificate request with the CA certificate (simulate a real CA signature): +- Sign a certificate request with the CA certificate (simulate a real CA +signature): `certutil -C -d CA_db -c "My Root CA" -a -i server.req -o server.crt -2 -6` - + Install the server-side certificate ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -439,7 +445,7 @@ upsd (required): certificate database and self certificate Edit the upsd.conf to tell where find the certificate database: CERTPATH /usr/local/ups/etc/cert_db - + Also tell which is the certificate to send to clients to authenticate itself and the password to decrypt private key associated to certificate: @@ -454,13 +460,15 @@ upsd (optional): client authentication NOTE: This functionality is disabled by default. To activate it, recompile NUT with `WITH_CLIENT_CERTIFICATE_VALIDATION` defined: - make CFLAGS="-DWITH_CLIENT_CERTIFICATE_VALIDATION" + make CFLAGS="-DWITH_CLIENT_CERTIFICATE_VALIDATION" UPSD can accept three levels of client authentication. Just specify it with -the directive `CERTREQUEST` with the corresponding value in the upsd.conf file: +the directive `CERTREQUEST` with the corresponding value in the upsd.conf +file: - NO: no client authentication. -- REQUEST: a certificate is request to the client but it is not strictly validated. +- REQUEST: a certificate is request to the client but it is not strictly +validated. If the client does not send any certificate, the connection is closed. - REQUIRE: a certificate is requested to the client and if it is not valid (no validation chain) the connection is closed. @@ -505,8 +513,9 @@ upsmon (optional): certificate database and self certificate Like upsd, upsmon may need to authenticate itself (upsd's `CERTREQUEST` directive set to `REQUEST` or `REQUIRE`). -It must access to a certificate (and its private key) in a certificate database -configuring `CERTPATH` and `CERTIDENT` in upsmon.conf in the same way than upsd. +It must access to a certificate (and its private key) in a certificate +database configuring `CERTPATH` and `CERTIDENT` in upsmon.conf in the +same way as upsd. CERTPATH /usr/local/ups/etc/cert_db CERTIDENT 'certificate name' 'database password' @@ -532,7 +541,7 @@ You should see something like this in the syslog from upsd: If upsd or upsmon give any error messages, or the `(SSL)` is missing, then something isn't right. -If in doubt about upsmon, start it with -D so it will stay in +If in doubt about upsmon, start it with -D so it will stay in the foreground and print debug messages. It should print something like this every couple of seconds: @@ -554,10 +563,10 @@ then something is not working. Potential problems ~~~~~~~~~~~~~~~~~~ -If you specify a certificate expiration date, you will eventually +If you specify a certificate expiration date, you will eventually see things like this in your syslog: - Oct 29 07:27:25 rktoy upsmon[3789]: Poll UPS [for750@rktoy] failed - + Oct 29 07:27:25 rktoy upsmon[3789]: Poll UPS [for750@rktoy] failed - SSL error: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE: certificate verify failed You can verify that it is expired by using openssl to display the date: @@ -593,7 +602,7 @@ Other packages have solved this by explicitly stating that an exception has been granted. That is (purposely) impossible here, since NUT is the combined effort of many people, and all of them would have to agree to a license change. This is actually a feature, since it means nobody can -unilaterally run off with the source - not even the NUT team. +unilaterally run off with the source -- not even the NUT team. Note that the replacement of OpenSSL by Mozilla Network Security Services (NSS) should avoid the above licensing issues. @@ -624,9 +633,9 @@ Generalities Essentially, you need to create your configuration directory and state path in their own little world, plus a special device or two. -For the purposes of this example, the chroot jail is /chroot/nut. The +For the purposes of this example, the chroot jail is `/chroot/nut`. The programs have been built with the default prefix, so they are using -/usr/local/ups. First, create the confpath and bring over a few files. +`/usr/local/ups`. First, create the confpath and bring over a few files. mkdir -p /chroot/nut/usr/local/ups/etc cd /chroot/nut/usr/local/ups/etc @@ -642,19 +651,19 @@ before. mkdir -p /chroot/nut/var/state cp -a /var/state/ups /chroot/nut/var/state -Next we must put /etc/localtime inside the jail, or you may get very +Next we must put `/etc/localtime` inside the jail, or you may get very strange readings in your syslog. You'll know you have this problem if -upsd shows up as UTC in the syslog while the rest of the system doesn't. +`upsd` shows up as UTC in the syslog while the rest of the system doesn't. mkdir -p /chroot/nut/etc cp /etc/localtime /chroot/nut/etc -Note that this is not "cp -a", since we want to copy the *content*, not +Note that this is not `cp -a`, since we want to copy the *content*, not the symlink that it may be on some systems. -Finally, create a tiny bit of /dev so the programs can enter the -background properly - they redirect fds into the bit bucket to make sure -nothing else grabs 0-2. +Finally, create a tiny bit of `/dev` so the programs can enter the +background properly -- they redirect file descriptors into the bit +bucket to make sure nothing else grabs fds 0-2. mkdir -p /chroot/nut/dev cp -a /dev/null /chroot/nut/dev @@ -663,30 +672,30 @@ Try to start your driver(s) and make sure everything fires up as before. upsdrvctl -r /chroot/nut -u nutdev start -Once your drivers are running properly, try starting upsd. +Once your drivers are running properly, try starting `upsd`. upsd -r /chroot/nut -u nutsrv Check your syslog. If nothing is complaining, try running clients like -upsc and upsmon. If they seem happy, then you're done. +`upsc` and `upsmon`. If they seem happy, then you're done. symlinks ~~~~~~~~ After you do this, you will have two copies of many things, like the confpath and the state path. I recommend deleting the 'real' -/var/state/ups, replacing it with a symlink to -/chroot/nut/var/state/ups. That will let other programs reference the -.pid files without a lot of hassle. +`/var/state/ups`, replacing it with a symlink to +`/chroot/nut/var/state/ups`. That will let other programs reference the +`.pid` files without a lot of hassle. -You can also do this with your confpath and point /usr/local/ups/etc at -/chroot/nut/usr/local/ups/etc unless you're worried about something -hurting the files inside that directory. In that case, you should -maintain a 'master' copy and push it into the chroot path after -making changes. +You can also do this with your confpath and point `/usr/local/ups/etc` (or +equivalent on your system) at `/chroot/nut/usr/local/ups/etc` unless you're +worried about something hurting the files inside that directory. In that +case, you should maintain a 'master' copy and push it into the chroot path +after making changes. -upsdrvctl itself does not chroot, so the ups.conf still needs to be in -the usual confpath. +The `upsdrvctl` itself does not chroot, so the `ups.conf` still needs to be +in the usual confpath. upsmon ~~~~~~ @@ -706,7 +715,7 @@ This one is messy, and may not happen for some time, if ever. Config files ~~~~~~~~~~~~ -You may now set chroot= and user= in the global section of ups.conf. +You may now set `chroot=` and `user=` in the global section of `ups.conf`. -upsd chroots before opening any config files, so there is no way to -add support for that in upsd.conf at the present time. +The `upsd` chroots before opening any config files, so there is no way to +add support for that in `upsd.conf` at the present time. diff --git a/docs/snmp-subdrivers.txt b/docs/snmp-subdrivers.txt index 0fe7332bab..f010ff8960 100644 --- a/docs/snmp-subdrivers.txt +++ b/docs/snmp-subdrivers.txt @@ -86,7 +86,7 @@ link:http://en.wikipedia.org/wiki/Simple_Network_Management_Protocol[Wikipedia] article, or browse the Internet. -To be able to convert values, NUT SNMP subdrivers need to provide: +To be able to convert values, NUT SNMP subdrivers need to provide: - manufacturer-specific sysOID, to determine which lookup structure applies to which devices, diff --git a/docs/snmp.txt b/docs/snmp.txt index b48abc7fd9..64b9c06f6f 100644 --- a/docs/snmp.txt +++ b/docs/snmp.txt @@ -25,7 +25,7 @@ This is part of the "UPS Sub-Agent" project with Net-SNMP team. 2) the client side * Introduction - + An SNMP client communicates with an agent to acquire data. This part, which has to be a NUT driver, is implemented by snmp-ups. @@ -37,14 +37,14 @@ declaration). For more information on snmp-ups, have a look at its manpage (man 8 snmp-ups). * Extending existing mib2nut information - + To be written... - + * Adding new mib2nut information To be written... - - + + References: - NUT SNMP Protocols Library Available at: http://www.networkupstools.org/ups-protocols.html#_snmp diff --git a/docs/sock-protocol.txt b/docs/sock-protocol.txt index 944d3ef7fd..e4701e5234 100644 --- a/docs/sock-protocol.txt +++ b/docs/sock-protocol.txt @@ -30,7 +30,7 @@ SETINFO SETINFO ups.status "OB LB" -There is no "ADDINFO" - if a given variable does not exist, it is +There is no "ADDINFO" -- if a given variable does not exist, it is created upon receiving the first SETINFO command. DELINFO @@ -146,6 +146,18 @@ status information once this has been sent. This will be sent in the beginning of a dump if the data is stale, and may be repeated. It is cleared by DATAOK. +TRACKING +~~~~~~~~ + + TRACKING + +This is sent in response to an INSTCMD or SET VAR that includes a TRACKING, +upon completion of request execution by the driver. is the integer +return value from the driver handlers instcmd and setvar (see +drivers/upshandler.h). The server is in charge of translating these codes into +strings, as per docs/net-protocol.txt GET TRACKING. + + Commands sent by the server --------------------------- @@ -166,16 +178,30 @@ server must not be passed on to the clients when this happens. INSTCMD ~~~~~~~ - INSTCMD + INSTCMD [] [TRACKING ] INSTCMD panel.test.start + INSTCMD load.off 10 + INSTCMD load.on 10 TRACKING 1bd31808-cb49-4aec-9d75-d056e6f018d2 + +NOTE: +* is an additional and optional parameter for the command, +* "TRACKING " can be provided to track commands execution status, if +TRACKING was set to ON on upsd. In this case, driver will later return +the execution status, using TRACKING. SET ~~~ - SET "" + SET "" [TRACKING ] SET ups.id "Data room" + SET ups.id "Data room" TRACKING 2dedb58a-3b91-4fab-831f-c8af4b90760a + +NOTE: +* "TRACKING " can be provided to track commands execution status, if +TRACKING was set to ON on upsd. In this case, driver will later return +the execution status, using TRACKING. DUMPALL ~~~~~~~ @@ -198,7 +224,7 @@ Requests ~~~~~~~~ There is no way to request just one variable. This was done on purpose -to limit the complexity of the drivers. Their job is to send out +to limit the complexity of the drivers. Their job is to send out updates and handle a few simple requests. DUMPALL is provided to give the server a known foundation. diff --git a/docs/solaris-usb.txt b/docs/solaris-usb.txt new file mode 100644 index 0000000000..e672c0bb2f --- /dev/null +++ b/docs/solaris-usb.txt @@ -0,0 +1,226 @@ +NUT USB setup in modern Solaris-like systems (OpenSolaris descendants) +====================================================================== + +Local-media device setup for use with NUT has some nuances with +numerous descendants of the OpenSolaris project, including both +the commercial Sun/Oracle Solaris 11 and illumos-based open source +distributions such as OpenIndiana and OmniOS. Recommendations +below may also apply to other related operating systems, possibly +to older releases as well. + +Change the OS driver binding: use UGEN +-------------------------------------- + +Like other hardware, USB devices are interfaced to the operating +system by OS drivers, and often there are several suitable drivers +with different capabilities. In Solaris and related systems, this +mapping is detailed in the `/etc/driver_aliases` file and properly +managed by dedicated tools. By default, USB devices can be captured +by the generic USB HID driver, or none at all; however an "UGEN" +driver can behave better with the libusb library used on Solaris. + +NOTE: Operations below would need running as `root` or elevating +the privileges (via `pfexec`, `sudo`, etc.) + +Connect the power device using its USB port to your computer. + +Run `prtconf -v | less` to see the details of device connections, +and search for its probable strings (vendor, model, serial number). +Two examples follow: + +In this example, no suitable driver was attached "out of the box": + +```` + input (driver not attached) + Hardware properties: + name='driver-minor' type=int items=1 + value=00000000 + name='driver-major' type=int items=1 + value=00000002 + name='low-speed' type=boolean + name='usb-product-name' type=string items=1 + value='Eaton 9PX' + name='usb-vendor-name' type=string items=1 + value='EATON' + name='usb-serialno' type=string items=1 + value='G202E02032' + name='usb-raw-cfg-descriptors' type=byte items=34 + value=09.02.22.00.01.01.00.a0.0a.09.04.00.00.01.03.00.00.00.09.21.10.01.21.01.22.10.0d.07.05.81.03.08.00.14 + name='usb-dev-descriptor' type=byte items=18 + value=12.01.10.01.00.00.00.08.63.04.ff.ff.00.01.01.02.04.01 + name='usb-release' type=int items=1 + value=00000110 + name='usb-num-configs' type=int items=1 + value=00000001 + name='usb-revision-id' type=int items=1 + value=00000100 + name='usb-product-id' type=int items=1 + value=0000ffff + name='usb-vendor-id' type=int items=1 + value=00000463 + name='compatible' type=string items=9 + value='usb463,ffff.100' + 'usb463,ffff' + 'usbif463,class3.0.0' + 'usbif463,class3.0' + 'usbif463,class3' + 'usbif,class3.0.0' + 'usbif,class3.0' + 'usbif,class3' + 'usb,device' + name='reg' type=int items=1 + value=00000002 + name='assigned-address' type=int items=1 + value=00000003 +```` + +In the following example, a "hid power" driver was attached, giving +some usability to the device although not enough for NUT to interact +well (at least, according to the helpful notes in the +https://web.archive.org/web/20140126045707/http://barbz.com.au/blog/?p=407 +blog entry): + +```` + input, instance #1 + Driver properties: + name='pm-components' type=string items=3 dev=none + value='NAME= hid1 Power' + '0=USB D3 State' + '3=USB D0 State' + Hardware properties: + name='driver-minor' type=int items=1 + value=00000000 + name='driver-major' type=int items=1 + value=00000002 + name='low-speed' type=boolean + name='usb-product-name' type=string items=1 + value='USB to Serial' + name='usb-vendor-name' type=string items=1 + value='INNO TECH' + name='usb-serialno' type=string items=1 + value='20100826' + name='usb-raw-cfg-descriptors' type=byte items=34 + value=09.02.22.00.01.01.03.80.32.09.04.00.00.01.03.00.00.04.09.21.00.01.00.01.22.1b.00.07.05.81.03.08.00.20 + name='usb-dev-descriptor' type=byte items=18 + value=12.01.10.01.00.00.00.08.65.06.61.51.02.00.01.02.03.01 + name='usb-release' type=int items=1 + value=00000110 + name='usb-num-configs' type=int items=1 + value=00000001 + name='usb-revision-id' type=int items=1 + value=00000002 + name='usb-product-id' type=int items=1 + value=00005161 + name='usb-vendor-id' type=int items=1 + value=00000665 + name='compatible' type=string items=9 + value='usb665,5161.2' + 'usb665,5161' + 'usbif665,class3.0.0' + 'usbif665,class3.0' + 'usbif665,class3' + 'usbif,class3.0.0' + 'usbif,class3.0' + 'usbif,class3' + 'usb,device' + name='reg' type=int items=1 + value=00000003 + name='assigned-address' type=int items=1 + value=00000005 + Device Minor Nodes: + dev=(108,2) + dev_path=/pci@0,0/pci8086,7270@1d/hub@1/input@3:hid_0_1 + spectype=chr type=minor + dev_link=/dev/usb/hid0 +```` + +You can also check with `cfgadm` if the device is at least somehow visible +(if not, there can be hardware issues in play). For example, if there is a +physical link but no recognized driver was attached, the device would show +up as "unconfigured": + +```` +# cfgadm | grep usb- +usb8/1 usb-input connected unconfigured ok +```` + +If you conclude that a change is needed, you would need to unload +the existing copy of the "ugen" driver and set it up to handle the +device patterns that you find in 'compatible' values from `prtconf`, +e.g. for monitoring the devices from listings above: + +```` +rem_drv ugen +add_drv -i '"usb463,ffff.100"' -m '* 0666 root sys' ugen +```` + +or + +```` +rem_drv ugen +add_drv -i '"usb665,5161.2"' -m '* 0666 root sys' ugen +```` + +Note that there are many patterns in the 'compatible' line which +allow for narrower or wider catchment. It is recommended to match +with the narrowest fit, to avoid potential conflict with other +devices from same vendor (especially if the declared identifiers +are for a generic USB chipset). + +Also note that the `add_drv` definition above lists the POSIX access +metadata for the device node files that would be generated when the +device is plugged in and detected. In the examples above, it would +be owned by `root:sys` but accessible for reads and writes (`0666`) +to anyone on the system. On shared systems you may want to constrain +this access to the account that the NUT driver would run as. + +After proper driver binding, `cfgadm` should expose the details: + +```` +# cfgadm -lv +... +usb8/1 connected configured ok + Mfg: EATON Product: Eaton 9PX NConfigs: 1 Config: 0 + unavailable usb-input n /devices/pci@0,0/pci103c,1309@1d,2:1 +... +```` + +Usually the driver mapping should set up the "friendly" device nodes +under `/dev/` tree as well (symlinks to real entries in `/devices/`) +so for NUT drivers you would specify a `port=/dev/usb/463.ffff/0` for +your new `driver=usbhid-ups` section. + +For some serial-to-USB converter chips however it was noted that while +the device driver is attached, and the `/device/...` path is exposed +in the `dmesg` output (saved to `/var/adm/messages`) the `/dev/...` +symlinks are not created. In this case you can pass the low-level +name of the character-device node as the "port" option, e.g.: + +```` +./mge-shut -s 9px-ser -DDDDD -d2 -u root \ + -x port=/devices/pci@0,0/pci103c,1309@1a,2/device@1:0 +```` + +libusb version and binary +------------------------- + +Until NUT release 2.7.4 the only option to build NUT drivers for +USB connectivity was to use libusb-0.1 or a distribution's variant +of it; the original Sun Solaris releases and later related systems +provided their customized version for example (packaged originally +as `SUNWlibusbugen`, `SUNWugen{,u}` and `SUNWusb{,s,u,vc}`). + +However, libusb-0.1 consuming programs had some stability issues +reported when running with long-term connections to devices (such +as an UPS), especially when using USB hubs and chips where hardware +vendors had cut a few corners too many, which were addressed in a +newer rewrite of the library as libusb-1.0. + +Subsequently as at least the illumos-based distributions evolved to +include the new library and certain patches for it, and the library +itself matured, the NUT project also added an ability to build with +libusb-1.0 either directly or using its 0.1-compat API. + +Currently this is not part of the master codebase and thus tagged +releases, but is experimented in several competing GitHub branches +until one gets chosen as the best to integrate: + +* https://github.com/networkupstools/nut/issues/300 - Please port to libusb 1.0 #300 +* https://github.com/networkupstools/nut/tree/libusb-1.0 +* https://github.com/networkupstools/nut/tree/libusb-1.0+0.1 +* https://github.com/networkupstools/nut/tree/libusb-compat-1.0 + +If your "standard" build of NUT has problems connecting to your +USB UPS, consider building one of those branches using the recent +library available for your distribution. + +In this context, note the OpenIndiana libusb-1 package pull requests +with code which was successfully used when developing this documentation: + +* https://github.com/OpenIndiana/oi-userland/pull/5382 +* (TO CHECK) https://github.com/OpenIndiana/oi-userland/pull/5277 + +Binaries from builds made in OpenIndiana using the recipe from PR #5382 +above were successfully directly used on contemporary OmniOS CE as well. diff --git a/docs/support.txt b/docs/support.txt index 9e6b6ebb24..2088889de9 100644 --- a/docs/support.txt +++ b/docs/support.txt @@ -9,8 +9,8 @@ There are various ways to obtain support for NUT. Documentation ------------- -- First, be sure to read the link:docs/FAQ.html[FAQ]. The most common problems are already -addressed there. +- First, be sure to read the link:docs/FAQ.html[FAQ]. The most common +problems are already addressed there. ifdef::website[] - Else, you can read the link:docs/user-manual.chunked/index.html[NUT User Manual]. @@ -66,15 +66,16 @@ In this case, be sure to include the following information: - OS name and version, - exact NUT version, - NUT installation method: from source tarball, package or Subversion, -- exact device name and related information (manufacturing date, web pointers, ...), -- complete problem description, with any relevant traces, like system log excerpts, -and driver debug output. You can obtain the latter using the following command, -as root and after having stopped NUT: +- exact device name and related information (manufacturing date, web +pointers, ...), +- complete problem description, with any relevant traces, like system +log excerpts, and driver debug output. You can obtain the latter using +the following command, running as root and after having stopped NUT: /path/to/driver -DD -a -If you don't include the above information in your help request, we will not be -able to help you! +If you don't include the above information in your help request, we will +not be able to help you! Post a patch, ask a development question, ... ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -82,15 +83,15 @@ Post a patch, ask a development question, ... Use the link:http://lists.alioth.debian.org/mailman/listinfo/nut-upsdev[NUT Developers] mailing list. -Refer to the +Refer to the ifdef::website[] link:docs/developer-guide.chunked/index.html[NUT Developer Guide] -for more information, and the chapter on how to +for more information, and the chapter on how to link:docs/developer-guide.chunked/ar01s03.html#_submitting_patches[submit patches]. endif::website[] ifndef::website[] linkdoc:developer-guide[NUT Developer Guide] -for more information, and the chapter on how to +for more information, and the chapter on how to link:../developer-guide.chunked/ar01s03.html#_submitting_patches[submit patches]. endif::website[] @@ -101,7 +102,7 @@ Discuss packaging and related topics Use the link:http://lists.alioth.debian.org/mailman/listinfo/nut-packaging[NUT Packagers] mailing list. -Refer to the +Refer to the ifdef::website[] link:docs/packager-guide.chunked/index.html[NUT Packager Guide] endif::website[] diff --git a/docs/user-manual.txt b/docs/user-manual.txt index 1a3ef8dad6..225f06d740 100644 --- a/docs/user-manual.txt +++ b/docs/user-manual.txt @@ -71,7 +71,7 @@ possibly some more packages to gain access to the serial ports. Other features, such as USB / SNMP / whatever, will also need extra software installed. -Success reports are welcomed to keep this list accurate. +Success reports are welcomed to keep this list accurate. [[Download_instructions]] diff --git a/drivers/Makefile.am b/drivers/Makefile.am index 6c95ac66cd..039cf61bf8 100644 --- a/drivers/Makefile.am +++ b/drivers/Makefile.am @@ -33,22 +33,22 @@ SERIAL_DRIVERLIST = al175 bcmxcp belkin belkinunv bestfcom \ bestfortress bestuferrups bestups dummy-ups etapro everups \ gamatronic genericups isbmex liebert liebert-esp2 masterguard metasys \ mge-utalk microdowell mge-shut oneac optiups powercom rhino \ - safenet skel solis tripplite tripplitesu upscode2 victronups powerpanel \ - blazer_ser clone clone-outlet ivtscd apcsmart apcsmart-old apcupsd-ups riello_ser \ - nutdrv_qx + safenet nutdrv_siemens-sitop skel solis tripplite tripplitesu upscode2 victronups powerpanel \ + blazer_ser clone clone-outlet ivtscd apcsmart apcsmart-old apcupsd-ups riello_ser SNMP_DRIVERLIST = snmp-ups USB_LIBUSB_DRIVERLIST = usbhid-ups bcmxcp_usb tripplite_usb \ blazer_usb richcomm_usb riello_usb \ - nutdrv_atcl_usb \ - nutdrv_qx + nutdrv_atcl_usb USB_DRIVERLIST = $(USB_LIBUSB_DRIVERLIST) +SERIAL_USB_DRIVERLIST = \ + nutdrv_qx NEONXML_DRIVERLIST = netxml-ups MACOSX_DRIVERLIST = macosx-ups MODBUS_DRIVERLIST = phoenixcontact_modbus -LINUX_I2C_DRIVERLIST = asem +LINUX_I2C_DRIVERLIST = asem pijuice # distribute all drivers, even ones that are not built by default -EXTRA_PROGRAMS = $(SERIAL_DRIVERLIST) $(SNMP_DRIVERLIST) $(USB_DRIVERLIST) $(NEONXML_DRIVERLIST) $(MACOSX_DRIVERLIST) +EXTRA_PROGRAMS = $(SERIAL_DRIVERLIST) $(SNMP_DRIVERLIST) $(USB_DRIVERLIST) $(SERIAL_USB_DRIVERLIST) $(NEONXML_DRIVERLIST) $(MACOSX_DRIVERLIST) # construct the list of drivers to build if SOME_DRIVERS @@ -56,7 +56,11 @@ if SOME_DRIVERS else driverexec_PROGRAMS = if WITH_SERIAL - driverexec_PROGRAMS += $(SERIAL_DRIVERLIST) + driverexec_PROGRAMS += $(SERIAL_DRIVERLIST) $(SERIAL_USB_DRIVERLIST) +else +if WITH_USB + driverexec_PROGRAMS += $(SERIAL_USB_DRIVERLIST) +endif endif if WITH_SNMP driverexec_PROGRAMS += $(SNMP_DRIVERLIST) @@ -131,6 +135,7 @@ powerpanel_LDADD = $(LDADD) -lm rhino_SOURCES = rhino.c rhino_LDADD = $(LDADD) -lm safenet_SOURCES = safenet.c +nutdrv_siemens_sitop_SOURCES = nutdrv_siemens_sitop.c solis_SOURCES = solis.c solis_LDADD = $(LDADD) -lm tripplite_SOURCES = tripplite.c @@ -207,7 +212,7 @@ snmp_ups_SOURCES = snmp-ups.c apc-mib.c baytech-mib.c compaq-mib.c \ ietf-mib.c mge-mib.c netvision-mib.c powerware-mib.c raritan-pdu-mib.c \ bestpower-mib.c cyberpower-mib.c delta_ups-mib.c xppc-mib.c huawei-mib.c \ eaton-ats16-mib.c apc-ats-mib.c raritan-px2-mib.c eaton-ats30-mib.c \ - apc-pdu-mib.c + apc-pdu-mib.c emerson-avocent-pdu-mib.c hpe-pdu-mib.c snmp_ups_CFLAGS = $(AM_CFLAGS) snmp_ups_CFLAGS += $(LIBNETSNMP_CFLAGS) snmp_ups_LDADD = $(LDADD_DRIVERS) $(LIBNETSNMP_LIBS) @@ -223,7 +228,7 @@ powerman_pdu_LDADD = $(LDADD) $(LIBPOWERMAN_LIBS) # IPMI PSU nut_ipmipsu_SOURCES = nut-ipmipsu.c if WITH_FREEIPMI - nut_ipmipsu_SOURCES += nut-libfreeipmi.c + nut_ipmipsu_SOURCES += nut-libfreeipmi.c endif nut_ipmipsu_LDADD = $(LDADD) $(LIBIPMI_LIBS) @@ -236,9 +241,11 @@ macosx_ups_SOURCES = macosx-ups.c phoenixcontact_modbus_SOURCES = phoenixcontact_modbus.c phoenixcontact_modbus_LDADD = $(LDADD_DRIVERS) $(LIBMODBUS_LIBS) -# Asem +# Linux I2C drivers asem_LDADD = $(LDADD_DRIVERS) asem_SOURCES = asem.c +pijuice_LDADD = $(LDADD_DRIVERS) +pijuice_SOURCES = pijuice.c # nutdrv_qx USB/Serial nutdrv_qx_SOURCES = nutdrv_qx.c @@ -279,8 +286,8 @@ dist_noinst_HEADERS = apc-mib.h apc-hid.h baytech-mib.h bcmxcp.h \ nutdrv_qx_voltronic.h nutdrv_qx_voltronic-qs.h nutdrv_qx_voltronic-qs-hex.h nutdrv_qx_zinto.h \ xppc-mib.h huawei-mib.h eaton-ats16-mib.h apc-ats-mib.h raritan-px2-mib.h eaton-ats30-mib.h \ apc-pdu-mib.h eaton-pdu-genesis2-mib.h eaton-pdu-marlin-mib.h \ - eaton-pdu-pulizzi-mib.h eaton-pdu-revelation-mib.h - + eaton-pdu-pulizzi-mib.h eaton-pdu-revelation-mib.h emerson-avocent-pdu-mib.h \ + hpe-pdu-mib.h # Define a dummy library so that Automake builds rules for the # corresponding object files. This library is not actually built, diff --git a/drivers/apc-ats-mib.c b/drivers/apc-ats-mib.c index d642a3f52b..3765f79443 100644 --- a/drivers/apc-ats-mib.c +++ b/drivers/apc-ats-mib.c @@ -24,9 +24,10 @@ #include "apc-ats-mib.h" -#define APC_ATS_MIB_VERSION "0.2" +#define APC_ATS_MIB_VERSION "0.4" #define APC_ATS_SYSOID ".1.3.6.1.4.1.318.1.3.11" +#define APC_ATS_OID_MODEL_NAME ".1.3.6.1.4.1.318.1.1.8.1.5.0" static info_lkp_t ats_sensitivity_info[] = { { 1, "high" }, @@ -59,389 +60,389 @@ static info_lkp_t ats_outletgroups_status_info[] = { static snmp_info_t apc_ats_mib[] = { /* Device collection */ - { "device.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "ats", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL }, + { "device.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "ats", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, /* ats2IdentManufacturer.0 = STRING: EATON */ - { "device.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "APC", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL }, + { "device.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "APC", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, /* atsIdentModelNumber.0 = STRING: "AP7724" */ - { "device.model", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.1.5.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "device.model", ST_FLAG_STRING, SU_INFOSIZE, APC_ATS_OID_MODEL_NAME, NULL, SU_FLAG_OK, NULL }, /* FIXME: RFC for device.firmware! */ /* atsIdentHardwareRev.0 = STRING: "R01" */ - { "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.1.1.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.1.1.0", NULL, SU_FLAG_OK, NULL }, /* FIXME: RFC for device.firmware.aux! */ /* atsIdentFirmwareRev.0 = STRING: "3.0.5" */ - { "ups.firmware.aux", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.1.2.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "ups.firmware.aux", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.1.2.0", NULL, SU_FLAG_OK, NULL }, /* atsIdentFirmwareDate.0 = STRING: "09/13/11" */ - /*{ "unmapped.atsIdentFirmwareDate", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.1.3.0", NULL, SU_FLAG_OK, NULL, NULL },*/ + /*{ "unmapped.atsIdentFirmwareDate", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.1.3.0", NULL, SU_FLAG_OK, NULL },*/ /* atsIdentSerialNumber.0 = STRING: "5A1516T15268" */ - { "device.serial", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.1.6.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "device.serial", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.1.6.0", NULL, SU_FLAG_OK, NULL }, /* FIXME: RFC for device.mfr.date! */ /* atsIdentDateOfManufacture.0 = STRING: "04/18/2015" */ - { "ups.mfr.date", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.1.4.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "ups.mfr.date", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.1.4.0", NULL, SU_FLAG_OK, NULL }, /* atsConfigProductName.0 = STRING: "m-ups-04" */ - { "ups.id", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.4.1.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "ups.id", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.4.1.0", NULL, SU_FLAG_OK, NULL }, /* Input collection */ /* atsIdentNominalLineVoltage.0 = INTEGER: 230 */ - { "input.voltage.nominal", 0, 1, ".1.3.6.1.4.1.318.1.1.8.1.7.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "input.voltage.nominal", 0, 1, ".1.3.6.1.4.1.318.1.1.8.1.7.0", NULL, SU_FLAG_OK, NULL }, /* atsIdentNominalLineFrequency.0 = INTEGER: 50 */ - { "input.frequency.nominal", 0, 1, ".1.3.6.1.4.1.318.1.1.8.1.8.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "input.frequency.nominal", 0, 1, ".1.3.6.1.4.1.318.1.1.8.1.8.0", NULL, SU_FLAG_OK, NULL }, /* atsStatusSelectedSource.0 = INTEGER: sourceB(2) */ - { "input.source", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.2.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "input.source", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.2.0", NULL, SU_FLAG_OK, NULL }, /* atsConfigPreferredSource.0 = INTEGER: sourceB(2) */ - { "input.source.preferred", ST_FLAG_RW, 1, ".1.3.6.1.4.1.318.1.1.8.4.2.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "input.source.preferred", ST_FLAG_RW, 1, ".1.3.6.1.4.1.318.1.1.8.4.2.0", NULL, SU_FLAG_OK, NULL }, /* atsInputVoltage.1.1.1 = INTEGER: 216 */ - { "input.1.voltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.3.1.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "input.1.voltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.3.1.1.1", NULL, SU_FLAG_OK, NULL }, /* atsInputVoltage.2.1.1 = INTEGER: 215 */ - { "input.2.voltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.3.2.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "input.2.voltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.3.2.1.1", NULL, SU_FLAG_OK, NULL }, /* atsInputFrequency.1 = INTEGER: 50 */ - { "input.1.frequency", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.4.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "input.1.frequency", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.4.1", NULL, SU_FLAG_OK, NULL }, /* atsInputFrequency.2 = INTEGER: 50 */ - { "input.2.frequency", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.4.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "input.2.frequency", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.4.2", NULL, SU_FLAG_OK, NULL }, /* atsConfigVoltageSensitivity.0 = INTEGER: high(1) */ - { "input.sensitivity", ST_FLAG_RW, 1, ".1.3.6.1.4.1.318.1.1.8.4.4.0", NULL, SU_FLAG_OK, &ats_sensitivity_info[0], NULL }, + { "input.sensitivity", ST_FLAG_RW, 1, ".1.3.6.1.4.1.318.1.1.8.4.4.0", NULL, SU_FLAG_OK, &ats_sensitivity_info[0] }, /* FIXME: RFC for input.count! */ /* atsNumInputs.0 = INTEGER: 2 */ - { "input.count", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.1.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "input.count", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.1.0", NULL, SU_FLAG_OK, NULL }, /* Output collection */ /* atsOutputFrequency.1 = INTEGER: 50 */ - { "output.frequency", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.2.1.4.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "output.frequency", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.2.1.4.1", NULL, SU_FLAG_OK, NULL }, /* atsOutputBankOutputVoltage.1 = INTEGER: 215 */ - { "output.voltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.6.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "output.voltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.6.1", NULL, SU_FLAG_OK, NULL }, /* UPS collection */ /* FIXME: RFC for device.status! */ /* atsStatusVoltageOutStatus.0 = INTEGER: ok(2) */ - { "ups.status", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.15.0", NULL, SU_FLAG_OK, &ats_output_status_info[0], NULL }, + { "ups.status", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.15.0", NULL, SU_FLAG_OK, &ats_output_status_info[0] }, /* Outlet groups collection */ /* Note: prefer the OutputBank data to the ConfigBank ones */ /* atsConfigBankTableSize.0 = INTEGER: 3 */ - /*{ "outlet.group.count", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.13.0", NULL, SU_FLAG_OK, NULL, NULL },*/ + /*{ "outlet.group.count", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.13.0", NULL, SU_FLAG_OK, NULL },*/ /* atsOutputBankTableSize.0 = INTEGER: 3 */ - { "outlet.group.count", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.4.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "outlet.group.count", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.4.0", NULL, SU_FLAG_OK, NULL }, /* atsConfigBankTableIndex.%i = INTEGER: %i */ - /*{ "outlet.group.%i.id", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.4.14.1.1.%i", NULL, SU_FLAG_OK, NULL, NULL },*/ + /*{ "outlet.group.%i.id", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.4.14.1.1.%i", NULL, SU_FLAG_OK, NULL },*/ /* atsOutputBankTableIndex.%i = INTEGER: %i */ - { "outlet.group.%i.id", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.1.%i", NULL, SU_FLAG_OK | SU_OUTLET_GROUP, NULL, NULL }, + { "outlet.group.%i.id", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.1.%i", NULL, SU_FLAG_OK | SU_OUTLET_GROUP, NULL }, /* atsConfigBank.%i = INTEGER: total(1) */ - /*{ "outlet.group.%i.name", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.14.1.2.%i", NULL, SU_FLAG_STATIC | SU_OUTLET_GROUP, &ats_group_name_info[0], NULL },*/ + /*{ "outlet.group.%i.name", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.14.1.2.%i", NULL, SU_FLAG_STATIC | SU_OUTLET_GROUP, &ats_group_name_info[0] },*/ /* atsOutputBank.1 = INTEGER: total(1) */ - { "outlet.group.%i.name", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.3.%i", NULL, SU_FLAG_STATIC | SU_OUTLET_GROUP, &ats_outletgroups_name_info[0], NULL }, + { "outlet.group.%i.name", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.3.%i", NULL, SU_FLAG_STATIC | SU_OUTLET_GROUP, &ats_outletgroups_name_info[0] }, /* atsOutputBankCurrent.%i = Gauge32: 88 */ - { "outlet.group.%i.current", 0, 0.1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.4.%i", NULL, SU_OUTLET_GROUP, NULL, NULL }, + { "outlet.group.%i.current", 0, 0.1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.4.%i", NULL, SU_OUTLET_GROUP, NULL }, /* atsOutputBankState.%i = INTEGER: normal(1) */ - { "outlet.group.%i.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.5.%i", NULL, SU_OUTLET_GROUP, &ats_outletgroups_status_info[0], NULL }, + { "outlet.group.%i.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.5.%i", NULL, SU_OUTLET_GROUP, &ats_outletgroups_status_info[0] }, /* atsOutputBankOutputVoltage.%i = INTEGER: 215 */ - { "outlet.group.%i.voltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.6.%i", NULL, SU_OUTLET_GROUP, NULL, NULL }, + { "outlet.group.%i.voltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.6.%i", NULL, SU_OUTLET_GROUP, NULL }, /* atsOutputBankPower.1 = INTEGER: 1883 */ - { "outlet.group.%i.realpower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.15.%i", NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP, NULL, NULL }, + { "outlet.group.%i.realpower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.15.%i", NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP, NULL }, #if 0 /* FIXME: Remaining data to be processed */ /* atsIdentDeviceRating.0 = INTEGER: 32 */ - { "unmapped.atsIdentDeviceRating", 0, 1, ".1.3.6.1.4.1.318.1.1.8.1.9.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsIdentDeviceRating", 0, 1, ".1.3.6.1.4.1.318.1.1.8.1.9.0", NULL, SU_FLAG_OK, NULL }, /* atsCalibrationNumInputs.0 = INTEGER: 2 */ - { "unmapped.atsCalibrationNumInputs", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.1.1.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsCalibrationNumInputs", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.1.1.0", NULL, SU_FLAG_OK, NULL }, /* atsCalibrationNumInputPhases.0 = INTEGER: 1 */ - { "unmapped.atsCalibrationNumInputPhases", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.1.2.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsCalibrationNumInputPhases", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.1.2.0", NULL, SU_FLAG_OK, NULL }, /* atsCalibrationInputTableIndex.1.1.1 = INTEGER: 1 */ - { "unmapped.atsCalibrationInputTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.1.3.1.1.1.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsCalibrationInputTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.1.3.1.1.1.1.1", NULL, SU_FLAG_OK, NULL }, /* atsCalibrationInputTableIndex.2.1.1 = INTEGER: 2 */ - { "unmapped.atsCalibrationInputTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.1.3.1.1.2.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsCalibrationInputTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.1.3.1.1.2.1.1", NULL, SU_FLAG_OK, NULL }, /* atsCalibrationInputPhaseTableIndex.1.1.1 = INTEGER: 1 */ - { "unmapped.atsCalibrationInputPhaseTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.1.3.1.2.1.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsCalibrationInputPhaseTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.1.3.1.2.1.1.1", NULL, SU_FLAG_OK, NULL }, /* atsCalibrationInputPhaseTableIndex.2.1.1 = INTEGER: 1 */ - { "unmapped.atsCalibrationInputPhaseTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.1.3.1.2.2.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsCalibrationInputPhaseTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.1.3.1.2.2.1.1", NULL, SU_FLAG_OK, NULL }, /* atsLineVoltageCalibrationFactor.1.1.1 = INTEGER: 487 */ - { "unmapped.atsLineVoltageCalibrationFactor", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.1.3.1.3.1.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsLineVoltageCalibrationFactor", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.1.3.1.3.1.1.1", NULL, SU_FLAG_OK, NULL }, /* atsLineVoltageCalibrationFactor.2.1.1 = INTEGER: 488 */ - { "unmapped.atsLineVoltageCalibrationFactor", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.1.3.1.3.2.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsLineVoltageCalibrationFactor", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.1.3.1.3.2.1.1", NULL, SU_FLAG_OK, NULL }, /* atsCalibrationPowerSupplyVoltages.0 = INTEGER: 5 */ - { "unmapped.atsCalibrationPowerSupplyVoltages", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.1.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsCalibrationPowerSupplyVoltages", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.1.0", NULL, SU_FLAG_OK, NULL }, /* atsCalibrationPowerSupplyVoltageTableIndex.1 = INTEGER: 1 */ - { "unmapped.atsCalibrationPowerSupplyVoltageTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsCalibrationPowerSupplyVoltageTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.1.1", NULL, SU_FLAG_OK, NULL }, /* atsCalibrationPowerSupplyVoltageTableIndex.2 = INTEGER: 2 */ - { "unmapped.atsCalibrationPowerSupplyVoltageTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.1.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsCalibrationPowerSupplyVoltageTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.1.2", NULL, SU_FLAG_OK, NULL }, /* atsCalibrationPowerSupplyVoltageTableIndex.3 = INTEGER: 3 */ - { "unmapped.atsCalibrationPowerSupplyVoltageTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.1.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsCalibrationPowerSupplyVoltageTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.1.3", NULL, SU_FLAG_OK, NULL }, /* atsCalibrationPowerSupplyVoltageTableIndex.4 = INTEGER: 4 */ - { "unmapped.atsCalibrationPowerSupplyVoltageTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.1.4", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsCalibrationPowerSupplyVoltageTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.1.4", NULL, SU_FLAG_OK, NULL }, /* atsCalibrationPowerSupplyVoltageTableIndex.5 = INTEGER: 5 */ - { "unmapped.atsCalibrationPowerSupplyVoltageTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.1.5", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsCalibrationPowerSupplyVoltageTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.1.5", NULL, SU_FLAG_OK, NULL }, /* atsCalibrationPowerSupplyVoltage.1 = INTEGER: powerSupply24V(1) */ - { "unmapped.atsCalibrationPowerSupplyVoltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.2.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsCalibrationPowerSupplyVoltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.2.1", NULL, SU_FLAG_OK, NULL }, /* atsCalibrationPowerSupplyVoltage.2 = INTEGER: powerSupply12V(2) */ - { "unmapped.atsCalibrationPowerSupplyVoltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.2.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsCalibrationPowerSupplyVoltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.2.2", NULL, SU_FLAG_OK, NULL }, /* atsCalibrationPowerSupplyVoltage.3 = INTEGER: powerSupply(3) */ - { "unmapped.atsCalibrationPowerSupplyVoltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.2.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsCalibrationPowerSupplyVoltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.2.3", NULL, SU_FLAG_OK, NULL }, /* atsCalibrationPowerSupplyVoltage.4 = INTEGER: powerSupply24VSourceB(4) */ - { "unmapped.atsCalibrationPowerSupplyVoltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.2.4", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsCalibrationPowerSupplyVoltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.2.4", NULL, SU_FLAG_OK, NULL }, /* atsCalibrationPowerSupplyVoltage.5 = INTEGER: powerSupplyMinus12V(5) */ - { "unmapped.atsCalibrationPowerSupplyVoltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.2.5", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsCalibrationPowerSupplyVoltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.2.5", NULL, SU_FLAG_OK, NULL }, /* atsPowerSupplyVoltageCalibrationFactor.1 = INTEGER: 521 */ - { "unmapped.atsPowerSupplyVoltageCalibrationFactor", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.3.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsPowerSupplyVoltageCalibrationFactor", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.3.1", NULL, SU_FLAG_OK, NULL }, /* atsPowerSupplyVoltageCalibrationFactor.2 = INTEGER: 1076 */ - { "unmapped.atsPowerSupplyVoltageCalibrationFactor", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.3.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsPowerSupplyVoltageCalibrationFactor", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.3.2", NULL, SU_FLAG_OK, NULL }, /* atsPowerSupplyVoltageCalibrationFactor.3 = INTEGER: 2560 */ - { "unmapped.atsPowerSupplyVoltageCalibrationFactor", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.3.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsPowerSupplyVoltageCalibrationFactor", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.3.3", NULL, SU_FLAG_OK, NULL }, /* atsPowerSupplyVoltageCalibrationFactor.4 = INTEGER: 521 */ - { "unmapped.atsPowerSupplyVoltageCalibrationFactor", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.3.4", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsPowerSupplyVoltageCalibrationFactor", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.3.4", NULL, SU_FLAG_OK, NULL }, /* atsPowerSupplyVoltageCalibrationFactor.5 = INTEGER: 975 */ - { "unmapped.atsPowerSupplyVoltageCalibrationFactor", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.3.5", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsPowerSupplyVoltageCalibrationFactor", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.2.2.1.3.5", NULL, SU_FLAG_OK, NULL }, /* atsCalibrationNumOutputs.0 = INTEGER: 1 */ - { "unmapped.atsCalibrationNumOutputs", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.3.1.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsCalibrationNumOutputs", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.3.1.0", NULL, SU_FLAG_OK, NULL }, /* atsCalibrationNumOutputPhases.0 = INTEGER: 1 */ - { "unmapped.atsCalibrationNumOutputPhases", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.3.2.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsCalibrationNumOutputPhases", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.3.2.0", NULL, SU_FLAG_OK, NULL }, /* atsCalibrationOutputTableIndex.1.phase1.1 = INTEGER: 1 */ - { "unmapped.atsCalibrationOutputTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.3.3.1.1.1.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsCalibrationOutputTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.3.3.1.1.1.1.1", NULL, SU_FLAG_OK, NULL }, /* atsCalibrationOutputPhasesTableIndex.1.phase1.1 = INTEGER: phase1(1) */ - { "unmapped.atsCalibrationOutputPhasesTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.3.3.1.2.1.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsCalibrationOutputPhasesTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.3.3.1.2.1.1.1", NULL, SU_FLAG_OK, NULL }, /* atsOutputCurrentCalibrationFactor.1.phase1.1 = INTEGER: 487 */ - { "unmapped.atsOutputCurrentCalibrationFactor", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.3.3.1.3.1.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputCurrentCalibrationFactor", 0, 1, ".1.3.6.1.4.1.318.1.1.8.2.3.3.1.3.1.1.1", NULL, SU_FLAG_OK, NULL }, /* atsControlResetATS.0 = INTEGER: none(1) */ - { "unmapped.atsControlResetATS", 0, 1, ".1.3.6.1.4.1.318.1.1.8.3.1.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsControlResetATS", 0, 1, ".1.3.6.1.4.1.318.1.1.8.3.1.0", NULL, SU_FLAG_OK, NULL }, /* atsControlClearAllAlarms.0 = INTEGER: -1 */ - { "unmapped.atsControlClearAllAlarms", 0, 1, ".1.3.6.1.4.1.318.1.1.8.3.2.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsControlClearAllAlarms", 0, 1, ".1.3.6.1.4.1.318.1.1.8.3.2.0", NULL, SU_FLAG_OK, NULL }, /* atsConfigFrontPanelLockout.0 = INTEGER: enableFrontPanel(2) */ - { "unmapped.atsConfigFrontPanelLockout", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.3.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsConfigFrontPanelLockout", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.3.0", NULL, SU_FLAG_OK, NULL }, /* atsConfigTransferVoltageRange.0 = INTEGER: medium(2) */ - { "unmapped.atsConfigTransferVoltageRange", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.5.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsConfigTransferVoltageRange", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.5.0", NULL, SU_FLAG_OK, NULL }, /* atsConfigCurrentLimit.0 = INTEGER: 32 */ - { "unmapped.atsConfigCurrentLimit", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.6.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsConfigCurrentLimit", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.6.0", NULL, SU_FLAG_OK, NULL }, /* atsConfigResetValues.0 = INTEGER: -1 */ - { "unmapped.atsConfigResetValues", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.7.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsConfigResetValues", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.7.0", NULL, SU_FLAG_OK, NULL }, /* atsConfigLineVRMS.0 = INTEGER: 230 */ - { "unmapped.atsConfigLineVRMS", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.8.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsConfigLineVRMS", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.8.0", NULL, SU_FLAG_OK, NULL }, /* atsConfigLineVRMSNarrowLimit.0 = INTEGER: 16 */ - { "unmapped.atsConfigLineVRMSNarrowLimit", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.9.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsConfigLineVRMSNarrowLimit", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.9.0", NULL, SU_FLAG_OK, NULL }, /* atsConfigLineVRMSMediumLimit.0 = INTEGER: 23 */ - { "unmapped.atsConfigLineVRMSMediumLimit", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.10.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsConfigLineVRMSMediumLimit", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.10.0", NULL, SU_FLAG_OK, NULL }, /* atsConfigLineVRMSWideLimit.0 = INTEGER: 30 */ - { "unmapped.atsConfigLineVRMSWideLimit", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.11.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsConfigLineVRMSWideLimit", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.11.0", NULL, SU_FLAG_OK, NULL }, /* atsConfigFrequencyDeviation.0 = INTEGER: two(2) */ - { "unmapped.atsConfigFrequencyDeviation", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.12.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsConfigFrequencyDeviation", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.12.0", NULL, SU_FLAG_OK, NULL }, /* Outlet groups collection */ /* atsConfigBankLowLoadThreshold.1 = INTEGER: 0 */ - { "unmapped.atsConfigBankLowLoadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.14.1.3.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsConfigBankLowLoadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.14.1.3.1", NULL, SU_FLAG_OK, NULL }, /* atsConfigBankLowLoadThreshold.2 = INTEGER: 0 */ - { "unmapped.atsConfigBankLowLoadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.14.1.3.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsConfigBankLowLoadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.14.1.3.2", NULL, SU_FLAG_OK, NULL }, /* atsConfigBankLowLoadThreshold.3 = INTEGER: 0 */ - { "unmapped.atsConfigBankLowLoadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.14.1.3.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsConfigBankLowLoadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.14.1.3.3", NULL, SU_FLAG_OK, NULL }, /* atsConfigBankNearOverLoadThreshold.1 = INTEGER: 28 */ - { "unmapped.atsConfigBankNearOverLoadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.14.1.4.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsConfigBankNearOverLoadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.14.1.4.1", NULL, SU_FLAG_OK, NULL }, /* atsConfigBankNearOverLoadThreshold.2 = INTEGER: 12 */ - { "unmapped.atsConfigBankNearOverLoadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.14.1.4.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsConfigBankNearOverLoadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.14.1.4.2", NULL, SU_FLAG_OK, NULL }, /* atsConfigBankNearOverLoadThreshold.3 = INTEGER: 12 */ - { "unmapped.atsConfigBankNearOverLoadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.14.1.4.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsConfigBankNearOverLoadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.14.1.4.3", NULL, SU_FLAG_OK, NULL }, /* atsConfigBankOverLoadThreshold.1 = INTEGER: 32 */ - { "unmapped.atsConfigBankOverLoadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.14.1.5.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsConfigBankOverLoadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.14.1.5.1", NULL, SU_FLAG_OK, NULL }, /* atsConfigBankOverLoadThreshold.2 = INTEGER: 16 */ - { "unmapped.atsConfigBankOverLoadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.14.1.5.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsConfigBankOverLoadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.14.1.5.2", NULL, SU_FLAG_OK, NULL }, /* atsConfigBankOverLoadThreshold.3 = INTEGER: 16 */ - { "unmapped.atsConfigBankOverLoadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.14.1.5.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsConfigBankOverLoadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.14.1.5.3", NULL, SU_FLAG_OK, NULL }, /* atsConfigPhaseTableSize.0 = INTEGER: 0 */ - { "unmapped.atsConfigPhaseTableSize", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.15.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsConfigPhaseTableSize", 0, 1, ".1.3.6.1.4.1.318.1.1.8.4.15.0", NULL, SU_FLAG_OK, NULL }, /* atsStatusCommStatus.0 = INTEGER: atsCommEstablished(2) */ - { "unmapped.atsStatusCommStatus", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.1.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsStatusCommStatus", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.1.0", NULL, SU_FLAG_OK, NULL }, /* atsStatusRedundancyState.0 = INTEGER: atsFullyRedundant(2) */ - { "unmapped.atsStatusRedundancyState", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.3.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsStatusRedundancyState", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.3.0", NULL, SU_FLAG_OK, NULL }, /* atsStatusOverCurrentState.0 = INTEGER: atsCurrentOK(2) */ - { "unmapped.atsStatusOverCurrentState", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.4.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsStatusOverCurrentState", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.4.0", NULL, SU_FLAG_OK, NULL }, /* atsStatus5VPowerSupply.0 = INTEGER: atsPowerSupplyOK(2) */ - { "unmapped.atsStatus5VPowerSupply", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.5.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsStatus5VPowerSupply", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.5.0", NULL, SU_FLAG_OK, NULL }, /* atsStatus24VPowerSupply.0 = INTEGER: atsPowerSupplyOK(2) */ - { "unmapped.atsStatus24VPowerSupply", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.6.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsStatus24VPowerSupply", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.6.0", NULL, SU_FLAG_OK, NULL }, /* atsStatus24VSourceBPowerSupply.0 = INTEGER: atsPowerSupplyOK(2) */ - { "unmapped.atsStatus24VSourceBPowerSupply", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.7.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsStatus24VSourceBPowerSupply", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.7.0", NULL, SU_FLAG_OK, NULL }, /* atsStatusPlus12VPowerSupply.0 = INTEGER: atsPowerSupplyOK(2) */ - { "unmapped.atsStatusPlus12VPowerSupply", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.8.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsStatusPlus12VPowerSupply", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.8.0", NULL, SU_FLAG_OK, NULL }, /* atsStatusMinus12VPowerSupply.0 = INTEGER: atsPowerSupplyOK(2) */ - { "unmapped.atsStatusMinus12VPowerSupply", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.9.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsStatusMinus12VPowerSupply", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.9.0", NULL, SU_FLAG_OK, NULL }, /* atsStatusSwitchStatus.0 = INTEGER: ok(2) */ - { "unmapped.atsStatusSwitchStatus", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.10.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsStatusSwitchStatus", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.10.0", NULL, SU_FLAG_OK, NULL }, /* atsStatusFrontPanel.0 = INTEGER: unlocked(2) */ - { "unmapped.atsStatusFrontPanel", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.11.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsStatusFrontPanel", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.11.0", NULL, SU_FLAG_OK, NULL }, /* atsStatusSourceAStatus.0 = INTEGER: ok(2) */ - { "unmapped.atsStatusSourceAStatus", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.12.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsStatusSourceAStatus", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.12.0", NULL, SU_FLAG_OK, NULL }, /* atsStatusSourceBStatus.0 = INTEGER: ok(2) */ - { "unmapped.atsStatusSourceBStatus", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.13.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsStatusSourceBStatus", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.13.0", NULL, SU_FLAG_OK, NULL }, /* atsStatusPhaseSyncStatus.0 = INTEGER: inSync(1) */ - { "unmapped.atsStatusPhaseSyncStatus", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.14.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsStatusPhaseSyncStatus", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.14.0", NULL, SU_FLAG_OK, NULL }, /* atsStatusHardwareStatus.0 = INTEGER: ok(2) */ - { "unmapped.atsStatusHardwareStatus", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.16.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsStatusHardwareStatus", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.1.16.0", NULL, SU_FLAG_OK, NULL }, /* atsStatusResetMaxMinValues.0 = INTEGER: -1 */ - { "unmapped.atsStatusResetMaxMinValues", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.2.1.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsStatusResetMaxMinValues", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.2.1.0", NULL, SU_FLAG_OK, NULL }, /* atsInputTableIndex.1 = INTEGER: 1 */ - { "unmapped.atsInputTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsInputTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.1.1", NULL, SU_FLAG_OK, NULL }, /* atsInputTableIndex.2 = INTEGER: 2 */ - { "unmapped.atsInputTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.1.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsInputTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.1.2", NULL, SU_FLAG_OK, NULL }, /* atsNumInputPhases.1 = INTEGER: 1 */ - { "unmapped.atsNumInputPhases", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.2.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsNumInputPhases", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.2.1", NULL, SU_FLAG_OK, NULL }, /* atsNumInputPhases.2 = INTEGER: 1 */ - { "unmapped.atsNumInputPhases", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.2.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsNumInputPhases", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.2.2", NULL, SU_FLAG_OK, NULL }, /* atsInputVoltageOrientation.1 = INTEGER: singlePhase(2) */ - { "unmapped.atsInputVoltageOrientation", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.3.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsInputVoltageOrientation", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.3.1", NULL, SU_FLAG_OK, NULL }, /* atsInputVoltageOrientation.2 = INTEGER: singlePhase(2) */ - { "unmapped.atsInputVoltageOrientation", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.3.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsInputVoltageOrientation", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.3.2", NULL, SU_FLAG_OK, NULL }, /* atsInputType.1 = INTEGER: main(2) */ - { "unmapped.atsInputType", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.5.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsInputType", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.5.1", NULL, SU_FLAG_OK, NULL }, /* atsInputType.2 = INTEGER: main(2) */ - { "unmapped.atsInputType", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.5.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsInputType", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.5.2", NULL, SU_FLAG_OK, NULL }, /* atsInputName.1 = STRING: "Source A" */ - { "unmapped.atsInputName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.6.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsInputName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.6.1", NULL, SU_FLAG_OK, NULL }, /* atsInputName.2 = STRING: "Source B" */ - { "unmapped.atsInputName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.6.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsInputName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.8.5.3.2.1.6.2", NULL, SU_FLAG_OK, NULL }, /* atsInputPhaseTableIndex.1.1.1 = INTEGER: 1 */ - { "unmapped.atsInputPhaseTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.1.1.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsInputPhaseTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.1.1.1.1", NULL, SU_FLAG_OK, NULL }, /* atsInputPhaseTableIndex.2.1.1 = INTEGER: 2 */ - { "unmapped.atsInputPhaseTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.1.2.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsInputPhaseTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.1.2.1.1", NULL, SU_FLAG_OK, NULL }, /* atsInputPhaseIndex.1.1.1 = INTEGER: 1 */ - { "unmapped.atsInputPhaseIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.2.1.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsInputPhaseIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.2.1.1.1", NULL, SU_FLAG_OK, NULL }, /* atsInputPhaseIndex.2.1.1 = INTEGER: 1 */ - { "unmapped.atsInputPhaseIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.2.2.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsInputPhaseIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.2.2.1.1", NULL, SU_FLAG_OK, NULL }, /* atsInputMaxVoltage.1.1.1 = INTEGER: -1 */ - { "unmapped.atsInputMaxVoltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.4.1.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsInputMaxVoltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.4.1.1.1", NULL, SU_FLAG_OK, NULL }, /* atsInputMaxVoltage.2.1.1 = INTEGER: -1 */ - { "unmapped.atsInputMaxVoltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.4.2.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsInputMaxVoltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.4.2.1.1", NULL, SU_FLAG_OK, NULL }, /* atsInputMinVoltage.1.1.1 = INTEGER: -1 */ - { "unmapped.atsInputMinVoltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.5.1.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsInputMinVoltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.5.1.1.1", NULL, SU_FLAG_OK, NULL }, /* atsInputMinVoltage.2.1.1 = INTEGER: -1 */ - { "unmapped.atsInputMinVoltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.5.2.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsInputMinVoltage", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.5.2.1.1", NULL, SU_FLAG_OK, NULL }, /* atsInputCurrent.1.1.1 = INTEGER: -1 */ - { "unmapped.atsInputCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.6.1.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsInputCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.6.1.1.1", NULL, SU_FLAG_OK, NULL }, /* atsInputCurrent.2.1.1 = INTEGER: -1 */ - { "unmapped.atsInputCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.6.2.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsInputCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.6.2.1.1", NULL, SU_FLAG_OK, NULL }, /* atsInputMaxCurrent.1.1.1 = INTEGER: -1 */ - { "unmapped.atsInputMaxCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.7.1.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsInputMaxCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.7.1.1.1", NULL, SU_FLAG_OK, NULL }, /* atsInputMaxCurrent.2.1.1 = INTEGER: -1 */ - { "unmapped.atsInputMaxCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.7.2.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsInputMaxCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.7.2.1.1", NULL, SU_FLAG_OK, NULL }, /* atsInputMinCurrent.1.1.1 = INTEGER: -1 */ - { "unmapped.atsInputMinCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.8.1.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsInputMinCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.8.1.1.1", NULL, SU_FLAG_OK, NULL }, /* atsInputMinCurrent.2.1.1 = INTEGER: -1 */ - { "unmapped.atsInputMinCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.8.2.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsInputMinCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.8.2.1.1", NULL, SU_FLAG_OK, NULL }, /* atsInputPower.1.1.1 = INTEGER: -1 */ - { "unmapped.atsInputPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.9.1.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsInputPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.9.1.1.1", NULL, SU_FLAG_OK, NULL }, /* atsInputPower.2.1.1 = INTEGER: -1 */ - { "unmapped.atsInputPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.9.2.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsInputPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.9.2.1.1", NULL, SU_FLAG_OK, NULL }, /* atsInputMaxPower.1.1.1 = INTEGER: -1 */ - { "unmapped.atsInputMaxPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.10.1.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsInputMaxPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.10.1.1.1", NULL, SU_FLAG_OK, NULL }, /* atsInputMaxPower.2.1.1 = INTEGER: -1 */ - { "unmapped.atsInputMaxPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.10.2.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsInputMaxPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.10.2.1.1", NULL, SU_FLAG_OK, NULL }, /* atsInputMinPower.1.1.1 = INTEGER: -1 */ - { "unmapped.atsInputMinPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.11.1.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsInputMinPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.11.1.1.1", NULL, SU_FLAG_OK, NULL }, /* atsInputMinPower.2.1.1 = INTEGER: -1 */ - { "unmapped.atsInputMinPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.11.2.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsInputMinPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.3.3.1.11.2.1.1", NULL, SU_FLAG_OK, NULL }, /* atsNumOutputs.0 = INTEGER: 1 */ - { "unmapped.atsNumOutputs", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.1.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsNumOutputs", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.1.0", NULL, SU_FLAG_OK, NULL }, /* atsOutputTableIndex.1 = INTEGER: 1 */ - { "unmapped.atsOutputTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.2.1.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputTableIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.2.1.1.1", NULL, SU_FLAG_OK, NULL }, /* atsNumOutputPhases.1 = INTEGER: 1 */ - { "unmapped.atsNumOutputPhases", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.2.1.2.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsNumOutputPhases", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.2.1.2.1", NULL, SU_FLAG_OK, NULL }, /* atsOutputVoltageOrientation.1 = INTEGER: singlePhase(2) */ - { "unmapped.atsOutputVoltageOrientation", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.2.1.3.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputVoltageOrientation", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.2.1.3.1", NULL, SU_FLAG_OK, NULL }, /* atsOutputPhase.1 = INTEGER: phase1(1) */ - { "unmapped.atsOutputPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.2.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.2.1", NULL, SU_FLAG_OK, NULL }, /* atsOutputPhase.2 = INTEGER: phase1(1) */ - { "unmapped.atsOutputPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.2.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.2.2", NULL, SU_FLAG_OK, NULL }, /* atsOutputPhase.3 = INTEGER: phase1(1) */ - { "unmapped.atsOutputPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.2.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.2.3", NULL, SU_FLAG_OK, NULL }, /* atsOutputBankMaxCurrent.1 = INTEGER: -1 */ - { "unmapped.atsOutputBankMaxCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.7.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputBankMaxCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.7.1", NULL, SU_FLAG_OK, NULL }, /* atsOutputBankMaxCurrent.2 = INTEGER: -1 */ - { "unmapped.atsOutputBankMaxCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.7.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputBankMaxCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.7.2", NULL, SU_FLAG_OK, NULL }, /* atsOutputBankMaxCurrent.3 = INTEGER: -1 */ - { "unmapped.atsOutputBankMaxCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.7.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputBankMaxCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.7.3", NULL, SU_FLAG_OK, NULL }, /* atsOutputBankMinCurrent.1 = INTEGER: -1 */ - { "unmapped.atsOutputBankMinCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.8.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputBankMinCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.8.1", NULL, SU_FLAG_OK, NULL }, /* atsOutputBankMinCurrent.2 = INTEGER: -1 */ - { "unmapped.atsOutputBankMinCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.8.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputBankMinCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.8.2", NULL, SU_FLAG_OK, NULL }, /* atsOutputBankMinCurrent.3 = INTEGER: -1 */ - { "unmapped.atsOutputBankMinCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.8.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputBankMinCurrent", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.8.3", NULL, SU_FLAG_OK, NULL }, /* atsOutputBankLoad.1 = INTEGER: 1883 */ - { "unmapped.atsOutputBankLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.9.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputBankLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.9.1", NULL, SU_FLAG_OK, NULL }, /* atsOutputBankLoad.2 = INTEGER: 984 */ - { "unmapped.atsOutputBankLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.9.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputBankLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.9.2", NULL, SU_FLAG_OK, NULL }, /* atsOutputBankLoad.3 = INTEGER: 898 */ - { "unmapped.atsOutputBankLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.9.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputBankLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.9.3", NULL, SU_FLAG_OK, NULL }, /* atsOutputBankMaxLoad.1 = INTEGER: -1 */ - { "unmapped.atsOutputBankMaxLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.10.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputBankMaxLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.10.1", NULL, SU_FLAG_OK, NULL }, /* atsOutputBankMaxLoad.2 = INTEGER: -1 */ - { "unmapped.atsOutputBankMaxLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.10.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputBankMaxLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.10.2", NULL, SU_FLAG_OK, NULL }, /* atsOutputBankMaxLoad.3 = INTEGER: -1 */ - { "unmapped.atsOutputBankMaxLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.10.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputBankMaxLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.10.3", NULL, SU_FLAG_OK, NULL }, /* atsOutputBankMinLoad.1 = INTEGER: -1 */ - { "unmapped.atsOutputBankMinLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.11.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputBankMinLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.11.1", NULL, SU_FLAG_OK, NULL }, /* atsOutputBankMinLoad.2 = INTEGER: -1 */ - { "unmapped.atsOutputBankMinLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.11.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputBankMinLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.11.2", NULL, SU_FLAG_OK, NULL }, /* atsOutputBankMinLoad.3 = INTEGER: -1 */ - { "unmapped.atsOutputBankMinLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.11.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputBankMinLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.11.3", NULL, SU_FLAG_OK, NULL }, /* atsOutputBankPercentLoad.1 = INTEGER: 25 */ - { "unmapped.atsOutputBankPercentLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.12.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputBankPercentLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.12.1", NULL, SU_FLAG_OK, NULL }, /* atsOutputBankPercentLoad.2 = INTEGER: 13 */ - { "unmapped.atsOutputBankPercentLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.12.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputBankPercentLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.12.2", NULL, SU_FLAG_OK, NULL }, /* atsOutputBankPercentLoad.3 = INTEGER: 12 */ - { "unmapped.atsOutputBankPercentLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.12.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputBankPercentLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.12.3", NULL, SU_FLAG_OK, NULL }, /* atsOutputBankMaxPercentLoad.1 = INTEGER: -1 */ - { "unmapped.atsOutputBankMaxPercentLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.13.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputBankMaxPercentLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.13.1", NULL, SU_FLAG_OK, NULL }, /* atsOutputBankMaxPercentLoad.2 = INTEGER: -1 */ - { "unmapped.atsOutputBankMaxPercentLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.13.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputBankMaxPercentLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.13.2", NULL, SU_FLAG_OK, NULL }, /* atsOutputBankMaxPercentLoad.3 = INTEGER: -1 */ - { "unmapped.atsOutputBankMaxPercentLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.13.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputBankMaxPercentLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.13.3", NULL, SU_FLAG_OK, NULL }, /* atsOutputBankMinPercentLoad.1 = INTEGER: -1 */ - { "unmapped.atsOutputBankMinPercentLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.14.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputBankMinPercentLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.14.1", NULL, SU_FLAG_OK, NULL }, /* atsOutputBankMinPercentLoad.2 = INTEGER: -1 */ - { "unmapped.atsOutputBankMinPercentLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.14.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputBankMinPercentLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.14.2", NULL, SU_FLAG_OK, NULL }, /* atsOutputBankMinPercentLoad.3 = INTEGER: -1 */ - { "unmapped.atsOutputBankMinPercentLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.14.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputBankMinPercentLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.14.3", NULL, SU_FLAG_OK, NULL }, /* atsOutputBankMaxPower.1 = INTEGER: -1 */ - { "unmapped.atsOutputBankMaxPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.16.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputBankMaxPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.16.1", NULL, SU_FLAG_OK, NULL }, /* atsOutputBankMaxPower.2 = INTEGER: -1 */ - { "unmapped.atsOutputBankMaxPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.16.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputBankMaxPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.16.2", NULL, SU_FLAG_OK, NULL }, /* atsOutputBankMaxPower.3 = INTEGER: -1 */ - { "unmapped.atsOutputBankMaxPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.16.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputBankMaxPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.16.3", NULL, SU_FLAG_OK, NULL }, /* atsOutputBankMinPower.1 = INTEGER: -1 */ - { "unmapped.atsOutputBankMinPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.17.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputBankMinPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.17.1", NULL, SU_FLAG_OK, NULL }, /* atsOutputBankMinPower.2 = INTEGER: -1 */ - { "unmapped.atsOutputBankMinPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.17.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputBankMinPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.17.2", NULL, SU_FLAG_OK, NULL }, /* atsOutputBankMinPower.3 = INTEGER: -1 */ - { "unmapped.atsOutputBankMinPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.17.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputBankMinPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.17.3", NULL, SU_FLAG_OK, NULL }, /* atsOutputBankPercentPower.1 = INTEGER: 25 */ - { "unmapped.atsOutputBankPercentPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.18.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputBankPercentPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.18.1", NULL, SU_FLAG_OK, NULL }, /* atsOutputBankPercentPower.2 = INTEGER: 13 */ - { "unmapped.atsOutputBankPercentPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.18.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputBankPercentPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.18.2", NULL, SU_FLAG_OK, NULL }, /* atsOutputBankPercentPower.3 = INTEGER: 12 */ - { "unmapped.atsOutputBankPercentPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.18.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputBankPercentPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.18.3", NULL, SU_FLAG_OK, NULL }, /* atsOutputBankMaxPercentPower.1 = INTEGER: -1 */ - { "unmapped.atsOutputBankMaxPercentPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.19.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputBankMaxPercentPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.19.1", NULL, SU_FLAG_OK, NULL }, /* atsOutputBankMaxPercentPower.2 = INTEGER: -1 */ - { "unmapped.atsOutputBankMaxPercentPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.19.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputBankMaxPercentPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.19.2", NULL, SU_FLAG_OK, NULL }, /* atsOutputBankMaxPercentPower.3 = INTEGER: -1 */ - { "unmapped.atsOutputBankMaxPercentPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.19.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputBankMaxPercentPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.19.3", NULL, SU_FLAG_OK, NULL }, /* atsOutputBankMinPercentPower.1 = INTEGER: -1 */ - { "unmapped.atsOutputBankMinPercentPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.20.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputBankMinPercentPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.20.1", NULL, SU_FLAG_OK, NULL }, /* atsOutputBankMinPercentPower.2 = INTEGER: -1 */ - { "unmapped.atsOutputBankMinPercentPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.20.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputBankMinPercentPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.20.2", NULL, SU_FLAG_OK, NULL }, /* atsOutputBankMinPercentPower.3 = INTEGER: -1 */ - { "unmapped.atsOutputBankMinPercentPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.20.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsOutputBankMinPercentPower", 0, 1, ".1.3.6.1.4.1.318.1.1.8.5.4.5.1.20.3", NULL, SU_FLAG_OK, NULL }, #endif /* 0 */ /* end of structure. */ { NULL, 0, 0, NULL, NULL, 0, NULL } }; -mib2nut_info_t apc_ats = { "apc_ats", APC_ATS_MIB_VERSION, NULL, NULL, apc_ats_mib, APC_ATS_SYSOID }; +mib2nut_info_t apc_ats = { "apc_ats", APC_ATS_MIB_VERSION, NULL, APC_ATS_OID_MODEL_NAME, apc_ats_mib, APC_ATS_SYSOID }; diff --git a/drivers/apc-mib.c b/drivers/apc-mib.c index e987c2db2f..83512ae51d 100644 --- a/drivers/apc-mib.c +++ b/drivers/apc-mib.c @@ -26,7 +26,7 @@ #include "apc-mib.h" -#define APCC_MIB_VERSION "1.2" +#define APCC_MIB_VERSION "1.3" /* Other APC sysOID: * @@ -276,21 +276,21 @@ static snmp_info_t apcc_mib[] = { { "ambient.humidity", 0, 1, APCC_OID_IEM_HUMID, "", SU_FLAG_OK, NULL }, /* instant commands. */ - { "load.off", 0, 2, ".1.3.6.1.4.1.318.1.1.1.6.2.1.0", "", SU_TYPE_CMD | SU_FLAG_OK, NULL }, - { "load.on", 0, 2, ".1.3.6.1.4.1.318.1.1.1.6.2.6.0", "", SU_TYPE_CMD | SU_FLAG_OK, NULL }, - { "shutdown.stayoff", 0, 3, ".1.3.6.1.4.1.318.1.1.1.6.2.1.0", "", SU_TYPE_CMD | SU_FLAG_OK, NULL }, + { "load.off", 0, 1, ".1.3.6.1.4.1.318.1.1.1.6.2.1.0", "2", SU_TYPE_CMD | SU_FLAG_OK, NULL }, + { "load.on", 0, 1, ".1.3.6.1.4.1.318.1.1.1.6.2.6.0", "2", SU_TYPE_CMD | SU_FLAG_OK, NULL }, + { "shutdown.stayoff", 0, 1, ".1.3.6.1.4.1.318.1.1.1.6.2.1.0", "3", SU_TYPE_CMD | SU_FLAG_OK, NULL }, /* { CMD_SDRET, 0, APCC_REBOOT_GRACEFUL, APCC_OID_REBOOT, "", SU_TYPE_CMD | SU_FLAG_OK, NULL }, */ - { "shutdown.return", 0, 2, ".1.3.6.1.4.1.318.1.1.1.6.1.1.0", "", SU_TYPE_CMD | SU_FLAG_OK, NULL }, - { "test.failure.start", 0, 2, ".1.3.6.1.4.1.318.1.1.1.6.2.4.0", "", SU_TYPE_CMD | SU_FLAG_OK, NULL }, - { "test.panel.start", 0, 2, ".1.3.6.1.4.1.318.1.1.1.6.2.5.0", "", SU_TYPE_CMD | SU_FLAG_OK, NULL }, - { "bypass.start", 0, 2, ".1.3.6.1.4.1.318.1.1.1.6.2.7.0", "", SU_TYPE_CMD | SU_FLAG_OK, NULL }, - { "bypass.stop", 0, 3, ".1.3.6.1.4.1.318.1.1.1.6.2.7.0", "", SU_TYPE_CMD | SU_FLAG_OK, NULL }, - { "test.battery.start", 0, 2, ".1.3.6.1.4.1.318.1.1.1.7.2.2.0", "", SU_TYPE_CMD | SU_FLAG_OK, NULL }, - { "calibrate.start", 0, 2, ".1.3.6.1.4.1.318.1.1.1.7.2.5.0", "", SU_TYPE_CMD | SU_FLAG_OK, NULL }, - { "calibrate.stop", 0, 3, ".1.3.6.1.4.1.318.1.1.1.7.2.5.0", "", SU_TYPE_CMD | SU_FLAG_OK, NULL }, - { "reset.input.minmax", 0, 2, ".1.3.6.1.4.1.318.1.1.1.9.1.1.0", "", SU_TYPE_CMD | SU_FLAG_OK, NULL }, + { "shutdown.return", 0, 1, ".1.3.6.1.4.1.318.1.1.1.6.1.1.0", "2", SU_TYPE_CMD | SU_FLAG_OK, NULL }, + { "test.failure.start", 0, 1, ".1.3.6.1.4.1.318.1.1.1.6.2.4.0", "2", SU_TYPE_CMD | SU_FLAG_OK, NULL }, + { "test.panel.start", 0, 1, ".1.3.6.1.4.1.318.1.1.1.6.2.5.0", "2", SU_TYPE_CMD | SU_FLAG_OK, NULL }, + { "bypass.start", 0, 1, ".1.3.6.1.4.1.318.1.1.1.6.2.7.0", "2", SU_TYPE_CMD | SU_FLAG_OK, NULL }, + { "bypass.stop", 0, 1, ".1.3.6.1.4.1.318.1.1.1.6.2.7.0", "3", SU_TYPE_CMD | SU_FLAG_OK, NULL }, + { "test.battery.start", 0, 1, ".1.3.6.1.4.1.318.1.1.1.7.2.2.0", "2", SU_TYPE_CMD | SU_FLAG_OK, NULL }, + { "calibrate.start", 0, 1, ".1.3.6.1.4.1.318.1.1.1.7.2.5.0", "2", SU_TYPE_CMD | SU_FLAG_OK, NULL }, + { "calibrate.stop", 0, 1, ".1.3.6.1.4.1.318.1.1.1.7.2.5.0", "3", SU_TYPE_CMD | SU_FLAG_OK, NULL }, + { "reset.input.minmax", 0, 1, ".1.3.6.1.4.1.318.1.1.1.9.1.1.0", "2", SU_TYPE_CMD | SU_FLAG_OK, NULL }, /* end of structure. */ { NULL, 0, 0, NULL, NULL, 0, NULL } diff --git a/drivers/apc-pdu-mib.c b/drivers/apc-pdu-mib.c index cfbbb855e1..dea0caded0 100644 --- a/drivers/apc-pdu-mib.c +++ b/drivers/apc-pdu-mib.c @@ -23,7 +23,7 @@ #include "apc-pdu-mib.h" -#define APC_PDU_MIB_VERSION "0.2" +#define APC_PDU_MIB_VERSION "0.3" #define APC_PDU_MIB_SYSOID_RPDU ".1.3.6.1.4.1.318.1.3.4.4" #define APC_PDU_MIB_SYSOID_RPDU2 ".1.3.6.1.4.1.318.1.3.4.5" @@ -47,923 +47,923 @@ static snmp_info_t apc_pdu_mib[] = { /* Device page */ { "device.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "APC", - SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL }, + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, /* sPDUIdentModelNumber.0 = STRING: "AP7900" */ { "device.model", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.1.4.0", - "Switched ePDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + "Switched ePDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, { "device.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "pdu", - SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL }, + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, { "device.contact", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.2.1.1.4.0", NULL, - SU_FLAG_STALE | SU_FLAG_OK, NULL, NULL }, + SU_FLAG_STALE | SU_FLAG_OK, NULL }, { "device.description", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.2.1.1.5.0", NULL, - SU_FLAG_STALE | SU_FLAG_OK, NULL, NULL }, + SU_FLAG_STALE | SU_FLAG_OK, NULL }, { "device.location", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.2.1.1.6.0", NULL, - SU_FLAG_STALE | SU_FLAG_OK, NULL, NULL }, + SU_FLAG_STALE | SU_FLAG_OK, NULL }, /* FIXME: to be RFC'ed */ - { "device.uptime", 0, 1, ".1.3.6.1.2.1.1.3.0", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL, NULL }, + { "device.uptime", 0, 1, ".1.3.6.1.2.1.1.3.0", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL }, /* sPDUIdentSerialNumber.0 = STRING: "5A1234E00874" */ - { "device.serial", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.1.5.0", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + { "device.serial", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.1.5.0", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL }, /* sPDUIdentModelNumber.0 = STRING: "AP7900" */ - { "device.part", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.1.4.0", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + { "device.part", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.1.4.0", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL }, /* sPDUIdentHardwareRev.0 = STRING: "B2" */ - { "device.version", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.1.1.0", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + { "device.version", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.1.1.0", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL }, /* sPDUIdentFirmwareRev.0 = STRING: "v3.7.3" */ /* FIXME: to be moved to device.firmware */ - { "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.1.2.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.1.2.0", NULL, SU_FLAG_OK, NULL }, /* sPDUIdentDateOfManufacture.0 = STRING: "08/13/2012" */ /* FIXME: to be moved to the device collection! */ - { "ups.date", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.1.3.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "ups.date", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.1.3.0", NULL, SU_FLAG_OK, NULL }, /* Input */ /* rPDUIdentDevicePowerWatts.0 = INTEGER: 0 */ - { "input.realpower", 0, 1, ".1.3.6.1.4.1.318.1.1.12.1.16.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "input.realpower", 0, 1, ".1.3.6.1.4.1.318.1.1.12.1.16.0", NULL, SU_FLAG_OK, NULL }, /* rPDULoadStatusLoad.1 = Gauge32: 0 */ - { "input.current", 0, 0.1, ".1.3.6.1.4.1.318.1.1.12.2.3.1.1.2.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "input.current", 0, 0.1, ".1.3.6.1.4.1.318.1.1.12.2.3.1.1.2.1", NULL, SU_FLAG_OK, NULL }, /* rPDUIdentDeviceLinetoLineVoltage.0 = INTEGER: 120 */ - { "input.voltage.nominal", 0, 1, ".1.3.6.1.4.1.318.1.1.12.1.15.0", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL, NULL }, + { "input.voltage.nominal", 0, 1, ".1.3.6.1.4.1.318.1.1.12.1.15.0", NULL, SU_FLAG_OK | SU_FLAG_NEGINVALID, NULL }, /* Outlets */ - { "outlet.count", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.1.0", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + { "outlet.count", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.1.0", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL }, { "outlet.%i.id", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.1.%i", "%i", - SU_FLAG_STATIC | SU_FLAG_OK | SU_OUTLET, NULL, NULL }, + SU_FLAG_STATIC | SU_FLAG_OK | SU_OUTLET, NULL }, /* sPDUOutletCtlName.%i = STRING: "Testing Name" */ { "outlet.%i.desc", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.4.2.1.4.%i", NULL, - SU_FLAG_STALE | SU_FLAG_OK | SU_OUTLET, NULL, NULL }, + SU_FLAG_STALE | SU_FLAG_OK | SU_OUTLET, NULL }, /* sPDUOutletCtl.1 = INTEGER: outletOn(1) */ { "outlet.%i.status", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.4.2.1.3.%i", NULL, - SU_FLAG_OK | SU_OUTLET, &apc_pdu_sw_outlet_status_info[0], NULL }, + SU_FLAG_OK | SU_OUTLET, &apc_pdu_sw_outlet_status_info[0] }, /* Also use this OID to determine switchability ; its presence means "yes" */ /* sPDUOutletCtl.1 = INTEGER: outletOn(1) */ { "outlet.%i.switchable", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.4.2.1.3.%i", "yes", - SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK | SU_OUTLET, &apc_pdu_sw_outlet_switchability_info[0], NULL }, + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK | SU_OUTLET, &apc_pdu_sw_outlet_switchability_info[0] }, #if 0 /* keep following scan for future development */ /* sPDUMasterControlSwitch.0 = INTEGER: noCommand(6) */ - { "unmapped.sPDUMasterControlSwitch", 0, 1, ".1.3.6.1.4.1.318.1.1.4.2.1.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUMasterControlSwitch", 0, 1, ".1.3.6.1.4.1.318.1.1.4.2.1.0", NULL, SU_FLAG_OK, NULL }, /* sPDUMasterState.0 = STRING: "On On On On On On On On " */ - { "unmapped.sPDUMasterState", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.2.2.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUMasterState", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.2.2.0", NULL, SU_FLAG_OK, NULL }, /* sPDUMasterPending.0 = STRING: "No No No No No No No No " */ - { "unmapped.sPDUMasterPending", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.2.3.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUMasterPending", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.2.3.0", NULL, SU_FLAG_OK, NULL }, /* sPDUMasterConfigPowerOn.0 = INTEGER: 0 */ - { "unmapped.sPDUMasterConfigPowerOn", 0, 1, ".1.3.6.1.4.1.318.1.1.4.3.1.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUMasterConfigPowerOn", 0, 1, ".1.3.6.1.4.1.318.1.1.4.3.1.0", NULL, SU_FLAG_OK, NULL }, /* sPDUMasterConfigReboot.0 = INTEGER: 0 */ - { "unmapped.sPDUMasterConfigReboot", 0, 1, ".1.3.6.1.4.1.318.1.1.4.3.2.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUMasterConfigReboot", 0, 1, ".1.3.6.1.4.1.318.1.1.4.3.2.0", NULL, SU_FLAG_OK, NULL }, /* sPDUMasterConfigPDUName.0 = STRING: "RackPDU" */ - { "unmapped.sPDUMasterConfigPDUName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.3.3.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUMasterConfigPDUName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.3.3.0", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletControlTableSize.0 = INTEGER: 8 */ /* sPDUOutletControlIndex.1 = INTEGER: 1 */ - { "unmapped.sPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.1.1", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletControlIndex.2 = INTEGER: 2 */ - { "unmapped.sPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.1.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.1.2", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletControlIndex.3 = INTEGER: 3 */ - { "unmapped.sPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.1.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.1.3", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletControlIndex.4 = INTEGER: 4 */ - { "unmapped.sPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.1.4", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.1.4", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletControlIndex.5 = INTEGER: 5 */ - { "unmapped.sPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.1.5", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.1.5", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletControlIndex.6 = INTEGER: 6 */ - { "unmapped.sPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.1.6", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.1.6", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletControlIndex.7 = INTEGER: 7 */ - { "unmapped.sPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.1.7", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.1.7", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletControlIndex.8 = INTEGER: 8 */ - { "unmapped.sPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.1.8", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.1.8", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletPending.1 = INTEGER: noCommandPending(2) */ - { "unmapped.sPDUOutletPending", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.2.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletPending", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.2.1", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletPending.2 = INTEGER: noCommandPending(2) */ - { "unmapped.sPDUOutletPending", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.2.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletPending", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.2.2", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletPending.3 = INTEGER: noCommandPending(2) */ - { "unmapped.sPDUOutletPending", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.2.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletPending", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.2.3", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletPending.4 = INTEGER: noCommandPending(2) */ - { "unmapped.sPDUOutletPending", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.2.4", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletPending", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.2.4", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletPending.5 = INTEGER: noCommandPending(2) */ - { "unmapped.sPDUOutletPending", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.2.5", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletPending", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.2.5", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletPending.6 = INTEGER: noCommandPending(2) */ - { "unmapped.sPDUOutletPending", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.2.6", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletPending", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.2.6", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletPending.7 = INTEGER: noCommandPending(2) */ - { "unmapped.sPDUOutletPending", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.2.7", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletPending", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.2.7", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletPending.8 = INTEGER: noCommandPending(2) */ - { "unmapped.sPDUOutletPending", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.2.8", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletPending", 0, 1, ".1.3.6.1.4.1.318.1.1.4.4.2.1.2.8", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletConfigTableSize.0 = INTEGER: 8 */ - { "unmapped.sPDUOutletConfigTableSize", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.1.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletConfigTableSize", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.1.0", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletConfigIndex.1 = INTEGER: 1 */ - { "unmapped.sPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.1.1", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletConfigIndex.2 = INTEGER: 2 */ - { "unmapped.sPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.1.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.1.2", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletConfigIndex.3 = INTEGER: 3 */ - { "unmapped.sPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.1.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.1.3", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletConfigIndex.4 = INTEGER: 4 */ - { "unmapped.sPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.1.4", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.1.4", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletConfigIndex.5 = INTEGER: 5 */ - { "unmapped.sPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.1.5", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.1.5", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletConfigIndex.6 = INTEGER: 6 */ - { "unmapped.sPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.1.6", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.1.6", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletConfigIndex.7 = INTEGER: 7 */ - { "unmapped.sPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.1.7", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.1.7", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletConfigIndex.8 = INTEGER: 8 */ - { "unmapped.sPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.1.8", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.1.8", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletPowerOnTime.1 = INTEGER: 0 */ - { "unmapped.sPDUOutletPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.2.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.2.1", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletPowerOnTime.2 = INTEGER: 0 */ - { "unmapped.sPDUOutletPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.2.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.2.2", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletPowerOnTime.3 = INTEGER: 0 */ - { "unmapped.sPDUOutletPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.2.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.2.3", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletPowerOnTime.4 = INTEGER: 0 */ - { "unmapped.sPDUOutletPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.2.4", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.2.4", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletPowerOnTime.5 = INTEGER: 0 */ - { "unmapped.sPDUOutletPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.2.5", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.2.5", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletPowerOnTime.6 = INTEGER: 0 */ - { "unmapped.sPDUOutletPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.2.6", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.2.6", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletPowerOnTime.7 = INTEGER: 0 */ - { "unmapped.sPDUOutletPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.2.7", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.2.7", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletPowerOnTime.8 = INTEGER: 0 */ - { "unmapped.sPDUOutletPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.2.8", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.2.8", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletName.1 = STRING: "Testing Name" */ - { "unmapped.sPDUOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.5.2.1.3.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.5.2.1.3.1", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletName.2 = STRING: "Testing 2" */ - { "unmapped.sPDUOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.5.2.1.3.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.5.2.1.3.2", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletName.3 = STRING: "Outlet 3" */ - { "unmapped.sPDUOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.5.2.1.3.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.5.2.1.3.3", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletName.4 = STRING: "Outlet 4" */ - { "unmapped.sPDUOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.5.2.1.3.4", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.5.2.1.3.4", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletName.5 = STRING: "Outlet 5" */ - { "unmapped.sPDUOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.5.2.1.3.5", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.5.2.1.3.5", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletName.6 = STRING: "Outlet 6" */ - { "unmapped.sPDUOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.5.2.1.3.6", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.5.2.1.3.6", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletName.7 = STRING: "Outlet 7" */ - { "unmapped.sPDUOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.5.2.1.3.7", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.5.2.1.3.7", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletName.8 = STRING: "Outlet 8" */ - { "unmapped.sPDUOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.5.2.1.3.8", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.4.5.2.1.3.8", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletPowerOffTime.1 = INTEGER: 0 */ - { "unmapped.sPDUOutletPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.4.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.4.1", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletPowerOffTime.2 = INTEGER: 0 */ - { "unmapped.sPDUOutletPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.4.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.4.2", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletPowerOffTime.3 = INTEGER: 0 */ - { "unmapped.sPDUOutletPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.4.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.4.3", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletPowerOffTime.4 = INTEGER: 0 */ - { "unmapped.sPDUOutletPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.4.4", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.4.4", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletPowerOffTime.5 = INTEGER: 0 */ - { "unmapped.sPDUOutletPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.4.5", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.4.5", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletPowerOffTime.6 = INTEGER: 0 */ - { "unmapped.sPDUOutletPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.4.6", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.4.6", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletPowerOffTime.7 = INTEGER: 0 */ - { "unmapped.sPDUOutletPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.4.7", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.4.7", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletPowerOffTime.8 = INTEGER: 0 */ - { "unmapped.sPDUOutletPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.4.8", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.4.8", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletRebootDuration.1 = INTEGER: 5 */ - { "unmapped.sPDUOutletRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.5.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.5.1", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletRebootDuration.2 = INTEGER: 5 */ - { "unmapped.sPDUOutletRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.5.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.5.2", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletRebootDuration.3 = INTEGER: 5 */ - { "unmapped.sPDUOutletRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.5.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.5.3", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletRebootDuration.4 = INTEGER: 5 */ - { "unmapped.sPDUOutletRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.5.4", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.5.4", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletRebootDuration.5 = INTEGER: 5 */ - { "unmapped.sPDUOutletRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.5.5", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.5.5", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletRebootDuration.6 = INTEGER: 5 */ - { "unmapped.sPDUOutletRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.5.6", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.5.6", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletRebootDuration.7 = INTEGER: 5 */ - { "unmapped.sPDUOutletRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.5.7", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.5.7", NULL, SU_FLAG_OK, NULL }, /* sPDUOutletRebootDuration.8 = INTEGER: 5 */ - { "unmapped.sPDUOutletRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.5.8", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.sPDUOutletRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.4.5.2.1.5.8", NULL, SU_FLAG_OK, NULL }, /* rPDUIdentName.0 = STRING: "RackPDU" */ - { "unmapped.rPDUIdentName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.1.1.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUIdentName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.1.1.0", NULL, SU_FLAG_OK, NULL }, /* rPDUIdentHardwareRev.0 = STRING: "B2" */ - { "unmapped.rPDUIdentHardwareRev", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.1.2.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUIdentHardwareRev", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.1.2.0", NULL, SU_FLAG_OK, NULL }, /* rPDUIdentFirmwareRev.0 = STRING: "v3.7.3" */ - { "unmapped.rPDUIdentFirmwareRev", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.1.3.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUIdentFirmwareRev", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.1.3.0", NULL, SU_FLAG_OK, NULL }, /* rPDUIdentDateOfManufacture.0 = STRING: "08/13/2012" */ - { "unmapped.rPDUIdentDateOfManufacture", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.1.4.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUIdentDateOfManufacture", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.1.4.0", NULL, SU_FLAG_OK, NULL }, /* rPDUIdentModelNumber.0 = STRING: "AP7900" */ - { "unmapped.rPDUIdentModelNumber", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.1.5.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUIdentModelNumber", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.1.5.0", NULL, SU_FLAG_OK, NULL }, /* rPDUIdentSerialNumber.0 = STRING: "5A1234E00874" */ - { "unmapped.rPDUIdentSerialNumber", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.1.6.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUIdentSerialNumber", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.1.6.0", NULL, SU_FLAG_OK, NULL }, /* rPDUIdentDeviceRating.0 = INTEGER: 12 */ - { "unmapped.rPDUIdentDeviceRating", 0, 1, ".1.3.6.1.4.1.318.1.1.12.1.7.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUIdentDeviceRating", 0, 1, ".1.3.6.1.4.1.318.1.1.12.1.7.0", NULL, SU_FLAG_OK, NULL }, /* rPDUIdentDeviceNumOutlets.0 = INTEGER: 8 */ - { "unmapped.rPDUIdentDeviceNumOutlets", 0, 1, ".1.3.6.1.4.1.318.1.1.12.1.8.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUIdentDeviceNumOutlets", 0, 1, ".1.3.6.1.4.1.318.1.1.12.1.8.0", NULL, SU_FLAG_OK, NULL }, /* rPDUIdentDeviceNumPhases.0 = INTEGER: 1 */ - { "input.phases", 0, 1, ".1.3.6.1.4.1.318.1.1.12.1.9.0", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + { "input.phases", 0, 1, ".1.3.6.1.4.1.318.1.1.12.1.9.0", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL }, /* rPDUIdentDeviceNumBreakers.0 = INTEGER: 0 */ - { "unmapped.rPDUIdentDeviceNumBreakers", 0, 1, ".1.3.6.1.4.1.318.1.1.12.1.10.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUIdentDeviceNumBreakers", 0, 1, ".1.3.6.1.4.1.318.1.1.12.1.10.0", NULL, SU_FLAG_OK, NULL }, /* rPDUIdentDeviceBreakerRating.0 = INTEGER: 0 */ - { "unmapped.rPDUIdentDeviceBreakerRating", 0, 1, ".1.3.6.1.4.1.318.1.1.12.1.11.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUIdentDeviceBreakerRating", 0, 1, ".1.3.6.1.4.1.318.1.1.12.1.11.0", NULL, SU_FLAG_OK, NULL }, /* rPDUIdentDeviceOrientation.0 = INTEGER: orientHorizontal(1) */ - { "unmapped.rPDUIdentDeviceOrientation", 0, 1, ".1.3.6.1.4.1.318.1.1.12.1.12.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUIdentDeviceOrientation", 0, 1, ".1.3.6.1.4.1.318.1.1.12.1.12.0", NULL, SU_FLAG_OK, NULL }, /* rPDUIdentDeviceOutletLayout.0 = INTEGER: seqPhaseToNeutral(1) */ - { "unmapped.rPDUIdentDeviceOutletLayout", 0, 1, ".1.3.6.1.4.1.318.1.1.12.1.13.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUIdentDeviceOutletLayout", 0, 1, ".1.3.6.1.4.1.318.1.1.12.1.13.0", NULL, SU_FLAG_OK, NULL }, /* rPDUIdentDeviceDisplayOrientation.0 = INTEGER: displayNormal(1) */ - { "unmapped.rPDUIdentDeviceDisplayOrientation", 0, 1, ".1.3.6.1.4.1.318.1.1.12.1.14.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUIdentDeviceDisplayOrientation", 0, 1, ".1.3.6.1.4.1.318.1.1.12.1.14.0", NULL, SU_FLAG_OK, NULL }, /* rPDUIdentDeviceLinetoLineVoltage.0 = INTEGER: 120 */ - { "unmapped.rPDUIdentDeviceLinetoLineVoltage", 0, 1, ".1.3.6.1.4.1.318.1.1.12.1.15.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUIdentDeviceLinetoLineVoltage", 0, 1, ".1.3.6.1.4.1.318.1.1.12.1.15.0", NULL, SU_FLAG_OK, NULL }, /* rPDUIdentDevicePowerFactor.0 = INTEGER: 1000 */ - { "unmapped.rPDUIdentDevicePowerFactor", 0, 1, ".1.3.6.1.4.1.318.1.1.12.1.17.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUIdentDevicePowerFactor", 0, 1, ".1.3.6.1.4.1.318.1.1.12.1.17.0", NULL, SU_FLAG_OK, NULL }, /* rPDUIdentDevicePowerVA.0 = INTEGER: 0 */ - { "unmapped.rPDUIdentDevicePowerVA", 0, 1, ".1.3.6.1.4.1.318.1.1.12.1.18.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUIdentDevicePowerVA", 0, 1, ".1.3.6.1.4.1.318.1.1.12.1.18.0", NULL, SU_FLAG_OK, NULL }, /* rPDULoadDevMaxPhaseLoad.0 = INTEGER: 12 */ - { "unmapped.rPDULoadDevMaxPhaseLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.1.1.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDULoadDevMaxPhaseLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.1.1.0", NULL, SU_FLAG_OK, NULL }, /* rPDULoadDevNumPhases.0 = INTEGER: 1 */ - { "unmapped.rPDULoadDevNumPhases", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.1.2.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDULoadDevNumPhases", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.1.2.0", NULL, SU_FLAG_OK, NULL }, /* rPDULoadDevMaxBankLoad.0 = INTEGER: 0 */ - { "unmapped.rPDULoadDevMaxBankLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.1.3.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDULoadDevMaxBankLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.1.3.0", NULL, SU_FLAG_OK, NULL }, /* rPDULoadDevNumBanks.0 = INTEGER: 0 */ - { "unmapped.rPDULoadDevNumBanks", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.1.4.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDULoadDevNumBanks", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.1.4.0", NULL, SU_FLAG_OK, NULL }, /* rPDULoadDevBankTableSize.0 = INTEGER: 0 */ - { "unmapped.rPDULoadDevBankTableSize", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.1.5.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDULoadDevBankTableSize", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.1.5.0", NULL, SU_FLAG_OK, NULL }, /* rPDULoadDevMaxOutletTableSize.0 = INTEGER: 0 */ - { "unmapped.rPDULoadDevMaxOutletTableSize", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.1.7.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDULoadDevMaxOutletTableSize", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.1.7.0", NULL, SU_FLAG_OK, NULL }, /* rPDULoadPhaseConfigIndex.phase1 = INTEGER: phase1(1) */ - { "unmapped.rPDULoadPhaseConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.2.1.1.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDULoadPhaseConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.2.1.1.1.1", NULL, SU_FLAG_OK, NULL }, /* rPDULoadPhaseConfigLowLoadThreshold.phase1 = INTEGER: 0 */ - { "unmapped.rPDULoadPhaseConfigLowLoadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.2.1.1.2.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDULoadPhaseConfigLowLoadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.2.1.1.2.1", NULL, SU_FLAG_OK, NULL }, /* rPDULoadPhaseConfigNearOverloadThreshold.phase1 = INTEGER: 8 */ - { "unmapped.rPDULoadPhaseConfigNearOverloadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.2.1.1.3.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDULoadPhaseConfigNearOverloadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.2.1.1.3.1", NULL, SU_FLAG_OK, NULL }, /* rPDULoadPhaseConfigOverloadThreshold.phase1 = INTEGER: 12 */ - { "unmapped.rPDULoadPhaseConfigOverloadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.2.1.1.4.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDULoadPhaseConfigOverloadThreshold", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.2.1.1.4.1", NULL, SU_FLAG_OK, NULL }, /* rPDULoadPhaseConfigAlarm.phase1 = INTEGER: noLoadAlarm(1) */ - { "unmapped.rPDULoadPhaseConfigAlarm", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.2.1.1.5.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDULoadPhaseConfigAlarm", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.2.1.1.5.1", NULL, SU_FLAG_OK, NULL }, /* rPDULoadStatusIndex.1 = INTEGER: 1 */ - { "unmapped.rPDULoadStatusIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.3.1.1.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDULoadStatusIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.3.1.1.1.1", NULL, SU_FLAG_OK, NULL }, /* rPDULoadStatusLoadState.1 = INTEGER: phaseLoadNormal(1) */ - { "unmapped.rPDULoadStatusLoadState", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.3.1.1.3.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDULoadStatusLoadState", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.3.1.1.3.1", NULL, SU_FLAG_OK, NULL }, /* rPDULoadStatusPhaseNumber.1 = INTEGER: 1 */ - { "unmapped.rPDULoadStatusPhaseNumber", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.3.1.1.4.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDULoadStatusPhaseNumber", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.3.1.1.4.1", NULL, SU_FLAG_OK, NULL }, /* rPDULoadStatusBankNumber.1 = INTEGER: 0 */ - { "unmapped.rPDULoadStatusBankNumber", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.3.1.1.5.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDULoadStatusBankNumber", 0, 1, ".1.3.6.1.4.1.318.1.1.12.2.3.1.1.5.1", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletDevCommand.0 = INTEGER: noCommandAll(1) */ - { "unmapped.rPDUOutletDevCommand", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.1.1.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletDevCommand", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.1.1.0", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletDevColdstartDelay.0 = INTEGER: 0 */ - { "unmapped.rPDUOutletDevColdstartDelay", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.1.2.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletDevColdstartDelay", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.1.2.0", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletDevNumCntrlOutlets.0 = INTEGER: 8 */ - { "unmapped.rPDUOutletDevNumCntrlOutlets", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.1.3.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletDevNumCntrlOutlets", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.1.3.0", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletDevNumTotalOutlets.0 = INTEGER: 8 */ - { "unmapped.rPDUOutletDevNumTotalOutlets", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.1.4.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletDevNumTotalOutlets", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.1.4.0", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletDevMonitoredOutlets.0 = INTEGER: 0 */ - { "unmapped.rPDUOutletDevMonitoredOutlets", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.1.5.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletDevMonitoredOutlets", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.1.5.0", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletPhaseIndex.phase1 = INTEGER: phase1(1) */ - { "unmapped.rPDUOutletPhaseIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.2.1.1.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletPhaseIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.2.1.1.1.1", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletPhaseOverloadRestriction.phase1 = INTEGER: alwaysAllowTurnON(1) */ - { "unmapped.rPDUOutletPhaseOverloadRestriction", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.2.1.1.2.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletPhaseOverloadRestriction", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.2.1.1.2.1", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletControlIndex.1 = INTEGER: 1 */ - { "unmapped.rPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.1.1", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletControlIndex.2 = INTEGER: 2 */ - { "unmapped.rPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.1.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.1.2", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletControlIndex.3 = INTEGER: 3 */ - { "unmapped.rPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.1.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.1.3", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletControlIndex.4 = INTEGER: 4 */ - { "unmapped.rPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.1.4", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.1.4", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletControlIndex.5 = INTEGER: 5 */ - { "unmapped.rPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.1.5", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.1.5", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletControlIndex.6 = INTEGER: 6 */ - { "unmapped.rPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.1.6", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.1.6", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletControlIndex.7 = INTEGER: 7 */ - { "unmapped.rPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.1.7", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.1.7", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletControlIndex.8 = INTEGER: 8 */ - { "unmapped.rPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.1.8", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletControlIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.1.8", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletControlOutletName.1 = STRING: "Testing Name" */ - { "unmapped.rPDUOutletControlOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.2.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletControlOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.2.1", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletControlOutletName.2 = STRING: "Testing 2" */ - { "unmapped.rPDUOutletControlOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.2.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletControlOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.2.2", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletControlOutletName.3 = STRING: "Outlet 3" */ - { "unmapped.rPDUOutletControlOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.2.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletControlOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.2.3", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletControlOutletName.4 = STRING: "Outlet 4" */ - { "unmapped.rPDUOutletControlOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.2.4", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletControlOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.2.4", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletControlOutletName.5 = STRING: "Outlet 5" */ - { "unmapped.rPDUOutletControlOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.2.5", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletControlOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.2.5", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletControlOutletName.6 = STRING: "Outlet 6" */ - { "unmapped.rPDUOutletControlOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.2.6", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletControlOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.2.6", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletControlOutletName.7 = STRING: "Outlet 7" */ - { "unmapped.rPDUOutletControlOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.2.7", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletControlOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.2.7", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletControlOutletName.8 = STRING: "Outlet 8" */ - { "unmapped.rPDUOutletControlOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.2.8", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletControlOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.2.8", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletControlOutletPhase.1 = INTEGER: phase1(1) */ - { "unmapped.rPDUOutletControlOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.3.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletControlOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.3.1", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletControlOutletPhase.2 = INTEGER: phase1(1) */ - { "unmapped.rPDUOutletControlOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.3.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletControlOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.3.2", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletControlOutletPhase.3 = INTEGER: phase1(1) */ - { "unmapped.rPDUOutletControlOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.3.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletControlOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.3.3", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletControlOutletPhase.4 = INTEGER: phase1(1) */ - { "unmapped.rPDUOutletControlOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.3.4", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletControlOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.3.4", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletControlOutletPhase.5 = INTEGER: phase1(1) */ - { "unmapped.rPDUOutletControlOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.3.5", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletControlOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.3.5", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletControlOutletPhase.6 = INTEGER: phase1(1) */ - { "unmapped.rPDUOutletControlOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.3.6", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletControlOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.3.6", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletControlOutletPhase.7 = INTEGER: phase1(1) */ - { "unmapped.rPDUOutletControlOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.3.7", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletControlOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.3.7", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletControlOutletPhase.8 = INTEGER: phase1(1) */ - { "unmapped.rPDUOutletControlOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.3.8", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletControlOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.3.8", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletControlOutletCommand.1 = INTEGER: immediateOn(1) */ - { "unmapped.rPDUOutletControlOutletCommand", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.4.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletControlOutletCommand", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.4.1", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletControlOutletCommand.2 = INTEGER: immediateOn(1) */ - { "unmapped.rPDUOutletControlOutletCommand", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.4.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletControlOutletCommand", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.4.2", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletControlOutletCommand.3 = INTEGER: immediateOn(1) */ - { "unmapped.rPDUOutletControlOutletCommand", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.4.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletControlOutletCommand", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.4.3", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletControlOutletCommand.4 = INTEGER: immediateOn(1) */ - { "unmapped.rPDUOutletControlOutletCommand", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.4.4", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletControlOutletCommand", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.4.4", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletControlOutletCommand.5 = INTEGER: immediateOn(1) */ - { "unmapped.rPDUOutletControlOutletCommand", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.4.5", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletControlOutletCommand", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.4.5", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletControlOutletCommand.6 = INTEGER: immediateOn(1) */ - { "unmapped.rPDUOutletControlOutletCommand", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.4.6", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletControlOutletCommand", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.4.6", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletControlOutletCommand.7 = INTEGER: immediateOn(1) */ - { "unmapped.rPDUOutletControlOutletCommand", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.4.7", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletControlOutletCommand", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.4.7", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletControlOutletCommand.8 = INTEGER: immediateOn(1) */ - { "unmapped.rPDUOutletControlOutletCommand", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.4.8", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletControlOutletCommand", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.4.8", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletControlOutletBank.1 = INTEGER: 0 */ - { "unmapped.rPDUOutletControlOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.5.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletControlOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.5.1", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletControlOutletBank.2 = INTEGER: 0 */ - { "unmapped.rPDUOutletControlOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.5.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletControlOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.5.2", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletControlOutletBank.3 = INTEGER: 0 */ - { "unmapped.rPDUOutletControlOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.5.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletControlOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.5.3", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletControlOutletBank.4 = INTEGER: 0 */ - { "unmapped.rPDUOutletControlOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.5.4", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletControlOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.5.4", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletControlOutletBank.5 = INTEGER: 0 */ - { "unmapped.rPDUOutletControlOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.5.5", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletControlOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.5.5", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletControlOutletBank.6 = INTEGER: 0 */ - { "unmapped.rPDUOutletControlOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.5.6", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletControlOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.5.6", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletControlOutletBank.7 = INTEGER: 0 */ - { "unmapped.rPDUOutletControlOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.5.7", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletControlOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.5.7", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletControlOutletBank.8 = INTEGER: 0 */ - { "unmapped.rPDUOutletControlOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.5.8", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletControlOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.3.1.1.5.8", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigIndex.1 = INTEGER: 1 */ - { "unmapped.rPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.1.1", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigIndex.2 = INTEGER: 2 */ - { "unmapped.rPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.1.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.1.2", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigIndex.3 = INTEGER: 3 */ - { "unmapped.rPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.1.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.1.3", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigIndex.4 = INTEGER: 4 */ - { "unmapped.rPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.1.4", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.1.4", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigIndex.5 = INTEGER: 5 */ - { "unmapped.rPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.1.5", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.1.5", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigIndex.6 = INTEGER: 6 */ - { "unmapped.rPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.1.6", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.1.6", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigIndex.7 = INTEGER: 7 */ - { "unmapped.rPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.1.7", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.1.7", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigIndex.8 = INTEGER: 8 */ - { "unmapped.rPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.1.8", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.1.8", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigOutletName.1 = STRING: "Testing Name" */ - { "unmapped.rPDUOutletConfigOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.2.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.2.1", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigOutletName.2 = STRING: "Testing 2" */ - { "unmapped.rPDUOutletConfigOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.2.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.2.2", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigOutletName.3 = STRING: "Outlet 3" */ - { "unmapped.rPDUOutletConfigOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.2.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.2.3", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigOutletName.4 = STRING: "Outlet 4" */ - { "unmapped.rPDUOutletConfigOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.2.4", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.2.4", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigOutletName.5 = STRING: "Outlet 5" */ - { "unmapped.rPDUOutletConfigOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.2.5", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.2.5", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigOutletName.6 = STRING: "Outlet 6" */ - { "unmapped.rPDUOutletConfigOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.2.6", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.2.6", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigOutletName.7 = STRING: "Outlet 7" */ - { "unmapped.rPDUOutletConfigOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.2.7", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.2.7", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigOutletName.8 = STRING: "Outlet 8" */ - { "unmapped.rPDUOutletConfigOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.2.8", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.2.8", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigOutletPhase.1 = INTEGER: phase1(1) */ - { "unmapped.rPDUOutletConfigOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.3.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.3.1", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigOutletPhase.2 = INTEGER: phase1(1) */ - { "unmapped.rPDUOutletConfigOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.3.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.3.2", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigOutletPhase.3 = INTEGER: phase1(1) */ - { "unmapped.rPDUOutletConfigOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.3.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.3.3", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigOutletPhase.4 = INTEGER: phase1(1) */ - { "unmapped.rPDUOutletConfigOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.3.4", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.3.4", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigOutletPhase.5 = INTEGER: phase1(1) */ - { "unmapped.rPDUOutletConfigOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.3.5", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.3.5", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigOutletPhase.6 = INTEGER: phase1(1) */ - { "unmapped.rPDUOutletConfigOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.3.6", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.3.6", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigOutletPhase.7 = INTEGER: phase1(1) */ - { "unmapped.rPDUOutletConfigOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.3.7", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.3.7", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigOutletPhase.8 = INTEGER: phase1(1) */ - { "unmapped.rPDUOutletConfigOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.3.8", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.3.8", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigPowerOnTime.1 = INTEGER: 0 */ - { "unmapped.rPDUOutletConfigPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.4.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.4.1", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigPowerOnTime.2 = INTEGER: 0 */ - { "unmapped.rPDUOutletConfigPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.4.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.4.2", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigPowerOnTime.3 = INTEGER: 0 */ - { "unmapped.rPDUOutletConfigPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.4.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.4.3", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigPowerOnTime.4 = INTEGER: 0 */ - { "unmapped.rPDUOutletConfigPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.4.4", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.4.4", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigPowerOnTime.5 = INTEGER: 0 */ - { "unmapped.rPDUOutletConfigPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.4.5", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.4.5", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigPowerOnTime.6 = INTEGER: 0 */ - { "unmapped.rPDUOutletConfigPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.4.6", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.4.6", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigPowerOnTime.7 = INTEGER: 0 */ - { "unmapped.rPDUOutletConfigPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.4.7", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.4.7", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigPowerOnTime.8 = INTEGER: 0 */ - { "unmapped.rPDUOutletConfigPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.4.8", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigPowerOnTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.4.8", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigPowerOffTime.1 = INTEGER: 0 */ - { "unmapped.rPDUOutletConfigPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.5.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.5.1", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigPowerOffTime.2 = INTEGER: 0 */ - { "unmapped.rPDUOutletConfigPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.5.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.5.2", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigPowerOffTime.3 = INTEGER: 0 */ - { "unmapped.rPDUOutletConfigPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.5.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.5.3", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigPowerOffTime.4 = INTEGER: 0 */ - { "unmapped.rPDUOutletConfigPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.5.4", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.5.4", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigPowerOffTime.5 = INTEGER: 0 */ - { "unmapped.rPDUOutletConfigPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.5.5", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.5.5", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigPowerOffTime.6 = INTEGER: 0 */ - { "unmapped.rPDUOutletConfigPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.5.6", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.5.6", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigPowerOffTime.7 = INTEGER: 0 */ - { "unmapped.rPDUOutletConfigPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.5.7", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.5.7", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigPowerOffTime.8 = INTEGER: 0 */ - { "unmapped.rPDUOutletConfigPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.5.8", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigPowerOffTime", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.5.8", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigRebootDuration.1 = INTEGER: 5 */ - { "unmapped.rPDUOutletConfigRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.6.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.6.1", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigRebootDuration.2 = INTEGER: 5 */ - { "unmapped.rPDUOutletConfigRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.6.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.6.2", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigRebootDuration.3 = INTEGER: 5 */ - { "unmapped.rPDUOutletConfigRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.6.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.6.3", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigRebootDuration.4 = INTEGER: 5 */ - { "unmapped.rPDUOutletConfigRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.6.4", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.6.4", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigRebootDuration.5 = INTEGER: 5 */ - { "unmapped.rPDUOutletConfigRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.6.5", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.6.5", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigRebootDuration.6 = INTEGER: 5 */ - { "unmapped.rPDUOutletConfigRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.6.6", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.6.6", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigRebootDuration.7 = INTEGER: 5 */ - { "unmapped.rPDUOutletConfigRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.6.7", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.6.7", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigRebootDuration.8 = INTEGER: 5 */ - { "unmapped.rPDUOutletConfigRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.6.8", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigRebootDuration", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.6.8", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigOutletBank.1 = INTEGER: 0 */ - { "unmapped.rPDUOutletConfigOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.7.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.7.1", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigOutletBank.2 = INTEGER: 0 */ - { "unmapped.rPDUOutletConfigOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.7.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.7.2", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigOutletBank.3 = INTEGER: 0 */ - { "unmapped.rPDUOutletConfigOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.7.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.7.3", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigOutletBank.4 = INTEGER: 0 */ - { "unmapped.rPDUOutletConfigOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.7.4", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.7.4", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigOutletBank.5 = INTEGER: 0 */ - { "unmapped.rPDUOutletConfigOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.7.5", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.7.5", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigOutletBank.6 = INTEGER: 0 */ - { "unmapped.rPDUOutletConfigOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.7.6", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.7.6", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigOutletBank.7 = INTEGER: 0 */ - { "unmapped.rPDUOutletConfigOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.7.7", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.7.7", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigOutletBank.8 = INTEGER: 0 */ - { "unmapped.rPDUOutletConfigOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.7.8", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.1.1.7.8", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletConfigMonitoredTableSize.0 = INTEGER: 0 */ - { "unmapped.rPDUOutletConfigMonitoredTableSize", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.2.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletConfigMonitoredTableSize", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.4.2.0", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusIndex.1 = INTEGER: 1 */ - { "unmapped.rPDUOutletStatusIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.1.1", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusIndex.2 = INTEGER: 2 */ - { "unmapped.rPDUOutletStatusIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.1.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.1.2", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusIndex.3 = INTEGER: 3 */ - { "unmapped.rPDUOutletStatusIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.1.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.1.3", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusIndex.4 = INTEGER: 4 */ - { "unmapped.rPDUOutletStatusIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.1.4", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.1.4", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusIndex.5 = INTEGER: 5 */ - { "unmapped.rPDUOutletStatusIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.1.5", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.1.5", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusIndex.6 = INTEGER: 6 */ - { "unmapped.rPDUOutletStatusIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.1.6", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.1.6", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusIndex.7 = INTEGER: 7 */ - { "unmapped.rPDUOutletStatusIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.1.7", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.1.7", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusIndex.8 = INTEGER: 8 */ - { "unmapped.rPDUOutletStatusIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.1.8", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.1.8", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusOutletName.1 = STRING: "Testing Name" */ - { "unmapped.rPDUOutletStatusOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.2.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.2.1", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusOutletName.2 = STRING: "Testing 2" */ - { "unmapped.rPDUOutletStatusOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.2.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.2.2", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusOutletName.3 = STRING: "Outlet 3" */ - { "unmapped.rPDUOutletStatusOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.2.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.2.3", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusOutletName.4 = STRING: "Outlet 4" */ - { "unmapped.rPDUOutletStatusOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.2.4", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.2.4", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusOutletName.5 = STRING: "Outlet 5" */ - { "unmapped.rPDUOutletStatusOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.2.5", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.2.5", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusOutletName.6 = STRING: "Outlet 6" */ - { "unmapped.rPDUOutletStatusOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.2.6", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.2.6", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusOutletName.7 = STRING: "Outlet 7" */ - { "unmapped.rPDUOutletStatusOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.2.7", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.2.7", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusOutletName.8 = STRING: "Outlet 8" */ - { "unmapped.rPDUOutletStatusOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.2.8", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusOutletName", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.2.8", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusOutletPhase.1 = INTEGER: phase1(1) */ - { "unmapped.rPDUOutletStatusOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.3.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.3.1", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusOutletPhase.2 = INTEGER: phase1(1) */ - { "unmapped.rPDUOutletStatusOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.3.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.3.2", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusOutletPhase.3 = INTEGER: phase1(1) */ - { "unmapped.rPDUOutletStatusOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.3.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.3.3", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusOutletPhase.4 = INTEGER: phase1(1) */ - { "unmapped.rPDUOutletStatusOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.3.4", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.3.4", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusOutletPhase.5 = INTEGER: phase1(1) */ - { "unmapped.rPDUOutletStatusOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.3.5", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.3.5", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusOutletPhase.6 = INTEGER: phase1(1) */ - { "unmapped.rPDUOutletStatusOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.3.6", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.3.6", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusOutletPhase.7 = INTEGER: phase1(1) */ - { "unmapped.rPDUOutletStatusOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.3.7", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.3.7", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusOutletPhase.8 = INTEGER: phase1(1) */ - { "unmapped.rPDUOutletStatusOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.3.8", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusOutletPhase", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.3.8", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusOutletState.1 = INTEGER: outletStatusOn(1) */ - { "unmapped.rPDUOutletStatusOutletState", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.4.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusOutletState", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.4.1", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusOutletState.2 = INTEGER: outletStatusOn(1) */ - { "unmapped.rPDUOutletStatusOutletState", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.4.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusOutletState", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.4.2", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusOutletState.3 = INTEGER: outletStatusOn(1) */ - { "unmapped.rPDUOutletStatusOutletState", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.4.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusOutletState", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.4.3", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusOutletState.4 = INTEGER: outletStatusOn(1) */ - { "unmapped.rPDUOutletStatusOutletState", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.4.4", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusOutletState", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.4.4", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusOutletState.5 = INTEGER: outletStatusOn(1) */ - { "unmapped.rPDUOutletStatusOutletState", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.4.5", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusOutletState", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.4.5", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusOutletState.6 = INTEGER: outletStatusOn(1) */ - { "unmapped.rPDUOutletStatusOutletState", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.4.6", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusOutletState", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.4.6", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusOutletState.7 = INTEGER: outletStatusOn(1) */ - { "unmapped.rPDUOutletStatusOutletState", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.4.7", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusOutletState", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.4.7", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusOutletState.8 = INTEGER: outletStatusOn(1) */ - { "unmapped.rPDUOutletStatusOutletState", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.4.8", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusOutletState", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.4.8", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusCommandPending.1 = INTEGER: outletStatusNoCommandPending(2) */ - { "unmapped.rPDUOutletStatusCommandPending", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.5.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusCommandPending", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.5.1", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusCommandPending.2 = INTEGER: outletStatusNoCommandPending(2) */ - { "unmapped.rPDUOutletStatusCommandPending", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.5.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusCommandPending", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.5.2", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusCommandPending.3 = INTEGER: outletStatusNoCommandPending(2) */ - { "unmapped.rPDUOutletStatusCommandPending", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.5.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusCommandPending", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.5.3", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusCommandPending.4 = INTEGER: outletStatusNoCommandPending(2) */ - { "unmapped.rPDUOutletStatusCommandPending", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.5.4", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusCommandPending", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.5.4", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusCommandPending.5 = INTEGER: outletStatusNoCommandPending(2) */ - { "unmapped.rPDUOutletStatusCommandPending", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.5.5", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusCommandPending", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.5.5", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusCommandPending.6 = INTEGER: outletStatusNoCommandPending(2) */ - { "unmapped.rPDUOutletStatusCommandPending", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.5.6", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusCommandPending", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.5.6", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusCommandPending.7 = INTEGER: outletStatusNoCommandPending(2) */ - { "unmapped.rPDUOutletStatusCommandPending", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.5.7", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusCommandPending", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.5.7", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusCommandPending.8 = INTEGER: outletStatusNoCommandPending(2) */ - { "unmapped.rPDUOutletStatusCommandPending", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.5.8", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusCommandPending", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.5.8", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusOutletBank.1 = INTEGER: 0 */ - { "unmapped.rPDUOutletStatusOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.6.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.6.1", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusOutletBank.2 = INTEGER: 0 */ - { "unmapped.rPDUOutletStatusOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.6.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.6.2", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusOutletBank.3 = INTEGER: 0 */ - { "unmapped.rPDUOutletStatusOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.6.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.6.3", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusOutletBank.4 = INTEGER: 0 */ - { "unmapped.rPDUOutletStatusOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.6.4", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.6.4", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusOutletBank.5 = INTEGER: 0 */ - { "unmapped.rPDUOutletStatusOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.6.5", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.6.5", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusOutletBank.6 = INTEGER: 0 */ - { "unmapped.rPDUOutletStatusOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.6.6", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.6.6", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusOutletBank.7 = INTEGER: 0 */ - { "unmapped.rPDUOutletStatusOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.6.7", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.6.7", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusOutletBank.8 = INTEGER: 0 */ - { "unmapped.rPDUOutletStatusOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.6.8", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusOutletBank", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.6.8", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusLoad.1 = Gauge32: 0 */ - { "unmapped.rPDUOutletStatusLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.7.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.7.1", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusLoad.2 = Gauge32: 0 */ - { "unmapped.rPDUOutletStatusLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.7.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.7.2", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusLoad.3 = Gauge32: 0 */ - { "unmapped.rPDUOutletStatusLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.7.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.7.3", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusLoad.4 = Gauge32: 0 */ - { "unmapped.rPDUOutletStatusLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.7.4", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.7.4", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusLoad.5 = Gauge32: 0 */ - { "unmapped.rPDUOutletStatusLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.7.5", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.7.5", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusLoad.6 = Gauge32: 0 */ - { "unmapped.rPDUOutletStatusLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.7.6", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.7.6", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusLoad.7 = Gauge32: 0 */ - { "unmapped.rPDUOutletStatusLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.7.7", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.7.7", NULL, SU_FLAG_OK, NULL }, /* rPDUOutletStatusLoad.8 = Gauge32: 0 */ - { "unmapped.rPDUOutletStatusLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.7.8", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUOutletStatusLoad", 0, 1, ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.7.8", NULL, SU_FLAG_OK, NULL }, /* rPDUPowerSupply1Status.0 = INTEGER: powerSupplyOneOk(1) */ - { "unmapped.rPDUPowerSupply1Status", 0, 1, ".1.3.6.1.4.1.318.1.1.12.4.1.1.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUPowerSupply1Status", 0, 1, ".1.3.6.1.4.1.318.1.1.12.4.1.1.0", NULL, SU_FLAG_OK, NULL }, /* rPDUPowerSupply2Status.0 = INTEGER: powerSupplyTwoOk(1) */ - { "unmapped.rPDUPowerSupply2Status", 0, 1, ".1.3.6.1.4.1.318.1.1.12.4.1.2.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUPowerSupply2Status", 0, 1, ".1.3.6.1.4.1.318.1.1.12.4.1.2.0", NULL, SU_FLAG_OK, NULL }, /* rPDUPowerSupplyAlarm.0 = INTEGER: allAvailablePowerSuppliesOK(1) */ - { "unmapped.rPDUPowerSupplyAlarm", 0, 1, ".1.3.6.1.4.1.318.1.1.12.4.1.3.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUPowerSupplyAlarm", 0, 1, ".1.3.6.1.4.1.318.1.1.12.4.1.3.0", NULL, SU_FLAG_OK, NULL }, /* rPDUStatusBankTableSize.0 = INTEGER: 0 */ - { "unmapped.rPDUStatusBankTableSize", 0, 1, ".1.3.6.1.4.1.318.1.1.12.5.1.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUStatusBankTableSize", 0, 1, ".1.3.6.1.4.1.318.1.1.12.5.1.0", NULL, SU_FLAG_OK, NULL }, /* rPDUStatusPhaseTableSize.0 = INTEGER: 1 */ - { "unmapped.rPDUStatusPhaseTableSize", 0, 1, ".1.3.6.1.4.1.318.1.1.12.5.3.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUStatusPhaseTableSize", 0, 1, ".1.3.6.1.4.1.318.1.1.12.5.3.0", NULL, SU_FLAG_OK, NULL }, /* rPDUStatusPhaseIndex.1 = INTEGER: 1 */ - { "unmapped.rPDUStatusPhaseIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.5.4.1.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUStatusPhaseIndex", 0, 1, ".1.3.6.1.4.1.318.1.1.12.5.4.1.1.1", NULL, SU_FLAG_OK, NULL }, /* rPDUStatusPhaseNumber.1 = INTEGER: 1 */ - { "unmapped.rPDUStatusPhaseNumber", 0, 1, ".1.3.6.1.4.1.318.1.1.12.5.4.1.2.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUStatusPhaseNumber", 0, 1, ".1.3.6.1.4.1.318.1.1.12.5.4.1.2.1", NULL, SU_FLAG_OK, NULL }, /* rPDUStatusPhaseState.1 = INTEGER: phaseLoadNormal(1) */ - { "unmapped.rPDUStatusPhaseState", 0, 1, ".1.3.6.1.4.1.318.1.1.12.5.4.1.3.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUStatusPhaseState", 0, 1, ".1.3.6.1.4.1.318.1.1.12.5.4.1.3.1", NULL, SU_FLAG_OK, NULL }, /* rPDUStatusOutletTableSize.0 = INTEGER: 0 */ - { "unmapped.rPDUStatusOutletTableSize", 0, 1, ".1.3.6.1.4.1.318.1.1.12.5.5.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.rPDUStatusOutletTableSize", 0, 1, ".1.3.6.1.4.1.318.1.1.12.5.5.0", NULL, SU_FLAG_OK, NULL }, /* experimental.2.1.0 = INTEGER: 1 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.1.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.1.0", NULL, SU_FLAG_OK, NULL }, /* experimental.2.2.1.1.1 = INTEGER: 1 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.2.1.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.2.1.1.1", NULL, SU_FLAG_OK, NULL }, /* experimental.2.2.1.2.1 = STRING: "Rack PDU_ISX" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.2.1.2.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.2.1.2.1", NULL, SU_FLAG_OK, NULL }, /* experimental.2.2.1.3.1 = STRING: "5A1234E00874" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.2.1.3.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.2.1.3.1", NULL, SU_FLAG_OK, NULL }, /* experimental.2.2.1.4.1 = INTEGER: 2 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.2.1.4.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.2.1.4.1", NULL, SU_FLAG_OK, NULL }, /* experimental.2.2.1.5.1 = STRING: "Rack PDU" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.2.1.5.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.2.1.5.1", NULL, SU_FLAG_OK, NULL }, /* experimental.2.2.1.6.1 = STRING: "1" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.2.1.6.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.2.1.6.1", NULL, SU_FLAG_OK, NULL }, /* experimental.2.2.1.7.1 = STRING: "Unknown" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.2.1.7.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.2.1.7.1", NULL, SU_FLAG_OK, NULL }, /* experimental.2.2.1.8.1 = INTEGER: 255 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.2.1.8.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.2.1.8.1", NULL, SU_FLAG_OK, NULL }, /* experimental.2.2.1.9.1 = STRING: "RackPDU" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.2.1.9.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.2.1.9.1", NULL, SU_FLAG_OK, NULL }, /* experimental.2.2.1.10.1 = INTEGER: 255 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.2.1.10.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.2.1.10.1", NULL, SU_FLAG_OK, NULL }, /* experimental.2.2.1.11.1 = INTEGER: 1 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.2.1.11.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.2.1.11.1", NULL, SU_FLAG_OK, NULL }, /* experimental.2.2.1.12.1 = STRING: "0" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.2.1.12.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.2.1.12.1", NULL, SU_FLAG_OK, NULL }, /* experimental.2.2.1.13.1 = INTEGER: 1 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.2.1.13.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.2.1.13.1", NULL, SU_FLAG_OK, NULL }, /* experimental.2.2.1.14.1 = STRING: "SB-1" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.2.1.14.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.2.1.14.1", NULL, SU_FLAG_OK, NULL }, /* experimental.2.3.0 = INTEGER: 2 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.3.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.3.0", NULL, SU_FLAG_OK, NULL }, /* experimental.2.4.1.1.1 = INTEGER: 1 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.4.1.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.4.1.1.1", NULL, SU_FLAG_OK, NULL }, /* experimental.2.4.1.1.2 = INTEGER: 2 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.4.1.1.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.4.1.1.2", NULL, SU_FLAG_OK, NULL }, /* experimental.2.4.1.2.1 = STRING: "5A1234E00874" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.4.1.2.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.4.1.2.1", NULL, SU_FLAG_OK, NULL }, /* experimental.2.4.1.2.2 = STRING: "5A1234E00874" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.4.1.2.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.4.1.2.2", NULL, SU_FLAG_OK, NULL }, /* experimental.2.4.1.3.1 = STRING: "apc_hw02_aos_373.bin" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.4.1.3.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.4.1.3.1", NULL, SU_FLAG_OK, NULL }, /* experimental.2.4.1.3.2 = STRING: "apc_hw02_rpdu_373.bin" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.4.1.3.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.4.1.3.2", NULL, SU_FLAG_OK, NULL }, /* experimental.2.4.1.4.1 = STRING: "v3.7.3" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.4.1.4.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.4.1.4.1", NULL, SU_FLAG_OK, NULL }, /* experimental.2.4.1.4.2 = STRING: "v3.7.3" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.4.1.4.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.4.1.4.2", NULL, SU_FLAG_OK, NULL }, /* experimental.2.5.0 = INTEGER: 19 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.5.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.5.0", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.1.1 = INTEGER: 1 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.1", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.1.2 = INTEGER: 2 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.2", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.1.3 = INTEGER: 3 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.3", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.1.4 = INTEGER: 4 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.4", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.4", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.1.5 = INTEGER: 5 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.5", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.5", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.1.6 = INTEGER: 6 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.6", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.6", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.1.7 = INTEGER: 7 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.7", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.7", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.1.8 = INTEGER: 8 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.8", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.8", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.1.9 = INTEGER: 9 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.9", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.9", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.1.10 = INTEGER: 10 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.10", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.10", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.1.11 = INTEGER: 11 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.11", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.11", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.1.12 = INTEGER: 12 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.12", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.12", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.1.13 = INTEGER: 13 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.13", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.13", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.1.14 = INTEGER: 14 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.14", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.14", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.1.15 = INTEGER: 15 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.15", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.15", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.1.16 = INTEGER: 16 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.16", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.16", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.1.17 = INTEGER: 17 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.17", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.17", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.1.18 = INTEGER: 18 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.18", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.18", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.1.19 = INTEGER: 19 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.19", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.1.19", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.2.1 = INTEGER: 1 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.1", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.2.2 = INTEGER: 2 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.2", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.2.3 = INTEGER: 3 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.3", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.2.4 = INTEGER: 4 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.4", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.4", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.2.5 = INTEGER: 5 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.5", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.5", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.2.6 = INTEGER: 6 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.6", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.6", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.2.7 = INTEGER: 7 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.7", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.7", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.2.8 = INTEGER: 8 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.8", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.8", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.2.9 = INTEGER: 9 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.9", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.9", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.2.10 = INTEGER: 10 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.10", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.10", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.2.11 = INTEGER: 11 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.11", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.11", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.2.12 = INTEGER: 12 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.12", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.12", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.2.13 = INTEGER: 13 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.13", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.13", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.2.14 = INTEGER: 14 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.14", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.14", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.2.15 = INTEGER: 15 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.15", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.15", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.2.16 = INTEGER: 16 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.16", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.16", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.2.17 = INTEGER: 17 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.17", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.17", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.2.18 = INTEGER: 18 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.18", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.18", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.2.19 = INTEGER: 19 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.19", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.2.19", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.3.1 = STRING: "0" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.1", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.3.2 = STRING: "0" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.2", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.3.3 = STRING: "0" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.3", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.3.4 = STRING: "0" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.4", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.4", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.3.5 = STRING: "0" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.5", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.5", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.3.6 = STRING: "0" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.6", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.6", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.3.7 = STRING: "0" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.7", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.7", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.3.8 = STRING: "0" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.8", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.8", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.3.9 = STRING: "0" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.9", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.9", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.3.10 = STRING: "0" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.10", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.10", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.3.11 = STRING: "0" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.11", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.11", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.3.12 = STRING: "0" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.12", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.12", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.3.13 = STRING: "0" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.13", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.13", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.3.14 = STRING: "0" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.14", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.14", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.3.15 = STRING: "0" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.15", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.15", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.3.16 = STRING: "0" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.16", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.16", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.3.17 = STRING: "0" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.17", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.17", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.3.18 = STRING: "0" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.18", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.18", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.3.19 = STRING: "0" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.19", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.3.19", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.4.1 = STRING: "MTYx" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.1", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.4.2 = STRING: "MjM=" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.2", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.4.3 = STRING: "ODA=" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.3", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.4.4 = STRING: "OTk1MA==" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.4", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.4", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.4.5 = STRING: "OTk1MA==" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.5", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.5", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.4.6 = STRING: "NDQz" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.6", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.6", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.4.7 = STRING: "MjI=" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.7", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.7", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.4.8 = STRING: "MjI=" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.8", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.8", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.4.9 = STRING: "MTIz" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.9", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.9", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.4.10 = STRING: "MjU=" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.10", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.10", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.4.11 = STRING: "MjE=" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.11", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.11", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.4.12 = STRING: "MjE=" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.12", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.12", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.4.13 = STRING: "Njg=" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.13", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.13", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.4.14 = STRING: "NTQ2" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.14", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.14", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.4.15 = STRING: "MTgxMg==" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.15", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.15", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.4.16 = STRING: "MTYx" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.16", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.16", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.4.17 = STRING: "MjE=" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.17", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.17", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.4.18 = STRING: "MjE=" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.18", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.18", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.4.19 = STRING: "OTk1MQ==" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.19", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.6.1.4.19", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.5.1 = INTEGER: 2 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.1", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.5.2 = INTEGER: 2 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.2", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.5.3 = INTEGER: 2 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.3", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.5.4 = INTEGER: 2 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.4", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.4", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.5.5 = INTEGER: 2 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.5", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.5", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.5.6 = INTEGER: 1 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.6", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.6", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.5.7 = INTEGER: 1 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.7", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.7", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.5.8 = INTEGER: 1 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.8", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.8", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.5.9 = INTEGER: 1 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.9", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.9", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.5.10 = INTEGER: 2 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.10", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.10", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.5.11 = INTEGER: 2 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.11", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.11", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.5.12 = INTEGER: 2 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.12", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.12", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.5.13 = INTEGER: 1 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.13", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.13", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.5.14 = INTEGER: 1 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.14", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.14", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.5.15 = INTEGER: 1 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.15", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.15", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.5.16 = INTEGER: 1 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.16", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.16", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.5.17 = INTEGER: 1 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.17", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.17", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.5.18 = INTEGER: 1 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.18", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.18", NULL, SU_FLAG_OK, NULL }, /* experimental.2.6.1.5.19 = INTEGER: 1 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.19", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.6.1.5.19", NULL, SU_FLAG_OK, NULL }, /* experimental.2.7.0 = INTEGER: 1 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.7.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.7.0", NULL, SU_FLAG_OK, NULL }, /* experimental.2.8.1.1.1 = INTEGER: 1 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.8.1.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.8.1.1.1", NULL, SU_FLAG_OK, NULL }, /* experimental.2.8.1.2.1 = STRING: "power" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.8.1.2.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.8.1.2.1", NULL, SU_FLAG_OK, NULL }, /* experimental.2.8.1.3.1 = STRING: "pdu" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.8.1.3.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.8.1.3.1", NULL, SU_FLAG_OK, NULL }, /* experimental.2.8.1.4.1 = STRING: "rpdu" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.8.1.4.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.8.1.4.1", NULL, SU_FLAG_OK, NULL }, /* experimental.2.8.1.5.1 = STRING: "version7" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.8.1.5.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.2.8.1.5.1", NULL, SU_FLAG_OK, NULL }, /* experimental.2.8.1.6.1 = INTEGER: 1 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.8.1.6.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.8.1.6.1", NULL, SU_FLAG_OK, NULL }, /* experimental.2.9.0 = INTEGER: 0 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.9.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.9.0", NULL, SU_FLAG_OK, NULL }, /* experimental.2.10.0 = INTEGER: 0 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.10.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.10.0", NULL, SU_FLAG_OK, NULL }, /* experimental.2.12.0 = INTEGER: 1 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.12.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.2.12.0", NULL, SU_FLAG_OK, NULL }, /* experimental.4.1.0 = INTEGER: 0 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.4.1.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.4.1.0", NULL, SU_FLAG_OK, NULL }, /* experimental.4.3.0 = STRING: ",<1 digit type identifier>" */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.4.3.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.4.3.0", NULL, SU_FLAG_OK, NULL }, /* experimental.4.4.0 = INTEGER: 0 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.4.4.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.4.4.0", NULL, SU_FLAG_OK, NULL }, /* experimental.5.1.0 = INTEGER: 12 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.1.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.1.0", NULL, SU_FLAG_OK, NULL }, /* experimental.5.2.1.1.1 = INTEGER: 1 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.1.1", NULL, SU_FLAG_OK, NULL }, /* experimental.5.2.1.1.2 = INTEGER: 2 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.1.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.1.2", NULL, SU_FLAG_OK, NULL }, /* experimental.5.2.1.1.3 = INTEGER: 3 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.1.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.1.3", NULL, SU_FLAG_OK, NULL }, /* experimental.5.2.1.1.4 = INTEGER: 4 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.1.4", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.1.4", NULL, SU_FLAG_OK, NULL }, /* experimental.5.2.1.1.5 = INTEGER: 5 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.1.5", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.1.5", NULL, SU_FLAG_OK, NULL }, /* experimental.5.2.1.1.6 = INTEGER: 6 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.1.6", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.1.6", NULL, SU_FLAG_OK, NULL }, /* experimental.5.2.1.1.7 = INTEGER: 7 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.1.7", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.1.7", NULL, SU_FLAG_OK, NULL }, /* experimental.5.2.1.1.8 = INTEGER: 8 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.1.8", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.1.8", NULL, SU_FLAG_OK, NULL }, /* experimental.5.2.1.1.9 = INTEGER: 9 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.1.9", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.1.9", NULL, SU_FLAG_OK, NULL }, /* experimental.5.2.1.1.10 = INTEGER: 10 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.1.10", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.1.10", NULL, SU_FLAG_OK, NULL }, /* experimental.5.2.1.1.11 = INTEGER: 11 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.1.11", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.1.11", NULL, SU_FLAG_OK, NULL }, /* experimental.5.2.1.1.12 = INTEGER: 12 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.1.12", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.1.12", NULL, SU_FLAG_OK, NULL }, /* experimental.5.2.1.2.1 = INTEGER: 3841 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.2.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.2.1", NULL, SU_FLAG_OK, NULL }, /* experimental.5.2.1.2.2 = INTEGER: 3843 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.2.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.2.2", NULL, SU_FLAG_OK, NULL }, /* experimental.5.2.1.2.3 = INTEGER: 3845 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.2.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.2.3", NULL, SU_FLAG_OK, NULL }, /* experimental.5.2.1.2.4 = INTEGER: 3848 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.2.4", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.2.4", NULL, SU_FLAG_OK, NULL }, /* experimental.5.2.1.2.5 = INTEGER: 3862 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.2.5", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.2.5", NULL, SU_FLAG_OK, NULL }, /* experimental.5.2.1.2.6 = INTEGER: 3864 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.2.6", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.2.6", NULL, SU_FLAG_OK, NULL }, /* experimental.5.2.1.2.7 = INTEGER: 3856 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.2.7", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.2.7", NULL, SU_FLAG_OK, NULL }, /* experimental.5.2.1.2.8 = INTEGER: 3858 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.2.8", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.2.8", NULL, SU_FLAG_OK, NULL }, /* experimental.5.2.1.2.9 = INTEGER: 3860 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.2.9", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.2.9", NULL, SU_FLAG_OK, NULL }, /* experimental.5.2.1.2.10 = INTEGER: 3871 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.2.10", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.2.10", NULL, SU_FLAG_OK, NULL }, /* experimental.5.2.1.2.11 = INTEGER: 3873 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.2.11", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.2.11", NULL, SU_FLAG_OK, NULL }, /* experimental.5.2.1.2.12 = INTEGER: 3875 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.2.12", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.5.2.1.2.12", NULL, SU_FLAG_OK, NULL }, /* experimental.6.1.1.0 = Hex-STRING: 07 00 00 00 */ - { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.6.1.1.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.318.1.4.6.1.1.0", NULL, SU_FLAG_OK, NULL }, /* experimental.7.1.0 = INTEGER: 4 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.7.1.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.7.1.0", NULL, SU_FLAG_OK, NULL }, /* experimental.7.3.0 = INTEGER: 4 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.7.3.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.7.3.0", NULL, SU_FLAG_OK, NULL }, /* experimental.7.4.0 = INTEGER: 3 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.7.4.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.7.4.0", NULL, SU_FLAG_OK, NULL }, /* experimental.7.5.0 = INTEGER: 3 */ - { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.7.5.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.experimental", 0, 1, ".1.3.6.1.4.1.318.1.4.7.5.0", NULL, SU_FLAG_OK, NULL }, #endif /* scan result */ /* end of structure. */ - { NULL, 0, 0, NULL, NULL, 0, NULL, NULL } + { NULL, 0, 0, NULL, NULL, 0, NULL } }; #define APC_PDU_DEVICE_MODEL ".1.3.6.1.4.1.318.1.1.4.1.4.0" diff --git a/drivers/apcsmart.c b/drivers/apcsmart.c index 3417479f72..8d609ff4e3 100644 --- a/drivers/apcsmart.c +++ b/drivers/apcsmart.c @@ -1419,7 +1419,7 @@ static int sdok(int ign) debx(1, "got \"%s\"", temp); if ((!ret && ign) || !strcmp(temp, "OK")) { - debx(1, "last shutdown cmd succeded"); + debx(1, "last shutdown cmd succeeded"); return STAT_INSTCMD_HANDLED; } diff --git a/drivers/apcupsd-ups.c b/drivers/apcupsd-ups.c index 9b5350b1d1..fc72842b49 100644 --- a/drivers/apcupsd-ups.c +++ b/drivers/apcupsd-ups.c @@ -28,6 +28,8 @@ #define DRIVER_NAME "apcupsd network client UPS driver" #define DRIVER_VERSION "0.5" +#define POLL_INTERVAL_MIN 10 + /* driver description structure */ upsdrv_info_t upsdrv_info = { DRIVER_NAME, @@ -145,7 +147,7 @@ static int getdata(void) char bfr[1024]; for(x=0;nut_data[x].info_type;x++) - if(!(nut_data[x].drv_flags&DU_FLAG_INIT)) + if(!(nut_data[x].drv_flags & DU_FLAG_INIT) && !(nut_data[x].drv_flags & DU_FLAG_PRESERVE)) dstate_delinfo(nut_data[x].info_type); if((p.fd=socket(AF_INET,SOCK_STREAM,0))==-1) @@ -237,14 +239,16 @@ void upsdrv_initinfo(void) if(!port)fatalx(EXIT_FAILURE,"invalid host or port specified!"); if(getdata())fatalx(EXIT_FAILURE,"can't communicate with apcupsd!"); else dstate_dataok(); - poll_interval=60; + + poll_interval = (poll_interval > POLL_INTERVAL_MIN) ? POLL_INTERVAL_MIN : poll_interval; } void upsdrv_updateinfo(void) { if(getdata())upslogx(LOG_ERR,"can't communicate with apcupsd!"); else dstate_dataok(); - poll_interval=60; + + poll_interval = (poll_interval > POLL_INTERVAL_MIN) ? POLL_INTERVAL_MIN : poll_interval; } void upsdrv_shutdown(void) diff --git a/drivers/apcupsd-ups.h b/drivers/apcupsd-ups.h index 14bf923629..706ce1ea1b 100644 --- a/drivers/apcupsd-ups.h +++ b/drivers/apcupsd-ups.h @@ -89,6 +89,7 @@ typedef struct { #define DU_FLAG_TIME 8 #define DU_FLAG_FW1 16 #define DU_FLAG_FW2 32 +#define DU_FLAG_PRESERVE 64 /* ------------ */ /* Data table */ @@ -124,14 +125,19 @@ static apcuspd_info_t nut_data[] = { "LINEFREQ", "input.frequency", ST_FLAG_RW, 1, "%1.1f", DU_FLAG_NONE, NULL }, { "OUTPUTV", "output.voltage", ST_FLAG_RW, 1, "%1.1f", DU_FLAG_NONE, NULL }, { "LINEFREQ", "output.frequency", ST_FLAG_RW, 1, "%1.1f", DU_FLAG_NONE, NULL }, - { "BCHARGE", "battery.charge", ST_FLAG_RW, 1, "%1.1f", DU_FLAG_NONE, NULL }, + { "BCHARGE", "battery.charge", ST_FLAG_RW, 1, "%1.1f", DU_FLAG_PRESERVE, NULL }, { "MBATTCHG", "battery.charge.low", ST_FLAG_RW, 1, "%.0f", DU_FLAG_NONE, NULL }, { "BATTDATE", "battery.date", ST_FLAG_STRING /* | ST_FLAG_RW */, 16, NULL, DU_FLAG_DATE, NULL }, { "BATTV", "battery.voltage", 0, 1, "%1.1f", DU_FLAG_NONE, NULL }, { "NOMBATTV", "battery.voltage.nominal", 0, 1, "%1.1f", DU_FLAG_NONE, NULL }, - { "TIMELEFT", "battery.runtime", ST_FLAG_RW, 60, "%1.1f", DU_FLAG_NONE, NULL }, + { "TIMELEFT", "battery.runtime", ST_FLAG_RW, 60, "%1.1f", DU_FLAG_PRESERVE, NULL }, { "MINTIMEL", "battery.runtime.low", ST_FLAG_RW, 60, "%.0f", DU_FLAG_NONE, NULL }, { "RETPCT", "battery.charge.restart", ST_FLAG_RW, 1, "%1.1f", DU_FLAG_NONE, NULL }, { "NOMPOWER", "ups.realpower.nominal", 0, 1, "%1.1f", DU_FLAG_INIT, NULL }, + { "LOAD_W", "ups.realpower", 0, 1, "%1.1f", DU_FLAG_NONE, NULL }, + { "LOADAPNT", "power.percent", ST_FLAG_RW, 1, "%1.1f", DU_FLAG_NONE, NULL }, + { "OUTCURNT", "output.current", 0, 1, "%1.2f", DU_FLAG_NONE, NULL }, + { "LOAD_VA", "ups.power", 0, 1, "%1.1f", DU_FLAG_NONE, NULL }, + { "NOMAPNT", "ups.power.nominal", 0, 1, "%.0f", DU_FLAG_INIT, NULL }, { NULL, NULL, 0, 0, NULL, DU_FLAG_NONE, NULL } }; diff --git a/drivers/asem.c b/drivers/asem.c index d5d6ea511a..fd0d39225c 100644 --- a/drivers/asem.c +++ b/drivers/asem.c @@ -30,13 +30,14 @@ so you need to boot with acpi_enforce_resources=lax option. */ -/* Depends on i2c-dev.h, Linux only */ +#include "main.h" + #include #include #include +/* Depends on i2c-dev.h, Linux only */ #include - -#include "main.h" +#include #ifndef __STR__ # define __STR__(x) #x diff --git a/drivers/baytech-mib.c b/drivers/baytech-mib.c index ec0b8c3754..5a18bbe5e3 100644 --- a/drivers/baytech-mib.c +++ b/drivers/baytech-mib.c @@ -23,6 +23,7 @@ #include "baytech-mib.h" +/* FIXME: should be "X.Y[Z]"! */ #define BAYTECH_MIB_VERSION "4032" /* Baytech MIB */ @@ -41,51 +42,51 @@ static info_lkp_t outlet_status_info[] = { static snmp_info_t baytech_mib[] = { /* Device page */ { "device.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "BayTech", - SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL }, + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, { "device.model", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.4779.1.3.5.2.1.24.1", - "Generic SNMP PDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + "Generic SNMP PDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, { "device.serial", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.4779.1.1.2.0", "", - SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + SU_FLAG_STATIC | SU_FLAG_OK, NULL }, { "device.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "pdu", - SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL }, + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, { "device.macaddr", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.2.1.2.2.1.6.2", - "", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + "", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, /* UPS page */ { "ups.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "Baytech", - SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL }, + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, { "ups.model", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.4779.1.3.5.2.1.24.1", - "Generic SNMP PDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + "Generic SNMP PDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, { "ups.id", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.4779.1.1.3.0", - "unknown", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + "unknown", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, { "ups.serial", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.4779.1.1.2.0", "", - SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + SU_FLAG_STATIC | SU_FLAG_OK, NULL }, { "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.4779.1.1.1.0", "", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, { "ups.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "pdu", - SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL }, - { "ups.temperature", 0, 0.1, ".1.3.6.1.4.1.4779.1.3.5.5.1.10.2.1", NULL, 0, NULL, NULL }, + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, + { "ups.temperature", 0, 0.1, ".1.3.6.1.4.1.4779.1.3.5.5.1.10.2.1", NULL, 0, NULL }, /* Outlet page */ { "outlet.id", 0, 1, NULL, "0", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, { "outlet.desc", ST_FLAG_RW | ST_FLAG_STRING, 20, NULL, "All outlets", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, { "outlet.count", 0, 1, ".1.3.6.1.4.1.4779.1.3.5.2.1.15.1", "0", 0, NULL }, - { "outlet.current", 0, 0.1, ".1.3.6.1.4.1.4779.1.3.5.5.1.6.2.1", NULL, 0, NULL, NULL }, - { "outlet.voltage", 0, 0.1, ".1.3.6.1.4.1.4779.1.3.5.5.1.8.2.1", NULL, 0, NULL, NULL }, + { "outlet.current", 0, 0.1, ".1.3.6.1.4.1.4779.1.3.5.5.1.6.2.1", NULL, 0, NULL }, + { "outlet.voltage", 0, 0.1, ".1.3.6.1.4.1.4779.1.3.5.5.1.8.2.1", NULL, 0, NULL }, /* outlet template definition */ - { "outlet.%i.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.4779.1.3.5.3.1.3.1.%i", NULL, SU_OUTLET, &outlet_status_info[0], NULL }, - { "outlet.%i.desc", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.4779.1.3.5.3.1.4.1.%i", NULL, SU_OUTLET, NULL, NULL }, - { "outlet.%i.id", 0, 1, ".1.3.6.1.4.1.4779.1.3.5.6.1.3.2.1.%i", "%i", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_OUTLET | SU_FLAG_OK, NULL, NULL }, - { "outlet.%i.switchable", 0, 1, ".1.3.6.1.4.1.4779.1.3.5.3.1.1.1.%i", "yes", SU_FLAG_STATIC | SU_OUTLET, NULL, NULL }, + { "outlet.%i.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.4779.1.3.5.3.1.3.1.%i", NULL, SU_OUTLET, &outlet_status_info[0] }, + { "outlet.%i.desc", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.4779.1.3.5.3.1.4.1.%i", NULL, SU_OUTLET, NULL }, + { "outlet.%i.id", 0, 1, ".1.3.6.1.4.1.4779.1.3.5.6.1.3.2.1.%i", "%i", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_OUTLET | SU_FLAG_OK, NULL }, + { "outlet.%i.switchable", 0, 1, ".1.3.6.1.4.1.4779.1.3.5.3.1.1.1.%i", "yes", SU_FLAG_STATIC | SU_OUTLET, NULL }, /* instant commands. */ - { "outlet.%i.load.off", 0, 0, ".1.3.6.1.4.1.4779.1.3.5.3.1.3.1.%i", NULL, SU_TYPE_CMD | SU_OUTLET, NULL, NULL }, - { "outlet.%i.load.on", 0, 1, ".1.3.6.1.4.1.4779.1.3.5.3.1.3.1.%i", NULL, SU_TYPE_CMD | SU_OUTLET, NULL, NULL }, + { "outlet.%i.load.off", 0, 1, ".1.3.6.1.4.1.4779.1.3.5.3.1.3.1.%i", "0", SU_TYPE_CMD | SU_OUTLET, NULL }, + { "outlet.%i.load.on", 0, 1, ".1.3.6.1.4.1.4779.1.3.5.3.1.3.1.%i", "1", SU_TYPE_CMD | SU_OUTLET, NULL }, /* end of structure. */ - { NULL, 0, 0, NULL, NULL, 0, NULL, NULL } + { NULL, 0, 0, NULL, NULL, 0, NULL } }; mib2nut_info_t baytech = { "baytech", BAYTECH_MIB_VERSION, NULL, BAYTECH_OID_MODEL_NAME, baytech_mib }; diff --git a/drivers/bcmxcp.h b/drivers/bcmxcp.h index 058b34f947..3cb027fd5c 100644 --- a/drivers/bcmxcp.h +++ b/drivers/bcmxcp.h @@ -22,7 +22,7 @@ /* No Autorisation required */ #define PW_ID_BLOCK_REQ (unsigned char)0x31 /* Model name, ... length 1 */ -#define PW_EVENT_HISTORY_LOG_REQ (unsigned char)0x32 /* List alarms that have occured. length 1 */ +#define PW_EVENT_HISTORY_LOG_REQ (unsigned char)0x32 /* List alarms that have occurred. length 1 */ #define PW_STATUS_REQ (unsigned char)0x33 /* On Line, On Bypass, ... length 1-2 */ #define PW_METER_BLOCK_REQ (unsigned char)0x34 /* Current UPS status (Load, utility,...) length 1 */ #define PW_CUR_ALARM_REQ (unsigned char)0x35 /* Current alarm and event request. length 1 */ diff --git a/drivers/bestfcom.c b/drivers/bestfcom.c index 54ea93ec2f..ef530c1982 100644 --- a/drivers/bestfcom.c +++ b/drivers/bestfcom.c @@ -444,7 +444,7 @@ void upsdrv_shutdown(void) { /* NB: hard-wired password */ ser_send(upsfd, "pw377\r"); - ser_send(upsfd, "off 1 a\r"); /* power off in 1 second and restart when line power returns */ + ser_send(upsfd, "o 10 a\r"); /* power off in 10 seconds and restart when line power returns, FE7K required a min of 5 seconds for off to function */ } /* list flags and values that you want to receive via -x */ diff --git a/drivers/bestpower-mib.c b/drivers/bestpower-mib.c index ea87186c0c..baa8c4d2b1 100644 --- a/drivers/bestpower-mib.c +++ b/drivers/bestpower-mib.c @@ -22,7 +22,7 @@ #include "bestpower-mib.h" -#define BESTPOWER_MIB_VERSION "0.1" +#define BESTPOWER_MIB_VERSION "0.2" #define BESTPOWER_OID_MODEL_NAME ".1.3.6.1.4.1.2947.1.1.2.0" /* @@ -43,19 +43,19 @@ static info_lkp_t bestpower_power_status[] = { static snmp_info_t bestpower_mib[] = { /* Device page */ { "device.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "ups", - SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL }, + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, { "ups.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "EATON", - SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL }, + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, /*.1.3.6.1.4.1.2947.1.1.1.0 = STRING: "Ferrups" .1.3.6.1.4.1.2947.1.1.2.0 = STRING: "FE850VA"*/ { "ups.model", ST_FLAG_STRING, SU_INFOSIZE, BESTPOWER_OID_MODEL_NAME, - "Best Ferrups", SU_FLAG_STATIC, NULL, NULL }, + "Best Ferrups", SU_FLAG_STATIC, NULL }, { "ups.serial", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.2947.1.1.5.0", "", SU_FLAG_STATIC, NULL }, { "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.2947.1.1.7.0", - "", SU_FLAG_STATIC, NULL }, + "", SU_FLAG_STATIC, NULL }, { "ups.power", 0, 1, ".1.3.6.1.4.1.2947.1.1.3.0", "", 0, NULL }, { "ups.mfr.date", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.2947.1.1.8.0", "", @@ -77,7 +77,7 @@ static snmp_info_t bestpower_mib[] = { 0, NULL }, /* end of structure. */ - { NULL, 0, 0, NULL, NULL, 0, NULL, NULL } + { NULL, 0, 0, NULL, NULL, 0, NULL } } ; mib2nut_info_t bestpower = { "bestpower", BESTPOWER_MIB_VERSION, NULL, diff --git a/drivers/bestuferrups.c b/drivers/bestuferrups.c index d60cb027d6..5d894ea0fe 100644 --- a/drivers/bestuferrups.c +++ b/drivers/bestuferrups.c @@ -484,7 +484,7 @@ void upsdrv_initups () fc.idealbvolts = ((fc.fullvolts - fc.emptyvolts) * 0.7) + fc.emptyvolts; break; default: - fatalx(EXIT_FAILURE, "Uknown model %s in ups_ident()", temp); + fatalx(EXIT_FAILURE, "Unknown model %s in ups_ident()", temp); } fc.valid = 1; diff --git a/drivers/compaq-mib.c b/drivers/compaq-mib.c index 564cf81ea3..e087f518da 100644 --- a/drivers/compaq-mib.c +++ b/drivers/compaq-mib.c @@ -30,12 +30,10 @@ #include "compaq-mib.h" -#define CPQPOWER_MIB_VERSION "1.61" +#define CPQPOWER_MIB_VERSION "1.64" -#define DEFAULT_ONDELAY 30 -#define DEFAULT_OFFDELAY 20 -#define STR_DEFAULT_ONDELAY "30" -#define STR_DEFAULT_OFFDELAY "20" +#define DEFAULT_ONDELAY "30" +#define DEFAULT_OFFDELAY "20" /* Note: RFC-1628 (UPS MIB) is also supported on these devices! */ @@ -82,6 +80,7 @@ #define CPQPOWER_OID_ALARM_OB ".1.3.6.1.4.1.232.165.3.7.3.0" /* UPS-MIB::upsOnBattery */ #define CPQPOWER_OID_ALARM_LB ".1.3.6.1.4.1.232.165.3.7.4.0" /* UPS-MIB::upsLowBattery */ +#define IETF_OID_AGENTREV ".1.3.6.1.2.1.33.1.1.4.0" /* UPS-MIB::upsIdentAgentSoftwareVersion.0 */ /* Not used, as no longer supported by MIB ver. 1.76 (Github issue 118) static info_lkp_t cpqpower_alarm_ob[] = { @@ -147,7 +146,7 @@ static info_lkp_t cpqpower_test_res_info[] = { { 0, NULL } } ; -#define CPQPOWER_START_TEST 1 +#define CPQPOWER_START_TEST "1" static info_lkp_t cpqpower_outlet_status_info[] = { { 1, "on" }, @@ -183,7 +182,9 @@ static snmp_info_t cpqpower_mib[] = { /* FIXME: split between firmware and firmware.aux ("00.01.0019;00.01.0004") * UPS Firmware Revision : 00.01.0004 * Communication Board Firmware Revision : 00.01.0019 */ - { "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, CPQPOWER_OID_FIRMREV, "", SU_FLAG_STATIC, NULL }, + /* FIXME: the 2 "firmware" entries below should be SU_FLAG_SEMI_STATIC */ + { "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, CPQPOWER_OID_FIRMREV, "", 0, NULL }, + { "ups.firmware.aux", ST_FLAG_STRING, SU_INFOSIZE, IETF_OID_AGENTREV, "", 0, NULL }, { "ups.load", 0, 1.0, CPQPOWER_OID_LOAD_LEVEL, "", 0, NULL }, { "ups.realpower", 0, 1.0, CPQPOWER_OID_OUT_POWER, "", SU_OUTPUT_1, NULL }, { "ups.realpower", 0, 1.0, ".1.3.6.1.4.1.232.165.3.9.3.0", "", SU_OUTPUT_1, NULL }, @@ -213,8 +214,8 @@ static snmp_info_t cpqpower_mib[] = { * flywheel(7) * fuelcell(8) */ - { "ups.delay.shutdown", ST_FLAG_STRING | ST_FLAG_RW, 6, ".1.3.6.1.4.1.232.165.3.8.1.0", STR_DEFAULT_OFFDELAY, SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, - { "ups.delay.start", ST_FLAG_STRING | ST_FLAG_RW, 6, ".1.3.6.1.4.1.232.165.3.8.2.0", STR_DEFAULT_ONDELAY, SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, + { "ups.delay.shutdown", ST_FLAG_STRING | ST_FLAG_RW, 6, ".1.3.6.1.4.1.232.165.3.8.1.0", DEFAULT_OFFDELAY, SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, + { "ups.delay.start", ST_FLAG_STRING | ST_FLAG_RW, 6, ".1.3.6.1.4.1.232.165.3.8.2.0", DEFAULT_ONDELAY, SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, { "ups.timer.shutdown", 0, 1, ".1.3.6.1.4.1.232.165.3.8.1.0", "", SU_FLAG_OK, NULL }, { "ups.timer.start", 0, 1, ".1.3.6.1.4.1.232.165.3.8.2.0", "", SU_FLAG_OK, NULL }, @@ -232,7 +233,7 @@ static snmp_info_t cpqpower_mib[] = { { "battery.status", 0, 0.1, ".1.3.6.1.4.1.232.165.3.2.5.0", "", 0, NULL }, */ /* Input page */ - { "input.phases", 0, 1.0, CPQPOWER_OID_IN_LINES, "", 0, NULL, NULL }, + { "input.phases", 0, 1.0, CPQPOWER_OID_IN_LINES, "", 0, NULL }, /* { "input.phase", 0, 1.0, CPQPOWER_OID_IN_PHASE, "", SU_OUTPUT_1, NULL }, */ { "input.frequency", 0, 0.1, CPQPOWER_OID_IN_FREQ , "", 0, NULL }, { "input.voltage", 0, 1.0, CPQPOWER_OID_IN_VOLTAGE, "", SU_OUTPUT_1, NULL }, @@ -254,7 +255,7 @@ static snmp_info_t cpqpower_mib[] = { { "input.quality", 0, 1.0, CPQPOWER_OID_IN_LINEBADS, "", 0, NULL }, /* Output page */ - { "output.phases", 0, 1.0, CPQPOWER_OID_OUT_LINES, "", 0, NULL, NULL }, + { "output.phases", 0, 1.0, CPQPOWER_OID_OUT_LINES, "", 0, NULL }, /* { "output.phase", 0, 1.0, CPQPOWER_OID_OUT_PHASE, "", SU_OUTPUT_1, NULL }, */ { "output.frequency", 0, 0.1, CPQPOWER_OID_OUT_FREQUENCY, "", 0, NULL }, /* FIXME: handle multiplier (0.1 there) */ @@ -291,38 +292,38 @@ static snmp_info_t cpqpower_mib[] = { /* outlet template definition */ /* FIXME always true? */ - { "outlet.%i.switchable", ST_FLAG_STRING, 3, ".1.3.6.1.4.1.232.165.3.10.2.1.1.%i", "yes", SU_FLAG_STATIC | SU_OUTLET, &cpqpower_outlet_switchability_info[0], NULL }, - { "outlet.%i.id", 0, 1, ".1.3.6.1.4.1.232.165.3.10.2.1.1.%i", "%i", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK | SU_OUTLET, NULL, NULL }, - /* { "outlet.%i.desc", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, AR_OID_OUTLET_NAME ".%i", NULL, SU_OUTLET, NULL, NULL }, */ - { "outlet.%i.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.3.10.2.1.2.%i", NULL, SU_FLAG_OK | SU_OUTLET, &cpqpower_outlet_status_info[0], NULL }, + { "outlet.%i.switchable", ST_FLAG_STRING, 3, ".1.3.6.1.4.1.232.165.3.10.2.1.1.%i", "yes", SU_FLAG_STATIC | SU_OUTLET, &cpqpower_outlet_switchability_info[0] }, + { "outlet.%i.id", 0, 1, ".1.3.6.1.4.1.232.165.3.10.2.1.1.%i", "%i", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK | SU_OUTLET, NULL }, + /* { "outlet.%i.desc", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, AR_OID_OUTLET_NAME ".%i", NULL, SU_OUTLET, NULL }, */ + { "outlet.%i.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.3.10.2.1.2.%i", NULL, SU_FLAG_OK | SU_OUTLET, &cpqpower_outlet_status_info[0] }, /* FIXME: come up with a suitable varname! * - The delay after going On Battery until the Receptacle is automatically turned Off. * A value of -1 means that this Output should never be turned Off automatically, but must be turned Off only by command. - * { "outlet.%i.autoswitch.delay.shutdown", ST_FLAG_STRING | ST_FLAG_RW, 6, ".1.3.6.1.4.1.232.165.3.10.2.1.5.%i", STR_DEFAULT_OFFDELAY, SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, // upsRecepAutoOffDelay + * { "outlet.%i.autoswitch.delay.shutdown", ST_FLAG_STRING | ST_FLAG_RW, 6, ".1.3.6.1.4.1.232.165.3.10.2.1.5.%i", DEFAULT_OFFDELAY, SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, // upsRecepAutoOffDelay * - Seconds delay after the Outlet is signaled to turn On before the Output is Automatically turned ON. * A value of -1 means that this Output should never be turned On automatically, but only when specifically commanded to do so. - * { "outlet.%i.autoswitch.delay.start", ST_FLAG_STRING | ST_FLAG_RW, 6, ".1.3.6.1.4.1.232.165.3.10.2.1.5.%i", STR_DEFAULT_OFFDELAY, SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, // upsRecepAutoOnDelay + * { "outlet.%i.autoswitch.delay.start", ST_FLAG_STRING | ST_FLAG_RW, 6, ".1.3.6.1.4.1.232.165.3.10.2.1.5.%i", DEFAULT_OFFDELAY, SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, // upsRecepAutoOnDelay */ /* FIXME: also define .stop (as for 'shutdown.reboot') * and .delay */ - { "outlet.%i.load.off", 0, 0, ".1.3.6.1.4.1.232.165.3.10.2.1.3.%i", NULL, SU_TYPE_CMD | SU_OUTLET, NULL, NULL }, - { "outlet.%i.load.on", 0, 0, ".1.3.6.1.4.1.232.165.3.10.2.1.4.%i", NULL, SU_TYPE_CMD | SU_OUTLET, NULL, NULL }, + { "outlet.%i.load.off", 0, 1, ".1.3.6.1.4.1.232.165.3.10.2.1.3.%i", "0", SU_TYPE_CMD | SU_OUTLET, NULL }, + { "outlet.%i.load.on", 0, 1, ".1.3.6.1.4.1.232.165.3.10.2.1.4.%i", "0", SU_TYPE_CMD | SU_OUTLET, NULL }, /* FIXME: also define a .delay or map to "outlet.%i.delay.shutdown" */ - { "outlet.%i.load.cycle", 0, 0, ".1.3.6.1.4.1.232.165.3.10.2.1.7.%i", NULL, SU_TYPE_CMD | SU_OUTLET, NULL, NULL }, + { "outlet.%i.load.cycle", 0, 1, ".1.3.6.1.4.1.232.165.3.10.2.1.7.%i", "0", SU_TYPE_CMD | SU_OUTLET, NULL }, /* instant commands. */ /* We need to duplicate load.{on,off} Vs load.{on,off}.delay, since * "0" cancels the shutdown, so we put "1" (second) for immediate off! */ - { "load.off", 0, 1, ".1.3.6.1.4.1.232.165.3.8.1.0", "", SU_TYPE_CMD, NULL }, - { "load.on", 0, 1, ".1.3.6.1.4.1.232.165.3.8.2.0", "", SU_TYPE_CMD, NULL }, - { "shutdown.stop", 0, 0, ".1.3.6.1.4.1.232.165.3.8.1.0", "", SU_TYPE_CMD | SU_FLAG_OK, NULL }, + { "load.off", 0, 1, ".1.3.6.1.4.1.232.165.3.8.1.0", "1", SU_TYPE_CMD, NULL }, + { "load.on", 0, 1, ".1.3.6.1.4.1.232.165.3.8.2.0", "1", SU_TYPE_CMD, NULL }, + { "shutdown.stop", 0, 1, ".1.3.6.1.4.1.232.165.3.8.1.0", "0", SU_TYPE_CMD | SU_FLAG_OK, NULL }, /* FIXME: need ups.{timer,delay}.{start,shutdown} param counterparts! */ - { "load.off.delay", 0, DEFAULT_OFFDELAY, ".1.3.6.1.4.1.232.165.3.8.1.0", "", SU_TYPE_CMD, NULL }, - { "load.on.delay", 0, DEFAULT_ONDELAY, ".1.3.6.1.4.1.232.165.3.8.2.0", "", SU_TYPE_CMD, NULL }, + { "load.off.delay", 0, 1, ".1.3.6.1.4.1.232.165.3.8.1.0", DEFAULT_OFFDELAY, SU_TYPE_CMD, NULL }, + { "load.on.delay", 0, 1, ".1.3.6.1.4.1.232.165.3.8.2.0", DEFAULT_ONDELAY, SU_TYPE_CMD, NULL }, /* { CMD_SHUTDOWN, 0, CPQPOWER_OFF_GRACEFUL, CPQPOWER_OID_OFF, "", 0, NULL }, */ - { "shutdown.reboot", 0, 0, ".1.3.6.1.4.1.232.165.3.8.6.0", "", SU_TYPE_CMD | SU_FLAG_OK, NULL }, - { "test.battery.start", 0, CPQPOWER_START_TEST, ".1.3.6.1.4.1.232.165.3.7.1.0", "", SU_TYPE_CMD | SU_FLAG_OK, NULL }, + { "shutdown.reboot", 0, 1, ".1.3.6.1.4.1.232.165.3.8.6.0", "0", SU_TYPE_CMD | SU_FLAG_OK, NULL }, + { "test.battery.start", 0, 1, ".1.3.6.1.4.1.232.165.3.7.1.0", CPQPOWER_START_TEST, SU_TYPE_CMD | SU_FLAG_OK, NULL }, /* end of structure. */ { NULL, 0, 0, NULL, NULL, 0, NULL } diff --git a/drivers/cyberpower-mib.c b/drivers/cyberpower-mib.c index 93b7bc4096..3c99ad4bc9 100644 --- a/drivers/cyberpower-mib.c +++ b/drivers/cyberpower-mib.c @@ -24,45 +24,74 @@ #include "cyberpower-mib.h" -#define CYBERPOWER_MIB_VERSION "0.1" +#define CYBERPOWER_MIB_VERSION "0.2" #define CYBERPOWER_OID_MODEL_NAME ".1.3.6.1.4.1.3808.1.1.1.1.1.1.0" -#define CYBERPOWER_SYSOID ".1.3.6.1.4.1.3808" +/* CPS-MIB::ups */ +#define CYBERPOWER_SYSOID ".1.3.6.1.4.1.3808.1.1.1" static info_lkp_t cyberpower_power_status[] = { { 2, "OL" }, { 3, "OB" }, - { 4, "OL" }, - { 5, "OL" }, + { 4, "OL BOOST" }, + { 5, "OFF" }, { 7, "OL" }, { 1, "NULL" }, - { 6, "NULL" }, + { 6, "OFF" }, { 0, NULL } } ; +static info_lkp_t cyberpower_battery_status[] = { + { 1, "" }, /* unknown */ + { 2, "" }, /* batteryNormal */ + { 3, "LB" }, /* batteryLow */ + { 0, NULL } +} ; + +static info_lkp_t cyberpower_cal_status[] = { + { 1, "" }, /* Calibration Successful */ + { 2, "" }, /* Calibration Invalid */ + { 3, "CAL" }, /* Calibration in progress */ + { 0, NULL } +}; + +static info_lkp_t cyberpower_battrepl_status[] = { + { 1, "" }, /* No battery needs replacing */ + { 2, "RB" }, /* Batteries need to be replaced */ + { 0, NULL } +}; + /* Snmp2NUT lookup table for CyberPower MIB */ static snmp_info_t cyberpower_mib[] = { /* Device page */ { "device.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "ups", - SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL }, + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, { "ups.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "CYBERPOWER", - SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL }, + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, { "ups.model", ST_FLAG_STRING, SU_INFOSIZE, CYBERPOWER_OID_MODEL_NAME, - "CyberPower", SU_FLAG_STATIC, NULL, NULL }, + "CyberPower", SU_FLAG_STATIC, NULL }, { "ups.serial", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.3808.1.1.1.1.2.3.0", "", SU_FLAG_STATIC, NULL }, { "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.3808.1.1.1.1.2.1.0", - "", SU_FLAG_STATIC, NULL }, + "", SU_FLAG_STATIC, NULL }, { "ups.mfr.date", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.3808.1.1.1.1.2.2.0", "", 0, NULL }, { "ups.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.3808.1.1.1.4.1.1.0", "", - 0 /*SU_STATUS_PWR*/, &cyberpower_power_status[0] }, + SU_FLAG_OK | SU_STATUS_PWR, &cyberpower_power_status[0] }, + { "ups.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.3808.1.1.1.2.1.1.0", "", + SU_FLAG_OK | SU_STATUS_BATT, &cyberpower_battery_status[0] }, + { "ups.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.3808.1.1.1.7.2.7.0", "", + SU_FLAG_OK | SU_STATUS_CAL, &cyberpower_cal_status[0] }, + { "ups.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.3808.1.1.1.2.2.5.0", "", + SU_FLAG_OK | SU_STATUS_RB, &cyberpower_battrepl_status[0] }, + { "ups.load", 0, 1.0, ".1.3.6.1.4.1.3808.1.1.1.4.2.3.0", "", + 0, NULL }, - /* Battery runtime is expressed in minutes */ - { "battery.runtime", 0, 60.0, ".1.3.6.1.4.1.3808.1.1.1.2.2.4.0", "", + /* Battery runtime is expressed in seconds */ + { "battery.runtime", 0, 1.0, ".1.3.6.1.4.1.3808.1.1.1.2.2.4.0", "", 0, NULL }, /* The elapsed time in seconds since the * UPS has switched to battery power */ @@ -72,9 +101,49 @@ static snmp_info_t cyberpower_mib[] = { 0, NULL }, { "battery.current", 0, 0.1, ".1.3.6.1.4.1.3808.1.1.1.2.2.7.0", "", 0, NULL }, + { "battery.charge", 0, 1.0, ".1.3.6.1.4.1.3808.1.1.1.2.2.1.0", "", + 0, NULL }, + + { "input.voltage", 0, 0.1, ".1.3.6.1.4.1.3808.1.1.1.3.2.1.0", "", + 0, NULL }, + { "input.frequency", 0, 0.1, ".1.3.6.1.4.1.3808.1.1.1.3.2.4.0", "", + 0, NULL }, + + { "output.voltage", 0, 0.1, ".1.3.6.1.4.1.3808.1.1.1.4.2.1.0", "", + 0, NULL }, + + /* Delays affecting instant commands */ + + /* upsAdvanceConfigReturnDelay */ + { "ups.delay.start", ST_FLAG_RW, 1.0, ".1.3.6.1.4.1.3808.1.1.1.5.2.9.0", "0", + SU_FLAG_OK | SU_TYPE_TIME, NULL }, + /* Not provided by CPS-MIB */ + { "ups.delay.reboot", 0, 1.0, NULL, "0", + SU_FLAG_OK | SU_FLAG_ABSENT, NULL }, + /* upsAdvanceConfigSleepDelay */ + { "ups.delay.shutdown", ST_FLAG_RW, 1.0, ".1.3.6.1.4.1.3808.1.1.1.5.2.11.0", "60", + SU_FLAG_OK | SU_TYPE_TIME, NULL }, + /* instant commands. */ + /* upsAdvanceControlUpsOff */ + { "load.off", 0, 2, ".1.3.6.1.4.1.3808.1.1.1.6.2.1.0", NULL, SU_TYPE_CMD | SU_FLAG_OK, NULL }, + /* upsAdvanceControlTurnOnUPS */ + { "load.on", 0, 2, ".1.3.6.1.4.1.3808.1.1.1.6.2.6.0", NULL, SU_TYPE_CMD | SU_FLAG_OK, NULL }, + /* upsAdvanceControlUpsOff */ + { "shutdown.stayoff", 0, 3, ".1.3.6.1.4.1.3808.1.1.1.6.2.6.0", NULL, SU_TYPE_CMD | SU_FLAG_OK, NULL }, + /* upsAdvanceControlUpsSleep */ + { "shutdown.return", 0, 3, ".1.3.6.1.4.1.3808.1.1.1.6.2.3.0", NULL, SU_TYPE_CMD | SU_FLAG_OK, NULL }, + /* upsAdvanceControlSimulatePowerFail */ + { "test.failure.start", 0, 2, ".1.3.6.1.4.1.3808.1.1.1.6.2.4.0", NULL, SU_TYPE_CMD | SU_FLAG_OK, NULL }, + /* upsAdvanceTestIndicators */ + { "test.panel.start", 0, 2, ".1.3.6.1.4.1.3808.1.1.1.7.2.5.0", NULL, SU_TYPE_CMD | SU_FLAG_OK, NULL }, + /* upsAdvanceTestDiagnostics */ + { "test.battery.start", 0, 2, ".1.3.6.1.4.1.3808.1.1.1.7.2.2.0", NULL, SU_TYPE_CMD | SU_FLAG_OK, NULL }, + /* upsAdvanceTestRuntimeCalibration */ + { "calibrate.start", 0, 2, ".1.3.6.1.4.1.3808.1.1.1.7.2.6.0", NULL, SU_TYPE_CMD | SU_FLAG_OK, NULL }, + { "calibrate.stop", 0, 3, ".1.3.6.1.4.1.3808.1.1.1.7.2.6.0", NULL, SU_TYPE_CMD | SU_FLAG_OK, NULL }, /* end of structure. */ - { NULL, 0, 0, NULL, NULL, 0, NULL, NULL } + { NULL, 0, 0, NULL, NULL, 0, NULL } } ; mib2nut_info_t cyberpower = { "cyberpower", CYBERPOWER_MIB_VERSION, NULL, diff --git a/drivers/delta_ups-mib.c b/drivers/delta_ups-mib.c index e3ba55e157..08563bc09c 100644 --- a/drivers/delta_ups-mib.c +++ b/drivers/delta_ups-mib.c @@ -73,7 +73,6 @@ static snmp_info_t delta_ups_mib[] = { * dfl: default value * flags: snmp-ups internal flags (FIXME: ...) * oid2info: lookup table between OID and NUT values - * setvar: variable to set for SU_FLAG_SETINT * * Example: * { "input.voltage", 0, 0.1, ".1.3.6.1.4.1.705.1.6.2.1.2.1", "", SU_INPUT_1, NULL }, diff --git a/drivers/dstate.c b/drivers/dstate.c index 32cd12e390..51e41a052a 100644 --- a/drivers/dstate.c +++ b/drivers/dstate.c @@ -201,6 +201,7 @@ static int send_to_one(conn_t *conn, const char *fmt, ...) ret = vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); + upsdebugx(2, "%s: sending %.*s", __func__, (int)strcspn(buf, "\n"), buf); if (ret < 1) { upsdebugx(2, "%s: nothing to write", __func__); return 1; @@ -356,6 +357,12 @@ static int cmd_dump_conn(conn_t *conn) return 1; } + +static void send_tracking(conn_t *conn, const char *id, int value) +{ + send_to_one(conn, "TRACKING %s %i\n", id, value); +} + static int sock_arg(conn_t *conn, int numarg, char **arg) { if (numarg < 1) { @@ -394,20 +401,40 @@ static int sock_arg(conn_t *conn, int numarg, char **arg) return 0; } - /* INSTCMD []*/ + /* INSTCMD [] [TRACKING ] */ if (!strcasecmp(arg[0], "INSTCMD")) { + int ret; + char *cmdname = arg[1]; + char *cmdparam = NULL; + char *cmdid = NULL; + + /* Check if and TRACKING were provided */ + if (numarg == 3) { + cmdparam = arg[2]; + } else if (numarg == 4 && !strcasecmp(arg[2], "TRACKING")) { + cmdid = arg[3]; + } else if (numarg == 5 && !strcasecmp(arg[3], "TRACKING")) { + cmdparam = arg[2]; + cmdid = arg[4]; + } else if (numarg != 2) { + upslogx(LOG_NOTICE, "Malformed INSTCMD request"); + return 0; + } + + if (cmdid) + upsdebugx(3, "%s: TRACKING = %s", __func__, cmdid); /* try the new handler first if present */ if (upsh.instcmd) { - if (numarg > 2) { - upsh.instcmd(arg[1], arg[2]); - return 1; - } + ret = upsh.instcmd(cmdname, cmdparam); - upsh.instcmd(arg[1], NULL); + /* send back execution result */ + if (cmdid) + send_tracking(conn, cmdid, ret); + + /* The command was handled, status is a separate consideration */ return 1; } - upslogx(LOG_NOTICE, "Got INSTCMD, but driver lacks a handler"); return 1; } @@ -416,12 +443,33 @@ static int sock_arg(conn_t *conn, int numarg, char **arg) return 0; } - /* SET */ + /* SET [TRACKING ] */ if (!strcasecmp(arg[0], "SET")) { + int ret; + char *setid = NULL; + + /* Check if TRACKING was provided */ + if (numarg == 5) { + if (!strcasecmp(arg[3], "TRACKING")) { + setid = arg[4]; + } + else { + upslogx(LOG_NOTICE, "Got SET with unsupported parameters (%s/%s)", + arg[3], arg[4]); + return 0; + } + upsdebugx(3, "%s: TRACKING = %s", __func__, setid); + } /* try the new handler first if present */ if (upsh.setvar) { - upsh.setvar(arg[1], arg[2]); + ret = upsh.setvar(arg[1], arg[2]); + + /* send back execution result */ + if (setid) + send_tracking(conn, setid, ret); + + /* The command was handled, status is a separate consideration */ return 1; } @@ -655,7 +703,7 @@ int dstate_addrange(const char *var, const int min, const int max) ret = state_addrange(dtree_root, var, min, max); if (ret == 1) { - send_to_all("ADDRANGE %s %i %i\n", var, min, max); + send_to_all("ADDRANGE %s %i %i\n", var, min, max); /* Also add the "NUMBER" flag for ranges */ dstate_addflags(var, ST_FLAG_NUMBER); } @@ -817,7 +865,7 @@ int dstate_delrange(const char *var, const int min, const int max) /* update listeners */ if (ret == 1) { - send_to_all("DELRANGE %s \"%i %i\"\n", var, min, max); + send_to_all("DELRANGE %s %i %i\n", var, min, max); } return ret; diff --git a/drivers/eaton-ats16-mib.c b/drivers/eaton-ats16-mib.c index 4441c3241c..c9eb859d83 100644 --- a/drivers/eaton-ats16-mib.c +++ b/drivers/eaton-ats16-mib.c @@ -2,7 +2,7 @@ * * Copyright (C) * 2011-2012 Arnaud Quette - * 2016-2017 Eaton (author: Arnaud Quette ) + * 2016-2020 Eaton (author: Arnaud Quette ) * * Note: this subdriver was initially generated as a "stub" by the * gen-snmp-subdriver script. It must be customized! @@ -24,9 +24,10 @@ #include "eaton-ats16-mib.h" -#define EATON_ATS16_MIB_VERSION "0.14" +#define EATON_ATS16_MIB_VERSION "0.17" -#define EATON_ATS16_SYSOID ".1.3.6.1.4.1.534.10" +#define EATON_ATS16_SYSOID_GEN1 ".1.3.6.1.4.1.705.1" /* legacy NMC */ +#define EATON_ATS16_SYSOID_GEN2 ".1.3.6.1.4.1.534.10.2" /* newer Network-M2 */ #define EATON_ATS16_MODEL ".1.3.6.1.4.1.534.10.2.1.2.0" static info_lkp_t eaton_ats16_source_info[] = { @@ -81,21 +82,22 @@ static info_lkp_t eaton_ats16_output_status_info[] = { static snmp_info_t eaton_ats16_mib[] = { /* Device collection */ - { "device.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "ats", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL }, + { "device.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "ats", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, /* ats2IdentManufacturer.0 = STRING: EATON */ - { "device.mfr", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.1.1.0", "Eaton", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + { "device.mfr", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.1.1.0", "Eaton", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, /* ats2IdentModel.0 = STRING: Eaton ATS */ - { "device.model", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.1.2.0", "ATS", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + { "device.model", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.1.2.0", "ATS", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, /* FIXME: RFC for device.firmware! */ + /* FIXME: the 2 "firmware" entries below should be SU_FLAG_SEMI_STATIC */ /* ats2IdentFWVersion.0 = STRING: 00.00.0009 */ - { "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.1.3.0", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + { "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.1.3.0", NULL, SU_FLAG_OK, NULL }, /* FIXME: RFC for device.firmware.aux! */ /* ats2IdentRelease.0 = STRING: JF */ - { "ups.firmware.aux", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.1.4.0", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + { "ups.firmware.aux", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.1.4.0", NULL, SU_FLAG_OK, NULL }, /* ats2IdentSerialNumber.0 = STRING: GA04F23009 */ - { "device.serial", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.1.5.0", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + { "device.serial", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.1.5.0", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL }, /* ats2IdentPartNumber.0 = STRING: EATS16N */ - { "device.part", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.1.6.0", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + { "device.part", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.1.6.0", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL }, /* ats2IdentAgentVersion.0 = STRING: 301F23C28 */ /* { "unmapped.ats2IdentAgentVersion", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.1.7.0", NULL, SU_FLAG_OK, NULL, NULL }, */ /* ats2InputDephasing.0 = INTEGER: 2 degrees */ @@ -103,145 +105,147 @@ static snmp_info_t eaton_ats16_mib[] = { /* Input collection */ /* ats2InputIndex.source1 = INTEGER: source1(1) */ - { "input.1.id", 0, 1, ".1.3.6.1.4.1.534.10.2.2.2.1.1.1", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + { "input.1.id", 0, 1, ".1.3.6.1.4.1.534.10.2.2.2.1.1.1", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL }, /* ats2InputIndex.source2 = INTEGER: source2(2) */ - { "input.2.id", 0, 1, ".1.3.6.1.4.1.534.10.2.2.2.1.1.2", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + { "input.2.id", 0, 1, ".1.3.6.1.4.1.534.10.2.2.2.1.1.2", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL }, /* ats2InputVoltage.source1 = INTEGER: 2292 0.1 V */ - { "input.1.voltage", 0, 0.1, ".1.3.6.1.4.1.534.10.2.2.2.1.2.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "input.1.voltage", 0, 0.1, ".1.3.6.1.4.1.534.10.2.2.2.1.2.1", NULL, SU_FLAG_OK, NULL }, /* ats2InputVoltage.source2 = INTEGER: 2432 0.1 V */ - { "input.2.voltage", 0, 0.1, ".1.3.6.1.4.1.534.10.2.2.2.1.2.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "input.2.voltage", 0, 0.1, ".1.3.6.1.4.1.534.10.2.2.2.1.2.2", NULL, SU_FLAG_OK, NULL }, /* ats2InputStatusVoltage.source1 = INTEGER: normalRange(1) */ - { "input.1.voltage.status", ST_FLAG_STRING, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.5.1", NULL, SU_FLAG_OK, eaton_ats16_input_voltage_status_info, NULL }, + { "input.1.voltage.status", ST_FLAG_STRING, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.5.1", NULL, SU_FLAG_OK, eaton_ats16_input_voltage_status_info }, /* ats2InputStatusVoltage.source2 = INTEGER: normalRange(1) */ - { "input.2.voltage.status", ST_FLAG_STRING, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.5.2", NULL, SU_FLAG_OK, eaton_ats16_input_voltage_status_info, NULL }, + { "input.2.voltage.status", ST_FLAG_STRING, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.5.2", NULL, SU_FLAG_OK, eaton_ats16_input_voltage_status_info }, /* ats2InputFrequency.source1 = INTEGER: 500 0.1 Hz */ - { "input.1.frequency", 0, 0.1, ".1.3.6.1.4.1.534.10.2.2.2.1.3.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "input.1.frequency", 0, 0.1, ".1.3.6.1.4.1.534.10.2.2.2.1.3.1", NULL, SU_FLAG_OK, NULL }, /* ats2InputFrequency.source2 = INTEGER: 500 0.1 Hz */ - { "input.2.frequency", 0, 0.1, ".1.3.6.1.4.1.534.10.2.2.2.1.3.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "input.2.frequency", 0, 0.1, ".1.3.6.1.4.1.534.10.2.2.2.1.3.2", NULL, SU_FLAG_OK, NULL }, /* ats2InputStatusFrequency.source1 = INTEGER: good(1) */ - { "input.1.frequency.status", ST_FLAG_STRING, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.2.1", NULL, SU_FLAG_OK, eaton_ats16_input_frequency_status_info, NULL }, + { "input.1.frequency.status", ST_FLAG_STRING, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.2.1", NULL, SU_FLAG_OK, eaton_ats16_input_frequency_status_info }, /* ats2InputStatusFrequency.source2 = INTEGER: good(1) */ - { "input.2.frequency.status", ST_FLAG_STRING, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.2.2", NULL, SU_FLAG_OK, eaton_ats16_input_frequency_status_info, NULL }, + { "input.2.frequency.status", ST_FLAG_STRING, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.2.2", NULL, SU_FLAG_OK, eaton_ats16_input_frequency_status_info }, /* ats2ConfigSensitivity.0 = INTEGER: normal(1) */ - { "input.sensitivity", ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.4.6.0", NULL, SU_FLAG_OK, &eaton_ats16_sensitivity_info[0], NULL }, + { "input.sensitivity", ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.4.6.0", NULL, SU_FLAG_OK, &eaton_ats16_sensitivity_info[0] }, /* ats2OperationMode.0 = INTEGER: source1(4) */ - { "input.source", ST_FLAG_STRING, 1, ".1.3.6.1.4.1.534.10.2.2.4.0", NULL, SU_FLAG_OK, eaton_ats16_source_info, NULL }, + { "input.source", ST_FLAG_STRING, 1, ".1.3.6.1.4.1.534.10.2.2.4.0", NULL, SU_FLAG_OK, eaton_ats16_source_info }, /* ats2ConfigPreferred.0 = INTEGER: source1(1) */ - { "input.source.preferred", ST_FLAG_RW, 1, ".1.3.6.1.4.1.534.10.2.4.5.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "input.source.preferred", ST_FLAG_RW, 1, ".1.3.6.1.4.1.534.10.2.4.5.0", NULL, SU_FLAG_OK, NULL }, /* ats2InputDephasing = INTEGER: 181 */ - { "input.phase.shift", 0, 1, ".1.3.6.1.4.1.534.10.2.2.1.1.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "input.phase.shift", 0, 1, ".1.3.6.1.4.1.534.10.2.2.1.1.0", NULL, SU_FLAG_OK, NULL }, /* Output collection */ /* ats2OutputVoltage.0 = INTEGER: 2304 0.1 V */ - { "output.voltage", 0, 0.1, ".1.3.6.1.4.1.534.10.2.2.3.1.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "output.voltage", 0, 0.1, ".1.3.6.1.4.1.534.10.2.2.3.1.0", NULL, SU_FLAG_OK, NULL }, /* ats2ConfigOutputVoltage.0 = INTEGER: 230 1 V */ - { "output.voltage.nominal", ST_FLAG_RW, 1, ".1.3.6.1.4.1.534.10.2.4.4.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "output.voltage.nominal", ST_FLAG_RW, 1, ".1.3.6.1.4.1.534.10.2.4.4.0", NULL, SU_FLAG_OK, NULL }, /* ats2OutputCurrent.0 = INTEGER: 5 0.1 A */ - { "output.current", 0, 0.1, ".1.3.6.1.4.1.534.10.2.2.3.2.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "output.current", 0, 0.1, ".1.3.6.1.4.1.534.10.2.2.3.2.0", NULL, SU_FLAG_OK, NULL }, /* UPS collection */ /* FIXME: RFC for device.test.result! */ /* ats2ConfigTransferTest.0 = INTEGER: noTestInitiated(6) */ - { "ups.test.result", 0, 1, ".1.3.6.1.4.1.534.10.2.4.8.0", NULL, SU_FLAG_OK, eaton_ats16_test_result_info, NULL }, + { "ups.test.result", 0, 1, ".1.3.6.1.4.1.534.10.2.4.8.0", NULL, SU_FLAG_OK, eaton_ats16_test_result_info }, /* FIXME: RFC for device.status! */ /* ats2StatusOutput.0 = INTEGER: outputPowered(2) */ - { "ups.status", 0, 1, ".1.3.6.1.4.1.534.10.2.3.3.2.0", NULL, SU_FLAG_OK, eaton_ats16_output_status_info, NULL }, + { "ups.status", 0, 1, ".1.3.6.1.4.1.534.10.2.3.3.2.0", NULL, SU_FLAG_OK, eaton_ats16_output_status_info }, /* Ambient collection */ /* ats2EnvRemoteTemp.0 = INTEGER: 0 degrees Centigrade */ - { "ambient.temperature", 0, 0.1, ".1.3.6.1.4.1.534.10.2.5.1.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "ambient.temperature", 0, 0.1, ".1.3.6.1.4.1.534.10.2.5.1.0", NULL, SU_FLAG_OK, NULL }, /* ats2EnvRemoteTempLowerLimit.0 = INTEGER: 5 degrees Centigrade */ - { "ambient.temperature.low", ST_FLAG_RW, 1, ".1.3.6.1.4.1.534.10.2.5.5.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "ambient.temperature.low", ST_FLAG_RW, 1, ".1.3.6.1.4.1.534.10.2.5.5.0", NULL, SU_FLAG_OK, NULL }, /* ats2EnvRemoteTempUpperLimit.0 = INTEGER: 40 degrees Centigrade */ - { "ambient.temperature.high", ST_FLAG_RW, 1, ".1.3.6.1.4.1.534.10.2.5.6.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "ambient.temperature.high", ST_FLAG_RW, 1, ".1.3.6.1.4.1.534.10.2.5.6.0", NULL, SU_FLAG_OK, NULL }, /* ats2EnvRemoteHumidity.0 = INTEGER: 0 percent */ - { "ambient.humidity", 0, 0.1, ".1.3.6.1.4.1.534.10.2.5.2.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "ambient.humidity", 0, 0.1, ".1.3.6.1.4.1.534.10.2.5.2.0", NULL, SU_FLAG_OK, NULL }, /* ats2EnvRemoteHumidityLowerLimit.0 = INTEGER: 5 percent */ - { "ambient.humidity.low", ST_FLAG_RW, 1, ".1.3.6.1.4.1.534.10.2.5.7.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "ambient.humidity.low", ST_FLAG_RW, 1, ".1.3.6.1.4.1.534.10.2.5.7.0", NULL, SU_FLAG_OK, NULL }, /* ats2EnvRemoteHumidityUpperLimit.0 = INTEGER: 90 percent */ - { "ambient.humidity.high", ST_FLAG_RW, 1, ".1.3.6.1.4.1.534.10.2.5.8.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "ambient.humidity.high", ST_FLAG_RW, 1, ".1.3.6.1.4.1.534.10.2.5.8.0", NULL, SU_FLAG_OK, NULL }, #if 0 /* FIXME: Remaining data to be processed */ /* ats2InputStatusDephasing.0 = INTEGER: normal(1) */ - { "unmapped.ats2InputStatusDephasing", 0, 1, ".1.3.6.1.4.1.534.10.2.3.1.1.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.ats2InputStatusDephasing", 0, 1, ".1.3.6.1.4.1.534.10.2.3.1.1.0", NULL, SU_FLAG_OK, NULL }, /* ats2InputStatusIndex.source1 = INTEGER: source1(1) */ - { "unmapped.ats2InputStatusIndex", 0, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.ats2InputStatusIndex", 0, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.1.1", NULL, SU_FLAG_OK, NULL }, /* ats2InputStatusIndex.source2 = INTEGER: source2(2) */ - { "unmapped.ats2InputStatusIndex", 0, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.1.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.ats2InputStatusIndex", 0, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.1.2", NULL, SU_FLAG_OK, NULL }, /* ats2InputStatusGood.source1 = INTEGER: voltageAndFreqNormalRange(2) */ - { "unmapped.ats2InputStatusGood", 0, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.3.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.ats2InputStatusGood", 0, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.3.1", NULL, SU_FLAG_OK, NULL }, /* ats2InputStatusGood.source2 = INTEGER: voltageAndFreqNormalRange(2) */ - { "unmapped.ats2InputStatusGood", 0, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.3.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.ats2InputStatusGood", 0, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.3.2", NULL, SU_FLAG_OK, NULL }, /* ats2InputStatusInternalFailure.source1 = INTEGER: good(1) */ - { "unmapped.ats2InputStatusInternalFailure", 0, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.4.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.ats2InputStatusInternalFailure", 0, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.4.1", NULL, SU_FLAG_OK, NULL }, /* ats2InputStatusInternalFailure.source2 = INTEGER: good(1) */ - { "unmapped.ats2InputStatusInternalFailure", 0, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.4.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.ats2InputStatusInternalFailure", 0, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.4.2", NULL, SU_FLAG_OK, NULL }, /* ats2InputStatusUsed.source1 = INTEGER: poweringLoad(2) */ - { "unmapped.ats2InputStatusUsed", 0, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.6.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.ats2InputStatusUsed", 0, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.6.1", NULL, SU_FLAG_OK, NULL }, /* ats2InputStatusUsed.source2 = INTEGER: notPoweringLoad(1) */ - { "unmapped.ats2InputStatusUsed", 0, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.6.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.ats2InputStatusUsed", 0, 1, ".1.3.6.1.4.1.534.10.2.3.2.1.6.2", NULL, SU_FLAG_OK, NULL }, /* ats2StatusInternalFailure.0 = INTEGER: good(1) */ - { "unmapped.ats2StatusInternalFailure", 0, 1, ".1.3.6.1.4.1.534.10.2.3.3.1.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.ats2StatusInternalFailure", 0, 1, ".1.3.6.1.4.1.534.10.2.3.3.1.0", NULL, SU_FLAG_OK, NULL }, /* ats2StatusOverload.0 = INTEGER: noOverload(1) */ - { "unmapped.ats2StatusOverload", 0, 1, ".1.3.6.1.4.1.534.10.2.3.3.3.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.ats2StatusOverload", 0, 1, ".1.3.6.1.4.1.534.10.2.3.3.3.0", NULL, SU_FLAG_OK, NULL }, /* ats2StatusOverTemperature.0 = INTEGER: noOverTemperature(1) */ - { "unmapped.ats2StatusOverTemperature", 0, 1, ".1.3.6.1.4.1.534.10.2.3.3.4.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.ats2StatusOverTemperature", 0, 1, ".1.3.6.1.4.1.534.10.2.3.3.4.0", NULL, SU_FLAG_OK, NULL }, /* ats2StatusShortCircuit.0 = INTEGER: noShortCircuit(1) */ - { "unmapped.ats2StatusShortCircuit", 0, 1, ".1.3.6.1.4.1.534.10.2.3.3.5.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.ats2StatusShortCircuit", 0, 1, ".1.3.6.1.4.1.534.10.2.3.3.5.0", NULL, SU_FLAG_OK, NULL }, /* ats2StatusCommunicationLost.0 = INTEGER: good(1) */ - { "unmapped.ats2StatusCommunicationLost", 0, 1, ".1.3.6.1.4.1.534.10.2.3.3.6.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.ats2StatusCommunicationLost", 0, 1, ".1.3.6.1.4.1.534.10.2.3.3.6.0", NULL, SU_FLAG_OK, NULL }, /* ats2StatusConfigurationFailure.0 = INTEGER: good(1) */ - { "unmapped.ats2StatusConfigurationFailure", 0, 1, ".1.3.6.1.4.1.534.10.2.3.3.7.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.ats2StatusConfigurationFailure", 0, 1, ".1.3.6.1.4.1.534.10.2.3.3.7.0", NULL, SU_FLAG_OK, NULL }, /* ats2ConfigTimeRTC.0 = Wrong Type (should be Counter32): Gauge32: 19191036 */ - { "unmapped.ats2ConfigTimeRTC", 0, 1, ".1.3.6.1.4.1.534.10.2.4.1.1.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.ats2ConfigTimeRTC", 0, 1, ".1.3.6.1.4.1.534.10.2.4.1.1.0", NULL, SU_FLAG_OK, NULL }, /* ats2ConfigTimeTextDate.0 = STRING: 08/11/1970 */ - { "unmapped.ats2ConfigTimeTextDate", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.4.1.2.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.ats2ConfigTimeTextDate", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.4.1.2.0", NULL, SU_FLAG_OK, NULL }, /* ats2ConfigTimeTextTime.0 = STRING: 02/50/36 */ - { "unmapped.ats2ConfigTimeTextTime", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.4.1.3.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.ats2ConfigTimeTextTime", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.4.1.3.0", NULL, SU_FLAG_OK, NULL }, /* ats2ConfigInputVoltageRating.0 = INTEGER: 1 1 V */ - { "unmapped.ats2ConfigInputVoltageRating", 0, 1, ".1.3.6.1.4.1.534.10.2.4.2.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.ats2ConfigInputVoltageRating", 0, 1, ".1.3.6.1.4.1.534.10.2.4.2.0", NULL, SU_FLAG_OK, NULL }, /* ats2ConfigInputFrequencyRating.0 = INTEGER: 50 Hz */ - { "unmapped.ats2ConfigInputFrequencyRating", 0, 1, ".1.3.6.1.4.1.534.10.2.4.3.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.ats2ConfigInputFrequencyRating", 0, 1, ".1.3.6.1.4.1.534.10.2.4.3.0", NULL, SU_FLAG_OK, NULL }, /* ats2ConfigTransferMode.0 = INTEGER: standard(1) */ - { "unmapped.ats2ConfigTransferMode", 0, 1, ".1.3.6.1.4.1.534.10.2.4.7.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.ats2ConfigTransferMode", 0, 1, ".1.3.6.1.4.1.534.10.2.4.7.0", NULL, SU_FLAG_OK, NULL }, /* ats2ConfigBrownoutLow.0 = INTEGER: 202 1 V */ - { "unmapped.ats2ConfigBrownoutLow", 0, 1, ".1.3.6.1.4.1.534.10.2.4.9.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.ats2ConfigBrownoutLow", 0, 1, ".1.3.6.1.4.1.534.10.2.4.9.0", NULL, SU_FLAG_OK, NULL }, /* ats2ConfigBrownoutLowDerated.0 = INTEGER: 189 1 V */ - { "unmapped.ats2ConfigBrownoutLowDerated", 0, 1, ".1.3.6.1.4.1.534.10.2.4.10.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.ats2ConfigBrownoutLowDerated", 0, 1, ".1.3.6.1.4.1.534.10.2.4.10.0", NULL, SU_FLAG_OK, NULL }, /* ats2ConfigBrownoutHigh.0 = INTEGER: 258 1 V */ - { "unmapped.ats2ConfigBrownoutHigh", 0, 1, ".1.3.6.1.4.1.534.10.2.4.11.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.ats2ConfigBrownoutHigh", 0, 1, ".1.3.6.1.4.1.534.10.2.4.11.0", NULL, SU_FLAG_OK, NULL }, /* ats2ConfigHysteresisVoltage.0 = INTEGER: 5 1 V */ - { "unmapped.ats2ConfigHysteresisVoltage", 0, 1, ".1.3.6.1.4.1.534.10.2.4.12.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.ats2ConfigHysteresisVoltage", 0, 1, ".1.3.6.1.4.1.534.10.2.4.12.0", NULL, SU_FLAG_OK, NULL }, /* Ambient collection */ /* ats2EnvNumContacts.0 = INTEGER: 2 */ - { "unmapped.ats2EnvNumContacts", 0, 1, ".1.3.6.1.4.1.534.10.2.5.3.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.ats2EnvNumContacts", 0, 1, ".1.3.6.1.4.1.534.10.2.5.3.0", NULL, SU_FLAG_OK, NULL }, /* ats2ContactIndex.1 = INTEGER: 1 */ - { "unmapped.ats2ContactIndex", 0, 1, ".1.3.6.1.4.1.534.10.2.5.4.1.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.ats2ContactIndex", 0, 1, ".1.3.6.1.4.1.534.10.2.5.4.1.1.1", NULL, SU_FLAG_OK, NULL }, /* ats2ContactIndex.2 = INTEGER: 2 */ - { "unmapped.ats2ContactIndex", 0, 1, ".1.3.6.1.4.1.534.10.2.5.4.1.1.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.ats2ContactIndex", 0, 1, ".1.3.6.1.4.1.534.10.2.5.4.1.1.2", NULL, SU_FLAG_OK, NULL }, /* ats2ContactType.1 = INTEGER: notUsed(4) */ - { "unmapped.ats2ContactType", 0, 1, ".1.3.6.1.4.1.534.10.2.5.4.1.2.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.ats2ContactType", 0, 1, ".1.3.6.1.4.1.534.10.2.5.4.1.2.1", NULL, SU_FLAG_OK, NULL }, /* ats2ContactType.2 = INTEGER: notUsed(4) */ - { "unmapped.ats2ContactType", 0, 1, ".1.3.6.1.4.1.534.10.2.5.4.1.2.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.ats2ContactType", 0, 1, ".1.3.6.1.4.1.534.10.2.5.4.1.2.2", NULL, SU_FLAG_OK, NULL }, /* ats2ContactState.1 = INTEGER: open(1) */ - { "unmapped.ats2ContactState", 0, 1, ".1.3.6.1.4.1.534.10.2.5.4.1.3.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.ats2ContactState", 0, 1, ".1.3.6.1.4.1.534.10.2.5.4.1.3.1", NULL, SU_FLAG_OK, NULL }, /* ats2ContactState.2 = INTEGER: open(1) */ - { "unmapped.ats2ContactState", 0, 1, ".1.3.6.1.4.1.534.10.2.5.4.1.3.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.ats2ContactState", 0, 1, ".1.3.6.1.4.1.534.10.2.5.4.1.3.2", NULL, SU_FLAG_OK, NULL }, /* ats2ContactDescr.1 = STRING: Input #1 */ - { "unmapped.ats2ContactDescr", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.5.4.1.4.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.ats2ContactDescr", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.5.4.1.4.1", NULL, SU_FLAG_OK, NULL }, /* ats2ContactDescr.2 = STRING: Input #2 */ - { "unmapped.ats2ContactDescr", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.5.4.1.4.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.ats2ContactDescr", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.2.5.4.1.4.2", NULL, SU_FLAG_OK, NULL }, #endif /* if 0 */ /* end of structure. */ { NULL, 0, 0, NULL, NULL, 0, NULL } }; -mib2nut_info_t eaton_ats16 = { "eaton_ats16", EATON_ATS16_MIB_VERSION, NULL, EATON_ATS16_MODEL, eaton_ats16_mib, ".1.3.6.1.4.1.705.1" }; -/* FIXME: Eaton ATS need to be fixed for the sysOID (currently .1.3.6.1.4.1.705.1!) */ -/* mib2nut_info_t eaton_ats16 = { "eaton_ats16", EATON_ATS16_MIB_VERSION, NULL, EATON_ATS16_MODEL, eaton_ats16_mib, EATON_ATS16_SYSOID }; */ +mib2nut_info_t eaton_ats16 = { "eaton_ats16", EATON_ATS16_MIB_VERSION, NULL, EATON_ATS16_MODEL, eaton_ats16_mib, EATON_ATS16_SYSOID_GEN1 }; +/* Newer Network-M2 communication cards, with a fixed sysOID */ +/* FIXME: Duplicate the line below to fix an issue with the code generator (nut-snmpinfo.py -> line is discarding) */ +/*mib2nut_info_t eaton_ats16_g2 = { "eaton_ats16_g2", EATON_ATS16_MIB_VERSION, NULL, EATON_ATS16_MODEL, eaton_ats16_mib, EATON_ATS16_SYSOID_GEN2 };*/ +mib2nut_info_t eaton_ats16_g2 = { "eaton_ats16", EATON_ATS16_MIB_VERSION, NULL, EATON_ATS16_MODEL, eaton_ats16_mib, EATON_ATS16_SYSOID_GEN2 }; diff --git a/drivers/eaton-ats16-mib.h b/drivers/eaton-ats16-mib.h index a3d26a11cb..87008517dd 100644 --- a/drivers/eaton-ats16-mib.h +++ b/drivers/eaton-ats16-mib.h @@ -26,5 +26,6 @@ #include "snmp-ups.h" extern mib2nut_info_t eaton_ats16; +extern mib2nut_info_t eaton_ats16_g2; #endif /* EATON_ATS16_MIB_H */ diff --git a/drivers/eaton-ats30-mib.c b/drivers/eaton-ats30-mib.c index 427a4003f5..1848f7a6d4 100644 --- a/drivers/eaton-ats30-mib.c +++ b/drivers/eaton-ats30-mib.c @@ -2,6 +2,7 @@ * * Copyright (C) 2017 Eaton * Author: Tomas Halman + * 2011-2012 Arnaud Quette * * Note: this subdriver was initially generated as a "stub" by the * gen-snmp-subdriver script. It must be customized! @@ -23,7 +24,7 @@ #include "eaton-ats30-mib.h" -#define EATON_ATS30_MIB_VERSION "0.01" +#define EATON_ATS30_MIB_VERSION "0.02" #define EATON_ATS30_SYSOID ".1.3.6.1.4.1.534.10.1" #define EATON_ATS30_MODEL ".1.3.6.1.4.1.534.10.1.2.1.0" @@ -76,141 +77,141 @@ static info_lkp_t eaton_ats30_status_info[] = { /* EATON_ATS30 Snmp2NUT lookup table */ static snmp_info_t eaton_ats30_mib[] = { /* device type: ats */ - { "device.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "ats", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL }, + { "device.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "ats", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, /* standard MIB items */ - { "device.description", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.1.0", NULL, SU_FLAG_OK, NULL, NULL }, - { "device.contact", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.4.0", NULL, SU_FLAG_OK, NULL, NULL }, - { "device.location", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.6.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "device.description", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.1.0", NULL, SU_FLAG_OK, NULL }, + { "device.contact", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.4.0", NULL, SU_FLAG_OK, NULL }, + { "device.location", ST_FLAG_STRING | ST_FLAG_RW, SU_INFOSIZE, ".1.3.6.1.2.1.1.6.0", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.1.1.0 = STRING: "Eaton" */ - { "device.mfr", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.1.1.0", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + { "device.mfr", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.1.1.0", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL }, /* enterprises.534.10.1.1.2.0 = STRING: "01.12.13b" -- SNMP agent version */ - /* { "device.firmware", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.1.2.0", NULL, SU_FLAG_OK, NULL, NULL }, */ + /* { "device.firmware", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.1.2.0", NULL, SU_FLAG_OK, NULL }, */ /* enterprises.534.10.1.1.3.1.0 = INTEGER: 1 */ - /* { "unmapped.enterprise", 0, 1, ".1.3.6.1.4.1.534.10.1.1.3.1.0", NULL, SU_FLAG_OK, NULL, NULL }, */ + /* { "unmapped.enterprise", 0, 1, ".1.3.6.1.4.1.534.10.1.1.3.1.0", NULL, SU_FLAG_OK, NULL }, */ /* enterprises.534.10.1.2.1.0 = STRING: "STS30002SR10019 " */ - { "device.model", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.2.1.0", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + { "device.model", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.2.1.0", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL }, /* enterprises.534.10.1.2.2.0 = STRING: "1A0003AR00.00.00" -- Firmware */ - { "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.2.2.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.2.2.0", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.2.3.0 = STRING: "2014-09-17 " -- Release date */ - /* { "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.2.3.0", NULL, SU_FLAG_OK, NULL, NULL }, */ + /* { "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.2.3.0", NULL, SU_FLAG_OK, NULL }, */ /* enterprises.534.10.1.2.4.0 = STRING: "JA00E52021 " */ - { "device.serial", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.2.4.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "device.serial", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.2.4.0", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.2.5.0 = STRING: " " -- Device ID codes */ - /* { "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.2.5.0", NULL, SU_FLAG_OK, NULL, NULL }, */ + /* { "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.2.5.0", NULL, SU_FLAG_OK, NULL }, */ /* ats measure */ /* =========== */ /* enterprises.534.10.1.3.1.1.1.1 = INTEGER: 1 */ - { "input.1.id", 0, 1, ".1.3.6.1.4.1.534.10.1.3.1.1.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "input.1.id", 0, 1, ".1.3.6.1.4.1.534.10.1.3.1.1.1.1", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.3.1.1.1.2 = INTEGER: 2 */ - { "input.2.id", 0, 1, ".1.3.6.1.4.1.534.10.1.3.1.1.1.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "input.2.id", 0, 1, ".1.3.6.1.4.1.534.10.1.3.1.1.1.2", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.3.1.1.2.1 = INTEGER: 2379 */ - { "input.1.voltage", 0, 0.1, ".1.3.6.1.4.1.534.10.1.3.1.1.2.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "input.1.voltage", 0, 0.1, ".1.3.6.1.4.1.534.10.1.3.1.1.2.1", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.3.1.1.2.2 = INTEGER: 0 */ - { "input.2.voltage", 0, 0.1, ".1.3.6.1.4.1.534.10.1.3.1.1.2.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "input.2.voltage", 0, 0.1, ".1.3.6.1.4.1.534.10.1.3.1.1.2.2", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.3.1.1.3.1 = INTEGER: 500 */ - { "input.1.frequency", 0, 0.1, ".1.3.6.1.4.1.534.10.1.3.1.1.3.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "input.1.frequency", 0, 0.1, ".1.3.6.1.4.1.534.10.1.3.1.1.3.1", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.3.1.1.3.2 = INTEGER: 0 */ - { "input.2.frequency", 0, 0.1, ".1.3.6.1.4.1.534.10.1.3.1.1.3.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "input.2.frequency", 0, 0.1, ".1.3.6.1.4.1.534.10.1.3.1.1.3.2", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.3.2.1.0 = INTEGER: 2375 */ - { "output.voltage", 0, 0.1, ".1.3.6.1.4.1.534.10.1.3.2.1.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "output.voltage", 0, 0.1, ".1.3.6.1.4.1.534.10.1.3.2.1.0", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.3.2.2.0 = INTEGER: 0 */ - { "output.current", 0, 0.1, ".1.3.6.1.4.1.534.10.1.3.2.2.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "output.current", 0, 0.1, ".1.3.6.1.4.1.534.10.1.3.2.2.0", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.3.3.0 = INTEGER: 25 -- internal temperature in celsius */ - { "ups.temperature", 0, 1, ".1.3.6.1.4.1.534.10.1.3.3.0", NULL, SU_FLAG_OK, NULL, NULL }, - /* enterprises.534.10.1.3.4.0 = INTEGER: 77 -- internal temperature in farenhait */ - /* { "ups.temperetureF", 0, 1, ".1.3.6.1.4.1.534.10.1.3.4.0", NULL, SU_FLAG_OK, NULL, NULL }, */ + { "ups.temperature", 0, 1, ".1.3.6.1.4.1.534.10.1.3.3.0", NULL, SU_FLAG_OK, NULL }, + /* enterprises.534.10.1.3.4.0 = INTEGER: 77 -- internal temperature in fahrenheit */ + /* { "ups.temperatureF", 0, 1, ".1.3.6.1.4.1.534.10.1.3.4.0", NULL, SU_FLAG_OK, NULL }, */ /* enterprises.534.10.1.3.5.0 = INTEGER: 37937541 */ - { "device.uptime", 0, 1, ".1.3.6.1.4.1.534.10.1.3.5.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "device.uptime", 0, 1, ".1.3.6.1.4.1.534.10.1.3.5.0", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.3.6.0 = INTEGER: 284 */ - /* { "unmapped.atsMessureTransferedTimes", 0, 1, ".1.3.6.1.4.1.534.10.1.3.6.0", NULL, SU_FLAG_OK, NULL, NULL }, */ + /* { "unmapped.atsMessureTransferedTimes", 0, 1, ".1.3.6.1.4.1.534.10.1.3.6.0", NULL, SU_FLAG_OK, NULL }, */ /* enterprises.534.10.1.3.7.0 = INTEGER: 4 */ - { "input.source", 0, 1, ".1.3.6.1.4.1.534.10.1.3.7.0", NULL, SU_FLAG_OK, eaton_ats30_source_info, NULL }, + { "input.source", 0, 1, ".1.3.6.1.4.1.534.10.1.3.7.0", NULL, SU_FLAG_OK, eaton_ats30_source_info }, /* atsStatus */ /* ========= */ #if 0 /* NOTE: Unused OIDs are left as comments for potential future improvements */ /* enterprises.534.10.1.4.1.0 = INTEGER: 7 */ - { "unmapped.atsInputFlowIndicator", 0, 1, ".1.3.6.1.4.1.534.10.1.4.1.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsInputFlowIndicator", 0, 1, ".1.3.6.1.4.1.534.10.1.4.1.0", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.4.2.1.1.1 = INTEGER: 1 -- atsInputFlowTable start */ - { "unmapped.atsInputFlowIndex.1", 0, 1, ".1.3.6.1.4.1.534.10.1.4.2.1.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsInputFlowIndex.1", 0, 1, ".1.3.6.1.4.1.534.10.1.4.2.1.1.1", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.4.2.1.1.2 = INTEGER: 2 */ - { "unmapped.atsInputFlowIndex.2", 0, 1, ".1.3.6.1.4.1.534.10.1.4.2.1.1.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsInputFlowIndex.2", 0, 1, ".1.3.6.1.4.1.534.10.1.4.2.1.1.2", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.4.2.1.2.1 = INTEGER: 1 */ - { "unmapped.atsInputFlowRelay.1", 0, 1, ".1.3.6.1.4.1.534.10.1.4.2.1.2.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsInputFlowRelay.1", 0, 1, ".1.3.6.1.4.1.534.10.1.4.2.1.2.1", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.4.2.1.2.2 = INTEGER: 2 */ - { "unmapped.atsInputFlowRelay.2", 0, 1, ".1.3.6.1.4.1.534.10.1.4.2.1.2.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsInputFlowRelay.2", 0, 1, ".1.3.6.1.4.1.534.10.1.4.2.1.2.2", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.4.2.1.3.1 = INTEGER: 1 */ - { "unmapped.atsInputFlowSCR.1", 0, 1, ".1.3.6.1.4.1.534.10.1.4.2.1.3.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsInputFlowSCR.1", 0, 1, ".1.3.6.1.4.1.534.10.1.4.2.1.3.1", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.4.2.1.3.2 = INTEGER: 2 */ - { "unmapped.atsInputFlowSCR.2", 0, 1, ".1.3.6.1.4.1.534.10.1.4.2.1.3.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsInputFlowSCR.2", 0, 1, ".1.3.6.1.4.1.534.10.1.4.2.1.3.2", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.4.2.1.4.1 = INTEGER: 1 */ - { "unmapped.atsInputFlowParallelRelay.1", 0, 1, ".1.3.6.1.4.1.534.10.1.4.2.1.4.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsInputFlowParallelRelay.1", 0, 1, ".1.3.6.1.4.1.534.10.1.4.2.1.4.1", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.4.2.1.4.2 = INTEGER: 2 */ - { "unmapped.atsInputFlowParallelRelay.2", 0, 1, ".1.3.6.1.4.1.534.10.1.4.2.1.4.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsInputFlowParallelRelay.2", 0, 1, ".1.3.6.1.4.1.534.10.1.4.2.1.4.2", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.4.3.0 = INTEGER: 58720256 */ - { "unmapped.atsInputFailureIndicator", 0, 1, ".1.3.6.1.4.1.534.10.1.4.3.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsInputFailureIndicator", 0, 1, ".1.3.6.1.4.1.534.10.1.4.3.0", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.4.4.1.1.1 = INTEGER: 1 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.1.1", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.4.4.1.1.2 = INTEGER: 2 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.1.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.1.2", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.4.4.1.2.1 = INTEGER: 2 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.2.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.2.1", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.4.4.1.2.2 = INTEGER: 2 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.2.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.2.2", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.4.4.1.3.1 = INTEGER: 2 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.3.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.3.1", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.4.4.1.3.2 = INTEGER: 2 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.3.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.3.2", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.4.4.1.4.1 = INTEGER: 2 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.4.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.4.1", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.4.4.1.4.2 = INTEGER: 2 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.4.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.4.2", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.4.4.1.5.1 = INTEGER: 2 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.5.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.5.1", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.4.4.1.5.2 = INTEGER: 2 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.5.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.5.2", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.4.4.1.6.1 = INTEGER: 2 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.6.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.6.1", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.4.4.1.6.2 = INTEGER: 2 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.6.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.6.2", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.4.4.1.7.1 = INTEGER: 2 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.7.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.7.1", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.4.4.1.7.2 = INTEGER: 2 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.7.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.7.2", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.4.4.1.8.1 = INTEGER: 2 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.8.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.8.1", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.4.4.1.8.2 = INTEGER: 2 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.8.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.8.2", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.4.4.1.9.1 = INTEGER: 2 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.9.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.9.1", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.4.4.1.9.2 = INTEGER: 1 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.9.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.9.2", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.4.4.1.10.1 = INTEGER: 2 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.10.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.10.1", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.4.4.1.10.2 = INTEGER: 1 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.10.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.10.2", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.4.4.1.11.1 = INTEGER: 2 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.11.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.11.1", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.4.4.1.11.2 = INTEGER: 1 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.11.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.4.1.11.2", NULL, SU_FLAG_OK, NULL }, #endif /* 0 */ /* enterprises.atsFailureIndicator = INTEGER: 0 */ - { "ups.status", 0, 1, ".1.3.6.1.4.1.534.10.1.4.5.0", NULL, SU_FLAG_OK, eaton_ats30_status_info, NULL }, + { "ups.status", 0, 1, ".1.3.6.1.4.1.534.10.1.4.5.0", NULL, SU_FLAG_OK, eaton_ats30_status_info }, #if 0 /* enterprises.534.10.1.4.6.1.0 = INTEGER: 2 -- atsFailure start */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.6.1.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.6.1.0", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.4.6.2.0 = INTEGER: 2 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.6.2.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.6.2.0", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.4.6.3.0 = INTEGER: 2 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.6.3.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.6.3.0", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.4.6.4.0 = INTEGER: 2 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.6.4.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.4.6.4.0", NULL, SU_FLAG_OK, NULL }, #endif /* 0 */ /* atsLog */ @@ -218,150 +219,150 @@ static snmp_info_t eaton_ats30_mib[] = { #if 0 /* We are not interested in log */ /* enterprises.534.10.1.5.1.0 = INTEGER: 272 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.1.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.1.0", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.5.2.1.1.1 = INTEGER: 1 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.1.1", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.5.2.1.1.2 = INTEGER: 2 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.1.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.1.2", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.5.2.1.1.3 = INTEGER: 3 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.1.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.1.3", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.5.2.1.1.4 = INTEGER: 4 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.1.4", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.1.4", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.5.2.1.1.5 = INTEGER: 5 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.1.5", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.1.5", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.5.2.1.1.6 = INTEGER: 6 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.1.6", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.1.6", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.5.2.1.1.7 = INTEGER: 7 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.1.7", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.1.7", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.5.2.1.1.8 = INTEGER: 8 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.1.8", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.1.8", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.5.2.1.1.9 = INTEGER: 9 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.1.9", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.1.9", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.5.2.1.1.10 = INTEGER: 10 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.1.10", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.1.10", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.5.2.1.2.1 = INTEGER: 1482323677 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.2.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.2.1", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.5.2.1.2.2 = INTEGER: 1480076955 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.2.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.2.2", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.5.2.1.2.3 = INTEGER: 1480069128 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.2.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.2.3", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.5.2.1.2.4 = INTEGER: 1480069093 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.2.4", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.2.4", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.5.2.1.2.5 = INTEGER: 1478693745 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.2.5", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.2.5", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.5.2.1.2.6 = INTEGER: 1478693741 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.2.6", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.2.6", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.5.2.1.2.7 = INTEGER: 1466604406 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.2.7", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.2.7", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.5.2.1.2.8 = INTEGER: 1466604386 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.2.8", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.2.8", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.5.2.1.2.9 = INTEGER: 1466604386 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.2.9", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.2.9", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.5.2.1.2.10 = INTEGER: 1463038288 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.2.10", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.2.10", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.5.2.1.3.1 = INTEGER: 41 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.3.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.3.1", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.5.2.1.3.2 = INTEGER: 41 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.3.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.3.2", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.5.2.1.3.3 = INTEGER: 44 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.3.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.3.3", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.5.2.1.3.4 = INTEGER: 44 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.3.4", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.3.4", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.5.2.1.3.5 = INTEGER: 44 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.3.5", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.3.5", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.5.2.1.3.6 = INTEGER: 41 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.3.6", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.3.6", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.5.2.1.3.7 = INTEGER: 41 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.3.7", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.3.7", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.5.2.1.3.8 = INTEGER: 46 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.3.8", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.3.8", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.5.2.1.3.9 = INTEGER: 45 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.3.9", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.3.9", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.5.2.1.3.10 = INTEGER: 41 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.3.10", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.5.2.1.3.10", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.5.2.1.4.1 = STRING: "12:34:37 12/21/2016" */ - { "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.5.2.1.4.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.5.2.1.4.1", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.5.2.1.4.2 = STRING: "12:29:15 11/25/2016" */ - { "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.5.2.1.4.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.5.2.1.4.2", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.5.2.1.4.3 = STRING: "10:18:48 11/25/2016" */ - { "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.5.2.1.4.3", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.5.2.1.4.3", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.5.2.1.4.4 = STRING: "10:18:13 11/25/2016" */ - { "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.5.2.1.4.4", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.5.2.1.4.4", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.5.2.1.4.5 = STRING: "12:15:45 11/09/2016" */ - { "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.5.2.1.4.5", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.5.2.1.4.5", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.5.2.1.4.6 = STRING: "12:15:41 11/09/2016" */ - { "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.5.2.1.4.6", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.5.2.1.4.6", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.5.2.1.4.7 = STRING: "14:06:46 06/22/2016" */ - { "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.5.2.1.4.7", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.5.2.1.4.7", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.5.2.1.4.8 = STRING: "14:06:26 06/22/2016" */ - { "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.5.2.1.4.8", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.5.2.1.4.8", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.5.2.1.4.9 = STRING: "14:06:26 06/22/2016" */ - { "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.5.2.1.4.9", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.5.2.1.4.9", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.5.2.1.4.10 = STRING: "07:31:28 05/12/2016" */ - { "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.5.2.1.4.10", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.5.2.1.4.10", NULL, SU_FLAG_OK, NULL }, #endif /* 0 */ /* atsConfig */ /* ========= */ #if 0 /* enterprises.534.10.1.6.1.1.0 = INTEGER: 538562409 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.1.1.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.1.1.0", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.6.1.2.0 = STRING: "01/24/2017" */ - { "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.6.1.2.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.6.1.2.0", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.6.1.3.0 = STRING: "08:40:09" */ - { "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.6.1.3.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.10.1.6.1.3.0", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.6.2.1.1.1 = INTEGER: 1 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.2.1.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.2.1.1.1", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.6.2.1.1.2 = INTEGER: 2 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.2.1.1.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.2.1.1.2", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.6.2.1.2.1 = INTEGER: 1700 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.2.1.2.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.2.1.2.1", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.6.2.1.2.2 = INTEGER: 1700 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.2.1.2.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.2.1.2.2", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.6.2.1.3.1 = INTEGER: 1800 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.2.1.3.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.2.1.3.1", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.6.2.1.3.2 = INTEGER: 1800 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.2.1.3.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.2.1.3.2", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.6.2.1.4.1 = INTEGER: 2640 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.2.1.4.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.2.1.4.1", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.6.2.1.4.2 = INTEGER: 2640 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.2.1.4.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.2.1.4.2", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.6.2.1.5.1 = INTEGER: 3000 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.2.1.5.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.2.1.5.1", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.6.2.1.5.2 = INTEGER: 3000 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.2.1.5.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.2.1.5.2", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.6.2.1.6.1 = INTEGER: 50 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.2.1.6.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.2.1.6.1", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.6.2.1.6.2 = INTEGER: 50 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.2.1.6.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.2.1.6.2", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.6.2.1.7.1 = INTEGER: 40 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.2.1.7.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.2.1.7.1", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.6.2.1.7.2 = INTEGER: 40 */ - { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.2.1.7.2", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.6.2.1.7.2", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.6.3.0 = INTEGER: 2640 */ - { "unmapped.atsConfigInputVoltageRating", 0, 1, ".1.3.6.1.4.1.534.10.1.6.3.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsConfigInputVoltageRating", 0, 1, ".1.3.6.1.4.1.534.10.1.6.3.0", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.6.4.0 = INTEGER: 26 */ - { "unmapped.atsConfigRandomTime", 0, 1, ".1.3.6.1.4.1.534.10.1.6.4.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "unmapped.atsConfigRandomTime", 0, 1, ".1.3.6.1.4.1.534.10.1.6.4.0", NULL, SU_FLAG_OK, NULL }, #endif /* 0 */ /* enterprises.534.10.1.6.5.0 = INTEGER: 1 */ - { "input.source.preferred", ST_FLAG_RW, 1, ".1.3.6.1.4.1.534.10.1.6.5.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "input.source.preferred", ST_FLAG_RW, 1, ".1.3.6.1.4.1.534.10.1.6.5.0", NULL, SU_FLAG_OK, NULL }, /* enterprises.534.10.1.6.6.0 = INTEGER: 2 */ - { "input.sensitivity", ST_FLAG_RW, 1, ".1.3.6.1.4.1.534.10.1.6.6.0", NULL, SU_FLAG_OK, eaton_ats30_input_sensitivity, NULL }, + { "input.sensitivity", ST_FLAG_RW, 1, ".1.3.6.1.4.1.534.10.1.6.6.0", NULL, SU_FLAG_OK, eaton_ats30_input_sensitivity }, /* enterprises.534.10.1.6.7.0 = INTEGER: 2 */ - /* { "unmapped.atsConfigTest", 0, 1, ".1.3.6.1.4.1.534.10.1.6.7.0", NULL, SU_FLAG_OK, NULL, NULL }, */ + /* { "unmapped.atsConfigTest", 0, 1, ".1.3.6.1.4.1.534.10.1.6.7.0", NULL, SU_FLAG_OK, NULL }, */ /* atsUpgrade */ /* ========== */ #if 0 /* We are not interested in atsUpgrade */ /* enterprises.534.10.1.7.1.0 = INTEGER: 1 */ - /* { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.7.1.0", NULL, SU_FLAG_OK, NULL, NULL }, */ + /* { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.7.1.0", NULL, SU_FLAG_OK, NULL }, */ /* enterprises.534.10.1.7.2.0 = INTEGER: 1 */ - /* { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.7.2.0", NULL, SU_FLAG_OK, NULL, NULL }, */ + /* { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.7.2.0", NULL, SU_FLAG_OK, NULL }, */ /* enterprises.534.10.1.7.3.0 = INTEGER: 0 */ - /* { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.7.3.0", NULL, SU_FLAG_OK, NULL, NULL }, */ + /* { "unmapped.enterprises", 0, 1, ".1.3.6.1.4.1.534.10.1.7.3.0", NULL, SU_FLAG_OK, NULL }, */ #endif /* 0 */ /* end of structure. */ diff --git a/drivers/eaton-pdu-genesis2-mib.c b/drivers/eaton-pdu-genesis2-mib.c index ae6037e609..80063f7459 100644 --- a/drivers/eaton-pdu-genesis2-mib.c +++ b/drivers/eaton-pdu-genesis2-mib.c @@ -1,7 +1,7 @@ /* eaton-pdu-genesis2-mib.c - data to monitor Eaton ePDUs branded as: * G1 Aphel based ePDUs (Basic) - GenesisII * - * Copyright (C) 2008 - 2017 + * Copyright (C) 2008 - 2019 * Arnaud Quette * Arnaud Quette * Copyright (C) 2015 - 2017 @@ -29,7 +29,7 @@ #include "eaton-pdu-genesis2-mib.h" -#define EATON_APHEL_GENESIS2_MIB_VERSION "0.49" +#define EATON_APHEL_GENESIS2_MIB_VERSION "0.50" /* APHEL-GENESIS-II-MIB (monitored ePDU) * ************************************* @@ -50,39 +50,39 @@ static snmp_info_t eaton_aphel_genesisII_mib[] = { /* Device page */ { "device.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "EATON | Powerware", - SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL }, + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, { "device.model", ST_FLAG_STRING, SU_INFOSIZE, APHEL1_OID_MODEL_NAME, - "Eaton Powerware ePDU Monitored", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + "Eaton Powerware ePDU Monitored", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, { "device.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "pdu", - SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL }, + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, { "device.macaddr", ST_FLAG_STRING, SU_INFOSIZE, APHEL1_OID_UNIT_MACADDR, "unknown", - 0, NULL, NULL }, + 0, NULL }, /* UPS page */ { "ups.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "EATON | Powerware", - SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL }, + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, { "ups.model", ST_FLAG_STRING, SU_INFOSIZE, APHEL1_OID_MODEL_NAME, - "Generic SNMP PDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + "Generic SNMP PDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, { "ups.id", ST_FLAG_STRING, SU_INFOSIZE, APHEL1_OID_DEVICE_NAME, - "unknown", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + "unknown", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, { "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, APHEL1_OID_FIRMREV, "", - SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + SU_FLAG_STATIC | SU_FLAG_OK, NULL }, { "ups.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "pdu", - SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL }, + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, /* Outlet page */ /* we can't use template since there is no counterpart to outlet.count */ - { "outlet.1.current", 0, 0.1, APHEL1_OID_OUTLET_CURRENT ".1.0", NULL, SU_FLAG_NEGINVALID, NULL, NULL }, - { "outlet.2.current", 0, 0.1, APHEL1_OID_OUTLET_CURRENT ".2.0", NULL, SU_FLAG_NEGINVALID, NULL, NULL }, - { "outlet.3.current", 0, 0.1, APHEL1_OID_OUTLET_CURRENT ".3.0", NULL, SU_FLAG_NEGINVALID, NULL, NULL }, - { "outlet.4.current", 0, 0.1, APHEL1_OID_OUTLET_CURRENT ".4.0", NULL, SU_FLAG_NEGINVALID, NULL, NULL }, - { "outlet.5.current", 0, 0.1, APHEL1_OID_OUTLET_CURRENT ".5.0", NULL, SU_FLAG_NEGINVALID, NULL, NULL }, - { "outlet.6.current", 0, 0.1, APHEL1_OID_OUTLET_CURRENT ".6.0", NULL, SU_FLAG_NEGINVALID, NULL, NULL }, - { "outlet.7.current", 0, 0.1, APHEL1_OID_OUTLET_CURRENT ".7.0", NULL, SU_FLAG_NEGINVALID, NULL, NULL }, - { "outlet.8.current", 0, 0.1, APHEL1_OID_OUTLET_CURRENT ".8.0", NULL, SU_FLAG_NEGINVALID, NULL, NULL }, + { "outlet.1.current", 0, 0.1, APHEL1_OID_OUTLET_CURRENT ".1.0", NULL, SU_FLAG_NEGINVALID, NULL }, + { "outlet.2.current", 0, 0.1, APHEL1_OID_OUTLET_CURRENT ".2.0", NULL, SU_FLAG_NEGINVALID, NULL }, + { "outlet.3.current", 0, 0.1, APHEL1_OID_OUTLET_CURRENT ".3.0", NULL, SU_FLAG_NEGINVALID, NULL }, + { "outlet.4.current", 0, 0.1, APHEL1_OID_OUTLET_CURRENT ".4.0", NULL, SU_FLAG_NEGINVALID, NULL }, + { "outlet.5.current", 0, 0.1, APHEL1_OID_OUTLET_CURRENT ".5.0", NULL, SU_FLAG_NEGINVALID, NULL }, + { "outlet.6.current", 0, 0.1, APHEL1_OID_OUTLET_CURRENT ".6.0", NULL, SU_FLAG_NEGINVALID, NULL }, + { "outlet.7.current", 0, 0.1, APHEL1_OID_OUTLET_CURRENT ".7.0", NULL, SU_FLAG_NEGINVALID, NULL }, + { "outlet.8.current", 0, 0.1, APHEL1_OID_OUTLET_CURRENT ".8.0", NULL, SU_FLAG_NEGINVALID, NULL }, /* end of structure. */ - { NULL, 0, 0, NULL, NULL, 0, NULL, NULL } + { NULL, 0, 0, NULL, NULL, 0, NULL } }; diff --git a/drivers/eaton-pdu-marlin-mib.c b/drivers/eaton-pdu-marlin-mib.c index de943679fd..1b55250e10 100644 --- a/drivers/eaton-pdu-marlin-mib.c +++ b/drivers/eaton-pdu-marlin-mib.c @@ -2,7 +2,7 @@ * G2 Marlin SW / MI / MO / MA * G3 Shark SW / MI / MO / MA * - * Copyright (C) 2008 - 2017 + * Copyright (C) 2008 - 2019 * Arnaud Quette * Arnaud Quette * Copyright (C) 2015 - 2017 @@ -34,7 +34,7 @@ /* Eaton PDU-MIB - Marlin MIB * ************************** */ -#define EATON_MARLIN_MIB_VERSION "0.44" +#define EATON_MARLIN_MIB_VERSION "0.47" #define EATON_MARLIN_SYSOID ".1.3.6.1.4.1.534.6.6.7" #define EATON_MARLIN_OID_MODEL_NAME ".1.3.6.1.4.1.534.6.6.7.1.2.1.2.0" @@ -209,55 +209,56 @@ static snmp_info_t eaton_marlin_mib[] = { /* Device collection */ { "device.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "EATON", - SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL }, + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, { "device.model", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.1.2.1.2.%i", - "Eaton Powerware ePDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + "Eaton Powerware ePDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, { "device.serial", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.1.2.1.4.%i", - "", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + "", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, { "device.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "pdu", - SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL }, + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, { "device.part", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.1.2.1.3.%i", - "", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + "", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, /* For daisychain, there is only 1 physical interface! */ { "device.macaddr", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.2.1.2.2.1.6.2", - "", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + "", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, /* Daisychained devices support * Notes: this definition is used to: * - estimate the number of devices, based on the below OID iteration capabilities * - determine the base index of the SNMP OID (ie 0 or 1) */ { "device.count", 0, 1, ".1.3.6.1.4.1.534.6.6.7.1.2.1.2.%i", - "1", SU_FLAG_STATIC, NULL, NULL /* devices_count */ }, + "1", SU_FLAG_STATIC, NULL }, /* UPS collection */ { "ups.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "EATON", - SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL }, + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, { "ups.model", ST_FLAG_STRING, SU_INFOSIZE, "1.3.6.1.4.1.534.6.6.7.1.2.1.2.%i", - "Eaton Powerware ePDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + "Eaton Powerware ePDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, /* FIXME: use unitName.0 (ePDU)? * { "ups.id", ST_FLAG_STRING, SU_INFOSIZE, AR_OID_DEVICE_NAME, - "unknown", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, */ + "unknown", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, */ { "ups.serial", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.1.2.1.4.%i", - "", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + "", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, + /* FIXME: this entry should be SU_FLAG_SEMI_STATIC */ { "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.1.2.1.5.%i", - "", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, + "", SU_FLAG_OK, NULL }, { "ups.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "pdu", - SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL }, + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, /* FIXME: needs a date reformating callback * 2011-8-29,16:27:25.0,+1:0 * Hex-STRING: 07 DB 08 1D 10 0C 36 00 2B 01 00 00 * { "ups.date", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.1.2.1.8.0", - "", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + "", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, * { "ups.time", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.1.2.1.8.0", - "", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + "", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, */ /* Input collection */ @@ -267,34 +268,34 @@ static snmp_info_t eaton_marlin_mib[] = { */ /* Note: the below gives the number of input, not the number of phase(s)! */ /* inputCount.0; Value (Integer): 1 - { "input.phases", 0, 1, ".1.3.6.1.4.1.534.6.6.7.1.2.1.20.0", - NULL, SU_FLAG_STATIC | SU_FLAG_SETINT, NULL, &input_phases }, */ + { "input.count", 0, 1, ".1.3.6.1.4.1.534.6.6.7.1.2.1.20.0", + NULL, SU_FLAG_STATIC, NULL }, */ /* Note: for daisychain mode, we must handle phase(s) per device, not as a whole */ /* inputType.%i.1 = INTEGER: singlePhase (1) */ { "input.phases", 0, 1, ".1.3.6.1.4.1.534.6.6.7.3.1.1.2.%i.1", - NULL, SU_FLAG_STATIC, &marlin_input_type_info[0], NULL }, + NULL, SU_FLAG_STATIC, &marlin_input_type_info[0] }, /* Frequency is measured globally */ { "input.frequency", 0, 0.1, ".1.3.6.1.4.1.534.6.6.7.3.1.1.3.%i.1", - NULL, 0, NULL, NULL }, + NULL, 0, NULL }, { "input.frequency.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.3.1.1.4.%i.1", - NULL, SU_FLAG_OK, &marlin_threshold_frequency_status_info[0], NULL }, + NULL, SU_FLAG_OK, &marlin_threshold_frequency_status_info[0] }, { "ups.alarm", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.3.1.1.4.%i.1", - NULL, SU_FLAG_OK, &marlin_threshold_frequency_alarm_info[0], NULL }, + NULL, SU_FLAG_OK, &marlin_threshold_frequency_alarm_info[0] }, /* inputCurrentPercentLoad (measured globally) * Current percent load, based on the rated current capacity */ /* FIXME: input.load is mapped on input.L1.load for both single and 3phase !!! */ { "input.load", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.3.3.1.11.%i.1.1", - NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, { "input.L1.load", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.3.3.1.11.%i.1.1", - NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, { "input.L2.load", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.3.3.1.11.%i.1.2", - NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, { "input.L3.load", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.3.3.1.11.%i.1.3", - NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, /* FIXME: * - Voltage is only measured per phase, as mV! @@ -305,302 +306,302 @@ static snmp_info_t eaton_marlin_mib[] = { * INTEGER {singlePhase (1),phase1toN (2),phase2toN (3),phase3toN (4),phase1to2 (5),phase2to3 (6),phase3to1 (7) * => RFC input.Lx.voltage.context */ { "input.voltage", 0, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.2.1.3.%i.1.1", - NULL, 0, NULL, NULL }, + NULL, 0, NULL }, { "input.voltage.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.3.2.1.4.%i.1.1", - NULL, SU_FLAG_OK, &marlin_threshold_status_info[0], NULL }, + NULL, SU_FLAG_OK, &marlin_threshold_status_info[0] }, { "ups.alarm", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.3.2.1.4.%i.1.1", - NULL, SU_FLAG_OK, &marlin_threshold_voltage_alarms_info[0], NULL }, + NULL, SU_FLAG_OK, &marlin_threshold_voltage_alarms_info[0] }, { "input.voltage.low.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.2.1.5.%i.1.1", - NULL, SU_FLAG_NEGINVALID, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID, NULL }, { "input.voltage.low.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.2.1.6.%i.1.1", - NULL, SU_FLAG_NEGINVALID, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID, NULL }, { "input.voltage.high.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.2.1.7.%i.1.1", - NULL, SU_FLAG_NEGINVALID, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID, NULL }, { "input.voltage.high.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.2.1.8.%i.1.1", - NULL, SU_FLAG_NEGINVALID, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID, NULL }, { "input.L1.voltage", 0, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.2.1.3.%i.1.1", - NULL, 0, NULL, NULL }, + NULL, 0, NULL }, { "input.L1.voltage.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.3.2.1.4.%i.1.1", - NULL, SU_FLAG_OK, &marlin_threshold_status_info[0], NULL }, + NULL, SU_FLAG_OK, &marlin_threshold_status_info[0] }, { "L1.alarm", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.3.2.1.4.%i.1.1", - NULL, SU_FLAG_OK, &marlin_threshold_voltage_alarms_info[0], NULL }, + NULL, SU_FLAG_OK, &marlin_threshold_voltage_alarms_info[0] }, { "input.L1.voltage.low.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.2.1.5.%i.1.1", - NULL, SU_FLAG_NEGINVALID, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID, NULL }, { "input.L1.voltage.low.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.2.1.6.%i.1.1", - NULL, SU_FLAG_NEGINVALID, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID, NULL }, { "input.L1.voltage.high.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.2.1.7.%i.1.1", - NULL, SU_FLAG_NEGINVALID, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID, NULL }, { "input.L1.voltage.high.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.2.1.8.%i.1.1", - NULL, SU_FLAG_NEGINVALID, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID, NULL }, { "input.L2.voltage", 0, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.2.1.3.%i.1.2", - NULL, 0, NULL, NULL }, + NULL, 0, NULL }, { "input.L2.voltage.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.3.2.1.4.%i.1.2", - NULL, SU_FLAG_OK, &marlin_threshold_status_info[0], NULL }, + NULL, SU_FLAG_OK, &marlin_threshold_status_info[0] }, { "L2.alarm", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.3.2.1.4.%i.1.2", - NULL, SU_FLAG_OK, &marlin_threshold_voltage_alarms_info[0], NULL }, + NULL, SU_FLAG_OK, &marlin_threshold_voltage_alarms_info[0] }, { "input.L2.voltage.low.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.2.1.5.%i.1.2", - NULL, SU_FLAG_NEGINVALID, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID, NULL }, { "input.L2.voltage.low.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.2.1.6.%i.1.2", - NULL, SU_FLAG_NEGINVALID, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID, NULL }, { "input.L2.voltage.high.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.2.1.7.%i.1.2", - NULL, SU_FLAG_NEGINVALID, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID, NULL }, { "input.L2.voltage.high.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.2.1.8.%i.1.2", - NULL, SU_FLAG_NEGINVALID, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID, NULL }, { "input.L3.voltage", 0, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.2.1.3.%i.1.3", - NULL, 0, NULL, NULL }, + NULL, 0, NULL }, { "input.L3.voltage.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.3.2.1.4.%i.1.3", - NULL, SU_FLAG_OK, &marlin_threshold_status_info[0], NULL }, + NULL, SU_FLAG_OK, &marlin_threshold_status_info[0] }, { "L3.alarm", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.3.2.1.4.%i.1.3", - NULL, SU_FLAG_OK, &marlin_threshold_voltage_alarms_info[0], NULL }, + NULL, SU_FLAG_OK, &marlin_threshold_voltage_alarms_info[0] }, { "input.L3.voltage.low.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.2.1.5.%i.1.3", - NULL, SU_FLAG_NEGINVALID, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID, NULL }, { "input.L3.voltage.low.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.2.1.6.%i.1.3", - NULL, SU_FLAG_NEGINVALID, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID, NULL }, { "input.L3.voltage.high.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.2.1.7.%i.1.3", - NULL, SU_FLAG_NEGINVALID, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID, NULL }, { "input.L3.voltage.high.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.2.1.8.%i.1.3", - NULL, SU_FLAG_NEGINVALID, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID, NULL }, /* FIXME: * - input.current is mapped on input.L1.current for both single and 3phase !!! */ { "input.current", 0, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.4.%i.1.1", - NULL, 0, NULL, NULL }, + NULL, 0, NULL }, { "input.current.nominal", 0, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.3.%i.1.1", - NULL, 0, NULL, NULL }, + NULL, 0, NULL }, { "input.current.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.3.3.1.5.%i.1.1", - NULL, SU_FLAG_OK, &marlin_threshold_status_info[0], NULL }, + NULL, SU_FLAG_OK, &marlin_threshold_status_info[0] }, { "ups.alarm", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.3.3.1.5.%i.1.1", - NULL, SU_FLAG_OK, &marlin_threshold_current_alarms_info[0], NULL }, + NULL, SU_FLAG_OK, &marlin_threshold_current_alarms_info[0] }, { "input.current.low.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.6.%i.1.1", - NULL, SU_FLAG_NEGINVALID, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID, NULL }, { "input.current.low.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.7.%i.1.1", - NULL, SU_FLAG_NEGINVALID, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID, NULL }, { "input.current.high.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.8.%i.1.1", - NULL, SU_FLAG_NEGINVALID, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID, NULL }, { "input.current.high.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.9.%i.1.1", - NULL, SU_FLAG_NEGINVALID, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID, NULL }, { "input.L1.current", 0, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.4.0.1.1", - NULL, 0, NULL, NULL }, + NULL, 0, NULL }, { "input.L1.current.nominal", 0, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.3.%i.1.1", - NULL, 0, NULL, NULL }, + NULL, 0, NULL }, { "input.L1.current.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.3.3.1.5.%i.1.1", - NULL, SU_FLAG_OK, &marlin_threshold_status_info[0], NULL }, + NULL, SU_FLAG_OK, &marlin_threshold_status_info[0] }, { "L1.alarm", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.3.3.1.5.%i.1.1", - NULL, SU_FLAG_OK, &marlin_threshold_current_alarms_info[0], NULL }, + NULL, SU_FLAG_OK, &marlin_threshold_current_alarms_info[0] }, { "input.L1.current.low.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.6.%i.1.1", - NULL, SU_FLAG_NEGINVALID, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID, NULL }, { "input.L1.current.low.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.7.%i.1.1", - NULL, SU_FLAG_NEGINVALID, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID, NULL }, { "input.L1.current.high.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.8.%i.1.1", - NULL, SU_FLAG_NEGINVALID, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID, NULL }, { "input.L1.current.high.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.9.%i.1.1", - NULL, SU_FLAG_NEGINVALID, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID, NULL }, { "input.L2.current", 0, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.4.%i.1.2", - NULL, 0, NULL, NULL }, + NULL, 0, NULL }, { "input.L2.current.nominal", 0, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.3.%i.1.2", - NULL, 0, NULL, NULL }, + NULL, 0, NULL }, { "input.L2.current.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.3.3.1.5.%i.1.2", - NULL, SU_FLAG_OK, &marlin_threshold_status_info[0], NULL }, + NULL, SU_FLAG_OK, &marlin_threshold_status_info[0] }, { "L2.alarm", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.3.3.1.5.%i.1.2", - NULL, SU_FLAG_OK, &marlin_threshold_current_alarms_info[0], NULL }, + NULL, SU_FLAG_OK, &marlin_threshold_current_alarms_info[0] }, { "input.L2.current.low.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.6.%i.1.2", - NULL, SU_FLAG_NEGINVALID, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID, NULL }, { "input.L2.current.low.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.7.%i.1.2", - NULL, SU_FLAG_NEGINVALID, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID, NULL }, { "input.L2.current.high.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.8.%i.1.2", - NULL, SU_FLAG_NEGINVALID, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID, NULL }, { "input.L2.current.high.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.9.%i.1.2", - NULL, SU_FLAG_NEGINVALID, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID, NULL }, { "input.L3.current", 0, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.4.%i.1.3", - NULL, 0, NULL, NULL }, + NULL, 0, NULL }, { "input.L3.current.nominal", 0, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.3.%i.1.3", - NULL, 0, NULL, NULL }, + NULL, 0, NULL }, { "input.L3.current.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.3.3.1.5.%i.1.3", - NULL, SU_FLAG_OK, &marlin_threshold_status_info[0], NULL }, + NULL, SU_FLAG_OK, &marlin_threshold_status_info[0] }, { "L3.alarm", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.3.3.1.5.%i.1.3", - NULL, SU_FLAG_OK, &marlin_threshold_current_alarms_info[0], NULL }, + NULL, SU_FLAG_OK, &marlin_threshold_current_alarms_info[0] }, { "input.L3.current.low.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.6.%i.1.3", - NULL, SU_FLAG_NEGINVALID, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID, NULL }, { "input.L3.current.low.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.7.%i.1.3", - NULL, SU_FLAG_NEGINVALID, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID, NULL }, { "input.L3.current.high.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.8.%i.1.3", - NULL, SU_FLAG_NEGINVALID, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID, NULL }, { "input.L3.current.high.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.3.1.9.%i.1.3", - NULL, SU_FLAG_NEGINVALID, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID, NULL }, /* Sum of all phases realpower, valid for Shark 1ph/3ph only */ { "input.realpower", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.3.5.1.4.%i.1", - NULL, SU_FLAG_NEGINVALID | SU_FLAG_UNIQUE | SU_FLAG_OK, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_FLAG_UNIQUE | SU_FLAG_OK, NULL }, /* Fallback 1: Sum of all phases realpower, valid for Marlin 3ph only */ { "input.realpower", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.3.4.1.4.%i.1.4", - NULL, SU_FLAG_NEGINVALID | SU_FLAG_UNIQUE | SU_FLAG_OK, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_FLAG_UNIQUE | SU_FLAG_OK, NULL }, /* Fallback 2: Sum of the phase realpower, valid for Marlin 1ph only */ { "input.realpower", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.3.4.1.4.%i.1.2", - NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, { "input.L1.realpower", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.3.4.1.4.%i.1.1", - NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, { "input.L2.realpower", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.3.4.1.4.%i.1.2", - NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, { "input.L3.realpower", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.3.4.1.4.%i.1.3", - NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, /* Sum of all phases apparent power, valid for Shark 1ph/3ph only */ { "input.power", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.3.5.1.3.%i.1", - NULL, SU_FLAG_NEGINVALID | SU_FLAG_UNIQUE | SU_FLAG_OK, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_FLAG_UNIQUE | SU_FLAG_OK, NULL }, /* Fallback 1: Sum of all phases realpower, valid for Marlin 3ph only */ { "input.power", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.3.4.1.3.%i.1.4", - NULL, SU_FLAG_NEGINVALID | SU_FLAG_UNIQUE | SU_FLAG_OK, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_FLAG_UNIQUE | SU_FLAG_OK, NULL }, /* Fallback 2: Sum of the phase realpower, valid for Marlin 1ph only */ { "input.power", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.3.4.1.3.%i.1.2", - NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, { "input.L1.power", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.3.4.1.3.%i.1.1", - NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, { "input.L2.power", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.3.4.1.3.%i.1.2", - NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, { "input.L3.power", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.3.4.1.3.%i.1.3", - NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, /* Ambient collection */ { "ambient.present", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.7.1.1.3.%i.1", - NULL, SU_FLAG_OK, &marlin_ambient_presence_info[0], NULL }, + NULL, SU_FLAG_OK, &marlin_ambient_presence_info[0] }, { "ambient.temperature.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.7.1.1.5.%i.1", - NULL, SU_FLAG_OK, &marlin_threshold_status_info[0], NULL }, + NULL, SU_FLAG_OK, &marlin_threshold_status_info[0] }, { "ups.alarm", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.7.1.1.5.%i.1", - NULL, SU_FLAG_OK, &marlin_threshold_temperature_alarms_info[0], NULL }, + NULL, SU_FLAG_OK, &marlin_threshold_temperature_alarms_info[0] }, { "ambient.temperature", 0, 0.1, ".1.3.6.1.4.1.534.6.6.7.7.1.1.4.%i.1", - NULL, SU_FLAG_OK, NULL, NULL }, + NULL, SU_FLAG_OK, NULL }, /* Low and high threshold use the respective critical levels */ { "ambient.temperature.low", ST_FLAG_RW, 0.1, ".1.3.6.1.4.1.534.6.6.7.7.1.1.7.%i.1", - NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, { "ambient.temperature.low.critical", ST_FLAG_RW, 0.1, ".1.3.6.1.4.1.534.6.6.7.7.1.1.7.%i.1", - NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, { "ambient.temperature.low.warning", ST_FLAG_RW, 0.1, ".1.3.6.1.4.1.534.6.6.7.7.1.1.6.%i.1", - NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, { "ambient.temperature.high", ST_FLAG_RW, 0.1, ".1.3.6.1.4.1.534.6.6.7.7.1.1.9.%i.1", - NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, { "ambient.temperature.high.warning", ST_FLAG_RW, 0.1, ".1.3.6.1.4.1.534.6.6.7.7.1.1.8.%i.1", - NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, { "ambient.temperature.high.critical", ST_FLAG_RW, 0.1, ".1.3.6.1.4.1.534.6.6.7.7.1.1.9.%i.1", - NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, { "ambient.humidity.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.7.2.1.5.%i.1", - NULL, SU_FLAG_OK, &marlin_threshold_status_info[0], NULL }, + NULL, SU_FLAG_OK, &marlin_threshold_status_info[0] }, { "ups.alarm", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.7.2.1.5.%i.1", - NULL, SU_FLAG_OK, &marlin_threshold_humidity_alarms_info[0], NULL }, + NULL, SU_FLAG_OK, &marlin_threshold_humidity_alarms_info[0] }, { "ambient.humidity", 0, 0.1, ".1.3.6.1.4.1.534.6.6.7.7.2.1.4.%i.1", - NULL, SU_FLAG_OK, NULL, NULL }, + NULL, SU_FLAG_OK, NULL }, /* Low and high threshold use the respective critical levels */ { "ambient.humidity.low", ST_FLAG_RW, 0.1, ".1.3.6.1.4.1.534.6.6.7.7.2.1.7.%i.1", - NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, { "ambient.humidity.low.warning", ST_FLAG_RW, 0.1, ".1.3.6.1.4.1.534.6.6.7.7.2.1.6.%i.1", - NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, { "ambient.humidity.low.critical", ST_FLAG_RW, 0.1, ".1.3.6.1.4.1.534.6.6.7.7.2.1.7.%i.1", - NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, { "ambient.humidity.high", ST_FLAG_RW, 0.1, ".1.3.6.1.4.1.534.6.6.7.7.2.1.9.%i.1", NULL, - SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL }, + SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, { "ambient.humidity.high.warning", ST_FLAG_RW, 0.1, ".1.3.6.1.4.1.534.6.6.7.7.2.1.8.%i.1", - NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, { "ambient.humidity.high.critical", ST_FLAG_RW, 0.1, ".1.3.6.1.4.1.534.6.6.7.7.2.1.9.%i.1", - NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, /* Dry contacts on TH module */ { "ambient.contacts.1.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.7.3.1.4.%i.1", - NULL, SU_FLAG_OK, &marlin_ambient_drycontacts_info[0], NULL }, + NULL, SU_FLAG_OK, &marlin_ambient_drycontacts_info[0] }, { "ambient.contacts.2.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.7.3.1.4.%i.2", - NULL, SU_FLAG_OK, &marlin_ambient_drycontacts_info[0], NULL }, + NULL, SU_FLAG_OK, &marlin_ambient_drycontacts_info[0] }, /* Outlet collection */ + { "outlet.count", 0, 1, ".1.3.6.1.4.1.534.6.6.7.1.2.1.22.%i", + "0", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, { "outlet.id", 0, 1, NULL, - "0", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL }, + "0", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, { "outlet.desc", ST_FLAG_RW | ST_FLAG_STRING, 20, NULL, "All outlets", - SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL }, - { "outlet.count", 0, 1, ".1.3.6.1.4.1.534.6.6.7.1.2.1.22.%i", - "0", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, /* The below ones are the same as the input.* equivalent */ /* FIXME: transition period, TO BE REMOVED, moved to input.* */ { "outlet.frequency", 0, 0.1, ".1.3.6.1.4.1.534.6.6.7.3.1.1.3.%i.1", - NULL, 0, NULL, NULL }, + NULL, 0, NULL }, { "outlet.voltage", 0, 0.001, ".1.3.6.1.4.1.534.6.6.7.3.2.1.3.%i.1.1", - NULL, 0, NULL, NULL }, + NULL, 0, NULL }, { "outlet.current", 0, 0.01, ".1.3.6.1.4.1.534.6.6.7.3.3.1.4.%i.1.1", - NULL, 0, NULL, NULL }, + NULL, 0, NULL }, { "outlet.realpower", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.3.4.1.4.%i.1.4", - NULL, 0, NULL, NULL }, + NULL, 0, NULL }, { "outlet.power", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.3.4.1.3.%i.1.4", - NULL, 0, NULL, NULL }, + NULL, 0, NULL }, /* outlet template definition * Indexes start from 1, ie outlet.1 => .1 */ @@ -608,106 +609,89 @@ static snmp_info_t eaton_marlin_mib[] = { /* outletName: Outlet friendly name, which can be modified by the user */ { "outlet.%i.desc", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.6.1.1.3.%i.%i", - NULL, SU_FLAG_STATIC | SU_FLAG_OK | SU_OUTLET | SU_TYPE_DAISY_1, - NULL, NULL }, + NULL, SU_FLAG_STATIC | SU_FLAG_OK | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, { "outlet.%i.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.6.6.1.2.%i.%i", - NULL, SU_FLAG_OK | SU_OUTLET | SU_TYPE_DAISY_1, - &marlin_outlet_status_info[0], NULL }, + NULL, SU_FLAG_OK | SU_OUTLET | SU_TYPE_DAISY_1, &marlin_outlet_status_info[0] }, /* Numeric identifier of the outlet, tied to the whole unit */ { "outlet.%i.id", 0, 1, NULL, "%i", - SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK | SU_OUTLET | SU_TYPE_DAISY_1, - NULL, NULL }, + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, /* outletID: Outlet physical name, related to its number in the group * ex: first outlet of the second group (B) is B1 */ { "outlet.%i.name", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.6.1.1.2.%i.%i", - NULL, SU_FLAG_STATIC | SU_FLAG_OK | SU_OUTLET | SU_TYPE_DAISY_1, - NULL, NULL }, + NULL, SU_FLAG_STATIC | SU_FLAG_OK | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, /* FIXME: the last part of the OID gives the group number (i.e. %i.1 means "group 1") * Need to address that, without multiple declaration (%i.%i, SU_OUTLET | SU_OUTLET_GROUP)? */ { "outlet.%i.groupid", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.6.2.1.3.%i.%i.1", - NULL, SU_FLAG_STATIC | SU_FLAG_UNIQUE | SU_OUTLET | SU_TYPE_DAISY_1, - NULL, NULL }, + NULL, SU_FLAG_STATIC | SU_FLAG_UNIQUE | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, { "outlet.%i.groupid", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.6.2.1.3.%i.%i.2", - NULL, SU_FLAG_STATIC | SU_FLAG_UNIQUE | SU_OUTLET | SU_TYPE_DAISY_1, - NULL, NULL }, + NULL, SU_FLAG_STATIC | SU_FLAG_UNIQUE | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, { "outlet.%i.groupid", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.6.2.1.3.%i.%i.3", - NULL, SU_FLAG_STATIC | SU_FLAG_UNIQUE | SU_OUTLET | SU_TYPE_DAISY_1, - NULL, NULL }, + NULL, SU_FLAG_STATIC | SU_FLAG_UNIQUE | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, { "outlet.%i.groupid", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.6.2.1.3.%i.%i.4", - NULL, SU_FLAG_STATIC | SU_FLAG_UNIQUE | SU_OUTLET | SU_TYPE_DAISY_1, - NULL, NULL }, + NULL, SU_FLAG_STATIC | SU_FLAG_UNIQUE | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, { "outlet.%i.groupid", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.6.2.1.3.%i.%i.5", - NULL, SU_FLAG_STATIC | SU_FLAG_UNIQUE | SU_OUTLET | SU_TYPE_DAISY_1, - NULL, NULL }, + NULL, SU_FLAG_STATIC | SU_FLAG_UNIQUE | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, { "outlet.%i.groupid", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.6.2.1.3.%i.%i.6", - NULL, SU_FLAG_STATIC | SU_FLAG_UNIQUE | SU_OUTLET | SU_TYPE_DAISY_1, - NULL, NULL }, + NULL, SU_FLAG_STATIC | SU_FLAG_UNIQUE | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, { "outlet.%i.current", 0, 0.001, ".1.3.6.1.4.1.534.6.6.7.6.4.1.3.%i.%i", - NULL, SU_OUTLET | SU_TYPE_DAISY_1, NULL, NULL }, + NULL, SU_OUTLET | SU_TYPE_DAISY_1, NULL }, { "outlet.%i.current.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.6.4.1.4.%i.%i", - NULL, SU_OUTLET | SU_TYPE_DAISY_1, - &marlin_threshold_status_info[0], NULL }, + NULL, SU_OUTLET | SU_TYPE_DAISY_1, &marlin_threshold_status_info[0] }, { "outlet.%i.alarm", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.6.4.1.4.%i.%i", - NULL, SU_OUTLET | SU_TYPE_DAISY_1, - &marlin_threshold_current_alarms_info[0], NULL }, + NULL, SU_OUTLET | SU_TYPE_DAISY_1, &marlin_threshold_current_alarms_info[0] }, { "outlet.%i.current.low.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.6.4.1.5.%i.%i", - NULL, SU_FLAG_NEGINVALID | SU_OUTLET | SU_TYPE_DAISY_1, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, { "outlet.%i.current.low.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.6.4.1.6.%i.%i", - NULL, SU_FLAG_NEGINVALID | SU_OUTLET | SU_TYPE_DAISY_1, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, { "outlet.%i.current.high.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.6.4.1.7.%i.%i", - NULL, SU_FLAG_NEGINVALID | SU_OUTLET | SU_TYPE_DAISY_1, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, { "outlet.%i.current.high.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.6.4.1.8.%i.%i", - NULL, SU_FLAG_NEGINVALID | SU_OUTLET | SU_TYPE_DAISY_1, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, { "outlet.%i.realpower", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.6.5.1.3.%i.%i", - NULL, SU_OUTLET | SU_TYPE_DAISY_1, NULL, NULL }, + NULL, SU_OUTLET | SU_TYPE_DAISY_1, NULL }, { "outlet.%i.voltage", 0, 0.001, ".1.3.6.1.4.1.534.6.6.7.6.3.1.2.%i.%i", - NULL, SU_OUTLET | SU_TYPE_DAISY_1, NULL, NULL }, + NULL, SU_OUTLET | SU_TYPE_DAISY_1, NULL }, { "outlet.%i.voltage.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.6.3.1.3.%i.%i", - NULL, SU_OUTLET | SU_TYPE_DAISY_1, - &marlin_threshold_status_info[0], NULL }, + NULL, SU_OUTLET | SU_TYPE_DAISY_1, &marlin_threshold_status_info[0] }, { "outlet.%i.alarm", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.6.3.1.3.%i.%i", - NULL, SU_OUTLET | SU_TYPE_DAISY_1, - &marlin_threshold_voltage_alarms_info[0], NULL }, + NULL, SU_OUTLET | SU_TYPE_DAISY_1, &marlin_threshold_voltage_alarms_info[0] }, { "outlet.%i.voltage.low.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.6.3.1.4.%i.%i", - NULL, SU_FLAG_NEGINVALID | SU_OUTLET | SU_TYPE_DAISY_1, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, { "outlet.%i.voltage.low.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.6.3.1.5.%i.%i", - NULL, SU_FLAG_NEGINVALID | SU_OUTLET | SU_TYPE_DAISY_1, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, { "outlet.%i.voltage.high.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.6.3.1.6.%i.%i", - NULL, SU_FLAG_NEGINVALID | SU_OUTLET | SU_TYPE_DAISY_1, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, { "outlet.%i.voltage.high.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.6.3.1.7.%i.%i", - NULL, SU_FLAG_NEGINVALID | SU_OUTLET | SU_TYPE_DAISY_1, NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, { "outlet.%i.power", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.6.5.1.2.%i.%i", - NULL, SU_OUTLET | SU_TYPE_DAISY_1, NULL, NULL }, + NULL, SU_OUTLET | SU_TYPE_DAISY_1, NULL }, /* FIXME: handle non switchable units (only measurements), which do not expose this OID */ { "outlet.%i.switchable", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.6.6.1.3.%i.%i", - "no", SU_FLAG_STATIC | SU_OUTLET | SU_FLAG_OK | SU_TYPE_DAISY_1, - &marlin_outlet_switchability_info[0], NULL }, + "no", SU_FLAG_STATIC | SU_OUTLET | SU_FLAG_OK | SU_TYPE_DAISY_1, &marlin_outlet_switchability_info[0] }, { "outlet.%i.type", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.6.1.1.5.%i.%i", - "unknown", SU_FLAG_STATIC | SU_OUTLET | SU_TYPE_DAISY_1, - &marlin_outlet_type_info[0], NULL }, - + "unknown", SU_FLAG_STATIC | SU_OUTLET | SU_TYPE_DAISY_1, &marlin_outlet_type_info[0] }, /* TODO: handle statistics * outletWh.0.1 @@ -716,118 +700,107 @@ static snmp_info_t eaton_marlin_mib[] = { /* Outlet groups collection */ { "outlet.group.count", 0, 1, ".1.3.6.1.4.1.534.6.6.7.1.2.1.21.%i", - "0", SU_FLAG_STATIC | SU_TYPE_DAISY_1, NULL, NULL }, + "0", SU_FLAG_STATIC | SU_TYPE_DAISY_1, NULL }, /* outlet groups template definition * Indexes start from 1, ie outlet.group.1 => .1 */ /* Note: the first definition is used to determine the base index (ie 0 or 1) */ /* groupID.0.1 = OctetString: A */ { "outlet.group.%i.id", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.5.1.1.2.%i.%i", - NULL, SU_FLAG_STATIC | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL, NULL }, + NULL, SU_FLAG_STATIC | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL }, /* groupName.0.1 = OctetString: Factory Group 1 */ /* FIXME: SU_FLAG_SEMI_STATIC or SU_FLAG_SETTING => refreshed from time to time or upon call to setvar */ { "outlet.group.%i.name", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.5.1.1.3.%i.%i", - NULL, SU_FLAG_STATIC | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL, NULL }, + NULL, SU_FLAG_STATIC | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL }, /* groupType.0.1 = Integer: outletSection (4) */ { "outlet.group.%i.type", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.5.1.1.4.%i.%i", NULL, SU_FLAG_STATIC | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, - &marlin_outlet_group_type_info[0], NULL }, + &marlin_outlet_group_type_info[0] }, { "outlet.group.%i.phase", 0, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.5.1.1.2.%i.%i", NULL, SU_FLAG_STATIC | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, - &marlin_outlet_group_phase_info[0], NULL }, + &marlin_outlet_group_phase_info[0] }, /* groupControlStatus.0.1 = Integer: on (1) */ { "outlet.group.%i.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.5.6.1.2.%i.%i", NULL, SU_FLAG_OK | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, - &marlin_outletgroups_status_info[0], NULL }, + &marlin_outletgroups_status_info[0] }, /* groupChildCount.0.1 = Integer: 12 */ { "outlet.group.%i.count", 0, 1, ".1.3.6.1.4.1.534.6.6.7.5.1.1.6.%i.%i", - NULL, SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL, NULL }, + NULL, SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL }, /* groupVoltage.0.1 = Integer: 243080 */ { "outlet.group.%i.voltage", 0, 0.001, ".1.3.6.1.4.1.534.6.6.7.5.3.1.3.%i.%i", - NULL, SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL, NULL }, + NULL, SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL }, /* groupVoltageThStatus.0.1 = Integer: good (0) */ { "outlet.group.%i.voltage.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.5.3.1.4.%i.%i", NULL, SU_OUTLET_GROUP | SU_TYPE_DAISY_1, - &marlin_threshold_status_info[0], NULL }, + &marlin_threshold_status_info[0] }, { "outlet.group.%i.alarm", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.5.3.1.4.%i.%i", NULL, SU_OUTLET_GROUP | SU_TYPE_DAISY_1, - &marlin_threshold_voltage_alarms_info[0], NULL }, + &marlin_threshold_voltage_alarms_info[0] }, { "outlet.group.%i.voltage.low.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.5.3.1.5.%i.%i", - NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, - NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL }, { "outlet.group.%i.voltage.low.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.5.3.1.6.%i.%i", - NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, - NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL }, { "outlet.group.%i.voltage.high.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.5.3.1.7.%i.%i", - NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, - NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL }, { "outlet.group.%i.voltage.high.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.5.3.1.8.%i.%i", - NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, - NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL }, /* groupCurrent.0.1 = Integer: 0 */ { "outlet.group.%i.current", 0, 0.001, ".1.3.6.1.4.1.534.6.6.7.5.4.1.3.%i.%i", - NULL, SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL, NULL }, + NULL, SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL }, /* groupCurrentCapacity.0.1 = Integer: 16000 */ { "outlet.group.%i.current.nominal", 0, 0.001, ".1.3.6.1.4.1.534.6.6.7.5.4.1.2.%i.%i", - NULL, SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL, NULL }, + NULL, SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL }, /* groupCurrentThStatus.0.1 = Integer: good (0) */ { "outlet.group.%i.current.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.5.4.1.4.%i.%i", NULL, SU_OUTLET_GROUP | SU_TYPE_DAISY_1, - &marlin_threshold_status_info[0], NULL }, + &marlin_threshold_status_info[0] }, { "outlet.group.%i.alarm", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.7.5.4.1.4.%i.%i", NULL, SU_OUTLET_GROUP | SU_TYPE_DAISY_1, - &marlin_threshold_current_alarms_info[0], NULL }, + &marlin_threshold_current_alarms_info[0] }, /* groupCurrentPercentLoad.0.1 = Integer: 0 */ { "outlet.group.%i.load", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.5.4.1.10.%i.%i", - NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, - NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL }, /* groupCurrentThLowerWarning.0.1 = Integer: 0 */ { "outlet.group.%i.current.low.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.5.4.1.5.%i.%i", - NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, - NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL }, /* groupCurrentThLowerCritical.0.1 = Integer: -1 */ { "outlet.group.%i.current.low.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.5.4.1.6.%i.%i", - NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, - NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL }, /* groupCurrentThUpperWarning.0.1 = Integer: 12800 */ { "outlet.group.%i.current.high.warning", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.5.4.1.7.%i.%i", - NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, - NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL }, /* groupCurrentThUpperCritical.0.1 = Integer: 16000 */ { "outlet.group.%i.current.high.critical", ST_FLAG_RW, 0.001, ".1.3.6.1.4.1.534.6.6.7.5.4.1.8.%i.%i", - NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, - NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL }, /* groupWatts.0.1 = Integer: 2670 */ { "outlet.group.%i.realpower", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.5.5.1.3.%i.%i", - NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, - NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL }, /* groupVA.0.1 = Integer: 3132 */ { "outlet.group.%i.power", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.5.5.1.2.%i.%i", - NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, - NULL, NULL }, + NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL }, /* instant commands. */ /* Notes: @@ -844,34 +817,53 @@ static snmp_info_t eaton_marlin_mib[] = { { "outlet.load.cycle", 0, DO_CYCLE, AR_OID_OUTLET_STATUS ".0", NULL, SU_TYPE_CMD, NULL, NULL }, */ - /* TODO: handle delays */ - { "outlet.%i.load.off", 0, 0, ".1.3.6.1.4.1.534.6.6.7.6.6.1.3.%i.%i", - NULL, SU_TYPE_CMD | SU_OUTLET | SU_TYPE_DAISY_1, NULL, NULL }, - { "outlet.%i.load.on", 0, 0, ".1.3.6.1.4.1.534.6.6.7.6.6.1.4.%i.%i", - NULL, SU_TYPE_CMD | SU_OUTLET | SU_TYPE_DAISY_1, NULL, NULL }, - { "outlet.%i.load.cycle", 0, 0, ".1.3.6.1.4.1.534.6.6.7.6.6.1.5.%i.%i", - NULL, SU_TYPE_CMD | SU_OUTLET | SU_TYPE_DAISY_1, NULL, NULL }, - - /* TODO: handle delays + /* Delays handling: + * 0-n :Time in seconds until the group command is issued + * -1:Cancel a pending group-level Off/On/Reboot command */ + { "outlet.%i.load.off", 0, 1, ".1.3.6.1.4.1.534.6.6.7.6.6.1.3.%i.%i", + "0", SU_TYPE_CMD | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, + { "outlet.%i.load.on", 0, 1, ".1.3.6.1.4.1.534.6.6.7.6.6.1.4.%i.%i", + "0", SU_TYPE_CMD | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, + { "outlet.%i.load.cycle", 0, 1, ".1.3.6.1.4.1.534.6.6.7.6.6.1.5.%i.%i", + "0", SU_TYPE_CMD | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, + /* Delayed version, parameter is mandatory (so dfl is NULL)! */ + { "outlet.%i.load.off.delay", 0, 1, ".1.3.6.1.4.1.534.6.6.7.6.6.1.3.%i.%i", + NULL, SU_TYPE_CMD | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, + { "outlet.%i.load.on.delay", 0, 1, ".1.3.6.1.4.1.534.6.6.7.6.6.1.4.%i.%i", + NULL, SU_TYPE_CMD | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, + { "outlet.%i.load.cycle.delay", 0, 1, ".1.3.6.1.4.1.534.6.6.7.6.6.1.5.%i.%i", + NULL, SU_TYPE_CMD | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, + + /* Delays handling: * 0-n :Time in seconds until the group command is issued * -1:Cancel a pending group-level Off/On/Reboot command */ /* groupControlOffCmd.0.1 = Integer: -1 */ - { "outlet.group.%i.load.off", 0, 0, + { "outlet.group.%i.load.off", 0, 1, ".1.3.6.1.4.1.534.6.6.7.5.6.1.3.%i.%i", - NULL, SU_TYPE_CMD | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL, NULL }, + "0", SU_TYPE_CMD | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL }, /* groupControl0nCmd.0.1 = Integer: -1 */ - { "outlet.group.%i.load.on", 0, 0, + { "outlet.group.%i.load.on", 0, 1, ".1.3.6.1.4.1.534.6.6.7.5.6.1.4.%i.%i", - NULL, SU_TYPE_CMD | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL, NULL }, + "0", SU_TYPE_CMD | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL }, /* groupControlRebootCmd.0.1 = Integer: -1 */ - { "outlet.group.%i.load.cycle", 0, 0, + { "outlet.group.%i.load.cycle", 0, 1, ".1.3.6.1.4.1.534.6.6.7.5.6.1.5.%i.%i", - NULL, SU_TYPE_CMD | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL, NULL }, - -// FIXME: miss load.{on,off}.delay + "0", SU_TYPE_CMD | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL }, + /* Delayed version, parameter is mandatory (so dfl is NULL)! */ + { "outlet.group.%i.load.off.delay", 0, 1, + ".1.3.6.1.4.1.534.6.6.7.5.6.1.3.%i.%i", + NULL, SU_TYPE_CMD | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL }, + /* groupControl0nCmd.0.1 = Integer: -1 */ + { "outlet.group.%i.load.on.delay", 0, 1, + ".1.3.6.1.4.1.534.6.6.7.5.6.1.4.%i.%i", + NULL, SU_TYPE_CMD | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL }, + /* groupControlRebootCmd.0.1 = Integer: -1 */ + { "outlet.group.%i.load.cycle.delay", 0, 1, + ".1.3.6.1.4.1.534.6.6.7.5.6.1.5.%i.%i", + NULL, SU_TYPE_CMD | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL }, /* end of structure. */ - { NULL, 0, 0, NULL, NULL, 0, NULL, NULL } + { NULL, 0, 0, NULL, NULL, 0, NULL } }; diff --git a/drivers/eaton-pdu-pulizzi-mib.c b/drivers/eaton-pdu-pulizzi-mib.c index 114d2bfd86..9a83375703 100644 --- a/drivers/eaton-pdu-pulizzi-mib.c +++ b/drivers/eaton-pdu-pulizzi-mib.c @@ -42,7 +42,7 @@ /* Pulizzi Switched ePDU */ -#define EATON_PULIZZI_SW_MIB_VERSION "0.2" +#define EATON_PULIZZI_SW_MIB_VERSION "0.3" #define PULIZZI_SW_OID_MIB ".1.3.6.1.4.1.20677.3.1.1" #define PULIZZI_SW_OID_MODEL_NAME ".1.3.6.1.4.1.20677.2.1.1.0" @@ -69,24 +69,24 @@ static info_lkp_t pulizzi_sw_outlet_switchability_info[] = { static snmp_info_t eaton_pulizzi_switched_mib[] = { /* Device page */ { "device.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "EATON | Powerware", - SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL }, + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, { "device.model", ST_FLAG_STRING, SU_INFOSIZE, PULIZZI_SW_OID_MODEL_NAME, - "Switched ePDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + "Switched ePDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, { "device.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "pdu", - SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL }, + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, { "device.macaddr", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.20677.2.2.6.0", - "unknown", 0, NULL, NULL }, + "unknown", 0, NULL }, /* UPS page */ { "ups.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "EATON", - SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL }, + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, { "ups.model", ST_FLAG_STRING, SU_INFOSIZE, PULIZZI_SW_OID_MODEL_NAME, - "Switched ePDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + "Switched ePDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, /* FIXME: to be moved to the device collection! */ { "ups.date", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.20677.2.1.4.0", - "", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + "", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, { "ups.time", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.20677.2.1.3.0", - "", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + "", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, /* Outlet page */ /* Note: outlet.count is deduced, with guestimate_outlet_count() */ @@ -94,40 +94,40 @@ static snmp_info_t eaton_pulizzi_switched_mib[] = { { "outlet.desc", ST_FLAG_RW | ST_FLAG_STRING, 20, NULL, "All outlets", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, - { "outlet.current", 0, 1.0, ".1.3.6.1.4.1.20677.2.8.6.4.2.0", NULL, 0, NULL, NULL }, - { "outlet.voltage", 0, 1.0, ".1.3.6.1.4.1.20677.2.8.6.4.1.0", NULL, 0, NULL, NULL }, - { "outlet.power", 0, 1.0, ".1.3.6.1.4.1.20677.2.8.6.4.3.0", NULL, 0, NULL, NULL }, + { "outlet.current", 0, 1.0, ".1.3.6.1.4.1.20677.2.8.6.4.2.0", NULL, 0, NULL }, + { "outlet.voltage", 0, 1.0, ".1.3.6.1.4.1.20677.2.8.6.4.1.0", NULL, 0, NULL }, + { "outlet.power", 0, 1.0, ".1.3.6.1.4.1.20677.2.8.6.4.3.0", NULL, 0, NULL }, /* outlet template definition * Notes: * - indexes start from 1, ie outlet.1 => .1 * - the first definition is used to determine the base index (ie 0 or 1) * - outlet.count is estimated, based on the below OID iteration capabilities */ - { "outlet.%i.desc", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.20677.2.6.1.%i.1.0", NULL, SU_FLAG_STATIC | SU_FLAG_OK | SU_OUTLET, NULL, NULL }, + { "outlet.%i.desc", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.20677.2.6.1.%i.1.0", NULL, SU_FLAG_STATIC | SU_FLAG_OK | SU_OUTLET, NULL }, { "outlet.%i.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.20677.2.6.3.%i.0", - NULL, SU_FLAG_OK | SU_OUTLET, &pulizzi_sw_outlet_status_info[0], NULL }, - { "outlet.%i.id", 0, 1, NULL, "%i", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK | SU_OUTLET, NULL, NULL }, + NULL, SU_FLAG_OK | SU_OUTLET, &pulizzi_sw_outlet_status_info[0] }, + { "outlet.%i.id", 0, 1, NULL, "%i", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK | SU_OUTLET, NULL }, /* we use the same OID as outlet.n.status..., to expose switchability */ - { "outlet.%i.switchable", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.20677.2.6.3.%i.0", "yes", SU_FLAG_STATIC | SU_FLAG_OK | SU_OUTLET, &pulizzi_sw_outlet_switchability_info[0], NULL }, + { "outlet.%i.switchable", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.20677.2.6.3.%i.0", "yes", SU_FLAG_STATIC | SU_FLAG_OK | SU_OUTLET, &pulizzi_sw_outlet_switchability_info[0] }, /* FIXME: need to be added to the namespace! */ - { "outlet.%i.delay.reboot", ST_FLAG_RW, 1, ".1.3.6.1.4.1.20677.2.6.1.%i.5.0", NULL, SU_OUTLET, NULL, NULL }, + { "outlet.%i.delay.reboot", ST_FLAG_RW, 1, ".1.3.6.1.4.1.20677.2.6.1.%i.5.0", NULL, SU_OUTLET, NULL }, /* "outlet1SequenceTime" is used for global sequence */ - { "outlet.%i.delay.start", ST_FLAG_RW, 1, ".1.3.6.1.4.1.20677.2.6.1.%i.4.0", NULL, SU_OUTLET, NULL, NULL }, + { "outlet.%i.delay.start", ST_FLAG_RW, 1, ".1.3.6.1.4.1.20677.2.6.1.%i.4.0", NULL, SU_OUTLET, NULL }, /* instant commands. */ /* FIXME: not exposed as "outlet.load...", or otherwise specific processing applies (template instanciation) */ - { "load.on", 0, 1, ".1.3.6.1.4.1.20677.2.6.2.1.0", NULL, SU_TYPE_CMD, NULL, NULL }, - { "load.off", 0, 2, ".1.3.6.1.4.1.20677.2.6.2.1.0", NULL, SU_TYPE_CMD, NULL, NULL }, - { "load.on.delay", 0, 3, ".1.3.6.1.4.1.20677.2.6.2.1.0", NULL, SU_TYPE_CMD, NULL, NULL }, - { "load.off.delay", 0, 4, ".1.3.6.1.4.1.20677.2.6.2.1.0", NULL, SU_TYPE_CMD, NULL, NULL }, + { "load.on", 0, 1, ".1.3.6.1.4.1.20677.2.6.2.1.0", "1", SU_TYPE_CMD, NULL }, + { "load.off", 0, 1, ".1.3.6.1.4.1.20677.2.6.2.1.0", "2", SU_TYPE_CMD, NULL }, + { "load.on.delay", 0, 1, ".1.3.6.1.4.1.20677.2.6.2.1.0", "3", SU_TYPE_CMD, NULL }, + { "load.off.delay", 0, 1, ".1.3.6.1.4.1.20677.2.6.2.1.0", "4", SU_TYPE_CMD, NULL }, - /* WARNING: outlet 1 => index 2! */ - { "outlet.%i.load.on", 0, 1, ".1.3.6.1.4.1.20677.2.6.2.%i.0", NULL, SU_TYPE_CMD | SU_OUTLET | SU_CMD_OFFSET, NULL, NULL }, - { "outlet.%i.load.off", 0, 2, ".1.3.6.1.4.1.20677.2.6.2.%i.0", NULL, SU_TYPE_CMD | SU_OUTLET | SU_CMD_OFFSET, NULL, NULL }, - { "outlet.%i.load.cycle", 0, 3, ".1.3.6.1.4.1.20677.2.6.2.%i.0", NULL, SU_TYPE_CMD | SU_OUTLET | SU_CMD_OFFSET, NULL, NULL }, + /* WARNING: outlet 1 => index 2, so SU_CMD_OFFSET! */ + { "outlet.%i.load.on", 0, 1, ".1.3.6.1.4.1.20677.2.6.2.%i.0", "1", SU_TYPE_CMD | SU_OUTLET | SU_CMD_OFFSET, NULL }, + { "outlet.%i.load.off", 0, 1, ".1.3.6.1.4.1.20677.2.6.2.%i.0", "2", SU_TYPE_CMD | SU_OUTLET | SU_CMD_OFFSET, NULL }, + { "outlet.%i.load.cycle", 0, 1, ".1.3.6.1.4.1.20677.2.6.2.%i.0", "3", SU_TYPE_CMD | SU_OUTLET | SU_CMD_OFFSET, NULL }, /* end of structure. */ - { NULL, 0, 0, NULL, NULL, 0, NULL, NULL } + { NULL, 0, 0, NULL, NULL, 0, NULL } }; diff --git a/drivers/eaton-pdu-revelation-mib.c b/drivers/eaton-pdu-revelation-mib.c index 9f96724b49..83504cec0e 100644 --- a/drivers/eaton-pdu-revelation-mib.c +++ b/drivers/eaton-pdu-revelation-mib.c @@ -29,7 +29,7 @@ #include "eaton-pdu-revelation-mib.h" -#define EATON_APHEL_REVELATION_MIB_VERSION "0.49" +#define EATON_APHEL_REVELATION_MIB_VERSION "0.50" /* APHEL PDU-MIB - Revelation MIB (Managed ePDU) * ********************************************* */ @@ -72,9 +72,9 @@ static info_lkp_t revelation_outlet_switchability_info[] = { { 0, NULL } }; -#define DO_OFF 0 -#define DO_ON 1 -#define DO_CYCLE 2 +#define DO_OFF "0" +#define DO_ON "1" +#define DO_CYCLE "2" #define AR_OID_OUTLET_COUNT AR_BASE_OID ".1.2.1.0" #define AR_OID_OUTLET_CURRENT AR_BASE_OID ".1.2.2.1.4" @@ -88,58 +88,58 @@ static info_lkp_t revelation_outlet_switchability_info[] = { static snmp_info_t eaton_aphel_revelation_mib[] = { /* Device collection */ { "device.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "EATON | Powerware", - SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL }, + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, { "device.model", ST_FLAG_STRING, SU_INFOSIZE, AR_OID_MODEL_NAME, - "Eaton Powerware ePDU Managed", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + "Eaton Powerware ePDU Managed", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, { "device.serial", ST_FLAG_STRING, SU_INFOSIZE, AR_OID_SERIAL, "", - SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + SU_FLAG_STATIC | SU_FLAG_OK, NULL }, { "device.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "pdu", - SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL }, + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, { "device.macaddr", ST_FLAG_STRING, SU_INFOSIZE, AR_OID_UNIT_MACADDR, "", - SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + SU_FLAG_STATIC | SU_FLAG_OK, NULL }, /* hardwareRev.0 = Integer: 26 */ /* FIXME: not compliant! to be RFC'ed */ { "device.revision", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.6.6.6.1.1.7.0", - "", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + "", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, /* UPS collection */ { "ups.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "EATON | Powerware", - SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL }, + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, { "ups.model", ST_FLAG_STRING, SU_INFOSIZE, AR_OID_MODEL_NAME, - "Generic SNMP PDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + "Generic SNMP PDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, { "ups.id", ST_FLAG_STRING, SU_INFOSIZE, AR_OID_DEVICE_NAME, - "unknown", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + "unknown", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, { "ups.serial", ST_FLAG_STRING, SU_INFOSIZE, AR_OID_SERIAL, "", - SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + SU_FLAG_STATIC | SU_FLAG_OK, NULL }, { "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, AR_OID_FIRMREV, "", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, { "ups.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "pdu", - SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL }, - { "ups.temperature", 0, 1, AR_OID_UNIT_CPUTEMPERATURE, NULL, 0, NULL, NULL }, + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, + { "ups.temperature", 0, 1, AR_OID_UNIT_CPUTEMPERATURE, NULL, 0, NULL }, /* Outlet collection */ { "outlet.id", 0, 1, NULL, "0", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, { "outlet.desc", ST_FLAG_RW | ST_FLAG_STRING, 20, NULL, "All outlets", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, { "outlet.count", 0, 1, AR_OID_OUTLET_COUNT, "0", 0, NULL }, - { "outlet.current", 0, 0.001, AR_OID_UNIT_CURRENT ".0", NULL, 0, NULL, NULL }, - { "outlet.voltage", 0, 0.001, AR_OID_UNIT_VOLTAGE ".0", NULL, 0, NULL, NULL }, - { "outlet.realpower", 0, 1.0, AR_OID_UNIT_ACTIVEPOWER ".0", NULL, 0, NULL, NULL }, - { "outlet.power", 0, 1.0, AR_OID_UNIT_APPARENTPOWER ".0", NULL, 0, NULL, NULL }, + { "outlet.current", 0, 0.001, AR_OID_UNIT_CURRENT ".0", NULL, 0, NULL }, + { "outlet.voltage", 0, 0.001, AR_OID_UNIT_VOLTAGE ".0", NULL, 0, NULL }, + { "outlet.realpower", 0, 1.0, AR_OID_UNIT_ACTIVEPOWER ".0", NULL, 0, NULL }, + { "outlet.power", 0, 1.0, AR_OID_UNIT_APPARENTPOWER ".0", NULL, 0, NULL }, /* outlet template definition * Caution: the index of the data start at 0, while the name is +1 * ie outlet.1 => .0 */ - { "outlet.%i.switchable", 0, 1, AR_OID_OUTLET_STATUS ".%i", "yes", SU_FLAG_STATIC | SU_OUTLET, &revelation_outlet_switchability_info[0], NULL }, - { "outlet.%i.id", 0, 1, NULL, "%i", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK | SU_OUTLET, NULL, NULL }, - { "outlet.%i.desc", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, AR_OID_OUTLET_NAME ".%i", NULL, SU_OUTLET, NULL, NULL }, - { "outlet.%i.status", ST_FLAG_STRING, SU_INFOSIZE, AR_OID_OUTLET_STATUS ".%i", NULL, SU_FLAG_OK | SU_OUTLET, &revelation_outlet_status_info[0], NULL }, - { "outlet.%i.current", 0, 0.001, AR_OID_OUTLET_CURRENT ".%i", NULL, SU_OUTLET, NULL, NULL }, - { "outlet.%i.current.maximum", 0, 0.001, AR_OID_OUTLET_MAXCURRENT ".%i", NULL, SU_OUTLET, NULL, NULL }, - { "outlet.%i.realpower", 0, 1.0, AR_OID_OUTLET_ACTIVEPOWER ".%i", NULL, SU_OUTLET, NULL, NULL }, - { "outlet.%i.voltage", 0, 1.0, AR_OID_OUTLET_VOLTAGE ".%i", NULL, SU_OUTLET, NULL, NULL }, - { "outlet.%i.powerfactor", 0, 0.01, AR_OID_OUTLET_POWERFACTOR ".%i", NULL, SU_OUTLET, NULL, NULL }, - { "outlet.%i.power", 0, 1.0, AR_OID_OUTLET_APPARENTPOWER ".%i", NULL, SU_OUTLET, NULL, NULL }, + { "outlet.%i.switchable", 0, 1, AR_OID_OUTLET_STATUS ".%i", "yes", SU_FLAG_STATIC | SU_OUTLET, &revelation_outlet_switchability_info[0] }, + { "outlet.%i.id", 0, 1, NULL, "%i", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK | SU_OUTLET, NULL }, + { "outlet.%i.desc", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, AR_OID_OUTLET_NAME ".%i", NULL, SU_OUTLET, NULL }, + { "outlet.%i.status", ST_FLAG_STRING, SU_INFOSIZE, AR_OID_OUTLET_STATUS ".%i", NULL, SU_FLAG_OK | SU_OUTLET, &revelation_outlet_status_info[0] }, + { "outlet.%i.current", 0, 0.001, AR_OID_OUTLET_CURRENT ".%i", NULL, SU_OUTLET, NULL }, + { "outlet.%i.current.maximum", 0, 0.001, AR_OID_OUTLET_MAXCURRENT ".%i", NULL, SU_OUTLET, NULL }, + { "outlet.%i.realpower", 0, 1.0, AR_OID_OUTLET_ACTIVEPOWER ".%i", NULL, SU_OUTLET, NULL }, + { "outlet.%i.voltage", 0, 1.0, AR_OID_OUTLET_VOLTAGE ".%i", NULL, SU_OUTLET, NULL }, + { "outlet.%i.powerfactor", 0, 0.01, AR_OID_OUTLET_POWERFACTOR ".%i", NULL, SU_OUTLET, NULL }, + { "outlet.%i.power", 0, 1.0, AR_OID_OUTLET_APPARENTPOWER ".%i", NULL, SU_OUTLET, NULL }, /* FIXME: * - delay for startup/shutdown sequence @@ -151,25 +151,25 @@ static snmp_info_t eaton_aphel_revelation_mib[] = { /* Ambient collection */ /* We use critical levels, for both temperature and humidity, * since warning levels are also available! */ - { "ambient.temperature", 0, 1.0, ".1.3.6.1.4.1.534.6.6.6.2.2.1.3.0", NULL, SU_FLAG_OK, NULL, NULL }, - { "ambient.temperature.low", 0, 1.0, "1.3.6.1.4.1.534.6.6.6.2.2.1.6.0", NULL, SU_FLAG_OK, NULL, NULL }, - { "ambient.temperature.high", 0, 1.0, "1.3.6.1.4.1.534.6.6.6.2.2.1.7.0", NULL, SU_FLAG_OK, NULL, NULL }, - { "ambient.humidity", 0, 1.0, ".1.3.6.1.4.1.534.6.6.6.2.4.1.3.0", NULL, SU_FLAG_OK, NULL, NULL }, - { "ambient.humidity.low", 0, 1.0, ".1.3.6.1.4.1.534.6.6.6.2.4.1.6.0", NULL, SU_FLAG_OK, NULL, NULL }, - { "ambient.humidity.high", 0, 1.0, ".1.3.6.1.4.1.534.6.6.6.2.4.1.7.0", NULL, SU_FLAG_OK, NULL, NULL }, + { "ambient.temperature", 0, 1.0, ".1.3.6.1.4.1.534.6.6.6.2.2.1.3.0", NULL, SU_FLAG_OK, NULL }, + { "ambient.temperature.low", 0, 1.0, "1.3.6.1.4.1.534.6.6.6.2.2.1.6.0", NULL, SU_FLAG_OK, NULL }, + { "ambient.temperature.high", 0, 1.0, "1.3.6.1.4.1.534.6.6.6.2.2.1.7.0", NULL, SU_FLAG_OK, NULL }, + { "ambient.humidity", 0, 1.0, ".1.3.6.1.4.1.534.6.6.6.2.4.1.3.0", NULL, SU_FLAG_OK, NULL }, + { "ambient.humidity.low", 0, 1.0, ".1.3.6.1.4.1.534.6.6.6.2.4.1.6.0", NULL, SU_FLAG_OK, NULL }, + { "ambient.humidity.high", 0, 1.0, ".1.3.6.1.4.1.534.6.6.6.2.4.1.7.0", NULL, SU_FLAG_OK, NULL }, /* instant commands. */ /* Note that load.cycle might be replaced by / mapped on shutdown.reboot */ /* no counterpart found! - { "outlet.load.off", 0, DO_OFF, AR_OID_OUTLET_STATUS ".0", NULL, SU_TYPE_CMD, NULL, NULL }, - { "outlet.load.on", 0, DO_ON, AR_OID_OUTLET_STATUS ".0", NULL, SU_TYPE_CMD, NULL, NULL }, - { "outlet.load.cycle", 0, DO_CYCLE, AR_OID_OUTLET_STATUS ".0", NULL, SU_TYPE_CMD, NULL, NULL }, */ - { "outlet.%i.load.off", 0, DO_OFF, AR_OID_OUTLET_STATUS ".%i", NULL, SU_TYPE_CMD | SU_OUTLET, NULL, NULL }, - { "outlet.%i.load.on", 0, DO_ON, AR_OID_OUTLET_STATUS ".%i", NULL, SU_TYPE_CMD | SU_OUTLET, NULL, NULL }, - { "outlet.%i.load.cycle", 0, DO_CYCLE, AR_OID_OUTLET_STATUS ".%i", NULL, SU_TYPE_CMD | SU_OUTLET, NULL, NULL }, + { "outlet.load.off", 0, DO_OFF, AR_OID_OUTLET_STATUS ".0", NULL, SU_TYPE_CMD, NULL }, + { "outlet.load.on", 0, DO_ON, AR_OID_OUTLET_STATUS ".0", NULL, SU_TYPE_CMD, NULL }, + { "outlet.load.cycle", 0, DO_CYCLE, AR_OID_OUTLET_STATUS ".0", NULL, SU_TYPE_CMD, NULL }, */ + { "outlet.%i.load.off", 0, 1, AR_OID_OUTLET_STATUS ".%i", DO_OFF, SU_TYPE_CMD | SU_OUTLET, NULL }, + { "outlet.%i.load.on", 0, 1, AR_OID_OUTLET_STATUS ".%i", DO_ON, SU_TYPE_CMD | SU_OUTLET, NULL }, + { "outlet.%i.load.cycle", 0, 1, AR_OID_OUTLET_STATUS ".%i", DO_CYCLE, SU_TYPE_CMD | SU_OUTLET, NULL }, /* end of structure. */ - { NULL, 0, 0, NULL, NULL, 0, NULL, NULL } + { NULL, 0, 0, NULL, NULL, 0, NULL } }; diff --git a/drivers/emerson-avocent-pdu-mib.c b/drivers/emerson-avocent-pdu-mib.c new file mode 100644 index 0000000000..3eb73e1084 --- /dev/null +++ b/drivers/emerson-avocent-pdu-mib.c @@ -0,0 +1,185 @@ +/* emerson-avocent-pdu-mib.c - subdriver to monitor Emerson Avocent PDUs with NUT + * + * Copyright (C) + * 2008-2018 Arnaud Quette + * 2009 Opengear + * 2017-2019 Eaton (Arnaud Quette ) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#define OPENGEAR_MULTIPLE_BANKS 1 + +#include "emerson-avocent-pdu-mib.h" + +#define EMERSON_AVOCENT_MIB_VERSION "1.1" +#define EMERSON_AVOCENT_SYSOID ".1.3.6.1.4.1.10418.17.1.7" +#define EMERSON_AVOCENT_OID_MODEL_NAME ".1.3.6.1.4.1.10418.17.2.1.2.0" + +/* FIXME: Avocent PM's seem to have 3 temperature sensors (index 1, 2, 3) + * for the embedded temperature (equivalent to ups.temperature) */ +#define AVOCENT_OID_UNIT_TEMPERATURE ".1.3.6.1.4.1.10418.17.2.5.3.1.17.1.1" + +/* Same as above for humidity... */ +#define AVOCENT_OID_UNIT_HUMIDITY ".1.3.6.1.4.1.10418.17.2.5.3.1.24.1" + +#define AVOCENT_OID_OUTLET_COUNT ".1.3.6.1.4.1.10418.17.2.5.3.1.8.%i.%i" + +/* FIXME: This is actually pmPowerMgmtPDUTableCurrent1Value */ +#define AVOCENT_OID_UNIT_CURRENT ".1.3.6.1.4.1.10418.17.2.5.3.1.10.1.1" +/* FIXME: This is actually pmPowerMgmtPDUTableVoltage1Value */ +#define AVOCENT_OID_UNIT_VOLTAGE ".1.3.6.1.4.1.10418.17.2.5.3.1.31.1.1" +#define AVOCENT_OID_UNIT_MACADDR ".1.3.6.1.2.1.2.2.1.6.1" + +#ifdef OPENGEAR_MULTIPLE_BANKS +#define AVOCENT_OID_OUTLET_ID ".1.3.6.1.4.1.10418.17.2.5.5.1.3" +#define AVOCENT_OID_OUTLET_NAME ".1.3.6.1.4.1.10418.17.2.5.5.1.4" +#define AVOCENT_OID_OUTLET_STATUS ".1.3.6.1.4.1.10418.17.2.5.5.1.5" +/* This the actual value for the Current of the sensor. */ +#define AVOCENT_OID_OUTLET_LOAD ".1.3.6.1.4.1.10418.17.2.5.5.1.50" +#define AVOCENT_OID_OUTLET_CONTROL ".1.3.6.1.4.1.10418.17.2.5.5.1.6" +#else +#define AVOCENT_OID_OUTLET_ID ".1.3.6.1.4.1.10418.17.2.5.5.1.3.1.1" +#define AVOCENT_OID_OUTLET_NAME ".1.3.6.1.4.1.10418.17.2.5.5.1.4.1.1" +#define AVOCENT_OID_OUTLET_STATUS ".1.3.6.1.4.1.10418.17.2.5.5.1.5.1.1" +#define AVOCENT_OID_OUTLET_LOAD ".1.3.6.1.4.1.10418.17.2.5.5.1.50.1.1" +#define AVOCENT_OID_OUTLET_CONTROL ".1.3.6.1.4.1.10418.17.2.5.5.1.6.1.1" +#endif + +info_lkp_t avocent_outlet_status_info[] = { + { 1, "off" }, + { 2, "on" }, +/* { 3, "offLocked" }, + { 4, "onLocked" }, + { 5, "offCycle" }, + { 6, "onPendingOff" }, + { 7, "offPendingOn" }, + { 8, "onPendingCycle" }, + { 9, "notSet" }, + { 10, "onFixed" }, + { 11, "offShutdown" }, + { 12, "tripped" },*/ + { 0, NULL } +}; + +snmp_info_t emerson_avocent_pdu_mib[] = { + /* Device page */ + { "device.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "Avocent", + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, + { "device.model", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.10418.17.2.5.3.1.5.1.%i", /* EMERSON_AVOCENT_OID_MODEL_NAME */ + "Avocent SNMP PDU", SU_FLAG_ABSENT | SU_FLAG_OK | SU_FLAG_NAINVALID, NULL }, + { "device.serial", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.10418.17.2.1.4.0", "", + SU_FLAG_STATIC | SU_FLAG_OK, NULL }, + { "device.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "pdu", + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, + /* Daisychained devices support + * Notes: this definition is used to: + * - estimate the number of devices, based on the below OID iteration capabilities + * - determine the base index of the SNMP OID (ie 0 or 1) */ + { "device.count", 0, 1, ".1.3.6.1.4.1.10418.17.2.5.2.1.4.1", + "1", SU_FLAG_STATIC, NULL }, + + /* UPS page */ + { "ups.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "Avocent", + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, + { "ups.model", ST_FLAG_STRING, SU_INFOSIZE, EMERSON_AVOCENT_OID_MODEL_NAME, + "Avocent SNMP PDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, + { "ups.id", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.10418.17.2.1.1.0", + "unknown", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, + { "ups.serial", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.10418.17.2.1.4.0", "", + SU_FLAG_STATIC | SU_FLAG_OK, NULL }, + { "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.10418.17.2.1.7.0", "", + SU_FLAG_STATIC | SU_FLAG_OK, NULL }, + { "ups.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "pdu", + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, + { "ups.macaddr", ST_FLAG_STRING, SU_INFOSIZE, AVOCENT_OID_UNIT_MACADDR, + "", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, + /* Outlet page */ + { "outlet.id", 0, 1, NULL, "0", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, + { "outlet.desc", ST_FLAG_RW | ST_FLAG_STRING, 20, NULL, "All outlets", + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, + { "outlet.count", 0, 1, ".1.3.6.1.4.1.10418.17.2.5.3.1.8.1.%i", "0", SU_FLAG_STATIC | SU_FLAG_ZEROINVALID | SU_FLAG_OK, NULL }, + + /* outlets */ + /* NOTE: there is a bug in Avocent FW: + * index '0' should not respond (and is not in subtree mode) but answers + * to unitary get, since OIDs start at index '1'. + *Use the status data below to test since '0' is not a supported value */ + { "outlet.%i.status", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.10418.17.2.5.5.1.5.1.%i.%i", NULL, SU_OUTLET | SU_TYPE_DAISY_1 | SU_FLAG_ZEROINVALID, &avocent_outlet_status_info[0] }, + { "outlet.%i.id", 0, 1, + ".1.3.6.1.4.1.10418.17.2.5.5.1.3.1.%i.%i", NULL, SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, + { "outlet.%i.desc", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.10418.17.2.5.5.1.4.1.%i.%i", NULL, SU_OUTLET | SU_TYPE_DAISY_1 | SU_FLAG_NAINVALID, NULL }, + /* pmPowerMgmtOutletsTableCurrentValue.1.1.1; Value (Integer): 0 */ + { "outlet.%i.current", 0, 0.1, + ".1.3.6.1.4.1.10418.17.2.5.5.1.50.1.%i.%i", NULL, SU_OUTLET | SU_TYPE_DAISY_1, NULL }, + /* pmPowerMgmtOutletsTableCurrentHighCritical.1.1.1; Value (Integer): 160 */ + { "outlet.%i.current.high.critical", ST_FLAG_RW, 0.1, + ".1.3.6.1.4.1.10418.17.2.5.5.1.100.1.%i.%i", + NULL, SU_OUTLET | SU_TYPE_DAISY_1, NULL }, + /* pmPowerMgmtOutletsTableCurrentHighWarning.1.1.1; Value (Integer): 120 */ + { "outlet.%i.current.high.warning", ST_FLAG_RW, 0.1, + ".1.3.6.1.4.1.10418.17.2.5.5.1.101.1.%i.%i", + NULL, SU_OUTLET | SU_TYPE_DAISY_1, NULL }, + /* pmPowerMgmtOutletsTableCurrentLowWarning.1.1.1; Value (Integer): 0 */ + { "outlet.%i.current.low.warning", ST_FLAG_RW, 0.1, + ".1.3.6.1.4.1.10418.17.2.5.5.1.102.1.%i.%i", + NULL, SU_OUTLET | SU_TYPE_DAISY_1, NULL }, + /* pmPowerMgmtOutletsTableCurrentLowCritical.1.1.1; Value (Integer): 0 */ + { "outlet.%i.current.low.critical", ST_FLAG_RW, 0.1, + ".1.3.6.1.4.1.10418.17.2.5.5.1.103.1.%i.%i", + NULL, SU_OUTLET | SU_TYPE_DAISY_1, NULL }, + /* pmPowerMgmtOutletsTablePowerValue.1.1.1; Value (Integer): 0 */ + { "outlet.%i.realpower", 0, 0.1, + ".1.3.6.1.4.1.10418.17.2.5.5.1.60.1.%i.%i", NULL, SU_OUTLET | SU_TYPE_DAISY_1, NULL }, + /* pmPowerMgmtOutletsTableVoltageValue.1.1.1; Value (Integer): 238 */ + { "outlet.%i.voltage", 0, 1, + ".1.3.6.1.4.1.10418.17.2.5.5.1.70.1.%i.%i", NULL, SU_OUTLET | SU_TYPE_DAISY_1, NULL }, + + /* TODO: handle statistics + * pmPowerMgmtOutletsTableEnergyValue.1.1.1; Value (Integer): 0 (Wh) + * pmPowerMgmtOutletsTableEnergyStartTime.1.1.1; Value (OctetString): 2018-02-13 10:40:09 + * pmPowerMgmtOutletsTableEnergyReset.1.1.1; Value (Integer): noAction (1) + */ + + /* Outlet groups collection */ + /* pmPowerMgmtNumberOfOutletGroup.0; Value (Integer): 0 */ + { "outlet.group.count", 0, 1, ".1.3.6.1.4.1.10418.17.2.5.6.%i", + "0", SU_FLAG_STATIC | SU_TYPE_DAISY_1, NULL }, + + /* TODO: support for "Banks" (not sure to understand what is this?!) + * pmPowerMgmtTotalNumberOfBanks.0; Value (Integer): 6 + * pmPowerMgmtBanksTableName.1.1.1; Value (OctetString): 18-bf-ffP0_1_A + */ + + /* According to MIB Power Control values are: + * noAction(1), + * powerOn(2), + * powerOff(3), + * powerCycle(4), + * powerLock(5), + * powerUnlock(6) + */ + { "outlet.%i.load.cycle", 0, 1, ".1.3.6.1.4.1.10418.17.2.5.5.1.6.1.%i.%i", "4", SU_TYPE_CMD | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, + { "outlet.%i.load.off", 0, 1, ".1.3.6.1.4.1.10418.17.2.5.5.1.6.1.%i.%i", "3", SU_TYPE_CMD | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, + { "outlet.%i.load.on", 0, 1, ".1.3.6.1.4.1.10418.17.2.5.5.1.6.1.%i.%i", "2", SU_TYPE_CMD | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, + + /* end of structure. */ + { NULL, 0, 0, NULL, NULL, 0, NULL } +}; + +mib2nut_info_t emerson_avocent_pdu = { "emerson_avocent_pdu", EMERSON_AVOCENT_MIB_VERSION, NULL, EMERSON_AVOCENT_OID_MODEL_NAME, emerson_avocent_pdu_mib, EMERSON_AVOCENT_SYSOID }; diff --git a/drivers/emerson-avocent-pdu-mib.h b/drivers/emerson-avocent-pdu-mib.h new file mode 100644 index 0000000000..fb9807500b --- /dev/null +++ b/drivers/emerson-avocent-pdu-mib.h @@ -0,0 +1,31 @@ +/* emerson-avocent-pdu-mib.h - subdriver to monitor Emerson Avocent PDUs with NUT + * + * Copyright (C) + * 2008-2018 Arnaud Quette + * 2009 Opengear + * 2018 Eaton (Arnaud Quette ) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef EMERSON_AVOCENT_PDU_MIB_H +#define EMERSON_AVOCENT_PDU_MIB_H + +#include "main.h" +#include "snmp-ups.h" + +extern mib2nut_info_t emerson_avocent_pdu; + +#endif /* EMERSON_AVOCENT_PDU_MIB_H */ diff --git a/drivers/hpe-pdu-mib.c b/drivers/hpe-pdu-mib.c new file mode 100644 index 0000000000..d764d3baf5 --- /dev/null +++ b/drivers/hpe-pdu-mib.c @@ -0,0 +1,895 @@ +/* hpe-pdu-mib.c - subdriver to monitor HPE ePDU SNMP devices with NUT + * + * Copyright (C) + * 2011 - 2016 Arnaud Quette + * 2019 Arnaud Quette + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "hpe-pdu-mib.h" +#include "dstate.h" + +#define HPE_EPDU_MIB_VERSION "0.31" +#define HPE_EPDU_MIB_SYSOID ".1.3.6.1.4.1.232.165.7" +#define HPE_EPDU_OID_MODEL_NAME ".1.3.6.1.4.1.232.165.7.1.2.1.3.0" + +static info_lkp_t hpe_pdu_outlet_status_info[] = { + { 1, "off" }, + { 2, "on" }, + { 3, "pendingOff" }, /* transitional status */ + { 4, "pendingOn" }, /* transitional status */ + { 0, NULL } +}; + +static info_lkp_t hpe_pdu_outletgroups_status_info[] = { + { 1, "N/A" }, /* notApplicable, if group.type == outlet-section */ + { 2, "on" }, /* breakerOn */ + { 3, "off" }, /* breakerOff */ + { 0, NULL } +}; + +static info_lkp_t hpe_pdu_outlet_switchability_info[] = { + { 1, "yes" }, + { 2, "no" }, + { 0, NULL } +}; + +/* The physical type of outlet */ +static info_lkp_t hpe_pdu_outlet_type_info[] = { + { 0, "unknown" }, + { 1, "iecC13" }, + { 2, "iecC19" }, + { 10, "uk" }, + { 11, "french" }, + { 12, "schuko" }, + { 20, "nema515" }, + { 21, "nema51520" }, + { 22, "nema520" }, + { 23, "nemaL520" }, + { 24, "nemaL530" }, + { 25, "nema615" }, + { 26, "nema620" }, + { 27, "nemaL620" }, + { 28, "nemaL630" }, + { 29, "nemaL715" }, + { 30, "rf203p277" }, + { 0, NULL } +}; + +static info_lkp_t hpe_pdu_ambient_presence_info[] = { + { -1, "unknown" }, + { 1, "no" }, /* disconnected */ + { 2, "yes" }, /* connected */ + { 0, NULL } +}; + +static info_lkp_t hpe_pdu_threshold_status_info[] = { + { 1, "good" }, /* No threshold triggered */ + { 2, "warning-low" }, /* Warning low threshold triggered */ + { 3, "critical-low" }, /* Critical low threshold triggered */ + { 4, "warning-high" }, /* Warning high threshold triggered */ + { 5, "critical-high" }, /* Critical high threshold triggered */ + { 0, NULL } +}; + +static info_lkp_t hpe_pdu_threshold_frequency_status_info[] = { + { 1, "good" }, /* No threshold triggered */ + { 2, "out-of-range" }, /* Frequency out of range triggered */ + { 0, NULL } +}; + +static info_lkp_t hpe_pdu_ambient_drycontacts_info[] = { + { -1, "unknown" }, + { 0, "unknown" }, + { 1, "open" }, + { 2, "closed" }, + { 3, "bad" }, /* FIXME: what to do with that? */ + { 0, NULL } +}; + +static info_lkp_t hpe_pdu_threshold_voltage_alarms_info[] = { + { 1, "" }, /* No threshold triggered */ + { 2, "low voltage warning!" }, /* Warning low threshold triggered */ + { 3, "low voltage critical!" }, /* Critical low threshold triggered */ + { 4, "high voltage warning!" }, /* Warning high threshold triggered */ + { 5, "high voltage critical!" }, /* Critical high threshold triggered */ + { 0, NULL } +}; + +static info_lkp_t hpe_pdu_threshold_current_alarms_info[] = { + { 1, "" }, /* No threshold triggered */ + { 2, "low current warning!" }, /* Warning low threshold triggered */ + { 3, "low current critical!" }, /* Critical low threshold triggered */ + { 4, "high current warning!" }, /* Warning high threshold triggered */ + { 5, "high current critical!" }, /* Critical high threshold triggered */ + { 0, NULL } +}; + +static info_lkp_t hpe_pdu_threshold_frequency_alarm_info[] = { + { 1, "" }, /* No threshold triggered */ + { 2, "frequency out of range!" }, /* Frequency out of range triggered */ + { 0, NULL } +}; + +static info_lkp_t hpe_pdu_threshold_temperature_alarms_info[] = { + { 1, "" }, /* No threshold triggered */ + { 2, "low temperature warning!" }, /* Warning low threshold triggered */ + { 3, "low temperature critical!" }, /* Critical low threshold triggered */ + { 4, "high temperature warning!" }, /* Warning high threshold triggered */ + { 5, "high temperature critical!" }, /* Critical high threshold triggered */ + { 0, NULL } +}; + +static info_lkp_t hpe_pdu_threshold_humidity_alarms_info[] = { + { 1, "" }, /* No threshold triggered */ + { 2, "low humidity warning!" }, /* Warning low threshold triggered */ + { 3, "low humidity critical!" }, /* Critical low threshold triggered */ + { 4, "high humidity warning!" }, /* Warning high threshold triggered */ + { 5, "high humidity critical!" }, /* Critical high threshold triggered */ + { 0, NULL } +}; + +static info_lkp_t hpe_pdu_outlet_group_type_info[] = { + { 0, "unknown" }, + { 1, "unknown" }, + { 2, "breaker1pole" }, + { 3, "breaker2pole" }, + { 4, "breaker3pole" }, + { 5, "outlet-section" }, + { 0, NULL } +}; + +static info_lkp_t hpe_pdu_input_type_info[] = { + { 1, "1" }, /* singlePhase */ + { 2, "2" }, /* splitPhase */ + { 3, "3" }, /* threePhaseDelta */ + { 4, "3" }, /* threePhaseWye */ + { 0, NULL } +}; + +static info_lkp_t hpe_pdu_outlet_group_phase_info[] = { + { 1, "L1" }, /* singlePhase */ + { 2, "L1" }, /* phase1toN */ + { 3, "L2" }, /* phase2toN */ + { 4, "L3" }, /* phase3toN */ + { 5, "L1" }, /* phase1to2 */ + { 6, "L2" }, /* phase2to3 */ + { 7, "L3" }, /* phase3to1 */ + { 0, NULL } +}; + +/* Snmp2NUT lookup table for HPE PDU MIB */ +static snmp_info_t hpe_pdu_mib[] = { + + /* Device collection */ + { "device.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "HPE", + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, + /* pdu2Model.0 = STRING: "HP 8.6kVA 208V 30A 3Ph NA/JP maPDU" */ + { "device.model", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.1.2.1.3.%i", + "HPE ePDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, + /* pdu2SerialNumber.0 = STRING: "CN94230105" */ + { "device.serial", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.1.2.1.7.%i", + "", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, + { "device.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "pdu", + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, + /* pdu2PartNumber.0 = STRING: "H8B52A" */ + { "device.part", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.1.2.1.6.%i", + "", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, + /* For daisychain, there is only 1 physical interface! */ + { "device.macaddr", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.2.1.2.2.1.6.2", + "", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, + /* Daisychained devices support + * Notes: this definition is used to: + * - estimate the number of devices, based on the below OID iteration capabilities + * - determine the base index of the SNMP OID (ie 0 or 1) */ + /* pdu2NumberPDU.0 = INTEGER: 1 */ + { "device.count", 0, 1, + ".1.3.6.1.4.1.232.165.7.1.1.0", + "1", SU_FLAG_STATIC, NULL }, + + /* UPS collection */ + { "ups.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "HPE", + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, + { "ups.model", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.1.2.1.3.%i", + "HPE ePDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, + + /* FIXME: use unitName.0 (ePDU)? + * { "ups.id", ST_FLAG_STRING, SU_INFOSIZE, AR_OID_DEVICE_NAME, + "unknown", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, */ + { "ups.serial", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.1.2.1.7.%i", + "", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, + /* FIXME: this entry should be SU_FLAG_SEMI_STATIC */ + /* pdu2FirmwareVersion.0 = STRING: "02.00.0043" */ + { "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.1.2.1.5.%i", + "", SU_FLAG_OK, NULL }, + { "ups.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "pdu", + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, + + /* FIXME: needs a date reformating callback + * 2011-8-29,16:27:25.0,+1:0 + * Hex-STRING: 07 DB 08 1D 10 0C 36 00 2B 01 00 00 + * { "ups.date", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.534.6.6.7.1.2.1.8.0", + "", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, + * { "ups.time", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.534.6.6.7.1.2.1.8.0", + "", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, + */ + + /* Input collection */ + /* Note: for daisychain mode, we must handle phase(s) per device, not as a whole */ + /* pdu2InputType.0 = INTEGER: threePhaseWye(4) */ + { "input.phases", 0, 1, ".1.3.6.1.4.1.232.165.7.2.1.1.1.%i", + NULL, SU_FLAG_STATIC, &hpe_pdu_input_type_info[0] }, + + /* Frequency is measured globally */ + /* pdu2InputFrequency.0 = INTEGER: 500 */ + { "input.frequency", 0, 0.1, ".1.3.6.1.4.1.232.165.7.2.1.1.2.%i", + NULL, 0, NULL }, + /* pdu2InputFrequencyStatus.0 = INTEGER: good(1) */ + { "input.frequency.status", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.2.1.1.3.%i", + NULL, SU_FLAG_OK, &hpe_pdu_threshold_frequency_status_info[0] }, + { "ups.alarm", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.2.1.1.3.%i", + NULL, SU_FLAG_OK, &hpe_pdu_threshold_frequency_alarm_info[0] }, + /* inputCurrentPercentLoad (measured globally) + * Current percent load, based on the rated current capacity */ + /* FIXME: input.load is mapped on input.L1.load for both single and 3phase !!! */ + { "input.load", 0, 1.0, ".1.3.6.1.4.1.534.6.6.7.3.3.1.11.%i.1.1", + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, + /* pdu2InputPhaseCurrentPercentLoad.0.1 = INTEGER: 0 */ + { "input.L1.load", 0, 1.0, ".1.3.6.1.4.1.232.165.7.2.2.1.18.%i.1", + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, + /* pdu2InputPhaseCurrentPercentLoad.0.2 = INTEGER: 0 */ + { "input.L1.load", 0, 1.0, ".1.3.6.1.4.1.232.165.7.2.2.1.18.%i.2", + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, + /* pdu2InputPhaseCurrentPercentLoad.0.3 = INTEGER: 0 */ + { "input.L1.load", 0, 1.0, ".1.3.6.1.4.1.232.165.7.2.2.1.18.%i.3", + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, + + /* FIXME: + * - Voltage is only measured per phase, as mV! + * so input.voltage == input.L1.voltage for both single and 3phase + * - As per NUT namespace (http://www.networkupstools.org/docs/developer-guide.chunked/apas01.html#_valid_contexts) + * Voltage has to be expressed either phase-phase or phase-neutral + * This is depending on OID inputVoltageMeasType + * INTEGER {singlePhase (1),phase1toN (2),phase2toN (3),phase3toN (4),phase1to2 (5),phase2to3 (6),phase3to1 (7) + * => RFC input.Lx.voltage.context */ + /* pdu2InputPhaseVoltage.0.1 = INTEGER: 216790 */ + { "input.voltage", 0, 0.001, ".1.3.6.1.4.1.232.165.7.2.2.1.3.%i.1", + NULL, 0, NULL }, + /* pdu2InputPhaseVoltageThStatus.0.1 = INTEGER: good(1) */ + { "input.voltage.status", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.2.2.1.4.%i.1", + NULL, SU_FLAG_OK, &hpe_pdu_threshold_status_info[0] }, + { "ups.alarm", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.2.2.1.4.%i.1", + NULL, SU_FLAG_OK, &hpe_pdu_threshold_voltage_alarms_info[0] }, + /* pdu2InputPhaseVoltageThLowerWarning.0.1 = INTEGER: 190000 */ + { "input.voltage.low.warning", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.2.2.1.5.%i.1", + NULL, SU_FLAG_NEGINVALID, NULL }, + /* pdu2InputPhaseVoltageThLowerCritical.0.1 = INTEGER: 180000 */ + { "input.voltage.low.critical", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.2.2.1.6.%i.1", + NULL, SU_FLAG_NEGINVALID, NULL }, + /* pdu2InputPhaseVoltageThUpperWarning.0.1 = INTEGER: 255000 */ + { "input.voltage.high.warning", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.2.2.1.7.%i.1", + NULL, SU_FLAG_NEGINVALID, NULL }, + /* pdu2InputPhaseVoltageThUpperCritical.0.1 = INTEGER: 265000 */ + { "input.voltage.high.critical", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.2.2.1.8.%i.1", + NULL, SU_FLAG_NEGINVALID, NULL }, + /* pdu2InputPhaseVoltage.0.1 = INTEGER: 216790 */ + { "input.L1.voltage", 0, 0.001, ".1.3.6.1.4.1.232.165.7.2.2.1.3.%i.1", + NULL, 0, NULL }, + /* pdu2InputPhaseVoltageThStatus.0.1 = INTEGER: good(1) */ + { "input.L1.voltage.status", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.2.2.1.4.%i.1", + NULL, SU_FLAG_OK, &hpe_pdu_threshold_status_info[0] }, + { "L1.alarm", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.2.2.1.4.%i.1", + NULL, SU_FLAG_OK, &hpe_pdu_threshold_voltage_alarms_info[0] }, + /* pdu2InputPhaseVoltageThLowerWarning.0.1 = INTEGER: 190000 */ + { "input.L1.voltage.low.warning", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.2.2.1.5.%i.1", + NULL, SU_FLAG_NEGINVALID, NULL }, + /* pdu2InputPhaseVoltageThLowerCritical.0.1 = INTEGER: 180000 */ + { "input.L1.voltage.low.critical", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.2.2.1.6.%i.1", + NULL, SU_FLAG_NEGINVALID, NULL }, + /* pdu2InputPhaseVoltageThUpperWarning.0.1 = INTEGER: 255000 */ + { "input.L1.voltage.high.warning", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.2.2.1.7.%i.1", + NULL, SU_FLAG_NEGINVALID, NULL }, + /* pdu2InputPhaseVoltageThUpperCritical.0.1 = INTEGER: 265000 */ + { "input.L1.voltage.high.critical", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.2.2.1.8.%i.1", + NULL, SU_FLAG_NEGINVALID, NULL }, + /* pdu2InputPhaseVoltage.0.2 = INTEGER: 216790 */ + { "input.L2.voltage", 0, 0.001, ".1.3.6.1.4.1.232.165.7.2.2.1.3.%i.2", + NULL, 0, NULL }, + /* pdu2InputPhaseVoltageThStatus.0.2 = INTEGER: good(1) */ + { "input.L2.voltage.status", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.2.2.1.4.%i.2", + NULL, SU_FLAG_OK, &hpe_pdu_threshold_status_info[0] }, + { "L2.alarm", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.2.2.1.4.%i.2", + NULL, SU_FLAG_OK, &hpe_pdu_threshold_voltage_alarms_info[0] }, + /* pdu2InputPhaseVoltageThLowerWarning.0.2 = INTEGER: 190000 */ + { "input.L2.voltage.low.warning", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.2.2.1.5.%i.2", + NULL, SU_FLAG_NEGINVALID, NULL }, + /* pdu2InputPhaseVoltageThLowerCritical.0.2 = INTEGER: 180000 */ + { "input.L2.voltage.low.critical", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.2.2.1.6.%i.2", + NULL, SU_FLAG_NEGINVALID, NULL }, + /* pdu2InputPhaseVoltageThUpperWarning.0.2 = INTEGER: 255000 */ + { "input.L2.voltage.high.warning", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.2.2.1.7.%i.2", + NULL, SU_FLAG_NEGINVALID, NULL }, + /* pdu2InputPhaseVoltageThUpperCritical.0.2 = INTEGER: 265000 */ + { "input.L2.voltage.high.critical", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.2.2.1.8.%i.2", + NULL, SU_FLAG_NEGINVALID, NULL }, + /* pdu2InputPhaseVoltage.0.3 = INTEGER: 216790 */ + { "input.L3.voltage", 0, 0.001, ".1.3.6.1.4.1.232.165.7.2.2.1.3.%i.3", + NULL, 0, NULL }, + /* pdu2InputPhaseVoltageThStatus.0.3 = INTEGER: good(1) */ + { "input.L3.voltage.status", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.2.2.1.4.%i.3", + NULL, SU_FLAG_OK, &hpe_pdu_threshold_status_info[0] }, + { "L3.alarm", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.2.2.1.4.%i.3", + NULL, SU_FLAG_OK, &hpe_pdu_threshold_voltage_alarms_info[0] }, + /* pdu2InputPhaseVoltageThLowerWarning.0.3 = INTEGER: 190000 */ + { "input.L3.voltage.low.warning", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.2.2.1.5.%i.3", + NULL, SU_FLAG_NEGINVALID, NULL }, + /* pdu2InputPhaseVoltageThLowerCritical.0.3 = INTEGER: 180000 */ + { "input.L3.voltage.low.critical", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.2.2.1.6.%i.3", + NULL, SU_FLAG_NEGINVALID, NULL }, + /* pdu2InputPhaseVoltageThUpperWarning.0.3 = INTEGER: 255000 */ + { "input.L3.voltage.high.warning", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.2.2.1.7.%i.3", + NULL, SU_FLAG_NEGINVALID, NULL }, + /* pdu2InputPhaseVoltageThUpperCritical.0.3 = INTEGER: 265000 */ + { "input.L3.voltage.high.critical", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.2.2.1.8.%i.3", + NULL, SU_FLAG_NEGINVALID, NULL }, + /* FIXME: + * - input.current is mapped on input.L1.current for both single and 3phase !!! */ + /* pdu2InputPhaseCurrent.0.1 = INTEGER: 185 */ + { "input.current", 0, 0.001, + ".1.3.6.1.4.1.232.165.7.2.2.1.11.%i.1", + NULL, 0, NULL }, + /* pdu2InputPhaseCurrentRating.0.1 = INTEGER: 24000 */ + { "input.current.nominal", 0, 0.001, + ".1.3.6.1.4.1.232.165.7.2.2.1.10.%i.1", + NULL, SU_FLAG_NEGINVALID, NULL }, + /* pdu2InputPhaseCurrentThStatus.0.1 = INTEGER: good(1) */ + { "input.current.status", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.2.2.1.12.%i.1", + NULL, SU_FLAG_OK, &hpe_pdu_threshold_status_info[0] }, + { "ups.alarm", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.2.2.1.12.%i.1", + NULL, SU_FLAG_OK, &hpe_pdu_threshold_current_alarms_info[0] }, + /* pdu2InputPhaseCurrentThLowerWarning.0.1 = INTEGER: 0 */ + { "input.current.low.warning", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.2.2.1.13.%i.1", + NULL, SU_FLAG_NEGINVALID, NULL }, + /* pdu2InputPhaseCurrentThLowerCritical.0.1 = INTEGER: -1 */ + { "input.current.low.critical", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.2.2.1.14.%i.1", + NULL, SU_FLAG_NEGINVALID, NULL }, + /* pdu2InputPhaseCurrentThUpperWarning.0.1 = INTEGER: 19200 */ + { "input.current.high.warning", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.2.2.1.15.%i.1", + NULL, SU_FLAG_NEGINVALID, NULL }, + /* pdu2InputPhaseCurrentThUpperCritical.0.1 = INTEGER: 24000 */ + { "input.current.high.critical", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.2.2.1.16.%i.1", + NULL, SU_FLAG_NEGINVALID, NULL }, + /* pdu2InputPhaseCurrent.0.1 = INTEGER: 185 */ + { "input.L1.current", 0, 0.001, + ".1.3.6.1.4.1.232.165.7.2.2.1.11.%i.1", + NULL, 0, NULL }, + /* pdu2InputPhaseCurrentRating.0.1 = INTEGER: 24000 */ + { "input.L1.current.nominal", 0, 0.001, + ".1.3.6.1.4.1.232.165.7.2.2.1.10.%i.1", + NULL, SU_FLAG_NEGINVALID, NULL }, + /* pdu2InputPhaseCurrentThStatus.0.1 = INTEGER: good(1) */ + { "input.L1.current.status", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.2.2.1.12.%i.1", + NULL, SU_FLAG_OK, &hpe_pdu_threshold_status_info[0] }, + { "L1.alarm", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.2.2.1.12.%i.1", + NULL, SU_FLAG_OK, &hpe_pdu_threshold_current_alarms_info[0] }, + /* pdu2InputPhaseCurrentThLowerWarning.0.1 = INTEGER: 0 */ + { "input.L1.current.low.warning", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.2.2.1.13.%i.1", + NULL, SU_FLAG_NEGINVALID, NULL }, + /* pdu2InputPhaseCurrentThLowerCritical.0.1 = INTEGER: -1 */ + { "input.L1.current.low.critical", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.2.2.1.14.%i.1", + NULL, SU_FLAG_NEGINVALID, NULL }, + /* pdu2InputPhaseCurrentThUpperWarning.0.1 = INTEGER: 19200 */ + { "input.L1.current.high.warning", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.2.2.1.15.%i.1", + NULL, SU_FLAG_NEGINVALID, NULL }, + /* pdu2InputPhaseCurrentThUpperCritical.0.1 = INTEGER: 24000 */ + { "input.L1.current.high.critical", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.2.2.1.16.%i.1", + NULL, SU_FLAG_NEGINVALID, NULL }, + /* pdu2InputPhaseCurrent.0.2 = INTEGER: 185 */ + { "input.L2.current", 0, 0.001, + ".1.3.6.1.4.1.232.165.7.2.2.1.11.%i.2", + NULL, 0, NULL }, + /* pdu2InputPhaseCurrentRating.0.2 = INTEGER: 24000 */ + { "input.L2.current.nominal", 0, 0.001, + ".1.3.6.1.4.1.232.165.7.2.2.1.10.%i.2", + NULL, SU_FLAG_NEGINVALID, NULL }, + /* pdu2InputPhaseCurrentThStatus.0.2 = INTEGER: good(1) */ + { "input.L2.current.status", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.2.2.1.12.%i.2", + NULL, SU_FLAG_OK, &hpe_pdu_threshold_status_info[0] }, + { "L2.alarm", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.2.2.1.12.%i.2", + NULL, SU_FLAG_OK, &hpe_pdu_threshold_current_alarms_info[0] }, + /* pdu2InputPhaseCurrentThLowerWarning.0.2 = INTEGER: 0 */ + { "input.L2.current.low.warning", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.2.2.1.13.%i.2", + NULL, SU_FLAG_NEGINVALID, NULL }, + /* pdu2InputPhaseCurrentThLowerCritical.0.2 = INTEGER: -1 */ + { "input.L2.current.low.critical", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.2.2.1.14.%i.2", + NULL, SU_FLAG_NEGINVALID, NULL }, + /* pdu2InputPhaseCurrentThUpperWarning.0.2 = INTEGER: 19200 */ + { "input.L2.current.high.warning", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.2.2.1.15.%i.2", + NULL, SU_FLAG_NEGINVALID, NULL }, + /* pdu2InputPhaseCurrentThUpperCritical.0.2 = INTEGER: 24000 */ + { "input.L2.current.high.critical", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.2.2.1.16.%i.2", + NULL, SU_FLAG_NEGINVALID, NULL }, + /* pdu2InputPhaseCurrent.0.3 = INTEGER: 185 */ + { "input.L3.current", 0, 0.001, + ".1.3.6.1.4.1.232.165.7.2.2.1.11.%i.3", + NULL, 0, NULL }, + /* pdu2InputPhaseCurrentRating.0.3 = INTEGER: 24000 */ + { "input.L3.current.nominal", 0, 0.001, + ".1.3.6.1.4.1.232.165.7.2.2.1.10.%i.3", + NULL, SU_FLAG_NEGINVALID, NULL }, + /* pdu2InputPhaseCurrentThStatus.0.3 = INTEGER: good(1) */ + { "input.L3.current.status", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.2.2.1.12.%i.3", + NULL, SU_FLAG_OK, &hpe_pdu_threshold_status_info[0] }, + { "L2.alarm", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.2.2.1.12.%i.2", + NULL, SU_FLAG_OK, &hpe_pdu_threshold_current_alarms_info[0] }, + /* pdu2InputPhaseCurrentThLowerWarning.0.3 = INTEGER: 0 */ + { "input.L3.current.low.warning", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.2.2.1.13.%i.3", + NULL, SU_FLAG_NEGINVALID, NULL }, + /* pdu2InputPhaseCurrentThLowerCritical.0.3 = INTEGER: -1 */ + { "input.L3.current.low.critical", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.2.2.1.14.%i.3", + NULL, SU_FLAG_NEGINVALID, NULL }, + /* pdu2InputPhaseCurrentThUpperWarning.0.3 = INTEGER: 19200 */ + { "input.L3.current.high.warning", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.2.2.1.15.%i.3", + NULL, SU_FLAG_NEGINVALID, NULL }, + /* pdu2InputPhaseCurrentThUpperCritical.0.3 = INTEGER: 24000 */ + { "input.L3.current.high.critical", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.2.2.1.16.%i.3", + NULL, SU_FLAG_NEGINVALID, NULL }, + /* pdu2InputPowerWatts.0 = INTEGER: 19 */ + { "input.realpower", 0, 1.0, + ".1.3.6.1.4.1.232.165.7.2.1.1.5.%i", + NULL, SU_FLAG_NEGINVALID | SU_FLAG_UNIQUE | SU_FLAG_OK, NULL }, + /* pdu2InputPhasePowerWatts.0.1 = INTEGER: 19 */ + { "input.L1.realpower", 0, 1.0, + ".1.3.6.1.4.1.232.165.7.2.2.1.21.%i.1", + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, + /* pdu2InputPhasePowerWatts.0.2 = INTEGER: 0 */ + { "input.L2.realpower", 0, 1.0, + ".1.3.6.1.4.1.232.165.7.2.2.1.21.%i.2", + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, + /* pdu2InputPhasePowerWatts.0.3 = INTEGER: 0 */ + { "input.L3.realpower", 0, 1.0, + ".1.3.6.1.4.1.232.165.7.2.2.1.21.%i.3", + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, + /* Sum of all phases apparent power, valid for Shark 1ph/3ph only */ + /* pdu2InputPowerVA.0 = INTEGER: 39 */ + { "input.power", 0, 1.0, + ".1.3.6.1.4.1.232.165.7.2.1.1.4.%i", + NULL, SU_FLAG_NEGINVALID | SU_FLAG_UNIQUE | SU_FLAG_OK, NULL }, + /* pdu2InputPhasePowerVA.0.1 = INTEGER: 40 */ + { "input.L1.power", 0, 1.0, + ".1.3.6.1.4.1.232.165.7.2.2.1.20.%i.1", + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, + /* pdu2InputPhasePowerVA.0.2 = INTEGER: 0 */ + { "input.L2.power", 0, 1.0, + ".1.3.6.1.4.1.232.165.7.2.2.1.20.%i.2", + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, + /* pdu2InputPhasePowerVA.0.3 = INTEGER: 0 */ + { "input.L3.power", 0, 1.0, + ".1.3.6.1.4.1.232.165.7.2.2.1.20.%i.3", + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, + + /* TODO: handle statistics */ + /* pdu2InputPowerWattHour.0 = INTEGER: 91819 + { "unmapped.pdu2InputPowerWattHour", 0, 1, ".1.3.6.1.4.1.232.165.7.2.1.1.6.0", NULL, SU_FLAG_OK, NULL }, */ + /* pdu2InputPowerWattHourTimer.0 = STRING: "16/10/2017,17:58:53" + { "unmapped.pdu2InputPowerWattHourTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.7.2.1.1.7.0", NULL, SU_FLAG_OK, NULL }, */ + /* pdu2InputPowerFactor.0 = INTEGER: 483 */ + { "input.powerfactor", 0, 0.001, + ".1.3.6.1.4.1.232.165.7.2.1.1.8.%i", + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, + + /* Ambient collection */ + /* pdu2TemperatureProbeStatus.0.1 = INTEGER: disconnected(1) */ + { "ambient.present", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.4.2.1.3.%i.1", + NULL, SU_FLAG_OK, &hpe_pdu_ambient_presence_info[0] }, + /* pdu2TemperatureThStatus.0.1 = INTEGER: good(1) */ + { "ambient.temperature.status", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.4.2.1.5.%i.1", + NULL, SU_FLAG_OK, &hpe_pdu_threshold_status_info[0] }, + { "ups.alarm", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.4.2.1.5.%i.1", + NULL, SU_FLAG_OK, &hpe_pdu_threshold_temperature_alarms_info[0] }, + /* pdu2TemperatureValue.0.1 = INTEGER: 0 */ + { "ambient.temperature", 0, 0.1, + ".1.3.6.1.4.1.232.165.7.4.2.1.4.%i.1", + NULL, SU_FLAG_OK, NULL }, + /* Low and high threshold use the respective critical levels */ + /* pdu2TemperatureThLowerCritical.0.1 = INTEGER: 50 */ + { "ambient.temperature.low", ST_FLAG_RW, 0.1, + ".1.3.6.1.4.1.232.165.7.4.2.1.7.%i.1", + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, + { "ambient.temperature.low.critical", ST_FLAG_RW, 0.1, + ".1.3.6.1.4.1.232.165.7.4.2.1.7.%i.1", + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, + /* pdu2TemperatureThLowerWarning.0.1 = INTEGER: 100 */ + { "ambient.temperature.low.warning", ST_FLAG_RW, 0.1, + ".1.3.6.1.4.1.232.165.7.4.2.1.6.%i.1", + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, + /* pdu2TemperatureThUpperCritical.0.1 = INTEGER: 650 */ + { "ambient.temperature.high", ST_FLAG_RW, 0.1, + ".1.3.6.1.4.1.232.165.7.4.2.1.9.%i.1", + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, + { "ambient.temperature.high.critical", ST_FLAG_RW, 0.1, + ".1.3.6.1.4.1.232.165.7.4.2.1.9.%i.1", + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, + /* pdu2TemperatureThUpperWarning.0.1 = INTEGER: 200 */ + { "ambient.temperature.high.warning", ST_FLAG_RW, 0.1, + ".1.3.6.1.4.1.232.165.7.4.2.1.8.%i.1", + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, + /* pdu2HumidityThStatus.0.1 = INTEGER: good(1) */ + { "ambient.humidity.status", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.4.3.1.5.%i.1", + NULL, SU_FLAG_OK, &hpe_pdu_threshold_status_info[0] }, + { "ups.alarm", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.4.3.1.5.%i.1", + NULL, SU_FLAG_OK, &hpe_pdu_threshold_humidity_alarms_info[0] }, + /* pdu2HumidityValue.0.1 = INTEGER: 0 */ + { "ambient.humidity", 0, 0.1, + ".1.3.6.1.4.1.232.165.7.4.3.1.4.%i.1", + NULL, SU_FLAG_OK, NULL }, + /* Low and high threshold use the respective critical levels */ + /* pdu2HumidityThLowerCritical.0.1 = INTEGER: 100 */ + { "ambient.humidity.low", ST_FLAG_RW, 0.1, + ".1.3.6.1.4.1.232.165.7.4.3.1.7.%i.1", + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, + { "ambient.humidity.low.critical", ST_FLAG_RW, 0.1, + ".1.3.6.1.4.1.232.165.7.4.3.1.7.%i.1", + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, + /* pdu2HumidityThLowerWarning.0.1 = INTEGER: 200 */ + { "ambient.humidity.low.warning", ST_FLAG_RW, 0.1, + ".1.3.6.1.4.1.232.165.7.4.3.1.6.%i.1", + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, + /* pdu2HumidityThUpperWarning.0.1 = INTEGER: 250 */ + { "ambient.humidity.high.warning", ST_FLAG_RW, 0.1, + ".1.3.6.1.4.1.232.165.7.4.3.1.8.%i.1", + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, + /* pdu2HumidityThUpperCritical.0.1 = INTEGER: 900 */ + { "ambient.humidity.high", ST_FLAG_RW, 0.1, + ".1.3.6.1.4.1.232.165.7.4.3.1.9.%i.1", + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, + { "ambient.humidity.high.critical", ST_FLAG_RW, 0.1, + ".1.3.6.1.4.1.232.165.7.4.3.1.9.%i.1", + NULL, SU_FLAG_NEGINVALID | SU_FLAG_OK, NULL }, + /* Dry contacts on TH module */ + /* pdu2ContactState.0.1 = INTEGER: contactBad(3) */ + { "ambient.contacts.1.status", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.4.4.1.4.%i.1", + NULL, SU_FLAG_OK, &hpe_pdu_ambient_drycontacts_info[0] }, + /* pdu2ContactState.0.2 = INTEGER: contactBad(3) */ + { "ambient.contacts.2.status", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.4.4.1.4.%i.2", + NULL, SU_FLAG_OK, &hpe_pdu_ambient_drycontacts_info[0] }, + + /* Outlet collection */ + { "outlet.id", 0, 1, NULL, + "0", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, + { "outlet.desc", ST_FLAG_RW | ST_FLAG_STRING, 20, NULL, "All outlets", + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, + /* pdu2OutletCount.0 = INTEGER: 24 */ + { "outlet.count", 0, 1, + ".1.3.6.1.4.1.232.165.7.1.2.1.12.%i", + "0", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, + /* outlet template definition + * Indexes start from 1, ie outlet.1 => .1 */ + /* Note: the first definition is used to determine the base index (ie 0 or 1) */ + /* pdu2OutletName.0.%i = STRING: "Outlet L1-%i" */ + { "outlet.%i.desc", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.5.1.1.2.%i.%i", + NULL, SU_FLAG_STATIC | SU_FLAG_OK | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, + /* pdu2OutletControlStatus.0.%i = INTEGER: on(2) */ + { "outlet.%i.status", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.5.2.1.1.%i.%i", + NULL, SU_FLAG_OK | SU_OUTLET | SU_TYPE_DAISY_1, &hpe_pdu_outlet_status_info[0] }, + /* Numeric identifier of the outlet, tied to the whole unit */ + { "outlet.%i.id", 0, 1, NULL, "%i", + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, + + +#if 0 + /* FIXME: the last part of the OID gives the group number (i.e. %i.1 means "group 1") + * Need to address that, without multiple declaration (%i.%i, SU_OUTLET | SU_OUTLET_GROUP)? */ + { "outlet.%i.groupid", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.534.6.6.7.6.2.1.3.%i.%i.1", + NULL, SU_FLAG_STATIC | SU_FLAG_UNIQUE | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, + { "outlet.%i.groupid", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.534.6.6.7.6.2.1.3.%i.%i.2", + NULL, SU_FLAG_STATIC | SU_FLAG_UNIQUE | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, + { "outlet.%i.groupid", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.534.6.6.7.6.2.1.3.%i.%i.3", + NULL, SU_FLAG_STATIC | SU_FLAG_UNIQUE | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, + { "outlet.%i.groupid", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.534.6.6.7.6.2.1.3.%i.%i.4", + NULL, SU_FLAG_STATIC | SU_FLAG_UNIQUE | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, + { "outlet.%i.groupid", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.534.6.6.7.6.2.1.3.%i.%i.5", + NULL, SU_FLAG_STATIC | SU_FLAG_UNIQUE | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, + { "outlet.%i.groupid", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.534.6.6.7.6.2.1.3.%i.%i.6", + NULL, SU_FLAG_STATIC | SU_FLAG_UNIQUE | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, +#endif + + /* pdu2OutletCurrent.0.%i = INTEGER: 0 */ + { "outlet.%i.current", 0, 0.001, + ".1.3.6.1.4.1.232.165.7.5.1.1.5.%i.%i", + NULL, SU_OUTLET | SU_TYPE_DAISY_1, NULL }, + /* pdu2OutletCurrentThStatus.0.%i = INTEGER: good(1) */ + { "outlet.%i.current.status", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.5.1.1.6.%i.%i", + NULL, SU_OUTLET | SU_TYPE_DAISY_1, &hpe_pdu_threshold_status_info[0] }, + { "outlet.%i.alarm", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.5.1.1.6.%i.%i", + NULL, SU_OUTLET | SU_TYPE_DAISY_1, &hpe_pdu_threshold_current_alarms_info[0] }, + /* pdu2OutletCurrentThLowerWarning.0.%i = INTEGER: 0 */ + { "outlet.%i.current.low.warning", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.5.1.1.7.%i.%i", + NULL, SU_FLAG_NEGINVALID | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, + /* pdu2OutletCurrentThLowerCritical.0.%i = INTEGER: -1 */ + { "outlet.%i.current.low.critical", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.5.1.1.8.%i.%i", + NULL, SU_FLAG_NEGINVALID | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, + /* pdu2OutletCurrentThUpperWarning.0.1 = INTEGER: 8000 */ + { "outlet.%i.current.high.warning", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.5.1.1.9.%i.%i", + NULL, SU_FLAG_NEGINVALID | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, + /* pdu2OutletCurrentThUpperCritical.0.1 = INTEGER: 10000 */ + { "outlet.%i.current.high.critical", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.5.1.1.10.%i.%i", + NULL, SU_FLAG_NEGINVALID | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, + /* pdu2OutletWatts.0.1 = INTEGER: 0 */ + { "outlet.%i.realpower", 0, 1.0, + ".1.3.6.1.4.1.232.165.7.5.1.1.14.%i.%i", + NULL, SU_FLAG_NEGINVALID | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, + /* pdu2OutletVA.0.%i = INTEGER: 0 */ + { "outlet.%i.power", 0, 1.0, + ".1.3.6.1.4.1.232.165.7.5.1.1.13.%i.%i", + NULL, SU_OUTLET | SU_TYPE_DAISY_1, NULL }, + /* pdu2OutletControlSwitchable.0.%i = INTEGER: switchable(1) */ + { "outlet.%i.switchable", ST_FLAG_RW, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.5.2.1.8.%i.%i", + "no", SU_FLAG_STATIC | SU_OUTLET | SU_FLAG_OK | SU_TYPE_DAISY_1, + &hpe_pdu_outlet_switchability_info[0] }, + /* pdu2OutletType.0.%i = INTEGER: iecC13(1) */ + { "outlet.%i.type", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.5.1.1.3.%i.%i", + "unknown", SU_FLAG_STATIC | SU_OUTLET | SU_TYPE_DAISY_1, + &hpe_pdu_outlet_type_info[0] }, + /* pdu2OutletPowerFactor.0.%i = INTEGER: 1000 */ + { "outlet.%i.powerfactor", 0, 0.001, + ".1.3.6.1.4.1.232.165.7.5.1.1.17.%i.%i", + NULL, SU_OUTLET | SU_TYPE_DAISY_1, NULL }, + /* TODO: handle statistics */ + /* pdu2OutletWh.0.1 = INTEGER: 1167 + * Note: setting this to zero resets the counter and timestamp => instcmd ???counter???.reset + { "unmapped.pdu2OutletWh", 0, 1, ".1.3.6.1.4.1.232.165.7.5.1.1.15.%i.%i", NULL, SU_FLAG_OK, NULL }, */ + /* pdu2OutletWhTimer.0.1 = STRING: "25/03/2016,09:03:26" + { "unmapped.pdu2OutletWhTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.7.5.1.1.16.%i.%i", NULL, SU_FLAG_OK, NULL }, */ + + /* Outlet groups collection */ + /* pdu2GroupCount.0 = INTEGER: 3 */ + { "outlet.group.count", 0, 1, + ".1.3.6.1.4.1.232.165.7.1.2.1.11.%i", + "0", SU_FLAG_STATIC | SU_TYPE_DAISY_1, NULL }, + /* outlet groups template definition + * Indexes start from 1, ie outlet.group.1 => .1 */ + /* Note: the first definition is used to determine the base index (ie 0 or 1) */ + /* pdu2GroupIndex.0.%i = INTEGER: %i */ + { "outlet.group.%i.id", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.3.1.1.1.%i.%i", + NULL, SU_FLAG_STATIC | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL }, + /* pdu2GroupName.0.%i = STRING: "Section L1" */ + { "outlet.group.%i.name", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.3.1.1.2.%i.%i", + NULL, SU_FLAG_STATIC | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL }, + /* pdu2GroupType.0.%i = INTEGER: breaker2pole(3) */ + { "outlet.group.%i.type", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.3.1.1.3.%i.%i", + NULL, SU_FLAG_STATIC | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, &hpe_pdu_outlet_group_type_info[0] }, + /* pdu2GroupVoltageMeasType.0.1 = INTEGER: phase1to2(5) */ + { "outlet.group.%i.phase", 0, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.3.1.1.4.%i.%i", + NULL, SU_FLAG_STATIC | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, + &hpe_pdu_outlet_group_phase_info[0] }, + /* pdu2groupBreakerStatus.0.%i = INTEGER: breakerOn(2) */ + { "outlet.group.%i.status", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.3.1.1.27.%i.%i", + NULL, SU_FLAG_OK | SU_FLAG_NAINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, + &hpe_pdu_outletgroups_status_info[0] }, + /* pdu2GroupOutletCount.0.%i = INTEGER: 8 */ + { "outlet.group.%i.count", 0, 1, + ".1.3.6.1.4.1.232.165.7.3.1.1.26.%i.%i", + NULL, SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL }, + /* pdu2GroupVoltage.0.%i = INTEGER: 216760 */ + { "outlet.group.%i.voltage", 0, 0.001, + ".1.3.6.1.4.1.232.165.7.3.1.1.5.%i.%i", + NULL, SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL }, + /* pdu2GroupVoltageThStatus.0.%i = INTEGER: good(1) */ + { "outlet.group.%i.voltage.status", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.3.1.1.6.%i.%i", + NULL, SU_OUTLET_GROUP | SU_TYPE_DAISY_1, + &hpe_pdu_threshold_status_info[0] }, + { "outlet.group.%i.alarm", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.3.1.1.6.%i.%i", + NULL, SU_OUTLET_GROUP | SU_TYPE_DAISY_1, + &hpe_pdu_threshold_voltage_alarms_info[0] }, + /* pdu2GroupVoltageThLowerWarning.0.%i = INTEGER: 190000 */ + { "outlet.group.%i.voltage.low.warning", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.3.1.1.7.%i.%i", + NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL }, + /* pdu2GroupVoltageThLowerCritical.0.%i = INTEGER: 180000 */ + { "outlet.group.%i.voltage.low.critical", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.3.1.1.8.%i.%i", + NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL }, + /* pdu2GroupVoltageThUpperWarning.0.%i = INTEGER: 255000 */ + { "outlet.group.%i.voltage.high.warning", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.3.1.1.9.%i.%i", + NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL }, + /* pdu2GroupVoltageThUpperCritical.0.%i = INTEGER: 265000 */ + { "outlet.group.%i.voltage.high.critical", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.3.1.1.10.%i.%i", + NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL }, + /* pdu2GroupCurrent.0.%i = INTEGER: 0 */ + { "outlet.group.%i.current", 0, 0.001, + ".1.3.6.1.4.1.232.165.7.3.1.1.12.%i.%i", + NULL, SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL }, + /* pdu2groupCurrentRating.0.%i = INTEGER: 16000 */ + { "outlet.group.%i.current.nominal", 0, 0.001, + ".1.3.6.1.4.1.232.165.7.3.1.1.11.%i.%i", + NULL, SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL }, + /* pdu2GroupCurrentThStatus.0.%i = INTEGER: good(1) */ + { "outlet.group.%i.current.status", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.3.1.1.13.%i.%i", + NULL, SU_OUTLET_GROUP | SU_TYPE_DAISY_1, + &hpe_pdu_threshold_status_info[0] }, + { "outlet.group.%i.alarm", ST_FLAG_STRING, SU_INFOSIZE, + ".1.3.6.1.4.1.232.165.7.3.1.1.13.%i.%i", + NULL, SU_OUTLET_GROUP | SU_TYPE_DAISY_1, + &hpe_pdu_threshold_current_alarms_info[0] }, + /* pdu2GroupCurrentThLowerWarning.0.%i = INTEGER: 0 */ + { "outlet.group.%i.current.low.warning", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.3.1.1.14.%i.%i", + NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL }, + /* pdu2GroupCurrentThLowerCritical.0.%i = INTEGER: -1 */ + { "outlet.group.%i.current.low.critical", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.3.1.1.15.%i.%i", + NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL }, + /* pdu2GroupCurrentThUpperWarning.0.%i = INTEGER: 12800 */ + { "outlet.group.%i.current.high.warning", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.3.1.1.16.%i.%i", + NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL }, + /* pdu2GroupCurrentThUpperCritical.0.%i = INTEGER: 16000 */ + { "outlet.group.%i.current.high.critical", ST_FLAG_RW, 0.001, + ".1.3.6.1.4.1.232.165.7.3.1.1.17.%i.%i", + NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL }, + /* pdu2GroupCurrentPercentLoad.0.%i = INTEGER: 0 */ + { "outlet.group.%i.load", 0, 1.0, + ".1.3.6.1.4.1.232.165.7.3.1.1.19.%i.%i", + NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL }, + /* pdu2GroupPowerWatts.0.%i = INTEGER: 0 */ + { "outlet.group.%i.realpower", 0, 1.0, + ".1.3.6.1.4.1.232.165.7.3.1.1.21.%i.%i", + NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL }, + /* pdu2GroupPowerVA.0.%i = INTEGER: 0 */ + { "outlet.group.%i.power", 0, 1.0, + ".1.3.6.1.4.1.232.165.7.3.1.1.20.%i.%i", + NULL, SU_FLAG_NEGINVALID | SU_OUTLET_GROUP | SU_TYPE_DAISY_1, NULL }, + /* pdu2GroupPowerFactor.0.%i = INTEGER: 1000 */ + { "outlet.group.%i.powerfactor", 0, 0.001, + ".1.3.6.1.4.1.232.165.7.3.1.1.24.%i.%i", + NULL, SU_OUTLET | SU_TYPE_DAISY_1, NULL }, + + /* TODO: handle statistics */ + /* pdu2GroupPowerWattHour.0.%i = INTEGER: 1373 + * Note: setting this to zero resets the counter and timestamp => instcmd .reset + { "unmapped.pdu2GroupPowerWattHour", 0, 1, ".1.3.6.1.4.1.232.165.7.3.1.1.22.%i.%i", NULL, SU_FLAG_OK, NULL }, */ + /* pdu2GroupPowerWattHourTimer.0.%i = STRING: "25/03/2016,09:01:16" + { "unmapped.pdu2GroupPowerWattHourTimer", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.232.165.7.3.1.1.23.%i.%i", NULL, SU_FLAG_OK, NULL }, */ + + /* instant commands. */ + /* TODO: handle delays (outlet.%i.{on,off}.delay) */ + /* pdu2OutletControlOffCmd.0.%i = INTEGER: -1 */ + { "outlet.%i.load.off", 0, 1, + ".1.3.6.1.4.1.232.165.7.5.2.1.2.%i.%i", + "0", SU_TYPE_CMD | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, + /* pdu2OutletControlOnCmd.0.%i = INTEGER: -1 */ + { "outlet.%i.load.on", 0, 1, + ".1.3.6.1.4.1.232.165.7.5.2.1.3.%i.%i", + "0", SU_TYPE_CMD | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, + /* pdu2OutletControlRebootCmd.0.%i = INTEGER: -1 */ + { "outlet.%i.load.cycle", 0, 1, + ".1.3.6.1.4.1.232.165.7.5.2.1.4.%i.%i", + "0", SU_TYPE_CMD | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, + /* Delayed version, parameter is mandatory (so dfl is NULL)! */ + /* pdu2OutletControlOffCmd.0.%i = INTEGER: -1 */ + { "outlet.%i.load.off.delay", 0, 1, + ".1.3.6.1.4.1.232.165.7.5.2.1.2.%i.%i", + NULL, SU_TYPE_CMD | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, + /* pdu2OutletControlOnCmd.0.%i = INTEGER: -1 */ + { "outlet.%i.load.on.delay", 0, 1, + ".1.3.6.1.4.1.232.165.7.5.2.1.3.%i.%i", + NULL, SU_TYPE_CMD | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, + /* pdu2OutletControlRebootCmd.0.%i = INTEGER: -1 */ + { "outlet.%i.load.cycle.delay", 0, 1, + ".1.3.6.1.4.1.232.165.7.5.2.1.4.%i.%i", + NULL, SU_TYPE_CMD | SU_OUTLET | SU_TYPE_DAISY_1, NULL }, + + /* end of structure. */ + { NULL, 0, 0, NULL, NULL, 0, NULL } +}; + + +mib2nut_info_t hpe_pdu = { "hpe_epdu", HPE_EPDU_MIB_VERSION, NULL, HPE_EPDU_OID_MODEL_NAME, hpe_pdu_mib, HPE_EPDU_MIB_SYSOID }; + diff --git a/drivers/hpe-pdu-mib.h b/drivers/hpe-pdu-mib.h new file mode 100644 index 0000000000..0ccfcdf235 --- /dev/null +++ b/drivers/hpe-pdu-mib.h @@ -0,0 +1,30 @@ +/* hpe-pdu-mib.h - subdriver to monitor HPE ePDU SNMP devices with NUT + * + * Copyright (C) + * 2011 - 2016 Arnaud Quette + * 2019 Arnaud Quette + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef HPE_EPDU_MIB_H +#define HPE_EPDU_MIB_H + +#include "main.h" +#include "snmp-ups.h" + +extern mib2nut_info_t hpe_pdu; + +#endif /* HPE_EPDU_MIB_H */ diff --git a/drivers/huawei-mib.c b/drivers/huawei-mib.c index 1d029b3aeb..8374fd6b39 100644 --- a/drivers/huawei-mib.c +++ b/drivers/huawei-mib.c @@ -21,10 +21,11 @@ #include "huawei-mib.h" -#define HUAWEI_MIB_VERSION "0.1" +#define HUAWEI_MIB_VERSION "0.2" #define HUAWEI_SYSOID ".1.3.6.1.4.1.8072.3.2.10" #define HUAWEI_UPSMIB ".1.3.6.1.4.1.2011" +#define HUAWEI_OID_MODEL_NAME ".1.3.6.1.4.1.2011.6.174.1.2.100.1.2.1" /* To create a value lookup structure (as needed on the 2nd line of the example * below), use the following kind of declaration, outside of the present snmp_info_t[]: @@ -35,7 +36,7 @@ * }; */ -static info_lkp_t supplymethod_info[] = { +static info_lkp_t huawei_supplymethod_info[] = { { 1, "" }, /* no supply */ { 2, "OL BYPASS" }, { 3, "OL" }, @@ -46,7 +47,7 @@ static info_lkp_t supplymethod_info[] = { { 0, NULL } }; -static info_lkp_t battstate_info[] = { +static info_lkp_t huawei_battstate_info[] = { { 1, "" }, /* not connected */ { 2, "" }, /* not charging or discharging */ { 3, "" }, /* hibernation */ @@ -56,13 +57,13 @@ static info_lkp_t battstate_info[] = { { 0, NULL } }; -static info_lkp_t phase_info[] = { +static info_lkp_t huawei_phase_info[] = { { 1, "1" }, { 2, "3" }, { 0, NULL } }; -static info_lkp_t voltrating_info[] = { +static info_lkp_t huawei_voltrating_info[] = { { 1, "200" }, { 2, "208" }, { 3, "220" }, @@ -75,13 +76,13 @@ static info_lkp_t voltrating_info[] = { { 0, NULL } }; -static info_lkp_t freqrating_info[] = { +static info_lkp_t huawei_freqrating_info[] = { { 1, "50" }, { 2, "60" }, { 0, NULL } }; -static info_lkp_t pwrrating_info[] = { +static info_lkp_t huawei_pwrrating_info[] = { { 1, "80000" }, { 2, "100000" }, { 3, "120000" }, @@ -97,7 +98,11 @@ static info_lkp_t pwrrating_info[] = { { 0, NULL } }; -static info_lkp_t ietf_test_result_info[] = { +/* Note: This is currently identical to ietf_test_result_info from IETF MIB + * We rename it here to a) allow evolution that may become incompatible; + * b) avoid namespace conflicts, especially with DMF loader of named objects + */ +static info_lkp_t huawei_test_result_info[] = { { 1, "done and passed" }, { 2, "done and warning" }, { 3, "done and error" }, @@ -122,7 +127,6 @@ static snmp_info_t huawei_mib[] = { * dfl: default value * flags: snmp-ups internal flags (FIXME: ...) * oid2info: lookup table between OID and NUT values - * setvar: variable to set for SU_FLAG_SETINT * * Example: * { "input.voltage", 0, 0.1, ".1.3.6.1.4.1.705.1.6.2.1.2.1", "", SU_INPUT_1, NULL }, @@ -148,16 +152,16 @@ static snmp_info_t huawei_mib[] = { { "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.2011.6.174.1.2.100.1.3.1", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL }, { "ups.serial", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.2011.6.174.1.2.100.1.5.1", NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL }, - { "ups.status", 0, 1, ".1.3.6.1.4.1.2011.6.174.1.2.101.1.1.1", NULL, SU_FLAG_OK, supplymethod_info }, - { "ups.status", 0, 1, ".1.3.6.1.4.1.2011.6.174.1.2.101.1.3.1", NULL, SU_STATUS_BATT | SU_FLAG_OK, battstate_info }, + { "ups.status", 0, 1, ".1.3.6.1.4.1.2011.6.174.1.2.101.1.1.1", NULL, SU_FLAG_OK, huawei_supplymethod_info }, + { "ups.status", 0, 1, ".1.3.6.1.4.1.2011.6.174.1.2.101.1.3.1", NULL, SU_STATUS_BATT | SU_FLAG_OK, huawei_battstate_info }, - { "ups.test.result", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.2.1.33.1.7.3.0", "", 0, ietf_test_result_info }, + { "ups.test.result", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.2.1.33.1.7.3.0", "", 0, huawei_test_result_info }, /* Input page */ /* hwUpsCtrlInputStandard listed in MIB but not present on tested UPS5000-E */ - { "input.phases", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.2011.6.174.1.102.100.1.8", "3", SU_FLAG_ABSENT | SU_FLAG_OK, phase_info }, + { "input.phases", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.2011.6.174.1.102.100.1.8", "3", SU_FLAG_ABSENT | SU_FLAG_OK, huawei_phase_info }, { "input.L1-N.voltage", 0, 0.1, ".1.3.6.1.4.1.2011.6.174.1.3.100.1.1.1", NULL, SU_FLAG_OK, NULL }, { "input.L2-N.voltage", 0, 0.1, ".1.3.6.1.4.1.2011.6.174.1.3.100.1.2.1", NULL, SU_FLAG_OK, NULL }, @@ -183,7 +187,7 @@ static snmp_info_t huawei_mib[] = { /* Output page */ /* hwUpsCtrlOutputStandard listed in MIB but not present on tested UPS5000-E */ - { "output.phases", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.2011.6.174.1.102.100.1.9", "3", SU_FLAG_ABSENT | SU_FLAG_OK, phase_info }, + { "output.phases", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.2011.6.174.1.102.100.1.9", "3", SU_FLAG_ABSENT | SU_FLAG_OK, huawei_phase_info }, { "output.L1-N.voltage", 0, 0.1, ".1.3.6.1.4.1.2011.6.174.1.4.100.1.1.1", NULL, SU_FLAG_OK, NULL }, { "output.L2-N.voltage", 0, 0.1, ".1.3.6.1.4.1.2011.6.174.1.4.100.1.2.1", NULL, SU_FLAG_OK, NULL }, @@ -207,9 +211,9 @@ static snmp_info_t huawei_mib[] = { { "output.L2.power.percent", 0, 0.1, ".1.3.6.1.4.1.2011.6.174.1.4.100.1.15.1", NULL, SU_FLAG_OK, NULL }, { "output.L3.power.percent", 0, 0.1, ".1.3.6.1.4.1.2011.6.174.1.4.100.1.16.1", NULL, SU_FLAG_OK, NULL }, - { "output.voltage.nominal", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.2011.6.174.1.4.100.1.17.1", NULL, SU_FLAG_STATIC | SU_FLAG_OK, voltrating_info }, - { "output.frequency.nominal", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.2011.6.174.1.4.100.1.18.1", NULL, SU_FLAG_STATIC | SU_FLAG_OK, freqrating_info }, - { "output.power.nominal", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.2011.6.174.1.2.100.1.6.1", NULL, SU_FLAG_STATIC | SU_FLAG_OK, pwrrating_info }, + { "output.voltage.nominal", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.2011.6.174.1.4.100.1.17.1", NULL, SU_FLAG_STATIC | SU_FLAG_OK, huawei_voltrating_info }, + { "output.frequency.nominal", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.2011.6.174.1.4.100.1.18.1", NULL, SU_FLAG_STATIC | SU_FLAG_OK, huawei_freqrating_info }, + { "output.power.nominal", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.2011.6.174.1.2.100.1.6.1", NULL, SU_FLAG_STATIC | SU_FLAG_OK, huawei_pwrrating_info }, { "output.L1.powerfactor", 0, 0.01, ".1.3.6.1.4.1.2011.6.174.1.4.100.1.19.1", NULL, SU_FLAG_OK, NULL }, { "output.L2.powerfactor", 0, 0.01, ".1.3.6.1.4.1.2011.6.174.1.4.100.1.20.1", NULL, SU_FLAG_OK, NULL }, @@ -231,4 +235,4 @@ static snmp_info_t huawei_mib[] = { { NULL, 0, 0, NULL, NULL, 0, NULL } }; -mib2nut_info_t huawei = { "huawei", HUAWEI_MIB_VERSION, NULL, NULL, huawei_mib, HUAWEI_SYSOID }; +mib2nut_info_t huawei = { "huawei", HUAWEI_MIB_VERSION, NULL, HUAWEI_OID_MODEL_NAME, huawei_mib, HUAWEI_SYSOID }; diff --git a/drivers/ietf-mib.c b/drivers/ietf-mib.c index 56925cde8d..c8b0a0ee03 100644 --- a/drivers/ietf-mib.c +++ b/drivers/ietf-mib.c @@ -26,7 +26,7 @@ #include "ietf-mib.h" -#define IETF_MIB_VERSION "1.51" +#define IETF_MIB_VERSION "1.52" /* SNMP OIDs set */ #define IETF_OID_UPS_MIB "1.3.6.1.2.1.33.1." @@ -135,7 +135,7 @@ static snmp_info_t ietf_mib[] = { #ifdef DEBUG { "debug.upsInputLineBads", 0, 1.0, IETF_OID_UPS_MIB "3.1.0", "", 0, NULL }, /* upsInputLineBads */ #endif - { "input.phases", 0, 1.0, IETF_OID_UPS_MIB "3.2.0", "", 0, NULL, NULL }, /* upsInputNumLines */ + { "input.phases", 0, 1.0, IETF_OID_UPS_MIB "3.2.0", "", 0, NULL }, /* upsInputNumLines */ #ifdef DEBUG { "debug.upsInputLineIndex", 0, 1.0, IETF_OID_UPS_MIB "3.3.1.1.1", "", SU_INPUT_1, NULL }, /* upsInputLineIndex */ { "debug.[1].upsInputLineIndex", 0, 1.0, IETF_OID_UPS_MIB "3.3.1.1.1", "", SU_INPUT_3, NULL }, @@ -162,7 +162,7 @@ static snmp_info_t ietf_mib[] = { /* Output Group */ { "ups.status", ST_FLAG_STRING, SU_INFOSIZE, IETF_OID_UPS_MIB "4.1.0", "", SU_STATUS_PWR, ietf_power_source_info }, /* upsOutputSource */ { "output.frequency", 0, 0.1, IETF_OID_UPS_MIB "4.2.0", "", 0, NULL }, /* upsOutputFrequency */ - { "output.phases", 0, 1.0, IETF_OID_UPS_MIB "4.3.0", "", 0, NULL, NULL }, /* upsOutputNumLines */ + { "output.phases", 0, 1.0, IETF_OID_UPS_MIB "4.3.0", "", 0, NULL }, /* upsOutputNumLines */ #ifdef DEBUG { "debug.upsOutputLineIndex", 0, 1.0, IETF_OID_UPS_MIB "4.4.1.1.1", "", SU_OUTPUT_1, NULL }, /* upsOutputLineIndex */ { "debug.[1].upsOutputLineIndex", 0, 1.0, IETF_OID_UPS_MIB "4.4.1.1.1", "", SU_OUTPUT_3, NULL }, @@ -187,7 +187,7 @@ static snmp_info_t ietf_mib[] = { { "output.L3.power.percent", 0, 1.0, IETF_OID_UPS_MIB "4.4.1.5.3", "", SU_OUTPUT_3, NULL }, /* Bypass Group */ - { "input.bypass.phases", 0, 1.0, IETF_OID_UPS_MIB "5.2.0", "", 0, NULL, NULL }, /* upsBypassNumLines */ + { "input.bypass.phases", 0, 1.0, IETF_OID_UPS_MIB "5.2.0", "", 0, NULL }, /* upsBypassNumLines */ { "input.bypass.frequency", 0, 0.1, IETF_OID_UPS_MIB "5.1.0", "", SU_BYPASS_1 | SU_BYPASS_3, NULL }, /* upsBypassFrequency */ #ifdef DEBUG { "debug.upsBypassLineIndex", 0, 1.0, IETF_OID_UPS_MIB "5.3.1.1.1", "", SU_BYPASS_1, NULL }, /* upsBypassLineIndex */ @@ -241,10 +241,10 @@ static snmp_info_t ietf_mib[] = { /* Test Group */ { "ups.status", ST_FLAG_STRING, SU_INFOSIZE, IETF_OID_UPS_MIB "7.1.0", "", 0, ietf_test_active_info }, /* upsTestId */ - { "test.battery.stop", 0, 0, IETF_OID_UPS_MIB "7.1.0", IETF_OID_UPS_MIB "7.7.2", SU_TYPE_CMD, NULL }, /* upsTestAbortTestInProgress */ - { "test.battery.start", 0, 0, IETF_OID_UPS_MIB "7.1.0", IETF_OID_UPS_MIB "7.7.3", SU_TYPE_CMD, NULL }, /* upsTestGeneralSystemsTest */ - { "test.battery.start.quick", 0, 0, IETF_OID_UPS_MIB "7.1.0", IETF_OID_UPS_MIB "7.7.4", SU_TYPE_CMD, NULL }, /* upsTestQuickBatteryTest */ - { "test.battery.start.deep", 0, 0, IETF_OID_UPS_MIB "7.1.0", IETF_OID_UPS_MIB "7.7.5", SU_TYPE_CMD, NULL }, /* upsTestDeepBatteryCalibration */ + { "test.battery.stop", 0, 1, IETF_OID_UPS_MIB "7.1.0", "0", SU_TYPE_CMD, NULL }, /* upsTestAbortTestInProgress */ + { "test.battery.start", 0, 1, IETF_OID_UPS_MIB "7.1.0", "0", SU_TYPE_CMD, NULL }, /* upsTestGeneralSystemsTest */ + { "test.battery.start.quick", 0, 1, IETF_OID_UPS_MIB "7.1.0", "0", SU_TYPE_CMD, NULL }, /* upsTestQuickBatteryTest */ + { "test.battery.start.deep", 0, 1, IETF_OID_UPS_MIB "7.1.0", "0", SU_TYPE_CMD, NULL }, /* upsTestDeepBatteryCalibration */ #ifdef DEBUG { "debug.upsTestSpinLock", 0, 1.0, IETF_OID_UPS_MIB "7.2.0", "", 0, NULL }, /* upsTestSpinLock */ #endif @@ -260,9 +260,9 @@ static snmp_info_t ietf_mib[] = { { "debug.upsShutdownType", ST_FLAG_STRING, SU_INFOSIZE, IETF_OID_UPS_MIB "8.1.0", "", 0, ietf_shutdown_type_info }, /* upsShutdownType */ #endif { "ups.timer.shutdown", ST_FLAG_STRING | ST_FLAG_RW, 8, IETF_OID_UPS_MIB "8.2.0", "", 0, NULL }, /* upsShutdownAfterDelay*/ - { "load.off", 0, 0, IETF_OID_UPS_MIB "8.2.0", "", SU_TYPE_CMD, NULL }, + { "load.off", 0, 1, IETF_OID_UPS_MIB "8.2.0", "0", SU_TYPE_CMD, NULL }, { "ups.timer.start", ST_FLAG_STRING | ST_FLAG_RW, 8, IETF_OID_UPS_MIB "8.3.0", "", 0, NULL }, /* upsStartupAfterDelay */ - { "load.on", 0, 0, IETF_OID_UPS_MIB "8.3.0", "", SU_TYPE_CMD, NULL }, + { "load.on", 0, 1, IETF_OID_UPS_MIB "8.3.0", "0", SU_TYPE_CMD, NULL }, { "ups.timer.reboot", ST_FLAG_STRING | ST_FLAG_RW, 8, IETF_OID_UPS_MIB "8.4.0", "", 0, NULL }, /* upsRebootWithDuration */ { "ups.start.auto", ST_FLAG_STRING, SU_INFOSIZE, IETF_OID_UPS_MIB "8.5.0", "", 0, ietf_yes_no_info }, /* upsAutoRestart */ @@ -275,9 +275,9 @@ static snmp_info_t ietf_mib[] = { { "output.realpower.nominal", 0, 1.0, IETF_OID_UPS_MIB "9.6.0", "", 0, NULL }, /* upsConfigOutputPower */ { "battery.runtime.low", 0, 60.0, IETF_OID_UPS_MIB "9.7.0", "", 0, NULL }, /* upsConfigLowBattTime */ { "ups.beeper.status", ST_FLAG_STRING, SU_INFOSIZE, IETF_OID_UPS_MIB "9.8.0", "", 0, ietf_beeper_status_info }, /* upsConfigAudibleStatus */ - { "beeper.disable", 0, 1, IETF_OID_UPS_MIB "9.8.0", "", SU_TYPE_CMD, NULL }, - { "beeper.enable", 0, 2, IETF_OID_UPS_MIB "9.8.0", "", SU_TYPE_CMD, NULL }, - { "beeper.mute", 0, 3, IETF_OID_UPS_MIB "9.8.0", "", SU_TYPE_CMD, NULL }, + { "beeper.disable", 0, 1, IETF_OID_UPS_MIB "9.8.0", "1", SU_TYPE_CMD, NULL }, + { "beeper.enable", 0, 1, IETF_OID_UPS_MIB "9.8.0", "2", SU_TYPE_CMD, NULL }, + { "beeper.mute", 0, 1, IETF_OID_UPS_MIB "9.8.0", "3", SU_TYPE_CMD, NULL }, { "input.transfer.low", 0, 1.0, IETF_OID_UPS_MIB "9.9.0", "", 0, NULL }, /* upsConfigLowVoltageTransferPoint */ { "input.transfer.high", 0, 1.0, IETF_OID_UPS_MIB "9.10.0", "", 0, NULL }, /* upsConfigHighVoltageTransferPoint */ @@ -285,8 +285,12 @@ static snmp_info_t ietf_mib[] = { { NULL, 0, 0, NULL, NULL, 0, NULL } }; -mib2nut_info_t ietf = { "ietf", IETF_MIB_VERSION, IETF_OID_UPS_MIB "4.1.0", IETF_OID_UPS_MIB "1.1.0", ietf_mib, IETF_SYSOID }; - /* FIXME: Rename the structure here (or even relocate to new file) * and in snmp-ups.c when the real TrippLite mappings get defined. */ +/* FIXME: Duplicate the line below to fix an issue with the code generator (nut-snmpinfo.py -> line is discarding) */ +/*mib2nut_info_t tripplite_ietf = { "tripplite", IETF_MIB_VERSION, NULL, NULL, ietf_mib, TRIPPLITE_SYSOID };*/ mib2nut_info_t tripplite_ietf = { "tripplite", IETF_MIB_VERSION, NULL, NULL, ietf_mib, TRIPPLITE_SYSOID }; + +/* FIXME: Duplicate the line below to fix an issue with the code generator (nut-snmpinfo.py -> line is discarding) */ +/*mib2nut_info_t ietf = { "ietf", IETF_MIB_VERSION, IETF_OID_UPS_MIB "4.1.0", IETF_OID_UPS_MIB "1.1.0", ietf_mib, IETF_SYSOID };*/ +mib2nut_info_t ietf = { "ietf", IETF_MIB_VERSION, IETF_OID_UPS_MIB "4.1.0", IETF_OID_UPS_MIB "1.1.0", ietf_mib, IETF_SYSOID }; diff --git a/drivers/libshut.c b/drivers/libshut.c index ac132e2504..c9417b3069 100644 --- a/drivers/libshut.c +++ b/drivers/libshut.c @@ -476,7 +476,7 @@ int libshut_open(int *upsfd, SHUTDevice_t *curDevice, char *device_path, upsdebugx(2, "Report descriptor too short (expected %d, got %d)", rdlen, res); } - upsdebugx(2, "No appropriate HID device found"); + upsdebugx(2, "libshut: No appropriate HID device found"); fflush(stdout); return -1; diff --git a/drivers/libusb.c b/drivers/libusb.c index 1d4688c645..0eb054a76d 100644 --- a/drivers/libusb.c +++ b/drivers/libusb.c @@ -173,6 +173,8 @@ static int libusb_open(usb_dev_handle **udevp, USBDevice_t *curDevice, USBDevice libusb_close(*udevp); #endif + upsdebugx(3, "usb_busses=%p", usb_busses); + for (bus = usb_busses; bus; bus = bus->next) { for (dev = bus->devices; dev; dev = dev->next) { upsdebugx(2, "Checking device (%04X/%04X) (%s/%s)", dev->descriptor.idVendor, @@ -410,7 +412,7 @@ static int libusb_open(usb_dev_handle **udevp, USBDevice_t *curDevice, USBDevice } *udevp = NULL; - upsdebugx(2, "No appropriate HID device found"); + upsdebugx(2, "libusb: No appropriate HID device found"); fflush(stdout); return -1; @@ -552,8 +554,8 @@ static void libusb_close(usb_dev_handle *udev) } usb_communication_subdriver_t usb_subdriver = { - USB_DRIVER_VERSION, USB_DRIVER_NAME, + USB_DRIVER_VERSION, libusb_open, libusb_close, libusb_get_report, diff --git a/drivers/main.c b/drivers/main.c old mode 100644 new mode 100755 index 6c181a70a9..945303e4da --- a/drivers/main.c +++ b/drivers/main.c @@ -607,9 +607,9 @@ int main(int argc, char **argv) become_user(new_uid); - /* Only switch to statepath if we're not powering off */ + /* Only switch to statepath if we're not powering off or just dumping data, for discovery */ /* This avoid case where ie /var is umounted */ - if ((!do_forceshutdown) && (chdir(dflt_statepath()))) + if ((!do_forceshutdown) && (!dump_data) && (chdir(dflt_statepath()))) fatal_with_errno(EXIT_FAILURE, "Can't chdir to %s", dflt_statepath()); /* Setup signals to communicate with driver once backgrounded. */ @@ -636,20 +636,23 @@ int main(int argc, char **argv) break; } - upslogx(LOG_WARNING, "Duplicate driver instance detected! Terminating other driver!"); + upslogx(LOG_WARNING, "Duplicate driver instance detected (PID file %s exists)! Terminating other driver!", buffer); /* Allow driver some time to quit */ sleep(5); } - pidfn = xstrdup(buffer); - writepid(pidfn); /* before backgrounding */ + /* Only write pid if we're not just dumping data, for discovery */ + if (!dump_data) { + pidfn = xstrdup(buffer); + writepid(pidfn); /* before backgrounding */ + } } /* clear out callback handler data */ memset(&upsh, '\0', sizeof(upsh)); - /* note: device.type is set early to be overriden by the driver + /* note: device.type is set early to be overridden by the driver * when its a pdu! */ dstate_setinfo("device.type", "ups"); @@ -698,7 +701,9 @@ int main(int argc, char **argv) } /* now we can start servicing requests */ - dstate_init(progname, upsname); + /* Only write pid if we're not just dumping data, for discovery */ + if (!dump_data) + dstate_init(progname, upsname); /* The poll_interval may have been changed from the default */ dstate_setinfo("driver.parameter.pollinterval", "%d", poll_interval); diff --git a/drivers/masterguard.c b/drivers/masterguard.c index 7edc899968..6ae17460a0 100644 --- a/drivers/masterguard.c +++ b/drivers/masterguard.c @@ -474,7 +474,7 @@ void upsdrv_initinfo(void) /******************************************************************** * * This is the main function. It gets called if the driver wants - * to update the ups status and the informations. + * to update the ups status and the information. * ********************************************************************/ void upsdrv_updateinfo(void) diff --git a/drivers/metasys.c b/drivers/metasys.c index 647de3c3ce..36e78f4ac8 100644 --- a/drivers/metasys.c +++ b/drivers/metasys.c @@ -200,7 +200,7 @@ int get_answer(unsigned char *data) { for (i = 0; i < (packet_length - 1); i++) checksum += my_buf[i]; checksum = checksum % 256; if (my_buf[packet_length-1] != checksum) { - ser_comm_fail("checksum error! got %x instad of %x, received %d bytes \n", my_buf[packet_length - 1], checksum, packet_length); + ser_comm_fail("checksum error! got %x instead of %x, received %d bytes \n", my_buf[packet_length - 1], checksum, packet_length); dump_buffer(my_buf, packet_length); return -1; } diff --git a/drivers/mge-hid.c b/drivers/mge-hid.c index 4845059cb9..e0d26eb706 100644 --- a/drivers/mge-hid.c +++ b/drivers/mge-hid.c @@ -38,7 +38,7 @@ #include "mge-hid.h" #include -#define MGE_HID_VERSION "MGE HID 1.43" +#define MGE_HID_VERSION "MGE HID 1.44" /* (prev. MGE Office Protection Systems, prev. MGE UPS SYSTEMS) */ /* Eaton */ @@ -121,7 +121,7 @@ typedef enum { } models_type_t; /* Default to line-interactive or online (ie, not offline). - * This is then overriden for offline, through mge_model_names */ + * This is then overridden for offline, through mge_model_names */ static models_type_t mge_type = MGE_DEFAULT; /* Countries definition, for region specific settings and features */ @@ -789,6 +789,22 @@ static info_lkp_t nominal_output_voltage_info[] = { { 0, NULL, NULL } }; +/* Limit reporting "online / !online" to when "!off" */ +static const char *eaton_converter_online_fun(double value) +{ + int ups_status = ups_status_get(); + + if (!(ups_status & STATUS(OFF))) + return (value == 0) ? "!online" : "online"; + else + return NULL; +} + +info_lkp_t eaton_converter_online_info[] = { + { 0, "dummy", eaton_converter_online_fun }, + { 0, NULL, NULL } +}; + /* --------------------------------------------------------------- */ /* Vendor-specific usage table */ /* --------------------------------------------------------------- */ @@ -1210,7 +1226,6 @@ static hid_info_t mge_hid2nut[] = /* Special case: boolean values that are mapped to ups.status and ups.alarm */ { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.ACPresent", NULL, NULL, HU_FLAG_QUICK_POLL, online_info }, { "BOOL", 0, 0, "UPS.PowerConverter.Input.[3].PresentStatus.Used", NULL, NULL, 0, mge_onbatt_info }, - { "BOOL", 0, 0, "UPS.PowerConverter.Input.[1].PresentStatus.Used", NULL, NULL, 0, online_info }, /* These 2 ones are used when ABM is disabled */ { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.Discharging", NULL, NULL, HU_FLAG_QUICK_POLL, eaton_discharging_info }, { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.Charging", NULL, NULL, HU_FLAG_QUICK_POLL, eaton_charging_info }, @@ -1232,6 +1247,9 @@ static hid_info_t mge_hid2nut[] = { "BOOL", 0, 0, "UPS.PowerConverter.Input.[1].PresentStatus.VoltageOutOfRange", NULL, NULL, 0, vrange_info }, { "BOOL", 0, 0, "UPS.PowerConverter.Input.[1].PresentStatus.FrequencyOutOfRange", NULL, NULL, 0, frange_info }, { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.Good", NULL, NULL, 0, off_info }, + /* NOTE: UPS.PowerConverter.Input.[1].PresentStatus.Used" must only be considered when not "OFF", + * and must hence be after "UPS.PowerSummary.PresentStatus.Good" */ + { "BOOL", 0, 0, "UPS.PowerConverter.Input.[1].PresentStatus.Used", NULL, NULL, 0, eaton_converter_online_info }, { "BOOL", 0, 0, "UPS.PowerConverter.Input.[2].PresentStatus.Used", NULL, NULL, 0, bypass_auto_info }, /* Automatic bypass */ { "BOOL", 0, 0, "UPS.PowerConverter.Input.[4].PresentStatus.Used", NULL, NULL, 0, bypass_manual_info }, /* Manual bypass */ { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.FanFailure", NULL, NULL, 0, fanfail_info }, diff --git a/drivers/mge-mib.c b/drivers/mge-mib.c index 499c027fba..3b98930185 100644 --- a/drivers/mge-mib.c +++ b/drivers/mge-mib.c @@ -27,7 +27,7 @@ #include "mge-mib.h" -#define MGE_MIB_VERSION "0.51" +#define MGE_MIB_VERSION "0.52" /* TODO: * - MGE PDU MIB and sysOID (".1.3.6.1.4.1.705.2") */ @@ -118,7 +118,7 @@ static info_lkp_t ietf_yes_no_info[] = { }; /* FIXME: the below may introduce status redundancy, that needs to be - * adressed by the driver, as for usbhid-ups! */ + * addressed by the driver, as for usbhid-ups! */ static info_lkp_t ietf_power_source_info[] = { { 1, "" /* other */ }, { 2, "OFF" /* none */ }, @@ -133,16 +133,14 @@ static info_lkp_t ietf_power_source_info[] = { }; /* Parameters default values */ -#define STR_DEFAULT_ONDELAY "30" /* Delay between return of utility power */ +#define DEFAULT_ONDELAY "30" /* Delay between return of utility power */ /* and powering up of load, in seconds */ /* CAUTION: ondelay > offdelay */ -#define DEFAULT_ONDELAY 30 -#define STR_DEFAULT_OFFDELAY "20" /* Delay before power off, in seconds */ -#define DEFAULT_OFFDELAY 20 +#define DEFAULT_OFFDELAY "20" /* Delay before power off, in seconds */ -#define MGE_NOTHING_VALUE 1 -#define MGE_START_VALUE 2 -#define MGE_STOP_VALUE 3 +#define MGE_NOTHING_VALUE "1" +#define MGE_START_VALUE "2" +#define MGE_STOP_VALUE "3" /* TODO: PowerShare (per plug .1, .2, .3) and deals with delays */ @@ -161,8 +159,8 @@ static snmp_info_t mge_mib[] = { { "ups.L2.load", 0, 1, ".1.3.6.1.4.1.705.1.7.2.1.4.2", "", SU_OUTPUT_3, NULL }, { "ups.L3.load", 0, 1, ".1.3.6.1.4.1.705.1.7.2.1.4.3", "", SU_OUTPUT_3, NULL }, { "ups.test.result", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.2.1.33.1.7.3.0", "", 0, ietf_test_result_info }, - { "ups.delay.shutdown", ST_FLAG_STRING | ST_FLAG_RW, 6, "1.3.6.1.2.1.33.1.8.2.0", STR_DEFAULT_OFFDELAY, SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, - { "ups.delay.start", ST_FLAG_STRING | ST_FLAG_RW, 6, "1.3.6.1.2.1.33.1.8.3.0", STR_DEFAULT_ONDELAY, SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, + { "ups.delay.shutdown", ST_FLAG_STRING | ST_FLAG_RW, 6, "1.3.6.1.2.1.33.1.8.2.0", DEFAULT_OFFDELAY, SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, + { "ups.delay.start", ST_FLAG_STRING | ST_FLAG_RW, 6, "1.3.6.1.2.1.33.1.8.3.0", DEFAULT_ONDELAY, SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, { "ups.timer.shutdown", 0, 1, "1.3.6.1.2.1.33.1.8.2.0", "", SU_FLAG_OK, NULL }, { "ups.timer.start", 0, 1, "1.3.6.1.2.1.33.1.8.3.0", "", SU_FLAG_OK, NULL }, { "ups.timer.reboot", 0, 1, "1.3.6.1.2.1.33.1.8.4.0", "", SU_FLAG_OK, NULL }, @@ -193,7 +191,7 @@ static snmp_info_t mge_mib[] = { */ /* Input page */ - { "input.phases", 0, 1.0, ".1.3.6.1.4.1.705.1.6.1.0", "", 0, NULL, NULL }, + { "input.phases", 0, 1.0, ".1.3.6.1.4.1.705.1.6.1.0", "", 0, NULL }, { "input.voltage", 0, 0.1, ".1.3.6.1.4.1.705.1.6.2.1.2.1", "", SU_INPUT_1, NULL }, { "input.L1-N.voltage", 0, 0.1, ".1.3.6.1.4.1.705.1.6.2.1.2.1", "", SU_INPUT_3, NULL }, { "input.L2-N.voltage", 0, 0.1, ".1.3.6.1.4.1.705.1.6.2.1.2.2", "", SU_INPUT_3, NULL }, @@ -217,7 +215,7 @@ static snmp_info_t mge_mib[] = { { "input.transfer.reason", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.705.1.6.4.0", "", SU_FLAG_OK, mge_transfer_reason_info }, /* Output page */ - { "output.phases", 0, 1.0, ".1.3.6.1.4.1.705.1.7.1.0", "", 0, NULL, NULL }, + { "output.phases", 0, 1.0, ".1.3.6.1.4.1.705.1.7.1.0", "", 0, NULL }, { "output.voltage", 0, 0.1, ".1.3.6.1.4.1.705.1.7.2.1.2.1", "", SU_OUTPUT_1, NULL }, { "output.L1-N.voltage", 0, 0.1, ".1.3.6.1.4.1.705.1.7.2.1.2.1", "", SU_OUTPUT_3, NULL }, { "output.L2-N.voltage", 0, 0.1, ".1.3.6.1.4.1.705.1.7.2.1.2.2", "", SU_OUTPUT_3, NULL }, @@ -247,7 +245,7 @@ static snmp_info_t mge_mib[] = { { "outlet.desc", ST_FLAG_RW | ST_FLAG_STRING, 20, NULL, "Main Outlet", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, /* instant commands. */ - { "test.battery.start", 0, MGE_START_VALUE, ".1.3.6.1.4.1.705.1.10.4.0", "", SU_TYPE_CMD | SU_FLAG_OK, NULL }, + { "test.battery.start", 0, 1, ".1.3.6.1.4.1.705.1.10.4.0", MGE_START_VALUE, SU_TYPE_CMD | SU_FLAG_OK, NULL }, /* Also use IETF OIDs * { "test.battery.stop", 0, 0, "1.3.6.1.2.1.33.1.7.1.0", "1.3.6.1.2.1.33.1.7.7.2", SU_TYPE_CMD, NULL }, * { "test.battery.start", 0, 0, "1.3.6.1.2.1.33.1.7.1.0", "1.3.6.1.2.1.33.1.7.7.3", SU_TYPE_CMD, NULL }, @@ -255,17 +253,18 @@ static snmp_info_t mge_mib[] = { * { "test.battery.start.deep", 0, 0, "1.3.6.1.2.1.33.1.7.1.0", "1.3.6.1.2.1.33.1.7.7.5", SU_TYPE_CMD, NULL }, */ - /* { "load.off", 0, MGE_START_VALUE, ".1.3.6.1.4.1.705.1.9.1.1.6.1", "", SU_TYPE_CMD | SU_FLAG_OK, NULL }, - * { "load.on", 0, MGE_START_VALUE, ".1.3.6.1.4.1.705.1.9.1.1.3.1", "", SU_TYPE_CMD | SU_FLAG_OK, NULL }, - * { "shutdown.return", 0, MGE_START_VALUE, ".1.3.6.1.4.1.705.1.9.1.1.9.1", "", SU_TYPE_CMD | SU_FLAG_OK, NULL }, + /* { "load.off", 0, 1, ".1.3.6.1.4.1.705.1.9.1.1.6.1", MGE_START_VALUE, SU_TYPE_CMD | SU_FLAG_OK, NULL }, + * { "load.on", 0, 1, ".1.3.6.1.4.1.705.1.9.1.1.3.1", MGE_START_VALUE, SU_TYPE_CMD | SU_FLAG_OK, NULL }, + * { "shutdown.return", 0, 1, ".1.3.6.1.4.1.705.1.9.1.1.9.1", MGE_START_VALUE, SU_TYPE_CMD | SU_FLAG_OK, NULL }, */ /* IETF MIB fallback */ - { "beeper.disable", 0, 1, "1.3.6.1.2.1.33.1.9.8.0", "", SU_TYPE_CMD, NULL }, - { "beeper.enable", 0, 2, "1.3.6.1.2.1.33.1.9.8.0", "", SU_TYPE_CMD, NULL }, - { "beeper.mute", 0, 3, "1.3.6.1.2.1.33.1.9.8.0", "", SU_TYPE_CMD, NULL }, - /* Use ST_FLAG_STRING to get default value from ->dfl instead of info_len */ - { "load.off.delay", 0, DEFAULT_OFFDELAY, "1.3.6.1.2.1.33.1.8.2.0", "", SU_TYPE_CMD, NULL }, - { "load.on.delay", 0, DEFAULT_ONDELAY, "1.3.6.1.2.1.33.1.8.3.0", "", SU_TYPE_CMD, NULL }, + { "beeper.disable", 0, 1, "1.3.6.1.2.1.33.1.9.8.0", "1", SU_TYPE_CMD, NULL }, + { "beeper.enable", 0, 1, "1.3.6.1.2.1.33.1.9.8.0", "2", SU_TYPE_CMD, NULL }, + { "beeper.mute", 0, 1, "1.3.6.1.2.1.33.1.9.8.0", "3", SU_TYPE_CMD, NULL }, + /*{ "load.off", 0, 1, "1.3.6.1.2.1.33.1.8.2.0", DEFAULT_OFFDELAY, SU_TYPE_CMD, NULL }, + { "load.on", 0, 1, "1.3.6.1.2.1.33.1.8.3.0", DEFAULT_ONDELAY, SU_TYPE_CMD, NULL },*/ + { "load.off.delay", 0, 1, "1.3.6.1.2.1.33.1.8.2.0", NULL, SU_TYPE_CMD, NULL }, + { "load.on.delay", 0, 1, "1.3.6.1.2.1.33.1.8.3.0", NULL, SU_TYPE_CMD, NULL }, /* end of structure. */ { NULL, 0, 0, NULL, NULL, 0, NULL } diff --git a/drivers/mge-xml.c b/drivers/mge-xml.c index 2cfade8f81..f12a8fb0ab 100644 --- a/drivers/mge-xml.c +++ b/drivers/mge-xml.c @@ -33,7 +33,7 @@ #include "mge-xml.h" #include "main.h" /* for testvar() */ -#define MGE_XML_VERSION "MGEXML/0.28" +#define MGE_XML_VERSION "MGEXML/0.29" #define MGE_XML_INITUPS "/" #define MGE_XML_INITINFO "/mgeups/product.xml /product.xml /ws/product.xml" @@ -544,6 +544,7 @@ static const char *mge_sensitivity_info(const char *val) static const char *mge_test_result_info(const char *val) { + STATUS_CLR(CAL); switch (atoi(val)) { case 1: @@ -555,6 +556,7 @@ static const char *mge_test_result_info(const char *val) case 4: return "aborted"; case 5: + STATUS_SET(CAL); return "in progress"; case 6: return "no test initiated"; diff --git a/drivers/netvision-mib.c b/drivers/netvision-mib.c index 37c2f8ce4e..89e2acf103 100644 --- a/drivers/netvision-mib.c +++ b/drivers/netvision-mib.c @@ -25,7 +25,7 @@ #include "netvision-mib.h" -#define NETVISION_MIB_VERSION "0.41" +#define NETVISION_MIB_VERSION "0.42" #define NETVISION_SYSOID ".1.3.6.1.4.1.4555.1.1.1" @@ -135,7 +135,7 @@ static snmp_info_t netvision_mib[] = { { "ups.load", 0, 1, NETVISION_OID_OUT_LOAD_PCT_P1, 0, SU_INPUT_1, NULL }, /*ups input,output voltage, output frquency phase 1 */ - { "input.phases", 0, 1.0, NETVISION_OID_INPUT_NUM_LINES, NULL, 0, NULL, NULL }, + { "input.phases", 0, 1.0, NETVISION_OID_INPUT_NUM_LINES, NULL, 0, NULL }, { "input.frequency", 0, 0.1, NETVISION_OID_INPUT_FREQ, NULL, SU_FLAG_OK, NULL }, { "input.voltage", 0, 0.1, NETVISION_OID_IN_VOLTAGE_P1, NULL, SU_INPUT_1, NULL }, { "input.current", 0, 0.1, NETVISION_OID_IN_CURRENT_P1, NULL, SU_INPUT_1, NULL }, @@ -146,7 +146,7 @@ static snmp_info_t netvision_mib[] = { { "input.L3-N.voltage", 0, 0.1, NETVISION_OID_IN_VOLTAGE_P3, NULL, SU_INPUT_3, NULL }, { "input.L3.current", 0, 0.1, NETVISION_OID_IN_CURRENT_P3, NULL, SU_INPUT_3, NULL }, - { "output.phases", 0, 1.0, NETVISION_OID_OUTPUT_NUM_LINES, NULL, 0, NULL, NULL }, + { "output.phases", 0, 1.0, NETVISION_OID_OUTPUT_NUM_LINES, NULL, 0, NULL }, { "output.frequency", 0, 0.1, NETVISION_OID_OUTPUT_FREQ, NULL, SU_FLAG_OK, NULL }, { "output.voltage", 0, 0.1, NETVISION_OID_OUT_VOLTAGE_P1, NULL, SU_OUTPUT_1, NULL }, { "output.current", 0, 0.1, NETVISION_OID_OUT_CURRENT_P1, NULL, SU_OUTPUT_1, NULL }, @@ -161,7 +161,7 @@ static snmp_info_t netvision_mib[] = { { "output.L3.current", 0, 0.1, NETVISION_OID_OUT_CURRENT_P3, NULL, SU_OUTPUT_3, NULL }, { "output.L3.power.percent", 0, 1.0, NETVISION_OID_OUT_LOAD_PCT_P3, NULL, SU_OUTPUT_3, NULL }, - { "input.bypass.phases", 0, 1.0, NETVISION_OID_BYPASS_NUM_LINES, NULL, 0, NULL, NULL }, + { "input.bypass.phases", 0, 1.0, NETVISION_OID_BYPASS_NUM_LINES, NULL, 0, NULL }, { "input.bypass.frequency", 0, 0.1, NETVISION_OID_BYPASS_FREQ, NULL, SU_FLAG_OK, NULL }, { "input.bypass.voltage", 0, 0.1, NETVISION_OID_BY_VOLTAGE_P1, NULL, SU_BYPASS_1, NULL }, { "input.bypass.current", 0, 0.1, NETVISION_OID_BY_CURRENT_P1, NULL, SU_BYPASS_1, NULL }, diff --git a/drivers/netxml-ups.c b/drivers/netxml-ups.c index 853784411d..43d67cfb4d 100644 --- a/drivers/netxml-ups.c +++ b/drivers/netxml-ups.c @@ -40,7 +40,7 @@ #include #define DRIVER_NAME "network XML UPS" -#define DRIVER_VERSION "0.42" +#define DRIVER_VERSION "0.43" /** *_OBJECT query multi-part body boundary */ #define FORM_POST_BOUNDARY "NUT-NETXML-UPS-OBJECTS" @@ -235,6 +235,7 @@ static subdriver_t *subdriver = &mge_xml_subdriver; static ne_session *session = NULL; static ne_socket *sock = NULL; static ne_uri uri; +static char *product_page = NULL; /* Support functions */ static void netxml_alarm_set(void); @@ -269,6 +270,8 @@ void upsdrv_initinfo(void) if (netxml_get_page(page) != NE_OK) { continue; } + /* store product page, for later use */ + product_page = xstrdup(page); dstate_setinfo("driver.version.data", "%s", subdriver->version); @@ -350,6 +353,12 @@ void upsdrv_updateinfo(void) errors++; } + /* also refresh the product information, at least for firmware information */ + ret = netxml_get_page(product_page); + if (ret != NE_OK) { + errors++; + } + if (errors > 1) { dstate_datastale(); return; @@ -641,6 +650,7 @@ void upsdrv_cleanup(void) free(subdriver->summary); free(subdriver->getobject); free(subdriver->setobject); + free(product_page); if (sock) { ne_sock_close(sock); @@ -984,6 +994,9 @@ static void netxml_status_set(void) if (STATUS_BIT(SHUTDOWNIMM)) { status_set("FSD"); /* shutdown imminent */ } + if (STATUS_BIT(CAL)) { + status_set("CAL"); /* calibrating */ + } } diff --git a/drivers/netxml-ups.h b/drivers/netxml-ups.h index 4729b7a58d..db2d74191b 100644 --- a/drivers/netxml-ups.h +++ b/drivers/netxml-ups.h @@ -67,7 +67,8 @@ typedef enum { CHARGERFAIL, /* battery charger failure */ VRANGE, /* voltage out of range */ FRANGE, /* frequency out of range */ - FUSEFAULT /* fuse fault */ + FUSEFAULT, /* fuse fault */ + CAL /* calibrating */ } status_bit_t; extern uint32_t ups_status; diff --git a/drivers/nutdrv_qx_q1.c b/drivers/nutdrv_qx_q1.c index bf3e2536b9..08073bca00 100644 --- a/drivers/nutdrv_qx_q1.c +++ b/drivers/nutdrv_qx_q1.c @@ -20,7 +20,7 @@ * NOTE: * This subdriver implements the same protocol as the one used by the 'megatec' subdriver minus the vendor (I) and ratings (F) queries. * In the claim function: - * - it doesn't even try to get 'vendor' informations (I) + * - it doesn't even try to get 'vendor' information (I) * - it checks only status (Q1), through 'input.voltage' variable * Therefore it should be able to work even if the UPS doesn't support vendor/ratings *and* the user doesn't use the 'novendor'/'norating' flags, as long as: * - the UPS replies a Q1-compliant answer (i.e. not necessary filled with all of the Q1-required data, but at least of the right length and with not available data filled with some replacement character) diff --git a/drivers/nutdrv_qx_q1.h b/drivers/nutdrv_qx_q1.h index bad2f13505..d990ef717b 100644 --- a/drivers/nutdrv_qx_q1.h +++ b/drivers/nutdrv_qx_q1.h @@ -20,7 +20,7 @@ * NOTE: * This subdriver implements the same protocol as the one used by the 'megatec' subdriver minus the vendor (I) and ratings (F) queries. * In the claim function: - * - it doesn't even try to get 'vendor' informations (I) + * - it doesn't even try to get 'vendor' information (I) * - it checks only status (Q1), through 'input.voltage' variable * Therefore it should be able to work even if the UPS doesn't support vendor/ratings *and* the user doesn't use the 'novendor'/'norating' flags, as long as: * - the UPS replies a Q1-compliant answer (i.e. not necessary filled with all of the Q1-required data, but at least of the right length and with not available data filled with some replacement character) diff --git a/drivers/nutdrv_siemens_sitop.c b/drivers/nutdrv_siemens_sitop.c new file mode 100644 index 0000000000..7414940ff0 --- /dev/null +++ b/drivers/nutdrv_siemens_sitop.c @@ -0,0 +1,295 @@ +/* + * nutdrv_siemens_sitop.c - model specific routines for the Siemens SITOP UPS500 series + * + * + * Copyright (C) 2018 Matthijs H. ten Berge + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Notes: + * These UPSes operate at 24V DC (both input and output), instead of 110V/230V AC. + * Therefore, the line input is also referred to by Siemens as 'DC'. + * + * The device is configured via DIP-switches. + * For correct functioning in combination with NUT, set the DIP-switches to the following: + * switch 1-4: choose whatever suits your situation. Any combination will work with NUT. + * switch 5 ('=>' / 't'): set to OFF ('t') + * switch 6-10 (delay): set to OFF (no additional delay) + * switch 11 (INTERR.): set to ON + * switch 12 (ON/OFF): set to ON + * + * These UPSes are available with serial or USB port. + * Both are supported by this driver. The version with USB port simply contains + * a serial-over-USB chip, so as far as this driver is concerned, all models are + * actually serial models. + * + * The FTDI USB-to-serial converters in the USB-models are programmed with a non-standard + * Product ID (mine had 0403:e0e3), but can be used with the normal ftdi_sio driver: + * # modprobe ftdi_sio + * # echo 0403 e0e3 > /sys/bus/usb-serial/drivers/ftdi_sio/new_id + * + * This can also be automated via a udev rule: + * ACTION=="add", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="e0e3", \ + * RUN+="/sbin/modprobe ftdi_sio", \ + * RUN+="/bin/sh -c 'echo 0403 e0e3 > /sys/bus/usb-serial/drivers/ftdi_sio/new_id'" + * + * Use the following udev rule to create a persistent device name, for example /dev/ttyUPS: + * SUBSYSTEM=="tty" ATTRS{idVendor}=="0403", ATTRS{idProduct}=="e0e3" SYMLINK+="ttyUPS" + */ + +#include "main.h" +#include "serial.h" +#include "limits.h" + +#define DRIVER_NAME "Siemens SITOP UPS500 series driver" +#define DRIVER_VERSION "0.02" + +#define RX_BUFFER_SIZE 100 + +/* driver description structure */ +upsdrv_info_t upsdrv_info = { + DRIVER_NAME, + DRIVER_VERSION, + "Matthijs H. ten Berge ", + DRV_EXPERIMENTAL, + { NULL } +}; + +/* The maximum number of consecutive polls in which the UPS does not provide any data: */ +static int max_polls_without_data; +/* The current number: */ +static int nr_polls_without_data; +/* receive buffer */ +static char rx_buffer[RX_BUFFER_SIZE]; +static int rx_count; + +static struct { + int battery_alarm; + int dc_input_low; + int on_battery; + int battery_above_85_percent; +} current_ups_status; + +/* remove n bytes from the head of rx_buffer, shift the remaining bytes to the start */ +static void rm_buffer_head(int n) { + if (rx_count <= n) { + /* nothing left */ + rx_count = 0; + return; + } + rx_count -= n; + memmove(rx_buffer, rx_buffer + n, rx_count); +} + +/* parse incoming data from the UPS. + * return true if something new was received. + */ +static int check_for_new_data() { + int new_data_received = 0; + int done = 0; + int num_received; + + while (!done) { + /* Get new data from the serial port. + * No extra delay, just get the chars that were already buffered. + */ + num_received = ser_get_buf(upsfd, rx_buffer + rx_count, RX_BUFFER_SIZE - rx_count, 0, 0); + if (num_received < 0) { + /* comm error */ + ser_comm_fail("error %d while reading", num_received); + /* discard any remaining old data from the receive buffer: */ + rx_count = 0; + /* try to re-open the serial port: */ + if (upsfd) { + ser_close(upsfd, device_path); + upsfd = 0; + } + upsfd = ser_open_nf(device_path); + ser_set_speed_nf(upsfd, device_path, B9600); + done = 1; + } else if (num_received == 0) { + /* no (more) new data */ + done = 1; + } else { + rx_count += num_received; + + /* parse received input data: */ + while (rx_count >= 5) { /* all valid input messages are strings of 5 characters */ + if (strncmp(rx_buffer, "BUFRD", 5) == 0) { + current_ups_status.battery_alarm = 0; + } else if (strncmp(rx_buffer, "ALARM", 5) == 0) { + current_ups_status.battery_alarm = 1; + } else if (strncmp(rx_buffer, "DC_OK", 5) == 0) { + current_ups_status.dc_input_low = 0; + } else if (strncmp(rx_buffer, "DC_LO", 5) == 0) { + current_ups_status.dc_input_low = 1; + } else if (strncmp(rx_buffer, "*****", 5) == 0) { + current_ups_status.on_battery = 0; + } else if (strncmp(rx_buffer, "*BAT*", 5) == 0) { + current_ups_status.on_battery = 1; + } else if (strncmp(rx_buffer, "BA>85", 5) == 0) { + current_ups_status.battery_above_85_percent = 1; + } else if (strncmp(rx_buffer, "BA<85", 5) == 0) { + current_ups_status.battery_above_85_percent = 0; + } else { + /* nothing sensible found at the start of the rx_buffer. */ + rm_buffer_head(1); + continue; /* skip the code below */ + } + rm_buffer_head(5); + new_data_received = 1; + } + } + } + return new_data_received; +} + + +static int instcmd(const char *cmdname, const char *extra) { + /* Note: the UPS does not really like to receive data. + * For example, sending an "R" without \n hangs the serial port. + * In that situation, the UPS will no longer send any status updates. + * For this reason, an additional \n is appended here. + * The commands are sent twice, because the first command is sometimes + * lost as well. + */ + if (!strcasecmp(cmdname, "shutdown.return")) { + upslogx(LOG_NOTICE, "instcmd: sending command R"); + ser_send_pace(upsfd, 200000, "\n\nR\n\n"); + ser_send_pace(upsfd, 200000, "R\n\n"); + return STAT_INSTCMD_HANDLED; + } + if (!strcasecmp(cmdname, "shutdown.stayoff")) { + upslogx(LOG_NOTICE, "instcmd: sending command S"); + ser_send_pace(upsfd, 200000, "\n\nS\n\n"); + ser_send_pace(upsfd, 200000, "S\n\n"); + return STAT_INSTCMD_HANDLED; + } + + upslogx(LOG_NOTICE, "instcmd: unknown command [%s]", cmdname); + return STAT_INSTCMD_UNKNOWN; +} + + +void upsdrv_initinfo(void) { + int max_attempts = 5; + int found = 0; + while (!found && max_attempts > 0) { + if (check_for_new_data()) { + found = 1; + } else { + sleep(1); /* Sleep a while, then try again */ + } + max_attempts--; + } + if (!found) { + fatalx(EXIT_FAILURE, "No data received from the UPS"); + } + + dstate_setinfo("device.mfr", "Siemens"); + dstate_setinfo("device.model", "SITOP UPS500 series"); + + /* supported commands: */ + dstate_addcmd("shutdown.stayoff"); + dstate_addcmd("shutdown.return"); + + upsh.instcmd = instcmd; +} + + +void upsdrv_updateinfo(void) { + if (check_for_new_data()) { + nr_polls_without_data = 0; + } else { + nr_polls_without_data++; + if (nr_polls_without_data < 0) + nr_polls_without_data = INT_MAX; + } + + if (nr_polls_without_data > max_polls_without_data) { + /* data is stale */ + dstate_datastale(); + return; + } + + /* This is all we know about the charge level... */ + dstate_setinfo("battery.charge.approx", + (current_ups_status.battery_above_85_percent) ? ">85" : "<85"); + + status_init(); + + if (current_ups_status.dc_input_low || current_ups_status.on_battery) { + status_set("OB"); + } else { + status_set("OL"); + } + if (current_ups_status.battery_alarm) { + status_set("LB"); + } + + status_commit(); + dstate_dataok(); + ser_comm_good(); +} + +void upsdrv_shutdown(void) { + /* tell the UPS to shut down, then return - DO NOT SLEEP HERE */ + instcmd("shutdown.return", NULL); +} + + +void upsdrv_help(void) { +} + +/* list flags and values that you want to receive via -x */ +void upsdrv_makevartable(void) { + /* allow '-x max_polls_without_data=' */ + addvar(VAR_VALUE, "max_polls_without_data", "The maximum number of consecutive polls in which the UPS does not provide any data."); +} + +void upsdrv_initups(void) { + char * maxPollsString; + unsigned int parsed; + + upsfd = ser_open(device_path); + ser_set_speed(upsfd, device_path, B9600); + + /* + * Fast polling is preferred, because + * A) the UPS spits out new data every 75 msec, + * B) some models in this SITOP series have a _very_ small capacity + * (< 10sec runtime), so every second might count. + */ + if (poll_interval > 5) { + upslogx(LOG_NOTICE, "Option poll_interval is recommended to be lower than 5 (found: %d)", poll_interval); + } + + /* option max_polls_without_data: */ + max_polls_without_data = 2; + maxPollsString = getval("max_polls_without_data"); + if (maxPollsString) { + if (str_to_uint(maxPollsString, &parsed, 10) == 1) { + max_polls_without_data = parsed; + } else { + upslog_with_errno(LOG_ERR, "Cannot parse option max_polls_without_data"); + } + } +} + +void upsdrv_cleanup(void) { + ser_close(upsfd, device_path); +} diff --git a/drivers/optiups.c b/drivers/optiups.c index 26b7f47797..53448033d4 100644 --- a/drivers/optiups.c +++ b/drivers/optiups.c @@ -536,7 +536,7 @@ void upsdrv_makevartable(void) { addvar(VAR_FLAG, OPTI_MINPOLL, "Only poll for critical status variables"); addvar(VAR_FLAG, OPTI_FAKELOW, "Fake a low battery status" ); - addvar(VAR_FLAG, OPTI_NOWARN_NOIMP, "Supress warnings of unsupported commands"); + addvar(VAR_FLAG, OPTI_NOWARN_NOIMP, "Suppress warnings of unsupported commands"); addvar(VAR_FLAG, OPTI_POWERUP, "(Zinto D) Power-up UPS at start (cannot identify a powered-down Zinto D)"); } diff --git a/drivers/pijuice.c b/drivers/pijuice.c new file mode 100644 index 0000000000..2211bff82f --- /dev/null +++ b/drivers/pijuice.c @@ -0,0 +1,836 @@ +/* pijuice.c Driver for the PiJuice HAT (www.pijuice.com), addressed via i2c. + + Copyright (C) 2019 Andrew Anderson + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "main.h" + +#include +#include + +/* + * Linux I2C userland is a bit of a mess until distros refresh to + * the i2c-tools 4.x release that profides i2c/smbus.h for userspace + * instead of (re)using linux/i2c-dev.h, which conflicts with a + * kernel header of the same name. + * + * See: + * https://i2c.wiki.kernel.org/index.php/Plans_for_I2C_Tools_4 + */ +#if HAVE_LINUX_SMBUS_H +# include +#endif +#if HAVE_LINUX_I2C_DEV_H +# include /* for I2C_SLAVE */ +# if !HAVE_LINUX_SMBUS_H +# ifndef I2C_FUNC_I2C +# include +# endif +# endif +#endif + +/* + * i2c-tools pre-4.0 has a userspace header with a name that conflicts + * with a kernel header, so it may be ignored/removed by distributions + * when packaging i2c-tools. + * + * This will cause the driver to be un-buildable on certain + * configurations, so include the necessary bits here to handle this + * situation. + */ +#if WITH_LINUX_I2C +#if !HAVE_DECL_I2C_SMBUS_ACCESS +static inline __s32 i2c_smbus_access(int file, char read_write, __u8 command, + int size, union i2c_smbus_data *data) +{ + struct i2c_smbus_ioctl_data args; + __s32 err; + + args.read_write = read_write; + args.command = command; + args.size = size; + args.data = data; + + err = ioctl(file, I2C_SMBUS, &args); + if (err == -1) + err = -errno; + return err; +} +#endif + +#if !HAVE_DECL_I2C_SMBUS_READ_BYTE_DATA +static inline __s32 i2c_smbus_read_byte_data(int file, __u8 command) +{ + union i2c_smbus_data data; + int err; + + if ((err = i2c_smbus_access(file, I2C_SMBUS_READ, command, + I2C_SMBUS_BYTE_DATA, &data)) < 0) + return err; + else + return 0x0FF & data.byte; +} +#endif + +#if !HAVE_DECL_I2C_SMBUS_WRITE_BYTE_DATA +static inline __s32 i2c_smbus_write_byte_data(int file, __u8 command, __u8 value) +{ + union i2c_smbus_data data; + int err; + + data.byte = value; + if ((err = i2c_smbus_access(file, I2C_SMBUS_WRITE, command, + I2C_SMBUS_BYTE_DATA, &data)) < 0) + return err; + else + return 0x0FF & data.byte; +} +#endif + +#if !HAVE_DECL_I2C_SMBUS_READ_WORD_DATA +static inline __s32 i2c_smbus_read_word_data(int file, __u8 command) +{ + union i2c_smbus_data data; + int err; + + if ((err = i2c_smbus_access(file, I2C_SMBUS_READ, command, + I2C_SMBUS_WORD_DATA, &data)) < 0) + return err; + else + return 0x0FFFF & data.word; +} +#endif + +#if !HAVE_DECL_I2C_SMBUS_WRITE_WORD_DATA +static inline __s32 i2c_smbus_write_word_data(int file, __u8 command, __u16 value) +{ + union i2c_smbus_data data; + int err; + + data.word = value; + if ((err = i2c_smbus_access(file, I2C_SMBUS_WRITE, command, + I2C_SMBUS_WORD_DATA, &data)) < 0) + return err; + else + return 0x0FFFF & data.word; +} +#endif + +#if !HAVE_DECL_I2C_SMBUS_READ_BLOCK_DATA +static inline __u8* i2c_smbus_read_i2c_block_data(int file, __u8 command, __u8 length, __u8 *values) +{ + union i2c_smbus_data data; + int err; + + if ( length > I2C_SMBUS_BLOCK_MAX) + { + length = I2C_SMBUS_BLOCK_MAX; + } + + data.block[0] = length; + memcpy(data.block + 1, values, length); + + if ((err = i2c_smbus_access(file, I2C_SMBUS_READ, command, + I2C_SMBUS_I2C_BLOCK_DATA, &data)) < 0) + return NULL; + else + memcpy(values, &data.block[1], data.block[0]); + + return values; +} +#endif +#endif // if WITH_LINUX_I2C + +#define STATUS_CMD 0x40 +#define CHARGE_LEVEL_CMD 0x41 +#define CHARGE_LEVEL_HI_RES_CMD 0x42 +#define FAULT_EVENT_CMD 0x44 +#define BUTTON_EVENT_CMD 0x45 +#define BATTERY_TEMPERATURE_CMD 0x47 +#define BATTERY_VOLTAGE_CMD 0x49 +#define BATTERY_CURRENT_CMD 0x4b +#define IO_VOLTAGE_CMD 0x4d +#define IO_CURRENT_CMD 0x4f + +#define CHARGING_CONFIG_CMD 0x51 +#define BATTERY_PROFILE_ID_CMD 0x52 +#define BATTERY_PROFILE_CMD 0x53 +#define BATTERY_EXT_PROFILE_CMD 0x54 +#define BATTERY_TEMP_SENSE_CONFIG_CMD 0x5D + +#define POWER_INPUTS_CONFIG_CMD 0x5E +#define RUN_PIN_CONFIG_CMD 0x5F +#define POWER_REGULATOR_CONFIG_CMD 0x60 +#define WATCHDOG_ACTIVATION_CMD 0x61 +#define POWER_OFF_CMD 0x62 +#define WAKEUP_ON_CHARGE_CMD 0x63 +#define SYSTEM_POWER_SWITCH_CTRL_CMD 0x64 + +#define LED_STATE_CMD 0x66 +#define LED_BLINK_CMD 0x68 +#define LED_CONFIGURATION_CMD 0x6A +#define BUTTON_CONFIGURATION_CMD 0x6E + +#define IO1_CONFIGURATION_CMD 0x72 +#define IO1_PIN_ACCESS_CMD 0x75 + +#define IO2_CONFIGURATION_CMD 0x77 +#define IO2_PIN_ACCESS_CMD 0x7A + +#define I2C_ADDRESS_CMD 0x7C + +#define ID_EEPROM_WRITE_PROTECT_CTRL_CMD 0x7E +#define ID_EEPROM_ADDRESS_CMD 0x7F + +#define RTC_TIME_CMD 0xB0 +#define RTC_ALARM_CMD 0xB9 +#define RTC_CTRL_STATUS_CMD 0xC2 + +#define RESET_TO_DEFAULT_CMD 0xF0 +#define FIRMWARE_VERSION_CMD 0xFD + +#define BATT_NORMAL 0 +#define BATT_CHARGING_FROM_IN 1 +#define BATT_CHARGING_FROM_5V 2 +#define BATT_NOT_PRESENT 3 + +#define POWER_NOT_PRESENT 0 +#define POWER_BAD 1 +#define POWER_WEAK 2 +#define POWER_PRESENT 3 + +#define LOW_BATTERY_THRESHOLD 25.0 +#define HIGH_BATTERY_THRESHOLD 75.0 +#define NOMINAL_BATTERY_VOLTAGE 4.18 + +#define DRIVER_NAME "PiJuice UPS driver" +#define DRIVER_VERSION "0.9" + +static uint8_t i2c_address = 0x14; +static uint8_t shutdown_delay = 30; + +/* + * Flags used to indicate a change in power status + */ +static uint8_t usb_power = 0; +static uint8_t gpio_power = 0; +static uint8_t battery_power = 0; + +/* + * Smooth out i2c read errors by holding the most recent + * battery charge level reading + */ +static float battery_charge_level = 0; + +/* driver description structure */ +upsdrv_info_t upsdrv_info = { + DRIVER_NAME, + DRIVER_VERSION, + "Andrew Anderson ", + DRV_EXPERIMENTAL, + { NULL } +}; + +#define I2C_READ_BYTE(fd, cmd, label) \ + if ((data = i2c_smbus_read_byte_data(upsfd, cmd)) < 0 ) { \ + upsdebugx(2, "Failure reading the i2c bus [%s]", label); \ + return; \ + } + +#define I2C_WRITE_BYTE(fd, cmd, value, label) \ + if ((data = i2c_smbus_write_byte_data(upsfd, cmd, value)) < 0 ) { \ + upsdebugx(2, "Failure writing to the i2c bus [%s]", label); \ + return; \ + } + +#define I2C_READ_WORD(fd, cmd, label) \ + if ((data = i2c_smbus_read_word_data(upsfd, cmd)) < 0 ) { \ + upsdebugx(2, "Failure reading the i2c bus [%s]", label); \ + return; \ + } + +#define I2C_READ_BLOCK(fd, cmd, size, block, label) \ + if ((i2c_smbus_read_i2c_block_data(upsfd, cmd, size, block)) < 0 ) { \ + upsdebugx(2, "Failure reading the i2c bus [%s]", label); \ + return; \ + } + +static inline int open_i2c_bus(char *path, uint8_t addr) +{ + int file; + + if ((file = open(path, O_RDWR)) < 0) + { + fatal_with_errno(EXIT_FAILURE, "Failed to open the i2c bus on %s", path); + } + + if (ioctl(file, I2C_SLAVE, addr) < 0) + { + fatal_with_errno(EXIT_FAILURE, "Failed to acquire the i2c bus and/or talk to the UPS"); + } + + return file; +} + +static void get_charge_level_hi_res() +{ + uint8_t cmd = CHARGE_LEVEL_HI_RES_CMD; + uint16_t data; + + upsdebugx( 3, __FUNCTION__ ); + + I2C_READ_WORD( upsfd, cmd, __FUNCTION__ ) + + /* + * Use an external variable to allow for missed i2c bus + * reads; the charge level data may be slightly stale, + * but no other options seem reasonable: + * + * 1) store 0 + * Leads to a false report of a depleted battery, possibly + * triggering an immediate shutdown if on battery power only + * 2) store -1 + * Adds a lot of logic to "skip" over negative charge levels, + * which effectively accomplishes the same thing + * 3) retry the read immediately + * Could tie up the i2c bus and make matters exponentially worse + */ + battery_charge_level = data / 10.0; + + upsdebugx( 1, "Battery Charge Level: %02.1f%%", battery_charge_level ); + dstate_setinfo( "battery.charge", "%02.1f", battery_charge_level ); +} + +static void get_status() +{ + uint8_t cmd = STATUS_CMD; + uint8_t data; + char status_buf[ST_MAX_VALUE_LEN]; + + upsdebugx( 3, __FUNCTION__ ); + + memset( status_buf, 0, ST_MAX_VALUE_LEN ); + + I2C_READ_BYTE( upsfd, cmd, __FUNCTION__ ) + + uint8_t batteryStatus = data >> 2 & 0x03; + switch( batteryStatus ) + { + case BATT_NORMAL: + upsdebugx( 1, "Battery Status: Normal" ); + dstate_setinfo( "battery.packs", "%d", 1 ); + dstate_setinfo( "battery.packs.bad", "%d", 0 ); + break; + case BATT_CHARGING_FROM_IN: + upsdebugx( 1, "Battery Status: Charging from IN" ); + dstate_setinfo( "battery.packs", "%d", 1 ); + dstate_setinfo( "battery.packs.bad", "%d", 0 ); + break; + case BATT_CHARGING_FROM_5V: + upsdebugx( 1, "Battery Status: Charging from 5V" ); + dstate_setinfo( "battery.packs", "%d", 1 ); + dstate_setinfo( "battery.packs.bad", "%d", 0 ); + break; + case BATT_NOT_PRESENT: + upsdebugx( 1, "Battery Status: Not Present" ); + dstate_setinfo( "battery.packs", "%d", 0 ); + dstate_setinfo( "battery.packs.bad", "%d", 1 ); + break; + default: + upsdebugx( 1, "battery.status: UNKNOWN" ); + } + + uint8_t powerInput = data >> 4 & 0x03; + switch( powerInput ) + { + case POWER_NOT_PRESENT: + upsdebugx( 1, "Power Input: Not Present" ); + break; + case POWER_BAD: + upsdebugx( 1, "Power Input: Bad" ); + break; + case POWER_WEAK: + upsdebugx( 1, "Power Input: Weak" ); + break; + case POWER_PRESENT: + upsdebugx( 1, "Power Input: Present" ); + break; + default: + upsdebugx( 1, "Power Input: UNKNOWN" ); + } + + uint8_t powerInput5vIo = data >> 6 & 0x03; + switch( powerInput5vIo ) + { + case POWER_NOT_PRESENT : + upsdebugx(1, "Power Input 5v: Not Present"); + break; + case POWER_BAD: + upsdebugx(1, "Power Input 5v: Bad"); + break; + case POWER_WEAK: + upsdebugx(1, "Power Input 5v: Weak"); + break; + case POWER_PRESENT: + upsdebugx(1, "Power Input 5v: Present"); + break; + default: + upsdebugx(1, "Power Input 5v: UNKNOWN"); + } + + if ( batteryStatus == BATT_NORMAL || + batteryStatus == BATT_CHARGING_FROM_IN || + batteryStatus == BATT_CHARGING_FROM_5V ) + { + get_charge_level_hi_res(); + + if ( battery_charge_level <= LOW_BATTERY_THRESHOLD ) + { + upsdebugx( 1, "Battery Charge Status: LOW" ); + snprintfcat( status_buf, ST_MAX_VALUE_LEN, "LB " ); + } + else if ( battery_charge_level > HIGH_BATTERY_THRESHOLD ) + { + upsdebugx( 1, "Battery Charge Status: HIGH" ); + snprintfcat( status_buf, ST_MAX_VALUE_LEN, "HB " ); + } + } + else if ( batteryStatus == BATT_NOT_PRESENT ) + { + snprintfcat( status_buf, ST_MAX_VALUE_LEN, "RB " ); + } + + if ( batteryStatus <= BATT_NOT_PRESENT && + powerInput <= POWER_PRESENT && + powerInput5vIo <= POWER_PRESENT ) + { + if ( powerInput == POWER_NOT_PRESENT && + ( powerInput5vIo != POWER_NOT_PRESENT && + powerInput5vIo <= POWER_PRESENT )) + { + if ( usb_power != 1 || gpio_power != 0 ) + { + upslogx( LOG_NOTICE, "On USB power" ); + } + usb_power = 1; + gpio_power = 0; + battery_power = 0; + upsdebugx( 1, "On USB power [%d:%d:%d]", usb_power, gpio_power, battery_power ); + + snprintfcat( status_buf, sizeof(status_buf), "OL" ); + if ( batteryStatus == BATT_CHARGING_FROM_5V ) + { + snprintfcat( status_buf, sizeof( status_buf ), " CHRG" ); + upsdebugx( 1, "Battery Charger Status: charging" ); + dstate_setinfo( "battery.charger.status", "%s", "charging" ); + } + else if ( batteryStatus == BATT_NORMAL ) + { + upsdebugx( 1, "Battery Charger Status: resting" ); + dstate_setinfo( "battery.charger.status", "%s", "resting" ); + } + status_set( status_buf ); + } + else if ( powerInput5vIo == POWER_NOT_PRESENT && + ( powerInput != POWER_NOT_PRESENT && + powerInput <= POWER_PRESENT )) + { + if ( gpio_power != 1 || usb_power != 0 ) + { + upslogx( LOG_NOTICE, "On 5V_GPIO power" ); + } + usb_power = 0; + gpio_power = 1; + battery_power = 0; + upsdebugx( 1, "On 5V_GPIO power [%d:%d:%d]", usb_power, gpio_power, battery_power ); + + snprintfcat( status_buf, sizeof(status_buf), "OL" ); + if ( batteryStatus == BATT_CHARGING_FROM_IN ) + { + snprintfcat( status_buf, sizeof(status_buf), " CHRG" ); + status_set( status_buf ); + upsdebugx( 1, "Battery Charger Status: charging" ); + dstate_setinfo( "battery.charger.status", "%s", "charging" ); + } + else if ( batteryStatus == BATT_NORMAL ) + { + status_set( status_buf ); + upsdebugx( 1, "Battery Charger Status: resting" ); + dstate_setinfo( "battery.charger.status", "%s", "resting" ); + } + } + else if ( ( powerInput != POWER_NOT_PRESENT && powerInput <= POWER_PRESENT ) && + ( powerInput5vIo != POWER_NOT_PRESENT && powerInput5vIo <= POWER_PRESENT )) + { + if ( usb_power != 1 || gpio_power != 1 ) + { + upslogx( LOG_NOTICE, "On USB and 5V_GPIO power" ); + } + usb_power = 1; + gpio_power = 1; + battery_power = 0; + upsdebugx( 1, "On USB and 5V_GPIO power [%d:%d:%d]", usb_power, gpio_power, battery_power ); + + snprintfcat( status_buf, sizeof( status_buf ), "OL" ); + if ( batteryStatus == BATT_CHARGING_FROM_IN ) + { + snprintfcat( status_buf, sizeof(status_buf), " CHRG"); + status_set( status_buf ); + upsdebugx( 1, "Battery Charger Status: charging" ); + dstate_setinfo("battery.charger.status", "%s", "charging"); + } + else if ( batteryStatus == BATT_NORMAL ) + { + status_set( status_buf ); + upsdebugx( 1, "Battery Charger Status: resting" ); + dstate_setinfo( "battery.charger.status", "%s", "resting" ); + } + } + else if ( powerInput == POWER_NOT_PRESENT && powerInput5vIo == POWER_NOT_PRESENT ) + { + if ( usb_power != 0 || gpio_power != 0 ) + { + upslogx( LOG_NOTICE, "On Battery power" ); + } + usb_power = 0; + gpio_power = 0; + battery_power = 1; + upsdebugx( 1, "On Battery power [%d:%d:%d]", usb_power, gpio_power, battery_power ); + + snprintfcat( status_buf, sizeof(status_buf), "OB DISCHRG" ); + status_set( status_buf ); + } + } +} + +static void get_battery_temperature() +{ + uint8_t cmd = BATTERY_TEMPERATURE_CMD; + int16_t data; + + upsdebugx( 3, __FUNCTION__ ); + + I2C_READ_WORD( upsfd, cmd, __FUNCTION__ ) + + upsdebugx( 1, "Battery Temperature: %d°C", data ); + dstate_setinfo( "battery.temperature", "%d", data ); +} + +static void get_battery_voltage() +{ + uint8_t cmd = BATTERY_VOLTAGE_CMD; + int16_t data; + + upsdebugx( 3, __FUNCTION__ ); + + I2C_READ_WORD( upsfd, cmd, __FUNCTION__ ) + + upsdebugx( 1, "Battery Voltage: %0.3fV", data / 1000.0 ); + dstate_setinfo( "battery.voltage", "%0.3f", data / 1000.0 ); +} + +static void get_battery_current() +{ + uint8_t cmd = BATTERY_CURRENT_CMD; + int16_t data; + + upsdebugx( 3, __FUNCTION__ ); + + /* + * The reported current can actually be negative, so we cannot + * check for I2C failure by looking for negative values + */ + data = i2c_smbus_read_word_data(upsfd, cmd); + + if ( data & ( 1 << 15 ) ) + { + data = data - ( 1 << 16 ); + } + + upsdebugx( 1, "Battery Current: %0.3fA", data / 1000.0 ); + dstate_setinfo( "battery.current", "%0.3f", data / 1000.0 ); +} + +static void get_io_voltage() +{ + uint8_t cmd = IO_VOLTAGE_CMD; + int16_t data; + + upsdebugx( 3, __FUNCTION__ ); + + I2C_READ_WORD( upsfd, cmd, __FUNCTION__ ) + + upsdebugx( 1, "Input Voltage: %.3fV", data / 1000.0 ); + dstate_setinfo( "input.voltage", "%.3f", data / 1000.0 ); +} + +static void get_io_current() +{ + uint8_t cmd = IO_CURRENT_CMD; + int16_t data; + + upsdebugx( 3, __FUNCTION__ ); + + /* + * The reported current can actually be negative, so we cannot + * check for I2C failure by looking for negative values + */ + data = i2c_smbus_read_word_data(upsfd, cmd); + + if ( data & ( 1 << 15 ) ) + { + data = data - ( 1 << 16 ); + } + + upsdebugx( 1, "Input Current: %.3fA", data / 1000.0 ); + dstate_setinfo( "input.current", "%.3f", data / 1000.0 ); +} + +static void get_firmware_version() +{ + uint8_t cmd = FIRMWARE_VERSION_CMD; + uint16_t data; + uint8_t major, minor; + + upsdebugx( 3, __FUNCTION__ ); + + I2C_READ_WORD( upsfd, cmd, __FUNCTION__ ) + + major = data >> 4; + minor = ( data << 4 & 0xf0 ) >> 4; + + if (( major != 1 ) || ( minor > 3 )) + { + upslogx( LOG_WARNING, "Unknown Firmware release: %d.%d", major, minor ); + } + + upsdebugx( 1, "UPS Firmware Version: %d.%d", major, minor ); + dstate_setinfo( "ups.firmware", "%d.%d", major, minor ); +} + +static void get_battery_profile() +{ + uint8_t cmd = BATTERY_PROFILE_CMD; + __u8 block[I2C_SMBUS_BLOCK_MAX]; + + upsdebugx( 3, __FUNCTION__ ); + + I2C_READ_BLOCK( upsfd, cmd, 14, block, __FUNCTION__ ) + + upsdebugx( 1, "Battery Capacity: %0.3fAh", ( block[1] << 8 | block[0] ) / 1000.0 ); + dstate_setinfo( "battery.capacity", "%0.3f", ( block[1] << 8 | block[0] ) / 1000.0 ); +} + +static void get_battery_profile_ext() +{ + uint8_t cmd = BATTERY_EXT_PROFILE_CMD; + __u8 block[I2C_SMBUS_BLOCK_MAX]; + + upsdebugx( 3, __FUNCTION__ ); + + I2C_READ_BLOCK( upsfd, cmd, 17, block, __FUNCTION__ ) + + switch( block[0] & 0xFF00 ) + { + case 0: + upsdebugx( 1, "Battery Chemistry: LiPO" ); + dstate_setinfo( "battery.type", "%s", "LiPO" ); + break; + case 1: + upsdebugx( 1, "Battery Chemistry: LiFePO4" ); + dstate_setinfo( "battery.type", "%s", "LiFePO4" ); + break; + default: + upsdebugx( 1, "Battery Chemistry: UNKNOWN" ); + dstate_setinfo( "battery.type", "%s", "UNKNOWN" ); + } +} + +static void get_power_off() +{ + uint8_t cmd = POWER_OFF_CMD; + uint8_t data; + + upsdebugx( 3, __FUNCTION__ ); + + I2C_READ_BYTE( upsfd, cmd, __FUNCTION__ ) + + if ( data == 255 ) + { + upsdebugx( 1, "Power Off: DISABLED" ); + } + else if ( data <= 250 ) + { + upsdebugx( 1, "Power Off: %d Seconds", data ); + } +} + +static void set_power_off() +{ + uint8_t cmd = POWER_OFF_CMD; + uint8_t data; + + upsdebugx( 3, __FUNCTION__ ); + + /* + * Acceptable values for shutdown_delay are 1-250, + * use 0/255 to clear a scheduled power off command + */ + + if ( shutdown_delay > 255 ) + { + upslogx( + LOG_WARNING, + "shutdown delay of >250 seconds requested, shortening to 250 seconds" + ); + shutdown_delay = 250; + } + + if ( shutdown_delay == 0 ) + { + upslogx( + LOG_WARNING, + "shutdown delay of 0 seconds requested, using 1 second instead" + ); + shutdown_delay = 1; + } + + I2C_WRITE_BYTE( upsfd, cmd, shutdown_delay, __FUNCTION__ ) +} + +static void get_time() +{ + uint8_t cmd = RTC_TIME_CMD; + __u8 block[I2C_SMBUS_BLOCK_MAX]; + uint8_t second, minute, hour, day, month, subsecond; + uint16_t year; + + upsdebugx( 3, __FUNCTION__ ); + + I2C_READ_BLOCK( upsfd, cmd, 9, block, __FUNCTION__ ) + + second = (( (block[0] >> 4 ) & 0x07) * 10 ) + ( block[0] & 0x0F ); + minute = (( (block[1] >> 4 ) & 0x07) * 10 ) + ( block[1] & 0x0F ); + hour = (( (block[2] >> 4 ) & 0x03) * 10 ) + ( block[2] & 0x0F ); + day = (( (block[4] >> 4 ) & 0x03) * 10 ) + ( block[4] & 0x0F ); + month = (( (block[5] >> 4 ) & 0x01) * 10 ) + ( block[5] & 0x0F ); + year = (( (block[6] >> 4 ) & 0x0F) * 10 ) + ( block[6] & 0x0F ) + 2000; + subsecond = block[7] * 100 / 256; + + upsdebugx( 1, "UPS Time: %02d:%02d:%02d.%02d", hour, minute, second, subsecond ); + dstate_setinfo( "ups.time", "%02d:%02d:%02d.%02d", hour, minute, second, subsecond ); + + upsdebugx( 1, "UPS Date: %04d-%02d-%02d", year, month, day ); + dstate_setinfo( "ups.date", "%04d-%02d-%02d", year, month, day ); +} + +static void get_i2c_address() +{ + uint8_t cmd = I2C_ADDRESS_CMD; + uint8_t data; + + upsdebugx( 3, __FUNCTION__ ); + + I2C_READ_BYTE( upsfd, cmd, __FUNCTION__ ) + + upsdebugx( 1, "I2C Address: 0x%0x", data ); + + if ( data == i2c_address ) + { + upsdebugx( 1, "Found device '0x%0x' on port '%s'", + (unsigned int) i2c_address, device_path ); + } + else + { + fatalx( EXIT_FAILURE, + "Could not find PiJuice HAT at I2C address 0x%0x", + i2c_address ); + } +} + +void upsdrv_initinfo(void) +{ + + dstate_setinfo( "ups.mfr", "%s", "PiJuice" ); + dstate_setinfo( "ups.type", "%s", "HAT" ); + + /* note: for a transition period, these data are redundant */ + + dstate_setinfo( "device.mfr", "%s", "PiJuice" ); + dstate_setinfo( "device.type", "%s", "HAT" ); + + upsdebugx( 1, "Low Battery Threshold: %0.0f%%", LOW_BATTERY_THRESHOLD ); + dstate_setinfo( "battery.charge.low", "%0.0f", LOW_BATTERY_THRESHOLD ); + + upsdebugx( 1, "Nominal Battery Voltage: %0.3fV", NOMINAL_BATTERY_VOLTAGE ); + dstate_setinfo( "battery.voltage.nominal", "%0.3f", NOMINAL_BATTERY_VOLTAGE ); + + get_i2c_address(); + get_battery_profile(); + get_battery_profile_ext(); +} + +void upsdrv_updateinfo(void) +{ + status_init(); + + get_status(); + get_battery_temperature(); + get_battery_voltage(); + get_battery_current(); + get_io_voltage(); + get_io_current(); + get_time(); + get_power_off(); + + status_commit(); + dstate_dataok(); +} + +void upsdrv_shutdown(void) +{ + set_power_off(); +} + +void upsdrv_help(void) +{ + printf("\nThe default I2C address is 20 [0x14]\n"); + printf("\n"); +} + +void upsdrv_makevartable(void) +{ + addvar(VAR_VALUE, "i2c_address", "Override i2c address setting"); +} + +void upsdrv_initups(void) +{ + upsfd = open_i2c_bus( device_path, i2c_address ); + + /* probe ups type */ + get_firmware_version(); + + /* get variables and flags from the command line */ + + if (getval("i2c_address")) + i2c_address = atoi(getval("i2c_address")); +} + +void upsdrv_cleanup(void) +{ + close(upsfd); +} diff --git a/drivers/powerware-mib.c b/drivers/powerware-mib.c index 670abf782b..d33b4f1fce 100644 --- a/drivers/powerware-mib.c +++ b/drivers/powerware-mib.c @@ -25,7 +25,7 @@ #include "powerware-mib.h" -#define PW_MIB_VERSION "0.90" +#define PW_MIB_VERSION "0.92" /* TODO: more sysOID and MIBs support: * @@ -204,10 +204,11 @@ static snmp_info_t pw_mib[] = { SU_FLAG_STATIC, NULL }, { "ups.model", ST_FLAG_STRING, SU_INFOSIZE, PW_OID_MODEL_NAME, "", SU_FLAG_STATIC, NULL }, + /* FIXME: the 2 "firmware" entries below should be SU_FLAG_SEMI_STATIC */ { "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, PW_OID_FIRMREV, "", - SU_FLAG_STATIC, NULL }, + 0, NULL }, { "ups.firmware.aux", ST_FLAG_STRING, SU_INFOSIZE, IETF_OID_AGENTREV, "", - SU_FLAG_STATIC, NULL }, + 0, NULL }, { "ups.serial", ST_FLAG_STRING, SU_INFOSIZE, IETF_OID_IDENT, "", SU_FLAG_STATIC, NULL }, { "ups.load", 0, 1.0, PW_OID_OUT_LOAD, "", @@ -256,7 +257,7 @@ static snmp_info_t pw_mib[] = { { "battery.date", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.1.2.6.0", NULL, SU_FLAG_OK, NULL }, /* Output page */ - { "output.phases", 0, 1.0, PW_OID_OUT_LINES, "", 0, NULL, NULL }, + { "output.phases", 0, 1.0, PW_OID_OUT_LINES, "", 0, NULL }, /* XUPS-MIB::xupsOutputFrequency.0 */ { "output.frequency", 0, 0.1, "1.3.6.1.4.1.534.1.4.2.0", "", 0, NULL }, /* XUPS-MIB::xupsConfigOutputFreq.0 */ @@ -303,7 +304,7 @@ static snmp_info_t pw_mib[] = { /* Input page */ { "input.phases", 0, 1.0, PW_OID_IN_LINES, "", - 0, NULL, NULL }, + 0, NULL }, { "input.frequency", 0, 0.1, PW_OID_IN_FREQUENCY, "", 0, NULL }, { "input.voltage", 0, 1.0, PW_OID_IN_VOLTAGE ".0", "", diff --git a/drivers/raritan-pdu-mib.c b/drivers/raritan-pdu-mib.c index 255ab418bb..96c0ae3ca0 100644 --- a/drivers/raritan-pdu-mib.c +++ b/drivers/raritan-pdu-mib.c @@ -1,6 +1,6 @@ /* raritan-mib.c - data to monitor Raritan PDUs (Basic and Complex) * - * Copyright (C) 2008 + * Copyright (C) 2008-2019 * Arnaud Quette * * Sponsored by Eaton @@ -25,7 +25,7 @@ #include "raritan-pdu-mib.h" -#define RARITAN_MIB_VERSION "0.5" +#define RARITAN_MIB_VERSION "0.6" /* Raritan MIB * this one uses the same MIB as Eaton Revelation, @@ -34,9 +34,9 @@ #define RARITAN_SYSOID RARITAN_BASE_OID #define RARITAN_OID_MODEL_NAME ".1.3.6.1.4.1.13742.1.1.12.0" -#define DO_OFF 0 -#define DO_ON 1 -#define DO_CYCLE 2 +#define DO_OFF "0" +#define DO_ON "1" +#define DO_CYCLE "2" static info_lkp_t outlet_status_info[] = { { -1, "error" }, @@ -50,54 +50,54 @@ static info_lkp_t outlet_status_info[] = { static snmp_info_t raritan_mib[] = { /* Device page */ { "device.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "Raritan", - SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL }, + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, { "device.model", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.13742.1.1.12.0", - "Generic SNMP PDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + "Generic SNMP PDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, { "device.serial", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.13742.1.1.2.0", "", - SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + SU_FLAG_STATIC | SU_FLAG_OK, NULL }, { "device.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "pdu", - SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL }, + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, { "device.macaddr", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.13742.1.1.6.0", "", - SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + SU_FLAG_STATIC | SU_FLAG_OK, NULL }, /* UPS page */ { "ups.mfr", ST_FLAG_STRING, SU_INFOSIZE, NULL, "Raritan", - SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL }, + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, { "ups.model", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.13742.1.1.12.0", - "Generic SNMP PDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + "Generic SNMP PDU", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, { "ups.id", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.13742.1.1.13.0", - "unknown", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + "unknown", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, { "ups.serial", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.13742.1.1.2.0", "", - SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + SU_FLAG_STATIC | SU_FLAG_OK, NULL }, { "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.13742.1.1.1.0", "", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, { "ups.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "pdu", - SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL }, - { "ups.temperature", 0, 1, ".1.3.6.1.4.1.13742.1.3.1.5.0", NULL, 0, NULL, NULL }, + SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, + { "ups.temperature", 0, 1, ".1.3.6.1.4.1.13742.1.3.1.5.0", NULL, 0, NULL }, /* Outlet page */ { "outlet.id", 0, 1, NULL, "0", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, { "outlet.desc", ST_FLAG_RW | ST_FLAG_STRING, 20, NULL, "All outlets", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, { "outlet.count", 0, 1, ".1.3.6.1.4.1.13742.1.2.1.0", "0", 0, NULL }, - { "outlet.current", 0, 0.001, ".1.3.6.1.4.1.13742.1.3.1.1" ".0", NULL, 0, NULL, NULL }, - { "outlet.voltage", 0, 0.001, ".1.3.6.1.4.1.13742.1.3.1.2" ".0", NULL, 0, NULL, NULL }, - { "outlet.realpower", 0, 1.0, ".1.3.6.1.4.1.13742.1.3.1.3" ".0", NULL, 0, NULL, NULL }, - { "outlet.power", 0, 1.0, ".1.3.6.1.4.1.13742.1.3.1.4" ".0", NULL, 0, NULL, NULL }, + { "outlet.current", 0, 0.001, ".1.3.6.1.4.1.13742.1.3.1.1" ".0", NULL, 0, NULL }, + { "outlet.voltage", 0, 0.001, ".1.3.6.1.4.1.13742.1.3.1.2" ".0", NULL, 0, NULL }, + { "outlet.realpower", 0, 1.0, ".1.3.6.1.4.1.13742.1.3.1.3" ".0", NULL, 0, NULL }, + { "outlet.power", 0, 1.0, ".1.3.6.1.4.1.13742.1.3.1.4" ".0", NULL, 0, NULL }, /* outlet template definition * Caution: the index of the data start at 0, while the name is +1 * ie outlet.1 => .0 */ - { "outlet.%i.switchable", 0, 1, ".1.3.6.1.4.1.13742.1.2.2.1.1.%i", "yes", SU_FLAG_STATIC | SU_OUTLET, NULL, NULL }, - { "outlet.%i.id", 0, 1, NULL, "%i", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK | SU_OUTLET, NULL, NULL }, - { "outlet.%i.desc", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.13742.1.2.2.1.2.%i", NULL, SU_OUTLET, NULL, NULL }, - { "outlet.%i.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.13742.1.2.2.1.3.%i", NULL, SU_FLAG_OK | SU_OUTLET, &outlet_status_info[0], NULL }, - { "outlet.%i.current", 0, 0.001, ".1.3.6.1.4.1.13742.1.2.2.1.4.%i", NULL, SU_OUTLET, NULL, NULL }, - { "outlet.%i.current.maximum", 0, 0.001, ".1.3.6.1.4.1.13742.1.2.2.1.5.%i", NULL, SU_OUTLET, NULL, NULL }, - { "outlet.%i.realpower", 0, 1.0, ".1.3.6.1.4.1.13742.1.2.2.1.7.%i", NULL, SU_OUTLET, NULL, NULL }, - { "outlet.%i.voltage", 0, 1.0, ".1.3.6.1.4.1.13742.1.2.2.1.6.%i", NULL, SU_OUTLET, NULL, NULL }, - { "outlet.%i.powerfactor", 0, 0.01, ".1.3.6.1.4.1.13742.1.2.2.1.9.%i", NULL, SU_OUTLET, NULL, NULL }, - { "outlet.%i.power", 0, 1.0, ".1.3.6.1.4.1.13742.1.2.2.1.8.%i", NULL, SU_OUTLET, NULL, NULL }, + { "outlet.%i.switchable", 0, 1, ".1.3.6.1.4.1.13742.1.2.2.1.1.%i", "yes", SU_FLAG_STATIC | SU_OUTLET, NULL }, + { "outlet.%i.id", 0, 1, NULL, "%i", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK | SU_OUTLET, NULL }, + { "outlet.%i.desc", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.13742.1.2.2.1.2.%i", NULL, SU_OUTLET, NULL }, + { "outlet.%i.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.13742.1.2.2.1.3.%i", NULL, SU_FLAG_OK | SU_OUTLET, &outlet_status_info[0] }, + { "outlet.%i.current", 0, 0.001, ".1.3.6.1.4.1.13742.1.2.2.1.4.%i", NULL, SU_OUTLET, NULL }, + { "outlet.%i.current.maximum", 0, 0.001, ".1.3.6.1.4.1.13742.1.2.2.1.5.%i", NULL, SU_OUTLET, NULL }, + { "outlet.%i.realpower", 0, 1.0, ".1.3.6.1.4.1.13742.1.2.2.1.7.%i", NULL, SU_OUTLET, NULL }, + { "outlet.%i.voltage", 0, 1.0, ".1.3.6.1.4.1.13742.1.2.2.1.6.%i", NULL, SU_OUTLET, NULL }, + { "outlet.%i.powerfactor", 0, 0.01, ".1.3.6.1.4.1.13742.1.2.2.1.9.%i", NULL, SU_OUTLET, NULL }, + { "outlet.%i.power", 0, 1.0, ".1.3.6.1.4.1.13742.1.2.2.1.8.%i", NULL, SU_OUTLET, NULL }, /* FIXME: * - delay for startup/shutdown sequence @@ -110,15 +110,15 @@ static snmp_info_t raritan_mib[] = { /* instant commands. */ /* Note that load.cycle might be replaced by / mapped on shutdown.reboot */ /* no counterpart found! - { "outlet.load.off", 0, DO_OFF, ".1.3.6.1.4.1.13742.1.2.2.1.3.0", NULL, SU_TYPE_CMD, NULL, NULL }, - { "outlet.load.on", 0, DO_ON, ".1.3.6.1.4.1.13742.1.2.2.1.3.0", NULL, SU_TYPE_CMD, NULL, NULL }, - { "outlet.load.cycle", 0, DO_CYCLE, ".1.3.6.1.4.1.13742.1.2.2.1.3.0", NULL, SU_TYPE_CMD, NULL, NULL }, */ - { "outlet.%i.load.off", 0, DO_OFF, ".1.3.6.1.4.1.13742.1.2.2.1.3.%i", NULL, SU_TYPE_CMD | SU_OUTLET, NULL, NULL }, - { "outlet.%i.load.on", 0, DO_ON, ".1.3.6.1.4.1.13742.1.2.2.1.3.%i", NULL, SU_TYPE_CMD | SU_OUTLET, NULL, NULL }, - { "outlet.%i.load.cycle", 0, DO_CYCLE, ".1.3.6.1.4.1.13742.1.2.2.1.3.%i", NULL, SU_TYPE_CMD | SU_OUTLET, NULL, NULL }, + { "outlet.load.off", 0, 1, ".1.3.6.1.4.1.13742.1.2.2.1.3.0", DO_OFF, SU_TYPE_CMD, NULL }, + { "outlet.load.on", 0, 1, ".1.3.6.1.4.1.13742.1.2.2.1.3.0", DO_ON, SU_TYPE_CMD, NULL }, + { "outlet.load.cycle", 0, 1, ".1.3.6.1.4.1.13742.1.2.2.1.3.0", DO_CYCLE, SU_TYPE_CMD, NULL }, */ + { "outlet.%i.load.off", 0, 1, ".1.3.6.1.4.1.13742.1.2.2.1.3.%i", DO_OFF, SU_TYPE_CMD | SU_OUTLET, NULL }, + { "outlet.%i.load.on", 0, 1, ".1.3.6.1.4.1.13742.1.2.2.1.3.%i", DO_ON, SU_TYPE_CMD | SU_OUTLET, NULL }, + { "outlet.%i.load.cycle", 0, 1, ".1.3.6.1.4.1.13742.1.2.2.1.3.%i", DO_CYCLE, SU_TYPE_CMD | SU_OUTLET, NULL }, /* end of structure. */ - { NULL, 0, 0, NULL, NULL, 0, NULL, NULL } + { NULL, 0, 0, NULL, NULL, 0, NULL } }; mib2nut_info_t raritan = { "raritan", RARITAN_MIB_VERSION, NULL, RARITAN_OID_MODEL_NAME, raritan_mib, RARITAN_SYSOID }; diff --git a/drivers/raritan-px2-mib.c b/drivers/raritan-px2-mib.c index 1157ffd772..6dbff80339 100644 --- a/drivers/raritan-px2-mib.c +++ b/drivers/raritan-px2-mib.c @@ -23,7 +23,7 @@ #include "raritan-px2-mib.h" -#define RARITAN_PX2_MIB_VERSION "0.1" +#define RARITAN_PX2_MIB_VERSION "0.2" #define RARITAN_PX2_MIB_SYSOID ".1.3.6.1.4.1.13742.6" #define RARITAN_PX2_OID_MODEL_NAME ".1.3.6.1.4.1.13742.6.3.2.1.1.3.1" @@ -69,65 +69,65 @@ static snmp_info_t raritan_px2_mib[] = { /* pduManufacturer.1 = STRING: Raritan */ { "device.mfr", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.13742.6.3.2.1.1.2.1", - "Raritan", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + "Raritan", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, /* pduModel.1 = STRING: PX2-5475 */ { "device.model", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.13742.6.3.2.1.1.3.1", - "Raritan PX2 SNMP PDU device", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + "Raritan PX2 SNMP PDU device", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, /* pduSerialNumber.1 = STRING: QFC3950619 */ { "device.serial", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.13742.6.3.2.1.1.4.1", - NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, - { "device.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "pdu", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL, NULL }, + NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL }, + { "device.type", ST_FLAG_STRING, SU_INFOSIZE, NULL, "pdu", SU_FLAG_STATIC | SU_FLAG_ABSENT | SU_FLAG_OK, NULL }, /* pxMACAddress.1 = STRING: 0:d:5d:b:49:0 */ { "device.macaddr", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.13742.6.3.2.2.1.11.1", - NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + NULL, SU_FLAG_STATIC | SU_FLAG_OK, NULL }, /* boardVersion.1.mainController.1 = STRING: 0x01 */ /* FIXME: not compliant! to be RFC'ed */ - { "device.revision", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.13742.6.3.2.3.1.4.1.1.1", "", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + { "device.revision", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.13742.6.3.2.3.1.4.1.1.1", "", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, /* FIXME: move to device collection! */ /* Wrong OID! * { "ups.mfr.date", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.13742.6.3.2.3.1.6.1.1.1", "", SU_FLAG_OK | SU_FLAG_STATIC, NULL },*/ /* boardFirmwareVersion.1.mainController.1 = STRING: 2.4.3.5-40298 */ - { "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.13742.6.3.2.3.1.6.1.1.1", "", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + { "ups.firmware", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.13742.6.3.2.3.1.6.1.1.1", "", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, /* pduName.1 = STRING: my PX */ - { "ups.id", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.13742.6.3.2.2.1.13.1", "", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + { "ups.id", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.13742.6.3.2.2.1.13.1", "", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, { "ups.model", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.13742.6.3.2.1.1.3.1", - "Raritan PX2 SNMP PDU device", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + "Raritan PX2 SNMP PDU device", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, /* Input data: * Units are given in inletSensorUnits.1.1.%i * Value should be scaled by inletSensorDecimalDigits.1.1.%i * For example, if the value is 1 and inletSensorDecimalDigits is 2, then actual value is 0.01. */ /* measurementsInletSensorValue.1.1.rmsCurrent = Gauge32: 10 (A) */ - { "input.load", 0, 0.1, ".1.3.6.1.4.1.13742.6.5.2.3.1.4.1.1.1", NULL, SU_FLAG_OK, NULL, NULL }, + { "input.load", 0, 0.1, ".1.3.6.1.4.1.13742.6.5.2.3.1.4.1.1.1", NULL, SU_FLAG_OK, NULL }, /* measurementsInletSensorValue.1.1.rmsVoltage = Gauge32: 119 (V) */ - { "input.voltage", 0, 1, ".1.3.6.1.4.1.13742.6.5.2.3.1.4.1.1.4", NULL, SU_FLAG_OK, NULL, NULL }, + { "input.voltage", 0, 1, ".1.3.6.1.4.1.13742.6.5.2.3.1.4.1.1.4", NULL, SU_FLAG_OK, NULL }, /* measurementsInletSensorValue.1.1.activePower = Gauge32: 10 (W) */ - { "input.realpower", 0, 1, ".1.3.6.1.4.1.13742.6.5.2.3.1.4.1.1.5", NULL, SU_FLAG_OK, NULL, NULL }, + { "input.realpower", 0, 1, ".1.3.6.1.4.1.13742.6.5.2.3.1.4.1.1.5", NULL, SU_FLAG_OK, NULL }, /* measurementsInletSensorValue.1.1.apparentPower = Gauge32: 122 (VA) */ - { "input.power", 0, 1, ".1.3.6.1.4.1.13742.6.5.2.3.1.4.1.1.6", NULL, SU_FLAG_OK, NULL, NULL }, + { "input.power", 0, 1, ".1.3.6.1.4.1.13742.6.5.2.3.1.4.1.1.6", NULL, SU_FLAG_OK, NULL }, /* measurementsInletSensorValue.1.1.powerFactor = Gauge32: 8 (none) */ /* FIXME: need RFC! */ - { "input.powerfactor", 0, 0.01, ".1.3.6.1.4.1.13742.6.5.2.3.1.4.1.1.7", NULL, SU_FLAG_OK, NULL, NULL }, + { "input.powerfactor", 0, 0.01, ".1.3.6.1.4.1.13742.6.5.2.3.1.4.1.1.7", NULL, SU_FLAG_OK, NULL }, /* measurementsInletSensorValue.1.1.activeEnergy = Gauge32: 193359 (wattHour) */ - /* { "unmapped.measurementsInletSensorValue", 0, 1, ".1.3.6.1.4.1.13742.6.5.2.3.1.4.1.1.8", NULL, SU_FLAG_OK, NULL, NULL }, */ + /* { "unmapped.measurementsInletSensorValue", 0, 1, ".1.3.6.1.4.1.13742.6.5.2.3.1.4.1.1.8", NULL, SU_FLAG_OK, NULL }, */ /* inletPlug.1.1 = INTEGER: plugIEC320C20(6) */ /* FIXME: need RFC (input.type | [input.]inlet.type...) and standardization * { "unmapped.inletPlug", 0, 1, ".1.3.6.1.4.1.13742.6.3.3.3.1.4.1.1", NULL, SU_FLAG_OK, NULL },*/ /* outletCount.1 = INTEGER: 24 */ - { "outlet.count", 0, 1, ".1.3.6.1.4.1.13742.6.3.2.2.1.4.1", "0", SU_FLAG_STATIC | SU_FLAG_OK, NULL, NULL }, + { "outlet.count", 0, 1, ".1.3.6.1.4.1.13742.6.3.2.2.1.4.1", "0", SU_FLAG_STATIC | SU_FLAG_OK, NULL }, /* outlet template definition * Indexes start from 1, ie outlet.1 => .1 */ /* Note: the first definition is used to determine the base index (ie 0 or 1) */ /* outletName.1.%i = STRING: */ - { "outlet.%i.desc", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.13742.6.3.5.3.1.3.1.%i", NULL, SU_OUTLET, NULL, NULL }, + { "outlet.%i.desc", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.13742.6.3.5.3.1.3.1.%i", NULL, SU_OUTLET, NULL }, /* outletSwitchingState.1.%i = INTEGER: on(7) */ - { "outlet.%i.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.13742.6.4.1.2.1.3.1.%i", NULL, SU_OUTLET, &raritanpx2_outlet_status_info[0], NULL }, + { "outlet.%i.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.13742.6.4.1.2.1.3.1.%i", NULL, SU_OUTLET, &raritanpx2_outlet_status_info[0] }, /* outletLabel.1.%i = STRING: 1 */ - { "outlet.%i.id", 0, 1, ".1.3.6.1.4.1.13742.6.3.5.3.1.2.1.%i", "%i", SU_FLAG_STATIC | SU_OUTLET | SU_FLAG_OK, NULL, NULL }, + { "outlet.%i.id", 0, 1, ".1.3.6.1.4.1.13742.6.3.5.3.1.2.1.%i", "%i", SU_FLAG_STATIC | SU_OUTLET | SU_FLAG_OK, NULL }, /* outletReceptacle.1.1 = INTEGER: receptacleNEMA520R(37) */ /* FIXME: need RFC and standardization @@ -135,30 +135,30 @@ static snmp_info_t raritan_px2_mib[] = { /* RMS Current (divide by 10). e.g. 5 == 0.5A */ /* measurementsOutletSensorValue.1.%i.rmsCurrent = Gauge32: 10 */ - { "outlet.%i.current", 0, 0.1, ".1.3.6.1.4.1.13742.6.5.4.3.1.4.1.%i.1", NULL, SU_OUTLET | SU_FLAG_OK, NULL, NULL }, + { "outlet.%i.current", 0, 0.1, ".1.3.6.1.4.1.13742.6.5.4.3.1.4.1.%i.1", NULL, SU_OUTLET | SU_FLAG_OK, NULL }, /* measurementsOutletSensorValue.1.%i.rmsVoltage = Gauge32: 119 */ - { "outlet.%i.voltage", 0, 1, ".1.3.6.1.4.1.13742.6.5.4.3.1.4.1.%i.4", "%i", SU_OUTLET | SU_FLAG_OK, NULL, NULL }, + { "outlet.%i.voltage", 0, 1, ".1.3.6.1.4.1.13742.6.5.4.3.1.4.1.%i.4", "%i", SU_OUTLET | SU_FLAG_OK, NULL }, /* measurementsOutletSensorValue.1.%i.activePower = Gauge32: 10 */ - { "outlet.%i.power", 0, 1, ".1.3.6.1.4.1.13742.6.5.4.3.1.4.1.%i.5", "%i", SU_OUTLET | SU_FLAG_OK, NULL, NULL }, + { "outlet.%i.power", 0, 1, ".1.3.6.1.4.1.13742.6.5.4.3.1.4.1.%i.5", "%i", SU_OUTLET | SU_FLAG_OK, NULL }, /* measurementsOutletSensorValue.1.%i.apparentPower = Gauge32: 122 */ - { "outlet.%i.realpower", 0, 1, ".1.3.6.1.4.1.13742.6.5.4.3.1.4.1.%i.6", "%i", SU_OUTLET | SU_FLAG_OK, NULL, NULL }, + { "outlet.%i.realpower", 0, 1, ".1.3.6.1.4.1.13742.6.5.4.3.1.4.1.%i.6", "%i", SU_OUTLET | SU_FLAG_OK, NULL }, /* measurementsOutletSensorValue.1.%i.powerFactor = Gauge32: 8 */ - { "outlet.%i.powerfactor", 0, 1, ".1.3.6.1.4.1.13742.6.5.4.3.1.4.1.%i.7", "%i", SU_OUTLET | SU_FLAG_OK, NULL, NULL }, + { "outlet.%i.powerfactor", 0, 1, ".1.3.6.1.4.1.13742.6.5.4.3.1.4.1.%i.7", "%i", SU_OUTLET | SU_FLAG_OK, NULL }, /* measurementsOutletSensorValue.1.1.activeEnergy = Gauge32: 89890 */ /* FIXME: - * { "unmapped.measurementsOutletSensorValue", 0, 1, ".1.3.6.1.4.1.13742.6.5.4.3.1.4.1.1.8", NULL, SU_FLAG_OK, NULL, NULL }, */ + * { "unmapped.measurementsOutletSensorValue", 0, 1, ".1.3.6.1.4.1.13742.6.5.4.3.1.4.1.1.8", NULL, SU_FLAG_OK, NULL }, */ /* measurementsOutletSensorValue.1.1.onOff = Gauge32: 0 */ /* FIXME: * { "unmapped.measurementsOutletSensorValue", 0, 1, ".1.3.6.1.4.1.13742.6.5.4.3.1.4.1.1.14", NULL, SU_FLAG_OK, NULL }, */ /* outletSwitchable.1.%i = INTEGER: true(1) */ - { "outlet.%i.switchable", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.13742.6.3.5.3.1.28.1.%i", "no", SU_FLAG_STATIC | SU_OUTLET | SU_FLAG_OK, &outlet_switchability_info[0], NULL }, + { "outlet.%i.switchable", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.13742.6.3.5.3.1.28.1.%i", "no", SU_FLAG_STATIC | SU_OUTLET | SU_FLAG_OK, &outlet_switchability_info[0] }, /* instant commands. */ /* switchingOperation.1.1 = INTEGER: on(1) */ - { "outlet.%i.load.off", 0, 0, ".1.3.6.1.4.1.13742.6.4.1.2.1.2.1.%i", NULL, SU_TYPE_CMD | SU_OUTLET, NULL, NULL }, - { "outlet.%i.load.on", 0, 1, ".1.3.6.1.4.1.13742.6.4.1.2.1.2.1.%i", NULL, SU_TYPE_CMD | SU_OUTLET, NULL, NULL }, - { "outlet.%i.load.cycle", 0, 2, ".1.3.6.1.4.1.13742.6.4.1.2.1.2.1.%i", NULL, SU_TYPE_CMD | SU_OUTLET, NULL, NULL }, + { "outlet.%i.load.off", 0, 1, ".1.3.6.1.4.1.13742.6.4.1.2.1.2.1.%i", "0", SU_TYPE_CMD | SU_OUTLET, NULL }, + { "outlet.%i.load.on", 0, 1, ".1.3.6.1.4.1.13742.6.4.1.2.1.2.1.%i", "1", SU_TYPE_CMD | SU_OUTLET, NULL }, + { "outlet.%i.load.cycle", 0, 1, ".1.3.6.1.4.1.13742.6.4.1.2.1.2.1.%i", "2", SU_TYPE_CMD | SU_OUTLET, NULL }, #ifdef DEBUG /* pduCount.0 = INTEGER: 1 */ diff --git a/drivers/snmp-ups.c b/drivers/snmp-ups.c index 39e0a097ff..1f4c3c342e 100644 --- a/drivers/snmp-ups.c +++ b/drivers/snmp-ups.c @@ -4,7 +4,7 @@ * * Copyright (C) * 2002 - 2014 Arnaud Quette - * 2015 - 2017 Eaton (author: Arnaud Quette ) + * 2015 - 2019 Eaton (author: Arnaud Quette ) * 2017 Eaton (author: Jim Klimov ) * 2002 - 2006 Dmitry Frolov * J.W. Hoogervorst @@ -62,6 +62,8 @@ #include "apc-ats-mib.h" #include "apc-pdu-mib.h" #include "eaton-ats30-mib.h" +#include "emerson-avocent-pdu-mib.h" +#include "hpe-pdu-mib.h" /* Address API change */ #ifndef usmAESPrivProtocol @@ -89,12 +91,15 @@ static mib2nut_info_t *mib2nut[] = { &huawei, &tripplite_ietf, &eaton_ats16, + &eaton_ats16_g2, &apc_ats, &raritan_px2, &eaton_ats30, &apc_pdu_rpdu, &apc_pdu_rpdu2, &apc_pdu_msp, + &emerson_avocent_pdu, + &hpe_pdu, /* * Prepend vendor specific MIB mappings before IETF, so that * if a device supports both IETF and vendor specific MIB, @@ -109,6 +114,7 @@ struct snmp_session g_snmp_sess, *g_snmp_sess_p; const char *OID_pwr_status; int g_pwr_battery; int pollfreq; /* polling frequency */ +int quirk_symmetra_threephase = 0; /* Number of device(s): standard is "1", but daisychain means more than 1 */ long devices_count = 1; int current_device_number = 0; /* global var to handle daisychain iterations - changed by loops in snmp_ups_walk() and su_addcmd() */ @@ -124,7 +130,7 @@ const char *mibname; const char *mibvers; #define DRIVER_NAME "Generic SNMP UPS driver" -#define DRIVER_VERSION "1.02" +#define DRIVER_VERSION "1.12" /* driver description structure */ upsdrv_info_t upsdrv_info = { @@ -146,6 +152,11 @@ time_t lastpoll = 0; /* template OIDs index start with 0 or 1 (estimated stable for a MIB), * automatically guessed at the first pass */ int template_index_base = -1; +/* Not that stable in the end... */ +int device_template_index_base = -1; /* OID index of the 1rst daisychained device */ +int outlet_template_index_base = -1; +int outletgroup_template_index_base = -1; +int device_template_offset = -1; /* sysOID location */ #define SYSOID_OID ".1.3.6.1.2.1.1.2.0" @@ -154,6 +165,7 @@ int template_index_base = -1; static void disable_transfer_oids(void); bool_t get_and_process_data(int mode, snmp_info_t *su_info_p); int extract_template_number(int template_type, const char* varname); +int get_template_type(const char* varname); /* --------------------------------------------- * driver functions implementations @@ -188,6 +200,11 @@ su_addcmd(su_info_p); if (testvar("notransferoids")) disable_transfer_oids(); + if (testvar("symmetrathreephase")) + quirk_symmetra_threephase = 1; + else + quirk_symmetra_threephase = 0; + /* initialize all other INFO_ fields from list */ if (snmp_ups_walk(SU_WALKMODE_INIT) == TRUE) dstate_dataok(); @@ -219,12 +236,17 @@ void upsdrv_updateinfo(void) /* Commit status first, otherwise in daisychain mode, "device.0" may * clear the alarm count since it has an empty alarm buffer and if there * is only one device that has alarms! */ + if (daisychain_enabled == FALSE) + alarm_commit(); status_commit(); - alarm_commit(); + if (daisychain_enabled == TRUE) + alarm_commit(); /* store timestamp */ lastpoll = time(NULL); } + else /* Just tell everything is ok to upsd */ + dstate_dataok(); } void upsdrv_shutdown(void) @@ -286,6 +308,8 @@ void upsdrv_makevartable(void) "Specifies the Net-SNMP timeout in seconds between retries (default=1)"); addvar(VAR_FLAG, "notransferoids", "Disable transfer OIDs (use on APCC Symmetras)"); + addvar(VAR_FLAG, "symmetrathreephase", + "Enable APCC three phase Symmetra quirks (use on APCC three phase Symmetras)"); addvar(VAR_VALUE, SU_VAR_SECLEVEL, "Set the securityLevel used for SNMPv3 messages (default=noAuthNoPriv, allowed: authNoPriv,authPriv)"); addvar(VAR_VALUE | VAR_SENSITIVE, SU_VAR_SECNAME, @@ -764,15 +788,20 @@ static bool_t decode_str(struct snmp_pdu *pdu, char *buf, size_t buf_len, info_l case ASN_OPAQUE: len = pdu->variables->val_len > buf_len - 1 ? buf_len - 1 : pdu->variables->val_len; - if (len > 0) { - /* Test for hexadecimal values */ - if (!isprint(pdu->variables->val.string[0])) - snprint_hexstring(buf, buf_len, pdu->variables->val.string, pdu->variables->val_len); - else { - memcpy(buf, pdu->variables->val.string, len); - buf[len] = '\0'; + /* Test for hexadecimal values */ + int hex = 0, x; + u_char *cp; + for(cp = pdu->variables->val.string, x = 0; x < (int)pdu->variables->val_len; x++, cp++) { + if (!(isprint(*cp) || isspace(*cp))) { + hex = 1; } } + if (hex) + snprint_hexstring(buf, buf_len, pdu->variables->val.string, pdu->variables->val_len); + else { + memcpy(buf, pdu->variables->val.string, len); + buf[len] = '\0'; + } break; case ASN_INTEGER: case ASN_COUNTER: @@ -1074,7 +1103,7 @@ static void disable_transfer_oids(void) } /* Universal function to add or update info element. - * If value is NULL, use the default one (su_info_p->dfl) */ + * If value is NULL, use the default one (su_info_p->dfl) if provided */ void su_setinfo(snmp_info_t *su_info_p, const char *value) { info_lkp_t *info_lkp; @@ -1118,8 +1147,12 @@ void su_setinfo(snmp_info_t *su_info_p, const char *value) { if (value != NULL) dstate_setinfo(info_type, "%s", value); - else + else if (su_info_p->dfl != NULL) dstate_setinfo(info_type, "%s", su_info_p->dfl); + else { + upsdebugx(3, "%s: no value nor default provided, aborting...", __func__); + return; + } dstate_setflags(info_type, su_info_p->info_flags); dstate_setaux(info_type, su_info_p->info_len); @@ -1319,7 +1352,7 @@ mib2nut_info_t *match_sysoid() continue; /* Clear variables */ - memset(mib2nut_sysOID, 0, MAX_OID_LEN); + memset(mib2nut_sysOID, 0, sizeof(mib2nut_sysOID)); mib2nut_sysOID_len = MAX_OID_LEN; if (!read_objid(mib2nut[i]->sysOID, mib2nut_sysOID, &mib2nut_sysOID_len)) @@ -1551,7 +1584,6 @@ snmp_info_t *instantiate_info(snmp_info_t *info_template, snmp_info_t *new_insta new_instance->dfl = info_template->dfl; new_instance->flags = info_template->flags; new_instance->oid2info = info_template->oid2info; - new_instance->setvar = info_template->setvar; upsdebugx(2, "instantiate_info: template instantiated"); return new_instance; @@ -1578,16 +1610,31 @@ void free_info(snmp_info_t *su_info_p) * the MIB, based on a test using a template OID */ int base_snmp_template_index(const snmp_info_t *su_info_p) { - int base_index = template_index_base; + if (!su_info_p) + return -1; + + int base_index = -1; char test_OID[SU_INFOSIZE]; + int template_type = get_template_type(su_info_p->info_type); + + if (!su_info_p->OID) + return base_index; upsdebugx(3, "%s: OID template = %s", __func__, su_info_p->OID); - /* FIXME: differentiate between template types (SU_OUTLET | SU_OUTLET_GROUP) - * which may have different indexes ; and store it to not redo it again */ -// FIXME: for now, process every time the index, if it's a "device" template! - if (!(su_info_p->flags & SU_OUTLET) && !(su_info_p->flags & SU_OUTLET_GROUP)) - template_index_base = -1; + /* Try to differentiate between template types which may have + * different indexes ; and store it to not redo it again */ + switch (template_type) { + case SU_OUTLET: + template_index_base = outlet_template_index_base; + break; + case SU_OUTLET_GROUP: + template_index_base = outletgroup_template_index_base; + break; + case SU_DAISY: + template_index_base = device_template_index_base; + } + base_index = template_index_base; if (template_index_base == -1) { @@ -1598,52 +1645,74 @@ int base_snmp_template_index(const snmp_info_t *su_info_p) if (is_multiple_template(su_info_p->OID) == TRUE) { if (su_info_p->flags & SU_TYPE_DAISY_1) { snprintf(test_OID, sizeof(test_OID), su_info_p->OID, - current_device_number - 1, base_index); + current_device_number + device_template_offset, base_index); } else { snprintf(test_OID, sizeof(test_OID), su_info_p->OID, - base_index, current_device_number - 1); + base_index, current_device_number + device_template_offset); } } else { snprintf(test_OID, sizeof(test_OID), su_info_p->OID, base_index); } - if (nut_snmp_get(test_OID) != NULL) - break; + if (nut_snmp_get(test_OID) != NULL) { + if (su_info_p->flags & SU_FLAG_ZEROINVALID) { + long value; + if ((nut_snmp_get_int(test_OID, &value)) && (value!=0)) { + break; + } + } + else if (su_info_p->flags & SU_FLAG_NAINVALID) { + char value[SU_BUFSIZE]; + if ((nut_snmp_get_str(test_OID, value, SU_BUFSIZE, NULL)) + && (strncmp(value, "N/A", 3))) { + break; + } + } + else { + break; + } + } } /* Only store if it's a template for outlets or outlets groups, * not for daisychain (which has different index) */ - if ((su_info_p->flags & SU_OUTLET) || (su_info_p->flags & SU_OUTLET_GROUP)) - template_index_base = base_index; + if (su_info_p->flags & SU_OUTLET) + outlet_template_index_base = base_index; + else if (su_info_p->flags & SU_OUTLET_GROUP) + outletgroup_template_index_base = base_index; + else + device_template_index_base = base_index; } - upsdebugx(3, "%s: %i", __func__, template_index_base); + upsdebugx(3, "%s: template_index_base = %i", __func__, base_index); return base_index; } -/* return the NUT offset (increment) based on template_index_base - * ie (template_index_base == 0) => increment +1 - * (template_index_base == 1) => increment +0 */ -int base_nut_template_offset(void) -{ - return (template_index_base==0)?1:0; -} - /* Try to determine the number of items (outlets, outlet groups, ...), * using a template definition. Walk through the template until we can't * get anymore values. I.e., if we can iterate up to 8 item, return 8 */ -static int guestimate_template_count(const char *OID_template) +static int guestimate_template_count(snmp_info_t *su_info_p) { int base_index = 0; char test_OID[SU_INFOSIZE]; int base_count; + const char *OID_template = su_info_p->OID; upsdebugx(1, "%s(%s)", __func__, OID_template); /* Determine if OID index starts from 0 or 1? */ snprintf(test_OID, sizeof(test_OID), OID_template, base_index); - if (nut_snmp_get(test_OID) == NULL) + if (nut_snmp_get(test_OID) == NULL) { base_index++; + } + else { + if (su_info_p->flags & SU_FLAG_ZEROINVALID) { + long value; + if ((nut_snmp_get_int(test_OID, &value)) && (value==0)) { + base_index++; + } + } + } /* Now, actually iterate */ for (base_count = 0 ; ; base_count++) { @@ -1684,7 +1753,7 @@ bool_t process_template(int mode, const char* type, snmp_info_t *su_info_p) /* FIXME: should we disable it? * su_info_p->flags &= ~SU_FLAG_OK; * or rely on guestimation? */ - template_count = guestimate_template_count(su_info_p->OID); + template_count = guestimate_template_count(su_info_p); /* Publish the count estimation */ if (template_count > 0) dstate_setinfo(template_count_var, "%i", template_count); @@ -1726,7 +1795,7 @@ bool_t process_template(int mode, const char* type, snmp_info_t *su_info_p) { /* Device 1 ("device.0", whole daisychain) needs no * special processing */ - cur_nut_index = cur_template_number + base_nut_template_offset(); + cur_nut_index = cur_template_number; snprintf((char*)cur_info_p.info_type, SU_INFOSIZE, su_info_p->info_type, cur_nut_index); } @@ -1734,7 +1803,7 @@ bool_t process_template(int mode, const char* type, snmp_info_t *su_info_p) else /* Outlet and outlet groups templates */ { /* Get the index of the current template instance */ - cur_nut_index = cur_template_number + base_nut_template_offset(); + cur_nut_index = cur_template_number; /* Special processing for daisychain */ if (daisychain_enabled == TRUE) { @@ -1771,7 +1840,7 @@ bool_t process_template(int mode, const char* type, snmp_info_t *su_info_p) /* Special processing for daisychain */ if (!strncmp(type, "device", 6)) { if (current_device_number > 0) { - snprintf((char *)cur_info_p.OID, SU_INFOSIZE, su_info_p->OID, current_device_number - 1); + snprintf((char *)cur_info_p.OID, SU_INFOSIZE, su_info_p->OID, current_device_number + device_template_offset); } //else // FIXME: daisychain-whole, what to do? @@ -1784,11 +1853,11 @@ bool_t process_template(int mode, const char* type, snmp_info_t *su_info_p) if (daisychain_enabled == TRUE) { if (su_info_p->flags & SU_TYPE_DAISY_1) { snprintf((char *)cur_info_p.OID, SU_INFOSIZE, - su_info_p->OID, current_device_number - 1, cur_template_number); + su_info_p->OID, current_device_number + device_template_offset, cur_template_number); } else { snprintf((char *)cur_info_p.OID, SU_INFOSIZE, - su_info_p->OID, cur_template_number - 1, current_device_number - 1); + su_info_p->OID, cur_template_number + device_template_offset, current_device_number - device_template_offset); } } else { @@ -1829,14 +1898,16 @@ bool_t process_template(int mode, const char* type, snmp_info_t *su_info_p) * Return: SU_OUTLET_GROUP, SU_OUTLET or 0 if not a template */ int get_template_type(const char* varname) { - /* Check if it is outlet / outlet.group */ if (!strncmp(varname, "outlet.group", 12)) { + upsdebugx(4, "outlet.group template"); return SU_OUTLET_GROUP; } else if (!strncmp(varname, "outlet", 6)) { + upsdebugx(4, "outlet template"); return SU_OUTLET; } else if (!strncmp(varname, "device", 6)) { + upsdebugx(4, "device template"); return SU_DAISY; } else { @@ -1957,7 +2028,7 @@ bool_t daisychain_init() * the number of devices present */ else { - devices_count = guestimate_template_count(su_info_p->OID); + devices_count = guestimate_template_count(su_info_p); upsdebugx(1, "Guesstimation: there are %ld device(s) present", devices_count); } @@ -1999,6 +2070,21 @@ bool_t daisychain_init() upsdebugx(1, "No device.count entry found, daisychain support not needed"); } + /* Finally, compute and store the base OID index and NUT offset */ + su_info_p = su_find_info("device.model"); + if (su_info_p != NULL) { + device_template_index_base = base_snmp_template_index(su_info_p); + upsdebugx(1, "%s: device_template_index_base = %i", __func__, device_template_index_base); + device_template_offset = device_template_index_base - 1; + upsdebugx(1, "%s: device_template_offset = %i", __func__, device_template_offset); + } + else { + upsdebugx(1, "%s: No device.model entry found.", __func__); + } + + upsdebugx(1, "%s: daisychain support is %s", __func__, + (daisychain_enabled==TRUE)?"enabled":"disabled"); + return daisychain_enabled; } @@ -2074,7 +2160,7 @@ int process_phase_data(const char* type, long *nb_phases, snmp_info_t *su_info_p * formatting string) that needs to be adapted! */ if (strchr(tmp_info_p->OID, '%') != NULL) { upsdebugx(2, "Found template, need to be adapted"); - snprintf((char*)tmpOID, SU_INFOSIZE, tmp_info_p->OID, current_device_number - 1); + snprintf((char*)tmpOID, SU_INFOSIZE, tmp_info_p->OID, current_device_number + device_template_offset); } else { /* Otherwise, just point at what we found */ @@ -2328,18 +2414,9 @@ bool_t su_ups_get(snmp_info_t *su_info_p) int index = 0; char *format_char = NULL; snmp_info_t *tmp_info_p = NULL; - int daisychain_offset = 0; upsdebugx(2, "%s: %s %s", __func__, su_info_p->info_type, su_info_p->OID); - if (daisychain_enabled == TRUE) { - /* Only apply the "-1" offset for master and slaves! */ - if (current_device_number > 0) - daisychain_offset = -1; - } - else - daisychain_offset = -1; - /* Check if this is a daisychain template */ if ((format_char = strchr(su_info_p->OID, '%')) != NULL) { tmp_info_p = instantiate_info(su_info_p, tmp_info_p); @@ -2347,7 +2424,7 @@ bool_t su_ups_get(snmp_info_t *su_info_p) /* adapt the OID */ if (su_info_p->OID != NULL) { snprintf((char *)tmp_info_p->OID, SU_INFOSIZE, su_info_p->OID, - current_device_number + daisychain_offset); + current_device_number + device_template_offset); } else { free_info(tmp_info_p); @@ -2493,10 +2570,22 @@ bool_t su_ups_get(snmp_info_t *su_info_p) if (su_info_p->info_flags & ST_FLAG_STRING) { status = nut_snmp_get_str(su_info_p->OID, buf, sizeof(buf), su_info_p->oid2info); + if (status == TRUE) { + if (quirk_symmetra_threephase) { + if (!strcasecmp(su_info_p->info_type, "input.transfer.low") + || !strcasecmp(su_info_p->info_type, "input.transfer.high")) { + /* Convert from three phase line-to-line voltage to line-to-neutral voltage */ + double value = atof(buf); + value = value * 0.707; + snprintf(buf, sizeof(buf), "%.2f", value); + } + } + } } else { status = nut_snmp_get_int(su_info_p->OID, &value); if (status == TRUE) { - if (su_info_p->flags&SU_FLAG_NEGINVALID && value<0) { + if ((su_info_p->flags&SU_FLAG_NEGINVALID && value<0) + || (su_info_p->flags&SU_FLAG_ZEROINVALID && value==0)) { su_info_p->flags &= ~SU_FLAG_OK; if(su_info_p->flags&SU_FLAG_UNIQUE) { disable_competition(su_info_p); @@ -2505,10 +2594,6 @@ bool_t su_ups_get(snmp_info_t *su_info_p) free_info(tmp_info_p); return FALSE; } - if (su_info_p->flags & SU_FLAG_SETINT) { - upsdebugx(1, "setvar %s", su_info_p->OID); - *su_info_p->setvar = value; - } /* Check if there is a value to be looked up */ if ((strValue = su_find_infoval(su_info_p->oid2info, value)) != NULL) snprintf(buf, sizeof(buf), "%s", strValue); @@ -2558,7 +2643,6 @@ int su_setOID(int mode, const char *varname, const char *val) /* normal (default), outlet, or outlet group variable */ int vartype = -1; int daisychain_device_number = -1; - int OID_offset = 0; /* Set to "-1" for daisychain devices > 0, 0 otherwise */ /* variable without the potential "device.X" prefix, to find the template */ char *tmp_varname = NULL; char setOID[SU_INFOSIZE]; @@ -2589,7 +2673,6 @@ int su_setOID(int mode, const char *varname, const char *val) } else { daisychain_device_number = 0; - OID_offset = 0; tmp_varname = strdup(varname); } @@ -2655,7 +2738,7 @@ int su_setOID(int mode, const char *varname, const char *val) (strstr(tmp_info_p->dfl, "%i") != NULL)) { su_info_p->dfl = (char *)xmalloc(SU_INFOSIZE); snprintf((char *)su_info_p->dfl, sizeof(su_info_p->dfl), tmp_info_p->dfl, - item_number - base_nut_template_offset()); + item_number); } /* adapt the OID */ if (su_info_p->OID != NULL) { @@ -2673,18 +2756,29 @@ int su_setOID(int mode, const char *varname, const char *val) * so we have to check if the daisychain is enabled, and if * the formatting info for it are in 1rst or 2nd position */ if (daisychain_enabled == TRUE) { + /* Note: daisychain_enabled == TRUE means that we have + * daisychain template. However: + * * when there are multiple devices, offset "-1" applies + * since device.0 is a fake and actual devices start at + * index 1 + * * when there is only 1 device, offset doesn't apply since + * the device index is "0" + */ + int daisychain_offset = 0; + if (devices_count > 1) + daisychain_offset = 1; + if (su_info_p->flags & SU_TYPE_DAISY_1) { snprintf((char *)su_info_p->OID, SU_INFOSIZE, tmp_info_p->OID, - daisychain_device_number + OID_offset, item_number - base_nut_template_offset()); + daisychain_device_number - daisychain_offset, item_number); } else { snprintf((char *)su_info_p->OID, SU_INFOSIZE, tmp_info_p->OID, - item_number - base_nut_template_offset(), daisychain_device_number + OID_offset); + item_number, daisychain_device_number - daisychain_offset); } } else { - snprintf((char *)su_info_p->OID, SU_INFOSIZE, tmp_info_p->OID, - item_number - base_nut_template_offset()); + snprintf((char *)su_info_p->OID, SU_INFOSIZE, tmp_info_p->OID, item_number); } } /* else, don't return STAT_SET_INVALID for mode==SU_MODE_SETVAR since we @@ -2717,22 +2811,43 @@ int su_setOID(int mode, const char *varname, const char *val) } /* set value into the device, using the provided one, or the default one otherwise */ + if (mode==SU_MODE_INSTCMD) { + /* Sanity check: commands should either have a value or a default */ + if ( (val == NULL) && (su_info_p->dfl == NULL) ) { + upsdebugx(1, "%s: cannot execute command '%s': a provided or default value is needed!", __func__, varname); + return STAT_SET_INVALID; + } + } + if (su_info_p->info_flags & ST_FLAG_STRING) { status = nut_snmp_set_str(su_info_p->OID, val ? val : su_info_p->dfl); - } else { + } + else { if (mode==SU_MODE_INSTCMD) { - status = nut_snmp_set_int(su_info_p->OID, val ? atoi(val) : su_info_p->info_len); + if ( !str_to_long(val ? val : su_info_p->dfl, &value, 10) ) { + upsdebugx(1, "%s: cannot execute command '%s': value is not a number!", __func__, varname); + return STAT_SET_INVALID; + } } else { /* non string data may imply a value lookup */ if (su_info_p->oid2info) { - value = su_find_valinfo(su_info_p->oid2info, val); + value = su_find_valinfo(su_info_p->oid2info, val ? val : su_info_p->dfl); } else { /* Convert value and apply multiplier */ - value = atof(val) / su_info_p->info_len; + if ( !str_to_long(val, &value, 10) ) { + upsdebugx(1, "%s: cannot set '%s': value is not a number!", __func__, varname); + return STAT_SET_INVALID; + } + value = (long)((double)value / su_info_p->info_len); } - /* Actually apply the new value */ + } + /* Actually apply the new value */ + if (su_info_p->flags & SU_TYPE_TIME) { + status = nut_snmp_set_time(su_info_p->OID, value); + } + else { status = nut_snmp_set_int(su_info_p->OID, value); } } diff --git a/drivers/snmp-ups.h b/drivers/snmp-ups.h index f14c97ecd2..7948d3855c 100644 --- a/drivers/snmp-ups.h +++ b/drivers/snmp-ups.h @@ -117,18 +117,16 @@ typedef struct { are converted according to the multiplier table */ typedef struct { - const char *info_type; /* INFO_ or CMD_ element */ - int info_flags; /* flags to set in addinfo */ - double info_len; /* length of strings if STR, - * cmd value if CMD, multiplier otherwise. */ - const char *OID; /* SNMP OID or NULL */ - const char *dfl; /* default value */ - unsigned long flags; /* my flags */ - info_lkp_t *oid2info; /* lookup table between OID and NUT values */ - int *setvar; /* variable to set for SU_FLAG_SETINT */ + const char *info_type; /* INFO_ or CMD_ element */ + int info_flags; /* flags to set in addinfo */ + double info_len; /* length of strings if ST_FLAG_STRING, multiplier otherwise. */ + const char *OID; /* SNMP OID or NULL */ + const char *dfl; /* default value */ + unsigned long flags; /* snmp-ups internal flags */ + info_lkp_t *oid2info; /* lookup table between OID and NUT values */ } snmp_info_t; -#define SU_FLAG_OK (1 << 0) /* show element to upsd - internal to snmp driver */ +#define SU_FLAG_OK (1 << 0) /* show element to upsd - internal to snmp driver */ #define SU_FLAG_STATIC (1 << 1) /* retrieve info only once. */ #define SU_FLAG_ABSENT (1 << 2) /* data is absent in the device, * use default value. */ @@ -137,8 +135,9 @@ typedef struct { #define SU_FLAG_UNIQUE (1 << 5) /* There can be only be one * provider of this info, * disable the other providers */ -#define SU_FLAG_SETINT (1 << 6) /* save value */ -#define SU_OUTLET (1 << 7) /* outlet template definition */ +/* Free slot + * #define SU_FLAG_SETINT (1 << 6)*/ /* save value */ +#define SU_OUTLET (1 << 7) /* outlet template definition */ #define SU_CMD_OFFSET (1 << 8) /* Add +1 to the OID index */ /* Notes on outlet templates usage: * - outlet.count MUST exist and MUST be declared before any outlet template @@ -190,6 +189,8 @@ typedef struct { #define SU_TYPE_DAISY_2 (2 << 19) /* Daisychain index is the 2nd specifier */ #define SU_TYPE_DAISY ((t)->flags & (7 << 19)) #define SU_DAISY (2 << 19) /* Daisychain template definition */ +#define SU_FLAG_ZEROINVALID (1 << 20) /* Invalid if "0" value */ +#define SU_FLAG_NAINVALID (1 << 21) /* Invalid if "N/A" value */ #define SU_VAR_COMMUNITY "community" #define SU_VAR_VERSION "snmp_version" diff --git a/drivers/solis.c b/drivers/solis.c index 23218a5a57..12dd91f75a 100644 --- a/drivers/solis.c +++ b/drivers/solis.c @@ -1,6 +1,7 @@ /* solis.c - driver for Microsol Solis UPS hardware - Copyright (C) 2004 Silvino B. Magalhães + Copyright (C) 2004 Silvino B. Magalhães + 2019 Roberto Panerai Velloso This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -23,8 +24,11 @@ 2005/06/30 - Version 0.41 - patch for solaris compability 2005/07/01 - Version 0.50 - add internal e external shutdown programming 2005/08/18 - Version 0.60 - save external shutdown programming to ups, - and support new cables for solis 3 + and support new cables for solis 3 2015/09/19 - Version 0.65 - patch for correct reading for Microsol Back-Ups BZ1200-BR + 2017/12/21 - Version 0.66 - remove memory leaks (unfreed strdup()s); + remove ser_flush_in calls that were causing desync issues; + other minor improvements in source code. (see the version control logs for more recent updates) Microsol contributed with UPS Solis 1.5 HS 1.5 KVA for my tests. @@ -42,13 +46,14 @@ #include "timehead.h" #define DRIVER_NAME "Microsol Solis UPS driver" -#define DRIVER_VERSION "0.65" +#define DRIVER_VERSION "0.67" /* driver description structure */ upsdrv_info_t upsdrv_info = { DRIVER_NAME, DRIVER_VERSION, - "Silvino B. Magalhães ", + "Silvino B. Magalhães " \ + "Roberto Panerai Velloso ", DRV_STABLE, { NULL } }; @@ -105,223 +110,96 @@ upsdrv_info_t upsdrv_info = { #define FMT_DAYS " %d %d %d %d %d %d %d\n" /* convert standard days string to firmware format */ -static char* convdays( char *cop ) -{ +static char* convert_days(char *cop) { + static char alt[8]; - char *stra; - char alt[8]; - int i, ish, fim, iw; - iw = weekn; - if ( iw == 6) + int ish, fim; + if (weekn == 6) ish = 0; else - ish = 1 + iw; + ish = 1 + weekn; fim = 7 - ish; /* rotate left only 7 bits */ - for(i=0; i < fim; i++) { - alt[i] = cop[i+ish]; - } - - if ( ish > 0 ) { + memcpy(alt, &cop[ish], fim); - for(i=0; i < ish; i++) { - alt[i+fim] = cop[i]; - } - } + if (ish > 0) + memcpy(&alt[fim], cop, ish); alt[7] = 0; /* string terminator */ - stra = strdup( alt ); - return stra; + return alt; } -static int IsBinary(char ch ) -{ - if( ch == '1' || ch == '0' ) - return 1; - else - return 0; +inline static int is_binary(char ch ) { + return ( ch == '1' || ch == '0' ); } /* convert string to binary */ -static int Binary( char *nome ) -{ - - char ch, cc; - int cont=0, nint = 1, tobin=0; - int ex, nbin; +static int str2bin( char *binStr ) { + int result = 0; + int i; - while( *nome && ( cont < 7 ) ) { - ch = *nome; - if( !(IsBinary( ch ) ) ) - nint = 0; + for (i = 0; i < 7; ++i) { + char ch = binStr[i]; + if (is_binary(ch)) + result += ( (ch - '0') << (6 - i) ); else - { - if( ch == '1') { - cc = 1; - ex = (6 - cont); - nbin = cc<> (5 - weekn - i)) & 0x01; + + for (i = 0; i < weekn+1; ++i) + alt[i+(6-weekn)] = (dweek >> (6 - i)) & 0x01; - for(i=0; i < 7; i++) { - if( alt[i] == 0 ) - alt[i] = '0'; - if( alt[i] == 1 ) - alt[i] = '1'; - } + for (i=0; i < 7; i++) + alt[i] += '0'; alt[7] = 0; /* string terminator */ - keewd = Binary ( alt ); - - return keewd; + return str2bin(alt); } -static int IsHour( char *strx, int qual ) -{ - - int hora=0, min = 0; +static int is_hour(char *hour, int qual) { + int hora, min; - if ((strlen(strx) != 5) || (sscanf(strx, "%d:%d", &hora, &min) != 2)) { + if ((strlen(hour) != 5) || + (sscanf(hour, "%d:%d", &hora, &min) != 2)) return -1; - } - if( qual ) { + if (qual) { dhour = hora; dmin = min; - } - else - { + } else { lhour = hora; lmin = min; } return 1; - } - -static void sendshut( void ) -{ - +static void send_shutdown( void ) { int i; - for(i=0; i < 10; i++) + for (i = 0; i < 10; i++) ser_send_char(upsfd, CMD_SHUT ); upslogx(LOG_NOTICE, "Ups shutdown command sent"); printf("Ups shutdown command sent\n"); - } /* save config ups */ -static void confups( void ) -{ - +static void save_ups_config( void ) { int i, chks = 0; ConfigPack[0] = 0xCF; @@ -341,91 +219,60 @@ static void confups( void ) /* MSB zero */ ConfigPack[10] = ConfigPack[10] & (~(0x80)); - for(i=0; i < 11; i++) - chks = chks + ConfigPack[i]; + for (i=0; i < 11; i++) + chks += ConfigPack[i]; ConfigPack[11] = chks % 256; - for(i=0; i < 12; i++) - ser_send_char(upsfd, ConfigPack[i] ); - + for (i=0; i < 12; i++) + ser_send_char(upsfd, ConfigPack[i]); } /* print UPS internal variables */ -static void prnInfo( void ) -{ - - int sunday=0, monday=0, tuesday=0, wednesday=0, thursday=0, friday=0, saturday=0; - unsigned char dweek; - - printf( UPS_DATE, Year, Month, Day ); - printf( SYS_DATE, anon, mesn, dian, seman ); +static void print_info( void ) { + printf(UPS_DATE, Year, Month, Day); + printf(SYS_DATE, anon, mesn, dian, seman); + printf(UPS_TIME, ihour, imin, isec); - printf( UPS_TIME, ihour, imin, isec); - - dweek = DaysStd; - - if( prgups > 0 ) { + if (prgups > 0) { + /*sunday, monday, tuesday, wednesday, thursday, friday, saturday*/ + int week_days[7] = {0, 0, 0, 0, 0, 0, 0}; + int i; /* this is the string to binary standard */ - sunday = ( ( dweek & 0x40 ) == 0x40 ); - monday = ( ( dweek & 0x20 ) == 0x20 ); - tuesday = ( ( dweek & 0x10 ) == 0x10 ); - wednesday = ( ( dweek & 0x08 ) == 0x08 ); - thursday = ( ( dweek & 0x04 ) == 0x04 ); - friday = ( ( dweek & 0x02 ) == 0x02 ); - saturday = ( ( dweek & 0x01 ) == 0x01 ); - - if( prgups == 3) - printf( PRG_ONOU ); - else - printf( PRG_ONON ); - printf( TIME_ON, lhour, lmin); - printf( TIME_OFF, dhour, dmin); - printf( PRG_DAYS ); - printf( FMT_DAYS, sunday, monday, tuesday, wednesday, thursday, friday, saturday); - } - else - printf( PRG_ONOF ); + for (i = 0; i < 7; ++i) + week_days[i] = (DaysStd >> (6 - i)) & 0x01; + if (prgups == 3) + printf(PRG_ONOU); + else + printf(PRG_ONON); + + printf(TIME_ON, lhour, lmin); + printf(TIME_OFF, dhour, dmin); + printf(PRG_DAYS); + printf(FMT_DAYS, + week_days[0], week_days[1], week_days[2], + week_days[3], week_days[4], week_days[5], + week_days[6]); + } else + printf(PRG_ONOF); } /* is today shutdown day ? */ -static int IsToday( unsigned char dweek, int nweek) -{ - - switch ( nweek ) - { - case 0: /* sunday */ - return ( ( ( dweek & 0x40 ) == 0x40 ) ); - case 1: - return ( ( ( dweek & 0x20 ) == 0x20 ) ); - case 2: - return ( ( ( dweek & 0x10 ) == 0x10 ) ); - case 3: - return ( ( ( dweek & 0x08 ) == 0x08 ) ); - case 4: - return ( ( ( dweek & 0x04 ) == 0x04 ) ); - case 5: - return ( ( ( dweek & 0x02 ) == 0x02 ) ); - case 6: /* saturday */ - return ( ( ( dweek & 0x01 ) == 0x01 ) ); - } - - return 0; - +inline static int is_today( unsigned char dweek, int nweek) { + return (dweek >> (6 - nweek)) & 0x01; } -static void AutonomyCalc( int iauto ) /* all models */ -{ - - int indice, indd, lim, min, max, inf, sup, indc, bx, ipo =0; +/* all models */ +static void autonomy_calc( int iauto ) { + int indice, indd, lim, min, max, inf, sup, indc, bx, ipo = 0; bx = bext[iauto]; indice = RecPack[3]; indd = indice - 139; - if( UtilPower > 20 ) - ipo = ( UtilPower - 51 ) / 100; + if (UtilPower > 20) + ipo = (UtilPower - 51) / 100; indc = auton[iauto].maxi; @@ -438,42 +285,38 @@ static void AutonomyCalc( int iauto ) /* all models */ lim = max - 139; sup = max + 1; - if( UtilPower <= 20 ) { + if (UtilPower <= 20) { Autonomy = 170; - maxauto = 170; - } - else - { + maxauto = 170; + } else { maxauto = auton[iauto].mm[ipo][lim]; - if( indice > inf && indice < sup ) { + if( indice > inf && indice < sup ) Autonomy = auton[iauto].mm[ipo][indd]; - } - else - { - if( indice > max ) Autonomy = maxauto; - if( indice < min ) Autonomy = 0; + else { + if (indice > max) + Autonomy = maxauto; + if (indice < min) + Autonomy = 0; } } - if( BattExtension > 0 && iauto < 4 ) + if (BattExtension > 0 && iauto < 4) Autonomy = ( Autonomy * ( BattExtension + bx ) * 1.0 / bx ); - } -static void ScanReceivePack( void ) -{ - int aux, im, ov = 0; +static void scan_received_pack(void) { + int aux, im, ov; /* model independent data */ - Year = ( RecPack[ 19 ] & 0x0F ) + BASE_YEAR; - Month = ( RecPack[ 19 ] & 0xF0 ) >> 4; - Day = ( RecPack[ 18 ] & 0x1F ); + Year = (RecPack[ 19 ] & 0x0F) + BASE_YEAR; + Month = (RecPack[ 19 ] & 0xF0) >> 4; + Day = (RecPack[ 18 ] & 0x1F); DaysOnWeek = RecPack[17]; /* Days of week if in UPS shutdown programming mode */ - if( prgups == 3 ) { - DaysStd = revertdays( DaysOnWeek ); + if (prgups == 3) { + DaysStd = revert_days( DaysOnWeek ); /* time for programming UPS off */ dhour = RecPack[15]; @@ -488,21 +331,23 @@ static void ScanReceivePack( void ) imin = RecPack[10]; isec = RecPack[9]; - if( ( ( 0x01 & RecPack[ 20 ] ) == 0x01 ) ) + if ((0x01 & RecPack[20]) == 0x01) Out220 = 1; - CriticBatt = ( ( 0x04 & RecPack[ 20 ] ) == 0x04 ); - InversorOn = ( ( 0x08 & RecPack[ 20 ] ) == 0x08 ); - SuperHeat = ( ( 0x10 & RecPack[ 20 ] ) == 0x10 ); - SourceFail = ( ( 0x20 & RecPack[ 20 ] ) == 0x20 ); - OverCharge = ( ( 0x80 & RecPack[ 20 ] ) == 0x80 ); - - if( ( ( 0x40 & RecPack[ 20 ] ) == 0x40 ) ) + + CriticBatt = (0x04 & RecPack[20]) == 0x04; + InversorOn = (0x08 & RecPack[20]) == 0x08; + SuperHeat = (0x10 & RecPack[20]) == 0x10; + SourceFail = (0x20 & RecPack[20]) == 0x20; + OverCharge = (0x80 & RecPack[20]) == 0x80; + + if ((0x40 & RecPack[20]) == 0x40) InputValue = 1; else InputValue = 0; - Temperature = ( 0x7F & RecPack[ 4 ]); - if( ( ( 0x80 & RecPack[ 4 ] ) == 0x80 ) ) - Temperature = Temperature - 128; + + Temperature = 0x7F & RecPack[4]; + if (0x80 & RecPack[4]) + Temperature -= 128; /* model dependent data */ @@ -510,36 +355,29 @@ static void ScanReceivePack( void ) ov = Out220; if (SolisModel != 16) { - - if( RecPack[ 6 ] >= 194 ) - InVoltage = RecPack[ 6 ] * ctab[imodel].m_involt194[0] + ctab[imodel].m_involt194[1]; + if (RecPack[6] >= 194) + InVoltage = RecPack[6] * ctab[imodel].m_involt194[0] + ctab[imodel].m_involt194[1]; else - InVoltage = RecPack[ 6 ] * ctab[imodel].m_involt193[0] + ctab[imodel].m_involt193[1]; + InVoltage = RecPack[6] * ctab[imodel].m_involt193[0] + ctab[imodel].m_involt193[1]; } else { /* Code InVoltage for STAY1200_USB */ - - if ((RecPack[20] & 0x1) == 0) { //IsOutVoltage 220 - + if ((RecPack[20] & 0x1) == 0) // IsOutVoltage 220 InVoltage = RecPack[2] * ctab[imodel].m_involt193[0] + ctab[imodel].m_involt193[1]; - } else { - + else InVoltage = RecPack[2] * ctab[imodel].m_involt193[0] + ctab[imodel].m_involt193[1] - 3.0; - } } BattVoltage = RecPack[ 3 ] * ctab[imodel].m_battvolt[0] + ctab[imodel].m_battvolt[1]; NominalPower = nompow[im]; - if( SourceFail ) { + if (SourceFail) { OutVoltage = RecPack[ 1 ] * ctab[imodel].m_outvolt_i[ov][0] + ctab[imodel].m_outvolt_i[ov][1]; OutCurrent = RecPack[ 5 ] * ctab[imodel].m_outcurr_i[ov][0] + ctab[imodel].m_outcurr_i[ov][1]; AppPower = ( RecPack[ 5 ] * RecPack[ 1 ] ) * ctab[imodel].m_appp_i[ov][0] + ctab[imodel].m_appp_i[ov][1]; UtilPower = ( RecPack[ 7 ] + RecPack[ 8 ] * 256 ) * ctab[imodel].m_utilp_i[ov][0] + ctab[imodel].m_utilp_i[ov][1]; InCurrent = 0; - } - else - { + } else { OutVoltage = RecPack[ 1 ] * ctab[imodel].m_outvolt_s[ov][0] + ctab[imodel].m_outvolt_s[ov][1]; OutCurrent = RecPack[ 5 ] * ctab[imodel].m_outcurr_s[ov][0] + ctab[imodel].m_outcurr_s[ov][1]; AppPower = ( RecPack[ 5 ] * RecPack[ 1 ] ) * ctab[imodel].m_appp_s[ov][0] + ctab[imodel].m_appp_s[ov][1]; @@ -547,102 +385,90 @@ static void ScanReceivePack( void ) InCurrent = ( ctab[imodel].m_incurr[0] * 1.0 / BattVoltage ) - ( AppPower * 1.0 / ctab[imodel].m_incurr[1] ) + OutCurrent *( OutVoltage * 1.0 / InVoltage ); } - if (SolisModel == 16) { - - int configRelay = (RecPack[6] & 0x38) >> 3; - double TENSAO_SAIDA_F1_MR[8] = { 1.1549, 1.0925, 0.0, 0.0, 1.0929, 1.0885, 0.0, 0.8654262224145391 }; - double TENSAO_SAIDA_F2_MR[8] = { -6.9157, 11.026, 10.43, 0.0, -0.6109, 12.18, 0.0, 13.677}; + + if (SolisModel == 16) { + int configRelay = (RecPack[6] & 0x38) >> 3; + double TENSAO_SAIDA_F1_MR[8] = { 1.1549, 1.0925, 0.0, 0.0, 1.0929, 1.0885, 0.0, 0.8654262224145391 }; + double TENSAO_SAIDA_F2_MR[8] = { -6.9157, 11.026, 10.43, 0.0, -0.6109, 12.18, 0.0, 13.677}; - const double TENSAO_SAIDA_F2_MI[8] ={ 5.59, 9.47, 13.7, 0.0, 0.0, 0.0, 0.0, 0.0 }; - const double TENSAO_SAIDA_F1_MI[8] = { 7.9, 9.1, 17.6, 0.0, 0.0, 0.0, 0.0, 0.0 }; - - const double corrente_saida_F1_MR = 0.12970000389100012; - const double corrente_saida_F2_MR = 0.5387060281204546; - /* double corrente_saida_F1_MI = 0.1372; - double corrente_saida_F2_MI = 0.3456; */ - - if (SourceFail) { - if (RecPack[20] == 0) { - double a = RecPack[1] * 2; - a /= 128.0; - // a = double sqrt(a); - OutVoltage = RecPack[1] * a * TENSAO_SAIDA_F1_MI[configRelay] + TENSAO_SAIDA_F2_MI[configRelay]; - - } - - } else { - - - OutCurrent = (float)(corrente_saida_F1_MR * RecPack[5] + corrente_saida_F2_MR); - OutVoltage = RecPack[1] * TENSAO_SAIDA_F1_MR[configRelay] + TENSAO_SAIDA_F2_MR[configRelay]; - AppPower = OutCurrent * OutVoltage; - - - - double RealPower = (RecPack[7] + RecPack[8] * 256); - - double potVA1 = 5.968 * AppPower - 284.36; - double potVA2 = 7.149 * AppPower - 567.18; - double potLin = 0.1664 * RealPower + 49.182; - double potRe = 0.1519 * RealPower + 32.644; - if (fabs(potVA1 - RealPower) < fabs(potVA2 - RealPower)) { - RealPower = potLin; - } else { - RealPower = potRe; - - } - if (OutCurrent < 0.7) { - RealPower = AppPower; - } - if (AppPower < RealPower) { - double f = AppPower; - AppPower = RealPower; - RealPower = f; - } + const double TENSAO_SAIDA_F2_MI[8] ={ 5.59, 9.47, 13.7, 0.0, 0.0, 0.0, 0.0, 0.0 }; + const double TENSAO_SAIDA_F1_MI[8] = { 7.9, 9.1, 17.6, 0.0, 0.0, 0.0, 0.0, 0.0 }; + const double corrente_saida_F1_MR = 0.12970000389100012; + const double corrente_saida_F2_MR = 0.5387060281204546; + /* double corrente_saida_F1_MI = 0.1372; + double corrente_saida_F2_MI = 0.3456; */ + if (SourceFail) { + if (RecPack[20] == 0) { + double a = RecPack[1] * 2; + a /= 128.0; + // a = double sqrt(a); + OutVoltage = RecPack[1] * a * TENSAO_SAIDA_F1_MI[configRelay] + TENSAO_SAIDA_F2_MI[configRelay]; } + } else { + OutCurrent = (float)(corrente_saida_F1_MR * RecPack[5] + corrente_saida_F2_MR); + OutVoltage = RecPack[1] * TENSAO_SAIDA_F1_MR[configRelay] + TENSAO_SAIDA_F2_MR[configRelay]; + AppPower = OutCurrent * OutVoltage; + + double RealPower = (RecPack[7] + RecPack[8] * 256); + + double potVA1 = 5.968 * AppPower - 284.36; + double potVA2 = 7.149 * AppPower - 567.18; + double potLin = 0.1664 * RealPower + 49.182; + double potRe = 0.1519 * RealPower + 32.644; + if (fabs(potVA1 - RealPower) < fabs(potVA2 - RealPower)) + RealPower = potLin; + else + RealPower = potRe; + + if (OutCurrent < 0.7) + RealPower = AppPower; + + if (AppPower < RealPower) { + double f = AppPower; + AppPower = RealPower; + RealPower = f; + } } + } - aux = ( RecPack[ 21 ] + RecPack[ 22 ] * 256 ); - if( aux > 0 ) + aux = (RecPack[ 21 ] + RecPack[ 22 ] * 256); + if (aux > 0) InFreq = ctab[imodel].m_infreq * 1.0 / aux; /* Specific for STAY1200_USB */ - if (SolisModel == 16) { - InFreq = ((float)(0.37 * (257 - (aux >> 8)))); - } - else + if (SolisModel == 16) { + InFreq = ((float)(0.37 * (257 - (aux >> 8)))); + } else InFreq = 0; /* input voltage offset */ - if( InVoltage < InVolt_offset ) { /* all is equal 30 */ + if (InVoltage < InVolt_offset) { /* all is equal 30 */ InFreq = 0; InVoltage = 0; InCurrent = 0; } /* app power offset */ - if( AppPower < ctab[imodel].m_appp_offset ) { + if (AppPower < ctab[imodel].m_appp_offset) { AppPower = 0; UtilPower = 0; ChargePowerFactor = 0; OutCurrent = 0; } - if( im < 3 ) - AutonomyCalc( im ); - else - { - if( BattExtension == 80 ) - AutonomyCalc( im + 1 ); + if (im < 3) + autonomy_calc(im); + else { + if (BattExtension == 80 && im == 3) + autonomy_calc(im + 1); else - AutonomyCalc( im ); + autonomy_calc(im); } /* model independent data */ - batcharge = ( Autonomy / maxauto ) * 100.0; upscharge = ( AppPower / NominalPower ) * 100.0; @@ -650,45 +476,45 @@ static void ScanReceivePack( void ) batcharge = 100.0; OutFreq = 60; - if( !( InversorOn ) ) { + if (!InversorOn) { OutVoltage = 0; OutFreq = 0; } - if( ( !( SourceFail ) && InversorOn ) ) + if (!SourceFail && InversorOn) OutFreq = InFreq; - if( AppPower <= 0 ) /* charge pf */ + if (AppPower <= 0) /* charge pf */ ChargePowerFactor = 0; - else - { + else { if( AppPower == 0 ) ChargePowerFactor = 100; else - ChargePowerFactor = (( UtilPower / AppPower) * 100 ); - if( ChargePowerFactor > 100 ) + ChargePowerFactor = (( UtilPower / AppPower) * 100); + + if(ChargePowerFactor > 100) ChargePowerFactor = 100; } - if( SourceFail && SourceLast ) /* first time failure */ + if (SourceFail && SourceLast) /* first time failure */ FailureFlag = true; /* source return */ - if( !( SourceFail ) && !( SourceLast ) ) { + if (!SourceFail && !SourceLast) { SourceReturn = true; - ser_flush_in(upsfd,"",0); /* clean port */ + //ser_flush_in(upsfd,"",0); /* clean port */ } - if( !( SourceFail ) == SourceLast ) { + if((!SourceFail) == SourceLast) { SourceReturn = false; FailureFlag = false; } - SourceLast = !( SourceFail ); + SourceLast = !SourceFail; /* Autonomy */ - if( Autonomy < 5 ) + if (Autonomy < 5) LowBatt = true; else LowBatt = false; @@ -696,338 +522,288 @@ static void ScanReceivePack( void ) UpsPowerFactor = 700; /* input 110V or 220v */ - if( InputValue == 0 ) { + if (InputValue == 0) { InDownLim = 75; InUpLim = 150; NomInVolt = 110; - } - else - { + } else { InDownLim = 150; InUpLim = 300; NomInVolt = 220; } /* output volage 220V or 110V */ - if( Out220 ) { + if (Out220) { OutDownLim = 190; OutUpLim = 250; NomOutVolt = 220; - } - else - { + } else { OutDownLim = 100; OutUpLim = 140; NomOutVolt = 110; } - if( SourceFail ) /* source status */ + if (SourceFail) /* source status */ InputStatus = 2; else InputStatus = 1; - if( InversorOn ) /* output status */ + if (InversorOn) /* output status */ OutputStatus = 1; else OutputStatus = 2; - if( OverCharge ) + if (OverCharge) OutputStatus = 3; - if( CriticBatt ) /* battery status */ + if (CriticBatt) /* battery status */ BattStatus = 4; else BattStatus = 1; SourceEvents = 0; - if( FailureFlag ) + if (FailureFlag) SourceEvents = 1; - if( SourceReturn ) + if (SourceReturn) SourceEvents = 2; /* verify Inversor */ - if( Flag_inversor ) { + if (Flag_inversor) { InversorOnLast = InversorOn; Flag_inversor = false; } OutputEvents = 0; - if( InversorOn && !( InversorOnLast ) ) + if (InversorOn && !InversorOnLast) OutputEvents = 26; - if( InversorOnLast && !( InversorOn ) ) + if (InversorOnLast && !InversorOn) OutputEvents = 27; InversorOnLast = InversorOn; - if( SuperHeat && !( SuperHeatLast ) ) + + if (SuperHeat && !SuperHeatLast) OutputEvents = 12; - if( SuperHeatLast && !( SuperHeat ) ) + if (SuperHeatLast && !SuperHeat) OutputEvents = 13; SuperHeatLast = SuperHeat; - if( OverCharge && !( OverChargeLast ) ) + + if (OverCharge && !OverChargeLast) OutputEvents = 10; - if( OverChargeLast && !( OverCharge ) ) + if (OverChargeLast && !OverCharge) OutputEvents = 11; OverChargeLast = OverCharge; BattEvents = 0; CriticBattLast = CriticBatt; - } -static void -CommReceive(const char *bufptr, int size) -{ +static void comm_receive(const unsigned char *bufptr, int size) { + if (size == packet_size) { + int CheckSum = 0, i; - int i, CheckSum, i_end; - - if( size == 25 ) { - i_end = 25; - for( i = 0 ; i < i_end ; ++i ) { - RecPack[i] = *bufptr; - bufptr++; - } - if(nut_debug_level >= 3) { - upsdebug_hex(3, "CommReceive: RecPack", RecPack, size); - } + memcpy(RecPack, bufptr, packet_size); + + if (nut_debug_level >= 3) + upsdebug_hex(3, "comm_receive: RecPack", RecPack, size); /* CheckSum verify */ - CheckSum = 0; - i_end = 23; - for( i = 0 ; i < i_end ; ++i ) - CheckSum = RecPack[ i ] + CheckSum; + for (i = 0 ; i < packet_size-2 ; ++i ) + CheckSum += RecPack[i]; CheckSum = CheckSum % 256; upsdebugx(4, "%s: calculated checksum = 0x%02x, RecPack[23] = 0x%02x", __func__, CheckSum, RecPack[23]); - ser_flush_in(upsfd,"",0); /* clean port */ - - /* RecPack[0] identify the model number below. - * SOLIS = 1; - RHINO = 2; - STAY = 3; - SOLIS_LI_700 = 169; - SOLIS_M11 = 171; - SOLIS_M15 = 175; - SOLIS_M14 = 174; - SOLIS_M13 = 173; - SOLISDC_M14 = 201; - SOLISDC_M13 = 206; - SOLISDC_M15 = 207; - CABECALHO_RHINO = 194; - PS800 = 185; - STAY1200_USB = 186; - PS350_CII = 184; - PS2200 = 187; - PS2200_22 = 188; - STAY700_USB = 189; - BZ1500 = 190; + //ser_flush_in(upsfd,"",0); /* clean port */ + + /* RecPack[0] == model number below: + * SOLIS = 1; + * RHINO = 2; + * STAY = 3; + * SOLIS_LI_700 = 169; + * SOLIS_M11 = 171; + * SOLIS_M15 = 175; + * SOLIS_M14 = 174; + * SOLIS_M13 = 173; + * SOLISDC_M14 = 201; + * SOLISDC_M13 = 206; + * SOLISDC_M15 = 207; + * CABECALHO_RHINO = 194; + * PS800 = 185; + * STAY1200_USB = 186; + * PS350_CII = 184; + * PS2200 = 187; + * PS2200_22 = 188; + * STAY700_USB = 189; + * BZ1500 = 190; */ - if( ( ( (RecPack[0] & 0xF0) == 0xA0 ) || (RecPack[0] & 0xF0) == 0xB0) - && ( RecPack[ 24 ] == 254 ) - && ( RecPack[ 23 ] == CheckSum ) ) { - - if(!(detected)) { + + if ((((RecPack[0] & 0xF0) == 0xA0 ) || (RecPack[0] & 0xF0) == 0xB0) && + (RecPack[24] == 254) && + (RecPack[23] == CheckSum)) { - if (RecPack[0] == 186) { + if (!detected) { + if (RecPack[0] == 186) SolisModel = 16; - } else { + else SolisModel = (int) (RecPack[0] & 0x0F); - } - if( SolisModel < 13 ) + + if (SolisModel < 13) imodel = SolisModel - 10; /* 10 = 0, 11 = 1 */ else imodel = SolisModel - 11; /* 13 = 2, 14 = 3, 15 = 4 */ detected = true; - } - switch( SolisModel ) - { - case 10: - case 11: - case 12: - case 13: - case 14: - case 15: - { - ScanReceivePack(); - break; - } - case 16: // STAY1200_USB model - { - ScanReceivePack(); - break; - } - default: - { - printf( M_UNKN ); - ScanReceivePack(); // Scan anyway. - break; - } + switch (SolisModel) { + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + scan_received_pack(); + break; + case 16: // STAY1200_USB model + scan_received_pack(); + break; + default: + printf(M_UNKN); + scan_received_pack(); // Scan anyway. + break; } } } } -static void getbaseinfo(void) -{ - unsigned char tmp; +static void get_base_info(void) { #ifdef PORTUGUESE - const char diassemana[7][4]={"Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sab"}; + const char DaysOfWeek[7][4]={"Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sab"}; #else const char DaysOfWeek[7][4]={"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; #endif - char *str1, *str2, *str3, *str4, *strx; - unsigned char Pacote[25]; - int i, i1=0, i2=0, tam; - const int tpac=25; + unsigned char packet[packet_size], syncEOR; + int i1=0, i2=0, tam, i; time_t tmt; struct tm *now; - time( &tmt ); - now = localtime( &tmt ); + time(&tmt); + now = localtime(&tmt); dian = now->tm_mday; mesn = now->tm_mon+1; anon = now->tm_year+1900; ihour = now->tm_hour; imin = now->tm_min; isec = now->tm_sec; - weekn = now->tm_wday; + weekn = now->tm_wday; -#ifdef PORTUGUESE - strcpy( seman, diassemana[weekn] ); -#else - strcpy( seman, DaysOfWeek[weekn] ); -#endif + strcpy(seman, DaysOfWeek[weekn]); - if( testvar("battext")) + if (testvar("battext")) BattExtension = atoi(getval("battext")); - if( testvar("prgshut")) + if (testvar("prgshut")) prgups = atoi(getval("prgshut")); - if( prgups > 0 && prgups < 3 ) { - if( testvar("daysweek") ) { - strx = getval("daysweek"); - str1 = convdays( strx ); - DaysOnWeek = Binary( str1 ); - } + if (prgups > 0 && prgups < 3) { + if (testvar("daysweek")) + DaysOnWeek = str2bin(convert_days(getval("daysweek"))); - if( testvar("daysoff") ) { - strx = getval("daysoff"); - str2 = convdays( strx ); - DaysStd = Binary ( strx ); - DaysOffWeek = Binary( str2 ); + if (testvar("daysoff")) { + char *doff = getval("daysoff"); + DaysStd = str2bin(doff); + DaysOffWeek = str2bin( convert_days(doff)); } - if( testvar("houron") ) { - str3 = getval("houron"); - i1 = IsHour( str3, 0 ); - } + if (testvar("houron")) + i1 = is_hour(getval("houron"), 0); - if( testvar("houroff") ) { - str4 = getval("houroff"); - i2 = IsHour( str4, 1 ); - } + if (testvar("houroff")) + i2 = is_hour(getval("houroff"), 1); - if( i1 == 1 && i2 == 1 && ( DaysOnWeek > 0 ) ) { + if (i1 == 1 && i2 == 1 && (DaysOnWeek > 0)) { isprogram = 1; /* prgups == 1 ou 2 */ - if( prgups == 2 ) - confups(); /* save ups config */ - } - else - { - if( (i2 == 1) && ( DaysOffWeek > 0 ) ) { + if (prgups == 2) + save_ups_config(); /* save ups config */ + } else { + if (i2 == 1 && DaysOffWeek > 0) { isprogram = 1; - if( DaysOnWeek != DaysOffWeek ) - DaysOnWeek = DaysOffWeek; + if (DaysOnWeek != DaysOffWeek) + DaysOnWeek = DaysOffWeek; + } } - } - } /* end prgups 1 - 2 */ /* dummy read attempt to sync - throw it out */ upsdebugx(3, "%s: sending CMD_UPSCONT and ENDCHAR to sync", __func__); ser_send(upsfd, "%c%c", CMD_UPSCONT, ENDCHAR); - /* Read until end-of-response character (0xFE): */ - for(i=0; i 0 && nut_debug_level >= 4) { - upsdebug_hex(4, "received from ser_get_buf_len()", Pacote, tam); + if (tam > 0 && nut_debug_level >= 4) { + upsdebug_hex(4, "received from ser_get_buf_len()", packet, tam); } - CommReceive((char *)Pacote, tam); + comm_receive(packet, tam); } - if( (!detected) ) { + if (!detected) fatalx(EXIT_FAILURE, NO_SOLIS ); - } - switch( SolisModel ) - { + switch (SolisModel) { case 10: - case 11: case 12: - { Model = "Solis 1.0"; break; - } case 13: - { Model = "Solis 1.5"; break; - } case 14: - { Model = "Solis 2.0"; break; - } case 15: - { Model = "Solis 3.0"; break; - } case 16: Model = "Microsol Back-Ups BZ1200-BR"; break; } /* if( isprogram ) */ - if( prgups == 1 ) { + if (prgups == 1) { hourshut = dhour; minshut = dmin; - } - else - { - if( prgups == 2 || prgups == 3 ) { /* broadcast before firmware shutdown */ - if( dmin < 5 ) { - if( dhour > 1 ) + } else { + if (prgups == 2 || prgups == 3) { /* broadcast before firmware shutdown */ + if (dmin < 5) { + if (dhour > 1) hourshut = dhour - 1; else hourshut = 23; + minshut = 60 - ( 5 - dmin ); + } else { + hourshut = dhour; + minshut = dmin - 5; } - else - { - hourshut = dhour; - minshut = dmin - 5; } - } } - /* manufacturer */ dstate_setinfo("ups.mfr", "%s", "Microsol"); @@ -1040,91 +816,83 @@ static void getbaseinfo(void) printf("Detected %s on %s\n", dstate_getinfo("ups.model"), device_path); - prnInfo(); + print_info(); } -static void getupdateinfo(void) -{ - unsigned char temp[256]; +static void get_update_info(void) { + unsigned char temp[256]; int tam, isday, hourn, minn; /* time update and programable shutdown block */ time_t tmt; struct tm *now; - time( &tmt ); - now = localtime( &tmt ); + time(&tmt); + now = localtime(&tmt); hourn = now->tm_hour; minn = now->tm_min; - weekn = now->tm_wday; + weekn = now->tm_wday; - if( isprogram || prgups == 3 ) { - if( isprogram ) - isday = IsToday( DaysStd, weekn ); + if (isprogram || prgups == 3) { + if (isprogram) + isday = is_today(DaysStd, weekn); else - isday = IsToday( DaysStd, weekn ); + isday = is_today( DaysStd, weekn); - if( isday ) - printf( TODAY_DD, hourshut, minshut ); + if (isday) + printf(TODAY_DD, hourshut, minshut); - if( ( hourn == hourshut ) && ( minn >= minshut ) && isday ) { + if ( + (hourn == hourshut) && + (minn >= minshut) && + isday) { + printf( SHUT_NOW ); progshut = 1; } } - /* programable shutdown end block */ - pacsize = 25; - /* get update package */ temp[0] = 0; /* flush temp buffer */ - upsdebugx(3, "%s: requesting %d bytes from ser_get_buf_len()", __func__, pacsize); - tam = ser_get_buf_len(upsfd, temp, pacsize, 3, 0); + upsdebugx(3, "%s: requesting %d bytes from ser_get_buf_len()", __func__, packet_size); + tam = ser_get_buf_len(upsfd, temp, packet_size, 3, 0); upsdebugx(2, "%s: received %d bytes from ser_get_buf_len()", __func__, tam); - if(tam > 0 && nut_debug_level >= 4) { + if(tam > 0 && nut_debug_level >= 4) upsdebug_hex(4, "received from ser_get_buf_len()", temp, tam); - } - - CommReceive((char *)temp, tam); + comm_receive(temp, tam); } -static int instcmd(const char *cmdname, const char *extra) -{ - - if (!strcasecmp(cmdname, "shutdown.return")) { +static int instcmd(const char *cmdname, const char *extra) { + if (!strcasecmp(cmdname, "shutdown.return")) { /* shutdown and restart */ ser_send_char(upsfd, CMD_SHUTRET); /* 0xDE */ /* ser_send_char(upsfd, ENDCHAR); */ return STAT_INSTCMD_HANDLED; } - if (!strcasecmp(cmdname, "shutdown.stayoff")) - { + if (!strcasecmp(cmdname, "shutdown.stayoff")) { /* shutdown now (one way) */ ser_send_char(upsfd, CMD_SHUT); /* 0xDD */ /* ser_send_char(upsfd, ENDCHAR); */ return STAT_INSTCMD_HANDLED; - } + } upslogx(LOG_NOTICE, "instcmd: unknown command [%s]", cmdname); return STAT_INSTCMD_UNKNOWN; } -void upsdrv_initinfo(void) -{ - getbaseinfo(); +void upsdrv_initinfo(void) { + get_base_info(); upsh.instcmd = instcmd; } -void upsdrv_updateinfo(void) -{ - - getupdateinfo(); /* new package for updates */ +void upsdrv_updateinfo(void) { + get_update_info(); /* new package for updates */ dstate_setinfo("output.voltage", "%03.1f", OutVoltage); dstate_setinfo("input.voltage", "%03.1f", InVoltage); @@ -1133,17 +901,17 @@ void upsdrv_updateinfo(void) dstate_setinfo("output.current", "%03.1f", OutCurrent); status_init(); - if (!SourceFail ) + if (!SourceFail) status_set("OL"); /* on line */ else status_set("OB"); /* on battery */ - if (Autonomy < 5 ) + if (Autonomy < 5) status_set("LB"); /* low battery */ - if( progshut ) { /* software programable shutdown immediately */ + if (progshut) { /* software programable shutdown immediately */ if( prgups == 2 ) - sendshut(); /* Ups shutdown in 4-5 minutes -- redundant Ups shutdown */ + send_shutdown(); /* Ups shutdown in 4-5 minutes -- redundant Ups shutdown */ status_set("LB"); /* no low battery but is a force shutdown */ } @@ -1155,7 +923,6 @@ void upsdrv_updateinfo(void) dstate_setinfo("ups.load", "%03.1f", upscharge); dstate_dataok(); - } /*! @brief Power down the attached load immediately. @@ -1163,26 +930,17 @@ void upsdrv_updateinfo(void) * - on battery: send normal shutdown, UPS will return by itself on utility * - on line: send shutdown+return, UPS will cycle and return soon. */ -void upsdrv_shutdown(void) -{ - - +void upsdrv_shutdown(void) { if (!SourceFail) { /* on line */ - upslogx(LOG_NOTICE, "On line, sending shutdown+return command...\n"); ser_send_char(upsfd, CMD_SHUTRET ); - } - else - { + } else { upslogx(LOG_NOTICE, "On battery, sending normal shutdown command...\n"); ser_send_char(upsfd, CMD_SHUT); } - } -void upsdrv_help(void) -{ - +void upsdrv_help(void) { printf("\nSolis options\n"); printf(" Battery Extension in AH\n"); printf(" battext = 80\n"); @@ -1198,25 +956,20 @@ void upsdrv_help(void) printf(" houron = hh:mm hh = hour 0-23 mm = minute 0-59 separated with :\n"); printf(" houroff = hh:mm hh = hour 0-23 mm = minute 0-59 separated with :\n"); printf(" where houron is power-on hour and houroff is shutdown and power-off hour\n"); - printf(" Uses daysweek and houron to programing and save UPS power on/off\n"); + printf(" Uses daysweek and houron to programming and save UPS power on/off\n"); printf(" These are valid only if prgshut = 2 or 3\n"); - } -void upsdrv_makevartable(void) -{ - +void upsdrv_makevartable(void) { addvar(VAR_VALUE, "battext", "Battery Extension (0-80)min"); addvar(VAR_VALUE, "prgshut", "Programable power off (0-3)"); addvar(VAR_VALUE, "daysweek", "Days of week UPS power of/off"); addvar(VAR_VALUE, "daysoff", "Days of week Driver shutdown"); addvar(VAR_VALUE, "houron", "Power on hour (hh:mm)"); addvar(VAR_VALUE, "houroff", "Power off hour (hh:mm)"); - } -void upsdrv_initups(void) -{ +void upsdrv_initups(void) { upsfd = ser_open(device_path); ser_set_speed(upsfd, device_path, B9600); @@ -1224,7 +977,6 @@ void upsdrv_initups(void) ser_set_rts(upsfd, 0); } -void upsdrv_cleanup(void) -{ +void upsdrv_cleanup(void) { ser_close(upsfd, device_path); } diff --git a/drivers/solis.h b/drivers/solis.h index 528a8bb0b1..bfaeade63f 100644 --- a/drivers/solis.h +++ b/drivers/solis.h @@ -1,6 +1,8 @@ /* solis.h - Microsol Solis UPS hardware - Copyright (C) 2004 Silvino B. Magalhaes + Copyright (C) 2004 Silvino B. Magalhaes + 2019 Roberto Panerai Velloso + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -38,6 +40,8 @@ const static int bext[5] = {14,18,28,18,1}; const static int nompow[5] = { 1000,1500,2000,3000,1200 }; const static int inds[6] = { 0,0,1,2,3,4 }; const static double InVolt_offset = 30.; +#define PACKET_SIZE 25 +const static int packet_size = PACKET_SIZE; const static struct { int maxi; /* power internals */ @@ -336,7 +340,7 @@ static unsigned char DaysOnWeek=0, DaysOffWeek=0, DaysStd = 0; static char seman[4]; /* buffers */ -static unsigned char RecPack[25]; +static unsigned char RecPack[PACKET_SIZE]; static unsigned char ConfigPack[12]; /* @@ -349,9 +353,6 @@ static const char *Model; static int SolisModel, imodel; static int InputValue, Out220; -/* protocol */ -static int pacsize; - /* Status group */ static unsigned char InputStatus,OutputStatus, BattStatus; /* Events group */ @@ -375,12 +376,12 @@ static double BattVoltage, Temperature, batcharge; static double AppPower, UtilPower, upscharge; static int ChargePowerFactor, NominalPower, UpsPowerFactor; -static void prnInfo(void); -static int IsToday( unsigned char, int ); -static void AutonomyCalc( int ); -static void ScanReceivePack(void); -static void CommReceive(const char*, int ); -static void getbaseinfo(void); -static void getupdateinfo(void); +static void print_info(void); +static int is_today( unsigned char, int ); +static void autonomy_calc( int ); +static void scan_received_pack(void); +static void comm_receive(const unsigned char*, int ); +static void get_base_info(void); +static void get_update_info(void); #endif /* INCLUDED_SOLIS_H */ diff --git a/drivers/tripplite_usb.c b/drivers/tripplite_usb.c index 9b06407e1a..82efe35d8d 100644 --- a/drivers/tripplite_usb.c +++ b/drivers/tripplite_usb.c @@ -1362,6 +1362,9 @@ void upsdrv_updateinfo(void) case TRIPP_LITE_SMARTPRO: dstate_setinfo("ups.load", "%d", hex2d(l_value+1, 2)); break; + case TRIPP_LITE_SMART_3005: + dstate_setinfo("ups.load", "%d", hex_or_bin2d(l_value+1, 1)); + break; case TRIPP_LITE_SMART_0004: dstate_setinfo("ups.load", "%d", hex2d(l_value+1, 2)); dstate_setinfo("ups.debug.L","%s", hexascdump(l_value+1, 7)); diff --git a/drivers/upsdrvctl.c b/drivers/upsdrvctl.c index 116fe69c73..7dd74bfaef 100644 --- a/drivers/upsdrvctl.c +++ b/drivers/upsdrvctl.c @@ -150,13 +150,14 @@ static void stop_driver(const ups_t *ups) ret = stat(pidfn, &fs); if ((ret != 0) && (ups->port != NULL)) { + upslog_with_errno(LOG_ERR, "Can't open %s", pidfn); snprintf(pidfn, sizeof(pidfn), "%s/%s-%s.pid", altpidpath(), ups->driver, xbasename(ups->port)); ret = stat(pidfn, &fs); } if (ret != 0) { - upslog_with_errno(LOG_ERR, "Can't open %s", pidfn); + upslog_with_errno(LOG_ERR, "Can't open %s either", pidfn); exec_error++; return; } diff --git a/drivers/upshandler.h b/drivers/upshandler.h index ca9a349594..fea10bc20c 100644 --- a/drivers/upshandler.h +++ b/drivers/upshandler.h @@ -25,15 +25,15 @@ enum { STAT_INSTCMD_HANDLED = 0, /* completed successfully */ STAT_INSTCMD_UNKNOWN, /* unspecified error */ STAT_INSTCMD_INVALID, /* invalid command */ - STAT_INSTCMD_FAILED /* command failed */ + STAT_INSTCMD_FAILED /* command failed */ }; /* return values for setvar */ enum { STAT_SET_HANDLED = 0, /* completed successfully */ - STAT_SET_UNKNOWN, /* unspecified error */ - STAT_SET_INVALID, /* not writeable */ - STAT_SET_FAILED /* writing failed */ + STAT_SET_UNKNOWN, /* unspecified error */ + STAT_SET_INVALID, /* not writeable */ + STAT_SET_FAILED /* writing failed */ }; /* structure for funcs that get called by msg parse routine */ diff --git a/drivers/usbhid-ups.c b/drivers/usbhid-ups.c index 954fa54670..ea198c4db9 100644 --- a/drivers/usbhid-ups.c +++ b/drivers/usbhid-ups.c @@ -28,7 +28,7 @@ */ #define DRIVER_NAME "Generic HID driver" -#define DRIVER_VERSION "0.42" +#define DRIVER_VERSION "0.43" #include "main.h" #include "libhid.h" @@ -135,40 +135,6 @@ static double interval(void); HIDDesc_t *pDesc = NULL; /* parsed Report Descriptor */ reportbuf_t *reportbuf = NULL; /* buffer for most recent reports */ -/* ---------------------------------------------------------------------- */ -/* data for processing boolean values from UPS */ - -#define STATUS(x) ((unsigned)1<hidpath); /* Check for fallback if not found */ if (hidups_item == NULL) { + upsdebugx(3, "%s: cmdname '%s' not found; checking for alternatives", __func__, cmdname); if (!strcasecmp(cmdname, "load.on")) { return instcmd("load.on.delay", "0"); @@ -604,6 +570,8 @@ int instcmd(const char *cmdname, const char *extradata) return STAT_INSTCMD_INVALID; } + upsdebugx(3, "%s: using Path '%s'", __func__, hidups_item->hidpath); + /* Check if the item is an instant command */ if (!(hidups_item->hidflags & HU_TYPE_CMD)) { upsdebugx(2, "instcmd: %s is not an instant command\n", cmdname); @@ -913,18 +881,24 @@ void upsdrv_initups(void) { int ret; char *val; + + upsdebugx(2, "Initializing an USB-connected UPS with library %s " \ + "(NUT subdriver name='%s' ver='%s')", + dstate_getinfo("driver.version.usb"), + comm_driver->name, comm_driver->version ); + #ifdef SHUT_MODE /*! * SHUT is a serial protocol, so it needs * only the device path */ - upsdebugx(1, "upsdrv_initups..."); + upsdebugx(1, "upsdrv_initups (SHUT)..."); subdriver_matcher = device_path; #else char *regex_array[6]; - upsdebugx(1, "upsdrv_initups..."); + upsdebugx(1, "upsdrv_initups (non-SHUT)..."); subdriver_matcher = &subdriver_matcher_struct; @@ -1430,6 +1404,12 @@ static void ups_alarm_set(void) } } +/* Return the current value of ups_status */ +int ups_status_get(void) +{ + return ups_status; +} + /* Convert the local status information to NUT format and set NUT status. */ static void ups_status_set(void) diff --git a/drivers/usbhid-ups.h b/drivers/usbhid-ups.h index eee182372d..8bd3828590 100644 --- a/drivers/usbhid-ups.h +++ b/drivers/usbhid-ups.h @@ -69,6 +69,9 @@ typedef struct { double (*nuf)(const char *nut_value); /* optional NUT to HID mapping */ } info_lkp_t; +/* accessor on the status */ +extern int ups_status_get(void); + /* declarations of public lookup tables */ /* boolean status values from UPS */ extern info_lkp_t online_info[]; @@ -113,6 +116,40 @@ extern info_lkp_t stringid_conversion[]; extern info_lkp_t divide_by_10_conversion[]; extern info_lkp_t kelvin_celsius_conversion[]; +/* ---------------------------------------------------------------------- */ +/* data for processing boolean values from UPS */ + +#define STATUS(x) ((unsigned)1<> _nut_version.h ; \ if [ -z "$$GITREV" ]; \ then NUT_VERSION="$(PACKAGE_VERSION)"; \ - echo '/* The version number is set by AC_INIT in configure.in. */' >> _nut_version.h ; \ + echo '/* The version number is set by AC_INIT in configure.ac. */' >> _nut_version.h ; \ else NUT_VERSION="$$GITREV"; \ echo '/* The version number is determined by the most recent Git tag. */' >> _nut_version.h ; \ fi ; \ diff --git a/include/common.h b/include/common.h index b1fb53ed2d..248dadd374 100644 --- a/include/common.h +++ b/include/common.h @@ -53,6 +53,12 @@ extern "C" { extern const char *UPS_VERSION; +/** @brief Default timeout (in seconds) for network operations, as used by `upsclient` and `nut-scanner`. */ +#define DEFAULT_NETWORK_TIMEOUT 5 + +/** @brief Default timeout (in seconds) for retrieving the result of a `TRACKING`-enabled operation (e.g. `INSTCMD`, `SET VAR`). */ +#define DEFAULT_TRACKING_TIMEOUT 10 + /* get the syslog ready for us */ void open_syslog(const char *progname); @@ -128,6 +134,9 @@ char * get_libname(const char* base_libname); #define SMALLBUF 512 #define LARGEBUF 1024 +/** @brief (Minimum) Size that a string must have to hold a UUID4 (i.e. UUID4 length + the terminating null character). */ +#define UUID4_LEN 37 + /* Provide declarations for getopt() global variables */ #ifdef NEED_GETOPT_H diff --git a/lib/libupsclient.pc.in b/lib/libupsclient.pc.in index 4ad31fbde9..8efce40205 100644 --- a/lib/libupsclient.pc.in +++ b/lib/libupsclient.pc.in @@ -9,5 +9,6 @@ nutuser=@RUN_AS_USER@ Name: libupsclient Description: UPS monitoring with Network UPS Tools Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lupsclient @LIBSSL_LIBS@ -Cflags: -I${includedir} @LIBSSL_CFLAGS@ +Libs: -L${libdir} -lupsclient +Cflags: -I${includedir} +Requires: @LIBSSL_REQUIRES@ diff --git a/m4/nut_check_libavahi.m4 b/m4/nut_check_libavahi.m4 index 034d31aa48..8567686264 100644 --- a/m4/nut_check_libavahi.m4 +++ b/m4/nut_check_libavahi.m4 @@ -1,4 +1,4 @@ -dnl Check for LIBAVAHI compiler flags. On success, set nut_have_neon="yes" +dnl Check for LIBAVAHI compiler flags. On success, set nut_have_avahi="yes" dnl and set LIBAVAHI_CFLAGS and LIBAVAHI_LIBS. On failure, set dnl nut_have_avahi="no". This macro can be run multiple times, but will dnl do the checking only once. diff --git a/m4/nut_check_libgd.m4 b/m4/nut_check_libgd.m4 index 73f4da76d0..c4e96761ce 100644 --- a/m4/nut_check_libgd.m4 +++ b/m4/nut_check_libgd.m4 @@ -12,50 +12,62 @@ if test -z "${nut_have_libgd_seen}"; then LDFLAGS_ORIG="${LDFLAGS}" LIBS_ORIG="${LIBS}" - dnl Initial defaults. These are only used if gdlib-config is - dnl unusable and the user fails to pass better values in --with - dnl arguments - CFLAGS="" - LDFLAGS="-L/usr/X11R6/lib" - LIBS="-lgd -lpng -lz -ljpeg -lfreetype -lm -lXpm -lX11" + AC_MSG_CHECKING(for gd version via pkg-config) + GD_VERSION="`pkg-config --silence-errors --modversion gdlib 2>/dev/null`" + if test "$?" = "0" -a -n "${GD_VERSION}"; then + CFLAGS="`pkg-config --silence-errors --cflags gdlib 2>/dev/null`" + LIBS="`pkg-config --silence-errors --libs gdlib 2>/dev/null`" + else + GD_VERSION="none" + fi + AC_MSG_RESULT(${GD_VERSION} found) - dnl By default seek in PATH - GDLIB_CONFIG=gdlib-config - AC_ARG_WITH(gdlib-config, - AS_HELP_STRING([@<:@--with-gdlib-config=/path/to/gdlib-config@:>@], - [path to program that reports GDLIB configuration]), - [ - case "${withval}" in - "") ;; - yes|no) - AC_MSG_ERROR(invalid option --with(out)-gdlib-config - see docs/configure.txt) + if test "${GD_VERSION}" = "none"; then + dnl Initial defaults. These are only used if gdlib-config is + dnl unusable and the user fails to pass better values in --with + dnl arguments + CFLAGS="" + LDFLAGS="-L/usr/X11R6/lib" + LIBS="-lgd -lpng -lz -ljpeg -lfreetype -lm -lXpm -lX11" + + dnl By default seek in PATH + GDLIB_CONFIG=gdlib-config + AC_ARG_WITH(gdlib-config, + AS_HELP_STRING([@<:@--with-gdlib-config=/path/to/gdlib-config@:>@], + [path to program that reports GDLIB configuration]), + [ + case "${withval}" in + "") ;; + yes|no) + AC_MSG_ERROR(invalid option --with(out)-gdlib-config - see docs/configure.txt) + ;; + *) + GDLIB_CONFIG="${withval}" + ;; + esac + ]) + + AC_MSG_CHECKING(for gd version via ${GDLIB_CONFIG}) + GD_VERSION=`${GDLIB_CONFIG} --version 2>/dev/null` + if test "$?" != "0" -o -z "${GD_VERSION}"; then + GD_VERSION="none" + fi + AC_MSG_RESULT(${GD_VERSION} found) + + case "${GD_VERSION}" in + none) + ;; + 2.0.5 | 2.0.6 | 2.0.7) + AC_MSG_WARN([[gd ${GD_VERSION} detected, unable to use ${GDLIB_CONFIG} script]]) + AC_MSG_WARN([[If gd detection fails, upgrade gd or use --with-gd-includes and --with-gd-libs]]) ;; *) - GDLIB_CONFIG="${withval}" + CFLAGS="`${GDLIB_CONFIG} --includes 2>/dev/null`" + LDFLAGS="`${GDLIB_CONFIG} --ldflags 2>/dev/null`" + LIBS="`${GDLIB_CONFIG} --libs 2>/dev/null`" ;; esac - ]) - - AC_MSG_CHECKING(for gd version via ${GDLIB_CONFIG}) - GD_VERSION=`${GDLIB_CONFIG} --version 2>/dev/null` - if test "$?" != "0" -o -z "${GD_VERSION}"; then - GD_VERSION="none" fi - AC_MSG_RESULT(${GD_VERSION} found) - - case "${GD_VERSION}" in - none) - ;; - 2.0.5 | 2.0.6 | 2.0.7) - AC_MSG_WARN([[gd ${GD_VERSION} detected, unable to use ${GDLIB_CONFIG} script]]) - AC_MSG_WARN([[If gd detection fails, upgrade gd or use --with-gd-includes and --with-gd-libs]]) - ;; - *) - CFLAGS="`${GDLIB_CONFIG} --includes 2>/dev/null`" - LDFLAGS="`${GDLIB_CONFIG} --ldflags 2>/dev/null`" - LIBS="`${GDLIB_CONFIG} --libs 2>/dev/null`" - ;; - esac dnl Now allow overriding gd settings if the user knows best AC_MSG_CHECKING(for gd include flags) diff --git a/m4/nut_check_libneon.m4 b/m4/nut_check_libneon.m4 index 4fd290b1b4..bbd84eb7d4 100644 --- a/m4/nut_check_libneon.m4 +++ b/m4/nut_check_libneon.m4 @@ -12,14 +12,24 @@ if test -z "${nut_have_neon_seen}"; then CFLAGS_ORIG="${CFLAGS}" LIBS_ORIG="${LIBS}" + nut_defaulted_neon_version=no + nut_defaulted_neon_cflags=no + nut_defaulted_neon_libs=no + dnl See which version of the neon library (if any) is installed + dnl FIXME : Support detection of cflags/ldflags below by legacy discovery if pkgconfig is not there AC_MSG_CHECKING(for libneon version via pkg-config (0.25.0 minimum required)) NEON_VERSION="`pkg-config --silence-errors --modversion neon 2>/dev/null`" if test "$?" != "0" -o -z "${NEON_VERSION}"; then + nut_defaulted_neon_version=yes NEON_VERSION="none" fi AC_MSG_RESULT(${NEON_VERSION} found) + if test "${nut_defaulted_neon_version}" = "yes" ; then + AC_MSG_WARN([could not get pkg-config information for libneon version, using fallback defaults]) + fi + AC_MSG_CHECKING(for libneon cflags) AC_ARG_WITH(neon-includes, AS_HELP_STRING([@<:@--with-neon-includes=CFLAGS@:>@], [include flags for the neon library]), @@ -32,9 +42,17 @@ if test -z "${nut_have_neon_seen}"; then CFLAGS="${withval}" ;; esac - ], [CFLAGS="`pkg-config --silence-errors --cflags neon 2>/dev/null`"]) + ], [CFLAGS="`pkg-config --silence-errors --cflags neon 2>/dev/null`" + if test "$?" != 0 ; then + nut_defaulted_neon_cflags=yes + CFLAGS="-I/usr/include/neon" + fi]) AC_MSG_RESULT([${CFLAGS}]) + if test "${nut_defaulted_neon_cflags}" = "yes" ; then + AC_MSG_WARN([could not get pkg-config information for libneon cflags, using fallback defaults]) + fi + AC_MSG_CHECKING(for libneon ldflags) AC_ARG_WITH(neon-libs, AS_HELP_STRING([@<:@--with-neon-libs=LIBS@:>@], [linker flags for the neon library]), @@ -47,9 +65,17 @@ if test -z "${nut_have_neon_seen}"; then LIBS="${withval}" ;; esac - ], [LIBS="`pkg-config --silence-errors --libs neon 2>/dev/null`"]) + ], [LIBS="`pkg-config --silence-errors --libs neon 2>/dev/null`" + if test "$?" != 0 ; then + nut_defaulted_neon_libs=yes + LIBS="-lneon" + fi]) AC_MSG_RESULT([${LIBS}]) + if test "${nut_defaulted_neon_libs}" = "yes" ; then + AC_MSG_WARN([could not get pkg-config information for libneon libs, using fallback defaults]) + fi + dnl check if neon is usable AC_CHECK_HEADERS(ne_xmlreq.h, [nut_have_neon=yes], [nut_have_neon=no], [AC_INCLUDES_DEFAULT]) AC_CHECK_FUNCS(ne_xml_dispatch_request, [], [nut_have_neon=no]) diff --git a/m4/nut_check_libnss.m4 b/m4/nut_check_libnss.m4 index 7c235318dd..7fed727d3f 100644 --- a/m4/nut_check_libnss.m4 +++ b/m4/nut_check_libnss.m4 @@ -11,16 +11,19 @@ if test -z "${nut_have_libnss_seen}"; then dnl save CFLAGS and LIBS CFLAGS_ORIG="${CFLAGS}" LIBS_ORIG="${LIBS}" + REQUIRES_ORIG="${REQUIRES}" AC_MSG_CHECKING(for Mozilla NSS version via pkg-config) NSS_VERSION="`pkg-config --silence-errors --modversion nss 2>/dev/null`" if test "$?" = "0" -a -n "${NSS_VERSION}"; then CFLAGS="`pkg-config --silence-errors --cflags nss 2>/dev/null`" LIBS="`pkg-config --silence-errors --libs nss 2>/dev/null`" + REQUIRES="nss" else NSS_VERSION="none" CFLAGS="" LIBS="-lnss3 -lnssutil3 -lsmime3 -lssl3 -lplds4 -lplc4 -lnspr4" + REQUIRES="nss" fi AC_MSG_RESULT(${NSS_VERSION} found) @@ -67,10 +70,12 @@ if test -z "${nut_have_libnss_seen}"; then AC_DEFINE(WITH_NSS, 1, [Define to enable SSL support using Mozilla NSS]) LIBSSL_CFLAGS="${CFLAGS}" LIBSSL_LIBS="${LIBS}" + LIBSSL_REQUIRES="${REQUIRES}" fi dnl restore original CFLAGS and LIBS CFLAGS="${CFLAGS_ORIG}" LIBS="${LIBS_ORIG}" + REQUIRES="${REQUIRES_ORIG}" fi ]) diff --git a/m4/nut_check_libopenssl.m4 b/m4/nut_check_libopenssl.m4 index 1b875077b9..d9e9e02376 100644 --- a/m4/nut_check_libopenssl.m4 +++ b/m4/nut_check_libopenssl.m4 @@ -12,16 +12,19 @@ if test -z "${nut_have_libopenssl_seen}"; then dnl save CFLAGS and LIBS CFLAGS_ORIG="${CFLAGS}" LIBS_ORIG="${LIBS}" + REQUIRES_ORIG="${REQUIRES}" AC_MSG_CHECKING(for OpenSSL version via pkg-config) OPENSSL_VERSION="`pkg-config --silence-errors --modversion openssl 2>/dev/null`" if test "$?" = "0" -a -n "${OPENSSL_VERSION}"; then CFLAGS="`pkg-config --silence-errors --cflags openssl 2>/dev/null`" LIBS="`pkg-config --silence-errors --libs openssl 2>/dev/null`" + REQUIRES="openssl" else OPENSSL_VERSION="none" CFLAGS="" LIBS="-lssl -lcrypto" + REQUIRES="openssl" fi AC_MSG_RESULT(${OPENSSL_VERSION} found) @@ -58,7 +61,7 @@ if test -z "${nut_have_libopenssl_seen}"; then dnl check if openssl is usable AC_CHECK_HEADERS(openssl/ssl.h, [nut_have_openssl=yes], [nut_have_openssl=no], [AC_INCLUDES_DEFAULT]) - AC_CHECK_FUNCS(SSL_library_init, [], [nut_have_openssl=no]) + AC_CHECK_FUNCS(SSL_CTX_new, [], [nut_have_openssl=no]) if test "${nut_have_openssl}" = "yes"; then nut_with_ssl="yes" @@ -67,10 +70,12 @@ if test -z "${nut_have_libopenssl_seen}"; then AC_DEFINE(WITH_OPENSSL, 1, [Define to enable SSL support using OpenSSL]) LIBSSL_CFLAGS="${CFLAGS}" LIBSSL_LIBS="${LIBS}" + LIBSSL_REQUIRES="${REQUIRES}" fi dnl restore original CFLAGS and LIBS CFLAGS="${CFLAGS_ORIG}" LIBS="${LIBS_ORIG}" + REQUIRES="${REQUIRES_ORIG}" fi ]) diff --git a/scripts/Aix/.gitignore b/scripts/Aix/.gitignore index ce505768bf..038fae6802 100644 --- a/scripts/Aix/.gitignore +++ b/scripts/Aix/.gitignore @@ -1 +1,2 @@ nut-aix.spec +nut.init diff --git a/scripts/Aix/nut.init b/scripts/Aix/nut.init deleted file mode 100644 index a54f85899d..0000000000 --- a/scripts/Aix/nut.init +++ /dev/null @@ -1,163 +0,0 @@ -#! /bin/sh -# -# ups: Starts the Network UPS Tools -# -# chkconfig: - 26 74 -# description: Network UPS Tools is a collection of programs which provide a common \ -# interface for monitoring and administering UPS hardware. -# processname: upsd -# config: /usr/local/ups/etc -# config: /etc/rc.ups -# -### BEGIN INIT INFO -# Provides: ups -# Required-Start: $syslog $network $named -# Required-Stop: $local_fs -# Default-Stop: 0 1 6 -# Short-Description: Starts the Network UPS tools -# Description: Network UPS Tools is a collection of programs which provide a common \ -# interface for monitoring and administering UPS hardware. -### END INIT INFO - -success() { - echo OK -} - -failure() { - echo FAILED -} - -# Resolve what processes should run -SERVER="no" -CLIENT="no" - -if [ -f /usr/local/ups/etc/nut.conf ]; then - . /usr/local/ups/etc/nut.conf - - case $MODE in - standalone|netserver) - SERVER="yes" - ;; - esac - - rpm -q nut-client >/dev/null 2>&1 && CLIENT="yes" -fi - -do_start() { - if [ "$SERVER" = "yes" ]; then - echo "Starting UPS driver controller: \c" - /usr/local/ups/sbin/upsdrvctl start >/dev/null 2>&1 && success || failure - RETVAL=$? - - echo "Starting upsd: \c" - /usr/local/ups/sbin/upsd $UPSD_OPTIONS >/dev/null 2>&1 && success || failure - if [ "$RETVAL" = 0 ]; then - RETVAL=$? - fi - fi - - if [ "$CLIENT" = "yes" ]; then - echo "Starting UPS monitor: \c" - /usr/local/ups/sbin/upsmon >/dev/null 2>&1 && success || failure - if [ "$RETVAL" = 0 ]; then - RETVAL=$? - fi - fi - - [ "$RETVAL" = 0 ] && touch /var/locks/ups -} - -do_stop() { - if test -e /var/run/nut/upsmon.pid; then - echo "Stopping UPS monitor: \c" - PID=`cat /var/run/nut/upsmon.pid` - kill $PID && success || failure - rm /var/run/nut/upsmon.pid - fi - - if [ "$SERVER" = "yes" ]; then - if test -e /var/run/nut/upsd.pid; then - echo "Stopping upsd: \c" - PID=`cat /var/run/nut/upsd.pid` - kill -9 $PID && success || failure - rm /var/run/nut/upsd.pid - fi - RETVAL=$? - - echo "Shutting down UPS driver controller: \c" - /usr/local/ups/sbin/upsdrvctl stop > /dev/null 2>&1 && success || failure - if [ "$RETVAL" = 0 ]; then - RETVAL=$? - fi - fi - [ "$RETVAL" = 0 ] && rm -f /var/locks/ups -} - -do_restart() { - do_stop - waitmore=5 - while [ -n "$(ls /var/run/nut/)" -a $waitmore -ge 1 ] - do - sleep 1 - waitmore=$((waitmore-1)) - done - do_start -} - -do_reload() { - # FIXME: upsd and upsmon always return 0 - # => can't tell if reload was successful - if [ "$SERVER" = "yes" ]; then - echo "Reloading upsd" - /usr/local/ups/sbin/upsd -c reload - RETVAL=$? - fi - - echo "Reloading upsmon" - /usr/local/ups/sbin/upsmon -c reload - if [ "$RETVAL" = 0 ]; then - RETVAL=$? - fi -} - -# See how we are called. -case "$1" in - start) - do_start ;; - - stop) - do_stop ;; - - restart) - do_restart ;; - - try-restart) - [ -f /var/locks/ups ] && do_restart || true - ;; - - reload) - do_reload ;; - - force-reload) - do_restart ;; - - status) - if [ "$SERVER" = "yes" ]; then - if test -f /var/locks/ups; then - echo "upsd is running with PID" `cat /var/run/nut/upsd.pid` - fi - fi - - if test -e /var/run/nut/upsmon.pid; then - echo "upsmon is running with PID" `cat /var/run/nut/upsmon.pid` - elif rpm -q nut-client >/dev/null 2>&1; then - echo "upsmon isn't running" - fi - ;; - - *) - echo "Usage: $0 {start|stop|restart|try-restart|reload|force-reload|status}" - RETVAL=3 -esac - -exit $RETVAL diff --git a/scripts/Aix/nut.init.in b/scripts/Aix/nut.init.in new file mode 100755 index 0000000000..018777efe6 --- /dev/null +++ b/scripts/Aix/nut.init.in @@ -0,0 +1,171 @@ +#! /bin/sh +# +# ups: Starts the Network UPS Tools +# +# chkconfig: - 26 74 +# description: Network UPS Tools is a collection of programs which provide a common \ +# interface for monitoring and administering UPS hardware. +# processname: upsd +# config: /usr/local/ups/etc +# config: /etc/rc.ups +# +### BEGIN INIT INFO +# Provides: ups +# Required-Start: $syslog $network $named +# Required-Stop: $local_fs +# Default-Stop: 0 1 6 +# Short-Description: Starts the Network UPS tools +# Description: Network UPS Tools is a collection of programs which provide a common \ +# interface for monitoring and administering UPS hardware. +### END INIT INFO + +success() { + echo OK +} + +failure() { + echo FAILED +} + +# Resolve what processes should run +SERVER="no" +CLIENT="no" + +NUT_DIR="@prefix@" +NUT_SBIN_DIR="${NUT_DIR}/sbin" +NUT_LIB_DIR="${NUT_DIR}/lib" +NUT_RUN_DIR="@PIDPATH@/nut" +CONFIG="@CONFPATH@/nut.conf" +NUTUSER="@RUN_AS_USER@" +NUTGROUP="@RUN_AS_GROUP@" +NUT_VAR_LOCK="/var/locks/ups" + +if [ -f "$CONFIG" ] ; then + . "$CONFIG" + + case "$MODE" in + standalone|netserver) + SERVER="yes" + ;; + esac + + rpm -q nut-client >/dev/null 2>&1 && CLIENT="yes" +fi + +do_start() { + RETVAL=0 + + if [ ! -d "$NUT_RUN_DIR" ]; then + mkdir -p "$NUT_RUN_DIR" && \ + chown "root:$NUTGROUP" "$NUT_RUN_DIR" && \ + chmod 770 "$NUT_RUN_DIR" + RETVAL=$? + fi + + if [ "$SERVER" = "yes" ]; then + echo "Starting UPS driver controller: \c" + LD_LIBRARY_PATH="${NUT_LIB_DIR}:$LD_LIBRARY_PATH" "${NUT_SBIN_DIR}"/upsdrvctl start >/dev/null 2>&1 && success || { RETVAL=$?; failure; } + + echo "Starting upsd: \c" + LD_LIBRARY_PATH="${NUT_LIB_DIR}:$LD_LIBRARY_PATH" "${NUT_SBIN_DIR}"/upsd $UPSD_OPTIONS >/dev/null 2>&1 && success || { RETVAL=$?; failure; } + fi + + if [ "$CLIENT" = "yes" ]; then + echo "Starting UPS monitor: \c" + LD_LIBRARY_PATH="${NUT_LIB_DIR}:$LD_LIBRARY_PATH" "${NUT_SBIN_DIR}"/upsmon >/dev/null 2>&1 && success || { RETVAL=$?; failure; } + fi + + [ "$RETVAL" = 0 ] && touch "${NUT_VAR_LOCK}" + return $RETVAL +} + +do_stop() { + RETVAL=0 + if test -e "${NUT_RUN_DIR}"/upsmon.pid; then + echo "Stopping UPS monitor: \c" + PID="`cat "${NUT_RUN_DIR}"/upsmon.pid`" + kill -15 $PID && success || { RETVAL=$?; failure; } + rm "${NUT_RUN_DIR}"/upsmon.pid + fi + + if [ "$SERVER" = "yes" ]; then + if test -e "${NUT_RUN_DIR}"/upsd.pid; then + echo "Stopping upsd: \c" + PID="`cat "${NUT_RUN_DIR}"/upsd.pid`" + kill -15 $PID && success || { RETVAL=$?; failure; } + rm "${NUT_RUN_DIR}"/upsd.pid + fi + + echo "Shutting down UPS driver controller: \c" + "${NUT_SBIN_DIR}"/upsdrvctl stop > /dev/null 2>&1 && success || { RETVAL=$?; failure; } + fi + [ "$RETVAL" = 0 ] && rm -f "${NUT_VAR_LOCK}" + return $RETVAL +} + +do_restart() { + do_stop + waitmore=5 + while [ -n "$(ls "${NUT_RUN_DIR}"/)" -a $waitmore -ge 1 ] + do + sleep 1 + waitmore="$(expr $waitmore - 1)" + done + do_start +} + +do_reload() { + # FIXME: upsd and upsmon always return 0 + # => can't tell if reload was successful + RETVAL=0 + if [ "$SERVER" = "yes" ]; then + echo "Reloading upsd" + LD_LIBRARY_PATH="${NUT_LIB_DIR}:$LD_LIBRARY_PATH" "${NUT_SBIN_DIR}"/upsd -c reload && success || { RETVAL=$?; failure; } + fi + + echo "Reloading upsmon" + LD_LIBRARY_PATH="${NUT_LIB_DIR}:$LD_LIBRARY_PATH" "${NUT_SBIN_DIR}"/upsmon -c reload && success || { RETVAL=$?; failure; } + return $RETVAL +} + +# See how we are called. +case "$1" in + start) + do_start ;; + + stop) + do_stop ;; + + restart) + do_restart ;; + + try-restart) + [ -f "${NUT_VAR_LOCK}" ] && do_restart || true + ;; + + reload) + do_reload ;; + + force-reload) + do_restart ;; + + status) + if [ "$SERVER" = "yes" ]; then + if test -f "${NUT_VAR_LOCK}"; then + echo "upsd is running with PID" `cat "${NUT_RUN_DIR}"/upsd.pid` + fi + fi + + if test -e "${NUT_RUN_DIR}"/upsmon.pid; then + echo "upsmon is running with PID" `cat "${NUT_RUN_DIR}"/upsmon.pid` + elif rpm -q nut-client >/dev/null 2>&1; then + echo "upsmon isn't running" + fi + ;; + + *) + echo "Usage: $0 {start|stop|restart|try-restart|reload|force-reload|status}" + RETVAL=3 +esac + +exit $RETVAL diff --git a/scripts/Makefile.am b/scripts/Makefile.am index 8e84e24b5d..2d54b5b085 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -25,4 +25,4 @@ EXTRA_DIST = README \ Windows/halt.c \ Windows/Makefile -SUBDIRS = augeas devd hotplug python systemd udev Solaris +SUBDIRS = augeas devd hotplug python systemd udev Solaris upsdrvsvcctl diff --git a/scripts/Solaris/.gitignore b/scripts/Solaris/.gitignore index 92334788dc..4bfd7c9314 100644 --- a/scripts/Solaris/.gitignore +++ b/scripts/Solaris/.gitignore @@ -1,4 +1,15 @@ /nut /pkginfo +/preinstall /postinstall /preremove +/postremove +/preproto.pl +/svc-nut-server +/svc-nut-monitor +/nut-driver.xml +/nut-driver-enumerator.xml +/nut-monitor.xml +/nut-server.xml +/nut.xml +/NUT*.local.gz diff --git a/scripts/Solaris/Makefile.am b/scripts/Solaris/Makefile.am index 15075b0617..baa4ee3713 100644 --- a/scripts/Solaris/Makefile.am +++ b/scripts/Solaris/Makefile.am @@ -1,17 +1,83 @@ -EXTRA_DIST = makelocal.sh - -package: makelocal.sh pkginfo - $ cd @prefix@; $ find . -print | pkgproto > prototype1 - $ cp makelocal.sh precheck.py pkginfo nut preinstall postinstall preremove postremove preproto.pl @prefix@ - $ cd @prefix@; perl preproto.pl - $ cd @prefix@; python precheck.py - $ cd @prefix@; rm -f prototype1 - $ cd @prefix@; ./makelocal.sh - $ cp @prefix@/*.gz $(srcdir) - if test `uname -p` = "i386"; then \ - mv NUT_solaris_package.local.gz NUT_solaris_i386_package@PACKAGE_VERSION@.local.gz; \ - else \ - if test `uname -p` = "sparc"; then \ - mv NUT_solaris_package.local.gz NUT_solaris_sparc_package@PACKAGE_VERSION@.local.gz; \ - fi; \ - fi; +EXTRA_DIST = makelocal.sh README +PROTOTYPE_DIR = $(DESTDIR)@prefix@ +SOLARIS_CHECK_TARGETS = + +SOLARIS_SMF_MANIFESTS = \ + nut.xml \ + nut-server.xml \ + nut-monitor.xml \ + nut-driver.xml \ + nut-driver-enumerator.xml + +SOLARIS_SMF_METHODSCRIPTS = \ + svc-nut-server \ + svc-nut-monitor + +if WITH_SOLARIS_SMF +# OS equivalent of /lib/svc/method and /var/svc/manifest/application +# but we can just use then from this location +solarissmfmethoddir = @datadir@/solaris-smf/method +solarissmfmanifestdir = @datadir@/solaris-smf/manifest +solarissmfmethod_SCRIPTS = $(SOLARIS_SMF_METHODSCRIPTS) +solarissmfmanifest_DATA = $(SOLARIS_SMF_MANIFESTS) + +libexec_SCRIPTS = ../upsdrvsvcctl/nut-driver-enumerator.sh + +sbin_SCRIPTS = ../upsdrvsvcctl/upsdrvsvcctl + +SOLARIS_CHECK_TARGETS += check-local-solaris-smf +endif + +solarisinitscriptdir = @datadir@/solaris-init +solarisinitscript_SCRIPTS = nut + +SOLARIS_PACKAGE_TARGETS = + +if WITH_SOLARIS_PKG_IPS +SOLARIS_PACKAGE_TARGETS += package-solaris-ips +endif + +if WITH_SOLARIS_PKG_SVR4 +SOLARIS_PACKAGE_TARGETS += package-solaris-svr4 +endif + +package: $(SOLARIS_PACKAGE_TARGETS) + +# TODO: Reduce build dependencies (implicit!) on python and perl +# by shelling the scripts used below +# NOTE: This assumes the rest of the product has already been built +# and installed under PROTOTYPE_DIR, but declares no explicit +# dependency on that +SOLARIS_PACKAGE_SVR4_HELPERSCRIPTS = makelocal.sh precheck.py preproto.pl +SOLARIS_PACKAGE_SVR4_INSTALLSCRIPTS = preinstall postinstall preremove postremove +SOLARIS_PACKAGE_SVR4_INSTALLDATA = pkginfo +package-solaris-svr4: $(SOLARIS_PACKAGE_SVR4_HELPERSCRIPTS) $(SOLARIS_PACKAGE_SVR4_INSTALLSCRIPTS) $(SOLARIS_PACKAGE_SVR4_INSTALLDATA) + if test -n "@auglensdir@" && test -d "$(DESTDIR)@auglensdir@" ; then \ + mkdir -p "$(DESTDIR)@datadir@/augeas-lenses" && \ + cd "$(DESTDIR)@auglensdir@" && \ + ( cp -prf ./ "$(DESTDIR)@datadir@/augeas-lenses/" || cp -rf ./ "$(DESTDIR)@datadir@/augeas-lenses/" ) ; fi + cd $(PROTOTYPE_DIR) && find . -print | pkgproto > prototype1 + cp $(SOLARIS_PACKAGE_SVR4_HELPERSCRIPTS) $(SOLARIS_PACKAGE_SVR4_INSTALLSCRIPTS) $(SOLARIS_PACKAGE_SVR4_INSTALLDATA) $(PROTOTYPE_DIR) + cd $(PROTOTYPE_DIR) && chmod +x $(SOLARIS_PACKAGE_SVR4_HELPERSCRIPTS) $(SOLARIS_PACKAGE_SVR4_INSTALLSCRIPTS) + cd $(PROTOTYPE_DIR) && perl preproto.pl + cd $(PROTOTYPE_DIR) && python precheck.py + cd $(PROTOTYPE_DIR) && rm -f prototype1 + cd $(PROTOTYPE_DIR) && ./makelocal.sh + cp $(PROTOTYPE_DIR)/*.gz $(builddir) + UNAME_P="`uname -p`" && case "$${UNAME_P}" in \ + i386|sparc) \ + mv -f NUT_solaris_package.local.gz "$(abs_top_builddir)/NUT_solaris_$${UNAME_P}_package@PACKAGE_VERSION@.local.gz" ;; \ + esac + +# TODO: Define support for IPS packaging (provide p5m files and make rules) +package-solaris-ips: + @echo "SKIPPED : Target $@ is not implemented yet" + +check-local: $(SOLARIS_CHECK_TARGETS) + +check-local-solaris-smf: $(SOLARIS_SMF_MANIFESTS) + @[ -x /usr/sbin/svccfg ] || { echo "WARNING : Target $@ skipped due to absent /usr/sbin/svccfg" >&2; return 0; } ; \ + RES=0 ; for F in $^ ; do \ + echo " SVCCFG-VALIDATE $$F"; \ + /usr/sbin/svccfg validate "$$F" || RES=$$? ; \ + done; exit $$RES diff --git a/scripts/Solaris/README b/scripts/Solaris/README new file mode 100644 index 0000000000..adb305efdc --- /dev/null +++ b/scripts/Solaris/README @@ -0,0 +1,38 @@ +This directory contains init-scripts and SMF manifests and methods +for integration of NUT services with Solaris and descendant OSes. + +This also includes the nut-driver-enumerator.sh (service and implementation +method) and upsdrvsvcctl (tool) to manage NUT drivers as service instances, +which are stored in ../upsdrvsvcctl/ subdirectory (portable codebase shared +with Linux systemd). + +The default implementation (runs once) can be enabled with: + + svcadm enable nut-driver-enumerator:default + +Note that at the moment there is no out-of-the-box integration for triggering +a restart/refresh of the nut-driver-enumerator SMF service at the very instant +when the `ups.conf` file is modified, like there is with systemd path unit type. +Due to this, the systems administrator is expected to either invoke +`svcadm refresh nut-driver-enumerator` after changing the NUT configuration +or wait until the daemonized mode, if enabled, picks up the change (should do +so within a minute by default). However, a DTrace script or a tool like +https://github.com/emcrisostomo/fswatch wrapped into a service might be used +for equivalent effect. + +Alternatively, but somewhat more expensively, the same `nut-driver-enumerator.sh` +script can be executed in a loop as the payload of the SMF service to keep +inspecting the configuration and apply changes to the running system. It is +not a common use-case to keep changing device setups, so this solution is not +enforced by default ;) although a service variant is provided... + +Note that only one of these can be enabled at the same time: + + svcadm disable nut-driver-enumerator:default + svcadm enable nut-driver-enumerator:daemon + +Init-script solution contributed by numerous authors +SMF solution contributed by Jim Klimov + +For special notes about USB-connected device monitoring with NUT under Solaris +and related operating systems, see docs/solaris-usb.txt diff --git a/scripts/Solaris/makelocal.sh b/scripts/Solaris/makelocal.sh index 639e780036..f017c43cdd 100755 --- a/scripts/Solaris/makelocal.sh +++ b/scripts/Solaris/makelocal.sh @@ -1,5 +1,11 @@ #!/bin/sh -pkgmk -o -d `pwd` -pkgtrans `pwd` `pwd`/NUT_solaris_package.local -gzip `pwd`/NUT_solaris_package.local +# Creates the package file from current-directory contents +# Called by Makefile starting from installed prototype directory + +echo "Making Solaris SVR4 package metadata..." && \ +pkgmk -o -d "`pwd`" && \ +echo "Making Solaris SVR4 package archive file..." && \ +( yes "" | pkgtrans "`pwd`" "`pwd`/NUT_solaris_package.local" ) && \ +echo "Compressing Solaris SVR4 package archive file..." && \ +gzip "`pwd`/NUT_solaris_package.local" diff --git a/scripts/Solaris/nut-driver-enumerator.xml.in b/scripts/Solaris/nut-driver-enumerator.xml.in new file mode 100644 index 0000000000..55723c0326 --- /dev/null +++ b/scripts/Solaris/nut-driver-enumerator.xml.in @@ -0,0 +1,178 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scripts/Solaris/nut-driver.xml.in b/scripts/Solaris/nut-driver.xml.in new file mode 100644 index 0000000000..c52afacf4b --- /dev/null +++ b/scripts/Solaris/nut-driver.xml.in @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scripts/Solaris/nut-monitor.xml.in b/scripts/Solaris/nut-monitor.xml.in new file mode 100644 index 0000000000..c3118d3557 --- /dev/null +++ b/scripts/Solaris/nut-monitor.xml.in @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scripts/Solaris/nut-server.xml.in b/scripts/Solaris/nut-server.xml.in new file mode 100644 index 0000000000..6b3b4d06d0 --- /dev/null +++ b/scripts/Solaris/nut-server.xml.in @@ -0,0 +1,154 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scripts/Solaris/nut.in b/scripts/Solaris/nut.in old mode 100644 new mode 100755 index ab7ec94efa..1c39603c37 --- a/scripts/Solaris/nut.in +++ b/scripts/Solaris/nut.in @@ -3,29 +3,31 @@ #init.d script to start nut services NUT_DIR="@prefix@" -CONFIG=$NUT_DIR/etc/nut.conf +NUT_SBIN_DIR="${NUT_DIR}/sbin" +NUT_LIB_DIR="${NUT_DIR}/lib" +CONFIG="@CONFPATH@/nut.conf" -if [ -f $CONFIG ] ; then - . $CONFIG +if [ -f "$CONFIG" ] ; then + . "$CONFIG" fi ups_stop () { pkill -n upsmon pkill -n upsd - ${NUT_DIR}/sbin/upsdrvctl stop > /dev/null 2>&1 + LD_LIBRARY_PATH="${NUT_LIB_DIR}:$LD_LIBRARY_PATH" "${NUT_SBIN_DIR}/upsdrvctl" stop > /dev/null 2>&1 } ups_start () { if [ "$MODE" = "none" ];then - echo No mode set + echo "No NUT mode set, not starting anything" >&2 exit 1 fi - if [ ! "$MODE" = "netclient" ];then - $NUT_DIR/sbin/upsdrvctl start #> /dev/null 2>&1 - $NUT_DIR/sbin/upsd #> /dev/null 2>&1 + if [ "$MODE" != "netclient" ] ; then + LD_LIBRARY_PATH="${NUT_LIB_DIR}:$LD_LIBRARY_PATH" "${NUT_SBIN_DIR}/upsdrvctl" start #> /dev/null 2>&1 + LD_LIBRARY_PATH="${NUT_LIB_DIR}:$LD_LIBRARY_PATH" "${NUT_SBIN_DIR}/upsd" #> /dev/null 2>&1 fi - $NUT_DIR/sbin/upsmon #> /dev/null 2>&1 + LD_LIBRARY_PATH="${NUT_LIB_DIR}:$LD_LIBRARY_PATH" "${NUT_SBIN_DIR}/upsmon" #> /dev/null 2>&1 } case $1 in @@ -46,10 +48,11 @@ case $1 in ups_start ;; 'poweroff') - $NUT_DIR/sbin/upsmon -K >/dev/null 2>&1 + LD_LIBRARY_PATH="${NUT_LIB_DIR}:$LD_LIBRARY_PATH" "${NUT_SBIN_DIR}/upsmon" -K >/dev/null 2>&1 if [ $? = 0 ]; then - echo "Shutting down the UPS ..." - #$NUT_DIR/sbin/upsdrvctl shutdown + echo "Shutting down the UPS(es) ..." + echo "WARNING: UPS shutdown is currently disabled, please uncomment it in the init-script if desired" >&2 + #${NUT_SBIN_DIR}/upsdrvctl shutdown fi ;; *) @@ -57,7 +60,7 @@ case $1 in echo "Usage: '$0' {start | stop | restart }" echo "" exit 64 - ;; + ;; esac exit $? diff --git a/scripts/Solaris/nut.xml.in b/scripts/Solaris/nut.xml.in new file mode 100644 index 0000000000..b06b2b151c --- /dev/null +++ b/scripts/Solaris/nut.xml.in @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scripts/Solaris/pkginfo.in b/scripts/Solaris/pkginfo.in index d99bdbec53..39667f0a79 100644 --- a/scripts/Solaris/pkginfo.in +++ b/scripts/Solaris/pkginfo.in @@ -1,6 +1,6 @@ PKG="NUT" NAME="Network UPS Tools" -ARCH="@OS_NAME@" +ARCH="@target_cpu@" VERSION="@PACKAGE_VERSION@" CATEGORY="application" VENDOR="http://www.networkupstools.org" diff --git a/scripts/Solaris/postinstall.in b/scripts/Solaris/postinstall.in old mode 100644 new mode 100755 index 136e07719c..31b9567458 --- a/scripts/Solaris/postinstall.in +++ b/scripts/Solaris/postinstall.in @@ -1,65 +1,126 @@ #!/bin/sh -#Postinstall script +# Postinstall script for Network UPS Tools package NUT_DIR="@prefix@" +prefix="@prefix@" # expanded as part of some autoconf macros below + +# TODO/FIXME : Should "/var/run" be a configure variable? +# Note that "/var/run" is transient tmpfs, so upgrade has to be done during same uptime. +ACTIVE_ENUMERATOR_FMRI_FILE="/var/run/nut-driver-enumerator-fmri.prev" # make sure the nut user exists and has correct memberships -res=`getent group nut` +res="`getent group @RUN_AS_GROUP@`" || res="" if [ -z "$res" ]; then - groupadd nut + /usr/sbin/groupadd "@RUN_AS_GROUP@" fi -res=`getent passwd nut` +res="`getent passwd @RUN_AS_USER@`" || res="" if [ -z "$res" ]; then - useradd -g nut -G root -d ${NUT_DIR}/bin nut + /usr/sbin/useradd -c "Network UPS Tools" -g "@RUN_AS_GROUP@" -G root -d "@STATEPATH@" -s /bin/false @RUN_AS_USER@ fi -res=`groups nut | grep -w nut` +res="`groups "@RUN_AS_GROUP@" | grep -w "@RUN_AS_USER@"`" || res="" if [ -z "$res" ]; then - usermod -g nut -G root nut + /usr/sbin/usermod -g "@RUN_AS_GROUP@" -G root "@RUN_AS_USER@" fi # make sure that conffiles are secured and have the correct ownerships -if [ -d @CONFPATH@ ] ; then - chown root:nut @CONFPATH@ +if [ -d "@CONFPATH@" ] ; then + chown "root:@RUN_AS_GROUP@" "@CONFPATH@" fi -for file in nut.conf ups.conf upsd.conf upsmon.conf upsd.users upssched.conf; do - if [ -f @CONFPATH@/$file ] ; then - chown root:nut @CONFPATH@/$file - chmod 640 @CONFPATH@/$file +for file in nut.conf ups.conf upsd.conf upsmon.conf upsd.users upssched.conf nut-driver-enumerator.conf; do + if [ -f "@CONFPATH@/$file" ] ; then + chown "root:@RUN_AS_GROUP@" "@CONFPATH@/$file" + chmod 640 "@CONFPATH@/$file" fi done # make sure that /var/run/nut exists and has the correct ownerships -if [ ! -d @PIDPATH@/nut ] ; then - mkdir -p @PIDPATH@/nut +if [ ! -d "@PIDPATH@/nut" ] ; then + mkdir -p "@PIDPATH@/nut" fi -if [ -d @PIDPATH@/nut ] ; then - chown root:nut @PIDPATH@/nut - chmod 770 @PIDPATH@/nut +if [ -d "@PIDPATH@/nut" ] ; then + chown "root:@RUN_AS_GROUP@" "@PIDPATH@/nut" + chmod 770 "@PIDPATH@/nut" fi # make sure that /var/state/ups exists and has the correct ownerships -if [ ! -d @STATEPATH@ ] ; then - mkdir -p @STATEPATH@ +if [ ! -d "@STATEPATH@" ] ; then + mkdir -p "@STATEPATH@" fi -if [ -d @STATEPATH@ ] ; then - chown root:nut @STATEPATH@ - chmod 770 @STATEPATH@ +if [ -d "@STATEPATH@" ] ; then + chown "root:@RUN_AS_GROUP@" "@STATEPATH@" + chmod 770 "@STATEPATH@" fi -# Put init script in /etc/init.d - -cp $NUT_DIR/nut /etc/init.d -chmod 744 /etc/init.d/nut +if [ -n "@auglensdir@" ] && [ -d "@auglensdir@" ] && [ -d "@datadir@/augeas-lenses" ] ; then + ( cd "@datadir@/augeas-lenses" && cp -prf ./ "@auglensdir@"/ ) +fi -ln -s /etc/init.d/nut /etc/rc3.d/S100nut > /dev/null 2>&1 -ln -s /etc/init.d/nut /etc/rc3.d/K100nut > /dev/null 2>&1 +if test -x /usr/sbin/svcadm && test -x /usr/sbin/svccfg && test -x /usr/bin/svcs ; then + echo "Register SMF services..." + for S in nut-driver-enumerator nut-driver nut-server nut-monitor nut ; do + echo "Importing NUT service manifest: $S..." + /usr/sbin/svccfg import "@datadir@/solaris-smf/manifest/$S.xml" + done + # Enable services if the system already has a configuration (e.g. upgrade) + if test -s "@CONFPATH@/ups.conf" ; then + echo "Stopping NUT drivers, if any (in case of upgrade)..." + @SBINDIR@/upsdrvsvcctl stop + @SBINDIR@/upsdrvctl -DDDDD stop + sleep 5 + echo "(Re-)register NUT drivers (if any)..." + REPORT_RESTART_42=no AUTO_START=no "@NUT_LIBEXECDIR@/nut-driver-enumerator.sh" --reconfigure + sleep 2 + echo "Enable NUT drivers (if any)..." + # Note: we now provide two services, a daemon that keeps checking + # the config for changes and a default one that should be refreshed + # manually to reconfigure nut-driver instances - and is "cheaper". + # This may still fail if the daemon instance is somehow enabled (admin) + PREV_ACTIVE_ENUMERATOR="" + if test -s "${ACTIVE_ENUMERATOR_FMRI_FILE}" ; then + PREV_ACTIVE_ENUMERATOR="`head -1 "${ACTIVE_ENUMERATOR_FMRI_FILE}"`" + fi + [ x"nut-driver-enumerator:default" = x"${PREV_ACTIVE_ENUMERATOR}" ] && PREV_ACTIVE_ENUMERATOR="" + for ACTIVE_ENUMERATOR in ${PREV_ACTIVE_ENUMERATOR} nut-driver-enumerator:default ; do + /usr/sbin/svcadm enable -s ${ACTIVE_ENUMERATOR} || \ + { /usr/sbin/svcadm clear ${ACTIVE_ENUMERATOR} 2>/dev/null ; \ + /usr/sbin/svcadm enable -s ${ACTIVE_ENUMERATOR} ; } && break || true + done + @SBINDIR@/upsdrvsvcctl start + else + echo "NOT ENABLING nut-driver-enumerator at this time : missing or empty @CONFPATH@/ups.conf" >&2 + fi + if test -s "@CONFPATH@/ups.conf" && test -e "@CONFPATH@/upsd.conf" && test -e "@CONFPATH@/upsd.users" ; then + # Note on the mix of "-s" and "-e" in tests above: + # it is a valid use-case for an admin to have just touched an + # empty upsd.conf and so use default settings for the daemon + echo "Enable NUT upsd data server..." + /usr/sbin/svcadm enable -s nut-server + else + echo "NOT ENABLING nut-server at this time : missing at least one of : @CONFPATH@/ups.conf @CONFPATH@/upsd.conf @CONFPATH@/upsd.users" >&2 + fi + if test -s "@CONFPATH@/upsmon.conf" ; then + echo "Enable NUT upsmon client..." + /usr/sbin/svcadm enable -s nut-monitor + else + echo "NOT ENABLING nut-monitor at this time : missing or empty @CONFPATH@/upsmon.conf" >&2 + fi + echo "Enable NUT umbrella service..." + /usr/sbin/svcadm enable -s nut +else + echo "Put init script in /etc/init.d..." + cp -pf "@NUT_DATADIR@/solaris-init/nut" /etc/init.d + chown root:bin /etc/init.d/nut + chmod 744 /etc/init.d/nut -# Start nut services + ln -s ../init.d/nut /etc/rc3.d/S90nut > /dev/null 2>&1 + ln -s ../init.d/nut /etc/rc3.d/K10nut > /dev/null 2>&1 -#echo "Starting nut services" -#$NUT_DIR/sbin/upsdrvctl start #> /dev/null 2>&1 -#$NUT_DIR/sbin/upsd #> /dev/null 2>&1 -#$NUT_DIR/sbin/upsmon #> /dev/null 2>&1 + # Start nut services + #echo "Starting nut services" + #$NUT_DIR/sbin/upsdrvctl start #> /dev/null 2>&1 + #$NUT_DIR/sbin/upsd #> /dev/null 2>&1 + #$NUT_DIR/sbin/upsmon #> /dev/null 2>&1 +fi diff --git a/scripts/Solaris/postremove b/scripts/Solaris/postremove deleted file mode 100755 index 99a0842bc3..0000000000 --- a/scripts/Solaris/postremove +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh - -# Remove nut group and user - -/usr/sbin/userdel nut - -/usr/sbin/groupdel nut - -# Remove init script from /etc/init.d - -rm /etc/init.d/nut -rm /etc/rc3.d/S100nut -rm /etc/rc3.d/K100nut - diff --git a/scripts/Solaris/postremove.in b/scripts/Solaris/postremove.in new file mode 100755 index 0000000000..dce3f44e84 --- /dev/null +++ b/scripts/Solaris/postremove.in @@ -0,0 +1,19 @@ +#!/bin/sh + +# Postremove script for Network UPS Tools package + +# Remove init script from /etc/init.d - created by scripts not packaging + +rm -f /etc/init.d/nut +rm -f /etc/rc3.d/S90nut +rm -f /etc/rc3.d/K10nut + +# Remove nut group and user + +/usr/sbin/userdel "@RUN_AS_USER@" + +/usr/sbin/groupdel "@RUN_AS_GROUP@" + +# Remove /var/run/nut + +rm -rf "@PIDPATH@/nut" diff --git a/scripts/Solaris/preinstall b/scripts/Solaris/preinstall deleted file mode 100755 index a63ade7c5f..0000000000 --- a/scripts/Solaris/preinstall +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh - -# Create group nut - -grep -w "nut" /etc/group -if [ $? -eq 1 ]; then - /usr/sbin/groupadd nut -fi - -# Create user for installing "Network UPS Tools" - -grep -w "nut" /etc/passwd -if [ $? -eq 1 ]; then - /usr/sbin/useradd -c "Network UPS Tools" -d /export/home/nut -m nut -fi diff --git a/scripts/Solaris/preinstall.in b/scripts/Solaris/preinstall.in new file mode 100755 index 0000000000..42da1ceaf6 --- /dev/null +++ b/scripts/Solaris/preinstall.in @@ -0,0 +1,23 @@ +#!/bin/sh + +# Preinstall script for Network UPS Tools package +NUT_DIR="@prefix@" + +# Create group nut + +grep -w "@RUN_AS_GROUP@" /etc/group +if [ "$?" != 0 ]; then + /usr/sbin/groupadd "@RUN_AS_GROUP@" +fi + +# Create user for installing "Network UPS Tools" + +grep -w "@RUN_AS_USER@" /etc/passwd +if [ "$?" != 0 ]; then + /usr/sbin/useradd -c "Network UPS Tools" -g "@RUN_AS_GROUP@" -G root -d "@STATEPATH@" -s /bin/false "@RUN_AS_USER@" +fi + +res="`groups "@RUN_AS_GROUP@" | grep -w "@RUN_AS_USER@"`" || res="" +if [ -z "$res" ]; then + /usr/sbin/usermod -g "@RUN_AS_GROUP@" -G root "@RUN_AS_USER@" +fi diff --git a/scripts/Solaris/prepackage.py b/scripts/Solaris/prepackage.py deleted file mode 100755 index f8d987b36b..0000000000 --- a/scripts/Solaris/prepackage.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env python - -import sys -import commands - -# checkinstall script creation - -platform = commands.getoutput('uname -s') -architecture = commands.getoutput('uname -p') - -fp=open("checkinstall","w") -fp.write("#!/bin/sh\n") -fp.write("\nexpected_platform=SunOS\n") -if platform == "SunOS" and architecture == "i386": - fp.write("expected_architecture=i386\n") -elif platform == "SunOS" and architecture == "sparc": - fp.write("expected_architecture=sparc\n") - -fp.write("platform=`uname -s`\n") -fp.write("architecture=`uname -p`\n\n") - -fp.write("if [ ${platform} -eq ${expected_platform} ]; then\n") -fp.write("\tif [ ${architecture} -eq ${expected_architecture} ]; then\n") -fp.write("\t\techo \"Checkinstall complete\"\n") -fp.write("\telse\n") -fp.write("\t\techo \"This is not Solaris $architecture machine\"\n") -fp.write("\t\texit 1\n") -fp.write("\tfi\n") -fp.write("else\n") -fp.write("\techo \"This is not Solaris machine\"\n") -fp.write("\texit 1\n") -fp.write("fi\n") -fp.write("exit 0\n") - -fp.close() - - diff --git a/scripts/Solaris/preproto.pl b/scripts/Solaris/preproto.pl.in similarity index 86% rename from scripts/Solaris/preproto.pl rename to scripts/Solaris/preproto.pl.in index 5068859704..ac52c16b29 100755 --- a/scripts/Solaris/preproto.pl +++ b/scripts/Solaris/preproto.pl.in @@ -8,6 +8,8 @@ $postinstall = "postinstall"; $preremove = "preremove"; $postremove = "postremove"; +$nutuser = "@RUN_AS_USER@"; +$nutgroup = "@RUN_AS_GROUP@"; open (PREPROTO,"< $temp") || die "Unable to read prototype information ($!)\n"; open (PROTO,"> $prototype") || die "Unable to write file prototype ($!)\n"; @@ -26,12 +28,12 @@ } elsif ($thisline =~ "^[fd] ") { # Change the ownership for files and directories ($dir, $none, $file, $mode, $user, $group) = split / /,$thisline; - print PROTO "$dir $none $file=$file $mode nut nut\n"; + print PROTO "$dir $none $file=$file $mode $nutuser $nutgroup\n"; } else { # Symlinks and other stuff should be printed as well ofcourse print PROTO "$thisline\n"; } } -print PROTO "f $none nut $mode root nut\n"; +#print PROTO "f $none nut $mode root $nutgroup\n"; close PROTO; close PREPROTO; diff --git a/scripts/Solaris/preremove.in b/scripts/Solaris/preremove.in old mode 100644 new mode 100755 index dc4a1a19b7..28023cadbe --- a/scripts/Solaris/preremove.in +++ b/scripts/Solaris/preremove.in @@ -1,8 +1,71 @@ -#!bin/sh +#!/bin/sh + +# Preremove script for Network UPS Tools package # Stop all nut services NUT_DIR="@prefix@" +prefix="@prefix@" # expanded as part of some autoconf macros below + +# TODO/FIXME : Should "/var/run" be a configure variable? +# Note that "/var/run" is transient tmpfs, so upgrade has to be done during same uptime. +ACTIVE_ENUMERATOR_FMRI_FILE="/var/run/nut-driver-enumerator-fmri.prev" -#$NUT_DIR/sbin/upsdrvctl stop +if test -x /usr/sbin/svcadm && test -x /usr/sbin/svccfg && test -x /usr/bin/svcs ; then + # Unconfigure SMF services + # First detect the first active (online, maintenance, etc.) + # instance of nut-driver-enumerator so we can pass it to the + # next lifetime in case of re-install of NUT and keep the + # user's previously declared preference. + ACTIVE_ENUMERATOR="`/usr/bin/svcs -H -o state,fmri '*/nut-driver-enumerator:*' | while read S F ; do [ "$S" != "disabled" ] && [ "$S" != "offline" ] && echo "$F" && break ; done`" + if [ -n "$ACTIVE_ENUMERATOR" ]; then + rm -f "${ACTIVE_ENUMERATOR_FMRI_FILE}" + touch "${ACTIVE_ENUMERATOR_FMRI_FILE}" + chmod 600 "${ACTIVE_ENUMERATOR_FMRI_FILE}" + chown 0:0 "${ACTIVE_ENUMERATOR_FMRI_FILE}" + echo "${ACTIVE_ENUMERATOR}" > "${ACTIVE_ENUMERATOR_FMRI_FILE}" + fi + # First tell the automagic to stop, so it does not interfere; diligently clean it out below + /usr/sbin/svcadm disable nut-driver-enumerator:default || true + /usr/sbin/svcadm disable nut-driver-enumerator:daemon || true + for S in nut nut-monitor nut-server ; do + echo "Stopping NUT service: $S..." + /usr/sbin/svcadm clear "$S" 2>/dev/null + /usr/sbin/svcadm disable -s "$S" + echo "Removing NUT service: $S..." + /usr/sbin/svccfg delete "$S" || \ + /usr/sbin/svccfg -s "$S" delete || \ + /usr/sbin/svccfg -s "$S" delete default + done + echo "Stopping NUT drivers, if any..." + @SBINDIR@/upsdrvsvcctl stop + @SBINDIR@/upsdrvctl -DDDDD stop + sleep 5 + for S in `/usr/bin/svcs -H -o fmri '*/nut-driver:*'` `/usr/bin/svcs -H -o fmri '*/nut-driver-enumerator:*'` ; do + echo "Stopping NUT service: $S..." + /usr/sbin/svcadm clear "$S" 2>/dev/null + /usr/sbin/svcadm disable -s "$S" + done + sleep 5 + for S in `/usr/bin/svcs -H -o fmri '*/nut-driver:*' | grep -wv default` `/usr/bin/svcs -H -o fmri '*/nut-driver-enumerator:*' | grep -wv default` ; do + echo "Removing NUT service: $S..." + # Note: S here is a full FMRI URL + SB="`echo "$S" | sed 's,:[^:]*$,,'`" + SI="`echo "$S" | sed 's,^.*:\([^:]*\)$,\1,'`" + /usr/sbin/svcadm disable -s "$S" + /usr/sbin/svccfg -s "$SB" delete -f "$SI" || \ + /usr/sbin/svccfg delete "$S" + done + for S in nut-driver-enumerator nut-driver ; do + echo "Removing NUT service: $S..." && \ + /usr/sbin/svccfg delete "$S" || \ + /usr/sbin/svccfg -s "$S" delete || \ + /usr/sbin/svccfg -s "$S" delete default + done +else + [ -x /etc/init.d/nut ] && /etc/init.d/nut stop +fi +if [ -n "@auglensdir@" ] && [ -d "@auglensdir@" ] && [ -d "@datadir@/augeas-lenses" ] ; then + ( cd "@datadir@/augeas-lenses" && find . -type f -exec rm -f "@auglensdir@"/'{}' \; ) +fi diff --git a/scripts/Solaris/svc-nut-monitor.in b/scripts/Solaris/svc-nut-monitor.in new file mode 100755 index 0000000000..a7dd0dc91d --- /dev/null +++ b/scripts/Solaris/svc-nut-monitor.in @@ -0,0 +1,56 @@ +#!/sbin/sh + +# Trivial (better is yet to come) SMF method script to start nut services +# Adapted for OpenIndiana userland from init.d script template in NUT sources +# Adaptation copyright (C) 2016-2017 Jim Klimov + +if [ -z "$SMF_FMRI" ]; then + echo "$0 must be called in SMF context!" >&2 + exit 1 +fi + +# smf(5) +. /lib/svc/share/smf_include.sh || exit + +prefix="@prefix@" +NUT_DIR="@prefix@" +NUT_SBIN_DIR="${NUT_DIR}/sbin" +NUT_LIB_DIR="${NUT_DIR}/lib" +NUT_RUN_DIR="@PIDPATH@/nut" +CONFIG="@CONFPATH@/nut.conf" +NUTUSER="@RUN_AS_USER@" +NUTGROUP="@RUN_AS_GROUP@" + +if [ -f "$CONFIG" ] ; then + . "$CONFIG" +fi + +ups_start () { + if [ "$MODE" = "none" ];then + echo "No NUT mode set, not starting anything" >&2 + exit $SMF_EXIT_ERR_CONFIG + fi + + # Default rights inspired by NUT scripts/Solaris/postinstall.in + mkdir -p "$NUT_RUN_DIR" && \ + chown "root:$NUTGROUP" "$NUT_RUN_DIR" && \ + chmod 770 "$NUT_RUN_DIR" \ + || exit $SMF_EXIT_ERR_FATAL + + LD_LIBRARY_PATH="${NUT_LIB_DIR}:$LD_LIBRARY_PATH" "${NUT_SBIN_DIR}"/upsmon #> /dev/null 2>&1 +} + +case "$1" in +'start') + ups_start + ;; + +*) + echo "" + echo "Usage: '$0' {start}" + echo "" + exit $SMF_EXIT_ERR_CONFIG + ;; +esac + +exit $? diff --git a/scripts/Solaris/svc-nut-server.in b/scripts/Solaris/svc-nut-server.in new file mode 100755 index 0000000000..5fee9c1802 --- /dev/null +++ b/scripts/Solaris/svc-nut-server.in @@ -0,0 +1,64 @@ +#!/sbin/sh + +# Trivial (better is yet to come) SMF method script to start nut services +# Adapted for OpenIndiana userland from init.d script template in NUT sources +# Adaptation copyright (C) 2016 Jim Klimov + +if [ -z "$SMF_FMRI" ]; then + echo "$0 must be called in SMF context!" >&2 + exit 1 +fi + +# smf(5) +. /lib/svc/share/smf_include.sh || exit + +prefix="@prefix@" +NUT_DIR="@prefix@" +NUT_SBIN_DIR="$NUT_DIR/sbin" +NUT_LIB_DIR="${NUT_DIR}/lib" +NUT_RUN_DIR="@PIDPATH@/nut" +CONFIG="@CONFPATH@/nut.conf" +NUTUSER="@RUN_AS_USER@" +NUTGROUP="@RUN_AS_GROUP@" + +if [ -f "$CONFIG" ] ; then + . "$CONFIG" +fi + +ups_start () { + # Default rights inspired by NUT scripts/Solaris/postinstall.in + mkdir -p "$NUT_RUN_DIR" && \ + chown "root:$NUTGROUP" "$NUT_RUN_DIR" && \ + chmod 770 "$NUT_RUN_DIR" \ + || exit $SMF_EXIT_ERR_FATAL + + if [ "$MODE" = "none" ];then + echo "No NUT mode set, not starting anything" >&2 + exit 1 + fi + + if [ "$MODE" != "netclient" ] ; then + # In this distribution, UPS drivers are wrapped by service instances + #LD_LIBRARY_PATH="${NUT_LIB_DIR}:$LD_LIBRARY_PATH" "${NUT_SBIN_DIR}/upsdrvctl" start #> /dev/null 2>&1 + LD_LIBRARY_PATH="${NUT_LIB_DIR}:$LD_LIBRARY_PATH" "${NUT_SBIN_DIR}/upsd" #> /dev/null 2>&1 + fi +} + +case "$1" in +'start') + ups_start + ;; + +'refresh'|'reload') + LD_LIBRARY_PATH="${NUT_LIB_DIR}:$LD_LIBRARY_PATH" "${NUT_SBIN_DIR}/upsd" -c reload + ;; + +*) + echo "" + echo "Usage: '$0' {start}" + echo "" + exit $SMF_EXIT_ERR_CONFIG + ;; +esac + +exit $? diff --git a/scripts/augeas/Makefile.am b/scripts/augeas/Makefile.am index 942849ba9b..db304fbd0c 100644 --- a/scripts/augeas/Makefile.am +++ b/scripts/augeas/Makefile.am @@ -15,6 +15,15 @@ dist-hook: echo "----------------------------------------------------------------------"; \ fi +# This needs augparse from augeas-tools +if HAVE_AUGPARSE +check-local: + @echo "augparse proceeding to lenses verification job..."; \ + echo "DISABLED for now due to https://github.com/networkupstools/nut/issues/657" +endif +# FIXME +# augparse -I $(srcdir)/ $(srcdir)/tests/test_nut.aug + if WITH_AUGLENS # Now "make install" should cover delivery of Augeas lenses... # The "auglensdir" value should be set up by configure diff --git a/scripts/augeas/nutupsdconf.aug.in b/scripts/augeas/nutupsdconf.aug.in index d3aef1d300..35bf896f09 100644 --- a/scripts/augeas/nutupsdconf.aug.in +++ b/scripts/augeas/nutupsdconf.aug.in @@ -39,6 +39,8 @@ let comment = Util.comment let path = word let upsd_maxage = [ opt_spc . key "MAXAGE" . sep_spc . store num . eol ] +let upsd_trackingdelay = [ opt_spc . key "TRACKINGDELAY" . sep_spc . store num . eol ] +let upsd_allow_no_device = [ opt_spc . key "ALLOW_NO_DEVICE" . sep_spc . store num . eol ] let upsd_statepath = [ opt_spc . key "STATEPATH" . sep_spc . store path . eol ] let upsd_listen = [ opt_spc . key "LISTEN" . sep_spc . [ label "interface" . store ip ] @@ -49,13 +51,15 @@ let upsd_certfile = [ opt_spc . key "CERTFILE" . sep_spc . store path . eol ] (************************************************************************ * MAXAGE seconds + * TRACKINGDELAY seconds + * ALLOW_NO_DEVICE Boolean * STATEPATH path * LISTEN interface port * Multiple LISTEN addresses may be specified. The default is to bind to 0.0.0.0 if no LISTEN addresses are specified. * LISTEN 127.0.0.1 LISTEN 192.168.50.1 LISTEN ::1 LISTEN 2001:0db8:1234:08d3:1319:8a2e:0370:7344 * *************************************************************************) -let upsd_other = upsd_maxage | upsd_statepath | upsd_listen_list | upsd_maxconn | upsd_certfile +let upsd_other = upsd_maxage | upsd_trackingdelay | upsd_allow_no_device | upsd_statepath | upsd_listen_list | upsd_maxconn | upsd_certfile let upsd_lns = (upsd_other|comment|empty)* diff --git a/scripts/augeas/tests/test_nut.aug b/scripts/augeas/tests/test_nut.aug index 4153ed7cf5..5f368620ec 100644 --- a/scripts/augeas/tests/test_nut.aug +++ b/scripts/augeas/tests/test_nut.aug @@ -27,6 +27,8 @@ test NutUpsConf.ups_lns get ups_conf = let upsd_conf = " MAXAGE 30 +TRACKINGDELAY 600 +ALLOW_NO_DEVICE 1 LISTEN 0.0.0.0 3493 MAXCONN 1024 " @@ -34,6 +36,8 @@ MAXCONN 1024 test NutUpsdConf.upsd_lns get upsd_conf = { } { "MAXAGE" = "30" } + { "TRACKINGDELAY" = "600" } + { "ALLOW_NO_DEVICE" = "1" } { "LISTEN" { "interface" = "0.0.0.0" } { "port" = "3493" } } diff --git a/scripts/python/Makefile.am b/scripts/python/Makefile.am index 03267257de..7b6eed0e11 100644 --- a/scripts/python/Makefile.am +++ b/scripts/python/Makefile.am @@ -5,7 +5,10 @@ EXTRA_DIST = README \ app/NUT-Monitor \ app/nut-monitor.appdata.xml \ app/nut-monitor.desktop \ - app/nut-monitor.png \ + app/icons/48x48/nut-monitor.png \ + app/icons/64x64/nut-monitor.png \ + app/icons/256x256/nut-monitor.png \ + app/icons/scalable/nut-monitor.svg \ app/README \ app/pixmaps/var-rw.png \ app/pixmaps/on_line.png \ diff --git a/scripts/python/app/NUT-Monitor b/scripts/python/app/NUT-Monitor index 3c4bec4a90..f4b9ce1065 100755 --- a/scripts/python/app/NUT-Monitor +++ b/scripts/python/app/NUT-Monitor @@ -491,7 +491,7 @@ class interface(object): self.gui_status_message(error_msg) except: - # Failed to get informations from the treeview... skip action + # Failed to get information from the treeview... skip action pass # ------------------------------------------------------------------- @@ -816,7 +816,7 @@ class gui_updater(threading.Thread): self.__parent_class.gui_status_notification(_("Device is running on batteries"), "on_battery.png") was_online = False - # Check for additionnal informations + # Check for additional information for k, v in status_mapper.items(): if vars_.get("ups.status").find(k) != -1: if text_right != "": diff --git a/scripts/python/app/icons/256x256/nut-monitor.png b/scripts/python/app/icons/256x256/nut-monitor.png new file mode 100644 index 0000000000..15f472a5bd Binary files /dev/null and b/scripts/python/app/icons/256x256/nut-monitor.png differ diff --git a/scripts/python/app/nut-monitor.png b/scripts/python/app/icons/48x48/nut-monitor.png similarity index 100% rename from scripts/python/app/nut-monitor.png rename to scripts/python/app/icons/48x48/nut-monitor.png diff --git a/scripts/python/app/icons/64x64/nut-monitor.png b/scripts/python/app/icons/64x64/nut-monitor.png new file mode 100644 index 0000000000..9d92284791 Binary files /dev/null and b/scripts/python/app/icons/64x64/nut-monitor.png differ diff --git a/scripts/python/app/icons/scalable/nut-monitor.svg b/scripts/python/app/icons/scalable/nut-monitor.svg new file mode 100644 index 0000000000..c04656270e --- /dev/null +++ b/scripts/python/app/icons/scalable/nut-monitor.svg @@ -0,0 +1,490 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + Lapo Calamandrei + + + Battery + + + battery + recharge + power + acpi + apm + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scripts/python/app/locale/ru/LC_MESSAGES/NUT-Monitor.mo b/scripts/python/app/locale/ru/LC_MESSAGES/NUT-Monitor.mo new file mode 100644 index 0000000000..89ee020832 Binary files /dev/null and b/scripts/python/app/locale/ru/LC_MESSAGES/NUT-Monitor.mo differ diff --git a/scripts/python/app/locale/ru/ru.po b/scripts/python/app/locale/ru/ru.po new file mode 100644 index 0000000000..b163415e18 --- /dev/null +++ b/scripts/python/app/locale/ru/ru.po @@ -0,0 +1,420 @@ +# Russian translations for NUT-Monitor. +# Copyright (C) 2020 Alexey Rodionov (RED SOFT, Russia) +# This file is distributed under the same license as the NUT package. +# Alexey Rodionov , 2020 + +msgid "" +msgstr "" +"Project-Id-Version: NUT Monitor\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-10-15 20:35+0200\n" +"PO-Revision-Date: 2020-10-08 23:16+0300\n" +"Last-Translator: Alexey Rodionov \n" +"Language-Team: Russian\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: NUT-Monitor:150 +msgid "Var name" +msgstr "Параметр" + +#: NUT-Monitor:158 +msgid "Value" +msgstr "Значение" + +#: NUT-Monitor:205 +msgid "Welcome to NUT Monitor" +msgstr "Добро пожаловать в NUT Monitor" + +#: NUT-Monitor:304 +#, python-brace-format +msgid "Found {0} devices on {1}" +msgstr "Найдено {0} устройств на {1}" + +#: NUT-Monitor:307 NUT-Monitor:664 +#, python-brace-format +msgid "Error connecting to '{0}' ({1})" +msgstr "Ошибка подключения к '{0}' ({1})" + +#: NUT-Monitor:315 +msgid "Disconnecting from device" +msgstr "Отключение от устройства" + +#: NUT-Monitor:380 +msgid "Are you sure that you want to remove this favorite ?" +msgstr "Вы уверены, что хотите удалить эту закладку ?" + +#: NUT-Monitor:388 +#, python-format +msgid "Removed favorite '%s'" +msgstr "Закладка '%s' удалена" + +#: NUT-Monitor:414 +#, python-format +msgid "Loaded '%s'" +msgstr "Загружено '%s'" + +#: NUT-Monitor:422 +#, python-format +msgid "" +"Are you sure that you want to send\n" +"'%s' to the device ?" +msgstr "" +"Вы уверены, что хотите отправить\n" +"'%s' на устройство ?" + +#: NUT-Monitor:431 +#, python-brace-format +msgid "Sent '{0}' command to {1}" +msgstr "Отправлена команда '{0}' на {1}" + +#: NUT-Monitor:434 +#, python-brace-format +msgid "Failed to send '{0}' ({1})" +msgstr "Ошибка отправки '{0}' ({1})" + +#: NUT-Monitor:452 +#, python-brace-format +msgid "" +"Enter a new value for the variable.\n" +"\n" +"{0} = {1} (current value)" +msgstr "" +"Введите новое значение параметра.\n" +"\n" +"{0} = {1} (текущее значение)" + +#: NUT-Monitor:466 +#, python-format +msgid "Updated variable on %s" +msgstr "Обновлён параметр на %s" + +#: NUT-Monitor:474 +#, python-brace-format +msgid "Error updating variable on '{0}' ({1})" +msgstr "Ошибка обновления параметра на '{0}' ({1})" + +#: NUT-Monitor:479 +#, python-format +msgid "No variable modified on %s - User cancelled" +msgstr "Параметр на %s не изменён - отменено пользователем" + +#: NUT-Monitor:558 +#, python-format +msgid "" +"Error parsing favorites, password for '%s' is not in base64\n" +"Skipping password for this entry" +msgstr "" +"Ошибка разбора закладок, пароль для '%s' не в формате base64\n" +"Пропускаем пароль для этой записи" + +#: NUT-Monitor:567 +#, python-format +msgid "Error while parsing favorites file (%s)" +msgstr "Ошибка при разборе файла закладок (%s)" + +#: NUT-Monitor:578 +#, python-format +msgid "Error while creating configuration folder (%s)" +msgstr "Ошибка при создании каталога настроек (%s)" + +#: NUT-Monitor:590 +msgid "Saved favorites..." +msgstr "Закладки сохранены..." + +#: NUT-Monitor:593 +#, python-format +msgid "Error while saving favorites (%s)" +msgstr "Ошибка при сохранении закладок (%s)" + +#: NUT-Monitor:665 +#, python-brace-format +msgid "" +"Error connecting to '{0}'\n" +"{1}" +msgstr "" +"Ошибка подключения к '{0}'\n" +"{1}" + +#: NUT-Monitor:673 NUT-Monitor:674 +#, python-format +msgid "Device '%s' not found on server" +msgstr "Устройство '%s' не найдено на сервере" + +#: NUT-Monitor:708 +#, python-brace-format +msgid "Connected to '{0}' on {1}" +msgstr "Подключено к '{0}' на {1}" + +#: NUT-Monitor:740 +msgid "Not connected" +msgstr "Не подключено" + +#: NUT-Monitor:750 +#, python-format +msgid "Disconnected from '%s'" +msgstr "Отключено от '%s'" + +#: NUT-Monitor:772 +msgid "Low batteries" +msgstr "Низкий заряд" + +#: NUT-Monitor:773 +msgid "Replace batteries !" +msgstr "Замените батареи !" + +#: NUT-Monitor:774 +msgid "(no battery protection)" +msgstr "(нет защиты батареей)" + +#: NUT-Monitor:775 +msgid "Performing runtime calibration" +msgstr "Выполнение калибровки" + +#: NUT-Monitor:776 +msgid "Offline" +msgstr "Выключен" + +#: NUT-Monitor:776 +msgid "not providing power to the load" +msgstr "не обеспечено должного уровня питания для нагрузки" + +#: NUT-Monitor:777 +msgid "Overloaded !" +msgstr "Перегрузка !" + +#: NUT-Monitor:777 +msgid "there is too much load for device" +msgstr "слишком большая нагрузка на устройство" + +#: NUT-Monitor:778 +msgid "Triming (UPS is triming incoming voltage)" +msgstr "Отсечение (ИБП обрезает входящее напряжение)" + +#: NUT-Monitor:779 +msgid "Boost (UPS is boosting incoming voltage)" +msgstr "Повышение (ИБП повышает входящее напряжение)" + +#: NUT-Monitor:792 +msgid "Device status :" +msgstr "Статус устройства : " + +#: NUT-Monitor:795 +msgid "Online" +msgstr "От сети" + +#: NUT-Monitor:801 +msgid "On batteries" +msgstr "От батарей" + +#: NUT-Monitor:804 +msgid "Device is running on batteries" +msgstr "Устройство работает от батарей" + +#: NUT-Monitor:817 +msgid "discharging" +msgstr "разрядка" + +#: NUT-Monitor:819 +msgid "charging" +msgstr "зарядка" + +#: NUT-Monitor:825 +msgid "Model :" +msgstr "Модель : " + +#: NUT-Monitor:829 +msgid "Temperature :" +msgstr "Температура : " + +#: NUT-Monitor:833 +msgid "Battery voltage :" +msgstr "Напряжение батарей :" + +#: NUT-Monitor:844 gui-1.3.glade.h:11 +msgid "Battery charge :" +msgstr "Уровень заряда батарей : " + +#: NUT-Monitor:847 NUT-Monitor:856 NUT-Monitor:868 +msgid "Not available" +msgstr "Не доступно" + +#: NUT-Monitor:853 +msgid "UPS load :" +msgstr "Нагрузка ИБП :" + +#: NUT-Monitor:862 +msgid "%H hours %M minutes %S seconds" +msgstr "%H ч.%M мин. %S сек." + +#: NUT-Monitor:864 +msgid "%M minutes %S seconds" +msgstr "%M мин. %S сек." + +#: NUT-Monitor:866 +msgid "%M minutes %S seconds" +msgstr "%M мин. %S сек." + +#: NUT-Monitor:876 +#, python-brace-format +msgid "Error from '{0}' ({1})" +msgstr "Ошибка от '{0}' ({1})" + +#: NUT-Monitor:877 +#, python-brace-format +msgid "" +"Error from '{0}'\n" +"{1}" +msgstr "" +"Ошибка от '{0}'\n" +"{1}" + +#: gui-1.3.glade.h:1 +msgid "NUT Monitor" +msgstr "NUT Monitor" + +#: gui-1.3.glade.h:2 +msgid "_File" +msgstr "_Файл" + +#: gui-1.3.glade.h:3 +msgid "F_avorites" +msgstr "_Закладки" + +#: gui-1.3.glade.h:4 +msgid "Host / Port : " +msgstr "Хост / Порт : " + +#: gui-1.3.glade.h:5 +msgid "Device : " +msgstr "Устройство : " + +#: gui-1.3.glade.h:6 +msgid "None" +msgstr "Нет" + +#: gui-1.3.glade.h:7 +msgid "Use authentication" +msgstr "Аутентификация" + +#: gui-1.3.glade.h:8 +msgid "Login / Password : " +msgstr "Имя / Пароль : " + +#: gui-1.3.glade.h:9 +msgid " NUT Server " +msgstr " Сервер NUT " + +#: gui-1.3.glade.h:10 +msgid "label" +msgstr "метка" + +#: gui-1.3.glade.h:12 +msgid "Current load :" +msgstr "Текущая нагрузка :" + +#: gui-1.3.glade.h:13 +msgid "Remaining time :" +msgstr "Время автономной работы : " + +#: gui-1.3.glade.h:14 +msgid "N/A" +msgstr "N/A" + +#: gui-1.3.glade.h:15 +msgid "Device commands :" +msgstr "Команды устройства : " + +#: gui-1.3.glade.h:16 +msgid "Device status" +msgstr "Статус устройства" + +#: gui-1.3.glade.h:17 +msgid "Device vars" +msgstr "Параметры устройства" + +#: gui-1.3.glade.h:18 +msgid "" +"Enter a name for this favorite\n" +"\n" +"You cannot re-use a name from another entry\n" +msgstr "" +"Введите название для этой закладки\n" +"\n" +"Вы не можете повторно использовать имя другой закладки\n" + +#: gui-1.3.glade.h:22 +msgid "" +"\n" +"Please select the favorite that you\n" +"want to delete from list...\n" +msgstr "" +"\n" +"Укажите закладку, которую Вы\n" +"хотите удалить из списка...\n" + +#: gui-1.3.glade.h:26 +msgid "" +msgstr "<Нет>" + +#: gui-1.3.glade.h:27 +msgid "Enter a new value for the variable.\n" +msgstr "Введите новое значение параметра.\n" + +#: gui-1.3.glade.h:29 +msgid "Copyright (c) 2010 David Goncalves" +msgstr "Copyright (c) 2010 David Goncalves" + +#: gui-1.3.glade.h:30 +msgid "" +"GUI to manage devices connected a NUT server.\n" +"\n" +"For more information about NUT (Network UPS Tools)\n" +"please visit the author's website.\n" +"\n" +"http://www.networkupstools.org\n" +msgstr "" +"Графическая утилита управления устройствами, подключенными к серверу NUT.\n" +"\n" +"Для получения дополнительной информации о NUT (Network UPS Tools)\n" +"пожалуйста посетите веб-сайт проекта.\n" +"\n" +"http://www.networkupstools.org\n" + +#: gui-1.3.glade.h:37 +msgid "http://www.lestat.st" +msgstr "http://www.lestat.st" + +#: gui-1.3.glade.h:38 +msgid "" +"Copyright (C) 2010 David Goncalves \n" +"\n" +"This program is free software: you can redistribute it and/or modify\n" +"it under the terms of the GNU General Public License as published by\n" +"the Free Software Foundation; either version 3 of the License, or\n" +"(at your option) any later version.\n" +"\n" +"This program is distributed in the hope that it will be useful,\n" +"but WITHOUT ANY WARRANTY; without even the implied warranty of\n" +"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" +"GNU General Public License for more details.\n" +"\n" +"You should have received a copy of the GNU General Public License\n" +"along with this program. If not, see ." +msgstr "" +"Copyright (C) 2010 David Goncalves \n" +"\n" +"This program is free software: you can redistribute it and/or modify\n" +"it under the terms of the GNU General Public License as published by\n" +"the Free Software Foundation; either version 3 of the License, or\n" +"(at your option) any later version.\n" +"\n" +"This program is distributed in the hope that it will be useful,\n" +"but WITHOUT ANY WARRANTY; without even the implied warranty of\n" +"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" +"GNU General Public License for more details.\n" +"\n" +"You should have received a copy of the GNU General Public License\n" +"along with this program. If not, see ." diff --git a/scripts/python/app/nut-monitor.appdata.xml b/scripts/python/app/nut-monitor.appdata.xml index ba1d0b9720..da0f163b6c 100644 --- a/scripts/python/app/nut-monitor.appdata.xml +++ b/scripts/python/app/nut-monitor.appdata.xml @@ -1,7 +1,7 @@ - - nut-monitor.desktop + + nut-monitor.desktop CC0-1.0 GPL-3.0+ NUT Monitor @@ -32,11 +32,17 @@

- http://www.lestat.st/_media/informatique/projets/nut-monitor/nut-monitor-1.png - http://www.lestat.st/_media/informatique/projets/nut-monitor/nut-monitor-2.png - http://www.lestat.st/_media/informatique/projets/nut-monitor/nut-monitor-3.png + + https://www.lestat.st/_media/informatique/projets/nut-monitor/nut-monitor-1.png + + + https://www.lestat.st/_media/informatique/projets/nut-monitor/nut-monitor-2.png + + + https://www.lestat.st/_media/informatique/projets/nut-monitor/nut-monitor-3.png + - http://www.lestat.st/en/informatique/projets/nut-monitor - david@lestat.st + https://www.lestat.st/en/informatique/projets/nut-monitor + david@lestat.st -
+ diff --git a/scripts/python/app/nut-monitor.desktop b/scripts/python/app/nut-monitor.desktop index 4e698d2f86..b4ccf398ae 100644 --- a/scripts/python/app/nut-monitor.desktop +++ b/scripts/python/app/nut-monitor.desktop @@ -4,9 +4,8 @@ Name[fr]=Moniteur NUT Comment=Network UPS Tools GUI client Comment[fr]=Client graphique pour NUT (Network UPS Tools) Comment[it]=Client grafico per NUT (Network UPS Tools) -Categories=Application;Network; -Encoding=UTF-8 +Categories=System;Monitor;HardwareSettings;Settings;GTK Exec=NUT-Monitor -Icon=nut-monitor.png +Icon=nut-monitor Terminal=false Type=Application diff --git a/scripts/subdriver/gen-snmp-subdriver.sh b/scripts/subdriver/gen-snmp-subdriver.sh index 15702c0aa6..c2223659bf 100755 --- a/scripts/subdriver/gen-snmp-subdriver.sh +++ b/scripts/subdriver/gen-snmp-subdriver.sh @@ -3,13 +3,13 @@ # an auxiliary script to produce a "stub" snmp-ups subdriver from # SNMP data from a real agent or from dump files # -# Version: 0.6 +# Version: 0.11 # # See also: docs/snmp-subdrivers.txt # # Copyright (C) # 2011 - 2012 Arnaud Quette -# 2015 - 2016 Arnaud Quette +# 2015 - 2019 Arnaud Quette # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -26,37 +26,53 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # TODO: +# - Prepend sysDescription (.1.3.6.1.2.1.1.1.0) to have some more visibility # - extend to SNMP v3 (auth.) usage() { - echo "Usage: $0 [options] [file]" - echo "Options:" - echo " -h, --help -- show this message and quit" - echo " -n name -- subdriver name (use natural capitalization)" - echo " -M DIRLIST -- colon separated list of directories to also search for MIBs" - echo " -k -- keep temporary files (for debugging)" - echo "" - echo "mode 1: get SNMP data from a real agent" - echo " -H host_address -- SNMP host IP address or name" - echo " -c community -- SNMP v1 community name (default: public)" - echo " -s XXXX -- override SNMP OID entry point (sysOID). Ex: '.1.3.6.1.4.1.534.10'" - echo "" - echo "mode 2: get data from files (snmpwalk dumps of 'sysOID' subtree)" - echo " -s XXXX -- SNMP OID entry point (sysOID). Ex: '.1.3.6.1.4.1.534.6.6.7'" - echo " file1 file2 -- read from files instead of an host (using Net SNMP)" - echo " file1: numeric SNMP walk (snmpwalk -On ... )" - echo " file2: string SNMP walk (snmpwalk -Os ... )" - echo "" - echo "Notes:" - echo " For both modes, prefer to copy the specific MIB file(s) for your device in the $0 script directory" - echo " In such case, for mode 2, also add \"-M.\" to allow the name resolution of OIDs" - echo "" - echo "Example:" - echo "mode 1: $0 -H 192.168.0.1 -n mibname -c mycommunity" - echo "mode 2: (using sysOID .1.3.6.1.4.1.534.6.6.7)" - echo " snmpwalk -On -v1 -c mycommunity 192.168.0.1 .1.3.6.1.4.1.534.6.6.7 2>/dev/null 1> numeric-walk-file" - echo " snmpwalk -Os -v1 -m ALL -M+. -c mycommunity 192.168.0.1 .1.3.6.1.4.1.534.6.6.7 2>/dev/null 1> string-walk-file" - echo " $0 -s .1.3.6.1.4.1.534.6.6.7 numeric-walk-file string-walk-file" + echo "Usage: $0 [options] [file]" + echo "Options:" + echo " -h, --help -- show this message and quit" + echo " -n name -- subdriver name (use natural capitalization)" + echo " -M DIRLIST -- colon separated list of directories to also search for MIBs" + echo " -k -- keep temporary files (for debugging)" + echo "" + echo "mode 1: get SNMP data from a real agent" + echo " -H host_address -- SNMP host IP address or name" + echo " -c community -- SNMP v1 community name (default: public)" + echo " -s XXXX -- override SNMP OID entry point (sysOID). Ex: '.1.3.6.1.4.1.534.10'" + echo "" + echo "mode 2: get data from files (snmpwalk dumps of 'sysOID' subtree)" + echo " -s XXXX -- SNMP OID entry point (sysOID). Ex: '.1.3.6.1.4.1.534.6.6.7'" + echo " file1 file2 -- read from files instead of an host (using Net SNMP)" + echo " file1: numeric SNMP walk (snmpwalk -On ... )" + echo " file2: string SNMP walk (snmpwalk -Os ... )" + echo "" + echo "mode 3: get data from 1 file (numeric snmpwalk dump of the whole SNMP tree)" + echo " The sysOID is extracted from the dump, and only the pointed subtree is used" + echo " A MIB file MUST be provided, and is used to produce the string SNMP walk" + echo " file1 -- read from file instead of an host (using Net SNMP)" + echo " file1: numeric SNMP walk (snmpwalk -On ... )" + echo "" + + echo "Notes:" + echo " For both modes, prefer to copy the specific MIB file(s) for your device in the $0 script directory" + echo " So that it is automatically taken into account for the string name resolution of OIDs" + echo " Otherwise, use \"-M.\" option" + echo "" + echo "Example:" + echo "mode 1: $0 -H 192.168.0.1 -n mibname -c mycommunity" + echo "mode 2: (using sysOID .1.3.6.1.4.1.534.6.6.7)" + echo " snmpwalk -On -v1 -c mycommunity 192.168.0.1 .1.3.6.1.4.1.534.6.6.7 2>/dev/null 1> numeric-walk-file" + echo " snmpwalk -Os -v1 -m ALL -M+. -c mycommunity 192.168.0.1 .1.3.6.1.4.1.534.6.6.7 2>/dev/null 1> string-walk-file" + echo " $0 -s .1.3.6.1.4.1.534.6.6.7 numeric-walk-file string-walk-file" + echo "mode 3:" + echo " snmpwalk -On -v1 -c mycommunity 192.168.0.1 .1 2>/dev/null 1> numeric-walk-file" + echo " $0 numeric-walk-file" + echo "" + echo " You may alos need to install additional packages:" + echo " - 'snmp' package (on Debian) for the base commands (snmpget, snmpwalk, snmptranslate)" + echo " - 'snmp-mibs-downloader' package (on Debian) to get all standard MIBs" } # variables @@ -65,12 +81,14 @@ KEEP="" HOSTNAME="" MIBS_DIRLIST="+." COMMUNITY="public" +DEVICE_SYSOID="" SYSOID="" MODE=0 # constants NAME=gen-snmp-subdriver TMPDIR="${TEMPDIR:-/tmp}" +SYSOID_NUMBER=".1.3.6.1.2.1.1.2.0" DEBUG=`mktemp "$TMPDIR/$NAME-DEBUG.XXXXXX"` DFL_NUMWALKFILE=`mktemp "$TMPDIR/$NAME-NUMWALK.XXXXXX"` DFL_STRWALKFILE=`mktemp "$TMPDIR/$NAME-STRWALK.XXXXXX"` @@ -78,129 +96,331 @@ TMP_NUMWALKFILE=`mktemp "$TMPDIR/$NAME-TMP-NUMWALK.XXXXXX"` TMP_STRWALKFILE=`mktemp "$TMPDIR/$NAME-TMP-STRWALK.XXXXXX"` get_snmp_data() { - # 1) get the sysOID (points the mfr specif MIB), apart if there's an override - if [ -z "$SYSOID" ] - then - SYSOID=`snmpget -On -v1 -c $COMMUNITY -Ov $HOSTNAME .1.3.6.1.2.1.1.2.0 | cut -d' ' -f2` + # 1) get the sysOID (points the mfr specif MIB), apart if there's an override + if [ -z "$SYSOID" ] + then + SYSOID=`snmpget -On -v1 -c $COMMUNITY -Ov $HOSTNAME $SYSOID_NUMBER | cut -d' ' -f2` echo "sysOID retrieved: ${SYSOID}" else echo "Using the provided sysOID override ($SYSOID)" fi + DEVICE_SYSOID=$SYSOID + + OID_COUNT=0 + while (test $OID_COUNT -eq 0) + do + # 2) get the content of the mfr specif MIB + echo "Retrieving SNMP information. This may take some time" + snmpwalk -On -v1 -c $COMMUNITY $HOSTNAME $SYSOID 2>/dev/null 1> $DFL_NUMWALKFILE + snmpwalk -Os -v1 -m ALL -M$MIBS_DIRLIST -c $COMMUNITY $HOSTNAME $SYSOID 2>/dev/null 1> $DFL_STRWALKFILE + + # 3) test return value of the walk, and possibly ramp-up the path to get something. + # The sysOID mechanism only works if we're pointed somehow in the right direction + # i.e. doesn't work if sysOID is .1.3.6.1.4.1.705.1 and data is at .1.3.6.1.4.1.534... + # Ex: sysOID = ".1.X.Y.Z" + # try with ".1.X.Y.Z", if fails try with .1.X.Y", if fails try with .1.X"... + OID_COUNT="`cat $NUMWALKFILE | wc -l`" + if [ $OID_COUNT -eq 0 ]; then + # ramp-up the provided sysOID by removing the last .x part + SYSOID=${SYSOID%.*} + echo "Warning: sysOID provided no data! Trying with a level up using $SYSOID" + fi + done + return $OID_COUNT +} + +generate_C() { + # create file names + LDRIVER=`echo $DRIVER | tr A-Z a-z` + UDRIVER=`echo $DRIVER | tr a-z A-Z` + CFILE="$LDRIVER-mib.c" + HFILE="$LDRIVER-mib.h" + + #FIXME: LDRIVER & UDRIVER => replace - by _ + + # generate header file + echo "Creating $HFILE" + cat > "$HFILE" <<-EOF + /* ${HFILE} - subdriver to monitor ${DRIVER} SNMP devices with NUT + * + * Copyright (C) + * 2011 - 2016 Arnaud Quette + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + #ifndef ${UDRIVER}_MIB_H + #define ${UDRIVER}_MIB_H + + #include "main.h" + #include "snmp-ups.h" + + extern mib2nut_info_t ${LDRIVER}; + + #endif /* ${UDRIVER}_MIB_H */ + EOF + + # generate source file + # create header + echo "Creating $CFILE" + cat > "$CFILE" <<-EOF + /* ${CFILE} - subdriver to monitor ${DRIVER} SNMP devices with NUT + * + * Copyright (C) + * 2011 - 2016 Arnaud Quette + * + * Note: this subdriver was initially generated as a "stub" by the + * gen-snmp-subdriver script. It must be customized! + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + #include "${HFILE}" + + #define ${UDRIVER}_MIB_VERSION "0.1" + + #define ${UDRIVER}_SYSOID "${DEVICE_SYSOID}" + + /* To create a value lookup structure (as needed on the 2nd line of the example + * below), use the following kind of declaration, outside of the present snmp_info_t[]: + * static info_lkp_t onbatt_info[] = { + * { 1, "OB" }, + * { 2, "OL" }, + * { 0, NULL } + * }; + */ - # 2) get the content of the mfr specif MIB - # FIXME: test return value of the walk, and possibly ramp-up the path to get something. - # only works if we're pointed somehow in the right direction - # i.e. doesn't work if sysOID is .1.3.6.1.4.1.705.1 and data is at .1.3.6.1.4.1.534... - # Ex: sysOID = ".1.X.Y.Z" - # try with ".1.X.Y.Z", if fails try with .1.X.Y", if fails try with .1.X"... - echo "Retrieving SNMP information. This may take some time" - snmpwalk -On -v1 -c $COMMUNITY $HOSTNAME $SYSOID 2>/dev/null 1> $DFL_NUMWALKFILE - snmpwalk -Os -v1 -m ALL -M $MIBS_DIRLIST -c $COMMUNITY $HOSTNAME $SYSOID 2>/dev/null 1> $DFL_STRWALKFILE + /* ${UDRIVER} Snmp2NUT lookup table */ + static snmp_info_t ${LDRIVER}_mib[] = { + + /* Data format: + * { info_type, info_flags, info_len, OID, dfl, flags, oid2info }, + * + * info_type: NUT INFO_ or CMD_ element name + * info_flags: flags to set in addinfo + * info_len: length of strings if ST_FLAG_STRING, multiplier otherwise + * OID: SNMP OID or NULL + * dfl: default value + * flags: snmp-ups internal flags (FIXME: ...) + * oid2info: lookup table between OID and NUT values + * + * Example: + * { "input.voltage", 0, 0.1, ".1.3.6.1.4.1.705.1.6.2.1.2.1", "", SU_INPUT_1, NULL }, + * { "ups.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.705.1.7.3.0", "", SU_FLAG_OK | SU_STATUS_BATT, onbatt_info }, + * + * To create a value lookup structure (as needed on the 2nd line), use the + * following kind of declaration, outside of the present snmp_info_t[]: + * static info_lkp_t onbatt_info[] = { + * { 1, "OB" }, + * { 2, "OL" }, + * { 0, NULL } + * }; + */ + EOF + + # extract OID string paths, one by one + LINENB="0" + while IFS= read -r line; do + LINENB="`expr $LINENB + 1`" + FULL_STR_OID="$line" + STR_OID="`echo $line | cut -d'.' -f1`" + echo $line | grep STRING > /dev/null + if [ $? -eq 0 ]; then + ST_FLAG_TYPE="ST_FLAG_STRING" + SU_INFOSIZE="SU_INFOSIZE" + else + ST_FLAG_TYPE="0" + SU_INFOSIZE="1" + fi + # get the matching numeric OID + NUM_OID="`sed -n ${LINENB}p ${NUMWALKFILE} | cut -d' ' -f1`" + printf "\t/* ${FULL_STR_OID} */\n\t{ \"unmapped.${STR_OID}\", ${ST_FLAG_TYPE}, ${SU_INFOSIZE}, \"${NUM_OID}\", NULL, SU_FLAG_OK, NULL },\n" + done < ${STRWALKFILE} >> ${CFILE} + + # append footer + cat >> "$CFILE" <<-EOF + + /* end of structure. */ + { NULL, 0, 0, NULL, NULL, 0, NULL } + }; + + mib2nut_info_t ${LDRIVER} = { "${LDRIVER}", ${UDRIVER}_MIB_VERSION, NULL, NULL, ${LDRIVER}_mib, ${UDRIVER}_DEVICE_SYSOID }; + EOF } # process command line options while [ $# -gt 0 ]; do - if [ $# -gt 1 -a "$1" = "-n" ]; then - DRIVER="$2" - shift 2 - elif [ $# -gt 1 -a "$1" = "-M" ]; then - MIBS_DIRLIST="$MIBS_DIRLIST:$2" - shift 2 - elif [ "$1" = "-k" ]; then - KEEP=yes - shift - elif [ $# -gt 1 -a "$1" = "-H" ]; then - HOSTNAME="$2" - shift 2 - elif [ $# -gt 1 -a "$1" = "-c" ]; then - COMMUNITY="$2" - shift 2 - elif [ $# -gt 1 -a "$1" = "-s" ]; then - SYSOID="$2" - shift 2 - elif echo "$1" | grep -qv '^-'; then - if [ $# -gt 1 ]; then - NUMWALKFILE="$1" - shift - STRWALKFILE="$1" - shift - else - usage - exit 1 - fi - elif [ "$1" = "--help" -o "$1" = "-h" ]; then - usage - exit 0 - else - echo "Illegal option $1. Try --help for more info." >&2 - exit 1 - fi + if [ $# -gt 1 -a "$1" = "-n" ]; then + DRIVER="$2" + shift 2 + elif [ $# -gt 1 -a "$1" = "-M" ]; then + MIBS_DIRLIST="$MIBS_DIRLIST:$2" + shift 2 + elif [ "$1" = "-k" ]; then + KEEP=yes + shift + elif [ $# -gt 1 -a "$1" = "-H" ]; then + HOSTNAME="$2" + shift 2 + elif [ $# -gt 1 -a "$1" = "-c" ]; then + COMMUNITY="$2" + shift 2 + elif [ $# -gt 1 -a "$1" = "-s" ]; then + SYSOID="$2" + shift 2 + elif echo "$1" | grep -qv '^-'; then + if [ $# -gt 1 ]; then + NUMWALKFILE="$1" + shift + STRWALKFILE="$1" + shift + else + NUMWALKFILE="$1" + shift + #usage + #exit 1 + fi + elif [ "$1" = "--help" -o "$1" = "-h" ]; then + usage + exit 0 + else + echo "Illegal option $1. Try --help for more info." >&2 + exit 1 + fi done # check that the needed parameters are provided, depending on the mode if [ -z "$NUMWALKFILE" ]; then - # mode 1: directly get SNMP data from a real agent - MODE=1 - NUMWALKFILE=$DFL_NUMWALKFILE - STRWALKFILE=$DFL_STRWALKFILE - - # check if Net SNMP is available - if [ -z "`which snmpget`" -o -z "`which snmpwalk`" ]; then - echo "Net SNMP not found! snmpget and snmpwalk commands are required." >&2 - exit 1 - fi - # hostname is also mandatory - while [ -z "$HOSTNAME" ]; do - echo " - Please enter the SNMP host IP address or name." - read -p "SNMP host IP name or address: " HOSTNAME < /dev/tty - if echo $HOSTNAME | egrep -q '[^a-zA-Z0-9]'; then - echo "Please use only letters and digits" - HOSTNAME="" - fi - done - # get data from the agent - get_snmp_data + # mode 1: directly get SNMP data from a real agent + echo "Mode 1 selected" + MODE=1 + NUMWALKFILE=$DFL_NUMWALKFILE + STRWALKFILE=$DFL_STRWALKFILE + + # check if Net SNMP is available + if [ -z "`which snmpget`" -o -z "`which snmpwalk`" ]; then + echo "Net SNMP not found! snmpget and snmpwalk commands are required." >&2 + exit 1 + fi + # hostname is also mandatory + while [ -z "$HOSTNAME" ]; do + printf "\n\tPlease enter the SNMP host IP address or name.\n" + read -p "SNMP host IP name or address: " HOSTNAME < /dev/tty + if echo $HOSTNAME | egrep -q '[^a-zA-Z0-9]'; then + echo "Please use only letters and digits" + HOSTNAME="" + fi + done + # get data from the agent + get_snmp_data else - # mode 2: get data from files - MODE=2 + # no string walk provided, so mode 3 + if [ -z "$STRWALKFILE" ]; then + # mode 3: get data from 1 file, + # Filter according to sysOID on the specific subtree + # Generate the numeric SNMP walk using this output + # then use snmptranslate to get the string OIDs and generated the string SNMP walk + echo "Mode 3 selected" + MODE=3 + RAWWALKFILE=$NUMWALKFILE + NUMWALKFILE=$DFL_NUMWALKFILE + STRWALKFILE=$DFL_STRWALKFILE + + # check for actual file existence + if [ ! -f "$RAWWALKFILE" ]; then + echo "SNMP walk dump file is missing on disk. Try --help for more info." >&2 + exit 1 + fi + # Extract the sysOID + # Format is "1.3.6.1.2.1.1.2.0 = OID: 1.3.6.1.4.1.4555.1.1.1" + DEVICE_SYSOID=`grep 1.3.6.1.2.1.1.2.0 $RAWWALKFILE | cut -d' ' -f4` + if [ -n "$DEVICE_SYSOID" ]; then + echo "Found sysOID $DEVICE_SYSOID" + else + echo "SNMP sysOID is missing in file. Try --help for more info." >&2 + exit 1 + fi + + # Switch to the entry point, and extract the subtree + # Extract the numeric walk + echo -n "Extracting numeric SNMP walk..." + grep $DEVICE_SYSOID $RAWWALKFILE | egrep -v "1.3.6.1.2.1.1.2.0" 2>/dev/null 1> $NUMWALKFILE + echo " done" + + # Create the string walk from a translation of the numeric one + echo -n "Converting string SNMP walk..." + while IFS=' = ' read NUM_OID OID_VALUE + do + STR_OID=`snmptranslate -Os -m ALL -M+. $NUM_OID 2>/dev/null` + echo "$STR_OID = $OID_VALUE" >> $STRWALKFILE + done < $NUMWALKFILE + echo " done" + else + # mode 2: get data from files + echo "Mode 2 selected" + MODE=2 - # get sysOID value from command line, if needed - while [ -z "$SYSOID" ]; do - echo " + # get sysOID value from command line, if needed + while [ -z "$SYSOID" ]; do + echo " Please enter the value of sysOID, as displayed by snmp-ups. For example '.1.3.6.1.4.1.2254.2.4'. -You can get it using: snmpget -v1 -c XXX .1.3.6.1.2.1.1.2.0" - read -p "Value of sysOID: " SYSOID < /dev/tty - if echo $SYSOID | egrep -q '[^0-9.]'; then - echo "Please use only the numeric form, with dots and digits" - SYSOID="" - fi - done - # check for actual files existence - if [ ! -f "$NUMWALKFILE" -o ! -f "$STRWALKFILE" ]; then - echo "SNMP walk dump files are missing on disk. Try --help for more info." >&2 - exit 1 - fi +You can get it using: snmpget -v1 -c XXX $SYSOID_NUMBER" + read -p "Value of sysOID: " SYSOID < /dev/tty + if echo $SYSOID | egrep -q '[^0-9.]'; then + echo "Please use only the numeric form, with dots and digits" + SYSOID="" + fi + done + # check for actual files existence + if [ ! -f "$NUMWALKFILE" -o ! -f "$STRWALKFILE" ]; then + echo "SNMP walk dump files are missing on disk. Try --help for more info." >&2 + exit 1 + fi + fi fi # delete temporary files: this is called just before exiting. cleanup () { - rm -f "$DEBUG $DFL_NUMWALKFILE $TMP_NUMWALKFILE $DFL_STRWALKFILE $TMP_STRWALKFILE" + rm -f "$DEBUG $DFL_NUMWALKFILE $TMP_NUMWALKFILE $DFL_STRWALKFILE $TMP_STRWALKFILE" } if [ -n "$KEEP" ]; then - trap cleanup EXIT + trap cleanup EXIT fi # prompt use for name of driver while [ -z "$DRIVER" ]; do - echo " + echo " Please enter a name for this driver. Use only letters and numbers. Use natural (upper- and lowercase) capitalization, e.g., 'Belkin', 'APC'." - read -p "Name of subdriver: " DRIVER < /dev/tty - if echo $DRIVER | egrep -q '[^a-zA-Z0-9]'; then - echo "Please use only letters and digits" - DRIVER="" - fi + read -p "Name of subdriver: " DRIVER < /dev/tty + if echo $DRIVER | egrep -q '[^a-zA-Z0-9]'; then + echo "Please use only letters and digits" + DRIVER="" + fi done # remove blank and "End of MIB" lines @@ -215,155 +435,13 @@ STR_OID_COUNT="`cat $STRWALKFILE | wc -l`" echo "COUNT = $NUM_OID_COUNT / $NUM_OID_COUNT" -# create file names -LDRIVER=`echo $DRIVER | tr A-Z a-z` -UDRIVER=`echo $DRIVER | tr a-z A-Z` -CFILE="$LDRIVER-mib.c" -HFILE="$LDRIVER-mib.h" - -FIXME: LDRIVER & UDRIVER => replace - by _ - -# generate header file -echo "Creating $HFILE" -cat > "$HFILE" < - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef ${UDRIVER}_MIB_H -#define ${UDRIVER}_MIB_H - -#include "main.h" -#include "snmp-ups.h" - -extern mib2nut_info_t ${LDRIVER}; - -#endif /* ${UDRIVER}_MIB_H */ -EOF - -# generate source file -# create header -echo "Creating $CFILE" -cat > "$CFILE" < - * - * Note: this subdriver was initially generated as a "stub" by the - * gen-snmp-subdriver script. It must be customized! - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "${HFILE}" - -#define ${UDRIVER}_MIB_VERSION "0.1" - -#define ${UDRIVER}_SYSOID "${SYSOID}" - -/* To create a value lookup structure (as needed on the 2nd line of the example - * below), use the following kind of declaration, outside of the present snmp_info_t[]: - * static info_lkp_t onbatt_info[] = { - * { 1, "OB" }, - * { 2, "OL" }, - * { 0, NULL } - * }; - */ - -/* ${UDRIVER} Snmp2NUT lookup table */ -static snmp_info_t ${LDRIVER}_mib[] = { - - /* Data format: - * { info_type, info_flags, info_len, OID, dfl, flags, oid2info, setvar }, - * - * info_type: NUT INFO_ or CMD_ element name - * info_flags: flags to set in addinfo - * info_len: length of strings if STR - * cmd value if CMD, multiplier otherwise - * OID: SNMP OID or NULL - * dfl: default value - * flags: snmp-ups internal flags (FIXME: ...) - * oid2info: lookup table between OID and NUT values - * setvar: variable to set for SU_FLAG_SETINT - * - * Example: - * { "input.voltage", 0, 0.1, ".1.3.6.1.4.1.705.1.6.2.1.2.1", "", SU_INPUT_1, NULL }, - * { "ups.status", ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.705.1.7.3.0", "", SU_FLAG_OK | SU_STATUS_BATT, onbatt_info }, - * - * To create a value lookup structure (as needed on the 2nd line), use the - * following kind of declaration, outside of the present snmp_info_t[]: - * static info_lkp_t onbatt_info[] = { - * { 1, "OB" }, - * { 2, "OL" }, - * { 0, NULL } - * }; - */ -EOF - - -# extract OID string paths, one by one -LINENB="0" -while IFS= read -r line; do - LINENB="`expr $LINENB + 1`" - FULL_STR_OID="$line" - STR_OID="`echo $line | cut -d'.' -f1`" - echo $line | grep STRING > /dev/null - if [ $? -eq 0 ]; then - ST_FLAG_TYPE="ST_FLAG_STRING" - SU_INFOSIZE="SU_INFOSIZE" - else - ST_FLAG_TYPE="0" - SU_INFOSIZE="1" - fi - # get the matching numeric OID - NUM_OID="`sed -n ${LINENB}p ${NUMWALKFILE} | cut -d' ' -f1`" - printf "\t/* ${FULL_STR_OID} */\n\t{ \"unmapped.${STR_OID}\", ${ST_FLAG_TYPE}, ${SU_INFOSIZE}, \"${NUM_OID}\", NULL, SU_FLAG_OK, NULL, NULL },\n" -done < ${STRWALKFILE} >> ${CFILE} - -# append footer -cat >> "$CFILE" < +Updated 2016-2018 by Michal Hrusecky and Jim Klimov diff --git a/scripts/systemd/nut-driver-enumerator.path.in b/scripts/systemd/nut-driver-enumerator.path.in new file mode 100644 index 0000000000..11f340615a --- /dev/null +++ b/scripts/systemd/nut-driver-enumerator.path.in @@ -0,0 +1,7 @@ +# Trigger restart of nut-driver-enumerator.service whenever ups.conf is edited + +[Path] +PathModified=@CONFPATH@/ups.conf + +[Install] +WantedBy=nut.target diff --git a/scripts/systemd/nut-driver-enumerator.service.in b/scripts/systemd/nut-driver-enumerator.service.in new file mode 100644 index 0000000000..4fd82eaae7 --- /dev/null +++ b/scripts/systemd/nut-driver-enumerator.service.in @@ -0,0 +1,29 @@ +[Unit] +# This unit starts early in system lifecycle to set up nut-driver instances. +# End-user may also restart this unit after editing ups.conf to automatically +# un-register or add new instances as appropriate. +Description=Network UPS Tools - enumeration of configure-file devices into systemd unit instances +After=local-fs.target +Before=nut-driver.target +PartOf=nut.target + +[Service] +### Script needs privileges to restart units +#User=@RUN_AS_USER@ +#Group=@RUN_AS_GROUP@ +User=root +# it is expected that the process has to exit before systemd starts follow-up +# units; it should not be a problem for those +Type=oneshot +# Currently systemd does not support restarting of oneshot services, and does +# not seem to guarantee that other services would only start after the script +# completes, for a non-oneshot case. The script itself handles restarting of +# nut-server which is the primary concerned dependency at the moment, so we +# don't want it to fail the unit (when it can't restart). +Environment=REPORT_RESTART_42=no +EnvironmentFile=-@CONFPATH@/nut.conf +ExecStart=@NUT_LIBEXECDIR@/nut-driver-enumerator.sh +ExecReload=@NUT_LIBEXECDIR@/nut-driver-enumerator.sh + +[Install] +WantedBy=nut.target diff --git a/scripts/systemd/nut-driver.service.in b/scripts/systemd/nut-driver.service.in deleted file mode 100644 index f81ac6996f..0000000000 --- a/scripts/systemd/nut-driver.service.in +++ /dev/null @@ -1,10 +0,0 @@ -[Unit] -Description=Network UPS Tools - power device driver controller -After=local-fs.target network.target -StopWhenUnneeded=yes - -[Service] -ExecStart=@SBINDIR@/upsdrvctl start -ExecStop=@SBINDIR@/upsdrvctl stop -Type=forking - diff --git a/scripts/systemd/nut-driver.target b/scripts/systemd/nut-driver.target new file mode 100644 index 0000000000..d994ab9882 --- /dev/null +++ b/scripts/systemd/nut-driver.target @@ -0,0 +1,8 @@ +[Unit] +Description=Network UPS Tools - target for power device drivers on this system +After=local-fs.target +# network.target +PartOf=nut.target + +[Install] +WantedBy=nut.target diff --git a/scripts/systemd/nut-driver@.service.in b/scripts/systemd/nut-driver@.service.in new file mode 100644 index 0000000000..dc2b5f71c0 --- /dev/null +++ b/scripts/systemd/nut-driver@.service.in @@ -0,0 +1,43 @@ +[Unit] +Description=Network UPS Tools - device driver for %I +After=local-fs.target +PartOf=nut-driver.target +# Note: The choice of "network.target" allows to schedule this unit +# roughly when the network stack of this OS is ready (e.g. that the +# subsequent `upsd` will have a `0.0.0.0` or a `localhost` to bind +# to); however this target does not ensure availability of a real +# connection or final IP addresses. Drivers that require network as +# a media for interaction with UPSes (snmp-ups, netxml-ups, ipmi etc.) +# may want to extend this unit with `Requires=network-online.target` +# instead. Also note that *generally* this should not be a problem, +# since the drivers have a few retries with timeouts during startup, +# and typically by the time the box gets an IP address, the driver +# is still retrying to start and will succeed. +# Extending the unit does not require *this* file to be edited, you +# can instead drop in an additional piece of configuration, e.g. add +# a `/etc/systemd/system/nut-driver@.service.d/network.conf` with: +# [Unit] +# Requires=network-online.target +# After=network-online.target +# If your `upsd` requires specific IP addresses to be available before +# starting, a `/etc/systemd/system/nut-driver.target.d/network.conf` +# can be used in a similar manner. +# Finally note that "nut-driver-enumerator.service" should take care of this. + +[Service] +EnvironmentFile=-@CONFPATH@/nut.conf +ExecStart=/bin/sh -c 'NUTDEV="`@NUT_LIBEXECDIR@/nut-driver-enumerator.sh --get-device-for-service %i`" && [ -n "$NUTDEV" ] || { echo "FATAL: Could not find a NUT device section for service unit %i" >&2 ; exit 1 ; } ; @SBINDIR@/upsdrvctl start "$NUTDEV"' +ExecStop=/bin/sh -c 'NUTDEV="`@NUT_LIBEXECDIR@/nut-driver-enumerator.sh --get-device-for-service %i`" && [ -n "$NUTDEV" ] || { echo "FATAL: Could not find a NUT device section for service unit %i" >&2 ; exit 1 ; } ; @SBINDIR@/upsdrvctl stop "$NUTDEV"' +Type=forking +# Note: If you customize the "maxstartdelay" in ups.conf or in your +# NUT compilation defaults, so it exceeds the default systemd unit +# startup timeout (typically 90 sec), then make sure to set a slightly +# longer systemd timeout for the nut-driver unit instances. You can +# do this by populating a drop-in configuration, so it is not later +# overwritten by updates to your NUT package -- create a dir+file: +# /etc/systemd/system/nut-driver@.service.d/timeout.conf with lines: +# [Service] +# TimeoutStartSec=190s + +[Install] +WantedBy=nut-driver.target diff --git a/scripts/systemd/nut-monitor.service.in b/scripts/systemd/nut-monitor.service.in index 8429bf280c..0d029cc5a2 100644 --- a/scripts/systemd/nut-monitor.service.in +++ b/scripts/systemd/nut-monitor.service.in @@ -1,11 +1,25 @@ [Unit] Description=Network UPS Tools - power device monitor and shutdown controller After=local-fs.target network.target nut-server.service +# Note: We do not specify Requires nut-server.service because +# the `upsd` daemon(s) may be running on a different machine +# (connected to the UPSes) than the `upsmon` shutdown protector. +# The "Wants" directive would try to start the nut-server but +# would not abort if that attempt fails for whatever reason. +Wants=nut-server.service +# Extending the unit does not require *this* file to be edited, you +# can instead drop in an additional piece of configuration, e.g. add +# a `/etc/systemd/system/nut-monitor.service.d/network.conf` with: +# [Unit] +# Requires=network-online.target +# After=network-online.target +PartOf=nut.target [Service] +EnvironmentFile=-@CONFPATH@/nut.conf ExecStart=@SBINDIR@/upsmon PIDFile=@PIDPATH@/upsmon.pid Type=forking [Install] -WantedBy=multi-user.target +WantedBy=nut.target diff --git a/scripts/systemd/nut-server.service.in b/scripts/systemd/nut-server.service.in index 7a786701f8..c8e195a987 100644 --- a/scripts/systemd/nut-server.service.in +++ b/scripts/systemd/nut-server.service.in @@ -1,16 +1,27 @@ [Unit] Description=Network UPS Tools - power devices information server -After=local-fs.target network.target nut-driver.service +After=local-fs.target network.target nut-driver.target # We don't Require drivers to be successfully started! This would be # a change of behavior compared to init SysV, and could prevent from # accessing successfully started, at least to audit a system. -Wants=nut-driver.service +Wants=nut-driver.target +# The `upsd` is a networked service (even if bound to a `localhost`) +# so it requires that the OS has some notion of networking already. +# Extending the unit does not require *this* file to be edited, you +# can instead drop in an additional piece of configuration, e.g. add +# a `/etc/systemd/system/nut-server.service.d/network.conf` with: +# [Unit] +# Requires=network-online.target +# After=network-online.target +Requires=network.target Before=nut-monitor.service +PartOf=nut.target [Service] +EnvironmentFile=-@CONFPATH@/nut.conf ExecStart=@SBINDIR@/upsd ExecReload=@SBINDIR@/upsd -c reload Type=forking [Install] -WantedBy=multi-user.target +WantedBy=nut.target diff --git a/scripts/systemd/nut.target b/scripts/systemd/nut.target new file mode 100644 index 0000000000..f744d29c55 --- /dev/null +++ b/scripts/systemd/nut.target @@ -0,0 +1,8 @@ +[Unit] +Description=Network UPS Tools - target for power device drivers, data server and monitoring client (if enabled) on this system +After=local-fs.target nut-driver.target nut-server.service nut-monitor.service +Wants=local-fs.target nut-driver.target nut-server.service nut-monitor.service +# network.target + +[Install] +WantedBy=multi-user.target diff --git a/scripts/systemd/nutshutdown.in b/scripts/systemd/nutshutdown.in old mode 100644 new mode 100755 index ab3cfcc913..ace2485b35 --- a/scripts/systemd/nutshutdown.in +++ b/scripts/systemd/nutshutdown.in @@ -1,7 +1,14 @@ #!/bin/sh +# This script requires both nut-server (drivers) +# and nut-client (upsmon) to be present locally +# and on mounted filesystems +[ -x "@SBINDIR@/upsmon" ] && [ -x "@SBINDIR@/upsdrvctl" ] || exit + if @SBINDIR@/upsmon -K >/dev/null 2>&1; then - wait_delay=`/bin/sed -ne 's#^ *POWEROFF_WAIT= *\(.*\)$#\1#p' @CONFPATH@/nut.conf` + # The argument may be anything compatible with sleep + # (not necessarily a non-negative integer) + wait_delay="`/bin/sed -ne 's#^ *POWEROFF_WAIT= *\(.*\)$#\1#p' @CONFPATH@/nut.conf`" || wait_delay="" @SBINDIR@/upsdrvctl shutdown diff --git a/scripts/upsdrvsvcctl/.gitignore b/scripts/upsdrvsvcctl/.gitignore new file mode 100644 index 0000000000..3c24b9a908 --- /dev/null +++ b/scripts/upsdrvsvcctl/.gitignore @@ -0,0 +1,2 @@ +/nut-driver-enumerator.sh +/upsdrvsvcctl diff --git a/scripts/upsdrvsvcctl/Makefile.am b/scripts/upsdrvsvcctl/Makefile.am new file mode 100644 index 0000000000..7d7a0f235e --- /dev/null +++ b/scripts/upsdrvsvcctl/Makefile.am @@ -0,0 +1,12 @@ +EXTRA_DIST = README + +if HAVE_SYSTEMD +EXTRA_DIST += nut-driver-enumerator.sh upsdrvsvcctl +else +if WITH_SOLARIS_SMF +EXTRA_DIST += nut-driver-enumerator.sh upsdrvsvcctl +endif +endif + +EXTRA_DIST += nut-driver-enumerator.sh.in upsdrvsvcctl.in + diff --git a/scripts/upsdrvsvcctl/README b/scripts/upsdrvsvcctl/README new file mode 100644 index 0000000000..b2a9db64a8 --- /dev/null +++ b/scripts/upsdrvsvcctl/README @@ -0,0 +1,11 @@ +This directory contains the shared NUT support files for Linux systemd (the +System and Service Manager) and Solaris SMF (Service Management Framework). +It includes the nut-driver-enumerator.sh (service and implementation method) +and upsdrvsvcctl (tool) to manage NUT drivers as service instances. + +These files are automatically installed into SBINDIR/upsdrvsvcctl and +LIBEXECDIR/nut-driver-enumerator.sh, upon detection (at configure time) +of a systemd or SMF enabled system, with Makefiles of the ../systemd/ and +../Solaris/ source directories respectively. + +Contributed 2016-2018 by Jim Klimov diff --git a/scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in b/scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in new file mode 100755 index 0000000000..69e51b9a4b --- /dev/null +++ b/scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in @@ -0,0 +1,1378 @@ +#!/bin/sh +# +# NOTE: This script is intentionally written with portable shell constructs +# with the aim and hope to work in different interpreters, so it is a +# bit dumber and less efficient than could be achieved with the more +# featured shells in the spectrum. +# NOTE ALSO: The configuration parser in this script is not meant to be a +# reference or 100% compliant with what the binary code uses; its aim +# is to just pick out some strings relevant for tracking config changes. +# +# Copyright (C) 2016-2018 Eaton +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +#! \file nut-driver-enumerator.sh(.in) +# \author Jim Klimov +# \brief Enumerate NUT devices for service-unit instance configuration +# \details This script allows to enumerate UPSes in order to produce the +# individual service unit instances for each defined configuration. +# It assumes the user has adequate permissions to inspect and create +# services (e.g. is a root or has proper RBAC profiles to do so). +# It helps service frameworks such as Linux systemd and Solaris SMF. +# When executed, this script looks for all configured ups.conf +# sections and registered service instances, and makes these two +# lists match up. It has also a mode to do this in a loop, to keep +# checking for differences and applying them, on systems where it's +# problematic to trigger it in response to FS event notifications. +# Returns exit codes: +# 0 Sections and services already match up +# 42 Sections and services differed, but now match up - +# now the caller should likely restart some services. +# Note that the drivers' service instances were started or +# stopped as required (by AUTO_START=yes) - but maybe the +# upsd or upsmon services should restart. If you pass envvar +# REPORT_RESTART_42=no then this codepath would return 0. +# In default mode, such non-null reconfiguration should cause +# the nut-driver-enumerator service to restart and this would +# propagate to other NUT services that depend on it. +# 13 Sections and services differed, and still do not match up +# 1 Bad inputs, e.g. unrecognized service management framework +# 2 Absent or unreadable ups.conf file +# + +# NOTE: Currently found caveats that might be solved later but require +# considerable effort: +# * Solaris SMF constrains the syntax of valid strings for instance names +# (e.g. not starting with a digit, no period chars) which blocks creation +# of some UPS driver instances. This might be worked around by hashing +# the device name e.g. to base64 (and un-hashing instance name when calling +# upsdrvctl), but is not quite user-friendly. Also can store device name +# in a service attribute while mangling the instance name to a valid subset. +# Comparisons (if devices are already wrapped) becomes more complicated in +# the script in either case, as well as in the service startup method. +# ** The `+` `/` `=` characters from base64 are also invalid for SMF instance +# name, but the first two can be sed'ed to `-` `_` and back, for example. +# Some prefix word is also needed (avoid starting with a digit). +# The trailing padding `=` can be dropped, and added until we get a +# non-empty decode. Conversions can be done by +# `echo "$string" | openssl base64 -e|-d` +# * Dummy-UPS services that "proxy" another locally defined section are +# essentially a circular dependency for upsd. While the system might +# start-up lacking a driver, there should be some timer to re-enable +# failed not-disabled drivers (would be useful in any case though). + +# Directory where NUT configs are located, e.g. /etc/nut or /etc/ups +# Set at package configuration, compiled into daemons and drivers +prefix="@prefix@" +[ -n "${NUT_CONFPATH-}" ] || NUT_CONFPATH="@sysconfdir@" +# Technically this should be a distribution-dependent value configured +# during package build. But everyone has it the same from systemd defaults: +[ -n "${SYSTEMD_CONFPATH-}" ] || SYSTEMD_CONFPATH="/etc/systemd/system" + +if [ -n "$ZSH_VERSION" ]; then + ### Problem: loops like `for UPS in $UPSLIST` do not separate + ### the UPSLIST into many tokens but use it as one string. + echo "FATAL: zsh is not supported in this script" >&2 + exit 1 +# setopt noglob +# setopt +F +# IFS="`printf ' \t\r\n'`" ; export IFS +fi + +# Third-party services to depend on (can be overridden by config file) +### Note that for systemd+udev integration, it may be better to set up +### triggers in udev, see e.g. +### http://stackoverflow.com/questions/18463755/linux-start-daemon-on-connected-usb-serial-dongle +### Also can tune whether a driver "Wants" another service (would consider +### ordering if that one is enabled, but live if it is disabled), or if it +### "Requires" that (would cause that to start). +DEPSVC_USB_SYSTEMD="systemd-udev.service systemd-udev-settle.service" +DEPREQ_USB_SYSTEMD="Wants" +DEPSVC_NET_FULL_SYSTEMD="network-online.target systemd-resolved.service ifplugd.service" +DEPREQ_NET_FULL_SYSTEMD="Wants" +DEPSVC_NET_LOCAL_SYSTEMD="network.target" +DEPREQ_NET_LOCAL_SYSTEMD="Wants" +SVCNAME_SYSTEMD="nut-driver" + +# Some or all of these FMRIs may be related to dynamically changing hardware +# require_all) ;; # All cited services are running (online or degraded) +# require_any) ;; # At least one of the cited services is running +# optional_all) ;; # (All) cited services are running or would not run +# # without administrative action (disabled, maintenance, +# # not present, or are waiting for dependencies which do +# # not start without administrative action). +DEPSVC_USB_SMF="svc:/system/hotplug:default svc:/system/dbus:default svc:/system/hal:default svc:/milestone/devices:default" +DEPREQ_USB_SMF="optional_all" +# By default there are several physical network FMRIs shipped and at most +# only one is enabled on a particular system (e.g. :default or :nwam) +DEPSVC_NET_FULL_SMF="svc:/network/physical svc:/milestone/name-services" +DEPREQ_NET_FULL_SMF="optional_all" +DEPSVC_NET_LOCAL_SMF="svc:/network/loopback:default" +DEPREQ_NET_LOCAL_SMF="optional_all" +SVCNAME_SMF="svc:/system/power/nut-driver" + +[ -z "${NUT_DRIVER_ENUMERATOR_CONF-}" ] && \ + NUT_DRIVER_ENUMERATOR_CONF="${NUT_CONFPATH}/nut-driver-enumerator.conf" + +[ -s "${NUT_DRIVER_ENUMERATOR_CONF}" ] && \ + echo "Sourcing config file: ${NUT_DRIVER_ENUMERATOR_CONF}" && \ + . "${NUT_DRIVER_ENUMERATOR_CONF}" + +[ -z "${UPSCONF-}" ] && \ + UPSCONF="${NUT_CONFPATH}/ups.conf" + +# Start a freshly-registered unit? +[ -z "${AUTO_START-}" ] && AUTO_START=yes + +# We avoid regex '\t' which gets misinterpreted by some tools +TABCHAR="`printf '\t'`" || TABCHAR=' ' + +if [ -z "${SERVICE_FRAMEWORK-}" ] ; then + [ -x /usr/sbin/svcadm ] && [ -x /usr/sbin/svccfg ] && [ -x /usr/bin/svcs ] && [ -x /usr/bin/svcprop ] && \ + SERVICE_FRAMEWORK="smf" + [ -z "${SERVICE_FRAMEWORK-}" ] && \ + [ -x /bin/systemctl ] && \ + SERVICE_FRAMEWORK="systemd" +fi + +# Cache needed bits of ups.conf to speed up later parsing. Note that these +# data are needed for most operations, and populated by upslist_readFile() +UPSCONF_DATA="" +# Subset of normalized data above that only has sections, drivers and ports +UPSCONF_DATA_SDP="" + +# List of configured UPSes in the config-file +UPSLIST_FILE="" +# List of configured service instances for UPS drivers +UPSLIST_SVCS="" + +# Framework-specific implementations are generally hooked here: +hook_registerInstance="" +hook_unregisterInstance="" +hook_refreshSupervizor="" +hook_listInstances="" +hook_listInstances_raw="" +hook_validInstanceName="" +hook_validFullUnitName="" +hook_validInstanceSuffixName="" +hook_getSavedMD5="" +hook_setSavedMD5="" +hook_restart_upsd="" +hook_restart_drv="" + +case "${SERVICE_FRAMEWORK-}" in + smf) + hook_registerInstance="smf_registerInstance" + hook_unregisterInstance="smf_unregisterInstance" + hook_refreshSupervizor="smf_refreshSupervizor" + hook_listInstances="smf_listInstances" + hook_listInstances_raw="smf_listInstances_raw" + hook_validInstanceName="smf_validInstanceName" + hook_validFullUnitName="smf_validFullUnitName" + hook_validInstanceSuffixName="smf_validInstanceSuffixName" + hook_getSavedMD5="smf_getSavedMD5" + hook_setSavedMD5="smf_setSavedMD5" + hook_restart_upsd="smf_restart_upsd" + hook_restart_drv="smf_restart_drv" + ;; + systemd) + hook_registerInstance="systemd_registerInstance" + hook_unregisterInstance="systemd_unregisterInstance" + hook_refreshSupervizor="systemd_refreshSupervizor" + hook_listInstances="systemd_listInstances" + hook_listInstances_raw="systemd_listInstances_raw" + hook_validInstanceName="systemd_validInstanceName" + hook_validFullUnitName="systemd_validFullUnitName" + hook_validInstanceSuffixName="systemd_validInstanceSuffixName" + hook_getSavedMD5="systemd_getSavedMD5" + hook_setSavedMD5="systemd_setSavedMD5" + hook_restart_upsd="systemd_restart_upsd" + hook_restart_drv="systemd_restart_drv" + ;; + selftest) + hook_registerInstance="selftest_NOOP" + hook_unregisterInstance="selftest_NOOP" + hook_refreshSupervizor="selftest_NOOP" + hook_listInstances="selftest_NOOP" + hook_listInstances_raw="selftest_NOOP" + hook_validInstanceName="selftest_NOOP" + hook_validFullUnitName="selftest_NOOP" + hook_validInstanceSuffixName="selftest_NOOP" + hook_getSavedMD5="selftest_NOOP" + hook_setSavedMD5="selftest_NOOP" + hook_restart_upsd="selftest_NOOP" + hook_restart_drv="selftest_NOOP" + ;; + "") + echo "Error detecting the service-management framework on this OS" >&2 + exit 1 + ;; + *) + echo "Error: User provided an unknown service-management framework '$SERVICE_FRAMEWORK'" >&2 + exit 1 + ;; +esac + +selftest_NOOP() { + echo "NO-OP: Self-testing context does not do systems configuration" >&2 + return 0 +} + +common_isFiled() { + [ -n "$UPSLIST_FILE" ] && \ + for UPSF in $UPSLIST_FILE ; do + [ "$1" = "$UPSF" ] && return 0 + [ "`$hook_validInstanceName "$UPSF"`" = "$1" ] && return 0 + done + return 1 +} + +common_isRegistered() { + [ -n "$UPSLIST_SVCS" ] && \ + for UPSS in $UPSLIST_SVCS ; do + [ "$1" = "$UPSS" ] && return 0 + [ "`$hook_validInstanceName "$1"`" = "$UPSS" ] && return 0 + done + return 1 +} + +upslist_equals() { + # Compare pre-sorted list of DEVICES ($1) and SVCINSTs ($2) including + # the possible mangling for service names. Return 0 if lists describe + # exactly same set of devices and their services. + # Note: This logic only checks the names, not the contents of device + # sections, so re-definitions of an existing device configuration + # would not trigger a service restart by itself. Such deeper check + # belongs in a different routine, see upssvcconf_checksum_unchanged(). + + # Trivial case 0: one string is empty, another is not + # Note: `echo '' | wc -l` == "1" not "0"! + [ -n "$1" -a -z "$2" ] && return 1 + [ -z "$1" -a -n "$2" ] && return 1 + + # Trivial case 1: equal strings + [ "$1" = "$2" ] && return 0 + # Trivial case 2: different amount of entries + [ "`echo "$1" | wc -l`" = "`echo "$2" | wc -l`" ] || return $? + + _TMP_DEV_SVC="" + for _DEV in $1 ; do + DEVINST="`$hook_validInstanceName "$_DEV"`" + for _SVC in $2 ; do + [ "$_DEV" = "$_SVC" ] \ + || [ "$DEVINST" = "$_SVC" ] \ + && { [ -z "$_TMP_DEV_SVC" ] \ + && _TMP_DEV_SVC="$_DEV = $_SVC" \ + || _TMP_DEV_SVC="$_TMP_DEV_SVC +$_DEV = $_SVC" ; } + done + done + + # Input was not empty; did anything in output fit? + [ -z "$_TMP_DEV_SVC" ] && return 1 + + # Exit code : is the built mapping as long as the source list(s)? + [ "`echo "$1" | wc -l`" = "`echo "$_TMP_DEV_SVC" | wc -l`" ] +} + +upssvcconf_checksum_unchanged() { + # $1 = dev, $2 = svc + # compare checksums of the configuration section from the file and the + # stashed configuration in a service instance (if any). + # FIXME : optimize by caching, we likely have quite a few requests + [ "`upsconf_getSection_MD5 "$1"`" = "`$hook_getSavedMD5 "$2"`" ] +} + +upslist_checksums_unchanged() { + # For each device and its corresponding unit, compare checksums of the + # configuration section from the file and the stashed configuration in + # a service instance. Prints a list of mismatching service names that + # should get reconfigured. + [ -z "$1" -o -z "$2" ] && return 1 + + _TMP_SVC="" + for _DEV in $1 ; do + DEVINST="`$hook_validInstanceName "$_DEV"`" + for _SVC in $2 ; do + if [ "$_DEV" = "$_SVC" ] \ + || [ "$DEVINST" = "$_SVC" ] \ + ; then + upssvcconf_checksum_unchanged "$_DEV" "$_SVC" || \ + { [ -z "$_TMP_SVC" ] \ + && _TMP_SVC="$_SVC" \ + || _TMP_SVC="$_TMP_SVC +$_SVC" ; } + fi + done + done + [ -z "$_TMP_SVC" ] && return 0 + echo "$_TMP_SVC" + return 1 +} + +upsconf_getSection_content() { + # "$1" = name of ups.conf section to display in whole, from whatever + # comes on stdin (file or a pre-made normalized variable) + # empty "$1" means the global config (before any sections) + # + # NOTE (TODO?): This routine finds the one NUT device section, prints it + # and returns when the section is over. It currently does not cover (in + # a way allowing to do it efficiently) selection of several sections, + # or storing each section content in some array or dynamic variables + # (as would be better fit for portable shells) to later address them + # quickly without re-parsing the file or big envvar many times. + # + + CURR_SECTION="" + SECTION_CONTENT="" + RES=1 + [ -n "$1" ] || RES=0 + while read LINE ; do + case "$LINE" in + \["$1"\]) + if [ "$RES" = 0 ]; then + # We have already displayed a section, here is a new one, + # and this routine only displays one (TODO: toggle?) + break + fi + SECTION_CONTENT="$LINE" + CURR_SECTION="$1" + RES=0 + continue + ;; + \[*\ *\]|\[*"$TABCHAR"*\]) + # Note that section-name brackets should contain a single token + # Fall through to add the line to contents of existing section + ;; + \[*\]) + [ "$CURR_SECTION" = "$1" ] && break + # Use a value that can not be a section name here: + CURR_SECTION="[]" + continue + ;; + "") continue ;; + *) ;; # Fall through to add the line to contents of existing section + esac + if [ "$CURR_SECTION" = "$1" ]; then + if [ -n "$SECTION_CONTENT" ]; then + SECTION_CONTENT="$SECTION_CONTENT +$LINE" + else + SECTION_CONTENT="$LINE" + fi + fi + done + + if [ -n "$SECTION_CONTENT" ]; then + echo "$SECTION_CONTENT" + fi + + [ "$RES" = 0 ] || echo "ERROR: Section [$1] was not found in the '$UPSCONF' file" >&2 + return $RES +} + +upsconf_getSection() { + # Use the whole output of normalization parser + upslist_normalizeFile_once || return # Propagate errors upwards + upsconf_getSection_content "$@" << EOF +${UPSCONF_DATA} +EOF +} + +upsconf_getSection_MD5() { + calc_md5 "`upsconf_getSection "$@"`" +} + +upsconf_getSection_SDP() { + # Use the section-driver-port subset + upslist_normalizeFile_once || return # Propagate errors upwards + upsconf_getSection_content "$@" << EOF +${UPSCONF_DATA_SDP} +EOF +} + +upsconf_getValue() { + # "$1" = name of ups.conf section, may be empty for global config + # "$2..$N" = name of config key; we will echo its value +### [ -n "$1" ] || return $? + [ -n "$2" ] || return $? + [ -n "$GETSECTION" ] || GETSECTION="upsconf_getSection" + CURR_SECTION="" # Gets set by a GETSECTION implementation + RES=0 + + # Note: Primary aim of this egrep is to pick either assignments or flags + # As a by-product it can be used to test if a particular value is set ;) + SECTION_CONTENT="`$GETSECTION "$1"`" || return + shift + KEYS="$*" + + while [ "$#" -gt 0 ] ; do + RES_L=0 + VALUE="" + + LINE="`echo "$SECTION_CONTENT" | egrep '(^'"$1"'=|^'"$1"'$)'`" \ + && VALUE="$(echo "$LINE" | sed -e "s,^$1=,," -e 's,^\"\(.*\)\"$,\1,' -e "s,^'\(.*\)'$,\1,")" \ + || RES_L=$? + + [ "$RES_L" = 0 ] || { RES="$RES_L" ; echo "ERROR: Section [$CURR_SECTION] or key '$1' in it was not found in the '$UPSCONF' file" >&2 ; } + + echo "$VALUE" + shift + done + + [ "$RES" = 0 ] || echo "ERROR: Section [$CURR_SECTION] or key(s) '$KEYS' in it was not found in the '$UPSCONF' file" >&2 + return $RES +} + +upsconf_getDriver() { + # "$1" = name of ups.conf section; return (echo) the driver name used there + # In the context this function is used, UPSCONF exists and section is there + GETSECTION="upsconf_getSection_SDP" upsconf_getValue "$1" "driver" + return $? +} + +upsconf_getPort() { + # "$1" = name of ups.conf section; return (echo) the "port" name used there + # In the context this function is used, UPSCONF exists and section is there + GETSECTION="upsconf_getSection_SDP" upsconf_getValue "$1" "port" + return $? +} + +upsconf_getDriverMedia() { + # "$1" = name of ups.conf section; return (echo) name and type of driver as + # needed for dependency evaluation (what services we must depend on for this + # unit), newline-separated (drvnametype). Empty type for unclassified + # results, assuming no known special dependencies (note that depending on + # particular system's physics, both serial and network media may need USB). + CURR_DRV="`upsconf_getDriver "$1"`" || return $? + case "$CURR_DRV" in + *netxml*|*snmp*|*ipmi*|*powerman*|*-mib*|*avahi*|*apcupsd*) + printf '%s\n%s\n' "$CURR_DRV" "network" ; return ;; + *usb*) + printf '%s\n%s\n' "$CURR_DRV" "usb" ; return ;; + nutdrv_qx) # May be direct serial or USB + CURR_PORT="`upsconf_getPort "$1"`" || CURR_PORT="" + case "$CURR_PORT" in + auto|/dev/*usb*|/dev/*hid*) + printf '%s\n%s\n' "$CURR_DRV" "usb" ; return ;; + /dev/*) + # See drivers/nutdrv_qx.c :: upsdrv_initups() for a list + if [ -n "`upsconf_getValue "$1" 'subdriver' 'vendorid' 'productid' 'vendor' 'product' 'serial' 'bus' 'langid_fix'`" ] \ + ; then + printf '%s\n%s\n' "$CURR_DRV" "usb" ; return + else + printf '%s\n%s\n' "$CURR_DRV" "serial" ; return + fi + ;; + *) + printf '%s\n%s\n' "$CURR_DRV" "" ; return ;; + esac + ;; + *dummy*|*clone*) # May be networked (proxy to remote NUT) + CURR_PORT="`upsconf_getPort "$1"`" || CURR_PORT="" + case "$CURR_PORT" in + *@localhost|*@|*@127.0.0.1|*@::1) + printf '%s\n%s\n' "$CURR_DRV" "network-localhost" ; return ;; + *@*) + printf '%s\n%s\n' "$CURR_DRV" "network" ; return ;; + *) + printf '%s\n%s\n' "$CURR_DRV" "" ; return ;; + esac + ;; + *) printf '%s\n%s\n' "$CURR_DRV" "" ; return ;; + esac +} + +upsconf_getMedia() { + _DRVMED="`upsconf_getDriverMedia "$1"`" || return + echo "$_DRVMED" | tail -n +2 + return 0 +} + +upsconf_debug() { + _DRV="`upsconf_getDriver "$1"`" + _PRT="`upsconf_getPort "$1"`" + _MED="`upsconf_getMedia "$1"`" + _MD5="`upsconf_getSection_MD5 "$1"`" + NAME_MD5="`calc_md5 "$1"`" + echo "INST: ${NAME_MD5}~[$1]: DRV='$_DRV' PORT='$_PRT' MEDIA='$_MED' SECTIONMD5='$_MD5'" +} + +calc_md5() { + # Tries several ways to produce an MD5 of the "$1" argument + _MD5="`echo "$1" | md5sum 2>/dev/null | awk '{print $1}'`" && [ -n "$_MD5" ] || \ + { _MD5="`echo "$1" | openssl dgst -md5 2>/dev/null | awk '{print $NF}'`" && [ -n "$_MD5" ]; } || \ + return 1 + + echo "$_MD5" +} + +calc_md5_file() { + # Tries several ways to produce an MD5 of the file named by "$1" argument + [ -s "$1" ] || return 2 + + _MD5="`md5sum 2>/dev/null < "$1" | awk '{print $1}'`" && [ -n "$_MD5" ] || \ + { _MD5="`openssl dgst -md5 2>/dev/null < "$1" | awk '{print $NF}'`" && [ -n "$_MD5" ]; } || \ + return 1 + + echo "$_MD5" +} + +smf_validFullUnitName() { + case "$1" in + *:*) echo "$1" ;; + *) echo "$SVCNAME_SMF:$1" ;; + esac +} +smf_validInstanceName() { + echo "MD5_`calc_md5 "$1"`" +} +smf_validInstanceSuffixName() { + case "$1" in + *:*) echo "$1" | sed 's,^.*:\([^:]*\)$,\1,' ;; + *) echo "$1" ;; + esac +} +smf_registerInstance() { + DEVICE="$1" + SVCINST="$1" + /usr/sbin/svccfg -s nut-driver add "$DEVICE" || \ + { SVCINST="`smf_validInstanceName "$1"`" && \ + /usr/sbin/svccfg -s nut-driver add "$SVCINST" || return ; } + echo "Added instance: 'nut-driver:$SVCINST' for NUT configuration section '$DEVICE'" >&2 + + DEPSVC="" + DEPREQ="" + _MED="`upsconf_getMedia "$DEVICE"`" + case "$_MED" in + usb) + DEPSVC="$DEPSVC_USB_SMF" + DEPREQ="$DEPREQ_USB_SMF" ;; + network-localhost) + DEPSVC="$DEPSVC_NET_LOCAL_SMF" + DEPREQ="$DEPREQ_NET_LOCAL_SMF" ;; + network) + DEPSVC="$DEPSVC_NET_FULL_SMF" + DEPREQ="$DEPREQ_NET_FULL_SMF" ;; + serial) ;; + '') ;; + *) echo "WARNING: Unexpected NUT media type ignored: '$_MED'" >&2 ;; + esac + + TARGET_FMRI="nut-driver:$SVCINST" + if [ -n "$DEPSVC" ]; then + [ -n "$DEPREQ" ] || DEPREQ="optional_all" + echo "Adding '$DEPREQ' dependency for '$SVCINST' on '$DEPSVC'..." + + DEPPG="nut-driver-enumerator-generated" + RESTARTON="refresh" + /usr/sbin/svccfg -s "$TARGET_FMRI" addpg "$DEPPG" dependency && \ + /usr/sbin/svccfg -s "$TARGET_FMRI" setprop "$DEPPG"/grouping = astring: "$DEPREQ" && \ + /usr/sbin/svccfg -s "$TARGET_FMRI" setprop "$DEPPG"/restart_on = astring: "$RESTARTON" && \ + /usr/sbin/svccfg -s "$TARGET_FMRI" setprop "$DEPPG"/type = astring: service && \ + /usr/sbin/svccfg -s "$TARGET_FMRI" setprop "$DEPPG"/entities = fmri: "($DEPSVC)" && \ + echo "OK" || echo "FAILED to define the dependency" >&2 + fi + + smf_setSavedMD5 "$SVCINST" "`upsconf_getSection_MD5 "$DEVICE"`" + + /usr/sbin/svcadm refresh "${TARGET_FMRI}" || return + if [ "$AUTO_START" = yes ] ; then + /usr/sbin/svcadm clear "${TARGET_FMRI}" 2>/dev/null || true + /usr/sbin/svcadm enable "${TARGET_FMRI}" || return + echo "Started instance: 'nut-driver:$SVCINST' for NUT configuration section '$DEVICE'" >&2 + fi +} +smf_unregisterInstance() { + echo "Removing instance: 'nut-driver:$1' ..." >&2 + /usr/sbin/svcadm disable -ts 'nut-driver:'"$1" || false + /usr/sbin/svccfg -s nut-driver delete "$1" +} +smf_refreshSupervizor() { + : +} +smf_listInstances_raw() { + # Newer versions have pattern matching; older SMF might not have this luxury + /usr/bin/svcs -a -H -o fmri | egrep '/nut-driver:' +} +smf_listInstances() { + smf_listInstances_raw | sed 's/^.*://' | sort -n +} +smf_getSavedMD5() { + # Query service instance $1 + PG="nut-driver-enumerator-generated-checksum" + PROP="SECTION_CHECKSUM" + + if [ -n "$1" ]; then + TARGET_FMRI="nut-driver:$1" + else + # Global section + TARGET_FMRI="nut-driver" + PROP="SECTION_CHECKSUM_GLOBAL" + fi + + # Note: lookups for GLOBAL cause each service instance to show up + /usr/bin/svcprop -p "$PG/$PROP" "$TARGET_FMRI" | head -1 | awk '{print $NF}' +} +smf_setSavedMD5() { + # Save checksum value $2 into service instance $1 + PG="nut-driver-enumerator-generated-checksum" + PROP="SECTION_CHECKSUM" + + if [ -n "$1" ]; then + TARGET_FMRI="nut-driver:$1" + else + # Global section + TARGET_FMRI="nut-driver" + PROP="SECTION_CHECKSUM_GLOBAL" + fi + + /usr/sbin/svccfg -s "$TARGET_FMRI" delprop "$PG" || true + /usr/sbin/svccfg -s "$TARGET_FMRI" addpg "$PG" application && \ + /usr/sbin/svccfg -s "$TARGET_FMRI" setprop "$PG/$PROP" = astring: "$2" + [ $? = 0 ] && echo "OK" || { echo "FAILED to stash the checksum">&2 ; return 1 ; } + /usr/sbin/svcadm refresh "${TARGET_FMRI}" || return +} +smf_restart_upsd() { + echo "Restarting NUT data server to make sure it knows new configuration..." + /usr/sbin/svcadm enable "nut-server" 2>/dev/null + /usr/sbin/svcadm clear "nut-server" 2>/dev/null + /usr/sbin/svcadm refresh "nut-server" || \ + /usr/sbin/svcadm restart "nut-server" +} +smf_restart_drv() { + echo "Restarting NUT driver instance '$1' to make sure it knows new configuration..." + /usr/sbin/svcadm enable "nut-driver:$1" 2>/dev/null + /usr/sbin/svcadm clear "nut-driver:$1" 2>/dev/null + /usr/sbin/svcadm refresh "nut-driver:$1" || \ + /usr/sbin/svcadm restart "nut-driver:$1" +} + +systemd_validFullUnitName() { + case "$1" in + *@*.*) echo "$1" ;; + *@*) echo "$1.service" ;; + *) echo "$SVCNAME_SYSTEMD@$1.service" ;; + esac +} +systemd_validInstanceName() { + echo "MD5_`calc_md5 "$1"`" +} +systemd_validInstanceSuffixName() { + echo "$1" | sed -e 's,^.*@,,' -e 's,\.service$,,' +} +systemd_registerInstance() { + # Instance is registered by device section name; ultimate name in systemd may differ + DEVICE="$1" + SVCINST="$1" + /bin/systemctl enable 'nut-driver@'"$DEVICE".service || \ + { SVCINST="`systemd_validInstanceName "$1"`" && \ + /bin/systemctl enable 'nut-driver@'"$SVCINST".service || return ; } + echo "Enabled instance: 'nut-driver@$SVCINST' for NUT configuration section '$DEVICE'" >&2 + + DEPSVC="" + DEPREQ="" + _MED="`upsconf_getMedia "$DEVICE"`" + case "$_MED" in + usb) + DEPSVC="$DEPSVC_USB_SYSTEMD" + DEPREQ="$DEPREQ_USB_SYSTEMD" ;; + network-localhost) + DEPSVC="$DEPSVC_NET_LOCAL_SYSTEMD" + DEPREQ="$DEPREQ_NET_LOCAL_SYSTEMD" ;; + network) + DEPSVC="$DEPSVC_NET_FULL_SYSTEMD" + DEPREQ="$DEPREQ_NET_FULL_SYSTEMD" ;; + serial) ;; + '') ;; + *) echo "WARNING: Unexpected NUT media type ignored: '$_MED'" >&2 ;; + esac + if [ -n "$DEPSVC" ]; then + [ -n "$DEPREQ" ] || DEPREQ="#Wants" + echo "Adding '$DEPREQ'+After dependency for '$SVCINST' on '$DEPSVC'..." + mkdir -p "${SYSTEMD_CONFPATH}/nut-driver@$SVCINST.service.d" && \ + cat > "${SYSTEMD_CONFPATH}/nut-driver@$SVCINST.service.d/nut-driver-enumerator-generated.conf" <&2 + fi + + systemd_setSavedMD5 "$SVCINST" "`upsconf_getSection_MD5 "$DEVICE"`" + + if [ "$AUTO_START" = yes ] ; then + /bin/systemctl start --no-block 'nut-driver@'"$SVCINST".service || return + echo "Started instance: 'nut-driver@$SVCINST' for NUT configuration section '$DEVICE'" >&2 + fi +} +systemd_unregisterInstance() { + echo "Removing instance: 'nut-driver@$1' ..." >&2 + /bin/systemctl stop 'nut-driver@'"$1".service || false + /bin/systemctl disable 'nut-driver@'"$1".service + rm -rf "${SYSTEMD_CONFPATH}/nut-driver@$1.service.d" + /bin/systemctl reset-failed 'nut-driver@'"$1".service +} +systemd_refreshSupervizor() { + /bin/systemctl daemon-reload +} +systemd_listInstances_raw() { + /bin/systemctl show 'nut-driver@*' -p Id | egrep '=nut-driver' | sed 's,^Id=,,' +} +systemd_listInstances() { + systemd_listInstances_raw | sed -e 's/^.*@//' -e 's/\.service$//' | sort -n +} +systemd_getSavedMD5() { + # Query service instance $1 or global section + PROP="SECTION_CHECKSUM" + [ -n "$1" ] || PROP="SECTION_CHECKSUM_GLOBAL" + [ -s "${SYSTEMD_CONFPATH}/nut-driver@$1.service.d/nut-driver-enumerator-generated-checksum.conf" ] \ + && grep "Environment='$PROP=" "${SYSTEMD_CONFPATH}/nut-driver@$1.service.d/nut-driver-enumerator-generated-checksum.conf" | sed -e "s,^Environment='$PROP=,," -e "s,'\$,," \ + || { echo "Did not find '${SYSTEMD_CONFPATH}/nut-driver@$1.service.d/nut-driver-enumerator-generated-checksum.conf' with a $PROP" ; return 1; } +} +systemd_setSavedMD5() { + # Save checksum value $2 into service instance $1 + PROP="SECTION_CHECKSUM" + [ -n "$1" ] || PROP="SECTION_CHECKSUM_GLOBAL" + mkdir -p "${SYSTEMD_CONFPATH}/nut-driver@$1.service.d" && \ + cat > "${SYSTEMD_CONFPATH}/nut-driver@$1.service.d/nut-driver-enumerator-generated-checksum.conf" << EOF +[Service] +Environment='$PROP=$2' +EOF + [ $? = 0 ] && echo "OK" || { echo "FAILED to stash the checksum">&2 ; return 1 ; } +} +systemd_restart_upsd() { + # Do not restart/reload if not already running + case "`/bin/systemctl is-active "nut-server"`" in + active|unknown) ;; # unknown meant "starting" in our testing... + *) return 0 ;; + esac + + echo "Restarting NUT data server to make sure it knows new configuration..." + # Note: reload is a better way to go about this, so the + # data service is not interrupted by re-initialization + # of the daemon. But systemd/systemctl sometimes stalls... + # Coreutils timeout + TIMEOUT="" + if which timeout 2>/dev/null >/dev/null ; then + # Systemd default timeout for unit start/stop + TIMEOUT="timeout 90s " + fi + + $TIMEOUT /bin/systemctl reload-or-restart "nut-server" || \ + $TIMEOUT /bin/systemctl restart "nut-server" +} + +systemd_restart_drv() { + # Do not restart/reload if not already running + case "`/bin/systemctl is-active "nut-driver@$1"`" in + active|unknown) ;; + *) return 0 ;; + esac + + echo "Restarting NUT driver instance '$1' to make sure it knows new configuration..." + TIMEOUT="" + if which timeout 2>/dev/null >/dev/null ; then + # Systemd default timeout for unit start/stop + TIMEOUT="timeout 90s " + fi + + # Full restart, e.g. in case we changed the user= in configs + $TIMEOUT /bin/systemctl restart "nut-driver@$1" +} + +upslist_normalizeFile_filter() { + # See upslist_normalizeFile() detailed comments below; this routine + # is a pipe worker to prepare the text into a simpler expected form. + + # Pick the lines which contain a bracket or assignment character, + # or a single token (certain keywords come as just NUT "flags"), + # trim leading and trailing whitespace, comment-only lines, and in + # assignment lines trim the spaces around equality character and + # quoting characters around assignment of values without whitespaces. + # Any whitespace characters around a section name (single token that + # starts the line and is enclosed in brackets) and a trailing comment + # are dropped. Note that brackets with spaces inside, and brackets + # that do not start the non-whitespace payload of the line, are not + # sections. + egrep -v '(^$|^#)' | \ + sed -e 's,^['"$TABCHAR"'\ ]*,,' \ + -e 's,^\#.*$,,' \ + -e 's,['"$TABCHAR"'\ ]*$,,' \ + -e 's,^\([^=\ '"$TABCHAR"']*\)['"$TABCHAR"'\ ]*=['"$TABCHAR"'\ ]*,\1=,g' \ + -e 's,=\"\([^\ '"$TABCHAR"']*\)\"$,=\1,' \ + -e 's,^\(\[[^]'"$TABCHAR"'\ ]*\]\)['"$TABCHAR"'\ ]*\(#.*\)*$,\1,' \ + | egrep -v '^$' \ + | egrep '([\[\=]|^[^ '"$TABCHAR"']*$|^[^ '"$TABCHAR"']*[ '"$TABCHAR"']*\#.*$)' +} + +upslist_normalizeFile() { + # Read the ups.conf file and find all defined sections (names of + # configuration blocks for drivers that connect to a certain device + # using specified protocol and media); normalize section contents + # as detailed below, to simplify subsequent parsing and comparison. + + # File contents + UPSCONF_DATA="" + UPSCONF_DATA_SDP="" + if [ -n "$UPSCONF" ] && [ -f "$UPSCONF" ] && [ -r "$UPSCONF" ]; then + [ ! -s "$UPSCONF" ] \ + && echo "WARNING: The '$UPSCONF' file exists but is empty" >&2 \ + && return 0 + # Ok to continue - we may end up removing all instances + else + echo "FATAL: The '$UPSCONF' file does not exist or is not readable" >&2 + return 2 + fi + + # Store a normalized version of NUT configuration file contents. + # Also use a SDP subset with just section, driver and port info + # for faster parsing when determining driver-required media etc. + UPSCONF_DATA="$(upslist_normalizeFile_filter < "$UPSCONF")" \ + && [ -n "$UPSCONF_DATA" ] \ + && UPSCONF_DATA_SDP="`egrep '^(\[.*\]|driver=|port=)' << EOF +$UPSCONF_DATA +EOF`" \ + || { echo "Error reading the '$UPSCONF' file or it does not declare any device configurations: nothing left after normalization" >&2 + UPSCONF_DATA="" + UPSCONF_DATA_SDP="" + } +} + +upslist_normalizeFile_once() { + # Wrapper that ensures that the parsing is only done once + # (will re-parse if there were no devices listed on the + # first time, though) + [ -z "$UPSCONF_DATA" ] && [ -z "$UPSCONF_DATA_SDP" ] || return 0 + upslist_normalizeFile +} + +upslist_readFile() { + # Use the routine above (unconditionally) to get or update the + # listing of device sections known at this moment. + + # List of devices from the config file + UPSLIST_FILE="" + if [ "$DO_NORMALIZE_ONCE" = yes ]; then + upslist_normalizeFile_once || return # Propagate errors upwards + else + upslist_normalizeFile || return # Propagate errors upwards + fi + + if [ -n "$UPSCONF_DATA" ] ; then + # Note that section-name brackets should contain a single token + UPSLIST_FILE="$(echo "$UPSCONF_DATA_SDP" | egrep '^\[[^'"$TABCHAR"'\ ]*\]$' | sed 's,^\[\(.*\)\]$,\1,' | sort -n)" \ + || UPSLIST_FILE="" + if [ -z "$UPSLIST_FILE" ] ; then + echo "Error reading the '$UPSCONF' file or it does not declare any device configurations: no section declarations in parsed normalized contents" >&2 + fi + fi + # Ok to continue with empty results - we may end up removing all instances +} + +upslist_readFile_once() { + # Wrapper that ensures that the parsing is only done once + # (will re-parse if there were no devices listed on the + # first time, though) + [ -z "$UPSLIST_FILE" ] || return 0 + DO_NORMALIZE_ONCE=yes upslist_readFile +} + +upslist_readSvcs() { + UPSLIST_SVCS="`$hook_listInstances`" || UPSLIST_SVCS="" + if [ -z "$UPSLIST_SVCS" ] && [ "$1" != "-" ] ; then + EXPLAIN="" + [ -z "$1" ] || EXPLAIN=" - $1" + echo "Error reading the list of ${SERVICE_FRAMEWORK-} service instances for UPS drivers, or none are defined${EXPLAIN}" >&2 + # Ok to continue - we may end up defining new instances + fi +} + +upslist_debug() { + for UPSF in "" $UPSLIST_FILE ; do + upsconf_debug "$UPSF" + done +} + +upslist_addSvcs() { + # Note: This routine registers service instances for device config sections + # that are not wrapped currently. Support for redefined previously existing + # sections - is attained by removing the old service instance elsewhere and + # recreating it here, since any data could change including the dependency + # list, etc. + for UPSF in $UPSLIST_FILE ; do + if ! common_isRegistered "$UPSF" ; then + echo "Adding new ${SERVICE_FRAMEWORK} service instance for power device [${UPSF}]..." >&2 + $hook_registerInstance "$UPSF" + fi + done +} + +upslist_delSvcs() { + for UPSS in $UPSLIST_SVCS ; do + if ! common_isFiled "$UPSS" ; then + echo "Dropping old ${SERVICE_FRAMEWORK} service instance for power device [${UPSS}] which is no longer in config file..." >&2 + $hook_unregisterInstance "$UPSS" + fi + done +} + +upslist_restartSvcs() { + for UPSS in $UPSLIST_SVCS ; do + if common_isFiled "$UPSS" ; then + $hook_restart_drv "$UPSS" + fi + done +} + +nut_driver_enumerator_main() { + ################# MAIN PROGRAM by default + + # Note: do not use the read..._once() here, to ensure that the + # looped daemon sees the whole picture, which can be new every time + upslist_readFile || return $? + #upslist_debug + upslist_readSvcs "before manipulations" + + # Test if global config has changed since last run + RESTART_ALL=no + upssvcconf_checksum_unchanged "" || { echo "`date -u` : Detected changes in global section of '$UPSCONF', will restart all drivers"; RESTART_ALL=yes; } + + # Quickly exit if there's nothing to do; note the lists are pre-sorted + # Otherwise a non-zero exit will be done below + # Note: We implement testing in detail whether section definitions were + # changed since last run, as a first step before checking that name + # lists are still equivalent, because we need to always have the result + # of the "has it changed?" check as a hit-list of something to remove, + # while the check for no new device section definitions is just boolean. + # We can only exit quickly if both there are no changed sections and no + # new or removed sections since last run. + NEW_CHECKSUM="`upslist_checksums_unchanged "$UPSLIST_FILE" "$UPSLIST_SVCS"`" \ + && [ -z "$NEW_CHECKSUM" ] \ + && upslist_equals "$UPSLIST_FILE" "$UPSLIST_SVCS" \ + && if [ -z "$DAEMON_SLEEP" -o "${VERBOSE_LOOP}" = yes ] ; then \ + echo "`date -u` : OK: No changes to reconcile between ${SERVICE_FRAMEWORK} service instances and device configurations in '$UPSCONF'" ; \ + fi \ + && [ "$RESTART_ALL" = no ] && return 0 + + if [ -n "$NEW_CHECKSUM" ]; then + for UPSS in $NEW_CHECKSUM ; do + echo "Dropping old ${SERVICE_FRAMEWORK} service instance ${UPSS} whose section in config file has changed..." >&2 + $hook_unregisterInstance "$UPSS" + done + upslist_readSvcs "after updating for new config section checksums" + fi + + if [ -n "$UPSLIST_SVCS" ]; then + # Drop services that are not in config file (any more?) + upslist_delSvcs + + if [ "$RESTART_ALL" = yes ] && [ "$AUTO_START" = yes ] ; then + # Here restart only existing services; new ones will (try to) + # start soon after creation and upsd is handled below + upslist_restartSvcs + fi + fi + + if [ "$RESTART_ALL" = yes ] ; then + # Save new checksum of global config + $hook_setSavedMD5 "" "`upsconf_getSection_MD5 ""`" + fi + + if [ -n "$UPSLIST_FILE" ]; then + # Add services for sections that are in config file but not yet wrapped + upslist_addSvcs + $hook_refreshSupervizor + upslist_readSvcs "after checking for new config sections to define service instances" + fi + + upslist_readSvcs + if [ -n "$UPSLIST_SVCS" ] ; then + echo "=== The currently defined service instances are:" + echo "$UPSLIST_SVCS" + fi + + if [ -n "$UPSLIST_FILE" ] ; then + echo "=== The currently defined configurations in '$UPSCONF' are:" + echo "$UPSLIST_FILE" + fi + + # We had some changes to the config file; upsd must be made aware + if [ "$AUTO_START" = yes ] ; then + $hook_restart_upsd + fi + + # Return 42 if there was a change applied succesfully + # (but e.g. some services should restart - upsd, maybe upsmon) + UPSLIST_EQ_RES=0 + upslist_equals "$UPSLIST_FILE" "$UPSLIST_SVCS" || UPSLIST_EQ_RES=$? + + # File processing and service startups take a while; + # make sure upsconf did not change while we worked... + # NOTE: Check this at the last moment to minimize + # the chance of still not noticing the change made + # at just the wrong moment. + UPSCONF_CHECKSUM_END="`calc_md5_file "$UPSCONF"`" || true + if [ "$UPSCONF_CHECKSUM_END" != "$UPSCONF_CHECKSUM_START" ] ; then + # NOTE: even if daemonized, the sleep between iterations + # can be configured into an uncomfortably long lag, so + # we should re-sync the system config in any case. + echo "`date -u` : '$UPSCONF' changed while $0 $* was processing its older contents; re-running the script to pick up the late-coming changes" + # Make sure the cycle does not repeat itself due to diffs + # from an ages-old state of the file from when we started. + UPSCONF_CHECKSUM_START="$UPSCONF_CHECKSUM_END" + ( nut_driver_enumerator_main ) ; return $? + # The "main" routine at the end of recursions will + # do REPORT_RESTART_42 logic or the error exit-code + fi + + if [ "$UPSLIST_EQ_RES" = 0 ] ; then + echo "`date -u` : OK: No more changes to reconcile between ${SERVICE_FRAMEWORK} service instances and device configurations in '$UPSCONF'" + [ "${REPORT_RESTART_42-}" = no ] && return 0 || return 42 + fi + return 13 +} + +daemonize() ( + # Support (SIG)HUP == signal code 1 to quickly reconfigure, + # e.g. to request it while the sleep is happening or while + # "main" is processing an earlier change of the file. + RECONFIGURE_ASAP=false + trap 'RECONFIGURE_ASAP=true' 1 + + # Note: this loop would die on errors with config file or + # inability to ensure that it matches the list of services. + # If caller did not `export REPORT_RESTART_42=no` then the + # loop would exit with code 42, and probably trigger restart + # of the service which wraps this daemon do topple others that + # depend on it. + # Note: do not quickly skip the "main" based on full-file + # checksum refresh, to ensure that whatever is configured + # gets applied (e.g. if user disabled some services or they + # died, or some config was not applied due to coding error). + while nut_driver_enumerator_main ; do + if $RECONFIGURE_ASAP ; then + echo "`date -u` : Trapped a SIGHUP during last run of nut_driver_enumerator_main, repeating reconfiguration quickly" >&2 + else + sleep $DAEMON_SLEEP & + trap "kill $! ; echo 'Sleep interrupted, processing configs now!'>&2" 1 + wait $! + fi + RECONFIGURE_ASAP=false + trap 'RECONFIGURE_ASAP=true' 1 + done + exit $? +) + +# Save the checksum of ups.conf as early as possible, +# to test in the end that it is still the same file. +UPSCONF_CHECKSUM_START="`calc_md5_file "$UPSCONF"`" || true + +# By default, update wrapping of devices into services +if [ $# = 0 ]; then + nut_driver_enumerator_main ; exit $? +fi + +if [ $# = 1 ] ; then + [ -n "$DAEMON_SLEEP" ] || DAEMON_SLEEP=60 + # Note: Not all shells have 'case ... ;&' support + case "$1" in + --daemon=*) DAEMON_SLEEP="`echo "$1" | sed 's,^--daemon=,,'`" ;; + esac + case "$1" in + --daemon|--daemon=*) + daemonize & + exit $? + ;; + esac +fi +unset DAEMON_SLEEP + +usage() { + cat << EOF +$0 (no args) + Update wrapping of devices into services +$0 --daemon(=freq) + Update wrapping of devices into services in an infinite loop + Default freq is 60 sec +$0 --reconfigure + Stop and un-register all service instances and recreate them + (e.g. if new dependency template was defined in a new + version of this script and/or NUT package) +$0 --get-service-framework + Print the detected service + management framework in this OS +$0 --list-devices + Print list of devices in NUT config +$0 --list-services + Print list of service instances which wrap registered + NUT devices (full name of service unit) +$0 --list-instances + Print list of service instances which wrap registered + NUT devices (just instance suffix) +$0 --get-service-for-device DEV + Print the full name of service unit which wraps a NUT + device named "DEV" +$0 --get-device-for-service SVC + Print the NUT device name for full or instance-suffix name of + a service unit which wraps it +$0 --list-services-for-devices + Print a TAB-separated list of service units and corresponding + NUT device names which each such unit wraps +$0 --show-configs|--show-all-configs + Show the complete normalized list of device configuration blocks +$0 --show-config DEV +$0 --show-device-config DEV + Show configuration block of the specified NUT device +$0 --show-device-config-value DEV KEY [KEY...] + Show single configuration key value of the specified NUT device + For flags, shows the flag name if present in the section + If several keys or flags are requested, their values are reported + one per line in the same order (including empty lines for missing + values); any missing value yields a non-zero exit code. +EOF +} + +while [ $# -gt 0 ]; do + case "$1" in + --help|-h|-help) usage; exit 0 ;; + --get-service-framework) echo "${SERVICE_FRAMEWORK}" ; exit 0 ;; + --reconfigure) + upslist_readFile_once || exit $? + upslist_readSvcs "before manipulations" + + if [ -n "$UPSLIST_SVCS" ]; then + for UPSS in $UPSLIST_SVCS ; do + echo "Dropping old ${SERVICE_FRAMEWORK} service instance for power device [${UPSS}] to reconfigure the service unit..." >&2 + $hook_unregisterInstance "$UPSS" + done + upslist_readSvcs "after dropping" + fi + + if [ -n "$UPSLIST_FILE" ]; then + upslist_addSvcs + upslist_readSvcs "after checking for new config sections to define service instances" + fi + + # Save new checksum of global config + $hook_setSavedMD5 "" "`upsconf_getSection_MD5 ""`" + + # Service units were manipulated, including saving of checksums; + # refresh the service management daemon if needed + $hook_refreshSupervizor + + if [ -n "$UPSLIST_SVCS" ] ; then + echo "=== The currently defined service instances are:" + echo "$UPSLIST_SVCS" + fi + + if [ -n "$UPSLIST_FILE" ] ; then + echo "=== The currently defined configurations in '$UPSCONF' are:" + echo "$UPSLIST_FILE" + fi + + # We had some changes to the config file; upsd must be made aware + if [ "$AUTO_START" = yes ] ; then + $hook_restart_upsd + fi + + # Return 42 if there was a change applied succesfully + # (but e.g. some services should restart - upsd, maybe upsmon) + UPSLIST_EQ_RES=0 + upslist_equals "$UPSLIST_FILE" "$UPSLIST_SVCS" || UPSLIST_EQ_RES=$? + + # File processing and service startups take a while; + # make sure upsconf did not change while we worked... + # NOTE: Check this at the last moment to minimize + # the chance of still not noticing the change made + # at just the wrong moment. + UPSCONF_CHECKSUM_END="`calc_md5_file "$UPSCONF"`" || true + if [ "$UPSCONF_CHECKSUM_END" != "$UPSCONF_CHECKSUM_START" ] ; then + echo "`date -u` : '$UPSCONF' changed while $0 $* was processing its older contents; re-running the script to pick up the late-coming changes" + $0 ; exit $? + # The "main" routine will do REPORT_RESTART_42 logic too + fi + + if [ "$UPSLIST_EQ_RES" = 0 ] ; then + echo "`date -u` : OK: No more changes to reconcile between ${SERVICE_FRAMEWORK} service instances and device configurations in '$UPSCONF'" + [ "${REPORT_RESTART_42-}" = no ] && exit 0 || exit 42 + fi + + exit 13 + ;; + --list-devices) + upslist_readFile_once && \ + if [ -n "$UPSLIST_FILE" ] ; then + echo "=== The currently defined configurations in '$UPSCONF' are:" >&2 + echo "$UPSLIST_FILE" + exit 0 + fi + echo "No devices detected in '$UPSCONF'" >&2 + exit 1 + ;; + --list-services) + UPSLIST_SVCS_RAW="`$hook_listInstances_raw`" && \ + if [ -n "$UPSLIST_SVCS_RAW" ] ; then + echo "=== The currently defined service units are:" >&2 + echo "$UPSLIST_SVCS_RAW" + exit 0 + fi + echo "No service units detected" >&2 + exit 1 + ;; + --list-instances) + upslist_readSvcs "by user request" && \ + if [ -n "$UPSLIST_SVCS" ] ; then + echo "=== The currently defined service instances are:" >&2 + echo "$UPSLIST_SVCS" + exit 0 + fi + echo "No service instances detected" >&2 + exit 1 + ;; + --get-service-for-device) [ -z "$2" ] && echo "Device name argument required" >&2 && exit 1 + DEV="$2" + upslist_readSvcs "by user request" && [ -n "$UPSLIST_SVCS" ] \ + || { echo "No service instances detected" >&2 ; exit 1; } + UPSLIST_SVCS_RAW="`$hook_listInstances_raw`" && [ -n "$UPSLIST_SVCS_RAW" ] \ + || { echo "No service units detected" >&2 ; exit 1; } + vINST="`$hook_validInstanceName "$DEV"`" + vUNITD="`$hook_validFullUnitName "$DEV"`" + vUNITI="`$hook_validFullUnitName "$vINST"`" + # First pass over simple verbatim names + for INST in $UPSLIST_SVCS ; do + if [ "$INST" = "$DEV" ] ; then + for UNIT in $UPSLIST_SVCS_RAW ; do + if [ "$UNIT" = "$vUNITD" ] ; then + echo "$UNIT" + exit 0 + fi + done + fi + done + for INST in $UPSLIST_SVCS ; do + if [ "$INST" = "$vINST" ] ; then + for UNIT in $UPSLIST_SVCS_RAW ; do + if [ "$UNIT" = "$vUNITI" ] ; then + echo "$UNIT" + exit 0 + fi + done + fi + done + echo "No service instances detected that match device '$2'" >&2 + exit 1 + ;; + --get-device-for-service) [ -z "$2" ] && echo "Service (instance) name argument required" >&2 && exit 1 + # Instance name can be a hash or "native" NUT section name + SVC="`$hook_validInstanceSuffixName "$2"`" + case "$SVC" in + MD5_*) ;; # fall through to the bulk of code + *) upslist_readFile_once || exit $? + echo "$UPSLIST_FILE" | egrep "^$SVC\$" + exit $? + ;; + esac + FINAL_RES=0 + OUT="`"$0" --list-services-for-devices`" && [ -n "$OUT" ] || FINAL_RES=$? + if [ "$FINAL_RES" = 0 ]; then + echo "$OUT" | grep "$SVC" | ( \ + while read _SVC _DEV ; do + _SVC="`$hook_validInstanceSuffixName "${_SVC}"`" || exit + [ "${_SVC}" = "${SVC}" ] && echo "$_DEV" && exit 0 + done ; exit 1 ) && exit 0 + fi + echo "No service instance '$2' was detected that matches a NUT device" >&2 + exit 1 + ;; + --list-services-for-devices) + FINAL_RES=0 + upslist_readFile_once && [ -n "$UPSLIST_FILE" ] \ + || { echo "No devices detected in '$UPSCONF'" >&2 ; exit 1 ; } + upslist_readSvcs "by user request" && [ -n "$UPSLIST_SVCS" ] \ + || { echo "No service instances detected" >&2 ; exit 1; } + UPSLIST_SVCS_RAW="`$hook_listInstances_raw`" && [ -n "$UPSLIST_SVCS_RAW" ] \ + || { echo "No service units detected" >&2 ; exit 1; } + for DEV in $UPSLIST_FILE ; do + vINST="`$hook_validInstanceName "$DEV"`" + vUNITD="`$hook_validFullUnitName "$DEV"`" + vUNITI="`$hook_validFullUnitName "$vINST"`" + # First pass over simple verbatim names + for INST in $UPSLIST_SVCS ; do + if [ "$INST" = "$DEV" ] ; then + for UNIT in $UPSLIST_SVCS_RAW ; do + if [ "$UNIT" = "$vUNITD" ] ; then + printf '%s\t%s\n' "$UNIT" "$DEV" + continue 3 + fi + done + fi + done + for INST in $UPSLIST_SVCS ; do + if [ "$INST" = "$vINST" ] ; then + for UNIT in $UPSLIST_SVCS_RAW ; do + if [ "$UNIT" = "$vUNITI" ] ; then + printf '%s\t%s\n' "$UNIT" "$DEV" + continue 3 + fi + done + fi + done + echo "WARNING: no service instances detected that match device '$DEV'" >&2 + FINAL_RES=1 + done + exit $FINAL_RES + ;; + --show-configs|--show-device-configs|--show-all-configs|--show-all-device-configs) + RES=0 + upslist_readFile_once || RES=$? + [ "$RES" != 0 ] && { echo "ERROR: upslist_readFile_once () failed with code $RES" >&2; exit $RES; } + [ -n "$UPSLIST_FILE" ] \ + || { echo "WARNING: No devices detected in '$UPSCONF'" >&2 ; RES=1 ; } + echo "$UPSCONF_DATA" + exit $RES + ;; + --show-config|--show-device-config) + [ -z "$2" ] && echo "WARNING: Device name argument empty, will show global config" >&2 + DEV="$2" + upsconf_getSection "$DEV" + exit $? + ;; + --show-config-value|--show-device-config-value) + [ -z "$3" ] && echo "At least one configuration key name argument is required" >&2 && exit 1 + [ -z "$2" ] && echo "WARNING: Device name argument empty, will show global config" >&2 + DEV="$2" + shift 2 + upsconf_getValue "$DEV" "$@" + exit $? + ;; + upsconf_debug) # Not public, not in usage() + [ -z "$2" ] && echo "Device name argument required" >&2 && exit 1 + upsconf_debug "$2" + exit $? + ;; + upslist_debug) # Not public, not in usage() + upslist_readFile_once || exit + upslist_debug + exit $? + ;; + *) echo "Unrecognized argument: $1" >&2 ; exit 1 ;; + esac + shift +done diff --git a/scripts/upsdrvsvcctl/upsdrvsvcctl.in b/scripts/upsdrvsvcctl/upsdrvsvcctl.in new file mode 100755 index 0000000000..d9e127c82f --- /dev/null +++ b/scripts/upsdrvsvcctl/upsdrvsvcctl.in @@ -0,0 +1,196 @@ +#!/bin/sh +# +# Copyright (C) 2016-2018 Eaton +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +#! \file upsdrvsvcctl(.in) +# \author Jim Klimov +# \brief Manage NUT devices registered as service-unit instances +# + +if [ -z "${SERVICE_FRAMEWORK-}" ] ; then + [ -x /usr/sbin/svcadm ] && [ -x /usr/sbin/svccfg ] && [ -x /usr/bin/svcs ] && \ + SERVICE_FRAMEWORK="smf" + [ -z "${SERVICE_FRAMEWORK-}" ] && \ + [ -x /bin/systemctl ] && \ + SERVICE_FRAMEWORK="systemd" +fi + +VERB="" +CMD="" +CMDARG="" +ENUMERATOR="" +case "$SERVICE_FRAMEWORK" in + smf) CMD="/usr/sbin/svcadm" + ENUMERATOR="@NUT_LIBEXECDIR@/nut-driver-enumerator.sh" + ;; + systemd) CMD="/bin/systemctl" + ENUMERATOR="@NUT_LIBEXECDIR@/nut-driver-enumerator.sh" + ;; + *) echo "Unrecognized SERVICE_FRAMEWORK: $SERVICE_FRAMEWORK" >&2 ; exit ;; +esac + + +usage() { + # Note: version header differs from UPS_VERSION in binaries that + # might also have the git-version suffixed during build time + cat << EOF +Network UPS Tools - UPS driver controller ${PACKAGE_VERSION} +Starts and stops UPS drivers via system service instances, see +the $ENUMERATOR +script for more details. + +usage: $0 [OPTIONS] (start | stop | shutdown) [] + +Options: + -h display this help + -t testing mode - prints actions without doing them + -D raise debugging level + start start all UPS drivers in ups.conf + start only start driver for UPS + stop stop all UPS drivers in ups.conf + stop only stop driver for UPS + +Note: the "shutdown" options from original upsdrvctl are not currently +directly supported by this service management framework wrapper; instead +they are passed to the native upsdrvctl binary (your current user account +should have sufficient permissions to do that all): + shutdown shutdown all UPS drivers in ups.conf + shutdown only shutdown UPS + +usage: $0 [OPTIONS] resync + resync call $ENUMERATOR + to update the mapping of service instances for + NUT drivers to device sections in 'ups.conf' + +usage: $0 [OPTIONS] reconfigure + reconfigure call $ENUMERATOR + to remove and re-create the mapping of all service + instances for NUT drivers to device sections in + 'ups.conf' e.g. after a NUT package upgrade + +usage: $0 [OPTIONS] list [] + list call $ENUMERATOR + to list the mapping of service instances to device sections + list (optionally return the service instance name for one device) + +usage: $0 [OPTIONS] show-config [] + show-config output config section from ups.conf for device + show-config ...or all devices if no argument was passed +EOF +} + +ACTION="" +SVCINST="" +DRYRUN="" +DEBUG=0 +# Note: DEBUG is UNUSED_PARAM so far +while [ $# -gt 0 ]; do + case "$1" in + resync) eval $DRYRUN $ENUMERATOR ; exit $? ;; + reconf|reconfigure) eval $DRYRUN $ENUMERATOR --reconfigure ; exit $? ;; + list) + if [ -n "$2" ] ; then + eval $ENUMERATOR --get-service-for-device "$2" ; exit $? + else + eval $ENUMERATOR --list-services-for-devices ; exit $? + fi + ;; + show-config) + if [ -n "$2" ] ; then + eval $ENUMERATOR --show-device-config "$2" ; exit $? + else + eval $ENUMERATOR --show-all-configs ; exit $? + fi + ;; + start|stop) + ACTION="$1" + if [ -n "$2" ] ; then + SVCINST="`$ENUMERATOR --get-service-for-device "$2"`" || exit + shift + fi + ;; + shutdown) + echo "NOTE: Action '$1' is not implemented via services currently, will call upsdrvctl" >&2 + echo "Stopping the driver service instance(s) to release exclusive resources, if any..." >&2 + RES=0 + $0 stop $2 + @SBINDIR@/upsdrvctl shutdown $2 || RES=$? + echo "Starting the driver service instance(s) so they can reconnect when the UPS returns..." >&2 + $0 start $2 + exit $RES + ;; + -t) DRYRUN="echo" ;; + -h) usage; exit 0 ;; + -D) DEBUG="`expr $DEBUG + 1`" ;; + -r|-u) echo "Option '$1 $2' is not implemented via services currently" >&2 ; shift;; + *) echo "Unrecognized argument: $1" >&2 ; exit ;; + esac + shift +done + +if [ -z "$ENUMERATOR" ] || [ ! -s "$ENUMERATOR" ] || [ ! -x "$ENUMERATOR" ] ; then + echo "ENUMERATOR script (nut-driver-enumerator.sh) not found!" >&2 + exit 1 +fi + +if [ -z "$ACTION" ]; then + echo "No action was requested!" >&2 + exit 1 +fi + +if [ -z "$SVCINST" ]; then + SVCINST="`$ENUMERATOR --list-services`" || exit +fi + +# TODO: Support shutdown of one or all UPSes by stopping its service +# and then calling the original upsdrvctl on it? +case "$ACTION" in + start) + VERB="Starting" + case "$SERVICE_FRAMEWORK" in + smf) CMDARG="enable -ts" ;; + systemd) CMDARG="start" ;; + esac + ;; + stop) + VERB="Stopping" + case "$SERVICE_FRAMEWORK" in + smf) CMDARG="disable -ts" ;; + systemd) CMDARG="stop" ;; + esac + ;; + *) echo "Unrecognized ACTION: $ACTION" >&2 ; exit ;; +esac + +for INST in $SVCINST ; do + echo "$VERB $INST ..." >&2 + $DRYRUN $CMD $CMDARG "$INST" & +done +wait + +case "$SERVICE_FRAMEWORK" in + smf) + sleep 1 + echo "Post-process clearing services that failed early..." >&2 + for INST in $SVCINST ; do + echo "Clearing $INST (if it got broken) ..." >&2 + $DRYRUN $CMD clear "$INST" & + done + ;; +esac + +wait diff --git a/server/conf.c b/server/conf.c index aea8220cd7..50404ea54f 100644 --- a/server/conf.c +++ b/server/conf.c @@ -23,6 +23,7 @@ #include "sstate.h" #include "user.h" #include "netssl.h" +#include ups_t *upstable = NULL; int num_ups = 0; @@ -121,14 +122,58 @@ static int parse_upsd_conf_args(int numargs, char **arg) /* MAXAGE */ if (!strcmp(arg[0], "MAXAGE")) { - maxage = atoi(arg[1]); - return 1; + if (isdigit(arg[1][0])) { + maxage = atoi(arg[1]); + return 1; + } + else { + upslogx(LOG_ERR, "MAXAGE has non numeric value (%s)!", arg[1]); + return 0; + } + } + + /* TRACKINGDELAY */ + if (!strcmp(arg[0], "TRACKINGDELAY")) { + if (isdigit(arg[1][0])) { + tracking_delay = atoi(arg[1]); + return 1; + } + else { + upslogx(LOG_ERR, "TRACKINGDELAY has non numeric value (%s)!", arg[1]); + return 0; + } + } + + /* ALLOW_NO_DEVICE */ + if (!strcmp(arg[0], "ALLOW_NO_DEVICE")) { + if (isdigit(arg[1][0])) { + allow_no_device = (atoi(arg[1]) != 0); // non-zero arg is true here + return 1; + } + else { + if ( (!strcasecmp(arg[1], "true")) || (!strcasecmp(arg[1], "on")) || (!strcasecmp(arg[1], "yes"))) { + allow_no_device = 1; + return 1; + } + if ( (!strcasecmp(arg[1], "false")) || (!strcasecmp(arg[1], "off")) || (!strcasecmp(arg[1], "no"))) { + allow_no_device = 0; + return 1; + } + upslogx(LOG_ERR, "ALLOW_NO_DEVICE has non numeric and non boolean value (%s)!", arg[1]); + return 0; + } } /* MAXCONN */ if (!strcmp(arg[0], "MAXCONN")) { - maxconn = atoi(arg[1]); - return 1; + if (isdigit(arg[1][0])) { + maxconn = atoi(arg[1]); + return 1; + } + else { + upslogx(LOG_ERR, "MAXCONN has non numeric value (%s)!", arg[1]); + return 0; + } } /* STATEPATH */ @@ -162,8 +207,14 @@ static int parse_upsd_conf_args(int numargs, char **arg) #ifdef WITH_CLIENT_CERTIFICATE_VALIDATION /* CERTREQUEST (0 | 1 | 2) */ if (!strcmp(arg[0], "CERTREQUEST")) { - certrequest = atoi(arg[1]); - return 1; + if (isdigit(arg[1][0])) { + certrequest = atoi(arg[1]); + return 1; + } + else { + upslogx(LOG_ERR, "CERTREQUEST has non numeric value (%s)!", arg[1]); + return 0; + } } #endif /* WITH_CLIENT_CERTIFICATE_VALIDATION */ #endif /* WITH_OPENSSL | WITH_NSS */ diff --git a/server/netget.c b/server/netget.c index 5ab41c3f3a..55a27a429c 100644 --- a/server/netget.c +++ b/server/netget.c @@ -216,6 +216,25 @@ static void get_var(nut_ctype_t *client, const char *upsname, const char *var) void net_get(nut_ctype_t *client, int numarg, const char **arg) { + if (numarg < 1) { + send_err(client, NUT_ERR_INVALID_ARGUMENT); + return; + } + + /* GET TRACKING [ID] */ + if (!strcasecmp(arg[0], "TRACKING")) { + if (numarg < 2) { + sendback(client, "%s\n", (client->tracking) ? "ON" : "OFF"); + } + else { + if (client->tracking) + sendback(client, "%s\n", tracking_get(arg[1])); + else + send_err(client, NUT_ERR_FEATURE_NOT_CONFIGURED); + } + return; + } + if (numarg < 2) { send_err(client, NUT_ERR_INVALID_ARGUMENT); return; diff --git a/server/netinstcmd.c b/server/netinstcmd.c index c21d7ec1d7..3c4ccc8212 100644 --- a/server/netinstcmd.c +++ b/server/netinstcmd.c @@ -29,9 +29,9 @@ #include "netinstcmd.h" static void send_instcmd(nut_ctype_t *client, const char *upsname, - const char *cmdname, const char *value) + const char *cmdname, const char *value, const char *tracking_id) { - int found; + int found, have_tracking_id = 0; upstype_t *ups; const cmdlist_t *ctmp; char sockcmd[SMALLBUF], esc[SMALLBUF]; @@ -70,20 +70,30 @@ static void send_instcmd(nut_ctype_t *client, const char *upsname, return; } - /* see if the user has also passed a value for this command */ - if (value != NULL) { - upslogx(LOG_INFO, "Instant command: %s@%s did %s with value \"%s\" on %s", - client->username, client->addr, cmdname, value, ups->name); + /* Format the base command */ + snprintf(sockcmd, sizeof(sockcmd), "INSTCMD %s", cmdname); - snprintf(sockcmd, sizeof(sockcmd), "INSTCMD %s %s\n", - cmdname, pconf_encode(value, esc, sizeof(esc))); + /* see if the user has also passed a value for this command */ + if (value != NULL) + snprintfcat(sockcmd, sizeof(sockcmd), " %s", pconf_encode(value, esc, sizeof(esc))); + + /* see if the user want execution tracking for this command */ + if (tracking_id && *tracking_id) { + snprintfcat(sockcmd, sizeof(sockcmd), " TRACKING %s", tracking_id); + /* Add an entry in the tracking structure */ + tracking_add(tracking_id); + have_tracking_id = 1; } - else { - upslogx(LOG_INFO, "Instant command: %s@%s did %s on %s", - client->username, client->addr, cmdname, ups->name); - snprintf(sockcmd, sizeof(sockcmd), "INSTCMD %s\n", cmdname); - } + /* add EOL */ + snprintfcat(sockcmd, sizeof(sockcmd), "\n"); + + upslogx(LOG_INFO, "Instant command: %s@%s did %s%s%s on %s (tracking ID: %s)", + client->username, client->addr, cmdname, + (value != NULL)?" with value ":"", + (value != NULL)?value:"", + ups->name, + (have_tracking_id) ? tracking_id : "disabled"); if (!sstate_sendline(ups, sockcmd)) { upslogx(LOG_INFO, "Set command send failed"); @@ -91,18 +101,38 @@ static void send_instcmd(nut_ctype_t *client, const char *upsname, return; } - /* FIXME: need to retrieve the cookie number */ - sendback(client, "OK\n"); + /* return the result, possibly including tracking_id */ + if (have_tracking_id) + sendback(client, "OK TRACKING %s\n", tracking_id); + else + sendback(client, "OK\n"); } void net_instcmd(nut_ctype_t *client, int numarg, const char **arg) { + const char *devname = NULL; + const char *cmdname = NULL; + const char *cmdparam = NULL; + char tracking_id[UUID4_LEN] = ""; + if (numarg < 2) { send_err(client, NUT_ERR_INVALID_ARGUMENT); return; } - - /* INSTCMD []*/ - send_instcmd(client, arg[0], arg[1], (numarg == 3)?arg[2]:NULL); + + /* INSTCMD [cmdparam] */ + /* Check arguments */ + devname = arg[0]; + cmdname = arg[1]; + if (numarg == 3) + cmdparam = arg[2]; + + if (client->tracking) { + /* Generate a tracking ID, if client requested status tracking */ + nut_uuid_v4(tracking_id); + } + + send_instcmd(client, devname, cmdname, cmdparam, tracking_id); + return; } diff --git a/server/netset.c b/server/netset.c index b88bb40f7d..a69aa96ff4 100644 --- a/server/netset.c +++ b/server/netset.c @@ -28,13 +28,14 @@ #include "netset.h" static void set_var(nut_ctype_t *client, const char *upsname, const char *var, - const char *newval) + const char *newval, const char *tracking_id) { upstype_t *ups; const char *val; const enum_t *etmp; const range_t *rtmp; char cmd[SMALLBUF], esc[SMALLBUF]; + int have_tracking_id = 0; ups = get_ups_ptr(upsname); @@ -134,31 +135,88 @@ static void set_var(nut_ctype_t *client, const char *upsname, const char *var, /* must be OK now */ - upslogx(LOG_INFO, "Set variable: %s@%s set %s on %s to %s", - client->username, client->addr, var, ups->name, newval); - - snprintf(cmd, sizeof(cmd), "SET %s \"%s\"\n", + snprintf(cmd, sizeof(cmd), "SET %s \"%s\"", var, pconf_encode(newval, esc, sizeof(esc))); + /* see if the user want execution tracking for this command */ + if (tracking_id && *tracking_id) { + snprintfcat(cmd, sizeof(cmd), " TRACKING %s", tracking_id); + /* Add an entry in the tracking structure */ + tracking_add(tracking_id); + have_tracking_id = 1; + } + + /* add EOL */ + snprintfcat(cmd, sizeof(cmd), "\n"); + + upslogx(LOG_INFO, "Set variable: %s@%s set %s on %s to %s (tracking ID: %s)", + client->username, client->addr, var, ups->name, newval, + (have_tracking_id) ? tracking_id : "disabled"); + if (!sstate_sendline(ups, cmd)) { upslogx(LOG_INFO, "Set command send failed"); send_err(client, NUT_ERR_SET_FAILED); return; } - sendback(client, "OK\n"); + /* return the result, possibly including tracking_id */ + if (have_tracking_id) + sendback(client, "OK TRACKING %s\n", tracking_id); + else + sendback(client, "OK\n"); } void net_set(nut_ctype_t *client, int numarg, const char **arg) { - if (numarg < 4) { + char tracking_id[UUID4_LEN] = ""; + + /* Base verification, to ensure that we have at least the SET parameter */ + if (numarg < 2) { send_err(client, NUT_ERR_INVALID_ARGUMENT); return; } /* SET VAR UPS VARNAME VALUE */ if (!strcasecmp(arg[0], "VAR")) { - set_var(client, arg[1], arg[2], arg[3]); + if (numarg < 4) { + send_err(client, NUT_ERR_INVALID_ARGUMENT); + return; + } + + if (client->tracking) { + /* Generate a tracking ID, if client requested status tracking */ + nut_uuid_v4(tracking_id); + } + + set_var(client, arg[1], arg[2], arg[3], tracking_id); + + return; + } + + /* SET TRACKING VALUE */ + if (!strcasecmp(arg[0], "TRACKING")) { + if (!strcasecmp(arg[1], "ON")) { + /* general enablement along with for this client */ + client->tracking = tracking_enable(); + } + else if (!strcasecmp(arg[1], "OFF")) { + /* disable status tracking for this client first */ + client->tracking = 0; + /* then only disable the general one if no other clients use it! + * Note: don't call tracking_free() since we want info to + * persist, and tracking_cleanup() takes care of cleaning */ + tracking_disable(); + } + else { + send_err(client, NUT_ERR_INVALID_ARGUMENT); + return; + } + upsdebugx(1, "%s: TRACKING general %s, client %s.", __func__, + tracking_is_enabled() ? "enabled" : "disabled", + client->tracking ? "enabled" : "disabled"); + + sendback(client, "OK\n"); + return; } diff --git a/server/netssl.c b/server/netssl.c index c2f409899d..cf9419edf8 100644 --- a/server/netssl.c +++ b/server/netssl.c @@ -275,7 +275,7 @@ void net_starttls(nut_ctype_t *client, int numarg, const char **arg) { case 1: client->ssl_connected = 1; - upsdebugx(3, "SSL connected"); + upsdebugx(3, "SSL connected (%s)", SSL_get_version(client->ssl)); break; case 0: @@ -371,13 +371,7 @@ void ssl_init(void) { #ifdef WITH_NSS SECStatus status; -#elif defined(WITH_OPENSSL) -#if OPENSSL_VERSION_NUMBER >= 0x10000000L - const SSL_METHOD *ssl_method; -#else - SSL_METHOD *ssl_method; -#endif -#endif /* WITH_NSS|WITH_OPENSSL */ +#endif /* WITH_NSS */ if (!certfile) { return; @@ -387,18 +381,29 @@ void ssl_init(void) #ifdef WITH_OPENSSL +#if OPENSSL_VERSION_NUMBER < 0x10100000L SSL_load_error_strings(); SSL_library_init(); - if ((ssl_method = TLSv1_server_method()) == NULL) { + ssl_ctx = SSL_CTX_new(SSLv23_server_method()); +#else + ssl_ctx = SSL_CTX_new(TLS_server_method()); +#endif + + if (!ssl_ctx) { ssl_debug(); - fatalx(EXIT_FAILURE, "TLSv1_server_method failed"); + fatalx(EXIT_FAILURE, "SSL_CTX_new failed"); } - if ((ssl_ctx = SSL_CTX_new(ssl_method)) == NULL) { +#if OPENSSL_VERSION_NUMBER < 0x10100000L + /* set minimum protocol TLSv1 */ + SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); +#else + if (SSL_CTX_set_min_proto_version(ssl_ctx, TLS1_VERSION) != 1) { ssl_debug(); - fatalx(EXIT_FAILURE, "SSL_CTX_new failed"); + fatalx(EXIT_FAILURE, "SSL_CTX_set_min_proto_version(TLS1_VERSION)"); } +#endif if (SSL_CTX_use_certificate_chain_file(ssl_ctx, certfile) != 1) { ssl_debug(); diff --git a/server/nut_ctype.h b/server/nut_ctype.h index c2302aadb8..54184d2baa 100644 --- a/server/nut_ctype.h +++ b/server/nut_ctype.h @@ -45,6 +45,9 @@ typedef struct nut_ctype_s { char *loginups; char *password; char *username; + /* per client status info for commands and settings + * (disabled by default) */ + int tracking; #ifdef WITH_OPENSSL SSL *ssl; diff --git a/server/sstate.c b/server/sstate.c index 15d2c1412e..0365cd30f6 100644 --- a/server/sstate.c +++ b/server/sstate.c @@ -25,6 +25,7 @@ #include "timehead.h" #include "sstate.h" +#include "upsd.h" #include "upstype.h" #include @@ -104,30 +105,45 @@ static int parse_args(upstype_t *ups, int numargs, char **arg) return 1; } - /* ADDRANGE */ - if (!strcasecmp(arg[0], "ADDRANGE")) { - state_addrange(ups->inforoot, arg[1], atoi(arg[2]), atoi(arg[3])); - return 1; - } - /* DELENUM */ if (!strcasecmp(arg[0], "DELENUM")) { state_delenum(ups->inforoot, arg[1], arg[2]); return 1; } - /* DELRANGE */ - if (!strcasecmp(arg[0], "DELRANGE")) { - state_delrange(ups->inforoot, arg[1], atoi(arg[2]), atoi(arg[3])); - return 1; - } - /* SETAUX */ if (!strcasecmp(arg[0], "SETAUX")) { state_setaux(ups->inforoot, arg[1], arg[2]); return 1; } + /* TRACKING */ + if (!strcasecmp(arg[0], "TRACKING")) { + tracking_set(arg[1], arg[2]); + upsdebugx(1, "TRACKING: ID %s status %s", arg[1], arg[2]); + + /* log actual result of instcmd / setvar */ + if (strncmp(arg[2], "PENDING", 7) != 0) { + upslogx(LOG_INFO, "tracking ID: %s\tresult: %s", arg[1], tracking_get(arg[1])); + } + return 1; + } + + if (numargs < 4) + return 0; + + /* ADDRANGE */ + if (!strcasecmp(arg[0], "ADDRANGE")) { + state_addrange(ups->inforoot, arg[1], atoi(arg[2]), atoi(arg[3])); + return 1; + } + + /* DELRANGE */ + if (!strcasecmp(arg[0], "DELRANGE")) { + state_delrange(ups->inforoot, arg[1], atoi(arg[2]), atoi(arg[3])); + return 1; + } + return 0; } @@ -385,7 +401,7 @@ int sstate_sendline(upstype_t *ups, const char *buf) ret = write(ups->sock_fd, buf, strlen(buf)); if (ret == (int)strlen(buf)) { - return 1; + return 1; } upslog_with_errno(LOG_NOTICE, "Send to UPS [%s] failed", ups->name); diff --git a/server/upsd.c b/server/upsd.c index c6efb217b8..dfbd2b75b1 100644 --- a/server/upsd.c +++ b/server/upsd.c @@ -4,6 +4,7 @@ 1999 Russell Kroll 2008 Arjen de Korte 2011 - 2012 Arnaud Quette + 2019 Eaton (author: Arnaud Quette ) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -53,6 +54,15 @@ int deny_severity = LOG_WARNING; /* default 15 seconds before data is marked stale */ int maxage = 15; + /* default to 1h before cleaning up status tracking entries */ + int tracking_delay = 3600; + + /* + * Preloaded to ALLOW_NO_DEVICE from upsd.conf or environment variable + * (with higher prio for envvar); defaults to disabled for legacy compat. + */ + int allow_no_device = 0; + /* preloaded to {OPEN_MAX} in main, can be overridden via upsd.conf */ int maxconn = 0; @@ -84,6 +94,28 @@ typedef struct { void *data; } handler_t; + +/* Commands and settings status tracking */ + +/* general enable/disable status info for commands and settings + * (disabled by default) + * Note that only client that requested it will have it enabled + * (see nut_ctype.h) */ +static int tracking_enabled = 0; + +/* Commands and settings status tracking structure */ +typedef struct tracking_s { + char *id; + int status; + time_t request_time; /* for cleanup */ + /* doubly linked list */ + struct tracking_s *prev; + struct tracking_s *next; +} tracking_t; + +static tracking_t *tracking_list = NULL; + + /* pollfd */ static struct pollfd *fds = NULL; static handler_t *handler = NULL; @@ -94,6 +126,11 @@ static char pidfn[SMALLBUF]; /* set by signal handlers */ static int reload_flag = 0, exit_flag = 0; +/* Minimalistic support for UUID v4 */ +/* Ref: RFC 4122 https://tools.ietf.org/html/rfc4122#section-4.1.2 */ +#define UUID4_BYTESIZE 16 + + static const char *inet_ntopW (struct sockaddr_storage *s) { static char str[40]; @@ -427,7 +464,7 @@ static void check_command(int cmdnum, nut_ctype_t *client, int numarg, } /* looks good - call the command */ - netcmds[cmdnum].func(client, numarg - 1, &arg[1]); + netcmds[cmdnum].func(client, numarg - 1, numarg > 1 ? &arg[1] : NULL); } /* parse requests from the network */ @@ -480,6 +517,8 @@ static void client_connect(stype_t *server) client->addr = xstrdup(inet_ntopW(&csock)); + client->tracking = 0; + pconf_init(&client->ctx, NULL); if (firstclient) { @@ -644,6 +683,7 @@ static void upsd_cleanup(void) server_free(); client_free(); driver_free(); + tracking_free(); free(statepath); free(datapath); @@ -672,6 +712,219 @@ void poll_reload(void) handler = xrealloc(handler, maxconn * sizeof(*handler)); } +/* instant command and setvar status tracking */ + +/* allocate a new status tracking entry */ +int tracking_add(const char *id) +{ + tracking_t *item; + + if ((!tracking_enabled) || (!id)) + return 0; + + item = xcalloc(1, sizeof(*item)); + + item->id = xstrdup(id); + item->status = STAT_PENDING; + time(&item->request_time); + + if (tracking_list) { + tracking_list->prev = item; + item->next = tracking_list; + } + + tracking_list = item; + + return 1; +} + +/* set status of a specific tracking entry */ +int tracking_set(const char *id, const char *value) +{ + tracking_t *item, *next_item; + + /* sanity checks */ + if ((!tracking_list) || (!id) || (!value)) + return 0; + + for (item = tracking_list; item; item = next_item) { + + next_item = item->next; + + if (!strcasecmp(item->id, id)) { + item->status = atoi(value); + return 1; + } + } + + return 0; /* id not found! */ +} + +/* free a specific tracking entry */ +int tracking_del(const char *id) +{ + tracking_t *item, *next_item; + + /* sanity check */ + if ((!tracking_list) || (!id)) + return 0; + + upsdebugx(3, "%s: deleting id %s", __func__, id); + + for (item = tracking_list; item; item = next_item) { + + next_item = item->next; + + if (strcasecmp(item->id, id)) + continue; + + if (item->prev) + item->prev->next = item->next; + else + /* deleting first entry */ + tracking_list = item->next; + + if (item->next) + item->next->prev = item->prev; + + free(item->id); + free(item); + + return 1; + + } + + return 0; /* id not found! */ +} + +/* free all status tracking entries */ +void tracking_free(void) +{ + tracking_t *item, *next_item; + + /* sanity check */ + if (!tracking_list) + return; + + upsdebugx(3, "%s", __func__); + + for (item = tracking_list; item; item = next_item) { + next_item = item->next; + tracking_del(item->id); + } +} + +/* cleanup status tracking entries according to their age and tracking_delay */ +void tracking_cleanup(void) +{ + tracking_t *item, *next_item; + time_t now; + + /* sanity check */ + if (!tracking_list) + return; + + time(&now); + + upsdebugx(3, "%s", __func__); + + for (item = tracking_list; item; item = next_item) { + + next_item = item->next; + + if (difftime(now, item->request_time) > tracking_delay) { + tracking_del(item->id); + } + } +} + +/* get status of a specific tracking entry */ +char *tracking_get(const char *id) +{ + tracking_t *item, *next_item; + + /* sanity checks */ + if ((!tracking_list) || (!id)) + return "ERR UNKNOWN"; + + for (item = tracking_list; item; item = next_item) { + + next_item = item->next; + + if (strcasecmp(item->id, id)) + continue; + + switch (item->status) + { + case STAT_PENDING: + return "PENDING"; + case STAT_HANDLED: + return "SUCCESS"; + case STAT_UNKNOWN: + return "ERR UNKNOWN"; + case STAT_INVALID: + return "ERR INVALID-ARGUMENT"; + case STAT_FAILED: + return "ERR FAILED"; + } + } + + return "ERR UNKNOWN"; /* id not found! */ +} + +/* enable general status tracking (tracking_enabled) and return its value (1). */ +int tracking_enable(void) +{ + tracking_enabled = 1; + + return tracking_enabled; +} + +/* disable general status tracking only if no client use it anymore. + * return the new value for tracking_enabled */ +int tracking_disable(void) +{ + nut_ctype_t *client, *cnext; + + for (client = firstclient; client; client = cnext) { + cnext = client->next; + if (client->tracking == 1) + return 1; + } + return 0; +} + +/* return current general status of tracking (tracking_enabled). */ +int tracking_is_enabled(void) +{ + return tracking_enabled; +} + +/* UUID v4 basic implementation + * Note: 'dest' must be at least `UUID4_LEN` long */ +int nut_uuid_v4(char *uuid_str) +{ + size_t i; + uint8_t nut_uuid[UUID4_BYTESIZE]; + + if (!uuid_str) + return 0; + + for (i = 0; i < UUID4_BYTESIZE; i++) + nut_uuid[i] = (unsigned)rand() + (unsigned)rand(); + + /* set variant and version */ + nut_uuid[6] = (nut_uuid[6] & 0x0F) | 0x40; + nut_uuid[8] = (nut_uuid[8] & 0x3F) | 0x80; + + return snprintf(uuid_str, UUID4_LEN, + "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X", + nut_uuid[0], nut_uuid[1], nut_uuid[2], nut_uuid[3], + nut_uuid[4], nut_uuid[5], nut_uuid[6], nut_uuid[7], + nut_uuid[8], nut_uuid[9], nut_uuid[10], nut_uuid[11], + nut_uuid[12], nut_uuid[13], nut_uuid[14], nut_uuid[15]); +} + /* service requests and check on new data */ static void mainloop(void) { @@ -690,6 +943,9 @@ static void mainloop(void) reload_flag = 0; } + /* cleanup instcmd/setvar status tracking entries if needed */ + tracking_cleanup(); + /* scan through driver sockets */ for (ups = firstups; ups && (nfds < maxconn); ups = ups->next) { @@ -722,6 +978,7 @@ static void mainloop(void) if (difftime(now, client->last_heard) > 60) { /* shed clients after 1 minute of inactivity */ + /* FIXME: create an upsd.conf parameter (CLIENT_INACTIVITY_DELAY) */ client_disconnect(client); continue; } @@ -890,7 +1147,7 @@ void check_perms(const char *fn) int main(int argc, char **argv) { - int i, cmd = 0; + int i, cmd = 0, cmdret = 0; char *chroot_path = NULL; const char *user = RUN_AS_USER; struct passwd *new_uid = NULL; @@ -959,8 +1216,8 @@ int main(int argc, char **argv) } if (cmd) { - sendsignalfn(pidfn, cmd); - exit(EXIT_SUCCESS); + cmdret = sendsignalfn(pidfn, cmd); + exit((cmdret == 0)?EXIT_SUCCESS:EXIT_FAILURE); } /* otherwise, we are being asked to start. @@ -1001,6 +1258,28 @@ int main(int argc, char **argv) /* handle upsd.conf */ load_upsdconf(0); /* 0 = initial */ + { // scope + /* As documented above, the ALLOW_NO_DEVICE can be provided via + * envvars and then has higher priority than an upsd.conf setting + */ + const char *envvar = getenv("ALLOW_NO_DEVICE"); + if ( envvar != NULL) { + if ( (!strncasecmp("TRUE", envvar, 4)) || (!strncasecmp("YES", envvar, 3)) || (!strncasecmp("ON", envvar, 2)) || (!strncasecmp("1", envvar, 1)) ) { + /* Admins of this server expressed a desire to serve + * anything on the NUT protocol, even if nothing is + * configured yet - tell the clients so, properly. + */ + allow_no_device = 1; + } else if ( (!strncasecmp("FALSE", envvar, 5)) || (!strncasecmp("NO", envvar, 2)) || (!strncasecmp("OFF", envvar, 3)) || (!strncasecmp("0", envvar, 1)) ) { + /* Admins of this server expressed a desire to serve + * anything on the NUT protocol, even if nothing is + * configured yet - tell the clients so, properly. + */ + allow_no_device = 0; + } + } + } // scope + /* start server */ server_load(); @@ -1019,7 +1298,11 @@ int main(int argc, char **argv) poll_reload(); if (num_ups == 0) { - fatalx(EXIT_FAILURE, "Fatal error: at least one UPS must be defined in ups.conf"); + if (allow_no_device) { + upslogx(LOG_WARNING, "Normally at least one UPS must be defined in ups.conf, currently there are none (please configure the file and reload the service)"); + } else { + fatalx(EXIT_FAILURE, "Fatal error: at least one UPS must be defined in ups.conf"); + } } /* try to bring in the var/cmd descriptions */ diff --git a/server/upsd.h b/server/upsd.h index 2b3a3a74d1..6b7cabb023 100644 --- a/server/upsd.h +++ b/server/upsd.h @@ -68,9 +68,29 @@ void server_free(void); void check_perms(const char *fn); -/* declarations from upsd.c */ +/* return values for instcmd / setvar status tracking, + * mapped on drivers/upshandler.h, apart from STAT_PENDING (initial state) */ +enum { + STAT_PENDING = -1, /* not yet completed */ + STAT_HANDLED = 0, /* completed successfully (NUT_SUCCESS or "OK") */ + STAT_UNKNOWN, /* unspecified error (NUT_ERR_UNKNOWN) */ + STAT_INVALID, /* invalid command/setvar (NUT_ERR_INVALID_ARGUMENT) */ + STAT_FAILED /* command/setvar failed (NUT_ERR_INSTCMD_FAILED / NUT_ERR_SET_FAILED) */ +}; + +/* Commands and settings status tracking functions */ +int tracking_add(const char *id); +int tracking_set(const char *id, const char *value); +int tracking_del(const char *id); +void tracking_free(void); +void tracking_cleanup(void); +char *tracking_get(const char *id); +int tracking_enable(void); +int tracking_disable(void); +int tracking_is_enabled(void); -extern int maxage, maxconn; +/* declarations from upsd.c */ +extern int maxage, maxconn, tracking_delay, allow_no_device; extern char *statepath, *datapath; extern upstype_t *firstups; extern nut_ctype_t *firstclient; @@ -91,6 +111,10 @@ extern nut_ctype_t *firstclient; #define shutdown_how 2 #endif +/* UUID v4 generation function + * Note: 'dest' must be at least `UUID4_LEN` long */ +int nut_uuid_v4(char *uuid_str); + #ifdef __cplusplus /* *INDENT-OFF* */ } diff --git a/tests/.gitignore b/tests/.gitignore index 547a8f4271..4237686589 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -2,3 +2,4 @@ /cppunittest.log /cppunittest.trs /test-suite.log +/selftest-rw/* diff --git a/tests/Makefile.am b/tests/Makefile.am index 5f39fac799..9388c5899d 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,6 +1,11 @@ # Network UPS Tools: tests +EXTRA_DIST = nut-driver-enumerator-test.sh nut-driver-enumerator-test--ups.conf + +if HAVE_CXX11 if HAVE_CPPUNIT +# Note: per configure script this "SHOULD" also assume +# that we HAVE_CXX11 - but better have it explicit TESTS = cppunittest @@ -22,6 +27,12 @@ cppunittest_SOURCES = $(CPPUNITTESTSRC) cpputest.cpp else !HAVE_CPPUNIT -EXTRA_DIST = example.cpp cpputest.cpp +EXTRA_DIST += example.cpp cpputest.cpp endif !HAVE_CPPUNIT + +else !HAVE_CXX11 + +EXTRA_DIST += example.cpp cpputest.cpp + +endif !HAVE_CXX11 diff --git a/tests/nut-driver-enumerator-test--ups.conf b/tests/nut-driver-enumerator-test--ups.conf new file mode 100644 index 0000000000..c2916e2117 --- /dev/null +++ b/tests/nut-driver-enumerator-test--ups.conf @@ -0,0 +1,71 @@ +# This is an ups.conf file for nut-driver-enumerator-test.sh +# It is intentionally written in different samples of markup, +# do not clean it up ;) + +maxstartdelay=180 +globalflag + +[dummy1] +driver = dummy-ups + port = file1.dev + desc = "This is ups-1" +[epdu-2] +# This is an ePDU +driver=netxml-ups +port="http://172.16.1.2" +synchronous=yes +[epdu-2-snmp] +driver=snmp-ups +port=172.16.1.2 +synchronous=no + +[usb_3] + driver = "usbhid-ups" + port = "auto" + +[serial.4] + + driver = serial-ups +driverflag + port = /dev/ttyS1 # some path + + +[dummy-proxy] +driver = "dummy-ups " + port = remoteUPS@RemoteHost.local + +[dummy-proxy-localhost] +driver = 'dummy-ups ' + port = "localUPS@127.0.0.1" + +[valueHasEquals] + driver = dummy=ups + port = file1.dev # key = val, right? + +[valueHasHashtag] + driver = dummy-ups + port = file#1.dev + +[valueHasQuotedHashtag] + driver = dummy-ups + port = "file#1.dev" + +[qx-serial] + driver=nutdrv_qx + port = /dev/ttyb + +[qx-usb1] + driver=nutdrv_qx + port = auto +[qx-usb2] + driver=nutdrv_qx + port = /dev/usb/8 +[sectionWithComment]# Some comment + driver=nutdrv_qx#comment + port = /dev/usb/8 + desc="value with [brackets]" + [brackets with spaces are not sections] # but rather an invalid mess as binary parser may think + [sectionWithCommentWhitespace] # Some comment with a space and tab + driver=nutdrv_qx # comment + port = /dev/usb/8 # comment + commentedDriverFlag # This flag gotta mean something diff --git a/tests/nut-driver-enumerator-test.sh b/tests/nut-driver-enumerator-test.sh new file mode 100755 index 0000000000..dd32e73b72 --- /dev/null +++ b/tests/nut-driver-enumerator-test.sh @@ -0,0 +1,311 @@ +#!/bin/sh + +# Copyright (C) 2018 Eaton +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +#! \file nut-driver-enumerator-test.sh +# \author Jim Klimov +# \brief Self-test for nut-driver-enumerator.sh utility +# \details Automated sanity test for nut-driver-enumerator.sh(.in) +# using different shells (per $SHELL_PROGS) and CLI requests +# for regression and compatibility tests as well as for TDD +# fueled by pre-decided expected outcomes. + +### Use a standard locale setup so sorting in expected results is not confused +LANG=C +LC_ALL=C +TZ=UTC +export LANG LC_ALL TZ + +### Note: These are relative to where the selftest script lives, +### not the NUT top_srcdir etc. They can be exported by a Makefile. +[ -n "${BUILDDIR-}" ] || BUILDDIR="`dirname $0`" +[ -n "${SRCDIR-}" ] || SRCDIR="`dirname $0`" +[ -n "${SHELL_PROGS-}" ] || SHELL_PROGS="/bin/sh" +case "${DEBUG-}" in + [Yy]|[Yy][Ee][Ss]) DEBUG=yes ;; + [Tt][Rr][Aa][Cc][Ee]) DEBUG=trace ;; + *) DEBUG="" ;; +esac + +SYSTEMD_CONFPATH="${BUILDDIR}/selftest-rw/systemd-units" +export SYSTEMD_CONFPATH + +NUT_CONFPATH="${BUILDDIR}/selftest-rw/nut" +export NUT_CONFPATH + +[ -n "${UPSCONF-}" ] || UPSCONF="${SRCDIR}/nut-driver-enumerator-test--ups.conf" +[ ! -s "${UPSCONF-}" ] && echo "FATAL : testing ups.conf not found as '$UPSCONF'" >&2 && exit 1 +export UPSCONF + +if [ ! -n "${NDE-}" ] ; then + for NDE in \ + "${BUILDDIR}/../scripts/upsdrvsvcctl/nut-driver-enumerator.sh" \ + "${SRCDIR}/../scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in" \ + ; do [ -s "$NDE" ] && break ; done +fi +[ ! -s "${NDE-}" ] && echo "FATAL : testing nut-driver-enumerator.sh implementation not found as '$NDE'" >&2 && exit 1 + +# TODO : Add tests that generate configuration files for units +#mkdir -p "${NUT_CONFPATH}" "${SYSTEMD_CONFPATH}" || exit + +FAIL_COUNT=0 +GOOD_COUNT=0 +callNDE() { + case "$DEBUG" in + yes) time $USE_SHELL $NDE "$@" ;; + trace) time $USE_SHELL -x $NDE "$@" ;; + *) $USE_SHELL $NDE "$@" 2>/dev/null ;; + esac +} + +run_testcase() { + # First 3 args are required as defined below; the rest are + # CLI arg(s) to nut-driver-enumerator.sh + CASE_DESCR="$1" + EXPECT_CODE="$2" + EXPECT_TEXT="$3" + shift 3 + + printf "Testing : SHELL='%s'\tCASE='%s'\t" "$USE_SHELL" "$CASE_DESCR" + OUT="`callNDE "$@"`" ; RESCODE=$? + printf "Got : RESCODE='%s'\t" "$RESCODE" + + RES=0 + if [ "$RESCODE" = "$EXPECT_CODE" ]; then + printf "STATUS_CODE='MATCHED'\t" + GOOD_COUNT="`expr $GOOD_COUNT + 1`" + else + printf "STATUS_CODE='MISMATCH' expect_code=%s received_code=%s\t" "$EXPECT_CODE" "$RESCODE" >&2 + FAIL_COUNT="`expr $FAIL_COUNT + 1`" + RES="`expr $RES + 1`" + fi + + if [ "$OUT" = "$EXPECT_TEXT" ]; then + printf "STATUS_TEXT='MATCHED'\n" + GOOD_COUNT="`expr $GOOD_COUNT + 1`" + else + printf "STATUS_TEXT='MISMATCH'\n" + printf '\t--- expected ---\n%s\n\t--- received ---\n%s\n\t--- MISMATCH ABOVE\n\n' "$EXPECT_TEXT" "$OUT" >&2 + # Give a nice output to help track the problem: + ( rm -f "/tmp/.nde.text.expected.$$" "/tmp/.nde.text.actual.$$" \ + && echo "$EXPECT_TEXT" > "/tmp/.nde.text.expected.$$" \ + && echo "$OUT" > "/tmp/.nde.text.actual.$$" \ + && diff -u "/tmp/.nde.text.expected.$$" "/tmp/.nde.text.actual.$$" ) 2>/dev/null || true + rm -f "/tmp/.nde.text.expected.$$" "/tmp/.nde.text.actual.$$" + FAIL_COUNT="`expr $FAIL_COUNT + 1`" + RES="`expr $RES + 2`" + fi + if [ "$RES" != 0 ] || [ -n "$DEBUG" ] ; then echo "" ; fi + return $RES +} + +################################################################## +# Note: expectations in test cases below are tightly connected # +# to both the current code in the script and content of the test # +# configuration file. # +################################################################## + +testcase_bogus_args() { + run_testcase "Reject unknown args" 1 "" \ + --some-bogus-arg +} + +testcase_list_all_devices() { + # We expect a list of unbracketed names from the device sections + # Note: unlike other outputs, this list is alphabetically sorted + run_testcase "List all device names from sections" 0 \ +"dummy-proxy +dummy-proxy-localhost +dummy1 +epdu-2 +epdu-2-snmp +qx-serial +qx-usb1 +qx-usb2 +sectionWithComment +sectionWithCommentWhitespace +serial.4 +usb_3 +valueHasEquals +valueHasHashtag +valueHasQuotedHashtag" \ + --list-devices +} + +testcase_show_all_configs() { + # We expect whitespace trimmed, comment-only lines removed + run_testcase "Show all configs" 0 \ +'maxstartdelay=180 +globalflag +[dummy1] +driver=dummy-ups +port=file1.dev +desc="This is ups-1" +[epdu-2] +driver=netxml-ups +port=http://172.16.1.2 +synchronous=yes +[epdu-2-snmp] +driver=snmp-ups +port=172.16.1.2 +synchronous=no +[usb_3] +driver=usbhid-ups +port=auto +[serial.4] +driver=serial-ups +driverflag +port=/dev/ttyS1 # some path +[dummy-proxy] +driver="dummy-ups " +port=remoteUPS@RemoteHost.local +[dummy-proxy-localhost] +driver='"'dummy-ups '"' +port=localUPS@127.0.0.1 +[valueHasEquals] +driver=dummy=ups +port=file1.dev # key = val, right? +[valueHasHashtag] +driver=dummy-ups +port=file#1.dev +[valueHasQuotedHashtag] +driver=dummy-ups +port=file#1.dev +[qx-serial] +driver=nutdrv_qx +port=/dev/ttyb +[qx-usb1] +driver=nutdrv_qx +port=auto +[qx-usb2] +driver=nutdrv_qx +port=/dev/usb/8 +[sectionWithComment] +driver=nutdrv_qx#comment +port=/dev/usb/8 +desc="value with [brackets]" +[brackets with spaces are not sections] # but rather an invalid mess as binary parser may think +[sectionWithCommentWhitespace] +driver=nutdrv_qx # comment +port=/dev/usb/8 # comment +commentedDriverFlag # This flag gotta mean something' \ + --show-all-configs +} + +testcase_upslist_debug() { + # We expect a list of names, ports and decided MEDIA type (for dependencies) + run_testcase "List decided MEDIA and config checksums for all devices" 0 \ +"INST: 68b329da9893e34099c7d8ad5cb9c940~[]: DRV='' PORT='' MEDIA='' SECTIONMD5='9a1f372a850f1ee3ab1fc08b185783e0' +INST: 010cf0aed6dd49865bb49b70267946f5~[dummy-proxy]: DRV='dummy-ups ' PORT='remoteUPS@RemoteHost.local' MEDIA='network' SECTIONMD5='aff543fc07d7fbf83e81001b181c8b97' +INST: 1ea79c6eea3681ba73cc695f3253e605~[dummy-proxy-localhost]: DRV='dummy-ups ' PORT='localUPS@127.0.0.1' MEDIA='network-localhost' SECTIONMD5='73e6b7e3e3b73558dc15253d8cca51b2' +INST: 76b645e28b0b53122b4428f4ab9eb4b9~[dummy1]: DRV='dummy-ups' PORT='file1.dev' MEDIA='' SECTIONMD5='9e0a326b67e00d455494f8b4258a01f1' +INST: a293d65e62e89d6cc3ac6cb88bc312b8~[epdu-2]: DRV='netxml-ups' PORT='http://172.16.1.2' MEDIA='network' SECTIONMD5='0d9a0147dcf87c7c720e341170f69ed4' +INST: 9a5561464ff8c78dd7cb544740ce2adc~[epdu-2-snmp]: DRV='snmp-ups' PORT='172.16.1.2' MEDIA='network' SECTIONMD5='2631b6c21140cea0dd30bb88b942ce3f' +INST: 16adbdafb22d9fdff1d09038520eb32e~[qx-serial]: DRV='nutdrv_qx' PORT='/dev/ttyb' MEDIA='serial' SECTIONMD5='e3e6e586fbe5b3c0a89432f4b993f4ad' +INST: a21bd2b786228b9619f6adba6db8fa83~[qx-usb1]: DRV='nutdrv_qx' PORT='auto' MEDIA='usb' SECTIONMD5='a6139c5da35bef89dc5b96e2296f5369' +INST: 0066605e07c66043a17eccecbeea1ac5~[qx-usb2]: DRV='nutdrv_qx' PORT='/dev/usb/8' MEDIA='usb' SECTIONMD5='5722dd9c21d07a1f5bcb516dbc458deb' +INST: 1280a731e03116f77290e51dd2a2f37e~[sectionWithComment]: DRV='nutdrv_qx#comment' PORT='/dev/usb/8' MEDIA='' SECTIONMD5='be30e15e17d0579c85eecaf176b4a064' +INST: 770abd5659061a29ed3ae4f7c0b00915~[sectionWithCommentWhitespace]: DRV='nutdrv_qx # comment' PORT='/dev/usb/8 # comment' MEDIA='' SECTIONMD5='c757822a331521cdc97310d0241eba28' +INST: efdb1b4698215fdca36b9bc06d24661d~[serial.4]: DRV='serial-ups' PORT='/dev/ttyS1 # some path' MEDIA='' SECTIONMD5='9c485f733aa6d6c85c1724f162929443' +INST: f4a1c33db201c2ca897a3337993c10fc~[usb_3]: DRV='usbhid-ups' PORT='auto' MEDIA='usb' SECTIONMD5='1f6a24becde9bd31c9852610658ef84a' +INST: 8e5686f92a5ba11901996c813e7bb23d~[valueHasEquals]: DRV='dummy=ups' PORT='file1.dev # key = val, right?' MEDIA='' SECTIONMD5='2f04d65da53e3b13771bb65422f0f4c0' +INST: 99da99b1e301e84f34f349443aac545b~[valueHasHashtag]: DRV='dummy-ups' PORT='file#1.dev' MEDIA='' SECTIONMD5='6029bda216de0cf1e81bd55ebd4a0fff' +INST: d50c3281f9b68a94bf9df72a115fbb5c~[valueHasQuotedHashtag]: DRV='dummy-ups' PORT='file#1.dev' MEDIA='' SECTIONMD5='af59c3c0caaa68dcd796d7145ae403ee'" \ + upslist_debug + + # FIXME : in [valueHasEquals] and [serial.4] the PORT value is quite bogus + # with its embedded comments. Check vs. binary config parser, whether in + # unquoted case only first token is the valid value, and how comments are + # handled in general? + # FIXME : in [valueHasHashtag] the line after "#" should likely be dropped + # (check in binary config parser first) while in [valueHasQuotedHashtag] + # it should stay. +} + +testcase_getValue() { + run_testcase "Query a configuration key (SDP)" 0 \ + "file1.dev" \ + --show-device-config-value dummy1 port + + run_testcase "Query a configuration key (other)" 0 \ + "yes" \ + --show-device-config-value epdu-2 synchronous + + run_testcase "Query a configuration key (originally quoted)" 0 \ + 'This is ups-1' \ + --show-device-config-value dummy1 desc + + run_testcase "Query a configuration flag (driver)" 0 \ + "driverflag" \ + --show-config-value 'serial.4' driverflag + + run_testcase "Query a missing configuration flag (driver)" 1 \ + "" \ + --show-config-value 'valueHasQuotedHashtag' nosuchflag + + run_testcase "Query multiple configuration keys (originally quoted)" 0 \ + 'This is ups-1 +file1.dev' \ + --show-device-config-value dummy1 desc port + + run_testcase "Query multiple configuration keys with some missing (originally quoted)" 1 \ + 'This is ups-1 + +file1.dev' \ + --show-device-config-value dummy1 desc unknownkey port +} + +testcase_globalSection() { + run_testcase "Display global config" 0 \ + "maxstartdelay=180 +globalflag" \ + --show-config '' + + run_testcase "Query a configuration key (global)" 0 \ + "180" \ + --show-config-value '' maxstartdelay + + run_testcase "Query a configuration flag (global)" 0 \ + "globalflag" \ + --show-config-value '' globalflag + + run_testcase "Query a missing configuration flag (global)" 1 \ + "" \ + --show-config-value '' nosuchflag +} + + +# Combine the cases above into a stack +testsuite() { + testcase_bogus_args + testcase_list_all_devices + testcase_show_all_configs + testcase_getValue + testcase_globalSection + # This one can take a while, put it last + testcase_upslist_debug +} + +# If no args... +for USE_SHELL in $SHELL_PROGS ; do + testsuite +done +# End of loop over shells + +echo "Test suite for nut-driver-enumerator has completed with $FAIL_COUNT failed cases and $GOOD_COUNT good cases" >&2 + +[ "$FAIL_COUNT" = 0 ] || { echo "As a developer, you may want to export DEBUG=trace or export DEBUG=yes and re-run the test; also make sure you meant the nut-driver-enumerator.sh implementation as NDE='$NDE'" >&2 ; exit 1; } diff --git a/tools/Makefile.am b/tools/Makefile.am index 1ba2820149..daf420bd76 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -1,9 +1,3 @@ -# TODO: remove redundancies! - -# XXX this does not work with Automake!!! -# -# In fact the very concept is entirely antithetical to Automake. -# # SUBDIRS are explicitly a listing of all the directories that make # must recurse into BEFORE processing the current directory. # @@ -13,36 +7,61 @@ # # Anyway, for the time being, we force build in ./ before nut-scanner, # to have nutscan-{usb,snmp}.h built before going into the nut-scanner -# sub-directory +# sub-directory. For good measure we also call this from nut-scanner's +# make, to handle developer workflow (editing the *.c sources this uses). SUBDIRS = . nut-scanner EXTRA_DIST = nut-usbinfo.pl nut-recorder.sh nut-ddl-dump.sh \ gitlog2changelog.py nut-snmpinfo.py driver-list-format.sh -all: nut-scanner-deps +GENERATED_SNMP_FILES = nut-scanner/nutscan-snmp.h + +GENERATED_USB_FILES = nut-scanner/nutscan-usb.h + +# Hotplug output file +GENERATED_USB_OS_FILES = ../scripts/hotplug/libhid.usermap + +# udev output file +GENERATED_USB_OS_FILES += ../scripts/udev/nut-usbups.rules.in + +# BSD devd output file +GENERATED_USB_OS_FILES += ../scripts/devd/nut-usb.conf.in + +# UPower output file +GENERATED_USB_OS_FILES += ../scripts/upower/95-upower-hid.rules + +all: nut-scanner-deps $(GENERATED_USB_OS_FILES) + +# This target is called from the making of nut-scanner to ensure its bits +nut-scanner-deps: $(GENERATED_SNMP_FILES) $(GENERATED_USB_FILES) + +# Aliases for particular files, if someone has a need: +nut-scanner-deps-snmpinfo: $(GENERATED_SNMP_FILES) +nut-scanner-deps-usb: $(GENERATED_USB_FILES) -# XXX these rules are all bogus! They cause un-named target files to -# always be rebuilt! None of that is ever the right way to use make, -# and especially not Automake. Explicit filenames and their exact -# dependencies need to be properly listed. -nut-scanner-deps: +$(GENERATED_SNMP_FILES): $(top_srcdir)/drivers/*-mib.c @if python -c 1; then \ - echo "Regenerating the SNMP helper files."; \ - $(top_srcdir)/tools/nut-snmpinfo.py; \ + echo "Regenerating the SNMP helper files in SRC dir."; \ + TOP_SRCDIR="$(top_srcdir)" ; export TOP_SRCDIR; \ + TOP_BUILDDIR="$(top_builddir)" ; export TOP_BUILDDIR; \ + cd $(builddir) && $(top_srcdir)/tools/nut-snmpinfo.py; \ else \ echo "----------------------------------------------------------------------"; \ echo "Warning: Python is not available."; \ - echo "Skipping the SNMP helper files regeneration."; \ + echo "Skipping the SNMP helper files regeneration in SRC dir."; \ echo "----------------------------------------------------------------------"; \ fi +$(GENERATED_USB_FILES): $(top_srcdir)/drivers/*-hid.c $(top_srcdir)/drivers/*usb*.c $(top_srcdir)/drivers/nutdrv_qx.c @if perl -e 1; then \ - echo "Regenerating the USB helper files."; \ - $(top_srcdir)/tools/nut-usbinfo.pl; \ + echo "Regenerating the USB helper files in SRC dir."; \ + TOP_SRCDIR="$(top_srcdir)" ; export TOP_SRCDIR; \ + TOP_BUILDDIR="$(top_builddir)" ; export TOP_BUILDDIR; \ + cd $(builddir) && $(top_srcdir)/tools/nut-usbinfo.pl; \ else \ echo "----------------------------------------------------------------------"; \ echo "Warning: Perl is not available."; \ - echo "Skipping the USB helper files regeneration."; \ + echo "Skipping the USB helper files regeneration in SRC dir."; \ echo "----------------------------------------------------------------------"; \ fi @@ -50,24 +69,31 @@ nut-scanner-deps: # call the SNMP info script upon "make dist", and if Python is present # and call both for building nut-scanner # Also ensure that data/driver.list is well formatted +# NOTE: Beware that current working directory for the script should be builddir +# so it may write the files in "dist" case (read-only sources), but the script +# is called from the distdir where its copy is present. dist-hook: @if python -c 1; then \ - echo "Regenerating the SNMP helper files."; \ + echo "Regenerating the SNMP helper files in DIST dir."; \ + TOP_SRCDIR="$(top_srcdir)" ; export TOP_SRCDIR; \ + TOP_BUILDDIR="$(top_builddir)" ; export TOP_BUILDDIR; \ $(distdir)/nut-snmpinfo.py; \ else \ echo "----------------------------------------------------------------------"; \ echo "Warning: Python is not available."; \ - echo "Skipping the SNMP helper files regeneration."; \ + echo "Skipping the SNMP helper files regeneration in DIST dir."; \ echo "----------------------------------------------------------------------"; \ fi @if perl -e 1; then \ - echo "Regenerating the USB helper files."; \ + echo "Regenerating the USB helper files in DIST dir."; \ + TOP_SRCDIR="$(top_srcdir)" ; export TOP_SRCDIR; \ + TOP_BUILDDIR="$(top_builddir)" ; export TOP_BUILDDIR; \ $(distdir)/nut-usbinfo.pl; \ else \ echo "----------------------------------------------------------------------"; \ echo "Warning: Perl is not available."; \ - echo "Skipping the USB helper files regeneration."; \ + echo "Skipping the USB helper files regeneration in DIST dir."; \ echo "----------------------------------------------------------------------"; \ fi diff --git a/tools/nut-scanner/Makefile.am b/tools/nut-scanner/Makefile.am index db85c68287..fd77252d9b 100644 --- a/tools/nut-scanner/Makefile.am +++ b/tools/nut-scanner/Makefile.am @@ -1,6 +1,16 @@ -BUILT_SOURCES = nutscan-usb.h nutscan-snmp.h +# Generally, list headers and/or sources which are re-generated +# for nut-scanner in the parent dir +NUT_SCANNER_DEPS_H = nutscan-usb.h nutscan-snmp.h +NUT_SCANNER_DEPS_C = -nutscan-usb.h nutscan-snmp.h: +# General set of nut-scanner dependencies generated in the parent dir +NUT_SCANNER_DEPS = $(NUT_SCANNER_DEPS_H) $(NUT_SCANNER_DEPS_C) + +BUILT_SOURCES = $(NUT_SCANNER_DEPS) + +# Make sure we have the freshest files (no-op if built earlier and then +# no driver sources and other dependencies were edited by a developer) +$(NUT_SCANNER_DEPS): cd ..; $(MAKE) $(AM_MAKEFLAGS) nut-scanner-deps # Only build nut-scanner, and its library, if libltdl was found (required!) @@ -10,18 +20,25 @@ if WITH_LIBLTDL endif libnutscan_la_SOURCES = scan_nut.c scan_ipmi.c \ nutscan-device.c nutscan-ip.c nutscan-display.c \ - nutscan-init.c scan_usb.c scan_snmp.c scan_xml_http.c \ + nutscan-init.c scan_usb.c scan_snmp.c scan_xml_http.c \ scan_avahi.c scan_eaton_serial.c nutscan-serial.c \ ../../drivers/serial.c \ ../../drivers/bcmxcp_ser.c \ ../../common/common.c ../../common/str.c libnutscan_la_LIBADD = $(NETLIBS) $(LIBLTDL_LIBS) -libnutscan_la_LDFLAGS = $(SERLIBS) -version-info 1:0:0 +# +# Below we set API versions of public libraries +# http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html +# Note that changes here may have to be reflected in packaging (the shared +# object .so names would differ) +# +# libnutscan version information +libnutscan_la_LDFLAGS = $(SERLIBS) -version-info 1:0:0 -export-symbols-regex ^nutscan_ libnutscan_la_CFLAGS = -I$(top_srcdir)/clients -I$(top_srcdir)/include $(LIBLTDL_CFLAGS) -I$(top_srcdir)/drivers nut_scanner_SOURCES = nut-scanner.c nut_scanner_CFLAGS = -I$(top_srcdir)/clients -I$(top_srcdir)/include -nut_scanner_LDADD = libnutscan.la +nut_scanner_LDADD = ../../common/libcommon.la libnutscan.la if WITH_SSL libnutscan_la_CFLAGS += $(LIBSSL_CFLAGS) @@ -43,13 +60,13 @@ if WITH_IPMI libnutscan_la_CFLAGS += $(LIBIPMI_CFLAGS) endif -dist_noinst_HEADERS = nutscan-usb.h nutscan-snmp.h +# C is not a header, but there is no dist_noinst_SOURCES +dist_noinst_HEADERS = $(NUT_SCANNER_DEPS_H) $(NUT_SCANNER_DEPS_C) if WITH_DEV - include_HEADERS = nut-scan.h nutscan-device.h nutscan-ip.h nutscan-init.h + include_HEADERS = nut-scan.h nutscan-device.h nutscan-ip.h nutscan-init.h nutscan-serial.h else dist_noinst_HEADERS += nut-scan.h nutscan-device.h nutscan-ip.h nutscan-init.h nutscan-serial.h endif -CLEANFILES = nutscan-usb.h nutscan-snmp.h - +CLEANFILES = $(BUILT_SOURCES) diff --git a/tools/nut-scanner/nut-scanner.c b/tools/nut-scanner/nut-scanner.c index 9fea9276c4..15069ec30d 100644 --- a/tools/nut-scanner/nut-scanner.c +++ b/tools/nut-scanner/nut-scanner.c @@ -38,8 +38,6 @@ #include "nut-scan.h" -#define DEFAULT_TIMEOUT 5 - #define ERR_BAD_OPTION (-1) const char optstring[] = "?ht:s:e:E:c:l:u:W:X:w:x:p:b:B:d:L:CUSMOAm:NPqIVaD"; @@ -84,7 +82,7 @@ const struct option longopts[] = static nutscan_device_t *dev[TYPE_END]; -static long timeout = DEFAULT_TIMEOUT*1000*1000; /* in usec */ +static long timeout = DEFAULT_NETWORK_TIMEOUT * 1000 * 1000; /* in usec */ static char * start_ip = NULL; static char * end_ip = NULL; static char * port = NULL; @@ -169,7 +167,7 @@ void show_usage() printf(" -E, --eaton_serial : Scan serial Eaton devices (XCP, SHUT and Q1).\n"); printf("\nNetwork specific options:\n"); - printf(" -t, --timeout : network operation timeout (default %d).\n",DEFAULT_TIMEOUT); + printf(" -t, --timeout : network operation timeout (default %d).\n", DEFAULT_NETWORK_TIMEOUT); printf(" -s, --start_ip : First IP address to scan.\n"); printf(" -e, --end_ip : Last IP address to scan.\n"); printf(" -m, --mask_cidr : Give a range of IP using CIDR notation.\n"); @@ -225,7 +223,7 @@ int main(int argc, char *argv[]) int allow_oldnut = 0; int allow_avahi = 0; int allow_ipmi = 0; - int allow_eaton_serial = 0; /* MUST be requested explicitely! */ + int allow_eaton_serial = 0; /* MUST be requested explicitly! */ int quiet = 0; /* The debugging level for certain upsdebugx() progress messages; 0 = print always, quiet==1 is to require at least one -D */ void (*display_func)(nutscan_device_t * device); int ret_code = EXIT_SUCCESS; @@ -246,8 +244,22 @@ int main(int argc, char *argv[]) xml_sec.usec_timeout = -1; /* Override with the "timeout" common setting later */ xml_sec.peername = NULL; + /* Parse command line options -- First loop: only get debug level */ + /* Suppress error messages, for now -- leave them to the second loop. */ + opterr = 0; + while((opt_ret = getopt_long(argc, argv, optstring, longopts, NULL)) != -1) + if (opt_ret == 'D') + nut_debug_level++; + + nutscan_init(); + display_func = nutscan_display_ups_conf; + /* Parse command line options -- Second loop: everything else */ + /* Restore error messages... */ + opterr = 1; + /* ...and index of the item to be processed by getopt(). */ + optind = 1; /* Note: the getopts print an error message about unknown arguments * or arguments which need a second token and that is missing now */ while((opt_ret = getopt_long(argc, argv, optstring, longopts, NULL))!=-1) { @@ -256,8 +268,8 @@ int main(int argc, char *argv[]) case 't': timeout = atol(optarg)*1000*1000; /*in usec*/ if( timeout == 0 ) { - fprintf(stderr,"Illegal timeout value, using default %ds\n", DEFAULT_TIMEOUT); - timeout = DEFAULT_TIMEOUT*1000*1000; + fprintf(stderr,"Illegal timeout value, using default %ds\n", DEFAULT_NETWORK_TIMEOUT); + timeout = DEFAULT_NETWORK_TIMEOUT * 1000 * 1000; } break; case 's': @@ -278,7 +290,7 @@ int main(int argc, char *argv[]) cidr = strdup(optarg); break; case 'D': - nut_debug_level++; + /* nothing to do, here */ break; case 'c': if(!nutscan_avail_snmp) { @@ -466,12 +478,6 @@ int main(int argc, char *argv[]) /* BEWARE: allow_all does not include allow_eaton_serial! */ } - /* TODO: nutscan_init() should consider (via args? shared global vars?) - * which scan types we desire at this run, and not try to load irrelevant - * libraries. - */ - nutscan_init(); - /* TODO/discuss : Should the #else...#endif code below for lack of pthreads * during build also serve as a fallback for pthread failure at runtime? */ diff --git a/tools/nut-scanner/scan_snmp.c b/tools/nut-scanner/scan_snmp.c index e4b991e68e..6471f64435 100644 --- a/tools/nut-scanner/scan_snmp.c +++ b/tools/nut-scanner/scan_snmp.c @@ -84,7 +84,7 @@ static void (*nut_init_snmp)(const char *type); static void (*nut_snmp_sess_init)(netsnmp_session * session); static void * (*nut_snmp_sess_open)(struct snmp_session *session); static int (*nut_snmp_sess_close)(void *handle); -static struct snmp_session * (*nut_snmp_sess_session)(void *handle); +static struct snmp_session * (*nut_snmp_sess_session)(void *handle); static void * (*nut_snmp_parse_oid)(const char *input, oid *objid, size_t *objidlen); static struct snmp_pdu * (*nut_snmp_pdu_create) (int command ); @@ -100,10 +100,10 @@ static int (*nut_generate_Ku)(const oid * hashtype, u_int hashtype_len, static char* (*nut_snmp_out_toggle_options)(char *options); static const char * (*nut_snmp_api_errstring) (int snmp_errnumber); static int (*nut_snmp_errno); -static oid * (*nut_usmAESPrivProtocol); -static oid * (*nut_usmHMACMD5AuthProtocol); -static oid * (*nut_usmHMACSHA1AuthProtocol); -static oid * (*nut_usmDESPrivProtocol); +static oid (*nut_usmAESPrivProtocol); +static oid (*nut_usmHMACMD5AuthProtocol); +static oid (*nut_usmHMACSHA1AuthProtocol); +static oid (*nut_usmDESPrivProtocol); /* return 0 on error */ int nutscan_load_snmp_library(const char *libname_path) @@ -268,17 +268,21 @@ static void scan_snmp_add_device(nutscan_snmp_t * sec, struct snmp_pdu *response dev->type = TYPE_SNMP; dev->driver = strdup("snmp-ups"); dev->port = strdup(session->peername); - buf = malloc( response->variables->val_len + 1 ); - if( buf ) { - memcpy(buf,response->variables->val.string, - response->variables->val_len); - buf[response->variables->val_len]=0; - nutscan_add_option_to_device(dev,"desc",buf); - free(buf); + if (response != NULL) { + buf = malloc( response->variables->val_len + 1 ); + if( buf ) { + memcpy(buf,response->variables->val.string, + response->variables->val_len); + buf[response->variables->val_len]=0; + nutscan_add_option_to_device(dev,"desc",buf); + free(buf); + } } nutscan_add_option_to_device(dev,"mibs",mib); /* SNMP v3 */ if( session->community == NULL || session->community[0] == 0) { + nutscan_add_option_to_device(dev,"snmp_version","v3"); + if( sec->secLevel ) { nutscan_add_option_to_device(dev,"secLevel", sec->secLevel); @@ -325,7 +329,7 @@ static void scan_snmp_add_device(nutscan_snmp_t * sec, struct snmp_pdu *response } -static struct snmp_pdu * scan_snmp_get_manufacturer(char* oid_str,void* handle) +static struct snmp_pdu * scan_snmp_get_oid(char* oid_str,void* handle) { size_t name_len; oid name[MAX_OID_LEN]; @@ -360,7 +364,7 @@ static struct snmp_pdu * scan_snmp_get_manufacturer(char* oid_str,void* handle) response->variables->name == NULL || (*nut_snmp_oid_compare)(response->variables->name, response->variables->name_length, - name, name_len) != 0 || + name, name_len) != 0 || response->variables->val.string == NULL ) { (*nut_snmp_free_pdu)(response); index++; @@ -370,21 +374,35 @@ static struct snmp_pdu * scan_snmp_get_manufacturer(char* oid_str,void* handle) return response; } -static void try_all_oid(void * arg) +static void try_all_oid(void * arg, const char * mib_found) { struct snmp_pdu *response = NULL; int index = 0; nutscan_snmp_t * sec = (nutscan_snmp_t *)arg; - while(snmp_device_table[index].oid != NULL) { + upsdebugx(2, "%s", __func__); + + while(snmp_device_table[index].mib != NULL) { + + if (snmp_device_table[index].oid == NULL || strcmp(snmp_device_table[index].oid, "") == 0) { + index++; + continue; + } - response = scan_snmp_get_manufacturer(snmp_device_table[index].oid,sec->handle); + response = scan_snmp_get_oid(snmp_device_table[index].oid,sec->handle); if( response == NULL ) { index++; continue; } - scan_snmp_add_device(sec,response,snmp_device_table[index].mib); + /* add device only if not yet detected with the same mib */ + if (mib_found == NULL || (strcmp(mib_found, snmp_device_table[index].mib) != 0)) { + scan_snmp_add_device(sec,response,snmp_device_table[index].mib); + upsdebugx(3, "Found another match for device with MIB '%s'", snmp_device_table[index].mib); + } + else { + upsdebugx(3, "Skip duplicated device %s", snmp_device_table[index].mib); + } (*nut_snmp_free_pdu)(response); response = NULL; @@ -410,7 +428,7 @@ static int init_session(struct snmp_session * snmp_sess, nutscan_snmp_t * sec) snmp_sess->community_len = strlen("public"); } } - else { /* SNMP v3 */ + else { /* SNMP v3 */ snmp_sess->version = SNMP_VERSION_3; /* Security level */ @@ -467,17 +485,16 @@ static int init_session(struct snmp_session * snmp_sess, nutscan_snmp_t * sec) snmp_sess->securityAuthKeyLen = USM_AUTH_KU_LEN; /* default to MD5 */ - snmp_sess->securityAuthProto = (*nut_usmHMACMD5AuthProtocol); + snmp_sess->securityAuthProto = nut_usmHMACMD5AuthProtocol; snmp_sess->securityAuthProtoLen = - sizeof((*nut_usmHMACMD5AuthProtocol))/ + sizeof(usmHMACMD5AuthProtocol)/ sizeof(oid); if( sec->authProtocol ) { if (strcmp(sec->authProtocol, "SHA") == 0) { - snmp_sess->securityAuthProto = - (*nut_usmHMACSHA1AuthProtocol); + snmp_sess->securityAuthProto = nut_usmHMACSHA1AuthProtocol; snmp_sess->securityAuthProtoLen = - sizeof((*nut_usmHMACSHA1AuthProtocol))/ + sizeof(usmHMACSHA1AuthProtocol)/ sizeof(oid); } else { @@ -510,16 +527,15 @@ static int init_session(struct snmp_session * snmp_sess, nutscan_snmp_t * sec) } /* default to DES */ - snmp_sess->securityPrivProto=(*nut_usmDESPrivProtocol); + snmp_sess->securityPrivProto = nut_usmDESPrivProtocol; snmp_sess->securityPrivProtoLen = - sizeof((*nut_usmDESPrivProtocol))/sizeof(oid); + sizeof(usmDESPrivProtocol)/sizeof(oid); if( sec->privProtocol ) { if (strcmp(sec->privProtocol, "AES") == 0) { - snmp_sess->securityPrivProto= - (*nut_usmAESPrivProtocol); - snmp_sess->securityPrivProtoLen = - sizeof((*nut_usmAESPrivProtocol))/ + snmp_sess->securityPrivProto = nut_usmAESPrivProtocol; + snmp_sess->securityPrivProtoLen = + sizeof(usmAESPrivProtocol)/ sizeof(oid); } else { @@ -561,13 +577,15 @@ static void * try_SysOID(void * arg) size_t name_len = MAX_OID_LEN; nutscan_snmp_t * sec = (nutscan_snmp_t *)arg; int index = 0; - int sysoid_found = 0; + char *mib_found = NULL; + + upsdebugx(2, "%s", __func__); /* Initialize session */ if( !init_session(&snmp_sess,sec) ) { goto try_SysOID_free; } - + snmp_sess.retries = 0; snmp_sess.timeout = g_usec_timeout; @@ -609,7 +627,7 @@ static void * try_SysOID(void * arg) /* Check if the received OID match with a known sysOID */ if(response->variables != NULL && response->variables->val.objid != NULL){ - while(snmp_device_table[index].oid != NULL) { + while(snmp_device_table[index].mib != NULL) { if(snmp_device_table[index].sysoid == NULL ) { index++; continue; @@ -626,15 +644,26 @@ static void * try_SysOID(void * arg) response->variables->val.objid, response->variables->val_len/sizeof(oid), name, name_len) == 0 ) { - /* we have found a relevent sysoid */ - resp = scan_snmp_get_manufacturer( - snmp_device_table[index].oid, - handle); - if( resp != NULL ) { - scan_snmp_add_device(sec,resp, - snmp_device_table[index].mib); - sysoid_found = 1; - (*nut_snmp_free_pdu)(resp); + + /* we have found a relevant sysoid */ + + /* add mib if no complementary oid is present */ + /* FIXME: No desc defined when add device */ + if (snmp_device_table[index].oid == NULL + || strcmp(snmp_device_table[index].oid, "") == 0) { + scan_snmp_add_device(sec,NULL,snmp_device_table[index].mib); + mib_found = snmp_device_table[index].sysoid; + } + /* else test complementary oid before adding mib */ + else { + resp = scan_snmp_get_oid( + snmp_device_table[index].oid, + handle); + if( resp != NULL ) { + scan_snmp_add_device(sec,resp, snmp_device_table[index].mib); + mib_found = snmp_device_table[index].mib; + (*nut_snmp_free_pdu)(resp); + } } } index++; @@ -642,9 +671,7 @@ static void * try_SysOID(void * arg) } /* try a list of known OID */ - if( !sysoid_found ) { - try_all_oid(sec); - } + try_all_oid(sec, mib_found); (*nut_snmp_free_pdu)(response); response = NULL; diff --git a/tools/nut-scanner/scan_usb.c b/tools/nut-scanner/scan_usb.c index 1027e93b06..67e61f7d33 100644 --- a/tools/nut-scanner/scan_usb.c +++ b/tools/nut-scanner/scan_usb.c @@ -236,18 +236,21 @@ nutscan_device_t * nutscan_scan_usb() "product", device_name); free(device_name); + device_name = NULL; } if(serialnumber) { nutscan_add_option_to_device(nut_dev, "serial", serialnumber); free(serialnumber); + serialnumber = NULL; } if(vendor_name) { nutscan_add_option_to_device(nut_dev, "vendor", vendor_name); free(vendor_name); + vendor_name = NULL; } nutscan_add_option_to_device(nut_dev,"bus", bus->dirname); diff --git a/tools/nut-snmpinfo.py b/tools/nut-snmpinfo.py index 32d17784e6..eda4fefbcf 100755 --- a/tools/nut-snmpinfo.py +++ b/tools/nut-snmpinfo.py @@ -1,6 +1,7 @@ #!/usr/bin/env python -# Copyright (C) 2011 - Frederic Bohe -# Copyright (C) 2016 - Arnaud Quette +# Copyright (C) 2011-2019 Eaton +# Authors: Frederic Bohe +# Arnaud Quette # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -21,8 +22,17 @@ import glob import re import sys +import os -output_file_name="./nut-scanner/nutscan-snmp.h" +TOP_SRCDIR = os.getenv('TOP_SRCDIR') +if TOP_SRCDIR is None: + TOP_SRCDIR=".." + +TOP_BUILDDIR = os.getenv('TOP_BUILDDIR') +if TOP_BUILDDIR is None: + TOP_BUILDDIR=".." + +output_file_name = TOP_BUILDDIR + "/tools/nut-scanner/nutscan-snmp.h" output_file = open(output_file_name,'w') #expand #define constant @@ -33,7 +43,7 @@ def expand_define(filename,constant): if constant in line and "#define" in line: line_without_carriage_return = re.sub("[\n\r]", "", line) line_with_single_blank = re.sub("[ \t]+", " ", line_without_carriage_return) - define_line = line_with_single_blank.split(" "); + define_line = line_with_single_blank.split(" ") #define_line[0] = "#define" #define_line[1] = const name #define_line[2...] = const value (may be other const name) @@ -45,13 +55,14 @@ def expand_define(filename,constant): clean_elem = re.sub("\"", "", elem) ret_line = ret_line + clean_elem else: - ret_line = ret_line + expand_define(filename,elem); + ret_line = ret_line + expand_define(filename,elem) return ret_line -output_file.write( "/* nutscan-snmp\n" ) -output_file.write( " * Copyright (C) 2011 - Frederic Bohe \n" ) -output_file.write( " * Copyright (C) 2016 - Arnaud Quette \n" ) +output_file.write( "/* nutscan-snmp.c - fully generated during build of NUT\n" ) +output_file.write( " * Copyright (C) 2011-2019 EATON\n" ) +output_file.write( " * Authors: Frederic Bohe \n" ) +output_file.write( " * Arnaud Quette \n" ) output_file.write( " *\n" ) output_file.write( " * This program is free software; you can redistribute it and/or modify\n" ) output_file.write( " * it under the terms of the GNU General Public License as published by\n" ) @@ -80,7 +91,7 @@ def expand_define(filename,constant): output_file.write( "/* SNMP IDs device table */\n" ) output_file.write( "static snmp_device_id_t snmp_device_table[] = {\n" ) -for filename in glob.glob('../drivers/*-mib.c'): +for filename in sorted(glob.glob(TOP_SRCDIR + '/drivers/*-mib.c')): list_of_line = open(filename,'r').read().split(';') for line in list_of_line: if "mib2nut_info_t" in line: @@ -97,7 +108,7 @@ def expand_define(filename,constant): line = line2.split("{",1) #line[1] is the part between {} line2 = line[1].split(",") - mib = line2[0] + mib = line2[0].lstrip(" ") #line2[3] is the OID of the device model name which #could be made of #define const and string. source_oid = line2[3] @@ -118,7 +129,7 @@ def expand_define(filename,constant): clean_elem = re.sub("\"", "", elem) oid = oid+clean_elem else: - oid = oid + expand_define(filename,elem); + oid = oid + expand_define(filename,elem) #decode source_sysoid line = source_sysoid.lstrip(" ") @@ -131,16 +142,22 @@ def expand_define(filename,constant): clean_elem = re.sub("\"", "", elem) sysoid = sysoid+clean_elem else: - sysoid = sysoid + expand_define(filename,elem); + sysoid = sysoid + expand_define(filename,elem) + # Sanity checks if sysoid == "": sysoid = "NULL" else: sysoid = "\"" + sysoid + "\"" - output_file.write( "\t{ \"" + oid + "\", " + mib + ", " + sysoid + "},\n" ) + if oid == "": + oid = "NULL" + else: + oid = "\"" + oid + "\"" + + output_file.write( "\t{ " + oid + ", " + mib + ", " + sysoid + " },\n" ) -output_file.write( " /* Terminating entry */\n" ) -output_file.write( " { NULL, NULL, NULL}\n" ) +output_file.write( "\t/* Terminating entry */\n" ) +output_file.write( "\t{ NULL, NULL, NULL }\n" ) output_file.write( "};\n" ) output_file.write( "#endif /* DEVSCAN_SNMP_H */\n" ) diff --git a/tools/nut-usbinfo.pl b/tools/nut-usbinfo.pl index 2c0dd055ba..186ea442c0 100755 --- a/tools/nut-usbinfo.pl +++ b/tools/nut-usbinfo.pl @@ -28,20 +28,31 @@ use File::Find; use strict; + +my $TOP_SRCDIR = ".."; +if (defined $ENV{'TOP_SRCDIR'}) { + $TOP_SRCDIR = $ENV{'TOP_SRCDIR'}; +} + +my $TOP_BUILDDIR = ".."; +if (defined $ENV{'TOP_BUILDDIR'}) { + $TOP_BUILDDIR = $ENV{'TOP_BUILDDIR'}; +} + # path to scan for USB_DEVICE pattern -my $scanPath="../drivers"; +my $scanPath="$TOP_SRCDIR/drivers"; # Hotplug output file -my $outputHotplug="../scripts/hotplug/libhid.usermap"; +my $outputHotplug="$TOP_BUILDDIR/scripts/hotplug/libhid.usermap"; # udev output file -my $outputUdev="../scripts/udev/nut-usbups.rules.in"; +my $outputUdev="$TOP_BUILDDIR/scripts/udev/nut-usbups.rules.in"; # BSD devd output file -my $output_devd="../scripts/devd/nut-usb.conf.in"; +my $output_devd="$TOP_BUILDDIR/scripts/devd/nut-usb.conf.in"; # UPower output file -my $outputUPower="../scripts/upower/95-upower-hid.rules"; +my $outputUPower="$TOP_BUILDDIR/scripts/upower/95-upower-hid.rules"; # tmp output, to allow generating the ENV{UPOWER_VENDOR} header list my $tmpOutputUPower; @@ -49,7 +60,7 @@ my $upowerMfrHeaderDone = 0; # NUT device scanner - C header -my $outputDevScanner = "./nut-scanner/nutscan-usb.h"; +my $outputDevScanner = "$TOP_BUILDDIR/tools/nut-scanner/nutscan-usb.h"; my $GPL_header = "\ * Copyright (C) 2011 - Arnaud Quette \ @@ -76,7 +87,7 @@ ################# MAIN ################# -find(\&find_usbdevs,$scanPath); +find({wanted=>\&find_usbdevs, preprocess=>sub{sort @_}}, $scanPath); &gen_usb_files; ################# SUB METHOD ################# @@ -280,27 +291,9 @@ sub find_usbdevs if($nameFile=~/(.+)-hid\.c/) { $driver="usbhid-ups"; } - # FIXME: make a generic matching rule *.c => * - elsif ($nameFile eq "bcmxcp_usb.c") { - $driver="bcmxcp_usb"; - } - elsif ($nameFile eq "tripplite_usb.c") { - $driver="tripplite_usb"; - } - elsif ($nameFile eq "blazer_usb.c") { - $driver="blazer_usb"; - } - elsif ($nameFile eq "richcomm_usb.c") { - $driver="richcomm_usb"; - } - elsif ($nameFile eq "nutdrv_atcl_usb.c") { - $driver="nutdrv_atcl_usb"; - } - elsif ($nameFile eq "riello_usb.c") { - $driver="riello_usb"; - } - elsif ($nameFile eq "nutdrv_qx.c") { - $driver="nutdrv_qx"; + # generic matching rule *.c => * + elsif ($nameFile =~ /(.+)\.c$/) { + $driver=$1; } else { die "Unknown driver type: $nameFile";