I am trying to use strongloop loopback sdk 2.0. I tried to use the following code https://github.com/strongloop/loopback-component-push/tree/master/example/server which is loopback version 1.7.0. But when i try compile with version 2.0, it throws me error
Error: The data in model-config.json is in the unsupported 1.x format.
I had also tried as per the strong loop tutorial, but still it does not work. Anyone has suggestion or sample code on how to implement PUSH notification using loopback 2.0?
Create 4 models application, installation, notification, push
In common/models/application.json
{
"name": "push",
"plural": "Push",
"base": "Model",
"properties": {},
"validations": [],
"relations": {},
"acls": [],
"methods": []
}
In common/models/installation.json
{
"name": "installation",
"base": "Installation",
"properties": {},
"validations": [],
"relations": {},
"acls": [],
"methods": []
}
In common/models/notification.js
{
"name": "notification",
"base": "Notification",
"properties": {},
"validations": [],
"relations": {},
"acls": [
{
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "ALLOW",
"property": "sendMessage"
}
],
"methods": []
}
In common/models/push.json
{
"name": "push",
"plural": "Push",
"base": "Model",
"properties": {},
"validations": [],
"relations": {},
"acls": [],
"methods": []
}
server/datasource.json
...
...
"push": {
"name": "push",
"connector": "loopback-component-push",
"installation": "installation",
"notification": "notification",
"application": "application"
}
In common/models/notification.js
module.exports = function(Notification) {
var badge = 1;
//DEFINING A PROPERTY IN NOTIFICATION FOR SENDING PUSH MESSAGE
Notification.sendMessage = function(message, registrationId, from, callback) {
var app = this.app;
from = from? from:'COMPANY_NAME';
sendMessage(app, message, registrationId, from, callback);
}//sendMessage Notification method..
//FUNCTION FOR SENDING PUSH MESSAGE..
var sendMessage = function(app, message, registrationId, from, callback){
var Application = app.models.application;
var PushModel = app.models.push;
var note = new Notification({
expirationInterval: 3600, // Expires 1 hour from now.
badge: badge++,
// sound: 'ping.aiff',
message: message,
messageFrom: from
});
PushModel.notifyById(registrationId, note, function (err) {
if (err) {
console.error('Cannot notify %j: %s', registrationId, err.stack);
return callback(err);
}
console.log('Pushing notification to %j', registrationId);
callback(null, []);
});
}//sendMessage function
//Now registering the method
Notification.remoteMethod(
'sendMessage',
{
accepts: [{arg: 'message', type: 'string', required:true},
{arg: 'registrationId', type: 'string', required:true},
{arg: 'from', type: 'string', required:true}],
description: "Sending message from notification.."
}
)
}//module.exports
Now inside server/ folder create a file push-service.js
module.exports = function(app) {
var Notification = app.models.notification;
var Application = app.models.application;
var PushModel = app.models.push;
function startPushServer() {
PushModel.on('error', function(err) {
console.error('Push Notification error: ', err.stack);
});
// Pre-register an application that is ready to be used for testing.
// You should tweak config options in ./config.js
var loopbackApp = {
id: 'loopback-push-application',
userId: 'strongloop',
name: config.appName,
description: 'loopback Push Notification Service',
pushSettings: {
apns: {
certData: "APPLE CERT. DATA",
keyData: "APPLE KEY DATA",
pushOptions: {
// Extra options can go here for APN
},
feedbackOptions: {
batchFeedback: true,
interval: 300
}
},
gcm: {
serverApiKey: "PASTE YOUR GOOGLE GCM KEY HERE"
}
}
};
updateOrCreateApp(function(err, appModel) {
if (err) {
throw err;
}
console.log('Application id: %j', appModel.id);
});
function updateOrCreateApp(cb) {
Application.findOne({
where: {
id: loopbackApp.id
}
},
function(err, result) {
if (err) cb(err);
if (result) {
delete loopbackApp.id;
result.updateAttributes(loopbackApp, cb);
} else {
return registerApp(cb);
}
});
} //updateOrCreate function
Application.beforeSave = function(next) {
if (this.name === loopbackApp.name) {
this.id = 'loopback-push-application';
}
next();
};
Application.register(
loopbackApp.userId,
loopbackApp.name, {
description: loopbackApp.description,
pushSettings: loopbackApp.pushSettings
},
function(err, app) {
if (err) {
return cb(err);
}
return cb(null, app);
}
);
} //register App
} //startPushServer
startPushServer();
};
Now finally in server.js
....
....
//Adding push service to the backend..
require('./push-service')(app);
....
Now run the loopback server open api explorer and go to NOTIFICATION->SendMessage method and type any message and it will send push notification on connected devices.
NOTE: You also need to configure push services from android/iphone to enable sending push application. For detail check loopback documentation.
Please check out this example - https://github.com/strongloop/loopback-component-push/tree/master/example/server-2.0
Related
I make my pwa from spa so that the user can install and then use it offline,but my application does not work offline when I set offline mode in devTools and refresh the page,a standard browser page appears with a message that there is no network,how to cache the entire application using workbox and make it possible to use it even offline with the data that was received from the server online, and when the network appears, update the data.
Project on GitHub
//sw code
importScripts('https://storage.googleapis.com/workbox-cdn/releases/6.1.1/workbox-sw.js')
// Note: Ignore the error that Glitch raises about workbox being undefined.
workbox.setConfig({
debug: true,
})
const cacheName = workbox.core.cacheNames.precache
const setCacheName = workbox.core.setCacheNameDetails
setCacheName({
prefix: 'guest',
suffix: 'v1',
precache: 'precache',
runtime: 'run-time',
googleAnalytics: 'ga',
});
workbox.core.clientsClaim();
self.addEventListener('fetch', function (event) {
event.respondWith(
caches.match(event.request).then(function (response) {
return response || fetch(event.request);
}),
);
});
workbox.precaching.precacheAndRoute([{
"revision": "99dbb1ac10f49b8b1fcc4879f60b7313",
"url": "favicon.ico"
}, {
"revision": "31aed546ded10cc4f78ac847b857f18a",
"url": "index.html"
}, {
"revision": "6fd885036a48c65dc1c9476777ddfc83",
"url": "static/css/main.accd9ff3.css"
}, {
"revision": "c02707f96adb01d9981185c8d500653c",
"url": "static/js/main.42e89394.js"
}, {
"revision": "bc9520ea17b2e9685ba5961e7d87ed17",
"url": "manifest.json"
}, {
"revision": "b578821088f639079d5dd8764b0ca38e",
"url": "static/media/Calendar.10a98c21b62903a00d416f25939ddeae.svg"
}, {
"revision": "f8fe944931626bc821b23085075f0cc9",
"url": "static/media/email.cfd7fc9e9b6a564041920dd6a8418ed8.svg"
}, {
"revision": "fb91e587caa3bd4206dbce278d766110",
"url": "static/media/gift.6524bbfefbfc6ecc77b94cf52dd23d7d.svg"
}, {
"revision": "9d895d740e1ca4000cb70b3d657752e5",
"url": "static/media/logo.80e3b7f2aa8f0e234e644ab3f5e86b66.svg"
}, {
"revision": "65f28d384b705542ed8d0179b9fc40b7",
"url": "static/media/Phone.7f57311fdf0e51e1c3a76d81166f79c4.svg"
}, {
"revision": "dc62ffcc81ee5c0cea710c09027204fd",
"url": "static/media/profile.d8beab90a1c3af72e650dfbb71a80de6.svg"
}, {
"revision": "6d33824ebe9a9b702096ff730f0cbd6f",
"url": "static/media/qr.d90ce238c55f0df5833d9ed78d541502.svg"
}, {
"revision": "cf2ff7c1a111bf12ea0e0565bc450c5f",
"url": "static/media/user.6056b4037e72f4521dc8e1fefa10472d.svg"
}, {
"revision": "fdd15f825a6db43442a758e2db168314",
"url": "static/media/Geometria-Bold.3a9ed34be5c5b3d8fc3c.woff"
}, {
"revision": "45656b73e1a07f979bfb56559b359b07",
"url": "static/media/Geometria-Medium.ce81051a1ed94e89b4e1.woff"
}, {
"revision": "3c6a7d3ae76a5aec78aac69db1af15cf",
"url": "static/media/Geometria.b7f74b260291c82461d1.woff"
}, {
"revision": "cd42d299828c8762ff81eb5f1fe73dd2",
"url": "offline.html"
},
])
sw builder code
const {injectManifest} =require ('workbox-build')
let workboxConfig={
globDirectory:'../build',
globPatterns:[
'favicon.ico',
'index.html',
'static/css/*.*.css',
'static/js/*.*.js',
'asset-manifest.json',
'static/media/*.*.svg',
'static/media/*.*.woff',
'offline.html'
],
swSrc:'sw-workbox.js',
swDest:'../public/service-worker.js',
}
injectManifest(workboxConfig).then(({count,size})=>{
console.log(`Generate ${workboxConfig.swDest}, which will precache ${count} files, total ${size} bytes`)
})
sw for workbox
// Note: Ignore the error that Glitch raises about workbox being undefined.
workbox.setConfig({
debug: true,
})
const cacheName = workbox.core.cacheNames.precache
const setCacheName = workbox.core.setCacheNameDetails
setCacheName({
prefix: 'guest',
suffix: 'v1',
precache: 'precache',
runtime: 'run-time',
googleAnalytics: 'ga',
});
workbox.core.clientsClaim();
self.addEventListener('fetch', function (event) {
event.respondWith(
caches.match(event.request).then(function (response) {
return response || fetch(event.request);
}),
);
});
workbox.precaching.precacheAndRoute(self.__WB_MANIFEST)
I am using RTK-Query, and Redux-toolkit for this app, and I created an api-slice with createApi, as per the docs.
When I run a request to the backend, I get a "FETCH_ERROR"; however, when I run the same request using Axios, I get the data correctly from the backend, which leads me to believe I have an error in my code. I am just not sure where exactly it is.
Here is the error:
Object {
"api": Object {
"config": Object {
"focused": true,
"keepUnusedDataFor": 60,
"middlewareRegistered": true,
"online": true,
"reducerPath": "api",
"refetchOnFocus": false,
"refetchOnMountOrArgChange": false,
"refetchOnReconnect": false,
},
"mutations": Object {},
"provided": Object {},
"queries": Object {
"test(undefined)": Object {
"endpointName": "test",
"error": Object {
"error": "TypeError: Network request failed",
"status": "FETCH_ERROR",
},
"requestId": "BWOuLpOxoDKTzlUYFLW4x",
"startedTimeStamp": 1643667104869,
"status": "rejected",
},
},
"subscriptions": Object {
"test(undefined)": Object {
"QJSCV641RznGWyudGWuMb": Object {
"pollingInterval": 0,
"refetchOnFocus": undefined,
"refetchOnReconnect": undefined,
},
},
},
},
"test": Object {
"data": Array [],
},
}
Here is the test slice:
import { createSlice } from "#reduxjs/toolkit";
const testSlice = createSlice({
name: "test",
initialState: {
data: [],
},
reducers: {
getData: (state) => {
state;
},
},
});
export const { getData } = testSlice.actions;
export default testSlice.reducer;
Here is the apiSlice:
import { createApi, fetchBaseQuery } from "#reduxjs/toolkit/query/react";
export const apiSice = createApi({
reducerPath: "test",
baseQuery: fetchBaseQuery({ baseUrl: process.env.REACT_APP_backend_url }),
endpoints: (builder) => ({
test: builder.query({
query: () => "/test",
}),
}),
});
export const { useTestQuery } = apiSice;
I solved it by changing the backend URL to my current ipv4 (for expo development, otherwise just your whatever your backend URL is) address in my .env file, then deleting cache, and restarting my app. In my case I was using expo so, expo r -c, and it worked.
I'm developing a Flutter application for Android and IOS. I have created notification channels for Android according to this article.
My node.js payload:
const payload = {
notification: {
title: "title",
},
android: {
priority: "high",
ttl: 60 * 60 * 1,
notification: {
channel_id: 'YO',
},
},
apns: {
payload: {
aps: {
sound: "sound_03.caf"
}
},
headers: {
"apns-collapse-id": "yo",
"apns-priority": "10"
}
},
priority: 10
}
My notifications are working just fine, for both Android and IOS using. The problem is that vibration is disabled by default.
How to enable notification vibration for Android and IOS for Firebase Cloud Messaging?
You can set the sound property to default so it makes uses the default sound if sound is enabled and it vibrates if the device is on vibrate.
You can update your payload to this:
const payload = {
notification: {
title: "title",
sound: "default"
},
android: {
priority: "high",
ttl: 60 * 60 * 1,
notification: {
channel_id: 'YO',
},
},
apns: {
payload: {
aps: {
sound: "default"
}
},
headers: {
"apns-collapse-id": "yo",
"apns-priority": "10"
}
},
priority: 10
}
For me, I only needed to add it to the notification portion of the message payload.
Below is how it looks in Typescript (but the message JSON is all that matters).
let tokens = ...
let message = {
message: {
notification: {
title: title,
body: body,
sound: 'default', // <----- All I needed
},
data: {
...
},
}
}
firebase.messaging().sendToDevice(tokens, message)
I'm trying to send silent push notification to iOS from could functions, but cannot receive any message.
Here is my payload
const payload = {
apns: {
"headers":{
"apns-priority":"5",
"apns-push-type":"background"
},
payload: {
aps: {
"content-available": 1,
"priority": "high"
}
}
},
data: {
orderId: "123",
orderStatus: "done"
},
token: "fcm_Token_Value_Here"
}
await admin.messaging().send(payload)
Any suggestions what could be the issue?
After short investigation with firebase docs the answer is following:
const payload = {
apns: {
payload: {
aps: {
"contentAvailable": true
}
}
},
data: {
orderId: "123",
orderStatus: "done"
},
token: "fcm_Token_Value_Here"
}
Removed headers part, changed "content-available": 1 to "contentAvailable": true, and removed "priority": "high".
I have started Alexa development very recently. Today I have suddenly started getting
which I did not encounter before.
The lambda function (index.js):
"use strict";
const Alexa = require("ask-sdk-core");
const http = require("http");
exports.handler = async (event, context, callback) => {
try {
if (event.request.type === "LaunchRequest") {
var welcomeMessage = '<speak>Hi</speak>';
callback(null, buildResponse(welcomeMessage, false));
}
else if (event.request.type === "AMAZON.CancelIntent") {
var msg2 = "<speak>Stopped!</speak>";
callback(null, buildResponse(msg2, true));
}
} catch (e) {
context.fail("Exception: ${e}");
}
};
function buildResponse(response, shouldEndSession) {
return {
version: "1.0",
response: {
outputSpeech: {
type: "SSML",
ssml: response
},
shouldEndSession: shouldEndSession
},
sessionAttributes: {}
};
}
package.json file:
{
"name": "third-test-skill",
"version": "1.0.0",
"description": "...",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Subrata Sarkar",
"license": "ISC",
"dependencies": {
"ask-sdk-core": "^2.5.2",
"ask-sdk-model": "^1.15.1"
}
}
Steps I followed to create the skill:
Crated a skill from AWS Alexa console
Created skill
Added sample utterances
Selected Lamda as end point Created a function called movieFacts
Uploaded .zip file containing the following file structure.
node_modules
|- ask-sdk-core
|- ask-sdk-model
|- ask-sdk-runtime
index.js
package.json
package.json.lock
When I say movie facts, I am getting the following message:
The requested skill did not provide a valid response
And this is the JSON output I am receiving:
{
"version": "1.0",
"session": {
"new": false,
"sessionId": "amzn1.echo-api.session.beca8832-50fe-4d17-96a4-30c855b18a4f",
"application": {
"applicationId": "amzn1.ask.skill.bdb88b1b-5a4a-4b37-9b63-71e78337bbca"
},
"user": {
"userId": "amzn1.ask.account.AEG2YALM6KQANVKR3YSUWKVN5DCKE66NJKN23SZIKRKZCVTU67E2JBZ5STPFIN325WNGGO5Z73FMVVL5X2SVEM27YEPD5VFNMPVDQSQK5XYW3NXOXSEIK6YPHE5HTZLGLCWW4VVQHLYECL6YBLG4XOTM2HTV5VCCQMPLVCIATFRSNS4DLHJFLY32JHD5N5MAPFBNRVN3YV7B53A"
}
},
"context": {
"System": {
"application": {
"applicationId": "amzn1.ask.skill.bdb88b1b-5a4a-4b37-9b63-71e78337bbca"
},
"user": {
"userId": "amzn1.ask.account.AEG2YALM6KQANVKR3YSUWKVN5DCKE66NJKN23SZIKRKZCVTU67E2JBZ5STPFIN325WNGGO5Z73FMVVL5X2SVEM27YEPD5VFNMPVDQSQK5XYW3NXOXSEIK6YPHE5HTZLGLCWW4VVQHLYECL6YBLG4XOTM2HTV5VCCQMPLVCIATFRSNS4DLHJFLY32JHD5N5MAPFBNRVN3YV7B53A"
},
"device": {
"deviceId": "amzn1.ask.device.AFXLD474IMHMD5V35NT2ZNUD5YLK2LTEJZUMO6DS2MY7ANONMZDZ67C3MU44OBJ6B5N4TPOXIJ64FBEFEOVOB2K4SSYEN3VTRSIHZETNTBNCDYUG6RGFIOKH7S7OBID6CG3WIHB774LNO4CFKWFUXYSNHD5HIAAXCEDKZ3U4EN7QB6EN4RRHQ",
"supportedInterfaces": {}
},
"apiEndpoint": "https://api.amazonalexa.com",
"apiAccessToken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IjEifQ.eyJhdWQiOiJodHRwczovL2FwaS5hbWF6b25hbGV4YS5jb20iLCJpc3MiOiJBbGV4YVNraWxsS2l0Iiwic3ViIjoiYW16bjEuYXNrLnNraWxsLmJkYjg4YjFiLTVhNGEtNGIzNy05YjYzLTcxZTc4MzM3YmJjYSIsImV4cCI6MTU1NzI0MTIxMCwiaWF0IjoxNTU3MjQwOTEwLCJuYmYiOjE1NTcyNDA5MTAsInByaXZhdGVDbGFpbXMiOnsiY29uc2VudFRva2VuIjpudWxsLCJkZXZpY2VJZCI6ImFtem4xLmFzay5kZXZpY2UuQUZYTEQ0NzRJTUhNRDVWMzVOVDJaTlVENVlMSzJMVEVKWlVNTzZEUzJNWTdBTk9OTVpEWjY3QzNNVTQ0T0JKNkI1TjRUUE9YSUo2NEZCRUZFT1ZPQjJLNFNTWUVOM1ZUUlNJSFpFVE5UQk5DRFlVRzZSR0ZJT0tIN1M3T0JJRDZDRzNXSUhCNzc0TE5PNENGS1dGVVhZU05IRDVISUFBWENFREtaM1U0RU43UUI2RU40UlJIUSIsInVzZXJJZCI6ImFtem4xLmFzay5hY2NvdW50LkFFRzJZQUxNNktRQU5WS1IzWVNVV0tWTjVEQ0tFNjZOSktOMjNTWklLUktaQ1ZUVTY3RTJKQlo1U1RQRklOMzI1V05HR081WjczRk1WVkw1WDJTVkVNMjdZRVBENVZGTk1QVkRRU1FLNVhZVzNOWE9YU0VJSzZZUEhFNUhUWkxHTENXVzRWVlFITFlFQ0w2WUJMRzRYT1RNMkhUVjVWQ0NRTVBMVkNJQVRGUlNOUzRETEhKRkxZMzJKSEQ1TjVNQVBGQk5SVk4zWVY3QjUzQSJ9fQ.UyCg4MXlOe16SlOyJnjAIiHzVpdLkRjd-izoKkUnGqiyZ0L_5eUpg8tKvVrCvTLNMtJS6ElksxgVfuLcNeOIwSbXtYCOXcSLRYbpcpgFI6oeamOZ2Yo-UMDEjzYi75fABuJyUJyZxp-Pieer8PMZO4G9-5zJXCVY2x3M_dmlpX23UBJDpW0DKddvAOzConmwgdaf3v_EWfc2q8BaCQIM950rEUbejOa08_AwE5CsqjNA9sD22QduE5hs09RV4-F-kU1zKvwwyDVDKyOkdFZQFEmCTC11_jI64re9c22e-hYR4leIE5XntNApMgtwaL-tHyjsJzVDVDfZd2q3w6wxYA"
},
"Viewport": {
"experiences": [
{
"arcMinuteWidth": 246,
"arcMinuteHeight": 144,
"canRotate": false,
"canResize": false
}
],
"shape": "RECTANGLE",
"pixelWidth": 1024,
"pixelHeight": 600,
"dpi": 160,
"currentPixelWidth": 1024,
"currentPixelHeight": 600,
"touch": [
"SINGLE"
],
"video": {
"codecs": [
"H_264_42",
"H_264_41"
]
}
}
},
"request": {
"type": "SessionEndedRequest",
"requestId": "amzn1.echo-api.request.c7b1b910-6309-48aa-af35-10ac0a20b5da",
"timestamp": "2019-05-07T14:55:10Z",
"locale": "en-US",
"reason": "ERROR",
"error": {
"type": "INVALID_RESPONSE",
"message": "An exception occurred while dispatching the request to the skill."
}
}
}
I think removing the <speak> and </speak> tags around the welcome message should do. They are by default generated by Alexa, so you don't need to provide them in your response.
What happened in my case (and definitely worth to check) is that I was using Serverless Framework to deploy Lambda and I changed the configuration in the serverless.yml but forgot to update the Lambda ARN in the Alexa Endpoint.
Updating the Endpoint to the correct ARN and rebuilding solved the issue.