Italian Meccanismo per inviare nel web molti piccoli files, in successione ordinata

AlpVir

Well-Known Member
Licensed User
La mia app riceve ogni secondo da un sensore dei dati di varia natura; fra questi dati c'è anche l'ora esatta. L'app scrive questi dati su un file, dal nome sempre diverso. Ogni 5 minuti trasferisce questo file nel mio sito.

Essenzialmente
B4X:
NomeFile=N & ".txt"
size = File.Size(File.DirRootExternal, NomeFile)
InputStream1 = File.OpenInput(File.DirRootExternal, NomeFile)
req.InitializePost("http:// ... /ricevi.asp?Numero=" & N, InputStream1, size) 
HttpClient1.Execute(req, N)

Se il trasferimento ha avuto successo l'app cancella il file locale, ormai inutile.
Sinteticamente :
B4X:
Sub HttpClient1_ResponseSuccess (Response As HttpResponse, N As Int)
  InputStream1.Close
  File.delete(File.DirRootExternal,N & ".txt")
  N=N+1
end sub
Se il trasferimento non avviene con successo (assenza di rete ad esempio) il contatore N non viene incrementato e la scrittura del file locale avviene sempre sul medesimo file che è sempre lì, pronto ad essere inviato non appena le condizioni ridiventano valide. Il meccanismo, per quanto complicato, sembra essere funzionante (non ne ho trovato uno migliore, per la verità).

Lo script nel web "ricevi.asp" non fa altro che scrivere alla fine del'unico file "Totale.txt" quanto viene ricevuto.
B4X:
BinaryStream.SaveToFile server.MapPath("/Cartella") & "/" & strFileBase , 2    
        BinaryStream.close
       set BinaryStream = nothing
In pratica su internet si ha contezza (o meglio si dovrebbe averla) dell'output del sensore, con i suoi valori attuali e anche con quelli passati; con qualche minuto di ritardo ma questo è accettabile.

Sembrerebbe tutto OK ma (c'è sempre un ma) l'ordine delle "spedizioni" non è purtroppo progressivo (1, 2, 3, 4, ecc.) ma (esempio 3, 4, 5, 8, 6, 7, ecc.)
Ne consegue che il file Totale. txt non rispecchia i valori reali nel tempo.
Io credo che dipenda da meccanismi interni con cui viene effettuato l'invio, meccanismi che procedono paralleli; ossia se ne possono innescare più di uno e magari qualcuno (bontà sua) termina prima di un altro (magari perchè ha meno byte da processare, cosa possibile).

Forse potrei agire dal lato web effettuando un controllo prima di scrivere sul file Totale.txt ma vorrei vedere se c'è una possibilità di "riordinare le spedizioni" fin dalla loro origine (lato B4A quindi).

Come potrei agire per correggere questi errori ?
Grazie per l'attenzione.
 

Filippo

Expert
Licensed User
Lo script nel web "ricevi.asp" non fa altro che scrivere alla fine del'unico file "Totale.txt" quanto viene ricevuto.
E se invece del File "Totale.txt" usi un Database? Io penso che sia più comodo.
 

AlpVir

Well-Known Member
Licensed User
L'idea di usare un database era in me presente quando ho iniziato la scrittura di questa app. L'ho poi eliminata (o meglio trascurata) poichè mi sembrava più semplice la soluzione che ho poi adottato.
Si tratterebbe però di riscrivere parte dell'app e totalmente gli script lato web. Senza contare che incontrerei sicuramente una serie di problemi che al momento non mi sono ben evidenti.
Se non si trova un'altra soluzione ......
 

Star-Dust

Expert
Licensed User
Quella suggerita da Filippo é un ottima idea.
Lo devi usare solo per memorizzare locale i dati. Leggendo la chiave primaria, hai anche la scaletta di cosa devi inviare prima e cosa dopo visto che é un intero progressivo.
Dell'App devi solo cambiare il codice per salvare il file di testo e sostituirlo con un aggiunto a SQL.
E anche per eliminare i dati inviati o segnarli come inviati e lasciarli su SQL.

Non vedo perché debba cambiare gli script ASP del WEB.. t
 

AlpVir

Well-Known Member
Licensed User
Concordo con giudicare l'idea di Filippo praticabile, meritevole di attenzione; difatti sto già lavorando in tal senso.
Tuttavia non mi sembra che sia giusto il "devi inviare prima e cosa dopo visto" di Start-Dust. E' proprio nell'ordine dell'invio (che si ripercuote in un errato ordine di ricezione) che saltano fuori i problemi.
Quindi, al momento attuale, mi sembra che non si debba cambiare quasi nulla lato B4A mentre bisogna cambiare quasi tutto lato web, compresa la creazione di un db (che prima non c'era). Come ho detto sto vedendo se tutto ciò porta ad un risultato positivo.
Forse non era ben chiaro ma l'output finale (ciò che guardano gli utenti web) è appunto sul web; e qui le cose debbono essere ben ordinate.
 

Star-Dust

Expert
Licensed User
Intendevo che la chiave primaria numerica ti impedisce di sbagliare ordine di invio.
Mi sono espresso male.
 

AlpVir

Well-Known Member
Licensed User
Piccolo problema: i dati che devo trasmettere ogni 5 minuti sono dell'ordine delle centinaia di Byte e quindi non ci stanno in una singola query. Ergo: devo inviare come già facevo un stream binario (da trasformare in un file) e contemporaneamente una query (con pochi dat)i che li collega; memorizzo il contenuto dello stream (ossia del file) su un database sul web ed i giochi son fatti. Con conseguenti problemi di sincronizzazione fra file e query.
Ma ... meglio non vendere la pelle dell'orso prima di averlo ucciso.
N.B.: ho usato un vecchio proverbio. Mai ucciderei un orso (e qualsiasi altro animale)
 

Star-Dust

Expert
Licensed User
Neanche io ad eccezione di scarafaggi, blatte, topi, zanzare, avvocati e politici. :p
 

Filippo

Expert
Licensed User
Il db lo configurerei così:
Id primery key , n integer unique, stream blob

In questo modo non hai quasi niente da modificare in b4a.
 

sirjo66

Well-Known Member
Licensed User
buone le indicazioni che ti hanno dato,
a me però invece è venuto un altro dubbio:
se nel momento in cui stai inviando i dati al server il sensore invia dei dati alla tua app, ti trovi che contemporaneamente stai inviando i dati al server (e hai lo stream aperto) e ci stai anche scrivendo dentro a quello stream, non rischi così di perdere dei dati ??
Può essere questo che fa saltare l'invio ??
 

AlpVir

Well-Known Member
Licensed User
Sì , veramente utili che indicazioni che ho avuto, ma, aldilà di questo, mi è utile lo stimolo di proseguire nella realizzazione di questa app (non me l'ha ordinato il dottore di farlo: è solo una mia passione) dato dal supporto di questo forum.
Ritornando al punto, dopo aver modificato un po' la pagina asp da una prova fatta or ora ho riscontrato che i file dall'1 al 7 vengono inviati alla giusta cadenza. Poi il sistema sembra bloccarsi per un po' e quindi, in rapidissima successione, vengono inviati l'8, il 10, il 12, il 9 e l'11. Adesso non viene trasmesso nulla ed i file dal 13 al 25 sono da ancora inviare. Ho sospeso la prova, deluso.
Ritengo quindi di dover "inventare" un modo alternativo di inviare i file visto che quello da me utilizzato sembra essere deficitario, in questo specifico caso.
Il codice B4A da me utilizzato per spedire i file è riportato nel post #1.
A quale alternativa potrei ricorrere ?
Indago .....
@sirjo66 : non credo di dover correre questo pericolo. Io creo file sempre diversi. E' nella spedizione/ricezione non ordinata che saltano fuori i problemi.
Il problema è simile a quello, in un contesto del tutto diverso, che avevo già segnalato nel post "Disordine in un file INI" (https://www.b4x.com/android/forum/threads/disordine-in-un-file-ini.68463/)
EDIT: Adesso mi accorgo dell'ultimo disordine di spedizione: 58, 54, 27, 23 !!!
 
Last edited:

AlpVir

Well-Known Member
Licensed User
Risolto !
Ho adottato un diverso meccanismo di invio, HttpJob invece di HttpClient
Invece di :
B4X:
size = File.Size(File.DirRootExternal, PartNomeFileLog)
InputStream1 = File.OpenInput(File.DirRootExternal, PartNomeFileLog)
Parametri="N=" & NumParteTW
req.InitializePost("http://" & SitoMio & "/cartella/ricevi.asp?" & Parametri, InputStream1, size)  
HttpClient1.Execute(req, NumParteTW)
questo :
B4X:
Parametri="N=" & NumParteTW
HttpClient1.PostFile("http://" & sitomio & "/Cartella/ricevi.asp?" & Parametri,File.DirRootExternal,PartNomeFileLog)
Poi ho inserito il codice delle sub Sub HttpClient1_ResponseSuccess (Response As HttpResponse, TaskId As Int) e HttpClient1_ResponseError (Reason As String, StatusCode As Int, TaskId As Int) nella Sub JobDone (Job As HttpJob)
Non ha perso un colpo per 54 invii/ricezioni !
Grazie a tutti.
 

Star-Dust

Expert
Licensed User
In effetti, non avevo fatto caso, ma io uso sempre HttpJob. Bravo
 
Top