Generic serial and TCP
Equipamentos que falam um protocolo próprio de texto ou de bytes, como balanças e leitores de código de barras, por uma linha serial, TCP ou UDP: como as mensagens deles terminam e são conferidas, e como cada tag tira o valor delas.
O driver Generic serial and TCP lê e escreve equipamentos que falam um protocolo próprio, feito de texto ou de bytes simples, onde nenhum protocolo padrão se aplica: uma balança, um leitor de código de barras ou de RFID, um instrumento antigo, uma impressora de etiquetas. Não dá para perguntar a esse equipamento o que ele é, então nada é descoberto. Você diz ao dispositivo como termina uma mensagem que ele envia e como o checksum dela é conferido, e diz a cada tag como ela obtém o valor, quais mensagens são dela e quais caracteres da mensagem são o valor.
Um dispositivo alcança o equipamento de uma de três formas, escolhida quando ele é criado:
| Transporte | Como o dispositivo é alcançado | O que as tags dele podem fazer |
|---|---|---|
| Numa linha serial | Uma linha serial deste driver, compartilhada com os outros dispositivos dela, uma requisição por vez. | Requisição e resposta, escuta, escritas. |
| Cliente TCP | Uma conexão própria com o host e a porta do equipamento. | Requisição e resposta, escuta, escritas. |
| Escuta UDP | Uma porta desta estação para a qual o equipamento envia datagramas. A estação não envia nada. | Só escuta, só leitura. |
Um dispositivo numa linha serial fica pendurado na linha, então essa parte da árvore fica Driver → Linha → Dispositivo → Tag, como no Modbus RTU. Um dispositivo de rede fica sob o driver e pode ser arquivado em pastas como o dispositivo de qualquer outro driver, Driver → Pasta → Dispositivo → Tag. Um dispositivo fica do lado em que foi criado: TCP e UDP trocam entre si, mas um dispositivo nunca passa de uma linha para a rede nem da rede para uma linha.
A página do driver
A frase abaixo do cabeçalho diz "As linhas seriais levam os instrumentos que compartilham um barramento, e os dispositivos de rede ficam sob o driver. Acrescente uma linha ou um dispositivo e depois abra-o para descrever as mensagens dele." e a página traz duas tabelas, uma abaixo da outra:
| Tabela | O que a faz crescer | O que ela lista |
|---|---|---|
| Linhas seriais | Acrescentar linha, à direita do título. | As linhas do driver: Linha, Parâmetros físicos (porta · baud · formato, sem timeout, porque uma linha deste driver não tem), Dispositivos, Estado, e as ações Abrir, Habilitar, Desabilitar e Excluir. Vazia, diz "Nenhuma linha serial ainda." |
| Dispositivos | Acrescentar dispositivo, à direita do título. Cria um dispositivo de rede, um Cliente TCP. | Todo dispositivo do driver, os de linha incluídos, com as colunas da tabela de dispositivos de qualquer driver. Vazia, diz "Nenhum dispositivo ainda." |
O cabeçalho conta os dispositivos entre parênteses, e a linha do driver na árvore conta os dois níveis quando existe uma linha ("1 linha · 2 dispositivos"). A barra do driver não tem Descobrir. O menu de contexto da linha do driver oferece Acrescentar dispositivo, Acrescentar linha, Nova pasta e Atualizar, e depois, após um separador, Remover o driver; no menu Novo… da coluna, a entrada do driver oferece Novo dispositivo, Nova linha serial e Nova pasta, e depois as linhas, as pastas e os dispositivos dele. Depois de acrescentado, o driver fica sob a pasta Drivers da árvore, com ou sem linha ou dispositivo.
Linha serial
Uma linha deste driver é a linha descrita em Linhas seriais, com menos campos. A página dela diz "Um barramento serial físico: os ajustes de porta que os instrumentos dele compartilham, uma requisição por vez." e o cartão Linha física traz:
| Campo | Significado | Padrão |
|---|---|---|
| Nome | O nome amigável do barramento, mostrado na árvore e em cada dispositivo dele. | "Nova linha" |
| Porta serial | A porta COM do Windows, física, virtual ou redirecionada, digitada ou escolhida entre as portas que o Windows relata (Atualizar as lê de novo). Uma porta pertence a uma linha, seja qual for o driver da linha. | a primeira porta livre |
| Velocidade em baud | A velocidade do barramento, compartilhada por todo dispositivo da linha. | 9600 |
| Formato serial | Bits de dados, paridade e bits de parada: 8N1, 8N2, 8E1, 8E2, 8O1, 8O2, 7N2, 7E1, 7E2 ou 7O1. Os dez são oferecidos, porque este driver não precisa de 8 bits de dados. |
8E1 |
Uma linha criada aqui nasce desabilitada, para que os ajustes da porta sejam digitados antes de a porta abrir. A porta, a velocidade e o formato só mudam com a linha desabilitada; o nome muda a qualquer momento. Uma linha deste driver não tem modo de transmissão, timeout de resposta, intervalo mínimo entre transações nem silêncio automático: cada dispositivo dela diz no próprio painel como as mensagens dele terminam e quanto ele espera por uma resposta, como diz o cartão Dispositivos abaixo da linha: "Todo dispositivo desta linha compartilha os ajustes da porta. Cada um diz no próprio painel como suas mensagens terminam e quanto espera por uma resposta." Ela não tem o cartão Descobrir unidades, e a tabela Dispositivos dela não tem a coluna ID da unidade, porque um instrumento se distingue pelo que as requisições dele dizem, não por um endereço.
Acrescentar dispositivo na linha, ou no menu de contexto dela, cria um dispositivo deste driver nessa linha. Uma linha pertence ao driver sob o qual foi criada, para sempre: um dispositivo Modbus RTU e um dispositivo deste driver nunca compartilham uma linha, e um agente que aponta um dispositivo para uma linha do outro driver é recusado. Os estados da linha (Desligado, Ocioso, Conectando…, Conectado, Falha na porta) são os de toda linha serial, em Habilitação e saúde.
Na linha, o driver abre a porta uma vez para todos os dispositivos dela e envia uma requisição por vez, esperando a resposta antes da próxima. Entre as requisições, o que chega é oferecido a todo dispositivo da linha, cada um cortando em mensagens pelas próprias regras. Uma porta que falha é reaberta pela linha para todos os dispositivos dela, com espera cada vez maior entre as tentativas enquanto continua falhando.
Dispositivo
Conexão
| Campo | Significado | Padrão |
|---|---|---|
| Transporte | Só num dispositivo de rede. Cliente TCP: "A estação se conecta ao host e à porta do dispositivo." Escuta UDP: "A estação escuta numa porta local o que o dispositivo envia e não envia nada." Os dois trocam entre si; um dispositivo numa linha mostra a linha no lugar. | Cliente TCP |
| Host ou IP | TCP: o nome do host ou o endereço IP do equipamento. Dá para colar um endereço inteiro, com tcp:// na frente e a porta depois do host. |
vazio |
| Porta | TCP: a porta em que o equipamento atende, de 1 a 65535. Nenhuma porta é padrão para esse tipo de equipamento, então um dispositivo novo não tem nenhuma. | vazio |
| Aceitar de | UDP, no lugar do host: "Só os datagramas deste endereço são lidos. Vazio: qualquer remetente." | vazio |
| Porta local | UDP, no lugar da porta: "A porta desta estação para a qual o dispositivo envia. O firewall do Windows precisa liberá-la." | vazio |
| Linha serial · fixa | Um dispositivo numa linha: o nome da linha sobre a porta, a velocidade e o formato dela, só leitura. | a linha sob a qual ele é acrescentado |
Um dispositivo TCP novo diz "Host ainda não informado" e não é conectado enquanto não tiver um host e uma porta. Um dispositivo com host e sem porta, e um dispositivo UDP sem a porta local, não podem ser salvos: "Informe a porta: a do dispositivo por TCP, a porta local de escuta por UDP." Um dispositivo numa linha não tem host, porta nem pasta, e não tem unit id.
A Base URI que o cabeçalho mostra é o endereço de runtime: generic://tcp/<host>:<port>,
generic://udp/<local port> (com from=<sender> quando Aceitar de está preenchido) ou
generic://serial/<line id>/<port>/<baud>/<format>, seguido de como as mensagens terminam e são
conferidas (end, start, terminator, length, gap, timeout, checksum e o resto). Os
bytes que ela leva são bytes, nunca a notação em que o dispositivo é digitado. A cópia de um
dispositivo numa linha fica nessa linha; a cópia de um dispositivo de rede vai para o nível do
próprio driver.
O cartão Mensagens
Abaixo do cartão Conexão, o cartão Mensagens diz como os bytes são digitados e como uma mensagem termina.
| Campo | Significado | Padrão |
|---|---|---|
| Digitado como | Como se escrevem o marcador de início, o terminador e, em cada tag, a requisição, o filtro, o separador, a mensagem de escrita e a resposta esperada. Texto com escapes: caracteres imprimíveis como são, \r, \n, \t, \\ e \xNN para qualquer outro byte. Bytes em hexadecimal: dois dígitos por byte, como 02 30 31 0D. Trocar reescreve todo campo de bytes do dispositivo e das tags dele, para que cada um continue enviando os mesmos bytes; enquanto um deles não for um byte válido, a troca é recusada: "A notação não foi trocada: um campo de bytes deste dispositivo ou das tags dele não é válido na notação em uso. Corrija-o antes." |
Texto com escapes |
| A mensagem termina com | Terminador, Tamanho fixo ou Silêncio. Por UDP, cada datagrama é uma mensagem, diga isto o que disser. | Terminador |
| Terminador | Com Terminador: os bytes que fecham toda mensagem. Eles não fazem parte do que as tags leem. | \r\n |
| Tamanho da mensagem (bytes) | Com Tamanho fixo, de 1 a 1024: "Toda mensagem tem esta quantidade de bytes, contando o marcador de início e o checksum." | |
| Silêncio (ms) | Com Silêncio, de 5 a 10000: "Uma mensagem termina quando nada chega durante este tempo." | 50 |
| Marcador de início | Opcional. Os bytes com que toda mensagem começa, como \x02. Os bytes antes dele são descartados, o que também põe de volta no compasso um fluxo pego no meio de uma mensagem, e ele conta como os primeiros caracteres da mensagem. |
vazio |
| Timeout de resposta (ms) | De 50 a 60000: "Quanto tempo uma requisição espera pela resposta, e uma escrita pela resposta esperada." | 1000 |
| Tempo máximo sem mensagem (s) | De 0 a 86400, 0 quer dizer nunca: "As tags em escuta deixam de valer como leitura quando nada chega durante este tempo. 0: nunca, para um dispositivo que só envia de vez em quando, como um leitor de código de barras. Ajuste-o para um dispositivo que envia o tempo todo, como uma balança." | 0 |
Um campo que o fim escolhido não lê não aparece e guarda o valor para quando esse fim voltar. Um valor com que o dispositivo não consegue trabalhar não é salvo, e o feed diz por quê, por exemplo "Informe o terminador com que as mensagens terminam, como \r\n." ou "O tamanho da mensagem precisa estar entre 1 e 1024 bytes."
O cartão Soma de verificação
| Campo | Significado | Padrão |
|---|---|---|
| Algoritmo | O checksum que toda mensagem traz: Nenhum, Soma (8 bits), Complemento de dois da soma (LRC), Complemento de dois da soma de 7 bits (Toledo), XOR (8 bits), CRC-16/MODBUS ou CRC-16/CCITT. "Uma mensagem cujo checksum não confere é descartada e contada no diário, nunca lida como valor." | Nenhum |
| Escrito como | Texto hexadecimal, o checksum escrito em dígitos hexadecimais, ou Bytes brutos, os próprios bytes do checksum. | Texto hexadecimal |
| Posição | Antes do fim: os últimos bytes antes do terminador, ou os últimos bytes da mensagem. Depois do terminador: logo depois dele, que então fica coberto; oferecido só quando as mensagens terminam com um terminador. | Antes do fim |
| Bytes deixados de fora no início | De 0 a 255: "Bytes no início da mensagem que o checksum não cobre, como um STX ou um $." | 0 |
| Bytes deixados de fora antes dele | De 0 a 255: "Bytes logo antes do checksum que ele não cobre, como o * de uma sentença NMEA. As tags também não os leem." | 0 |
Todo campo além do algoritmo só aparece depois que um checksum é escolhido. O checksum cobre a mensagem do primeiro byte até o byte antes do checksum, menos os bytes deixados de fora. Uma mensagem cujo checksum não confere nunca é lida como valor: ela é descartada, e o diário registra isso sob o dispositivo no máximo uma vez por minuto. O checksum é só conferido: requisições e escritas são enviadas exatamente como digitadas, então uma requisição que precisa de checksum o leva nos próprios bytes.
| Algoritmo | Uso comum |
|---|---|
| Soma (8 bits) | Indicadores. |
| Complemento de dois da soma (LRC) | Indicadores, quadros no estilo do Modbus ASCII. |
| Complemento de dois da soma de 7 bits (Toledo) | A saída contínua de um indicador Toledo, como um byte bruto depois do CR. |
| XOR (8 bits) | Sentenças NMEA 0183 ($…*hh), indicadores, leitores de RFID. |
| CRC-16/MODBUS | Quadros binários; o byte baixo primeiro em bytes brutos. |
| CRC-16/CCITT | Quadros binários (a variante CCITT-FALSE); o byte alto primeiro em bytes brutos. |
Endereçamento da tag
Uma tag deste driver não tem endereço para digitar: o cartão Origem dela pergunta como ela obtém o valor, nos campos abaixo. Os bytes são digitados na notação do dispositivo.
| Campo | Significado | Padrão |
|---|---|---|
| Modo de leitura | Requisição e resposta: "A estação envia a requisição no intervalo de leitura da tag e lê o valor na resposta." Escuta: "O dispositivo envia por conta própria, e a tag guarda a última mensagem que o filtro dela aceita." Um dispositivo UDP oferece só Escuta: "Este dispositivo escuta por UDP e não envia nada: as tags dele só ficam em escuta e são só de leitura." | Requisição e resposta |
| Requisição | Só em requisição e resposta: "O que a estação envia no intervalo de leitura da tag, digitado como o dispositivo define. A primeira mensagem que o filtro aceita dentro do timeout de resposta é a resposta." | obrigatória |
| Filtro de mensagens | Quais mensagens pertencem à tag: Todas as mensagens, Começa com (os bytes com que começam) ou Corresponde a uma expressão regular (a Expressão regular a que correspondem). Numa requisição, "Qual mensagem responde à requisição. As outras seguem para as tags em escuta." | Todas as mensagens |
| O valor é | Como o valor é recortado da mensagem: A mensagem inteira, Posição fixa (Primeiro caractere e Tamanho), Campo entre separadores (Separador e Número do campo) ou Grupo de captura de um padrão (Padrão). "Posições e campos contam a partir de 1. O padrão precisa de exatamente um grupo de captura, o valor. Os números são lidos com ponto decimal." | A mensagem inteira |
| O dispositivo usa vírgula como separador decimal | Só em tags Float e Double. A vírgula é o separador decimal na leitura e na escrita. | desligado |
| Mensagem de escrita | Tags que são escritas, fora do UDP: "O que uma escrita envia, com onde vai o valor, como SP \r, ou para formatá-lo. Numa tag Boolean, uma mensagem de escrita sem é um comando, enviado quando se escreve true." | vazio |
| Resposta esperada | "Opcional. Com o que começa a resposta do dispositivo a uma escrita. A escrita só dá certo quando essa resposta chega dentro do timeout de resposta." | vazio |
Os caracteres são contados do início da mensagem, o marcador de início incluído; o terminador, o checksum e os bytes que o checksum deixa de fora antes dele não fazem parte do que uma tag lê. Um padrão é uma expressão regular do .NET, e uma mensagem que ele leva mais de 250 ms para ler não é lida. Uma tag Somente escrita não tem campos de requisição, filtro ou valor; uma tag sem mensagem de escrita é só de leitura.
Os tipos de dado são Boolean, Int32, Int64, Float, Double e String. O texto recortado é lido como o
tipo da tag antes que os estágios da própria tag o convertam, como em todo driver (veja
A cadeia de valor): um Boolean lê 1, true, on ou yes e 0,
false, off ou no; um inteiro lê um número inteiro (12.0 vira 12, 12.5 é recusado); um
Float ou um Double lê um número decimal; um String pega os caracteres como são. Os espaços em volta
de um número, e entre o sinal e os dígitos, são ignorados, porque os indicadores preenchem os
números com espaços. Uma tag cujos campos não funcionam não é salva, e a página da tag diz o que
falta, por exemplo "Informe a requisição que esta tag envia." ou "O padrão precisa de exatamente um grupo de captura, em volta do valor."
A prévia somente leitura do endereço de barramento traz ask ou listen seguido do que se aplica,
por exemplo listen?extract=position&start=5&length=6, ou ask?send=01RD%0D&extract=field&separator=,&field=3
para uma tag que envia 01RD e um CR e lê o terceiro campo separado por vírgula da resposta.
Leitura
| Situação | Tag de requisição e resposta | Tag em escuta |
|---|---|---|
| O valor | Da primeira mensagem conferida que o filtro aceita dentro do timeout de resposta depois da requisição. | Da última mensagem conferida que o filtro aceita, datada pela chegada. |
| Quando é lido | No intervalo de leitura da tag. | Sempre que o equipamento envia; a tag mostra a última mensagem no intervalo de leitura dela. |
| Antes da primeira mensagem | Não se aplica. | A tag espera: sem valor e sem erro, como qualquer tag antes da primeira resposta. |
| Sem resposta, ou equipamento calado | Nenhuma resposta dentro do timeout de resposta é uma leitura que falhou, e a política da tag para um dispositivo que não respondeu decide o que ela mostra. | Passado o Tempo máximo sem mensagem (s) do dispositivo, toda tag em escuta falha a leitura e a política dela decide o que ela mostra. Uma conexão TCP que cai faz todas falharem, diga esse tempo o que disser. |
| Uma mensagem que a tag não consegue ler | Uma leitura que falhou, com o motivo: um campo que falta, o valor passando do fim da mensagem, ou um texto que o tipo não comporta. | O mesmo. |
As mensagens que não respondem a nenhuma requisição seguem para as tags em escuta do mesmo dispositivo, então um dispositivo pode ter os dois tipos de tag. Tags em escuta com o mesmo filtro compartilham o que foi ouvido, e podem tirar campos diferentes da mesma mensagem.
Escrita
Uma escrita passa pelo mesmo funil que a de qualquer outro driver: a caixa de escrita recebe o valor de engenharia, e os estágios de conversão são revertidos antes de o valor bruto ser enviado (veja Connector).
| Mensagem de escrita | O que é enviado | O que a escrita relata |
|---|---|---|
Com {value} |
Os bytes digitados, com o valor onde está {value}: um número em cultura invariante (com vírgula como separador decimal quando a tag diz isso), ou formatado por {value:FORMAT} com um formato numérico do .NET (W{value:000.0}\r envia 12,5 como W012.5 e um CR); um Boolean como 1 ou 0; um texto como é. |
Concluída assim que enviada. Com uma Resposta esperada, concluída só quando chega uma resposta que começa com ela dentro do timeout de resposta; outra resposta recusa a escrita com essa resposta como motivo, e silêncio é falta de resposta. |
Sem {value}, numa tag Boolean |
Um comando, como uma tara ou uma impressão: escrever true o envia, escrever false é recusado. | O mesmo. |
| Nenhuma | Nada: a tag é só de leitura. |
As escritas esperam a vez na fila do dispositivo como as de todo driver: numa linha elas compartilham a requisição por vez da linha, no TCP a conexão própria do dispositivo. Um dispositivo UDP não envia nada, então as tags dele não podem ser escritas.
Exemplo: uma balança em RS-232
Um indicador no estilo da saída contínua da Toledo envia, muitas vezes por segundo, um STX, três bytes de estado, seis dígitos de peso, seis de tara, um CR e um byte de checksum. Na estação:
- Acrescentar linha na página do driver; dê o nome
Scale line, escolhaCOM3, mantenha Velocidade em baud 9600 e escolha7E1como Formato serial, depois Habilitar a linha. - Acrescentar dispositivo na linha; dê o nome
Scale. No cartão Mensagens mantenha Texto com escapes e Terminador, ponha o Terminador em\r, o Marcador de início em\x02e o Tempo máximo sem mensagem (s) em 10, para que um cabo solto apareça como comunicação perdida. - No cartão Soma de verificação escolha Complemento de dois da soma de 7 bits (Toledo), Bytes brutos e Depois do terminador, com as duas contagens de bytes deixados de fora em 0.
- Acrescentar tag; dê o nome
Weight, Double, Somente leitura. No cartão Origem escolha Escuta, Todas as mensagens e Posição fixa, com Primeiro caractere 5 e Tamanho 6: o STX é o caractere 1, os três bytes de estado são do 2 ao 4, o peso do 5 ao 10. - Os dígitos não trazem ponto decimal, então o estágio Escala da tag o põe no lugar, por exemplo um fator de 0,01 para um indicador ajustado em duas casas decimais.
Um agente faz o mesmo com três chamadas de ferramenta:
serial_line_upsert driver=GenericSerialTcp name="Scale line" serialPort=COM3 baudRate=9600 serialFormat=7E1
device_upsert driver=GenericSerialTcp name=Scale transport=SerialLine serialLineId=<id> messageEnd=Terminator terminator=\r startMarker=\x02 checksum=SumTwosComplement7Bit checksumFormat=Raw checksumPlacement=AfterEnd silenceTimeoutSeconds=10
tag_upsert device=Scale name=Weight opcUaType=Double tagMode=Listen valueExtraction=FixedPosition valueStart=5 valueLength=6
Exemplo: um leitor de código de barras em TCP
Um leitor de código de barras com porta Ethernet envia um código por linha, e só quando lê um:
- Acrescentar dispositivo na página do driver; dê o nome
Reader, mantenha Cliente TCP e informe Host ou IP 192.168.0.40 e Porta 2001. - No cartão Mensagens mantenha Texto com escapes, Terminador
\r\ne Tempo máximo sem mensagem (s) 0: um leitor que passa uma hora sem enviar nada não está com defeito. Mantenha Nenhum no cartão Soma de verificação. - Acrescentar tag; dê o nome
Code, String, Somente leitura. No cartão Origem escolha Escuta, Todas as mensagens e A mensagem inteira.
O mesmo com as ferramentas do agente:
device_upsert driver=GenericSerialTcp name=Reader transport=TcpClient host=192.168.0.40 port=2001 messageEnd=Terminator terminator=\r\n
tag_upsert device=Reader name=Code opcUaType=String tagMode=Listen valueExtraction=WholeMessage
driver_capabilities descreve este driver em genericSerialTcp, com estes dois exemplos, e
serial_line_upsert cria uma linha deste driver com driver=GenericSerialTcp; as outras
ferramentas estão em As ferramentas, área por área.
Limites que vale conhecer
- Nada é descoberto: não há protocolo para perguntar a esse equipamento o que ele é ou o que guarda.
- Um quadro binário que anuncia o próprio tamanho num cabeçalho não é lido; uma mensagem termina com um terminador, um tamanho fixo, um silêncio ou um datagrama.
- O checksum é só conferido: nenhum checksum é acrescentado ao que a estação envia.
- Uma tag tira um valor de uma mensagem, como texto lido no tipo dela; números empacotados como inteiros ou ponto flutuante binários dentro da mensagem não são decodificados.
- Um dispositivo UDP só escuta: não envia requisição nem aceita escrita.
- Um dispositivo não pode ser movido entre uma linha serial e a rede, nem para outra linha: crie-o onde ele pertence e exclua o antigo.