- 01Frame read
- 02QR decode
- 03Journal policy
- 04Append + flush
Put the boundary code in one place
The adapter opens one image or one camera. It appends accepted events to a local JSON-lines file, flushes after each event and releases the camera on exit. It does not save frames, upload images, launch a browser or execute the contents of a marker.
"""Use a V4L2/OpenCV camera or a local image; never follow decoded URLs."""
import argparse
from datetime import datetime, timezone
import json
from pathlib import Path
import time
from journal import Journal
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--device", type=int, default=0)
parser.add_argument("--image", type=Path)
parser.add_argument("--output", type=Path, default=Path("events.jsonl"))
args = parser.parse_args()
import cv2 # Install python3-opencv using your OS package manager.
detector, journal = cv2.QRCodeDetector(), Journal()
camera = None
try:
if not args.image:
camera = cv2.VideoCapture(args.device)
if not camera.isOpened():
raise RuntimeError("Camera unavailable; verify its vendor example and device index first")
with args.output.open("a", encoding="utf-8") as log:
while True:
if args.image:
frame = cv2.imread(str(args.image))
ok = frame is not None
else:
ok, frame = camera.read()
if not ok:
raise RuntimeError("No image/frame; no event was recorded")
payload, _, _ = detector.detectAndDecode(frame)
event = journal.accept(payload, time.monotonic())
if event:
event["at_utc"] = datetime.now(timezone.utc).isoformat()
log.write(json.dumps(event, ensure_ascii=True) + "\n")
log.flush()
print(event["label"])
if args.image:
break
time.sleep(0.05)
except KeyboardInterrupt:
pass
finally:
if camera:
camera.release()
if __name__ == "__main__":
main()Append mode preserves earlier events. Flush makes Python's buffered data available to the operating system; it is not a crash-durability guarantee. If you need durable publication later, continue into the free Unix file and filesystem lessons.
Observe the output
Run the program, present CRIGOR:BOX_A, hold it still, then wait longer than five seconds and present it again. Inspect the file with a text editor. Each line should be a complete JSON object. Stop with Ctrl+C and confirm another camera program can open the device afterward.
The elapsed value comes from a monotonic clock and is not seconds since the start of this particular program. Use differences within a run. at_utc is the human-readable timestamp.
Try it
Point --output at a directory you cannot write to. The program should report the filesystem error rather than quietly claiming a saved event. Use a temporary trial file when experimenting and keep personal locations out of marker labels.