Newer
Older
#include "mpod.hpp"
#include <SNMP.h>
#include <WiFiUdp.h>
MPOD::MPOD() {
bool _on = false;
bool _up = false;
bool _down = false;
float _measurementSenseVoltage = 0;
float _measurementCurrent = 0;
float _voltage = 0;
float _current = 0;
float _voltageRiseRate = 0;
}
// Create an SNMP SETREQUEST message to setup MPOD
SNMP::Message* MPOD::setup() {
// Use read/write community, not read-only
SNMP::Message* message = new SNMP::Message(SNMP::Version::V2C, "guru", SNMP::Type::SetRequest);
// In SETREQUEST, use node type and set the value.
// OUTPUT SWITCH, integer type, 0 is OFF and 1 is ON.
message->add(OID::NAMES[OID::OUTPUTSWITCH], new IntegerBER(0));
// OUTPUT VOLTAGE is an opaque float embedded in an opaque node
message->add(OID::NAMES[OID::OUTPUTVOLTAGE], new OpaqueBER(new OpaqueFloatBER(10.0)));
// OUTPUT CURRENT is an opaque float embedded in an opaque node
message->add(OID::NAMES[OID::OUTPUTCURRENT], new OpaqueBER(new OpaqueFloatBER(0.001)));
// OUTPUT VOLTAGE RISE RATE is negative. Don't ask me why...
message->add(OID::NAMES[OID::OUTPUTVOLTAGERISERATE], new OpaqueBER(new OpaqueFloatBER(-1.0)));
return message;
}
// Create an SNMP GETREQUEST message
SNMP::Message* MPOD::read() {
SNMP::Message* message = new SNMP::Message(SNMP::Version::V2C, "public", SNMP::Type::GetRequest);
// In GETREQUEST, values are always of type NULL.
message->add(OID::NAMES[OID::OUTPUTSTATUS]);
message->add(OID::NAMES[OID::OUTPUTMEASUREMENTSENSEVOLTAGE]);
message->add(OID::NAMES[OID::OUTPUTMEASUREMENTCURRENT]);
return message;
}
// Create an SNMP SETREQUEST message to switch on or off the MPOD
SNMP::Message* MPOD::output(const bool on) {
SNMP::Message* message = new SNMP::Message(SNMP::Version::V2C, "guru", SNMP::Type::SetRequest);
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
// In SETREQUEST, use node type and set the value.
// OUTPUT SWITCH, integer type, 0 is OFF and 1 is ON.
message->add(OID::NAMES[OID::OUTPUTSWITCH], new IntegerBER(on ? 1 : 0));
return message;
}
// Parse incoming message
bool MPOD::message(const SNMP::Message *message) {
unsigned int found = 0;
unsigned int index = 0;
// Get the variable binding list from the message.
VarBindList *varbindlist = message->getVarBindList();
for (unsigned int index = 0; index < varbindlist->count(); ++index) {
// Each variable binding is a sequence of 2 objects:
// - First one is and ObjectIdentifierBER. It holds the OID
// - Second is the value of any type
VarBind *varbind = (*varbindlist)[index];
// There is a convenient function to get the OID as a const char*
const char *name = varbind->getName();
switch (OID::match(name)) {
case OID::OUTPUTSTATUS: {
// OUTPUTSTATUS is defined in MIB as BITS but encoded as OCTETSTRING by MPOD
OctetStringBER *status = static_cast<OctetStringBER*>(varbind->getValue());
_on = status->getBit(0);
_up = status->getBit(11);
_down = status->getBit(12);
}
found++;
break;
case OID::OUTPUTMEASUREMENTSENSEVOLTAGE:
// Use private helper function to extract float value
_measurementSenseVoltage = getFloatFromVarBind(varbind);
found++;
break;
case OID::OUTPUTMEASUREMENTCURRENT:
_measurementCurrent = getFloatFromVarBind(varbind);
found++;
break;
case OID::OUTPUTSWITCH:
// Use private helper function to extract integer value
_on = getIntegerFromVarBind(varbind);
found++;
break;
case OID::OUTPUTVOLTAGE:
_voltage = getFloatFromVarBind(varbind);
found++;
break;
case OID::OUTPUTCURRENT:
_current = getFloatFromVarBind(varbind);
found++;
break;
case OID::OUTPUTVOLTAGERISERATE:
_voltageRiseRate = getFloatFromVarBind(varbind);
found++;
break;
}
}
// Return true if nodes found, that means this is a valid response from MPOD
return found;
}
bool MPOD::isOn() const {
return _on;
}
bool MPOD::isUp() const {
return _up;
}
bool MPOD::isDown() const {
return _down;
}
float MPOD::getMeasurementSenseVoltage() const {
return _measurementSenseVoltage;
}
float MPOD::getMeasurementCurrent() const {
return _measurementCurrent;
}
float MPOD::getVoltage() const {
return _voltage;
}
float MPOD::getCurrent() const {
return _current;
}
float MPOD::getVoltageRiseRate() const {
return _voltageRiseRate;
}
// Use appropriate cast to get integer value
unsigned int MPOD::getIntegerFromVarBind(const VarBind *varbind) {
return static_cast<IntegerBER*>(varbind->getValue())->getValue();
}
// Use appropriate casts to get embedded opaque float value
float MPOD::getFloatFromVarBind(const VarBind *varbind) {
return static_cast<OpaqueFloatBER*>(static_cast<OpaqueBER*>(varbind->getValue())->getBER())->getValue();
}
String MPOD::toJSON() {
String json = "\"status\":{\n";
json += "\"is_on\":" + String(isOn()) + ",";
json += "\"is_up\":" + String(isUp()) + ",";
json += "\"is_down\":" + String(isDown()) + ",";
json += "\"sense_voltage\":" + String(getMeasurementSenseVoltage()) + ",";
json += "\"set_voltage\":" + String(getVoltage()) + ",";
json += "\"sense_current\":" + String(getMeasurementCurrent()) + ",";
json += "\"set_current\":" + String(getCurrent()) + ",";
json += "\"voltage_rise_rate\":" + String(getVoltageRiseRate());
json += "}";
return json;
}
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
WiFiUDP udp;
SNMP::Manager snmp;
MPOD mpod;
// Event handler to process SNMP messages
void onMessage(const SNMP::Message *message, const IPAddress remote, const uint16_t port) {
if (mpod.message(message)) {
Serial.println();
Serial.print("MPOD status");
Serial.print(mpod.isOn() ? " on" : " off");
if (mpod.isUp()) {
Serial.print(" up");
}
if (mpod.isDown()) {
Serial.print(" down");
}
Serial.println();
Serial.print("HV voltage ");
Serial.print(mpod.getMeasurementSenseVoltage());
Serial.print(" V (");
Serial.print(mpod.getVoltage());
Serial.print(") current ");
Serial.print(mpod.getMeasurementCurrent());
Serial.print(" A (");
Serial.print(mpod.getCurrent());
Serial.print(") rise rate ");
Serial.print(mpod.getVoltageRiseRate());
Serial.println(" V/s");
} else {
Serial.println("Received non-MPOD traffic");
}
}
void initializeSNMP() {