XBee and XBee-PRO ZigBee RF modules provide cost-effective wireless connectivity to electronic devices. They are interoperable with other ZigBee PRO feature set devices, including devices from other vendors.

Dependencies:   BufferedArray

Dependents:   MBEDminiproject

Core/CoreAPI.cpp

Committer:
yangcq88517
Date:
2015-11-14
Revision:
6:5f31ddc17239
Parent:
4:a0f1fba6c2fb

File content as of revision 6:5f31ddc17239:

#include "CoreAPI.h"

CoreAPI::CoreAPI(ISerial * serial, bool escape)
    :xBeeRx64Indicator(NULL),xBeeRx16Indicator(NULL),xBeeRx64IOSampleIndicator(NULL),xBeeRx16IOSampleIndicator(NULL),xBeeTxStatusIndicator(NULL),
     aTCommandIndicator(NULL),modemStatusIndicator(NULL),zigBeeTxStatusIndicator(NULL),zigBeeRxIndicator(NULL),
     zigBeeExplicitRxIndicator(NULL),zigBeeIOSampleIndicator(NULL),sensorReadIndicator(NULL),nodeIdentificationIndicator(NULL),
     remoteCommandIndicator(NULL),routeRecordIndicator(NULL),manyToOneRouteIndicator(NULL)
{
    this->serial = serial;
    isEscapeMode = escape;
    msg = new APIFrame(INITIAL_FRAME_LENGTH);
    isChecksum = false;
    isRunning = false;
}

CoreAPI::~CoreAPI()
{
    if (msg != NULL)
        delete msg;

    if (serial != NULL)
        delete serial;
}

void CoreAPI::start()
{
    if (!isRunning) {
        isRunning = true;

        if (!serial->isOpen())
            serial->open();
    }
}

void CoreAPI::stop()
{
    if (isRunning) {
        isRunning = false;
        serial->close();
    }
}

void CoreAPI::setVerifyChecksum(bool isCheck)
{
    isChecksum = isCheck;
}

void CoreAPI::send(APIFrame * request)
{
    if (!isRunning)
        return;

    request->calculateChecksum();
    int size = request->getPosition();

    serial->writeByte(KEY);

    writeByte(size >> 8);
    writeByte(size);

    for (int i = 0; i < size; i++)
        writeByte(request->get(i));

    writeByte(request->getCheckSum());
}

int CoreAPI::readByte()
{
    int value = serial->readByte();

    if (isEscapeMode && value == ESCAPED)
        return serial->readByte() ^ 0x20;

    return value;
}

void CoreAPI::writeByte(unsigned char data)
{
    if (isEscapeMode) {
        if (data == KEY || data == ESCAPED || data == XON || data == XOFF) {
            serial->writeByte(ESCAPED);
            serial->writeByte(data ^ 0x20);
            return;
        }
    }

    serial->writeByte(data);
}

APIFrame * CoreAPI::getResponse()
{
    if (!isRunning)
        return NULL;

    if (!serial->peek())
        return NULL;

    while (serial->readByte() != KEY);

    int length = getLength();

    msg->allocate(length);

    readPayLoad(length);

    if (isChecksum) {
        if (msg->verifyChecksum())
            return msg;
        else
            return NULL;
    } else return msg;
}

int CoreAPI::getLength()
{
    int msb = readByte();

    int lsb = readByte();

    return (msb << 8) | lsb;
}

void CoreAPI::readPayLoad(int length)
{
    for (int i = 0; i < length; i++)
        msg->set(readByte());

    msg->setCheckSum(readByte());
}

XBeeRx64Indicator * CoreAPI::getXBeeRx64()
{
    if (getResponse() == NULL)
        return NULL;

    if (xBeeRx64Indicator.convert(msg))
        return &xBeeRx64Indicator;
    else return NULL;
}

XBeeRx16Indicator * CoreAPI::getXBeeRx16()
{
    if (getResponse() == NULL)
        return NULL;

    if (xBeeRx16Indicator.convert(msg))
        return &xBeeRx16Indicator;
    else return NULL;
}

XBeeRx64IOSampleIndicator * CoreAPI::getXBeeRx64IOSample()
{
    if (getResponse() == NULL)
        return NULL;

    if (xBeeRx64IOSampleIndicator.convert(msg))
        return &xBeeRx64IOSampleIndicator;
    else return NULL;
}

XBeeRx16IOSampleIndicator * CoreAPI::getXBeeRx16IOSample()
{
    if (getResponse() == NULL)
        return NULL;

    if (xBeeRx16IOSampleIndicator.convert(msg))
        return &xBeeRx16IOSampleIndicator;
    else return NULL;
}

XBeeTxStatusIndicator * CoreAPI::getXBeeTxStatus()
{
    if (getResponse() == NULL)
        return NULL;

    if (xBeeTxStatusIndicator.convert(msg))
        return &xBeeTxStatusIndicator;
    else return NULL;
}

ATCommandIndicator * CoreAPI::getATCommand()
{
    if (getResponse() == NULL)
        return NULL;

    if (aTCommandIndicator.convert(msg))
        return &aTCommandIndicator;
    else return NULL;
}

ModemStatusIndicator * CoreAPI::getModemStatus()
{
    if (getResponse() == NULL)
        return NULL;

    if (modemStatusIndicator.convert(msg))
        return &modemStatusIndicator;
    else return NULL;
}

ZigBeeTxStatusIndicator * CoreAPI::getZigBeeTxStatus()
{
    if (getResponse() == NULL)
        return NULL;

    if (zigBeeTxStatusIndicator.convert(msg))
        return &zigBeeTxStatusIndicator;
    else return NULL;
}

ZigBeeRxIndicator * CoreAPI::getZigBeeRx()
{
    if (getResponse() == NULL)
        return NULL;

    if (zigBeeRxIndicator.convert(msg))
        return &zigBeeRxIndicator;
    else return NULL;
}

ZigBeeExplicitRxIndicator * CoreAPI::getZigBeeExplicitRx()
{
    if (getResponse() == NULL)
        return NULL;

    if (zigBeeExplicitRxIndicator.convert(msg))
        return &zigBeeExplicitRxIndicator;
    else return NULL;
}

ZigBeeIOSampleIndicator * CoreAPI::getZigBeeIOSample()
{
    if (getResponse() == NULL)
        return NULL;

    if (zigBeeIOSampleIndicator.convert(msg))
        return &zigBeeIOSampleIndicator;
    else return NULL;
}

SensorReadIndicator * CoreAPI::getSensorRead()
{
    if (getResponse() == NULL)
        return NULL;

    if (sensorReadIndicator.convert(msg))
        return &sensorReadIndicator;
    else return NULL;
}

NodeIdentificationIndicator * CoreAPI::getNodeIdentification()
{
    if (getResponse() == NULL)
        return NULL;

    if (nodeIdentificationIndicator.convert(msg))
        return &nodeIdentificationIndicator;
    else return NULL;
}

RemoteCommandIndicator * CoreAPI::getRemoteCommand()
{
    if (getResponse() == NULL)
        return NULL;

    if (remoteCommandIndicator.convert(msg))
        return &remoteCommandIndicator;
    else return NULL;
}

RouteRecordIndicator * CoreAPI::getRouteRecord()
{
    if (getResponse() == NULL)
        return NULL;

    if (routeRecordIndicator.convert(msg))
        return &routeRecordIndicator;
    else return NULL;
}

ManyToOneRouteIndicator * CoreAPI::getManyToOneRoute()
{
    if (getResponse() == NULL)
        return NULL;

    if (manyToOneRouteIndicator.convert(msg))
        return &manyToOneRouteIndicator;
    else return NULL;
}

XBeeTxStatusIndicator * CoreAPI::sendXBeeTx16(Address * remoteAddress, OptionsBase * option, const unsigned char * payload, int offset, int length)
{
    if (!isRunning)
        return NULL;

    waitFrameID++;
    if (waitFrameID == 0)
        waitFrameID = 0x01;

    msg->rewind();
    msg->set(APIFrame::Tx16_Request);
    msg->set(waitFrameID);
    msg->set(remoteAddress->getNetworkAddress() >> 8);
    msg->set(remoteAddress->getNetworkAddress());
    msg->set(option->getValue());
    msg->sets(payload, offset, length);

    send(msg);

    timer.start();
    for (int i = 0; i < 3; i++) {
        timer.reset();
        while (!serial->peek()) {
            if (timer.read_ms() > 1000) {
                timer.stop();
                return NULL;
            }
        }

        getResponse();

        if (xBeeTxStatusIndicator.convert(msg) && xBeeTxStatusIndicator.getFrameID() == waitFrameID) {
            timer.stop();
            return &xBeeTxStatusIndicator;
        }
    }
    timer.stop();
    return NULL;
}

XBeeTxStatusIndicator * CoreAPI::sendXBeeTx64(Address * remoteAddress, OptionsBase * option, const unsigned  char * payload, int offset, int length)
{
    if (!isRunning)
        return NULL;

    waitFrameID++;
    if (waitFrameID == 0)
        waitFrameID = 0x01;

    msg->rewind();
    msg->set(APIFrame::Tx64_Request);
    msg->set(waitFrameID);
    msg->sets(remoteAddress->getAddressValue(), 0, 8);
    msg->set(option->getValue());
    msg->sets(payload, offset, length);

    send(msg);

    timer.start();
    for (int i = 0; i < 3; i++) {
        timer.reset();
        while (!serial->peek()) {
            if (timer.read_ms() > 1000) {
                timer.stop();
                return NULL;
            }
        }

        getResponse();

        if (xBeeTxStatusIndicator.convert(msg) && xBeeTxStatusIndicator.getFrameID() == waitFrameID) {
            timer.stop();
            return &xBeeTxStatusIndicator;
        }
    }
    timer.stop();
    return NULL;
}

ATCommandIndicator * CoreAPI::sendATCommand(const char * command, bool applyChange, const unsigned  char * parameter, int offset, int length)
{
    waitFrameID++;
    if (waitFrameID == 0)
        waitFrameID = 0x01;

    msg->rewind();
    if (applyChange)
        msg->set(APIFrame::AT_Command);
    else msg->set(APIFrame::AT_Command_Queue_Parameter_Value);
    msg->set(waitFrameID);
    msg->set(command[0]);
    msg->set(command[1]);
    if (parameter != NULL)
        msg->sets(parameter, offset, length);

    send(msg);

    timer.start();
    for (int i = 0; i < 3; i++) {
        timer.reset();
        while (!serial->peek()) {
            if (timer.read_ms() > 1000) {
                timer.stop();
                return NULL;
            }
        }

        getResponse();

        if (aTCommandIndicator.convert(msg) && aTCommandIndicator.getFrameID() == waitFrameID) {
            timer.stop();
            return &aTCommandIndicator;
        }
    }
    timer.stop();
    return NULL;
}

RemoteCommandIndicator * CoreAPI::sendRemoteATCommand(Address * remoteAddress, const char * command, OptionsBase * transmitOptions, const unsigned  char * parameter, int parameterOffset, int parameterLength)
{
    waitFrameID++;
    if (waitFrameID == 0)
        waitFrameID = 0x01;

    msg->rewind();
    msg->set(APIFrame::Remote_Command_Request);
    msg->set(waitFrameID);

    msg->sets(remoteAddress->getAddressValue(), 0, 10);
    msg->set(transmitOptions->getValue());
    msg->set(command[0]);
    msg->set(command[1]);

    if (parameter != NULL)
        msg->sets(parameter, parameterOffset, parameterLength);

    send(msg);

    timer.start();
    for (int i = 0; i < 3; i++) {
        timer.reset();
        while (!serial->peek()) {
            if (timer.read_ms() > 1000) {
                timer.stop();
                return NULL;
            }
        }

        getResponse();

        if (remoteCommandIndicator.convert(msg) && remoteCommandIndicator.getFrameID() == waitFrameID) {
            timer.stop();
            return &remoteCommandIndicator;
        }
    }
    timer.stop();
    return NULL;
}

