Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for APC Galaxy 5500 UPS #2239

Closed

Conversation

mateusz-jastrzebski
Copy link

I am working with (APC) MGE Galaxy 5500 UPS and the default way of grabbing ups.status is different from other APC drivers sadly (talking about drivers/apc-mib.c). OID that works: 1.3.6.1.4.1.318.1.1.1.11.1.1

Easiest way I found out to make my ups.status work (as far as OL OB go and also not block other APC/snmp-ups devices's functionality) was to make a custom snmp-ups driver with special treatment; If I have used custom functions for it, I'd still need to modify macro (and compile whole project) that allows custom lookup functions to work but I might be wrong
The new driver is a modified clone of the apc-mib.c
It is in usable state; should get the job done for turning off devices.

Feel free to leave some comments - I am still learning coding.

@jimklimov
Copy link
Member

Hello, thanks for this! Just in case - we have many apc-something subdrivers; did you check that none of them fits your device?

If not, and the problem is about just a few mapping-table data points, it may work to just add them into an existing subdriver (not sure OTOH if the first or last initially probed working match would be used in fact). They are flexible enough to support vendor variant MIBs - so you can see a few duplicate names with different OIDs already.

@mateusz-jastrzebski
Copy link
Author

I tried grepping for my status OID in other drivers/subdrivers lookup files with no result.
Well still I'll try to check if other APC subdrivers work but in the meanwhile I'll continue working on patching my code for PR.
See You in 2024!

@jimklimov jimklimov added APC SNMP needs-work PR discussion concluded that some work is needed from the contributor labels Jan 2, 2024
@jimklimov
Copy link
Member

From CI:

In file included from snmp-ups.c:45:
./apcgalaxy5500-mib.h:10:33: error: no newline at end of file [-Werror,-Wnewline-eof]
#endif /* APCGALAXY5500_MIB_H */
                                ^
snmp-ups.c:3512:9: error: mixing declarations and code is incompatible with standards before C99 [-Werror,-Wdeclaration-after-statement]
                        char pwr_status = buf[1];
                             ^
2 errors generated.
make[1]: *** [Makefile:2389: snmp_ups-snmp-ups.o] Error 1
In file included from apcgalaxy5500-mib.c:30:
./apcgalaxy5500-mib.h:10:33: error: no newline at end of file [-Werror,-Wnewline-eof]
#endif /* APCGALAXY5500_MIB_H */
                                ^
apcgalaxy5500-mib.c:303:3: error: no newline at end of file [-Werror,-Wnewline-eof]
*/
  ^
2 errors generated.

mateusz-jastrzebski added a commit to mateusz-jastrzebski/nut-with-galaxy5500 that referenced this pull request Jan 10, 2024
su_status_set(su_info_p, value);
upsdebugx(2, "=> value: %ld", value);
status = nut_snmp_get_str(su_info_p->OID, buf, sizeof(buf), su_info_p->oid2info);
char pwr_status;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks error-prone: strtol() deals with a (nul-terminated) string, but your copy of the first character from buf is not necessarily followed in RAM by a zero byte. Any random garbage can pop up here...

Trying to make sense of that MIB/OID with http://oidref.com/1.3.6.1.4.1.318.1.1.1.11.1.1.0 I see that it is a child of http://oidref.com/1.3.6.1.4.1.318.1.1.1.11.1.1 but otherwise got no clue of its own value. That parent however is a string representing 64 bit-flags (or UNKNOWN which you don't check for), and the second byte (your buf[1]?) would be the "On Battery" flag. There is a separate flag for "On Line" as well as bypass, self-test, and a united "Low Battery / On Battery" flag, so it may be prudent to check several values for this reading.

Also wondering if all this complex logic should be here or can be better served by "lookup functions" in the *-mib.c file (the later, generally NULL, fields of lookup tables like APCC_G5500_pwr_info[])?.. See e.g. drivers/eaton-pdu-marlin-mib.c for some practical examples.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll try to learn about strtol() and its functioning, thank you.

As far as I know, those lookup functions only work when (to put it simply)
the macro `WITH_SNMP_LKP_FUN' is set to 1

drivers/snmp-ups.h 137:142

# if (defined WITH_DMFMIB) && (WITH_DMFMIB != 0)
#  define WITH_SNMP_LKP_FUN 0
# else
#  define WITH_SNMP_LKP_FUN 1
# endif
#endif

Does it mean that in best scenario I will still have to use a self-built version of NUT for this particular UPS model?
Or I might be missing something

Yes, I acknowledge the fact that ups.status is more than OL or OB, things would get easier with lookup functions, I understand

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And umm I have put child OID (not parent) there because that's what actually works when using something like snmpget
The parent OID does not work

snmpget -v1 -c public 'redacted_ip' 1.3.6.1.4.1.318.1.1.1.11.1.1

Error in packet
Reason: (noSuchName) There is no such variable name in this MIB.
Failed object: iso.3.6.1.4.1.318.1.1.1.11.1.1

Comment on lines +3509 to +3528
if(!(strcasecmp(su_info_p->OID, ".1.3.6.1.4.1.318.1.1.1.11.1.1.0")))
{
su_status_set(su_info_p, value);
upsdebugx(2, "=> value: %ld", value);
status = nut_snmp_get_str(su_info_p->OID, buf, sizeof(buf), su_info_p->oid2info);
char pwr_status;
pwr_status = buf[1];
su_status_set(su_info_p, strtol(&pwr_status, NULL, 10));
if (status == TRUE)
upsdebugx(2, "=> value: %c", pwr_status);
else
upsdebugx(2, "=> Failed");
}
else
upsdebugx(2, "=> Failed");

free_info(tmp_info_p);
{
status = nut_snmp_get_int(su_info_p->OID, &value);
su_status_set(su_info_p, value);
if (status == TRUE)
upsdebugx(2, "=> value: %ld", value);
else
upsdebugx(2, "=> Failed");
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did this block change so drastically - a lot more than indenting generally, losing the debug log and now calling su_status_set() regardless of a successful status to fetch the value, for example? Did a local experiment seep out here?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright I agree I did mess this up

{ 7, "smallMomentarySpike", NULL, NULL },
{ 8, "largeMomentarySpike", NULL, NULL },
{ 9, "selfTest", NULL, NULL },
{ 10, "rateOfVoltageChange", NULL, NULL }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here and above, lookup tables must end with a { 0, NULL, NULL, NULL } entry to stop iterations.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't think of that, this code snippet is copied from drivers/apc-mib.c

Comment on lines +194 to +201
{ "ups.status", ST_FLAG_STRING, SU_INFOSIZE, APCC_G5500_OID_POWER_STATUS, "OFF",
SU_FLAG_OK | SU_STATUS_PWR, APCC_G5500_pwr_info },
{ "ups.status", ST_FLAG_STRING, SU_INFOSIZE, APCC_G5500_OID_BATT_STATUS, "",
SU_FLAG_OK | SU_STATUS_BATT, APCC_G5500_batt_info },
{ "ups.status", ST_FLAG_STRING, SU_INFOSIZE, APCC_G5500_OID_CAL_RESULTS, "",
SU_FLAG_OK | SU_STATUS_CAL, APCC_G5500_cal_info },
{ "ups.status", ST_FLAG_STRING, SU_INFOSIZE, APCC_G5500_OID_NEEDREPLBATT, "",
SU_FLAG_OK | SU_STATUS_RB, APCC_G5500_battrepl_info },
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aren't these all different statuses? Check with docs/nut-names.txt for suitable strings for the first column.

Also, I think the first hit (query that gets a response from a particular device for the reading name) wins, so the later lines would be effectively ignored at run time.

@jimklimov
Copy link
Member

Did a bit of cursory review, for some things that stung my eye :)

Also, as you might have noticed by now, it is much less cumbersome to issue PRs from a dedicated git branch (avoid using your copy of master or any other branches named by upstream projects). Especially makes it easier to collaborate, e.g. when maintainer like me may push typo fixes to your unprotected branch that is a source of PR, and specifically to sync changes from the shared upstream codebase back into yours if the PR stays open for a non-trivial length of time.

@aquette
Copy link
Member

aquette commented Jan 14, 2024

Have you checked the subpart (after .318) do not match mge-mib? These Galaxy may just the rebadged MGE.

@jimklimov jimklimov marked this pull request as draft January 14, 2024 18:36
@jimklimov jimklimov marked this pull request as ready for review February 27, 2024 09:06
@jimklimov jimklimov marked this pull request as draft February 27, 2024 13:27
@jimklimov
Copy link
Member

Odd, notifications here show a commit with nuked README.adoc... why?

@mateusz-jastrzebski
Copy link
Author

Umm, I just wanted to have a clean readme for my fork, I acknowledge the fact that this PR's not going to be merged anytime soon. I have also just found out the importance of merging a non default branch from forked repo..
I think I'm going to just close this PR "for now" as I physically don't have time and patience for fixing my code.
If there will be next time, I'll make sure I do it with best manners, sorry!

@jimklimov
Copy link
Member

Ah, I see. Just was worried someone stole your account to spam, or something.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
APC needs-work PR discussion concluded that some work is needed from the contributor SNMP
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants