Problem z after w tkinter, odświeżanie co minutę.

0

Witajcie, po niedługiej przerwie wróciłem do Pythona, poprzednio utknąłem w tym samym punkcie co teraz. Dokładnie chodzi o odświeżanie całodobowe parametrów odczytywanych z pliku json. Program ma być częścią większego projektu u mnie w domu. Jedna z maszynek Raspberry odczytuje parametry z innych urządzeń( jak dotej pory z dwóch) i na jednym pokazuje odczytane wyniki. Do tego celu korzystam z tkinter i funkcji after. Wyniki odczytywane są co minutę. Po kilku godzinach (6-7)program zawiesza swoje działanie. Co zrobić, podejrzewam że pewnie zapycha się pamięć i dlatego program się zatrzymuje. Czu ktoś może spotkał się z podobnym problemem?

kod:

# -*- coding: utf-8 -*-
"""
Created on Thu Dec 16 12:40:36 2021

@author: ilodz
"""

import pandas as pd
import json
import requests
import datetime as dt
import tkinter as tk
from time import strftime

class Application:
    def __init__(self):
        self.window = tk.Tk()

        self.temperatura = tk.StringVar()
        self.cisnienie = tk.StringVar()
        self.temperatura_bojler = tk.StringVar()
        self.data_sypialnia = tk.StringVar()
        self.godzina_sypialnia = tk.StringVar()
        self.temp_sypialnia = tk.StringVar()
        self.cisn_sypialnia = tk.StringVar()
        self.kolor_temp_sypialnia = tk.StringVar()
        self.kolor_bojler = tk.StringVar()

        self.window.geometry("800x600+0+0")
        self.window.configure(background="black")
        self.window.title("Inteligentny dom - stacja bazowa")

        self.parametry()

        self.rama = tk.LabelFrame(self.window, text="Inteligentny Dom", bg="black", fg="white", padx=5, pady=5)
        self.rama.pack(padx=5, pady=5)

        self.r1 = tk.LabelFrame(self.rama, padx=5, pady=5)
        self.r1.configure(background="black")
        self.r1.pack(fill="both", expand="yes")

        self.linia0 = tk.Label(self.r1, textvariable=self.data_sypialnia,font=("Arial", 40), fg="green", bg="black")
        self.linia0.grid(row=0, column=0)

        self.linia0a = tk.Label(self.r1,text = "   " ,font=("Arial", 40), fg="green", bg="black")
        self.linia0a.grid(row=0, column=1)

        self.linia1 = tk.Label(self.r1, textvariable=self.godzina_sypialnia,font=("Arial", 70), fg="silver", bg="black")
        self.linia1.grid(row=0, column=2)

        self.rama1 = tk.LabelFrame(self.window, text="Parametry", bg="black", fg="white", padx=5, pady=5)
        self.rama1.pack(padx=5, pady=5)

        self.r2 = tk.LabelFrame(self.rama1, padx=5, pady=5)
        self.r2.configure(background="black")
        self.r2.pack(fill="both", expand="yes")

        self.linia5 = tk.Label(self.r2, text="Temperatura w sypialni: ", font=("Arial", 17), fg="white", bg="black")
        self.linia5.grid(row=0, column=0, sticky = "w")

        self.linia5a= tk.Label(self.r2, textvariable=self.temp_sypialnia, font=("Arial", 20), fg=self.kolor_temp_sypialnia.get(), bg="black")
        self.linia5a.grid(row=0, column=1, sticky = "w")

        self.linia5b = tk.Label(self.r2, text="  °C ", font=("Arial", 17), fg="white", bg="black")
        self.linia5b.grid(row=0, column=2, sticky = "w")

        self.linia6 = tk.Label(self.r2, text="Ciśnienie powietrza: ", font=("Arial", 17), fg="white", bg="black")
        self.linia6.grid(row=1,column=0,sticky = "w")

        self.linia6a= tk.Label(self.r2, textvariable=self.cisn_sypialnia, font=("Arial", 20), fg="silver", bg="black")
        self.linia6a.grid(row=1, column=1, sticky = "w")

        self.linia6b = tk.Label(self.r2, text="  hPa ", font=("Arial", 17), fg="white", bg="black")
        self.linia6b.grid(row=1, column=2, sticky = "w")

        self.r3 = tk.LabelFrame(self.rama1, padx=5, pady=8)
        self.r3.configure(background="black")
        self.r3.pack(fill="both", expand="yes") 

        self.linia7 = tk.Label(self.r2, text="Temperatura bojlera: ", font=("Arial", 17), fg="white", bg="black")
        self.linia7.grid(row=2,column=0, sticky = "w")

        self.linia8 = tk.Label(self.r2, textvariable=self.temperatura_bojler, font=("Arial", 17), fg=self.kolor_bojler.get(), bg="black")
        self.linia8.grid(row=2,column=1, sticky = "w")

        self.linia9 = tk.Label(self.r2, text="  °C ", font=("Arial", 17), fg="white", bg="black")
        self.linia9.grid(row=2, column=2, sticky = "w")

        self.window.mainloop()

    def parametry(self):
        self.readDane2=requests.get("http://192.168.1.80/data_sypialnia.json")
        self.task2 = self.readDane2.json()

        self.data_sypialnia.set(self.task2["data"])
        self.godzina_sypialnia.set(self.task2["godzina"])
        self.temp_sypialnia.set(self.task2["temperatura_sypialnia"])
        self.cisn_sypialnia.set(self.task2["cisnienie_sypialnia"])

        # przekształcanie koloru temperatury w sypialni
        x1 = self.temp_sypialnia.get()
        x1 = float(x1)

        if x1>25:
            self.kolor_temp_sypialnia.set("red")
        elif x1<21:
            self.kolor_temp_sypialnia.set("blue")
        else:
            self.kolor_temp_sypialnia.set("green")

        self.readDane=requests.get("http://192.168.1.81/temp_bojler.json")
        self.task = self.readDane.json()

        self.temperatura_bojler.set(self.task["temperatura_bojlera_1"])

        # przekształcanie koloru temperatury wody w bojlerze
        x2 = self.temperatura_bojler.get()
        x2 = float(x2)

        if x2< 40:
            self.kolor_bojler.set("blue")
        elif x2 > 40 and x2 < 60:
            self.kolor_bojler.set("orange")
        elif x2 > 60 and x2 < 80:
            self.kolor_bojler.set("red")
        else:
            self.temperatura_bojler.set("!!!")
            self.kolor_bojler.set("red")

        self.window.after(60000, self.parametry)

