8-900-374-94-44
[email protected]
Slide Image
Меню

Работа с com портами python – Последовательный порт. Да, поможет нам Python!

Последовательный порт. Да, поможет нам Python!

Давным-давно, когда я сидел под Виндовсом у меня была прога для работы с COM-портом. Это были мои «уши и руки» для доступа к моим микроконтроллерным устройствам. Я очень боялся потерять её, боялся, чтобы её не загрызли вирусы…

Потом я пересел на Линукс, и как все Линукс-новички искал аналоги этой проги. Можно не уточнять, что я их не нашел. Конечно, я тогда расстроился — «Ну как же так! Потребность есть, а проги нет? Что-то не так в мире Линукса. Ведь в мире Виндовса каких-только программ нет! А тут такая фигня — и нет! Да, похоже, правильно говорят: Линукс — это какая-то недоделанная ОСь. Ничего в нем (Линуксе) толкового нет!»

Да-да, именно такие мысли бродили у меня в голове. Иногда они подогревались Виндузятниками, которые «эксперты-по-Линуксу», и мне было очень даже тяжко. Но я, «закусив удила», пер как трактор — только вперед!

Через какое-то время я допер, что в мире Линукса существует программа MiniCom. Прога как прога, как принято говорить — «малость не дотягивает до уровня аналогичных программ для Виндос». Я ее юзал какое-то время, пока опять-таки не допер, что даже и она не очень-то нужна в мире Линукса.

Линукс — более чем самодостаточен. В Линуксе не надо никаких особых программ для работы с последовательным портом, как это принято в мире Виндовс. По этой причине, собственно, нет и не должно быть программ для работы с портом. Они просто не нужны!

В мире Линукса последовательный порт — это файл. (Вообще, Линукс на всё «смотрит» как на файлы. Всё унифицировано.) Ну а с файлами-то мы работать умеем! А раз так, то всякие вычурные программы с бантиками и бубенчиками — это ненужный антураж, который создает видимость «продуманности» программы. Отвлекать юзера от основной цели (назначения программы), уводить его на второстепенные (менее значительные) показатели и ненужную побочную функциональность — это по-Виндовому!

Однако, вернемся к Линуксу. Что я делал, когда мне нужно было принять информацию с устройства и сохранить ее в файле? Я просто в консоли выполнял команду:

$ cat /dev/ttyS0 > my-data

Но это прога выполнялась молча, на экран ничего не выводила. Но иногда требуется «мониторить» поток. Тогда команда должна стать составной — дополниться командой tee, которая одну копию потока отправляет в указанный файл, а другую выводит на консоль:

$ cat /dev/ttyS0 | tee my-data

Все предельно просто. Но что же делать, когда требуется какая-то обработка данных в реальном времени? И вот тут у меня не было ничего «красивого», что бы я мог предложить.

В этих случаях я поступал по-Виндовому. Я писал Си-шные программы, которые открывали последовательный порт, считывали из него информационный поток, как-то его обрабатывали, результат работы записывали в файл и при необходимости что-то выдавали на экран. Все это работало. Работало не плохо. Работало надежно. Но какое-то шестое чувство мне подсказывало, что это не совсем тот самый путь, который есть правильный. В Линуксе всё должно быть как-то по другому. Но, как? Я не знал. И продолжал компилировать свои многочисленные программы.

В процессе работы возникали смешные проблемы. Надо сказать, что все эти проги не были предназначены ни для продажи, ни для широкого тиражирования. Эти проги работали в единичных экземплярах и/или только с моим оборудованием. Но каждый раз, даже при незначительных (казалось бы!) изменениях, мне приходилось их заново компилировать и присваивать им версии. Путаница начинала свой разбег по взлетной полосе…

Конечно, можно было пойти по другому пути. Все переменные параметры можно было бы сохранять в конфигурационных файлах. Но, ребята, окститесь! Это ж не коммерческие проги! Я их сам поддерживаю, я сам знаю, что и где в них нужно подкрутить или изменить, чтобы они работали чуть-чуть по другому.

Конфигурационные файлы — это еще один уровень сложности в борьбе с той сложностью, ради которой создается программа. С точки зрения уменьшения сложности, конфигурационные файлы мало-что меняют. Это просто перенос сложностей в другую плоскость (на другой уровень), но это не уменьшение количества сложностей. Наша жизнь и без того сложна, и отчетливо помнить все подробности весьма затруднительно. Поэтому нужно уменьшать количество сложности, а не увеличивать.

Я понимал, что нужно было что-то делать. Как минимум, нужно было что-нибудь почитать по Линуксу и обработке данных. И я погрузился в изучение парадигмы Линукса.

Следует заметить, что Линукс очень силен в обработке статических текстов и текстовых потоков. Обработка текстовой информации — это один из столпов Линукса. Это могучий булыжник в фундаменте Линукса. И тот, кто упускает этот момент, можно утверждать, что он не понимает Линукса.

Отсюда вытекает весьма простая истина, если информационный поток, который идет через последовательный порт, будет в текстовом формате, то все проблемы легко решаются штатными утилитами, входящими в состав любого дистрибутива Линукс.
Я даже выделил эту синтецию жирным, на столько она фундаментальна.

Понимая эту и некоторые другие Линуксовые идеи начинаешь задумываться над вопросом — «Ребята, а зачем нам вообще нужна Винда?» Она и без того мне мозги прочистила так, что я до сих пор иногда мыслю по-Виндовому. А когда я мыслю по-Виндовому, я не понимаю Линукса. Отсюда все мои неудачи и разочарования. К счастью, это происходит всё реже и реже!

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

А раз так, то зачем нам какие-то специализированные (а к пущему греху еще и графические — прости-хоспади!) проги для работы с последовательным портом? Написать на Python-е для работы с последовательным портом прогу, специализированную под наши требования, — проще пареной репы!

Для работы с последовательным портом существует модуль serial, который инкапсулирует доступ к порту. (В интернете иногда можно встретить название PySerial. Это одно и тоже! Возможно, так назывался этот модуль раньше, но точно я не знаю. Это только мои предположения.) Модуль serial не входит в состав Python – его нужно устанавливать самостоятельно. В Ubuntu это делается с помощью команды:

$ sudo apt-get install python-serial

Заметьте, что название модуля и название пакета не совпадают. Почему? Какая причина?

Всё просто. Дело в том, что название пакета python-serial — это, так сказать, «область имен» в сфере пакетов программ, то есть в это область операционной системы, область репозиториев пакетов, область инсталляции программ — улавливаете?

А название модуля serial — это область работы Питона. Питон понятия не имеет об операционной системе и тем более о каких-то пакетах программ. У Питона свои тараканы — модули. Модули — это в некоторой степени библиотеки.

Вас ведь не смущает, что какая-нибудь программа-инсталлятор имеет одно имя, а устанавливаемая из неё программ — другое. Так и тут: имя пакета — это название коробочки, в которой лежит куча разных файлов. Среди этих файлов вполне может находиться Питоновский модуль, возможно какие-то справочные файлы или файлы конфигурации.

В программную среду Python модуль подключается обычным способом – через команду import:

import serial

И опять, название модуля отличается.

