简体   繁体   English

通过Python通过PHP将实时传感器数据作为服务器发送事件(SSE)?

[英]Real-time sensor data as Server-Sent Events (SSE) from Python through PHP?

I'm in the process of updating a web app presenting real-time sensor data, which in it's current first iteration does this by continuous AJAX polling. 我正在更新一个显示实时传感器数据的Web应用程序,该应用程序是当前的第一个迭代,它通过连续的AJAX轮询来实现。 However, in order to make this more like a 'true real-time' app, I would like it to be event-based. 但是,为了使它更像一个“真正的实时”应用程序,我希望它是基于事件的。

I've been reading up on event-based techniques, and based on the fact that the real-time communication only has to go one way (server - > client), I have chosen to go with Server-Sent Events (SSE) for now instead of something like websockets. 我一直在学习基于事件的技术,并且基于实时通信仅需采用一种方式(服务器->客户端)的事实,我选择使用服务器发送事件(SSE)现在,而不是像websockets这样的东西。 As described here on the Mozilla Docs , this is easily implemented on the server side with something like (a little simplified): 在Mozilla Docs上所述 ,可以在服务器端轻松实现,方法如下(略有简化):

<?php
// SSEscript.php
date_default_timezone_set("America/New_York");
header("Content-Type: text/event-stream\n\n");

while (1) {
   if ($new_data_available) {
      echo "data:". $data;
   } 

   sleep($short_time_to_spare_cpu);
}
?>

and on the client side with: 在客户端上:

<script>
var evtSource = new EventSource("SSEscript.php");

evtSource.onmessage = function(e) {
   var data = e.data;
   // Do something with data object
} 
</script>

All the above works fine for me. 以上所有对我来说都很好。 However, the sensor data is initially retrieved by a Python script running continuously on the server, so how do I transfer the sensor data from the Python script to the PHP script IMMEDIATELY when it is retrieved, so that an event can be generated and sent? 但是,传感器数据最初是通过在服务器上连续运行的Python脚本检索的,那么如何在检索传感器数据时将其从Python脚本传输到PHP脚本,以便可以生成和发送事件?

Can I do something like depicted below? 我可以做如下所示的事情吗? : 方案1

At the same time all new data is stored in a MySQL db, so I could of course make the PHP script query the db really often for new entries, but there has to be a smarter way. 同时所有新数据都存储在MySQL数据库中,因此我当然可以使PHP脚本确实经常向数据库查询新条目,但是必须有一种更聪明的方法。 So can I make 2.1 and 2.2 in the image happen at the same time? 那么我可以使图像中的2.1和2.2同时发生吗?

All the answers I could find in here describes how data can be transferred by making the PHP execute the Python script, but that is not what I want as this has to run whether or not a user asks for data. 我在这里可以找到的所有答案都描述了如何通过使PHP执行Python脚本来传输数据,但这不是我想要的,因为无论用户是否要求数据,这都必须运行。

Is a kind of socket the way to go, and if so, can you point me in the direction of how to do so? 是一种插座吗?如果是,您能指出我的方向吗? I hope you can help me out! 希望您能帮帮我!

I use redis to do the signalling between python and redis. 我使用redis在python和redis之间进行信号传递。 After python do all the stuffs, rpush a token (or the latest data) into a redis queue. 在python完成所有工作后,将令牌(或最新数据)推送到redis队列中。 In the PHP I use a while(true) loop to hold the request and redis lpop(queue,timeout) to wait for the token, and send data out, something like this: 在PHP中,我使用while(true)循环来保存请求,并使用redis lpop(queue,timeout)等待令牌并发送数据,如下所示:

<?php
    require __DIR__.'/predis-1.0/autoload.php';
    header("Content-Type: text/event-stream");
    header("Cache-Control: no-cache");
    header("Connection: keep-alive");

    $lastId = isset($_SERVER["HTTP_LAST_EVENT_ID"]) ? 
              $_SERVER["HTTP_LAST_EVENT_ID"] : null;
    if (isset($lastId) && !empty($lastId) && is_numeric($lastId)) {
        $lastId = intval($lastId);
        $lastId++;
    }

    $index = isset($_GET['index']) ? $_GET['index'] : null;

    echo "retry: 2000\n";

    $client = new Predis\Client();
    while (true) {
        $data = $client->blpop('queue',5);
        if ($data) {
            error_log("$index : " . strlen($data));
            sendMessage($lastId, $data);
            $lastId++;
        }
    }

    function sendMessage($id, $data) {
        echo "id: $id\n";
        echo "data: $data\n\n";
        ob_flush();
        flush();
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM