2016-07-20 20:57:04 +02:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* Copyright 2016 Florian Schmaus
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
package org.igniterealtime.smack.smackrepl;
|
|
|
|
|
2016-10-31 12:24:05 +01:00
|
|
|
import java.io.IOException;
|
2016-07-20 20:57:04 +02:00
|
|
|
import java.util.Collections;
|
|
|
|
import java.util.List;
|
|
|
|
import java.util.concurrent.TimeoutException;
|
|
|
|
|
|
|
|
import org.jivesoftware.smack.ConnectionConfiguration.SecurityMode;
|
|
|
|
import org.jivesoftware.smack.SmackException;
|
2017-06-14 17:12:43 +02:00
|
|
|
import org.jivesoftware.smack.XMPPException;
|
|
|
|
import org.jivesoftware.smack.packet.Presence;
|
|
|
|
import org.jivesoftware.smack.roster.Roster;
|
|
|
|
import org.jivesoftware.smack.roster.RosterUtil;
|
2016-07-20 20:57:04 +02:00
|
|
|
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
|
|
|
|
import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
|
|
|
|
import org.jivesoftware.smack.util.StringUtils;
|
2017-06-14 17:12:43 +02:00
|
|
|
|
2016-07-20 20:57:04 +02:00
|
|
|
import org.jivesoftware.smackx.iot.IoTDiscoveryIntegrationTest;
|
|
|
|
import org.jivesoftware.smackx.iot.Thing;
|
|
|
|
import org.jivesoftware.smackx.iot.data.IoTDataManager;
|
|
|
|
import org.jivesoftware.smackx.iot.data.ThingMomentaryReadOutRequest;
|
|
|
|
import org.jivesoftware.smackx.iot.data.ThingMomentaryReadOutResult;
|
|
|
|
import org.jivesoftware.smackx.iot.data.element.IoTDataField;
|
|
|
|
import org.jivesoftware.smackx.iot.data.element.IoTDataField.IntField;
|
|
|
|
import org.jivesoftware.smackx.iot.data.element.IoTFieldsExtension;
|
|
|
|
import org.jivesoftware.smackx.iot.discovery.AbstractThingStateChangeListener;
|
|
|
|
import org.jivesoftware.smackx.iot.discovery.IoTDiscoveryManager;
|
|
|
|
import org.jivesoftware.smackx.iot.discovery.ThingState;
|
2016-10-31 12:24:05 +01:00
|
|
|
import org.jivesoftware.smackx.iot.provisioning.BecameFriendListener;
|
2016-07-20 20:57:04 +02:00
|
|
|
import org.jivesoftware.smackx.iot.provisioning.IoTProvisioningManager;
|
2017-06-14 17:12:43 +02:00
|
|
|
|
|
|
|
import org.igniterealtime.smack.inttest.util.SimpleResultSyncPoint;
|
2016-07-20 20:57:04 +02:00
|
|
|
import org.jxmpp.jid.BareJid;
|
|
|
|
import org.jxmpp.jid.EntityBareJid;
|
|
|
|
import org.jxmpp.jid.impl.JidCreate;
|
|
|
|
|
|
|
|
public class IoT {
|
|
|
|
|
|
|
|
// A 10 minute timeout.
|
|
|
|
private static final long TIMEOUT = 10 * 60 * 1000;
|
|
|
|
|
2016-10-31 12:24:05 +01:00
|
|
|
private interface IotScenario {
|
|
|
|
void iotScenario(XMPPTCPConnection dataThingConnection, XMPPTCPConnection readinThingConnection) throws XMPPException, SmackException, IOException, InterruptedException, TimeoutException, Exception;
|
|
|
|
}
|
|
|
|
|
2016-07-20 20:57:04 +02:00
|
|
|
public static void iotScenario(String dataThingJidString, String dataThingPassword, String readingThingJidString,
|
2016-10-31 12:24:05 +01:00
|
|
|
String readingThingPassword, IotScenario scenario) throws TimeoutException, Exception {
|
2016-07-20 20:57:04 +02:00
|
|
|
final EntityBareJid dataThingJid = JidCreate.entityBareFrom(dataThingJidString);
|
|
|
|
final EntityBareJid readingThingJid = JidCreate.entityBareFrom(readingThingJidString);
|
|
|
|
|
|
|
|
final XMPPTCPConnectionConfiguration dataThingConnectionConfiguration = XMPPTCPConnectionConfiguration.builder()
|
2016-10-31 12:24:05 +01:00
|
|
|
.setUsernameAndPassword(dataThingJid.getLocalpart(), dataThingPassword)
|
|
|
|
.setXmppDomain(dataThingJid.asDomainBareJid()).setSecurityMode(SecurityMode.disabled)
|
2017-07-28 11:59:11 +02:00
|
|
|
.enableDefaultDebugger().build();
|
2016-10-31 12:24:05 +01:00
|
|
|
final XMPPTCPConnectionConfiguration readingThingConnectionConfiguration = XMPPTCPConnectionConfiguration
|
|
|
|
.builder().setUsernameAndPassword(readingThingJid.getLocalpart(), readingThingPassword)
|
|
|
|
.setXmppDomain(readingThingJid.asDomainBareJid()).setSecurityMode(SecurityMode.disabled)
|
2017-07-28 11:59:11 +02:00
|
|
|
.enableDefaultDebugger().build();
|
2016-07-20 20:57:04 +02:00
|
|
|
|
|
|
|
final XMPPTCPConnection dataThingConnection = new XMPPTCPConnection(dataThingConnectionConfiguration);
|
|
|
|
final XMPPTCPConnection readingThingConnection = new XMPPTCPConnection(readingThingConnectionConfiguration);
|
|
|
|
|
2017-01-12 20:57:19 +01:00
|
|
|
dataThingConnection.setReplyTimeout(TIMEOUT);
|
|
|
|
readingThingConnection.setReplyTimeout(TIMEOUT);
|
2016-07-20 20:57:04 +02:00
|
|
|
|
2016-10-31 12:24:05 +01:00
|
|
|
dataThingConnection.setUseStreamManagement(false);
|
|
|
|
readingThingConnection.setUseStreamManagement(false);
|
|
|
|
|
2016-07-20 20:57:04 +02:00
|
|
|
try {
|
2016-10-31 12:24:05 +01:00
|
|
|
dataThingConnection.connect().login();
|
|
|
|
readingThingConnection.connect().login();
|
|
|
|
scenario.iotScenario(dataThingConnection, readingThingConnection);
|
|
|
|
} finally {
|
2016-07-20 20:57:04 +02:00
|
|
|
dataThingConnection.disconnect();
|
|
|
|
readingThingConnection.disconnect();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-31 12:24:05 +01:00
|
|
|
public static void iotReadOutScenario(String dataThingJidString, String dataThingPassword, String readingThingJidString,
|
|
|
|
String readingThingPassword)
|
|
|
|
throws Exception {
|
|
|
|
iotScenario(dataThingJidString, dataThingPassword, readingThingJidString, readingThingPassword, READ_OUT_SCENARIO);
|
|
|
|
}
|
2016-07-20 20:57:04 +02:00
|
|
|
|
2016-10-31 12:24:05 +01:00
|
|
|
public static final IotScenario READ_OUT_SCENARIO = new IotScenario() {
|
|
|
|
@Override
|
|
|
|
public void iotScenario(XMPPTCPConnection dataThingConnection, XMPPTCPConnection readingThingConnection) throws TimeoutException, Exception {
|
|
|
|
ThingState dataThingState = actAsDataThing(dataThingConnection);
|
|
|
|
|
|
|
|
final SimpleResultSyncPoint syncPoint = new SimpleResultSyncPoint();
|
|
|
|
dataThingState.setThingStateChangeListener(new AbstractThingStateChangeListener() {
|
|
|
|
@Override
|
|
|
|
public void owned(BareJid jid) {
|
|
|
|
syncPoint.signal();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
// Wait until the thing is owned.
|
|
|
|
syncPoint.waitForResult(TIMEOUT);
|
|
|
|
printStatus("OWNED - Thing now onwed by " + dataThingState.getOwner());
|
|
|
|
|
|
|
|
// Make sure things are befriended.
|
|
|
|
IoTProvisioningManager readingThingProvisioningManager = IoTProvisioningManager.getInstanceFor(readingThingConnection);
|
|
|
|
readingThingProvisioningManager.sendFriendshipRequestIfRequired(dataThingConnection.getUser().asBareJid());
|
|
|
|
|
|
|
|
Roster dataThingRoster = Roster.getInstanceFor(dataThingConnection);
|
|
|
|
RosterUtil.waitUntilOtherEntityIsSubscribed(dataThingRoster, readingThingConnection.getUser().asBareJid(), TIMEOUT);
|
|
|
|
printStatus("FRIENDSHIP ACCEPTED - Trying to read out data");
|
|
|
|
|
|
|
|
IoTDataManager readingThingDataManager = IoTDataManager.getInstanceFor(readingThingConnection);
|
|
|
|
List<IoTFieldsExtension> values = readingThingDataManager.requestMomentaryValuesReadOut(dataThingConnection.getUser());
|
|
|
|
if (values.size() != 1) {
|
|
|
|
throw new IllegalStateException("Unexpected number of values returned: " + values.size());
|
2016-07-20 20:57:04 +02:00
|
|
|
}
|
2016-10-31 12:24:05 +01:00
|
|
|
IoTFieldsExtension field = values.get(0);
|
|
|
|
printStatus("DATA READ-OUT SUCCESS: " + field.toXML());
|
|
|
|
printStatus("IoT SCENARIO FINISHED SUCCESSFULLY");
|
2016-07-20 20:57:04 +02:00
|
|
|
}
|
2016-10-31 12:24:05 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
public static void iotOwnerApprovesFriendScenario(String dataThingJidString, String dataThingPassword,
|
|
|
|
String readingThingJidString, String readingThingPassword) throws Exception {
|
|
|
|
iotScenario(dataThingJidString, dataThingPassword, readingThingJidString, readingThingPassword,
|
|
|
|
OWNER_APPROVES_FRIEND_SCENARIO);
|
2016-07-20 20:57:04 +02:00
|
|
|
}
|
|
|
|
|
2016-10-31 12:24:05 +01:00
|
|
|
public static final IotScenario OWNER_APPROVES_FRIEND_SCENARIO = new IotScenario() {
|
|
|
|
@Override
|
|
|
|
public void iotScenario(XMPPTCPConnection dataThingConnection, XMPPTCPConnection readingThingConnection) throws TimeoutException, Exception {
|
|
|
|
// First ensure that the two XMPP entities are not already subscribed to each other presences.
|
|
|
|
RosterUtil.ensureNotSubscribedToEachOther(dataThingConnection, readingThingConnection);
|
|
|
|
|
|
|
|
final BareJid dataThingBareJid = dataThingConnection.getUser().asBareJid();
|
|
|
|
final BareJid readingThingBareJid = readingThingConnection.getUser().asBareJid();
|
|
|
|
final ThingState dataThingState = actAsDataThing(dataThingConnection);
|
|
|
|
|
|
|
|
printStatus("WAITING for 'claimed' notification. Please claim thing now");
|
|
|
|
final SimpleResultSyncPoint syncPoint = new SimpleResultSyncPoint();
|
|
|
|
dataThingState.setThingStateChangeListener(new AbstractThingStateChangeListener() {
|
|
|
|
@Override
|
|
|
|
public void owned(BareJid jid) {
|
|
|
|
syncPoint.signal();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
// Wait until the thing is owned.
|
|
|
|
syncPoint.waitForResult(TIMEOUT);
|
|
|
|
printStatus("OWNED - Thing now onwed by " + dataThingState.getOwner());
|
|
|
|
|
|
|
|
// Now, ReadingThing sends a friendship request to data thing, which
|
|
|
|
// will proxy the request to its provisioning service, which will
|
|
|
|
// likely return that both a not friends since the owner did not
|
|
|
|
// authorize the friendship yet.
|
|
|
|
final SimpleResultSyncPoint friendshipApprovedSyncPoint = new SimpleResultSyncPoint();
|
|
|
|
final IoTProvisioningManager readingThingProvisioningManager = IoTProvisioningManager.getInstanceFor(readingThingConnection);
|
|
|
|
final BecameFriendListener becameFriendListener = new BecameFriendListener() {
|
|
|
|
@Override
|
|
|
|
public void becameFriend(BareJid jid, Presence presence) {
|
|
|
|
if (jid.equals(dataThingBareJid)) {
|
|
|
|
friendshipApprovedSyncPoint.signal();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
readingThingProvisioningManager.addBecameFriendListener(becameFriendListener);
|
|
|
|
|
|
|
|
try {
|
|
|
|
readingThingProvisioningManager
|
|
|
|
.sendFriendshipRequestIfRequired(dataThingConnection.getUser().asBareJid());
|
|
|
|
friendshipApprovedSyncPoint.waitForResult(TIMEOUT);
|
|
|
|
} finally {
|
|
|
|
readingThingProvisioningManager.removeBecameFriendListener(becameFriendListener);
|
|
|
|
}
|
|
|
|
|
|
|
|
printStatus("FRIENDSHIP APPROVED - ReadingThing " + readingThingBareJid + " is now a friend of DataThing " + dataThingBareJid);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2016-07-20 20:57:04 +02:00
|
|
|
private static ThingState actAsDataThing(XMPPTCPConnection connection) throws XMPPException, SmackException, InterruptedException {
|
|
|
|
final String key = StringUtils.randomString(12);
|
|
|
|
final String sn = StringUtils.randomString(12);
|
|
|
|
Thing dataThing = Thing.builder()
|
|
|
|
.setKey(key)
|
|
|
|
.setSerialNumber(sn)
|
2016-10-31 12:24:05 +01:00
|
|
|
.setManufacturer("IgniteRealtime")
|
2016-07-20 20:57:04 +02:00
|
|
|
.setModel("Smack")
|
|
|
|
.setVersion("0.1")
|
|
|
|
.setMomentaryReadOutRequestHandler(new ThingMomentaryReadOutRequest() {
|
|
|
|
@Override
|
|
|
|
public void momentaryReadOutRequest(ThingMomentaryReadOutResult callback) {
|
|
|
|
IoTDataField.IntField field = new IntField("timestamp", (int) (System.currentTimeMillis() / 1000));
|
|
|
|
callback.momentaryReadOut(Collections.singletonList(field));
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.build();
|
|
|
|
IoTDiscoveryManager iotDiscoveryManager = IoTDiscoveryManager.getInstanceFor(connection);
|
|
|
|
ThingState state = IoTDiscoveryIntegrationTest.registerThing(iotDiscoveryManager, dataThing);
|
|
|
|
printStatus("SUCCESS: Thing registered:" + dataThing);
|
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
|
|
|
private static void printStatus(CharSequence status) {
|
|
|
|
// CHECKSTYLE:OFF
|
|
|
|
System.out.println(status);
|
|
|
|
// CHECKSTYLE:ON
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void main(String[] args) throws TimeoutException, Exception {
|
|
|
|
if (args.length != 4) {
|
|
|
|
throw new IllegalArgumentException();
|
|
|
|
}
|
2016-10-31 12:24:05 +01:00
|
|
|
iotOwnerApprovesFriendScenario(args[0], args[1], args[2], args[3]);
|
2016-07-20 20:57:04 +02:00
|
|
|
}
|
2016-10-31 12:24:05 +01:00
|
|
|
|
2016-07-20 20:57:04 +02:00
|
|
|
}
|