Danny96 Ответов: 2

Не удается получить данные с последовательного порта


Я пытаюсь получать и записывать данные в txt-файл, я проверил этот пост и правильно добавил eventHandler. Последовательность открытия и т. д. одинакова. Однако я не могу получать данные, даже когда пытаюсь печатать внутри
SerialPort_DataReceived
это ничего не значит. Я не могу получить данные.

p.CmdSerialPort.DataReceived
всегда равно нулю, что бы я ни менял.

Может кто-нибудь помочь?

using System;
using System.Linq;
using System.IO;
using System.IO.Ports;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;


namespace Logger
{
    public class SPWrapper
    {
        

        public System.IO.Ports.SerialPort CmdSerialPort;
        public StreamWriter swLog;
        public DateTime lastComm = DateTime.MinValue;
        public UdpClient udpClient_Cmd;
        public volatile bool _enabled_Cmd;
        public static int Ethernet_Packet_Header_Length = 14;
        public IPAddress IP { get;  set; }
        public int Cmd_Port { get;  set; }
        ////////////////////////////////////////////////////////////
        // SERIAL PORT 
        ////////////////////////////////////////////////////////////

        public bool TryConnect(string portName)
        {

            try
            {

                CmdSerialPort.PortName = portName;
                CmdSerialPort.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(SerialPort_DataReceived);
                CmdSerialPort.Open();

                if (CmdSerialPort.IsOpen)
                {

                    return true;

                }
                return false;

            }
            catch (UnauthorizedAccessException e)
            {

                Debug.WriteLine(e.ToString());

                Debug.WriteLine(e.Message);

                return false;

            }

            catch (ArgumentOutOfRangeException e)
            {

                Debug.WriteLine(e.ToString());

                Debug.WriteLine(e.Message);

                return false;
            }
            catch (ArgumentException e)
            {

                Debug.WriteLine(e.ToString());

                Debug.WriteLine(e.Message);

                return false;

            }

        }

        internal void Close2()
        {
            if (CmdSerialPort.IsOpen)
            {

                CmdSerialPort.Close();

            }

            swLog.Close();

            swLog = null;

        }



        public void SerialPort_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {

            lastComm = DateTime.Now;

            if (sender is SerialPort sp)
            {

                string indata = sp.ReadExisting();

                indata = indata.Trim(' ').Trim('\n').Trim('\r');

                WriteToFile($"{CmdSerialPort.PortName}\t{lastComm}\t{indata}");

            }

        }

        public void WriteToFile(string v)
        {

            swLog.WriteLine(v);

        }


        ////////////////////////////////////////////////////////////
        // ETHERNET 
        ////////////////////////////////////////////////////////////
        public IPEndPoint IPE_Cmd;



        internal void Close()
        {

            udpClient_Cmd?.Close();

        }



        public bool Initialize()
        {

            bool retVal = true;

            IPE_Cmd = new IPEndPoint(IP, Cmd_Port);

            try
            {

                udpClient_Cmd = new UdpClient();

                udpClient_Cmd.Client.Bind(IPE_Cmd);

                _enabled_Cmd = true;

                udpClient_Cmd.BeginReceive(new AsyncCallback(ReceiveCallbackCmd), null);

            }
            catch (Exception ex)
            {

                retVal = false;

                udpClient_Cmd?.Close();

                udpClient_Cmd = null;

                Debug.WriteLine(ex.ToString());

                Debug.WriteLine(ex.Message);

                Debug.WriteLine(ex.InnerException?.ToString());

            }


            return retVal;

        }



        public void ReceiveCallbackCmd(IAsyncResult ar)
        {

            DateTime now = DateTime.Now;

            IPEndPoint e = new IPEndPoint(IPAddress.Any, 0);

            byte[] receiveBytes = null;

            try

            {

                receiveBytes = udpClient_Cmd?.EndReceive(ar, ref e);
                Console.WriteLine(receiveBytes);

            }

            catch (ObjectDisposedException)

            {

                _enabled_Cmd = false;

                udpClient_Cmd?.Close();

                udpClient_Cmd = null;

            }

            if (receiveBytes != null)

            {

                string UDP_Read_Message = System.Text.Encoding.UTF8.GetString(receiveBytes.Skip(Ethernet_Packet_Header_Length).ToArray());

                WriteToFile($"{e}\t{now}\t{UDP_Read_Message}");

            }

            if (_enabled_Cmd)

            {

                udpClient_Cmd?.BeginReceive(new AsyncCallback(ReceiveCallbackCmd), null);

            }

        }
    }

    class Program
    {
        public static SPWrapper p;
        static void Main(string[] args)
        {
            Console.WriteLine("Please Enter Parameters: ");
            p = new SPWrapper();
            p.IP = IPAddress.Parse("....");//IP

            //serial port configurations
            p.CmdSerialPort = new SerialPort();
            p.CmdSerialPort.Handshake = Handshake.None;
            p.CmdSerialPort.BaudRate = 115200;
            p.CmdSerialPort.Parity = Parity.None;
            p.CmdSerialPort.StopBits = StopBits.One;
            p.CmdSerialPort.DataBits = 8;

            //takes port, ethernet and filename inputs
            string s = Console.ReadLine();
            string[] input = s.Split(' ').ToArray();

            if (input.Length > 3)
                Console.WriteLine("Wrong input size!");

            string filename = input[2];//takes filename 
            //DEFAULT PATH ROOT
            String root = @".\\";
            string path_combined;

            filename += ".txt";
            path_combined = Path.Combine(root, filename);

            try
            {

                if (p.TryConnect(input[0]))//takes port name  eg.COM9
                    p.swLog = File.CreateText(path_combined);

            }
            catch (System.IndexOutOfRangeException ex)
            {
                System.ArgumentException argEx = new System.ArgumentException("File creation failed!", ex);
                throw argEx;
            }



            p.Cmd_Port = Int32.Parse(input[1]);//takes port number  eg.4667

            p.Initialize();

            Console.ReadKey();

            p.Close2();

            p.Close();


        }//end of main


    }
    
}


