tiistai, 22. lokakuu 2019

Puuvillan infotaulujen tutkailua 2

Ennen
https://teknokoodiradio.vuodatus.net/lue/2017/06/kauppakeskus-puuvillan-infotaulujen-tutkailua

Nyt pienet laatikot kadonneet uusista infotauluista.

taulu2.jpg

taulu1.jpg
 

sunnuntai, 20. lokakuu 2019

SDR# signal diagnostics logger plugin

C#, .NET Framework 4.6
Visual Studio 2019 Community edition
https://docs.microsoft.com/en-us/dotnet/api/system.device.location.geocoordinatewatcher?view=netframework-4.6

Copy SDRSharp.SDLogPlugin.dll (SDRSharp.SDLogPlugin\bin\Release) to SDR# folder and add this line to plugins.xml file <add key="SDLog" value="SDRSharp.SDLogPlugin.SDLogPlugin,SDRSharp.SDLogPlugin"/>
https://github.com/OH1GIU-P/SDLog

SDLog is SDR# Signal Diagnostics power value (dB) file logger plugin. Power value less or greater than threshold value is written into the log file with timestamp, SDR# tuned frequency, latitude and longitude (if location is enabled and available - GeoCoordinateWatcher) with tab field separator.
20191020112024    -20,71    393012500        
20191020112024    -20,73    393012500        
20191020112024    -20,73    393012500        
20191020112024    -20,74    393012500        
20191020112025    -20,74    393012500        
20191020112025    -20,72    393012500        
20191020112025    -20,72    393012500   

Log file is created in SDR# folder and each time when start button is clicked, new log file is created.

sdlp.jpg

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Device.Location;
using SDRSharp.Common;

namespace SDRSharp.SDLogPlugin
{
    public partial class SDLogPluginPanel : UserControl
    {
        private GeoCoordinateWatcher _watcher = null;
        private Control _controlSDValue = null;
        private StreamWriter _sw = null;
        private ISharpControl _sdlogplugin;
        private string _logPath = string.Empty;

        public SDLogPluginPanel(ISharpControl control)
        {
            InitializeComponent();
            _sdlogplugin = control;
            labelLogFile.Text = "";        
            labelLat.Text = "";
            labelLon.Text = "";
            labelStatus.Text = "";
            _watcher = new GeoCoordinateWatcher();
            _watcher.StatusChanged += new EventHandler<GeoPositionStatusChangedEventArgs>(watcher_StatusChanged);
            //_watcher.PositionChanged += new EventHandler<GeoPositionChangedEventArgs<GeoCoordinate>>(watcher_PositionChanged);
        }

