示例#1
0
class MainWindow(QMainWindow):
    FILENAME_CONFIG_VIEWS = "views"
    FILENAME_CONFIG_NODES = "nodes"

    NODE_DEMO_ID = "2"

    def __init__(self, feed_layer, *args, **kwargs):
        super().__init__(*args, **kwargs)

        uic.loadUi(os.path.join(os.path.dirname(__file__), "MainWindow.ui"),
                   self)

        jsonpickle.set_encoder_options('simplejson', sort_keys=True, indent=4)
        jsonpickle.set_encoder_options('json', sort_keys=True, indent=4)
        jsonpickle.set_preferred_backend("simplejson")

        self.__tabs = {}

        self.uiMainTabWidget = self.findChild(QTabWidget, "tabWidget")
        self.uiMainTabWidget.tabCloseRequested.connect(self.closeView)

        nodes = self.__loadConfigFromFile(MainWindow.FILENAME_CONFIG_NODES, {})
        self.nodes = NodeManager(nodes)

        views = self.__loadConfigFromFile(MainWindow.FILENAME_CONFIG_VIEWS, {})
        self.views = ViewManager(views)

        self.sensorManager = SensorManager(self.views.callbackUpdate,
                                           self.nodes.addId)

        nodeConfigTab = NodeConfigTab(
            self.nodes, callbackModified=self.callbackModifiedNodes)
        self.nodes.setCallbackNodeAdded(nodeConfigTab.add)
        self.uiMainTabWidget.addTab(nodeConfigTab, "Konfiguration")
        self.uiMainTabWidget.tabBar().setTabButton(0, QTabBar.RightSide, None)

        viewConfigTab = ViewConfigTab(
            self.views,
            self.nodes,
            self.showView,
            callbackModified=self.callbackModifiedViews)
        self.uiMainTabWidget.addTab(viewConfigTab, "Ansichten")
        self.uiMainTabWidget.tabBar().setTabButton(1, QTabBar.RightSide, None)

        self.__updateTimer = QtCore.QTimer(self)
        self.__updateTimer.setInterval(1000)
        self.__updateTimer.timeout.connect(self.views.updateWidgets)
        self.__updateTimer.start()

        if feed_layer is not None:
            self.link = feed_layer
            self.readAllEvents()
            self.link.subscribe_sensor_feed(self.parseSensorFeedEventNoId)
        else:
            self.link = None
            self.demoTimer = None

    def readAllEvents(self):
        fid = self.link.get_sensor_feed_fid()
        eventCount = self.link.get_feed_length(fid)

        for seq in range(eventCount):
            self.parseSensorFeedEventNoId(self.link.get_event_content(
                fid, seq))

    def pushInterval(self, interval):
        fid = self.link.get_control_feed_fid()
        self.link.create_event(fid, f"{int(interval)}")

    def stopTimer(self):
        self.readTimer.cancel()

    def callbackModifiedNodes(self):
        if self.nodes.containsId(MainWindow.NODE_DEMO_ID):
            self.pushInterval(self.nodes.get(MainWindow.NODE_DEMO_ID).interval)
        self.__saveConfigToFile(self.nodes.getAll(),
                                MainWindow.FILENAME_CONFIG_NODES)

    def callbackModifiedViews(self):
        self.__saveConfigToFile(self.views.getAll(),
                                MainWindow.FILENAME_CONFIG_VIEWS)

    def addSensorDataSet(self, nodeId, timestamp, t, p, h, b):
        # T=1 P=2 rH=3 J=%
        # d/m/Y
        time = timestamp.timestamp()
        self.sensorManager.addData(nodeId, "T_celcius", float(t), time)
        self.sensorManager.addData(nodeId, "P_bar", float(p), time)
        self.sensorManager.addData(nodeId, "rH", float(h), time)
        self.sensorManager.addData(nodeId, "J_lumen", float(b), time)

    def parseSensorFeedEventNoId(self, feedEvent):
        print("DATA: {}".format(feedEvent))
        data = ast.literal_eval(feedEvent)
        if len(data) != 5:
            return
        self.addSensorDataSet(
            MainWindow.NODE_DEMO_ID,
            datetime.datetime.strptime(data[0], '%d/%m/%y %H:%M:%S'), data[1],
            data[2], data[3], data[4])

    def parseSensorFeedEvent(self, feedEvent):
        data = ast.literal_eval(feedEvent)
        if len(data) != 6:
            return
        self.addSensorDataSet(
            data[0], datetime.datetime.strptime(data[1], '%d/%m/%y %H:%M:%S'),
            data[2], data[3], data[4], data[5])

    def readSensorFeed(self):
        sensorFid = self.link.get_sensor_feed_fid()
        feedLength = self.link.get_feed_length(sensorFid)
        feedEvent = self.link.get_event_content(sensorFid, feedLength - 1)
        self.parseSensorFeedEvent(feedEvent)

    def periodicRead(self, interval):
        self.readSensorFeed()
        self.readTimer = threading.Timer(interval,
                                         self.periodicRead,
                                         args=[interval])
        self.readTimer.start()

    '''
        View Methods
    '''

    def showView(self, view):
        if view is None:
            return

        widget = self.views.open(view.id)

        for yAxis in view.getYAxes():
            if not yAxis.active:
                continue
            for nodeId, sensorId in yAxis.sensors.items():
                widget.setData(
                    yAxis.id, nodeId, sensorId,
                    self.sensorManager.dataReference(nodeId, sensorId))

        index = self.uiMainTabWidget.indexOf(widget)
        if index >= 0:
            self.uiMainTabWidget.setCurrentIndex(index)
        else:
            self.uiMainTabWidget.addTab(widget, view.name)
            self.uiMainTabWidget.setCurrentWidget(widget)
        widget.setOpen(True)

    def closeView(self, tabIndex):
        if tabIndex > 1:
            widget = self.uiMainTabWidget.widget(tabIndex)
            if isinstance(widget, ViewWidget):
                widget.setOpen(False)
            self.uiMainTabWidget.removeTab(tabIndex)

    '''
        General Methods
    '''

    def __saveConfigToFile(self, config, filename):
        if config is None or not isinstance(filename, str):
            return False
        with open(filename + ".json", "w") as f:
            f.write(jsonpickle.encode(config))

    def __loadConfigFromFile(self, filename, default=None):
        if not isinstance(filename,
                          str) or not os.path.isfile(filename + ".json"):
            return default
        with open(filename + ".json", "r") as f:
            config = jsonpickle.decode(f.read())

        return config

    def demo(self, interval):
        if interval < 1 or not self or not self.isVisible():
            print(self.isVisible())
            if self.demoTimer is not None:
                self.demoTimer.cancel()
            return
        self.parseSensorFeedEvent(
            f"['1','{datetime.datetime.now().strftime('%d/%m/%y %H:%M:%S')}','{random.random() * 3 + 20}','{random.randrange(10000) + 95000}','{random.random() * 30 + 30}','{random.random() * 10 + 50}']"
        )
        self.demoTimer = threading.Timer(interval, self.demo, args=[interval])
        self.demoTimer.start()

    def show(self):
        super().show()
        if self.link is None:
            self.demo(2)