Subversion Repositories f9daq

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. // WIENER SNMP basic SNMP library to Demonstrate C-Access to WIENER-Crates via SNMP
  2. // modified for LabView import 04/23/06, Andreas Ruben
  3. //
  4. // The path to the Net-SNMP include files (default /usr/include) must be added to the
  5. // include file search path!
  6. // The following libraries must be included:
  7. // netsnmp.lib ws2_32.lib
  8. // The path to the Net-SNMP library must be added to the linker files.
  9. // /usr/lib
  10. // path for the WIENER MIB file (mibdirs) c:/usr/share/snmp/mibs
  11.  
  12. #include <windows.h>
  13. #include "toolbox.h"
  14. #include <ansi_c.h>
  15. #include "WIENER_SNMP.h"
  16.  
  17. #define VER_FILEVERSION             1,1,1,0
  18. #define VER_FILEVERSION_STR         "1.1.1.0\0"
  19.  
  20. #ifdef _MSC_VER
  21. #define strdup _strdup
  22. #define vsnprintf vsprintf_s
  23. #define strPrintf sprintf_s
  24. #else
  25. #define strdup StrDup
  26. #define strPrintf snprintf
  27. #endif
  28.  
  29. #ifndef UNREFERENCED_PARAMETER
  30. #define UNREFERENCED_PARAMETER(P) (void)(P)
  31. #endif
  32.  
  33. #define false 0;
  34. #define true  1;
  35.  
  36.  
  37. static const char WienerMibFileName[] = "WIENER-CRATE-MIB";
  38. static const char DefaultReadCommunity[] = "public";  ///< default community name for read operations
  39. static const char DefaultWriteCommunity[] = "guru";   ///< default community name for write operation
  40.  
  41. static char *m_readCommunity = (char *)DefaultReadCommunity;
  42. static char *m_writeCommunity = (char *)DefaultWriteCommunity;
  43.  
  44. /**
  45.  * @brief The SnmpObject class is used internally to resolve OIDs and for the SNMP calls.
  46.  */
  47. //class SnmpObject {
  48. //public:
  49. typedef struct {
  50.         oid    id[MAX_OID_LEN]; ///< The resolved SNMP OID
  51.         size_t len;             ///< The resolved OIDs length in byte
  52.         char   desc[100];       ///< The OIDs textual representation, e.g. "sysDescr.0"
  53. } SnmpObject;
  54. //typedef struct snmp_object SnmpObject;
  55.  
  56. static SnmpObject moduleIndex[MaxSlotsPerCrate];
  57. static SnmpObject moduleDescription[MaxSlotsPerCrate];
  58. static SnmpObject moduleSupply[MaxModuleAuxSupplies][MaxSlotsPerCrate];
  59. static SnmpObject moduleHardwareLimitVoltage[MaxSlotsPerCrate];
  60. static SnmpObject moduleHardwareLimitCurrent[MaxSlotsPerCrate];
  61. static SnmpObject moduleRampSpeedVoltage[MaxSlotsPerCrate];
  62. static SnmpObject moduleRampSpeedCurrent[MaxSlotsPerCrate];
  63. static SnmpObject moduleStatus[MaxSlotsPerCrate];
  64. static SnmpObject moduleEventStatus[MaxSlotsPerCrate];
  65. static SnmpObject moduleDoClear[MaxSlotsPerCrate];
  66. static SnmpObject moduleAuxiliaryMeasurementTemperature[MaxModuleAuxTemperatures][MaxSlotsPerCrate];
  67.  
  68. static SnmpObject sysDescr;
  69. static SnmpObject sysMainSwitch;
  70. static SnmpObject sysStatus;
  71. static SnmpObject sysVmeSysReset;
  72. static SnmpObject outputNumber;
  73. static SnmpObject groupsNumber;
  74. static SnmpObject highVoltageGroupsSwitch;
  75. static SnmpObject lowVoltageGroupsSwitch;
  76. static SnmpObject ipStaticAddress;
  77.  
  78. static SnmpObject outputName[MaxChannelsPerCrate];
  79. static SnmpObject outputIndex[MaxChannelsPerCrate];
  80. static SnmpObject outputGroup[MaxChannelsPerCrate];
  81. static SnmpObject outputStatus[MaxChannelsPerCrate];
  82. static SnmpObject outputMeasurementSenseVoltage[MaxChannelsPerCrate];
  83. static SnmpObject outputMeasurementTerminalVoltage[MaxChannelsPerCrate];
  84. static SnmpObject outputMeasurementCurrent[MaxChannelsPerCrate];
  85. static SnmpObject outputMeasurementTemperature[MaxChannelsPerCrate];
  86. static SnmpObject outputSwitch[MaxChannelsPerCrate];
  87. static SnmpObject outputVoltage[MaxChannelsPerCrate];
  88. static SnmpObject outputCurrent[MaxChannelsPerCrate];
  89. static SnmpObject outputVoltageRiseRate[MaxChannelsPerCrate];
  90. static SnmpObject outputVoltageFallRate[MaxChannelsPerCrate];
  91. static SnmpObject outputCurrentRiseRate[MaxChannelsPerCrate];
  92. static SnmpObject outputCurrentFallRate[MaxChannelsPerCrate];
  93. static SnmpObject outputSupervisionBehavior[MaxChannelsPerCrate];
  94. static SnmpObject outputSupervisionMinSenseVoltage[MaxChannelsPerCrate];
  95. static SnmpObject outputSupervisionMaxSenseVoltage[MaxChannelsPerCrate];
  96. static SnmpObject outputSupervisionMaxTerminalVoltage[MaxChannelsPerCrate];
  97. static SnmpObject outputSupervisionMaxCurrent[MaxChannelsPerCrate];
  98. static SnmpObject outputSupervisionMaxTemperature[MaxChannelsPerCrate];
  99. static SnmpObject outputConfigMaxSenseVoltage[MaxChannelsPerCrate];
  100. static SnmpObject outputConfigMaxTerminalVoltage[MaxChannelsPerCrate];
  101. static SnmpObject outputConfigMaxCurrent[MaxChannelsPerCrate];
  102. static SnmpObject outputSupervisionMaxPower[MaxChannelsPerCrate];
  103. static SnmpObject outputTripTimeMaxCurrent[MaxChannelsPerCrate];
  104.  
  105. static SnmpObject sensorNumber;
  106. static SnmpObject sensorTemperature[MaxSensors];
  107. static SnmpObject sensorWarningThreshold[MaxSensors];
  108. static SnmpObject sensorFailureThreshold[MaxSensors];
  109.  
  110. //static SnmpObject psFirmwareVersion;
  111. static SnmpObject psSerialNumber;
  112. static SnmpObject psOperatingTime;
  113. static SnmpObject psDirectAccess;
  114. static SnmpObject fanNumberOfFans;
  115. static SnmpObject fanOperatingTime;
  116. //static SnmpObject fanFirmwareVersion;
  117. static SnmpObject fanSerialNumber;
  118. static SnmpObject fanAirTemperature;
  119. static SnmpObject fanSwitchOffDelay;
  120. static SnmpObject fanNominalSpeed;
  121. static SnmpObject fanSpeed[MaxFans];
  122.  
  123. static SnmpObject psAuxVoltage[MaxPsAuxSupplies];
  124. static SnmpObject psAuxCurrent[MaxPsAuxSupplies];
  125.  
  126. static SnmpObject snmpCommunityName[MaxCommunities];
  127.  
  128. //static double snmpSetDouble(HSNMP session, const SnmpObject &object, double value);
  129. static double snmpSetDouble(HSNMP session, const SnmpObject *object, double value);
  130. static double snmpGetDouble(HSNMP session, const SnmpObject *object);
  131. static int    snmpSetInt(HSNMP session, const SnmpObject *object, int value);
  132. static int    snmpGetInt(HSNMP session, const SnmpObject *object);
  133. static char  *snmpGetString(HSNMP session, const SnmpObject *object);
  134.  
  135. char snmpStringBuffer[1024];
  136. char snmpLastErrorBuffer[1024];
  137.  
  138. SnmpDoubleBuffer snmpDoubleBuffer;
  139. SnmpIntegerBuffer snmpIntegerBuffer;
  140.  
  141. #ifdef _MSC_VER
  142.  
  143. BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
  144. {
  145.         UNREFERENCED_PARAMETER(hModule);
  146.         UNREFERENCED_PARAMETER(ul_reason_for_call);
  147.         UNREFERENCED_PARAMETER(lpReserved);
  148.  
  149.         return TRUE;
  150. }
  151.  
  152. #endif
  153.  
  154. /**
  155.  * @brief Simple logging function with printf-like usage.
  156.  * @internal
  157.  * @param priority
  158.  * @param format
  159.  */
  160. static void sysLog(int priority, const char *format, ...)
  161. {
  162.         UNREFERENCED_PARAMETER(priority);
  163.  
  164.         va_list vaPrintf;
  165.         va_start(vaPrintf, format);
  166.         vprintf(format, vaPrintf);
  167.         putchar('\n');
  168.  
  169.         // store errors in snmpLastErrorBuffer, which can be read by snmpGetLastError()
  170.         if (priority == LOG_ERR)
  171.                 vsnprintf(snmpLastErrorBuffer, sizeof(snmpLastErrorBuffer), format, vaPrintf);
  172.  
  173.         va_end(vaPrintf);
  174. }
  175.  
  176. // Helper functions
  177.  
  178. /**
  179.  * @brief Resolves the OID from the textual SNMP description
  180.  * and stores the OID in *object.
  181.  * @internal
  182.  * @param node e.g. "sysMainSwitch"
  183.  * @param object the resolved OID
  184.  * @return true on success, false otherwise
  185.  */
  186. static int getNode(const char * const node, SnmpObject *object)
  187. {
  188.         object->len = MAX_OID_LEN;
  189.         if (!get_node(node, object->id, &object->len)) {
  190.                 snmp_log(LOG_ERR, "OID %s not found!\n", node);
  191.                 return false;
  192.         }
  193.  
  194. #ifdef _MSC_VER
  195.         strcpy_s(object->desc, sizeof(object->desc), node);
  196. #else
  197.         strncpy(object->desc, node, sizeof(object->desc));
  198. #endif
  199.  
  200.         return true;
  201. }
  202.  
  203. /**
  204.  * @brief Resolves the OID from the textual SNMP description
  205.  * with appended index and stores the OID in *object.
  206.  * @internal
  207.  * @param nodeBase e.g. "outputSwitch"
  208.  * @param index e.g. 100
  209.  * @param object the resolved OID
  210.  * @return true on success, false otherwise
  211.  */
  212. static int getIndexNode(const char * const nodeBase, int index, SnmpObject *object)
  213. {
  214.         char node[100];
  215.  
  216.         strPrintf(node, sizeof(node), "%s.%i", nodeBase, index);
  217.  
  218.         return getNode(node, object);
  219. }
  220.  
  221. /**
  222.  * @brief Activates logging on stderr console.
  223.  * @since 1.1
  224.  * @note This is the default setting.
  225.  */
  226. void snmpSetStdErrLog(void)
  227. {
  228.         snmp_enable_stderrlog();
  229. }
  230.  
  231. /**
  232.  * @brief Activates logging to the file filename.
  233.  * @since 1.1
  234.  * @param fileName The full path to the file where all log
  235.  * information should go to.
  236.  * @note If the specified file already exists,
  237.  * new log information is appended.
  238.  */
  239. void snmpSetFileLog(const char * const fileName)
  240. {
  241.         snmp_enable_filelog(fileName, 1);
  242. }
  243.  
  244. /**
  245.  * @brief Returns the library four digit version number as unsigned int value.
  246.  *
  247.  * This allows to check for a specific version number.
  248.  * @since 1.1
  249.  * @return The version number as unsigned long value, e.g. 0x01010000
  250.  */
  251. unsigned int snmpGetVersion(void)
  252. {
  253.         const uint32_t version[] = { VER_FILEVERSION };
  254.  
  255.         return (version[0] << 24) + (version[1] << 16) + (version[2] << 8) + version[3];
  256. }
  257.  
  258. /**
  259.  * @brief Returns the library four digit version number as null-terminated string.
  260.  *
  261.  * The digits are separated by dots.
  262.  * @since 1.1
  263.  * @return The version number, e.g. "1.1.0.3"
  264.  */
  265. char *snmpGetVersionString(void)
  266. {
  267.         return VER_FILEVERSION_STR;
  268. }
  269.  
  270. /**
  271.  * @brief Setup the default conditions for logging and SNMP passwords.
  272.  * @internal
  273.  */
  274. static void setDefaultSettings(void)
  275. {
  276.         snmpSetStdErrLog();
  277.  
  278.         m_readCommunity = (char *)DefaultReadCommunity;
  279.         m_writeCommunity = (char *)DefaultWriteCommunity;
  280.  
  281.         memset(snmpLastErrorBuffer, 0, sizeof(snmpLastErrorBuffer));
  282. }
  283.  
  284. /**
  285.  * @brief SNMP Initialization.
  286.  *
  287.  * Resolves all needed OIDs from the MIB file and prepares the SNMP communication.
  288.  * The actual connection to a MPOD crate is done with snmpOpen().
  289.  * @return true on success, false otherwise (e.g. an OID could not be resolved)
  290.  */
  291. int snmpInit(void)
  292. {
  293.         setDefaultSettings();
  294.  
  295.         snmp_log(LOG_DEBUG, "*** Initialise SNMP ***\n");
  296.  
  297.         init_snmp("WIENER_SNMP_DLL");
  298.         init_mib();                                                             // init MIB processing
  299.         if (!read_module(WienerMibFileName)) {          // read specific mibs
  300.                 snmp_log(LOG_ERR, "Unable to load SNMP MIB file \"%s\"\n", WienerMibFileName);
  301.                 return false;
  302.         }
  303.         snmp_log(LOG_DEBUG, "*** Translate OIDs ***\n");
  304.  
  305.         // Translate System OIDS
  306.         getNode("sysDescr.0", &sysDescr); // FIXME: doesn't work atm in Linux
  307.  
  308.         if (
  309.                 (!getNode("sysMainSwitch.0",      &sysMainSwitch)) ||
  310.                 (!getNode("sysStatus.0",          &sysStatus)) ||
  311.                 (!getNode("sysVmeSysReset.0",     &sysVmeSysReset)) ||
  312.                 (!getNode("outputNumber.0",       &outputNumber)) ||
  313.                 (!getNode("groupsNumber.0",       &groupsNumber)) ||
  314.                 (!getNode("groupsSwitch.64",      &highVoltageGroupsSwitch)) ||
  315.                 (!getNode("groupsSwitch.128",     &lowVoltageGroupsSwitch)) ||
  316.                 (!getNode("ipStaticAddress.0",    &ipStaticAddress)) ||
  317. //              (!getNode("psFirmwareVersion.0",  &psFirmwareVersion)) ||
  318.                 (!getNode("psSerialNumber.0",     &psSerialNumber)) ||
  319.                 (!getNode("psOperatingTime.0",    &psOperatingTime)) ||
  320.                 (!getNode("psDirectAccess.0",     &psDirectAccess)) ||
  321.                 (!getNode("sensorNumber.0",       &sensorNumber)) ||
  322. //              (!getNode("fanFirmwareVersion.0", &fanFirmwareVersion)) ||
  323.                 (!getNode("fanSerialNumber.0",    &fanSerialNumber)) ||
  324.                 (!getNode("fanOperatingTime.0",   &fanOperatingTime)) ||
  325.                 (!getNode("fanAirTemperature.0",  &fanAirTemperature))||
  326.                 (!getNode("fanSwitchOffDelay.0",  &fanSwitchOffDelay)) ||
  327.                 (!getNode("fanNominalSpeed.0",    &fanNominalSpeed)) ||
  328.                 (!getNode("fanNumberOfFans.0",    &fanNumberOfFans))
  329.         ) {
  330.                 return false;
  331.         }
  332.  
  333.         // Translate module and channel information OIDs
  334.         for (int slot = 0; slot < MaxSlotsPerCrate; ++slot) {
  335.  
  336.                 if (
  337.                         (!getIndexNode("moduleIndex", slot + 1, &moduleIndex[slot])) ||
  338.                         (!getIndexNode("moduleDescription", slot + 1, &moduleDescription[slot])) ||
  339.                         (!getIndexNode("moduleAuxiliaryMeasurementVoltage0", slot + 1, &moduleSupply[0][slot])) ||
  340.                         (!getIndexNode("moduleAuxiliaryMeasurementVoltage1", slot + 1, &moduleSupply[1][slot])) ||
  341.                         (!getIndexNode("moduleAuxiliaryMeasurementTemperature0", slot + 1, &moduleAuxiliaryMeasurementTemperature[0][slot])) ||
  342.                         (!getIndexNode("moduleAuxiliaryMeasurementTemperature1", slot + 1, &moduleAuxiliaryMeasurementTemperature[1][slot])) ||
  343.                         (!getIndexNode("moduleAuxiliaryMeasurementTemperature2", slot + 1, &moduleAuxiliaryMeasurementTemperature[2][slot])) ||
  344.                         (!getIndexNode("moduleAuxiliaryMeasurementTemperature3", slot + 1, &moduleAuxiliaryMeasurementTemperature[3][slot])) ||
  345.                         (!getIndexNode("moduleHardwareLimitVoltage", slot + 1, &moduleHardwareLimitVoltage[slot])) ||
  346.                         (!getIndexNode("moduleHardwareLimitCurrent", slot + 1, &moduleHardwareLimitCurrent[slot])) ||
  347.                         (!getIndexNode("moduleRampSpeedVoltage", slot + 1, &moduleRampSpeedVoltage[slot])) ||
  348.                         (!getIndexNode("moduleRampSpeedCurrent", slot + 1, &moduleRampSpeedCurrent[slot])) ||
  349.                         (!getIndexNode("moduleStatus", slot + 1, &moduleStatus[slot])) ||
  350.                         (!getIndexNode("moduleEventStatus", slot + 1, &moduleEventStatus[slot])) ||
  351.                         (!getIndexNode("moduleDoClear", slot + 1, &moduleDoClear[slot]))
  352.                 ) {
  353.                         return false;
  354.                 }
  355.  
  356.                 int base = MaxChannelsPerSlot * slot; // array index
  357.  
  358.                 for (int channel = base; channel < base + MaxChannelsPerSlot; ++channel) {
  359.                         if (
  360.                                 (!getIndexNode("outputName", channel + 1, &outputName[channel])) ||
  361.                                 (!getIndexNode("outputIndex", channel + 1, &outputIndex[channel])) ||
  362.                                 (!getIndexNode("outputGroup", channel + 1, &outputGroup[channel])) ||
  363.                                 (!getIndexNode("outputStatus", channel + 1, &outputStatus[channel])) ||
  364.                                 (!getIndexNode("outputMeasurementSenseVoltage", channel + 1, &outputMeasurementSenseVoltage[channel])) ||
  365.                                 (!getIndexNode("outputMeasurementTerminalVoltage", channel + 1, &outputMeasurementTerminalVoltage[channel])) ||
  366.                                 (!getIndexNode("outputMeasurementCurrent", channel + 1, &outputMeasurementCurrent[channel])) ||
  367.                                 (!getIndexNode("outputMeasurementTemperature", channel + 1, &outputMeasurementTemperature[channel])) ||
  368.                                 (!getIndexNode("outputSwitch", channel + 1, &outputSwitch[channel])) ||
  369.                                 (!getIndexNode("outputVoltage", channel + 1, &outputVoltage[channel])) ||
  370.                                 (!getIndexNode("outputCurrent", channel + 1, &outputCurrent[channel])) ||
  371.                                 (!getIndexNode("outputVoltageRiseRate", channel + 1, &outputVoltageRiseRate[channel])) ||
  372.                                 (!getIndexNode("outputVoltageFallRate", channel + 1, &outputVoltageFallRate[channel])) ||
  373.                                 (!getIndexNode("outputCurrentRiseRate", channel + 1, &outputCurrentRiseRate[channel])) ||
  374.                                 (!getIndexNode("outputCurrentFallRate", channel + 1, &outputCurrentFallRate[channel])) ||
  375.                                 (!getIndexNode("outputSupervisionBehavior", channel + 1, &outputSupervisionBehavior[channel])) ||
  376.                                 (!getIndexNode("outputSupervisionMinSenseVoltage", channel + 1, &outputSupervisionMinSenseVoltage[channel])) ||
  377.                                 (!getIndexNode("outputSupervisionMaxSenseVoltage", channel + 1, &outputSupervisionMaxSenseVoltage[channel])) ||
  378.                                 (!getIndexNode("outputSupervisionMaxTerminalVoltage", channel + 1, &outputSupervisionMaxTerminalVoltage[channel])) ||
  379.                                 (!getIndexNode("outputSupervisionMaxCurrent", channel + 1, &outputSupervisionMaxCurrent[channel])) ||
  380. //                              (!getIndexNode("outputSupervisionMaxTemperature", channel + 1, &outputSupervisionMaxTemperature[channel])) ||
  381.                                 (!getIndexNode("outputConfigMaxSenseVoltage", channel + 1, &outputConfigMaxSenseVoltage[channel])) ||
  382.                                 (!getIndexNode("outputConfigMaxTerminalVoltage", channel + 1, &outputConfigMaxTerminalVoltage[channel])) ||
  383.                                 (!getIndexNode("outputSupervisionMaxPower", channel + 1, &outputSupervisionMaxPower[channel])) ||
  384.                                 (!getIndexNode("outputConfigMaxCurrent", channel + 1, &outputConfigMaxCurrent[channel])) ||
  385.                                 (!getIndexNode("outputTripTimeMaxCurrent", channel + 1, &outputTripTimeMaxCurrent[channel]))
  386.                         ) {
  387.                                 return false;
  388.                         }
  389.                 }
  390.         }
  391.  
  392.         for (int sensor = 0; sensor < MaxSensors; ++sensor)
  393.                 if (
  394.                         (!getIndexNode("sensorTemperature", sensor + 1, &sensorTemperature[sensor])) ||
  395.                         (!getIndexNode("sensorWarningThreshold", sensor + 1, &sensorWarningThreshold[sensor])) ||
  396.                         (!getIndexNode("sensorFailureThreshold", sensor + 1, &sensorFailureThreshold[sensor]))
  397.                 ) {
  398.                         return false;
  399.                 }
  400.  
  401.         for (int name = 0; name < MaxCommunities; ++name)
  402.                 if (!getIndexNode("snmpCommunityName", name + 1, &snmpCommunityName[name]))
  403.                         return false;
  404.  
  405.         for (int fan = 0; fan < MaxFans; ++fan)
  406.                 if (!getIndexNode("fanSpeed", fan + 1, &fanSpeed[fan]))
  407.                         return false;
  408.  
  409.         for (int aux = 0; aux < MaxPsAuxSupplies; ++aux) {
  410.                 if (
  411.                         (!getIndexNode("psAuxiliaryMeasurementVoltage", aux + 1, &psAuxVoltage[aux])) ||
  412.                         (!getIndexNode("psAuxiliaryMeasurementCurrent", aux + 1, &psAuxCurrent[aux]))
  413.                 ) {
  414.                         return false;
  415.                 }
  416.         }
  417.  
  418.         snmp_log(LOG_DEBUG, "*** Initialise SNMP done ***\n");
  419.         SOCK_STARTUP;                                                                                   // only in main thread
  420.  
  421.         return true;
  422. }
  423.  
  424. /**
  425.  * @brief Additional cleanup. Should be called after snmpClose.
  426.  */
  427. void snmpCleanup(void)
  428. {
  429.         SOCK_CLEANUP;
  430. }
  431.  
  432. /**
  433.  * @brief Set a new read community name for SNMP access.
  434.  *
  435.  * The read community name has to match the configured read community name in the MPOD.
  436.  * The default read community name is "public".
  437.  * @since 1.1
  438.  * @note This function must be called before snmpOpen().
  439.  * @param readCommunityName the new read community name
  440.  */
  441. void snmpSetReadCommunityName(const char * const readCommunityName)
  442. {
  443.         m_readCommunity = strdup(readCommunityName);
  444. }
  445.  
  446. /**
  447.  * @brief Set a new write community name for SNMP access.
  448.  *
  449.  * The write community name has to match the configured write community name in the MPOD.
  450.  * The default write community name is "guru".
  451.  * @since 1.1
  452.  * @note This function must be called before any write access function.
  453.  * @param writeCommunityName the new write community name
  454.  */
  455. void snmpSetWriteCommunityName(const char * const writeCommunityName)
  456. {
  457.         m_writeCommunity = strdup(writeCommunityName);
  458. }
  459.  
  460. /**
  461.  * @brief Opens a SNMP session to the specified ipAddress.
  462.  *
  463.  * This function also sets the number of retries and the timeout value.
  464.  * @param ipAddress a zero-terminated ASCII string representation
  465.  * of an IPv4 address, e.g. "192.168.17.101"
  466.  * @return a handle to the opened SNMP session, which is a required
  467.  * parameter for any further call.
  468.  */
  469. HSNMP snmpOpen(const char * const ipAddress)
  470. {
  471.         HSNMP session;
  472.         struct snmp_session snmpSession;
  473.         snmp_sess_init(&snmpSession);                  // structure defaults
  474.         snmpSession.version = SNMP_VERSION_2c;
  475.         snmpSession.peername = strdup(ipAddress);
  476.         snmpSession.community = (u_char *)strdup(m_readCommunity);
  477.         snmpSession.community_len = strlen(m_readCommunity);
  478.  
  479.         snmpSession.timeout = 300000;   // timeout (us)
  480.         snmpSession.retries = 2;        // retries
  481.  
  482.         if (!(session = snmp_sess_open(&snmpSession))) {
  483.                 int liberr, syserr;
  484.                 char *errstr;
  485.                 snmp_error(&snmpSession, &liberr, &syserr, &errstr);
  486.                 snmp_log(LOG_ERR, "Open SNMP session for host \"%s\": %s\n", ipAddress, errstr);
  487.                 free(errstr);
  488.                 return 0;
  489.         }
  490.  
  491.         snmp_log(LOG_INFO, "SNMP session for host \"%s\" opened\n", ipAddress);
  492.         return session;
  493. }
  494.  
  495. /**
  496.  * @brief Closes the previously opened session specified by session.
  497.  * @param session The handle returned by snmpOpen()
  498.  */
  499. void snmpClose(HSNMP session)
  500. {
  501.         if (!session)
  502.                 return;
  503.  
  504.         if (!snmp_sess_close(session))
  505.                 snmp_log(LOG_ERR, "Close SNMP session: ERROR\n");
  506.         else
  507.                 snmp_log(LOG_INFO, "SNMP session closed\n");
  508. }
  509.  
  510. /**
  511.  * @brief Returns a pointer to a descriptive string for the last failed SNMP operation.
  512.  * @return a pointer to a zero-terminated error string for the last failed
  513.  * SNMP operation. Note: this pointer is valid until the next string operation.
  514.  */
  515. char *snmpGetLastError(void)
  516. {
  517.         return snmpLastErrorBuffer;
  518. }
  519.  
  520. // System Information Functions
  521.  
  522. /**
  523.  * @brief Returns a pointer to the MPOD controller description string.
  524.  *
  525.  * The pointer is valid until the next call of any string function.
  526.  * @param session The handle returned by snmpOpen()
  527.  * @return the MPOD controller description string, containing the
  528.  * controller serial number and firmware releases, e.g.:
  529.  * "WIENER MPOD (4388090, MPOD 2.1.2098.1, MPODslave 1.09, MPOD-BL 1.50 )"
  530.  */
  531. char *getSysDescr(HSNMP session)
  532. {
  533.         return snmpGetString(session, &sysDescr);
  534. }
  535.  
  536. /**
  537.  * @brief Returns the crate power on/off status.
  538.  *
  539.  * The result is the logical "and" between the hardware main switch
  540.  * and the setMainSwitch function.
  541.  * @param session The handle returned by snmpOpen()
  542.  * @return The current on/off status of the crate:
  543.  * 0: crate is powered off
  544.  * 1: crate is powered on
  545.  */
  546. int getMainSwitch(HSNMP session)
  547. {
  548.         return snmpGetInt(session, &sysMainSwitch);
  549. }
  550.  
  551. /**
  552.  * @brief Sets the crate main switch to 1 = on or 0 = off.
  553.  *
  554.  * If the hardware main switch is set to "0" position, this function always returns 0.
  555.  * @param session The handle returned by snmpOpen()
  556.  * @param value 0 = set off, 1 = set on
  557.  * @return The new on/off status of the crate.
  558.  */
  559. int setMainSwitch(HSNMP session, int value)
  560. {
  561.         return snmpSetInt(session, &sysMainSwitch, value);
  562. }
  563.  
  564. /**
  565.  * @brief Returns a bit field with the status of the complete crate.
  566.  * @param session The handle returned by snmpOpen()
  567.  * @return The complete crate status.
  568.  */
  569. int getMainStatus(HSNMP session)
  570. {
  571.         return snmpGetInt(session, &sysStatus);
  572. }
  573.  
  574. /**
  575.  * @brief Returns the VME system reset status.
  576.  * @param session The handle returned by snmpOpen()
  577.  * @return
  578.  */
  579. int getVmeReset(HSNMP session)
  580. {
  581.         return snmpGetInt(session, &sysVmeSysReset);
  582. }
  583.  
  584. /**
  585.  * @brief Initiate a VME system reset.
  586.  * @param session The handle returned by snmpOpen()
  587.  * @return
  588.  */
  589. int setVmeReset(HSNMP session)
  590. {
  591.         return snmpSetInt(session, &sysVmeSysReset, 1);
  592. }
  593.  
  594. /**
  595.  * @brief Returns the static IP address as 32 bit integer.
  596.  * @param session The handle returned by snmpOpen()
  597.  * @return The static IP address.
  598.  */
  599. int getIpStaticAddress(HSNMP session)
  600. {
  601.         return snmpGetInt(session, &ipStaticAddress);
  602. }
  603.  
  604. /**
  605.  * @brief Sets a new static IP address.
  606.  * @param session The handle returned by snmpOpen()
  607.  * @param value The IP address as 32 bit integer
  608.  * @return
  609.  */
  610. int setIpStaticAddress(HSNMP session, int value)
  611. {
  612.         return snmpSetInt(session, &ipStaticAddress, value);
  613. }
  614.  
  615. /**
  616.  * @brief Returns a pointer to a string containing the MPOD controllers serial number.
  617.  *
  618.  * The pointer is valid until the next call of any string function.
  619.  * @param session The handle returned by snmpOpen()
  620.  * @return The crates serial number, e.g. "4388090".
  621.  */
  622. char *getPsSerialNumber(HSNMP session)
  623. {
  624.         return snmpGetString(session, &psSerialNumber);
  625. }
  626.  
  627. // System Count Functions
  628.  
  629. /**
  630.  * @brief Returns the total number of output channels in the crate.
  631.  * @param session The handle returned by snmpOpen()
  632.  * @return The total number of output channels
  633.  */
  634. int getOutputNumber(HSNMP session)
  635. {
  636.         return snmpGetInt(session, &outputNumber);
  637. }
  638.  
  639. /**
  640.  * @brief getOutputGroups
  641.  * @param session The handle returned by snmpOpen()
  642.  * @return
  643.  */
  644. int getOutputGroups(HSNMP session)
  645. {
  646.         return snmpGetInt(session, &groupsNumber);
  647. }
  648.  
  649. // Output Channel Information
  650.  
  651. /**
  652.  * @brief getOutputGroup
  653.  * @param session The handle returned by snmpOpen()
  654.  * @param channel The requested channel in the range of 0...999
  655.  * @return
  656.  */
  657. int getOutputGroup(HSNMP session, int channel)
  658. {
  659.         if (channel < 0 || channel >= MaxChannelsPerCrate)
  660.                 return 0;
  661.  
  662.         return snmpGetInt(session, &outputGroup[channel]);
  663. }
  664.  
  665. /**
  666.  * @brief Returns the channel outputStatus register.
  667.  * @note This function is deprecated. Use getOutputStatus() instead.
  668.  * @param session The handle returned by snmpOpen()
  669.  * @param channel The requested channel in the range of 0...999
  670.  * @return The channels outputStatus register
  671.  */
  672. int getChannelStatus(HSNMP session, int channel)
  673. {
  674.         return getOutputStatus(session, channel);
  675. }
  676.  
  677. /**
  678.  * @brief Returns the channel outputStatus register.
  679.  * @since 1.1
  680.  * @param session The handle returned by snmpOpen()
  681.  * @param channel The requested channel in the range of 0...999
  682.  * @return The channels outputStatus register
  683.  */
  684. int getOutputStatus(HSNMP session, int channel)
  685. {
  686.         if (channel < 0 || channel >= MaxChannelsPerCrate)
  687.                 return 0;
  688.  
  689.         return snmpGetInt(session, &outputStatus[channel]);
  690. }
  691.  
  692. /**
  693.  * @brief Returns the measured output sense voltage for channel in Volt.
  694.  * @note This is only valid for WIENER LV modules.
  695.  * @param session The handle returned by snmpOpen()
  696.  * @param channel The requested channel in the range of 0...999
  697.  * @return
  698.  */
  699. double getOutputSenseMeasurement(HSNMP session, int channel)
  700. {
  701.         if (channel < 0 || channel >= MaxChannelsPerCrate)
  702.                 return 0;
  703.  
  704.         return snmpGetDouble(session, &outputMeasurementSenseVoltage[channel]);
  705. }
  706.  
  707. /**
  708.  * @brief Returns the measured output terminal voltage for channel in Volt.
  709.  * @param session The handle returned by snmpOpen()
  710.  * @param channel The requested channel in the range of 0...999
  711.  * @return The measured output terminal voltage in Volt.
  712.  */
  713. double getOutputTerminalMeasurement(HSNMP session, int channel)
  714. {
  715.         if (channel < 0 || channel >= MaxChannelsPerCrate)
  716.                 return 0;
  717.  
  718.         return snmpGetDouble(session, &outputMeasurementTerminalVoltage[channel]);
  719. }
  720.  
  721. /**
  722.  * @brief Returns the measured output current for channel in Ampere.
  723.  * @param session The handle returned by snmpOpen()
  724.  * @param channel The requested channel in the range of 0...999
  725.  * @return The measured output measurement current in Ampere.
  726.  */
  727. double getCurrentMeasurement(HSNMP session, int channel)
  728. {
  729.         if (channel < 0 || channel >= MaxChannelsPerCrate)
  730.                 return 0;
  731.  
  732.         return snmpGetDouble(session, &outputMeasurementCurrent[channel]);
  733. }
  734.  
  735. /**
  736.  * @brief Returns the measured temperature for channel in Degree Celsius.
  737.  * @note Only WIENER Low Voltage modules have a channel-wise temperature measurement.
  738.  * For iseg HV modules, use getModuleAuxTemperature().
  739.  * @param session The handle returned by snmpOpen()
  740.  * @param channel The requested channel in the range of 0...999
  741.  * @return The measured output temperature in Degree Celsius.
  742.  */
  743. int getTemperatureMeasurement(HSNMP session, int channel)
  744. {
  745.         if (channel < 0 || channel >= MaxChannelsPerCrate)
  746.                 return 0;
  747.  
  748.         return snmpGetInt(session, &outputMeasurementTemperature[channel]);
  749. }
  750.  
  751. /**
  752.  * @brief Change the state of the channel.
  753.  * @note This function is deprecated. Use setOutputSwitch() instead.
  754.  * @param session The handle returned by snmpOpen()
  755.  * @param channel The channel in the range of 0...999
  756.  * @param value One of the following: off (0), on (1),
  757.  * resetEmergencyOff (2), setEmergencyOff (3), clearEvents (10).
  758.  * @return
  759.  */
  760. int setChannelSwitch(HSNMP session, int channel, int value)
  761. {
  762.         return setOutputSwitch(session, channel, value);
  763. }
  764.  
  765. /**
  766.  * @brief Change the state of the channel.
  767.  * @since 1.1
  768.  * @param session The handle returned by snmpOpen()
  769.  * @param channel The channel in the range of 0...999
  770.  * @param value One of the following: off (0), on (1),
  771.  * resetEmergencyOff (2), setEmergencyOff (3), clearEvents (10).
  772.  * @return
  773.  */
  774. int setOutputSwitch(HSNMP session, int channel, int value)
  775. {
  776.         if (channel < 0 || channel >= MaxChannelsPerCrate)
  777.                 return 0;
  778.  
  779.         return snmpSetInt(session, &outputSwitch[channel], value);
  780. }
  781.  
  782. /**
  783.  * @brief Returns the state of the channel.
  784.  * @note This function is deprecated. Use getOutputSwitch() instead.
  785.  * @param session The handle returned by snmpOpen()
  786.  * @param channel The requested channel in the range of 0...999
  787.  * @return One of the following: off (0), on (1),
  788.  * resetEmergencyOff (2), setEmergencyOff (3), clearEvents (10).
  789.  */
  790. int getChannelSwitch(HSNMP session, int channel)
  791. {
  792.         return getOutputSwitch(session, channel);
  793. }
  794.  
  795. /**
  796.  * @brief Returns the state of the channel.
  797.  * @since 1.1
  798.  * @param session The handle returned by snmpOpen()
  799.  * @param channel The requested channel in the range of 0...999
  800.  * @return One of the following: off (0), on (1),
  801.  * resetEmergencyOff (2), setEmergencyOff (3), clearEvents (10).
  802.  */
  803. int getOutputSwitch(HSNMP session, int channel)
  804. {
  805.         if (channel < 0 || channel >= MaxChannelsPerCrate)
  806.                 return 0;
  807.  
  808.         return snmpGetInt(session, &outputSwitch[channel]);
  809. }
  810.  
  811. /**
  812.  * @brief setHighVoltageGroupsSwitch
  813.  * @param session The handle returned by snmpOpen()
  814.  * @param value
  815.  * @return
  816.  */
  817. int setHighVoltageGroupsSwitch(HSNMP session, int value)
  818. {
  819.         return snmpSetInt(session, &highVoltageGroupsSwitch, value);
  820. }
  821.  
  822. /**
  823.  * @brief getHighVoltageGroupsSwitch
  824.  * @param session The handle returned by snmpOpen()
  825.  * @return
  826.  */
  827. int getHighVoltageGroupsSwitch(HSNMP session)
  828. {
  829.         return snmpGetInt(session, &highVoltageGroupsSwitch);
  830. }
  831.  
  832. /**
  833.  * @brief setLowVoltageGroupsSwitch
  834.  * @param session The handle returned by snmpOpen()
  835.  * @param value
  836.  * @return
  837.  */
  838. int setLowVoltageGroupsSwitch(HSNMP session, int value)
  839. {
  840.         return snmpSetInt(session, &lowVoltageGroupsSwitch, value);
  841. }
  842.  
  843. /**
  844.  * @brief getLowVoltageGroupsSwitch
  845.  * @param session The handle returned by snmpOpen()
  846.  * @return
  847.  */
  848. int getLowVoltageGroupsSwitch(HSNMP session)
  849. {
  850.         return snmpGetInt(session, &lowVoltageGroupsSwitch);
  851. }
  852.  
  853. /**
  854.  * @brief Returns the demanded output voltage for channel.
  855.  * @param session The handle returned by snmpOpen()
  856.  * @param channel The requested channel in the range of 0...999
  857.  * @return The demanded output voltage in Volt.
  858.  */
  859. double getOutputVoltage(HSNMP session, int channel)
  860. {
  861.         if (channel < 0 || channel >= MaxChannelsPerCrate)
  862.                 return 0;
  863.  
  864.         return snmpGetDouble(session, &outputVoltage[channel]);
  865. }
  866.  
  867. /**
  868.  * @brief Sets the demanded output voltage for channel.
  869.  * @param session The handle returned by snmpOpen()
  870.  * @param channel The requested channel in the range of 0...999
  871.  * @param value the demanded output voltage in Volt.
  872.  * @return The demanded output voltage in Volt.
  873.  */
  874. double setOutputVoltage(HSNMP session, int channel, double value)
  875. {
  876.         if (channel < 0 || channel >= MaxChannelsPerCrate)
  877.                 return 0;
  878.  
  879.         return snmpSetDouble(session, &outputVoltage[channel], value);
  880. }
  881.  
  882. /**
  883.  * @brief Returns the demanded maximum output current for channel.
  884.  * @param session The handle returned by snmpOpen()
  885.  * @param channel The requested channel in the range of 0...999
  886.  * @return The demanded output current in Ampere.
  887.  */
  888. double getOutputCurrent(HSNMP session, int channel)
  889. {
  890.         if (channel < 0 || channel >= MaxChannelsPerCrate)
  891.                 return 0;
  892.  
  893.         return snmpGetDouble(session, &outputCurrent[channel]);
  894. }
  895.  
  896. /**
  897.  * @brief Sets the demanded maximum output current for channel.
  898.  * @param session The handle returned by snmpOpen()
  899.  * @param channel The channel in the range of 0...999
  900.  * @param value The demanded ouput current in Ampere
  901.  * @return The demanded maximum output current in Ampere.
  902.  */
  903. double setOutputCurrent(HSNMP session, int channel, double value)
  904. {
  905.         if (channel < 0 || channel >= MaxChannelsPerCrate)
  906.                 return 0;
  907.  
  908.         return snmpSetDouble(session, &outputCurrent[channel], value);
  909. }
  910.  
  911. /**
  912.  * @brief Returns the channel voltage rise rate in Volt/second.
  913.  *
  914.  * @note This function is for WIENER LV only.
  915.  * For iseg HV modules, use getModuleRampSpeedVoltage().
  916.  * @param session The handle returned by snmpOpen()
  917.  * @param channel The requested channel in the range of 0...999
  918.  * @return
  919.  */
  920. double getOutputRiseRate(HSNMP session, int channel)
  921. {
  922.         if (channel < 0 || channel >= MaxChannelsPerCrate)
  923.                 return 0;
  924.  
  925.         return snmpGetDouble(session, &outputVoltageRiseRate[channel]);
  926. }
  927.  
  928. /**
  929.  * @brief Sets the channel voltage rise rate in Volt/second.
  930.  *
  931.  * @note This function is for WIENER LV only.
  932.  * For iseg HV modules, use setModuleRampSpeedVoltage().
  933.  * @param session The handle returned by snmpOpen()
  934.  * @param channel The requested channel in the range of 0...999
  935.  * @param value
  936.  * @return
  937.  */
  938. double setOutputRiseRate(HSNMP session, int channel, double value)
  939. {
  940.         if (channel < 0 || channel >= MaxChannelsPerCrate)
  941.                 return 0;
  942.  
  943.         return snmpSetDouble(session, &outputVoltageRiseRate[channel], value);
  944. }
  945.  
  946. /**
  947.  * @brief Returns the channel voltage fall rate in Volt/second.
  948.  *
  949.  * @note This function is for WIENER LV only.
  950.  * For iseg HV modules, use getModuleRampSpeedVoltage().
  951.  * @param session The handle returned by snmpOpen()
  952.  * @param channel The requested channel in the range of 0...999
  953.  * @return
  954.  */
  955. double getOutputFallRate(HSNMP session, int channel)
  956. {
  957.         if (channel < 0 || channel >= MaxChannelsPerCrate)
  958.                 return 0;
  959.  
  960.         return snmpGetDouble(session, &outputVoltageFallRate[channel]);
  961. }
  962.  
  963. /**
  964.  * @brief Sets the channel voltage fall rate in Volt/second.
  965.  *
  966.  * @note This function is for WIENER LV only.
  967.  * For iseg HV modules, use setModuleRampSpeedVoltage().
  968.  * @param session The handle returned by snmpOpen()
  969.  * @param channel The requested channel in the range of 0...999
  970.  * @param value
  971.  * @return
  972.  */
  973. double setOutputFallRate(HSNMP session, int channel, double value)
  974. {
  975.         if (channel < 0 || channel >= MaxChannelsPerCrate)
  976.                 return 0;
  977.  
  978.         return snmpSetDouble(session, &outputVoltageFallRate[channel], value);
  979. }
  980.  
  981. /**
  982.  * @brief Returns the channel current rise rate in Ampere/second.
  983.  *
  984.  * @note This function is for WIENER LV only.
  985.  * For iseg HV modules, use getModuleRampSpeedCurrent().
  986.  * @param session The handle returned by snmpOpen()
  987.  * @param channel The requested channel in the range of 0...999
  988.  * @return
  989.  */
  990. double getOutputCurrentRiseRate(HSNMP session, int channel)
  991. {
  992.         if (channel < 0 || channel >= MaxChannelsPerCrate)
  993.                 return 0;
  994.  
  995.         return snmpGetDouble(session, &outputCurrentRiseRate[channel]);
  996. }
  997.  
  998. /**
  999.  * @brief Sets the channel current rise rate in Ampere/second.
  1000.  *
  1001.  * @note This function is for WIENER LV only.
  1002.  * For iseg HV modules, use setModuleRampSpeedCurrent().
  1003.  * @param session The handle returned by snmpOpen()
  1004.  * @param channel The requested channel in the range of 0...999
  1005.  * @param value
  1006.  * @return
  1007.  */
  1008. double setOutputCurrentRiseRate(HSNMP session, int channel, double value)
  1009. {
  1010.         if (channel < 0 || channel >= MaxChannelsPerCrate)
  1011.                 return 0;
  1012.  
  1013.         return snmpSetDouble(session, &outputCurrentRiseRate[channel], value);
  1014. }
  1015.  
  1016. /**
  1017.  * @brief Returns the channel current fall rate in Ampere/second.
  1018.  *
  1019.  * @note This function is for WIENER LV only.
  1020.  * For iseg HV modules, use getModuleRampSpeedCurrent().
  1021.  * @param session The handle returned by snmpOpen()
  1022.  * @param channel The requested channel in the range of 0...999
  1023.  * @return
  1024.  */
  1025. double getOutputCurrentFallRate(HSNMP session, int channel)
  1026. {
  1027.         if (channel < 0 || channel >= MaxChannelsPerCrate)
  1028.                 return 0;
  1029.  
  1030.         return snmpGetDouble(session, &outputCurrentFallRate[channel]);
  1031. }
  1032.  
  1033. /**
  1034.  * @brief Sets the channel current fall rate in Ampere/second.
  1035.  *
  1036.  * @note This function is for WIENER LV only.
  1037.  * For iseg HV modules, use setModuleRampSpeedCurrent().
  1038.  * @param session The handle returned by snmpOpen()
  1039.  * @param channel The requested channel in the range of 0...999
  1040.  * @param value
  1041.  * @return
  1042.  */
  1043. double setOutputCurrentFallRate(HSNMP session, int channel, double value)
  1044. {
  1045.         if (channel < 0 || channel >= MaxChannelsPerCrate)
  1046.                 return 0;
  1047.  
  1048.         return snmpSetDouble(session, &outputCurrentFallRate[channel], value);
  1049. }
  1050.  
  1051. /**
  1052.  * @brief Returns a bit field packed into an integer
  1053.  * which define the behavior of the output channel or power supply after failures.
  1054.  * @param session The handle returned by snmpOpen()
  1055.  * @param channel The requested channel in the range of 0...999
  1056.  * @return
  1057.  */
  1058. int getOutputSupervisionBehavior(HSNMP session, int channel)
  1059. {
  1060.         if (channel < 0 || channel >= MaxChannelsPerCrate)
  1061.                 return 0;
  1062.  
  1063.         return snmpGetInt(session, &outputSupervisionBehavior[channel]);
  1064. }
  1065.  
  1066. /**
  1067.  * @brief Set the behavior of the output channel or power supply after failures.
  1068.  *
  1069.  * For each supervision value, a two-bit field exists.
  1070.  * The enumeration of this value (..L+..H*2) is:
  1071.  *           WIENER LV devices
  1072.  *              0           ignore the failure
  1073.  *              1           switch off this channel
  1074.  *              2           switch off all channels with the same group number
  1075.  *              3           switch off the complete crate.
  1076.  *           iseg HV devices
  1077.  *              0           ignore the failure
  1078.  *              1           switch off this channel by ramp down the voltage
  1079.  *              2           switch off this channel by a emergencyOff
  1080.  *              3           switch off the whole board of the HV module by emergencyOff.
  1081.  *           The position of the bit fields in the integer value are:
  1082.  *              Bit 0, 1:   outputFailureMinSenseVoltage
  1083.  *              Bit 2, 3:   outputFailureMaxSenseVoltage
  1084.  *              Bit 4, 5:   outputFailureMaxTerminalVoltage
  1085.  *              Bit 6, 7:   outputFailureMaxCurrent
  1086.  *              Bit 8, 9:   outputFailureMaxTemperature
  1087.  *              Bit 10, 11: outputFailureMaxPower
  1088.  *              Bit 12, 13: outputFailureInhibit
  1089.  *              Bit 14, 15: outputFailureTimeout
  1090.  * @param session The handle returned by snmpOpen()
  1091.  * @param channel The channel (0...999) for which the behaviour should be set
  1092.  * @param value The 16 bit integer with bits set according the preceding table.
  1093.  * @return
  1094.  */
  1095. int setOutputSupervisionBehavior(HSNMP session, int channel, int value)
  1096. {
  1097.         if (channel < 0 || channel >= MaxChannelsPerCrate)
  1098.                 return 0;
  1099.  
  1100.         return snmpSetInt(session, &outputSupervisionBehavior[channel], value );
  1101. }
  1102.  
  1103. /**
  1104.  * @brief getOutputSupervisionMinSenseVoltage
  1105.  * @param session The handle returned by snmpOpen()
  1106.  * @param channel The requested channel in the range of 0...999
  1107.  * @return
  1108.  */
  1109. double getOutputSupervisionMinSenseVoltage(HSNMP session, int channel)
  1110. {
  1111.         if (channel < 0 || channel >= MaxChannelsPerCrate)
  1112.                 return 0;
  1113.  
  1114.         return snmpGetDouble(session, &outputSupervisionMinSenseVoltage[channel]);
  1115. }
  1116.  
  1117. /**
  1118.  * @brief setOutputSupervisionMinSenseVoltage
  1119.  * @param session The handle returned by snmpOpen()
  1120.  * @param channel
  1121.  * @param value
  1122.  * @return
  1123.  */
  1124. double setOutputSupervisionMinSenseVoltage(HSNMP session, int channel, double value)
  1125. {
  1126.         if (channel < 0 || channel >= MaxChannelsPerCrate)
  1127.                 return 0;
  1128.  
  1129.         return snmpSetDouble(session, &outputSupervisionMinSenseVoltage[channel], value);
  1130. }
  1131.  
  1132. /**
  1133.  * @brief getOutputSupervisionMaxSenseVoltage
  1134.  * @param session The handle returned by snmpOpen()
  1135.  * @param channel The requested channel in the range of 0...999
  1136.  * @return
  1137.  */
  1138. double getOutputSupervisionMaxSenseVoltage(HSNMP session, int channel)
  1139. {
  1140.         if (channel < 0 || channel >= MaxChannelsPerCrate)
  1141.                 return 0;
  1142.  
  1143.         return snmpGetDouble(session, &outputSupervisionMaxSenseVoltage[channel]);
  1144. }
  1145.  
  1146. /**
  1147.  * @brief setOutputSupervisionMaxSenseVoltage
  1148.  * @param session The handle returned by snmpOpen()
  1149.  * @param channel
  1150.  * @param value
  1151.  * @return
  1152.  */
  1153. double setOutputSupervisionMaxSenseVoltage(HSNMP session, int channel, double value)
  1154. {
  1155.         if (channel < 0 || channel >= MaxChannelsPerCrate)
  1156.                 return 0;
  1157.  
  1158.         return snmpSetDouble(session, &outputSupervisionMaxSenseVoltage[channel], value);
  1159. }
  1160.  
  1161. /**
  1162.  * @brief If the measured voltage at the power supply output terminals is above this value,
  1163.  * the power supply performs the function defined by setOutputSupervisionBehavior().
  1164.  * @param session The handle returned by snmpOpen()
  1165.  * @param channel The requested channel in the range of 0...999
  1166.  * @return The maximum terminal voltage in Volt
  1167.  */
  1168. double getOutputSupervisionMaxTerminalVoltage(HSNMP session, int channel)
  1169. {
  1170.         if (channel < 0 || channel >= MaxChannelsPerCrate)
  1171.                 return 0;
  1172.  
  1173.         return snmpGetDouble(session, &outputSupervisionMaxTerminalVoltage[channel]);
  1174. }
  1175.  
  1176. /**
  1177.  * @brief If the measured voltage at the power supply output terminals is above this value,
  1178.  * the power supply performs the function defined by setOutputSupervisionBehavior().
  1179.  * @param session The handle returned by snmpOpen()
  1180.  * @param channel the channel (0...999) to set the max. terminal voltage
  1181.  * @param value The maximum terminal voltage in Volt
  1182.  * @return
  1183.  */
  1184. double setOutputSupervisionMaxTerminalVoltage(HSNMP session, int channel, double value)
  1185. {
  1186.         if (channel < 0 || channel >= MaxChannelsPerCrate)
  1187.                 return 0;
  1188.  
  1189.         return snmpSetDouble(session, &outputSupervisionMaxTerminalVoltage[channel], value);
  1190. }
  1191.  
  1192. /**
  1193.  * @brief If the measured current is above this value, the power supply
  1194.  * performs the function defined by setOutputSupervisionBehavior().
  1195.  * @param session The handle returned by snmpOpen()
  1196.  * @param channel The requested channel in the range of 0...999
  1197.  * @return The maximum output current in Ampere
  1198.  */
  1199. double getOutputSupervisionMaxCurrent(HSNMP session, int channel)
  1200. {
  1201.         if (channel < 0 || channel >= MaxChannelsPerCrate)
  1202.                 return 0;
  1203.  
  1204.         return snmpGetDouble(session, &outputSupervisionMaxCurrent[channel]);
  1205. }
  1206.  
  1207. /**
  1208.  * @brief If the measured current is above this value, the power supply
  1209.  * performs the function defined by setOutputSupervisionBehavior().
  1210.  * @param session The handle returned by snmpOpen()
  1211.  * @param channel The channel (0...999) to set the max. current
  1212.  * @param value The maximum current in Ampere
  1213.  * @return
  1214.  */
  1215. double setOutputSupervisionMaxCurrent(HSNMP session, int channel, double value)
  1216. {
  1217.         if (channel < 0 || channel >= MaxChannelsPerCrate)
  1218.                 return 0;
  1219.  
  1220.         return snmpSetDouble(session, &outputSupervisionMaxCurrent[channel], value );
  1221. }
  1222.  
  1223. /**
  1224.  * @brief getOutputSupervisionMaxTemperature
  1225.  * @param session The handle returned by snmpOpen()
  1226.  * @param channel The requested channel in the range of 0...999
  1227.  * @return The maximum temperature in degree Celsius
  1228.  */
  1229. int getOutputSupervisionMaxTemperature(HSNMP session, int channel)
  1230. {
  1231.         if (channel < 0 || channel >= MaxChannelsPerCrate)
  1232.                 return 0;
  1233.  
  1234.         return snmpGetInt(session, &outputSupervisionMaxTemperature[channel]);
  1235. }
  1236.  
  1237. /**
  1238.  * @brief getOutputConfigMaxSenseVoltage
  1239.  * @param session The handle returned by snmpOpen()
  1240.  * @param channel The requested channel in the range of 0...999
  1241.  * @return
  1242.  */
  1243. double getOutputConfigMaxSenseVoltage(HSNMP session, int channel)
  1244. {
  1245.         if (channel < 0 || channel >= MaxChannelsPerCrate)
  1246.                 return 0;
  1247.  
  1248.         return snmpGetDouble(session, &outputConfigMaxSenseVoltage[channel]);
  1249. }
  1250.  
  1251. /**
  1252.  * @brief getOutputConfigMaxTerminalVoltage
  1253.  * @param session The handle returned by snmpOpen()
  1254.  * @param channel The requested channel in the range of 0...999
  1255.  * @return
  1256.  */
  1257. double getOutputConfigMaxTerminalVoltage(HSNMP session, int channel)
  1258. {
  1259.         if (channel < 0 || channel >= MaxChannelsPerCrate)
  1260.                 return 0;
  1261.  
  1262.         return snmpGetDouble(session, &outputConfigMaxTerminalVoltage[channel]);
  1263. }
  1264.  
  1265. /**
  1266.  * @brief getOutputConfigMaxCurrent
  1267.  * @param session The handle returned by snmpOpen()
  1268.  * @param channel The requested channel in the range of 0...999
  1269.  * @return
  1270.  */
  1271. double getOutputConfigMaxCurrent(HSNMP session, int channel)
  1272. {
  1273.         if (channel < 0 || channel >= MaxChannelsPerCrate)
  1274.                 return 0;
  1275.  
  1276.         return snmpGetDouble(session, &outputConfigMaxCurrent[channel]);
  1277. }
  1278.  
  1279. /**
  1280.  * @brief getOutputSupervisionMaxPower
  1281.  * @param session The handle returned by snmpOpen()
  1282.  * @param channel The requested channel in the range of 0...999
  1283.  * @return
  1284.  */
  1285. double getOutputSupervisionMaxPower(HSNMP session, int channel)
  1286. {
  1287.         if (channel < 0 || channel >= MaxChannelsPerCrate)
  1288.                 return 0;
  1289.  
  1290.         return snmpGetDouble(session, &outputSupervisionMaxPower[channel]);
  1291. }
  1292.  
  1293. /**
  1294.  * @brief Returns the time span for the delayed trip function.
  1295.  * @param session The handle returned by snmpOpen()
  1296.  * @param channel The requested channel in the range of 0...999
  1297.  * @return the trip delay time (0...4000 ms)
  1298.  */
  1299. int getOutputTripTimeMaxCurrent(HSNMP session, int channel)
  1300. {
  1301.         if (channel < 0 || channel >= MaxChannelsPerCrate)
  1302.                 return 0;
  1303.  
  1304.         return snmpGetInt(session, &outputTripTimeMaxCurrent[channel]);
  1305. }
  1306.  
  1307. /**
  1308.  * @brief Defines a span for the delayed trip function.
  1309.  * @param session The handle returned by snmpOpen()
  1310.  * @param channel The channel (0...999) for which to set the delayed trip
  1311.  * @param delay The trip delay time (0...4000 ms)
  1312.  * @return
  1313.  */
  1314. int setOutputTripTimeMaxCurrent(HSNMP session, int channel, int delay)
  1315. {
  1316.         if (channel < 0 || channel >= MaxChannelsPerCrate)
  1317.                 return 0;
  1318.  
  1319.         return snmpSetInt(session, &outputTripTimeMaxCurrent[channel], delay);
  1320. }
  1321.  
  1322. // Sensor Information functions
  1323.  
  1324. int getSensorNumber(HSNMP session)
  1325. {
  1326.         return snmpGetInt(session, &sensorNumber);
  1327. }
  1328.  
  1329. int getSensorTemp(HSNMP session, int sensor)
  1330. {
  1331.         if (sensor < 0 || sensor > MaxSensors)
  1332.                 return 0;
  1333.  
  1334.         return snmpGetInt(session, &sensorTemperature[sensor]);
  1335. }
  1336.  
  1337. int getSensorWarningTemperature(HSNMP session, int sensor)
  1338. {
  1339.         if (sensor < 0 || sensor > MaxSensors)
  1340.                 return 0;
  1341.  
  1342.         return snmpGetInt(session, &sensorWarningThreshold[sensor]);
  1343. }
  1344.  
  1345. int setSensorWarningTemperature(HSNMP session, int sensor, int value)
  1346. {
  1347.         if (sensor < 0 || sensor > MaxSensors)
  1348.                 return 0;
  1349.  
  1350.         return snmpSetInt(session, &sensorWarningThreshold[sensor], value);
  1351. }
  1352.  
  1353. int getSensorFailureTemperature(HSNMP session, int sensor)
  1354. {
  1355.         if (sensor < 0 || sensor > MaxSensors)
  1356.                 return 0;
  1357.  
  1358.         return snmpGetInt(session, &sensorFailureThreshold[sensor]);
  1359. }
  1360.  
  1361. int setSensorFailureTemperature(HSNMP session, int sensor, int value)
  1362. {
  1363.         if (sensor < 0 || sensor > MaxSensors)
  1364.                 return 0;
  1365.  
  1366.         return snmpSetInt(session, &sensorFailureThreshold[sensor], value);
  1367. }
  1368.  
  1369. // Power Supply specific Functions.
  1370.  
  1371. /**
  1372.  * @brief Returns the crates operating time in seconds.
  1373.  * @param session The handle returned by snmpOpen()
  1374.  * @return
  1375.  */
  1376. int getPsOperatingTime(HSNMP session)
  1377. {
  1378.         return snmpGetInt(session, &psOperatingTime);
  1379. }
  1380.  
  1381. double getPsAuxVoltage(HSNMP session, int auxIndex)
  1382. {
  1383.         if ( (auxIndex < 0) || (auxIndex >= MaxPsAuxSupplies) )
  1384.                 return 0.0;
  1385.  
  1386.         return snmpGetDouble(session, &psAuxVoltage[auxIndex]);
  1387. }
  1388.  
  1389. double getPsAuxCurrent(HSNMP session, int auxIndex)
  1390. {
  1391.         if ( (auxIndex < 0) || (auxIndex >= MaxPsAuxSupplies) )
  1392.                 return 0.0;
  1393.  
  1394.         return snmpGetDouble(session, &psAuxCurrent[auxIndex]);
  1395. }
  1396.  
  1397. // Fan Tray Functions
  1398.  
  1399. int getFanOperatingTime(HSNMP session)
  1400. {
  1401.         return snmpGetInt(session, &fanOperatingTime);
  1402. }
  1403.  
  1404. int getFanAirTemperature(HSNMP session)
  1405. {
  1406.         return snmpGetInt(session, &fanAirTemperature);
  1407. }
  1408.  
  1409. int getFanSwitchOffDelay(HSNMP session)
  1410. {
  1411.         return snmpGetInt(session, &fanSwitchOffDelay);
  1412. }
  1413.  
  1414. int setFanSwitchOffDelay(HSNMP session, int value)
  1415. {
  1416.         return snmpSetInt(session, &fanSwitchOffDelay, value);
  1417. }
  1418.  
  1419. /**
  1420.  * @brief Returns the MPODs fan rotation speed in revolutions per minute.
  1421.  * @param session The handle returned by snmpOpen()
  1422.  * @return
  1423.  */
  1424. int getFanNominalSpeed(HSNMP session)
  1425. {
  1426.         return snmpGetInt(session, &fanNominalSpeed);
  1427. }
  1428.  
  1429. /**
  1430.  * @brief Sets the MPODs fan rotation speed in revolutions per minute.
  1431.  * @param session The handle returned by snmpOpen()
  1432.  * @param value 1200..3600. 0 turns off the crates fans.
  1433.  * @return
  1434.  */
  1435. int setFanNominalSpeed(HSNMP session, int value)
  1436. {
  1437.         return snmpSetInt(session, &fanNominalSpeed, value );
  1438. }
  1439.  
  1440. int getFanNumberOfFans(HSNMP session)
  1441. {
  1442.         return snmpGetInt(session, &fanNumberOfFans);
  1443. }
  1444.  
  1445. int getFanSpeed(HSNMP session, int fan)
  1446. {
  1447.         if (fan < 0 || fan > MaxFans)
  1448.                 return 0;
  1449.  
  1450.         return snmpGetInt(session, &fanSpeed[fan]);
  1451. }
  1452.  
  1453. /**
  1454.  * @brief Returns a pointer to the module description string.
  1455.  *
  1456.  * The pointer is valid until the next call of any string function.
  1457.  * @param session The handle returned by snmpOpen()
  1458.  * @param slot The modules slot position in the crate (0...9)
  1459.  * @return A string with the following contents, separated by comma and space:
  1460.  * - The module vendor ("iseg" or "WIENER")
  1461.  * - The module type name
  1462.  * - The channel number
  1463.  * - The module serial number (optional)
  1464.  * - The module firmware release (optional)
  1465.  *
  1466.  * Example: "iseg, E24D1, 24, 715070, 5.14"
  1467.  */
  1468. char *getModuleDescription(HSNMP session, int slot)
  1469. {
  1470.         if (slot < 0 || slot >= MaxSlotsPerCrate)
  1471.                 return 0;
  1472.  
  1473.         return snmpGetString(session, &moduleDescription[slot]);
  1474. }
  1475.  
  1476. /**
  1477.  * @brief Returns the measured value of the modules +24 Volt line.
  1478.  * @note This function is for iseg HV modules only.
  1479.  * @param session The handle returned by snmpOpen()
  1480.  * @param slot the modules slot position in the crate (0...9)
  1481.  * @return the measured +24 Volt line voltage in Volt.
  1482.  */
  1483. double getModuleSupply24(HSNMP session, int slot)
  1484. {
  1485.         if (slot < 0 || slot >= MaxSlotsPerCrate)
  1486.                 return 0.0;
  1487.  
  1488.         return snmpGetDouble(session, &moduleSupply[0][slot]);
  1489. }
  1490.  
  1491. /**
  1492.  * @brief Returns the measured value of the modules +5 Volt line.
  1493.  * @note This function is for iseg HV modules only.
  1494.  * @param session The handle returned by snmpOpen()
  1495.  * @param slot the modules slot position in the crate (0...9)
  1496.  * @return the measured +5 Volt line voltage in Volt.
  1497.  */
  1498. double getModuleSupply5(HSNMP session, int slot)
  1499. {
  1500.         if (slot < 0 || slot >= MaxSlotsPerCrate)
  1501.                 return 0.0;
  1502.  
  1503.         return snmpGetDouble(session, &moduleSupply[1][slot]);
  1504. }
  1505.  
  1506. /**
  1507.  * @brief Returns the measured value of one of the modules temperature sensors.
  1508.  *
  1509.  * @note This function is for iseg HV modules only.
  1510.  * @param session The handle returned by snmpOpen()
  1511.  * @param slot The modules slot position in the crate (0...9)
  1512.  * @param index The temperature sensor index (0...3)
  1513.  * @note Most modules only have one temperature sensor at index 0.
  1514.  * @return
  1515.  */
  1516. double getModuleAuxTemperature(HSNMP session, int slot, int index)
  1517. {
  1518.         if (slot < 0 || slot >= MaxSlotsPerCrate)
  1519.                 return 0.0;
  1520.  
  1521.         if (index < 0 || index >= MaxModuleAuxTemperatures)
  1522.                 return 0.0;
  1523.  
  1524.         return snmpGetDouble(session, &moduleAuxiliaryMeasurementTemperature[index][slot]);
  1525. }
  1526.  
  1527. /**
  1528.  * @brief Returns the modules hardware voltage limit in percent.
  1529.  *
  1530.  * @note This function is for iseg HV modules only.
  1531.  * @param session The handle returned by snmpOpen()
  1532.  * @param slot The modules slot position in the crate (0...9)
  1533.  * @return The modules hardware voltage limit in percent (2...102)
  1534.  */
  1535. double getModuleHardwareLimitVoltage(HSNMP session, int slot)
  1536. {
  1537.         if (slot < 0 || slot >= MaxSlotsPerCrate)
  1538.                 return 0.0;
  1539.  
  1540.         return snmpGetDouble(session, &moduleHardwareLimitVoltage[slot]);
  1541. }
  1542.  
  1543. /**
  1544.  * @brief Returns the modules hardware current limit in percent.
  1545.  *
  1546.  * @note This function is for iseg HV modules only.
  1547.  * @param session The handle returned by snmpOpen()
  1548.  * @param slot The modules slot position in the crate (0...9)
  1549.  * @return The modules hardware current limit in percent (2...102)
  1550.  */
  1551. double getModuleHardwareLimitCurrent(HSNMP session, int slot)
  1552. {
  1553.         if (slot < 0 || slot >= MaxSlotsPerCrate)
  1554.                 return 0.0;
  1555.  
  1556.         return snmpGetDouble(session, &moduleHardwareLimitCurrent[slot]);
  1557. }
  1558.  
  1559. /**
  1560.  * @brief Returns the modules voltage ramp speed in percent.
  1561.  *
  1562.  * @note This function is for iseg HV modules only.
  1563.  * iseg modules have one common ramp speed for all channels.
  1564.  * @param session The handle returned by snmpOpen()
  1565.  * @param slot The modules slot position in the crate (0...9)
  1566.  * @return The modules voltage ramp speed in percent
  1567.  */
  1568. double getModuleRampSpeedVoltage(HSNMP session, int slot)
  1569. {
  1570.         if (slot < 0 || slot >= MaxSlotsPerCrate)
  1571.                 return 0.0;
  1572.  
  1573.         return snmpGetDouble(session, &moduleRampSpeedVoltage[slot]);
  1574. }
  1575.  
  1576. /**
  1577.  * @brief Sets the modules voltage ramp speed in percent.
  1578.  *
  1579.  * @note This function is for iseg HV modules only.
  1580.  *
  1581.  * iseg modules have one common ramp speed for all channels.
  1582.  * @param session The handle returned by snmpOpen()
  1583.  * @param slot the modules slot position in the crate (0...9)
  1584.  * @param value The new voltage ramp speed in percent
  1585.  * @note For most modules, the range is 0.001...20 percent.
  1586.  * @return The new voltage ramp speed in percent
  1587.  */
  1588. double setModuleRampSpeedVoltage(HSNMP session, int slot, double value)
  1589. {
  1590.         if (slot < 0 || slot >= MaxSlotsPerCrate)
  1591.                 return 0.0;
  1592.  
  1593.         return snmpSetDouble(session, &moduleRampSpeedVoltage[slot], value);
  1594. }
  1595.  
  1596. /**
  1597.  * @brief Returns the modules current ramp speed in percent.
  1598.  *
  1599.  * @note This function is for iseg HV modules only.
  1600.  *
  1601.  * iseg modules have one common ramp speed for all channels.
  1602.  * This item is only valid for modules with constant current regulation.
  1603.  * @param session The handle returned by snmpOpen()
  1604.  * @param slot The modules slot position in the crate (0...9)
  1605.  * @return The modules current ramp speed in percent
  1606.  */
  1607. double getModuleRampSpeedCurrent(HSNMP session, int slot)
  1608. {
  1609.         if (slot < 0 || slot >= MaxSlotsPerCrate)
  1610.                 return 0.0;
  1611.  
  1612.         return snmpGetDouble(session, &moduleRampSpeedCurrent[slot]);
  1613. }
  1614.  
  1615. /**
  1616.  * @brief Sets the modules current ramp speed in percent.
  1617.  *
  1618.  * @note This function is for iseg HV modules only.
  1619.  *
  1620.  * iseg modules have one common ramp speed for all channels.
  1621.  * This item is only valid for modules with constant current regulation.
  1622.  * @param session The handle returned by snmpOpen()
  1623.  * @param slot The modules slot position in the crate (0...9)
  1624.  * @param value The new current ramp speed in percent
  1625.  * @return The new current ramp speed in percent
  1626.  */
  1627. double setModuleRampSpeedCurrent(HSNMP session, int slot, double value)
  1628. {
  1629.         if (slot < 0 || slot >= MaxSlotsPerCrate)
  1630.                 return 0.0;
  1631.  
  1632.         return snmpSetDouble(session, &moduleRampSpeedCurrent[slot], value);
  1633. }
  1634.  
  1635. /**
  1636.  * @brief Returns the value of the module status register.
  1637.  *
  1638.  * @note This function is for iseg HV modules only.
  1639.  * @param session The handle returned by snmpOpen()
  1640.  * @param slot The modules slot position in the crate (0...9)
  1641.  * @return The module status register
  1642.  */
  1643. int getModuleStatus(HSNMP session, int slot)
  1644. {
  1645.         if (slot < 0 || slot >= MaxSlotsPerCrate)
  1646.                 return 0;
  1647.  
  1648.         return snmpGetInt(session, &moduleStatus[slot]);
  1649. }
  1650.  
  1651. /**
  1652.  * @brief Returns the value of the module event status register.
  1653.  *
  1654.  * @note This function is for iseg HV modules only.
  1655.  * @param session The handle returned by snmpOpen()
  1656.  * @param slot the modules slot position in the crate (0...9)
  1657.  * @return The module event status register
  1658.  */
  1659. int getModuleEventStatus(HSNMP session, int slot)
  1660. {
  1661.         if (slot < 0 || slot >= MaxSlotsPerCrate)
  1662.                 return 0;
  1663.  
  1664.         return snmpGetInt(session, &moduleEventStatus[slot]);
  1665. }
  1666.  
  1667. /**
  1668.  * @brief Clears all modules events in a specific slot.
  1669.  *
  1670.  * To clear all events in all iseg HV modules, use setHighVoltageGroupsSwitch()
  1671.  * with the parameter clearEvents(10).
  1672.  * @param session The handle returned by snmpOpen()
  1673.  * @param slot The modules slot position in the crate (0...9)
  1674.  * @return
  1675.  */
  1676. int setModuleDoClear(HSNMP session, int slot)
  1677. {
  1678.         if (slot < 0 || slot >= MaxSlotsPerCrate)
  1679.                 return 0;
  1680.  
  1681.         return snmpSetInt(session, &moduleDoClear[slot], 1);
  1682. }
  1683.  
  1684. // The rest of the functions are utility functions that actually do the SNMP calls
  1685.  
  1686. static void logErrors(HSNMP session, struct snmp_pdu *response,
  1687.                                                          const SnmpObject *object, int status, const char *functionName)
  1688. {
  1689.         // FAILURE: print what went wrong!
  1690.         if (status == STAT_SUCCESS)
  1691.                 snmp_log(LOG_ERR, "%s(%s): Error in packet. Reason: %s\n",
  1692.                                 functionName, object->desc, snmp_errstring(response->errstat));
  1693.         else
  1694.                 snmp_sess_perror("snmpget", snmp_sess_session(session));
  1695. }
  1696.  
  1697. static int getIntegerVariable(struct variable_list *vars)
  1698. {
  1699.         if (vars->type == ASN_BIT_STR || vars->type == ASN_OCTET_STR) {
  1700.                 int value = 0;
  1701.                 for (size_t i = 0; i < vars->val_len && i < sizeof(int); ++i)
  1702.                         value |= (vars->val.bitstring[i] << (i * 8));
  1703.                 return value;
  1704.         } if (vars->type == ASN_OPAQUE_FLOAT)
  1705.                 return (int)*vars->val.floatVal;
  1706.         else if (vars->type == ASN_OPAQUE_DOUBLE)
  1707.                 return (int)*vars->val.doubleVal;
  1708.         else if (vars->type == ASN_INTEGER)
  1709.                 return *vars->val.integer;
  1710.         else if (vars->type == ASN_OCTET_STR)
  1711.                 return *vars->val.integer;
  1712.         else if (vars->type == ASN_IPADDRESS)
  1713.                 return *vars->val.integer;
  1714.  
  1715.         return 0;
  1716. }
  1717.  
  1718. static double getDoubleVariable(struct variable_list *vars)
  1719. {
  1720.         if (vars->type == ASN_OPAQUE_FLOAT)
  1721.                 return *vars->val.floatVal;
  1722.         else if (vars->type == ASN_OPAQUE_DOUBLE)
  1723.                 return *vars->val.doubleVal;
  1724.         else if (vars->type == ASN_INTEGER)
  1725.                 return (double)*vars->val.integer;
  1726.  
  1727.         return 0.0;
  1728. }
  1729.  
  1730. static struct snmp_pdu *prepareSetRequestPdu(void)
  1731. {
  1732.         struct snmp_pdu *pdu = snmp_pdu_create(SNMP_MSG_SET);
  1733.         pdu->community = (u_char *)strdup(m_writeCommunity);
  1734.         pdu->community_len = strlen(m_writeCommunity);
  1735.  
  1736.         return pdu;
  1737. }
  1738.  
  1739. static struct snmp_pdu *prepareGetRequestPdu()
  1740. {
  1741.         struct snmp_pdu *pdu = snmp_pdu_create(SNMP_MSG_GET);
  1742.  
  1743.         return pdu;
  1744. }
  1745.  
  1746. static int snmpGetInt(HSNMP session, const SnmpObject *object)
  1747. {
  1748.         int value = 0;
  1749.  
  1750.         struct snmp_pdu *pdu = prepareGetRequestPdu();
  1751.  
  1752.         snmp_add_null_var(pdu, object->id, object->len);   // generate request data
  1753.  
  1754.         struct snmp_pdu *response;
  1755.         int status = snmp_sess_synch_response(session, pdu, &response);
  1756.  
  1757.         if (status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR) {
  1758.                 value = getIntegerVariable(response->variables);
  1759.         } else {
  1760.                 logErrors(session, response, object, status, "snmpGetInt");
  1761.                 return 0;
  1762.         }
  1763.  
  1764.         snmp_free_pdu(response);
  1765.         return value;
  1766. }
  1767.  
  1768. static int snmpSetInt(HSNMP session, const SnmpObject *object, int value)
  1769. {
  1770.         struct snmp_pdu *pdu = prepareSetRequestPdu();
  1771.  
  1772.         if (snmp_oid_compare(object->id, object->len, ipStaticAddress.id, ipStaticAddress.len) == 0)
  1773.                 snmp_pdu_add_variable(pdu, object->id, object->len, ASN_IPADDRESS, (u_char *)&value, sizeof(value));
  1774.         else
  1775.                 snmp_pdu_add_variable(pdu, object->id, object->len, ASN_INTEGER, (u_char *)&value, sizeof(value));
  1776.  
  1777.         int result = value;
  1778.         struct snmp_pdu *response;
  1779.         int status = snmp_sess_synch_response(session, pdu, &response);
  1780.  
  1781.         if (status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR) {
  1782.                 result = getIntegerVariable(response->variables);
  1783.         } else {
  1784.                 logErrors(session, response, object, status, "snmpSetInt");
  1785.                 return 0;
  1786.         }
  1787.  
  1788.         snmp_free_pdu(response);
  1789.         return result;
  1790. }
  1791.  
  1792. static double snmpGetDouble(HSNMP session, const SnmpObject *object)
  1793. {
  1794.         double value = 0.0;
  1795.  
  1796.         struct snmp_pdu *pdu = prepareGetRequestPdu();
  1797.  
  1798.         snmp_add_null_var(pdu, object->id, object->len);   // generate request data
  1799.  
  1800.         struct snmp_pdu *response;
  1801.         int status = snmp_sess_synch_response(session, pdu, &response);
  1802.  
  1803.         if (status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR) {
  1804.                 value = getDoubleVariable(response->variables);
  1805.         } else {
  1806.                 logErrors(session, response, object, status, "snmpGetDouble");
  1807.                 return 0;
  1808.         }
  1809.  
  1810.         snmp_free_pdu(response);
  1811.         return value;
  1812. }
  1813.  
  1814. static double snmpSetDouble(HSNMP session, const SnmpObject *object, double value)
  1815. {
  1816.         struct snmp_pdu *pdu = prepareSetRequestPdu();
  1817.  
  1818.         float v = (float)value;
  1819.         snmp_pdu_add_variable(pdu, object->id, object->len, ASN_OPAQUE_FLOAT, (u_char *)&v, sizeof(v));
  1820.  
  1821.         double result = v;
  1822.  
  1823.         struct snmp_pdu *response;
  1824.         int status = snmp_sess_synch_response(session, pdu, &response);
  1825.  
  1826.         if (status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR) {
  1827.                 result = getDoubleVariable(response->variables);
  1828.         } else {
  1829.                 logErrors(session, response, object, status, "snmpSetDouble");
  1830.                 return 0;
  1831.         }
  1832.  
  1833.         snmp_free_pdu(response);
  1834.         return result;
  1835. }
  1836.  
  1837. static char *snmpGetString(HSNMP session, const SnmpObject *object)
  1838. {
  1839.         struct snmp_pdu *pdu = prepareGetRequestPdu();
  1840.  
  1841.         snmp_add_null_var(pdu, object->id, object->len);   // generate request data
  1842.  
  1843.         struct snmp_pdu *response;
  1844.         int status = snmp_sess_synch_response(session, pdu, &response);
  1845.  
  1846.         memset(snmpStringBuffer, 0, sizeof(snmpStringBuffer));
  1847.  
  1848.         if (status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR) {
  1849.                 struct variable_list *vars = response->variables;
  1850.                 if (vars->type == ASN_OCTET_STR) {
  1851.                         size_t len = sizeof(snmpStringBuffer) - 1;
  1852.                         if (len > vars->val_len)
  1853.                                 len = vars->val_len;
  1854.  
  1855.                         memcpy(snmpStringBuffer, vars->val.string, len);
  1856.                         snmpStringBuffer[len] = 0;
  1857.                 }
  1858.         } else {
  1859.                 logErrors(session, response, object, status, "snmpGetString");
  1860.                 return 0;
  1861.         }
  1862.  
  1863.         snmp_free_pdu(response);
  1864.         return snmpStringBuffer;
  1865. }
  1866.  
  1867. static SnmpIntegerBuffer *snmpGetMultipleInteger(HSNMP session, const SnmpObject *objects, int size)
  1868. {
  1869.         struct snmp_pdu *pdu = prepareGetRequestPdu();
  1870.  
  1871.         if (size > MaxChannelsPerSlot)
  1872.                 size = MaxChannelsPerSlot;
  1873.  
  1874.         memset(&snmpIntegerBuffer, 0, sizeof(snmpIntegerBuffer));
  1875.  
  1876.         for (int i = 0; i < size; ++i)
  1877.                 snmp_add_null_var(pdu, objects[i].id, objects[i].len);   // generate request data
  1878.  
  1879.         struct snmp_pdu *response;
  1880.         int status = snmp_sess_synch_response(session, pdu, &response);
  1881.  
  1882.         if (status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR) {
  1883.                 struct variable_list *vars;
  1884.                 for (vars = response->variables; vars; vars = vars->next_variable)
  1885.                         snmpIntegerBuffer.value[snmpIntegerBuffer.size++] = getIntegerVariable(vars);
  1886.         } else {
  1887.                 logErrors(session, response, &objects[0], status, "snmpGetMultipleInteger");
  1888.                 return &snmpIntegerBuffer;
  1889.         }
  1890.  
  1891.         snmp_free_pdu(response);
  1892.         return &snmpIntegerBuffer;
  1893. }
  1894.  
  1895. static SnmpIntegerBuffer *snmpSetMultipleInteger(HSNMP session, const SnmpObject *objects, SnmpIntegerBuffer *values)
  1896. {
  1897.         struct snmp_pdu *pdu = prepareSetRequestPdu();
  1898.  
  1899.         int size = values->size;
  1900.         if (size > MaxChannelsPerSlot)
  1901.                 size = MaxChannelsPerSlot;
  1902.  
  1903.         for (int i = 0; i < size; ++i) {
  1904.                 int v = values->value[i];
  1905.                 snmp_pdu_add_variable(pdu, objects[i].id, objects[i].len, ASN_INTEGER, (u_char *)&v, sizeof(v));
  1906.         }
  1907.  
  1908.         memset(&snmpIntegerBuffer, 0, sizeof(snmpIntegerBuffer));
  1909.  
  1910.         struct snmp_pdu *response;
  1911.         int status = snmp_sess_synch_response(session, pdu, &response);
  1912.  
  1913.         if (status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR) {
  1914.                 struct variable_list *vars;
  1915.                 for (vars = response->variables; vars; vars = vars->next_variable)
  1916.                         snmpIntegerBuffer.value[snmpIntegerBuffer.size++] = getIntegerVariable(vars);
  1917.         } else {
  1918.                 logErrors(session, response, &objects[0], status, "snmpSetMultipleInteger");
  1919.                 return &snmpIntegerBuffer;
  1920.         }
  1921.  
  1922.         snmp_free_pdu(response);
  1923.         return &snmpIntegerBuffer;
  1924. }
  1925.  
  1926. static SnmpDoubleBuffer *snmpGetMultipleDouble(HSNMP session, const SnmpObject *objects, int size)
  1927. {
  1928.         struct snmp_pdu *pdu = prepareGetRequestPdu();
  1929.  
  1930.         if (size > MaxChannelsPerSlot)
  1931.                 size = MaxChannelsPerSlot;
  1932.  
  1933.         memset(&snmpDoubleBuffer, 0, sizeof(snmpDoubleBuffer));
  1934.  
  1935.         for (int i = 0; i < size; ++i)
  1936.                 snmp_add_null_var(pdu, objects[i].id, objects[i].len);   // generate request data
  1937.  
  1938.         struct snmp_pdu *response;
  1939.         int status = snmp_sess_synch_response(session, pdu, &response);
  1940.  
  1941.         if (status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR) {
  1942.                 struct variable_list *vars;
  1943.                 for (vars = response->variables; vars; vars = vars->next_variable)
  1944.                         snmpDoubleBuffer.value[snmpDoubleBuffer.size++] = getDoubleVariable(vars);
  1945.         } else {
  1946.                 logErrors(session, response, &objects[0], status, "snmpGetMultipleDouble");
  1947.                 return &snmpDoubleBuffer;
  1948.         }
  1949.  
  1950.         snmp_free_pdu(response);
  1951.  
  1952.         return &snmpDoubleBuffer;
  1953. }
  1954.  
  1955. static SnmpDoubleBuffer *snmpSetMultipleDouble(HSNMP session, const SnmpObject *objects, SnmpDoubleBuffer *values)
  1956. {
  1957.         struct snmp_pdu *pdu = prepareSetRequestPdu();
  1958.  
  1959.         int size = values->size;
  1960.         if (size > MaxChannelsPerSlot)
  1961.                 size = MaxChannelsPerSlot;
  1962.  
  1963.         for (int i = 0; i < size; ++i) {
  1964.                 float v = (float)values->value[i];
  1965.                 snmp_pdu_add_variable(pdu, objects[i].id, objects[i].len, ASN_OPAQUE_FLOAT, (u_char *)&v, sizeof(v));
  1966.         }
  1967.  
  1968.         memset(&snmpDoubleBuffer, 0, sizeof(snmpDoubleBuffer));
  1969.  
  1970.         struct snmp_pdu *response;
  1971.         int status = snmp_sess_synch_response(session, pdu, &response);
  1972.  
  1973.         if (status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR) {
  1974.                 struct variable_list *vars;
  1975.                 for (vars = response->variables; vars; vars = vars->next_variable)
  1976.                         snmpDoubleBuffer.value[snmpDoubleBuffer.size++] = getDoubleVariable(vars);
  1977.         } else {
  1978.                 logErrors(session, response, &objects[0], status, "snmpSetMultipleDouble");
  1979.                 return &snmpDoubleBuffer;
  1980.         }
  1981.  
  1982.         snmp_free_pdu(response);
  1983.         return &snmpDoubleBuffer;
  1984. }
  1985.  
  1986. /**
  1987.  * @brief Returns an array with the outputStatus for a consecutive range of channels.
  1988.  *
  1989.  * @note This function is deprecated. Use getMultipleOutputStatuses() instead.
  1990.  * @param session The handle returned by snmpOpen()
  1991.  * @param start The first channel (in the range of 0 to MaxArraySize).
  1992.  * 0 = slot 0, channel 0; 100 = slot 1, channel 0.
  1993.  * @param size The number of requested channels.
  1994.  * @return A pointer to SnmpIntegerBuffer with the requested information.
  1995.  * @note This pointer is only valid until the next call of getMultiple...
  1996.  * or setMultiple... function.
  1997.  */
  1998. SnmpIntegerBuffer *getMultipleChannelStatuses(HSNMP session, int start, int size)
  1999. {
  2000.         return getMultipleOutputStatuses(session, start, size);
  2001. }
  2002.  
  2003. /**
  2004.  * @brief Returns an array with the outputStatus for a consecutive range of channels.
  2005.  * @since 1.1
  2006.  * @param session The handle returned by snmpOpen()
  2007.  * @param start The first channel (in the range of 0 to MaxArraySize).
  2008.  * 0 = slot 0, channel 0; 100 = slot 1, channel 0.
  2009.  * @param size The number of requested channels.
  2010.  * @return A pointer to SnmpIntegerBuffer with the requested information.
  2011.  * @note This pointer is only valid until the next call of getMultiple...
  2012.  * or setMultiple... function.
  2013.  */
  2014. SnmpIntegerBuffer *getMultipleOutputStatuses(HSNMP session, int start, int size)
  2015. {
  2016.         if (start < 0 || size < 0 || start + size > MaxChannelsPerCrate) {
  2017.                 memset(&snmpIntegerBuffer, 0, sizeof(snmpIntegerBuffer));
  2018.                 return &snmpIntegerBuffer;
  2019.         }
  2020.  
  2021.         return snmpGetMultipleInteger(session, &outputStatus[start], size);
  2022. }
  2023.  
  2024. /**
  2025.  * @brief Returns an array with the outputSwitches for a consecutive range of channels.
  2026.  * @param session The handle returned by snmpOpen()
  2027.  * @param start The first channel (in the range of 0 to MaxArraySize).
  2028.  * 0 = slot 0, channel 0; 100 = slot 1, channel 0.
  2029.  * @param size The number of requested channels.
  2030.  * @return A pointer to SnmpIntegerBuffer with the requested information.
  2031.  * @note This pointer is only valid until the next call of getMultiple...
  2032.  * or setMultiple... function.
  2033.  */
  2034. SnmpIntegerBuffer *getMultipleOutputSwitches(HSNMP session, int start, int size)
  2035. {
  2036.         if (start < 0 || size < 0 || start + size > MaxChannelsPerCrate) {
  2037.                 memset(&snmpIntegerBuffer, 0, sizeof(snmpIntegerBuffer));
  2038.                 return &snmpIntegerBuffer;
  2039.         }
  2040.  
  2041.         return snmpGetMultipleInteger(session, &outputSwitch[start], size);
  2042. }
  2043.  
  2044. /**
  2045.  * @brief Sets the outputSwitch for a consecutive range of channels.
  2046.  * @param session The handle returned by snmpOpen()
  2047.  * @param start The first channel (in the range of 0 to MaxArraySize).
  2048.  * 0 = slot 0, channel 0; 100 = slot 1, channel 0.
  2049.  * @param values A pointer to SnmpIntegerBuffer with the list of outputSwitches.
  2050.  * @return
  2051.  */
  2052. SnmpIntegerBuffer *setMultipleOutputSwitches(HSNMP session, int start, SnmpIntegerBuffer *values)
  2053. {
  2054.         if (start < 0 || values->size < 0 || start + values->size > MaxChannelsPerCrate) {
  2055.                 memset(&snmpIntegerBuffer, 0, sizeof(snmpIntegerBuffer));
  2056.                 return &snmpIntegerBuffer;
  2057.         }
  2058.  
  2059.         return snmpSetMultipleInteger(session, &outputSwitch[start], values);
  2060. }
  2061.  
  2062. /**
  2063.  * @brief Returns the actual outputVoltage for a consecutive range of channels.
  2064.  * @param session The handle returned by snmpOpen()
  2065.  * @param start The first channel (in the range of 0 to MaxArraySize).
  2066.  * 0 = slot 0, channel 0; 100 = slot 1, channel 0.
  2067.  * @param size The number of requested channels.
  2068.  * @return A pointer to SnmpDoubleBuffer with the requested information.
  2069.  * @note This pointer is only valid until the next call of getMultiple...
  2070.  * or setMultiple... function.
  2071.  */
  2072. SnmpDoubleBuffer *getMultipleOutputVoltages(HSNMP session, int start, int size)
  2073. {
  2074.         if (start < 0 || size < 0 || start + size > MaxChannelsPerCrate) {
  2075.                 memset(&snmpDoubleBuffer, 0, sizeof(snmpDoubleBuffer));
  2076.                 return &snmpDoubleBuffer;
  2077.         }
  2078.  
  2079.         return snmpGetMultipleDouble(session, &outputVoltage[start], size);
  2080. }
  2081.  
  2082. /**
  2083.  * @brief Sets the demanded outputVoltage for a consecutive range of channels.
  2084.  * @param session The handle returned by snmpOpen()
  2085.  * @param start The first channel (in the range of 0 to MaxArraySize).
  2086.  * 0 = slot 0, channel 0; 100 = slot 1, channel 0.
  2087.  * @param values A pointer to SnmpDoubleBuffer with the list of new outputVoltages
  2088.  * @return
  2089.  */
  2090. SnmpDoubleBuffer *setMultipleOutputVoltages(HSNMP session, int start, SnmpDoubleBuffer *values)
  2091. {
  2092.         if (start < 0 || values->size < 0 || start + values->size > MaxChannelsPerCrate) {
  2093.                 memset(&snmpDoubleBuffer, 0, sizeof(snmpDoubleBuffer));
  2094.                 return &snmpDoubleBuffer;
  2095.         }
  2096.  
  2097.         return snmpSetMultipleDouble(session, &outputVoltage[start], values);
  2098. }
  2099.  
  2100. /**
  2101.  * @brief Returns the measured terminal voltages for a consecutive range of channels.
  2102.  * @param session The handle returned by snmpOpen()
  2103.  * @param start The first channel (in the range of 0 to MaxArraySize).
  2104.  * 0 = slot 0, channel 0; 100 = slot 1, channel 0.
  2105.  * @param size The number of requested channels.
  2106.  * @return A pointer to SnmpDoubleBuffer with the requested information.
  2107.  * @note This pointer is only valid until the next call of getMultiple...
  2108.  * or setMultiple... function.
  2109.  */
  2110. SnmpDoubleBuffer *getMultipleMeasurementTerminalVoltages(HSNMP session, int start, int size)
  2111. {
  2112.         return getMultipleOutputMeasurementTerminalVoltages(session, start, size);
  2113. }
  2114.  
  2115. /**
  2116.  * @brief Returns an array with the measured terminal voltages for a consecutive range of channels.
  2117.  * @since 1.1
  2118.  * @param session The handle returned by snmpOpen()
  2119.  * @param start The first channel (in the range of 0 to MaxArraySize).
  2120.  * 0 = slot 0, channel 0; 100 = slot 1, channel 0.
  2121.  * @param size The number of requested channels.
  2122.  * @return A pointer to SnmpDoubleBuffer with the requested information.
  2123.  * @note This pointer is only valid until the next call of getMultiple...
  2124.  * or setMultiple... function.
  2125.  */
  2126. SnmpDoubleBuffer *getMultipleOutputMeasurementTerminalVoltages(HSNMP session, int start, int size)
  2127. {
  2128.         if (start < 0 || size < 0 || start + size > MaxChannelsPerCrate) {
  2129.                 memset(&snmpDoubleBuffer, 0, sizeof(snmpDoubleBuffer));
  2130.                 return &snmpDoubleBuffer;
  2131.         }
  2132.  
  2133.         return snmpGetMultipleDouble(session, &outputMeasurementTerminalVoltage[start], size);
  2134. }
  2135.  
  2136. /**
  2137.  * @brief getMultipleOutputConfigMaxTerminalVoltages
  2138.  * @param session The handle returned by snmpOpen()
  2139.  * @param start The first channel (in the range of 0 to MaxArraySize).
  2140.  * 0 = slot 0, channel 0; 100 = slot 1, channel 0.
  2141.  * @param size The number of requested channels.
  2142.  * @return
  2143.  */
  2144. SnmpDoubleBuffer *getMultipleOutputConfigMaxTerminalVoltages(HSNMP session, int start, int size)
  2145. {
  2146.         if (start < 0 || size < 0 || start + size > MaxChannelsPerCrate) {
  2147.                 memset(&snmpDoubleBuffer, 0, sizeof(snmpDoubleBuffer));
  2148.                 return &snmpDoubleBuffer;
  2149.         }
  2150.  
  2151.         return snmpGetMultipleDouble(session, &outputConfigMaxTerminalVoltage[start], size);
  2152. }
  2153.  
  2154. /**
  2155.  * @brief Returns an array the demanded output currents for a consecutive range of channels.
  2156.  * @param session The handle returned by snmpOpen()
  2157.  * @param start The first channel (in the range of 0 to MaxArraySize).
  2158.  * 0 = slot 0, channel 0; 100 = slot 1, channel 0.
  2159.  * @param size The number of requested channels.
  2160.  * @return
  2161.  */
  2162. SnmpDoubleBuffer *getMultipleOutputCurrents(HSNMP session, int start, int size)
  2163. {
  2164.         if (start < 0 || size < 0 || start + size > MaxChannelsPerCrate) {
  2165.                 memset(&snmpDoubleBuffer, 0, sizeof(snmpDoubleBuffer));
  2166.                 return &snmpDoubleBuffer;
  2167.         }
  2168.  
  2169.         return snmpGetMultipleDouble(session, &outputCurrent[start], size);
  2170. }
  2171.  
  2172. /**
  2173.  * @brief Sets the demanded output current for a consecutive range of channels.
  2174.  * @param session The handle returned by snmpOpen()
  2175.  * @param start The first channel (in the range of 0 to MaxArraySize).
  2176.  * 0 = slot 0, channel 0; 100 = slot 1, channel 0.
  2177.  * @param values A pointer to SnmpDoubleBuffer with a list of new output currents
  2178.  * @return
  2179.  */
  2180. SnmpDoubleBuffer *setMultipleOutputCurrents(HSNMP session, int start, SnmpDoubleBuffer *values)
  2181. {
  2182.         if (start < 0 || values->size < 0 || start + values->size > MaxChannelsPerCrate) {
  2183.                 memset(&snmpDoubleBuffer, 0, sizeof(snmpDoubleBuffer));
  2184.                 return &snmpDoubleBuffer;
  2185.         }
  2186.  
  2187.         return snmpSetMultipleDouble(session, &outputCurrent[start], values);
  2188. }
  2189.  
  2190. /**
  2191.  * @brief Returns an array with the measured currents for a consecutive range of channels.
  2192.  *
  2193.  * @note This function is deprecated. Use getMultipleOutputMeasurementCurrents() instead.
  2194.  * @param session The handle returned by snmpOpen()
  2195.  * @param start The first channel (in the range of 0 to MaxArraySize).
  2196.  * 0 = slot 0, channel 0; 100 = slot 1, channel 0.
  2197.  * @param size The number of requested channels.
  2198.  * @return A pointer to SnmpDoubleBuffer with the requested information.
  2199.  * @note This pointer is only valid until the next call of getMultiple...
  2200.  * or setMultiple... function.
  2201.  */
  2202. SnmpDoubleBuffer *getMultipleMeasurementCurrents(HSNMP session, int start, int size)
  2203. {
  2204.         return getMultipleOutputMeasurementCurrents(session, start, size);
  2205. }
  2206.  
  2207. /**
  2208.  * @brief Returns an array with the measured currents for a consecutive range of channels.
  2209.  * @since 1.1
  2210.  * @param session The handle returned by snmpOpen()
  2211.  * @param start The first channel (in the range of 0 to MaxArraySize).
  2212.  * 0 = slot 0, channel 0; 100 = slot 1, channel 0.
  2213.  * @param size The number of requested channels.
  2214.  * @return A pointer to SnmpDoubleBuffer with the requested information.
  2215.  * @note This pointer is only valid until the next call of getMultiple...
  2216.  * or setMultiple... function.
  2217.  */
  2218. SnmpDoubleBuffer *getMultipleOutputMeasurementCurrents(HSNMP session, int start, int size)
  2219. {
  2220.         if (start < 0 || size < 0 || start + size > MaxChannelsPerCrate) {
  2221.                 memset(&snmpDoubleBuffer, 0, sizeof(snmpDoubleBuffer));
  2222.                 return &snmpDoubleBuffer;
  2223.         }
  2224.  
  2225.         return snmpGetMultipleDouble(session, &outputMeasurementCurrent[start], size);
  2226. }
  2227.  
  2228. /**
  2229.  * @brief Returns an array with the outputConfigMaxCurrent for a consecutive range of channels.
  2230.  * @param session The handle returned by snmpOpen()
  2231.  * @param start The first channel (in the range of 0 to MaxArraySize).
  2232.  * 0 = slot 0, channel 0; 100 = slot 1, channel 0.
  2233.  * @param size The number of requested channels.
  2234.  * @return
  2235.  */
  2236. SnmpDoubleBuffer *getMultipleOutputConfigMaxCurrents(HSNMP session, int start, int size)
  2237. {
  2238.         if (start < 0 || size < 0 || start + size > MaxChannelsPerCrate) {
  2239.                 memset(&snmpDoubleBuffer, 0, sizeof(snmpDoubleBuffer));
  2240.                 return &snmpDoubleBuffer;
  2241.         }
  2242.  
  2243.         return snmpGetMultipleDouble(session, &outputConfigMaxCurrent[start], size);
  2244. }
  2245.  
  2246. /**
  2247.  * @brief Returns an array with the outputTripTimeMaxCurrent for a consecutive range of channels.
  2248.  * @param session The handle returned by snmpOpen()
  2249.  * @param start The first channel (in the range of 0 to MaxArraySize).
  2250.  * 0 = slot 0, channel 0; 100 = slot 1, channel 0.
  2251.  * @param size The number of requested channels.
  2252.  * @return
  2253.  */
  2254. SnmpIntegerBuffer *getMultipleOutputTripTimeMaxCurrents(HSNMP session, int start, int size)
  2255. {
  2256.         if (start < 0 || size < 0 || start + size > MaxChannelsPerCrate) {
  2257.                 memset(&snmpIntegerBuffer, 0, sizeof(snmpIntegerBuffer));
  2258.                 return &snmpIntegerBuffer;
  2259.         }
  2260.  
  2261.         return snmpGetMultipleInteger(session, &outputTripTimeMaxCurrent[start], size);
  2262. }
  2263.  
  2264. /**
  2265.  * @brief Sets the outputTripTimeMaxCurrent for a consecutive ranges of channels.
  2266.  * @param session The handle returned by snmpOpen()
  2267.  * @param start The first channel (in the range of 0 to MaxArraySize).
  2268.  * 0 = slot 0, channel 0; 100 = slot 1, channel 0.
  2269.  * @param values
  2270.  * @return
  2271.  */
  2272. SnmpIntegerBuffer *setMultipleOutputTripTimeMaxCurrents(HSNMP session, int start, SnmpIntegerBuffer *values)
  2273. {
  2274.         if (start < 0 || values->size < 0 || start + values->size > MaxChannelsPerCrate) {
  2275.                 memset(&snmpIntegerBuffer, 0, sizeof(snmpIntegerBuffer));
  2276.                 return &snmpIntegerBuffer;
  2277.         }
  2278.  
  2279.         return snmpSetMultipleInteger(session, &outputTripTimeMaxCurrent[start], values);
  2280. }
  2281.  
  2282. /**
  2283.  * @brief Returns an array with the outputSupervisionBehavior for a consecutive range of channels.
  2284.  * @param session The handle returned by snmpOpen()
  2285.  * @param start The first channel (in the range of 0 to MaxArraySize).
  2286.  * 0 = slot 0, channel 0; 100 = slot 1, channel 0.
  2287.  * @param size The number of requested channels.
  2288.  * @return
  2289.  */
  2290. SnmpIntegerBuffer *getMultipleOutputSupervisionBehaviors(HSNMP session, int start, int size)
  2291. {
  2292.         if (start < 0 || size < 0 || start + size > MaxChannelsPerCrate) {
  2293.                 memset(&snmpIntegerBuffer, 0, sizeof(snmpIntegerBuffer));
  2294.                 return &snmpIntegerBuffer;
  2295.         }
  2296.  
  2297.         return snmpGetMultipleInteger(session, &outputSupervisionBehavior[start], size);
  2298. }
  2299.  
  2300. /**
  2301.  * @brief Sets the outputSupervisionBehavior for a consecutive range of channels.
  2302.  * @param session The handle returned by snmpOpen()
  2303.  * @param start The first channel (in the range of 0 to MaxArraySize).
  2304.  * 0 = slot 0, channel 0; 100 = slot 1, channel 0.
  2305.  * @param values The new outputSupervisionBehavior for the all channels starting with start.
  2306.  * @return
  2307.  */
  2308. SnmpIntegerBuffer *setMultipleOutputSupervisionBehaviors(HSNMP session, int start, SnmpIntegerBuffer *values)
  2309. {
  2310.         if (start < 0 || values->size < 0 || start + values->size > MaxChannelsPerCrate) {
  2311.                 memset(&snmpIntegerBuffer, 0, sizeof(snmpIntegerBuffer));
  2312.                 return &snmpIntegerBuffer;
  2313.         }
  2314.  
  2315.         return snmpSetMultipleInteger(session, &outputSupervisionBehavior[start], values);
  2316. }
  2317.