Update CHANGELOG, enhance configuration loading with default values, and add tests for missing defaults

This commit is contained in:
sh4un
2026-01-22 17:20:30 -05:00
parent d197be89f2
commit e9ebb338b4
6 changed files with 45 additions and 18 deletions

View File

@@ -4,11 +4,11 @@
## Version 2.0.0 - Comprehensive Code Review and Enhancements (December 31, 2025)
### 🐛 Bug Fixes
### Bug Fixes
- **Fixed test file errors**: Corrected incomplete string in `test_config_handler.py` and wrong function name in `test_protocol.py`
- **Fixed missing method**: Added `_on_log` method to `MQTTHandler` that was referenced but not defined
### New Features
### New Features
#### 1. Metrics and Statistics Collection
- **New Module**: `ammb/metrics.py`
@@ -70,7 +70,7 @@
- Configurable insecure mode (for testing)
- Automatic TLS context creation
### 🔧 Enhancements
### Enhancements
#### Configuration System
- Added API configuration options:
@@ -111,32 +111,32 @@
- Enhanced shutdown sequence
- Better error handling and logging
### 📊 Performance Optimizations
### Performance Optimizations
- Thread-safe metrics collection
- Non-blocking message logging
- Efficient rate limiting algorithm
- Optimized health check intervals
- Reduced lock contention
### 🛡️ Security Enhancements
### Security Enhancements
- Message validation prevents malformed data
- Rate limiting prevents message flooding
- TLS/SSL support for secure MQTT
- Input sanitization prevents injection attacks
- Node ID validation prevents spoofing
### 📝 Documentation
### Documentation
- Updated README.md with new features
- Enhanced configuration examples
- Added API endpoint documentation
- Improved code comments and docstrings
### 🧪 Testing
### Testing
- Fixed broken test files
- All modules compile successfully
- No linter errors
### 🔄 Backward Compatibility
### Backward Compatibility
- All new features are optional and configurable
- Default behavior maintains backward compatibility
- Existing configurations continue to work

View File

@@ -100,14 +100,12 @@ def load_config(config_path: str = CONFIG_FILE) -> Optional[BridgeConfig]:
if 'DEFAULT' not in config.sections():
logger.warning(f"Configuration file '{config_path}' lacks the [DEFAULT] section. Using only defaults.")
cfg_section = config.defaults()
else:
cfg_section = config['DEFAULT']
meshtastic_port = cfg_section.get('MESHTASTIC_SERIAL_PORT')
external_network_id = cfg_section.get('EXTERNAL_NETWORK_ID')
bridge_node_id = cfg_section.get('BRIDGE_NODE_ID')
log_level = cfg_section.get('LOG_LEVEL').upper()
meshtastic_port = cfg_section.get('MESHTASTIC_SERIAL_PORT', fallback=DEFAULT_CONFIG['MESHTASTIC_SERIAL_PORT'])
external_network_id = cfg_section.get('EXTERNAL_NETWORK_ID', fallback=DEFAULT_CONFIG['EXTERNAL_NETWORK_ID'])
bridge_node_id = cfg_section.get('BRIDGE_NODE_ID', fallback=DEFAULT_CONFIG['BRIDGE_NODE_ID'])
log_level = cfg_section.get('LOG_LEVEL', fallback=DEFAULT_CONFIG['LOG_LEVEL']).upper()
if log_level not in VALID_LOG_LEVELS:
logger.error(f"Invalid LOG_LEVEL '{log_level}'. Must be one of: {VALID_LOG_LEVELS}")
@@ -121,7 +119,7 @@ def load_config(config_path: str = CONFIG_FILE) -> Optional[BridgeConfig]:
logger.error(f"Invalid integer value for MESSAGE_QUEUE_SIZE: {e}")
return None
external_transport = cfg_section.get('EXTERNAL_TRANSPORT').lower()
external_transport = cfg_section.get('EXTERNAL_TRANSPORT', fallback=DEFAULT_CONFIG['EXTERNAL_TRANSPORT']).lower()
if external_transport not in VALID_TRANSPORTS:
logger.error(f"Invalid EXTERNAL_TRANSPORT '{external_transport}'. Must be one of: {VALID_TRANSPORTS}")
return None
@@ -140,8 +138,8 @@ def load_config(config_path: str = CONFIG_FILE) -> Optional[BridgeConfig]:
mqtt_retain_out = None
if external_transport == 'serial':
serial_port = cfg_section.get('SERIAL_PORT')
serial_protocol = cfg_section.get('SERIAL_PROTOCOL').lower()
serial_port = cfg_section.get('SERIAL_PORT', fallback=DEFAULT_CONFIG['SERIAL_PORT'])
serial_protocol = cfg_section.get('SERIAL_PROTOCOL', fallback=DEFAULT_CONFIG['SERIAL_PROTOCOL']).lower()
if not serial_port:
logger.error("SERIAL_PORT must be set when EXTERNAL_TRANSPORT is 'serial'.")
return None

View File

@@ -0,0 +1,14 @@
import importlib.util
def test_load_config_missing_default(tmp_path):
cfgfile = tmp_path / "no_default.ini"
cfgfile.write_text("[serial]\nSERIAL_PORT=/dev/ttyS1\n")
spec = importlib.util.spec_from_file_location('config_handler', 'ammb/config_handler.py')
mod = importlib.util.module_from_spec(spec)
spec.loader.exec_module(mod)
cfg = mod.load_config(str(cfgfile))
assert cfg is not None
assert cfg.log_level == 'INFO'

2
tmp_no_default.ini Normal file
View File

@@ -0,0 +1,2 @@
[serial]
SERIAL_PORT = /dev/ttyS1

6
tmp_run_load.py Normal file
View File

@@ -0,0 +1,6 @@
import importlib.util
spec = importlib.util.spec_from_file_location('config_handler', 'ammb/config_handler.py')
mod = importlib.util.module_from_spec(spec)
spec.loader.exec_module(mod)
print('Using file: tmp_no_default.ini')
print(mod.load_config('tmp_no_default.ini'))

7
tmp_test_config.py Normal file
View File

@@ -0,0 +1,7 @@
from ammb import config_handler
path='tmp_no_default.ini'
with open(path,'w') as f:
f.write('[serial]\nSERIAL_PORT=/dev/ttyS1\n')
print('Using file:', path)
cfg = config_handler.load_config(path)
print('Result:', cfg)