2008-10-21 5 views
11

He aquí algunos antecedentes sobre lo que estoy tratando de hacer:¿Cómo obligo a un método de escritura de puerto serie a esperar que la línea se borre antes de enviar sus datos?

  1. Abrir un puerto en serie desde un dispositivo móvil a una impresora Bluetooth.
  2. Envía una forma EPL/2 a la impresora Bluetooth, para que entienda cómo tratar los datos que está a punto de recibir.
  3. Una vez que se haya recibido el formulario, enviar algunos datos a la impresora que será impreso en la etiqueta de valores.
  4. Repita el paso 3 tantas veces como sea necesario para cada etiqueta que se va a imprimir.

El paso 2 solo ocurre la primera vez, ya que no es necesario que el formulario preceda a cada etiqueta. Mi problema es que cuando envío el formulario, si envío los datos de la etiqueta demasiado rápido, no se imprimirá. A veces aparece impreso "Fallo de Bluetooth: Radio no operativa" en la etiqueta en lugar de los datos que envié.

he encontrado una forma de evitar el problema de la siguiente manera:

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); 
    } 
} 

Así que, básicamente, puedo coger un TimeoutException y vuelva a intentar el método de escritura después de esperar una cierta cantidad de tiempo (tres segundos parece funcionar todo el tiempo, pero menos y parece arrojar la excepción en todos los intentos). Después de tres intentos, asumo que el puerto serie tiene algo mal y lo dejo saber al usuario.

De esta manera parece funcionar bien, pero estoy seguro de que hay una mejor manera de manejar esto. Hay algunas propiedades en la clase SerialPort que creo que necesito usar, pero realmente no puedo encontrar ninguna buena documentación o ejemplos de cómo usarlas. He intentado jugar con algunas de las propiedades, pero ninguna parece hacer lo que intento lograr.

He aquí una lista de las propiedades que he jugado con:

  • CDHolding
  • CtsHolding
  • DsrHolding
  • DTREnable
  • apretón de manos
  • RTSEnable

Estoy seguro de que una combinación de estos se encargará de lo que estoy tratando de hacer con más gracia.

estoy usando C# (2,0 marco), una impresora Zebra QL 220 + Bluetooth y un dispositivo de mano Windows Mobile 6, si hay alguna diferencia de soluciones.

Cualquier sugerencia sería apreciada.

[ACTUALIZACIÓN]

También debo señalar que el dispositivo móvil está utilizando Bluetooth 2.0, mientras que la impresora está solamente en la versión 1.1. Supongo que la diferencia de velocidad es lo que está causando que la impresora se quede atrás al recibir los datos.

+0

Jason, ¿se contactó con Zebra, y qué dijeron? Me interesa saber cómo resultó esta historia ... –

+0

Hace un tiempo ... Recuerdo que recomendaron el control de flujo de software, que ya habíamos determinado como el mejor enfoque.No recuerdo que mencionen limitar la velocidad de transmisión ni nada por el estilo. –

Respuesta

5

El control de flujo es la respuesta correcta aquí, y puede no estar presente/implementado/aplicable a su conexión bluetooth.

Consulte la especificación de Zebra y vea si implementan, o si puede activar, el control de flujo de software (xon, xoff) que le permitirá ver cuándo se llenan los diversos almacenamientos intermedios.

Además, es poco probable que la radio bluetooth sea capaz de transmitir más de 250k como máximo. Podría considerar limitarlo artificialmente a 9,600 bps, esto le permitirá a la radio mucho espacio para retransmitir, corregir errores, detectar y controlar su propio flujo.

Si todo lo demás falla, el truco que está utilizando en este momento no es malo, pero llamaría al soporte técnico de Zebra y descubriría qué recomiendan antes de darse por vencido.

-Adam

+0

Gracias Adam. Veré lo que dice Zebra. –

2

La cuestión no es probable que con el código de puerto serie, pero con la pila Bluetooth subyacente.El puerto que estás utilizando es puramente virtual, y es poco probable que se haya implementado siquiera el protocolo de enlace (ya que no tendría ningún sentido). CTS/RTS DTR/DSR simplemente no son aplicables para lo que está trabajando.

El problema subyacente es que cuando crea el puerto virtual, debajo tiene que vincularse a la pila de bluetooth y conectarse al dispositivo serie emparejado. El puerto en sí no tiene idea de cuánto tiempo tomará eso y probablemente esté configurado para hacerlo de forma asíncrona (aunque sería responsabilidad exclusiva del OEM del dispositivo cómo hacerlo) para evitar que la persona que llama bloquee durante un período prolongado si no hay el dispositivo emparejado o el dispositivo emparejado está fuera de rango.

Si bien su código puede parecer un hack, es probablemente la mejor y más portátil forma de hacer lo que está haciendo.

Puede utilizar una API bluetooth stack para intentar ver si el dispositivo está allí y vivo antes de conectarse, pero no hay estandarización de las API de pila, por lo que las API Widcom y Microsoft difieren en cómo lo haría, y Widcom es propietario y costoso. Lo que terminaría es un desastre al tratar de descubrir el tipo de pila, cargando dinámicamente una clase de verificador adecuada, haciendo que llame a la pila y busque el dispositivo. A la luz de eso, su encuesta simple parece mucho más limpia, y no tiene que pagar unos $ k por el Widcom SDK.

+0

Buena respuesta. Lo archivaría en "Cuando un hack no es realmente un hack". – endian

+0

Esto explicaría por qué el uso de cualquiera de los clear-to-send, request-to-send opción parecía no tener ningún efecto. –

+1

Realice el desarrollo de dispositivos móviles por un tiempo y tenderá a recopilar varios bits de "cuándo es un hack no realmente un hackeo". De hecho, probablemente creará una pequeña biblioteca de ellos. Es una de esas cosas que hace creer que el desarrollo de escritorio y el desarrollo de dispositivos son prácticamente inválidos. – ctacke

7

Bueno he encontrado una manera de hacer esto sobre la base de las dos sugerencias ya dadas. Necesito configurar mi objeto puerto serie con lo siguiente:

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

Entonces sólo tiene que hacer la llamada de escritura:

serialPort.Write(labelData); 

Desde la impresora Zebra soporta el control de flujo por software, se enviará una Valor XOff para el dispositivo móvil cuando el búfer está casi lleno. Esto hace que el dispositivo móvil espere a que se envíe un valor XOn desde la impresora, notificando efectivamente al dispositivo móvil que puede continuar transmitiendo.

Al establecer la propiedad de tiempo de espera de escritura, concedo un tiempo total permitido para la transmisión antes de que se produzca una excepción de tiempo de espera de escritura. Todavía querría atrapar el tiempo de espera de escritura, como lo había hecho en mi código de muestra en la pregunta. Sin embargo, no sería necesario repetir 3 (o una cantidad arbitraria de) veces, intentando escribir cada vez, ya que el control de flujo del software se iniciaría y detendría la transmisión de escritura del puerto serie.

Cuestiones relacionadas