LINUX.ORG.RU

Помогите с логикой программы

 


1

1

Есть много устройств на RS-232,485 интерфейсах, опрашиваемых по всяким протоколам.

Есть классы:

-Очередь (хранит список команд, которые поочередно выполняет прибор)

-Генератор очереди (запихивает команды в очередь)

-Считыватель очереди (вытаскивает из очереди по одной команде и отправляет в Читатель)

-Читатель прибора (выполняет команду на приборе, возвращает статус)

Сейчас Генератор очереди и Считыватель очереди запускаются в двух потоках и все пихается в одну очередь. Но этот вариант не подходит, поскольку пока один прибор выполняет команду - другие спят.

Нужно создавать на каждый прибор свою очередь, чтобы они обрабатывались параллельно. Но я не пойму как это правильно и более лучше организовать.

Смотреть в сторону процессов или проще можно как-то? ЯП - python.



Последнее исправление: qq6ka (всего исправлений: 1)

Тебе либо надо писать дополнительно планировщик который будет дёргать прибор за прибором либо делать по потоку на прибор man OpenMP.

blogdron
()
Ответ на: комментарий от blogdron

делать по потоку на прибор

Не совсем понимаю как тогда будет вестись работа с очередями. Сейчас у меня так с общей очередью:

queue=queue_sender.Queue() #очередь

class Add_Queue(threading.Thread):
    def run(self):
        while True:
            #добавляем в очередь команды
            #queue.add()

class Start_Read(threading.Thread):
    def run(self):
        while True:
            #читаем из очереди команды, отправляем в прибор
            #queue.get()

Add_Queue().start()
Start_Read().start()

Как в случае с частными очередями объяснить генерирующему и читающему очередь потокам с какой очередью работать?

for device in devices:
    #что тут примерно будет?
qq6ka
() автор топика

Много устройств это как, много устройств на одной линии 485-го или каждому прибору своя линия ?

ilovewindows ★★★★★
()

Сейчас Генератор очереди и Считыватель очереди запускаются в двух потоках и все пихается в одну очередь. Но этот вариант не подходит, поскольку пока один прибор выполняет команду - другие спят.

можно по подробней, как первое предложение связано со вторым? в первом предложении описывается только внутреннее устройство приложения (Генератор очереди, Считыватель очереди, Очередь), канал связи (Читатель прибора) не описывается. во втором сообщается про блокировку одновременного доступа в канале связи (Читатель прибора). или я не правильно все понял?

anonymous
()
Ответ на: комментарий от ilovewindows

Пока окончательный вариант неизвестен. Но в итоге какие-то будут читаться напрямую с виртуальных СОМ-портов через преобразователи типа Моха, какие-то будут висеть в одной шине и обращаться буду по адресу прибора в шине.

qq6ka
() автор топика
Ответ на: комментарий от anonymous

Читателя прибора не стал описывать, ему передается значение из очереди, он обращается к конкретному прибору, отправляет команду, получает ответ и возвращает в Считыватель очереди статус (успешно или нет), если успешно - из очереди берется следующее значение, если нет - эта же команда добавляется в очередь снова. И в этом случае (с общей очередью) с нее ничего не читается, пока не будет получения статус выполнения от прибора.

К тому же прибор я могу через веб-интерфейс «выключить» и не читать. А позже снова включить и нужно, чтобы он начал читаться сразу, а в случае с общей очередью его задания добавятся в конец очереди.

Поэтому нужно на каждый прибор создавать свою очередь, чтобы все приборы опрашивались независимо друг от друга.

И я немного не понимаю.

Если я запущу 3 (уже фигня какая-то) потока на устройство - один поток стартует экземпляр очереди и два потока, пишущие/читающие в/из нее. Откуда пишущие и читающие потоки будут знать, что именно в этот экземпляр очереди нужно добавить команду? Ну и читать из него же, а не десятка других очередей.

Если я правильно понял, то все потоки имеют доступ к объектам (процесс же один). А процессы независимы и если я запущу, например, в двух процессах экземпляр очереди и по 2 потока, с ней работающие, то они не будут мешаться друг другу.

qq6ka
() автор топика
Ответ на: комментарий от qq6ka

Тогда класс «порт RS-485» как бы напрашивается сам собой, одна будет очередь или на каждое устройство своя зависит от протокола устройств.

ilovewindows ★★★★★
()
Ответ на: комментарий от qq6ka

классы: Порт, Устройство, Очередь команд, Очередь ответов. Содержимое:

  • Порт - виртуальный порт, Очередь команд.
  • Устройство - Очередь ответов, средство доступа к Порту, список команд.
  • Очередь команд - данные команды, средство доступа к Устройству.
  • Очередь ответов - средство доступа к команде, данные ответа.

на каждый Порт свой поток, на устройства как хочешь.

функционал Порта - кодировка данных из команды в соответствующем протоколе, отправка данных в порт, чтение данных из порта и декодировка в соответствующем протоколе, отправка ответа на команду соответствующему устройству в Очередь ответов.

функционал Устройства - периодическая отправка команд, отправка команд по запросу, обработка очереди ответов, обработка запросов на получение данных (от верхних уровней).

anonymous
()
Ответ на: комментарий от qq6ka

Ты мудришь, одного потока вполне достаточно для всех очередей всех твоих девайсов. Сколько надо потоков на обслуживание последовательного порта на питоне вопрос, но не больше двух уж точно.

ilovewindows ★★★★★
()
Последнее исправление: ilovewindows (всего исправлений: 1)

А как физически осуществляется запись и чтение в устройства? Если через файловые дескрипторы, то здесь должен обычный poll/select все решить.

provaton ★★★★★
()
Ответ на: комментарий от qq6ka

Ну тут да с потоками я переборщил. Хотя можно придумать что то вроде меток каждому прибору тупо присвоить номер, каждая команда для прибора должна будет содержать номер прибора какой номер такая и очередь тут вообще всё полностью асинхронно сляпать можно будет, только вот как передавать команды конкретному прибору это уже другой вопрос, слишком всё мутно тут.

p.s. Да и с питоном я на вы.

blogdron
()
Ответ на: комментарий от blogdron

Coroutines

Есть просто офигенное решение с использованием Coroutines («круатины») http://www.dabeaz.com/coroutines/. в архиве с примера есть pdf там на странице 79 все по полочкам разложено, рекомендую документ изучит досконально.

energyclab
()
Ответ на: комментарий от qq6ka

Читателя прибора не стал описывать, ему передается значение из очереди, он обращается к конкретному прибору, отправляет команду, получает ответ и возвращает в Считыватель очереди статус (успешно или нет), если успешно - из очереди берется следующее значение, если нет - эта же команда добавляется в очередь снова.

Как Считыватель добавляет неудачную команду в очередь? Он отдает ее Генератору или сам добавляет в Очередь или отдает Читателю сразу минуя Очередь? От этого будет зависеть архитектура системы обработки очереди.

codeogre
()
Ответ на: комментарий от blogdron

так в том то и дело, что там изучать ничего не надо, синтаксис yeald описан в двух примерах, а далее происходит описание применения его в различных ситуациях, так сказать паттерн проектирования. Просто потом, когда python изучишь и если вспомнишь про эту статью будешь локти кусать что не воспользовался этой штукой. Там тебе и многозадачность в одном потоке, и разбор xml и инкапсуляция многопоточности, которой очень легко управлять...и скорость выполнения в разы быстрее чем у традиционных средств, и при все при этом это является частью самого языка а не каким то фреймворком)) ну вообщем сам решай, делай как знаешь)))

energyclab
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.