Browse Source

feat: merge emitter & receiver

bdestombes 3 years ago
parent
commit
508d947989

emitter/.editorconfig → .editorconfig


emitter/.gitattributes → .gitattributes


emitter/.gitignore → .gitignore


receiver/backend/osc-parser.js → backend/osc-parser.js


+ 74 - 21
emitter/backend/server.js

@@ -1,11 +1,74 @@
 const express = require('express');
+const dgram = require('dgram');
+const oscParser = require('./osc-parser');
+const bodyParser = require('body-parser');
 const { Bundle, Client } = require('node-osc');
 const path = require('path');
 
-const bodyParser = require('body-parser');
 const app = express();
 
-const oscClient = new Client('127.0.0.1', 3333);
+app.use(bodyParser.json());
+app.use(bodyParser.urlencoded({extended:true}));
+app.use(express.static('./frontend/assets'));
+
+app.get('/', function (req, res) {
+	res.sendFile('./frontend/index.html', {
+		root: path.resolve(__dirname + '/..')
+	});
+});
+
+const httpServer = require('http').Server(app);
+
+/* --------
+ * RECEIVER
+ * --------
+ */
+
+const receiverIo = require('socket.io')(httpServer, {
+	transports: ['websocket']
+});
+
+const onSocketListening = function() {
+	const address = receiverUdpSocket.address();
+	console.log('Serveur TUIO en écoute sur : ' + address.address + ':' + address.port);
+};
+
+const onSocketConnection = function(socket) {
+	receiverUdpSocket.on('message', function(msg) {
+		socket.emit('osc', oscParser.decode(msg));
+	});
+};
+
+const receiverUdpSocket = dgram.createSocket('udp4');
+receiverUdpSocket.on('listening', onSocketListening);
+receiverUdpSocket.bind(3333, '127.0.0.1');
+
+app.get('/receiver/json', function (req, res) {
+	res.status(200).send();
+});
+
+receiverIo.sockets.on('connection', (socket) =>{
+	console.log(`Connecté au client ${socket.id}`);
+	const dgramCallback = function (buf) {
+		// console.log(oscParser.decode(buf));
+		socket.emit('osc', oscParser.decode(buf));
+	};
+
+	// forward UDP packets via socket.io
+	receiverUdpSocket.on('message', dgramCallback);
+
+	// prevent memory leak on disconnect
+	socket.on('disconnect', function (socket) {
+		receiverUdpSocket.removeListener('message', dgramCallback);
+	});
+});
+
+/* -------
+ * EMITTER
+ * -------
+ */
+
+const emitterOscClient = new Client('127.0.0.1', 3333);
 let alive = [];
 let fseq;
 
@@ -88,19 +151,7 @@ function getOrientation(dotTrio, topIndex) {
 	 //return length ;
 }
 
