package at.acdp.urweb; import at.acdp.urweb.sclient.data.MasterBoardData; import at.acdp.urweb.sclient.data.RobotProgramLabel; import at.acdp.urweb.sclient.data.ScReadThread; import okhttp3.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.Semaphore; import java.util.concurrent.atomic.AtomicInteger; public class URBot { private static final Logger log = LoggerFactory.getLogger(URBot.class); private static final MediaType MEDIA_TYPE_JSON = MediaType.get("application/json; charset=utf-8"); private ScReadThread sc; private BlockingQueue cmdq = new LinkedBlockingQueue<>(); private AtomicInteger nextID = new AtomicInteger(1); private Semaphore cmdDoneSem = new Semaphore(0); private RobotProgramLabel currentAck; public URBot(String ip, int port) { sc = new ScReadThread(ip, port, this); } public synchronized void ackNumber(RobotProgramLabel rpl) { this.currentAck = rpl; cmdDoneSem.release(); } public void start() { Thread readThread = new Thread(sc); readThread.start(); Thread queueThread = new Thread(() -> { try { while (true) { cmdDoneSem.acquire(); var c = cmdq.take(); sc.writeCmd(c); while (true) { if (currentAck.id == c.id && currentAck.message.equals("URWEB_END")) { if (c.cpeeCallback != null) { ackCPEE(c); } break; } } } } catch (InterruptedException e) { e.printStackTrace(); } }); queueThread.start(); } private void write(RobotCommand rc) { String[] lines = rc.cmd.split("[\\r\\n]+"); String res = ""; for (String line : lines) { line = line.trim(); if (line.startsWith("//")) continue; if (line.startsWith("#")) continue; if (!line.endsWith("\n")) line += "\n"; res += line; } if (!res.endsWith("\n")) res += "\n"; res=res.trim(); int id = nextID.getAndIncrement(); if(res.endsWith("end")) { res=res.substring(0, res.length()-3); res+=String.format("$ %s \"URWEB_END\"\nend\n", id); } try { rc.id=id; // rc.cmd = String.format("def urweb():\n%s\n$ %s \"URWEB_END\"\nend\n", res, id); rc.cmd = res; this.cmdq.put(rc); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } private void ackCPEE(RobotCommand r) { try { OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .url(r.cpeeCallback + "/") .put(RequestBody.create(MEDIA_TYPE_JSON, "[{}]")) .build(); log.info("putting to {}", r.cpeeCallback); Response res = client.newCall(request).execute(); log.info("result {}", res.toString()); r.cpeeCallbackResult = res.body().string(); r.cpeeCallbackCode = res.code(); r.cpeeCallbackMessage = res.message(); } catch (Exception e) { log.warn("cpee callback failed", e); r.cpeeCallbackError = e.getMessage(); } } private void sendStringCmd(String cmd) { sc.writeCmd(new RobotCommand(nextID.getAndIncrement(), cmd)); } public void sendFreedrive(int timeout) { sendStringCmd(String.format("def myProg():\n\tfreedrive_mode()\n\tsleep(%d)\nend", timeout)); } public void sendMessage(String message) { sendStringCmd(String.format("textmsg(%s)", message)); } public void setDigital(int which, boolean val) { sendStringCmd(String.format("digital_out[%d]=%s", which, val ? "True" : "False")); } public boolean getDigital(int which) { MasterBoardData mb = sc.getRde().getLastMB(); return ((mb.digitalOutputBits & (1 << which)) > 0); } public void sendCmd(RobotCommand cmd) { write(cmd); } public BlockingQueue getCmdq() { return cmdq; } }