我有一个django项目,我想要显示每20秒被ping的设备的实时数据。我写了一个外部python脚本,通过在cmd“python manage.py ping”中运行,每20秒ping一次设备。
我的问题是我不太确定如何处理这个问题。我会将返回的数据从外部脚本传递给视图函数,然后从那里发送到客户端吗?
这是我编写的脚本,它将ping设备并获取值
from pymodbus.client.sync import ModbusTcpClient
from pymodbus.exceptions import ModbusException, ConnectionException, ParameterException
from models import *
from devices_models import *
from views import reciever
import datetime
from django.core.management.base import NoArgsCommand
import threading
import time
class Command(NoArgsCommand):
def handle_noargs(self, **options):
timerThread = threading.Thread(target=run)
timerThread.start()
def run():
next_call = time.time()
while True:
print("sending ping..")
with open("test.txt", "a") as my_file:
for device in TDevices.objects.all():
if device.bIsLogging == True:
my_file.write("Pinging device: " + device.asDeviceName + " at " + datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") + '\n')
try:
config = TModbusConfigs.objects.get(pk=device.ixDevice)
client = None
if config != None:
client = ModbusTcpClient(config.asIPAddressv4, config.iPort)
client.connect()
response = None
my_file.write("\t(dev ID=" + str(device.ixDevice) + ") pinging registers...\n")
for register in TDeviceMeasurememts.objects.filter(ixDevice=device.ixDevice):
#determine register type by prefix
reg_parse = AddressParser(register.iAddress)
func_code = reg_parse.get_prefix()
reg_addr = reg_parse.get_address()
if func_code == 1:
try:
response = client.read_coils(reg_addr, register.iLength, unit=int(config.iSlaveID))
if response != None:
temp = response.bits[0]
else:
raise ParameterException()
except ConnectionException as ex:
LogSysAlert(ex, "Communication")
pass
except ParameterException() as ex:
LogSysAlert(ex, "Communication")
pass
except ModbusException as ex:
LogSysAlert(ex, "Communication")
pass
elif func_code == 2:
try:
response = client.read_discrete_inputs(reg_addr, register.iLength, unit=int(config.iSlaveID))
if response != None:
temp = response.bits[0]
else:
raise ParameterException()
except ConnectionException as ex:
LogSysAlert(ex, "Communication")
pass
except ParameterException() as ex:
LogSysAlert(ex, "Communication")
pass
except ModbusException as ex:
LogSysAlert(ex, "Communication")
pass
elif func_code == 3:
try:
response = client.read_holding_registers(reg_addr, register.iLength, unit=int(config.iSlaveID))
if response != None:
if hasattr(response, 'registers'):
value = ''
for val in response.registers:
value += str(val)
if value != None:
temp = value
my_file.write("\t\t\t" + device.asDeviceName + " (" + register.asInputID + ") Register(" + str(register.iAddress) + "): " + value + "\n")
else:
my_file.write("\t\t\tNo register Attribute \n")
else:
raise ParameterException("Invalid Parameter")
except ConnectionException as ex:
my_file.write("\t\t\tConnectedException: " + ex.message + " - " + ex.string + "\n")
#LogSysAlert(ex, "Communication")
pass
except ParameterException() as ex:
my_file.write("\t\t\tParameterException: " + ex.message + " - " + ex.string + "\n")
#LogSysAlert(ex, "Communication")
pass
except ModbusException as ex:
my_file.write("\t\t\tModbusException: " + ex.message + " - " + ex.string + "\n")
#LogSysAlert(ex, "Communication")
pass
elif func_code == 4:
try:
response = client.read_input_registers(reg_addr, register.iLength, unit=int(config.iSlaveID))
if response != None:
if hasattr(response, 'registers'):
value = ''
for val in response.registers:
value += str(val)
if value != None:
temp = value
my_file.write("(" + device.asDeviceName + ") Register( " + str(register.iAddress) + "): " + value)
else:
raise ParameterException()
except ConnectionException as ex:
my_file.write("\t\t\ConnectionException: " + ex.message + " - " + ex.string + "\n")
#LogSysAlert(ex, "Communication")
pass
except ParameterException() as ex:
my_file.write("\t\t\ParameterException: " + ex.message + " - " + ex.string + "\n")
#LogSysAlert(ex, "Communication")
pass
except ModbusException as ex:
my_file.write("\t\t\ModbusException: " + ex.message + " - " + ex.string + "\n")
#LogSysAlert(ex, "Communication")
pass
client.close()
except ModbusException as ex:
my_file.write("\t\t\ModbusException: " + ex.message + " - " + ex.string + "\n")
if client != None:
client.close()
#log_exception(ex)
LogSysAlert(ex, "Communication")
pass
except AttributeError as ex:
my_file.write("\t\t\AttributeError: " + ex.message + " - " + ex.string + "\n")
if client != None:
client.close()
pass
except Exception as ex:
my_file.write("\t\t\Exception: " + ex.message + " - " + ex.string + "\n")
if client != None:
client.close()
pass
#raise Exception(ex)
my_file.write("...-----------------------------------------------------------------------------------------------ending\n\n\n")
print("finished...")
next_call = next_call + 20
time.sleep(next_call - time.time())
class AddressParser():
def __init__(self, address):
self.address = address
self.prefix = None
def get_prefix(self):
self.prefix = str(self.address)[0]
return int(self.prefix)
def get_address(self):
if self.prefix != None:
return int(str(self.address)[1:])
现在我只将它写入文本文件,但会转换为数组或对象。
这是我查看设备及其寄存器的视图:
@login_required(login_url='/login/')
def devices(request):
assert isinstance(request, HttpRequest)
devices = TDevices.objects.all()
if request.method == "POST":
for device in devices:
if "device_" + str(device.ixDevice) in request.POST:
device.bIsLogging = True
device.save()
else:
device.bIsLogging = False
device.save()
return render(request, 'devices.html' , context_instance = RequestContext(request, { 'title':'Device Management', 'sysalerts': TSystemAlerts.objects.all(), 'devices': TDevices.objects.all(), 'counterCheck': [4,7,10,13,16,19,22]}))
我能想到的一种方法是暂时将数据存储在某处,然后每隔20秒让客户端ajax GET并读取/返回该值。
答案 0 :(得分:1)
您希望在命令for device in TDevices.objects.all():
之后移动所有代码,并使其成为TDevices模型的方法。像
class TDevices(...):
[...]
def ping(self):
if device.bIsLogging == True:
# collect data, etc
return dataDict
然后视图调用device.ping()
并将返回的数据合成到视图中。对不起,如果它有点抽象,但问题实际上就是放置代码的地方。一旦进入模型,视图就可以轻松访问它。希望你能得到它的要点。