from i7lib.client import run from i7lib.dbutils import Database from i7lib.timeutils import now, to_datetime db = Database() prev_in = None prev_out = None temp_measurement = None def log(msg): ts = now() dt = to_datetime(ts).strftime("%Y-%m-%d %H:%M:%S") print(f"[{dt}] {msg}") def record_enter_detection(instant): result = db.insert("oven_bar_enter_detection", {"detected_time": instant, "deleted": 0, "deleted_time": 0}) if result: log(f"detection recorded in oven_bar_enter_detection, id={result['id']}") else: log("ERROR: detection insert failed in oven_bar_enter_detection") def record_exit_detection(instant): result = db.insert("oven_bar_exit_detection", {"detected_time": instant, "bar_temperature": 0, "deleted": 0, "deleted_time": 0}) if result: log(f"detection recorded in oven_bar_exit_detection, id={result['id']}") else: log("ERROR: detection insert failed in oven_bar_exit_detection") return result def handle_entry(instant): record_enter_detection(instant) result = db.insert("oven_bar", {"entered_time": instant, "exited_time": 0, "bar_temperature": 0, "deleted": 0, "deleted_time": 0}) if result: log(f"bar entered, id={result['id']}") else: log("ERROR: insert failed on entry") def find_oldest_open_bar(): rows = db.query( "oven_bar", filters=[ {"column": "exited_time", "op": "eq", "value": 0}, {"column": "deleted", "op": "eq", "value": 0}, ], order_by=["entered_time"], limit=1, ) if not rows: return None r = rows[0] log(f"oldest open bar: id={r['id']} entered={r['entered_time']}") return r def handle_exit(instant): global temp_measurement det = record_exit_detection(instant) det_id = det["id"] if det else None row = find_oldest_open_bar() if row: db.update("oven_bar", row["id"], {"exited_time": instant}) bar_id = row["id"] log(f"bar exited, id={bar_id}") else: result = db.insert("oven_bar", {"entered_time": instant, "exited_time": instant, "bar_temperature": 0, "deleted": 0, "deleted_time": 0}) bar_id = result["id"] if result else None if result: log(f"bar exited (no open entry), id={bar_id}") else: log("ERROR: insert failed on orphan exit") temp_measurement = {"det_id": det_id, "bar_id": bar_id, "readings": [], "remaining": 5} log("started temperature measurement (5 ticks)") def collect_temperature(thprocess): global temp_measurement if temp_measurement is None: return temp_measurement["readings"].append(thprocess) temp_measurement["remaining"] -= 1 log(f"temp reading: {thprocess} ({temp_measurement['remaining']} remaining)") if temp_measurement["remaining"] > 0: return max_temp = max(temp_measurement["readings"]) log(f"temperature measurement complete, max={max_temp}") if temp_measurement["det_id"]: db.update("oven_bar_exit_detection", temp_measurement["det_id"], {"bar_temperature": max_temp}) if temp_measurement["bar_id"]: db.update("oven_bar", temp_measurement["bar_id"], {"bar_temperature": max_temp}) temp_measurement = None def logic(plant): global prev_in, prev_out sig_in = plant.state.get("in-detect-oven", 0.0) sig_out = plant.state.get("out-detect-oven", 0.0) thprocess = plant.state.get("THprocess", 0.0) if prev_in is not None: if sig_in == 1.0 and prev_in == 0.0: instant_in = plant.instants.get("in-detect-oven", 0) log(f"RISING EDGE in-detect-oven (prev={prev_in} -> cur={sig_in})") handle_entry(instant_in) if sig_out == 1.0 and prev_out == 0.0: instant_out = plant.instants.get("out-detect-oven", 0) log(f"RISING EDGE out-detect-oven (prev={prev_out} -> cur={sig_out})") handle_exit(instant_out) else: log(f"first tick, skipping edges (in={sig_in}, out={sig_out})") collect_temperature(thprocess) prev_in = sig_in prev_out = sig_out if __name__ == "__main__": run(logic, interval_ms=1000, offset_ms=200)