/// <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> private SrezTableLight.Srez ConvertSrez(KPLogic.TagSrez tagSrez) { List<int> boundIndexes; int cnlCnt; if (tagSrez == null) { boundIndexes = null; cnlCnt = 0; } else { boundIndexes = tagSrez.GetBoundTagIndexes(); cnlCnt = boundIndexes.Count; } if (cnlCnt == 0) { return null; } else { SrezTableLight.Srez srez = new SrezTableLight.Srez(tagSrez.DateTime, cnlCnt); for (int i = 0; i < cnlCnt; i++) { int tagInd = boundIndexes[i]; srez.CnlNums[i] = tagSrez.KPTags[tagInd].CnlNum; srez.CnlData[i] = tagSrez.TagData[tagInd]; } return srez; } }
/// <summary> /// Export archived data by downloading it from a file /// </summary> private void ExportArcDataFromFile(Exporter exporter, DateTime dateTime) { // loading the table of minute slices from a file 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)); } // search for a slice for a specified time SrezTableLight.Srez srez = srezTable.GetSrez(dateTime); // add slice to export queue 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 ExportArcData() { if (ExportParams.ExportArcData) { DbTransaction trans = null; SrezTableLight.Srez srez = null; try { trans = DataSource.Connection.BeginTransaction(); DataSource.ExportArcDataCmd.Transaction = trans; for (int i = 0; i < BundleSize; i++) { // извлечение среза из очереди lock (arcSrezQueue) { if (arcSrezQueue.Count > 0) { srez = arcSrezQueue.Dequeue(); } else { break; } } // экспорт ExportSrez(DataSource.ExportArcDataCmd, srez); expArcSrezCnt++; exportError = false; } trans.Commit(); } catch (Exception ex) { if (trans != null) { trans.Rollback(); } // возврат среза в очередь if (srez != null) { lock (arcSrezQueue) arcSrezQueue.Enqueue(srez); } log.WriteAction(string.Format(Localization.UseRussian ? "Ошибка при экспорте архивных данных в БД {0}: {1}" : "Error export archive data to DB {0}: {1}", DataSource.Name, ex.Message)); exportError = true; Thread.Sleep(ErrorDelay); } } }
public bool SetCurrSrez(SrezTableLight.Srez srez) { bool rec; lock (rssrv) { rec = rssrv.SendSrez(srez, out rec); } return(rec); }
/// <summary> /// Получить расширенные текущие данные входных каналов /// </summary> private CnlDataExt[] GetCurCnlDataExtArr(IList <int> cnlList) { DateTime dataAge; SrezTableLight.Srez snapshot = AppData.DataAccess.DataCache.GetCurSnapshot(out dataAge); string emptyVal; bool dataVisible = DataFormatter.CurDataVisible(dataAge, DateTime.Now, out emptyVal); return(CreateCnlDataExtArr(cnlList, snapshot, dataVisible, emptyVal)); }
/// <summary> /// Export current data /// </summary> private void ExportCurData() { if (ExportParams.ExportCurData) { DbTransaction trans = null; SrezTableLight.Srez srez = null; try { trans = DataSource.Connection.BeginTransaction(); DataSource.ExportCurDataCmd.Transaction = trans; for (var i = 0; i < BundleSize; i++) { // extract slice from the queue lock (curSrezQueue) { if (curSrezQueue.Count > 0) { srez = curSrezQueue.Dequeue(); } else { break; } } // export ExportSrez(DataSource.ExportCurDataCmd, srez); expCurSrezCnt++; exportError = false; } trans.Commit(); } catch (Exception ex) { SafeRollback(trans); // return cut to the queue if (srez != null) { lock (curSrezQueue) curSrezQueue.Enqueue(srez); } log.WriteAction(string.Format( Localization.UseRussian ? "Ошибка при экспорте текущих данных в БД {0}: {1}" : "Error export current data to DB {0}: {1}", DataSource.Name, ex.Message)); exportError = true; Thread.Sleep(ErrorDelay); } } }
/// <summary> /// Добавить часовые данные в список /// </summary> private void AppendHourCnlData(List <HourCnlData> hourCnlDataList, double hour, IList <int> cnlList, SrezTableLight.Srez snapshot, DateTime snapshotDT, DateTime nowDT) { HourCnlData hourCnlData = new HourCnlData(hour); hourCnlData.Modified = true; string emptyVal; bool dataVisible = DataFormatter.HourDataVisible(snapshotDT, nowDT, snapshot != null, out emptyVal); hourCnlData.CnlDataExtArr = CreateCnlDataExtArr(cnlList, snapshot, dataVisible, emptyVal); hourCnlDataList.Add(hourCnlData); }
/// <summary> /// Perform actions after processing new current data /// </summary> public override void OnCurDataProcessed(int[] cnlNums, SrezTableLight.Srez curSrez) { // export of current data to the database if (normalWork) { // creating an exported slice SrezTableLight.Srez srez = new SrezTableLight.Srez(DateTime.Now, cnlNums, curSrez); // add slice to export queue foreach (var exporter in exporters) { exporter.EnqueueCurData(srez); } } }
/// <summary> /// Выполнить действия после обработки новых текущих данных /// </summary> public override void OnCurDataProcessed(int[] cnlNums, SrezTableLight.Srez curSrez) { // экспорт текущих данных в БД if (normalWork) { // создание экпортируемого среза SrezTableLight.Srez srez = new SrezTableLight.Srez(DateTime.Now, cnlNums, curSrez); // добавление среза в очередь экспорта foreach (Exporter exporter in exporters) { exporter.EnqueueCurData(srez); } } }
/// <summary> /// Выполнить действия после обработки новых архивных данных /// </summary> public override void OnArcDataProcessed(int[] cnlNums, SrezTableLight.Srez arcSrez) { // экспорт архивных данных в БД if (normalWork) { // создание экпортируемого среза SrezTableLight.Srez srez = new SrezTableLight.Srez(arcSrez.DateTime, cnlNums, arcSrez); // добавление среза в очередь экспорта foreach (Exporter exporter in exporters) { exporter.EnqueueArcData(srez); } } }
/// <summary> /// Perform actions after processing new archived data /// </summary> public override void OnArcDataProcessed(int[] cnlNums, SrezTableLight.Srez arcSrez) { // export of archive data to the database if (normalWork) { // creating an exported slice SrezTableLight.Srez srez = new SrezTableLight.Srez(arcSrez.DateTime, cnlNums, arcSrez); // add slice to export queue foreach (var exporter in exporters) { exporter.EnqueueArcData(srez); } } }
/// <summary> /// Экспортировать срез /// </summary> private void ExportSrez(DbCommand cmd, SrezTableLight.Srez srez) { DataSource.SetCmdParam(cmd, "dateTime", srez.DateTime); foreach (int cnlNum in srez.CnlNums) { SrezTableLight.CnlData cnlData; if (srez.GetCnlData(cnlNum, out cnlData)) { DataSource.SetCmdParam(cmd, "cnlNum", cnlNum); DataSource.SetCmdParam(cmd, "val", cnlData.Val); DataSource.SetCmdParam(cmd, "stat", cnlData.Stat); cmd.ExecuteNonQuery(); } } }
/// <summary> /// Экспортировать текущие данные /// </summary> private void ExportCurData() { if (ExportParams.ExportCurData) { SrezTableLight.Srez sres = null; try { for (int i = 0; i < BundleSize; i++) { // извлечение среза из очереди lock (curSrezQueue) { if (curSrezQueue.Count > 0) { sres = curSrezQueue.Dequeue(); } else { break; } } // экспорт ExportSrez(DataSource.ExportCurDataCmd, sres); expCurSrezCnt++; exportError = false; } } catch (Exception ex) { // возврат среза в очередь if (sres != null) { lock (curSrezQueue) curSrezQueue.Enqueue(sres); } log.WriteAction(string.Format(Localization.UseRussian ? "Ошибка при экспорте текущих данных в БД {0}: {1}" : "Error export current data to DB {0}: {1}", DataSource.Name, ex.Message)); exportError = true; Thread.Sleep(ErrorDelay); } } }
/// <summary> /// Получить расширенные текущие данные входных каналов /// </summary> private CnlDataExtDTO[] GetCnlDataExtDTOs(IList <int> cnlList) { int cnlCnt = cnlList.Count; CnlDataExtDTO[] cnlDataDTOs = new CnlDataExtDTO[cnlCnt]; DataAccess dataAccess = AppData.DataAccess; DateTime dataAge; SrezTableLight.Srez snapshot = dataAccess.DataCache.GetCurSnapshot(out dataAge); string emptyVal = ""; bool dataVisible = snapshot != null && DataFormatter.CurDataVisible(dataAge, DateTime.Now, out emptyVal); for (int i = 0; i < cnlCnt; i++) { int cnlNum = cnlList[i]; CnlDataExtDTO cnlDataDTO = new CnlDataExtDTO(cnlNum); cnlDataDTOs[i] = cnlDataDTO; SrezTableLight.CnlData cnlData; snapshot.GetCnlData(cnlNum, out cnlData); cnlDataDTO.Val = cnlData.Val; cnlDataDTO.Stat = cnlData.Stat; if (dataVisible) { InCnlProps cnlProps = dataAccess.GetCnlProps(cnlNum); string text; string textWithUnit; DataFormatter.FormatCnlVal(cnlData.Val, cnlData.Stat, cnlProps, out text, out textWithUnit); cnlDataDTO.Text = text; cnlDataDTO.TextWithUnit = textWithUnit; cnlDataDTO.Color = DataFormatter.GetCnlValColor(cnlData.Val, cnlData.Stat, cnlProps, dataAccess.GetColorByStat); } else { cnlDataDTO.Text = cnlDataDTO.TextWithUnit = emptyVal; } } return(cnlDataDTOs); }
/// <summary> /// Добавить текущие данные в очередь экспорта /// </summary> public void EnqueueCurData(SrezTableLight.Srez curSrez) { lock (curSrezQueue) { if (curSrezQueue.Count < MaxQueueSize) { curSrezQueue.Enqueue(curSrez); } else { skipCurSrezCnt++; log.WriteAction(string.Format(Localization.UseRussian ? "Невозможно добавить в очередь текущие данные. Максимальный размер очереди {0} превышен" : "Unable to enqueue current data. The maximum size of the queue {0} is exceeded", MaxQueueSize)); } } }
/// <summary> /// Добавить архивные данные в очередь экспорта /// </summary> public void EnqueueArcData(SrezTableLight.Srez arcSrez) { lock (arcSrezQueue) { if (arcSrezQueue.Count < MaxQueueSize) { arcSrezQueue.Enqueue(arcSrez); } else { skipArcSrezCnt++; log.WriteAction(string.Format(Localization.UseRussian ? "Невозможно добавить в очередь архивные данные. Максимальный размер очереди {0} превышен" : "Unable to enqueue archive data. The maximum size of the queue {0} is exceeded", MaxQueueSize)); } } }
/// <summary> /// Создать срез с заданными номерами каналов, используя данные из исходного среза /// </summary> private SrezTableLight.Srez CreateSrez(DateTime srezDT, int[] cnlNums, SrezTableLight.Srez sourceSrez) { int cnlCnt = cnlNums.Length; SrezTableLight.Srez srez = new SrezTableLight.Srez(srezDT, cnlCnt); for (int i = 0; i < cnlCnt; i++) { int cnlNum = cnlNums[i]; SrezTableLight.CnlData cnlData; sourceSrez.GetCnlData(cnlNum, out cnlData); srez.CnlNums[i] = cnlNum; srez.CnlData[i] = cnlData; } return(srez); }
/// <summary> /// Создать и заполнить массив расширенных данных входных каналов /// </summary> private CnlDataExt[] CreateCnlDataExtArr(IList <int> cnlList, SrezTableLight.Srez snapshot, bool dataVisible, string emptyVal) { DataAccess dataAccess = AppData.DataAccess; int cnlCnt = cnlList == null ? 0 : cnlList.Count; CnlDataExt[] cnlDataExtArr = new CnlDataExt[cnlCnt]; for (int i = 0; i < cnlCnt; i++) { int cnlNum = cnlList[i]; CnlDataExt cnlDataExt = new CnlDataExt(cnlNum); cnlDataExtArr[i] = cnlDataExt; if (dataVisible) { double val; int stat; snapshot.GetCnlData(cnlNum, out val, out stat); if (!double.IsNaN(val)) { cnlDataExt.Val = val; cnlDataExt.Stat = stat; } InCnlProps cnlProps = dataAccess.GetCnlProps(cnlNum); string text; string textWithUnit; DataFormatter.FormatCnlVal(val, stat, cnlProps, out text, out textWithUnit); cnlDataExt.Text = text; cnlDataExt.TextWithUnit = textWithUnit; CnlStatProps cnlStatProps = dataAccess.GetCnlStatProps(stat); cnlDataExt.Color = DataFormatter.GetCnlValColor(val, stat, cnlProps, cnlStatProps); } else { cnlDataExt.Text = cnlDataExt.TextWithUnit = emptyVal; } } return(cnlDataExtArr); }
/// <summary> /// Получить текущие данные входного канала. /// </summary> public SrezTableLight.CnlData GetCurCnlData(int cnlNum, out DateTime dataAge) { try { SrezTableLight.Srez snapshot = dataCache.GetCurSnapshot(out dataAge); SrezTableLight.CnlData cnlData; return(snapshot != null && snapshot.GetCnlData(cnlNum, out cnlData) ? cnlData : SrezTableLight.CnlData.Empty); } catch (Exception ex) { log.WriteException(ex, Localization.UseRussian ? "Ошибка при получении текущих данных входного канала {0}" : "Error getting current data of the input channel {0}", cnlNum); dataAge = DateTime.MinValue; return(SrezTableLight.CnlData.Empty); } }
public void SendCurrSrez(List <Cnl> cnls) { bool res = false; DateTime dt = DateTime.Now; foreach (Cnl cnl in cnls) { RSServer RSSrv = GetRSSrvId(cnl.ID); SrezTableLight stl = new SrezTableLight(); SrezTableLight.Srez curSrezSrc = new SrezTableLight.Srez(dt, 1); curSrezSrc.CnlNums [0] = cnl.Num; curSrezSrc.CnlData [0] = new SrezTableLight.CnlData() { Val = cnl.Value, Stat = cnl.State }; res = RSSrv.SendSrez(curSrezSrc, out res); } }
private void btnSend_Click(object sender, EventArgs e) { // retrieve data to send if (!int.TryParse(cbCnlNum.Text, out int cnlNum)) { ScadaUiUtils.ShowError(ServerShellPhrases.IncorrectCnlNum); return; } double cnlVal = ScadaUtils.StrToDouble(txtCnlVal.Text); if (double.IsNaN(cnlVal)) { ScadaUiUtils.ShowError(ServerShellPhrases.IncorrectCnlVal); return; } DateTime srezDT = rbCurData.Checked ? DateTime.MinValue : dtpArcDate.Value.Date.Add(dtpArcTime.Value.TimeOfDay); SrezTableLight.Srez srez = new SrezTableLight.Srez(srezDT, 1); srez.CnlNums[0] = cnlNum; srez.CnlData[0] = new SrezTableLight.CnlData(cnlVal, decimal.ToInt32(numCnlStat.Value)); // send data if (rbCurData.Checked ? serverComm.SendSrez(srez, out bool result) : serverComm.SendArchive(srez, out result)) { cbCnlNum.Items.Remove(cnlNum); cbCnlNum.Items.Insert(0, cnlNum); DialogResult = DialogResult.OK; } else { errLog.WriteError(serverComm.ErrMsg); ScadaUiUtils.ShowError(serverComm.ErrMsg); } }
public override void OnCurDataProcessed(int[] cnlNums, SrezTableLight.Srez curSrez) { // the method executes when new current data have been processed by the server, // the channel numbers are sorted in ascending order const int MyCnlNum = 1; const int MyKpNum = 1; const int MyCmdNum = 1; const double MyCmdVal = 1.0; // send a command if the value of MyCnlNum channel greater than 200 WriteToLog("Process current data by the module " + Name, Log.ActTypes.Action); SrezTableLight.CnlData cnlData; if (curSrez.GetCnlData(MyCnlNum, out cnlData) && cnlData.Val > 200) { WriteToLog("Send command by the module " + Name, Log.ActTypes.Action); Command cmd = new Command(BaseValues.CmdTypes.Standard); cmd.KPNum = MyKpNum; cmd.CmdNum = MyCmdNum; cmd.CmdVal = MyCmdVal; ServerCommands.PassCommand(cmd); } }
public List <MQTTPubTopic> GetValues(List <MQTTPubTopic> MqttPTs) { if (cn) { SrezTableLight stl = new SrezTableLight(); IsCurr = rsrv.ReceiveSrezTable("current.dat", stl); SrezTableLight.Srez srez = stl.SrezList.Values [0]; bool found; SrezTableLight.CnlData cnlData; foreach (MQTTPubTopic MqttPT in MqttPTs) { found = srez.GetCnlData(MqttPT.NumCnl, out cnlData); if (found) { if (MqttPT.Value != cnlData.Val) { MqttPT.IsPub = true; } MqttPT.Value = cnlData.Val; } } } return(MqttPTs); }
public override void OnCurDataProcessed(int[] cnlNums, SrezTableLight.Srez curSrez) { // the method executes when new current data have been processed by the server, // the channel numbers are sorted in ascending order // метод выполняется после обработки новых текущих данных сервером, // номера каналов упорядочены по возрастанию const int MyCnlNum = 1; const int MyKpNum = 1; const int MyCmdNum = 1; const double MyCmdVal = 1.0; // send a command if the value of MyCnlNum channel greater than 200 WriteToLog("Process current data by the module " + Name, Log.ActTypes.Action); SrezTableLight.CnlData cnlData; if (curSrez.GetCnlData(MyCnlNum, out cnlData) && cnlData.Val > 200) { WriteToLog("Send command by the module " + Name, Log.ActTypes.Action); Command cmd = new Command(BaseValues.CmdTypes.Standard); cmd.KPNum = MyKpNum; cmd.CmdNum = MyCmdNum; cmd.CmdVal = MyCmdVal; PassCommand(cmd); } }
/// <summary> /// Преобразовать среза параметров в срез входных каналов /// </summary> private SrezTableLight.Srez ConvertSrez(KPLogic.ParamSrez paramSrez) { List <int> bindedIndexes; int cnlCnt; if (paramSrez == null) { bindedIndexes = null; cnlCnt = 0; } else { bindedIndexes = paramSrez.GetBindedParamIndexes(); cnlCnt = bindedIndexes.Count; } if (cnlCnt == 0) { return(null); } else { SrezTableLight.Srez srez = new SrezTableLight.Srez(paramSrez.DateTime, cnlCnt); for (int i = 0; i < cnlCnt; i++) { int paramInd = bindedIndexes[i]; srez.CnlNums[i] = paramSrez.KPParams[paramInd].CnlNum; KPLogic.ParamData paramData = paramSrez.Data[paramInd]; SrezTableLight.CnlData cnlData = new SrezTableLight.CnlData(paramData.Val, paramData.Stat); srez.CnlData[i] = cnlData; } return(srez); } }
/// <summary> /// Получить таблицу срезов, содержащую данные заданных каналов /// </summary> public SrezTableLight GetSrezTable(DateTime date, SrezTypes srezType, int[] cnlNums) { try { SrezTableLight destSrezTable; int cnlNumsLen = cnlNums == null ? 0 : cnlNums.Length; if (serverIsReady && cnlNumsLen > 0) { // получение кэша таблицы срезов SrezTableCache srezTableCache = GetSrezTableCache(date.Date, srezType); lock (srezTableCache) { // заполнение таблицы срезов в кэше srezTableCache.FillSrezTable(); // создание новой таблицы срезов и копирование в неё данных заданных каналов SrezTable srcSrezTable = srezTableCache.SrezTable; SrezTable.SrezDescr prevSrezDescr = null; int[] cnlNumIndexes = new int[cnlNumsLen]; destSrezTable = new SrezTableLight(); foreach (SrezTable.Srez srcSrez in srcSrezTable.SrezList.Values) { // определение индексов каналов if (!srcSrez.SrezDescr.Equals(prevSrezDescr)) { for (int i = 0; i < cnlNumsLen; i++) cnlNumIndexes[i] = Array.BinarySearch<int>(srcSrez.CnlNums, cnlNums[i]); } // создание и заполнение среза, содержащего заданные каналы SrezTableLight.Srez destSrez = new SrezTableLight.Srez(srcSrez.DateTime, cnlNumsLen); for (int i = 0; i < cnlNumsLen; i++) { destSrez.CnlNums[i] = cnlNums[i]; int cnlNumInd = cnlNumIndexes[i]; destSrez.CnlData[i] = cnlNumInd < 0 ? SrezTableLight.CnlData.Empty : srcSrez.CnlData[cnlNumInd]; } destSrezTable.SrezList.Add(destSrez.DateTime, destSrez); prevSrezDescr = srcSrez.SrezDescr; } } } else { destSrezTable = null; } return destSrezTable; } catch (Exception ex) { AppLog.WriteAction((Localization.UseRussian ? "Ошибка при получении таблицы срезов: " : "Error getting snapshot table: ") + ex.Message, Log.ActTypes.Exception); return null; } }
private void btnSendSrez_Click(object sender, EventArgs e) { // отправка среза SCADA-Серверу int cnlNum; if (!int.TryParse(cbSrezCnlNum.Text, out cnlNum)) { ScadaUtils.ShowError(AppPhrases.IncorrectCnlNum); return; } double cnlVal = ScadaUtils.StrToDouble(txtSrezCnlVal.Text); if (double.IsNaN(cnlVal)) { ScadaUtils.ShowError(AppPhrases.IncorrectCnlVal); return; } DateTime srezDT = rbCurSrez.Checked ? DateTime.MinValue : dtpSrezDate.Value.Date.Add(dtpSrezTime.Value.TimeOfDay); SrezTableLight.Srez srez = new SrezTableLight.Srez(srezDT, 1); srez.CnlNums[0] = cnlNum; srez.CnlData[0] = new SrezTableLight.CnlData(cnlVal, decimal.ToInt32(numSrezCnlStat.Value)); bool result; bool sendOk = rbCurSrez.Checked ? ServerComm.SendSrez(srez, out result) : ServerComm.SendArchive(srez, out result); if (sendOk) { string cnlNumStr = cbSrezCnlNum.Text.Trim(); cbSrezCnlNum.Items.Remove(cnlNumStr); cbSrezCnlNum.Items.Insert(0, cnlNumStr); cbSrezCnlNum.Text = cnlNumStr; ScadaUtils.ShowInfo(AppPhrases.SendDataCompleted); } else { ScadaUtils.ShowError(ServerComm.ErrMsg); } }
/// <summary> /// Обработать полученную команду /// </summary> private void ProcCommand(ClientInfo client, byte cmd, int cmdLen) { bool sendResp = true; // отправить ответ на команду int respDataLen = 0; // длина данных ответа на команду byte[] extraData = null; // дополнительные данные ответа switch (cmd) { case 0x01: // проверка имени и пароля int userNameLen = inBuf[3]; string userName = Encoding.Default.GetString(inBuf, 4, userNameLen); string password = Encoding.Default.GetString(inBuf, 5 + userNameLen, inBuf[4 + userNameLen]); bool pwdIsEmpty = string.IsNullOrEmpty(password); int roleID; bool checkOk = CheckUser(userName, password, out roleID); if (client.Authenticated) { if (pwdIsEmpty) { string checkOkStr = checkOk ? (Localization.UseRussian ? "успешно" : "success") : (Localization.UseRussian ? "ошибка" : "error"); appLog.WriteAction(string.Format(Localization.UseRussian ? "Получение роли пользователя {0}. Результат: {1}" : "Get user {0} role. Result: {1}", userName, checkOkStr), Log.ActTypes.Action); } else { string checkOkStr = checkOk ? (Localization.UseRussian ? "верно" : "passed") : (Localization.UseRussian ? "неверно" : "failed"); appLog.WriteAction(string.Format(Localization.UseRussian ? "Проверка имени и пароля пользователя {0}. Результат: {1}" : "Check user {0} name and password. Result: {1}", userName, checkOkStr), Log.ActTypes.Action); } } else { if (checkOk && roleID != BaseValues.Roles.Disabled && !pwdIsEmpty) { client.Authenticated = true; client.UserName = userName; client.UserRoleID = roleID; appLog.WriteAction(string.Format(Localization.UseRussian ? "Пользователь {0} успешно аутентифицирован" : "The user {0} is successfully authenticated", userName), Log.ActTypes.Action); } else { client.ActivityDT = DateTime.MinValue; // для отключения клиента после отправки ответа appLog.WriteAction(string.Format(Localization.UseRussian ? "Неудачная попытка аутентификации пользователя {0}" : "Unsuccessful attempt to authenticate the user {0}", userName), Log.ActTypes.Action); } } respDataLen = 1; outBuf[3] = (byte)roleID; break; case 0x02: // запрос состояния сервера (ping) respDataLen = 1; outBuf[3] = mainLogic.ServerIsReady ? (byte)1 : (byte)0; break; case 0x03: // запись текущего среза if (client.UserRoleID == BaseValues.Roles.App) { int cnlCnt = BitConverter.ToUInt16(inBuf, 3); SrezTableLight.Srez srez = new SrezTableLight.Srez(DateTime.MinValue, cnlCnt); for (int i = 0, j = 5; i < cnlCnt; i++, j += 14) { srez.CnlNums[i] = (int)BitConverter.ToUInt32(inBuf, j); srez.CnlData[i] = new SrezTableLight.CnlData( BitConverter.ToDouble(inBuf, j + 4), BitConverter.ToUInt16(inBuf, j + 12)); } outBuf[3] = mainLogic.ProcCurData(srez) ? (byte)1 : (byte)0; } else { outBuf[3] = 0; } respDataLen = 1; break; case 0x04: // запись архивного среза if (client.UserRoleID == BaseValues.Roles.App) { DateTime dateTime = Arithmetic.DecodeDateTime(BitConverter.ToDouble(inBuf, 3)); int cnlCnt = BitConverter.ToUInt16(inBuf, 11); SrezTableLight.Srez srez = new SrezTableLight.Srez(dateTime, cnlCnt); for (int i = 0, j = 13; i < cnlCnt; i++, j += 14) { srez.CnlNums[i] = (int)BitConverter.ToUInt32(inBuf, j); srez.CnlData[i] = new SrezTableLight.CnlData( BitConverter.ToDouble(inBuf, j + 4), BitConverter.ToUInt16(inBuf, j + 12)); } outBuf[3] = mainLogic.ProcArcData(srez) ? (byte)1 : (byte)0; } else { outBuf[3] = 0; } respDataLen = 1; break; case 0x05: // запись события if (client.UserRoleID == BaseValues.Roles.App) { EventTableLight.Event ev = new EventTableLight.Event(); ev.DateTime = Arithmetic.DecodeDateTime(BitConverter.ToDouble(inBuf, 3)); ev.ObjNum = BitConverter.ToUInt16(inBuf, 11); ev.KPNum = BitConverter.ToUInt16(inBuf, 13); ev.ParamID = BitConverter.ToUInt16(inBuf, 15); ev.CnlNum = (int)BitConverter.ToUInt32(inBuf, 17); ev.OldCnlVal = BitConverter.ToDouble(inBuf, 21); ev.OldCnlStat = BitConverter.ToUInt16(inBuf, 29); ev.NewCnlVal = BitConverter.ToDouble(inBuf, 31); ev.NewCnlStat = BitConverter.ToUInt16(inBuf, 39); ev.Checked = BitConverter.ToBoolean(inBuf, 41); ev.UserID = BitConverter.ToUInt16(inBuf, 42); int evDescrLen = inBuf[44]; int evDataLen = inBuf[45 + evDescrLen]; ev.Descr = Encoding.Default.GetString(inBuf, 45, evDescrLen); ev.Data = Encoding.Default.GetString(inBuf, 46 + evDescrLen, evDataLen); outBuf[3] = mainLogic.ProcEvent(ev) ? (byte)1 : (byte)0; } else { outBuf[3] = 0; } respDataLen = 1; break; case 0x06: // команда ТУ bool cmdProcOk = false; // команда обработана успешно if (client.UserRoleID == BaseValues.Roles.Admin || client.UserRoleID == BaseValues.Roles.Dispatcher || client.UserRoleID == BaseValues.Roles.App) { int cmdUserID = BitConverter.ToUInt16(inBuf, 3); byte cmdTypeID = inBuf[5]; int ctrlCnlNum = BitConverter.ToUInt16(inBuf, 6); MainLogic.CtrlCnl ctrlCnl = mainLogic.GetCtrlCnl(ctrlCnlNum); string notFoundStr = ctrlCnl == null ? Localization.UseRussian ? " (не найден)" : " (not found)" : ""; appLog.WriteAction(string.Format(Localization.UseRussian ? "Команда ТУ: канал упр. = {0}{1}, ид. польз. = {2}" : "Command: out channel = {0}{1}, user ID = {2}", ctrlCnlNum, notFoundStr, cmdUserID), Log.ActTypes.Action); if (ctrlCnl != null) { // создание команды ТУ ModLogic.Command ctrlCmd = new ModLogic.Command(cmdTypeID); ctrlCmd.CmdData = new byte[BitConverter.ToUInt16(inBuf, 8)]; Array.Copy(inBuf, 10, ctrlCmd.CmdData, 0, ctrlCmd.CmdData.Length); if (cmdTypeID == BaseValues.CmdTypes.Standard || cmdTypeID == BaseValues.CmdTypes.Binary) { ctrlCmd.KPNum = (ushort)ctrlCnl.KPNum; ctrlCmd.CmdNum = (ushort)ctrlCnl.CmdNum; if (cmdTypeID == BaseValues.CmdTypes.Standard && ctrlCmd.CmdData.Length == 8) ctrlCmd.CmdVal = BitConverter.ToDouble(ctrlCmd.CmdData, 0); } else if (cmdTypeID == BaseValues.CmdTypes.Request) { ctrlCmd.KPNum = BitConverter.ToUInt16(inBuf, 10); } // обработка команды ТУ bool passToClients; mainLogic.ProcCommand(ctrlCnl, ctrlCmd, cmdUserID, out passToClients); // передача команды ТУ подключенным клиентам if (passToClients) { foreach (ClientInfo cl in clients) if (cl.UserRoleID == BaseValues.Roles.App) cl.CmdList.Add(ctrlCmd); } else { appLog.WriteAction(Localization.UseRussian ? "Команда ТУ отменена" : "Command is canceled", Log.ActTypes.Action); } cmdProcOk = true; } } respDataLen = 1; outBuf[3] = cmdProcOk ? (byte)1 : (byte)0; break; case 0x07: // запрос команды ТУ if (client.UserRoleID == BaseValues.Roles.App && client.CmdList.Count > 0) { ModLogic.Command ctrlCmd = client.CmdList[0]; int cmdDataLen = ctrlCmd.CmdData == null ? 0 : ctrlCmd.CmdData.Length; respDataLen = 7 + cmdDataLen; outBuf[3] = (byte)(cmdDataLen % 256); outBuf[4] = (byte)(cmdDataLen / 256); outBuf[5] = (byte)ctrlCmd.CmdTypeID; outBuf[6] = (byte)(ctrlCmd.KPNum % 256); outBuf[7] = (byte)(ctrlCmd.KPNum / 256); outBuf[8] = (byte)(ctrlCmd.CmdNum % 256); outBuf[9] = (byte)(ctrlCmd.CmdNum / 256); if (cmdDataLen > 0) Array.Copy(ctrlCmd.CmdData, 0, outBuf, 10, cmdDataLen); // удаление команды ТУ из списка команд клиента client.CmdList.RemoveAt(0); } else { respDataLen = 2; outBuf[3] = 0; outBuf[4] = 0; } break; case 0x08: // открытие и чтение из файла int readCnt = 0; bool readOk = false; if (client.Authenticated) { client.CloseFile(); try { client.Dir = (Dirs)inBuf[3]; } catch { client.Dir = Dirs.Cur; } int fileNameLen = inBuf[4]; client.FileName = Encoding.Default.GetString(inBuf, 5, fileNameLen); string fullFileName = GetFullFileName(client.Dir, client.FileName); int count = BitConverter.ToUInt16(inBuf, 5 + fileNameLen); if (settings.DetailedLog) appLog.WriteAction(string.Format(Localization.UseRussian ? "Открытие файла {0}" : "Opening file {0}", fullFileName), Log.ActTypes.Action); try { if (File.Exists(fullFileName)) { client.FileStream = new FileStream(fullFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); readCnt = client.FileStream.Read(outBuf, 6, count); readOk = true; } else { appLog.WriteAction(string.Format(Localization.UseRussian ? "Файл {0} не найден." : "File {0} not found.", client.FullFileNameInfo), Log.ActTypes.Error); } } catch (Exception ex) { appLog.WriteAction(string.Format(Localization.UseRussian ? "Ошибка при работе с файлом {0}: {1}" : "Error working with the file {0}: {1}", client.FullFileNameInfo, ex.Message), Log.ActTypes.Exception); } finally { if (readCnt < count) client.CloseFile(); } } respDataLen = 3 + readCnt; outBuf[3] = readOk ? (byte)1 : (byte)0; outBuf[4] = (byte)(readCnt % 256); outBuf[5] = (byte)(readCnt / 256); break; case 0x09: // перемещение позиции чтения из файла long pos = 0; bool seekOk = false; if (client.Authenticated && client.FileStream != null) { SeekOrigin origin; try { origin = (SeekOrigin)inBuf[3]; } catch { origin = SeekOrigin.Begin; } long offset = BitConverter.ToUInt32(inBuf, 4); try { pos = client.FileStream.Seek(offset, origin); seekOk = true; } catch (Exception ex) { appLog.WriteAction("Ошибка при работе с файлом " + client.FullFileNameInfo + ": " + ex.Message, Log.ActTypes.Exception); } } respDataLen = 5; outBuf[3] = seekOk ? (byte)1 : (byte)0; Array.Copy(BitConverter.GetBytes((uint)pos), 0, outBuf, 4, 4); break; case 0x0A: // чтение из файла readCnt = 0; if (client.Authenticated && client.FileStream != null) { int count = BitConverter.ToUInt16(inBuf, 3); try { readCnt = client.FileStream.Read(outBuf, 5, count); } catch (Exception ex) { appLog.WriteAction(string.Format(Localization.UseRussian ? "Ошибка при работе с файлом {0}: {1}" : "Error working with the file {0}: {1}", client.FullFileNameInfo, ex.Message), Log.ActTypes.Exception); } finally { if (readCnt < count) client.CloseFile(); } } respDataLen = 2 + readCnt; outBuf[3] = (byte)(readCnt % 256); outBuf[4] = (byte)(readCnt / 256); break; case 0x0B: // закрытие файла if (client.Authenticated && client.FileStream != null) { client.CloseFile(); outBuf[3] = 1; } else { outBuf[3] = 0; } respDataLen = 1; break; case 0x0C: // запрос времени изменения файлов int fileCnt = inBuf[3]; outBuf[3] = inBuf[3]; for (int i = 0, j = 4, k = 4; i < fileCnt; i++, k += 8) { Dirs dir; try { dir = (Dirs)inBuf[j++]; } catch { dir = Dirs.Cur; } int fileNameLen = inBuf[j++]; string fileName = Encoding.Default.GetString(inBuf, j, fileNameLen); string fullFileName = GetFullFileName(dir, fileName); j += fileNameLen; if (settings.DetailedLog) appLog.WriteAction(string.Format(Localization.UseRussian ? "Получение времени изменения файла {0}" : "Obtaining the modification time of the file {0}", fullFileName), Log.ActTypes.Action); double fileModTime; try { fileModTime = File.Exists(fullFileName) ? Arithmetic.EncodeDateTime(File.GetLastWriteTime(fullFileName)) : 0; } catch { fileModTime = 0; } Array.Copy(BitConverter.GetBytes(fileModTime), 0, outBuf, k, 8); } respDataLen = 1 + 8 * fileCnt; break; case 0x0D: // запрос данных из таблицы среза byte srezTypeNum = inBuf[3]; MainLogic.SrezTypes srezType; DateTime srezDate; if (srezTypeNum == 0x01) { srezType = MainLogic.SrezTypes.Cur; srezDate = DateTime.MinValue; } else { srezType = srezTypeNum == 0x02 ? MainLogic.SrezTypes.Hour : MainLogic.SrezTypes.Min; srezDate = new DateTime(inBuf[4] + 2000, inBuf[5], inBuf[6]); } int cnlNumCnt = BitConverter.ToUInt16(inBuf, 7); int[] cnlNums = new int[cnlNumCnt]; for (int i = 0, j = 9; i < cnlNumCnt; i++, j += 4) cnlNums[i] = (int)BitConverter.ToUInt32(inBuf, j); if (settings.DetailedLog) { string srezTypeStr; if (srezType == MainLogic.SrezTypes.Cur) srezTypeStr = Localization.UseRussian ? "текущие" : "current"; else if (srezType == MainLogic.SrezTypes.Min) srezTypeStr = Localization.UseRussian ? "минутные" : "minute"; else srezTypeStr = Localization.UseRussian ? "часовые" : "hourly"; appLog.WriteAction(string.Format(Localization.UseRussian ? "Запрос данных. Тип: {0}. Дата: {1}. Каналы: {2}" : "Data request. Type: {0}. Date: {1}. Channels: {2}", srezTypeStr, srezDate.ToString("d", Localization.Culture), string.Join(", ", cnlNums)), Log.ActTypes.Action); } SrezTableLight srezTable = mainLogic.GetSrezTable(srezDate, srezType, cnlNums); int srezCnt = srezTable == null ? 0 : srezTable.SrezList.Count; outBuf[5] = (byte)(srezCnt % 256); outBuf[6] = (byte)(srezCnt / 256); extraData = new byte[srezCnt * (10 * cnlNumCnt + 8)]; for (int i = 0, j = 0; i < srezCnt; i++) { SrezTableLight.Srez srez = srezTable.SrezList.Values[i]; Array.Copy(BitConverter.GetBytes(Arithmetic.EncodeDateTime(srez.DateTime)), 0, extraData, j, 8); j += 8; for (int k = 0; k < cnlNumCnt; k++) { SrezTable.CnlData cnlData = srez.CnlData[k]; Array.Copy(BitConverter.GetBytes(cnlData.Val), 0, extraData, j, 8); j += 8; extraData[j++] = (byte)(cnlData.Stat % 256); extraData[j++] = (byte)(cnlData.Stat / 256); } } respDataLen = 2 + extraData.Length; break; case 0x0E: // квитирование события if (client.Authenticated) { int evUserID = BitConverter.ToUInt16(inBuf, 3); DateTime evDate = new DateTime(inBuf[5] + 2000, inBuf[6], inBuf[7]); int evNum = BitConverter.ToUInt16(inBuf, 8); outBuf[3] = mainLogic.CheckEvent(evDate, evNum, evUserID) ? (byte)1 : (byte)0; } else { outBuf[3] = 0; } respDataLen = 1; break; } // передача ответа на команду if (sendResp) { if (cmd == 0x0D) { int respLen = 5 + respDataLen; Array.Copy(BitConverter.GetBytes((uint)respLen), 0, outBuf, 0, 4); outBuf[4] = cmd; client.NetStream.Write(outBuf, 0, 7); } else { int respLen = 3 + respDataLen; Array.Copy(BitConverter.GetBytes((ushort)respLen), 0, outBuf, 0, 2); outBuf[2] = cmd; client.NetStream.Write(outBuf, 0, respLen); } if (extraData != null && extraData.Length > 0) client.NetStream.Write(extraData, 0, extraData.Length); } }
/// <summary> /// Преобразовать среза параметров в срез входных каналов /// </summary> private SrezTableLight.Srez ConvertSrez(KPLogic.ParamSrez paramSrez) { List<int> bindedIndexes; int cnlCnt; if (paramSrez == null) { bindedIndexes = null; cnlCnt = 0; } else { bindedIndexes = paramSrez.GetBindedParamIndexes(); cnlCnt = bindedIndexes.Count; } if (cnlCnt == 0) { return null; } else { SrezTableLight.Srez srez = new SrezTableLight.Srez(paramSrez.DateTime, cnlCnt); for (int i = 0; i < cnlCnt; i++) { int paramInd = bindedIndexes[i]; srez.CnlNums[i] = paramSrez.KPParams[paramInd].CnlNum; KPLogic.ParamData paramData = paramSrez.Data[paramInd]; SrezTableLight.CnlData cnlData = new SrezTableLight.CnlData(paramData.Val, paramData.Stat); srez.CnlData[i] = cnlData; } return srez; } }
/// <summary> /// Заполнить объект dest из файла срезов FileName /// </summary> protected void FillObj(object dest) { Stream stream = null; BinaryReader reader = null; DateTime fillTime = DateTime.Now; SrezTableLight srezTableLight = dest as SrezTableLight; DataTable dataTable = dest as DataTable; Trend trend = dest as Trend; SrezTable srezTable = srezTableLight as SrezTable; SrezTableLight.Srez lastStoredSrez = null; try { if (srezTableLight == null && dataTable == null && trend == null) throw new Exception("Destination object is invalid."); // подготовка объекта для хранения данных if (srezTableLight != null) { srezTableLight.Clear(); srezTableLight.TableName = tableName; if (srezTable != null) srezTable.BeginLoadData(); } else if (dataTable != null) { // формирование структуры таблицы dataTable.BeginLoadData(); dataTable.DefaultView.Sort = ""; if (dataTable.Columns.Count == 0) { dataTable.Columns.Add("DateTime", typeof(DateTime)); dataTable.Columns.Add("CnlNum", typeof(int)); dataTable.Columns.Add("Val", typeof(double)); dataTable.Columns.Add("Stat", typeof(int)); dataTable.DefaultView.AllowNew = false; dataTable.DefaultView.AllowEdit = false; dataTable.DefaultView.AllowDelete = false; } else { dataTable.Rows.Clear(); } } else // trend != null { trend.Clear(); trend.TableName = tableName; } // заполнение объекта данными stream = ioStream == null ? new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite) : ioStream; reader = new BinaryReader(stream); DateTime date = Arithmetic.ExtractDate(tableName); // определение даты срезов SrezTable.SrezDescr srezDescr = null; // описание среза int[] cnlNums = null; // ссылка на номера входных каналов из описания среза while (stream.Position < stream.Length) { // считывание списка номеров каналов и КС int cnlNumCnt = reader.ReadUInt16(); if (cnlNumCnt > 0) { // загрузка номеров каналов в буфер для увеличения скорости работы int cnlNumSize = cnlNumCnt * 2; byte[] buf = new byte[cnlNumSize]; int readSize = reader.Read(buf, 0, cnlNumSize); // создание описания среза и заполнение номеров каналов из буфера // с проверкой их уникальности и упорядоченности if (readSize == cnlNumSize) { int prevCnlNum = -1; srezDescr = new SrezTable.SrezDescr(cnlNumCnt); cnlNums = srezDescr.CnlNums; for (int i = 0; i < cnlNumCnt; i++) { int cnlNum = BitConverter.ToUInt16(buf, i * 2); if (prevCnlNum >= cnlNum) throw new Exception("Table is incorrect."); cnlNums[i] = prevCnlNum = cnlNum; } srezDescr.CalcCS(); } } else if (srezDescr == null) { throw new Exception("Table is incorrect."); } // считывание и проверка КС ushort cs = reader.ReadUInt16(); bool csOk = cnlNumCnt > 0 ? srezDescr.CS == cs : cs == 1; // считывание данных среза int cnlCnt = cnlNums.Length; // количество каналов в срезе int srezDataSize = cnlCnt * 9; // размер данных среза if (csOk) { long srezPos = stream.Position; double time = reader.ReadDouble(); int hour, min, sec; Arithmetic.DecodeTime(time, out hour, out min, out sec); DateTime srezDT = new DateTime(date.Year, date.Month, date.Day, hour, min, sec); // инициализация нового среза SrezTableLight.Srez srez; if (srezTable != null) { srez = new SrezTable.Srez(srezDT, srezDescr) { State = DataRowState.Unchanged, Position = srezPos }; } else if (srezTableLight != null) { srez = new SrezTableLight.Srez(srezDT, cnlCnt); cnlNums.CopyTo(srez.CnlNums, 0); } else // srezTableLight == null { srez = null; } // считывание данных входных каналов int bufInd = 0; double val; byte stat; if (trend != null) { // выбор данных требуемого канала для тренда int index = Array.BinarySearch<int>(cnlNums, trend.CnlNum); if (index >= 0) { stream.Seek(index * 9, SeekOrigin.Current); byte[] buf = new byte[9]; int readSize = reader.Read(buf, 0, 9); if (readSize == 9) { ExtractCnlData(buf, ref bufInd, out val, out stat); Trend.Point point = new Trend.Point(srezDT, val, stat); trend.Points.Add(point); stream.Seek(srezDataSize - (index + 1) * 9, SeekOrigin.Current); } } else { stream.Seek(srezDataSize, SeekOrigin.Current); } } else { // загрузка данных среза в буфер для увеличения скорости работы byte[] buf = new byte[srezDataSize]; int readSize = reader.Read(buf, 0, srezDataSize); // заполение таблицы срезов из буфера if (srezTableLight != null) { for (int i = 0; i < cnlCnt; i++) { ExtractCnlData(buf, ref bufInd, out val, out stat); srez.CnlNums[i] = cnlNums[i]; srez.CnlData[i].Val = val; srez.CnlData[i].Stat = stat; if (bufInd >= readSize) break; } srezTableLight.AddSrez(srez); lastStoredSrez = srez; } else // dataTable != null { for (int i = 0; i < cnlCnt; i++) { ExtractCnlData(buf, ref bufInd, out val, out stat); DataRow row = dataTable.NewRow(); row["DateTime"] = srezDT; row["CnlNum"] = cnlNums[i]; row["Val"] = val; row["Stat"] = stat; dataTable.Rows.Add(row); if (bufInd >= readSize) break; } } } } else { // пропустить срез, считая его размер так, как при повторяющемся списке номеров каналов stream.Seek(srezDataSize + 8, SeekOrigin.Current); } } } catch (EndOfStreamException) { // нормальная ситуация окончания файла } catch { fillTime = DateTime.MinValue; throw; } finally { if (fileMode) { if (reader != null) reader.Close(); if (stream != null) stream.Close(); } if (srezTableLight != null) { srezTableLight.LastFillTime = fillTime; if (srezTable != null) { srezTable.LastStoredSrez = (SrezTable.Srez)lastStoredSrez; srezTable.EndLoadData(); } } else if (dataTable != null) { dataTable.EndLoadData(); dataTable.AcceptChanges(); dataTable.DefaultView.Sort = "DateTime, CnlNum"; } else if (trend != null) { trend.LastFillTime = fillTime; trend.Sort(); } } }
/// <summary> /// Выполнить действия после обработки новых архивных данных /// </summary> /// <remarks> /// Номера каналов упорядочены по возрастанию. /// Вычисление дорасчётных каналов архивного среза в момент вызова метода завершено. /// Параметр arcSrez равен null, если запись архивных срезов отключена /// </remarks> public virtual void OnArcDataProcessed(int[] cnlNums, SrezTableLight.Srez arcSrez) { }
/// <summary> /// Выполнить действия после вычисления дорасчётных каналов текущего среза /// </summary> /// <remarks>Номера каналов упорядочены по возрастанию</remarks> public virtual void OnCurDataCalculated(int[] cnlNums, SrezTableLight.Srez curSrez) { }
/// <summary> /// Выполнить действия после обработки новых текущих данных /// </summary> /// <remarks>Номера каналов упорядочены по возрастанию. /// Вычисление дорасчётных каналов текущего среза в момент вызова метода не выполнено</remarks> public virtual void OnCurDataProcessed(int[] cnlNums, SrezTableLight.Srez curSrez) { }
/// <summary> /// Exports the specified snapshot. /// </summary> private bool ExportSnapshot(SrezTableLight.Srez snapshot, DbTransaction trans, IEnumerable <DataTrigger> dataTriggers) { Trigger currentTrigger = null; try { int firstCnlNum = snapshot.CnlNums.Length > 0 ? snapshot.CnlNums[0] : 0; entityMap.DeviceByCnlNum.TryGetValue(firstCnlNum, out int deviceNum); foreach (DataTrigger trigger in dataTriggers) { currentTrigger = trigger; if ((trigger.CnlNums.Count == 0 || trigger.CnlNums.Overlaps(snapshot.CnlNums)) && (trigger.DeviceNums.Count == 0 || trigger.DeviceNums.Contains(deviceNum))) { DbCommand cmd = trigger.Command; cmd.Transaction = trans; trigger.DateTimeParam.Value = snapshot.DateTime; trigger.KpNumParam.Value = deviceNum; if (trigger.DataTriggerOptions.SingleQuery) { if (trigger.CnlNums.Count > 0) { foreach (int cnlNum in trigger.CnlNums) { SrezTableLight.CnlData cnlData = snapshot.GetCnlData(cnlNum); trigger.SetValParam(cnlNum, cnlData.Val); trigger.SetStatParam(cnlNum, cnlData.Stat); } cmd.ExecuteNonQuery(); } } else { void ExportDataPoint(int cnlNum) { SrezTableLight.CnlData cnlData = snapshot.GetCnlData(cnlNum); trigger.CnlNumParam.Value = cnlNum; trigger.ValParam.Value = cnlData.Val; trigger.StatParam.Value = cnlData.Stat; cmd.ExecuteNonQuery(); } if (trigger.CnlNums.Count > 0) { foreach (int cnlNum in snapshot.CnlNums) { if (trigger.CnlNums.Contains(cnlNum)) { ExportDataPoint(cnlNum); } } } else { foreach (int cnlNum in snapshot.CnlNums) { ExportDataPoint(cnlNum); } } } } } return(true); } catch (Exception ex) { log.WriteException(ex, Localization.UseRussian ? "Ошибка при экспорте среза по триггеру \"{0}\"" : "Error export snapshot by the trigger \"{0}\"", currentTrigger?.Options?.Name ?? ""); return(false); } }
/// <summary> /// Вычислить дорасчётные каналы /// </summary> private void CalcDRCnls(List<InCnl> inCnls, SrezTableLight.Srez srez, bool genEvents) { lock (calculator) { try { procSrez = srez; foreach (InCnl inCnl in inCnls) { int cnlInd = srez.GetCnlIndex(inCnl.CnlNum); if (cnlInd >= 0) { // вычисление новых данных входного канала SrezTableLight.CnlData oldCnlData = srez.CnlData[cnlInd]; SrezTableLight.CnlData newCnlData = new SrezTableLight.CnlData(oldCnlData.Val, BaseValues.CnlStatuses.Defined); CalcCnlData(inCnl, oldCnlData, ref newCnlData); // запись новых данных в срез srez.CnlData[cnlInd] = newCnlData; // генерация события if (genEvents) GenEvent(inCnl, oldCnlData, newCnlData); } } } catch (Exception ex) { AppLog.WriteAction((Localization.UseRussian ? "Ошибка при вычислении дорасчётных каналов: " : "Error calculating channels: ") + ex.Message, Log.ActTypes.Exception); } finally { procSrez = null; } } }
/// <summary> /// Обработать новые текущие данные /// </summary> public bool ProcCurData(SrezTableLight.Srez receivedSrez) { lock (curSrez) lock (calculator) { try { if (serverIsReady) { procSrez = curSrez; int cnlCnt = receivedSrez == null ? 0 : receivedSrez.CnlNums.Length; for (int i = 0; i < cnlCnt; i++) { int cnlNum = receivedSrez.CnlNums[i]; int cnlInd = curSrez.GetCnlIndex(cnlNum); InCnl inCnl; if (inCnls.TryGetValue(cnlNum, out inCnl) && cnlInd >= 0) // входной канал существует { if (inCnl.CnlTypeID == BaseValues.CnlTypes.TS || inCnl.CnlTypeID == BaseValues.CnlTypes.TI) { // вычисление новых данных входного канала SrezTableLight.CnlData oldCnlData = curSrez.CnlData[cnlInd]; SrezTableLight.CnlData newCnlData = receivedSrez.CnlData[i]; CalcCnlData(inCnl, oldCnlData, ref newCnlData); // расчёт данных для усреднения if (inCnl.Averaging && newCnlData.Stat > BaseValues.CnlStatuses.Undefined && newCnlData.Stat != BaseValues.CnlStatuses.FormulaError && newCnlData.Stat != BaseValues.CnlStatuses.Unreliable) { minAvgData[cnlInd].Sum += newCnlData.Val; minAvgData[cnlInd].Cnt++; hrAvgData[cnlInd].Sum += newCnlData.Val; hrAvgData[cnlInd].Cnt++; } // запись новых данных в текущий срез curSrez.CnlData[cnlInd] = newCnlData; // генерация события GenEvent(inCnl, oldCnlData, newCnlData); // обновление информации об активности канала activeDTs[cnlInd] = DateTime.Now; } else if (inCnl.CnlTypeID != BaseValues.CnlTypes.TSDR && inCnl.CnlTypeID != BaseValues.CnlTypes.TIDR) { // запись новых данных минутных и часовых каналов, а также // количества переключений в текущий срез без вычислений curSrez.CnlData[cnlInd] = receivedSrez.CnlData[i]; } } } // выполнение действий модулей if (cnlCnt > 0) RaiseOnCurDataProcessed(receivedSrez.CnlNums, curSrez); return true; } else { return false; } } catch (Exception ex) { AppLog.WriteAction((Localization.UseRussian ? "Ошибка при обработке новых текущих данных: " : "Error processing the new current data: ") + ex.Message, Log.ActTypes.Exception); return false; } finally { procSrez = null; curSrezMod = true; } } }
/// <summary> /// Обработать команду ТУ /// </summary> public void ProcCommand(CtrlCnl ctrlCnl, Command cmd, int userID, out bool passToClients) { passToClients = false; if (serverIsReady && ctrlCnl != null) { int ctrlCnlNum = ctrlCnl.CtrlCnlNum; // вычисление значения или данных команды по формуле канала управления if (ctrlCnl.CalcCmdVal != null) { // вычисление значения стандартной команды lock (curSrez) lock (calculator) { try { procSrez = curSrez; // необходимо для работы формул Val(n) и Stat(n) double cmdVal = cmd.CmdVal; ctrlCnl.CalcCmdVal(ref cmdVal); cmd.CmdVal = cmdVal; passToClients = !double.IsNaN(cmdVal); } catch (Exception ex) { AppLog.WriteAction(string.Format(Localization.UseRussian ? "Ошибка при вычислении значения стандартной команды для канала управления {0}: {1}" : "Error calculating standard command value for the output channel {0}: {1}", ctrlCnlNum, ex.Message), Log.ActTypes.Error); cmd.CmdVal = double.NaN; } finally { procSrez = null; } } } else if (ctrlCnl.CalcCmdData != null) { // вычисление данных бинарной команды lock (curSrez) lock (calculator) { try { procSrez = curSrez; byte[] cmdData = cmd.CmdData; ctrlCnl.CalcCmdData(ref cmdData); cmd.CmdData = cmdData; passToClients = cmdData != null; } catch (Exception ex) { AppLog.WriteAction(string.Format(Localization.UseRussian ? "Ошибка при вычислении данных бинарной команды для канала управления {0}: {1}" : "Error calculating binary command data for the output channel {0}: {1}", ctrlCnlNum, ex.Message), Log.ActTypes.Error); cmd.CmdVal = double.NaN; } finally { procSrez = null; } } } else { passToClients = true; } // выполнение действий модулей после приёма команды RaiseOnCommandReceived(ctrlCnlNum, cmd, userID, ref passToClients); // создание события if (passToClients && ctrlCnl.EvEnabled) { EventTableLight.Event ev = new EventTableLight.Event(); ev.DateTime = DateTime.Now; ev.ObjNum = ctrlCnl.ObjNum; ev.KPNum = ctrlCnl.KPNum; ev.Descr = cmd.GetCmdDescr(ctrlCnlNum, userID); // запись события и выполнение действий модулей WriteEvent(ev); } } }
public override void OnArcDataProcessed(int[] cnlNums, SrezTableLight.Srez arcSrez) { // the method executes when new archive data have been processed by the server WriteToLog("Process archive data by the module " + Name, Log.ActTypes.Action); }
/// <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 SrezTableLight.Srez CreateSrez(DateTime srezDT, int[] cnlNums, SrezTableLight.Srez sourceSrez) { int cnlCnt = cnlNums.Length; SrezTableLight.Srez srez = new SrezTableLight.Srez(srezDT, cnlCnt); for (int i = 0; i < cnlCnt; i++) { int cnlNum = cnlNums[i]; SrezTableLight.CnlData cnlData; sourceSrez.GetCnlData(cnlNum, out cnlData); srez.CnlNums[i] = cnlNum; srez.CnlData[i] = cnlData; } return srez; }