Topic: Comunicazione bluetooth  (Letto 142 volte)

0 Utenti e 1 Visitatore stanno visualizzando questo topic.

Offline bigpix

  • python unicellularis
  • *
  • Post: 3
  • Punti reputazione: 0
    • Mostra profilo
Comunicazione bluetooth
« il: Aprile 29, 2020, 11:07 »
Ciao,
sto provando a testare una comunicazione tra un'applicazione android e un raspberry pi3.
L'obiettivo è creare un file json che venga letto e scritto sia dall'applicazione android via bluetooth che da un touch screen, ed entrambe le interfacce dovrebbero auto-aggiornarsi.
Per testare questa cosa ho pensato di creare due thread diversi, ma ho subito notato un problema: il thread che gestiva il bluetooth inviava dati solo dopo aver letto dei dati in ricezione (io come detto vorrei che inviasse ciclicamente i dati del file json perchè potrebbero essere stati modificati dal touch screeen)
Avendo scoperto che la procedura si bloccava sul " client_socket.recv(1024) " ho creato un altro thread che per i fatti suoi aspetta che arrivi qualcosa per scriverlo. Nel frattempo io vado avanti a leggere e ad inviare.
Questo è il codice:

import bluetooth
import json
import time
from threading import Thread
import threading
lock=threading.Lock()
BtOk = False
server_socket=bluetooth.BluetoothSocket( bluetooth.RFCOMM )
port = 1
server_socket.bind(('',port))
server_socket.listen(1)
client_socket,address = server_socket.accept()   

BtOk= True
   
def thread1():     
    while 1:
        time.sleep (1)
       
        lock.acquire()
        with open("ProvaJson2.json")as JsonFile:
            DataStringInvio=json.load(JsonFile)
            DataStringInvioBt= str(DataStringInvio)+"\n"
        client_socket.send(DataStringInvioBt)
        lock.release()
 
    client_socket.close()
    server_socket.close()
 
def thread2():   
    i=0
    while 1:   
            time.sleep(3)
            with open("ProvaJson2.json")as JsonFile:
                Stringa=json.load(JsonFile)
            print("letto:")
            print(Stringa)
            print("")
            print("nuovo:")
            i+=1
            time.sleep(3)
            NomeInput = "miu"+ str(i)
            LingInput = "bas"+ str(i)
            lock.acquire()
            ManualDict = {"nome":NomeInput,"linguaggio":LingInput}
            print (ManualDict)
            with open("ProvaJson2.json","w")as JsonFile:
                json.dump(ManualDict,JsonFile)
            lock.release()
               
def thread3():
    while 1:
        data = client_socket.recv(1024)
            #if not data:
        lock.acquire()            #break
        DataStringBt = data.decode()
        DataDict = json.loads(DataStringBt)
        with open("ProvaJson2.json","w")as JsonFile:
                json.dump(DataDict,JsonFile)
        lock.release()
       
t1 = Thread(target=thread1)
t2 = Thread(target=thread2)
t3 = Thread(target=thread3)

t3.start()
t2.start()
t1.start()

Il programma funziona, ma con una grossa limitazione: se non attivo la connessione bluetooth non parte neanche il secondo thread che invece dovrebbe funzionare per i fatti suoi.
Ho provato diverse soluzioni, ma credo che il problema stia nel capire perchè la procedura si fermi sul recv e finche non arriva qualcosa non si schioda da lì!
Pensavo di poter fare un controllo condizionale sul fatto che fosse vuoto, ma non funziona.
Qualche idea?
Grazie

Offline RicPol

  • python sapiens sapiens
  • ******
  • Post: 3.062
  • Punti reputazione: 9
    • Mostra profilo
Re:Comunicazione bluetooth
« Risposta #1 il: Maggio 08, 2020, 14:43 »
Mi ricordo molto vagamente che c'era già stato qualcuno che voleva "testare" un'applicazione multiprocessing con i thread... e mi sembra che avessi risposto qualcosa come, ma che te ne fai dei thread quando comunque non sarà l'architettura che potrai usare nella tua applicazione reale... piuttosto fatti due processi separati e testa la comunicazione tra quelli... che almeno è la cosa che dovrai fare dopo...

Comunque, non ho capito bene che cosa devi fare, ma in ogni caso recv() è bloccante, certo. Almeno... il tuo socket è messo a disposizione da una libreria che non conosco, quindi dovresti leggerti la documentazione di quella libreria e studiare un po' la cosa... ma suppongo che il loro socket derivi pur sempre da "socket" della libreria standard, e in quelli recv() è bloccante. Puoi senz'altro usare socket non-bloccanti, ma non saprei se *quei* socket possono essere resi non-bloccanti. Per prima cosa dovresti capire bene come si usano i socket della libreria standard, partendo da qui https://docs.python.org/3/howto/sockets.html
Poi dovresti scriverti qualche progammino di prova, con due processi (lascia stare i thread) che comunicano tra loro con socket normali, quelli della libreria standard, per vedere come funziona. A quel punto puoi riprovare con il tuo caso specifico e i socket della tua libreria, e vedere se riesci ad adattare il meccanismo.

Offline bigpix

  • python unicellularis
  • *
  • Post: 3
  • Punti reputazione: 0
    • Mostra profilo
Re:Comunicazione bluetooth
« Risposta #2 il: Maggio 12, 2020, 21:15 »
Ciao,
grazie della risposta.
Immagino che tu abbia associato la mia richiesta a qualcos'altro, ma io sono nuovo e questi sono i miei primi post quindi ti spiego cosa vorrei fare e perchè sono arrivato ai thread...
Vorrei utilizzare il raspberry per una applicazione elettronica.
Per gestire questa applicazione ho bisogno di alcune variabili che vengono influenzate dal processo e altre variabili di input che vengono modificate dall'utente.
L'utente deve avere la possibilita in qualsiasi momento e in tempo reale di poter leggere e scrivere queste variabili in tre modi diversi: un touch screen, un'applicazione bluetooth e accedendo ad un web server interno al raspberry.
Per quest'ultima cosa mi è stato suggerito di implementare un file json da leggere e scrivere da ognuna delle tre interfacce, cosa che ho fatto e che funziona bene.
A questo punto stavo testando la "contemporaneità" delle tre interfacce e, per fare alcune prove, ho imbastito il codice che hai visto sopra: ho simulato la modifica periodica di alcuni parametri e dall'applicazione bluetooth voglio poter vedere le variazioni in "real time" e, parimenti, fare la stessa cosa  modificando i parametri dall'app collegata in bluetooth.
Questa "contemporaneità" ho pensato di ottenerla con il multithreading.
Conscio dei miei limiti ho cercato di capire il funzionamento dei socket in generale (sono approdato qui attraverso un link contenuto in una guida sui socket) ed in particolare di quello bluetooth sul quale mi ero concentrato ma, come hai accennato il recv() sembra che sia bloccante e quindi al momento l'ho risolta così:
ho impostato l'app (android) in modo che quando riceve un dato lo rispedisce indietro e sblocca il processo che è fermo aspettando qualcosa dal recv().
Ovviamente se nel frattempo ho scritto qualcosa di diverso nell'app, rimanda indietro il dato modificato.
Così funziona, non so se è bello o se si può fare in maniera migliore...sono tutt'orecchi!!!
In questo momento sto facendo solo delle prove per vedere se "l'impalcatura" regge.

Grazie
A presto  :) :)

Offline RicPol

  • python sapiens sapiens
  • ******
  • Post: 3.062
  • Punti reputazione: 9
    • Mostra profilo
Re:Comunicazione bluetooth
« Risposta #3 il: Maggio 13, 2020, 12:49 »
Mah, continua a valere quello che ho già scritto. Primo, nell'applicazione reale si tratterà di processi, non di thread. Quindi non so fino a che punto vale la pena scrivere un proof of concept coi thread... piuttosto, scrivi un proof of concept coi processi. Secondo, se non usi qualche astrazione di tipo superiore (non so, asyncio per dire), questa è programmazione di basso livello coi socket: parti dal socket howto della documentazione di python. Terzo, certo tipicamente recv è bloccante. Se non lo vuoi bloccante, usa un socket non bloccante. Quarto, usare un file come strumento di comunicazione tra thread è notoriamente una cattiva idea, perché sei in balia delle primitive di locking del sistema operativo sottostante (e notoriamente Posix non fa queste cose proprio benissimo, diciamo). Certo, tu circondi l'accesso al file con un bel lock... e questo va anche bene... ma d'altra parte non hai considerato che anche lock.acquire() è bloccante? Ovviamente nell'esempio giocattolo che ti sei fatto non puoi tanto rendertene conto, ma tecnicamente... acquisire un lock è comunque bloccante. In genere la soluzione che si preferisce è usare un oggetto intrinsecamente thread-safe, tipicamente una Queue.

Offline bigpix

  • python unicellularis
  • *
  • Post: 3
  • Punti reputazione: 0
    • Mostra profilo
Re:Comunicazione bluetooth
« Risposta #4 il: Maggio 13, 2020, 18:54 »
WOW ! , il 70 % di quello che hai scritto per me è arabo, quindi ti ringrazio e mi studio una ad una le indicazioni che mi hai dato e vediamo se ne ricavo qualcosa di buono.
Grazie :ok: