Récents articles

Cours web Mobile – React Native

Chap 0 : Présentation de ReactNative & Expo

Vous commencez le développement mobile et vous hésitez à choisir ReactNative ou la surcouche Expo ? Je vous donne quelques indices afin d’y voir plus clair sur quel framework vous devriez choisir en fonction de vos compétences, du temps, et de vos besoins.

 

Présentation de React

Framework pour le développement web frontend, développé par Facebook et concurrent direct de Angular et de Vue.js.

 

Dom Réel et virtuel

React est à la mode. Il est performant, et ce grave à un point important, est qu’il utilise un DOM (Document Object Model) virtuel.

Le DOM (réel) est l’arbre de nœuds, la représentation textuelle de toute votre application web. Quand vous effectuez un changement d’état au sein de votre application, l’intégralité du DOM est recréer. Cela comprend alors l’ensembles des éléments fils de l’application. Et ceci peut être couteux en terme de performance pour des applications grandissantes, surtout si vous y effectuez des modifications fréquentes de votre UI.

Le DOM virtuel quand à lui est un second arbre, correspondant à l’état réel de la globalité de votre application. Vous pouvez alors vous demandez, n’est-ce pas doublon d’avoir deux arbres à l’identique ? Et bien non.

On imagine que vous effectuiez une modification de couleur, sur un texte par exemple. Dans le cas d’une application avec Angular, celui-ci va redessiner la globalité de l’application. Avec React, seul le DOM virtuel va être modifié. React va alors réaliser une comparaison avec des algorithmes spécifiques entre le DOM virtuel fraichement actualisé, et le DOM réel. En fonction des différences entre les deux arbres, seul les nœuds qui ont un nouvel état, vont être redessiner dans le DOM réel. Cela permet de redessiner seulement un seul nœud, dans notre exemple.

Voici une image plus parlante :

virutal dom vs real dom

Présentation de React Native (Vanilla)

C’est un framework développé par Facebook pour le développement d’applications cross-platform (iOS et Android).

 

Développement natif vs développement hybride

Le développement natif est l’utilisation de SDK spécifique. Xcode pour iOS, et Android studio pour Android.

 

Pourquoi éviter le dév. hybride
  • Le développement natif utilise ses modules et bibliothèques natives, avec son langage natif. Il sera toujours plus performant que les solutions hybrides, même si au cours du temps nous observons de moins en moins de différences
  • L’accès à certains modules du smartphones (notifications push…) est facilité
  • Poids des apk/ipa très léger

 

Pourquoi favoriser le dév. hybride
  • Un seul langage de dév. pour deux plateformes
  • Un code unique. Donc 2x moins de bug, en 2x moins de temps
  • Une interface UI/UX identique, évitant des différences
  • Poids des apk/ipa bien supérieur, car embarque des surcouches

Présentation de Expo

Expo embarque ReactNative, c’est une sorte de wrapper, de surcouche.

 

Pourquoi favoriser Expo ?

Projet déjà configuré ! En une minute vous avez votre Helloworld de fonctionnel !

Pas besoin de mac pour tester votre app ! Et ça, ça fait plaisir. Ayant un vielle Iphone et mon Android de tout les jours, je peux tester via l’application Expo, avec hot-reload, et sans avoir de Mac, l’application que je développe sur mes deux smartphones. Même si le dév. hybride promet d’avoir un UI/UX 100% identique entre les deux plateformes, il m’est arrivé que mes checkbox ne s’affichait pas correctement sur iOS. J’ai donc forcé pour mes deux plateforme, l’utilisation de la checkbox Android. Soucis auquel je me serais rendu compte une fois seulement uploader sur les stores…

Pas besoin de mac pour builder votre app ! Vous pouvez utiliser les serveurs expo pour cela. Attention, il vous faudra obligatoirement un compte développeur chez les deux sociétés, et acheter la licence qui va avec. Autre piège, votre build se fera à distance et non en local, attention donc si vous développer une app qui doit rester à l’abris des regards..

Accès à l’ensemble des modules natifs compliqué voir impossible ! A un moment donnée, votre application grandissante va prendre en fonctionnalités. Etant donnée que Expo est une surcouche, l’accès aux modules natifs n’est pas possible pour réaliser certaines fonctionnalités. Je prends comme exemple connu comme les notifications push, ou achats-in app. Vous n’y aurez simplement pas accès.

Ejecter Expo… Vous pouvez cependant ‘éjecter’ Expo pour palier au problème précédent. Mais à en lire certaines expériences sur le net, selon la taille et le versionning de votre projet, que ça puisse très bien se passer comme mal se passer.

 

 

 

Quel framework choisir au final ?

  • Vous débutez sur le développement mobile ?
    • Oui ? Foncez sur ReactNative + Expo
    • Non ? Peut importe

 

  • Votre application requiert des accès natifs à des modules particuliers (achats in-apps ou push-notifications) ?
    • Oui ? : Foncez sur ReactNative vanilla
    • Non ? : Foncez ReactNative + Expo

 

 

 

 

mac os apple installation catalina vm virtual machine qemu kvm Système d'exploitation

macOS Catalina sans macbook, gratuit & fluide

J’ai eu récemment besoin de Catalina afin de builder une application ReactNative pour iOS. Les solutions traditionnels Virtualbox ou encore Vmware m’ont donnée des OS inutilisable, résultant en d’important lag même sur ma config à 4000€. Au bout de deux jours de recherche et d’installations en tout genre pour activer l’accélération graphique via GPU, je suis tombé ENFIN sur une option viable, gratuite, et donnant d’excellent résultat sur mon laptop à 500€ qui datent des années 2015 avec un vieux dual-core !

Vous aurez accès à l’ensemble des outils de Apple, XCode, les app stores, etc.

 

Prérequis

Désolé les amis, il vous faudra lâché Windows au profit d’une distrib Linux. Donc ayez une machine en dual-boot sous la main, c’est obligatoire.

 

Dépôt

J’ai trouvé deux répo intéressant:

 

Le premier de Foxlet est le plus simple. Mais celui de Kholia est un poil plus performant, et nous partirons sur celui-ci dans la suite du tuto.

 

Pourquoi ?

Foxlet utilise le bootmanager Clover, alors que Kholia Open-core. Open-core est plus jeune, moins robuste, mais semble être plus prometteur et performant. Clover semble être délaissé au profit du jeune OpenCore, la plupart des gros développeur sont partie pour ce dernier.

Vous pouvez y ajouter votre GPU, votre carte son, périphériques USB pour développer sous XCode, etc.

 

Installation

On va suivre les infos du dépôts :

  • On paramètre KVM
    $ echo 1 | sudo tee /sys/module/kvm/parameters/ignore_msrs
    

    On rend la modification permanente

    $ sudo cp kvm.conf /etc/modprobe.d/kvm.conf
    
  • Installation des packages nécessaires
    sudo apt-get install qemu uml-utilities virt-manager git wget libguestfs-tools -y
    
  • Clone le répo de Kholia
    cd ~
    
    git clone --depth 1 https://github.com/kholia/OSX-KVM.git
    
    cd OSX-KVM
    
  • Lancez le scripts suivant :
    ./fetch-macOS.py
    

    Selectionnez la version de macOS que vous souhaitez installer.

    $ ./fetch-macOS.py
     #    ProductID    Version   Post Date  Title
     1    061-26578    10.14.5  2019-10-14  macOS Mojave
     2    061-26589    10.14.6  2019-10-14  macOS Mojave
     3    041-91758    10.13.6  2019-10-19  macOS High Sierra
     4    041-88800    10.14.4  2019-10-23  macOS Mojave
     5    041-90855    10.13.5  2019-10-23  Install macOS High Sierra Beta
     6    061-86291    10.15.3  2020-03-23  macOS Catalina
     7    001-04366    10.15.4  2020-05-04  macOS Catalina
     8    001-15219    10.15.5  2020-06-15  macOS Catalina
     9    001-36735    10.15.6  2020-08-06  macOS Catalina
    10    001-36801    10.15.6  2020-08-12  macOS Catalina
    11    001-51042    10.15.7  2020-09-24  macOS Catalina
    12    001-57224    10.15.7  2020-10-27  macOS Catalina
    13    001-68446    10.15.7  2020-11-11  macOS Catalina
    14    001-79699     11.0.1  2020-11-12  macOS Big Sur
    
    Choose a product to download (1-14): 14
    

    On a récupérer le BaseSystem.dmg, on va le convertir

    qemu-img convert BaseSystem.dmg -O raw BaseSystem.img
    
  • On créer un disque dur virtuel, ou notre distri de macOS sera installé. Attribuez la valeur de stockage comme vous le souhaitez. Sachez que Xcode prends pas mal de place, donc au minimum une partition de 64go me semble correct…
    qemu-img create -f qcow2 mac_hdd_ng.img 128G
    

     

Démarrer Catalina

Pour démarrer notre futur macbook pour la première ainsi que les autres sessions, lancez le script suivant :

./OpenCore-Boot.sh

 

On commence par booter sur le disque de base :

installer apple mac os catalina gratuit qemu kvm

 

Sélectionnez Disk Utiliy :

installer apple mac os catalina gratuit qemu kvm

 

Sélectionnez le disque que vous venez de créer dans les étapes précédentes :

installer apple mac os catalina gratuit qemu kvm

 

On va cliquer sur Erase. Donnez lui un nom à notre disque, macOS Catalina par exemple. Validez en cliquant une nouvelle fois sur Erase :

installer apple mac os catalina gratuit qemu kvm

 

Tout est fini. Fermez l’utilitaire de disque afin de revenir sur le menu de départ.

installer apple mac os catalina gratuit qemu kvm

 

Sélectionnez Reinstall macOS :

installer apple mac os catalina gratuit qemu kvm

 

Un tas de chose vont vous être demander, laissez vous guidez à travers l’installation. Acceptez les divers conditions, remplissez votre profil, enregistrer votre compte Apple afin d’avoir accès au store, etc. Je vous explique pas chaque détails, c’est plutôt intuitif :

installer apple mac os catalina gratuit qemu kvm

 

Après une vingtaine de minute, votre installation est fini

installer apple mac os catalina gratuit qemu kvm

 

Pour utiliser le plein écran : Shift + Alt + F

Pour quitter le focus et revenir sur votre linux : Shit + Alt + G

react native expo android ios sqlite Cours web Mobile – React Native

Chap 6 : Stockage de données complexes (SQLite)

Nous avons vu dans le chapitre précédent comment stocker en local des données simples.

On va s’attarder cette fois-ci à comment stocker des informations plus nombreuses, plus complexes et ce de façon plus ordonnée, en utilisant des bases de données SQL.

On va réaliser une simple to-do app, avec possibilité d’ajouter une note, ou d’en supprimer, avec une liste permettant de toute les afficher.

 

On ne peut utiliser n’importe quel outils pour persister des données car nous sommes sur un projet Expo, nous empêchant d’accéder aux modules natifs de iOS et Android. SQLite est un moyen fonctionnant avec des projets Expo.

 

Objectifs

  • Stocker localement des informations via une base de donnée SQL

 

react native sqlite

 

Prérequis

Installez le package pour utiliser SQLite :

expo install expo-sqlite

 

Nous l’importerons dans nos fichiers de la manière suivante :

import * as SQLite from 'expo-sqlite';

Base de données & CRUD

CRUD : diminutif correspondant aux requêtes basique, à savoir Create, Read, Update et Delete.

Création de la base de données

Rien de plus simple, une seule ligne suffit :

On donne un nom à notre base, en argument. Celle-ci n’est crée qu’une seule et unique fois. Si on rappelle cette même méthode, on récupère la base de donnée crée auparavant, aucun risque de doublon.

 

Création de la table NOTE

On va maintenant créer notre table. Je vous montre la façon la plus simple de réaliser des transaction SQL vers notre base :

Requête SQL des plus basique avec le mot clé CREATE TABLE. On lui donne un nom de table, ainsi que la définitions de nos colonnes. Un ID auto-incrémenté pour garantir l’unicité de nos données, ainsi qu’un attribut TEXT qui contiendra le contenu de nos notes.

Nos deux attributs ne peuvent être null, et on leur défini un type, soit Text ou Integer.

 

Optimiser les requêtes

Je préfère une autre annotation que la précédente pour questionner la base de données, récupérer nos objets et leurs affecter des transformations. Je trouve plus clair et simple à l’utilisation. On définit notre modèle de requête avec une promesse :

On pourra utiliser ce modèle dans des fonctions async, via un appel par un await. On pourra utiliser des then() et catch() à l’appel du service dans nos vues, permettant par exemple d’afficher à l’utilisateur dans une popup si une note à bien été ajouté ou si dans le cas inverse afficher un message d’erreur avec son origine.

 

Récupérer toute les notes

On définit une interface pour les objets que l’on va récupérer en base. Cela nous facilitera leurs manipulations au sein de notre application :

 

On fait appel à notre modèle pour questionner la base :

On récupère nos objets via la requête. On va itérer sur notre résultat de requête pour re-typer correctement nos objets.

 

Ajouter une note

Seule différence, on va ici passer en argument le contenu de ma note que l’on souhaite persister en base. Pas besoin de lui passer un ID pour la note, car celle-ci est généré automatiquement en base. Nous avons défini cette option tout à l’heure, lors de la création de la table.

Supprimer une note

Quasiment identique au point précédent, sauf qu’ici on lui passe un ID de note à notre fonction, étant donné que c’est l’attribut qui défini l’unicité de mes items dans ma table NOTE :

 

Récupération des items dans la vue

Nous venons de créer notre base ainsi que des opérations CRUD permettant d’interagir avec elle. On va désormais créer une nouvelle vue, avec un champ de texte permettant de donner du contenu à une note, un bouton pour ajouter cette note, une liste scrollable permettant de naviguer sur l’ensemble de nos notes en base, et leur associé à chacun un bouton pour les supprimer.

 

Définition du state de notre vue

On commence par créer le squelette de base de notre vue :

On utilise ici un composant de classe et non un composant fonctionnel. On a besoin d’utiliser un state pour l’affichage dynamique du contenu de notre liste scrollable. On défini un attribut myNoteList correspondant à une liste de l’ensemble de nos notes en base, ainsi qu’un second attribut note correspondant au champ de texte remplissable par l’utilisateur pour créer une nouvelle note. On initialise les deux attributs dans le constructeur.

 

Définition des méthodes de notre vue

On défini les méthodes pour mettre à jour nos éléments, pour ajouter une note, ainsi que la supprimer :

La méthode componentDidMount() est une méthode standardisé de React, permettant d’être appelé une seule et unique fois et ce à la fin de la création du composant. On lui demande à l’ouverture de notre page, d’initialiser notre liste avec le contenu de notre base de données.

 

Définition des éléments visuels de notre vue

Ici rien de bien complexe. J’ai créer un titre de page, un champ de texte avec un bouton pour ajouter une note. Une liste scrollable présentant l’ensemble des notes en base, ainsi qu’une option permettant de les supprimer :

J’ai utilisé des icones Ionicons inclus dans Expo, qui s’adapte en fonction de si vous êtes sur Android ou iOS via la méthode Platform.OS, encapsulé dans des TouchableOpacity, pour rendre un peu plus esthétique mes boutons d’interactions, ainsi que des flexbox pour avoir une touche de responsive design.

 

Conclusion

Vous venez de voir comment créer très simplement une base de donnée pour votre application React Native tournant sous Expo, comment l’interroger et surtout comment récupérer et afficher le résultats dans une belle vue responsive.

 

react native expo android ios async storage Cours web Mobile – React Native

Chap 5 : Stockage de données simples (AsyncStorage)

Nous venons de voir au chapitre précédent comment organiser une navigation complexe et imbriquée pour une application avec une architecture grandissante.

Nous allons voir aujourd’hui comment stocker des données plutôt simple, par exemple des paramètres de l’application comme l’activation ou non d’un thème clair ou sombre.

 

On ne peut utiliser n’importe quel outils pour persister des données car nous sommes sur un projet Expo, nous empêchant d’accéder aux modules natifs de iOS et Android. AsyncStorage est un moyen fonctionnant avec des projets Expo.

 

Objectifs

  • Stocker localement des informations via JSON

async storage chap 5

 

Prérequis

Installez le packet requis via une console :

expo install @react-native-async-storage/async-storage

Utilisez l’import qui correspond dans vos fichiers :

import AsyncStorage from '@react-native-async-storage/async-storage';

Que-ce que AsyncStorage

AsyncStorage nous permet de persister des données en local sur le smartphone, de façon asynchrone et non crypté. Les informations sont sauvegardé en clair, donc éviter de stocker des données sensibles tel que des mots de passes.

Le stockage s’effectue sous forme de couple tel quel : <Clé, Valeur>.

On ne peut stocker que des string, donc pour des éléments plus complexe tel que des objets, on devra utiliser JSON.stringify() pour la conversion en JSON lors de la sauvegarde d’une donnée, et utiliser JSON.parse() pour lire un objet.

Sauvegarder des données

Pour un string

Pour un objet

 

Lire des données

Pour un string

Pour un objet

 

En pratique

On va faire un exemple tout bête, à savoir charger le nom d’un utilisateur à l’appui d’un bouton.

 

Méthode d’écriture & lecture de donnée

On commence par définir nos deux méthodes pour charger et sauvegarder une donnée :

On appellera la méthode initProfileName() dans l’entrée de notre l’application (App.tsx) pour initialiser notre donnée.

 

Mise à jour de notre vue

On crée un état initialisé à ‘Invité’. On aura une méthode appelant notre fonction pour lire notre donnée via AsyncStorage, définit précédemment. Et enfin une méthode render() pour afficher un champ de texte, et un bouton bindé avec la fonction de chargement de notre donnée locale :

 

Conclusion

On vient de voir comment stocker des informations simple en local. Nous allons voir au prochain chapitre comment stocker des informations plus complexe et surtout en quantités plus importantes.

react native expo android ios stack navigator Cours web Mobile – React Native

Chap 4 : Stack navigator ( navigation imbriquée )

Nous venons de voir dans le chapitre précèdent comment faire une barre de navigation principal. Mais comment faire si nous souhaitons naviguer dans de nouveaux composant à travers nos vues actuelle ?

Pour réaliser une navigation imbriqué de vue dans d’autres vues, nous allons ajouter un nouvel élément, une StackNavigation.

 

Objectifs

  • Créer de nouvelles vues
  • Réaliser une navigation imbriqué

stack navigator and tabs navigator react native

Prérequis

Installez la lib qui gère la stack :

npm install @react-navigation/stack

 

Créer une nouvelle vue

Pour faire de la navigation imbriquée, il va nous falloir dans une première partie créer un nouveau composant, une nouvelle page. Faisons une nouvelle page Profil, qui affiche mon prénom, par exemple :

 

Mise a jour des ROUTES

On va ajouter une nouvelle route dans notre constante globale des routes, amenant à notre nouvelle vue précédemment crée :

 

Création de la stack navigator 

On va créer notre composant qui va gérer la navigation par pile. On doit lui définir nos deux composants (nos deux vues), leurs routes respectifs pour y accéder, et la route initiale lorsque le composant est crée :

 

Mise a jour de notre tab navigator

On va désormais fournir à notre navigation par tab, non plus mon composant WelcomePage comme initial, mais directement notre stackNavigator, crée précédemment :

 

Appel du changement de route par un bouton

On met à jour notre composant WelcomePage, via la méthode onPress, qui est appelé lors d’un clique sur notre item, permettant d’appeler le changement de vue en lui donnant la route que l’on souhaite. Je vous montre comment faire cet appel selon le type de composant que vous utilisez au sein de votre application :

 

Navigation via composant fonctionnel

 

Navigation via composant de classe

 

react native stack tab navigator
Résultat du cours

Conclusion

Nous venons de voir comment naviguer à l’infinie entre nos vues. Dans le prochain chapitre, nous nous attarderons à comment sauvegarder, à la fermeture de notre application, des données simples, comme des paramètres de l’application.

react native expo android ios tab navigator Cours web Mobile – React Native

Chap 3 : Tab navigator, police d’écriture, status bar…

On va vu dans le chapitre 1 comment afficher un HelloWorld!, puis dans le chapitre 2 comment générer nos installeurs. Maintenant que l’on est capable d’utiliser notre application du code à notre smartphone, on va commencer le développement.

react native chap 3 bottom tab bar navigation

 

Objectif

  • Initialiser une petite architecture
  • Créer plusieurs écrans en affichant un titre différent
  • Créer une barre de navigation qui switch entre elles

 

Définition de l’architecture

On va devoir commencer à réfléchir à la structure de notre projet. En effet, nous codions toute l’app dans le même fichier auparavant. On va ajouter cette fois ci de nouveaux composants, et ça risquerai de faire plutôt brouillon par la suite de notre tutoriel. Je vous propose celle-ci :

 

squelette de base application react native

Voici un squelette de base que j’utilise couramment pour débuter une application ReactNative. Quelques explications concernant leurs utilités :

– Service : dossier donnant des services à l’utilisateurs. Générer un pdf, initialiser des paramètres à l’ouverture de l’application, etc.

– Page : contient nos vues globales, affiché tel qu’elle à l’utilisateur

– Navigation : définit l’ensemble des éléments permettant de naviguer entre les vues (tab navigator, stack navigator, etc.)

– Database : contient l’ensemble des requêtes pour questionner une base de données SQL

– Shared : éléments utilisé à travers toute l’application, que ça soit des énumérations, constantes ou interfaces

– Assets : contient des images, des polices, et tout autre éléments ‘brut’ nécessaire pour remplir notre application

– Scripts : permet d’automatiser des tâches, comme le build des ipa ou apk

– Component : contient les différents composants de notre applications, avec une granularité concernant leurs tailles (Atome => Molécule => Organisme => Template )

App.tsx : Point d’entrée de notre application

App.json : fichier de configuration global de notre application

Package.json : contient l’ensemble des dépendances de notre app (paquets npm)

 

Biblio requises

Il nous faut de belles icones :

npm install --save @expo/vector-icons

Il nous faut notre lib de navigation, inclus depuis react :

npm install --save @react-navigation/bottom-tabs

Ainsi que les dépendances nécessaires :

npm install @react-navigation/native
expo install react-native-gesture-handler react-native-reanimated react-native-screens react-native-safe-area-context @react-native-community/masked-view

Définition de nos écrans

Pour chaque écrans que l’on aura besoin, nous allons juste y inclure au milieu un texte, pour démontrer que l’on change bien d’écrans en naviguant. Je créer des interface minimaliste avec le code suivant :

Je le fais à l’identique pour mes deux autres écrans. Tout se passe dans le dossier /scenes/.

 

Définition de notre barre de navigation

  1. Premièrement, on définit via la méthode  createBottomTabNavigator(), une instance
  2. On export le type MainTabNavigator()
  3. On créer un <NavigationContainer>
  4. On créer <Tab.Navigator>
  5. Dans ce dernier on définit autant de <Tab.Screen> que nous souhaitons d’écrans. On lui fourni un nom, et un composant à afficher. Rappelez vous, ce sont les écrans définit précédemment via <View>

Le tabBarOptions nous permet de définir une couleur différente selon l’onglet qui est actuellement ouvert.

 

 

Ajout d’icone

Afin de rendre notre barre plus jolie, on va y ajouter des icones au dessus de nos écritures. Pour cela on va ajouter une nouvelles propriétés à la suite de tabBarOptions, dans le Tab.Navigator :

La propriété route nous permet d’assigner la bonne icone à la bonne page.

La propriété Platform.OS nous permet de savoir si nous sommes sur un iOS ou Android, permettant d’assigner la bonne icones selon les codes de bonne conduite UI/UX de chaque constructeur.

 

 

Ajouter notre tab barre au lancement de l’application

On ajoute simplement notre composant MainTabNavigator dans la fonction principale de notre App :

Soucis de superposition de status bar

Dans certains cas, il se peut que votre application déborde sur la status bar, engendrant des données au niveau de l’horloge ainsi que sur les icones de vos notifications. Pour régler ce problème, on va encapsuler notre MainTabNavigator, par une SafeAreaView :

 

Chargement local de fonts

J’ai déjà eu des soucis concernant certains texte qui étaient coupé au sein de mon application, lorsque je rendais le texte en gras. En me baladant un peu sur la toile, j’ai trouvé une petite soluce, qui consiste à charger une nouvelle font pour toute mon application, en local. Dans votre dossier Assets/, rajoutez un dossier Fonts/. Ajoutez y la police que vous souhaitez, je prends pour exemple la police Arial.

Installez le module correspondant :

expo install expo-font

 

On commence par définir nos variables dans le fichier d’entrée globale de notre application :

 

Je transforme notre composant de fonction en un composant de classe. Cela va nous permettre de définir un attribut nous permettant de savoir quand notre police sera chargé :

 

J’initialise le constructeur de la classe App :

 

On utilise la fonction componentDidMount(). Celle-ci est une routine appelé une seule fois la construction de la classe, et permet de lancer des fonctions une seule et unique fois durant tout le cycle de vie de l’application :

Elle appellera ma fonction ou je lui demande de charger ma police en local, et de mettre à jour ma variable fontsLoaded.

 

Le dernier changement consiste à laisser l’utilisateur patienter sur le splashscreen, tant que la police d’écriture n’est pas chargé. Une les assets voulu chargé, on lance notre application :

 

Faîte comme suit pour utiliser notre nouvelle police fraichement installé :

 

Conclusion

Nous venons de construire notre barre de navigation principale de notre application.

Je vous montre au prochain chapitre, comme faire de la navigation imbriqué avec des StackNavigator. Cela permettra d’ajouter autant de vue que l’on souhaite à travers nos onglets de notre barre principale.

android ios react native expo Cours web Mobile – React Native

Chap 2 : Builder & générer les .apk &…

Après quelques instants de build.. TADAAA !

Objectif

  • Signer son app
  • Builder offline et en local son app
  • Générer les fichiers d’installation Android (apk) & iOS (ipa)

 

Introduction

Vous pouvez utiliser directement Expo pour lancer très facilement votre build sur leurs serveurs distants, avec la simple commande :

expo build:android

Pourquoi je ne l’utilise pas ?

Car lorsque que j’ai voulu lancer un build, leurs serveurs étaient down, laissant mon build en attente. Flemme de perdre plus de temps, je me suis lancé dans les recherches afin de savoir si l’on pouvait nous même générer notre build. C’est un peu plus tricky, mais ça marche.

 

A SAVOIR AVANT DE SE LANCER DANS LE DEV MOBILE

Je souhaite vous parler de compte développeur. ça vous évitera toute surprise comme j’ai pu avoir en développant ma première application sur les stores.

Si vous souhaitez distribuer votre application sur les stores :

  • iOS : Compte développeur nécessaire ( 100€ par an )
  • Android : Compte développeur nécessaire (25€ à vie )

Avec une licence, vous pouvez ensuite lancez autant d’application que vous le souhaitez, vous n’êtes pas limité en nombre.

 

Si vous souhaitez seulement builder votre application en local :

  • iOS : Compte développeur toujours nécessaires, sur un macOS exclusivement. Vous ne pouvez générer votre certificat, teamID et votre fichier de provision en local par vous même.
  • Android : Pas besoin de compte spécifique. Juste un macOS ou Linux d’obligatoire. Car votre fichier de clée nécessaire au build est générable en local, par vous même.

 

Prérequis

  • Bash
  • NodeJS

Build pour Android

  • macOS ou Linux ( pensez à avoir une VM )
  • JDK/JRE (Java Development kit) en version 8 exclusivement

Build pour iOS

  • macOS
  • Xcode (minimum v11.4)
  • Fastlane ( préférez l’installation par Homebrew, le plus simple et rapide moyen )

 

Si comme moi vous êtes pauvres et n’avez pas de macbook pour build votre .IPA, je vous ait fait un article qui vous sauvera un ou deux jours de recherche et de test pour avoir un macOS Catalina sur votre linux qui est proche d’avoir les performances d’une install native ! Oubliez windows, oubliez virtual box ou vmware. Même mon pc à 4000€ ne fait pas tourner macOS, car aucun de ces softs ne peut attribuer des ressources graphiques, entrainant de gros ralentissement lors de vos déplacement de souris et ouverture de logiciel. Bref, c’est inutilisable, à moins de passer par mon tuto qui utilise le combo QEMU/KVM, et qui fait tourner lui Catalina facilement sur mon portable à 2 coeurs de 2015 😁

 

On utilisera la TurtleCLI pour générer le build. Installez le via npm :

npm install -g turtle-cli

 

Signature de l’application

Android

La première étape consiste à signer l’application. Cela permet de créer des certificats concernant la sécurité, pour la distribution. On va utiliser l’outil keytool de java pour générer notre keystore :

Vous pouvez apercevoir aussi des clés avec l’extension « .keystore ». C’est une clée comme les « .jks » avec un format différent.

Cette commande va vous demander plusieurs questions vous concernant :

Génération du keystore

Un fichier va être crée. Veillez à bien mettre de côté de fichier. Il vous sera demander à chaque build de votre application

 

iOS

Il vous faudra un certificat, un apple Team ID, et un fichier de provision

 

 Génération du certificat

Allez sur votre compte développeur Apple. Dans l’onglet certificat, cliquez sur le bouton + :

apple ios generation application ipa certificat p12 provision

 

Choisissiez l’option iOS Distribution (app store and ad hoc ) :

 

Faîte continuer, et on arrive sur une nouvelle fenêtre nous invitant à envoyer un fichier CRC :

apple ios generation application ipa certificat p12 provision

 

On va devoir générer un certificat. Pour cela, lancez l’application Trousseaux d’accès qui est dans le dossier Applications/Utilitaires de votre macbook. Dans le menu en haut à gauche, cliquez sur Trousseaux d’accès, puis sur Assistant de certification, puis sur Demander un certificat à une autorité de certificat :

apple ios generation application ipa certificat p12 provision

 

Remplir les champs demandé, et faîte enregistrer en local :

apple ios generation application ipa certificat p12 provision

 

Vous aurez un nouveau fichier sur votre bureau :

apple ios generation application ipa certificat p12 provision

 

On retourne sur le compte développeur Apple ouvert précédemment, nous étions rester sur la fenêtre ou on nous demander notre fichier CSR. C’est le fichier que nous venons de générer sur le bureau que nous allons upload :

apple ios generation application ipa certificat p12 provision

 

Nous pouvons désormais télécharger notre certificat ! Téléchargez le, et ouvrez le :

apple ios generation application ipa certificat p12 provision

 

Il sera automatiquement ajouté à notre trousseau d’accès, attaché à notre session :

apple ios generation application ipa certificat p12 provision

 

Sélectionnez votre certificat fraichement installé avec sa clé privée, et exportez les deux éléments :

apple ios generation application ipa certificat p12 provision

apple ios generation application ipa certificat p12 provision

 

Exportez au format .p12, et donnez lui un nom et mettez le de côté, ce fichier vous sera obligatoire pour builder :

apple ios generation application ipa certificat p12 provision

 

Un mot de passe sera demandé, notez le bien de côté, il vous le sera demandé lors du build :

apple ios generation application ipa certificat p12 provision

 

Vous avez maintenant un certificat au format .p12 sur votre bureau. Gardez le bien de côté.

 

Création du teamID

On revient sur le compte développeur Apple, et on va allez cette fois ci dans l’onglet Identifiers, cliquez sur + :

apple team build id

 

On coche App IDs, et on continue :

apple team build id

 

 

On sélectionne App, et on continue :

apple team build id

 

 

On remplis le champ Description qui est le nom de l’application, ainsi que son bundleID sous la forme recommandé. Dans Capabilities, vous cocherez les accès et autorisations que votre application à besoin. Par exemple si c’est une application photo, elle devra avoir accès à l’APN du smartphone. Vous cliquez ensuite sur Continue, puis Register :

apple team build id

 

Notez bien votre App ID Prefix, qui est votre Team ID. Vous en aurez besoin pour build par la suite.

 

 

Fichier de provision

Troisième et dernière étape. On va maintenant s’occuper de générer du fichier de provision, lui aussi nécessaire pour buid l’application.

Toujours sur notre compte développeur Apple, on va sélectionner cette fois ci l’onglet Profiles, et cliquer sur + :

apple build ios appstore provision file

 

On sélectionne ensuite App store, dans l’onglet Distribution. A savoir, les builds Ad Hoc ne sont pas pris en charge par Expo. On clique sur Continue :

apple build ios appstore provision file

 

Sélectionnez l’app ID précédemment crée, et faîte Continue :

apple build ios appstore provision file

 

Sélectionnez le certificat précédemment crée, et faîte Continue :

apple build ios appstore provision file

 

Donnez un nom à votre fichier de provision, et faîte Generate :

apple build ios appstore provision file

 

Téléchargez le, et gardez le de côté, vous en aurez besoin pour générer votre build :

apple build ios appstore provision file

 

Export de l’application

Android & iOS

La seconde étape consiste à exporter notre application. Cela permet de créer les bundles (iOS & Android) à partir des fichiers javascript. Vous devriez apercevoir la création d’un dossier « dist » dans votre répertoire courant via la commande suivante :


Attention à utiliser la bonne, selon si votre application contient du HTTP ou HTTPS.

 

Servir l’application

Android & iOS

On va maintenant lancer notre application à partir du bundle crée précédemment, en local. Pour cela on va utiliser python. Déplacez vous dans le dossier « dist » précédemment crée, et lancer la commande suivante :

 

Vérifiez bien que le serveur tourne, via curl, ou en lançant une connexion à votre localhost via votre navigateur :

 

Build l’application

Dernière étape, on va pouvoir lancer le build de nos fichiers. Revenez à la racine de votre projet et ouvrer une autre console.

Android

Lancez la commande suivante pour lancer le build via turtle-cli :

Voilà votre fichier APK, situé dans le répertoire annoncé dans la console.

 

iOS

Lancez la commande suivante pour lancer le build via turtle-cli :

 

Soucis fréquemment rencontré

EACESS permissions denied

Vous pouvez vous confronter à des erreurs d’accès aux fichiers pour installer des packets npm globaux ( pour turtle-cli ou encore expo ). Oubliez les sudo su et sudo en tout genre, qui m’ont fait juste galérer encore plus. Vous pouvez fix cela en deux étapes :

  • Utilisez l’option ‘–unsafe-perm‘ de NPM
  • Pour le dossier ‘lib/node_modules’ qui résisterait aux erreurs, passez un coup de chown -R votreNomUser pour donner accès à votre utilisateur courant de la session au dossier en lecture et écriture.

 

Conclusion

Nous venons de générer nos fichiers d’installation APK pour Android et IPA pour iOS, afin de distribuer notre application.
On s’attaque à la navigation entre plusieurs écrans sur notre prochain chapitre.

 

android ios react native expo Cours web Mobile – React Native

Chap 1 : Environnement, prérequis & Hello world !

Résultat du cours

Objectif

  • Configurer l’environnement de développement
  • Générer le squelette basique d’une application
  • Tester son application sur son smartphone

 

ReactNativeCLI, ExpoCLI…

Nous avons des outils dans le développment web, permettant de développer rapidement un squelette de base pour une application :

  • CLI pour Angular
  • CRA pour React
  • CLI pour React Native

 

Mais pour créer mon premier projet pour découvrir ces technos mobile, je pars non pas sur ReactNative CLI, mais sur ExpoCLI. C’est comme Rails mais pour ReactNative, ou encore Phonegap pour Cordova. Il étends les fonctionnalité de ReactNativeCLI.

Qu’apporte t-il de plus par rapport à React Native CLI et quand l’utiliser ?

Avantage :

  • Pas besoin d’Android Studio ni de Xcode
  • Configuration bien plus simple & rapide ( hello world en moins de une minute )
  • Hot reload, sur smartphone physique et non par simulateur. Oui, via l’appli Expo, vous pouvez tester votre app sur votre smartphone iOS ou Android physique, et ce instantanément. En react native vanilla, vous avez droit au simulateur Android sur Windows, et simulateur iOS sous macOS exclusivement.

Inconvénient :

  • Poids de l’apk/ipa, du à l’ajout de librairie annexes (~50mo le hello world, ça fait mal…)
  • Accès aux modules natifs impossible. Vous ne pouvez ajouter de lib natif via Xcode ou Android studio, car tout est packagé via le sdk Expo. Certaines fonctionnalité sont impossible d’être utilisé, comme les achats in-app ou le bluetooth.

 

En résumé, pour débuter le dév mobile ou pour de simples application, vous devriez commencer par Expo. Pour des utilisateurs expérimentés ou souhaitant des fonctionnalités spécifiques à chaque plateforme, partez sur du ReactNative vanilla.

 

Prérequis

Il vous faudra de base :

  • NodeJS

Installez ensuite la CLI de Expo via une console :

npm install -g expo-cli

Pensez à avoir Python dans vos variables d’environnements, au risque d’avoir une erreur d’installation.

 

Initialisation du squelette

On initialise une nouvelle application via la commande :

expo init "Nom_de_votre_app"

 

Vous aurez l’architecture suivante :

  • assets/ : dossier contenant vos images
  • app.json : fichier de configuration du projet
  • app.tsx : fichier d’entrée de votre application
  • package-json : contient l’ensemble des dépendances et scripts du projet
  • tsconfig.json : fichier de configuration de typescript
  • babel.config.js : fichier de configuration pour la gen du bundle ( une sorte de webpack )

 

Lancement du serveur de dév

Simple :

npm start

Un nouvel onglet dans votre navigateur va s’ouvrir, vous proposant divers options :

 

Pour faire fonctionner le simulateur Android ou iOS, vous allez devoir installer les biblio natives. Mais on peut éviter cela en utilisant notre propre smartphone. On va devoir connecter notre smartphone au même réseau wifi que l’ordinateur sur lequel on développe.

Installez l’application EXPO, disponible sur l’iOS Store et GooglePlay store, selon votre type de device. Une fois l’application lancé sur votre smartphone, vous allez pouvoir scanner le QR code affiché sur la console, comme montré sur la capture d’écran précédent. Cela va permettre de transférer le bundle directement sur le smartphone.

Vous allez pouvoir ainsi voir vos modification en temps réel sur votre téléphone, de l’application que vous codez, à chaque sauvegarde.

 

Icone & Splash screen

Vous pouvez changer l’icone de votre application via le fichier « app.json ».

De même pour le splash screen, qui correspond a l’image qui sera affiché le temps que votre application soit chargé par votre smartphone.

react native chap1 splash screen

 

Conclusion

Nous venons de voir comment réaliser un « HelloWorld » en quelques minutes, et ce directement sur notre smartphone.

On discutera dans le prochain chapitre sur comment générer les fichiers APK et IPA, permettant d’installer et de distribuer notre application.

Cours pratiques - Deep learning

Radar automatique partie 1 : Constitution du dataset de…

Introduction

Projet qui consiste à reproduire le fonctionnement d’un radar automatique.

Comment fait-il, à partir d’une photo, pour reconnaître l’emplacement d’une plaque d’immatriculation, afin d’en lire les caractères ?

On s’intéressera ici dans cette première partie à la constitution du dataset nécessaire pour entraîner des modèles de réseau de neurones pour réaliser un apprentissage profond.

Scénario global de notre projet

 

Données nécessaires à notre projet

Pourquoi ?

Vous avez une multitude de technique en traitement de l’image pour réaliser une lecture de caractère sur une image. Mais j’ai souhaité rester dans le domaine de la data-science, en pensant au réseau de neurones à convolution français le plus connu au monde, à savoir leNet-5 de Y.Le Cun, qui permet de transcrire en texte des chiffres écrit à la main sur une image.

Qui dit deep learning, dit nécessité de beaucoup de données.

 

Quels types de données

Je suis partie sur l’architecture suivante :

Entraîner un premier réseau de neurones, pour qu’il puisse repérer une plaque d’immatriculation au sein d’une photo. On va utiliser un CNN des plus standard. Il va prendre en entrée des images de voiture, et nous extraire les coordonnées d’un rectangle contenant la plaque. Nous pourrons l’extraire par la suite de l’image pour la fournir à notre second réseau.

Notre premier dataset sera constitué de 2 parties :

  • partie 1 : regroupe des images de voitures.
  • partie 2 : un fichier CSV ou n’importe quel format permettant de stocker le nom d’une image de voiture (exemple: image1.png) associés aux coordonnées du rectangle contenant la plaque.
Dataset 1 pour notre premier réseau

 

Entraîner un second réseau de neurones qui va prendre en entrée la sortie du premier réseau, à savoir une image sous forme de rectangle, contenant la plaque d’immatriculation de la voiture. Celui-ci encore sera un CNN standard. Il donnera en sortie, du texte, représentant les caractères présents sur la plaque d’immatriculation de la voiture.

Ce second dataset lui aussi sera en deux parties :

  • partie 1 :  regroupe des images de plaques d’immatriculation.
  • partie 2 : un fichier CSV ou n’importe quel format permettant de stocker le nom d’une image d’une plaque (exemple: image1.png) associés au caractères présent sur la plaque.
    Dataset 2 pour notre second réseau

     

Constituer son jeu de données

Je vais vous présenter quelques techniques afin de récolter et réunir des données.

Dataset pré-existant

Comme tout bon informaticien, on sait que c’est inutile de réinventer la roue. En effectuant quelques recherches, vous avez déjà de fortes chances que des chercheurs ou autres développeurs aient déjà fait le travail pour vous. En recherchant des articles scientifiques sur des moteurs de recherches spécifique ( Google Scholar, Arxiv, etc.), on peut trouver des travaux sur des reconnaissances comme celle que je souhaite réaliser. Vous pouvez des fois tomber pile sur ce que vous cherchez et gagner grandement en temps (phase de récolte, nettoyage & régulation des données, etc.), c’est tout bénéf pour vous. Ou des fois tomber comme pour moi, sur des données, mais qui ne s’adapte pas pleinement à mon cas précis pour plusieurs raisons :

  • Pas de dataset sur des plaques exclusivement françaises
  • Certains dataset ont des images de qualité médiocre
  • Certains dataset ont très peu de données ( une centaine… )

Comme expliqué dans le point précédent, j’ai un type de données bien précis. C’est d’ailleurs pour cette raison que j’ai repoussé x fois de faire ce tutoriel, car la constitution du dataset aller être un casse-tête terrible, me demandant des fois si je ne devrais pas passer des journées entières sur la rocade Bordelaise à photographier le passage du moindre véhicule 🤣

 

Crawling & Scraping

En effectuant des recherches sur le net, vous pouvez trouver des sites comme Google image, Twitter, Instagram, etc, contenant des images de voiture ou de plaque. Une première solution serait de réaliser des requêtes BigQuery afin de pouvoir tout télécharger (pour google), ou faire du web crawling et scraping (pour les autres réseaux). On va s’attarder sur cette seconde solution 😀

 

Cela consiste en quoi ? ( Théorie )

Faisons simple.

Le web crawling est le fait d’utiliser des robots afin de circuler et parcourir un site web de façon scripter, automatique, dans l’ensemble de son domaine.

Le web scraping est le fait d’utiliser des robots afin de récupérer des informations d’un site, de télécharger ses images, en bref récupérer l’ensemble de son DOM.

 

On va bosser avec des Dataframes Pandas, donc on va rester sur du Python. Et ça tombe bien, car il se prête bien à ce type d’utilisation. Les principales librairies de crawl/scrap sont les suivantes :

  • BeautifulSoup : libraire des plus simples, donc très pratique pour ce genre de petit projet. Je l’ai utilisé pour récolter des datas pour de la détection de harcèlement.
  • Scrapy : bien plus complet, il s’apparente à un framework à part entière, donc plus compliqué à prendre en main mais permet beaucoup plus de chose.

Pour un projet aussi simple j’aurais dû partir sur BS, mais pour le goût du défi je suis parti sur Scrapy pour découvrir de nouvelles choses. C’est vrai que BS nécessite que quelques lignes de code pour récupérer des données, chose un poil plus complexe avec Scrapy.

 

Initialiser un projet Scrapy

On commence par installer notre paquet :

  • pip install scrapy

Vous pouvez l’installer aussi via Anaconda.

 

Dans une console initialiser un nouveau projet :

  • scrapy startproject Nom_De_Ton_Projet

 

Vous allez avoir l’architecture suivante :

  • Projet
    • __init__.py
    • middlewares.py : permet de définir des customisations sur le mécanisme de comment procède le spider
    • pipelines.py : pour créer des pipelines. Les items scrapé sont envoyé là-dedans pour y affecter de nouvelles choses, comme vérifier la présence de doublon, de nettoyer des datas, qu’ils contiennent bien les champs souhaités, etc. ( on s’en fou )
    • settings.py : fichier de configuration du projet. Définissez vos vitesses de crawl, de parallélisation, nom de l’agent, etc.
    • scrapy.cfg : fichier de configuration de déploiement ( on s’en fou )
    • SPIDERS/
      • __init__.py

On a vraiment besoin que du strict minimal concernant les outils que nous propose ce framework.

 

On va juste s’attarder un poil sur le settings.py. Ce genre de technique est très peu apprécié car vous pouvez littéralement surcharger les accès à un site. Vérifier que le site ne possède pas une API publique permettant de récupérer les données souhaitées.

Pour rester courtois, renseignez les champs BOT_NAME et USER_AGENT. Ce qui donne pour ma part :

BOT_NAME = 'Crawl&Scrap'
USER_AGENT = 'Bastien Maurice (+https://deeplylearning.fr/)'

Utiliser des vitesses de crawl/scrap et un nombre de requête concurrente de façon raisonné :

CONCURRENT_REQUESTS = 16

Scrapy propose même des outils permettant d’ajuster sa vitesse de requêtes de façon intelligente :

AUTOTHROTTLE_ENABLED = True
AUTOTHROTTLE_START_DELAY = 5
AUTOTHROTTLE_MAX_DELAY = 60
AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0 (le plus important)
Squelette minimal d’un spider

Un spider est un composant qui va scrap un type de donnée. Nous souhaitons scrap deux types de données, nous aurons alors deux spiders. Voici le code minimal lors de la création d’un spider :

name est le nom du spider

allowed_domains est un tableau contenant les noms de domaines autorisés pour notre spider

start_urls est un tableau contenant les URL de points de départ par où commencer à scrap

La méthode __init__ est le constructeur de la classe. On va définir deux méthode (start et end) qui seront exécuté lors de l’appel de signaux (signals.spider_closed & signals.spider_opened) correspondant au lancement et à la clôture du scraper.

La méthode parse est la méthode appelé par Scrapy, c’est ici que toute la magie du scraping va se dérouler et ou on devra définir ce que l’on souhaite récupérer du site distant 😎

 

Coder notre spider pour le dataset 1 & 2 😏 ( Simple parsage )

La première idée était d’utiliser ces deux méthodes sur un maximum de site afin de récupérer un maximum de donnée. Seul bémol, j’aurais dû écrire à la main mon fichier CSV pour y ajouter le numéro des plaques. Mais j’ai réussi en creusant dans mes recherches, à trouver un site qui expose des images de plaques, avec diverses infos :

  • Choix de la nationalité de la plaque ( voiture française dans notre cas exclusivement )
  • Photo de la voiture en entier
  • Photo de la plaque d’immatriculation (généré automatiquement, ce n’est pas un crop de la plaque de la photo)
  • Date d’ajout
  • Pseudo de l’utilisateur qui a ajouté
Exemple d’une photo disponible sur le site

 

On va pouvoir récupérer à la fois des données pour le dataset 1 et pour le dataset 2.

Créons un nouveau fichier, scraper.py dans le dossier ‘spider‘ de notre projet Scrapy. Ajoutons-lui les attributs suivants :

csvFilepath : chemin de destination vers mon fichier CSV, qui va contenir les données de ma plaque d’immatriculation. Je souhaite que à chaque donnée on récupère les données suivantes :

  • date : date à laquelle la photo a été upload sur le site distant
  • heure : heure à laquelle la photo a été upload sur le site distant
  • voitureMarque : marque de la voiture
  • voitureModele : modèle de la voiture
  • imgGlobalName : nom de l’image de la voiture global que je vais enregistrer en local
  • imgPlaqueName : nom de l’image de la plaque que je vais enregistrer en local
  • plateNumber : numéro de la plaque d’immatriculation
page : numéro de la page en cours de scraping
maxPage : nombre de page max à parser
DIRECTORY_IMG_PLATE : dossier de destination pour enregistrer les images PNG de la plaque seule
DIRECTORY_IMG_GLOBAL : dossier de destination pour enregistrer les images PNG de la voiture globale
GLOBAL_DATA : fichier CSV qui sera lu par la librairie Pandas
L’attribut urllib.urlopener va être extrêmement important. Il peut vous arriver que le site distant vous remonte une erreur, signifiant qu’il bloque les spiders qui scrap des datas. On va camoufler notre spider en lui associant une version pour le faire ressembler à une connexion venant d’un humain. Vous pouvez lui donner d’autres versions, peu importe qu’il vienne de Mozilla, Chrome, Firefox, de même pour les versions…
On va pouvoir ainsi scrap nos data comme souhaité 😁

 

Je connecte mes signaux :
Début du scrap : je demande à Pandas de charger mon fichier CSV contenant l’ensemble de mes datas
Fin du scrap : je demande à Pandas de sauvegarder mes nouvelles données en plus des anciennes en local

 

Et enfin la méthode parse qui permet de récupérer nos données, de les nettoyer :
Quelques infos utiles :
La méthode xpath me renvoi de base un object xpath
La méthode .get() me converti mon object xpath en string
L’attribut xpath du sélecteur text() me renvoi le champ text, d’une balise <division>Coucou</division par exemple
L’attribut xpath du sélecteur @src me renvoi le champ src, d’une balise <img src= »lien_vers_image« > par exemple
L’attribut xpath du sélecteur @altme renvoi le champ alt, d’une balise <img alt= »infos_utiles« > par exemple
Résultat des données récupérés par notre spider

 

Coder notre spider pour le dataset 2 😏 ( Utilisation de leur API )

Je me suis dit pour augmenter notre dataset de façon bien plus conséquente, qu’il serait intéressant d’avoir un générateur de plaque avec des caractères aléatoire. Une image de plaque d’immat est simple à réaliser en effet. Et il se trouve que sur ce même site il y a un système permettant de réaliser nos plaques sur mesure via leur API :

Capture d’écran de leur système de génération de plaque

Comme vous pouvez le voir, on peut choisir nos plaques selon :

  • La nationalité
  • Le type de standard
  • Le nombre de rangé
  • Le département
  • L’ensemble des caractères de la plaque

Après avoir remplis l’ensemble de ces informations, le site vous génère la plaque selon vos numéros choisi. J’ai souhaité rendre ce processus de façon automatique. Etant donnée que c’est nous qui rentrons les lettres voulues, on pourra les récupérer pour les inscrire dans notre fichier de données CSV.

 

Avant de se lancer dans le code, il va falloir faire une petite analyse du site, pour savoir comment générer une plaque en utilisant l’API, sans que celle-ci nous soit indiqué explicitement. En effet, contrairement à des outils tel que Sélénium, Scrapy ne peut faire des interactions directement avec le javascript, comme par exemple simuler des clics de souris sur des boutons. On a donc besoin de l’accès de l’API.

En utilisant les outils de Chrome qui sont intégrés, on va aller chercher que fait ce bouton lors d’un événement (click), et lire le code source de la page. En remontant dans les parents du bouton, on aperçoit le formulaire qu’envoi le bouton lors d’un clique. Il envoi l’action « /fr/informer » avec comme méthode « post » :

 

 

On va maintenant aller voir du côté réseaux et des paquets qui y sont échangés. Vous pouvez enregistrer sur des périodes, l’ensemble des requêtes qui transite de vous au serveur, permettant de voir les informations qui y sont échangés. J’ai lancé mon enregistrement, puis j’ai cliqué sur le bouton pour générer une plaque. Dans l’onglet Network, vous aurez pleins de requêtes. A vous de les analyser pour récupérer les informations dont vous souhaitez.

J’ai réussi à retrouver l’action appelé par mon bouton :

On peut observer dans la partie Form Data, que plusieurs paramètres ont transités lors de l’appel à l’API. Celles-ci sont les données permettant de générer la plaque, donnée par les champs de texte vu précédemment et rempli par l’utilisateur. Nous devrons donc induire de nouvelles notions pour coder ce nouveau spider, afin d’y injecter des paramètres lors de notre requête au site distant.

 

 

Nous venons d’analyser brièvement le site. Passons à la pratique.

Créons un nouveau fichier, plateGenerator.py dans le dossier ‘spider‘ de notre projet Scrapy que voici :

Pas de nouvelles choses comparées à l’exemple précédant. On garde une version custom pour les en-têtes URL pour by-pass le 403 forbidden.

 

Je définis deux nouvelles fonctions. Celles-ci vont me permettre de me générer de façon aléatoire soit seulement des lettres, soit des chiffres, de longueur que je souhaite. Elles vont me permettre de générer les valeurs de mes plaques générées :

 

On va utiliser la méthode « start_requests ». Celle-ci est appelé de base, par rapport à notre url défini dans « start_urls » :

L’ensemble du code est documenté ligne à ligne.

La dernière ligne, avec le mot clé ‘yield’, va nous permettre de générer une requête basée sur des données de formulaires. On lui donne les données de la plaque que l’on souhaite générer à l’API. Le paramètre « meta » n’est utilisé que pour passer des informations de ma fonction « start_requests » à ma méthode « parse ».

 

Cette requête appelé va être interprété par notre méthode « parse ». Comme pour le premier cas, c’est ici que tout la magie du scrapping s’opère :

Résultat des données récupérés par notre spider

Ajuster ses données

Ajout des coordonnées de la plaque dans le dataset 1

Après avoir craw/scrap le site en question, on se retrouve avec la photo de la voiture, le numéro de sa plaque, mais pas la position (X, Y) où se trouve la plaque sur la photo de la voiture. Cela aurait été fait dans des datasets pré-existant. Etant donné que je le constitue moi-même, je vais devoir le réaliser moi-même.

Vous avez plusieurs logiciels sur Github vous permettant d’ouvrir des images, de placer des rectangles, et celui-ci vous renvoi les coordonnées et vous permet de constituer un fichier CSV avec l’ensemble des coordonnées des images de votre dataset. ça risque d’être long et répétitif. C’est pour cela que je suis parti pour créer mon propre logiciel me permettant de tout automatiser. Cela risque de me prendre du temps, mais à terme, d’en gagner pas mal de façon proportionnelle à la taille de mon dataset.

 

Coder son propre logiciel

Nous avons vu les limites pour constituer un dataset.

Que cela soit en reprenant le travail d’autres personne malgré qu’il ne corresponde pas à 100% de notre objectif. Ou le fait qu’il soit incomplet (manque de la positions X,Y de la plaque d’immatriculation au sein de la photo) lorsque on le réalise soit même par crawl/scrap. Ou encore que l’on manque cruellement de données.

 

Une possible solution pourrait être de créer son propre logiciel pour générer des images ?

On pourrait réaliser un système de génération de plaque d’immatriculation pour remplir le dataset 2 (comme le fait l’API du site précédent), ou encore coller ces plaques générées sur des photos aléatoires de Google. En effet, notre réseau de neurones 1 n’a pour but que de détecter, de localiser, et de fournir la position de la plaque au sein de la photo, rien de plus. Donc que l’on prenne de vraies photos de voiture avec de vraies plaques d’immatriculations placé au vrai endroit revient au même pour notre réseau que de générer une plaque aléatoire, et de l’insérer dans une photo aléatoire.

Le fond n’est pas important, car on lui apprend à détecter seulement les plaques. Les sorties resteront les mêmes dans les deux cas

 

 

Je dit presque, car il y aura toujours une différences entre de vraies photos et des photos/plaques générés. Il ne faudrait pas entraîner notre réseau sur des données qu’il ne rencontrera pas à nouveau, du moins des données semblables. Les fonds générés ne devraient pas gêner notre système, contrairement à nos plaques que l’on va générer :

  • Plaque plus ou moins inclinés et non droite selon la prise de photo
  • Plaque plus ou moins éclairés selon le soleil
  • Ombre plus ou moins importante selon le soleil
  • Plaque plus ou moins propre (boue, moustiques, etc.)
Différences plaque généré et plaque réelle…

On peut prévoir d’avance des risques d’avoir quelques soucis en utilisant notre système tel quel. Il ne pourrait reconnaître que des plaques parfaitement blanches, et droite, ce qui risque de peu arriver dans la réalité sur le terrain. Il faut donc permettre à notre réseau de mieux généraliser, et donc lui fournir des cas d’exemples pour qu’il puisse apprendre plus ‘intelligemment’. Il faudra donc ajouter à notre logiciel de génération de plaque le moyen de pouvoir répondre au problématiques précédents :

  • Permettre d’ajouter une rotation et
  • Permettre d’ajouter un effet de perspective
  • Permettre d’ajouter du bruit,
  • Permettre d’ajouter des assombrissement et/ou tâche

Ces effets permettront de se rapprocher un peu plus à la réalité des plaques d’immatriculation que l’on retrouve en service. Ces effets devront être généré de façon aléatoire, et ceux dans des proportions minimal et maximal définit par des intervalles.

 

L’article se faisant déjà assez long, je ferais un article dédié à mon logiciel de générateur de plaque, DeeplyPlate.

 

Conclusion

Au bout de cette première partie je vous ait données quelques pistes pour  :

  • Circuler sur un site via Scrapy
  • Coder son premier spider pour récupérer des données sur le net

Les données que vous souhaitez ne seront pas forcement existante sur le net, ou sous un format spécifique à votre utilisation. C’est pour cela que je vous montre que vous pouvez réaliser votre propre logiciel assez rapidement, en 10-15 jours de travail régulier pour soit réaliser de façon artificielle vos données, ou encore créer votre propre logiciel de data augmentation afin d’augmenter la taille de vos données aussi petite soient-elles.

 

Je vous propose de passer à la Partie 2. On s’attaquera cette fois-ci à comment faire de la détection d’objets sur une image. Nous allons montrer comment entraîner un modèle pour qu’il puisse nous fournir les coordonnées sur une image donnée, de l’emplacement d’une plaque d’immatriculation. Nous pourrons ensuite découper cette partie de l’image afin de le donner à un second modèle, afin qu’il puisse nous lire et extraire sous forme de texte les valeurs de la plaque. Mais celle-ci se fera en Partie 3 😎

 

Remerciement

Le tutoriel n’aurait pu être possible sans le site Platesmania. Pour préserver la stabilité du site, ne crawler/scraper qu’avec un nombre de requête et parallèles raisonnable.

 

 

Cours pratiques - Data visualization

Intégration de Plotly.js dans Angular 9

Exemple d’un graphique, venant de mon projet Covid19-Vizualisation

 
Lorsque j’ai voulu me lancer dans la data visualisation intégrée à un site web, j’ai directement voulu utiliser la librairie la plus célèbre en la matière, à savoir D3.js. Mais j’ai trouvé une alternative qui m’a interpellé car basé à la fois sur D3.js ainsi que Stack.gl, permettant de réaliser des graphiques plus interactifs, à première vue.

Celle-ci est disponible à la fois en Python, R, et enfin Javascript, celle qui nous intéresse dans notre article. Et c’est pour cette raison que je l’écris, car celui-ci n’est pas vraiment disponible en Typescript et bien intégré à l’écosystème d’Angular, qui a des notions de modules, de composants, etc.

Comparatif de popularité entre nos deux librairies

 

Objectifs

  • Intégration de Plotly.js
  • Initialisation d’un graph
  • Ajout de données
  • Customisation du type de graph
  • Customisation de son UI

 

Source du projet

Lien vers le dépôt Github contenant les sources

Lien vers une utilisation possible pour réaliser de la Data vizualisation pour suivre l’évolution de la pandémie du Covid19

 

On utilisera des données du Covid19 pour alimenter en data nos graphiques. C’est parti !

 

Quelques infos sur Plotly.js

Pour créer un graphique, on va avoir besoin de trois choses principalement qui se découpe de la façon suivante :

Data

Un objet data qui va contenir l’ensemble des points (ordonnées Y, et abscisse X) que l’on souhaite afficher sur notre graphique.

On le défini dans notre composant en Typescript.

Layout

Un objet layout qui définit les caractéristiques générales au niveau de l’UI de notre graphique, comme le titre, la taille de notre graphique, etc. Si l’on souhaite modifier l’allure d’une courbe en particulier, cela se fera dans l’objet data cependant.

On le défini dans notre composant en Typescript.

Config

C’est l’objet final crée, qui englobe notre objet Data ainsi que notre objet Layout.

On le défini dans notre composant en Typescript, et on ira le binder avec notre fichier de vue en HTML.

 

Intégration de Plotly.js

Je commence par initialiser un nouveau projet Angular pour illustrer notre exemple. Je vous renvoie sur un précédent article, expliquant comment initialiser une application Angular.

On installe via npm les modules nécessaires :

  • npm install angular-plotly.js plotly.js

On ajoute le module Plotly à notre module globall App :

Dans votre fichier de configuration tsconfig.json, passez ‘target’ en ‘es5’, si vous avez une erreur dans votre console comme quoi Plotly n’est pas défini dans votre document.

 

Création d’un graphique avec une courbe

Partie vue

On ajout un composant ‘plotly-plot’. Celui-ci est composé de plusieurs directives et attributs :

  • fxFlex & Style : directive FlexLayout de Angular, permettant à notre composant de prendre toute la hauteur et largeur du parent disponible
  • useResizeHandler : directive permettant de resize automatiquement le graphique selon la taille de la fenêtre
  • data: object contenant l’ensemble des données du graphique
  • config: object contenant la configuration général de notre graphique
  • layout: object contenant la configuration graphique de notre graphique

 

Partie composant

On déclare nos attributs généraux :

 

J’initialise mes précédents attributs dans le constructeur du composant :

 

Par la suite, je vais charger mon fichier de données. J’utilise un fichier CSV qui va être lu en local via le httpClient :

 

Enfin, ma fonction permettant de parser mon fichier CSV de string :

Le plus important sont les lignes suivantes :

  • 4-5 : création de tableau temporaire, contenant nos données
  • 14-15: on remplit nos tableau déclarés précédemment des données du fichier CSV en cours de parsage
  • 23-24: ajout de nos nouvelles données

 

Voici le résultat de ce que l’on obtient selon le type de graphique que l’on choisit dans notre objet de data :

 

Vous avez une multitude de type de graphique selon ce que vous voulez donner comme aspect à vos données, je vous laisse lire la doc pour en savoir plus.

 

 

Création d’un graphique avec une multitude de courbe

On va reprendre l’exemple précédent, et y ajouter une nouvelle courbe concernant les cas soignés. Je vais enlever quelques données en début de pandémie, étant donné que l’on a eu des cas à partir du 1er Mars à peu près. Cela permettra une meilleure visibilité pour mon tutoriel.

 

On commence par ajouter une nouvelle courbe en ajoutant une donnée dans notre tableau de données. On fait cela comme précédemment, dans le constructeur du composant :

Vous pouvez apercevoir quelques changements comparé à la première partie de ce tutoriel :

  • marker : permet d’affecter une couleur à notre courbe
  • name : nom de la courbe dans la légende
  • legendgroup : permet de grouper plusieurs courbes dans un même groupe, et de pouvoir les cacher en cliquant dessus dans la légende pour toute les faire disparaître

 

La dernière étape va être de modifier notre fonction de parsing de notre fichier CSV qui contient nos données, afin de récupérer des informations pour une seconde courbes, qui sera elle concernant les cas soignés :

  • Lignes 4 : L’axe X des abscisses ne change pas, puisque on veut garder nos dates.
  • Lignes 6 et 18 : On va créer un nouveau tableau contenant des nombres, et le remplir de la même façon que précédemment, mais avec un indice différent et donc une donnée différente.
  • Lignes 29-30 : correspond à notre second objet de données créer précédemment. On fait attention de lui affecter en abscisses nos données DATE, et en ordonnés notre tableau contenant le nombre de cas soignés.

 

Voici le résultat de ce que l’on obtient selon le type de graphique que l’on choisit dans notre objet de data :

 

 

Quelques exemples de customisation de l’UI

Je vous présente quelques attributs plutôt chouettes pour changer rapidement le sous type de nos graphiques que je vous ai présenté précédemment, à savoir Scatter et Bar

Vous avez moyen de vraiment poussé beaucoup de chose dans l’UI du graphique, regardez la documentation si vous voulez des envies bien précises.

Sous-type de BAR

L’attribut ‘barmod’ se définit dans l’objet LAYOUT de notre graphique ( attribut ‘layout’ dans nos exemples précédents )

 

Espacement de BAR

Vous pouvez gérer l’espacement entre les bars pour optimiser la lisibilité de votre graphique. Vous avez deux arguments pour cela :

  • bargap : espacement entre les bars d’un même groupe
  • bargroupgap : espacement entre les bars de groupes différents

Ces deux arguments se définissent dans l’objet LAYOUT.

 

Sous-type de SCATTER

L’attribut ‘mode’ se définit dans l’objet DATA de notre graphique ( attribut ‘allData’ dans nos exemples précédents )

 

Conclusion

Vous avez donc accès pleinement à la librairie Plotly.js dans votre application Angular.

Rien de bien complexe sur son intégration donc, juste un zeste déroutant d’utiliser du Javascript dans du Typescript, on mélange du typage fort avec des objets que l’on remplit d’attributs à la volé.

Vous pouvez ajouter des events de clic, de listener, pour rendre tout cela un peu plus dynamique comme par exemple divers chargements de données pour combiner plusieurs sources, modifier en temps réel l’allure et l’UI des graphiques, etc.