Python-arduinodan Html'e dinamik veri aktarma (localhost/0 gibi) nasıl olur?

İyi günler. Arduinodan gönderdiğim verileri seri porta aktarıyorum ve pythonda okuyorum. Flask modülü sayesinde bu verileri localhost’dan paylaşıyorum ama bu verileri istenilen web sayfasına yönlendiremiyorum.Aslında arduinodan sensör bilgilerini yayınlamak amacım deneme olarak bu kodları kullandım.
python kodum

from flask import Flask, render_template,Response
import serial
import time

app = Flask(__name__)

def seri():

    ser = serial.Serial()
    ser.port = 'COM18'
    ser.baudrate = 9600
    ser.open()
    while True:
        s = str(ser.readline())
        s=s[2:-5]+' <br>'
        print(s)
        print(ser.in_waiting)
        time.sleep(0.3)
        if ser.in_waiting > 1000:
            ser.flushInput()
            time.sleep(0.12)
            ser.flush()
            print("temizlendi")
        yield s

@app.route('/', methods=["GET","POST"])
def index():
    return render_template("index.html",)

@app.route('/0', methods=["GET","POST"])
def temp():
    title=Response(seri())
    return title

if __name__=="__main__":
    app.run(debug=True)

Arduinodan gönderme yaptığım basit bir kod

int a =0;
void setup() {
Serial.begin(9600);

}

void loop() {
Serial.print(a);
Serial.println(" deneme verisi kontrol-1");
a++;
delay(300);
}

Html kodlarım:

                 <form action="http://localhost:5000/0" method="get" >
                     {{title}}
                    </form>

böyle bir şey denedim fakat direkt olarak http://localhost:5000 'e veri gönderemiyorum biraz uzun oldu kusura bakmayın yardımcı olursanız sevinirim

Yanlış anlamadıysam aşağıdaki mantıkla olabilir, daha önce c ve php ile benzer bir uygulama yapmıştım.

Python tarafı

import requests
data = {"data1": "data", "data2": "data", "data3": "data"}
resp = requests.post('http://localhost:5000/test.php', params=data)

PHP Tarafı

$data1 = htmlspecialchars($_GET["data1"]);
$data2 = htmlspecialchars($_GET["data2"]);
$data3 = htmlspecialchars($_GET["data3"]);
echo "data1: $data1 data2: $data2 data3: $data3";

sanırım sizin istediğiniz burada : https://www.elektormagazine.com/articles/display-serial-data-on-a-web-page

Eğer Flask kullanmadaki tek amacınız kendi bilgisayarınızda tarayıcı üzerinden güzel bir arayüz sağlamak ise masaüstü uygulamalarda bu amaçla daha kolay bir şekilde kullanılabilecek bir kütüphane mevcut. Daha önce kullandığım için isterseniz yardım da edebilirim.

Flask üzerinden gitmek zorundayım. Bu projmin bir parçası sadece. Teşekkür ederim :slight_smile:

Hocam php bilgim yok ama kodlardan anladığım kadarıyla data1 isimli değişken yolluyoruz ve php o değişkenin adının data1 olduğunu anlıyor. data1’in değeri "data"yı da ekrana bastırıyor.
benim problemim aslında http://localhost:5000/0 tarafına sürekli veri yolluyor ama ben bunu siteye çekemiyorum. ‘/0’ adresine girince alt alta sürekli verileri yazıyor. ama title diye bir değişkene gelse bu veriler tek bir yere yazacaktır.

<script type="text/javascript" src="/0" >  </script>

şeklinde ‘/0’ a bağlanıyor index sayfası sürekli yenileniyor fakat ben yine siteye ‘title’ adına sahip değişkeni ekrana bastıramıyorum.

localhost:5000 web sunucusu mu? yani bilgisayarınızda sunucu kurulu mu? kuruluysa hangi sunucuyu kullanıyorsunuz? bir de veriler hangi yolla geliyor? bildiğim kadarıyla arduino udp gibi protokoller de kullanıyor. sorunuzu tekrar okudum ve şimdi anladım :slight_smile: serial kısmını atlamışım.

Madem sürekli veri alışverişinde bulunacaksınız niçin javascript üzerinden socket kullanmıyorsunuz?

1 Beğeni

dinamik veri istiyorsanız jquery kullanın
https://code-maven.com/slides/python-programming/flask-and-ajax-jquery

güzel bir kaynak buldum incelerseniz sorunu bu çözecektir
https://flask-socketio.readthedocs.io/en/latest/

1 Beğeni

hocam sorunu çözerseniz burada paylaşır mısınız ?

Burada bir mimari sikintisi var. Calisabilecek bir sistem genel hatlariyla tasarlanmamis, tasarlanmissa da bu bize dogru bir sekilde aktarilamiyor.

  • Siteye ayni anda tek bir kullanici mi baglanacak?
  • Veri akisi hangi yonde olacak? Baslikta “arduino’dan HTML’e” denilmis (arduino’dan web sayfasina denilmek istedigini varsayiyorum) ama HTML kodu sadece web sayfasindan web sunucusuna veri aktaran bir formdan ibaret.
  • Nasil bir veri, hangi arayuzle aktarilacak?

Localhost’tan paylasmak ne demek? Bilgisayarda calisan flask web sunucusu uzerinden bir web sayfasinda sunabilmek mi demek? O zaman “web sayfasina yonlendiremiyorum” ne anlama geliyor?

Problem web sunucusuna veri mi yolluyor? Ne?

Siteye cekmek ne demek?


Problemleri dogru ifade edebilmek cozum bulmanin ilk adimi. Ve sadece baskalarina iletilen problemlerden bahsetmiyorum; rubber duck debugging diye son derece kullanisli bir yontem var ve kisinin problemi kendisine iletmesine dayaniyor.

1 Beğeni

Buradaki örnek sorunsuz çalışıyor, test edildi.

araştırmalarım sonucunda istediğim şeyi yaptım. Ama tek bir veri yollanabiliyor ve python yield f"data:{ntc_deger}\n\n" kısmında data değilde “veri : …” yapınca çalışmıyor. Flask kısmından verileri JSON tipinde gönderiyor. Göndermeden önce gelen veri “ntc:12” şeklinde değişken bir veridir.“12” olan kısım her defasında artıyor ve göndermeden önce sadece “ntc:12” olan değişkeni parçalayıp “12” şekline çevirip f’string ile yolluyorum .html js kısmında buna göre okuyor. js de data yerine veri yazıyorum yine olmuyor. Bu konu hakkında fikri olan varsa görüşlerinizi bekliyorum.
yeni düzenlemeye göre python kodlarım:

from sql import db,Login,Sicaklik
from flask import Flask,render_template,request,redirect,url_for,Response
import serial
import time

temp=Sicaklik.query.get(1)
app=Flask(__name__)

def sicakik():
    ser = serial.Serial()
    ser.port='COM18'
    ser.baudrate=9600
    if not ser.is_open:
        ser.open()
    while True:
        if "ntc" in str(ser.readline()):
            ntc = str(ser.readline())
            ntc = ntc.split("b'")
            ntc=str(ntc[1]).split("\\r\\n'")
            ntc_deger=str(ntc[0])
            print("ntc: ", ntc_deger)
        if ser.in_waiting > 1000:
            ser.flushInput()
            time.sleep(0.12)
            ser.flush()
            print("temizlendi")
        yield f"data:{ntc_deger}\n\n" #+f"data:{ntc_deger}b\n\n"
        #time.sleep(0.3)

@app.route('/', methods=["GET","POST"])
def index():
    return render_template("show.html")

@app.route('/temp', methods=["GET","POST"])
def temp():
    sicaklik_res=Response(sicakik(), mimetype='text/event-stream')
    return sicaklik_res

if __name__=="__main__":
    app.run(debug=True)

html kodlarım

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
<script>
     $(function () {
            var stream = new EventSource('/temp');
            stream.onmessage = function(e) {
            $("#veri").html(e.data);
         };
     });

</script>
<p id="veri"  > !!! </p>
<p id="veri2" > ??? </p>
</body>
</html>

arduino kısmı aynı sayılır…

int a = 0, b = 120;
void setup() {
  Serial.begin(9600);

}

void loop() {
  Serial.println("ntc:");
  Serial.println(a);
  //Serial.println("nem:");
  //Serial.println(b);
  a++;
  //b++;
  delay(550);
}

" https://blog.easyaspy.org/post/10/2019-04-30-creating-real-time-charts-with-flask " sitesindeki kodları yorumlayarak sonuca ulaştım
localhostdan aldığım verileri de ek olarak gösteriyorum:
lokal1 lokal2

çok karışık pek anlıyamadım mantığını

