This is the multi-page printable view of this section. Click here to print...

Return to the regular view of this page

As of 2025-07-24

pktparser

Packet Parser
pktparser (parser_packet) interprets byte sequences converted by the serparser.
serparser_heap parser_ser;

void setup() {
    // init ser parser (heap alloc)
    parser_ser.begin(PARSER::ASCII, 256);
}

void loop() {
    int c;
    while ((c = Serial.read()) >= 0) {
        parser_ser.parse(c);
        if (parser_ser.available()) {
            // get buffer object
            auto&& payl = parser_ser.get_buf();
            // identify packet type
            auto&& typ = identify_packet_type(payl.begin(), payl.end());

            // if packet type is TWELITE standard 0x81 message
            if (typ == E_PKT::PKT_TWELITE) {
                pktparser pkt; // packet parser object
                // analyze packet data
                typ = pkt.parse<TwePacketTwelite>(payl.begin(), payl.end());

                if (typ != E_PKT::PKT_ERROR) { // success!
                    // get data object
                    auto&& atw = pkt.use<TwePacketTwelite>();

                    // display packet inforamtion
                    Serial << crlf << format("TWELITE: SRC=%08X LQI=%03d "
                        , app.u32addr_src, app.u8lqi);
	                  Serial << " DI1..4="
	                      << atw.DI1 ? 'L' : 'H' << atw.DI2 ? 'L' : 'H'
                        << atw.DI3 ? 'L' : 'H' << atw.DI4 ? 'L' : 'H';
                }
            }
        }
    }
}

The example above shows how to interpret a 0x81 message from the standard application. The parser_ser object receives input from Serial and converts it to a byte sequence. This sequence is then passed to identify_packet_type() to determine the packet type (E_PKT). If the packet type is identified, .parse<TwePacketTwelite>() is called to analyze the content. The result is of type TwePacketTwelite, and the .use<TwePacketTwelite>() function is used to retrieve the parsed object. TwePacketTwelite is a class, but its member variables can be accessed like a struct.

parse<T>

template <class T>
E_PKT parse(const uint8_t* p, const uint8_t* e)

Parses the byte sequence.

Specify the packet type T to be parsed. For example, use TwePacketTwelite for a 0x81 message from the standard application.

p and e specify the beginning and one-past-the-end of the byte sequence.

Returns a value of type E_PKT. If an error occurs, it returns E_PKT::PKT_ERROR.

use<T>

template 
T& use()

Returns a reference to the object corresponding to the interpreted byte sequence. Call this only after successfully executing parse<T>.

T must be the same type used in parse<T>, or you can specify TwePacket to retrieve only basic information.

1 - E_PKT

Packet Type Definitions

The following packet types are supported:

NameDescription
PKT_ERRORUsed before parsing or when the packet type cannot be determined. The TwePacket does not contain valid data.
PKT_TWELITEParsed result of the 0x81 command from the standard application App_Twelite.
PKT_PALParsed format of TWELITE PAL serial output.
PKT_APPIOParsed UART messages from the remote control application App_IO.
PKT_APPUARTParsed extended format from the serial communication application App_UART.
PKT_APPTAGParsed UART messages from the wireless tag application App_Tag. Sensor-specific parts are not interpreted but returned as raw payload bytes.
PKT_ACT_STDOutput format used by samples of Act.

2 - identify_packet_type()

Determine Packet Type

idenify_packet_type()

Determines the packet type from a byte sequence. Returns a value of E_PKT.

E_PKT identify_packet_type(uint8_t* p, uint8_t u8len)

If the byte sequence cannot be interpreted as a known packet type, E_PKT::PKT_ERROR is returned.

3 - TwePacket

Packet Type
This is the base class for packet types. The common member struct contains shared information such as address data.
class TwePacket {
	public:
		static const E_PKT _pkt_id = E_PKT::PKT_ERROR;

		struct {
			uint32_t tick;     // System time at the time of interpretation [ms]
			uint32_t src_addr; // Source address (serial number)
			uint8_t src_lid;   // Source address (logical ID)
			uint8_t lqi;       // LQI
			uint16_t volt;     // Voltage [mV]
		} common;
};

3.1 - TwePacketTwelite

Packet from App_Twelite
The TwePacketTwelite class interprets the 0x81 command from the standard application App_Twelite.
class TwePacketTwelite : public TwePacket, public DataTwelite { ... };

After executing parse<TwePacketTwelite>(), packet information is stored in DataTwelite.

DataTwelite Struct

struct DataTwelite {
		// Source serial number
		uint32_t u32addr_src;

		// Source logical ID
		uint8_t u8addr_src;

		// Destination logical ID
		uint8_t u8addr_dst;

