Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Script to test simulate hardware beacons #26

Merged
merged 12 commits into from
Nov 10, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions hw_sim/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules/
34 changes: 34 additions & 0 deletions hw_sim/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Hardware simulation script

## Requirements
Any versions of the below should work, but when in doubt, take the latest one

- `npm`
- `node`

## Setup

`npm install`

## Run

- First make sure an instance of telraam is running (see below how to specify the telraam address and port)

- Then run: `node main.js`

## Arguments

- `-h`: Show all the help messages.
- `-p`: What port to connect to (default: `4564`)
- `-a`: What address to connect to (default: `127.0.0.1`).
- `-r`: The amount of runners to spawn.
- `-b`: The amount of beacons to spawn.
- `-m`: The average time per round
- `-d`: Standard deviation for the average runner speed.
- `-D`: Standard deviation of round speed, global for all runners.
- `--miss-rate`: Missrate of runner detection.

### Todo: added bonusses

- Malformed message rate. We need closing and starting tags to properly detect this. So server code and code here. Look at the class `telraam.beacon.BeaconMessage`.
- Messages per beacon or something, because irl the beacons are probably gonna send more than 1 message for a runner passing by.
116 changes: 116 additions & 0 deletions hw_sim/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
'use strict';

const ArgumentParser = require('argparse').ArgumentParser;
const net = require('net');

var args;

// Standard Normal variate using Box-Muller transform.
function randn_bm(mean, dev) {
var u = 0,
v = 0;
while (u === 0) u = Math.random(); //Converting [0,1) to (0,1)
while (v === 0) v = Math.random();
const out = Math.sqrt(-2.0 * Math.log(u)) * Math.cos(2.0 * Math.PI * v);
return out * dev + mean;
}

class Beacon {
constructor(id) {
this.socket = net.Socket();
this.socket.connect(args.port, args.address);
this.id = id;
}

send(id) {
console.log("Beacon", id, "Runner", this.id);

// This is so ugly
const start_tag = [60, 60, 60, 60];
const end_tag = [62, 62, 62, 62];
const actual_message_size = 10;

const buffer = Buffer.alloc(actual_message_size + start_tag.length + end_tag.length);

let offset = 0;
for (let tag of start_tag) {
buffer.writeInt8(tag, offset);
offset += 1; // '<'
}

buffer.writeInt8(this.id, offset);
offset += 1;
buffer.writeInt8(id, offset);
offset += 1;

buffer.writeBigInt64LE(BigInt(Date.now()), offset);
offset += 8;

for (let tag of end_tag) {
buffer.writeInt8(tag, offset);
offset += 1; // '<'
}
this.socket.write(buffer);
}
}

class Runner {
constructor(id, mean, beacons) {
this.mean = mean;
this.dev = args.round_deviation;
this.beacons = beacons;
this.at = 0;
this.id = id;

this.run = this.send.bind(this);

this.set_next();
}

send() {
if (Math.random() >= args.miss_rate) {
this.beacons[this.at].send(this.id);
}

this.at++;

if (this.at >= this.beacons.length) {
this.at = 0;
}

this.set_next();
}

set_next() {
const time_till_next = randn_bm(this.mean, this.dev);
setTimeout(this.run, time_till_next);
}
}

function main() {
const parser = new ArgumentParser({
addHelp: true,
description: 'Hardware simulation script for Telraam'
});

parser.addArgument(['-p', "--port"], { defaultValue: 4564, type: "int", help: "Port to use" });
parser.addArgument(['-a', "--address"], { defaultValue: "127.0.0.1", help: "Ip address to test" });
parser.addArgument(['-b', "--beacons"], { defaultValue: 2, type: "int", help: "Amount of beacons" });
parser.addArgument(['-r', "--runners"], { defaultValue: 5, type: "int", help: "Amount of runners" });
parser.addArgument(['-m', "--mean"], { defaultValue: 500, type: "int", help: "Mean of runner speed (ms per round)" });
parser.addArgument(['-d', "--runner-deviation"], { defaultValue: 10, type: "int", help: "Standard deviation of runner speed (per runner)" });
parser.addArgument(['-D', "--round-deviation"], { defaultValue: 0, type: "int", help: "Standard deviation of runner speed (per round)" });
parser.addArgument(['--miss-rate'], { defaultValue: 0, type: "float", help: "Missrate of runner detection." });
args = parser.parseArgs();

const beacons = [];
for (let i = 0; i < args.beacons; i++) {
beacons.push(new Beacon(i + 1));
}

const runners = [];
for (let i = 0; i < args.runners; i++) {
runners.push(new Runner(i + 1, randn_bm(args.mean, args.runner_deviation), beacons));
}
}
main();
23 changes: 23 additions & 0 deletions hw_sim/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions hw_sim/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "hw_sim",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {},
"devDependencies": {
"argparse": "^1.0.10"
}
}
18 changes: 13 additions & 5 deletions src/main/java/telraam/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,33 @@
import io.dropwizard.jdbi3.bundles.JdbiExceptionsBundle;
import io.dropwizard.setup.Bootstrap;
import io.dropwizard.setup.Environment;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import org.jdbi.v3.core.Jdbi;
import telraam.api.BatonResource;
import telraam.api.HelloworldResource;
import telraam.beacon.BeaconAggregator;
import telraam.database.daos.BatonDAO;
import telraam.database.models.Baton;
import telraam.database.models.Id;
import telraam.healthchecks.TemplateHealthCheck;