        private void ButtonStart_Click(object sender, EventArgs e)
        {
            labelLat.Text = "";
            labelLon.Text = "";
            if (!_watcher.TryStart(false, TimeSpan.FromMilliseconds(Utils.GEOCOORDWATCHER_TIMEOUT)))
            {
                labelStatus.Text = Utils.GEOCOORDWATCHER_TIMEOUT_MSG;
            }
            else
            {
                labelStatus.Text = Utils.GEOCOORDWATCHER_START_MSG;
            }
            labelStatus.Text = labelStatus.Text + " - " + _watcher.Status.ToString();
            _controlSDValue = null;
            try
            {
                Control[] ctrls = ParentForm.Controls.Find(Utils.TXT_AVERAGE, true);
                foreach (Control c in ctrls)
                {
                    _controlSDValue = c;
                    break;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, Utils.APP_CAPTION, MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            if (_controlSDValue != null)
            {
                if (_sw == null)
                {
                    _sw = new StreamWriter(Application.StartupPath + "\\" + DateTime.Now.ToString("yyyyMMddHHmmss") +
                    "_" + _sdlogplugin.Frequency.ToString() + ".txt", true);
                    numericUpDownThresh.Enabled = false;
                    groupBoxOperator.Enabled = false;
                    buttonStart.Enabled = false;
                    buttonStop.Enabled = true;
                    timerSDLog.Enabled = true;
                }
            }
        }

        private void ButtonStop_Click(object sender, EventArgs e)
        {
            timerSDLog.Enabled = false;
            _watcher.Stop();
            labelStatus.Text = "";
            _sw.Close();
            _sw.Dispose();
            _sw = null;
            buttonStop.Enabled = false;
            buttonStart.Enabled = true;
            numericUpDownThresh.Enabled = true;
            groupBoxOperator.Enabled = true;
        }

        public void Close()
        {
            if (_sw != null)
            {
                _sw.Close();
            }
        }
        private void timerSDLog_Tick(object sender, EventArgs e)
        {
            decimal d;
            if (decimal.TryParse(_controlSDValue.Text.Replace("dB", "").Trim(), out d))
            {
                bool b = false;
                if (radioButtonLT.Checked)
                {
                    if (d < numericUpDownThresh.Value)
                    {
                        b = true;
                    }
                }
                else
                {
                    if (d > numericUpDownThresh.Value)
                    {
                        b = true;
                    }
                }
                if (b)
                {
                    _sw.WriteLine(string.Format("{0}\t{1}\t{2}\t{3}\t{4}", DateTime.Now.ToString("yyyyMMddHHmmss"), d, _sdlogplugin.Frequency, labelLat.Text, labelLon.Text));
                }
            }
        }

        private void watcher_StatusChanged(object sender, GeoPositionStatusChangedEventArgs e)
        {
            labelLat.Text = "";
            labelLon.Text = "";
            labelStatus.Text = "";
            switch (e.Status)
            {
                case GeoPositionStatus.Ready:
                    {
                        if (!_watcher.Position.Location.IsUnknown)
                        {
                            labelLat.Text = _watcher.Position.Location.Latitude.ToString();
                            labelLon.Text = _watcher.Position.Location.Longitude.ToString();
                        }
                        else
                        {
                            labelStatus.Text = Utils.STATUS_CANNOT_FIND_DATA;
                        }
                        break;
                    }
                case GeoPositionStatus.Initializing:
                    {
                        labelStatus.Text = Utils.STATUS_INIT;
                        break;
                    }
                case GeoPositionStatus.NoData:
                    {
                        labelStatus.Text = Utils.STATUS_NO_DATA;
                        break;
                    }
                case GeoPositionStatus.Disabled:
                    {
                        labelStatus.Text = Utils.STATUS_DISABLED;
                        break;
                    }
            }
        }

        //void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
        //{
        //    labelLat.Text = e.Position.Location.Latitude.ToString();
        //    labelLon.Text = e.Position.Location.Longitude.ToString();
        //}
    }
}

 

perjantai, 4. lokakuu 2019

Clear PDUs - 3

SSI:nnnnnnn Call ID:nnnnn D_Alert Mode_of_Operation:Duplex Notification_Indicator:SS_CFU_invoked Basic_service:Individual Clear High_Protect_24_1 T301_T302:Predefined

SSI:nnnnnnn Call ID:nnnnn Disconnect_cause:Called_party_busy D_Disconnect

SSI:nnnnnnn Call ID:nnnnn Encrypt:Clear D_TX_Granted Transmission Request_queued Party_SSI:nnnnnnn External_subscriber_number:';,.......;' Notification_Indicator:Presentation_restriction_overridden
https://www.etsi.org/deliver/etsi_etr/300_399/30005/01_60/etr_30005e01p.pdf

SSI:nnnnnnn Call ID:nnnnn Disconnect_cause:Reserved27 D_Disconnect Notification_Indicator:Limited_group_coverage

SSI:nnnnnnn Call ID:nnnn D_Connect Transmission Request_queued Mode_of_Operation:Simplex Hook_method:No hook signalling (direct through-connect) Basic_service:Point_to_multipoint_Acknowledged E2EE Low_Protect_48_4 Call_time-out:t min

SSI:nnnnnnn Call ID:nnnnn D_Info Modify_Mode_of_Operation:Simplex Notification_Indicator:Call_barred_by_SS_BIC Modify_Basic_service:Individual Clear High_Protect_24_8 T301_T302:t s Call_time-out:tt min

SSI:nnnnnnn Call ID:nnnn D_Call_Proceeding Mode_of_Operation:Simplex Hook_method:No hook signalling (direct through-connect) Notification_Indicator:Reserved39 T301_T302:tt s

SSI:nnnnnnn Call ID:nnnn Disconnect_cause:Invalid_call_identifier D_Disconnect Notification_Indicator:Limited_group_coverage

SSI:nnnnnnn Call ID:nnnnn Disconnect_cause:Concurrent_setup_not_supported D_Release
SSI:nnnnnnn Call ID:nnnn D_TX_Continue Notification_Indicator:Notice_of_imminent_call_disconnection
SSI:nnnnnnn Call ID:nnnn D_TX_Continue Notification_Indicator:AL_call_or_speech_item
SSI:nnnnnnn Call ID:nnnn Disconnect_cause:Incompatible_traffic_case D_Release Notification_Indicator:LSC_invoked
SSI:nnnnnnn Call ID:nnnn Encrypt:Clear D_TX_Granted Transmission Granted Notification_Indicator:AL_operation

MS request for registration/authentication ACCEPTED for SSI: nnnnnnn - Authentication successful or no authentication currently in progress - CCK_identifier: x - ITSI attach
MS request for registration/authentication ACCEPTED for SSI: nnnnnnn - Authentication successful or no authentication currently in progress - CCK_identifier: x - Roaming location updatingMS request for registration/authentication ACCEPTED for SSI: nnnnnnn - Authentication successful or no authentication currently in progress - CCK_identifier: x - Periodic location updating

sunnuntai, 8. syyskuu 2019

Examining 433 MHz sensor signal with SX1278/Arduino

WX station 433 MHz OOK remote sensor, channel change signal.
Arduino Due & Dragino 433 MHz Lora Shield (Semtech SX1278).

due-sx1278.jpg

remsens.jpg

ser-ouput.jpg

#include <SPI.h>

#define SERIAL_SPEED        38400
#define FREQ                433.983
#define BPS                 1800
#define STATE_SLEEP         0
#define STATE_STANDBY       1
#define STATE_FSRX          4
#define STATE_RX            5
#define S_DELAY             10
#define L_DELAY             100
#define SX_FREQ             "Frequency "
#define SX_VERSION          "Version code of the chip "
#define SX_RX               "RX..."
#define RCS_RX              "Received "
#define RCS_SEP             " / "
#define RCS_UNKNOWN_ENC     "Unknown encoding"
#define RCS_BIT             "bit "
#define RCS_PROTOCOL        "Protocol: "
#define CH_FILTER_BW        B00001100       // 25 kHz

#define DATA_PIN            7

#define RegFifo             0x00
#define RegOpMode           0x01
#define RegBitrateMsb       0x02
#define RegBitrateLsb       0x03
#define RegFrfMsb           0x06
#define RegFrfMid           0x07
#define RegFrfLsb           0x08
#define RegPaRamp           0x0a
#define RegRssiConfig       0x0e
#define RegRssiThresh       0x10
#define RegRxBw             0x12
#define RegOokPeak          0x14
#define RegPreambleDetect   0x1f
#define RegSyncConfig       0x27
#define RegPacketConfig1    0x30
#define RegPacketConfig2    0x31
#define RegPayloadLength    0x32
#define RegIrqFlags2        0x3f
#define RegDioMapping1      0x40
#define RegVersion          0x42

#define SX_OSC_FREQ         32000000
#define SX_RESET            9
#define SX_RESET_DELAY_H    5
#define SX_RESET_DELAY_L    100
#define SPI_SS              10
#define SPI_RW_DELAY        50

volatile uint32_t pulse_len = 0;

void setup() {
  Serial.begin(SERIAL_SPEED);
  if (initSX()) {
    pinMode(DATA_PIN, INPUT);
    Serial.print(F(SX_VERSION));
    Serial.print(readSPI(RegVersion));
    Serial.println();
    delay(S_DELAY);
    startFSK();
    // Set OOK
    uint8_t b = readSPI(RegOpMode);
    bitClear(b, 6);
    bitSet(b, 5);
    writeSPI(RegOpMode, b);

    // Channel filter bandwidth control
    writeSPI(RegRxBw, CH_FILTER_BW);

    setFreq(FREQ);
    Serial.print(F(SX_FREQ));
    Serial.println(FREQ, DEC);
    setBps(BPS);

    // Bits 7-6: AutoRestartRxMode, 01  On, without waiting for the PLL to re-lock
    // Bit 4: Enables the Sync word generation and detection: 0 =>  Off, 1 =>  On
    // Bit 5: Sets the polarity of the Preamble. 0  0xAA, 1  0x55
    // Bits 2-0: Size of the Sync word (SyncSize + 1)
    b = readSPI(RegSyncConfig);
    bitClear(b, 7);
    bitSet(b, 6);
    bitClear(b, 4);
    bitClear(b, 5);
    writeSPI(RegSyncConfig, b);

    // Bits 6-5: Defines DC-free encoding/decoding performed: 00->none, 01->manchester, 10->whitening
    // Bit 7: packet format, 0 = fixed length, 1 = variable length
    // Bit 4: crc calc/check, 0 = off, 1 = on
    // Bits 2-1: Defines address based filtering in Rx: 00  None (Off)
    // Bit 3: Defines the behavior of the packet handler when CRC check fails:
    // 0 => Clear FIFO and restart new packet reception. No PayloadReady interrupt issued.
    // 1 =>  Do not clear FIFO. PayloadReady interrupt issued.
    // Bit 0: Selects the CRC and whitening algorithms:
    // 0  CCITT CRC implementation with standard whitening
    // 1  IBM CRC implementation with alternate whitening
    writeSPI(RegPacketConfig1, 0);

    // Data processing mode: 0 => Continuous mode, 1 => Packet mode
    b = readSPI(RegPacketConfig2);
    bitClear(b, 6);
    writeSPI(RegPacketConfig2, b);
    
    // Set DIO mapping
    b = readSPI(RegDioMapping1);
    bitClear(b, 5);
    bitClear(b, 4);
    bitClear(b, 3);
    bitClear(b, 2);
    writeSPI(RegDioMapping1, b);

    // Bit 5: enables the Bit Synchronizer:
    // 0 -> bit sync disabled (not possible in packet mode), 1 -> bit sync enabled
    b = readSPI(RegOokPeak);
    bitClear(b, 5);
    writeSPI(RegOokPeak, b);

    // RegPreambleDetect (0x1f). Enables Preamble detector when set to 1.
    // The AGC settings supersede this bit during the startup / AGC phase.
    // Bit 7: 0 -> turned off, 1 -> turned on
    // Bits 6-5: Number of Preamble bytes to detect to trigger an interrupt.
    // 00  1 byte, 10  3 bytes, 01  2 bytes
    b = readSPI(RegPreambleDetect);
    bitClear(b, 7);
    writeSPI(RegPreambleDetect, b);

    clearFifoAndFlags();

    setState(STATE_FSRX);
    delay(L_DELAY);
    setState(STATE_RX);
    delay(S_DELAY);
    Serial.println(F(SX_RX));
    attachInterrupt(digitalPinToInterrupt(DATA_PIN), isr, CHANGE);
  }
}

void loop() {
  if ((pulse_len > 500) && (pulse_len < 3000)) {
    Serial.println(pulse_len);
  }
}

void isr() {
  static uint32_t last_irq_ti = 0;
  uint32_t t = micros();
  pulse_len = t - last_irq_ti;
  last_irq_ti = t;
}

void clearFifoAndFlags() {
  // Flag(s) and FIFO are cleared when this bit is set
  uint8_t b = readSPI(RegIrqFlags2);
  bitSet(b, 4);
  writeSPI(RegIrqFlags2, b);
  delay(S_DELAY);
}

void setBps(uint16_t bps) {
  uint16_t baudRate = SX_OSC_FREQ / bps;
  writeSPI(RegBitrateMsb, baudRate >> 8);
  writeSPI(RegBitrateLsb, baudRate & 0xff);
}

void setFreq(float f)
{
  uint32_t lf = (f * 1000000) / 61.035;
  writeSPI(RegFrfMsb, (lf >> 16) & 0xff);
  writeSPI(RegFrfMid, (lf >> 8) & 0xff);
  writeSPI(RegFrfLsb, lf & 0xff);
}

void setState(uint8_t s) {
  uint8_t b = readSPI(RegOpMode);
  b = b | s;
  writeSPI(RegOpMode, b);
}

void startFSK()
{
  setState(STATE_SLEEP);
  delay(S_DELAY);
  uint8_t b = readSPI(RegOpMode);
  bitClear(b, 7);
  writeSPI(RegOpMode, b);
}

bool initSX() {
  pinMode(SX_RESET, OUTPUT);
  resetSX();
  initSPI();
  if (readSPI(RegVersion) == 0) {
    return false;
  }
  setState(STATE_STANDBY);
  return true;
}

void resetSX() {
  digitalWrite(SX_RESET, LOW);
  delayMicroseconds(SX_RESET_DELAY_L);
  digitalWrite(SX_RESET, HIGH);
  delay(SX_RESET_DELAY_H);
}

uint8_t readSPI(uint8_t addr) {
  digitalWrite(SPI_SS, LOW);
  SPI.transfer(addr);
  delayMicroseconds(SPI_RW_DELAY);
  uint8_t v = SPI.transfer(0x00);
  digitalWrite(SPI_SS, HIGH);
  return v;
}

void writeSPI(uint8_t addr, uint8_t v) {
  digitalWrite(SPI_SS, LOW);
  SPI.transfer(addr | 0x80);
  delayMicroseconds(SPI_RW_DELAY);
  SPI.transfer(v);
  digitalWrite(SPI_SS, HIGH);
}

void initSPI()
{
  digitalWrite(SPI_SS, HIGH);
  pinMode(SPI_SS, OUTPUT);  
  SPI.begin();
  SPI.setDataMode(SPI_MODE0);
  SPI.setBitOrder(MSBFIRST);
}

torstai, 29. elokuu 2019

SDR# Uniden scanner react tune

by using Uniden GLG remote command (many Uniden DMA scanners feature GLG remote protocol command) and SDRSharp net remote plugin https://github.com/EarToEarOak/SDRSharp-Net-Remote

sdrnetrmt.jpg

Uniden SQL closed
uniden-glg-sql-close.jpg

SQL open. SDR# tuned to frequency and mode reported by GLG command.
uniden-glg-sql-open.jpg

C# code. VS project: https://github.com/OH1GIU-P/Uniden-react-tune

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Web.Script.Serialization;
using System.Threading;
using System.Net.Sockets;
using System.IO;
using System.IO.Ports;

namespace WindowsFormsApp3
{
    public partial class Form1 : Form
    {
        string dataRX = string.Empty;
        string freq = string.Empty;
        bool rx = false;
        bool tcpConnect = false;
        const string APP_TITLE = "SDR# Uniden react tune";
        const string IP = "127.0.0.1";
        const string UNIDEN_CMD = "GLG\r";
        const string GLG_SQL_CLOSED = "GLG,,,,,,,,,";
        const string GLG_SQL_CLOSE_MSG = "GLG...";
        const string NO_COM_PORT_MSG = "No serial ports found";
        const string SQL_OPEN = "1";
        const string FM = "FM";
        const string NFM = "NFM";
        const string WFMB = "WFMB";
        const string WFM = "WFM";
        const int GLG_MSG_MIN_LEN = 16;
        const int GLG_FREQ = 1;
        const int GLG_MODE = 2;
        const int GLG_SQL = 8;
        const int GLG_LEN = 10;

