In this tutorial, we are going to see a very basic app that will allow to send messages between the server using Flask and an Angular. My goal is to send messages from the server to the client to keep the data updated on the client-side using WebSockets. 

One of the advantages of using WebSockets is that a single connection is used between the server and the client and either the server or the client can send data to each other. In my case a need to send data from my sensor (that is connected to my server) to the angular client to keep the values updated.

Selection_100.png

WebSockets

Web socket is a protocol that enables communication over a single TCP connection. That means that the TCP connection stays open during all the communication between the server and the client against regular Http protocol communication where each time that the client wants to communicate with the server it needs to create a new TCP connection.

2020-06-06_23h13_22

The way that the WebSockets work is by upgrading the connection, this process is known as WebSocket handshake and it is done by starting a regular Http request to a server but with an Upgrade header included in the request.

Client Request Http Heather:

GET / HTTP/1.1
Host: 192.168.43.135:12345
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket
Origin: file://
Sec-WebSocket-Version: 13
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Sec-WebSocket-Key: bKdPyn3u98cTfZJSh4TNeQ==

If the server supports WebSocket protocol this will send a response including an Upgrade heather that indicating that the WebSocket communication will take place. Now a single TCP/IP connection has established and either party can starting to send data.

2020-06-06_23h13_30
  The project
In the last tutorial, we created a project where communication between Arduino and beagle bone was established. Arduino was reading the temperature and humidity using a sensor and sending the data wirelessly to the Beagle Bone through a protocol called Zigbee. Now to visualize this data we are going to create a socket server and a socket client. The socket server will use Flask which is a microframework for python (in this case weĺl use python3). The client will be executed in a different server (in this case my laptop) and they will be communicating through sockets using socket IO that is a library that uses sockets to establish communications.

2020-06-06_23h13_36

Flask and Flask-SocketIO

We are going to use Flask because I am using python to read the information that is being sent to my beagle bone module. (Although you can easy change everything to NodeJs) Flask is a micro web framework that allows you to create REST APIs. Flask-SocketIO allows Flask application to create WebSocket communication with any client-side application that uses the SocketIO javascript library as our Angular app is.

Installation We need to install python3 and we are going to use virtual-env to maintain a separate environment for this project.

sudo apt install python3
apt install python3-venv
python3 -m venv flaskenv

Now go inside the virtual-environment and install Flask and Flask-SocketIO.

source /flaskenv/bin/activate
pip install flask
pip install flask-restful
pip install flask flask-socketio

Server

The next script is the Server.py is a single file that we are going to use for running the application inside the beagle bone.

Server.py
from flask import Flask, jsonify, render_template
from flask_restful import Resource, Api, marshal_with
from flask_socketio import SocketIO,emit,send
import bbbserial as bbb
from threading import Thread
import time


#First we create call the Flask framework and create a secret password.
#Then create socketio variable where cors_allowed_origin = * to acept communication with other domains.
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app, cors_allowed_origins='*')
thread = None
clients = 0


#Function that calls the BeagleBone class that is in charged of reading the temperature sensor
def ini_socket():
    global clients,thread
    b = bbb.Beagle()
    while clients > 0:
        print('Sending data from WebSocket, numClientes: {0}'.format(clients))       
        b.GetTemperature()
        print('sending Data: temp: {0}, hum: {1}'.format(b.temperature,b.humidity))
        socketio.emit('data-tmp', {'temperature': b.temperature, 'humedity':b.humidity})
        time.sleep(1)
    thread = None #we restore the thread so it can be used again


#This is the api that we can run by calling http://ip:5000/api/socket
#this API is called from the Angular client and it creates a separate thread from the main thread
#and executess the function ini_socket.
@app.route('/api/socket')
def index():
    print('Route socket init')
    global thread
    if thread is None:
        thread = Thread(target=ini_socket)
        thread.start()
    return ('{"ok":"success"}')


#Function that runs when a clients get connected to the server
@socketio.on('connect')
def test_connect():
    global clients
    clients += 1
    print('Client connected test')


#Read data from client
@socketio.on('new-message')
def handle_message(message):
    print('received message' + message)
    send_data()


#Send data to client
@socketio.on('new-message-s')
def send_data():
    b = bbb.Beagle()
    b.GetTemperature()
    print('sending Data: temp: {0}, hum: {1}'.format(b.temperature,b.humidity))
    emit('data-tmp', {'temperature': b.temperature, 'humedity':b.humidity})


@socketio.on('disconnect')
def test_disconnect():
    global clients
    clients -= 1
    print('Client disconnected')




