Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

355
Views
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 answers
Answer question

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 Report

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 Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!