phonegap webos 3.0+ - node.js

I have a phonegap iOS app that i ported to webos on the touchpad the app works great except for the one iOS plugin that i used. it basically saved the canvas data to the photo roll. From my understanding of webos i will need to create a node.js service and write the data to a buffer and finally to the file system, there is an example for that in the forums. however what i can not figure out is how to call all of this from my phonegap app. I believe i will need to have the following in my index.html file.
<script src="/opt/PalmSDK/Current/share/framework/enyo/1.0/framework/enyo.js" type="text/javascript"></script>
and something like
enyo.create({kind: "Main"}).renderInto(document.body);
my guess i will also have to have all of the "kind" data in a js file. but how do i do the little step from my app's js file to communicate with the service that is created. I looked in the phonegap 1.0.js file and see that they are calling services this way.
this.service = navigator.service.Request('palm://com.palm.applicationManager', {
method: 'launch',
parameters: {
id: 'com.palm.app.camera',
params: {
appId: 'com.palm.app.camera',
name: 'capture',
sublaunch: true,
filename: filename
}
},
onSuccess: successCallback,
onFailure: errorCallback
});
but i also noticed it appears that it is all mojo and what i am doing is enyo, so yes i am pretty confused the moment...
seems it should be easy to call a service in webos, say here is a string of image data and write it to the file system from my existing phonegap app. and not have to do everything in enyo. anyone have a sample of a webos plugin like this or know where to point me?
thanks tim
**Update
I have created a node service now as defined below, i think that works and i am trying to make the call to the service, but it does not get to it. the test app runs on my touchpad, but when i push the button to save the image i do not get into the service. I tried to follow what was done for the camera in the phonegap0.0.1.js file this is a copy of my service, how i defined it and how i am calling it. any ideas what i am doing wrong.
services.json =
"id": "com.tim.pgmojo1.service",
"description": "FileIO Service",
"services": [
{
"name": "com.tim.pgmojo1.service",
"description": "FileIO Service",
"commands": [
{
"name": "writefile",
"assistant": "WriteFileAssistant",
"public": true
}]
}]
}
** service code
var libraries = MojoLoader.require({ name: "foundations", version: "1.0" });
var fs = IMPORTS.require("fs");
var sys = require('sys');
var WriteFileAssistant = function() {}
WriteFileAssistant.prototype.run = function(future) {
var mypath = this.controller.args.thepath;
var mydata = this.controller.args.thedata;
console.log("in write file");
console.log("path=" + thepath);
console.log("image data=" + thedata);
var data = content.replace(/^data:image\/\w+;base64,/, "");
var buf = new Buffer(data, 'base64');
fs.writeFile('/media/internal/downloads/timimage.png', buf);
}
my call to the service**
this.service = navigator.service.Request('palm://com.tim.pgmojo.service', {
method: 'writefile',
parameters: {
thepath: '/media/internal/downloads/timimage.png',
thedata: canvasData
},
onSuccess: mySuccess,
onFailure: myFailure
});
currently i have this in my index.html file since it is only for testing..

Mojo is still included on the TouchPad. You can use the same service-calling functions as PhoneGap is doing.

In Enyo, access to on-device services is handled by the enyo.PalmService kind. You can see an example of an app that has a node.js service included and how calls are made to this service at https://github.com/palm/txjs-fortunecookie

Related

{Action name} isn't responding right now. Try again soon

I'm new with the ActionSDK and I created an project with the Action SDK.
The fulfillment of my actions is deploy in Azure as a web service.
I've being updating my action with:
gactions update --action_package action.json --project "projectID"
this being said, the update is successful.
this is my action.json:
{
"actions": [
{
"name": "MAIN",
"intent": {
"name": "actions.intent.MAIN",
"trigger": {
"queryPatterns": [
"talk to Conduent Helper",
"Talk to conduent help"
]
}
},
"fulfillment": {
"conversationName": "conduentHelpTest"
}
}
],
"conversations": {
"conduentHelpApp": {
"name": "conduentHelpTest",
"url": "https://dialogflowappnc.azurewebsites.net",
"fulfillmentApiVersion": 2
}
}
}
this is a fulfillment code I found after trying my own and had no success with it:
'use strict';
var express = require('express');
var bodyParser = require('body-parser');
var exps = express();
const ApiAiApp = require('actions-on-google').ApiAiApp;
exps.use(bodyParser.json());
// API.AI actions
const WELCOME_ACTION = 'input.welcome';
exps.post('/', function(request, response) {
console.log("hello World");
const app = new ApiAiApp({request, response});
function greetUser (app) {
app.tell("Hello World!");
}
let actionMap = new Map();
actionMap.set(WELCOME_ACTION, greetUser);
app.handleRequest(actionMap);
});
exps.listen((process.env.PORT || 7001), function() {
console.log("App up and running, listening.")
})
Whenever I test in the simulator the response is:
{Action name} isn't responding right now. Try again soon.
Whenever I do an update with the command above I see in my web service a request. But when I try to test the action in the simulator I see no request being made.
If someone can point me in the right direction. Point out any knowledge I most gain before proceeding. I there's more info I need to provide let me know and thanks.
Sorry I do not have enough points to comment but We are currently experiencing an outage you can see here if you are being impacted https://azure.microsoft.com/en-us/status/
You will want to monitor the Azure Status Page for further updates. Unfortunately we cannot do anything until the problem has been mitigated by engineering.
There are a couple of potential issues:
First - you haven't shown your package.json file, but the code suggests you're using an older version of the actions-on-google library. So the code itself may not be running. Check your runtime logs to make sure it is.
Next, you've specified that it should be listening on port 7001, but the URL you've provided in the actions.json file doesn't include the port number. If that is the host and port it is running on, and you haven't provided a proxy of some sort, then you need to specify the URL as https://dialogflowappnc.azurewebsites.net:7001/
Also, if you're running on port 7001, you likely haven't opened up the firewall to access it.
But it seems likely you're running a proxy (or you should), since you also need to be providing a valid HTTPS connection with a valid SSL certificate. If this is a self-signed certificate, the connection may still be rejected.

Electron with node-notifier display windows 10 notification

I'm trying to make a simple app that should display notification when button is clicked. The problem is that the notification does not show, but console.logs are showing. Should the notification work on development mode? (meaning just running electron ., and I don't have to build and install the app)
Windows OS:
Edition: Windows 10 Home
Version: 1709
Build:16299.98
NOTE: Toast is enabled (banner, action center) under System->Notification & Actions
Code:
// main.js
const { app, BrowserWindow, ipcMain, Notification } = require("electron");
const path = require("path");
const url = require("url");
let win;
function createWindow() {
// Create the browser window.
win = new BrowserWindow({ width: 800, height: 600 });
// and load the index.html of the app.
win.loadURL(
url.format({
pathname: path.join(__dirname, "index.html"),
protocol: "file:",
slashes: true
})
);
// Open the DevTools.
// win.webContents.openDevTools()
// Emitted when the window is closed.
win.on("closed", () => {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
win = null;
});
}
const appId = "elite-notifier";
app.setAppUserModelId(appId);
app.on("ready", createWindow);
console.log("notifying");
ipcMain.on("notify", () => {
console.log("notified");
const WindowsToaster = require("node-notifier").WindowsToaster;
const notifier = new WindowsToaster({
withFallback: false
});
notifier.notify(
{
title: "My awesome title",
message: "Hello from node, Mr. User!",
sound: true, // Only Notification Center or Windows Toasters
wait: false // Wait with callback, until user action is taken against notification
},
function(err, response) {
// Response is response from notification
console.log("responded...");
}
);
});
// index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
</head>
<body>
<h1>Notifier!</h1>
<button type="button" id="notify">Click here to trigger a notification!</button>
<script type="text/javascript">
const { ipcRenderer } = require('electron');
const button = document.getElementById('notify');
console.log('BUTTON: ', button)
button.addEventListener('click', function(event) {
console.log('clicked...');
ipcRenderer.send('notify')
});
</script>
</body>
</html>
I've got it working now, thanks to all the people here :) https://github.com/mikaelbr/node-notifier/issues/144#issuecomment-319324058
Based on anthonyraymond's comment, you need to have your app INSTALLED in your windows machine with an appId. You can configure appId in your package.json like this.
{
"name": "myapp",
"version": "1.0.0",
"description": "test",
"main": "main.js",
"build": {
"appId": "com.myapp.id"
}
}
The appId does not need to have that java/android format, my app just have an appId of elite-notifier.
Then you can pass the appId when calling the notify function of notifier.
notifier.notify(
{
appName: "com.myapp.id", <-- yes, the key here is appName :)
title: "Hello",
message: "Hello world!",
wait: true
},
function(err, response) {
// Response is response from notification
console.log("responded...");
}
);
After installation, This will work even on development mode (by running electron . command) provided that you'll not change the appId of your app after installation since there will be a mismatch on the installed one and the development version of the app.
You don't need to use IPC and send notifications from the main process, this is supported from the renderer process using the HTML5 notification API.
let myNotification = new Notification('Title', {
body: 'Lorem Ipsum Dolor Sit Amet'
})
myNotification.onclick = () => {
console.log('Notification clicked')
}
I've also tried many things, but sometimes it works or not.
At last, I've found a way. This works well for not only "npm run dev", but also package built.
use Notification at renderer process.
register app id at package.json
"build": {
"appId": "my app id",
...
call app.setAppUserModelId("my app id") at main process (https://electronjs.org/docs/api/app#appsetappusermodelidid-windows)
Here app id can be any type of string.
This error doesn't need any configuration all you have to do is go to your setting and enable notification Because in some cases on your computer you just switched off notifications.
System Setting ->Notification & Actions
Then turn on Notification By clicking the switch (problem solved)
You can do this, it works for me even on windows 10.
in package.json
"build": {
"appId": "your.custom.app.id",
}
in main.js
app.setAppUserModelId("your.custom.app.id");

Angular Controllers and Services

I'm pretty new to web dev and AngularJS. I'm trying to figure out how to use services and I'm following this tutorial: http://scotch.io/bar-talk/setting-up-a-mean-stack-single-page-application
How does the service connect with the controller? Is this done implicitly? I understand that you can inject the service into the controller, but how is it being done in the tutorial?
You inject your service into your controller. Like this. The reason behind services are that you want to keep your controller as 'skinny' as possible. All heavy logic/requests should be outsourced to the service.
app.service('myService', function(){
this.name = 'Tyler';
}
app.controller('myCtrl', function($scope, myService){
$scope.name = myService.name;
}
Another benefit of using a service is that you could inject that service into more than one controller. A good example is if you had a service that made a HTTP request. Instead of recreating the same code in every controller to make the request, you could simply create a service that did the request and inject that service into every controller you needed that functionality.
edit: To answer your question. You need to be sure to place the service in the controller on the same 'module'. Meaning. In your HTML you have something like this.
<body ng-app="myApp">
That's telling the whole BODY that whatever is nested inside it belongs to the 'myAPP' app. Then you usually have an app.js file that has something like this.
var app = angular.module('myApp', []);
Notice that the angular.module takes two parameters. You're telling angular to create a new app called 'myApp' (which coincides with your HTML).
Then in your controller, service, directive files you'll have something like this at the top.
var app = angular.module('myApp');
Notice this one is only taking one parameter, the name of the app. You're telling angular that instead of creating a new app, you're going and 'getting' the one you already build. You'll then stick your controllers, directives, services on this app and as long as things are on the same app, you'll be able to inject them.
Another EDIT to your comment.
In the tutorial they're doing it a little weird. They're creating new modules for every controller, service, etc. It's not bad, just different. Doing it this way confuses me so I just prefer to stick everything under one module. In the tutorial this is the line that's gluing it all together.
// public/js/app.js
angular.module('sampleApp', ['ngRoute', 'appRoutes', 'MainCtrl', 'NerdCtrl', 'NerdService', 'GeekCtrl', 'GeekService']);
They have a sampleApp then all there other modules they build are being injected into the main sample app.
a service means to be accesible from all controllers, a service is a constructor, every controller can read or write in a service, in order to use a service you must call a service in this way:
var app = angular.module('myApp', []);
app.service('sharedProperties', function() {
var stringValue = 'test string value';
var objectValue = {
data: 'test object value'
};
return {
getString: function() {
return stringValue;
},
setString: function(value) {
stringValue = value;
},
getObject: function() {
return objectValue;
}
}
});
app.controller('myController1', function($scope, sharedProperties) {
$scope.setOnController1 = function(sharedPoperties){
$scope.stringValue = sharedProperties.getString();
$scope.objectValue = sharedProperties.getObject().data;
}
});
app.controller('myController2', function($scope, sharedProperties) {
$scope.stringValue = sharedProperties.getString;
$scope.objectValue = sharedProperties.getObject();
$scope.setString = function(newValue) {
$scope.objectValue.data = newValue;
sharedProperties.setString(newValue);
//some code to set values on screen at controller1
};
});
Here is the JS FIDDLE
http://jsfiddle.net/b2fCE/228/

Serve custom static files with socket.io nodejs

I try to share my code betwen server and client I use following code (app.js):
var io = require('socket.io').listen(8000),
Static = require('socket.io').Static;
io.configure(function () {
var _static = new Static(io);
// some methods to add my custom files
_static.add('\public\test.js');
io.set('static', _static);
});
My file structure looks like this:
root
app.js
public
test.js
When I type "http://localhost:8000/public.test.js" Browser download default file "Welcome to socket.io"
This question is rather old, but here's the current way to do it (for v0.9):
var io = require('socket.io').listen(8000);
io.static.add('/path/for/request.js', {file: 'path/to/file.js'});
Note that the path to the resource is relative to the socket.io path, so the request URI would be something like:
http://localhost:8000/socket.io/path/for/request.js
If you see an error like Protocol version not supported, then that means your request URI probably has an extension that the manager can't support. Here's how to add that support:
io.static.add('/path/for/request.foo', {
mime: {
type: 'application/javascript',
encoding: 'utf8',
gzip: true
},
file: 'path/to/file.js'
});
The documentation points at their own Static library for a working implementation.

How to track usage on a node.js RESTful service with Google Analytics?

I've written a RESTful node.js service as a backend for http://www.cross-copy.net and would like to not only track usage of the web-client but also other clients (like commandline or Apps) which use the service for inter-device copy/paste. Is it possible to embed the Google Analytics JavaScript API into a node.js application and do server-side tracking?
Since all of the answers are really old, I will mention a new npm package:
https://www.npmjs.com/package/universal-analytics
It's really great and incredible easy to use.
Install universal analytics
npm install universal-analytics --save
In your routes file, require the module. (Replace process.env.GA_ACCOUNT with string like 'UA-12345678-1')
// Init GA client
var ua = require('universal-analytics');
var visitor = ua(process.env.GA_ACCOUNT);
Now inside your endpoint functions, you can track a pageview. (Replace request.url with the current url string like '/api/users/1')
// Track pageview
visitor.pageview(request.url).send();
Read the documentation on UA for more info on this module.
As Brad rightfully sad, there was nothing for Node... So I wrote a nodejs module tailored for this these last few days and just published it on NPM: node-ga
The module is still really new (barely trying it in production on a pet project), so don't hesitate to give your input :)
You won't be able to just drop ga.js into your Node project. It has to be loaded in a browser to function correctly.
I don't believe there is anything out there for Node yet (correct me if I'm wrong!), but you should be able to easily adapt the existing PHP classes for doing logging server-side:
https://developers.google.com/analytics/devguides/collection/other/mobileWebsites
You can see how the URL to request the tracking GIF is constructed within ga.php. Translate ga.php to JS and you're set.
$utmGifLocation = "http://www.google-analytics.com/__utm.gif";
// Construct the gif hit url.
$utmUrl = $utmGifLocation . "?" .
"utmwv=" . VERSION .
"&utmn=" . getRandomNumber() .
"&utmhn=" . urlencode($domainName) .
"&utmr=" . urlencode($documentReferer) .
"&utmp=" . urlencode($documentPath) .
"&utmac=" . $account .
"&utmcc=__utma%3D999.999.999.999.999.1%3B" .
"&utmvid=" . $visitorId .
"&utmip=" . getIP($_SERVER["REMOTE_ADDR"]);
I tried out node-ga, but didn't get event tracking to work. nodealytics did the job.
See Core Reporting API Client Libraries & Sample Code (v3).
There is also the following version: Google APIs Client Library for Node.js (alpha).
I wrote a script to query data with Node.js from Googles Analytics Core Reporting API (v3). The script and a detailed setup description is available here.
Here is the script part:
'use strict';
var googleapi = require('googleapis');
var ApiKeyFile = require('mywebsiteGAapi-6116b1dg49a1.json');
var viewID = 'ga:123456700';
var google = getdefaultObj(googleapi);
var Key = getdefaultObj(ApiKeyFile);
function getdefaultObj(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var jwtClient = new google.default.auth.JWT(Key.default.client_email, null, Key.default.private_key, ['https://www.googleapis.com/auth/analytics.readonly'], null);
jwtClient.authorize(function (err, tokens) {
if (err) {
console.log(err);
return;
}
var analytics = google.default.analytics('v3');
queryData(analytics);
});
function queryData(analytics) {
analytics.data.ga.get({
'auth': jwtClient,
'ids': viewID,
'metrics': 'ga:users,ga:pageviews',
'start-date': 'yesterday',
'end-date': 'today',
}, function (err, response) {
if (err) {
console.log(err);
return;
}
console.log(JSON.stringify(response, null, 4));
});
}

Resources