首页 > 数据库 >fastapi websocket mongodb swagger-ui离线

fastapi websocket mongodb swagger-ui离线

时间:2022-12-07 15:14:18浏览次数:42  
标签:websocket socket fastapi 离线 agv msg import data

E:\song\agv_fastapi_socket_v3\app.py

import json
# fastapi
from fastapi import FastAPI, WebSocket, Request, WebSocketDisconnect
from fastapi.responses import RedirectResponse, HTMLResponse
from fastapi.staticfiles import StaticFiles
from fastapi.openapi.docs import get_swagger_ui_html
from fastapi.templating import Jinja2Templates
from fastapi.middleware.cors import CORSMiddleware
# 启动数据库
# from config.config import initiate_database
from routes.scheduler import scheduler_router
from routes.status import status_router
from routes.config import config_router
from routes.control import control_router
from routes.navigate import navigate_router

from websocket.manager import websocketmanager
# websocket dispatch
from websocket.dispatch import dispatch_socket
# scheduler
from scheduler.scheduler import scheduler

# 启动定时器
scheduler.start()

# docs_url一定要设置成None,才会使用本地的 swagger-ui 的静态文件
app = FastAPI(docs_url=None)


app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

templates = Jinja2Templates(directory="templates")


app.mount('/static', StaticFiles(directory='static'), name='static')


@app.get('/docs', include_in_schema=False)
async def custom_swagger_ui_html():
    return get_swagger_ui_html(
        openapi_url=app.openapi_url,
        title=app.title + " - Swagger UI ",
        oauth2_redirect_url=app.swagger_ui_oauth2_redirect_url,
        swagger_js_url="/static/swagger-ui/swagger-ui-bundle.js",
        swagger_css_url="/static/swagger-ui/swagger-ui.css",
        swagger_favicon_url="/static/swagger-ui/favicon.png"
    )


# 初始化事件
@app.on_event("startup")
async def start_database():
    # await initiate_database()
    pass


# docs文档
@app.get("/", tags=["Docs"])
async def get_docs():
    return RedirectResponse("/docs")


# jinjia2的测试网页
@app.get("/jinjia2", response_class=HTMLResponse)
async def read_jinjia2(request: Request):
    return templates.TemplateResponse("index.html", {"request": request, "name": "Alice"})


# websocket的测试网页
@app.get("/websocket", response_class=HTMLResponse)
async def websocket_test(request: Request):
    return templates.TemplateResponse("websocket.html", {"request": request})


@app.websocket("/wstest")
async def websocket_endpoint(websocket: WebSocket):
    await websocket.accept()
    while True:
        data = await websocket.receive_text()
        await websocket.send_text(f"send from serve: {data}")


app.include_router(scheduler_router, tags=["Scheduler"], prefix="/scheduler")
app.include_router(status_router, tags=["Status"], prefix="/status")
app.include_router(config_router, tags=["Config"], prefix="/config")
app.include_router(control_router, tags=["Control"], prefix="/control")
app.include_router(navigate_router, tags=["Navigate"], prefix="/navigate")


# client_id代表用户的唯一标识,用来区分不同的用户
@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
    # 将新的socket连接存储起来
    await websocketmanager.connect(websocket)
    try:
        while True:
            # data = await websocket.receive_json()
            data = await websocket.receive_text()
            data_dict = eval(data)
            if 'websocket' in data_dict:  # 处理心跳检测
                await websocket.send_text("pong")
            else:
                await dispatch_socket(data_dict['msg_type'], data_dict["msg"], websocket)
    except WebSocketDisconnect:
        websocketmanager.disconnect(websocket)
        await websocketmanager.broadcast(f"Client left the chat")

E:\song\agv_fastapi_socket_v3\main.py

import uvicorn

if __name__ == '__main__':
    uvicorn.run('app:app', host="127.0.0.1", port=9000, reload=True)```
# `E:\song\agv_fastapi_socket_v3\config\config.py`

```py
from typing import Optional

from beanie import init_beanie
from motor.motor_asyncio import AsyncIOMotorClient
from pydantic import BaseSettings

from models.student import Student


class Settings(BaseSettings):
    # database configurations
    DATABASE_URL: Optional[str] = None

    class Config:
        env_file = ".env"
        orm_mode = True


async def initiate_database():
    client = AsyncIOMotorClient(Settings().DATABASE_URL)
    await init_beanie(database=client['agv'],
                      document_models=[Student])

E:\song\agv_fastapi_socket_v3\dao\student.py

from typing import List, Union

from beanie import PydanticObjectId

from models.student import Student

student_collection = Student


async def retrieve_students() -> List[Student]:
    students = await student_collection.all().to_list()
    return students


async def add_student(new_student: Student) -> Student:
    student = await new_student.create()
    return student


async def retrieve_student(id: PydanticObjectId) -> Student:
    student = await student_collection.get(id)
    if student:
        return student


async def delete_student(id: PydanticObjectId) -> bool:
    student = await student_collection.get(id)
    if student:
        await student.delete()
        return True


async def update_student_data(id: PydanticObjectId, data: dict) -> Union[bool, Student]:
    des_body = {k: v for k, v in data.items() if v is not None}
    update_query = {"$set": {
        field: value for field, value in des_body.items()
    }}
    student = await student_collection.get(id)
    if student:
        await student.update(update_query)
        return student
    return False

E:\song\agv_fastapi_socket_v3\models\student.py

from typing import Optional, Any

from beanie import Document
from pydantic import BaseModel, EmailStr


class Student(Document):
    fullname: str
    email: EmailStr
    course_of_study: str
    year: int
    gpa: float

    class Config:
        schema_extra = {
            "example": {
                "fullname": "Abdulazeez Abdulazeez Adeshina",
                "email": "[email protected]",
                "course_of_study": "Water resources engineering",
                "year": 4,
                "gpa": "3.76"
            }
        }


class UpdateStudentModel(BaseModel):
    fullname: Optional[str]
    email: Optional[EmailStr]
    course_of_study: Optional[str]
    year: Optional[int]
    gpa: Optional[float]

    class Collection:
        name = "student"

    class Config:
        schema_extra = {
            "example": {
                "fullname": "Abdulazeez Abdulazeez",
                "email": "[email protected]",
                "course_of_study": "Water resources and environmental engineering",
                "year": 4,
                "gpa": "5.0"
            }
        }


class Response(BaseModel):
    status_code: int
    response_type: str
    description: str
    data: Optional[Any]

    class Config:
        schema_extra = {
            "example": {
                "status_code": 200,
                "response_type": "success",
                "description": "Operation successful",
                "data": "Sample data"
            }
        }

E:\song\agv_fastapi_socket_v3\routes\config.py

from fastapi import APIRouter
from typing import Optional
from pydantic import BaseModel
# agv socket 工厂方法
from tcpsocket.factory import agv_socket_factory
# status的端口号
from tcpsocket.params import Port

# 创建status router路由
config_router = APIRouter()

# 创建agv status的socket
agv_status_socket = agv_socket_factory.create(Port.STATUS.value)
agv_config_socket = agv_socket_factory.create(Port.CONFIG.value)


class StatusParams(BaseModel):
    msg_type: int
    msg: Optional[dict]

    class Config:
        schema_extra = {
            "example": {
                "msg_type": 1000,
                "msg": {"参数名称": "xx参数"}
            }
        }


@config_router.get("/", response_description="编号 查询结果")
async def get_config():
    return "地图"


@config_router.post("/", response_description="编号 查询结果")
async def post_config(params: StatusParams):
    print(params)
    return {
        "map": '地图'
    }
    # try:
    #     agv_socket.send(1,Status(params.msg_type).value,{})
    #     res = agv_socket.receive()
    #     return res
    # except Exception as e:
    #     print(e)
    #     raise HTTPException(
    #         status_code=409,
    #         detail="查询编号不正确"
    #     )

E:\song\agv_fastapi_socket_v3\routes\control.py


from fastapi import APIRouter
from typing import Optional
from pydantic import BaseModel
# agv socket 工厂方法
from tcpsocket.factory import agv_socket_factory
# status的端口号
from tcpsocket.params import Port

# 创建status router路由
control_router = APIRouter()

# 创建agv status的socket
agv_control_socket = agv_socket_factory.create(Port.CONTROL.value)


class StatusParams(BaseModel):
    msg_type: int
    msg: Optional[dict]

    class Config:
        schema_extra = {
            "example": {
                "msg_type": 1000,
                "msg": {"参数名称": "xx参数"}
            }
        }


@control_router.get("/", response_description="编号 查询结果")
async def get_control():
    return "地图"


@control_router.post("/", response_description="编号 查询结果")
async def post_control(params: StatusParams):
    print(params)
    return {
        "map": '地图'
    }
    # try:
    #     agv_socket.send(1,Status(params.msg_type).value,{})
    #     res = agv_socket.receive()
    #     return res
    # except Exception as e:
    #     print(e)
    #     raise HTTPException(
    #         status_code=409,
    #         detail="查询编号不正确"
    #     )

