aboutsummaryrefslogtreecommitdiff
path: root/lib/motion.js
diff options
context:
space:
mode:
Diffstat (limited to 'lib/motion.js')
-rw-r--r--lib/motion.js100
1 files changed, 100 insertions, 0 deletions
diff --git a/lib/motion.js b/lib/motion.js
new file mode 100644
index 0000000..781d54b
--- /dev/null
+++ b/lib/motion.js
@@ -0,0 +1,100 @@
+const util = require("util")
+ , EventEmitter = require("events").EventEmitter;
+
+const longTime = 600;
+
+//const clone = x => JSON.parse(JSON.stringify(x)); // Deep
+const clone = x => Object.assign({}, x); // Shallow
+const slotToPoint = s => ({xi:s.xi, yi:s.yi, xf:s.x, yf:s.y});
+
+function Motion(device) {
+ this.device = device;
+ this.slotsUsed = 0;
+ this.slots = [];
+ this.points = [];
+ this.longed = false;
+
+ device.on("EV_ABS", e => this.doABS(e));
+ device.on("EV_SYN", e => this.doSYN(e));
+ device.on("error", e => this.emit("error", "Device Error: "+e));
+ this.addSlot();
+}
+
+util.inherits(Motion, EventEmitter);
+
+Motion.prototype.addSlot = function() {
+ this.slots.push({id: -1, xi: -1, yi: -1, x: 0, y: 0});
+};
+
+Motion.prototype.emitLong = function() {
+ this.slots.forEach(s => { if (s.id >= 0)
+ this.points.push(slotToPoint(s)); });
+ this.emit("long", this.points);
+ this.points = [];
+ this.longed = true;
+};
+
+Motion.prototype.doABS = function(e) {
+switch (e.code) {
+
+ case "ABS_MT_SLOT":
+ for (let i=this.slots.length-1;
+ i<e.value; i++) this.addSlot();
+ this.currentSlot = this.slots[e.value];
+ break;
+
+ case "ABS_MT_TRACKING_ID":
+ if (!this.currentSlot) return;
+ if (e.value >= 0) {
+ this.currentSlot.id = e.value;
+ if (this.slotsUsed++ === 0) {
+ //this.start = e.time;
+ this.longTimeout = setTimeout(() =>
+ this.emitLong(), longTime);
+ }
+
+ } else {
+ if (!this.longed && this.currentSlot.xi >= 0)
+ this.points.push(slotToPoint(this.currentSlot));
+ this.currentSlot.id = -1;
+ this.currentSlot.xi = -1;
+ this.currentSlot.yi = -1;
+ this.currentSlot.x = 0;
+ this.currentSlot.y = 0;
+ if (--this.slotsUsed === 0) {
+ //this.end = e.time;
+ clearTimeout(this.longTimeout);
+ }
+ } break;
+
+ case "ABS_MT_POSITION_X":
+ if (!this.currentSlot) return;
+ if (this.currentSlot.id < 0) return;
+ this.currentSlot.x = e.value;
+ if (this.currentSlot.xi < 0)
+ this.currentSlot.xi = e.value;
+ break;
+
+ case "ABS_MT_POSITION_Y":
+ if (!this.currentSlot) return;
+ if (this.currentSlot.id < 0) return;
+ this.currentSlot.y = e.value;
+ if (this.currentSlot.yi < 0)
+ this.currentSlot.yi = e.value;
+ break;
+
+ //default:
+ // console.log(e.code, e.value);
+}};
+
+Motion.prototype.doSYN = function(e) {
+ if (e.code === "SYN_REPORT" && this.slotsUsed === 0) {
+ if (this.longed) { this.longed = false;
+ } else if (this.points.length > 0) {
+ this.emit("short", this.points);
+ this.points = [];
+ }
+ }
+};
+
+module.exports = Motion;