Fork to see if I can get working

Dependencies:   BufferedSerial OneWire WinbondSPIFlash libxDot-dev-mbed5-deprecated

Fork of xDotBridge_update_test20180823 by Matt Briggs

xDotBridge/inc/CommProtocolPeerBrute.h

Committer:
Matt Briggs
Date:
2017-03-27
Revision:
70:6b3ca63792c2
Parent:
65:d546060aa03d

File content as of revision 70:6b3ca63792c2:

/**
 * Library for LoRa Peer to Peer Brute Force Protocol
*/

#ifndef COMMPROTOCOLPEERBRUTE_H_
#define COMMPROTOCOLPEERBRUTE_H_

#include <inttypes.h>
#include <vector>
#include "../config.h"
#include "mDot.h"

// TODO make base class to allow different protocols to be used with easy
// TODO wrap radio commands for error checking

// TODO change to const
static uint8_t pair_network_address[] = { 0x01, 0x00, 0x00, 0x00 }; // 0x00000000 reserved for multicast so use 1
static uint8_t pair_network_session_key[] = { 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04 };
static uint8_t pair_data_session_key[] =    { 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04 };

const uint16_t PROTOCOL_NVM_START_ADDR = 0x1000;
const uint16_t PROTOCOL_NVM_SIZE = 54; // Bytes
const uint16_t PROTOCOL_FLAG = 0x5A00;
const uint16_t PROTOCOL_REV = 0x0002;

/**
 *  @class NvmProtocolObj
 *  @brief This convenience class implements helps storing protocol settings to non-volatile memory
 *
 *  @details This class can translate to and from a byte array which can be stored then be easily stored
 *           using any number of APIs.
 */
class NvmProtocolObj {
public:
    /**
    * @brief NvmProtocolObj constructor
    * @details Initializes internal values with defaults
    */
    NvmProtocolObj();

    /**
    * @brief Set all internal variables to defaults.  This is automatically called from constructor.
    */
    void setDefaults();

    /**
    * @brief Saves internal state from a byte array
    */
    CmdResult toBytes(uint8_t *data, uint8_t &size);

    /**
    * @brief Loads internal state from a byte array.  This byte array should typically have
    *  previously generated by the toBytes function.
    */
    CmdResult fromBytes(uint8_t *data, uint8_t size);

    /**
    * @brief Accessor for protocol flag
    */
    uint16_t getProtocolFlag();

    /**
    * @brief Checks if protocol flag is valid
    */
    bool validProtocolFlag();

    /**
    * @brief Accessor for protocol rev
    */
    uint16_t getProtocolRev();

    /**
    * @brief Checks if the revision of the protocol matches
    */
    bool validProtocolRev();

    /**
     * @brief Accessor for network address.  Note value is returned via parameter.
     * @param addr A STL vector which will be set to 4 byte address
     */
    void getNetworkAddr(std::vector<uint8_t> &addr);

    /**
     * @brief A setter for network address
     * @param addr The network address to be stored.  This value should be 4 bytes.
     */
    void setNetworkAddr(const std::vector<uint8_t> &addr);

    /**
     * @brief Accessor for network session key.  Value return via parameter
     * @param key A STL Vector which will be set with 16 byte key
     */
    void getNetworkSessionKey(std::vector<uint8_t> &key);

    /**
     * @brief A setter for network session key
     *
     * @param key The network session key to be stored.  This value should be 16 bytes.
     */
    void setNetworkSessionKey(const std::vector<uint8_t> &key);

    /**
     * @brief Accessor for data session key.  Value return via parameter
     * @param key A STL Vector which will be set with 16 byte key
     */
    void getDataSessionKey(std::vector<uint8_t> &key);

    /**
     * @brief A setter for data session key
     * @param key The network session key to be stored.  This value should be 16 bytes.
     */
    void setDataSessionKey(const std::vector<uint8_t> &key);

    /**
     * @brief A accessor for logical address
     */
    uint16_t getLogicalAddr();

    /**
     * @brief A setter for logical address
     * @param in Value for logical address
     */
    void setLogicalAddr(uint16_t in);

    /**
     * @brief A accessor for LastMsgSeq
     */
    uint32_t getLastMsgSeq();

    /**
     * @brief A setter for LastMsgSeq
     * @param in Value for ter for LastMsgSeq
     */
    void setLastMsgSeq(uint32_t in);

    /**
     * @brief A convenience method which increments LastMsgSeq
     */
    void incLastMsgSeq();

    // TODO some day make these private with setters and getters
    uint8_t  mNetworkAddr[4];
    uint8_t  mNetworkSessionKey[16];
    uint8_t  mDataSessionKey[16];
private:
    uint16_t mProtocolFlag;
    uint16_t mProtocolRev;
    uint32_t mFreq;
    uint16_t mLogicalAddr;
    uint32_t mSeqNum;
};

/**
 *  @class CommProtocolPeerBrute
 *  @brief This class implements a peer-to-peer (P2P) brute force protocol.
 *
 *  @details The protocol consists of at a minimum one transmitter (TX) and one
 *  receiver (RX) which communicate via the 900MHz LoRa modulation.  The concept
 *  is that the RX is cycling on and off thus only listening for a small period
 *  of time.  Since we are not relying on a common time-base or other
 *  synchronization mechanism the TX simply transmits for a duration long enough
 *  guarantee that the RX will have at least one receive window during that time
 *  period.  Hence the name brute since the TX is just transmitting plenty for
 *  the RX to hear it.
 *
 *  The following should be implemented outside of the class:
 *  - Power settings?
 *  - What to do with the msgs which are received
 *  - When to send messages
 *  - When to sleep
 *
 */
class CommProtocolPeerBrute
{
public:
    /**
    * @brief CommProtocolPeerBrute constructor
    *
    * @details Just initialized internal variables does not configure devices.
    * Should call init before other functions are called.
    *
    * On Entry:
    *
    * On Exit:
    * Internal variables are set to a known state but further initialization is required
    *
    * @return
    */
    CommProtocolPeerBrute();

    /**
     * Attempts to read values from NVM (xDot's eeprom) if failure saves defaults.  Then
     * configures radio with settings.
     * @return Success unless radio configuration error
     */
    CmdResult init();

    /**
     * @brief Initialize radio with stored network network settings
     *
     * @return Returns the result of all the radio commands
     */
    CmdResult configForSavedNetwork();

    /**
     * @brief Sets weather this object is configured as a TX or RX
     *
     * @param isTx if true then configured as transmitter if false then configured as receiver.
     */
    void setTx(bool isTx);

    /**
     * @brief Returns weather this object is configured as a TX or RX
     * @return Returns true if TX
     */
    bool isTx();

    /**
     * @brief Returns weather this object is configured as a TX or RX
     * @return Returns true if RX
     */
    bool isRx() {return !isTx();}

    /**
     * @brief This will clear the security pairs and channel info for pair
     *
     * @details This will clear both the value in RAM as well as the value stored in EEPROM for security and
     * clarity purposes.  If RX this command will automatically trigger the generation of new security keys and
     * pair specific parameters.
     *
     * @return Returns status of all commands completed
     */
    CmdResult clearPair();

    // TX focused
    /**
     * @brief Accessor sequence number
     * @return Integer value
     */
    uint32_t getSeqNum();
    /**
     * @brief Transmit the msg attached
     *
     * @details TODO figure out what information is wrapped by the LoRaWAN stuff implemented by
     * Multitech Systems
     *
     * @param msg A STL vector of uint8_t
     * @return Returns status of all commands completed
     */
    CmdResult send (const std::vector<uint8_t> &msg);

    /**
     * @brief Transmit an alert per documentation
     *
     * @details Sends EUI, uint16 data, alert seqNum
     *
     * @param data Input data to send
     * @return if transmission is successful (note no ACK checked)
     */
    CmdResult sendAlert (uint16_t data);

    /**
     * @brief This function sends a request to pair with a RX.  If successful a pair accept message is received.
     *
     * @return Returns status of all commands completed
     */
    CmdResult sendPairReq();

    // RX focused
    /**
     * @brief This function enables the RX hardware of a radio.  Note the listen time is defined internally by the protocol
     *
     * @param msgPending This boolean is return by reference.  If true then during the listen window a msg was received.
     * @return Returns status of all commands completed
     */
    CmdResult listen (bool &msgPending);

    /**
     * @brief Returns the last message received via listening
     *
     * @param msg This STL vector of uint8_t is returned by reference with msg contents.
     * @return Returns status of all commands completed
     */
    CmdResult recv (std::vector<uint8_t> &msg);

    /**
     * @brief Attempts to parse and return the last message received
     *
     * @details If the message is too short or if the flag is not correct will return an error.
     *
     * @param eui 4 byte value returned
     * @param data Data field from alert message
     * @param seqNum Transmitter's sequence number
     * @return Returns status of all commands completed
     */
    CmdResult recvAlert (std::vector<uint8_t> &eui, uint16_t &data, uint32_t &seqNum);

    /**
     * @brief This function enables the radio to listen for pair requests.
     * @param waitTime The maximum time which radio waits for pair requests
     *
     * TODO determine if it is important to know who is paired
     *
     * @return If pair message received then cmdSucess is returned otherwise
     * timeout is returned.
     */
    CmdResult waitForPairing(float waitTime);

    /**
     * @brief Send a pair accept message.  This message contains all the information for TX to properly send
     * msgs to RX in P2P mode.
     * @return Returns status of all commands completed
     */
    CmdResult sendPairAccepted();

    /**
     *
     * @param waitTime
     * @return
     */
    CmdResult waitForAccept(float waitTime);

    // xDot Peer to Peer Specific
    /**
     * Convenience function to get the internal downlink count from radio
     * @return Number of downlink msgs
     */
    uint32_t getDLC();

    /**
     * Convenience function to get the internal uplink count from radio
     * @return Number of uplink msgs
     */
    uint32_t getULC();

    /**
     * Resets both uplink and downlink counters (1 and 0 respectively).
     * @return
     */
    CmdResult resetCounters();

    // TODO maybe this should be private
    CmdResult configForPairingNetwork();
    void printDotConfig();

private:
    NvmProtocolObj mMemObj;
    bool mIsTx;
    uint32_t mPrevDownLinkCnt;

    /**
    * @brief Reads baseboard information from non-volatile memory (NVM)
    *
    * @details This data is read from the xDot's internal EEPROM.  This
    * method is called from init().  The following
    * is stored:
    * 1.  Peer Brute Storage code word
    * 2.  8-bit protocol version
    * 3.  16-bit Baseboard serial number
    * 4.  4 Byte network address
    * 5.  16 Byte network session key
    * 6.  16 Byte data session key
    * 7.  4 Byte DLC
    * 8.  4 Byte ULC
    *
    * TODO add memory map information
    *
    * @return CmdResult
    */
    CmdResult readInfoFromNVM();

    /**
    * @brief Stores baseboard information to non-volatile memory (NVM)
    *
    * @details This method is called during special configuration events like first time boot or factory reset.
    *
    * TODO add memory map information
    *
    * @return CmdResult
    */
    CmdResult writeInfoToNVM();

    /**
     * Generates new encryption keys for radio
     * @return
     */
    CmdResult genEncypKey(std::vector<uint8_t> &newKey, uint8_t keySize, bool allowZero);
    CmdResult genEncypKey(std::vector<uint8_t> &newKey, uint8_t keySize);

};


#endif