diff --git a/AttributesSample/LersSample.csproj b/AttributesSample/LersSample.csproj new file mode 100644 index 0000000..b3e8686 --- /dev/null +++ b/AttributesSample/LersSample.csproj @@ -0,0 +1,81 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {1E9BFBEA-6183-416C-B5EA-C883CD62277E} + Exe + Properties + LersSample + LersSample + v4.0 + Client + 512 + + + x86 + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + false + + + x86 + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + false + + + true + bin\x64\Debug\ + DEBUG;TRACE + full + x64 + false + prompt + false + false + + + bin\x64\Release\ + TRACE + true + pdbonly + x64 + false + prompt + + + + False + ..\..\Lers.System\bin\x64\Debug\Lers.System.dll + + + + + + + + + + + + + + \ No newline at end of file diff --git a/AttributesSample/LersSample.sln b/AttributesSample/LersSample.sln new file mode 100644 index 0000000..043b7a5 --- /dev/null +++ b/AttributesSample/LersSample.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LersSample", "LersSample.csproj", "{1E9BFBEA-6183-416C-B5EA-C883CD62277E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1E9BFBEA-6183-416C-B5EA-C883CD62277E}.Debug|x64.ActiveCfg = Debug|x64 + {1E9BFBEA-6183-416C-B5EA-C883CD62277E}.Debug|x64.Build.0 = Debug|x64 + {1E9BFBEA-6183-416C-B5EA-C883CD62277E}.Debug|x86.ActiveCfg = Debug|x86 + {1E9BFBEA-6183-416C-B5EA-C883CD62277E}.Debug|x86.Build.0 = Debug|x86 + {1E9BFBEA-6183-416C-B5EA-C883CD62277E}.Release|x64.ActiveCfg = Release|x86 + {1E9BFBEA-6183-416C-B5EA-C883CD62277E}.Release|x64.Build.0 = Release|x86 + {1E9BFBEA-6183-416C-B5EA-C883CD62277E}.Release|x86.ActiveCfg = Release|x86 + {1E9BFBEA-6183-416C-B5EA-C883CD62277E}.Release|x86.Build.0 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/AttributesSample/Program.cs b/AttributesSample/Program.cs new file mode 100644 index 0000000..fd5e476 --- /dev/null +++ b/AttributesSample/Program.cs @@ -0,0 +1,126 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Security; +using Lers.Core; +using Lers.Data; + +namespace LersSample +{ + class Program + { + static void Main(string[] args) + { + // Создаем экземпляр объекта LersServer, через который осуществляется работа с сервером ЛЭРС УЧЕТ. + + Lers.LersServer server = new Lers.LersServer(); + + // Создаем данные для авторизации в системе (логин и пароль). + + string login = "admin"; + SecureString password = Lers.Networking.SecureStringHelper.ConvertToSecureString("admin"); + + Lers.Networking.BasicAuthenticationInfo authInfo = new Lers.Networking.BasicAuthenticationInfo(login, password); + + // Выполняем подключение к серверу, указывая имя компьютера и TCP-порт, а так же данные для авторизации. + + try + { + server.Connect("localhost", 10000, authInfo); + } + catch (Exception exc) + { + Console.WriteLine("Ошибка подключения к серверу.\r\n" + exc.Message); + Console.Read(); + return; + } + + Console.WriteLine("Версия сервера: " + server.Version.ToString()); + + // Получаем объект учета по уникальному номеру, который задается в свойствах объекта учета. + // Указываем через флаг, что нам нужны атрибуты и системы объекта учета. + Node node = server.Nodes.GetByNumber(1232, NodeInfoFlags.Attributes | NodeInfoFlags.Systems); + + // Убеждаемся, что мы получили указатель на объект Node. + // Если объект учета с таким номером не существует или он недоступна для текущего пользовтеля, то метод GetByNumber() вернет null. + + if (node != null) + { + // Выводим наименование Объекта учета. + + Console.WriteLine("Объект учета \'{0}\'", node.Title); + + MeasurePoint[] measurePoints = node.Systems.HotWater.MeasurePoints.ToArray(); + + // Запрашиваем данные о суточном потреблении гвс за двое суток. + + MeasurePointConsumptionRecord[] consumption1 = measurePoints[0].Data.GetConsumption(DateTime.Today.AddDays(-1), DateTime.Today, Lers.Data.DeviceDataType.Day).ToArray(); + + MeasurePointConsumptionRecord[] consumption2 = measurePoints[1].Data.GetConsumption(DateTime.Today.AddDays(-1), DateTime.Today, Lers.Data.DeviceDataType.Day).ToArray(); + + string scheme = (string)node.Attributes["схема"]; + + MeasurePointConsumptionRecord[] consumption = new MeasurePointConsumptionRecord[consumption1.Length]; + + switch (scheme) + { + // Первая схема измерения + case "1": + + // Здесь реализуем расчет по схеме измерения, например складываем потребления по двум точкам учета. + + for (int i = 0; i < consumption1.Length; i++) + { + MeasurePointConsumptionRecordWater record = new MeasurePointConsumptionRecordWater(consumption1[i].DateTime); + + record.M_in = ((MeasurePointConsumptionRecordWater)consumption1[i]).M_in + ((MeasurePointConsumptionRecordWater)consumption2[i]).M_in; + record.M_out = ((MeasurePointConsumptionRecordWater)consumption1[i]).M_out + ((MeasurePointConsumptionRecordWater)consumption2[i]).M_out; + + consumption[i] = record; + } + + break; + + // Вторая схема измерения + case "2": + + // Здесь реализуем расчет по схеме измерения, например вычисляем разницу потребления по двум точкам учета. + + for (int i = 0; i < consumption1.Length; i++) + { + MeasurePointConsumptionRecordWater record = new MeasurePointConsumptionRecordWater(consumption1[i].DateTime); + + record.M_in = ((MeasurePointConsumptionRecordWater)consumption1[i]).M_in - ((MeasurePointConsumptionRecordWater)consumption2[i]).M_in; + record.M_out = ((MeasurePointConsumptionRecordWater)consumption1[i]).M_out - ((MeasurePointConsumptionRecordWater)consumption2[i]).M_out; + + consumption[i] = record; + } + + break; + + default: + throw new Exception("Неподдерживаемый номер схемы измерения."); + } + + // Выводим данные на экран. + + foreach (MeasurePointConsumptionRecordWater recordWater in consumption) + { + Console.WriteLine("{0}: M1 = {1}, M2 = {2}", recordWater.DateTime, recordWater.M_in, recordWater.M_out); + } + } + else + { + Console.WriteLine("Объект учета не существует или недоступен для данной учетной записи."); + } + + Console.ReadLine(); + + // Отключаемся от сервера. + // Указываем таймаут 2 секунды на нормальное завершение сеанса, после выхода которого, соединение будет разорвано. + + server.Disconnect(2000); + } + } +} diff --git a/AttributesSample/Properties/AssemblyInfo.cs b/AttributesSample/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..49ac514 --- /dev/null +++ b/AttributesSample/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("LersSample")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("LersSample")] +[assembly: AssemblyCopyright("Copyright © 2013")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("6a23aa78-7b98-4b51-bad6-69ea6363f58c")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/GetDataSample/LersSample.csproj b/GetDataSample/LersSample.csproj new file mode 100644 index 0000000..bc881c9 --- /dev/null +++ b/GetDataSample/LersSample.csproj @@ -0,0 +1,60 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {1E9BFBEA-6183-416C-B5EA-C883CD62277E} + Exe + Properties + LersSample + LersSample + v4.0 + Client + 512 + + + x86 + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + false + + + x86 + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + false + + + + ..\..\Lers.System\bin\x86\Release\Lers.System.dll + + + + + + + + + + + + + + \ No newline at end of file diff --git a/GetDataSample/LersSample.sln b/GetDataSample/LersSample.sln new file mode 100644 index 0000000..60a22e3 --- /dev/null +++ b/GetDataSample/LersSample.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LersSample", "LersSample.csproj", "{1E9BFBEA-6183-416C-B5EA-C883CD62277E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x86 = Debug|x86 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1E9BFBEA-6183-416C-B5EA-C883CD62277E}.Debug|x86.ActiveCfg = Debug|x86 + {1E9BFBEA-6183-416C-B5EA-C883CD62277E}.Debug|x86.Build.0 = Debug|x86 + {1E9BFBEA-6183-416C-B5EA-C883CD62277E}.Release|x86.ActiveCfg = Release|x86 + {1E9BFBEA-6183-416C-B5EA-C883CD62277E}.Release|x86.Build.0 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/GetDataSample/Program.cs b/GetDataSample/Program.cs new file mode 100644 index 0000000..e13939c --- /dev/null +++ b/GetDataSample/Program.cs @@ -0,0 +1,109 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Security; +using Lers.Core; +using Lers.Data; + +namespace LersSample +{ + class Program + { + static void Main(string[] args) + { + // Создаем экземпляр объекта LersServer, через который осуществляется работа с сервером ЛЭРС УЧЕТ. + + Lers.LersServer server = new Lers.LersServer(); + + // Создаем данные для авторизации в системе (логин и пароль). + + string login = "Admin"; + SecureString password = Lers.Networking.SecureStringHelper.ConvertToSecureString("admin"); + + Lers.Networking.BasicAuthenticationInfo authInfo = new Lers.Networking.BasicAuthenticationInfo(login, password); + + // Выполняем подключение к серверу, указывая имя компьютера и TCP-порт, а так же данные для авторизации. + + try + { + server.Connect("localhost", 10000, authInfo); + } + catch (Exception exc) + { + Console.WriteLine("Ошибка подключения к серверу.\r\n" + exc.Message); + Console.Read(); + return; + } + + Console.WriteLine("Версия сервера: " + server.Version.ToString()); + + // Получаем точку учета по уникальному номеру, который задается в свойствах точки учета. + + MeasurePoint measurePoint = server.MeasurePoints.GetByNumber(123); + + // Убеждаемся, что мы получили указатель на объект MeasurePoint. + // Если точки учета с таким номером не существует или она недоступна для текущего пользовтеля, то метод GetByNumber() вернет null. + + if (measurePoint != null) + { + // Выводим полное наименование точки учета. + + Console.WriteLine("Точка учета \'{0}\'", measurePoint.FullTitle); + + if (measurePoint.SystemType != SystemType.Gas) + { + Console.WriteLine("Точка учета должна иметь систему Газонабжение."); + Console.Read(); + return; + } + + // Сохраняем суточные данные о потреблении по точке учета. + // Чтобы сохранить данные по воде, используйте Lers.Data.WaterConsumptionRecord, по электроэнергии - Lers.Data.ElectricConsumptionRecord. + + MeasurePointConsumptionRecordCollection data = new MeasurePointConsumptionRecordCollection(DeviceDataType.Day); + + MeasurePointConsumptionRecordGas record = new MeasurePointConsumptionRecordGas(DateTime.Today.AddDays(-1)); // За вчерашние сутки + record.V = 100; // Объем газа + record.T = 20; // Температура газа + + data.Add(record); + + MeasurePointConsumptionRecordGas record2 = new Lers.Data.MeasurePointConsumptionRecordGas(DateTime.Today); // За сегодняшние сутки + record2.V = 80; // Объем газа + record2.T = 15; // Температура газа + + data.Add(record2); + + // Устанавливаем флаг для перезаписи существующих данных и сохраняем данные. + + MeasurePointSetConsumptionOptions options = new MeasurePointSetConsumptionOptions(); + options.OverwriteExistingRecords = true; + + measurePoint.Data.SetConsumption(data, options); + + // Запрашиваем данные о суточном потреблении газа за двое суток. + + MeasurePointConsumptionRecordCollection consumption = measurePoint.Data.GetConsumption(DateTime.Today.AddDays(-1), DateTime.Today, Lers.Data.DeviceDataType.Day); + + // Выводим данные на экран. + + foreach (MeasurePointConsumptionRecordGas recordGas in consumption) + { + Console.WriteLine("{0}: V = {1}, T = {2}", recordGas.DateTime, recordGas.V, recordGas.T); + } + } + else + { + Console.WriteLine("Точка учета не существует или недоступна для данной учетной записи."); + } + + Console.ReadLine(); + + // Отключаемся от сервера. + // Указываем таймаут 2 секунды на нормальное завершение сеанса, после выхода которого, соединение будет разорвано. + + server.Disconnect(2000); + } + } +} diff --git a/GetDataSample/Properties/AssemblyInfo.cs b/GetDataSample/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..49ac514 --- /dev/null +++ b/GetDataSample/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("LersSample")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("LersSample")] +[assembly: AssemblyCopyright("Copyright © 2013")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("6a23aa78-7b98-4b51-bad6-69ea6363f58c")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/ImportTemperature/ImportTemperature.docx b/ImportTemperature/ImportTemperature.docx new file mode 100644 index 0000000..476d6c8 --- /dev/null +++ b/ImportTemperature/ImportTemperature.docx @@ -0,0 +1,22 @@ +Назначение + Скрипт ImportTemperature.ps1 выполняет импорт данных среднесуточной температуры наружного воздуха с сайта мониторинга погоды www.pogoda.ru.net [HYPERLINK: http://www.pogoda.ru.net] в ЛЭРС УЧЕТ. Импортированные данные сохраняются в справочник температур наружного воздуха. + +Синтаксис + Powershell .\ImportTemperature.ps1 Город [период] + где: + Город - название города, по которому необходимо импортировать данные среднесуточной температуры. Параметр должен быть первым в параметрах командной строки. + [период] - интервал времени в формате <дата_начала>-< дата_окончания>, за который импортируются данные среднесуточной температуры. Если параметр не указан, то импортируются данные за предыдущий день. Даты начала и окончания периода задаются в формате dd.mm.yyyy. + +Пример 1. Импорт данных среднесуточной температуры за предыдущий день в Хабаровске. + Powershell .\ImportTemperature.ps1 "Хабаровск" + +Пример 2. Импорт данных среднесуточной температуры с 1 декабря по 10 декабря в Хабаровске. + Powershell .\ImportTemperature.ps1 "Хабаровск" "01.12.2010-10.12.2010" + +Параметры +Перед первым запуском импорта данных необходимо настроить параметры импорта, которые задаются в тексте самого скрипта. +$LersAutoPath - расположение файла сервера автоматизации +$ServerAddress - адрес сервера ЛЭРС УЧЕТ. В качестве адреса сервера может быть указано как имя, так и IP-адрес компьютера, на котором установлен сервер +$ServerPort - порт сервера ЛЭРС УЧЕТ +$Login - Имя входа в ЛЭРС УЧЕТ +$PassWord - пароль для входа в ЛЭРС УЧЕТ diff --git a/ImportTemperature/ImportTemperature.ps1 b/ImportTemperature/ImportTemperature.ps1 new file mode 100644 index 0000000..ec4626f --- /dev/null +++ b/ImportTemperature/ImportTemperature.ps1 @@ -0,0 +1,405 @@ + + ######################################################################## + # Настройки + ######################################################################## + + # путь к фреймворку ЛЭРС УЧЕТ + $LersFrameworkPath = "C:\Program Files\LERS\Common\Framework\bin\Lers.System.dll" + + # Адрес сервера приложения + $ServerAddress = 'localhost' + + # Порт сервера приложения + $ServerPort = 10000 + + # Имя входа/пароль для подключения к Серверу + $Login = 'login' + $PassWord = 'password' + + # адрес ресурса + $url = 'http://www.pogoda.ru.net/monitor.php' + + # регулярное выражение, для нахождения url адреса заданного города + # Хабаровск + $regExpressionCityFirst = '(?i:' + $regExpressionCitySecond = ')' + + # регулярное выражение для поиска среднесуточной температуры + # 5-21.0-15.1 + $regExpressionTemperatureFirst = '(?i:' + $regExpressionTemperatureSecond = '\s*[\d\.\-\+]+\s*([\d\.\-\+]+))' + + ################################################################## + # Подключаемые типы + ################################################################## + + try + { + # подключаем фреймворк + add-type -path $LersFrameworkPath + } + catch + { + write-host 'Ошибка. Не удалось загрузить файл Lers.System.dll. Проверьте правильность расположения файла. ' + $Error[0].Exception.Message + exit + } + + ######################################################################## + # Функции + ######################################################################## + + # Проверяет заданы ли параметры настройки скрипта + Function CheckParameters($url, $ServerAddress, $ServerPort, $Login, $PassWord) + { + try + { + if ($url -eq '') + { + throw new-object Exception('Адрес сайта мониторинга погоды не задан.') + } + + if ($ServerAddress -eq '') + { + throw new-object Exception('Адрес сервера ЛЭРС УЧЕТ не задан.') + } + + if (($ServerPort -eq $null) -or ($ServerPort -eq 0) -or ($ServerPort -eq '')) + { + throw new-object Exception('Порт сервера ЛЭРС УЧЕТ не задан.') + } + + if ($Login -eq '') + { + throw new-object Exception('Имя входа в ЛЭРС УЧЕТ не задано.') + } + + if ($PassWord -eq '') + { + throw new-object Exception('Пароль для входа в ЛЭРС УЧЕТ не задан.') + } + } + catch + { + throw new-object Exception('Параметры скрипта не настроены. ', $Error[0].Exception) + } + } + + ################################################################## + + # возвращает содержимое html страницы по адресу url ввиде строки + Function Get-WwwString([string]$url, [string]$Encoding = "windows-1251") + { + try + { + # создаем web client + $wc = new-object System.Net.WebClient + + # устанавливаем кодировку + $wc.Encoding = [System.Text.Encoding]::GetEncoding($Encoding) + + # возвращаем html страницу ввиде строки + return $wc.DownloadString($url) + } + catch + { + throw new-object Exception('Не удалось загрузить html страницу по адресу ' + $url + '.', $Error[0].Exception) + } + } + + ################################################################## + + # возращает описание исключений + Function GetFullExceptionMessage([Exception]$exc) + { + if($exc -eq $null) + { + return '' + } + + $msg = $exc.Message + + if ($exc.InnerException -ne $null) + { + $mes = GetFullExceptionMessage $exc.InnerException + $msg = $msg + ' ' + $mes + } + + return $msg + } + + ########################################################################## + + # возвращает url адрес на страницу заданного города + # $reply - содержимое html страницы ввиде строки + # $gorod - имя города + # $url - адрес страницы мониторинга погоды + Function Get-CityUrl($reply, $gorod, $url) + { + try + { + # регулярное выражение, для нахождения url адреса заданного города + # Хабаровск + [regex]$reg = $regExpressionCityFirst + $gorod + $regExpressionCitySecond + $match = $reg.match($reply) + + if(!$match.Success) + { + throw new-object Exception(' Url страницы не найден.') + } + + # формируем ссылку на страницу + $uri = new-object Uri ($url) + $urlCity = $match.Groups[1].value + $urlCity = 'http://' + $uri.Host + '/' + $urlCity + + return $urlCity + } + catch + { + throw new-object Exception('Не удалось получить ссылку на страницу города - ' + $gorod + '.', $Error[0].Exception) + } + } + + ########################################################################## + + # возвращает хеш-таблицу среднесуточной температуры наружного воздуха за указанный период времени + # dateFrom - дата начало периода + # dateTo - дата окончания периода + # link - url города + Function Get-CityTemperature($dateFrom, $dateTo, $link) + { + try + { + $today = [DateTime]::Today + if($dateFrom -gt $today) + { + throw new-object Exception('Дата начала периода превышает текущую.') + } + + if($dateFrom -gt $dateTo) + { + throw new-object Exception('Дата начала периода больше даты окончания.') + } + + if($dateTo -gt $today) + { + $dateTo = $today + } + + # хеш таблица для хранения среднесуточных значениий температур по дате + $TempTable = @{} + + # месяц, за который загружается html-страница с темпераиурами + $month = 0 + + # html страница + [void][string]$html + + while ($dateFrom -le $dateTo) + { + if ($dateFrom.Month -ne $month) + { + $month = $dateFrom.Month + + # ссылка на страницу за указанный месяц и год + $ref = $link + '&month=' + $dateFrom.Month + '&year=' + $dateFrom.Year + + # загружаем html страницу заданного месяца и года + $html = Get-WwwString $ref + } + + # регулярное выражение для поиска среднесуточной температуры + # 5-21.0-15.1 + [regex]$reg = $regExpressionTemperatureFirst + $dateFrom.Day + $regExpressionTemperatureSecond + $match = $reg.match($html) + + if (!$match.Success) + { + # температура не найдена + throw new-object Exception('Температура не найдена.') + } + + # считываем температуру + $T = $match.Groups[1].value + + # сохраняем температуру + $TempTable[$dateFrom.ToString()] = $T + + $dateFrom = $dateFrom.AddDays(1) + } + + return $TempTable + } + catch + { + throw new-object Exception('Ошибка получения среднесуточной температуры за указанный период. ', $Error[0].Exception) + } + } + + ########################################################################## + + # возвращает входные параметры + Function Arguments($inArgs) + { + try + { + # проверяем количество параметров + + if($inArgs.Length -eq 0) + { + throw new-object Exception('Отсутствуют параметры командной строки.') + } + + # возвращает введенное имя города + $gorod = $inArgs[0] + $gorod + + [DateTime]$dateTo = [System.DateTime]::Today.AddDays(-1) + [DateTime]$dateFrom = $dateTo + + + if($inArgs.Length -eq 2) + { + $DateTimeStr = $inArgs[1] + $DateTimeStr = $DateTimeStr.Split('-', [System.StringSplitOptions]::RemoveEmptyEntries) + + if($DateTimeStr.Length -ne 2) + { + throw new-object Exception('Период времени задан неверно.') + } + + # дата начало периода + if (![DateTime]::TryParse($DateTimeStr[0], [ref]$dateFrom)) + { + throw new-object Exception('Дата начала периода задана в неверном формате. Формат даты: dd.mm.yyyy') + } + + + # дата конца периода + if (![DateTime]::TryParse($DateTimeStr[1], [ref]$dateTo)) + { + throw new-object Exception('Дата окончания периода задана в неверном формате. Формат даты: dd.mm.yyyy') + } + } + + + # возвращаем дату начало/конца + $dateFrom + $dateTo + } + catch + { + throw new-object Exception('Ошибка разбора параметров коммандной строки. ', $Error[0].Exception) + } + } + + ########################################################################## + + # Функция подключается к серверу автоматизации и возвращает объект сервера + Function ConnectToServer() + { + try + { + Write-Host 'подключаемся к серверу по адресу ' $ServerAddress ':' $ServerPort + + $securePassword = [Lers.Networking.SecureStringHelper]::ConvertToSecureString($PassWord) + + $authenticationInfo = New-Object Lers.Networking.BasicAuthenticationInfo($Login, $securePassword) + + # подключаемся к серверу + $server = new-object Lers.LersServer + + $server.Connect($ServerAddress, $ServerPort, $authenticationInfo) + return $server + } + catch + { + throw new-object Exception('Не удалось подключится к серверу ЛЭРС УЧЕТ. ', $Error[0].Exception) + } + } + + ########################################################################## + + # функция сохраняет данные о температуре на сервере ЛЭРС УЧЕТ + # $server - сервер автоматизации + # $tempTable - таблица среднесуточных температур + Function SaveTemperatureToServer ($server, $tempTable) + { + Write-Host 'Cохраняем данные на сервере ЛЭРС УЧЕТ' + try + { + $str ='' + $keys = $tempTable.Keys + + $temperature = New-Object Lers.Data.OutdoorTemperatureRecord[] $keys.Count + $i = 0 + + foreach($key in $keys) + { + $dt = [DateTime]::Parse($key) + + $value = [string]$tempTable[$key] + + $separator = [System.Globalization.CultureInfo]::CurrentCulture.NumberFormat.NumberDecimalSeparator; + + $value = [Convert]::ToSingle($value.Replace(".",$separator)) + + $record = New-Object Lers.Data.OutdoorTemperatureRecord($dt) + $record.Value = $value + + $temperature[$i] = $record + + $i++ + } + + # сохранение данных на сервере + $server.OutdoorTemperature.Set($temperature) + } + catch + { + throw new-object Exception('Не удалось сохранить данные среднесуточной температуры на сервере ЛЭРС учет. ', $Error[0].Exception) + } + } + + ########################################################################## + # Точка входа + ########################################################################## + + try + { + Write-Host 'Запуск импорта данных среднесуточной температуры с сайта мониторинга погоды.' + + # проверяем параметры настройки скрипта + CheckParameters $url $ServerAddress $ServerPort $Login $PassWord + + #param[0] = город, param[1] = дата_начала, param[2] = дата_окончания + [object[]]$param = Arguments $Args + + Write-host 'Загружаем ресурс ' $url + + # загружаем html страницу + $reply = Get-WwwString $url + + # получаем ссылку на страницу, указанного города + $link = Get-CityUrl $reply $param[0] $url + + # загружаем таблицу с температурами наружного воздуха + $tempTable = Get-CityTemperature $param[1] $param[2] $link + + write-host 'Получены среднесуточные температуры.' + + # подключаемся к серверу ЛЭРС + $server = ConnectToServer + + # сохраняем температуру на сервере + SaveTemperatureToServer $server $tempTable + + Write-Host 'Импорт температур успешно завершен.' + } + catch + { + write-host 'Ошибка импорта температур. ' (GetFullExceptionMessage $Error[0].Exception) + exit + } + + ######################################################################## \ No newline at end of file diff --git a/KhvAdmDataAdapter/App_Code/Handler.cs b/KhvAdmDataAdapter/App_Code/Handler.cs new file mode 100644 index 0000000..60ceea8 --- /dev/null +++ b/KhvAdmDataAdapter/App_Code/Handler.cs @@ -0,0 +1,486 @@ +using System; +using System.Collections.Specialized; +using System.Configuration; +using System.IO; +using System.Text; +using System.Web; +using Lers.Data; +using Lers.Core; +using Lers.Utils; + +namespace Lers.Web.DataAdapter.KhvAdm +{ + /// + /// Реализует обработчик запроса на выдачу данных в формате экспорта, утвержденном администрацией г. Хабаровск + /// + internal class Handler: IHttpHandler + { + /// + /// Используется в качестве источника при протоколировании. + /// + private static readonly string CLASS_NAME = typeof(Handler).FullName; + + /// + /// Начальная дата для экспорта данных + /// Берется из параметра dateFrom + /// + private DateTime beginDate = new DateTime(DateTime.Today.Year, DateTime.Today.Month, 1); + + /// + /// Конечная дата для экспорта данных + /// Берется из параметра dateTo + /// + private DateTime endDate = DateTime.Now; + + /// Тип временных меток: 1 - часовые, 0 - суточные; -1 - и часовые и суточные + private int dataPeriodType = 0; + + /// + /// Экземпляр класса для подключения к серверу ЛЭРС УЧЕТ + /// + private LersServer server; + + /// + /// Протоколирует в файл + /// + private Logger logger; + + /// + /// Возвращает значение, позволяющее определить, может ли другой запрос использовать экземпляр класса IHttpHandler. + /// + bool IHttpHandler.IsReusable + { + get + { + return false; + } + } + + /// + /// Получает информацию о запросе + /// + /// Информация о запросе + private string GetRequestInfo() + { + if (HttpContext.Current == null || HttpContext.Current.Request == null) + return "<Не удалось получить дополнительную информацию о запросе>"; + + HttpRequest currentRequest = HttpContext.Current.Request; + + // Адрес, с которого пришёл запрос (может быть адрес прокси) + string publicAddress = currentRequest.ServerVariables["REMOTE_ADDR"]; + + // Локальный адрес компа, заполняется при перенаправлении запроса через прокси + string localAddress = currentRequest.ServerVariables["HTTP_X_FORWARDED_FOR"]; + + + StringBuilder info = new StringBuilder(); + + info.AppendFormat("IP-адрес запроса: {0}.\r\nИсходный IP-адрес запроса: {1}\r\n", publicAddress, localAddress); + + info.AppendFormat("Адрес web-страницы: {0}\r\n", currentRequest.Url); + + return info.ToString(); + } + + /// + /// Обрабатывает веб запрос. Исходная точка в HttpHandler + /// + /// Контекст Http запроса + void IHttpHandler.ProcessRequest(HttpContext context) + { + InitLogger(); + + try + { + string msg = "Получен запрос на экспорт данных в формате ДГК.\r\n" + GetRequestInfo(); + + LogInfo(msg); + + Init(); + + // Разбираем входные параметры + ParseInputParams(); + + // Экспортируем данные + ExportData(); + + if (context.Response.IsClientConnected) + LogInfo("Данные успешно отправлены."); + } + catch (ConfigurationErrorsException ex) + { + LogError(ex.Message); + } + catch (Lers.Networking.RequestTimeoutException exc) + { + LogError("Вышло время ожидания на выполнение операции.\r\n"); + } + catch (Lers.Networking.ServerConnectionException exc) + { + LogError("Ошибка при попытки установить соединение с сервером ЛЭРС УЧЕТ.\r\n"); + } + catch (Lers.Networking.AuthorizationFailedException exc) + { + LogError("Ошибка при попытки установить соединение с сервером ЛЭРС УЧЕТ.\r\n"); + } + catch (VersionMismatchException exc) + { + LogError("Ошибка при попытки установить соединение с сервером ЛЭРС УЧЕТ.\r\n"); + } + catch(Exception exc) + { + string msg = "Ошибка экспорта данных в формате ДГК. "; + LogError(msg); + throw; + } + finally + { + this.logger.LogDebug("Закрываем подключение...", CLASS_NAME); + + if(server != null && server.IsConnected) + server.Disconnect(2000); + + this.logger.Close(); + + context.Response.End(); + } + } + + #region Протоколирование + + /// + /// Протоколирует сообщение об ошибке + /// + /// Текст сообщения + private void LogError(string message) + { + this.logger.LogError("Dgk:\t" + message, CLASS_NAME); + } + + /// + /// Протоколирует информационное сообщение + /// + /// Текст сообщения + private void LogInfo(string message) + { + this.logger.LogMessage("Dgk:\t" + message, CLASS_NAME); + } + + /// + /// Протоколирует отладочное сообщение + /// + /// Текст сообщения + private void LogDebug(string message) + { + this.logger.LogDebug("Dgk:\t" + message, CLASS_NAME); + } + + /// + /// Протоколирует предупреждающее сообщение + /// + /// Текст сообщения + private void LogWarning(string message) + { + this.logger.LogWarning("Dgk:\t" + message, CLASS_NAME); + } + + /// + /// Инициализирует логгер + /// + private void InitLogger() + { + // Считываем путь до журнала протокола + string logFile = System.Configuration.ConfigurationManager.AppSettings["DataAdapterFileLogPath"] ?? ""; + + if (logFile == "") + logFile = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + @"\LERS\Logs\Web\DataAdapter.log"; + + // Если каталога нет, создаем его + if (!Directory.Exists(Path.GetDirectoryName(logFile))) + Directory.CreateDirectory(Path.GetDirectoryName(logFile)); + + bool debug = false; + + // Считываем значение включено ли протоколирование отладочных сообщений + string fileLogDebug = System.Configuration.ConfigurationManager.AppSettings["DataAdapterFileLogDebug"] ?? ""; + + if (fileLogDebug == "1") + debug = true; + + this.logger = Logger.Create(logFile); + + this.logger.LogDebugMessages = debug; + } + + #endregion + + #region Инициализация и разбор входных параметров + + /// + /// Инициализация + /// + private void Init() + { + LogDebug("Инициализация..."); + + // Отключаем буферизацию + HttpContext.Current.Response.BufferOutput = false; + + // ServerAddress + string serverAddress = ConfigurationManager.AppSettings["ServerAddress"] ?? ""; + + if (serverAddress == "") + serverAddress = "localhost"; + + // ServerPort + int serverPort; + + if (!Int32.TryParse(ConfigurationManager.AppSettings["ServerPort"], out serverPort)) + serverPort = 10000; + + // Login + string login = ConfigurationManager.AppSettings["AdmLogin"]; + + if(string.IsNullOrEmpty(login)) + throw new ConfigurationErrorsException("В конфигурации приложения отсутствует параметр: AdmLogin"); + + // Password + string password = ConfigurationManager.AppSettings["AdmPassword"]; + + if(string.IsNullOrEmpty(password)) + throw new ConfigurationErrorsException("В конфигурации приложения отсутствует параметр: AdmPassword"); + + LogDebug("Инициализация завершена."); + + // Соединяемся + + LogDebug("Соединение с сервером ЛЭРС УЧЕТ..."); + + this.server = new LersServer(); + + this.server.VersionMismatch += server_VersionMismatch; + + System.Security.SecureString securePassword = Networking.SecureStringHelper.ConvertToSecureString(password); + + this.server.Connect(serverAddress, (ushort)serverPort, new Networking.BasicAuthenticationInfo(login, securePassword)); + + LogDebug("Соединение установлено."); + } + + /// + /// Обработчик ошибки несовместимости версий сервера и фреймворка + /// + void server_VersionMismatch(object sender, VersionMismatchEventArgs e) + { +#if DEBUG + e.Ignore = true; +#endif + } + + /// + /// Разбор входных параметров + /// + private void ParseInputParams() + { + NameValueCollection paramCollection = HttpContext.Current.Request.Params; + + DateTime result; + + // Начальная дата + if (TryParseDateParam(paramCollection, "dateFrom", out result)) + beginDate = result; + + // Конечная дата + if (TryParseDateParam(paramCollection, "DateTo", out result)) + endDate = result; + + // Из регламента: + // ДГК может в любое время выполнять запросы данных за произвольный период, + // но на глубину не более чем два месяца, включая отчетный. + + // Комментарий Клауса: + // Если запрашивается большой интервал, то подрезаем его с начала, + // иначе получаем исключение "Слишком большой размер пакета ( > 20МБ ) + + // Если запрашивается интервал больше 3 месяцев, подрезаем его с начала. + if(((TimeSpan)endDate.Subtract(beginDate)).TotalDays > 60) + { + beginDate = endDate.Subtract(new TimeSpan(60, 0, 0, 0)); + + LogWarning("Интервал выборки данных превышает 60 дней. Дата начала интервала заменена на " + beginDate); + } + + //Если интервал не корректный то устанавливаем интервал по умолчанию + if (beginDate > endDate) + { + beginDate = new DateTime(DateTime.Today.Year, DateTime.Today.Month, 1); + + endDate = DateTime.Now; + + LogWarning("Конечная дата периода превышает начальную. Параметры были установлены по умолчанию."); + } + + // Тип данных + if (!Int32.TryParse(paramCollection["PeriodType"], out dataPeriodType)) + dataPeriodType = -1; // Суточные и часовые + + // По умолчанию выдаем и суточные и часовые данные + if (dataPeriodType != -1 && dataPeriodType != 0 && dataPeriodType != 1) + dataPeriodType = -1; + + LogDebug(String.Format("параметры запроса: beginDate = {0}, endDate = {1}, dataPeriodType = {2}", + beginDate, endDate, dataPeriodType)); + } + + /// + /// Пытается разобрать параметр дата задающую начало и конец периода + /// + /// Коллекция параметров, полученная из HttpContext.Request.Params + /// Имя параметра для разбора + /// Дата полученная из указанного параметра + /// Результат разбора: true - успех, false - провал. + private bool TryParseDateParam(NameValueCollection paramCollection, string paramName, out DateTime result) + { + result = new DateTime(); + + // Проверяем есть ли вообще параметры, есть ли необходимый нам параметр, не пустой ли он + if (paramCollection.Count > 0 && + !String.IsNullOrEmpty(paramCollection[paramName])) + { + if (DateTime.TryParseExact(paramCollection[paramName], "yyyyMMddHHmm", null, System.Globalization.DateTimeStyles.AssumeLocal, out result)) + return true; + + if (DateTime.TryParseExact(paramCollection[paramName], "yyyyMMdd", null, System.Globalization.DateTimeStyles.AssumeLocal, out result)) + return true; + } + + return false; + } + + #endregion + + #region Выдача данных + + /// + /// Экспортирует данные потребления указанного типа + /// + /// Точка учета + /// Тип данных: true - суточные, false - часовые + private void ExportConsumption(MeasurePoint measurePoint, bool isDay) + { + // TODO: Сократить количество запросов на сервер, одновременно запрашивая суточные и часовые данные + + // Получаем данные потребления по точке учета + MeasurePointConsumptionRecordCollection consumption = measurePoint.Data.GetConsumption(beginDate, endDate, ((isDay) ? DeviceDataType.Day : DeviceDataType.Hour)); + + // Измеряемый ресурс + int systemTypeId = (int)measurePoint.SystemType; + + // Номер точки учета + int number = measurePoint.Number ?? 0; + + string output = ""; + + foreach (MeasurePointConsumptionRecordWater dataRecord in consumption) + { + if (dataRecord.M_in == null) + continue; + + // Накапливаем данные в строке + output = number + ";" + + ((isDay) ? dataRecord.DateTime.ToString("yyyy-MM-dd") : dataRecord.DateTime.ToString("yyyy-MM-dd HH:mm")) + + ";2;" + + systemTypeId + ";" + + (dataRecord.T_in ?? 0) + ";" + + (dataRecord.T_out == null ? "" : dataRecord.T_out.ToString()) + ";" + + (dataRecord.M_in ?? 0) + ";" + + (dataRecord.M_out == null ? "" : dataRecord.M_out.ToString()) + ";" + + (dataRecord.Q_in == null? "" : dataRecord.Q_in.ToString()) + ";" + + (dataRecord.Q_out == null ? "" : dataRecord.Q_out.ToString()) + ";" + + (dataRecord.P_in == null ? "" : dataRecord.P_in.ToString()) + ";" + + (dataRecord.P_out == null ? "" : dataRecord.P_out.ToString()) + ";" + + (dataRecord.WorkTime == null ? "" : dataRecord.WorkTime.ToString()) + ";" + + Convert.ToInt32(isDay) + ";\n"; + + // Выдаем браузеру + HttpContext.Current.Response.Write(output); + } + } + + /// + /// Отправляет заголовок + /// + private void SendHeader() + { + HttpResponse response = HttpContext.Current.Response; + + // Определяем имя файла + string fileName = "" + ((beginDate != DateTime.MinValue) ? beginDate.ToString("yyyyMMddHHmm") : "") + + "-" + ((endDate != DateTime.MinValue) ? endDate.ToString("yyyyMMddHHmm") : "") + + ((dataPeriodType > -1) ? "_" + dataPeriodType : "") + + ".csv"; + + // Подготавливаем заголовок + // Ставим в качестве ответа, файл в кодировке по умолчанию + response.ContentEncoding = System.Text.Encoding.Default; + response.ContentType = "application/x-download"; + response.AddHeader("Content-Disposition", "attachment; filename=" + HttpUtility.UrlEncode(fileName)); + + // Выдаем браузеру заголовок данных потребления + response.Write("MeasurePointID;DataDate;DataSource;ResourceTypeID;T_in;T_out;M_in;M_out;H_in;H_out;P_in;P_out;WorkTime;IsDay\n"); + } + + /// + /// Экспортирует данные потребления + /// + private void ExportData() + { + LogDebug("Отправка данных для администрации г. Хабаровска в ответ на запрос..."); + + SendHeader(); + + MeasurePoint[] measurePoints = this.server.MeasurePoints.GetList(MeasurePointType.Regular); + + // Выдаем все суточные данные потребления + if (dataPeriodType == 0 || dataPeriodType == -1) + { + foreach (MeasurePoint measurepoint in measurePoints) + { + // Выгружаем данные только по воде + if (measurepoint.SystemType != SystemType.ColdWater && measurepoint.SystemType != SystemType.HotWater && measurepoint.SystemType != SystemType.Heat) + continue; + + ExportConsumption(measurepoint, true); + + if (!HttpContext.Current.Response.IsClientConnected) + { + LogDebug("Клиент был отключен от веб-сервера."); + return; + } + } + } + + // Выдаем все часовые данные потребления + if (dataPeriodType == 1 || dataPeriodType == -1) + { + foreach (MeasurePoint measurepoint in measurePoints) + { + // Выгружаем данные только по воде + if (measurepoint.SystemType != SystemType.ColdWater && measurepoint.SystemType != SystemType.HotWater && measurepoint.SystemType != SystemType.Heat) + continue; + + ExportConsumption(measurepoint, false); + + if (!HttpContext.Current.Response.IsClientConnected) + { + LogDebug("Клиент был отключен от веб-сервера."); + return; + } + } + } + } + + #endregion + } +} \ No newline at end of file diff --git a/KhvAdmDataAdapter/App_Code/Logger.cs b/KhvAdmDataAdapter/App_Code/Logger.cs new file mode 100644 index 0000000..5d1e206 --- /dev/null +++ b/KhvAdmDataAdapter/App_Code/Logger.cs @@ -0,0 +1,267 @@ +using System; +using System.IO; +using System.Text; +using System.Threading; + +namespace Lers.Utils +{ + /// + /// Протоколирует сообщения в файл. + /// + public class Logger : IDisposable + { + /// + /// Тип сообщения в журнале. + /// + private enum LogType + { + /// + /// Отладочное сообщение. + /// + Debug = 0, + + /// + /// Информационное сообщение. + /// + Info = 1, + + /// + /// Предупреждение. + /// + Warning = 2, + + /// + /// Ошибка. + /// + Error = 3, + } + + private Stream stream; + + private StreamWriter streamWriter; + + /// + /// Определяет, нужно ли протоколировать отладочные сообщения. + /// + public bool LogDebugMessages { get; set; } + + /// + /// Определяет, нужно ли протоколировать идентификатор потока + /// + public bool LogThreadId { get; set; } + + /// + /// Инициализирует новый экземпляр класса. + /// + /// Поток записи. + private Logger(Stream stream) + { + if (stream == null) + throw new ArgumentNullException("stream"); + + this.stream = stream; + this.streamWriter = new StreamWriter(stream, Encoding.UTF8); + + WritePreamble(); + } + + /// + /// Создает новый экземпляр, протоколирующий сообщения в указанный файл. + /// + /// Имя файла журнала. + /// Возвращает экземпляр . + public static Logger Create(string fileName) + { + // Если папка не существует, то создаем её. + + string logDirectory = Path.GetDirectoryName(fileName); + + if (!Directory.Exists(logDirectory)) + { + Directory.CreateDirectory(logDirectory); + } + + // Открываем файловый поток на запись. Если файл уже существует, то будем дописывать в него, + // если нет - создаем новый файл. + + FileMode fileMode; + + if (File.Exists(fileName)) + fileMode = FileMode.Append; + else + fileMode = FileMode.CreateNew; + + FileStream stream = new FileStream(fileName, fileMode, FileAccess.Write, FileShare.Read); + + // Создаем новый экземпляр класса и возвращаем его. + + try + { + return new Logger(stream); + } + catch + { + // При ошибке закрываем файловый поток. + + stream.Close(); + + throw; + } + } + + /// + /// Закрывает файл журнала. + /// + public void Close() + { + Dispose(); + } + + /// + /// Протоколирует информационное сообщение. + /// + /// Текст сообщения. + /// Источник сообщения. + public void LogMessage(string message, string source) + { + Log(LogType.Info, message, source); + } + + /// + /// Протоколирует предупреждающее сообщение. + /// + /// Текст сообщения. + /// Источник сообщения. + public void LogWarning(string message, string source) + { + Log(LogType.Warning, message, source); + + } + + /// + /// Протоколирует сообщение об ошибке. + /// + /// Текст сообщения. + /// Источник сообщения. + public void LogError(string message, string source) + { + Log(LogType.Error, message, source); + } + + /// + /// Протоколирует отладочное. + /// + /// Текст сообщения. + /// Источник сообщения. + public void LogDebug(string message, string source) + { + // Отладочные сообщения протоколируем только если включено. + + if (this.LogDebugMessages) + Log(LogType.Debug, message, source); + } + + /// + /// Протоколирует сообщение в журнал. + /// + /// Важность сообщения. + /// Текст сообщения. + /// Источник сообщения. + private void Log(LogType logType, string message, string source) + { + CheckDisposed(); + + if (message == null) + throw new ArgumentNullException("message"); + + if (source == null) + throw new ArgumentNullException("source"); + + // Сонхронизируем доступ из разных потоков. + + lock (this.streamWriter) + { + // Записываем строку и очищаем буфер, чтобы строка сразу появилась в лог-файле. + + if(this.LogThreadId) + this.streamWriter.WriteLine("{0:dd-MM-yyyy HH:mm:ss.fff}\t{1}:{2:000}\t{3}\t\t\t{4}", + DateTime.Now, FormatLogType(logType), Thread.CurrentThread.ManagedThreadId, message, source); + else + this.streamWriter.WriteLine("{0:dd-MM-yyyy HH:mm:ss.fff}\t{1}\t{2}\t\t\t{3}", DateTime.Now, FormatLogType(logType), message, source); + + this.streamWriter.Flush(); + } + + // В отладочной версии дополнительно протоколируем в окно Output отладчика. + +#if DEBUG + System.Diagnostics.Debugger.Log((int)logType, source, message + "\r\n"); +#endif + } + + /// + /// Записывает заголовок в файл журнала. + /// + private void WritePreamble() + { + this.streamWriter.WriteLine("========================================"); + this.streamWriter.WriteLine("== Журнал открыт " + DateTime.Now.ToString("dd-MM-yyyy HH:mm:ss.fff")); + this.streamWriter.WriteLine("========================================"); + + this.streamWriter.Flush(); + } + + private static string FormatLogType(LogType logType) + { + switch (logType) + { + case LogType.Debug: + return "D"; + + case LogType.Info: + return "I"; + + case LogType.Warning: + return "W"; + + case LogType.Error: + return "E"; + + default: + throw new ArgumentOutOfRangeException("logType"); + } + } + + #region IDisposable + + private bool isDisposed = false; + + /// + /// Проверяет, что экземпляр не уничтожен. + /// + private void CheckDisposed() + { + if (this.isDisposed) + throw new ObjectDisposedException("Использование экземпляра невозможно, т.к. объект был закрыт."); + } + + /// + /// Освобождает ресурсы. + /// + public void Dispose() + { + if (!this.isDisposed) + { + this.streamWriter.Close(); + this.stream.Close(); + + this.streamWriter = null; + this.stream = null; + + this.isDisposed = true; + } + } + + #endregion + } +} diff --git a/KhvAdmDataAdapter/KhvAdmDataAdapter.csproj b/KhvAdmDataAdapter/KhvAdmDataAdapter.csproj new file mode 100644 index 0000000..5688900 --- /dev/null +++ b/KhvAdmDataAdapter/KhvAdmDataAdapter.csproj @@ -0,0 +1,85 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {0C6B7048-E464-439D-82CD-99532A932E5A} + {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + Lers.Web.DataAdapter.KhvAdm + Lers.KhvAdmDataAdapter + v4.0 + + + 3.5 + + + false + + + true + full + false + bin\ + DEBUG;TRACE + prompt + 4 + Off + + + pdbonly + true + bin\ + TRACE + prompt + 4 + + + + ..\..\Lers.System\bin\x86\Debug\Lers.System.dll + + + + + + + + + + + + + + + + + + + + + + False + False + 89 + / + + + False + False + + + False + + + + + \ No newline at end of file diff --git a/KhvAdmDataAdapter/KhvAdmDataAdapter.sln b/KhvAdmDataAdapter/KhvAdmDataAdapter.sln new file mode 100644 index 0000000..44e3380 --- /dev/null +++ b/KhvAdmDataAdapter/KhvAdmDataAdapter.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KhvAdmDataAdapter", "KhvAdmDataAdapter.csproj", "{0C6B7048-E464-439D-82CD-99532A932E5A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0C6B7048-E464-439D-82CD-99532A932E5A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0C6B7048-E464-439D-82CD-99532A932E5A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0C6B7048-E464-439D-82CD-99532A932E5A}.Debug|x64.ActiveCfg = Debug|Any CPU + {0C6B7048-E464-439D-82CD-99532A932E5A}.Debug|x86.ActiveCfg = Debug|Any CPU + {0C6B7048-E464-439D-82CD-99532A932E5A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0C6B7048-E464-439D-82CD-99532A932E5A}.Release|Any CPU.Build.0 = Release|Any CPU + {0C6B7048-E464-439D-82CD-99532A932E5A}.Release|x64.ActiveCfg = Release|Any CPU + {0C6B7048-E464-439D-82CD-99532A932E5A}.Release|x86.ActiveCfg = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/KhvAdmDataAdapter/Properties/AssemblyInfo.cs b/KhvAdmDataAdapter/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..9b874e4 --- /dev/null +++ b/KhvAdmDataAdapter/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// Управление общими сведениями о сборке осуществляется с помощью +// набора атрибутов. Измените значения этих атрибутов, чтобы изменить сведения, +// связанные со сборкой. +[assembly: AssemblyTitle("ЛЭРС УЧЕТ. Адаптер данных для администрации г. Хабаровска")] +[assembly: AssemblyDescription("Выполняет преобразование данных в формат экспорта администрации г. Хабаровска")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("ООО \"Хабаровский центр энергоресурсосбережения\"")] +[assembly: AssemblyCulture("")] +[assembly: AssemblyProduct("Система диспетчеризации ЛЭРС УЧЕТ")] +[assembly: AssemblyCopyright("© 2000-2011, Хабаровский центр энергоресурсосбережения")] +[assembly: AssemblyTrademark("Внимание: Данная компьютерная программа защищена законами об авторских правах и международными соглашениями. Незаконное воспроизведение или распространения данной программы или любой ее части влечет гражданскую и уголовную ответственность.")] + +// Параметр ComVisible со значением FALSE делает типы в сборке невидимыми +// для COM-компонентов. Если требуется обратиться к типу в этой сборке через +// COM, задайте атрибуту ComVisible значение TRUE для этого типа. +[assembly: ComVisible(false)] + +// Следующий GUID служит для идентификации библиотеки типов, если этот проект будет видимым для COM +[assembly: Guid("a0027496-d7ea-4530-9e78-3033f1d4e2c7")] + +// Сведения о версии сборки состоят из следующих четырех значений: +// +// Основной номер версии +// Дополнительный номер версии +// Номер построения +// Редакция +// +// Можно задать все значения или принять номер построения и номер редакции по умолчанию, +// используя "*", как показано ниже: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/KhvAdmDataAdapter/web.config b/KhvAdmDataAdapter/web.config new file mode 100644 index 0000000..09dd29b --- /dev/null +++ b/KhvAdmDataAdapter/web.config @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/README.md b/README.md index e4a247d..824641c 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,9 @@ # samples Примеры использования Lers Framework + +Проекты: + +AttributesSample Работа с атрибутами. Консольное приложение. +GetDataSample Получение данных из ЛЭРС УЧЁТ. Консольное приложение. +ImportTemperature Импорт температуры наружного воздуха в ЛЭРС УЧЁТ. +KhvAdmDataAdapter Экспорт данных из ЛЭРС УЧЁТ. Обработчик HttpHandler для веб-сайта