Следующая программа позволяет найти в системе все последовательные порты. (Программа взята из книги «Beginning Python Visialization.: Crafting Visual Transformation Scripts» Shai Vaingast, 2009. Стр. 3., и немного переделана для работы Linux-е.

#! /usr/bin/env python
# coding: utf-8

import serial

found = False

for i in range(64) :
  try :
    port = "/dev/ttyS%d" % i
    ser = serial.Serial(port)
    ser.close()
    print "Найден последовательный порт: ", port
    found = True
  except serial.serialutil.SerialException :
    pass

if not found :
  print "Последовательных портов не обнаружено"

Следующая программа забирает поток данных из последовательного порта и выводит его на экран

#! /usr/bin/env python
# coding: utf-8

import serial

ser = serial.Serial("/dev/ttyS0")
ser.baudrate = 115200

while True :
  line = ser.readline()
  print line

Программа имеет бесконечный цикл, поэтому для ее окончания нужно нажать Ctrl-C.

Еще одна программа из книги «Beginning Python Visialization.: Crafting Visual Transformation Scripts» Shai Vaingast, 2009. (cтраница 5). Эта программа забирает поток данных из последовательного порта и сохраняет его в файле. В целях контроля, поток данных выводится на экран.

Имя файла формируется автоматически на основе времени запуска программы. Например, имя файла, созданного 8-го Февраля 2014-го года в 9 часов (утра) 3 минуты и 31-у секунду, будет следующим:

GPS-2014-02-08-09-03-31.csv

здесь GPS – это префикс файла. По нему можно ориентироваться, какие данные в нем находятся. Программа использовалась для работы с GPS-приёмником, это отразилось на имени создаваемых ею файлов.

Далее следует дата-время, записанные через дефис. Стандарт ISO 8601 предписывает числа в дате писать через черточки, а числа во времени писать через двоеточие. Использование символа двоеточия в именах файлов – это не очень хорошая идея, поэтому числа во времени удобнее написать так же через дефис. Следует обратить внимание, что месяцы, дни, часы, минуты и секунды должны всегда иметь две цифры – незначащий ноль должен присутствовать. Это облегчит поиск и анализ файлов в директории, где подобных файлов может оказаться очень много. Поскольку файловые менеджеры зачастую упорядочивают файлы, то избранная правильная система наименования файлов только облегчат работу с ними.

Суффикс файла csv – говорит о том, что этот файл текстовый, то есть состоит из строк текста. Каждая строка состоит из информационных полей, разделителем которых является символ запятая. В английском это более прозрачно: csv – это Comma Separaterd Values – значения, разделенные запятой.

Однако, давайте перейдем к рассмотрению самой программы:

#! /usr/bin/python
# coding: utf-8

import time, serial

ser = serial.Serial("/dev/ttyUSB0")
ser.baudrate = 9600

filename = 'GPS-%4d-%02d-%02d-%02d-%02d-%02d.csv" % time.localtime()[0:6]

f = open(filename, 'w')
while True :
  line = ser.readline()
  f.write(line)
  print line, # Запятая нужна!

Здесь имя последовательного порта несколько отличается. У меня GPS-приемник подключен к USB-порту через самодельный переходник USB-UART. Переходник самый обычный, выполнен на микросхеме FTDI232RL.

Со стороны компа я обращаюсь к UART-у, как к виртуальному последовательному порту, который «проброшен» через USB-порт. Поэтому имя файла порта в моем случае будет /dev/ttyUSB0.

В самой последней команде программы запятая нужна для того, чтобы исключить переход на следующую строку. Дело в том, что в сообщениях GPS-приемника, которые состоят из строк, символ перевода на новую строку уже есть. И если в команде опустить запятую, то на экран будут выводится два символа перевода на новую строку – один присутствует в самой строке , а другой – от команды print.

Вот пример текста, который появляется у меня на экране и записывается в файл:

...
$GNRMC,110354.000,A,5654.2781,N,06049.3861,E,0.07,105.23,110214,,,A*7E
$GPVTG,105.23,T,,M,0.07,N,0.13,K,A*3D
$GPGGA,110354.000,5654.2781,N,06049.3861,E,1,10,1.14,292.5,M,-7.0,M,,*74
$GNGSA,A,3,13,23,04,20,10,31,,,,,,,1.44,1.14,0.89*1E
$GNGSA,A,3,83,77,67,68,,,,,,,,,1.44,1.14,0.89*1C
$GPGSV,4,1,13,23,62,270,45,20,57,202,38,31,41,062,15,32,33,157,*71
$GPGSV,4,2,13,13,28,272,40,04,24,305,42,16,18,149,,25,08,023,*78
$GPGSV,4,3,13,29,06,045,16,10,05,316,30,02,04,348,18,01,02,209,*7C
$GPGSV,4,4,13,45,,,*7A
$GLGSV,3,1,09,67,74,300,34,76,66,063,,77,49,196,31,66,46,141,*6B
$GLGSV,3,2,09,68,19,314,42,84,18,002,,83,14,311,38,75,13,036,*6F
$GLGSV,3,3,09,85,04,045,*54
$GNGLL,5654.2781,N,06049.3861,E,110354.000,A,A*4C
...

Это текст в формате NMEA (америкосы произносят это как «эн-ем-Иа», ударение на «И»). Я бы не хотел сейчас заострять внимание на его расшифровке. Важно только то, что это, во первых, текстовая информация (а не двоичная), а во вторых, эта информация достаточно хорошо структурирована и может быть легко обработана.

Точно такой же тип текстовой информации я получаю с геологических приборов:

...
E 3 825 48 499 508 508 508 508 508 506 542 573 602 628 652 674 695 713 731 748 762 776 789 801 812 822 832 841 849 857 864 871 877 883 888 893 897 902 905 909 912 915 918 920 922 924 926 928 930 931 933 934 935 937 938 939 940 941 942 942 943 944 944 945 946 946 947 947 947 948 948 949 949 949 950 950 950 950 951 951 951 951 951 952 952 952 952 952 952 952 952 953 953 953 953 953 953 953 953 953 953 953 953 953 953 954 954 954 954 968 923 885 851 820 792 767 745 724 705 688 673 659 646 635 624 614 605 597 590 583 577 571 566 561 557 553 550 546 543 540 538 536 533 531 529 528 526 525 524 523 521 520 519 519 518 517 516 516 515 515 514 514 513 513 513 512 512 512 511 511 511 511 511 510 510 510 510 510 510 510 509 509 509 509 509 509 509 509 509 509 509 508 508 508 508 508 508 508 508 508 508 508 508 508 508 508 508 508 508 501 463 431 400 373 348 325 304 285 267 251 236 222 209 197 186 176 166 157 149 142 135 128 122 116 111 107 102 98 94 90 87 84 81 78 76 73 71 69 67 66 64 63 61 60 59 57 56 55 55 54 53 52 51 51 50 49 49 48 48 47 47 46 46 45 45 44 44 44 44 43 43 43 43 42 42 42 42 41 41 41 41 41 41 40 40 40 40 40 40 40 40 39 39 39 39 39 39 39 39 47 92 131 165 195 223 248 271 291 310 327 342 356 369 381 392 401 411 419 426 433 439 445 450 455 459 463 466 470 473 476 478 480 483 484 486 488 489 491 492 493 494 495 496 497 498 498 499 499 500 501 501 502 502 502 503 503 503 504 504 504 504 504 504 505 505 505 505 505 505 505 505 505 506 506 506 506 506 506 506 506 506 506 506 506 506 506 506 506 507 507 506 507 507 507 507 507 507 507 507
M 3 0 10524 12498 14417 16335 18239 20157 22078 23989 25915 27834
E 4 825 33 499 508 508 508 508 508 506 542 573 602 628 652 674 695 713 731 748 762 776 789 801 812 822 832 841 849 857 864 871 877 883 888 893 897 902 905 909 912 915 918 920 922 924 926 928 930 931 933 934 935 937 938 939 940 941 942 942 943 944 944 945 945 946 947 947 947 948 948 949 949 949 950 950 950 950 951 951 951 951 951 952 952 952 952 952 952 952 952 952 953 953 953 953 953 953 953 953 953 953 953 954 954 954 954 954 954 967 923 885 851 820 792 767 745 724 705 688 673 659 646 634 624 614 605 597 590 583 577 571 566 561 557 553 550 546 543 540 538 536 533 531 529 528 526 525 524 523 521 520 519 519 518 517 516 516 515 515 514 514 513 513 513 512 512 512 511 511 511 511 511 510 510 510 510 510 510 510 509 509 509 509 509 509 509 509 509 509 509 508 508 508 508 508 508 508 508 508 508 508 508 508 508 508 508 508 508 501 463 431 401 373 348 326 304 285 267 251 236 222 209 197 186 176 166 158 149 142 135 128 122 117 111 107 102 98 94 91 87 84 81 79 76 74 71 69 67 66 64 63 61 60 59 58 57 56 55 54 53 52 51 51 50 49 49 48 48 47 47 46 46 45 45 44 44 44 44 43 43 43 43 42 42 42 42 41 41 41 41 41 41 41 40 40 40 40 40 40 40 40 39 39 39 39 39 39 39 47 92 131 165 195 223 248 271 291 310 327 342 356 369 381 392 402 411 419 426 433 439 445 450 455 459 463 466 470 473 476 478 480 483 484 486 488 489 491 492 493 494 495 496 497 498 498 499 499 500 501 501 502 502 502 503 503 503 504 504 504 504 504 504 505 505 505 505 505 505 505 505 505 506 506 506 506 506 506 506 506 506 506 506 506 506 506 506 506 507 507 507 507 507 507 507 507 507 507 507
M 4 0 10528 12500 14420 16339 18243 20162 22084 23996 25924 27843
...

Здесь у меня чередуются два типа пакетов (два типа строк). Пакет типа «M» содержит данные Модуля Магнитного Каротажа (ММК), а пакет типа «E» – данные Модуля Электро-Каротажа (МЭК). Пакет ММК значительно меньше по размеру пакета МЭК. Если пакет ММК состоит из 13 полей, то пакет МЭК содержит более 400.

Каждая запись (каждый пакет) располагается в одной информационной строке, которая заканчивается символом «новая строка». Здесь поля отделяются друг от друга символом пробела. Это не совсем правильно. Это я только сейчас понял, что csv-формат может автоматически «затягиваться» в программы электронных таблиц из офисных пакетов (типа Calc из Libre-Office) без дополнительных телодвижений по указанию символов-разграничителей полей. Да, надо будет как-нибудь переписать программу и заменить символ-разграничитель.

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

А пока на этом всё!

 

UPDATE 29.10.2015

Небольшая заметка, касающаяся особенности использования модуля serial под Python-3:

http://wp.me/p1H7g0-1ed

 

UPDATE 01.12.2015

Вопрос: где взять модуль serial для Python-3?

Ответ: Модуль serial для Python-3 я тупо взял из репозитория Debian-8. То есть даже не заморачивался его поисками в интернете.

Команда для инсталляции:

# apt-get install python3-serial

Установка модуля serial для Python-2.x на Ubuntu-10.04 LTS производится очень просто:

$ sudo apt-get install python-serial

Но для Python-3.x модуля serial в репозитории Ubuntu-10.04 LTS нет. Поэтому установка будет производиться несколько сложнее

1) Идем на страницу http://pupi.python.org/pypi/serial/2.7

