web-dev-qa-db-fra.com

Comment lire une page Web depuis le port série de l'utilisateur - en 2017?

Je dois réimplémenter un système existant à partir de zéro.

À un moment donné, lorsque l'utilisateur accède à une certaine page Web, le serveur doit lire les données du port série de l'utilisateur.

Actuellement, la page Web dispose d'un contrôle ActiveX; lorsque la page est chargée, le contrôle ActiveX appelle dans un COM DLL sur le PC de l'utilisateur qui lit les données du port série.

Le système a 10 ans. Existe-t-il une "meilleure" façon de mettre cela en œuvre?

Par exemple, la technologie a évolué au cours des dix dernières années. Et cette solution ne semble fonctionner que dans MS IE, qui a maintenant une part de marché d'environ 26% (elle avait, en 2013, la dernière fois que j'ai mis à jour cette question. En février 2107, MS IE = a 3-4% et Edge a 1-2%. Comme Edge est aussi un produit MS, il pourrait supporte Active X - je n'ai pas essayé. Otoh, comme il est nouveau à partir de zéro, il y a de fortes chances que ce ne soit pas le cas).

HTML 5 a-t-il offert de nouvelles possibilités? Qu'en est-il des produits comme Cordova ?

Y a-t-il d'autres possibilités?

Puis-je ajouter un Raspberry Pi pour effectuer la lecture sur le port série et faire en sorte que l'application de navigateur communique avec cela via un service RESTful?


[Mise à jour] @ EuroMicelli a déclaré: "Je vais supposer que vous avez une très bonne raison d'exécuter votre application à partir d'un navigateur Web, au lieu d'une application native". Je ne sais pas car je n'étais pas là quand le projet original a été planifié (et la société qui l'a conçu est maintenant disparue).

Peut-être ne voulaient-ils pas que l'utilisateur final s'interface directement avec la base de données? Peut-être que "basé sur un navigateur" était un nouveau mot à la mode à l'époque? Personnellement, je n'ai aucun problème avec une application de bureau (car je les trouve plus faciles à mettre en œuvre), mais peut-être devrions-nous envisager de rester basé sur un navigateur? (d'ailleurs, je peux gérer l'application de bureau moi-même; c'est uniquement la lecture basée sur un navigateur depuis le port COM qui me conduit à offrir un bonus ;-)

19
Mawg

Pour n'en nommer qu'une autre (plutôt "web-of-things"): le matériel externe.

Selon le cas d'utilisation, vous POUVEZ utiliser un appareil externe à faible coût comme un microcontrôleur Arduino ou un PC embarqué Raspberry-Pi.

Il n'est pas très difficile de construire un simple pont série-service Web sur ce type d'appareils. Vous pouvez utiliser certains projets comme celui-ci, par exemple : https://code.google.com/p/serwebproxy/

Dans un tel scénario, toutes les choses de bas niveau sont gérées par le matériel externe et vous sont proposées par une interface de type service Web (via get/post).

Un autre avantage est que le PC sur lequel s'exécute votre application n'a pas besoin d'un port série (ce qui devient assez rare sur certains systèmes).

À partir de votre application de navigation, vous pouvez interroger le service Web sur l'appareil intégré avec un simple appel ajax. Le navigateur n'aurait besoin d'aucun plugin, la solution fonctionne sur plusieurs plates-formes et est générique et indépendante du développement de technologies de navigateur dans un avenir proche.

7
Chris

Une chose est sûre, vous ne pourrez jamais communiquer avec le matériel de la machine locale sans installer des binaires spéciaux (et les exécuter avec les privilèges appropriés) sur la machine locale. Cependant, cela ne signifie pas que vous devez utiliser un composant ActiveX et rester coincé avec Internet Explorer. Bien sûr, vous pouvez également développer un composant pour chaque navigateur du marché.

Je suggère une autre approche:

  • Écrivez un service Windows (je suppose que votre machine fonctionne sous Windows), configurez-le avec les privilèges nécessaires. Vous devrez de toute façon installer quelque chose sur la machine. Le service peut être implémenté dans n'importe quelle langue.
  • Ajoutez-y des capacités de serveur HTTP (S). Vous pouvez utiliser un grand nombre de technologies ici de WCF à WebAPI.
  • Inventez votre propre protocole de communication via HTTP. Vous pouvez utiliser JSON, Ajax, WebSockets, SignalR, etc.
  • Écrivez un fichier Javascript qui sera compatible avec la plupart des navigateurs du marché - vous n'avez donc qu'à l'écrire une seule fois - qui deviendra votre API COM série. Vous pouvez prendre en charge tous les navigateurs dotés de capacités Javascript et Ajax ( XmlHttpRequest ), avec une seule base de code.

Voici à quoi cela ressemblerait: enter image description here

23
Simon Mourier

Pour minimiser les exigences de bibliothèque externe ou de plugin sur les machines clientes, j'écrirais une applet Java .

Résumé (y compris des liens vers la plupart de la documentation dont vous aurez besoin pour y arriver):

  1. Assurez-vous que vos clients ont Java installé ( la plupart le font déjà et sinon, le navigateur peut l'installer) (c'est le uniquement installation dont vous pourriez avoir besoin pour certains de vos clients pour cette approche)
  2. Choisissez une Java qui ne nécessite aucune installation externe, comme PureJavaComm
  3. Écrivez un très simple applet Java qui fournit des méthodes publiques pour lire le port série
  4. Signez votre applet pour lui accorder les privilèges d'accès système
  5. Incluez l'applet dans votre page Web et simplement appelez les méthodes publiques directement depuis JavaScript

Plus de détails:

Selon StatOwl , environ les deux tiers de toutes les machines ont les frameworks requis Java déjà installés, vous n'aurez peut-être même pas besoin de demander à vos clients de fournir une infrastructure supplémentaire . Et si vous le faites, au moins vous demandez un ( pour la plupart ) logiciel bien entretenu que les gens connaissent et ne seront pas trop sceptiques. Et, la plupart des navigateurs devraient avoir la possibilité d'inviter vos utilisateurs à installer automatiquement le framework Java s'il est manquant).

Il existe plusieurs bibliothèques différentes que vous pouvez utiliser dans Java pour accéder au port série. PureJavaComm semble être l'une des rares, cependant, qui ne nécessite pas de code externe Plus précisément, sous Windows, leur WinAPI Java vous donne un accès direct aux ports COM, y compris tous leurs paramètres, à l'aide d'appels aux bibliothèques Windows déjà installées. Depuis PureJavaComm est une bibliothèque Java uniquement, vous pouvez l'intégrer avec votre applet dans un fichier .jar, que le navigateur télécharge automatiquement, donc il n'y a rien à installer.

Vous pouvez ensuite écrire une applet minimale Java (probablement seulement environ 50-100 lignes au total) qui définit les méthodes publiques pour effectuer l'accès au port série dont vous avez besoin, que vous pouvez ensuite facilement appeler directement à partir de JavaScript: Appel des méthodes d'applet à partir du code JavaScript

La seule chose dont vous devez vous assurer est que vous signez votre applet et que vous encapsulez votre code de port série dans doPrivileged (...) appels pour qu'il soit accordé l'accès système requis à partir de la JVM Sandbox. Pour cela, vous pouvez soit obtenir un certificat SSL acheté (que vous avez peut-être déjà si votre service utilise https) ou générer le vôtre. Si vous générez le vôtre, les utilisateurs seront invités à indiquer s'ils veulent faire confiance à votre applet, mais ils peuvent choisir "toujours faire confiance" et il ne s'agit donc que d'une case à cocher unique et d'un clic correct. Mais au-delà, cela devrait être une solution complètement transparente qui minimisera l'impact sur votre expérience utilisateur.

Alternative 1:

Une autre option serait de simplement abandonner complètement l'interface Web et de fournir à la place un programme Java que les utilisateurs peuvent facilement exécuter (avec ou sans l'installer) directement à partir de votre site Web en utilisant JNLP (Java Web Start) .

Alternative 2 (probablement Windows uniquement):

Je suppose que vous pouvez également utiliser Microsoft Silverlight , ce qui semble également assez largement déployé :

Communication série avec Silverlight 5 (port COM)

Certains pourraient le considérer comme plus "moderne" que Java Applets, mais c'est probablement moins multiplateforme.

Il semble également un peu plus compliqué d'appeler votre code Silverlight à partir de JavaScript, mais il est possible:

Rendre Silverlight Scriptable par JavaScript

10
Markus A.

Vous pouvez utiliser Web USB - mais la compatibilité du navigateur est (actuellement) très faible - Chrome 61 semble être à ce sujet.

Le principal avantage de cette approche est que le périphérique USB est branché sur la machine du navigateur. Apparemment, cela fonctionne pour Chrome pour Android 64 également (non testé).

L'API est à https://wicg.github.io/webusb/ .

Pour un tutoriel, voir https://developers.google.com/web/updates/2016/03/access-usb-devices-on-the-web .

5
AndyS

Probablement pas.

Je vais supposer que vous avez une très bonne raison d'exécuter votre application à partir d'un navigateur Web, au lieu d'une application native. Je peux penser à quelques scénarios où je peux voir que c'est une décision commerciale justifiable.

Même aujourd'hui, avec toutes les avancées modernes, les navigateurs Web sont toujours de fantastiques visualiseurs de documents interactifs, pas des environnements d'exécution universels. Même les fonctionnalités les plus avancées comme les Websockets ont été introduites pour permettre des communications client-serveur sophistiquées, et non en raison d'un intérêt universel à pouvoir un jour tout faire à partir du navigateur.

Il peut y avoir un environnement spécialisé où cela est nativement possible (ne Chrome OS?), Mais ce ne sera pas une solution générale. ouvrir les ports série via une balise de navigateur ou un script. Cela signifie que vous aurez besoin d'une sorte de technologie de plug-in de bas niveau comme ActiveX. ActiveX est une très bonne solution si vous êtes Ok with = IE support uniquement, en particulier s'il est déjà écrit et qu'il fonctionne.

La plupart des gens qui recherchent un accès au port série à partir d'un navigateur font probablement l'acquisition de données à partir de certains matériels propriétaires qu'ils spécifient (construire/vendre?) Et contrôler, tels que les équipements de laboratoire, les scanners de codes à barres, les instruments scientifiques, etc. est également parfaitement acceptable pour spécifier le navigateur requis. Les applications spécialisées font généralement cela.

Si vous voulez toujours regarder un support de navigateur plus large, essayez de regarder la solution proposée pour cette question: Communiquer avec le port série en utilisant Adobe Flash . Je n'ai pas d'expérience avec ce produit, mais s'il fonctionne, il devrait permettre à la plupart des navigateurs de faire ce que vous voulez faire avec une seule base de code, et c'est aussi bon que vous pouvez l'espérer.

Quoi que vous finissiez par faire, cela impliquera très certainement une certaine forme de plug-in tiers.

5
Euro Micelli

L'utilisation du package serialport via Node JS en tant que serveur est une option. Cela fonctionne sur Windows, et apparemment sur Linux et OSX également. Voir https://github.com/ node-serialport/node-serialport .

C'est une solution que j'ai utilisée pour lire les communications micro-bit via USB vers un navigateur. J'ai dû reconstruire le pilote pour Windows (10) avec:

  • npm install --global --production windows-build-tools
  • npm install serialport - build-from-source

J'ai collé une partie de mon code ci-dessous pour référence:

const serialport = require('serialport')

// list serial ports:
const find_microbit = (error, success) => {
  serialport.list((err, ports) => {
    if (err) {
      error(err)
    } else {
      let comName = null
      ports.forEach((port) => {
        if ((port.vendorId == '0D28') && (port.productId == '0204')) {
          comName = port.comName
        }
      })
      if (comName != null) {
        success(comName)
      } else {
        error('Could not find micro:bit.')
      }
    }
  })
}

exports.get_serial = (error, success) => {
  find_microbit(error, (comName) => {
    let serial = new serialport(comName, {baudRate: 115200, parser: serialport.parsers.readline('\n')}, (err) => {
      if (err) {
        error(err)
      } else {
        success(serial)
      }
    })
  })
}
/* e.g.
get_serial((err)=>{console.log("Error:" + err)},
    (serial)=>{
        serial.on('data', (data) => {
            let ubit = JSON.parse(data)
            if (ubit.button == 'a') {
                console.log('Button A Pressed')
            }
            if (ubit.button == 'b') {
                console.log('Button B Pressed')
            }
            if (ubit.ir) {
                console.log('Visitor detected')
            }
        })
    })
    */

Cette approche fonctionne - pour moi - mais cela peut prendre du temps pour la faire fonctionner. Ce n'est pas, à mon avis, une solution évidente ou simple. Cela nécessite une bonne quantité de savoir-faire technique - et je pense que c'est beaucoup plus complexe et "délicat" qu'il ne devrait l'être.

En particulier - la reconstruction de la bibliothèque n'est pas quelque chose que je m'attendrais à faire en utilisant Node JS. L'un des effets possibles est que vous auriez besoin de reconstruire les binaires du port série pour une plate-forme différente.

2
AndyS