//Запись тегов в БД protected internal override void WriteItemToDB(DBPGContext context) { foreach (var item in CapacityList) { try { context.capacityDescs.FirstOrDefault(c => c.tagname == item.TagName).value = item.ValCalc; } catch (Exception) { throw new Exception($"Tag = {item.TagName}"); } } context.SaveChanges(); }
//Определяем свой ip и свою роль в процессе чтения-записи в (из) OPC private HostRole DefineHostRole() { List <AuthorizedHost> hostsAddressList = null; //Checking for Autorized hostAddresses for writing to OPC (reading from Data Base) try { using (DBPGContext dbContext = new DBPGContext()) { hostsAddressList = (from h in dbContext.contentAutorizedServers select h).ToList(); } } catch (Exception) { return(HostRole.ERROR); } hostsAddressList.Sort((x, y) => x.id.CompareTo(y.id)); if (hostsAddressList == null) { return(HostRole.UNKNOWN); } //IP addresses from Data Base IPAddress[] dBHostIpAddresses = new IPAddress[hostsAddressList.Count()]; for (int i = 0; i < dBHostIpAddresses.Length; i++) { IPAddress.TryParse(hostsAddressList[i].hostAddress, out dBHostIpAddresses[i]); } //Local Machine IP addresses IPAddress[] localHostIpAddresses = Dns.GetHostAddresses(Dns.GetHostName()); //Check for consistance IP Address in DB and IP Address of Local Machine if (dBHostIpAddresses.Length > 0 && localHostIpAddresses.Contains(dBHostIpAddresses[0])) { return(HostRole.PRIMARY_SERVER); } if (dBHostIpAddresses.Length > 1 && localHostIpAddresses.Contains(dBHostIpAddresses[1])) { return(HostRole.SECONDARY_SERVER); } return(HostRole.CLIENT); }
private void TestDBButton_Click(object sender, RoutedEventArgs e) { try { using (var dbContext = new DBPGContext()) { dbContext.Database.Connection.Open(); dbContext.Database.Connection.Close(); MessageBox.Show("Connection Ok!", "Check connection", MessageBoxButton.OK, MessageBoxImage.Information); } } catch (Exception) { MessageBox.Show("Connection Error!", "Check connection", MessageBoxButton.OK, MessageBoxImage.Error); } }
//Обновление Capacity тегов из Базы Данных protected internal override void UpdateItemListFromDB(List <Temperature> temperatureList, List <Pressure> pressureList, DBPGContext dbContext) { // считываем описание с базы данных var capData = from c in dbContext.capacityDescs select c; //} // ------------------------------------------------------------------------------------------------------- // обьединяем два листа по условию равности tagName и формируем объект var result = from itemCapData in (IEnumerable <CapacityContent>) capData join itemCapacityList in CapacityList on itemCapData.tagname equals itemCapacityList.TagName select new { tagname = itemCapData.tagname, percDescription = new string[] { itemCapData.perc0 ?? string.Empty, itemCapData.perc1 ?? string.Empty, itemCapData.perc2 ?? string.Empty, itemCapData.perc3 ?? string.Empty, itemCapData.perc4 ?? string.Empty, }, temperature = temperatureList.FirstOrDefault(x => x.TagName == itemCapData.temperature), pressure = pressureList.FirstOrDefault(x => x.TagName == itemCapData.pressure), description = itemCapData.description, isWriteble = itemCapData.isWritable }; // ---------------------------------------------------------------------------- var capacity = default(Characteristic); foreach (var item in result) { capacity = CapacityList.FirstOrDefault(c => c.TagName == item.tagname); try { if (capacity != null) { Array.Copy(item.percDescription, ((Capacity)capacity).PercDescription, ((Capacity)capacity).CompN); capacity.Description = item.description; ((Capacity)capacity).Temperature = item.temperature as Temperature; ((Capacity)capacity).Pressure = item.pressure as Pressure == null ? new Pressure("PressureSample") : item.pressure as Pressure; ((Capacity)capacity).IsWriteble = item.isWriteble ?? false; } } catch (Exception e) { MessageBox.Show(e.Message, "Alert!", MessageBoxButton.OK, MessageBoxImage.Error); capacity.IsInValid = true; } } }
//Обновление LevelTank тегов из Базы Данных protected internal void UpdateItemListFromDB(List <Level> levelList, List <Density> densityList, DBPGContext dbContext) { //Создаем список анонимных объектов var collection = (from tc in dbContext.tankContents join t in dbContext.tanks on tc.tankId equals t.id select new { Id = tc.id, TagName = tc.tankVarDef, Tank = t, tc.distanceA, tc.distanceB, tc.probeLength, tc.distToDistanceA }).ToList(); //Создаем список LevelTank, параллельно инициализируем его переменными Level LevelTankList = new List <LevelTank>(); collection.ForEach(x => { var level = levelList.FirstOrDefault(l => l.TagName == x.TagName.Substring(0, Math.Max(x.TagName.IndexOf("_TANK"), 0))); var density = level != null ? densityList.FirstOrDefault(d => d.TagName == level.TagName + "_DENS") : null; if (level != null && density != null && nodeElementCollection.Any(ne => ne.Name == x.TagName)) { LevelTankList.Add(new LevelTank { Id = x.Id, TagName = x.TagName, Tank = x.Tank, Level = level, Density = density, DistanceA = x.distanceA, DistanceB = x.distanceB, ProbeLength = x.probeLength, DistToDistanceA = x.distToDistanceA, IsWriteble = true }); } }); //Инициализация объектов Tank значениями из LevelTank (distA, distB, LtoDistA) LevelTankList.ForEach((lt) => { lt.Tank.InitalizeTank(lt.DistToDistanceA, lt.DistanceA, lt.DistanceB); }); }
//Записывает данные в БД protected internal virtual void WriteItemToDB(DBPGContext context) { }
//Обновляет список переменных, занося в объекты листа данные из Базы Данных protected internal virtual void UpdateItemListFromDB(List <Temperature> temperatureList, List <Pressure> pressureList, DBPGContext dbContext) { }
//Cycle parameters calculating internal void CalculateParameters(CancellationToken token) { int iteratonCount = 0; while (!CancellationCommand && !token.IsCancellationRequested) { timer.Start(); try { temperatureCreator.UpdateItemListFromOpc(); pressureCreator.UpdateItemListFromOpc(); singleTagCreator.UpdateItemListFromOpc(); //Capacity calculation capacityCreator.UpdateItemListFromOpc(); foreach (var item in (capacityCreator as CapacityCreator).CapacityList) { if (!item.IsInValid) { item.CalculateCapacity(); } } //Density calculation densityCreator.UpdateItemListFromOpc(); foreach (var item in (densityCreator as DensityCreator).DensityList) { if (!item.IsInValid) { item.CalculateDensity(); } } //Content calculation contentCreator.UpdateItemListFromOpc(); foreach (var item in (contentCreator as ContentCreator).ContentList) { if (!item.IsInValid) { item.CalculateContent(); } } //LevelTank calculation //levelTankCreator.UpdateItemListFromOpc(); levelCreator.UpdateItemListFromOpc(); foreach (var item in (levelTankCreator as LevelTankCreator).LevelTankList) { if (!item.IsInValid) { item.CalculateTankVolume(); } } //Дополнительные расчеты (базируются на ранее расчитанных параметрах) additionalCalculator.CalculateParameters(); //Сообщаем MainWindow о том, что параметры расчитаны успешно if (parameterClaculatedSucceedEvent != null) { parameterClaculatedSucceedEvent.Invoke(this, new CustomEventArgs() { IsSucceed = true }); } AtemtsCount = 0; } catch (Exception e) { //Сообщаем MainWindow о том, что параметры не удалось расчитать if (parameterClaculatedSucceedEvent != null) { parameterClaculatedSucceedEvent.Invoke(this, new CustomEventArgs() { IsSucceed = false, ErrorMessage = e.Message }); } AtemtsCount++; //Запрашиваем реинициализацию подключения, если достигли максимального заданного кол-ва попыток if (AtemtsCount >= maxAttemptsCount && reinitalizeClientEvent != null) { AtemtsCount = 0; reinitalizeClientEvent(this, new CustomEventArgs { ErrorMessage = "Реинициализация в цикле чтения и расчета (5 попыток)" }); } IsInstanceActive = false; iteratonCount = 0; } //Проверяем, изменяется ли бит состояния записи в OPC-сервер на стороне контроллера //Если инстанс программы - Primary - записывает Primary //Если инстанс программы - Secondary и статус записи Primary не изменяется - записывает Secondary IsInstanceActive = (controllerRole == HostRole.PRIMARY_SERVER && isServerPrimaryFlipping || (controllerRole == HostRole.SECONDARY_SERVER && !isServerPrimaryFlipping && isServerSecondaryFlipping)) && controllerParameters.isEnableWriting; //6.7 Записываем singleTag - оба сервера пишут switch (controllerRole) { case HostRole.PRIMARY_SERVER: (singleTagCreator as SingleTagCreator).IsWritableTagToPLC = (singleTagCreator as SingleTagCreator).SingleTagFromPLC[0] == 0 ? (short)1 : (short)0; break; case HostRole.SECONDARY_SERVER: (singleTagCreator as SingleTagCreator).IsWritableTagToPLC = (singleTagCreator as SingleTagCreator).SingleTagFromPLC[1] == 0 ? (short)1 : (short)0; break; } try { (singleTagCreator as SingleTagCreator).WriteSyncItemToOPC(); } catch (Exception) { //Сообщаемм MainWindow о том, что произошла ошибка записи в OPC - сервер if (errorRaisedEvent != null) { errorRaisedEvent.Invoke(this, new CustomEventArgs { ErrorMessage = "Can not write value to OPC - Single tag" }); } } //Записываем все остальное if (IsInstanceActive) { try { //3.7 Записываем Capacities в OPC capacityCreator.WriteItemToOPC(); //4.7 Записываем Densities в OPC densityCreator.WriteItemToOPC(); //5.7 Записываем Contents в OPC contentCreator.WriteItemToOPC(); //5.8 Записываем LevelTanks в OPC levelTankCreator.WriteItemToOPC(); //5.9 Записываем асинхронные данные для тегов (то, что может писать только один инстанс) (singleTagCreator as SingleTagCreator).WriteASyncItemToOPC(); } catch (Exception) { //Сообщаемм MainWindow о том, что произошла ошибка записи в OPC - сервер if (errorRaisedEvent != null) { errorRaisedEvent.Invoke(this, new CustomEventArgs { ErrorMessage = "Can not write value to OPC - all other tags" }); } } //Записываем результаты расчета в поле Value БД try { using (DBPGContext dbcontext = new DBPGContext()) { capacityCreator.WriteItemToDB(dbcontext); densityCreator.WriteItemToDB(dbcontext); } } catch (Exception e) { //Сообщаемм MainWindow о том, что произошла ошибка записи в базу данных if (errorRaisedEvent != null) { errorRaisedEvent.Invoke(this, new CustomEventArgs { ErrorMessage = "Can not write value to Data Base" + $" {e.Message }" }); } } } //Если контроллер не видит сигнал записи от инстанса программы (SingleTagFromPLC[2] - Primary, SingleTagFromPLC[3] - Secondary) и при этом инстанс продолжает считать данные - запрос на реинициализацию подключения if (( (controllerRole == HostRole.PRIMARY_SERVER && isServerPrimaryFlipping && (singleTagCreator as SingleTagCreator).SingleTagFromPLC[3] == 0) || (controllerRole == HostRole.SECONDARY_SERVER && isServerSecondaryFlipping && (singleTagCreator as SingleTagCreator).SingleTagFromPLC[4] == 0) ) && reinitalizeClientEvent != null && iteratonCount >= 5 //Даем 5 циклов для сброса аварии записи в контроллере ) { reinitalizeClientEvent(this, new CustomEventArgs { ErrorMessage = "RESTARTING due to controller writing OPC Alarm!" }); break; } if (iteratonCount <= 5) { iteratonCount++; } //Time mesuring timer.Stop(); timer.Reset(); Thread.Sleep(pollingPeriod); } }
//Метод для создания и инициализации параметров из OPC internal bool InitializeParameters() { bool isiInitSuccess = true; #region 0. OpcStatusInfo From PLC + AtmoPressure //0.2. Формируем группы чтения для OPC-сервера singleTagCreator.CreateOPCReadGroup(); //0.3. Обновленная данными из OPC переменная singleTagCreator.SingleTagFromPLC try { singleTagCreator.UpdateItemListFromOpc(); errorRaisedEvent.Invoke(this, new CustomEventArgs { ErrorMessage = "Single tag - ok" }); } catch (Exception e) { if (errorRaisedEvent != null) { errorRaisedEvent.Invoke(this, new CustomEventArgs { ErrorMessage = "Single tag OPC reading error" + $" {e.Message }" }); } isiInitSuccess = false; } //0.5. Формируем группы записи для OPC-сервера (singleTagCreator as SingleTagCreator).CreateOPCWriteGroup(controllerRole == HostRole.PRIMARY_SERVER); #endregion #region 1. Temperatures //1.1. Пустой список переменных Temperature temperatureCreator.CreateItemList(); //1.2. Формируем группы чтения для OPC-сервера temperatureCreator.CreateOPCReadGroup(); //1.3. Обновленный данными из OPC список переменных Temperature try { temperatureCreator.UpdateItemListFromOpc(); errorRaisedEvent.Invoke(this, new CustomEventArgs { ErrorMessage = "Temperatures - ok" }); } catch (Exception e) { if (errorRaisedEvent != null) { errorRaisedEvent.Invoke(this, new CustomEventArgs { ErrorMessage = "Temperature OPC reading error" + $" {e.Message }" }); } isiInitSuccess = false; } #endregion #region 2. Pressures //2.1. Пустой список переменных Pressure pressureCreator.CreateItemList(); //2.2. Формируем группы чтения для OPC-сервера pressureCreator.CreateOPCReadGroup(); //2.3. Обновленный данными из OPC список переменных Pressure try { pressureCreator.UpdateItemListFromOpc(); errorRaisedEvent.Invoke(this, new CustomEventArgs { ErrorMessage = "Pressures - ok" }); } catch (Exception e) { if (errorRaisedEvent != null) { errorRaisedEvent.Invoke(this, new CustomEventArgs { ErrorMessage = "Pressures OPC reading error" + $" {e.Message }" }); } isiInitSuccess = false; } #endregion #region Levels //1.1. Пустой список переменных Level (strings с наименованием тегов) levelCreator.CreateItemList(); //1.2. Формируем группы чтения для OPC-сервера levelCreator.CreateOPCReadGroup(); //1.3. Обновленный данными из OPC список переменных Temperature try { levelCreator.UpdateItemListFromOpc(); errorRaisedEvent.Invoke(this, new CustomEventArgs { ErrorMessage = "Levels - ok" }); } catch (Exception e) { if (errorRaisedEvent != null) { errorRaisedEvent.Invoke(this, new CustomEventArgs { ErrorMessage = "Level OPC reading error" + $" {e.Message }" }); } isiInitSuccess = false; } #endregion #region 3. Capacities //3.1. Пустой список переменных Capacity capacityCreator.CreateItemList(); //3.2. Формируем группы чтения для OPC-сервера capacityCreator.CreateOPCReadGroup(); //3.3. Обновленный данными из OPC список переменных Capacity try { capacityCreator.UpdateItemListFromOpc(); errorRaisedEvent.Invoke(this, new CustomEventArgs { ErrorMessage = "Capacities - ok" }); } catch (Exception e) { if (errorRaisedEvent != null) { errorRaisedEvent.Invoke(this, new CustomEventArgs { ErrorMessage = "Capacities OPC reading error" + $" {e.Message }" }); } isiInitSuccess = false; } //3.4. Обновленный данными из DB список переменных Capacity try { using (DBPGContext dbcontext = new DBPGContext()) { capacityCreator.UpdateItemListFromDB((temperatureCreator as TemperatureCreator).TemperatureList, (pressureCreator as PressureCreator).PressureList, dbcontext); //Заполененный данными из DB список переменных } } catch (Exception e) { if (errorRaisedEvent != null) { errorRaisedEvent.Invoke(this, new CustomEventArgs { ErrorMessage = "Error in DB Capacity" + $" {e.Message }" }); } isiInitSuccess = false; } //3.5. Формируем группы записи для OPC-сервера capacityCreator.CreateOPCWriteGroup(); //3.6. Сообщаемм MainWindow о том, что Capacities сформировались if (capacitiesReadyEvent != null) { capacitiesReadyEvent.Invoke(this, new EventArgs()); } #endregion #region 4. Densities //4.1. Пустой список переменных Density densityCreator.CreateItemList(); //4.2. Формируем группы чтения для OPC-сервера densityCreator.CreateOPCReadGroup(); //4.3. Обновленный данными из OPC список переменных Density try { densityCreator.UpdateItemListFromOpc(); errorRaisedEvent.Invoke(this, new CustomEventArgs { ErrorMessage = "Densities - ok" }); } catch (Exception e) { if (errorRaisedEvent != null) { errorRaisedEvent.Invoke(this, new CustomEventArgs { ErrorMessage = "Densities OPC reading error" + $" {e.Message }" }); } isiInitSuccess = false; } //4.4. Обновленный данными из DB список переменных Density try { using (DBPGContext dbcontext = new DBPGContext()) { densityCreator.UpdateItemListFromDB((temperatureCreator as TemperatureCreator).TemperatureList, (pressureCreator as PressureCreator).PressureList, dbcontext); //Заполененный данными из DB список переменных } } catch (Exception e) { if (errorRaisedEvent != null) { errorRaisedEvent.Invoke(this, new CustomEventArgs { ErrorMessage = "Error in DB Density" + $" {e.Message }" }); } isiInitSuccess = false; } //4.5. Формируем группы записи для OPC-сервера densityCreator.CreateOPCWriteGroup(); //4.6. Сообщаемм MainWindow о том, что Densities сформировались и ими можно наполнять ComboBox в ParametersUC if (densitiesReadyEvent != null) { densitiesReadyEvent.Invoke(this, new EventArgs()); } #endregion #region 5. Contents //5.1. Пустой список переменных Content contentCreator.CreateItemList(); //5.2. Формируем группы чтения для OPC-сервера contentCreator.CreateOPCReadGroup(); //5.3. Обновленный данными из OPC список переменных Content try { contentCreator.UpdateItemListFromOpc(); errorRaisedEvent.Invoke(this, new CustomEventArgs { ErrorMessage = "Contents - ok" }); } catch (Exception e) { if (errorRaisedEvent != null) { errorRaisedEvent.Invoke(this, new CustomEventArgs { ErrorMessage = "Contents OPC reading error" + $" {e.Message }" }); } isiInitSuccess = false; } //5.4. Обновленный данными из DB список переменных Content try { using (DBPGContext dbcontext = new DBPGContext()) { contentCreator.UpdateItemListFromDB((temperatureCreator as TemperatureCreator).TemperatureList, (pressureCreator as PressureCreator).PressureList, dbcontext); //Заполененный данными из DB список переменных } } catch (Exception e) { if (errorRaisedEvent != null) { errorRaisedEvent.Invoke(this, new CustomEventArgs { ErrorMessage = "Error in DB Contents" + $" {e.Message }" }); } isiInitSuccess = false; } //5.5. Формируем группы записи для OPC-сервера contentCreator.CreateOPCWriteGroup(); //5.6. Сообщаемм MainWindow о том, что Contents сформировались и ими можно наполнять ComboBox в ParametersUC if (contentsReadyEvent != null) { contentsReadyEvent.Invoke(this, new EventArgs()); } #endregion #region 6. LevelTanks //6.1. Пустой список переменных LevelTank (список string с именами тегов) levelTankCreator.CreateItemList(); //6.2. Формируем группы чтения для OPC-сервера levelTankCreator.CreateOPCReadGroup(); //6.3.Обновленный данными из OPC список переменных LevelTank try { //levelTankCreator.UpdateItemListFromOpc(); errorRaisedEvent.Invoke(this, new CustomEventArgs { ErrorMessage = "LevelsTank - ok" }); } catch (Exception e) { if (errorRaisedEvent != null) { errorRaisedEvent.Invoke(this, new CustomEventArgs { ErrorMessage = "LevelsTank OPC reading error" + $" {e.Message }" }); } isiInitSuccess = false; } //6.4. Обновленный данными из DB список переменных LevelTank try { using (DBPGContext dbcontext = new DBPGContext()) { (levelTankCreator as LevelTankCreator).UpdateItemListFromDB((levelCreator as LevelCreator).LevelList, (densityCreator as DensityCreator).DensityList, dbcontext); //Заполененный данными из DB список переменных } } catch (Exception e) { if (errorRaisedEvent != null) { errorRaisedEvent.Invoke(this, new CustomEventArgs { ErrorMessage = "Error in DB Level" + $" {e.Message }" }); } isiInitSuccess = false; } //6.5. Формируем группы записи для OPC-сервера levelTankCreator.CreateOPCWriteGroup(); //6.6. Сообщаемм MainWindow о том, что LevelTanks сформировались и ими можно наполнять ComboBox в ParametersUC //if (densitiesReadyEvent != null) // densitiesReadyEvent.Invoke(this, new EventArgs()); #endregion //Сообщаемм MainWindow о том, что все расчетные параметры сформированы if (parametersReadyEvent != null) { parametersReadyEvent.Invoke(this, new EventArgs()); } if (!isiInitSuccess && reinitalizeClientEvent != null) { reinitalizeClientEvent(this, new CustomEventArgs { ErrorMessage = "Реинициализация при ошибке начального чтения после перезагрузки" }); } //Создаемкласс для вспомогательных вычислений additionalCalculator = new AdditionalCalculator(temperatureCreator, pressureCreator, densityCreator, capacityCreator, contentCreator, singleTagCreator); return(isiInitSuccess); }