Before jumping into the technical details, let's start with a basic explanation of Emitter. Emitter is a scalable publish-subscribe platform. Emitter has a generous free tier with all functionality, so feel free to sign up and play around.
Emitter makes use of the MQTT protocol. The MQTT protocol is very light weight, which makes sure battery usage is minimized and bandwidth usage stays very low. An advantage of publish-subscribe systems is that communication between clients is asynchronous. Clients do not need be online at the same time to communicate and clients do not need to know each other’s location (or IP-address). All clients can simply publish messages to a broker and can subscribe to topics to receive messages from that broker. In case of the Emitter cloud system the broker is scalable, so it is a mesh of servers that will always have overcapacity. In case you use the on-premise version of Emitter you can install the broker on your own server or server grid.
Including the fact that Emitter was designed for low latency, this combination of properties makes Emitter very suitable for a wide range of applications, including IoT, online games, web applications and much more.
In the remainder of this documentation we will mainly focus on what developers need to know to work with Emitter. This means the main focus is on the client side and not on the broker side. The four main operations a client can do are:
Developers who are familiar with message queueing systems might think we forgot about ‘creating a topic/channel’ but with Emitter it is not necessary to explicitly do that, you can just start publishing to a channel.
Before being able to publish messages or to subscribe to channels, each client needs to connect to the Emitter broker.
// connect to emitter service
var connection = emitter.connect();Once a client is connected, it will stay connected until it sends a disconnect message, or until it has not been able to ping the Emitter broker for more than 5 minutes.
The following code needs to be executed to disconnect immediately.
// Disconnect from the broker
connection.disconnect();When publishing a message, the client needs to provide at least:
Although it is not mandatory, a message usually also has a body. Finally, you can define how long a message needs to be stored (in seconds). If you omit this part, the message will not be stored. An example of publishing a message is given below.
// publish a message to the chat channel
emitter.publish({
key: "<channel key>",
channel: "chat/my_name",
ttl: 1200,
message: "hello, emitter!"
});Note that you do not explicitly create a channel before starting to publish. A channel is automatically created upon generating a channel key.
There are 2 types of keys; the channel key and the secret key:
emitter.keygen({
key: "<your secret key>",
channel: "chat/#/",
type: "rwls",
ttl: 600
}); Creating a channel key requires the following three parameters in addition to the secret key:
+ to skip any intermediary level.End with #/ to get access to any subchannels (e.g. a key generated for the channel chat/ would not grants you access to chat/user1, unless this key was generated before the introduction of this feature).
For more information about the structure of channels for key generation, see Message filtering.
r - requests a key that can be used for reading (subscribing) from the channel.w - requests a key that can be used for writing (publishing) to the channel.l - requests a key that can be used for loading message history from the channel storage, if this flag is specified, r should also be set.s - requests a key that can be used for storing messages in the channel storage, if this flag is specified, w should also be set.p - request a key that can be used for getting presence information. See presence for more details.Section publish explained that a channel is automatically created if you create a channel key. You can define names for channels yourself. Examples of channel names are:
house/bedroom1/temperaturegame1/user5/zone3/x-coordinateA channel can consist of multiple levels with forward slashes between them. An advantage of using channels with multiple levels is that clients can use filtering and wildcards to subscribe to parts of the complete channel. Channel names are case sensitive. Emitter supports the following characters:
0-9a-zA-Z., :, -Emitter is a binary messaging system. This means you can send text, audio data, images, executables or any other message type you desire. The only limitation is the message size. By default this is limited to 64KB. If you require a larger message size, please contact us so we can set up the system differently for you. If you try to send a message that is too large, the message will not be published and you will get an error message.
When subscribing to a channel, the client needs to provide the key and the channel name. An example of subscribing to a message is given below.
// once we're connected, subscribe to the 'chat' channel
emitter.on('connect', function(){
emitter.subscribe({
key: "<channel key>",
channel: "chat",
last: 5
});
});A client can connect to a complete channel, or single- or multi-level filtering can be used. The last argument is optional. It defines how many messages are retrieved from storage at the moment of connecting. If the argument is omitted, no messages are retrieved from history. This will only work if the channel key authorizations are defined to give access for retrieving from history. When retrieving from history, the last created messages are retrieved, they are retrieved in the same sequence at which they were stored.
Finally, it is also possible to unsubscribe from the channel.
// unsubscribe from the 'chat' channel
emitter.unsubscribe({
key: "<channel key>",
channel: "chat"
});The format of the request is similar to the subscription one, you'll need to provide the key with subscription permissions to the target channel and the channel name.
Sometimes, you might need to retrieve some information about the underlying client connection, which can be done by sending a me request to emitter. Currently, the broker only sends a globally unique identifier of the connection, but more information may be added in the future.
emitter.on('me', function(conn){
console.log('Connection id : ' + conn.id);
});
// retrieve connection info
emitter.me();