import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;



public class App extends Application<AppConfiguration> {
private static Logger logger = Logger.getLogger(App.class.getName());

public static void main(String[] args) throws Exception {
new App().run(args);
BeaconAggregator ba = new BeaconAggregator(4564);
ba.onError((e) -> {logger.warning(e.getMessage()); return null;});
ba.onData((e) -> {logger.info(e.toString()); return null;});
ba.onConnect((_e) -> {logger.info("Connect"); return null;});
ba.onDisconnect((_e) -> {logger.info("Disconnected"); return null;});
// new App().run(args);
ba.run();
}

@Override
Expand Down
99 changes: 81 additions & 18 deletions src/main/java/telraam/beacon/Beacon.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,27 @@

import java.io.IOException;
import java.io.InputStream;
import java.io.BufferedInputStream;
import java.io.EOFException;
import java.net.Socket;
import java.nio.Buffer;
import java.util.List;
import java.util.ArrayList;

/**
* Beacon is socket wrapper that listens to the sockets
* and emits BeaconMessages when enough bytes are read.
*
* Beacons are closed at the first Exception encountered.
* This could be changed if need be.
*
* @author Arthur Vercruysse
*/
* Beacon is socket wrapper that listens to the sockets and emits BeaconMessages
* when enough bytes are read.
*
* Beacons are closed at the first Exception encountered. This could be changed
* if need be.
*
* @author Arthur Vercruysse
*/
public class Beacon extends EventGenerator<BeaconMessage> implements Runnable {
private Socket s;
private int messageSize = BeaconMessage.MESSAGESIZE;
private byte[] startTag = BeaconMessage.STARTTAG;
private byte[] endTag = BeaconMessage.ENDTAG;

public Beacon(Socket socket, Callback<Void, Event<BeaconMessage>> h) {
super(h);
Expand All @@ -29,25 +35,82 @@ public Beacon(Socket socket, Callback<Void, Event<BeaconMessage>> h) {
public void run() {
this.connect();

byte[] buf = new byte[messageSize];
int at = 0;
InputStream is;
boolean readingMsg = false;

List<Byte> msgBuf = new ArrayList<>(messageSize);
int sTagIndex = 0;
int eTagIndex = 0;
byte[] buf = new byte[1024];

BufferedInputStream is;

try {
is = s.getInputStream();
is = new BufferedInputStream(s.getInputStream());
} catch (IOException e) {
error(e);
return;
}

try {
while (true) {
int c = is.read(buf, at, messageSize - at);
if (c < 0) throw new EOFException();
at += c;
if (at == messageSize) {
this.data(new BeaconMessage(buf));
at = 0;
int c = is.read(buf);
if (c < 0)
throw new EOFException();

for (int i = 0; i < c; i++) {
byte b = buf[i];
msgBuf.add(b);

if (b == startTag[sTagIndex]) {
sTagIndex++;

// A complete start tag is found
// Delete current msgBuf content and start over
if (sTagIndex == startTag.length) {
sTagIndex = 0;

if (readingMsg) {
// TODO: Maybe we want to reset msgBuf idk
this.error(new BeaconException.MsgStartWithNoEnd());
} else {
msgBuf.clear();
readingMsg = true;
}
}
} else {
sTagIndex = 0;
}

if (b == endTag[eTagIndex]) {
eTagIndex++;

// A complete end tag is found
// Flush the msgBuffer
if (eTagIndex == endTag.length) {
eTagIndex = 0;

if (readingMsg) {

// Remove end tag from message
for (int k = 0; k < endTag.length; k++) {
msgBuf.remove(msgBuf.size() - 1);
}

// Catch errors thrown at message decoding and propagate
try {
this.data(new BeaconMessage(msgBuf));
} catch (Exception e) {
this.error(e);
}

readingMsg = false;
} else {
this.error(new BeaconException.MsgEndWithNoStart());
}
}
} else {
eTagIndex = 0;
}
}
}
} catch (IOException e) {
Expand Down
19 changes: 19 additions & 0 deletions src/main/java/telraam/beacon/BeaconException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package telraam.beacon;

public class BeaconException extends Exception {
protected BeaconException(String reason) {
super(reason);
}

public static class MsgEndWithNoStart extends BeaconException {
public MsgEndWithNoStart() {
super("Message end tag detected without a start tag");
}
}

public static class MsgStartWithNoEnd extends BeaconException {
public MsgStartWithNoEnd() {
super("2 message start tags detected.");
}
}
}
Loading