google cloud speech not working in electron package - electron

When I run the application from command prompt using npm start command it works well. It returning the result from speech api.
I am using binaryServer and binaryclient to stream audio to google cloud API.
When I create package for electron application everything works but it not returning the result from speech api.
Here are my code snippe:
Package.json
{
"name": "test",
"version": "1.0.0",
"description": "test Web Server",
"main": "main.js",
"scripts": {
"start": "electron main.js"
},
"devDependencies": {
"electron": "^1.4.12"
},
"dependencies": {
"binaryjs": "^0.2.1",
"connect": "^3.3.4",
"biased-opener": "^0.2.8",
"serve-static": "^1.9.1",
"uaparser": "^0.0.2",
"#google-cloud/speech" : "^0.5.0"
}
}
Here is my main.js
app.on('ready', function () {
load_app();
});
var workerProcess = child_process.spawn('node', __dirname + '/binaryServer.js');
workerProcess.stdout.on('data', function (data) {
console.log('stdout: ' + data);
});
workerProcess.stderr.on('data', function (data) {
console.log('stderr: ' + data);
});
workerProcess.on('close', function (code) {
console.log('child process exited with code ' + code);
});
processes.push(workerProcess);
function load_app () {
// Launches the browser window
mainWindow = new BrowserWindow({ width: 1080, height: 1920 });
// Load just launched server in browser window
mainWindow.loadURL("http://localhost:" + config.port);
if (config.devMode) {
mainWindow.webContents.openDevTools();
}
else {
mainWindow.setFullScreen(true);
}
}
here is my binary server
var binaryServer = require('binaryjs').BinaryServer,
https = require('http'),
connect = require('connect'),
serveStatic = require('serve-static');
var config = require('./config');
var server = connect()
.use(serveStatic(__dirname));
var speech = require('#google-cloud/speech')({
projectId: config.speech.projectId,
keyFilename: config.speech.keyFilename
});
httpServer = https.createServer(server);
httpServer.timeout = 0;
httpServer.listen(config.port);
var binarySer = binaryServer({ server: httpServer });
console.log("server pid" + process.pid);
binarySer.on('connection', function (client) {
console.log("new connection...");
client.on('stream', function (stream, meta) {
var options = {
config: {
encoding: 'LINEAR16',
sampleRate: meta.sampleRate,
languageCode: "en-IN"
},
singleUtterance: false,
interimResults: true,
verbose: true
};
// Create a recognize stream
const recognizeStream = speech.createRecognizeStream(options)
.on('error', console.error)
.on('data', function (data) { if (stream.writable && !stream.destroyed) stream.write(data) }); // send data to client
if (recognizeStream.writable && !recognizeStream.destroyed && stream.readable && !stream.destroyed)
stream.pipe(recognizeStream); // pipe audio to cloud speech
});
client.on('close', function () {
console.log("Connection Closed");
});
});
Thanks for your help

Taking a shot in the dark here (without much familiarity with binaryServer, which realistically could be the issue). I'm also a bit unclear about where the audio stream actually comes from:
Electron packages its own version of V8. When you run npm install it will install (or compile on the fly) the native binaries targeted for the version of V8 that are installed on your machine (local version). When you spawn the child process it uses that same local version.
However, when you package your electron app it will try to spawn the process with Electron's version of V8 and there will be binary incompatibilities.
Put simply
[Your version of V8] != [Electron's version of V8]
On to potential solutions
Sonus is compatible with
Electron provided that you
Re-compile dependencies with
electron-recompile

Related

electron app update now crashing on http require statement

I made a electron app a couple years ago. now like to update for a little bit diiferint usage.
When I try to run this after updating electron and libraries and import it is failing on the http requirement.
The long ago compiled app still works, but even the code for that if i copy it to new project also failed on this require line.
Error in the console
ReferenceError: Can't find variable: require
renderer.js:62
And below are the codes
browser setup in index.js
const path = require('path');
// Handle creating/removing shortcuts on Windows when installing/uninstalling.
if (require('electron-squirrel-startup')) { // eslint-disable-line global-require
app.quit();
}
const createWindow = () => {
// Create the browser window.
const mainWindow = new BrowserWindow({
width: 200,
height: 600,
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
enableRemoteModule: true,
}
});
// and load the index.html of the app.
mainWindow.loadFile(path.join(__dirname, 'index.html'));
// Open the DevTools.
//mainWindow.webContents.openDevTools();
};
failing request in renderer.js
/* placeCall
* Grab the SIP uri from the input box and send it to the codec.
* Requires an account on the codec that can make calls.
* Send the authorization in the http header.
*/
function placeCall(){
var uri = document.getElementById("sipuri").value;
var xmldoc = '<Command><Dial command="true"><Number>' + uri + '</Number></Dial></Command>';
var xmlLength = xmldoc.length;
var sysIp = document.getElementById("sysip").value;
// console.log("XMLDOC: " + xmldoc);
var http = require("https"); <- CRASHES HERE ON LINE 62!
var options = {
"method": "POST",
"hostname": sysIp,
"port": null,
"path": "/putxml",
"rejectUnauthorized": false,
"headers": {
"content-type": "text/xml",
"content-length": xmlLength,
"authorization": "Basic dkeicjsmcielwoslkdddddd"
}
};
var req = http.request(options, function (res) {
var chunks = [];
res.on("data", function (chunk) {
chunks.push(chunk);
});
res.on("end", function () {
var body = Buffer.concat(chunks);
console.log(body.toString());
});
});
req.write(xmldoc);
req.end();
}
the error is in the browser. seems like it has to run as electron app.
That must be that require is really a node.js operation.
Maybe this question is repeated elsewhere and this one can be deleted.

Browsersync is running but does not refresh the page

I have MacOS + installed Docker container by Mark Shust (https://github.com/markshust/docker-magento) + installed browsersync on the host.
Magento has ".less" files in the folder: app/design/frontend. I set a folder as a current one in the cli. And run this command from the host:
browser-sync start --host "domain.test" --proxy "https://domain.test" --files "**/*.less" --https
I get this output:
[Browsersync] Proxying: https://domain.test
[Browsersync] Access URLs:
--------------------------------------
Local: https://localhost:3000
External: https://domain.test:3000
--------------------------------------
UI: http://localhost:3002
UI External: http://localhost:3002
--------------------------------------
[Browsersync] Watching files...
I can open https://domain.test and it works properly. http://localhost:3002 shows that there are no current connections. However, the output in the cli infoms: "[Browsersync] Reloading Browsers..."
if i change less, i still can find changes on the website but only after a manual reload.
The documentation mentions grunt configuration and there are some recipes as an example. I tried to use standard magento's file but it does not help. It looks like this:
module.exports = function (grunt) {
'use strict';
grunt.initConfig({
watch: {
files: 'app/design/**/*.less',
tasks: ['less']
},
browserSync: {
dev: {
bsFiles: {
src : [
'app/design/**/*.css'
]
},
options: {
watchTask: true,
server: './'
}
}
}
});
// load npm tasks
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-browser-sync');
// define default task
grunt.registerTask('default', ['browserSync', 'watch']);
var _ = require('underscore'),
path = require('path'),
filesRouter = require('./dev/tools/grunt/tools/files-router'),
configDir = './dev/tools/grunt/configs',
tasks = grunt.file.expand('./dev/tools/grunt/tasks/*'),
themes;
filesRouter.set('themes', 'dev/tools/grunt/configs/themes');
themes = filesRouter.get('themes');
tasks = _.map(tasks, function (task) {
return task.replace('.js', '');
});
tasks.push('time-grunt');
tasks.forEach(function (task) {
require(task)(grunt);
});
require('load-grunt-config')(grunt, {
configPath: path.join(__dirname, configDir),
init: true,
jitGrunt: {
staticMappings: {
usebanner: 'grunt-banner'
}
}
});
_.each({
/**
* Assembling tasks.
* ToDo: define default tasks.
*/
default: function () {
grunt.log.subhead('I\'m default task and at the moment I\'m empty, sorry :/');
},
/**
* Production preparation task.
*/
prod: function (component) {
var tasks = [
'less',
'cssmin',
'usebanner'
].map(function (task) {
return task + ':' + component;
});
if (typeof component === 'undefined') {
grunt.log.subhead('Tip: Please make sure that u specify prod subtask. By default prod task do nothing');
} else {
grunt.task.run(tasks);
}
},
/**
* Refresh themes.
*/
refresh: function () {
var tasks = [
'clean',
'exec:all'
];
_.each(themes, function (theme, name) {
tasks.push('less:' + name);
});
grunt.task.run(tasks);
},
/**
* Documentation
*/
documentation: [
'replace:documentation',
'less:documentation',
'styledocco:documentation',
'usebanner:documentationCss',
'usebanner:documentationLess',
'usebanner:documentationHtml',
'clean:var',
'clean:pub'
],
'legacy-build': [
'mage-minify:legacy'
],
spec: function (theme) {
var runner = require('./dev/tests/js/jasmine/spec_runner');
runner.init(grunt, { theme: theme });
grunt.task.run(runner.getTasks());
}
}, function (task, name) {
grunt.registerTask(name, task);
});};
Should it work without gruntjs running? And why the page reload is not triggered?
PS: I did not place this question into https://magento.stackexchange.com/ cause i believe it's a general problem and not related to Magento.

Electron application Can not find Squirrel

I build an electron app with auto-update enabled. After running the application on Windows, I got an error emitted by my application which is "Error: Can not find Squirrel".
After look into the code of electron project for finding the error message.
checkForUpdates () {
const url = this.updateURL;
if (!url) {
return this.emitError(new Error('Update URL is not set'));
}
if (!squirrelUpdate.supported()) {
return this.emitError(new Error('Can not find Squirrel'));
}
this.emit('checking-for-update');
squirrelUpdate.checkForUpdate(url, (error, update) => {
if (error != null) {
return this.emitError(error);
}
if (update == null) {
return this.emit('update-not-available');
}
this.updateAvailable = true;
this.emit('update-available');
squirrelUpdate.update(url, (error) => {
if (error != null) {
return this.emitError(error);
}
const { releaseNotes, version } = update;
// Date is not available on Windows, so fake it.
const date = new Date();
this.emit('update-downloaded', {}, releaseNotes, version, date, this.updateURL, () => {
this.quitAndInstall();
});
});
});
}
And after check the function squirrelUpdate.supported(). I know it is because the install location has no file "Update.exe".
I use electron-builder to generate my application and there is no Update.exe in unpacked packaged directory. How do I generate the Update.exe file?
The block of configuration of electron-builder in package.json is blow:
"win": {
"target": [
"nsis"
],
"defaultArch": "x64",
"verifyUpdateCodeSignature": false
},
How to solve the problem? Thanks.
The reason there is no update.exe is because you have "nsis" as the target package type.
The auto updater package you are trying to use is meant to be compatible with Squirrel.Windows. If you change your target to "squirrel" it will have the update.exe you are looking for.
There are additional dependencies required when using Squirrel.Windows; see below:
https://www.electron.build/configuration/win

How to Update Device Configuration using Google Cloud functions and MQTT bridge

I am using the Google Cloud IoT with Pub/Sub.
I have a device reading sensor data and sending it to a topic in Pub/Sub.
I have a topic cloud function that is triggered by this message and I would like to have the device configuration updated, however I am unable to do so due to the following permission error.
index.js :
/**
* Triggered from a message on a Cloud Pub/Sub topic.
*
* #param {!Object} event The Cloud Functions event.
* #param {!Function} The callback function.
*/
var google = require('googleapis');
//var tt = google.urlshortener('v1');
//console.log(Object.getOwnPropertyNames(google.getAPIs()));
var cloudiot = google.cloudiot('v1');
function handleDeviceGet(authClient, name, device_id, err, data) {
if (err) {
console.log('Error with get device:', device_id);
console.log(err);
return;
}
console.log('Got device:', device_id);
console.log(data);
console.log(data.config);
var data2 = JSON.parse(
Buffer.from(data.config.binaryData, 'base64').toString());
console.log(data2);
data2.on = !data2.on;
console.log(data2);
var request2 = {
name: name,
resource: {
'versionToUpdate' : data.config.version,
'binaryData' : Buffer(JSON.stringify(data2)).toString('base64')
},
auth: authClient
};
console.log('request2' + request2);
var devices = cloudiot.projects.locations.registries.devices;
devices.modifyCloudToDeviceConfig(request2, (err, data) => {
if (err) {
console.log('Error patching device:', device_id);
console.log(err);
} else {
console.log('Patched device:', device_id);
console.log(data);
}
});
}
const handleAuth = (device_id) => {
console.log(device_id);
return (err, authClient) => {
const project_id = 'animated-bonsai-195009';
const cloud_region = 'us-central1';
const registry_id = 'reg1';
const name = `projects / ${project_id} /locations / ${cloud_region} /` +
`registries / ${registry_id} /devices / ${device_id}`;
if (err) {
console.log(err);
}
if (authClient.createScopedRequired &&
authClient.createScopedRequired()) {
authClient = authClient.createScoped(
['https://www.googleapis.com/auth/cloud-platforme']);
}
var request = {
name: name,
auth: authClient
};
// Get device version
var devices = cloudiot.projects.locations.registries.devices;
devices.get(request, (err, data) =>
handleDeviceGet(authClient, name, device_id, err, data));
}
};
exports.subscribe = (event, callback) => {
// The Cloud Pub/Sub Message object.
const pubsubMessage = event.data;
// We're just going to log the message to prove that
// it worked.
var obj = JSON.parse(Buffer.from(pubsubMessage.data, 'base64').toString());
console.log(Buffer.from(pubsubMessage.data, 'base64').toString());
console.log(event);
console.log(Object.getOwnPropertyNames(event));
console.log(callback);
let message = {
"watter": 1
};
message = new Buffer(JSON.stringify(message));
const req = {
name: event.data.deviceId,
resource: message
};
console.log(obj.deviceId);
google.auth.getApplicationDefault(handleAuth(obj['deviceId']));
// Don't forget to call the callback.
callback();
};
package.json :
{
"name": "sample-pubsub",
"version": "0.0.1",
"dependencies": {
"googleapis": "25.0.0"
}
}
Error:
A few options:
Check that you have enabled API access for the Google Cloud IoT Core API for the project used when creating the Google Cloud Function.
Check that you have enabled billing for your project
If you are deploying your Google Cloud Functions with gcloud beta functions deploy ... from the folder with your .js and package.json files, you may want to set the environment variables (GCLOUD_PROJECT and GOOGLE_APPLICATION_CREDENTIALS) or use gcloud auth application-default login before deploying in case you have multiple Google Cloud projects and need to enable the API on the configured one.
Update This community tutorial shows you how to do this - note that there have been some updates to Google Cloud Functions that require you to use a newer version of the Node JS client library as is done in the NodeJS sample and as corrected in this PR, note the version of the client library in package.json.

"Error: no such session" Webdriver-IO, Appium

I have setup Cucumber, Webdriver-IO, and Appium. Everything appears to be talking to each other, however I'm getting Error: no such session when trying to navigate to http://google.com.
On the Android device it opens up the Chrome browser, then closes it really fast.
webdriverio.js
//webdriverio.js
let client = WebDriverIO.remote({
desiredCapabilities: {
platformName: 'Android',
browserName: 'chrome',
deviceName: 'test',
},
host: 'localhost',
port: 4723,
waitForTimeout: 120 * 1000,
});
global.client = client;
module.exports = function() {
this.registerHandler('BeforeFeatures', function(event, done) {
client.init().call(done);
});
this.registerHandler('AfterFeatures', function(event, done) {
client.end().call(done);
});
};
env.js
// env.js
module.exports = function() {
// added because default 50000 ms was long enough
this.setDefaultTimeout(60 * 1000);
};
search_steps.js
// search_steps.js
module.exports = function() {
this.Given('I have visited Google', function (done) {
client
.url('http://google.com')
.call(done);
});
this.When('I search for {arg1:stringInDoubleQuotes}', function (arg1, done) {
// Write code here that turns the phrase above into concrete actions
client
.setValue('input[name="q"]', 'Kittens')
.call(done);
});
this.Then('I see {arg1:stringInDoubleQuotes}', function (arg1, done) {
// Write code here that turns the phrase above into concrete actions
client
.getValue('input[name="q"]').then(function(text){
expect('Kittens').to.eql(text);
})
.call(done);
});
};
The issue is chromedriver 2.21.371459 that is shipped with my version of Appium (1.3.5) for Mac. I downloaded the latest version of chromedriver and overwritten the existing one that is shipped with Appium. See the answer here Chrome opens for a second and the crashes for windows. For mac the location of the chromedriver exec shipped with Appium is. /Applications/Appium.app/Contents/Resources/node_modules/appium/node_modules/appium-android-driver/node_modules/appium-chromedriver/chromedriver/mac

Resources