E:\song\agv_fastapi_socket_v3\routes\navigate.py


from fastapi import APIRouter
from typing import Optional
from pydantic import BaseModel
# agv socket 工厂方法
from tcpsocket.factory import agv_socket_factory
# status的端口号
from tcpsocket.params import Port

# 创建status router路由
navigate_router = APIRouter()

# 创建agv status的socket
agv_navigate_socket = agv_socket_factory.create(Port.NAVIGATE.value)


class StatusParams(BaseModel):
    msg_type: int
    msg: Optional[dict]

    class Config:
        schema_extra = {
            "example": {
                "msg_type": 1000,
                "msg": {"参数名称": "xx参数"}
            }
        }


@navigate_router.get("/", response_description="编号 查询结果")
async def get_navigate():
    return "地图"


@navigate_router.post("/", response_description="编号 查询结果")
async def post_navigate(params: StatusParams):
    print(params)
    return {
        "map": '地图'
    }
    # try:
    #     agv_socket.send(1,Status(params.msg_type).value,{})
    #     res = agv_socket.receive()
    #     return res
    # except Exception as e:
    #     print(e)
    #     raise HTTPException(
    #         status_code=409,
    #         detail="查询编号不正确"
    #     )

E:\song\agv_fastapi_socket_v3\routes\scheduler.py

from fastapi import APIRouter, Body
from scheduler.scheduler import scheduler

scheduler_router = APIRouter()


@scheduler_router.get("/", response_description="Toggle the scheduler")
async def toggle_scheduler(flag: bool):
    if flag:
        scheduler.resume()
    else:
        scheduler.pause()
    return {
        "status_code": 200,
        "response_type": "success",
        "description": "Students data retrieved successfully",
        "data": "ok"
    }

E:\song\agv_fastapi_socket_v3\routes\status.py

from fastapi import APIRouter
from typing import Optional
from pydantic import BaseModel
# agv socket 工厂方法
from tcpsocket.factory import agv_socket_factory
# status的端口号
from tcpsocket.params import Port

# 创建status router路由
status_router = APIRouter()
# 创建agv status的socket
agv_status_socket = agv_socket_factory.create(Port.STATUS.value)


class StatusParams(BaseModel):
    msg_type: int
    msg: Optional[dict]

    class Config:
        schema_extra = {
            "example": {
                "msg_type": 1000,
                "msg": {"参数名称": "xx参数"}
            }
        }


@status_router.get("/")
async def get_status(msg_type: int):
    print(msg_type)
    return 'ok'


@status_router.post("/", response_description="编号 查询结果")
async def post_status(params: StatusParams):
    return {
        "name": 'Alice',
        "age": 19,
        "sex": "male"
    }
    # try:
    #     agv_socket.send(1,Status(params.msg_type).value,{})
    #     res = agv_socket.receive()
    #     return res
    # except Exception as e:
    #     print(e)
    #     raise HTTPException(
    #         status_code=409,
    #         detail="查询编号不正确"
    #     )

E:\song\agv_fastapi_socket_v3\routes\student.py

from fastapi import APIRouter, Body

from dao.student import *
from models.student import *

student_router = APIRouter()


@student_router.get("/", response_description="Students retrieved", response_model=Response)
async def get_students():
    return {
        "status_code": 200,
        "response_type": "success",
        "description": "Students data retrieved successfully",
        "data": "test"
    }

E:\song\agv_fastapi_socket_v3\scheduler\scheduler.py

# 定时器任务计划
from apscheduler.schedulers.asyncio import AsyncIOScheduler
scheduler = AsyncIOScheduler()

E:\song\agv_fastapi_socket_v3\socket_routes\status.py

import json
from websocket.manager import websocketmanager
from scheduler.scheduler import scheduler


# dispatch status,根据msg_type的值,来决定哪些查询添加定时器任务,哪些查询直接查询返回结果
async def dispatch_status(msg_type, msg, websocket):
    if msg_type == 1020:
        await add_schdulers(msg_type, msg, websocket)
        print("添加任务计划")
    else:
        print("直接查询返回")


# 添加定时器任务
async def add_schdulers(msg_type, msg, websocket):
    scheduler.add_job(job_status_task, 'interval',
                      seconds=5, args=[websocket])
    scheduler.add_job(job_status_loc, 'interval',
                      seconds=5, args=[websocket])


