duanou9758 2017-06-05 02:35
浏览 396
已采纳

实时传感器数据作为Python发送事件(SSE)从PHP到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. 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. As described here on the Mozilla Docs, this is easily implemented on the server side with something like (a little simplified):

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

");

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?

Can I do something like depicted below? : scenario1

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. So can I make 2.1 and 2.2 in the image happen at the same time?

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.

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!

  • 写回答

1条回答 默认 最新

  • douyu7618 2017-06-05 02:46
    关注

    I use redis to do the signalling between python and redis. After python do all the stuffs, rpush a token (or the latest data) into a redis queue. 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
        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
    ";
    
        $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
    ";
            echo "data: $data
    
    ";
            ob_flush();
            flush();
        }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥100 Jenkins自动化部署—悬赏100元
  • ¥15 关于#python#的问题:求帮写python代码
  • ¥20 MATLAB画图图形出现上下震荡的线条
  • ¥15 关于#windows#的问题:怎么用WIN 11系统的电脑 克隆WIN NT3.51-4.0系统的硬盘
  • ¥15 perl MISA分析p3_in脚本出错
  • ¥15 k8s部署jupyterlab,jupyterlab保存不了文件
  • ¥15 ubuntu虚拟机打包apk错误
  • ¥199 rust编程架构设计的方案 有偿
  • ¥15 回答4f系统的像差计算
  • ¥15 java如何提取出pdf里的文字?