<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-1566084130752530982</id><updated>2024-11-08T16:37:46.141+01:00</updated><category term="Eclipse"/><category term="Java"/><category term="arduino"/><category term="cumulocity"/><category term="plugin"/><category term="PDE"/><category term="scala"/><category term="api"/><category term="iiot"/><category term="iot"/><category term="camel"/><category term="ide"/><category term="tycho"/><category term="xml"/><category term="Flex"/><category term="Google App Engine"/><category term="junit"/><category term="swing"/><category term="GeoTools"/><category term="Red 5"/><category term="android"/><category term="edge computing"/><category term="jenkins"/><category term="kepware"/><category term="maven"/><category term="performance"/><category term="plc"/><category term="programmation fonctionelle"/><category term="siemens"/><category term="xslt"/><category term="FLV"/><category term="JTable"/><category term="NetConnection"/><category term="SWT"/><category term="apache"/><category term="atmel"/><category term="avr"/><category term="business intelligence"/><category term="client"/><category term="coap"/><category term="communauté"/><category term="design pattern"/><category term="editor"/><category term="emf"/><category term="graphique"/><category term="icones"/><category term="intégration continue"/><category term="nosql"/><category term="nuxeo"/><category term="opcua"/><category term="paradigmes"/><category term="planet"/><category term="recommender"/><category term="xbee"/><category term="AVI"/><category term="Converter"/><category term="ENC28J60"/><category term="EventDispatcher"/><category term="Excel"/><category term="ExecutorService"/><category term="FFMpeg"/><category term="FLVMDI"/><category term="IWorkbenchActivitySupport"/><category term="NetStream"/><category term="Newman"/><category term="Pazera"/><category term="Postgis"/><category term="Postman"/><category term="RCP"/><category term="REST"/><category term="RTMP"/><category term="Swagger"/><category term="TDD"/><category term="Table"/><category term="TableViewer"/><category term="actinium"/><category term="actionscript 2"/><category term="activites"/><category term="activities"/><category term="adapter"/><category term="adc"/><category term="aframe"/><category term="altova"/><category term="annotations"/><category term="ant"/><category term="ar"/><category term="arjs"/><category term="arm"/><category term="artisan"/><category term="assembly"/><category term="assistant"/><category term="audio"/><category term="automation"/><category term="bridge"/><category term="builder"/><category term="c++"/><category term="calc"/><category term="californium"/><category term="callable"/><category term="cell"/><category term="cellule"/><category term="chatbot"/><category term="chronon"/><category term="classification"/><category term="coin"/><category term="composants"/><category term="console"/><category term="couchdb"/><category term="cours"/><category term="css"/><category term="customization"/><category term="deadlock"/><category term="debug"/><category term="demo camp"/><category term="devee"/><category term="devops"/><category term="dispatchEvent"/><category term="document"/><category term="download"/><category term="dwr"/><category term="dynamictext"/><category term="dépendances"/><category term="e4"/><category term="ecologie"/><category term="ektorp"/><category term="extending"/><category term="facade"/><category term="file associations"/><category term="flash player 8"/><category term="force"/><category term="francaise"/><category term="future"/><category term="gain"/><category term="generation"/><category term="generics"/><category term="git"/><category term="google"/><category term="gravité"/><category term="greenit"/><category term="groovy"/><category term="gui"/><category term="headless build"/><category term="hibernate"/><category term="hook"/><category term="html"/><category term="ia"/><category term="iadptable"/><category term="ihm"/><category term="industry"/><category term="industry 4.0"/><category term="infrarouge"/><category term="integration patterns"/><category term="internationalisation"/><category term="introspection"/><category term="invalid thread access"/><category term="ireport"/><category term="jasper"/><category term="jcombobox"/><category term="jelastic"/><category term="jelly"/><category term="jet"/><category term="jet2"/><category term="jmx"/><category term="jsch"/><category term="jsf"/><category term="jtree"/><category term="jvm"/><category term="langages"/><category term="lastfm"/><category term="ligne commande"/><category term="listener"/><category term="localization"/><category term="log4j"/><category term="logstash"/><category term="lora"/><category term="magazine"/><category term="maintenance conditionnelle"/><category term="mantis"/><category term="meta data"/><category term="metadonnees"/><category term="micropython"/><category term="miglayout"/><category term="mobile"/><category term="mongodb"/><category term="moteur"/><category term="musicbrainz"/><category term="musique"/><category term="mylyn"/><category term="netbeans"/><category term="nio"/><category term="node.js"/><category term="ntp"/><category term="observer"/><category term="office"/><category term="openoffice"/><category term="orion"/><category term="paas"/><category term="papervision3D"/><category term="pattern matching"/><category term="pdf2swf"/><category term="physics"/><category term="pizza"/><category term="poi"/><category term="polymorphisme parametrique"/><category term="ponte"/><category term="pool"/><category term="pragmatisme"/><category term="programmation"/><category term="projet"/><category term="proxy"/><category term="pycom"/><category term="pygate"/><category term="python"/><category term="quartz"/><category term="recast"/><category term="recompiler"/><category term="record"/><category term="reflexion"/><category term="refresh"/><category term="registry"/><category term="renderer"/><category term="rtc"/><category term="scalableexplorer"/><category term="schema"/><category term="scp"/><category term="serveur"/><category term="shapefile"/><category term="shoaken"/><category term="sigfox"/><category term="singleton"/><category term="sourceforge"/><category term="spring"/><category term="sqlserver"/><category term="ssh"/><category term="streaming"/><category term="studio"/><category term="swftools"/><category term="swtbot"/><category term="swtexception"/><category term="sélection"/><category term="templates"/><category term="textarea"/><category term="texteditor"/><category term="the things network"/><category term="thread"/><category term="traduction"/><category term="tree"/><category term="types parametres"/><category term="uithread"/><category term="usine du futur"/><category term="valtech"/><category term="velleman"/><category term="visualvm"/><category term="webcam"/><category term="webservice"/><category term="websocket"/><category term="wildcards"/><category term="windowbuilder"/><category term="wow engine"/><category term="xsd"/><category term="xtext"/><category term="yahoo"/><title type='text'>Developpef</title><subtitle type='html'>From technology to value...</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://developpef.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default'/><link rel='alternate' type='text/html' href='http://developpef.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default?start-index=26&amp;max-results=25'/><author><name>Paul-Emmanuel Faidherbe</name><uri>http://www.blogger.com/profile/14333816988154371906</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJF9OHIybxl9BZ8qHqpkX3CzEcAtPsFesbRt6NQNIAy_LD1arQRfxFXPo0Ur442M6LqY4ZNZk9gwTy474Fa_gayo5ukXRMAxwkMBRTFQqVkD2y1kMHdxc_W0lox-j_E8A6rlntimZ50JZwxmK-mM5egC_mdthRx5lUFhpt_H7obAZ-7w/s220/identite.png'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>150</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1566084130752530982.post-8603252352921134302</id><published>2020-11-27T15:27:00.000+01:00</published><updated>2020-11-27T15:27:09.427+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="cumulocity"/><category scheme="http://www.blogger.com/atom/ns#" term="iiot"/><category scheme="http://www.blogger.com/atom/ns#" term="industry 4.0"/><category scheme="http://www.blogger.com/atom/ns#" term="kepware"/><category scheme="http://www.blogger.com/atom/ns#" term="plc"/><category scheme="http://www.blogger.com/atom/ns#" term="usine du futur"/><title type='text'>Connectivité des moyens industriels : la démo!</title><content type='html'>&lt;p&gt;
  Un article rapide pour présenter une vidéo qui donne vie aux différents sujets que j&#39;ai pu aborder dans mes précédents articles. Enjoy!
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;iframe allowfullscreen=&#39;allowfullscreen&#39; webkitallowfullscreen=&#39;webkitallowfullscreen&#39; mozallowfullscreen=&#39;mozallowfullscreen&#39; width=&#39;600&#39; height=&#39;498&#39; src=&#39;https://www.blogger.com/video.g?token=AD6v5dygSQlf6iCd5sLDmFUWvmyIKr3RFHORIvBaUq8YoJ1QkoA9djHlROaqO7vnV06HPEto0al1EPKp7mONFSzYXA&#39; class=&#39;b-hbp-video b-uploaded&#39; frameborder=&#39;0&#39;&gt;&lt;/iframe&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://developpef.blogspot.com/feeds/8603252352921134302/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1566084130752530982/8603252352921134302?isPopup=true' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/8603252352921134302'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/8603252352921134302'/><link rel='alternate' type='text/html' href='http://developpef.blogspot.com/2020/11/connectivite-des-moyens-industriels-la.html' title='Connectivité des moyens industriels : la démo!'/><author><name>Paul-Emmanuel Faidherbe</name><uri>http://www.blogger.com/profile/14333816988154371906</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJF9OHIybxl9BZ8qHqpkX3CzEcAtPsFesbRt6NQNIAy_LD1arQRfxFXPo0Ur442M6LqY4ZNZk9gwTy474Fa_gayo5ukXRMAxwkMBRTFQqVkD2y1kMHdxc_W0lox-j_E8A6rlntimZ50JZwxmK-mM5egC_mdthRx5lUFhpt_H7obAZ-7w/s220/identite.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1566084130752530982.post-8603212562234857103</id><published>2020-11-16T10:11:00.000+01:00</published><updated>2020-11-16T10:11:42.654+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="iiot"/><category scheme="http://www.blogger.com/atom/ns#" term="kepware"/><category scheme="http://www.blogger.com/atom/ns#" term="opcua"/><category scheme="http://www.blogger.com/atom/ns#" term="plc"/><category scheme="http://www.blogger.com/atom/ns#" term="siemens"/><title type='text'>Connecter un automate à un serveur OPC/UA sous Linux</title><content type='html'>&lt;p&gt;
  J&#39;ai déjà présenté dans de précédents articles le couteau suisse de la connectivité OT/IT : KEPServerEX. Indispensable pour exposer les données d&#39;une grande variété de machines via un serveur OPC/UA. Il est prévu pour fonctionner sous un environnement Windows.
&lt;/p&gt;
&lt;p&gt;
  Nous allons voir ici comment utiliser son pendant pour serveurs Linux : &lt;a href=&quot;https://www.kepware.com/en-us/products/thingworx-kepware-edge/&quot; target=&quot;_blank&quot;&gt;ThingWorx Kepware Edge&lt;/a&gt;.
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;a href=&quot;https://www.kepware.com/getattachment/products/Thingworx-Kepware-Edge/ThingWorx_Kepware_Edge-%282%29.png?lang=en-US&amp;amp;width=700&amp;amp;height=725&quot; style=&quot;display: block; padding: 1em 0; text-align: center; &quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; data-original-height=&quot;725&quot; data-original-width=&quot;700&quot; src=&quot;https://www.kepware.com/getattachment/products/Thingworx-Kepware-Edge/ThingWorx_Kepware_Edge-%282%29.png?lang=en-US&amp;amp;width=700&amp;amp;height=725&quot;/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;
  Pour les besoins de cet article, nous utiliserons de nouveau notre PLC Siemens Logo! 8.
&lt;/p&gt;
&lt;p&gt;
  Contrairement à la version pour Windows, celle-ci ne dispose pas d&#39;interface graphique. En revanche, elle expose une interface REST très complète et très bien documentée dans le ThingWorx Kepware Edge User Manual disponible en téléchargement. Elle est même autodocumentée, via des APIs spécifiques. Par exemple :
&lt;/p&gt;
&lt;h4&gt;Définition des drivers/channels spécifiques&lt;/h4&gt;
&lt;p&gt;
  La requête suivante renvoie les éléments nécessaires à la création de channels dédiés au type de machine/équipement à connecter :
&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;GET https://localhost:57513/config/v1/doc/drivers/Siemens%20TCP%2FIP%20Ethernet/channels
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;i&gt;Réponse :&lt;/i&gt;&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;{
    &quot;type_definition&quot;: {
        &quot;name&quot;: &quot;Channel&quot;,
        &quot;collection&quot;: &quot;channels&quot;,
        &quot;namespace&quot;: &quot;servermain&quot;,
        &quot;can_create&quot;: true,
        &quot;can_delete&quot;: true,
        &quot;can_modify&quot;: true,
        &quot;auto_generated&quot;: false,
        &quot;requires_driver&quot;: true,
        &quot;access_controlled&quot;: true,
        &quot;child_collections&quot;: [
            &quot;devices&quot;,
            &quot;phonebooks&quot;
        ]
    },
    &quot;property_definitions&quot;: [
        {
            &quot;symbolic_name&quot;: &quot;common.ALLTYPES_NAME&quot;,
            &quot;display_name&quot;: &quot;Name&quot;,
            &quot;display_description&quot;: &quot;Specify the identity of this object.&quot;,
            &quot;read_only&quot;: false,
            &quot;type&quot;: &quot;String&quot;,
            &quot;default_value&quot;: null,
            &quot;minimum_length&quot;: 1,
            &quot;maximum_length&quot;: 256
        },
        {
            &quot;symbolic_name&quot;: &quot;common.ALLTYPES_DESCRIPTION&quot;,
            &quot;display_name&quot;: &quot;Description&quot;,
            &quot;display_description&quot;: &quot;Provide a brief summary of this object or its use.&quot;,
            &quot;read_only&quot;: false,
            &quot;type&quot;: &quot;String&quot;,
            &quot;default_value&quot;: null,
            &quot;minimum_length&quot;: 0,
            &quot;maximum_length&quot;: 255
        },
        {
            &quot;symbolic_name&quot;: &quot;servermain.MULTIPLE_TYPES_DEVICE_DRIVER&quot;,
            &quot;display_name&quot;: &quot;Driver&quot;,
            &quot;display_description&quot;: &quot;&quot;,
            &quot;read_only&quot;: true,
            &quot;type&quot;: &quot;String&quot;,
            &quot;default_value&quot;: &quot;Siemens TCP/IP Ethernet&quot;,
            &quot;minimum_length&quot;: 0,
            &quot;maximum_length&quot;: -1
        },
        {
            &quot;symbolic_name&quot;: &quot;servermain.CHANNEL_DIAGNOSTICS_CAPTURE&quot;,
            &quot;display_name&quot;: &quot;Diagnostics Capture&quot;,
            &quot;display_description&quot;: &quot;Select whether or not to make the channel&#39;s diagnostic information available to an OPC application.&quot;,
            &quot;read_only&quot;: false,
            &quot;type&quot;: &quot;EnableDisable&quot;,
            &quot;default_value&quot;: false
        },
        {
            &quot;symbolic_name&quot;: &quot;servermain.CHANNEL_UNIQUE_ID&quot;,
            &quot;display_name&quot;: &quot;Unique Id&quot;,
            &quot;display_description&quot;: &quot;Unique identifier associated with this object.&quot;,
            &quot;read_only&quot;: false,
            &quot;type&quot;: &quot;Integer&quot;,
            &quot;default_value&quot;: 422613010,
            &quot;minimum_value&quot;: null,
            &quot;maximum_value&quot;: null
        },
        {
            &quot;symbolic_name&quot;: &quot;servermain.CHANNEL_ETHERNET_COMMUNICATIONS_NETWORK_ADAPTER_STRING&quot;,
            &quot;display_name&quot;: &quot;Network Adapter&quot;,
            &quot;display_description&quot;: &quot;Specify the name of a network adapter to bind or allow the OS to select the default.&quot;,
            &quot;read_only&quot;: false,
            &quot;type&quot;: &quot;StringWithBrowser&quot;,
            &quot;default_value&quot;: null,
            &quot;minimum_length&quot;: 0,
            &quot;maximum_length&quot;: -1,
            &quot;hints&quot;: [
                &quot;&quot;,
                &quot;wlp3s0&quot;,
                &quot;eno1&quot;
            ]
        },
        ...
    ]
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;
&lt;h4&gt;Définition des devices&lt;/h4&gt;
&lt;p&gt;
  La requête suivante renvoie les éléments nécessaires à la création de devices dédiés au type de machine/équipement à connecter :
&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;GET https://localhost:57513/config/v1/doc/drivers/Siemens%20TCP%2FIP%20Ethernet/devices&lt;/code&gt;&lt;/pre&gt;
    &lt;p&gt;&lt;i&gt;Réponse :&lt;/i&gt;&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;{
    &quot;type_definition&quot;: {
        &quot;name&quot;: &quot;Device&quot;,
        &quot;collection&quot;: &quot;devices&quot;,
        &quot;namespace&quot;: &quot;servermain&quot;,
        &quot;can_create&quot;: true,
        &quot;can_delete&quot;: true,
        &quot;can_modify&quot;: true,
        &quot;auto_generated&quot;: false,
        &quot;requires_driver&quot;: true,
        &quot;access_controlled&quot;: true,
        &quot;child_collections&quot;: [
            &quot;services&quot;,
            &quot;tag_groups&quot;,
            &quot;tags&quot;
        ]
    },
    &quot;property_definitions&quot;: [
        {
            &quot;symbolic_name&quot;: &quot;common.ALLTYPES_NAME&quot;,
            &quot;display_name&quot;: &quot;Name&quot;,
            &quot;display_description&quot;: &quot;Specify the identity of this object.&quot;,
            &quot;read_only&quot;: false,
            &quot;type&quot;: &quot;String&quot;,
            &quot;default_value&quot;: null,
            &quot;minimum_length&quot;: 1,
            &quot;maximum_length&quot;: 256
        },
        {
            &quot;symbolic_name&quot;: &quot;common.ALLTYPES_DESCRIPTION&quot;,
            &quot;display_name&quot;: &quot;Description&quot;,
            &quot;display_description&quot;: &quot;Provide a brief summary of this object or its use.&quot;,
            &quot;read_only&quot;: false,
            &quot;type&quot;: &quot;String&quot;,
            &quot;default_value&quot;: null,
            &quot;minimum_length&quot;: 0,
            &quot;maximum_length&quot;: 255
        },
        {
            &quot;symbolic_name&quot;: &quot;servermain.MULTIPLE_TYPES_DEVICE_DRIVER&quot;,
            &quot;display_name&quot;: &quot;Driver&quot;,
            &quot;display_description&quot;: &quot;&quot;,
            &quot;read_only&quot;: true,
            &quot;type&quot;: &quot;String&quot;,
            &quot;default_value&quot;: &quot;Siemens TCP/IP Ethernet&quot;,
            &quot;minimum_length&quot;: 0,
            &quot;maximum_length&quot;: -1
        },
        {
            &quot;symbolic_name&quot;: &quot;servermain.DEVICE_MODEL&quot;,
            &quot;display_name&quot;: &quot;Model&quot;,
            &quot;display_description&quot;: &quot;Select the specific type of device associated with this ID. Options depend on the type of communications in use.&quot;,
            &quot;read_only&quot;: false,
            &quot;type&quot;: &quot;Enumeration&quot;,
            &quot;default_value&quot;: null,
            &quot;enumeration&quot;: {
                &quot;S7-200&quot;: 0,
                &quot;S7-300&quot;: 1,
                &quot;S7-400&quot;: 2,
                &quot;S7-1200&quot;: 3,
                &quot;S7-1500&quot;: 4,
                &quot;NetLink: S7-300&quot;: 5,
                &quot;NetLink: S7-400&quot;: 6
            }
        },
        {
            &quot;symbolic_name&quot;: &quot;servermain.DEVICE_UNIQUE_ID&quot;,
            &quot;display_name&quot;: &quot;Unique Id&quot;,
            &quot;display_description&quot;: &quot;Unique identifier associated with this object.&quot;,
            &quot;read_only&quot;: false,
            &quot;type&quot;: &quot;Integer&quot;,
            &quot;default_value&quot;: 4145021575,
            &quot;minimum_value&quot;: null,
            &quot;maximum_value&quot;: null
        },
        {
            &quot;symbolic_name&quot;: &quot;servermain.DEVICE_ID_FORMAT&quot;,
            &quot;display_name&quot;: &quot;ID Format&quot;,
            &quot;display_description&quot;: &quot;Indicate the format of the device ID (set by the driver by default).&quot;,
            &quot;read_only&quot;: false,
            &quot;type&quot;: &quot;Enumeration&quot;,
            &quot;default_value&quot;: 0,
            &quot;enumeration&quot;: {
                &quot;Octal&quot;: 0,
                &quot;Decimal&quot;: 1,
                &quot;Hex&quot;: 2
            }
        },
        ...
    ]
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Munissez-vous donc d&#39;un client d&#39;API comme Postman, d&#39;un client OPC/UA comme UAExpert, et c&#39;est parti!&lt;/p&gt;
&lt;h3&gt;Les endpoints&lt;/h3&gt;
&lt;p&gt;
  La documentation ThingWorx Kepware Edge Quick Start décrit les étapes nécessaires pour connecter un premier client UAExpert au serveur OPC/UA, via le endpoint créé par défaut par l&#39;installation standard. Ce dernier est sécurisé et requiert une validation manuelle pour accepter la connexion du client au serveur.
&lt;/p&gt;
&lt;p&gt;
  Mais il est fréquent que le client qui sera utilisé dans une application (que vous découvrirez dans un prochain article ;) ne supporte pas ce mécanisme d&#39;authentification. Il devient donc nécessaire de créer en premier lieu un nouveau endpoint &quot;non sécurisé&quot;. 
&lt;/p&gt;
&lt;p&gt;
  Ceci peut donc être fait via l&#39;API REST de Kepware Edge :
&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;POST https://localhost:57513/config/v1/admin/ua_endpoints&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;i&gt;Body :&lt;/i&gt;&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;{
    &quot;common.ALLTYPES_NAME&quot;: &quot;UnsecureEndpoint&quot;,
    &quot;common.ALLTYPES_DESCRIPTION&quot;: &quot;Available adapters: Default; wlp3s0:192.168.1.94; vboxnet0:192.168.56.1; eno1:&lt;disconnected&gt;; localhost&quot;,
    &quot;libadminsettings.UACONFIGMANAGER_ENDPOINT_ENABLE&quot;: true,
    &quot;libadminsettings.UACONFIGMANAGER_ENDPOINT_ADAPTER&quot;: &quot;Default&quot;,
    &quot;libadminsettings.UACONFIGMANAGER_ENDPOINT_PORT&quot;: 49331,
    &quot;libadminsettings.UACONFIGMANAGER_ENDPOINT_URL&quot;: &quot;opc.tcp://localhost:49331&quot;,
    &quot;libadminsettings.UACONFIGMANAGER_ENDPOINT_SECURITY_NONE&quot;: true,
    &quot;libadminsettings.UACONFIGMANAGER_ENDPOINT_SECURITY_BASIC128_RSA15&quot;: 0,
    &quot;libadminsettings.UACONFIGMANAGER_ENDPOINT_SECURITY_BASIC256&quot;: 0,
    &quot;libadminsettings.UACONFIGMANAGER_ENDPOINT_SECURITY_BASIC256_SHA256&quot;: 0
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
Il sera nécessaire de redémarrer le serveur pour prendre en compte cette modification. Ce nouveau endpoint apparaitra donc dans le client OPC/UA :
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6TIcFeSPovpHgUYrjy_FdPIoxiE61eFBkATrp_9BJz02AMjXcjHMr3lqU7CboYx76jB0gm2dOYaz7sFPvthn9ZK8gz0MaXZoUayYU4JnKG8HNLhyphenhyphenqaGR0hn_rjsKg7bh_jpHdXhIjmCo/s1440/Capture+du+2020-11-14+20-56-02.png&quot; style=&quot;display: block; padding: 1em 0; text-align: center; &quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;400&quot; data-original-height=&quot;900&quot; data-original-width=&quot;1440&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6TIcFeSPovpHgUYrjy_FdPIoxiE61eFBkATrp_9BJz02AMjXcjHMr3lqU7CboYx76jB0gm2dOYaz7sFPvthn9ZK8gz0MaXZoUayYU4JnKG8HNLhyphenhyphenqaGR0hn_rjsKg7bh_jpHdXhIjmCo/s400/Capture+du+2020-11-14+20-56-02.png&quot;/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h3&gt;Le Channel&lt;/h3&gt;
&lt;p&gt;
  En s&#39;appuyant sur la documentation récupérée plus haut, nous pouvons créer le channel spécifique à notre PLC Siemens :
&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;POST https://localhost:57513/config/v1/project/channels&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;i&gt;Body :&lt;/i&gt;&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;{
    &quot;common.ALLTYPES_NAME&quot;: &quot;SiemensChannel&quot;,
    &quot;servermain.MULTIPLE_TYPES_DEVICE_DRIVER&quot;: &quot;Siemens TCP/IP Ethernet&quot;,
    &quot;servermain.CHANNEL_DIAGNOSTICS_CAPTURE&quot;: false,
    &quot;servermain.CHANNEL_WRITE_OPTIMIZATIONS_METHOD&quot;: 2,
    &quot;servermain.CHANNEL_WRITE_OPTIMIZATIONS_DUTY_CYCLE&quot;: 10,
    &quot;servermain.CHANNEL_NON_NORMALIZED_FLOATING_POINT_HANDLING&quot;: 0,
    &quot;servermain.CHANNEL_ETHERNET_COMMUNICATIONS_NETWORK_ADAPTER_STRING&quot;:&quot;wlp3s0&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Le Device&lt;/h3&gt;
&lt;p&gt;
  Nous pouvons maintenant associer à notre Channel un Device représentant notre Logo! 8 :
&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;POST https://localhost:57513/config/v1/project/channels/SiemensChannel/devices&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;i&gt;Body :&lt;/i&gt;&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;{
    &quot;common.ALLTYPES_NAME&quot;: &quot;Logo8&quot;,
    &quot;servermain.DEVICE_ID_STRING&quot;: &quot;192.168.1.13&quot;,
    &quot;servermain.MULTIPLE_TYPES_DEVICE_DRIVER&quot;: &quot;Siemens TCP/IP Ethernet&quot;,
    &quot;servermain.DEVICE_MODEL&quot;: 0,
    &quot;servermain.DEVICE_ID_FORMAT&quot;: 0,
    &quot;servermain.DEVICE_ID_HEXADECIMAL&quot;: 0,
    &quot;servermain.DEVICE_ID_DECIMAL&quot;: 0,
    &quot;servermain.DEVICE_ID_OCTAL&quot;: 0,
    &quot;servermain.DEVICE_DATA_COLLECTION&quot;: true,
    &quot;servermain.DEVICE_SIMULATED&quot;: false,
    &quot;servermain.DEVICE_SCAN_MODE&quot;: 0,
    &quot;servermain.DEVICE_SCAN_MODE_RATE_MS&quot;: 1000,
    &quot;servermain.DEVICE_SCAN_MODE_PROVIDE_INITIAL_UPDATES_FROM_CACHE&quot;: false,
    &quot;servermain.DEVICE_CONNECTION_TIMEOUT_SECONDS&quot;: 3,
    &quot;servermain.DEVICE_REQUEST_TIMEOUT_MILLISECONDS&quot;: 2000,
    &quot;servermain.DEVICE_RETRY_ATTEMPTS&quot;: 2,
    &quot;servermain.DEVICE_INTER_REQUEST_DELAY_MILLISECONDS&quot;: 0,
    &quot;servermain.DEVICE_AUTO_DEMOTION_ENABLE_ON_COMMUNICATIONS_FAILURES&quot;: false,
    &quot;servermain.DEVICE_AUTO_DEMOTION_DEMOTE_AFTER_SUCCESSIVE_TIMEOUTS&quot;: 3,
    &quot;servermain.DEVICE_AUTO_DEMOTION_PERIOD_MS&quot;: 10000,
    &quot;servermain.DEVICE_AUTO_DEMOTION_DISCARD_WRITES&quot;: false,
    &quot;servermain.DEVICE_TAG_GENERATION_ON_STARTUP&quot;: 1,
    &quot;servermain.DEVICE_TAG_GENERATION_DUPLICATE_HANDLING&quot;: 0,
    &quot;servermain.DEVICE_TAG_GENERATION_GROUP&quot;: &quot;&quot;,
    &quot;servermain.DEVICE_TAG_GENERATION_ALLOW_SUB_GROUPS&quot;: true,
    &quot;siemens_tcpip_ethernet.DEVICE_COMMUNICATIONS_PORT_NUMBER&quot;: 102,
    &quot;siemens_tcpip_ethernet.DEVICE_COMMUNICATIONS_MPI_ID&quot;: 0,
    &quot;siemens_tcpip_ethernet.DEVICE_S7_COMMUNICATIONS_MAX_PDU&quot;: 960,
    &quot;siemens_tcpip_ethernet.DEVICE_S7_COMMUNICATIONS_200_LOCAL_TSAP&quot;: 200,
    &quot;siemens_tcpip_ethernet.DEVICE_S7_COMMUNICATIONS_200_REMOTE_TSAP&quot;: 200,
    &quot;siemens_tcpip_ethernet.DEVICE_S7_COMMUNICATIONS_300_400_1200_1500_LINK_TYPE&quot;: 3,
    &quot;siemens_tcpip_ethernet.DEVICE_S7_COMMUNICATIONS_CPU_RACK&quot;: 0,
    &quot;siemens_tcpip_ethernet.DEVICE_S7_COMMUNICATIONS_CPU_SLOT&quot;: 2,
    &quot;siemens_tcpip_ethernet.DEVICE_ADDRESSING_BYTE_ORDER&quot;: 0,
    &quot;siemens_tcpip_ethernet.DEVICE_TAG_IMPORT_TYPE&quot;: 0,
    &quot;siemens_tcpip_ethernet.DEVICE_TAG_IMPORT_CODE_PAGE&quot;: 4294967295,
    &quot;siemens_tcpip_ethernet.DEVICE_TAG_IMPORT_STEP_7_PROJECT_FILE&quot;: &quot;&quot;,
    &quot;siemens_tcpip_ethernet.DEVICE_TAG_IMPORT_PROGRAM_PATH&quot;: &quot;&quot;,
    &quot;siemens_tcpip_ethernet.DEVICE_TAG_IMPORT_TIA_EXPORT_FILE&quot;: &quot;&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
Toutes ces informations correspondent à ce qui est demandé par l&#39;assistant de configuration dans la version Windows.
&lt;/p&gt;
&lt;h3&gt;Les Tags&lt;/h3&gt;
&lt;p&gt;
  Terminons par le plus important, exposer les informations de l&#39;automate via les tags OPC/UA :
&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;POST https://localhost:57513/config/v1/project/channels/SiemensChannel/devices/Logo8/tags&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;i&gt;Body :&lt;/i&gt;&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;[
    {
        &quot;common.ALLTYPES_NAME&quot;: &quot;Entree1&quot;,
        &quot;servermain.TAG_ADDRESS&quot;: &quot;I0.0&quot;,
        &quot;servermain.TAG_DATA_TYPE&quot;: 1,
        &quot;servermain.TAG_READ_WRITE_ACCESS&quot;: 1,
        &quot;servermain.TAG_SCAN_RATE_MILLISECONDS&quot;: 100,
        &quot;servermain.TAG_SCALING_TYPE&quot;: 0
    },
    {
        &quot;common.ALLTYPES_NAME&quot;: &quot;EntreeReseau1&quot;,
        &quot;servermain.TAG_ADDRESS&quot;: &quot;V0.0&quot;,
        &quot;servermain.TAG_DATA_TYPE&quot;: 1,
        &quot;servermain.TAG_READ_WRITE_ACCESS&quot;: 1,
        &quot;servermain.TAG_SCAN_RATE_MILLISECONDS&quot;: 100,
        &quot;servermain.TAG_SCALING_TYPE&quot;: 0
    },
    {
        &quot;common.ALLTYPES_NAME&quot;: &quot;Output1&quot;,
        &quot;servermain.TAG_ADDRESS&quot;: &quot;Q0.0&quot;,
        &quot;servermain.TAG_DATA_TYPE&quot;: 1,
        &quot;servermain.TAG_READ_WRITE_ACCESS&quot;: 1,
        &quot;servermain.TAG_SCAN_RATE_MILLISECONDS&quot;: 100,
        &quot;servermain.TAG_SCALING_TYPE&quot;: 0
    }
]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Et voilà! Notre serveur est prêt à être utilisé :&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4G5wxeSx3KRo5XYJoDV4CZTO4VSFODNIUVzxeHdaFxcJwEc3J-s7Coisd697Q61ro8tmhOuOv-xXIZIlIR2vYbVObOCa4IpufoAAWaSYbNlBYrjW-dUiCxZO44xLN-5iNR-2YpWvTWrU/s1440/Capture+du+2020-11-14+20-58-20.png&quot; style=&quot;display: block; padding: 1em 0; text-align: center; &quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;600&quot; data-original-height=&quot;900&quot; data-original-width=&quot;1440&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4G5wxeSx3KRo5XYJoDV4CZTO4VSFODNIUVzxeHdaFxcJwEc3J-s7Coisd697Q61ro8tmhOuOv-xXIZIlIR2vYbVObOCa4IpufoAAWaSYbNlBYrjW-dUiCxZO44xLN-5iNR-2YpWvTWrU/s600/Capture+du+2020-11-14+20-58-20.png&quot;/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h3&gt;Pour aller plus loin&lt;/h3&gt;
&lt;p&gt;
Si vous avez besoin de configuration spécifique, avec des attributs particuliers, pour ne pas avoir à fouiller dans toute la documentation, il est possible d&#39;exporter un projet déjà existant sous Kepware version Windows au format JSON : vous retrouverez ainsi tout le contenu nécessaire pour appeler les APIs REST!
&lt;/p&gt;
&lt;h3&gt;Récupération des logs&lt;/h3&gt;
&lt;p&gt;
  Les logs du serveur, habituellement visibles sous Windows dans la console, peuvent être récupérés via cette interface :
&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;GET https://localhost:57513/config/v1/event_log&lt;/code&gt;&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://developpef.blogspot.com/feeds/8603212562234857103/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1566084130752530982/8603212562234857103?isPopup=true' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/8603212562234857103'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/8603212562234857103'/><link rel='alternate' type='text/html' href='http://developpef.blogspot.com/2020/11/connecter-un-automate-un-serveur-opcua.html' title='Connecter un automate à un serveur OPC/UA sous Linux'/><author><name>Paul-Emmanuel Faidherbe</name><uri>http://www.blogger.com/profile/14333816988154371906</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJF9OHIybxl9BZ8qHqpkX3CzEcAtPsFesbRt6NQNIAy_LD1arQRfxFXPo0Ur442M6LqY4ZNZk9gwTy474Fa_gayo5ukXRMAxwkMBRTFQqVkD2y1kMHdxc_W0lox-j_E8A6rlntimZ50JZwxmK-mM5egC_mdthRx5lUFhpt_H7obAZ-7w/s220/identite.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6TIcFeSPovpHgUYrjy_FdPIoxiE61eFBkATrp_9BJz02AMjXcjHMr3lqU7CboYx76jB0gm2dOYaz7sFPvthn9ZK8gz0MaXZoUayYU4JnKG8HNLhyphenhyphenqaGR0hn_rjsKg7bh_jpHdXhIjmCo/s72-c/Capture+du+2020-11-14+20-56-02.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1566084130752530982.post-6678189697285879875</id><published>2020-10-31T15:23:00.002+01:00</published><updated>2020-10-31T15:23:52.042+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="cumulocity"/><category scheme="http://www.blogger.com/atom/ns#" term="iot"/><category scheme="http://www.blogger.com/atom/ns#" term="lora"/><category scheme="http://www.blogger.com/atom/ns#" term="micropython"/><category scheme="http://www.blogger.com/atom/ns#" term="pycom"/><category scheme="http://www.blogger.com/atom/ns#" term="pygate"/><category scheme="http://www.blogger.com/atom/ns#" term="the things network"/><title type='text'>Créer un réseau LoRa et exploiter les données transmises</title><content type='html'>&lt;p&gt;
  Nous allons voir ici comment contruire facilement votre propre réseau local LoRaWAN.
&lt;/p&gt;
&lt;h3&gt;Le matériel&lt;/h3&gt;
&lt;p&gt;
  Avant de commencer, il est nécessaire de s&#39;équiper d&#39;un ou plusieurs devices constituant les noeuds finaux (transmettant les données de capteurs) ainsi que d&#39;une passerelle (gateway) pour la centralisation des messages. Pour plus de détails sur l&#39;architecture LoRaWAN, vous pouvez &lt;a href=&quot;https://www.thethingsnetwork.org/docs/lorawan/architecture.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;voir ici&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
  Pour cet article, la plateforme qui recevra nos messages LoRa (le Network server) sera The Things Network (TTN) : gratuit, complet et simple d&#39;utilisation.
&lt;/p&gt;
&lt;p&gt;
  A ce jour, le matériel le plus abordable (tant en prix qu&#39;en complexité) sur le marché est fourni par &lt;a href=&quot;https://pycom.io/&quot; target=&quot;_blank&quot;&gt;Pycom&lt;/a&gt; : en premier lieu leur toute nouvelle passerelle &lt;a href=&quot;https://pycom.io/product/pygate/&quot; target=&quot;_blank&quot;&gt;Pygate&lt;/a&gt;, qui est très simple à prendre en main et peu chère. Elle est programmable en MicroPython et dispose d&#39;une extension Ethernet/PoE. Pour ce qui est des noeuds et capteurs, un &lt;a href=&quot;https://pycom.io/product/lopy4/&quot; target=&quot;_blank&quot;&gt;LoPy4&lt;/a&gt; posé sur une carte d&#39;extensions &lt;a href=&quot;https://pycom.io/product/pysense-2-0-x/&quot; target=&quot;_blank&quot;&gt;PySense&lt;/a&gt; répondra à la plupart des besoins.
&lt;/p&gt;
&lt;p&gt;
  Je passe sur les détails de l&#39;assemblage des cartes, très bien expliqué sur leur site.
&lt;/p&gt;
&lt;h3&gt;La programmation&lt;/h3&gt;
&lt;p&gt;
  Le développement en MicroPython et la programmation des cartes peut se faire assez simplement avec VSCode et l&#39;extension Pymakr.
&lt;/p&gt;
&lt;h4&gt;La passerelle&lt;/h4&gt;
&lt;p&gt;
  Avant même de commencer à programmer la Pygate, il est nécessaire de l&#39;enregistrer auprès de la plateforme TTN afin de récupérer des indentifiants. Pour cela, il suffit de suivre &lt;a href=&quot;https://docs.pycom.io/tutorials/networks/lora/lorawan-nano-gateway/#registering-with-ttn&quot; target=&quot;_blank&quot;&gt;les instructions ici&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
  Ensuite, sur le site de Pycom se trouve &lt;a href=&quot;https://docs.pycom.io/tutorials/expansionboards/pygate/&quot; target=&quot;_blank&quot;&gt;un très bon exemple de code&lt;/a&gt; permettant de programmer la passerelle pour se connecter à TTN via Wifi. Si vous êtes équipés du module Ethernet/PoE, il suffit de remplacer le code intialisant l&#39;interface Wifi par celui-ci :
&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;from network import ETH

eth = ETH()
while not eth.isconnected():
    print(&quot;connecting to ethernet&quot;)
    time.sleep(1)
print(&quot;ifconfig&quot;, eth.ifconfig())
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
  Ainsi, une fois la gateway connectée à un réseau accédant à Internet, la communication s&#39;établira toute seule et vous verrez remonter régulièrement des signaux de vie sur la page de TTN.
&lt;/p&gt;
&lt;h4&gt;Les noeuds&lt;/h4&gt;
&lt;p&gt;
  Pour ce qui est du code nécessaire à l&#39;activation d&#39;un end device, il existe encore une fois &lt;a href=&quot;https://docs.pycom.io/tutorials/networks/lora/lorawan-nano-gateway/#lopy-node&quot; target=&quot;_blank&quot;&gt;un très bon exemple&lt;/a&gt; sur le site de Pycom. Comme expliqué, il vous sera nécessaire de créer une application dans TTN pour récupérer tous les identifiants utiles.
&lt;/p&gt;
&lt;p&gt;
  Afin de transmettre les données des capteurs d&#39;un Pysense, tout est disponible &lt;a href=&quot;https://docs.pycom.io/tutorials/expansionboards/pysense2/#app&quot; target=&quot;_blank&quot;&gt;sur cette page&lt;/a&gt;.
&lt;/p&gt;
&lt;h3&gt;Le décodage des données&lt;/h3&gt;
&lt;p&gt;
  Sur TTN, le payload des messages est encodé en hexadécimal, sous forme d&#39;octets. Mais la plaforme met à disposition, au sein des Applications, des moyens de décoder et manipuler les contenus afin de faciliter leur utilisation, et ce à partir de fonctions Javascript.
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgS_ZvJ9Jnt5oFwOiTWyMFo7TvZAwfWuot6TMOffe_PEKI-2K_x7MDtrVWbNKpESNqbsaFFRLAoCyT-vuAGFUmOie68Kh9pV8Y91IYdlEJaKvbmD7q7b-1PNWTnphDWrCZ4i4iHcweNNKY/s0/article.png&quot; style=&quot;display: block; padding: 1em 0; text-align: center; &quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; data-original-height=&quot;268&quot; data-original-width=&quot;1039&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgS_ZvJ9Jnt5oFwOiTWyMFo7TvZAwfWuot6TMOffe_PEKI-2K_x7MDtrVWbNKpESNqbsaFFRLAoCyT-vuAGFUmOie68Kh9pV8Y91IYdlEJaKvbmD7q7b-1PNWTnphDWrCZ4i4iHcweNNKY/s0/article.png&quot;/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h4&gt;Le Decoder&lt;/h4&gt;
&lt;p&gt;
  Ces fonctions permettent de transformer le contenu brut (octets) en données lisibles.
&lt;/p&gt;
&lt;p&gt;
  Prenons le scénario suivant : le payload envoyé est constitué de données encodées selon un mécanisme personnalisé : 15 premiers bits pour une température, 7 bits suivants pour une humidité... Cette succession de bits est finalement encodée en hexa afin d&#39;être transmise.
&lt;/p&gt;
&lt;p&gt;
  Voici un exemple de décodeur qui transforme le payload des messages LoRa en une chaine binaire :
&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;function Decoder(bytes, port) {
  function bytesToBinStr(bytes) {
    var binstr = &#39;&#39;;
    for(var i=0; i&amp;lt;bytes.length; i++) { 
        var str = bytes[i].toString(2);
        while(str.length&amp;lt;8){
          str = &#39;0&#39;+str;
        }
        binstr += str;
    }
    return binstr;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
  Ensuite, selon notre scénario, une fonction permettant de reconstituer la température :
&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;function parseForTemperature(binStr) {
    var level = 0.0;
    if (binStr.length &gt;= 18) { 
      var entier = parseInt(binStr.substr(3, 7), 2);
      var dec = parseInt(binStr.substr(10, 8), 2);
      level = entier + (dec / 100);
      if(binStr.substr(2, 1)==&quot;1&quot;) {
          level = level * -1;
      }
  	}
    return level;
  }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
  Enfin, le code complet du Decoder permettant de retourner la température :
&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;function Decoder(bytes, port) {

  function bytesToBinStr(bytes) {
    ...
  }
  
  function parseForTemperature(binStr) {
  	...
  }
  
  // Decode an uplink message from a buffer
  // (array) of bytes to an object of fields.
  var decoded = {};

  var binstr = bytesToBinStr(bytes);
  decoded.temp = parseForTemperature(binstr);

  return decoded;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Le Converter&lt;/h4&gt;
&lt;p&gt;
  Imaginons maintenant que nous souhaitions transmettre ces données à une plateforme tierce. Il est possible grâce aux convertisseurs de transformer les données décodées afin d&#39;en adapter le format, pour être correctement interprétées par la plateforme cible (ceux qui me suivent reconnaitront &lt;a href=&quot;https://www.softwareag.cloud/site/product/cumulocity-iot.html&quot; target=&quot;_blank&quot;&gt;Cumulocity&lt;/a&gt; ;). En voici un exemple :
&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;function Converter(decoded, port) {
  // Merge, split or otherwise
  // mutate decoded fields.
  var date = new Date().toISOString();
  var tempMeasurement = {&#39;c8y_TemperatureMeasurement&#39;:{&#39;T&#39;:{&#39;unit&#39;:&#39;C&#39;,&#39;value&#39;:decoded.temp}}};
  tempMeasurement.type = &#39;c8y_TemperatureMeasurement&#39;;
  tempMeasurement.time = date;
  tempMeasurement.source = {&#39;id&#39;:&#39;3466704&#39;};

  var converted = {&#39;measurements&#39;:[tempMeasurement]};

  return converted;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
  Ce qui, ici, produira au final un message de la forme :
&lt;/p&gt;
&lt;pre&gt;
{
        &quot;app_id&quot;: &quot;pygate-test&quot;,
        &quot;dev_id&quot;: &quot;pysense&quot;,
        &quot;hardware_serial&quot;: &quot;...&quot;,
        &quot;port&quot;: 2,
        &quot;counter&quot;: 27,
        &quot;payload_raw&quot;: &quot;CBHMmQFHhVM=&quot;,
        &quot;payload_fields&quot;: {
            &quot;measurements&quot;: [
                {
                    &quot;c8y_TemperatureMeasurement&quot;: {
                        &quot;T&quot;: {
                            &quot;unit&quot;: &quot;C&quot;,
                            &quot;value&quot;: 32.71
                        }
                    },
                    &quot;source&quot;: {
                        &quot;id&quot;: &quot;3466704&quot;
                    },
                    &quot;time&quot;: &quot;2020-10-27T16:21:50.698Z&quot;,
                    &quot;type&quot;: &quot;c8y_TemperatureMeasurement&quot;
                }
            ]
        },
        &quot;metadata&quot;: {
            &quot;time&quot;: &quot;2020-10-27T16:21:50.491459008Z&quot;,
            &quot;frequency&quot;: 868.1,
            &quot;modulation&quot;: &quot;LORA&quot;,
            &quot;data_rate&quot;: &quot;SF7BW125&quot;,
            &quot;coding_rate&quot;: &quot;4/5&quot;,
            &quot;gateways&quot;: [
                {
                    &quot;gtw_id&quot;: &quot;eui-...&quot;,
                    &quot;timestamp&quot;: 2919800980,
                    &quot;time&quot;: &quot;&quot;,
                    &quot;channel&quot;: 0,
                    &quot;rssi&quot;: -25,
                    &quot;snr&quot;: 10,
                    &quot;rf_chain&quot;: 0
                }
            ]
        },
        &quot;downlink_url&quot;: &quot;https://integrations.thethingsnetwork.org/ttn-eu/api/v2/down/.../integromat?key=...&quot;
    }
&lt;/pre&gt;
&lt;p&gt;
  Vous avez maintenant tout ce qu&#39;il vous faut pour monter votre propre réseau LoRa et faire voyager vos données!
&lt;/p&gt;
&lt;p&gt;
  Nous verrons dans un prochain article comment développer un microservice sur Cumulocity pour récupérer ces messages et en extraire les measurements utiles.
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://developpef.blogspot.com/feeds/6678189697285879875/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1566084130752530982/6678189697285879875?isPopup=true' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/6678189697285879875'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/6678189697285879875'/><link rel='alternate' type='text/html' href='http://developpef.blogspot.com/2020/10/creer-un-reseau-lora-et-exploiter-les.html' title='Créer un réseau LoRa et exploiter les données transmises'/><author><name>Paul-Emmanuel Faidherbe</name><uri>http://www.blogger.com/profile/14333816988154371906</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJF9OHIybxl9BZ8qHqpkX3CzEcAtPsFesbRt6NQNIAy_LD1arQRfxFXPo0Ur442M6LqY4ZNZk9gwTy474Fa_gayo5ukXRMAxwkMBRTFQqVkD2y1kMHdxc_W0lox-j_E8A6rlntimZ50JZwxmK-mM5egC_mdthRx5lUFhpt_H7obAZ-7w/s220/identite.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgS_ZvJ9Jnt5oFwOiTWyMFo7TvZAwfWuot6TMOffe_PEKI-2K_x7MDtrVWbNKpESNqbsaFFRLAoCyT-vuAGFUmOie68Kh9pV8Y91IYdlEJaKvbmD7q7b-1PNWTnphDWrCZ4i4iHcweNNKY/s72-c/article.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1566084130752530982.post-8672814894420268327</id><published>2020-01-24T21:24:00.000+01:00</published><updated>2020-01-24T21:24:24.530+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="api"/><category scheme="http://www.blogger.com/atom/ns#" term="cumulocity"/><category scheme="http://www.blogger.com/atom/ns#" term="edge computing"/><category scheme="http://www.blogger.com/atom/ns#" term="iiot"/><category scheme="http://www.blogger.com/atom/ns#" term="kepware"/><category scheme="http://www.blogger.com/atom/ns#" term="siemens"/><title type='text'>Pilotez votre usine pour une production plus agile grâce au Edge computing</title><content type='html'>&lt;p&gt;
Pour faire suite à mon précédent article, où nous avions vu &lt;a href=&quot;https://developpef.blogspot.com/2020/01/convergence-des-reseaux-ot-et-it-en.html&quot;&gt;comment lier les réseaux IT et OT&lt;/a&gt; pour faire de la supervision (par exemple d&#39;une chaine de production), il reste maintenant à voir comment agir sur les équipements connectés dans l&#39;usine : envoyer des commandes, définir des programmes, déclencher des arrêts...
&lt;/p&gt;
&lt;p&gt;
Pour simplifier la réalisation et ne pas interférer avec les réseaux de terrains spécifiques (Profinet, Profibus, AS-i...), nous allons interfacer le noeud &quot;de plus haut niveau&quot; en termes de réseaux OT : l&#39;automate!
&lt;/p&gt;
&lt;p&gt;
Voici en résumé ce qui peut être mis en place :
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVCY-a98JuEL_Z41SX5jonzuIwHs1CStlVEAaavqKA4h72DFdVOAHPqup45bkWHOwSTiMf_Nh74CPTQ5qCo_htZy4QLd2e4Zdrf9d7umq_7OExtW2QqjLZVOu1t0SIQdfNx0Afo2udtAU/s1600/article+%25281%2529.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVCY-a98JuEL_Z41SX5jonzuIwHs1CStlVEAaavqKA4h72DFdVOAHPqup45bkWHOwSTiMf_Nh74CPTQ5qCo_htZy4QLd2e4Zdrf9d7umq_7OExtW2QqjLZVOu1t0SIQdfNx0Afo2udtAU/s1600/article+%25281%2529.png&quot; data-original-width=&quot;641&quot; data-original-height=&quot;521&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;
En quelques mots :
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;La plateforme IoT Cumulocity Edge permet de planifier n&#39;importe quel type d&#39;opération à destination d&#39;un équipement spécifique (marche/arrêt, changement de programme...)&lt;/li&gt;
&lt;li&gt;Une instance de Kepware Kepserver permet d&#39;exposer les données et les actions possible sur un équipement (quel qu&#39;il soit, même ancien et/ou propriétaire) via une interface OPC/UA&lt;/li&gt;
&lt;li&gt;Un &quot;agent&quot; permet de récupérer les opérations en attente sur la plateforme pour les interpréter en appels de méthodes OPC/UA, que Kepware traduira ensuite en langage automate&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;Le pilotage du parc machines grâce aux fonctions de device management&lt;/h4&gt;
&lt;p&gt;
Pour commencer, les commandes à envoyer aux équipements sont décrites dans des &quot;opérations&quot; sur la plateforme IoT :
&lt;/p&gt;
&lt;table&gt;&lt;tr&gt;&lt;td&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-NLg3E8vz70ODZvr9ur4FcEVwODOfyJNyCG37mgxGDfRhgZurFA4ijIpSLCz9248CqLfedJRbyP9kUXCZFNV0HgPWLkB29ZtfnvxbinFzq9U8dnLJ3BV2pwpIyHK0t2SjVZFVQj8IwT8/s1600/C8Yops.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-NLg3E8vz70ODZvr9ur4FcEVwODOfyJNyCG37mgxGDfRhgZurFA4ijIpSLCz9248CqLfedJRbyP9kUXCZFNV0HgPWLkB29ZtfnvxbinFzq9U8dnLJ3BV2pwpIyHK0t2SjVZFVQj8IwT8/s640/C8Yops.png&quot; width=&quot;640&quot; height=&quot;367&quot; data-original-width=&quot;1500&quot; data-original-height=&quot;861&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/td&gt;&lt;td&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4_vqyVx5j2aoJlHFDIYP7WOEdSH2idUk8-hfC_6wQ_G2tJh_BaATliITEykXmEfUE6yqb4mpDEbDXdGEjrVSpErRSFBCQJ7ZtGDNOThgh6B1PvB1yzMzqTrVfjYqXyuzjP7UM-Mwnx1k/s1600/IMG_20200110_155827_914_compressed.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4_vqyVx5j2aoJlHFDIYP7WOEdSH2idUk8-hfC_6wQ_G2tJh_BaATliITEykXmEfUE6yqb4mpDEbDXdGEjrVSpErRSFBCQJ7ZtGDNOThgh6B1PvB1yzMzqTrVfjYqXyuzjP7UM-Mwnx1k/s400/IMG_20200110_155827_914_compressed.jpg&quot; width=&quot;225&quot; height=&quot;400&quot; data-original-width=&quot;900&quot; data-original-height=&quot;1600&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;p&gt;
Le principe est le suivant : l&#39;opération est créée pour un équipement spécifique, au statut &quot;En attente&quot;. L&#39;équipement (ou un agent) va alors consulter régulièrement la plateforme pour savoir si une opération lui a été demandée. Le cas échéant, il la prendra en considération en la passant au statut &quot;En cours d&#39;exécution&quot; et réalisera la tâche demandée. Une fois terminée, il passera l&#39;opération au statut &quot;Succès&quot; ou &quot;Echec&quot; selon le résultat.
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;Un Agent pour orchestrer les opérations&lt;/h4&gt;
&lt;p&gt;
Dans certains cas, l&#39;intégration d&#39;un agent spécifique pourra être nécessaire pour scruter le contenu de la plateforme IoT et piloter en conséquence les interfaces OPC/UA existantes.
&lt;/p&gt;
&lt;p&gt;
Un des moyens les plus versatiles pour ce genre de besoin peut être un script en langage Python : il peut facilement s&#39;intégrer avec les interfaces de la plateforme IoT et l&#39;OPC/UA et peut être déployé sur n&#39;importe quelle passerelle ou autre équipement réseau de ce type.
&lt;/p&gt;
&lt;p&gt;
Vous voilà équipés pour interagir au mieux avec vos lignes de production!
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://developpef.blogspot.com/feeds/8672814894420268327/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1566084130752530982/8672814894420268327?isPopup=true' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/8672814894420268327'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/8672814894420268327'/><link rel='alternate' type='text/html' href='http://developpef.blogspot.com/2020/01/pilotez-votre-usine-pour-une-production.html' title='Pilotez votre usine pour une production plus agile grâce au Edge computing'/><author><name>Paul-Emmanuel Faidherbe</name><uri>http://www.blogger.com/profile/14333816988154371906</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJF9OHIybxl9BZ8qHqpkX3CzEcAtPsFesbRt6NQNIAy_LD1arQRfxFXPo0Ur442M6LqY4ZNZk9gwTy474Fa_gayo5ukXRMAxwkMBRTFQqVkD2y1kMHdxc_W0lox-j_E8A6rlntimZ50JZwxmK-mM5egC_mdthRx5lUFhpt_H7obAZ-7w/s220/identite.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVCY-a98JuEL_Z41SX5jonzuIwHs1CStlVEAaavqKA4h72DFdVOAHPqup45bkWHOwSTiMf_Nh74CPTQ5qCo_htZy4QLd2e4Zdrf9d7umq_7OExtW2QqjLZVOu1t0SIQdfNx0Afo2udtAU/s72-c/article+%25281%2529.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1566084130752530982.post-8970359877152957987</id><published>2020-01-10T16:24:00.000+01:00</published><updated>2020-01-10T16:24:30.000+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="api"/><category scheme="http://www.blogger.com/atom/ns#" term="cumulocity"/><category scheme="http://www.blogger.com/atom/ns#" term="edge computing"/><category scheme="http://www.blogger.com/atom/ns#" term="iiot"/><category scheme="http://www.blogger.com/atom/ns#" term="plc"/><category scheme="http://www.blogger.com/atom/ns#" term="siemens"/><title type='text'>Convergence des réseaux OT et IT en pratique : de l&#39;automate à la plateforme IoT (sans Cloud!)</title><content type='html'>&lt;p&gt;
Après avoir traité le sujet du Edge computing dans &lt;a href=&quot;https://developpef.blogspot.com/2019/12/iot-edge-computing-pour-la-maintenance.html&quot;&gt;mon précédent article&lt;/a&gt;, il est temps d&#39;aborder un autre frein souvent recontré lors de la transformation numérique d&#39;une unité de production : l&#39;unification des réseaux industriels (OT) et applicatifs (IT).
&lt;/p&gt;
&lt;h4&gt;L&#39;automate comme noeud central&lt;/h4&gt;
&lt;p&gt;
Les APIs (Automate programmable industriel) ou PLC en anglais (Programmable Logic Controller) sont depuis longtemps les &quot;cerveaux&quot; des usines, orchestrant les différents processus techniques. Depuis quelques années, les fabricants misent de plus en plus sur leur rôle central en les rendant de plus en plus intelligents et interconnectés.
&lt;/p&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;td&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1_grHT-zijV_CcvtE5aPKDt4vOnX00gqDkDAALOU0wLlyfu1nlQlLCcSjzGKNGUswNaP9C5QJu8Wt28mPRci8OBta_m9rpZA_LUhEDY6CmKKVcnDIb0ot_uVVAAwzE3fpN_BWMWLbbN0/s1600/button_industrial2.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1_grHT-zijV_CcvtE5aPKDt4vOnX00gqDkDAALOU0wLlyfu1nlQlLCcSjzGKNGUswNaP9C5QJu8Wt28mPRci8OBta_m9rpZA_LUhEDY6CmKKVcnDIb0ot_uVVAAwzE3fpN_BWMWLbbN0/s320/button_industrial2.jpg&quot; width=&quot;320&quot; height=&quot;320&quot; data-original-width=&quot;500&quot; data-original-height=&quot;500&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/td&gt;
&lt;td&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQQKJuJDMnerNSL5gqC47btn6XSzXzGAxwsgxuChCe6xWQvdxecYsxRXeCQ6frWkbnbWQ69HJdnptMX7FysHqI2jBDQijQ8SPkkgiFbFKFVeVcg0rDk7TvGDiTQO3kDbNEcCQVKdkTekQ/s1600/alleantia-smart-manufacturing-fig02.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQQKJuJDMnerNSL5gqC47btn6XSzXzGAxwsgxuChCe6xWQvdxecYsxRXeCQ6frWkbnbWQ69HJdnptMX7FysHqI2jBDQijQ8SPkkgiFbFKFVeVcg0rDk7TvGDiTQO3kDbNEcCQVKdkTekQ/s400/alleantia-smart-manufacturing-fig02.png&quot; width=&quot;400&quot; height=&quot;265&quot; data-original-width=&quot;750&quot; data-original-height=&quot;496&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;Mais avant d&#39;envisager le remplacer de tout le parc installé dans un site, il existe différents moyens permettant de faire remonter les informations d&#39;un automate standard (même ancien) vers des applications du SI.&lt;/p&gt;
&lt;h4&gt;Cas d&#39;usage&lt;/h4&gt;
&lt;p&gt;
Le PoC réalisé ici repose sur un des automates les plus répandus dans l&#39;industrie, à savoir un Siemens S7-200, décliné dans le modèle d&#39;entrée de gamme le &lt;a href=&quot;https://new.siemens.com/global/en/products/automation/systems/industrial/plc/logo/industry.html&quot;&gt;LOGO! 8&lt;/a&gt;. Plusieurs briques logicielles vont lui être adossées afin de récupérer les états de ses différentes entrées/sorties et les remonter vers la plateforme IoT Cumulocity Edge installée localement.
&lt;/p&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;td&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisxHoQqV4HfLkC1Jy9aGVHRy6mYmdnBVTplw3TB15cKi5OIWCstUPJstp9wrp-RObQujRtigU9gB5cH9ZLZHkac9oVWlpK9VRq7V1ZNLnZuoRnhhYaVAHj_NyGaCGwVR7113pLzk7UKdk/s1600/SiemensLogoC8Y.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisxHoQqV4HfLkC1Jy9aGVHRy6mYmdnBVTplw3TB15cKi5OIWCstUPJstp9wrp-RObQujRtigU9gB5cH9ZLZHkac9oVWlpK9VRq7V1ZNLnZuoRnhhYaVAHj_NyGaCGwVR7113pLzk7UKdk/s640/SiemensLogoC8Y.png&quot; width=&quot;640&quot; height=&quot;330&quot; data-original-width=&quot;987&quot; data-original-height=&quot;561&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEVjLAvbPB2pXBgWl6Lx0gjn-ZL2oV_AxTlyHjgOdzlcKTGwi9-4uvnetMZdDvP1mrafenPbTQFXr87yZ1uB7DJGjlViwFHP2KsqSS4uRymUZGYy3c4t4UtkVMfanLDCHhUM5P8whmZJk/s1600/IMG_20200110_155827_914_compressed.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEVjLAvbPB2pXBgWl6Lx0gjn-ZL2oV_AxTlyHjgOdzlcKTGwi9-4uvnetMZdDvP1mrafenPbTQFXr87yZ1uB7DJGjlViwFHP2KsqSS4uRymUZGYy3c4t4UtkVMfanLDCHhUM5P8whmZJk/s320/IMG_20200110_155827_914_compressed.jpg&quot; width=&quot;180&quot; height=&quot;320&quot; data-original-width=&quot;900&quot; data-original-height=&quot;1600&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;h4&gt;Kepware Kepserver comme porte d&#39;entrée&lt;/h4&gt;
&lt;p&gt;
Ce &lt;a href=&quot;https://www.kepware.com/en-us/products/kepserverex/&quot;&gt;logiciel distribué par PTC&lt;/a&gt; est le véritable couteau suisse de l&#39;industrie 4.0, car il permet de se connecter directement et nativement à un grand nombre d&#39;automates puisqu&#39;il contient tous les pilotes nécessaires :
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitg222FkeJe9fqkrMfb6EgpdCf1Uf42RvKizlGZ4DTA2mLX9_wXO6Y2GlAlVY-xgPufp3kyBSYU89q4Nufn38yDIc7Scn6QnbriEFsrFr0kNfw5vKzOS_i7s8_FToAPfhnqgnldQeecsc/s1600/kepware_drivers.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitg222FkeJe9fqkrMfb6EgpdCf1Uf42RvKizlGZ4DTA2mLX9_wXO6Y2GlAlVY-xgPufp3kyBSYU89q4Nufn38yDIc7Scn6QnbriEFsrFr0kNfw5vKzOS_i7s8_FToAPfhnqgnldQeecsc/s400/kepware_drivers.png&quot; width=&quot;400&quot; height=&quot;362&quot; data-original-width=&quot;688&quot; data-original-height=&quot;622&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;
Après configuration pour utiliser le pilote Siemens et reconnaissance des entrées/sorties, il expose automatiquement les données issues de l&#39;automate via un serveur OPC/UA :
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgb4_7nzYu5fCJQ0IPyhaxSo89VpoEOUcnTjYqSlD1ZcektLH9fiGUnKcLd4K7gILgsG3IN66glSjQKzI41kCiyKhp9pws32hyphenhyphenEwPre8pgop8_Z6bRvMiC1VSYmxlDs-MuOsrSSza2WgBQ/s1600/kepware_opc.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgb4_7nzYu5fCJQ0IPyhaxSo89VpoEOUcnTjYqSlD1ZcektLH9fiGUnKcLd4K7gILgsG3IN66glSjQKzI41kCiyKhp9pws32hyphenhyphenEwPre8pgop8_Z6bRvMiC1VSYmxlDs-MuOsrSSza2WgBQ/s640/kepware_opc.png&quot; width=&quot;640&quot; height=&quot;351&quot; data-original-width=&quot;1301&quot; data-original-height=&quot;713&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h4&gt;Cumulocity Edge et client OPC/UA&lt;/h4&gt;
&lt;p&gt;
La version Edge de Cumulocity IoT embarque nativement un connecteur vers un serveur OPC/UA. Il suffit donc de le faire pointer vers le serveur exposé par Kepware pour récupérer les informations de l&#39;automate :
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgm8K4mQjbncaJa-zPBDFE8MeEaS8seuvrqCagpzVviqmjLbPn1hp6nY8MKoa9WW4lhfBL-KJ2IE5BOSpPebMd-ncMr-xRlS5rratj2Fl2zerfJkGdzXIRrDLzgUZ6uQRoT6Lw3MUAdhEw/s1600/Capture+d%25E2%2580%2599%25C3%25A9cran+de+2020-01-10+16-13-03.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgm8K4mQjbncaJa-zPBDFE8MeEaS8seuvrqCagpzVviqmjLbPn1hp6nY8MKoa9WW4lhfBL-KJ2IE5BOSpPebMd-ncMr-xRlS5rratj2Fl2zerfJkGdzXIRrDLzgUZ6uQRoT6Lw3MUAdhEw/s640/Capture+d%25E2%2580%2599%25C3%25A9cran+de+2020-01-10+16-13-03.png&quot; width=&quot;640&quot; height=&quot;400&quot; data-original-width=&quot;1440&quot; data-original-height=&quot;900&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h3&gt;
Vous voici entrés dans la 4ème révolution industrielle!
&lt;/h3&gt;</content><link rel='replies' type='application/atom+xml' href='http://developpef.blogspot.com/feeds/8970359877152957987/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1566084130752530982/8970359877152957987?isPopup=true' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/8970359877152957987'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/8970359877152957987'/><link rel='alternate' type='text/html' href='http://developpef.blogspot.com/2020/01/convergence-des-reseaux-ot-et-it-en.html' title='Convergence des réseaux OT et IT en pratique : de l&#39;automate à la plateforme IoT (sans Cloud!)'/><author><name>Paul-Emmanuel Faidherbe</name><uri>http://www.blogger.com/profile/14333816988154371906</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJF9OHIybxl9BZ8qHqpkX3CzEcAtPsFesbRt6NQNIAy_LD1arQRfxFXPo0Ur442M6LqY4ZNZk9gwTy474Fa_gayo5ukXRMAxwkMBRTFQqVkD2y1kMHdxc_W0lox-j_E8A6rlntimZ50JZwxmK-mM5egC_mdthRx5lUFhpt_H7obAZ-7w/s220/identite.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1_grHT-zijV_CcvtE5aPKDt4vOnX00gqDkDAALOU0wLlyfu1nlQlLCcSjzGKNGUswNaP9C5QJu8Wt28mPRci8OBta_m9rpZA_LUhEDY6CmKKVcnDIb0ot_uVVAAwzE3fpN_BWMWLbbN0/s72-c/button_industrial2.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1566084130752530982.post-4095925349855516401</id><published>2019-12-17T11:11:00.000+01:00</published><updated>2019-12-17T11:11:58.859+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="cumulocity"/><category scheme="http://www.blogger.com/atom/ns#" term="edge computing"/><category scheme="http://www.blogger.com/atom/ns#" term="iiot"/><category scheme="http://www.blogger.com/atom/ns#" term="maintenance conditionnelle"/><title type='text'>IoT Edge computing pour la maintenance conditionnelle</title><content type='html'>&lt;p&gt;La transformation vers l&#39;&quot;Industrie 4.0&quot; implique de profonds changements pour les usines (organisationnels, technologiques...). Parmi eux, le concept de &quot;Edge computing&quot; fait partie des plus attendus et des plus complexes. Il découle du besoin grandissant d&#39;analyser de plus en plus d&#39;informations issues des machines, dans le contexte notamment de la maintenance conditionnelle, qui permet de connaitre en temps réel leur état pendant les phases de production.
&lt;/p&gt;
&lt;h2&gt;
Vers l’usine intelligente...&lt;/h2&gt;
&lt;p&gt;Le &quot;Edge computing&quot; a pour vocation d&#39;apporter des capacités de calcul et de prise de décision au sein même de l&#39;usine, au plus près des machines.&lt;/p&gt;
&lt;p&gt;L&#39;intérêt premier est de répondre aux problématiques de sécurité, vis-à-vis de la connectivité avec un Cloud : disposer d&#39;une plateforme IoT fonctionnant entièrement en mode déconnecté permet de s&#39;affranchir de toutes les difficultés d&#39;ouvrir un réseau OT vers l&#39;extérieur et ainsi limiter les risques de failles de sécurité.&lt;/p&gt;
&lt;p&gt;Le second intérêt est de permettre l&#39;analyse en temps réel de signaux complexes et volumineux, tels que des vibrations ou des rotations et ainsi accélérer la prise de décision. Plus besoin d&#39;agréger ou préformatter les données avant de les envoyer vers un Cloud, ce qui réduit les efforts nécessaires et améliore la qualité des informations utilisées dans les analyses.&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://www2.deloitte.com/content/dam/insights/us/articles/4051_The-smart-factory/figures/4051_fig2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;800&quot; data-original-width=&quot;768&quot; height=&quot;400&quot; src=&quot;https://www2.deloitte.com/content/dam/insights/us/articles/4051_The-smart-factory/figures/4051_fig2.png&quot; width=&quot;384&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h2&gt;
... utilisant l&#39;expérience de l&#39;Homme&lt;/h2&gt;
&lt;p&gt;Mais cette usine &quot;agile&quot; et &quot;intelligente&quot; ne serait rien sans le savoir et le savoir-faire des personnels de maintenance. Leur connaissance du parc de machines et leur expérience en détection de pannes sont les éléments clés qui doivent être utilisés et préservés tout au long du processus de transformation numérique.&lt;/p&gt;&lt;p&gt;
Il est donc important que les nouveaux outils introduits au sein de l&#39;usine soient au service de ces Hommes et leur permettent de garder la main sur leur métier, tout en valorisant leurs connaissances et en facilitant leur quotidien.&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisZisuDdM_I91TaasYE0ZQgApJztAwwHnM_22WUNBjEnU57IHkDTlJKkT87moTwAtjAcZnubBkdCTTG3aki_vtDH72vlE9qCgzv__NzzKNYZFOlX7Yo1rYF4Cfi42IHHFn6XvPgxmPFkc/s1600/smart-factory-article-1-877x432.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;432&quot; data-original-width=&quot;877&quot; height=&quot;197&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisZisuDdM_I91TaasYE0ZQgApJztAwwHnM_22WUNBjEnU57IHkDTlJKkT87moTwAtjAcZnubBkdCTTG3aki_vtDH72vlE9qCgzv__NzzKNYZFOlX7Yo1rYF4Cfi42IHHFn6XvPgxmPFkc/s400/smart-factory-article-1-877x432.jpg&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h2&gt;
Par des industriels, pour des industriels&lt;/h2&gt;
&lt;p&gt;&lt;b&gt;Brilliant things&lt;/b&gt;  repose sur la plateforme &lt;a href=&quot;https://www.softwareag.cloud/site/product/cumulocity-iot.html&quot;&gt;Cumulocity IoT&lt;/a&gt;, de l&#39;éditeur allemand SoftwareAG, plusieurs fois reconnue comme leader sur le marché par des organismes observateurs indépendants. Celle-ci apporte toutes les fonctionnalités d&#39;une plateforme (dashboard, device management, droits d&#39;accès, stockage, sécurité...) ainsi qu&#39;une large palette de connecteurs vers des protocoles de communication industriels (OPC/UA, Modbus...) et des pilotes pour des machines de grands fabricants (DMG-MORI, Dürr, Engel...) développés par le consensus d’industriels &lt;a href=&quot;https://adamos.com/en/iiot-platform&quot;&gt;ADAMOS&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;
De plus, sa version &lt;a href=&quot;https://www.softwareag.com/corporate/products/data_analytics/edge_analytics/default.html&quot;&gt;Edge&lt;/a&gt; décline toutes les fonctionnalités de la version SaaS dans un environnement pouvant être déployé localement, sur un serveur situé dans l&#39;usine, sans nécessiter de connexion vers l&#39;internet. Elle offre en supplément la présence du moteur de streaming analytics &lt;a href=&quot;https://www.softwareag.com/ru/products/data_analytics/analytics/default&quot;&gt;Apama&lt;/a&gt;, capable de recevoir et traiter d&#39;importants flux d&#39;évènements.&lt;/p&gt;
&lt;h2&gt;
Plus de pouvoir pour la maintenance&lt;/h2&gt;
&lt;p&gt;&lt;b&gt;Brilliant things&lt;/b&gt; est une solution destinée au personnel de maintenance : elle met à disposition une interface simple d&#39;utilisation pour créer des corrélations d&#39;évènements, afin de générer une information à haute valeur pour la maintenance, à partir d&#39;évènements disparates reçus des différents équipements de l&#39;usine. &lt;/p&gt;&lt;p&gt;
Par exemple, en s&#39;appuyant sur son expérience et sa connaissance du parc, l&#39;utilisateur (typiquement un responsable de maintenance) pourra créer une corrélation d&#39;évènements avancée du type : &lt;b&gt;&quot;Si, sur ma fraiseuse verticale, la vitesse de rotation de la broche dépasse 60.000 tours/min et que la température de l&#39;outil atteint 85°C dans un intervalle de 30 secondes, pendant le programme TUENC5, alors déclencher une alarme !&quot;&lt;/b&gt;. En complément, d&#39;autres règles de gestion dans la plateforme peuvent implémenter un scénario d&#39;escalade (envoi de mail par ex) ou un workflow de traitement (déclencher une opération : arrêt machine...).&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0QB_uJTJKSh1LGDwL9S-3eYZ9o12j0BziaKBXOmr3VToA4CKNsSpxSbq6i8cVDgSJDYyJ_caI-nERmf16P5Ge8j_Y3lYZ6rALypltqf0AylNulCjS81z-AYLXLE-T3AKO88YDfSxtxZA/s1600/Edge_lite_compressed.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;889&quot; data-original-width=&quot;1600&quot; height=&quot;356&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0QB_uJTJKSh1LGDwL9S-3eYZ9o12j0BziaKBXOmr3VToA4CKNsSpxSbq6i8cVDgSJDYyJ_caI-nERmf16P5Ge8j_Y3lYZ6rALypltqf0AylNulCjS81z-AYLXLE-T3AKO88YDfSxtxZA/s640/Edge_lite_compressed.jpg&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h2&gt;
Une vision globale du parc&lt;/h2&gt;
&lt;p&gt;La première étape consiste à sélectionner l&#39;ensemble des évènements qui seront utilisés pour créer la corrélation :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pour les machines en fonctionnement, peuvent être utilisés :&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Les évènements remontés en temps réel liés par exemple à une supervision conditionnelle : vitesses de rotation, température de fonctionnement, vibrations, qualité de l’huile...&lt;/li&gt;
&lt;li&gt;Les évènements liés à leurs opérations : temps de fonctionnement, programme courant, paramétrage...&lt;/li&gt;
&lt;li&gt;Les informations contextuelles liées à la maintenance : date de dernière révision, indicateurs (MTBF, MTTR...)&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Les évènements issus d&#39;autres appareils connectés à la plateforme (autres que les machines) : détecteurs de fumée, capteurs d&#39;hygrométrie ambiante, de luminosité...&lt;/li&gt;
&lt;li&gt;Des évènements spécifiques issus d&#39;autres systèmes applicatifs du Système d’Information, par exemple venant d&#39;un broker MQTT ou service web REST&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEyCoJPp09NgceC1HxR77QZWl5VRI35eEFb47Ihc1jHTHy57p4WIfZPNoN_dXpdDjl3Li2am4-8TscsVqNG5tUeqTD12IR0r0EwOIREjQtBgdtMVJBfNS8gJW1bAujESsBYm4A0yHb5hw/s1600/Capture1.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEyCoJPp09NgceC1HxR77QZWl5VRI35eEFb47Ihc1jHTHy57p4WIfZPNoN_dXpdDjl3Li2am4-8TscsVqNG5tUeqTD12IR0r0EwOIREjQtBgdtMVJBfNS8gJW1bAujESsBYm4A0yHb5hw/s640/Capture1.PNG&quot; width=&quot;640&quot; height=&quot;319&quot; data-original-width=&quot;1600&quot; data-original-height=&quot;798&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h2&gt;L&#39;expertise en jeu&lt;/h2&gt;
&lt;p&gt;Vient maintenant le temps de l&#39;élaboration de la corrélation de tous ces évènements : fort de son expertise et de sa maitrise du parc de machines, l&#39;utilisateur va pouvoir reconstituer les conditions précises liées au dysfonctionnement à observer. Quelle que soit la complexité des évènements ou leur source, cette interface claire permet de configurer la succession de contrôles à effectuer pour créer une information à forte valeur ajoutée pour la production.&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhn1gV6iYJfe548DimGl0gC0PEjs493oZd9yeYenK1fvSZi3QpSzRuDXyltJ132BgIxTkReCrZ6Uwl2PCwweqRzAVtVR_X4-Ek119WjKD4a9liSNNuzpMW_bNd8gjdklEvV3cLscB-9mY/s1600/Capture2.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhn1gV6iYJfe548DimGl0gC0PEjs493oZd9yeYenK1fvSZi3QpSzRuDXyltJ132BgIxTkReCrZ6Uwl2PCwweqRzAVtVR_X4-Ek119WjKD4a9liSNNuzpMW_bNd8gjdklEvV3cLscB-9mY/s640/Capture2.PNG&quot; width=&quot;640&quot; height=&quot;319&quot; data-original-width=&quot;1600&quot; data-original-height=&quot;797&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;Ainsi, tout le savoir du personnel de maintenance est mis en jeu pour devenir la pierre angulaire de ce système d&#39;analyse, pour conduire à un ensemble performant et pertinent.&lt;/p&gt;
&lt;h2&gt;Maintenance conditionnelle intelligente&lt;/h2&gt;
&lt;p&gt;Dans certains contextes, la maintenance conditionnelle devient une source de bruit important, par le grand nombre de signaux et d&#39;alarmes qui peuvent être émis (capteurs, actionneurs, voyants...) : il peut alors être difficile de donner un sens juste à tous ces signaux même avec une parfaite connaissance du parc et des processus. Ce qui peut parfois mener à des situations à risque lorsque la multitude d&#39;informations est finalement ignorée car trop complexe à analyser dans les délais impartis.&lt;/p&gt;
&lt;p&gt;C&#39;est la raison pour laquelle il est important de pouvoir regrouper tous ces signaux et les analyser simultanément afin de lever des alertes plus pertinentes et plus efficaces, et ainsi réduire les risques de faux positifs ou d&#39;éléments perturbateurs.&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbHjwYjVCF9NF3jCOl4q1Z5fwxNXSq7091FM6CeAmVkGNIyljDWpZP44XqTtz8Td0l007eweOv8hKVl4Ct4v3IS1g0FgDGWvm74_JkKTZe1-QF4gniCs0DhuctEWaDtD8oxxNi3JrPIyc/s1600/Capture3.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbHjwYjVCF9NF3jCOl4q1Z5fwxNXSq7091FM6CeAmVkGNIyljDWpZP44XqTtz8Td0l007eweOv8hKVl4Ct4v3IS1g0FgDGWvm74_JkKTZe1-QF4gniCs0DhuctEWaDtD8oxxNi3JrPIyc/s640/Capture3.PNG&quot; width=&quot;640&quot; height=&quot;322&quot; data-original-width=&quot;1600&quot; data-original-height=&quot;805&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;En résumé, &lt;b&gt;Brilliant Things&lt;/b&gt; apporte une solution à la complexité montante de la maintenance conditionnelle, en la rendant accessible aux personnes qui en sont les premiers acteurs.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://developpef.blogspot.com/feeds/4095925349855516401/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1566084130752530982/4095925349855516401?isPopup=true' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/4095925349855516401'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/4095925349855516401'/><link rel='alternate' type='text/html' href='http://developpef.blogspot.com/2019/12/iot-edge-computing-pour-la-maintenance.html' title='IoT Edge computing pour la maintenance conditionnelle'/><author><name>Paul-Emmanuel Faidherbe</name><uri>http://www.blogger.com/profile/14333816988154371906</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJF9OHIybxl9BZ8qHqpkX3CzEcAtPsFesbRt6NQNIAy_LD1arQRfxFXPo0Ur442M6LqY4ZNZk9gwTy474Fa_gayo5ukXRMAxwkMBRTFQqVkD2y1kMHdxc_W0lox-j_E8A6rlntimZ50JZwxmK-mM5egC_mdthRx5lUFhpt_H7obAZ-7w/s220/identite.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisZisuDdM_I91TaasYE0ZQgApJztAwwHnM_22WUNBjEnU57IHkDTlJKkT87moTwAtjAcZnubBkdCTTG3aki_vtDH72vlE9qCgzv__NzzKNYZFOlX7Yo1rYF4Cfi42IHHFn6XvPgxmPFkc/s72-c/smart-factory-article-1-877x432.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1566084130752530982.post-5463908468340834114</id><published>2018-04-09T10:30:00.000+02:00</published><updated>2018-04-25T11:07:35.184+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="aframe"/><category scheme="http://www.blogger.com/atom/ns#" term="ar"/><category scheme="http://www.blogger.com/atom/ns#" term="arjs"/><title type='text'>IoT et interface naturelle (2) : réalité augmentée</title><content type='html'>&lt;p&gt;
Dans mon &lt;a href=&quot;http://developpef.blogspot.com/2017/12/iot-et-interface-naturelle.html&quot;&gt;précédent article&lt;/a&gt;, j&#39;ai présenté un type d&#39;interface naturelle basée sur l&#39;assistant vocal de Google.
&lt;/p&gt;
&lt;p&gt;
Cette fois, nous allons explorer les possibilités de la réalité augmentée! Avant de commencer, une petite démonstration :
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOFoAkkJ-jEJxKkc9qPIF5bgB70kBzojHHx_eaiNz4zuXhyUr6ag6VfgXseJQDmGdZHbtIoAcpKt23J7wac_9Xd9QBkdsLfiUKdEV3ADaej1MY_FQB1HRJ-gOu_CKdLT9TxEpuKZry5Js/s1600/Screenshot_20180409-170203.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOFoAkkJ-jEJxKkc9qPIF5bgB70kBzojHHx_eaiNz4zuXhyUr6ag6VfgXseJQDmGdZHbtIoAcpKt23J7wac_9Xd9QBkdsLfiUKdEV3ADaej1MY_FQB1HRJ-gOu_CKdLT9TxEpuKZry5Js/s400/Screenshot_20180409-170203.png&quot; width=&quot;225&quot; height=&quot;400&quot; data-original-width=&quot;900&quot; data-original-height=&quot;1600&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;
Comme vous pouvez le constater, le but est de récupérer en temps réel les données émises par un objet connecté (la poubelle), pour les afficher en réalité augmentée lors de son survol, avec n&#39;importe quel type de terminal (smartphone, tablette...).
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6uwYBwDz9_KEzwdnUyuEO9fPvJ7q7hlaXf1OitSz4tdZU_jtlvT_7hWkyy1HXdiflMp7XLd0XD5WNgK3f6dJLXKzbyc9h7pRQ6mOP7bIxEbdLg59vbL4QoabqgqStTF_JRKuWrG9mdL8/s1600/ARJS_C8Y.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6uwYBwDz9_KEzwdnUyuEO9fPvJ7q7hlaXf1OitSz4tdZU_jtlvT_7hWkyy1HXdiflMp7XLd0XD5WNgK3f6dJLXKzbyc9h7pRQ6mOP7bIxEbdLg59vbL4QoabqgqStTF_JRKuWrG9mdL8/s1600/ARJS_C8Y.PNG&quot; data-original-width=&quot;510&quot; data-original-height=&quot;721&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h3&gt;AR.js&lt;/h3&gt;
&lt;p&gt;
L&#39;interface en réalité augmentée est réalisée à partir du &lt;a href=&quot;https://github.com/jeromeetienne/AR.js&quot;&gt;framework AR.js&lt;/a&gt;. Son intérêt principal est de s&#39;appuyer sur les technos web (HTML, Javascript) et donc d&#39;être utilisable sur toutes les plateformes. Voici un exemple de page web utilisée dans la démonstration précédente :
&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;
&amp;html*
 &amp;head*
  &amp;title*ARjs&amp;/title*
  &amp;script src=&quot;https://aframe.io/releases/0.8.0/aframe.min.js&quot;*&amp;/script*
  &amp;script src=&quot;https://rawgit.com/donmccurdy/aframe-extras/master/dist/aframe-extras.loaders.min.js&quot;*&amp;/script*
  &amp;script src=&quot;https://jeromeetienne.github.io/AR.js/aframe/build/aframe-ar.js&quot;*&amp;/script*
  &amp;script*
   /*AFRAME.registerComponent(&#39;cursor-listener&#39;, {
     init: function () {
    this.el.addEventListener(&#39;click&#39;, function (evt) {
      // alert(&#39;click&#39;);
    });
     }
   });
   // https://stackoverflow.com/questions/47032056/gltf-cursor-listener-click-event-in-a-frame
   AFRAME.registerComponent(&#39;raycaster-autorefresh&#39;, {
     init: function () {
    var el = this.el;
    this.el.addEventListener(&#39;model-loaded&#39;, function () {
      var cursorEl = el.querySelector(&#39;[raycaster]&#39;);
      cursorEl.components.raycaster.refreshObjects();
    });
     }
   });*/
  &amp;/script*
 &amp;/head*

 &amp;body style=&#39;margin : 0px; overflow: hidden;&#39;*
  &amp;a-scene arjs=&quot;debugUIEnabled: false;&quot;*
   &amp;a-assets*
    &amp;img id=&quot;full&quot; src=&quot;img/full.png&quot;/*
    &amp;img id=&quot;empty&quot; src=&quot;img/empty.png&quot;/*
    &amp;img id=&quot;medium&quot; src=&quot;img/medium.png&quot;/*
    &amp;img id=&quot;low&quot; src=&quot;img/low.png&quot;/*
    &amp;img id=&quot;recycle&quot; src=&quot;img/recycle.png&quot;/*
   &amp;/a-assets*
   &amp;!-- handle marker with hiro preset --*
   &amp;!--&amp;a-marker preset=&quot;hiro&quot;*--*
   &amp;a-marker-camera preset=&quot;custom&quot; type=&#39;pattern&#39; url=&#39;data/can-marker.patt&#39;*
    &amp;!--&amp;a-image id=&quot;levelIndicator&quot; src=&quot;#empty&quot;  width=&quot;3&quot; height=&quot;2&quot; position=&quot;-2 2 0&quot;*&amp;/a-image*--*
    &amp;a-text value=&quot;Fill level&quot; position=&quot;0 2.6 0&quot; width=&quot;10&quot; anchor=&quot;left&quot; color=&quot;#00BFFF&quot;*&amp;/a-text*
    &amp;a-text test-counter font=&quot;exo2bold&quot; id=&quot;fillLevel&quot; value=&quot;0 %&quot; position=&quot;0 2.1 0&quot; width=&quot;15&quot; anchor=&quot;left&quot; color=&quot;#00BFFF&quot;*&amp;/a-text*
    &amp;a-image src=&quot;#recycle&quot;  width=&quot;1&quot; height=&quot;1&quot; position=&quot;-1.5 -2 0&quot;*&amp;/a-image*
    &amp;a-text value=&quot;Next interv.&quot; position=&quot;-0.9 -1.6 0&quot; width=&quot;10&quot; anchor=&quot;left&quot; color=&quot;#00BFFF&quot;*&amp;/a-text*
    &amp;a-text id=&quot;date&quot; font=&quot;exo2bold&quot; value=&quot;01 Jan 2018&quot; position=&quot;-0.9 -2.4 0&quot; width=&quot;20&quot; anchor=&quot;left&quot; color=&quot;#00BFFF&quot;*&amp;/a-text*
    &amp;a-entity position=&quot;-1.5 2 0&quot;*
     &amp;a-entity id=&quot;threeDcan&quot; gltf-model=&quot;url(obj/trash.gltf);&quot; position=&quot;0 0 0&quot; cursor-listener*&amp;/a-entity*
     &amp;a-animation attribute=&quot;rotation&quot;
        dur=&quot;4000&quot;
        fill=&quot;forwards&quot;
        to=&quot;0 360 0&quot;
        repeat=&quot;indefinite&quot;*&amp;/a-animation*
     &amp;a-animation begin=&quot;click&quot; attribute=&quot;position&quot; to=&quot;-1 2 0&quot;
      easing=&quot;linear&quot; dur=&quot;50&quot; fill=&quot;backwards&quot; repeat=&quot;10&quot;*&amp;/a-animation*
    &amp;/a-entity*
   &amp;/a-marker-camera*
   &amp;!--&amp;a-camera*
    &amp;a-cursor*&amp;/a-cursor*
   &amp;/a-camera*--*
   &amp;a-entity light=&quot;type: ambient; color: #FFF; intensity: 5;&quot;*&amp;/a-entity*
  &amp;/a-scene*
  &amp;script*
   ...
   document.querySelector(&#39;a-scene&#39;).querySelector(&#39;#date&#39;).setAttribute(&#39;value&#39;, getDate(daysCount));
   ...
  &amp;/script*
 &amp;/body*
&amp;/html*
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
&lt;i&gt;PS : pour des raisons de compatibilité, j&#39;ai du remplacer dans cet extrait les &#39;&lt;&#39; par &#39;&amp;&#39; et &#39;&gt;&#39; par &#39;*&#39;.&lt;/i&gt;
&lt;/p&gt;
&lt;h3&gt;En détails&lt;/h3&gt;
&lt;p&gt;
Quelques précisions sur le fonctionnement de cette démonstration :
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Utilisation d&#39;un tag personnalisé&lt;/b&gt; : le tag basique Hiro (utilisé par défaut par AR.js pour reconnaître la scène) a été remplacé par un tag personnalisé, via la balise : &lt;code&gt;a-marker-camera preset=&quot;custom&quot; type=&#39;pattern&#39; url=&#39;&lt;b&gt;data/can-marker.patt&lt;/b&gt;&#39;&lt;/code&gt; et l&#39;outil en ligne &lt;a href=&quot;https://jeromeetienne.github.io/AR.js/three.js/examples/marker-training/examples/generator.html&quot;&gt;Marker Training&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Intégration de modèle 3D animé&lt;/b&gt; : pour permettre l&#39;intégration dans la scène d&#39;un modèle 3D animé, il est nécessaire de se procurer un modèle (au format GLTF, via &lt;a href=&quot;https://sketchfab.com/&quot;&gt;Sketchfab&lt;/a&gt; par ex) et d&#39;intégrer le script &lt;code&gt;aframe-extras.loaders.min.js&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Gestion de l&#39;éclairage&lt;/b&gt; : dès lors que vous ajoutez des modèles dans une scène, il faut commencer à jouer avec les lumières. Ici une lumière d&#39;ambiance général a été mise en place : &lt;code&gt;a-entity light=&quot;type: ambient; color: #FFF; intensity: 5;&quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Manipulation du DOM&lt;/b&gt; : c&#39;est ce qui constitue un des points fort du framework AR.js. Vous pouvez utiliser Javascript pour manipuler les éléments de la scène 3D de la même manière que le DOM 2D standard HTML!&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;
&lt;h3&gt;Connectivité&lt;/h3&gt;
&lt;p&gt;
Qui dit technos web, dit Javascript : il est donc possible d&#39;utiliser n&#39;importe quel code (par ex websockets) pour vous connecter à la source de données (la plateforme IoT) afin de récupérer toutes les données et créer des interactions avec la réalité augmentée!
&lt;/p&gt;
&lt;p&gt;
Enjoy!
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://developpef.blogspot.com/feeds/5463908468340834114/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1566084130752530982/5463908468340834114?isPopup=true' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/5463908468340834114'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/5463908468340834114'/><link rel='alternate' type='text/html' href='http://developpef.blogspot.com/2018/04/iot-et-interface-naturelle-2-realite.html' title='IoT et interface naturelle (2) : réalité augmentée'/><author><name>Paul-Emmanuel Faidherbe</name><uri>http://www.blogger.com/profile/14333816988154371906</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJF9OHIybxl9BZ8qHqpkX3CzEcAtPsFesbRt6NQNIAy_LD1arQRfxFXPo0Ur442M6LqY4ZNZk9gwTy474Fa_gayo5ukXRMAxwkMBRTFQqVkD2y1kMHdxc_W0lox-j_E8A6rlntimZ50JZwxmK-mM5egC_mdthRx5lUFhpt_H7obAZ-7w/s220/identite.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOFoAkkJ-jEJxKkc9qPIF5bgB70kBzojHHx_eaiNz4zuXhyUr6ag6VfgXseJQDmGdZHbtIoAcpKt23J7wac_9Xd9QBkdsLfiUKdEV3ADaej1MY_FQB1HRJ-gOu_CKdLT9TxEpuKZry5Js/s72-c/Screenshot_20180409-170203.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1566084130752530982.post-3779747674397636196</id><published>2017-12-12T08:35:00.000+01:00</published><updated>2017-12-12T08:35:34.996+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="android"/><category scheme="http://www.blogger.com/atom/ns#" term="assistant"/><category scheme="http://www.blogger.com/atom/ns#" term="chatbot"/><category scheme="http://www.blogger.com/atom/ns#" term="cumulocity"/><category scheme="http://www.blogger.com/atom/ns#" term="google"/><category scheme="http://www.blogger.com/atom/ns#" term="ia"/><category scheme="http://www.blogger.com/atom/ns#" term="iot"/><category scheme="http://www.blogger.com/atom/ns#" term="recast"/><title type='text'>IoT et interface naturelle</title><content type='html'>&lt;p&gt;
Créer des applications technologiques c&#39;est bien, mais les rendre accessibles de manière naturelle aux utilisateurs, c&#39;est mieux!
&lt;/p&gt;
&lt;p&gt;
Voici donc un exemple de comment mettre en place un cas d&#39;usage complet : un chatbot (&quot;robot conversationnel&quot; !) vocal capable de récupérer les données émises par des objets.
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiH0ghx4_7FfblljFni4G-ufJZtisV3wzIi9QO8QWlRM9PfO8_9BXbCtBcUPPfag7_Wnz-asng8UYdCeehuQi0qbp-16rFEGTZ7Gwxt6WHEyzBncgdDvPfgBIGEio5CddtLgKtSh2NABDo/s1600/blogchat.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;chatbot iot cumulocity ai&quot; border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiH0ghx4_7FfblljFni4G-ufJZtisV3wzIi9QO8QWlRM9PfO8_9BXbCtBcUPPfag7_Wnz-asng8UYdCeehuQi0qbp-16rFEGTZ7Gwxt6WHEyzBncgdDvPfgBIGEio5CddtLgKtSh2NABDo/s1600/blogchat.jpg&quot; data-original-width=&quot;960&quot; data-original-height=&quot;720&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h3&gt;Scénario fonctionnel&lt;/h3&gt;
&lt;p&gt;
&lt;ul&gt;
&lt;li&gt;Un utilisateur pose une question à l&#39;assistant vocal Google&lt;/li&gt;
&lt;li&gt;Une fois interprétée, la version textuelle est transmise à un chatbot&lt;/li&gt;
&lt;li&gt;Le chatbot comprend l&#39;action à déclencher à partir de mots-clés&lt;/li&gt;
&lt;li&gt;Une requête est envoyée vers la plateforme IoT pour récupérer les données&lt;/li&gt;
&lt;li&gt;Le chatbot répond à l&#39;utilisateur de manière naturelle en incluant une visualisation pertinente des données&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;
&lt;h3&gt;Mise en place&lt;/h3&gt;
&lt;p&gt;
Concrètement, ce genre de solution peut être mis en place à l&#39;aide d&#39;outils simples enchainés les uns aux autres. Pour la partie vocale, l&#39;assistant de Google pour smartphone fait très bien le travail de reconnaissance. Le chatbot ainsi que son intelligence artificielle apportés par le service &lt;a href=&quot;https://recast.ai&quot;&gt;Recast.ai&lt;/a&gt; permettent d&#39;apporter une fluidité très appréciée dans l&#39;interaction homme-machine. &lt;b&gt;Son atout principal repose sur le fait qu&#39;il permet d&#39;étendre un robot pré-entrainé, par exemple à faire la conversation, pour lui ajouter des compétences spécifiques à notre besoin.&lt;/b&gt; Cela garanti que même lorsque votre robot ne sera pas en mesure de reconnaitre une action correspondant à votre scénario, il répondra de manière naturelle en mode conversation.
&lt;/p&gt;
&lt;p&gt;
L&#39;autre grand intérêt de la solution Recast.ai est qu&#39;elle est très orientée vers les développeurs, et fourni donc &lt;b&gt;plusieurs types d&#39;interfaces pour activer son robot selon les besoins&lt;/b&gt; : via des &quot;BotConnector&quot; vers les applications de messageries les plus répandues (Facebook, Slack, Tweeter, Skype...) mais également via une interface REST. Et la customisation du robot passe par l&#39;écriture de code Javascript/NodeJS, hébergé par Recast.ai eux-mêmes.
&lt;/p&gt;
&lt;p&gt;
Pour démarrer rapidement la mise en place de votre bot, vous pouvez suivre &lt;a href=&quot;https://recast.ai/blog/master-bot-hosting/&quot;&gt;cette documentation&lt;/a&gt;, expliquant de A à Z toutes les étapes.
&lt;/p&gt;
&lt;h3&gt;Retour d&#39;expérience&lt;/h3&gt;
&lt;p&gt;
Pour vous faciliter la tâche, voici quelques astuces afin d&#39;optimiser l&#39;élaboration de votre bot. Cet exemple s&#39;appui sur les extraits de code issus de la documentation citée précédemment. Le code du bot ressemble donc à cela :
&lt;/p&gt;
&lt;div style=&quot;overflow:auto&quot;&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;
const recastai = require(&#39;recastai&#39;).default;
const client = new recastai(process.env.REQUEST_TOKEN);
const request = require(&#39;request&#39;);
const axios = require(&#39;axios&#39;);

export const bot = (body, response, callback) =&gt; {
    console.log(body);

// response, the response object from the server in case of a local run
// callback, the object called in case of a bot hosting run

    if (body.message) {
        // pour gérer les appels par BotConnector (Slack...)
        client.connect.handleMessage({body}, response, replyMessage);
    } else if (body.text) {
        // pour gérer les appels par API REST en direct
        replyMessage(null, body.text, callback);
    } else {
        callback(&#39;Requete vide?!&#39;);
    }
};

function replyMessage(message, textMessage, callback) {
    if (message) {
        console.log(&quot;handling BotConnector message&quot;);
    } else {
        console.log(&quot;handling API message&quot;);
    }
    const recastaiReq = new recastai.request(process.env.REQUEST_TOKEN, process.env.LANGUAGE);
    const contentMessage = message ? message.content : textMessage;
    recastaiReq.analyseText(contentMessage)
            .then(recastaiRes =&gt; {
    var varcontent = &quot;&quot;;
                // get the intent detected
                var intent = recastaiRes.intent();
                if (intent) {
                    console.log(&quot;intent:&quot; + intent.slug + &quot;/&quot; + intent.confidence);
                    if (intent.slug === &#39;c8y_geoloc&#39; &amp;&amp; intent.confidence &gt; 0.7) {
                        if (recastaiRes.get(&#39;asset-type&#39;) &amp;&amp; recastaiRes.get(&#39;number&#39;)) {
                            // type d&#39;objet recherché (par ex &#39;caisse&#39;)
                            var asset = recastaiRes.get(&#39;asset-type&#39;).raw;
                            // id de l&#39;objet
                            var number = recastaiRes.get(&#39;number&#39;).raw;

                            axios.get(&#39;&lt;requete vers plateforme IOT&gt;&#39;,
                                    {
                                        headers: {&quot;Authorization&quot;: &quot;Basic ...&quot;} 
                                    })
                                    .then(response =&gt; {
                                        var body = response.data;

                                        if (body.managedObject) {
                                            //... do stuff
                                            return message ? message.reply([{type: &#39;text&#39;, content: varcontent}]).then() :
                                                   callback(null, {result: varcontent, intent: intent.slug, data: dataResp});
                                        } else {
                                            varcontent = &#39;Je n\&#39;ai rien trouvé!&#39;;
                                            return message ? message.reply([{type: &#39;text&#39;, content: varcontent}]).then() :
                                                    callback(null, {result: varcontent, intent: intent.slug});
                                        }
                                    })
                                    .catch(error =&gt; {
                                        varcontent = &#39;Il y a eu un problème...&#39;;
                                        return message ? message.reply([{type: &#39;text&#39;, content: varcontent + error}]) :
                                                callback(error, null);
                                    });
                        } else {
                            varcontent = &#39;Je ne sais pas quoi chercher...&#39;;
                            return message ? message.reply([{type: &#39;text&#39;, content: varcontent}]).then() :
                                    callback(null, {result: varcontent, intent: intent.slug});
                        }
                    } else {
                        // on fait appel au moteur de conversation, pour conserver l&#39;intelligence par defaut du bot
                        const converseReq = new recastai.request(process.env.REQUEST_TOKEN, process.env.LANGUAGE);

                        return converseReq.converseText(contentMessage)
                                .then(function (res2) {
                                    // ...extract the reply...
                                    varcontent = res2.reply();

                                    return message ? message.reply([{type: &#39;text&#39;, content: varcontent}]).then() :
                                            callback(null, {result: varcontent, intent: &#39;null&#39;});
                                })
                                .catch(err =&gt; {
                                    console.error(&#39;Something went wrong&#39;, err);
                                    return message ? message.reply([{type: &#39;text&#39;, content: &#39;Something went wrong&#39; + err}]) :
                                            callback(err, null);
                                });
                    }
                } else {
                    return message ? message.reply([{type: &#39;text&#39;, content: varcontent}]) :
                            callback(null, {result: varcontent, intent: &#39;null&#39;});
                }
            })
            .catch(err =&gt; {
                console.error(&#39;Something went wrong&#39;, err);
                return message ? message.reply([{type: &#39;text&#39;, content: &#39;Something went wrong&#39; + err}]) :
                        callback(err, null);
            });
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4&gt;Gestion des exceptions&lt;/h4&gt;
&lt;p&gt;
Il est primordial que toutes les éventuelles exceptions soient correctement gérées afin que dans tous les cas, une réponse soit renvoyée, même s&#39;il s&#39;agit d&#39;un message d&#39;erreur (plus ou moins &quot;naturel&quot; ;), sans quoi la requête HTTP qui a appelée votre bot restera bloquée en attente d&#39;une réponse...
&lt;/p&gt;
&lt;h4&gt;Exploiter au mieux l&#39;API Message&lt;/h4&gt;
&lt;p&gt;
La plateforme Recast.ai met à disposition une API très utile permettant de créer automatiquement une réponse à un message issu d&#39;une conversation via une messagerie instantanée (Tweeter, Slack...) tout en préservant les notions de conversation, réponse à un utilisateur spécifique, contexte du message etc, tout ceci de manière transparente via l&#39;utilisation de la méthode &lt;code&gt;message.reply()&lt;/code&gt;. Ainsi, quelle que soit l&#39;origine du message ou sa forme, votre contenu sera toujours correctement interprété par la plateforme cible.
&lt;/p&gt;
&lt;p&gt;
Vous avez maintenant tout ce qu&#39;il faut pour mettre en place une interface naturelle dans votre projet!
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://developpef.blogspot.com/feeds/3779747674397636196/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1566084130752530982/3779747674397636196?isPopup=true' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/3779747674397636196'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/3779747674397636196'/><link rel='alternate' type='text/html' href='http://developpef.blogspot.com/2017/12/iot-et-interface-naturelle.html' title='IoT et interface naturelle'/><author><name>Paul-Emmanuel Faidherbe</name><uri>http://www.blogger.com/profile/14333816988154371906</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJF9OHIybxl9BZ8qHqpkX3CzEcAtPsFesbRt6NQNIAy_LD1arQRfxFXPo0Ur442M6LqY4ZNZk9gwTy474Fa_gayo5ukXRMAxwkMBRTFQqVkD2y1kMHdxc_W0lox-j_E8A6rlntimZ50JZwxmK-mM5egC_mdthRx5lUFhpt_H7obAZ-7w/s220/identite.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiH0ghx4_7FfblljFni4G-ufJZtisV3wzIi9QO8QWlRM9PfO8_9BXbCtBcUPPfag7_Wnz-asng8UYdCeehuQi0qbp-16rFEGTZ7Gwxt6WHEyzBncgdDvPfgBIGEio5CddtLgKtSh2NABDo/s72-c/blogchat.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1566084130752530982.post-5890575825361134987</id><published>2017-12-11T15:37:00.001+01:00</published><updated>2017-12-11T15:37:58.601+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="cumulocity"/><category scheme="http://www.blogger.com/atom/ns#" term="iiot"/><category scheme="http://www.blogger.com/atom/ns#" term="opcua"/><title type='text'>Connecter une machine industrielle à Cumulocity</title><content type='html'>&lt;p&gt;
Il est clair aujourd&#39;hui que c&#39;est l&#39;Industrie qui va drainer le plus de marché (et d&#39;innovation) dans le domaine de l&#39;internet des objets. Pour s&#39;inscrire dans cette mouvance, nous allons voir comment il est possible de connecter une machine industrielle à la plateforme IoT Cumulocity.
&lt;/p&gt;
&lt;h3&gt;Le protocole OPC/UA&lt;/h3&gt;
&lt;p&gt;
Il s&#39;agit d&#39;une extension du protocole OPC, standard de l&#39;industrie permettant la communication entre machines, qui vise à simplifier leur intégration et leur utilisation en apportant notamment de la flexibilité, de la sécurité et de l&#39;indépendance vis-à-vis des fabricants.
&lt;/p&gt;
&lt;p&gt;
Rapide point d&#39;architecture : avec OPC/UA, chaque machine est reliée à un serveur (souvent 1 machine = 1 serveur, installé en local). Ensuite, une passerelle permet d&#39;interroger les données des serveurs ou envoyer des opérations :
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_iVtHt8hExSHcsIOfaSvjVPve8WIYpcyHvr6xfd5ykKt-0AEsdn9PbfcZNS8MGEXO4F2A2CBdsIqGSZdXUtDiJZi1NSeK4pD8yFrz5NtWXoX1cUx8TeQKw9749LiNcipFxlJFbo2Yq0A/s1600/scada_control_room_case_1_700px.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_iVtHt8hExSHcsIOfaSvjVPve8WIYpcyHvr6xfd5ykKt-0AEsdn9PbfcZNS8MGEXO4F2A2CBdsIqGSZdXUtDiJZi1NSeK4pD8yFrz5NtWXoX1cUx8TeQKw9749LiNcipFxlJFbo2Yq0A/s1600/scada_control_room_case_1_700px.png&quot; data-original-width=&quot;700&quot; data-original-height=&quot;326&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;&lt;center&gt;source : https://ewon.biz/opc-ua-server&lt;/center&gt;&lt;/p&gt;
&lt;h4&gt;Serveurs de démo&lt;/h4&gt;
&lt;p&gt;
Pour tester les fonctionnalités d&#39;OPC/UA, il est possible d&#39;utiliser un serveur public, comme par ex ceux &lt;a href=&quot;http://www.opclabs.com/resources/product-information/articles/1094-public-demo-opc-xml-da-server-2&quot;&gt;d&#39;OPCLabs&lt;/a&gt;, ou d&#39;installer son propre serveur local, comme ceux fournis par &lt;a href=&quot;https://www.unified-automation.com/downloads/opc-ua-servers.html&quot;&gt;Unified Automation&lt;/a&gt;.
&lt;/p&gt;
&lt;h4&gt;Client&lt;/h4&gt;
&lt;p&gt;
Le client le plus pratique à utiliser pour des premiers tests est UaExpert d&#39;OPCLabs &lt;a href=&quot;https://www.unified-automation.com/downloads/opc-ua-clients.html&quot;&gt;téléchargeable ici&lt;/a&gt;. C&#39;est lui que nous utiliserons pour notre démonstration.
&lt;/p&gt;
&lt;h3&gt;Premier cas d&#39;usage&lt;/h3&gt;
&lt;h4&gt;Description&lt;/h4&gt;
&lt;p&gt;
Pour les besoins de cet article, nous allons nous appuyer sur les données de démo contenues dans le serveur présenté plus haut, représentant une chaudière (boiler), simulée donc par le serveur. &lt;b&gt;L&#39;idée principale est qu&#39;une nouvelle donnée et un nouvel évènement soient générés côté Cumulocity chaque fois que la température de notre chaudière change.&lt;/b&gt; Voici l&#39;architecture mise en place pour créer le lien jusqu&#39;à Cumulocity :
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3vu1_igo15mlVio3OtQGhJMncHp-tNeOey7UrFNy3rVatYS6KHXQJGl8OtKX7-0Bn9BlAoWhKGw2bI7it8G3cEwusSzvrPguGaw7pmMvUEJbW4x2PUhJJbzEoJpxtqVoGt4_Z_XoNVxE/s1600/opc8y.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3vu1_igo15mlVio3OtQGhJMncHp-tNeOey7UrFNy3rVatYS6KHXQJGl8OtKX7-0Bn9BlAoWhKGw2bI7it8G3cEwusSzvrPguGaw7pmMvUEJbW4x2PUhJJbzEoJpxtqVoGt4_Z_XoNVxE/s1600/opc8y.png&quot; data-original-width=&quot;960&quot; data-original-height=&quot;720&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;
Le lien vers la plateforme est réalisé par un Agent (fourni par Cumulocity) déployé sur la passerelle. Pour le récupérer et le configurer, il suffit de suivre la &lt;a href=&quot;https://www.cumulocity.com/guides/devices/opcua/&quot;&gt;documentation ici&lt;/a&gt;.
&lt;/p&gt;
&lt;h4&gt;Configuration des Devices&lt;/h4&gt;
&lt;p&gt;
Voici à quoi ressemble la configuration dans Cumulocity du Device correspondant à notre passerelle :
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxBII2dygxbsHy4OPGaHBK1xofA9NACFK1B6Yjcn-2KWaAA66P6L_4_zQg603uwDrg2mALFzyQXFXUWK5gK1_e8D42W9b4zxdtEmqgXPBpIMLgvrtn4knDne3n-1ARxAkzm3rB2Nx7EU8/s1600/C8YGateway.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxBII2dygxbsHy4OPGaHBK1xofA9NACFK1B6Yjcn-2KWaAA66P6L_4_zQg603uwDrg2mALFzyQXFXUWK5gK1_e8D42W9b4zxdtEmqgXPBpIMLgvrtn4knDne3n-1ARxAkzm3rB2Nx7EU8/s1600/C8YGateway.PNG&quot; data-original-width=&quot;1525&quot; data-original-height=&quot;599&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;
Comme vous pouvez le voir, il est lié à un autre Device, représentant le capteur de température. Voici sa configuration :
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFh9eWZF1P3KCzo4ogJLAIbctr0-0fPqHvK44VOp13BpWJjxucHnADl1D5UiJv8gXTDrtKYQMh2R-M0AoQyhK4hk0xPTFDjZ3qIgqz4m-xYliKKVby6kD8j6-_DIjFA3PtTdyVuq5aIwk/s1600/C8YTemp.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFh9eWZF1P3KCzo4ogJLAIbctr0-0fPqHvK44VOp13BpWJjxucHnADl1D5UiJv8gXTDrtKYQMh2R-M0AoQyhK4hk0xPTFDjZ3qIgqz4m-xYliKKVby6kD8j6-_DIjFA3PtTdyVuq5aIwk/s1600/C8YTemp.PNG&quot; data-original-width=&quot;1314&quot; data-original-height=&quot;962&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;
Comme vous le constatez, nous avons configuré ce Device pour émettre un Measurement et un Event à chaque changement de valeur. Nous aurions pu également lui dire de lever une Alarme. On retrouve également à chaque fois le &quot;Browse Path&quot; qui permet de naviguer (à la mode OPC/UA) jusqu&#39;à la valeur à surveiller. Cette information peut se trouver grâce au client UaExpert, dans la vue Attributes, sous le nom de BrowseName :
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFSjeMZpzs3pYh9uTOL4UB0JembivwHA4BWklBO7bpQ1QK0xOBZ1RrtgFfbeMHYJF5bf2xjSdzxALCkb0zF1wV13autBEM9MTl7dpH_wbisRSw7nAxyxl5n7D-lifi6Iw5uDRdmnKPKqs/s1600/uabrowse.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFSjeMZpzs3pYh9uTOL4UB0JembivwHA4BWklBO7bpQ1QK0xOBZ1RrtgFfbeMHYJF5bf2xjSdzxALCkb0zF1wV13autBEM9MTl7dpH_wbisRSw7nAxyxl5n7D-lifi6Iw5uDRdmnKPKqs/s1600/uabrowse.PNG&quot; data-original-width=&quot;1300&quot; data-original-height=&quot;698&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h3&gt;Testons!&lt;/h3&gt;
&lt;p&gt;
Maintenant que tout est configuré, il ne nous reste plus qu&#39;à tester! Pour cela, il faut tout d&#39;abord démarrer l&#39;Agent Cumulocity (voir doc). Si tout a bien été préparé, il n&#39;y aura pas d&#39;erreur dans la console ni d&#39;Alarme levée sur la plateforme.
&lt;/p&gt;
&lt;p&gt;
Nous pouvons maintenant, à l&#39;aide d&#39;UaExpert, simuler un changement de température dans notre chaudière via l&#39;appel à la méthode dédiée &quot;Heat&quot; :
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHJ1FsxoFkfUzE9ntxrSs3ZeuepskzFspYsaDs58MvkEx3EnD7oEeIquY6MakWehyaY44qLcLKEudERzVViOFaWai_i3zPDiNE2m4NHECTzxUF8GzmoWM0pNaaUoHtEUKhgLHPDSNs0bo/s1600/opc8y_call.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHJ1FsxoFkfUzE9ntxrSs3ZeuepskzFspYsaDs58MvkEx3EnD7oEeIquY6MakWehyaY44qLcLKEudERzVViOFaWai_i3zPDiNE2m4NHECTzxUF8GzmoWM0pNaaUoHtEUKhgLHPDSNs0bo/s1600/opc8y_call.png&quot; data-original-width=&quot;960&quot; data-original-height=&quot;720&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;
Une fois la méthode invoquée, nous verrons apparaitre dans Cumulocity nos valeurs de température ainsi que nos évènements :
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6IvHXXKc0H4jyrK9UCCBJUonfxl93KVKVOedQls4KFVRETbBfz9g2cIGu03NG-_kSA0Ue_HETMbzTS5cfugLr-DFyQagQM3RgmD48uMxuinhlyuEjJFpDnWkH8UBvkixEjKIs9vow_us/s1600/opc8y_call_c8y.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6IvHXXKc0H4jyrK9UCCBJUonfxl93KVKVOedQls4KFVRETbBfz9g2cIGu03NG-_kSA0Ue_HETMbzTS5cfugLr-DFyQagQM3RgmD48uMxuinhlyuEjJFpDnWkH8UBvkixEjKIs9vow_us/s1600/opc8y_call_c8y.png&quot; data-original-width=&quot;1511&quot; data-original-height=&quot;1313&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;
Hope this helps!
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://developpef.blogspot.com/feeds/5890575825361134987/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1566084130752530982/5890575825361134987?isPopup=true' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/5890575825361134987'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/5890575825361134987'/><link rel='alternate' type='text/html' href='http://developpef.blogspot.com/2017/12/connecter-une-machine-industrielle.html' title='Connecter une machine industrielle à Cumulocity'/><author><name>Paul-Emmanuel Faidherbe</name><uri>http://www.blogger.com/profile/14333816988154371906</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJF9OHIybxl9BZ8qHqpkX3CzEcAtPsFesbRt6NQNIAy_LD1arQRfxFXPo0Ur442M6LqY4ZNZk9gwTy474Fa_gayo5ukXRMAxwkMBRTFQqVkD2y1kMHdxc_W0lox-j_E8A6rlntimZ50JZwxmK-mM5egC_mdthRx5lUFhpt_H7obAZ-7w/s220/identite.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_iVtHt8hExSHcsIOfaSvjVPve8WIYpcyHvr6xfd5ykKt-0AEsdn9PbfcZNS8MGEXO4F2A2CBdsIqGSZdXUtDiJZi1NSeK4pD8yFrz5NtWXoX1cUx8TeQKw9749LiNcipFxlJFbo2Yq0A/s72-c/scada_control_room_case_1_700px.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1566084130752530982.post-7429497334985619849</id><published>2017-11-28T09:20:00.000+01:00</published><updated>2017-11-28T09:20:55.040+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="cumulocity"/><category scheme="http://www.blogger.com/atom/ns#" term="iot"/><category scheme="http://www.blogger.com/atom/ns#" term="sigfox"/><title type='text'>Interpréter des messages Sigfox avec Cumulocity</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1zotKjAXIfSw_r3SGn7AQtZuNIkepwVT_vSuH_hXvXvgYljXVie1YVvlgSzcv2yKfzGPBfWopjR-aO3Aaq5oi9QtUt0VffYEuqT1rtBdEUTp9aPgLzitfFcy1KS4r4zZym9NzYJgjhGQ/s1600/Sigfox2C8Y.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1zotKjAXIfSw_r3SGn7AQtZuNIkepwVT_vSuH_hXvXvgYljXVie1YVvlgSzcv2yKfzGPBfWopjR-aO3Aaq5oi9QtUt0VffYEuqT1rtBdEUTp9aPgLzitfFcy1KS4r4zZym9NzYJgjhGQ/s1600/Sigfox2C8Y.PNG&quot; data-original-width=&quot;1146&quot; data-original-height=&quot;409&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;
Sigfox propose, depuis son &quot;backend&quot;, de configurer une adresse de callback où seront transférés tous les messages émis par les objets :
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKul8H4CpYX-cFHmz3JyNUS05d20D_gClKDbQnQCOBiEKm5YdAvBnylDbI8EF4RRo_xxPAY_wLFZMQC_BJ08UjXD5DSx3FgeBYzCoCYqZKSuVrAC3EmflJGkxd0qcBevYdJsheRd2-DUE/s1600/sigfoxCallback.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKul8H4CpYX-cFHmz3JyNUS05d20D_gClKDbQnQCOBiEKm5YdAvBnylDbI8EF4RRo_xxPAY_wLFZMQC_BJ08UjXD5DSx3FgeBYzCoCYqZKSuVrAC3EmflJGkxd0qcBevYdJsheRd2-DUE/s400/sigfoxCallback.png&quot; width=&quot;400&quot; height=&quot;309&quot; data-original-width=&quot;1218&quot; data-original-height=&quot;942&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;
De son côté, Cumulocity dispose nativement d&#39;une brique technique (appelée Agent), capable de recevoir un message issu du réseau Sigfox et de l&#39;interpréter, pour par exemple créer automatiquement un Device s&#39;il n&#39;existe pas dans l&#39;Inventaire, lui rattacher de nouveaux messages, ou transformer les erreurs (au sens Sigfox, via la configuration de callback d&#39;erreur) en Alarmes. Il est également possible d&#39;envoyer des commandes vers l&#39;objet via l&#39;interface de Cumulocity.
&lt;/p&gt;
&lt;p&gt;Leur documentation pour la configuration de l&#39;Agent étant très claire et précise, je vous laisse la parcourir de vous-mêmes : &lt;a href=&quot;https://www.cumulocity.com/guides/devices/sigfox/&quot;&gt;Configuring SIGFOX devices for Cumulocity&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;
Une fois tout cela mis en place, les messages reçus du réseau Sigfox apparaissent en tant qu&#39;Evènements rattachés au Device dans Cumulocity, dont le contenu correspond à la structure JSON configurée dans le callback Sigfox :
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidUNpn7dy4tayVns6Xnmk3NYylopjIQVGscS4n9XmzyufpNDuYYrOeKGO6uXfkG0YSzkSM4vxEyuCeeShUI-WxDQ862xutIF34qmMJmHqqWCCArjlidyN_kfhGMORN7414kVrFxyFNikg/s1600/C8YEvent.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidUNpn7dy4tayVns6Xnmk3NYylopjIQVGscS4n9XmzyufpNDuYYrOeKGO6uXfkG0YSzkSM4vxEyuCeeShUI-WxDQ862xutIF34qmMJmHqqWCCArjlidyN_kfhGMORN7414kVrFxyFNikg/s400/C8YEvent.png&quot; width=&quot;400&quot; height=&quot;180&quot; data-original-width=&quot;1600&quot; data-original-height=&quot;720&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;
Comme vous pouvez le constater, l&#39;évènement contient une propriété &quot;data&quot; qui porte les données brutes présentes dans le message Sigfox. Il faudrait maintenant pouvoir interpréter à la volée cette information pour récupérer les valeurs que nous avons stockées dans notre message, puis créer automatiquement des vrais Relevés de données (Measurements). Ceci dans le but, par exemple, de faciliter l&#39;intégration avec des applications clientes qui seraient à l&#39;écoute de données en temps réel issues de capteurs ou permettre l&#39;exécution des moteurs de règles de Cumulocity pour déclencher des alarmes en fonction des valeurs reçues.
&lt;/p&gt;
&lt;p&gt;
Pour ce faire, nous allons utiliser le moteur de traitement d&#39;évènements complexes &lt;a href=&quot;https://www.cumulocity.com/guides/concepts/realtime/&quot;&gt;fourni par Cumulocity&lt;/a&gt; (&lt;a href=&quot;https://blog.octo.com/complex-event-processing-avec-esper/&quot;&gt;Complex Event Processing&lt;/a&gt;).
&lt;/p&gt;
&lt;p&gt;
Ainsi, dès la réception d&#39;un message, nous allons parcourir le contenu de &quot;data&quot; et extraire les informations issues de nos capteurs :
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8u0GQ80UpCHgz36xuBtHDRq7B5ZsD7BYhav2i1eK7vPYUEUkzp6ymidZQ1JjJau5vAZCRKDeVhgR51hYPh3W4iXrmgtzz6p7hLSU2k6Hc11OZ3uT5aLOsq1voh1S6wPEReUVzpLEnIyo/s1600/C8YCEP.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8u0GQ80UpCHgz36xuBtHDRq7B5ZsD7BYhav2i1eK7vPYUEUkzp6ymidZQ1JjJau5vAZCRKDeVhgR51hYPh3W4iXrmgtzz6p7hLSU2k6Hc11OZ3uT5aLOsq1voh1S6wPEReUVzpLEnIyo/s640/C8YCEP.png&quot; width=&quot;640&quot; height=&quot;324&quot; data-original-width=&quot;1600&quot; data-original-height=&quot;811&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;
Quelques explications :
&lt;/p&gt;
&lt;p&gt;
Avec le langage fourni par Cumulocity (Complex Event Language), nous sélectionnons tous les évènements en temps réel issus de l&#39;Agent Sigfox :
&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;
select * from EventCreated event where getObject(event, &quot;com_sigfox_SigFoxData&quot;) is not null;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
Puis pour chacun nous créons notre propre structure de données que nous insérons en tant que Relevé (Measurement) :
&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;
insert into CreateMeasurement select ...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
Le concept de Fragment dans Cumulocity nous permet de recréer une structure JSON composée de plusieurs valeurs. Vous pouvez voir le résultat à la réception d&#39;un message à droite de la capture d&#39;écran, ainsi que dans le dashboard du Device :
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiy5ys-fdslEazFnNLE1bdGxmnzhn0srMHuwDwb2sJT3KvD_APzA2KLHkquESreX1qoxCw2hNRPXucR-NTwXH7VwtsVFf0okZHMdyI7FJHdQe_X6NM_ieBAk4vj6nJwUIte1f348ZDioZI/s1600/C8YSigfoxDevice.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiy5ys-fdslEazFnNLE1bdGxmnzhn0srMHuwDwb2sJT3KvD_APzA2KLHkquESreX1qoxCw2hNRPXucR-NTwXH7VwtsVFf0okZHMdyI7FJHdQe_X6NM_ieBAk4vj6nJwUIte1f348ZDioZI/s640/C8YSigfoxDevice.png&quot; width=&quot;640&quot; height=&quot;324&quot; data-original-width=&quot;1600&quot; data-original-height=&quot;811&quot; /&gt;&lt;/a&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://developpef.blogspot.com/feeds/7429497334985619849/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1566084130752530982/7429497334985619849?isPopup=true' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/7429497334985619849'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/7429497334985619849'/><link rel='alternate' type='text/html' href='http://developpef.blogspot.com/2017/11/interpreter-des-messages-sigfox-avec.html' title='Interpréter des messages Sigfox avec Cumulocity'/><author><name>Paul-Emmanuel Faidherbe</name><uri>http://www.blogger.com/profile/14333816988154371906</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJF9OHIybxl9BZ8qHqpkX3CzEcAtPsFesbRt6NQNIAy_LD1arQRfxFXPo0Ur442M6LqY4ZNZk9gwTy474Fa_gayo5ukXRMAxwkMBRTFQqVkD2y1kMHdxc_W0lox-j_E8A6rlntimZ50JZwxmK-mM5egC_mdthRx5lUFhpt_H7obAZ-7w/s220/identite.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1zotKjAXIfSw_r3SGn7AQtZuNIkepwVT_vSuH_hXvXvgYljXVie1YVvlgSzcv2yKfzGPBfWopjR-aO3Aaq5oi9QtUt0VffYEuqT1rtBdEUTp9aPgLzitfFcy1KS4r4zZym9NzYJgjhGQ/s72-c/Sigfox2C8Y.PNG" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1566084130752530982.post-6046692275476636922</id><published>2017-09-21T10:11:00.000+02:00</published><updated>2017-09-21T10:11:04.137+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="arduino"/><category scheme="http://www.blogger.com/atom/ns#" term="infrarouge"/><title type='text'>Arduino et infrarouge</title><content type='html'>&lt;p&gt;
Aujourd&#39;hui, un article rapide sous forme de mémo, pour mettre en place une communication série entre deux Arduinos en infrarouge. Ceci pour permettre de trouver rapidement le matériel et code nécessaires.
&lt;/p&gt;
&lt;p&gt;
Avant tout, il faut savoir que dès lors qu&#39;une communication série &lt;b&gt;filaire&lt;/b&gt; (USB par ex) a été mise en place, il suffit de &quot;remplacer&quot; le fil par une liaison optique infrarouge, puisque l&#39;encodage reste le même (&lt;a href=&quot;https://fr.wikipedia.org/wiki/UART&quot;&gt;UART&lt;/a&gt; pour de la communication série).
&lt;/p&gt;
&lt;h4&gt;Code et montage&lt;/h4&gt;
&lt;p&gt;
Puisqu&#39;il est inutile de réinventer la roue, voici un &lt;a href=&quot;http://www.zolalab.com.br/references/serial2ir.php&quot;&gt;très bon tutoriel de Zola lab&lt;/a&gt; expliquant quel montage et quel code utiliser pour mettre en place la liaison optique :
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;http://www.zolalab.com.br/references/serial2ir.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://www.zolalab.com.br/references/serial2ir.png&quot; width=&quot;640&quot; height=&quot;289&quot; data-original-width=&quot;800&quot; data-original-height=&quot;361&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h4&gt;Matériel&lt;/h4&gt;
&lt;p&gt;
Et pour se fournir le bon matériel pour réaliser ce montage, rendez-vous chez Lextronic :
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.lextronic.fr/P1743-photodiode-infrarouge-rceptrice-til81.html&quot;&gt;Photodiode infrarouge réceptrice &quot;TIL81&quot; 930nm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.lextronic.fr/P1747-diode-infrarouge-mettrice-35-l.html&quot;&gt;Diode infrarouge émettrice &quot;35-L&quot; 930nm&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Have fun!&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://developpef.blogspot.com/feeds/6046692275476636922/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1566084130752530982/6046692275476636922?isPopup=true' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/6046692275476636922'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/6046692275476636922'/><link rel='alternate' type='text/html' href='http://developpef.blogspot.com/2017/09/arduino-et-infrarouge.html' title='Arduino et infrarouge'/><author><name>Paul-Emmanuel Faidherbe</name><uri>http://www.blogger.com/profile/14333816988154371906</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJF9OHIybxl9BZ8qHqpkX3CzEcAtPsFesbRt6NQNIAy_LD1arQRfxFXPo0Ur442M6LqY4ZNZk9gwTy474Fa_gayo5ukXRMAxwkMBRTFQqVkD2y1kMHdxc_W0lox-j_E8A6rlntimZ50JZwxmK-mM5egC_mdthRx5lUFhpt_H7obAZ-7w/s220/identite.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1566084130752530982.post-520284372284673832</id><published>2017-09-20T09:00:00.000+02:00</published><updated>2017-09-20T09:03:42.383+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="api"/><category scheme="http://www.blogger.com/atom/ns#" term="jenkins"/><category scheme="http://www.blogger.com/atom/ns#" term="Newman"/><category scheme="http://www.blogger.com/atom/ns#" term="Postman"/><category scheme="http://www.blogger.com/atom/ns#" term="REST"/><category scheme="http://www.blogger.com/atom/ns#" term="Swagger"/><category scheme="http://www.blogger.com/atom/ns#" term="TDD"/><title type='text'>Tester une API REST avec Swagger, Postman et Jenkins</title><content type='html'>&lt;p&gt;
Avec &lt;a href=&quot;https://www.wired.com/insights/2013/07/without-api-management-the-internet-of-things-is-just-a-big-thing/&quot;&gt;l&#39;essor de l&#39;IoT vient l&#39;âge d&#39;or&lt;/a&gt; &lt;a href=&quot;http://www.apidays.io/&quot;&gt;des APIs&lt;/a&gt; (et de &lt;a href=&quot;https://medium.com/@AlexandraBowen/iot-is-eating-the-world-apis-and-rest-9e0321bc6cbf&quot;&gt;REST&lt;/a&gt;), pour ouvrir facilement et de &lt;a href=&quot;https://nordicapis.com/apis-power-the-internet-of-things/&quot;&gt;manière universelle&lt;/a&gt; des services.
&lt;/p&gt;
&lt;p&gt;
La gestion des APIs devient donc une affaire de pros et doit être de plus en plus rigoureuse. Nous allons voir comment maîtriser les évolutions d&#39;une API à partir d&#39;outils spécialisés.
&lt;/p&gt;
&lt;h3&gt;Les basiques&lt;/h3&gt;
&lt;p&gt;
Je pense qu&#39;il n&#39;est plus nécessaire de présenter Postman (extension Chrome pour tester une API) ni Jenkins (serveur d&#39;intégration continue). Mais il est intéressant de voir comment les deux peuvent travailler ensemble pour devenir une suite de tests automatisée d&#39;API, via l&#39;utilitaire en ligne de commande Newman et cette &lt;a href=&quot;https://www.getpostman.com/docs/postman/collection_runs/integration_with_jenkins&quot;&gt;très bonne documentation officielle&lt;/a&gt;.
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://www.getpostman.com/img/v1/docs/integrating_with_jenkins/integrating_with_jenkins_11.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://www.getpostman.com/img/v1/docs/integrating_with_jenkins/integrating_with_jenkins_11.png&quot; data-original-width=&quot;800&quot; data-original-height=&quot;418&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h3&gt;Swagger, la documentation simple et efficace!&lt;/h3&gt;
&lt;p&gt;
Le meilleur moyen de s&#39;assurer de la cohérence d&#39;une API reste une bonne documentation. Pour ce faire, il existe &lt;a href=&quot;https://swagger.io/&quot;&gt;Swagger&lt;/a&gt; (et sa version en ligne SwaggerHub) qui est l&#39;outil de référence en la matière. En effet, il est très simple d&#39;écrire rapidement une documentation pertinente, avec qui plus est une présentation agréable :
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBQDM7G-ImT-rmkKCB6eZf-MZrvFy-JJryUA6uf3GP6DL42Bn4qomm1qekNos7C-RMuImQTwW4q_sGaVFSGb_4XMHPT2_xhBidZZ-NQ52sE4bFCRRP_62ACYFXPZLwXzvJukd8eQs0JHM/s1600/swagger.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBQDM7G-ImT-rmkKCB6eZf-MZrvFy-JJryUA6uf3GP6DL42Bn4qomm1qekNos7C-RMuImQTwW4q_sGaVFSGb_4XMHPT2_xhBidZZ-NQ52sE4bFCRRP_62ACYFXPZLwXzvJukd8eQs0JHM/s640/swagger.PNG&quot; width=&quot;640&quot; height=&quot;338&quot; data-original-width=&quot;1600&quot; data-original-height=&quot;845&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h3&gt;Putting it all together&lt;/h3&gt;
&lt;p&gt;
Maintenant, voyons comment combiner tout cela. 
&lt;/p&gt;
&lt;p&gt;
Avec Swagger, vous avez la possibilité de définir, en plus de vos URLs, le formalisme des objets métier que vous manipulez. Pour cela il faut utiliser la section &quot;definitions&quot;. Par exemple :
&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;
paths:
...
definitions:
  Asset :
    type: object
    additionalProperties: false
    required: [&#39;name&#39;,&#39;owner&#39;,&#39;type&#39;]
    properties :
      name: 
        type: string
        description: Nom de l&#39;Asset.
      owner:
        type: string
        description: Propriétaire du Device (User / domaine métier)
      type:
        type: string
        description: Type de l&#39;objet
  Zone :
    type: object
    additionalProperties: false
    required: [&#39;name&#39;,&#39;geojson&#39;]
    properties :
      name: 
        type: string
        description: Nom de la Zone.
      geojson :
        type: object
        description: Géométrie au format GeoJSON
        properties:
          type:
            type: string
            description: Feature
          geometry:
            type: object
            properties:
              type:
                type: string
                description: Point
              coordinates:
                type: array
                description: tableau de points GPS
                items:
                  type: number
      country:
        type: string
        description: Pays de la Zone, issu du référentiel Country.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
Parallèlement, il est possible dans les tests Postman de &lt;a href=&quot;https://www.getpostman.com/docs/postman/scripts/test_examples&quot;&gt;vérifier que le contenu d&#39;une réponse correspond à un schéma particulier&lt;/a&gt; (via TinyValidator). Et surprise, le formalisme des &quot;schémas&quot; utilisés par Postman correspond parfaitement à celui de nos &quot;definitions&quot; Swagger! Cela vous donne des idées?? Alors allons-y!
&lt;/p&gt;
&lt;p&gt;
Tout d&#39;abord, nous allons récupérer notre définition Swagger en l&#39;exportant au format JSON pour pouvoir l&#39;utiliser avec Postman. Cependant, à l&#39;heure actuelle, il n&#39;est pas possible dans Postman de charger un fichier externe, autre qu&#39;un fichier de données de tests. Donc nous allons devoir faire un copié/collé de notre définition dans Postman. Mais pour essayer de faire cela proprement, nous allons coller notre Swagger dans une variable d&#39;environnement de Postman, afin qu&#39;elle soit accessible dans tous les tests :
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvwc1qdssu9iyWao8B_29NpnuBVKMDsWkMQOegl03PJR1s25KLHT5b3ETxviFTEm8XhPSj8nkpGIi0Y6cSetUg7Iuhl7711-keq_tYsbidfav0ffDFgxNHOZU_EJtGMdIHJ3wFmVJx3Ns/s1600/swaggerEnv.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvwc1qdssu9iyWao8B_29NpnuBVKMDsWkMQOegl03PJR1s25KLHT5b3ETxviFTEm8XhPSj8nkpGIi0Y6cSetUg7Iuhl7711-keq_tYsbidfav0ffDFgxNHOZU_EJtGMdIHJ3wFmVJx3Ns/s640/swaggerEnv.PNG&quot; width=&quot;640&quot; height=&quot;536&quot; data-original-width=&quot;1207&quot; data-original-height=&quot;1010&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;
Ensuite, nous allons écrire un test de vérification de schéma qui va se baser sur la définition d&#39;un de nos objets métier Swagger :
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjF1nUmQTcxhiJPiWyMvg2WdT7Sfod_g2-6cwqxTEfATPiMk-yXs0cRGTL7AzAguIajLh3y9vbnS48fcKzh8XBmwY3c1dKwM_uYr2eZWh6V9nMW5lAcjwywfASQ3Xz17rnVee-Y0BBmnL8/s1600/swaggerTest.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjF1nUmQTcxhiJPiWyMvg2WdT7Sfod_g2-6cwqxTEfATPiMk-yXs0cRGTL7AzAguIajLh3y9vbnS48fcKzh8XBmwY3c1dKwM_uYr2eZWh6V9nMW5lAcjwywfASQ3Xz17rnVee-Y0BBmnL8/s640/swaggerTest.PNG&quot; width=&quot;640&quot; height=&quot;436&quot; data-original-width=&quot;1504&quot; data-original-height=&quot;1025&quot; alt=&quot;var swaggerJson = JSON.parse(environment.Swagger);// test schema var jsonData = JSON.parse(responseBody);var schema = {type:array,items: swaggerJson.definitions.Asset};tests[Valid Data] = tv4.validate(jsonData, schema);if(tv4.error) {   console.log(tv4.error);}&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;
Comme vous le voyez, nous chargeons en JSON notre définition Swagger, puis définissons un schéma de type tableau d&#39;Assets, en récupérant la définition des Assets avec &lt;code&gt;swaggerJson.definitions.Asset&lt;/code&gt;. Et en plus c&#39;est facile!
&lt;/p&gt;
&lt;p&gt;
Maintenant, lors de l&#39;exécution de votre requête, les tests seront lancés et la réponse sera validée en fonction du schéma indiqué! &lt;strong&gt;Il est important à ce stade de disposer d&#39;une définition d&#39;objet stricte, notamment via l&#39;utilisation des propriétés Swagger &lt;code&gt;additionalProperties:false&lt;/code&gt; et &lt;code&gt;required: [&#39;name&#39;,&#39;owner&#39;,&#39;type&#39;]&lt;/code&gt;, sans quoi n&#39;importe quelle réponse passera la validation.&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
Vous pouvez même aller jusqu&#39;à utiliser votre définition Swagger pour récupérer les URLs à tester. Pour cela, il faut utiliser la partie &quot;Pre-request Script&quot; de Postman et parcourir de la même façon notre Swagger :
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYmD86H2zxcW1hlDTBth6HnuA5d9S-gKGzdf1SSMS60wdHySzeYUo21ysBPPCKrKjC_DG5JQhyphenhyphenXyDr9lxatwxDKP4saPZHHyD9IHF8G1N0Tzp7exAg0nUndAWwLTaO9_UtOlFwt4I7ynA/s1600/swaggerPreTest.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYmD86H2zxcW1hlDTBth6HnuA5d9S-gKGzdf1SSMS60wdHySzeYUo21ysBPPCKrKjC_DG5JQhyphenhyphenXyDr9lxatwxDKP4saPZHHyD9IHF8G1N0Tzp7exAg0nUndAWwLTaO9_UtOlFwt4I7ynA/s640/swaggerPreTest.PNG&quot; width=&quot;640&quot; height=&quot;344&quot; data-original-width=&quot;882&quot; data-original-height=&quot;474&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;
Ici, nous définissons une variable d&#39;environnement &#39;url&#39; à l&#39;aide des attributs &#39;host&#39; et &#39;basePath&#39; de Swagger. Cette variable est ensuite utilisée par Postman via la syntaxe &lt;code&gt;{{url}}&lt;/code&gt; dans sa barre d&#39;adresse.
&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Remarque :&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;
Il est également possible d&#39;importer directement la définition Swagger dans Postman (via le bouton Import) pour récupérer automatiquement toutes les URLs à tester. Cependant, si vous avez besoin de réimporter votre définition suite à des modifications, &lt;strong&gt;cela va écraser tout ce qui existe déjà, y compris les tests!&lt;/strong&gt;. 
&lt;/p&gt;
&lt;p&gt;
Pour terminer, il ne vous reste plus qu&#39;à mettre tout cela dans Jenkins, via l&#39;export de votre collection et de l&#39;environnement Postman que vous passerez en paramètres de Newman! Enjoy!
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://developpef.blogspot.com/feeds/520284372284673832/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1566084130752530982/520284372284673832?isPopup=true' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/520284372284673832'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/520284372284673832'/><link rel='alternate' type='text/html' href='http://developpef.blogspot.com/2017/09/tester-une-api-rest-avec-swagger.html' title='Tester une API REST avec Swagger, Postman et Jenkins'/><author><name>Paul-Emmanuel Faidherbe</name><uri>http://www.blogger.com/profile/14333816988154371906</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJF9OHIybxl9BZ8qHqpkX3CzEcAtPsFesbRt6NQNIAy_LD1arQRfxFXPo0Ur442M6LqY4ZNZk9gwTy474Fa_gayo5ukXRMAxwkMBRTFQqVkD2y1kMHdxc_W0lox-j_E8A6rlntimZ50JZwxmK-mM5egC_mdthRx5lUFhpt_H7obAZ-7w/s220/identite.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBQDM7G-ImT-rmkKCB6eZf-MZrvFy-JJryUA6uf3GP6DL42Bn4qomm1qekNos7C-RMuImQTwW4q_sGaVFSGb_4XMHPT2_xhBidZZ-NQ52sE4bFCRRP_62ACYFXPZLwXzvJukd8eQs0JHM/s72-c/swagger.PNG" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1566084130752530982.post-7877685684839774155</id><published>2017-09-13T08:44:00.002+02:00</published><updated>2017-09-14T14:24:50.007+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="cumulocity"/><category scheme="http://www.blogger.com/atom/ns#" term="industry"/><category scheme="http://www.blogger.com/atom/ns#" term="iot"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="websocket"/><title type='text'>Cumulocity : une plateforme IoT taillée pour l&#39;industrie</title><content type='html'>&lt;p&gt;
Désormais &lt;a href=&quot;https://www.forbes.com/sites/louiscolumbus/2016/11/27/roundup-of-internet-of-things-forecasts-and-market-estimates-2016/#49542a51292d&quot;&gt;c&#39;est un fait&lt;/a&gt;, c&#39;est bien l&#39;industrie qui va guider les prochaines évolutions majeures de l&#39;IoT, pousser l&#39;adoption de certaines normes et standardiser les principaux cas d&#39;usages.
&lt;p&gt;
&lt;p&gt;
Il est donc temps de commencer à prendre en main les plateformes spécialisées, délivrant des services professionnels : device management, intégration de protocoles, sécurité, mise à l&#39;échelle, analytics, multitenants...
&lt;/p&gt;
&lt;p&gt;
Pour cela, nous allons utiliser la plateforme &lt;a href=&quot;http://www2.softwareag.com/corporate/products/internet_of_things/default.aspx&quot;&gt;Cumulocity&lt;/a&gt;.
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOJ60f1JXZ7vqWlahoOIiuXxMjnxQ2ldeCd9hm_Se0xJJzU03TbApT0Dbh8R2LQO4SvLz1nH4-FnqkcQvLIveHYErzdL2V0Dcbo6_C8_RQV-8_oHEdXhmtaOxReW3ZIym3wU2aucUGOw0/s1600/C8Ylogo.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOJ60f1JXZ7vqWlahoOIiuXxMjnxQ2ldeCd9hm_Se0xJJzU03TbApT0Dbh8R2LQO4SvLz1nH4-FnqkcQvLIveHYErzdL2V0Dcbo6_C8_RQV-8_oHEdXhmtaOxReW3ZIym3wU2aucUGOw0/s1600/C8Ylogo.PNG&quot; data-original-width=&quot;789&quot; data-original-height=&quot;198&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;
Son nom ne vous dit peut-être rien, mais elle fait partie des leaders du marché, avec déjà de &lt;a href=&quot;http://cumulocity.com/reference-cases/&quot;&gt;belles références&lt;/a&gt;. Pour en avoir comparé bon nombre, je la place grande première de mon top 3 des plateformes, juste devant &lt;a href=&quot;https://www.ibm.com/internet-of-things/&quot;&gt;IBM Watson IoT&lt;/a&gt; et &lt;a href=&quot;https://thethings.io/&quot;&gt;theThings.io&lt;/a&gt; (je n&#39;oublie bien sûr pas &lt;a href=&quot;https://www.thingworx.com/&quot;&gt;Thingworx&lt;/a&gt; de PTC, mais elle est à mon sens beaucoup trop complexe à mettre en oeuvre, et reste difficile d&#39;accès aux néophytes du PLM...).
&lt;/p&gt;
&lt;h3&gt;Prise en main en 5 minutes&lt;/h3&gt;
&lt;p&gt;
Pour la tester, rien de plus simple, il suffit de créer un compte d&#39;essai gratuit, qui donne accès à la majeure partie des fonctionnalités pendant 1 mois. Ensuite, il est possible d&#39;ajouter par exemple un smartphone en tant que Device, via l&#39;appli Android spécifique. Vous aurez alors accès à un dashboard affichant en temps réel les données relevées par votre téléphone (gyroscope, accéléromètre, luxmètre...). 
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgs9COXHx3wJOyi5BoI4OfA19HKzUL04P3K4ppua8KuI2tbVSIVpDWTwV2MB-ClYkA_uDGS7QDo_XwwSvfJ0faxKF22P6gjESsZWQCjWVj9QUg3DKEYP8jOWY1YYKG4ujOdb1__hMw8r8/s1600/c8ydash.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgs9COXHx3wJOyi5BoI4OfA19HKzUL04P3K4ppua8KuI2tbVSIVpDWTwV2MB-ClYkA_uDGS7QDo_XwwSvfJ0faxKF22P6gjESsZWQCjWVj9QUg3DKEYP8jOWY1YYKG4ujOdb1__hMw8r8/s400/c8ydash.PNG&quot; width=&quot;400&quot; height=&quot;196&quot; data-original-width=&quot;1600&quot; data-original-height=&quot;785&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h3&gt;Explorer toute l&#39;API REST&lt;/h3&gt;
&lt;p&gt;
Puisqu&#39;une plateforme IoT n&#39;est rien sans une interface REST, il est assez simple d&#39;explorer toute l&#39;étendue des possibilités offertes par celle de Cumulocity. Pour cela, le plus pratique est d&#39;utiliser l&#39;extension Chrome Postman et récupérer la &lt;a href=&quot;https://www.cumulocity.com/guides/rest/introduction/&quot;&gt;librairie publiée par Cumulocity&lt;/a&gt;. Vous aurez ainsi sous la main toutes les requêtes prêtes à être utilisées pour envoyer des données, créer des Devices, déclencher des alarmes, pousser des Opérations...
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhaYqgvNV-czqFtJpEc9Hcv51ATdiW-mOYiwH-CzhYIebiJv_wCU3izj1KLoZXW-cggxjU00n5maiHzsvQt5zKkZuAciYovb-itMVP1by0hyphenhyphenIFDAsQy9M01jeXyaG62J7jaivosg8eS_8/s1600/c8ypostman.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhaYqgvNV-czqFtJpEc9Hcv51ATdiW-mOYiwH-CzhYIebiJv_wCU3izj1KLoZXW-cggxjU00n5maiHzsvQt5zKkZuAciYovb-itMVP1by0hyphenhyphenIFDAsQy9M01jeXyaG62J7jaivosg8eS_8/s400/c8ypostman.png&quot; width=&quot;400&quot; height=&quot;236&quot; data-original-width=&quot;1600&quot; data-original-height=&quot;944&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h3&gt;Premier cas concret&lt;/h3&gt;
&lt;p&gt;
Maintenant que nous avons fait les premiers tests de la plateforme, il est temps de créer un vrai cas d&#39;usage du monde réel. Voici le scénario envisagé :
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxrZzsTvcPBNpQLRd604CYpXH6VdoFplYFD3D8Z6bEV1bkcWaPxGE3GgMbhnCxBf00lU8RwmfEC8uouz31wWpPq3A3m-YqbbpqGzvx-Je0ZhZLfzSJmLBUmL5CAKx66sHCIIzweh52hlg/s1600/c8yeg.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxrZzsTvcPBNpQLRd604CYpXH6VdoFplYFD3D8Z6bEV1bkcWaPxGE3GgMbhnCxBf00lU8RwmfEC8uouz31wWpPq3A3m-YqbbpqGzvx-Je0ZhZLfzSJmLBUmL5CAKx66sHCIIzweh52hlg/s400/c8yeg.PNG&quot; width=&quot;400&quot; height=&quot;209&quot; data-original-width=&quot;1007&quot; data-original-height=&quot;525&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;
Des Devices émettent des données vers la plateforme (quel que soit le protocole) qui sont reçues en temps réel sur des serveurs ou des applications d&#39;analyse. Très commun! Cependant, selon les services offerts par les API REST, il n&#39;est pas toujours trivial de mettre en place un mécanisme de réception en temps réel de la dernière donnée émise ou alarme levée par un Device spécifique. 
&lt;/p&gt;
&lt;p&gt;
Cumulocity offre de ce point de vue 2 outils intéressants :
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;des connexions par websockets, qui permettent de créer des flux de données en temps réel, plus robustes pour ce besoin que du simple HTTP (même en long-polling)&lt;/li&gt;
&lt;li&gt;un ensemble de flux d&#39;évènements internes au framework, sur lesquels il est possible de s&#39;abonner, pour recevoir des notifications sur TOUT ce qui se passe sur la plateforme (réception de données, création de Device, déclenchement d&#39;évènements/alarmes...)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Pour établir une connexion, il suffit de respecter le &lt;a href=&quot;http://blog.inovia-conseil.fr/?p=61&quot;&gt;protocole de Bayeux&lt;/a&gt;, basé les concepts de publish/subsribe et d&#39;échanges de données en JSON. La &lt;a href=&quot;https://www.cumulocity.com/guides/reference/real-time-notifications/&quot;&gt;documentation de Cumulocity&lt;/a&gt; à ce sujet permet de rapidement mettre en place ces flux temps réel.
&lt;/p&gt;
&lt;p&gt;
Afin de réaliser une implémentation la plus simple possible et la plus polyvalente, utilisable tant par un serveur web qu&#39;embarqué dans un Device, nous allons utiliser le langage Python. 
&lt;/p&gt;
&lt;h4&gt;Gestion des websockets&lt;/h4&gt;
&lt;p&gt;
Notre premier module s&#39;occupera de la gestion bas niveau des websockets, grâce au package &lt;a href=&quot;https://pypi.python.org/pypi/websocket-client&quot;&gt;websocket-client&lt;/a&gt;. Vous aurez également besoin de &lt;a href=&quot;https://pypi.python.org/pypi/simplejson/&quot;&gt;simplejson&lt;/a&gt; pour créer du contenu JSON.
&lt;/p&gt;
&lt;div style=&quot;overflow-x:auto&quot;&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;
import websocket
import simplejson

class WebsocketWrapper:
    def __init__(self, cnxUrl):
        self.ws = websocket.WebSocketApp(cnxUrl,
                              on_message = self.on_message,
                              on_error = self.on_error,
                              on_close = self.on_close)
        self.ws.on_open = self.on_open
        self.servermsgjson = []
        
    def on_error(self, ws, error):
        print(error)
    
    def on_close(self, ws):
        print(&#39;closed&#39;)
        
    def on_open(self, ws):
        print(&#39;connected&#39;)
        self.afterOpen()
        
    def on_message(self, ws, message):
        print(&quot;server msg: &quot;+message)
        self.servermsgjson = simplejson.loads(message)
        self.parseMsg(self.servermsgjson)
        
    def send(self,msg):
        self.ws.send(msg)
        
    def openWebsocket(self):
        print(&#39;opening websocket...&#39;)
        # websocket.enableTrace(True)
        self.ws.run_forever(http_proxy_host=&#39;...&#39;, http_proxy_port=80)
        
    def afterOpen(self):
        pass
    
    def parseMsg(self, jsonMsg):
        pass
    
    def handshake(self):
        self.ws.send(simplejson.dumps([{&#39;channel&#39;:&#39;/meta/handshake&#39;,&#39;ext&#39;:{&#39;com.cumulocity.authn&#39;:{&#39;token&#39;:&#39;...&#39;}},&#39;version&#39;:&#39;1.0&#39;,&#39;mininumVersion&#39;:&#39;1.0beta&#39;,&#39;supportedConnectionTypes&#39;:[&#39;websocket&#39;,&#39;long-polling&#39;,&#39;callback-polling&#39;],&#39;advice&#39;:{&#39;timeout&#39;:120000,&#39;interval&#39;:30000}}]))
        
    def connect(self, clientId):
        print(&#39;realtime connection...&#39;)
        self.ws.send(simplejson.dumps([{&quot;channel&quot;:&quot;/meta/connect&quot;,&quot;connectionType&quot;:&quot;websocket&quot;,&quot;clientId&quot;:clientId}]))
        
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
Il vous faudra ici modifier l&#39;adresse du proxy (ou supprimer les paramètres s&#39;il n&#39;y a pas de proxy) et ajouter le token d&#39;authentification (usr:pwd encodés en Base64).
&lt;/p&gt;
&lt;h4&gt;Clients websockets&lt;/h4&gt;
&lt;p&gt;
Le code ci-dessous va permettre de créer 2 clients en websockets écoutant des flux différents : gestion des évènements et réception de mesures.
&lt;/p&gt;
&lt;div style=&quot;overflow-x:auto&quot;&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;
import simplejson

from websocket.websocket_wrapper import WebsocketWrapper

class C8YClient:
    def __init__(self):
        self.clientId = &#39;&#39;
        self.findClientId = False
        self.readyToConnect = False
        
        self.wrapper = WebsocketWrapper(&#39;wss://&lt;tenant&gt;.cumulocity.com/cep/realtime&#39;)
        self.wrapper.parseMsg = self.parseMsg
        self.wrapper.afterOpen = self.afterOpen
        
    def init(self):
        self.wrapper.openWebsocket()
    
    def afterOpen(self):
        self.initClient()
        
    def initClient(self):
        self.findClientId = True
        self.wrapper.handshake()

    def parseMsg(self, jsonMsg):
        if self.findClientId:
            self.findClientId = False
            self.doFindClientId(jsonMsg)
            self.doSubscription()
        elif self.readyToConnect:
            self.readyToConnect = False
            self.connectClient()
        else:
            self.useMsg(jsonMsg)
            
    def useMsg(self, jsonMsg):
        pass
            
    def doSubscription(self):
        pass
        
    def doFindClientId(self, jsonMsg):
        self.clientId = jsonMsg[0][&#39;clientId&#39;]
        print(&#39;got clientId : &#39; + self.clientId)
        
    def connectClient(self):
        self.wrapper.connect(self.clientId)
        
    def subscribe(self, channel):
        print(&#39;subscribing to &#39;+channel+&#39;...&#39;)
        self.readyToConnect = True
        self.wrapper.send(simplejson.dumps([{&quot;channel&quot;:&quot;/meta/subscribe&quot;,&quot;subscription&quot;:&quot;/&quot;+channel+&quot;/*&quot;,&quot;clientId&quot;:self.clientId}]))
        
        
class MeasurementsClient(C8YClient):
    def __init__(self):
        super().__init__()
        
    def initClient(self):
        print(&#39;initMeasurementsClient...&#39;)
        super().initClient()
        
    def doSubscription(self):
        super().subscribe(&#39;measurements&#39;)
            
    def useMsg(self, jsonMsg):
        print(&#39;new measurement : &#39; + simplejson.dumps(jsonMsg))


class EventsClient(C8YClient):
    def __init__(self):
        super().__init__()
        
    def initClient(self):
        print(&#39;initEventsClient...&#39;)
        super().initClient()
        
    def doSubscription(self):
        super().subscribe(&#39;events&#39;)
            
    def useMsg(self, jsonMsg):
        print(&#39;new event : &#39; + simplejson.dumps(jsonMsg))
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
Ne reste plus qu&#39;un petit main pour exécuter tout cela :
&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;
from threading import Thread
from websocket.c8y_client import MeasurementsClient, EventsClient  

if __name__ == &#39;__main__&#39;:
    
    measurementsClient = MeasurementsClient()
    threadM = Thread(target = measurementsClient.init, args = ())
    threadM.start()
    
    eventsClient = EventsClient()
    threadE = Thread(target = eventsClient.init, args = ())
    threadE.start()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
Nous disposons maintenant d&#39;une simple application Python qui reçoit en temps réel des notifications d&#39;évènements de Cumulocity! Vous pouvez le tester simplement via les requêtes REST déjà existantes dans la librairie Postman. Ainsi, POSTer un nouveau Measurement (relevé de données issu d&#39;un capteur) déclenchera immédiatement sa réception côté Python.
&lt;/p&gt;
&lt;p&gt;
A vous l&#39;IIoT !
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://developpef.blogspot.com/feeds/7877685684839774155/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1566084130752530982/7877685684839774155?isPopup=true' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/7877685684839774155'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/7877685684839774155'/><link rel='alternate' type='text/html' href='http://developpef.blogspot.com/2017/09/cumulocity-une-plateforme-iot-taillee.html' title='Cumulocity : une plateforme IoT taillée pour l&#39;industrie'/><author><name>Paul-Emmanuel Faidherbe</name><uri>http://www.blogger.com/profile/14333816988154371906</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJF9OHIybxl9BZ8qHqpkX3CzEcAtPsFesbRt6NQNIAy_LD1arQRfxFXPo0Ur442M6LqY4ZNZk9gwTy474Fa_gayo5ukXRMAxwkMBRTFQqVkD2y1kMHdxc_W0lox-j_E8A6rlntimZ50JZwxmK-mM5egC_mdthRx5lUFhpt_H7obAZ-7w/s220/identite.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOJ60f1JXZ7vqWlahoOIiuXxMjnxQ2ldeCd9hm_Se0xJJzU03TbApT0Dbh8R2LQO4SvLz1nH4-FnqkcQvLIveHYErzdL2V0Dcbo6_C8_RQV-8_oHEdXhmtaOxReW3ZIym3wU2aucUGOw0/s72-c/C8Ylogo.PNG" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1566084130752530982.post-2902320972813066055</id><published>2015-07-30T22:49:00.001+02:00</published><updated>2015-07-30T22:49:25.261+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="iot"/><category scheme="http://www.blogger.com/atom/ns#" term="valtech"/><title type='text'>News autour de l&#39;IoT</title><content type='html'>&lt;p&gt;
Pour tous ceux qui veulent se former et/ou en savoir plus sur les objets connectés et l&#39;Internet des objets, voici quelques événements à ne pas manquer :
&lt;/p&gt;
&lt;h3&gt;Journée de formation&lt;/h3&gt;
&lt;p&gt;
Je suis sur le point de terminer l&#39;élaboration d&#39;une journée de formation proposant un tour d&#39;horizon complet de sujets impliqués par ces nouvelles technologies (matériel, protocoles, sécurité, juridique...) ainsi que plusieurs exercices pratiques à base d&#39;Arduino!
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTwB7tDhYPobLkPupb0HhWYW0VbtKTO0_EJIz6KdPSfJyiEHOJ-QKqSiqJHOimnEfUv1I6M47KvHrf56JPmko9IkQFie_Ub3ltNgT9N2oMueIIjofwLMOhqfJ3VdGTFTwlDHwQ2rDyxVM/s1600/intro.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTwB7tDhYPobLkPupb0HhWYW0VbtKTO0_EJIz6KdPSfJyiEHOJ-QKqSiqJHOimnEfUv1I6M47KvHrf56JPmko9IkQFie_Ub3ltNgT9N2oMueIIjofwLMOhqfJ3VdGTFTwlDHwQ2rDyxVM/s400/intro.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;
Les premières sessions seront disponibles dès la rentrée, alors n&#39;hésitez pas à contacter &lt;a href=&quot;http://www.valtech-training.fr/formation/developpement-mobile/introduction-aux-objets-connectes/&quot;&gt;les équipes de Valtech Training&lt;/a&gt;!
&lt;/p&gt;
&lt;h3&gt;Séminaire : &quot;Internet of Things&quot; &amp; &quot;Big Data&quot; un mariage de raison&lt;/h3&gt;
&lt;p&gt;
Une matinée de présentation des enjeux et impacts de la rencontre de ces deux technologies. Se déroulera surement au mois de novembre. En voici le contenu :
&lt;/p&gt;
&lt;p&gt;&lt;b&gt;
Programme :&lt;/b&gt;&lt;/p&gt;
 &lt;p&gt;
9h00 - 9h30 : Accueil et petit déjeuner
 &lt;/p&gt;&lt;p&gt;
9h30 – 10h00 : Internet of Things (IoT)
&lt;ul&gt;&lt;li&gt;Les usages&lt;/li&gt;
&lt;li&gt;La technologie&lt;/li&gt;
&lt;li&gt;L’arrivée de nouveaux problèmes&lt;/li&gt;&lt;/ul&gt;
&lt;/p&gt;&lt;p&gt;10h15 - 12h30 :  La vrai vie pour &quot;IOT for a better life&quot;
&lt;ul&gt;&lt;li&gt;Cas d’utilisation Valtech&lt;/li&gt;
&lt;li&gt;Architecture Big Data pour &quot;IOT for a better life&quot;&lt;/li&gt;
&lt;li&gt;Ecosystème Big Data complet&lt;/li&gt;
&lt;/ul&gt;&lt;/p&gt;
&lt;br/&gt;
&lt;p&gt;
En espérant vous voir nombreux!
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://developpef.blogspot.com/feeds/2902320972813066055/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1566084130752530982/2902320972813066055?isPopup=true' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/2902320972813066055'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/2902320972813066055'/><link rel='alternate' type='text/html' href='http://developpef.blogspot.com/2015/07/news-autour-de-liot.html' title='News autour de l&#39;IoT'/><author><name>Paul-Emmanuel Faidherbe</name><uri>http://www.blogger.com/profile/14333816988154371906</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJF9OHIybxl9BZ8qHqpkX3CzEcAtPsFesbRt6NQNIAy_LD1arQRfxFXPo0Ur442M6LqY4ZNZk9gwTy474Fa_gayo5ukXRMAxwkMBRTFQqVkD2y1kMHdxc_W0lox-j_E8A6rlntimZ50JZwxmK-mM5egC_mdthRx5lUFhpt_H7obAZ-7w/s220/identite.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTwB7tDhYPobLkPupb0HhWYW0VbtKTO0_EJIz6KdPSfJyiEHOJ-QKqSiqJHOimnEfUv1I6M47KvHrf56JPmko9IkQFie_Ub3ltNgT9N2oMueIIjofwLMOhqfJ3VdGTFTwlDHwQ2rDyxVM/s72-c/intro.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1566084130752530982.post-5460061453784552303</id><published>2015-06-03T23:07:00.000+02:00</published><updated>2017-09-14T14:27:01.076+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="actinium"/><category scheme="http://www.blogger.com/atom/ns#" term="californium"/><category scheme="http://www.blogger.com/atom/ns#" term="coap"/><category scheme="http://www.blogger.com/atom/ns#" term="iot"/><category scheme="http://www.blogger.com/atom/ns#" term="node.js"/><category scheme="http://www.blogger.com/atom/ns#" term="ponte"/><title type='text'>Créer un serveur CoAP</title><content type='html'>&lt;p&gt;J’évoquai dans un précédent article comment créer un client CoAP directement à partir de la spécification, sans avoir à s’imposer une librairie.
&lt;/p&gt;&lt;p&gt;
Nous allons donc maintenant voir comment mettre en place facilement un serveur CoAP à partir des différentes solutions déjà existantes sur le marché.
&lt;/p&gt;
&lt;h4&gt;Actinium&lt;/h4&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;http://www.eclipse.org/californium/images/boxes/b3bb780d.Ac_box_256.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://www.eclipse.org/californium/images/boxes/b3bb780d.Ac_box_256.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;
Intégré dans la suite logicielle &quot;Californium&quot; mise en avant par la fondation Eclipse dans le cadre de son grand projet &quot;IOT&quot;, cet outil est basé entièrement sur des services REST : de l’administration au déploiement de nouveaux services, tout peut être fait par l’appel à des URL. Il est également très simple de créer de nouvelles application puisque tout est codé en Javascript! Il utilise en effet le moteur open source &lt;a href=&quot;https://developer.mozilla.org/fr/docs/Rhino&quot;&gt;Rhino&lt;/a&gt; de la fondation Mozilla. Petit exemple d’application (issu de la documentation) :
&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;
app.root.onget = fnc;
app.root.onpost = fnc;
app.root.onput = fnc;
app.root.ondelete = fnc;

fnc = function(request) {
    request.respond(2.05, &quot;Hello World&quot;); 
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
L’ensemble du code est très léger, le serveur se démarre à partir d’un simple Jar :
&lt;/p&gt;
&lt;pre name=&quot;code&quot; class=&quot;javascript&quot;&gt;java -jar actinium-*.jar&lt;/pre&gt;
&lt;p&gt;Cependant, Rhino est désormais connu pour être un peu vieillissant et ses performances ne sont plus comparables aux moteurs Javascript plus récents, comme le montre &lt;a href=&quot;http://ariya.ofilabs.com/2014/03/nashorn-the-new-rhino-on-the-block.html&quot;&gt;ce document&lt;/a&gt;. Depuis Java 8, il a d’ailleurs été remplacé par Nashorn.
&lt;/p&gt;
&lt;h4&gt;Node.JS&lt;/h4&gt;
&lt;p&gt;Puisque nous sommes en train de parler de moteurs JS côté serveur, qu’en est-il de Node.JS? Il existe en effet un module &quot;&lt;a href=&quot;https://github.com/mcollina/node-coap&quot;&gt;node-coap&lt;/a&gt;&quot; développé par Matteo Collina. Il profite alors des très bonnes performances du moteur “V8” de Google lui permettant de s’insérer dans des applications &quot;temps réel&quot;.
&lt;/p&gt;
&lt;p&gt;Egalement très simple d’utilisation, il permet de tester rapidement les fonctionnalités essentielles du protocole. Par exemple :
&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;
var coap = require(&quot;coap&quot;);

var server = coap.createServer();

server.on(&#39;request&#39;, function(req, res) {
 switch(req.url) {
  case (&#39;/test&#39;) :
   if (req.method == &#39;GET&#39;) {
    res.end(&quot;NodeJS CoAP server OK!!!&quot;);
    console.log(&quot;[test] &quot; + req.method + &quot; to &quot; + req.url);
   }
  break;
  case (&#39;/.well-known/core&#39;) :
   if (req.method == &#39;GET&#39;) {
    res.code = &#39;2.05&#39;;
    res.setOption(&quot;Content-Format&quot;, &quot;application/link-format&quot;);
res.end(&quot;&lt;/test&gt;;title=Test server,&lt;/helloWorld&gt;;title=Hello!&quot;);
   }
  break;
  default:
   res.code = &#39;4.04&#39;;
   res.setOption(&quot;Content-Format&quot;, &#39;text/html&#39;);
   res.end(&#39;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;404 - Not found&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;&amp;lt;h1&amp;gt;Not found.&amp;lt;/h1&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;&#39;);
   console.log(&quot;[404] &quot; + req.method + &quot; to &quot; + req.url);
  break;
 }
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;On voit ici qu’il est très facile de mettre en place un serveur répondant à différentes URL et requêtes HTTP.
&lt;/p&gt;
&lt;p&gt;Au passage, vous pouvez lire dans cet exemple l’implémentation de la découverte de services (discovery) utilisée par CoAP et constituée d’une requête GET sur l’URL &quot;/.well-known/core&quot; renvoyant du contenu au format &quot;CoRE Link Format&quot; (RFC 6690).
&lt;/p&gt;
&lt;h4&gt;Ponte&lt;/h4&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://eclipse.org/ponte/imgs/logo-banner-black.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://eclipse.org/ponte/imgs/logo-banner-black.png&quot; width=&quot;400px&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;Pour aller plus loin, &lt;a href=&quot;https://www.npmjs.com/package/ponte&quot;&gt;cet autre module Node.JS&lt;/a&gt; propose une solution complète mêlant HTTP, CoAP et MQTT (protocole basé sur du publish/subscribe), en plus notamment de quelques connecteurs vers des bases de données NoSQL :
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://eclipse.org/ponte/imgs/architecture.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://eclipse.org/ponte/imgs/architecture.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;Je vous laisse le soin de découvrir ses fonctionnalités.
&lt;/p&gt;&lt;p&gt;
Amusez-vous bien!
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://developpef.blogspot.com/feeds/5460061453784552303/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1566084130752530982/5460061453784552303?isPopup=true' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/5460061453784552303'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/5460061453784552303'/><link rel='alternate' type='text/html' href='http://developpef.blogspot.com/2015/06/creer-un-serveur-coap.html' title='Créer un serveur CoAP'/><author><name>Paul-Emmanuel Faidherbe</name><uri>http://www.blogger.com/profile/14333816988154371906</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJF9OHIybxl9BZ8qHqpkX3CzEcAtPsFesbRt6NQNIAy_LD1arQRfxFXPo0Ur442M6LqY4ZNZk9gwTy474Fa_gayo5ukXRMAxwkMBRTFQqVkD2y1kMHdxc_W0lox-j_E8A6rlntimZ50JZwxmK-mM5egC_mdthRx5lUFhpt_H7obAZ-7w/s220/identite.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1566084130752530982.post-6288211397571305035</id><published>2015-04-08T22:29:00.001+02:00</published><updated>2017-09-14T13:46:45.689+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="adc"/><category scheme="http://www.blogger.com/atom/ns#" term="arduino"/><category scheme="http://www.blogger.com/atom/ns#" term="audio"/><category scheme="http://www.blogger.com/atom/ns#" term="gain"/><title type='text'>Préparer un projet audio avec Arduino</title><content type='html'>&lt;p&gt;Je vais tâcher ici de vous donner quelques informations de base à connaître lorsque vous décidez de vous lancer dans un projet Arduino traitant avec de l’audio. 
&lt;/p&gt;&lt;p&gt;
Mais attention, je ne parle pas de projet “audio-réactif”, comme on en voit en majorité sur le net, dont le but est de faire réagir le matériel en fonction d’une intensité sonore ou d’une fréquence particulière, ni même de “vu-meter” (visualisateur de fréquence type équaliseur). Mon but ici est de présenter les éléments importants à maîtriser dans le cas où vous souhaiteriez enregistrer réellement du son, c’est-à-dire capturer le signal sonore dans son intégralité en vue de traitement ultérieur : re-lecture, analyse spectrale, manipulation en Big Data pour créer votre propre Shazam... ;-)
&lt;/p&gt;&lt;p&gt;
Ainsi, sans avoir la prétention de vous donner un cours d’électronique avancée ou de traitement du signal (je n’en ai pas les capacités), je vais vous livrer tout ce que j’ai appris en tant que néophyte après m’être plongé tête baissée dans ce type de projet sans trop de connaissances de ces domaines.
&lt;/p&gt;
&lt;h3&gt;Passage obligé : la théorie&lt;/h3&gt;
&lt;p&gt;Même si vous me voyez venir, je ne vais pas me lancer dans une explication des Transformées de Fourier (ou Fast Fourier Transform - FFT utilisées en électronique). Cependant, il est intéressant de comprendre leur concept de base : tout signal (ici sonore) peut être décomposé en signaux sinusoïdaux élémentaires, d’amplitudes et de fréquences différentes :&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;http://music.columbia.edu/cmc/musicandcomputers/images/chapter3/sumofsines.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://music.columbia.edu/cmc/musicandcomputers/images/chapter3/sumofsines.jpg&quot; /&gt;&lt;/a&gt;&lt;p&gt;Source : &lt;a href=&quot;http://music.columbia.edu/cmc/musicandcomputers/chapter3/03_03.php&quot;&gt;http://music.columbia.edu/cmc/musicandcomputers/chapter3/03_03.php&lt;/a&gt; &lt;/p&gt;&lt;/div&gt;

&lt;p&gt;Comme on le voit ici, il s’agit donc d’ondes oscillant avec une amplitude variable autour de 0. Or, nos traitements numériques ne peuvent s’appuyer que sur des valeurs positives : nous allons donc devoir commencer par adapter les signaux captés pour pouvoir les traiter proprement, sans risquer de perdre la moitié des informations.
&lt;/p&gt;&lt;p&gt;
Pour ce faire, il va falloir décaler l’amplitude du signal de sorte que les oscillations aient une valeur minimum de 0. Ceci est possible en ajoutant une composante continue (pour créer un biais, ou “offset”), ayant pour valeur la moitié de l’amplitude max du signal : si la source émet une onde à partir d’une tension de 5V, le signal oscillera entre +2.5V et -2.5V. L’ajout d’une composante continue de 2.5V le fera alors osciller entre 0V et 5V. 
&lt;/p&gt;&lt;p&gt;
La théorie est simple, n’est-ce pas? Mais voyons ce que cela implique au niveau matériel… Les choses se compliquent.
&lt;/p&gt;
&lt;h3&gt;Un peu d’électronique&lt;/h3&gt;
&lt;p&gt;Pour additionner nos tensions (alternatives et continues), nous avons besoins d’un pont diviseur. Composé de deux résistances en série, il permet de faire entrer une tension de chaque côté et d’en restituer l’addition entre les deux résistances : nous avons d’ores-et-déjà réussi à décaler notre signal alternatif! Mais on ne peut pas s’arrêter là… Comme vous le constatez, son amplitude a été divisée de moitié, à cause des résistances. Petit aparté : nous venons de toucher du doigt la notion de Gain : c’est notamment la valeur de ces résistances qui fera varier le gain (la puissance) du signal en sortie. Il faut donc ajouter à notre montage un Amplificateur Opérationnel (AO) pour retrouver l’amplitude d’origine. Mais ce dernier ne fonctionnant qu’avec des tensions alternatives, il faut bloquer la composante continue. Pour ce faire, il faut ajouter un condensateur.&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMdNUGmPaDXtS62nJbU5cW99OXFWiXEkui_4ODoZYjvMSmoBeUe967WJgLAz4q3lyO8ggPUJP3nqicNtC2IS9DBpOui29NY9D7PuZTarp15R3ketobtCPeNv1BN4yaRQI5I-QOfzNjjng/s1600/offset.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMdNUGmPaDXtS62nJbU5cW99OXFWiXEkui_4ODoZYjvMSmoBeUe967WJgLAz4q3lyO8ggPUJP3nqicNtC2IS9DBpOui29NY9D7PuZTarp15R3ketobtCPeNv1BN4yaRQI5I-QOfzNjjng/s400/offset.jpg&quot; width=&quot;450px&quot; /&gt;&lt;/a&gt;&lt;p&gt;Source : &lt;a href=&quot;http://www.amazon.fr/L%C3%A9lectronique-d%C3%A9butants-s%C3%A8chent-soudent-br%C3%BBler/dp/2866611802&quot;&gt;L&#39;électronique pour les débutants qui sèchent les cours mais soudent sans se brûler les doigts&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;Un autre exemple avec un micro :&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5X4-rXKxKZmtKAWxD-YV-L60wHCKmOufvQwp6aEDRgj8_vyrj7YjQEpii0x1cm39De2s_jSN3yUl37MZK6VcS5HpnuvUlzBF2pFjhI_fKAMQcdnWgzRE_j1CQRPAIYltgUky9zpmRCXk/s1600/electret.gif&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5X4-rXKxKZmtKAWxD-YV-L60wHCKmOufvQwp6aEDRgj8_vyrj7YjQEpii0x1cm39De2s_jSN3yUl37MZK6VcS5HpnuvUlzBF2pFjhI_fKAMQcdnWgzRE_j1CQRPAIYltgUky9zpmRCXk/s1600/electret.gif&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;Voici donc le rôle de ce montage de base que vous retrouverez régulièrement lorsqu’il s’agit de traiter des signaux audio. Vous voyez donc que plusieurs composants électroniques entre en jeu : il est alors évident que les caractéristiques de chacun vont avoir un impact sur la qualité du signal restitué. C’est ce dont nous allons traiter par la suite.&lt;/p&gt;
&lt;h3&gt;Choix du matériel&lt;/h3&gt;
&lt;p&gt;Le premier élément à choisir est le micro lui-même, qui fera la captation du son. Sauf besoin particulier (nous l’aborderons un peu plus loin dans cet article), les modules à électrets les plus répandus suffisent amplement.&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibErifFAb84_9iJHQwvfmF5AfsYytbe4gwuYmtNkmHYODIBDBN3ML6Nb6evTWrij8AShaXeQ-Ro9laxDiiBsw0HWfzGIuvZorShXo12_dPGQ8K2MHfOotXlvmnPXZX104wr5HeTqXRKFY/s1600/rys.kpcm15ep.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibErifFAb84_9iJHQwvfmF5AfsYytbe4gwuYmtNkmHYODIBDBN3ML6Nb6evTWrij8AShaXeQ-Ro9laxDiiBsw0HWfzGIuvZorShXo12_dPGQ8K2MHfOotXlvmnPXZX104wr5HeTqXRKFY/s320/rys.kpcm15ep.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;
Cependant, ils peuvent s’avérer très sensibles au bruit électrique du circuit qui les entoure. Par exemple, s’ils sont alimentés via un adaptateur secteur, un signal de “souffle” peut apparaître même en silence complet. De même, sur un Arduino, la sortie 3.3V est connue pour être plus stable que la 5V car plus régulée, mais l’idéal reste de prévoir l’alimentation du micro par pile simple.
&lt;/p&gt;&lt;p&gt;
Ensuite, l’Amplificateur Opérationnel joue un rôle primordial dans la préservation de la qualité du signal. Prenons pour commencer l’exemple d’un circuit très répandu : le &lt;a href=&quot;http://www.seeedstudio.com/wiki/Grove_-_Sound_Sensor&quot;&gt;Grove Sound sensor de SeeedStudio&lt;/a&gt;.
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_AGjn376CgCYANB0gHZtGoHB_b-Xc6DdYCMN2BcKMqkXga1mODzopAKzlwD9iLW65kJZ3zvKfIv0z2dCDMyfu7V6uys77BD2NhBwAELLw2rsv4Wx2DzKnMIufjgmVGNJt8Jza7aPZFWQ/s1600/MK00320-40.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_AGjn376CgCYANB0gHZtGoHB_b-Xc6DdYCMN2BcKMqkXga1mODzopAKzlwD9iLW65kJZ3zvKfIv0z2dCDMyfu7V6uys77BD2NhBwAELLw2rsv4Wx2DzKnMIufjgmVGNJt8Jza7aPZFWQ/s1600/MK00320-40.jpg&quot; data-original-width=&quot;211&quot; data-original-height=&quot;200&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;
Il est équipé d’un AO LM358 dont l’inconvénient majeur est d’induire une perte de tension d’environ 1.5V par rapport à la tension d’entrée. Ce qui veut dire que par exemple, pour une tension d’entrée de 5V, la valeur maximale lue sur l’ADC de l’Arduino sera de 750 au lieu de 1024, comme &lt;a href=&quot;https://lowvoltage.wordpress.com/2011/05/21/lm358-mic-amp/&quot;&gt;expliqué ici&lt;/a&gt;.
&lt;/p&gt;&lt;p&gt;
Il vaudra mieux donc s’orienter vers un AO possédant une vraie caractéristique “Rail-to-Rail”, c’est à dire fournissant une tension de sortie égale à la tension d’entrée. L’exemple le plus courant est le MAX4466, disponible sur &lt;a href=&quot;http://www.adafruit.com/products/1063&quot;&gt;ce circuit d’Adafruit&lt;/a&gt; :
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiENPDAh91ueFD6SMTSzRAgvV1-lNQQ48UPJuwxLOucoaulnX5Izq4l6UC9GGJ2DlUb3gx1T0f3qDrCknqwvRXgvsaoR3CMjCPp9sIGhjQV0zGSOm8zPP5CkZ69hMu8thpX3dT8-cadXOc/s1600/ID1063top_LRG.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiENPDAh91ueFD6SMTSzRAgvV1-lNQQ48UPJuwxLOucoaulnX5Izq4l6UC9GGJ2DlUb3gx1T0f3qDrCknqwvRXgvsaoR3CMjCPp9sIGhjQV0zGSOm8zPP5CkZ69hMu8thpX3dT8-cadXOc/s320/ID1063top_LRG.jpg&quot; width=&quot;320&quot; height=&quot;240&quot; data-original-width=&quot;964&quot; data-original-height=&quot;723&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;Cerise sur le gâteau, ce montage dispose d’un gain ajustable, autrement dit un potentiomètre variable à l’arrière.
&lt;/p&gt;&lt;p&gt;
Cependant, il faut garder en tête l’usage qui va être fait de ce micro : s’il s’agit de capter par exemple une musique, pas de souci, il suffira de régler le gain en fonction du volume de la source. Mais dans le cas d’une captation de son ambiant, ou environnemental, la difficulté réside dans l’impossibilité de connaître le volume du son qui sera capté. En effet, il n’est pas si évident de pouvoir bien capter à la fois un son faible ou éloigné et un son fort ou proche. Dans ce cas, si le gain est réglé au maximum pour capter les sons faibles, un effet de “clipping” (écrêtage) peut apparaître sur les sons forts, c’est-à-dire qu’ils seront trop amplifiés pour être captés entièrement :
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrCD7Y5BIzYo9FKdXjBdLKqZAl1fttFf7OdhIjdf2D4PhdIugWNYYDPy_XMB3N8ZJr8mf511oBMxkC2sU3kq4RBkqkn_0XQJ2Jso5THtQHBlf2vKXxMVG5mEq0gz4Zfom2F_hWYuNS58A/s1600/clipping.gif&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrCD7Y5BIzYo9FKdXjBdLKqZAl1fttFf7OdhIjdf2D4PhdIugWNYYDPy_XMB3N8ZJr8mf511oBMxkC2sU3kq4RBkqkn_0XQJ2Jso5THtQHBlf2vKXxMVG5mEq0gz4Zfom2F_hWYuNS58A/s1600/clipping.gif&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;L’idéal est donc de se diriger vers des montages disposant de gain automatiques, capable de passer d’un gain fort dans une ambiance calme à un gain faible dans un environnement bruyant. Cela se trouve également facilement grâce à l’AO MAX9814, disponible sur &lt;a href=&quot;http://www.adafruit.com/products/1713&quot;&gt;ce module Adafruit&lt;/a&gt; :&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;http://www.adafruit.com/images/970x728/1713-00.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img width=&quot;350px&quot; border=&quot;0&quot; src=&quot;http://www.adafruit.com/images/970x728/1713-00.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;
En plus de ce réglage automatique, il est possible de configurer un gain par défaut (40dB, 50dB ou 60dB) selon le montage.
&lt;/p&gt;&lt;p&gt;
Enfin, qui dit réglage automatique, dit réactivité pour adapter le gain. Pour cela, il faut influer sur le ratio Attack:Release (broche “AR” sur le montage), qui détermine la vitesse avec laquelle le gain est diminué (“Attack”) pour atteindre le seuil nécessaire puis augmenté (“Release”) pour revenir en état initial :
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;http://www.softube.com/images/attack-and-release-times.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://www.softube.com/images/attack-and-release-times.jpg&quot; /&gt;&lt;/a&gt;&lt;p&gt;Source : &lt;a href=&quot;http://www.softube.com/images/attack-and-release-times.jpg&quot;&gt;http://www.softube.com/images/attack-and-release-times.jpg&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;J&#39;ai essayé ci-dessous d&#39;illustrer ce concept avec les images d&#39;un oscilloscope :&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghUbnaubFikjuqrjYQK0lv0WKAjZq8P2bDZyaJ6wBKMs4DIUUsJBEAyg-NAEZwboYw3kw3NR5KiwWCJMs3gL4horaYXNHMRidjutu4rf6DC8CnR1u9bfRg67vzI7GpITqCbwDJRKej6qQ/s1600/ARRatio.gif&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghUbnaubFikjuqrjYQK0lv0WKAjZq8P2bDZyaJ6wBKMs4DIUUsJBEAyg-NAEZwboYw3kw3NR5KiwWCJMs3gL4horaYXNHMRidjutu4rf6DC8CnR1u9bfRg67vzI7GpITqCbwDJRKej6qQ/s1600/ARRatio.gif&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h3&gt;Pour aller plus loin...&lt;/h3&gt;
&lt;p&gt;Il reste encore bien des paramètres à prendre en compte au niveau du matériel pour obtenir une captation de bonne qualité. 
&lt;/p&gt;&lt;p&gt;
Pour en citer quelques-uns, on peut commencer par la topologie des micros. En effet, une prise de son stéréo se révèle également bien plus efficace : deux micros permettent de réduire les sources de bruit (ou en tout cas de le soustraire par différentiel) mais également de pallier à l’aspect directif de certains micros.
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;http://doumai.pagesperso-orange.fr/Preampli_Micro/Preampli_Micro_Electret_Perche.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img width=&quot;350px&quot; border=&quot;0&quot; src=&quot;http://doumai.pagesperso-orange.fr/Preampli_Micro/Preampli_Micro_Electret_Perche.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;http://doumai.pagesperso-orange.fr/Preampli_Micro/Preampli_Micro-Electret.htm&quot;&gt;Cette page&lt;/a&gt; explique par exemple comment un couple de micro ORTF permet de reproduire un son entendu par les oreilles humaines, en tenant compte de la distance entre les micros et de leur orientation. Il existe évidemment bien d’&lt;a href=&quot;http://lasonotheque.org/dossier-placement-micros-stereo.html&quot;&gt;autres possibilités selon les situations&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Au niveau logiciel&lt;/h3&gt;&lt;p&gt;
Le programme à mettre en place joue également un rôle important dans la qualité du signal enregistré. Le défi principal est d’arriver à l’enregistrer de manière continue, sans être interrompu par d’autres tâches. Imaginons que vous vouliez enregistrer votre son dans un fichier WAV (sur une carte SD) : il faut être en mesure de continuer l’enregistrement du son le temps de l’écriture des données sur la carte afin de rester fidèle au signal d’origine et ne pas le hachurer.
&lt;/p&gt;&lt;h4&gt;
Utilité des interruptions
&lt;/h4&gt;&lt;p&gt;
Pour cette raison, il est préférable d’utiliser les interruptions, disponibles sur tous les micro-contrôleurs, notamment ceux équipant les Arduino (AVR ou ARM). Ceci nous permettra de lire à intervalles réguliers les valeurs captées par le micro sans pour autant bloquer les processus d’écriture du fichier WAV (et inversement). Mais nous ne pouvons pas pour autant nous contenter d’écrire sur dans le fichier chaque valeur lue : en effet, le temps d’écriture dans un fichier n’étant pas négligeable, nous perdrions trop d’informations du signal. Pour pallier à ceci, il faut utiliser un tampon, dans lequel nous allons stocker par exemple 512 valeurs, avant de lancer l’écriture sur la carte SD. Mais le problème reste à peu près le même... La solution optimale est d’utiliser 2 tampons en parallèle : une fois que le premier est rempli, on lance l’écriture sur la carte SD tandis que le second se rempli en arrière-plan. Une autre technique similaire est celle du “&lt;a href=&quot;http://www.instructables.com/id/Girino-Fast-Arduino-Oscilloscope/step6/Continuously-acquire-with-a-circular-buffer/&quot;&gt;circular buffer&lt;/a&gt;”. Sur les plateformes ARM, il est également possible d’utiliser le &lt;a href=&quot;http://www.embedds.com/using-direct-memory-access-dma-in-stm23-projects/&quot;&gt;Direct Memory Access&lt;/a&gt;.
&lt;/p&gt;&lt;p&gt;
Enfin, les micro-contrôleurs Arduino étant cadencés à plusieurs MHz et un extrait audio ne nécessitant qu’un échantillonage de l’ordre du kHz, nous utiliserons un “prescaler”, c’est-à-dire un diviseur pour limiter la fréquence de déclenchement des interrupts.
&lt;/p&gt;
&lt;h4&gt;Comprendre le convertisseur analogique-numérique&lt;/h4&gt;
&lt;p&gt;Puisque nous voulons enregistrer un signal analogique, nous allons devoir utiliser la fonction “ADC“ qui permet de convertir une valeur analogique en numérique. Il est à ce stade très important de jeter un oeil à la spécification de l’ATmega2560 : elle indique (page 279) qu’une conversion analogique-digital dure 13 cycles d’horloge. Voyons ce que cela implique pour nous.
&lt;/p&gt;&lt;p&gt;
Comme évoqué plus haut, le micro-contrôleur de l’Arduino Mega 2560 est cadencé à 16MHz. Commençons donc par réduire la fréquence des interrupts par un prescaler de 32 :
&lt;/p&gt;
&lt;pre&gt;16 MHz / 32 = 500 kHz&lt;/pre&gt;
&lt;p&gt;Cependant, pour prendre en compte le temps de conversion analogique-numérique, il faut encore diviser cette fréquence :&lt;/p&gt;
&lt;pre&gt;500 kHz / 13 ≈ 38 kHz &lt;/pre&gt;
&lt;p&gt;Nous obtenons donc ici une fréquence d’échantillonage finale de 38 kHz, proche de ce qui se pratique sur un CD audio (44,1 kHz). Pour cet exemple je me suis inspiré de &lt;a href=&quot;http://www.instructables.com/id/Arduino-Audio-Input/step6/Sampling-rate-of-40kHz/&quot;&gt;cet Instructable&lt;/a&gt;. Vous pourrez donc adapter ce réglage à vos besoins.
&lt;/p&gt;&lt;p&gt;
Enfin, les échantillons relevés par l’ADC de l’Arduino sont codés sur 10 bits, comme présenté sur &lt;a href=&quot;http://www.instructables.com/id/Girino-Fast-Arduino-Oscilloscope/step8/How-the-ADC-works/&quot;&gt;cette page&lt;/a&gt;. Or la plupart des formats audio le sont sur 8 bits. Il faut donc diminuer la précision des données acquises (“down-sample”) pour respecter les standards. Pour ce faire, il faut paramétrer l’ADC pour ne lire que les 8 bits ADCH via la commande : ADLAR=1
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;http://cdn.instructables.com/FA2/MS3S/GZQ40KO6/FA2MS3SGZQ40KO6.LARGE.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://cdn.instructables.com/FA2/MS3S/GZQ40KO6/FA2MS3SGZQ40KO6.LARGE.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h4&gt;Prendre en compte l’offset&lt;/h4&gt;
&lt;p&gt;Vous vous souvenez de l’offset abordé en début d’article? Vous remarquerez que sur le dernier montage d’Adafruit, il est indiqué “DC offset : 1.25V”. Ce qui signifie que dans un silence complet, les valeurs retournées ne seront pas de 0 mais d’une valeur légèrement supérieure (dépendant du la tension d’entrée).
&lt;/p&gt;&lt;p&gt;
Ceci convient très bien à l’enregistrement de fichier WAV 8 bits, qui sont codés uniquement à partir de valeurs positives (unsigned int). Les logiciels de lecture (type Audacity) le savent et s’adaptent en fonction. 
&lt;/p&gt;&lt;p&gt;
Cependant, à des fins de traitements du signal plus poussés, il peut s’avérer nécessaire de posséder à la fois les valeurs positives et négatives. Pour cela, il faudra penser à soustraire la valeur de l’offset (donc du silence) des valeurs mesurées.
&lt;/p&gt;
&lt;h3&gt;A vous de jouer!
&lt;/h3&gt;&lt;p&gt;
Vous avez dorénavant les éléments les plus importants pour vous lancer dans un projet de traitement de signal audio. J’espère que cela vous aura été utile!
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://developpef.blogspot.com/feeds/6288211397571305035/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1566084130752530982/6288211397571305035?isPopup=true' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/6288211397571305035'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/6288211397571305035'/><link rel='alternate' type='text/html' href='http://developpef.blogspot.com/2015/04/preparer-un-projet-audio-avec-arduino.html' title='Préparer un projet audio avec Arduino'/><author><name>Paul-Emmanuel Faidherbe</name><uri>http://www.blogger.com/profile/14333816988154371906</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJF9OHIybxl9BZ8qHqpkX3CzEcAtPsFesbRt6NQNIAy_LD1arQRfxFXPo0Ur442M6LqY4ZNZk9gwTy474Fa_gayo5ukXRMAxwkMBRTFQqVkD2y1kMHdxc_W0lox-j_E8A6rlntimZ50JZwxmK-mM5egC_mdthRx5lUFhpt_H7obAZ-7w/s220/identite.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMdNUGmPaDXtS62nJbU5cW99OXFWiXEkui_4ODoZYjvMSmoBeUe967WJgLAz4q3lyO8ggPUJP3nqicNtC2IS9DBpOui29NY9D7PuZTarp15R3ketobtCPeNv1BN4yaRQI5I-QOfzNjjng/s72-c/offset.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1566084130752530982.post-6566493821715400599</id><published>2015-03-30T22:47:00.002+02:00</published><updated>2015-03-30T22:47:30.482+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="devee"/><category scheme="http://www.blogger.com/atom/ns#" term="devops"/><title type='text'>DevOps ok? Voici DevEE!</title><content type='html'>&lt;p&gt;
Pour comprendre comment envisager la collaboration entre les développeurs et les électroniciens, je vous invite à aller lire cet article publié sur le blog de Valtech : &lt;a href=&quot;http://blog.valtech.fr/2015/03/30/devops-ok-voici-devee/&quot;&gt;DevOps ok? Voici DevEE!&lt;/a&gt;
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://developpef.blogspot.com/feeds/6566493821715400599/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1566084130752530982/6566493821715400599?isPopup=true' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/6566493821715400599'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/6566493821715400599'/><link rel='alternate' type='text/html' href='http://developpef.blogspot.com/2015/03/devops-ok-voici-devee.html' title='DevOps ok? Voici DevEE!'/><author><name>Paul-Emmanuel Faidherbe</name><uri>http://www.blogger.com/profile/14333816988154371906</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJF9OHIybxl9BZ8qHqpkX3CzEcAtPsFesbRt6NQNIAy_LD1arQRfxFXPo0Ur442M6LqY4ZNZk9gwTy474Fa_gayo5ukXRMAxwkMBRTFQqVkD2y1kMHdxc_W0lox-j_E8A6rlntimZ50JZwxmK-mM5egC_mdthRx5lUFhpt_H7obAZ-7w/s220/identite.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1566084130752530982.post-1999169715669929602</id><published>2015-03-29T20:53:00.001+02:00</published><updated>2015-03-29T20:53:52.464+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="arduino"/><category scheme="http://www.blogger.com/atom/ns#" term="ENC28J60"/><category scheme="http://www.blogger.com/atom/ns#" term="velleman"/><title type='text'>Arduino Ethernet avec module ENC28J60 </title><content type='html'>&lt;p&gt;
J&#39;ai récemment acquis des cartes Ethernet de chez Velleman, dédiées à l&#39;Arduino : &lt;a href=&quot;http://www.velleman.eu/products/view/?id=412540&quot;&gt;VMA04&lt;/a&gt;
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;width:400px&quot;&gt;&lt;a href=&quot;http://www.velleman.eu/images/products/0/ka04-5.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://www.velleman.eu/images/products/0/ka04-5.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;
Elles ont le mérite d&#39;êtres moins chères, de par leur fabrication et aussi par l&#39;absence de slot SD. Mais il n&#39;est pas si simple de trouver une bonne librairie pour l&#39;utiliser, celle disponible dans la distribution Arduino ne fonctionnant qu&#39;avec un module W5100.
&lt;/p&gt;
&lt;p&gt;
Après de longues recherches, mon choix s&#39;est orienté vers UIPEthernet, présentée ici : &lt;a href=&quot;http://bibi21000.gallet.info/index.php/fr/domotique/82-arduino-fr/185-arduino-et-enc28j60-ethercard-ou-uipethernet.html&quot;&gt;Arduino et enc28j60 : EtherCard ou UIPEthernet&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
Et pour la faire fonctionner avec un Arduino Mega, il faut modifier quelque peu le code comme expliqué dans la page liée, mais avec les valeurs suivantes (dans le fichier fichier utility/Enc28J60Network.h) :
&lt;/p&gt;
&lt;pre&gt;
#define ENC28J60_CONTROL_CS     10
#define SPI_MOSI        MOSI
#define SPI_MISO        MISO
#define SPI_SCK         SCK
#define SPI_SS          SS
&lt;/pre&gt;
&lt;p&gt;
Hope this helps!
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://developpef.blogspot.com/feeds/1999169715669929602/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1566084130752530982/1999169715669929602?isPopup=true' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/1999169715669929602'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/1999169715669929602'/><link rel='alternate' type='text/html' href='http://developpef.blogspot.com/2015/03/arduino-ethernet-avec-module-enc28j60.html' title='Arduino Ethernet avec module ENC28J60 '/><author><name>Paul-Emmanuel Faidherbe</name><uri>http://www.blogger.com/profile/14333816988154371906</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJF9OHIybxl9BZ8qHqpkX3CzEcAtPsFesbRt6NQNIAy_LD1arQRfxFXPo0Ur442M6LqY4ZNZk9gwTy474Fa_gayo5ukXRMAxwkMBRTFQqVkD2y1kMHdxc_W0lox-j_E8A6rlntimZ50JZwxmK-mM5egC_mdthRx5lUFhpt_H7obAZ-7w/s220/identite.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1566084130752530982.post-2945394098908117409</id><published>2015-03-27T11:59:00.001+01:00</published><updated>2017-09-14T14:28:09.091+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="arduino"/><category scheme="http://www.blogger.com/atom/ns#" term="client"/><category scheme="http://www.blogger.com/atom/ns#" term="coap"/><title type='text'>Un client CoAP simple en C</title><content type='html'>&lt;p&gt;
&lt;a href=&quot;http://coap.technology/&quot;&gt;CoAP&lt;/a&gt; est un protocole de communication dédié aux objets connectés : basé sur UDP et REST, il permet de diminuer au maximum le contenu des messages pour économiser les ressources des objets lors des transferts de données.
&lt;/p&gt;
&lt;p&gt;
Nous allons voir ici comment implémenter votre propre client, à l&#39;aide de la spécification du protocole. Le but est d&#39;être capable d&#39;envoyer, de la manière la plus simple possible, des données à un serveur CoAP exposant des services. Niveau matériel, un Arduino Mega avec un shield Ethernet communique avec un serveur Java.
&lt;/p&gt;
&lt;p&gt;
Commençons par la structure des messages. &lt;a href=&quot;http://tools.ietf.org/html/rfc7252#section-3.1&quot;&gt; Ce chapitre de la spécification&lt;/a&gt; nous explique comment les structurer :
&lt;/p&gt;
&lt;table width=&quot;50%&quot; style=&quot;border:1px solid black;border-collapse:collapse&quot;&gt;
&lt;tr bgcolor=&quot;#2400B3&quot; style=&quot;font-style:italic;color:white&quot;&gt;
&lt;th style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;3&quot;&gt;8 bits&lt;/th&gt;
&lt;th style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;8 bits&lt;/th&gt;
&lt;th style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;8 bits&lt;/th&gt;
&lt;th style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;8 bits&lt;/th&gt;
&lt;/tr&gt;
&lt;tr bgcolor=&quot;#B4FF82&quot;&gt;
&lt;td width=&quot;20px&quot; style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;Ver&lt;/td&gt;
&lt;td width=&quot;20px&quot; style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;T&lt;/td&gt;
&lt;td width=&quot;70px&quot; style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;TKL&lt;/td&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;Code&lt;/td&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;2&quot;&gt;Message ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr bgcolor=&quot;#C9ECFF&quot;&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;6&quot;&gt;Token&lt;/td&gt;
&lt;/tr&gt;
&lt;tr bgcolor=&quot;#FFD000&quot;&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;6&quot;&gt;Options&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;3&quot;&gt;Terminator&lt;/td&gt;
&lt;td bgcolor=&quot;#FFFF00&quot; style=&quot;border:1px solid black; padding:5px; text-align:center&quot; colspan=&quot;3&quot;&gt;Payload&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;
Je vous laisse vous référer à la spécification pour la signification des champs. Un peu plus en détails, les Options suivent un format propre :
&lt;/p&gt;
&lt;table width=&quot;50%&quot; style=&quot;border:1px solid black;border-collapse:collapse&quot;&gt;
&lt;tr bgcolor=&quot;#2400B3&quot; style=&quot;font-style:italic;color:white&quot;&gt;
&lt;th style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;3&quot;&gt;8 bits&lt;/th&gt;
&lt;th style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;8 bits&lt;/th&gt;
&lt;th style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;8 bits&lt;/th&gt;
&lt;th style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;8 bits&lt;/th&gt;
&lt;/tr&gt;
&lt;tr bgcolor=&quot;#B4FF82&quot;&gt;
&lt;td width=&quot;20px&quot; style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;Ver&lt;/td&gt;
&lt;td width=&quot;20px&quot; style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;T&lt;/td&gt;
&lt;td width=&quot;70px&quot; style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;TKL&lt;/td&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;Code&lt;/td&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;2&quot;&gt;Message ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr bgcolor=&quot;#C9ECFF&quot;&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;6&quot;&gt;Token&lt;/td&gt;
&lt;/tr&gt;
&lt;tr bgcolor=&quot;#FFD000&quot;&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;2&quot;&gt;Delta&lt;/td&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;Length&lt;/td&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;3&quot;&gt;Value&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;3&quot;&gt;Terminator&lt;/td&gt;
&lt;td bgcolor=&quot;#FFFF00&quot; style=&quot;border:1px solid black; padding:5px; text-align:center&quot; colspan=&quot;3&quot;&gt;Payload&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;
Ici nous allons construire un message contenant :
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;version : 1&lt;/li&gt;
&lt;li&gt;type : Request&lt;/li&gt;
&lt;li&gt;TKL : 0 (pas de Token)&lt;/li&gt;
&lt;li&gt;Code : POST&lt;/li&gt;
&lt;li&gt;vers le service : &quot;/sensors&quot;&lt;/li&gt;
&lt;li&gt;contenu : &quot;test&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Voici ce que cela donne :
&lt;/p&gt;
&lt;table width=&quot;50%&quot; style=&quot;border:1px solid black;border-collapse:collapse&quot;&gt;
&lt;tr bgcolor=&quot;#2400B3&quot; style=&quot;font-style:italic;color:white&quot;&gt;
&lt;th style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;3&quot;&gt;8 bits&lt;/th&gt;
&lt;th style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;8 bits&lt;/th&gt;
&lt;th style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;8 bits&lt;/th&gt;
&lt;th style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;8 bits&lt;/th&gt;
&lt;/tr&gt;
&lt;tr bgcolor=&quot;#B4FF82&quot;&gt;
&lt;td width=&quot;20px&quot; style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;1&lt;/td&gt;
&lt;td width=&quot;20px&quot; style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;Request&lt;/td&gt;
&lt;td width=&quot;70px&quot; style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;0&lt;/td&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;POST&lt;/td&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;2&quot;&gt;Message ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr bgcolor=&quot;#C9ECFF&quot;&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;6&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr bgcolor=&quot;#FFD000&quot;&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;2&quot;&gt;Uri-Path&lt;/td&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;7&lt;/td&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;3&quot;&gt;URI segment &quot;sensors&quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;3&quot;&gt;Terminator&lt;/td&gt;
&lt;td bgcolor=&quot;#FFFF00&quot; style=&quot;border:1px solid black; padding:5px; text-align:center&quot; colspan=&quot;3&quot;&gt;&quot;test&quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;
Chaque Option possède un code &quot;Option Number&quot; propre. Par exemple, &quot;Uri-Path&quot; qui permet d&#39;indiquer un segment de l&#39;adresse du service, a pour code 11. Le Delta se calcule alors en additionnant le code de l&#39;option avec celles des précédentes :
&lt;/p&gt;
&lt;table width=&quot;50%&quot; style=&quot;border:1px solid black;border-collapse:collapse&quot;&gt;
&lt;tr bgcolor=&quot;#2400B3&quot; style=&quot;font-style:italic;color:white&quot;&gt;
&lt;th style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;3&quot;&gt;8 bits&lt;/th&gt;
&lt;th style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;8 bits&lt;/th&gt;
&lt;th style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;8 bits&lt;/th&gt;
&lt;th style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;8 bits&lt;/th&gt;
&lt;/tr&gt;
&lt;tr bgcolor=&quot;#B4FF82&quot;&gt;
&lt;td width=&quot;20px&quot; style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;1&lt;/td&gt;
&lt;td width=&quot;20px&quot; style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;Request&lt;/td&gt;
&lt;td width=&quot;70px&quot; style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;0&lt;/td&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;POST&lt;/td&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;2&quot;&gt;Message ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr bgcolor=&quot;#C9ECFF&quot;&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;6&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr bgcolor=&quot;#FFD000&quot;&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;2&quot;&gt;0+11&lt;/td&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;7&lt;/td&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;3&quot;&gt;&quot;sensors&quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;3&quot;&gt;Terminator&lt;/td&gt;
&lt;td bgcolor=&quot;#FFFF00&quot; style=&quot;border:1px solid black; padding:5px; text-align:center&quot; colspan=&quot;3&quot;&gt;&quot;test&quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;
Si l&#39;on veut spécifier plusieurs options du même type, il n&#39;est pas nécessaire d&#39;additionner le code. Par exemple, pour pointer sur le service &quot;/sensors/temp&quot; :
&lt;/p&gt;
&lt;table width=&quot;50%&quot; style=&quot;border:1px solid black;border-collapse:collapse&quot;&gt;
&lt;tr bgcolor=&quot;#2400B3&quot; style=&quot;font-style:italic;color:white&quot;&gt;
&lt;th style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;3&quot;&gt;8 bits&lt;/th&gt;
&lt;th style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;8 bits&lt;/th&gt;
&lt;th style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;8 bits&lt;/th&gt;
&lt;th style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;8 bits&lt;/th&gt;
&lt;/tr&gt;
&lt;tr bgcolor=&quot;#B4FF82&quot;&gt;
&lt;td width=&quot;20px&quot; style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;1&lt;/td&gt;
&lt;td width=&quot;20px&quot; style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;Request&lt;/td&gt;
&lt;td width=&quot;70px&quot; style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;0&lt;/td&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;POST&lt;/td&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;2&quot;&gt;Message ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr bgcolor=&quot;#C9ECFF&quot;&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;6&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr bgcolor=&quot;#FFD000&quot;&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;2&quot;&gt;0+11&lt;/td&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;7&lt;/td&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;3&quot;&gt;&quot;sensors&quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr bgcolor=&quot;#FFD000&quot;&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;2&quot;&gt;0+11+0&lt;/td&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;4&lt;/td&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;3&quot;&gt;&quot;temp&quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;3&quot;&gt;Terminator&lt;/td&gt;
&lt;td bgcolor=&quot;#FFFF00&quot; style=&quot;border:1px solid black; padding:5px; text-align:center&quot; colspan=&quot;3&quot;&gt;&quot;test&quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;
En revanche, pour une autre Option, par exemple &quot;Max-Age&quot; qui a le code 14 :
&lt;/p&gt;
&lt;table width=&quot;50%&quot; style=&quot;border:1px solid black;border-collapse:collapse&quot;&gt;
&lt;tr bgcolor=&quot;#2400B3&quot; style=&quot;font-style:italic;color:white&quot;&gt;
&lt;th style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;3&quot;&gt;8 bits&lt;/th&gt;
&lt;th style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;8 bits&lt;/th&gt;
&lt;th style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;8 bits&lt;/th&gt;
&lt;th style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;8 bits&lt;/th&gt;
&lt;/tr&gt;
&lt;tr bgcolor=&quot;#B4FF82&quot;&gt;
&lt;td width=&quot;20px&quot; style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;1&lt;/td&gt;
&lt;td width=&quot;20px&quot; style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;Request&lt;/td&gt;
&lt;td width=&quot;70px&quot; style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;0&lt;/td&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;POST&lt;/td&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;2&quot;&gt;Message ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr bgcolor=&quot;#C9ECFF&quot;&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;6&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr bgcolor=&quot;#FFD000&quot;&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;2&quot;&gt;0+11&lt;/td&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;7&lt;/td&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;3&quot;&gt;&quot;sensors&quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr bgcolor=&quot;#FFD000&quot;&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;2&quot;&gt;0+11+14&lt;/td&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;2&lt;/td&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;3&quot;&gt;12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;3&quot;&gt;Terminator&lt;/td&gt;
&lt;td bgcolor=&quot;#FFFF00&quot; style=&quot;border:1px solid black; padding:5px; text-align:center&quot; colspan=&quot;3&quot;&gt;&quot;test&quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;
Revenons à notre exemple et transformons tout en valeurs selon la spec et notre cas :
&lt;/p&gt;
&lt;table width=&quot;50%&quot; style=&quot;border:1px solid black;border-collapse:collapse&quot;&gt;
&lt;tr bgcolor=&quot;#2400B3&quot; style=&quot;font-style:italic;color:white&quot;&gt;
&lt;th style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;3&quot;&gt;8 bits&lt;/th&gt;
&lt;th style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;8 bits&lt;/th&gt;
&lt;th style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;8 bits&lt;/th&gt;
&lt;th style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;8 bits&lt;/th&gt;
&lt;/tr&gt;
&lt;tr bgcolor=&quot;#B4FF82&quot;&gt;
&lt;td width=&quot;20px&quot; style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;1&lt;/td&gt;
&lt;td width=&quot;20px&quot; style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;1&lt;/td&gt;
&lt;td width=&quot;70px&quot; style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;0&lt;/td&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;0.02&lt;/td&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;2&quot;&gt;52942&lt;/td&gt;
&lt;/tr&gt;
&lt;tr bgcolor=&quot;#C9ECFF&quot;&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;6&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr bgcolor=&quot;#FFD000&quot;&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;2&quot;&gt;11&lt;/td&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;7&lt;/td&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;3&quot;&gt;&quot;sensors&quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;3&quot;&gt;Terminator&lt;/td&gt;
&lt;td bgcolor=&quot;#FFFF00&quot; style=&quot;border:1px solid black; padding:5px; text-align:center&quot; colspan=&quot;3&quot;&gt;&quot;test&quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;
Ce qui nous donne, en binaire en respectant la longueur des champs (pour les champs les plus simples) :
&lt;/p&gt;
&lt;table width=&quot;50%&quot; style=&quot;border:1px solid black;border-collapse:collapse&quot;&gt;
&lt;tr bgcolor=&quot;#2400B3&quot; style=&quot;font-style:italic;color:white&quot;&gt;
&lt;th style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;3&quot;&gt;8 bits&lt;/th&gt;
&lt;th style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;8 bits&lt;/th&gt;
&lt;th style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;8 bits&lt;/th&gt;
&lt;th style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;8 bits&lt;/th&gt;
&lt;/tr&gt;
&lt;tr bgcolor=&quot;#B4FF82&quot;&gt;
&lt;td width=&quot;20px&quot; style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;01&lt;/td&gt;
&lt;td width=&quot;20px&quot; style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;01&lt;/td&gt;
&lt;td width=&quot;70px&quot; style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;00000&lt;/td&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;00000010&lt;/td&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;2&quot;&gt;1100111011001110&lt;/td&gt;
&lt;/tr&gt;
&lt;tr bgcolor=&quot;#C9ECFF&quot;&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;6&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr bgcolor=&quot;#FFD000&quot;&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;2&quot;&gt;1011&lt;/td&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;0111&lt;/td&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;3&quot;&gt;&quot;sensors&quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;11&lt;/td&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;11&lt;/td&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;1111&lt;/td&gt;
&lt;td bgcolor=&quot;#FFFF00&quot; style=&quot;border:1px solid black; padding:5px; text-align:center&quot; colspan=&quot;3&quot;&gt;&quot;test&quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;
Enfin, pour se faciliter l&#39;envoi via le contrôleur Ethernet, dont la librairie est prévue pour traiter des &quot;char&quot; sur 8 bits, il suffit de transformer le résultat en concaténant les bits par 8 :
&lt;/p&gt;
&lt;table width=&quot;50%&quot; style=&quot;border:1px solid black;border-collapse:collapse&quot;&gt;
&lt;tr bgcolor=&quot;#2400B3&quot; style=&quot;font-style:italic;color:white&quot;&gt;
&lt;th style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;8 bits&lt;/th&gt;
&lt;th style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;8 bits&lt;/th&gt;
&lt;th style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;8 bits&lt;/th&gt;
&lt;th style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;8 bits&lt;/th&gt;
&lt;/tr&gt;
&lt;tr bgcolor=&quot;#B4FF82&quot;&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;0x50&lt;/td&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;0x02&lt;/td&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;0xCE&lt;/td&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;0xCE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr bgcolor=&quot;#C9ECFF&quot;&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;6&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr bgcolor=&quot;#FFD000&quot;&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;0xB7&lt;/td&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot; colspan=&quot;3&quot;&gt;&quot;sensors&quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border:1px solid black; padding:3px; text-align:center&quot;&gt;0xFF&lt;/td&gt;
&lt;td bgcolor=&quot;#FFFF00&quot; style=&quot;border:1px solid black; padding:5px; text-align:center&quot; colspan=&quot;4&quot;&gt;&quot;test&quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;
En pratique, un petit exemple de code Arduino pour envoyer nos données :
&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;
#include &amp;lt;SPI.h&amp;gt;
#include &amp;lt;Ethernet.h&amp;gt;
#include &amp;lt;EthernetUdp.h&amp;gt;

char coapacket[18];
EthernetUDP udp;

void loop() {
  coapacket[0] = 0x50;
  coapacket[1] = 0x02;
  coapacket[2] = 0xce;
  coapacket[3] = 0xce;
  coapacket[4] = 0xB7;
  coapacket[5] = &#39;s&#39;;
  coapacket[6] = &#39;e&#39;;
  coapacket[7] = &#39;n&#39;;
  coapacket[8] = &#39;s&#39;;
  coapacket[9] = &#39;o&#39;;
  coapacket[10] = &#39;r&#39;;
  coapacket[11] = &#39;s&#39;;
  coapacket[12] = 0xff;
  coapacket[13] = &#39;t&#39;;
  coapacket[14] = &#39;e&#39;;
  coapacket[15] = &#39;s&#39;;
  coapacket[16] = &#39;t&#39;;
  coapacket[17] = &#39;\0&#39;;
 
  udp.beginPacket(serverIP, 5683);
  udp.write(coapacket);
  udp.endPacket();
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
Voilà tout!
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://developpef.blogspot.com/feeds/2945394098908117409/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1566084130752530982/2945394098908117409?isPopup=true' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/2945394098908117409'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/2945394098908117409'/><link rel='alternate' type='text/html' href='http://developpef.blogspot.com/2015/03/un-client-coap-simple-en-c.html' title='Un client CoAP simple en C'/><author><name>Paul-Emmanuel Faidherbe</name><uri>http://www.blogger.com/profile/14333816988154371906</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJF9OHIybxl9BZ8qHqpkX3CzEcAtPsFesbRt6NQNIAy_LD1arQRfxFXPo0Ur442M6LqY4ZNZk9gwTy474Fa_gayo5ukXRMAxwkMBRTFQqVkD2y1kMHdxc_W0lox-j_E8A6rlntimZ50JZwxmK-mM5egC_mdthRx5lUFhpt_H7obAZ-7w/s220/identite.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1566084130752530982.post-3041252689016838813</id><published>2014-09-25T23:17:00.000+02:00</published><updated>2017-09-14T14:29:26.413+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="arduino"/><category scheme="http://www.blogger.com/atom/ns#" term="ntp"/><category scheme="http://www.blogger.com/atom/ns#" term="rtc"/><title type='text'>Arduino : créer une horloge synchronisée</title><content type='html'>&lt;p&gt;
Dans cet article, nous allons voir comment afficher sur un écran la date et l&#39;heure courantes, avec la possibilité de se synchroniser sur un serveur de temps public (NTP - Network Time Protocol), comme le font tous les PC ou téléphones.
&lt;/p&gt;
&lt;h4&gt;Matériel&lt;/h4&gt;
&lt;p&gt;
Pour cet exemple, il faut vous munir :
&lt;ul&gt;
&lt;li&gt;d&#39;un arduino (ici un DUE)&lt;/li&gt;
&lt;li&gt;un shield Ethernet&lt;/li&gt;
&lt;li&gt;un module RTC (Real Time Clock, ici un &lt;a href=&quot;http://www.gravitech.us/i2crecl.html&quot;&gt;Gravitech&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;un écran LCD&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;
&lt;p&gt;
Voici un schéma du montage :
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjovu7JoDvxcyWYpFxxD_05Pr-sXyJ3Mq_0Q-Dz8Vn3ZtBXDithS9jDt2rrRE9_9G2Hkpr9aAS5SgucG8YtI8cVitzgbBZRPQ7Pjbz2OWx94tOu_cXcUnHeQKOlZblOanC_X6IJMgMZodI/s1600/rtc_ntp.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjovu7JoDvxcyWYpFxxD_05Pr-sXyJ3Mq_0Q-Dz8Vn3ZtBXDithS9jDt2rrRE9_9G2Hkpr9aAS5SgucG8YtI8cVitzgbBZRPQ7Pjbz2OWx94tOu_cXcUnHeQKOlZblOanC_X6IJMgMZodI/s400/rtc_ntp.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;
L&#39;écran est branché, de manière classique, sur des broches numériques. Le module RTC quant à lui est intégré sur le bus I2C par les broches SDA1 et SCL1.
&lt;/p&gt;
&lt;h4&gt;Logiciel&lt;/h4&gt;
&lt;p&gt;
Nous allons utiliser les librairies :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ethernet&lt;/li&gt;
&lt;li&gt;Wire1 (pour le bus I2C)&lt;/li&gt;
&lt;li&gt;LiquidCrystal&lt;/li&gt;
&lt;li&gt;Time (pour faciliter la décomposition de la date à partir d&#39;un timestamp)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;u&gt;Données importantes :&lt;/u&gt;&lt;/p&gt;
&lt;p&gt;
Selon la spécification du constructeur, l&#39;adresse de communication du module RTC sur le bus I2C est 0x68. Le serveur NTP choisi est celui de l&#39;Observatoire de Paris (ntp-p1.obspm.fr, IP: 145.238.203.14). Le dialogue avec un serveur NTP se fait par échange de paquets par le protocole UDP.
&lt;/p&gt;
&lt;p&gt;C&#39;est parti!&lt;/p&gt;
&lt;p&gt;&lt;b&gt;1. Configuration d&#39;une date par défaut sur le module RTC&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;
Commençons par un premier échange avec ce module :
&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;
const int I2C_address = 0x68;
...
Wire1.begin();        // join i2c bus (address optional for master)
Wire1.beginTransmission(I2C_address);// Début de transaction I2C
Wire1.write(0); // Arrête l&#39;oscillateur
Wire1.write(0); // sec
Wire1.write(0x11); // min
Wire1.write(0x20); // heure
Wire1.write(6); // jour de la semaine
Wire1.write(0x20); // jour
Wire1.write(9); // mois
Wire1.write(0x14); // annee
Wire1.write(0); // Redémarre l&#39;oscillateur
Wire1.endTransmission(); // Fin de transaction I2C
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
Ici nous définissons la date &quot;20/09/2014 20:11:00&quot;. Remarquez que les valeurs transmises sont au format hexadécimal.
&lt;/p&gt;
&lt;p&gt;&lt;b&gt;2. Lecture de la date sur le module RTC&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;
Interrogeons notre module pour récupérer la date :
&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;
void getTime(char* tempData) {
 byte i = -1;
 byte error;
 
 Wire1.beginTransmission(I2C_address); // Début de transaction I2C
 Wire1.write(0); // Demande les info à partir de l&#39;adresse 0 (soit toutes les info)
 error = Wire1.endTransmission(); // Fin de transaction I2C
 
 if(error==0) {
  Wire1.requestFrom(I2C_address, 7); // Récupère les info (7 octets = 7 valeurs correspondant à l&#39;heure et à la date courante)
 
  while(Wire1.available())        
  {
   tempData[++i] = Wire1.read(); // receive a byte as character
  }
 } else {
  // le composant RTC n&#39;etait pas joignable, on relance le bus I2C pour la prochaine fois
  Wire1.begin();
 }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
Cette méthode nous permet de récupérer, dans un tableau de 7 char (tempData), les données du module.
&lt;/p&gt;
&lt;p&gt;&lt;b&gt;3. Affichage de la date sur l&#39;écran&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;
void displayTime()
{
 char tempchar[7] = {&#39;\0&#39;};
 // recuperation de la date
 getTime(tempchar);
 // affichage
 if(tempchar[0]!=&#39;\0&#39;) {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(tempchar[4],HEX);
  lcd.write(&quot;/&quot;);
  lcd.print(tempchar[5],HEX);
  lcd.write(&quot;/20&quot;);
  lcd.print(tempchar[6],HEX);
  lcd.setCursor(0, 1);
  lcd.print(tempchar[2],HEX);
  lcd.write(&quot;:&quot;);
  lcd.print(tempchar[1],HEX);
  lcd.write(&quot;:&quot;);
  lcd.print(tempchar[0],HEX);
 }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
Avec cette méthode, on envoie à l&#39;écran chaque caractère (toujours au format hexadecimal) retourné par l&#39;appel au module RTC.
&lt;/p&gt;
&lt;p&gt;
Il ne vous reste plus qu&#39;à placer l&#39;appel à cette méthode dans une boucle toutes les secondes pour voir défiler le temps. Essayez même de couper l&#39;alimentation du module RTC : l&#39;affichage de l&#39;heure se fige, jusqu&#39;à nouvelle alimentation du module. Elle sera alors mise à jour avec la date qui a continué à défiler grâce à la pile du module.
&lt;/p&gt;
&lt;p&gt;&lt;b&gt;4. Interrogation du serveur de temps&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;
Le shield Ethernet va nous permettre de contacter le serveur public et de récupérer les informations de date &quot;de référence&quot;.
&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;
IPAddress timeServer(145, 238, 203, 14); // ntp-p1.obspm.fr (IP: 145.238.203.14)
const int NTP_PACKET_SIZE= 48; // NTP time stamp is in the first 48 bytes of the message
uint8_t packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets
/* Set this to the offset (in seconds) to your local time
   GMT - 2 */
const long timeZoneOffset = -7200L;  
// A UDP instance to let us send and receive packets over UDP
EthernetUDP udpClient;
EthernetClient client;

/**
* Démarrage des librairies
*/
Ethernet.begin(mac);
udpClient.begin(8888); // port UDP local


/**
* Envoi de la requete 
*/
// set all bytes in the buffer to 0
memset(packetBuffer, 0, NTP_PACKET_SIZE);
// Initialize values needed to form NTP request
// (see URL above for details on the packets)
packetBuffer[0] = 0b11100011;   // LI, Version, Mode
packetBuffer[1] = 0;     // Stratum, or type of clock
packetBuffer[2] = 6;     // Polling Interval
packetBuffer[3] = 0xEC;  // Peer Clock Precision
// 8 bytes of zero for Root Delay &amp; Root Dispersion
packetBuffer[12]  = 49;
packetBuffer[13]  = 0x4E;
packetBuffer[14]  = 49;
packetBuffer[15]  = 52;

// all NTP fields have been given values, now
// you can send a packet requesting a timestamp:
udpClient.beginPacket(timeServer, 123); //NTP requests are to port 123
udpClient.write(packetBuffer,NTP_PACKET_SIZE);
udpClient.endPacket();


/**
* Parcours de la réponse du serveur
*/
unsigned long epoch = 0;
if ( udpClient.parsePacket() ) {
 // We&#39;ve received a packet, read the data from it
 udpClient.read(packetBuffer,NTP_PACKET_SIZE);  // read the packet into the buffer

 //the timestamp starts at byte 40 of the received packet and is four bytes,
 // or two words, long. First, esxtract the two words:

 unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
 unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
 // combine the four bytes (two words) into a long integer
 // this is NTP time (seconds since Jan 1 1900):
 unsigned long secsSince1900 = highWord &lt;&lt; 16 | lowWord;

 // now convert NTP time into everyday time:
 // Unix time starts on Jan 1 1970. In seconds, that&#39;s 2208988800:
 const unsigned long seventyYears = 2208988800UL + timeZoneOffset;
 // subtract seventy years:
 epoch = secsSince1900 - seventyYears;
}


/**
* Configuration du module RTC avec la nouvelle date
*/
setTime(epoch); // on affecte le timestamp récupéré à la librairie Time
Wire1.beginTransmission(I2C_address);// Début de transaction I2C
Wire1.write(0); // Arrête l&#39;oscillateur
String strval = String(second(), DEC);
Wire1.write(strtol(strval.c_str(),NULL, HEX)); // sec
strval = String(minute(), DEC);
Wire1.write(strtol(strval.c_str(),NULL, HEX)); // min
strval = String(hour(), DEC);
Wire1.write(strtol(strval.c_str(),NULL, HEX)); // heure
Wire1.write(weekday()-1); // jour de la semaine
strval = String(day(), DEC);
Wire1.write(strtol(strval.c_str(),NULL, HEX)); // jour
strval = String(month(), DEC);
Wire1.write(strtol(strval.c_str(),NULL, HEX)); // mois
strval = String(year(), DEC);
Wire1.write(strtol(strval.c_str(),NULL, HEX)); // annee
Wire1.write(0); // Redémarre l&#39;oscillateur
Wire1.endTransmission(); // Fin de transaction I2C
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
La librairie Time nous permet de décomposer facilement les données de la date. Mais le serveur NTP nous a envoyé la date au format décimal &quot;20/09/2014 20:11:00&quot;. Il faut donc convertir les données au format hexa avant de configurer le module RTC.
&lt;/p&gt;
&lt;p&gt;
Ainsi, après l&#39;appel à ce code (à découper en méthodes pour plus de clarté), l&#39;affichage de la date sera automatiquement actualisé avec la date de référence.
&lt;/p&gt;
Have fun!
&lt;/p&gt;
&lt;h4&gt;Sources :&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://skyduino.wordpress.com/2012/01/07/tutoriel-arduino-horloge-rtc-ds1307-librairie-liquidcrystal/&quot;&gt;http://skyduino.wordpress.com/2012/01/07/tutoriel-arduino-horloge-rtc-ds1307-librairie-liquidcrystal/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://arduino.cc/en/Tutorial/UdpNTPClient&quot;&gt;http://arduino.cc/en/Tutorial/UdpNTPClient&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><link rel='replies' type='application/atom+xml' href='http://developpef.blogspot.com/feeds/3041252689016838813/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1566084130752530982/3041252689016838813?isPopup=true' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/3041252689016838813'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/3041252689016838813'/><link rel='alternate' type='text/html' href='http://developpef.blogspot.com/2014/09/arduino-creer-une-horloge-synchronisee.html' title='Arduino : créer une horloge synchronisée'/><author><name>Paul-Emmanuel Faidherbe</name><uri>http://www.blogger.com/profile/14333816988154371906</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJF9OHIybxl9BZ8qHqpkX3CzEcAtPsFesbRt6NQNIAy_LD1arQRfxFXPo0Ur442M6LqY4ZNZk9gwTy474Fa_gayo5ukXRMAxwkMBRTFQqVkD2y1kMHdxc_W0lox-j_E8A6rlntimZ50JZwxmK-mM5egC_mdthRx5lUFhpt_H7obAZ-7w/s220/identite.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjovu7JoDvxcyWYpFxxD_05Pr-sXyJ3Mq_0Q-Dz8Vn3ZtBXDithS9jDt2rrRE9_9G2Hkpr9aAS5SgucG8YtI8cVitzgbBZRPQ7Pjbz2OWx94tOu_cXcUnHeQKOlZblOanC_X6IJMgMZodI/s72-c/rtc_ntp.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1566084130752530982.post-3187918686350070442</id><published>2014-09-08T22:19:00.000+02:00</published><updated>2017-09-14T14:30:18.070+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="arduino"/><category scheme="http://www.blogger.com/atom/ns#" term="atmel"/><title type='text'>Utiliser les librairies Arduino dans Atmel Studio</title><content type='html'>&lt;p&gt;
Dans cet article je vais vous présenter comment démarrer un projet simple (exemple Blink) avec un Arduino Due, Atmel Studio 6.2 et les librairies du projet Arduino.
&lt;/p&gt;
&lt;p&gt;
Pour commencer, vous pouvez suivre cet article très clair et très simple pour initier l&#39;environnement : &lt;a href=&quot;http://www.engblaze.com/tutorial-using-atmel-studio-6-with-arduino-projects/&quot;&gt;http://www.engblaze.com/tutorial-using-atmel-studio-6-with-arduino-projects/&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
Datant cependant de 2012, il mérite quelques mises à jour : il vous faudra télécharger la dernière version du software Arduino capable de gérer le Due. Les chemins vers les répertoires à inclure seront donc légèrement différents, puisque spécifiques à la plateforme (par ex &quot;.\hardware\arduino\&lt;b&gt;sam&lt;/b&gt;\variants\arduino_due_x&quot;). Il faudra également ajouter dans le Linker un lien vers la librairie &lt;b&gt;libsam_sam3x8e_gcc_rel&lt;/b&gt; située sous &quot;.\hardware\arduino\sam\variants\arduino_due_x&quot;.
&lt;/p&gt;
&lt;p&gt;
Il se peut que vous rencontriez des petites erreurs de compilation, que vous pourrez résoudre à la main en commentant/déplaçant du code.&lt;/p&gt;
&lt;p&gt;
Voici maintenant la nouvelle version de l&#39;exemple Blink :
&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;
#include &quot;sam.h&quot;
#include &quot;Arduino.h&quot;


int led = 53;

/**
 * \brief SysTick_Handler.
 */
void SysTick_Handler(void)
{
 /* Increment counter necessary in delay(). */
 TimeTick_Increment();
}

/**
 * \brief Application entry point.
 *
 * \return Unused (ANSI-C compatibility).
 */
int main(void)
{
    /* Initialize the SAM system */
    SystemInit();
    SysTick_Config(SystemCoreClock / 1000); //1ms per interrupt
 
    pinMode(led, OUTPUT);

    while (1) 
    {
        digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
        delay(1000);               // wait for a second
        digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
        delay(1000);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
Pour faire fonctionner la méthode &lt;b&gt;delay&lt;/b&gt;, il est nécessaire d&#39;ajouter le code activant l&#39;incrémentation du compteur systeme : 
&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;
void SysTick_Handler(void)
{
 /* Increment counter necessary in delay(). */
 TimeTick_Increment();
}
...
SysTick_Config(SystemCoreClock / 1000); //1ms per interrupt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
Ainsi, la méthode d&#39;incrémentation &lt;b&gt;TimeTick_Increment&lt;/b&gt; sera appelée par l&#39;handler interne au processeur &lt;b&gt;SysTick_Handler&lt;/b&gt; toutes les 1ms comme indiqué par &lt;b&gt;SysTick_Config&lt;/b&gt;
&lt;/p&gt;
&lt;p&gt;
Ne reste plus qu&#39;à indiquer la plateforme cible à la compilation (processeur SAM3X8E) et lancer la programmation!
&lt;/p&gt;
&lt;p&gt;
Edit : il est également possible d&#39;appeler la méthode Arduino &lt;b&gt;TimeTick_Configure(SystemCoreClock)&lt;/b&gt;
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://developpef.blogspot.com/feeds/3187918686350070442/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1566084130752530982/3187918686350070442?isPopup=true' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/3187918686350070442'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/3187918686350070442'/><link rel='alternate' type='text/html' href='http://developpef.blogspot.com/2014/09/utiliser-les-librairies-arduino-dans.html' title='Utiliser les librairies Arduino dans Atmel Studio'/><author><name>Paul-Emmanuel Faidherbe</name><uri>http://www.blogger.com/profile/14333816988154371906</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJF9OHIybxl9BZ8qHqpkX3CzEcAtPsFesbRt6NQNIAy_LD1arQRfxFXPo0Ur442M6LqY4ZNZk9gwTy474Fa_gayo5ukXRMAxwkMBRTFQqVkD2y1kMHdxc_W0lox-j_E8A6rlntimZ50JZwxmK-mM5egC_mdthRx5lUFhpt_H7obAZ-7w/s220/identite.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1566084130752530982.post-9044864857520063245</id><published>2014-08-30T09:35:00.000+02:00</published><updated>2017-09-20T21:17:44.032+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="sqlserver"/><title type='text'>SQLServer, JDBC et procédures stockées </title><content type='html'>&lt;p&gt;
On ne le repètera jamais assez, migrer une base de données n&#39;a rien d&#39;anodin... Surtout lorsque l&#39;application s&#39;appuie sur des procédures stockées.
En effet, chaque SGBD en propose son propre moteur et aucun driver JDBC ne se ressemble...
&lt;/p&gt;
&lt;blockquote&gt;&lt;center&gt;&lt;br/&gt;Le diable est dans les détails&lt;br/&gt;&lt;/center&gt;&lt;/blockquote&gt;
&lt;p&gt;
Voici donc quelques exemples de &quot;détails&quot; qui vous éviteront de vous arracher les cheveux. La configuration utilisée ici est SQL Server Express 2014 et le driver JDBC Microsoft 4.0.
&lt;/p&gt;
&lt;h4&gt;Un message peut en cacher un autre&lt;/h4&gt;
&lt;p&gt;
Prenons l&#39;exemple de la procédure stockées suivante :
&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;
CREATE PROCEDURE p_maproc(@param INTEGER)
AS
BEGIN

  UPDATE MATABLE SET COL1 = &#39;VALEUR&#39;

  select &#39;data1&#39; as RET1, &#39;data2&#39; as RET2, &#39;data3&#39; as RET3

END
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
Rien de bien compliqué, un UPDATE et un SELECT dont le but est de renvoyer un ResultSet avec 3 colonnes de données.
&lt;/p&gt;
&lt;p&gt;
Appelons maintenant cette procédure avec un outil type Squirrel (configuré pour utiliser le driver JDBC) :
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQZjr0Cs5hUc_s_XUZiOoHLO-k77vEeCt4LLjDIBCxIDq_bKbg-FAn_v-w4jO0eRzEIed65_O28PpXyXTTZjJizC-wb2Yt88qHLNFRR3TPKbab9Nb-oa8azyeOb1WnVnI-h637Xk8rwbE/s1600/execSquirrel.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQZjr0Cs5hUc_s_XUZiOoHLO-k77vEeCt4LLjDIBCxIDq_bKbg-FAn_v-w4jO0eRzEIed65_O28PpXyXTTZjJizC-wb2Yt88qHLNFRR3TPKbab9Nb-oa8azyeOb1WnVnI-h637Xk8rwbE/s1600/execSquirrel.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;
Tout se passe bien, le retour est bien constitué des 3 colonnes du SELECT.
&lt;/p&gt;
&lt;p&gt;
Cependant, lorsque cette même procédure est appelée dans une application Java (via le même driver JDBC), l&#39;erreur suivante est renvoyée :
&lt;/p&gt;
&lt;pre&gt;
com.microsoft.sqlserver.jdbc.SQLServerException: L&#39;instruction n&#39;a pas renvoyé le jeu de résultat.
&lt;/pre&gt;
&lt;p&gt;
En somme, le driver n&#39;a pas pu remonter le ResultSet qu&#39;il attendait...
&lt;/p&gt;
&lt;p&gt;
Ceci est en fait du à la présence de l&#39;instruction UPDATE. Son exécution génère l&#39;émission d&#39;un message appelé DONE_IN_PROC, qui sert à indiquer le nombre de lignes modifiées.
Et c&#39;est donc ce message qui est en priorité capté comme retour par le driver JDBC, ce qui l&#39;empêche ensuite de récupérer le vrai ResultSet final.
&lt;/p&gt;
&lt;p&gt;
Pour corriger ce problème, il existe l&#39;instruction &lt;pre&gt;SET NOCOUNT ON&lt;/pre&gt; qui permet de désactiver l&#39;envoi des messages DONE_IN_PROC par la base. Notre procédure devient donc :
&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;
CREATE PROCEDURE p_maproc(@param INTEGER)
AS
BEGIN

  SET NOCOUNT ON
  UPDATE MATABLE SET COL1 = &#39;VALEUR&#39;
  SET NOCOUNT OFF

  select &#39;data1&#39; as RET1, &#39;data2&#39; as RET2, &#39;data3&#39; as RET3

END
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
Il est également possible de configurer directement le serveur de base de données pour ne pas avoir à écrire cette instruction dans toutes les procédures (voir les liens plus bas).
&lt;/p&gt;
&lt;h4&gt;Du bon usage des types utilisateur&lt;/h4&gt;
&lt;p&gt;
Les UDT (user defined type) fonctionnent comme des alias, permettant de créer des types de données personnalisés. Exemple :
&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;
CREATE TYPE [dbo].[T_DATEHEURE] FROM [datetime] NULL
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
Cette instruction va créer un type de données T_DATEHEURE basé sur le type primitif datetime, utilisable dans la base de données courante.
&lt;/p&gt;
&lt;p&gt;
Prenons donc maintenant l&#39;instruction suivante (toujours dans une procédure stockée) :
&lt;/p&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;
CREATE PROCEDURE p_maproc(@param INTEGER)
AS
BEGIN

  CREATE TABLE #TABLETEMP (ID int, DATE T_DATEHEURE);
 
  ...

END
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
Cette fois-ci, l&#39;erreur suivante sera levée :
&lt;/p&gt;
&lt;pre&gt;
Msg 2715, Level 16, State 7, Line 1
Colonne, parametre, ou variable #2: Type de données T_DATEHEURE introuvable.
&lt;/pre&gt;
&lt;p&gt;
Ceci provient de la nécessité de déclarer également le type de données T_DATEHEURE dans la base de données tempdb, utilisée par SQLServer pour créer les tables temporaires.
Ainsi, une fois l&#39;ordre &quot;CREATE TYPE&quot; exécuté sur tempdb, tout fonctionnera normalement...
&lt;/p&gt;
&lt;p&gt;
Hope this helps!
&lt;/p&gt;
&lt;h4&gt;Sources :&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.mssqltips.com/sqlservertip/1226/set-nocount-on-improves-sql-server-stored-procedure-performance/&quot;&gt;http://www.mssqltips.com/sqlservertip/1226/set-nocount-on-improves-sql-server-stored-procedure-performance/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/questions/1483732/set-nocount-on-usage&quot;&gt;http://stackoverflow.com/questions/1483732/set-nocount-on-usage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://msdn.microsoft.com/fr-fr/library/ms190763.aspx&quot;&gt;http://msdn.microsoft.com/fr-fr/library/ms190763.aspx&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sqlblog.com/blogs/aaron_bertrand/archive/2009/10/14/bad-habits-to-kick-using-alias-types.aspx&quot;&gt;http://sqlblog.com/blogs/aaron_bertrand/archive/2009/10/14/bad-habits-to-kick-using-alias-types.aspx&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><link rel='replies' type='application/atom+xml' href='http://developpef.blogspot.com/feeds/9044864857520063245/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1566084130752530982/9044864857520063245?isPopup=true' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/9044864857520063245'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/9044864857520063245'/><link rel='alternate' type='text/html' href='http://developpef.blogspot.com/2014/08/sqlserver-jdbc-et-procedures-stockees.html' title='SQLServer, JDBC et procédures stockées '/><author><name>Paul-Emmanuel Faidherbe</name><uri>http://www.blogger.com/profile/14333816988154371906</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJF9OHIybxl9BZ8qHqpkX3CzEcAtPsFesbRt6NQNIAy_LD1arQRfxFXPo0Ur442M6LqY4ZNZk9gwTy474Fa_gayo5ukXRMAxwkMBRTFQqVkD2y1kMHdxc_W0lox-j_E8A6rlntimZ50JZwxmK-mM5egC_mdthRx5lUFhpt_H7obAZ-7w/s220/identite.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQZjr0Cs5hUc_s_XUZiOoHLO-k77vEeCt4LLjDIBCxIDq_bKbg-FAn_v-w4jO0eRzEIed65_O28PpXyXTTZjJizC-wb2Yt88qHLNFRR3TPKbab9Nb-oa8azyeOb1WnVnI-h637Xk8rwbE/s72-c/execSquirrel.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1566084130752530982.post-4133786484367719991</id><published>2014-07-02T21:48:00.000+02:00</published><updated>2014-07-02T21:56:24.961+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ecologie"/><category scheme="http://www.blogger.com/atom/ns#" term="greenit"/><title type='text'>Développeurs écolos! </title><content type='html'>&lt;p&gt;Depuis quelques années, la notion de GreenIT envahi l&#39;univers des systèmes d&#39;informations, en particulier au niveau matériel : composants de moins en moins énergivores, utilisation d&#39;énergies renouvelables pour le refroidissement des machines...&lt;/p&gt;
&lt;p&gt;
Mais il est également possible de faire un geste pour la planète en tant que développeur, cela s&#39;appelle l&#39;&lt;b&gt;éco-conception logicielle&lt;/b&gt;.
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEC7-mSAMA-HgLYUXQJgZ049a44t-ngneQdm7qVBXhJvSD0Z4lZXyJONE74xHUt5qDSF6sbNq4abE-7GhY0bNLLWTSvVvR4TCYsCWn7iPvdmsfme5NmQ6R0BdZ4r0ZO_uramsIkF6iCfw/s1600/ecoconcept.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEC7-mSAMA-HgLYUXQJgZ049a44t-ngneQdm7qVBXhJvSD0Z4lZXyJONE74xHUt5qDSF6sbNq4abE-7GhY0bNLLWTSvVvR4TCYsCWn7iPvdmsfme5NmQ6R0BdZ4r0ZO_uramsIkF6iCfw/s1600/ecoconcept.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;
L&#39;idée de départ de ce concept peut être représentée par le &lt;a href=&quot;http://fr.wikipedia.org/wiki/Paradoxe_de_Jevons&quot;&gt;paradoxe de Jevons&lt;/a&gt; :
&lt;/p&gt;
&lt;blockquote&gt;
(...) à mesure que les améliorations technologiques augmentent l&#39;efficacité avec laquelle une ressource est employée, la consommation totale de cette ressource peut augmenter au lieu de diminuer.
&lt;/blockquote&gt;
&lt;p&gt;Autrement connu en économie sous le nom d&#39; &quot;effet rebond&quot; :&lt;/p&gt;
&lt;blockquote&gt;
(...) augmentation de consommation liée à la réduction des limites à l’utilisation d’une technologie.
&lt;/blockquote&gt;
&lt;p&gt;
Prenons un exemple : l&#39;apparition des écrans LCD. Au tout début, le passage des écrans à tube cathodique vers la technologie à cristaux liquides devait générer d’importantes économies d’énergie car, à diagonale identique, un écran LCD consomme de 2 à 3 fois moins d’énergie qu’un écran CRT. Or, l&#39;augmentation exponentielle du nombre d&#39;écrans LCD utilisés a finalement engendré une consommation globale plus importante. De plus, la fabrication d&#39;un écran LCD entraine une production de gaz à effet de serre 2 fois plus importante que celle d&#39;un CRT. Et les exemples sont innombrables.
&lt;/p&gt;
&lt;p&gt;
Dans cette idée, de plus en plus d&#39;organisations pointent du doigt la surconsommation des logiciels, n&#39;hésitant pas à qualifier d&#39; &quot;obésiciels&quot; (&lt;i&gt;bloated software&lt;/i&gt;) ou de &quot;gras numérique&quot; le surplus de code embarqué par les applications modernes.
&lt;p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOYB3GMrGbQzZ-gZDQFB18-epcCWZANvlQYwFTEccXdvbiCtHAHyuYGCQ_eSuBT35W5Hba_Ge-2Wydp8HIxWgDBtHuhttEhASSKZCsnjXQxa1myNpznPcmCjGO5EvXdT3IKn1sSf-jctA/s1600/bloated-android.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOYB3GMrGbQzZ-gZDQFB18-epcCWZANvlQYwFTEccXdvbiCtHAHyuYGCQ_eSuBT35W5Hba_Ge-2Wydp8HIxWgDBtHuhttEhASSKZCsnjXQxa1myNpznPcmCjGO5EvXdT3IKn1sSf-jctA/s1600/bloated-android.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;
Même les plus hautes instances réfléchissent à ce sujet : en 2011, la WWF a publié un rapport intitulé &lt;a href=&quot;http://www.wwf.fr/vous_informer/rapports_pdf_a_telecharger/entreprises/?1180/guide-systme-information-eco-responsable&quot;&gt;&quot;Guide pour un système d&#39;information éco-responsable&quot;&lt;/a&gt;, dans lequel il pointe le constat suivant :
&lt;/p&gt;
&lt;blockquote&gt;
Si on prend l’exemple de Microsoft, chaque nouvelle version du couple Windows – Office nécessite 2 fois plus de ressources que la précédente.&lt;br/&gt;
En d’autres termes, la puissance nécessaire pour écrire un texte double tous les deux ans. Si bien qu’il faut 70 fois plus de mémoire vive sous Windows 7 – Office 2010 pour écrire le même texte que sous Windows 98 – Office 97 !&lt;br/&gt;
On imagine mal devoir utiliser une voiture 70 fois plus puissante qu’il y a 12 ans pour parcourir le même nombre de kilomètres, à la même vitesse.
&lt;/blockquote&gt;
&lt;p&gt;
Ainsi, de plus en plus de grandes entreprises se lancent dans la course au logiciel vert : Facebook a par exemple économisé des centaines de millions de dollars en investissant quelques centaines de &quot;jours.homme&quot; dans le développement d’un compilateur PHP vers C++ : &quot;HHVM&quot; a permis au réseau social de diviser par 2 le nombre de serveurs nécessaires à la génération des milliards de pages servies chaque mois. Facebook a ainsi évité la construction d’un nouveau data center et récupéré près de 50 % de la capacité de ses data centers existants ! Sans compter une facture électrique divisée par 2 et des émissions de gaz à effet de serre réduites d’autant. On peut encore trouver des exemples similaires chez IBM ou LinkedIn.
&lt;/p&gt;
&lt;p&gt;
Bien sûr, il y a aussi des contre-exemples d&#39;entreprises peu consciencieuses de ces considérations : Greenpeace à son tour dénonce, dans &lt;a href=&quot;http://www.greenpeace.org/international/Global/international/publications/climate/2012/iCoal/HowCleanisYourCloud.pdf&quot;&gt;ce rapport de 2012&lt;/a&gt;, le manque de transparence de Twitter, affublée de &quot;lanterne rouge&quot; de l&#39;industrie, ne fournissant aucune information sur son empreinte énergétique. De même, Amazon est accusée de continuer à agrandir son infrastructure dont l&#39; &quot;alimentation électrique ne dépend d&#39;aucune énergie renouvelable, et repose uniquement sur le charbon, le gaz et le nucléaire&quot;.
&lt;/p&gt;
&lt;p&gt;
Il est également intéressant de noter que ce rapport indique que dès 2005, la consommation électrique du &quot;cloud computing&quot; dépassait déjà celle de certains grands pays : 
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTqwf375SlWBqgTe3804oDu2rVCX_50A4p-gbiU1n8expZfA15BVb3hxOUrc3zqGmeMwofETPwDDm66IwjijqQ45xVprx1KmKaydqPwZXFhHrgznboIZg6Adynjed8gewSNyOjE2SeTz4/s1600/greenpeace.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTqwf375SlWBqgTe3804oDu2rVCX_50A4p-gbiU1n8expZfA15BVb3hxOUrc3zqGmeMwofETPwDDm66IwjijqQ45xVprx1KmKaydqPwZXFhHrgznboIZg6Adynjed8gewSNyOjE2SeTz4/s1600/greenpeace.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;
Mais venons-en à l&#39;essentiel : &lt;b&gt;peut-on développer des logiciels &quot;verts&quot;? Et comment?&lt;/b&gt;
&lt;/p&gt;
&lt;p&gt;
Au vu des éléments précédents, la première réponse serait : avec des logiciels &quot;simples&quot;! En effet, en se contentant d&#39;effectuer les calculs et traitements strictement nécessaires, un logiciel pourrait réduire son impact sur la consommation d&#39;énergie. Mais la loi de Moore (qui veut que la puissance des PC double tous les ans) ajoutée au paradoxe de Jevons nous a permis de produire des logiciels de plus en plus complexes (frameworks, surcouches...), sans tenir compte de l&#39;impact de l&#39;exécution de ce code &quot;superficiel&quot;.
&lt;/p&gt;
&lt;p&gt;
Autre exemple &quot;anti-écolo&quot; : on souhaite mettre en place un algorithme, selon deux méthodes :
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;La première sera développée en 1 mois et produira un algorithme s&#39;exécutant en 1 minute&lt;/li&gt;
&lt;li&gt;La seconde sera développée en 2 mois et produira un algorithme s&#39;exécutant en 30 secondes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Que choisiriez-vous? Sûrement le plus rapide à développer... Qui sera pourtant le plus gourmand en ressources et donc le moins &quot;vert&quot; ! Cet exemple prouve que la réflexion d&#39;éco-conception peut venir contrarier l&#39;élaboration classique de logiciels.
&lt;/p&gt;
&lt;p&gt;
Tout ceci pousse donc directement à l&#39;adoption de nouveau matériel toujours plus puissant et accélère le renouvellement des parcs informatiques : la durée de vie moyenne d&#39;un PC a été divisée par 3 en quelques années (généralement 3 ans au lieu de 10), jouant ainsi le jeu de la société de consommation. [Effet papillon :)]
&lt;/p&gt;
&lt;p&gt;
Pour résumer, même s&#39;il peut paraître quelques fois compliqué de conserver des considérations écologiques dans le cadre du développement d&#39;un logiciel, ces réflexions peuvent permettre de produire du code simple, efficace et finalement bon pour la planète.
&lt;/P&gt;
&lt;h4&gt;Sources :&lt;/h4&gt; 
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.greenit.fr/article/bonnes-pratiques/dossier-ecoconception-logicielle-benefices-potentiels-5179&quot;&gt;http://www.greenit.fr/article/bonnes-pratiques/dossier-ecoconception-logicielle-benefices-potentiels-5179&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.greenit.fr/article/bonnes-pratiques/l-effet-rebond-dans-le-numerique-est-il-evitable-5071&quot;&gt;http://www.greenit.fr/article/bonnes-pratiques/l-effet-rebond-dans-le-numerique-est-il-evitable-5071&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.journaldunet.com/solutions/cloud-computing/energie-des-datacenters-d-amazon-twitter-google-microsoft-et-apple.shtml&quot;&gt;http://www.journaldunet.com/solutions/cloud-computing/energie-des-datacenters-d-amazon-twitter-google-microsoft-et-apple.shtml&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.axosoft.com/blog/2007/12/24/rules-for-being-a-green-software-engineer/&quot;&gt;http://www.axosoft.com/blog/2007/12/24/rules-for-being-a-green-software-engineer/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.simula.no/research/se/publications/Simula.SE.647/simula_pdf_file&quot;&gt;https://www.simula.no/research/se/publications/Simula.SE.647/simula_pdf_file&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://fr.slideshare.net/WWF_France/guide-ntic-27042011-8746043&quot;&gt;http://fr.slideshare.net/WWF_France/guide-ntic-27042011-8746043&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://greencodelab-challenge.org/images/support-conferences/Jerome_ROCHETEAU.pdf&quot;&gt;http://greencodelab-challenge.org/images/support-conferences/Jerome_ROCHETEAU.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.greencodelab.fr/content/software-eco-design-approach-with-12-conference-during-the-green-code-lab-challenge&quot;&gt;http://www.greencodelab.fr/content/software-eco-design-approach-with-12-conference-during-the-green-code-lab-challenge&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;</content><link rel='replies' type='application/atom+xml' href='http://developpef.blogspot.com/feeds/4133786484367719991/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1566084130752530982/4133786484367719991?isPopup=true' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/4133786484367719991'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/4133786484367719991'/><link rel='alternate' type='text/html' href='http://developpef.blogspot.com/2014/07/developpeurs-ecolos.html' title='Développeurs écolos! '/><author><name>Paul-Emmanuel Faidherbe</name><uri>http://www.blogger.com/profile/14333816988154371906</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJF9OHIybxl9BZ8qHqpkX3CzEcAtPsFesbRt6NQNIAy_LD1arQRfxFXPo0Ur442M6LqY4ZNZk9gwTy474Fa_gayo5ukXRMAxwkMBRTFQqVkD2y1kMHdxc_W0lox-j_E8A6rlntimZ50JZwxmK-mM5egC_mdthRx5lUFhpt_H7obAZ-7w/s220/identite.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEC7-mSAMA-HgLYUXQJgZ049a44t-ngneQdm7qVBXhJvSD0Z4lZXyJONE74xHUt5qDSF6sbNq4abE-7GhY0bNLLWTSvVvR4TCYsCWn7iPvdmsfme5NmQ6R0BdZ4r0ZO_uramsIkF6iCfw/s72-c/ecoconcept.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1566084130752530982.post-8547207292379334105</id><published>2014-06-30T20:30:00.000+02:00</published><updated>2014-06-30T20:30:11.537+02:00</updated><title type='text'>Comprendre les objets connectés avec Arduino</title><content type='html'>&lt;p&gt;
J&#39;ai récemment eu l&#39;occasion de publier un article sur les objets connectés dans le magazine &lt;b&gt;Programmez!&lt;/b&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;
&lt;a href=&quot;http://www.programmez.com/magazine/article/comprendre-les-objets-connectes-avec-arduino&quot;&gt;Comprendre les objets connectés avec Arduino&lt;/a&gt;&lt;br/&gt;
&lt;a href=&quot;http://www.programmez.com/sites/default/files/img_articles/00075_23.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://www.programmez.com/sites/default/files/img_articles/00075_23.jpg&quot; /&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
Alors n&#39;hésitez pas à acheter ce numéro, cela fera une lecture intéressante sur la plage!
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://developpef.blogspot.com/feeds/8547207292379334105/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1566084130752530982/8547207292379334105?isPopup=true' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/8547207292379334105'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/8547207292379334105'/><link rel='alternate' type='text/html' href='http://developpef.blogspot.com/2014/06/comprendre-les-objets-connectes-avec.html' title='Comprendre les objets connectés avec Arduino'/><author><name>Paul-Emmanuel Faidherbe</name><uri>http://www.blogger.com/profile/14333816988154371906</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJF9OHIybxl9BZ8qHqpkX3CzEcAtPsFesbRt6NQNIAy_LD1arQRfxFXPo0Ur442M6LqY4ZNZk9gwTy474Fa_gayo5ukXRMAxwkMBRTFQqVkD2y1kMHdxc_W0lox-j_E8A6rlntimZ50JZwxmK-mM5egC_mdthRx5lUFhpt_H7obAZ-7w/s220/identite.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1566084130752530982.post-5489805716054645112</id><published>2014-02-17T22:14:00.000+01:00</published><updated>2014-03-04T22:15:42.329+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="arduino"/><category scheme="http://www.blogger.com/atom/ns#" term="arm"/><title type='text'>Arduino et après?</title><content type='html'>&lt;p&gt;
Ce titre est un peu raccoleur, surtout que je vais continuer à parler d&#39;Arduino... Le sujet exact ici est plutôt &quot;AVR et après?&quot;. 
&lt;/p&gt;
&lt;p&gt;
En effet, l&#39;ampleur ou les besoins de certains projets nécessitent d&#39;aborder une solution plus complète que les plateformes Arduino classiques, utilisant des microcontrôleurs AVR 8 bits.
&lt;/p&gt;
&lt;p&gt;
Voici donc comment prendre en main l&#39;Arduino Due, et surtout son microprocesseur ARM 32 bits (ATSAM3X8E), utilisé par exemple dans les &lt;a href=&quot;http://www.arm.com/markets/mobile/smartphones.php&quot;&gt;smartphones&lt;/a&gt;.
&lt;/p&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;http://arduino.cc/en/uploads/Main/ArduinoDue_Front.jpg&quot; imageanchor=&quot;1&quot; &gt;&lt;img border=&quot;0&quot; src=&quot;http://arduino.cc/en/uploads/Main/ArduinoDue_Front.jpg&quot; width=&quot;350&quot; /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;http://www.atmel.com/Images/tout_sam3x_lg.jpg&quot; imageanchor=&quot;1&quot; &gt;&lt;img border=&quot;0&quot; src=&quot;http://www.atmel.com/Images/tout_sam3x_lg.jpg&quot; width=&quot;300&quot; /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;h4&gt;Plus de mémoire!&lt;/h4&gt;
&lt;p&gt;
Le point le plus marquant et intéressant de la plateforme est sans doute la quantité de mémoire disponible : 512Ko de Flash (pour le programme) et 96Ko de RAM (pour l&#39;execution et les données).
&lt;/p&gt;
&lt;p&gt;
De plus la vitesse d&#39;exécution de 84Mhz peut apporter un sacré coup de pouce aux projets qui le nécessitent (temps réel...). Enfin, l&#39;utilisation de données sur 32 bits offre une puissance de calcul importante.
&lt;/p&gt;
&lt;p&gt;
Pour une présentation détaillée, je vous laisse lire l&#39;article suivant : &lt;a href=&quot;http://skyduino.wordpress.com/2013/03/26/test-arduino-due-ide-arduino-1-5-x/&quot;&gt;[Test] Arduino Due &amp; IDE arduino 1.5.x&lt;/a&gt;
&lt;/p&gt;
&lt;h4&gt;
Appréhender le nouveau coeur
&lt;/h4&gt;
&lt;p&gt;
Un processeur ARM est bien plus complexe que les traditionnels AVR : bus de données, contrôleur avancé d&#39;interruptions, optimisation du code exécuté, timers (watchdog)... Je ne vais pas m&#39;attarder ici sur ce sujet complexe, je vous laisse vous lancer par vous-même en lisant par exemple &lt;a href=&quot;http://www.zembedded.com/an-intro-to-cortex-m3-by-nxp/&quot;&gt;cette présetation&lt;/a&gt;, l&#39;excellent ouvrage &quot;Processeurs arm - architecture et langage d&#39;assemblage&quot; de Jacques Jorda ou le livre &quot;The Definitive Guide to the ARM Cortex-M3, Second Edition&quot; de Joseph Yiu.
&lt;/p&gt;
&lt;h4&gt;
Outils de développement
&lt;/h4&gt;
&lt;p&gt;
Qui dit nouvelle architecture, dit nouveaux outils... Pour commencer, le compilateur : place à la &lt;a href=&quot;https://launchpad.net/gcc-arm-embedded&quot;&gt;toolchain ARM-GCC&lt;/a&gt;. Maintenue par les développeurs de AVR-GCC, elle permet de faire du bare-metal (oh-yeah!), comprenez du code indépendant de la plateforme. Pour la culture, voici une exlication du nom du compilateur &quot;arm-none-eabi&quot; :
&lt;/p&gt;
&lt;blockquote&gt;
Basically, &quot;arm-none-eabi&quot; means:
&lt;br/&gt;&lt;br/&gt;
- &#39;arm&#39; we are building for the ARM architecture (ARM, Thumb, Thumb-2, etc).&lt;br/&gt;
- &#39;none&#39; means we are not building for a specific operating system.  or &#39;bare-metal&#39;  (...)&lt;/br&gt;
- &#39;eabi&#39; says we&#39;re going to use the ARM standard EABI, which describes how binary files (libraries, etc) are stored (the actual file formats), and calling conventions, register usage, etc.  This makes libraries from different parties compatible with each other and your code.  ABI&#39;s and EABI&#39;s standardize our compiled code.. (...)&lt;br/&gt;&lt;br/&gt;
&lt;i&gt; source : &lt;a href=&quot;http://kunen.org/uC/gnu_tool.html&quot;&gt;http://kunen.org/uC/gnu_tool.html&lt;/a&gt;&lt;/i&gt;
&lt;/blockquote&gt;
&lt;p&gt;
Qu&#39;en est-il du code lui-même? Là où les plateformes AVR supportent très bien le C++, les processeurs ARM préfèrent nettement le C car ils sont bien plus optimisés pour gérer ce langage. Qui plus est, la plupart des améliorations apportées par le C++ (orienté objet...) ne sont que très peu utilisées dans cet environnement et ne justifient donc pas (pour le moment) son utilisation.
&lt;/p&gt;
&lt;p&gt;
Des librairies et frameworks permettent également de faciliter la prise en main du code : &lt;a href=&quot;http://www.arm.com/products/processors/cortex-m/cortex-microcontroller-software-interface-standard.php&quot;&gt;CMSIS&lt;/a&gt;, une couche d&#39;abstration de moyen niveau fournie par ARM (donc &quot;vendor-independant&quot;), ou bien &lt;a href=&quot;http://www.atmel.com/tools/avrsoftwareframework.aspx?tab=overview&quot;&gt;Atmel Software Framework&lt;/a&gt;, cette fois-ci proposé par le fabricant Atmel dans son environnement de développement, qui apporte notamment une tonne d&#39;exemples et de bonnes pratiques.
&lt;/p&gt;
&lt;h4&gt;
Débugger un ARM
&lt;/h4&gt;
&lt;p&gt;
La nouvelle gestion de la mémoire du processeur ainsi que les nouvelles possibilités d&#39;observation du code exécuté requièrent forcément de nouveaux outils pour débugger votre programme. Adieu donc notre bel AVR-Dragon vu précédemment. Même s&#39;il est heureusement toujours possible d&#39;utiliser une interface JTAG, il vous faudra investir dans par exemple ce J-Link de Segger :
&lt;/p&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;http://www.segger.com/debug-probes.html&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://www.segger.com/cms/admin/uploads/imageBox/J-Link-PRO_left_shadow_350x.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;
Pourquoi celui-ci en particulier? En effet, il existe également le &lt;a href=&quot;http://www.atmel.com/tools/ATMELSAM-ICE.aspx&quot;&gt;SAM-ICE&lt;/a&gt; de Atmel. Mais je pense que lorsque vous aurez jeté un oeil aux prix pratiqués, la version Education du JLink fera pencher la balance! Surtout qu&#39;au final les fonctionnalités sont quasi-identiques, l&#39;un n&#39;étant qu&#39;une déclinaison de l&#39;autre...
&lt;/p&gt;
&lt;p&gt;
Pour la commande, je me permets de vous conseiller le site Mouser, très pro et très rapide pour la livraison. Dernier point important, même si l&#39;Arduino Due dispose bien d&#39;une interface JTAG 2x5 broches, elle est de taille réduite! Et les debuggers quant à eux utilisent des interfaces 2x10 broches. Il faudra vous procurer l&#39;adaptateur correspondant : &lt;a href=&quot;http://www.embeddedartists.com/products/acc/acc_jtag_adapter_kit.php&quot;&gt;10-PIN TO 20-PIN JTAG ADAPTER&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
Vous voilà bien armés pour démarrer... La suite au prochain épisode! Have fun!
&lt;/p&gt;
&lt;h4&gt;Sources :&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://mcuoneclipse.com/2013/02/14/tutorial-using-the-arm-cmsis-library/&quot;&gt;Tutorial: Using the ARM CMSIS Library&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.zilogic.com/releases/current/zdev-user-manual/index.html&quot;&gt;http://www.zilogic.com/releases/current/zdev-user-manual/index.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://siwawi.bauing.uni-kl.de/avr_projects/arm_projects/index.html#cm3_cpp1&quot;&gt;Exemples de code C++&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><link rel='replies' type='application/atom+xml' href='http://developpef.blogspot.com/feeds/5489805716054645112/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1566084130752530982/5489805716054645112?isPopup=true' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/5489805716054645112'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1566084130752530982/posts/default/5489805716054645112'/><link rel='alternate' type='text/html' href='http://developpef.blogspot.com/2014/02/arduino-et-apres.html' title='Arduino et après?'/><author><name>Paul-Emmanuel Faidherbe</name><uri>http://www.blogger.com/profile/14333816988154371906</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJF9OHIybxl9BZ8qHqpkX3CzEcAtPsFesbRt6NQNIAy_LD1arQRfxFXPo0Ur442M6LqY4ZNZk9gwTy474Fa_gayo5ukXRMAxwkMBRTFQqVkD2y1kMHdxc_W0lox-j_E8A6rlntimZ50JZwxmK-mM5egC_mdthRx5lUFhpt_H7obAZ-7w/s220/identite.png'/></author><thr:total>0</thr:total></entry></feed>