Lamp testbench in Rust around the HPCS 6500
lampbench station / export / label / tm30 / calibrate replace the Python lamp_station.py, lamp_export.py, label_printer.py, tm30.py and calibration.py that lived in HPCS6500-py. The driver is a submodule (HPCS6500/, like mppt-testbench). Workspace crates: tm30 (TM-30-18 port of colour-science 0.4.7), brother-ql (raster protocol, byte-identical to brother_ql) and lamp-label (QR + ID labels for the QL-820NWB). Bundles are byte-identical to lamp_export.py's (golden tests); the station runs end to end in a test against the simulated instrument.
This commit is contained in:
commit
2a3f28001c
241 files changed
+46390
No files matched your search
@@ -0,0 +1,203 @@
|
||||
//! The station end to end: scripted answers on stdin, the simulated
|
||||
//! instrument, a throwaway comparison-data repository.
|
||||
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
use std::process::{Command, Stdio};
|
||||
|
||||
fn git(dir: &Path, args: &[&str]) -> String {
|
||||
let o = Command::new("git")
|
||||
.arg("-C")
|
||||
.arg(dir)
|
||||
.args(args)
|
||||
.output()
|
||||
.unwrap();
|
||||
assert!(
|
||||
o.status.success(),
|
||||
"git {args:?}: {}",
|
||||
String::from_utf8_lossy(&o.stderr)
|
||||
);
|
||||
String::from_utf8_lossy(&o.stdout).to_string()
|
||||
}
|
||||
|
||||
/// A valid EAN-13 with the given 12 leading digits.
|
||||
fn ean(d12: &str) -> String {
|
||||
let sum: u32 = d12
|
||||
.chars()
|
||||
.enumerate()
|
||||
.map(|(i, c)| c.to_digit(10).unwrap() * if i % 2 == 1 { 3 } else { 1 })
|
||||
.sum();
|
||||
format!("{d12}{}", (10 - sum % 10) % 10)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn station_measures_commits_and_re_measures() {
|
||||
let tmp = std::env::temp_dir().join(format!("lampbench-station-{}", std::process::id()));
|
||||
let _ = std::fs::remove_dir_all(&tmp);
|
||||
let repo = tmp.join("comparison-data");
|
||||
std::fs::create_dir_all(repo.join("lamps")).unwrap();
|
||||
git(&repo, &["init", "-q"]);
|
||||
git(&repo, &["config", "user.name", "Test"]);
|
||||
git(&repo, &["config", "user.email", "test@example.com"]);
|
||||
std::fs::write(repo.join("README.md"), "data\n").unwrap();
|
||||
git(&repo, &["add", "."]);
|
||||
git(&repo, &["commit", "-qm", "init"]);
|
||||
|
||||
// --interval 0.5 keeps the runs in different seconds, so the re-measure changes measured_at
|
||||
let internal = ean("200123456789");
|
||||
let answers = [
|
||||
// lamp 1: no barcode
|
||||
"",
|
||||
"philips", // manufacturer -> canonical "Philips"
|
||||
"Test A60", // model
|
||||
"", // type: led
|
||||
"y", // dimmable
|
||||
"Warm White", // variant -> lower case
|
||||
"", // notes
|
||||
"806",
|
||||
"2700",
|
||||
"8.5",
|
||||
"",
|
||||
"",
|
||||
"60", // rated: flux, CCT, W, Ra, lifetime, equivalent
|
||||
"", // insert the lamp
|
||||
// lamp 2: retailer-internal EAN (no online lookup)
|
||||
&internal,
|
||||
"",
|
||||
"Shop bulb",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
// re-measure lamp 1, everything pre-filled
|
||||
"L0001",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
// a bad barcode, then quit
|
||||
"12345",
|
||||
"q",
|
||||
]
|
||||
.join("\n")
|
||||
+ "\n";
|
||||
|
||||
let mut child = Command::new(env!("CARGO_BIN_EXE_lampbench"))
|
||||
.args([
|
||||
"station",
|
||||
"--simulate",
|
||||
"--settle",
|
||||
"0",
|
||||
"--readings",
|
||||
"2",
|
||||
"--interval",
|
||||
"0.5",
|
||||
"--no-push",
|
||||
"--no-labels",
|
||||
"--no-lookup",
|
||||
])
|
||||
.arg("--data-repo")
|
||||
.arg(&repo)
|
||||
.arg("--cache")
|
||||
.arg(tmp.join("ean-cache.json"))
|
||||
.env_remove("HPCS_LABEL_PRINTER")
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.spawn()
|
||||
.unwrap();
|
||||
child
|
||||
.stdin
|
||||
.take()
|
||||
.unwrap()
|
||||
.write_all(answers.as_bytes())
|
||||
.unwrap();
|
||||
let out = child.wait_with_output().unwrap();
|
||||
let text = String::from_utf8_lossy(&out.stdout);
|
||||
assert!(
|
||||
out.status.success(),
|
||||
"{text}\n{}",
|
||||
String::from_utf8_lossy(&out.stderr)
|
||||
);
|
||||
assert!(text.contains("--- New lamp L0001 ---"), "{text}");
|
||||
assert!(
|
||||
text.contains("Using canonical brand name: Philips") || text.contains("Manufacturer"),
|
||||
"{text}"
|
||||
);
|
||||
assert!(
|
||||
text.contains("Lookup: ? / ? (retailer-internal barcode, not resolvable)"),
|
||||
"{text}"
|
||||
);
|
||||
assert!(text.contains("Re-measuring L0001"), "{text}");
|
||||
assert!(text.contains("Not a valid EAN-13/UPC-A: '12345'"), "{text}");
|
||||
assert!(text.contains("PSU off"), "{text}");
|
||||
assert!(text.trim_end().ends_with("Bye."), "{text}");
|
||||
|
||||
let m: serde_json::Value = serde_json::from_str(
|
||||
&std::fs::read_to_string(repo.join("lamps/L0001/metrics.json")).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(m["manufacturer"], "Philips");
|
||||
assert_eq!(m["variant"], "warm white");
|
||||
assert_eq!(m["dimmable"], true);
|
||||
assert_eq!(m["type"], "led");
|
||||
assert_eq!(
|
||||
m["rated"],
|
||||
serde_json::json!({"Phi_lm": 806, "CCT_K": 2700, "Power_W": 8.5, "W_equiv": 60})
|
||||
);
|
||||
assert_eq!(m["readings_averaged"], 2);
|
||||
assert_eq!(m["supply"]["ac_voltage"], 230.0);
|
||||
let m2: serde_json::Value = serde_json::from_str(
|
||||
&std::fs::read_to_string(repo.join("lamps/L0002/metrics.json")).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(m2["ean"], internal.as_str());
|
||||
assert_eq!(m2["notes"], "retailer-internal barcode, brand unknown");
|
||||
assert_eq!(
|
||||
std::fs::read_to_string(repo.join("lamps/L0001/spd.csv"))
|
||||
.unwrap()
|
||||
.lines()
|
||||
.count(),
|
||||
351
|
||||
);
|
||||
assert_eq!(
|
||||
std::fs::read_to_string(repo.join("lamps/L0001/tm30.csv"))
|
||||
.unwrap()
|
||||
.lines()
|
||||
.count(),
|
||||
17
|
||||
);
|
||||
|
||||
let log = git(&repo, &["log", "--format=%s"]);
|
||||
let subjects: Vec<&str> = log.lines().collect();
|
||||
assert_eq!(
|
||||
subjects[0], "Re-measure lamp L0001 (Philips, Test A60, warm white)",
|
||||
"{log}"
|
||||
);
|
||||
assert_eq!(
|
||||
subjects[1],
|
||||
format!("Add lamp L0002 (Shop bulb, EAN {internal})"),
|
||||
"{log}"
|
||||
);
|
||||
assert_eq!(
|
||||
subjects[2], "Add lamp L0001 (Philips, Test A60, warm white)",
|
||||
"{log}"
|
||||
);
|
||||
let _ = std::fs::remove_dir_all(&tmp);
|
||||
}
|
||||
Reference in new issue
Block a user