Lecteur de code barre python, instruction read bloquante
Répondre à la discussion
Affichage des résultats 1 à 12 sur 12

Lecteur de code barre python, instruction read bloquante



  1. #1
    Brixsm

    Unhappy Lecteur de code barre python, instruction read bloquante


    ------

    Bonjour à tous,
    Voilà maintenant plusieurs semaines en stage où je dois gérer 2 projets dont l'un où je dois réaliser un programme, sous python, qui vise à lire des codes barres à l'aide d'un lecteur GFS4470 de chez datalogic connecté via USB à une Raspberry Pi 3. Lorsque je fais fonctionner le lecteur uniquement, j'obtiens la valeur scannée sans trop de difficulté, le problème est qu'en parallèle (ou asynchrone) je dois transmettre des informations à un afficheur (via modbus) et à une API (USB).
    Or, lorsque je demande la lecture de code barre( fonction contenant une instruction .read() ) celui-ci attend indéfiniment d'avoir quelque chose a se mettre sous la dent que ce soit un "bon" ou un "mauvais" code barre. Tant qu'il n'a rien lu, impossible de poursuivre le programme et de dépasser l'instruction ".read".
    J'ai effectué de nombreuses recherches et essais (en essayant différents modes du scanner) j'ai notamment découvert l'existence des threads, du multitasking, des librairies evdev, asyncio(en passant ma RPi de pyton 2.7 à 3.7), asynchore et select.
    Ce que j'en ai conclu :
    - Asyncio ne me permet pas de "passer" l'instruction bloquante "d'attente de lecture" (pourtant il me semblait que le but d'une librairie ASYNChronous Input Output était de gérer les entrées/sorties des périphériques ???)
    - Asynchore est un ancêtre d'Asyncio, plus fonctionnel depuis python 3.4
    - le multitasking n'est pas possible sur RPi car cela nécessite processeurs
    - le multithread doit être possible mais cela semble assez technique et potentiellement contournable
    - par la librairie .select entre autres mais je ne comprends pas trop comment la mettre en place
    - evdev gère des évènements de type souris ou clavier en parallèle au programme; mais je n'obtiens rien de pertinent même en configurant mon lecteur de code barre en mode clavier (plusieurs modes, en français/anglais) impossible de récupérer des informations de lectures comme des interruptions, mais je vois souvent cette librairie utilisée avec select (dont je rappelle j'ai du mal à saisir le fonctionnement)
    Voilà, j'ai essayé de multiples méthodes et malheureusement mon instruction .read reste bloquante et toutes les autre méthodes que j'ai pu tenter m'ont laissé sans résultats, je précise que jusqu'alors ma connaissance de python se résumait aux tableaux et à tkinter autant dire quasi nulle
    Si vous avez des explications/idées/solutions à m'apporter je suis preneur, il me reste un peu moins de 3 semaines et là je ne vois plus comment faire.. Je sais c'est court pour espérer une réponse mais je tenais vraiment à trouver une solution par moi même...
    Merci d'avance pour vos retours

    -----
    Dernière modification par Brixsm ; 09/02/2022 à 08h36.

  2. #2
    polo974

    Re : Lecteur de code barre python, instruction read bloquante

    Bonjour,
    Déjà, comment est configuré le scanner?
    En usb/oem (alias ibm/usb, à fuir)
    En émulation clavier (le pire choix possible)
    En usb/com (celui-là, je l'aime bien)

    Avec select et compagnie, tu peux attendre des événements de plusieures sources, mais quand tu es réveillé, c'est à toi de trouver qui "a bougé" et donc depuis le même endroit, tu dois donner suite à différents flux.

    Pas très "sexy", mais efficace.

    Les lib async s'appuient sur ça. C'est normalement plus cool, quoi que...

    Le threading, disons que c'est la bombe H pour décortiquer une cacahuète...

    Bref, si pas de truc réseau et pas trop de choses tordues à faire, je me débrouille avec un select, s'il y a du réseau ou du web, j'utilise tornado, entre les 2, asyncio, ça peut aussi être cool, mais de toute façon dans aucun des cas, le programme ne sera un long fleuve tranquille.

    Les lib asynchrones demandent que tu prépares le taf et que tu lances l'ioloop...

    N'oublie pas que si tu débranches / rebranches le scanner, il faut que tu fermes le device et que tu le rouvres... (idem pour les autres périphs usb)

    N'utilise JAMAIS le /dev/ttyusb0 ou autre /dev/hidraw0...
    Car dès qu'il pourra changer de numéro, il le fera...
    Jusqu'ici tout va bien...

  3. #3
    umfred

    Re : Lecteur de code barre python, instruction read bloquante

    ta fonction read du lecteur code barre ne dispose pas d'un paramètre de type timeout (si tu utilises pySerial, il y a un read timeout que l'on peut définir) https://pyserial.readthedocs.io/en/l...erial_api.html ça restera bloquant mais pendant un certain temps (défini en seconde)

  4. #4
    polo974

    Re : Lecteur de code barre python, instruction read bloquante

    mauvaise bidouille, inutile de faire tourner une boucle s'il n'y a rien à faire, autant utiliser un select (ou similaire).

    car on bouffe du cpu pour rien et de plus, on perd en réactivité sur les autres inputs.
    Jusqu'ici tout va bien...

  5. A voir en vidéo sur Futura
  6. #5
    pm42

    Re : Lecteur de code barre python, instruction read bloquante

    Il y des OS multi-tâche sur le Raspberry PI. Donc on peut aussi faire 2 process : un qui lit le lecteur en mode bloquant et met les résultats quelque part, dans un fichier, socket ou n'importe quoi qui permet de communiquer.
    Et un autre qui fait de l'affichage et regarde dans le fichier, socket ou n'importe quoi qui permet de communiquer s'il y a quelque chose de nouveau.

    La librairie de multiprocessing est faite pour ça : https://docs.python.org/3/library/mu...-process-class

  7. #6
    Brixsm

    Re : Lecteur de code barre python, instruction read bloquante

    Bonjour,
    Mon lecteur est en USB/COM.
    J'ai du mal a saisir les possibilités qu'offre la lib select. Cette librairie utilisée seule me permettrait de jongler entre mes différentes entrées sorties de ma RPi en outrepassant l'attente de réponse (avec un timeout peut-être) ? Ou donne un ordre de priorité dans les tâches ?
    Qu'entendez vous par
    c'est à toi de trouver qui "a bougé" et donc depuis le même endroit, tu dois donner suite à différents flux
    ?

    Lorsque j'utilise AsyncIO, je créer mes fonctions asynchrones "async def fct1" et je les appelle dans mon programme via "loop = asyncio.get_event_loop" et "loop.run_until_complete(async io.wait([fct1, fct2, ...]) mais lorsque j'arrive à ma lecture, je suis toujours bloqué.

    Mon problème de lecture ne nécessite pas de connexion réseau particulière.

    J'ouvre le port de mon scanner via " open('/dev/hidraw3') " en effet, en le connectant toujours au même port je n'ai pas de problème, il existe une meilleure solution ?

    J'ai déjà essayé PySerial mais j'obtenais systématiquement un problème de "parité" je ne sais pas pourquoi.

    Pour ce qui est du multi-processing/multitasking il me semblait que ma RPi 3 n'avait qu'un seul processeur de 4 cœurs, donc que ce n'était pas possible, d'où l'idée du multithread, (qui me semblait être la même chose en "moins puissant") mais comme vous me l'avez confirmé ça ne semble pas être la méthode optimale.
    Dernière modification par Brixsm ; 14/02/2022 à 11h06.

  8. #7
    pm42

    Re : Lecteur de code barre python, instruction read bloquante

    Citation Envoyé par Brixsm Voir le message
    Pour ce qui est du multi-processing/multitasking il me semblait que ma RPi 3 n'avait qu'un seul processeur de 4 cœurs, donc que ce n'était pas possible
    On fait du multi-tâche depuis des décennies sur des machine avec 1 processeur et 1 coeur 100 fois moins puissante que la tienne au moins sans problème.
    Dans ton cas, cela revient à déléguer le "select" au noyau du système d'exploitation.

    Citation Envoyé par Brixsm Voir le message
    d'où l'idée du multithread, (qui me semblait être la même chose en "moins puissant")
    Il n'y a pas de différence à part qu'en multithread, la mémoire est partagée ce qui simplifie certaines choses et en complique d'autres.

  9. #8
    pm42

    Re : Lecteur de code barre python, instruction read bloquante

    Petite édition : il y a aussi d'autres différences en multithread mais on ne va pas rentrer dans les détails qui compliqueraient inutilement dans le cas décrit ici.
    Il faut aussi savoir que le multithreading en python, c'est entre l'enfer et l'impossible. Dans un autre langage par contre, c'est sans doute ce que j'aurais recommandé dans ce cas.

  10. #9
    polo974

    Re : Lecteur de code barre python, instruction read bloquante

    Citation Envoyé par Brixsm Voir le message
    Bonjour,

    Mon lecteur est en <strong>USB/COM</strong>.
    ...

    J'ouvre le port de mon scanner via " open(<strong>'/dev/hidraw3'</strong>) " en effet, en le connectant toujours au même port je n'ai pas de problème, il existe une meilleure solution ?
    ...
    C'est contradictoire ! ! !


    si tu fais (dans une console):
    lsusb -d 05f9:
    il doit te rendre un truc du genre (Bus et Device pouvant changer):
    Code:
    Bus 002 Device 004: ID 05f9:4204 PSC Scanning, Inc. Gryphon series (RS-232 emulation mode)
    le 4204 correspond au GFS4470 en mode usb/com.
    il apparaît alors en tant que /dev/ttyACMx (x étant un numéro)

    mais s'il est en mode clavier, il te réponds ça:
    Code:
    Bus 002 Device 025: ID 05f9:2216 PSC Scanning, Inc.

    tu peux avoir plus d'info en faisant lsusb -d 05f9: -v


    tu peux ajouter une règle udev pour avoir un lien avec un nom fixe sur le dev
    créer un fichier 52-perso.rules contenant:
    Code:
    KERNEL!="hidraw[0-9]*", GOTO="not_hid"
    SYMLINK+="HIDRAWnouveau", MODE="0666"
    ATTRS{idVendor}=="05f9", ATTRS{idProduct}=="2216", SYMLINK+="GRYPHON4470KBD"
    GOTO="end"
    LABEL="not_hid"
    
    
    KERNEL!="ttyACM[0-9]*", GOTO="not_ttyacm"
    SYMLINK+="ttyACMnouveau", MODE="0666"
    ATTRS{idVendor}=="05f9", ATTRS{idProduct}=="4204", SYMLINK+="GRYPHON4470COM"
    GOTO="end"
    LABEL="not_ttyacm"
    
    KERNEL!="ttyUSB[0-9]*", GOTO="not_ttyusb"
    SYMLINK+="ttyUSBnouveau", MODE="0666"
    ATTRS{idVendor}=="067b", ATTRS{idProduct}=="2303|23c3", SYMLINK+="PL2303"
    GOTO="end"
    LABEL="not_ttyusb"
    
    # etc... mais attention, une erreur et tout est cassé...
    
    LABEL="end"
    copier ce fichier dans /etc/udev/rules.d/ (avec les droits root)
    débrancher/rebrancher le scanner ou faire un udevadm trigger (avec les droits root)


    (j'ai ajouté le classique pl2303 en exemple de ttyUSB, et mis les dev en rw pour tout le monde (ce qui est une horreur pour la sécu, mais bien pratique))


    la doc se trouve par là:
    https://www.datalogic.com/fra/oem-au...2d-pd-193.html

    la planche spécifique pour changer l'interface:
    https://cdn.datalogic.com/Download?iddwnfile=9963
    la doc complète:
    https://cdn.datalogic.com/Download?iddwnfile=18548
    Attention! bien masquer les autres codes sur la même page...
    Jusqu'ici tout va bien...

  11. #10
    polo974

    Re : Lecteur de code barre python, instruction read bloquante

    Your request has been blocked due to suspicious activity.

    LocalTime : Tuesday, 15-Feb-2022 07:45:15 GMT TransactionID : 9413c525675df425f7b2da1d7477f4 22 Remote Address : ..... Remote Country : Reunion (RE) Method : GET Requested URL : https://forums.futura-sciences.com/n...reply&t=918327 Protocol : HTTP/2.0 User Agent : Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:97.0) Gecko/20100101 Firefox/97.0 Please contact the webmaster of this website and provide the information above if you think this is a mistake.

    quand on met du python3 en code ! ! !
    Jusqu'ici tout va bien...

  12. #11
    polo974

    Re : Lecteur de code barre python, instruction read bloquante

    gag.zip

    dans un zip, ça passera peut-être...
    Jusqu'ici tout va bien...

  13. #12
    Brixsm

    Re : Lecteur de code barre python, instruction read bloquante

    OK j'ai finalement réussi à outrepasser mon instruction bloquante "open() + read()" par un "serial.serial() + read()" avec un timeout(très faible) dans le serial.serial, le tout avec mon scanner en mode USB/COM et en changeant le port.
    Merci beaucoup pour vos réponses, je note qu'à l'avenir je me tournerais plus vers du serial.serial() que du open()

Discussions similaires

  1. remplacer lecteur code barre par lecteur rfid
    Par finalkim dans le forum Bricolage et décoration
    Réponses: 0
    Dernier message: 23/12/2015, 22h00
  2. PIC & lecteur code a barre
    Par inviteba1c2ffa dans le forum Électronique
    Réponses: 7
    Dernier message: 05/04/2012, 20h57
  3. lecteur code a barre /pic
    Par invite2cc4dbb7 dans le forum Électronique
    Réponses: 0
    Dernier message: 17/04/2010, 14h18
  4. [TPE] Lecteur code barre
    Par MisterCyp59 dans le forum Électronique
    Réponses: 5
    Dernier message: 24/01/2010, 10h37