		// Timestamp at transmission
		uint16_t u16timestamp;

		// Flag for low-latency transmission
		bool b_lowlatency_tx;

		// Number of repeat transmissions
		uint16_t u8rpt_cnt;

		// LQI value
		uint16_t u8lqi;

		// DI state (true = active, Lo/GND)
		bool DI1, DI2, DI3, DI4;
		// DI state bitmap (from LSB: DI1, DI2, DI3, DI4)
		uint8_t DI_mask;

		// True if DI has ever been active
		bool DI1_active, DI2_active, DI3_active, DI4_active;
		// DI active bitmap (from LSB: DI1, DI2, DI3, DI4)
		uint8_t DI_active_mask;

		// Module power voltage [mV]
		uint16_t u16Volt;

		// AD values [mV]
		uint16_t u16Adc1, u16Adc2, u16Adc3, u16Adc4;
		// Bitmap indicating which ADs are active (from LSB: AD1, AD2, AD3, AD4)
		uint8_t Adc_active_mask;
};

3.2 - TwePacketIO

Packet from App_IO
The TwePacketAppIO class interprets the standard application’s App_IO serial message (0x81).
class TwePacketAppIO : public TwePacket, public DataAppIO { ... };

Packet data details are stored in DataTwelite after executing parse<TwePacketIO>().

DataAppIO Struct

struct DataAppIO {
		// Source serial number
		uint32_t u32addr_src;

		// Source logical ID
		uint8_t u8addr_src;

		// Destination logical ID
		uint8_t u8addr_dst;

		// Timestamp at transmission
		uint16_t u16timestamp;

		// Flag for low-latency transmission
		bool b_lowlatency_tx;

		// Number of repeat relays
		uint16_t u8rpt_cnt;

		// LQI value
		uint16_t u8lqi;

		// DI state bitmap (from LSB: DI1, DI2, DI3, DI4, ...)
		uint8_t DI_mask;

		// DI active (1 if in use) bitmap (from LSB: DI1, DI2, DI3, DI4, ...)
		uint8_t DI_active_mask;

		// Bitmap indicating whether DI is triggered by interrupt (from LSB: DI1, DI2, DI3, DI4, ...)
		uint16_t DI_int_mask;
};

3.3 - TwePacketUART

Packet from App_UART
The TwePacketAppUart class represents the extended format of App_UART received by the parent or repeater application App_Wings.
class TwePacketAppUART : public TwePacket, public DataAppUART

After executing parse<TwePacketUART>(), the packet information is stored in DataAppUART.

DataAppUART Struct

struct DataAppUART {
		/**
		 * source address (Serial ID)
		 */
		uint32_t u32addr_src;

		/**
		 * source address (Serial ID)
		 */
		uint32_t u32addr_dst;

		/**
		 * source address (logical ID)
		 */
		uint8_t u8addr_src;

		/**
		 * destination address (logical ID)
		 */
		uint8_t u8addr_dst;

		/**
		 * LQI value
		 */
		uint8_t u8lqi;

		/**
		 * Response ID
		 */
		uint8_t u8response_id;

		/**
		 * Payload length
		 */
		uint16_t u16paylen;

		/**
		 * payload
		 */
##if MWX_PARSER_PKT_APPUART_FIXED_BUF == 0
		mwx::smplbuf_u8_attach payload;
##else
		mwx::smplbuf_u8<MWX_PARSER_PKT_APPUART_FIXED_BUF> payload;
##endif
	};

payload represents the data portion, but the storage method varies depending on the macro definition.

If MWX_PARSER_PKT_APPUART_FIXED_BUF is set to 0 during compilation, payload will reference the byte sequence directly. If the original byte sequence is modified, the data in payload may become corrupted.

If MWX_PARSER_PKT_APPUART_FIXED_BUF is defined with a value greater than 0, a buffer of that size (in bytes) is allocated for payload. However, if the size of the serial data exceeds the buffer, parse<TwePacketAppUART>() will fail and return E_PKT::PKT_ERROR.

3.4 - TwePacketPAL

Packet from App_PAL
The TwePacketPal class interprets packet data from TWELITE PAL. This class provides a common interface for handling TWELITE PAL packets (e.g., sensor data sent upstream).
class TwePacketPal : public TwePacket, public DataPal { ... };

Common PAL data is defined in DataPal.

Generator functions are provided to extract sensor-board-specific data for each type of PAL.

DataPal Struct

The data structure of PAL packets varies depending on the connected sensor, but DataPal holds the common part of the data structure.

struct DataPal {
	uint8_t u8lqi;        // LQI value

	uint32_t u32addr_rpt; // Address of repeater

	uint32_t u32addr_src; // Source address
	uint8_t u8addr_src;   // Source logical address

	uint16_t u16seq;      // Sequence number

	E_PAL_PCB u8palpcb;		// Type of PAL board
	uint8_t u8palpcb_rev;	// Revision of PAL board
	uint8_t u8sensors;		// Number of sensor data entries included (MSB=1 indicates error)
	uint8_t u8snsdatalen; // Length of sensor data (in bytes)

	union {
		const uint8_t *au8snsdata; // Pointer to sensor data
		uint8_t _pobj[MWX_PARSER_PKT_APPPAL_FIXED_BUF]; // Sensor-specific objects
	};
};

A PAL packet consists of two main blocks: the common PAL part and a sensor-specific data part. The sensor-specific part is stored as-is without parsing. To simplify handling, data exceeding 32 bytes is stored in uptr_snsdata, which is dynamically allocated.

The sensor-specific part is stored in a structure that inherits from PalBase. This structure is generated by generator functions defined in TwePacketPal.

When parse<TwePacketPAL>() is executed and the data fits within MWX_PARSER_PKT_APPPAL_FIXED_BUF, sensor-specific objects are created.

If it exceeds that size, a reference to the raw byte sequence is stored in au8snsdata.

In such cases, if the original byte sequence is modified, sensor-specific objects can no longer be generated.

PalBase

All sensor-specific structures for PAL inherit from PalBase, which contains the sensor data storage status u32StoredMask.

	struct PalBase {
		uint32_t u32StoredMask; // Internal flag indicating which data is stored
	};

PalEvent

A PAL event does not directly transmit raw sensor data, but rather processed information triggered under specific conditions. For example, when acceleration exceeds a threshold from a stationary state.

	struct PalEvent {
		uint8_t b_stored;       // True if stored
		uint8_t u8event_source; // Reserved
		uint8_t u8event_id;     // Event ID
		uint32_t u32event_param;// Event parameter
	};

If event data is present, .is_PalEvent() in TwePacketPal returns true, and .get_PalEvent() provides the PalEvent structure.

Generator Functions

Generator functions are provided to extract sensor-board-specific data for each type of PAL.

void print_pal(pktparser& pkt) {
	auto&& pal = pkt.use<TwePacketPal>();
	if (pal.is_PalEvent()) {
		PalEvent obj = pal.get_PalEvent();
	} else
	switch(pal.u8palpcb) {
	case E_PAL_PCB::MAG:
	  {
		  // generate pal board specific data structure.
		  PalMag obj = pal.get_PalMag();
	  } break;
  case E_PAL_PCB::AMB:
	  {
		  // generate pal board specific data structure.
		  PalAmb obj = pal.get_PalAmb();
	  } break;
	  ...
	default: ;
	}
}

To use generator functions, first check whether pkt is an event using .is_PalEvent(). If so, retrieve the data using get_PalEvent(). Otherwise, generate the appropriate object based on u8palpcb.

get_PalMag()

PalMag get_PalMag()

// MAG
struct PalMag : public PalBase {
    uint16_t u16Volt;         // Module voltage [mV]
    uint8_t u8MagStat;        // Magnetic switch state [0: no magnet, 1, 2]
    uint8_t bRegularTransmit; // MSB flag of u8MagStat
};

If .u8palpcb == E_PAL_PCB::MAG, retrieve PalMag data for the open-close sensor PAL.

get_PalAmb()

PalAmb get_PalAmb()

// AMB
struct PalAmb : public PalBase {
    uint16_t u16Volt;       // Module voltage [mV]
    int16_t i16Temp;        // Temperature (value ×100)
    uint16_t u16Humd;       // Humidity (value ×100)
    uint32_t u32Lumi;       // Illuminance (approx. lux)
};

If .u8palpcb == E_PAL_PCB::AMB, retrieve PalAmb data for the environmental sensor PAL.

get_PalMot()

PalMot get_PalMot()

// MOT
struct PalMot : public PalBase {
    uint16_t u16Volt;  // Module voltage [mV]
    uint8_t u8samples; // Number of samples
    uint8_t u8sample_rate_code; // Sample rate (0: 25Hz, 4: 100Hz)
    int16_t i16X[16]; // X-axis
    int16_t i16Y[16]; // Y-axis
    int16_t i16Z[16]; // Z-axis
};

If .u8palpcb == E_PAL_PCB::MOT, retrieve PalMot data for the motion sensor PAL.

get_PalEvent()

PalEvent get_PalEvent()

// PAL event
struct PalEvent {
    uint8_t b_stored;        // True if event information is available
    uint8_t u8event_source;  // Event source
    uint8_t u8event_id;      // Event ID
    uint32_t u32event_param; // 24-bit event parameter
};

If .is_PalEvent() is true, retrieve PalEvent data.