localhost Flask framework’una aittir.‘http://127.0.0.1:5000’ adresinden yayın yapıp denemeleri kolaylaştırıyor.hocam sorunun bir kısmını çözdüm fakat dediğiniz gibi başka problemlerde var. Birden fazla kullanıcı bağlanamıyor ve bağlanması gerekecektir. veri akışı
arduino -> python( flask ) -> html şeklinde. Düzgün bir şekilde anlatamadığım için kusura bakmayın. aslında sorunun kaynağı html, js, jquery’den ibaret. gelen verileri kontrol edemiyorum. Gönderme methodum ile okuma methotumu senkronize edemedim. Burda python kodlarınıda paylaştım çünkü gönderirken yanlışlık yapmış olabilirim veya başka bir methot ile gönderim daha kolay olur diye tavsiye edebilen olur diye

pythonda socket kullanmadan js de socket kullanabilir miyim?

geçici olarak bir çözüme ulaştım

jquery kullandım fakat birden fazla data’yı alamıyorum. Bilginiz var mı bu konuda?

Bunun onundeki en buyuk engel Flask’a yapilan /temp istegine cevap donduren kodun (bundan sonra kisaca “sicaklik” diyecegim) COM18’i acip aldigi data’yi istemciye stream etmesi. Ikinci bir /temp istegi de aynisini yapmaya calisacak, ilk istegin actigi portu acamayip hata dondurecek.

Butun isteklerin ayni datayi okumasi ve dondurmesi gerektigini varsayarsak, seri portun paylasilmasi bile sorunu cozmeyecektir. (Cunku her satir en fazla bir sicaklik() cagrisi tarafindan okunuyor.)

Seri porttan gelen her deger 1 kere okunacak ve N tane istemciye yollanacaksa, seri portu okuyan koddan 1 tane, bunun okudugunu istemcilere yollayacak koddan da N tane calismasi lazim.

O yuzden mesela arkaplanda calisacak bir program seri porttan okudugu degerleri bir dosyaya yazabilir, sicaklik da bu dosyayi okuyabilir.

Veya arkaplanda calisacak bir thread seri porttan okudugu degerleri bir list’e yazabilir, sicaklik da bu listeyi okuyabilir.

Ikinci engel ise Flask’in varsayilan modunun tek istemcili olmasi. Bu ayari degistirmek kolay—hatta Flask 1.0’dan itibaren gereksizmis.

Bu JSON degil. Art arda JSON’lardan olusan* bir JSON stream’e benziyor, ama o da degil. Elle JSON yaratacaksan format dokumentasyonunu okumani tavsiye ediyorum. Yaratmamani ve json kutuphanesini kullanmani tavsiye ediyorum.


*: Emin degilim. Protokol/format dokumentasyonu veya bir aciklama var mi? MIME type’in text/event-stream olmasi gerektigini soyleyen kaynak mutlaka soyluyordur bu formattaki datanin neye benzemesi gerektigini.

Bu ikisinin arasina 5 cumle girmesi beni baya zorladi.

Calismayan kodu gorebilir miyiz?

socket.io guzel bir kutuphane, python modulleri de kullanisli (python-socketio idi sanirim benim begendigim)

  • python kısmında "data:" yerine "veri:" yazıyorum (herhengibir kelime de olabilir. )
yield f"veri:{ntc_deger}\n\n"

html kısmında okumak için e.data yerine e.veri yazıyorum olmuyor;

<script>
     $(function () {
            var stream = new EventSource('/temp');
            stream.onmessage = function(e) {
            $("#veri").html(e.veri);
         };
     });
</script>

burada "data" 'nın özel bir anlamı mı var?

  • Arduinodan okuduğum verileri tek bir seferde gönderip html tarafında parçalıyabilir miyim?
    yani şu şekilde ;
yield f"data1:{değişken1}\n\n" +f"data2:{değişken2}b\n\n"+f"data3:{değişken3}b\n\n"

bu şekilde gönderip html taradında bunları parçalayıp istediğim gibi yazdırsam bu iş olucak gibi geliyor. Bir kaç deneme yaptım ama ilk maddede bahsettiğim sıkıntıyı aşmadan bunu yapamıyacağım gibi

  • text/event-stream kısmını koddan kaldırdığım zaman veriler (“127.0.0.1:500” kısmında) gözükmüyor. ilginç tarafı "127.0.0.1:500/temp" kısmındaki çıktıar.
    lokal1
    text/event-stream yazıldığında düzgün bir şekilde çalışıyor. Benim yorumum
    yield f"data:{ntc_deger}\n\n" kısmında json’a benzeyen yapıyı json’a çevirmek gibi bir işlem yapıyor olabilir.
  • Yorumlarınız için teşekkür ederim :slight_smile: