ClientAPI - .Net
|
00001 using System; 00002 using System.IO; 00003 using System.Threading; 00004 00005 namespace ebl_arduino 00006 { 00010 public abstract class SerialProtocol 00011 { 00015 public enum MessageTypes 00016 { 00020 DEBUG = 0x01, 00021 00025 MESSAGE = 0x02, 00026 00030 MESSAGE_ACKNOWLEDGE = 0x03, 00031 00035 DISCOVERY_REQUEST = 0x04, 00036 00040 DISCOVERY_RESPONSE = 0x05 00041 } 00042 00046 public class AdvancedSerialMessage 00047 { 00051 public MessageTypes Type = MessageTypes.MESSAGE; 00052 00056 public byte ID; 00057 00061 public byte Size = 0; 00062 00066 public byte[] Payload; 00067 } 00068 00072 public enum ConnectionState 00073 { 00077 ReadingSTX, 00078 00082 ReadingETX, 00083 00087 ReadingHeader, 00088 00092 ReadingPayload 00093 } 00094 00098 public const int MESSAGE_HEADER_SIZE = 3; 00099 00103 public const int MESSAGE_DELIMITER_SIZE = 1; 00104 00108 public const int MESSAGE_MAX_PAYLOAD_SIZE = 32; 00109 00113 public const int MESSAGE_SIZE = MESSAGE_MAX_PAYLOAD_SIZE + MESSAGE_HEADER_SIZE; 00114 00118 public const byte STX = 0x02; 00119 00123 public const byte ETX = 0x03; 00124 00128 public delegate void MessageReceivedCallback(AdvancedSerialMessage Message); 00129 00133 public event MessageReceivedCallback MessageReceived; 00134 00138 protected Stream ConnectionStream; 00139 00144 public abstract bool IsConnected(); 00145 00149 public abstract void Close(); 00150 00154 public int MessageTimeout = 2000; 00155 00156 private AdvancedSerialMessage InputMessage = new AdvancedSerialMessage(); 00157 private byte[] InputBuffer = new byte[MESSAGE_SIZE]; 00158 private byte[] InputDelimiter = new byte[1]; 00159 private ConnectionState State = ConnectionState.ReadingSTX; 00160 private int ReceivedBytes; 00161 private int RequestedBytes; 00162 00167 public void Send(AdvancedSerialMessage Message) 00168 { 00169 this.Send(Message.Type, Message.ID, Message.Size, Message.Payload); 00170 } 00171 00179 public void Send(MessageTypes Type, byte ID, byte Size, byte[] Payload) 00180 { 00181 if (Size >= 0 && Size <= MESSAGE_MAX_PAYLOAD_SIZE) 00182 { 00183 this.ConnectionStream.WriteByte(STX); 00184 this.ConnectionStream.WriteByte((byte)Type); 00185 this.ConnectionStream.WriteByte(ID); 00186 this.ConnectionStream.WriteByte(Size); 00187 if (Size > 0) this.ConnectionStream.Write(Payload, 0, Size); 00188 this.ConnectionStream.WriteByte(ETX); 00189 00190 //wait for confirmations 00191 if (Type == MessageTypes.MESSAGE || 00192 Type == MessageTypes.DISCOVERY_REQUEST) 00193 { 00194 lock (this.ConnectionStream) 00195 { 00196 if (!Monitor.Wait(this.ConnectionStream, this.MessageTimeout)) 00197 throw new TimeoutException("Device not responding."); 00198 } 00199 } 00200 } 00201 else 00202 { 00203 throw new TimeoutException("Accepted message's payload size between 0 and " + MESSAGE_MAX_PAYLOAD_SIZE + "."); 00204 } 00205 } 00206 00211 public void Send(MessageTypes Type) 00212 { 00213 this.Send(Type, 0, 0, null); 00214 } 00215 00219 public void Flush() 00220 { 00221 byte[] flushdata = new byte[MESSAGE_DELIMITER_SIZE+MESSAGE_SIZE+MESSAGE_DELIMITER_SIZE]; 00222 for (int i = 0; i < flushdata.Length; i++) 00223 { 00224 flushdata[i] = (byte)0x00; 00225 } 00226 this.ConnectionStream.Write(flushdata, 0, flushdata.Length); 00227 this.ConnectionStream.Flush(); 00228 } 00229 00233 protected void Receive() 00234 { 00235 this.ReceivedBytes = 0; 00236 00237 if (this.DataReceivingCallback == null) 00238 this.DataReceivingCallback = new AsyncCallback(DataReceiving); 00239 00240 try 00241 { 00242 switch (this.State) 00243 { 00244 case ConnectionState.ReadingSTX: 00245 case ConnectionState.ReadingETX: 00246 this.ConnectionStream.BeginRead(this.InputDelimiter, 0, MESSAGE_DELIMITER_SIZE, this.DataReceivingCallback, null); 00247 this.RequestedBytes = MESSAGE_DELIMITER_SIZE; 00248 break; 00249 00250 case ConnectionState.ReadingHeader: 00251 this.ConnectionStream.BeginRead(this.InputBuffer, 0, MESSAGE_HEADER_SIZE, this.DataReceivingCallback, null); 00252 this.RequestedBytes = MESSAGE_HEADER_SIZE; 00253 break; 00254 00255 case ConnectionState.ReadingPayload: 00256 this.ConnectionStream.BeginRead(this.InputBuffer, 0, this.InputMessage.Size, this.DataReceivingCallback, null); 00257 this.RequestedBytes = this.InputMessage.Size; 00258 break; 00259 } 00260 } 00261 catch (Exception) 00262 { 00263 this.Close(); 00264 } 00265 } 00266 00267 private AsyncCallback DataReceivingCallback; 00268 private void DataReceiving(IAsyncResult ar) 00269 { 00270 int ReceivedSize = 0; 00271 try 00272 { 00273 ReceivedSize = this.ConnectionStream.EndRead(ar); 00274 } 00275 catch (Exception) 00276 { 00277 this.Close(); 00278 return; 00279 } 00280 00281 //verify if buffer was completelly received 00282 this.ReceivedBytes += ReceivedSize; 00283 if (this.ReceivedBytes < this.RequestedBytes) 00284 { 00285 try 00286 { 00287 this.ConnectionStream.BeginRead(this.InputBuffer, ReceivedBytes, RequestedBytes - ReceivedBytes, this.DataReceivingCallback, null); 00288 } 00289 catch (Exception) 00290 { 00291 this.Close(); 00292 } 00293 return; 00294 } 00295 00296 switch (this.State) 00297 { 00298 case ConnectionState.ReadingSTX: 00299 if (this.InputDelimiter[0] == STX) 00300 { 00301 this.State = ConnectionState.ReadingHeader; 00302 } 00303 break; 00304 00305 case ConnectionState.ReadingHeader: 00306 this.InputMessage.Type = (MessageTypes)this.InputBuffer[0]; 00307 this.InputMessage.Size = this.InputBuffer[1]; 00308 if (this.InputMessage.Size == 0) 00309 { 00310 //payload is empty 00311 this.State = ConnectionState.ReadingETX; 00312 } 00313 else if (this.InputMessage.Size > 0 && this.InputMessage.Size <= MESSAGE_MAX_PAYLOAD_SIZE) 00314 { 00315 //read 00316 this.State = ConnectionState.ReadingPayload; 00317 } 00318 else 00319 { 00320 //avoid wrong sized messages 00321 this.State = ConnectionState.ReadingSTX; 00322 } 00323 break; 00324 00325 case ConnectionState.ReadingPayload: 00326 Array.Copy(this.InputBuffer, this.InputMessage.Payload, this.InputMessage.Size); 00327 this.State = ConnectionState.ReadingETX; 00328 break; 00329 00330 case ConnectionState.ReadingETX: 00331 if (this.InputDelimiter[0] == ETX) 00332 { 00333 if (this.InputMessage.Type == MessageTypes.DISCOVERY_RESPONSE || 00334 this.InputMessage.Type == MessageTypes.MESSAGE_ACKNOWLEDGE) 00335 { 00336 lock (this.ConnectionStream) 00337 { 00338 Monitor.Pulse(this.ConnectionStream); 00339 } 00340 } 00341 else if (this.InputMessage.Type == MessageTypes.MESSAGE) 00342 { 00343 this.Send(MessageTypes.MESSAGE_ACKNOWLEDGE); 00344 this.MessageReceived(this.InputMessage); 00345 } 00346 else if (this.InputMessage.Type == MessageTypes.DISCOVERY_REQUEST) 00347 { 00348 this.Send(MessageTypes.DISCOVERY_RESPONSE); 00349 } 00350 } 00351 00352 this.State = ConnectionState.ReadingSTX; 00353 break; 00354 } 00355 00356 this.Receive(); 00357 } 00358 } 00359 }