aboutsummaryrefslogtreecommitdiff
path: root/lib/motion.js
blob: 3e2496200fd23abab5f98884a41d2eac5e227ed4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
const util = require("util")
    , EventEmitter = require("events").EventEmitter;

//const slotToPoint = s => ({xi:s.xi, yi:s.yi, xf:s.x, yf:s.y});
const slotToPoint = s => ({
  i:{x:s.xi, y:s.yi}, f:{x:s.x, y:s.y},
  m:{x:(s.xi+s.x)/2, y:(s.yi+s.y)/2}
});

function Motion(device, longTime) {
  this.device = device;
  this.slotsActive = 0;
  this.slots = [];
  this.points = [];
  this.longed = false;
  this.longTime = longTime || 600;

  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 === undefined) {
      this.addSlot();
      this.currentSlot = this.slots[0];
    }

    if (e.value >= 0) {
      this.currentSlot.id = e.value;
      if (this.slotsActive++ === 0) {
        this.longTimeout = setTimeout(() =>
          this.emitLong(), this.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.slotsActive === 0) {
        clearTimeout(this.longTimeout);
      }
    } break;

  case "ABS_MT_POSITION_X":
    if (this.currentSlot === undefined) return;
    if (this.currentSlot.id < 0) return;
    if (this.currentSlot.xi < 0)
      this.currentSlot.xi = e.value;
    this.currentSlot.x = e.value;
    break;

  case "ABS_MT_POSITION_Y":
    if (this.currentSlot === undefined) return;
    if (this.currentSlot.id < 0) return;
    if (this.currentSlot.yi < 0)
      this.currentSlot.yi = e.value;
    this.currentSlot.y = e.value;
    break;

  //default:
  //  console.log(e.code, e.value);
}};

Motion.prototype.doSYN = function(e) {
  if (e.code === "SYN_REPORT") {
    //console.log("SYN", this.slotsActive, this.points.length);
    if (this.slotsActive <= 0) {
      this.slotsActive = 0;

      if (this.longed) { this.longed = false;
      } else if (this.points.length > 0) {
        this.emit("short", this.points);
        this.points = [];
      }
    }
  }
};

module.exports = Motion;