Quickstart: sync¶
fujilib.sync wraps the async core for code that is not async. Each method
has the same name, parameters and defaults as its async twin; it blocks until
the result is in.
from fujilib.sync import Fuji
with Fuji.open("COM8", channel_map={"CH1": "co2", "CH2": "co", "CH3": "o2"}) as anz:
frame = anz.poll()
print(frame.channel("CH3").value)
print(anz.read_metadata().response_time_o2_s)
Fuji.open takes the same arguments as open_device and
closes the analyzer at the end of the with block.
Several analyzers, one event loop¶
Each Fuji.open runs its own event loop in a background thread. To share one,
open a SyncPortal and pass it in:
from fujilib.sync import Fuji, SyncPortal
with SyncPortal() as portal:
with Fuji.open("COM8", portal=portal) as a, Fuji.open("COM9", portal=portal) as b:
print(a.poll(), b.poll())
Discovery¶
from fujilib.sync import find_devices
for result in find_devices(ports=["COM8"], addresses=range(1, 32)):
print(result.port, result.address, result.ok, result.model)
Recording¶
from fujilib.sync import Fuji, PollSourceAdapter, SyncCsvSink, pipe, record
with (
Fuji.open("COM8", channel_map={"CH1": "co2", "CH2": "co", "CH3": "o2"}) as anz,
record(PollSourceAdapter("zpa", anz), rate_hz=1.0, duration=600) as rec,
SyncCsvSink("run.csv", portal=anz.portal) as sink,
):
pipe(rec, sink)
for batch in rec: iterates the polls instead. See Recording.