I'd like to update attributes from the device using Thingsboard IoT Gateway, but it will not work.
Thingsboard 1.4.0
Thingsboard IoT Gateway 1.2
Mosqquito(Broker)
Node.js(Client)
It all starts up and calls the attribute update API of the device, but the Gateway log does not appear and it does not seem to have arrived.
Client ->(OK) Mosqquito ->(??? no log) Gateway -> Thingsboard
mqtt-config.json uses this as it is.
https://github.com/thingsboard/thingsboard-gateway/blob/master/src/main/resources/mqtt-config.json
teremetoryAPI is working (value has been updated as seen in Console)
Please tell me what settings should be made to update the attributes of the device.
var mqtt = require('mqtt');
var os = require("os");
require('date-utils');
var device = 'T-001';
const thingsboardHost = "mqtt://127.0.0.1:1883";
console.log('Connecting to: %s', thingsboardHost);
var client = mqtt.connect(thingsboardHost, {
will: {topic: device + '/disconnect', payload: '', qos: 1}
});
var appState;
client.on('connect', function () {
publish(device + '/connect', "");
console.log('Client connected!');
// teremetory OK
publish('sensor/' + device + '/temperature', JSON.stringify({"firmware_version":"1.0.2", "value":"37.7"}));
// attribute NG ?????
publish("sensor/" + device + "/appState", JSON.stringify({"appState":"123"}));
});
client.on('message', function (topic, message) {
console.log('Received attribute topic: %s, message: %s', topic, message.toString());
})
function publish (topic, json) {
client.publish(topic, json);
console.log('Client publish. topic[' + topic + "] [" + json + "]");
}
Related
I just build a video call app in flutter for android and ios,
I used callkeep to show incoming call notification and fcm push notification.
In ios it works when the app is in foreground. but it is not showing when the app is in background.
In android it works both in foreground and background.
How to fix this issue?
you should use this package for your case flutter_ios_voip_kit, this is the link: https://pub.dev/packages/flutter_ios_voip_kit
For us the only reliable way to be "called" on iOS was using VoIP. You can use this also with callkeep. However you will need to call the APN not via firebase, but have to implement the call yourself.
In our case this looks like below. And there are several good tutorials on this. For example here: https://levelup.gitconnected.com/send-push-notification-through-apns-using-node-js-7427a01662a2
const key = fs.readFileSync(__dirname + "/AuthKey_XXXXXXXXXX.p8", 'utf8');
//"iat" should not be older than 1 hr from current time or will get rejected
const token = jwt.sign(
{
iss: "XXXXXXXXX", //"team ID" of your developer account
iat: Math.floor(new Date().getTime() / 1000)
},
key,
{
header: {
alg: "ES256",
kid: "XXXXXXXXXXX", //issuer key which is "key ID" of your p8 file
}
}
);
const options = {
':method': 'POST',
':scheme': 'https',
':path': '/3/device/' + deviceToken,
'apns-topic': 'XXX.ANEXAMPLE.ID.voip',//VERY IMPORTANT TO ADD THE .voip here
'apns-push-type': 'voip',
'apns-priority': '10',
'apns-expiration': '0',
'authorization': `bearer ${token}`
};
const uuid = crypto.randomUUID()
fullName = change.data().firstName + ' ' + change.data().lastName;
body = {
uuid: uuid,
caller_id: context.params.callerId,
caller_name: context.params.callerId,
has_video: true,
caller_id_type: "number"
};
strBody = JSON.stringify(body);
console.log("BODY: " + strBody);
let data = '';
const client = http2.connect('https://api.push.apple.com');
buff = Buffer.from(strBody);
req = client.request(options);
req.write(buff);
req.on('response', (headers) => {
for (const name in headers) {
console.log(`${name}: ${headers[name]}`)
}
})
.on('data', (chunk) => { data += chunk })
.on('end', () => {
console.log(`\n${data}`)
client.close()
})
.on('error', (err) => console.error(err));
req.end();
I am trying for a while now to implement this flow: When user adds some files on server app, notification should trigger and send from server to FCM and that from there to pass message saying something like: 'New file has been added'.
Basically I want to inform mobile device user that something on server has been changed.
I have tried many things, but nothing seems to work as I would expect, at least.
On the mobile side I have set up Firebase inside my Xamarin.Android project, and when I am sending notifications directly from Firebase console, I get notifications, and everything is good.
But I don't want to send notifications via Firebase console, I would rather send notification from server (which is ASP.NET MVC project) to Firebase console and then pass it from there to android device.
My first question would be: Has anybody got an idea how can I inform web app about device_id? Is there some way that android device send this information on server? And maybe from there I can store that data and update it occasionally, since it is basically a refresh token.
My second problem is this: Even when I hard code current device_id of an active android device and try to send a message from server whit this code:
public class FirebaseService : IFirebaseService
{
public void SendMessageToClientApplication(string message, string serverApiKey, string senderId, string deviceId)
{
AndroidFCMPushNotificationStatus result = new AndroidFCMPushNotificationStatus();
try
{
result.Successful = false;
result.Error = null;
deviceId = "eMk6mD8P8Dc:APA91bG5Lmqn4Hwb4RZJ1Mkdl8Rf_uYQsQCEfDJK334tzSvIGzdao7o2X6VmtcTEp_Li0mG8iUoUT7-_RnZxQKocHosZwx6ITWdpmQyCwUv60IIIy0vxNlEaccT6RqK6c-cE1C6I3FTT";
var value = message;
WebRequest tRequest = WebRequest.Create("https://fcm.googleapis.com/fcm/send");
tRequest.Method = "post";
tRequest.ContentType = "application/x-www-form-urlencoded;charset=UTF-8";
tRequest.Headers.Add(string.Format("Authorization: key={0}", serverApiKey));
tRequest.Headers.Add(string.Format("Sender: id={0}", senderId));
string postData = "collapse_key=score_update&time_to_live=108&delay_while_idle=1&data.message="
+ value + "&data.time=" + DateTime.Now.ToString() + "®istration_id=" + deviceId + "";
Byte[] byteArray = Encoding.UTF8.GetBytes(postData);
tRequest.ContentLength = byteArray.Length;
using (Stream dataStream = tRequest.GetRequestStream())
{
dataStream.Write(byteArray, 0, byteArray.Length);
using (WebResponse tResponse = tRequest.GetResponse())
{
using (Stream dataStreamResponse = tResponse.GetResponseStream())
{
using (StreamReader tReader = new StreamReader(dataStreamResponse))
{
String sResponseFromServer = tReader.ReadToEnd();
result.Response = sResponseFromServer;
}
}
}
}
}
catch (Exception ex)
{
result.Successful = false;
result.Response = null;
result.Error = ex;
}
}
}
I get nothing both in Firebase console and of course nothing on device as well.
I have tried to implement Firebase web as javascript on my server app like this:
<script>
var config = {
apiKey: "mykey",
authDomain: "myauthdomain",
databaseURL: "mydatabaseurl",
projectId: "myprojectid",
storageBucket: "mystoragebucket",
messagingSenderId: "mysenderid"
};
window.onload = function () {
firebase.initializeApp(config);
const messaging = firebase.messaging();
messaging.requestPermission()
.then(function () {
console.log('Notification permission granted.');
return messaging.getToken()
})
.then(function (token) {
console.log(token);
})
.catch(function (err) {
console.log('Unable to get permission to notify.', err);
});
messaging.onMessage(function (payload) {
console.log('onMessage: ', payload);
});
}
</script>
But this code gets some kind of a different device_id(aka token), probably one generated for that server machine.
Does anybody has experience with sending device_id to server app and from there sending notification message to Firebase console? I would appreciate some code examples, tutorials or anything that can help, since I was unable to find something useful during my google search.
My first question would be: Has anybody got an idea how can I inform web app about device_id?
The most common approach is to store the list of device tokens (each device that uses FCM has such a token) in a database, such as the Firebase Database. There is an example of this in the Cloud Functions for Firebase documentation. In this example the devices receiving the messages are web pages, but the approach is the same for iOS and Android.
I also recommend reading Sending notifications between Android devices with Firebase Database and Cloud Messaging. In this article, instead of sending to a device token, each user subscribes to a topic. That prevents having to manage the device tokens in your code.
i have a ASP.NET Web API hosted as app on Azure and one of the APIs is to send notifications to users on iOS.
i am facing a strange issue on Azure. Sometimes the push notifications work and randomly stop after. I am using PushSharp and not NotificationHub or anything.
the code basically loops over device tokens and makes calls to APNS.
this seems to work fine locally but fails on Azure.
any ideas what i am missing? the error just says multiple errors.
thanks in advance.
var broker = new ApnsServiceBroker(config);
broker.OnNotificationFailed += (notification, exception) =>
{
callback(new Result { status = "FAIL", message = exception.Message });
Console.WriteLine("failed");
};
broker.OnNotificationSucceeded += (notification) =>
{
callback(new Result { status = "Success", message = "" });
Console.WriteLine("pass");
};
broker.Start();
broker.QueueNotification(new ApnsNotification
{
DeviceToken = userDeviceToken,
Payload = JObject.Parse("{ \"aps\" : { \"alert\" : \"" + message + "\", \"sound\":\"default\", \"badge\":0 },\"notification\":" + json + " }")
});
broker.Stop();
I am trying to connect to the Watson TTS API over a Websocket connection in React-Native. The connection is established and I can send a message to the server, however the data that I get back from the server somehow always is empty.
It seems as if the event.data property is completely missing. If I log it to the console in react-native I get 'undefined' as a result. If i use the same code in the browser everything works perfectly.
I am using react-native 0.33 and here's my code:
function connectTTS(token) {
var voice = "de-DE_BirgitVoice";
var format = 'audio/basic';
var token = token;
var wsURI = "wss://stream.watsonplatform.net/text-to-speech/api/v1/synthesize?voice=" + voice + "&watson-token=" + token;
function onOpen(evt) {
var message = {
text: "Hello world.",
accept: format
};
// note: the Text to Speech service currently only accepts a single message per WebSocket connection
websocket.send(JSON.stringify(message));
}
var audioParts = [];
var finalAudio;
function onMessage(evt) {
console.log(evt.data);
if (typeof evt.data === 'string') {
console.log('Received string message: ', evt.data)
} else {
console.log('Received ' + evt.data.size + ' binary bytes', evt.data.type);
audioParts.push(evt.data);
}
}
function onClose(evt) {
console.log('WebSocket closed', evt.code, evt.reason);
console.log(audioParts);
console.log(format);
finalAudio = new Blob(audioParts, {type: format});
console.log('final audio: ', finalAudio);
}
function onError(evt) {
console.log('WebSocket error', evt);
}
var websocket = new WebSocket(wsURI);
websocket.onopen = onOpen;
websocket.onclose = onClose;
websocket.onmessage = onMessage;
websocket.onerror = onError;
}
It would be great if somebody with more react-native / websocket experience could help me find the solution. Thanks.
In react-native up to 0.53 (latest version at the moment), react-native WebSocket event processing relies on event-target-shim 1.1.1 lib which wraps an event and does not include data to the wrapped event, so in order to get WebSocket event data you may use one of two approaches:
Get data from __proto__;
Rewrite event-target-shim 1.1.1;
The first approach:
use <your event>.__proto__.__proto__.data
The second approach:
fork event-target-shim and reset to event-target-shim 1.1.1;
fork react-native;
Add the code listed below to the event-target-shim/lib/event-wrapper.js;
rewrite react-native package.json to use forked version of the event-target-shim;
rewrite package.json of your project;
Code to add in exports.createEventWrapper after var propertyDefinition = {...}:
if (event.type === "message"){
propertyDefinition.data = {value: event.data, enumerable: true};
}
I am trying to POST an image to my grails application and I'm not having much luck.
My titanium code is:
function upload(){
var xhr = Titanium.Network.createHTTPClient();
xhr.onerror = function(e){
Ti.API.info(picMedia + " : " +message.value);
Ti.API.info('IN ERROR ' + e.error);
alert('Sorry, we could not upload your photo! Please try again.');
};
xhr.onload = function(){
Ti.API.info('IN ONLOAD ' + this.status + ' readyState ' + this.readyState);
};
xhr.onsendstream = function(e){
Ti.API.info('ONSENDSTREAM - PROGRESS: ' + e.progress);
};
// open the client
xhr.open('POST', 'http://localhost:8080/FYP/Profile/appUploader');
// send the data
xhr.send({
media: picMedia,
message: message.value,
});
}
My grails code is as follows:
def appUploader(){
println "MEDAI PARAMS: " + params.media
def f = request.getFile('media') ;
println "HERE: " + f
if (request.getFile(params.media).getOriginalFilename()) {
println "FROM APP: " + request.getFile('myFile').getOriginalFilename()
return
}
}
Im getting error from the mobile app and error on the "if" line in the web app.
What am i doing wrong?
we had the same problem in one of our apps. The difficulty is that titanium is not really able to handle binary files in that case.
We did the following:
create base64 encoded string of the image on client side
post this string to the backend
decode base64 to image again
We analyzed a lot of network traffic and in most cases titanium tries to send the file but due to javascript its alway converted into some kind of ascii and this is not usable by the server side.