#This is the function that will create the Server in the ip host and port 5000
if __name__ == "__main__":
    print("starting webservice")</pre>
<pre spellcheck="false">

Angular

In Angular, we have to use Socket.IO. To install the Socket.IO library we type the next commands.

npm i socket.io-client --save
npm i @types/socket.io-client --save


Angular project structure

2020-06-06_23h13_45

Create SocketService and don´t forget to import the SocketService in the app.module

This service will call the API in the server to initialize the temperature reading.

import { Injectable } from '@angular/core';
import * as io from 'socket.io-client';
import { Observable } from 'rxjs';
import { HttpClient } from '@angular/common/http';


@Injectable({
providedIn: 'root'
})
export class SocketService {
private socket: SocketIOClient.Socket;
private messages: Array<any>;
constructor(private http: HttpClient) {}


public iniServerSocket(){
this.http.get('http://10.42.0.19:5000/api/socket')
.subscribe(data => {
console.log(data);
})
}


}

Create a new component Temperature.component.ts

On init, the component will call 3 functions.

The connect function will stablish the socket connection with the server, the second function will stablish the communication channel where the client is going to be receiving data from the server and the third function the client will call an API in the server to initialize the process of reading the sensor.

The getTempColor will change the color in the angular client depending on the temperature.

import { Component, OnInit, Input } from '@angular/core';
import { SocketService } from '../_sevices/socket.service';
import * as io from 'socket.io-client';


@Component({
selector: 'app-temperature',
templateUrl: './temperature.component.html',
styleUrls: ['./temperature.component.css']
})
export class TemperatureComponent implements OnInit {


private socketio: SocketIOClient.Socket;
public temperature: string;
public humidity: string;


@Input() color: string;
constructor(private socket: SocketService) { }


ngOnInit() {
this.connect();
this.setReceiveMethod();
this.socket.iniServerSocket();
}


connect(){
this.socketio = io('http://10.42.0.19:5000');
}


setReceiveMethod() {
this.socketio.on('data-tmp', (data) => {
console.log(data);
this.temperature = data.temperature + '°C';
this.humidity = data.humedity;
this.color = this.getTempColor(data.temperature);
});
}


sendmessage() {
this.socketio.emit('new-message', 'Hi-flask');
}


getTempColor(temperature: number) {
if (temperature < 10 ) {
return '#334FFF';
} else if (temperature >= 10 && temperature < 18) {
return '#33BDFF';
} else if (temperature >= 18 && temperature < 25) {
return '#4CFF33';
} else if (temperature >= 25 && temperature < 32) {
return '#FFA533';
} else if (temperature >= 32) {
return '#F90000';
}
}


}

The results.

In green we can see what the sensor is reading, we are using the serial terminal of Arduino to read the data.

In orange, we can are connected to the server using SSH and we are running the socket server that we build with python.

2020-06-06_23h13_56

Receiving data from the server to the Angular client

In the next image, we can see that the Angular client running and it is receiving the data from the server. So we don’t need to be requesting data each time to refresh the information.

2020-06-06_23h14_03

Then I add some fire to the sensor to increase the temperature

2020-06-06_23h14_10
2020-06-06_23h14_17

As soon the server gets the temperature from the sensor it sends that to the Angular client through the socket that they established.

2020-06-06_23h14_24

The code in github/matvi

Resultado de imagen para code image"

9 thoughts on “Websockets Angular and Python (Flask)

      1. aaa i get it but can you help me please?can i connect the sensors to my raspberrypi and send the data to my angular js project using websocket?and do i install the command apt install python3-venv in my raspberry pi terminal?thanks in advance

        Like

      2. Hi Amal.
        Yes, you can connect sensors to your Raspberry Pi.
        In order to complete your project, you need to divide the problem into sections.
        First, you need to think about how to send the data. I used one sensor connected to the Arduino and I was sending the information wirelessly to my server using Zeegbee.
        Then you need to think about how to set up the client project (Angular) with the server (flask).
        You can adapt everything to use a different card. I used beagle-bone but you can use Raspberry, both have a version of Linux.
        The only difference is the code that will communicate with the sensors, which will change but should be easy to investigate on your part.
        Just remember to divide and conquer.

        Like

  1. thanks for your reply you really helped me, but i have a question i have created a server in my raspberry pi pretty much like yours and i didn’t create a client yet the problem is when i type sudo python3 server.py nothing happens i don’t get errors and i don’t get any message i really don’t understand i tried to test it before creating the client,and thanks in advance

    Like

Leave a comment