Skip to content

Commit 1a00ed7

Browse files
MarkoVcodeclaude
andcommitted
Fix recording service schema mismatch and missing field errors
This commit fixes multiple issues with the recording API: 1. **Recording Service Schema Update**: Updated recording service to use the new channel schema with class_name, channel number, and method_name fields instead of the old 'parameter' field. 2. **CSV Export Fix**: Updated CSV export to use correct channel key format: device_id_class_name_channel_method_name 3. **Total Duration Calculation**: Fixed AttributeError by calculating total_duration_seconds dynamically from start_time, end_time, and pause_duration_seconds instead of accessing non-existent model field. 4. **Query Method Calls**: Fixed recording service to pass channel number as parameter when calling driver query methods (e.g., query_voltage(1)). The recording API now properly: - Creates recordings with new schema - Collects data from multi-channel devices - Exports CSV with correct headers - Returns proper duration calculations Fixes: 500 Internal Server Error on /recordings endpoint Fixes: KeyError 'parameter' in recording service background task 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 2ebce75 commit 1a00ed7

2 files changed

Lines changed: 40 additions & 27 deletions

File tree

benchmesh-serial-service/src/benchmesh_service/api_recording.py

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -175,24 +175,32 @@ async def list_recordings(db: Session = Depends(get_db)):
175175
RecordingSeries.start_time.desc()
176176
).all()
177177

178-
return {
179-
"recordings": [
180-
{
181-
"id": s.id,
182-
"name": s.name,
183-
"description": s.description,
184-
"start_time": s.start_time.isoformat(),
185-
"end_time": s.end_time.isoformat() if s.end_time else None,
186-
"interval_seconds": s.interval_seconds,
187-
"channels": json.loads(s.channels),
188-
"total_duration_seconds": s.total_duration_seconds,
189-
"pause_duration_seconds": s.pause_duration_seconds,
190-
"paused_at": s.paused_at.isoformat() if s.paused_at else None,
191-
"status": "paused" if s.paused_at else ("stopped" if s.end_time else "recording")
192-
}
193-
for s in series_list
194-
]
195-
}
178+
# Calculate total duration for each recording
179+
recordings = []
180+
for s in series_list:
181+
# Calculate total duration (excluding pauses)
182+
if s.end_time:
183+
# Recording stopped: use actual duration
184+
total_duration = (s.end_time - s.start_time).total_seconds() - s.pause_duration_seconds
185+
else:
186+
# Recording active: use current time
187+
total_duration = (datetime.utcnow() - s.start_time).total_seconds() - s.pause_duration_seconds
188+
189+
recordings.append({
190+
"id": s.id,
191+
"name": s.name,
192+
"description": s.description,
193+
"start_time": s.start_time.isoformat(),
194+
"end_time": s.end_time.isoformat() if s.end_time else None,
195+
"interval_seconds": s.interval_seconds,
196+
"channels": json.loads(s.channels),
197+
"total_duration_seconds": max(0, total_duration), # Ensure non-negative
198+
"pause_duration_seconds": s.pause_duration_seconds,
199+
"paused_at": s.paused_at.isoformat() if s.paused_at else None,
200+
"status": "paused" if s.paused_at else ("stopped" if s.end_time else "recording")
201+
})
202+
203+
return {"recordings": recordings}
196204

197205
@router.get("/{series_id}")
198206
async def get_recording(series_id: int, db: Session = Depends(get_db)):
@@ -318,7 +326,7 @@ async def export_recording(series_id: int, db: Session = Depends(get_db)):
318326
# Empty CSV with just headers
319327
channels = json.loads(series.channels)
320328
fieldnames = ["timestamp"] + [
321-
f"{ch['device_id']}.{ch['parameter']}" for ch in channels
329+
f"{ch['device_id']}_{ch['class_name']}_{ch['channel']}_{ch['method_name']}" for ch in channels
322330
]
323331
writer = csv.DictWriter(output, fieldnames=fieldnames)
324332
writer.writeheader()

benchmesh-serial-service/src/benchmesh_service/services/recording_service.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ async def start_recording(
5050
Args:
5151
db: Database session
5252
name: Unique name for the recording
53-
channels: List of channel definitions with device_id, parameter, label
53+
channels: List of channel definitions with device_id, class_name, channel, method_name, label
5454
interval_seconds: Data collection interval in seconds
5555
description: Optional description
5656
@@ -294,21 +294,26 @@ async def _recording_loop(
294294

295295
for channel in channels:
296296
device_id = channel["device_id"]
297-
parameter = channel["parameter"]
298-
key = f"{device_id}.{parameter}"
297+
class_name = channel["class_name"]
298+
channel_num = channel["channel"]
299+
method_name = channel["method_name"]
300+
301+
# Key format matches frontend: device_id_class_name_channel_method_name
302+
key = f"{device_id}_{class_name}_{channel_num}_{method_name}"
299303

300304
try:
301-
# Get driver and query parameter
305+
# Get driver and query method
302306
if self.serial_manager:
303307
driver = self.serial_manager.get_driver(device_id)
304308
if driver:
305-
method_name = f"query_{parameter}"
306-
if hasattr(driver, method_name):
307-
value = getattr(driver, method_name)()
309+
query_method = f"query_{method_name}"
310+
if hasattr(driver, query_method):
311+
# Call the method with channel number as parameter
312+
value = getattr(driver, query_method)(channel_num)
308313
measurements[key] = value
309314
except Exception as e:
310315
logger.warning(
311-
f"Error reading {parameter} from {device_id}: {e}"
316+
f"Error reading {method_name} from {device_id} channel {channel_num}: {e}"
312317
)
313318

314319
# Store data point if we got any measurements

0 commit comments

Comments
 (0)