WebSocket 기반 관제 프로그램

2024. 4. 23. 18:05IT관련

반응형

서비스 하는 지역 기준으로 가장 많은 택시수는 3000대이다.

관제 프로그램이 3000대를 한번에 표시할 수 있을거라고는 생각하지 않는다. 다만 몇대까지가 적합한지 테스트를 해보려고 코드를 작성해 보았다.

 

모든 택시가 실시간으로 움직이고 있다고 가정하고 서버는 초단위로 클라이언트에게 택시들의 좌표를 송출하며 클라이언트는 받은 차량의 정보를 전부 표시한다.

from flask import Flask, render_template
from flask_socketio import SocketIO
import random
import threading
import json

app = Flask(__name__)
app.config['SECRET_KEY'] = 'vnkdjnfjknfl1232#'
socketio = SocketIO(app, async_mode='threading')

cars = []
car_num = 100
lat = 37.5115557
lng = 127.0595261

@app.route('/maps')
def maps():
    return render_template('show.html')

@socketio.on('map event')
def handle_map_event(json, methods=['GET', 'POST']):
    print('received map event: ' + str(json))
    if json['data'] == 'User Connected':
        threading.Thread(target=send_mapdata, args=[1]).start()
    

def send_mapdata(i: int):
    threading.Thread(target=modify_carinfo).start()
    for n in range(3000):
        print('emit!')
        socketio.emit('map response', json.dumps(cars))
        socketio.sleep(2)

def modify_carinfo():
    for n in range(100000):
        x = random.randint(0, car_num - 1)
        cars[x] = { 
            'label': f'12가{x:04d}', 
            'name': f'12가{x:04d}', 
            'lat': lat + random.random(), 
            'lng': lng + random.random()
        }
        label = cars[x]['label']
        print(f'{label} is changed.')

if __name__ == '__main__':
    for n in range(car_num):
        cars.append({
                'label': f'12가{n:04d}',
                'name': f'12가{n:04d}',
                'lat': lat, 
                'lng': lng
            })
    print(json.dumps(cars))
    socketio.run(app, debug=True)

main.py

<!DOCTYPE html>
<!--
 @license
 Copyright 2019 Google LLC. All Rights Reserved.
 SPDX-License-Identifier: Apache-2.0
-->
<html>
  <head>
    <title>Add Map</title>
    <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
	  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
    <script src="https://cdn.socket.io/4.7.5/socket.io.min.js"></script>

    <!-- <link rel="stylesheet" type="text/css" href="./style.css" /> -->
    <script type="text/javascript">
    let markers = [];

    window.initMap = function () {
    const map = new google.maps.Map(document.getElementById("map"), {
      center: { lat: 37.7534173597528, lng: 127.567749023437 },
      zoom: 5
    });
    const bounds = new google.maps.LatLngBounds();
  
    var socket = io.connect('http://' + document.domain + ':' + location.port);
    
    socket.on('connect', function() {
      socket.emit( 'map event', {
        data: 'User Connected'
      })
    });

    socket.on( 'map response', function( msg ) {
      console.log( msg )
      var cars = JSON.parse(msg)
      for (var i=0; i < cars.length; i++)
      {
        lat = cars[i].lat
        lng = cars[i].lng
        label = cars[i].label
        isNew = true;

        for (var m of markers) {
          if (m.label == label) {
            isNew = false;
            var latlng = new google.maps.LatLng(lat, lng);
            m.setPosition(latlng);
            break;
          }
        }
        if (isNew) 
        {
          const marker = new google.maps.Marker({
            position: { lat, lng },
            label,
            map,
            optimized: true
          });

          markers.push(marker);
    
          marker.addListener("click", () => {
            map.panTo(marker.position);
            infoWindow.setContent(msg.name);
            infoWindow.open({
              anchor: marker,
              map
            });
          });
        }
        
      }
      
    })
    bounds.extend(new google.maps.LatLng(37.7534173597528, 127.567749023437));
    map.fitBounds(bounds);
  };
  
    </script>
    <script
    defer
    src="https://maps.googleapis.com/maps/api/js?key=...&callback=initMap"
    ></script>
  </head>
  <body>
    <!--The div element for the map -->
    <div id="map" style="height: 800px; width: 100%"></div>
  </body>
</html>

show.html

 

테스트 해보니 대략 100대 정도가 적합한것 같다. 500개만 넘어도 클라이언트가 더디게 움직인다. 서버는 전 택시의 데이터를 관리하되, 클라이언트 화면에 표시 차량은 선별적으로 최대 100개 내외로 지정해야 할 것이다.

 

Gitlab 코드: https://gitlab.com/jasmine125/websocket-car-agent

 

반응형