/*
This software is subject to the license described in the License.txt file
included with this software distribution. You may not use this file except
in compliance with this license.
Copyright (c) Dynastream Innovations Inc. 2016
All rights reserved.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ANT_Managed_Library
{
///
/// Container for all the information passed from an ANT device callback function
///
public class ANT_Response
{
///
/// The object that created this response (ie: The corresponding ANTChannel or ANTDevice instance).
///
public object sender;
///
/// The channel parameter received in the message. Note: For some messages this is not applicable.
///
public byte antChannel;
///
/// The time the message was received.
///
public DateTime timeReceived;
///
/// The MessageID of the response
///
public byte responseID;
///
/// The raw contents of the response message
///
public byte[] messageContents;
internal ANT_Response(object sender, byte antChannel, DateTime timeReceived, byte IDcode, byte[] messageContents)
{
this.sender = sender;
this.antChannel = antChannel;
this.timeReceived = timeReceived;
this.responseID = IDcode;
this.messageContents = messageContents;
}
#region Accessors
///
/// Returns messageContents[2] cast to an ANTEventID. Throws an exception if this is not a channel event.
///
public ANT_ReferenceLibrary.ANTEventID getChannelEventCode()
{
if (responseID != (byte)ANT_ReferenceLibrary.ANTMessageID.RESPONSE_EVENT_0x40)
throw new ANT_Exception("Response is not a channel event");
return (ANT_ReferenceLibrary.ANTEventID)messageContents[2];
}
///
/// Returns messageContents[1] cast to an ANTMessageID. Throws an exception if this is not a response event.
///
public ANT_ReferenceLibrary.ANTMessageID getMessageID()
{
if (responseID != (byte)ANT_ReferenceLibrary.ANTMessageID.RESPONSE_EVENT_0x40)
throw new ANT_Exception("Response is not a response event");
return (ANT_ReferenceLibrary.ANTMessageID)messageContents[1];
}
///
/// Returns the 8-byte data payload of an ANT message. Throws an exception if this is not a received message.
///
///
public byte[] getDataPayload()
{
if (messageContents.Length == 9
&& (responseID == (byte)ANT_ReferenceLibrary.ANTMessageID.BROADCAST_DATA_0x4E
|| responseID == (byte)ANT_ReferenceLibrary.ANTMessageID.ACKNOWLEDGED_DATA_0x4F
|| responseID == (byte)ANT_ReferenceLibrary.ANTMessageID.BURST_DATA_0x50
))
return messageContents.Skip(1).ToArray(); //Just skip the channel byte and return the payload
else
return splitExtMessage(extMsgParts.DataPayload); // Extended message
}
///
/// Returns the burst sequence number (upper three bits of channel number). Throws exception if this is not a burst event.
///
public byte getBurstSequenceNumber()
{
if (responseID != (byte)ANT_ReferenceLibrary.ANTMessageID.BURST_DATA_0x50
&& responseID != (byte)ANT_ReferenceLibrary.ANTMessageID.EXT_BURST_DATA_0x5F
)
throw new ANT_Exception("Response is not a burst event");
else
return (byte)((messageContents[0] & 0xE0) >> 5);
}
///
/// Returns the channel ID portion of an extended message. Throws an exception if this is not an extended message.
///
public ANT_ChannelID getDeviceIDfromExt()
{
ANT_ChannelID extID = new ANT_ChannelID();
byte[] rawID = splitExtMessage(extMsgParts.DeviceID);
extID.deviceNumber = (UInt16)(rawID[0] + (rawID[1] << 8));
extID.pairingBit = Convert.ToBoolean(rawID[2] & 0x80);
extID.deviceTypeID = (byte)(rawID[2] & 0x7F);
extID.transmissionTypeID = rawID[3];
return extID;
}
///
/// Returns true if this is an extended message, false otherwise
///
public bool isExtended()
{
if (messageContents.Length < 13
)
return false;
else
return true;
}
///
/// Splits and returns the requested part of an extended message. Throws an exception if this is not an extended message.
///
/// The desired part of the message
private byte[] splitExtMessage(extMsgParts whichPart)
{
if (!isExtended())
throw new ANT_Exception("Response is not an extended message");
byte[] dataPayload;
byte[] deviceID;
// Legacy extended message
// The "extended" part of this message is the 4-byte channel ID of the device that we recieved this message from.
// This event is only available on the AT3
if (responseID == (byte)ANT_ReferenceLibrary.ANTMessageID.EXT_BROADCAST_DATA_0x5D
|| responseID == (byte)ANT_ReferenceLibrary.ANTMessageID.EXT_ACKNOWLEDGED_DATA_0x5E
|| responseID == (byte)ANT_ReferenceLibrary.ANTMessageID.EXT_BURST_DATA_0x5F)
{
deviceID = messageContents.Skip(1).Take(4).ToArray(); //Skip channel byte
dataPayload = messageContents.Skip(5).Take(8).ToArray(); //Skip channel byte and 4 bytes of id parameters
}
// "Flag" extended message. The 4-byte channel ID is included if the flag byte includes 0x80
else if (responseID == (byte)ANT_ReferenceLibrary.ANTMessageID.BROADCAST_DATA_0x4E
|| responseID == (byte)ANT_ReferenceLibrary.ANTMessageID.ACKNOWLEDGED_DATA_0x4F
|| responseID == (byte)ANT_ReferenceLibrary.ANTMessageID.BURST_DATA_0x50)
{
dataPayload = messageContents.Skip(1).Take(8).ToArray(); //Skip channel byte
if ((messageContents[9] & 0x80) == 0) // Check flag byte
throw new ANT_Exception("Response does not contain a channel ID");
deviceID = messageContents.Skip(10).Take(4).ToArray(); //Skip channel byte, 8 bytes of data, and flag byte
}
else
throw new ANT_Exception("Response is not an extended message");
switch (whichPart)
{
case extMsgParts.DataPayload:
return dataPayload;
case extMsgParts.DeviceID:
return deviceID;
default:
throw new ANT_Exception("Invalid extMsgPart");
}
}
//This enum makes the code more readable when calling splitExtMessage()
private enum extMsgParts
{
DataPayload,
DeviceID
}
#endregion
}
}