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!
The org.jivesoftware.smackx.iot.Thing
class acts as basic entity representing a single "Thing" which can be used to retrieve data from or to send control commands to. Things
are constructed using a builder API.
For example, we can build a Thing which provides the current temperature with
Thing dataThing = Thing.builder().setKey(key).setSerialNumber(sn).setMomentaryReadOutRequestHandler(new ThingMomentaryReadOutRequest() {
@Override
public void momentaryReadOutRequest(ThingMomentaryReadOutResult callback) {
int temp = getCurrentTemperature();
IoTDataField.IntField field = new IntField("temperature", temp);
callback.momentaryReadOut(Collections.singletonList(field));
}
}).build();
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, retrieves the current temperature and reports it back to the requestor.
After the Thing
is built, it needs to be made available so that other entities within the federated XMPP network can use it. Right now we only install 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);
iotDataManager.installThing(thing);
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.
Things can also be controlled, e.g. to turn on a light. Let's create a thing which can be used to turn the light on and off.
Thing controlThing = Thing.builder().setKey(key).setSerialNumber(sn).setControlRequestHandler(new ThingControlRequest() {
@Override
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;
setLight(boolData.getBooleanValue());
}
}
}).build();
Now we have to install this thing into the IoTControlManager
:
IoTControlManager iotControlManager = IoTControlManager.getInstanceFor(connection);
iotControlManager.installThing(thing);
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 have 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 an 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 this also installs the thing in the IoTDataManager
and the IoTControlManager
.
IoTDiscoveryManager iotDiscoveryManager = IoTDiscoveryManager.getInstanceFor(connection);
iotDiscovyerManager.registerThing(thing);
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 decision 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);
iotProvisioningManager.sendFriendshipRequest(jid);