и скачиваем архивный файл pyserial-2.7.tar.gz

$ wget -c http://pupi.python.org/pypi/serial/2.7/pyserial-2.7.tar.gz

2) Распаковываем полученный архивный файл:

$ tar -xvf pyserial-2.7.tar.gz

3) Заходим в поддиректорий:

$ cd pyserial-2.7/

4) Запускаем процесс  инсталляции:

$ sudo python3 setup.py install

После этого можно использовать модуль serial в программах под Python-3.x.

Есть мнение, что можно проинсталлировать модуль вот так:

pip install pyserial

или так

$ easy_install -U pyserial

, но я этого не делал. Поэтому я не могу сказать можно ли так делать или нельзя.

 

UPDATE 30.03.2016

Написал новую статью: «Python, последовательный порт и нуль-модемный кабель»

http://wp.me/p1H7g0-1nb

 

UPDATE 12.11.2017

Написал статью про использование последовательного порта в проектах с микроконтроллером

https://wp.me/p1H7g0-1Mx

Понравилось это:

Нравится Загрузка...

Похожее

zhevak.wordpress.com

Скрипт для автоматического определения настроек COM порта на Python 3



Сохранить запись:

 

У многих встраиваемых систем, устройств промышленной электроники для связи с внешними устройствами или выполнения сервисных функций, в том числе считывания диагностических кодов неисправностей, отладки, обноления встроенного программного обеспечения(прошивки) до сих пор присутствует последовательный интерфейс RS232, более известный как COM порт. В подобных устройствах таких интерфейсов может быть несколько и не всегда каждый интерфейс имеет свой разъем DB9. Довольно часто служебные или сервисные интерфейсы выполнены в виде штыръевого male-разъема c 3, 4, 5 пинами или могут быть не распаяны на печатной плате. При наличии исправного источника питания в исследуемом устройстве для связи нам достаточно 3 проводов: RX, TX, GND. Если источник питания отсутствует или неисправен, подключаем дополнительный провод питания Vcc, проверив соотвествие уровней напряжения (5В или 3.3В) порта компьютера и исследуемого устройства. В таких случаях ищем datasheet на используемые микросхемы и подключаемся в удобном месте. 

Работа скрипта проверена на системах Windows 7 x64, Windows 10 x64, Ubuntu 16.04 x64, Debian 8 x32. Для запуска программы необходим установленный интерпретатор python3 и библиотека pyserial. Скачать версию для различных операционных систем можно на официальном сайте https://www.python.org/downloads/. Вне зависимости от разрядности установленной операционной системы лучше устанавливать версию Python 3 x32. В большинстве Linux систем интерпретатор Python присутствует по умолчанию, но необходимо проверить его версию. Для этого запускаем окно терминала и вводим:

sudo apt-get install python3
sudo python3

 

Версия 3.4 установлена, проверяем наличие библиотеки pyserial:

sudo apt-get install python3-pip
sudo pip3 install pyserial

 Далее в домашней директории создаем файл в любом текстовом редакторе:

cd ~
nano comscanner.py

 

 И сохраняем текст скрипта:

#comscanner 0.1
#Скрипт для автоматического определения скорости COM порта путем перебора скорости, четности, стоп-бит
#по заданной сигнатуре в полученном ответе от устройства с возможностью отправки команды перед получением данных
#для отправки команды раскомментировать строку №74 - #ser.write(cmd)
#Работа скрипта проверена на адаптерах USBtoCOM ch440, ft232 в Windows 10 x64, Debian 8 x32, Raspbian jessie
#[email protected]

import sys, glob, time, serial, os, struct, subprocess, threading, struct

std_speeds = ['1843200', '921600', '460800', '230400', '115200', '57600', '38400', '19200', '9600', '4800', '2400', '1200', '600', '300', '150', '100', '75', '50'] #Скорость COM порта
paritys = ['N', 'E', 'O']   #Бит четности
stopbitss = [1, 2]             #Количество стоп-бит
bite_size = 8               #Биты данных
t_out = 1                   #Таймаут в секундах, должен быть больше 1с
flag1=0                     #Флаг для остановки программы, устанавливается в 1, если найдена сигнатура  
reading_bytes = 10          #Количество байт для чтения после открытия порта
keyword=b'\x00\x00\x00'     #!Сигнатура для поиска
cmd = b'\x00\x34\x65'       #!Команда перед началом приема
ser = serial.Serial()

################# Поиск доступных портов windows, linux, cygwin, darwin
def serial_ports():
    if sys.platform.startswith('win'):
        ports = ['COM%s' % (i + 1) for i in range(256)]
    elif sys.platform.startswith('linux') or sys.platform.startswith('cygwin'):
        # this excludes your current terminal "/dev/tty"
        ports = glob.glob('/dev/tty[A-Za-z]*')
    elif sys.platform.startswith('darwin'):
        ports = glob.glob('/dev/tty.*')
    else:
        raise EnvironmentError('Unsupported platform')

    result = []
    for port in ports:
        try:
            s = serial.Serial(port)
            s.close()
            result.append(port)
        except (OSError, serial.SerialException):
            pass
    return result
##################################

print('Сигнатура для поиска ', end = '')
print(keyword)

