Aller au contenu principal

Accès aux périphériques

Comme les navigateurs basés sur Chromium, Electron fournit un accès au matériel du périphérique via des API Web. Ces API fonctionnent pour la plupart, comme dans un navigateur, mais il y a quelques différences qui doivent être prises en compte. La principale différence entre Electron et les navigateurs est ce qui se passe lorsque l'accès à l'appareil est demandé . Dans un navigateur, les utilisateurs se voient présenter une popup où ils peuvent accorder l' accès à un appareil individuel. Dans Electron des API sont fournies pouvant être utilisées par un développeur pour choisir automatiquement un périphérique ou demander aux utilisateurs de choisir un périphérique via une interface créée par un développeur.

API Web Bluetooth

L’API Web Bluetooth peut être utilisée pour communiquer avec des périphériques Bluetooth. In order to use this API in Electron, developers will need to handle the select-bluetooth-device event on the webContents associated with the device request.

Additionally, ses.setBluetoothPairingHandler(handler) can be used to handle pairing to bluetooth devices on Windows or Linux when additional validation such as a pin is needed.

Exemple

Cet exemple montre une application Electron qui sélectionne automatiquement le premier périphérique Bluetooth disponible lorsque le bouton Test Bluetooth est cliqué.

const { app, BrowserWindow, ipcMain } = require('electron/main')
const path = require('node:path')

let bluetoothPinCallback
let selectBluetoothCallback

function createWindow () {
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})

mainWindow.webContents.on('select-bluetooth-device', (event, deviceList, callback) => {
event.preventDefault()
selectBluetoothCallback = callback
const result = deviceList.find((device) => {
return device.deviceName === 'test'
})
if (result) {
callback(result.deviceId)
} else {
// The device wasn't found so we need to either wait longer (eg until the
// device is turned on) or until the user cancels the request
}
})

ipcMain.on('cancel-bluetooth-request', (event) => {
selectBluetoothCallback('')
})

// Listen for a message from the renderer to get the response for the Bluetooth pairing.
ipcMain.on('bluetooth-pairing-response', (event, response) => {
bluetoothPinCallback(response)
})

mainWindow.webContents.session.setBluetoothPairingHandler((details, callback) => {
bluetoothPinCallback = callback
// Send a message to the renderer to prompt the user to confirm the pairing.
mainWindow.webContents.send('bluetooth-pairing-request', details)
})

mainWindow.loadFile('index.html')
}

app.whenReady().then(() => {
createWindow()

app.on('activate', function () {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})

app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit()
})

API WebHID

L' API WebHID peut être utilisée pour accéder aux périphériques HID tels que les claviers et les manettes. Electron fournit plusieurs API pour travailler avec l'API WebHID:

  • The select-hid-device event on the Session can be used to select a HID device when a call to navigator.hid.requestDevice is made. Additionally the hid-device-added and hid-device-removed events on the Session can be used to handle devices being plugged in or unplugged when handling the select-hid-device event. Note: Ces événements pourront se déclencher tant que la fonction de callback de select-hid-device n'a pas pas encore été appelée. Ils ne sont pas, d'ailleurs, destinés à être utilisés comme écouteurs génériques de port série.
  • ses.setDevicePermissionHandler(handler) peut être utilisé pour fournir une autorisation par défaut aux périphériques sans avoir à en faire la demande préalablement via navigator.hid.requestDevice. De plus, le comportement par défaut d'Electron est de stocker les autorisations accordées à l'appareil pendant la durée de vie du WebContents. Si un stockage à plus long terme est nécessaire, le développeur peut stocker les autorisations accordées à l'appareil (par exemple lors de la gestion de l'événement select-hid-device) puis les lire à partir de ce stockage avec setDevicePermissionHandler.
  • ses.setPermissionCheckHandler(handler) can be used to disable HID access for specific origins.

Blocklist

Par défaut, Electron utilise la même liste noire que celle utilisée par Chromium. Si vous souhaitez outrepasser ce comportement, vous pouvez le faire en définissant le drapeau disable-hid-blocklist:

app.commandLine.appendSwitch('disable-hid-blocklist')

Exemple

This example demonstrates an Electron application that automatically selects HID devices through ses.setDevicePermissionHandler(handler) and through select-hid-device event on the Session when the Test WebHID button is clicked.

const { app, BrowserWindow } = require('electron/main')

function createWindow () {
const mainWindow = new BrowserWindow({
width: 800,
height: 600
})

mainWindow.webContents.session.on('select-hid-device', (event, details, callback) => {
// Add events to handle devices being added or removed before the callback on
// `select-hid-device` is called.
mainWindow.webContents.session.on('hid-device-added', (event, device) => {
console.log('hid-device-added FIRED WITH', device)
// Optionally update details.deviceList
})

mainWindow.webContents.session.on('hid-device-removed', (event, device) => {
console.log('hid-device-removed FIRED WITH', device)
// Optionally update details.deviceList
})

event.preventDefault()
if (details.deviceList && details.deviceList.length > 0) {
callback(details.deviceList[0].deviceId)
}
})

mainWindow.webContents.session.setPermissionCheckHandler((webContents, permission, requestingOrigin, details) => {
if (permission === 'hid' && details.securityOrigin === 'file:///') {
return true
}
})

mainWindow.webContents.session.setDevicePermissionHandler((details) => {
if (details.deviceType === 'hid' && details.origin === 'file://') {
return true
}
})

mainWindow.loadFile('index.html')
}

app.whenReady().then(() => {
createWindow()

app.on('activate', function () {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})

app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit()
})

API Web Serial

L' API Web Serial peut être utilisée pour accéder aux périphériques série qui sont connectés par port série, USB, ou Bluetooth. In order to use this API in Electron, developers will need to handle the select-serial-port event on the Session associated with the serial port request.

Il existe plusieurs API supplémentaires pour travailler avec l'API Web Serial :

  • The serial-port-added and serial-port-removed events on the Session can be used to handle devices being plugged in or unplugged when handling the select-serial-port event. Note: Ces événements pourront se déclencher tant que la fonction de callback de select-serial-port n'a pas pas encore étét appelée. Ils ne sont pas d'ailleurs destinés à être utilisés comme écouteurs génériques de port série.
  • ses.setDevicePermissionHandler(handler) peut être utilisé pour fournir une autorisation par défaut aux périphériques sans avoir à en faire la demande préalablement via navigator.serial.requestPort. De plus, le comportement par défaut d'Electron est de stocker les autorisations accordées à l'appareil pendant la durée de vie du WebContents. Si un stockage à plus long terme est nécessaire, le développeur peut stocker les autorisations accordées à l'appareil (par exemple lors de la gestion de l'événement select-serial-port) puis les lire à partir de ce stockage avec setDevicePermissionHandler.
  • ses.setPermissionCheckHandler(handler) can be used to disable serial access for specific origins.

Exemple

This example demonstrates an Electron application that automatically selects serial devices through ses.setDevicePermissionHandler(handler) as well as demonstrating selecting the first available Arduino Uno serial device (if connected) through select-serial-port event on the Session when the Test Web Serial button is clicked.

const { app, BrowserWindow } = require('electron/main')

function createWindow () {
const mainWindow = new BrowserWindow({
width: 800,
height: 600
})

mainWindow.webContents.session.on('select-serial-port', (event, portList, webContents, callback) => {
// Add listeners to handle ports being added or removed before the callback for `select-serial-port`
// is called.
mainWindow.webContents.session.on('serial-port-added', (event, port) => {
console.log('serial-port-added FIRED WITH', port)
// Optionally update portList to add the new port
})

mainWindow.webContents.session.on('serial-port-removed', (event, port) => {
console.log('serial-port-removed FIRED WITH', port)
// Optionally update portList to remove the port
})

event.preventDefault()
if (portList && portList.length > 0) {
callback(portList[0].portId)
} else {
// eslint-disable-next-line n/no-callback-literal
callback('') // Could not find any matching devices
}
})

mainWindow.webContents.session.setPermissionCheckHandler((webContents, permission, requestingOrigin, details) => {
if (permission === 'serial' && details.securityOrigin === 'file:///') {
return true
}

return false
})

mainWindow.webContents.session.setDevicePermissionHandler((details) => {
if (details.deviceType === 'serial' && details.origin === 'file://') {
return true
}

return false
})

mainWindow.loadFile('index.html')

mainWindow.webContents.openDevTools()
}

app.whenReady().then(() => {
createWindow()

app.on('activate', function () {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})

app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit()
})

API WebUSB

L' API WebUSB peut être utilisée pour accéder aux périphériques USB. Electron fournit plusieurs API pour travailler avec l'API WebUSB :

  • The select-usb-device event on the Session can be used to select a USB device when a call to navigator.usb.requestDevice is made. Additionally the usb-device-added and usb-device-removed events on the Session can be used to handle devices being plugged in or unplugged when handling the select-usb-device event. Note: Ces deux événements ne se déclenchent qu'après l'appel à la callback de select-usb-device . Ils ne sont pas destinés à être utilisés comme un écouteur de périphérique Usb générique.
  • The usb-device-revoked event on the Session can be used to respond when device.forget() is called on a USB device.
  • ses.setDevicePermissionHandler(handler) peut être utilisé pour fournir une autorisation par défaut aux périphériques sans avoir à en faire la demande préalablement via navigator.usb.requestDevice. De plus, le comportement par défaut d'Electron est de stocker les autorisations accordées à l'appareil pendant la durée de vie du WebContents. Si un stockage à plus long terme est nécessaire, un développeur peut stocker les autorisations de périphérique accordées (par exemple lors de la gestion l’événement select-usb-device) afin de pouvoir ensuite relire à partir de ce stockage avec setDevicePermissionHandler.
  • ses.setPermissionCheckHandler(handler) can be used to disable USB access for specific origins.
  • `ses.setUSBProtectedClassesHandler can be used to allow usage of protected USB classes that are not available by default.

Exemple

This example demonstrates an Electron application that automatically selects USB devices (if they are attached) through ses.setDevicePermissionHandler(handler) and through select-usb-device event on the Session when the Test WebUSB button is clicked.

const { app, BrowserWindow } = require('electron/main')

function createWindow () {
const mainWindow = new BrowserWindow({
width: 800,
height: 600
})

let grantedDeviceThroughPermHandler

mainWindow.webContents.session.on('select-usb-device', (event, details, callback) => {
// Add events to handle devices being added or removed before the callback on
// `select-usb-device` is called.
mainWindow.webContents.session.on('usb-device-added', (event, device) => {
console.log('usb-device-added FIRED WITH', device)
// Optionally update details.deviceList
})

mainWindow.webContents.session.on('usb-device-removed', (event, device) => {
console.log('usb-device-removed FIRED WITH', device)
// Optionally update details.deviceList
})

event.preventDefault()
if (details.deviceList && details.deviceList.length > 0) {
const deviceToReturn = details.deviceList.find((device) => {
return !grantedDeviceThroughPermHandler || (device.deviceId !== grantedDeviceThroughPermHandler.deviceId)
})
if (deviceToReturn) {
callback(deviceToReturn.deviceId)
} else {
callback()
}
}
})

mainWindow.webContents.session.setPermissionCheckHandler((webContents, permission, requestingOrigin, details) => {
if (permission === 'usb' && details.securityOrigin === 'file:///') {
return true
}
})

mainWindow.webContents.session.setDevicePermissionHandler((details) => {
if (details.deviceType === 'usb' && details.origin === 'file://') {
if (!grantedDeviceThroughPermHandler) {
grantedDeviceThroughPermHandler = details.device
return true
} else {
return false
}
}
})

mainWindow.webContents.session.setUSBProtectedClassesHandler((details) => {
return details.protectedClasses.filter((usbClass) => {
// Exclude classes except for audio classes
return usbClass.indexOf('audio') === -1
})
})

mainWindow.loadFile('index.html')
}

app.whenReady().then(() => {
createWindow()

app.on('activate', function () {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})

app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit()
})