/// <summary> /// No throw. Returns null or changed clientObjs (not null, but possibly zero-lenghth). /// </summary> public object[]? PollChanges() { if (DataGrpcList is null || DataGrpcList.Disposed) { return(null); } try { var changedClientObjs = new List <object>(); ClientElementValueListItem[] changedClientElementValueListItems = DataGrpcList.PollElementValuesChanges(); foreach (ClientElementValueListItem dataGrpcElementValueListItem in changedClientElementValueListItems) { var o = dataGrpcElementValueListItem.Obj as DataGrpcListItemWrapper; if (o is null) { throw new InvalidOperationException(); } foreach (var modelItem in o.ClientObjectInfosCollection) { if (modelItem.ClientObj is not null) { changedClientObjs.Add(modelItem.ClientObj); } } } return(changedClientObjs.ToArray()); } catch { } return(null); }
/// <summary> /// Returns whether connection errors occur. /// </summary> /// <returns></returns> protected bool SubscribeInitial() { bool connectionError = false; foreach (ClientObjectInfo clientObjectInfo in _clientObjectInfosDictionary.Values) { if (clientObjectInfo.DataGrpcListItemWrapper is null) { var elementId = clientObjectInfo.ElementId; DataGrpcListItemWrapper?dataGrpcListItemWrapper; if (!_dataGrpcListItemWrappersDictionary.TryGetValue(elementId, out dataGrpcListItemWrapper)) { dataGrpcListItemWrapper = new DataGrpcListItemWrapper(); _dataGrpcListItemWrappersDictionary.Add(elementId, dataGrpcListItemWrapper); } clientObjectInfo.ForceNotifyClientObj = true; clientObjectInfo.DataGrpcListItemWrapper = dataGrpcListItemWrapper; dataGrpcListItemWrapper.ClientObjectInfosCollection.Add(clientObjectInfo); } } var dataGrpcListItemWrappersToAdd = new List <DataGrpcListItemWrapper>(); foreach (var kvp in _dataGrpcListItemWrappersDictionary) { DataGrpcListItemWrapper dataGrpcListItemWrapper = kvp.Value; if (dataGrpcListItemWrapper.DataGrpcListItem is null && !dataGrpcListItemWrapper.ItemDoesNotExist) { dataGrpcListItemWrappersToAdd.Add(dataGrpcListItemWrapper); TDataGrpcListItem?dataGrpcListItem = null; if (DataGrpcList is not null && !DataGrpcList.Disposed) { try { dataGrpcListItem = DataGrpcList.PrepareAddItem(kvp.Key); } catch { connectionError = true; } }
/// <summary> /// /// </summary> /// <param name="clientObj"></param> /// <param name="valueStatusTimestamp"></param> public void Write(object clientObj, ValueStatusTimestamp valueStatusTimestamp) { if (DataGrpcList is null || DataGrpcList.Disposed) { return; } ClientObjectInfo?modelItem; if (!ModelItemsDictionary.TryGetValue(clientObj, out modelItem)) { return; } if (modelItem.DataGrpcListItemWrapper is null || modelItem.DataGrpcListItemWrapper.DataGrpcListItem is null || modelItem.DataGrpcListItemWrapper.DataGrpcListItem.StatusCode != StatusCode.OK) { return; } ClientElementValueListItem dataGrpcElementValueListItem = modelItem.DataGrpcListItemWrapper.DataGrpcListItem; try { dataGrpcElementValueListItem.PrepareForWrite(valueStatusTimestamp); try { DataGrpcList.CommitWriteElementValueListItems(); } catch { } } catch (Exception ex) { Logger.LogWarning(ex, "DataGrpcList.CommitWriteElementValueListItems() exception"); } }
/// <summary> /// Creates List, adds/removes items. /// No throw. /// </summary> /// <param name="clientConnectionManager"></param> /// <param name="сallbackDispatcher"></param> /// <param name="elementValuesCallbackEventHandler"></param> /// <param name="callbackIsEnabled"></param> /// <param name="ct"></param> public void Subscribe(ClientConnectionManager clientConnectionManager, IDispatcher?сallbackDispatcher, ElementValuesCallbackEventHandler elementValuesCallbackEventHandler, bool callbackIsEnabled, CancellationToken ct) { try { if (ct.IsCancellationRequested) { return; } if (!DataGrpcItemsMustBeAddedOrRemoved) { return; } bool firstTimeDataConnection = (DataGrpcList is null); if (firstTimeDataConnection) { try { if (clientConnectionManager.ConnectionExists) { DataGrpcList = clientConnectionManager.NewElementValueList(null); } } catch (Exception) { } } bool connectionError = SubscribeInitial(); try { if (!connectionError && DataGrpcList is not null && !DataGrpcList.Disposed) { if (firstTimeDataConnection) { DataGrpcList.ElementValuesCallback += (ClientElementValueList dataList, ClientElementValueListItem[] items, ValueStatusTimestamp[] values) => { var changedClientObjs = new List <object>(items.Length); var changedValues = new List <ValueStatusTimestamp>(items.Length); int i = 0; foreach (ClientElementValueListItem dataGrpcElementValueListItem in items) { var o = dataGrpcElementValueListItem.Obj as DataGrpcListItemWrapper; if (o is null) { throw new InvalidOperationException(); } foreach (var modelItem in o.ClientObjectInfosCollection) { modelItem.ForceNotifyClientObj = false; if (modelItem.ClientObj is not null) { changedClientObjs.Add(modelItem.ClientObj); changedValues.Add(values[i]); } } i++; } if (ct.IsCancellationRequested) { return; } Logger.LogDebug("DataGrpcList.ElementValuesCallback"); if (сallbackDispatcher is not null) { try { сallbackDispatcher.BeginInvoke(ct => { Logger.LogDebug("DataGrpcList.ElementValuesCallback dispatched"); elementValuesCallbackEventHandler(changedClientObjs.ToArray(), changedValues.ToArray()); }); } catch (Exception) { } } }; if (callbackIsEnabled) { DataGrpcList.EnableListCallback(true); } } } } catch (Exception ex) { Logger.LogWarning(ex, "ClientElementValueListItemsManager.Subscribe exception"); connectionError = true; } { var utcNow = DateTime.UtcNow; var changedClientObjs = new List <object>(); var changedValues = new List <ValueStatusTimestamp>(); foreach (DataGrpcListItemWrapper dataGrpcListItemWrapper in DataGrpcListItemWrappersDictionary.Values) { foreach (var modelItem in dataGrpcListItemWrapper.ClientObjectInfosCollection) { if (modelItem.ForceNotifyClientObj) { modelItem.ForceNotifyClientObj = false; if (modelItem.ClientObj is not null) { if (dataGrpcListItemWrapper.ItemDoesNotExist) { changedClientObjs.Add(modelItem.ClientObj); changedValues.Add(new ValueStatusTimestamp { ValueStatusCode = ValueStatusCode.ItemDoesNotExist }); } else if (dataGrpcListItemWrapper.DataGrpcListItem is not null) { changedClientObjs.Add(modelItem.ClientObj); changedValues.Add(dataGrpcListItemWrapper.DataGrpcListItem.ValueStatusTimestamp); } else { changedClientObjs.Add(modelItem.ClientObj); changedValues.Add(new ValueStatusTimestamp(new Any(), ValueStatusCode.Unknown, utcNow)); } } } } } if (changedClientObjs.Count > 0) { if (ct.IsCancellationRequested) { return; } if (сallbackDispatcher is not null) { try { сallbackDispatcher.BeginInvoke(ct => elementValuesCallbackEventHandler(changedClientObjs.ToArray(), changedValues.ToArray())); } catch (Exception) { } } } } if (!connectionError) { DataGrpcItemsMustBeAddedOrRemoved = false; } } finally { SubscribeFinal(); } }
/// <summary> /// Returns clientObjs whose write failed. /// If connection error, no throw and returns all clientObjs. /// </summary> /// <param name="clientObjs"></param> /// <param name="valueStatusTimestamps"></param> /// <returns></returns> public object[] Write(object[] clientObjs, ValueStatusTimestamp[] valueStatusTimestamps) { if (DataGrpcList is null || DataGrpcList.Disposed) { return(clientObjs); } int i = -1; var result = new List <object>(); foreach (var clientObj in clientObjs) { i++; ClientObjectInfo?modelItem; if (!ModelItemsDictionary.TryGetValue(clientObj, out modelItem)) { result.Add(clientObj); continue; } if (modelItem.DataGrpcListItemWrapper is null || modelItem.DataGrpcListItemWrapper.DataGrpcListItem is null || modelItem.DataGrpcListItemWrapper.DataGrpcListItem.StatusCode != StatusCode.OK) { result.Add(clientObj); continue; } ClientElementValueListItem dataGrpcElementValueListItem = modelItem.DataGrpcListItemWrapper.DataGrpcListItem; dataGrpcElementValueListItem.PrepareForWrite(valueStatusTimestamps[i]); } IEnumerable <ClientElementValueListItem> failedItems; try { failedItems = DataGrpcList.CommitWriteElementValueListItems(); } catch { return(clientObjs); } foreach (var dataGrpcElementValueListItem in failedItems) { var o = dataGrpcElementValueListItem.Obj as DataGrpcListItemWrapper; if (o is null) { throw new InvalidOperationException(); } foreach (var modelItem in o.ClientObjectInfosCollection) { if (modelItem.ClientObj is not null) { result.Add(modelItem.ClientObj); } } } return(result.ToArray()); }