Skip to content
Snippets Groups Projects
mpod.hpp 3.37 KiB
Newer Older
Cyril Danilevski's avatar
Cyril Danilevski committed
#pragma once
#include <SNMP.h>

using SNMP::IntegerBER;
using SNMP::OctetStringBER;
using SNMP::OpaqueBER;
using SNMP::OpaqueFloatBER;
using SNMP::VarBind;
using SNMP::VarBindList;


// In ms., the time it takes for an MPOD to process a query, and update its status.
// While the MPOD will acknowledge more or less immediately, (in the next snmp update loop),
// its information may be stale.
// It is preferable to set a channel, ignore the reply, wait a bit, and poll the channel.
//
// The fastest a channel can be updated is about 375ms, round up to 400ms.
#define MPOD_UPDATE_LATENCY 400


Cyril Danilevski's avatar
Cyril Danilevski committed
class MPOD {
    public:
        // Simple helper class to handle OIDs
        class OID {
        public:
            enum {
                OUTPUTSTATUS,
                OUTPUTMEASUREMENTSENSEVOLTAGE,
                OUTPUTMEASUREMENTCURRENT,
                OUTPUTSWITCH,
                OUTPUTVOLTAGE,
                OUTPUTCURRENT,
                OUTPUTVOLTAGERISERATE,
                UNKNOWN,
                COUNT = UNKNOWN,
            };
Cyril Danilevski's avatar
Cyril Danilevski committed
            static inline const char *NAMES[] = {
                    // These are incomplete SNMP commands needing to be
                    // formatted with the channel id after the final dot
                    "1.3.6.1.4.1.19947.1.3.2.1.4.",
                    "1.3.6.1.4.1.19947.1.3.2.1.5.",
                    "1.3.6.1.4.1.19947.1.3.2.1.7.",
                    "1.3.6.1.4.1.19947.1.3.2.1.9.",
                    "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.",
Cyril Danilevski's avatar
Cyril Danilevski committed
            };
Cyril Danilevski's avatar
Cyril Danilevski committed
            // Returns index of OID equals to name
            // Returns UNKNOWN if none
            static unsigned int match(const char *name) {
                for (unsigned int index = 0; index < COUNT; ++index) {
                    if (strstr(name, NAMES[index])) {
Cyril Danilevski's avatar
Cyril Danilevski committed
                        return index;
                    }
                }
                return UNKNOWN;
            }
        };
        SNMP::Message* read(const uint16_t);
        SNMP::Message* setChannelState(const uint16_t, const bool);
        SNMP::Message* setTargetVoltage(const uint16_t, const float);
Cyril Danilevski's avatar
Cyril Danilevski committed
        bool message(const SNMP::Message*);
        bool isOn() const;
        bool isInterlocked() const;
        bool isRampingUp() const;
        bool isRampingDown() const;
Cyril Danilevski's avatar
Cyril Danilevski committed
        float getMeasurementSenseVoltage() const;
        float getMeasurementCurrent() const;
        float getVoltage() const;
        float getCurrent() const;
        float getVoltageRiseRate() const;
        uint16_t getChannel() const;
        String toJSON();
Cyril Danilevski's avatar
Cyril Danilevski committed
    private:
        unsigned int getIntegerFromVarBind(const VarBind*);
        float getFloatFromVarBind(const VarBind*);
        uint16_t _channel;
Cyril Danilevski's avatar
Cyril Danilevski committed
        bool _on;
        bool _interlocked;
        bool _rampingUp;
        bool _rampingDown;
Cyril Danilevski's avatar
Cyril Danilevski committed
        float _measurementSenseVoltage;
        float _measurementCurrent;
        float _voltage;
        float _current;
        float _voltageRiseRate;
};

extern SNMP::Manager snmp;
extern MPOD mpod;

// Event handler to process SNMP messages
void onSNMPMessage(const SNMP::Message *message, const IPAddress remote, const uint16_t port);
void initializeSNMP();
void setChannelStateAndWait(const IPAddress*, const uint16_t, const uint8_t);
void setChannelVoltageAndWait(const IPAddress*, const uint16_t, const float);