        TcpClient tcpClient = new TcpClient();

        DetectorType _detectorType;
        Freq _freq;
        //Freq _centerFreq;

        private delegate void SetTextDeleg(string text);

        public Form1()
        {
            InitializeComponent();
            _detectorType = new DetectorType
            {
                Command = "Set",
                Method = "DetectorType",
                Value = ""
            };
            _freq = new Freq
            {
                Command = "Set",
                Method = "Frequency",
                Value = 0
            };
            //_centerFreq = new Freq
            //{
            //    Command = "Set",
            //    Method = "CenterFrequency",
            //    Value = 0
            //};

// serialPort1 speed is 38400
            string[] ports = SerialPort.GetPortNames();
            if (ports.Length > 0)
            {
                serialPort1.PortName = ports[0];
            }
            else
            {
                buttonStart.Enabled = false;
                buttonStop.Enabled = false;
                textBoxScr.Text = NO_COM_PORT_MSG;
            }
        }

        private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            dataRX = dataRX + serialPort1.ReadExisting();
            if (rx)
            {
                if ((dataRX.Contains('\r')) && (!dataRX.Contains(GLG_SQL_CLOSED)))
                {
                    this.BeginInvoke(new SetTextDeleg(ser_DataReceived), new object[] { dataRX });
                }
                if (dataRX.Contains(GLG_SQL_CLOSED + "\r"))
                {
                    this.BeginInvoke(new SetTextDeleg(ser_DataReceived), new object[] { GLG_SQL_CLOSE_MSG });
                }
            }
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (serialPort1.IsOpen)
            {
                rx = false;
                serialPort1.DiscardOutBuffer();
                serialPort1.DiscardInBuffer();
                serialPort1.DataReceived -= serialPort1_DataReceived;
            }
        }

