Форум программистов, компьютерный форум, киберфорум
АСУ ТП, промэлектроника
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.69/193: Рейтинг темы: голосов - 193, средняя оценка - 4.69
54 / 54 / 2
Регистрация: 30.05.2014
Сообщений: 83

OPC клиент (OPC_DA v2.05) для платформы NET

12.10.2014, 22:35. Показов 46020. Ответов 51
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Предлагаю следующую библиотеку для обмена данными с OPC сервером в приложении NET.

Библиотека "OPC_NET" представляет OPC клиент для платформы NET и предназначена для легкого обмена с любыми OPC серверами поддерживающими стандарт OPC_DA v2.05. Основана на SDK OpcNetApi организации OPC Foundation - разработчика стандарта.
Данные для обмена объявляются в файле типа xlsx. Данные читаются и пишутся по именам заданным в этом файле.

Пример работы:

1. Заполнение таблицы сигналов



2. Соединение с сервером
C#
1
2
3
4
5
6
7
8
  // создаем клиент
   OPC_NET.OPCclient cl = new OPC_NET.OPCclient();
 
  // объявляем переменные     
   cl.Init(@".\TableSignal.xlsx");
 
  // запрос на соединение с сервером
    int er =  cl.ConnectOpcServer(_ipAddrOPCserver, _nameOPCserver, _timeUpdDataOPCserver);
3. Читаем значения переменных:
C#
1
2
3
4
5
6
7
8
9
       bool err;
           
    bool val0 =  cl.ReadBool("enaFW", out err);
 
    int val1 =  cl.ReadInt16("driveFlt", out err);
 
    int val2 =  cl.ReadInt32("sensorFlt", out err);
 
    double val3 = cl.ReadReal("pressure", out err);
4. Пишем значения переменных:
C#
1
2
3
4
5
    bool err;
           
     cl.WriteInt16("dag", 34, out err);
 
     cl.WriteBool("sensEna", true, out err);

Скачать (исходник и мануал прилагаются):OPC_NET_RUS_V1.0.rar

PS: буду благодарен, если кто поделится этим чудом - ".NET4.0(WCF)" от OPC Foundation (https://opcfoundation.org/deve... et-4-0-wcf). Сразу перепишу либу на новый лад.

Изменения версии 1.11:
- переделаны события изменения данных: удалены события конкретных типов и создано общее событие – содержащее информацию обо всех измененных переменных;
- в классе Items добавлены несколько методов для коллекции объектов;
- открыты перечисления для входных числовых значений;
- переименованы некоторые объекты;

Скачать (исходник и мануал прилагаются): OPC_NET_RUS_V1.11.rar

Прошу добавить в заголовок темы, а то сам тему изменить не могу.
5
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
12.10.2014, 22:35
Ответы с готовыми решениями:

OPC клиент для сохранения данных с OPC сервера
Добрый день! Подскажите библиотеку для создания OPC клиента или возможно есть готовый OPC клиент, сохраняющий опрошенные данные?

ASP.net OPC клиент
Я подключаю dll-ки к проекту web-forms OpcNetApi.dll то есть делаю opc-клиент. при разработке все работает теги принимаю как запускаю...

OPC DA клиент на библиотеках OPC Foundation
Народ, подскажите pls, если кто знает... Написал пробного OPC клиента на C#, использовал библиотеки от OPC Foundation OpcNetApi.Com.dll и...

51
3 / 3 / 1
Регистрация: 18.12.2014
Сообщений: 74
21.04.2017, 07:47
Студворк — интернет-сервис помощи студентам
при подключении к opc, 0 возвращается? там есть ещё функция проверки переменных! попробуйте её ещё, она тоже если всё верно должна 0 возвратить! на овне не тестил, а на siemens всё работает как надо)
0
0 / 0 / 0
Регистрация: 28.02.2017
Сообщений: 9
21.04.2017, 11:54
Попробую заново создам проект. На win 7 x64 базовой может работать или обязательно нужна х32 ?
0
3 / 3 / 1
Регистрация: 18.12.2014
Сообщений: 74
21.04.2017, 12:34
нет, работает и на x64, скомпилируй проект под x86, c Any CPU не запускалось у меня на x64
1
0 / 0 / 0
Регистрация: 28.02.2017
Сообщений: 9
22.04.2017, 13:27
Цитата Сообщение от Leo28 Посмотреть сообщение
при подключении к opc, 0 возвращается? там есть ещё функция проверки переменных! попробуйте её ещё, она тоже если всё верно должна 0 возвратить!
С сервером коннектится, возвращает 0, но когда пытаюсь прочитать переменную напрямую err принимает значение true, т.е. с сервера не читает.

