Fix device listing parser to match bash script logic

The Python parser was waiting for password= which comes much later
in the auth section. Rewrote to match the simpler bash approach:
- Find device comment line, parse name/category/AA tag
- Find next [extension] line, add device to list
- Update transport/encryption if found in following lines

This matches how show_registered_devices() works in bash.
This commit is contained in:
Claude
2025-12-23 02:28:45 +00:00
parent ccb5a5560f
commit 9f6033fd03
+49 -41
View File
@@ -3773,58 +3773,66 @@ def get_registered_endpoints():
return {} return {}
def get_devices(): def get_devices():
"""Parse pjsip.conf to get device information""" """Parse pjsip.conf to get device information - matches bash script logic"""
devices = [] devices = []
if not os.path.exists(PJSIP_CONF): if not os.path.exists(PJSIP_CONF):
return devices return devices
with open(PJSIP_CONF, 'r') as f: with open(PJSIP_CONF, 'r') as f:
content = f.read() lines = f.readlines()
# Parse devices using a state machine approach dev_name = None
current_device = None dev_cat = None
current_ext = None dev_aa = None
for line in content.split('\n'): for line in lines:
line = line.strip() line = line.strip()
# Match device comment line (handles variable spacing before ===) # Match device comment line
if line.startswith('; === Device:'): if '; === Device:' in line:
match = re.match(r'; === Device:\s*(.+?)\s*\((\w+)\)\s*(\[AA:(yes|no)\])?\s*===', line) # Parse: ; === Device: Name (category) [AA:yes/no] ===
if match: temp = line.split('; === Device:')[1] if '; === Device:' in line else ''
current_device = { temp = temp.split('===')[0].strip() # Remove trailing ===
'name': match.group(1).strip(),
'category': match.group(2), # Check for AA tag
'auto_answer': match.group(4) if match.group(3) else None, dev_aa = None
'extension': None, if '[AA:yes]' in temp:
'password': None, dev_aa = 'yes'
'transport': 'udp', temp = temp.replace('[AA:yes]', '').strip()
elif '[AA:no]' in temp:
dev_aa = 'no'
temp = temp.replace('[AA:no]', '').strip()
# Extract category from parentheses
if '(' in temp and ')' in temp:
dev_cat = temp[temp.rfind('(')+1:temp.rfind(')')]
dev_name = temp[:temp.rfind('(')].strip()
else:
dev_name = temp
dev_cat = 'unknown'
# Match extension line [xxx]
elif dev_name and re.match(r'^\[(\d+)\]$', line):
ext = re.match(r'^\[(\d+)\]$', line).group(1)
devices.append({
'name': dev_name,
'category': dev_cat,
'extension': ext,
'auto_answer': dev_aa,
'transport': 'udp', # Default, will check below
'encryption': 'no' 'encryption': 'no'
} })
current_ext = None dev_name = None
dev_cat = None
dev_aa = None
# Match extension section header # Update transport/encryption for last added device
elif current_device and re.match(r'^\[(\d{3})\]$', line): elif devices and line.startswith('transport=transport-'):
ext = re.match(r'^\[(\d{3})\]$', line).group(1) devices[-1]['transport'] = line.split('transport-')[1]
if current_device['extension'] is None: elif devices and line.startswith('media_encryption='):
current_device['extension'] = ext val = line.split('=')[1]
current_ext = ext if val != 'no':
elif ext == current_ext: devices[-1]['encryption'] = val
# Same extension, could be auth or aor section
pass
# Parse properties within sections
elif current_device and current_ext:
if line.startswith('transport=transport-'):
current_device['transport'] = line.split('-')[1]
elif line.startswith('media_encryption='):
current_device['encryption'] = line.split('=')[1]
elif line.startswith('password='):
current_device['password'] = line.split('=')[1]
# Found password, device is complete
devices.append(current_device)
current_device = None
current_ext = None
return devices return devices