Projekt

Obecné

Profil

Stáhnout (12.2 KB) Statistiky
| Větev: | Tag: | Revize:
1
using System;
2
using System.Net.Sockets;
3
using System.Threading;
4
using System.IO;
5
using System.Linq;
6
using System.Text;
7

    
8
namespace DeltaRobotVr
9
{
10
    public readonly struct Single3
11
    {
12
        public float X { get; }
13
        public float Y { get; }
14
        public float Z { get; }
15

    
16
        public Single3(float x, float y, float z)
17
        {
18
            X = x;
19
            Y = y;
20
            Z = z;
21
        }
22

    
23
        public override string ToString() => "Single3[ " + X + " " + Y + " " + Z + " ]";
24
    }
25

    
26
    public sealed class Client
27
    {
28
        // singleton instance
29
        public static readonly Client Instance = new Client();
30

    
31
        // default server
32
        private const string DefaultServer = "127.0.0.1";
33
        private const int DefaultPort = 4242;
34

    
35
        // protocol constants
36
        private const UInt16 ProtocolMagicId = 0x3001;
37
        private const UInt16 ProtocolVersionId = 0x2002;
38
        private const UInt16 PingId = 0x3004;
39
        private const UInt16 EotId = 0xF006;
40
        private const UInt16 CurrentActuatorPositionId = 0x4003;
41
        private const UInt16 CurrentDirectionVectorId = 0x4007;
42
        private const UInt16 DesiredDirectionVectorId = 0x4008;
43
        private const UInt16 CurveId = 0xF009;
44

    
45
        private const UInt16 Size8 = 0x0000;
46
        private const UInt16 Size16 = 0x1000;
47
        private const UInt16 Size32 = 0x2000;
48
        private const UInt16 Size64 = 0x3000;
49
        private const UInt16 Size128 = 0x4000;
50
        private const UInt16 SizeVariable = 0xF000;
51
        
52
        private static readonly byte[] ProtocolMagicValue = Encoding.ASCII.GetBytes("DeltaRVr");
53
        private const UInt32 ProtocolVersionValue = 1;
54

    
55
        private const UInt32 PointLength = 12;
56

    
57
        
58
        private Thread _thread;
59
        
60
        private readonly object _isRunningLock = new object();
61
        private bool _isRunning;
62

    
63
        private readonly object _actuatorPositionLock = new object();
64
        private Single3 _actuatorPosition;
65

    
66
        private readonly object _currentDirectionVectorLock = new object();
67
        private Single3 _currentDirectionVector;
68

    
69
        private readonly object _desiredDirectionVectorLock = new object();
70
        private Single3 _desiredDirectionVector;
71

    
72
        private readonly object _curveLock = new object();
73
        private Single3[] _curve;
74
        private long _curveCounter = 0;
75

    
76
        private volatile bool _isConnected;
77
        private volatile string _eotMsg;
78

    
79
        static Client()
80
        {
81
        }
82

    
83
        private Client()
84
        {
85
        }
86

    
87
        public void Start()
88
        {
89
            _thread = new Thread(ThreadProcedure);
90
            IsRunning = true;
91
            _thread.Start();
92
        }
93

    
94
        public void Stop()
95
        {
96
            IsRunning = false;
97
            _thread.Join();
98
        }
99

    
100
        public string EotMsg
101
        {
102
            get => _eotMsg;
103
            private set => _eotMsg = value;
104
        }
105

    
106
        public bool IsConnected
107
        {
108
            get => _isConnected;
109
            private set => _isConnected = value;
110
        }
111

    
112
        public Single3 ActuatorPosition
113
        {
114
            get
115
            {
116
                lock (_actuatorPositionLock)
117
                {
118
                    return _actuatorPosition;
119
                }
120
            }
121
            private set
122
            {
123
                lock (_actuatorPositionLock)
124
                {
125
                    _actuatorPosition = value;
126
                }
127
            } 
128
        }
129

    
130
        public Single3 CurrentDirectionVector
131
        {
132
            get
133
            {
134
                lock (_currentDirectionVectorLock)
135
                {
136
                    return _currentDirectionVector;
137
                }
138
            }
139
            private set
140
            {
141
                lock (_currentDirectionVectorLock)
142
                {
143
                    _currentDirectionVector = value;
144
                }
145
            }
146
        }
147

    
148
        public Single3 DesiredDirectionVector
149
        {
150
            get
151
            {
152
                lock (_desiredDirectionVectorLock)
153
                {
154
                    return _desiredDirectionVector;
155
                }
156
            }
157
            private set
158
            {
159
                lock (_desiredDirectionVectorLock)
160
                {
161
                    _desiredDirectionVector = value;
162
                }
163
            }
164
        }
165

    
166
        public Single3[] Curve
167
        {
168
            get
169
            {
170
                lock (_curveLock)
171
                {
172
                    return _curve;
173
                }
174
            }
175
            private set
176
            {
177
                lock (_curveLock)
178
                {
179
                    _curve = value;
180
                }
181
            }
182
        }
183

    
184
        public long CurveCounter
185
        {
186
            get
187
            {
188
                lock (_curveLock)
189
                {
190
                    return _curveCounter;
191
                }
192
            }
193
            private set
194
            {
195
                lock (_curveLock)
196
                {
197
                    _curveCounter = value;
198
                }
199
            }
200
        }
201

    
202
        public bool IsRunning
203
        {
204
            get {
205
                lock (_isRunningLock)
206
                {
207
                    return _isRunning;
208
                }
209
            }
210
            private set
211
            {
212
                lock (_isRunningLock)
213
                {
214
                    _isRunning = value;
215
                }
216
            }
217
        }
218

    
219
        private void ThreadProcedure()
220
        {
221
            try
222
            {
223
                var client = new TcpClient(DefaultServer, DefaultPort);
224
                var stream = client.GetStream();
225
                BinaryReader reader = new BinaryReader(stream);
226
                BinaryWriter writer = new BinaryWriter(stream);
227
                IsConnected = true;
228
                
229
                writer.Write(ProtocolMagicId);
230
                writer.Write(ProtocolMagicValue);
231
                writer.Write(ProtocolVersionId);
232
                writer.Write(ProtocolVersionValue);
233
                
234
                try
235
                {
236
                    while (IsRunning && IsConnected)
237
                    {
238
                        var messageIdentifier = reader.ReadUInt16();
239
                        switch (messageIdentifier)
240
                        {
241
                            case ProtocolMagicId:
242
                                ProcessProtocolMagic(reader);
243
                                break;
244
                            case ProtocolVersionId:
245
                                ProcessProtocolVersion(reader);
246
                                break;
247
                            case PingId:
248
                                ProcessPing(reader, writer);
249
                                break;
250
                            case EotId:
251
                                ProcessEot(reader);
252
                                break;
253
                            case CurrentActuatorPositionId:
254
                                ProcessCurrentActuatorPosition(reader);
255
                                break;
256
                            case CurrentDirectionVectorId:
257
                                ProcessCurrentDirectionVector(reader);
258
                                break;
259
                            case DesiredDirectionVectorId:
260
                                ProcessDesiredDirectionVector(reader);
261
                                break;
262
                            case CurveId:
263
                                ProcessCurve(reader);
264
                                break;
265
                            default: //client tuto zpravu nezna
266
                                var sizeIdentifier = (UInt16) (messageIdentifier & 0xF000);
267
                                switch (sizeIdentifier)
268
                                {
269
                                    case Size8:
270
                                        Skip8(reader);
271
                                        break;
272
                                    case Size16:
273
                                        Skip16(reader);
274
                                        break;
275
                                    case Size32:
276
                                        Skip32(reader);
277
                                        break;
278
                                    case Size64:
279
                                        Skip64(reader);
280
                                        break;
281
                                    case Size128:
282
                                        Skip128(reader);
283
                                        break;
284
                                    case SizeVariable:
285
                                        SkipVariableLength(reader);
286
                                        break;
287
                                }
288

    
289
                                break;
290
                        }
291
                    }
292
                }
293
                finally
294
                {
295
                    stream.Close();
296
                    client.Close();
297
                    IsConnected = true;
298
                }
299
            }
300
            catch (Exception)
301
            {
302
                Console.WriteLine("failed to connect");
303
            }
304
        }
305

    
306

    
307
        private void Skip8(BinaryReader reader)
308
        {
309
            reader.ReadByte();
310
        }
311

    
312
        private void Skip16(BinaryReader reader)
313
        {
314
            reader.ReadUInt16();
315
        }
316

    
317
        private void Skip32(BinaryReader reader)
318
        {
319
            reader.ReadUInt32();
320
        }
321

    
322
        private void Skip64(BinaryReader reader)
323
        {
324
            reader.ReadUInt64();
325
        }
326

    
327
        private void Skip128(BinaryReader reader)
328
        {
329
            reader.ReadUInt64();
330
            reader.ReadUInt64();
331
        }
332

    
333
        private void SkipVariableLength(BinaryReader reader)
334
        {
335
            UInt32 numberOfBytes = reader.ReadUInt32();
336
            reader.ReadBytes((int) numberOfBytes);
337
        }
338

    
339
        private void ProcessCurrentActuatorPosition(BinaryReader reader)
340
        {
341
            var x = reader.ReadSingle();
342
            var y = reader.ReadSingle();
343
            var z = reader.ReadSingle();
344
            reader.ReadSingle(); // skip unused
345

    
346
            ActuatorPosition = new Single3(x, y, z);
347
        }
348

    
349
        private void ProcessCurrentDirectionVector(BinaryReader reader)
350
        {
351
            var x = reader.ReadSingle();
352
            var y = reader.ReadSingle();
353
            var z = reader.ReadSingle();
354
            reader.ReadSingle(); // skip unused
355

    
356
            CurrentDirectionVector = new Single3(x, y, z);
357
        }
358

    
359
        private void ProcessDesiredDirectionVector(BinaryReader reader)
360
        {
361
            var x = reader.ReadSingle();
362
            var y = reader.ReadSingle();
363
            var z = reader.ReadSingle();
364
            reader.ReadSingle(); // skip unused
365

    
366
            DesiredDirectionVector = new Single3(x, y, z);
367
        }
368

    
369
        private void ProcessCurve(BinaryReader reader)
370
        {
371
            UInt32 numberOfBytes = reader.ReadUInt32();
372
            UInt32 numberOfPoints = numberOfBytes / PointLength;
373
            Single3[] curve = new Single3[numberOfPoints];
374
            var x, y, z;
375

    
376
            for(int i = 0; i < numberOfPoints; i++)
377
            {
378
                x = reader.ReadSingle();
379
                y = reader.ReadSingle();
380
                z = reader.ReadSingle();
381
                curve[i] = new Single3(x, y, z);
382
            }
383

    
384
            lock(_curveLock)
385
            {
386
                CurveCounter++;
387
                Curve = curve;
388
            }
389
        }
390

    
391
        private void ProcessEot(BinaryReader reader)
392
        {
393
            UInt32 numberOfBytes = reader.ReadUInt32();
394
            Byte[] buffer = reader.ReadBytes((int) numberOfBytes);
395
            EotMsg = Encoding.ASCII.GetString(buffer);
396
            IsConnected = false;
397
        }
398

    
399
        private void ProcessProtocolMagic(BinaryReader reader)
400
        {
401
            byte[] value = reader.ReadBytes(8);
402
            if (!value.SequenceEqual(ProtocolMagicValue))
403
            {
404
                IsConnected = false;
405
            }
406
        }
407

    
408
        private void ProcessProtocolVersion(BinaryReader reader)
409
        {
410
            UInt32 value = reader.ReadUInt32();
411
            if (value != ProtocolVersionValue)
412
            {
413
                IsConnected = false;
414
            }
415
        }
416

    
417
        private void ProcessPing(BinaryReader reader, BinaryWriter writer)
418
        {
419
            UInt64 pingValue = reader.ReadUInt64();
420
            writer.Write(pingValue);
421
        }
422
    }
423
}
(1-1/2)