Revision 908a231e

View differences:

DesktopConnector/DesktopConnector.js
1
var net = require('net');
2
var ws = require("nodejs-websocket");
3

  
4
var HOST = '127.0.0.1';
5
var PORT = 6555;
6
var connected = false;
7
var client = new net.Socket();
8

  
9
var connectionManager = [];
10
var connectionId = 0;
11
var websocket_server = null;
12

  
13
var eyeTracker = "";
14
if (process.argv.length == 2) {
15

  
16
	console.log("Start the server with --tracker=smi or --tracker=mygaze or --tracker=eyetribe");
17
	process.exit();
18

  
19
} else if (process.argv.length > 2) {
20
	process.argv.forEach(function(val, index, array) {
21

  
22
		if (val.indexOf("tracker") > -1) {
23
			eyeTracker = val.split("=")[1];
24
		}
25

  
26
	});
27
}
28

  
29
if (eyeTracker == "" || eyeTracker == undefined) {
30
	console.log("tracker was not set - exiting.");
31
	process.exit();
32
}
33

  
34
console.log("Tracker is " + eyeTracker);
35

  
36
function createServer() {
37
	websocket_server = ws.createServer(function(conn) {
38
		conn.on("text", function(str) {
39

  
40

  
41
			var senderID;
42
			for (var c in connectionManager) {
43
				//console.log(c+"{__}"+position);
44
				if (conn == connectionManager[c].conn) {
45
					senderID = connectionManager[c].id;
46
				}
47
			}
48

  
49
			console.log("Message from connection with id:" + senderID + " : \"" + str + "\"");
50
			if (str.indexOf("TYPE") > -1) {
51
				console.log("typestring: " + str);
52
				var clientType = str.split(':');
53
				//connectionManager[connectionId] = new Array();
54
				console.log("type = " + clientType[1]);
55

  
56
				for (var c in connectionManager) {
57
					//console.log("Sending SMI Data: "+str);
58
					if (connectionManager[c]['conn'] == conn) {
59
						connectionManager[c]['type'] = clientType[1];
60
					}
61
				}
62

  
63

  
64
			}
65

  
66
			if (eyeTracker == "smi") {
67
				try {
68
					for (var c in connectionManager) {
69
						console.log("Sending SMI Data: " + str);
70
						if (connectionManager[c]['type'] == "browser") {
71
							connectionManager[c]['conn'].sendText(str);
72
						}
73
					}
74
				} catch (err) {
75
					console.log("error in websocketserver: ");
76
					console.log("error at line:" + err.lineNumber);
77
					console.log("error:" + err);
78
					console.log("error at message:" + data);
79
					console.log("trying to establish new connection");
80
					createServer();
81
				}
82

  
83

  
84
			}
85
			if (eyeTracker == "mygaze") {
86
				try {
87
					for (var c in connectionManager) {
88
						console.log("Sending myGaze Data: " + str);
89
						if (connectionManager[c]['type'] == "browser") {
90
							connectionManager[c]['conn'].sendText(str);
91
						}
92
					}
93
				} catch (err) {
94
					console.log("error in websocketserver: ");
95
					console.log("error at line:" + err.lineNumber);
96
					console.log("error:" + err);
97
					console.log("error at message:" + data);
98
					console.log("trying to establish new connection");
99
					createServer();
100
				}
101

  
102

  
103
			}
104
			if (eyeTracker == "eyetribe") {
105
				//send the message from the browser directly to the eyetracker
106
				client.write(str);
107
			}
108
		});
109

  
110
			conn.on('error', function(er) {
111
  // The error won't crash the process, but what it does is worse!
112
  // Though we've prevented abrupt process restarting, we are leaking
113
  // resources like crazy if this ever happens.
114
  // This is no better than process.on('uncaughtException')!
115
  console.log(eyeTracker +" disconnected. ERRORMESSAGE: ", er.message);
116
});
117

  
118

  
119
		conn.on("close", function(code, reason) {
120
			for (var c in connectionManager) {
121
				//console.log(c+"{__}"+position);
122
				if (conn == connectionManager[c].conn) {
123
					console.log("connection '" + c + "' disconnected.");
124
					delete connectionManager[c];
125
				}
126
			}
127
		});
128
	}).listen(6777);
129

  
130

  
131

  
132
	websocket_server.on("connection", function(conn) {
133
		connectionManager[connectionId] = [];
134
		connectionManager[connectionId].conn = conn;
135
		connectionManager[connectionId].id = connectionId;
136
		console.log("A new client connected with id: " + connectionId);
137
		connectionId++;
138
	});
139

  
140
}
141

  
142

  
143

  
144
if (eyeTracker == "eyetribe") {
145
	//Heartbeat timer
146
	setInterval(function() {
147
		if (connected) {
148
			sendHeartbeat(client);
149
		}
150
	}, 250);
151
	client.connect(PORT, HOST, function() {
152

  
153
		console.log('Websocket connected successfully to tcp server(EyeTracker): ' + HOST + ':' + PORT);
154
		connected = true;
155

  
156
		//check the eyetracker status
157
		//client.write('{"category": "tracker","request": "get","values": ["push", "iscalibrated" ]}');
158
		//client.write('{"category": "tracker","request": "set","values": {"push": true,"version": 1}}');
159

  
160
		//client.write('{"category": "tracker","request" : "get","values": [ "push", "iscalibrated" ]}');
161
	});
162
} else if (eyeTracker == "smi") {
163
	console.log('Waiting for messages from SMI EyeTracker on 127.0.0.1:6777');
164

  
165
} else if (eyeTracker == "mygaze") {
166
	console.log('Waiting for messages from myGaze EyeTracker on 127.0.0.1:6777');
167

  
168
}
169

  
170

  
171
//as soon as the websocket receives any data from the eyetracker it is forwarded to the browser
172
client.on('data', function(data) {
173

  
174
	try {
175
		for (var c in connectionManager) {
176
			console.log("Sending EyeTrackingData to Browser: "+data);
177

  
178
			connectionManager[c]['conn'].sendText(data);
179

  
180
		}
181
	} catch (err) {
182
		console.log("error in websocketserver: ");
183
		console.log("error at line:" + err.lineNumber);
184
		console.log("error:" + err);
185
		console.log("error at message:" + data);
186
		console.log("trying to establish new connection");
187
		createServer();
188
	}
189
	// Close the client socket completely
190
	//client.destroy();    
191
});
192

  
193
// Add a 'close' event handler for the client socket
194
client.on('close', function() {
195
	connected = false;
196
	console.log('EyeTracker Disconnected.');
197
	createServer();
198
	
199
});
200

  
201
function sendHeartbeat(socket) {
202
	socket.write("{\"category\":\"heartbeat\",\"request\":null}");
203
	//console.log('Heartbeat sent.');	
204
}
205

  
206

  
207

  
208
try {
209
	createServer();
210
} catch (err) {
211
	console.log("error in websocketserver: ");
212
	console.log("error at line:" + err.lineNumber);
213
	console.log("error:" + err);
214
	console.log("error at message:" + data);
215
	console.log("trying to establish new connection");
216
	createServer();
217
}
DesktopConnector/DeviceServer_MyGaze/DeviceServer_MyGaze.py
1
#
2
# DeviceServer_MyGaze.py
3
# 
4
# This file is part of GazeTk.
5
#
6
# Copyright 2015 Thies Pfeiffer and Dimitri Heil
7
# GazeTk is distributed under the terms of the GNU General Public License
8
# 
9
# GazeTk is free software: you can redistribute it and/or modify
10
# it under the terms of the GNU General Public License as published by
11
# the Free Software Foundation, either version 3 of the License, or
12
# (at your option) any later version.
13
# 
14
# GazeTk is distributed in the hope that it will be useful,
15
# but WITHOUT ANY WARRANTY; without even the implied warranty of
16
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
# GNU General Public License for more details.
18
# 
19
# You should have received a copy of the GNU General Public License
20
# along with GazeTk. If not, see <http://www.gnu.org/licenses/>.
21
#
22

  
23
from myGazeAPI import  *            			# myGaze library
24

  
25
from websocket import create_connection
26
ws = create_connection("ws://127.0.0.1:6777")
27
print "sending: Hi, this is the python server"
28
ws.send("TYPE:mygaze");
29
ws.send("Hi, this is the mygaze python server")
30
print "sent."
31

  
32

  
33
# ---------------------------------------------------------------------------- 
34
# ---- connect to myGazeAPI eyetracking-server 
35
# ---------------------------------------------------------------------------- 
36

  
37
res = myGazeAPI.iV_Connect()
38
if res != 1:
39
    print "Could not connect " + str(res) 
