Ejemplo n.º 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);
        }
Ejemplo n.º 2
0
        public override void ThreadFunction()
        {
            ErrorCallback(this, "ET232 connection started.", "Waiting for device handshake.", false);

            Initialize();

            bool should_exit = false;

            byte[] device_inputs = Array.Empty <byte>();

            // https://www.sparxeng.com/blog/software/must-use-net-system-io-ports-serialport
            byte[] read_buffer = new byte[1024];
            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 = device_inputs.Length;
                                    Array.Resize(ref device_inputs, pos + len);
                                    Buffer.BlockCopy(read_buffer, 0, device_inputs, pos, len);
                                }
                            }
                            catch (Exception e)
                            {
                                bool exiting;
                                lock (_thread_interlock) exiting = _thread_end;
                                if (!exiting)
                                {
                                    ErrorCallback(this, "Device error.", e.Message, false);
                                }
                            }
                            DataReader();
                        }, null);
                }
                catch (Exception e)
                {
                    bool exiting;
                    lock (_thread_interlock) exiting = _thread_end;
                    if (!exiting)
                    {
                        ErrorCallback(this, "Device error.", e.Message, false);
                    }
                }
            }

            DataReader();

            while (!should_exit)
            {
                Thread.Yield();
                State  current_state;
                byte[] current_input_data;
                lock (_thread_interlock)
                {
                    Governor.PruneHistory();
                    current_state      = _state;
                    current_input_data = device_inputs;
                    device_inputs      = Array.Empty <byte>();
                }

                switch (current_state)
                {
                case State.init:
                    CheckHandshake(ref current_input_data);
                    break;

                case State.ready:
                    TransmitCommand();
                    break;

                case State.command:
                    CheckResponse(ref current_input_data);
                    break;
                }

                lock (_thread_interlock)
                {
                    int pos = current_input_data.Length;
                    Array.Resize(ref current_input_data, pos + device_inputs.Length);
                    Buffer.BlockCopy(device_inputs, 0, current_input_data, pos, device_inputs.Length);
                    device_inputs = current_input_data;
                }

                QueueMaintenance();

                lock (_thread_interlock)
                {
                    should_exit = _thread_end;
                    if (CommandQueue.Count > 0)
                    {
                        should_exit = false;
                    }
                }
                if (last_command != null)
                {
                    should_exit = false;
                }
            }

            lock (_thread_interlock)
            {
                if (DeviceStream != null)
                {
                    DeviceStream.Close();
                    DeviceStream.Dispose();
                }
                DeviceStream = null;
            }

            ErrorCallback(this, "ET232 disconnected.", "Device should now be unlocked. Switch it off before reconnecting.", false);
        }