Internet of Things (XEP-0323, -0324, -0325, -0347)

The Internet of Things (IoT) XEPs are an experimental open standard how XMPP can be used for IoT. They currently consists of - XEP-0323 Sensor Data - XEP-0324 Provisioning - XEP-0325 Control - XEP-0326 Concentrators - XEP-0347 Discovery

Smack only supports a subset of the functionality described by the XEPs!

Thing Builder

The org.jivesoftware.smackx.iot.Thing class acts as basic entity representing a single "Thing" which can used to retrieve data from or to send control commands to. Things are constructed using a builder API.

Reading data from things

For example, we can build a Thing which provides the current temperature with

Thing dataThing = Thing.builder().setKey(key).setSerialNumber(sn).setMomentaryReadOutRequestHandler(new ThingMomentaryReadOutRequest() {
    public void momentaryReadOutRequest(ThingMomentaryReadOutResult callback) {
        int temp = getCurrentTemperature();
        IoTDataField.IntField field = new IntField("temperature", temp);

While not strictly required, most things are identified via a key and serial number. We also build the thing with a "momentary read out request handler" which when triggered, retrieved the current temperature and reports it back to the requestor.

After the Thing is build, it needs to be made available so that other entities within the federated XMPP network can use it. Right now, we only intall the Thing in the IoTDataManager, which means the thing will act on read out requests but not be managed by a provisioning server.

IoTDataManager iotDataManager = IoTDataManager.getInstanceFor(connection);

The data can be read out also by using the IoTDataManager:

FullJid jid = …
List<IoTFieldsExtension> values = iotDataManager.requestMomentaryValuesReadOut(jid);

Now you have to unwrap the IoTDataField instances from the IoTFieldsExtension. Note that Smack currently only supports a subset of the specified data types.

Controlling a thing

Things can also be controlled, e.g. to turn on a light. Let's create thing which can be used to turn the light on and off.

Thing controlThing = Thing.builder().setKey(key).setSerialNumber(sn).setControlRequestHandler(new ThingControlRequest() {
    public void processRequest(Jid from, Collection<SetData> setData) throws XMPPErrorException {
        for (final SetData data : setData) {
            if (!data.getName().equals("light")) continue;
            if (!(data instanceof SetBoolData)) continue;
            SetBoolData boolData = (SetBoolData) data;

No we have to install this thing into the IoTControlManager:

IoTControlManager iotControlManager = IoTControlManager.getInstanceFor(connection);

The IoTControlManager can also be used to control a thing:

FullJid jid = …
SetData setData = new SetBoolData("light", true);
iotControlManager.setUsingIq(jid, setData);

Smack currently only supports a subset of the possible data types for set data.


You may wondered how a full JIDs of things can be determined. One approach is using the discovery mechanisms specified in XEP-0347. Smack provides the IoTDiscoveryManager as API for this.

For example, instead of just installing the previous things in the IoTDataManager and/or IoTControlManager, we could also use the IoTDiscoveryManger to register the thing with a registry. Doing thing also installs the thing in the IoTDataManager and the IoTControlManager.

IoTDiscoveryManager iotDiscoveryManager = IoTDiscoveryManager.getInstanceFor(connection);

The registry will now make the thing known to a broader audience, and available for a potential owner.

The IoTDiscoveryManager can also be used to claim, disown, remove and unregister a thing.


Things can usually only be used by other things if they are friends. Since a thing normally can't decide on its own if an incoming friendship request should be granted or not, we can delegate this decission to a provisioning service. Smack provides the IoTProvisinoManager to deal with friendship and provisioning.

For example, if you want to befriend another thing:

BareJid jid = …
IoTProvisioningManager iotProvisioningManager = IoTProvisioningManager.getInstanceFor(connection);