Commit 053d9b7c by qianmo

Merge remote-tracking branch 'origin/main'

parents 136548f2 18636750
# chat/consumers.py # chat/consumers.py
import urllib.parse
import json import json
from asgiref.sync import async_to_sync from asgiref.sync import async_to_sync
...@@ -74,8 +75,9 @@ class ChatConsumer(AsyncWebsocketConsumer): ...@@ -74,8 +75,9 @@ class ChatConsumer(AsyncWebsocketConsumer):
# Receive message from room group # Receive message from room group
async def chat_message(self, event): async def chat_message(self, event):
message = dict(event["message"]) # print(event['message'])
message = event["message"]
# print(message)
# Send message to WebSocket # Send message to WebSocket
await self.send(text_data=json.dumps({"message": [message]})) await self.send(text_data=json.dumps({"message": [message]}))
# await self.send(bytes_data=message) # await self.send(bytes_data=message)
......
<template> <template>
<div class="w-48% float-left border-solid border-black border-1"> <div class="w-48% float-left border-solid border-black border-1">
<el-scrollbar ref="scrollbarRef" style="height: 30rem;" class="mb-10" always> <el-scrollbar ref="scrollbarRef" style="height: 34rem;" class="mb-10" always>
<div ref="innerRef"> <div ref="innerRef">
<p v-for="item in items" :key="item" class="scrollbar-demo-item text-sm"> <p v-for="item in items" :key="item" class="scrollbar-demo-item text-sm">
<div>{{ JSON.parse(item)?.ts }}</div> <div>{{ JSON.parse(item)?.ts }}</div>
...@@ -10,28 +10,47 @@ ...@@ -10,28 +10,47 @@
</el-scrollbar> </el-scrollbar>
<div> <div>
<el-input style="width: 80%;" v-model="input" placeholder="Please input" @keyup.enter="send" /> <el-button class="ml-4" @click="showCmdDialog">Send Cmd</el-button>
<el-button class="ml-4" @click="send">Send</el-button>
</div> </div>
</div> </div>
<div class="w-50% float-right border-solid border-black border-1"> <div class="w-50% float-right border-solid border-black border-1">
<el-tabs v-model="activeName" class="px-5">
<el-tab-pane label="设备" name="device">
<el-scrollbar style="height: 30rem;" class="mb-10" always> <el-scrollbar style="height: 30rem;" class="mb-10" always>
<device-performance-table <device-performance-table
v-for="param in deviceTableParams" v-for="param in deviceTableParams"
mt-5 class="mt-5"
:dev-name="param.devName" :dev-name="param.devName"
:protocol-name="param.protocolName" :protocol-name="param.protocolName"
:group-name="param.key" :group-name="param.key"
:key="param.key" :key="param.key"
:type="activeName==='device'?'1': '2'"
@delete-table="deleteDeviceInfo(param)" /> @delete-table="deleteDeviceInfo(param)" />
</el-scrollbar> </el-scrollbar>
<el-button @click="dialogVisible = true">Add table</el-button> <el-button @click="dialogVisible = true">Add table</el-button>
</el-tab-pane>
<el-tab-pane label="虚拟设备" name="simulateDevice">
<el-scrollbar style="height: 30rem;" class="mb-10" always>
<device-performance-table
v-for="param in simulateDeviceTableParams"
class="mt-5"
:dev-name="param.devName"
:protocol-name="param.protocolName"
:group-name="param.key"
:key="param.key"
:type="activeName==='device'?'1': '2'"
@delete-table="deleteDeviceInfo(param)" />
</el-scrollbar>
<el-button @click="dialogVisible = true">Add table</el-button>
</el-tab-pane>
</el-tabs>
</div> </div>
<el-dialog class="w-150" v-model="dialogVisible" title="Select device"> <el-dialog class="w-150" v-model="dialogVisible" title="Select device">
<el-select class="w-100" v-model="selectedDeviceName"> <el-select class="w-100" v-model="selectedDeviceName">
<el-option v-for="deviceInfo in deviceInfos" :key="deviceInfo.dev_name" :label="deviceInfo.dev_name" :value="deviceInfo.dev_name" /> <el-option v-for="deviceInfo in deviceInfos" :key="deviceInfo.dev_name" :label="deviceInfo.dev_name"
:value="deviceInfo.dev_name" />
</el-select> </el-select>
<template #footer> <template #footer>
<span class="dialog-footer"> <span class="dialog-footer">
...@@ -42,39 +61,53 @@ ...@@ -42,39 +61,53 @@
</span> </span>
</template> </template>
</el-dialog> </el-dialog>
<el-dialog v-model="dialogCmdVisible" class="w-150" title="Send Cmd">
<el-form :model="formData" label-width="120px">
<el-form-item label="设备名称">
<el-select v-model="formData.deviceName" w-100 @change="showCmds">
<el-option
v-for="deviceName in deviceNamesOptions"
:label="deviceName.label"
:value="deviceName.value" />
</el-select>
</el-form-item>
<el-form-item label="命令">
<el-select v-model="formData.cmdName" w-100 @change="showFields">
<el-option
v-for="cmdName in cmdNamesOptions"
:label="cmdName.label"
:value="cmdName.value" />
</el-select>
</el-form-item>
<el-form-item v-for="field in formData.fields" :label="field.fieldname">
<el-input v-model="field.value" />
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogCmdVisible = false">Cancel</el-button>
<el-button type="primary" @click="sendCmd">
Confirm
</el-button>
</span>
</template>
</el-dialog>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted, watch, onBeforeUnmount } from 'vue'; import { ref, onMounted, watch, onBeforeUnmount, reactive } from 'vue';
import { ElScrollbar, ElInput, ElButton, ElSelect, ElOption, ElMessage } from 'element-plus'; import { ElScrollbar, ElButton, ElSelect, ElOption, ElMessage } from 'element-plus';
import DevicePerformanceTable from '@/components/home/DevicePerformanceTabel' import DevicePerformanceTable from '@/components/home/DevicePerformanceTabel'
import axios from 'axios'; import axios from 'axios';
const innerRef = ref<HTMLDivElement>(); const innerRef = ref<HTMLDivElement>();
const scrollbarRef = ref<InstanceType<typeof ElScrollbar>>(); const scrollbarRef = ref<InstanceType<typeof ElScrollbar>>();
const input = ref(''); const items = ref<string[]>([]);
const items = ref<string[]>([
JSON.stringify([{ "CMDS": "$,", "Xaxis": "034.00", "Comma": ",", "Yaxis": "034.00", "Azimuth": "000.00", "ElevationAngle": "090.00", "ACUstatus": "P", "XTrackerSigIntensity": "255", "YTrackerSigIntensity": "255", "X_STATUS": "244", "Y_STATUS": "245", "XInitPhase": "012", "XPolarizationType": "1", "SPolarizationType": "0", "XTrackerVoltageLimit": "255", "STrackerVoltageLimit": "255", "SUpPolarizationType": "1", "XUpPolarizationType": "1", "TrackingStatus": "0", "TrackingBand": "1", "X-Bias": "+0.00", "Y-Bias": "+0.00", "END": "\r\n", "XaxisAlarm": "0", "XaxisServoStatus": "1", "EasternLimit": "0", "WestLimit": "0", "YaxisAlarm": "0", "YaxisServoStatus": "1", "SouthrLimit": "0", "NorthLimit": "1" }]),
JSON.stringify([{ "CMDS": "$,", "Xaxis": "034.00", "Comma": ",", "Yaxis": "034.00", "Azimuth": "000.00", "ElevationAngle": "090.00", "ACUstatus": "P", "XTrackerSigIntensity": "255", "YTrackerSigIntensity": "255", "X_STATUS": "244", "Y_STATUS": "245", "XInitPhase": "012", "XPolarizationType": "1", "SPolarizationType": "0", "XTrackerVoltageLimit": "255", "STrackerVoltageLimit": "255", "SUpPolarizationType": "1", "XUpPolarizationType": "1", "TrackingStatus": "0", "TrackingBand": "1", "X-Bias": "+0.00", "Y-Bias": "+0.00", "END": "\r\n", "XaxisAlarm": "0", "XaxisServoStatus": "1", "EasternLimit": "0", "WestLimit": "0", "YaxisAlarm": "0", "YaxisServoStatus": "1", "SouthrLimit": "0", "NorthLimit": "1" }]),
JSON.stringify([{ "CMDS": "$,", "Xaxis": "034.00", "Comma": ",", "Yaxis": "034.00", "Azimuth": "000.00", "ElevationAngle": "090.00", "ACUstatus": "P", "XTrackerSigIntensity": "255", "YTrackerSigIntensity": "255", "X_STATUS": "244", "Y_STATUS": "245", "XInitPhase": "012", "XPolarizationType": "1", "SPolarizationType": "0", "XTrackerVoltageLimit": "255", "STrackerVoltageLimit": "255", "SUpPolarizationType": "1", "XUpPolarizationType": "1", "TrackingStatus": "0", "TrackingBand": "1", "X-Bias": "+0.00", "Y-Bias": "+0.00", "END": "\r\n", "XaxisAlarm": "0", "XaxisServoStatus": "1", "EasternLimit": "0", "WestLimit": "0", "YaxisAlarm": "0", "YaxisServoStatus": "1", "SouthrLimit": "0", "NorthLimit": "1" }]),
JSON.stringify([{ "CMDS": "$,", "Xaxis": "034.00", "Comma": ",", "Yaxis": "034.00", "Azimuth": "000.00", "ElevationAngle": "090.00", "ACUstatus": "P", "XTrackerSigIntensity": "255", "YTrackerSigIntensity": "255", "X_STATUS": "244", "Y_STATUS": "245", "XInitPhase": "012", "XPolarizationType": "1", "SPolarizationType": "0", "XTrackerVoltageLimit": "255", "STrackerVoltageLimit": "255", "SUpPolarizationType": "1", "XUpPolarizationType": "1", "TrackingStatus": "0", "TrackingBand": "1", "X-Bias": "+0.00", "Y-Bias": "+0.00", "END": "\r\n", "XaxisAlarm": "0", "XaxisServoStatus": "1", "EasternLimit": "0", "WestLimit": "0", "YaxisAlarm": "0", "YaxisServoStatus": "1", "SouthrLimit": "0", "NorthLimit": "1" }]),
JSON.stringify([{ "CMDS": "$,", "Xaxis": "034.00", "Comma": ",", "Yaxis": "034.00", "Azimuth": "000.00", "ElevationAngle": "090.00", "ACUstatus": "P", "XTrackerSigIntensity": "255", "YTrackerSigIntensity": "255", "X_STATUS": "244", "Y_STATUS": "245", "XInitPhase": "012", "XPolarizationType": "1", "SPolarizationType": "0", "XTrackerVoltageLimit": "255", "STrackerVoltageLimit": "255", "SUpPolarizationType": "1", "XUpPolarizationType": "1", "TrackingStatus": "0", "TrackingBand": "1", "X-Bias": "+0.00", "Y-Bias": "+0.00", "END": "\r\n", "XaxisAlarm": "0", "XaxisServoStatus": "1", "EasternLimit": "0", "WestLimit": "0", "YaxisAlarm": "0", "YaxisServoStatus": "1", "SouthrLimit": "0", "NorthLimit": "1" }]),
]);
const flag = ref<boolean>(false); const flag = ref<boolean>(false);
let chatSocket: WebSocket | null = null; let chatSocket: WebSocket | null = null;
const send = () => {
if (chatSocket === null) {
console.error('chatSocket is null');
return;
}
chatSocket.send(JSON.stringify({
'message': input.value
}));
input.value = '';
}
watch(flag, () => { watch(flag, () => {
setTimeout(() => { setTimeout(() => {
scrollbarRef.value!.setScrollTop(innerRef.value!.offsetHeight); scrollbarRef.value!.setScrollTop(innerRef.value!.offsetHeight);
...@@ -96,14 +129,10 @@ onMounted(() => { ...@@ -96,14 +129,10 @@ onMounted(() => {
// // 将字节流转换为字符串或其他格式进行处理 // // 将字节流转换为字符串或其他格式进行处理
// const message = byteArray.toString(); // const message = byteArray.toString();
// items.value.push(JSON.stringify(e.data)); // items.value.push(JSON.stringify(e.data));
items.value.push(e.data); items.value.push(decodeURIComponent(e.data));
flag.value = !flag.value flag.value = !flag.value
}; };
chatSocket.onclose = (e) => {
console.error('Chat socket closed unexpectedly', e);
};
axios.get('/api/xpro_all_devinfo/') axios.get('/api/xpro_all_devinfo/')
.then((res) => { .then((res) => {
deviceInfos.value = res.data deviceInfos.value = res.data
...@@ -126,7 +155,13 @@ type MonitorType = { ...@@ -126,7 +155,13 @@ type MonitorType = {
protocolName: string protocolName: string
devName: string devName: string
} }
// tab
// 维护两个列表,通过判断当前在哪个标签页就对谁添加
// 删除同理
const activeName = ref<string>('device')
const deviceTableParams = ref<MonitorType[]>([]); const deviceTableParams = ref<MonitorType[]>([]);
const simulateDeviceTableParams = ref<MonitorType[]>([]);
const addDeviceTable = () => { const addDeviceTable = () => {
if (deviceInfos.value.length === 0) { if (deviceInfos.value.length === 0) {
ElMessage.warning('input invalid'); ElMessage.warning('input invalid');
...@@ -136,6 +171,7 @@ const addDeviceTable = () => { ...@@ -136,6 +171,7 @@ const addDeviceTable = () => {
for (let deviceInfo of deviceInfos.value) { for (let deviceInfo of deviceInfos.value) {
if (deviceInfo.dev_name === selectedDeviceName.value) { if (deviceInfo.dev_name === selectedDeviceName.value) {
if ((deviceInfo.comunitate_mode as string).toUpperCase().includes('TCP')) { if ((deviceInfo.comunitate_mode as string).toUpperCase().includes('TCP')) {
if (activeName.value === 'device') {
deviceTableParams.value.push({ deviceTableParams.value.push({
key: (deviceInfo.tcp_port).toString(), key: (deviceInfo.tcp_port).toString(),
protocolName: deviceInfo.protocol_name, protocolName: deviceInfo.protocol_name,
...@@ -143,12 +179,29 @@ const addDeviceTable = () => { ...@@ -143,12 +179,29 @@ const addDeviceTable = () => {
}); });
} }
else { else {
simulateDeviceTableParams.value.push({
key: (deviceInfo.tcp_port).toString(),
protocolName: deviceInfo.protocol_name,
devName: deviceInfo.dev_name
})
}
}
else {
if (activeName.value === 'device') {
deviceTableParams.value.push({ deviceTableParams.value.push({
key: (deviceInfo.udp_port_src).toString(), key: (deviceInfo.udp_port_src).toString(),
protocolName: deviceInfo.protocol_name, protocolName: deviceInfo.protocol_name,
devName: deviceInfo.dev_name devName: deviceInfo.dev_name
}); });
} }
else {
simulateDeviceTableParams.value.push({
key: (deviceInfo.udp_port_src).toString(),
protocolName: deviceInfo.protocol_name,
devName: deviceInfo.dev_name
})
}
}
} }
} }
...@@ -157,7 +210,110 @@ const addDeviceTable = () => { ...@@ -157,7 +210,110 @@ const addDeviceTable = () => {
} }
const deleteDeviceInfo = (param: MonitorType) => { const deleteDeviceInfo = (param: MonitorType) => {
if (activeName.value === 'device') {
deviceTableParams.value.splice(deviceTableParams.value.indexOf(param), 1); deviceTableParams.value.splice(deviceTableParams.value.indexOf(param), 1);
}
else {
simulateDeviceTableParams.value.splice(simulateDeviceTableParams.value.indexOf(param), 1);
}
}
// send Cmd
type FieldDataType = {
fieldname: string
value: string
}
type FromDataType = {
deviceName: string
cmdName: string
fields: FieldDataType[]
}
const formData = reactive<FromDataType>({
deviceName: '',
cmdName: '',
fields: []
})
const dialogCmdVisible = ref<boolean>(false);
type OptionType = {
label: string
value: string
}
const deviceNamesOptions = ref<OptionType[]>([])
const deviceNameMap = new Map<string, any>()
const showCmdDialog = () => {
dialogCmdVisible.value = true
for (let deviceInfo of deviceInfos.value) {
deviceNamesOptions.value.push({
label: deviceInfo.dev_name,
value: deviceInfo.dev_name
})
}
// 如果 map 中没有内容的话,将信息存到一个 map 中方便查找
if (deviceNameMap.size === 0) {
for (let deviceInfo of deviceInfos.value) {
deviceNameMap.set(deviceInfo.dev_name, deviceInfo)
}
}
}
const cmdNamesOptions = ref<OptionType[]>([])
const showCmds = () => {
cmdNamesOptions.value.splice(0, cmdNamesOptions.value.length);
axios.get('/api/mqtt/protocol/' + deviceNameMap.get(formData.deviceName).protocol_name + '/')
.then((res) => {
for (let item of res.data) {
cmdNamesOptions.value.push({
label: item,
value: item
})
}
})
.catch((err) => {
console.log(err);
})
}
const filterFields = ["CMDS", "END", "Comma"]
const showFields = () => {
axios.get('/api/mqtt/cmd/' + formData.cmdName + '/')
.then((res) => {
formData.fields = res.data.filter((item: FieldDataType) =>
!filterFields.includes(item.fieldname)
)
})
.catch((err) => {
console.log(err);
})
}
const sendCmd = () => {
dialogCmdVisible.value = false
// 发送命令
const obj = deviceNameMap.get(formData.deviceName)
axios.post('/api/mqtt/publish/',
{
station_id: obj.sta_id,
device_id: obj.dev_id,
cmd_name: formData.cmdName,
fields: formData.fields
})
.catch((err) => {
console.log(err);
})
// 展示到聊天框
let cmdText = `设备 ${formData.deviceName} 发送命令 ${formData.cmdName}`
if (chatSocket === null) {
console.error('chatSocket is null');
return;
}
chatSocket.send(JSON.stringify({
'message': cmdText
}));
} }
</script> </script>
......
...@@ -24,6 +24,7 @@ type propsType = { ...@@ -24,6 +24,7 @@ type propsType = {
devName: string devName: string
groupName: string groupName: string
protocolName: string protocolName: string
type: string
} }
const props = defineProps<propsType>() const props = defineProps<propsType>()
...@@ -42,19 +43,13 @@ onMounted(() => { ...@@ -42,19 +43,13 @@ onMounted(() => {
// console.log(e.data); // console.log(e.data);
let data = JSON.parse(e.data).message let data = JSON.parse(e.data).message
for (const [key, value] of Object.entries(data[0] as Record<string, string>)) { for (const [key, value] of Object.entries(data[0] as Record<string, string>)) {
console.log(key, value);
if (tableTitles.value.indexOf(key) !== -1) { if (tableTitles.value.indexOf(key) !== -1) {
tableData.value[0][key] = value tableData.value[0][key] = value
} }
} }
} }
table_websocket.onclose = (e) => { axios.get('/api/device_communication/performance/' + props.type + '/' + props.protocolName)
console.error('Table socket closed unexpectedly', e);
}
axios.get('/api/device_communication/performance/1/' + props.protocolName)
.then((res) => { .then((res) => {
tableTitles.value = res.data tableTitles.value = res.data
for (let key of res.data) { for (let key of res.data) {
......
...@@ -23,6 +23,8 @@ def on_message(mqtt_client, userdata, msg): ...@@ -23,6 +23,8 @@ def on_message(mqtt_client, userdata, msg):
data, device_name = parse_proto(msg.payload) data, device_name = parse_proto(msg.payload)
# data = msg.payload.decode('utf-8') # data = msg.payload.decode('utf-8')
print(f'Received message on topic: {msg.topic} with payload: {data}') print(f'Received message on topic: {msg.topic} with payload: {data}')
if len(data) == 0:
return
send_message(data, device_name) send_message(data, device_name)
...@@ -38,6 +40,8 @@ def send_message(data: dict, device_name: str): ...@@ -38,6 +40,8 @@ def send_message(data: dict, device_name: str):
name = dev_info.tcp_port name = dev_info.tcp_port
elif "UDP" in dev_info.comunitate_mode.upper(): elif "UDP" in dev_info.comunitate_mode.upper():
name = dev_info.udp_port_src name = dev_info.udp_port_src
else:
return
send_websocket_message(data, group_name=f'chat_{name}') send_websocket_message(data, group_name=f'chat_{name}')
# cmds = data.get('CMDS') # cmds = data.get('CMDS')
......
...@@ -32,7 +32,7 @@ def cmd_fields_list(request, cmd_name: str): ...@@ -32,7 +32,7 @@ def cmd_fields_list(request, cmd_name: str):
cmd_fields = TableAllDevCmdDefine.objects.filter(cmd_name=cmd_name).all() cmd_fields = TableAllDevCmdDefine.objects.filter(cmd_name=cmd_name).all()
serializer = TableAllDevCmdDefineSerializer(cmd_fields, many=True) serializer = TableAllDevCmdDefineSerializer(cmd_fields, many=True)
ret_data = [data['fieldname'] for data in serializer.data] ret_data = [{'fieldname': data['fieldname'], 'value': data['value']} for data in serializer.data]
return Response(data=ret_data, status=status.HTTP_200_OK) return Response(data=ret_data, status=status.HTTP_200_OK)
...@@ -43,7 +43,6 @@ def publish_message(request): ...@@ -43,7 +43,6 @@ def publish_message(request):
:param request: :param request:
{ {
"type": "device",
"station_id": "XX1", "station_id": "XX1",
"device_id": 1, "device_id": 1,
"cmd_name": "HY_ACU7M5_PositionSet", "cmd_name": "HY_ACU7M5_PositionSet",
...@@ -63,6 +62,9 @@ def publish_message(request): ...@@ -63,6 +62,9 @@ def publish_message(request):
if request.data['station_id'] == "XX1": if request.data['station_id'] == "XX1":
topic = "/1/1/1/3" topic = "/1/1/1/3"
dst_suid = 0x1113_0000 dst_suid = 0x1113_0000
elif request.data['station_id'] == "XX2":
topic = "/1/1/2/3"
dst_suid = 0x1103_0000
elif request.data['station_id'] == "XX0": elif request.data['station_id'] == "XX0":
topic = "/1/1/0/3" topic = "/1/1/0/3"
dst_suid = 0x1103_0000 dst_suid = 0x1103_0000
......
...@@ -37,7 +37,7 @@ urlpatterns = [ ...@@ -37,7 +37,7 @@ urlpatterns = [
path("", index), path("", index),
path("test/upload/", upload), path("test/upload/", upload),
path("test/download/", download), path("test/download/", download),
path("mqtt/", include("mqtt.urls")), 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("device_data_op.urls")),
path("api/", include("download_db.urls")), path("api/", include("download_db.urls")),
......
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