/// <summary> /// Создать данные события на основе строки таблицы /// </summary> protected EventTableLight.Event CreateEvent(DataRowView rowView) { EventTableLight.Event ev = new EventTableLight.Event(); ev.Number = ConvertToInt(rowView["Number"]); ev.DateTime = ConvertToDateTime(rowView["DateTime"]); ev.ObjNum = ConvertToInt(rowView["ObjNum"]); ev.KPNum = ConvertToInt(rowView["KPNum"]); ev.ParamID = ConvertToInt(rowView["ParamID"]); ev.CnlNum = ConvertToInt(rowView["CnlNum"]); ev.OldCnlVal = ConvertToDouble(rowView["OldCnlVal"]); ev.OldCnlStat = ConvertToInt(rowView["OldCnlStat"]); ev.NewCnlVal = ConvertToDouble(rowView["NewCnlVal"]); ev.NewCnlStat = ConvertToInt(rowView["NewCnlStat"]); ev.Checked = ConvertToBoolean(rowView["Checked"]); ev.UserID = ConvertToInt(rowView["UserID"]); ev.Descr = Convert.ToString(rowView["Descr"]); ev.Data = Convert.ToString(rowView["Data"]); return(ev); }
/// <summary> /// Добавить событие в файл или поток /// </summary> public void AppendEvent(EventTableLight.Event ev) { if (ev == null) { throw new ArgumentNullException("ev"); } Stream stream = null; BinaryWriter writer = null; try { stream = ioStream == null ? new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite) : ioStream; writer = new BinaryWriter(stream); // установка позиции записи кратной размеру данных события stream.Seek(0, SeekOrigin.End); long offset = stream.Position / EventDataSize * EventDataSize; stream.Seek(offset, SeekOrigin.Begin); // запись события writer.Write(CreateEventBuffer(ev)); } finally { if (fileMode) { if (writer != null) { writer.Close(); } if (stream != null) { stream.Close(); } } } }
/// <summary> /// Создать буфер для записи события /// </summary> protected byte[] CreateEventBuffer(EventTableLight.Event ev) { byte[] evBuf = new byte[EventDataSize]; Array.Copy(BitConverter.GetBytes(Arithmetic.EncodeDateTime(ev.DateTime)), 0, evBuf, 0, 8); evBuf[8] = (byte)(ev.ObjNum % 256); evBuf[9] = (byte)(ev.ObjNum / 256); evBuf[10] = (byte)(ev.KPNum % 256); evBuf[11] = (byte)(ev.KPNum / 256); evBuf[12] = (byte)(ev.ParamID % 256); evBuf[13] = (byte)(ev.ParamID / 256); evBuf[14] = (byte)(ev.CnlNum % 256); evBuf[15] = (byte)(ev.CnlNum / 256); Array.Copy(BitConverter.GetBytes(ev.OldCnlVal), 0, evBuf, 16, 8); evBuf[24] = (byte)ev.OldCnlStat; Array.Copy(BitConverter.GetBytes(ev.NewCnlVal), 0, evBuf, 25, 8); evBuf[33] = (byte)ev.NewCnlStat; evBuf[34] = ev.Checked ? (byte)1 : (byte)0; evBuf[35] = (byte)(ev.UserID % 256); evBuf[36] = (byte)(ev.UserID / 256); string descr = ev.Descr ?? ""; if (descr.Length > MaxDescrLen) { descr = descr.Substring(0, MaxDescrLen); } evBuf[37] = (byte)descr.Length; Array.Copy(Encoding.Default.GetBytes(descr), 0, evBuf, 38, descr.Length); string data = ev.Data ?? ""; if (data.Length > MaxDataLen) { data = data.Substring(0, MaxDataLen); } evBuf[138] = (byte)data.Length; Array.Copy(Encoding.Default.GetBytes(data), 0, evBuf, 139, data.Length); return(evBuf); }
/// <summary> /// Заполнить объект dest из файла событий FileName /// </summary> protected void FillObj(object dest) { Stream stream = null; BinaryReader reader = null; DateTime fillTime = DateTime.Now; EventTableLight eventTableLight = null; DataTable dataTable = null; try { if (dest is EventTableLight) eventTableLight = dest as EventTableLight; else if (dest is DataTable) dataTable = dest as DataTable; else throw new Exception("Destination object is invalid."); // определение даты событий в таблице DateTime date = Arithmetic.ExtractDate(tableName); // подготовка объекта для хранения данных if (eventTableLight != null) { eventTableLight.Clear(); eventTableLight.TableName = tableName; } else // dataTable != null { // формирование структуры таблицы dataTable.BeginLoadData(); dataTable.DefaultView.Sort = ""; if (dataTable.Columns.Count == 0) { dataTable.Columns.Add("Number", typeof(int)); dataTable.Columns.Add("DateTime", typeof(DateTime)).DefaultValue = date; dataTable.Columns.Add("ObjNum", typeof(int)).DefaultValue = 0; dataTable.Columns.Add("KPNum", typeof(int)).DefaultValue = 0; dataTable.Columns.Add("ParamID", typeof(int)).DefaultValue = 0; dataTable.Columns.Add("CnlNum", typeof(int)).DefaultValue = 0; dataTable.Columns.Add("OldCnlVal", typeof(double)).DefaultValue = 0.0; dataTable.Columns.Add("OldCnlStat", typeof(int)).DefaultValue = 0; dataTable.Columns.Add("NewCnlVal", typeof(double)).DefaultValue = 0.0; dataTable.Columns.Add("NewCnlStat", typeof(int)).DefaultValue = 0; dataTable.Columns.Add("Checked", typeof(bool)).DefaultValue = false; dataTable.Columns.Add("UserID", typeof(int)).DefaultValue = 0; dataTable.Columns.Add("Descr", typeof(string)); dataTable.Columns.Add("Data", typeof(string)); dataTable.DefaultView.AllowNew = false; dataTable.DefaultView.AllowEdit = false; dataTable.DefaultView.AllowDelete = false; } else { DataColumn colDateTime = dataTable.Columns["DateTime"]; if (colDateTime != null) colDateTime.DefaultValue = date; dataTable.Rows.Clear(); } } // заполнение таблицы из файла stream = ioStream == null ? new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite) : ioStream; reader = new BinaryReader(stream); Byte[] eventBuf = new byte[EventDataSize]; // буфер данных события int evNum = 1; // порядковый номер события while (stream.Position < stream.Length) { int readSize = reader.Read(eventBuf, 0, EventDataSize); if (readSize == EventDataSize) { // создание события на основе считанных данных EventTableLight.Event ev = new EventTableLight.Event(); ev.Number = evNum; evNum++; double time = BitConverter.ToDouble(eventBuf, 0); int hour, min, sec; Arithmetic.DecodeTime(time, out hour, out min, out sec); ev.DateTime = new DateTime(date.Year, date.Month, date.Day, hour, min, sec); ev.ObjNum = BitConverter.ToUInt16(eventBuf, 8); ev.KPNum = BitConverter.ToUInt16(eventBuf, 10); ev.ParamID = BitConverter.ToUInt16(eventBuf, 12); ev.CnlNum = BitConverter.ToUInt16(eventBuf, 14); ev.OldCnlVal = BitConverter.ToDouble(eventBuf, 16); ev.OldCnlStat = eventBuf[24]; ev.NewCnlVal = BitConverter.ToDouble(eventBuf, 25); ev.NewCnlStat = eventBuf[33]; ev.Checked = eventBuf[34] > 0; ev.UserID = BitConverter.ToUInt16(eventBuf, 35); ev.Descr = BytesToStr(eventBuf, 37); ev.Data = BytesToStr(eventBuf, 138); // создание строки заполняемой таблицы if (eventTableLight != null) { eventTableLight.AllEvents.Add(ev); // быстрее, чем eventTableLight.AddEvent(ev) } else // dataTable != null { DataRow row = dataTable.NewRow(); row["Number"] = ev.Number; row["DateTime"] = ev.DateTime; row["ObjNum"] = ev.ObjNum; row["KPNum"] = ev.KPNum; row["ParamID"] = ev.ParamID; row["CnlNum"] = ev.CnlNum; row["OldCnlVal"] = ev.OldCnlVal; row["OldCnlStat"] = ev.OldCnlStat; row["NewCnlVal"] = ev.NewCnlVal; row["NewCnlStat"] = ev.NewCnlStat; row["Checked"] = ev.Checked; row["UserID"] = ev.UserID; row["Descr"] = ev.Descr; row["Data"] = ev.Data; dataTable.Rows.Add(row); } } } } catch (EndOfStreamException) { // нормальная ситуация окончания файла } catch { fillTime = DateTime.MinValue; throw; } finally { if (fileMode) { if (reader != null) reader.Close(); if (stream != null) stream.Close(); } if (eventTableLight != null) { eventTableLight.LastFillTime = fillTime; } else if (dataTable != null) { dataTable.EndLoadData(); dataTable.AcceptChanges(); dataTable.DefaultView.Sort = "Number"; } } }
/// <summary> /// Создать данные события на основе строки таблицы /// </summary> protected EventTableLight.Event CreateEvent(DataRowView rowView) { EventTableLight.Event ev = new EventTableLight.Event(); ev.Number = ConvertToInt(rowView["Number"]); ev.DateTime = ConvertToDateTime(rowView["DateTime"]); ev.ObjNum = ConvertToInt(rowView["ObjNum"]); ev.KPNum = ConvertToInt(rowView["KPNum"]); ev.ParamID = ConvertToInt(rowView["ParamID"]); ev.CnlNum = ConvertToInt(rowView["CnlNum"]); ev.OldCnlVal = ConvertToDouble(rowView["OldCnlVal"]); ev.OldCnlStat = ConvertToInt(rowView["OldCnlStat"]); ev.NewCnlVal = ConvertToDouble(rowView["NewCnlVal"]); ev.NewCnlStat = ConvertToInt(rowView["NewCnlStat"]); ev.Checked = ConvertToBoolean(rowView["Checked"]); ev.UserID = ConvertToInt(rowView["UserID"]); ev.Descr = Convert.ToString(rowView["Descr"]); ev.Data = Convert.ToString(rowView["Data"]); return ev; }
/// <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); } } }
/// <summary> /// Генерировать событие в соответствии со свойствами и данными входного канала /// </summary> private void GenEvent(InCnl inCnl, SrezTableLight.CnlData oldCnlData, SrezTableLight.CnlData newCnlData) { if (inCnl.EvEnabled) { double oldVal = oldCnlData.Val; double newVal = newCnlData.Val; int oldStat = oldCnlData.Stat; int newStat = newCnlData.Stat; bool dataHasChanged = oldStat > BaseValues.CnlStatuses.Undefined && newStat > BaseValues.CnlStatuses.Undefined && (oldVal != newVal || oldStat != newStat); if (// события по изменению inCnl.EvOnChange && dataHasChanged || // события по неопределённому состоянию и выходу из него inCnl.EvOnUndef && (oldStat > BaseValues.CnlStatuses.Undefined && newStat == BaseValues.CnlStatuses.Undefined || oldStat == BaseValues.CnlStatuses.Undefined && newStat > BaseValues.CnlStatuses.Undefined) || // события нормализации, занижения и завышения (newStat == BaseValues.CnlStatuses.Normal || newStat == BaseValues.CnlStatuses.LowCrash || newStat == BaseValues.CnlStatuses.Low || newStat == BaseValues.CnlStatuses.High || newStat == BaseValues.CnlStatuses.HighCrash) && oldStat != newStat) { // создание события EventTableLight.Event ev = new EventTableLight.Event(); ev.DateTime = DateTime.Now; ev.ObjNum = inCnl.ObjNum; ev.KPNum = inCnl.KPNum; ev.ParamID = inCnl.ParamID; ev.CnlNum = inCnl.CnlNum; ev.OldCnlVal = oldCnlData.Val; ev.OldCnlStat = oldStat; ev.NewCnlVal = newCnlData.Val; ev.NewCnlStat = dataHasChanged && oldStat == BaseValues.CnlStatuses.Defined && newStat == BaseValues.CnlStatuses.Defined ? BaseValues.CnlStatuses.Changed : newStat; // запись события и выполнение действий модулей WriteEvent(ev); } } }
/// <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); } }
private void btnSendEvent_Click(object sender, EventArgs e) { // отправка события SCADA-Серверу double oldCnlVal = ScadaUtils.StrToDouble(txtEvOldCnlVal.Text); if (double.IsNaN(oldCnlVal)) { ScadaUtils.ShowError(AppPhrases.IncorrectOldCnlVal); return; } double newCnlVal = ScadaUtils.StrToDouble(txtEvNewCnlVal.Text); if (double.IsNaN(newCnlVal)) { ScadaUtils.ShowError(AppPhrases.IncorrectNewCnlVal); return; } EventTableLight.Event ev = new EventTableLight.Event(); ev.DateTime = dtpEvDate1.Value.Date.Add(dtpEvTime.Value.TimeOfDay); ev.ObjNum = decimal.ToInt32(numEvObjNum.Value); ev.KPNum = decimal.ToInt32(numEvKPNum.Value); ev.ParamID = decimal.ToInt32(numEvParamID.Value); ev.CnlNum = decimal.ToInt32(numEvCnlNum.Value); ev.OldCnlVal = oldCnlVal; ev.OldCnlStat = decimal.ToInt32(numEvOldCnlStat.Value); ev.NewCnlVal = newCnlVal; ev.NewCnlStat = decimal.ToInt32(numEvNewCnlStat.Value); ev.UserID = decimal.ToInt32(numEvUserID1.Value); ev.Checked = ev.UserID > 0; ev.Descr = txtEvDescr.Text; ev.Data = txtEvData.Text; bool result; if (ServerComm.SendEvent(ev, out result)) ScadaUtils.ShowInfo(AppPhrases.SendEventCompleted); else ScadaUtils.ShowError(ServerComm.ErrMsg); }
/// <summary> /// Записать изменения таблицы dataTable в файл или поток /// </summary> public void Update(DataTable dataTable) { if (dataTable == null) { throw new ArgumentNullException("dataTable"); } Stream stream = null; BinaryWriter writer = null; try { stream = ioStream == null ? new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite) : ioStream; writer = new BinaryWriter(stream); // запись изменённых событий DataView dataView = new DataView(dataTable, "", "", DataViewRowState.ModifiedCurrent); foreach (DataRowView rowView in dataView) { EventTableLight.Event ev = CreateEvent(rowView); if (ev.Number > 0) { stream.Seek((ev.Number - 1) * EventDataSize, SeekOrigin.Begin); writer.Write(CreateEventBuffer(ev)); } } // запись добавленных событий dataView = new DataView(dataTable, "", "", DataViewRowState.Added); if (dataView.Count > 0) { // установка позиции записи кратной размеру данных события stream.Seek(0, SeekOrigin.End); int evInd = (int)(stream.Position / EventDataSize); int evNum = evInd + 1; stream.Seek(evInd * EventDataSize, SeekOrigin.Begin); // запись событий и установка номеров событий foreach (DataRowView rowView in dataView) { EventTableLight.Event ev = CreateEvent(rowView); writer.Write(CreateEventBuffer(ev)); rowView["Number"] = evNum++; } } // подтверждение успешного сохранения изменений dataTable.AcceptChanges(); } finally { if (fileMode) { if (writer != null) { writer.Close(); } if (stream != null) { stream.Close(); } } } }
/// <summary> /// Заполнить объект dest из файла событий FileName /// </summary> protected void FillObj(object dest) { Stream stream = null; BinaryReader reader = null; DateTime fillTime = DateTime.Now; EventTableLight eventTableLight = null; DataTable dataTable = null; try { if (dest is EventTableLight) { eventTableLight = dest as EventTableLight; } else if (dest is DataTable) { dataTable = dest as DataTable; } else { throw new ScadaException("Destination object is invalid."); } // определение даты событий в таблице DateTime date = Arithmetic.ExtractDate(tableName); // подготовка объекта для хранения данных if (eventTableLight != null) { eventTableLight.Clear(); eventTableLight.TableName = tableName; } else // dataTable != null { // формирование структуры таблицы dataTable.BeginLoadData(); dataTable.DefaultView.Sort = ""; if (dataTable.Columns.Count == 0) { dataTable.Columns.Add("Number", typeof(int)); dataTable.Columns.Add("DateTime", typeof(DateTime)).DefaultValue = date; dataTable.Columns.Add("ObjNum", typeof(int)).DefaultValue = 0; dataTable.Columns.Add("KPNum", typeof(int)).DefaultValue = 0; dataTable.Columns.Add("ParamID", typeof(int)).DefaultValue = 0; dataTable.Columns.Add("CnlNum", typeof(int)).DefaultValue = 0; dataTable.Columns.Add("OldCnlVal", typeof(double)).DefaultValue = 0.0; dataTable.Columns.Add("OldCnlStat", typeof(int)).DefaultValue = 0; dataTable.Columns.Add("NewCnlVal", typeof(double)).DefaultValue = 0.0; dataTable.Columns.Add("NewCnlStat", typeof(int)).DefaultValue = 0; dataTable.Columns.Add("Checked", typeof(bool)).DefaultValue = false; dataTable.Columns.Add("UserID", typeof(int)).DefaultValue = 0; dataTable.Columns.Add("Descr", typeof(string)); dataTable.Columns.Add("Data", typeof(string)); dataTable.DefaultView.AllowNew = false; dataTable.DefaultView.AllowEdit = false; dataTable.DefaultView.AllowDelete = false; } else { DataColumn colDateTime = dataTable.Columns["DateTime"]; if (colDateTime != null) { colDateTime.DefaultValue = date; } dataTable.Rows.Clear(); } } // заполнение таблицы из файла stream = ioStream == null ? new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite) : ioStream; reader = new BinaryReader(stream); Byte[] eventBuf = new byte[EventDataSize]; // буфер данных события int evNum = 1; // порядковый номер события while (stream.Position < stream.Length) { int readSize = reader.Read(eventBuf, 0, EventDataSize); if (readSize == EventDataSize) { // создание события на основе считанных данных EventTableLight.Event ev = new EventTableLight.Event(); ev.Number = evNum; evNum++; double time = BitConverter.ToDouble(eventBuf, 0); int hour, min, sec; Arithmetic.DecodeTime(time, out hour, out min, out sec); ev.DateTime = new DateTime(date.Year, date.Month, date.Day, hour, min, sec); ev.ObjNum = BitConverter.ToUInt16(eventBuf, 8); ev.KPNum = BitConverter.ToUInt16(eventBuf, 10); ev.ParamID = BitConverter.ToUInt16(eventBuf, 12); ev.CnlNum = BitConverter.ToUInt16(eventBuf, 14); ev.OldCnlVal = BitConverter.ToDouble(eventBuf, 16); ev.OldCnlStat = eventBuf[24]; ev.NewCnlVal = BitConverter.ToDouble(eventBuf, 25); ev.NewCnlStat = eventBuf[33]; ev.Checked = eventBuf[34] > 0; ev.UserID = BitConverter.ToUInt16(eventBuf, 35); ev.Descr = BytesToStr(eventBuf, 37); ev.Data = BytesToStr(eventBuf, 138); // создание строки заполняемой таблицы if (eventTableLight != null) { eventTableLight.AllEvents.Add(ev); // быстрее, чем eventTableLight.AddEvent(ev) } else // dataTable != null { DataRow row = dataTable.NewRow(); row["Number"] = ev.Number; row["DateTime"] = ev.DateTime; row["ObjNum"] = ev.ObjNum; row["KPNum"] = ev.KPNum; row["ParamID"] = ev.ParamID; row["CnlNum"] = ev.CnlNum; row["OldCnlVal"] = ev.OldCnlVal; row["OldCnlStat"] = ev.OldCnlStat; row["NewCnlVal"] = ev.NewCnlVal; row["NewCnlStat"] = ev.NewCnlStat; row["Checked"] = ev.Checked; row["UserID"] = ev.UserID; row["Descr"] = ev.Descr; row["Data"] = ev.Data; dataTable.Rows.Add(row); } } } } catch (EndOfStreamException) { // нормальная ситуация окончания файла } catch { fillTime = DateTime.MinValue; throw; } finally { if (fileMode) { if (reader != null) { reader.Close(); } if (stream != null) { stream.Close(); } } if (eventTableLight != null) { eventTableLight.LastFillTime = fillTime; } else if (dataTable != null) { dataTable.EndLoadData(); dataTable.AcceptChanges(); dataTable.DefaultView.Sort = "Number"; } } }
/// <summary> /// Отправить событие SCADA-Серверу /// </summary> public bool SendEvent(KPLogic.KPEvent kpEvent) { if (kpEvent == null || kpEvent.KPTag == null || kpEvent.KPTag.CnlNum <= 0) { return true; } else { EventTableLight.Event ev = new EventTableLight.Event(); ev.Number = kpEvent.KPNum; ev.DateTime = kpEvent.DateTime; ev.ObjNum = kpEvent.KPTag.ObjNum; ev.KPNum = kpEvent.KPNum; ev.ParamID = kpEvent.KPTag.ParamID; ev.CnlNum = kpEvent.KPTag.CnlNum; ev.OldCnlVal = kpEvent.OldData.Val; ev.OldCnlStat = kpEvent.OldData.Stat; ev.NewCnlVal = kpEvent.NewData.Val; ev.NewCnlStat = kpEvent.NewData.Stat; ev.Checked = kpEvent.Checked; ev.UserID = kpEvent.UserID; ev.Descr = kpEvent.Descr; ev.Data = kpEvent.Data; bool result; return SendEvent(ev, out result) && result; } }