Ligne de commande pour recharger une page dans Chrome

Pour lier le développement Web avec Eclipse JEE en profitant d’un rechargement « automatique » de la page dans Chrome, j’ai testé la solution d’utiliser l’option de démarre de ce dernier avec –remote-debugging-port=9222 .

En premier lieu, il faut configurer le démarrage de Chrome dans Eclipse via le Menu Windows > Preferences. Puis, il faut chercher « Web Browser » et ajouter les réglages dans « Parametres » (d’autres réglages sont présents dans cette copie d’écran)

Une fois que la première URL de déboggage est lancé dans Chrome, on doit trouver l’information sur l’URL de debuggage de l’onglet ouvert via cette ligne de commande sous Windows:

curl http://127.0.0.1:9222/json | findstr "devtoolsFrontendUrl"

ou avec Linux/MacOS

curl http://127.0.0.1:9222/json | grep "devtoolsFrontendUrl"

La réponse devrait être de cette forme:

"devtoolsFrontendUrl": "/devtools/inspector.html?ws=127.0.0.1:9222/devtools/page/33F5C3BF94DE9AC1FC756D161E5E5D6E",

La liaison avec Chrome se fait via une WebSocket indiquée par

ws=127.0.0.1:9222/devtools/page/33F5C3BF94DE9AC1FC756D161E5E5D6E

Pour ouvrir simplement une connexion WebSocket, on peut utiliser le logiciel Websockat (https://github.com/vi/websocat) pour envoyer une commande au Chrome.

echo {"id":0,"method":"Page.reload","params":{"ignoreCache":true}} | websocat_nossl_win64.exe -n1 ws://127.0.0.1:9222/devtools/page/33F5C3BF94DE9AC1FC756D161E5E5D6E

Il y a aussi l’option d’ouvrir une nouvelle page sur une URL

echo {"id":0,"method":"Page.navigate","params":{"url":"http://127.0.0.1:8080/test/LesTodos.jsp"}} | c:\DEV\websocat_nossl_win64.exe -n1 ws://127.0.0.1:9222/devtools/page/33F5C3BF94DE9AC1FC756D161E5E5D6E

Pour déclencher l’appel automatique après la publication d’un projet dans Eclipse, on peut utiliser les Builders.

Dans l’exemple ci-dessus, on utilise un fichier Ant Builder, mais la version avec « Program » peut aussi être utilisé en créant un fichier chrome.cmd à la racine du projet par exemple:

Il faut indiquer donc que le builder « Chrome debug reload » appelle le programme se trouvant dans ${workspace_loc:/test/chrome.cmd}. La seule option qui semble nécessaire dans l’onglet « Build Options » est « During auto-build »

Le contenu du programme chrome.cmd doit être le suivant avec modification du numéro lié à l’URL vue précédemment:

@echo off

ping 127.0.0.1 -n 2 > nul

echo {"id":0,"method":"Page.reload","params":{"ignoreCache":true}} | c:\DEV\websocat_nossl_win64.exe -n1 ws://127.0.0.1:9222/devtools/page/33F5C3BF94DE9AC1FC756D161E5E5D6E > nul 

On peut remarquer la commande ping qui permet d’attendre 2 secondes ici pour laisser le déploiement se faire sur le serveur Tomcat.

Une autre option est de passer par la console des outils de développement Web de chrome pour demander le rechargement de la page. Si les outils de développements Web sont activé dans Chrome on peut trouver un autre WebSocket de communication qui permet donc d’envoyer des commandes à ce dernier.

@echo off

ping 127.0.0.1 -n 2 > nul
echo {"id":0,"method":"Runtime.evaluate","params":{"expression": "history.go()"}} | c:\DEV\websocat_nossl_win64.exe -n1 ws://127.0.0.1:9222/devtools/page/EBE6422FBAE16A0A8A39BB637309DA8D > nul 

On exploite l’envoie de la commande JavaScript history.go() pour recharger la page locale. Il y a plusieurs solutions pour recharger la page dont aussi location.reload() . Au vu d’un problème de retard dans le rechargement de la page, j’ai doublé ces commandes pour être sûr d’avoir la « bonne page » affichée.

J’ai expérimenté avec curl pour faire la liaison en WebSocket mais sans succès pour envoyer les commandes. De la même façon, j’ai trouvé aussi plusieurs utilitaires alternatifs sous Linux/MacOs comme websocat qui semble aussi très bien.

À la fin, j’ai développé un programme complet qui fait normalement l’extraction de l’url correcte :


@echo off
SETLOCAL ENABLEDELAYEDEXPANSION

SET count=1
FOR /F "tokens=* USEBACKQ" %%F IN (`curl -s  http://127.0.0.1:9222/json`) DO (
  SET var!count!=%%F
  SET /a count=!count!+1
)

set str=%var3:"devtoolsFrontendUrl":=%
set str=%str:,= %
set str=%str:"/devtools/inspector.html?=%
set str=%str: =%
set str=%str:"=%
set str=%str:ws=%
set str=!str:~1!
set str=ws://%str%

ping 127.0.0.1 -n 2 > nul
echo {"id":0,"method":"Page.reload","params":{"ignoreCache":true}} | c:\DEV\websocat_nossl_win64.exe -n1 %str% > NUL 

ENDLOCAL

Publié dans IMT Mines Alès | Laisser un commentaire

Web Development

1. Networks concepts

Web development uses a network to link a software name Client to another software name Server. A common confusion is to speak about a dedicated computer as the Web Server or shorten as Server. The same shorten is to speak about Database as Database Server.

Between ClientServer software programs, there are a protocol which uses a unique IP address for each computer.

2. IP address

Each computer has at least one IP address the default IP address 127.0.0.1 also named localhost.

But on each network card as an Ethernet plug, a Wi-Fi card, a Bluetooth connection to a smartphone using as modem (also name: sharing connection).

Usually the terminal command ipconfig or ifconfig could show the list of IP Address.

If the computer is link via network or Wi-Fi to an internet Box, there are a local networks between the computer and the Box. For outside this local network (on Internet), the Internet Box provides a unique IP address and works as a mandatory for computers or smartphones link to the Internet Box.

3. Client

Web development uses a browser as classical client to display content from HTML, to apply a style to the content with CSS, to provide user interface with forms and advanced interactions with JavaScript.

Modern browsers provide tools for Web Development as IDEs.

Web developers usually work with Client and Server on the same computer with the IP address 127.0.0.1.

Other clients exist acting as a browser: Team application or a smartphone application are working as a browser with Web connection to a Server.

4. Server

Client Browsers communicate to a Server computer with the IP address of the computer which have a running Web Server software.

The connection should be a URL as protocol://IP Address:port number for example http://127.0.0.1:80/

Companies could buy a domain name from a registrar to provide a comprehensive name instead of IP address http://gitlab.mines-ales.fr/. The network provides a conversion from the domain name to the IP address (with DNS servers).

Usually a communication from Client Browser to a Web Server is named request or HTTP request. The Web Server sends back several HTTP responses as files with HTML, CSS, images, documents, video content, etc. using severals languages.

5. Port number

A software server program (as Web Server, Database, mail Server) with an Internet connection asks the computer to book a port number. Then a connection is open to the computer on a specific port to transfers data to the correct software.

A Web Server usually listen a specific port number into the computer. With a Web Server program for HTTP request, 80 is the default port, for HTTPS request, 443, for tomcat Web Server in development 8080.

With a MySQL Database Server, 3306 is the default port.

6. Asynchronous communication

The HTTP request sends from a Browser to Web Server could take a while. See Ajax later to display a trouble with the delay.

When the Web Server sends back contents, it could not know if the Client is still online without a new request from the Client

All requests are anonymous and independents by default (without using cookies and forms).

7. HTTP request

The HTTP request contains a lot of technical information send from the Client to the server and from the server to the Client.

The HTTP request sends a URL to the server to get content for example: http://127.0.0.1/cv/fr/cv-2020.pdf.

The Web Server sends back contents with HTTP request codes : usually code 200 everything is ok or 404 for missing content.

8. URL

The last slash of the URL indicates the root folder (aka DOCUMENT_ROOT) of the Web Server, a specific folder into the computer where contents into sub-folders will be sent.

Suppose a root folder as c:/WebServer/www/ and subs-folders c:/WebServer/www/CV/fr/ the correct URL to access a file cv-2020.pdf from the same computer will be http://127.0.0.1/CV/fr/cv-2020.pdf.

The Web Server default configuration is to list content if URL finish by slash as http://127.0.0.1/cv/fr/ if there are no file call index.html call by default in this case.

9. Languages

Web development use a set of several languages, each for a specific part of the process or the interaction between software. Web developers have to learn each usage of those languages.

Common Client side languages are :

HTML provides the structured content and basic interactions with user thrown forms.

CSS provides a way to apply a style a page layout to the HTML content.

JavaScript provides a way with interactions and dynamic the HTML content.

jQuery a JavaScript extension (or framework) is a simplification of JavaScript.

Commons Server side languages are:

Java / Python / PHP / ASP.Net / JavaScript server-side / C# languages provide a way to generate contents usually into HTML.

SQL provides a classical way to interact with databases

JSON provides a way to structure data to the Client with Ajax side and also to some other Database server or third-party software.

10. HTML

Web Server usually sent back content with a structure into the language HTML.

HTML language use opening and closing Tag, the global structure of an HTML page looks like with 2 parts head part (between <head></head>) and body part (between <body></body>)

<html>
  <head>
  </head>
  <body>
    Content visible
  </body>
</html>

The head part will include mainly CSS and JavaScript, few specific tags as <title></title>

The body part will include the visible content of the page displays into the Client browser render. To display the HTML part, right-click on the Client browser and choose « Show Source code » (or something close see IDEs)

11. Tag

A tag could be lonely as <img /> or also have several attributes as shows below by hyperlink tag <a></a> (href hyperlink attribute and target attribute to open into a new page)

<img 
 src="https://www.mines-ales.fr/themes/custom/boots/assets/images/logo.svg" 
/>

Visit our Web site:
<a href="https://www.mines-ales.fr/" target="_blank" >IMT Mines Al&egrave;s</a>

Tags could be included together into the correct opening-closing way:

<a href="https://www.mines-ales.fr/" target="_blank" >
<img 
 src="https://www.mines-ales.fr/themes/custom/boots/assets/images/logo.svg" 
/>
</a>

Shopping list:
<ul>
  <li> Paper </li>
  <li> Pen </li>
</ul>

12. CSS

A CSS rule/instruction could be applied to a tag. CSS is write into a <style></style> tag (place into header) or load from an external file with <link /> tag.

<head>
  <style> 
    a{
       color:red;
    }
  </style>

  <link href="http://www.mines-ales.fr/css/main.css" />

</head>

A Tag could have 2 attributes id and class use by CSS rules :

Office list:
<ul id="office">
  <li class="done"> Paper </li>
  <li> Pen </li>
</ul>

Market list: 
<ul id="market" class="urgent" >
  <li id="bread" class="done" > Bread </li>
  <li id="egg" class="done notfound" > Eggs </li>
</ul>

A collection of extensive selector could apply to identify a set or a unique tag ant then affect visual and styling effect (change background color, line through text, composition and space):

<style> 
#office{
  background-color: grey;
}
.done{
    text-decoration: line-through;
}
.urgent{
    background-color: red;
    padding:10px;
}
.notfound{
   margin-left:100px;
   color: green;
}
</style>

