예제 #1
0
        public override void ThreadFunction()
        {
            ErrorCallback(this, "Network processing startup.", "", false);

            bool should_exit = false;

            byte[]         remote_bytes = Array.Empty <byte>();
            NetworkHeader  read_header  = null;
            Utf8JsonWriter jsonwriter;

            lock (_thread_interlock)
            {
                jsonwriter = new Utf8JsonWriter(DeviceStream);
                CommandQueue.Clear();
            }

            byte[] read_buffer = new byte[block_size];
            void DataReader()
            {
                try
                {
                    lock (_thread_interlock) DeviceStream.BeginRead(read_buffer, 0, read_buffer.Length, delegate(IAsyncResult ar)
                        {
                            try
                            {
                                lock (_thread_interlock)
                                {
                                    if (DeviceStream == null)
                                    {
                                        return;
                                    }
                                    int len = DeviceStream.EndRead(ar);
                                    int pos = remote_bytes.Length;
                                    Array.Resize(ref remote_bytes, pos + len);
                                    Buffer.BlockCopy(read_buffer, 0, remote_bytes, pos, len);
                                }
                            }
                            catch (Exception e)
                            {
                                bool exiting;
                                lock (_thread_interlock) exiting = _thread_end;
                                if (!exiting)
                                {
                                    ErrorCallback(this, "Network error.", e.Message, false);
                                }
                            }
                            DataReader();
                        }, null);
                }
                catch (Exception e)
                {
                    bool exiting;
                    lock (_thread_interlock) exiting = _thread_end;
                    if (!exiting)
                    {
                        ErrorCallback(this, "Network error.", e.Message, false);
                    }
                }
            }

            DataReader();

            while (!should_exit)
            {
                Thread.Yield();

                long consumed = 0;
                if (read_header == null)
                {
                    try
                    {
                        lock (_thread_interlock)
                        {
                            if (remote_bytes.Length > 0)
                            {
                                Utf8JsonReader jsonreader = new Utf8JsonReader(new ReadOnlySpan <byte>(remote_bytes));
                                read_header = JsonSerializer.Deserialize <NetworkHeader>(ref jsonreader);
                                consumed    = jsonreader.BytesConsumed;
                            }
                        }
                    }
                    catch (JsonException) { }
                }
                else
                {
                    CommandBase received_command = null;
                    try
                    {
                        lock (_thread_interlock)
                        {
                            if (remote_bytes.Length > 0)
                            {
                                Utf8JsonReader jsonreader = new Utf8JsonReader(new ReadOnlySpan <byte>(remote_bytes));
                                switch (read_header.ObjectType)
                                {
                                case TransmissionType.Nothing:
                                    break;

                                case TransmissionType.Ready:
                                    received_command = JsonSerializer.Deserialize <ReadyCommand>(ref jsonreader);
                                    break;

                                case TransmissionType.Panic:
                                    received_command = JsonSerializer.Deserialize <PanicCommand>(ref jsonreader);
                                    break;

                                case TransmissionType.Levels:
                                    received_command = JsonSerializer.Deserialize <LevelsCommand>(ref jsonreader);
                                    break;

                                case TransmissionType.Raw:
                                    received_command = JsonSerializer.Deserialize <RawCommand>(ref jsonreader);
                                    break;

                                case TransmissionType.Mode:
                                    received_command = JsonSerializer.Deserialize <ModeCommand>(ref jsonreader);
                                    break;

                                case TransmissionType.Response:
                                    received_command = JsonSerializer.Deserialize <DeviceResponse>(ref jsonreader);
                                    break;

                                case TransmissionType.Request:
                                    break;

                                case TransmissionType.Error:
                                    received_command = JsonSerializer.Deserialize <ErrorCommand>(ref jsonreader);
                                    break;
                                }
                                consumed = jsonreader.BytesConsumed;
                            }
                        }
                    }
                    catch (JsonException) { }

                    if (received_command != null)
                    {
                        switch (read_header.ObjectType)
                        {
                        case TransmissionType.Nothing:
                            break;

                        case TransmissionType.Ready:
                            QueueStateCallback(this, 0);
                            break;

                        case TransmissionType.Panic:
                            MassLevelSetCallback(this, 0, 0, 0, true);
                            ErrorCallback(this, "PANIC!", "Panic received from remote!", true);
                            break;

                        case TransmissionType.Levels:
                            LevelsCommand levels = (LevelsCommand)received_command;
                            LastA = levels.A;
                            LastB = levels.B;
                            MassLevelSetCallback(this, levels.A, levels.B, levels.MA, levels.Mode == ControlMode.absolute);
                            break;

                        case TransmissionType.Raw:
                            RawCommand raw = (RawCommand)received_command;
                            if (raw.Address == (int)AddressByte.Pot_A)
                            {
                                LastA = raw.Data;
                            }
                            if (raw.Address == (int)AddressByte.Pot_B)
                            {
                                LastB = raw.Data;
                            }
                            StateUpdatedCallback(this, raw.Address, raw.Data);
                            break;

                        case TransmissionType.Mode:
                            ModeCommand mode = (ModeCommand)received_command;
                            StateUpdatedCallback(this, (int)AddressByte.ModeOverride, mode.Mode);
                            StateUpdatedCallback(this, (int)AddressByte.Pot_MA, mode.MA);
                            break;

                        case TransmissionType.Request:
                            break;

                        case TransmissionType.Response:
                            DeviceResponse response = (DeviceResponse)received_command;
                            DataReturnedCallback(this, response.Address, response.Data);
                            double     current_unixtime = UnixTime.Current();
                            LevelEvent level            = new LevelEvent()
                            {
                                unixtime = current_unixtime
                            };
                            lock (_thread_interlock)
                            {
                                if (response.Address == (int)AddressByte.PulseAmp_A)
                                {
                                    level.level = (int)Math.Sqrt(LastA * response.Data);
                                    AmpHistoryA.Add(level);
                                }
                                if (response.Address == (int)AddressByte.PulseAmp_B)
                                {
                                    level.level = (int)Math.Sqrt(LastB * response.Data);
                                    AmpHistoryB.Add(level);
                                }
                            }
                            break;

                        case TransmissionType.Error:
                            ErrorCommand error = (ErrorCommand)received_command;
                            ErrorCallback(this, error.Error, error.Details, false);
                            break;
                        }
                        read_header = null;
                    }
                }

                if (consumed > 0)
                {
                    lock (_thread_interlock)
                    {
                        byte[] remaining = new byte[remote_bytes.Length - consumed];
                        Buffer.BlockCopy(remote_bytes, (int)consumed, remaining, 0, remaining.Length);
                        remote_bytes = remaining;
                    }
                }

                lock (_thread_interlock)
                {
                    if (CommandQueue.Count > 0)
                    {
                        CommandBase command = CommandQueue.First();
                        CommandQueue.RemoveAt(0);
                        NetworkHeader write_header = new NetworkHeader()
                        {
                            ObjectType = command.ObjectType
                        };
                        try
                        {
                            JsonSerializer.Serialize(jsonwriter, write_header, typeof(NetworkHeader));
                            jsonwriter.Flush();
                            jsonwriter.Reset();
                            switch (command.ObjectType)
                            {
                            case TransmissionType.Nothing:
                                break;

                            case TransmissionType.Ready:
                                JsonSerializer.Serialize(jsonwriter, (ReadyCommand)command, typeof(ReadyCommand));
                                break;

                            case TransmissionType.Panic:
                                JsonSerializer.Serialize(jsonwriter, (PanicCommand)command, typeof(PanicCommand));
                                break;

                            case TransmissionType.Levels:
                                JsonSerializer.Serialize(jsonwriter, (LevelsCommand)command, typeof(LevelsCommand));
                                break;

                            case TransmissionType.Raw:
                                JsonSerializer.Serialize(jsonwriter, (RawCommand)command, typeof(RawCommand));
                                break;

                            case TransmissionType.Mode:
                                JsonSerializer.Serialize(jsonwriter, (ModeCommand)command, typeof(ModeCommand));
                                break;

                            case TransmissionType.Request:
                                JsonSerializer.Serialize(jsonwriter, (RequestCommand)command, typeof(RequestCommand));
                                break;

                            case TransmissionType.Response:
                                JsonSerializer.Serialize(jsonwriter, (ResponseCommand)command, typeof(ResponseCommand));
                                break;

                            case TransmissionType.Error:
                                JsonSerializer.Serialize(jsonwriter, (ErrorCommand)command, typeof(ErrorCommand));
                                break;
                            }
                            jsonwriter.Flush();
                            jsonwriter.Reset();
                        }
                        catch (JsonException) { }
                        catch (IOException e) when(e.InnerException is SocketException)
                        {
                            _thread_end = true;
                            ErrorCallback(this, "Network error.", e.InnerException.Message, false);
                        }
                        catch (IOException e)
                        {
                            _thread_end = true;
                            ErrorCallback(this, "Network error.", e.Message, false);
                        }
                        catch (Exception e)
                        {
                            _thread_end = true;
                            ErrorCallback(this, "Network error.", e.Message, false);
                        }
                        if (CommandQueue.Count == 0 && command.ObjectType != TransmissionType.Ready)
                        {
                            CommandQueue.Add(new ReadyCommand());
                        }
                    }
                    should_exit = _thread_end;
                }
            }

            try
            {
                lock (_thread_interlock)
                {
                    if (DeviceStream != null)
                    {
                        DeviceStream.Close();
                        DeviceStream.Dispose();
                    }
                    DeviceStream = null;
                }
            }
            catch (Exception e)
            {
                ErrorCallback(this, "Network error.", e.Message, false);
            }

            ErrorCallback(this, "Network processing shutdown.", "", false);
        }
