decodeSample method
Builds a message from a binary sample frame sent by fromNodeUId.
The sender's identity is a parameter here rather than read out of the frame, as the WebSocket transport reads it out of the slot: the channel the frame arrived on already names its peer, exactly and without a lookup table.
Implementation
@override
IMessage? decodeSample(Uint8List frame, String fromNodeUId) {
final channels = WsSampleFrame.decodeChannels(frame, config.channels);
final timestamp = DateTime.now();
final offsets = clockOffsets;
final sourceClock = WsSampleFrame.senderMicrosOf(frame) / 1e6;
// Null until the estimator has accepted a burst for this peer, which
// keeps transitSeconds null rather than reporting the difference of two
// unrelated monotonic clocks.
var clockOffset = offsets?.offsetFor(fromNodeUId);
var uncertainty = offsets?.uncertaintyFor(fromNodeUId);
ClockChain? upstream;
if (WsSampleFrame.isRelayed(frame)) {
// Stamped by its origin: the way from there to the sender comes first,
// and until the sender has said what it is the offset is unknown.
upstream = _upstreams[fromNodeUId];
clockOffset = upstream == null || clockOffset == null
? null
: upstream.offsetAt(sourceClock) + clockOffset;
uncertainty = upstream == null || uncertainty == null
? null
: upstream.uncertainty + uncertainty;
}
final timing = MessageTiming(
sourceClock: sourceClock,
clockOffset: clockOffset,
uncertainty: uncertainty,
receivedClock: PeerClock.now(),
sourceId: fromNodeUId,
upstream: upstream,
);
switch (config.dataType) {
case StreamDataType.float32:
case StreamDataType.double64:
return MessageFactory.double64Message(
data: IList(channels.map((v) => (v! as num).toDouble())),
channels: config.channels,
timestamp: timestamp,
timing: timing,
);
case StreamDataType.int8:
case StreamDataType.int16:
case StreamDataType.int32:
case StreamDataType.int64:
return MessageFactory.int64Message(
data: IList(channels.cast<int>()),
channels: config.channels,
timestamp: timestamp,
timing: timing,
);
case StreamDataType.string:
return MessageFactory.stringMessage(
data: IList(channels.cast<String>()),
channels: config.channels,
timestamp: timestamp,
timing: timing,
);
}
}