处理用户定义的数据包
Simulations often require extended communication, which is not covered by standard packets included in a certain communication standard or protocol (DIS, CIGI, etc.). So, custom (user-defined) packets are needed.模拟通常需要扩展的通信,而某些通信标准或协议(DIS,CIGI等)中包含的标准数据包并未涵盖这些通信。因此,需要自定义(用户定义)的数据包。
Such custom packets make it possible to extend basic functionality and add more flexibility to the system (e.g. when you need to display some avionics data).这种自定义数据包可以扩展基本功能并为系统增加更多的灵活性(例如,当您需要显示一些航空电子数据时)。
UNIGINE IG enables you to define and process custom (user-defined) packets. The workflow is simple and similar for all communication protocols:UNIGINE IG使您能够定义和处理自定义(用户定义)数据包。对于所有通信协议,工作流程都非常简单且相似:
- Set a callback on receiving a certain packet. When IG receives a packet from the network, it creates an object of the appropriate class and passes it to the callback function.在接收到某个数据包时设置回调。 IG从网络接收到数据包时,它将创建适当类的对象,并将其传递给回调函数。
- Inside the callback function, read and interpret the data of the class instance passed to it (depending on what was written to the packet on the host).在回调函数中,读取并解释传递给它的类实例的数据(取决于在主机上写入数据包的内容)。
- Create and send a corresponding response packet, if necessary.如有必要,创建并发送相应的响应数据包。
User-Defined CIGI Packets用户定义的CIGI数据包#
Just like with all other types of packets, to receive user-defined ones, we should add a callback for CIGI_OPCODE >= 201 (in accordance with CIGI ICD). On receiving such a packet, the callback shall be executed with CigiHostUserDefined * packet passed to it.就像所有其他类型的数据包一样,要接收用户定义的数据包,我们应该为CIGI_OPCODE >= 201添加一个回调(根据CIGI ICD)。收到这样的数据包后,回调函数应以CigiHostUserDefined * packet传递给它。
The CigiHostUserDefined class has the getData() method, which returns a set of bytes to be read and interpreted by the user (depending on what was written to the packet on the host).CigiHostUserDefined类具有getData()方法,该方法返回一组要由用户读取和解释的字节(取决于在主机上写入数据包的内容)。
The same situation is with sending packets. First, we ask the CIGIConnector to create a packet with a certain CIGI_OPCODE. If the code is equal to 201 or greater, a CigiIGUserDefined instance shall be returned. You can set bytes to be sent by calling the CigiIGUserDefined::setData() method.发送数据包也是如此。首先,我们要求CIGIConnector创建一个具有特定CIGI_OPCODE的数据包。如果代码等于或大于201,则应返回CigiIGUserDefined实例。您可以通过调用CigiIGUserDefined::setData()方法来设置要发送的字节。
Below is an example of working with user-defined CIGI packets: 以下是使用用户定义的CIGI数据包的示例:
using namespace Plugins;
int AppWorldLogic::init()
{
// ....
int index = Engine::get()->findPlugin("CIGIConnector");
// check CIGIConnector plugin load
if (index != -1)
{
// getting the CIGI interface
cigi = Unigine::Plugins::IG::CIGI::Connector::get();
// adding a callback for OPCODE = 202
cigi->addOnReceivePacketCallback(202, MakeCallback(this, &AppWorldLogic::on_recv_user_packet));
}
return 1;
}
// ....
void AppWorldLogic::on_recv_user_packet(Unigine::Plugins::IG::CIGI::CigiHostPacket * host_packet)
{
Log::error("AppWorldLogic::on_recv_user_packet\n");
CigiHostUserDefined * packet = dynamic_cast<CigiHostUserDefined *>(host_packet);
unsigned char * request_data = packet->getData(); // read
// ...
// creating a new IG user packet with opcode 203
CigiIGPacket * response_packet = cigi->createIGPacket(203);
CigiIGUserDefined * user_defined = dynamic_cast < CigiIGUserDefined *>(response_packet);
user_defined->setData(response_data, size_of_data); // write
cigi->addIGPacket(response_packet);
}
Custom DIS PDUs自定义DIS PDU#
In case of using DIS, custom Protocol Data Units (PDUs) are processed the same way as user-defined CIGI packets.如果使用DIS,则自定义协议数据单元(PDU)的处理方式与用户定义的CIGI数据包。
Below is an example of working with custom PDUs: 以下是使用自定义PDU的示例:
#include <PDU/Header.h>
#include <DataTypes/EntityType.h>
#include <PDU/Entity_Info_Interaction/Entity_State_PDU.h>
using namespace Plugins;
// ...
int AppWorldLogic::init()
{
// ....
int index = Engine::get()->findPlugin("DISConnector");
// check DISConnector plugin load
if (index != -1)
{
// getting the DIS interface
dis = Unigine::Plugins::IG::DIS::Connector::get();
// adding a callback for all packets
dis->addReceivePacketCallback(KDIS::DATA_TYPE::ENUMS::Entity_State_PDU_Type, MakeCallback(this, &AppWorldLogic::on_recv_entitystate_packet));
dis->addReceivePacketCallback(KDIS::DATA_TYPE::ENUMS::Other_PDU_Type, MakeCallback(this, &AppWorldLogic::on_recv_other_packet));
}
return 1;
}
// ....
void AppWorldLogic::on_recv_entitystate_packet(KDIS::PDU::Header *pdu)
{
if (pdu->GetPDUType() == KDIS::DATA_TYPE::ENUMS::Entity_State_PDU_Type)
{
KDIS::PDU::Entity_State_PDU *entity_state_pdu = static_cast<KDIS::PDU::Entity_State_PDU *>(pdu);
auto location = entity_state_pdu->GetEntityLocation();
auto linear_velocity = entity_state_pdu->GetEntityLinearVelocity();
auto appearance = entity_state_pdu->GetEntityAppearance();
// ...
}
}
void AppWorldLogic::on_recv_other_packet(KDIS::PDU::Header *pdu)
{
// ...
}