Is it possible to have more than one simultaneous connection to the specified IoT Watson device via the MQTT client? - ibm-watson

A unique client id having a specific format (d:organizationID:deviceType:deviceID) is used for connection to MQTT in IoT Watson.
It looks that only one unique MQTT connection is allowed per client id to a specific device.
For some cases is required to have more than one simultaneous MQTT connection to the specific device inside the organization account, e.g., in the case of scaling of services integrated with the IBM Watson platform (i.e. clustering).
The question will be, is there the possibility to have more than one simultaneous MQTT connection to the specific device inside the organization account?
For example, by having the possibility to generate a client id or some part of the client id?

It is not possible for devices. The clientId has to be unique as you said and so any existing connection using that clientId would be disconnected when the new connections is made. I am not quite sure I understand the use case you mention with clustering, as the one connection should be fine for a device.
If you have an application rather than a device then you can create a "Scalable Application" as mentioned here https://www.ibm.com/docs/en/watson-iot-platform?topic=applications-communicating-mqtt which extends the clientId.

Related

Webapp server data storage: Memory vs database

We are making a web application in Go with a MySQL database. Our users are allowed to only have one active client at a time. Much like Spotify allows you to only listen to music on one device at a time. To do this I made a map with as key the user ids and a reference to their active websocket connection as a value. Based on the websocket id that the client has to send in the header of the request we can identify weather the request comes from their active session.
My question is if it's a good practice to store data (in this case the map with the user ids and websockets) in a global space or is it better to store it in the database.
We don't expect to reach over 10000 simultaneously active clients. Average is probably gonna be around 1000.
If you only run one instance of the websocket server storing it in memory should be sufficient. Because if it for some reason goes down/restarts then all the connections will be lost and all the clients will have to create them again (and hence the list of connection will once again be populated by all the clients who want to use the service).
However, if you plan on scaling it horizontally so you have multiple websocket services behind a load balancer, then the connections may need to be stored in a database of some sort. And not because it necessarily needs to be more persistant but because you need to be able to check the request against all the services connections.
It is also possible to have a separate service which handles the incoming request and asks all the websocket services if any of them have the connection specified in the request. This could be done if you add a pub/sub queue and every websocket service subscribes to channels for all its websocket ids and the service that receives the request then publishes the websocket id, and the websocket services can then send back replies on a separate channel if they have that connection. You must decide how to handle if no one is responding (no websocket service has the websocket id). Either the channel does not exist, or you expect the answer within a specific time. Or you could publish the question on a general topic and expect all the websocket services to reply (yes or no).
And regarding whether you need to scale it I guess depends mostly on the underlying server you're running the service on. If I understand it correctly the websocket service will basically not do anything except from keeping track of its connections (you should add some ping pong to discover if connections are lost). Then your limitation should mainly be on how many file descriptors your system can handle at once. If that limit is much larger than your expected maximum number of users, then running only one server and storing everything in memory might be an OK solution!
Finally, if you're in the business of having a websocket open for all users, why not do all the "other" communication over that websocket connection instead of having them send HTTP requests with their websocket id? Perhaps HTTP fits better for your use case but could be something to think about :)

What is the best way to determine the connection state of an AWS IoT device?

How can I determine if a particular AWS IoT device is currently online? I could send an MQTT message and make the device answer it. But is there some implicit way on seeing if a device is online/connected?
You can also use Fleet Indexing with enabled Connectivity Indexing
https://docs.aws.amazon.com/iot/latest/developerguide/managing-index.html and do search for your deviceId. In results you can check connectivity. Also you can search for all connected devices by using search with query connectivity.connected:true
Ok, there is a dedicated internal MQTT topic for it. Subscribe to $aws/events/presence/# to get presence events for all your devices.

WebRTC and authentication implementations

Ok so recently I have been in need of creating a application with WebRTC for video voice etc.
So after looking into some libraries I found SimpleWebRTC to be pretty handly looking:
https://github.com/andyet/SimpleWebRTC
So what I am interested in is how do I implement a STUN/TURN server? (Would be great if someone could explain the differences in plain English!) And also is there a authentication mechanism. At the moment my app contacts my database and logins in user etc, but the stun and turn server would be private and not in any way involved in the authentication procedure.
So basically:
What is the best way to implement STUN/TURN
Is there any authentication mechanism?
Note, this is for a hybrid app so I will be using JavaScript/AngularJS for this. The main reason why I chose SimpleWebRTC.
Thank you!
I suggest you use an existing STUN or TURN server like coturn.
STUN servers are very lightweight and often left without authentication. A STUN server basically tells a client what its IP address appears to be, which is necessary to make peer connections across NAT (network address translation) boundaries.
TURN servers are very resource intensive because they relay media; all of the media for a call can go through the TURN server, so it's important to secure TURN. You use TURN servers in situations where UDP may be blocked, or for particular kinds of NATs that cause problems.
The authentication for coturn's TURN server can take one of two forms:
Simple (username, password) pair
TURN REST API. This uses a secret between the TURN server and another entity. The entity issues tokens with expiration times, and the TURN server verifies the token has not expired and was issued with knowledge of the shared secret. This is passed by the TURN client as a username, password pair in a format described in the documentation.

User Destinations with Stomp, Spring Websockets, an External Broker with an External Consumer

My Question centers around this slide from one of Rossen Stoyanchev webinars.
When using a simpleBroker I can send messages to individual users with the /user/** destination format that is picked up in UserDestination and converted. I can also use it to send to a specific session, or all sessions of a specific user.
This is also possible when using an External Broker like ActiveMQ or RabbitMQ as long as the sender is also able to use /user/** or its helper annotations #SentToUser etc.
But, if I am not processing these messages locally and I have another consumer connected to the External Message Broker (Apache Camel for example) How do handle User specific messages and also reply at a user and session level?
If the other consumer is in the same JVM you can have the "brokerMessagingTemplate" bean injected and use it to send messages to user-prefixed destinations.
For 4.2 we plan to support user destinations in a deployment with multiple web application servers connected to an External broker (see https://jira.spring.io/browse/SPR-11620). So if the other consumer is in a different JVM, then you could declare the #EnableWebSocketMessageBroker setup in that JVM as well or you could simple extend AbstractMessageBrokerConfiguration if you don't need the WebSocket client bits.
HTH

Google App Engine Channel Token and Client ID relationship

In Google App Engine documentation for Channel API, it is stated that "Only one client at a time can connect to a channel using a given Client ID".
In contradiction, when I try to create a channel with the same Client ID, a new channel is consumed. In other words, when I call creat channel api for ClientID "user_one" channelService.createChannel("user_one"); for ten times, 10 different channels with 10 different token strings would be created, and when I send a message to "user_one" channelService.sendMessage(new ChannelMessage("user_one", message));, all of the ten clients on different devices, would receive the message!
How would you describe this scenario ? How one can benefit from this mechanism (one clientID with different channel, all receiving same message)? how to prevent it from creating multiple channel for single user ?
The documentation is not complete but it describes its intent pretty well. It says:
Only one client at a time can connect to a channel using a given Client ID, so an application cannot use a Client ID for fan-out. In other words, it's not possible to create a central Client ID for connections to multiple clients (For example, you can't create a Client ID for something like a "global-high-scores" channel and use it to broadcast to multiple game clients.)
It's up to you to keep track of the of the number of channels you create for each ClientID. From my experience, what you describe works, but not reliably. The newest channel created with the ClientID works, the older ones, sometimes work, sometimes don't receive messages.
Note that if you're trying this out on the dev_appserver, all the clients receive messages, but on the real server this behavior is not the same.

Resources