        private void ser_DataReceived(string data)
        {
            textBoxScr.Text = string.Empty;
            if (rx)
            {
                textBoxScr.Text = data;
                if (data.Length > GLG_MSG_MIN_LEN)
                {
                    textBoxScr.Text = string.Empty;
                    string[] lines = data.Replace(" ", "").Split(',');
                    foreach (var line in lines)
                    {
                        if (line.Trim().Length > 0)
                        {
                            textBoxScr.Text = textBoxScr.Text + line + Environment.NewLine;
                        }
                    }
                    if (lines.Length == GLG_LEN)
                    {
                        if (lines[GLG_SQL].Equals(SQL_OPEN))
                        {
                            string fs = string.Empty;
                            long f;
                            if (Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator.Equals(","))
                            {
                                fs = lines[GLG_FREQ].Replace('.', ',');
                            }
                            if (long.TryParse(fs, out f))
                            {
                                _freq.Value = f * 100;
                                _detectorType.Value = lines[GLG_MODE];
                                if (_detectorType.Value.Equals(FM))
                                {
                                    _detectorType.Value = NFM;
                                }
                                if (_detectorType.Value.Equals(WFMB))
                                {
                                    _detectorType.Value = WFM;
                                }
                                string detectorJSON = new JavaScriptSerializer().Serialize(_detectorType);
                                //string centerFreqJSON = new JavaScriptSerializer().Serialize(_centerFreq);
                                string freqJSON = new JavaScriptSerializer().Serialize(_freq);
                                textBoxScr.Text = textBoxScr.Text + detectorJSON + Environment.NewLine;
                                //textBoxScr.Text = textBoxScr.Text + centerFreqJSON + Environment.NewLine;
                                textBoxScr.Text = textBoxScr.Text + freqJSON + Environment.NewLine;

                                if ((tcpConnect) && (!freq.Equals(fs)))
                                {
                                    freq = fs;
                                    ASCIIEncoding ascii = new ASCIIEncoding();
                                    byte[] msg = ascii.GetBytes(detectorJSON);
                                    try
                                    {
                                        NetworkStream stream = tcpClient.GetStream();
                                        stream.Write(msg, 0, msg.Length);
                                        msg = ascii.GetBytes(freqJSON);
                                        stream.Write(msg, 0, msg.Length);
                                    }
                                    catch (Exception ex)
                                    {
                                        textBoxScr.Text = textBoxScr.Text + ex.Message + Environment.NewLine;
                                    }
                                }
                            }
                        }
                    }
                }
                dataRX = string.Empty;
                serialPort1.Write(UNIDEN_CMD);
            }
        }

