Automatizar terminais 3270 (Mainframes) usando PHP é um desafio que mistura protocolos modernos com sistemas de décadas de existência. O segredo de uma automação que não “quebra” está na forma como você lê os dados da tela.
1. O Problema da Velocidade: PHP vs. Mainframe Link para o cabeçalho
O PHP executa instruções em microssegundos. Já o Mainframe processa dados em uma arquitetura baseada em blocos e buffers de rede. Se o seu script tentar ler a tela antes do mainframe terminar de pintá-la, você obterá dados incompletos ou erros de sincronia.
É aqui que reside a diferença entre as duas principais formas de captura:
A Captura Passiva (getScreen)
Link para o cabeçalho
A função que retorna $this->conexao->screen apenas olha para o que está no cache local da memória. Se a rede oscilar, o cache estará vazio ou defasado. É como tirar uma foto de um carro em alta velocidade: o resultado pode ser apenas um borrão.
A Captura Ativa (lerDadosTelaAtual)
Link para o cabeçalho
Esta abordagem utiliza o comando wait do s3270. Ela instrui o emulador a aguardar o estado “Ready” (teclado desbloqueado) antes de realizar o comando rectangle(), que varre as coordenadas da tela e extrai o texto real.
2. Implementação Robusta: Blindando seu Script Link para o cabeçalho
Para evitar que seu robô pare de funcionar em dias de lentidão no mainframe, precisamos de uma função que gerencie exceções e valide se a tela correta foi carregada.
Abaixo, apresentamos uma implementação profissional que utiliza Identificadores de Tela e Tratamento de Exceções:
/**
* Realiza a leitura da tela com validação de estado e conteúdo.
* * @param string|null $identificador Esperado (ex: "MENU", "ERRO")
* @param int $tentativas Máximo de re-leituras em caso de atraso
* @return string Conteúdo da tela
* @throws Exception Caso o sistema trave ou a tela esteja incorreta
*/
public function lerComSeguranca($identificador = null, $tentativas = 3)
{
for ($i = 0; $i < $tentativas; $i++) {
// Tenta sincronizar com o buffer do s3270
// O parâmetro true geralmente indica para esperar o retorno das linhas
$dados = $this->conexao->waitReturn(true) ? $this->conexao->rectangle() : false;
if ($dados !== false) {
// Se não pedimos um identificador, retornamos o que foi lido
if (!$identificador) return $dados;
// Se a tela contém o que esperamos, sucesso!
if (strpos($dados, $identificador) !== false) {
return $dados;
}
}
// Pequena pausa antes da próxima tentativa (milissegundos)
usleep(500000);
}
throw new Exception("Falha Crítica: Tela '$identificador' não encontrada ou Timeout no Mainframe.");
}
3. Melhores Práticas para Automação Link para o cabeçalho
Ao construir seu fluxo, siga estas regras de ouro:
-
Sempre valide o “X SYSTEM”: Nunca envie comandos (como
EnterouF3) se o terminal estiver no estado de espera. A funçãowaitReturncuida disso internamente. -
Identificadores Únicos: Cada tela do Mainframe costuma ter um código no canto superior esquerdo (ex:
PRG001). Use isso como o$identificadorna função acima. -
Logs de Depuração: Em caso de erro, salve o conteúdo de
$dadosem um arquivo.txt. Isso permite que você veja exatamente o que o robô viu no momento da falha.
Conclusão Link para o cabeçalho
A diferença entre uma automação instável e uma profissional é o sincronismo. Ao trocar leituras diretas de propriedades por métodos que aguardam o status do terminal, você reduz em até 90% as falhas de “tela em branco” ou “comando ignorado”.