/// <summary> /// Initializes a new instance of the <see cref="NotifyChangeMonitor{T}"/> class. /// </summary> /// <param name="obj">Object to monitor.</param> public NotifyChangeMonitor(T obj) { this.obj = obj; this.obj.PropertyChanged += (sender, args) => PropertiesChanged.Add(args.PropertyName); this.obj.OnChanged += (sender, wasChanged) => StateChanges.Add(wasChanged); }
public virtual void FindDifferences(object oldState, object newState, StateChanges stateChanges, int maxDepth) { values = new Dictionary <string, StateChange>(); if (oldState != null) { beingTraversed = BeingTraversed.Old; traverser.TraverseInstance(oldState, maxDepth, this); } if (newState != null) { beingTraversed = BeingTraversed.New; traverser.TraverseInstance(newState, maxDepth, this); } beingTraversed = BeingTraversed.Nothing; foreach (var kvp in values) { var change = kvp.Value; if (change.OldValue == null && change.NewValue != null) { stateChanges.Changes.Add(change); } else if (change.OldValue != null && !change.OldValue.Equals(change.NewValue)) { stateChanges.Changes.Add(change); } } }
private void ManageNightLights() { Entity(HallPir !) .StateChanges .Where(e => e.New?.State == "on" && e.Old?.State == "off" && (IsNight || IsMorning || IsEvening)) .Subscribe( s => { Light.HallTak1.TurnOn(new { transition = 0 }); Light.HallTak2.TurnOn(new { transition = 0 }); } ); Entity(HallPir !) .StateChanges .Where(e => e.New?.State == "off" && e.Old?.State == "on" && (IsNight || IsMorning || IsEvening) && !IsTimeNowBetween(TimeSpan.FromHours(5), TimeSpan.FromHours(10))) .NDSameStateFor(TimeSpan.FromMinutes(1)) .Subscribe( s => { Light.HallTak1.TurnOff(new { transition = 0 }); Light.HallTak2.TurnOff(new { transition = 0 }); } ); }
public UptimeReport CalculateDurations() { StateChanges = StateChanges.OrderByDescending(r => r.NobreakState.Timestamp).ToList(); for (int i = 0; i < StateChanges.Count; i++) { StateChanges[i].Duration = (i > 0 ? StateChanges[i - 1].NobreakState.Timestamp : CalculatedOn) - StateChanges[i].NobreakState.Timestamp; } return(this); }
private void AddStateChange(SaleStateChange stateChange, bool isInitialStateChange) { if (stateChange is null) { throw new BaristaException("invalid_sale_state_change", "The state change is empty."); } ValidateStateChange(stateChange.State, isInitialStateChange); StateChanges.Add(stateChange); SetUpdatedNow(); }
public virtual void FindDifferences ( object oldState, object newState, StateChanges stateChanges, int maxDepth, Func <FieldInfo, IReadOnlyInstanceTraversalContext, bool> fieldIgnoreFunc = null, Func <PropertyInfo, IReadOnlyInstanceTraversalContext, bool> propertyIgnoreFunc = null ) { if (fieldIgnoreFunc == null) { fieldIgnoreFunc = (field, context) => false; } if (propertyIgnoreFunc == null) { propertyIgnoreFunc = (prop, context) => false; } fieldIgnoreFn = fieldIgnoreFunc; propertyIgnoreFn = propertyIgnoreFunc; values = new Dictionary <string, StateChange>(); if (oldState != null) { beingTraversed = BeingTraversed.Old; traverser.TraverseInstance(oldState, maxDepth, this); } if (newState != null) { beingTraversed = BeingTraversed.New; traverser.TraverseInstance(newState, maxDepth, this); } beingTraversed = BeingTraversed.Nothing; foreach (var kvp in values) { var change = kvp.Value; if (change.OldValue == null && change.NewValue != null) { stateChanges.Changes.Add(change); } else if (change.OldValue != null && !change.OldValue.Equals(change.NewValue)) { stateChanges.Changes.Add(change); } } }
public override void Initialize() { Entity(AlarmSensor !) .StateChanges.Where(e => e.New.Attribute?.next_alarm_status == "ringing" && e.Old.Attribute?.next_alarm_status != "ringing") .Subscribe(s => { // make a short delay RunIn(TimeSpan.FromSeconds(30), () => Speak("media_player.sovrum", "du har satt larm!")); }); }
public void TrackStateChange(State <T> oldState, State <T> newState) { if (TrackChanges) { if (oldState != null) { StateChangeRecord <T> record = new StateChangeRecord <T>(oldState.Name, newState.Name, TimingFunction.Invoke()); StateChanges.Add(record); } } }
public override Task InitializeAsync() { Entity(Calendar !) .StateChanges.Where(e => e.New.State == "on") .Subscribe(s => { Speak("media_player.huset", "Viktigt meddelande"); // Important message Speak("media_player.huset", s.New?.Attribute?.message); Speak("media_player.huset", s.New?.Attribute?.description); }); return(Task.CompletedTask); }
/// <summary> /// Initialize, is automatically run by the daemon /// </summary> public override void Initialize() { // Set up the state management // When chromecast is going off // Entities("media_player.tv_nere") // .StateChanges // .Where(e => e.New?.State == "off" && e.Old?.State is object ) // .Subscribe(s => // { // if (TvIsOn) // { // Log('TV is off, turnin off shield and tv') // RunScript("tv_off_scene"); // } // }); // When state change on my media players, call OnMediaStateChanged Entities(TvMediaPlayers !) .StateChanges .Subscribe(s => { OnMediaStateChanged(s.New, s.Old); }); // When TV on (remote on), call OnTvTurnedOn Entity(RemoteTVRummet !) .StateChanges .Where(e => e.Old?.State == "off" && e.New?.State == "on") .Subscribe(s => { LogDebug("TV remote status change from {from} to {to}", s.Old?.State, s.New?.State); OnTVTurnedOn(); }); // When ever TV remote activity changes, ie TV, Film, Poweroff call OnTvActivityChange Entity(RemoteTVRummet !) .StateAllChanges .Where(e => e.New?.Attribute?.current_activity != e.Old?.Attribute?.current_activity) .Subscribe(s => { LogDebug("TV remote activity change from {from} to {to}", s.Old?.Attribute?.current_activity, s.New?.Attribute?.current_activity); OnTvActivityChange(s.New); }); }
/// <summary> /// Generate a diff of the given objects, suitable /// for logging. /// /// You can control which members are included and how /// by marking your state objects with <see cref="AuditAttribute"/>. /// </summary> /// <param name="oldState">The old state - null is allowed</param> /// <param name="newState">The new state - null is allowed</param> /// <returns>A set of changes</returns> /// <exception cref="ArgumentException">Thrown if a value masker has been supplied, that does not implement the right interface</exception> public virtual StateChanges GetAuditReadyDiff(object oldState, object newState) { var auditChanges = new StateChanges(); var changes = stateChangeFinder.GetChanges(oldState, newState); foreach (var change in changes.Changes) { if (change.MemberInfo is FieldInfo fieldInfo && !fieldInfo.IsPublic) { // we do not want private/protected fields continue; } if (change.MemberInfo is PropertyInfo propInfo && propInfo.GetMethod != null && !propInfo.GetMethod.IsPublic) { // we do not want private/protected properties continue; } if (change.MemberInfo.HasAttribute(typeof(AuditAttribute))) { var attr = change.MemberInfo.GetCustomAttribute <AuditAttribute>(); if (!attr.Include) { continue; } if (attr.DoMaskValue) { if (!attr.ValueMasker.ImplementsInterface(typeof(IAuditValueMasker))) { throw new ArgumentException($"A {nameof(AuditAttribute.ValueMasker)} must implement {typeof(IAuditValueMasker).Name}, which {attr.ValueMasker.Name} does not."); } var masker = (IAuditValueMasker)container.Resolve(attr.ValueMasker); change.OldValue = masker.MaskValue(change.OldValue); change.NewValue = masker.MaskValue(change.NewValue); } } auditChanges.Changes.Add(change); } return(auditChanges); }
public override Task InitializeAsync() { if (!CheckConfig()) { return(Task.CompletedTask); } Entity(DoorSensor !) .StateChanges .Where(e => e.New?.State == "on") .Subscribe(s => GreetIfJustArrived(s.New.EntityId)); StateChanges .Where( e => e.New.EntityId.EndsWith(PresenceCriteria !) && e.New?.State == "Nyss anlänt") .Subscribe(s => GreetIfJustArrived(s.New.EntityId)); return(Task.CompletedTask); }
/// <summary> /// Initialize, is automatically run by the daemon /// </summary> public override void Initialize() { // Set up the state management // When chromecast is going off // Entities("media_player.tv_nere") // .StateChanges // .Where(e => e.New?.State == "off" && e.Old?.State is object ) // .Subscribe(s => // { // if (TvIsOn) // { // Log('TV is off, turnin off shield and tv') // RunScript("tv_off_scene"); // } // }); // When state change on my media players, call OnMediaStateChanged Entities(TvMediaPlayers !) .StateChanges .Subscribe(s => OnMediaStateChanged(s.New, s.Old)); // When TV on (remote on), call OnTvTurnedOn Entity(RemoteTVRummet !) .StateChanges .Where(e => e.Old?.State == "off" && e.New?.State == "on") .Subscribe(s => OnTVTurnedOn()); // When ever TV remote activity changes, ie TV, Film, Poweroff call OnTvActivityChange Entity(RemoteTVRummet !) .StateAllChanges .Where(e => e.New?.Attribute?.current_activity != e.Old?.Attribute?.current_activity) .Subscribe(s => OnTvActivityChange(s.New)); // This function does not contain any async calls so just return completed task // return Task.CompletedTask; }
/// <summary> /// Initialize the automations /// </summary> /// <remarks> /// - Schedules check every minute if heater should be on or off depending on temperature /// - Set the manually started flag if heater is turn on and not turned on by this script /// </remarks> public override void Initialize() { // Get the state if manually started from statestorage RunEveryMinute(0, () => HandleCarHeater()); Entity(HeaterSwitch !) .StateChanges .Where(e => e.New.State == "on") .Subscribe(s => { if (_appChangedState == false) { // It is manually turned on Storage.IsManualState = true; } else { Storage.IsManualState = false; } _appChangedState = false; }); }
public UptimeReport CalculateUptimePerIntervals() { UptimePerIntervals = RelevantTimespans.Select(relevantTimespan => { var since = CalculatedOn - relevantTimespan; var events = StateChanges.Where(s => s.NobreakState.Timestamp >= since).ToList(); var rightBefore = StateChanges.SkipWhile(s => s.NobreakState.Timestamp >= (events.LastOrDefault()?.NobreakState.Timestamp ?? DateTime.Now)).FirstOrDefault(); if (rightBefore != null) { events.Add(rightBefore); } var sumPerState = PossibleStates.Select(s => new KeyValuePair <PowerStates, TimeSpan>(s, TimeSpan.Zero)).ToDictionary(); for (int i = 0; i < events.Count; i++) { sumPerState[events[i].PowerState] += events[i].NobreakState.Timestamp < since ? events[i].Duration - (CalculatedOn - relevantTimespan - events[i].NobreakState.Timestamp) : events[i].Duration; } var sum = TimeSpan.Zero; foreach (var state in sumPerState) { sum += state.Value; } return(new UptimeInInterval { UptimeStates = sumPerState.Select(stateSum => new UptimeState { ShareTimespan = stateSum.Value, SharePercentage = stateSum.Value / sum * 100, PowerState = stateSum.Key }).ToList(), Since = since, TimeSpan = relevantTimespan }); }).ToList(); return(this); }
/// <summary> /// Generate a diff of the given objects, suitable /// for logging. /// /// You can control which members are included and how /// by marking your state objects with <see cref="AuditAttribute"/>. /// </summary> /// <param name="oldState">The old state - null is allowed</param> /// <param name="newState">The new state - null is allowed</param> /// <returns>A set of changes</returns> /// <exception cref="ArgumentException">Thrown if a value masker has been supplied, that does not implement the right interface</exception> public virtual StateChanges GetAuditReadyDiff(object oldState, object newState) { var auditChanges = new StateChanges(); var changes = stateChangeFinder.GetChanges(oldState, newState, ShouldIgnoreMember, ShouldIgnoreMember); foreach (var change in changes.Changes) { if (change.MemberInfo is FieldInfo fieldInfo && !fieldInfo.IsPublic) { // we do not want private/protected fields continue; } if (change.MemberInfo is PropertyInfo propInfo && propInfo.GetMethod != null && !propInfo.GetMethod.IsPublic) { // we do not want private/protected properties continue; } if (change.MemberInfo.HasAttribute(typeof(AuditAttribute))) { var attr = change.MemberInfo.GetCustomAttribute <AuditAttribute>(); if (attr.DoMaskValue) { var masker = GetValidValueMaskerOrThrow(attr); change.OldValue = masker.MaskValue(change.OldValue); change.NewValue = masker.MaskValue(change.NewValue); } } auditChanges.Changes.Add(change); } return(auditChanges); }
/// <summary> /// Initialize, is automatically run by the daemon /// </summary> public override void Initialize() { // Set up the state management // When state change on my media players, call OnMediaStateChanged Entities(TvMediaPlayers !) .StateChanges .Subscribe(s => OnMediaStateChanged(s.New, s.Old)); // When TV on (remote on), call OnTvTurnedOn Entity(RemoteTVRummet !) .StateChanges .Where(e => e.New?.State == "on") .Subscribe(s => OnTVTurnedOn()); // When ever TV remote activity changes, ie TV, Film, Poweroff call OnTvActivityChange Entity(RemoteTVRummet !) .StateAllChanges .Where(e => e.New?.Attribute?.current_activity != e.Old?.Attribute?.current_activity) .Subscribe(s => OnTvActivityChange(s.New)); // This function does not contain any async calls so just return completed task // return Task.CompletedTask; }
public override void Initialize() { _Emoji = Type ! == "Washer" ? "🧼" : "🧺"; Entity(PowerSensor !) .StateChanges .Where( e => e.New?.ToStateBool() == true) .NDSameStateFor(TimeSpan.FromSeconds(90)) .Subscribe(s => Running()); Entity(PowerSensor !) .StateChanges .Where( e => e.New?.ToStateBool() == false) .NDSameStateFor(TimeSpan.FromSeconds(270)) .Subscribe(s => Clean()); Entity(HatchSensor !) .StateChanges .Where( e => e.New?.State == "on") .Subscribe(s => Emptied()); }
/// <summary> /// Creates a new RichTextModel with the formatting from this RichText. /// </summary> public RichTextModel ToRichTextModel() { return(new RichTextModel(StateChangeOffsets, StateChanges.Select(ch => ch.Clone()).ToArray())); }
public StateChangeFinderWorker_ArrayTests() { stateChanges = new StateChanges(); worker = new StateChangeFinderWorker(new InstanceTraverser()); }
/// <summary> /// Initialize the app /// </summary> public void Initialize() { _app.Entity("binary_sensor.kitchen") .StateChanges .Where(e => e.New?.State == "on" && e.Old?.State == "off") .Subscribe(_ => { // Just for the testing of all these _app.Entity("light.kitchen").TurnOn(new { brightness = 100 }); _app.Entity("light.kitchen").TurnOff(new { brightness = 100 }); _app.Entity("light.kitchen").Toggle(new { brightness = 100 }); } ); _app.Entity("binary_sensor.livingroom") .StateChanges .Where(e => e.New?.State == "on" && e.Old?.State == "off") .Subscribe(_ => _app.Entity("sensor.mysensor").SetState(20, new { battery_level = 90 })); _app.Entities(n => n.EntityId !.EndsWith("entities", StringComparison.InvariantCultureIgnoreCase)).StateChanges.Where(s => s.New.State == "on").Subscribe(_ => _app.Entity("light.kitchen").TurnOn()); _app.Entities(n => n.EntityId !.EndsWith("entities", StringComparison.InvariantCultureIgnoreCase)).StateChanges.Where(s => s.New.State == "off").Subscribe(_ => _app.Entity("light.kitchen").TurnOff()); _app.Entity("sensor.temperature") .StateAllChanges .Where(e => e.New?.Attribute?.battery_level < 15) .Subscribe(_ => _app.CallService("notify", "notify", new { title = "Hello from Home Assistant" })); _app.EventChanges .Where(e => e.Event == "hello_event") .Subscribe(_ => _app.Entity("light.livingroom").TurnOn()); _app.EventChanges .Where(e => e.Event == "bye_event") .Subscribe(_ => _app.Entity("light.livingroom").TurnOff()); _app.SetState("sensor.any_sensor", 20, new { battery_level = 70 }); _app.SetState("sensor.any_sensor2", 20, new { battery_level = 70 }); _app.Entity("binary_sensor.test_state_entity") .StateChanges .Subscribe(_ => { if (_app.State("sensor.some_other_entity")?.State == "on") { _app.Entity("light.state_light").TurnOn(); } }); _app.RunIn(TimeSpan.FromMilliseconds(100), () => _app.Entity("binary_sensor.fake_run_in_happened").TurnOn()); _app.RunEveryMinute(0, () => _app.Entity("binary_sensor.fake_run_every_minute_happened").TurnOn()); _app.RunEveryHour("15:00", () => _app.Entity("binary_sensor.fake_run_every_hour_happened").TurnOn()); _app.RunDaily("23:00:00", () => _app.Entity("binary_sensor.fake_run_daily_happened").TurnOn()); _timer = _app.RunEveryMinute(0, TestTimerDisposal); }
private void mstp_thread() { try { StateChanges state_change = StateChanges.Reset; while (m_port != null) { if (StateLogging) { Trace.WriteLine(state_change.ToString(), null); } switch (state_change) { case StateChanges.Reset: state_change = Initialize(); break; case StateChanges.DoneInitializing: case StateChanges.ReceivedUnexpectedFrame: case StateChanges.Reply: case StateChanges.DeferredReply: case StateChanges.SawTokenUser: state_change = Idle(); break; case StateChanges.GenerateToken: case StateChanges.FindNewSuccessor: case StateChanges.SendMaintenancePFM: case StateChanges.SoleMasterRestartMaintenancePFM: case StateChanges.NextStationUnknown: state_change = PollForMaster(); break; case StateChanges.DoneWithPFM: case StateChanges.ResetMaintenancePFM: case StateChanges.ReceivedReplyToPFM: case StateChanges.SendToken: state_change = PassToken(); break; case StateChanges.ReceivedDataNeedingReply: state_change = AnswerDataRequest(); break; case StateChanges.ReceivedToken: case StateChanges.SoleMaster: case StateChanges.DeclareSoleMaster: case StateChanges.SendAnotherFrame: state_change = UseToken(); break; case StateChanges.NothingToSend: case StateChanges.SendNoWait: case StateChanges.ReplyTimeOut: case StateChanges.InvalidFrame: case StateChanges.ReceivedReply: case StateChanges.ReceivedPostpone: state_change = DoneWithToken(); break; case StateChanges.SendAndWait: state_change = WaitForReply(); break; } } Trace.WriteLine("MSTP thread is closing down", null); } catch (Exception ex) { Trace.TraceError("Exception in MSTP thread: " + ex.Message); } m_is_running = false; }
private void SetupSubscriptions() { LogTrace("SetupSubscriptions()"); foreach (var entityId in _presenceEntityIds) { _app.Entity(entityId) .StateAllChanges .Where(e => e.Old?.State == "off" && e.New?.State == "on" || e.Old?.State == "on" && e.New?.State == "on") .Subscribe(s => { LogDebug("Presence event: {entityId}", s.New.EntityId); HandleEvent(); }); } foreach (var entityId in _keepAliveEntityIds) { _app.Entity(entityId) .StateChanges .Where(e => e.Old?.State == "off" && e.New?.State == "on" || e.Old?.State == "on" && e.New?.State == "on") .Subscribe(s => { LogDebug("Keep Alive event: {entityId}", s.New.EntityId); HandleEvent(); }); } foreach (var entityId in _controlEntityIds.Union(_nightControlEntityIds)) { _app.Entity(entityId) .StateChanges .Where(e => e.Old?.State == "on" && e.New?.State == "off") .Subscribe(s => { LogDebug("Entitiy Manually Turned Off: {entityId}", s.New.EntityId); SetRoomState(RoomState.Idle); }); } foreach (var entityId in _controlEntityIds.Union(_nightControlEntityIds)) { _app.Entity(entityId) .StateAllChanges .Where(e => e.Old?.State == "on" && e.New?.State == "on" && e.New?.Context?.UserId != null && (e.Old?.Attribute?.brightness != e.New?.Attribute?.brightness || e.Old?.Attribute?.color_temp != e.New?.Attribute?.color_temp)) .Subscribe(s => { LogDebug("Brightness/Colour Manually Changed: {entityId}", s.New.EntityId); DisableCircadian(); }); } foreach (var entityId in _controlEntityIds.Union(_nightControlEntityIds)) { _app.Entity(entityId) .StateChanges .Where(e => e.Old?.State == "off" && e.New?.State == "on") .Subscribe(s => { LogDebug("Entitiy Manually Turned On: {entityId}", s.New.EntityId); SetRoomState(RoomState.Override); }); } _app.Entity(_roomConfig.EnabledSwitchEntityId) .StateChanges .Subscribe(s => { LogDebug("Enabled Switch event changed to: {state}", s.New.State); if (s.New.State == "on") { SetRoomState(RoomState.Idle); } if (s.New.State == "off") { SetRoomState(RoomState.Disabled); } }); if (_app.States.Any(s => s.EntityId == _roomConfig.NightTimeEntityId)) { _app.Entity(_roomConfig.NightTimeEntityId !) .StateChanges .Subscribe(s => { LogDebug("Night Mode Switched: {state}", s.New.State); NightModeChanged(s.New.State); }); } }