|
10 | 10 | module_logger = logging.getLogger('blockly.loader') |
11 | 11 |
|
12 | 12 |
|
| 13 | +# Elements of WiFi Port Records (wports) |
| 14 | +wpUID = 0 |
| 15 | +wpName = 1 |
| 16 | +wpIP = 2 |
| 17 | +wpMAC = 3 |
| 18 | +wpLife = 4 |
| 19 | + |
| 20 | +# Max lifetime+1 for WiFi Port Records to remain without refresh |
| 21 | +MaxLife = 4 |
| 22 | + |
| 23 | + |
13 | 24 | class PropellerLoad: |
14 | 25 | loading = False |
15 | | - # COM & WiFi-Name ports list |
| 26 | + # COM & WiFi-UID (unique name) ports list |
16 | 27 | ports = [] |
17 | | - # Full WiFi ports list |
| 28 | + # WiFi Port Record list |
18 | 29 | wports = [] |
19 | 30 |
|
20 | 31 |
|
@@ -69,12 +80,10 @@ def get_ports(self): |
69 | 80 | # Get Wi-Fi ports |
70 | 81 | (success, out, err) = loader(self, ["-W"]) |
71 | 82 | if success: |
72 | | - # Save Wi-Fi port record(s) |
73 | | - self.wports = out.splitlines() |
74 | | - # Extract Wi-Fi module names (from Wi-Fi records) and sort them |
75 | | - wnames = [] |
76 | | - for i in range(len(self.wports)): |
77 | | - wnames.extend([getWiFiName(self.wports[i])]) |
| 83 | + # Save Wi-Fi port records (in self.wports) |
| 84 | + updateWiFiPorts(self, out.splitlines()) |
| 85 | + # Extract unique Wi-Fi module names (UID; from Wi-Fi records) and sort them |
| 86 | + wnames = [wifiports[wpUID] for wifiports in self.wports] |
78 | 87 | wnames.sort(None, None, False) |
79 | 88 | else: |
80 | 89 | self.logger.debug('WiFi Port request returned %s', err) |
@@ -115,12 +124,13 @@ def download(self, action, file_to_load, com_port): |
115 | 124 | # Add requested port |
116 | 125 | if com_port is not None: |
117 | 126 | # Find port(s) named com_port |
118 | | - targetWiFi = [l for l in self.wports if isWiFiName(l, com_port)] |
119 | | - if len(targetWiFi) > 0: |
| 127 | + if com_port in [wifiports[wpUID] for wifiports in self.wports]: |
120 | 128 | # Found Wi-Fi match |
121 | | - self.logger.debug('Requested port %s is at %s', com_port, getWiFiIP(targetWiFi[0])) |
| 129 | + idx = [wifiports[wpUID] for wifiports in self.wports].index(com_port) |
| 130 | + IPAddr = [wifiports[wpIP] for wifiports in self.wports][idx] |
| 131 | + self.logger.debug('Requested port %s is at %s', com_port, IPAddr) |
122 | 132 | command.extend(["-i"]) |
123 | | - command.extend([getWiFiIP(targetWiFi[0]).encode('ascii', 'ignore')]) |
| 133 | + command.extend([IPAddr.encode('ascii', 'ignore')]) |
124 | 134 | else: |
125 | 135 | # Not Wi-Fi match, should be COM port |
126 | 136 | self.logger.debug('Requested port is %s', com_port) |
@@ -179,7 +189,57 @@ def loader(self, cmdOptions): |
179 | 189 | return False, '', 'Exception: OSError' |
180 | 190 |
|
181 | 191 |
|
182 | | - |
| 192 | +def updateWiFiPorts(self, wstrings): |
| 193 | +# Merge wstrings into WiFi Ports list |
| 194 | +# Ensures unique entries (UIDs), updates existing entries, and removes ancient entries |
| 195 | +# Records "age" with each update unless refreshed by a matching port; those older than MaxLife-1 are considered ancient |
| 196 | + for newPort in wstrings: |
| 197 | + # Search for MAC address in known ports |
| 198 | + if not getWiFiMAC(newPort) in [port[wpMAC] for port in self.wports]: |
| 199 | + # No MAC match, enter as unique port record |
| 200 | + enterUniqueWiFiPort(self, newPort) |
| 201 | + else: |
| 202 | + # Found MAC match, update record as necessary |
| 203 | + idx = [port[wpMAC] for port in self.wports].index(getWiFiMAC(newPort)) |
| 204 | + if self.wports[idx][wpName] == getWiFiName(newPort): |
| 205 | + # Name hasn't changed; leave Name and UID, update IP and Life |
| 206 | + self.wports[idx][wpIP] = getWiFiIP(newPort) |
| 207 | + self.wports[idx][wpLife] = MaxLife |
| 208 | + else: |
| 209 | + # Name has changed; replace entire record with guaranteed-unique entry |
| 210 | + self.wports.pop(idx) |
| 211 | + enterUniqueWiFiPort(self, newPort) |
| 212 | + |
| 213 | + # Age records |
| 214 | + for port in self.wports: |
| 215 | + port[wpLife] = port[wpLife] - 1 |
| 216 | + # Remove ancients |
| 217 | + while 0 in [port[wpLife] for port in self.wports]: |
| 218 | + self.wports.pop([port[wpLife] for port in self.wports].index(0)) |
| 219 | + |
| 220 | + |
| 221 | +def enterUniqueWiFiPort(self, newPort): |
| 222 | +# Enter newPort as unique port record |
| 223 | +# If name matches another, it will be made unique by appending one or more if its MAC digits |
| 224 | + # Start with UID = Name |
| 225 | + Name = getWiFiName(newPort)+'-' |
| 226 | + UID = Name[:-1] |
| 227 | + # Prep modifer (MAC address without colons) |
| 228 | + Modifier = getWiFiMAC(newPort).replace(":", "") |
| 229 | + |
| 230 | + # Check for unique name (UID) |
| 231 | + Size = 1 |
| 232 | + while UID in [port[wpUID] for port in self.wports]: |
| 233 | + # Name is duplicate; modify for unique name |
| 234 | + UID = Name + Modifier[-Size:] |
| 235 | + Size += 1 |
| 236 | + if Size == len(Modifier): |
| 237 | + # Ran out of digits? Repeat Modifier |
| 238 | + Name = UID |
| 239 | + Size = 0 |
| 240 | + |
| 241 | + # UID is unique, create new entry (UID, Name, IP, MAC, MaxLife) |
| 242 | + self.wports.append([UID, getWiFiName(newPort), getWiFiIP(newPort), getWiFiMAC(newPort), MaxLife]) |
183 | 243 |
|
184 | 244 |
|
185 | 245 |
|
|
0 commit comments