Italian Connessione bluetooth

StefanoTag

Active Member
Licensed User
Longtime User
Salve! Premetto che sono un principiante e quindi è possibilissimo che non riesca a spiegarmi bene o che possa dire delle cose poco sensate. Confido sulla vostra comprensione ;-)
Dispongo di cinque schedine elettroniche HC-06 che consentono la connessione con Android via bluetooth. Mediante le funzioni della libreria "Serial", volevo provare a connettermi con queste cinque schedine in "modo circolare" e cioè: connettermi alla prima, poi, a connessione completata, disconnettermi da essa e connettermi alla seconda e così via con quelle successive. La cosa più naturale mi è sembrata quella di fare un ciclo da 0 a 4 e usare "Serial1.Connect(...)" per la connessione e "Serial1.Disconnect" per la successiva disconnessione. Il problema però è che non so come intercettare la conclusione dell' "evento connessione" in modo da non disconnettere la schedina prima ancora che essa sia connessa. Mi spiego meglio: se, dentro il ciclo, tra il Serial1.Connect e il Serial1.Disconnect metto un tasto di attesa (il classico Msgbox...) in modo che l'utente attende fisicamente la conclusione della connessione, preme il tasto di attesa e quindi disconnette, tutto funziona bene...se però volessi fare il ciclo in modo automatico e cioè senza l'intervento umano che attenda fisicamente la conclusione della connessione e quindi tolgo il Msgbox... allora il giochino non funziona più perchè non riesco più a sincronizzare la disconnessione della schedina solo dopo che la connessione sia andata a buon fine...temo di aver scritto troppe parole senza essermi spiegato bene. Confido in qualche amico paziente e ringrazio in anticipo!
 

LucaMs

Expert
Licensed User
Longtime User
Non ho capito molto ma non per colpa tua, perché non uso questi "oggetti".

Comunque, normalmente in situazioni del genere si usa una variabile globale che conservi il numero della scheda attualmente connessa e aggiornarla nell'evento Connected.
Oppure usa un timer, non un ciclo.
 

StefanoTag

Active Member
Licensed User
Longtime User
Ti ringrazio del suggerimento...proverò sicuramente ad usare il timer (anche se non so come si fa ma...me lo studio). Il problema è che dovrei in qualche modo fermare l'esecuzione del codice finchè non si è positivamente conclusa la connessione, invece ho guardato in mille esempi ma non ho trovato il modo di farlo e B4A una volta che ha processato l'istruzione Serial1.connect(...) passa subito all'istruzione successiva senza pausa alcuna...
 

LucaMs

Expert
Licensed User
Longtime User
Ovviamente non so cosa devi fare esattamente, però penso a qualcosa del genere:

Globals
mScheda = 1

sub someName
Serial1.Connect
End sub

sub xxx_connected (...)
select case mScheda
case 1
faiQuesto
case 2
faiAltro
...



sub faiQuesto
...


sub faiAltro
 

StefanoTag

Active Member
Licensed User
Longtime User
Grazie per l'attenzione che mi dedichi.
I problemi sono due: il primo è che non so a priori se le schedine disponibili per la connessione sono proprio 5 o meno (alcune potrebbero essere spente) per questo inizialmente prevedevo la soluzione del ciclo for...next: prima facevo una ricerca delle connessioni disponibili (alcune schedine potrebbero essere spente) e solo dopo, il ciclo for...next mi consentiva di adattarmi al numero di schedine trovate accese, mentre il tuo suggerimento comporta una struttura statica che prescinde dal nr di connessioni disponibili al momento. Ma il problema più grosso, che mi ha portato a rivolgermi alla comunità, resta comunque e cioè, anche secondo la tua ipotesi, dopo che B4A ha eseguito la riga Serial1.Connect della sub someName, passa subito all'istruzione successiva mentre ancora il tentativo di connessione è ancora in corso e l'istruzione successiva prevederebbe proprio o la connessione alla schedina successiva o la disconnessione della schedina appena connessa. Ambedue le operazioni sono impraticabili mentre il processo di connessione è in corso. Anche l'ipotesi del timer è problematica in quanto nel bluetooth una connessione può avvenire dopo due secondi e magari la connessione successiva impiega moltissimo più tempo (la schedina è lontana o ci sono ostacoli intermedi o altro). Insomma...temo di essermi trovato davanti ad un problema al di sopra delle mie capacità :-(
Se intravedi altri suggerimenti li gradisco volentierissimo...
Ti ringrazio comunque
 

udg

Expert
Licensed User
Longtime User
Ciao a tutti.
Oggi dopo giorni (o settimane?) ho avuto tempo di ritornare sul forum e di leggere un po' di arretrati..eheh.

Qui mi sembra che la risposta di Luca sia già completa in funzione di quanto richiesto; forse va solo leggermente chiarita in merito all'utilizzo atteso.

La tattica suggerita è:
- lanci il Connect sulla prima schedina da testare e termini quella sub senza altre istruzioni relative alla conenssione.
- nell'evento Connected (Success as bool) utilizzi il boolean per capire se la schedina correntemente sotto esame si è connessa o meno. In caso di connessione, ne prendi nota (se ti serve) ed esegui la funzione Disconnect.
Poi incrementi di uno il numero di schedina (fino al suo max) e lanci un nuovo Connect (identico a quello della prima sub del primo lancio).
Quello che succede è che verrà chiamato nuovamente lo stesso evento (ma questa volta il risultato di Success si riferisce alla schedina ennesima).
Ammettendo che dopo un connect positivo hai la necessità di scambiare dei dati, allora dopo un Success positivo chiami la sub che ti interessa e la Disconenct la poni alla fine di tale sub così come un nuovo Connect per la successiva sceha.

Umberto
 

StefanoTag

Active Member
Licensed User
Longtime User
Ciao Umberto! Il tuo messaggio giunge come un massaggio cardiaco ad un elettrocardiogramma ormai quasi spento ;-) sto scherzando, ma ero e sono quasi vicino ad arrendermi. Purtroppo sia nel tuo suggerimento che in quello di LucaMs non riesco a capire come possa governare i passaggi che indicate, dal momento che avrei la necessità di organizzare un processo automatico e cioè senza l'intervento umano che possa decidere come e quando dare inizio ad un evento. Mi spiego meglio: in una stanza ho un numero imprecisato di schedine bluetooth e la mia necessità è quella di premere semplicemente un pulsante e di connettermi (e subito dopo disconnettermi) per brevi istanti ad ognuna di esse in modo ciclico e cioè dalla prima all'ultima (magari solo per vedere se sono accese e magari per vedere se trasmettono o meno qualche carattere). Io non riesco ad immaginare nulla di diverso da una struttura logica di questo tipo:

...
...
1. For i=0 To nDevices
2. Serial1.Connect(nr_mac)
3. ...fai qualcosa...
4. Serial1.Disconnect
5. Next i
...
...

Sub Serial1_Connected (Success AsBoolean)
If Success Then
ToastMessageShow("Connessione riuscita", False)
connected = True
Else
connected = False
ToastMessageShow("Connessione non riuscita", False).")
EndIf
End Sub

il problema è che B4A una volta processata la riga 2. passa subito alla 3. e poi alla 4. quando magari la connessione non è ancora stabilita. Non riesco a capire (ma sono certo che è un limite tutto mio, dovuto alla mie scarse conoscenze sugli oggetti e sugli eventi) come possa governare la connessione...sto per dire una sciocchezza, ma mi piacerebbe "congelare" l'esecuzione del codice sul rigo 2. finchè il Serial1.Connect non abbia avuto successo (o meno). Sia nel tuo suggerimento che in quello di LucaMs ci vedo la necessità della presenza dell'utente che possa decidere quando avviare o concludere la connessione alla schedina successiva, cosa che devo evitare.
Comunque ti ringrazio in ogni modo e cercherò di fare il possibile per capire meglio la tua traccia (...potresti indicarmi la sequenza a grandi linee del codice che mi suggerisci? chiedo troppo?)
Stefano
 

LucaMs

Expert
Licensed User
Longtime User
La questione è che quel "fai qualcosa" del punto 2 devi farlo eseguire (o lanciare, meglio ancora) dalla routine evento Sub Serial1_Connected.

Ad esempio (copiando il tuo codice):

B4X:
Sub Serial1_Connected (Success AsBoolean)
If Success Then
   SELECT CASE nr_mac_ATTUALE
          CASE XXX
               FaiQuesto <--- nome di routine
               nr_mac_ATTUALE = YYY
          CASE YYY
               FaiAltro   <--- nome di routine
               nr_mac_ATTUALE = ZZZ
      ...
    END SELECT
    connected = True
Else
connected = False
ToastMessageShow("Connessione non riuscita", False).")
EndIf
End Sub

nr_mac_ATTUALE sarà una variabile globale. Se necessario / più utile, puoi impostare il prossimo mac nella routine eseguita, anziché nella Select.
 

StefanoTag

Active Member
Licensed User
Longtime User
Probabilmente sono duro come una roccia, ma proprio non riesco a capire!
Anche se seguo la tua traccia, il mio problema resta inalterato e cioè:

B4X:
.......
For i=0 To nDevices
    Serial1.Connect(nr_mac)
    Serial1.Disconnect
Next i
.......

Sub Serial1_Connected (Success AsBoolean)
    If Success Then
        SELECTCASE nr_mac_ATTUALE
            CASE XXX
                FaiQuesto <--- nome di routine
                nr_mac_ATTUALE = YYY
            CASE YYY
                FaiAltro <--- nome di routine
                nr_mac_ATTUALE = ZZZ
         ENDSELECT
         connected = True
    Else
        connected = FalseToastMessageShow("Connessione non riuscita", False).")
    EndIf
End Sub

Però!!! ...quando B4A ha processato il rigo Serial1.Connect(nr_mac) MA SICURAMENTE ANCOR PRIMA CHE L' "EVENTO CONNESSIONE" SIA CONCLUSO (perchè il tentativo di connessione dura alcuni secondi!) e che quindi possa valutare la variabile globale Success nella struttura Select case, B4A passa "subito" al rigo successivo e cioè al Serial1.Disconnect...non è B4A aspetta di eseguire il rigo successivo dopo che la connessione sia definitivamente stabilita...boh...ripeto, forse devo ancora studiare un bel pò prima di pretendere di risolvere queste difficoltà.
Comunque...di nuovo...grazie se potrai rispondermi!
Stefano
 

LucaMs

Expert
Licensed User
Longtime User
Non preoccuparti, aumento soltanto la parcella :D.

Nel mio esempio io non userei un ciclo. Io avvierei la prima connessione:

(globals)
dim nr_mac_attuale

btnAvvia_Click
nr_mac_attuale = nr_mac_1
END SUB

e poi gestirei il tutto nella
Sub Serial1_Connected (Success AsBoolean)

facendo eseguire alcune routine diverse (FaiQuesto, FaiAltro, ...) a seconda del nr_mac_attuale (select case), al termine della esecuzione delle quali lancerei nuovamente la connessione (anche dall'interno delle routine, volendo) dopo aver cambiato il nr_mac_attuale.
 

StefanoTag

Active Member
Licensed User
Longtime User
...comincio piano piano a capire...potenza della condivisione!
Nonostante i miei 63 anni, mi sento un pò come uno dei miei studenti quando smette di corrugare la fronte e distende piano piano l'espressione...comincio piano piano a capire.
Resta però il fatto che la libreria Serial aveva un oggetto che consentiva di cercare e conoscere anticipatamente il numero di connessioni disponibili (da 0 a n) e dunque, subito dopo, con il ciclo for i=1 to n...next potevo accendere e spengere tante connessioni quante erano al momento disponibili, mentre una struttura fissa come quella suggerita nella Sub Serial1_Connected presuppone di sapere a priori e quindi inserire nel codice il numero dei SELECT CASE...o mi sbaglio ancora una volta?
...aspetto la parcella con animo religiosamente rassegnato :rolleyes:
Comunque, a parte le battute, un grazie sincero per davvero!
 

LucaMs

Expert
Licensed User
Longtime User
Puoi riempire un array con i mac disponibili e poi incrementare il puntatore, ad esempio:

Globals
mac_disp() = ...
mac_attuale = 0


nelle routine...

mac_attuale = mac_attuale + 1
if mac_attuale > mac_Disp.Lenght - 1 then
mac_attuale = 0
end if
Serial1.Connect(mac_disp(mac_attuale))

(che vuoi che siano 63 anni? La vita inizia a 40, quindi sei poco più che adolescente, no? :))
 

StefanoTag

Active Member
Licensed User
Longtime User
...arrivati a questo punto credo davvero ci siano tutti gli elementi per cucinare la pietanza.
Sinceramente non non mi è ancora chiarissimo l'intero processo, ma credo che i suggerimenti iniziali di Umberto e poi quelli di LucaMs possano essere sufficienti affinchè io mi metta al tavolino e svolga perbenino i miei compiti per casa.
A parte l'aspetto tecnico, ringrazio davvero chi dedica tempo e attenzione ai problemi altrui e auguro a me stesso di poter ricambiare presto questa disponibilità.
 

udg

Expert
Licensed User
Longtime User
Ciao,

da ex-teenager (molto ex) mi associo al commento di LucaMs.
Ricorda solo che la Disconnect va chiamata dopo che hai utilizzato la parte Success = True dell'evento Connected.
In pratica avresti:

1. In una sub a tua scelta (es. il click di un pulsante), Serial1.Connect (ma solo per la prima schedina da testare)
2. Evento Serial1.Connected (Success)
2.1 se Success è True, esegui ciò che ti serve (es. lettura dati) e poi Disconnect
2.2 se Success è False, ti segni che quella schedina non è attiva (se ti occorre saperlo)
2.3 istruzione Serial1.Connect su prossima schedina nella lista
3. Dopo che l'evento è stato così richiamato tante volte quante sono le schedine da testare, l'utente potrà ricominciare da capo premendo il tasto di inizio sequenza (punto 1) oppure terminare premendo il relativo tasto Exit.

udg
 

StefanoTag

Active Member
Licensed User
Longtime User
La perseveranza dell'ignoranza: tutto abbastanza chiaro anche se continuo ad avere dubbi sul punto 3. : "...dopo che l'evento è stato così richiamato tante volte quante sono le schedine da testare" ...il problema è che a priori non so quante siano le schedine da testare!!
Comunque purtroppo fino a domani non potrò fare delle prove al pc perchè sono fuori casa e quindi per ora mi limito solo a leggere i vs preziosi suggerimenti e ad immaginarmi come possano andare le cose.
grazie di nuovo!
 

StefanoTag

Active Member
Licensed User
Longtime User
Grazie per l'indicazione...i tutorial sul bluetooth disponibili in rete credo d'averli spulciati tutti, ma ognuno di essi si riferisce alla prima connessione disponibile e fin lì tutto ok...il problema nasce quando ho davanti n schedine bluetooth e voglio connettermi (e disconnettermi) con ognuna di esse, una dopo l'altra...
 
Top