Skip to content

Commit 4276aec

Browse files
committed
Release 1.14.2
1 parent 09d6761 commit 4276aec

File tree

153 files changed

+34917
-184
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

153 files changed

+34917
-184
lines changed

cli/blocks.ts

Lines changed: 178 additions & 30 deletions
Large diffs are not rendered by default.

cli/config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ export interface EdgeImpulseConfig {
7474
api: EdgeImpulseAPI;
7575
endpoints: EdgeImpulseEndpoints;
7676
setDeviceUpload: boolean;
77+
host: string;
7778
}
7879

7980
export class Config {
@@ -338,6 +339,7 @@ export class Config {
338339
api: this._api,
339340
endpoints: this._endpoints,
340341
setDeviceUpload: setDeviceUpload,
342+
host: host,
341343
};
342344
}
343345

cli/run-impulse.ts

Lines changed: 157 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,16 @@ import { SerialConnector } from './serial-connector';
44
import fs from 'fs';
55
import Path from 'path';
66
import EiSerialProtocol, {
7-
EiSerialDeviceConfig
7+
EiSerialDeviceConfig, EiSerialSensor
88
} from '../shared/daemon/ei-serial-protocol';
99
import { Config } from './config';
1010
import { findSerial } from './find-serial';
1111
import checkNewVersions from './check-new-version';
1212
import { getCliVersion } from './init-cli-app';
13+
import express = require('express');
14+
import http from 'http';
15+
import socketIO from 'socket.io';
16+
import { ips } from './get-ips';
1317

1418
const SERIAL_PREFIX = '\x1b[33m[SER]\x1b[0m';
1519

@@ -23,6 +27,8 @@ const whichDeviceArgv = whichDeviceArgvIx !== -1 ? Number(process.argv[whichDevi
2327

2428
let stdinAttached = false;
2529
let serial: SerialConnector | undefined;
30+
let startedWebserver = false;
31+
let inferenceStarted = false;
2632

2733
const configFactory = new Config();
2834
// tslint:disable-next-line:no-floating-promises
@@ -111,10 +117,10 @@ async function connectToSerial(deviceId: string) {
111117
process.on('SIGHUP', onSignal);
112118
process.on('SIGINT', onSignal);
113119

114-
let inferenceStarted = false;
120+
let logMessages = true;
115121

116122
serial.on('data', data => {
117-
if ((serial && serial.isConnected() && inferenceStarted) || rawArgv) {
123+
if (((serial && serial.isConnected() && inferenceStarted) || rawArgv) && logMessages) {
118124
process.stdout.write(data.toString('ascii'));
119125
}
120126
});
@@ -168,6 +174,23 @@ async function connectToSerial(deviceId: string) {
168174
mode = 'debug';
169175
}
170176

177+
if (config.inference.sensor === EiSerialSensor.EI_CLASSIFIER_SENSOR_CAMERA) {
178+
if (mode !== 'debug') {
179+
console.log('');
180+
console.log(SERIAL_PREFIX,
181+
'To get a live feed of the camera and live classification in your browser, run with --debug');
182+
console.log('');
183+
}
184+
else {
185+
let webserverPort = await startWebServer(config);
186+
console.log('');
187+
console.log('Want to see a feed of the camera and live classification in your browser? ' +
188+
'Go to http://' + (ips.length > 0 ? ips[0].address : 'localhost') + ':' + webserverPort);
189+
console.log('');
190+
logMessages = false;
191+
}
192+
}
193+
171194
await serialProtocol.startInference(mode);
172195

173196
console.log(SERIAL_PREFIX, 'Started inferencing, press CTRL+C to stop...');
@@ -204,3 +227,134 @@ async function connectToSerial(deviceId: string) {
204227
// tslint:disable-next-line:no-floating-promises
205228
serial_connect();
206229
}
230+
231+
async function startWebServer(config: EiSerialDeviceConfig) {
232+
if (!serial) return;
233+
if (startedWebserver) return;
234+
235+
startedWebserver = true;
236+
237+
const app = express();
238+
app.use(express.static(Path.join(__dirname, '..', '..', 'public')));
239+
240+
const server = new http.Server(app);
241+
const io = socketIO(server);
242+
243+
server.listen(Number(process.env.PORT) || 4915, process.env.HOST || '0.0.0.0', async () => {
244+
// noop
245+
});
246+
247+
let currentMsg: string | undefined;
248+
serial.on('data', (data: Buffer) => {
249+
let s = data.toString('utf-8');
250+
if (s.indexOf('End output') > -1) {
251+
if (typeof currentMsg === 'string') {
252+
currentMsg += s.substr(0, s.indexOf('End output'));
253+
254+
let lines = currentMsg.split('\n');
255+
let fb = lines.find(x => x.startsWith('Framebuffer: '));
256+
257+
let printMsg = '';
258+
259+
let classifyTime = 0;
260+
let timingLine = lines.find(x => x.startsWith('Predictions'));
261+
if (timingLine) {
262+
let m = timingLine.match(/Classification: (\d+)/);
263+
if (m) {
264+
classifyTime = Number(m[1]);
265+
}
266+
printMsg += timingLine + '\n';
267+
}
268+
269+
if (fb) {
270+
fb = fb.replace('Framebuffer: ', '').trim();
271+
272+
let snapshot = Buffer.from(fb, 'base64');
273+
io.emit('image', {
274+
img: 'data:image/jpeg;base64,' + snapshot.toString('base64')
275+
});
276+
}
277+
278+
let mode: 'classification' | 'object_detection';
279+
let firstClassifyLine = lines.find(x => x.startsWith(' '));
280+
if (firstClassifyLine && !isNaN(Number(firstClassifyLine.split(':')[1]))) {
281+
mode = 'classification';
282+
}
283+
else {
284+
mode = 'object_detection';
285+
}
286+
287+
if (mode === 'object_detection') {
288+
let cubes = [];
289+
// parse object detection
290+
for (let l of lines.filter(x => x.startsWith(' ') && x.indexOf('width:') > -1)) {
291+
let m = l.trim()
292+
.match(/^(\w+) \(([\w\.]+)\) \[ x: (\d+), y: (\d+), width: (\d+), height: (\d+)/);
293+
if (!m) continue;
294+
let cube = {
295+
label: m[1],
296+
value: Number(m[2]),
297+
x: Number(m[3]),
298+
y: Number(m[4]),
299+
width: Number(m[5]),
300+
height: Number(m[6]),
301+
};
302+
cubes.push(cube);
303+
printMsg += l + '\n';
304+
}
305+
306+
io.emit('classification', {
307+
result: {
308+
bounding_boxes: cubes
309+
},
310+
timeMs: classifyTime,
311+
});
312+
}
313+
else {
314+
let results: { [k: string]: number } = { };
315+
// parse object detection
316+
for (let l of lines.filter(x => x.startsWith(' '))) {
317+
let m = l.split(':').map(x => x.trim());
318+
if (m.length !== 2) continue;
319+
results[m[0]] = Number(m[1]);
320+
printMsg += l + '\n';
321+
}
322+
323+
io.emit('classification', {
324+
result: {
325+
classification: results
326+
},
327+
timeMs: classifyTime,
328+
});
329+
}
330+
331+
if (inferenceStarted) {
332+
console.log(printMsg.trim());
333+
}
334+
}
335+
336+
currentMsg = undefined;
337+
s = s.substr(s.indexOf('End output'));
338+
}
339+
340+
if (s.indexOf('Begin output') > -1) {
341+
s = s.substr(s.indexOf('Begin output') + 'Begin output'.length);
342+
currentMsg = s;
343+
return;
344+
}
345+
346+
if (currentMsg) {
347+
currentMsg += s;
348+
}
349+
350+
// console.log('data', data.toString('utf-8');
351+
});
352+
353+
io.on('connection', socket => {
354+
socket.emit('hello', {
355+
projectName: 'Live classification on ' + config.info.type
356+
});
357+
});
358+
359+
return Number(process.env.PORT) || 4915;
360+
}

0 commit comments

Comments
 (0)