11import json
2+ import logging
23import os
3- from typing import ClassVar
44
55from pytest_embedded .app import App
66
@@ -13,60 +13,74 @@ class ArduinoApp(App):
1313 sketch (str): Sketch name.
1414 fqbn (str): Fully Qualified Board Name.
1515 target (str) : ESPxx chip.
16- flash_files (List[Tuple[int, str, str]]): List of (offset, file path, encrypted) of files need to be flashed in.
16+ flash_settings (dict[str, str]): Flash settings for the target.
17+ binary_file (str): Merged binary file path.
18+ elf_file (str): ELF file path.
1719 """
1820
19- #: dict of flash settings
20- flash_settings : ClassVar [dict [str , dict [str , str ]]] = {
21- 'esp32' : {'flash-mode' : 'dio' , 'flash-size' : 'detect' , 'flash-freq' : '80m' },
22- 'esp32c2' : {'flash-mode' : 'dio' , 'flash-size' : 'detect' , 'flash-freq' : '60m' },
23- 'esp32c3' : {'flash-mode' : 'dio' , 'flash-size' : 'detect' , 'flash-freq' : '80m' },
24- 'esp32c5' : {'flash-mode' : 'dio' , 'flash-size' : 'detect' , 'flash-freq' : '80m' },
25- 'esp32c6' : {'flash-mode' : 'dio' , 'flash-size' : 'detect' , 'flash-freq' : '80m' },
26- 'esp32c61' : {'flash-mode' : 'dio' , 'flash-size' : 'detect' , 'flash-freq' : '80m' },
27- 'esp32h2' : {'flash-mode' : 'dio' , 'flash-size' : 'detect' , 'flash-freq' : '48m' },
28- 'esp32p4' : {'flash-mode' : 'dio' , 'flash-size' : 'detect' , 'flash-freq' : '80m' },
29- 'esp32s2' : {'flash-mode' : 'dio' , 'flash-size' : 'detect' , 'flash-freq' : '80m' },
30- 'esp32s3' : {'flash-mode' : 'dio' , 'flash-size' : 'detect' , 'flash-freq' : '80m' },
31- }
32-
33- #: dict of binaries' offset.
34- binary_offsets : ClassVar [dict [str , list [int ]]] = {
35- 'esp32' : [0x1000 , 0x8000 , 0x10000 ],
36- 'esp32c2' : [0x0 , 0x8000 , 0x10000 ],
37- 'esp32c3' : [0x0 , 0x8000 , 0x10000 ],
38- 'esp32c5' : [0x2000 , 0x8000 , 0x10000 ],
39- 'esp32c6' : [0x0 , 0x8000 , 0x10000 ],
40- 'esp32c61' : [0x0 , 0x8000 , 0x10000 ],
41- 'esp32h2' : [0x0 , 0x8000 , 0x10000 ],
42- 'esp32p4' : [0x2000 , 0x8000 , 0x10000 ],
43- 'esp32s2' : [0x1000 , 0x8000 , 0x10000 ],
44- 'esp32s3' : [0x0 , 0x8000 , 0x10000 ],
45- }
46-
4721 def __init__ (
4822 self ,
4923 ** kwargs ,
5024 ):
5125 super ().__init__ (** kwargs )
5226
53- self .sketch = os .path .basename (self .app_path )
27+ # If no valid binary path is found, assume the build directory is the app path
28+ if not self .binary_path and self .app_path :
29+ self .binary_path = self .app_path
30+
31+ # Extract sketch name from binary files in the build directory
32+ self .sketch = self ._get_sketch_name (self .binary_path )
5433 self .fqbn = self ._get_fqbn (self .binary_path )
5534 self .target = self .fqbn .split (':' )[2 ]
56- self .flash_files = self ._get_bin_files (self .binary_path , self .sketch , self .target )
35+ self .flash_settings = self ._get_flash_settings ()
36+ self .binary_file = os .path .realpath (os .path .join (self .binary_path , self .sketch + '.ino.merged.bin' ))
5737 self .elf_file = os .path .realpath (os .path .join (self .binary_path , self .sketch + '.ino.elf' ))
5838
59- def _get_fqbn (self , build_path ) -> str :
39+ logging .debug (f'Sketch name: { self .sketch } ' )
40+ logging .debug (f'FQBN: { self .fqbn } ' )
41+ logging .debug (f'Target: { self .target } ' )
42+ logging .debug (f'Flash settings: { self .flash_settings } ' )
43+ logging .debug (f'Binary file: { self .binary_file } ' )
44+ logging .debug (f'ELF file: { self .elf_file } ' )
45+
46+ def _get_sketch_name (self , build_path : str ) -> str :
47+ """Extract sketch name from binary files in the build directory."""
48+ if not build_path or not os .path .isdir (build_path ):
49+ logging .warning ('No build path found. Using default sketch name "sketch".' )
50+ return 'sketch'
51+
52+ # Look for .ino.bin or .ino.merged.bin files
53+ for filename in os .listdir (build_path ):
54+ if filename .endswith ('.ino.bin' ) or filename .endswith ('.ino.merged.bin' ):
55+ # Extract sketch name (everything before .ino.bin or .ino.merged.bin)
56+ if filename .endswith ('.ino.merged.bin' ):
57+ return filename [: - len ('.ino.merged.bin' )]
58+ else :
59+ return filename [: - len ('.ino.bin' )]
60+
61+ # If no .ino.bin or .ino.merged.bin files found, raise an error
62+ raise ValueError (f'No .ino.bin or .ino.merged.bin file found in { build_path } ' )
63+
64+ def _get_fqbn (self , build_path : str ) -> str :
65+ """Get FQBN from build.options.json file."""
6066 options_file = os .path .realpath (os .path .join (build_path , 'build.options.json' ))
6167 with open (options_file ) as f :
6268 options = json .load (f )
6369 fqbn = options ['fqbn' ]
6470 return fqbn
6571
66- def _get_bin_files (self , build_path , sketch , target ) -> list [tuple [int , str , bool ]]:
67- bootloader = os .path .realpath (os .path .join (build_path , sketch + '.ino.bootloader.bin' ))
68- partitions = os .path .realpath (os .path .join (build_path , sketch + '.ino.partitions.bin' ))
69- app = os .path .realpath (os .path .join (build_path , sketch + '.ino.bin' ))
70- files = [bootloader , partitions , app ]
71- offsets = self .binary_offsets [target ]
72- return [(offsets [i ], files [i ], False ) for i in range (3 )]
72+ def _get_flash_settings (self ) -> dict [str , str ]:
73+ """Get flash settings from flash_args file."""
74+ flash_args_file = os .path .realpath (os .path .join (self .binary_path , 'flash_args' ))
75+ with open (flash_args_file ) as f :
76+ flash_args = f .readline ().split (' ' )
77+
78+ flash_settings = {}
79+ for i , arg in enumerate (flash_args ):
80+ if arg .startswith ('--' ):
81+ flash_settings [arg [2 :].strip ()] = flash_args [i + 1 ].strip ()
82+
83+ if flash_settings == {}:
84+ raise ValueError (f'Flash settings not found in { flash_args_file } ' )
85+
86+ return flash_settings
0 commit comments