private void ProcessEvent(BehaviourInfo behaviourInfo, object sender, StateUpdateEventArgs args) { Debug.Assert(Enabled, "Enabled"); var targetBehaviour = behaviourInfo.Behaviour; if (!targetBehaviour.Enabled) { return; } // Wait for the cooldown period before running again var lastTriggerTime = TriggerCounter.GetCounter(behaviourInfo.Behaviour).LastTriggerTime; if (lastTriggerTime.AddSeconds(behaviourInfo.Behaviour.CooldownPeriod) > args.SnapshotTime) { return; } var triggerTester = new Func <ITrigger, bool>(tr => { try { var triggerResult = tr.ProcessTrigger(sender, args); if ((triggerResult && !tr.InvertResult) || (!triggerResult && tr.InvertResult)) { TriggerCounter.BumpCounter(tr, args.SnapshotTime); return(true); } } catch (Exception ex) { DebugTools.WriteException(ex); } return(false); }); var triggerTriggered = targetBehaviour.Triggers.Where(x => x.Enabled).Any(triggerTester); if (triggerTriggered) { triggerTriggered = targetBehaviour.Conditions.Where(x => x.Enabled).All(triggerTester); } var result = false; switch (targetBehaviour.TriggeringKind) { case TriggeringMode.RisingEdge: result = !behaviourInfo.LastTriggerState && triggerTriggered; break; case TriggeringMode.FallingEdge: result = behaviourInfo.LastTriggerState && !triggerTriggered; break; case TriggeringMode.Always: result = triggerTriggered; break; case TriggeringMode.BothEdges: result = (!behaviourInfo.LastTriggerState && triggerTriggered) || (behaviourInfo.LastTriggerState && !triggerTriggered); break; case TriggeringMode.Timed: if (triggerTriggered) { if (behaviourInfo.InitialTriggerTime.Equals(DateTime.MaxValue)) { break; } if (behaviourInfo.InitialTriggerTime.AddSeconds(targetBehaviour.MinimalTimedTriggerDelay) <= args.SnapshotTime) { behaviourInfo.InitialTriggerTime = DateTime.MaxValue; result = true; } } else { behaviourInfo.InitialTriggerTime = args.SnapshotTime; } break; default: throw new InvalidEnumArgumentException(); } behaviourInfo.LastTriggerState = triggerTriggered; if (!result) { return; } Action runActions = () => { foreach (var action in targetBehaviour.Actions.Where(x => x.Enabled)) { try { action.ExecuteAction(sender, args); TriggerCounter.BumpCounter(action, args.SnapshotTime); } catch (Exception ex) { DebugTools.WriteException(ex); } } }; if (string.IsNullOrEmpty(targetBehaviour.Group)) { //BUG different than running using BehaviourGroup, can queue next run before it ends // Task doesnt exist yet or it has been completed if (behaviourInfo.UngroupedTask?.IsCompleted != false) { behaviourInfo.UngroupedTask = Task.Run(runActions); } } else { BehaviourGroup behaviourGroup; if (!_groupedTasks.TryGetValue(targetBehaviour.Group, out behaviourGroup)) { behaviourGroup = new BehaviourGroup(); _groupedTasks.Add(targetBehaviour.Group, behaviourGroup); } behaviourGroup.RunBehaviour(runActions, targetBehaviour); } TriggerCounter.BumpCounter(behaviourInfo.Behaviour, args.SnapshotTime); }