mirror of
https://github.com/cjfranko/NTP-Timeturner.git
synced 2025-11-08 10:22:02 +00:00
fix: Handle drop-frame timecode separator in API and UI
Co-authored-by: aider (gemini/gemini-2.5-pro) <aider@aider.chat>
This commit is contained in:
parent
22dc01e80f
commit
3ffb54e9aa
3 changed files with 38 additions and 6 deletions
|
|
@ -8,13 +8,13 @@ This document describes the HTTP API for the NTP Timeturner application.
|
|||
|
||||
- **`GET /api/status`**
|
||||
|
||||
Retrieves the real-time status of the LTC reader and system clock synchronization.
|
||||
Retrieves the real-time status of the LTC reader and system clock synchronization. The `ltc_timecode` field uses `:` as a separator for non-drop-frame timecode, and `;` for drop-frame timecode between seconds and frames (e.g., `10:20:30;00`).
|
||||
|
||||
**Example Response:**
|
||||
```json
|
||||
{
|
||||
"ltc_status": "LOCK",
|
||||
"ltc_timecode": "10:20:30:00",
|
||||
"ltc_timecode": "10:20:30;00",
|
||||
"frame_rate": "25.00fps",
|
||||
"system_clock": "10:20:30.005",
|
||||
"system_date": "2025-07-30",
|
||||
|
|
|
|||
32
src/api.rs
32
src/api.rs
|
|
@ -47,7 +47,11 @@ async fn get_status(data: web::Data<AppState>) -> impl Responder {
|
|||
|
||||
let ltc_status = state.latest.as_ref().map_or("(waiting)".to_string(), |f| f.status.clone());
|
||||
let ltc_timecode = state.latest.as_ref().map_or("…".to_string(), |f| {
|
||||
format!("{:02}:{:02}:{:02}:{:02}", f.hours, f.minutes, f.seconds, f.frames)
|
||||
let sep = if f.is_drop_frame { ';' } else { ':' };
|
||||
format!(
|
||||
"{:02}:{:02}:{:02}{}{:02}",
|
||||
f.hours, f.minutes, f.seconds, sep, f.frames
|
||||
)
|
||||
});
|
||||
let frame_rate = state.latest.as_ref().map_or("…".to_string(), |f| {
|
||||
format!("{:.2}fps", f.frame_rate.to_f64().unwrap_or(0.0))
|
||||
|
|
@ -291,6 +295,32 @@ mod tests {
|
|||
assert_eq!(resp.hardware_offset_ms, 10);
|
||||
}
|
||||
|
||||
#[actix_web::test]
|
||||
async fn test_get_status_drop_frame() {
|
||||
let app_state = get_test_app_state();
|
||||
// Set state to drop frame
|
||||
app_state
|
||||
.ltc_state
|
||||
.lock()
|
||||
.unwrap()
|
||||
.latest
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.is_drop_frame = true;
|
||||
|
||||
let app = test::init_service(
|
||||
App::new()
|
||||
.app_data(app_state.clone())
|
||||
.service(get_status),
|
||||
)
|
||||
.await;
|
||||
|
||||
let req = test::TestRequest::get().uri("/api/status").to_request();
|
||||
let resp: ApiStatus = test::call_and_read_body_json(&app, req).await;
|
||||
|
||||
assert_eq!(resp.ltc_timecode, "01:02:03;04");
|
||||
}
|
||||
|
||||
#[actix_web::test]
|
||||
async fn test_get_config() {
|
||||
let app_state = get_test_app_state();
|
||||
|
|
|
|||
|
|
@ -98,9 +98,11 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||
}
|
||||
|
||||
// Animate LTC Timecode - only if status is LOCK
|
||||
if (lastApiData.ltc_status === 'LOCK' && lastApiData.ltc_timecode && lastApiData.ltc_timecode.includes(':') && lastApiData.frame_rate) {
|
||||
const tcParts = lastApiData.ltc_timecode.split(':');
|
||||
if (lastApiData.ltc_status === 'LOCK' && lastApiData.ltc_timecode && lastApiData.ltc_timecode.match(/[:;]/) && lastApiData.frame_rate) {
|
||||
const separator = lastApiData.ltc_timecode.includes(';') ? ';' : ':';
|
||||
const tcParts = lastApiData.ltc_timecode.split(/[:;]/);
|
||||
const frameRate = parseFloat(lastApiData.frame_rate);
|
||||
|
||||
if (tcParts.length === 4 && !isNaN(frameRate) && frameRate > 0) {
|
||||
let h = parseInt(tcParts[0], 10);
|
||||
let m = parseInt(tcParts[1], 10);
|
||||
|
|
@ -126,7 +128,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||
h %= 24;
|
||||
|
||||
statusElements.ltcTimecode.textContent =
|
||||
`${String(h).padStart(2, '0')}:${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}:${String(f).padStart(2, '0')}`;
|
||||
`${String(h).padStart(2, '0')}:${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}${separator}${String(f).padStart(2, '0')}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue