В данном разделе вы познакомитесь с менеджером API C# с помощью некоторых примеров исполняемого исходного кода. Полный исходный код примера приведен последним.
- Создание нового менеджера
Следуйте инструкциям главы «Создание менеджера C# API» и удалите исходный код класса «Program». Теперь ваш класс должен выглядеть следующим образом:
using System; using System.Threading.Tasks; namespace GettingStarted { class Samples { static OaManager _managerInstance = null; public Samples() { PrintSampleUsage(); } public void PrintSampleUsage() { Console.Clear(); Console.WriteLine("Нажмите клавиши 1 – 9, чтобы запустить соответствующий пример кода:"); Console.WriteLine("1 Создать новый менеджер"); Console.WriteLine("2 Установить соединение"); Console.WriteLine("3 Считать текущее значение из "КАСКАД Цифра" (синхронно и асинхронно)"); Console.WriteLine("4 Асинхронно записать значение в "КАСКАД Цифра""); Console.WriteLine("5 Запросить изменения значений"); Console.WriteLine("6 Создать точку данных"); Console.WriteLine("7 Запросить текущие алармы с использованием выражения SELECT"); Console.WriteLine("8 Запросить исторические значения"); Console.WriteLine("9 Полный пример"); Приставка.WriteLine ("ESC Выхов"); } } }
- Подключение
В следующем примере устанавливается соединение с проектом «КАСКАД Цифра» с помощью заданных программных аргументов, предоставляемых командной строкой. Скопируйте исходный код в пустой проект.
class Program using System; using System.Threading.Tasks; namespace GettingStarted { class Samples { static OaManager _managerInstance = null; public Samples() { PrintSampleUsage(); } public void PrintSampleUsage() { Console.Clear(); Console.WriteLine("Нажмите клавиши 1 – 9, чтобы запустить соответствующий пример кода:"); Console.WriteLine("1 Создать новый менеджер"); Console.WriteLine("2 Установить соединение"); Console.WriteLine("3 Считать текущее значение из "КАСКАД Цифра" (синхронно и асинхронно)"); Console.WriteLine("4 Асинхронно записать значение в "КАСКАД Цифра""); Console.WriteLine("5 Запросить изменения значений"); Console.WriteLine("6 Создать точку данных"); Console.WriteLine("7 Запросить текущие алармы с использованием выражения SELECT"); Console.WriteLine("8 Запросить исторические значения"); Console.WriteLine("9 Полный пример"); Приставка.WriteLine ("ESC Выхов"); } // Пример 1: создание объекта менеджера public OaManager ManagerInstance { get { // Шаблон проектирования "Одиночка" (Синглтон) гарантирует, что будет создан только один объект менеджера if (_managerInstance == null) _managerInstance = OaSdk.CreateManager(); return _managerInstance; } } // Пример 2: установка соединения с проектом "КАСКАД Цифра" public async Task<int>EstablishConection(string[] args) { // Инициализация конфигурации менеджера ManagerInstance.Init(ManagerSettings.DefaultApiSettings, args); // Запуск менеджера await ManagerInstance.StartAsync(); // Сообщение о подключении. Консольный вывод идет прямо в средство просмотра журналов "КАСКАД Цифра" Console.WriteLine("Connection to project established"); return 1; } } }
- Чтение текущих значений «КАСКАД Цифра»
В первом примере считывается текущее значение с помощью синхронной версии функции GetDpValue() из подключенного проекта «КАСКАД Цифра». Запустите пример, скопировав код в класс Program, и вызовите ReadValuesExample() из функции main ().
// Пример 3: считывание текущего значения из "КАСКАД Цифра" public void ReadValuesExample() { // Получение доступа к ProcessValues OaProcessValues valueAccess = ManagerInstance.ProcessValues; // Вызов GetDpValue через объект "Access" OaDpValueItem myFloatItem = valueAccess.GetDpValue("ExampleDP_Arg1."); // Чтение свойства DpValue из экземпляра OaDpValue double myFloatVal1 = myFloatItem.DpValue; // Это также можно было бы сделать в одной строке с double myFloatVal2 = valueAccess.GetDpValue("ExampleDP_Arg1.").DpValue; // Чтение более одного значения string[] myValuesToRead = { "ExampleDP_Arg1.", "ExampleDP_AlertHdl1." }; var myResultCollection = valueAccess.GetDpValue(myValuesToRead); // Проход циклом по всем ответам foreach (var item in myResultCollection) { Console.WriteLine(item.DpValue.ToString()); } }
Второй фрагмент демонстрирует считывание текущего значения с помощью асинхронной версии функции GetDpValue() из подключенного проекта «КАСКАД Цифра». Запустите пример, скопировав код в класс Program и вызвав ReadValuesExampleAsync().Wait() из функции main().
// Пример 3b: асинхронное считывание текущих значений из "КАСКАД Цифра" public async Task ReadValuesExampleAsync() { // Получение доступа к ProcessValues OaProcessValues valueAccess = ManagerInstance.ProcessValues; // Вызов GetDpValue через объект "Access" OaDpValueItem myFloatItem = await valueAccess.GetDpValueAsync("ExampleDP_Arg1."); // Чтение свойства DpValue из экземпляра OaDpValue double myFloatVal1 = myFloatItem.DpValue; // Без await асинхронное значение возвращает объект Task, который можно было бы ожидать позже Task<OaDpValueItem> myTaskToWait = valueAccess.GetDpValueAsync("ExampleDP_Arg1."); // Здесь можно сделать какие-то действия, пока идет ожидание значения Console.WriteLine("Во время ожидания ожидания можно сделать какие-то действия"); // Дождитесь результата и получите значение результата напрямую var myFloatIVal2 = (await myTaskToWait).DpValue; }
- Запись значений в «КАСКАД Цифра»
Следующий код демонстрирует запись значения float 4.2 в точку данных «ExampleDP_Arg1.” Запустите пример, скопировав код в класс Program и вызвав WriteValuesExampleAsync().Wait() из функции main ().
// Пример 4. Запись значений в "КАСКАД Цифра" public async Task WriteValuesExampleAsync() { // Получение доступа к ProcessValues OaProcessValues valueAccess = ManagerInstance.ProcessValues; // Вызов SetDpValue через объект "Access". SetDpValue ждет ответа от // менеджера событий await valueAccess.SetDpValueAsync("ExampleDP_Arg1.", 4.2); // Вызов FireDpValue. FireDpValue не ждет ответа от менеджера событий // (поэтому асинхронный вариант не нужен) valueAccess.FireDpValue("ExampleDP_Arg1.", 77.2); // Установить набор значений с определенным временем await valueAccess.SetDpValueAsync(DateTime.Now.AddSeconds(2), new Tuple<string, OaVariant>("ExampleDP_Arg1.", (double)7.7), new Tuple<string, OaVariant>("ExampleDP_AlertHdl1.", (bool)false)); }
- Запрос изменений значений
Следующий пример демонстрирует оформление подписки на изменения значений и меток времени точек данных «ExampleDP_Arg1.» и «ExampleDP_Arg2.”. Запустите пример, скопировав код в класс Program и вызвав SubscribeOnValueChangesExampleAsync().Wait() из функции main ().
// Пример 5: запрос изменений значений public async Task SubscribeOnValueChangesExampleAsync() { // Получение доступа к ProcessValues OaProcessValues valueAccess = ManagerInstance.ProcessValues; // Создать объект "Subscription" OaDpValueSubscription mySubscription = valueAccess.CreateDpValueSubscription(); // Добавить точки данных для подписки на них mySubscription.AddDp("ExampleDP_Arg1."); mySubscription.AddDp("ExampleDP_Arg1.:_online.._stime"); mySubscription.AddDp("ExampleDP_Arg2."); mySubscription.AddDp("ExampleDP_Arg2.:_online.._stime"); // Определите функцию делегата для события изменения значения. Можно сделать так, как показано здесь. //Либо в виде лямбда-функции, либо в виде отдельной функции mySubscription.SingleValueChanged += (vcsender, vce) => { if (vce.IsAnswer) Console.WriteLine("Первый ответ: " + vce.Value.DpValue.ToString()); else Console.WriteLine("Измененное значение: " + vce.Value.DpValue.ToString()); }; // Если FireChangedEventForAnswer имеет значение true, то ValueChangedEvent также срабатывает для первого ответа mySubscription.FireChangedEventForAnswer = true; // Активируйте подписку и в качестве дополнительной опции дождитесь первого ответа в качестве результирующего значения var FirstAnswerItem = await mySubscription.StartAsync(); // Измените значение одного DPE, чтобы вызвать событие подписки await valueAccess.SetDpValueAsync("ExampleDP_Arg1.", 100.1); await mySubscription.StopAsync(); }
- Создание точки данных
Следующий код демонстрирует создание новой точки данных «myNewTestDp». Если точка данных уже существует, она автоматически удаляется. Запустите пример, скопировав код в класс Program и вызвав ModifyDataModelExample().Wait() из функции main ().
// Пример 6: Создание точки данных public async Task ModifyDataModelExample() { // Получение доступа к ProcessModel OaProcessModel dataModel = ManagerInstance.ProcessModel; // Проверьте, существует ли уже точка данных "myNewTestDp", и в этом случае удалите ее if (await dataModel.IsDpPathExistingAsync("myNewTestDp")) await dataModel.DeleteDpAsync("myNewTestDp"); // Создание "myNewTestDp" await dataModel.CreateDpAsync("myNewTestDp", "ExampleDP_Float"); }
- Запрос текущих алармов с использованием выражения SELECT
Этот фрагмент кода запрашивает текущие алармы. Запустите пример, скопировав код в класс Program и вызвав AlertQuerySubscriptionExample().Wait() из функции main ().
// Пример 7: запрос текущих алармов с использованием выражения SELECT EventHandler<OaQuerySubscriptionChangedEventArgs> myAlertChangedEvent = delegate (object sender, OaQuerySubscriptionChangedEventArgs args) { for (int iLoop = 0; iLoop < args.Result.GetRecordCount(); iLoop++) { var atime = args.Result.GetData(iLoop, 1); var avalue = args.Result.GetData(iLoop, 2); Console.WriteLine("Запись " + iLoop + ": Время аларма: " + atime.ToString() + "значение: " + avalue.ToString()); } }; public async Task AlertQuerySubscriptionExample() { // Получение доступа к алармам var alerts = ManagerInstance.Alerts; // Создание подписки AlertQuerySubscription var alertSubscription = alerts.CreateAlertQuerySubscription(); // Настройка AlertQuerySubscription; // Установите AlertChangedEvent, назначив обработчик SystemEventHandler; alertSubscription.ValueChanged += myAlertChangedEvent; // Триггер ChangedEvent также сработает и для первого ответа alertSubscription.FireChangedEventForAnswer = true; // Ниже будет задана строка запроса alertSubscription.SetQuery("SELECT ALERT '_alert_hdl.._value' FROM '*.**'"); // Запуск AlertQuerySubscription await alertSubscription.StartAsync(); }
- Запрос исторических значений
Код запрашивает исторические значения в определенном временном диапазоне. Запустите пример, скопировав код в класс Program и вызвав QueryHistoricalValuesExample().Wait() из функции main ().
// Пример 8: запрос исторических значений public async Task QueryHistoricalValuesExample() { // Получение доступа к ValueHistory var histAccess = ManagerInstance.ValueHistory; DateTime tStart = DateTime.Now; // запоминаем начальное время // Сымитируем 5 значений с помощью SetValue for (int i = 1; i <= 5; i++) { // использование ProcessValues напрямую без временной переменной ManagerInstance.ProcessValues.SetDpValue("ExampleDP_Rpt1.", (double)i); } DateTime tEnd = DateTime.Now; // remember the end time // Запрос исторических данных var myResult = await histAccess.GetDpValuePeriodAsync(tStart, tEnd, "ExampleDP_Rpt1."); foreach (var TimedValue in myResult) { Console.WriteLine("Получено: " + TimedValue.DpName.ToString() + " Значение: " + TimedValue.DpValue.ToString() + " Метка времени: " + TimedValue.SourceTime.ToString()); } }
- Полный пример
Следующий пример содержит все ранее перечисленные блоки кода:
// Пример 9: полный public void CompleteSample(string[] args) { // Получение локальной ссылки на объект менеджера OaManager myManager = ManagerInstance; // Инициализация конфигурации менеджера myManager.Init(ManagerSettings.DefaultApiSettings, args); // Запуск менеджера и подключение к проекту OA с заданной конфигурацией myManager.Start(); // Чтение из конфигурационного файла секции myCsTest. // ReadString(section, key, defaultval) OaConfigurationFile file = new OaConfigurationFile(); string dpNameSet = file.ReadString("myCsTest", "dpNameSet", "ExampleDP_Arg2."); string dpNameConnect = file.ReadString("myCsTest", "dpNameConnect", "ExampleDP_Arg1."); // Получение доступа к ProcessValues var valueAccess = myManager.ProcessValues; // Создание объекта подписки var mySubscription = valueAccess.CreateDpValueSubscription(); // Добавление точки данных для подписки mySubscription.AddDp(dpNameConnect); // Определение лямбда-функции для события изменения значения. Может быть сделано в виде отдельной функции mySubscription.SingleValueChanged += (vcsender, vce) => { // В случае ошибки vce.Value может быть null if (vce.Value == null) return; Console.WriteLine("Полученное значение: " + vce.Value.DpValue.ToString() + " для DPE: " + vce.Value.DpName.ToString()); //Установить полученное значение для DPE с помощью dpNameSet valueAccess.SetDpValue(dpNameSet, vce.Value.DpValue.ToDouble()); Console.WriteLine("Установлено значение: " + vce.Value.DpValue.ToString() + "в DPE: " + dpNameSet); }; // Если FireChangedEventForAnswer имеет значение true, то ValueChangedEvent также срабатывает для первого ответа mySubscription.FireChangedEventForAnswer = true; // Активируйте подписку и в качестве дополнительной опции дождитесь первого ответа в качестве результирующего значения mySubscription.StartAsync(); } } }