-const server = require('http').Server(app);
-
-app.use(bodyParser.json());
-app.use(bodyParser.urlencoded({extended:true}));
-app.use(express.static('./frontend/assets'));
-
-app.get('/', function (req, res) {
-	res.sendFile('./frontend/index.html', {
-		root: path.resolve(__dirname + '/..')
-	})
-});
-
-app.post('/json', function (req, res) {
+app.post('/emitter/json', function (req, res) {
 	if (req.body.debug) {
 		//console.log(req.body);
 	}
@@ -119,7 +170,7 @@ app.post('/json', function (req, res) {
 				req.body.changedTouches[0].identifier
 			]
 		);
-		oscClient.send(oscBundle, () => {
+		emitterOscClient.send(oscBundle, () => {
 			const index = alive.indexOf(req.body.changedTouches[0].identifier);
 			alive.splice(index, 1);
 			if (alive.length === 0) {
@@ -128,7 +179,7 @@ app.post('/json', function (req, res) {
 					[ '/tuio/2Dcur', 'alive' ],
 					[ '/tuio/2Dcur', 'fseq', fseq ]
 				);
-				oscClient.send(oscBundle, () => {
+				emitterOscClient.send(oscBundle, () => {
 					res.status(200).send();
 					fseq = 0;
 				});
@@ -318,7 +369,7 @@ app.post('/json', function (req, res) {
 			// 	// 	// 	);
 			// 	// 	// });
 			// 	console.log(oscBundleObj);
-			// 	oscClient.send(oscBundleObj, () => {
+			// 	emitterOscClient.send(oscBundleObj, () => {
 			// 		res.status(200).send();
 			// 	});
 			// }
@@ -361,7 +412,7 @@ app.post('/json', function (req, res) {
 					]);
 				}
 				oscBundle.append([ '/tuio/2Dobj', 'fseq', fseq ]);
-				oscClient.send(oscBundle, () => {
+				emitterOscClient.send(oscBundle, () => {
 					res.status(200).send();
 				});
 			} else {
@@ -370,6 +421,8 @@ app.post('/json', function (req, res) {
 	}
 });
 
-server.listen(5001, function () {
- console.log('Votre app est disponible sur localhost:5001 !')
+
+
+httpServer.listen(5000, function () {
+ console.log('Votre app est disponible sur localhost:5000 !')
 });

+ 0 - 926
emitter/package-lock.json

@@ -1,926 +0,0 @@
-{
-  "name": "http-keep-alive",
-  "version": "0.1.0",
-  "lockfileVersion": 2,
-  "requires": true,
-  "packages": {
-    "": {
-      "name": "http-keep-alive",
-      "version": "0.1.0",
-      "license": "MIT",
-      "dependencies": {
-        "body-parser": "^1.19.0",
-        "express": "^4.17.1",
-        "node-osc": "^6.1.11"
-      }
-    },
-    "node_modules/accepts": {
-      "version": "1.3.7",
-      "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
-      "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
-      "dependencies": {
-        "mime-types": "~2.1.24",
-        "negotiator": "0.6.2"
-      },
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/array-flatten": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
-      "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
-    },
-    "node_modules/binpack": {
-      "version": "0.1.0",
-      "resolved": "https://registry.npmjs.org/binpack/-/binpack-0.1.0.tgz",
-      "integrity": "sha1-vT0JdMPyoERuF99PYLVacqIFqX4="
-    },
-    "node_modules/body-parser": {
-      "version": "1.19.1",
-      "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.1.tgz",
-      "integrity": "sha512-8ljfQi5eBk8EJfECMrgqNGWPEY5jWP+1IzkzkGdFFEwFQZZyaZ21UqdaHktgiMlH0xLHqIFtE/u2OYE5dOtViA==",
-      "dependencies": {
-        "bytes": "3.1.1",
-        "content-type": "~1.0.4",
-        "debug": "2.6.9",
-        "depd": "~1.1.2",
-        "http-errors": "1.8.1",
-        "iconv-lite": "0.4.24",
-        "on-finished": "~2.3.0",
-        "qs": "6.9.6",
-        "raw-body": "2.4.2",
-        "type-is": "~1.6.18"
-      },
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/bytes": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.1.tgz",
-      "integrity": "sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg==",
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/content-disposition": {
-      "version": "0.5.4",
-      "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
-      "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
-      "dependencies": {
-        "safe-buffer": "5.2.1"
-      },
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/content-type": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
-      "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/cookie": {
-      "version": "0.4.1",
-      "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz",
-      "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==",
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/cookie-signature": {
-      "version": "1.0.6",
-      "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
-      "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
-    },
-    "node_modules/debug": {
-      "version": "2.6.9",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-      "dependencies": {
-        "ms": "2.0.0"
-      }
-    },
-    "node_modules/depd": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
-      "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/destroy": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
-      "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
-    },
-    "node_modules/ee-first": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
-      "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
-    },
-    "node_modules/encodeurl": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
-      "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/escape-html": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
-      "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
-    },
-    "node_modules/etag": {
-      "version": "1.8.1",
-      "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
-      "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=",
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/express": {
-      "version": "4.17.2",
-      "resolved": "https://registry.npmjs.org/express/-/express-4.17.2.tgz",
-      "integrity": "sha512-oxlxJxcQlYwqPWKVJJtvQiwHgosH/LrLSPA+H4UxpyvSS6jC5aH+5MoHFM+KABgTOt0APue4w66Ha8jCUo9QGg==",
-      "dependencies": {
-        "accepts": "~1.3.7",
-        "array-flatten": "1.1.1",
-        "body-parser": "1.19.1",
-        "content-disposition": "0.5.4",
-        "content-type": "~1.0.4",
-        "cookie": "0.4.1",
-        "cookie-signature": "1.0.6",
-        "debug": "2.6.9",
-        "depd": "~1.1.2",
-        "encodeurl": "~1.0.2",
-        "escape-html": "~1.0.3",
-        "etag": "~1.8.1",
-        "finalhandler": "~1.1.2",
-        "fresh": "0.5.2",
-        "merge-descriptors": "1.0.1",
-        "methods": "~1.1.2",
-        "on-finished": "~2.3.0",
-        "parseurl": "~1.3.3",
-        "path-to-regexp": "0.1.7",
-        "proxy-addr": "~2.0.7",
-        "qs": "6.9.6",
-        "range-parser": "~1.2.1",
-        "safe-buffer": "5.2.1",
-        "send": "0.17.2",
-        "serve-static": "1.14.2",
-        "setprototypeof": "1.2.0",
-        "statuses": "~1.5.0",
-        "type-is": "~1.6.18",
-        "utils-merge": "1.0.1",
-        "vary": "~1.1.2"
-      },
-      "engines": {
-        "node": ">= 0.10.0"
-      }
-    },
-    "node_modules/finalhandler": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
-      "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
-      "dependencies": {
-        "debug": "2.6.9",
-        "encodeurl": "~1.0.2",
-        "escape-html": "~1.0.3",
-        "on-finished": "~2.3.0",
-        "parseurl": "~1.3.3",
-        "statuses": "~1.5.0",
-        "unpipe": "~1.0.0"
-      },
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/forwarded": {
-      "version": "0.2.0",
-      "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
-      "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/fresh": {
-      "version": "0.5.2",
-      "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
-      "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=",
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/http-errors": {
-      "version": "1.8.1",
-      "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz",
-      "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==",
-      "dependencies": {
-        "depd": "~1.1.2",
-        "inherits": "2.0.4",
-        "setprototypeof": "1.2.0",
-        "statuses": ">= 1.5.0 < 2",
-        "toidentifier": "1.0.1"
-      },
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/iconv-lite": {
-      "version": "0.4.24",
-      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
-      "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
-      "dependencies": {
-        "safer-buffer": ">= 2.1.2 < 3"
-      },
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/inherits": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
-      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
-    },
-    "node_modules/ipaddr.js": {
-      "version": "1.9.1",
-      "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
-      "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
-      "engines": {
-        "node": ">= 0.10"
-      }
-    },
-    "node_modules/media-typer": {
-      "version": "0.3.0",
-      "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
-      "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=",
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/merge-descriptors": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
-      "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
-    },
-    "node_modules/methods": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
-      "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=",
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/mime": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
-      "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
-      "bin": {
-        "mime": "cli.js"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/mime-db": {
-      "version": "1.51.0",
-      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz",
-      "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==",
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/mime-types": {
-      "version": "2.1.34",
-      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz",
-      "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==",
-      "dependencies": {
-        "mime-db": "1.51.0"
-      },
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/ms": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-      "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
-    },
-    "node_modules/negotiator": {
-      "version": "0.6.2",
-      "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
-      "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==",
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/node-osc": {
-      "version": "6.1.11",
-      "resolved": "https://registry.npmjs.org/node-osc/-/node-osc-6.1.11.tgz",
-      "integrity": "sha512-bwFV/UKBBaSNK5pLYeA8Qx0GVc49fKRjmfMwMoypfPwb7RdhyRccW+tTNHcwr/OJ2b01uVKpnTPurSNs4fWnvw==",
-      "dependencies": {
-        "osc-min": "^1.1.1"
-      },
-      "engines": {
-        "node": "^12.22 || ^14.13 || >=16"
-      }
-    },
-    "node_modules/on-finished": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
-      "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
-      "dependencies": {
-        "ee-first": "1.1.1"
-      },
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/osc-min": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/osc-min/-/osc-min-1.1.2.tgz",
-      "integrity": "sha512-8DbiO8ME85R75stgNVCZtHxB9MNBBNcyy+isNBXrsFeinXGjwNAauvKVmGlfRas5VJWC/mhzIx7spR2gFvWxvg==",
-      "dependencies": {
-        "binpack": "~0"
-      },
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/parseurl": {
-      "version": "1.3.3",
-      "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
-      "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/path-to-regexp": {
-      "version": "0.1.7",
-      "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
-      "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
-    },
-    "node_modules/proxy-addr": {
-      "version": "2.0.7",
-      "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
-      "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
-      "dependencies": {
-        "forwarded": "0.2.0",
-        "ipaddr.js": "1.9.1"
-      },
-      "engines": {
-        "node": ">= 0.10"
-      }
-    },
-    "node_modules/qs": {
-      "version": "6.9.6",
-      "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz",
-      "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==",
-      "engines": {
-        "node": ">=0.6"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/range-parser": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
-      "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/raw-body": {
-      "version": "2.4.2",
-      "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.2.tgz",
-      "integrity": "sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ==",
-      "dependencies": {
-        "bytes": "3.1.1",
-        "http-errors": "1.8.1",
-        "iconv-lite": "0.4.24",
-        "unpipe": "1.0.0"
-      },
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/safe-buffer": {
-      "version": "5.2.1",
-      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
-      "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/feross"
-        },
-        {
-          "type": "patreon",
-          "url": "https://www.patreon.com/feross"
-        },
-        {
-          "type": "consulting",
-          "url": "https://feross.org/support"
-        }
-      ]
-    },
-    "node_modules/safer-buffer": {
-      "version": "2.1.2",
-      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
-      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
-    },
-    "node_modules/send": {
-      "version": "0.17.2",
-      "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz",
-      "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==",
-      "dependencies": {
-        "debug": "2.6.9",
-        "depd": "~1.1.2",
-        "destroy": "~1.0.4",
-        "encodeurl": "~1.0.2",
-        "escape-html": "~1.0.3",
-        "etag": "~1.8.1",
-        "fresh": "0.5.2",
-        "http-errors": "1.8.1",
-        "mime": "1.6.0",
-        "ms": "2.1.3",
-        "on-finished": "~2.3.0",
-        "range-parser": "~1.2.1",
-        "statuses": "~1.5.0"
-      },
-      "engines": {
-        "node": ">= 0.8.0"
-      }
-    },
-    "node_modules/send/node_modules/ms": {
-      "version": "2.1.3",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
-      "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
-    },
-    "node_modules/serve-static": {
-      "version": "1.14.2",
-      "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz",
-      "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==",
-      "dependencies": {
-        "encodeurl": "~1.0.2",
-        "escape-html": "~1.0.3",
-        "parseurl": "~1.3.3",
-        "send": "0.17.2"
-      },
-      "engines": {
-        "node": ">= 0.8.0"
-      }
-    },
-    "node_modules/setprototypeof": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
-      "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
-    },
-    "node_modules/statuses": {
-      "version": "1.5.0",
-      "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
-      "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=",
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/toidentifier": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
-      "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
-      "engines": {
-        "node": ">=0.6"
-      }
-    },
-    "node_modules/type-is": {
-      "version": "1.6.18",
-      "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
-      "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
-      "dependencies": {
-        "media-typer": "0.3.0",
-        "mime-types": "~2.1.24"
-      },
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/unpipe": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
-      "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=",
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/utils-merge": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
-      "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=",
-      "engines": {
-        "node": ">= 0.4.0"
-      }
-    },
-    "node_modules/vary": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
-      "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=",
-      "engines": {
-        "node": ">= 0.8"
-      }
-    }
-  },
-  "dependencies": {
-    "accepts": {
-      "version": "1.3.7",
-      "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
-      "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
-      "requires": {
-        "mime-types": "~2.1.24",
-        "negotiator": "0.6.2"
-      }
-    },
-    "array-flatten": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
-      "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
-    },
-    "binpack": {
-      "version": "0.1.0",
-      "resolved": "https://registry.npmjs.org/binpack/-/binpack-0.1.0.tgz",
-      "integrity": "sha1-vT0JdMPyoERuF99PYLVacqIFqX4="
-    },
-    "body-parser": {
-      "version": "1.19.1",
-      "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.1.tgz",
-      "integrity": "sha512-8ljfQi5eBk8EJfECMrgqNGWPEY5jWP+1IzkzkGdFFEwFQZZyaZ21UqdaHktgiMlH0xLHqIFtE/u2OYE5dOtViA==",
-      "requires": {
-        "bytes": "3.1.1",
-        "content-type": "~1.0.4",
-        "debug": "2.6.9",
-        "depd": "~1.1.2",
-        "http-errors": "1.8.1",
-        "iconv-lite": "0.4.24",
-        "on-finished": "~2.3.0",
-        "qs": "6.9.6",
-        "raw-body": "2.4.2",
-        "type-is": "~1.6.18"
-      }
-    },
-    "bytes": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.1.tgz",
-      "integrity": "sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg=="
-    },
-    "content-disposition": {
-      "version": "0.5.4",
-      "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
-      "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
-      "requires": {
-        "safe-buffer": "5.2.1"
-      }
-    },
-    "content-type": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
-      "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
-    },
-    "cookie": {
-      "version": "0.4.1",
-      "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz",
-      "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA=="
-    },
-    "cookie-signature": {
-      "version": "1.0.6",
-      "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
-      "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
-    },
-    "debug": {
-      "version": "2.6.9",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-      "requires": {
-        "ms": "2.0.0"
-      }
-    },
-    "depd": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
-      "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
-    },
-    "destroy": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
-      "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
-    },
-    "ee-first": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
-      "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
-    },
-    "encodeurl": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
-      "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
-    },
-    "escape-html": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
-      "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
-    },
-    "etag": {
-      "version": "1.8.1",
-      "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
-      "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
-    },
-    "express": {
-      "version": "4.17.2",
-      "resolved": "https://registry.npmjs.org/express/-/express-4.17.2.tgz",
-      "integrity": "sha512-oxlxJxcQlYwqPWKVJJtvQiwHgosH/LrLSPA+H4UxpyvSS6jC5aH+5MoHFM+KABgTOt0APue4w66Ha8jCUo9QGg==",
-      "requires": {
-        "accepts": "~1.3.7",
-        "array-flatten": "1.1.1",
-        "body-parser": "1.19.1",
-        "content-disposition": "0.5.4",
-        "content-type": "~1.0.4",
-        "cookie": "0.4.1",
-        "cookie-signature": "1.0.6",
-        "debug": "2.6.9",
-        "depd": "~1.1.2",
-        "encodeurl": "~1.0.2",
-        "escape-html": "~1.0.3",
-        "etag": "~1.8.1",
-        "finalhandler": "~1.1.2",
-        "fresh": "0.5.2",
-        "merge-descriptors": "1.0.1",
-        "methods": "~1.1.2",
-        "on-finished": "~2.3.0",
-        "parseurl": "~1.3.3",
-        "path-to-regexp": "0.1.7",
-        "proxy-addr": "~2.0.7",
-        "qs": "6.9.6",
-        "range-parser": "~1.2.1",
-        "safe-buffer": "5.2.1",
-        "send": "0.17.2",
-        "serve-static": "1.14.2",
-        "setprototypeof": "1.2.0",
-        "statuses": "~1.5.0",
-        "type-is": "~1.6.18",
-        "utils-merge": "1.0.1",
-        "vary": "~1.1.2"
-      }
-    },
-    "finalhandler": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
-      "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
-      "requires": {
-        "debug": "2.6.9",
-        "encodeurl": "~1.0.2",
-        "escape-html": "~1.0.3",
-        "on-finished": "~2.3.0",
-        "parseurl": "~1.3.3",
-        "statuses": "~1.5.0",
-        "unpipe": "~1.0.0"
-      }
-    },
-    "forwarded": {
-      "version": "0.2.0",
-      "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
-      "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="
-    },
-    "fresh": {
-      "version": "0.5.2",
-      "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
-      "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
-    },
-    "http-errors": {
-      "version": "1.8.1",
-      "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz",
-      "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==",
-      "requires": {
-        "depd": "~1.1.2",
-        "inherits": "2.0.4",
-        "setprototypeof": "1.2.0",
-        "statuses": ">= 1.5.0 < 2",
-        "toidentifier": "1.0.1"
-      }
-    },
-    "iconv-lite": {
-      "version": "0.4.24",
-      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
-      "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
-      "requires": {
-        "safer-buffer": ">= 2.1.2 < 3"
-      }
-    },
-    "inherits": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
-      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
-    },
-    "ipaddr.js": {
-      "version": "1.9.1",
-      "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
-      "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
-    },
-    "media-typer": {
-      "version": "0.3.0",
-      "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
-      "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
-    },
-    "merge-descriptors": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
-      "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
-    },
-    "methods": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
-      "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
-    },
-    "mime": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
-      "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
-    },
-    "mime-db": {
-      "version": "1.51.0",
-      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz",
-      "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g=="
-    },
-    "mime-types": {
-      "version": "2.1.34",
-      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz",
-      "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==",
-      "requires": {
-        "mime-db": "1.51.0"
-      }
-    },
-    "ms": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-      "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
-    },
-    "negotiator": {
-      "version": "0.6.2",
-      "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
-      "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
-    },
-    "node-osc": {
-      "version": "6.1.11",
-      "resolved": "https://registry.npmjs.org/node-osc/-/node-osc-6.1.11.tgz",
-      "integrity": "sha512-bwFV/UKBBaSNK5pLYeA8Qx0GVc49fKRjmfMwMoypfPwb7RdhyRccW+tTNHcwr/OJ2b01uVKpnTPurSNs4fWnvw==",
-      "requires": {
-        "osc-min": "^1.1.1"
-      }
-    },
-    "on-finished": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
-      "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
-      "requires": {
-        "ee-first": "1.1.1"
-      }
-    },
-    "osc-min": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/osc-min/-/osc-min-1.1.2.tgz",
-      "integrity": "sha512-8DbiO8ME85R75stgNVCZtHxB9MNBBNcyy+isNBXrsFeinXGjwNAauvKVmGlfRas5VJWC/mhzIx7spR2gFvWxvg==",
-      "requires": {
-        "binpack": "~0"
-      }
-    },
-    "parseurl": {
-      "version": "1.3.3",
-      "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
-      "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
-    },
-    "path-to-regexp": {
-      "version": "0.1.7",
-      "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
-      "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
-    },
-    "proxy-addr": {
-      "version": "2.0.7",
-      "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
-      "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
-      "requires": {
-        "forwarded": "0.2.0",
-        "ipaddr.js": "1.9.1"
-      }
-    },
-    "qs": {
-      "version": "6.9.6",
-      "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz",
-      "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ=="
-    },
-    "range-parser": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
-      "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
-    },
-    "raw-body": {
-      "version": "2.4.2",
-      "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.2.tgz",
-      "integrity": "sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ==",
-      "requires": {
-        "bytes": "3.1.1",
-        "http-errors": "1.8.1",
-        "iconv-lite": "0.4.24",
-        "unpipe": "1.0.0"
-      }
-    },
-    "safe-buffer": {
-      "version": "5.2.1",
-      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
-      "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
-    },
-    "safer-buffer": {
-      "version": "2.1.2",
-      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
-      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
-    },
-    "send": {
-      "version": "0.17.2",
-      "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz",
-      "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==",
-      "requires": {
-        "debug": "2.6.9",
-        "depd": "~1.1.2",
-        "destroy": "~1.0.4",
-        "encodeurl": "~1.0.2",
-        "escape-html": "~1.0.3",
-        "etag": "~1.8.1",
-        "fresh": "0.5.2",
-        "http-errors": "1.8.1",
-        "mime": "1.6.0",
-        "ms": "2.1.3",
-        "on-finished": "~2.3.0",
-        "range-parser": "~1.2.1",
-        "statuses": "~1.5.0"
-      },
-      "dependencies": {
-        "ms": {
-          "version": "2.1.3",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
-          "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
-        }
-      }
-    },
-    "serve-static": {
-      "version": "1.14.2",
-      "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz",
-      "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==",
-      "requires": {
-        "encodeurl": "~1.0.2",
-        "escape-html": "~1.0.3",
-        "parseurl": "~1.3.3",
-        "send": "0.17.2"
-      }
-    },
-    "setprototypeof": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
-      "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
-    },
-    "statuses": {
-      "version": "1.5.0",
-      "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
-      "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
-    },
-    "toidentifier": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
-      "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="
-    },
-    "type-is": {
-      "version": "1.6.18",
-      "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
-      "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
-      "requires": {
-        "media-typer": "0.3.0",
-        "mime-types": "~2.1.24"
-      }
-    },
-    "unpipe": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
-      "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
-    },
-    "utils-merge": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
-      "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
-    },
-    "vary": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
-      "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
-    }
-  }
-}

