Archive for gennaio 2022

Interpolazione dati stazione meteo

Posted on 2 gennaio 2022. Filed under: Senza categoria |

Buon anno cari lettori di questo blog. Come sapete ho una stazione meteo costruita con i fascicoli della De Agostini tra il 2008 e il 2010.

Il Datalogger raccoglie ogni 5 minuti i dati che gli arrivano dai vari sensori esterni.

Tuttavia succede che a causa dello scaricamento delle batterie, in invio, o in ricezione, alcuni dati siano, purtroppo, andati persi.

Ma se l’intervallo di dati mancanti è abbastanza breve, possiamo recuperarli per interpolazione.

Ho quindi sviluppato un piccolo programma in VB.NET per recuperare questi dati e cancellare il più possibile le celle bianche.

In questo articolo, vado quindi a descrivere come funziona questo programma, nel caso anche altri avessero avuto il mio stesso problema.

Apriamo Visual Studio 2019 e creiamo un nuovo progetto WPF, XAML (.NET Framework) e VB.NET.

Aggiungiamo poi la mappatura Entity Data Model (First Database), con origine dati a un server SqlServer.

Io ho sul Cloud questi dati.

Lo XAML è semplicemente un pulsante.

Nel code-behind mettiamo il codice di gestione del pulsante all’evento Click:

    Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
ritorna:
        Lista.Clear()
        Dim enti As New crystalweb_it_meteoEntities
        Dim numerovuoti As Integer = 0
        Dim uuu = (From hhh In enti.DataLog Select hhh.idLog, hhh.Ch1_Hum, hhh.Realtime Where idLog > 15749).ToList
        Dim ValoreInizialePrimaDellaSequenzaVuota As String
        Dim ValoreFinaleDopoLaSequenzaVuota As String
        Collezione.Source = (From hhh In enti.DataLog Select hhh.idLog, hhh.Ch1_Hum, hhh.Realtime).ToList
        For Each sss In uuu
            If sss.Ch1_Hum = "" Then
                Collezione.View.MoveCurrentTo(sss)
                idPrimoVuoto = sss.idLog
                Collezione.View.MoveCurrentToPrevious()
                ValoreInizialePrimaDellaSequenzaVuota = Collezione.View.CurrentItem.Ch1_Hum
                NumeroSpazivuoti = CercaNumeroSpaziVuotiConsecutivi()
                If NumeroSpazivuoti > 2 * 24 * 12 Then MessageBox.Show("Periodo troppo lungo senza dati, saltiamo l'interpolazione. Idlog=" & idPrimoVuoto) : Exit Sub
                ValoreFinaleDopoLaSequenzaVuota = CercaValoreFinaleDopoLaSequenzaVuota(idPrimoVuoto, NumeroSpazivuoti)
                Collezione.View.MoveCurrentTo(sss)
                Call CalcolaValoriNellaSequenzaVuota(idPrimoVuoto, NumeroSpazivuoti, ValoreInizialePrimaDellaSequenzaVuota, ValoreFinaleDopoLaSequenzaVuota)
                Call RegistraNelDBNuoviValori(idPrimoVuoto)
                GoTo ritorna
            End If
        Next
    End Sub

Come potete vedere, ho spezzettato vari segmenti di codice in base a quello che deve fare.

Come prima cosa dichiariamo variabili e oggetti:

Public Property idPrimoVuoto As Integer
Public Property NumeroSpazivuoti As Integer
Dim Collezione As New System.Windows.Data.CollectionViewSource
Dim Lista As New List(Of ListaDaAggiungere)

Facciamo una query per individuare il primo “buco”. Dobbiamo ora cercare l’ultimo buco della sequenza. Verifichiamo che la sequenza senza dati non sia troppo lunga.

Otteniamo quindi il valore iniziale e il valore finale.

Calcoliamo quindi l’interpolazione e quindi salviamo i dati sul database.

Il resto del codice è il seguente:

Private Sub RegistraNelDBNuoviValori(idPrimoVuoto As Integer)
    For Each zzz In Lista
        Dim rti As New crystalweb_it_meteoEntities
        Dim vol = rti.DataLog.First(Function(c) c.idLog = zzz.idDataLog)
        vol.Ch1_Hum = zzz.Umidita
        rti.SaveChanges()
    Next

End Sub

Private Sub CalcolaValoriNellaSequenzaVuota(idPrimoVuoto As Integer, NumeroSpazivuoti As Integer, ValoreInizialePrimaDellaSequenzaVuota As Integer, ValoreFinaleDopoLaSequenzaVuota As Integer)
    Dim diffe = ValoreFinaleDopoLaSequenzaVuota - ValoreInizialePrimaDellaSequenzaVuota
    Dim salto = diffe / (NumeroSpazivuoti + 1)
    Dim ValoreReale As Double = ValoreInizialePrimaDellaSequenzaVuota
    Dim ValoreArrotondato As Integer = ValoreReale
    For ty = 1 To NumeroSpazivuoti
        ValoreReale = ValoreReale + salto
        ValoreArrotondato = Math.Round(ValoreReale, 0)
        Lista.Add(New ListaDaAggiungere(Collezione.View.CurrentItem.idLog, ValoreArrotondato))
        Collezione.View.MoveCurrentToNext()
    Next
End Sub

Private Function CercaValoreFinaleDopoLaSequenzaVuota(idPrimoVuoto As Integer, numeroSpazivuoti As Integer) As String
    Dim enti As New crystalweb_it_meteoEntities
    Dim ccc = (From hhh In enti.DataLog Where hhh.idLog > (idPrimoVuoto - 1) Take (numeroSpazivuoti) + 1 Select hhh.idLog, hhh.Ch1_Hum, hhh.Realtime).ToList
    Dim ritorna As String
    ritorna = ccc.LastOrDefault.Ch1_Hum
    Return ritorna
End Function
Private Function CercaNumeroSpaziVuotiConsecutivi() As Integer
    Dim NumeroSpazivuoti As Integer = 0
ciclo:
Collezione.View.MoveCurrentToNext()
If Collezione.View.CurrentItem.Ch1_Hum = "" Then<br>NumeroSpazivuoti = NumeroSpazivuoti + 1
GoTo ciclo
Else
GoTo EsceFunzione
End If
EsceFunzione:
Return NumeroSpazivuoti
End Function
End Class
Class ListaDaAggiungere
Private _idDataLog As Integer
Private _Umidita As String
Public Sub New(ByVal idDataLog As Integer, ByVal Umidita As String)
    _idDataLog = idDataLog
    _Umidita = Umidita
End Sub
Public Property idDataLog As Integer
    Get
        Return _idDataLog
    End Get
    Set(value As Integer)
        _idDataLog = value
    End Set
End Property

Public Property Umidita As String
    Get
        Return _Umidita
    End Get
    Set(value As String)
        _Umidita = value
    End Set
End Property
End Class

Sicuramente ci saranno altri metodi per ottenere le interpolazioni, questo è il metodo al quale ho pensato.

Se avete pensato di scrivere il codice in modo differente, fatemi sapere.

Alla prossima.

Pubblicità
Leggi l'articolo intero | Make a Comment ( None so far )

Liked it here?
Why not try sites on the blogroll...