several dvmcfggen fixes: correct HEX vs DEC issues reported by digilink/TAC-10; correct indentation issue for voiceChNo reported by digilink/TAC-10; fix missing configuration parameter;

r05a06_dev
Bryan Biedenkapp 4 days ago
parent 493ef2a728
commit 92bea91a5b

@ -35,6 +35,55 @@ from typing import Dict, Any, Optional, List
import re import re
class HexInt(int):
"""Marker type for integers that should be emitted in hexadecimal."""
class DVMConfigDumper(yaml.SafeDumper):
"""Custom YAML dumper with consistent list indentation and NAC hex output."""
def increase_indent(self, flow=False, indentless=False):
# Force sequence items to be indented under mapping keys.
return super().increase_indent(flow, False)
def _represent_hex_int(dumper, data):
"""Represent marked integers as YAML int scalars in hex format."""
hex_value = f'{int(data):X}'
# YAML only accepts decimal/octal/0x-prefixed ints; bare A-F text must be a string.
if any(ch in 'ABCDEF' for ch in hex_value):
return dumper.represent_scalar('tag:yaml.org,2002:str', hex_value)
return dumper.represent_scalar('tag:yaml.org,2002:int', hex_value)
DVMConfigDumper.add_representer(HexInt, _represent_hex_int)
def _mark_hex_fields(value: Any, key: Optional[str] = None) -> Any:
"""Recursively mark NAC-like fields for hexadecimal YAML serialization."""
hex_keys = {
'nac',
'txNAC',
'p25NAC',
'netId',
'p25NetId',
'sysId',
'rfssId',
'siteId',
'dmrNetId',
'channelNo',
'rxChannelNo',
}
if isinstance(value, dict):
return {k: _mark_hex_fields(v, k) for k, v in value.items()}
if isinstance(value, list):
return [_mark_hex_fields(item) for item in value]
if key in hex_keys and isinstance(value, int):
return HexInt(value)
return value
class ConfigValidator: class ConfigValidator:
"""Validates DVMHost configuration values""" """Validates DVMHost configuration values"""
@ -111,8 +160,16 @@ class DVMConfig:
backup_path = path.with_suffix(path.suffix + '.bak') backup_path = path.with_suffix(path.suffix + '.bak')
path.rename(backup_path) path.rename(backup_path)
config_to_write = _mark_hex_fields(self.config)
with open(path, 'w') as f: with open(path, 'w') as f:
yaml.dump(self.config, f, default_flow_style=False, sort_keys=False) yaml.dump(
config_to_write,
f,
Dumper=DVMConfigDumper,
default_flow_style=False,
sort_keys=False,
)
def get(self, key_path: str, default: Any = None) -> Any: def get(self, key_path: str, default: Any = None) -> Any:
""" """

@ -76,6 +76,7 @@ def load_base_config() -> Dict[str, Any]:
def get_minimal_fallback_config() -> Dict[str, Any]: def get_minimal_fallback_config() -> Dict[str, Any]:
"""Minimal fallback configuration if config.example.yml is not available""" """Minimal fallback configuration if config.example.yml is not available"""
return { return {
'iAgreeNotToBeStupid': True,
'daemon': True, 'daemon': True,
'log': { 'log': {
'displayLevel': 1, 'displayLevel': 1,
@ -187,6 +188,9 @@ def apply_template_customizations(config: Dict[str, Any], template_type: str) ->
import copy import copy
config = copy.deepcopy(config) config = copy.deepcopy(config)
# Generated configs must explicitly include license acknowledgement.
config['iAgreeNotToBeStupid'] = True
if template_type == 'control-channel-p25': if template_type == 'control-channel-p25':
# P25 dedicated control channel # P25 dedicated control channel
config['system']['duplex'] = True config['system']['duplex'] = True

Loading…
Cancel
Save

Powered by TurnKey Linux.