geldek's avatar
Level 1

replace pusher in reverb

I had a brief look at the reverb code in laravel 12 and it seems, pusher protocol is hard wired into it. My problem is, that I run a web socket server that receives ocpp messages from charging stations and I only control the web socket server (cboden/ratchet that I used with previous versions of laravel will not install due to outdated dependencies). I could not find any documentation on how to extend reverb to support different protocols. Is there a way how to intercept the communication and insert my own logic before it reaches vendor\laravel\reverb\src\Protocols\Pusher\Server.php? That way I could write a wrapper over ocpp message and reverb/pusher could handle it.

1 like
1 reply
Braunson's avatar

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:

  1. Do you need bidirectional communication with the charging stations, or just receiving OCPP messages?
  2. Are you planning to broadcast OCPP events to web clients via Reverb, or keep them separate?
  3. 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 :)

Please or to participate in this conversation.