apl = Application()
1

Ładnie przy odświeżaniu danych modyfikujesz istniejące pola, nie dodajesz nowych, nie zbierasz też danych do żadnej tablicy tylko nadpisujesz wartości, więc raczej nie powinno się zapychać, ale warto to sprawdzić. Porównaj sobie ile zasobów zżera apka po godzinie czy dwóch działania.
Ja bym jeszcze zabezpieczył momenty komunikacji przez sieć. U mnie z całą pewnością by ten skrypt się zacinał ze względu na gówniany router. Dodałbym timeout i jakieś obsłużenie wyjątków. https://docs.python-requests.org/en/latest/user/quickstart/#timeouts

(tak w ogóle to bym olał tkintera i dał to jako stronkę)

0
Arthan napisał(a):

Ładnie przy odświeżaniu danych modyfikujesz istniejące pola, nie dodajesz nowych, nie zbierasz też danych do żadnej tablicy tylko nadpisujesz wartości, więc raczej nie powinno się zapychać, ale warto to sprawdzić. Porównaj sobie ile zasobów zżera apka po godzinie czy dwóch działania.
Ja bym jeszcze zabezpieczył momenty komunikacji przez sieć. U mnie z całą pewnością by ten skrypt się zacinał ze względu na gówniany router. Dodałbym timeout i jakieś obsłużenie wyjątków. https://docs.python-requests.org/en/latest/user/quickstart/#timeouts

(tak w ogóle to bym olał tkintera i dał to jako stronkę)

Też myślałem nad wyświetlaniem przez www, ale musiałbym postudiować php :) co do , timeout=1, już zmieniłem może to pomoże, dzięki za podpowiedź

2

Nie koniecznie php. Masz kilka fajnych frameworków do pisania stron w Pythonie. Ale by zrealizować tak prosty projekt wystarczą podstawy html i css. W sumie to mam całkiem podobny projekt. W Cronie dodałem by co minutę odpalał mi się skrypt pythona, który pobiera dane ze stronki i wrzuca do pliku json w folderze, który widzi serwer www. Na serwerze mam baardzo prostą stronkę, która co jakiś czas odświeża prezentowane dane. Do tego dodałem plik manifest, jakąś ikonkę i tak oto powstała pełnoekranowa apka na tel/tablet.

0
Arthan napisał(a):

Nie koniecznie php. Masz kilka fajnych frameworków do pisania stron w Pythonie. Ale by zrealizować tak prosty projekt wystarczą podstawy html i css. W sumie to mam całkiem podobny projekt. W Cronie dodałem by co minutę odpalał mi się skrypt pythona, który pobiera dane ze stronki i wrzuca do pliku json w folderze, który widzi serwer www. Na serwerze mam baardzo prostą stronkę, która co jakiś czas odświeża prezentowane dane. Do tego dodałem plik manifest, jakąś ikonkę i tak oto powstała pełnoekranowa apka na tel/tablet.