ports=serial_ports()
if ports:
        print('Доступные порты:')
        print(ports)
        if len(ports)>1:
            ser.port = input('Введите адрес COM порта ')
        else:
            ser.port = ports[0]
            print ('Работаем с портом '+ser.port)
else:
    print('\nНет доступных COM портов, проверьте подключние.\n')
    sys.exit()

try:
    for stop_bit in stopbitss:
        for parit in paritys:
            for com_speed in std_speeds:
                ser.close()
                ser.baudrate = com_speed
                ser.timeout = t_out
                ser.bytesize = bite_size
                ser.parity = parit
                ser.stopbits = stop_bit
                ser.open()
                #ser.write(cmd)                                       #!Раскомментировать при необходимости отправки команды в устройство для инициализации связи                    
                message_b=ser.read(reading_bytes)
                if flag1==1:
                    break
                if message_b:
                    print ('\nRAW data on '+ser.port+', '+com_speed+', '+str(ser.bytesize)+', '+ser.parity+', '+str(ser.stopbits)+':')
                    print ('---------------------')
                    print (message_b)
                    print ('---------------------')
                    try:
                        if keyword in message_b:
                            print ('\n\033[0;33mСигнатура ', end = '') #желтый цвет текста
                            print(keyword, end = '')
                            print(' найдена при следующих настройках: \n'+ser.port+', '+com_speed+', '+str(ser.bytesize)+', '+ser.parity+', '+str(ser.stopbits))
                            print('\x1b[0m')
                            ser.close()
                            flag1=1
                            break
                        else:
                            ser.close()
                    except:
                        print ('error decode')
                        print ('---------------------')
                        ser.close()
                else:
                    print('timeout on '+ser.port+', '+com_speed+', '+str(ser.bytesize)+', '+ser.parity+', '+str(ser.stopbits))
                    print ('---------------------')
                    ser.close()
    if flag1 == 0:
        print('Поиск завершен, сигнатура не найдена')
except serial.SerialException:                                
    print ('Ошибка при открытии порта '+ser.port)
    sys.exit()
                                      
sys.exit()

Для запуска вводим:

sudo python3 comscanner.py

Пример работы скрипта:

 

Запуск в Windows 10:

Перезагружаемся после установки интерпретатора Python 3, сохраняем файл comscanner.py, например, в каталог C:/comscanner/. Нажимаем сочетание Win+X, в появившемся меню выбираем пункт "Командная строка (администратор)" и вводим:

c:
cd c:\comscanner
comscanner.py

Если произошла ошибка "comscanner.py не является внутренней или внешней командой, исполняемой программой или пакетным файлом." - нужно узнать полный путь к установленному Python 3. Запускаем проводник, нажимаем "Вид" - "Показать или скрыть" - отмечаем пункты "Расширения имен файлов" и "Скрытые элементы", открываем - "Локальный диск C:" - Пользователи (Users) - Имя пользователя - AppData - Local - Programs - Python - Python3x. Копируем из адресной строки полный путь как текст и вставляем в открытое окно командной строки. Далее дописываем

python.exe c:\comscanner.py

 

По умолчанию считываются первые 10 байт данных, при необходимости изменяем в переменной reading_bytes. Сигнатуру для поиска (переменная keyword) берем из datasheet на компонент или из инструкции на исследуемое устройство. Если устройство ждет команды для начала передачи дописываем текст команды в переменную cmd и убираем знак комментария # из строки 72   #ser.write(cmd). Команда отправляется последовательно перед чтением и до получения искомой сигнатуры.

 

Последовательность перебора по умолчанию:

стопбит=1, четность=нет, скорость на уменьшение от 1843200 до 50
стопбит=1, четность=чет, скорость на уменьшение от 1843200 до 50
стопбит=1, четность=нечет, скорость на уменьшение от 1843200 до 50
стопбит=2, четность=нет, скорость на уменьшение от 1843200 до 50
стопбит=2, четность=чет, скорость на уменьшение от 1843200 до 50
стопбит=2, четность=нечет, скорость на уменьшение от 1843200 до 50

 

Скачать скрипт comscanner 0.1

 [email protected]


Поделиться записью:

prom-electric.ru

Доступ к портам с использованием WinApi и dll из Python

или взлет на рожденном ползать

Предыдущие реализации на Питоне аналога проприетарного софта, оказались вполне ничего себе, т. е. все работает, и все похоже на Excel, а значит endusers будут довольны-). Дальнейший простор для полета фантазии немного сдерживается невозможностью доступа к более детальным настройкам портов из стандартных модулей. Но оказывается в Питоне есть такая изумительная вещь как доступ к WinApi функциям, что расширяет перспективы чуть ли не до Cpp-шных. Причем это касается не только портов, а еще кучи всяких вещей. Список и краткое описание поддерживаемых WinApi функций для Питона здесь-
docs.activestate.com/activepython/3.3/pywin32/win32file.html, прорва примеров на Nullege здесь — nullege.com/codes/search/win32file и здесь www.programcreek.com/python/index/1133/win32file, ну и как это принято в Питоне избавление от несовершенства модулей — доступ к WinApi функциям, осуществляется через модуль-) — win32file,- соответственно — pip install win32file.
Вот например как может выглядеть настройка и работа Com порта —
сначала понятно импортируем модуль:

import win32file

создаем хэндл:

hFile = win32file.CreateFile(«COM2», win32file.GENERIC_READ | win32file.GENERIC_WRITE, 0,None,win32file.OPEN_EXISTING, 0,None)

тут разница в названиях — стандартным предшествует 'win32file.', и вместо NULLNone
(в названии порта кавычки верхние см. рис. и комменты).
Далее аналогично стандартным процедурам, например в Visual Studo — структура настройки — создаем:

comDCB = win32file.DCB()

настраиваем:

comDCB.ByteSize = 8
comDCB.Parity = win32file.NOPARITY
comDCB.StopBits = win32file.ONESTOPBIT
comDCB.BaudRate = 9600

