/// <summary>
 /// Записывает запрос в выходной буфер 
 /// </summary>
 /// <param name="request">Сетевой запрос</param>
 /// <param name="isExternalCall">Признак внешнего вызова</param>
 internal void Enqueue(NetworkRequest request, bool isExternalCall) 
 { 
     if (isExternalCall)
     {
         _OutputBufferExternalCalls.Enqueue(request);
     }
     else
     {
         _OutputBufferInternalCalls.Enqueue(request);
     }
 }
        //[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());
            }
        }
        /// <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();
                    }
            }
        }
 public override IAsyncRequestResult Write(
     NetworkRequest networkRequest, bool isExternalCall = true)
 {
     lock (_syncRoot)
     {
         if (Status == Status.Running)
         {
             networkRequest.TotalAttempts = TotalAttempts;
             _outputBuffer.Enqueue(networkRequest, isExternalCall);
             _autoResetEventWorker.Set();
             return (IAsyncRequestResult)networkRequest.AsyncRequestResult;
         }
         else
         {
             throw new InvalidOperationException(
                 "Невозможно выполнить операцию. Контроллер остановлен");
         }
     }
 }
示例#5
0
 /// <summary>
 /// Записывает транзакцию в буфер исходящих сообщений
 /// </summary>
 /// <param name="request"></param>
 /// <param name="isExternalCall"></param>
 public abstract IAsyncRequestResult Write(NetworkRequest request, bool isExternalCall);
示例#6
0
        /// <summary>
        /// Разбирает ответ по запросу ReadGroupAddress (CMD=20h)
        /// </summary>
        /// <param name="transaction"></param>
        private void GetAnswerReadGroupAddress(NetworkRequest networkRequest)
        {
            // Разбираем ответ
            if (networkRequest.Status == NetworkRequestStatus.Completed)
            {
                var command = _activeRequests.FirstOrDefault(
                    p => p.Id == networkRequest.Id);

                if (command == null)
                {
                    throw new Exception("Не найдена команда с указанной транзакцией");
                }

                if (networkRequest.CurrentTransaction.Answer.ToArray().Length != 11)
                {
                    //command.Status = Result.Error;
                    //command.ErrorDescription = "Неверная длина ответного сообщения";
                    //OnErrorOccurred(new ErrorOccuredEventArgs() { DescriptionError = command.ToString() });
                    //TODO:
                    _activeRequests.Remove(command);
                }

                var request = (DataMessage)networkRequest.Request.Request;
                var answer = (DataMessage)networkRequest.CurrentTransaction.Answer;

                // Проверяем новый адрес в запросе и в ответе
                if (request.Address != answer.Address)
                {
                    //command.Status = Result.Error;
                    //command.ErrorDescription = "Адрес команды в ответе не соответствует адресу в запросе";
                    //OnErrorOccurred(new ErrorOccuredEventArgs() { DescriptionError = command.ToString() });
                    //TODO:
                    _activeRequests.Remove(command);
                }

                if (answer.CmdCode != request.CmdCode)
                {
                    //command.Status = Result.Error;
                    //command.ErrorDescription = "Код команды в ответе не соответствует коду в запросе";
                    //OnErrorOccurred(new ErrorOccuredEventArgs() { DescriptionError = command.ToString() });
                    //TODO:
                    _activeRequests.Remove(command);
                }

                // Получаем параметр
                // Присваиваем новое значение параметру
                var parameter = _parameters[ParameterNamesMercury203.GADDR];
                parameter.Value = parameter.ValueConverter.FromArray(
                    new byte[] 
                    {
                        answer.Data[0],
                        answer.Data[1],
                        answer.Data[2],
                        answer.Data[3]
                    });

                //command.Status = Result.OK;
                _activeRequests.Remove(command);
            }
            else
            {
                // Транзакция выполнена с ошибкам
                var command = _activeRequests.FirstOrDefault(
                    p => p.Id == networkRequest.Id);
                //command.Status = Result.Error;
                //OnErrorOccurred(new ErrorOccuredEventArgs() { DescriptionError = command.ToString() });
                //TODO:
                _activeRequests.Remove(command);
            }
        }
