public static string Decode_data(TransmittedData data)
 {
     if (data.MessageCode == Transmission.STRING_MESSAGE || data.MessageCode == Transmission.ERROR_MESSAGE)
     {
         //return BitConverter.ToString(data.data, data.length).Replace("-", " ");
         return(Encoding.ASCII.GetString(data.Data, 0, sizeof(byte) * data.Length));
     }
     return("Nope");
 }
        public static SerialPort Connect(string portName, int baudRate, int dataBits, StopBits stopBits, BootloaderFile bootloaderFile, Form1 parentForm)
        {
            SerialPort serialPort = new SerialPort(portName, DEFAULT_BAUDRATE, Parity.None, dataBits, stopBits);

            try
            {
                if (!serialPort.IsOpen)
                {
                    serialPort.Open();
                }
            }
            catch (UnauthorizedAccessException Ex)
            {
                Debug.WriteLine(Ex.ToString());
                Debug.WriteLine("Access is denied to the port.");
                serialPort.Close();
            }
            catch (ArgumentOutOfRangeException Ex)
            {
                Debug.WriteLine(Ex.ToString());
                Debug.WriteLine("One of the properties is invalid");
                serialPort.Close();
            }
            catch (IOException Ex)
            {
                Debug.WriteLine(Ex.ToString());
                Debug.WriteLine("The port is in an invalid state");
                serialPort.Close();
            }
            catch (InvalidOperationException Ex)
            {
                Debug.WriteLine(Ex.ToString());
                Debug.WriteLine("SerialPort is already open");
                serialPort.Close();
            }

            Debug.WriteLine("SerialPort is open");
            TransmittedData.StartCommunication(serialPort);
            TransmittedData.TransmissionOfData(serialPort, baudRate, bootloaderFile, ClientCodes.CONNECT, parentForm);
            return(serialPort);
        }
        public static void StartCommunication(SerialPort serialPort)
        {
            Debug.WriteLine("Waiting for the start code");

            //waiting for communication with SerialPort
            Debug.WriteLine("Waiting for communication");
            while (true)
            {
                if (serialPort.BytesToRead > 0)
                {
                    byte[] oneByteToRead = new byte[10];
                    serialPort.Read(oneByteToRead, 0, sizeof(byte) * 1);
                    int transmissionCode = BitConverter.ToInt32(oneByteToRead, 0);
                    if (transmissionCode == Transmission.START_CODE)
                    {
                        Debug.WriteLine("Session successful started");

                        break;
                    }
                    else
                    {
                        Debug.WriteLine("ERROR IN CODE");
                    }
                }
            }
            serialPort.Write(BitConverter.GetBytes(Transmission.START_CODE), 0, 1);
            Debug.WriteLine("Communication was started");
            while (true)
            {
                Utils.Wait_for_data(serialPort);
                TransmittedData recievedData = Receive.ReceiveData(serialPort);

                if (recievedData.MessageCode == Transmission.NEXT)
                {
                    Debug.WriteLine("Request for next block received");
                    break;
                }
            }
        }
        //Done
        public static TransmittedData ReceiveData(SerialPort serialPort)
        {
            TransmittedData recievedData = new TransmittedData(0, 0, new byte[5000000]);
            HeaderFormat    header;
            BodyFormat      body;

            while (true)
            {
                Thread.Sleep(10);
                try
                {
                    header = ReceiveHeader(serialPort);
                }
                catch (Exception)
                {
                    serialPort.DiscardInBuffer();
                    Debug.WriteLine("Wrong format Header");
                    continue;
                }
                if (!HeaderFormat.CheckHeaderCrc(header))
                {
                    serialPort.DiscardInBuffer();
                    Debug.WriteLine("Wrong CRC Header");
                    continue;
                }
                if (header.PacketNum + 1 == TransmittedData.packetCounter)
                {
                    serialPort.DiscardInBuffer();
                    Debug.WriteLine("Packet Number is invalid");
                    Send.SendACK(serialPort, TransmittedData.packetCounter);
                }
                Send.SendACK(serialPort, TransmittedData.packetCounter + 1);
                if (header.Length == 0)
                {
                    recievedData.MessageCode = header.MessageCode;
                    recievedData.Length      = header.Length;
                    return(recievedData);
                }
                break;
            }
            while (true)
            {
                HeaderFormat recievedHeader;
                try
                {
                    body           = ReceiveFullBody(serialPort, header.Length);
                    recievedHeader = new HeaderFormat(headerByteArrayCrutch);
                }
                catch (Exception)
                {
                    serialPort.DiscardInBuffer();
                    Debug.WriteLine("Wrong format Header");
                    continue;
                }
                if (!BodyFormat.CheckBodyCrc(body.Data, body.Crc))
                {
                    serialPort.DiscardInBuffer();
                    Debug.WriteLine("When receiving Full Data package, Header CRC is invalid");
                    continue;
                }
                if (recievedHeader.PacketNum + 1 == TransmittedData.packetCounter)
                {
                    serialPort.DiscardInBuffer();
                    Debug.WriteLine("Packet Number is invalid");
                    Send.SendACK(serialPort, TransmittedData.packetCounter);
                }
                if (recievedHeader.Length == 0 || !BodyFormat.CheckBodyCrc(body.Data, body.Crc))
                {
                    serialPort.DiscardInBuffer();
                    Debug.WriteLine("CRC of Full Body is invalid");
                    continue;
                }
                Send.SendACK(serialPort, TransmittedData.packetCounter + 1);
                recievedData.MessageCode = recievedHeader.MessageCode;
                recievedData.Length      = recievedHeader.Length;
                recievedData.Data        = body.Data;
                break;
            }
            TransmittedData.packetCounter++;
            return(recievedData);
        }
 public void DownloadData(SerialPort serialPort, int baudRate, BootloaderFile bootloaderFile, Form1 parentForm)
 {
     TransmittedData.TransmissionOfData(serialPort, baudRate, bootloaderFile, ClientCodes.DOWNLOAD_DATA, parentForm);
 }
 /// <summary>
 /// Client's point of entry
 /// </summary>
 /// <param name="portName"> Name of SerialPort</param>
 /// <param name="baudRate"> Baud rate for the serial port </param>
 /// <param name="dataBits"> Standard number of data bits per byte</param>
 /// <param name="stopBits">Stop Bits for SerialPort </param>
 /// <param name="bootloaderFile">binary data to transmit</param>
 public void Upload(SerialPort serialPort, int baudRate, BootloaderFile bootloaderFile, Form1 parentForm)
 {
     TransmittedData.TransmissionOfData(serialPort, baudRate, bootloaderFile, ClientCodes.UPLOAD, parentForm);
 }
 public static void Disconnect(SerialPort serialPort, int baudRate, BootloaderFile bootloaderFile, Form1 parentForm)
 {
     TransmittedData.TransmissionOfData(serialPort, baudRate, bootloaderFile, ClientCodes.DISCONNECT, parentForm);
     serialPort.DiscardInBuffer();
     serialPort.Close();
 }
        public static void TransmissionOfData(SerialPort serialPort, int baudRate, BootloaderFile bootloaderFile, int clientCode, Form1 parentForm)
        {
            int    currentBytesSended = 0;
            String decodedData;

            state = 0;

            while (true)
            {
                ChangeCode(clientCode);
                if (transmissionCode == Transmission.BAUDRATE)
                {
                    if (serialPort.BaudRate != baudRate)
                    {
                        Send.SendData(serialPort, Transmission.BAUDRATE, sizeof(int), BitConverter.GetBytes(baudRate));
                        serialPort.BaudRate = baudRate;
                    }
                    else if (breakFlag == 1)
                    {
                        breakFlag = 0;
                        break;
                    }
                    else
                    {
                        continue;
                    }
                }
                if (transmissionCode == Transmission.FIRMWARE_INFO_FROM_BOOTLOADER)
                {
                    byte[] firmware = new byte[1];
                    Send.SendData(serialPort, Transmission.FIRMWARE_INFO_FROM_BOOTLOADER, 0, firmware);
                }
                if (transmissionCode == Transmission.FIRMWARE_INFO)
                {
                    Send.SendData(serialPort, Transmission.FIRMWARE_INFO, bootloaderFile.GetMetadataAsByteArray().Length, bootloaderFile.GetMetadataAsByteArray());
                    Debug.WriteLine(BitConverter.ToString(bootloaderFile.GetMetadataAsByteArray()));
                    Debug.WriteLine("Firmware Info is sended");
                }
                if (transmissionCode == Transmission.ADDRESSES_INFO)
                {
                    Send.SendData(serialPort, Transmission.ADDRESSES_INFO, bootloaderFile.FirstBlock.Length, bootloaderFile.FirstBlock);
                    Debug.WriteLine(BitConverter.ToString(bootloaderFile.FirstBlock));
                    Debug.WriteLine("Addresses Info is sended");
                }
                if (transmissionCode == Transmission.DOWNLOAD_CODE)
                {
                    byte[] downloadCodeUselessArray = new byte[1];
                    Send.SendData(serialPort, Transmission.DOWNLOAD_CODE, 0, downloadCodeUselessArray);
                    Debug.WriteLine("Code Downloading statred");
                }
                if (transmissionCode == Transmission.DOWNLOAD_DATA)
                {
                    byte[] downloadDataUselessArray = new byte[1];
                    Send.SendData(serialPort, Transmission.DOWNLOAD_DATA, 0, downloadDataUselessArray);
                    Debug.WriteLine("Data Downloading statred");
                }
                if (transmissionCode == Transmission.PROGRAM)
                {
                    byte[] program = BitConverter.GetBytes(bootloaderFile.Data.Length);
                    Debug.WriteLine($"Data len is {bootloaderFile.Data.Length}");
                    Send.SendData(serialPort, Transmission.PROGRAM, program.Length, program);
                }
                //перенести
                if (transmissionCode == Transmission.RELEASE)
                {
                    byte[] release = new byte[1];
                    Send.SendData(serialPort, Transmission.RELEASE, 0, release);
                    Debug.WriteLine("Bye-Bye");
                    break;
                }
                if (breakFlag == 1)
                {
                    breakFlag = 0;
                    break;
                }

                while (true)
                {
                    //Utils.Wait_for_data(serialPort);
                    TransmittedData recievedData = Receive.ReceiveData(serialPort);

                    if (recievedData.MessageCode == Transmission.NEXT)
                    {
                        Debug.WriteLine("Request for next block received");
                        break;
                    }
                    else if (recievedData.MessageCode == Transmission.END_OF_DOWNLOAD)
                    {
                        //добавить флаг только для кода
                        Debug.WriteLine("Code/Data Downloaded");
                        //downloadedSmth = recievedMetaInfo.GetMetadataAsByteArray();
                        recievedMetaInfo.FirstBlock = downloadedCode.Take(16).ToArray();
                        recievedMetaInfo.Data       = downloadedCode.Skip(16).ToArray();
                        //downloadedSmth = recievedMetaInfo.GetMetadataAsByteArray().Concat(downloadedCode).ToArray();
                        //вынести в форму
                        //var fileStream = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write);
                        //using var binaryWriter = new BinaryWriter(fileStream, Encoding.ASCII);
                        //binaryWriter.Write(downloadedSmth);
                    }
                    else if (recievedData.MessageCode == Transmission.REQUEST)
                    {
                        Debug.WriteLine($"{recievedData.Data}");
                        uint f = BitConverter.ToUInt32(recievedData.Data, 0);
                        uint t = BitConverter.ToUInt32(recievedData.Data, 4);
                        Debug.WriteLine($"{f} {t} and len of sended data is {bootloaderFile.Data.Skip((int)f).Take((int)(t - f)).ToArray().Length}");
                        Send.SendData(serialPort, Transmission.PROGRAM, bootloaderFile.Data.Skip((int)f).Take((int)(t - f)).ToArray().Length, bootloaderFile.Data.Skip((int)f).Take((int)(t - f)).ToArray());
                        currentBytesSended += ((int)(t - f));
                        parentForm.ProgressChanged((int)(100 * currentBytesSended / bootloaderFile.Data.Length));
                        continue;
                    }
                    else if (recievedData.MessageCode == Transmission.FIRMWARE_INFO_FROM_BOOTLOADER)
                    {
                        recievedMetaInfo.GetMetadataFromByteArray(recievedData.Data);
                        Debug.WriteLine("MetaInfo was recieved");
                        continue;
                    }
                    else if (recievedData.MessageCode == Transmission.PROGRAM)
                    {
                        downloadedCode = downloadedCode.Concat(recievedData.Data).ToArray();
                    }
                    else if (recievedData.MessageCode == Transmission.DATA)
                    {
                        downloadedData = downloadedData.Concat(recievedData.Data).ToArray();
                    }
                    else
                    {
                        decodedData = Utils.Decode_data(recievedData);
                        Debug.WriteLine($"Data: {decodedData}");
                        continue;
                    }
                }

                /*
                 * switch (flag) {
                 *  //Que
                 *  case Transmission.BAUDRATE:
                 *      if (serialPort.BaudRate != baudRate)
                 *      {
                 *          Send.SendData(serialPort, Transmission.BAUDRATE, sizeof(int), BitConverter.GetBytes(baudRate));
                 *          serialPort.BaudRate = baudRate;
                 *          continue;
                 *      }
                 *      break;
                 *  case Transmission.FIRMWARE_INFO_FROM_BOOTLOADER:
                 *      byte[] firmware = new byte[1];
                 *      Send.SendData(serialPort, Transmission.FIRMWARE_INFO_FROM_BOOTLOADER, 0, firmware);
                 *      continue;
                 *
                 *  case Transmission.FIRMWARE_INFO:
                 *      Send.SendData(serialPort, Transmission.FIRMWARE_INFO, bootloaderFile.GetMetadataAsByteArray().Length, bootloaderFile.GetMetadataAsByteArray());
                 *      Debug.WriteLine("Firmware Info is sended");
                 *      continue;
                 *  case Transmission.ADDRESSES_INFO:
                 *      Send.SendData(serialPort, Transmission.FIRMWARE_INFO, bootloaderFile.FirstBlock.Length, bootloaderFile.FirstBlock);
                 *      Debug.WriteLine("Addresses Info is sended");
                 *      continue;
                 *  case Transmission.PROGRAM:
                 *      byte[] program = BitConverter.GetBytes(bootloaderFile.Data.Length);
                 *      Debug.WriteLine($"Data len is {bootloaderFile.Data.Length}");
                 *      Send.SendData(serialPort, Transmission.PROGRAM, program.Length, program);
                 *      continue;
                 *  case Transmission.RELEASE:
                 *      byte[] release = new byte[1];
                 *      Send.SendData(serialPort, Transmission.RELEASE, 0, release);
                 *      Debug.WriteLine("Bye-Bye");
                 *      break;
                 * }
                 */
            }
        }