Como faço para forçar um método de gravação de porta serial para aguardar a linha limpar antes de enviar os seus dados?

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

Pergunta

Eis algumas informações sobre o que estou tentando fazer:

  1. Abrir uma porta serial de um dispositivo móvel a uma impressora Bluetooth.
  2. Envie um formulário EPL / 2 para a impressora Bluetooth, para que ele entende como tratar os dados que ele está prestes a receber.
  3. Uma vez que o formulário foi recebido, enviar alguns dados para a impressora que será impresso em papel de etiqueta.
  4. Repita o passo 3 quantas vezes for necessário para cada etiqueta a ser impressa.

Passo 2 só acontece pela primeira vez, desde que o formulário não precisa preceder cada etiqueta. Meu problema é que quando eu enviar o formulário, se eu enviar os dados da etiqueta demasiado depressa não vai imprimir. Às vezes eu fico "Falha Bluetooth: Radio Não Operacional". Impresso no rótulo em vez dos dados que enviei

Eu encontrei uma maneira de contornar o problema fazendo o seguinte:

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

Então, basicamente, eu posso pegar um TimeoutException e repetir o método de gravação depois de esperar um determinado período de tempo (três segundos parece funcionar o tempo todo, mas menos e parece lançar a exceção cada tentativa). Depois de três tentativas eu só assumir a porta serial tem algo de errado e deixar o know usuário.

Desta forma parece funcionar ok, mas eu tenho certeza que há uma maneira melhor de lidar com isso. Existem algumas propriedades na classe SerialPort que eu acho que eu preciso para usar, mas eu realmente não posso encontrar qualquer documentação bom ou exemplos de como usá-los. Eu tentei brincar com algumas das propriedades, mas nenhum deles parece fazer o que eu estou tentando alcançar.

Aqui está uma lista das propriedades que já joguei com:

  • CDHolding
  • CtsHolding
  • DsrHolding
  • DtrEnable
  • Handshake
  • RTSEnable

Estou certo de alguma combinação destes irá lidar com o que eu estou tentando fazer mais graciosamente.

Eu estou usando C # (2,0-quadro), uma impressora Zebra QL 220+ Bluetooth e um Windows Mobile 6 dispositivo portátil, se isso faz alguma diferença para soluções.

Todas as sugestões serão apreciadas.

[UPDATE]

Gostaria também de salientar que o dispositivo móvel está usando Bluetooth 2.0, enquanto que a impressora é apenas a versão 1.1. Estou assumindo que a diferença de velocidade é o que está causando a impressora a ficar para trás em receber os dados.

Foi útil?

Solução

O controle de fluxo é a resposta correta aqui, e pode não estar presente / implementado / aplicável a sua conexão bluetooth.

Confira o Zebra especificação e ver se eles implementar, ou se você pode ligar, software de controle de fluxo (xon, xoff), que irá permitir que você veja quando os vários buffers estão ficando cheio.

Além disso, o rádio Bluetooth é improvável que seja capaz de transmitir mais rápido do que 250k no máximo. Você pode considerar artificialmente limitando-a 9,600bps -. Isso vai permitir que o rádio um monte de espaço para respirar para retransmissões, correção de erros, detecção e seu próprio controle de fluxo

Se tudo isso falhar, o hack que você está usando agora não é ruim, mas eu chamaria Zebra suporte técnico e descobrir o que eles recomendam antes de desistir.

-Adam

Outras dicas

Bem, eu encontrei uma maneira de fazer isso com base nas duas sugestões já dadas. Eu preciso configurar meu objeto de porta serial com o seguinte:

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

Então eu só precisa fazer a chamada gravação:

serialPort.Write(labelData);

Uma vez que a Zebra controle de fluxo de software impressora suporta, ele irá enviar um valor xoff para o dispositivo móvel quando o buffer está quase cheio. Isso faz com que o dispositivo móvel para esperar por um valor de XON para ser enviado a partir da impressora, efetivamente notificando o dispositivo móvel que possa continuar transmissão.

Ao definir o tempo de gravação fora da propriedade, estou dando um tempo total permitido para a transmissão antes de uma exceção de gravação tempo limite é lançada. Você ainda gostaria de pegar o tempo de espera de gravação, como eu tinha feito no meu código de exemplo na questão. No entanto, não seria necessário fazer um loop 3 (ou uma quantidade arbitrária de) vezes, tentando escrever a cada vez, desde o controle de fluxo de software iria iniciar e parar a transmissão porta de escrita serial.

A questão provavelmente não é com o código de porta serial, mas com a pilha Bluetooth subjacente. A porta que você está usando é puramente virtual, e é improvável que qualquer um dos handshaking é ainda implementado (como seria em grande parte sem sentido). CTS / RTS DTR / DSR são simplesmente não-aplicável para o que você está trabalhando.

O problema subjacente é que quando você cria a porta virtual, debaixo dela tem que ligar para a pilha Bluetooth e conectar-se ao dispositivo serial emparelhado. O porto em si não tem idéia de quanto tempo que pode demorar e ele provavelmente está configurado para fazer isso de forma assíncrona (apesar de que seria puramente até o dispositivo OEM como isso é feito) para evitar que o chamador de bloqueio por um longo período se não houver dispositivo emparelhado ou o dispositivo emparelhado está fora do intervalo.

Enquanto seu código pode sentir como um hack, é provavelmente o melhor caminho, mais portátil para fazer o que você está fazendo.

Você pode usar uma API pilha Bluetooth para tentar ver se o dispositivo está lá e vivo antes de ligar, mas não há padronização de APIs pilha, de modo que as APIs Widcom e Microsoft diferem em como você faria isso, e Widcom é proprietária e caro. O que você acabar com uma confusão de tentar descobrir o tipo de pilha, carregar dinamicamente um apropriado verificador classe, tê-lo chamar a pilha e olhar para o dispositivo. À luz disso, sua enquete simples parece muito mais limpo, e você não tem que desembolsar alguns $ k para o Widcom SDK.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top