Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

361
Vistas
Tiempo de espera de lectura de conexión serie PHP

Estoy tratando de resolver algo aquí

Tengo una 'secuencia' para ejecutar a través de un puerto serie (en un RPI).

Tengo un comando PHP supervisado en ejecución en Laravel que se conecta a un corredor MQTT.

Cuando envío un mensaje a ese corredor, el RPI lo recoge y lo procesa. Ahora, tengo un momento en el que espero la interacción del usuario. El problema aquí es que, a veces, el usuario no interactúa con el sistema y el PI sigue "esperando" los datos en serie. Cuando un usuario presiona un botón, obtengo datos en serie, que puedo procesar.

Intenté usar un bucle while (true) {} que lee los datos en serie, pero se detiene repentinamente. Aquí hay un código de ejemplo;

 $configure = new TTYConfigure(); $configure->removeOption("9600"); $configure->setOption("115200"); $this->serialPort = new SerialPort(new SeparatorParser("\n"), $configure); $serialDevice = config('app.device_type') === 'usb' ? '/dev/ttyACM0' : '/dev/ttyAMA0'; $this->serialPort->open($serialDevice); // this is a special one, we add an timeout here of 15 seconds, to prevent that the machine would get stuck. $timeoutStart = time(); $timeout = $timeoutStart + 15; // 15 seconds of timeout. $aborted = false; while (true) { $data2 = $this->serialPort->read(); if (Str::contains($data2, "Whatever I want to check for")) { // Process the data and get out of this loop via a 'break;' statement } // check if 15 seconds have passed, if so, then we want to stop the vend sequence. if (time() >= $timeout) { $this->serialPort->write("C,STOP\n"); // STOP vending $aborted = true; $this->alert("vending sequence stopped"); } }

Cuando coloco registros en el bucle verdadero, veo que se repite, pero de repente deja de hacerlo (apuesto a que es $data2 = $this->serialPort->read(); eso simplemente "detiene" la lectura o sigue leyendo el puerto serie.

Quiero poder eliminar los bucles y hacer una llamada a la API para revertir algunos cambios que ocurrieron antes de esa acción.

es posible? ¿Si es así, cómo?

Paquetes que uso:

  • lumen de laravel
  • PHPMqtt
  • lepiaf\Puerto serie
over 4 years ago · Santiago Trujillo
2 Respuestas
Responde la pregunta

0

Si observa la fuente de lepiaf\SerialPort, encontrará que configura la transmisión en modo sin bloqueo, sin embargo, el método de lectura realiza un ciclo infinito hasta que encuentra el separador. Esto significa que nunca regresará a menos que se reciba el separador y, dependiendo de su configuración, su secuencia de comandos se eliminará una vez que se alcance el tiempo máximo de ejecución de php. Dado que la biblioteca es muy simple, la mejor opción es editar el método de lectura agregando un parámetro de tiempo de espera. Edite el archivo "lepiaf/SerialPort/SerialPort.php", desplácese hacia abajo hasta el método de lectura (línea 107) y cámbielo de la siguiente manera:

 public function read($maxElapsed = 'infinite') { $this->ensureDeviceOpen(); $chars = []; $timeout = $maxElapsed == 'infinite' ? 1.7976931348623E+308 : (microtime(true) + $maxElapsed); do { $char = fread($this->fd, 1); if ($char === '') { if (microtime(true) > $timeout) return false; usleep(100); //Why waste CPU? continue; } $chars[] = $char; } while ($char !== $this->getParser()->getSeparator()); return $this->getParser()->parse($chars); }

Luego, en su código, llame al método como:

 $data2 = $this->serialPort->read(15); if ($data2 === false) { //Timeout occurred } elseif (Str::contains($data2, "Whatever I want to check for")) { //String found } else { //Data received but string not found }
over 4 years ago · Santiago Trujillo Denunciar

0

if (Str::contains($data2, "Whatever I want to check for"))

el código anterior es tu culpable.

 $data2 = $this->serialPort->read();

Es posible que no lea toda la cadena a la vez, proporcionará datos cuando llegue al búfer de lectura. por lo tanto, es mejor recopilar datos en un búfer interno y verificar el búfer para su condición.

 $data2 .= $this->serialPort->read();

asegúrese de inicializar data2 antes del bucle.

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda