Comment forcer une méthode d'écriture sur port série à attendre que la ligne s'efface avant d'envoyer ses données?

StackOverflow https://stackoverflow.com/questions/222455

Question

Voici un aperçu de ce que j'essaie de faire:

  1. Ouvrez un port série d'un périphérique mobile vers une imprimante Bluetooth.
  2. Envoyez un formulaire EPL / 2 à l’imprimante Bluetooth afin qu’elle comprenne comment traiter les données qu’elle est sur le point de recevoir.
  3. Une fois le formulaire reçu, envoyez à l'imprimante des données qui seront imprimées sur le stock d'étiquettes.
  4. Répétez l'étape 3 autant de fois que nécessaire pour chaque étiquette à imprimer.

L'étape 2 n'a lieu que la première fois, car le formulaire n'a pas besoin de précéder chaque étiquette. Mon problème est que lorsque j'envoie le formulaire, si j'envoie les données d'étiquette trop rapidement, elles ne seront pas imprimées. Parfois, j'obtiens un "échec Bluetooth: radio non opérationnelle". imprimé sur l'étiquette au lieu des données que j'ai envoyées.

J'ai trouvé un moyen de contourner le problème en procédant comme suit:

for (int attempt = 0; attempt < 3; attempt++)
{
    try
    {
        serialPort.Write(labelData);
        break;
    }
    catch (TimeoutException ex)
    {
        // Log info or display info based on ex.Message
        Thread.Sleep(3000);
    }
}

Donc, en gros, je peux attraper une exception TimeoutException et réessayer la méthode d’écriture après avoir attendu un certain temps (trois secondes semblent fonctionner tout le temps, mais pas moins et il semble lancer l’exception à chaque tentative). Après trois tentatives, je suppose que le port série a un problème et que l'utilisateur le sache.

Cela semble fonctionner correctement, mais je suis sûr qu'il existe un meilleur moyen de gérer cela. Il y a quelques propriétés dans la classe SerialPort que je pense devoir utiliser, mais je ne trouve pas vraiment de bonne documentation ni d'exemples sur la façon de les utiliser. J'ai essayé de jouer avec certaines des propriétés, mais aucune ne semble faire ce que j'essaie de faire.

Voici une liste des propriétés avec lesquelles j'ai joué:

  • CDHolding
  • CtsHolding
  • DsrHolding
  • DtrEnable
  • poignée de main
  • RtsEnable

Je suis sûr qu'une combinaison de ces éléments résoudra ce que j'essaie de faire avec plus de grâce.

J'utilise C # (structure 2.0), une imprimante Bluetooth Zebra QL 220+ et un périphérique portable Windows Mobile 6, si cela peut changer les solutions.

Toutes les suggestions seraient appréciées.

[UPDATE]

Je dois également noter que le périphérique mobile utilise Bluetooth 2.0, tandis que l'imprimante est uniquement à la version 1.1. Je suppose que la différence de vitesse est la cause de la lenteur avec laquelle l'imprimante reçoit les données.

Était-ce utile?

La solution

Le contrôle de flux est la bonne réponse ici, et il se peut qu’il ne soit pas présent / implémenté / applicable à votre connexion Bluetooth.

Vérifiez les spécifications de Zebra et voyez si elles implémentent, ou si vous pouvez activer, le contrôle de flux logiciel (xon, xoff) qui vous permettra de voir quand les divers tampons seront pleins.

De plus, il est peu probable que la radio bluetooth soit capable de transmettre plus de 250k au maximum. Vous pouvez envisager de le limiter artificiellement à 9 600 bps, ce qui laissera à la radio beaucoup de marge de manœuvre pour les retransmissions, la correction des erreurs, la détection et son propre contrôle de flux.

Si tout échoue, le hack que vous utilisez actuellement n’est pas mauvais, mais j’appellerais le support technique de Zebra pour savoir ce qu’ils recommandent avant de baisser les bras.

-Adam

Autres conseils

Eh bien, j'ai trouvé un moyen de le faire en me basant sur les deux suggestions déjà données. Je dois configurer mon objet de port série avec les éléments suivants:

serialPort.Handshake = Handshake.RequestToSendXOnXOff;
serialPort.WriteTimeout = 10000; // Could use a lower value here.

Ensuite, il me suffit de faire l'appel d'écriture:

serialPort.Write(labelData);

Comme l’imprimante Zebra prend en charge le contrôle de flux logiciel, elle enverra une valeur XOff au périphérique mobile lorsque la mémoire tampon est presque pleine. Le périphérique mobile attend alors qu'une valeur XOn soit envoyée par l'imprimante, ce qui l'avertit de la possibilité de continuer à transmettre.

En définissant la propriété de délai d'écriture, je donne le temps total imparti pour la transmission avant qu'une exception de délai d'écriture ne soit levée. Vous voudriez toujours intercepter le délai d’écriture, comme je l’avais fait dans mon exemple de code dans la question. Toutefois, il ne serait pas nécessaire de boucler 3 fois (ou une quantité arbitraire de), en essayant d’écrire à chaque fois, car le contrôle de flux logiciel commencerait et arrêterait la transmission d’écriture du port série.

Le problème ne vient probablement pas du code du port série, mais de la pile Bluetooth sous-jacente. Le port que vous utilisez est purement virtuel et il est peu probable qu'une telle poignée de main soit même mise en œuvre (car cela n'aurait en gros pas de sens). Les CTS / RTS DTR / DSR ne sont tout simplement pas applicables à votre travail.

Le problème sous-jacent est que, lorsque vous créez le port virtuel, il doit se lier à la pile Bluetooth et se connecter au périphérique série couplé. Le port lui-même n'a aucune idée du temps que cela pourrait prendre et il est probablement configuré pour le faire de manière asynchrone (bien que cela incombe au fabricant OEM du périphérique), afin d'éviter que l'appelant ne se bloque pendant une longue période s'il n'y a pas appareil associé ou l'appareil associé est hors de portée.

Votre code peut sembler être un hack, mais c'est probablement le meilleur moyen, le plus portable, de faire ce que vous faites.

Vous pouvez utiliser une API de pile bluetooth pour voir si le périphérique est présent et actif avant de vous connecter, mais il n'y a pas de normalisation des API de pile. Par conséquent, les API Widcom et Microsoft diffèrent quant à la façon de procéder. Widcom est propriétaire et coûteux. Vous vous retrouvez avec un fouillis d'essayer de découvrir le type de pile, de charger dynamiquement une classe de vérificateurs appropriée, de le faire appeler la pile et de rechercher le périphérique. À la lumière de cela, votre sondage simple semble beaucoup plus propre et vous n’aurez pas à débourser quelques k $ pour le SDK Widcom.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top