Simple implementation of PPT remote controller based on WebSocket

Keywords: Laravel

1, Background

This idea germinated before the college graduation defense. At that time, I was learning and practicing the front-end knowledge and came into contact with a PPT project written through the front-end code and running in the browser revealjs

After reading the inner monologue at that time:

This can be used to write the PPT of bisher's defense,
Science (bi) ā o)
In (x) ī n)
To (l ì)
Use (y ì)
, it's worth learning front-end technology;

With the PPT page, do you still need a mouse click to turn the page? Is there a better way to replace the page turning effect?

Other people's PPT speeches also need to be equipped with a wireless page turning pen. What can be done to achieve similar operations?

Can I use my mobile phone to control the browser side PPT page written through revealjs?

After consulting some materials, I learned about WebSocket full duplex communication protocol [1] , modern browser support;

It is thought that you can write a page with up, down, left and right controls, connect a WebSocket service, click up, down, left and right, and then issue "instructions" to the WebSocket service. Then the PPT page is also connected to the WebSocket service. Finally, the WebSocket service forwards "instructions" to the PPT page, so as to turn the page.

NICE!🍻

2, Target

Based on WebSocket and review.js, the PPT web page realized by using review.js can be controlled through the mobile terminal to turn pages up, down, left and right remotely.

At present, a controller is implemented to control a PPT web page

3, Basic principles

The PPT web page end and the controller end are connected to the WebSocket Service at the same time. The controller end sends the page turning operation instructions (up, down, left and right) to the WebSocket Service, and then the WebSocket Service notifies the PPT web page end, and the PPT web page end executes the page turning operation instructions.

4, Realization effect

The original idea is realized by replacing the control end page opened by the browser in the figure above with a mobile browser connected to the same LAN.

5, Function realization

Source address: github.com/wenlong-date/ppt

1. Use workman to provide WebSocket services

After the WebSocket Service is connected between the PPT web page and the controller, it will simply "report home" and initialize the connection between the PPT web page and the controller,

file: server.php

// ... 
(new PptSocketServer())->run();

class PptSocketServer
{
    const CONNECTION_TYPE_PPT = 'connection_ppt';
    const CONNECTION_TYPE_CONTROLLER = 'connection_controller';

    protected $worker;
    protected $globalUid = 0;
    protected $globalPptConnection;
    protected $globalControllerConnection;

    public function __construct(int $port = 2346)
    {
        $this->initWorker($port);
    }

    public function run()
    {
        Worker::runAll();
    }

    protected function initWorker(int $port)
    {
        $this->worker            = new Worker("websocket://0.0.0.0:" . $port);
        $this->worker->count     = 1;
        $this->worker->onConnect = [$this, 'handleConnection'];
        $this->worker->onMessage = [$this, 'handleMessage'];
        $this->worker->onClose   = [$this, 'handleClose'];

    }

    // Simply record the id information of the connection
    public function handleConnection($connection)
    {
        $connection->uid = ++$this->globalUid;
    }

    public function handleMessage($connection, $data)
    {
        // Initialize the connection of PPT web page
        if ($this->setPptConnectionIfNull($connection, $data)) {
            Log::info('ppt online');
            return;
        }
        // Initialize the connection of the control side page
        if ($this->setControllerConnectionIfNull($connection, $data)) {
            Log::info('controller online');
            return;
        }

        // ...
    }

    public function handleClose($connection)
    {
        // Judge and destroy the connection of PPT web page or control page
        $this->destructConnection($connection);

        Log::info($connection->uid . ' offline by close websocket');
    }

    protected function destructConnection($connection)
    {
        if (isset($connection->type) && $connection->type === self::CONNECTION_TYPE_PPT) {
            $this->globalPptConnection = null;
            Log::info('ppt offline');
            return true;
        }

        if (isset($connection->type) && $connection->type === self::CONNECTION_TYPE_CONTROLLER) {
            $this->globalControllerConnection = null;
            Log::info('controller offline');
            return true;
        }

        return true;
    }

    /**
     * Judge and initialize the connection of PPT web page according to the command
     *
     * @param $connection
     * @param $data
     * @return bool
     */
    protected function setPptConnectionIfNull($connection, $data)
    {
        if (!is_null($this->globalPptConnection)) return false;
        if (!$this->requestConnectionIsPpt($data)) return false;

        $connection->type          = self::CONNECTION_TYPE_PPT;
        $this->globalPptConnection = $connection;
        return true;
    }

