diff --git a/simulation/.classpath b/simulation/.classpath new file mode 100644 index 0000000..3717ff0 --- /dev/null +++ b/simulation/.classpath @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/simulation/.gitignore b/simulation/.gitignore new file mode 100644 index 0000000..ae3c172 --- /dev/null +++ b/simulation/.gitignore @@ -0,0 +1 @@ +/bin/ diff --git a/simulation/.project b/simulation/.project new file mode 100644 index 0000000..eaad9a1 --- /dev/null +++ b/simulation/.project @@ -0,0 +1,17 @@ + + + WS2812Emulation + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/simulation/libs/.gitignore b/simulation/libs/.gitignore new file mode 100644 index 0000000..44794ca --- /dev/null +++ b/simulation/libs/.gitignore @@ -0,0 +1,3 @@ +luaj-3.0.1.zip +luaj-3.0.1/ +luaj-sources-3.0.1.jar diff --git a/simulation/libs/Readme.md b/simulation/libs/Readme.md new file mode 100644 index 0000000..c76c4af --- /dev/null +++ b/simulation/libs/Readme.md @@ -0,0 +1,7 @@ +# Dependencies + +The following file is expected here: +`luaj-3.0.1.zip` + +It can be downloaded here: +https://sourceforge.net/projects/luaj/files/latest/download diff --git a/simulation/libs/luaj-jme-3.0.1.jar b/simulation/libs/luaj-jme-3.0.1.jar new file mode 100644 index 0000000..4541df3 Binary files /dev/null and b/simulation/libs/luaj-jme-3.0.1.jar differ diff --git a/simulation/libs/luaj-jse-3.0.1.jar b/simulation/libs/luaj-jse-3.0.1.jar new file mode 100644 index 0000000..e125860 Binary files /dev/null and b/simulation/libs/luaj-jse-3.0.1.jar differ diff --git a/simulation/src/de/c3ma/ollo/LuaSimulation.java b/simulation/src/de/c3ma/ollo/LuaSimulation.java new file mode 100644 index 0000000..7ea3476 --- /dev/null +++ b/simulation/src/de/c3ma/ollo/LuaSimulation.java @@ -0,0 +1,13 @@ +package de.c3ma.ollo; + +/** + * created at 29.12.2017 - 18:29:07
+ * creator: ollo
+ * project: WS2812Emulation
+ * $Id: $
+ * @author ollo
+ */ +public interface LuaSimulation { + + public void reboottriggered(); +} diff --git a/simulation/src/de/c3ma/ollo/LuaThreadTmr.java b/simulation/src/de/c3ma/ollo/LuaThreadTmr.java new file mode 100644 index 0000000..0a958fd --- /dev/null +++ b/simulation/src/de/c3ma/ollo/LuaThreadTmr.java @@ -0,0 +1,54 @@ +package de.c3ma.ollo; + +import org.luaj.vm2.LuaValue; + +/** + * created at 29.12.2017 - 18:48:27
+ * creator: ollo
+ * project: WS2812Emulation
+ * $Id: $
+ * @author ollo
+ */ +public class LuaThreadTmr extends Thread { + + + private boolean running = true; + + private boolean stopped = false; + + private LuaValue code; + + private final int delay; + + private final int timerNumber; + + public LuaThreadTmr(int timerNumber, LuaValue code, boolean endlessloop, int delay) { + this.code = code; + this.running = endlessloop; + this.delay = delay; + this.timerNumber = timerNumber; + } + + @Override + public void run() { + try { + do { + Thread.sleep(delay); + if (code != null) { + code.call(); + } + } while(running); + } catch(InterruptedException ie) { + System.err.println("[TMR] Timer" + timerNumber + " interrupted"); + } + stopped = true; + } + + public boolean isStopped() { return stopped; } + + public void stopThread() { + running = false; + code = null; + } + +} diff --git a/simulation/src/de/c3ma/ollo/WS2812Simulation.java b/simulation/src/de/c3ma/ollo/WS2812Simulation.java new file mode 100644 index 0000000..57c28f6 --- /dev/null +++ b/simulation/src/de/c3ma/ollo/WS2812Simulation.java @@ -0,0 +1,120 @@ +package de.c3ma.ollo; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; + +import org.luaj.vm2.Globals; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.lib.jse.JsePlatform; + +import de.c3ma.ollo.mockup.DoFileFunction; +import de.c3ma.ollo.mockup.ESP8266File; +import de.c3ma.ollo.mockup.ESP8266Node; +import de.c3ma.ollo.mockup.ESP8266Tmr; +import de.c3ma.ollo.mockup.ESP8266Uart; +import de.c3ma.ollo.mockup.ESP8266Wifi; +import de.c3ma.ollo.mockup.ESP8266Ws2812; + +/** + * created at 28.12.2017 - 13:19:32
+ * creator: ollo
+ * project: WS2812Emulation
+ * $Id: $
+ * + * @author ollo
+ */ +public class WS2812Simulation implements LuaSimulation { + + private Globals globals = JsePlatform.standardGlobals(); + private ESP8266Tmr espTmr = new ESP8266Tmr(); + private ESP8266File espFile = new ESP8266File(); + private ESP8266Node espNode = new ESP8266Node(this); + private DoFileFunction doFile = new DoFileFunction(globals); + private String scriptName; + + public WS2812Simulation(File sourceFolder) { + globals.load(new ESP8266Uart()); + globals.load(new ESP8266Ws2812()); + globals.load(espTmr); + globals.load(espFile); + globals.load(espNode); + globals.load(new ESP8266Wifi()); + globals.set("dofile", doFile); + + try { + File tempFile = File.createTempFile("NodemcuSimuFile", ""); + File tempDir = new File(tempFile.getParent() + File.separator + "Nodemcu" + System.currentTimeMillis()); + tempDir.mkdir(); + + + System.out.println("[Nodemcu] Directory is " + tempDir.getAbsolutePath()); + + // Copy all files into the temporary folder + for (File f : sourceFolder.listFiles()) { + Files.copy(f.toPath(), new File(tempDir.getAbsolutePath() + File.separator + f.getName()).toPath()); + } + + espFile.setWorkingDirectory(tempDir); + espNode.setWorkingDirectory(tempDir); + doFile.setWorkingDirectory(tempDir); + } catch (IOException e) { + System.err.println("[Nodemcu] " + e.getMessage()); + espFile = null; + espNode = null; + } + } + + public static void main(String[] args) { + + if (args.length == 0) { + printUsage(); + return; + } + + if (args.length == 1) { + File f = new File(args[0]); + if (f.exists()) { + WS2812Simulation simu = new WS2812Simulation(f.getParentFile()); + System.out.println("File : " + f.getAbsolutePath()); + simu.callScript(f.getName()); + } + } else { + printUsage(); + } + + } + + private static void printUsage() { + System.out.println("Usage:"); + System.out.println("one argument required: file to execute."); + System.out.println(".e.g: init.lua"); + } + + @Override + public void reboottriggered() { + System.out.println("=================== Reboot in Simulation -> call it again ================="); + this.espTmr.stopAllTimer(); + try { + Thread.sleep(200); + if (this.scriptName != null) { + System.out.println("Reexecuting..."); + callScript(this.scriptName); + } + } catch (InterruptedException e) { + + } + + } + + private void callScript(String filename) { + this.scriptName=filename; + + if ((espFile != null) && (espFile.getFileInWorkingDir(filename) != null)) { + LuaValue chunk = globals.loadfile(espFile.getFileInWorkingDir(filename).getAbsolutePath()); + chunk.call(); + } else { + throw new RuntimeException("Copy into temporary folder failed; script not available"); + } + } +} diff --git a/simulation/src/de/c3ma/ollo/mockup/DoFileFunction.java b/simulation/src/de/c3ma/ollo/mockup/DoFileFunction.java new file mode 100644 index 0000000..56e5a63 --- /dev/null +++ b/simulation/src/de/c3ma/ollo/mockup/DoFileFunction.java @@ -0,0 +1,46 @@ +package de.c3ma.ollo.mockup; + +import java.io.File; + +import org.luaj.vm2.Globals; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.lib.OneArgFunction; + +/** + * created at 29.12.2017 - 20:23:48
+ * creator: ollo
+ * project: WS2812Emulation
+ * $Id: $
+ * @author ollo
+ */ +public class DoFileFunction extends OneArgFunction { + + private File workingDir = null; + private Globals globals; + + public DoFileFunction(Globals globals) { + this.globals = globals; + } + + @Override + public LuaValue call(LuaValue luaFilename) { + String filename = luaFilename.checkjstring(); + + System.out.println("[Nodemcu] dofile " + filename); + + File f = new File(workingDir.getAbsolutePath() + File.separator + filename); + + if (f.exists()) { + LuaValue chunk = this.globals.loadfile(f.getAbsolutePath()); + chunk.call(); + return LuaValue.valueOf(true); + } else { + return LuaValue.valueOf(false); + } + } + + public void setWorkingDirectory(File workingDir) { + this.workingDir = workingDir; + } + +} diff --git a/simulation/src/de/c3ma/ollo/mockup/ESP8266File.java b/simulation/src/de/c3ma/ollo/mockup/ESP8266File.java new file mode 100644 index 0000000..27ad122 --- /dev/null +++ b/simulation/src/de/c3ma/ollo/mockup/ESP8266File.java @@ -0,0 +1,101 @@ +package de.c3ma.ollo.mockup; + +import java.io.File; +import java.util.ArrayList; + +import org.luaj.vm2.LuaTable; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.lib.OneArgFunction; +import org.luaj.vm2.lib.TwoArgFunction; + +/** + * created at 29.12.2017 - 01:08:53
+ * creator: ollo
+ * project: WS2812Emulation
+ * $Id: $
+ * @author ollo
+ */ +public class ESP8266File extends TwoArgFunction { + + private File workingDir = null; + + private File openedFile = null; + + @Override + public LuaValue call(LuaValue modname, LuaValue env) { + env.checkglobals(); + final LuaTable file = new LuaTable(); + file.set("open", new OpenFunction()); + file.set("list", new ListFunction()); + file.set("remove", new RemoveFunction()); + env.set("file", file); + env.get("package").get("loaded").set("file", file); + + return file; + } + + private class ListFunction extends TwoArgFunction { + + @Override + public LuaValue call(LuaValue arg1, LuaValue arg2) { + final LuaTable fileList = new LuaTable(); + + if ((workingDir != null) && (workingDir.exists())) { + File[] files = workingDir.listFiles(); + for (File file : files) { + fileList.set(file.getName(), file.getAbsolutePath()); + } + } + + return fileList; + } + + } + + private class OpenFunction extends OneArgFunction { + + @Override + public LuaValue call(LuaValue fileName) { + + final String codeFileName = fileName.checkjstring(); + final File f = new File( workingDir.getAbsolutePath() + File.separator + codeFileName); + //System.out.println("[FILE] Loading " + codeFileName); + if (f.exists()) { + ESP8266File.this.openedFile = f; + } + + return LuaValue.valueOf((f.exists())); + } + + } + + private class RemoveFunction extends OneArgFunction { + + @Override + public LuaValue call(LuaValue fileName) { + + final String luaFileName = fileName.checkjstring(); + System.out.println("[FILE] Removing " + luaFileName); + File f = new File(workingDir.getAbsolutePath() + File.separator + fileName); + if (f.exists()) { + return LuaValue.valueOf(f.delete()); + } else { + return LuaValue.valueOf(false); + } + } + + } + + public void setWorkingDirectory(File workingDir) { + this.workingDir = workingDir; + } + + public File getFileInWorkingDir(String filename) { + File f = new File (workingDir.getAbsolutePath() + File.separator + filename); + if (f.exists()) { + return f; + } else { + return null; + } + } +} diff --git a/simulation/src/de/c3ma/ollo/mockup/ESP8266Node.java b/simulation/src/de/c3ma/ollo/mockup/ESP8266Node.java new file mode 100644 index 0000000..ab4fb8a --- /dev/null +++ b/simulation/src/de/c3ma/ollo/mockup/ESP8266Node.java @@ -0,0 +1,79 @@ +package de.c3ma.ollo.mockup; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; + +import org.luaj.vm2.LuaTable; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.lib.OneArgFunction; +import org.luaj.vm2.lib.TwoArgFunction; +import org.luaj.vm2.lib.ZeroArgFunction; + +import de.c3ma.ollo.LuaSimulation; + +/** + * created at 29.12.2017 - 01:29:40
+ * creator: ollo
+ * project: WS2812Emulation
+ * $Id: $
+ * @author ollo
+ */ +public class ESP8266Node extends TwoArgFunction { + + private File workingDir = null; + private LuaSimulation nodemcuSimu; + + public ESP8266Node(LuaSimulation nodemcuSimu) { + this.nodemcuSimu = nodemcuSimu; + } + + @Override + public LuaValue call(LuaValue modname, LuaValue env) { + env.checkglobals(); + final LuaTable node = new LuaTable(); + node.set("compile", new CompileFunction()); + node.set("restart", new RestartFunction()); + env.set("node", node); + env.get("package").get("loaded").set("node", node); + return node; + } + + private class CompileFunction extends OneArgFunction { + + @Override + public LuaValue call(LuaValue fileName) { + final String codeFileName = fileName.checkjstring(); + final String compiledFileName = fileName.checkjstring().replace(".lua", ".lc"); + final File f = new File( workingDir.getAbsolutePath() + File.separator + codeFileName); + System.out.println("[Node] Compiling " + compiledFileName); + final File outf = new File( workingDir.getAbsolutePath() + File.separator + compiledFileName); + if (f.exists()) { + //Simply copy the file as .lc file + try { + Files.copy(f.toPath(), outf.toPath()); + } catch (IOException e) { + return LuaValue.valueOf(false); + } + } + + return LuaValue.valueOf(f.exists()); + } + + } + + private class RestartFunction extends ZeroArgFunction { + + @Override + public LuaValue call() { + System.out.println("[Node] Restart"); + nodemcuSimu.reboottriggered(); + return LuaValue.valueOf(false); + } + + } + + public void setWorkingDirectory(File workingDir) { + this.workingDir = workingDir; + } +} diff --git a/simulation/src/de/c3ma/ollo/mockup/ESP8266Tmr.java b/simulation/src/de/c3ma/ollo/mockup/ESP8266Tmr.java new file mode 100644 index 0000000..2b01e83 --- /dev/null +++ b/simulation/src/de/c3ma/ollo/mockup/ESP8266Tmr.java @@ -0,0 +1,92 @@ +package de.c3ma.ollo.mockup; + +import org.luaj.vm2.LuaTable; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.Varargs; +import org.luaj.vm2.lib.OneArgFunction; +import org.luaj.vm2.lib.TwoArgFunction; +import org.luaj.vm2.lib.VarArgFunction; + +import de.c3ma.ollo.LuaThreadTmr; + +/** + * created at 29.12.2017 - 00:07:22
+ * creator: ollo
+ * project: WS2812Emulation
+ * $Id: $
+ * @author ollo
+ */ +public class ESP8266Tmr extends TwoArgFunction { + + private static final int MAXTHREADS = 7; + + private static LuaThreadTmr[] allThreads = new LuaThreadTmr[MAXTHREADS]; + + @Override + public LuaValue call(LuaValue modname, LuaValue env) { + env.checkglobals(); + final LuaTable tmr = new LuaTable(); + tmr.set("stop", new stop()); + tmr.set("alarm", new alarm()); + env.set("tmr", tmr); + env.get("package").get("loaded").set("tmr", tmr); + + /* initialize the Threads */ + for (Thread t : allThreads) { + t = null; + } + + return tmr; + } + + private boolean stopTmr(int i) { + if (allThreads[i] != null) { + allThreads[i].stopThread(); + allThreads[i] = null; + return true; + } else { + return false; + } + } + + private class stop extends OneArgFunction { + + @Override + public LuaValue call(LuaValue arg) { + final int timerNumer = arg.toint(); + System.out.println("[TMR] Timer" + timerNumer + " stopped"); + return LuaValue.valueOf(stopTmr(timerNumer)); + } + + } + + private class alarm extends VarArgFunction { + public Varargs invoke(Varargs varargs) { + if (varargs.narg()== 4) { + final int timerNumer = varargs.arg(1).toint(); + final byte endlessloop = varargs.arg(3).tobyte(); + final int delay = varargs.arg(2).toint(); + final LuaValue code = varargs.arg(4); + System.out.println("[TMR] Timer" + timerNumer ); + + if ((timerNumer < 0) || (timerNumer > timerNumer)) { + return LuaValue.error("[TMR] Timer" + timerNumer + " is not available, choose 0 to 6"); + } + + if (stopTmr(timerNumer)) { + System.err.println("[TMR] Timer" + timerNumer + " stopped"); + } + + allThreads[timerNumer] = new LuaThreadTmr(timerNumer, code, (endlessloop == 1), delay); + allThreads[timerNumer].start(); + } + return LuaValue.valueOf(true); + } + } + + public void stopAllTimer() { + for (int i = 0; i < allThreads.length; i++) { + stopTmr(i); + } + } +} diff --git a/simulation/src/de/c3ma/ollo/mockup/ESP8266Uart.java b/simulation/src/de/c3ma/ollo/mockup/ESP8266Uart.java new file mode 100644 index 0000000..9cb59c4 --- /dev/null +++ b/simulation/src/de/c3ma/ollo/mockup/ESP8266Uart.java @@ -0,0 +1,38 @@ +package de.c3ma.ollo.mockup; + +import org.luaj.vm2.LuaTable; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.Varargs; +import org.luaj.vm2.lib.TwoArgFunction; +import org.luaj.vm2.lib.VarArgFunction; + +/** + * created at 28.12.2017 - 23:05:05
+ * creator: ollo
+ * project: WS2812Emulation
+ * $Id: $
+ * @author ollo
+ */ +public class ESP8266Uart extends TwoArgFunction { + + @Override + public LuaValue call(LuaValue modname, LuaValue env) { + env.checkglobals(); + final LuaTable uart = new LuaTable(); + uart.set("setup", new setup()); + env.set("uart", uart); + env.get("package").get("loaded").set("uart", uart); + return uart; + } + + private class setup extends VarArgFunction { + public Varargs invoke(Varargs varargs) { + if (varargs.narg()== 6) { + System.out.println("[UART] " + varargs.arg(2) + " " + varargs.arg(3) + + ((varargs.arg(4).checkint() > 0) ? "Y" : "N") + + varargs.arg(5)); + } + return LuaValue.valueOf(true); + } + } +} diff --git a/simulation/src/de/c3ma/ollo/mockup/ESP8266Wifi.java b/simulation/src/de/c3ma/ollo/mockup/ESP8266Wifi.java new file mode 100644 index 0000000..48bcb3b --- /dev/null +++ b/simulation/src/de/c3ma/ollo/mockup/ESP8266Wifi.java @@ -0,0 +1,69 @@ +package de.c3ma.ollo.mockup; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; + +import org.luaj.vm2.LuaTable; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.lib.OneArgFunction; +import org.luaj.vm2.lib.TwoArgFunction; +import org.luaj.vm2.lib.ZeroArgFunction; + +import de.c3ma.ollo.LuaSimulation; + +/** + * created at 29.12.2017 - 01:29:40
+ * creator: ollo
+ * project: WifiEmulation
+ * $Id: $
+ * @author ollo
+ */ +public class ESP8266Wifi extends TwoArgFunction { + + @Override + public LuaValue call(LuaValue modname, LuaValue env) { + env.checkglobals(); + final LuaTable wifi = new LuaTable(); + wifi.set("setmode", new SetModeFunction()); + wifi.set("ap", new ApFunction()); + wifi.set("SOFTAP", "SOFTAP"); + env.set("wifi", wifi); + env.get("package").get("loaded").set("wifi", wifi); + return wifi; + } + + private class SetModeFunction extends OneArgFunction { + + @Override + public LuaValue call(LuaValue apmode) { + final String APmodeString = apmode.checkjstring(); + System.out.println("[Wifi] set mode " + APmodeString); + return LuaValue.valueOf(true); + } + + } + + private class ApFunction extends TwoArgFunction { + + @Override + public LuaValue call(LuaValue modname, LuaValue env) { + final LuaTable ap = new LuaTable(); + ap.set("config", new ConfigFunction()); + env.set("ap", ap); + env.get("package").get("loaded").set("wifi.ap", ap); + return ap; + } + + } + + private class ConfigFunction extends OneArgFunction { + + @Override + public LuaValue call(LuaValue arg) { + System.out.println("[Wifi] config"); + return LuaValue.valueOf(true); + } + + } +} diff --git a/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java b/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java new file mode 100644 index 0000000..97d015c --- /dev/null +++ b/simulation/src/de/c3ma/ollo/mockup/ESP8266Ws2812.java @@ -0,0 +1,61 @@ +package de.c3ma.ollo.mockup; + +import org.luaj.vm2.LuaTable; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.lib.OneArgFunction; +import org.luaj.vm2.lib.TwoArgFunction; +import org.luaj.vm2.lib.ZeroArgFunction; + +/** + * created at 28.12.2017 - 23:34:04
+ * creator: ollo
+ * project: WS2812Emulation
+ * $Id: $
+ * @author ollo
+ */ +public class ESP8266Ws2812 extends TwoArgFunction { + + @Override + public LuaValue call(LuaValue modname, LuaValue env) { + env.checkglobals(); + final LuaTable ws2812 = new LuaTable(); + ws2812.set("init", new init()); + ws2812.set("write", new write()); + env.set("ws2812", ws2812); + env.get("package").get("loaded").set("ws2812", ws2812); + return ws2812; + } + + private class init extends ZeroArgFunction { + + @Override + public LuaValue call() { + System.out.println("[WS2812] init"); + return LuaValue.valueOf(true); + } + + } + + private class write extends OneArgFunction { + + @Override + public LuaValue call(LuaValue arg) { + if (arg.isstring()) { + int length = arg.checkstring().rawlen(); + System.out.println("[WS2812] write length:" + length); + if ((length % 3) == 0) { + byte[] array = arg.toString().getBytes(); + for (int i = 0; i < length; i+=3) { + /*System.out.println( + array[i+0] + " " + + array[i+1] + " " + + array[i+2] + );*/ + } + } + } + return LuaValue.valueOf(true); + } + + } +}