13. JavaScript

A programming language create to be trigger by events into the Client Browser. JavaScript is write into a <script></script> tag (place into header) or load from an external file with <script /> tag.

<head>
  <script> 
   function click(){
     var imgLogo = document.getElementById("imgLogo");
     imgLogo.src = "https://upload.wikimedia.org/wikipedia/fr/6/6d/Logo-IMT-Mines-Al%C3%A8s.jpg";
   }
  </script>

  <script src="http://www.imt.fr/javascript.js" />
</head>
<body>
   Click to see a different logo :
   <img 
      id="imgLogo"
      src="https://www.mines-ales.fr/themes/custom/boots/assets/images/logo.svg" 
      onclick="click()"
     />
</body>


The onclick attribut of <img/> could trigger a JavaScript function. The function creates a variable imgLogo by finding an Html tag by its attribute id imgLogo. The modification of attribute src of <img/> asks the Client Browser to change the image.

The manipulation of the HTML from JavaScript follows the DOM structure of the HTML page.

The default usage of JavaScript is not really common. JavaScript’s frameworks like jQuery are more common.

14. Relative or Absolute URL

HTML page contains call by URL to image, CSS/Javascript file, hyperlink tag, as see before with this set of tag.

<head>
    <script src="http://www.mines-ales.fr/js/javascript.js" />
    <link href="http://www.mines-ales.fr/css/main.css" />
</head>
<body>
   <img src="https://www.mines-ales.fr/themes/custom/boots/assets/images/logo.svg" />      
   <a href="https://www.mines-ales.fr/welcome/" target="_blank" >IMT Mines Al&egrave;s</a>

</body>

If this HTML page is loading from the Server with a URL like

http://www.mines-ales.fr/index.html

Is it very common to only use relative folder URLs to let Client Browser convert to absolute URL. Base folder will be in ours case from the top folder.

<head>
    <script src="js/javascript.js" />
    <link href="css/main.css" />
</head>
<body>
   <img src="themes/custom/boots/assets/images/logo.svg" />      
   <a href="welcome/" target="_blank" >IMT Mines Al&egrave;s</a>
</body>

Operators like ./ or .. or / could be use to create the correct convention from relative to URL to absolute URL. (./ is for same folder than initial HTML page, .. is for parent folder tan initial HTML page, / in first symbol is for top folder of Server).

15. Forms

A specific set of tags from HTML is dedicated to create forms to allow interaction with the user, as a login and password HTML page.

<body>
   <form method="get" action="http://127.0.0.1:8080/Controler">
      <input type="text" name="login" value="Please provide your login" />
      <input type="text" name="birthdate" value="Please provide your birth date" />
      <input type="password" name="pwd" />
      <input type="radio" name="interface" value="computer" />
      <input type="radio" name="interface" value="smartphone" />

      <input type="submit" name="action" value="Log me please" />
   </form>
</body>

The user could provide into 4 specifics fields of this form some information. When the user clicks the button « Log me please », all fields name and information provide will be sent to Server by the URL into attribute action.

About the field name interface, the value is specified by the tag and could be change by the user. The Client browser knows they are linked by their attribute name.

The attribute method value could be also post usually use with input field to send a file.

16. Java

Java could be use into a Web Server software call Tomcat Web Server (other Web Servers use Java but Tomcat is the reference) to create HTML content from a JSP Page or Servlet Page.

There are a short list of languages and Web Server as

Apache Web Server and Nginx Server could use C, PHP, Perl languages.

Django Web Server could use Python.

Internet Information Server could use C# and VB.Net

NodeJS could use JavaScript Server side.

All of them could create HTML content and receive information from forms.

Additional to Java, the Web developers will use Java software libraries to generate Unit tests or logging process systems and more.

17. JSP

A JSP page is a file creates with IDEs as Eclipse JEE to generate HTML page. Suppose the HTML page has to display the date of the day:

<%@page import="java.text.DateFormat"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<html>
<body> We are:
<%=java.text.DateFormat.getDateInstance( DateFormat.MEDIUM ).format(new java.util.Date())%>
</body>
</html>

The generation from Tomcat Web Server will create the HTML Page.

<html>
<body> We are: 
01/05/2025
</body>
</html>

The Web Developer will detect the pure HTML part and the Java part into the JSP page by using a specific non-HTML tag <% %>. The HTML generation is available into the Client Browser.

18. Servlet

A Servlet page is a file creates with IDEs as Eclipse JEE to generate an HTML page. Suppose the HTML page has to display the date of the day:

package model;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/date")
public class date extends HttpServlet {
   public date() {
       super();
   }

 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 	response.getWriter().append("We are: ").append(java.text.DateFormat.getDateInstance( java.text.DateFormat.MEDIUM ).format(new java.util.Date()));
 }

 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 	doGet(request, response);
 }
} 

The generation from Tomcat Web Server will create the HTML Page.

<html>
<body> We are: 
01/05/2025
</body>
</html>

But the Web Developer will not use the Servlet to generate HTML part because JSP Page are simplest to compare with HTML. The Servlet will receive information from forms. The MVC design pattern will be used to combine forms, JSP and Servlet Page.

19. IDEs

A Web Developer will use several software programs to create and tests Web applications.

Tomcat Web Server, JSP and Servlet Page will be use and create by using a specific IDE as Eclipse JEE.

An Eclipse JEE project will link Tomcat Web Server with a set JSP and Servlet Pages also CSS and JavaScript additional files, images and other documents as video, PDF files, etc.

The Client Browser as Chrome or Firefox will be use as an IDE to create, check and debug contents send by the Server mainly JavaScript, CSS and HTML. To activate the IDE part, usually the command CTRL+MAJ+I open the Web Developers Tools include into Chrome or Firefox.

The whole purpose is to give access to tools to debug and find errors easily into code.

20. Tomcat

Tomcat is a Web Server provides content from JSP, Servlet, JavaScript, CSS and HTML. Tomcat could receive several projects create by Eclipse JEE IDEs on the same computer or across several computers.

Tomcat convert JSP Page into Servlet Page compiles and deploy the project at a specific URL.

Tomcat is writing in Java and should be start with a JDK software not a JRE software program.

21. Database

A Database Server could be connected to Tomcat Web Server if a Java library is provide and if this library is compliant as JDBC protocol. The following example provides a demonstration to connect to an SQLite Database server.

 try {
  Class.forName("org.sqlite.JDBC");
  	connection = DriverManager.getConnection("jdbc:sqlite:c:/Developpement/todo.db");
 } catch (Exception e) {
 	System.err.println(e.getClass().getName() + ": " + e.getMessage());
 	System.exit(0);
 }
 System.out.println("Opened database successfully");

The same piece of code could be used to connect to MySQL or MariaDB or PostgreSQL Database server

If the Database Server is not started, the connection will fail. The connection could provide a login/password authentication mechanism to access the Database server.

22. SQL

SQL language is an historical and legacy language to manipulate data from a Database Server set of information store into a group of tables calls a Database.

In the following example, a command into SQL extracts only the name from a table of user order by lexicology.


Statement statement = connection.createStatement();

if (statement.execute("Select name FROM user order by name asc ")) {
  ResultSet resultSet = statement.getResultSet();
  while (resultSet.next()) {
	String name = resultSet.getString("name");
  }
}

Complex SQL command could be created to manage complex operations.

But the Web Developer will not use the Servlet to generate HTML part because JSP Page are simplest to compare with HTML. The Servlet will receive information from forms.

23. DOM

Into the Client Browser the combination of tags is consider by Web Developers as a Document Object Model with root element, parent, children and brothers elements.

CSS and jQuery use a set of symbol to describe links between tag. Suppose an HTML page as bellow:

<html>
<head>
    <script src="http://www.mines-ales.fr/js/javascript1.js" />
    <script src="http://www.mines-ales.fr/js/javascript2.js" />
</head>
<body>
  <ul id="office">
    <li class="done"><a href="#"> Command </a></li>
    <li> Ask </li>
    <li> Cancel </li>
  </ul>
  <a href="#"> Delete </a>
</body>
</html>

DOM stores <scripts> tags as brothers, <scripts> tags have on parent <head></head> tag.

The Web developers should know several symbol to select element depending on another. // is the symbol of comment and use as into a CSS page in this case.

// Full path on an element so specific not really use
html > body > ul#office

// Simpliest solution and ID should be unique
#office

// Only apply a setting to the direct children of body
body > a

// Apply of all children and sub-children de type a into body
body a 

// Brother of tag f class done, so <li> Ask </li> and <li> Cancel </li>
.done | li

// Only the last children of office so <li> Cancel </li>
#office:last-child

A complex set of additional symbol selectors exist but out of the field of this page.

But the Web Developer will not use the Servlet to generate HTML part because JSP Page are simplest to compare with HTML. The Servlet will receive information from forms.

24. Jquery

jQuery is a library write into JavaScript also call a framework providing a way to avoid a strong link between JavaScript and HTML DOM.

To link a click event onto a specific HTML tag, Jquery use a special function call $ to find HTML element without add attribute on tag.


<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  <script> 
   function basicClick(){
     var imgLogo = document.getElementById("imgLogo");
     imgLogo.src = "https://upload.wikimedia.org/wikipedia/fr/6/6d/Logo-IMT-Mines-Al%C3%A8s.jpg";
   }


$(document).ready(function(){
    $("img#imgLogo").click( basicClick );
}); 
  </script>


</head>
<body>
   Click to see a different logo :
   <img 
      id="imgLogo"
      src="https://www.mines-ales.fr/themes/custom/boots/assets/images/logo.svg" 
     />
</body>
</html>

This version is not « very » Jquery because a Web Developers will replace the name of the function by a direct call as below.


<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  <script> 

$(document).ready(function(){

    $("img#imgLogo").click( function() {
      $( this ).src = "https://upload.wikimedia.org/wikipedia/fr/6/6d/Logo-IMT-Mines-Al%C3%A8s.jpg";
    }
   );

}); 
  </script>

</head>
<body>
   Click to see a different logo :
   <img 
      id="imgLogo"
      src="https://www.mines-ales.fr/themes/custom/boots/assets/images/logo.svg" 
     />
</body>
</html>

jQuery knows which HTML tag is pressed by using again the function $ to find it.

25. Ajax

Ajax is a way to call the Server from JavaScript to send and receive information into an XML or a JSON format in the background of the HTML page.

jQuery way of using Ajax is simpler than pure JavaScript, the example will be in jQuery.

The Web Server will send an XML Page below

<now>01/12/2035</now>

Or JSON version

{ now:'01/12/2035' }

<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  <script> 
   
$(document).ready(function(){
  $("#dateNow").click( 
    function (){     
      $.ajax({
        url: 'http://127.0.0.1/date.jsp',
        type: 'GET',
        dataType: 'xml',
        success : function(result){
           $("#dateNow").html( result.innerHtml );
        }
      });
   
    });

});
  </script>


</head>
<body>
   Click to show date:
   <p id="dateNow">
   </p>
</body>
</html>

This version with JSON is only different into the success function call and the dataType.


<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  <script> 
   
$(document).ready(function(){
  $("#dateNow").click( 
    function (){     
      $.ajax({
        url: 'http://127.0.0.1/date.jsp',
        type: 'GET',
        dataType: 'json',
        success : function(result){
           $("#dateNow").html( result.now);
        }
      });
   
    });

});
  </script>


</head>
<body>
   Click to show date:
   <p id="dateNow">
   </p>
</body>
</html>

jQuery knows which HTML tag is pressed by using again the function $ to find it.

26. JSON

The way to format data to exchange from JavaScript to with the Server was XML at first but JSON is short and could be convert directly into variables and uses as a DOM.

{
    "menu": {
        "id": "file",
        "value": "File",
        "popup": {
            "menuitem": [
                { "value": "New", "action": "CreateNewDoc" },
                { "value": "Open", "action": "OpenDoc" },
                { "value": "Close", "action": "CloseDoc" }
            ]
        }
    }
}

Or XML version


 <menu id="file" value="File">
   <popup>
     <menuitem value="New" action="CreateNewDoc"/>
     <menuitem value="Open" action="OpenDoc"/>
     <menuitem value="Close" action="CloseDoc"/>
   </popup>
 </menu>

jQuery and JavaScript know how to convert a JSON string into a variable to display into the Client IDEs console the content of the id attribute.

var obj = JSON.parse('{ "menu": { "id": "file", "value": "File", "popup": { "menuitem": [ { "value": "New", "action": "CreateNewDoc" }, { "value": "Open", "action": "OpenDoc" }, { "value": "Close", "action": "CloseDoc" } ] } } ');

console.log( obj.menu.id );

27. Cookies

The Server could send several couple keys/values of information to the Client Browser. Each time a URL is send to the same Server, keys/values are send from the Client to the Server.

The Web Developer uses cookies to identify the user after a successful login/password page.

28. MVC

To convert the design pattern MVC with Web Development, Tomcat development process could be use.

A Servlet page will be in use as a Controller to receive information and manipulate Model and DAO parts of the project., then forward information to View part.

One JSP Page could be used to display one interface or View to simplify the process and the structure of the project.

Model part could be tested by Unit test program include into the Tomcat project.

29. DAO

Data Access Object is a design pattern to separate the loading of information from Database to Model POJO instance.

The main idea is to avoid loading information from the database into the Controller part but use Model part to manage information and then store them into the Database.

30. Unit test

Unit test a method is an advanced way to test the whole program by trying to avoid error and regressions. The web Developer could imagine a method and usually another Developer create a Unit Test method dedicated to test this method.

Suppose a method which add a String to the list only if this String not exist into but in this case, suppose an error of testing vale of indexOf method (-1 if element not exist instead of zero) :

List<String> listOfString = new  java.util.ArrayList<String>();

private void addOnlyNotExist(String element){
  if ( listOfString.indexOf( element  ) == 0 ) {
    listOfString.add( "test" );      
   }
}

Suppose a test method to check a double String not exist

private void testAddOnlyNotExist(){
  addOnlyNotExist( "test" );
  addOnlyNotExist( "test" );
  System.out.println( listOfString .size() );

}

A Unit test framework library as JUnit will be used to automatization of report of all Unit test method.

31. POJO

Plain Old Java Object is a way to speak of instances and classes which the purpose is only to store information. The following example will show a POJO of Person link to a POJO a Phone

class Person{
    private int ID;
    private String name;
    private int age;
    private List<Phone> phones = new ArrayList<Phone>();
     
}

class Phone{
    private int ID;
    private String phoneNumber;
    private String name; 
}

The 2 POJO missing getters and setters and some additional methods to work, but their purposes are really clear and simple to manage the Model part of MVC.

32. equals() & hashCode()

A POJO usually provides 2 specifics method call equals and hashCode.

Equals is well-know to compare String instance ( « test ».equals(« TEST ») ) but suppose two instances of POJO Person how to compare them ?

Suppose a case, it is a specification 2 instance of Person are the same if their property name are equals.

class Person{
    private int ID;
    private String name;
    private int age;
    private List<Phone> phones = new ArrayList<Phone>();

    public boolean equals(Object obj) {
      if (obj == null) return false;
      if( ! (obj instanceof Person) ) return false;
      Person other = (Person) obj;
      return this.name !=null ? this.name.equals(other.name) : this.name == other.name;
    }     
}

The hashCode method is less used, usually to create an order between instance of POJO

class Person{
    private int ID;
    private String name;
    private int age;
    private List<Phone> phones = new ArrayList<Phone>();
     
   public int hashCode() {
     return this.ID;
   }
}

With this solution, 2 instances of Person will be order by their ID into a HashMap or a HashSet. It could be more performant to group instance on another criteria like using a conversion of property name into int value as Eclipse generation offers below.

In this case a HashMap or a HashSet will be performant to order instance by their property name:

class Person{
    private int ID;
    private String name;
    private int age;
    private List<Phone> phones = new ArrayList<Phone>();
     
  public int hashCode()
  {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((name == null) ? 0 : name.hashCode());
    return result;
  }
}

33. Debug

Eclipse JEE could start a Tomcat server with a project into Debug mode to place breakpoints into Java code, finding state of variables and chains of instructions into the Server side program .

Client Browser with Web Development Tools provides HTML contents access as DOM inspector, network information, JavaScript breakpoints, CSS editor, HTTP request content, log console, etc.

Challenging the process of Debug into the Asynchronous communication between Client and the Server is a goal of the Web Developer.

34. Form & Parameters

A Tomcat Servlet could receive a list of parameters from an HTML Form. Into a the Servlet, it is possible to display all the name of the parameters from the URL coming also from the Form


for(String parameterName : request.getParameterMap().keySet()) { 
   System.out.println( parameterName);
}

Suppose a Form with values not changed by the user as bellow:

<form method="get" action"./Controleur" />
  <input type="hidden" name="sessionId" value="123456" />
  <input type="text" name="todo_text" value="Bred" />
  <input type="checkbox" name="todo_actif" value="todo_actif_bred" checked />
  <input type="submit" name="action" value="add Todo" />
</form>

The URLs create will be :


http://127.0.0.1:8080/Project/Controleur?sessionId=123456&todo_text=Bred&todo_actif=todo_actif_bred&action=add+Todo

The Java code will display:

sessionId
todo_text
todo_actif
action

Publié dans IMT Mines Alès | Laisser un commentaire

X-Sens Dot Sensor

Dans le cadre d’un projet de recherche, j’ai testé un senseur de chez X-Sens: X-Sens Dot :

Ce capteur doit permettre de remonter des informations accélération pour l’expérience. Devant la documentation en ligne sur ce dispositif et avec l’accord du support très réactif de l’entreprise X-sens, je pense qu’un tutoriel plus complet sur ce dispositif peut être utile au plus grand nombre.

Des informations actuellement que je dispose, je n’ai pas trouvé de solution pour connecter mon Windows 10 sur le X-Sens, le développement se fait via mon smartphone android (un samsung S10+) et avec Android Studio.

Je ne peux que vous conseiller de télécharger l’application officielle (xsensdot-apk-v2020.0.apk en Avril 2020) de X-Sens pour les X-Sens Dot et le SDK X-Sens Dot dans la rubrique Software/Wearable Sensor: https://www.xsens.com/software-downloads

Le SDK contient une documentation PDF et .chm et un fichier XsensDotSdk.aar qui a servi de base à ce tutoriel.

 

1/ Démarrage d’Android Studio

En premier lieu créons dans Android Studio un nouveau projet se basant sur une Activity vide:

Configuration du projet avec un nom, un nom de package, un dossier de stockage et surtout une version de SDK minimale à API 22 selon les recommandations de la documentation:

En premier ajoutons les droits spécifiques et nécessaire sur cette application, il est à noter que je déploie sur un smartphone réel et non vers l’émulateur. Je trouve que c’est plus rapide et plus efficace de développer sur un smartphone réel en suivant ces recommandations sur developer.android.com.

Ajoutons donc ces permissions, qu’il faudra activer aussi sur le smartphone individuellement pour Storage et Position (voir plus bas dans le tutoriel):

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

 

2/ Importation de XsensDotSdk.aar

L’importation d’un module aar se fait en plusieurs étapes que j’ai découvert avec ce projet.

En premier lieu, il faut indiquer l’importation de ce module via le Menu File > New > New Module … puis choisir « Import .JAR/.AAR Package » , faire Next:

 

Indiquer le chemin vers le module XsensDotSdk.aar (pour le nom du subproject le laisser par défaut):

Ce n’est pas parce que le module est importé en tant que subproject que notre projet a une dépendance envers lui.

Donc, Menu File > Project Structure … > puis Dependencies > app (notre projet par défaut) puis le petit bouton + (Add Depency) puis choisir « Module Depency » :

 

 

 

Indiquons que l’on veut une dépendance vers XsensDotSDK, Ok pour valider cette fenêtre et ensuite de nouveau OK pour valider la fenêtre précédente:

Une phase de build se déclenche plus ou moins longue selon la performance de son ordinateur…

 

3/ Utilisation des classes du  XsensDotSdk.aar

Nous allons travailler dans ce tutoriel sur la MainActivity, ce n’est pas l’idéal mais pour un développement de test nous pouvons réaliser un premier essai.

Ajoutons l’implémentation des classes XsensDotDeviceCv et XSensDotScannerCb:

Nous avons une erreur d’importation que l’on règle en laissant la souris sur les 2 classes problématiques, IntelliJ nous propose d’importer les packages manquants:

Nous pouvons maintenant aussi fabriquer les implémentations manquantes pour les méthodes nécessaires aux classes XsensDotDeviceCv et XSensDotScannerCb en survolant avec notre curseur ces dernières:

 

L’ajout de toutes les méthodes se fait rapidement:

 

 

4/ Développement des fonctions de connexion au X-sens DOT

Nous allons donc coder dans la méthode onCreate encore une fois par simplicité puis nous détecterons que le smartphone a bien trouvé le X-Sens Dot en mettant un point d’arrêt dans la méthode onXsensDotScanner:

public void onXsensDotScanned(BluetoothDevice bluetoothDevice) {

Donc on code une propriété mxScanner

private XsensDotScanner mXsScanner;

Puis dans la méthode onCreate :

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    String version = XsensDotSdk.getSdkVersion();
    XsensDotSdk.setDebugEnabled(true);
    XsensDotSdk.setReconnectEnabled(true);
    mXsScanner = new XsensDotScanner(this.getApplicationContext(), this);
    mXsScanner.setScanMode(ScanSettings.SCAN_MODE_BALANCED);
    mXsScanner.startScan();
}

 

Enfin un bout de code pour récupérer les informations sur le device:

@Override
public void onXsensDotScanned(BluetoothDevice bluetoothDevice) {
    String name = bluetoothDevice.getName();
    String address = bluetoothDevice.getAddress();
}

Choisissez ensuite votre smartphone (il faut que le débuggage soit possible sur ce smartphone d’ailleurs cf developer.android.com) puis le bouton « débug app » :

Voici les indications de débugage avec les adresses (factice sur cet écran) de réponse:

Ajoutons maintenant la récupération des données par le capteur en ajoutant une nouvelle propriété et  en modification la méthode onXsensDotScanned:

Nouvelle propriété: xsDevice pour gérer la connexion à notre Xsens Dot

private XsensDotDevice xsDevice = null;

 

Nouvelle version de onXsensDotScanned

@Override
public void onXsensDotScanned(BluetoothDevice bluetoothDevice) {
    String name = bluetoothDevice.getName();
    String address = bluetoothDevice.getAddress();

    xsDevice = new XsensDotDevice(this.getApplicationContext(), bluetoothDevice,MainActivity.this);
    xsDevice.connect();
    xsDevice.startMeasuring();
}

Notre X-Sens Dot devrait capture les données dans la méthode onXsensDotDataChanged et l’envoyer dans le loger LogCat d’Android:

@Override
public void onXsensDotDataChanged(String address, XsensDotData xsensDotData) {
    Log.i( "XsensDot", "onXsensDotDataChanged " + address + " " + xsensDotData );
}

 

Nous lançons le débugage avec un point d’arrêt sur l’évènement onXsensDotDataChanged et un regard sur le LogCat dans IntelliJ:

Aucune donnée n’arrive sur la méthode onXsensDotDataChanged….

 

5/ Ajout des droits dans le smartphone

Les données n’arrivent pas car il faut ajouter les droits sur l’application directement sur ce dernier. j’avais eu déjà le problème avec les IMU embarquées dans le smartphone.

Il faut donc aller sur l’application, faire un appuie long, puis choisir « Infos sur l’appli. » puis dans l’écran « informations sur l’application » choisir le menu « Autorisations » puis accepter les 2 autorisations « Localisation » et « Stockage » pour enfin pour relancer l’application avec les droits complets:

Et donc récupération des données sur un point d’arrêt du débug quand les données arrivent:

 

6/ Liaison Xsens DOT – Smartphone Android – Code JAVA

Pour la récupération des données de l’accélération  angulaire sur X du capteur Xsens DOT, j’ai utilisé une liaison bluetooth additionnel de type Port COM à 115200 bauds avec un programme en Java sur mon PC:

 

Vous pouvez constater sur la vidéo ci-dessous que le résultat est quand même assez impressionnant, la rotation de ma main déclenche bien le déplacement du point rouge sur le smartphone et l’envoie au PC de l’information Gauche/Droite/Centre pour faire réaliser le même déplacement au point vert.

Il y a un délais bien sur entre la modification d’orientation et le déplacement du point. L’algorithme doit être améliorer pour diminuer ce délais.

7/ Nouvelle version des SDK de Xsens

Suite à la conférence d’Avril 2020 de Xsens, j’ai la possibilité de récupérer les données directement depuis le PC. Donc la nouvelle version doit être directement développée sur l’ordinateur pour récupérer les données via le protocole Bluetooth BLE.

Pour simplifier le développement sur Windows, j’ai développé le code en C#. En effet, mes anciens développement avec le bluetooth m’ont montré que ce langage est le plus proche du système d’exploitation sur windows; aucune surprise le langage C# appartient à Microsoft. Du coup, je pense que les ouvertures/fermetures des canaux de communication bluetooth BLE seront simplifiées par ce langage de programmation.

Mon conseil est d’en premier lieu de travailler à partir du document « Xsens DOT BLE Services Specifications » proposé en téléchargement par Xsens sur son site internet. Ce document indique bien une évolution dans l’accès à certaines données envoyés par la nouvelle version (1.3) des Xsens. Personnellement, je vais continuer à utiliser la version 1.0.0 car moins de données = plus simple à interpréter.

Nota: attention au format big-endiant/little-endian des données, j’ai passé un peu de temps en lisant les octets dans le mauvais ordre.
Ce n’est pas encore standardisé, heureusement la documentation indique « All the big-endian members will be changed to little-endian in the next firmware release ».

Le développement a du être mis en stand-by pour cause de projet en parallèle, mais les premiers résultats sont encourageant. Le standard Bluetooth BLE est bien accepté par le xSens DOT comme montre la vidéo suivante qui affiche les accélérations du composant sur un seul axe.

Démonstration de la liaison bleutooth BLE du Xsens avec un développement C# sur un PC Windows 10 Pro version 18362 (Indiquer ma version n’est pas anodin pour le développement bluetooth BLE).

Publié dans Développement | Laisser un commentaire

git sourcesup

https://sourcesup.renater.fr/account/
Mettre un mot de passe du compte unix
Vérifier le mot de passe: https://sourcesup.renater.fr/account/change_pw.php

Trouver l’URL
URL : https://pierre.jean@git.renater.fr/authscm/pierre.jean/git/rearm/rearm.git cf copie d’écran en dessous pour le trouver
login UNIX pierre.jean
le BON MDP de SOurcesup

Ouvrir GitHub Desktop, faire clone a repository du smart https
https://pierre.jean@git.renater.fr/authscm/pierre.jean/git/rearm/rearm.git

—–
Ne fonctionne plus ?

Commande
git init

git clone ssh://git@git.renater.fr:2222/nom_projet.git

git clone https://pierre.jean@git.renater.fr/authscm/pierre.jean/git/rearm/rearm.git

Ouvre fenêtre authentification pour cloner sauf…

git config –global user.email « pierre.jean@mines-ales.fr »
git config –global user.name « pierre.jean »
git add rearm
git commit -m « Message de validation »

Publié dans Développement | Laisser un commentaire

Taiga Docker surprises

 

Pour une première étape avec Docker, j’ai essayé d’installer le logiciel taiga via cet outil de container. La solution la plus classique serait de prendre une image ubuntu et de suivre l’installation de docker (Setup development installation taiga).

Sauf qu’après avoir suivi une formation de Docker, j’ai compris que l’intérêt de Docker ou du moins un intéret est dans les micro service soit d’avoir 5 containers au lieu d’un seul.


NOTE: Vous avez un problème pour impoter votre projet taiga dans taiga (par exemple après une mise à jours) ?

Taiga contient un utilitaire qui se trouve dans le cotnaineur taiga-back et qui permet de faire l’importation suivant cette commande:

/usr/bin/python3 manage.py load_dump dump.json p.jean@mines-ales.fr

 

 

Taiga et Docker

Taiga est un logiciel de gestion de projet agile de type assez classique avec kanban et spring intégré. Ce que j’aime dans Taiga en plus qu’il soit open source est que l’on peut activer ou non les outils agile, par exemple commencé avec un simple kanban et ensuite rajouter des sprint et/ou un wiki et/ou un gestionnaire de bug.

Taiga n’a pas de version officielle de Docker. Plusieurs images sont disponibles mais j’avoue que parfois les personnes qui ont fait les images avaient des idées très précises de leur utilisation qui ne m’allait par.

Dans ma solution je souhaite que Docker puisse gérer les cinq containers avec l’avantage de pouvoir renforcer un container ou le remplacer au besoin :

  • taiga-db database postgreSQL
  • taiga-front pour la partie front web de Taiga
  • taiga-back pour la partie backoffice de Taiga
  • taiga-rabbit pour le gestionnaire de message dans Taiga
  • taga-events pour l’envoie des notifications dans Taiga via le navigateur
  • taiga-proxy pour le serveur front nginx dispatchant les requêtes.

L’image de docker de base

Je pars donc d’une image existante de docker. En fait, j’en essaye plusieurs avant de trouver une image qui correspond à ce que je souhaite soit avec une base de données et avec la partie notifications/messages.

La version suivante : https://github.com/docker-taiga/taiga semble être un bon compromis. Je télécharge donc le dépot github et je fais une installation sans problème sur un serveur linux de test.

Hors, cette installation ne fonctionne qu’une seule fois. Je n’arrive pas en relançant à récupérer le fonctionnement de mon serveur taiga. Après plusieurs essaies et avec l’obligation de devoir intégrer mes propres développements dans Taiga, je suis donc contraint de prépare une installation à partir du fichier docker-compose.yml.

 

Docker-taiga-pje

Pourquoi faire une version de taiga docker personnelles:

  • Je souhaite intégrer 1 fichier et une bibliothèque python en plus.
  • Je souhaite débugger avec un outil curl dans taiga-back et taiga-proxy
  • Je souhaite que le déploiement se fasse tout seul avec le minimum d’intervention de ma part
  • Le container taiga-back contient un serveur web nginx qui fait double emploie pour moi avec le serveur taiga-proxy en frontal
  • Monter en compétence avec Docker avec un exemple et des contraintes réelles
  • Docker sur Windows 10 avec tout les désavantages que l’on y trouve (et il y en a Docker est fait pour Linux et cela se voit)

La première étape que je vais faire est de créer un dossier pour le taiga-proxy et modifier le code de nginx.conf et nginx_ssl.conf pour que le nginx de ce container aille chercher le http://back:8000/. Cela suppose aussi la modificaiton du docker-compose.yml pour qu’il prenne en charge cette nouvelle image appelée taiga-proxy-pje.

Puis je faire la même modification pour le taiga-back pour qu’il prenne en charge de nouveau modules python et modifier le script de démarrage pour ne pas charger le serveur nginx. J’en profiterai pour que le port 8000 de ce container soit accessible pour faire le débogage avec curl installé dans ce container.

 

Etape 1 création de l’image taiga-proxy-pje

Téléchargement des fichiers du dépot git-hub depuis https://github.com/docker-taiga/proxy

 

Version initiale du fichier nginx.conf

server {
	server_name $TAIGA_HOST;
	listen 80;
	location ^~ /events {
		proxy_pass http://$EVENTS_HOST:8888/;
		proxy_http_version 1.1;
		proxy_set_header Upgrade $http_upgrade;
		proxy_set_header Connection "upgrade";
		proxy_connect_timeout 7d;
		proxy_send_timeout 7d;
		proxy_read_timeout 7d;
	}
	location ^~ /api {
		include proxy_params;
		proxy_pass http://$TAIGA_BACK_HOST;
	}
	location ^~ /admin {
		include proxy_params;
		proxy_pass http://$TAIGA_BACK_HOST;
	}
	location ^~ /static {
		include proxy_params;
		proxy_pass http://$TAIGA_BACK_HOST;
	}
	location ^~ /media {
		include proxy_params;
		proxy_pass http://$TAIGA_BACK_HOST;
	}
	location / {
		include proxy_params;
		proxy_pass http://$TAIGA_FRONT_HOST;
	}
}

Version modifiée du fichier nginx.conf

server {
server_name $TAIGA_HOST;
listen 80;
location ^~ /events {
proxy_pass http://$EVENTS_HOST:8888/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection « upgrade »;
proxy_connect_timeout 7d;
proxy_send_timeout 7d;
proxy_read_timeout 7d;
}
location ^~ /api {
include proxy_params;
proxy_pass http://$TAIGA_BACK_HOST:8000;
}
location ^~ /admin {
include proxy_params;
proxy_pass http://$TAIGA_BACK_HOST;
}
location ^~ /static {
include proxy_params;
proxy_pass http://$TAIGA_BACK_HOST;
}
location ^~ /media {
include proxy_params;
proxy_pass http://$TAIGA_BACK_HOST;
}
location / {
include proxy_params;
proxy_pass http://$TAIGA_FRONT_HOST;
}
}

Maintenant dans le dossier taiga-pje/proxy en ligne de commande pour construire l’image taiga-proxy-pje :

docker build -t taiga-proxy-pje .

Il faut ensuite modifier le fichier docker-compose.yml pour ne plus appeler l’image taiga-proxy mais l’image taiga-proxy-pje, donc après avoir téléchargé tous les fichiers du dossier taiga via git

git clone –depth=1 -b latest https://github.com/docker-taiga/taiga.git

Nous obtenons le dossier suivant:

Nous pouvons donc ensuite modifier le fichier docker-compose.yml:

version: ‘3’

services:
back:
image: taiga-back
container_name: taiga-back
restart: unless-stopped
depends_on:
– db
– events
networks:
– default
volumes:
– ./data/media:/taiga-media
– ./conf/back:/taiga-conf
env_file:
– variables.env

front:
image: dockertaiga/front
container_name: taiga-front
restart: unless-stopped
networks:
– default
volumes:
– ./conf/front:/taiga-conf
env_file:
– variables.env

db:
image: postgres:11-alpine
container_name: taiga-db
restart: unless-stopped
networks:
– default
env_file:
– variables.env
volumes:
– ./data/db:/var/lib/postgresql/data

rabbit:
image: dockertaiga/rabbit
container_name: taiga-rabbit
restart: unless-stopped
networks:
– default
env_file:
– variables.env

events:
image: dockertaiga/events
container_name: taiga-events
restart: unless-stopped
depends_on:
– rabbit
networks:
– default
env_file:
– variables.env

proxy:
image: taiga-proxy-pje
container_name: taiga-proxy
restart: unless-stopped
depends_on:
– back
– front
– events
networks:
– default
ports:
– 80:80
– 443:443
volumes:
#- ./cert:/taiga-cert
– ./conf/proxy:/taiga-conf
env_file:
– variables.env

networks:
default:

 

Pour fabriquer l’ensemble des containers en allant chercher les images, la magie de docker est appeler avec

cd taiga
docker-compose.exe up -d

Pour mémoire, le dossier taiga/ contient le docker-compose.yml qui va faire l’assemblage des images et le dossier proxy contient l’image spéciale docker-proxy-pje.

Rapidement, vous allez faire un fichier go.bat avec:

cd proxy
docker build -t taiga-proxy-pje .
cd ..
cd taiga
docker-compose.exe up -d
cd ..

 

et un purge.bat qui fait plusieurs actions: retire les fichiers indiquant que ce démarrage n’est pas la version initiale, arrête l’option redémarrage des container pour pouvoir les arrêter :

  • retire les fichiers .initial_setup.lock qui indiquent que la configuration a déjà été faite (cf processus de création des fichiers conf ci-dessous)
  • mettre à jours le critères restart à no pour me permettre d’arrêter les containers car sinon docker les redémarre automatiquement, vous pouvez aussi faire docker update –restart=np $(docker ps -q) pour empecher tous les containers en fonctionnement de redémarrer
  • effacer les containeurs
  • effacer les images
  • effacer les volumes non utilisé par aucun container, attention cela pourrait retirer aussi d’autres volumes qui ne serait pas lié à des containers
rm taiga/conf/back/.initial_setup.lock
rm taiga/conf/front/.initial_setup.lock
rm taiga/conf/proxy/.initial_setup.lock
docker update –restart=no $(docker ps -a -q –filter « name=taiga-proxy » –filter « name=taiga-events » –filter « name=taiga-front » –filter « name=taiga-rabbit » –filter « name=taiga-db »)
docker rm taiga-proxy taiga-back taiga-events taiga-front taiga-rabbit taiga-db
docker rmi taiga-proxy-pje dockertaiga/front dockertaiga/events dockertaiga/rabbit dockertaiga/back
docker volume prune –force

Attention c’est assez violent de retirer tous les volumes non utilisé. Dans mon cas je n’avais que les containers et images liés à taiga.

Processus de créations des fichiers

J’ai eu beaucoup de problème pour comprendre qui fabrique les fichiers dans le dossier taiga/conf. En effet, au premier démarrage des containers taiga-back, taiga-proxy, taiga-front, le script appelé par le RUN (habituellement start.sh) de chaque Dockerfile va créer les dossiers et fichiers de la configuraton pour qu’au redémarrage du container, ces fichiers soient utilisés au lieu de les recréer à chaque fois. Le problème est de créer un processus complet de fabrication et non pas de bricoler dans les fichiers de taiga/conf/. On peut modifier ces fichiers pour tester quelqus réglages de nginx par exemple mais il faut bien qu’à la fin on ai la totalité du processus from scratch

Enfin, j’ai un taiga proxy qui appelle sur le port 8000, le serveur django. Maintenant, il faut configurer le taiga-back pour ne pas utiliser le nginx inclus mais directement le django

taiga-back-pje

Création du dossier back et modification du fichier go.sh

cd proxy
docker build -t taiga-proxy-pje .
cd ..
cd back
docker build -t taiga-back-pje .
cd ..

cd taiga
docker-compose.exe up -d
cd ..

 

et purge.bat:

rm taiga/conf/back/.initial_setup.lock
rm taiga/conf/front/.initial_setup.lock
rm taiga/conf/proxy/.initial_setup.lock
docker update –restart=no $(docker ps -a -q –filter « name=taiga-proxy » –filter « name=taiga-events » –filter « name=taiga-front » –filter « name=taiga-rabbit » –filter « name=taiga-db »)
docker rm taiga-proxy taiga-back taiga-events taiga-front taiga-rabbit taiga-db
docker rmi taiga-proxy-pje dockertaiga/front dockertaiga/events dockertaiga/rabbit taiga-back-pje
docker volume prune –force

 

Dans notre dossier back, nous allons trouver:

d—– 11/06/2019 11:04 users <— Le dossier contenant le nouveau fichier python pour l’OTP
-a—- 13/06/2019 18:43 1225 config.py <— Le fichier de configuration de taiga back
-a—- 08/06/2019 14:52 1956 Dockerfile <— Le fichier Dockerfile où le travail est le plus important
-a—- 02/06/2019 17:26 1466 Dockerfile.v0 <— Fichier Dockerfile initial, pour voir entre Linux et Windows
-a—- 08/06/2019 14:17 157 ntpd.conf <— Le container n’a pas accès à l’heure, cf plus bas
-a—- 13/02/2019 10:26 74 README.md <— Le fichier README de github
-a—- 10/06/2019 20:05 2015 start.sh <— Le nouveau fichier start.sh qui va bien changer

Il faut avec le terminal créer une nouvelle image docker-back que l’on va appeler docker-back-pje.

docker build -t taiga-back-pje .

Cette commande fabrique une nouvelle image de taiga-back. Sauf que sur windows, j’ai une erreur :

WARNING: Ignoring APKINDEX.b89edf6e.tar.gz: No such file or directory
WARNING: Ignoring APKINDEX.737f7e01.tar.gz: No such file or directory

Cette erreur vient d’un problème de dossier cache des packages d’alpine.

La solution est de modifier le dockerfile pour détruire ce cache et d’ajouter le package ca-certificates.
Je rajoute aussi le package « jq » pour avoir un outil d’affichage des données json lisible.

FROM alpine:latestENV TAIGA_HOST=taiga.lan \
TAIGA_SECRET=secret \
TAIGA_SCHEME=http \
POSTGRES_HOST=db \
POSTGRES_DB=taiga \
POSTGRES_USER=postgres \
POSTGRES_PASSWORD=password \
RABBIT_HOST=rabbit \
RABBIT_PORT=5672 \
RABBIT_USER=taiga \
RABBIT_PASSWORD=password \
RABBIT_VHOST=taiga \
STARTUP_TIMEOUT=15sWORKDIR /srv/taigaRUN rm -rf /var/cache/apk/* && rm -rf /tmp/* \
&& apk –no-cache add python3 gettext postgresql-dev libxslt-dev libxml2-dev libjpeg-turbo-dev zeromq-dev libffi-dev nginx \
&& apk add –no-cache –virtual .build-dependencies musl-dev python3-dev linux-headers git zlib-dev libjpeg-turbo-dev gcc ca-certificates jq \
&& mkdir logs \
&& git clone –depth=1 -b stable https://github.com/taigaio/taiga-back.git back && cd back \
&& sed -e ‘s/cryptography==.*/cryptography==2.3.1/’ -i requirements.txt \
&& pip3 install –upgrade pip \
&& pip3 install -r requirements.txt \
&& rm -rf /root/.cache \
&& apk del .build-dependencies \
&& rm /srv/taiga/back/settings/local.py.example \
&& rm /etc/nginx/conf.d/default.conf

EXPOSE 80

WORKDIR /srv/taiga/back

COPY config.py /tmp/taiga-conf/
COPY nginx.conf /etc/nginx/conf.d/
COPY start.sh /

VOLUME [« /taiga-conf », « /taiga-media »]

CMD [« /start.sh »]

Ok cela fabrique l’image, je peux modifier le fichier docker-compose.yml et recréer l’ensemble des images manquantes et des containers associés avec le script go.sh

version: ‘3’

services:
back:
image: taiga-back-pje
container_name: taiga-back
restart: unless-stopped
depends_on:
– db
– events
networks:
– default
volumes:
– ./data/media:/taiga-media
– ./conf/back:/taiga-conf
env_file:
– variables.env

front:
image: dockertaiga/front
container_name: taiga-front
restart: unless-stopped
networks:
– default
volumes:
– ./conf/front:/taiga-conf
env_file:
– variables.env

db:
image: postgres:11-alpine
container_name: taiga-db
restart: unless-stopped
networks:
– default
env_file:
– variables.env
volumes:
– ./data/db:/var/lib/postgresql/data

rabbit:
image: dockertaiga/rabbit
container_name: taiga-rabbit
restart: unless-stopped
networks:
– default
env_file:
– variables.env

events:
image: dockertaiga/events
container_name: taiga-events
restart: unless-stopped
depends_on:
– rabbit
networks:
– default
env_file:
– variables.env

proxy:
image: taiga-proxy-pje
container_name: taiga-proxy
restart: unless-stopped
depends_on:
– back
– front
– events
networks:
– default
ports:
– 80:80
– 443:443
volumes:
#- ./cert:/taiga-cert
– ./conf/proxy:/taiga-conf
env_file:
– variables.env

networks:
default:

Sauf que après un petit tour dans le container taiga-back fabriqué à partir de mon image taiga-back-pje

docker exec -it taiga-back sh

La date est complètement fausse sur Windows

En fait, docker windows ne peut accéder (avec la version que j’avais en mars 2019) à l’horloge système.
Il n’y a pas de problème sous Linux.

