Beispiel #1
0
        /// <inheritdoc />
        public void Send(string serialNumber, ICommandList commands)
        {
            if (!commands.CanSend)
            {
                InvalidOperationException e = new("CommandList was not made ready before Send was called");
                _logger.LogError(e, "Send failed.");
                throw e;
            }

            Location?location = _devices.GetLocation(serialNumber);

            if (location == null)
            {
                throw new InvalidOperationException("Location was null when sending to serial number.");
            }

            lock (_deviceLocker[location.Value])
            {
                const int delayInMilliseconds = 10;

                double?millisecondsSinceLastSend = null;

                if (_lastSends.ContainsKey(location.Value))
                {
                    millisecondsSinceLastSend = (DateTime.UtcNow - _lastSends[location.Value]).TotalMilliseconds;
                }

                if (millisecondsSinceLastSend != null && millisecondsSinceLastSend < delayInMilliseconds)
                {
                    Thread.Sleep(delayInMilliseconds - (int)millisecondsSinceLastSend);
                }

                _ = _devices.TryGetValue(location.Value, out IUsbDevice? device);

                if (device == null)
                {
                    _logger.LogCritical("Device was null when getting it using location.");
                    return;
                }

                bool  shouldRetry        = false;
                int   retryCount         = 0;
                int   currentFrameNumber = 0;
                Error writeResult        = Error.Other;
                do
                {
                    for (int frameNumber = currentFrameNumber; frameNumber < commands.TotalFrames;)
                    {
                        // Generate the write buffer and write to PM
                        byte[]            writeBuffer = commands.GetFrame(frameNumber).Select(b => (byte)b).ToArray();
                        UsbEndpointWriter writer      = device.OpenEndpointWriter(LibUsbDotNet.Main.WriteEndpointID.Ep02);
                        try
                        {
                            writeResult = writer.Write(writeBuffer, 100, out int writeBufferSize);

                            if (writeResult == Error.Io)
                            {
                                CloseAndOpen(device);
                                shouldRetry = retryCount++ < 2;
                                continue;
                            }

                            shouldRetry = false;
                            frameNumber++;
                        }
                        catch (Exception e)
                        {
                            _logger.LogWarning(e, "Exception occurred during writing. Buffer: [{WriteBuffer}]", writeBuffer);
                        }
                        finally
                        {
                            _lastSends[location.Value] = DateTime.UtcNow;
                        }
                    }
                } while (shouldRetry);

                if (writeResult != Error.Success)
                {
                    _logger.LogWarning("An error occurred while writing. Result: [{WriteResult}])", writeResult);
                    return;
                }

                byte[] readBuffer = new byte[1024];
                Error  readResult = Error.Other;
                retryCount  = 0;
                shouldRetry = false;
                do
                {
                    UsbEndpointReader reader = device.OpenEndpointReader(LibUsbDotNet.Main.ReadEndpointID.Ep01);
                    try
                    {
                        readResult = reader.Read(readBuffer, 100, out int responseDataSize);

                        if (readResult == Error.Io)
                        {
                            CloseAndOpen(device);
                            shouldRetry = retryCount++ < 2;
                            continue;
                        }

                        if (commands.TotalFrames > 1)
                        {
                            // This is required if there was more than one packet.
                            // TODO: Improve this so that results from each packet are read in.
                            reader.ReadFlush();
                        }

                        shouldRetry = false;
                    }
                    catch (Exception e)
                    {
                        _logger.LogWarning(e, "Exception occurred during reading. Buffer: [{ReadBuffer}]", readBuffer);
                        return;
                    }
                } while (shouldRetry);

                if (readResult != Error.Success)
                {
                    _logger.LogWarning("An error occurred while reading. Result: [{ReadResult}])", readResult);
                    return;
                }

                IResponseReader responseReader        = new ResponseReader(readBuffer.Select(b => (uint)b));
                bool            responseReaderSuccess = commands.Read(responseReader);

                if (!responseReaderSuccess)
                {
                    _logger.LogWarning("An error occurred while consuming the read buffer. Result: [{ResponseReadResult}])", responseReaderSuccess);
                    return;
                }
            }
        }