mirror of
https://github.com/espressif/openthread.git
synced 2026-08-03 09:27:47 +00:00
[tcat] implementation of tcat Ping command (#10484)
Commit implements Tcat ping command `kTlvPing`. Signed-off-by: Przemyslaw Bida <[email protected]>
This commit is contained in:
@@ -355,21 +355,21 @@ bool TcatAgent::CanProcessTlv(uint8_t aTlvType) const
|
||||
return IsCommandClassAuthorized(tlvCommandClass);
|
||||
}
|
||||
|
||||
Error TcatAgent::HandleSingleTlv(const Message &aIncommingMessage, Message &aOutgoingMessage)
|
||||
Error TcatAgent::HandleSingleTlv(const Message &aIncomingMessage, Message &aOutgoingMessage)
|
||||
{
|
||||
Error error = kErrorParse;
|
||||
ot::Tlv tlv;
|
||||
uint16_t offset = aIncommingMessage.GetOffset();
|
||||
uint16_t offset = aIncomingMessage.GetOffset();
|
||||
uint16_t length;
|
||||
bool response = false;
|
||||
|
||||
VerifyOrExit(IsConnected(), error = kErrorInvalidState);
|
||||
SuccessOrExit(error = aIncommingMessage.Read(offset, tlv));
|
||||
SuccessOrExit(error = aIncomingMessage.Read(offset, tlv));
|
||||
|
||||
if (tlv.IsExtended())
|
||||
{
|
||||
ot::ExtendedTlv extTlv;
|
||||
SuccessOrExit(error = aIncommingMessage.Read(offset, extTlv));
|
||||
SuccessOrExit(error = aIncomingMessage.Read(offset, extTlv));
|
||||
length = extTlv.GetLength();
|
||||
offset += sizeof(ot::ExtendedTlv);
|
||||
}
|
||||
@@ -392,7 +392,7 @@ Error TcatAgent::HandleSingleTlv(const Message &aIncommingMessage, Message &aOut
|
||||
break;
|
||||
|
||||
case kTlvSetActiveOperationalDataset:
|
||||
error = HandleSetActiveOperationalDataset(aIncommingMessage, offset, length);
|
||||
error = HandleSetActiveOperationalDataset(aIncomingMessage, offset, length);
|
||||
break;
|
||||
|
||||
case kTlvStartThreadInterface:
|
||||
@@ -405,7 +405,7 @@ Error TcatAgent::HandleSingleTlv(const Message &aIncommingMessage, Message &aOut
|
||||
|
||||
case kTlvSendApplicationData:
|
||||
LogInfo("Application data len:%d, offset:%d", length, offset);
|
||||
mAppDataReceiveCallback.InvokeIfSet(&GetInstance(), &aIncommingMessage, offset,
|
||||
mAppDataReceiveCallback.InvokeIfSet(&GetInstance(), &aIncomingMessage, offset,
|
||||
MapEnum(mCurrentApplicationProtocol), mCurrentServiceName);
|
||||
response = true;
|
||||
error = kErrorNone;
|
||||
@@ -413,6 +413,13 @@ Error TcatAgent::HandleSingleTlv(const Message &aIncommingMessage, Message &aOut
|
||||
case kTlvDecommission:
|
||||
error = HandleDecomission();
|
||||
break;
|
||||
case kTlvPing:
|
||||
error = HandlePing(aIncomingMessage, aOutgoingMessage, offset, length);
|
||||
if (error == kErrorNone)
|
||||
{
|
||||
response = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
error = kErrorInvalidCommand;
|
||||
}
|
||||
@@ -460,14 +467,14 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error TcatAgent::HandleSetActiveOperationalDataset(const Message &aIncommingMessage, uint16_t aOffset, uint16_t aLength)
|
||||
Error TcatAgent::HandleSetActiveOperationalDataset(const Message &aIncomingMessage, uint16_t aOffset, uint16_t aLength)
|
||||
{
|
||||
Dataset dataset;
|
||||
OffsetRange offsetRange;
|
||||
Error error;
|
||||
|
||||
offsetRange.Init(aOffset, aLength);
|
||||
SuccessOrExit(error = dataset.SetFrom(aIncommingMessage, offsetRange));
|
||||
SuccessOrExit(error = dataset.SetFrom(aIncomingMessage, offsetRange));
|
||||
SuccessOrExit(error = dataset.ValidateTlvs());
|
||||
|
||||
if (!CheckCommandClassAuthorizationFlags(mCommissionerAuthorizationField.mApplicationFlags,
|
||||
@@ -504,6 +511,35 @@ Error TcatAgent::HandleDecomission(void)
|
||||
return error;
|
||||
}
|
||||
|
||||
Error TcatAgent::HandlePing(const Message &aIncomingMessage,
|
||||
Message &aOutgoingMessage,
|
||||
uint16_t aOffset,
|
||||
uint16_t aLength)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
ot::ExtendedTlv extTlv;
|
||||
ot::Tlv tlv;
|
||||
|
||||
VerifyOrExit(aLength <= kPingPayloadMaxLength, error = kErrorParse);
|
||||
if (aLength > ot::Tlv::kBaseTlvMaxLength)
|
||||
{
|
||||
extTlv.SetType(kTlvResponseWithPayload);
|
||||
extTlv.SetLength(aLength);
|
||||
SuccessOrExit(error = aOutgoingMessage.Append(extTlv));
|
||||
}
|
||||
else
|
||||
{
|
||||
tlv.SetType(kTlvResponseWithPayload);
|
||||
tlv.SetLength(static_cast<uint8_t>(aLength));
|
||||
SuccessOrExit(error = aOutgoingMessage.Append(tlv));
|
||||
}
|
||||
|
||||
SuccessOrExit(error = aOutgoingMessage.AppendBytesFromMessage(aIncomingMessage, aOffset, aLength));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error TcatAgent::HandleStartThreadInterface(void)
|
||||
{
|
||||
Error error;
|
||||
|
||||
@@ -350,9 +350,10 @@ private:
|
||||
Error Connected(MeshCoP::SecureTransport &aTlsContext);
|
||||
void Disconnected(void);
|
||||
|
||||
Error HandleSingleTlv(const Message &aIncommingMessage, Message &aOutgoingMessage);
|
||||
Error HandleSetActiveOperationalDataset(const Message &aIncommingMessage, uint16_t aOffset, uint16_t aLength);
|
||||
Error HandleSingleTlv(const Message &aIncomingMessage, Message &aOutgoingMessage);
|
||||
Error HandleSetActiveOperationalDataset(const Message &aIncomingMessage, uint16_t aOffset, uint16_t aLength);
|
||||
Error HandleDecomission(void);
|
||||
Error HandlePing(const Message &aIncomingMessage, Message &aOutgoingMessage, uint16_t aOffset, uint16_t aLength);
|
||||
Error HandleStartThreadInterface(void);
|
||||
|
||||
bool CheckCommandClassAuthorizationFlags(CommandClassFlags aCommissionerCommandClassFlags,
|
||||
@@ -361,7 +362,8 @@ private:
|
||||
bool CanProcessTlv(uint8_t aTlvType) const;
|
||||
CommandClass GetCommandClass(uint8_t aTlvType) const;
|
||||
|
||||
static constexpr uint16_t kJoinerUdpPort = OPENTHREAD_CONFIG_JOINER_UDP_PORT;
|
||||
static constexpr uint16_t kJoinerUdpPort = OPENTHREAD_CONFIG_JOINER_UDP_PORT;
|
||||
static constexpr uint16_t kPingPayloadMaxLength = 512;
|
||||
|
||||
JoinerPskd mJoinerPskd;
|
||||
const VendorInfo *mVendorInfo;
|
||||
|
||||
@@ -46,6 +46,18 @@ send "thread start\n"
|
||||
expect_line "\tTYPE:\tRESPONSE_W_STATUS"
|
||||
expect_line "\tVALUE:\t0x00"
|
||||
|
||||
send "ping\n"
|
||||
expect_line "\tTYPE:\tRESPONSE_W_PAYLOAD"
|
||||
expect_line "\tLEN:\t10"
|
||||
|
||||
send "ping 255\n"
|
||||
expect_line "\tTYPE:\tRESPONSE_W_PAYLOAD"
|
||||
expect_line "\tLEN:\t255"
|
||||
|
||||
send "ping 512\n"
|
||||
expect_line "\tTYPE:\tRESPONSE_W_PAYLOAD"
|
||||
expect_line "\tLEN:\t512"
|
||||
|
||||
send "exit\n"
|
||||
expect eof
|
||||
|
||||
|
||||
@@ -37,6 +37,8 @@ from cli.command import Command, CommandResultNone, CommandResultTLV
|
||||
from dataset.dataset import ThreadDataset
|
||||
from utils import select_device_by_user_input
|
||||
from os import path
|
||||
from time import time
|
||||
from secrets import token_bytes
|
||||
|
||||
|
||||
class HelpCommand(Command):
|
||||
@@ -103,6 +105,37 @@ class DecommissionCommand(Command):
|
||||
return CommandResultTLV(tlv_response)
|
||||
|
||||
|
||||
class PingCommand(Command):
|
||||
|
||||
def get_help_string(self) -> str:
|
||||
return 'Send echo request to TCAT device.'
|
||||
|
||||
async def execute_default(self, args, context):
|
||||
bless: BleStreamSecure = context['ble_sstream']
|
||||
payload_size = 10
|
||||
max_payload = 512
|
||||
if len(args) > 0:
|
||||
payload_size = int(args[0])
|
||||
if payload_size > max_payload:
|
||||
print(f'Payload size too large. Maximum supported value is {max_payload}')
|
||||
return
|
||||
to_send = token_bytes(payload_size)
|
||||
data = TLV(TcatTLVType.PING.value, to_send).to_bytes()
|
||||
elapsed_time = time()
|
||||
response = await bless.send_with_resp(data)
|
||||
elapsed_time = time() - elapsed_time
|
||||
if not response:
|
||||
return
|
||||
|
||||
tlv_response = TLV.from_bytes(response)
|
||||
if tlv_response.value != to_send:
|
||||
print("Received malformed response.")
|
||||
|
||||
print(f"Roundtrip time {elapsed_time} s.")
|
||||
|
||||
return CommandResultTLV(tlv_response)
|
||||
|
||||
|
||||
class ThreadStartCommand(Command):
|
||||
|
||||
def get_help_string(self) -> str:
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
import readline
|
||||
import shlex
|
||||
from ble.ble_stream_secure import BleStreamSecure
|
||||
from cli.base_commands import (HelpCommand, HelloCommand, CommissionCommand, DecommissionCommand, ThreadStateCommand,
|
||||
ScanCommand)
|
||||
from cli.base_commands import (HelpCommand, HelloCommand, CommissionCommand, DecommissionCommand, PingCommand,
|
||||
ThreadStateCommand, ScanCommand)
|
||||
from cli.dataset_commands import (DatasetCommand)
|
||||
from dataset.dataset import ThreadDataset
|
||||
from typing import Optional
|
||||
@@ -44,6 +44,7 @@ class CLI:
|
||||
'hello': HelloCommand(),
|
||||
'commission': CommissionCommand(),
|
||||
'decommission': DecommissionCommand(),
|
||||
'ping': PingCommand(),
|
||||
'dataset': DatasetCommand(),
|
||||
'thread': ThreadStateCommand(),
|
||||
'scan': ScanCommand(),
|
||||
|
||||
@@ -32,6 +32,7 @@ class TcatTLVType(Enum):
|
||||
RESPONSE_W_STATUS = 0x01
|
||||
RESPONSE_W_PAYLOAD = 0x02
|
||||
DISCONNECT = 0x09
|
||||
PING = 0x0A
|
||||
ACTIVE_DATASET = 0x20
|
||||
DECOMMISSION = 0x60
|
||||
APPLICATION = 0x82
|
||||
|
||||
@@ -58,14 +58,19 @@ class TLV():
|
||||
def set_from_bytes(self, data: bytes):
|
||||
self.type = data[0]
|
||||
header_len = 2
|
||||
size_offset = 1
|
||||
if data[1] == 0xFF:
|
||||
header_len = 4
|
||||
length = int.from_bytes(data[1:header_len], byteorder='big')
|
||||
size_offset = 2
|
||||
length = int.from_bytes(data[size_offset:header_len], byteorder='big')
|
||||
self.value = data[header_len:header_len + length]
|
||||
|
||||
def to_bytes(self) -> bytes:
|
||||
has_long_header = len(self.value) >= 255
|
||||
has_long_header = len(self.value) >= 254
|
||||
header_len = 4 if has_long_header else 2
|
||||
len_bytes = len(self.value).to_bytes(header_len - 1, byteorder='big')
|
||||
header = bytes([self.type]) + len_bytes
|
||||
len_bytes = len(self.value).to_bytes(header_len // 2, byteorder='big')
|
||||
type = self.type
|
||||
if has_long_header:
|
||||
type = type << 8 | 255
|
||||
header = type.to_bytes(header_len // 2, byteorder='big') + len_bytes
|
||||
return header + self.value
|
||||
|
||||
Reference in New Issue
Block a user