Is it possible to connect to the Google IOTCore MQTT Bridge via Javascript? - google-cloud-platform

I've been trying to use the javacscript version of the Eclipse Paho MQTT client to access the Google IOTCore MQTT Bridge, as suggested here:
https://cloud.google.com/iot/docs/how-tos/mqtt-bridge
However, whatever I do, any attempt to connect with known good credentials (working with other clients) results in this connection error:
errorCode: 7, errorMessage: "AMQJS0007E Socket error:undefined."
Not much to go on there, so I'm wondering if anyone has ever been successful connecting to the MQTT Bridge via Javascript with Eclipse Paho, the client implementation suggested by Google in their documentation.
I've gone through their troubleshooting steps, and things seem to be on the up and up, so no help there either.
https://cloud.google.com/iot/docs/troubleshooting
I have noticed that in their docs they have sample code for Java/Python, etc, but not Javascript, so I'm wondering if it's simply not supported and their documentation just fails to mention as such.
I've simplified my code to just use the 'Hello World' example in the Paho documentation, and as far as I can tell I've done things correctly (including using my device path as the ClientID, the JWT token as the password, specifying an 'unused' userName field and explicitly requiring MQTT v3.1.1).
In the meantime I'm falling back to polling via their HTTP bridge, but that has obvious latency and network traffic shortcomings.
// Create a client instance
client = new Paho.MQTT.Client("mqtt.googleapis.com", Number(8883), "projects/[my-project-id]/locations/us-central1/registries/[my registry name]/devices/[my device id]");
// set callback handlers
client.onConnectionLost = onConnectionLost;
client.onMessageArrived = onMessageArrived;
// connect the client
client.connect({
mqttVersion: 4, // maps to MQTT V3.1.1, required by IOTCore
onSuccess:onConnect,
onFailure: onFailure,
userName: 'unused', // suggested by Google for this field
password: '[My Confirmed Working JWT Token]' // working JWT token
function onFailure(resp) {
console.log(resp);
}
// called when the client connects
function onConnect() {
// Once a connection has been made, make a subscription and send a message.
console.log("onConnect");
client.subscribe("World");
message = new Paho.MQTT.Message("Hello");
message.destinationName = "World";
client.send(message);
}
// called when the client loses its connection
function onConnectionLost(responseObject) {
if (responseObject.errorCode !== 0) {
console.log("onConnectionLost:"+responseObject.errorMessage);
}
}
// called when a message arrives
function onMessageArrived(message) {
console.log("onMessageArrived:"+message.payloadString);
}

I'm a Googler (but I don't work in Cloud IoT).
Your code looks good to me and it should work. I will try it for myself this evening or tomorrow and report back to you.
I've spent the past day working on a Golang version of the samples published on Google's documentation. Like you, I was disappointed to not see all Google's regular languages covered by samples.
Are you running the code from a browser or is it running on Node.JS?
Do you have a package.json (if Node) that you would share too please?
Update
Here's a Node.JS (JavaScript but non-browser) that connects to Cloud IoT, subscribes to /devices/${DEVICE}/config and publishes to /devices/${DEVICE}/events.
https://gist.github.com/DazWilkin/65ad8890d5f58eae9612632d594af2de
Place all the files in the same directory
Replace values in index.js of the location of Google's CA and your key
Replaces [[YOUR-X]] values in config.json
Use "npm install" to pull the packages
Use node index.js
You should be able to pull messages from the Pub/Sub subscription and you should be able to send config messages to the device.

Short answer is no. Google Cloud IoT Core doesn't support WebSockets.
All the JavaScript MQTT libraries use WebSocket because JavaScript is restricted to perform HTTP requests and WebSocket connections only.

Related

Connection to Google IoT with Hive MQTT client instead of Paho

I have working code similar to this connecting to google IoT with the paho client.
Since I am in a spring boot reactive application, I would like to use Hive MQTT Client, but I can't find the right setup, I keep having the following error message :
com.hivemq.client.mqtt.exceptions.ConnectionClosedException: Server closed connection without DISCONNECT.
The current code I use :
hiveClient = MqttClient.builder()
.identifier(UUID.randomUUID().toString())
.serverHost("mqtt.googleapis.com")
.serverPort(443)
.useMqttVersion3()
.sslWithDefaultConfig()
.simpleAuth(
Mqtt3SimpleAuth.builder()
.username("unused")
.password(StandardCharsets.UTF_8.encode("// a token string generation that works fine with palo"))
.build()
)
.build()
.toBlocking();
hiveClient.connect(); // Error
It looks like the identifier (client ID) should be set to something other than a UUID. The documentation indicates the client ID should be formed as the following path:
projects/PROJECT_ID/locations/REGION/registries/REGISTRY_ID/devices/DEVICE_ID
Note that all of the requirements for the Google Cloud IoT Core MQTT device bridge are strict, so also verify that Hive is configured as follows:
Mqtt 3.1.1
TLS 1.2
Publish to /devices/DEVICE_ID/events or /devices/DEVICE_ID/state
Subscribe to /devices/DEVICE_ID/config or /devices/DEVICE_ID/commands/#
QoS 0 or 1
Note that if you do not adhere to the requirements, your device gets disconnected. Additional information on the disconnect reason may be available in the logging for your registry visible on the Cloud Console for IoT.

How to send Firebase Cloud Message with AWS SNS? [duplicate]

I am using AWS resources for my android project, I am planning to add push notification service for my project with AWS SNS.there are few questions bothering me much. I did not find any questions regarding these, except one or two but with unclear explanations.
1.Does AWS support FCM? SNS work with GCM. But Google recommends to use FCM instead of GCM. I did not find AWS supporting FCM.
2.Do AWS store messages (or data) into their databases even after sending push notifications?
3.I tried putting FCM api key in SNS application platform, it is showing invalid parameters why?
FCM is backwards compatible with GCM. The steps for setting up FCM on AWS are identical to the GCM set up procedure and (at least for the moment) FCM works transparently with GCM and SNS with respect to server-side configuration.
However, if you are sending data payloads to the Android device they will not be processed unless you implement a client side service that extends FirebaseMessagingService. The default JSON message generator in the AWS console sends data messages, which will be ignored by your app unless the aforementioned service is implemented. To get around this for initial testing you can provide a custom notification payload which will be received by your device (as long as your app is not in the foreground)
There are GCM-FCM migration instructions provided by Google however the changes you need to make are predominantly on the App side.
The steps you need to follow to test GCM/FCM on your app with SNS are:
Create a Platform Application in SNS, selecting Google Cloud Messaging (GCM) as the Push Notification Platform, and providing your Server API key in the API key field.
Select the Platform Application and click the Create platform endpoint button.
Provide the InstanceID (Device Token) generated by your app. You must extend the FirebaseInstanceIDService and override the onTokenRefresh method to see this within your Android App. Once you have done this, uninstall and reinstall your app and your token should be printed to the Debug console in Android Studio on first boot.
Click the Add endpoint button.
Click on the ARN link for your platform application.
Select the newly created Endpoint for your device and click the Publish to endpoint button.
Select the JSON Message Format, and click the JSON message generator button.
Enter a test message and click the Generate JSON button
Now comes the "gotcha part".
The message that is generated by SNS will be of the form:
{
"GCM": "{ \"data\": { \"message\": \"test message\" } }"
}
As we mentioned earlier, data payloads will be ignored if no service to receive them has been implemented. We would like to test without writing too much code, so instead we should send a notification payload. To do this, simply change the JSON message to read:
{
"GCM": "{ \"notification\": { \"title\": \"test title\", \"body\": \"test body\" } }"
}
(For more information about the JSON format of an FCM message, see the FCM documentation.)
Once you have done this, make sure your app is not running on the device, and hit the Publish Message button. You should now see a notification pop up on your device.
You can of course do all this programmatically through the Amazon SNS API, however all the examples seem to use the data payload so you need to keep that in mind and generate a payload appropriate to your use case.
Now you can go to your firebase console (https://console.firebase.google.com/) select your project, click the gear icon and choose project settings, then click on the cloud messaging tab...
You'll see the legacy Server Key which is the GCM API Key and you'll have the option to generate new Server Keys which are the FCM versions
SNS will accept both versions but their menu option is still categorizing it under GCM
Here is picture for your reference:
Note that you can "accidentally" remove your Server Keys but the Legacy server key is not deletable. Also, if you click the add server key button, you'll get a new server key BELOW the first one, WITH NO WARNING! ...Nice job Google ;)
One more additional note to Nathan Dunn's great answer.
How to send data with the notification from SNS to Firebase.
We need to add data to the Json (inside the notification):
{
"default": “any value",
"GCM": "{ \"notification\": { \"body\": \”message body\”, \”title\”: \”message title \”, \"sound\":\"default\" } , \"data\" : {\”key\" : \”value\", \”key2\" : \”value\” } }”
}
In your FirebaseMessagingService implementation (Xamarin example)
public override void OnMessageReceived(RemoteMessage message)
{
try
{
var body = message?.GetNotification()?.Body;
var title = message?.GetNotification()?.Title;
var tag = message?.GetNotification()?.Tag;
var sound = message?.GetNotification()?.Sound;
var data = message?.Data
foreach (string key in data.Keys)
{
// get your data values here
}
}
catch (Exception e)
{
}
}
I tried to use solution with notification payload instead of data, but I did not receive push notifications on the mobile device. I found this tutorial https://youtu.be/iBTFLu30dSg with English subtitles of how to use FCM with AWS SNS step by step and example of how to send push notifications from AWS console and implement it on php with aws php sdk. It helped me a lot.
Just an additional note to Nathan Dunn's Answer: to add sound use the following JSON message
{
"GCM": "{ \"notification\": { \"text\": \"test message\",\"sound\":\"default\" } }"
}
It took me a while to figure out how to send the notification with the right payload (publish to topic). So I will put it here.
private void PublishToTopic(string topicArn)
{
AmazonSimpleNotificationServiceClient snsClient =
new AmazonSimpleNotificationServiceClient(Amazon.RegionEndpoint.EUWest1);
PublishRequest publishRequest = new PublishRequest();
publishRequest.TopicArn = topicArn;
publishRequest.MessageStructure = "json";
string payload = "\\\"data\\\":{\\\"text\\\":\\\"Test \\\"}";
publishRequest.Message = "{\"default\": \"default\",\"GCM\":\"{" + payload + "}\"}";
PublishResponse publishResult = snsClient.Publish(publishRequest);
}
Amazon does support FCM as all previous code has been migrated from GCM to FCM. Below article explains in detail.
Article Published by Amazon
To answer the questions:
AWS SNS does support FCM.
No AWS does not store messages after sending push notifications.
For a detailed tutorial on setting up FCM with SNS please read this article.

aws-cpp-sdk : How to IoT publish using MQTT over Web Socket (in c++)

I did a lot of research (here and on github) to find out how Iot Data Plane class works.
I wonder how I could publish data on a topic with the c++ sdk and use of port 443. I would like to establish my connection, and have the connection alive until I close it.
In brief, I need help to use the cpp sdk to send MQTT over Web Socket, on Linux.
Does anyone can help?
Aws::SDKOptions options;
options.loggingOptions.logLevel = Aws::Utils::Logging::LogLevel::Info;
Aws::InitAPI(options);
Aws::Auth::AWSCredentials credentials;
credentials.SetAWSAccessKeyId("a valid key id generated in Aws IAM");
credentials.SetAWSSecretKey("a valid secret key generated in Aws IAM");
Aws::IoTDataPlane::IoTDataPlaneClient client(credentials);
Aws::IoTDataPlane::Model::PublishRequest request;
std::shared_ptr<Aws::StringStream> stream = std::make_shared<Aws::StringStream>("Something to publish.");
request.SetBody(stream);
request.SetTopic("MyTopic");
Aws::IoTDataPlane::Model::PublishOutcome outcome(client.Publish(request));
if(outcome.IsSuccess())
{
printf("Success");
}
else
{
printf("%s", outcome.GetError().GetMessage().c_str());
}
Aws::ShutdownAPI(options);
What I want to do is not yet possible, as answered by a software engineer of Aws on Git Hub.
https://github.com/aws/aws-sdk-cpp/issues/594
the c++ sdk does not support mqtt at the moment. We have plans to add this to an upcoming c99 sdk. We'll keep you posted. In the meantime, if you need to use mqtt you can use the iot sdk.

Need qpid-proton publish/subscribe amqp sample program for python to access Azure topic

I am using Azure cloud service bus to send and receive messages using AMQP protocol. I have installed proton-c libraries in my debian-linux. I tried the below program to send and receive message from the queue. My requirement is instead of queue I have use topics. Please anyone give me a sample program to use topics in Azure cloud.
import sys, optparse
from proton import *
messenger = Messenger()
message = Message()
message.address = "amqps://owner:<<key>>#namespace.servicebus.windows.net/queuename"
message.body = "sending message to the queue"
messenger.put(message)
messenger.send()
Instead of queuename in above url if I give the topic name then the program running forever. Please someone help me. I am new to python programming.
I found myself the solution for this problem. I guess very few people are working in Azure Cloud so I didn't get any answers.
Here is the solution:
If we create topics in Azure service bus, it always select the checkbox "Enable Partitioning". AMQP protocol doesn't support partitioning topics/queues so I stuck with above issue. Once I deleted the topic and recreate the same topic without select the checkbox "Enable Partitioning". Its work fine. :)

Use ColdFusion to read events over a TCP/IP stream

Our new phone system is making use of Asterisk manager API which allows to read events and issue commands over a TCP/IP stream. My question is.. Is there any way at all to use ColdFusion to read (and in-turn process) the stream of events? As of now I'm able to view the phone events (incoming calls, transfers, hang-ups etc) via telnet and I'm wondering if it's possible to use a ColdFusion event gateway to process these events as they come over?
Once the initial connection is made (via telnet), I have to submit the following key:values in order to authenticate the connection before the stream begins.
Action: login<CRLF>
Username: usr<CRLF>
Secret: abc123<CRLF>
<CRLF>
Just wanted to specify that as I'm not sure if that's a deal-breaker with possibly using a web service in this manner. Also note we are using ColdFusion 10 Enterprise.
I realize this is an old thread, but I am posting this in case it helps the next guy ....
AFAIK, it cannot be done with a standard CF Event Gateway. However, one possibility is using Asterisk-Java. It is a java library that allows communication with an Asterisk Server. More specifically it Manager interface:
... is capable of sending [actions] and receiving [responses] and
[events]. It does not add any further functionality but rather
provides a Java view to Asterisk's Manager API (freeing you from
TCP/IP connection and parsing stuff).
So it can be used to issue commands to the server, and receive events, just like telnet.
Starter example:
Download the Asterisk-Java jar and load it via this.javaSettings in your Application.cfc
Create a ManagerConnection with the settings for your Asterisk server
factory = createObject("java", "org.asteriskjava.manager.ManagerConnectionFactory");
connection = factory.init( "hostNameOrIP"
, portNum
, "userName"
, "theSecret" ).createManagerConnection();
Create a CFC to act as a listener. It will receive and handle events from Asterisk:
component {
public void function onManagerEvent(any managerEvent)
{
// For demo purposes, just output a summary of the event
WriteLog( text=arguments.managerEvent.toString(), file="AsteriskLog" );
}
}
Using a bit of dynamic proxy magic, register the CFC with the connection:
proxyListener = createDynamicProxy("path.YourCFCListener"
, ["org.asteriskjava.manager.ManagerEventListener"]);
connection.addEventListener( proxyListener );
Login to the server to begin receiving events. Setting the appropriate event level: "off", "on" or csv list of available events - "system", "call" and/or "log".
connection.login("on");
Run a simple "Ping" test to verify everything is working. Then sleep for a few seconds to allow some events to flow. Then close the connection.
action = createObject("java", "org.asteriskjava.manager.action.PingAction").init();
response = application.connection.sendAction(action);
writeDump(response.getResponse());
// disconnect and stop events
sleep(4000);
connection.logoff();
Check the demo log file. It should contain one or more events.
"Information","http-bio-8500-exec-4","10/14/16","15:17:19","XXXXX","org.asteriskjava.manager.event.ConnectEvent[dateReceived=Fri Oct 14 15:17:19 CDT 2016,....]"
NB: In a real application, the connection would probably be opened once, in OnApplicationStart, and stored in a persistent scope.
Events would continue to stream as long as the connection remained open. The connection should only be closed when the application
ends, to halt event streaming.
Yes-- you'd want to use a Socket Gateway. Ben Nadel has a great writeup about how to do this: Using Socket Gateways To Communicate Between ColdFusion And Node.js
Although he uses Node.js in his example, you should be able to use his guide to set up the Socket Gateway, then handle the data passed to it as you see fit.
What you want is a server-side TCP client. I suggest easySocket, a simple UDF that allows you to send TCP messages via Coldfusion by utilizing Java sockets.