powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / синхронизация потоков и класс serialport
1 сообщений из 1, страница 1 из 1
синхронизация потоков и класс serialport
    #39331141
kadet635
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здраствуйте, нужен совет, как грамотно синхронизировать потоки в C#, точнее синхронизировать доступ к serialport.
Есть некое приложение которое работает со СКУД через com порт.
В функции ReadEvent организовано считывание событий в бесконечном цикле
При возникновении события в контроллеры записываются ключи через serialport, как синхронизировать потоки чтоб в ком порт отправлять правильные данные

Код: 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.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
331.
332.
333.
334.
335.
336.
337.
338.
339.
340.
341.
342.
343.
344.
345.
346.
347.
348.
349.
350.
351.
352.
353.
354.
355.
356.
357.
358.
359.
360.
361.
362.
363.
364.
365.
366.
367.
368.
369.
370.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO.Ports;
using FirebirdSql.Data.FirebirdClient;
using System.Collections;
using System.Threading;
using System.Runtime.Remoting.Contexts;


namespace GateConsole
{
    class Program
    {       
        static FbConnection connection;
        static Mutex mutexObj = new Mutex();
        static void Main(string[] args)
        {           
            List<Contr> ContrList = new List<Contr>();
            FbConnectionStringBuilder cs = new FbConnectionStringBuilder();
            
            cs.DataSource = "192.168.0.220";
            cs.Database = "FITNESS";
            cs.UserID = "SYSDBA";
            cs.Password = "metalink";
            cs.Charset = "NONE";
            cs.Pooling = false;
            connection = new FbConnection(cs.ToString());
            GatePort.InitializationPort();
            GatePort._serialPort.Open();
            connection.Open();
            ///////////////////////////////////////////////////////////////////
            FbRemoteEvent revent = new FbRemoteEvent(connection);
            revent.AddEvents(new string[] { "EDIT_GATEKEY"/*, "NEW_EVENT", "new_visit"*/ });
            //Добавить функцию обратного вызова для Firebird событий
            revent.RemoteEventCounts += new FbRemoteEventEventHandler(WriteKey);
            revent.QueueEvents();
            ////////////////////////////////////////////////////////////////////            
            FbCommand com = new FbCommand("select contrid,addr from contr", connection);
            FbDataReader reader = com.ExecuteReader();
            if (reader.HasRows)
            {
                while (reader.Read())
                {
                    ContrList.Add(new Contr(Convert.ToInt32(reader.GetValue(0)), Convert.ToByte(reader.GetValue(1))));
                }
            }
            ReadEvent(ContrList);
            Console.WriteLine("Достигнута конечная точка программы");     
            Console.ReadLine(); 
            connection.Close();
            GatePort._serialPort.Close();
           
        }

      
        static void WriteKey(object sender, FbRemoteEventEventArgs args)
        {
            List<Key> ListKey = new List<Key>();
            byte[] dataRead;
            //Console.WriteLine("Предъмьютекс");
            try
            {
                //получить ключи и контроллеры
                //записать их в конроллеры
                FbCommand com = new FbCommand("select * from eventbufer", connection);
                FbDataReader reader = com.ExecuteReader();
                if (reader.HasRows)
                {
                    while (reader.Read())
                    {
                        ListKey.Add(new Key()
                        {
                            KeyId = (int)reader.GetValue(0),
                            AddresContr = (int)reader.GetValue(1),
                            AddresKey = (int)reader.GetValue(2),
                            KeySeries = (int)reader.GetValue(3),
                            KeyNumber = (int)reader.GetValue(4)
                        });
                    }

                    foreach (var i in ListKey)
                    {
                        Console.WriteLine("Контроллер {0} карта {1},{2}", i.AddresContr, i.KeySeries, i.KeyNumber);
                        dataRead = i.WriteKey(0x01);//Запись ключа в банк 1

                        dataRead = i.WriteKey(0x02);//Запись ключа в банк 2
                        
                        com = new FbCommand("delete  from eventbufer where id=" + i.KeyId, connection);
                        Console.WriteLine("Удалено {0} строк", com.ExecuteNonQuery());
                    }
                };
            }
            catch (Exception ex)
            {
                Console.WriteLine("ИСКЛЮЧЕНИЕ!!! {0}", ex);
            }
           
        }

        static public string Win1251ToUTF8(string source)
        {
            var fromEncodind = Encoding.GetEncoding("Windows-1251");//из какой кодировки
            var bytes = fromEncodind.GetBytes(source);
            var toEncoding = Encoding.UTF8;//в какую кодировку
            source = toEncoding.GetString(bytes);
            return source;
        }

        static void ReadEvent(Object controller)
        {
            List<Contr> ContrList = (List<Contr>)controller;
            int PointerUp = 0;
            int PointerDown = 0;
            List<ValueEvent> EventContr = new List<ValueEvent>();
            FbCommand com = new FbCommand("select * from eventscode", connection);
            FbDataReader reader = com.ExecuteReader();
            if (reader.HasRows)
            {
                while (reader.Read())
                {
                    EventContr.Add(new ValueEvent((int)reader.GetValue(0), Win1251ToUTF8((string)reader.GetValue(1))));
                }
            }
      
            byte[] dataRead, data;
            dataRead = new byte[] { 0x00 };

            while (true)
            {
                
                foreach (var cont in ContrList)
                {                   
                    dataRead = GatePort.RequestContr(0x09, cont.AdressContr, new byte[] { });//Номер версии контроллера                   
                    cont.VersionNumber = dataRead[6] >> 4;
                    //Console.WriteLine("Номер Версии:{0}", dataRead[6] >> 4);
                    switch (cont.VersionNumber)
                    {
                        //GATE-4 (адреса 0-7FFFh)
                        //GATE-8000 (адреса 0-FFFFh).
                        case 8:
                            cont.MaxAddrByte = 65535;
                            break;
                        case 4:
                            cont.MaxAddrByte = 32767;
                            break;
                    }

                    do
                    {
                        System.Threading.Thread.Sleep(100);
                       
                        dataRead = GatePort.RequestContr(0x04,cont.AdressContr, new byte[] { 0x00, 0xD0, 0x04, 0x00, 0x08, });//Нижняя и верхняя границы
                       
                        //Console.WriteLine("\nПоложение указателей");
                        //foreach (var i in dataRead)
                        //{
                        //    Console.Write(Convert.ToString(i, 16) + " ");
                        //}
                        Array.Reverse(dataRead);
                        PointerUp = BitConverter.ToInt16(dataRead, 4);
                        PointerDown = BitConverter.ToInt16(dataRead, 2);
                        Console.ForegroundColor = ConsoleColor.Green;
                        Console.WriteLine("\nАдрес нижней границы:{0}, адрес верхней границы: {1}", PointerDown, PointerUp);
                        Console.ResetColor();

                        if (PointerDown != PointerUp)
                        {
                            byte[] BufByte = BitConverter.GetBytes(PointerDown);//убрал+8, 2 байта-нижняя граница                            
                            dataRead = GatePort.RequestContr(0x04, cont.AdressContr, new byte[] { 0x02, 0xA0, 0x08, BufByte[1], BufByte[0] });
                            Console.WriteLine("Ответ сервера с событием");
                            foreach (var i in dataRead)
                            {
                                Console.Write(Convert.ToString(i, 16) + " ");
                            }
                            Console.WriteLine("\nНовое событие события:{0}, сдвиг на 1 разряд:{1}", dataRead[6], (dataRead[6] & 127));

                            foreach (ValueEvent i in EventContr)
                            {
                                if (i.ValueEventId == (dataRead[6] & 127))
                                {
                                    Console.ForegroundColor = ConsoleColor.Red;
                                    Console.WriteLine("Контроллер {5} Наименование события {0}, Месяц:{1:X}, Дата: {2:X}, Часы: {3:X}, Минуты:{4:X}", i.Name.ToString(), (int)dataRead[9], (int)dataRead[10], (int)dataRead[11], (int)dataRead[12],cont.AdressContr);
                                    Console.ResetColor();
                                    string date = String.Format("{0:X}.{1:X}.{2}", (int)dataRead[10], (int)dataRead[9],DateTime.Now.Year);
                                    string time = String.Format("{0:X}:{1:X}:{2:X}", (int)dataRead[11], (int)dataRead[12],(int)dataRead[13]);
                                    com = new FbCommand("insert into events (rearerid,eventscode,ddate,ttime,ser,number,contrid,client) values (" + cont.ContrId + "," + (dataRead[6] & 127) + "," + date + "," + time + "," + null+","+null+","+cont.ContrId+")", connection);
                                
                                }
                            }

                            //увелчить на 8 нижнюю границу  
                            if ((PointerDown + 8) >= cont.MaxAddrByte)
                            { PointerDown = -8; }
                            byte[] data11 = BitConverter.GetBytes(PointerDown + 8);                        
                            dataRead = GatePort.RequestContr(0x05, cont.AdressContr, new byte[] { 0x00, 0xD0, 0x02, 0x00, 0x0A, data11[1], data11[0] });
                            Console.WriteLine("Ответ после изменения нижней границы");
                            foreach (var i in dataRead)
                            {
                                Console.Write(Convert.ToString(i, 16) + " ");
                            }
                        }
                    } while (PointerDown != PointerUp);
                    Console.ForegroundColor = ConsoleColor.DarkBlue;
                    Console.WriteLine("Все события контроллера {0} считаны, переход к следующемуу контроллеру", cont.AdressContr);
                    Console.ResetColor();
                    System.Threading.Thread.Sleep(100);
                }
            }
        }
    }