+ 0 - 53
emitter/readme.md

@@ -1,53 +0,0 @@
-# objets tangibles - emitter
-
-> Application basée sur Node.js et Express 4 qui envoie des datagrammes TUIO en fonction des touch-events récupérés sur une page web
-
-## Description
-
-Le projet fourni est composé de 2 parties:
-* un backend
-* un frontend
-
-Le backend est une application Node.js basée sur Express; il officie comme émetteur de données TUIO qui sont récupérées à chaque touch-event.
-
-Le frontend est une page web, servie par le backend, qui envoie les touch-events au backend via requête HTTP.
-
-Chaque partie est contenue dans le dossier correspondant.
-
-
-## Pré-requis
-
-* Installer Node.js (v16 ou v17)
-* Installer les dépendances:
-
-```sh
-cd receiver
-npm install
-```
-
-
-## Lancer le serveur
-
-Dans le dossier du projet, lancer la commande suivante:
-
-```sh
-node ./backend/server.js
-```
-
-* La page du frontend sera accessible à l'adresse http://localhost:5001
-* Le serveur envoie les messages TUIO sur le port UDP 3333.
-
-
-## Gestion de la "section" d'identifiants de points
-
-Utiliser le paramètre d'URL `section` pour déterminer le modulo qui sera appliqué aux identifiants de points, par exemple: http://localhost:5001?section=100
-
-Valeurs possibles: 100, 200, 300
-
-
-## Gestion du mode "debug" sur le frontend
-
-Ajouter le paramètre "debug" avec comme valeur 1 à l'URL: http://localhost:5001?debug=1 ou http://localhost:5001?section=100&debug=1
-
-Le mode debug affiche les messages de debuggage dans la console du navigateur.
-

emitter/frontend/assets/favicon.ico → frontend/assets/favicon.ico


emitter/frontend/assets/jquery-1.7.2.js → frontend/assets/jquery-1.7.2.js


receiver/frontend/assets/lodash.js → frontend/assets/lodash.js


receiver/frontend/assets/socket.io/socket.io.js → frontend/assets/socket.io/socket.io.js


receiver/frontend/assets/tuio.js → frontend/assets/tuio.js


+ 132 - 35
emitter/frontend/index.html

@@ -3,44 +3,43 @@
 	<head>
 		<meta charset="utf-8">
 		<meta name="viewport" content="width=device-width">
-		<title>Touch detect and send to Node server</title>
+		<title>ASR tangibles</title>
+
+		<style>
+			body {
+				margin: 0;
+			}
+			.tuioCursor {
+				background: #111;
+				height: 8px;
+				left: 0;
+				position: absolute;
+				top: 0;
+				width: 8px;
+			}
+			.tuioObj {
+				background: #111;
+				height: 15px;
+				left: 0;
+				position: absolute;
+				top: 0;
+				width: 8px;
+				rotate: 0deg;
+			}
+		</style>
 	</head>
 
 	<body style="height: 100%;">
 		<div id="box" style="width: 100%; height: 100%; background-color: #EEEEEE;"></div>
 		<script src="/jquery-1.7.2.js"></script>
+		<script src="/lodash.js"></script>
+		<script src="/socket.io/socket.io.js"></script>
+		<script src="/tuio.js"></script>
 		<script>
-			/* simulation de touch events */
-			/*
-			function sendTouchEvent(x, y, element, eventType) {
-				const touchObj = new Touch({
-					identifier: Date.now(),
-					target: element,
-					clientX: x,
-					clientY: y,
-					radiusX: 2.5,
-					radiusY: 2.5,
-					rotationAngle: 10,
-					force: 0.5,
-				});
-
-				const touchEvent = new TouchEvent(eventType, {
-					cancelable: true,
-					bubbles: true,
-					touches: [touchObj],
-					targetTouches: [],
-					changedTouches: [touchObj],
-					shiftKey: true,
-				});
-
-				element.dispatchEvent(touchEvent);
-			}
-
-			sendTouchEvent(150, 150, box, 'touchstart');
-			sendTouchEvent(220, 200, box, 'touchmove');
-			sendTouchEvent(220, 200, box, 'touchend');
-			*/
-
+			/* -------
+			 * EMITTER
+			 * -------
+			 */
 			const box = document.getElementById('box');
 
 			const urlParams = new URLSearchParams(window.location.search);
@@ -74,7 +73,7 @@
 						};
 					};
 					box.innerHTML = evt.touches.length;
-					fetch('http://localhost:5001/json', {
+					fetch('http://localhost:5000/emitter/json', {
 						method: 'POST',
 						mode: 'cors',
 						cache: 'no-cache',
@@ -116,7 +115,7 @@
 						};
 					};
 					box.innerHTML = evt.touches.length;
-					fetch('http://localhost:5001/json', {
+					fetch('http://localhost:5000/emitter/json', {
 						method: 'POST',
 						mode: 'cors',
 						cache: 'no-cache',
@@ -159,7 +158,7 @@
 						};
 					};
 					box.innerHTML = evt.touches.length;
-					fetch('http://localhost:5001/json', {
+					fetch('http://localhost:5000/emitter/json', {
 						method: 'POST',
 						mode: 'cors',
 						cache: 'no-cache',
@@ -184,6 +183,104 @@
 			if (!(typeof box.ontouchstart != 'undefined')) {
 					box.style.border = '1px solid red';
 			}
+
+
+			/* --------
+			 * RECEIVER
+			 * --------
+			 */
+
+			$(function() {
+				const urlParams = new URLSearchParams(window.location.search);
+				const debugParams = urlParams.get('debug');
+				const debug = debugParams ? true : false;
+				if (debug) {
+						console.log('--- Debug activated ---');
+				}
+				var dotGroups = [];
+				var client = new Tuio.Client({
+						host: 'http://localhost:5000'
+				}),
+				screenW = $(document).width(),
+				screenH = $(document).height()
+
+				cursors = {},
+				objects = {},
+
+				onConnect = function() {
+					if (debug) {
+						console.log('connected');
+					}
+				},
+
+				onAddTuioCursor = function(addCursor) {
+					var $addCursor = $('<div class="tuioCursor"></div>');
+					$('body').append($addCursor);
+					cursors[addCursor.getCursorId()] = $addCursor;
+					onUpdateTuioCursor(addCursor);
+				},
+
+				onUpdateTuioCursor = function(updateCursor) {
+					var $updateCursor = cursors[updateCursor.getCursorId()];
+					$updateCursor.css({
+						left: updateCursor.getScreenX(screenW),
+						top: updateCursor.getScreenY(screenH)
+					});
+				},
+
+				onRemoveTuioCursor = function(removeCursor) {
+					var $removeCursor = cursors[removeCursor.getCursorId()];
+					$removeCursor.remove();
+					delete[removeCursor.getCursorId()];
+				},
+
+				onAddTuioObject = function(addObject) {
+					var $addObject = $('<div class="tuioObj"></div>');
+					$('body').append($addObject);
+					objects[addObject.symbolID] = $addObject;
+					onUpdateTuioObject(addObject);
+					if (debug) {
+						console.log('addTuioObject', addObject);
+					}
+				},
+
+				onUpdateTuioObject = function(updateObject) {
+					var $updateObject = objects[updateObject.symbolID];
+					$updateObject.css({
+						left: updateObject.getScreenX(screenW),
+						top: updateObject.getScreenY(screenH),
+						rotate : updateObject.getAngleDegrees()
+					});
+					if (debug) {
+						console.log('updateTuioObject', updateObject);
+					}
+				},
+
+				onRemoveTuioObject = function(removeObject) {
+					var $removeObject = objects[removeObject.symbolID];
+					$removeObject.remove();
+					delete[removeObject.symbolID];
+					if (debug) {
+						console.log('removeTuioObject', removeObject);
+					}
+				},
+
+				onRefresh = function(time) {
+					if (debug) {
+						console.log('refresh', time);
+					}
+				};
+
+				client.on('connect', onConnect);
+				client.on('addTuioCursor', onAddTuioCursor);
+				client.on('updateTuioCursor', onUpdateTuioCursor);
+				client.on('removeTuioCursor', onRemoveTuioCursor);
+				client.on('addTuioObject', onAddTuioObject);
+				client.on('updateTuioObject', onUpdateTuioObject);
+				client.on('removeTuioObject', onRemoveTuioObject);
+				client.on('refresh', onRefresh);
+				client.connect();
+			});
 		</script>
 	</body>
 </html>

emitter/license → license


+ 70 - 20
receiver/package-lock.json

@@ -1,17 +1,19 @@
 {
-  "name": "poc-objets-tangibles",
+  "name": "asr-tangibles",
   "version": "0.1.0",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
-      "name": "poc-objets-tangibles",
+      "name": "asr-tangibles",
       "version": "0.1.0",
+      "license": "MIT",
       "dependencies": {
         "body-parser": "^1.19.0",
         "dgram": "^1.0.1",
         "express": "^4.17.1",
         "jspack": "0.0.4",
+        "node-osc": "^6.1.11",
         "socket.io": "^4.3.2"
       }
     },
@@ -31,9 +33,9 @@
       "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw=="
     },
     "node_modules/@types/node": {
-      "version": "17.0.2",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.2.tgz",
-      "integrity": "sha512-JepeIUPFDARgIs0zD/SKPgFsJEAF0X5/qO80llx59gOxFTboS9Amv3S+QfB7lqBId5sFXJ99BN0J6zFRvL9dDA=="
+      "version": "17.0.8",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.8.tgz",
+      "integrity": "sha512-YofkM6fGv4gDJq78g4j0mMuGMkZVxZDgtU0JRdx6FgiJDG+0fY0GKVolOV8WqVmEhLCXkQRjwDdKyPxJp/uucg=="
     },
     "node_modules/accepts": {
       "version": "1.3.7",
@@ -68,6 +70,11 @@
         "node": "^4.5.0 || >= 5.9"
       }
     },
+    "node_modules/binpack": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/binpack/-/binpack-0.1.0.tgz",
+      "integrity": "sha1-vT0JdMPyoERuF99PYLVacqIFqX4="
+    },
     "node_modules/body-parser": {
       "version": "1.19.1",
       "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.1.tgz",
@@ -186,9 +193,9 @@
       }
     },
     "node_modules/engine.io": {
-      "version": "6.1.0",
-      "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.0.tgz",
-      "integrity": "sha512-ErhZOVu2xweCjEfYcTdkCnEYUiZgkAcBBAhW4jbIvNG8SLU3orAqoJCiytZjYF7eTpVmmCrLDjLIEaPlUAs1uw==",
+      "version": "6.1.1",
+      "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.1.tgz",
+      "integrity": "sha512-AyMc20q8JUUdvKd46+thc9o7yCZ6iC6MoBCChG5Z1XmFMpp+2+y/oKvwpZTUJB0KCjxScw1dV9c2h5pjiYBLuQ==",
       "dependencies": {
         "@types/cookie": "^0.4.1",
         "@types/cors": "^2.8.12",
@@ -431,6 +438,17 @@
         "node": ">= 0.6"
       }
     },
+    "node_modules/node-osc": {
+      "version": "6.1.11",
+      "resolved": "https://registry.npmjs.org/node-osc/-/node-osc-6.1.11.tgz",
+      "integrity": "sha512-bwFV/UKBBaSNK5pLYeA8Qx0GVc49fKRjmfMwMoypfPwb7RdhyRccW+tTNHcwr/OJ2b01uVKpnTPurSNs4fWnvw==",
+      "dependencies": {
+        "osc-min": "^1.1.1"
+      },
+      "engines": {
+        "node": "^12.22 || ^14.13 || >=16"
+      }
+    },
     "node_modules/object-assign": {
       "version": "4.1.1",
       "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
@@ -450,6 +468,17 @@
         "node": ">= 0.8"
       }
     },
+    "node_modules/osc-min": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/osc-min/-/osc-min-1.1.2.tgz",
+      "integrity": "sha512-8DbiO8ME85R75stgNVCZtHxB9MNBBNcyy+isNBXrsFeinXGjwNAauvKVmGlfRas5VJWC/mhzIx7spR2gFvWxvg==",
+      "dependencies": {
+        "binpack": "~0"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
     "node_modules/parseurl": {
       "version": "1.3.3",
       "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
@@ -580,9 +609,9 @@
       "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
     },
     "node_modules/socket.io": {
-      "version": "4.4.0",
-      "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.4.0.tgz",
-      "integrity": "sha512-bnpJxswR9ov0Bw6ilhCvO38/1WPtE3eA2dtxi2Iq4/sFebiDJQzgKNYA7AuVVdGW09nrESXd90NbZqtDd9dzRQ==",
+      "version": "4.4.1",
+      "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.4.1.tgz",
+      "integrity": "sha512-s04vrBswdQBUmuWJuuNTmXUVJhP0cVky8bBDhdkf8y0Ptsu7fKU2LuLbts9g+pdmAdyMMn8F/9Mf1/wbtUN0fg==",
       "dependencies": {
         "accepts": "~1.3.4",
         "base64id": "~2.0.0",
@@ -745,9 +774,9 @@
       "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw=="
     },
     "@types/node": {
-      "version": "17.0.2",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.2.tgz",
-      "integrity": "sha512-JepeIUPFDARgIs0zD/SKPgFsJEAF0X5/qO80llx59gOxFTboS9Amv3S+QfB7lqBId5sFXJ99BN0J6zFRvL9dDA=="
+      "version": "17.0.8",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.8.tgz",
+      "integrity": "sha512-YofkM6fGv4gDJq78g4j0mMuGMkZVxZDgtU0JRdx6FgiJDG+0fY0GKVolOV8WqVmEhLCXkQRjwDdKyPxJp/uucg=="
     },
     "accepts": {
       "version": "1.3.7",
@@ -773,6 +802,11 @@
       "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz",
       "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog=="
     },
+    "binpack": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/binpack/-/binpack-0.1.0.tgz",
+      "integrity": "sha1-vT0JdMPyoERuF99PYLVacqIFqX4="
+    },
     "body-parser": {
       "version": "1.19.1",
       "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.1.tgz",
@@ -866,9 +900,9 @@
       "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
     },
     "engine.io": {
-      "version": "6.1.0",
-      "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.0.tgz",
-      "integrity": "sha512-ErhZOVu2xweCjEfYcTdkCnEYUiZgkAcBBAhW4jbIvNG8SLU3orAqoJCiytZjYF7eTpVmmCrLDjLIEaPlUAs1uw==",
+      "version": "6.1.1",
+      "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.1.tgz",
+      "integrity": "sha512-AyMc20q8JUUdvKd46+thc9o7yCZ6iC6MoBCChG5Z1XmFMpp+2+y/oKvwpZTUJB0KCjxScw1dV9c2h5pjiYBLuQ==",
       "requires": {
         "@types/cookie": "^0.4.1",
         "@types/cors": "^2.8.12",
@@ -1054,6 +1088,14 @@
       "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
       "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
     },
+    "node-osc": {
+      "version": "6.1.11",
+      "resolved": "https://registry.npmjs.org/node-osc/-/node-osc-6.1.11.tgz",
+      "integrity": "sha512-bwFV/UKBBaSNK5pLYeA8Qx0GVc49fKRjmfMwMoypfPwb7RdhyRccW+tTNHcwr/OJ2b01uVKpnTPurSNs4fWnvw==",
+      "requires": {
+        "osc-min": "^1.1.1"
+      }
+    },
     "object-assign": {
       "version": "4.1.1",
       "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
@@ -1067,6 +1109,14 @@
         "ee-first": "1.1.1"
       }
     },
+    "osc-min": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/osc-min/-/osc-min-1.1.2.tgz",
+      "integrity": "sha512-8DbiO8ME85R75stgNVCZtHxB9MNBBNcyy+isNBXrsFeinXGjwNAauvKVmGlfRas5VJWC/mhzIx7spR2gFvWxvg==",
+      "requires": {
+        "binpack": "~0"
+      }
+    },
     "parseurl": {
       "version": "1.3.3",
       "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
@@ -1161,9 +1211,9 @@
       "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
     },
     "socket.io": {
-      "version": "4.4.0",
-      "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.4.0.tgz",
-      "integrity": "sha512-bnpJxswR9ov0Bw6ilhCvO38/1WPtE3eA2dtxi2Iq4/sFebiDJQzgKNYA7AuVVdGW09nrESXd90NbZqtDd9dzRQ==",
+      "version": "4.4.1",
+      "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.4.1.tgz",
+      "integrity": "sha512-s04vrBswdQBUmuWJuuNTmXUVJhP0cVky8bBDhdkf8y0Ptsu7fKU2LuLbts9g+pdmAdyMMn8F/9Mf1/wbtUN0fg==",
       "requires": {
         "accepts": "~1.3.4",
         "base64id": "~2.0.0",

+ 5 - 2
emitter/package.json

@@ -1,5 +1,5 @@
 {
-  "name": "http-keep-alive",
+  "name": "asr-tangibles",
   "version": "0.1.0",
   "description": "",
   "main": "index.js",
@@ -10,7 +10,10 @@
   "license": "MIT",
   "dependencies": {
     "body-parser": "^1.19.0",
+    "dgram": "^1.0.1",
     "express": "^4.17.1",
-    "node-osc": "^6.1.11"
+    "jspack": "0.0.4",
+    "node-osc": "^6.1.11",
+    "socket.io": "^4.3.2"
   }
 }

+ 0 - 12
receiver/.editorconfig

@@ -1,12 +0,0 @@
-root = true
-
-[*]
-indent_style = tab
-end_of_line = lf
-charset = utf-8
-trim_trailing_whitespace = true
-insert_final_newline = true
-
-[*.yml,*.yaml]
-indent_style = space
-indent_size = 2

+ 0 - 3
receiver/.gitattributes

@@ -1,3 +0,0 @@
-* text=auto
-*.js text eol=lf
-

+ 0 - 4
receiver/.gitignore

@@ -1,4 +0,0 @@
-node_modules
-yarn.lock
-.nyc_output
-coverage

+ 0 - 62
receiver/backend/server.js

@@ -1,62 +0,0 @@
-const express = require('express');
-const dgram = require('dgram');
-const oscParser = require('./osc-parser');
-const bodyParser = require('body-parser');
-const path = require('path');
-const app = express();
-
-const server = require('http').Server(app);
-const io = require('socket.io')(server, {
-	transports: ['websocket']
-});
-
-const onSocketListening = function() {
-	const address = udpSocket.address();
-	console.log('Serveur TUIO en écoute sur : ' + address.address + ':' + address.port);
-};
-
-const onSocketConnection = function(socket) {
-	udpSocket.on('message', function(msg) {
-		socket.emit('osc', oscParser.decode(msg));
-	});
-};
-
-const udpSocket = dgram.createSocket('udp4');
-udpSocket.on('listening', onSocketListening);
-udpSocket.bind(3333, '127.0.0.1');
-
-app.use(bodyParser.json());
-app.use(bodyParser.urlencoded({extended:true}));
-app.use(express.static('./frontend/assets'));
-
-app.get('/', function (req, res) {
-	res.sendFile('./frontend/index.html', {
-		root: path.resolve(__dirname + '/..')
-	});
-});
-
-app.get('/json', function (req, res) {
-	res.status(200).send();
-});
-
-io.sockets.on('connection', (socket) =>{
-	console.log(`Connecté au client ${socket.id}`);
-	const dgramCallback = function (buf) {
-		// console.log(oscParser.decode(buf));
-		socket.emit('osc', oscParser.decode(buf));
-	};
-
-	// forward UDP packets via socket.io
-	udpSocket.on('message', dgramCallback);
-
-	// prevent memory leak on disconnect
-	socket.on('disconnect', function (socket) {
-		udpSocket.removeListener('message', dgramCallback);
-	});
-});
-
-// on change app par server
-server.listen(5000, function () {
-console.log('App frontend disponible sur localhost:5000 !')
-});
-

BIN
receiver/frontend/assets/favicon.ico


File diff suppressed because it is too large
+ 0 - 9404
receiver/frontend/assets/jquery-1.7.2.js


+ 0 - 133
receiver/frontend/index.html

@@ -1,133 +0,0 @@
-<!DOCTYPE html>
-<html>
-	<head>
-		<meta charset="utf-8">
-		<meta name="viewport" content="width=device-width">
-		<title>Proof of concept - Objets tangibles</title>
-
-		<style>
-			body {
-				background: #000;
-				margin: 0;
-			}
-			.tuioCursor {
-				background: #fff;
-				height: 8px;
-				left: 0;
-				position: absolute;
-				top: 0;
-				width: 8px;
-			}
-			.tuioObj {
-				background: #f00;
-				height: 15px;
-				left: 0;
-				position: absolute;
-				top: 0;
-				width: 8px;
-				rotate: 0deg;
-			}
-		</style>
-	</head>
-
-	<body>
-		<script src="/jquery-1.7.2.js"></script>
-		<script src="/lodash.js"></script>
-		<script src="/socket.io/socket.io.js"></script>
-		<script src="/tuio.js"></script>
-
-		<script>
-		$(function() {
-			const urlParams = new URLSearchParams(window.location.search);
-			const debugParams = urlParams.get('debug');
-			const debug = debugParams ? true : false;
-			if (debug) {
-				console.log('--- Debug activated ---');
-			}
-			var dotGroups = [];
-				var client = new Tuio.Client({
-					host: 'http://localhost:5000'
-				}),
-				screenW = $(document).width(),
-				screenH = $(document).height()
-
-				cursors = {},
-				objects = {},
-
-				onConnect = function() {
-					if (debug) {
-						console.log('connected');
-					}
-				},
-
-				onAddTuioCursor = function(addCursor) {
-					var $addCursor = $('<div class="tuioCursor"></div>');
-					$('body').append($addCursor);
-					cursors[addCursor.getCursorId()] = $addCursor;
-					onUpdateTuioCursor(addCursor);
-				},
-
-				onUpdateTuioCursor = function(updateCursor) {
-					var $updateCursor = cursors[updateCursor.getCursorId()];
-					$updateCursor.css({
-						left: updateCursor.getScreenX(screenW),
-						top: updateCursor.getScreenY(screenH)
-					});
-				},
-
-				onRemoveTuioCursor = function(removeCursor) {
-					var $removeCursor = cursors[removeCursor.getCursorId()];
-					$removeCursor.remove();
-					delete[removeCursor.getCursorId()];
-				},
-
-				onAddTuioObject = function(addObject) {
-					var $addObject = $('<div class="tuioObj"></div>');
-					$('body').append($addObject);
-					objects[addObject.symbolID] = $addObject;
-					onUpdateTuioObject(addObject);
-					if (debug) {
-						console.log('addTuioObject', addObject);
-					}
-				},
-
-				onUpdateTuioObject = function(updateObject) {
-					var $updateObject = objects[updateObject.symbolID];
-					$updateObject.css({
-						left: updateObject.getScreenX(screenW),
-						top: updateObject.getScreenY(screenH),
-						rotate : updateObject.getAngleDegrees()
-					});
-					if (debug) {
-						console.log('updateTuioObject', updateObject);
-					}
-				},
-
-				onRemoveTuioObject = function(removeObject) {
-					var $removeObject = objects[removeObject.symbolID];
-					$removeObject.remove();
-					delete[removeObject.symbolID];
-					if (debug) {
-						console.log('removeTuioObject', removeObject);
-					}
-				},
-
-				onRefresh = function(time) {
-					if (debug) {
-						console.log('refresh', time);
-					}
-				};
-
-				client.on('connect', onConnect);
-				client.on('addTuioCursor', onAddTuioCursor);
-				client.on('updateTuioCursor', onUpdateTuioCursor);
-				client.on('removeTuioCursor', onRemoveTuioCursor);
-				client.on('addTuioObject', onAddTuioObject);
-				client.on('updateTuioObject', onUpdateTuioObject);
-				client.on('removeTuioObject', onRemoveTuioObject);
-				client.on('refresh', onRefresh);
-				client.connect();
-			});
-		</script>
-	</body>
-</html>

+ 0 - 10
receiver/license

@@ -1,10 +0,0 @@
-MIT License
-
-Copyright (c) t1st3 <contact@t1st3.com> (t1st3.com)
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-

+ 0 - 13
receiver/package.json

@@ -1,13 +0,0 @@
-{
-  "name": "poc-objets-tangibles",
-  "version": "0.1.0",
-  "description": "",
-  "main": "index.js",
-  "dependencies": {
-    "body-parser": "^1.19.0",
-    "dgram": "^1.0.1",
-    "express": "^4.17.1",
-    "jspack": "0.0.4",
-    "socket.io": "^4.3.2"
-  }
-}

+ 0 - 59
receiver/readme.md

@@ -1,59 +0,0 @@
-# objets tangibles - receiver
-
-> Application basée sur Node.js et Express 4 qui reçoit des datagrammes TUIO et les transmet à une page web via web-sockets
-
-## Description
-
-Le projet fourni est composé de 2 parties:
-* un backend
-* un frontend
-
-Le backend est une application Node.js basée sur Express; il officie comme récepteur de données TUIO et les renvoie vers le frontend au moyen d'un web-socket.
-
-Le frontend est une page web, servie par le backend, qui reçoit les événements émis par le serveur grâce au web-socket.
-
-Chaque partie est contenue dans le dossier correspondant.
-
-
-## Pré-requis
-
-* Installer Node.js (v16 ou v17)
-* Installer les dépendances:
-
-```sh
-cd receiver
-npm install
-```
-
-
-## Lancer le serveur
-
-Dans le dossier du projet, lancer la commande suivante:
-
-```sh
-node ./backend/server.js
-```
-
-* La page du frontend sera accessible à l'adresse http://localhost:5000
-* Le serveur écoute les messages TUIO sur le port UDP 3333.
-
-
-## Tester la réception de messages TUIO
-
-On utilise le simulateur TUIO pour envoyer des messages. Par défaut, celui-ci émet également sur le port UDP 3333.
-Ce simulateur a été inclus à la racine du projet.
-
-Sur GNU/linux, le simulateur peut être lancé avec la commande suivante:
-
-```sh
-java -Djavax.accessibility.assistive_technologies=" " -jar TuioSimulator.jar
-```
-
-Note: le laguage Java doit être installé sur la machine.
-
-
-## Gestion du mode "debug" sur le frontend
-
-Ajouter le paramètre "debug" avec comme valeur 1 à l'URL: http://localhost:5000?debug=1
-Le mode debug affiche les messages de debuggage dans la console du navigateur.
-