var async = require("async"); var homedir = require("homedir")(); var spawn = require("child_process").spawn; var SerialPort = require("serialport"); var path = require("path"); var test = require("tape"); var testbed = require("testbed-query-fixtures"); const exec = path.join(process.env.IDF_PATH, "components", "esptool_py", "esptool", "esptool.py"); const buildPath = path.join(__dirname, "lora32", "build"); try { var testbedConfig = require(path.join(homedir, ".testbed.json")); } catch(e) { console.log(e); console.error("testbed.json fixture file not found."); process.exit(1); } var devices = testbed({ f: [ "esp32", "lora" ], fixtures: testbedConfig.fixtures }); if(devices.length < 2) { throw new Error("Not enough test devices available"); } const TB_DEV1 = devices[0].DEVNAME; const TB_DEV2 = devices[1].DEVNAME; var args = [ "--chip", "esp32", "--baud", "460800", "--before", "default_reset", "--after", "hard_reset", "write_flash", "-z", "--flash_mode", "dio", "--flash_freq", "40m", "--flash_size", "detect", "0x1000", path.join(buildPath, "bootloader/bootloader.bin"), "0x10000", path.join(buildPath, "lora32.bin"), "0x8000", path.join(buildPath, "partitions_singleapp.bin") ]; function flash(port, cb) { console.log("Flashing devices at %s", port); var cp = spawn(exec, ["--port", port].concat(args)); cp.on("exit", function(code) { console.log("%s\nexited: %d", port, code); cb(code === 0 ? null : new Error("exited non-zero: " + code)); }); } function toggleReset(sp) { sp.set({ dtr: false }, function() { setTimeout(function() { sp.set({ dtr: true }); }, 1000); }); } function serial(port, cb) { var to = -1; var buf = ""; var sp = new SerialPort(port, { baudRate: 115200 }); sp.once("open", function() { console.log("port open %s", port); sp.on("data", onData); toggleReset(sp); }); function done(reason) { console.log("%s ready%s", port, reason || ""); cb(null, sp); sp.removeListener("data", onData); } function onData(chunk) { buf += chunk.toString(); clearTimeout(to); to = setTimeout(function() { done(" (timeout)"); }, 3000); if(buf.indexOf("set_spread") !== -1) { clearTimeout(to); done(" (got set_spreadfactor)"); } } } async.series([ function(next) { if(process.env.NOFLASH) { return next(null); } async.parallel([ function(done) { flash(TB_DEV1, done); }, function(done) { flash(TB_DEV2, done); }], next); }, function(next) { async.parallel({ dev1: function(done) { serial(TB_DEV1, done); }, dev2: function(done) { serial(TB_DEV2, done); } }, next); } ], function(err, results) { var ports = results[1]; console.log("init done"); var buf = ""; var message = "test"; test.onFinish(function() { console.log("Cleaning up"); ports.dev1.close(); ports.dev2.close(); }); test(function(t) { t.plan(1); ports.dev1.on("data", function onData(chunk) { //process.stdout.write(chunk); buf += chunk.toString(); if(buf.indexOf(`msg: ${message}`) !== -1) { ports.dev1.removeListener("data", onData); t.pass("got round-trip message!"); } }); ports.dev2.on("data", function(chunk) { //process.stdout.write(chunk); }); ports.dev2.write(`send${message}\n`); }, "round-trip message"); test(function(t) { t.plan(2); var sf = 9; var msg = `sf${sf}\n`; testSetSpreadFactor(ports.dev1); testSetSpreadFactor(ports.dev2); function testSetSpreadFactor(port) { var buf = ""; port.on("data", function onData(c) { buf += c.toString(); if(buf.indexOf(`spreadfactor: ${sf}`) !== -1) { t.pass("spreadfactor set"); port.removeListener("data", onData); } }); port.write(msg); }; }, "set spreadfactor"); test(function(t) { t.plan(4); var i = 0; async.doWhilst(function(done) { var write = ports["dev" + (1 + i % 2)]; var read = ports["dev" + (1 + (i + 1) % 2)]; var buf = ""; var msg = `tick${i}`; read.on("data", onData); write.write(`send${msg}\n`); function onData(c) { buf += c.toString(); if(buf.indexOf(msg) !== -1) { t.pass((i % 2 === 0 ? ">" : "<") + " got message " + i); read.removeListener("data", onData); done(null); } } }, function() { return i++ < 3; }) }, "exchange"); test(function(t) { t.plan(2); var cr = 7; var msg = `cr${cr}\n`; testSetCodingRate(ports.dev1); testSetCodingRate(ports.dev2); function testSetCodingRate(port) { var buf = ""; port.on("data", function onData(c) { buf += c.toString(); if(buf.indexOf(`coding rate: ${cr}`) !== -1) { t.pass("coding factor set"); port.removeListener("data", onData); } }); port.write(msg); }; }, "set coding rate"); test(function(t) { t.plan(1); ports.dev1.on("data", function onData(chunk) { //process.stdout.write(chunk); buf += chunk.toString(); if(buf.indexOf(`msg: ${message}`) !== -1) { ports.dev1.removeListener("data", onData); t.pass("got round-trip message!"); } }); ports.dev2.on("data", function(chunk) { //process.stdout.write(chunk); }); ports.dev2.write(`send${message}\n`); }, "round-trip message"); });