Что я уже пробовал:

Я поставил точки останова рядом со всеми open() и close(), кажется, они работают нормально, но я считаю, что проблема может возникнуть из-за
CmdSerialPort.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(SerialPort_DataReceived);

В официальной ссылке microsoft эта строка ставится перед open(). Все равно я получаю пустой txt-файл, его нельзя записать.

2 Ответов

Рейтинг:
2

OriginalGriff

Начните с использования того, что, как вы знаете, работает: Гипертерминал или что-то подобное. Установите это в соответствии с книгой и докажите, что вы можете установить связь непосредственно с другим устройством. Если вы не можете, вам нужно выяснить, почему, и это будет неправильный порт; или неправильная скорость, BPC, четность; неправильный отжим; неправильное устройство; аппаратный сбой; или вы не понимаете, как разговаривать с этим устройством (ему может потребоваться определенная последовательность, отправленная ему, чтобы что-то сделать).

Когда это работает, вы знаете, что у вас есть правильный материал, так что вы можете начать с кодирования.
Но до тех пор вы не можете иметь ни малейшего представления о том, что происходит!


Danny96

Я правильно установил скорость и четность, я использовал разные кабели, мой компьютер успешно видит COM3, я думаю, что это связано с программным обеспечением. И я только что изучил понятия последовательного порта/IP/ethernet вместе с базовыми сетевыми знаниями 2-3 дня назад. Я борюсь, вот почему я ищу помощи, я проиграл. Я ставлю точки останова, они все кажутся работающими, последовательный порт открывается, но нет приема данных. Я изучал все сетевые вещи в течение 2-3 дней, я новичок, и у меня очень ограниченное время. Я хорошо общаюсь с устройством, с этим нет никаких проблем.

Рейтинг:
2

phil.o

Это потому что p переменная создается и, таким образом, доступна только в Main метод. В ясном виде: Program пример p В вашем Main метод не тот же самый Program экземпляр, как ваша программа на самом деле работает.
Вы могли бы поставить все, кроме Main метод в своем собственном классе, экземпляр которого вы затем создадите внутри класса. Main метод.
Схематически:

public class SPWrapper
{
   public IPAddress IP { get; protected set; }
   public int Cmd_Port { get; protected set; }
   // ...
}

class Program
{
   private static SPWrapper p;

   static void Main(string[] args)
   {
      p = new SPWrapper();
      // ...
   }
}

p тогда он был бы доступен отовсюду внутри здания. Program класс.


Danny96

Я изменил структуру, но там написано:;
"'SPWrapper.CmdSerialPort' недоступен из-за его уровня защиты" и "свойство или индексатор 'SPWrapper.IP' не может быть использован в этом контексте, поскольку метод доступа set недоступен "

phil.o

Вы должны либо изменить уровень защиты для указанных свойств/методов в новом классе, либо создать конструктор, принимающий аргументы, используемые для настройки внутреннего состояния.
Например, либо объявить

public IPAddress IP { get; set; }
или добавьте конструктор, позволяющий установить это значение:
public SPWrapper(IPAddress address){   IPAddress = address; }

Пожалуйста используйте зеленый цвет Улучшить вопрос виджет и предоставьте новый код.

Danny96

Я исправил частную проблему, она просто дает предупреждение о том, что "CmdSerialPort всегда будет нулевым"

phil.o

Не видя вашего реального кода, мне остается только гадать, а я ненавижу угадывать, когда дело доходит до разработки :)
Пожалуйста, обратитесь к последней фразе моего предыдущего комментария.

Danny96

Я обновил свой код в соответствии с вашей структурой, не могли бы вы мне помочь

phil.o

Какая строка жалуется на последовательный порт, который всегда будет нулевым?

Danny96

-публичная система.IO.Ports.SerialPort CmdSerialPort;" где он определен, говоря, что CmdSerialPort всегда будет равен нулю

phil.o

Ну, вообще-то это просто предупреждение. Вы устанавливаете значение для этого поля из Main метод.
В идеале, все внутренние поля SPWrapper класс должен быть приватным, а для тех, к которым необходимо получить доступ извне, должно быть предоставлено публичное свойство для манипулирования ими.
Вы можете попробовать сделать его собственностью (public System.IO.Ports.SerialPort CmdSerialPort { get; set; }) вместо этого, и посмотреть, если это избавит от предупреждения.

Danny96

да он ушел, но, к сожалению, до сих пор не получит данных

Danny96

спасибо за помощь, я продолжу поиски

phil.o

Пожалуйста. Теперь вы можете запустить сеанс отладки, чтобы попытаться найти проблему. Вам нужна помощь в отладке?

Danny96

Я справлюсь, спасибо. :)