Parse MSP messages from the backpack while TX is in mavlink mode (#2883)
[ExpressLRS.git] / src / python / build_flags.py
blob80143ee76a13d63775b5debf9745863405e372bc
1 Import("env")
2 from genericpath import exists
3 import os
4 from random import randint
5 import sys
6 import hashlib
7 import fnmatch
8 import time
9 import re
10 import melodyparser
11 import elrs_helpers
13 build_flags = env.get('BUILD_FLAGS', [])
14 json_flags = {}
15 UIDbytes = ""
16 define = ""
17 target_name = env.get('PIOENV', '').upper()
19 isRX = True if '_RX_' in target_name else False
21 def print_error(error):
22 time.sleep(1)
23 sys.stdout.write("\n\n\033[47;31m%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n")
24 sys.stdout.write("\033[47;31m!!! ExpressLRS Warning Below !!!\n")
25 sys.stdout.write("\033[47;31m%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n")
26 sys.stdout.write("\033[47;30m %s \n" % error)
27 sys.stdout.write("\033[47;31m%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n\n")
28 sys.stdout.flush()
29 time.sleep(3)
30 raise Exception('!!! %s !!!' % error)
33 def dequote(str):
34 if str[0] == '"' and str[-1] == '"':
35 return str[1:-1]
36 return str
38 def process_json_flag(define):
39 parts = re.search(r"-D(.*)\s*=\s*(.*)$", define)
40 if parts and define.startswith("-D"):
41 if parts.group(1) == "MY_BINDING_PHRASE":
42 json_flags['uid'] = [x for x in hashlib.md5(define.encode()).digest()[0:6]]
43 if parts.group(1) == "HOME_WIFI_SSID":
44 json_flags['wifi-ssid'] = dequote(parts.group(2))
45 if parts.group(1) == "HOME_WIFI_PASSWORD":
46 json_flags['wifi-password'] = dequote(parts.group(2))
47 if parts.group(1) == "AUTO_WIFI_ON_INTERVAL":
48 parts = re.search(r"-D(.*)\s*=\s*\"?([0-9]+).*\"?$", define)
49 json_flags['wifi-on-interval'] = int(dequote(parts.group(2)))
50 if parts.group(1) == "TLM_REPORT_INTERVAL_MS" and not isRX:
51 parts = re.search(r"-D(.*)\s*=\s*\"?([0-9]+).*\"?$", define)
52 json_flags['tlm-interval'] = int(dequote(parts.group(2)))
53 if parts.group(1) == "FAN_MIN_RUNTIME" and not isRX:
54 parts = re.search(r"-D(.*)\s*=\s*\"?([0-9]+).*\"?$", define)
55 json_flags['fan-runtime'] = int(dequote(parts.group(2)))
56 if parts.group(1) == "RCVR_UART_BAUD" and isRX:
57 parts = re.search(r"-D(.*)\s*=\s*\"?([0-9]+).*\"?$", define)
58 json_flags['rcvr-uart-baud'] = int(dequote(parts.group(2)))
59 if parts.group(1) == "USE_AIRPORT_AT_BAUD":
60 parts = re.search(r"-D(.*)\s*=\s*\"?([0-9]+).*\"?$", define)
61 json_flags['is-airport'] = True
62 if isRX:
63 json_flags['rcvr-uart-baud'] = int(dequote(parts.group(2)))
64 else:
65 json_flags['airport-uart-baud'] = int(dequote(parts.group(2)))
66 if define == "-DUNLOCK_HIGHER_POWER" and not isRX:
67 json_flags['unlock-higher-power'] = True
68 if define == "-DLOCK_ON_FIRST_CONNECTION" and isRX:
69 json_flags['lock-on-first-connection'] = True
71 def process_build_flag(define):
72 if define.startswith("-D") or define.startswith("!-D"):
73 if "MY_BINDING_PHRASE" in define:
74 bindingPhraseHash = hashlib.md5(define.encode()).digest()
75 UIDbytes = ",".join(list(map(str, bindingPhraseHash))[0:6])
76 define = "-DMY_UID=" + UIDbytes
77 sys.stdout.write("\u001b[32mUID bytes: " + UIDbytes + "\n")
78 sys.stdout.flush()
79 if "MY_STARTUP_MELODY=" in define:
80 parsedMelody = melodyparser.parse(define.split('"')[1::2][0])
81 define = "-DMY_STARTUP_MELODY_ARR=\"" + parsedMelody + "\""
82 if "HOME_WIFI_SSID=" in define:
83 parts = re.search(r"(.*)=\w*\"(.*)\"$", define)
84 if parts and parts.group(2):
85 define = "-DHOME_WIFI_SSID=" + string_to_ascii(parts.group(2))
86 if "HOME_WIFI_PASSWORD=" in define:
87 parts = re.search(r"(.*)=\w*\"(.*)\"$", define)
88 if parts and parts.group(2):
89 define = "-DHOME_WIFI_PASSWORD=" + string_to_ascii(parts.group(2))
90 if "DEVICE_NAME=" in define:
91 parts = re.search(r"(.*)=\w*'?\"(.*)\"'?$", define)
92 if parts and parts.group(2):
93 env['DEVICE_NAME'] = parts.group(2)
94 if not define in build_flags:
95 build_flags.append(define)
97 def parse_flags(path):
98 global build_flags
99 global json_flags
100 try:
101 with open(path, "r") as _f:
102 for define in _f:
103 define = define.strip()
104 process_build_flag(define)
105 process_json_flag(define)
107 except IOError:
108 print("File '%s' does not exist" % path)
110 def process_flags(path):
111 global build_flags
112 if not os.path.isfile(path):
113 return
114 parse_flags(path)
116 def condense_flags():
117 global build_flags
118 for line in build_flags:
119 # Some lines have multiple flags so this will split them and remove them all
120 for flag in re.findall(r"!-D\s*[^\s]+", line):
121 build_flags = [x.replace(flag,"") for x in build_flags] # remove the removal flag
122 build_flags = [x.replace(flag[1:],"") for x in build_flags] # remove the flag if it matches the removal flag
123 build_flags = [x for x in build_flags if (x.strip() != "")] # remove any blank items
125 def version_to_env():
126 ver = elrs_helpers.get_git_version()
127 env.Append(GIT_SHA = ver['sha'], GIT_VERSION= ver['version'])
129 def string_to_ascii(str):
130 return ",".join(["%s" % ord(char) for char in str])
132 def get_git_sha():
133 return string_to_ascii(env.get('GIT_SHA'))
135 def get_version():
136 return string_to_ascii(env.get('GIT_VERSION'))
138 json_flags['flash-discriminator'] = randint(1,2**32-1)
139 json_flags['wifi-on-interval'] = -1
141 process_flags("user_defines.txt")
142 process_flags("super_defines.txt") # allow secret super_defines to override user_defines
143 version_to_env()
144 build_flags.append("-DLATEST_COMMIT=" + get_git_sha())
145 build_flags.append("-DLATEST_VERSION=" + get_version())
146 build_flags.append("-DTARGET_NAME=" + re.sub("_VIA_.*", "", target_name))
147 condense_flags()
149 if '-DRADIO_SX127X=1' in build_flags or '-DRADIO_LR1121=1' in build_flags:
150 # disallow setting 2400s for 900
151 if fnmatch.filter(build_flags, '*-DRegulatory_Domain_ISM_2400') or \
152 fnmatch.filter(build_flags, '*-DRegulatory_Domain_EU_CE_2400'):
153 print_error('Regulatory_Domain 2400 not compatible with RADIO_SX127X/RADIO_LR1121')
155 # require a domain be set for 900
156 if not fnmatch.filter(build_flags, '*-DRegulatory_Domain*'):
157 print_error('Please define a Regulatory_Domain in user_defines.txt')
159 if fnmatch.filter(build_flags, '*-DRegulatory_Domain_AU_915'):
160 json_flags['domain'] = 0
161 if fnmatch.filter(build_flags, '*-DRegulatory_Domain_FCC_915'):
162 json_flags['domain'] = 1
163 if fnmatch.filter(build_flags, '*-DRegulatory_Domain_EU_868'):
164 json_flags['domain'] = 2
165 if fnmatch.filter(build_flags, '*-DRegulatory_Domain_IN_866'):
166 json_flags['domain'] = 3
167 if fnmatch.filter(build_flags, '*-DRegulatory_Domain_AU_433'):
168 json_flags['domain'] = 4
169 if fnmatch.filter(build_flags, '*-DRegulatory_Domain_EU_433'):
170 json_flags['domain'] = 5
171 if fnmatch.filter(build_flags, '*-DRegulatory_Domain_US_433'):
172 json_flags['domain'] = 6
173 if fnmatch.filter(build_flags, '*-DRegulatory_Domain_US_433_WIDE'):
174 json_flags['domain'] = 7
175 else:
176 json_flags['domain'] = 0
178 # Remove ISM_2400 domain flag if not unit test, it is defined per target config
179 if fnmatch.filter(build_flags, '*Regulatory_Domain_ISM_2400*') and \
180 target_name != "NATIVE":
181 build_flags = [f for f in build_flags if "Regulatory_Domain_ISM_2400" not in f]
183 env['OPTIONS_JSON'] = json_flags
184 env['BUILD_FLAGS'] = build_flags
185 sys.stdout.write("\nbuild flags: %s\n\n" % build_flags)
187 if fnmatch.filter(build_flags, '*PLATFORM_ESP32*'):
188 sys.stdout.write("\u001b[32mBuilding for ESP32 Platform\n")
189 elif fnmatch.filter(build_flags, '*PLATFORM_STM32*'):
190 sys.stdout.write("\u001b[32mBuilding for STM32 Platform\n")
191 elif fnmatch.filter(build_flags, '*PLATFORM_ESP8266*'):
192 sys.stdout.write("\u001b[32mBuilding for ESP8266/ESP8285 Platform\n")
193 if fnmatch.filter(build_flags, '-DAUTO_WIFI_ON_INTERVAL*'):
194 sys.stdout.write("\u001b[32mAUTO_WIFI_ON_INTERVAL = ON\n")
195 else:
196 sys.stdout.write("\u001b[32mAUTO_WIFI_ON_INTERVAL = OFF\n")
198 sys.stdout.flush()
199 time.sleep(.5)
201 # Set upload_protovol = 'custom' for STM32 MCUs
202 # otherwise firmware.bin is not generated
203 stm = env.get('PIOPLATFORM', '') in ['ststm32']
204 if stm:
205 env['UPLOAD_PROTOCOL'] = 'custom'
206 # -DFLASH_DISCRIM=xxxx can't be passed on the command line or it will every file to
207 # always be rebuilt, so put it in a header that options.cpp can include
208 print(f"#define FLASH_DISCRIM {json_flags['flash-discriminator']}",
209 file=open("include/flashdiscrim.h", "w"))