Comme j’ai besoins de cette date à jour pour la suite du projet. Je dois injecter un serveur de temps openntpd et le configurer dans l’image docker-back-pje

Nouveaux modifications du fichier Dockerfile

FROM alpine:latestENV TAIGA_HOST=taiga.lan \
TAIGA_SECRET=secret \
TAIGA_SCHEME=http \
POSTGRES_HOST=db \
POSTGRES_DB=taiga \
POSTGRES_USER=postgres \
POSTGRES_PASSWORD=password \
RABBIT_HOST=rabbit \
RABBIT_PORT=5672 \
RABBIT_USER=taiga \
RABBIT_PASSWORD=password \
RABBIT_VHOST=taiga \
STARTUP_TIMEOUT=15sWORKDIR /srv/taigaRUN rm -rf /var/cache/apk/* && rm -rf /tmp/* \
&& apk –no-cache add python3 gettext postgresql-dev libxslt-dev libxml2-dev libjpeg-turbo-dev zeromq-dev libffi-dev nginx \
&& apk add –no-cache –virtual .build-dependencies musl-dev python3-dev linux-headers git zlib-dev libjpeg-turbo-dev gcc ca-certificates jq openntpd \
&& mkdir logs \
&& cp /usr/share/zoneinfo/Europe/Paris /etc/localtime && echo « Europe/Paris » > /etc/timezone && renice -n-8 $(pidof ntpd -s) \
&& git clone –depth=1 -b stable https://github.com/taigaio/taiga-back.git back && cd back \
&& sed -e ‘s/cryptography==.*/cryptography==2.3.1/’ -i requirements.txt \
&& pip3 install –upgrade pip \
&& pip3 install -r requirements.txt \
&& rm -rf /root/.cache \
&& apk del .build-dependencies tzdata \
&& rm /srv/taiga/back/settings/local.py.example \
&& rm /etc/nginx/conf.d/default.conf

EXPOSE 80

WORKDIR /srv/taiga/back

COPY ntpd.conf /etc/ntpd.conf
COPY config.py /tmp/taiga-conf/
COPY nginx.conf /etc/nginx/conf.d/
COPY start.sh /

VOLUME [« /taiga-conf », « /taiga-media »]

CMD [« /start.sh »]

On note qu’il y a une injection de la timezone dans le fichier /etc/timezone pour indiquer le fuseau horaire

Bien sur le fichier ntpd.conf sur le disque dur a ces informations

# See ntpd.conf(5) and /etc/examples/ntpd.conf
listen on *server time1.google.com
server time2.google.com
server time3.google.com
server time4.google.com

On peut indiquer d’autres serveurs de temps dans le cas d’une structure qui aurait une politique locale des serveurs de temps

Je suis toujours dessus pour améliorer le processus…

Publié dans Développement | Laisser un commentaire

Accès manager-gui via Tomcat 8.5 dans Docker

Suite à l’installation de Tomcat 8.5 dans docker, je n’ai pas trouvé simplement comment accéder à l’interface de déploiement web dans Tomcat.

Il faut donc modifier les fichiers suivants:

/usr/local/tomcat/conf/tomcat-users.xml:

<role rolename="manager-gui"/>
<role rolename="manager-script"/>
<user username="admin" password="password" roles="manager-gui,manager-script" />

Puis aller dans les réglages de l’application manager dans /usr/local/tomcat/webapps/manager/META-INF/context.xml et modifier le tag suivant :

 <Valve className="org.apache.catalina.valves.RemoteAddrValve"
allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" />

Par ceci:

 <Valve className="org.apache.catalina.valves.RemoteAddrValve"
allow="\d+\.\d+\.\d+.\d+|127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" />

Merci à cet article :

https://stackoverflow.com/questions/42692206/docker-tomcat-users-configuration-not-working

 

 

 

 

 

Publié dans Développement | Laisser un commentaire

gvim et vimrc

Habituellement je n’utilise que la ligne suivante dans mon fichier vimrc qui gère la configuration par défaut de mon gvim/vim :

colorscheme slate

Juste le changement du thème et donc des couleurs par défaut de Gvim en choisissant un thème prédéfini.

J’avais besoin de disposer d’un Gvim ouvert au centre de mon écran de taille plutôt réduite déjà en mode édition avec un fichier vide par défaut. Du coup, j’ai installé le plugin wimproved.vim. Ce plugin a installer simplement, le fichier wimproved32.dll dans le dossier principal de vim, dans le dossier autoload le fichier autoload/wimproved.vim et dans le dossier plugin le fichier plugin/wimproved.vim.

Ensuite il faut configurer le fichier vimrc :

" Simplifier l'interface de gvim en retirant le menu et les icones
autocmd GUIEnter * silent! WToggleClean
" Centrer gvim avec une taille de 30% de l'écran
autocmd GUIEnter * silent! WCenter 30
" Degré de transparence de l'interface sur 255 niveau
autocmd GUIEnter * silent! WSetAlpha 220
" Couleur du thème
colorscheme slate

" test si c'est l'édition d'un nouveau fichier ou d'un fichier existant
" ces réglages ne sont appliqués qu'au nouveau fichier pas aux fichiers en éditon 
if argc()==0

  " cache les symboles ~ qui indiquent des lignes non existente
  hi NonText guifg=bg
  " fait une insertion vide par défaut pour retirer le message d'introduction 
  normal i 
  " mode insertion au lieu d'être mode commande comme habituellement
  start
endif


 

Vi / VIM / Gvim sont des outils très pratiques car disponiblent sur toutes les plateformes et les systèmes d’exploitations. Ils gèrent un nombre important type de format et ouvrent même des fichiers de tailles énormes sans sourciller. Je sais que l’apprentissage sur cet outil est compliqué (mode commande <-> mode édition) mais les manipulations de types expressions régulières et les plugins additionnels en font un outil extraordinaire.

Efface les lignes avec le mot profile quelque part:

:g/profile/d

Efface les lignes ne contenant par le mot profile quelque part:

:g!/profile/d

 

 

Publié dans Développement | Laisser un commentaire

Tp4 IMT Mines Développement Web

 

1/ Test unitaire front-end avec Selenium

Les outils de tests dans le navigateur sont nombreux. De mémoire, le plus ancien que je connaisse est Selenium. Les alternatives aujourd’hui sont nombreuses (https://www.guru99.com/selenium-alternatives.html).

Nota: je dédie un navigateur au développement Web, pas de bookmark, pas de données stockées rien qui ne permettent de remonter des informations critiques par un développement indiscret de ces extensions. A vous de voir ce que vous voulez partager comme informations.

L’emploie de Selenium IDE se fait par l’appel de l’interface avec le bouton dédié (à droite de l’extension de React dans mon cas):

Pour créer un projet de test, nous allons appelé « Record a new test in a new project« . Pour un projet donné, nous pourrons avoir plusieurs tests.

Indiquez ensuite un nom de projet pour l’identifier des autres projets.

La fenêtre suivante demande d’indiquer l’URL de démarrage du test:

Nous allons ensuite enregistrer les opérations de tests, par exemple dans notre cas juste cliqué sur le troisième élément de la liste des Todo pour le sélectionné.

Une fois l’enregistrement de cette opération faite en utilisant votre navigateur:

Revenez dans l’interface de Selenium pour arréter l’enregistrement:

Vous avez ainsi toute les 3 commandes qui peuvent être rejoué.

Ajoutons des commandes de vérifications avec la ligne vide (4ième ligne)  comme une Command: assert avec comme Target: name=Yaourt qui permet d’identifier cet élément.

Ajoutons un test additionnel, pour tester Command: assert element present sur le tag <li> qui a comme id dans mon cas id=id_Yaourt car dans mon code Html j’ai <li id= »id=id_Yaourt » > pour identifier les <li>. Et quand on clique sur un élément la class du tag <li> change en <li class= »style_checked » /> ou <li class= »style_not_checked » />.

Testons donc ce cas en remplissant la ligne 5 et en exécutant le test avec « Run current test »:

Nous pouvons bien sur imaginer des tests beaucoup plus complexes et les executer en accélérer et les groupes dans une suite de tests automatisée.

Il est aussi possible d’externaliser ces tests en ligne de commande pour tester plusieurs navigateurs en parallèle : https://www.selenium.dev/selenium-ide/docs/en/introduction/command-line-runner

 

2/ Hibernate ORM, Object Relational Mapping

La persistance des données est habituellement gérée par une base de données relationnelles.

Le problème est que suite à l’évolution des POJO par exemple en ajoutant une date de création à notre POJO Todo, il faut souvent recoder toutes les requêtes SQL et modifier la structure des tables.

Avec les annotations Java qui permettent d’indiquer des informations additionnelles au code Java, on peut informer un framework de persistance comme Hibernate de ce qu’il doit faire de chaque méthode et propriété d’un POJO.

On a par exemple utilisé l’annoation @WebServlet({ « /Controleur » }) pour indiquer à Tomcat quel est la Servlet qui va être activée par l’URL /Controleur.

Nous avons donc une classe Todo dont nous voulons faire persister les instances avec des annotations à ajouter:

/* Import des packages générique qui sont des interfaces d'hibernate 
ou d'autres outils de persistance */

import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

// Annotation pour indiquer que l'on fait persister ce POJO
@Entity
// Nom de la table créé, indication optionnelle le nom de la table
// est habituellement le nom de la classe
@Table(name = "todo")
public class Todo {

 private Integer id;
 private String texte = "";
 private boolean actif = false;
 
  // Nom de la colonne information optionnelle habituellement
  // c'est le nom du champ qui sert de nom à la colonne
  @Column(name = "texte")
  public String getTexte() {
   return texte;
  }
 
  // Champ créé par défaut le nom de la colonne "actif"
  public boolean isActif() {
    return actif;
  }

  // Clef unique des instances pour 
  @Id
  @Column(name = "id")
  // 2 annotations pour indiquer que la génération de cette 
  // information est assurée par l'identité 
  @GeneratedValue(strategy=GenerationType.IDENTITY)
  @Basic
  public Integer getId() {
    return id;
  }
}

 

Maintenant il faut configurer la liaison entre la base de données et notre projet en ajoutant un fichier de configuration hibernate.cfg.xml dans le dossier src de notre projet.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" 
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
 
<hibernate-configuration>
 <session-factory>
 <property name="show_sql">true</property>
 <property name="format_sql">true</property>
 <property name="dialect">fr.ema.lgi2p.emacs.hibernate.SQLiteDialect</property>
 <property name="connection.driver_class">org.sqlite.JDBC</property>
 <property name="connection.url">jdbc:sqlite:c:/Developpement/todoHibernate2.sqlite</property>
 <property name="connection.username"></property>
 <property name="connection.password"></property>
 
 <property name="hibernate.hbm2ddl.auto">update</property>
 
<!-- <mapping class="fr.ema.lgi2p.emacs.metier.Todo"/> -->
 </session-factory>
</hibernate-configuration>

Ce fichier indique la nature de la base de données utilisée (sqlite) avec les nom et mot de passe utilisateur (ici aucun à la différence de MySql par exemple), le nom de du driver SQLiteDialect, le connecteur JDBC, l’url pour se connecter à la base de données. J’ai ajouté show-sql et format_sql pour afficher dans les logs les requêtes SQL.

Le réglages hibernate.hbm2ddl.auto permet ici d’indiquer que l’on souhaite créer les tables de bases de données et les modifier mais sans effacer les colonnes. Si par exemple on retire une propriété par exemple « actif » à notre POJO, la base de données n’enlèvera pas de données.

Nous devons ajouter un Dialect spécifique pour Sqlite suite à un bug sur le driver officiel.Il est téléchargeable à cette adresse : SQLiteDialect. Il faut bien sur le dézipper et le mettre dans le bon package.

Pour utiliser maintenant la couche de persistance il faut créer une classe spécialisée DaoManagerHibernate:

private DaoManagerHiberante() {
    // Ouvrir le fichier hibernate.cfg.xml pour lire la configuration
    Configuration configuration = new Configuration();
    configuration.configure();
   
    // Indique que la classe Todo.class est à analyser 
    configuration.addAnnotatedClass(Todo.class);

   // Ouvre le gestionnaire de connexion 
   serviceRegistry = new ServiceRegistryBuilder()
        .applySettings(configuration.getProperties())
        .buildServiceRegistry();
 
    // Fabrique une session de connexion, on a une seule connexion
   // mais il est possible d'avoir plusieurs connexions en même temps
    sessionFactory = configuration
        .buildSessionFactory(serviceRegistry);

    // Ouverture de la session de connexion
    session = sessionFactory.openSession();
 }

// Méthode pour sauver un Todo
public void addTodo(Todo todo){
 // Ouvre une transaction sur la base de données
 Transaction tx = session.beginTransaction();

 // Avec la session, nous sauvons le todo passé en paramètre 
 session.save( todo );

 // Validation de la sauvegarde réellement dans la base de données
 // Parfois il est utile de ne garder l'objet en mémoire et d'écrire 
 // dans la base de données plus tardivement pour optimiser le temps 
 session.flush();

 // La transaction est validé, tout est OK, le todo est sauevgardé
 tx.commit();
 }
 
 // Retourne toues les todos de la base de données 
 public List<Todo> getLestTodos(){
   @SuppressWarnings("unchecked")
   // sur la session on créer une requête HQL (H=Hibernate) 
   // Finalement assez proche du SQL, on peut rajouter des clauses
   // comme en SQL "from Todo where Todo.actif = true
   List<Todo> todos = session.createQuery("from Todo").list();
 
   return todos;
 }

 

Pour finir, il faut ajouter les packages hibernate et Sqlite avec leur logger et des classes utilitaires additionnelles (dom4j pour ouvrir les fichiers xml par exemple).

Vous pouvez les télécharger à cette adresse pour ma version de démonstration (Hibernate-jars) à dézipper et à placer dans le dossier WEB-INF/lib/ de votre projet.

 

Finalement, après configuration, on va se concentrer sur les classes annoté @Entity qui vont être sauvegarder et la classe DaoManagerHibernate qui assure la gestion de la session de connexion avec la base de données.

Hibernate est framework de persistance très performant, donc avec beaucoup d’option. Au début de son utilisation on se retrouve avec beaucoup de réglages mais ensuite en fonctionnement normal, on n’intervient que sur très peu de réglages et récupère enfin les avantages de l’utilisation d’un tel framework complexe.

Publié dans IMT Mines Alès | Commentaires fermés sur Tp4 IMT Mines Développement Web

Résultat du sondage de Stackoverflow 2017 et Infographie de Chooseyourboss 2018

Le sondage 2017 du site web de support informatique stackoverflow vient de sortir. Le sondage est très/trop complet notamment sur des questions hors du domaine du développement (le développeur a t’il des enfants par exemple). Vous pouvez le trouver à cette URL.

Je sors quelques points que je trouve intéressant et donc ce n’est que mon regard personnel sur ce sondage, chacun est libre d’en sortir ses propres impressions.

Et blog de Choose Your Boss a ajouté une infographie pour 2018

 

 

Comment se définit le développeur:

Finalement on peut dire que les sondés sont globalement des développeurs qui font un peu de tout en Front/Back/Full, finalement c’est le « Desktop or entreprise applications » qui montre bien que ce type de développement est assez faible sur ce site. Peut être que les développeurs de ce genre d’applications sont expérimentés et n’ont plus besoin de poser des questions.

 

La bataille des IDEs:

Le Visual Studio payant et gratuit semble enfoncé les autres, le trio des éditeurs Sublime Text/Vim/Notepad++ semble être très utilisé au final, le reste est très classique au final.

Les langages des développeurs:

Beaucoup de développement web en Front, donc JS+HTML+CSS sontles premier. On trouve les inaltérables SQL/Shell en plus. La tendance reste Java/Python/C#/PHP/C++/C.  J’ai indiqué les langages ayant plus de 10%, vous trouverez surement votre langage dans le sondage.

 

Les Framework des développeurs:

Node.js / Angular /react indique bien que le développement des solutions javascript a le vent en poupe. Ce qui est surprenant encore c’est le .Net Core qui est très important, une information que je n’avais pas personnellement.

Base de données utilisées

 

La seconde place de SQL Server est pour moi une surprise, le reste me parait assez classique comme représentation.

Les plateformes cible des développeurs:

Attention, ce n’est pas avec quel OS ils développent, il y a une réponse spécifique sur ce point. On voit bien que le classique c’est Linux/Windows, un peu d’android, de cluster AWS, Mac OS. Rasberry Pi et WordPress sont présentés comme des cibles cela indique bien la force de leur spécificité.

 

Les regroupement  des technologies pour les développeurs:

Très utile cela indique bien les liaisons outils/technologies/plateformes pour comprendre qu’elles sont les compétences liées.

 

 

Publié dans Développement | Laisser un commentaire

Arduino M0 pro et UART additionnel

Dans le cadre d’un développement sur un Arduino M0 Pro, je me retrouve a devoir brancher en protocole UART un module bluetooth et un lecteur RFID tout les deux en UART.

Comme je débute en Arduino, je branche le module bluetooth sur RT( broche 0) /TX (broche 1) de la carte :

 

Donc se pose la question d’avoir une entrée UART sur d’autres broches. J’avoue que je traine sur google et que je trouve enfin la bonne explication pour transformer les broches  10 en TX et 11 en RX.

Vous trouverez sur ce lien toutes les explications chez Adafruit mais pour ceux qui cherchent comme moi, voici le résumé avec le code:

#include "wiring_private.h"

Uart Serial2(&sercom1, 11, 10, SERCOM_RX_PAD_0, UART_TX_PAD_2);

void SERCOM1_Handler()
{
 Serial2.IrqHandler();
}

void setup()
{
  Serial2.begin(9600);
  pinPeripheral(10, PIO_SERCOM);
  pinPeripheral(11, PIO_SERCOM);
}


void loop()
{
 if (Serial2.available()){
   byte byteRead = Serial2.read();
   Serial2.write(byteRead);
   Serial.write( byteRead ); 
 }
}

Et voila, j’avoue que cela m’a permis d’entrer dans des détails du « M0 pro » et de son contrôleur ATSAMD21  mais enfin j’ai compris comment on peut refaire un UART de plus en cas de besoin.

Voila le montage final avec UART sur PIN 0 et 1, SDA & SCL branché et enfin le nouveau UART PIN 10 et PIN 11

Publié dans Développement | Laisser un commentaire