Пример #1
0
 private void PushRawToAllActiveSinks(string message, params object[] sinkArgs)
 {
     foreach (var sink in Sinks.Where(x => x.Active))
     {
         sink.Write(message, sinkArgs);
     }
 }
Пример #2
0
 public void CreateInputs()
 {
     Sinks.Add("AngleSetpoint", new InputSignalViewModel("AngleSetpoint", FriendlyName));
     Sinks.Add("JogForward", new InputSignalViewModel("JogForward", FriendlyName));
     Sinks.Add("JogReverse", new InputSignalViewModel("JogReverse", FriendlyName));
     Sinks.Add("JogSpeed", new InputSignalViewModel("JogSpeed", FriendlyName));
 }
Пример #3
0
 public bool UnregisterMessageSink(IMessageSink sink)
 {
     if (!Sinks.Contains(sink))
     {
         return(false);
     }
     Sinks.Remove(sink);
     return(true);
 }
Пример #4
0
 public bool RegisterMessageSink(IMessageSink sink)
 {
     if (Sinks.Contains(sink))
     {
         return(true);
     }
     Sinks.Add(new MessageSink(sink, Messages));
     FlushMessages();
     return(true);
 }
Пример #5
0
        public virtual async Task <object> Process(object input)
        {
            var type = input.GetType();

            if (Sinks.ContainsKey(type))
            {
                return(await Sinks[type].ConvertAsync(input));
            }

            return(null);
        }
Пример #6
0
        public Log SinkTo <T>() where T : Sink, new()
        {
            EnsureNotClosed();

            if (SinkExists <T>())
            {
                throw new DuplicateSinkException(typeof(T));
            }

            Sinks.Add(new T());
            return(this);
        }
Пример #7
0
        static public A roundTrip <A, F>(A a, Writer <A, F> w, Reader <A, F> r)
        {
            var ms   = new System.IO.MemoryStream();
            var sink = Sinks.ToOutputStream(ms);

            w.Bind(sink).Invoke(a);
            sink.Finished();
            // NOTE: don't remove this. its super useful.
            //Console.Write("bytes: " + ms.ToArray().Select((x) => x.ToString()).Aggregate((x,y) => x + ", " + y) + "\n");
            var o = r.Bind(Sources.FromByteArray(ms.ToArray())).Get;

            return(o);
        }
Пример #8
0
        public Log SinkTo(Sink sink)
        {
            EnsureNotClosed();

            var sinkType = sink.GetType();

            if (SinkExists(sinkType))
            {
                throw new DuplicateSinkException(sinkType);
            }

            Sinks.Add(sink);

            return(this);
        }
Пример #9
0
        public void Listen()
        {
            if (Routes.Count() == 0)
            {
                Logger.Info("No routes specified. All emitted values will be passed on to all sinks.");
                Observable
                .Merge(Sources.Select((it) => it.Get()))
                .Catch(Observable.Empty <object>())
                .Subscribe((value) =>
                {
                    Sinks.ForEach((sink) => sink.Consume(value));
                });
                return;
            }

            Logger.Info("Setting up routes...");
            Routes.ForEach(route =>
            {
                var source = Sources.Find(source => source.Id == route.From);
                var sinks  = Sinks.Where(sink => route.To.Contains(sink.Id)).ToList();
                Logger.Info($"Values from {source} will be passed on to {string.Join(", ", sinks.Select(it => it.ToString()))}");

                source
                .Get()
                .Catch(Observable.Empty <object>())
                .Subscribe((value) =>
                {
                    sinks.ForEach((sink) => sink.Consume(value));
                });
            });

            var unconnectedSources = Sources.Where((source) => !Routes.Select((route) => route.From).Contains(source.Id));
            var unconnectedSinks   = Sinks.Where((sink) => !Routes.SelectMany((route) => route.To).Contains(sink.Id));

            if (unconnectedSources.Count() > 0)
            {
                Logger.Warn($"Found {unconnectedSources.Count()} unconnected sources. Emitted values from those will never be processed by any sinks:");
                Logger.Warn(string.Join(", ", unconnectedSources.Select(source => source.ToString())));
            }

            if (unconnectedSinks.Count() > 0)
            {
                Logger.Warn($"Found {unconnectedSinks.Count()} unconnected sinks (not targeted by any route):");
                Logger.Warn(string.Join(", ", unconnectedSinks.Select(sink => sink.ToString())));
                Logger.Warn("Please double check your configuration");
            }
        }
Пример #10
0
        private void DecorateAndPushToAllActiveSinks(LogLevel logLevel, string message, params object[] sinkArgs)
        {
            foreach (var sink in Sinks.Where(x => x.Active))
            {
                var actualOutput = Template;

                foreach (var kvp in Decorators)
                {
                    actualOutput = actualOutput.Replace(
                        kvp.Key,
                        kvp.Value.Decorate(logLevel, actualOutput, message, sink)
                        );
                }

                sink.Write(logLevel, actualOutput, sinkArgs);
            }
        }
Пример #11
0
        private void ProcessAwaitInput(SpectrumProcessor sink)
        {
            CurrentActivityDescription = "Awaiting signal...";

            var allInputSingnalsPresent = _testSignalPresentMap.Values.All(v => v == true);

            if (!allInputSingnalsPresent)
            {
                var expectedLoopbackDelay = Math.Max(
                    (AppSettings.Current.Device.InputDevice.LatencyMilliseconds + AppSettings.Current.Device.OutputDevice.LatencyMilliseconds),
                    2.0 * 1000.0 * Settings.Fft.Value.WindowSize / AppSettings.Current.Device.SampleRate
                    );

                if (Elapsed.TotalMilliseconds > expectedLoopbackDelay)
                {
                    var channel = Sinks.First(s => s.Value == sink).Key;
                    _testSignalPresentMap[channel] = CheckSignalPresent(sink.Data);

                    if (!_testSignalPresentMap[channel])
                    {
                        var channels = _testSignalPresentMap.Where(m => m.Value == false).Select(m => m.Key.ToString()).OrderBy(k => k);

                        var message = $"No test signal detected in channels {channels.Aggregate((a, b) => (a + ", " + b))}.";
                        OnError(new Exception(message));
                        Stop(true);

                        return;
                    }


                    _inputSignalReceivedAt = DateTime.Now;
                    if (Settings is IWarmable warmable)
                    {
                        _phase = Phase.WarmUp;
                    }
                    else
                    {
                        SetGatheringPhase(sink);
                    }

                    sink.Data.Reset();
                }
            }
        }
Пример #12
0
        public void Close()
        {
            EnsureNotClosed();

            foreach (var sink in Sinks)
            {
                if (sink is IDisposable disposable)
                {
                    disposable.Dispose();
                }

                sink.Active = false;
            }

            Sinks.Clear();
            Decorators.Clear();

            HasBeenClosed = true;
        }
Пример #13
0
        /// <summary>
        /// Gets the average storage time for the time period. Calculated as mean volume divide by mean (sinks + outflow + evaporation)
        /// </summary>
        /// <param name="Start"></param>
        /// <param name="End"></param>
        /// <returns></returns>
        public TimeSpan GetStorageTime(DateTime Start, DateTime End)
        {
            if (!IsEmpty)
            {
                if (EndTime < End || StartTime > Start)
                {
                    throw new Exception("Cannot calculate storage time outside of the simulated period");
                }

                //Find the total outflow
                double d = Sinks.GetSiValue(Start, End);
                d += Outflow.GetSiValue(Start, End);
                //Evaporation is negative
                d += Evaporation.GetSiValue(Start, End);
                d += GroundwaterOutflow.GetSiValue(Start, End);

                return(TimeSpan.FromSeconds(StoredVolume.GetSiValue(Start, End) / d));
            }
            return(TimeSpan.Zero);
        }
Пример #14
0
 private bool SinkExists(Type type)
 => Sinks.Exists(x => x.GetType() == type);
Пример #15
0
 /// <summary>
 /// Sets write function that will be used for logging messages
 /// </summary>
 /// <param name="writeFunction">Function receiving <see cref="string"/> message parameter</param>
 public static void WriteTo(Action <string> writeFunction)
 {
     Sinks.Add(writeFunction);
 }
Пример #16
0
 public void AddSink(SinkFunction sf)
 {
     Sinks.Add(sf);
 }
Пример #17
0
 // add a sink for logging
 public void AddSink(iLogSink sink)
 {
     Sinks.AddFirst(sink);
 }
