diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000000000000000000000000000000000000..47b4a23bca16c98fc532aaf337ddca22400bcc7f --- /dev/null +++ b/.clang-format @@ -0,0 +1,5 @@ +BasedOnStyle: Google +IndentWidth: 4 +ColumnLimit: 100 +Language: Cpp +AllowShortIfStatementsOnASingleLine: false diff --git a/README.md b/README.md index 1a33f6fe75e2ea77bace3586dff234abd55c4a58..dabb980fccbe8b58172136a5534cce5f3bea627f 100644 --- a/README.md +++ b/README.md @@ -100,3 +100,11 @@ CI artefacts can be uploaded so: unzip icbm-0.0.0.zip arduino-cli upload -p /dev/ttyUSB1 -b esp32:esp32:esp32wroverkit --input-dir icbm-0.0.0 + + +## Contributing + +Use `clang-format` to format the project: + + find . -regex '.*\.\(ino\|cpp\|h\)' -exec clang-format -i {} + + diff --git a/esp32_ethernet.cpp b/esp32_ethernet.cpp index ec384a46f6b5950a858b31c90cc5834c82f19f20..15b2e629ce95fa51e54f906b1539d7c681e265c7 100644 --- a/esp32_ethernet.cpp +++ b/esp32_ethernet.cpp @@ -7,46 +7,42 @@ We use Ethernet, but reuse much of the networking utilities. bool eth_connected = false; - -void EthernetEvent(WiFiEvent_t event) -{ - switch (event) { - case ARDUINO_EVENT_ETH_START: - Serial.println("ETH Started"); - ETH.setHostname("esp32-ethernet"); - break; - case ARDUINO_EVENT_ETH_CONNECTED: - Serial.println("ETH Connected"); - break; - case ARDUINO_EVENT_ETH_GOT_IP: - Serial.print("ETH MAC: "); - Serial.print(ETH.macAddress()); - Serial.print(", IPv4: "); - Serial.print(ETH.localIP()); - if (ETH.fullDuplex()) { - Serial.print(", FULL_DUPLEX"); - } - Serial.print(", "); - Serial.print(ETH.linkSpeed()); - Serial.println("Mbps"); - eth_connected = true; - break; - case ARDUINO_EVENT_ETH_DISCONNECTED: - Serial.println("ETH Disconnected"); - eth_connected = false; - break; - case ARDUINO_EVENT_ETH_STOP: - Serial.println("ETH Stopped"); - eth_connected = false; - break; - default: - break; - } +void EthernetEvent(WiFiEvent_t event) { + switch (event) { + case ARDUINO_EVENT_ETH_START: + Serial.println("ETH Started"); + ETH.setHostname("esp32-ethernet"); + break; + case ARDUINO_EVENT_ETH_CONNECTED: + Serial.println("ETH Connected"); + break; + case ARDUINO_EVENT_ETH_GOT_IP: + Serial.print("ETH MAC: "); + Serial.print(ETH.macAddress()); + Serial.print(", IPv4: "); + Serial.print(ETH.localIP()); + if (ETH.fullDuplex()) { + Serial.print(", FULL_DUPLEX"); + } + Serial.print(", "); + Serial.print(ETH.linkSpeed()); + Serial.println("Mbps"); + eth_connected = true; + break; + case ARDUINO_EVENT_ETH_DISCONNECTED: + Serial.println("ETH Disconnected"); + eth_connected = false; + break; + case ARDUINO_EVENT_ETH_STOP: + Serial.println("ETH Stopped"); + eth_connected = false; + break; + default: + break; + } } -void initializeNetwork() -{ - WiFi.onEvent(EthernetEvent); - ETH.begin(ETH_TYPE, ETH_ADDR, ETH_MDC_PIN, ETH_MDIO_PIN, ETH_POWER_PIN, ETH_CLK_MODE); +void initializeNetwork() { + WiFi.onEvent(EthernetEvent); + ETH.begin(ETH_TYPE, ETH_ADDR, ETH_MDC_PIN, ETH_MDIO_PIN, ETH_POWER_PIN, ETH_CLK_MODE); } - diff --git a/icbm.ino b/icbm.ino index e980bd0e8b1aa67e854f41947c875822a8825d6d..4b1580e5f3de40d1586a04229b7900ef9ee8cf0e 100644 --- a/icbm.ino +++ b/icbm.ino @@ -1,8 +1,7 @@ #include "esp32_ethernet.hpp" -#include "rest.hpp" #include "mpod.hpp" #include "pins.hpp" - +#include "rest.hpp" unsigned long start; extern bool eth_connected; @@ -21,7 +20,6 @@ void setup() { poll_port_expander(); } - enum { NONE, ON, @@ -29,11 +27,10 @@ enum { }; void serial_loop() { - if (millis() - start >= 1000) { + if (millis() - start >= 1000) { start = millis(); Serial.print(eth_connected ? "." : "-"); } - } void loop() { diff --git a/mpod.cpp b/mpod.cpp index c7d66b66473687c90d7e82f7f3b69f01153aee1e..aaf667bbfc576eead85f8a17aa61a44b306239cf 100644 --- a/mpod.cpp +++ b/mpod.cpp @@ -1,4 +1,5 @@ #include "mpod.hpp" + #include <SNMP.h> #include <WiFiUdp.h> @@ -13,10 +14,10 @@ MPOD::MPOD() { float _voltageRiseRate = 0; } - // Create an SNMP GETREQUEST message -SNMP::Message* MPOD::read(uint16_t channel) { - SNMP::Message* message = new SNMP::Message(SNMP::Version::V2C, "public", SNMP::Type::GetRequest); +SNMP::Message *MPOD::read(uint16_t channel) { + SNMP::Message *message = + new SNMP::Message(SNMP::Version::V2C, "public", SNMP::Type::GetRequest); // In GETREQUEST, values are always of type NULL. String snmp_cmd = OID::NAMES[OID::OUTPUTSTATUS]; snmp_cmd += channel; @@ -34,8 +35,8 @@ SNMP::Message* MPOD::read(uint16_t channel) { } // Create an SNMP SETREQUEST message to switch on or off the MPOD -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 *MPOD::output(const uint16_t channel, const bool on) { + 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. String snmp_cmd = OID::NAMES[OID::OUTPUTSWITCH]; @@ -58,97 +59,80 @@ bool MPOD::message(const SNMP::Message *message) { // 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; + 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; } // 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; + 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 found; } -bool MPOD::isOn() const { - return _on; -} +bool MPOD::isOn() const { return _on; } -bool MPOD::isUp() const { - return _up; -} +bool MPOD::isUp() const { return _up; } -bool MPOD::isDown() const { - return _down; -} +bool MPOD::isDown() const { return _down; } -float MPOD::getMeasurementSenseVoltage() const { - return _measurementSenseVoltage; -} +float MPOD::getMeasurementSenseVoltage() const { return _measurementSenseVoltage; } -float MPOD::getMeasurementCurrent() const { - return _measurementCurrent; -} +float MPOD::getMeasurementCurrent() const { return _measurementCurrent; } -float MPOD::getVoltage() const { - return _voltage; -} +float MPOD::getVoltage() const { return _voltage; } -float MPOD::getCurrent() const { - return _current; -} +float MPOD::getCurrent() const { return _current; } -float MPOD::getVoltageRiseRate() const { - return _voltageRiseRate; -} +float MPOD::getVoltageRiseRate() const { return _voltageRiseRate; } -uint16_t MPOD::getChannel() const { - return _channel; -} +uint16_t MPOD::getChannel() const { return _channel; } // Use appropriate cast to get integer value unsigned int MPOD::getIntegerFromVarBind(const VarBind *varbind) { - return static_cast<IntegerBER*>(varbind->getValue())->getValue(); + 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(); + return static_cast<OpaqueFloatBER *>(static_cast<OpaqueBER *>(varbind->getValue())->getBER()) + ->getValue(); } String MPOD::toJSON() { @@ -167,7 +151,6 @@ String MPOD::toJSON() { return json; } - WiFiUDP udp; SNMP::Manager snmp; MPOD mpod; diff --git a/pins.cpp b/pins.cpp index 3f0837a19dc7609c97bd0aa7079d3d59b3654794..c64146c4b3562c038a48d1fa582a581abb837675 100644 --- a/pins.cpp +++ b/pins.cpp @@ -4,102 +4,91 @@ MCP23S08 MCP(SS, MISO, MOSI, SCK); volatile byte ISR_FLAG = 0; struct pins PINS; -void IRAM_ATTR isr(){ - ISR_FLAG = 1; -} - -void initializeMCP() -{ - pinMode(ISR_PIN, INPUT_PULLUP); - attachInterrupt(digitalPinToInterrupt(ISR_PIN), isr, CHANGE); +void IRAM_ATTR isr() { ISR_FLAG = 1; } - SPI.begin(); - MCP.begin(); +void initializeMCP() { + pinMode(ISR_PIN, INPUT_PULLUP); + attachInterrupt(digitalPinToInterrupt(ISR_PIN), isr, CHANGE); - // Enable inputs and interrupts on pins 0-2 - MCP.pinMode8(0b00000111); - MCP.enableInterrupt(0, CHANGE); - MCP.enableInterrupt(1, CHANGE); - MCP.enableInterrupt(2, CHANGE); - Serial.println("MCP23S08 Started"); + SPI.begin(); + MCP.begin(); + // Enable inputs and interrupts on pins 0-2 + MCP.pinMode8(0b00000111); + MCP.enableInterrupt(0, CHANGE); + MCP.enableInterrupt(1, CHANGE); + MCP.enableInterrupt(2, CHANGE); + Serial.println("MCP23S08 Started"); } - -void isr_check_loop() -{ - if (ISR_FLAG == 1){ - PINS.sib = false; - PINS.plc = false; - PINS.ups = false; - PINS.last_triggered = millis(); - - Serial.print("Interrupt: "); - uint8_t regval = MCP.getInterruptCaptureRegister(); //INTCAP - Serial.print(regval, BIN); - - uint8_t mask = 1 << 0; - if (!(regval & mask)) { - Serial.print(" UPS"); - PINS.ups = true; - } - - mask = 1 << 1; - if (!(regval & mask)) { - Serial.print(" PLC"); - PINS.plc = true; +void isr_check_loop() { + if (ISR_FLAG == 1) { + PINS.sib = false; + PINS.plc = false; + PINS.ups = false; + PINS.last_triggered = millis(); + + Serial.print("Interrupt: "); + uint8_t regval = MCP.getInterruptCaptureRegister(); // INTCAP + Serial.print(regval, BIN); + + uint8_t mask = 1 << 0; + if (!(regval & mask)) { + Serial.print(" UPS"); + PINS.ups = true; + } + + mask = 1 << 1; + if (!(regval & mask)) { + Serial.print(" PLC"); + PINS.plc = true; + } + + mask = 1 << 2; + if (!(regval & mask)) { + Serial.print(" SIB"); + PINS.sib = true; + } + + Serial.println(); + ISR_FLAG = 0; } - - mask = 1 << 2; - if (!(regval & mask)) { - Serial.print(" SIB"); - PINS.sib = true; - } - - Serial.println(); - ISR_FLAG = 0; - } } - -void poll_port_expander() -{ +void poll_port_expander() { PINS.sib = false; PINS.plc = false; PINS.ups = false; PINS.last_triggered = millis(); int regval = MCP.read8(); - + uint8_t mask = 1 << 0; if (!(regval & mask)) { - Serial.print(" UPS"); - PINS.ups = true; + Serial.print(" UPS"); + PINS.ups = true; } mask = 1 << 1; if (!(regval & mask)) { - Serial.print(" PLC"); - PINS.plc = true; + Serial.print(" PLC"); + PINS.plc = true; } mask = 1 << 2; if (!(regval & mask)) { - Serial.print(" SIB"); - PINS.sib = true; + Serial.print(" SIB"); + PINS.sib = true; } Serial.println(); - - } - bool on = true; unsigned long toggle_start = 0; void toggle_status_led() { - if (millis() - toggle_start >= 1000) { + if (millis() - toggle_start >= 1000) { toggle_start = millis(); - on = !on; + on = !on; MCP.write1(STATUS_LED_PIN, on); - } + } } diff --git a/rest.cpp b/rest.cpp index b3c5247b97d321c10d48d4a0e4f64d95ddcf4dd3..9d5504053f1c0a5249c09b7441b08291163c2af3 100644 --- a/rest.cpp +++ b/rest.cpp @@ -1,8 +1,10 @@ #include "rest.hpp" + +#include <ETH.h> + #include "mpod.hpp" #include "panel.hpp" #include "pins.hpp" -#include <ETH.h> #ifndef ICBM_GIT_VERSION #define ICBM_GIT_VERSION "DEVEL" @@ -26,7 +28,6 @@ void initializeRoutes() { Serial.println("REST Server Started"); } - void identify() { int seconds = millis() / 1000; int hours = seconds / 3600; @@ -86,12 +87,7 @@ void identify() { void panel() { unsigned long elapsed_seconds = (millis() - PINS.last_triggered) / 1000; - String content = buildPanel( - PINS.sib, - PINS.plc, - PINS.ups, - elapsed_seconds - ); + String content = buildPanel(PINS.sib, PINS.plc, PINS.ups, elapsed_seconds); restServer.send(200, "text/html", content); } @@ -106,101 +102,100 @@ void notFound() { for (uint8_t i = 0; i < restServer.args(); i++) { message += "\n\"" + restServer.argName(i) + "\":\"" + restServer.arg(i) + "\","; } - if (restServer.args() != 0) { - message.remove(message.length()-1); // remove trailing comma for valid json - } + if (restServer.args() != 0) { + message.remove(message.length() - 1); // remove trailing comma for valid json + } - message += "\n}\n}"; + message += "\n}\n}"; restServer.send(404, "text/json", message); - Serial.println(message); + Serial.println(message); } void restart() { - restServer.send(200); - ESP.restart(); + restServer.send(200); + ESP.restart(); } - enum { - OFF, - ON, - NONE, + OFF, + ON, + NONE, }; 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++) { - if(restServer.argName(i) == "output") { - if(restServer.arg(i) == "on") { - output = ON; - } else if (restServer.arg(i) == "off") { - output = OFF; - } - } else if(restServer.argName(i) == "ch") { + if (restServer.argName(i) == "output") { + if (restServer.arg(i) == "on") { + output = ON; + } else if (restServer.arg(i) == "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 && channel != 0) { - SNMP::Message *snmp_msg = mpod.output(channel, output); - snmp.send(snmp_msg, ipAddr, SNMP::Port::SNMP); - delete snmp_msg; - success = true; - } + SNMP::Message *snmp_msg = mpod.output(channel, output); + snmp.send(snmp_msg, ipAddr, SNMP::Port::SNMP); + delete snmp_msg; + success = true; + } if (success) { - SNMP::Message *snmp_msg = mpod.read(channel); - snmp.send(snmp_msg, ipAddr, SNMP::Port::SNMP); - delete snmp_msg; + SNMP::Message *snmp_msg = mpod.read(channel); + snmp.send(snmp_msg, ipAddr, SNMP::Port::SNMP); + delete snmp_msg; } - String http_msg = "{\n"; - http_msg += "\"target\":\"" + ipAddr.toString() + "\",\n"; - http_msg += "\"arguments\":{"; + String http_msg = "{\n"; + http_msg += "\"target\":\"" + ipAddr.toString() + "\",\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() { uint16_t channel = 0; - for(uint8_t i = 0; i < restServer.args(); i++) { - if(restServer.argName(i) == "ch") { + for (uint8_t i = 0; i < restServer.args(); i++) { + if (restServer.argName(i) == "ch") { channel = restServer.arg(i).toInt(); } } String ret; - if(!channel) { + if (!channel) { ret = "\"reason\": \"Invalid channel\""; } else { - auto ipAddr = IPAddress(192,168,140,79); + 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! + 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"; - http_msg += ret; - http_msg += ",\"success\": "; + String http_msg = "{\n"; + http_msg += ret; + 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); }