Python Websocket 控制大屏显示

news2024/12/23 12:58:35

场景描述:

        在做大屏展示时,有这样一个需求:在不刷新页面的情况下,动态改变大屏展示内容,如:执行某个函数,把相关数据醒目展示,轮换数据显示顺序等等。比如有领导参观时,马上切换到领导感兴趣的页面(面向领导编程^_^)

实现思路:

1.搭建一个Websocket服务器。

2.让大屏与Websocket服务器建立长连接。(此操作存在风险,请斟酌使用)

3.再写一个控制页面,用来控制大屏展示内容(css,js)。

实现步骤:

1.搭建一个Websocket服务器,这里使用Python的websockets来搭建。话不多说,直接上代码。

import asyncio
import websockets
import time
import json
host = '0.0.0.0'
port=8765
client_list = {} #客户端列表 

# 检测客户端权限,用户名密码通过才能退出循环
async def check_permit(websocket):
    while True:
        recv_str = await websocket.recv()
        cred_dict = recv_str.split(":")
        if (cred_dict[0] == "screen" and cred_dict[1] == "123456") or (cred_dict[0] == "screencontrol" and cred_dict[1] == "123456"): 
            response_str = "{\"action\":\"login_result\",\"data\":\"登录成功\"}"
            await websocket.send(response_str)         
            return True    #关闭这个socket
        else:
            response_str ="{\"action\":\"login_result\",\"data\":\"抱歉,用户名或密码错误\"}"
            await websocket.send(response_str) #挂起,不进入下面代码

# 接收客户端消息并处理,这里只是简单把客户端发来的返回回去
async def recv_msg(websocket):
    addr=str(websocket.remote_address) 
    client_list[addr]=websocket#用addr作为客户端标识 
    print(addr, "上线了,当前在线:", len(client_list))        
    while True:
        try:
            #接收信息
            recv_text = await websocket.recv()
            print(addr+" say:"+ recv_text)   

            response=""
            #解析传入json
            o = json.loads(recv_text)
            action=o.get('action')
            data=o.get('data')

            if len(action) > 0:
                if (action=="1"):
                    response = data 
                elif (action=="2"):
                    response = data 
                else:
                    response = recv_text

            #通知其他客户端
            for key,socket in client_list.items():
                if(key!=addr):
                    await socket.send(response)


            # #返回信息
            # response_text = f"server: {recv_text}"
            # #await websocket.send(response_text)

            # #通知其他客户端
            # for key,socket in client_list.items():
            #     await socket.send(response_text)

        except Exception as error:
            print("exception:", error)
            if addr in client_list: 
                client_list.pop(addr) #从客户端列表移除
                print("当前在线:", len(client_list))   
            return True

# 服务器端主逻辑
async def main(websocket, path):
    try:
        await check_permit(websocket)
        await recv_msg(websocket)

    except Exception as error:
        print("Exception:", error)

start_server = websockets.serve(main, host, port)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()

这里有个简单授权检查,当客户端连到Websocket服务器时,先要发送证明自己身份的消息,服务器端进行验证,通过了,才能进行后面的交互,否则直接拦截在外面。

2.大屏展示页面,此页面用于模拟大屏展示的效果。

<!DOCTYPE HTML>
<html>

<head>
    <meta charset="utf-8">
    <title>大屏演示</title>
    <script src="https://www.rc114.com/js/jquery-1.11.3.min.js"></script>
    <style type="text/css">
        input {
            padding: 3px;
            outline: none;
            border: 1px solid #ccc;
        }

        .log {
            padding: 10px 0;
            color: gray;
            font-size: 14px;
            line-height: 25px;
        }

        .main {
            margin: 40px auto;
            width: 80%;
        }

        .showArea {
            text-align: center;
            font-size: 48px;
            padding: 150px 0;

        }

        .title {
            border-bottom: 2px solid brown;
            padding-bottom: 10px;
        }
    </style>
</head>

