OpenLCP/protocol/artistic/artnet/packet.cpp

1060 lines
51 KiB
C++
Raw Normal View History

2022-06-08 16:05:06 -04:00
/*
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"
2022-11-28 15:57:52 -05:00
#include "dmx.h"
#include <cstring>
2022-06-08 16:05:06 -04:00
#include <sstream>
namespace ARTNET {
void poll_data::iStream(std::shared_ptr<bufferstream> stream)
2022-06-08 16:05:06 -04:00
{ // Field #
version = stream->get() << 8 | // 3
stream->get(); // 4
if (version < VERSION)
return stream->setstate(std::ios_base::failbit);
*stream >> talk_to_me._raw; // 5
diagnostic_level = static_cast<Priority>(stream->get()); // 6
}
void poll_data::oStream(std::shared_ptr<bufferstream> stream) const
2022-06-08 16:05:06 -04:00
{ // Field #
stream->put(version >> 8); // 3
stream->put(version & 0xff); // 4
*stream << talk_to_me._raw; // 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)
2022-06-08 16:05:06 -04:00
{ // Field #
*stream >> my_ip; // 3
*stream >> udp_port; // 4
version = stream->get() << 8 | // 5
stream->get(); // 6
net_sub_switch.value = stream->get() << 8 | // 7
stream->get() << 4; // 8
oem.word = stream->get() << 8 | // 9
stream->get(); // 10
*stream >> ubea_version; // 11
*stream >> status._raw1; // 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]._raw; // 20
for( size_t i = 0; i < sizeof(good_input) / sizeof(GoodInput); i++)
*stream >> good_input[i]._raw; // 21
for( size_t i = 0; i < sizeof(good_output) / sizeof(GoodOutput); i++)
*stream >> good_output[i]._rawA; // 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._raw; // 26
*stream >> SwRemote._raw; // 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._raw2; // 40
*stream >> good_output->_rawB; // 41
*stream >> status._raw3; // 42
for( size_t i = 0; i < _filler_length; i++)
stream->get(); // 43
}
void pollreply_data::oStream(std::shared_ptr<bufferstream> stream) const
2022-06-08 16:05:06 -04:00
{ // Field #
*stream << my_ip; // 3
*stream << udp_port; // 4
stream->put(version >> 8); // 5
stream->put(version & 0xff); // 6
stream->put(net_sub_switch.value >> 8); // 7
stream->put(net_sub_switch.value >> 4 & 0x0f); // 8
stream->put(oem.word >> 8); // 9
stream->put(oem.word & 0xff); // 10
*stream << ubea_version; // 11
*stream << status._raw1; // 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]._raw; // 20
for( size_t i = 0; i < sizeof(good_input) / sizeof(GoodInput); i++)
*stream << good_input[i]._raw; // 21
for( size_t i = 0; i < sizeof(good_output) / sizeof(GoodOutput); i++)
*stream << good_output[i]._rawA; // 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._raw; // 26
*stream << SwRemote._raw; // 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._raw2; // 40
*stream << good_output->_rawB; // 41
*stream << status._raw3; // 42
for( size_t i = 0; i < _filler_length; i++)
stream->put(0); // 43
}
void ipprog_data::iStream(std::shared_ptr<bufferstream> stream)
2022-06-08 16:05:06 -04:00
{ // 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
2022-06-08 16:05:06 -04:00
{ // 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)
2022-06-08 16:05:06 -04:00
{ // 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
2022-06-08 16:05:06 -04:00
{ // 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)
2022-06-08 16:05:06 -04:00
{ // Field #
version = stream->get() << 8 | // 3
stream->get(); // 4
if (version < VERSION)
return stream->setstate(std::ios_base::failbit);
net_sub_switch.value = stream->get() << 8; // 5
*stream >> bind_index; // 6
stream->readString(short_name, Short_Name_Length); // 7
stream->readString(long_name, Long_Name_Length); // 8
for( size_t i = 0; i < sizeof(SwIn); i++)
SwIn[i] = stream->get() & 0x0f; // 9
for( size_t i = 0; i < sizeof(SwOut); i++)
SwOut[i] = stream->get() & 0x0f; // 10
net_sub_switch.value |= stream->get() << 4; // 11
*stream >> SwVideo; // 12
command = static_cast<AddressCommand>(stream->get()); // 13
}
void address_data::oStream(std::shared_ptr<bufferstream> stream) const
2022-06-08 16:05:06 -04:00
{ // Field #
stream->put(version >> 8); // 3
stream->put(version & 0xff); // 4
stream->put(net_sub_switch.value >> 8); // 5
*stream << bind_index; // 6
stream->writeString(short_name, Short_Name_Length, true); // 7
stream->writeString(long_name, Long_Name_Length, true); // 8
for( size_t i = 0; i < sizeof(SwIn); i++)
stream->put(SwIn[i] &0x0f); // 9
for( size_t i = 0; i < sizeof(SwOut); i++)
stream->put(SwOut[i] &0x0f); // 10
stream->put(net_sub_switch.value >> 4 & 0x0f); // 11
*stream << SwVideo; // 12
*stream << command; // 13
}
void diagdata_data::iStream(std::shared_ptr<bufferstream> stream)
2022-06-08 16:05:06 -04:00
{ // 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
2022-06-08 16:05:06 -04:00
{ // 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)
2022-06-08 16:05:06 -04:00
{ // 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
2022-06-08 16:05:06 -04:00
{ // 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)
2022-06-08 16:05:06 -04:00
{ // 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
2022-06-08 16:05:06 -04:00
{ // 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)
2022-06-08 16:05:06 -04:00
{ // 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.word = 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
2022-06-08 16:05:06 -04:00
{ // Field #
stream->put(version >> 8); // 3
stream->put(version & 0xff); // 4
stream->put(0); // 5
stream->put(0); // 6
stream->put(oem.word >> 8); // 7
stream->put(oem.word & 0xff); // 8
*stream << key; // 9
*stream << subkey; // 10
stream->write(data, sizeof(data)); // 11
}
void dmx_data::iStream(std::shared_ptr<bufferstream> stream)
2022-06-08 16:05:06 -04:00
{ // 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
2022-06-08 16:05:06 -04:00
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
2022-06-08 16:05:06 -04:00
{ // 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)
2022-06-08 16:05:06 -04:00
{ // 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
2022-06-08 16:05:06 -04:00
{ // 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)
2022-06-08 16:05:06 -04:00
{ // 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
2022-06-08 16:05:06 -04:00
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
2022-06-08 16:05:06 -04:00
{ // 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)
2022-06-08 16:05:06 -04:00
{ // 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
2022-06-08 16:05:06 -04:00
{ // 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)
2022-06-08 16:05:06 -04:00
{ // 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
2022-06-08 16:05:06 -04:00
{ // 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)
2022-06-08 16:05:06 -04:00
{ // 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
2022-06-08 16:05:06 -04:00
{ // 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)
2022-06-08 16:05:06 -04:00
{ // 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++)
2023-05-20 13:19:17 -04:00
universes.push_back(PortAddress{.net=net, .subuni=stream->readType<uint8_t>()}); // 17
2022-06-08 16:05:06 -04:00
}
void todrequest_data::oStream(std::shared_ptr<bufferstream> stream) const
2022-06-08 16:05:06 -04:00
{ // 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)
2022-06-08 16:05:06 -04:00
{ // 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
2022-06-08 16:05:06 -04:00
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
2022-06-08 16:05:06 -04:00
{ // 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)
2022-06-08 16:05:06 -04:00
{ // 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
2022-06-08 16:05:06 -04:00
command = static_cast<RDM::TodControlCommand>(stream->get()); // 15
*stream >> universe.subuni; // 16
}
void todcontrol_data::oStream(std::shared_ptr<bufferstream> stream) const
2022-06-08 16:05:06 -04:00
{ // 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)
2022-06-08 16:05:06 -04:00
{ // 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
2022-06-08 16:05:06 -04:00
command = static_cast<RDM::RdmCommand>(stream->get()); // 15
*stream >> universe.subuni; // 16
data.reserve(stream->available() + 1);
2023-05-18 14:39:05 -04:00
while (stream->available())
2022-06-08 16:05:06 -04:00
data.push_back(stream->get()); // 17
}
void rdm_data::oStream(std::shared_ptr<bufferstream> stream) const
2022-06-08 16:05:06 -04:00
{ // 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)
2022-06-08 16:05:06 -04:00
{ // 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
2022-06-08 16:05:06 -04:00
{ // 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)
2022-06-08 16:05:06 -04:00
{
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::failbit);
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:
createData<poll_data>(stream);
break;
case OpPollReply:
createData<pollreply_data>(stream);
break;
case OpIpProg:
createData<ipprog_data>(stream);
break;
case OpIpProgReply:
createData<ipprogreply_data>(stream);
break;
case OpAddress:
createData<address_data>(stream);
break;
case OpDiagData:
createData<diagdata_data>(stream);
break;
case OpTimeCode:
createData<timecode_data>(stream);
break;
case OpCommand:
createData<command_data>(stream);
break;
case OpTrigger:
createData<trigger_data>(stream);
break;
case OpDmx:
createData<dmx_data>(stream);
break;
case OpSync:
createData<sync_data>(stream);
break;
case OpNzs:
{
createData<nzs_data>(stream);
if (!_data)
break;
#ifdef RTTI_ENABLED
auto data = std::dynamic_pointer_cast<nzs_data>(_data);
#else
auto data = std::static_pointer_cast<nzs_data>(_data);
#endif
if (data->data[0] == VLC::START_CODE)
_data = std::make_shared<vlc_data>(data.get());
}
break;
case OpInput:
createData<input_data>(stream);
break;
case OpFirmwareMaster:
createData<firmwaremaster_data>(stream);
break;
case OpFirmwareReply:
createData<firmwarereply_data>(stream);
break;
case OpTodRequest:
createData<todrequest_data>(stream);
break;
case OpTodData:
createData<toddata_data>(stream);
break;
case OpTodControl:
createData<todcontrol_data>(stream);
break;
case OpRdm:
createData<rdm_data>(stream);
break;
case OpRdmSub:
createData<rdmsub_data>(stream);
break;
default:
break;
}
}
/**
* @brief packet::oStream
*
* Write a packet to the network.
*
* @param stream
*/
void Packet::oStream(std::shared_ptr<bufferstream> stream) const
2022-06-08 16:05:06 -04:00
{
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