Commit 0237384b by 周田

feat:修改通信表规则,channel使用redis,web控制device容器,页面不被注销

parent e15a8807
......@@ -3,3 +3,5 @@ __pycache__
.idea
assets
*.tar
dist
build
......@@ -85,3 +85,4 @@ ps:以上步骤在 windows 环境和 ubuntu 20.04 下都测试过,都能正
* 如果是在远程的情况下,需要将 vue_django 目录中 urls.py 文件中的 `mqtt``chat` url 给注释了,否则启动不成功
* ![1692841883700](image/README/1692841883700.png)
* 使用 pyinstaller 打包之后的可执行文件需要在 runserver 后加上 --noreload
\ No newline at end of file
No preview for this file type
......@@ -10,6 +10,7 @@ router.register('device_communication/simulate_communicate',
urlpatterns = [
re_path(r'^device_communication/$', views.get_protocol_names),
re_path(r'^device_communication/init/$', views.init),
re_path(r'^device_communication/protocol_performance/(?P<protocol_name>.+)/$', views.get_protocol_field_names),
re_path(r'^device_communication/performance/(?P<type>.+)/(?P<protocol_name>.+)/$',
views.get_checked_field_names),
......
......@@ -24,6 +24,39 @@ def get_protocol_names(request):
return Response(data=res_data, status=status.HTTP_200_OK)
@api_view(['POST'])
def init(request):
"""
通信参数初始化,移除了 device_info 中与 udp 组播相关的参数
多 performance_fields 字段
"""
device_infos = TableXproAllDevinfo.objects.all()
device_communication_manager = DeviceCommunicationParameter.objects.all()
# 如果设备信息表中有数据,而设备通信参数表中没有数据,
# 则将设备信息表中的数据添加到设备通信参数表中
if (len(device_infos) != 0 and
len(device_communication_manager) == 0):
DeviceCommunicationParameter.objects.bulk_create(
[DeviceCommunicationParameter(station_id=device_info.sta_id,
device_id=device_info.dev_id,
device_name=device_info.dev_name,
device_name_chn=device_info.dev_name_chn,
protocol_name=device_info.protocol_name,
communicate_mode=device_info.comunitate_mode,
tcp_ip=device_info.tcp_ip,
tcp_port=device_info.tcp_port,
udp_ip_src=device_info.udp_ip_src,
udp_port_src=device_info.udp_port_src,
udp_ip_dst=device_info.udp_ip_dst,
udp_port_dst=device_info.udp_port_dst,
performance_fields=json.dumps([]))
for device_info in device_infos])
return Response(status=status.HTTP_200_OK)
@api_view(['GET'])
def get_protocol_field_names(request, protocol_name):
"""
......
......@@ -14,13 +14,14 @@
</el-menu-item>
</el-menu>
</el-header>
<el-button type="primary" @click="restartDevice">重启device</el-button>
<el-main>
<router-view />
<!-- <router-view v-slot="{ Component }">
<!-- <router-view /> -->
<router-view v-slot="{ Component }">
<keep-alive>
<component :is="Component" />
</keep-alive>
</router-view> -->
</router-view>
</el-main>
</el-container>
</div>
......@@ -33,6 +34,8 @@ import { DeviceProtocol, ProtocolCmd } from "@/dao/device";
import { GetProtocolVersion, GetCurrentVersion } from '@/dao/protocol';
import { useProtocolInfoStore } from './stores/protocolInfo';
import { useProtocolVersionStore } from '@/stores/allProtocolVersion';
import { ElMessage, ElMessageBox } from 'element-plus'
import request from '@/plugins/axios/requests'
const store = useProtocolVersionStore()
const protocolStore = useProtocolInfoStore()
......@@ -55,6 +58,40 @@ onMounted(async () => {
protocolStore.protocolCmd = res.data
})
})
const restartDevice = () => {
ElMessageBox.confirm(
'确定要重启 device 模块吗?',
'警告',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
request.post('/api/restart_device/')
.then(() => {
ElMessage({
type: 'success',
message: '重启成功',
})
})
.catch(() => {
ElMessage({
type: 'error',
message: '重启失败',
})
})
})
.catch(() => {
ElMessage({
type: 'info',
message: '取消成功',
})
})
}
</script>
<style>
......
......@@ -40,6 +40,7 @@ import useClipboard from 'vue-clipboard3'
import DeviceInfoCard from '@/components/device_communication/DeviceInfoCard'
import type { DeviceInfo } from '@/components/device_communication/types'
import EditDialog from '@/components/device_communication/EditDialog';
import request from '@/plugins/axios/requests';
type propType = {
tabType: string
......@@ -49,15 +50,39 @@ const props = defineProps<propType>()
const device_infos = ref<Record<string, DeviceInfo[]>>({})
// 获取当前选择的页面
onMounted(() => {
axios.get('/api/device_communication/' + props.tabType + '/')
// props.tabType 的值为 communicate 或者 simulate_communicate
request.get<string>('/api/device_communication/' + props.tabType + '/')
.then(res => {
// console.log(res.data);
// console.log(res.data); // string 类型
let data: DeviceInfo[] = JSON.parse(res.data!)
// 将数据按照不同的 station_id 分组
for (let i = 0; i < res.data.length; i++) {
if (device_infos.value[res.data[i].station_id] !== undefined) {
device_infos.value[res.data[i].station_id].push(res.data[i])
} else {
device_infos.value[res.data[i].station_id] = [res.data[i]]
if (data.length === 0) {
// 如果返回的数据为空,则初始化
request.post('/api/device_communication/init/')
// 重新获取数据
request.get<string>('/api/device_communication/' + props.tabType + '/')
.then(res => {
let data: DeviceInfo[] = JSON.parse(res.data!)
for (let i = 0; i < data.length; i++) {
if (device_infos.value[data[i].station_id] !== undefined) {
device_infos.value[data[i].station_id].push(data[i])
} else {
device_infos.value[data[i].station_id] = [data[i]]
}
}
})
.catch(err => {
console.log(err);
})
}
else {
for (let i = 0; i < data.length; i++) {
if (device_infos.value[data[i].station_id] !== undefined) {
device_infos.value[data[i].station_id].push(data[i])
} else {
device_infos.value[data[i].station_id] = [data[i]]
}
}
}
})
......
......@@ -129,7 +129,9 @@ onMounted(() => {
// // 将字节流转换为字符串或其他格式进行处理
// const message = byteArray.toString();
// items.value.push(JSON.stringify(e.data));
items.value.push(decodeURIComponent(e.data));
let message = decodeURIComponent(e.data)
// TODO 处理数据,看是否有是被检测的设备
items.value.push(message);
flag.value = !flag.value
};
......
import { defineStore } from 'pinia'
import { ref } from 'vue'
type ProtocolName = {
export type ProtocolName = {
label: string
value: string
}
......
......@@ -14,20 +14,22 @@
</template>
<script lang="ts" setup>
import axios from 'axios';
import { onMounted, ref } from 'vue'
import { useProtocolNamesStore } from '@/stores/protocolNames'
import { useProtocolNamesStore, ProtocolName } from '@/stores/protocolNames'
import CommunicationTab from "@/components/device_communication/CommunicationTab";
import request from "@/plugins/axios/requests"
// tab 相关
const activeName = ref<string>('simulate_device')
// 默认为设备界面
const activeName = ref<string>('device')
onMounted(() => {
axios.get('/api/device_communication/')
// 获取协议名
request.get<ProtocolName[]>('/api/device_communication/')
.then((res) => {
const store = useProtocolNamesStore()
store.protocolNames.push(...res.data)
store.protocolNames.push(...res.data!)
})
})
......
# -*- mode: python ; coding: utf-8 -*-
a = Analysis(
['manage.py'],
pathex=[],
binaries=[],
datas=[],
hiddenimports=[],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
noarchive=False,
)
pyz = PYZ(a.pure)
exe = EXE(
pyz,
a.scripts,
[],
exclude_binaries=True,
name='manage',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=False,
console=True,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
)
coll = COLLECT(
exe,
a.binaries,
a.datas,
strip=False,
upx=False,
upx_exclude=[],
name='manage',
)
......@@ -14,6 +14,7 @@ drf-yasg = "^1.21.7"
paho-mqtt = "^1.6.1"
protobuf = "3.20.1"
daphne = "^4.0.0"
channels-redis = "^4.1.0"
[build-system]
......
......@@ -32,10 +32,12 @@ ALLOWED_HOSTS = ['*']
INSTALLED_APPS = [
'daphne',
'chat',
# 'chat',
'device_data_op',
'protocol_version_manage',
'device_communication',
'mqtt',
'simulate_device_manager',
'django.contrib.admin',
'django.contrib.auth',
......@@ -157,17 +159,19 @@ MQTT_SUBSCRIBE_LIST = [('/1/0/0/6', 2),
('/1/1/0/6', 2),
('/1/1/1/6', 2)]
DEVICE_CONTAINER_NAME = 'hydev_111'
# channel 的 websocket 设置
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels.layers.InMemoryChannelLayer',
}
# "default": {
# "BACKEND": "channels_redis.core.RedisChannelLayer",
# "CONFIG": {
# "hosts": [("127.0.0.1", 6379)],
# },
# },
# 'default': {
# 'BACKEND': 'channels.layers.InMemoryChannelLayer',
# }
"default": {
"BACKEND": "channels_redis.core.RedisChannelLayer",
"CONFIG": {
"hosts": [("127.0.0.1", 6379)],
},
},
}
CORS_ALLOW_CREDENTIALS = True
......
......@@ -16,7 +16,7 @@ Including another URLconf
import os
from django.contrib import admin
from django.urls import path, include, re_path
from .views import index, test, upload, download
from .views import index, test, upload, download, restart_device
from django.conf import settings
from django.views.static import serve
......@@ -35,12 +35,13 @@ schema_view = get_schema_view(
urlpatterns = [
path('admin/', admin.site.urls),
path("test/upload/", upload),
path("test/download/", download),
# path("test/upload/", upload),
# path("test/download/", download),
path("api/restart_device/", restart_device),
path("api/mqtt/", include("mqtt.urls")),
path("chat/", include("chat.urls")),
# path("chat/", include("chat.urls")),
path("api/", include("device_data_op.urls")),
path("api/", include("download_db.urls")),
# path("api/", include("download_db.urls")),
path("api/", include("protocol_version_manage.urls")),
path("api/", include("device_communication.urls")),
path("api/", include("simulate_device_manager.urls")),
......
import os
import urllib.parse
import subprocess
from django.conf import settings
from django.http import FileResponse
......@@ -10,7 +11,6 @@ from rest_framework.parsers import MultiPartParser
from rest_framework import status
def index(request):
return render(request, 'index.html')
......@@ -57,3 +57,14 @@ def download(request):
return response
return Response(status=status.HTTP_200_OK)
@api_view(['POST'])
def restart_device(request):
try:
subprocess.Popen(f'sudo docker restart {settings.DEVICE_CONTAINER_NAME}', shell=True)
except Exception as e:
print(e)
return Response(status=status.HTTP_500_INTERNAL_SERVER_ERROR)
return Response(status=status.HTTP_200_OK)
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment