Comments (9)
@Sididi When you run $mqtt->loop()
, the process which executes the Artisan command is being blocked by the MQTT client. The only possible way to run other code in parallel (well, not really concurrently, but invoked by the MQTT client) is through subscription callbacks and loop event handlers.
But why do you need this anyway? If you only want to publish data, you can of course just call MQTT::publish('my/topic', 'my message')
in your controller or wherever. Doing so will open one connection to the MQTT broker per request though, so you should not use a static client id.
from laravel-client.
Alright, this makes sense (and is also a good thing to avoid). In this case, there are two quite common options:
-
You can create a queued job for each message to publish. There will be one MQTT client per queue worker, so the number is easily calculatable.
- Pros: Easy to develop and within the Laravel best practices
- Cons: If you publish messages infrequently, the MQTT client will lose its connection regularly
-
You can build your own MQTT publish queue worker which fetches new messages to publish from a queue and publishes them within a loop. Something like this (please be aware this has intentionally no error handling, etc.):
$mqtt = MQTT::connection(); $mqtt->registerLoopEventHandler(function (MqttClient $mqtt, float $elapsedTime) { $nextMessage = \Redis::lpop('mqtt-messages-to-publish'); if ($nextMessage === null) { // TODO: maybe sleep for a bit to avoid polling Redis too fast return; } $message = json_decode($nextMessage); $mqtt->publish($message->topic, $message->content, $message->qos, $message->retain); }); $mqtt->loop(true);
- Pros: The MQTT connection will be kept open (via ping/pong) and you have full control over the number of workers/connections
- Cons: More effort to develop, although not by much
from laravel-client.
Option 2 definitely does the job, thank you kindly
I want to congratulate you for always answering so quickly and with code example on each of your issues, truly a gentleman
from laravel-client.
Hi there, glad you like the package and find it useful.
I understand your question, but I have to tell you that your current approach, where the subscription is made within a controller, will not work as expected. By default, PHP requests are limited to 30 seconds of execution time and require a client to keep the connection to the server open, to prevent the request from being aborted. To keep the connection between client and server open, you will also need to ensure proper connection timeouts are in place. All in all, using such subscriptions is bad application design and is not how you would implement it in Laravel.
Instead, you should perform subscriptions within a console command. The command can be started (and restarted in case of a crash) by something like supervisor (this article is for the queue:work
command, but works similar for other commands).
By using a command, the data collection runs entirely as daemon on the server and does not require a client (i.e. web browser) to be open at all. In such case, you can then implement the dashboard which displays the collected data in a controller.
from laravel-client.
i see, understandable. Supervisor the queue looks convicing. Thank you for the reply ! Have a great day !
from laravel-client.
Running $mqtt->loop()
anywhere, even in a artisan command causes the program to hang. Supervisor only ensures that the script is kept running, but if it won't finish then it is unable to do anything?
I've tried to follow the examples in examples repo but all of the subscription examples close the connection which won't keep the subscription connection open.
I'm not sure how to make the daemon run in laravel when the loop function is called without it blocking the laravel application
from laravel-client.
The whole point of the $mqtt->loop()
method is that it is blocking. It is an event loop, which means it does the following things over and over again:
- Read incoming data from the MQTT broker
- Process and deliver the received data to subscription callbacks
(i.e. the function you register with$mqtt->subscribe($topic, $callback)
) - Send outgoing data (published messages, retries, etc.) to the MQTT broker
Because $mqtt->loop()
is blocking and intended to be run forever, it is not recommended to run this method in a controller during a request. It should only be called in a console command where the process is able to run forever.
For console commands, the ext_pcntl
example is the most suitable. Just remove line 41 and you are good to go. If you wonder what it does:
- It registers a signal handler for
SIGINT
(ctrl + c) which interrupts the$mqtt->loop()
if running - It connects to the MQTT broker and subscribes to a topic, then infinitely runs using
$mqtt->loop()
according to above description - It disconnects gracefully after being interrupted via a
SIGINT
signal
Please be aware that ext_pcntl
only works on UNIX based systems.
from laravel-client.
Hi there, glad you like the package and find it useful.
I understand your question, but I have to tell you that your current approach, where the subscription is made within a controller, will not work as expected. By default, PHP requests are limited to 30 seconds of execution time and require a client to keep the connection to the server open, to prevent the request from being aborted. To keep the connection between client and server open, you will also need to ensure proper connection timeouts are in place. All in all, using such subscriptions is bad application design and is not how you would implement it in Laravel.
Instead, you should perform subscriptions within a console command. The command can be started (and restarted in case of a crash) by something like supervisor (this article is for the
queue:work
command, but works similar for other commands).By using a command, the data collection runs entirely as daemon on the server and does not require a client (i.e. web browser) to be open at all. In such case, you can then implement the dashboard which displays the collected data in a controller.
Hi Namoshek,
Currently doing something pretty similar, I have a simple artisan command initializing connection and running the infinite loop so it handles subscriptions / sent messages (all in QoS 2)
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Contracts\Console\Isolatable;
use PhpMqtt\Client\Facades\MQTT;
class RunMQTTLoop extends Command implements Isolatable
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'mqtt:start';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Starts a loop handling all MQTT events';
/**
* Determine when an isolation lock expires for the command.
*
* @return \DateTimeInterface|\DateInterval
*/
public function isolationLockExpiresAt()
{
return now();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
/** @var \PhpMqtt\Client\Contracts\MqttClient $mqtt */
$this->info('Connecting to MQTT broker...');
$mqtt = MQTT::connection();
$this->info('Connected. Now initializing loop.');
$mqtt->loop();
return Command::SUCCESS;
}
}
But I would like to access that instance of php-mqtt ($mqtt variable) outside of my artisan command so I can use it to send messages and register new subscription channels interactively
By any chance, have you any idea how to properly do it in Laravel? Many thanks
from laravel-client.
Thank you for the fast answer Namoshek
I wanted to do it this way precisely to avoid opening a connection on each request as I will possibly have several dozens publish per second (each independant)
from laravel-client.
Related Issues (20)
- Is Laravel 9 support planned? HOT 6
- Can not transfer data bigger than 1MB HOT 7
- could be use/configured as broadcast driver? HOT 3
- Godaddy Server(Shared Hosting) connecting to AWS iot core showing error. HOT 1
- Which Version of Laravel does it support? HOT 1
- Can this be used to make a MQTT sink? HOT 1
- Does it support auto reconnect? HOT 1
- Websocket port HOT 3
- Can the client publish messages on two different ports (TCP and WebSockets)? HOT 1
- Publish message as a bytes array HOT 8
- Support for Laravel 10 HOT 2
- Detect if response is not received from MQTT broker for specified duration. HOT 8
- SSL/TLS connection configuration HOT 6
- Is it possible to do subscribing to mutliple topics on 1 command? HOT 1
- How do you reset the command under supervisor when something changes in controller? HOT 3
- The broker did not acknowledge the connection attempt within the configured connection timeout period HOT 4
- plans to support php-mqtt client v2.0? HOT 2
- Cannot dispatch job inside subscribe closure HOT 1
- Certificate file on different disk HOT 1
- Settings without useBlockingSocket option HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from laravel-client.