/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ /* * Message contains all SPIT messages. * A Message contains a Header and an OPPart. * * File: Message.cpp * Author: Hagi * * Created on 3. April 2019, 08:51 */ #include "spit_message.hpp" #include "esp_log.h" #include const char *TAG = "SpitMsg"; namespace spit { //---------- Receive --------- Message::Message(std::vector message) { if (message.empty()) { ESP_LOGE(TAG, "message is emtpy, nothing to parse"); return; } if (!parse(message)) { ESP_LOGE(TAG, "Failed ot parse message"); return; } } // Receive bool Message::parse(std::vector message) { // parse Header auto header = make_unique
(); if (!header->parse(message)) { return false; } // parse OP switch (header->getType()) { case Message::Connect::OPFLAG: { // Connection m_OPPart = make_unique(move(header)); } break; case Message::ConnectAnswer::OPFLAG: { m_OPPart = make_unique(move(header)); } break; case Disconnect::OPFLAG: { m_OPPart = make_unique(move(header)); } break; case Watchdog::OPFLAG: { m_OPPart = make_unique(move(header)); } break; case WatchdogAnswer::OPFLAG: { m_OPPart = make_unique(move(header)); } break; case ReportProject::OPFLAG: { // SpitProject m_OPPart = make_unique(move(header)); } break; case CloseProject::OPFLAG: { m_OPPart = make_unique(move(header)); } break; case RequestProjectTransfer::OPFLAG: { m_OPPart = make_unique(move(header)); } break; case StartProjectTransfer::OPFLAG: { m_OPPart = make_unique(move(header)); } break; case EndProjectTransfer::OPFLAG: { m_OPPart = make_unique(move(header)); } break; case ReportType::OPFLAG: { // SpitType m_OPPart = make_unique(move(header)); } break; case RemoveType::OPFLAG: { m_OPPart = make_unique(move(header)); } break; case ReportObject::OPFLAG: { // SpitObject m_OPPart = make_unique(move(header)); } break; case RemoveObject::OPFLAG: { m_OPPart = make_unique(move(header)); } break; case PlayStart::OPFLAG: { // PlaySpitObjects m_OPPart = make_unique(move(header)); } break; case PlayObject::OPFLAG: { m_OPPart = make_unique(move(header)); } break; case PlayEnd::OPFLAG: { m_OPPart = make_unique(move(header)); } break; case ReportPlayStatus::OPFLAG: { m_OPPart = make_unique(move(header)); } break; default: return false; } return m_OPPart->parse(message); } //---------- Send ---------- std::vector Message::createMessage(OPPart &p_OPPart) { if (!p_OPPart.getHeader()) { return {}; } try { int totalSize = Header::BYTESLENGTH + p_OPPart.getBytesCount(); std::vector msgByts(totalSize); p_OPPart.fillBytes(msgByts); return msgByts; } catch (...) { ESP_LOGE(TAG, "Failed to allocate memory"); } return {}; } //----------- Header ----------- Message::Header::Header(const Header &orig) { mID = &SPITID[0]; mMessageNumber = orig.getMessageNumber(); mServerID = orig.getServerID(); mClientID = orig.getClientID(); } Message::Header::Header() { mID = &SPITID[0]; } bool Message::Header::parse(const std::vector &message) { try { mParseOffset = 0; auto strID = getString(message, mParseOffset, 7).value(); if (strID != SPITID) { return false; } auto iVer = getInt(message, mParseOffset).value(); if (iVer < 0) { return false; } mMessageNumber = getByte(message, mParseOffset).value(); mBytesCount = getInt(message, mParseOffset).value(); if (mBytesCount < 0) { return false; } mServerID = getString(message, mParseOffset, 41).value(); mClientID = getString(message, mParseOffset, 41).value(); mOpFlag = message[mParseOffset++] & 0xFF; } catch (...) { ESP_LOGE(TAG, "failed to parse Header"); return false; } return true; } // Send Message::Header::Header(int p_SPITVersion, int p_OPFlag) { mID = &SPITID[0]; mVersion = p_SPITVersion; mOpFlag = p_OPFlag; } bool Message::Header::fillBytes(std::vector &message) { try { mParseOffset = 0; mParseOffset += setString(mID, message, mParseOffset, 7); mParseOffset += setInt(SPITVERSION, message, mParseOffset); mParseOffset += setByte(mMessageNumber, message, mParseOffset); mParseOffset += setInt(mBytesCount, message, mParseOffset); mParseOffset += setString(mServerID, message, mParseOffset, 41); mParseOffset += setString(mClientID, message, mParseOffset, 41); mParseOffset += setByte(mOpFlag, message, mParseOffset); } catch (...) { ESP_LOGE(TAG, "failed to create Header"); return false; } return true; } //----------- OPPart ----------- Message::OPPart::~OPPart() { } // Receive Message::OPPart::OPPart(unique_ptr
p_Header, int p_OPFlag, int size) : mHeader(move(p_Header)), mBytesCount(size) { if (!mHeader) { mParseOffset = Header::BYTESLENGTH; mHeader->setOPFlag(p_OPFlag); } } void Message::OPPart::setHeader(int opFlag) { mHeader = make_unique
(SPITVERSION, opFlag); mParseOffset = Header::BYTESLENGTH; } // Send Message::OPPart::OPPart(int size) : mBytesCount(size) {} //--------------------------- Connection -------------------------------- //----------- Connect ----------- // Receive Message::Connect::Connect(unique_ptr
p_Header) : OPPart(move(p_Header), OPFLAG, BYTESLENGTH) { } bool Message::Connect::parse(const std::vector &message) { if (!mHeader) { return false; } int intOPFlag = mHeader->getType(); if (intOPFlag != OPFLAG) return false; try { mParseOffset = Header::BYTESLENGTH; mBytesCount = getInt(message, mParseOffset).value(); m_ClientComputerName = getString(message, mParseOffset, 64).value(); m_ClientName = getString(message, mParseOffset, 64).value(); m_LoginName = getString(message, mParseOffset, 64).value(); m_LoginPassword = getString(message, mParseOffset, 64).value(); m_ServerIP = getString(message, mParseOffset, 40).value(); m_ServerPort = getInt(message, mParseOffset).value(); } catch (...) { ESP_LOGE(TAG, "failed to parse Connect message"); return false; } return true; } // Send Message::Connect::Connect(string p_ComputerName, string p_ClientName) : OPPart(BYTESLENGTH), m_ClientComputerName(p_ComputerName), m_ClientName(p_ClientName) { setHeader(OPFLAG); mParseOffset = Header::BYTESLENGTH; } void Message::Connect::setServerPort(int p_ServerPort) { if (p_ServerPort < 0 || p_ServerPort > 65535) p_ServerPort = 0; m_ServerPort = p_ServerPort; } bool Message::Connect::fillBytes(std::vector &message) { if (!mHeader) { return false; } if (mHeader->fillBytes(message) == false) return false; try { mParseOffset = Header::BYTESLENGTH; mParseOffset += setInt(mBytesCount, message, mParseOffset); mParseOffset += setString(m_ClientComputerName, message, mParseOffset, 64); mParseOffset += setString(m_ClientName, message, mParseOffset, 64); mParseOffset += setString(m_LoginName, message, mParseOffset, 64); mParseOffset += setString(m_LoginPassword, message, mParseOffset, 64); mParseOffset += setString(m_ServerIP, message, mParseOffset, 40); mParseOffset += setInt(m_ServerPort, message, mParseOffset); } catch (...) { ESP_LOGE(TAG, "failed to create Connect message"); return false; } return true; } //----------- ConnectAnswer ----------- // Receive Message::ConnectAnswer::ConnectAnswer(unique_ptr
p_Header) : OPPart(move(p_Header), OPFLAG, BYTESLENGTH) {} bool Message::ConnectAnswer::parse(const std::vector &message) { if (!mHeader) { return false; } int intOPFlag = mHeader->getType(); if (intOPFlag != OPFLAG) return false; try { mParseOffset = Header::BYTESLENGTH; mBytesCount = getInt(message, mParseOffset).value(); m_ServerComputerName = getString(message, mParseOffset, 64).value(); m_ServerName = getString(message, mParseOffset, 64).value(); m_StepTime = getInt(message, mParseOffset).value(); m_Connected = getBoolean(message, mParseOffset).value(); } catch (...) { ESP_LOGE(TAG, "failed to parse ConnectAnswer message"); return false; } return true; } // Send Message::ConnectAnswer::ConnectAnswer() : OPPart(BYTESLENGTH) { setHeader(OPFLAG); mParseOffset = Header::BYTESLENGTH; } void Message::ConnectAnswer::setStepTime(int p_StepTime_ms) { if (p_StepTime_ms < 0) p_StepTime_ms = 1; m_StepTime = p_StepTime_ms; } bool Message::ConnectAnswer::fillBytes(std::vector &message) { if (!mHeader) { return false; } if (mHeader->fillBytes(message) == false) return false; try { mParseOffset = Header::BYTESLENGTH; mParseOffset += setInt(mBytesCount, message, mParseOffset); mParseOffset += setString(m_ServerComputerName, message, mParseOffset, 64); mParseOffset += setString(m_ServerName, message, mParseOffset, 64); mParseOffset += setInt(m_StepTime, message, mParseOffset); mParseOffset += setBoolean(m_Connected, message, mParseOffset); } catch (...) { ESP_LOGE(TAG, "failed to create ConnectAnswer message"); return false; } return true; } //----------- Disconnect ----------- // Receive Message::Disconnect::Disconnect(unique_ptr
p_Header) : OPPart(move(p_Header), OPFLAG, BYTESLENGTH) { } bool Message::Disconnect::parse(const std::vector &message) { if (!mHeader) { return false; } int intOPFlag = mHeader->getType(); if (intOPFlag != OPFLAG) return false; try { mParseOffset = Header::BYTESLENGTH; mBytesCount = getInt(message, mParseOffset).value(); } catch (...) { ESP_LOGE(TAG, "failed to parse Disconnect message"); return false; } return true; } // Send Message::Disconnect::Disconnect() : OPPart(BYTESLENGTH) { setHeader(OPFLAG); } bool Message::Disconnect::fillBytes(std::vector &message) { if (!mHeader) { return false; } if (mHeader->fillBytes(message) == false) return false; try { mParseOffset = Header::BYTESLENGTH; mParseOffset += setInt(mBytesCount, message, mParseOffset); } catch (...) { ESP_LOGE(TAG, "failed to create Disconnect message"); return false; } return true; } //----------- Watchdog ----------- // Receive Message::Watchdog::Watchdog(unique_ptr
p_Header) : OPPart(move(p_Header), OPFLAG, BYTESLENGTH) { } bool Message::Watchdog::parse(const std::vector &message) { if (!mHeader) { return false; } int intOPFlag = mHeader->getType(); if (intOPFlag != OPFLAG) return false; try { mParseOffset = Header::BYTESLENGTH; mBytesCount = getInt(message, mParseOffset).value(); } catch (...) { ESP_LOGE(TAG, "failed to parse Watchdog message"); return false; } return true; } // Send Message::Watchdog::Watchdog() : OPPart(BYTESLENGTH) { setHeader(OPFLAG); mParseOffset = Header::BYTESLENGTH; } bool Message::Watchdog::fillBytes(std::vector &message) { if (!mHeader) { return false; } if (mHeader->fillBytes(message) == false) return false; try { mParseOffset = Header::BYTESLENGTH; mParseOffset += setInt(mBytesCount, message, mParseOffset); } catch (...) { ESP_LOGE(TAG, "failed to create Watchdog message"); return false; } return true; } //----------- WatchdogAnswer ----------- // Receive Message::WatchdogAnswer::WatchdogAnswer(unique_ptr
p_Header) : OPPart(move(p_Header), OPFLAG, BYTESLENGTH) { } bool Message::WatchdogAnswer::parse(const std::vector &message) { if (!mHeader) { return false; } int intOPFlag = mHeader->getType(); if (intOPFlag != OPFLAG) return false; try { mParseOffset = Header::BYTESLENGTH; mBytesCount = getInt(message, mParseOffset).value(); } catch (...) { ESP_LOGE(TAG, "failed to parse WatchdogAnswer message"); return false; } return true; } // Send Message::WatchdogAnswer::WatchdogAnswer() : OPPart(BYTESLENGTH) { setHeader(OPFLAG); mParseOffset = Header::BYTESLENGTH; } bool Message::WatchdogAnswer::fillBytes(std::vector &message) { if (!mHeader) { return false; } if (mHeader->fillBytes(message) == false) return false; try { mParseOffset = Header::BYTESLENGTH; mParseOffset += setInt(mBytesCount, message, mParseOffset); } catch (...) { ESP_LOGE(TAG, "failed to create WatchdogAnswer message"); return false; } return true; } //--------------------------- SPITProject -------------------------------- //----------- ReportProject ----------- // Receive Message::ReportProject::ReportProject(unique_ptr
p_Header) : OPPart(move(p_Header), OPFLAG, BYTESLENGTH) { } bool Message::ReportProject::parse(const std::vector &message) { if (!mHeader) { return false; } int intOPFlag = mHeader->getType(); if (intOPFlag != OPFLAG) return false; try { mParseOffset = Header::BYTESLENGTH; mBytesCount = getInt(message, mParseOffset).value(); m_ProjectID = getString(message, mParseOffset, 41).value(); m_ProjectName = getString(message, mParseOffset, 64).value(); m_FramesPerSecond = getInt(message, mParseOffset).value(); } catch (...) { ESP_LOGE(TAG, "failed to parse ReportProject message"); return false; } return true; } // Send Message::ReportProject::ReportProject(string p_ProjectID, string p_ProjectName) : OPPart(BYTESLENGTH), m_ProjectID(p_ProjectID), m_ProjectName(p_ProjectName) { setHeader(OPFLAG); mParseOffset = Header::BYTESLENGTH; } bool Message::ReportProject::fillBytes(std::vector &message) { if (!mHeader) { return false; } if (mHeader->fillBytes(message) == false) return false; try { mParseOffset = Header::BYTESLENGTH; mParseOffset += setInt(mBytesCount, message, mParseOffset); mParseOffset += setString(m_ProjectID, message, mParseOffset, 41); mParseOffset += setString(m_ProjectName, message, mParseOffset, 64); mParseOffset += setInt(m_FramesPerSecond, message, mParseOffset); } catch (...) { ESP_LOGE(TAG, "failed to create ReportProject message"); return false; } return true; } //----------- StartProjectTransfer ----------- // Receive Message::CloseProject::CloseProject(unique_ptr
p_Header) : OPPart(move(p_Header), OPFLAG, BYTESLENGTH) { } bool Message::CloseProject::parse(const std::vector &message) { if (!mHeader) { return false; } int intOPFlag = mHeader->getType(); if (intOPFlag != OPFLAG) return false; try { mParseOffset = Header::BYTESLENGTH; mBytesCount = getInt(message, mParseOffset).value(); m_ProjectID = getString(message, mParseOffset, 41).value(); } catch (...) { ESP_LOGE(TAG, "failed to parse CloseProject message"); return false; } return true; } // Send Message::CloseProject::CloseProject(string projectID) : OPPart(BYTESLENGTH), m_ProjectID(projectID) { setHeader(OPFLAG); mParseOffset = Header::BYTESLENGTH; } bool Message::CloseProject::fillBytes(std::vector &message) { if (!mHeader) { return false; } if (mHeader->fillBytes(message) == false) return false; try { mParseOffset = Header::BYTESLENGTH; mParseOffset += setInt(mBytesCount, message, mParseOffset); mParseOffset += setString(m_ProjectID, message, mParseOffset, 41); } catch (...) { ESP_LOGE(TAG, "failed to create CloseProject message"); return false; } return true; } //----------- RequestProjectTransfer ----------- // Receive Message::RequestProjectTransfer::RequestProjectTransfer(unique_ptr
p_Header) : OPPart(move(p_Header), OPFLAG, BYTESLENGTH) { } bool Message::RequestProjectTransfer::parse(const std::vector &message) { if (!mHeader) { return false; } int intOPFlag = mHeader->getType(); if (intOPFlag != OPFLAG) return false; try { mParseOffset = Header::BYTESLENGTH; mBytesCount = getInt(message, mParseOffset).value(); } catch (...) { ESP_LOGE(TAG, "failed to parse RequestProjectTransfer message"); return false; } return true; } // Send Message::RequestProjectTransfer::RequestProjectTransfer() : OPPart(BYTESLENGTH) { setHeader(OPFLAG); mParseOffset = Header::BYTESLENGTH; } bool Message::RequestProjectTransfer::fillBytes(std::vector &message) { if (!mHeader) { return false; } if (mHeader->fillBytes(message) == false) return false; try { mParseOffset = Header::BYTESLENGTH; mParseOffset += setInt(mBytesCount, message, mParseOffset); } catch (...) { ESP_LOGE(TAG, "failed to create RequestProjectTransfer message"); return false; } return true; } //----------- StartProjectTransfer ----------- // Receive Message::StartProjectTransfer::StartProjectTransfer(unique_ptr
p_Header) : OPPart(move(p_Header), OPFLAG, BYTESLENGTH) { } bool Message::StartProjectTransfer::parse(const std::vector &message) { if (!mHeader) { return false; } int intOPFlag = mHeader->getType(); if (intOPFlag != OPFLAG) return false; try { mParseOffset = Header::BYTESLENGTH; mBytesCount = getInt(message, mParseOffset).value(); } catch (...) { ESP_LOGE(TAG, "failed to parse StartProjectTransfer message"); return false; } return true; } // Send Message::StartProjectTransfer::StartProjectTransfer() : OPPart(BYTESLENGTH) { setHeader(OPFLAG); mParseOffset = Header::BYTESLENGTH; } bool Message::StartProjectTransfer::fillBytes(std::vector &message) { if (!mHeader) { return false; } if (mHeader->fillBytes(message) == false) return false; try { mParseOffset = Header::BYTESLENGTH; mParseOffset += setInt(mBytesCount, message, mParseOffset); } catch (...) { ESP_LOGE(TAG, "failed to create StartProjectTransfer message"); return false; } return true; } //----------- ENdProjectTransfer ----------- // Receive Message::EndProjectTransfer::EndProjectTransfer(unique_ptr
p_Header) : OPPart(move(p_Header), OPFLAG, BYTESLENGTH) { } bool Message::EndProjectTransfer::parse(const std::vector &message) { if (!mHeader) { return false; } int intOPFlag = mHeader->getType(); if (intOPFlag != OPFLAG) return false; try { mParseOffset = Header::BYTESLENGTH; mBytesCount = getInt(message, mParseOffset).value(); } catch (...) { ESP_LOGE(TAG, "failed to parse EndProjectTransfer message"); return false; } return true; } // Send Message::EndProjectTransfer::EndProjectTransfer() : OPPart(BYTESLENGTH) { setHeader(OPFLAG); mParseOffset = Header::BYTESLENGTH; } bool Message::EndProjectTransfer::fillBytes(std::vector &message) { if (!mHeader) { return false; } if (mHeader->fillBytes(message) == false) return false; try { mParseOffset = Header::BYTESLENGTH; mParseOffset += setInt(mBytesCount, message, mParseOffset); } catch (...) { ESP_LOGE(TAG, "failed to create EndProjectTransfer message"); return false; } return true; } //--------------------------- SPITType --------------------------------- //----------- ReportType ----------- // Receive Message::ReportType::ReportType(unique_ptr
p_Header) : OPPart(move(p_Header), OPFLAG, BYTESLENGTH) { } bool Message::ReportType::parse(const std::vector &message) { if (!mHeader) { return false; } int intOPFlag = mHeader->getType(); if (intOPFlag != OPFLAG) return false; try { mParseOffset = Header::BYTESLENGTH; mBytesCount = getInt(message, mParseOffset).value(); m_Confirmed = getBoolean(message, mParseOffset).value(); m_SPITTypeID = getString(message, mParseOffset, 41).value(); m_Fixed = getBoolean(message, mParseOffset).value(); m_ServerRemote = getBoolean(message, mParseOffset).value(); m_ServerProjectIndepended = getBoolean(message, mParseOffset).value(); m_SPITTypeGroupName = getString(message, mParseOffset, 39).value(); m_SPITTypeName = getString(message, mParseOffset, 64).value(); m_Delay = getLong(message, mParseOffset).value(); m_Duration = getLong(message, mParseOffset).value(); } catch (...) { ESP_LOGE(TAG, "failed to parse ReportType message"); return false; } return true; } // Send Message::ReportType::ReportType() : OPPart(BYTESLENGTH) { setHeader(OPFLAG); mParseOffset = Header::BYTESLENGTH; } bool Message::ReportType::fillBytes(std::vector &message) { if (!mHeader) { return false; } if (mHeader->fillBytes(message) == false) return false; try { mParseOffset = mHeader->BYTESLENGTH; mParseOffset += setInt(mBytesCount, message, mParseOffset); mParseOffset += setBoolean(m_Confirmed, message, mParseOffset); mParseOffset += setString(m_SPITTypeID, message, mParseOffset, 41); mParseOffset += setBoolean(m_Fixed, message, mParseOffset); mParseOffset += setBoolean(m_ServerRemote, message, mParseOffset); mParseOffset += setBoolean(m_ServerProjectIndepended, message, mParseOffset); mParseOffset += setString(m_SPITTypeGroupName, message, mParseOffset, 39); mParseOffset += setString(m_SPITTypeName, message, mParseOffset, 64); mParseOffset += setLong(m_Delay, message, mParseOffset); mParseOffset += setLong(m_Duration, message, mParseOffset); } catch (...) { ESP_LOGE(TAG, "failed to create ReportType message"); return false; } return true; } //----------- ReportType ----------- // Receive Message::RemoveType::RemoveType(unique_ptr
p_Header) : OPPart(move(p_Header), OPFLAG, BYTESLENGTH) { } bool Message::RemoveType::parse(const std::vector &message) { if (!mHeader) { return false; } int intOPFlag = mHeader->getType(); if (intOPFlag != OPFLAG) return false; try { mParseOffset = Header::BYTESLENGTH; mBytesCount = getInt(message, mParseOffset).value(); m_SPITTypeID = getString(message, mParseOffset, 41).value(); } catch (...) { ESP_LOGE(TAG, "failed to parse RemoveType message"); return false; } return true; } // Send Message::RemoveType::RemoveType() : OPPart(BYTESLENGTH) { setHeader(OPFLAG); mParseOffset = Header::BYTESLENGTH; } bool Message::RemoveType::fillBytes(std::vector &message) { if (!mHeader) { return false; } if (mHeader->fillBytes(message) == false) return false; try { mParseOffset = Header::BYTESLENGTH; mParseOffset += setInt(mBytesCount, message, mParseOffset); mParseOffset += setString(m_SPITTypeID, message, mParseOffset, 41); } catch (...) { ESP_LOGE(TAG, "failed to create RemoveType message"); return false; } return true; } //---------------------------- SPITObjects ---------------------------------- //----------- ReportObject ----------- // Receive Message::ReportObject::ReportObject(unique_ptr
p_Header) : OPPart(move(p_Header), OPFLAG, BYTESLENGTH) { } bool Message::ReportObject::parse(const std::vector &message) { if (!mHeader) { return false; } int intOPFlag = mHeader->getType(); if (intOPFlag != OPFLAG) return false; try { mParseOffset = Header::BYTESLENGTH; mBytesCount = getInt(message, mParseOffset).value(); m_Confirmed = getBoolean(message, mParseOffset).value(); m_SPITObjectID = getString(message, mParseOffset, 41).value(); m_Fixed = getBoolean(message, mParseOffset).value(); m_ServerRemote = getBoolean(message, mParseOffset).value(); m_SPITObjectName = getString(message, mParseOffset, 64).value(); m_SPITTypeID = getString(message, mParseOffset, 41).value(); m_ServerParams = getString(message, mParseOffset, 64).value(); m_FrameStart = getLong(message, mParseOffset).value(); m_FrameLength = getLong(message, mParseOffset).value(); m_FrameFadeInLength = getLong(message, mParseOffset).value(); m_FrameFadeOutLength = getLong(message, mParseOffset).value(); m_ValueFactor = getInt(message, mParseOffset).value(); m_ValueUse = getByte(message, mParseOffset).value(); m_Track = getInt(message, mParseOffset).value(); m_Remark = getString(message, mParseOffset, 64).value(); m_Delay = getLong(message, mParseOffset).value(); m_Duration = getLong(message, mParseOffset).value(); m_ActionAssigned = getBoolean(message, mParseOffset).value(); } catch (...) { ESP_LOGE(TAG, "failed to parse ReportObject message"); return false; } return true; } // Send Message::ReportObject::ReportObject() : OPPart(BYTESLENGTH) { setHeader(OPFLAG); mParseOffset = Header::BYTESLENGTH; } void Message::ReportObject::setDelay(uint64_t p_Delay) { if (p_Delay < 0) p_Delay = 0; m_Delay = p_Delay; } void Message::ReportObject::setDuration(uint64_t p_Duration) { if (p_Duration < 0) p_Duration = 0; m_Duration = p_Duration; } bool Message::ReportObject::fillBytes(std::vector &message) { if (!mHeader) { return false; } if (mHeader->fillBytes(message) == false) return false; try { mParseOffset = Header::BYTESLENGTH; mParseOffset += setInt(mBytesCount, message, mParseOffset); mParseOffset += setBoolean(m_Confirmed, message, mParseOffset); mParseOffset += setString(m_SPITObjectID, message, mParseOffset, 41); mParseOffset += setBoolean(m_Fixed, message, mParseOffset); mParseOffset += setBoolean(m_ServerRemote, message, mParseOffset); mParseOffset += setString(m_SPITObjectName, message, mParseOffset, 64); mParseOffset += setString(m_SPITTypeID, message, mParseOffset, 41); mParseOffset += setString(m_ServerParams, message, mParseOffset, 64); mParseOffset += setLong(m_FrameStart, message, mParseOffset); mParseOffset += setLong(m_FrameLength, message, mParseOffset); mParseOffset += setLong(m_FrameFadeInLength, message, mParseOffset); mParseOffset += setLong(m_FrameFadeOutLength, message, mParseOffset); mParseOffset += setInt(m_ValueFactor, message, mParseOffset); mParseOffset += setByte(m_ValueUse, message, mParseOffset); mParseOffset += setInt(m_Track, message, mParseOffset); mParseOffset += setString(m_Remark, message, mParseOffset, 64); mParseOffset += setLong(m_Delay, message, mParseOffset); mParseOffset += setLong(m_Duration, message, mParseOffset); mParseOffset += setBoolean(m_ActionAssigned, message, mParseOffset); } catch (...) { ESP_LOGE(TAG, "failed to create ReportObject message"); return false; } return true; } //----------- RemoveObject ----------- // Receive Message::RemoveObject::RemoveObject(unique_ptr
p_Header) : OPPart(move(p_Header), OPFLAG, BYTESLENGTH) { } bool Message::RemoveObject::parse(const std::vector &message) { if (!mHeader) { return false; } int intOPFlag = mHeader->getType(); if (intOPFlag != OPFLAG) return false; try { mParseOffset = Header::BYTESLENGTH; mBytesCount = getInt(message, mParseOffset).value(); m_SPITObjectID = getString(message, mParseOffset, 41).value(); } catch (...) { ESP_LOGE(TAG, "failed to parse RemoveObject message"); return false; } return true; } // Send Message::RemoveObject::RemoveObject() : OPPart(BYTESLENGTH) { setHeader(OPFLAG); mParseOffset = Header::BYTESLENGTH; } bool Message::RemoveObject::fillBytes(std::vector &message) { if (!mHeader) { return false; } if (mHeader->fillBytes(message) == false) return false; try { mParseOffset = Header::BYTESLENGTH; mParseOffset += setInt(mBytesCount, message, mParseOffset); mParseOffset += setString(m_SPITObjectID, message, mParseOffset, 41); } catch (...) { ESP_LOGE(TAG, "failed to create RemoveObject message"); return false; } return true; } //---------------------------- SPITPlayer ---------------------------------- //----------- PlayStart ----------- // Receive Message::PlayStart::PlayStart(unique_ptr
p_Header) : OPPart(move(p_Header), OPFLAG, BYTESLENGTH) { } bool Message::PlayStart::parse(const std::vector &message) { if (!mHeader) { return false; } int intOPFlag = mHeader->getType(); if (intOPFlag != OPFLAG) return false; try { mParseOffset = Header::BYTESLENGTH; mBytesCount = getInt(message, mParseOffset).value(); m_PlayerID = getString(message, mParseOffset, 41).value(); m_PlayerName = getString(message, mParseOffset, 64).value(); m_PlayerType = getByte(message, mParseOffset).value(); m_PlayerIsRunning = getBoolean(message, mParseOffset).value(); m_Time = getLong(message, mParseOffset).value(); } catch (...) { ESP_LOGE(TAG, "failed to parse PlayStart message"); return false; } return true; } // Send Message::PlayStart::PlayStart(string p_PlayerID, string p_PlayerName, char p_PlayerType) : OPPart(BYTESLENGTH), m_PlayerID(p_PlayerID), m_PlayerName(p_PlayerName), m_PlayerType(p_PlayerType) { setHeader(OPFLAG); mParseOffset = Header::BYTESLENGTH; } bool Message::PlayStart::fillBytes(std::vector &message) { if (!mHeader) { return false; } if (mHeader->fillBytes(message) == false) return false; try { mParseOffset = Header::BYTESLENGTH; mParseOffset += setInt(mBytesCount, message, mParseOffset); mParseOffset += setString(m_PlayerID, message, mParseOffset, 41); mParseOffset += setString(m_PlayerName, message, mParseOffset, 64); mParseOffset += setByte(m_PlayerType, message, mParseOffset); mParseOffset += setBoolean(m_PlayerIsRunning, message, mParseOffset); mParseOffset += setLong(m_Time, message, mParseOffset); } catch (...) { ESP_LOGE(TAG, "failed to create PlayStart message"); return false; } return true; } //----------- PlayObject ----------- // Receive Message::PlayObject::PlayObject(unique_ptr
p_Header) : OPPart(move(p_Header), OPFLAG, BYTESLENGTH) { } bool Message::PlayObject::parse(const std::vector &message) { if (!mHeader) { return false; } int intOPFlag = mHeader->getType(); if (intOPFlag != OPFLAG) return false; try { mParseOffset = Header::BYTESLENGTH; mBytesCount = getInt(message, mParseOffset).value(); m_PlayerID = getString(message, mParseOffset, 41).value(); m_SPITObjectID = getString(message, mParseOffset, 41).value(); m_FrameInsideObject = getLong(message, mParseOffset).value(); m_PlayPrePosition = getBoolean(message, mParseOffset).value(); m_Value = getInt(message, mParseOffset).value(); m_ValueFlag = getByte(message, mParseOffset).value(); } catch (...) { ESP_LOGE(TAG, "failed to parse PlayObject message"); return false; } return true; } // Send Message::PlayObject::PlayObject() : OPPart(BYTESLENGTH) { setHeader(OPFLAG); mParseOffset = Header::BYTESLENGTH; } bool Message::PlayObject::fillBytes(std::vector &message) { if (!mHeader) { return false; } if (mHeader->fillBytes(message) == false) return false; try { mParseOffset = Header::BYTESLENGTH; mParseOffset += setInt(mBytesCount, message, mParseOffset); mParseOffset += setString(m_PlayerID, message, mParseOffset, 41); mParseOffset += setString(m_SPITObjectID, message, mParseOffset, 41); mParseOffset += setLong(m_FrameInsideObject, message, mParseOffset); mParseOffset += setBoolean(m_PlayPrePosition, message, mParseOffset); mParseOffset += setInt(m_Value, message, mParseOffset); mParseOffset += setByte(m_ValueFlag, message, mParseOffset); } catch (...) { ESP_LOGE(TAG, "failed to create PlayObject message"); return false; } return true; } //----------- PlayEnd ----------- // Receive Message::PlayEnd::PlayEnd(unique_ptr
p_Header) : OPPart(move(p_Header), OPFLAG, BYTESLENGTH) { } bool Message::PlayEnd::parse(const std::vector &message) { if (!mHeader) { return false; } int intOPFlag = mHeader->getType(); if (intOPFlag != OPFLAG) return false; try { mParseOffset = Header::BYTESLENGTH; mBytesCount = getInt(message, mParseOffset).value(); m_PlayerID = getString(message, mParseOffset, 41).value(); } catch (...) { ESP_LOGE(TAG, "failed to parse PlayEnd message"); return false; } return true; } // Send Message::PlayEnd::PlayEnd(string p_PlayerID) : OPPart(BYTESLENGTH), m_PlayerID(p_PlayerID) { setHeader(OPFLAG); mParseOffset = Header::BYTESLENGTH; } bool Message::PlayEnd::fillBytes(std::vector &message) { if (!mHeader) { return false; } if (mHeader->fillBytes(message) == false) return false; try { mParseOffset = Header::BYTESLENGTH; mParseOffset += setInt(mBytesCount, message, mParseOffset); mParseOffset += setString(m_PlayerID, message, mParseOffset, 41); } catch (...) { ESP_LOGE(TAG, "failed to create PlayEnd message"); return false; } return true; } //----------- ReportPlayStatus ----------- // Receive Message::ReportPlayStatus::ReportPlayStatus(unique_ptr
p_Header) : OPPart(move(p_Header), OPFLAG, BYTESLENGTH) { } bool Message::ReportPlayStatus::parse(const std::vector &message) { if (!mHeader) { return false; } int intOPFlag = mHeader->getType(); if (intOPFlag != OPFLAG) return false; try { mParseOffset = Header::BYTESLENGTH; mBytesCount = getInt(message, mParseOffset).value(); m_SPITObjectID = getString(message, mParseOffset, 41).value(); m_FrameInsideObject = getLong(message, mParseOffset).value(); m_Value = getInt(message, mParseOffset).value(); } catch (...) { ESP_LOGE(TAG, "failed to parse ReportPlayStatus message"); return false; } return true; } // Send Message::ReportPlayStatus::ReportPlayStatus() : OPPart(BYTESLENGTH) { setHeader(OPFLAG); mParseOffset = Header::BYTESLENGTH; } void Message::ReportPlayStatus::setID(string p_ID) { m_SPITObjectID = p_ID; } void Message::ReportPlayStatus::setFrameInsideObject(uint64_t p_TimeInside) { m_FrameInsideObject = p_TimeInside; } void Message::ReportPlayStatus::setValue(int p_Value) { m_Value = p_Value; } bool Message::ReportPlayStatus::fillBytes(std::vector &message) { if (!mHeader) { return false; } if (mHeader->fillBytes(message) == false) return false; try { mParseOffset = Header::BYTESLENGTH; mParseOffset += setInt(mBytesCount, message, mParseOffset); mParseOffset += setString(m_SPITObjectID, message, mParseOffset, 41); mParseOffset += setLong(m_FrameInsideObject, message, mParseOffset); mParseOffset += setInt(m_Value, message, mParseOffset); } catch (...) { ESP_LOGE(TAG, "failed to create ReportPlayStatus message"); return false; } return true; } //---------------------------- static helper functions ----------------------- bool Message::isSystemLittleEndian() { // todo replace with #include then if constexpr (std::endian::native == std::endian::big) int intOne = 1; char *firstByte; firstByte = (char *)&intOne; if (*firstByte > 0) { return false; } return true; } optional Message::getInt(const std::vector &message, int &offset) { if (offset < 0 || offset + 4 > message.size()) return std::nullopt; // low byte first int intValue = 0; if (isSystemLittleEndian() == false) { intValue += ((message[offset + 0] & 0x000000ff)); intValue += ((message[offset + 1] & 0x000000ff) << 8); intValue += ((message[offset + 2] & 0x000000ff) << 16); intValue += ((message[offset + 3] & 0x000000ff) << 24); } else { intValue += ((message[offset + 3] & 0x000000ff)); intValue += ((message[offset + 2] & 0x000000ff) << 8); intValue += ((message[offset + 1] & 0x000000ff) << 16); intValue += ((message[offset + 0] & 0x000000ff) << 24); } offset += 4; return intValue; } int Message::setInt(int p_Value, std::vector &message, int p_Offset) { if ((p_Offset < 0) || (message.size() < p_Offset + 4)) throw "ParseError_send"; // low byte first if (isSystemLittleEndian() == false) { message[p_Offset + 0] = (char)(p_Value & 0x000000ff); message[p_Offset + 1] = (char)((p_Value & 0x0000ff00) >> 8); message[p_Offset + 2] = (char)((p_Value & 0x00ff0000) >> 16); message[p_Offset + 3] = (char)((p_Value & 0xff000000) >> 24); } else { message[p_Offset + 3] = (char)(p_Value & 0x000000ff); message[p_Offset + 2] = (char)((p_Value & 0x0000ff00) >> 8); message[p_Offset + 1] = (char)((p_Value & 0x00ff0000) >> 16); message[p_Offset + 0] = (char)((p_Value & 0xff000000) >> 24); } return 4; } optional Message::getLong(const std::vector &message, int &offset) { if (offset < 0 || offset + 8 > message.size()) return std::nullopt; // low byte first uint64_t intValue = 0; if (isSystemLittleEndian() == false) { intValue += ((uint64_t)(message[offset] & 0x000000ff)); intValue += ((uint64_t)(message[offset + 1] & 0x000000ff) << 8); intValue += ((uint64_t)(message[offset + 2] & 0x000000ff) << 16); intValue += ((uint64_t)(message[offset + 3] & 0x000000ff) << 24); intValue += ((uint64_t)(message[offset + 4] & 0x000000ff) << 32); intValue += ((uint64_t)(message[offset + 5] & 0x000000ff) << 40); intValue += ((uint64_t)(message[offset + 6] & 0x000000ff) << 48); intValue += ((uint64_t)(message[offset + 7] & 0x000000ff) << 56); } else { intValue += ((uint64_t)(message[offset + 7] & 0x000000ff)); intValue += ((uint64_t)(message[offset + 6] & 0x000000ff) << 8); intValue += ((uint64_t)(message[offset + 5] & 0x000000ff) << 16); intValue += ((uint64_t)(message[offset + 4] & 0x000000ff) << 24); intValue += ((uint64_t)(message[offset + 3] & 0x000000ff) << 32); intValue += ((uint64_t)(message[offset + 2] & 0x000000ff) << 40); intValue += ((uint64_t)(message[offset + 1] & 0x000000ff) << 48); intValue += ((uint64_t)(message[offset + 0] & 0x000000ff) << 56); } offset += 8; return intValue; } int Message::setLong(uint64_t p_Value, std::vector &message, int p_Offset) { if ((p_Offset < 0) || (message.size() < p_Offset + 8)) throw "ParseError_send"; // low byte first if (isSystemLittleEndian() == false) { message[p_Offset + 0] = (char)((p_Value & 0x00000000000000ff)); message[p_Offset + 1] = (char)((p_Value & 0x000000000000ff00) >> 8); message[p_Offset + 2] = (char)((p_Value & 0x0000000000ff0000) >> 16); message[p_Offset + 3] = (char)((p_Value & 0x00000000ff000000) >> 24); message[p_Offset + 4] = (char)((p_Value & 0x000000ff00000000) >> 32); message[p_Offset + 5] = (char)((p_Value & 0x0000ff0000000000) >> 40); message[p_Offset + 6] = (char)((p_Value & 0x00ff000000000000) >> 48); message[p_Offset + 7] = (char)((p_Value & 0xff00000000000000) >> 56); } else { message[p_Offset + 7] = (char)((p_Value & 0x00000000000000ff)); message[p_Offset + 6] = (char)((p_Value & 0x000000000000ff00) >> 8); message[p_Offset + 5] = (char)((p_Value & 0x0000000000ff0000) >> 16); message[p_Offset + 4] = (char)((p_Value & 0x00000000ff000000) >> 24); message[p_Offset + 3] = (char)((p_Value & 0x000000ff00000000) >> 32); message[p_Offset + 2] = (char)((p_Value & 0x0000ff0000000000) >> 40); message[p_Offset + 1] = (char)((p_Value & 0x00ff000000000000) >> 48); message[p_Offset + 0] = (char)((p_Value & 0xff00000000000000) >> 56); } return 8; } optional Message::getBoolean(const std::vector &message, int &offset) { if (offset < 0 || offset + 1 > message.size()) return std::nullopt; return {message[offset++] > 0x00}; } int Message::setBoolean(bool p_Value, std::vector &message, int p_Offset) { if ((p_Offset < 0) || (message.size() < p_Offset + 1)) throw "ParseError_send"; if (p_Value == false) { message[p_Offset] = 0x00; } else { message[p_Offset] = 0x01; } return 1; } optional Message::getByte(const std::vector &message, int &offset) { if (offset < 0 || offset + 1 > message.size()) return std::nullopt; return {message[offset++]}; } int Message::setByte(int p_Value, std::vector &message, int p_Offset) { if ((p_Offset < 0) || (message.size() < p_Offset + 1)) throw "ParseError_send"; message[p_Offset] = (char)(p_Value & 0xff); return 1; } optional Message::getString(const std::vector &message, int &offset, int maxLength) { if (offset < 0 || offset + maxLength > message.size()) return std::nullopt; size_t len = strnlen(&message[offset], maxLength); if (len >= maxLength) return std::nullopt; string str(&message[offset], len); offset += maxLength; return str; } int Message::setString(string p_String, std::vector &message, int offset, int maxLength) { if ((offset < 0) || (maxLength < 1) || (message.size() < offset + maxLength)) throw "ParseError_send"; int intLength; if (p_String.length() + 1 > maxLength) { intLength = maxLength; } else { intLength = p_String.length() + 1; } int intChar = 0; bool boolNullChar = false; while (intChar < intLength) { message[offset + intChar] = p_String.data()[intChar]; if (p_String[intChar] == '\0') { boolNullChar = true; break; } intChar++; } if (boolNullChar == false) { message[offset + intLength - 1] = '\0'; } return maxLength; } }