Yeah, you're right that Reverb is tightly coupled to the Pusher protocol. However, there are a few possible options to handle OCPP messages alongside Reverb without modifying core files.
Quick questions:
- Do you need bidirectional communication with the charging stations, or just receiving OCPP messages?
- Are you planning to broadcast OCPP events to web clients via Reverb, or keep them separate?
- What OCPP version are you working with (1.6, 2.0.1)?
Option1: Separate WebSocket server with message bridging
// Custom OCPP WebSocket server (using ReactPHP - more maintained than Ratchet)
use React\Socket\SocketServer;
use React\Stream\WritableResourceStream;
class OCPPServer
{
public function __construct()
{
$this->server = new SocketServer('0.0.0.0:8080');
$this->server->on('connection', [$this, 'handleConnection']);
}
public function handleConnection($connection)
{
$connection->on('data', function($data) {
// Parse OCPP message
$ocppMessage = json_decode($data, true);
// Process OCPP logic
$this->handleOCPPMessage($ocppMessage);
// Bridge to Reverb/Pusher for web clients
broadcast(new ChargingStationEvent($ocppMessage));
});
}
}
Option 2: Proxy/middleware layer Create a middleware that intercepts WebSocket upgrades and routes based on protocol:
// In a custom service provider try this
class WebSocketRoutingProvider extends ServiceProvider
{
public function boot()
{
// Hook into Reverb's server startup
$this->app['events']->listen(
\Laravel\Reverb\Events\ServerStarted::class,
function ($event) {
$this->addOCPPHandler($event->server);
}
);
}
private function addOCPPHandler($server)
{
// Wrap the original handler to check protocols first
$originalHandler = $server->getMessageHandler();
$server->setMessageHandler(function($connection, $message) use ($originalHandler) {
if ($this->isOCPPMessage($message)) {
return $this->handleOCPP($connection, $message);
}
return $originalHandler($connection, $message);
});
}
}
Option 3: Custom Reverb server extension Since you mentioned wanting to intercept before the Pusher server, you could try extending Reverb's server:
// Custom server that extends Reverb's
class HybridWebSocketServer extends \Laravel\Reverb\Servers\Reverb\Server
{
protected function handleMessage($connection, $message)
{
// Check if it's OCPP format
if ($this->isOCPPProtocol($message)) {
return $this->handleOCPPMessage($connection, $message);
}
// Fall back to Pusher protocol
return parent::handleMessage($connection, $message);
}
}
It really comes down to what option aligns better with your architecture. The separate server approach is probably cleanest and most maintainable but it's entirely up to you :)