Projekt

Obecné

Profil

Stáhnout (12.3 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 PongId = 0x3005;
40
        private const UInt16 EotId = 0xF006;
41
        private const UInt16 CurrentActuatorPositionId = 0x4003;
42
        private const UInt16 CurrentDirectionVectorId = 0x4007;
43
        private const UInt16 DesiredDirectionVectorId = 0x4008;
44
        private const UInt16 CurveId = 0xF009;
45

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

    
56
        private const UInt32 PointLength = 12;
57

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

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

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

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

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

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

    
80
        static Client()
81
        {
82
        }
83

    
84
        private Client()
85
        {
86
        }
87

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

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

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

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

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

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

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

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

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

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

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

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

    
307

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

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

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

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

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

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

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

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

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

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

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

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

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

    
376
            for(int i = 0; i < numberOfPoints; i++)
377
            {
378
                var x = reader.ReadSingle();
379
                var y = reader.ReadSingle();
380
                var 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

    
421
            writer.Write(PongId);
422
            writer.Write(pingValue);
423
        }
424
    }
425
}
(3-3/16)