Libraries
define_packet/define_packet.cpp
/*
This example is for a simple, completely made up packet. It has a header,
data, and trailer with all of the packet attributes set. The 'purpose' of
this example is to define the packet and save it to disk. Other examples
will use the saved packet to build and extract the packet. There are other
ways to create packet definitions in TReK (e.g., simple comma delimited
files).
Just for fun here is the packet definition in a small table. All of the
data is 'big endian' except for a single parameter. All sizes are listed
in bits. The data is packed (i.e., there are no gaps). The code below will
set the start location for parameter, but it isn't shown in the table.
Name Data Type Size Notes
Version unsigned integer 4 Should always be zero
PktId unsigned integer 12 For this packet, the value is 54
PktLen unsigned integer 16 Length of packet after this point
PktCnt unsigned integer 8 Packet counter
Time system time 32 A.k.a. DT_UNIX_TIME
IntParam signed integer 16 First data parameter
UintParam unsigned integer 32 Three consecutive values
FloatParam double 64 Little-endian floating point
StrParam string 800 Varible length string
Checksum unsigned integer 32 CRC-32 checksum
*/
#include "packet.h"
#include "parameter.h"
#include <iostream>
using namespace trek;
using namespace std;
int main()
{
//
// NOTE: There is only minimal error checking shown in the code below in
// order to simplify the example. In general, only the first time a
// method is used will the error handling be in this example. You should
// always check the returned value when one is available to ensure proper
// operation of the code. Error handling for this example is to exit on
// error.
//
Packet pkt;
int32_t ret_value;
//
// Need to create the 'zones' for the packet and add it to the packet.
// The general steps for this are:
//
// 1. Initialize the parameter collection
// 2. Initialize the parameter.
// 3. Set the parameter attributes as needed (data type, name, length,
// byte order, start bit, etc.)
// 4. Add the parameter to the collection.
// 5. Repeat steps 2, 3, and 4 until all the parameters are in the
// parameter collection.
// 6. Add the parameter collection into the correct zone.
//
//
// Using the above procedure as a guideline, create the header zone for
// the packet. This will consist of 5 parameters: Version, PktId, PktLen,
// PktCnt, and Time.
//
pc.Init(); // this will clear out any data in the collection
pc.SetName( "MyHeader" ); // not required, but can be useful
p.Init(); // this will clear out any data in the parameter
p.SetName( "Version" );
if( p.SetStartBit( 0 ) )
{
// Currently only will be success, but may return errors at a late
// time.
cout << "Error setting start bit\n";
return 1;
}
{
// There are a lot of return codes for this method. The returned error
// is usually self explanatory, but an attempt at explanation is made
// throughout the documentation.
cout << "Error setting data type\n";
return 1;
}
p.SetModifiableFlag( false ); // don't want this value changed
if( p.SetValue( (uint8_t)0 ) )
{
// If this method fails it is usually because you have a data type
// mismatch or the value won't fit in the data. Since this is a 4-bit
// unsigned integer, any value above 15 will fail.
cout <<"Error setting value\n";
return 1;
}
if( pc.AddParameter( p ) ) // add the parameter to the collection
{
// If this fails, it's most likely because you already have a parameter
// with the same name.
cout << "Error adding parameter\n";
return 1;
}
//
// Time to add the rest of the header parameters...and without error
// checking.
//
p.Init(); // this will clear out any data in the parameter
p.SetName( "PktId" );
p.SetStartBit( 4 ); // Don't forget to set this!
p.SetModifiableFlag( false ); // don't want this value changed
pc.AddParameter( p ); // add the parameter to the collection
p.Init();
p.SetName( "PktLen" );
p.SetStartBit( 16 );
p.SetModifiableFlag( true ); // packet length will change
pc.AddParameter( p );
p.Init(); // this will clear out any data in the parameter
p.SetName( "PktCnt" );
p.SetStartBit( 32 );
p.SetModifiableFlag( true ); // sequence count will change
pc.AddParameter( p );
p.Init(); // this will clear out any data in the parameter
p.SetName( "Time" );
p.SetStartBit( 40 );
p.SetModifiableFlag( true ); // time will change
pc.AddParameter( p );
//
// Now all of the parameters are in the collection, add the header. The
// Packet will make a copy of the input, so feel free to use it again.
//
if( pkt.AddHeader( pc ) )
{
// If it fails, you probably have already added a header. Use
// RemoveHeader first if you really want to add a different one.
cout << "Error adding header\n";
return 1;
}
//
// Time to add the 'data zone' to the packet. Same basic procedure as the
// header. The start location for each parameter is relative to the
// collection so they will restart at zero. This makes it much easier to
// reuse collections and packets within other packets.
//
pc.Init(); // we're going to reuse this, so must initialize it again.
pc.SetName( "MyData" );
p.Init(); // this will clear out any data in the parameter
p.SetName( "IntParam" );
p.SetStartBit( 0 ); // Don't forget to start over for a new collection
p.SetModifiableFlag( true );
pc.AddParameter( p ); // add the parameter to the collection
//
// This parameter has 3 samples, you should set the number of samples and
// also the sample offset. The sample offset will default to 0 which is
// the required value in this case. The sample offset is the number of
// bits that are between each of the samples.
//
p.Init();
p.SetName( "UintParam" );
p.SetStartBit( 16 );
p.SetNumberOfSamples( 3 ); // the default is 1, need 3 samples
p.SetModifiableFlag( true );
pc.AddParameter( p ); // add the parameter to the collection
//
// This parameter has a little endian byte order. The default byte order
// when setting the data type is big endian so you must pass in an extra
// parameter here.
//
p.Init();
p.SetName( "FloatParam" );
p.SetStartBit( 112 );
p.SetModifiableFlag( true );
pc.AddParameter( p ); // add the parameter to the collection
//
// The last parameter in the data is variable length. Variable length
// data must always be at the end of the container. You'll need to
// specify the parameter is variable length when setting the data type.
//
p.Init();
p.SetName( "StrParam" );
p.SetStartBit( 176 );
800, // 100 byte string (as bits)
true );
p.SetModifiableFlag( true );
pc.AddParameter( p ); // add the parameter to the collection
//
// Now add the data zone to the packet.
//
pkt.AddData( pc );
//
// The trailer consists of a single 32-bit parameter that is used for a
// checksum. The type of checksum is specified in the packet attributes.
// You just need to create the parameter to hold it here.
//
pc.Init();
p.Init();
p.SetName( "Checksum" );
p.SetStartBit( 0 );
p.SetModifiableFlag( true ); // checksum will change
p.SetValue( (uint32_t)0 );
pc.AddParameter( p );
pkt.AddTrailer( pc );
//
// Once all of the data is in the packet, create the packet map that will
// allow lookup of the parameters in the packet.
//
//
// Now it's time to set the packet attributes. None of the attributes are
// required, but all are used in this example.
//
std::string name; // the name of the parameter to use for an attribute
//
// Add an identifier. This packet only has one, but you can have any
// number of identifiers as required. The "Version" of the packet could
// be used here to ensure that the packet header hasn't changed, but we
// won't use it today.
//
id_struct.zone = HEADER_ZONE; // the parameter is in the header
id_struct.type = CONTENT_IDENTIFIER; // it identifies content (data)
id_struct.default_value_available = false; // using expect value instead
id_struct.expected_value_available = true;
id_struct.expected_value = 54;
ret_value = pkt.AddIdentifier( "PktId", &id_struct );
if( ret_value )
{
// Check the parameter name and ensure that you have set up the global
// packet map with CreateGlobalPacketMap.
cout << "Error adding identifier parameter\n";
return 1;
}
//
// Add the length parameter. In this case the actual length of the packet
// is 4 bytes longer than the value of this field.
//
ret_value = pkt.SetLengthParameter( "PktLen", HEADER_ZONE, 4 );
if( ret_value )
{
// Check the parameter name and ensure that you have set up the global
// packet map with CreateGlobalPacketMap.
cout << "Error setting length parameter\n";
return 1;
}
//
// Add the packet counter. Since it is a simple forward based counter,
// the defaults work fine.
//
ret_value = pkt.SetCounterParameter( "PktCnt", HEADER_ZONE );
if( ret_value )
{
// Check the parameter name and ensure that you have set up the global
// packet map with CreateGlobalPacketMap.
cout << "Error setting counter parameter\n";
return 1;
}
//
// Add the time stamp. There's no offset here, so the defaults will work.
//
ret_value = pkt.SetTimeStampParameter( "Time", HEADER_ZONE );
if( ret_value )
{
// Check the parameter name and ensure that you have set up the global
// packet map with CreateGlobalPacketMap.
cout << "Error setting time stamp parameter\n";
return 1;
}
//
// Add the checksum. It's a CRC-32 of all of the header and data.
//
ret_value = pkt.SetChecksumParameter( "Checksum",
0,
0,
if( ret_value )
{
// Check the parameter name and ensure that you have set up the global
// packet map with CreateGlobalPacketMap.
cout << "Error setting checksum parameter\n";
return 1;
}
//
// Saving this packet to a file is easy.
//
ret_value = pkt.SaveFile( "my_file.xml" ); // output is XML
if( ret_value )
{
// Could not save the file. Most likely cause is that you don't have
// write permission to the directory.
cout << "Error saving file\n";
return 1;
}
//
// The definition of the packet now is saved to a file. You can use this
// definition to build a packet to send or extract a packet you receive.
// Examples for both are provided.
//
// THE END
return 0;
}