### # options for output format
hook_out_fmt <- "pdf"
### # specify knitr options
knitr::opts_chunk$set(echo = FALSE, results = 'asis')
devtools::load_all()
knitr::knit_hooks$set(conv.odg = rmddochelper::odg.graphics.conv.hook)
### # initialize section counter
robjSecEnum <- rqudocuhelper::SectionEnumerator$new()
### # init table of abbreviation
r6ob_abbrtable <- rmddochelper::R6ClassTableAbbrev$new()
r6ob_abbrtable$setColHeader(pvColHeader = c("Abkürzung","Bedeutung"))
#r6ob_abbrtable$setQuote(pbQuote = FALSE)
r6objDocStat <- rmddochelper::R6ClassDocuStatus$new()
r6objDocStat$setStatusColnames(psStatusColnames = c("Version", "Datum", "Wer","Status", "Projekt"))

\begin{flushright} \includegraphics[width=0.7\linewidth]{png/QualitasLogo.png} \end{flushright}

\fcolorbox{white}{white}{ \parbox[t]{1.0\linewidth}{ \centering \fontsize{12pt}{20pt}\selectfont % \vspace*{0.5cm} %

    \hfill Beschreibung Testphase

    \vspace*{0.5cm} 
}

}

\vspace*{0.5cm}

\fcolorbox{red}{white}{ \parbox[t]{1.0\linewidth}{ \centering \fontsize{25pt}{40pt}\selectfont %

    \vspace*{1.5cm}
Automatisierter Tierdatenaustausch

    \vspace*{1.5cm} % Space between the end of the title and the bottom of the grey box
}

}

\vspace*{1cm}

\begin{center} \includegraphics[width=\textwidth]{png/WordCloud.png} \end{center}

\vspace{5ex} {\centering \small \hfill \begin{tabular}{l} Peter von Rohr \ FB EDV, Qualitas AG \ Chamerstrasse 56, CH-6300 Zug \ \verb+http://www.qualitasag.ch+ \ \verb+peter.vonrohr@qualitasag.ch+
\end{tabular} }

\pagebreak

\tableofcontents

\pagebreak

r6objDocStat$set_current_status(psVersion = "0.0.901",
                                psStatus = "Erstellung",  
                                psProject = "ATDA-ASR")
r6objDocStat$set_current_status(psVersion = "0.0.902",
                                psStatus = "Einleitung",  
                                psProject = "ATDA-ASR")
r6objDocStat$set_current_status(psVersion = "0.0.903",
                                psStatus = "Beispiel Übertragung Milchmengendaten",  
                                psProject = "ATDA-ASR")
r6objDocStat$set_current_status(psVersion = "0.0.904",
                                psStatus = "Anfragen mit SoapUI",  
                                psProject = "ATDA-ASR")
r6objDocStat$set_current_status(psVersion = "0.0.905",
                                psStatus = "Verarbeitung der Daten",  
                                psProject = "ATDA-ASR")
r6objDocStat$set_current_status(psVersion = "0.0.906",
                                psStatus = "Erster Entwurf",  
                                psProject = "ATDA-ASR")
r6objDocStat$set_current_status(psVersion = "0.0.907",
                                psStatus = "Ergänzung der Tagesmilchberechnung",  
                                psProject = "ATDA-ASR")
r6objDocStat$set_current_status(psVersion = "0.0.908",
                                psStatus = "Vergleich Tagesmilch mit Milchwägung",  
                                psProject = "ATDA-ASR")
r6objDocStat$set_current_status(psVersion = "0.0.909",
                                psStatus = "Tagesmilch als Boxplots und Milchwägung als Punkte",  
                                psProject = "ATDA-ASR")
r6objDocStat$include_doc_stat(psTitle = "# Dokumentenstatus")

\pagebreak

Erklärung

Dieses Dokument beschreibt die Testphase im Projekt r r6ob_abbrtable$add_abbrev(psAbbrev = "ATDA-ASR", psMeaning = "Automatisierter Tierdatenaustausch der ASR"). Die Testphase umfasst alle Punkte des Projektplans bis und mit dem erfolgreichen Tierdatenaustausch von einem Testbetrieb in der Schweiz bis in die r r6ob_abbrtable$add_abbrev(psAbbrev = "ARGUS", psMeaning = "Datenbank der Zuchtorganisationen bei Qualitas").

Einleitung

Als primäres Ziel im Projektplan steht der Ersatz der manuellen Übertragung der Milchmengendaten durch eine automatisierte elektronische Übertragung. Die Testphase für das Projekt ist durch die erfolgreiche Übertragung der Milchmengendaten von einem Betrieb in der Schweiz bis zum Datenbanksystem ARGUS abgeschlossen. Durch diese Testphase konnte eine mögliche Umsetzung für die erfolgreiche Übertragung der Milchmengendaten gezeigt werden. Wie diese Umsetzung aussieht, soll in den folgenden Abschnitten beschrieben werden.

Umsetzung des Tierdatenaustauschs

Die hier beschriebene Umsetzung des automatisierten Tierdatenaustauschs basiert zu einem wichtigen Teil auf der Zusammenarbeit mit VSM. VSM ist ein holländische Informatikunternehmen, welches für verschiedenste Bereiche in der Nutztierhaltung Software entwickelt. Unter anderem hat VSM für alle wichtigen Melkanlagenanbieter Programme geschrieben, welche Daten aus den r r6ob_abbrtable$add_abbrev(psAbbrev = "ISM", psMeaning = "Informationssystem der Melkanlage", psShowText = "Informationssystemen der Melkanlagen") exportieren und an eine zentrale Datenbank übermitteln. Diese Programme werden als PlugIns bezeichnet. Aufgrund der Zusammenarbeit mit VSM war es uns möglich diese Plug-Ins für den Datenexport ab den ISM zu verwenden.

Testbetrieb

Das von VSM zur Verfügung gestellte PlugIn für die Melkanlagen von Lely wurde per Remote-Zugriff auf einem Testbetrieb in der Schweiz installiert (siehe nachfolgende Grafik). Während der Installation des PlugIns verbindet sich dieses mit dem Management-System der Melkanlage. Im Fall von Lely wird dieses System mit T4C bezeichnet. Sobald das PlugIn von T4C erkannt wurde, konnte das PlugIn eine Verbindung zur zentralen Datenbank bei VSM aufnehmen und einen ersten Datenaustausch starten. Nach anfänglichen Bereinigungen von fehlenden Tiernummern (basierend auf Nummern der r r6ob_abbrtable$add_abbrev(psAbbrev = "TVD", psMeaning = "Tierverkehrsdatenbank")) konnte die routine-mässige Übertragung von Milchmengendaten gestartet werden.

knitr::include_graphics(path = paste("InstallationTestbetrieb", hook_out_fmt, sep ="."))

Komponenten des Datenaustauschs

Im Projektplan wurde der automatisierte Tierdatenaustausch in drei Komponenten unterteilt.

  1. Export der Daten aus dem ISM
  2. Transfer der Daten zu ARGUS
  3. Import der Daten in die Datenbank

In der hier beschriebenen Umsetzung des Datenaustauschs wird die Komponente 2. Transfer der Daten zu ARGUS in zwei Schritte 2a und 2b unterteilt.

  1. Transfer der Daten zu ARGUS a. Das auf dem Testbetrieb installierte PlugIn von VSM übermittelt die Daten an die zentrale Datenbank bei VSM b. Von dieser Datenbank werden die Daten per Webservice abgeholt und in ARGUS importiert.

Webservice zwischen VSM und ARGUS

Der Webservice zwischen VSM und ARGUS basiert auf der sogenannten r r6ob_abbrtable$add_abbrev(psAbbrev = "REST", psMeaning = "Representational State Transfer", pbOut = FALSE) REST-Technologie. Ein REST-Webservice besteht aus einem Server und einem Client. Der Server läuft bei VSM und stellt gewisse Ressourcen zur Verfügung. Diese werden durch einen definierten r r6ob_abbrtable$add_abbrev(psAbbrev = "URL", psMeaning = "Unified Resource Locator") eindeutig bestimmt. Ruft ein Client eine gewisse Ressource auf, so erhält er als Antwort die durch die Ressource definierte Datenmenge als Antwort zurück.

Beispiel Milchmengen

Die Milchmengendaten vom REST-Server bei VSM werden zum Datenbanksystem ARGUS per Anfrage an den URL https://api-dev.agrobase.nl/dairy/api/EMM übertragen. Jede Anfrage an den REST-Server bei VSM ist spezifisch für einen bestimmten Betrieb. Deshalb müssen wir der Anfrage die Betriebs-Id mitgeben. Zur Autorisierung müssen wir der Anfrage zusätzlich zur Betriebs-Id einen Authentifizierungsschlüssel mitgeben. Der Server überprüft bei jeder Anfrage, ob der Authentifizierungsschlüssel zur Abfrage von Informationen auf dem entsprechenden Betrieb berechtigt ist. Als optionale Parameter können ein Anfangs- und ein Enddatum mitgegeben werden. Werden bei der Anfrage ein Anfangs- und ein Enddatum mitgeliefert, dann definieren diese eine bestimmte Zeitperiode. Das Resultat auf eine solche Anfrage enthält alle Milchmengendaten, welche in die definierte Zeitperiode fallen. Bei allen Anfragen ohne Anfangs- und Enddatum ist per default das Enddatum auf das aktuelle Datum und das Anfangsdatum auf drei Tage vor dem aktuellen Datum eingestellt.

Als Antwort bekommen wir alle Milchmengenrecords für den angegebenen Betrieb über die definierte Zeitperiode zurück.

Anfrage an EMM-Resource

Einzelne konkrete Anfragen an die EMM-Ressource auf dem REST-Server von VSM können mit dem graphischen Tool SoapUI gemacht werden. Diese Art der Erstellung einer Anfrage wird nur für Testzwecke verwendet und dient einzig der Veranschaulichung der Funktionsweise der Datenübertragung. Für den Routinebetrieb wird die hier manuell erstellte Anfrage an die Ressource automatisch mit einem Programm auf der Datenbank erstellt.

Der folgende Screenshot zeigt eine Anfrage an die Login-Ressource des REST-Servers. Als Input verlangt die Login-Ressource den Benutzernamen und das Passwort (siehe Pfeil 1). Als Antwort (siehe Pfeil 2) liefert der Server einen Record im sogenannten r r6ob_abbrtable$add_abbrev(psAbbrev = "JSON", psMeaning = "Java-Script Object Notation") Format zurück. In der Antwort ist der Authentifizierungsschlüssel enthalten, welchen wir für alle folgenden Anfragen verwenden werden.

knitr::include_graphics(path = paste("LoginResource", hook_out_fmt, sep ="."))

Zur Übertragung der Milchmengendaten müssen wir eine Anfrage an die EMM-Ressource erstellen. Als Input für die EMM-Anfrage übergeben wir einen JSON-Record mit dem (1), dem Benutzernamen (2), der BetriebsId (3), dem Start- (4) und dem Enddatum (5). Ein Beispiel für eine EMM-Anfrage ist im nachfolgenden Screenshot gezeigt.

knitr::include_graphics(path = paste("EmmResource", hook_out_fmt, sep ="."))

Die oben gezeigte EMM-Anfrage fordert die Übertragung aller Milchmengendaten für den Betrieb mit der Id "CH360830" für die Zeitspanne zwischen dem 01.01.2017 und dem 30.01.2017 an.

Resultat der EMM-Anfrage

Als Resultat erhalten wir dann einen ganzen Array von JSON-Records. Ein Ausschnitt der übermittelten Daten ist im folgenden Screenshot gezeigt.

knitr::include_graphics(path = paste("EmmDataResult", hook_out_fmt, sep ="."))

Ein einzelner JSON-Record besteht aus den Datenkomponenten zwischen zwei geschweiften Klammern {}. Jeder einzelne JSON-Record repräsentiert einen Besuch einer Kuh im Roboter. Die Kuh wird mit der "LifeNumber", welche der TVD-Nummer entspricht, identifiziert. Die Besuchsdauer der entsprechenden Kuh kann über die Zeitdifferenz zwischen "EndMilking" und "StartMilking bestimmt werden. Die letzte Datenkomponente in einem JSON-Record beinhaltet die Milchmenge.

Routinemässige Datenübertragung

Wie schon im vorherigen Abschnitt erwähnt ist die gezeigte Übertragungsart via SoapUI nicht für den routinemässigen Einsatz geeignet. Die routinemässe Datenübertragung umfasst nicht nur einen Betrieb sondern muss die Übertragung der Daten von vielen Betrieben sicherstellen. Deshalb kommt nur eine vollautomatische Umsetzung der Datenübertragung und der anschliessenden Verarbeitung in Frage.

Prozess der Datenübertragung

Auf dem Datenbanksystem ARGUS läuft täglich ein Batch-Job, welcher die Datenübertragung für die entsprechenden Betriebe startet. Von welchem Betrieb an einem gewissen Datum Daten übertragen werden, wird aufgrund der Tabelle T_ATDA_TRDATE entschieden. In dieser Tabelle ist für jeden Betrieb abgelegt, an welchem Datum die nächste Datenübertragung geplant ist. Für einen einzelnen Betrieb können Daten in verschiedenen Intervallen abgefragt werden. Wie häufig eine Datenabfrage für den gleichen Betrieb gemacht werden soll, muss getestet werden und ist unter Umständen von der Anzahl Betriebe abhängig, welche im Prozess der automatisierten Datenübertragung beteiligt sind.

Ablaufplanung der Datenübertragung

Wird ein neuer Betrieb in den Prozess der automatisierten Datenübertragung aufgenommen, so wird als erstes das zum Hersteller der Melkanlage passende PlugIn auf dem ISM installiert. Auf ARGUS wird der Betrieb mit dem Datum der ersten geplanten Datenübertragung in die Tabelle T_ATDA_TRDATE eingetragen.

Für eine allfällige Bereinigung der Tieridentifikation wird die Liste aller weiblichen Tiere, welche den aktuellen Standort auf dem neuen Betrieb haben, an VSM übermittelt. Bei VSM werden dann die Tier-Ids, welche vom Roboter übermittelt werden mit den Werten aus ARGUS verglichen.

Sobald alle Tier-Ids bereinigt sind, kann die automatisierte Datenübertragung gemäss dem geplanten Datum in T_ATDA_TRDATE gestartet werden. Nach jeder erfolgreichen Datenübertragung wird der Zeitpunkt für die nächste geplante Übertragung in die Tabelle T_ATDA_TRDATE eingetragen.

Verarbeitung der übertragenen Daten

Analog zu anderen Datenimportprozessen werden auch die von VSM erhaltenen Daten in einem zwei-schritt Verfahren importiert. Im einem ersten Schritt werden die Rohdaten, wie sie von VSM her kommen in eine Importtabelle abgelegt. Für die Milchmengendaten heisst diese Tabelle TI_ATDA_EMM. Dort werden die übertragenen Daten mit der entsprechenden Betriebsnummer abgelegt. Einige Beispiele für übertragene Datenrecords, wie sie in der Importtabelle TI_ATDA_EMM abgelegt werden, sind im folgenden Screenshot gezeigt.

knitr::include_graphics(path = paste("EmmImport", hook_out_fmt, sep ="."))

In einem zweiten Schritt werden die übertragenen Daten verarbeitet. Für die Milchmengendaten können wir die Milchmengen der einzelnen Besuche für jeden Tag aufaddieren und erhalten so für jede Kuh die Tagesmilchmenge. Zu Testzwecken sind die berechneten Tagesmilchmengen in der Tabelle T_ATDA_TMM abgelegt. Ein Ausschnitt aus dieser Tabelle ist im folgenden Screenshot gezeigt.

knitr::include_graphics(path = paste("AtdaTmm", hook_out_fmt, sep ="."))

Als repräsentativen Wert der Milchmenge pro Kuh für einen Monat können wir den Durchschnitt über alle Tagesmilchmengen errechnen.

Vergleich der übertragenen Daten mit Milchwägungen

Seit der Installation der Plug-Ins sind gut zwei Monate vergangen. Somit haben wir Tagesmilchmengen von zwei Monaten und zwei konventionelle Milchwägungen zur Verfügung, damit wir einen Vergleich anstellen können.

Übertragung der Milchmengendaten

In einem ersten Schritt werden die Milchmengendaten für die Monate Januar und Februar 2017 übertragen und verarbeitet. Aufgrund der übertragenen Rohdaten wurden für jede Kuh die Tagesmilchmenge berechnet. Die berechneten Tagesmilchmengen werden als Boxplots dargestellt und die Milchmengen werden durch gefüllte rote Punkte repräsentiert.

sAtdaTmmRda <- "atda_tmm.rda"
if (!file.exists(sAtdaTmmRda)){
  stop(" * ATDA TMM data not found, read it from database first\n")
} else {
  cat(" * Load data from file ...\n")
  load(file = sAtdaTmmRda)
}
### # get dimensions of data to check
dim(dfResult)

### # extract all cows from dataframe
#suppressPackageStartupMessages(require(dplyr))

### # extract data for Month 01
sMonthNr <- "01"
tdfResult01 <- AtdaAsrProjectTestFinalDocu::tdfGetTmmPerMonth(pdfResult = dfResult,
                                                              psMonth    = sMonthNr)

### # control milk yield
sControlMilkYieldRda <- paste0("con_my_2017",sMonthNr, ".rda")
if (!file.exists(sControlMilkYieldRda)){
  stop(" * No control milk yield data found, read it from DB first\n")
} else {
  load(file = sControlMilkYieldRda)
}
### # get the tbl_df with control milk yields
tdfControlMilkYield <- AtdaAsrProjectTestFinalDocu::tdfGetControlMilkYield(pdfControlMilkYield = dfControlMilkYield201701,
                                              pdfResult           = dfResult)

In der nachfolgenden Grafik werden die TVD-Nummern der Kühe durch fortlaufende Nummern ersetzt. Die folgende Tabelle gibt die Zuordnung zwischen Kuh-Nummern und TVD-Nummern der Kühe.

nNrRowsPerPage <- 36
vecTmmLifeNr <- vecGetTmmLifeNr(pdfResult = dfResult)
nNrCowsTmm <- length(vecTmmLifeNr)
nNrRounds <- floor(nNrCowsTmm/nNrRowsPerPage)
lstCowNr <- NULL
for (i in 1:nNrRounds){
  lstCurNr <- list(Knr = as.character(c(((i-1)*nNrRowsPerPage + 1):(i*nNrRowsPerPage))),
                   Tnr = vecTmmLifeNr[((i-1)*nNrRowsPerPage + 1):(i*nNrRowsPerPage)])
  names(lstCurNr) <- sapply(c("Kuhnummer","TVDNummer"), function(x) paste0(x,i))
  if (is.null(lstCowNr)){
    lstCowNr <- lstCurNr
  } else {
    lstCowNr <- c(lstCowNr, lstCurNr)
  }
}
### # add remainder
if (i*nNrRowsPerPage < nNrCowsTmm){
  vecEmptyRows <- rep("", (nNrRowsPerPage-nNrCowsTmm+i*nNrRowsPerPage))
  lstCurNr <- list(Knr = c(as.character(c((i*nNrRowsPerPage + 1):(nNrCowsTmm))), vecEmptyRows),
                   Tnr = c(vecTmmLifeNr[(i*nNrRowsPerPage + 1):(nNrCowsTmm)], vecEmptyRows))
  names(lstCurNr) <- sapply(c("Kuhnummer","TVDNummer"), function(x) paste0(x,(i+1)))
  lstCowNr <- c(lstCowNr, lstCurNr)
}

dfCowNumber <- as.data.frame(lstCowNr)
knitr::kable(dfCowNumber)
### # create boxplots
bpAtmmM01 <- ggp2bpGetBoxPlotAtmm(ptdfResult = tdfResult01, 
                                  psMonthNr = sMonthNr,
                                  ptdfControlMilkYield = tdfControlMilkYield)
bpAtmmM01
### # same for month 2
sMonthNr <- "02"
tdfResult02 <- tdfGetTmmPerMonth(pdfResult = dfResult,
                                 psMonth   = sMonthNr)

sControlMilkYieldRda <- paste0("con_my_2017",sMonthNr, ".rda")
if (!file.exists(sControlMilkYieldRda)){
  stop(" * No control milk yield data found, read it from DB first\n")
} else {
  load(file = sControlMilkYieldRda)
}
### # get the tbl_df with control milk yields
tdfControlMilkYield <- tdfGetControlMilkYield(pdfControlMilkYield = dfControlMilkYield201702,
                                              pdfResult           = dfResult)

bpAtmmM02 <- ggp2bpGetBoxPlotAtmm(ptdfResult = tdfResult02, 
                                  psMonthNr = sMonthNr,
                                  ptdfControlMilkYield = tdfControlMilkYield)
bpAtmmM02

Erklärung der Boxplots

Ein Boxplot ist ein Diagramm, welches zur grafischen Darstellung von Datenverteilungen verwendet wird. Die Bedeutung der Bestandteile des Boxplots werden in der nachfolgenden Grafik erklärt.

knitr::include_graphics(path = paste("BoxplotMeaning", hook_out_fmt, sep ="."))

Ein Boxplot besteht aus einem Rechteck (Box) und zwei Linien, welche das Rechteck verlängern. Die Linien heissen "Whisker". Der Strich innerhalb der Box repräsentiert den Median der Datenverteilung.

Die Breite der Box, welche als r r6ob_abbrtable$add_abbrev(psAbbrev = "IQR", psMeaning = "Inter-Quartil-Range") bezeichnet wird, ist so definiert, dass die mittleren 50% der Daten innerhalb der Box liegen. Somit steht die linke Begrenzungsseite der Box am unteren Quartil, d.h. 25% der Daten liegen links ausserhalb der Box. Die rechte Begrenzungsseite der Box steht am oberen Quartil, d.h. 25% der Daten liegen rechts ausserhalb der Box.

Die oberen und unteren Whiskers reichen bis zum Maximum oder zum Minimum der Daten, vorausgesetzt die Entfernung der Extrema von den Quartilen ist kleiner als $1.5 * IQR$. Sind die Extrema zu weit von den Quartilen entfernt, werden diese als einzelne Punkte (Ausreisser) dargestellt.

\pagebreak

if (!r6ob_abbrtable$is_empty_abbr())
  r6ob_abbrtable$writeToTsvFile()
r6ob_abbrtable$include_abbr_table(psAbbrTitle = "# Abkürzungen")


pvrqualitasag/AtdaAsrProjectTestFinalDocu documentation built on May 26, 2019, 11:34 a.m.