from pathlib import Path import subprocess,threading,queue,json,time,atexit R=Path.home()/'run/fly-knp' class Worker: def __init__(self,mode='cpu'):self.mode=mode;self.p=None;atexit.register(self.close) def close(self): p=self.p;self.p=None if p: p.terminate() try:p.wait(timeout=2) except subprocess.TimeoutExpired:p.kill();p.wait() def start(self): self.close();self.q=queue.Queue();q=self.q;p=subprocess.Popen([str(R/'controller'),self.mode],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.STDOUT,text=True,bufsize=1);self.p=p def read(): with (R/('worker-'+self.mode+'.log')).open('a') as log: for line in p.stdout: if line.startswith('RESULT '):q.put(json.loads(line[7:])) else:log.write(line);log.flush() q.put(None) threading.Thread(target=read,daemon=True).start() def infer(self,sensors): if not isinstance(sensors,list) or len(sensors)!=9 or any(type(v) is not int or not 0<=v<=15 for v in sensors):raise ValueError('Nine integer sensors0..15 required') if self.p is None or self.p.poll() is not None:self.start() t=time.monotonic() try: self.p.stdin.write(' '.join(map(str,sensors))+'\n');self.p.stdin.flush();v=self.q.get(timeout=20) if v is None:raise RuntimeError('KNP worker stopped') return dict(v,backend='KNP '+self.mode,neuralMilliseconds=round((time.monotonic()-t)*1000,3)) except Exception:self.close();raise