# 定时获取路径导航信息
async def job_status_task(websocket):
    await websocketmanager.send_personal_json(json.dumps({"robot_status_task_res": "name"}), websocket)

# 定时获取agv的位置坐标


async def job_status_loc(websocket):
    await websocketmanager.send_personal_json(json.dumps({"robot_status_loc_res": "name"}), websocket)

E:\song\agv_fastapi_socket_v3\tcpsocket\agvsocket.py

import json
import socket
import struct


class AgvSocket:
    __PACK_FMT_STR = '!BBHLH6s'

    def __init__(self, ip, port):
        so = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        so.connect((ip, port))
        so.settimeout(5)
        self.so = so

    def send(self, req_id, msg_type, msg={}):
        raw_msg = self.__pack_msg(req_id, msg_type, msg={})
        self.so.send(raw_msg)

    def receive(self):
        global data
        data_all = b''

        try:
            data = self.so.recv(16)
        except socket.timeout:
            print('timeout')
            self.so.close()

        json_data_len = 0
        back_req_num = 0

        if len(data) < 16:
            print('pack head error')
            print(data)
            self.so.close()
        else:
            header = struct.unpack(AgvSocket.__PACK_FMT_STR, data)
            json_data_len = header[3]
            back_req_num = header[4]
        data_all += data
        data = b''
        read_size = 1024
        try:
            while json_data_len > 0:
                recv = self.so.recv(read_size)
                data += recv
                json_data_len -= len(recv)
                if json_data_len < read_size:
                    read_size = json_data_len
            data_all += data
            return json.loads(data_all[16:].decode())

        except socket.timeout:
            print('timeout')

    def close(self):
        self.so.close()

    @staticmethod
    def __pack_msg(req_id, msg_type, msg={}):
        msg_len = 0
        json_str = json.dumps(msg)

        if msg != {}:
            msg_len = len(json_str)

        raw_msg = struct.pack(AgvSocket.__PACK_FMT_STR, 0x5A, 0x01, req_id,
                              msg_len, msg_type, b'\x00\x00\x00\x00\x00\x00')
        if msg != {}:
            raw_msg += bytearray(json_str, 'ascii')

        return raw_msg

E:\song\agv_fastapi_socket_v3\tcpsocket\factory.py

from .params import IP, Port
from .agvsocket import AgvSocket


class FactoryTcpSocket:
    def __init__(self, ip: str):
        self.ip = ip
        self.socket_dic = {}

    def create(self, port):
        pass
        # res = self.socket_dic.get(port)
        # if res is None:
        #     agv_socket = AgvSocket(self.ip, port)
        #     self.socket_dic[port]=agv_socket
        #     return agv_socket
        # else:
        #     return res


agv_socket_factory = FactoryTcpSocket(IP)

E:\song\agv_fastapi_socket_v3\tcpsocket\params.py

from enum import Enum

IP = "192.168.192.5"


class Port(Enum):
    STATUS = 19204
    CONTROL = 19205
    NAVIGATE = 19206
    CONFIG = 19207
    OTHER = 19210
    PUSH = 192301


class Status(Enum):
    INFO = 1000  # 查询机器人信息
    RUN = 1002  # 机器人运行信息
    LOC = 1004  # 机器人位置
    SPEED = 1005  # 机器人速度
    BLOCK = 1006  # 机器人的被阻挡状态
    BATTERY = 1007  # 机器人电池状态
    MOTOR = 1040  # 电机状态信息
    LASER = 1009  # 激光点云数据
    AREA = 1011  # 机器人当前所在区域
    EMERGENCY = 1012  # 机器人急停状态
    IO = 1013  # 查询机器人I/O状态
    IMU = 1014  # 查询机器人IMU数据
    RFID = 1015  # RFID数据
    ULTRASONIC = 1016  # 超声传感器数据
    PGV = 1017  # 二维码数据
    ENCODER = 1018  # 编码器数据
    TASK = 1020  # 机器人导航状态
    TASK_STATUS_PACKAGE = 1110  # 机器人任务状态
    RELOC = 1021  # 机器人定位状态
    LOADMAP = 1022  # 地图载入状态
    SLAM = 1025  # 机器人扫图状态
    DISPATCH = 1030  # 机器人当前的调度状态
    ALARM = 1050  # 机器人报警状态
    CURRENT_LOCK = 1060  # 当前控制权所有者
    MAP = 1300  # 机器人载入的地图以及存储的地图
    STATION = 1301  # 查询机器人当前载入地图中的站点信息
    STARTDMXSCRIPT = 1903  # 运行氛围灯脚本
    STOPBATTERYSCRIPT = 1904  # 停止氛围灯脚本
    ALL1 = 1100  # 批量查询数据1
    ALL2 = 1101  # 批量查询数据2
    ALL3 = 1102  # 批量查询数据3