40
    exit(0)
41

  
42
	
43
# ---------------------------------------------------------------------------- 
44
# ---- read out system information 
45
# ---------------------------------------------------------------------------- 
46

  
47
res = myGazeAPI.iV_GetSystemInfo(byref(systemData))
48
print "myGaze eyetracking-server Version: " + str(systemData.iV_MajorVersion) + "." + str(systemData.iV_MinorVersion) + "." + str(systemData.iV_Buildnumber)
49
print "myGaze API Version: " + str(systemData.API_MajorVersion) + "." + str(systemData.API_MinorVersion) + "." + str(systemData.API_Buildnumber)
50

  
51

  
52
# ---------------------------------------------------------------------------- 
53
# ---- start the calibration and validation process 
54
# ---------------------------------------------------------------------------- 
55

  
56
# see the User Manual for detailed information due to setting up calibration 
57
calibrationData = CCalibration(5, 1, 0, 0, 1, 250, 220, 2, 20, b"")
58
res = myGazeAPI.iV_SetupCalibration(byref(calibrationData))
59
print "iV_SetupCalibration " + str(res)
60

  
61
# start the calibration process 
62
res = myGazeAPI.iV_Calibrate()
63
print "iV_Calibrate " + str(res)
64

  
65
# start the validation process 
66
res = myGazeAPI.iV_Validate()
67
print "iV_Validate " + str(res)
68

  
69
# read out the accuracy values 
70
res = myGazeAPI.iV_GetAccuracy(byref(accuracyData))
71
print "iV_GetAccuracy " + str(res)
72
print "accuracy left X: " + str(accuracyData.deviationLX) + " left Y: " + str(accuracyData.deviationLY)
73
print "accuracy right X: " + str(accuracyData.deviationRX) + " left Y: " + str(accuracyData.deviationRY)
74

  
75
# show tracking monitor 
76
res = myGazeAPI.iV_ShowTrackingMonitor()
77
print "iV_ShowTrackingMonitor " + str(res)
78

  
79

  
80
# ---------------------------------------------------------------------------- 
81
# ---- accessing eye tracking data stream 
82
# ---------------------------------------------------------------------------- 
83

  
84
# output samples
85
a = 0;
86
while a < 1000:
87

  
88
    # get gaze data sample
