Table of Contents

Отображение событий на каждую метку времени

В списке полей редактора отчетов данные из архива ошибок хранятся в узле Архив ошибок точки учета, а данные из архива событий устройства хранятся в узле Устройство->Архив событий устройства. Архив ошибок и архив событий это наборы записей с полями:

Архив ошибок связан с опрашиваемой точкой учета. Записи архива ошибок содержат дату/время начала метки времени DateTime, к которой относится ошибка. Архив событий связан с опрашиваемым устройством, тепловые вводы которого могут быть подключены к разным точкам учета. Записи архива событий содержат дату/время начала StartDateTime и окончания EndDateTime события, а также номер теплового ввода HeatLeadIn, к которому подключена точка учета. В редакторе отчетов информация по ошибкам и событиям на каждую метку времени хранится в полях DeviceErrorCodes, DeviceErrorDurations, DeviceEventCodes, DeviceEventDurations.

Примечание

Чтобы при формировании отчета была доступна информация о событиях устройства, необходимо в параметрах автоопроса или в параметрах ручного опроса выбрать загрузку архива событий. Архив ошибок, если он есть, заполняется автоматически при опросе точки учета.

За период одной метки времени могут происходить события относящиеся к разным типам, поэтому для каждого события указываются тип архива, номер теплового ввода, номер канала и код события. В полях DeviceErrorCodes и DeviceEventCodes информация хранится в виде строки с разделителями: архив1|ввод1|канал1|код1; ... архивN|вводN|каналN|кодN. В полях DeviceErrorDurations и DeviceEventDurations информация хранится в виде строки с разделителями: архив1|ввод1|канал1|код1|длительность1; ... архивN|вводN|каналN|кодN|длительностьN Длительность указывается в секундах. Коды событий зависят от модели устройства и описываются в руководстве по эксплуатации прибора. Если при формировании отчета для каждой метки времени требуется выводить информацию о типе архива, коде и длительности события, то это выполняется в скриптах обработчика Перед печатью для ячеек связанных с полем DeviceEventCodes или DeviceEventDurations.

Рассмотрим использование полей DeviceEventCodes и DeviceEventDurations для архива событий на примере отчетной формы для точки учета c прибором КМ-5. Использование полей DeviceErrorCodes и DeviceErrorDurations для архива ошибок выполняется аналогично.

ШАГ 1. Создайте отчетную форму для точки учета.

ШАГ 2. Добавьте колонку в секции PageHeader и Detail. Добавленную колонку секции Detail назовите EventArchive.

ШАГ 3. Свяжите добавленную колонку EventArchive с полем DeviceEventCodes из узла Архив потреблений и интеграторов.

ШАГ 4. Добавьте в секцию Detail ячейку с именем EventDuration. Свойству Видимость для этой ячейки задайте значение Нет. Эта ячейка нужна только для доступа к полю DeviceEventDurations.

ШАГ 5. Свяжите ячейку EventDuration с полем DeviceEventDurations.

ШАГ 6. Для вывода расшифровки кодов событий для каждого типа архива положите на форму в секцию ReportFooter поле DeviceEventDescription из узла Устройство.

Для отображения длительностей для групп событий добавьте в секцию ReportFooter таблицу. Задайте наименования ячеек как показано на рисунке для групп событий обозначенных символами U, E, D, g, G, *

Ячейку с длительностью отчетного периода свяжите с полем RequestedInterval из узла Рассчитанные значения->Суммарные потребления по системам снабжения за отчетный период, а ячейку с длительностью периода имеющихся данных с полем ExistingInterval.

ШАГ 7. В окне свойств колонки EventArchive в разделе Скрипты добавьте новый обработчик события Перед печатью.

ШАГ 8. Откроется редактор скриптов, в котором будет пустая заготовка обработчика Перед печатью c именем EventArchive_BeforePrint(). Перед обработчиком EventArchive_BeforePrint() добавьте массивы для хранения групп кодов событий и переменные для хранения длительностей соответствующих периодов:

`// Код периода отключения питания int[] codes_U = {122};

// Длительность отключения питания double period_U = 0;

// Код периода t1-t2 < min int[] codes_D = {96};

// Длительность периода t1-t2 < min double period_D = 0;

// Коды функционального отказа int[] codes_E = {61, 64, 65, 66, 67, 68, 69, 71, 73, 74, 76, 79, 81, 88, 90, 91, 93, 94, 106, 114, 119, 120, 121};

// Длительность функционального отказа double period_E = 0;

// Коды периода G > max int[] codes_G = {82, 85};

// Длительность периода G > max double period_G = 0;

// Коды периода G < min int[] codes_g = {84, 87};

// Длительность периода G < min double period_g = 0;

// Длительность периода для прочих кодов double period_other = 0; `

В метод EventArchive_BeforePrint() обработчика добавьте код, в котором формируется отображаемое значение ячейки EventArchive.

`// Формирует текст для колонки 'Архив событий' // Эта колонка связана с полем DeviceEventCodes, в котором события записаны в виде строки: // архив1|ввод1|канал1|код1; архив2|ввод2|канал2|код2; ... архивN|вводN|каналN|кодN private void EventArchive_BeforePrint(object sender, System.Drawing.Printing.PrintEventArgs e) { // Строка с информацией о событиях. // Формат строки: архив1|ввод1|канал1|код1; архив2|ввод2|канал2|код2; ... архивN|вводN|каналN|кодN. string eventCodesString = ((XRLabel)sender).Text;

if (String.IsNullOrEmpty(eventCodesString))
	return;

// Получаем массив типов архива и кодов событий:
// eventCodesString - строка с форматом: архив1|ввод1|канал1|код1; архив2|ввод2|канал2|код2; ... архивN|вводN|каналN|кодN
string[] eventCodes =  eventCodesString.Split(new string[]{";"}, StringSplitOptions.RemoveEmptyEntries);

// Формируем обозначения для групп событий и типов архивов
string eventCodesSymbol = String.Empty;
foreach (string eventCodeInfo in eventCodes)
{
	// Получаем информация по событию в виде строки: архив|ввод|канал|код
	string[] eventInfo = (eventCodeInfo.Trim()).Split(new string[]{"|"}, StringSplitOptions.RemoveEmptyEntries);

	// Код типа архива 
	int archiveType = -1;
	if (!String.IsNullOrEmpty(eventInfo[0].Trim()))
		archiveType = Convert.ToInt32(eventInfo[0]);

	// Номер теплового ввода 
	int heatLeadIn = -1;
	if (!String.IsNullOrEmpty(eventInfo[1].Trim()))
		heatLeadIn = Convert.ToInt32(eventInfo[1]);

	// Номер канала 
	int channelNumber = -1;
	if (!String.IsNullOrEmpty(eventInfo[2].Trim()))
		channelNumber = Convert.ToInt32(eventInfo[2]);

	// Код события
	int code = -1;
	if (!String.IsNullOrEmpty(eventInfo[3].Trim()))
		code = Convert.ToInt32(eventInfo[3]);

	// Формируем символьное отображение набора событий в зависимости от кода события

	// Период отключения питания
	if (Array.Exists(codes_U, delegate(int c) { return (c == code); }) && eventCodesSymbol.IndexOf("U") == -1)
		eventCodesSymbol += "U";

	// Период t1-t2 < min
	else if (Array.Exists(codes_D, delegate(int c) { return (c == code); }) && eventCodesSymbol.IndexOf("D") == -1)
		eventCodesSymbol += "D";

	// Период функционального отказа
	else if (Array.Exists(codes_E, delegate(int c) { return (c == code); }) && eventCodesSymbol.IndexOf("E") == -1)
		eventCodesSymbol += "E";

	// Период G > max
	else if (Array.Exists(codes_G, delegate(int c) { return (c == code); }) && eventCodesSymbol.IndexOf("G") == -1)
		eventCodesSymbol += "G";

	// Период G < min
	if (Array.Exists(codes_g, delegate(int c) { return (c == code); }) && eventCodesSymbol.IndexOf("g") == -1)
		eventCodesSymbol += "g";

	// Период прочих кодов
	else if (eventCodesSymbol.IndexOf("*") == -1)
		eventCodesSymbol += "*";
}

// Задаем текст отображаемый в ячейке EventArchive
((XRLabel)sender).Text = eventCodesSymbol;

} `

ШАГ 9. В окне свойств ячейки EventDuration в разделе Скрипты добавьте новый обработчик Перед печатью с именем EventsDuration_BeforePrint. В метод EventsDuration_BeforePrint() обработчика добавьте код, в котором формируются суммарные длительности для групп событий:

` // Формируем суммарные длительности для групп событий

// Ячейка EventsDuration связана с полем DeviceEventDuration, в котором события записаны в виде строки:

// архив1|ввод1|канал1|код1|длительность1; архив2|ввод2|канал2|код2|длительность2; ... архивN|вводN|каналN|кодN|длительностьN

// Ячейка EventsDuration нужна только для расчета суммарных длительностей, поэтому ее можно сделать невидимой, установив свойство Видимость = Нет

private void EventDuration_BeforePrint(object sender, System.Drawing.Printing.PrintEventArgs e) { // Получаем содержимое ячейки. string eventDurationString = ((XRLabel)sender).Text;

if (String.IsNullOrEmpty(eventDurationString))
	return;

// Получаем массив кодов и длительностей событий
// Каждый элемент мвссива - это строка формата: архив|ввод|канал|код|длительность
string[] eventDurations =  eventDurationString.Split(new string[]{";"}, StringSplitOptions.RemoveEmptyEntries);

// Перебираем события и формируем суммарные длительности 	
foreach (string eventDuration in eventDurations)
{
	// eventDuration - строка c форматом: архив|ввод|канал|код|длительность
	string[] codeDuration = (eventDuration.Trim()).Split(new string[]{"|"}, StringSplitOptions.RemoveEmptyEntries);
	
	// Код типа архива 
	int archiveType = -1;
	if (!String.IsNullOrEmpty(codeDuration[0].Trim()))
		archiveType = Convert.ToInt32(codeDuration[0]);

	// Номер теплового ввода 
	int heatLeadIn = -1;
	if (!String.IsNullOrEmpty(codeDuration[1].Trim()))
		heatLeadIn = Convert.ToInt32(codeDuration[1]);

	// Номер канала 
	int channelNumber = -1;
	if (!String.IsNullOrEmpty(codeDuration[2].Trim()))
		channelNumber = Convert.ToInt32(codeDuration[2]);

	// Код события
	int code = -1;
	if (!String.IsNullOrEmpty(codeDuration[3].Trim()))
		code = Convert.ToInt32(codeDuration[3]);

	// Длительность события в секундах
	double duration = 0;
	if (!String.IsNullOrEmpty(codeDuration[4].Trim()))
		duration = Convert.ToDouble(codeDuration[4]);

	// Переводим длительность события из секунд в доли часа
	duration = duration / 3600D;

	// Период отключения питания
	if (Array.Exists(codes_U, delegate(int c) { return (c == code); }))
		period_U += duration;

	// Период t1-t2 < min
	else if (Array.Exists(codes_D, delegate(int c) { return (c == code); }))
		period_D += duration;

	// Период функционального отказа
	else if (Array.Exists(codes_E, delegate(int c) { return (c == code); }))
		period_E += duration;

	// Период G > max
	else if (Array.Exists(codes_G, delegate(int c) { return (c == code); }))
		period_G += duration;

	// Период G < min
	else if (Array.Exists(codes_g, delegate(int c) { return (c == code); }))
		period_g += duration;

	// Период прочих кодов
	else 
		period_other += duration;
}

} `

ШАГ 10. Для всех ячеек с длительностями групп событий в добавленной таблице в секции ReportFooter в разделе Скрипты добавьте обработчик Перед печатью c именем Period_BeforePrint. В метод Period_BeforePrint() обработчика добавьте код, в котором заполняются ячейки с суммарными длительностями для групп событий:

// Отображаем суммарные длительности периодов групп событий
private void Period_BeforePrint(object sender, System.Drawing.Printing.PrintEventArgs e) 
{
	XRTableCell cell= ((XRTableCell)sender);

	double period = 0;
	switch (cell.Name)
	{
		case "Period_U":	// Период отключения питания
			period = period_U;
			break;

		case "Period_D":	// Период t1-t2 < min
			period = period_D;
			break;

		case "Period_E":	// Период функционального отказа
			period = period_E;
			break;

		case "Period_Gmax":	// Период G > max
			period = period_G;
			break;

		case "Period_Gmin":	// Период G < min
			period = period_g;
			break;

		case "Period_Other":	// Период прочие
			period = period_other;
			break;
	}

	cell.Text = String.Format("{0:F4}", period);
}

ШАГ 11. Сохраните отчетную форму. Если сформировать отчет по созданной отчетной форме, то он будет выглядеть так: