1
0
Fork 0
OpenLCP/protocol/artistic/artnet/packet.cpp

1048 lines
51 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
packet.cpp
Copyright (c) 2022 Kevin Matz (kevin.matz@gmail.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "packet.h"
#include "dmx.h"
#include <cstring>
#include <sstream>
namespace ARTNET {
void poll_data::iStream(std::shared_ptr<bufferstream> stream)
{ // Field #
version = stream->get() << 8 | // 3
stream->get(); // 4
if (version < VERSION)
return stream->setstate(std::ios_base::failbit);
*stream >> talk_to_me.value; // 5
diagnostic_level = static_cast<Priority>(stream->get()); // 6
}
void poll_data::oStream(std::shared_ptr<bufferstream> stream) const
{ // Field #
stream->put(version >> 8); // 3
stream->put(version & 0xff); // 4
*stream << talk_to_me.value; // 5
*stream << diagnostic_level; // 6
}
/**
* @brief ArtPollReply::set_report
* @param code
* @param count
* @param text
*/
void pollreply_data::set_report(NodeReport code, uint count, std::string text)
{
std::ostringstream report;
std::ostringstream codestr;
codestr << "#";
codestr.width(4);
codestr.fill('0');
codestr << std::ios::hex << code;
report << codestr.str();
report << " ";
report << count;
report << " ";
report << text;
_node_report = report.str();
_node_report.resize(Node_Report_Length - 1);
};
void pollreply_data::iStream(std::shared_ptr<bufferstream> stream)
{ // Field #
*stream >> my_ip; // 3
*stream >> udp_port; // 4
fw_version = stream->get() << 8 | // 5
stream->get(); // 6
net_sub_switch.value = stream->get() << 8 | // 7
stream->get() << 4; // 8
oem.value = stream->get() << 8 | // 9
stream->get(); // 10
*stream >> ubea_version; // 11
*stream >> status.value1; // 12
esta_manufacturer = stream->get() | // 13
stream->get() << 8; // 14
stream->readString(short_name, Short_Name_Length); // 15
stream->readString(long_name, Long_Name_Length); // 16
stream->readString(_node_report, Node_Report_Length); // 17
num_ports = stream->get() << 8 | // 18
stream->get(); // 19
for( size_t i = 0; i < sizeof(port_types) / sizeof(PortTypes); i++)
*stream >> port_types[i].value; // 20
for( size_t i = 0; i < sizeof(good_input) / sizeof(GoodInput); i++)
*stream >> good_input[i].value; // 21
for( size_t i = 0; i < sizeof(good_output) / sizeof(GoodOutput); i++)
*stream >> good_output[i].valueA; // 22
for( size_t i = 0; i < sizeof(SwIn); i++)
SwIn[i] = stream->get() & 0x0f; // 23
for( size_t i = 0; i < sizeof(SwOut); i++)
SwOut[i] = stream->get() & 0x0f; // 24
*stream >> SwVideo; // 25
*stream >> SwMacro.value; // 26
*stream >> SwRemote.value; // 27
stream->get(); // 28
stream->get(); // 29
stream->get(); // 30
style = static_cast<Style>(stream->get()); // 31
for( size_t i = sizeof(mac_address); i > 0; i--)
*stream >> mac_address[i-1]; // 32-37
*stream >> bind_ip; // 38
*stream >> bind_index; // 39
*stream >> status.value2; // 40
*stream >> good_output->valueB; // 41
*stream >> status.value3; // 42
for( size_t i = 0; i < _filler_length; i++)
stream->get(); // 43
}
void pollreply_data::oStream(std::shared_ptr<bufferstream> stream) const
{ // Field #
*stream << my_ip; // 3
*stream << udp_port; // 4
stream->put(fw_version >> 8); // 5
stream->put(fw_version & 0xff); // 6
stream->put(net_sub_switch.value >> 8); // 7
stream->put(net_sub_switch.value >> 4 & 0x0f); // 8
stream->put(oem.value >> 8); // 9
stream->put(oem.value & 0xff); // 10
*stream << ubea_version; // 11
*stream << status.value1; // 12
stream->put(esta_manufacturer & 0xff); // 13
stream->put(esta_manufacturer >> 8); // 14
stream->writeString(short_name, Short_Name_Length, true); // 15
stream->writeString(long_name, Long_Name_Length, true); // 16
stream->writeString(_node_report, Node_Report_Length, true); // 17
stream->put(num_ports >> 8); // 18
stream->put(num_ports & 0xff); // 19
for( size_t i = 0; i < sizeof(port_types) / sizeof(PortTypes); i++)
*stream << port_types[i].value; // 20
for( size_t i = 0; i < sizeof(good_input) / sizeof(GoodInput); i++)
*stream << good_input[i].value; // 21
for( size_t i = 0; i < sizeof(good_output) / sizeof(GoodOutput); i++)
*stream << good_output[i].valueA; // 22
for( size_t i = 0; i < sizeof(SwIn); i++)
stream->put(SwIn[i] &0x0f); // 23
for( size_t i = 0; i < sizeof(SwOut); i++)
stream->put(SwOut[i] &0x0f); // 24
*stream << SwVideo; // 25
*stream << SwMacro.value; // 26
*stream << SwRemote.value; // 27
stream->put(0); // 28
stream->put(0); // 29
stream->put(0); // 30
*stream << style; // 31
for( size_t i = sizeof(mac_address); i > 0; i--)
*stream << mac_address[i-1]; // 32-37
*stream << bind_ip; // 38
*stream << bind_index; // 39
*stream << status.value2; // 40
*stream << good_output->valueB; // 41
*stream << status.value3; // 42
for( size_t i = 0; i < _filler_length; i++)
stream->put(0); // 43
}
void ipprog_data::iStream(std::shared_ptr<bufferstream> stream)
{ // Field #
version = stream->get() << 8 | // 3
stream->get(); // 4
if (version < VERSION)
return stream->setstate(std::ios_base::failbit);
stream->get(); // 5
stream->get(); // 6
*stream >> command._raw; // 7
stream->get(); // 8
*stream >> ip_address; // 9-12
*stream >> subnet_mask; // 13-16
*stream >> udp_port; // 17-18
stream->ignore(_spare_length); // 19
}
void ipprog_data::oStream(std::shared_ptr<bufferstream> stream) const
{ // Field #
stream->put(version >> 8); // 3
stream->put(version & 0xff); // 4
stream->put(0); // 5
stream->put(0); // 6
*stream << command._raw; // 7
stream->put(0); // 8
*stream << ip_address; // 9-12
*stream << subnet_mask; // 13-16
*stream << udp_port; // 17-18
for( size_t i = 0; i < _spare_length; i++)
stream->put(0); // 19
}
void ipprogreply_data::iStream(std::shared_ptr<bufferstream> stream)
{ // Field #
version = stream->get() << 8 | // 3
stream->get(); // 4
if (version < VERSION)
return stream->setstate(std::ios_base::failbit);
stream->get(); // 5
stream->get(); // 6
stream->get(); // 7
stream->get(); // 8
*stream >> ip_address; // 9-12
*stream >> subnet_mask; // 13-16
*stream >> udp_port; // 17-18
*stream >> status._raw; // 19
stream->ignore(_spare_length); // 20-26
}
void ipprogreply_data::oStream(std::shared_ptr<bufferstream> stream) const
{ // Field #
stream->put(version >> 8); // 3
stream->put(version & 0xff); // 4
stream->put(0); // 5
stream->put(0); // 6
stream->put(0); // 7
stream->put(0); // 8
*stream << ip_address; // 9-12
*stream << subnet_mask; // 13-16
*stream << udp_port; // 17-18
*stream << status._raw; // 19
for( size_t i = 0; i < _spare_length; i++)
stream->put(0); // 20-26
}
void address_data::iStream(std::shared_ptr<bufferstream> stream)
{ // Field #
version = stream->get() << 8 | // 3
stream->get(); // 4
if (version < VERSION)
return stream->setstate(std::ios_base::failbit);
*stream >> net_switch; // 5
*stream >> bind_index; // 6
stream->readString(short_name, Short_Name_Length); // 7
stream->readString(long_name, Long_Name_Length); // 8
stream->read(SwIn, sizeof(SwIn)); // 9
stream->read(SwOut, sizeof(SwOut)); // 10
*stream >> sub_switch; // 11
*stream >> SwVideo; // 12
command = static_cast<AddressCommand>(stream->get()); // 13
}
void address_data::oStream(std::shared_ptr<bufferstream> stream) const
{ // Field #
stream->put(version >> 8); // 3
stream->put(version & 0xff); // 4
*stream << net_switch; // 5
*stream << bind_index; // 6
stream->writeString(short_name, Short_Name_Length, true); // 7
stream->writeString(long_name, Long_Name_Length, true); // 8
stream->write(SwIn, sizeof(SwIn)); // 9
stream->write(SwOut, sizeof(SwOut)); // 10
*stream << sub_switch; // 11
*stream << SwVideo; // 12
*stream << command; // 13
}
void diagdata_data::iStream(std::shared_ptr<bufferstream> stream)
{ // Field #
version = stream->get() << 8 | // 3
stream->get(); // 4
if (version < VERSION)
return stream->setstate(std::ios_base::failbit);
stream->get(); // 5
priority = static_cast<Priority>(stream->get()); // 6
stream->get(); // 7
stream->get(); // 8
uint16_t length = stream->get() << 8 | // 9
stream->get(); // 10
stream->readString(data, length); // 11
}
void diagdata_data::oStream(std::shared_ptr<bufferstream> stream) const
{ // Field #
stream->put(version >> 8); // 3
stream->put(version & 0xff); // 4
stream->put(0); // 5
*stream << priority; // 6
stream->put(0); // 7
stream->put(0); // 8
uint16_t length = data.length() + 1; // include null terminator
if ( length > _max_data_length )
length = _max_data_length;
stream->put(length >> 8); // 9
stream->put(length & 0xff); // 10
stream->writeString(data, length, true); // 11
}
void timecode_data::iStream(std::shared_ptr<bufferstream> stream)
{ // Field #
version = stream->get() << 8 | // 3
stream->get(); // 4
if (version < VERSION)
return stream->setstate(std::ios_base::failbit);
stream->get(); // 5
stream->get(); // 6
*stream >> time.frame; // 7
*stream >> time.seconds; // 8
*stream >> time.minutes; // 9
*stream >> time.hours; // 10
time.type = static_cast<TimecodeType>(stream->get()); // 11
}
void timecode_data::oStream(std::shared_ptr<bufferstream> stream) const
{ // Field #
stream->put(version >> 8); // 3
stream->put(version & 0xff); // 4
stream->put(0); // 5
stream->put(0); // 6
*stream << time.frame; // 7
*stream << time.seconds; // 8
*stream << time.minutes; // 9
*stream << time.hours; // 10
*stream << time.type; // 11
}
void command_data::iStream(std::shared_ptr<bufferstream> stream)
{ // Field #
version = stream->get() << 8 | // 3
stream->get(); // 4
if (version < VERSION)
return stream->setstate(std::ios_base::failbit);
stream->put(esta_manufacturer & 0xff); // 5
stream->put(esta_manufacturer >> 8); // 6
uint16_t length = stream->get() << 8 | // 7
stream->get(); // 8
stream->readString(data, length); // 9
}
void command_data::oStream(std::shared_ptr<bufferstream> stream) const
{ // Field #
stream->put(version >> 8); // 3
stream->put(version & 0xff); // 4
stream->put(esta_manufacturer & 0xff); // 5
stream->put(esta_manufacturer >> 8); // 6
uint16_t length = data.length() + 1; // include null terminator
if ( length > _max_data_length )
length = _max_data_length;
stream->put(length >> 8); // 7
stream->put(length & 0xff); // 8
stream->writeString(data, length, true); // 9
}
void trigger_data::iStream(std::shared_ptr<bufferstream> stream)
{ // Field #
version = stream->get() << 8 | // 3
stream->get(); // 4
if (version < VERSION)
return stream->setstate(std::ios_base::failbit);
stream->get(); // 5
stream->get(); // 6
oem.value = stream->get() << 8 | // 7
stream->get(); // 8
*stream >> key; // 9
*stream >> subkey; // 10
stream->read(data, sizeof(data)); // 11
}
void trigger_data::oStream(std::shared_ptr<bufferstream> stream) const
{ // Field #
stream->put(version >> 8); // 3
stream->put(version & 0xff); // 4
stream->put(0); // 5
stream->put(0); // 6
stream->put(oem.value >> 8); // 7
stream->put(oem.value & 0xff); // 8
*stream << key; // 9
*stream << subkey; // 10
stream->write(data, sizeof(data)); // 11
}
void dmx_data::iStream(std::shared_ptr<bufferstream> stream)
{ // Field #
version = stream->get() << 8 | // 3
stream->get(); // 4
if (version < VERSION)
return stream->setstate(std::ios_base::failbit);
*stream >> sequence; // 5
*stream >> physical; // 6
*stream >> universe.subuni; // 7
universe.net = stream->readType<uint8_t>(); // 8
uint16_t length = stream->get() << 8 | // 9
stream->get(); // 10
// this value should be an even number in the range 2 512
if ( length % 2 != 0 ||
length < 2 ||
length > DMX::E111_LAST_SLOT )
return stream->setstate(std::ios_base::failbit);
data.reserve(length + 1);
for (int i = 1; i <= length; i++)
data.push_back(stream->get()); // 11
}
void dmx_data::oStream(std::shared_ptr<bufferstream> stream) const
{ // Field #
stream->put(version >> 8); // 3
stream->put(version & 0xff); // 4
*stream << sequence; // 5
*stream << physical; // 6
*stream << universe.subuni; // 7
*stream << universe.net; // 8
uint16_t length = data.size() - 1;
uint16_t datalength = length + (length % 2);
stream->put(datalength >> 8); // 9
stream->put(datalength & 0xff ); // 10
for (int i = 1; i <= length; i++)
stream->put(data.at(i)); // 11
for (int i = 0; i < length % 2; i++)
stream->put(0);
}
void sync_data::iStream(std::shared_ptr<bufferstream> stream)
{ // Field #
version = stream->get() << 8 | // 3
stream->get(); // 4
if (version < VERSION)
return stream->setstate(std::ios_base::failbit);
stream->get(); // 5
stream->get(); // 6
}
void sync_data::oStream(std::shared_ptr<bufferstream> stream) const
{ // Field #
stream->put(version >> 8); // 3
stream->put(version & 0xff); // 4
stream->put(0); // 5
stream->put(0); // 6
}
void nzs_data::iStream(std::shared_ptr<bufferstream> stream)
{ // Field #
version = stream->get() << 8 | // 3
stream->get(); // 4
if (version < VERSION)
return stream->setstate(std::ios_base::failbit);
*stream >> sequence; // 5
data.clear();
data.push_back(stream->get()); // 6
*stream >> universe.subuni; // 7
universe.net = stream->readType<uint8_t>(); // 8
uint16_t length = stream->get() << 8 | // 9
stream->get(); // 10
// this value should be an even number in the range 1 512
if (length < 1 ||
length > DMX::E111_LAST_SLOT )
return stream->setstate(std::ios_base::failbit);
data.reserve(length + 1);
for (int i = 1; i <= length; i++)
data.push_back(stream->get()); // 11
}
void nzs_data::oStream(std::shared_ptr<bufferstream> stream) const
{ // Field #
stream->put(version >> 8); // 3
stream->put(version & 0xff); // 4
*stream << sequence; // 5
*stream << data.at(0); // 6
*stream << universe.subuni; // 7
*stream << universe.net; // 8
uint16_t length = data.size() - 1;
stream->put(length >> 8); // 9
stream->put(length & 0xff ); // 10
for (int i = 1; i <= length; i++)
stream->put(data.at(i)); // 11
}
bool vlc_data::_from_nzs(const nzs_data * other)
{ // Field #
version = other->version;
sequence = other->sequence;
universe = other->universe;
if (other->data.size() < 11) // enough data to read the payload length
return false;
if (other->data[0] != VLC::START_CODE ||
other->data[1] != VLC::MagicNumber[0] || // 11
other->data[2] != VLC::MagicNumber[1] || // 12
other->data[3] != VLC::MagicNumber[2]) // 13
return false;
flags._raw = other->data[4]; // 14
transaction = other->data[5] << 8 | // 15
other->data[6]; // 16
address = other->data[7] << 8 | // 17
other->data[8]; // 18
size_t length = other->data[9] << 8 | // 19
other->data[10]; // 20
if (other->data.size() < 23 + length ||
length > _payload_max_length)
return false;
uint16_t cksm = other->data[11] << 8 | // 21
other->data[12]; // 22
// skip unlucky other->data[13] // 23
depth = other->data[14]; // 24
frequency = other->data[15] << 8 | // 25
other->data[16]; // 26
modulation = other->data[17] << 8 | // 27
other->data[18]; // 28
language = other->data[19] << 8 | // 29
other->data[20]; // 30
beacon_frequency = other->data[21] << 8 | // 31
other->data[22]; // 32
for (size_t i = 0; i < length; i++)
payload.push_back(other->data[23+i]); // 33
if (cksm != _checksum())
return false;
return true;
}
void vlc_data::compile()
{ // Field #
data.insert(data.end(), // 11-13
std::begin(VLC::MagicNumber), std::end(VLC::MagicNumber));
data.push_back(flags._raw); // 14
data.push_back(transaction >> 8); // 15
data.push_back(transaction & 0xff); // 16
data.push_back(address >> 8); // 17
data.push_back(address & 0xff); // 18
uint16_t length = payload.size();
data.push_back(length >> 8); // 19
data.push_back(length & 0xff); // 20
uint16_t chksum = _checksum();
data.push_back(chksum >> 8); // 21
data.push_back(chksum & 0xff); // 22
data.push_back(0); // 23
data.push_back(depth); // 24
data.push_back(frequency >> 8); // 25
data.push_back(frequency & 0xff); // 26
data.push_back(modulation >> 8); // 27
data.push_back(modulation & 0xff); // 28
data.push_back(language >> 8); // 29
data.push_back(language & 0xff); // 30
data.push_back(beacon_frequency >> 8); // 31
data.push_back(beacon_frequency & 0xff); // 32
data.insert(data.end(), payload.begin(), payload.end()); // 33
}
uint16_t vlc_data::_checksum() const
{
/// \todo impliment the real checksum!
return 0;
}
void input_data::iStream(std::shared_ptr<bufferstream> stream)
{ // Field #
version = stream->get() << 8 | // 3
stream->get(); // 4
if (version < VERSION)
return stream->setstate(std::ios_base::failbit);
stream->get(); // 5
*stream >> bind_index; // 6
num_ports = stream->get() << 8 | // 7
stream->get(); // 8
for (size_t i = 0; i < (sizeof(status) / sizeof(InputFlags)); i++)
*stream >> status[i]._raw; // 9
}
void input_data::oStream(std::shared_ptr<bufferstream> stream) const
{ // Field #
stream->put(version >> 8); // 3
stream->put(version & 0xff); // 4
stream->put(0); // 5
*stream << bind_index; // 6
stream->put(num_ports >> 8); // 7
stream->put(num_ports & 0xff); // 8
for (size_t i = 0; i < (sizeof(status) / sizeof(InputFlags)); i++)
*stream << status[i]._raw; // 9
}
void firmwaremaster_data::iStream(std::shared_ptr<bufferstream> stream)
{ // Field #
version = stream->get() << 8 | // 3
stream->get(); // 4
if (version < VERSION)
return stream->setstate(std::ios_base::failbit);
stream->get(); // 5
stream->get(); // 6
type = static_cast<FIRMWARE::MasterType>(stream->get()); // 7
*stream >> block_id; // 8
length = stream->get() << 24 | // 9
stream->get() << 16 | // 10
stream->get() << 8 | // 11
stream->get(); // 12
stream->ignore(_spare_length); // 13
for (size_t i = 0; i < sizeof(block) / sizeof(block[0]); i++)
*stream >> block[i]; // 14
}
void firmwaremaster_data::oStream(std::shared_ptr<bufferstream> stream) const
{ // Field #
stream->put(version >> 8); // 3
stream->put(version & 0xff); // 4
stream->put(0); // 5
stream->put(0); // 6
*stream << type; // 7
*stream << block_id; // 8
stream->put((length >> 24) & 0xff); // 9
stream->put((length >> 16) & 0xff); // 10
stream->put((length >> 8) & 0xff); // 11
stream->put(length & 0xff); // 12
for (size_t i = 0; i < _spare_length; i++)
stream->put(0); // 13
for (size_t i = 0; i < sizeof(block); i++)
*stream << block[i]; // 14
}
void firmwarereply_data::iStream(std::shared_ptr<bufferstream> stream)
{ // Field #
version = stream->get() << 8 | // 3
stream->get(); // 4
if (version < VERSION)
return stream->setstate(std::ios_base::failbit);
stream->get(); // 5
stream->get(); // 6
type = static_cast<FIRMWARE::ResponseType>(stream->get()); // 7
stream->ignore(_spare_length); // 8
}
void firmwarereply_data::oStream(std::shared_ptr<bufferstream> stream) const
{ // Field #
stream->put(version >> 8); // 3
stream->put(version & 0xff); // 4
stream->put(0); // 5
stream->put(0); // 6
*stream << type; // 7
for (size_t i = 0; i < _spare_length; i++)
stream->put(0); // 8
}
void todrequest_data::iStream(std::shared_ptr<bufferstream> stream)
{ // Field #
version = stream->get() << 8 | // 3
stream->get(); // 4
if (version < VERSION)
return stream->setstate(std::ios_base::failbit);
stream->get(); // 5
stream->get(); // 6
stream->get(); // 7
stream->get(); // 8
stream->get(); // 9
stream->get(); // 10
stream->get(); // 11
stream->get(); // 12
stream->get(); // 13
uint8_t net = stream->get(); // 14
if ( stream->get() != RDM::TodFull) // 15
return stream->setstate(std::ios_base::failbit);
uint8_t count = stream->get(); // 16
for (int i = 0; i < count; i++)
universes.push_back(PortAddress{.net=net, .subuni=stream->readType<uint8_t>()}); // 17
}
void todrequest_data::oStream(std::shared_ptr<bufferstream> stream) const
{ // Field #
stream->put(version >> 8); // 3
stream->put(version & 0xff); // 4
stream->put(0); // 5
stream->put(0); // 6
stream->put(0); // 7
stream->put(0); // 8
stream->put(0); // 9
stream->put(0); // 10
stream->put(0); // 11
stream->put(0); // 12
stream->put(0); // 13
stream->put(universes.empty() ? 0 : universes[0].net); // 14
stream->put(RDM::TodFull); // 15
stream->put(universes.size() < _max_count ? universes.size() : _max_count); // 16
for (size_t i = 0; i < universes.size() && i < _max_count; i++ )
stream->put(universes[i].subuni); // 17
}
void toddata_data::iStream(std::shared_ptr<bufferstream> stream)
{ // Field #
version = stream->get() << 8 | // 3
stream->get(); // 4
if (version < VERSION)
return stream->setstate(std::ios_base::failbit);
rdm_version = static_cast<RDM::Version>(stream->get()); // 5
*stream >> port; // 6
stream->get(); // 7
stream->get(); // 8
stream->get(); // 9
stream->get(); // 10
stream->get(); // 11
stream->get(); // 12
*stream >> bind_index; // 13
universe.net = stream->readType<uint8_t>(); // 14
type = static_cast<RDM::TodCommandResponse>(stream->get()); // 15
*stream >> universe.subuni; // 16
*stream >> total_count; // 17-18
*stream >> block_count; // 19
uint8_t count = stream->get(); // 20
uint16_t manufacturer;
uint32_t device;
for (int i = 0; i < count; i++) // 21
{
*stream >> manufacturer;
*stream >> device;
devices.emplace_back(std::make_shared<::RDM::UID>(device, manufacturer));
}
}
void toddata_data::oStream(std::shared_ptr<bufferstream> stream) const
{ // Field #
stream->put(version >> 8); // 3
stream->put(version & 0xff); // 4
stream->put(rdm_version); // 5
*stream << port; // 6
stream->put(0); // 7
stream->put(0); // 8
stream->put(0); // 9
stream->put(0); // 10
stream->put(0); // 11
stream->put(0); // 12
*stream << bind_index; // 13
*stream << universe.net; // 14
*stream << type; // 15
*stream << universe.subuni; // 16
*stream << total_count; // 17-18
*stream << block_count; // 19
stream->put(devices.size()); // 20
for (size_t i = 0; i < devices.size(); i++) { // 21
auto uid = devices.at(i)->uid();
stream->put((uid >> 40) & 0xff);
stream->put((uid >> 32) & 0xff);
stream->put((uid >> 24) & 0xff);
stream->put((uid >> 16) & 0xff);
stream->put((uid >> 8) & 0xff);
stream->put(uid & 0xff);
}
}
void todcontrol_data::iStream(std::shared_ptr<bufferstream> stream)
{ // Field #
version = stream->get() << 8 | // 3
stream->get(); // 4
if (version < VERSION)
return stream->setstate(std::ios_base::failbit);
stream->get(); // 5
stream->get(); // 6
stream->get(); // 7
stream->get(); // 8
stream->get(); // 9
stream->get(); // 10
stream->get(); // 11
stream->get(); // 12
stream->get(); // 13
universe.net = stream->readType<uint8_t>(); // 14
command = static_cast<RDM::TodControlCommand>(stream->get()); // 15
*stream >> universe.subuni; // 16
}
void todcontrol_data::oStream(std::shared_ptr<bufferstream> stream) const
{ // Field #
stream->put(version >> 8); // 3
stream->put(version & 0xff); // 4
stream->put(0); // 5
stream->put(0); // 6
stream->put(0); // 7
stream->put(0); // 8
stream->put(0); // 9
stream->put(0); // 10
stream->put(0); // 11
stream->put(0); // 12
stream->put(0); // 13
*stream << universe.net; // 14
*stream << command; // 15
*stream << universe.subuni; // 16
}
void rdm_data::iStream(std::shared_ptr<bufferstream> stream)
{ // Field #
version = stream->get() << 8 | // 3
stream->get(); // 4
if (version < VERSION)
return stream->setstate(std::ios_base::failbit);
rdm_version = static_cast<RDM::Version>(stream->get()); // 5
stream->get(); // 6
stream->get(); // 7
stream->get(); // 8
stream->get(); // 9
stream->get(); // 10
stream->get(); // 11
stream->get(); // 12
stream->get(); // 13
universe.net = stream->readType<uint8_t>(); // 14
command = static_cast<RDM::RdmCommand>(stream->get()); // 15
*stream >> universe.subuni; // 16
data.reserve(stream->available() + 1);
while (stream->available())
data.push_back(stream->get()); // 17
}
void rdm_data::oStream(std::shared_ptr<bufferstream> stream) const
{ // Field #
stream->put(version >> 8); // 3
stream->put(version & 0xff); // 4
*stream << rdm_version; // 5
stream->put(0); // 6
stream->put(0); // 7
stream->put(0); // 8
stream->put(0); // 9
stream->put(0); // 10
stream->put(0); // 11
stream->put(0); // 12
stream->put(0); // 13
*stream << universe.net; // 14
*stream << command; // 15
*stream << universe.subuni; // 16
for (size_t i = 1; i < data.size(); i++)
*stream << data[i]; // 17
}
void rdmsub_data::iStream(std::shared_ptr<bufferstream> stream)
{ // Field #
version = stream->get() << 8 | // 3
stream->get(); // 4
if (version < VERSION)
return stream->setstate(std::ios_base::failbit);
rdm_version = static_cast<RDM::Version>(stream->get()); // 5
stream->get(); // 6
auto manufacturer = stream->readType<uint16_t>(); // 7
auto device = stream->readType<uint32_t>(); // 7
uid = ::RDM::UID(device, manufacturer);
stream->get(); // 8
*stream >> command_class; // 9
*stream >> pid; // 10
*stream >> subdevice; // 11
auto count = stream->readType<uint16_t>(); // 12
stream->get(); // 13
stream->get(); // 14
stream->get(); // 15
stream->get(); // 16
if (command_class == ::RDM::SET_COMMAND ||
command_class == ::RDM::GET_COMMAND_RESPONSE)
for (uint i = 0; i < count; i++)
data.push_back(stream->readType<uint16_t>()); // 17
}
void rdmsub_data::oStream(std::shared_ptr<bufferstream> stream) const
{ // Field #
stream->put(version >> 8); // 3
stream->put(version & 0xff); // 4
*stream << rdm_version; // 5
stream->put(0); // 6
auto uid_number = uid.uid();
stream->put((uid_number >> 40) & 0xff); // 7
stream->put((uid_number >> 32) & 0xff); // 7
stream->put((uid_number >> 24) & 0xff); // 7
stream->put((uid_number >> 16) & 0xff); // 7
stream->put((uid_number >> 8) & 0xff); // 7
stream->put(uid_number & 0xff); // 7
stream->put(0); // 8
*stream << command_class; // 9
*stream << pid; // 10
*stream << subdevice; // 11
if (command_class == ::RDM::GET_COMMAND ||
command_class == ::RDM::SET_COMMAND_RESPONSE ||
data.empty())
*stream << (uint16_t)1; // 12
else
*stream << (uint16_t)data.size(); // 12
stream->put(0); // 13
stream->put(0); // 14
stream->put(0); // 15
stream->put(0); // 16
if (command_class == ::RDM::SET_COMMAND ||
command_class == ::RDM::GET_COMMAND_RESPONSE)
for (uint i = 0; i < data.size(); i++)
*stream << data[i]; // 17
}
/**
* @brief packet::streamSize
* @return
*/
size_t Packet::streamSize() const
{
return sizeof(PACKET_IDENTIFIER)
+ sizeof(OpCode)
+ _data->streamSize();
}
/**
* @brief packet::iStream
*
* Read a packet from the network.
*
* @param stream
*/
void Packet::iStream(std::shared_ptr<bufferstream> stream)
{
uint8_t identifier[sizeof(PACKET_IDENTIFIER)]; //!< 'A''r''t''-''N''e''t'0x00
// Field #
stream->read(identifier, sizeof(identifier)); // 1
if (stream->gcount() != sizeof(identifier))
return stream->setstate(std::ios_base::badbit);
if (memcmp(identifier, PACKET_IDENTIFIER, sizeof(identifier))) // memcmp returns 0 if matched
return stream->setstate(std::ios_base::failbit);
OpCode opcode = static_cast<OpCode>(stream->readType<uint16_t>()); // 2
switch (opcode) { // 3-...
case OpPoll:
_data = std::make_shared<poll_data>();
break;
case OpPollReply:
_data = std::make_shared<pollreply_data>();
break;
case OpIpProg:
_data = std::make_shared<ipprog_data>();
break;
case OpIpProgReply:
_data = std::make_shared<ipprogreply_data>();
break;
case OpAddress:
_data = std::make_shared<address_data>();
break;
case OpDiagData:
_data = std::make_shared<diagdata_data>();
break;
case OpTimeCode:
_data = std::make_shared<timecode_data>();
break;
case OpCommand:
_data = std::make_shared<command_data>();
break;
case OpTrigger:
_data = std::make_shared<trigger_data>();
break;
case OpDmx:
_data = std::make_shared<dmx_data>();
break;
case OpSync:
_data = std::make_shared<sync_data>();
break;
case OpNzs:
_data = std::make_shared<nzs_data>();
break;
case OpInput:
_data = std::make_shared<input_data>();
break;
case OpFirmwareMaster:
_data = std::make_shared<firmwaremaster_data>();
break;
case OpFirmwareReply:
_data = std::make_shared<firmwarereply_data>();
break;
case OpTodRequest:
_data = std::make_shared<todrequest_data>();
break;
case OpTodData:
_data = std::make_shared<toddata_data>();
break;
case OpTodControl:
_data = std::make_shared<todcontrol_data>();
break;
case OpRdm:
_data = std::make_shared<rdm_data>();
break;
case OpRdmSub:
_data = std::make_shared<rdmsub_data>();
break;
default:
break;
}
if (_data)
_data->iStream(stream);
}
/**
* @brief packet::oStream
*
* Write a packet to the network.
*
* @param stream
*/
void Packet::oStream(std::shared_ptr<bufferstream> stream) const
{
if ( _opcode == OpNull )
return stream->setstate(std::ios_base::failbit);
if ( _data == nullptr )
return stream->setstate(std::ios_base::failbit);
// Field #
stream->write(PACKET_IDENTIFIER, sizeof(PACKET_IDENTIFIER)); // 1
*stream << _opcode; // 2
*stream << _data; // 3-...
}
} // namespace ARTNET