<body>
    <div class="main">
        <h3 class="title">大屏演示</h3>
        <div class="showArea">
            大屏演示区域
        </div> 
        <span style="font-size: 14px;color:brown;">此处打印数据交互日志,可以根据实际情况删除或隐藏。</span>
        <div class="log"></div>
    </div>
    <script type="text/javascript">
        var ws;
        var server = "192.168.100.192";
        var port = "8765";
        $(function () {
            conn();
        })

        function onmessage(msg) {
            log(msg);

            //处理服务器返回消息
            var o = JSON.parse(msg);
            var action = o.action;
            var data = o.data;
            switch (action) {
                case "login_result":
                    break;
                case "setcss":
                    createStyleSheet(data);
                    break;
                case "runjs":
                    eval(data)
                    break;
                default:
                    break;
            }
        }

        function conn() {
            ws = new WebSocket("ws://" + server + ":" + port);
            ws.onopen = function () {
                ws.send("screen:123456");
                log("连接成功");
            };
            ws.onmessage = function (evt) {
                onmessage(evt.data);
            };
            ws.onclose = function () {
                log("连接已关闭...");
            };
        }

        function log(msg) {
            $(".log").append(getNowTime() + ":" + msg + "</br>");
        }
        function getNowTime() {
            var date = new Date();
            var year = date.getFullYear();
            var month = date.getMonth() + 1;
            var day = date.getDate();
            var hour = date.getHours();
            var minute = date.getMinutes();
            var second = date.getSeconds();
            var time = year + '-' + addZero(month) + '-' + addZero(day) + ' ' + addZero(hour) + ':' + addZero(minute) + ':' + addZero(second);
            return time;
        }
        function addZero(s) {
            return s < 10 ? ('0' + s) : s;
        }

        function createStyleSheet(css) {
            var dynamic = document.getElementById("_dynamicCss");
            if (dynamic == undefined) {
                dynamic = document.createElement('style');
                dynamic.id = "_dynamicCss";

                var head = document.head || document.getElementsByTagName('head')[0];
                head.appendChild(dynamic);
            }
            dynamic.type = 'text/css';
            dynamic.innerText = css;
        }
    </script>
    </div>
</body>

</html>

(1)页面加载完毕后,与Websocket服务器建立连接。

(2)在ws.onmessage事件处理服务器端返回的指令,此处写了3个事件类型login_result,setcss,runjs,login_result用来处理登录回调,setcss设置页面css样式,runjs用来执行js代码。

3.大屏控制页,用来控制大屏显示效果。

<!DOCTYPE HTML>
<html>

<head>
    <meta charset="utf-8">
    <title>大屏控制端</title>
    <script src="https://www.rc114.com/js/jquery-1.11.3.min.js"></script>
    <style type="text/css">
        * {
            font-size: 14px;
        }

        h3 {
            font-size: 18px;
        }

        .main {
            margin: 40px auto;
            width: 80%;
        }

        .main table {
            border: 1px solid #ccc;
            border-collapse: collapse;
            width: 100%;
        }

        .main .td-left {
            text-align: right;
            width: 100px;
        }

        .main table td {
            padding: 5px;
            border: 1px solid #ccc;
        }

        input,
        select,
        textarea {
            padding: 3px;
            outline: none;
            border: 1px solid #ccc;
        }

        .log {
            padding: 10px 0;
            color: gray;
            font-size: 14px;
            line-height: 25px;
        }

        input[type="button"] {
            background-color: brown;
            padding: 3px 5px;
            color: white;
            border: 0;

        }
    </style>
</head>

<body>
    <div class="main">
        <h3 style="border-bottom: 2px solid brown;padding-bottom: 10px;">大屏控制端</h3>

        <table>
            <tr>
                <td colspan="2" style="text-align: center;line-height: 32px;">
                    用此页面可以控制大屏页面的展示效果,可以追加css,可以执行js方法,实时生效。
                </td>
            </tr>
            <tr>
                <td class="td-left">服务器</td>
                <td>
                    <span class="server"></span>

                    <input type="button" value="连接" id="btnCon">
                </td>
            </tr>
            <tr>
                <td class="td-left">操作</td>
                <td>
                    <select class="action">
                        <option value="setcss">设置css样式(setcss)</option>
                        <option value="runjs">执行JS方法(runjs)</option>
                    </select>
                </td>
            </tr>
            <tr>
                <td class="td-left">内容</td>
                <td>
                    <textarea style="width: 99%;height: 200px;" class="data">body{background-color:#e3e3e3}</textarea>
                </td>
            </tr>
            <tr>
                <td class="td-left"> </td>
                <td>
                    <input type="button" value="发送消息" id="btnSend">
                    <input type="button" value="清除日志" id="btnClearLog">
                </td>
            </tr>
            <tr>
                <td class="td-left">日志</td>
                <td>
                    <div class="log"></div>
                </td>
            </tr>
        </table>

    </div>
    <script type="text/javascript">
        var ws;
        var server = "192.168.100.192";
        var port = "8765";
        $(function () {
            $(".server").text("ws://" + server + ":" + port);

            conn();
            $("#btnCon").click(function () {
                conn();
            });

            $("#btnSend").click(function () {
                if (ws.readyState == 1) {
                    var action = $(".action").val();
                    var data = $(".data").val();
                    if (action.length > 0) {
                        var o = {};
                        o["action"] = action;
                        o["data"] = data;
                        ws.send(JSON.stringify(o));
                    }
                }
            });
            $("#btnClearLog").click(function () {
                $(".log").text("");
            });

        })

        function onmessage(msg) {
            log(msg);
        }

        function conn() {
            ws = new WebSocket("ws://" + server + ":" + port);

            ws.onopen = function () {
                ws.send("screencontrol:123456");
                log("连接成功");
                $(".server").html("ws://" + server + ":" + port + "<span style='color:green'> 连接成功</span>")
            };

            ws.onmessage = function (evt) {
                onmessage(evt.data);
            };

            ws.onclose = function () {
                log("连接断开(event.code):" + event.code);
                $(".server").html("ws://" + server + ":" + port + "<span style='color:red'> 连接断开</span>")
            };
        }

        function log(msg) {
            $(".log").append(getNowTime() + ":" + msg + "</br>");
        }


        function getNowTime() {
            var date = new Date();
            var year = date.getFullYear();
            var month = date.getMonth() + 1;
            var day = date.getDate();
            var hour = date.getHours();
            var minute = date.getMinutes();
            var second = date.getSeconds();
            var time = year + '-' + addZero(month) + '-' + addZero(day) + ' ' + addZero(hour) + ':' + addZero(minute) + ':' + addZero(second);
            return time;
        }
        function addZero(s) {
            return s < 10 ? ('0' + s) : s;
        }
    </script>
    </div>
</body>

</html>

运行效果:

在大屏控制页,输入指定命令,就可以动态改版大屏展示页的效果了。

大屏连Websocket存在风险,如果Websocket服务器被黑了,就可能会显示其他内容,请谨慎使用。

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/718053.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

技术分享| 融合通讯的架构介绍

在融合通讯中&#xff0c;我们经常听到如下一些术语&#xff1a;MCU服务&#xff0c;SFU架构&#xff0c;MESH架构&#xff0c;星形网络等等。很多客户听到这些数据都是一脸雾水&#xff0c;经常说我们就是要一个可以把多种设备拉到同一个会议中&#xff0c;怎么搞这么复杂。今…

《动手学深度学习》(PyTorch版)-第一章

TOC 第一章 1.1、一般编程要解决的问题 例如&#xff0c;如果我们要为一台微波炉编写一个用户界面 假设我们要编写一个电子邮件客户端。 1.2、深度学习要解决的问题 例如&#xff0c;假设我们想要编写一个判定一张图像中有没有猫的程序。这件事听起来好像很简单&#xff0…

PSI算法极简概述

什么是隐私求交PSI 隐私求交是多方安全计算中的密码学技术&#xff0c;它允许数据持有方通过比较加密集合计算得到交集&#xff0c;且任何一方都不会获得其他信息。PSI还存在一种变体&#xff0c;即CS场景。客户端可以获取其与服务器的交集但是服务器无法学习到该集合。如果在…

【Linux】gcc 的使用 | 动静态库 | make Makefile

程序翻译的过程 程序翻译的过程就是将C语言转换成二进制指令的过程。 预编译&#xff08;完成 去注释、宏替换、头文件展开、条件编译等工作&#xff09;&#xff1a;gcc -E test.c -o test.i 编译&#xff08;将C文本替换成汇编语言&#xff09;&#xff1a;gcc -S test.i -…

Excel实用技巧 如何将EXCEL中在同个单元格中的汉字和数字分开

右边字符串&#xff0c;左边数字 RIGHT(A1,LENB(A1)-LEN(A1)) LEFT(A1,2*LEN(A1)-LENB(A1)) 左边字符串&#xff0c;右边数字 LEFT(A1,LENB(A1)-LEN(A1)) RIGHT(A1,2*LEN(A1)-LENB(A1))

在Ubuntu环境下安装anaconda(很简单!!!!!)

前言&#xff1a;想要使用tensorflow-compression,但是这个在windows下不支持。那我只好去Ubuntu环境下的安装anaconda。但是&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;找了半天&#xff0c;都没找到好的安装教程&#xff0c;浪费了一下午&#xff0c;心态…

每天一点Python——day49

#第四十九天 # #元组的创建方式&#xff1a; #如图&#xff1a; #①直接小括号 a(python,world,98) print(a) print(type(a)) #也可以省略不写 a1python,world,98 print(a1) print(type(a1)) #为什么可以省略省略小括号呢 a3(python) print(type(a3)) #会发现是字符串类型 #因为…

Python 批量修改或替换文本内容

Python 批量修改或替换文本内容 前言源码效果图鸣谢 前言 遇到一个需要将一堆代码中部分文字替换或删除的需求。 需要处理像下面上百个脚本 需要删除每个脚本中类似下图的内容 可以用python批量处理所有的代码&#xff0c;并且删除我想要删除的内容。 源码 其中使用charde…

C#(四十九)之关于string的一些函数

1&#xff1a;startswith 字符串以。。。开头 // startswith 字符串以。。。开头string[] strArr { "asd","azx","qwe","aser","asdfgh"};for (int i 0; i < strArr.Length; i){if(strArr[i].StartsWith("as&qu…

Unity 新输入系统InputAction设置按键的阈值

输入阈值问题 在新的输入系统中&#xff0c;如果添加一个手柄按键只需要添加Pressed就够了&#xff0c;监听他的三个动作就可以得到按下&#xff0c;点击&#xff0c;抬起。 例如下面的代码&#xff1a; inputAction.Player.Trigger_Right.started OnRightTriggerStarted;i…

2023年07月数据库流行度最新排名

点击查看最新数据库流行度最新排名&#xff08;每月更新&#xff09; 2023年07月数据库流行度最新排名 TOP DB顶级数据库索引是通过分析在谷歌上搜索数据库名称的频率来创建的 一个数据库被搜索的次数越多&#xff0c;这个数据库就被认为越受欢迎。这是一个领先指标。原始数…

国产开源流批统一的数据同步工具Chunjun入门实战

文章目录 概述定义特性 部署安装版本对应关系通用配置详解整体配置Content 配置Setting 配置 Local提交Standalone提交Json方式使用SQL方式使用MySQL SinkKafka Sink 概述 定义 Chunjun 官网 https://dtstack.github.io/chunjun-web/ 源码release最新版本1.12.8 Chunjun 文档地…

代码源 扫描线权值线段树 板子

矩形面积并&#xff08;存档&#xff09; 矩形面积并 - 题目 - Daimayuan Online Judge 题意&#xff1a; Code&#xff08;存档&#xff0c;还没写完&#xff09;&#xff1a; #include <bits/stdc.h>#define y1 Y1 #define int long longusing namespace std;const…

k8s的资源配置清单的管理操作

目录 一、资源配置清单1.1 初步认识资源清单中svc的重要配置项1.2 手动编写 svc资源配置1.3 手动生成模板&#xff0c;再编写资源清单1.4 写yaml太累怎么办&#xff1f;1.5 官网下载资源模板 一、资源配置清单 Kubernetes 支持 YAML 和 JSON 格式管理资源对象 JSON 格式&#…

HOT45-二叉树的右视图

leetcode原题链接&#xff1a;二叉树的右视图 题目描述 给定一个二叉树的 根节点 root&#xff0c;想象自己站在它的右侧&#xff0c;按照从顶部到底部的顺序&#xff0c;返回从右侧所能看到的节点值。 示例 1: 输入: [1,2,3,null,5,null,4] 输出: [1,3,4]示例 2: 输入: [1,n…

django celery简单 例子

django celery简单 例子 https://docs.celeryq.dev/en/latest/django/first-steps-with-django.html pip list pip install Django4.2.3 pip install redis4.6.0 pip install celery5.3.1 pip install SQLAlchemy2.0.17 source demo1_venv/bin/activate django-admin start…

激光雷达在ADAS测试中的应用与方案

在科技高速发展的今天&#xff0c;汽车智能化已是必然的趋势&#xff0c;且自动驾驶汽车的研究也在世界范围内进行得如火如荼。而在ADAS测试与开发中&#xff0c;激光雷达以其高性能和高精度占据着非常重要的地位&#xff0c;它是ADAS测试与开发中不可缺少的组成。 一 激光雷达…

sendRedirect进行页面重定向无反应

问题 sendRedirect进行页面重定向无反应 详细问题 笔者使用ServletJSP作为技术框架&#xff0c;使用AJAX进行数据请求&#xff0c;后程序运行完成 response.sendRedirect("请求链接");并没有按照笔者预期&#xff0c;进行页面重定向 请求端核心代码 $.ajax({url…

nginx报403 Forbidden错误

nginx是以root启动的&#xff0c;将 "user nobody" 改为 "user root" 刷新一下配置&#xff1a; /usr/local/nginx/sbin/nginx -t /usr/local/nginx/sbin/nginx -s reload

PCL点云处理之细小空洞填补 (一百九十八)

PCL点云处理之细小空洞填补 (一百九十八) 一、算法介绍二、具体实现1.代码2.结果一、算法介绍 点云扫描过程中,由于遮挡或其他原因,可能存在一些细小空洞,有可能造成数据处理上一些问题,这里介绍一种填补细小空洞的方法。具体方法和效果如下所示 二、具体实现 1.代码…