class Control(Enum):
    pass


class Navigate(Enum):
    pass


class Config(Enum):
    # 从机器人上下载地图
    DOWN_LOAD_MAP = 4011


class Other(Enum):
    pass


class Push(Enum):
    pass

E:\song\agv_fastapi_socket_v3\tcpsocket\socket_config.py

import socket
import json
import time
import struct

PACK_FMT_STR = '!BBHLH6s'
IP = '192.168.192.5'
Port = 19207


def packMasg(reqId, msgType, msg={}):
    msgLen = 0
    jsonStr = json.dumps(msg)
    if (msg != {}):
        msgLen = len(jsonStr)
    rawMsg = struct.pack(PACK_FMT_STR, 0x5A, 0x01, reqId,
                         msgLen, msgType, b'\x00\x00\x00\x00\x00\x00')
    if (msg != {}):
        rawMsg += bytearray(jsonStr, 'ascii')
        print(msg)
    return rawMsg


so = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
so.connect((IP, Port))
so.settimeout(5)
# test_msg = packMasg(1,1110,{"task_ids":["SEER78914"]})
# 查询agv中所有的地图信息
test_msg = packMasg(1, 1300)
# 查询motor
# test_msg = packMasg(1,1040,{"motor_names":["left motor"]})
# 下载地图
test_msg = packMasg(1, 4011, {"map_name": "20221116_biaotou"})

so.send(test_msg)

dataall = b''
# while True:
try:
    data = so.recv(16)
except socket.timeout:
    print('timeout')
    so.close

jsonDataLen = 0
backReqNum = 0

if (len(data) < 16):
    print('pack head error')
    print(data)
    so.close()
else:
    header = struct.unpack(PACK_FMT_STR, data)
    jsonDataLen = header[3]
    backReqNum = header[4]
dataall += data
data = b''
readSize = 1024
try:
    while (jsonDataLen > 0):
        recv = so.recv(readSize)
        data += recv
        jsonDataLen -= len(recv)
        if jsonDataLen < readSize:
            readSize = jsonDataLen
    dataall += data
    with open('map.json', 'w', encoding='utf-8') as f:
        f.write(dataall[16:].decode())

except socket.timeout:
    print('timeout')

so.close()

E:\song\agv_fastapi_socket_v3\templates\index.html

<!DOCTYPE html>
<html lang="zh">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>jinjia2</title>
    <link href="{{ url_for('static', path='/index/style.css') }}" rel="stylesheet">
</head>

<body>
    <h1>this is jinja2 template</h1>
    <h2>{{name}}</h2>

</body>

</html>```
# `E:\song\agv_fastapi_socket_v3\templates\websocket.html`

```html
<!DOCTYPE html>
<html>

<head>
    <title>Chat</title>
</head>

<body>
    <h1>WebSocket Chat</h1>
    <form action="" onsubmit="sendMessage(event)">
        <input type="text" id="messageText" autocomplete="off" />
        <button>Send</button>
    </form>
    <ul id='messages'>
    </ul>
    <script>
        // socket的连接地址
        const ws = new WebSocket("ws://localhost:9000/status/ws");

        // socket 连接成功的回调
        ws.addEventListener('open', (e) => {
            console.log(`socket 连接成功`)
        })
        // socket 连接失败的回调
        ws.addEventListener('error', (e) => {
            console.log(`socket 连接失败`)
        })
        // socket 连接断开时候的回调
        ws.addEventListener('close', (e) => {
            console.log(`socket 连接断开`)
        })

        // 采用这中属性赋值的方法,只能有一个回调函数,如果想要有多个回调函数,可以采用上面的addEventListener的方法,来添加回调函数
        ws.onmessage = function (event) {
            receMessage(event.data)
        };

        // 将接受到内容渲染到界面上
        function receMessage(msg) {
            var messages = document.getElementById('messages')
            var message = document.createElement('li')
            var content = document.createTextNode(msg)
            message.appendChild(content)
            messages.appendChild(message)
        }

        // 发送内容
        function sendMessage(event) {
            var input = document.getElementById("messageText")
            ws.send(input.value)
            input.value = ''
            event.preventDefault()
        }
    </script>
</body>

</html>```
# `E:\song\agv_fastapi_socket_v3\websocket\dispatch.py`

```py
from socket_routes.status import dispatch_status


# 分发任务
async def dispatch_socket(msg_type, msg, websocket):
    # 查询机器人状态
    if msg_type >= 1000 and msg_type <= 1999:
        print("状态api")
        await dispatch_status(msg_type, msg, websocket)
    elif msg_type >= 2000 and msg_type <= 2999:
        print("控制api")
    elif msg_type >= 3000 and msg_type <= 3999:
        print("导航api")
    elif msg_type >= 4000 and msg_type <= 4999:
        print("配置api")
    elif msg_type >= 6000 and msg_type <= 6999:
        print("其他api")
    elif msg_type == 9300 or msg_type == 19301:
        print("推送api")
    else:
        print("暂无此api")

E:\song\agv_fastapi_socket_v3\websocket\manager.py

from typing import List
from fastapi.websockets import WebSocket


class ConnectionManager:
    def __init__(self):
        self.active_connections: List[WebSocket] = []

    async def connect(self, websocket: WebSocket):
        await websocket.accept()
        self.active_connections.append(websocket)

    def disconnect(self, websocket: WebSocket):
        self.active_connections.remove(websocket)

    # 直接发送,就是单个发送
    async def send_personal_message(self, message: str, websocket: WebSocket):
        await websocket.send_text(message)

    async def send_personal_json(self, message: str, websocket: WebSocket):
        await websocket.send_json(message)

    # 广播,遍历所有的connection连接,然后发送消息

    async def broadcast(self, message: str):
        for connection in self.active_connections:
            await connection.send_text(message)


websocketmanager = ConnectionManager()

标签:websocket,socket,fastapi,离线,agv,msg,import,data
From: https://www.cnblogs.com/zhuoss/p/16963090.html

相关文章

  • FastApi (一)前端项目
    来自《PythonFastAPIWeb开发从入门到项目实战》一书的前端项目1.项目目录2.主文件main.js项目运行时执行的第一个文件,初始化运行环境,统一管理项目用到的模块import......
  • 离线下载功能设计
    1、功能梳理 excel导出全部异步进行,生成一个下载清单即可 下载清单默认状态初始化,映射地址默认无法访问。异步完成文件服务器生成到映射位置,下载清单为已完成状态 已完成......
  • 摹客RP,资源库可随项目同步离线导出!
    Hello,小伙伴们,又到了摹客的新功能播报时间。本月更新,摹客RP在导出项目文件方面,可支持​​同步导出该项目的资源库​​​,方便后续复用资源;摹客协作对​​任务管理​​模块进......
  • SpringBoot整合Netty+WebSocket
    SpringBoot整合Netty+WebSocket构建环境pom.xml<?xmlversion="1.0"encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w......
  • Uniapp 版本更新(采用离线打包)
    Uniapp版本更新(采用离线打包)其实离线打包方式的版本更新大体上跟云打包方式的版本更新差不多,最主要的差别就是需要后端在离线打包的时候做一些配置,可点击详情链接查看离......
  • 离线安装docker
    #!/bin/bash#url=https://download.docker.com/linux/static/stable/x86_64docker_version=$1get_docker(){[-d"/opt/docker-${docker_version:-20.10.9}"]||......
  • websocket
    转自小林coding使用HTTP不断轮询其实问题的痛点在于,怎么样才能在用户不做任何操作的情况下,网页能收到消息并发生变更。最常见的解决方案是,网页的前端代码里不断定时发......
  • centos7 离线(内网环境无外网) 安装docker
    1.环境1.centos7内网环境无外网连接,yum安装会失效,采用离线安装包方式安装docker 2.下载安装包1.百度网盘:链接:https://pan.baidu.com/s/1ArPt-NhjtdKTBW3I4BE-......
  • WGCLOUD进阶教程:主机下线离线不上报数据的原因 超详细整理
    agent主机下线问题,agent日志打印防篡改校验失败或者防篡改校验错误次数大于10次,不再上报数据这个问题注意几点,按照顺序依次排查下1、server和agent的主机系统时间差不能大......
  • ubuntu docker离线安装教程
    离线安装包下载docker离线安装时需要三个安装包:containerd.io包、docker-ce-cli包,docker-ce包,​​下载地址:https://download.docker.com/linux/ubuntu/dists/xenial/pool/st......