Добавлено через 14 часов 17 минут
Похоже ошибка появляется из-за прописанного тега Com4/TRM201v24(8bit adr=0)/LvoP/Pv До этого пробовал на 3х других OPC клиентах, всё нормально читается. Собственно вопрос, как в этом клиенте правильно задавать переменные для сервера OWEN.RS485, или придётся в сам клиент какие-то изменения вносить?

Добавлено через 2 часа 11 минут
Всё заработало когда прописал переменные через TableSignal4.xml
0
0 / 0 / 0
Регистрация: 28.02.2017
Сообщений: 9
23.04.2017, 13:52
Подскажите, когда на подписку ставлю больше одного тега, значения перестают автоматически обновляться, может что-то не так делаю?
0
 Аватар для Spectral-Owl
608 / 583 / 157
Регистрация: 29.06.2010
Сообщений: 1,620
21.03.2018, 12:00
Возможно я пинаю труп, но решил попробовать что за оно.

OPC_NET.OPCclient использовать не стал, не понравилось что у события приёма данных отсутствуют биты качества и метка времени.

т.е. остались нужны всего две из выложенных библиотек: OpcNetApi.Com.dll и OpcNetApi.dll

дальше, для конкретного OPC сервера получил все его элементы и подписался на обновления (код в WPF, немного изменил то, что представил EVG-1980):

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
        //поля для связи с сервером: сам сервер, его подписка, и фильтр
        private Opc.Da.Server server;
        private Opc.Da.ISubscription subscription;
        private Opc.Da.BrowseFilters filters;
 
        //коллекция добавленных в подписку тэгов
        Dictionary<string, TreeViewItem> tags = new Dictionary<string, TreeViewItem>();
 
        public MainWindow()
        {
            InitializeComponent();
 
            //получение текущего IP
            string strip = "127.0.0.1";
            String host = System.Net.Dns.GetHostName();
            System.Net.IPAddress ip = System.Net.Dns.GetHostByName(host).AddressList[0];
            strip = ip.ToString();
 
            //строка коннекта
            Opc.URL url = new Opc.URL("opcda://" + strip + "/" + OpcName);
 
            //создание и подключение сервера
            OpcCom.Factory fact = new OpcCom.Factory();
            server = new Opc.Da.Server(fact, null);
            server.Connect(url, new Opc.ConnectData(new System.Net.NetworkCredential()));
 
            //создание подписки
            server.Subscriptions.Clear();
            subscription = server.CreateSubscription(new Opc.Da.SubscriptionState());
            subscription.DataChanged += Subscription_DataChanged;
 
            //обзор содержимого сервера
            filters = new Opc.Da.BrowseFilters() { BrowseFilter = Opc.Da.browseFilter.all };
            browseserver(null, null);  
        }
        
        //рекурсивный метод просмотра содержимого сервера
        private void browseserver(TreeViewItem node, Opc.Da.BrowseElement parent)
        {
            try {
                //выход на уровень повыше, если достигнут конечный элемент
                if (parent != null && parent.IsItem)
                    return;
 
                //получение инфы о текущем объекте
                Opc.ItemIdentifier ItemID = null;
                if (node != null && node.Tag != null && node.Tag.GetType() == typeof(Opc.Da.BrowseElement)) {
                    parent = (Opc.Da.BrowseElement)node.Tag;
                    ItemID = new Opc.ItemIdentifier(parent.ItemPath, parent.ItemName);
                }
 
                //получение дочерних объектов
                Opc.Da.BrowsePosition position = null;
                Opc.Da.BrowseElement[] elements = server.Browse(ItemID, filters, out position);
                
                if (elements != null) {
                    foreach (Opc.Da.BrowseElement element in elements) {
                        //добавление дочернего объекта
                        TreeViewItem newnode = createcontrol(node, element);
                        //просмотр содержимого дочернего объекта
                        browseserver(newnode, element);
                    }
                }
            }
            catch (Exception e) { MessageBox.Show(e.Message); }
        }
 
        //создание нода для объекта
        private TreeViewItem createcontrol(TreeViewItem _parent, Opc.Da.BrowseElement element)
        {
            //создание нода
            TreeViewItem node = new TreeViewItem();
            node.Header = element.Name;
            node.Tag = element;
 
            //добавление нода на экран
            if (_parent == null)
                tv1.Items.Add(node);//tv1 - TreeView, корневые ноды добавляются в него
            else _parent.Items.Add(node);
 
            //если объект - тэг, а не папка..
            if (element.IsItem) {
                //получение инфы для подписки
                Opc.Da.Item item = new Opc.Da.Item(new Opc.ItemIdentifier(element.ItemPath, element.ItemName));
                //добавление подписки
                Opc.Da.ItemResult[] result = subscription.AddItems(new Opc.Da.Item[] { item });
                //анализ подписки на ошибки
                foreach (var res in result)
                    if (res.ResultID.Code != 0)
                        MessageBox.Show(res.ResultID.ToString());
                //добавление тэга в коллекцию
                tags.Add(element.ItemName, node);
            }
            //возврат созданного нода
            return node;
        }
        
        //обработчик события принятия данных подписки
        private void Subscription_DataChanged(object subscriptionHandle, object requestHandle, Opc.Da.ItemValueResult[] values)
        {
            //возврат в основной поток
            Dispatcher.Invoke(new System.Threading.ThreadStart(() => {
                //для всех принятых данных
                foreach (var val in values)
                    //если они не null (разок видел, удивился)
                    if (val != null && val.ItemName != null)
                        //отображение состояния
                        tags[val.ItemName].Header = val.Timestamp.ToLongTimeString() + " {" + val.Quality.QualityBits.ToString() + "} " + val.ItemName + " = " + val.Value;
            }));
        }
и вроде-бы всё замечательно и всё работает, даже захотел использовать данную либу в своём OPC клиенте, добавил указанные библиотеки, всё сделал в общем, и столкнулся с проблемой:

Opc.Da.BrowseElement.IsItem всегда false. Чёрт его знает чего. Пробовал переносить рабочие куски кода, пересоздавать окна, переписывать код вручную заново, даже перезагружать студию и комп, не помогает =(

следовательно две проблеммы:
1) в методе browseserver не срабатывает выход на уровень наверх, рекурсия не прерывается (ну как, прерывается, т.к. сервер при попытке просмотреть дочерние элементы тэга сыпет ошибки).
2) в методе createcontrol не происходит подписка на тэг, что печально.

пробовал анализировать не только свойство IsItem, но и HasChildren. Проблему 1 это исправляет, проблема 2 начинает сыпать ошибками 0x80020008 (несоответствие типа вроде)

сталкивался ли кто с такой фигнёй? Либо может идеи есть? и да, может стоило не некропостить, а новую тему создать (хотя вопросы по выложенным в теме либам)? в общем, одни вопросы)

Добавлено через 45 минут
Опаньки, нашел как всё поломать:
свойства проекта, изменить требуемую версию Framework с 4.5.2 на любую другую. Всё. Потом, даже если выполнить обратное действие, всё останется поломанным, даже удаление и добавление ссылок на библиотеки заново не помогает. Я, честно говоря, в недоумении. Вопросов стало ещё больше.

Добавлено через 1 час 12 минут
ну, и немного ещё:

если использовать OPC_NET.OPCClient и поменять версию Framework все вышеназванные проблемы сохраняются:
C#
1
2
3
4
5
6
7
            OPC_NET.Items items = client.GetItems();
            OPC_NET.VarData vd = new OPC_NET.VarData();
            vd.Address = "GRP-1/IO/AI/AI4";
            vd.Name = "ai4";
            vd.TypeRW = OPC_NET.TypeRW.Read;
            vd.Value = 0.0;
            items.Add(new List<OPC_NET.VarData> { vd }, out erradd);
items.OpcReadResult.ResultID равен 0x80020008 и т.д.

и ещё заметил, после коннекта Opc.Da.Server.GetState() выбрасывает FatalExecutionEngineError даже находясь внутри try{}catch{}
1
 Аватар для Voland_
1983 / 1276 / 131
Регистрация: 04.01.2010
Сообщений: 4,607
21.03.2018, 17:19
радуйтесь. этож .NET . Когда Allen Bradley затевали тему OPC, подобной лабуды в помине не было. Все прекрасно справлялись с COM/DCOM. Причем, даже delphi'сты (в лице, например, меня), где COM-объекты выглядят не так красиво как в C++.
0
 Аватар для Spectral-Owl
608 / 583 / 157
Регистрация: 29.06.2010
Сообщений: 1,620
22.03.2018, 08:36
уря) я починиль!)
сначала скажу что наткнулся на эту страницу, где в ветке downloads скачал OPC client for WPF. Увидел очень похожие исходники, только с комментариями на английском, да и версия у встроенных dll подревнее была))
Так вот, к чему это я: в скаченном проекте указанные мною действия к проблемам не приводили, всё продолжало работать. Поплясав с бубном в поисках разницы в проектах увидел, чтоб всё работало, конечная платформа должна иметь тип x86, а не AnyCPU, как было по умолчанию.

Теперь походу нужно будет тестить в разных виндах...
0
54 / 54 / 2
Регистрация: 30.05.2014
Сообщений: 83
31.03.2018, 16:51  [ТС]
переходите на плюсы, нах этот net.
на плюсах все гораздо проще, нет кучи прослоек и интфейсов.
0
23.12.2018, 19:37  [ТС]

Не по теме:


Для мониторинга-записи сигналов предлагаю воспользоваться системой "SVisual" - тоже моя разработка.
Интерфейс и мануал на русском, все открыто и бесплатно.

С целью продвижения оставлю ссылку : https://github.com/Tyill/SVisual/releases
Ставьте звездочки на github-е, если понравится.

Пример мониторинга сигналов после получения с ПЛК:

Кликните здесь для просмотра всего текста

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
 
