feat: Add comprehensive NL-43/NL-53 Communication Guide and command references
- Introduced a new communication guide detailing protocol basics, transport modes, and a quick startup checklist. - Added a detailed list of commands with their functions and usage for NL-43/NL-53 devices. - Created a verified quick reference for command formats to prevent common mistakes. - Implemented an improvements document outlining critical fixes, security enhancements, reliability upgrades, and code quality improvements for the SLMM project. - Enhanced the frontend with a new button to retrieve all device settings, along with corresponding JavaScript functionality. - Added a test script for the new settings retrieval API endpoint to demonstrate its usage and validate functionality.
This commit is contained in:
195
FEATURE_SUMMARY.md
Normal file
195
FEATURE_SUMMARY.md
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
# Feature Summary: Device Settings Verification
|
||||||
|
|
||||||
|
## What Was Added
|
||||||
|
|
||||||
|
A new API endpoint that retrieves all current device settings in a single request, allowing users to quickly verify the NL43/NL53 configuration before starting measurements.
|
||||||
|
|
||||||
|
## New Endpoint
|
||||||
|
|
||||||
|
**`GET /api/nl43/{unit_id}/settings`**
|
||||||
|
|
||||||
|
Returns comprehensive device configuration including:
|
||||||
|
- Measurement state and weighting settings
|
||||||
|
- Timing and interval configuration
|
||||||
|
- Battery level and device clock
|
||||||
|
- Sleep mode and FTP status
|
||||||
|
|
||||||
|
## Files Modified
|
||||||
|
|
||||||
|
### 1. [app/routers.py](app/routers.py)
|
||||||
|
**Lines:** 728-761
|
||||||
|
|
||||||
|
Added new route handler `get_all_settings()` that:
|
||||||
|
- Validates device configuration exists
|
||||||
|
- Checks TCP communication is enabled
|
||||||
|
- Calls `NL43Client.get_all_settings()`
|
||||||
|
- Returns formatted JSON response with all settings
|
||||||
|
- Handles connection errors, timeouts, and exceptions
|
||||||
|
|
||||||
|
### 2. [README.md](README.md)
|
||||||
|
**Updated sections:**
|
||||||
|
- Line 134: Added new endpoint to Measurement Settings table
|
||||||
|
- Lines 259-283: Added usage example showing how to verify device settings
|
||||||
|
|
||||||
|
## Files Created
|
||||||
|
|
||||||
|
### 1. [test_settings_endpoint.py](test_settings_endpoint.py)
|
||||||
|
Test/demonstration script showing:
|
||||||
|
- How to use the `get_all_settings()` method
|
||||||
|
- Example API endpoint usage with curl
|
||||||
|
- Expected response format
|
||||||
|
|
||||||
|
### 2. [SETTINGS_ENDPOINT.md](SETTINGS_ENDPOINT.md)
|
||||||
|
Comprehensive documentation including:
|
||||||
|
- Detailed endpoint description
|
||||||
|
- Complete list of settings retrieved
|
||||||
|
- Usage examples in bash, Python, and JavaScript
|
||||||
|
- Performance considerations
|
||||||
|
- Best practices and troubleshooting
|
||||||
|
|
||||||
|
### 3. [FEATURE_SUMMARY.md](FEATURE_SUMMARY.md)
|
||||||
|
This file - summary of changes for reference
|
||||||
|
|
||||||
|
## Existing Functionality Used
|
||||||
|
|
||||||
|
The implementation leverages the existing `get_all_settings()` method in [app/services.py](app/services.py#L538) which was already implemented but not exposed via the API. This method queries multiple device settings and handles errors gracefully.
|
||||||
|
|
||||||
|
## How It Works
|
||||||
|
|
||||||
|
1. **User makes GET request** to `/api/nl43/{unit_id}/settings`
|
||||||
|
2. **Router validates** device configuration exists and TCP is enabled
|
||||||
|
3. **NL43Client queries device** for each setting sequentially (with 1-second delays)
|
||||||
|
4. **Individual errors** are caught and returned as error strings
|
||||||
|
5. **Response returned** with all settings in JSON format
|
||||||
|
|
||||||
|
## Usage Example
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Quick verification before measurement
|
||||||
|
curl http://localhost:8100/api/nl43/NL43-001/settings
|
||||||
|
|
||||||
|
# Response:
|
||||||
|
{
|
||||||
|
"status": "ok",
|
||||||
|
"unit_id": "NL43-001",
|
||||||
|
"settings": {
|
||||||
|
"measurement_state": "Stop",
|
||||||
|
"frequency_weighting": "A",
|
||||||
|
"time_weighting": "F",
|
||||||
|
"measurement_time": "00:01:00",
|
||||||
|
"leq_interval": "1s",
|
||||||
|
"lp_interval": "125ms",
|
||||||
|
"index_number": "0",
|
||||||
|
"battery_level": "100%",
|
||||||
|
"clock": "2025/12/24,20:45:30",
|
||||||
|
"sleep_mode": "Off",
|
||||||
|
"ftp_status": "On"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Benefits
|
||||||
|
|
||||||
|
1. **Single request** - Get all settings at once instead of multiple API calls
|
||||||
|
2. **Pre-flight checks** - Verify configuration before starting measurements
|
||||||
|
3. **Documentation** - Easy to save configuration snapshots for audit trails
|
||||||
|
4. **Troubleshooting** - Quickly identify misconfigured settings
|
||||||
|
5. **Multi-device** - Compare settings across multiple devices
|
||||||
|
|
||||||
|
## Performance Notes
|
||||||
|
|
||||||
|
- **Query time:** ~10-15 seconds (due to required 1-second delays between commands)
|
||||||
|
- **Rate limiting:** Automatically enforced by NL43Client
|
||||||
|
- **Error handling:** Partial failures don't prevent other settings from being retrieved
|
||||||
|
- **Caching recommended:** Settings don't change frequently, cache for 5-10 minutes
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
To test the new endpoint:
|
||||||
|
|
||||||
|
1. **Start the server:**
|
||||||
|
```bash
|
||||||
|
uvicorn app.main:app --reload --port 8100
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Configure a device** (if not already configured):
|
||||||
|
```bash
|
||||||
|
curl -X PUT http://localhost:8100/api/nl43/test-meter/config \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"host": "192.168.1.100", "tcp_port": 80, "tcp_enabled": true}'
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Query settings:**
|
||||||
|
```bash
|
||||||
|
curl http://localhost:8100/api/nl43/test-meter/settings
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Check Swagger UI:**
|
||||||
|
- Navigate to http://localhost:8100/docs
|
||||||
|
- Find "GET /api/nl43/{unit_id}/settings" endpoint
|
||||||
|
- Click "Try it out" and test interactively
|
||||||
|
|
||||||
|
## Integration Tips
|
||||||
|
|
||||||
|
### Frontend Integration
|
||||||
|
```javascript
|
||||||
|
// React/Vue/Angular example
|
||||||
|
async function verifyDeviceBeforeMeasurement(unitId) {
|
||||||
|
const response = await fetch(`/api/nl43/${unitId}/settings`);
|
||||||
|
const { settings } = await response.json();
|
||||||
|
|
||||||
|
// Verify critical settings
|
||||||
|
if (settings.frequency_weighting !== 'A') {
|
||||||
|
alert('Warning: Frequency weighting not set to A');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check battery
|
||||||
|
const batteryPercent = parseInt(settings.battery_level);
|
||||||
|
if (batteryPercent < 20) {
|
||||||
|
alert('Low battery! Please charge device.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Python Automation
|
||||||
|
```python
|
||||||
|
def ensure_correct_config(unit_id: str, required_config: dict):
|
||||||
|
"""Verify device matches required configuration."""
|
||||||
|
settings = get_device_settings(unit_id)
|
||||||
|
|
||||||
|
mismatches = []
|
||||||
|
for key, expected in required_config.items():
|
||||||
|
actual = settings.get(key)
|
||||||
|
if actual != expected:
|
||||||
|
mismatches.append(f"{key}: expected {expected}, got {actual}")
|
||||||
|
|
||||||
|
if mismatches:
|
||||||
|
raise ValueError(f"Configuration mismatch: {', '.join(mismatches)}")
|
||||||
|
|
||||||
|
return True
|
||||||
|
```
|
||||||
|
|
||||||
|
## Future Enhancements
|
||||||
|
|
||||||
|
Potential improvements for future versions:
|
||||||
|
|
||||||
|
1. **Filtered queries** - Query parameter to select specific settings
|
||||||
|
2. **Diff mode** - Compare current settings to expected values
|
||||||
|
3. **Batch queries** - Get settings from multiple devices in one request
|
||||||
|
4. **Settings profiles** - Save/load common configuration profiles
|
||||||
|
5. **Change detection** - Track when settings were last modified
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
For questions or issues with this feature:
|
||||||
|
- See [SETTINGS_ENDPOINT.md](SETTINGS_ENDPOINT.md) for detailed documentation
|
||||||
|
- Check [README.md](README.md) for general API usage
|
||||||
|
- Review [COMMUNICATION_GUIDE.md](COMMUNICATION_GUIDE.md) for protocol details
|
||||||
|
|
||||||
|
## Version Info
|
||||||
|
|
||||||
|
- **Added:** December 24, 2025
|
||||||
|
- **API Version:** Compatible with existing v1 API
|
||||||
|
- **Breaking Changes:** None - purely additive feature
|
||||||
27
README.md
27
README.md
@@ -131,6 +131,7 @@ Logs are written to:
|
|||||||
|
|
||||||
| Method | Endpoint | Description |
|
| Method | Endpoint | Description |
|
||||||
|--------|----------|-------------|
|
|--------|----------|-------------|
|
||||||
|
| GET | `/api/nl43/{unit_id}/settings` | Get all current device settings for verification |
|
||||||
| GET | `/api/nl43/{unit_id}/frequency-weighting` | Get frequency weighting (A/C/Z) |
|
| GET | `/api/nl43/{unit_id}/frequency-weighting` | Get frequency weighting (A/C/Z) |
|
||||||
| PUT | `/api/nl43/{unit_id}/frequency-weighting` | Set frequency weighting |
|
| PUT | `/api/nl43/{unit_id}/frequency-weighting` | Set frequency weighting |
|
||||||
| GET | `/api/nl43/{unit_id}/time-weighting` | Get time weighting (F/S/I) |
|
| GET | `/api/nl43/{unit_id}/time-weighting` | Get time weighting (F/S/I) |
|
||||||
@@ -255,6 +256,32 @@ curl -X POST http://localhost:8100/api/nl43/meter-001/start
|
|||||||
curl http://localhost:8100/api/nl43/meter-001/live
|
curl http://localhost:8100/api/nl43/meter-001/live
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Verify Device Settings
|
||||||
|
```bash
|
||||||
|
curl http://localhost:8100/api/nl43/meter-001/settings
|
||||||
|
```
|
||||||
|
|
||||||
|
This returns all current device configuration:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "ok",
|
||||||
|
"unit_id": "meter-001",
|
||||||
|
"settings": {
|
||||||
|
"measurement_state": "Stop",
|
||||||
|
"frequency_weighting": "A",
|
||||||
|
"time_weighting": "F",
|
||||||
|
"measurement_time": "00:01:00",
|
||||||
|
"leq_interval": "1s",
|
||||||
|
"lp_interval": "125ms",
|
||||||
|
"index_number": "0",
|
||||||
|
"battery_level": "100%",
|
||||||
|
"clock": "2025/12/24,20:45:30",
|
||||||
|
"sleep_mode": "Off",
|
||||||
|
"ftp_status": "On"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Stream Real-time Data (JavaScript)
|
### Stream Real-time Data (JavaScript)
|
||||||
```javascript
|
```javascript
|
||||||
const ws = new WebSocket('ws://localhost:8100/api/nl43/meter-001/stream');
|
const ws = new WebSocket('ws://localhost:8100/api/nl43/meter-001/stream');
|
||||||
|
|||||||
258
SETTINGS_ENDPOINT.md
Normal file
258
SETTINGS_ENDPOINT.md
Normal file
@@ -0,0 +1,258 @@
|
|||||||
|
# Device Settings Verification Endpoint
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The new `GET /api/nl43/{unit_id}/settings` endpoint provides a comprehensive view of all current device settings. This allows you to quickly verify the configuration of your NL43/NL53 sound level meter before starting measurements, ensuring the device is configured correctly for your testing requirements.
|
||||||
|
|
||||||
|
## Endpoint Details
|
||||||
|
|
||||||
|
**URL:** `GET /api/nl43/{unit_id}/settings`
|
||||||
|
|
||||||
|
**Description:** Retrieves all queryable settings from the device in a single request.
|
||||||
|
|
||||||
|
**Response Time:** Approximately 10-15 seconds (due to required 1-second delay between device commands)
|
||||||
|
|
||||||
|
## Settings Retrieved
|
||||||
|
|
||||||
|
The endpoint queries the following categories of settings:
|
||||||
|
|
||||||
|
### Measurement Configuration
|
||||||
|
- **measurement_state**: Current state (Measure, Stop, Pause)
|
||||||
|
- **frequency_weighting**: Frequency weighting (A, C, or Z)
|
||||||
|
- **time_weighting**: Time weighting (F=Fast, S=Slow, I=Impulse)
|
||||||
|
|
||||||
|
### Timing and Intervals
|
||||||
|
- **measurement_time**: Total measurement duration setting
|
||||||
|
- **leq_interval**: Leq calculation interval
|
||||||
|
- **lp_interval**: Lp sampling interval
|
||||||
|
- **index_number**: Current index/file number for storage
|
||||||
|
|
||||||
|
### Device Information
|
||||||
|
- **battery_level**: Current battery percentage
|
||||||
|
- **clock**: Device clock time (format: YYYY/MM/DD,HH:MM:SS)
|
||||||
|
|
||||||
|
### Operational Status
|
||||||
|
- **sleep_mode**: Sleep mode status (On/Off)
|
||||||
|
- **ftp_status**: FTP server status (On/Off)
|
||||||
|
|
||||||
|
## Usage Examples
|
||||||
|
|
||||||
|
### Basic Request
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl http://localhost:8100/api/nl43/NL43-001/settings
|
||||||
|
```
|
||||||
|
|
||||||
|
### Response Format
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "ok",
|
||||||
|
"unit_id": "NL43-001",
|
||||||
|
"settings": {
|
||||||
|
"measurement_state": "Stop",
|
||||||
|
"frequency_weighting": "A",
|
||||||
|
"time_weighting": "F",
|
||||||
|
"measurement_time": "00:01:00",
|
||||||
|
"leq_interval": "1s",
|
||||||
|
"lp_interval": "125ms",
|
||||||
|
"index_number": "0",
|
||||||
|
"battery_level": "100%",
|
||||||
|
"clock": "2025/12/24,20:45:30",
|
||||||
|
"sleep_mode": "Off",
|
||||||
|
"ftp_status": "On"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Error Handling
|
||||||
|
|
||||||
|
Individual settings that fail to query will show an error message instead of a value:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "ok",
|
||||||
|
"unit_id": "NL43-001",
|
||||||
|
"settings": {
|
||||||
|
"measurement_state": "Stop",
|
||||||
|
"frequency_weighting": "A",
|
||||||
|
"time_weighting": "Error: Status error - device is in wrong state for this command",
|
||||||
|
...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This partial error handling ensures you get as much information as possible even if some settings fail to query.
|
||||||
|
|
||||||
|
## Common Use Cases
|
||||||
|
|
||||||
|
### Pre-Measurement Verification
|
||||||
|
|
||||||
|
Before starting a measurement session, verify all critical settings:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Get all settings
|
||||||
|
SETTINGS=$(curl -s http://localhost:8100/api/nl43/meter-001/settings)
|
||||||
|
|
||||||
|
# Extract specific values (using jq)
|
||||||
|
FREQ_WEIGHT=$(echo $SETTINGS | jq -r '.settings.frequency_weighting')
|
||||||
|
TIME_WEIGHT=$(echo $SETTINGS | jq -r '.settings.time_weighting')
|
||||||
|
|
||||||
|
echo "Frequency: $FREQ_WEIGHT, Time: $TIME_WEIGHT"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configuration Audit
|
||||||
|
|
||||||
|
Document device configuration for quality assurance:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Save settings snapshot
|
||||||
|
curl http://localhost:8100/api/nl43/meter-001/settings > config_snapshot_$(date +%Y%m%d_%H%M%S).json
|
||||||
|
```
|
||||||
|
|
||||||
|
### Multi-Device Comparison
|
||||||
|
|
||||||
|
Compare settings across multiple devices:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Compare two devices
|
||||||
|
curl http://localhost:8100/api/nl43/meter-001/settings > device1.json
|
||||||
|
curl http://localhost:8100/api/nl43/meter-002/settings > device2.json
|
||||||
|
diff device1.json device2.json
|
||||||
|
```
|
||||||
|
|
||||||
|
## Integration Examples
|
||||||
|
|
||||||
|
### Python
|
||||||
|
|
||||||
|
```python
|
||||||
|
import requests
|
||||||
|
|
||||||
|
def verify_device_settings(unit_id: str) -> dict:
|
||||||
|
"""Retrieve and verify device settings."""
|
||||||
|
response = requests.get(f"http://localhost:8100/api/nl43/{unit_id}/settings")
|
||||||
|
response.raise_for_status()
|
||||||
|
|
||||||
|
data = response.json()
|
||||||
|
settings = data["settings"]
|
||||||
|
|
||||||
|
# Verify critical settings
|
||||||
|
assert settings["frequency_weighting"] == "A", "Wrong frequency weighting!"
|
||||||
|
assert settings["time_weighting"] == "F", "Wrong time weighting!"
|
||||||
|
|
||||||
|
return settings
|
||||||
|
|
||||||
|
# Usage
|
||||||
|
settings = verify_device_settings("NL43-001")
|
||||||
|
print(f"Battery: {settings['battery_level']}")
|
||||||
|
print(f"Clock: {settings['clock']}")
|
||||||
|
```
|
||||||
|
|
||||||
|
### JavaScript/TypeScript
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface DeviceSettings {
|
||||||
|
measurement_state: string;
|
||||||
|
frequency_weighting: string;
|
||||||
|
time_weighting: string;
|
||||||
|
measurement_time: string;
|
||||||
|
leq_interval: string;
|
||||||
|
lp_interval: string;
|
||||||
|
index_number: string;
|
||||||
|
battery_level: string;
|
||||||
|
clock: string;
|
||||||
|
sleep_mode: string;
|
||||||
|
ftp_status: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getDeviceSettings(unitId: string): Promise<DeviceSettings> {
|
||||||
|
const response = await fetch(`http://localhost:8100/api/nl43/${unitId}/settings`);
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
if (data.status !== "ok") {
|
||||||
|
throw new Error("Failed to retrieve settings");
|
||||||
|
}
|
||||||
|
|
||||||
|
return data.settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Usage
|
||||||
|
const settings = await getDeviceSettings("NL43-001");
|
||||||
|
console.log(`Frequency weighting: ${settings.frequency_weighting}`);
|
||||||
|
console.log(`Battery level: ${settings.battery_level}`);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Performance Considerations
|
||||||
|
|
||||||
|
### Query Duration
|
||||||
|
|
||||||
|
The endpoint queries multiple settings sequentially with required 1-second delays between commands. Total query time depends on:
|
||||||
|
- Number of settings queried (~10-12 settings)
|
||||||
|
- Network latency
|
||||||
|
- Device response time
|
||||||
|
|
||||||
|
**Expected duration:** 10-15 seconds
|
||||||
|
|
||||||
|
### Caching Strategy
|
||||||
|
|
||||||
|
For applications that need frequent access to settings:
|
||||||
|
|
||||||
|
1. **Cache results** - Settings don't change frequently unless you modify them
|
||||||
|
2. **Refresh periodically** - Query every 5-10 minutes or on-demand
|
||||||
|
3. **Track changes** - Re-query after sending configuration commands
|
||||||
|
|
||||||
|
### Rate Limiting
|
||||||
|
|
||||||
|
The endpoint respects device rate limiting (1-second delay between commands). Concurrent requests to the same device will be serialized automatically.
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
1. **Pre-flight check**: Always verify settings before starting critical measurements
|
||||||
|
2. **Document configuration**: Save settings snapshots for audit trails
|
||||||
|
3. **Monitor battery**: Check battery level to avoid measurement interruption
|
||||||
|
4. **Sync clocks**: Verify device clock is accurate for timestamped data
|
||||||
|
5. **Error handling**: Check for "Error:" prefixes in individual setting values
|
||||||
|
|
||||||
|
## Related Endpoints
|
||||||
|
|
||||||
|
- `GET /api/nl43/{unit_id}/frequency-weighting` - Get single frequency weighting setting
|
||||||
|
- `PUT /api/nl43/{unit_id}/frequency-weighting` - Set frequency weighting
|
||||||
|
- `GET /api/nl43/{unit_id}/time-weighting` - Get single time weighting setting
|
||||||
|
- `PUT /api/nl43/{unit_id}/time-weighting` - Set time weighting
|
||||||
|
- `GET /api/nl43/{unit_id}/battery` - Get battery level only
|
||||||
|
- `GET /api/nl43/{unit_id}/clock` - Get device clock only
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Slow Response
|
||||||
|
|
||||||
|
**Problem:** Endpoint takes longer than expected
|
||||||
|
|
||||||
|
**Solutions:**
|
||||||
|
- Normal behavior due to rate limiting (1 second between commands)
|
||||||
|
- Check network connectivity
|
||||||
|
- Verify device is not in sleep mode
|
||||||
|
|
||||||
|
### Partial Errors
|
||||||
|
|
||||||
|
**Problem:** Some settings show "Error:" messages
|
||||||
|
|
||||||
|
**Solutions:**
|
||||||
|
- Device may be in wrong state for certain queries
|
||||||
|
- Check if measurement is running (some settings require stopped state)
|
||||||
|
- Verify firmware version supports all queried commands
|
||||||
|
|
||||||
|
### Connection Timeout
|
||||||
|
|
||||||
|
**Problem:** 504 Gateway Timeout error
|
||||||
|
|
||||||
|
**Solutions:**
|
||||||
|
- Verify device IP address and port in configuration
|
||||||
|
- Check if device is powered on and connected
|
||||||
|
- Ensure TCP communication is enabled in device config
|
||||||
|
|
||||||
|
## See Also
|
||||||
|
|
||||||
|
- [README.md](README.md) - Main documentation
|
||||||
|
- [API.md](API.md) - Complete API reference
|
||||||
|
- [COMMUNICATION_GUIDE.md](COMMUNICATION_GUIDE.md) - NL43 protocol details
|
||||||
171
UI_UPDATE.md
Normal file
171
UI_UPDATE.md
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
# Standalone UI Update: Get ALL Settings Button
|
||||||
|
|
||||||
|
## What Was Added
|
||||||
|
|
||||||
|
A new **"Get ALL Settings"** button has been added to the standalone web UI at [templates/index.html](templates/index.html).
|
||||||
|
|
||||||
|
## Location
|
||||||
|
|
||||||
|
The button is located in the **Measurement Settings** fieldset, at the top before the individual frequency and time weighting controls.
|
||||||
|
|
||||||
|
## Visual Layout
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────┐
|
||||||
|
│ Measurement Settings │
|
||||||
|
├─────────────────────────────────────────────────────┤
|
||||||
|
│ │
|
||||||
|
│ [Get ALL Settings] ← NEW BUTTON (bold styling) │
|
||||||
|
│ │
|
||||||
|
│ Frequency Weighting: │
|
||||||
|
│ [Get] [Set A] [Set C] [Set Z] │
|
||||||
|
│ │
|
||||||
|
│ Time Weighting: │
|
||||||
|
│ [Get] [Set Fast] [Set Slow] [Set Impulse] │
|
||||||
|
│ │
|
||||||
|
└─────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## Functionality
|
||||||
|
|
||||||
|
When clicked, the button:
|
||||||
|
|
||||||
|
1. **Shows loading message**: "Retrieving all device settings (this may take 10-15 seconds)..."
|
||||||
|
|
||||||
|
2. **Calls API**: `GET /api/nl43/{unit_id}/settings`
|
||||||
|
|
||||||
|
3. **Displays results in two places**:
|
||||||
|
- **Status area** (top): Shows formatted JSON with all settings
|
||||||
|
- **Log area** (bottom): Shows each setting on a separate line
|
||||||
|
|
||||||
|
## Example Output
|
||||||
|
|
||||||
|
### Status Area Display
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"measurement_state": "Stop",
|
||||||
|
"frequency_weighting": "A",
|
||||||
|
"time_weighting": "F",
|
||||||
|
"measurement_time": "00:01:00",
|
||||||
|
"leq_interval": "1s",
|
||||||
|
"lp_interval": "125ms",
|
||||||
|
"index_number": "0",
|
||||||
|
"battery_level": "100%",
|
||||||
|
"clock": "2025/12/24,20:45:30",
|
||||||
|
"sleep_mode": "Off",
|
||||||
|
"ftp_status": "On"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Log Area Display
|
||||||
|
```
|
||||||
|
Retrieving all device settings (this may take 10-15 seconds)...
|
||||||
|
=== ALL DEVICE SETTINGS ===
|
||||||
|
measurement_state: Stop
|
||||||
|
frequency_weighting: A
|
||||||
|
time_weighting: F
|
||||||
|
measurement_time: 00:01:00
|
||||||
|
leq_interval: 1s
|
||||||
|
lp_interval: 125ms
|
||||||
|
index_number: 0
|
||||||
|
battery_level: 100%
|
||||||
|
clock: 2025/12/24,20:45:30
|
||||||
|
sleep_mode: Off
|
||||||
|
ftp_status: On
|
||||||
|
===========================
|
||||||
|
```
|
||||||
|
|
||||||
|
## Code Changes
|
||||||
|
|
||||||
|
### HTML Changes (Line 60)
|
||||||
|
```html
|
||||||
|
<button onclick="getAllSettings()" style="margin-bottom: 12px; font-weight: bold;">
|
||||||
|
Get ALL Settings
|
||||||
|
</button>
|
||||||
|
```
|
||||||
|
|
||||||
|
### JavaScript Changes (Lines 284-305)
|
||||||
|
```javascript
|
||||||
|
async function getAllSettings() {
|
||||||
|
const unitId = document.getElementById('unitId').value;
|
||||||
|
log('Retrieving all device settings (this may take 10-15 seconds)...');
|
||||||
|
|
||||||
|
const res = await fetch(`/api/nl43/${unitId}/settings`);
|
||||||
|
const data = await res.json();
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
log(`Get All Settings failed: ${res.status} - ${data.detail || JSON.stringify(data)}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display in status area
|
||||||
|
statusEl.textContent = JSON.stringify(data.settings, null, 2);
|
||||||
|
|
||||||
|
// Log summary
|
||||||
|
log('=== ALL DEVICE SETTINGS ===');
|
||||||
|
Object.entries(data.settings).forEach(([key, value]) => {
|
||||||
|
log(`${key}: ${value}`);
|
||||||
|
});
|
||||||
|
log('===========================');
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage Flow
|
||||||
|
|
||||||
|
1. **Configure device** using the "Unit Config" section
|
||||||
|
2. **Click "Get ALL Settings"** to retrieve current configuration
|
||||||
|
3. **Review settings** in the Status and Log areas
|
||||||
|
4. **Verify** critical settings match requirements before starting measurements
|
||||||
|
|
||||||
|
## Benefits
|
||||||
|
|
||||||
|
✓ **Quick verification** - One click to see all device settings
|
||||||
|
✓ **Pre-measurement check** - Ensure device is configured correctly
|
||||||
|
✓ **Debugging** - Identify misconfigured settings easily
|
||||||
|
✓ **Documentation** - Copy settings from status area for records
|
||||||
|
✓ **Comparison** - Compare settings across multiple devices
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
If the request fails:
|
||||||
|
- Error message is displayed in the log
|
||||||
|
- Status code and details are shown
|
||||||
|
- Previous status display is preserved
|
||||||
|
|
||||||
|
Example error output:
|
||||||
|
```
|
||||||
|
Retrieving all device settings (this may take 10-15 seconds)...
|
||||||
|
Get All Settings failed: 502 - Failed to communicate with device
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing the Feature
|
||||||
|
|
||||||
|
1. **Start the SLMM server**:
|
||||||
|
```bash
|
||||||
|
cd /home/serversdown/slmm
|
||||||
|
uvicorn app.main:app --reload --port 8100
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Open the standalone UI**:
|
||||||
|
```
|
||||||
|
http://localhost:8100
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Configure a device**:
|
||||||
|
- Enter Unit ID (e.g., "nl43-1")
|
||||||
|
- Enter Host IP (e.g., "192.168.1.100")
|
||||||
|
- Enter Port (e.g., "80")
|
||||||
|
- Click "Save Config"
|
||||||
|
|
||||||
|
4. **Test the new button**:
|
||||||
|
- Click "Get ALL Settings"
|
||||||
|
- Wait 10-15 seconds for results
|
||||||
|
- Review settings in Status and Log areas
|
||||||
|
|
||||||
|
## Related Files
|
||||||
|
|
||||||
|
- [templates/index.html](templates/index.html) - Standalone UI (updated)
|
||||||
|
- [app/routers.py](app/routers.py#L728-L761) - Settings endpoint
|
||||||
|
- [app/services.py](app/services.py#L538-L606) - Client implementation
|
||||||
|
- [README.md](README.md) - Main documentation
|
||||||
|
- [SETTINGS_ENDPOINT.md](SETTINGS_ENDPOINT.md) - API documentation
|
||||||
Binary file not shown.
Binary file not shown.
219
app/routers.py
219
app/routers.py
@@ -725,6 +725,42 @@ async def get_ftp_status(unit_id: str, db: Session = Depends(get_db)):
|
|||||||
raise HTTPException(status_code=500, detail=f"Failed to get FTP status: {str(e)}")
|
raise HTTPException(status_code=500, detail=f"Failed to get FTP status: {str(e)}")
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/{unit_id}/settings")
|
||||||
|
async def get_all_settings(unit_id: str, db: Session = Depends(get_db)):
|
||||||
|
"""Get all current device settings for verification.
|
||||||
|
|
||||||
|
Returns a comprehensive view of all device configuration including:
|
||||||
|
- Measurement state and weightings
|
||||||
|
- Timing and interval settings
|
||||||
|
- Battery level and clock
|
||||||
|
- Sleep and FTP status
|
||||||
|
|
||||||
|
This is useful for verifying device configuration before starting measurements.
|
||||||
|
"""
|
||||||
|
cfg = db.query(NL43Config).filter_by(unit_id=unit_id).first()
|
||||||
|
if not cfg:
|
||||||
|
raise HTTPException(status_code=404, detail="NL43 config not found")
|
||||||
|
|
||||||
|
if not cfg.tcp_enabled:
|
||||||
|
raise HTTPException(status_code=403, detail="TCP communication is disabled for this device")
|
||||||
|
|
||||||
|
client = NL43Client(cfg.host, cfg.tcp_port, ftp_username=cfg.ftp_username, ftp_password=cfg.ftp_password)
|
||||||
|
try:
|
||||||
|
settings = await client.get_all_settings()
|
||||||
|
logger.info(f"Retrieved all settings for unit {unit_id}")
|
||||||
|
return {"status": "ok", "unit_id": unit_id, "settings": settings}
|
||||||
|
|
||||||
|
except ConnectionError as e:
|
||||||
|
logger.error(f"Failed to get settings for {unit_id}: {e}")
|
||||||
|
raise HTTPException(status_code=502, detail="Failed to communicate with device")
|
||||||
|
except TimeoutError:
|
||||||
|
logger.error(f"Timeout getting settings for {unit_id}")
|
||||||
|
raise HTTPException(status_code=504, detail="Device communication timeout")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Unexpected error getting settings for {unit_id}: {e}")
|
||||||
|
raise HTTPException(status_code=500, detail="Internal server error")
|
||||||
|
|
||||||
|
|
||||||
@router.get("/{unit_id}/ftp/files")
|
@router.get("/{unit_id}/ftp/files")
|
||||||
async def list_ftp_files(unit_id: str, path: str = "/", db: Session = Depends(get_db)):
|
async def list_ftp_files(unit_id: str, path: str = "/", db: Session = Depends(get_db)):
|
||||||
"""List files on the device via FTP.
|
"""List files on the device via FTP.
|
||||||
@@ -748,6 +784,14 @@ async def list_ftp_files(unit_id: str, path: str = "/", db: Session = Depends(ge
|
|||||||
raise HTTPException(status_code=500, detail="Internal server error")
|
raise HTTPException(status_code=500, detail="Internal server error")
|
||||||
|
|
||||||
|
|
||||||
|
class TimingPayload(BaseModel):
|
||||||
|
preset: str
|
||||||
|
|
||||||
|
|
||||||
|
class IndexPayload(BaseModel):
|
||||||
|
index: int
|
||||||
|
|
||||||
|
|
||||||
class DownloadRequest(BaseModel):
|
class DownloadRequest(BaseModel):
|
||||||
remote_path: str
|
remote_path: str
|
||||||
|
|
||||||
@@ -790,3 +834,178 @@ async def download_ftp_file(unit_id: str, payload: DownloadRequest, db: Session
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Unexpected error downloading file from {unit_id}: {e}")
|
logger.error(f"Unexpected error downloading file from {unit_id}: {e}")
|
||||||
raise HTTPException(status_code=500, detail="Internal server error")
|
raise HTTPException(status_code=500, detail="Internal server error")
|
||||||
|
|
||||||
|
|
||||||
|
# Timing/Interval Configuration Endpoints
|
||||||
|
|
||||||
|
@router.get("/{unit_id}/measurement-time")
|
||||||
|
async def get_measurement_time(unit_id: str, db: Session = Depends(get_db)):
|
||||||
|
"""Get current measurement time preset."""
|
||||||
|
cfg = db.query(NL43Config).filter_by(unit_id=unit_id).first()
|
||||||
|
if not cfg:
|
||||||
|
raise HTTPException(status_code=404, detail="NL43 config not found")
|
||||||
|
|
||||||
|
if not cfg.tcp_enabled:
|
||||||
|
raise HTTPException(status_code=403, detail="TCP communication is disabled for this device")
|
||||||
|
|
||||||
|
client = NL43Client(cfg.host, cfg.tcp_port, ftp_username=cfg.ftp_username, ftp_password=cfg.ftp_password)
|
||||||
|
try:
|
||||||
|
preset = await client.get_measurement_time()
|
||||||
|
return {"status": "ok", "measurement_time": preset}
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to get measurement time for {unit_id}: {e}")
|
||||||
|
raise HTTPException(status_code=502, detail=str(e))
|
||||||
|
|
||||||
|
|
||||||
|
@router.put("/{unit_id}/measurement-time")
|
||||||
|
async def set_measurement_time(unit_id: str, payload: TimingPayload, db: Session = Depends(get_db)):
|
||||||
|
"""Set measurement time preset (10s, 1m, 5m, 10m, 15m, 30m, 1h, 8h, 24h, or custom like 00:05:30)."""
|
||||||
|
cfg = db.query(NL43Config).filter_by(unit_id=unit_id).first()
|
||||||
|
if not cfg:
|
||||||
|
raise HTTPException(status_code=404, detail="NL43 config not found")
|
||||||
|
|
||||||
|
if not cfg.tcp_enabled:
|
||||||
|
raise HTTPException(status_code=403, detail="TCP communication is disabled for this device")
|
||||||
|
|
||||||
|
client = NL43Client(cfg.host, cfg.tcp_port, ftp_username=cfg.ftp_username, ftp_password=cfg.ftp_password)
|
||||||
|
try:
|
||||||
|
await client.set_measurement_time(payload.preset)
|
||||||
|
return {"status": "ok", "message": f"Measurement time set to {payload.preset}"}
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to set measurement time for {unit_id}: {e}")
|
||||||
|
raise HTTPException(status_code=502, detail=str(e))
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/{unit_id}/leq-interval")
|
||||||
|
async def get_leq_interval(unit_id: str, db: Session = Depends(get_db)):
|
||||||
|
"""Get current Leq calculation interval preset."""
|
||||||
|
cfg = db.query(NL43Config).filter_by(unit_id=unit_id).first()
|
||||||
|
if not cfg:
|
||||||
|
raise HTTPException(status_code=404, detail="NL43 config not found")
|
||||||
|
|
||||||
|
if not cfg.tcp_enabled:
|
||||||
|
raise HTTPException(status_code=403, detail="TCP communication is disabled for this device")
|
||||||
|
|
||||||
|
client = NL43Client(cfg.host, cfg.tcp_port, ftp_username=cfg.ftp_username, ftp_password=cfg.ftp_password)
|
||||||
|
try:
|
||||||
|
preset = await client.get_leq_interval()
|
||||||
|
return {"status": "ok", "leq_interval": preset}
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to get Leq interval for {unit_id}: {e}")
|
||||||
|
raise HTTPException(status_code=502, detail=str(e))
|
||||||
|
|
||||||
|
|
||||||
|
@router.put("/{unit_id}/leq-interval")
|
||||||
|
async def set_leq_interval(unit_id: str, payload: TimingPayload, db: Session = Depends(get_db)):
|
||||||
|
"""Set Leq calculation interval preset (Off, 10s, 1m, 5m, 10m, 15m, 30m, 1h, 8h, 24h, or custom like 00:05:30)."""
|
||||||
|
cfg = db.query(NL43Config).filter_by(unit_id=unit_id).first()
|
||||||
|
if not cfg:
|
||||||
|
raise HTTPException(status_code=404, detail="NL43 config not found")
|
||||||
|
|
||||||
|
if not cfg.tcp_enabled:
|
||||||
|
raise HTTPException(status_code=403, detail="TCP communication is disabled for this device")
|
||||||
|
|
||||||
|
client = NL43Client(cfg.host, cfg.tcp_port, ftp_username=cfg.ftp_username, ftp_password=cfg.ftp_password)
|
||||||
|
try:
|
||||||
|
await client.set_leq_interval(payload.preset)
|
||||||
|
return {"status": "ok", "message": f"Leq interval set to {payload.preset}"}
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to set Leq interval for {unit_id}: {e}")
|
||||||
|
raise HTTPException(status_code=502, detail=str(e))
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/{unit_id}/lp-interval")
|
||||||
|
async def get_lp_interval(unit_id: str, db: Session = Depends(get_db)):
|
||||||
|
"""Get current Lp store interval."""
|
||||||
|
cfg = db.query(NL43Config).filter_by(unit_id=unit_id).first()
|
||||||
|
if not cfg:
|
||||||
|
raise HTTPException(status_code=404, detail="NL43 config not found")
|
||||||
|
|
||||||
|
if not cfg.tcp_enabled:
|
||||||
|
raise HTTPException(status_code=403, detail="TCP communication is disabled for this device")
|
||||||
|
|
||||||
|
client = NL43Client(cfg.host, cfg.tcp_port, ftp_username=cfg.ftp_username, ftp_password=cfg.ftp_password)
|
||||||
|
try:
|
||||||
|
preset = await client.get_lp_interval()
|
||||||
|
return {"status": "ok", "lp_interval": preset}
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to get Lp interval for {unit_id}: {e}")
|
||||||
|
raise HTTPException(status_code=502, detail=str(e))
|
||||||
|
|
||||||
|
|
||||||
|
@router.put("/{unit_id}/lp-interval")
|
||||||
|
async def set_lp_interval(unit_id: str, payload: TimingPayload, db: Session = Depends(get_db)):
|
||||||
|
"""Set Lp store interval (Off, 10ms, 25ms, 100ms, 200ms, 1s)."""
|
||||||
|
cfg = db.query(NL43Config).filter_by(unit_id=unit_id).first()
|
||||||
|
if not cfg:
|
||||||
|
raise HTTPException(status_code=404, detail="NL43 config not found")
|
||||||
|
|
||||||
|
if not cfg.tcp_enabled:
|
||||||
|
raise HTTPException(status_code=403, detail="TCP communication is disabled for this device")
|
||||||
|
|
||||||
|
client = NL43Client(cfg.host, cfg.tcp_port, ftp_username=cfg.ftp_username, ftp_password=cfg.ftp_password)
|
||||||
|
try:
|
||||||
|
await client.set_lp_interval(payload.preset)
|
||||||
|
return {"status": "ok", "message": f"Lp interval set to {payload.preset}"}
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to set Lp interval for {unit_id}: {e}")
|
||||||
|
raise HTTPException(status_code=502, detail=str(e))
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/{unit_id}/index-number")
|
||||||
|
async def get_index_number(unit_id: str, db: Session = Depends(get_db)):
|
||||||
|
"""Get current index number for file numbering."""
|
||||||
|
cfg = db.query(NL43Config).filter_by(unit_id=unit_id).first()
|
||||||
|
if not cfg:
|
||||||
|
raise HTTPException(status_code=404, detail="NL43 config not found")
|
||||||
|
|
||||||
|
if not cfg.tcp_enabled:
|
||||||
|
raise HTTPException(status_code=403, detail="TCP communication is disabled for this device")
|
||||||
|
|
||||||
|
client = NL43Client(cfg.host, cfg.tcp_port, ftp_username=cfg.ftp_username, ftp_password=cfg.ftp_password)
|
||||||
|
try:
|
||||||
|
index = await client.get_index_number()
|
||||||
|
return {"status": "ok", "index_number": index}
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to get index number for {unit_id}: {e}")
|
||||||
|
raise HTTPException(status_code=502, detail=str(e))
|
||||||
|
|
||||||
|
|
||||||
|
@router.put("/{unit_id}/index-number")
|
||||||
|
async def set_index_number(unit_id: str, payload: IndexPayload, db: Session = Depends(get_db)):
|
||||||
|
"""Set index number for file numbering (0000-9999)."""
|
||||||
|
cfg = db.query(NL43Config).filter_by(unit_id=unit_id).first()
|
||||||
|
if not cfg:
|
||||||
|
raise HTTPException(status_code=404, detail="NL43 config not found")
|
||||||
|
|
||||||
|
if not cfg.tcp_enabled:
|
||||||
|
raise HTTPException(status_code=403, detail="TCP communication is disabled for this device")
|
||||||
|
|
||||||
|
client = NL43Client(cfg.host, cfg.tcp_port, ftp_username=cfg.ftp_username, ftp_password=cfg.ftp_password)
|
||||||
|
try:
|
||||||
|
await client.set_index_number(payload.index)
|
||||||
|
return {"status": "ok", "message": f"Index number set to {payload.index:04d}"}
|
||||||
|
except ValueError as e:
|
||||||
|
raise HTTPException(status_code=400, detail=str(e))
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to set index number for {unit_id}: {e}")
|
||||||
|
raise HTTPException(status_code=502, detail=str(e))
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/{unit_id}/settings/all")
|
||||||
|
async def get_all_settings(unit_id: str, db: Session = Depends(get_db)):
|
||||||
|
"""Get all device settings for verification."""
|
||||||
|
cfg = db.query(NL43Config).filter_by(unit_id=unit_id).first()
|
||||||
|
if not cfg:
|
||||||
|
raise HTTPException(status_code=404, detail="NL43 config not found")
|
||||||
|
|
||||||
|
if not cfg.tcp_enabled:
|
||||||
|
raise HTTPException(status_code=403, detail="TCP communication is disabled for this device")
|
||||||
|
|
||||||
|
client = NL43Client(cfg.host, cfg.tcp_port, ftp_username=cfg.ftp_username, ftp_password=cfg.ftp_password)
|
||||||
|
try:
|
||||||
|
settings = await client.get_all_settings()
|
||||||
|
return {"status": "ok", "settings": settings}
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to get all settings for {unit_id}: {e}")
|
||||||
|
raise HTTPException(status_code=502, detail=str(e))
|
||||||
|
|||||||
140
app/services.py
140
app/services.py
@@ -465,6 +465,146 @@ class NL43Client:
|
|||||||
|
|
||||||
logger.info(f"DRD stream ended for {self.device_key}")
|
logger.info(f"DRD stream ended for {self.device_key}")
|
||||||
|
|
||||||
|
async def set_measurement_time(self, preset: str):
|
||||||
|
"""Set measurement time preset.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
preset: Time preset (10s, 1m, 5m, 10m, 15m, 30m, 1h, 8h, 24h, or custom like "00:05:30")
|
||||||
|
"""
|
||||||
|
await self._send_command(f"Measurement Time Preset Manual,{preset}\r\n")
|
||||||
|
logger.info(f"Set measurement time to {preset} on {self.device_key}")
|
||||||
|
|
||||||
|
async def get_measurement_time(self) -> str:
|
||||||
|
"""Get current measurement time preset.
|
||||||
|
|
||||||
|
Returns: Current time preset setting
|
||||||
|
"""
|
||||||
|
resp = await self._send_command("Measurement Time Preset Manual?\r\n")
|
||||||
|
return resp.strip()
|
||||||
|
|
||||||
|
async def set_leq_interval(self, preset: str):
|
||||||
|
"""Set Leq calculation interval preset.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
preset: Interval preset (Off, 10s, 1m, 5m, 10m, 15m, 30m, 1h, 8h, 24h, or custom like "00:05:30")
|
||||||
|
"""
|
||||||
|
await self._send_command(f"Leq Calculation Interval Preset,{preset}\r\n")
|
||||||
|
logger.info(f"Set Leq interval to {preset} on {self.device_key}")
|
||||||
|
|
||||||
|
async def get_leq_interval(self) -> str:
|
||||||
|
"""Get current Leq calculation interval preset.
|
||||||
|
|
||||||
|
Returns: Current interval preset setting
|
||||||
|
"""
|
||||||
|
resp = await self._send_command("Leq Calculation Interval Preset?\r\n")
|
||||||
|
return resp.strip()
|
||||||
|
|
||||||
|
async def set_lp_interval(self, preset: str):
|
||||||
|
"""Set Lp store interval.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
preset: Store interval (Off, 10ms, 25ms, 100ms, 200ms, 1s)
|
||||||
|
"""
|
||||||
|
await self._send_command(f"Lp Store Interval,{preset}\r\n")
|
||||||
|
logger.info(f"Set Lp interval to {preset} on {self.device_key}")
|
||||||
|
|
||||||
|
async def get_lp_interval(self) -> str:
|
||||||
|
"""Get current Lp store interval.
|
||||||
|
|
||||||
|
Returns: Current store interval setting
|
||||||
|
"""
|
||||||
|
resp = await self._send_command("Lp Store Interval?\r\n")
|
||||||
|
return resp.strip()
|
||||||
|
|
||||||
|
async def set_index_number(self, index: int):
|
||||||
|
"""Set index number for file numbering.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
index: Index number (0000-9999)
|
||||||
|
"""
|
||||||
|
if not 0 <= index <= 9999:
|
||||||
|
raise ValueError("Index must be between 0000 and 9999")
|
||||||
|
await self._send_command(f"Index Number,{index:04d}\r\n")
|
||||||
|
logger.info(f"Set index number to {index:04d} on {self.device_key}")
|
||||||
|
|
||||||
|
async def get_index_number(self) -> str:
|
||||||
|
"""Get current index number.
|
||||||
|
|
||||||
|
Returns: Current index number
|
||||||
|
"""
|
||||||
|
resp = await self._send_command("Index Number?\r\n")
|
||||||
|
return resp.strip()
|
||||||
|
|
||||||
|
async def get_all_settings(self) -> dict:
|
||||||
|
"""Query all device settings for verification.
|
||||||
|
|
||||||
|
Returns: Dictionary with all current device settings
|
||||||
|
"""
|
||||||
|
settings = {}
|
||||||
|
|
||||||
|
# Measurement settings
|
||||||
|
try:
|
||||||
|
settings["measurement_state"] = await self.get_measurement_state()
|
||||||
|
except Exception as e:
|
||||||
|
settings["measurement_state"] = f"Error: {e}"
|
||||||
|
|
||||||
|
try:
|
||||||
|
settings["frequency_weighting"] = await self.get_frequency_weighting()
|
||||||
|
except Exception as e:
|
||||||
|
settings["frequency_weighting"] = f"Error: {e}"
|
||||||
|
|
||||||
|
try:
|
||||||
|
settings["time_weighting"] = await self.get_time_weighting()
|
||||||
|
except Exception as e:
|
||||||
|
settings["time_weighting"] = f"Error: {e}"
|
||||||
|
|
||||||
|
# Timing/interval settings
|
||||||
|
try:
|
||||||
|
settings["measurement_time"] = await self.get_measurement_time()
|
||||||
|
except Exception as e:
|
||||||
|
settings["measurement_time"] = f"Error: {e}"
|
||||||
|
|
||||||
|
try:
|
||||||
|
settings["leq_interval"] = await self.get_leq_interval()
|
||||||
|
except Exception as e:
|
||||||
|
settings["leq_interval"] = f"Error: {e}"
|
||||||
|
|
||||||
|
try:
|
||||||
|
settings["lp_interval"] = await self.get_lp_interval()
|
||||||
|
except Exception as e:
|
||||||
|
settings["lp_interval"] = f"Error: {e}"
|
||||||
|
|
||||||
|
try:
|
||||||
|
settings["index_number"] = await self.get_index_number()
|
||||||
|
except Exception as e:
|
||||||
|
settings["index_number"] = f"Error: {e}"
|
||||||
|
|
||||||
|
# Device info
|
||||||
|
try:
|
||||||
|
settings["battery_level"] = await self.get_battery_level()
|
||||||
|
except Exception as e:
|
||||||
|
settings["battery_level"] = f"Error: {e}"
|
||||||
|
|
||||||
|
try:
|
||||||
|
settings["clock"] = await self.get_clock()
|
||||||
|
except Exception as e:
|
||||||
|
settings["clock"] = f"Error: {e}"
|
||||||
|
|
||||||
|
# Sleep mode
|
||||||
|
try:
|
||||||
|
settings["sleep_mode"] = await self.get_sleep_status()
|
||||||
|
except Exception as e:
|
||||||
|
settings["sleep_mode"] = f"Error: {e}"
|
||||||
|
|
||||||
|
# FTP status
|
||||||
|
try:
|
||||||
|
settings["ftp_status"] = await self.get_ftp_status()
|
||||||
|
except Exception as e:
|
||||||
|
settings["ftp_status"] = f"Error: {e}"
|
||||||
|
|
||||||
|
logger.info(f"Retrieved all settings for {self.device_key}")
|
||||||
|
return settings
|
||||||
|
|
||||||
async def enable_ftp(self):
|
async def enable_ftp(self):
|
||||||
"""Enable FTP server on the device.
|
"""Enable FTP server on the device.
|
||||||
|
|
||||||
|
|||||||
@@ -594,3 +594,18 @@
|
|||||||
2025-12-24 06:46:07,062 - app.services - INFO - Sending command to 63.45.161.30:2255: Sleep Mode,On
|
2025-12-24 06:46:07,062 - app.services - INFO - Sending command to 63.45.161.30:2255: Sleep Mode,On
|
||||||
2025-12-24 06:46:07,221 - app.services - INFO - Device 63.45.161.30:2255 entering sleep mode
|
2025-12-24 06:46:07,221 - app.services - INFO - Device 63.45.161.30:2255 entering sleep mode
|
||||||
2025-12-24 06:46:07,222 - app.routers - INFO - Put device nl43-1 to sleep
|
2025-12-24 06:46:07,222 - app.routers - INFO - Put device nl43-1 to sleep
|
||||||
|
2025-12-24 07:24:24,390 - app.services - INFO - Sending command to 63.45.161.30:2255: DOD?
|
||||||
|
2025-12-24 07:24:29,391 - app.services - ERROR - Connection timeout to 63.45.161.30:2255
|
||||||
|
2025-12-24 07:24:29,391 - app.routers - ERROR - Failed to get live status for nl43-1: Failed to connect to device at 63.45.161.30:2255
|
||||||
|
2025-12-24 20:37:45,341 - app.main - INFO - Database tables initialized
|
||||||
|
2025-12-24 20:37:45,342 - app.main - INFO - CORS allowed origins: ['*']
|
||||||
|
2025-12-24 20:38:04,141 - app.main - INFO - Database tables initialized
|
||||||
|
2025-12-24 20:38:04,142 - app.main - INFO - CORS allowed origins: ['*']
|
||||||
|
2025-12-24 20:38:40,693 - app.main - INFO - Database tables initialized
|
||||||
|
2025-12-24 20:38:40,693 - app.main - INFO - CORS allowed origins: ['*']
|
||||||
|
2025-12-24 20:39:08,484 - app.main - INFO - Database tables initialized
|
||||||
|
2025-12-24 20:39:08,484 - app.main - INFO - CORS allowed origins: ['*']
|
||||||
|
2025-12-24 21:22:06,678 - app.main - INFO - Database tables initialized
|
||||||
|
2025-12-24 21:22:06,679 - app.main - INFO - CORS allowed origins: ['*']
|
||||||
|
2025-12-24 21:22:38,825 - app.main - INFO - Database tables initialized
|
||||||
|
2025-12-24 21:22:38,825 - app.main - INFO - CORS allowed origins: ['*']
|
||||||
|
|||||||
@@ -240,6 +240,210 @@ Sets the time weighting.
|
|||||||
- `S` - Slow (1s)
|
- `S` - Slow (1s)
|
||||||
- `I` - Impulse (35ms)
|
- `I` - Impulse (35ms)
|
||||||
|
|
||||||
|
## Timing and Interval Configuration
|
||||||
|
|
||||||
|
### Get Measurement Time
|
||||||
|
```
|
||||||
|
GET /{unit_id}/measurement-time
|
||||||
|
```
|
||||||
|
Gets the current measurement time preset.
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "ok",
|
||||||
|
"measurement_time": "1h"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Set Measurement Time
|
||||||
|
```
|
||||||
|
PUT /{unit_id}/measurement-time
|
||||||
|
```
|
||||||
|
Sets the measurement time preset.
|
||||||
|
|
||||||
|
**Request Body:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"preset": "1h"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Preset Values:**
|
||||||
|
- `10s`, `1m`, `5m`, `10m`, `15m`, `30m`, `1h`, `8h`, `24h`
|
||||||
|
- Custom format: `HH:MM:SS` (e.g., `00:05:30` for 5.5 minutes)
|
||||||
|
|
||||||
|
### Get Leq Calculation Interval
|
||||||
|
```
|
||||||
|
GET /{unit_id}/leq-interval
|
||||||
|
```
|
||||||
|
Gets the current Leq calculation interval.
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "ok",
|
||||||
|
"leq_interval": "1m"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Set Leq Calculation Interval
|
||||||
|
```
|
||||||
|
PUT /{unit_id}/leq-interval
|
||||||
|
```
|
||||||
|
Sets the Leq calculation interval preset.
|
||||||
|
|
||||||
|
**Request Body:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"preset": "1m"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Preset Values:**
|
||||||
|
- `Off`, `10s`, `1m`, `5m`, `10m`, `15m`, `30m`, `1h`, `8h`, `24h`
|
||||||
|
- Custom format: `HH:MM:SS` (e.g., `00:05:30` for 5.5 minutes)
|
||||||
|
|
||||||
|
### Get Lp Store Interval
|
||||||
|
```
|
||||||
|
GET /{unit_id}/lp-interval
|
||||||
|
```
|
||||||
|
Gets the current Lp store interval.
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "ok",
|
||||||
|
"lp_interval": "1s"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Set Lp Store Interval
|
||||||
|
```
|
||||||
|
PUT /{unit_id}/lp-interval
|
||||||
|
```
|
||||||
|
Sets the Lp store interval.
|
||||||
|
|
||||||
|
**Request Body:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"preset": "1s"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Preset Values:**
|
||||||
|
- `Off`, `10ms`, `25ms`, `100ms`, `200ms`, `1s`
|
||||||
|
|
||||||
|
### Get Index Number
|
||||||
|
```
|
||||||
|
GET /{unit_id}/index-number
|
||||||
|
```
|
||||||
|
Gets the current index number for file numbering.
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "ok",
|
||||||
|
"index_number": "0042"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Set Index Number
|
||||||
|
```
|
||||||
|
PUT /{unit_id}/index-number
|
||||||
|
```
|
||||||
|
Sets the index number for file numbering. This number is incremented with each measurement and used in file names.
|
||||||
|
|
||||||
|
**Request Body:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"index": 42
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Valid Range:** 0000 to 9999
|
||||||
|
|
||||||
|
## Device Settings Query
|
||||||
|
|
||||||
|
### Get All Settings
|
||||||
|
```
|
||||||
|
GET /{unit_id}/settings/all
|
||||||
|
```
|
||||||
|
Retrieves all current device settings for verification. This is useful for confirming device configuration before starting measurements.
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "ok",
|
||||||
|
"settings": {
|
||||||
|
"measurement_state": "Stop",
|
||||||
|
"frequency_weighting": "A",
|
||||||
|
"time_weighting": "F",
|
||||||
|
"measurement_time": "1h",
|
||||||
|
"leq_interval": "1m",
|
||||||
|
"lp_interval": "1s",
|
||||||
|
"index_number": "0042",
|
||||||
|
"battery_level": "80",
|
||||||
|
"clock": "2025/12/24,02:30:15",
|
||||||
|
"sleep_mode": "Off",
|
||||||
|
"ftp_status": "Off"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note:** If any setting query fails, the error message will be included in the response for that setting (e.g., `"frequency_weighting": "Error: Connection timeout"`).
|
||||||
|
|
||||||
|
## Data Retrieval
|
||||||
|
|
||||||
|
### Get Final Results
|
||||||
|
```
|
||||||
|
GET /{unit_id}/results
|
||||||
|
```
|
||||||
|
Retrieves the final calculation results (DLC) from the last completed measurement.
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "ok",
|
||||||
|
"data": {
|
||||||
|
"leq": "68.4",
|
||||||
|
"lmax": "82.1",
|
||||||
|
"lmin": "42.3",
|
||||||
|
"lpeak": "89.5"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Power Management
|
||||||
|
|
||||||
|
### Sleep Device
|
||||||
|
```
|
||||||
|
POST /{unit_id}/sleep
|
||||||
|
```
|
||||||
|
Enables Sleep Mode on the device. When enabled, the device will automatically enter sleep mode between Timer Auto measurements.
|
||||||
|
|
||||||
|
**Note:** This is a SETTING, not a command to sleep immediately. Sleep Mode only applies when using Timer Auto measurements.
|
||||||
|
|
||||||
|
### Wake Device
|
||||||
|
```
|
||||||
|
POST /{unit_id}/wake
|
||||||
|
```
|
||||||
|
Disables Sleep Mode on the device.
|
||||||
|
|
||||||
|
### Get Sleep Status
|
||||||
|
```
|
||||||
|
GET /{unit_id}/sleep/status
|
||||||
|
```
|
||||||
|
Gets the current Sleep Mode status.
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "ok",
|
||||||
|
"sleep_mode": "Off"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## FTP File Management
|
## FTP File Management
|
||||||
|
|
||||||
### Enable FTP
|
### Enable FTP
|
||||||
@@ -344,8 +548,46 @@ All endpoints return standard HTTP status codes:
|
|||||||
### Terra-view Integration Example
|
### Terra-view Integration Example
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// Get live status from all devices
|
|
||||||
const devices = ['nl43-1', 'nl43-2', 'nl43-3'];
|
const devices = ['nl43-1', 'nl43-2', 'nl43-3'];
|
||||||
|
|
||||||
|
// Configure all devices before measurement
|
||||||
|
for (const device of devices) {
|
||||||
|
// Set measurement time to 12 hours
|
||||||
|
await fetch(`http://localhost:8000/api/nl43/${device}/measurement-time`, {
|
||||||
|
method: 'PUT',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ preset: '12h' })
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set Leq interval to 1 minute
|
||||||
|
await fetch(`http://localhost:8000/api/nl43/${device}/leq-interval`, {
|
||||||
|
method: 'PUT',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ preset: '1m' })
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set index number for daily file organization
|
||||||
|
const dayNumber = new Date().getDate();
|
||||||
|
await fetch(`http://localhost:8000/api/nl43/${device}/index-number`, {
|
||||||
|
method: 'PUT',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ index: dayNumber })
|
||||||
|
});
|
||||||
|
|
||||||
|
// Verify all settings are correct
|
||||||
|
const settings = await fetch(`http://localhost:8000/api/nl43/${device}/settings/all`)
|
||||||
|
.then(r => r.json());
|
||||||
|
console.log(`Device ${device} settings:`, settings.settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start measurement on all devices at 7pm
|
||||||
|
await Promise.all(
|
||||||
|
devices.map(id =>
|
||||||
|
fetch(`http://localhost:8000/api/nl43/${id}/start`, { method: 'POST' })
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Get live status from all devices
|
||||||
const statuses = await Promise.all(
|
const statuses = await Promise.all(
|
||||||
devices.map(id =>
|
devices.map(id =>
|
||||||
fetch(`http://localhost:8000/api/nl43/${id}/live`)
|
fetch(`http://localhost:8000/api/nl43/${id}/live`)
|
||||||
@@ -353,25 +595,18 @@ const statuses = await Promise.all(
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Start measurement on all devices
|
// Download files from all devices the next morning
|
||||||
await Promise.all(
|
|
||||||
devices.map(id =>
|
|
||||||
fetch(`http://localhost:8000/api/nl43/${id}/start`, { method: 'POST' })
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Download latest files from all devices
|
|
||||||
for (const device of devices) {
|
for (const device of devices) {
|
||||||
// Enable FTP
|
// Enable FTP
|
||||||
await fetch(`http://localhost:8000/api/nl43/${device}/ftp/enable`, {
|
await fetch(`http://localhost:8000/api/nl43/${device}/ftp/enable`, {
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
});
|
});
|
||||||
|
|
||||||
// List files
|
// List files in device data directory
|
||||||
const res = await fetch(`http://localhost:8000/api/nl43/${device}/ftp/files?path=/NL43_DATA`);
|
const res = await fetch(`http://localhost:8000/api/nl43/${device}/ftp/files?path=/NL43_DATA`);
|
||||||
const { files } = await res.json();
|
const { files } = await res.json();
|
||||||
|
|
||||||
// Download latest file
|
// Download latest measurement file
|
||||||
const latestFile = files
|
const latestFile = files
|
||||||
.filter(f => !f.is_dir)
|
.filter(f => !f.is_dir)
|
||||||
.sort((a, b) => b.modified - a.modified)[0];
|
.sort((a, b) => b.modified - a.modified)[0];
|
||||||
@@ -384,10 +619,10 @@ for (const device of devices) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const blob = await download.blob();
|
const blob = await download.blob();
|
||||||
// Process blob...
|
// Save to local storage or process...
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable FTP, re-enable TCP
|
// Disable FTP to re-enable TCP
|
||||||
await fetch(`http://localhost:8000/api/nl43/${device}/ftp/disable`, {
|
await fetch(`http://localhost:8000/api/nl43/${device}/ftp/disable`, {
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
});
|
});
|
||||||
@@ -57,6 +57,7 @@
|
|||||||
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>Measurement Settings</legend>
|
<legend>Measurement Settings</legend>
|
||||||
|
<button onclick="getAllSettings()" style="margin-bottom: 12px; font-weight: bold;">Get ALL Settings</button>
|
||||||
<div style="margin-bottom: 8px;">
|
<div style="margin-bottom: 8px;">
|
||||||
<label style="display: inline; margin-right: 8px;">Frequency Weighting:</label>
|
<label style="display: inline; margin-right: 8px;">Frequency Weighting:</label>
|
||||||
<button onclick="getFreqWeighting()">Get</button>
|
<button onclick="getFreqWeighting()">Get</button>
|
||||||
@@ -280,6 +281,29 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Measurement settings functions
|
// Measurement settings functions
|
||||||
|
async function getAllSettings() {
|
||||||
|
const unitId = document.getElementById('unitId').value;
|
||||||
|
log('Retrieving all device settings (this may take 10-15 seconds)...');
|
||||||
|
|
||||||
|
const res = await fetch(`/api/nl43/${unitId}/settings`);
|
||||||
|
const data = await res.json();
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
log(`Get All Settings failed: ${res.status} - ${data.detail || JSON.stringify(data)}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display in status area
|
||||||
|
statusEl.textContent = JSON.stringify(data.settings, null, 2);
|
||||||
|
|
||||||
|
// Log summary
|
||||||
|
log('=== ALL DEVICE SETTINGS ===');
|
||||||
|
Object.entries(data.settings).forEach(([key, value]) => {
|
||||||
|
log(`${key}: ${value}`);
|
||||||
|
});
|
||||||
|
log('===========================');
|
||||||
|
}
|
||||||
|
|
||||||
async function getFreqWeighting() {
|
async function getFreqWeighting() {
|
||||||
const unitId = document.getElementById('unitId').value;
|
const unitId = document.getElementById('unitId').value;
|
||||||
const res = await fetch(`/api/nl43/${unitId}/frequency-weighting?channel=Main`);
|
const res = await fetch(`/api/nl43/${unitId}/frequency-weighting?channel=Main`);
|
||||||
|
|||||||
98
test_settings_endpoint.py
Normal file
98
test_settings_endpoint.py
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Test script to demonstrate the GET /api/nl43/{unit_id}/settings endpoint.
|
||||||
|
|
||||||
|
This endpoint retrieves all current device settings for verification purposes.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
async def test_settings_retrieval():
|
||||||
|
"""Test the settings retrieval functionality."""
|
||||||
|
from app.services import NL43Client
|
||||||
|
|
||||||
|
# Example configuration - adjust these to match your actual device
|
||||||
|
host = "192.168.1.100" # Replace with your NL43 device IP
|
||||||
|
port = 80
|
||||||
|
unit_id = "NL43-001"
|
||||||
|
|
||||||
|
print(f"Connecting to NL43 device at {host}:{port}...")
|
||||||
|
print(f"Unit ID: {unit_id}\n")
|
||||||
|
|
||||||
|
client = NL43Client(host, port)
|
||||||
|
|
||||||
|
try:
|
||||||
|
print("Retrieving all device settings...")
|
||||||
|
settings = await client.get_all_settings()
|
||||||
|
|
||||||
|
print("\n" + "="*60)
|
||||||
|
print("DEVICE SETTINGS SUMMARY")
|
||||||
|
print("="*60)
|
||||||
|
|
||||||
|
for key, value in settings.items():
|
||||||
|
print(f"{key:.<30} {value}")
|
||||||
|
|
||||||
|
print("="*60)
|
||||||
|
print(f"\nTotal settings retrieved: {len(settings)}")
|
||||||
|
print("\n✓ Settings retrieval successful!")
|
||||||
|
|
||||||
|
except ConnectionError as e:
|
||||||
|
print(f"\n✗ Connection Error: {e}")
|
||||||
|
print("\nTroubleshooting:")
|
||||||
|
print(" 1. Verify the device IP address and port")
|
||||||
|
print(" 2. Ensure the device is powered on and connected to the network")
|
||||||
|
print(" 3. Check firewall settings")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"\n✗ Error: {e}")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_api_endpoint():
|
||||||
|
"""Demonstrate how to call the API endpoint."""
|
||||||
|
print("\n" + "="*60)
|
||||||
|
print("API ENDPOINT USAGE")
|
||||||
|
print("="*60)
|
||||||
|
print("\nTo retrieve all settings via the API, use:")
|
||||||
|
print("\n GET /api/nl43/{unit_id}/settings")
|
||||||
|
print("\nExample with curl:")
|
||||||
|
print("\n curl http://localhost:8000/api/nl43/NL43-001/settings")
|
||||||
|
print("\nExample response:")
|
||||||
|
print("""
|
||||||
|
{
|
||||||
|
"status": "ok",
|
||||||
|
"unit_id": "NL43-001",
|
||||||
|
"settings": {
|
||||||
|
"measurement_state": "Stop",
|
||||||
|
"frequency_weighting": "A",
|
||||||
|
"time_weighting": "F",
|
||||||
|
"measurement_time": "00:01:00",
|
||||||
|
"leq_interval": "1s",
|
||||||
|
"lp_interval": "125ms",
|
||||||
|
"index_number": "0",
|
||||||
|
"battery_level": "100%",
|
||||||
|
"clock": "2025/12/24,20:45:30",
|
||||||
|
"sleep_mode": "Off",
|
||||||
|
"ftp_status": "On"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
print("="*60)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print("NL43 Settings Retrieval Test")
|
||||||
|
print("="*60)
|
||||||
|
print("\nThis test demonstrates the new /api/nl43/{unit_id}/settings endpoint")
|
||||||
|
print("which allows you to view all current device settings for verification.\n")
|
||||||
|
|
||||||
|
# Show API usage
|
||||||
|
asyncio.run(test_api_endpoint())
|
||||||
|
|
||||||
|
# Uncomment below to test actual device connection
|
||||||
|
# asyncio.run(test_settings_retrieval())
|
||||||
|
|
||||||
|
print("\n✓ Test completed!")
|
||||||
Reference in New Issue
Block a user