Пример #18
0
 public Broker RegisterSinks(params ISink[] sinks)
 {
     Sinks.AddRange(sinks);
     return(this);
 }
Пример #19
0
 public void Add <T>(Func <T, object> callback)
 {
     Sinks.TryAdd(typeof(T), new ConversionAdapter <T, object>(callback));
 }
Пример #20
0
        /// <summary>
        /// This is the timestepping procedure
        /// </summary>
        /// <param name="TimeStep"></param>
        public void Update(DateTime NewTime)
        {
            CurrentTimeStep = NewTime.Subtract(CurrentTime);
            #region Sum of Sinks and sources

            //Sum the sources
            var          GWFlow       = GroundwaterBoundaries.Where(var => var.IsSource(CurrentTime)).Select(var => var.GetSourceWater(CurrentTime, CurrentTimeStep));
            var          SourceFlow   = Sources.Select(var => var.GetSourceWater(CurrentTime, CurrentTimeStep));
            IWaterPacket InFlow       = WaterMixer.Mix(GWFlow.Concat(SourceFlow));
            double       InflowVolume = 0;
            if (InFlow != null)
            {
                InflowVolume = InFlow.Volume;
            }

            //Sum the Evaporation boundaries
            double EvapoVolume = _evapoBoundaries.Sum(var => var.GetSinkVolume(CurrentTime, CurrentTimeStep));

            //Sum the sinks
            double SinkVolume = Sinks.Sum(var => var.GetSinkVolume(CurrentTime, CurrentTimeStep));
            //Add the sinking groundwater boundaries
            SinkVolume += GroundwaterBoundaries.Where(var => !var.IsSource(CurrentTime)).Sum(var => var.GetSinkVolume(CurrentTime, CurrentTimeStep));
            double sumSinkSources = InflowVolume - EvapoVolume - SinkVolume;

            //If we have no water from upstream but Inflow, remove water from inflow to fill stream
            if (sumSinkSources / Volume > 5)
            {
                AddWaterPacket(CurrentTime, NewTime, InFlow.Substract(sumSinkSources - Volume * 5));
                InflowVolume   = InFlow.Volume;
                sumSinkSources = InflowVolume - EvapoVolume - SinkVolume;
            }

            //Sort the incoming water an put in to queue
            PrePareIncomingWater();

            //Calculate the surplus
            WaterToRoute = _waterInStream.Sum(var => var.Volume) + InflowVolume - EvapoVolume - SinkVolume - Volume + _incomingWater.Sum(var => var.Volume);

            //If the loss is bigger than available water, reduce Evaporation and Sinks
            if (WaterToRoute + Volume < 0)
            {
                double reductionfactor = 1 + (WaterToRoute + Volume) / (EvapoVolume + SinkVolume);
                EvapoVolume *= reductionfactor;
                SinkVolume  *= reductionfactor;
                WaterToRoute = 0;
            }

            //Convert to rates
            double qu   = sumSinkSources / CurrentTimeStep.TotalSeconds / Volume;
            double qop  = _incomingWater.Sum(var => var.Volume) / CurrentTimeStep.TotalSeconds;
            double qout = qu * Volume + qop;

            //Create a mixer class
            Mixer M = new Mixer(InFlow, EvapoVolume, SinkVolume);

            #endregion

            #region Stored water
            //Send stored water out
            if (WaterToRoute > 0)
            {
                double OutflowTime = 0;

                //The volume that needs to flow out to meet the watertotroute
                double VToSend = WaterToRoute;
                if (qu != 0)
                {
                    VToSend = qout / qu * (1 - 1 / (Math.Exp(qu * CurrentTimeStep.TotalSeconds)));
                }
                //There is water in the stream that should be routed
                while (VToSend > 0 & _waterInStream.Count > 0)
                {
                    IWaterPacket IW;
                    //Mixing during flow towards end of stream
                    double dv = _waterInStream.Peek().Volume *(Math.Exp(qu * OutflowTime) - 1);

                    //Check if the entire water packet should flow out or it should be split
                    if (_waterInStream.Peek().Volume + dv < VToSend)
                    {
                        IW = _waterInStream.Dequeue();
                    }
                    else
                    {
                        IW = _waterInStream.Peek().Substract(VToSend);
                    }

                    //Update how mush water is yet to be routed
                    VToSend -= IW.Volume;
                    //Now do the mix
                    M.Mix(dv, IW);

                    //Calculate outflow time
                    double dt;
                    if (qu == 0)
                    {
                        dt = IW.Volume / qop;
                    }
                    else
                    {
                        dt = Math.Log(qout / (qout - qu * IW.Volume)) / qu;
                    }
                    //Mixing during outflow
                    M.Mix(qout * dt - IW.Volume, IW);

                    IW.MoveInTime(TimeSpan.FromSeconds(OutflowTime + dt / 2), IW.Volume / Depth);
                    SendWaterDownstream(IW);
                    OutflowTime += dt;
                }
            }

            //Now move the remaining packets to their final destination and time
            foreach (IWaterPacket IWP in _waterInStream)
            {
                if (qu != 0)
                {
                    M.Mix(IWP.Volume * (Math.Exp(qu * CurrentTimeStep.TotalSeconds) - 1), IWP);
                }
                IWP.MoveInTime(CurrentTimeStep, IWP.Volume / Depth);
            }
            #endregion

            #region Water packets traveling right through
            double inflowtime = 0;

            //No water in stream and incoming water. Just pass through
            if (_waterInStream.Count == 0 & _incomingWater.Count > 0)
            {
                //Calculate how much incoming water is required to fill stream volume;
                double VToStore = Volume;
                if (qu != 0)
                {
                    VToStore = qop / qu * Math.Log(Volume * qu / qop + 1);
                }

                //Now send water through
                double incomingVolume = _incomingWater.Sum(var => var.Volume);
                //Send packets through until the remaining will just fill the stream
                while (incomingVolume > VToStore + 1e-12 & _incomingWater.Count != 0)
                {
                    IWaterPacket WP;
                    if (incomingVolume - _incomingWater.Peek().Volume > VToStore)
                    {
                        WP = _incomingWater.Dequeue();
                    }
                    else
                    {
                        WP = _incomingWater.Peek().Substract(incomingVolume - VToStore);
                    }

                    incomingVolume -= WP.Volume;

                    //Keep track of inflow time.
                    inflowtime += WP.Volume / qop;
                    if (qu != 0)
                    {
                        double dvr = WP.Volume * qu * Volume / qop;
                        M.Mix(dvr, WP);
                    }

                    //Calculate the time a water package uses to travel through the stream
                    TimeSpan CurrentTravelTime;
                    if (qu != 0)
                    {
                        CurrentTravelTime = TimeSpan.FromSeconds(1 / qu * Math.Log(Volume * qu / qop + 1));
                    }
                    else
                    {
                        CurrentTravelTime = TimeSpan.FromSeconds(Volume / qout);
                    }

                    //Moves right through
                    WP.MoveInTime(CurrentTravelTime, WP.Volume / Depth);
                    SendWaterDownstream(WP);
                }
            }

            #endregion

            #region Fill the stream
            //The remaining incoming water is moved forward and stays in the stream.
            while (_incomingWater.Count > 0)
            {
                IWaterPacket WP = _incomingWater.Dequeue();

                double dt = WP.Volume / qop;
                inflowtime += dt;
                double dt2 = CurrentTimeStep.TotalSeconds - inflowtime; //How much of the timestep is left when this packet has moved in.

                if (qu != 0)
                {
                    //Volume change during inflow
                    double Vnew = qop * (Math.Exp(qu * dt) - 1) / qu;
                    //Volume change while in stream
                    Vnew *= Math.Exp(qu * dt2);
                    M.Mix(Vnew - WP.Volume, WP);
                }
                //The time is half the inflowtime + the time in stream
                WP.MoveInTime(TimeSpan.FromSeconds(dt2 + dt / 2), WP.Volume / Depth);
                _waterInStream.Enqueue(WP);
            }
            #endregion

            Output.Outflow.AddSiValue(CurrentTime, NewTime, WaterToRoute / CurrentTimeStep.TotalSeconds);
            CurrentTime = NewTime;

            StartofFlowperiod = CurrentTime;
        }
 public IEnumerator <LogSink> GetEnumerator() => Sinks.GetEnumerator();