|
18 | 18 | *
|
19 | 19 | */
|
20 | 20 |
|
21 |
| -import { interval } from 'rxjs'; |
22 |
| -import { |
23 |
| - distinctUntilChanged, filter, startWith, takeUntil |
24 |
| -} from 'rxjs/operators'; |
| 21 | +import WebSerialDaemon from './web-serial-daemon'; |
| 22 | +import ChromeAppDaemon from './chrome-app-daemon'; |
25 | 23 |
|
26 |
| -import webSerialApiBoards from './web-serial-supported-boards'; |
| 24 | +/** |
| 25 | + * ChromeOSDaemon is a new implementation for ChromeOS which allows |
| 26 | + + to select the legacy Chrome app or the new BETA web serial API, |
| 27 | + * based on the the existance of a specific key in the browser CacheStorage, |
| 28 | + * which in turn means that the user has installed it from the Google Play Store |
| 29 | + * |
| 30 | + */ |
| 31 | +export default function ChromeOsDaemon(boardsUrl, options) { |
27 | 32 |
|
28 |
| -import Daemon from './daemon'; |
29 |
| - |
30 |
| -const POLLING_INTERVAL = 2000; |
31 |
| - |
32 |
| -// class WebSerialPort { |
33 |
| -// sendVersion () {} |
34 |
| -// sendSupportedBoards () {} |
35 |
| -// listPorts () {} |
36 |
| -// log (message, category) {} |
37 |
| -// upload (data) {} |
38 |
| -// openPort (data) {} |
39 |
| -// closePort (data) {} |
40 |
| -// writePort (data) {} |
41 |
| -// onMessage (message) {} |
42 |
| -// onDisconnect (message) {} |
43 |
| -// onSerialData (name, data) {} |
44 |
| -// } |
45 |
| -export default class ChromeOsDaemon extends Daemon { |
46 |
| - constructor(boardsUrl, chromeExtensionId) { |
47 |
| - super(boardsUrl); |
48 |
| - this.chromeExtensionId = chromeExtensionId; |
49 |
| - this.channel = null; |
50 |
| - this.init(); |
51 |
| - } |
52 |
| - |
53 |
| - init() { |
54 |
| - this.initChromeApp(); |
55 |
| - this.initWebSerialApi(); |
56 |
| - } |
57 |
| - |
58 |
| - /* ChromeApp specific */ |
59 |
| - initChromeApp() { |
60 |
| - this.openChannel(() => this.channel.postMessage({ |
61 |
| - command: 'listPorts' |
62 |
| - })); |
63 |
| - this.agentFound |
64 |
| - .pipe(distinctUntilChanged()) |
65 |
| - .subscribe(agentFound => { |
66 |
| - if (!agentFound) { |
67 |
| - this.findApp(); |
68 |
| - } |
69 |
| - }); |
70 |
| - } |
71 |
| - |
72 |
| - /* WebSerialApi specific */ |
73 |
| - // eslint-disable-next-line class-methods-use-this |
74 |
| - initWebSerialApi() { |
75 |
| - // nothing to be done, the channel is open |
76 |
| - } |
77 |
| - |
78 |
| - /* ChromeApp specific */ |
79 |
| - findApp() { |
80 |
| - interval(POLLING_INTERVAL) |
81 |
| - .pipe(startWith(0)) |
82 |
| - .pipe(takeUntil(this.channelOpen.pipe(filter(status => status)))) |
83 |
| - .subscribe(() => this._appConnect()); |
84 |
| - } |
85 |
| - |
86 |
| - /** |
87 |
| - * Instantiate connection and events listeners for chrome app |
88 |
| - */ |
89 |
| - _appConnect() { |
90 |
| - if (chrome.runtime) { |
91 |
| - this.channel = chrome.runtime.connect(this.chromeExtensionId); |
92 |
| - this.channel.onMessage.addListener(message => { |
93 |
| - if (message.version) { |
94 |
| - this.agentInfo = message; |
95 |
| - this.agentFound.next(true); |
96 |
| - this.channelOpen.next(true); |
97 |
| - } |
98 |
| - else { |
99 |
| - this.appMessages.next(message); |
100 |
| - } |
101 |
| - }); |
102 |
| - this.channel.onDisconnect.addListener(() => { |
103 |
| - this.channelOpen.next(false); |
104 |
| - this.agentFound.next(false); |
105 |
| - }); |
106 |
| - } |
107 |
| - } |
108 |
| - |
109 |
| - handleAppMessage(message) { |
110 |
| - if (message.ports) { |
111 |
| - this.handleListMessage(message); |
112 |
| - } |
113 |
| - |
114 |
| - if (message.supportedBoards) { |
115 |
| - this.supportedBoards.next(message.supportedBoards); |
116 |
| - } |
117 |
| - |
118 |
| - if (message.serialData) { |
119 |
| - this.serialMonitorMessages.next(message.serialData); |
120 |
| - } |
121 |
| - |
122 |
| - if (message.uploadStatus) { |
123 |
| - this.handleUploadMessage(message); |
124 |
| - } |
125 |
| - |
126 |
| - if (message.err) { |
127 |
| - this.uploading.next({ status: this.UPLOAD_ERROR, err: message.Err }); |
128 |
| - } |
129 |
| - } |
130 |
| - |
131 |
| - handleListMessage(message) { |
132 |
| - const newPorts = message.ports; |
133 |
| - // remove web serial API boards |
134 |
| - const lastDevices = this.devicesList.getValue() |
135 |
| - if (!Daemon.devicesListAreEquals(lastDevices.serial, newPorts)) { |
136 |
| - this.devicesList.next({ |
137 |
| - serial: newPorts.map(port => ({ |
138 |
| - Name: port.name, |
139 |
| - SerialNumber: port.serialNumber, |
140 |
| - IsOpen: port.isOpen, |
141 |
| - VendorID: port.vendorId, |
142 |
| - ProductID: port.productId |
143 |
| - })), |
144 |
| - network: [] |
145 |
| - }); |
146 |
| - } |
| 33 | + // const { cacheStorageKey } = options; |
| 34 | + if (false) { // typeof options === 'string') { |
| 35 | + console.dir('******** BEGIN: chrome-os-daemon:40 ********'); |
| 36 | + console.dir('CREATING CHROME APP', { depth: null, colors: true }); |
| 37 | + console.dir('******** END: chrome-os-daemon:40 ********'); |
| 38 | + // chrome app |
| 39 | + this.flavour = new ChromeAppDaemon(boardsUrl, options); |
147 | 40 | }
|
148 |
| - |
149 |
| - /** |
150 |
| - * Send 'close' command to all the available serial ports |
151 |
| - */ |
152 |
| - closeAllPorts() { |
153 |
| - const devices = this.devicesList.getValue().serial; |
154 |
| - devices.forEach(device => { |
155 |
| - this.channel.postMessage({ |
156 |
| - command: 'closePort', |
157 |
| - data: { |
158 |
| - name: device.Name |
159 |
| - } |
160 |
| - }); |
161 |
| - }); |
162 |
| - } |
163 |
| - |
164 |
| - /** |
165 |
| - * Send 'message' to serial port |
166 |
| - * @param {string} port the port name |
167 |
| - * @param {string} message the text to be sent to serial |
168 |
| - */ |
169 |
| - writeSerial(port, message) { |
170 |
| - this.channel.postMessage({ |
171 |
| - command: 'writePort', |
172 |
| - data: { |
173 |
| - name: port, |
174 |
| - data: message |
175 |
| - } |
176 |
| - }); |
177 |
| - } |
178 |
| - |
179 |
| - /** |
180 |
| - * Request serial port open |
181 |
| - * @param {string} port the port name |
182 |
| - */ |
183 |
| - openSerialMonitor(port, baudrate) { |
184 |
| - if (this.serialMonitorOpened.getValue()) { |
185 |
| - return; |
186 |
| - } |
187 |
| - const serialPort = this.devicesList.getValue().serial.find(p => p.Name === port); |
188 |
| - if (!serialPort) { |
189 |
| - return this.serialMonitorError.next(`Can't find port ${port}`); |
190 |
| - } |
191 |
| - this.appMessages |
192 |
| - .pipe(takeUntil(this.serialMonitorOpened.pipe(filter(open => open)))) |
193 |
| - .subscribe(message => { |
194 |
| - if (message.portOpenStatus === 'success') { |
195 |
| - this.serialMonitorOpened.next(true); |
196 |
| - } |
197 |
| - if (message.portOpenStatus === 'error') { |
198 |
| - this.serialMonitorError.next(`Failed to open serial ${port}`); |
199 |
| - } |
200 |
| - }); |
201 |
| - this.channel.postMessage({ |
202 |
| - command: 'openPort', |
203 |
| - data: { |
204 |
| - name: port, |
205 |
| - baudrate |
206 |
| - } |
207 |
| - }); |
| 41 | + else { |
| 42 | + console.dir('******** BEGIN: chrome-os-daemon:47 ********'); |
| 43 | + console.dir('CREATING WEB SERIAL', { depth: null, colors: true }); |
| 44 | + console.dir('******** END: chrome-os-daemon:47 ********'); |
| 45 | + // const { cacheStorageKey } = options; |
| 46 | + this.flavour = new WebSerialDaemon(boardsUrl); |
208 | 47 | }
|
209 | 48 |
|
210 |
| - /** |
211 |
| - * Request serial port close |
212 |
| - * @param {string} port the port name |
213 |
| - */ |
214 |
| - closeSerialMonitor(port) { |
215 |
| - if (!this.serialMonitorOpened.getValue()) { |
216 |
| - return; |
217 |
| - } |
218 |
| - const serialPort = this.devicesList.getValue().serial.find(p => p.Name === port); |
219 |
| - if (!serialPort) { |
220 |
| - return this.serialMonitorError.next(`Can't find port ${port}`); |
221 |
| - } |
222 |
| - this.appMessages |
223 |
| - .pipe(takeUntil(this.serialMonitorOpened.pipe(filter(open => !open)))) |
224 |
| - .subscribe(message => { |
225 |
| - if (message.portCloseStatus === 'success') { |
226 |
| - this.serialMonitorOpened.next(false); |
227 |
| - } |
228 |
| - if (message.portCloseStatus === 'error') { |
229 |
| - this.serialMonitorError.next(`Failed to close serial ${port}`); |
230 |
| - } |
231 |
| - }); |
232 |
| - this.channel.postMessage({ |
233 |
| - command: 'closePort', |
234 |
| - data: { |
235 |
| - name: port |
236 |
| - } |
237 |
| - }); |
238 |
| - } |
| 49 | + const handler = { |
| 50 | + get: (_, name) => this.flavour[name], |
239 | 51 |
|
240 |
| - handleUploadMessage(message) { |
241 |
| - if (this.uploading.getValue().status !== this.UPLOAD_IN_PROGRESS) { |
242 |
| - return; |
243 |
| - } |
244 |
| - switch (message.uploadStatus) { |
245 |
| - case 'message': |
246 |
| - this.uploading.next({ status: this.UPLOAD_IN_PROGRESS, msg: message.message }); |
247 |
| - break; |
248 |
| - case 'error': |
249 |
| - this.uploading.next({ status: this.UPLOAD_ERROR, err: message.message }); |
250 |
| - break; |
251 |
| - case 'success': |
252 |
| - this.uploading.next({ status: this.UPLOAD_DONE, msg: message.message }); |
253 |
| - break; |
254 |
| - default: |
255 |
| - this.uploading.next({ status: this.UPLOAD_IN_PROGRESS }); |
| 52 | + set: (_, name, value) => { |
| 53 | + this.flavour[name] = value; |
| 54 | + return true; |
256 | 55 | }
|
257 |
| - } |
| 56 | + }; |
258 | 57 |
|
259 |
| - /** |
260 |
| - * Perform an upload via http on the daemon |
261 |
| - * @param {Object} target = { |
262 |
| - * board: "name of the board", |
263 |
| - * port: "port of the board", |
264 |
| - * commandline: "commandline to execute", |
265 |
| - * data: "compiled sketch" |
266 |
| - * } |
267 |
| - */ |
268 |
| - _upload(uploadPayload, uploadCommandInfo) { |
269 |
| - const { |
270 |
| - board, port, commandline, data |
271 |
| - } = uploadPayload; |
272 |
| - const extrafiles = uploadCommandInfo && uploadCommandInfo.files && Array.isArray(uploadCommandInfo.files) ? uploadCommandInfo.files : []; |
273 |
| - try { |
274 |
| - window.oauth.token().then(token => { |
275 |
| - this.channel.postMessage({ |
276 |
| - command: 'upload', |
277 |
| - data: { |
278 |
| - board, |
279 |
| - port, |
280 |
| - commandline, |
281 |
| - data, |
282 |
| - token: token.token, |
283 |
| - extrafiles |
284 |
| - } |
285 |
| - }); |
286 |
| - }); |
287 |
| - } |
288 |
| - catch (err) { |
289 |
| - this.uploading.next({ status: this.UPLOAD_ERROR, err: 'you need to be logged in on a Create site to upload by Chrome App' }); |
290 |
| - } |
291 |
| - } |
| 58 | + return new Proxy(this, handler); |
292 | 59 |
|
293 |
| - downloadTool() { |
294 |
| - // no need to download tool on chromeOS |
295 |
| - this.downloading.next({ status: this.DOWNLOAD_DONE }); |
296 |
| - } |
297 | 60 | }
|
| 61 | + |
0 commit comments