Skip to content

Commit 346870a

Browse files
committed
Merge branch 'bugfix/add_old_btsnoop_hci_py' into 'master'
fix(nimble): Updated parser script for HCI log creation See merge request espressif/esp-idf!40726
2 parents bc58afc + 54e65df commit 346870a

File tree

2 files changed

+44
-22
lines changed

2 files changed

+44
-22
lines changed

tools/bt/README.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,23 @@ Alternatively, manually create a log file containing HCI data in the expected fo
4545

4646
### **Running the Script**
4747

48+
Timestamp information is now included as part of the dump. The log looks like below, where
49+
the first 8 bytes contains timestamp information:
50+
51+
00 C:49 ed 01 00 00 00 00 00 03 0c 00
52+
01 E:8e f0 01 00 00 00 00 00 0e 04 05 03 0c 00
53+
54+
If timestamp information is not present, then same log would look like:
55+
56+
00 C:03 0c 00
57+
01 E:0e 04 05 03 0c 00
58+
59+
The script takes "--has-ts" parameter, if output log has timestamp information
60+
4861
To parse the logs and generate a BTSnoop file, run:
4962

5063
```bash
51-
python bt_hci_to_btsnoop.py -p <input_log_file> -o <output_tag>
64+
python bt_hci_to_btsnoop.py -p <input_log_file> -o <output_tag> [--has-ts]
5265
```
5366

5467
#### **Parameters**

tools/bt/bt_hci_to_btsnoop.py

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import os
55
import re
66
import struct
7+
import time
78

89

910
def create_new_bt_snoop_file(filename: str) -> None:
@@ -36,7 +37,7 @@ def log_data_clean(data: str) -> str:
3637
return cleaned
3738

3839

39-
def parse_log(input_path: str, output_tag: str) -> None:
40+
def parse_log(input_path: str, output_tag: str, has_timestamp: bool = True) -> None:
4041
if not os.path.exists(input_path):
4142
print(f"Error: The file '{input_path}' does not exist.")
4243
return
@@ -53,10 +54,9 @@ def parse_log(input_path: str, output_tag: str) -> None:
5354
if not line:
5455
continue
5556
parts = line.split()
56-
if len(parts) < 10:
57+
if len(parts) < 2:
5758
continue
5859
parts_wo_ln = parts[1:]
59-
# Check for literal in the first token
6060
literal = None
6161
if ':' in parts_wo_ln[0]:
6262
literal_part, sep, ts_byte = parts_wo_ln[0].partition(':')
@@ -66,16 +66,18 @@ def parse_log(input_path: str, output_tag: str) -> None:
6666
else:
6767
literal = None
6868
if literal:
69-
# Parse timestamp
70-
try:
71-
timestamp_bytes = bytes(int(b, 16) for b in parts_wo_ln[1:9])
72-
except Exception:
73-
continue
74-
timestamp_us = int.from_bytes(timestamp_bytes, byteorder='little', signed=False)
75-
hci_data = ' '.join(parts_wo_ln[9:])
69+
if has_timestamp:
70+
try:
71+
timestamp_bytes = bytes(int(b, 16) for b in parts_wo_ln[1:9])
72+
timestamp_us = int.from_bytes(timestamp_bytes, byteorder='little', signed=False)
73+
hci_data = ' '.join(parts_wo_ln[9:])
74+
except Exception:
75+
continue
76+
else:
77+
timestamp_us = int(time.time() * 1e6)
78+
hci_data = ' '.join(parts_wo_ln[1:])
7679
if not hci_data:
7780
continue
78-
# Determine indicator and direction
7981
if literal == 'C:':
8082
hci_data = '01 ' + hci_data
8183
direction = 0
@@ -93,13 +95,16 @@ def parse_log(input_path: str, output_tag: str) -> None:
9395
append_hci_to_bt_snoop_file(output_file, direction, hci_data, timestamp_us)
9496
parsed_num += 1
9597
else:
96-
# No literal: treat as advertising report
97-
try:
98-
timestamp_bytes = bytes(int(b, 16) for b in parts[1:9])
99-
except Exception:
100-
continue
101-
timestamp_us = int.from_bytes(timestamp_bytes, byteorder='little', signed=False)
102-
adv_data = ' '.join(parts[9:])
98+
if has_timestamp:
99+
try:
100+
timestamp_bytes = bytes(int(b, 16) for b in parts[1:9])
101+
timestamp_us = int.from_bytes(timestamp_bytes, byteorder='little', signed=False)
102+
adv_data = ' '.join(parts[9:])
103+
except Exception:
104+
continue
105+
else:
106+
timestamp_us = int(time.time() * 1e6)
107+
adv_data = ' '.join(parts[1:])
103108
if not adv_data:
104109
continue
105110
hci_data = '04 3e ' + adv_data
@@ -120,10 +125,14 @@ def main() -> None:
120125
parser = argparse.ArgumentParser(description='Log Parsing Tool')
121126
parser.add_argument('-p', '--path', required=True, help='Path to the input log file')
122127
parser.add_argument('-o', '--output', required=True, help='Name tag for the output file')
128+
parser.add_argument(
129+
'--has-ts',
130+
action='store_true',
131+
default=False,
132+
help='Set this if the input file has timestamp bytes at the beginning (default: False)',
133+
)
123134
args = parser.parse_args()
124-
input_path = args.path
125-
output_tag = args.output
126-
parse_log(input_path, output_tag)
135+
parse_log(args.path, args.output, has_timestamp=args.has_ts)
127136

128137

129138
if __name__ == '__main__':

0 commit comments

Comments
 (0)