• 从0开始疫情3D地球


    前面几篇已经完成了前端3D疫情地球的实现和疫情数据的爬虫,如何将这两个链接起来,需要在这两个程序之间搭建一个服务

    服务类型很多,这里使用websocket实现

    1 websocket服务端

    2 websocket客户端

    websocket服务端

    这里使用python实现一个简易的websocket服务端,借助python组件websockets即可实现

    新建一个server.py,做一个简单连接验证,代码最后设定服务地址为 localhost:9998 

    import asyncio
    import websockets
    import json
    from mysqlDataAccess import MysqlDataAccess
    import logging
    from datetime import datetime
    import time
    
    interval = 60
    
    logging.basicConfig(format='%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s',
                        level=logging.INFO)
    logging.info('websocket服务启动')
    
    # 检测客户端权限,用户名密码通过才能退出循环
    async def check_permit(websocket):
        while True:
            recv_str = await websocket.recv()
            cred_dict = recv_str.split(":")
            if cred_dict[0] == "admin" and cred_dict[1] == "123456":
                logging.info('认证通过')
                return True
            else:
                content = {"code": 0, "msg": "authentication failed"}
                logging.info('认证失败')
                await websocket.send(json.dumps(content))
    
    # 接收客户端消息并处理,这里只是简单把客户端发来的返回回去
    async def send(websocket):
        await send_data(websocket)
        while True:
            await send_data(websocket)
            time.sleep(interval)
    
    # 服务器端主逻辑
    async def main_logic(websocket, path):
        await check_permit(websocket)
        # await recv_msg(websocket)
        await send(websocket)
    
    async def send_data(websocket):
        access = MysqlDataAccess()
        data = access.getData()
        logging.info('数据获取完成')
        await websocket.send(json.dumps(data))
        logging.info('信息发送中')
    
    
    start_server = websockets.serve(main_logic, 'localhost', 9998)
    asyncio.get_event_loop().run_until_complete(start_server)
    asyncio.get_event_loop().run_forever()

    里面调用了一个MysqlDataAccess类,这个用来定时的从mysql数据库获取数据,相关代码如下,实现了MySQL的疫情数据的读写

    import pymysql 
    
    MYSQL_HOST = 'localhost'
    MYSQL_DB = 'covid19'
    MYSQL_USER = 'root'
    MYSQL_PASSWORD = '123456'
    MYSQL_PORT = 3306
    
    
    class MysqlDataAccess:
        def __init__(self,host = MYSQL_HOST,database=MYSQL_DB,user=MYSQL_USER,password=MYSQL_PASSWORD,port=MYSQL_PORT):
            try:
                self.db = pymysql.connect(host,user,password,database,charset='utf8',port=port)
                self.cursor = self.db.cursor(cursor=pymysql.cursors.DictCursor)
            except  pymysql.MySQLError as e :
                print(e.args)
    
        def updateCountryPosition(self,name,lng,lat,type):
            sql_update = 'insert into dic_lnglat (name,lng,lat,type) values(%s,%s,%s,%s) on duplicate key update'
            sql_update += ' name= %s,lng=%s,lat=%s,type=%s'
            try:
                self.cursor.execute(sql_update,(name,lng,lat,type) * 2)
                self.db.commit()
                print(name)
            except pymysql.MySQLError as e:
                print(e.args)
                self.db.rollback()
    
        def getData(self):
            sql_query = 'SELECT a.name,b.lng,b.lat,IFNULL(a.new,0) as new,IFNULL(a.now,0) as now,IFNULL(a.total,0) as total,IFNULL(a.cure,0) as cure,IFNULL(a.death,0) as death from covid19  a inner join dic_lnglat b on a.`name`=b.`name`'
            try:
                self.cursor.execute(sql_query)
                return self.sql_fetch_json()
            except pymysql.MySQLError as e:
                print(e.args)
    
    
        def sql_fetch_json(self):
            keys = []
            for column in self.cursor.description:
                keys.append(column[0])
            key_number = len(keys)
    
            json_data = []
            for row in self.cursor.fetchall():
                item = dict()
                for q in range(key_number):
                    item[keys[q]] = row[keys[q]]
                json_data.append(item)
    
            return json_data

    这样一个简单的websocket服务就完成了

    为了启动简单,在windows环境下,新建一个socketServer.bat用来启动服务

    @echo off
    
    
    F:
    rem ִ开启socker服务 
    cd F:mygithubVDDataServerSocketServer
    python3 server.py
    
    TIMEOUT /T 10
    exit

    执行bat就可以打开服务

    websocket客户端

    websocket的客户端,VDEarth是基于js的前端可视化应用,这里需要实现一个前端的websocket客户端,这里直接对之前的VDEarth前端组件进行改造

    在VDEarth项目文件夹src文件夹下新增一个socket.js, 新增socket访问类

    import _ from 'lodash';
    
    function reconnect() {
      console.log('重新连接');
    }
    function open() {
      // Web Socket 已连接上,使用 send() 方法发送数据
      this.ws.send(this.account + ':' + this.password);
    }
    // 接受数据执行回调方法
    function receive(evt, callback) {
      var data = evt.data;
      if (_.isFunction(callback)) {
        callback(JSON.parse(data));
      }
    }
    function close() {
      // 关闭 websocket
      console.log('连接已关闭...');
      reconnect();
    }
    function reload() {
      this.ws.send('reload');
    }
    class socket {
      constructor(server, port, account, password) {
        this.account = account;
        this.password = password;
        this.server = server;
        this.port = port;
      }
    
      init(onmessage) {
        if ('WebSocket' in window) {
          try {
            this.uri = 'ws://' + this.server + ':' + this.port;
            this.ws = new WebSocket(this.uri);
            this.ws.onopen = () => {
              open.call(this);
            };
            this.ws.onmessage = (evt) => {
              receive.call(this, evt, onmessage);
            };
            this.ws.onclose = () => {
              close.call(this);
            };
            window.onbeforeunload = () => {
              reload();
            };
          } catch (error) {
            console.log(error);
          }
        } else {
          // 浏览器不支持 WebSocket
          console.log('您的浏览器不支持 WebSocket!');
        }
      }
    }
    
    export default socket;

    修改VDEarth.js

    数据的加载主要是用在了柱形图和名称标记那里,所以修改那里的代码,即initObj方法,VDEarth类的options方法配置默认的socket链接,server  = localhost,port = 9998,account = admin,password = 123456

    // 创建模型
    function initObj() {
      let self = this;
      let fontloader = new FontLoader();
      // 创建地球模型组
      this.baseGroup = new Group();
      // 创建地球
      this.radius = minSize(this.contentWidth, this.contentHeight) * 0.2;
      let globalMesh = new model().createGlobe(this.radius, this.textrue);
      this.baseGroup.add(globalMesh);
      // 创建星点
      let stars = new model().createStars();
      this.baseGroup.add(stars);
    
      // 创建连接
      var mySocket = new socket(
        this.options.server,
        this.options.port,
        this.options.account,
        this.options.password
      );
      mySocket.init(function (data) {
        // 创建一个标记组
        self.markerGroup = new Group();
        // 创建标记
        var myMarkers = new marker();
        // 柱形
        myMarkers.addBoxMarkers(self.markerGroup, self.radius, data);
        // 加载字体
        if (self.font) {
          myMarkers.addNameMarkers(self.markerGroup, self.radius, data, self.font);
        } else {
          fontloader.load('./fonts/SimHei_Regular.json', function (font) {
            self.font = font;
            myMarkers.addNameMarkers(
              self.markerGroup,
              self.radius,
              data,
              self.font
            );
          });
        }
        self.baseGroup.add(self.markerGroup);
      });
      this.scene.add(this.baseGroup);
    }

    至此定时数据推送和VDEarth的展示更新就完成了

    打开爬虫服务,打开websokcet服务,打开浏览器就输入VDEarth 的web容器的地址就可以了

    相关链接

    从0开始疫情3D地球 - 3D疫情地球VDEarth - 1- 引言 

    从0开始疫情3D地球 - 3D疫情地球VDEarth - 2 - 前端代码构建 

    从0开始疫情3D地球 - 3D疫情地球VDEarth - 3 - 3D地球组件实现(1) 

    从0开始疫情3D地球 - 3D疫情地球VDEarth - 4 - 3D地球组件实现(2) 

    从0开始疫情3D地球 - 3D疫情地球VDEarth - 5 - 疫情数据爬虫 

    从0开始疫情3D地球 - 3D疫情地球VDEarth - 6 - 数据推送  

  • 相关阅读:
    linux基础
    Jscript复选框
    Java 常用的几个算法(菜鸟初学)
    Hello World!
    调用快递鸟接口实现丰密面单打印 顺丰隐私面单 C#版
    快递单号智能识别API接口
    快递鸟开放平台API对接新手指南 极兔速递为例
    打印顺丰快递电子面单步骤 快递鸟教程
    打印京东电子面单步骤 快递鸟教程
    如何使用快递鸟打印顺丰电子面单
  • 原文地址:https://www.cnblogs.com/dpwow/p/12739270.html
Copyright © 2020-2023  润新知