image

Comme vous le savez sans doute, le portail Open Data du gouvernement français data.gouv.fr a été mis en ligne le 5 décembre. Celui-ci résulte d’une volonté d'une "politique audacieuse d'ouverture des données publiques" comme exprimé par le Premier ministre François Fillon à l'occasion des 4ièmes Assises du Numérique.

image

Le portail data.gouv.fr met à disposition aujourd’hui plus de 350 000 jeux de données sous la forme de fichiers aux formats XLS, CSV, SHP, XML, PDF, DOC, etc. Sont ainsi libérées des données budgétaires, environnementales, culturelles, démographiques, sociologiques, etc.

On ne peut que saluer une telle initiative destinée à renforcer la transparence de l’action de l’Etat et la volonté dans ce contexte de favoriser le partage des données publiques avec les citoyens à qui les institutions publiques souhaitent ainsi rendre des comptes.

Au-delà des données ainsi disponibles, si l’on se place d’un point de vue strictement technologique vis-à-vis de la réutilisation des données ainsi libérées, la version courante n’offre malheureusement pas (encore) d’API pour consommer les jeux de données. Ceci rend ainsi obligatoire le téléchargement des fichiers de données. Pour autant, ce modèle d’accès et de consommation des données trouve vite certaines limites…

Les jeux de données libérées sont présentés très sobrement, avec un ou plusieurs fichiers (en fonction des formats disponibles pour le jeu considéré) proposés en téléchargement pour l’accès aux données brutes. (Une documentation fonctionnelle est proposée pour certains jeux de données très spécialisés mais celle-ci s’adresse à des spécialistes.) Cette forme de présentation de l’information ne s’intègre pas directement dans la culture de consommation de contenus très répandue chez les citoyens : nombres de citoyens perçoivent généralement les contenus à travers le prisme d’applications, comme le prouve le succès des différentes places de marchés applicatives pour Smartphones et tablettes.

Une approche de ce type devient également rapidement un facteur limitant pour les développeurs d’applications. En effet, si les applications envisagées nécessitent plusieurs sources de données, cela implique pour les développeurs d’inclure chacun des fichiers nécessaires dans leur application ; ce qui peut avoir des conséquences sur la taille, les performances et donc au final l’utilisabilité de l’application.

L’approche rend également par définition les mises à jour des données impossibles, une fois l’application publiée sur la place de marché, et élimine donc, de facto :

  • Tous les scénarios applicatifs impliquant des données mises à jour régulièrement ;
  • Ainsi que les scénarios impliquant des données temps réel.

De plus, l’approche n’offre pas de possibilité pour requêter et agréger de manière efficace les fichiers de données qui ne sont, par ailleurs, pas indexés. Ceci conduit à de possibles problèmes de performances vis-à-vis des fichiers de taille importante (plus de 1000 lignes) et ce, surtout sur dans le contexte d’appareils de type Smartphones et tablettes qui disposent d’une puissance de calcul limitée.

Enfin, il convient de considérer une tâche de traitement additionnelle sur chaque fichier pour le rendre pleinement utilisable ; ce qui est susceptible de décourager malheureusement un certain nombre d’initiatives...

Partant de ces constats, nous avons donc souhaité charger l’un des jeux de données (les données sont publiées sous la Licence Ouverte de la mission Etalab) sur l’instance de test OGDI France afin de d’illustrer les avantages et les potentiels d’un service de données RESTful vis-à-vis de la création d’application visant des scénarios originaux et innovants pour le citoyen.

Pour ce faire, notre choix s’est porté sur la liste des musées de France (mise à disposition sous le format de fichier ouvert XLS) avec le chalenge de mettre en avant ces lieux garants de la Culture Française et de donner ainsi envie de les découvrir et de partager cette expérience.

Nous avons donc conçus une application rendant la navigation à travers les musées la plus efficace possible, une application intégrant une fonction GPS pour pouvoir se rendre de façon simple et rapide au(x) musée(s) sélectionné(s), avec, à la clé, la possibilité de planifier des visites dans son agenda et enfin de partager sur son réseau social favori les expériences et les critiques sur les musées visités.

Le code source de cette application est fourni en téléchargement à la fin de l’article. Dans la suite de ce billet, nous allons présenter l’application de façon globale ainsi que les parties de code qui paraissent apporter le plus de valeur à l’application (et, qui n’ont pas déjà été présentées dans de précédents billets).

Par ailleurs, l’application est publiée sur la place de marché Zune (sous le nom « Musées de France ») et est désormais disponible ici.

image

Présentation de l’application

Il s’agit d’une application Windows Phone ; la solution s’ouvre donc dans Visual Studio 2010.

image

Pour développer cette application, plusieurs bibliothèques non fournies avec le Framework Windows Phone ont été utilisées, à savoir :

  • Le Silverlight for Windows Phone Toolkit (disponible sur la forge Codeplex) dont nous nous sommes servis afin de bénéficier de contrôles riches pour l’interface, d’animations et de transitions déjà conçus entre les pages. A noter que le site windowsphonegeek.com met à disposition gratuitement un livre blanc qui constitue la documentation de référence sur cette bibliothèque.
  • Le Live SDK pour Windows Phone (disponible ici) qui fournit un ensemble de contrôles et d’APIs qui permettent aux applications de s’intégrer avec Windows Live ID et d’accéder à des informations depuis SkyDrive, Hotmail et Windows Live Messenger.

Page d’accueil

Intéressons-nous tout d’abord à la page d’accueil de l’application.

image image

Comme on peut le voir, nous affichons sur la page d’accueil la liste des régions et des départements français de façon hiérarchique (une région comprend des départements). La sélection d’une région affiche donc à l’écran une vue située à un niveau de hiérarchie plus élevé représenté par une liste de tuiles comprenant juste la liste des régions et permettant donc de se rendre plus rapidement à la région souhaitée en sélectionnant le carré bleu qui lui correspond.

Pour afficher cette liste hiérarchique de régions et de départements, la vue vient se lier au modèle de données suivant :

image

Comme vous pouvez le constater, la classe Region implémente l’interface IEnumerable<Departement> ; ce qui est loin d’être un hasard.

Pour obtenir la vue à 2 niveaux de hiérarchie, nous nous servons du contrôle LongListSelector du Silberlight for Windows Phone Toolkit qui, dans la pratique, est une ListBox avec des fonctionnalités avancées comme notamment la prise en charge des listes de groupes.

Dans les ressources de la page DepartementsPage.xaml, nous déclarons une instance de la classe Regions :

<phone:PhoneApplicationPage.Resources>

   <utils:Regions x:Key="Regions" />

</phone:PhoneApplicationPage.Resources>

Nous déclarons ensuite dans la page notre contrôle de type LongListSelector :

<toolkit:LongListSelector

       Height="600"

       Name="LongListSelectorDepartements"

       GroupHeaderTemplate="{StaticResource LongListSelectorGroupHeaderTemplate}"

       GroupItemTemplate="{StaticResource LongListSelectorGroupItemTemplate}"

       ItemsSource="{Binding Source={StaticResource Regions}, Path=ListeRegions}"

       ItemTemplate="{StaticResource LongListSelectorItemTemplate}"

       SelectionChanged="LongListSelector_SelectionChanged">

  <toolkit:LongListSelector.GroupItemsPanel>

    <ItemsPanelTemplate>

      <toolkit:WrapPanel></toolkit:WrapPanel>

    </ItemsPanelTemplate>

  </toolkit:LongListSelector.GroupItemsPanel>

</toolkit:LongListSelector>

Il convient de noter ici plusieurs points :

  1. La propriété ItemsSource vient se lier à la propriété ListeRegions de l’instance de la classe Regions déclarée en tant que ressource de la page ;
  2. La propriété ItemTemplate permet de spécifier l’apparence visuelle pour chaque élément de la liste (et donc pour chaque département) ;
  3. La propriété GroupHeaderTemplate permet de spécifier l’apparence visuelle pour chaque groupe de la liste (et donc pour chaque région) dans la « vue à plat » ;
  4. La propriété GroupItemTemplate permet de spécifier l’apparence visuelle pour chaque élément dans la « vue de niveau supérieur » (et donc pour chaque région) ;
  5. La propriété GroupItemsPanel permet de spécifier le panneau qui structure la disposition des éléments graphiques de la « vue de niveau supérieur ». En l’occurrence, un WrapPanel est un panneau qui permet de positionner les éléments séquentiellement de gauche à droite ou de haut en bas.

Les templates sont déclarés dans les ressources de la page dans un souci de lisibilité du code :

<DataTemplate x:Key="LongListSelectorGroupHeaderTemplate">

  <Border BorderBrush="{StaticResource PhoneAccentBrush}"

          BorderThickness="2"

          Margin="6"

          toolkit:TiltEffect.IsTiltEnabled="True">

    <TextBlock Text="{Binding Nom, Converter={StaticResource ToLowerCaseConverter}}"

               Foreground="{StaticResource PhoneAccentBrush}"

               Style='{StaticResource PhoneTextLargeStyle}'

               VerticalAlignment="Center"/>

  </Border>

</DataTemplate>

 

<DataTemplate x:Key="LongListSelectorGroupItemTemplate">

  <Border Background="{StaticResource PhoneAccentBrush}"

          Margin="6"

          Height="173"

          Width="173"

          toolkit:TiltEffect.IsTiltEnabled="True">

    <TextBlock Text="{Binding Nom, Converter={StaticResource ToLowerCaseConverter}}"

               TextWrapping="Wrap"

               Style='{StaticResource PhoneTextNormalStyle}'

               FontStretch="Expanded"

               FontWeight="Bold"

               VerticalAlignment="Bottom" />

  </Border>

</DataTemplate>

 

<DataTemplate x:Key="LongListSelectorItemTemplate">

  <TextBlock Text="{Binding Nom, Converter={StaticResource ToLowerCaseConverter}}"

             Margin="6"

             Style='{StaticResource PhoneTextLargeStyle}'

             toolkit:TiltEffect.IsTiltEnabled="True"/>

</DataTemplate>

Consommation du flux OData

Une fois le département sélectionné, l’application change de page et n’affiche alors que les musées situés dans le département choisi. Pour cela, la page MuseesPage.xaml dispose d’un modèle de vue MuseesPageViewModel.cs qui, via une méthode, se charge de réaliser l’appel asynchrone vers l’instance OGDI France. Nous passons brièvement sur ce point comme cela a été très largement développé dans de précédents billets.

private void DownloadMusees(string departement)

{

  Musees = new ObservableCollection<museesdeFranceItem>();

  frOpenDataDataService dataservice =

        new frOpenDataDataService(new Uri(App.ogdifranceurl, UriKind.Absolute));

  DataServiceCollection<museesdeFranceItem> tmp = new DataServiceCollection<museesdeFranceItem>();

  tmp.LoadCompleted += (s, e) =>

  {

    NotLoaded = false;

    if (e.Error == null)

    {

      tmp.OrderBy(m => m.ville).ToList().ForEach(m => Musees.Add(m));

    }

  };

 

  departement = departement.Replace(" ", "");

  tmp.LoadAsync(from musee in dataservice.museesdeFrance

                where musee.PartitionKey == departement && musee.adresse != ""

                select musee);

}

 

 

public partial class App : Application

{

  public const string ogdifranceurl = "http://ogdifrancedataservice.cloudapp.net/v1/frOpenData/";

 

}

La vue vient se lier sur la propriété Musees de la classe MuseesPageViewModel pour mettre en forme les données.

image

Intégration avec les fonctionnalités Windows Phone

image

Une fois qu’un musée a été sélectionné, la possibilité d’utiliser les fonctionnalités GPS du téléphone est offerte pour se laisser guider jusqu’au musée. Au-delà des apparences, ceci s’avère en fait très simple à implémenter, à une précision près :

private void AppBarCartes_Click(object sender, EventArgs e)

{

  BingMapsDirectionsTask task = new BingMapsDirectionsTask();

 

  string adresse = App.CurrentMusee.adresse;

  if (adresse == "34, Quai du Louvre")

  {

    adresse = "Musée du Louvre";

  }

 

  string searchTerm = string.Format("{0}, {1}", adresse, App.CurrentMusee.ville);

 

  LabeledMapLocation museeLocation = new LabeledMapLocation();

  museeLocation.Label = searchTerm;

 

  task.End = museeLocation;

  task.Show();

}

Il suffit simplement de se servir de la classe BingMapsDirectionsTask pour lancer une recherche GPS du chemin le plus court (piéton ou véhicule) entre la position actuelle et la position du musée qui est la position recherchée et donc la fin du parcours (task.End). Nous ne vous faisons pas l’affront d’expliquer ce code.

Cependant, une petite remarque s’impose : la classe BingMapsDirectionsTask fait partie d’une API spécifique sur Windows Phone que l’on appelle les « Launchers & Choosers ». Ces classes particulières permettent de s’intégrer avec les différentes fonctionnalités du téléphone (GPS, SMS, emails, contacts, appels téléphoniques, lecteur vidéo, appareil photo, etc.). Nous nous sommes justement servis d’un autre Launcher afin de bénéficier de la fonctionnalité de partage social :

private void AppBarVisite_Click(object sender, EventArgs e)

{

  ShareStatusTask task = new ShareStatusTask();

  task.Status = string.Format("J'ai visité le {0} à {1}",

                   App.CurrentMusee.nom, App.CurrentMusee.ville);

  task.Show();

}

A noter que la différence entre les Launchers et les Choosers réside dans le fait que les Choosers retournent un résultat à l’application qui les a appelé (une photo ou un contact par exemple).

Live SDK pour Windows Phone

image

Pour offrir la possibilité de planifier dans son agenda personnel des visites de musées, nous avons fait le choix de la toute nouvelle bibliothèque Live SDK afin de pouvoir sauvegarder sous forme d’évènement dans un calendrier Hotmail les visites de musées.

Pour cela, nous avons inclut dans la page VisitePage.xaml un contrôle de type SignInButton :

<livecontrols:SignInButton Name="SignInButton"

                           Branding="Hotmail"

                           ClientId="XXXXXXXXXX"

                           Scopes="wl.signin wl.calendars wl.events_create"

                           SessionChanged="SignInButton_SessionChanged"/>

Ce contrôle permet à l’utilisateur de s’authentifier avec son compte Live ID. La propriété Scopes permet de lister les autorisations que l’application demande à l’utilisateur lors de son authentification.

La propriété ClientId correspond à un identifiant qui sera donné à l’application lors de son enregistrement sur le portail développeurs de Windows Live ID (nous abordons la procédure associée dans la suite du billet). Nous nous abonnons enfin à l’évènement SessionChanged afin de sauvegarder la session Live de l’utilisateur une fois celui-ci authentifié :

private void SignInButton_SessionChanged(object sender, LiveConnectSessionChangedEventArgs e)

{

  if (e != null && e.Session != null && e.Status == LiveConnectSessionStatus.Connected)

  {

    App.LiveClient = new LiveConnectClient(e.Session);

  }

  else

  {

    App.LiveClient = null;

    if (e.Error != null)

    {

      MessageBox.Show(e.Error.ToString());

    }

  }

}

Lors de la validation de la planification par l’utilisateur, il suffit d’appeler la bonne méthode sur l’API REST de Live SDK avec les paramètres correspondants à l’action que l’on souhaite réaliser (à noter que les API sont documentées sur MSDN) (nous sautons volontairement certaines lignes de code) :

private void AppBarValider_Click(object sender, EventArgs e)

{

 

 

  var calEvent = new Dictionary<string, object>();

  calEvent.Add("name", App.CurrentMusee.nom);

  calEvent.Add("description", "Visite du " + App.CurrentMusee.nom);

  calEvent.Add("start_time", string.Format("{0}-{1}-{2}T{3}:{4}:00{5}",

            year, month, day, startHours, startMinutes, offset));

  calEvent.Add("end_time", string.Format("{0}-{1}-{2}T{3}:{4}:00{5}",

            year, month, day, endHours, startMinutes, offset));

  calEvent.Add("location", string.Format("{0}, {1}",

            App.CurrentMusee.adresse, App.CurrentMusee.ville));

  calEvent.Add("is_all_day_event", false);

  calEvent.Add("availability", "busy");

  calEvent.Add("visibility", "public");

 

  PerformanceProgressBar.IsIndeterminate = true;

  App.LiveClient.PostCompleted += createEvent_PostCompleted;               

  App.LiveClient.PostAsync("me/events", calEvent);

 

 

}

 

void createEvent_PostCompleted(object sender, LiveOperationCompletedEventArgs e)

{

  PerformanceProgressBar.IsIndeterminate = false;

  App.LiveClient.PostCompleted -= createEvent_PostCompleted; 

  if (e.Error == null)

  {

    MessageBox.Show("Visite planifiée dans votre agenda Live.");

    NavigationService.GoBack();

  }

}

*Il est à noter que, sur Windows Phone, le calendrier Hotmail peut mettre un certain temps à se synchroniser (de l’ordre de la dizaine de minutes).

La dernière étape consiste à enregistrer l’application sur le portail développeurs de Windows Live afin d’obtenir le ClientId pour l’application.

Pour cela, rendez-vous à l’URL de gestion de vos applications et cliquez sur le lien Create application. Renseignez un nom pour l’application puis cliquez sur I accept.

image

Sur la page suivante, vous avez accès à votre Client Id :

image

Cliquez enfin sur le lien Application Settings Page afin de configurer l’application en tant qu’application mobile :

image

Conclusion

Nous avons vu au cours de ce billet comment fournir un service original, innovant et culturel aux citoyens au travers de données exposées par une API Web suivant le protocole ouvert de données OData plutôt que par un fichier XLS par exemple, certes ouvert au regard de l’article 4 de la loi n° 2004-575 du 21 juin 2004 pour la confiance dans l’économie numérique, mais qui aurait rendu beaucoup plus long le temps de développement de l’application et aurait fourni un niveau d’agreement bien inférieur pour l’utilisateur.

En plus d'avoir accès aux informations détaillées des musées telles que leur adresse, leurs horaires d'ouvertures, les fermetures annuelles et leur site Web, vous disposez en plus de fonctions de géolocalisation et de GPS pour vous guider vers les musées depuis votre position actuelle.

Vous pouvez de plus planifier vos visites de musées dans votre agenda grâce à l'intégration avec Hotmail.

Et enfin, vous pouvez tenir votre réseau social informé de toutes vos visites de musées grâce à l'intégration avec Twitter, Facebook et Windows Live et par exemple conseiller votre réseau sur les visites à ne pas louper ! N’hésitez pas à télécharger l’application sur la place de marché Zune pour tester tout cela.