        private void buttonStart_Click(object sender, EventArgs e)
        {
            textBoxScr.Text = string.Empty;
            dataRX = string.Empty;
            freq = string.Empty;
            try
            {
                if (!serialPort1.IsOpen)
                {
                    serialPort1.Open();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), APP_TITLE, MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            tcpConnect = true;
            try
            {
                if (!tcpClient.Client.Connected)
                {
                    tcpClient.Connect(IP, Convert.ToInt32(numericUpDownTcpPort.Value));
                }
            }
            catch (Exception ex)
            {
                tcpConnect = false;
                MessageBox.Show(ex.ToString(), APP_TITLE, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            numericUpDownTcpPort.Enabled = false;
            buttonStart.Enabled = false;
            buttonStop.Enabled = true;
            rx = true;
            serialPort1.Write(UNIDEN_CMD);
        }

        private void buttonStop_Click(object sender, EventArgs e)
        {
            rx = false;
            serialPort1.DiscardOutBuffer();
            serialPort1.DiscardInBuffer();
            tcpConnect = false;
            textBoxScr.Text = string.Empty;
            numericUpDownTcpPort.Enabled = true;
            buttonStart.Enabled = true;
            buttonStop.Enabled = false;
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WindowsFormsApp3
{
    public class Freq
    {
        public string Command;
        public string Method;
        public long Value;
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WindowsFormsApp3
{
    public class DetectorType
    {
        public string Command;
        public string Method;
        public string Value;
    }
}