|
1 /* |
|
2 * This file is part of the TraKERS\Middleware package. |
|
3 * |
|
4 * (c) IRI <http://www.iri.centrepompidou.fr/> |
|
5 * |
|
6 * For the full copyright and license information, please view the LICENSE |
|
7 * file that was distributed with this source code. |
|
8 */ |
|
9 |
|
10 /* |
|
11 * Projet : TraKERS |
|
12 * Module : MIDDLEWARE |
|
13 * Sous-Module : Communication |
|
14 * Classe : WSServer |
|
15 * |
|
16 * Auteur : alexandre.bastien@iri.centrepompidou.fr |
|
17 * |
|
18 * Fonctionnalités : Reçoit des notifications du module sous-module Tracking. |
|
19 * Traduit les notifications sous forme de strings et les envoie au Front IDILL via WebSocket. |
|
20 * Forme des messages : |
|
21 * - Notification de main dans le champ de recherche : Point3D converti en String indiquant la position de la main dans l'espace. |
|
22 * - Notification de gesture/mode : String. |
|
23 * - Paramètres de config : String. |
|
24 */ |
|
25 |
|
26 using System; |
|
27 using System.Collections.Generic; |
|
28 using System.Linq; |
|
29 using System.Text; |
|
30 using System.Threading; |
|
31 using Fleck; |
|
32 using System.Timers; |
|
33 using System.Windows.Media.Media3D; |
|
34 |
|
35 namespace Trakers.Communication |
|
36 { |
|
37 public class WSServer |
|
38 { |
|
39 //Server WebSocket. |
|
40 WebSocketServer server; |
|
41 List<IWebSocketConnection> allSockets; |
|
42 |
|
43 //Permet de savoir si un curseur pour la main gauche/droite a été créé. |
|
44 private bool leftHandCursorCreated; |
|
45 private bool rightHandCursorCreated; |
|
46 private bool messageCreated; |
|
47 private bool gestureLocked, modLocked; |
|
48 //Intervalle minimum entre les gestures. |
|
49 private int timerElapsing; |
|
50 //Timer. |
|
51 private System.Timers.Timer _timer; |
|
52 //Dernier code envoyé. |
|
53 private String lastCode; |
|
54 //Messages envoyés en WS. |
|
55 private String rightHandMessage, leftHandMessage, gestureMessage; |
|
56 //Messages précédents |
|
57 private String prevRightHandMessage, prevLeftHandMessage, prevGestureMessage; |
|
58 |
|
59 /* |
|
60 * Constructeur : On initialise le serveur avec une adresse et un port, au début les curseurs |
|
61 * ne sont pas créés et on indique au ThreadPool une fonction de callback de manière à vérifier |
|
62 * s'il reçoit des notifications. |
|
63 */ |
|
64 public WSServer(String host, int port, int _timerElapsing) |
|
65 { |
|
66 FleckLog.Level = LogLevel.Debug; |
|
67 allSockets = new List<IWebSocketConnection>(); |
|
68 server = new WebSocketServer(port, "ws://" + host + ":" + port); |
|
69 |
|
70 //Au départ, aucune main n'est dans le champ de recherche et aucune gesture n'est détectée. |
|
71 leftHandCursorCreated = false; |
|
72 rightHandCursorCreated = false; |
|
73 messageCreated = false; |
|
74 gestureLocked = false; |
|
75 modLocked = false; |
|
76 lastCode = ""; |
|
77 |
|
78 timerElapsing = _timerElapsing; |
|
79 |
|
80 rightHandMessage = leftHandMessage = gestureMessage = ""; |
|
81 |
|
82 //On démarre le serveur WebSocket. |
|
83 server.Start(socket => |
|
84 { |
|
85 socket.OnOpen = () => |
|
86 { |
|
87 Console.WriteLine("Open!"); |
|
88 allSockets.Add(socket); |
|
89 }; |
|
90 socket.OnClose = () => |
|
91 { |
|
92 Console.WriteLine("Close!"); |
|
93 allSockets.Remove(socket); |
|
94 }; |
|
95 /*socket.OnMessage = message => |
|
96 { |
|
97 Console.WriteLine(message); |
|
98 allSockets.ToList().ForEach(s => s.Send("Echo: " + message)); |
|
99 };*/ |
|
100 }); |
|
101 |
|
102 //On initialise le threadPool (appelé toutes les N ms). |
|
103 ThreadPool.QueueUserWorkItem(ThreadPoolCallback); |
|
104 |
|
105 //On instancie le timer à N ms. |
|
106 _timer = new System.Timers.Timer(timerElapsing); |
|
107 //Dès que le timer est expiré, on appelle _timer_Elapsed. |
|
108 _timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed); |
|
109 |
|
110 /*var input = Console.ReadLine(); |
|
111 while (input != "exit") |
|
112 { |
|
113 foreach (var socket in allSockets.ToList()) |
|
114 { |
|
115 socket.Send(input); |
|
116 } |
|
117 input = Console.ReadLine(); |
|
118 }*/ |
|
119 } |
|
120 |
|
121 /* |
|
122 * Méthode appelée à l'expiration du timer pour les gestures et modes. |
|
123 */ |
|
124 public void _timer_Elapsed(object sender, ElapsedEventArgs e) |
|
125 { |
|
126 //On débloque la détection de gesture. |
|
127 gestureLocked = false; |
|
128 //On débloque la notification de nouveau mode. |
|
129 modLocked = false; |
|
130 //On arrête le timer. |
|
131 _timer.Stop(); |
|
132 } |
|
133 |
|
134 /* |
|
135 * Méthode appelée lors d'une notification de type : main gauche entrée dans le champ. |
|
136 */ |
|
137 public void LeftHandTracked(Point3D pt) |
|
138 { |
|
139 leftHandMessage = "0-" + pt.X + ";" + pt.Y + ";" + pt.Z; |
|
140 //Si le curseur de la main gauche n'est pas créé, alors on le crée. |
|
141 if (!leftHandCursorCreated) |
|
142 leftHandCursorCreated = true; |
|
143 } |
|
144 |
|
145 /* |
|
146 * Méthode appelée lors d'une notification de type : main droite entrée dans le champ. |
|
147 */ |
|
148 public void RightHandTracked(Point3D pt) |
|
149 { |
|
150 rightHandMessage = "1-" + pt.X + ";" + pt.Y + ";" + pt.Z; |
|
151 //Si le curseur de la main droite n'est pas créé, alors on le crée. |
|
152 if (!rightHandCursorCreated) |
|
153 rightHandCursorCreated = true; |
|
154 } |
|
155 |
|
156 /* |
|
157 * Méthode appelée lors d'une notification de type : main gauche sortie du champ. |
|
158 */ |
|
159 public void LeftHandQuit() |
|
160 { |
|
161 leftHandMessage = ""; |
|
162 //Si le curseur de la main gauche existe, alors on le supprime. |
|
163 if (leftHandCursorCreated) |
|
164 leftHandCursorCreated = false; |
|
165 } |
|
166 |
|
167 /* |
|
168 * Méthode appelée lors d'une notification de type : main droite sortie du champ. |
|
169 */ |
|
170 public void RightHandQuit() |
|
171 { |
|
172 rightHandMessage = ""; |
|
173 //Si le curseur de la main droite existe, alors on le supprime. |
|
174 if (rightHandCursorCreated) |
|
175 rightHandCursorCreated = false; |
|
176 } |
|
177 |
|
178 /* |
|
179 * Méthode appelée lorsqu'une gesture a été détectée et que l'événement approprié a été lancé. |
|
180 */ |
|
181 public void GesturePerformed(String code) |
|
182 { |
|
183 //Si le code vient d'être envoyé, on passe. |
|
184 if (lastCode.Equals(code)) |
|
185 return; |
|
186 lastCode = code; |
|
187 //Si une gesture a été effectuée, on bloque un certain temps. |
|
188 if (!gestureLocked) |
|
189 { |
|
190 gestureLocked = true; |
|
191 |
|
192 //On crée un message contenant le code à envoyer. |
|
193 if (!messageCreated) |
|
194 { |
|
195 messageCreated = true; |
|
196 gestureMessage = "2-" + code; |
|
197 //On démarre le timer. |
|
198 _timer.Start(); |
|
199 } |
|
200 } |
|
201 } |
|
202 |
|
203 /* |
|
204 * Méthode appelée lorsqu'on doit entrer dans un autre mode. |
|
205 */ |
|
206 public void ModeNotification(String code) |
|
207 { |
|
208 //Si le code vient d'être envoyé, on passe. |
|
209 if (lastCode.Equals(code)) |
|
210 return; |
|
211 lastCode = code; |
|
212 //Si on a été notifié. |
|
213 if (!modLocked) |
|
214 { |
|
215 modLocked = true; |
|
216 |
|
217 //On crée un message contenant le code à envoyer. |
|
218 if (!messageCreated) |
|
219 { |
|
220 messageCreated = true; |
|
221 gestureMessage = "2-" + code; |
|
222 //On démarre le timer. |
|
223 _timer.Start(); |
|
224 } |
|
225 } |
|
226 } |
|
227 |
|
228 /* |
|
229 * Méthode de callback vérifiant toutes les 25 ms les nouvelles notifications. |
|
230 * Il est à noter que si le temps de rafraîchissement des trop rapide, les messages n'ont pas |
|
231 * le temps d'être envoyés. |
|
232 */ |
|
233 private void ThreadPoolCallback(Object threadContext) |
|
234 { |
|
235 while (true) |
|
236 { |
|
237 //S'il existe un message. |
|
238 if (gestureMessage != null && !gestureMessage.Equals("") && !gestureMessage.Equals(prevGestureMessage)) |
|
239 { |
|
240 //On l'envoie au client (au host et au port spécifiés dans le constructeur). |
|
241 foreach (var socket in allSockets.ToList()) |
|
242 { |
|
243 socket.Send(gestureMessage); |
|
244 prevGestureMessage = gestureMessage; |
|
245 } |
|
246 } |
|
247 //Si la main gauche est détectée. |
|
248 if (leftHandMessage != null && !leftHandMessage.Equals("") && !leftHandMessage.Equals(prevLeftHandMessage)) |
|
249 { |
|
250 //On l'envoie au client (au host et au port spécifiés dans le constructeur). |
|
251 foreach (var socket in allSockets.ToList()) |
|
252 { |
|
253 socket.Send(leftHandMessage); |
|
254 prevLeftHandMessage = leftHandMessage; |
|
255 } |
|
256 } |
|
257 //Si la main droite est détectée. |
|
258 if (rightHandMessage != null && !rightHandMessage.Equals("") && !rightHandMessage.Equals(prevRightHandMessage)) |
|
259 { |
|
260 //On l'envoie au client (au host et au port spécifiés dans le constructeur). |
|
261 foreach (var socket in allSockets.ToList()) |
|
262 { |
|
263 socket.Send(rightHandMessage); |
|
264 prevRightHandMessage = rightHandMessage; |
|
265 } |
|
266 } |
|
267 |
|
268 //On attend 25 ms. |
|
269 Thread.Sleep(25); |
|
270 |
|
271 //Si une gesture a été effectuée et que le délai d'attente est expiré. |
|
272 if (messageCreated && !gestureLocked && !modLocked) |
|
273 { |
|
274 //On débloque la détection de gesture et on supprime l'objet envoyant les messages OSC de gesture. |
|
275 messageCreated = false; |
|
276 gestureMessage = ""; |
|
277 } |
|
278 } |
|
279 } |
|
280 |
|
281 /* |
|
282 * Getters et Setters |
|
283 */ |
|
284 public void setTimerElapsing(int _timerElapsing) |
|
285 { |
|
286 timerElapsing = _timerElapsing; |
|
287 } |
|
288 |
|
289 public int getTimerElapsing() |
|
290 { |
|
291 return timerElapsing; |
|
292 } |
|
293 } |
|
294 } |