Exemplo n.º 1
0
        /// <summary>
        /// Асинхронное пакетное чтение множества преременных.
        /// </summary>
        /// <param name="options">Параметры NiBUS-операции.</param>
        /// <param name="target">Адрес устойства.</param>
        /// <param name="ids">Список идентификаторов переменных.</param>
        /// <returns>
        /// Аснихронная задача
        /// </returns>
        /// <seealso cref="ReadProgressInfo"/>
        public async Task ReadManyValuesAsync(NibusOptions options, Address target, params int[] ids)
        {
            //Contract.Requires(options != null);
            //Contract.Requires(options.Progress != null);
            //Contract.Requires(target != null);
            //Contract.Requires(target.Type == AddressType.Hardware || target.Type == AddressType.Net);
            foreach (var splitIds in ids.Split(NmsMessage.NmsMaxDataLength / 3).Select(splitIds => splitIds.ToArray()))
            {
                NmsMessage lastMessage;
                IncomingMessages.TryReceive(null, out lastMessage);
                await OutgoingMessages.SendAsync(new NmsReadMany(target, splitIds));

                var tasks = from id in splitIds
                            select GetNmsReadResponseAsync(lastMessage, target, id, options)
                            .ContinueWith(
                    task =>
                {
                    var rp = new ReadProgressInfo(target, id, task);
                    if (Logger.IsTraceEnabled)
                    {
                        Logger.Trace("Received id={0}, Exc = {1}", rp.Id, rp.Exception);
                    }
                    options.Progress.Report(rp);
                });

                try
                {
                    await Task.WhenAll(tasks.ToArray());
                }
                catch (Exception e)
                {
                    Logger.Error(e, "Read failed");
                }
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Асинхронная проверка доступности устройства.
        /// </summary>
        /// <param name="target">Адрес устройства.</param>
        /// <param name="options">Параметры NiBUS-операции.</param>
        /// <returns>
        /// Возвращает время в миллисекундах, затрачиваемое на отправку запроса
        /// и получение соответствующего сообщения ответа.
        /// </returns>
        /// <value>
        ///   <c>-1</c> - устройство не ответило в течение заданного интервала времени <see cref="NibusOptions.Timeout"/>
        /// либо выполнение было прервано пользователем или статус ответа содержал ошибку.
        ///   </value>
        public async Task <long> PingAsync(Address target, NibusOptions options = null)
        {
            //Contract.Requires(!IsDisposed);
            //Contract.Requires(target != null);
            //Contract.Requires(target.Type == AddressType.Hardware || target.Type == AddressType.Net);
            var queryVersion = new NmsRead(target, (int)StdNms.SoftwareVersion);
            var sw           = new Stopwatch();

            try
            {
                sw.Start();
                await WaitForNmsResponseAsync(queryVersion, options).ConfigureAwait(false);

                sw.Stop();
            }
            catch (TimeoutException)
            {
                return(-1);
            }
            catch (TaskCanceledException)
            {
                return(-1);
            }
            catch (NibusResponseException)
            {
                return(-1);
            }

            return(sw.ElapsedMilliseconds);
        }
Exemplo n.º 3
0
        private void LastMessageDublicate_ThrowTimeout()
        {
            var        nmsProtocol = _stack.GetCodec <NmsCodec>().Protocol;
            var        options     = new NibusOptions();
            NmsMessage lastMessage;

            nmsProtocol.IncomingMessages.TryReceive(null, out lastMessage);
            var query = new NmsRead(Destanation, 2);

            nmsProtocol.OutgoingMessages.Post(query);
            var        wob = new WriteOnceBlock <NmsMessage>(m => m);
            NmsMessage response, response2;

            using (nmsProtocol.IncomingMessages.LinkTo(
                       wob, m => !ReferenceEquals(m, lastMessage) && m.IsResponse && m.ServiceType == query.ServiceType && m.Id == query.Id))
            {
                response = wob.Receive(options.Timeout);
            }
            nmsProtocol.IncomingMessages.TryReceive(null, out lastMessage);
            Assert.That(lastMessage, Is.EqualTo(response));
            var wob2 = new WriteOnceBlock <NmsMessage>(m => m);

            using (nmsProtocol.IncomingMessages.LinkTo(
                       wob2, m => !ReferenceEquals(m, lastMessage) && m.IsResponse && m.ServiceType == query.ServiceType && m.Id == query.Id))
            {
                response2 = wob2.Receive(options.Timeout);
            }
        }
Exemplo n.º 4
0
        // ReSharper disable MemberCanBePrivate.Global

        #region Сервис NmsServiceType.Read

        /// <summary>
        /// Проверка доступности устройства.
        /// </summary>
        /// <param name="target">Адрес устройства.</param>
        /// <param name="options">Параметры NiBUS-операции.</param>
        /// <returns>
        /// Возвращает время в миллисекундах, затрачиваемое на отправку запроса
        /// и получение соответствующего сообщения ответа.
        /// </returns>
        /// <value>
        /// <c>-1</c> - устройство не ответило в течение заданного интервала времени <see cref="NibusOptions.Timeout"/>
        /// либо выполнение было прервано пользователем или статус ответа содержал ошибку.
        /// </value>
        public long Ping(Address target, NibusOptions options = null)
        {
            Contract.Requires(!IsDisposed);
            Contract.Requires(target != null);
            Contract.Requires(target.Type == AddressType.Hardware || target.Type == AddressType.Net);
            return(PingAsync(target, options).Result);
        }
Exemplo n.º 5
0
        /// <summary>
        /// The default Constructor.
        /// </summary>
        /// <param name="incoming">Источник входящих NMS-сообщений.</param>
        /// <param name="outgoing">Канал для исходящих NMS-сообщений.</param>
        internal NmsProtocol(IReceivableSourceBlock <NmsMessage> incoming, ITargetBlock <NmsMessage> outgoing)
        {
            IsDisposed      = false;
            _cts            = new CancellationTokenSource();
            _defaultOptions = new NibusOptions {
                Token = _cts.Token
            };

            IncomingMessages = incoming;
            OutgoingMessages = outgoing;

            if (SynchronizationContext.Current == null)
            {
                SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
            }

            var ui           = TaskScheduler.FromCurrentSynchronizationContext();
            var infoHandlers = new ActionBlock <NmsMessage>(
                message => OnInformationReport((NmsInformationReport)message),
                new ExecutionDataflowBlockOptions
            {
                //CancellationToken = _cts.Token,
                TaskScheduler = ui
            });

            IncomingMessages.LinkTo(
                infoHandlers,
                message => message.ServiceType == NmsServiceType.InformationReport);
        }
Exemplo n.º 6
0
        /// <summary>
        /// Асинхронно остановить устройство с подтверждением успеха.
        /// </summary>
        /// <param name="target">Адрес устройства.</param>
        /// <param name="options">Параметры NiBUS-операции.</param>
        /// <returns><see cref="Task"/> - асинхронная операция.</returns>
        public async Task ShutdownDeviceComfirmedAsync(Address target, NibusOptions options = null)
        {
            //Contract.Requires(!IsDisposed);
            //Contract.Requires(target != null);
            //Contract.Requires(target.Type == AddressType.Hardware || target.Type == AddressType.Net);
            var shutdown = new NmsShutdown(Address.Empty, target);

            await WaitForNmsResponseAsync(shutdown, options);
        }
Exemplo n.º 7
0
        /// <summary>
        /// Асинхронно продолжить выполнять подпрограмму на устройстве с подтверждением успеха операции.
        /// </summary>
        /// <param name="target">Адрес устройства.</param>
        /// <param name="id">Идентификатор подпрограммы.</param>
        /// <param name="options">Параметры NiBUS-операции.</param>
        /// <returns><see cref="Task"/> - асинхронная операция.</returns>
        public async Task ResumeProgramComfirmedAsync(Address target, int id, NibusOptions options = null)
        {
            //Contract.Requires(!IsDisposed);
            //Contract.Requires(target != null);
            //Contract.Requires(target.Type == AddressType.Hardware || target.Type == AddressType.Net);
            var resume = new NmsResume(Address.Empty, target, id);

            await WaitForNmsResponseAsync(resume, options);
        }
Exemplo n.º 8
0
        /// <summary>
        /// Асинхронное чтение переменной.
        /// </summary>
        /// <param name="target">Адрес устройства, с которого необходимо получить значение переменной.</param>
        /// <param name="id">Идентификатор переменной.</param>
        /// <param name="options">Параметры NiBUS-операции.</param>
        /// <returns><see cref="Task{TResult}"/> представляющий асинхронную операцию чтения.</returns>
        /// <seealso cref="WaitForNmsResponseAsync{TMessage}"/>
        public async Task <object> ReadValueAsync(Address target, int id, NibusOptions options = null)
        {
            //Contract.Requires(!IsDisposed);
            //Contract.Requires(target != null);
            //Contract.Requires(target.Type == AddressType.Hardware || target.Type == AddressType.Net);
            var query    = new NmsRead(target, id);
            var response = await WaitForNmsResponseAsync(query, options);

            return(response.Value);
        }
Exemplo n.º 9
0
 private NibusOptions GetDefaultOrClone(NibusOptions options)
 {
     return(options == null
                ? _defaultOptions
                : new NibusOptions
     {
         Attempts = options.Attempts,
         Progress = options.Progress,
         Timeout = options.Timeout,
         Token = options.Token
     });
 }
Exemplo n.º 10
0
        /// <summary>
        /// Асинхронная загрузка массива данных в устройство.
        /// </summary>
        /// <param name="target">Адрес устройства.</param>
        /// <param name="domain">Домен.</param>
        /// <param name="data">Данные.</param>
        /// <param name="offset">Смещение в домене.</param>
        /// <param name="options">Параметры NiBUS-операции.</param>
        /// <returns>
        ///   <see cref="Task"/> - асинхронная операция.
        /// </returns>
        public async Task DownloadDomainAsync(
            Address target,
            string domain,
            byte[] data,
            uint offset,
            NibusOptions options = null)
        {
            //Contract.Requires(!IsDisposed);
            //Contract.Requires(target != null);
            //Contract.Requires(target.Type == AddressType.Hardware || target.Type == AddressType.Net);
            //Contract.Requires(domain != null);
            //Contract.Requires(0 < domain.Length && domain.Length <= 8);

            var query    = new NmsRequestDomainDownload(Address.Empty, target, domain);
            var response = await WaitForNmsResponseAsync(query, options);

            if (data.Length + offset > response.DomainSize)
            {
                throw new ArgumentOutOfRangeException(
                          "data",
                          data.Length + offset,
                          String.Format("Address space overflow detected. Domain size is {0} bytes.", response.DomainSize));
            }

            var downloadOptions = new NibusOptions(options);

            downloadOptions.Attempts = Math.Max(downloadOptions.Attempts, 3);
            if (downloadOptions.Timeout < MinUploadDounloadTimeout)
            {
                downloadOptions.Timeout = MinUploadDounloadTimeout;
            }
            var initiation = new NmsInitiateDownloadSequence(Address.Empty, target, response.Id);

            await WaitForNmsResponseAsync(initiation, downloadOptions);

            foreach (var split in data.Split(16).Select(s => s.ToArray()))
            {
                downloadOptions.Token.ThrowIfCancellationRequested();
                var download = new NmsDownloadSegment(
                    Address.Empty, target, response.Id, offset, split, !response.IsFastDownload);
                if (response.IsFastDownload)
                {
                    await OutgoingMessages.SendAsync(download);
                }
                else
                {
                    await WaitForNmsResponseAsync(download, downloadOptions);
                }

                offset += (uint)split.Length;
            }
        }
Exemplo n.º 11
0
        /// <summary>
        /// Асинхронно начать выполнять подпрограмму на устройстве с подтверждением успеха операции.
        /// </summary>
        /// <param name="target">Адрес устройства.</param>
        /// <param name="id">Идентификатор подпрограммы.</param>
        /// <param name="options">Параметры NiBUS-операции.</param>
        /// <param name="args">Аргументы, передаваемые в подпрограмму в виде массива пар,
        /// где первый элемент пары содержит тип параметра, второй - значение.</param>
        /// <returns><see cref="Task"/> - асинхронная операция.</returns>
        public async Task StartProgramConfirmedAsync(
            Address target,
            int id,
            NibusOptions options = null,
            params Tuple <NmsValueType, object>[] args)
        {
            //Contract.Requires(!IsDisposed);
            //Contract.Requires(target != null);
            //Contract.Requires(target.Type == AddressType.Hardware || target.Type == AddressType.Net);
            var start = new NmsStartProgramInvocation(Address.Empty, target, id, true, args);

            await WaitForNmsResponseAsync(start, options);
        }
Exemplo n.º 12
0
        /// <summary>
        /// Разрешить сигнализацию о событии с подтверждением о приеме.
        /// </summary>
        /// <param name="target">Адрес устройства.</param>
        /// <param name="id">Идентификатор события.</param>
        /// <param name="isEventEnabled"><c>true</c> - разрешить сигнализацию о событии, иначе - <c>false</c>.</param>
        /// <param name="options">Параметры NiBUS-операции.</param>
        /// <returns><see cref="Task"/> - асинхронная операция.</returns>
        public async Task EnableEventMonitoringConfirmedAsync(
            Address target,
            int id,
            bool isEventEnabled,
            NibusOptions options = null)
        {
            Contract.Requires(!IsDisposed);
            Contract.Requires(target != null);
            Contract.Requires(target.Type == AddressType.Hardware || target.Type == AddressType.Net);
            var msg = new NmsAlterEventConditionMonitoring(Address.Empty, target, id, isEventEnabled);

            await WaitForNmsResponseAsync(msg, options);
        }
Exemplo n.º 13
0
        public void NmsProtocol_Ping_MinusOne()
        {
            var nmsProtocol = _stack.GetCodec <NmsCodec>().Protocol;
            var sw          = new Stopwatch();
            var options     = new NibusOptions {
                Timeout = TimeSpan.FromSeconds(1)
            };

            sw.Start();
            Assert.That(nmsProtocol.Ping(Address.CreateMac(1, 2, 3, 4, 5, 6), options), Is.EqualTo(-1));
            sw.Stop();
            Assert.That(sw.ElapsedMilliseconds, Is.InRange(options.Timeout.TotalMilliseconds, options.Timeout.TotalMilliseconds + 150));
        }
Exemplo n.º 14
0
        public void NmsProtocol_ReadMany()
        {
            var nmsProtocol = _stack.GetCodec <NmsCodec>().Protocol;
            var ids         = GetMibIds(@"Z:\mibs\siolynx.mib.xsd");

            Assert.That(ids.Length, Is.GreaterThanOrEqualTo(16));
            var test    = new List <ReadProgressInfo>(ids.Length);
            var options = new NibusOptions {
                Progress = new Progress <object>(pi => test.Add((ReadProgressInfo)pi))
            };

            nmsProtocol.ReadManyValuesAsync(options, Destanation, ids).Wait();
            Assert.That(test.Select(pi => pi.IsFaulted), Is.All.EqualTo(false));
            Assert.That(test.Count, Is.EqualTo(ids.Length));
        }
Exemplo n.º 15
0
        /// <summary>
        /// Асинхронно изменить значение переменной с подтверждением успеха внесения изменений.
        /// </summary>
        /// <param name="target">Адрес устройства, на котором требуется изменить значение переменной.</param>
        /// <param name="id">Идентификатор переменной.</param>
        /// <param name="valueType">Тип значения.</param>
        /// <param name="value">Записываемое значение.</param>
        /// <param name="options">Параметры NiBUS-операции.</param>
        /// <returns>
        ///  <see cref="Task"/> асинхронная операция.
        /// </returns>
        public async Task WriteValueConfirmedAsync(
            Address target,
            int id,
            NmsValueType valueType,
            object value,
            NibusOptions options = null)
        {
            Contract.Requires(!IsDisposed);
            Contract.Requires(target != null);
            Contract.Requires(target.Type == AddressType.Hardware || target.Type == AddressType.Net);
            Contract.Requires(value != null);
            var write = new NmsWrite(target, id, valueType, value);

            await WaitForNmsResponseAsync(write, options);
        }
Exemplo n.º 16
0
        private void ReadValueAsync_ThrowTimeout()
        {
            var nmsProtocol = _stack.GetCodec <NmsCodec>().Protocol;
            var options     = new NibusOptions {
                Attempts = 5, Timeout = TimeSpan.FromSeconds(1)
            };

            try
            {
                nmsProtocol.ReadValueAsync(Address.CreateMac(1, 2, 3, 4, 5, 6), 2, options).Wait();
            }
            catch (AggregateException e)
            {
                throw e.Flatten().InnerException;
            }
        }
Exemplo n.º 17
0
 static void Upload()
 {
     using (var stack = new NibusStack(
                new SerialTransport("COM7", 115200, true),
                new NibusDataCodec(),
                new NmsCodec()))
     {
         var nmsProtocol = stack.GetCodec <NmsCodec>().Protocol;
         try
         {
             var sw      = new Stopwatch();
             var total   = 0;
             var options = new NibusOptions
             {
                 Progress = new Progress <object>(
                     cb =>
                 {
                     if (total == 0)
                     {
                         total = (int)cb;
                         Console.WriteLine("Total: {0}", total);
                     }
                     else
                     {
                         Console.Write("{0}\t{1}\r", cb, (int)cb * 100 / total);
                     }
                 })
             };
             sw.Start();
             var result = nmsProtocol.UploadDomainAsync(Address.CreateMac(0x6c, 0xea), "NVRAM", 0, 0, options).Result;
             sw.Stop();
             Console.WriteLine("Duration: {0}", sw.Elapsed);
             using (var file = File.Create(@"c:\temp\nvram.hex"))
             {
                 file.Write(result, 0, result.Length);
             }
         }
         catch (AggregateException e)
         {
             Console.WriteLine(e.Flatten().InnerException);
         }
     }
 }
Exemplo n.º 18
0
        private async Task <NmsRead> GetNmsReadResponseAsync(
            NmsMessage lastMessage, Address target, int id, NibusOptions options)
        {
            var wob = new WriteOnceBlock <NmsMessage>(m => m);

            using (IncomingMessages.LinkTo(
                       wob,
                       m => !ReferenceEquals(lastMessage, m) && m.IsResponse && m.ServiceType == NmsServiceType.Read &&
                       m.Id == id && (target == Address.Empty || m.Datagram.Source == target)))
            {
                var response = (NmsRead)await wob.ReceiveAsync(options.Timeout, options.Token).ConfigureAwait(false);

                if (response.ErrorCode != 0)
                {
                    throw new NibusResponseException(response.ErrorCode);
                }

                return(response);
            }
        }
Exemplo n.º 19
0
        /// <summary>
        /// Загружает с универсального пульта длительность таймеров и обновляет провайдера игры.
        /// </summary>
        /// <param name="uconsole">Адрес пульта или <c>null</c>.</param>
        /// <remarks>Асинхронная операция.</remarks>
        public async void LoadProvider(Address uconsole = null)
        {
            if (uconsole == null)
            {
                uconsole = Address.Empty;
            }

            var timerInfos = new List <ReadProgressInfo>(12);
            var options    = new NibusOptions
            {
                Progress = new Progress <object>(o => timerInfos.Add((ReadProgressInfo)o))
            };

            await NmsProtocol.ReadManyValuesAsync(
                options,
                uconsole,
                (int)Uconsole.Timer1Min,
                (int)Uconsole.Timer1Sec,
                (int)Uconsole.Timer2Min,
                (int)Uconsole.Timer2Sec,
                (int)Uconsole.Timer3Min,
                (int)Uconsole.Timer3Sec,
                (int)Uconsole.Timer4Min,
                (int)Uconsole.Timer4Sec,
                (int)Uconsole.Timer5Min,
                (int)Uconsole.Timer5Sec,
                (int)Uconsole.Timer6Min,
                (int)Uconsole.Timer6Sec);

            foreach (var progressInfo in timerInfos.Where(pi => !pi.IsFaulted && !pi.IsCanceled))
            {
                switch (progressInfo.Id)
                {
                case (int)Uconsole.Timer1Min:
                    Provider.Timers[0].Duration = (uint)(Provider.Timers[0].Duration % 60 + (byte)progressInfo.Value * 60);
                    break;

                case (int)Uconsole.Timer1Sec:
                    Provider.Timers[0].Duration = (Provider.Timers[0].Duration / 60) * 60 + (byte)progressInfo.Value;
                    break;

                case (int)Uconsole.Timer2Min:
                    Provider.Timers[1].Duration = (uint)(Provider.Timers[0].Duration % 60 + (byte)progressInfo.Value * 60);
                    break;

                case (int)Uconsole.Timer2Sec:
                    Provider.Timers[1].Duration = (Provider.Timers[0].Duration / 60) * 60 + (byte)progressInfo.Value;
                    break;

                case (int)Uconsole.Timer3Min:
                    Provider.Timers[2].Duration = (uint)(Provider.Timers[0].Duration % 60 + (byte)progressInfo.Value * 60);
                    break;

                case (int)Uconsole.Timer3Sec:
                    Provider.Timers[2].Duration = (Provider.Timers[0].Duration / 60) * 60 + (byte)progressInfo.Value;
                    break;

                case (int)Uconsole.Timer4Min:
                    Provider.Timers[3].Duration = (uint)(Provider.Timers[0].Duration % 60 + (byte)progressInfo.Value * 60);
                    break;

                case (int)Uconsole.Timer4Sec:
                    Provider.Timers[3].Duration = (Provider.Timers[0].Duration / 60) * 60 + (byte)progressInfo.Value;
                    break;

                case (int)Uconsole.Timer5Min:
                    Provider.Timers[4].Duration = (uint)(Provider.Timers[0].Duration % 60 + (byte)progressInfo.Value * 60);
                    break;

                case (int)Uconsole.Timer5Sec:
                    Provider.Timers[4].Duration = (Provider.Timers[0].Duration / 60) * 60 + (byte)progressInfo.Value;
                    break;

                case (int)Uconsole.Timer6Min:
                    Provider.Timers[5].Duration = (uint)(Provider.Timers[0].Duration % 60 + (byte)progressInfo.Value * 60);
                    break;

                case (int)Uconsole.Timer6Sec:
                    Provider.Timers[5].Duration = (Provider.Timers[0].Duration / 60) * 60 + (byte)progressInfo.Value;
                    break;
                }
            }
        }
Exemplo n.º 20
0
        /// <summary>
        /// Отправляет NMS-сообщение <paramref name="query"/> и ожидает ответа.
        /// Асинхронная операция.
        /// </summary>
        /// <typeparam name="TMessage">Тип сообщения, потомок NmsMessage.</typeparam>
        /// <param name="query">Сообщение-запрос.</param>
        /// <param name="options">Параметры асинхронной операции.</param>
        /// <returns>
        ///  <see cref="Task{TResult}"/> асинхронная операция - ответное сообщение.
        /// </returns>
        /// <exception cref="AggregateException">Призошла ошибка в асинхронном коде. См. <see cref="Exception.InnerException"/></exception>
        /// <exception cref="TimeoutException">Ошибка по таймауту.</exception>
        /// <exception cref="TaskCanceledException">Операция прервана пользователем.</exception>
        /// <exception cref="NibusResponseException">Ошибка NiBUS.</exception>
        public async Task <TMessage> WaitForNmsResponseAsync <TMessage>(TMessage query, NibusOptions options = null)
            where TMessage : NmsMessage
        {
            //Contract.Requires(!IsDisposed);
            //Contract.Requires(
            //    query.Datagram.Destanation.Type == AddressType.Hardware
            //    || query.Datagram.Destanation.Type == AddressType.Net);

            options = GetDefaultOrClone(options);

            // Последнее сообщение в BroadcastBlock всегда остается! Незабываем его фильтровать.
            NmsMessage lastMessage;

            IncomingMessages.TryReceive(null, out lastMessage);

            var wob = new WriteOnceBlock <NmsMessage>(m => m);

            using (IncomingMessages.LinkTo(
                       wob,
                       m => !ReferenceEquals(lastMessage, m) && m.IsResponse && m.ServiceType == query.ServiceType &&
                       (query.Id == 0 || m.Id == query.Id) && (query.Datagram.Destanation == Address.Empty || m.Datagram.Source == query.Datagram.Destanation)))
            {
                for (var i = 0; i < options.Attempts; i++)
                {
                    await OutgoingMessages.SendAsync(query);

                    try
                    {
                        var response =
                            (TMessage)await wob.ReceiveAsync(options.Timeout, options.Token).ConfigureAwait(false);

                        if (response.ErrorCode != 0)
                        {
                            throw new NibusResponseException(response.ErrorCode);
                        }

                        return(response);
                    }
                    catch (TimeoutException)
                    {
                        Logger.Debug("Timeout {0}", i + 1);
                        if (i < options.Attempts - 1)
                        {
                            continue;
                        }
                        throw;
                    }
                }
            }

            // Эта точка недостижима при attempts > 0!
            throw new InvalidOperationException();
        }
Exemplo n.º 21
0
        /// <summary>
        /// Асинхронная выгрузка массива данных с устройства.
        /// </summary>
        /// <param name="target">Адрес устройства.</param>
        /// <param name="domain">Домен.</param>
        /// <param name="offset">Смещение в домене.</param>
        /// <param name="cbSize">Количество байт.</param>
        /// <param name="options">Параметры NiBUS-операции.</param>
        /// <returns>
        ///   <see cref="Task"/> - асинхронная операция с данными домена.
        /// </returns>
        public async Task <byte[]> UploadDomainAsync(
            Address target,
            string domain,
            uint offset          = 0,
            uint cbSize          = 0,
            NibusOptions options = null)
        {
            //Contract.Requires(!IsDisposed);
            //Contract.Requires(target != null);
            //Contract.Requires(target.Type == AddressType.Hardware || target.Type == AddressType.Net);
            //Contract.Requires(domain != null);
            //Contract.Requires(0 < domain.Length && domain.Length <= 8);

            options = GetDefaultOrClone(options);
            var query    = new NmsRequestDomainUpload(Address.Empty, target, domain);
            var response = await WaitForNmsResponseAsync(query, options);

            if (cbSize > response.DomainSize - offset)
            {
                throw new ArgumentOutOfRangeException(
                          "cbSize",
                          cbSize,
                          String.Format("Address space overflow detected. Domain size is {0} bytes.", response.DomainSize));
            }

            if (cbSize == 0)
            {
                cbSize = response.DomainSize - offset;
            }

            if (options != null && options.Progress != null)
            {
                options.Progress.Report((int)cbSize);
            }

            var uploadOptions = new NibusOptions(options);

            uploadOptions.Attempts = Math.Max(uploadOptions.Attempts, 3);
            if (uploadOptions.Timeout < MinUploadDounloadTimeout)
            {
                uploadOptions.Timeout = MinUploadDounloadTimeout;
            }

            var initiation = new NmsInitiateUploadSequence(Address.Empty, target, response.Id);

            await WaitForNmsResponseAsync(initiation, uploadOptions);

            var uploaded = new List <byte>((int)cbSize);

            while (uploaded.Count < cbSize)
            {
                uploadOptions.Token.ThrowIfCancellationRequested();
                var rest   = cbSize - uploaded.Count;
                var upload = new NmsUploadSegment(
                    Address.Empty, target, response.Id, offset + (uint)uploaded.Count, rest > 58 ? (byte)58 : (byte)rest);
                var respUpload = await WaitForNmsResponseAsync(upload, uploadOptions);

                if (respUpload.Offset != uploaded.Count + offset)
                {
                    if (Logger.IsDebugEnabled)
                    {
                        Logger.Debug(
                            "Invalid offset, resp.ofs = {0}, but = {1}", respUpload.Offset, uploaded.Count + offset);
                    }
                    continue;
                }

                uploaded.AddRange(respUpload.Segment);
                if (uploadOptions.Progress != null)
                {
                    uploadOptions.Progress.Report(uploaded.Count);
                }
            }

            return(uploaded.ToArray());
        }