Skip to content
Snippets Groups Projects
Commit b1331c84 authored by Cyril Danilevski's avatar Cyril Danilevski
Browse files

Accept MPOD channel as argument

parent 3ccc752f
No related branches found
No related tags found
No related merge requests found
Pipeline #152674 passed
...@@ -18,6 +18,9 @@ Available routes are: ...@@ -18,6 +18,9 @@ Available routes are:
- `/idn`: provides information about firmware and hardware version, and uptime. - `/idn`: provides information about firmware and hardware version, and uptime.
It can be queried as a heartbeat, seeing the uptime increasing. It can be queried as a heartbeat, seeing the uptime increasing.
- `/poll?ch=1`: get status of a channel.
### Serial Interface ### Serial Interface
The serial interface is available through the micro-usb port. The serial interface is available through the micro-usb port.
......
...@@ -14,42 +14,37 @@ MPOD::MPOD() { ...@@ -14,42 +14,37 @@ MPOD::MPOD() {
} }
// Create an SNMP SETREQUEST message to setup MPOD // Create an SNMP GETREQUEST message
SNMP::Message* MPOD::setup() { SNMP::Message* MPOD::read(uint16_t channel) {
// 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); SNMP::Message* message = new SNMP::Message(SNMP::Version::V2C, "public", SNMP::Type::GetRequest);
// In GETREQUEST, values are always of type NULL. // In GETREQUEST, values are always of type NULL.
message->add(OID::NAMES[OID::OUTPUTSTATUS]); String snmp_cmd = OID::NAMES[OID::OUTPUTSTATUS];
message->add(OID::NAMES[OID::OUTPUTMEASUREMENTSENSEVOLTAGE]); snmp_cmd += channel;
message->add(OID::NAMES[OID::OUTPUTMEASUREMENTCURRENT]); message->add(snmp_cmd.c_str());
snmp_cmd = OID::NAMES[OID::OUTPUTMEASUREMENTSENSEVOLTAGE];
snmp_cmd += channel;
message->add(snmp_cmd.c_str());
snmp_cmd = OID::NAMES[OID::OUTPUTMEASUREMENTCURRENT];
snmp_cmd += channel;
message->add(snmp_cmd.c_str());
return message; return message;
} }
// Create an SNMP SETREQUEST message to switch on or off the MPOD // Create an SNMP SETREQUEST message to switch on or off the MPOD
SNMP::Message* MPOD::output(const bool on) { SNMP::Message* MPOD::output(const uint16_t channel, const bool on) {
SNMP::Message* message = new SNMP::Message(SNMP::Version::V2C, "guru", SNMP::Type::SetRequest); SNMP::Message* message = new SNMP::Message(SNMP::Version::V2C, "guru", SNMP::Type::SetRequest);
// In SETREQUEST, use node type and set the value. // In SETREQUEST, use node type and set the value.
// OUTPUT SWITCH, integer type, 0 is OFF and 1 is ON. // OUTPUT SWITCH, integer type, 0 is OFF and 1 is ON.
message->add(OID::NAMES[OID::OUTPUTSWITCH], new IntegerBER(on ? 1 : 0)); String snmp_cmd = OID::NAMES[OID::OUTPUTSWITCH];
snmp_cmd += channel;
message->add(snmp_cmd.c_str(), new IntegerBER(on ? 1 : 0));
return message; return message;
} }
// Parse incoming message // Parse incoming message
bool MPOD::message(const SNMP::Message *message) { bool MPOD::message(const SNMP::Message *message) {
unsigned int found = 0; unsigned int found = 0;
unsigned int index = 0; unsigned int index = 0;
...@@ -99,6 +94,12 @@ bool MPOD::message(const SNMP::Message *message) { ...@@ -99,6 +94,12 @@ bool MPOD::message(const SNMP::Message *message) {
found++; found++;
break; break;
} }
// Get the channel ID from the last value in the varbind name
// No validation is done here as the varbind must be legal to get
// that far.
const char* channel = strrchr(varbind->getName(), '.') + 1;
_channel = atoi(channel);
} }
// Return true if nodes found, that means this is a valid response from MPOD // Return true if nodes found, that means this is a valid response from MPOD
return found; return found;
...@@ -136,6 +137,10 @@ float MPOD::getVoltageRiseRate() const { ...@@ -136,6 +137,10 @@ float MPOD::getVoltageRiseRate() const {
return _voltageRiseRate; return _voltageRiseRate;
} }
uint16_t MPOD::getChannel() const {
return _channel;
}
// Use appropriate cast to get integer value // Use appropriate cast to get integer value
unsigned int MPOD::getIntegerFromVarBind(const VarBind *varbind) { unsigned int MPOD::getIntegerFromVarBind(const VarBind *varbind) {
return static_cast<IntegerBER*>(varbind->getValue())->getValue(); return static_cast<IntegerBER*>(varbind->getValue())->getValue();
...@@ -148,6 +153,7 @@ float MPOD::getFloatFromVarBind(const VarBind *varbind) { ...@@ -148,6 +153,7 @@ float MPOD::getFloatFromVarBind(const VarBind *varbind) {
String MPOD::toJSON() { String MPOD::toJSON() {
String json = "\"status\":{\n"; String json = "\"status\":{\n";
json += "\"channel\":" + String(getChannel()) + ",";
json += "\"is_on\":" + String(isOn()) + ","; json += "\"is_on\":" + String(isOn()) + ",";
json += "\"is_up\":" + String(isUp()) + ","; json += "\"is_up\":" + String(isUp()) + ",";
json += "\"is_down\":" + String(isDown()) + ","; json += "\"is_down\":" + String(isDown()) + ",";
...@@ -170,7 +176,8 @@ MPOD mpod; ...@@ -170,7 +176,8 @@ MPOD mpod;
void onMessage(const SNMP::Message *message, const IPAddress remote, const uint16_t port) { void onMessage(const SNMP::Message *message, const IPAddress remote, const uint16_t port) {
if (mpod.message(message)) { if (mpod.message(message)) {
Serial.println(); Serial.println();
Serial.print("MPOD status"); Serial.print("MPOD status: ");
Serial.print(mpod.getChannel());
Serial.print(mpod.isOn() ? " on" : " off"); Serial.print(mpod.isOn() ? " on" : " off");
if (mpod.isUp()) { if (mpod.isUp()) {
Serial.print(" up"); Serial.print(" up");
......
...@@ -27,20 +27,22 @@ class MPOD { ...@@ -27,20 +27,22 @@ class MPOD {
}; };
static inline const char *NAMES[] = { static inline const char *NAMES[] = {
"1.3.6.1.4.1.19947.1.3.2.1.4.1", // These are incomplete SNMP commands needing to be
"1.3.6.1.4.1.19947.1.3.2.1.5.1", // formatted with the channel id after the final dot
"1.3.6.1.4.1.19947.1.3.2.1.7.1", "1.3.6.1.4.1.19947.1.3.2.1.4.",
"1.3.6.1.4.1.19947.1.3.2.1.9.1", "1.3.6.1.4.1.19947.1.3.2.1.5.",
"1.3.6.1.4.1.19947.1.3.2.1.10.1", "1.3.6.1.4.1.19947.1.3.2.1.7.",
"1.3.6.1.4.1.19947.1.3.2.1.12.1", "1.3.6.1.4.1.19947.1.3.2.1.9.",
"1.3.6.1.4.1.19947.1.3.2.1.13.1", "1.3.6.1.4.1.19947.1.3.2.1.10.",
"1.3.6.1.4.1.19947.1.3.2.1.12.",
"1.3.6.1.4.1.19947.1.3.2.1.13.",
}; };
// Returns index of OID equals to name // Returns index of OID equals to name
// Returns UNKNOWN if none // Returns UNKNOWN if none
static unsigned int match(const char *name) { static unsigned int match(const char *name) {
for (unsigned int index = 0; index < COUNT; ++index) { for (unsigned int index = 0; index < COUNT; ++index) {
if (strcmp(NAMES[index], name) == 0) { if (strstr(name, NAMES[index])) {
return index; return index;
} }
} }
...@@ -50,9 +52,8 @@ class MPOD { ...@@ -50,9 +52,8 @@ class MPOD {
// Create an SNMP SETREQUEST message to setup MPOD // Create an SNMP SETREQUEST message to setup MPOD
MPOD(); MPOD();
SNMP::Message* setup(); SNMP::Message* read(const uint16_t);
SNMP::Message* read(); SNMP::Message* output(const uint16_t, const bool);
SNMP::Message* output(const bool);
bool message(const SNMP::Message*); bool message(const SNMP::Message*);
bool isOn() const; bool isOn() const;
bool isUp() const; bool isUp() const;
...@@ -62,11 +63,13 @@ class MPOD { ...@@ -62,11 +63,13 @@ class MPOD {
float getVoltage() const; float getVoltage() const;
float getCurrent() const; float getCurrent() const;
float getVoltageRiseRate() const; float getVoltageRiseRate() const;
uint16_t getChannel() const;
String toJSON(); String toJSON();
private: private:
unsigned int getIntegerFromVarBind(const VarBind*); unsigned int getIntegerFromVarBind(const VarBind*);
float getFloatFromVarBind(const VarBind*); float getFloatFromVarBind(const VarBind*);
uint16_t _channel;
bool _on; bool _on;
bool _up; bool _up;
bool _down; bool _down;
......
...@@ -38,6 +38,7 @@ String buildPanel(bool sib, bool plc, bool ups, unsigned long elapsed_secs) { ...@@ -38,6 +38,7 @@ String buildPanel(bool sib, bool plc, bool ups, unsigned long elapsed_secs) {
page += "<h3>Last INT: "; page += "<h3>Last INT: ";
page += elapsed_secs; page += elapsed_secs;
page += " secs. ago";
page += "</h3></div></body></html>"; page += "</h3></div></body></html>";
return page; return page;
......
...@@ -68,6 +68,6 @@ void toggle_status_led() { ...@@ -68,6 +68,6 @@ void toggle_status_led() {
if (millis() - toggle_start >= 1000) { if (millis() - toggle_start >= 1000) {
toggle_start = millis(); toggle_start = millis();
on = !on; on = !on;
MCP.write1(STATUS_LED_PIN, on); MCP.write1(STATUS_LED_PIN, on);
} }
} }
...@@ -20,6 +20,7 @@ void initializeRoutes() { ...@@ -20,6 +20,7 @@ void initializeRoutes() {
restServer.onNotFound(notFound); restServer.onNotFound(notFound);
restServer.on("/send", sendSNMP); restServer.on("/send", sendSNMP);
restServer.on("/", panel); restServer.on("/", panel);
restServer.on("/poll", pollMPODChannel);
restServer.begin(); restServer.begin();
Serial.println("REST Server Started"); Serial.println("REST Server Started");
...@@ -128,6 +129,7 @@ enum { ...@@ -128,6 +129,7 @@ enum {
void sendSNMP() { void sendSNMP() {
uint8_t output = NONE; uint8_t output = NONE;
uint16_t channel = 0;
bool success = false; bool success = false;
for (uint8_t i = 0; i < restServer.args(); i++) { for (uint8_t i = 0; i < restServer.args(); i++) {
...@@ -137,32 +139,67 @@ void sendSNMP() { ...@@ -137,32 +139,67 @@ void sendSNMP() {
} else if (restServer.arg(i) == "off") { } else if (restServer.arg(i) == "off") {
output = OFF; output = OFF;
} }
} } else if(restServer.argName(i) == "ch") {
channel = restServer.arg(i).toInt();
}
} }
auto ipAddr = IPAddress(192,168,140,79); auto ipAddr = IPAddress(192,168,140,79);
if (output != NONE) { if (output != NONE && channel != 0) {
SNMP::Message *snmp_msg = mpod.output(output); SNMP::Message *snmp_msg = mpod.output(channel, output);
snmp.send(snmp_msg, ipAddr, SNMP::Port::SNMP); snmp.send(snmp_msg, ipAddr, SNMP::Port::SNMP);
delete snmp_msg; delete snmp_msg;
success = true; success = true;
} }
if (success) {
SNMP::Message *snmp_msg = mpod.read(channel);
snmp.send(snmp_msg, ipAddr, SNMP::Port::SNMP);
delete snmp_msg;
}
String http_msg = "{\n"; String http_msg = "{\n";
http_msg += "\"target\":\"" + ipAddr.toString() + "\","; http_msg += "\"target\":\"" + ipAddr.toString() + "\",\n";
http_msg += "\"arguments\":{\"output\":" + String(output) + "},\n"; http_msg += "\"arguments\":{";
http_msg += "\"channel\":" + String(channel) + ",";
http_msg += "\"output\":" + String(output) + "},\n";
http_msg += "\"success\":" + String(success); http_msg += "\"success\":" + String(success);
if (success) {
http_msg += ",\n";
http_msg += mpod.toJSON();
}
http_msg += "\n}"; http_msg += "\n}";
restServer.send(200, "text/json", http_msg); restServer.send(200, "text/json", http_msg);
} }
void pollMPODChannel() { void pollMPODChannel() {
auto ret = mpod.toJSON(); uint16_t channel = 0;
for(uint8_t i = 0; i < restServer.args(); i++) {
if(restServer.argName(i) == "ch") {
channel = restServer.arg(i).toInt();
}
}
String ret;
if(!channel) {
ret = "\"reason\": \"Invalid channel\"";
} else {
auto ipAddr = IPAddress(192,168,140,79);
SNMP::Message *snmp_msg = mpod.read(channel);
snmp.send(snmp_msg, ipAddr, SNMP::Port::SNMP);
delete snmp_msg;
ret = mpod.toJSON(); // TODO: This has stale info at this stage!
}
String http_msg = "{\n"; String http_msg = "{\n";
http_msg += ret; http_msg += ret;
http_msg += ",\"success\": 1"; http_msg += ",\"success\": ";
http_msg += channel ? 1 : 0;
http_msg += ",\"channel\": ";
http_msg += channel;
http_msg += "\n}"; http_msg += "\n}";
restServer.send(200, "text/json", http_msg); restServer.send(200, "text/json", http_msg);
......
...@@ -8,5 +8,6 @@ void initializeRoutes(); ...@@ -8,5 +8,6 @@ void initializeRoutes();
void identify(); // /idn void identify(); // /idn
void notFound(); // 404 void notFound(); // 404
void restart(); // /restart void restart(); // /restart
void sendSNMP(); // /send?output=on void sendSNMP(); // /send?ch=107&output=on
void panel(); //show a status page void panel(); // / show a status page
void pollMPODChannel(); // /poll?ch=1
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment