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/src/CommProtocolPeerBrute.cpp

Committer:
mbriggs_vortex
Date:
2017-11-18
Revision:
91:8196900df6fe
Parent:
89:edfe5d376e55
Child:
95:aa9908d459c2

File content as of revision 91:8196900df6fe:

/*
 * CommProtocolPeerBrute.cpp
 *
 *  Created on: Jan 30, 2017
 *      Author: mbriggs
 */

#include "CommProtocolPeerBrute.h"
#include "dot_util.h"
#include "util.h"
#include "MyLog.h"
#include "ChannelPlan.h"

// wireless bridge protocol
const uint8_t TX_PWR = 20; // 20 dBm
const float RX_SLEEP_TIME = 2000; // ms (one second resolution, min 2 seconds)
const uint8_t TX_TIME = 30*2; // in ms
//const unsigned int nTimesToTx = ceil(RX_SLEEP_TIME / ((float)TX_TIME));
const unsigned int nTimesToTx = 75; // Hand tuned to be over 2.03 seconds of transmitting
//const uint8_t maxPayloadSize = 10; // Number of bytes (used for toa calcultion)

CommProtocolPeerBrute::CommProtocolPeerBrute()
{
    myLogDebug("RX_SLEEP_TIME %f, timeOnAir %lu, nTimesToTx %lu", RX_SLEEP_TIME, TX_TIME, nTimesToTx);

    mIsTx = true; // default to TX
}

CmdResult CommProtocolPeerBrute::init()
{
    CmdResult result;
    if (dot == NULL) {
        return cmdError;
    }
    result = readInfoFromNVM();
    if (result != cmdSuccess) {
        myLogWarning("Reverting to protocol defaults NVM Read failed");
        mMemObj.setDefaults();
        writeInfoToNVM();
    }
    result = configForSavedNetwork();
    if (result != cmdSuccess) {
        myLogError("Init error during radio config");
        return result;
    }

    resetCounters();

    mPrevDownLinkCnt = dot->getDownLinkCounter();
    return cmdSuccess;
}
CmdResult CommProtocolPeerBrute::configForSavedNetwork()
{
    if (dot == NULL) {
        return cmdError;
    }

//    myLogInfo("defaulting Dot configuration");
//    dot->resetConfig();

    // Common Configuration
    dot->setAesEncryption(true);  // Enable encryption
    dot->setTxWait(false);
    dot->setAck(0);  // Disable Ack
    dot->setClass("C"); // Set class C
    dot->setTxPower(TX_PWR);
    dot->setPreserveSession(false);

    // TODO break out in a utility function
    // update configuration if necessary
    myLogDebug("Setting up peer to peer configuration");
    if (dot->getJoinMode() != mDot::PEER_TO_PEER) {
        myLogDebug("changing network join mode to PEER_TO_PEER");
        if (dot->setJoinMode(mDot::PEER_TO_PEER) != mDot::MDOT_OK) {
            myLogError("failed to set network join mode to PEER_TO_PEER");
        }
    }
    uint8_t tx_power;
    uint8_t tx_datarate;
    uint32_t tx_frequency;
    uint8_t frequency_band = dot->getFrequencyBand();
    switch (frequency_band) {
		case lora::ChannelPlan::EU868_OLD:
		case lora::ChannelPlan::EU868:
            // 250kHz channels achieve higher throughput
            // DR6 : SF7 @ 250kHz
            // DR0 - DR5 (125kHz channels) available but much slower
            tx_frequency = 869850000;
            tx_datarate = mDot::DR6;
            // the 869850000 frequency is 100% duty cycle if the total power is under 7 dBm - tx power 4 + antenna gain 3 = 7
            tx_power = 4;
            break;
        case lora::ChannelPlan::US915_OLD:
        case lora::ChannelPlan::US915:
        case lora::ChannelPlan::AU915_OLD:
        case lora::ChannelPlan::AU915:
        default:
            // 500kHz channels achieve highest throughput
            // DR8 : SF12 @ 500kHz
            // DR9 : SF11 @ 500kHz
            // DR10 : SF10 @ 500kHz
            // DR11 : SF9 @ 500kHz
            // DR12 : SF8 @ 500kHz
            // DR13 : SF7 @ 500kHz
            // DR0 - DR3 (125kHz channels) available but much slower
            tx_frequency = 915500000;
            tx_datarate = mDot::DR13;
            // 915 bands have no duty cycle restrictions, set tx power to max
            tx_power = 20;
            break;
    }
    // in PEER_TO_PEER mode there is no join request/response transaction
    // as long as both Dots are configured correctly, they should be able to communicate

    update_peer_to_peer_config(mMemObj.mNetworkAddr, mMemObj.mNetworkSessionKey,
            mMemObj.mDataSessionKey, tx_frequency, tx_datarate, tx_power);
    dot->saveConfig();
    return cmdSuccess;
}
CmdResult CommProtocolPeerBrute::configForPairingNetwork()
{
    if (dot == NULL) {
        return cmdError;
    }

//    myLogInfo("defaulting Dot configuration");
//    dot->resetConfig();

    // Common Configuration
    dot->setAesEncryption(true);  // Enable encryption
    dot->setTxWait(false);
    dot->setAck(0);  // Disable Ack
    dot->setClass("C"); // Set class C
    dot->setTxPower(TX_PWR);
    dot->setPreserveSession(false);
//    dot->setDownLinkCounter(0);
//    dot->setUpLinkCounter(1);
    // TODO break out in a utility function
    // update configuration if necessary
    myLogDebug("Setting up peer to peer configuration");
    if (dot->getJoinMode() != mDot::PEER_TO_PEER) {
        myLogDebug("changing network join mode to PEER_TO_PEER");
        if (dot->setJoinMode(mDot::PEER_TO_PEER) != mDot::MDOT_OK) {
            myLogError("failed to set network join mode to PEER_TO_PEER");
        }
    }

    uint8_t tx_power;
    uint8_t tx_datarate;
    uint32_t tx_frequency;
    uint8_t frequency_band = dot->getFrequencyBand();
    switch (frequency_band) {
		case lora::ChannelPlan::EU868_OLD:
		case lora::ChannelPlan::EU868:
            // 250kHz channels achieve higher throughput
            // DR6 : SF7 @ 250kHz
            // DR0 - DR5 (125kHz channels) available but much slower
            tx_frequency = 869850000;
            tx_datarate = mDot::DR6;
            // the 869850000 frequency is 100% duty cycle if the total power is under 7 dBm - tx power 4 + antenna gain 3 = 7
            tx_power = 4;
            break;
        case lora::ChannelPlan::US915_OLD:
        case lora::ChannelPlan::US915:
        case lora::ChannelPlan::AU915_OLD:
        case lora::ChannelPlan::AU915:
        default:
            // 500kHz channels achieve highest throughput
            // DR8 : SF12 @ 500kHz
            // DR9 : SF11 @ 500kHz
            // DR10 : SF10 @ 500kHz
            // DR11 : SF9 @ 500kHz
            // DR12 : SF8 @ 500kHz
            // DR13 : SF7 @ 500kHz
            // DR0 - DR3 (125kHz channels) available but much slower
            tx_frequency = 915500000;
            tx_datarate = mDot::DR13;
            // 915 bands have no duty cycle restrictions, set tx power to max
            tx_power = 20;
            break;
    }
    update_peer_to_peer_config(pair_network_address, pair_network_session_key, pair_data_session_key, tx_frequency, tx_datarate, tx_power);
    dot->saveConfig(); // This is required for network settings to apply
    return cmdSuccess;
}
void CommProtocolPeerBrute::setTx(bool isTx)
{
    mIsTx = isTx;
}
bool CommProtocolPeerBrute::isTx()
{
    return mIsTx;
}
CmdResult CommProtocolPeerBrute::clearPair()
{
    CmdResult result;

    // TODO generate possibly random channel for new pair
    std::vector<uint8_t> key;
    key.reserve(16);

    result = genEncypKey(key, 4, false);
    if (result != cmdSuccess) {
        myLogError("Error generating network address.");
        return cmdError;
    }
    mMemObj.setNetworkAddr(key);

    result = genEncypKey(key, 16);
    if (result != cmdSuccess) {
        myLogError("Error generating network encryption keys.");
        return cmdError;
    }
    mMemObj.setNetworkSessionKey(key);

    result = genEncypKey(key, 16);
    if (result != cmdSuccess) {
        myLogError("Error generating data session encryption keys.");
        return cmdError;
    }
    mMemObj.setDataSessionKey(key);

    configForSavedNetwork();
    writeInfoToNVM();

    return cmdSuccess;
}

// TX focused
uint32_t CommProtocolPeerBrute::getSeqNum()
{
    return mMemObj.getLastMsgSeq();
}
CmdResult CommProtocolPeerBrute::send (const std::vector<uint8_t> &msg)
{
    if (!dot->getNetworkJoinStatus()) {
        join_network();
    }
    myLogDebug("Starting TX.  Time: %07lu", us_ticker_read());
    for(uint8_t i=0;i<nTimesToTx;++i) {
        dot->send(msg);
    }
    myLogDebug("Finished TX.  Time: %07lu", us_ticker_read());
    return cmdError;
}

CmdResult CommProtocolPeerBrute::sendAlert(uint16_t data)
{
    if (!dot->getNetworkJoinStatus()) {
        join_network();
    }
    // Request Message
    std::vector<uint8_t> msg;
    msg.reserve(16);
    // Flag 2 Bytes
    msg.push_back(0xEF);
    msg.push_back(0x10);
    // EUI 8 Bytes
    std::vector<uint8_t> eui(dot->getDeviceId());
    msg.insert(msg.end(), eui.begin(), eui.end());
    // Data 2 Bytes
    appendUint16ToVector(msg, data);
    // SeqNum 4 Bytes
    appendUint32ToVector(msg, mMemObj.getLastMsgSeq());
    mMemObj.incLastMsgSeq();
    return send(msg);
}

CmdResult CommProtocolPeerBrute::sendPairReq()
{
    if (!dot->getNetworkJoinStatus()) {
        join_network();
    }
    // Request Message
    std::vector<uint8_t> msg;
    msg.reserve(16);
    // Flag 2 Bytes
    msg.push_back(0xFE);
    msg.push_back(0x01);
    // EUI 8 Bytes
    std::vector<uint8_t> eui(dot->getDeviceId());
    msg.insert(msg.end(), eui.begin(), eui.end());
    // Reserved 6 Bytes
    for (uint8_t i=0;i<6;i++) {
        msg.push_back(0x00);
    }
    dot->send(msg); // Can just send once since the RX should be always listening
    return cmdSuccess;
}

// RX focused
CmdResult CommProtocolPeerBrute::listen (bool &msgPending)
{
    if (!dot->getNetworkJoinStatus()) {
        join_network();
    }

//    uint32_t cDwnLink = dot->getDownLinkCounter();

    wait(TX_TIME/1000.0); // Wait TX_TIME

    mPrevDownLinkCnt = 0;  // XXX improve how we keep track of new messages.  Maybe use lib callbacks.
    if (mPrevDownLinkCnt < dot->getDownLinkCounter()) {
        msgPending = true;
    }
    else {
        msgPending = false;
    }
    mPrevDownLinkCnt = dot->getDownLinkCounter();
    return cmdSuccess;  // Maybe add timeout as a possible return value
}

CmdResult CommProtocolPeerBrute::recv (std::vector<uint8_t> &msg)
{
    dot->recv(msg);
    return cmdSuccess;
}

CmdResult CommProtocolPeerBrute::recvAlert (std::vector<uint8_t> &eui, uint16_t &data, uint32_t &seqNum)
{
    std::vector<uint8_t> alertMsg;
    dot->recv(alertMsg);
    if (alertMsg.size() < 16) {
        myLogError("Alert message too short");
        return cmdError;
    }
    if (alertMsg[0] != 0xEF || alertMsg[1] != 0x10) {
        myLogError("Invalid alert message flag.");
        return cmdError;
    }
    eui.clear();
    eui.assign(alertMsg.begin()+2, alertMsg.begin()+2+8);

    data = (alertMsg[10] << 8) + alertMsg[11];

    seqNum =  alertMsg[12] << 24;
    seqNum += alertMsg[13] << 16;
    seqNum += alertMsg[14] << 8;
    seqNum += alertMsg[15];

    return cmdSuccess;
}

CmdResult CommProtocolPeerBrute::waitForPairing(float waitTime)
{
    float t = 0.0;
    bool msgPending;
    bool validPairReq = false;
    std::vector<uint8_t> pairMsg;
    do {
        listen(msgPending);
        t += TX_TIME/1000.0;
        if (msgPending) {
            pairMsg.clear();
            dot->recv(pairMsg);
            if (pairMsg[0] == 0xFE && pairMsg[1] == 0x01) {
                validPairReq = true;
            }
            else {
                myLogWarning("Invalid pair message message flag received .");
            }
        }
    }
    while (t < waitTime && !validPairReq);

    if (!msgPending) {
        return cmdTimeout;
    }

    wait(1.0);  // Wait just a little so it is clear for requester that it is a pair message
    return sendPairAccepted();
}

CmdResult CommProtocolPeerBrute::sendPairAccepted()
{
    bool sendResult;
    // Request Message
    std::vector<uint8_t> *msg = new std::vector<uint8_t>;
    msg->reserve(34);
    // Flag
    msg->push_back(0xFD);
    msg->push_back(0x02);
    myLogDebug("flag msg size %d", msg->size());
    // EUI
    std::vector<uint8_t> *eui = new std::vector<uint8_t>(dot->getDeviceId());
    msg->insert(msg->end(),eui->begin(), eui->end());
    delete eui;
    myLogDebug("eui msg size %d", msg->size());

    // Reserved for Freq
    for(uint8_t i=0;i<4;i++) {
        msg->push_back(0x00);
    }
    myLogDebug("freq msg size %d", msg->size());

    // Network Address
    std::vector<uint8_t> *networkAddr = new std::vector<uint8_t>;
    mMemObj.getNetworkAddr(*networkAddr);
    msg->insert(msg->end(),networkAddr->begin(), networkAddr->end());
    delete networkAddr;
    myLogDebug("netAddr msg size %d", msg->size());

    // Network session key
    std::vector<uint8_t> *networkSessionKey = new std::vector<uint8_t>;
    mMemObj.getNetworkSessionKey(*networkSessionKey);
    msg->insert(msg->end(),networkSessionKey->begin(), networkSessionKey->end());
    delete networkSessionKey;
    myLogDebug("netSessionKey msg size %d", msg->size());

    // Data session key
    std::vector<uint8_t> *dataSessionKey = new std::vector<uint8_t>;
    mMemObj.getDataSessionKey(*dataSessionKey);
    msg->insert(msg->end(),dataSessionKey->begin(), dataSessionKey->end());
    delete dataSessionKey;

    myLogDebug("msg size %d", msg->size());
    // Only send once since requester should be listening always
    sendResult = mDot::MDOT_OK == dot->send(*msg);
    delete msg;
    if (sendResult)
        return cmdSuccess;
    else
        return cmdError;
}

CmdResult CommProtocolPeerBrute::waitForAccept(float waitTime)
{
    float t = 0.0;
    bool msgPending = false;
    do {
        listen(msgPending);
        t += TX_TIME/1000.0;
    }
    while (t < waitTime && !msgPending);

    if (!msgPending) {
        return cmdTimeout;
    }

    std::vector<uint8_t> acceptMsg;
    dot->recv(acceptMsg);
    if (acceptMsg[0] != 0xFD || acceptMsg[1] != 0x02) {
        myLogError("Invalid accept message flag.");
        return cmdError;
    }

    std::vector<uint8_t> *netAddr = new std::vector<uint8_t>(acceptMsg.begin()+0x0E, acceptMsg.begin()+0x12);
    mMemObj.setNetworkAddr(*netAddr);
    delete netAddr;

    std::vector<uint8_t> *netSessionKey = new std::vector<uint8_t>(acceptMsg.begin()+0x12, acceptMsg.begin()+0x22);
    mMemObj.setNetworkSessionKey(*netSessionKey);
    delete netSessionKey;

    std::vector<uint8_t> *dataSessionKey = new std::vector<uint8_t>(acceptMsg.begin()+0x22, acceptMsg.begin()+0x32);
    mMemObj.setDataSessionKey(*dataSessionKey);
    delete dataSessionKey;

    writeInfoToNVM();

    return cmdSuccess;
}

// xDot Peer to Peer Specific
uint32_t CommProtocolPeerBrute::getDLC()
{
    return dot->getDownLinkCounter();
}

uint32_t CommProtocolPeerBrute::getULC()
{
    return dot->getUpLinkCounter();
}

// private:

CmdResult CommProtocolPeerBrute::readInfoFromNVM()
{
    bool nvmReadResult;
    uint8_t *data = new uint8_t [PROTOCOL_NVM_SIZE];

    nvmReadResult = dot->nvmRead(PROTOCOL_NVM_START_ADDR, data, PROTOCOL_NVM_SIZE);
    if (!nvmReadResult) {
        delete [] data;
        return cmdError;
    }
    mMemObj.fromBytes(data, PROTOCOL_NVM_SIZE);
    delete [] data;
    if (!mMemObj.validProtocolFlag()) {
        myLogWarning("Invalid Protocol Flag.  Using default values.");
        mMemObj.setDefaults();
        return cmdError;
    }
    else if (!mMemObj.validProtocolRev()) {
        myLogWarning("Invalid Protocol Rev.  Using default values.");
        mMemObj.setDefaults();
        return cmdError;
    }
    return cmdSuccess;
}

CmdResult CommProtocolPeerBrute::writeInfoToNVM()
{
    uint8_t *data = new uint8_t [PROTOCOL_NVM_SIZE];
    uint8_t size = PROTOCOL_NVM_SIZE;
    mMemObj.toBytes(data, size);
    dot->nvmWrite(PROTOCOL_NVM_START_ADDR, data, PROTOCOL_NVM_SIZE);

    delete [] data;
    return cmdSuccess;
}

CmdResult CommProtocolPeerBrute::resetCounters()
{
    dot->setDownLinkCounter(0);
    dot->setUpLinkCounter(1);
    return cmdSuccess;
}

CmdResult CommProtocolPeerBrute::genEncypKey(std::vector<uint8_t> &newKey, uint8_t keySize)
{
    return genEncypKey(newKey, keySize, true); // Default allow zero
}
CmdResult CommProtocolPeerBrute::genEncypKey(std::vector<uint8_t> &newKey, uint8_t keySize, bool allowZero)
{
    newKey.clear();
    for (uint8_t i=0;i<keySize; i++){
        if (allowZero) {
            newKey.push_back(dot->getRadioRandom() & 0xFF);
        }
        else {
            newKey.push_back((dot->getRadioRandom() % 254) + 1);
        }
    }
    return cmdSuccess;
}

void CommProtocolPeerBrute::printDotConfig()
{
    // display configuration and library version information
    myLogInfo("=====================");
    myLogInfo("general configuration");
    myLogInfo("=====================");
    myLogInfo("version ------------------ %s", dot->getId().c_str());
    myLogInfo("device ID/EUI ------------ %s", mts::Text::bin2hexString(dot->getDeviceId()).c_str());
    myLogInfo("frequency band ----------- %s", mDot::FrequencyBandStr(dot->getFrequencyBand()).c_str());
    if ((dot->getFrequencySubBand() != lora::ChannelPlan::EU868_OLD)
     || (dot->getFrequencySubBand() != lora::ChannelPlan::EU868)) {
        myLogInfo("frequency sub band ------- %u", dot->getFrequencySubBand());
    }
    myLogInfo("public network ----------- %s", dot->getPublicNetwork() ? "on" : "off");
    myLogInfo("=========================");
    myLogInfo("credentials configuration");
    myLogInfo("=========================");
    myLogInfo("device class ------------- %s", dot->getClass().c_str());
    myLogInfo("network join mode -------- %s", mDot::JoinModeStr(dot->getJoinMode()).c_str());
    if (dot->getJoinMode() == mDot::MANUAL || dot->getJoinMode() == mDot::PEER_TO_PEER) {
	myLogInfo("network address ---------- %s", mts::Text::bin2hexString(dot->getNetworkAddress()).c_str());
#if SHOW_SECRETS
	myLogInfo("network session key------- %s", mts::Text::bin2hexString(dot->getNetworkSessionKey()).c_str());
	myLogInfo("data session key---------- %s", mts::Text::bin2hexString(dot->getDataSessionKey()).c_str());
#endif
    } else {
	myLogInfo("network name ------------- %s", dot->getNetworkName().c_str());
	myLogInfo("network phrase ----------- %s", dot->getNetworkPassphrase().c_str());
#if SHOW_SECRETS
	myLogInfo("network EUI -------------- %s", mts::Text::bin2hexString(dot->getNetworkId()).c_str());
	myLogInfo("network KEY -------------- %s", mts::Text::bin2hexString(dot->getNetworkKey()).c_str());
#endif
    }
    myLogInfo("========================");
    myLogInfo("communication parameters");
    myLogInfo("========================");
    if (dot->getJoinMode() == mDot::PEER_TO_PEER) {
	myLogInfo("TX frequency ------------- %lu", dot->getTxFrequency());
    } else {
	myLogInfo("acks --------------------- %s, %u attempts", dot->getAck() > 0 ? "on" : "off", dot->getAck());
    }
    myLogInfo("TX datarate -------------- %s", mDot::DataRateStr(dot->getTxDataRate()).c_str());
    myLogInfo("TX power ----------------- %lu dBm", dot->getTxPower());
    myLogInfo("antenna gain ------------- %u dBm", dot->getAntennaGain());
}

// NvmProtocolObj
NvmProtocolObj::NvmProtocolObj()
{
    setDefaults();
}
void NvmProtocolObj::setDefaults()
{
    mProtocolFlag = PROTOCOL_FLAG;
    mProtocolRev = PROTOCOL_REV;
    mFreq = 915500000;
    std::memset(mNetworkAddr, 0x00, sizeof(mNetworkAddr));
    std::memset(mNetworkSessionKey, 0x00, sizeof(mNetworkSessionKey));
    std::memset(mDataSessionKey, 0x00, sizeof(mDataSessionKey));
    mLogicalAddr = 0x00000000;
    mSeqNum = 0x00000000;
}
CmdResult NvmProtocolObj::fromBytes(uint8_t *data, uint8_t size)
{
    if (size != PROTOCOL_NVM_SIZE) {
        return cmdError;
    }

    mProtocolFlag   = *((uint16_t *) (data));
    mProtocolRev    = *((uint16_t *) (data+0x02));
    mFreq           = *((uint32_t *) (data+0x04));
    std::memcpy(&mNetworkAddr,        data+0x08, 4);
    std::memcpy(&mNetworkSessionKey,  data+0x10, 16);
    std::memcpy(&mDataSessionKey,     data+0x20, 16);
    mLogicalAddr    = *((uint32_t *) (data+0x30));
    mSeqNum         = *((uint32_t *) (data+0x32));

    return cmdSuccess;
}
CmdResult NvmProtocolObj::toBytes(uint8_t *data, uint8_t &size) {
    // TODO check data size

    *((uint16_t *) (data))   = mProtocolFlag;
    *((uint16_t *) (data+2)) = mProtocolRev;
    *((uint32_t *) (data+0x04)) = mFreq;
    std::memcpy(data+0x08, &mNetworkAddr, 4);
    std::memcpy(data+0x10, &mNetworkSessionKey, 16);
    std::memcpy(data+0x20, &mDataSessionKey, 16);
    *((uint32_t *) (data+0x30)) = mLogicalAddr;
    *((uint32_t *) (data+0x32)) = mSeqNum;

    size = PROTOCOL_NVM_SIZE;

    return cmdSuccess;
}
uint16_t NvmProtocolObj::getProtocolFlag()
{
    return mProtocolFlag;
}
bool NvmProtocolObj::validProtocolFlag()
{
    return mProtocolFlag == PROTOCOL_FLAG;
}
uint16_t NvmProtocolObj::getProtocolRev()
{
    return mProtocolRev;
}
bool NvmProtocolObj::validProtocolRev()
{
    return mProtocolRev == PROTOCOL_REV;
}
void NvmProtocolObj::getNetworkAddr(std::vector<uint8_t> &addr)
{
    addr.clear();
    addr.assign(mNetworkAddr, mNetworkAddr+sizeof(mNetworkAddr));
}
void NvmProtocolObj::setNetworkAddr(const std::vector<uint8_t> &addr)
{
    if (addr.size() > sizeof(mNetworkAddr)) {
        myLogError("Network address too long.  Value not stored.");
        return;
    }
    for (uint8_t i=0; i < sizeof(mNetworkAddr); i++) {
        mNetworkAddr[i] = addr[i];
    }
}
void NvmProtocolObj::getNetworkSessionKey(std::vector<uint8_t> &key)
{
    key.clear();
    key.assign(mNetworkSessionKey, mNetworkSessionKey+sizeof(mNetworkSessionKey));
}
void NvmProtocolObj::setNetworkSessionKey(const std::vector<uint8_t> &key)
{
    if (key.size() > sizeof(mNetworkSessionKey)) {
        myLogError("Network session key too long.  Value not stored.");
        return;
    }
    for (uint8_t i=0; i < sizeof(mNetworkSessionKey); i++) {
        mNetworkSessionKey[i] = key[i];
    }
}
void NvmProtocolObj::getDataSessionKey(std::vector<uint8_t> &key)
{
    key.clear();
    key.assign(mDataSessionKey, mDataSessionKey+sizeof(mDataSessionKey));
}
void NvmProtocolObj::setDataSessionKey(const std::vector<uint8_t> &key)
{
    if (key.size() > sizeof(mDataSessionKey)) {
        myLogError("Data session key too long.  Value not stored.");
        return;
    }
    for (uint8_t i=0; i < sizeof(mDataSessionKey); i++) {
        mDataSessionKey[i] = key[i];
    }
}
uint16_t NvmProtocolObj::getLogicalAddr()
{
    return mLogicalAddr;
}
void NvmProtocolObj::setLogicalAddr(uint16_t in)
{
    mLogicalAddr= in;
}
uint32_t NvmProtocolObj::getLastMsgSeq()
{
    return mSeqNum;
}
void NvmProtocolObj::incLastMsgSeq()
{
    mSeqNum++;
}