示例#1
0
        /// <summary>
        /// Obsługa komunikatów z klasy MODBUS.
        /// </summary>
        /// <param name="arg"></param>
        private void OnMODBUSCommunicate(MODBUSCommunicateEventArgs arg)
        {
            if (InvokeRequired)
            {
                // Aktualizacja kontrolki z innego wątku.
                MODBUS.MODBUSCommunicateDelegate d = new MODBUS.MODBUSCommunicateDelegate(OnMODBUSCommunicate);
                Invoke(d, new object[] { arg });
                return;
            }

            switch (arg.Type)
            {
                case MODBUSCommunicateType.FrameSent:
                    uxSentHexBox.ByteProvider = new DynamicByteProvider(arg.Frame);
                    break;

                case MODBUSCommunicateType.FrameReceived:
                    uxReceivedHexBox.ByteProvider = new DynamicByteProvider(arg.Frame);
                    break;

                case MODBUSCommunicateType.TextReceived:
                    uxReceivedTextBox.Text = arg.Text;
                    break;

                case MODBUSCommunicateType.ErrorOccured:
                    ShowMessage(arg.Text);
                    break;

                case MODBUSCommunicateType.TextRequest:
                    // Reakcja na rozkaz nr 2 - odesłanie tekstu.
                    MODBUS.Instance.SendMessage((byte)uxStationAddress.Value, 2, uxMessageTextBox.Text);
                    break;

                default:
                    break;
            }
        }
示例#2
0
        /// <summary>
        /// Przetwarza otrzymaną ramkę.
        /// </summary>
        /// <param name="frame"></param>
        private void ProcessFrame(List<byte> frame)
        {
            if (frame.Count == 0)
                return;

            List<byte> data;

            // Dane otrzymane.
            if (_generalTransimssionMode == GeneralTransmissionModeEnum.ASCII)
            {
                 data = ConvertASCIIToBytes(frame);

                 // Nic nie robimy jeśli nie zgadza się suma kontrolna.
                 if (!CheckLRC(data))
                     return;
            }
            else
            {
                // RTU
                data = frame;

                // Nic nie robimy jeśli nie zgadza się suma kontrolna.
                if (!CheckCRC(data))
                    return;
            }

            // Jeśli jesteśmy slavem to sprawdzamy czy ramka jest do nas.
            if (Type == StationTypeEnum.SLAVE && data[0] != StationAddress && data[0] != 0)
                return;

            // Akcje dla slave'a.
            if (Type == StationTypeEnum.SLAVE)
            {
                // Informacja o otrzymanej ramce.
                MODBUSCommunicateEventArgs arg = new MODBUSCommunicateEventArgs(MODBUSCommunicateType.FrameReceived);
                arg.Frame = frame.ToArray();
                Communicate(arg);

                // Tekst ze stacji Master do Slave
                if (data[1] == 1)
                {
                    // Jeśli to nie broadcast to potwierdzenie wykonania rozkazu.
                    if(data[0] != 0)
                        SendMessage(StationAddress, 1, "");

                    List<byte> messageBytes = _generalTransimssionMode == GeneralTransmissionModeEnum.ASCII ?
                        data.GetRange(2, data.Count - 3) :
                        data.GetRange(2, data.Count - 4);

                    // Przetworzenie do tekstu
                    string message = System.Text.Encoding.ASCII.GetString(messageBytes.ToArray());
                    arg = new MODBUSCommunicateEventArgs(MODBUSCommunicateType.TextReceived);
                    arg.Text = message;
                    Communicate(arg);
                }

                // Tekst ze stajcji Slave do Master
                if (data[1] == 2 && data[0] != 0)
                {
                    arg = new MODBUSCommunicateEventArgs(MODBUSCommunicateType.TextRequest);
                    Communicate(arg);
                }
            }

            // Akcje dla Mastera.
            if (Type == StationTypeEnum.MASTER)
            {
                _transactionTimeout.Stop();
                _retransmittedCount = 0;
                _transactionInProgress = false;

                Console.WriteLine("Otrzymano potwierdzenie wykonania rozkazu {0}", data[1]);

                // Informacja o otrzymanej ramce.
                MODBUSCommunicateEventArgs arg = new MODBUSCommunicateEventArgs(MODBUSCommunicateType.FrameReceived);
                arg.Frame = frame.ToArray();
                Communicate(arg);

                // Odczytanie tekstu
                if (data[1] == 2)
                {
                    List<byte> messageBytes = _generalTransimssionMode == GeneralTransmissionModeEnum.ASCII ?
                        data.GetRange(2, data.Count - 3) :
                        data.GetRange(2, data.Count - 4);

                    // Przetworzenie do tekstu
                    string message = System.Text.Encoding.ASCII.GetString(messageBytes.ToArray());
                    arg = new MODBUSCommunicateEventArgs(MODBUSCommunicateType.TextReceived);
                    arg.Text = message;
                    Communicate(arg);
                }
            }
        }
示例#3
0
        /// <summary>
        /// Reakcja na komunikaty z RS232.
        /// </summary>
        /// <param name="arg"></param>
        private void OnRS232Communicate(RS232CommunicateEventArgs arg)
        {
            switch (arg.Type)
            {
                case CommunicateType.ErrorOccured:
                    MODBUSCommunicateEventArgs modbusArg = new MODBUSCommunicateEventArgs(MODBUSCommunicateType.ErrorOccured);
                    modbusArg.Text = arg.ErrorMessage;
                    break;

                case CommunicateType.BinaryDataReceived:
                    _intercharInterval.Stop();

                    // Unieważnienie danych z powodu nieciągłości ramki.
                    if (_discardInBuffer)
                    {
                        _discardInBuffer = false;
                        _inBuffer.Clear();
                    }

                    // Dodanie danych do bufora wejściowego i sprawdzenie czy jest tam ramka ASCII dla trybu ASCII.
                    _inBuffer.AddRange(arg.BinaryData);

                    if(_generalTransimssionMode == GeneralTransmissionModeEnum.ASCII && CheckForASCIIFrameInBuffer())
                    {
                        int start = _inBuffer.IndexOf((byte)':');
                        int end = _inBuffer.IndexOf(0x0A);

                        List<byte> frame = _inBuffer.GetRange(start, end - start + 1);
                        _inBuffer.RemoveRange(start, end - start + 1);
                        ProcessFrame(frame);
                    }

                    // Zresetowanie timera dla trybu RTU
                    if (_generalTransimssionMode == GeneralTransmissionModeEnum.RTU)
                    {
                        _RTUTimer.Stop();
                        _RTUTimer.Start();
                    }

                    // Zapewnienie ciągłości ramki
                    _intercharInterval.Start();
                    break;
                default:
                    break;
            }
        }
示例#4
0
        /// <summary>
        /// Wysyła odpowiednią ramkę z wiadomością, rozkazem i adresem docelowym.
        /// </summary>
        /// <param name="destAddress"></param>
        /// <param name="instructionCode"></param>
        /// <param name="message"></param>
        public void SendMessage(byte destAddress, byte instructionCode, string message)
        {
            // Jeśli korzystamy z rozkazu nr 2 to nie ma sensu wysyłać dodatkowych danych
            // do slave'a.
            if (instructionCode == 2 && Type == StationTypeEnum.MASTER)
                message = "";

            byte[] frame = new byte[] {};
            // Utworzenie ramki
            switch (_generalTransimssionMode)
            {
                case GeneralTransmissionModeEnum.ASCII:
                    frame = CreateASCIIFrame(destAddress, instructionCode, message);
                    break;

                case GeneralTransmissionModeEnum.RTU:
                    frame = CreateRTUFrame(destAddress, instructionCode, message);
                    break;
            }

            // Zapisanie utworzonej ramki w razie potrzeby retransmisji.
            _lastFrame = frame;

            {
                // Poinformowanie o wysłanej ramce.
                MODBUSCommunicateEventArgs arg = new MODBUSCommunicateEventArgs(MODBUSCommunicateType.FrameSent);
                arg.Frame = frame;
                Communicate(arg);
            }

            if (!RS232.Instance.SendBinary(frame))
            {
                MODBUSCommunicateEventArgs arg = new MODBUSCommunicateEventArgs(MODBUSCommunicateType.ErrorOccured);
                arg.Text = "Nie udało się wysłać ramki - błąd zapisu do portu.";
                Communicate(arg);
                return;
            }

            if (Type == StationTypeEnum.MASTER && destAddress != 0)
            {
                _transactionInProgress = true;
                _transactionTimeout.Start();
            }
        }