News:

We really need your input in this questionnaire

Main Menu

PDU SNMP Parsing

Started by twparker, March 08, 2024, 04:21:30 PM

Previous topic - Next topic

twparker

Hello all,

I have a PDU that I am trying to monitor power usage and temperature for, but the oid that I utilize for this purpose reports data in one long string string like this -

type=Master,,voltage=121.7,current=0.136,activePower=0.007,powerFactor=0.422,energy=2.893,temperature=23.3,humidity=30.7

What would be the best way to separate all of these data points into different DCIs?


Filipp Sudanov

This could be done with transformation scripts on a number of SNMP DCIs, but this is not convenient to manage, as transformation script on each of these DCis would be different. 

A cleaner approach would be to use script DCIs. In script library create a script, named e.g. getPduMetric with the following contents:

function main(oid, name) {
  transport = $node->createSNMPTransport();
  if (transport == null) return null;
  v = transport->getValue(oid);

  h = %{};
  for (a : v->split(",")) {
    b = a->split("=");
    if (b->size == 2) h[b] = b[1];
  }

  return h[name];
}

Then create a DCI on the node, origin should be Script. In the metric field we have name of the script with it's parameters:
getPduMetric(.1.3.6.1.2.1.1.1.0, activePower)

Script accepts two parameters - OID and variable name. This way you can have just one script and define everything in metric of your DCIs.

twparker

Thanks for the help, Filipp.

I tried to make a DCI with this script as the origin and I noticed that it keeps on disappearing from my Data Collection list a moment after hitting Apply and Close. Any suggestions?

Filipp Sudanov

Most probably your DCI became unsupported. If you right-click the list of DCIs, there's "show unsupported" in the context menu. Or you can switch to edit mode - there's pen icon above DCI list.

Check that DCI origin is set to script, check the name of the script. If you right-click your node and choose "execute script", you can run your script there to test if it returns some result. Script parameters, e.g. .1.3.6.1.2.1.1.1.0, activePower can be provided via parameters field.

twparker

So the error I got when I tried executing it was "Error 35 in line 10: Hash map key is not a string"

I thought I could just turn it into a string with

string(b);

However, I still get the above error.






Filipp Sudanov

is it this line?:
    if (b->size == 2) h[b] = b[1];
Try running your script via "Execute script" on your PDU node. You can add line like
    println(b);into your script, this way you'll see what exactly is contained in the variables. I'd start with checking of what comes in variable v, it could be that nothing just comes via snmp. Actually, transport->getValue() can return null if there's some problem, so after that line there should be a check for that:

    if (v == null) return null;

twparker

V returns a valid result namely the full OID value "type=Master,,voltage=121.0,current=0.000,activePower=0.000,powerFactor=1.000,energy=3.446,temperature=-1,humidity=-1

I thought the next function was stuck on the second comma because the only result I get for b is "type=Master" That led me to try this

function main(oid, name) {
  transport = $node->createSNMPTransport();
  if (transport == null) return null;
  v = transport->getValue(oid);
  z = string(v);
  x = substr(z, 13);


  h = %{};
  for (a : x->split(",")) {
    b = a->split("=");
 println(b);
    if (b->size == 2) h = b[1];
  }
    return h[name];
}


Apparently I can't change the value to a string before passing it to h.

Filipp Sudanov

Well, my bad, seems that I did not fully test the script that I've posted initially. It should be like this:

function main(oid, name) {
  transport = $node->createSNMPTransport();
  if (transport == null) return null;
  v = transport->getValue(oid);
  h = %{};
  for (a : v->split(",")) {
    b = a->split("=");
    if (b->size == 2) h[b[0]] = b[1];
  }
  return h[name];
}

The way it works - v->split(",") produces array where elements are "voltage=121.0" and so on. We loop through that array, so variable "a" has the value of each element of that array.
Now we need to split by "=" character and variable "b" becomes an array with two elements: [voltage, 121.0]. To access these elements we use index, so b[0] is "voltage" and b[1] is "121.0".
Now, h is a hashmap - sort of an array, but instead of numeric index elements are identified by string. We initialize it empty with h = %{}; And then we fill h with values with this code: h[b[0]] = b[1]; (and I now see the reason of the wrong code - forum editor is garbling the h[b[0]] part when pasting)

twparker

This works beautifully. Thanks so much, Filipp!