ChartJS 如何区分一个主题的数据或来自美居中心的另一个,如果客户端是suscribed两个主题

7kjnsjlb  于 2023-11-18  发布在  Chart.js
关注(0)|答案(1)|浏览(127)

我在一个Symony应用程序上有一个 Jmeter 板,上面有两个ChartJS图表,一个是温度数据,另一个是压力数据。我需要实时更新这两个图表;为此,我尝试使用MercureBundle和两个主题:['realtime-notif/temperature/{sensorId}', 'realtime-notif/pressure/{sensorId}']。虽然主题听起来很相似,但由于两个ChartJS不同,因此符合数据的逻辑是不同的,为此,我有两个带有AMQP队列的Messenger消息处理程序,一个在主题'realtime-notif/temperature/{sensorId}'中发布Mercure更新,另一个消息处理程序类在'realtime-notif/pressure/{sensorId}'中发布。

#mercure.yaml:
mercure:
    hubs:
        default:
            url: '%env(MERCURE_URL)%'
            public_url: '%env(MERCURE_PUBLIC_URL)%'
            jwt:
                secret: '%env(MERCURE_JWT_SECRET)%'
                publish: ['realtime-notif/temperature/{sensorId}', 'realtime-notif/pressure/{sensorId}']
                subscribe: ['realtime-notif/temperature/{sensorId}', 'realtime-notif/pressure/{sensorId}']

#The TemperatureMessageHandler class: 
class TemperatureMessageHandler implements MessageHandlerInterface
{

    private $mercureHub;
    private $managerRegistry;

    public function __construct(HubInterface $mercureHub, ManagerRegistry $managerRegistry)
    {
        $this->mercureHub = $mercureHub;
        $this->managerRegistry = managerRegistry;
    }

    public function __invoke(TemperatureMessage $message)
    {
        try {
            $graphId=$message->getGraphId();
            $lastElapsedTime=$message->getLastElapsedTime();
            
            $em=$this->managerRegistry->getManager();

            $storedData = $em->getRepository(Temperature::class)->findLastRecordsForGraph($graphId, $lastElapsedTime);
            
            /**
             Set the data source for the temperature graph to a specific format from $toredData
            **/
            $formatedChartData = [];
                **....**

            $update = new Update(
                    sprintf('realtime-notif/temperature/%s', $graphId),
                    \json_encode($$formatedChartData),
                    true
            );

            $this->mercureHub->publish($update);
        } catch (\Exception $exc) {
            
        }
    }
}

字符串
而且,

#The PressureMessageHandler class:
 class PressureMessageHandler implements MessageHandlerInterface
{

    private $mercureHub;
    private $managerRegistry;

    public function __construct(HubInterface $mercureHub, ManagerRegistry $managerRegistry)
    {
        $this->mercureHub = $mercureHub;
        $this->managerRegistry = managerRegistry;
    }

    public function __invoke(PressureMessage $message)
    {
        try {
            $graphId = $message->getGraphId();
            $lastElapsedTime = $message->getLastElapsedTime();
            
            $em = $this->managerRegistry->getManager();

            $storedData = $em->getRepository(Pressure::class)->findLastRecordsForGraph($graphId, $lastElapsedTime);
            
            /**
             Set the data source for the pressure graph to a specific format from $toredData
            **/
            $formatedChartData = [];
                **....**
            

            $update = new Update(
                    sprintf('realtime-notif/pressure/%s', $graphId),
                    \json_encode($$formatedChartData),
                    true
            );

            $this->mercureHub->publish($update);
        } catch (\Exception $exc) {
            
        }
    }
}


对我来说,问题是我不知道如何在客户端区分从Mercure hub接收的数据是来自EventSource对象的消息事件中的温度主题还是压力主题。

<script type="text/javascript">
                $(document).ready(function () {
                    /**Create two graph on page ready **/
                    let temperatureGraphObject = createTemperatureGraph(canvasTemperaturaGraph);
                    let pressureGRaphObject = createPressureGraph(canvasPressureGraph);
                    
                    /** 
                    I have two function updateTemperatureGraph(temperatureGraphObject, newTemperaturaData) and updatePressureGraph(pressureGraphObject, newPresureData)
                    **/
                    
                    /**Subscribe client to topics for data updates **/
                    {% set topics = ['realtime-notif/temperature/'~temperatureSensorId, 'realtime-notif/pressure/'~pressureSensorId] %}

                    const eventSource = new EventSource("{{ mercure(topics, { subscribe:topics})|escape('js')}}", {withCredentials: true});

                    eventSource.onopen = function () {
                        console.log('New socket connection!');
                    };

                    eventSource.onmessage = function (e) {
                        console.log('New data received');
                        var data = JSON.parse(e.data);
                        
                        /** 
                        The problem is here, how differentiate the topics data to call updateTemperaturaGraph(temperatureGraphObject, data) or  updatePressureGraph(pressureGraphObject, data)
                        **/                     
                    };

                    eventSource.onerror = function () {
                        console.log('Socket connection lost!');
                    };
                });
            </script>


那么,如何区分调用updateTemperaturaGraph(temperatureGraphObject,data)或updatePressureGraph(pressureGraphObject,data)到onmessage事件的主题数据呢?
如果我只为客户端订阅一个主题,则接收到的所有数据都将是主题图的类型,当然,图会正确更新。

kadbb459

kadbb4591#

解决方案是为更新类构造函数设置detype属性,该构造函数是您希望从MessageUpdate相关类发布到Mercure中心的。因此,对于与温度通知相关的消息,我们将设置type属性= 'temperatureUpdate',对于与压力通知相关的消息,我们将设置type属性= 'pressureUpdate'。
TemperatureMessageHandler上的__invoke函数:

public function __invoke(TemperatureMessage $message)
{
    try {
        $graphId = $message->getGraphId();
        
        // Collect the data for the update
        $data = [/* ... */];

        $update = new Update(
            sprintf('realtime-notif/temperature/%s', $graphId),
            \json_encode($data),
            true,
            null,
            'temperatureUpdate'
        );

        $this->mercureHub->publish($update);
    } catch (\Exception $exc) {
        
    }
}

字符串
PressureMessageHandler上的__invoke函数:

public function __invoke(PressureMessage $message)
{
    try {
        $graphId = $message->getGraphId();

        // Collect the data for the update
        $data = [/* ... */];

        $update = new Update(
            sprintf('realtime-notif/pressure/%s', $graphId),
            \json_encode($data),
            true,
            null,
            'pressureUpdate'
        );

        $this->mercureHub->publish($update);
    } catch (\Exception $exc) {
        
    }
}


在客户端,必须为EventSource对象创建两个新的EventListeners,其名称与创建的新类型相同。每个新的Listeners将处理Mercure中心中发布的相关消息类型:

<script type="text/javascript">
    $(document).ready(function () {
        /**Create two graph on page ready **/
        let temperatureGraphObject = createTemperatureGraph(canvasTemperaturaGraph);
        let pressureGRaphObject = createPressureGraph(canvasPressureGraph);
        
        /** 
        I have two function updateTemperatureGraph(temperatureGraphObject, newTemperaturaData) and updatePressureGraph(pressureGraphObject, newPresureData)
        **/
        
        /**Subscribe client to topics for data updates **/
        {% set topics = ['realtime-notif/temperature/'~temperatureSensorId, 'realtime-notif/pressure/'~pressureSensorId] %}

        const eventSource = new EventSource("{{ mercure(topics, { subscribe:topics})|escape('js')}}", {withCredentials: true});

        eventSource.onopen = function () {
            console.log('New socket connection!');
        };

        eventSource.addEventListener("temperaturaUpdate", function (e) {
            let parsedData = null;
            try {
                parsedData = JSON.parse(e.data);
            } catch (error) {
                console.log(error);
            }
            
            if (parsedData) {
                updateTemperatureGraph(temperatureGraphObject, parsedData);
            }
        }, false);
        
        eventSource.addEventListener("pressureUpdate", function (e) {
            let parsedData = null;
            try {
                parsedData = JSON.parse(e.data);
            } catch (error) {
                console.log(error);
            }
            
            if (parsedData) {
                updatePressureGraph(pressureGraphObject, parsedData);
            }
        }, false);

        eventSource.onerror = function () {
            console.log('Socket connection lost!');
        };
    });
</script>


通过这种方式,Mercure中心发布分类信息,每个Eventsites将负责按照信息到达订阅客户端的顺序处理相应的信息,而不管订阅的主题是什么。

相关问题