записываем:

win32file.SetCommState(hFile,comDCB)

рамер входного/выходного буфера:

win32file.SetupComm(hFile, 4096, 4096)

вот например маска(1) по приему первого байта, то чего нет в стандартном модуле pyserial:

win32file.SetCommMask(hFile, 1)

соответственно event:

win32file.WaitCommEvent(hFile, None)

ну и чтение и запись-

buff='пишем чего-нибудь-)'

не забываем, что передаем поток байт — переконвертируем строку в массив байт:

ttt=bytearray(buff, encoding='cp1251')

отправляем:

win32file.WriteFile(hFile,ttt,None)

ждем эвента по приему первого байта и читаем 19 байт:

win32file.WaitCommEvent(hFile, None)
win32file.ReadFile(hFile, 19)



ну и закрыть:

win32file.CloseHandle(hFile)

C LPT все немного по-другому, хотя и можно создать хэндл как показано выше — запись и чтение в файл повидимому приведет к обращению к стандартному драйверу и невозможности записи без получения 'ASK' от 'принтера'. Поэтому, как мне кажется, более удобное — широко известное решение — inpout32.dll.
Для возни с параллельным портом я использую следующий гипердевайс-

по мотивам того, который был представлен на pcports — www.kernelchip.ru/pcports/PS005.php Повторять мне было лень, я сделал проще — задействованы два регистра из трех — чтения нет(регистр Status не задействован). Питание светодиодов счетверенного семисегментного индикатора от высокого состояния одного порта и низкого состояния другого. Такая схема дает возможность использовать динамическую индикацию и оценить быстродействие разных способов вывода через порт, но… не будем забегать вперед-) Итак, пока просто выведем циферку скажем '7' на второй индикатор:
from ctypes import windll
p = windll.LoadLibrary(«C:\Python34\DLLs\inpout32.dll»)
p.Out32(890, 9)
p.Out32(888, 241)

(в названии пути кавычки верхние см. рис. и комменты)

функция возвращает 1 — типа все нормально-)

тут только одно тонкое место, часть выводов в регистре 'Control' инвертирована — ru.wikipedia.org/wiki/Параллельный_порт и это надо учитывать.

Ну и в заключение небольшой сравнительный тест результаты которого меня просто поразили. Две аналогичные программы — на старом VC6 и на Python — функционально это динамическая индикация через LPT порт. В VC6 в обработчике таймера производится пересчет(преобразование) числа в первом окошке в семисегментный код, во втором окне — задается время переключения (таймера). Запуск преобразования кнопка 'Start indicate', остановка — 'Stop'.

В Питоне все аналогично, но таймеров там нет и задержка реализована функцией time.sleep(timer) где timer — время в секундах, в VC6 время задается в миллисекундах. В Питоне в отдельном потоке функции вывода и задержки в бесконечном цикле, в VC функция вывода(такая же как в Питоне) в обработчике таймера, — по каждому срабатыванию выводит по одной цифре. Ну в общем все как обычно, и программная реализация самостоятельного интереса не представляет. А представляет интерес результат — скорости вывода( на вид естественно ) идентичны (!!!), т. е. шустрый питонский байт код, в этих конкретных условиях вполне такой же быстрый как и сишный компиллированный. Вообще-то из-за того что таймер в VC6 вообще нельзя поставить меньше 10 мс(поставить-то можно, толку не будет), а в Питоне задержку можно и 0.001 с, то Питон еще и быстрее, что собственно и видно при последнем включении с задержкой 0.001 с. на видео. Да, и отдельно прошу извинить за качество фоток и видео— снимал телефоном, более того когда снимал, если кто обратил внимание)), задержка в питонской программе стояла в два раза больше чем в сишной (т.е смена цифр была в два раза медленнее — забыл убрать вторую задержку во время отладки — сейчас конечно убрал), будет возможность видео пересниму. Если, что исходник питонской программы внизу, и заодно видео файлом.
P.S. Добавляю ссылку на видео — переснять не получится — слегка спалил LPT порт -(

we.easyelectronics.ru

Как написать сканер портов на языке Python? — asp24.ru

В этой статье мы напишем сканер портов на языке Python. С его помощью можно будет сканировать свои хосты на предмет открытых портов. Например, тот же Mikrotik Routerboard.

Приступаем к написанию.

Для написания сканера будем использовать модуль socket.

#!/usr/bin/env python

# -*- coding: utf_8 -*-

Импортируем модуль для работы с сокетами:

import socket

Вводим IP-адрес хоста, который будем сканировать:

host = raw_input("Введите ip адрес компьютера: ")

Создаем пустой список портов:

ports = []

При помощи функции xrange добавляем в список портов значения от 0 до 65535:

for i in xrange(65536):

ports.append(i)

Создаем пустой список, в который будут занесены открытые порты:

open_port = []

В цикле переберем все порты:

for port in ports:

Создаем новый сокет:

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

Устанавливаем таймаут, чтобы скрипт не приостанавливался, если сокет открыт:

sock.settimeout(0.01)

try:

Выполняем подключение:

sock.connect((host, port))

except:

Если подключиться не удалось, возникает исключение:

print ("Порт %s закрыт" % port)

else:

Если исключения не возникло, добавляем номер открытого порта в список open_port и выводим сообщение о том, что порт открыт:

open_port.append(port)

print ("Порт %s открыт." % port)

Закрываем сокет:

sock.close()

print "\033[34m Открытые порты\033[0m"

Выводим информацию об открытых портах:

print open_port

Выполним сканирование портов устройства Mikrotik Routerboard.

 

Рис.1. Запуск скрипта.

 

Запускаем скрипт для выполнения сканирования.

 

Рис.2. Ввод IP-адреса.

 

Скрипт предлагает ввести IP-адрес, который нужно просканировать.

 

Рис.3. Процесс сканирования.

 

В процессе работы скрипт проверяет весь заданный диапазон портов.

 

Рис.4. Результат работы сканера.

 

В результате работы сканер выдал список открытых портов, на которых запущены различные службы в Mikrotik Routerboard.

 

Евгений Рудченко специально для ASP24.

asp24.ru

запись и чтение из последовательного порта Ru Python

Я прочитал документацию, но не могу найти прямой ответ на это. У меня есть список всех COM-портов, используемых модемами, подключенными к компьютеру. Из этого списка я попытаюсь открыть его, отправьте ему команду, и если он скажет что-нибудь обратно, добавьте его в другой список. Я не совсем уверен, что правильно использую функции чтения и записи pyserial.

i=0 for modem in PortList: for port in modem: try: ser = serial.Serial(port, 9600, timeout=1) ser.close() ser.open() ser.write("ati") time.sleep(3) print ser.read(64) if ser.read(64) is not '': print port except serial.SerialException: continue i+=1 

Я не получаю ничего из ser.read (). Я всегда получаю пустые строки.

ser.read(64) должен быть ser.read(size=64) ; ser.read использует аргументы ключевых слов, а не позиционные.

Кроме того, вы читаете из порта дважды; что вы, вероятно, хотите сделать, это:

 i=0 for modem in PortList: for port in modem: try: ser = serial.Serial(port, 9600, timeout=1) ser.close() ser.open() ser.write("ati") time.sleep(3) read_val = ser.read(size=64) print read_val if read_val is not '': print port except serial.SerialException: continue i+=1 

кусок кода, который работает с python, чтобы читать rs232 на всякий случай, если кому-то еще нужно это

 ser = serial.Serial('/dev/tty.usbserial', 9600, timeout=0.5) ser.write('*99C\r\n') time.sleep(0.1) ser.close() 
  • Использование Pyserial для построения графика времени от напряжения от последовательного порта Arduino
  • Используя PySerial, можно ли ждать данных?
  • PySerial: как отправить команду Ctrl-C на последовательную линию
  • Последовательный порт не работает в перезаписанном коде Python
  • Как открыть последовательный порт с помощью pyserial?
  • Как я могу исправить « Ручка недействительна». С PySerial
  • Повторное подключение к устройству с помощью pySerial
  • Доступ к последовательным портам USB с использованием Python и pyserial
  • Приложение PySerial запускается в оболочке, а не в скрипте py
  • Листинг серийных (COM) портов в Windows?
  • Python AttributeError: объект 'module' не имеет атрибута 'Serial'
  • www.rupython.com

    Список доступных COM-портов с Python Ru Python

    Я ищу простой метод для перечисления всех доступных COM-портов на ПК.

    Я нашел этот метод, но он специфичен для Windows: листинг последовательных портов (COM) в Windows?

    Я использую python 3 с pyserial на win7 (Windows 7).

    Я нашел в pyserial API ( http://pyserial.sourceforge.net/pyserial_api.html ) функцию serial.tools.list_ports.comports (), которая перечисляет COM-порты (именно то, что я хочу).

    import serial.tools.list_ports print(list(serial.tools.list_ports.comports())) 

    Но кажется, что это не работает.

    Когда мой USB-шлюз COM подключен к ПК (я вижу COM5 в диспетчере устройств), у меня нет этого COM-порта. У меня только COM4, ​​который, кажется, подключен к модему (я не вижу его в разделе COM и LPT диспетчера устройств!)

    Вы знаете, почему это не работает? У вас есть другое решение, которое не является специфичным для системы?

    благодаря

    Это код, который я использую.

    Успешно протестированы в Windows 8.1 x64, Windows 10 x64, Mac OS X 10.9.x / 10.10.x / 10.11.x и Ubuntu 14.04 / 14.10 / 15.04 / 15.10 как с Python 2, так и с Python 3.

     import sys import glob import serial def serial_ports(): """ Lists serial port names :raises EnvironmentError: On unsupported or unknown platforms :returns: A list of the serial ports available on the system """ if sys.platform.startswith('win'): ports = ['COM%s' % (i + 1) for i in range(256)] elif sys.platform.startswith('linux') or sys.platform.startswith('cygwin'): # this excludes your current terminal "/dev/tty" ports = glob.glob('/dev/tty[A-Za-z]*') elif sys.platform.startswith('darwin'): ports = glob.glob('/dev/tty.*') else: raise EnvironmentError('Unsupported platform') result = [] for port in ports: try: s = serial.Serial(port) s.close() result.append(port) except (OSError, serial.SerialException): pass return result if __name__ == '__main__': print(serial_ports()) 

    Возможная доработка превосходного ответа Томаса заключается в том, что Linux и, возможно, OSX также пытаются открыть порты и возвращать только те, которые могут быть открыты. Это связано с тем, что Linux, по крайней мере, перечисляет лодку портов как файлы в / dev /, которые не связаны ни с чем. Если вы работаете в терминале, / dev / tty – это терминал, в котором вы работаете, и открытие и закрытие может привести к вашей командной строке, поэтому glob не предназначен для этого. Код:

      # ... Windows code unchanged ... elif sys.platform.startswith ('linux'): temp_list = glob.glob ('/dev/tty[A-Za-z]*') result = [] for a_port in temp_list: try: s = serial.Serial(a_port) s.close() result.append(a_port) except serial.SerialException: pass return result 

    Эта модификация кода Томаса была проверена только на Ubuntu 14.04.

    Доступны несколько вариантов:

    Вызовите QueryDosDevice с NULL lpDeviceName, чтобы перечислить все устройства DOS. Затем используйте CreateFile и GetCommConfig с каждым именем устройства, чтобы выяснить, является ли это последовательным портом.

    Вызовите SetupDiGetClassDevs с ClassGuid GUID_DEVINTERFACE_COMPORT.

    WMI также доступен для программ C / C ++ .

    Есть какой-то разговор о группе новостей win32 и проекте CodeProject, er,.

    уточнение ответа moylop260 :

     import serial.tools.list_ports list = serial.tools.list_ports.comports() connected = [] for element in list: connected.append(element.device) print("Connected COM ports: " + str(connected)) 

    В нем перечислены порты, которые существуют в аппаратном обеспечении, включая те, которые используются. В списке имеется намного больше информации в документации на pyserial tools

  • Что такое кросс-платформенный метод перечисления последовательных портов в Python (включая виртуальные порты)?
  • Общаться с портами Firewire в python
  • Feedparser - KeyError: 'fullcount'
  • Как я могу исправить « Ручка недействительна». С PySerial
  • Специфичность импорта модуля python?
  • Невозможно открыть последовательное соединение в Pyserial: "termios.error: (22, 'Invalid argument')"
  • pySerial write () отлично работает в интерпретаторе Python, но не в скрипте Python
  • Python Serial: как использовать функцию read или readline для чтения более 1 символа за раз
  • Чтение данных из последовательного порта (COM3) с использованием pyserial модуля в Windows XP
  • Pyserial не играет хорошо с виртуальным портом
  • Использование QThread в PyQT для последовательной связи (w. Pyserial)
  • www.rupython.com

    Работа с последовательным портом из консоли Linux

    В предыдущем посте было показано как запустить UART на отладочной плате Launchpad для MSP430. Теперь рассмотрим как общаться с платой при помощи средств командной строки Linux. Используется плата с прошивкой из предыдущего поста. Для подробностей - см. под кат


    Как известно, все устройства последовательных портов представлены файлами устройств в каталоге /dev.Через эти файлы и происходит общение ОС Linux  с внешним устройством на последовательном порту. Чтобы передать что-то на внешнее устройство нужно записать данные в файл устройства, а чтобы считать информацию из устройства --- прочитать данные из файла устройства. Это можно делать при помощи команд cat и echo так же как для обычных файлов на диске. Или внутри программы на С при помощи вызовов ioctl(), read() и write() или библиотеки termios.

    Физическим последовательным портам RS232, к которым подключались диалапные модемы на старых компьютерах, соответствуют файлы устройств /dev/ttyS*, начиная с /dev/ttyS0. Виртуальным последовательным портам, которые создаются различными конвертерами USB<->UART соответствуют файлы устройств /dev/ttyUSB* и /dev/ttyACM*. Ядро Linux автоматически разпознаёт подключенное устройство, загружает для него драйвер и создаёт файл устройства. Вручную устанавливать драйвер, как в ОС Windows не требуется. Например, если подключить к USB преобразователь USB<->UART FT232, то создаётся файл устройства /dev/ttyUSB0, с которым можно работать также как и с обычным последовательным портом. На плате Launcpad находится микросхема TUSB3410, которая тоже представляет собой конвертер USB<->UART. Если подключить её к USB, то создаётся файл устройства /dev/ttyACM0. Чтобы общаться с платой нужно что-либо писать/читать с этого файла.

    Чтобы пользователь мог читать или писать в файл устройства последовательного порта, его нужно добавить в группу dialout. Иначе работать с последовательным портом сможет только администратор root.

    Простейшим приложением с графическим интерфейсом, которое работает с последовательным портом, является CuteCOM. Он обычно уже есть в вашем дистрибутиве Linux. Его можно установить из репозиториев. При помощи CuteCOM мы работали с платой в предыдущем посте. Выглядит CuteCOM вот так:


    Работать с ним крайне просто. Указываем нужное устройство, если его нет в списке, то его можно впечатать вручную. Затем указываем скорость и параметры и нажимаем OpenDevice. В окне видим данные, которые пришли от устройства. В поле ввода в нижней части можем печать строку символов, которые предаются на устройство. Чтобы передать данный нажимаем Enter и смотрим ответ устройства в окне.

    Теперь рассмотрим как работать с COM-портом из командной строки. Для этого служат три команды: stty, cat и echo.

    Команда stty устанавливает параметры и скорость COM-порта. Её формат:

    stty <СКОРОСТЬ> -F <УСТРОЙСТВО> <ПАРАМЕТРЫ>

    Чтобы установить параметры для платы Launchpad для соединения на скорости 9600 нужно выполнить:

    $ stty 9600 -F /dev/ttyACM0 raw -echo

    Параметр raw устанавливает, что данные в компьютер передаются байт за байтом так же как приходят в порт без преобразований. Аппаратное управление потоком отключено. Подробнее о том, что включает и выключает raw - см. man stty. Если не включить raw, то скорее всего ничего работать не будет.

    Теперь в той же консоли нужно набрать

    $ cat /dev/ttyACM0

    И можно смотреть данные, которые приходят от платы. Выход - нажать Ctrl+C.

    Теперь нажимаем на плате RESET и видим, что в консоди напечатался текст.

    Чтобы передать в плату данные, в другой консоли нужно использовать команду echo и перенаправление вывода в файл устройства. Наберём в другой консоли:

    $ echo "1">/dev/ttyACM0

    Видим, что на плате загорелся красный светодиод и в первой консоли было выдано сообщение об этом. Чтобы убрать конец строки в передаваемых данных, то нужно использовать запуск echo -n, а чтобы интерпретировать 16-ричные коды -- нужно echo -e. Ключи можно комбинировать.

    В итоге должно получиться так:


    Чтобы увидеть 16-ричные коды данных, приходящих от устройства, нужно использовать команду hexdump:

    $ cat /dev/ttyACM0|hexdump -C

    Получится вот так:

    Чтобы иметь вывод данных от устройство на экран и в текстовый файл нужно использовать tee:

    $ cat /dev/ttyACM0|tee output.txt

    Все эти команды можно встраивать в свои Bash-скрипты и работать с вашим устройством вообще без программирования со стороны компьютера.

    Про работу с последовательным портом на Python можно прочитать здесь:
    Если нужно написать своё приложение на Qt, котрое работает с устройством на COM-порту, то смотрите здесь http://diymicro.ru/pic-mk-eksperiment-n … yu-qt.html про расширение для Qt qserialport.

    На этом всё.

    ra3xdh.blogspot.com

    Добавить комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *