Affichage des articles dont le libellé est update. Afficher tous les articles
Affichage des articles dont le libellé est update. Afficher tous les articles

13/03/2016

big data facile - une application pour insérer des données sur un serveur Fuseki

[ cet article fait partie de la série RDF FACILE - Mon petit BigData ]

Repartons de l'application Android faite avec AppInventor pour visualiser les informations de notre serveur Fuseki comme nous l'avons construite ici : http://smag0.blogspot.fr/2016/03/bigdata-facile-une-application-android.html

Si vous avez tout bien suivi, vous avez créé un écran "Saisie", et nous avons sur cette page http://smag0.blogspot.fr/2016/03/un-serveur-fuseki-rdf-bigdata-sur.html  une piste pour construire la requete que nous devons envoyer pour insérer des données :

PREFIX rdf:   <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs:   <http://www.w3.org/2000/01/rdf-schema#>
PREFIX ex:   <http://example.org/>
PREFIX zoo:   <http://example.org/zoo/>
PREFIX owl: <http://www.w3.org/2002/07/owl#>


INSERT DATA {
GRAPH <http://example/bookStore>
{
ex:dog1    rdf:type         ex:animal .
ex:cat1    rdf:type         ex:cat .
ex:cat     rdfs:subClassOf  ex:animal .
zoo:host   rdfs:range       ex:animal .
ex:zoo1    zoo:host         ex:cat2 .
ex:cat3    owl:sameAs       ex:cat2 .
}
}

Je rappelle que pour les flémards, le code de la première partie (récupération des données) est accessible ici : http://ai2.appinventor.mit.edu/?galleryId=4993525195735040

Les données au format RDF se présentent sous la forme de triplets, si c'est pas clair pour toi, jette un oeil là https://fr.wikipedia.org/wiki/Resource_Description_Framework .
Nous avons donc besoin de trois champs.
Dans App Inventor, passez sur l'écran "Saisie" que nous avons créé dans le tuto précédent, et insérez trois zone de texte ( on va repasser en english, car la traduction en français pose quelques problèmes lors des tests...)
Comme pour la page "Visualisation", insérons un bouton retour accueil, avec le même code que précedemment.
Ainsi que trois zones de texte, profitez-en pour les renommer, passer leur "width" à "Fill Parent" et mettre des Hint selon le contenu que l'on attend : Sujet, propriete, Objet... ça sera plus parlant pour la suite.
Oui , je sais , Sujet et Objet ont droit à la majuscule, mais pas "propriété", c'est un peu comme ça en RDF... alors gardons cette norme, ça ne peut pas faire de mal...
N'oubliez pas aussi d'ajouter un composant Web1 que vous trouverez dans Connectivity, c'est lui qui va nous faire la requête POST, mais pour ça, il va falloir lui donner la bonne requête.
Complétez par une nouvelle zone de texte, que l'on nommera "Résultat", avec Height et Width à "Fill Parent, et "Hint" à "Attente resultat".



Passons maintenant à l'envers du décor, en cliquant sur le bouton "Blocks".
Pour faire au plus simple, considérons que les trois éléments que nous allons insérer avec notre première requête, ont tous le même préfixe :  PREFIX ex:   <http://example.org/>.

Notre application devra donc envoyer la requete :

PREFIX ex:   <http://example.org/>

INSERT DATA {
GRAPH <http://example/bookStore>
{
ex:Sujet    ex:propriete         ex:Objet .
}
}

Et pour ce faire, nous aurons besoin de récupérer les valeurs qui se trouvent dans nos trois zones de texte.

Commençons par la ligne où se trouve notre triplet (ex:Sujet    ex:propriete         ex:Objet .)
Les quelques blocs suivants devraient nous faire apparaître notre ligne dans la zone de texte "Résultat" :
On initialise nos variables Sujet, propriete, Objet, ainsi que la requeteUpdate.
Au click du bouton, on concatène la chaîne "ex:" avec chacune des valeurs récupérées dans nos trois textBox.
On construit ensuite notre requeteUpdate, en joignant nos trois variables, en les séparant d'un espace .
Astuce : pour ajouter une nouvelle ligne dans un "join", cliquez sur la roue sur fond bleu.
Attention, bien mettre un espace dans les deux blocs entre "get  global Sujet " et "get global propriete" ainsi que entre les blocs "get global propriete" et "get global Objet" .
On termine notre "set global requeteUpdate" par un bloc texte qui contient un espace et un point " .", c'est ainsi qu'on termine un triplet simple en rdf.
Et pour finir, on affiche notre "global requeteUpdate" dans la zone texte "Resultat"



Pour tester, utilisez l'appli " compagnon App Inventor", et entrez un triplet rdf, par exemple :
dans Sujet : David
dans propriété : type
et dans Objet : Personne
cliquez ensuite sur "Envoyer"

Si tout se passe bien, vous devriez immédiatement voir apparaître :
ex:David ex:type ex:Personne . 
Si c'est le cas, BRAVO ! on y est presque, il suffit juste d'envoyer tout ça au serveur (http://rdf-smag0.rhcloud.com/) mais avant de pouvoir lui demander d'intégrer ces information, nous devons y mettre les formes...

L'enrobage sauvage...
Pour voir si ça marche, on va juste englober notre triplet par le strict nécessaire :
Avant notre triplet, on va mettre :
PREFIX ex:   <http://example.org/>
INSERT DATA {
GRAPH <http://example/bookStore>
{
et à près, on fermera par
}
}

C'est pas très orthodoxe, mais le principal, c'est de tester si ça marche, alors on va la faire simple, on aura tout le loisir de faire joli ensuite.
Attention.... POF :
-  une variable "debutRequete" avec comme valeur :
PREFIX ex:   <http://example.org/> INSERT DATA { GRAPH <http://example/bookStore> 
- et une variable "finRequete" avec comme valeur :
}}

Bouhhh ! c'est pas bien !!!



On complète ensuite notre "requeteUpdate", en ajoutant deux blocs :
 "get global debutRequete" (avant "get global Sujet" )
et "get global finRequete" (après le bloc " .").

Votre code devrait maintenant ressembler à ceci :


et le texte qui s'affiche dans la zone de texte "Resultat" à ceci :
PREFIX ex:   <http://example.org/> INSERT DATA { GRAPH <http://example/bookStore> ex:David ex:type ex:Personne . }}


Nous avons maintenant nos données, que nous avons mis dans une enveloppe.
Le destinataire, c'est le serveur http://rdf-smag0.rhcloud.com/, on va même être plus précis, car sa boite au lettre se trouve à l'adresse : http://rdf-smag0.rhcloud.com/update, et il va falloir envoyer à cette adresse, une requête de type POST.
Il ne reste plus qu'à mettre en place le transporteur... et c'est là qu'intervient notre composant "WEB1" que nous avions inséré au tout début de ce post...

Créons maintenant une nouvelle variable que nous nommerons "endpointUpdate" et donnons-lui la valeur de l'adresse de la boite aux lettres de notre serveur "http://rdf-smag0.rhcloud.com/ds/update"

Ensuite, on sort le bloc "set Resultat.Text" du bloc "When EnvoyerBouton.click", et à la place, on y met deux blocs : "set Web1.Url" et "Call Web1.PostText" qui vont respectivement donner à WEB1 l'adresse de destination, et la valeur du paramètre "update=".

Et bien voilà, le plus dur est fait... pas insurmontable, quand même...
juste une toute petite dernière chose, pour être sûr du résultat...
Ajouter un bloc "When Web1.gotText" qui s'exécutera dès que la réponse du serveur arrivera... avec à l'intérieur, l'affichage dans la zone de texte "Résultat", de la valeur "reponseContent".



Lorsque vous testez maintenant votre appli, ( MIT compagnon) et que vous cliquez sur "Envoyer", vous devriez voir apparaitre dans la zone "Résultat", la ligne suivante :
<html><head></head><body><h1>Success</h1><p>Update succeeded </p></body></html>


et c'est plutôt bon signe : <h1>Success</h1><p>Update succeeded </p>

Pour vérifier, repassez sur l'écran d'accueil après avoir ajouté le code du bouton "retour Accueil", puis sur l'écran "Visualisation" comme nous l'avons implémenté ici http://smag0.blogspot.fr/2016/03/bigdata-facile-une-application-android.html
mais c'est plus joli ici http://rdf-smag0.rhcloud.com/ds/query?query=select+*+where+%7B%3Fs+%3Fp+%3Fo%7D&output=text , car pour l'instant dans la visualisation, on n'a pas formaté le résultat...


Si t'es arrivé jusque là, t'es plus un flemmard, alors cadeau : le code sur AppInventor : http://ai2.appinventor.mit.edu/?galleryId=5233374557372416

Les retours sont les bienvenus, si j'ai fait des boulettes, ou si je ne suis pas clair. Pour rappel : ceux qui veulent s'installer leur propre serveur peuvent le faire en local (en téléchargeant Apache Fuseki ou sur le cloud , par exemple Openshift en récupérant le source ici : https://github.com/scenaristeur/smag0-fuseki-rdf-openshift



[ cet article fait partie de la série RDF FACILE - Mon petit BigData ]



11/03/2016

Un serveur fuseki RDF bigdata sur openshift

[ cet article fait partie de la série RDF FACILE - Mon petit BigData ]


serveur de test : http://rdf-smag0.rhcloud.com/
- choisissez "Control Panel",
-  puis le Dataset "/ds",
- cliquez sur select,
-  un formulaire apparait, ou vous pouvez insérer des données (SPARQL Update) ou executer une requete (SPARQL Query))

repo github : https://github.com/scenaristeur/smag0-fuseki-rdf-openshift
(des problèmes de socket lorsque l'on tente d'utiliser la dernière version de Fuseki, donc on reste pour l'instant avec l'ancienne)


test pour insérer des données :


PREFIX rdf:   <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs:   <http://www.w3.org/2000/01/rdf-schema#>
PREFIX ex:   <http://example.org/>
PREFIX zoo:   <http://example.org/zoo/>
PREFIX owl: <http://www.w3.org/2002/07/owl#>


INSERT DATA {
GRAPH <http://example/bookStore>
{
ex:dog1    rdf:type         ex:animal .
ex:cat1    rdf:type         ex:cat .
ex:cat     rdfs:subClassOf  ex:animal .
zoo:host   rdfs:range       ex:animal .
ex:zoo1    zoo:host         ex:cat2 .
ex:cat3    owl:sameAs       ex:cat2 .
}
}



--> remplacez  le bloc  :
ex:dog1    rdf:type         ex:animal .
ex:cat1    rdf:type         ex:cat .
ex:cat     rdfs:subClassOf  ex:animal .
zoo:host   rdfs:range       ex:animal .
ex:zoo1    zoo:host         ex:cat2 .
ex:cat3    owl:sameAs       ex:cat2 .

par les triplets que vous souhaitez ajouter



test pour récupérer des données : 

select * where {?s ?p ?o}

ce qui nous donne pour une requete GET , et des données de retour au format JSON,
 par exemple pour une appli
 avec APP INVENTOR ou PROCESSING,
ou encore depuis une page web en javascript  l'url :

http://rdf-smag0.rhcloud.com/ds/query?query=select+*+where+%7B%3Fs+%3Fp+%3Fo%7D&output=json

Par exemple, on peut utiliser App Inventor pour récupérer les données : http://smag0.blogspot.fr/2016/03/bigdata-facile-une-application-android.html

ensuite, complétez-là pour mettre à jour les données du serveur :
http://smag0.blogspot.fr/2016/03/big-data-facile-une-application-pour.html


[ cet article fait partie de la série RDF FACILE - Mon petit BigData ]



07/02/2016

Insert d'informations sur un serveur Fuseki, post

1. installer fuseki pour qu'il soit accessible sur http://127.0.0.1:3030

2. creer un fichier smag.html  dans le repertoire webapp du serveur fuseki, avec le contenu qui suit et y accéder via http://127.0.0.1:3030/smag.html


<!DOCTYPE html>
<!-- https://github.com/scenaristeur/coolitude4/blob/master/Coolitude4/src/org/favedave/smag0/coolitude4/projet/Projet.java -->

<html>
    <body>
  
  
    </body>
   <script>
var debutRequete = "INSERT DATA { GRAPH <http://example/bookStore> {";
var finRequete = "} }";
var data="test";

</script>


<script>
function post(path, params, method) {
    method = method || "post"; // Set method to post by default if not specified.

    // The rest of this code assumes you are not using a library.
    // It can be made less wordy if you use one.
    var form = document.createElement("form");
    form.setAttribute("method", method);
    form.setAttribute("action", path);
console.log(params);

    for(var key in params) {
        if(params.hasOwnProperty(key)) {
            var hiddenField = document.createElement("input");
            hiddenField.setAttribute("type", "hidden");
            hiddenField.setAttribute("name", key);
            hiddenField.setAttribute("value", params[key]);

            form.appendChild(hiddenField);
         }
    }


  
  
       document.body.appendChild(form);

    form.submit();
}



<!--post('/contact/', {name: 'Johnny Bravo'}); -->
//post('http://127.0.0.1:3030/test/update', {"update" : update});


function constructRequete(){

 var update  =  "PREFIX rdf:   <http://www.w3.org/1999/02/22-rdf-syntax-ns#> ";
 update +=  "PREFIX rdfs:   <http://www.w3.org/2000/01/rdf-schema#>";
     update += "PREFIX smag:   <http://smag0.blogspot.fr/NS#>";
     update += "PREFIX zoo:   <http://example.org/zoo#>";
     update += "PREFIX owl: <http://www.w3.org/2002/07/owl#>";
     update += "PREFIX ex: <http://example.org#>";
update+= "INSERT DATA {";
 //update += "GRAPH <http://smag0.blogspot.fr/GraphTest>{";
  //update += "smag:RobokIze    rdf:type         smag:Site .";
  //update +="smag:RobokIze   smag:objectif         'un site de vente revente piece detachees , pour robots, et objets connectes' ." ;
//     update += "ex:cat     rdfs:subClassOf  ex:animal .";
//     update += "zoo:host   rdfs:range       ex:animal .";
//     update += "ex:zoo1    zoo:host         ex:cat2 .";
//     update += "ex:cat3    owl:sameAs       ex:cat2 .";
//    update += "ex:cat3    owl:sameAs       ex:cat2 .";
  
    var sujet=document.getElementById("sujet").value;
    var propriete=document.getElementById("propriete").value;
    var objet=document.getElementById("objet").value;
 update += "smag:"+sujet+"    smag:"+propriete+"         smag:"+objet+" .";

 // fin requete avec graphe var finRequete = "} }";
 var finRequete = "}"; // fin requete sans graphe

update+=finRequete;
console.log(update);


post('http://127.0.0.1:3030/test/update', {"update" : update});
    //console.log(update);
  
    //console.log(document.getElementById("sujet").value);
    //window.location.assign('http://127.0.0.1:3030/smag.html');
//modifier la pause créée par l'alerte --> ceci permet la mise à jour par la fonction post
    alert(update);
    maj();
}

function httpGetAsync(theUrl, callback)
{
    var xmlHttp = new XMLHttpRequest();
    xmlHttp.onreadystatechange = function() {
        if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
           callback(xmlHttp.responseText);
            //console.log(xmlHttp.responseText);
             //document.getElementById("result").innerHTML = xhttp.responseText;
    }
    xmlHttp.open("GET", theUrl, true); // true for asynchronous
    xmlHttp.send(null);
}

function updateDiv(data){
var myJSONOBJECT= eval('(' + data+ ')');
// ou var myJSONOBJECT= JSON.parse(data, reviver);
var bindings = myJSONOBJECT.results.bindings;
//console.log("update");
//var resultat="";
var list = document.getElementById('resultats');
while (list.firstChild) {
    list.removeChild(list.firstChild);
}
for(i in bindings) {
  var binding = bindings[i];
  //alert(binding); // a for-loop to print all the bindings
  sujet=binding.s.value.split("#")[1];
  propriete=binding.p.value.split("#")[1];
  objet=binding.o.value.split("#")[1];
//  resultat=sujet +" "+propriete+" "+objet;
 // console.log("resultat :"+resultat);
var entry = document.createElement('li');
entry.appendChild(document.createTextNode(sujet));
entry.appendChild(document.createTextNode("  -> "));
entry.appendChild(document.createTextNode(propriete));
entry.appendChild(document.createTextNode("  -> "));
entry.appendChild(document.createTextNode(objet));
list.appendChild(entry);
}
//document.getElementById("result").innerHTML = resultat;

//var bindings = sr.results.bindings;

// JavaScript  for...in loop iterates
// through the properties of bindings array
// which are [0,1,length-1] as opposed to the
// array item.

//for(i in bindings) {
 // var binding = bindings[i];
 // alert(binding); // a for-loop to print all the bindings
//}

// The only difference here (a subtle one) is
// that the iterator variable is n as opposed to r
// n=name, r=row index
//for(i in bindings) {
  //var binding = bindings[i];
  //for(n in binding) {
  //  alert(binding[n].value); // a nested for-loop to print binding values
 // }
//}



}


function maj(){
//console.log('maj');
httpGetAsync('http://127.0.0.1:3030/test/query?query=select+*+where{%0D%0A%0D%0A%3Fs+%3Fp+%3Fo}%0D%0A&output=json',updateDiv);

}

</script>



<form name="form1" onsubmit="constructRequete()">
<input type="texte" name="q" value="a">

 <input type="submit">
</form>

<ul id="resultats"></ul>

<div id="result">

</div>

<script>

setInterval(function(){ maj(); }, 3000);
//maj();

            var inputSujet = document.createElement("input");
            inputSujet.setAttribute("type", "text");
            inputSujet.setAttribute("name", "sujet");
            inputSujet.setAttribute("id", "sujet");
            inputSujet.setAttribute("placeholder", "Sujet");
          
            form1.appendChild(inputSujet);
          
            var inputPropriete = document.createElement("input");
            inputPropriete.setAttribute("type", "text");
            inputPropriete.setAttribute("name", "propriete");
            inputPropriete.setAttribute("id", "propriete");
            inputPropriete.setAttribute("placeholder", "propriete");

            form1.appendChild(inputPropriete);
          
            var inputObjet = document.createElement("input");
            inputObjet.setAttribute("type", "text");
            inputObjet.setAttribute("name", "objet");
            inputObjet.setAttribute("id", "objet");
            inputObjet.setAttribute("placeholder", "Objet");

            form1.appendChild(inputObjet);
  
    // console.log(document.getElementById("sujet").value);
</script>


</html>

01/10/2014

Android , Fuseki & RDF. Utilisation de APPINVENTOR 2 pour envoyer des triplets au serveur Fuseki

Pour rappel :
Le but est de faciliter l'échange d'information entre les différents objets connectés.
On utilise un serveur Fuseki. Le serveur fuseki permet de stocker les informations sous forme de triplets  Sujet/propriété/Objet comme par exemple  ("Voiture" "couleur" "rouge")
voir RDF / web sémantique / Jena / Fuseki ... pour plus d'infos sur le sujet.

pour résumer : RDF permet aux machines d'inférer ou de déduire des informations qui n'existent pas , à partir des relations entre les informations qui existent.

Dans le cadre du projet, nous avons besoin d'un serveur où sont partagées les informations.
Attention, les données ne sont pour l'instant pas sécurisées et tout le monde peut y mettre / remplacer, effacer tout et n'importe quoi.
Ce serveur est un peu un tableau blanc où chacun peut poser tout type d'information.

Le serveur est accessible via l'adresse : http://fuseki-smag0.rhcloud.com

pour consulter les informations qui y sont présentes, vous pouvez utiliser :
-  les formulaires en cliquant sur "Control Panel", choisissez le dataset "ds" puis cliquez sur "Select".
ensuite dans la zone de texte "Sparql Query" saisissez la requete suivante :

select * WHERE { ?s ?p ?o} LIMIT 100

puis dans Output, choisissez "xml"
cliquez ensuite sur "Get Result"

ceci vous affiche  100  informations
On trouve des infos pour faire des requetes sparql un peu partout : exemple là http://rdf.myexperiment.org/howtosparql?page=Using+the+SPARQL+Endpoint#

- ou directement :
http://fuseki-smag0.rhcloud.com/ds/query?query=select+*+WHERE+%7B%3Fs+%3Fp+%3Fo%7D&output=xml&stylesheet=%2Fxml-to-html.xsl


Depuis un bout de temps, je cherche le moyen d'envoyer des informations au format RDF sur ce serveur depuis mon smartphone Android pour pouvoir transmettre des informations au système Smag qui est sensé gérer les objets connectés que nous aurons dans nos habitations.

Plusieurs tests avec APDE, androjena, arqoid, (voir articles précédents...) mais je ne trouve pas ce qu'il faut, car l'utilisation de Jena plante les applis android

Par contre avec Appinventor j'ai un début de solution.
Le serveur Fuseki, n'acceptant que les requetes Post ou Put pour updater les informations, il a fallu décortiquer la requete http :

PREFIX dc: <http://purl.org/dc/elements/1.1/>
 PREFIX ns: <http://example.org/ns#>
 INSERT DATA {
 GRAPH <http://example/bookStore> {
  <http://example/book14>  ns:price  6 }
 }


Pour tester, modifier l'appli, vous devez télécharger ce fichier : https://drive.google.com/file/d/0B0zEK4yLB5C6cTZvN01jemQ5bHM/edit?usp=sharing

et l'importer dans Appinventor : http://ai2.appinventor.mit.edu/

Reste maintenant à récupérer les Prefix, et proposer une liste de propriétés courantes, récupération des infos, recherches dans la base... modification des infos, et vote pour chaque info, pour valider leur véracité, sécurisation des données perso.

un coup de main pour l'utilisation de Appinventor ou de ce fichier ? n'hésitez pas à laisser un message