private void btnOpen_Click(object sender, EventArgs e) { if (rbSrez.Checked) { dataTable = new DataTable("SrezTable"); SrezAdapter sa = new SrezAdapter(); sa.FileName = txtFileName.Text; sa.Fill(dataTable); } else if (rbEvent.Checked) { dataTable = new DataTable("EventTable"); EventAdapter ea = new EventAdapter(); ea.FileName = txtFileName.Text; ea.Fill(dataTable); } else // rbBase.Checked { dataTable = new DataTable("BaseTable"); BaseAdapter ba = new BaseAdapter(); ba.FileName = txtFileName.Text; ba.Fill(dataTable, true); } dataGridView.DataSource = dataTable; }
private bool editMode; // режим редактирования /// <summary> /// Конструктор /// </summary> private FrmSrezTableEdit() { InitializeComponent(); errLog = null; srezAdapter = null; srezTable = null; dataTable1 = null; dataTable2 = null; selSrez = null; editMode = false; }
/// <summary> /// Записать принятый срез в таблицу архивных срезов /// </summary> private bool WriteReceivedSrez(SrezTable srezTable, SrezAdapter srezAdapter, SrezTableLight.Srez receivedSrez, DateTime srezDT, ref SrezTableLight.Srez arcSrez) { string fileName = ""; try { // получение существующего или создание нового архивного среза fileName = srezAdapter.FileName; SrezTableCache.FillSrezTable(srezTable, srezAdapter); SrezTable.Srez srez = srezTable.GetSrez(srezDT); bool addSrez; if (srez == null) { srez = new SrezTable.Srez(srezDT, srezDescr, receivedSrez); addSrez = true; } else { addSrez = false; } if (arcSrez == null) arcSrez = srez; // изменение архивного среза lock (calculator) { try { procSrez = srez; int cntCnt = receivedSrez.CnlNums.Length; for (int i = 0; i < cntCnt; i++) { int cnlNum = receivedSrez.CnlNums[i]; int cnlInd = srez.GetCnlIndex(cnlNum); InCnl inCnl; if (inCnls.TryGetValue(cnlNum, out inCnl) && cnlInd >= 0 && (inCnl.CnlTypeID == BaseValues.CnlTypes.TS || inCnl.CnlTypeID == BaseValues.CnlTypes.TI)) { // вычисление новых данных входного канала SrezTableLight.CnlData oldCnlData = srez.CnlData[cnlInd]; SrezTableLight.CnlData newCnlData = receivedSrez.CnlData[i]; if (newCnlData.Stat == BaseValues.CnlStatuses.Defined) newCnlData.Stat = BaseValues.CnlStatuses.Archival; CalcCnlData(inCnl, oldCnlData, ref newCnlData); // запись новых данных в архивный срез srez.CnlData[cnlInd] = newCnlData; } } } finally { procSrez = null; } } // вычисление дорасчётных каналов CalcDRCnls(drCnls, srez, false); if (addSrez) srezTable.AddSrez(srez); else srezTable.MarkSrezAsModified(srez); // запись изменений таблицы срезов srezAdapter.Update(srezTable); srezTable.FileModTime = File.GetLastWriteTime(fileName); return true; } catch (Exception ex) { string fileNameStr = string.IsNullOrEmpty(fileName) ? "" : Environment.NewLine + (Localization.UseRussian ? "Имя файла: " : "Filename: ") + fileName; AppLog.WriteAction(string.Format(Localization.UseRussian ? "Ошибка при записи принятого среза в таблицу архивных срезов: {0}{1}" : "Error writing received snapshot in the archive data table: {0}{1}", ex.Message, fileNameStr), Log.ActTypes.Exception); return false; } }
/// <summary> /// Записать срез в таблицу текущего среза /// </summary> private void WriteCurSrez(SrezAdapter srezAdapter, DateTime srezDT) { string fileName = ""; try { fileName = srezAdapter.FileName; srezAdapter.Create(curSrez, srezDT); if (Settings.DetailedLog) { if (srezAdapter == curSrezAdapter) AppLog.WriteAction(Localization.UseRussian ? "Запись среза в таблицу текущего среза завершена" : "Writing snapshot in the current data table is completed", Log.ActTypes.Action); else AppLog.WriteAction(Localization.UseRussian ? "Запись среза в таблицу копии текущего среза завершена" : "Writing snapshot in the current data copy table is completed", Log.ActTypes.Action); } } catch (Exception ex) { string fileNameStr = string.IsNullOrEmpty(fileName) ? "" : Environment.NewLine + (Localization.UseRussian ? "Имя файла: " : "Filename: ") + fileName; AppLog.WriteAction(string.Format(Localization.UseRussian ? "Ошибка при записи среза в таблицу текущего среза: {0}{1}" : "Error writing snapshot in the current data table: {0}{1}", ex.Message, fileNameStr), Log.ActTypes.Exception); } }
/// <summary> /// Записать срез в таблицу архивных (минутных или часовых) срезов /// </summary> private void WriteArcSrez(SrezTable srezTable, SrezAdapter srezAdapter, DateTime srezDT, AvgData[] avgData) { string fileName = ""; try { // заполнение таблицы срезов, если файл изменился fileName = srezAdapter.FileName; SrezTableCache.FillSrezTable(srezTable, srezAdapter); // добавление копии среза в таблицу SrezTable.Srez newSrez = srezTable.AddSrezCopy(curSrez, srezDT); // запись усредняемых данных bool changed = false; foreach (int cnlInd in avgCnlInds) { AvgData ad = avgData[cnlInd]; if (ad.Cnt > 0) { newSrez.CnlData[cnlInd] = new SrezTableLight.CnlData(ad.Sum / ad.Cnt, BaseValues.CnlStatuses.Defined); avgData[cnlInd] = new AvgData() { Sum = 0.0, Cnt = 0 }; // сброс changed = true; } } // вычисление дорасчётных каналов, если добавленый срез изменился if (changed) CalcDRCnls(drCnls, newSrez, false); // запись изменений таблицы срезов srezAdapter.Update(srezTable); srezTable.FileModTime = File.GetLastWriteTime(fileName); if (Settings.DetailedLog) AppLog.WriteAction(string.Format(Localization.UseRussian ? "Запись среза в таблицу {0} завершена" : "Writing snapshot in the {0} table is completed", srezTable.Descr), Log.ActTypes.Action); } catch (Exception ex) { string fileNameStr = string.IsNullOrEmpty(fileName) ? "" : Environment.NewLine + (Localization.UseRussian ? "Имя файла: " : "Filename: ") + fileName; AppLog.WriteAction(string.Format(Localization.UseRussian ? "Ошибка при записи среза в таблицу архивных срезов: {0}{1}" : "Error writing snapshot in the archive data table: {0}{1}", ex.Message, fileNameStr), Log.ActTypes.Exception); } }
private string workState; // состояние работы #endregion Fields #region Constructors /// <summary> /// Конструктор /// </summary> public MainLogic() { AppDirs = new AppDirs(); AppLog = new Log(Log.Formats.Full); AppLog.Encoding = Encoding.UTF8; Settings = new Settings(); infoFileName = ""; thread = null; terminated = false; serverIsReady = false; startDT = DateTime.MinValue; workState = ""; comm = new Comm(this); calculator = new Calculator(this); inCnls = new SortedList<int, InCnl>(); drCnls = null; drmCnls = null; drhCnls = null; drCnlNums = null; drmCnlNums = null; drhCnlNums = null; avgCnlInds = null; ctrlCnls = new SortedList<int, CtrlCnl>(); users = new SortedList<string, User>(); formulas = new List<string>(); curSrez = null; curSrezMod = false; srezDescr = null; minAvgData = null; hrAvgData = null; activeDTs = null; curSrezAdapter = null; curSrezCopyAdapter = null; eventAdapter = null; eventCopyAdapter = null; minSrezTableCache = null; hrSrezTableCache = null; modules = new List<ModLogic>(); }
/// <summary> /// Цикл работы сервера (метод вызывается в отдельном потоке) /// </summary> private void Execute() { try { // запись информации о работе приложения workState = WorkStateNames.Normal; WriteInfo(); // выполнение действий модулей RaiseOnServerStart(); // инициализация адаптеров таблиц текущего среза и событий curSrezAdapter = new SrezAdapter(); curSrezCopyAdapter = new SrezAdapter(); eventAdapter = new EventAdapter(); eventCopyAdapter = new EventAdapter(); curSrezAdapter.FileName = ServerUtils.BuildCurFileName(Settings.ArcDir); curSrezCopyAdapter.FileName = ServerUtils.BuildCurFileName(Settings.ArcCopyDir); eventAdapter.Directory = Settings.ArcDir + "Events" + Path.DirectorySeparatorChar; eventCopyAdapter.Directory = Settings.ArcCopyDir + "Events" + Path.DirectorySeparatorChar; // инициализация кэша таблиц минутных и часовых срезов minSrezTableCache = new SortedList<DateTime, SrezTableCache>(); hrSrezTableCache = new SortedList<DateTime, SrezTableCache>(); // инициализация описания создаваемых срезов int cnlCnt = inCnls.Count; srezDescr = new SrezTable.SrezDescr(cnlCnt); for (int i = 0; i < cnlCnt; i++) srezDescr.CnlNums[i] = inCnls.Values[i].CnlNum; srezDescr.CalcCS(); // загрузка исходного текущего среза из файла SrezTableLight.Srez curSrezSrc = null; SrezTableLight tblCurSrezScr = new SrezTableLight(); try { if (File.Exists(curSrezAdapter.FileName)) { curSrezAdapter.Fill(tblCurSrezScr); if (tblCurSrezScr.SrezList.Count > 0) curSrezSrc = tblCurSrezScr.SrezList.Values[0]; } if (curSrezSrc == null) AppLog.WriteAction(Localization.UseRussian ? "Текущий срез не загружен" : "Current data are not loaded", Log.ActTypes.Action); else AppLog.WriteAction(Localization.UseRussian ? "Текущий срез загружен" : "Current data are loaded", Log.ActTypes.Action); } catch (Exception ex) { AppLog.WriteAction((Localization.UseRussian ? "Ошибка при загрузке текущего среза: " : "Error loading current data: ") + ex.Message, Log.ActTypes.Exception); } // инициализация текущего среза, предназначенного для формироваться данных сервера curSrez = new SrezTable.Srez(DateTime.MinValue, srezDescr, curSrezSrc); // инициализация данных для усреднения и времени активности каналов minAvgData = new AvgData[cnlCnt]; hrAvgData = new AvgData[cnlCnt]; activeDTs = new DateTime[cnlCnt]; DateTime nowDT = DateTime.Now; for (int i = 0; i < cnlCnt; i++) { minAvgData[i] = new AvgData() { Sum = 0.0, Cnt = 0 }; hrAvgData[i] = new AvgData() { Sum = 0.0, Cnt = 0 }; activeDTs[i] = nowDT; } // цикл работы сервера nowDT = DateTime.MaxValue; DateTime today = nowDT.Date; DateTime prevDT; DateTime writeCurSrezDT = DateTime.MinValue; DateTime writeMinSrezDT = DateTime.MinValue; DateTime writeHrSrezDT = DateTime.MinValue; DateTime calcMinDT = DateTime.MinValue; DateTime calcHrDT = DateTime.MinValue; DateTime clearCacheDT = nowDT; bool writeCur = Settings.WriteCur || Settings.WriteCurCopy; bool writeCurOnMod = Settings.WriteCurPer <= 0; bool writeMin = (Settings.WriteMin || Settings.WriteMinCopy) && Settings.WriteMinPer > 0; bool writeHr = (Settings.WriteHr || Settings.WriteHrCopy) && Settings.WriteHrPer > 0; curSrezMod = false; serverIsReady = true; while (!terminated) { prevDT = nowDT; nowDT = DateTime.Now; today = nowDT.Date; // расчёт времени записи срезов и вычисления значений дорасчётных каналов // при переводе времени назад или при первом проходе цикла if (prevDT > nowDT) { writeCurSrezDT = nowDT; writeMinSrezDT = CalcNextTime(nowDT, Settings.WriteMinPer); writeHrSrezDT = CalcNextTime(nowDT, Settings.WriteHrPer); calcMinDT = drmCnls.Count > 0 ? CalcNextTime(nowDT, 60) : DateTime.MaxValue; calcHrDT = drhCnls.Count > 0 ? CalcNextTime(nowDT, 3600) : DateTime.MaxValue; } // удаление устаревших файлов срезов и событий при изменении даты или при первом проходе цикла if (prevDT.Date != today) { ClearArchive(Settings.ArcDir + "Min", "m*.dat", today.AddDays(-Settings.StoreMinPer)); ClearArchive(Settings.ArcDir + "Hour", "h*.dat", today.AddDays(-Settings.StoreHrPer)); ClearArchive(Settings.ArcDir + "Events", "e*.dat", today.AddDays(-Settings.StoreEvPer)); ClearArchive(Settings.ArcCopyDir + "Min", "m*.dat", today.AddDays(-Settings.StoreMinPer)); ClearArchive(Settings.ArcCopyDir + "Hour", "h*.dat", today.AddDays(-Settings.StoreHrPer)); ClearArchive(Settings.ArcCopyDir + "Events", "e*.dat", today.AddDays(-Settings.StoreEvPer)); } lock (curSrez) { // установка недостоверности неактивных каналов SetUnreliable(); // вычисление дорасчётных каналов и выполнение действий модулей CalcDRCnls(drCnls, curSrez, true); RaiseOnCurDataCalculated(drCnlNums, curSrez); // вычисление минутных каналов и выполнение действий модулей if (calcMinDT <= nowDT) { CalcDRCnls(drmCnls, curSrez, true); RaiseOnCurDataCalculated(drmCnlNums, curSrez); calcMinDT = CalcNextTime(nowDT, 60); curSrezMod = true; } // вычисление часовых каналов и выполнение действий модулей if (calcHrDT <= nowDT) { CalcDRCnls(drhCnls, curSrez, true); RaiseOnCurDataCalculated(drhCnlNums, curSrez); calcHrDT = CalcNextTime(nowDT, 3600); curSrezMod = true; } // запись текущего среза if ((writeCurSrezDT <= nowDT || writeCurOnMod && curSrezMod) && writeCur) { if (writeCurOnMod) { WriteSrez(SrezTypes.Cur, nowDT); curSrezMod = false; writeCurSrezDT = DateTime.MaxValue; } else { WriteSrez(SrezTypes.Cur, writeCurSrezDT); writeCurSrezDT = CalcNextTime(nowDT, Settings.WriteCurPer); } } // запись минутного среза if (writeMinSrezDT <= nowDT && writeMin) { WriteSrez(SrezTypes.Min, writeMinSrezDT); writeMinSrezDT = CalcNextTime(nowDT, Settings.WriteMinPer); } // запись часового среза if (writeHrSrezDT <= nowDT && writeHr) { WriteSrez(SrezTypes.Hour, writeHrSrezDT); writeHrSrezDT = CalcNextTime(nowDT, Settings.WriteHrPer); } } // очистка устаревших данных кэша if (nowDT - clearCacheDT > CacheClearSpan || nowDT < clearCacheDT /*время переведено назад*/) { clearCacheDT = nowDT; ClearSrezTableCache(minSrezTableCache, MinCacheStorePer, MinCacheCapacity); ClearSrezTableCache(hrSrezTableCache, HourCacheStorePer, HourCacheCapacity); } // запись информации о работе приложения WriteInfo(); // задержка для экономиии ресурсов процессора Thread.Sleep(100); } } finally { // выполнение действий модулей RaiseOnServerStop(); // запись информации о работе приложения workState = WorkStateNames.Stopped; WriteInfo(); } }
/// <summary> /// Принять таблицу срезов от SCADA-Сервера /// </summary> public bool ReceiveSrezTable(string tableName, SrezTableLight srezTableLight) { Monitor.Enter(tcpLock); bool result = false; errMsg = ""; try { try { if (RestoreConnection()) { // определение директории таблицы Dirs dir = Dirs.Cur; if (tableName.Length > 0) { if (tableName[0] == 'h') dir = Dirs.Hour; else if (tableName[0] == 'm') dir = Dirs.Min; } // приём данных using (MemoryStream memStream = new MemoryStream()) { if (ReceiveFile(dir, tableName, memStream)) { SrezAdapter adapter = new SrezAdapter(); adapter.Stream = memStream; adapter.TableName = tableName; adapter.Fill(srezTableLight); result = true; } } } } finally { // очистка таблицы, если не удалось получить новые данные if (!result) { srezTableLight.Clear(); srezTableLight.TableName = tableName; } } } catch (Exception ex) { errMsg = (Localization.UseRussian ? "Ошибка при приёме таблицы срезов от SCADA-Сервера: " : "Error receiving data table from SCADA-Server: ") + ex.Message; WriteAction(errMsg, Log.ActTypes.Exception); } finally { Monitor.Exit(tcpLock); } return result; }
/// <summary> /// Заполнить таблицу срезов /// </summary> public static void FillSrezTable(SrezTable srezTable, SrezAdapter srezAdapter) { string fileName = srezAdapter.FileName; if (File.Exists(fileName)) { // определение времени последнего изменения файла таблицы срезов DateTime fileModTime = File.GetLastWriteTime(fileName); // загрузка данных, если файл был изменён if (srezTable.FileModTime != fileModTime) { srezAdapter.Fill(srezTable); srezTable.FileModTime = fileModTime; } } else { srezTable.Clear(); } }
/// <summary> /// Конструктор /// </summary> public SrezTableCache(DateTime date) { AccessDT = DateTime.Now; Date = date; SrezTable = new SrezTable(); SrezTableCopy = new SrezTable(); SrezAdapter = new SrezAdapter(); SrezCopyAdapter = new SrezAdapter(); }
/// <summary> /// Экспортировать архивные данные, загрузив их из файла /// </summary> private void ExportArcDataFromFile(Exporter exporter, DateTime dateTime) { // загрузка таблицы минутных срезов из файла SrezTableLight srezTable = new SrezTableLight(); SrezAdapter srezAdapter = new SrezAdapter(); srezAdapter.FileName = ServerUtils.BuildMinFileName(Settings.ArcDir, dateTime); try { srezAdapter.Fill(srezTable); } catch (Exception ex) { log.WriteAction(string.Format(Localization.UseRussian ? "Ошибка при загрузке таблицы минутных срезов из файла {0}: {1}" : "Error loading minute data table from file {0}: {1}", srezAdapter.FileName, ex.Message)); } // поиск среза на заданное время SrezTableLight.Srez srez = srezTable.GetSrez(dateTime); // добавление среза в очередь экспорта if (srez == null) { log.WriteAction(Localization.UseRussian ? "Отсутствуют архивные данные для экспорта" : "No archive data to export"); } else { exporter.EnqueueArcData(srez); log.WriteAction(Localization.UseRussian ? "Архивные данные добавлены в очередь экспорта" : "Archive data added to export queue"); } }
/// <summary> /// Экспортировать текущие данные, загрузив их из файла /// </summary> private void ExportCurDataFromFile(Exporter exporter) { // загрузка текущего среза из файла SrezTableLight srezTable = new SrezTableLight(); SrezAdapter srezAdapter = new SrezAdapter(); srezAdapter.FileName = ServerUtils.BuildCurFileName(Settings.ArcDir); try { srezAdapter.Fill(srezTable); } catch (Exception ex) { log.WriteAction(string.Format(Localization.UseRussian ? "Ошибка при загрузке текущего среза из файла {0}: {1}" : "Error loading current data from file {0}: {1}", srezAdapter.FileName, ex.Message)); } // добавление среза в очередь экспорта if (srezTable.SrezList.Count > 0) { SrezTableLight.Srez sourceSrez = srezTable.SrezList.Values[0]; SrezTableLight.Srez srez = CreateSrez(DateTime.Now, sourceSrez.CnlNums, sourceSrez); exporter.EnqueueCurData(srez); log.WriteAction(Localization.UseRussian ? "Текущие данные добавлены в очередь экспорта" : "Current data added to export queue"); } else { log.WriteAction(Localization.UseRussian ? "Отсутствуют текущие данные для экспорта" : "No current data to export"); } }
/// <summary> /// Отобразить форму редактирования или просмотра таблицы срезов /// </summary> public static void Show(string directory, string tableName, bool editMode, Log errLog) { if (string.IsNullOrEmpty(directory)) throw new ArgumentException("directory"); if (string.IsNullOrEmpty(tableName)) throw new ArgumentException("tableName"); if (errLog == null) throw new ArgumentNullException("errLog"); SrezAdapter srezAdapter = new SrezAdapter(); srezAdapter.Directory = directory; srezAdapter.TableName = tableName; SrezTable srezTable = new SrezTable(); if (LoadSrezTable(srezAdapter, errLog, ref srezTable)) { FrmSrezTableEdit frmSrezTableEdit = new FrmSrezTableEdit(); frmSrezTableEdit.errLog = errLog; frmSrezTableEdit.srezAdapter = srezAdapter; frmSrezTableEdit.srezTable = srezTable; frmSrezTableEdit.editMode = editMode; frmSrezTableEdit.ShowDialog(); } }
/// <summary> /// Загрузить таблицу срезов /// </summary> private static bool LoadSrezTable(SrezAdapter srezAdapter, Log errLog, ref SrezTable srezTable) { try { srezAdapter.Fill(srezTable); return true; } catch (Exception ex) { string errMsg = AppPhrases.LoadSrezTableError + ":\r\n" + ex.Message; if (errLog != null) errLog.WriteAction(errMsg, Log.ActTypes.Exception); ScadaUtils.ShowError(errMsg); return false; } finally { Cursor.Current = Cursors.Default; } }