ThingJS v1.0-alpha


Depuis deux ans, je développe ma propre plateforme IoT et aujourd'hui je suis prêt à montrer sa version alpha.


Avec un partenaire, nous créons et prenons en charge des appareils IoT. Nous avons démantelé plus d'un hangar à râteau dans le cadre de cette activité. ThingJS est né non pas tant du désir que du besoin de nous faciliter la vie, mais en même temps, je l'espère, de vous.


L'article sera intéressant pour les personnes proches du sujet de l'IoT et qui ont déjà fait quelque chose dans ce domaine. Un point important sera que la plate-forme devrait intéresser (soudainement) les développeurs JavaScript, cette langue est choisie comme base de la plateforme. Bien sûr, les développeurs C / C ++ auront également quelque chose à lire.


Tout d'abord, je parlerai des problèmes clés que nous avons rencontrés lors du développement d'appareils IoT, puis je décrirai comment la plate-forme les gère, et à la fin, tout est ennuyeux: la vidéo , la partie technique, et vous pouvez tout toucher en direct .



Problèmes IoT:


- Le problème des armes courtes


L'IoT est basé sur un écosystème. Le développement de son concept et de son architecture technique demande vraiment beaucoup de travail. De plus, vous devez encore développer un tas de micrologiciels pour les appareils hétérogènes. Inventer et mettre en œuvre le transport pour l'échange de données entre appareils selon différents principes physiques et logiques. Développez les ressources cloud. Élaborez des interfaces utilisateur. Etc. etc.


Même si un spécialiste individuel a les compétences nécessaires pour le faire, il n'a tout simplement pas assez de temps (mains) pour mettre en œuvre une telle idée. Pendant qu'il le coupera, elle deviendra obsolète.


- Le problème de la tour de Babel


Développer un écosystème IoT à part entière nécessite une pile technologique très large. Être une pile complète dans l'IoT est simple ... difficile. Besoin d'expérience partout. Tout le monde ne peut pas se vanter d'un éventail aussi large de connaissances et même d'expérience. Et ici, la question n'est pas dans les capacités mentales. C'est une conclusion évidente du problème de la main-d'œuvre.


Pour créer un écosystème vraiment riche, il faut le travail de nombreux spécialistes assez étroits, mais avec une connaissance approfondie de leur domaine. Ces spécialistes parlent différentes langues, utilisent différents modèles et comprennent souvent les termes élémentaires de différentes manières. Et étant donné que l'IoT est basé sur des appareils aux ressources limitées, des communications efficaces sont essentielles à la réalisation de ce qui est prévu.


- Le problème du syndrome de Stockholm


Aujourd'hui, il y a des vendeurs qui développent leurs écosystèmes. Ce sont Google, Microsoft, Yandex, Megaphone, MTS, etc. Certains d'entre eux vous permettent d'intégrer vos propres choses dans leurs écosystèmes à leurs conditions. Cela couvre largement les problèmes décrits ci-dessus. Mais cela en crée une nouvelle - la dépendance. Et les vendeurs aiment changer les conditions d'intégration. Et plus encore, il n'est pas question de réalisation de soi dans ce paradigme.


Solutions aux problèmes:


- Communauté, toxicomanie, à la mode, jeunesse


Les problèmes décrits ci-dessus bloquent en fait l'accès au développement de l'IoT pour les individus. Le développement de la plateforme a été lancé avec la prise de conscience de ces problèmes. Les bases ont été jetées pour le développement de la plateforme à travers la communauté.


Pour implémenter cette idée, la plate-forme, bien sûr, est livrée avec une base de code ouverte et possède également un paradigme de dépendance sur toutes les couches.


Si vous ne savez pas ce que sont les dépendances, il est temps de les connaître. Mais si vous essayez d'expliquer très simplement, le module que vous développez peut dépendre d'un autre que votre ami écrit. Et vous accéderez à son module via une interface prédéfinie.


Ainsi, en même temps, indépendamment, de nombreuses personnes peuvent développer leurs propres composants de plate-forme et réutiliser ceux existants développés par quelqu'un. Cela résout fondamentalement le problème des mains courtes.



De plus, le problème de la «Tour de Babel» est en train d'être résolu. Les dépendances sont construites de sorte que les différents niveaux de la plateforme, développés dans différents langages, disposent d'un mécanisme prédéterminé pour créer des dépendances entre eux.


Par exemple, un développeur C peut tirer parti d'un composant frontal prêt à l'emploi en lui fournissant l'interface requise. Ou, au contraire, le développeur frontal peut utiliser un composant prêt à l'emploi écrit en C. C'est-à-dire chacun fera ce qu'il sait le mieux.


- Plus de promesses et d'abstractions


Le protocole de communication entre les appareils n'est pas défini. Au lieu de cela, il y a une abstraction - un bus de données. L'appareil peut envoyer un événement au bus ou écouter le bus. On ne sait pas qui écrit dans le bus et qui reçoit à l'avance. Et quand aussi. L'échange et la livraison de données asynchrones ne sont pas garantis. En général - l'enfer. Pas de panique. Ainsi conçu.


Le fait est que l'écosystème est un groupe d'appareils séparés et autosuffisants. À tout moment, certains appareils peuvent ne pas être disponibles. Pour diverses raisons. Arrêter l'activité d'autres appareils si une pièce n'est pas disponible n'est pas le meilleur scénario. Il faut légaliser ce qui ne peut être évité.


La plateforme met en œuvre le paradigme des promesses de fournir des événements. Le premier appareil souscrit à la promesse du second de lui donner des informations. Mais il n'y a aucune garantie. L'abonné doit décider quoi faire en cas de transmission intempestive de données.


Le problème de la communication synchrone est résolu par la transmission d'événements via le bus avec des liaisons vers des canaux synchrones. Le protocole de canal synchrone est déterminé par le type d'événement lui-même. Par exemple, vous pouvez envoyer un événement avec le type "do-render-video-stream" et comment envoyer des caméras IP WEB en tant que charge utile. Ainsi, le destinataire saura que vous devez lire le flux vidéo à partir de l'adresse spécifiée.



Mais comment fonctionne physiquement le bus? La mise en œuvre du bus incombe à la communauté. Le pneu se dilate avec le transport que votre projet nécessite. Par exemple, un événement est reçu via http et relayé via UART. Pour tous les éléments de l'écosystème, rien ne changera extérieurement.


- Périphériques IoT virtuels


Pour ThingJS, une chose n'est pas seulement une chose physique, mais aussi une application spéciale - une chose virtuelle. De plus, une chose physique peut contenir plusieurs choses virtuelles (applications) qui utilisent les ressources d'une chose physique.


Cette approche vous permet d'unifier l'interaction entre le backend conditionnel (contrôleur / serveur / cloud, etc.) et le frontend (navigateur, application, etc.), ainsi que b2b et même f2f. Construisez une matrice, pas une hiérarchie d'interactions.



Un exemple simple serait une caméra WEB, qui en soi a une chose virtuelle - une interface utilisateur. Lorsque l'utilisateur accède à l'adresse http://192.168.4.1 , la page WEB s'ouvre, où la chose virtuelle commence à «vivre». La caméra (chose physique) et la page (chose virtuelle) deviennent automatiquement un écosystème où un bus de données unifié est disponible. À travers elle, la chose virtuelle communique avec le physique. Dans ce cas: la chose physique indique à la chose virtuelle via le bus l'adresse du flux vidéo, son état, etc., et la virtuelle montre à l'utilisateur la vidéo et donne les commandes nécessaires à la chose physique.


La suite logique est la possibilité d'héberger des objets virtuels dans les nuages ​​et de les inclure dans un écosystème commun. Et cela, à son tour, vous permet de créer des périphériques virtuels avec d'énormes ressources qui résolvent des problèmes, par exemple, disponibles pour l'IA.


Vous pouvez créer ces appareils vous-même ou utiliser ceux déjà créés. Le syndrome de Stockholm est vaincu. Vous déterminez vous-même de quoi dépend votre projet et comment vous le développerez.


Information technique


Structure d'application ThingJS



Pile technologique


La plate-forme matérielle sélectionnée est le contrôleur ESP32 . La plateforme a été conçue comme indépendante du matériel. Mais, malheureusement, il n'y avait pas de temps pour partitionner sur d'autres appareils.


Pour le développement du firmware, les outils Espressif recommandés sont utilisés . Le firmware est développé en C. Le collecteur cmake. Le projet utilise le concept de composant, également promu par Espressif.


En plus de esp-idf, Mongoose WEB Server est utilisé , ainsi qu'un interpréteur JavaScript Mongoose mJS modifié .


Pour le développement d'applications, JavaScript est utilisé avec le framework VUE 2. Créez des applications à l'aide de webpack. Le gestionnaire de packages est npm. La CLI VUE a été utilisée comme base pour l'environnement de développement.


Afin de standardiser la visualisation des applications et de soulager la créativité de l'interface utilisateur, le package vuetifyjs est inclus dans la plateforme.


Caractéristiques de l'environnement de développement


Pour les développeurs JavaScript (objets virtuels):


  • IDE recommandé - WEBStorm;
  • Tous les bénéfices que VUE CLI et IDE donnent;
  • Débogage intra-système des applications (débogueur mJS sur le contrôleur);
  • MJS implémente la commande debugger, qui vous permet d'appeler le débogueur à un endroit arbitraire;
  • Téléchargement à chaud de fichiers mis à jour sur le contrôleur pendant le développement (les développeurs JavaScript ne peuvent déjà pas vivre sans cette fonctionnalité);
  • Le développement du runtime est associé à un vrai contrôleur. Vous programmez et, là, vous voyez le résultat sur le matériel;
  • ESLint configuré pour comprendre les objets de la plateforme.

Pour les développeurs C (choses physiques):


  • IDE recommandé - CLion;
  • Tous les bénéfices esp-idf et IDE;
  • La plateforme est divisée en composants dans le cadre du concept esp-idf;
  • Intégration facile avec la plate-forme de composants natifs.

Appareils pris en charge


Seul ESP32 est actuellement pris en charge. La puce est populaire en raison de sa disponibilité avec des caractéristiques techniques étonnantes. Sur cette base, de nombreux appareils IoT prêts à l'emploi ont été créés et peuvent être utilisés sous ThingJS.


Comparaison avec les concurrents


Je suggère de ne pas courir aussi loin. Je n'ose pas appeler des concurrents de plateformes commerciales. Et l'open source apparaît et disparaît sans laisser de trace notable. Par conséquent, je n'ai pas fait de comparaison. Cependant, si quelqu'un a un désir, je suis prêt à publier le résultat de son travail ici.


Démarrage rapide


Je dois juste regarder



Je veux essayer


Afin d'essayer la plate-forme sur du matériel réel, vous aurez besoin de tout appareil basé sur ESP32 avec flash 4 Mo et de la possibilité de le flasher via USB. Mais la carte mère ESP32 v2 est la mieux adaptée.



Vous pouvez acheter de telles choses sans aucun problème sur Aliexpress ou Ebay. De plus, il existe même des bureaux de représentation en Russie. J'achète personnellement à Saint-Pétersbourg .


Afin de tester le fonctionnement de l'application de test «Blink», vous devez connecter une LED. Certaines versions des cartes ont une LED préinstallée connectée à GPIO2. Si vous avez un tel tableau, vous ne pouvez rien faire. Le clignotement devrait fonctionner sans mouvements inutiles. Si vous n'avez qu'une seule diode (alimentation), vous devrez connecter la diode indicatrice vous-même. Ce n'est rien de compliqué.


Vous aurez besoin de tout indicateur LED et résistance de 1 à 5K.



La seule chose qui reste est de déployer le package utilisateur sur l'appareil. Vous pouvez le prendre ici . Les instructions de déploiement s'y trouvent.




Blink est un écosystème simple composé d'un appareil virtuel qui implémente l'interface utilisateur et d'un physique. Un appareil virtuel démarre à partir d'un appareil physique lorsqu'il y accède via un navigateur.


Le script est simple. Lors de l'installation de l'application sur un appareil physique, la LED (précédemment connectée à celui-ci) commence à clignoter à une fréquence de 1 Hz. L'utilisateur peut activer ou désactiver le clignotement de la diode depuis l'interface. Vous pouvez regarder la vidéo dans la section "Je ne peux que regarder"


Les sources se trouvent dans le référentiel src / applications / blink. Pour collecter des clignements et jouer avec, vous n'avez besoin que de ce dépôt. Assurez-vous que git, npm et nodejs sont déjà installés.


git clone --branch alpha https://github.com/rpiontik/ThingJS-front cd ThingJS-front npm install npm run build 

Si tout s'est bien passé, vous vous retrouverez avec quelque chose comme ceci:



Félicitations! Vous avez créé votre première application ThingJS. Vous pouvez le trouver dans le dossier dist / apps / blink et essayer immédiatement de l'installer sur l'appareil, guidé par la vidéo de la section "Je ne peux que regarder" .



FichierLa description
scripts / blink.jsLe script installé sur le contrôleur
blink.jsPoint de montage du composant d'application
Blink.vueComposant VUE qui implémente l'interface utilisateur
favicon.svgIcône d'application
langs.jsPack de langue d'application
manifest.jsonManifeste d'application

Vous pouvez vous familiariser avec tous les détails de l'application. Je vais me concentrer sur plusieurs fichiers.



 { "name": "Blink", "vendor" : "rpiontik", "version" : 1, "subversion" : 0, "patch" : 0, "description": { "ru": " ", "en": "Blink Example" }, "components": {...}, "scripts": {...}, "requires" : {...} } 

Comme le nom du fichier l'indique, il s'agit du manifeste d'application. Il contient des métadonnées générales sur le but dont il est facile de deviner. En plus d'eux, il y a trois blocs importants. Examinons-les de près:



 "components": { "blink-app": { "source": "blink.js", "intent_filter": [ { "action": "thingjs.intent.action.MAIN", "category": "thingjs.intent.category.LAUNCH" } ] } } 

Le bloc décrit la base complète des composants de l'application. Le champ «source» pointe vers le point de montage du composant (voir blink.js) et est le point d'entrée de l'assemblage pour webpack ( entrée ). Ainsi, chaque composant sera émis dans un bundle séparé. Ce bundle se chargera au besoin ( chargement paresseux ).


Une structure importante est l' intention_filter . S'il vous arrive de programmer pour Android, vous trouverez quelque chose de familier. Et ne vous trompez pas. Le système génère des événements d'interface et de service auxquels le composant est abonné. Si un événement se produit qui satisfait aux conditions de filtrage, le composant sera chargé et le contrôle sera transféré au point de montage.


Dans ce cas, le composant «blink-app» est abonné à l'événement de lancement du composant d'interface principal de l'application. Lorsque le lanceur démarre l'application, ce composant sera introduit.


Si vous modifiez le manifeste en changeant la ligne


thingjs.intent.category.LAUNCH >> thingjs.intent.category.PREFERENCE


, puis après son assemblage et son installation, il s'avère que l'application a cessé de s'ouvrir sur le bureau. Mais une nouvelle «tuile» est apparue dans la section «Paramètres». En même temps, rien n'a changé fonctionnellement.


Ainsi, nous avons indiqué au lanceur que ce composant est un élément d'interface pour personnaliser notre application. Et ce composant a commencé à apparaître dans les paramètres.



 "scripts": { "entry": "blink", "subscriptions" : ["$-script-restart", "blink"], "modules": { "blink": { "hot_reload": true, "source": "scripts/blink.js", "optimize": false } } } 

Ce bloc est similaire en fonction au bloc «composants», mais il décrit la base des composants d'application côté contrôleur.


Il indique clairement le point d'entrée. Dans le champ «entrée». Séparément, je ferai attention lors de l'installation de l'application, le script ne démarre pas immédiatement. Il n'est lancé que lorsqu'un des événements auxquels le script est abonné se produit.


Le champ «abonnements» est responsable des abonnements. Maintenant, il indique deux événements:


  • $ -script-restart - se produit lorsque le système démarre ou redémarre;
  • blink est un événement personnalisé qui est pertinent pour l'écosystème blink.

Dans le bloc «modules», la description des scripts suit. Je noterai deux champs:


  • hot_reload - si ce champ est défini sur true, puis lorsqu'un fichier est modifié en mode développement, il sera automatiquement téléchargé sur le contrôleur (rechargement à chaud);
  • Optimiser - si vrai, alors lors de la construction du projet, le script sera optimisé et agrégé.


 "requires" : { "interfaces" : { "blink" : { "type" : "bit_port", "required" : true, "default" : 2, "description" : { "ru" : "LED ", "en" : "LED indicator" } } } } 

Vous avez probablement déjà remarqué que lors de l'installation de l'application, vous devez sélectionner la broche sur laquelle la LED clignotera. Cependant, par défaut, il est déjà sélectionné comme GPIO2. Ce bloc est responsable de ces paramètres.


Dans ce bloc, les dépendances sont indiquées. Dans ce cas, pour que l'application fonctionne, elle doit fournir une interface de type «bit_port». Cette interface est une exigence requise (required = true) et par défaut, GPIO2 est spécifié (default = 2). Il sera projeté dans le script avec le nom «clignotement».


Lors de l'installation de l'application, le profil de l'équipement sur lequel les scripts seront déployés est pris en compte. Ce profil répertorie les interfaces disponibles et les ressources matérielles disponibles pour elles (en particulier, les broches et leurs combinaisons). Vérifie la compatibilité des exigences et des équipements. Si l'équipement peut satisfaire aux exigences de l'application, un schéma d'allocation des ressources est présenté à l'utilisateur, dans lequel les ressources primaires sont allouées automatiquement, en tenant compte des recommandations du manifeste. C'est-à-dire à partir de ce même champ "par défaut".


Ainsi, plusieurs applications peuvent être installées sur un même appareil, qui peuvent partager des ressources matérielles entre elles.



 import App from './Blink.vue'; import Langs from './langs'; $includeLang(Langs); $exportComponent('blink-app', App); 

Le fichier est le point de montage du composant annoncé dans le manifeste (voir manifest.js / components). Il enregistre le composant VUE 'blink-app' via la méthode d'abstraction $ exportComponent, et enregistre également le module linguistique.


Vous pouvez demander - pourquoi de telles difficultés? Pourquoi ne pas enregistrer immédiatement le composant VUE que vous spécifiez dans la source? Le fait est que le manifeste décrit les composants publics. Ces composants peuvent être demandés par des applications tierces (dépendances d'exécution). Le point de montage, à son tour, peut enregistrer des composants associés (pour un usage interne), ainsi que des services. Autrement dit, préparez l'environnement des composants.



 export default { name: 'Blink', watch: { blink_state (state) { // Send event to script this.$bus.$emit($consts.EVENTS.UBUS_MESSAGE, 'blink', state); } }, data () { return { blink_state: true }; } }; 

Le code parle de lui-même. Lorsque la propriété «blink_state» est modifiée, un message est envoyé au bus ($ bus) avec la valeur actuelle. C'est tout ce que vous devez faire pour que le script côté contrôleur reçoive la commande souhaitée.



 let active = true; let state = true; // Set port direction $res.blink.direction($res.blink.DIR_MODE_DEF_OUTPUT); // Run background process setInterval(function () { if (active) { // $res - is container with required resources $res.blink.set(state); // Do invert state = !state; } }, 1000); // Event listener // $bus - system bus interface $bus.on(function (event, content, data) { if (event === 'blink') { active = !!JSON.parse(content); } }, null); 

En général, le code est très similaire à l'utilisation classique d'une minuterie en JavaScript. Sauf que ce n'est pas dans ce dialecte de JavaScript. Il est implémenté dans la plateforme. Rencontrez ce mJS . Vous pouvez en savoir plus sur la page officielle du projet.


Pour les besoins de la plateforme, le dialecte est finalisé. Des minuteries ont été introduites, ainsi qu'une commande aussi utile que «débogueur». Eh bien, le débogueur lui-même. Plus d'informations à ce sujet séparément dans la section "Environnement de développement" .


Faites attention aux objets globaux de la plateforme. Ils sont nommés avec le caractère «$».


  • $ res - contient les ressources allouées au script;
  • $ bus - interface de bus .

Parce que l'application a demandé une interface avec le type "bit_port" (voir profile.json / requires) et le nom "blink", elle lui a été donnée comme $ res.blink. L'interface implémente seulement trois fonctions:


  • set (value) - définit le niveau GPIO
  • get () - récupère le niveau GPIO actuel
  • direction (valeur) - définir le mode GPIO

Pour la fonction direction, les constantes disponibles sont décrites via la même interface $ res.blink.: DIR_MODE_DISABLE; DIR_MODE_DEF_INPUT; DIR_MODE_DEF_OUTPUT; DIR_MODE_INPUT_OUTPUT_OD; DIR_MODE_INPUT_OUTPUT.


L'abonnement aux événements de bus se fait via la méthode $ bus.on. Dans ce cas, tous les événements auxquels le script est abonné reviendront au gestionnaire. Le gestionnaire accepte trois paramètres:


  • événement - identifiant d' événement . Dans ce cas, seuls deux sont possibles: «$ -script-restart» et «blink». Dont un seul est traité - clignotement. L'abonnement au second n'est nécessaire que pour que le script soit lancé immédiatement au démarrage du système.
  • contenu - des données peuvent accompagner l'événement. Leur taille est limitée à 126 octets, compte tenu de la longueur de l'identifiant d'événement.
  • données - données transmises lors de la souscription à l'événement en tant que deuxième paramètre. Et dans ce cas, ils sont nuls.

Les interfaces sont extensibles. Vous trouverez ci-dessous une description de la façon de créer votre propre interface.


Implémentation de l'interface


ThingJS vous permet d'étendre les ressources matérielles et de service disponibles via des interfaces spéciales. Vous pouvez créer indépendamment une interface qui implémentera tout complexe, précis, chargé, etc. fonctionnel.


Par exemple, vous pouvez implémenter une interface d'intégration avec votre service cloud. Ou un arrière-plan, processus asynchrone avec lequel le script pourra échanger des messages. Eh bien, ou implémentez le support d'affichage. Il sera également facile à réaliser et à utiliser. Vous et les autres. Certes, pour cela, vous devez savoir C.


Considérez l'implémentation de l'interface bit_port, qui est utilisée dans l'exemple Blink. Pour commencer, vous devez déployer le projet de version alpha du modèle ThingJS . La documentation de déploiement se trouve dans le projet lui-même.


 git clone --branch alpha https://github.com/rpiontik/ThingJS-template 

Le projet comprend des éléments:


  • ThingJS-boards - contient des configurations d'appareils. Jusqu'à présent, seulement ESP32_CORE_BOARD V2 et compatible;
  • ThingJS-extern - bibliothèques de projets tiers que ThingJS utilise;
  • ThingJS-core - noyau de plate-forme;
  • ThingJS-front - environnement de développement d'applications;
  • ThingJS-stdi - interfaces standard.

Nous sommes intéressés par le projet ThingJS-stdi. Sa structure est la suivante:


FichierLa description
implémentation / tgsi_bit_port.cImplémentation de l'interface Bit_port
implémentation / tgsi_bit_port.hFichier d'en-tête d'interface Bit_pro
CMakeLists.txtscript de construction cmake
README.md
sdti_utils.hAides
thingjs_stdi.cPoint de montage d'interface
thingjs_stdi.hFichier d'en-tête de point de montage

En fait, nous ne sommes intéressés que par un seul fichier - implementation / tgsi_bit_port.c. Il contient tout ce qui nécessite une explication distincte.


 void thingjsBitPortRegister(void) { static int thingjs_bit_port_cases[] = DEF_CASES( DEF_CASE(GPIO0), DEF_CASE(GPIO2), DEF_CASE(GPIO3), DEF_CASE(GPIO4), DEF_CASE(GPIO5), DEF_CASE(GPIO12), DEF_CASE(GPIO13), DEF_CASE(GPIO14), DEF_CASE(GPIO15), DEF_CASE(GPIO16), DEF_CASE(GPIO17), DEF_CASE(GPIO18), DEF_CASE(GPIO19), DEF_CASE(GPIO21), DEF_CASE(GPIO22), DEF_CASE(GPIO23), DEF_CASE(GPIO25), DEF_CASE(GPIO26), DEF_CASE(GPIO27), DEF_CASE(GPIO32), DEF_CASE(GPIO33) ); static const struct st_thingjs_interface_manifest interface = { .type = "bit_port", .constructor = thingjsBitPortConstructor, .cases = thingjs_bit_port_cases }; thingjsRegisterInterface(&interface); } 

La fonction thingjsBitPortRegister enregistre un composant dans le noyau ThingJS. Pour ce faire, il appelle la fonction thingjsRegisterInterface, à laquelle il transmet une structure avec une description d'interface.


  • type - identifiant d'interface. C'est lui qui est spécifié comme type dans le fichier manifest.json de l'application;
  • constructeur - lien vers le constructeur de l'interface. La fonction est appelée chaque fois que vous devez créer une nouvelle instance de l'interface;
  • cases est un tableau décrivant les ressources matérielles possibles que l'interface peut utiliser pour son travail. Dans ce cas, il s'agit de GPIO uniques. Mais leurs combinaisons ou dépendances peuvent être décrites séparément.

Le constructeur d'interface monte l'interface dans la machine mJS.


 mjs_val_t thingjsBitPortConstructor(struct mjs *mjs, cJSON *params) { //Validate preset params //The params must have pin number if (!cJSON_IsNumber(params)) return MJS_UNDEFINED; //Get pin number gpio_num_t gpio = params->valueint; //Create mjs object mjs_val_t interface = mjs_mk_object(mjs); /* Configure the IOMUX register for pad BLINK_GPIO (some pads are muxed to GPIO on reset already, but some default to other functions and need to be switched to GPIO. Consult the Technical Reference for a list of pads and their default functions.) */ gpio_pad_select_gpio(gpio); //Add protected property to interface mjs_set(mjs, interface, "gpio", ~0, mjs_mk_number(mjs, gpio)); //Set protected flag mjs_set_protected(mjs, interface, "gpio", ~0, true); //Bind functions mjs_set(mjs, interface, "set", ~0, mjs_mk_foreign_func(mjs, (mjs_func_ptr_t) thingjsBitPortSet)); mjs_set(mjs, interface, "get", ~0, mjs_mk_foreign_func(mjs, (mjs_func_ptr_t) thingjsBitPortGet)); mjs_set(mjs, interface, "direction", ~0, mjs_mk_foreign_func(mjs, (mjs_func_ptr_t) thingjsBitPortDirection)); //Consts mjs_set(mjs, interface, "DIR_MODE_DISABLE", ~0, mjs_mk_number(mjs, GPIO_MODE_DISABLE)); mjs_set(mjs, interface, "DIR_MODE_DEF_INPUT", ~0, mjs_mk_number(mjs, GPIO_MODE_DEF_INPUT)); mjs_set(mjs, interface, "DIR_MODE_DEF_OUTPUT", ~0, mjs_mk_number(mjs, GPIO_MODE_DEF_OUTPUT)); mjs_set(mjs, interface, "DIR_MODE_INPUT_OUTPUT_OD", ~0, mjs_mk_number(mjs, GPIO_MODE_INPUT_OUTPUT_OD)); mjs_set(mjs, interface, "DIR_MODE_INPUT_OUTPUT", ~0, mjs_mk_number(mjs, GPIO_MODE_INPUT_OUTPUT)); //Return mJS interface object return interface; } 

Comment les paramètres sont passés:


  • mjs - contexte d'exécution global;
  • params - paramètres d'initialisation de l'interface. Dans ce cas, il s'agit du numéro GPIO.

Un objet «interface» mJS est créé, où les méthodes et propriétés de l'interface sont montées:


  • gpio - propriété en lecture seule dans laquelle le nombre de GPIO utilisés est stocké;
  • set - méthode pour régler le niveau du signal;
  • get - une méthode pour obtenir le niveau de signal actuel;
  • direction - réglage du mode GPIO;

De plus, des constantes sont montées avec lesquelles les scripts peuvent fonctionner (DIR_MODE_DISABLE, DIR_MODE_DEF_INPUT, etc.).


Après avoir créé l'interface, elle est montée sous un identifiant spécifique (dans l'exemple Blink c'est «blink») dans l'objet global $ res. Un exemple d'utilisation peut être trouvé dans la section Blink ( scripts / blink.js ).


Vous pouvez formater les interfaces en composants ou packages distincts. Cela vous permettra d'assembler le firmware en lego.


Environnement de développement


Développement d'applications


L'environnement de développement d'applications est basé sur la VUE CLI, qui a été affinée pour répondre aux besoins de la plateforme ThingJS. Ceci est une fourche dure, incl. les nouvelles fonctionnalités de VUE CLI valent la peine d'attendre si elles facilitent directement la vie.


Pour déployer l'environnement, vous devez cloner le projet de version alpha de ThingJS-front . Assurez-vous que git, npm et nodejs sont déjà installés.


 git clone --branch alpha https://github.com/rpiontik/ThingJS-front cd ThingJS-front npm install 

Lors du développement, je recommande d'utiliser l'IDE WEBStorm.


La composition et la structure du projet héritent de VUE CLI. Je vais refléter des différences importantes:


  1. Scripts de build retravaillés dans le dossier de build.
  2. Une variable d'environnement «HW_DEVICE_URL» a été ajoutée à la configuration de l'environnement de développement (config / dev.env.js). Il est nécessaire de spécifier un lien vers le périphérique physique avec lequel vous travaillerez.
  3. Le dossier système src / applications est apparu. Il contient des applications qui seront construites automatiquement. En particulier, il contient deux applications: ante (lanceur) et blink (application).
  4. Tout ce qui se trouve au-dessus du dossier src / applications est considéré comme des modules et des ressources de plate-forme. Bien sûr, vous pouvez y apporter des modifications, mais dans ce cas, elles n'apparaîtront dans le contrôleur qu'après le clignotement. T.ch. À moins que vous ne vous fixiez des objectifs spécifiques, il vaut mieux ne pas les toucher.

Pour les tests, vous pouvez immédiatement démarrer le serveur de développement. Bien que vous ne puissiez pas développer complètement sans le matériel physique, cela n'interfère pas avec le développement de l'interface. Et donc, le serveur de développement démarre:


 npm run dev 

Le résultat devrait être quelque chose comme ceci:



En ouvrant le navigateur et en saisissant http://0.0.0.0:8080 dans la barre d'adresse, vous verrez la plateforme en mode développement:



Le processus de développement d'interface lui-même n'est pas très différent du développement frontal classique sur VUE. Sauf qu'il existe des objets de plateforme globale dont vous devez être conscient:


  • $ const - contient des constantes de plate-forme, ainsi que des modules linguistiques;
  • $ bus - bus de données;
  • $ store - stockage global (VUEX).
    À partir des exemples, vous pouvez comprendre comment les utiliser.

Le multilinguisme est mis en œuvre de la manière la plus simple - via le filtre «lang». Spécifiez une constante de langue, elle est interprétée en texte selon la langue de l'interface.


 v-bind:label="'BLINK_SATE' | lang" 

Afin d'évaluer pleinement les capacités de l'environnement de développement, vous aurez besoin d'un contrôleur préparé (assemblé). Vous pouvez assembler le firmware vous-même à partir du projet ou utiliser le firmware et l'utilitaire prêts à l'emploi d'ici .


Après avoir flashé le contrôleur et vous être connecté au réseau, vous devez vous assurer que le contrôleur est accessible via IP depuis votre ordinateur. Pour ce faire, tapez http: // [IP du contrôleur] dans le navigateur. L'interface WEB devrait s'ouvrir.


Vous devez maintenant spécifier l'adresse du contrôleur dans le fichier config / dev.env.js


 'use strict' const merge = require('webpack-merge') const prodEnv = require('./prod.env') module.exports = merge(prodEnv, { NODE_ENV: '"development"', HW_DEVICE_URL: '"http://[IP ]"' //HW_DEVICE_URL: '"http://192.168.8.105"', //HW_DEVICE_URL: '"http://192.168.4.1"', }) 

Si le serveur de développement a été démarré, arrêtez-le et redémarrez-le. À l'avenir, après avoir modifié les fichiers de construction, la configuration et le manifeste d'application, redémarrez toujours le serveur de développement.


Bien que lorsque vous travaillez dans un environnement de développement, toutes les applications qui se trouvent dans le dossier src / application tel qu'installé soient affichées, seules celles qui sont réellement installées sur le contrôleur fonctionneront pleinement. Ce n'est pas une fonctionnalité, mais un bug alpha. À l'avenir, la synchronisation du matériel et de l'environnement de développement se fera automatiquement. Mais pour l'instant, vous devez installer manuellement l'application sur le contrôleur afin que l'environnement la «accroche» et la synchronise avec ce qui est en dev.


Nous assemblons l'application en mode prod:


 npm run prod 

Installez directement les applications collectées sur le contrôleur. Pas via le serveur de développement .


Vous pouvez maintenant commencer le développement. Toutes les modifications que vous apportez à vos fichiers démarreront automatiquement la reconstruction des applications et l'image à l'écran changera (rechargement à chaud). La même règle s'applique aux scripts de contrôleur. Par exemple, vous pouvez ajouter la commande de débogage au script d'application de clignotement et voir le résultat.


 // Event listener // $bus - system bus interface $bus.on(function (event, content, data) { if (event === 'blink') { debugger; active = !!JSON.parse(content); } }, null); 

Désormais, lorsque l'état de la case à cocher de l'application Blink change, l'environnement de développement envoie le message suivant:



Cliquez sur le lien «Démarrer le débogueur» pour accéder au débogueur. La ligne à laquelle l'arrêt s'est produit s'affiche.



Le processus de débogage lui-même n'est pas très différent des autres débogueurs.



Le débogueur est divisé en quatre sections. Dans le code central lui-même. Applications installées à gauche sur le contrôleur. Leur structure et composition. À droite, inspecteur. Le journal est affiché ci-dessous. En bas à gauche se trouve l'état actuel de la communication avec le contrôleur.


L'environnement de débogage est en cours de développement intensif. Il existe de nombreux autres outils de surveillance et de débogage à créer. Je m'excuse à l'avance pour d'éventuels bugs.


Développement de firmware


Le développement du firmware est basé sur le concept proposé par Espressif. Je ne peux pas battre la documentation native à cet égard.


Un référentiel a été préparé pour un démarrage rapide. Il contient des informations de déploiement. Pour un exemple d'utilisation, voir «Implémentation d'une interface» .


L'assemblage est très simple et en une à deux heures, vous assemblerez déjà le firmware sans aucun problème.


Et ensuite?


De plus, si la plateforme intéresse la communauté, il est prévu:


  • Développement d'un environnement de débogage;
  • Standardisation de la dénomination des interfaces, des événements, des composants;
  • Documentation détaillée sur la plateforme;
  • Hébergement cloud pour les choses virtuelles;
  • Référentiels d'exécution
  • Partitionnement vers divers appareils finis.

Aussi, je recherche des personnes qui souhaiteraient développer la plateforme avec moi. Il est déjà très vaste par sa portée et son ambition. Je suppose une coopération égale, dont le but sera de développer la plate-forme à un principes OpenSource à part entière.


Pour entrer dans le projet, vous devez faire de précieuses demandes d'extraction aux composants de la plateforme qui vous intéressent.


Les références


ThingJS:



ThingJS:



:



FAQ


.

Source: https://habr.com/ru/post/fr474356/


All Articles