private void PushRawToAllActiveSinks(string message, params object[] sinkArgs) { foreach (var sink in Sinks.Where(x => x.Active)) { sink.Write(message, sinkArgs); } }
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)); }
public bool UnregisterMessageSink(IMessageSink sink) { if (!Sinks.Contains(sink)) { return(false); } Sinks.Remove(sink); return(true); }
public bool RegisterMessageSink(IMessageSink sink) { if (Sinks.Contains(sink)) { return(true); } Sinks.Add(new MessageSink(sink, Messages)); FlushMessages(); return(true); }
public virtual async Task <object> Process(object input) { var type = input.GetType(); if (Sinks.ContainsKey(type)) { return(await Sinks[type].ConvertAsync(input)); } return(null); }
public Log SinkTo <T>() where T : Sink, new() { EnsureNotClosed(); if (SinkExists <T>()) { throw new DuplicateSinkException(typeof(T)); } Sinks.Add(new T()); return(this); }
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); }
public Log SinkTo(Sink sink) { EnsureNotClosed(); var sinkType = sink.GetType(); if (SinkExists(sinkType)) { throw new DuplicateSinkException(sinkType); } Sinks.Add(sink); return(this); }
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"); } }
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); } }
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(); } } }
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; }
/// <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); }
private bool SinkExists(Type type) => Sinks.Exists(x => x.GetType() == type);
/// <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); }
public void AddSink(SinkFunction sf) { Sinks.Add(sf); }
// add a sink for logging public void AddSink(iLogSink sink) { Sinks.AddFirst(sink); }
public Broker RegisterSinks(params ISink[] sinks) { Sinks.AddRange(sinks); return(this); }
public void Add <T>(Func <T, object> callback) { Sinks.TryAdd(typeof(T), new ConversionAdapter <T, object>(callback)); }
/// <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();