Do strony użyłeś Djago?

0

Nie, strona siedzi sobie na serwerze Apache na RaspberryPi, to jest czysty html+css i kilka linijek javascriptu, który pobiera dane i odświeża je na stronie by nie trzeba było odświeżać strony samemu.

0
Arthan napisał(a):

Nie koniecznie php. Masz kilka fajnych frameworków do pisania stron w Pythonie. Ale by zrealizować tak prosty projekt wystarczą podstawy html i css. W sumie to mam całkiem podobny projekt. W Cronie dodałem by co minutę odpalał mi się skrypt pythona, który pobiera dane ze stronki i wrzuca do pliku json w folderze, który widzi serwer www. Na serwerze mam baardzo prostą stronkę, która co jakiś czas odświeża prezentowane dane. Do tego dodałem plik manifest, jakąś ikonkę i tak oto powstała pełnoekranowa apka na tel/tablet.

Jeszcze jedno pytanie jak zrobić aby strona otwierała się jako pełny ekran? (wspomniałeś o manifest, co to jest?)

1

https://developer.mozilla.org/en-US/docs/Web/Manifest
W head dajesz:

<link rel="manifest" href="manifest.json">

Ja w tym pliku mam coś takiego:

{
  "short_name": "eKontrol",
  "name": "eKontrol++",
  "icons": [
    {
      "src": "icon.png",
      "sizes": "192x192",
      "type": "image/png"
    }
  ],
  "start_url": "index.html",
  "display": "fullscreen",
  "orientation": "portrait"
}

Po wejściu na tak przygotowaną stronkę w telefonie, możesz ją dodać do ekranu głównego. W tym momencie strona jest traktowana podobnie jak apka i uruchamia się wg ustawień w tym pliku.

0
Arthan napisał(a):

https://developer.mozilla.org/en-US/docs/Web/Manifest
W head dajesz:

<link rel="manifest" href="manifest.json">

Ja w tym pliku mam coś takiego:

{
  "short_name": "eKontrol",
  "name": "eKontrol++",
  "icons": [
    {
      "src": "icon.png",
      "sizes": "192x192",
      "type": "image/png"
    }
  ],
  "start_url": "index.html",
  "display": "fullscreen",
  "orientation": "portrait"
}

Po wejściu na tak przygotowaną stronkę w telefonie, możesz ją dodać do ekranu głównego. W tym momencie strona jest traktowana podobnie jak apka i uruchamia się wg ustawień w tym pliku.

ok, dzięki postudiuje i pokombinuje, dzięki za podpowiedź

0
slavoHeys napisał(a):
Arthan napisał(a):

https://developer.mozilla.org/en-US/docs/Web/Manifest
W head dajesz:

<link rel="manifest" href="manifest.json">

Ja w tym pliku mam coś takiego:

{
  "short_name": "eKontrol",
  "name": "eKontrol++",
  "icons": [
    {
      "src": "icon.png",
      "sizes": "192x192",
      "type": "image/png"
    }
  ],
  "start_url": "index.html",
  "display": "fullscreen",
  "orientation": "portrait"
}

Po wejściu na tak przygotowaną stronkę w telefonie, możesz ją dodać do ekranu głównego. W tym momencie strona jest traktowana podobnie jak apka i uruchamia się wg ustawień w tym pliku.

ok, dzięki postudiuje i pokombinuje, dzięki za podpowiedź

Zrobiłem tak jak napisałeś ale u mnie nie działa, myślę że coś schrzaniłem, to mój plik php i plik json