ZigBeeTxStatusIndicator * CoreAPI::sendZigBeeTx(Address * remoteAddress, OptionsBase * option, const unsigned  char * payload, int offset, int length)
{
    waitFrameID++;
    if (waitFrameID == 0)
        waitFrameID = 0x01;

    msg->rewind();
    msg->set(APIFrame::ZigBee_Transmit_Request);
    msg->set(waitFrameID);
    msg->sets(remoteAddress->getAddressValue(), 0, 10);
    msg->set(0x00);
    msg->set(option->getValue());
    msg->sets(payload, offset, length);

    send(msg);

    timer.start();
    for (int i = 0; i < 3; i++) {
        timer.reset();
        while (!serial->peek()) {
            if (timer.read_ms() > 1000) {
                timer.stop();
                return NULL;
            }
        }

        getResponse();

        if (zigBeeTxStatusIndicator.convert(msg) && zigBeeTxStatusIndicator.getFrameID() == waitFrameID) {
            timer.stop();
            return &zigBeeTxStatusIndicator;
        }
    }
    timer.stop();
    return NULL;
}

ZigBeeTxStatusIndicator * CoreAPI::sendZigBeeExplicitTx(ExplicitAddress * remoteAddress, OptionsBase * option, const unsigned  char * payload, int offset, int length)
{
    waitFrameID++;
    if (waitFrameID == 0)
        waitFrameID = 0x01;

    msg->rewind();
    msg->set(APIFrame::Explicit_Addressing_ZigBee_Command_Frame);
    msg->set(waitFrameID);
    msg->sets(remoteAddress->getAddressValue(), 0, 10);
    msg->sets(remoteAddress->getExplicitValue(), 0 , 6);
    msg->set(0x00);
    msg->set(option->getValue());
    msg->sets(payload, offset, length);

    send(msg);

    timer.start();
    for (int i = 0; i < 3; i++) {
        timer.reset();
        while (!serial->peek()) {
            if (timer.read_ms() > 1000) {
                timer.stop();
                return NULL;
            }
        }

        getResponse();

        if (zigBeeTxStatusIndicator.convert(msg) && zigBeeTxStatusIndicator.getFrameID() == waitFrameID) {
            timer.stop();
            return &zigBeeTxStatusIndicator;
        }
    }
    timer.stop();
    return NULL;
}

ATCommandIndicator * CoreAPI::setPinFunction(Pin * pin, unsigned char function)
{
    return sendATCommand(pin->getCommand(), true, &function, 0 , 1);
}

ATCommandIndicator * CoreAPI::setIODetection(Pin ** pins, int size)
{
    return sendATCommand(ATCommands::Digital_IO_Change_Detection, true, Pin::IOChangeDetectionConfiguration(pins, size));
}

RemoteCommandIndicator * CoreAPI::setRemotePinFunction(Address * remoteAddress, Pin * pin, unsigned char function)
{
    return sendRemoteATCommand(remoteAddress, pin->getCommand(), RemoteCommandOptions::ApplyChanges, &function, 0 , 1);
}

RemoteCommandIndicator * CoreAPI::setRemoteIODetection(Address * remoteAddress, Pin ** pins, int size)
{
    return sendRemoteATCommand(remoteAddress, ATCommands::Digital_IO_Change_Detection, RemoteCommandOptions::ApplyChanges, Pin::IOChangeDetectionConfiguration(pins, size), 0, 2);
}

bool CoreAPI::forceXBeeLocalIOSample()
{
    ATCommandIndicator * re = sendATCommand(ATCommands::Force_Sample, true);

    if (re == NULL)
        return false;

    if (re->getCommandStatus() != 0x00)
        return false;

    return true;
}

IOSamples * CoreAPI::forceZigBeeLocalIOSample()
{
    ATCommandIndicator * re = sendATCommand(ATCommands::Force_Sample, true);

    if (re == NULL)
        return NULL;

    return IOSampleDecoder::ZigBeeSamplesParse(re->getParameter());
}

IOSamples * CoreAPI::forceXBeeRemoteIOSample(Address * remote)
{
    RemoteCommandIndicator * re = sendRemoteATCommand(remote, ATCommands::Force_Sample, OptionsBase::DEFAULT);

    return IOSampleDecoder::XBeeSamplesParse(re->getParameter());
}

IOSamples * CoreAPI::forceZigBeeRemoteIOSample(Address * remote)
{
    RemoteCommandIndicator * re = sendRemoteATCommand(remote, ATCommands::Force_Sample, OptionsBase::DEFAULT);

    return IOSampleDecoder::ZigBeeSamplesParse(re->getParameter());
}