예제 #2
0
        public override void SetLevels(LevelsCommand levels)
        {
            int    A, B, MA;
            double current_unixtime = UnixTime.Current();

            lock (_thread_interlock)
            {
                if (levels.Mode == ControlMode.absolute)
                {
                    LastA = levels.A;
                    LastB = levels.B;
                }
                else
                {
                    LastA += levels.A;
                    LastB += levels.B;
                }

                if (LastA > 255)
                {
                    LastA = 255;
                }
                if (LastB > 255)
                {
                    LastB = 255;
                }
                if (LastA < 0)
                {
                    LastA = 0;
                }
                if (LastB < 0)
                {
                    LastB = 0;
                }

                AmpHistoryA.Add(new LevelEvent()
                {
                    unixtime = current_unixtime, level = LastA
                });
                AmpHistoryB.Add(new LevelEvent()
                {
                    unixtime = current_unixtime, level = LastB
                });

                A = LastA;
                B = LastB;
            }

            StateUpdatedCallback(this, (int)AddressByte.Pot_A, A);
            StateUpdatedCallback(this, (int)AddressByte.Pot_B, B);
            if (levels.MA != 0)
            {
                lock (_thread_interlock)
                {
                    LastMA += levels.MA;
                    if (LastMA > 255)
                    {
                        LastMA = 255;
                    }
                    if (LastMA < 0)
                    {
                        LastMA = 0;
                    }
                    MA = LastMA;
                }
                StateUpdatedCallback(this, (int)AddressByte.Pot_MA, MA);
            }
        }