示例#7
0
		public AsyncRequestResult(NetworkRequest networkCommand)
		{
			if (networkCommand == null)
			{
				throw new ArgumentNullException("networkCommand", String.Empty);
			}

			_NetworkRequest = networkCommand;
		}
示例#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;
		}
示例#9
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;
        }
示例#10
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;
		}
示例#11
0
		/// <summary>
		/// Разбирает ответ на запрос записи параметра, общий для команд
		/// записи имеющий структуру ADDR-CMD-CRC
		/// </summary>
		/// <param name="networkRequest"></param>
		private void GetAnswerGeneralWriteRequest(NetworkRequest networkRequest)
		{
			// Разбираем ответ
			if (networkRequest.Status == NetworkRequestStatus.Completed)
			{
				var command = _activeRequests.FirstOrDefault(
					p => p.Id == networkRequest.Id);

				if (command == null)
				{
					throw new Exception("Не найдена команда с указанной транзакцией");
				}

				if (networkRequest.CurrentTransaction.Answer.ToArray().Length != 7)
				{
					//command.Status = Result.Error;
					//command.ErrorDescription = "Неверная длина ответного сообщения";
					//OnErrorOccurred(new ErrorOccuredEventArgs() { DescriptionError = command.ToString() });
					//TODO:
					_activeRequests.Remove(command);
				}

				var request = (DataMessage)networkRequest.Request.Request;
				var answer = (DataMessage)networkRequest.CurrentTransaction.Answer;

				// Проверяем новый адрес в запросе и в ответе
				if (request.Address != answer.Address)
				{
					//command.Status = Result.Error;
					//command.ErrorDescription = "Адрес команды в ответе не соответствует адресу в запросе";
					//OnErrorOccurred(new ErrorOccuredEventArgs() { DescriptionError = command.ToString() });
					//TODO:
					_activeRequests.Remove(command);
				}

				if (answer.CmdCode != request.CmdCode)
				{
					//command.Status = Result.Error;
					//command.ErrorDescription = "Код команды в ответе не соответствует коду в запросе";
					//OnErrorOccurred(new ErrorOccuredEventArgs() { DescriptionError = command.ToString() });
					//TODO:
					_activeRequests.Remove(command);
				}

				//command.Status = Result.OK;
				_activeRequests.Remove(command);
			}
			else
			{
				// Транзакция выполнена с ошибкам
				var command = _activeRequests.FirstOrDefault(
					p => p.Id == networkRequest.Id);
				//command.Status = Result.Error;
				//OnErrorOccurred(new ErrorOccuredEventArgs() { DescriptionError = command.ToString() });
				//TODO:
				_activeRequests.Remove(command);
			}
		}
示例#12
0
        /// <summary>
		/// Разбирает ответ от удалённого устройтва по запросу SetNewAddress (CMD=00h)
        /// </summary>
        /// <param name="networkRequest"></param>
        private void GetAnswerWriteAdderss(NetworkRequest networkRequest)
        {
            var request = (DataMessage)networkRequest.Request.Request;

            // Разбираем ответ
            if (networkRequest.Status == NetworkRequestStatus.Completed)
            {
                var requestArray = networkRequest.Request.Request.ToArray();
                var answerArray = networkRequest.CurrentTransaction.Answer.ToArray();
                var command = _activeRequests.FirstOrDefault(
                    p => p.Id == networkRequest.Id);

                if (command == null)
                {
                    throw new Exception("Не найдена команда с указанной транзакцией");
                }

                if (answerArray.Length != 7)
                {
                    //command.Status = Result.Error;
                    //command.ErrorDescription = "Неверная длина ответного сообщения";
                    //OnErrorOccurred(new ErrorOccuredEventArgs() { DescriptionError = command.ToString() });
                    //TODO: Пишем в лог
                    _activeRequests.Remove(command);
                }

                if (answerArray[4] != request.CmdCode)
                {
                    //command.Status = Result.Error;
                    //command.ErrorDescription = "Код команды в ответе не соответствует коду в запросе";
                    //OnErrorOccurred(new ErrorOccuredEventArgs() { DescriptionError = command.ToString() });
                    //TODO: Пишем в лог
                    _activeRequests.Remove(command);
                }

                // Проверяем новый адрес в запросе и в ответе
                if ((requestArray[6] != answerArray[0]) ||
                    (requestArray[7] != answerArray[1]) ||
                    (requestArray[8] != answerArray[2]) ||
                    (requestArray[9] != answerArray[3]))
                {
                    //command.Status = Result.Error;
                    //command.ErrorDescription =
                    //    "Новый адрес счётчика в ответе не соответствует устанавливаемому";
                    //OnErrorOccurred(new ErrorOccuredEventArgs() { DescriptionError = command.ToString() });
                    //TODO: Пишем в лог
                    _activeRequests.Remove(command);
                }
                
                //Всё в порядке выполняем изменение сетевого адреса
                var converter = new BigEndianUInt32ValueConverter();
                var adr = (UInt32)converter.FromArray(
                    new Byte[] { answerArray[0], answerArray[1], answerArray[2], answerArray[3] });

                Address = adr;
                //command.Status = Result.OK;
                _activeRequests.Remove(command);
            }
            else
            {
                // Транзакция выполнена с ошибкам
                var command = _activeRequests.FirstOrDefault(
                    p => p.Id == networkRequest.Id);

                //command.Status = Result.Error;
                //OnErrorOccurred(new ErrorOccuredEventArgs() { DescriptionError = command.ToString() });
                //TODO: Пишем в лог
                _activeRequests.Remove(command);
            }
        }
示例#13
0
        private void GetAnswer(NetworkRequest networkRequest)
        {
            var request = (DataMessage)networkRequest.Request.Request;
            //ищем устройтво
            var device = (Mercury203)_NetworkController.Devices[request.Address];

            switch ((Mercury203CmdCode)request.CmdCode)
            {
				case Mercury203CmdCode.WriteAddress:
					{
						GetAnswerWriteAdderss(networkRequest); break;
					}
				case Mercury203CmdCode.WriteGroupAddress:
					{
						GetAnswerGeneralWriteRequest(networkRequest); break;
					}
				case Mercury203CmdCode.WriteDateTime:
					{
						GetAnswerGeneralWriteRequest(networkRequest); break;
					}
				case Mercury203CmdCode.WriteLimitPower:
					{
						GetAnswerGeneralWriteRequest(networkRequest); break;
					}
				case Mercury203CmdCode.WriteAmountOfActiveTariffs:
					{
						GetAnswerGeneralWriteRequest(networkRequest); break;
					}
                case Mercury203CmdCode.ReadGroupAddress:
                    {
                        GetAnswerReadGroupAddress(networkRequest); break;
                    }
				case Mercury203CmdCode.ReadDateTime:
					{
						GetAnswerReadDateTime(networkRequest); break;
					}
				case Mercury203CmdCode.ReadTariffAccumulators:
					{
						GetAnswerReadTariffAccumulators(networkRequest); break;
					}
				case Mercury203CmdCode.ReadPowerLimit:
					{
						GetAnswerPowerLimit(networkRequest); break;
					}
                default:
                    {
                        throw new NotImplementedException(
                            String.Format("Устройтво Mercury 203 не поддерживает команду с кодом {0}",
                            request.CmdCode));
                    }
            }

        }
		public IAsyncRequestResult Write(
			NetworkRequest request, bool isExternalCall)
		{
			throw new NotImplementedException();
		}