For suitable output, we recommend to use Google Chrome (15+) or Microsoft Edge (79+).
As of 2025-07-24pktparser
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:
Supports the ASCII format output by the parent node in App_Wings.
Name | Description |
---|
PKT_ERROR | Used before parsing or when the packet type cannot be determined. The TwePacket does not contain valid data. |
PKT_TWELITE | Parsed result of the 0x81 command from the standard application App_Twelite. |
PKT_PAL | Parsed format of TWELITE PAL serial output. |
PKT_APPIO | Parsed UART messages from the remote control application App_IO. |
PKT_APPUART | Parsed extended format from the serial communication application App_UART. |
PKT_APPTAG | Parsed UART messages from the wireless tag application App_Tag. Sensor-specific parts are not interpreted but returned as raw payload bytes. |
PKT_ACT_STD | Output 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;
};
Used when mixing different packet types into an array or similar as pktparser
, to retrieve minimal shared information such as address data.
3.1 - TwePacketTwelite
Packet from 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
.
The simple format cannot be parsed. parse<TwePacketUART>()
will return E_PKT::PKT_ERROR
. To inspect the contents, refer directly to the original byte sequence.
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.