예제 #3
0
        private void CheckResponse(ref byte[] input)
        {
            double current_unixtime = UnixTime.Current();
            int    expected_bytes   = last_command.IsWrite() ? et232_success_sequence.Length : et232_read_response_length;

            if (input.Length < expected_bytes)
            {
                if (current_unixtime - last_command_time > command_timeout)
                {
                    HandleCommandFailure("Device timeout.");
                    input = Array.Empty <byte>();
                }
                return;
            }

            byte[] result_bytes = input;
            int    extra_bytes  = result_bytes.Length - expected_bytes;

            if (extra_bytes > 0)
            {
                input = new byte[extra_bytes];
                Buffer.BlockCopy(result_bytes, expected_bytes, input, 0, extra_bytes);
            }
            else
            {
                input = Array.Empty <byte>();
            }

            bool error = false;

            if (last_command.IsWrite())
            {
                for (int idx = 0; idx < et232_success_sequence.Length; idx++)
                {
                    if (result_bytes[idx] != et232_success_sequence[idx])
                    {
                        error = true;
                    }
                }
            }
            else if (result_bytes.Last() != (byte)'\n')
            {
                error = true;
            }

            if (error)
            {
                HandleCommandFailure("Device error.");
                return;
            }

            int ScalingFunction(int user_level, int function)
            {
                return((int)(Math.Sqrt(user_level * function)));
            }

            command_retries = 0;
            if (last_command.IsWrite())
            {
                if (last_command.Address == AddressByte.Pot_A)
                {
                    lock (_thread_interlock)
                    {
                        Governor.RecordA(last_command.Data);
                        LastA = last_command.Data;
                    }
                }
                if (last_command.Address == AddressByte.Pot_B)
                {
                    lock (_thread_interlock)
                    {
                        Governor.RecordB(last_command.Data);
                        LastB = last_command.Data;
                    }
                }
                if (last_command.Address == AddressByte.Pot_MA)
                {
                    lock (_thread_interlock) LastMA = last_command.Data;
                }
                if (last_command.Address == AddressByte.ModeOverride)
                {
                    lock (_thread_interlock) draining_queue = true;
                    Thread.Sleep(mode_delay);
                    StateUpdatedCallback(this, (int)last_command.Address, last_command.Data & ErosTek.ET232.Constants.ForceModeMask);
                }
                else
                {
                    StateUpdatedCallback(this, (int)last_command.Address, last_command.Data);
                }
            }
            else
            {
                string result_string = Encoding.ASCII.GetString(result_bytes, 0, 2);
                try
                {
                    int result_value = int.Parse(result_string, System.Globalization.NumberStyles.HexNumber);
                    DataReturnedCallback(this, (int)last_command.Address, result_value);
                    LevelEvent level = new LevelEvent()
                    {
                        unixtime = current_unixtime, level = result_value
                    };
                    if (last_command.Address == AddressByte.PulseAmp_A)
                    {
                        lock (_thread_interlock)
                        {
                            level.level = ScalingFunction(LastA, level.level);
                            AmpHistoryA.Add(level);
                        }
                    }
                    if (last_command.Address == AddressByte.PulseAmp_B)
                    {
                        lock (_thread_interlock)
                        {
                            level.level = ScalingFunction(LastB, level.level);
                            AmpHistoryB.Add(level);
                        }
                    }
                }
                catch (Exception)
                {
                    List <string> details = result_bytes.Select(e => String.Format("0x{0,2:X2}", new object[] { e })).ToList();
                    ErrorCallback(this,
                                  "Device returned invalid data.",
                                  "Bytes: " + input.Length + " Data: " + String.Join(", ", details), false);
                }
            }

            last_command = null;
            lock (_thread_interlock) _state = State.ready;
        }