Projekt

Obecné

Profil

Stáhnout (8.36 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

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

    
52
        
53
        private Thread _thread;
54
        
55
        private readonly object _isRunningLock = new object();
56
        private bool _isRunning;
57

    
58
        private readonly object _actuatorPositionLock = new object();
59
        private Single3 _actuatorPosition;
60

    
61
        private volatile bool _isConnected;
62
        private volatile string _eotMsg;
63

    
64
        static Client()
65
        {
66
        }
67

    
68
        private Client()
69
        {
70
        }
71

    
72
        public void Start()
73
        {
74
            _thread = new Thread(ThreadProcedure);
75
            IsRunning = true;
76
            _thread.Start();
77
        }
78

    
79
        public void Stop()
80
        {
81
            IsRunning = false;
82
            _thread.Join();
83
        }
84

    
85
        public string EotMsg
86
        {
87
            get => _eotMsg;
88
            private set => _eotMsg = value;
89
        }
90

    
91
        public bool IsConnected
92
        {
93
            get => _isConnected;
94
            private set => _isConnected = value;
95
        }
96

    
97
        public Single3 ActuatorPosition
98
        {
99
            get
100
            {
101
                lock (_actuatorPositionLock)
102
                {
103
                    return _actuatorPosition;
104
                }
105
            }
106
            private set
107
            {
108
                lock (_actuatorPositionLock)
109
                {
110
                    _actuatorPosition = value;
111
                }
112
            } 
113
        }
114

    
115
        public bool IsRunning
116
        {
117
            get {
118
                lock (_isRunningLock)
119
                {
120
                    return _isRunning;
121
                }
122
            }
123
            private set
124
            {
125
                lock (_isRunningLock)
126
                {
127
                    _isRunning = value;
128
                }
129
            }
130
        }
131

    
132
        private void ThreadProcedure()
133
        {
134
            try
135
            {
136
                var client = new TcpClient(DefaultServer, DefaultPort);
137
                var stream = client.GetStream();
138
                BinaryReader reader = new BinaryReader(stream);
139
                BinaryWriter writer = new BinaryWriter(stream);
140
                IsConnected = true;
141
                
142
                writer.Write(ProtocolMagicId);
143
                writer.Write(ProtocolMagicValue);
144
                writer.Write(ProtocolVersionId);
145
                writer.Write(ProtocolVersionValue);
146
                
147
                try
148
                {
149
                    while (IsRunning && IsConnected)
150
                    {
151
                        var messageIdentifier = reader.ReadUInt16();
152
                        switch (messageIdentifier)
153
                        {
154
                            case ProtocolMagicId:
155
                                ProcessProtocolMagic(reader);
156
                                break;
157
                            case ProtocolVersionId:
158
                                ProcessProtocolVersion(reader);
159
                                break;
160
                            case PingId:
161
                                ProcessPing(reader, writer);
162
                                break;
163
                            case EotId:
164
                                ProcessEot(reader);
165
                                break;
166
                            case CurrentActuatorPositionId:
167
                                ProcessCurrentActuatorPosition(reader);
168
                                break;
169
                            default: //client tuto zpravu nezna
170
                                var sizeIdentifier = (UInt16) (messageIdentifier & 0xF000);
171
                                switch (sizeIdentifier)
172
                                {
173
                                    case Size8:
174
                                        Skip8(reader);
175
                                        break;
176
                                    case Size16:
177
                                        Skip16(reader);
178
                                        break;
179
                                    case Size32:
180
                                        Skip32(reader);
181
                                        break;
182
                                    case Size64:
183
                                        Skip64(reader);
184
                                        break;
185
                                    case Size128:
186
                                        Skip128(reader);
187
                                        break;
188
                                    case SizeVariable:
189
                                        SkipVariableLength(reader);
190
                                        break;
191
                                }
192

    
193
                                break;
194
                        }
195
                    }
196
                }
197
                finally
198
                {
199
                    stream.Close();
200
                    client.Close();
201
                    IsConnected = true;
202
                }
203
            }
204
            catch (Exception)
205
            {
206
                Console.WriteLine("failed to connect");
207
            }
208
        }
209

    
210

    
211
        private void Skip8(BinaryReader reader)
212
        {
213
            reader.ReadByte();
214
        }
215

    
216
        private void Skip16(BinaryReader reader)
217
        {
218
            reader.ReadUInt16();
219
        }
220

    
221
        private void Skip32(BinaryReader reader)
222
        {
223
            reader.ReadUInt32();
224
        }
225

    
226
        private void Skip64(BinaryReader reader)
227
        {
228
            reader.ReadUInt64();
229
        }
230

    
231
        private void Skip128(BinaryReader reader)
232
        {
233
            reader.ReadUInt64();
234
            reader.ReadUInt64();
235
        }
236

    
237
        private void SkipVariableLength(BinaryReader reader)
238
        {
239
            UInt32 numberOfBytes = reader.ReadUInt32();
240
            reader.ReadBytes((int) numberOfBytes);
241
        }
242

    
243
        private void ProcessCurrentActuatorPosition(BinaryReader reader)
244
        {
245
            var x = reader.ReadSingle();
246
            var y = reader.ReadSingle();
247
            var z = reader.ReadSingle();
248
            reader.ReadSingle(); // skip unused
249

    
250
            ActuatorPosition = new Single3(x, y, z);
251
        }
252

    
253
        private void ProcessEot(BinaryReader reader)
254
        {
255
            UInt32 numberOfBytes = reader.ReadUInt32();
256
            Byte[] buffer = reader.ReadBytes((int) numberOfBytes);
257
            EotMsg = Encoding.ASCII.GetString(buffer);
258
            IsConnected = false;
259
        }
260

    
261
        private void ProcessProtocolMagic(BinaryReader reader)
262
        {
263
            byte[] value = reader.ReadBytes(8);
264
            if (!value.SequenceEqual(ProtocolMagicValue))
265
            {
266
                IsConnected = false; // mozna vyhodit vyjimku
267
            }
268
        }
269

    
270
        private void ProcessProtocolVersion(BinaryReader reader)
271
        {
272
            UInt32 value = reader.ReadUInt32();
273
            if (value != ProtocolVersionValue)
274
            {
275
                IsConnected = false; // mozna vyhodit vyjimku
276
            }
277
        }
278

    
279
        private void ProcessPing(BinaryReader reader, BinaryWriter writer)
280
        {
281
            UInt64 pingValue = reader.ReadUInt64();
282
            writer.Write(pingValue);
283
        }
284
    }
285
}
(1-1/2)