    /**
     * Judge and initialize the connection of the control side page according to the command
     *
     * @param $connection
     * @param $data
     * @return bool
     */
    protected function setControllerConnectionIfNull($connection, $data)
    {
        if (!is_null($this->globalControllerConnection)) return false;
        if (!$this->requestConnectionIsController($data)) return false;

        $connection->type                 = self::CONNECTION_TYPE_CONTROLLER;
        $this->globalControllerConnection = $connection;
        return true;
    }

    public function requestConnectionIsPpt($data)
    {
        return $data === 'i am ppt';
    }

    public function requestConnectionIsController($data)
    {
        return $data === 'i am controller';
    }

}

2. The control side page sends "instructions" to the WebSocket Service

file: /web/controller/index.html

// ...

var ws = new WebSocket('ws://' + location.hostname + ":2346");
ws.onopen = function () {
    ws.send('i am controller');
};
ws.onmessage = function (e) {
    console.log('controller get message from server: ' + e.data);
};

var $ = function (dom) {
    return document.getElementById(dom);
}
$('up').onclick = function () {
    sendCommand('up');
}
$('right').onclick = function () {
    sendCommand('right');
}
$('down').onclick = function () {
    sendCommand('down');
}
$('left').onclick = function () {
    sendCommand('left');
}

function sendCommand(status) {
    ws.send(status);
}

// ...

3. WebSocket Service sends "instruction" to PPT web page

Before sending the "command", judge whether the PPT web page is online, and only one control page is allowed to issue the "command"

file: /web/controller/control.js

// ...

class PptSocketServer
{
    // ...

    public function handleMessage($connection, $data)
    {
        // ...

        if (is_null($this->globalPptConnection)) {
            Log::info('ppt offline; cant control');
            return;
        }

        // At present, only one controller is allowed to send instructions.
        if (!is_null($this->globalControllerConnection)
            && $connection->uid !== $this->globalControllerConnection->uid
        ) {
            Log::info('sorry, you are not correct controller ' . $connection->uid);
            return;
        }
        // Forward the "instruction" of the control end to the PPT web page end
        $this->globalPptConnection->send($data);
    }
    // ...

}

4. PPT web page side executes page turning "instruction"

file: server.php

// ...

var ws = new WebSocket('ws://' + location.hostname + ":2346");
ws.onopen = function () {
    ws.send('i am ppt');
};
ws.onmessage = function (e) {
    console.log('ppt get message from server: ' + e.data);
    switch (e.data) {
        case 'up':
            Reveal.up();
            break;
        case 'right':
            Reveal.right();
            break;
        case 'down':
            Reveal.down();
            break;
        case 'left':
            Reveal.left();
            break;
        default:
            console.log('unSupport command : ' . e.data)
    }
};

// ...

6, Local operation

Note: if you want to demonstrate your revealjs PPT, you need to first introduce control.js in the end of the html file on the front page of the PPT

 <script src="/controller/control.js"></script>

1. git clone github.com/wenlong-date/ppt.git && composer install
2. Replace the files in the web/ppt directory with your own review.js ppt related front-end files (PPT for demo demonstration is available by default)
3. Execute php server.php start [-d] (- d running in the background)
4. Another window executes CD Web & & PHP - s 0.0.0.0:80 (or use Nginx to provide web services)
5. Web page opening address: http://{yourip}/ppt/
6. The mobile browser connected to the same LAN can be opened at http://{yourip}/ppt / (which will automatically jump to the control end page). (if the public IP address is not limited by the local area network)

7, Docker image & & docker run

Dockerfile file already exists in the warehouse, which can be built manually.

1. You can also use docker pull wenlongdotdate/websocketppt to obtain the image
2. Run docker run -it -p 2346:2346 -p 80:80 -d wenlongdotdate/websocketppt locally (you can select your own PPT front-end file directory and mount it to the / var/www/html/web/ppt directory of the container)
3. Open http://{yourip}/ppt on the web page/
4. The mobile browser connected to the same LAN can be opened at http://{yourip}/ppt / (which will automatically jump to the control end page). (if the public IP address is not limited by the local area network)

8, More ideas

At present, it is only one-to-one control of a PPT, and the function is very simple.

You can consider providing different users with a web page developed for review.js. PPT provides a WebSocket web page control side service.

Each user can create a controller resource in the background. The controller will generate a unique communication channel and JavaScript files that can be introduced into the PPT (connect to the WebSocket service and communicate).

In this way, different users can control their own web pages developed based on Reveal.js through mobile browser. PPT requires the following three steps:

1. Create controller resources
2. Import the corresponding JavaScript file into the PPT of review.js
3. The mobile browser scans the QR code of the current controller resource controller and opens the control end page for remote control

reference material

Posted by dallasx on Fri, 17 Sep 2021 20:37:27 -0700