/// <summary> /// Fired when the duty cyle channel value changes /// </summary> /// <param name="value">new tag value</param> private void OnDutyCycleChannelValueChange(ITagValue value) { double newChannelValue = (double)value.Value; using (AcquireReadLock()) { // The visual parent is null if the item is deleted, this is not null for models that are within a container // and are not directly the children of the screen surface. if (VisualParent == null) { return; } ScreenModel screenModel = ScreenModel.GetScreen(this); screenModel.FromGatewayActionCollator.AddAction( _dutyCycleCollatorOwner, () => { using (AcquireReadLock()) { // The item could get deleted after the action has been dispatched. if (VisualParent != null) { DutyCycleChannelValue = newChannelValue; OnDutyCycleChannelValueChangedEvent(); } } }); } }
/// <summary> /// Fired when frequency channel value changes /// </summary> /// <param name="value">new tag value</param> private void OnFrequencyChannelValueChange(ITagValue value) { double newChannelValue = (double)value.Value; using (AcquireReadLock()) { // The visual parent is null if the item is deleted, this is not null for models that are within a container // and are not directly the children of the screen surface. if (VisualParent == null) { return; } ScreenModel screenModel = ScreenModel.GetScreen(this); // add an action to the collator. the collator will limit the number of actions coming from the gateway and only // process the most recent action. This keeps us from falling behind in time if we can't process the gateway updates as fast as they are received. screenModel.FromGatewayActionCollator.AddAction( _frequencyCollatorOwner, () => { using (AcquireReadLock()) { // The item could get deleted after the action has been dispatched. if (VisualParent != null) { if (!Equals(FrequencyChannelValue, newChannelValue)) { FrequencyChannelValue = newChannelValue; OnFrequencyChannelValueChangedEvent(); } } } }); } }
/// <summary> /// Called when the view model observes a change in a model property. /// Used to reflect model property changes on the VeriStand gateway (when necessary). /// </summary> /// <param name="modelElement">The model whose property changed. Unused by this method.</param> /// <param name="propertyName">The name of the property that changed.</param> /// <param name="transactionItem">The transaction item associated with the property change.</param> public void PropertyChanged(Element modelElement, string propertyName, TransactionItem transactionItem) { ScreenModel owningScreen = ScreenModel.GetScreen(this); switch (propertyName) { case DutyCycleChannelName: HandleChannelChangeAsync(transactionItem, owningScreen, OnDutyCycleChannelValueChange).IgnoreAwait(); break; case FrequencyChannelName: HandleChannelChangeAsync(transactionItem, owningScreen, OnFrequencyChannelValueChange).IgnoreAwait(); break; } }
/// <summary> /// Called by the view when a value change occurs. The view fires this for both duty cycle and frequency value changes and the event args let us /// tell which one was fired /// </summary> /// <param name="channelName">The name of the channel to set the value on.</param> /// <param name="channelValue">The new channel value.</param> public void SetChannelValue(string channelName, double channelValue) { // set the collator owner to be different for the different channel value change operations so a value change for one of the controls doesn't // erase the value change for the other one var collatorOwner = channelName == PulseWidthModulationControlModel.DutyCycleChannelName ? _dutyCycleCollatorOwner : _frequencyCollatorOwner; if (Host.ActiveRunTimeServiceProvider().Status == RunTimeProviderStatus.Connected) { ScreenModel screenModel = ScreenModel.GetScreen(this); if (screenModel != null) { // Use the action collator to make sure we are not generating more set channel value calls than we can handle. screenModel.ToGatewayActionCollator.AddAction(collatorOwner, async() => { try { if (channelName == PulseWidthModulationControlModel.DutyCycleChannelName && !string.IsNullOrEmpty(DutyCycleChannel)) { // set the channel value on the gateway, we are passing in empty labda expressions to the success and failure callbacks in this case // if we wanted to report errors to the user we could add some handling code for the failure case await Host.GetRunTimeService <ITagService>().SetTagValueAsync(DutyCycleChannel, TagFactory.CreateTag(channelValue)); } if (channelName == PulseWidthModulationControlModel.FrequencyChannelName && !string.IsNullOrEmpty(FrequencyChannel)) { await Host.GetRunTimeService <ITagService>().SetTagValueAsync(FrequencyChannel, TagFactory.CreateTag(channelValue)); } } catch (VeriStandException e) { Host.Dispatcher.InvokeIfNecessary( PlatformDispatcher.AsyncOperationAlwaysValid, #if MUTATE2021 () => this.SafeReportError( #else () => this.ReportError( #endif PwmControlModelErrorString, null, MessageDescriptor.Empty, e)); } });
private ScreenView GetScreen(string screenName) { return(ScreenModel?.GetScreen(screenName) ?? null); }