Commit 462b2eed by 周田

feat:控制模拟设备(初版,未完成

parent 6aa86105
......@@ -5,6 +5,13 @@
<p>{{ props.devName }}</p>
</div>
<div class="float-right">
<el-switch
v-if="props.type === '2'"
v-model="openSimulateDevice"
@change="changeSimulateDevice"
class="mr-4"
style="--el-switch-on-color: #13ce66; --el-switch-off-color: #ff4949"
/>
<el-button type="danger" size="small" class="mr-4" @click="del" :icon="Delete" circle />
</div>
</div>
......@@ -18,6 +25,7 @@
<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount } from 'vue'
import { Delete } from '@element-plus/icons-vue'
import request from '@/plugins/axios/requests';
import axios from 'axios';
type propsType = {
......@@ -72,4 +80,21 @@ onBeforeUnmount(() => {
table_websocket?.close()
})
const openSimulateDevice = ref<boolean>(false)
const changeSimulateDevice = () => {
let body = {
protocol_name: props.protocolName,
status: openSimulateDevice.value,
device_name: props.devName
}
console.log(body);
request.post('/api/change_simulate_device/', body)
.then((res) => {
console.log(res);
})
.catch((err) => {
console.log(err);
})
}
</script>
from django.contrib import admin
# Register your models here.
from django.apps import AppConfig
class ManageSimulateDeviceConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'simulate_device_manager'
import os
import subprocess
import signal
from subprocess import CompletedProcess
from django.dispatch import Signal, receiver
# 用于存储模拟设备的进程
# str: device_name -> CompletedProcess
SIMULATE_DEVICE_PROCESS: dict[str, CompletedProcess] = {}
start_signal = Signal(providing_args=['protocol_name', 'device_name', 'port'])
stop_signal = Signal(providing_args=['device_name'])
@receiver(start_signal)
def start_signal_callback(sender, **kwargs):
"""
处理启动模拟设备的信号
"""
protocol_name = kwargs.get('protocol_name')
device_name = kwargs.get('device_name')
device_port = kwargs.get('port')
assert protocol_name is not None, 'protocol_name is None'
assert device_name is not None, 'device_name is None'
assert device_port is not None, 'device_port is None'
process = subprocess.Popen(['python',
f'./simulate_device_manager/simulate_devices/{protocol_name}.py',
f'{device_port}'])
SIMULATE_DEVICE_PROCESS[device_name] = process
@receiver(stop_signal)
def stop_signal_callback(sender, **kwargs):
"""
处理关闭模拟设备的信号
"""
device_name = kwargs.get('device_name')
assert device_name is not None, 'device_name is None'
process = SIMULATE_DEVICE_PROCESS.get(device_name)
process.terminate()
process.wait()
os.kill(process.pid, signal.SIGTERM)
del SIMULATE_DEVICE_PROCESS[device_name]
from pickletools import pyinteger_or_bool
import socket
import sys
import time
import re
import threading
import datetime
import sys
import configparser
import signal
# 定义回调函数
def myHandler(signum, frame):
print("接收信号为:", signum)
exit(0)
# 等待接收 signal.SIGTERM命令
signal.signal(signal.SIGTERM, myHandler)
argv = sys.argv[1:]
tcp_port = int(argv[0])
map_work_status_lock = threading.Lock() # 锁的声明
"""字典 数据存放的map 使用锁进行读写访问"""
map_work_status = {"Pow1": "ON",
"Pow2": "ON",
"Pow3": "ON",
"Pow4": "ON",
"Pow5": "ON",
"Pow6": "ON",
"Pow7": "ON",
"Pow8": "ON",
"Pow9": "ON",
"Pow10": "ON",
"Pow11": "ON",
"Pow12": "ON",
"Pow13": "ON",
"Pow14": "ON",
"Pow15": "ON",
"Pow16": "ON"
}
"""字段中文名"""
map_name_chg = {"Pow1": "电源输出端口1",
"Pow2": "电源输出端口2",
"Pow3": "电源输出端口3",
"Pow4": "电源输出端口4",
"Pow5": "电源输出端口5",
"Pow6": "电源输出端口6",
"Pow7": "电源输出端口7",
"Pow8": "电源输出端口8",
"Pow9": "电源输出端口9",
"Pow10": "电源输出端口10",
"Pow11": "电源输出端口11",
"Pow12": "电源输出端口12",
"Pow13": "电源输出端口13",
"Pow14": "电源输出端口14",
"Pow15": "电源输出端口15",
"Pow16": "电源输出端口16"
}
packet_head = \
"************************************************************\r\n\
* *\r\n\
* *\r\n\
* Power Outlet Port Parameters and Status *\r\n\
* *\r\n\
* *\r\n\
************************************************************\r\n\
>\r\n\
>\r\n\
\r\n\
Port | Name | status | Reserved By | Timer | AutoPing \r\n\
-----+------------+--------+-------------+-----------|---------\r\n\
"
tem_packet_str=""
def packet_string(tem_packet_str):
packet_info=""
status_str=""
for num in range(1,17):
key = "Pow"+str(num)
if(num<10):
str1=" "+ str(num).zfill(2)+" | Outlet "+str(num)+" |"
else:
str1=" "+ str(num).zfill(2)+" | Outlet "+str(num).zfill(2)+" |"
if(map_work_status[key] == "ON"):
status_str=" "+map_work_status[key] +" "
else:
status_str=" "+map_work_status[key] +" "
str3="| Open | OFF | OFF\r\n"
packet_info=packet_info+str1+status_str+str3
tem_packet_str=packet_head +packet_info+"\r\n> "
# print("11111111111122222222222222222: ",tem_packet_str)
return tem_packet_str
tem_packet_str = packet_string(tem_packet_str)
print("初始化数据:\r\n" + tem_packet_str)
tcpServer_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 1创建socket对象
tcpServer_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
tcpServer_socket.bind(('0.0.0.0', tcp_port)) # 2,需要自己绑定一个ip地址和端口号
tcpServer_socket.listen(1) # 可以同时监听3个,但是这里只有一个因为没有写多线程
client_socket, addr = tcpServer_socket.accept() # 阻塞 是服务端的socket对象clientServer_socket是接入的客户端socket对象
TCP_LINK_STATUS = 1 # TCP 连接标志位
""" 状态查询指令 回调函数 """
def HY_NP16EHPDU_PShow_CallBack(recv_cmd):
print("NP16EHPDU_PShow_CallBack")
map_work_status_lock.acquire() # 上锁
tem_packet_str=""
tem_packet_str = packet_string(tem_packet_str)
if (TCP_LINK_STATUS != 0):
# client_socket.send("".encode("utf-8"))
print("send")
client_socket.send(tem_packet_str.encode("utf-8"))
map_work_status_lock.release() # 解锁
""" 控制开关指令 回调函数"""
def HY_NP16EHPDU_SetOutPort_CallBack(recv_cmd):
print(recv_cmd)
if(len(recv_cmd)==10):
key = "Pow"+recv_cmd[5]
value = recv_cmd[7]
else:
key = "Pow"+recv_cmd[5:7]
value = recv_cmd[8]
print("key = ",key," value = ",value)
map_work_status_lock.acquire() # 上锁
if (int(value) == 1):
map_work_status[key] = "ON"
elif (int(value) == 0):
map_work_status[key] = "OFF"
map_work_status_lock.release() # 解锁
map_calBackFun = {"pset": HY_NP16EHPDU_SetOutPort_CallBack,
"pshow":HY_NP16EHPDU_PShow_CallBack
}
"""定时读取 map_work_status 发布设备状态报文 间隔200ms"""
def SendStatusHandle():
print("线程1")
global client_socket
cont = 0
cont_print = 0
max_cont = 10000
while max_cont:
map_work_status_lock.acquire()
# tem_packet_str =""
# tem_packet_str = packet_string(tem_packet_str)
# if (TCP_LINK_STATUS != 0):
# max_cont = max_cont - 1
# client_socket.send(tem_packet_str.encode("utf-8"))
tem_status_str=""
for num in range(1,17):
key = "Pow"+str(num)
tem_status_str =tem_status_str+map_name_chg[key]+" : "+map_work_status[key]+"\r\n"
map_work_status_lock.release()
cont = cont + 1
if (cont > 2 and TCP_LINK_STATUS):
cont_print = cont_print + 1
print("=============== 打印当前模拟设备状态 ================= ", cont_print)
print(tem_status_str)
cont = 0
time.sleep(1)
""" 一个模拟接收端,收到设置类型的指令后,修改 map_work_status。"""
def RecvSetCMDHandle():
print("线程2")
global TCP_LINK_STATUS
global client_socket
while 1:
data = client_socket.recv(1024)
rec_str = data.decode()
cmd=""
if (len(data) > 0):
if(len(data)==7):
cmd = rec_str[0:5]
print("1111111",cmd)#查询指令
elif(len(data)==10 or len(data)==11):
cmd = rec_str[0:4]
print("1111111",cmd)#设置指令
if (cmd in map_calBackFun):
map_calBackFun[cmd](rec_str)
# SendMessage(rec_str)
else:
print("收到未知报文 : " + rec_str)
else:
TCP_LINK_STATUS = 0
print("连接断开,等待接入")
client_socket.close()
client_socket, addr = tcpServer_socket.accept() # s是服务端的socket对象clientServer_socket是接入的客户端socket对象
TCP_LINK_STATUS = 1
print(addr)
cont = 0
time.sleep(1)
def SendMessage(recv_cmd):
global client_socket
send_str = ""
map_work_status_lock.acquire()
if recv_cmd[0] == "C":
send_str = "<" + recv_cmd
elif recv_cmd[0] == "B":
send_str = "<" + recv_cmd
elif recv_cmd[0] == "?":
send_str = "<CF_" + map_work_status["InputFrequency"] + ",BD_" + map_banwith_status[map_work_status["Bandwidth"]] + "\r\n"
client_socket.send(send_str.encode("utf-8"))
map_work_status_lock.release()
if __name__ == '__main__':
tr1 = threading.Thread(target=SendStatusHandle)
tr2 = threading.Thread(target=RecvSetCMDHandle)
tr1.start()
tr2.start()
"""数据格式:
CF_xxxx.xxx\r\n
解释:
xxxx.xxx:输入频率,范围:2200.000~3000.000,单位:MHz;
BD_x\r\n
解释:
x:带宽,范围:1,2,3 1:50KHz 2:1MHz 3:2MHz 默认 1
"""
from pickletools import pyinteger_or_bool
import socket
import sys
import time
import re
import threading
import datetime
import sys
import configparser
import signal
# 定义回调函数
def myHandler(signum, frame):
print("接收信号为:", signum)
exit(0)
# 等待接收 signal.SIGTERM命令
signal.signal(signal.SIGTERM, myHandler)
argv = sys.argv[1:]
tcp_port = int(argv[0])
map_work_status_lock = threading.Lock() # 锁的声明
"""字典 数据存放的map 使用锁进行读写访问"""
map_work_status = {"InputFrequency": "2200.000", "Bandwidth": "50KHz"}
"""字段中文名"""
map_name_chg = {"InputFrequency": "输入频率", "Bandwidth": "带宽"}
map_banwith_status = {"50KHz":"1","1MHz":"2","2MHz":"3"}
tem_packet_str = map_name_chg["InputFrequency"]+":"+map_work_status["InputFrequency"]+" "+map_name_chg["Bandwidth"]+":"+map_work_status["Bandwidth"]
print("初始化数据:" + tem_packet_str)
# config = configparser.ConfigParser() # 类实例化
# 定义ini文件路径 这个文件用于存放 跟踪接收机当前的报警状态
# path = r'trackingReceiver.ini'
tcpServer_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 1创建socket对象
tcpServer_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
tcpServer_socket.bind(('0.0.0.0', tcp_port)) # 2,需要自己绑定一个ip地址和端口号
tcpServer_socket.listen(1) # 可以同时监听3个,但是这里只有一个因为没有写多线程
client_socket, addr = tcpServer_socket.accept() # 阻塞 是服务端的socket对象clientServer_socket是接入的客户端socket对象
TCP_LINK_STATUS = 1 # TCP 连接标志位
""" 处理输入频率指令 回调函数"""
def HY_TrackingReceiver_SetInputFrequency_CallBack(recv_cmd):
InputFrequency = recv_cmd[3:11]
print("HY_TrackingReceiver_SetInputFrequency_CallBack InputFrequency = ",InputFrequency)
map_work_status_lock.acquire() # 上锁
map_work_status["InputFrequency"] = InputFrequency
map_work_status_lock.release() # 解锁
""" 处理带宽指令 回调函数"""
def HY_TrackingReceiver_Bandwidth_CallBack(recv_cmd):
Bandwith = recv_cmd[3]
print("HY_TrackingReceiver_Bandwidth_CallBack Bandwith = ",Bandwith)
map_work_status_lock.acquire() # 上锁
if int(Bandwith) == 1:
map_work_status["Bandwidth"] = "50KHz"
elif int(Bandwith) == 2:
map_work_status["Bandwidth"] = "1MHz"
elif int(Bandwith) == 3:
map_work_status["Bandwidth"] = "2MHz"
else:
map_work_status["Bandwidth"] = "50KHz"
map_work_status_lock.release() # 解锁
""" 处理查询状态指令 回调函数"""
def HY_TrackingReceiver_QueryState_CallBack(recv_cmd):
map_work_status_lock.acquire() # 上锁
# print("2222222222222",recv_cmd)
#map_work_status = map_work_status
tem_packet_str = "CF_" + map_work_status["InputFrequency"] + ", BD_" + map_banwith_status[map_work_status["Bandwidth"]]+ " \r\n"
# tem_status_str = map_name_chg["InputFrequency"]+":"+map_work_status["InputFrequency"]+"\r\n"+map_name_chg["Bandwidth"]+":"+map_work_status["Bandwidth"]+"\r\n"
if (TCP_LINK_STATUS != 0):
client_socket.send(tem_packet_str.encode("utf-8"))
map_work_status_lock.release() # 解锁
map_calBackFun = {"C": HY_TrackingReceiver_SetInputFrequency_CallBack,
"B": HY_TrackingReceiver_Bandwidth_CallBack,
"?": HY_TrackingReceiver_QueryState_CallBack}
"""定时读取 map_work_status 发布设备状态报文 间隔200ms"""
def SendStatusHandle():
print("线程1")
global client_socket
cont = 0
cont_print = 0
max_cont = 10000
while max_cont:
map_work_status_lock.acquire()
# tem_packet_str = "<CF_" + map_work_status["InputFrequency"] + ",BD_" + map_banwith_status[map_work_status["Bandwidth"]]+ "\r\n"
tem_status_str = map_name_chg["InputFrequency"]+":"+map_work_status["InputFrequency"]+"\r\n"+map_name_chg["Bandwidth"]+":"+map_work_status["Bandwidth"]+"\r\n"
# if (TCP_LINK_STATUS != 0):
# max_cont = max_cont - 1
# client_socket.send(tem_packet_str.encode("utf-8"))
map_work_status_lock.release()
cont = cont + 1
if (cont > 2 and TCP_LINK_STATUS):
cont_print = cont_print + 1
print("=============== 打印当前模拟设备状态 ================= ", cont_print)
print(tem_status_str)
cont = 0
time.sleep(1)
""" 一个模拟接收端,收到设置类型的指令后,修改map_work_status。"""
def RecvSetCMDHandle():
print("线程2")
global TCP_LINK_STATUS
global client_socket
while 1:
data = client_socket.recv(1024)
rec_str = data.decode()
if (len(data) > 0):
cmd = rec_str[0]
# print("1111111",cmd)
# print("2222222",rec_str)
if (cmd in map_calBackFun):
map_calBackFun[cmd](rec_str)
# SendMessage(rec_str)
else:
print("收到未知报文 : " + rec_str)
else:
TCP_LINK_STATUS = 0
print("连接断开,等待接入")
client_socket.close()
client_socket, addr = tcpServer_socket.accept() # s是服务端的socket对象clientServer_socket是接入的客户端socket对象
TCP_LINK_STATUS = 1
print(addr)
cont = 0
time.sleep(1)
def SendMessage(recv_cmd):
global client_socket
send_str = ""
map_work_status_lock.acquire()
if recv_cmd[0] == "C":
send_str = "<" + recv_cmd
elif recv_cmd[0] == "B":
send_str = "<" + recv_cmd
elif recv_cmd[0] == "?":
send_str = "<CF_" + map_work_status["InputFrequency"] + ",BD_" + map_banwith_status[map_work_status["Bandwidth"]] + "\r\n"
client_socket.send(send_str.encode("utf-8"))
map_work_status_lock.release()
if __name__ == '__main__':
tr1 = threading.Thread(target=SendStatusHandle)
tr2 = threading.Thread(target=RecvSetCMDHandle)
tr1.start()
tr2.start()
"""数据格式:
CF_xxxx.xxx\r\n
解释:
xxxx.xxx:输入频率,范围:2200.000~3000.000,单位:MHz;
BD_x\r\n
解释:
x:带宽,范围:1,2,3 1:50KHz 2:1MHz 3:2MHz 默认 1
"""
; XaxisAlarm X轴报警 Boolean 1 X轴报警;0 正常;
; XaxisServoStatus X轴伺服状态 Boolean 1 X轴伺服打开;0 X轴伺服关闭;
; EasternLimit 东限位 Boolean 1 东限位;0 正常;
; WestLimit 西限位 Boolean 1 西限位;0 正常;
; YaxisAlarm Y轴报警 Boolean 1 Y轴报警;0 正常;
; YaxisServoStatus Y轴伺服 Boolean 1 Y轴伺服打开;0 Y轴伺服关闭;
; SouthrLimit 南限位 Boolean 1 限位;0 正常;
; NorthLimit 北限位 Boolean 1 限位;0 正常;
[alarm_status]
XaxisAlarm = 0
XaxisServoStatus = 1
EasternLimit = 0
WestLimit = 0
YaxisAlarm = 0
YaxisServoStatus= 1
SouthrLimit = 0
NorthLimit = 1
from django.urls import re_path
from .views import change_simulate_device_status
urlpatterns = [
re_path(r'^change_simulate_device/$', change_simulate_device_status)
]
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
from device_data_op.models import TableXproAllDevinfo
from drf_yasg.utils import swagger_auto_schema
from drf_yasg import openapi
from .device_manager import SIMULATE_DEVICE_PROCESS, start_signal, stop_signal
@swagger_auto_schema(method='post', request_body=openapi.Schema(
type=openapi.TYPE_OBJECT,
properties={
'status': openapi.Schema(type=openapi.TYPE_BOOLEAN),
'protocol_name': openapi.Schema(type=openapi.TYPE_STRING),
'device_name': openapi.Schema(type=openapi.TYPE_STRING)
}
), responses={200: 'OK', 400: 'Bad Request', 500: 'Internal Server Error'})
@api_view(['POST'])
def change_simulate_device_status(request):
"""
通过 subprocess 模块来启动或者关闭模拟设备
"""
device_status = request.data.get('status')
protocol_name = request.data.get('protocol_name')
device_name = request.data.get('device_name')
if device_status is None or protocol_name is None or device_name is None:
return Response(status=status.HTTP_400_BAD_REQUEST)
# 获取改设备的端口
device_communication = TableXproAllDevinfo.objects.filter(dev_name=device_name).first()
if "TCP" in device_communication.comunitate_mode.upper():
device_port = device_communication.tcp_port
else:
return Response(status=status.HTTP_500_INTERNAL_SERVER_ERROR)
# 发送相关信号
if device_status == 'true':
if device_name in SIMULATE_DEVICE_PROCESS.keys():
return Response(status=status.HTTP_400_BAD_REQUEST)
start_signal.send(sender=None, protocol_name=protocol_name, device_name=device_name, port=device_port)
else:
if device_name not in SIMULATE_DEVICE_PROCESS.keys():
return Response(status=status.HTTP_400_BAD_REQUEST)
stop_signal.send(sender=None, device_name=device_name)
return Response(status=status.HTTP_200_OK)
......@@ -42,6 +42,7 @@ urlpatterns = [
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")),
re_path(r'^assets/(?P<path>.*)/$', serve, {'document_root': settings.STATIC_ROOT}),
......
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