Python Websocket 控制大屏显示

场景描述:

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

实现思路:

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    #关闭这个socketelse: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=""#解析传入jsono = 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.hqwc.cn/news/9386.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

通过阿里云函数计算FC实现音视频转码

1.进入阿里云函数计算FC页面 2.创建音视频转码应用 可以看到代码&#xff0c;看到相关的传参 3.进行测试 编辑测试参数&#xff0c;使用账号的OSS中的资源 点击测试函数进行测试 可以在OSS中看到生成的mp4格式的视频了 测试后发现函数计算可以使用 4. 接下来就是在项目中通过代…

logback日志的分片压缩

logback-spring.xml <?xml version"1.0" encoding"UTF-8"?> <configuration debug"true"><springProperty name"LOG_PATH" source"shands.log.logPath" defaultValue"/var/delonix/logs/local"…

el-date-picker禁用指定日期之前或之后的日期

一、elementUI中el-date-picker禁用指定日期之前或之后的日期 通过配置picker-options配置指定禁用日期&#xff08;pickerOptions写到data里面&#xff09; <el-date-pickerv-model"date"type"date"size"small"value-format"yyyy-MM-d…

基于matlab使用视频和深度学习进行手势识别(附源码)

一、前言 此示例首先演示如何使用预训练的SlowFast视频分类器执行手势识别&#xff0c;然后演示如何使用迁移学习在自定义手势识别数据集上训练分类器。 基于视觉的人类手势识别涉及使用一组视频帧预测手势&#xff0c;例如挥手打招呼、手语手势或鼓掌。手势识别的一个吸引人…

【VSCODE】4、vscode git pull/push 报错 remote: HTTP Basic: Access denied

一、报错示例 在执行 git pull/push 的时候报错如下 二、解决方式 该问题来自 vscode 的身份验证 打开 vscode →code → 首选项 → 设置搜索 git.terminalAuthentication取消选中该选项重启终端即可

5.8.5 TCP可靠传输(一)序号确认机制

5.8.5 TCP可靠传输&#xff08;一&#xff09;序号确认机制 TCP是可靠的传输层协议&#xff0c;主要通过序号确认机制、超时重传机制、定时器三个方面实现可靠传输。 一、序号确认机制 TCP将所要传送的整个的应用层报文看成是一个一个字节组成的数据流&#xff0c;并对每一个…

sql统计某一字段不同状态的数量,时间戳转日期格式、按月统计使用

背景 1、在sql语句中统计一个字段的不同状态时&#xff0c;需要将每个状态的数量查出来&#xff0c;在进行统一输出&#xff0c;涉及表多次查询&#xff0c;下面用一个聚合函数的方式进行查询&#xff0c;比较方便&#xff0c;容易理解。 2、有时候数据表中的时间字段存储的是…

Jmeter使用之:怎么编写扩展函数(二)

目录 前言&#xff1a; 1、实现function的类的package声明必须包含".functions" 2、需要继承org.apache.jmeter.functions.AbstractFunction&#xff0c;并且实现相应的方法。 第一步&#xff1a;eclipse 导入jmeter目录&#xff1a;apache-jmeter-2.13libext下的…

卡尔曼滤波简单实例分析

1 现实问题 假设一个物体位于1000米处以自由落体运动&#xff0c;底面有一台具有特殊功能的雷达&#xff0c;对其进行观察&#xff0c;现需要对其下落的高度进行测量&#xff1b; &#xff08;1&#xff09;建模 速度&#xff1a;V gt 位置&#xff1a;Y -Vt Y0 &#xff0…

ES6: 模版字符串

前言: ES5 中我们表示字符串的时候使用 或者 "" 作用: 在 ES6 中&#xff0c;我们还有一个东西可以表示字符串&#xff0c;就是 &#xff08;反引号&#xff09; let str hello worldconsole.log(typeof str) // string和单引号还有双引号的区别: 反引号可以换行…

Android 应用层 到 HAL 层

Android 应用层 到 HAL 层 1、相关知识点1.1 概要1.2 参考 2、拿SensorService举例2.1 Android Apps > Android Framework阶段2.2 Android Framework内部阶段2.2.1 frameworks/base2.2.2 frameworks/native 2.3 Android Framework > HAL 阶段2.3.1 旧版 HAL 1、相关知识点…

Python爬虫——怎么搭建和维护一个本地IP池

目录 背景 一、什么是本地代理IP池 二、代理IP池功能架构图 三、各个组件功能说明及示例代码 1. IP池管理器 2. 代理IP获取器 3. IP质量检测器 4、数据存储器 5、API接口层 6、应用程序 总结 背景 在我们进行爬虫工作时&#xff0c;经常需要使用代理IP。大多数代理…