New to Kendo UI for Angular? Start a free 30-day trial

Implementing Real-Time Charts with WebSockets

Environment

ProductProgress® Kendo UI® for Angular Charts

Description

How can I display real-time data which comes from a WebSocket server in the Kendo UI for Angular Chart?

Solution

Apart from displaying real-time data which comes from a WebSocket, the Chart provides options for setting a bidirectional (full-duplex) type of communication and allows multiple clients to push messages to the server, which will be received from all connected clients.

For the full implementation of the approach, refer to the sample GitHub project.

Configuring the Server

The sample project features a Node.js Express server, which serves the Angular application and provides the data feed for the Chart through a WebSocket stream.

The following example demonstrates how to set the HTTP server.

    app.use(express.static(path.join(__dirname, '../../dist/websocket-charts')));

    app.get('*', (req, res) => {
        res.sendFile(path.join(__dirname, '../../dist/websocket-charts/index.html'));
    });

    const port = process.env.PORT || 8000;
    const server = http.createServer(app);

    server.listen(port, () => {
        console.log(`HTTP server running on port ${port}...`);
    });

The following example demonstrates how to set the WebSocket server.

    const wsPort = 8088;
    const wsServer = new ws.Server({port: wsPort});

    console.log(`WebSocket server is running on port ${wsPort}...`);

    wsServer.on('connection',
            websocket => {
                    setInterval(() => {
                    // Broadcasting to all clients
                    wsServer.clients.forEach(
                        client => client.send(JSON.stringify({
                        value: Math.random() * 50,
                        time: new Date()
                        })));
                    }, 1000);

                    // Broadcasting messages from any client to all clients
                    websocket.on('message', message => {
                    const now = new Date();
                    wsServer.clients.forEach(
                        client => client.send(JSON.stringify({
                        text: message,
                        time: now })));
                    });
            });

Configuring the Client

The following example demonstrates how to configure the WebSocket service.

    import { Injectable } from '@angular/core';
    import { Observable } from 'rxjs';

    @Injectable()
    export class WebSocketService {
        public ws: WebSocket;

        public createObservableSocket(url: string): Observable<string> {
            this.ws = new WebSocket(url);

            return Observable.create(observer => {
                    this.ws.onmessage = event => observer.next(event.data);
                    this.ws.onerror = event => observer.error(event);
                    this.ws.onclose = event => observer.complete();
                });
            }

        public sendMessage(message: any): void {
            this.ws.send(message);
        }
    }

Configuring the Chart

The following example demonstrates how to configure the Chart.

    <kendo-chart [transitions]="false">
        <kendo-chart-series>
            <kendo-chart-title text="Current temp (&deg;C)"></kendo-chart-title>
            <kendo-chart-series-item
                type="scatterLine"
                [data]="chartValues"
                yField="value" xField="time">
            </kendo-chart-series-item>
        </kendo-chart-series>
        <kendo-chart-x-axis>
            <kendo-chart-x-axis-item
                baseUnit="seconds"
                baseUnitSteps="seconds"
                [min]="min"
                [max]="max">
            </kendo-chart-x-axis-item>
        </kendo-chart-x-axis>
    </kendo-chart>
    public chartValues = [];
    public messages = [];
    public min: Date = new Date();
    public max: Date = new Date(this.min.getTime() + 20000);
    private url = 'ws://localhost:8088';

    constructor(private wsService: WebSocketService) {
        wsService.createObservableSocket(this.url)
        .subscribe(m => {
            const item: any = JSON.parse(m);
            item.time = new Date(item.time);
            if (item.value) {
            this.chartValues = [...this.chartValues, item];
            if (this.chartValues.length > 20) {
                this.min = this.chartValues[this.chartValues.length - 20].time;
                this.max = item.time;
            }
            } else {
            this.messages = [...this.messages, item];
            }
        });
    }