1+ #!/usr/bin/env python3
2+ # generated by ChatGPT
3+ import os
4+ import shutil
5+ import zipfile
6+ import re
7+
8+ def extract_zip (zip_path , extract_to = "." ):
9+ print (f"Extracting { zip_path } ..." )
10+ with zipfile .ZipFile (zip_path , "r" ) as zip_ref :
11+ zip_ref .extractall (extract_to )
12+
13+ def find_subfolder (base_dir , pattern ):
14+ """Finds the first folder under base_dir containing the given pattern."""
15+ for root , dirs , _ in os .walk (base_dir ):
16+ for d in dirs :
17+ if pattern in d :
18+ return os .path .join (root , d )
19+ return None
20+
21+ def copy_contents (api_folder , examples_folder , dest_folder ):
22+ """Copies API and Examples folders (skipping Platform)."""
23+ print (f"Copying contents to { dest_folder } ..." )
24+
25+ if os .path .exists (dest_folder ):
26+ shutil .rmtree (dest_folder )
27+ os .makedirs (dest_folder )
28+
29+ # Copy top-level files (LICENSE if available)
30+ for fname in ["LICENSE.txt" ]:
31+ src = os .path .join (api_folder , fname )
32+ if os .path .exists (src ):
33+ shutil .copy (src , os .path .join (dest_folder , fname ))
34+
35+ # Copy inc/, src/, examples/
36+ shutil .copytree (os .path .join (api_folder , "inc" ), os .path .join (dest_folder , "inc" ))
37+ shutil .copytree (os .path .join (api_folder , "src" ), os .path .join (dest_folder , "src" ))
38+ if os .path .exists (examples_folder ):
39+ shutil .copytree (examples_folder , os .path .join (dest_folder , "examples" ))
40+
41+ def perform_replacements (dest_folder , sensor_type ):
42+ """Perform all requested replacements in C and H files."""
43+ print (f"Performing replacements in { dest_folder } for { sensor_type } ..." )
44+
45+ replacements = {
46+ # both sensors: platform header rename
47+ r"\bplatform\.h\b" : "vl53_platform.h" ,
48+ }
49+
50+ if sensor_type == "vl53l5cx" :
51+ replacements .update ({
52+ r"\bVL53L5CX_Platform\b" : "VL53_Platform" ,
53+ r"\bVL53L5CX_RdByte\b" : "VL53_RdByte" ,
54+ r"\bVL53L5CX_RdMulti\b" : "VL53_RdMulti" ,
55+ r"\bVL53L5CX_WrByte\b" : "VL53_WrByte" ,
56+ r"\bVL53L5CX_WrMulti\b" : "VL53_WrMulti" ,
57+ r"\bVL53L5CX_Reset_Sensor\b" : "VL53_Reset_Sensor" ,
58+ r"\bVL53L5CX_SwapBuffer\b" : "VL53_SwapBuffer" ,
59+ r"\bVL53L5CX_WaitMs\b" : "VL53_WaitMs" ,
60+ })
61+ elif sensor_type == "vl53lmz" :
62+ replacements .update ({
63+ r"\bVL53LMZ_Platform\b" : "VL53_Platform" ,
64+ r"\bRdByte\b" : "VL53_RdByte" ,
65+ r"\bRdMulti\b" : "VL53_RdMulti" ,
66+ r"\bWrByte\b" : "VL53_WrByte" ,
67+ r"\bWrMulti\b" : "VL53_WrMulti" ,
68+ r"\bReset_Sensor\b" : "VL53_Reset_Sensor" ,
69+ r"\bSwapBuffer\b" : "VL53_SwapBuffer" ,
70+ r"\bWaitMs\b" : "VL53_WaitMs" ,
71+ })
72+
73+ # Apply replacements recursively
74+ for root , _ , files in os .walk (dest_folder ):
75+ for fname in files :
76+ if fname .endswith ((".c" , ".h" )):
77+ path = os .path .join (root , fname )
78+ with open (path , "r" , encoding = "utf-8" ) as f :
79+ lines = f .readlines ()
80+
81+ new_lines = []
82+ for line in lines :
83+ # Skip any line containing "platform.address"
84+ if "platform.address" in line :
85+ continue
86+ new_lines .append (line )
87+
88+ content = "" .join (new_lines )
89+ for pattern , repl in replacements .items ():
90+ content = re .sub (pattern , repl , content )
91+
92+ with open (path , "w" , encoding = "utf-8" ) as f :
93+ f .write (content )
94+
95+
96+ def modify_examples (dest_folder , sensor_type ):
97+ """Rename .c to .h and update example function signatures and body."""
98+ examples_path = os .path .join (dest_folder , "examples" )
99+ if not os .path .exists (examples_path ):
100+ return
101+
102+ print (f"Updating example files in { examples_path } ..." )
103+
104+ for root , _ , files in os .walk (examples_path ):
105+ for fname in files :
106+ if not fname .endswith (".c" ):
107+ continue
108+
109+ old_path = os .path .join (root , fname )
110+ new_path = os .path .splitext (old_path )[0 ] + ".h"
111+ os .rename (old_path , new_path )
112+
113+ with open (new_path , "r" , encoding = "utf-8" ) as f :
114+ lines = f .readlines ()
115+
116+ new_lines = []
117+ inserted_transport = False
118+ for line in lines :
119+ # replace int example#(void) → int example#(void* transport)
120+ m = re .match (r"(\s*int\s+example\d+)\s*\(\s*void\s*\)" , line )
121+ if m :
122+ line = re .sub (r"\(\s*void\s*\)" , "(void* transport)" , line )
123+
124+ if "printf" in line and "integration_time" in line :
125+ if not re .search (r"\(int\)\s*integration_time\w*\b" , line ):
126+ line = re .sub (r"\bintegration_time(\w*)\b" , r"(int)integration_time\1" , line )
127+
128+ new_lines .append (line )
129+
130+ # after Dev declaration, insert Dev.platform.transport = transport;
131+ if ("VL53LMZ_Configuration" in line or "VL53L5CX_Configuration" in line ) and "Dev;" in line :
132+ new_lines .append (" Dev.platform.transport = transport;\n " )
133+ inserted_transport = True
134+
135+ if not inserted_transport :
136+ print (f"⚠️ Warning: Did not insert transport assignment in { new_path } " )
137+
138+ with open (new_path , "w" , encoding = "utf-8" ) as f :
139+ f .writelines (new_lines )
140+
141+ def cleanup (folder ):
142+ """Removes the extracted source folder and its empty parent."""
143+ if not os .path .exists (folder ):
144+ return
145+ print (f"Cleaning up { folder } ..." )
146+ parent = os .path .dirname (folder )
147+ shutil .rmtree (folder , ignore_errors = True )
148+ try :
149+ if os .path .exists (parent ) and not os .listdir (parent ):
150+ print (f"Removing empty parent folder { parent } ..." )
151+ os .rmdir (parent )
152+ except Exception :
153+ pass
154+
155+ def process_package (zip_path , folder_hint , api_hint , examples_hint , dest_folder , sensor_type ):
156+ """Processes one STMicro package end-to-end."""
157+ if not os .path .exists (zip_path ):
158+ print (f"❌ Error: { zip_path } not found." )
159+ return
160+
161+ extract_zip (zip_path )
162+ base_name = os .path .splitext (zip_path )[0 ]
163+
164+ # Try both extraction patterns
165+ root_folder = find_subfolder ("." , folder_hint )
166+ if root_folder is None :
167+ root_folder = find_subfolder (base_name , folder_hint )
168+ if root_folder is None :
169+ raise FileNotFoundError (f"Could not find '{ folder_hint } ' folder in extracted contents of { zip_path } " )
170+
171+ api_folder = find_subfolder (root_folder , api_hint )
172+ examples_folder = find_subfolder (root_folder , examples_hint )
173+
174+ if not all ([api_folder , examples_folder ]):
175+ raise FileNotFoundError (f"Missing expected subfolders in { root_folder } " )
176+
177+ copy_contents (api_folder , examples_folder , dest_folder )
178+ perform_replacements (dest_folder , sensor_type )
179+ modify_examples (dest_folder , sensor_type )
180+ cleanup (root_folder )
181+
182+ print (f"✅ Finished processing { zip_path } → { dest_folder } /\n " )
183+
184+ def main ():
185+ # Process VL53LMZ (STSW-IMG043_ULD.zip)
186+ process_package (
187+ zip_path = "STSW-IMG043_ULD.zip" ,
188+ folder_hint = "VL53LMZ_ULD_" ,
189+ api_hint = "VL53LMZ_ULD_API" ,
190+ examples_hint = "Examples" ,
191+ dest_folder = "vl53lmz" ,
192+ sensor_type = "vl53lmz"
193+ )
194+
195+ # Process VL53L5CX (STSW-IMG023.zip)
196+ process_package (
197+ zip_path = "STSW-IMG023.zip" ,
198+ folder_hint = "VL53L5CX_ULD_driver" ,
199+ api_hint = "VL53L5CX_ULD_API" ,
200+ examples_hint = "Examples" ,
201+ dest_folder = "vl53l5cx" ,
202+ sensor_type = "vl53l5cx"
203+ )
204+
205+ print ("🎉 All updates completed successfully." )
206+
207+ if __name__ == "__main__" :
208+ main ()
0 commit comments