|
2 | 2 |
|
3 | 3 | ## How it Works |
4 | 4 |
|
5 | | -Using a combination of the manifest file and WebUSB APIs, we can search for and detect connected USB devices inside of a container application. |
| 5 | +Using a combination of the manifest file and WebUSB/WebHID APIs, we permission and get connected USB devices inside of a container application. |
6 | 6 |
|
7 | 7 | ## Get Started |
8 | 8 |
|
@@ -36,14 +36,219 @@ npm run client |
36 | 36 |
|
37 | 37 | ### What you will see |
38 | 38 |
|
39 | | -1. An Platform Window with a button that leads you to documentation around WebUSB API usage, along with another button that should detect a plugged in device and display it in a list below. |
| 39 | +#### Main App View (app.html) |
40 | 40 |
|
41 | | -## A note about this example |
| 41 | +- A view loaded into a platform window. |
| 42 | +- It contains a button to open up the HERE related documentation in a new window. |
| 43 | +- It contains a button to open up a window in your default browser (Chrome/Edge) called device-identifier.html |
| 44 | +- Form elements to say whether you are targeting a USB or HID Device, the VendorID and the ProductID of the device you are looking to test against (these details can be return by the device-identifier.html page). |
| 45 | +- It contains a button that will take the data from the form elements to create a new window with the correct permissions to allow a connection to the specified device (device-connector.html). |
42 | 46 |
|
43 | | -This is an example of how to use OpenFin APIs to configure OpenFin Container. Its purpose is to provide an example and suggestions. **DO NOT** assume that it contains production-ready code. Please use this as a guide and provide feedback. Thanks! |
| 47 | + |
44 | 48 |
|
45 | | -There are 3 things you should know when trying to detect and use USB devices (Printers, etc..) alongside your Container: |
| 49 | +#### Device Identifier (device-identifier.html) |
46 | 50 |
|
47 | | -1. Make sure to add the necessary permissions to the manifest file, specifically, the WebAPI and Devices sections. |
48 | | -2. Use best practices with the API by reading more [here](https://developer.mozilla.org/en-US/docs/Web/API/WebUSB_API). |
49 | | -3. If you have any additional questions, please email [Here.io Support ](mailto:[email protected]). |
| 51 | +Launched from the main window into your default desktop browser (e.g. Chrome/Edge). This page provides two buttons so you can pick a USB or HID device. On selection the results will be presented so that you can manually add the VendorID and ProductID on the main page or you can use a button to return to the pass the details back to the form elements within the platform. |
| 52 | + |
| 53 | + |
| 54 | + |
| 55 | +#### Device Connector (device-connector.html) |
| 56 | + |
| 57 | +Launched from the main window using the form details related to the target device. The permissions of the launched window will include the correct details for the connection and the window will show a code section showing some example code and a log section that shows what's happening. There is an option to open a connection to the device through a button. |
| 58 | + |
| 59 | + |
| 60 | + |
| 61 | +## Example Loom |
| 62 | + |
| 63 | +<https://www.loom.com/share/63d31b30454e478fbc415724fb28ec82?sid=1480153e-c2a3-4208-98b9-1b2c45df554b> |
| 64 | + |
| 65 | +## Required Permissions |
| 66 | + |
| 67 | +Permissions need to be defined in the window/view that wants to connect to a USB/HID device. This lets developers connect to the device without requiring user interaction. |
| 68 | + |
| 69 | +This can be done in a number of places and must include the webAPIs permissions to access usb and hid devices as well as the list of devices you are allowing by providing their vendor and product Ids: |
| 70 | + |
| 71 | +### Manifest - startup_app |
| 72 | + |
| 73 | +If you have a classic manifest where you are using a startup_app definition and you want the entry (main) window to be able to connect to a device then you can have the following defined: |
| 74 | + |
| 75 | +```json |
| 76 | +{ |
| 77 | + "startup_app": { |
| 78 | + "permissions": { |
| 79 | + "webAPIs": ["hid", "usb"], |
| 80 | + "devices": [ |
| 81 | + { |
| 82 | + "vendorId": 3034, |
| 83 | + "productId": 21783 |
| 84 | + } |
| 85 | + ] |
| 86 | + } |
| 87 | + } |
| 88 | +} |
| 89 | +``` |
| 90 | + |
| 91 | +### Manifest - platform |
| 92 | + |
| 93 | +If you have a platform app with a custom platform provider window and you want the platform provider to connect then you will need to define the rules inside of the platform section of your manifest. \*\*Please note if any child window/view needs access to usb/hid devices then the platform should define the permission (it doesn't need to specify the devices but the permission should be available at the root level). |
| 94 | + |
| 95 | +```json |
| 96 | +{ |
| 97 | + "platform": { |
| 98 | + "permissions": { |
| 99 | + "webAPIs": ["hid", "usb"], |
| 100 | + "devices": [ |
| 101 | + { |
| 102 | + "vendorId": 3034, |
| 103 | + "productId": 21783 |
| 104 | + } |
| 105 | + ] |
| 106 | + } |
| 107 | + } |
| 108 | +} |
| 109 | +``` |
| 110 | + |
| 111 | +#### Window Level |
| 112 | + |
| 113 | +You can either set the window permissions for all windows through Default Window Options (if you are using a platform manifest setup) or for a specific window through Window Options when you launch it. |
| 114 | + |
| 115 | +##### Default Window Options |
| 116 | + |
| 117 | +```json |
| 118 | +{ |
| 119 | + "platform": { |
| 120 | + "permissions": { |
| 121 | + "webAPIs": ["hid", "usb"] |
| 122 | + }, |
| 123 | + "defaultWindowOptions": { |
| 124 | + "permissions": { |
| 125 | + "webAPIs": ["hid", "usb"], |
| 126 | + "devices": [ |
| 127 | + { |
| 128 | + "vendorId": 3034, |
| 129 | + "productId": 21783 |
| 130 | + } |
| 131 | + ] |
| 132 | + } |
| 133 | + } |
| 134 | + } |
| 135 | +} |
| 136 | +``` |
| 137 | + |
| 138 | +##### Window Options |
| 139 | + |
| 140 | +If you only want a specific window to have this permission then you can specify the permission as part of the window options when launching it (this is the approach used by the sample when it is launching a window targeting a specific device). |
| 141 | + |
| 142 | +```json |
| 143 | +{ |
| 144 | + "url": "The url to load alongside other settings", |
| 145 | + "permissions": { |
| 146 | + "webAPIs": ["hid", "usb"], |
| 147 | + "devices": [ |
| 148 | + { |
| 149 | + "vendorId": 3034, |
| 150 | + "productId": 21783 |
| 151 | + } |
| 152 | + ] |
| 153 | + } |
| 154 | +} |
| 155 | +``` |
| 156 | + |
| 157 | +#### View Level |
| 158 | + |
| 159 | +If you are using a platform manifest and views then you can either set the view permissions for all views through Default View Options or for a specific view through View Options when you launch it. |
| 160 | + |
| 161 | +##### Default View Options |
| 162 | + |
| 163 | +```json |
| 164 | +{ |
| 165 | + "platform": { |
| 166 | + "permissions": { |
| 167 | + "webAPIs": ["hid", "usb"] |
| 168 | + }, |
| 169 | + "defaultViewOptions": { |
| 170 | + "permissions": { |
| 171 | + "webAPIs": ["hid", "usb"], |
| 172 | + "devices": [ |
| 173 | + { |
| 174 | + "vendorId": 3034, |
| 175 | + "productId": 21783 |
| 176 | + } |
| 177 | + ] |
| 178 | + } |
| 179 | + } |
| 180 | + } |
| 181 | +} |
| 182 | +``` |
| 183 | + |
| 184 | +##### View Options |
| 185 | + |
| 186 | +```json |
| 187 | +{ |
| 188 | + "permissions": { |
| 189 | + "webAPIs": ["hid", "usb"], |
| 190 | + "devices": [ |
| 191 | + { |
| 192 | + "vendorId": 3034, |
| 193 | + "productId": 21783 |
| 194 | + } |
| 195 | + ] |
| 196 | + } |
| 197 | +} |
| 198 | +``` |
| 199 | + |
| 200 | +##### Domain Settings |
| 201 | + |
| 202 | +If your platform is loading or navigating to a number of different domains and you only want your specific domain to be able to connect to the device then we would recommend using Domain Settings. If you are already familiar with domain settings we generally recommend them over window/view level settings as they ensure only your domain can utilize a permission. |
| 203 | + |
| 204 | +<https://resources.here.io/docs/javascript/stable/interfaces/OpenFin.DomainSettings.html> |
| 205 | + |
| 206 | +## Code Example |
| 207 | + |
| 208 | +You do not need to request the device as the permissions have already given access. |
| 209 | + |
| 210 | +You can get the devices and then open the one you wish using standard JavaScript APIs. The example below is using the HID API but the sample will provide code snippets for USB or HID when run. |
| 211 | + |
| 212 | +```js |
| 213 | +// Listen for device connection and disconnection events |
| 214 | +navigator.hid.addEventListener('disconnect', (event) => { |
| 215 | + console.log('HID disconnected: ' + event.device.productName); |
| 216 | +}); |
| 217 | +navigator.hid.addEventListener('connect', (event) => { |
| 218 | + console.log('HID connected: ' + event.device.productName); |
| 219 | +}); |
| 220 | + |
| 221 | +// Getting HID devices |
| 222 | +// You don't need to call requestDevice as the device has already been given permissions through the manifest/window/view permission settings. You can call getDevices to interact with the device. |
| 223 | +const devices = await navigator.hid.getDevices(); |
| 224 | +console.log('Found ' + devices.length + ' HID devices.'); |
| 225 | +devices.forEach((device, index) => { |
| 226 | + console.log( |
| 227 | + 'Device ' + |
| 228 | + (index + 1) + |
| 229 | + ': Product Name: ' + |
| 230 | + device.productName + |
| 231 | + ', Vendor ID: ' + |
| 232 | + device.vendorId + |
| 233 | + ', Product ID: ' + |
| 234 | + device.productId |
| 235 | + ); |
| 236 | +}); |
| 237 | + |
| 238 | +// Selecting the first device (if any) |
| 239 | +const device = devices.length > 0 ? devices[0] : null; |
| 240 | + |
| 241 | +// Opening the device |
| 242 | +if (device) { |
| 243 | + await device.open(); |
| 244 | + console.log('Device opened:', device.productName); |
| 245 | + // Add event listeners for input reports |
| 246 | + device.addEventListener('inputreport', (event) => { |
| 247 | + // perform custom logic here. The below is just an example. |
| 248 | + const data = new Uint8Array(event.data.buffer); |
| 249 | + console.log('Input report received:', data); |
| 250 | + }); |
| 251 | +} else { |
| 252 | + console.log('No device selected'); |
| 253 | +} |
| 254 | +``` |
0 commit comments