89
    res = myGazeAPI.iV_GetSample(byref(sampleData))
90
    if res == 1:
91
       # a = a + 1
92
        #print "Gaze Data - GazeX: " + str(sampleData.leftEye.gazeX) + " GazeY: " + str(sampleData.leftEye.gazeY) 
93
        ws.send("{\"x\":"+str(sampleData.leftEye.gazeX)+",\"y\":"+str(sampleData.leftEye.gazeY)+"}")
94
        #ws.send("{\"x\":"+str(sampleData.rightEye.gazeX)+",\"y\":"+str(sampleData.rightEye.gazeY)+"}")
95
    # get gaze data sample
96
    res = myGazeAPI.iV_GetEvent(byref(eventData))
97
    #if res == 1:
98
        #print "Fixation " + str(eventData.eye) + " - X: " + str(eventData.positionX) + " Y: " + str(eventData.positionY) 
99

  
100
		
101
# ---------------------------------------------------------------------------- 
102
# ---- disconnect from myGaze eyetracking server 
103
# ---------------------------------------------------------------------------- 
104

  
105
res = myGazeAPI.iV_Disconnect()
106
ws.close()
107
#end of the trial 
108
#window.close()
109
#core.quit()
110

  
111

  
DesktopConnector/DeviceServer_MyGaze/README.md
1
DeviceServer_MyGaze
2
===================
3

  
4
[Download](https://opensource.cit-ec.de/projects/gazetk/repository/gazetk)
5

  
6
License
7
-------
8
DeviceServer_MyGaze is free and open source software distributed under the terms of the [GNU General Public License](http://www.gnu.org/licenses/).
9

  
10
Description
11
-----------
12
Welcome to DeviceServer_MyGaze!
13

  
14
This python-based server connects your MyGaze eye tracking device with the GazeTk DesktopConnector. 
15

  
16
Requirements
17
------------
18
- Python 2.7 32bit
19
- Python module websocket
20

  
21
Installation
22
------------
23
1. Install Python 2.7 32bit
24
2. Install websocket-client by running the following script from PYTHONDIR/Scripts:
25

  
26
$ pip install websocket-client
27

  
28
Starting DeviceServer_MyGaze
29
----------------------------
30
1. Start the myGaze application provided with the device.
31
2. Make sure you have the myGazeAPI.dll on your PATH, they come with the MyGaze installation package.
32
3. Start the DeviceServer_MyGaze:
33

  
34
$ python DeviceServer_MyGaze.py
35

  
36

  
DesktopConnector/DeviceServer_MyGaze/myGazeAPI.py
1
# myGazeAPI.py 
2
#
3
# (C) Copyright 2013, Visual Interaction GmbH 
4
# All rights reserved. This work contains unpublished proprietary 
5
# information of Visual Interaction GmbH and is copy protected by law. 
6
# (see accompanying file eula.pdf)
7
#
8
# Author: Visual Interaction GmbH 
9
# November, 2012 
10

  
11

  
12

  
13
from ctypes import *
14

  
15

  
16
# ---------------------------------------------------------------------------- 
17
# ---- Struct Definitions 
18
# ---- (for detailed information due to the data  
19
# ---- structuresplease refer to the myGaze SDK Manual) 
20
# ---------------------------------------------------------------------------- 
21

  
22
class CSystem(Structure):
23
	_fields_ = [("samplerate", c_int),
24
	("iV_MajorVersion", c_int),
25
	("iV_MinorVersion", c_int),
26
	("iV_Buildnumber", c_int),
27
	("API_MajorVersion", c_int),
28
	("API_MinorVersion", c_int),
29
	("API_Buildnumber", c_int),
30
	("iV_ETDevice", c_int)]
31

  
32
	
33
class CCalibrationPoint(Structure):
34
	_fields_ = [("number", c_int),
35
	("positionX", c_int),
36
	("positionY", c_int)]
37

  
38
	
39
class CEye(Structure):
40
	_fields_ = [("gazeX", c_double),
41
	("gazeY", c_double),
42
	("diam", c_double),
43
	("eyePositionX", c_double),
44
	("eyePositionY", c_double),
45
	("eyePositionZ", c_double)]
46

  
47
	
48
class CSample(Structure):
49
	_fields_ = [("timestamp", c_longlong),
50
	("leftEye", CEye),
51
	("rightEye", CEye)]
52

  
53
	
54
class CEvent(Structure):
55
	_fields_ = [("eventType", c_char),
56
	("eye", c_char),
57
	("startTime", c_longlong),
58
	("endTime", c_longlong),
59
	("duration", c_longlong),
60
	("positionX", c_double),
61
	("positionY", c_double)]
62

  
63

  
64
class CAccuracy(Structure):
65
	_fields_ = [("deviationLX", c_double),
66
	("deviationLY", c_double),
67
	("deviationRX", c_double),
68
	("deviationRY", c_double)]
69
				
70
				
71
class CCalibration(Structure):
72
	_fields_ = [("method", c_int),
73
	("visualization", c_int),
74
	("displayDevice", c_int),
75
	("speed", c_int),
76
	("autoAccept", c_int),
77
	("foregroundBrightness", c_int),
78
	("backgroundBrightness", c_int),
79
	("targetShape", c_int),
80
	("targetSize", c_int),
81
	("targetFilename", c_char * 256)]
82

  
83

  
84
class CMonitorAttachedGeometry(Structure):
85
	_fields_ = [("setupName", c_char * 256),
86
	("stimX", c_int),
87
	("stimY", c_int),
88
	("redStimDistHeight", c_int),
89
	("redStimDistDepth", c_int),
90
	("redInclAngle", c_int)]
91
	
92
	
93
class CImage(Structure):
94
	_fields_ = [("imageHeight", c_int),
95
	("imageWidth", c_int),
96
	("imageSize", c_int),
97
	("imageBuffer", c_char)]
98
	
99

  
100
class CDate(Structure):
101
	_fields_ = [("day", c_int),
102
	("month", c_int),
103
	("year", c_int)]
104
	
105

  
106
# ---------------------------------------------------------------------------- 
107
# ---- loading myGazeAPI.dll 
108
# ---------------------------------------------------------------------------- 
109

  
110
myGazeAPI = windll.LoadLibrary("myGazeAPI.dll")
111

  
112

  
113
# ---------------------------------------------------------------------------- 
114
# ---- initializing structs
115
# ---------------------------------------------------------------------------- 
116

  
117
systemData = CSystem(0, 0, 0, 0, 0, 0, 0, 0)
118
leftEye = CEye(0, 0, 0, 0, 0, 0)
119
rightEye = CEye(0, 0, 0, 0, 0, 0)
120
sampleData = CSample(0, leftEye, rightEye)
121
eventData = CEvent('F', 'L', 0, 0, 0, 0, 0)
122
accuracyData = CAccuracy(0,0,0,0)
123
calibrationData = CCalibration(5, 1, 0, 0, 1, 20, 239, 1, 15, b"")
124
geometry = CMonitorAttachedGeometry(b"DefaultSetup", 474, 296, 0, 35, 20);
125

  
DesktopConnector/DeviceServer_MyGaze/myGazeAPIReturnCodes.py
1
# myGazeAPIReturnCodes.py 
2
#
3
# (C) Copyright 2013, Visual Interaction GmbH 
4
# All rights reserved. This work contains unpublished proprietary 
5
# information of Visual Interaction GmbH and is copy protected by law. 
6
# (see accompanying file eula.pdf)
7
#
8
# Author: Visual Interaction GmbH 
9
# March, 2012 
10

  
11
	
12
def HandleError(ret):
13
	switch(ret)
14
	{
15
	case 1: 
16
		break;
17
	case 2: 
18
		print "not valid data."
19
		break;
20
	case 3: 
21
		print "Calibration/validation aborted."
22
		break;
23
	case 4: 
24
		print "Server is already running."
25
		break;
26
	case 100: 
27
		print "Connection is not established."
28
		break;
29
	case 101: 
30
		print "Could not establish connection."
31
		break;
32
	case 102: 
33
		print "System is not calibrated."
34
		break;
35
	case 103: 
36
		print "System is not validated."
37
		break;
38
	case 104: 
39
		print "Could not establish connection. Check if Eye Tracker is running."
40
		break;
41
	case 112: 
42
		print "Invalid parameter."
43
		break;
44
	case 113: 
45
		print "Calibration method is not supported."
46
		break;
47
	case 114: 
48
		print "Timeout during calibration."
49
		break;
50
	case 115: 
51
		print "tracking is not stable."
52
		break;
53
	case 121: 
54
		print "Communication problem."
55
		break;
56
	case 122: 
57
		print "Communication problem."
58
		break;
59
	case 123: 
60
		print "Could not establish connection. Another Process is blocking the communication Ports."
61
		break; 
62
	case 124: 
63
		print "Communication problem."
64
		break;
65
	case 131: 
66
		print "Server is not responding."
67
		break;
68
	case 132: 
69
		print "Invalid server version."
70
		break;
71
	case 133: 
72
		print "Wrong server version."
73
		break;
74
	case 171: 
75
		print "File access error."
76
		break;
77
	case 181: 
78
		print "Socket connection error."
79
		break;
80
	case 194: 
81
		print "Server is not ready."
82
		break;
83
	case 201: 
84
		print "Could not establish connection. Check if Eye Tracker is installed and running."
85
		break;
86
	case 202: 
87
		print "Server path not found."
88
		break;
89
	case 203: 
90
		print "Server access denied."
91
		break;
92
	case 204: 
93
		print "Server access error."
94
		break;
95
	case 205: 
96
		print "Server out of memory."
97
		break;
98
	case 211: 
99
		print "Camera not found."
100
		break;
101
	case 212: 
102
		print "Wrong camera."
103
		break;
104
	case 213: 
105
		print "Wrong camera port."
106
		break;
107
	case 220: 
108
		print "Could not open port."
109
		break;
110
	case 221: 
111
		print "Could not close port."
112
		break;
113
	case 250: 
114
		print "Feature not licensed."
115
		break;
116
	}
117
	
118
return 
119

  
DesktopConnector/DeviceServer_MyGaze/startDeviceServer_MyGaze.bat
1
python DeviceServer_MyGaze.py
2
pause
DesktopConnector/README.md
1
DesktopConnector
2
================
3

  
4
[Download](https://opensource.cit-ec.de/projects/gazetk/repository/gazetk)
5

  
6
License
7
-------
8
DesktopConnector is free and open source software distributed under the terms of the [GNU General Public License](http://www.gnu.org/licenses/).
9

  
10
Description
11
-----------
12
Welcome to DesktopConnector!
13

  
14
DesktopConnector is the bridge between your remote desktop eye tracking device and gaze-enabled applications.
15

  
16
At the moment, DesktopConnector is written in Node.js. It consists of a basic server, which provides the interface to the application, and different DeviceConnectors for certain types of remote eye tracking systems.
17

  
18
Requirements
19
------------
20
* Node.js
21
* One of the supported eye tracking systems
22
** Eyetribe
23
** MyGaze
24
** SMI REDm
25

  
26
Installation
27
------------
28
1. Install Node.js
29
2. Install the Node.js module nodejs-websocket
30

  
31
$ npm install nodejs-websocket
32

  
33
Starting DesktopConnector
34
-------------------------
35
1. Use the corresponding bat-file to start the DeviceConnector confiured for your eye tracking device, or start
36

  
37
$ node DesktopConnector.js --tracker=XXX
38

  
39
with XXX standing for smi, eyetribe or mygaze, which are the eye tracking systems that are currently supported.
40

  
41
2. If you are using SMI REDm or MyGaze, you will need to start an additional DeviceServer. You can find them in the subdirectories.
DesktopConnector/runEyetribe.bat
1
node DesktopConnector.js --tracker=eyetribe
DesktopConnector/runMyGaze.bat
1
node DesktopConnector.js --tracker=mygaze
2
pause
DesktopConnector/runSMI.bat
1
node DesktopConnector.js --tracker=smi
README.md
1
GazeTk
2
======
3

  
4
[Download](https://opensource.cit-ec.de/projects/gazetk/repository/gazetk)
5

  
6
License
7
-------
8
GazeTk is free and open source software distributed under the terms of the [GNU General Public License](http://www.gnu.org/licenses/).
9

  
10
Description
11
-----------
12
Welcome to GazeTk!
13

  
14

  
15
Subprojects
16
-----------
17

  
18
* **DesktopConnector** provides connectivity to many different remote desktop eye tracking systems.
19

  
read.me
1
asdasds

Also available in: Unified diff