【问题标题】:Pass live data from external script to django view将实时数据从外部脚本传递到 django 视图
【发布时间】:2016-08-13 07:57:21
【问题描述】:

我有一个 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 一次并读取/返回该值。

【问题讨论】:

  • 这对我来说似乎有点倒退,你能不能让设备 ping 服务器(而不是反过来)?
  • 设备 ping 服务器是什么意思?该设备只是某个地方的仪表,我正在使用我的脚本使用 pymodbus 发送读取请求。不要认为设备除了回复我发送的请求之外什么都做不了。除非我误会了你
  • 我的意思是让设备向服务器发布请求,我想如果它可以响应一个它必须也能够发送一个,但是我不知道任何内在函数涉及

标签: python ajax django django-templates


【解决方案1】:

您想从您的命令中移动for device in TDevices.objects.all(): 之后的所有代码,并使其成为 TDevices 模型的方法。所以像

class TDevices(...):
    [...]
    def ping(self):
         if device.bIsLogging == True:
                # collect data, etc
         return dataDict

然后视图调用device.ping()并将返回的数据合成到视图中。抱歉,如果它有点抽象,但问题实际上只是将代码放在哪里。一旦它在模型中,视图就很容易访问它。希望你能明白它的要点。

【讨论】:

  • 其实这个还不错。我假设这仍然可以与我的 threading.timer 一起使用?
  • 这只是 python 代码,所以任何东西都可以工作。在最坏的情况下,您必须阻止该过程才能完成。只要您使用多线程 Web 服务器来提供不应该成为问题的页面,除非该过程需要很长时间并且最终用户不满意。
猜你喜欢
  • 1970-01-01
  • 2013-06-24
  • 1970-01-01
  • 1970-01-01
  • 2020-03-19
  • 2019-02-16
  • 1970-01-01
  • 1970-01-01
  • 2019-11-14
相关资源
最近更新 更多