//[ExpectedException(typeof(InvalidOperationException), "")]
        public void TestWriteByWrongReqeustType()
        {
            // Arrange
            var msg = new DataMessage(new byte[] { 0, 0, 0, 2 })
            {
                Address = 1,
                CmdCode = 0x20,
                MessageType = MessageType.IncomingMessage
            };

            Mock<IDataLinkPort> comPort = new Mock<IDataLinkPort>();
            comPort.Setup(p => p.IsOpen).Returns(true);
            comPort.Setup(p => p.MessagesToRead).Returns(0);

            comPort.Setup(p => p.Write(It.IsAny<IMessage>()))
                .Raises(m => m.MessageReceived += null, new EventArgs());
            comPort.Setup(p => p.Read()).Returns(msg);

            var controller = new IncotexNetworkController();
            controller.Connection = comPort.Object;
            var device = new Mercury203();
            controller.Devices.Add(device);
            controller.Start();

            var request = new DataMessage()
            {
                Address = 0x1,
                CmdCode = Convert.ToByte(Mercury203CmdCode.ReadGroupAddress)
            };
            var wrongTrans = new Transaction(null, TransactionType.Undefined, request) { Sender = device }; // Ошибка !!!
            var networkRequest = new NetworkRequest(wrongTrans);

            // Act
            try
            {
                controller.Write(networkRequest);

                while (networkRequest.Status != NetworkRequestStatus.Failed)
                {
                    // Ждём, должно быть исключение
                }
            }
            catch (Exception ex)
            {
                // Assert
                Assert.AreEqual(typeof(InvalidOperationException), ex.GetType());
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Обработчик срабатываения таймера межкадрового интервала
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void EventHandler_TimerInterFrameDelay_Elapsed(
            object sender, ElapsedEventArgs e)
        {
            DataMessage message;
            ServiceErrorMessage errMessage;
            // Если сработал межкадровый таймер, значит сообщение полностью
            // принято.
            List<Byte> list = new List<byte>();
            // Получаем массив байт принятого сообщения
            while(_serialPort.BytesToRead != 0)
            {
                 list.Add((Byte)_serialPort.ReadByte());
            }
            
			// Проверяем форат сообщения
            // Минимальная длина сообщения 1 байт: 
            //          [ADDR: 4 байта] + [CMD: 1 байт] + [DATA: 0 байт] + [CRC16: 2 байта] = 7 байт
            if (list.Count < 7)
            {
                //TODO: Ошибка. Создать служебное сообщение об ошибке
                errMessage = new ServiceErrorMessage
                {
                    SpecificErrorCode = ErrorCode.IncorrectMessageLength,
                    Description = "Неправильная длина сообщения",
                    ExecutionTime = DateTime.Now
                };
                
                _InputBuffer.Enqueue(errMessage);
                OnMessageReceived();
				return;
            }

            // Проверяем CRC16
            var array = new Byte[list.Count - 2];
			list.CopyTo(0, array, 0, array.Length);
			if (!CRC16.CheckCRC16(list.ToArray()))
			{
				errMessage = new ServiceErrorMessage
				{
					SpecificErrorCode = ErrorCode.IncorrectCRC,
					Description = "Неправильная контрольная сумма",
					ExecutionTime = DateTime.Now
				};

				_InputBuffer.Enqueue(errMessage);
				OnMessageReceived();
				return;
			}

            // Получаем данные сообщения
			array = new Byte[list.Count - 7]; // 7 = 5 [adr:4 cmd: 1] + 2 [crc16: 2]
            list.CopyTo(5, array, 0, array.Length);

			// Получаем адрес устройства
            UInt32 adr = 0;
			//adr |= ((UInt32)list[3] << 24);
			//adr |= ((UInt32)list[2] << 16);
			//adr |= ((UInt32)list[1] << 8);
			//adr |= list[0];

			var arrayAdr = new Byte[4];
			list.CopyTo(0, arrayAdr, 0, 4);
			if (BitConverter.IsLittleEndian)
				Array.Reverse(arrayAdr);
			adr = BitConverter.ToUInt32(arrayAdr, 0); 

            message = new DataMessage(array) 
            { 
                MessageType = MessageType.IncomingMessage,
                Address = adr,
                CmdCode = list[4],
                ExecutionTime = DateTime.Now 
            };
			
			// Формируем сообщение и сохраняем его в буфер
			_InputBuffer.Enqueue(message);
			OnMessageReceived();
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Выполняет сетевую транзакцию 
        /// </summary>
        /// <param name="networkRequest"></param>
        public void ExecuteTransaction(NetworkRequest networkRequest)
        {
            if ((CurrentNetworkRequest != null) &&
                (CurrentNetworkRequest.Status == NetworkRequestStatus.Running))
            {
                throw new InvalidOperationException(
                    "Попытка выполнить транзакцию во время действия другой");
            }

            if ((networkRequest.CurrentTransaction.TransactionType != TransactionType.BroadcastMode) &&
                (networkRequest.CurrentTransaction.TransactionType != TransactionType.UnicastMode))
            {
                networkRequest.CurrentTransaction.Start();
                networkRequest.CurrentTransaction.Abort(new TransactionError
                {
                    ErrorCode = TransactionErrorCodes.TransactionTypeIsWrong,
                    Description = "Попытка запустить сетевую транзакцию с недопустимым типом"
                });
                throw new InvalidOperationException(
                    String.Format("Попытка запустить сетевую транзакцию с недопустимым типом: {0}",
                    networkRequest.CurrentTransaction.TransactionType));
            }

            // Устанавливаем транзакцию в качестве текущей
            _currentNetworkRequest = networkRequest;
            var result = _currentNetworkRequest.AsyncRequestResult;

            // Если запрос адресованный, то ждём ответа
            // Если запрос широковещательный выдерживаем установленную паузу
            switch (_currentNetworkRequest.CurrentTransaction.TransactionType)
            {
                case TransactionType.UnicastMode:
                    {
                        var disconnected = false;

                        for (int i = 0; i < TotalAttempts; i++)
                        {
                            // Отправляем запрос к удалённому устройтву
                            _currentNetworkRequest.CurrentTransaction.Start();
                            _Connection.Write(_currentNetworkRequest.CurrentTransaction.Request);

                            // Ждём ответа от удалённого устройтва или тайм аут
                            if (!_autoResetEventRequest.WaitOne(_requestTimeout))
                            {
                                // TimeOut!!! Прекращает текущую транзакцию
                                _currentNetworkRequest.CurrentTransaction.Abort(new TransactionError
                                {
                                    ErrorCode = TransactionErrorCodes.RequestTimeout,
                                    Description = "Request timeout"
                                });
                                
                                Transaction trn;
                                // Повторяем запрос
                                _currentNetworkRequest.NextAttempt(out trn);
                                disconnected = true;
                                continue;                               
                            }
                            else
                            {
                                // Ответ получен
                                _currentNetworkRequest.CurrentTransaction.Stop(_CurrentIncomingMessage);
                                _CurrentIncomingMessage = null;
                                disconnected = false;
                                break;
                            }
                        }
                        
                        // Кол-во попыток доступа к устройтсву исчерпано
                        if (disconnected)
                        {

                            //var errors = ((DeviceBase)_CurrentNetworkRequest.CurrentTransaction.Sender).Errors;
                            //errors.CommunicationError = true;
                            //((DeviceBase)_CurrentNetworkRequest.CurrentTransaction.Sender).SetError(errors);
                        }
                        else
                        {
                            // Если ранее была установлена ошибка связи, то сбрасываем её
                            //var errors = ((DeviceBase)_CurrentNetworkRequest.CurrentTransaction.Sender).Errors;
                            //if (errors.CommunicationError == true)
                            //{
                            //    errors.CommunicationError = false;
                            //    ((DeviceBase)_CurrentNetworkRequest.CurrentTransaction.Sender).SetError(errors);
                            //}
                        }

						result.SetCompleted();

                        OnNetwrokRequestCompleted(
                            new NetworkRequestCompletedArgs { NetworkRequest = _currentNetworkRequest });

                        break;
                    }
                case TransactionType.BroadcastMode:
                    {
                        // Отправляем запрос к удалённому устройтву
                        _currentNetworkRequest.CurrentTransaction.Start();
                        _Connection.Write(_currentNetworkRequest.CurrentTransaction.Request);

                        if (!_autoResetEventRequest.WaitOne(_broadcastRequestDelay))
                        {
                            _currentNetworkRequest.CurrentTransaction.Stop(null);
                        }
                        else
                        {
                            _CurrentIncomingMessage = null;
                            throw new Exception(
                                "Принят ответ от удалённого устройтства во время широковещательного запроса");
                        }

						result.SetCompleted();
						
						OnNetwrokRequestCompleted(
							new NetworkRequestCompletedArgs { NetworkRequest = _currentNetworkRequest });

                        break;
                    }
                default:
                    {
                        result.SetCompleted();
                        throw new NotSupportedException();
                    }
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Обработчик приёма сообщения из сети
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected override void EventHandler_Connection_MessageReceived(
            object sender, EventArgs e)
        {
            IDataLinkPort port = (IDataLinkPort)sender;
            var messages = new List<MessageBase>();
            
            // Читаем входящие сообщения из входного буфера порта 
            while(port.MessagesToRead > 0)
            {
                var msg = port.Read();
                messages.Add((MessageBase)msg);
            }

            // Обрабатываем сервисные сообщения
            var serviceErrorMessages = messages
                .Where(y => y.MessageType == MessageType.ServiceErrorMessage)
                .Select(z => (ServiceErrorMessage)z);

            foreach (var msg in serviceErrorMessages)
            {
                //запись в лог ошибок
                Logger.Error(String.Format("Controller Id={0} | Ошибка Code={1} | Description={2}",
                    _Id, msg.Code, msg.Description));

                //TODO: Сделать обработчик ошибок, если потребуется
                //switch (msg.SpecificErrorCode)
                //{
                //    case ErrorCode.
                //}
            }

            // TODO: сделать сервистные сообщения, если понадобятся 
            //var serviceInfoMessages = messages
            //    .Where(y => y.MessageType == MessageType.ServiceInfoMessage)
            //    .Select(z => (....));

            var dataMessages = messages
                .Where(y => y.MessageType == MessageType.IncomingMessage)
                .Select(z => (DataMessage)z).ToArray();

            if (dataMessages.Length > 1)
            {
                throw new Exception(
                    "Сетевой контроллер принял одновременно более одного сообщения из сети");
            }

            if ((_currentNetworkRequest == null) || 
                (_currentNetworkRequest.Status != NetworkRequestStatus.Running))
            {
                throw new Exception("Принято сообщение в отсутствии запроса");
            }

            // Обрабатывает сообщение
            _CurrentIncomingMessage = dataMessages[0];
			_autoResetEventRequest.Set();
		}
        public void TestReadGroupAddressSuccess()
        {
            // Arrange
            int amount = 1;

            var msg = new DataMessage(new byte[] { 0, 0, 0, 2 })
            {
                Address = 1,
                CmdCode = 0x20,
                MessageType = MessageType.IncomingMessage
            };

            Mock<IDataLinkPort> comPort = new Mock<IDataLinkPort>();
            //comPort.Setup(p => p.GetType()).Returns(typeof(IncotexNetworkController));
            comPort.Setup(p => p.IsOpen).Returns(true);
            comPort.Setup(p => p.MessagesToRead)
                .Returns(() => amount)
                .Callback(() => amount--);

            comPort.Setup(p => p.Write(It.IsAny<IMessage>()))
                .Raises(m => m.MessageReceived += null, new EventArgs());
            comPort.Setup(p => p.Read()).Returns(msg);

            var controller = new IncotexNetworkController();
            controller.Connection = comPort.Object;
            controller.Start();
            //controller.Stop();

            var device = new Mercury203()
            {
                Address = 1,
            };

            controller.Devices.Add(device);

            // Act
            var result = device.ReadGroupAddress();
            //controller.Write(trans);
            do
            {
                // Ждём выполения комманды
            }
            while (!result.IsCompleted);

            // Assert
            Assert.AreEqual(TransactionStatus.Completed, result.Stack[result.Stack.Length - 1].Status, "Success");
        }
        //[ExpectedException(typeof(InvalidOperationException), "")]
        public void TestReadGroupAddressByControllerIsStopped()
        {
            // Arrange
            var msg = new DataMessage(new byte[] { 0, 0, 0, 2 })
            {
                Address = 1,
                CmdCode = 0x20,
                MessageType = MessageType.IncomingMessage
            };

            Mock<IDataLinkPort> comPort = new Mock<IDataLinkPort>();
            comPort.Setup(p => p.IsOpen).Returns(true);
            comPort.Setup(p => p.MessagesToRead).Returns(0);

            comPort.Setup(p => p.Write(It.IsAny<IMessage>()))
                .Raises(m => m.MessageReceived += null, new EventArgs());
            comPort.Setup(p => p.Read()).Returns(msg);

            var controller = new IncotexNetworkController();
            controller.Connection = comPort.Object;
            controller.Stop(); // Контроллер остановлен

            var device = new Mercury203()
            {
                Address = 1,
            };

            controller.Devices.Add(device);

            Type type = null;

            // Act
            try
            {
                var result = device.ReadGroupAddress();
            }
            catch (Exception ex)
            {
                type = ex.GetType();
            }

            // Assert
            Assert.AreEqual(typeof(InvalidOperationException), type);

            // Assert
            //while(true)
            //{
                // Ждём должно быть исключение
            //}
        }
Ejemplo n.º 7
0
        public IAsyncRequestResult ReadGroupAddress(bool isExternalCall = true)
        {
            var request = new DataMessage()
            {
                Address = Address,
                CmdCode = Convert.ToByte(Mercury203CmdCode.ReadGroupAddress)
            };
            var transaction = new Transaction(this, TransactionType.UnicastMode, request)
            { 
                Sender = this 
            };

            var networkRequest = new NetworkRequest(transaction);

            if (_NetworkController == null)
            {
                transaction.Start();
                transaction.Abort(new TransactionError
                {
                    ErrorCode = TransactionErrorCodes.DataLinkPortNotInstalled,
                    Description = "Невозможно выполенить запрос. Не установлен контроллер сети"
                });
                networkRequest.AsyncRequestResult.SetCompleted();
            }
            else
            {
                _activeRequests.Add(networkRequest);
                _NetworkController.Write(networkRequest, isExternalCall);
            }
            return (IAsyncRequestResult)networkRequest.AsyncRequestResult;
        }
Ejemplo n.º 8
0
		/// <summary>
		/// Установка тарифа (CMD=0Bh)
		/// </summary>
		/// <param name="value"></param>
		/// <param name="isExternalCall"></param>
		/// <returns></returns>
		public IAsyncRequestResult WriteActiveTariff(byte value, bool isExternalCall = true)
		{
			if ((value < 1) || (value > 4))
			{
				throw new ArgumentOutOfRangeException("Amount",
					"Действующий тарифов должн быть от 1 до 4");
			}

			var request = new DataMessage(
				Mpower.GetValueConveter().ToArray(value))
			{
				Address = Address,
				CmdCode = Convert.ToByte(Mercury203CmdCode.WriteActiveTariff)
			};

			var transaction = new Transaction(this, TransactionType.UnicastMode, request)
			{
				Sender = this
			};

			var networkRequest = new NetworkRequest(transaction);

			if (_NetworkController == null)
			{
				transaction.Start();
				transaction.Abort(new TransactionError
				{
					ErrorCode = TransactionErrorCodes.DataLinkPortNotInstalled,
					Description = "Невозможно выполенить запрос. Не установлен контроллер сети"
				});
				networkRequest.AsyncRequestResult.SetCompleted();
			}
			else
			{
				_activeRequests.Add(networkRequest);
				_NetworkController.Write(networkRequest, isExternalCall);
			}

			return (IAsyncRequestResult)networkRequest.AsyncRequestResult;
		}
Ejemplo n.º 9
0
		/// <summary>
		/// Широковешательная команда записи времени и даты во все устройтсва
		/// сети с указанным групповым адресом
		/// </summary>
		/// <param name="dateTime"></param>
		/// <param name="groupAddress">Групповой адрес устройтсв</param>
		/// <param name="networkController"></param>
		/// <param name="isExternalCall"></param>
		/// <returns></returns>
		/// <remarks>Ответ на данный тип запросов не приходит, 
		/// только создаётся временная выдержка</remarks>
		public static IAsyncRequestResult WriteDateTimeInGroupDevices(
			DateTime dateTime, 
			UInt32 groupAddress, 
			INetwrokController networkController, 
			bool isExternalCall = true)
		{
			var request = new DataMessage(
				new IncotexDataTimeTypeConverter().ToArray(IncotexDateTime.FromDateTime(dateTime)))
			{
				Address = groupAddress,
				CmdCode = Convert.ToByte(Mercury203CmdCode.WriteDateTime)
			};

			var transaction = new Transaction(null, TransactionType.BroadcastMode, request)
			{
				Sender = null
			};

			var networkRequest = new NetworkRequest(transaction);

			if (networkController == null)
			{
				transaction.Start();
				transaction.Abort(new TransactionError
				{
					ErrorCode = TransactionErrorCodes.DataLinkPortNotInstalled,
					Description = "Невозможно выполенить запрос. Не установлен контроллер сети"
				});
				networkRequest.AsyncRequestResult.SetCompleted();
			}
			else
			{
				networkController.Write(networkRequest, isExternalCall);
			}
			return (IAsyncRequestResult)networkRequest.AsyncRequestResult;
		}