        class Key
        {
            public int KeyId { get; set; }
            public int KeySeries { get; set; }
            public int KeyNumber { get; set; }
            public int AddresKey { get; set; }
            public int AddresContr { get; set; }

            public byte[] WriteKey(byte bank)
            {
                byte[] buf = BitConverter.GetBytes(AddresKey);
                byte[] BufKeyNumber = BitConverter.GetBytes(KeyNumber);
                byte[] Request = GatePort.RequestContr(0x05, (byte)AddresContr, new byte[] { bank, 0xA0, 0x08, buf[1], buf[0],
                    0x00,
                    0x00,
                    0x00,
                    (byte)KeySeries,
                    BufKeyNumber[1],
                    BufKeyNumber[0],
                    0x00,
                    0x80,//16 байт
                });               
                return Request;
            }
    }

        class Contr
        {
            public int ContrId { get; set; }
            public byte AdressContr { get; set; }
            public string ContrName { get; set; }
            public int VersionNumber { get; set; }
            public int MaxAddrByte { get; set; }//максимальный адрес буфера событий
            //IEnumerable<Key> Keys { get; set; }

            public Contr(int contrid, byte adres)
            {
                ContrId = contrid;
                AdressContr = adres;
            }         
        }


        class ValueEvent
        {
            public int ValueEventId { get; set; }
            public string Name { get; set; }
            public ValueEvent(int id, string name)
            {
                ValueEventId = id;
                Name = name;
            }

        }

    static class GatePort
    {
        public static SerialPort _serialPort;
        public static byte[] Data, DataRead;
        static byte ContrSumma;
        static int ErrorCount;

        public static void InitializationPort()
        {
            _serialPort = new SerialPort("COM4", 19200, Parity.None, 8, StopBits.One);
            _serialPort.Handshake = Handshake.None;
            _serialPort.ReadTimeout = 1500;
        }

        public static byte[] RequestContr(byte CodeRead, byte AddressContr, byte[] BodyCommand)
        {
            ErrorCount = 0;
            ContrSumma = CodeRead;
            Data = new byte[] { 0xFA, 0x01, AddressContr, CodeRead };
            //Сначала обработать bodycommand на предмет наличия FF,F5
            foreach (var i in BodyCommand)
            {
                Array.Resize(ref Data, Data.Length + CheckByte(i).Length);
                CheckByte(i).CopyTo(Data, Data.Length - CheckByte(i).Length);
            }
            for (int i = 4; i < Data.Length; i++)
            {
                ContrSumma = (byte)(ContrSumma ^ Data[i]);
            }
           // ContrSumma = 0xF5;
            switch (CheckByte(ContrSumma).Length)
            {
                case 1:
                    Array.Resize(ref Data, Data.Length + 2);
                    Data[Data.Length - 2] = ContrSumma;
                    Data[Data.Length - 1] = 0xF5;
                    break;
                case 2:
                    Array.Resize(ref Data, Data.Length + 3);
                    Data[Data.Length - 3] = CheckByte(ContrSumma)[0];
                    Data[Data.Length - 2] = CheckByte(ContrSumma)[1];
                    Data[Data.Length - 1] = 0xF5;
                    break;
            }
            //Console.WriteLine("Запрос на сервер:");
            //foreach(var i in Data)
            //{
            //    Console.Write("{0} ",i);
            //}
            do
            {
                try
                {
                    _serialPort.Write(Data, 0, Data.Length);
                    System.Threading.Thread.Sleep(100);
                    DataRead = new byte[255];
                    int KollByte = _serialPort.Read(DataRead, 0, DataRead.Length);
                    Array.Resize(ref DataRead, KollByte);
                    ErrorCount = 0;
                }
                catch (TimeoutException)
                {
                    ErrorCount++;
                    if (ErrorCount >= 10)
                    { ErrorCount = 0; }
                    Console.WriteLine("Контроллер не ответил");
                }
            } while (ErrorCount != 0);
            return DataRead;
            //Console.WriteLine("Результат:");
            //foreach (var i in DataRead)
            //{
            //    Console.Write("{0} ", i);
            //}

        }


        static byte[] CheckByte(byte b)
        {
            byte[] buf;
            switch (b)
            {
                case 0xFA:
                    buf = new byte[] { 0xFF, 0x01 };
                    break;
                case 0xF5:
                    buf = new byte[] { 0xFF, 0x02 };
                    break;

                case 0xFF:
                    buf = new byte[] { 0xFF, 0x03 };
                    break;
                default:
                    buf = new byte[] { b };
                    break;
            }
            return buf;
        }
    }
}
...
Рейтинг: 0 / 0
1 сообщений из 1, страница 1 из 1
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / синхронизация потоков и класс serialport
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]