<<!doctype html>
<html>
    <head>
        <meta http-equiv="Content-type" content="text/html; charset=iso-8859-2" />
        <meta http-equiv="Reply-to" content="[email protected]" />
        <meta name="Author" content="Slavo Heys" />
        <!-- <meta http-equiv="refresh" content="30"> -->
        <link rel="manifest" href="manifest.json">
        <title><?php echo "Strona domowa DOM"; ?></title>
        <style type="text/css">


            body {
            font-family: Verdana, Arial;
            font-size: 12px;
            color: white;
            background-color: black;
                }

           

        </style>
    </head>

    <body>
        <table border="1" cellpadding="0" cellspacing="0" width="100%">
        <tr>
                <td align = "center" width="50%" colspan="3"><?php include "time_2.php"; ?></td>
                <td align = "center" width="50%" colspan="2"><?php include "time.php"; ?></td>
                
        </tr>

            <tr>
                <td align = "center" width="20%"><a href="index.php"><img src="home-page_b.png" style="border: 0" alt="strona główna"></a></td>
                <td align = "center" width="10%" rowspan="2"><?php include "cisnienie_sypialnia.php"; ?></td>
                <td align = "center" width="20%" rowspan="2"><?php include "baza_danych_dzieci_2.php"; ?></td>
                <td align = "center" width="20%" rowspan="2"><?php include "cisnienie_sypialnia.php"; ?></td>
                <td align = "center"width="30%"><?php include "wilgotnosc_dzieci.php"; ?></td>
                
                
            </tr>
                       
            <tr>
                <td align = "center" width="20%"><a href="statystyka.php"><img src="trend_b.png" style="border: 0" alt="statystyka"></a></td>
                <td align = "center" width="30%"><?php include "cisnienie_2.php"; ?></td>
                
            </tr>

            <tr>
                <td align = "center" width="20%"><a href="stacjaPogodowa.php"><img src="weather.png" style="border: 0" alt="Dane pogodowe"></a></td>
                <td align = "center" width="10%" rowspan="2"><?php include "baza_danych.php"; ?></td>
                <td align = "center" width="20%" rowspan="2"><?php include "baza_danych_2.php"; ?></td>
                <td align = "center" width="20%" rowspan="2"><?php include "baza_danych3.php"; ?></td>
                <td align = "center"width="30%"><?php include "wilgotnosc_sypialnia.php"; ?></td>
            </tr>

            <tr>
                <td align = "center" width="20%"><a href="ustawienia.php"><img src="settings_b.png" style="border: 0" alt="ustawienia"></a></td>
                <td align = "center"width="30%"><?php include "cisnienie.php"; ?></td>
            </tr>

            <tr>
                <td align = "center" width="100%" height = "20px" colspan="5"></td>
            </tr>
        </table>
    </body>
</html>



{
 "short_name": "eKontrol",
 "name": "eKontrol++",
 "start_url": "index.php",
 "display": "fullscreen",
 "orientation": "portrait"
}

Nie wiem sam, dawno nie robiłem nic w html i php trochę już pozapominałem, pomożesz? doradzisz?

0
<<!doctype html>

Jeśli faktycznie masz tu dwa znaki: "<", to to powoduje problem :)
Trochę zaszalałeś z tymi plikami phpa.
Ja mam jeden plik json z taką zawartością:

{"temp": [[8, "dach"], [41, "dol kotla"], [22, "powrot na kolektory"], [42, "gora kotla"], [35, "piec"]], "czas": "2022-05-12 21:58:55"}

odczytuje tylko ten jeden plik i aktualizuję stronę wg tego co tam się znajduje.
W head mam jeszcze:

<meta name="mobile-web-app-capable" content="yes">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">

0
Arthan napisał(a):
<<!doctype html>

Jeśli faktycznie masz tu dwa znaki: "<", to to powoduje problem :)
Trochę zaszalałeś z tymi plikami phpa.
Ja mam jeden plik json z taką zawartością:

{"temp": [[8, "dach"], [41, "dol kotla"], [22, "powrot na kolektory"], [42, "gora kotla"], [35, "piec"]], "czas": "2022-05-12 21:58:55"}

odczytuje tylko ten jeden plik i aktualizuję stronę wg tego co tam się znajduje.
W head mam jeszcze:

<meta name="mobile-web-app-capable" content="yes">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">

muszę się trochę doszkolić żeby to pojąć ;) Dzięki za pomoc

0

Może na początku Ci się wydawać to skomplikowane, ale tak naprawdę tam nie ma żadnej magii. Całą obsługę tego po stronie stronki można skrócić do czegoś takiego jak poniżej. Pisałem jakiś czas temu, więc bym teraz większość pozmieniał, ale to nie ważne bo działa :D
Strona zawiera element span o id "temperatura" i zmieniam jego zawartość dynamicznie po wczytaniu strony, a potem co 10 sekund.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
	$(document).ready(function(){
    
    function refreshData() {
      $.getJSON('dane.json', function(data) {
        $("#temperatura").text(data.temp[0][0]);  
      });
    };
    refreshData();
    
    const interval = setInterval(function() {
      refreshData();
    }, 10000);
		
	});
</script>

<body>
  <span style="font-size:150px"><span id="temperatura">--</span>&deg;C</span>
</body>
</html>

0

Niestety javy nie ogarniam, wkleiłem do index

<meta name="mobile-web-app-capable" content="yes">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">

i to na telefonie zadziałało natomiast na 7 calowym ekranie raspberry nie, ale pouczę się i pokombinuje :)

0

Ja też Javy nie ogarniam, to inny język niż javascript ;)
Jak odpalasz stronę na raspberry? Zakładam że pod jakimś Linuxowym OS w Chromie lub Firefoxie? podłącz klawiaturę, wciśnij F11 i będziesz miał na pełen ekran. Te znaczniki działają jedynie na mobilkach, więc na RPi by działało tylko jeżeli byś miał LineageOS.

1 użytkowników online, w tym zalogowanych: 0, gości: 1