namespace SV
{
 public unsafe class Client
 {
 [DllImport("SVClient.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
     static extern bool svConnect([MarshalAs(UnmanagedType.LPStr)]string moduleName, [MarshalAs(UnmanagedType.LPStr)]string ipaddr, int port);
 
 public bool connect(string moduleName, string ipaddr, int port)
 {
     return svConnect(moduleName, ipaddr, port);
 }
 
 [DllImport("SVClient.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
 static extern void svDisconnect();
 
 public void disconnect()
 {
     svDisconnect();
 }
 
 [DllImport("SVClient.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
 static extern bool svAddBoolValue([MarshalAs(UnmanagedType.LPStr)]string name, bool value, bool onlyFront);
 
 public bool addBoolValue(string name, bool value, bool onlyFront)
 {
     return svAddBoolValue(name, value, onlyFront);
 }
     
 [DllImport("SVClient.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
 static extern bool svAddIntValue([MarshalAs(UnmanagedType.LPStr)]string name, int value);
 
 public bool addIntValue(string name, int value)
 {
     return svAddIntValue(name, value);
 }
 
 [DllImport("SVClient.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
 static extern bool svAddFloatValue([MarshalAs(UnmanagedType.LPStr)]string name, float value);
 
 public bool addFloatValue(string name, float value)
 {
     return svAddFloatValue(name, value);
 }
 
 };
};
 
 
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
                                        
            // соединение с OPC
            OPC_NET.OPCclient cl = new OPC_NET.OPCclient();
            cl.Init(@".\TableSignal.xlsx");
 
            int er =  cl.ConnectOpcServer("???.?.?.?", ???, 100);
 
            // соединение с монитором
            SV.Client clMon = new SV.Client();
            clMon.connect("fromPLC", "127.0.0.1", 2144);
            
            while (true)    
            {
                // читаем данные с OPC
                bool err;    
                int val =  cl.ReadInt16("Speed", out err);
 
                // передаем на монитор
                clMon.addIntValue("Speed", val);
               
                System.Threading.Thread.Sleep(100);
            }
        }
    }
}


SVClient.dll - это библиотека для отправки данных на монитор, написана на C++, поэтому сверху обертка для C#.
Находится рядом с дистрибутивом в архиве cpp_client.rar.
Сам только проверить на ПЛК не могу, не связан с автоматикой сейчас. Пишите в комментариях этой темы, что получилось-нет.

0
1 / 1 / 1
Регистрация: 19.03.2020
Сообщений: 10
05.04.2020, 13:41
Цитата Сообщение от Spectral-Owl Посмотреть сообщение
Opc.Da.BrowseElement.IsItem всегда false. Чёрт его знает чего. Пробовал переносить рабочие куски кода, пересоздавать окна, переписывать код вручную заново, даже перезагружать студию и комп, не помогает =(
следовательно две проблеммы:
1) в методе browseserver не срабатывает выход на уровень наверх, рекурсия не прерывается (ну как, прерывается, т.к. сервер при попытке просмотреть дочерние элементы тэга сыпет ошибки).
2) в методе createcontrol не происходит подписка на тэг, что печально.
пробовал анализировать не только свойство IsItem, но и HasChildren. Проблему 1 это исправляет, проблема 2 начинает сыпать ошибками 0x80020008 (несоответствие типа вроде)
сталкивался ли кто с такой фигнёй? Либо может идеи есть? и да, может стоило не некропостить, а новую тему создать (хотя вопросы по выложенным в теме либам)? в общем, одни вопросы)
Эту программу проверил под WIndows Forms. Адаптировал и всё работает, указанных проблем нет. Платформа AnyCPU

ВОт так выглядит у меня метод BrowseServer

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
        
private void BrowseServer(TreeNode node, Opc.Da.BrowseElement parent)            
        {
            Opc.Da.BrowseFilters bf = new Opc.Da.BrowseFilters();
            bf.BrowseFilter = browseFilter.all;
            try
            {
                //выход на уровень повыше, если достигнут конечный элемент
              //  if (parent != null && parent.IsItem) return;
 
                //получение инфы о текущем объекте
                Opc.ItemIdentifier itemID = null;
                if (node != null && node.Tag != null && node.Tag.GetType() == typeof(Opc.Da.BrowseElement))
                    itemID = new Opc.ItemIdentifier(parent.ItemPath, parent.ItemName);
                //получение дочерних объектов
                Opc.Da.BrowsePosition position = null; // position всё время возвращает нулевое значение. Не нужная переменная
                Opc.Da.BrowseElement[] elements = server.Browse(itemID, bf, out position); //Просматривает содержимое тэга ItemID
 
                if (elements != null) // если элементов больше нет, то начинаем подниматься наверх
                {
 
                    foreach (Opc.Da.BrowseElement element in elements)
                    {
                        TreeNode newnode = new TreeNode();
                        Item item = new Item();
                        //добавление дочернего объекта                        
 
                        newnode.Text = element.Name; // создание нода дочернего объекта
                        newnode.Tag = element;
 
                        //добавление нода на экран
                        if (node == null)
                            treeView1.Nodes.Add(newnode);// Если находимся в корне
                        else node.Nodes.Add(newnode);
                                                   
                        //если объект - тэг, а не папка..
                        if (element.IsItem)
                        {
                            //добавление тэга в коллекцию
                            item.ItemName = element.ItemName;
                            item.Active = true;
                            item.ActiveSpecified = true;
                            Items.Add(item);
                            //Tags.Add(element.ItemName, newnode);                            
                            listBox1.Items.Add(element.Name);
                        }
 
                        //просмотр содержимого дочернего объекта, если он есть
                        if (element.HasChildren) BrowseServer(newnode, element); // рекурсивный вызов функции
                    }
                }                
            }
            catch (Exception e) { MessageBox.Show(e.Message); }
        }
0
0 / 0 / 0
Регистрация: 19.09.2024
Сообщений: 3
19.09.2024, 23:03
Что такое N7:0,L2 в подключении в RSLinx OPC Server??
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
19.09.2024, 23:03

Использование OPC-сервера от OPC Foundation (.NET)
Всем привет, возникла необходимость в разработке OPC DA 2.05a сервера под .NET, среди бесплатных вариантов ничего не нашел, писать...

Клиент OPC DA для Quantum
Добрый день всем! Мне необходимо создать клиента для обмена данными с контроллерами Quantum (Schneider Electric) через OPC DA. Опыт...

OPC UA Клиент для работы с TeslaScada2 в Debian
Здравствуйте. Я создал проект в TeslaSCADA2 IDE, создал там Modbus сервер, тэг, на всякий случай цифровой дисплей для вывода результата....

Клиент для OPC сервер Kepware и удаленное подключение
Добрый день, подскажите пожалуйста. Есть маленький клиент на c#, который читает значения тегов и записывает в них значения. Сервер OPC...

Выпущен официальный ICQ-клиент для платформы Android
Интернет-сервис ICQ объявил о выпуске официального клиента ICQ Mobile для смартфонов под управлением операционной системы Android. ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
52
Ответ Создать тему
Новые блоги и статьи
Программа опроса у.з. расходомера SLS-720F
Argus19 02.09.2026
Программа опроса у. з. расходомера SLS-720F Программа опрашивает один раз в минуту три ультразвуковых расходомера SLS-720F через интерфейс RS-485 по протоколу Modbus RTU. Опрашиваются регистры. . .
Hyper-V: Компьютер должен поддерживать доверенный платформенный модуль 2.0.
Maks 31.08.2026
При установке Windows 11 на виртуальную машину Hyper-V 2-го поколения вылезла такая ошибка: Решение: в параметрах виртуальной машины, в разделе "Безопасность" (Security) активировать флаг. . .
Архитектура биовида Стива в Майнкрафте: Зачем бонобо кубический каннибализм
anaschu 30.08.2026
Кубический Вагинокапитализм в Minecraft: Математический инвариант ОДУ и рок Стивов-бонобо Главная задача разработанной «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы». . .
Оттачиваю умение писать js программы.
russiannick 30.08.2026
Проектом выходного дня стало написание Книги шифров Виженера. Итогом стала версия 200, синий туман. Синий туман назван так, потому что замораживает текст под собой. Нажатие синих кнопок управляют. . .
мат медиц модель 30. презентация проекта
anaschu 27.08.2026
хоп хоп хоп хидахоп, а я кладую))
Как у меня протекала болезнь
zorxor 27.08.2026
Здравствуйте, друзья! Эта запись блога предназначена именно для вас - для моих дорогих друзей, которые знали меня лично. Чтобы ответить на вопрос - а что же со мной произошло на самом деле? Я учился. . .
Нашел вот забавное видео о измерениях. Лучшее что я видел на эту тему
kumehtar 26.08.2026
ILETXiw9bMQ Основная суть и тезисы по измерениям: 0D (Нулевое измерение): точка, не имеющая длины, ширины, высоты или объема. Объект не может перемещаться в 0D. 1D (Первое измерение):. . .
[EasyBuilder Pro] Памятка по разработке для панелей Weintek
ФедосеевПавел 26.08.2026
Памятка по разработке для панелей Weintek ВВЕДЕНИЕ Ранее, при реализации проектов основное внимание уделял разработке управляющей программы для контроллера, а панели оператора доставалось время. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru