/*
 * SmartHome server: Plug-in xbee
 *
 * Copyright (C) 2010 Daniel Pisi <dan.pisi@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License
 * as published by the Free Software Foundation.
 *
 */

/**
 * @file xbpacket.cpp
 * @brief XBee2 API frame template class
 * @author Daniel Pisi
 */

#include "xbpacket.h"

// -----------------------------------------------------------------------------

XbPacket::XbPacket(quint8 frameType)
{
    mFrameType = frameType;
}
// -----------------------------------------------------------------------------

XbPacket::~XbPacket()
{
    foreach (XbStreamItem *functionoid, mItems)
    {
        if (functionoid != NULL)
            delete functionoid;
    }
    mItems.clear();
}
// -----------------------------------------------------------------------------

quint8 XbPacket::frameType()
{
    return mFrameType;
}
// -----------------------------------------------------------------------------

quint8 XbPacket::checksum(QByteArray data)
{
    quint8 result = 0;

    for (int i = 0; i < data.size(); ++i)
        result += data.at(i);

    return 0xFF - result;
}
// -----------------------------------------------------------------------------

bool XbPacket::valid(QByteArray data)
{
    if ((data.size() < 5) || (data.at(0) != 0x7E))
        return false;

    quint16 len = data.at(1)*256 + data.at(2);

    if (data.size() != len+4)
        return false;

    return data.endsWith(checksum(data.mid(3, len)));
}
// -----------------------------------------------------------------------------

QByteArray XbPacket::frameData()
{
    QByteArray data;
    QDataStream stream(&data, QIODevice::ReadWrite);

    quint16 len = 0;

    stream << (quint8)0x7E;
    stream << len;
    stream << mFrameType;

    foreach (XbStreamItem *item, mItems)
    {
        item->wr(stream);
    }

    len = stream.device()->pos() - 3;

    quint8 b, sum = 0;
    stream.device()->seek(1);
    stream << len;
    for (int i = 0; i < len; ++i)
    {
        stream >> b;
        sum += b;
    }
    stream << quint8(0xFF - sum);

    return data;
}
// -----------------------------------------------------------------------------

bool XbPacket::parseFrameData(QByteArray &data)
{
    QDataStream stream(&data, QIODevice::ReadOnly);

    if (stream.device()->size() < 4)
        return false;

    quint8 b, sum = 0;
    quint16 len;

    stream >> b;
    if (b != 0x7E)
        return false;

    stream >> len;
    if (stream.device()->size() != len+4)
        return false;

    stream >> mFrameType;

    foreach (XbStreamItem *item, mItems)
    {
        item->rd(stream);
    }

    stream.device()->seek(3);
    for (int i = 0; i < len; ++i)
    {
        stream >> b;
        sum += b;
    }

    stream >> b;

    if (b != 0xFF-sum)
        return false;

    return true;
}
// =============================================================================
