mirror of
https://github.com/vanitasvitae/Smack.git
synced 2025-09-09 17:19:39 +02:00
Add (partial) support for IoT XEPs
That is XEP-0323, -0324, -0325, and -0347. SMACK-727.
This commit is contained in:
parent
d1fe5c2933
commit
b91978dcc4
110 changed files with 5395 additions and 40 deletions
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot;
|
||||
|
||||
import org.jivesoftware.smack.SmackException;
|
||||
|
||||
public class IoTException extends SmackException {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import org.jivesoftware.smack.Manager;
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
|
||||
public final class IoTManager extends Manager {
|
||||
|
||||
private static final Map<XMPPConnection, IoTManager> INSTANCES = new WeakHashMap<>();
|
||||
|
||||
public static synchronized IoTManager getInstanceFor(XMPPConnection connection) {
|
||||
IoTManager manager = INSTANCES.get(connection);
|
||||
if (manager == null) {
|
||||
manager = new IoTManager(connection);
|
||||
INSTANCES.put(connection, manager);
|
||||
}
|
||||
return manager;
|
||||
}
|
||||
|
||||
private IoTManager(XMPPConnection connection) {
|
||||
super(connection);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,161 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.jivesoftware.smackx.iot.control.ThingControlRequest;
|
||||
import org.jivesoftware.smackx.iot.data.ThingMomentaryReadOutRequest;
|
||||
import org.jivesoftware.smackx.iot.discovery.element.Tag;
|
||||
import org.jivesoftware.smackx.iot.discovery.element.Tag.Type;
|
||||
import org.jivesoftware.smackx.iot.element.NodeInfo;
|
||||
|
||||
public final class Thing {
|
||||
|
||||
private final HashMap<String, Tag> metaTags;
|
||||
private final boolean selfOwned;
|
||||
private final NodeInfo nodeInfo;
|
||||
|
||||
private final ThingMomentaryReadOutRequest momentaryReadOutRequestHandler;
|
||||
private final ThingControlRequest controlRequestHandler;
|
||||
|
||||
private Thing(Builder builder) {
|
||||
this.metaTags = builder.metaTags;
|
||||
this.selfOwned = builder.selfOwned;
|
||||
|
||||
this.nodeInfo = builder.nodeInfo;
|
||||
|
||||
this.momentaryReadOutRequestHandler = builder.momentaryReadOutRequest;
|
||||
this.controlRequestHandler = builder.controlRequest;
|
||||
}
|
||||
|
||||
public Collection<Tag> getMetaTags() {
|
||||
return metaTags.values();
|
||||
}
|
||||
|
||||
public boolean isSelfOwened() {
|
||||
return selfOwned;
|
||||
}
|
||||
|
||||
public NodeInfo getNodeInfo() {
|
||||
return nodeInfo;
|
||||
}
|
||||
|
||||
public String getNodeId() {
|
||||
return nodeInfo.getNodeId();
|
||||
}
|
||||
|
||||
public String getSourceId() {
|
||||
return nodeInfo.getSourceId();
|
||||
}
|
||||
|
||||
public String getCacheType() {
|
||||
return nodeInfo.getCacheType();
|
||||
}
|
||||
|
||||
public ThingMomentaryReadOutRequest getMomentaryReadOutRequestHandler() {
|
||||
return momentaryReadOutRequestHandler;
|
||||
}
|
||||
|
||||
public ThingControlRequest getControlRequestHandler() {
|
||||
return controlRequestHandler;
|
||||
}
|
||||
|
||||
private String toStringCache;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (toStringCache == null) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append( "Thing " + nodeInfo + " [");
|
||||
Iterator<Tag> it = metaTags.values().iterator();
|
||||
while (it.hasNext()) {
|
||||
Tag tag = it.next();
|
||||
sb.append(tag);
|
||||
if (it.hasNext()) {
|
||||
sb.append(' ');
|
||||
}
|
||||
}
|
||||
sb.append(']');
|
||||
toStringCache = sb.toString();
|
||||
}
|
||||
return toStringCache;
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private HashMap<String, Tag> metaTags = new HashMap<>();
|
||||
private boolean selfOwned;
|
||||
private NodeInfo nodeInfo = NodeInfo.EMPTY;
|
||||
private ThingMomentaryReadOutRequest momentaryReadOutRequest;
|
||||
private ThingControlRequest controlRequest;
|
||||
|
||||
public Builder setSerialNumber(String sn) {
|
||||
final String name = "SN";
|
||||
Tag tag = new Tag(name, Type.str, sn);
|
||||
metaTags.put(name, tag);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setKey(String key) {
|
||||
final String name = "KEY";
|
||||
Tag tag = new Tag(name, Type.str, key);
|
||||
metaTags.put(name, tag);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setManufacturer(String manufacturer) {
|
||||
final String name = "MAN";
|
||||
Tag tag = new Tag(name, Type.str, manufacturer);
|
||||
metaTags.put(name, tag);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setModel(String model) {
|
||||
final String name = "MODEL";
|
||||
Tag tag = new Tag(name, Type.str, model);
|
||||
metaTags.put(name, tag);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setVersion(String version) {
|
||||
final String name = "V";
|
||||
Tag tag = new Tag(name, Type.num, version);
|
||||
metaTags.put(name, tag);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setMomentaryReadOutRequestHandler(ThingMomentaryReadOutRequest momentaryReadOutRequestHandler) {
|
||||
this.momentaryReadOutRequest = momentaryReadOutRequestHandler;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setControlRequestHandler(ThingControlRequest controlRequest) {
|
||||
this.controlRequest = controlRequest;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Thing build() {
|
||||
return new Thing(this);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,149 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.control;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.jivesoftware.smack.Manager;
|
||||
import org.jivesoftware.smack.SmackException.NoResponseException;
|
||||
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
|
||||
import org.jivesoftware.smack.iqrequest.AbstractIqRequestHandler;
|
||||
import org.jivesoftware.smack.iqrequest.IQRequestHandler.Mode;
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
import org.jivesoftware.smackx.iot.Thing;
|
||||
import org.jivesoftware.smackx.iot.control.element.IoTSetRequest;
|
||||
import org.jivesoftware.smackx.iot.control.element.IoTSetResponse;
|
||||
import org.jivesoftware.smackx.iot.control.element.SetData;
|
||||
import org.jivesoftware.smackx.iot.element.NodeInfo;
|
||||
import org.jxmpp.jid.FullJid;
|
||||
|
||||
/**
|
||||
* A manger for XEP-0325: Internet of Things - Control.
|
||||
*
|
||||
* @author Florian Schmaus {@literal <flo@geekplace.eu>}
|
||||
* @see <a href="http://xmpp.org/extensions/xep-0325.html">XEP-0323: Internet of Things - Control</a>
|
||||
*/
|
||||
public final class IoTControlManager extends Manager {
|
||||
|
||||
private static final Map<XMPPConnection, IoTControlManager> INSTANCES = new WeakHashMap<>();
|
||||
|
||||
/**
|
||||
* Get the manger instance responsible for the given connection.
|
||||
*
|
||||
* @param connection the XMPP connection.
|
||||
* @return a manager instance.
|
||||
*/
|
||||
public static synchronized IoTControlManager getInstanceFor(XMPPConnection connection) {
|
||||
IoTControlManager manager = INSTANCES.get(connection);
|
||||
if (manager == null) {
|
||||
manager = new IoTControlManager(connection);
|
||||
INSTANCES.put(connection, manager);
|
||||
}
|
||||
return manager;
|
||||
}
|
||||
|
||||
private final Map<NodeInfo, Thing> things = new ConcurrentHashMap<>();
|
||||
|
||||
private IoTControlManager(XMPPConnection connection) {
|
||||
super(connection);
|
||||
connection.registerIQRequestHandler(new AbstractIqRequestHandler(IoTSetRequest.ELEMENT, IoTSetRequest.NAMESPACE, IQ.Type.set, Mode.async) {
|
||||
@Override
|
||||
public IQ handleIQRequest(IQ iqRequest) {
|
||||
// TODO Lookup thing and provide data.
|
||||
IoTSetRequest iotSetRequest = (IoTSetRequest) iqRequest;
|
||||
|
||||
// TODO Add support for multiple things(/NodeInfos).
|
||||
final Thing thing = things.get(NodeInfo.EMPTY);
|
||||
if (thing == null) {
|
||||
// TODO return error if not at least one thing registered.
|
||||
return null;
|
||||
}
|
||||
|
||||
ThingControlRequest controlRequest = thing.getControlRequestHandler();
|
||||
if (controlRequest == null) {
|
||||
// TODO return error if no request handler for things.
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
controlRequest.processRequest(iotSetRequest.getFrom(), iotSetRequest.getSetData());
|
||||
} catch (XMPPErrorException e) {
|
||||
return IQ.createErrorResponse(iotSetRequest, e.getXMPPError());
|
||||
}
|
||||
|
||||
return new IoTSetResponse(iotSetRequest);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Control a thing by sending a collection of {@link SetData} instructions.
|
||||
*
|
||||
* @param jid
|
||||
* @param data
|
||||
* @return
|
||||
* @throws NoResponseException
|
||||
* @throws XMPPErrorException
|
||||
* @throws NotConnectedException
|
||||
* @throws InterruptedException
|
||||
* @see #setUsingIq(FullJid, Collection)
|
||||
*/
|
||||
public IoTSetResponse setUsingIq(FullJid jid, SetData data) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||
return setUsingIq(jid, Collections.singleton(data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Control a thing by sending a collection of {@link SetData} instructions.
|
||||
*
|
||||
* @param jid the thing to control.
|
||||
* @param data a collection of {@link SetData} instructions.
|
||||
* @return the {@link IoTSetResponse} if successful.
|
||||
* @throws NoResponseException
|
||||
* @throws XMPPErrorException
|
||||
* @throws NotConnectedException
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public IoTSetResponse setUsingIq(FullJid jid, Collection<SetData> data) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||
IoTSetRequest request = new IoTSetRequest(data);
|
||||
request.setTo(jid);
|
||||
IoTSetResponse response = connection().createPacketCollectorAndSend(request).nextResultOrThrow();
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Install a thing in the manager. Activates control functionality (if provided by the thing).
|
||||
*
|
||||
* @param thing the thing to install.
|
||||
*/
|
||||
public void installThing(Thing thing) {
|
||||
things.put(thing.getNodeInfo(), thing);
|
||||
}
|
||||
|
||||
public Thing uninstallThing(Thing thing) {
|
||||
return uninstallThing(thing.getNodeInfo());
|
||||
}
|
||||
|
||||
public Thing uninstallThing(NodeInfo nodeInfo) {
|
||||
return things.remove(nodeInfo);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.control;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
|
||||
import org.jivesoftware.smackx.iot.control.element.SetData;
|
||||
import org.jxmpp.jid.Jid;
|
||||
|
||||
public interface ThingControlRequest {
|
||||
|
||||
public void processRequest(Jid from, Collection<SetData> setData) throws XMPPErrorException;
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.control.element;
|
||||
|
||||
public class Constants {
|
||||
|
||||
public static final String IOT_CONTROL_NAMESPACE = "urn:xmpp:iot:control";
|
||||
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.control.element;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
|
||||
public class IoTSetRequest extends IQ {
|
||||
|
||||
public static final String ELEMENT = "set";
|
||||
public static final String NAMESPACE = Constants.IOT_CONTROL_NAMESPACE;
|
||||
|
||||
private final Collection<SetData> setData;
|
||||
|
||||
public IoTSetRequest(Collection<SetData> setData) {
|
||||
super(ELEMENT, NAMESPACE);
|
||||
setType(Type.set);
|
||||
this.setData = Collections.unmodifiableCollection(setData);
|
||||
}
|
||||
|
||||
public Collection<SetData> getSetData() {
|
||||
return setData;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) {
|
||||
xml.rightAngleBracket();
|
||||
xml.append(setData);
|
||||
return xml;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.control.element;
|
||||
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
|
||||
public class IoTSetResponse extends IQ {
|
||||
|
||||
public static final String ELEMENT = "setResponse";
|
||||
public static final String NAMESPACE = Constants.IOT_CONTROL_NAMESPACE;
|
||||
|
||||
public IoTSetResponse() {
|
||||
super(ELEMENT, NAMESPACE);
|
||||
}
|
||||
|
||||
public IoTSetResponse(IoTSetRequest iotSetRequest) {
|
||||
this();
|
||||
initialzeAsResultFor(iotSetRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) {
|
||||
xml.setEmptyElement();
|
||||
return xml;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.control.element;
|
||||
|
||||
public class SetBoolData extends SetData {
|
||||
|
||||
public SetBoolData(String name, boolean value) {
|
||||
this(name, Boolean.toString(value));
|
||||
booleanCache = value;
|
||||
}
|
||||
|
||||
protected SetBoolData(String name, String value) {
|
||||
super(name, Type.BOOL, value);
|
||||
}
|
||||
|
||||
private Boolean booleanCache;
|
||||
|
||||
public Boolean getBooleanValue() {
|
||||
if (booleanCache != null) {
|
||||
booleanCache = Boolean.valueOf(getValue());
|
||||
}
|
||||
return booleanCache;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.control.element;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import org.jivesoftware.smack.packet.NamedElement;
|
||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||
|
||||
public abstract class SetData implements NamedElement {
|
||||
|
||||
public enum Type {
|
||||
BOOL,
|
||||
INT,
|
||||
LONG,
|
||||
DOUBLE,
|
||||
;
|
||||
|
||||
private String toStringCache;
|
||||
|
||||
private Type() {
|
||||
toStringCache = this.name().toLowerCase(Locale.US);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toStringCache;
|
||||
}
|
||||
}
|
||||
|
||||
protected SetData(String name, Type type, String value) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
private final String name;
|
||||
|
||||
private final Type type;
|
||||
|
||||
private final String value;
|
||||
|
||||
public final String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public final String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public final Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the root element name.
|
||||
*
|
||||
* @return the element name.
|
||||
*/
|
||||
@Override
|
||||
public final String getElementName() {
|
||||
return getType().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the XML representation of this Element.
|
||||
*
|
||||
* @return the stanza(/packet) extension as XML.
|
||||
*/
|
||||
@Override
|
||||
public final XmlStringBuilder toXML() {
|
||||
XmlStringBuilder xml = new XmlStringBuilder(this);
|
||||
xml.attribute("name", name);
|
||||
xml.attribute("value", value);
|
||||
xml.closeEmptyElement();
|
||||
return xml;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.control.element;
|
||||
|
||||
public class SetDoubleData extends SetData {
|
||||
|
||||
public SetDoubleData(String name, double value) {
|
||||
this(name, Double.toString(value));
|
||||
doubleCache = value;
|
||||
}
|
||||
|
||||
protected SetDoubleData(String name, String value) {
|
||||
super(name, Type.DOUBLE, value);
|
||||
}
|
||||
|
||||
private Double doubleCache;
|
||||
|
||||
public Double getDoubleValue() {
|
||||
if (doubleCache != null) {
|
||||
doubleCache = Double.valueOf(getValue());
|
||||
}
|
||||
return doubleCache;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.control.element;
|
||||
|
||||
public class SetIntData extends SetData {
|
||||
|
||||
public SetIntData(String name, int value) {
|
||||
this(name, Integer.toString(value));
|
||||
integerCache = value;
|
||||
}
|
||||
|
||||
protected SetIntData(String name, String value) {
|
||||
super(name, Type.INT, value);
|
||||
}
|
||||
|
||||
private Integer integerCache;
|
||||
|
||||
public Integer getIntegerValue() {
|
||||
if (integerCache != null) {
|
||||
integerCache = Integer.valueOf(getValue());
|
||||
}
|
||||
return integerCache;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.control.element;
|
||||
|
||||
public class SetLongData extends SetData {
|
||||
|
||||
public SetLongData(String name, long value) {
|
||||
this(name, Long.toString(value));
|
||||
longCache = value;
|
||||
}
|
||||
|
||||
protected SetLongData(String name, String value) {
|
||||
super(name, Type.LONG, value);
|
||||
}
|
||||
|
||||
private Long longCache;
|
||||
|
||||
public Long getLongValue() {
|
||||
if (longCache != null) {
|
||||
longCache = Long.valueOf(getValue());
|
||||
}
|
||||
return longCache;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Smack's API for XMPP IoT.
|
||||
*/
|
||||
package org.jivesoftware.smackx.iot.control.element;
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Smack's API for XMPP IoT.
|
||||
*/
|
||||
package org.jivesoftware.smackx.iot.control;
|
|
@ -0,0 +1,82 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.control.provider;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.jivesoftware.smack.provider.IQProvider;
|
||||
import org.jivesoftware.smackx.iot.control.element.IoTSetRequest;
|
||||
import org.jivesoftware.smackx.iot.control.element.SetBoolData;
|
||||
import org.jivesoftware.smackx.iot.control.element.SetData;
|
||||
import org.jivesoftware.smackx.iot.control.element.SetDoubleData;
|
||||
import org.jivesoftware.smackx.iot.control.element.SetIntData;
|
||||
import org.jivesoftware.smackx.iot.control.element.SetLongData;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
public class IoTSetRequestProvider extends IQProvider<IoTSetRequest> {
|
||||
|
||||
@Override
|
||||
public IoTSetRequest parse(XmlPullParser parser, int initialDepth) throws Exception {
|
||||
List<SetData> data = new ArrayList<>(4);
|
||||
outerloop: while (true) {
|
||||
final int eventType = parser.next();
|
||||
final String name = parser.getName();
|
||||
switch (eventType) {
|
||||
case XmlPullParser.START_TAG:
|
||||
switch (name) {
|
||||
case "bool": {
|
||||
String valueName = parser.getAttributeValue(null, "name");
|
||||
String valueString = parser.getAttributeValue(null, "value");
|
||||
boolean value = Boolean.parseBoolean(valueString);
|
||||
data.add(new SetBoolData(valueName, value));
|
||||
}
|
||||
break;
|
||||
case "double": {
|
||||
String valueName = parser.getAttributeValue(null, "name");
|
||||
String valueString = parser.getAttributeValue(null, "value");
|
||||
double value = Double.parseDouble(valueString);
|
||||
data.add(new SetDoubleData(valueName, value));
|
||||
}
|
||||
break;
|
||||
case "int": {
|
||||
String valueName = parser.getAttributeValue(null, "name");
|
||||
String valueString = parser.getAttributeValue(null, "value");
|
||||
int value = Integer.parseInt(valueString);
|
||||
data.add(new SetIntData(valueName, value));
|
||||
}
|
||||
break;
|
||||
case "long": {
|
||||
String valueName = parser.getAttributeValue(null, "name");
|
||||
String valueString = parser.getAttributeValue(null, "value");
|
||||
long value = Long.parseLong(valueString);
|
||||
data.add(new SetLongData(valueName, value));
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case XmlPullParser.END_TAG:
|
||||
if (parser.getDepth() == initialDepth) {
|
||||
break outerloop;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return new IoTSetRequest(data);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.control.provider;
|
||||
|
||||
import org.jivesoftware.smack.provider.IQProvider;
|
||||
import org.jivesoftware.smackx.iot.control.element.IoTSetResponse;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
public class IoTSetResponseProvider extends IQProvider<IoTSetResponse> {
|
||||
|
||||
@Override
|
||||
public IoTSetResponse parse(XmlPullParser parser, int initialDepth) throws Exception {
|
||||
return new IoTSetResponse();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Smack's API for XMPP IoT.
|
||||
*/
|
||||
package org.jivesoftware.smackx.iot.control.provider;
|
|
@ -0,0 +1,210 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.jivesoftware.smack.ConnectionCreationListener;
|
||||
import org.jivesoftware.smack.Manager;
|
||||
import org.jivesoftware.smack.PacketCollector;
|
||||
import org.jivesoftware.smack.SmackException.NoResponseException;
|
||||
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
import org.jivesoftware.smack.XMPPConnectionRegistry;
|
||||
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
|
||||
import org.jivesoftware.smack.filter.StanzaFilter;
|
||||
import org.jivesoftware.smack.iqrequest.AbstractIqRequestHandler;
|
||||
import org.jivesoftware.smack.iqrequest.IQRequestHandler.Mode;
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
import org.jivesoftware.smack.packet.Message;
|
||||
import org.jivesoftware.smackx.iot.Thing;
|
||||
import org.jivesoftware.smackx.iot.data.element.IoTDataField;
|
||||
import org.jivesoftware.smackx.iot.data.element.IoTDataReadOutAccepted;
|
||||
import org.jivesoftware.smackx.iot.data.element.IoTDataRequest;
|
||||
import org.jivesoftware.smackx.iot.data.element.IoTFieldsExtension;
|
||||
import org.jivesoftware.smackx.iot.data.filter.IoTFieldsExtensionFilter;
|
||||
import org.jivesoftware.smackx.iot.element.NodeInfo;
|
||||
import org.jxmpp.jid.EntityFullJid;
|
||||
|
||||
/**
|
||||
* A manager for XEP-0323: Internet of Things - Sensor Data.
|
||||
*
|
||||
* @author Florian Schmaus {@literal <flo@geekplace.eu>}
|
||||
* @see <a href="http://xmpp.org/extensions/xep-0323.html">XEP-0323: Internet of Things - Sensor Data</a>
|
||||
*/
|
||||
public final class IoTDataManager extends Manager {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(IoTDataManager.class.getName());
|
||||
|
||||
private static final Map<XMPPConnection, IoTDataManager> INSTANCES = new WeakHashMap<>();
|
||||
|
||||
// Ensure a IoTDataManager exists for every connection.
|
||||
static {
|
||||
XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() {
|
||||
public void connectionCreated(XMPPConnection connection) {
|
||||
getInstanceFor(connection);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the manger instance responsible for the given connection.
|
||||
*
|
||||
* @param connection the XMPP connection.
|
||||
* @return a manager instance.
|
||||
*/
|
||||
public static synchronized IoTDataManager getInstanceFor(XMPPConnection connection) {
|
||||
IoTDataManager manager = INSTANCES.get(connection);
|
||||
if (manager == null) {
|
||||
manager = new IoTDataManager(connection);
|
||||
INSTANCES.put(connection, manager);
|
||||
}
|
||||
return manager;
|
||||
}
|
||||
|
||||
private final AtomicInteger nextSeqNr = new AtomicInteger();
|
||||
|
||||
private final Map<NodeInfo, Thing> things = new ConcurrentHashMap<>();
|
||||
|
||||
private IoTDataManager(XMPPConnection connection) {
|
||||
super(connection);
|
||||
|
||||
connection.registerIQRequestHandler(new AbstractIqRequestHandler(IoTDataRequest.ELEMENT,
|
||||
IoTDataRequest.NAMESPACE, IQ.Type.get, Mode.async) {
|
||||
@Override
|
||||
public IQ handleIQRequest(IQ iqRequest) {
|
||||
// TODO Verify that iqRequest.from is friend?
|
||||
|
||||
final IoTDataRequest dataRequest = (IoTDataRequest) iqRequest;
|
||||
|
||||
if (!dataRequest.isMomentary()) {
|
||||
// TODO return error IQ that non momentary requests are not implemented yet.
|
||||
return null;
|
||||
}
|
||||
|
||||
// TODO Add support for multiple things(/NodeInfos).
|
||||
final Thing thing = things.get(NodeInfo.EMPTY);
|
||||
if (thing == null) {
|
||||
// TODO return error if not at least one thing registered.
|
||||
return null;
|
||||
}
|
||||
|
||||
ThingMomentaryReadOutRequest readOutRequest = thing.getMomentaryReadOutRequestHandler();
|
||||
if (readOutRequest == null) {
|
||||
// TODO Thing does not provide momentary read-out
|
||||
return null;
|
||||
}
|
||||
|
||||
// Callback hell begins here. :) XEP-0323 decouples the read-out results from the IQ result. I'm not
|
||||
// sure if I would have made the same design decision but the reasons where likely being able to get a
|
||||
// fast read-out acknowledgement back to the requester even with sensors that take "a long time" to
|
||||
// read-out their values. I had designed that as special case and made the "results in IQ response" the
|
||||
// normal case.
|
||||
readOutRequest.momentaryReadOutRequest(new ThingMomentaryReadOutResult() {
|
||||
@Override
|
||||
public void momentaryReadOut(List<? extends IoTDataField> results) {
|
||||
IoTFieldsExtension iotFieldsExtension = IoTFieldsExtension.buildFor(dataRequest.getSequenceNr(), true, thing.getNodeInfo(), results);
|
||||
Message message = new Message(dataRequest.getFrom());
|
||||
message.addExtension(iotFieldsExtension);
|
||||
try {
|
||||
connection().sendStanza(message);
|
||||
}
|
||||
catch (NotConnectedException | InterruptedException e) {
|
||||
LOGGER.log(Level.SEVERE, "Could not send read-out response " + message, e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return new IoTDataReadOutAccepted(dataRequest);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Install a thing in the manager. Activates data read out functionality (if provided by the
|
||||
* thing).
|
||||
*
|
||||
* @param thing the thing to install.
|
||||
*/
|
||||
public void installThing(Thing thing) {
|
||||
things.put(thing.getNodeInfo(), thing);
|
||||
}
|
||||
|
||||
public Thing uninstallThing(Thing thing) {
|
||||
return uninstallThing(thing.getNodeInfo());
|
||||
}
|
||||
|
||||
public Thing uninstallThing(NodeInfo nodeInfo) {
|
||||
return things.remove(nodeInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to read out a things momentary values.
|
||||
*
|
||||
* @param jid the full JID of the thing to read data from.
|
||||
* @return a list with the read out data.
|
||||
* @throws NoResponseException
|
||||
* @throws XMPPErrorException
|
||||
* @throws NotConnectedException
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public List<IoTFieldsExtension> requestMomentaryValuesReadOut(EntityFullJid jid)
|
||||
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||
final XMPPConnection connection = connection();
|
||||
final int seqNr = nextSeqNr.incrementAndGet();
|
||||
IoTDataRequest iotDataRequest = new IoTDataRequest(seqNr, true);
|
||||
iotDataRequest.setTo(jid);
|
||||
|
||||
StanzaFilter doneFilter = new IoTFieldsExtensionFilter(seqNr, true);
|
||||
StanzaFilter dataFilter = new IoTFieldsExtensionFilter(seqNr, false);
|
||||
|
||||
// Setup the IoTFieldsExtension message collectors before sending the IQ to avoid a data race.
|
||||
PacketCollector doneCollector = connection.createPacketCollector(doneFilter);
|
||||
|
||||
PacketCollector.Configuration dataCollectorConfiguration = PacketCollector.newConfiguration().setStanzaFilter(
|
||||
dataFilter).setCollectorToReset(doneCollector);
|
||||
PacketCollector dataCollector = connection.createPacketCollector(dataCollectorConfiguration);
|
||||
|
||||
try {
|
||||
connection.createPacketCollectorAndSend(iotDataRequest).nextResultOrThrow();
|
||||
// Wait until a message with an IoTFieldsExtension and the done flag comes in.
|
||||
doneCollector.nextResult();
|
||||
}
|
||||
finally {
|
||||
// Ensure that the two collectors are canceled in any case.
|
||||
dataCollector.cancel();
|
||||
doneCollector.cancel();
|
||||
}
|
||||
|
||||
int collectedCount = dataCollector.getCollectedCount();
|
||||
List<IoTFieldsExtension> res = new ArrayList<>(collectedCount);
|
||||
for (int i = 0; i < collectedCount; i++) {
|
||||
Message message = dataCollector.pollResult();
|
||||
IoTFieldsExtension iotFieldsExtension = IoTFieldsExtension.from(message);
|
||||
res.add(iotFieldsExtension);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.data;
|
||||
|
||||
public interface ThingMomentaryReadOutRequest {
|
||||
|
||||
public void momentaryReadOutRequest(ThingMomentaryReadOutResult callback);
|
||||
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.jivesoftware.smackx.iot.data.element.IoTDataField;
|
||||
|
||||
public interface ThingMomentaryReadOutResult {
|
||||
|
||||
public void momentaryReadOut(List<? extends IoTDataField> results);
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.data.element;
|
||||
|
||||
public class Constants {
|
||||
|
||||
public static final String IOT_SENSORDATA_NAMESPACE = "urn:xmpp:iot:data";
|
||||
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.data.element;
|
||||
|
||||
import org.jivesoftware.smack.packet.NamedElement;
|
||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||
|
||||
public abstract class IoTDataField implements NamedElement {
|
||||
|
||||
enum Type {
|
||||
integer("int"),
|
||||
bool("boolean"),
|
||||
;
|
||||
|
||||
Type(String stringRepresentation) {
|
||||
this.stringRepresentation = stringRepresentation;
|
||||
}
|
||||
|
||||
private final String stringRepresentation;
|
||||
}
|
||||
|
||||
private final Type type;
|
||||
|
||||
private final String name;
|
||||
|
||||
protected IoTDataField(Type type, String name) {
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public final String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getElementName() {
|
||||
return type.stringRepresentation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final XmlStringBuilder toXML() {
|
||||
XmlStringBuilder xml = new XmlStringBuilder(this);
|
||||
xml.attribute("name", name).attribute("value", getValueString());
|
||||
// TODO handle 'unit' attribute as special case if <numeric/> is implemented.
|
||||
xml.closeEmptyElement();
|
||||
return xml;
|
||||
}
|
||||
|
||||
private String valueString;
|
||||
|
||||
public final String getValueString() {
|
||||
if (valueString == null) {
|
||||
valueString = getValueInternal();
|
||||
}
|
||||
return valueString;
|
||||
}
|
||||
|
||||
protected abstract String getValueInternal();
|
||||
|
||||
public static class IntField extends IoTDataField {
|
||||
|
||||
private final int value;
|
||||
|
||||
public IntField(String name, int value) {
|
||||
super(Type.integer, name);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getValueInternal() {
|
||||
return Integer.toString(value);
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
public static class BooleanField extends IoTDataField {
|
||||
|
||||
private final boolean value;
|
||||
|
||||
public BooleanField(String name, boolean value) {
|
||||
super(Type.bool, name);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getValueInternal() {
|
||||
return Boolean.toString(value);
|
||||
}
|
||||
|
||||
public boolean getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.data.element;
|
||||
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
|
||||
public class IoTDataReadOutAccepted extends IQ {
|
||||
|
||||
public static final String ELEMENT = "accepted";
|
||||
public static final String NAMESPACE = Constants.IOT_SENSORDATA_NAMESPACE;
|
||||
|
||||
/**
|
||||
* The sequence number. According to XEP-0323 an xs:int.
|
||||
*/
|
||||
private final int seqNr;
|
||||
|
||||
private final boolean queued;
|
||||
|
||||
public IoTDataReadOutAccepted(int seqNr, boolean queued) {
|
||||
super(ELEMENT, NAMESPACE);
|
||||
this.seqNr = seqNr;
|
||||
this.queued = queued;
|
||||
setType(Type.result);
|
||||
}
|
||||
|
||||
public IoTDataReadOutAccepted(IoTDataRequest dataRequest) {
|
||||
this(dataRequest.getSequenceNr(), false);
|
||||
setStanzaId(dataRequest.getStanzaId());
|
||||
setTo(dataRequest.getFrom());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) {
|
||||
xml.attribute("seqnr", seqNr);
|
||||
xml.optBooleanAttribute("queued", queued);
|
||||
xml.setEmptyElement();
|
||||
return xml;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.data.element;
|
||||
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
|
||||
public class IoTDataRequest extends IQ {
|
||||
|
||||
public static final String ELEMENT = "req";
|
||||
public static final String NAMESPACE = Constants.IOT_SENSORDATA_NAMESPACE;
|
||||
|
||||
/**
|
||||
* The sequence nummber. According to XEP-0323 an xs:int.
|
||||
*/
|
||||
private final int seqNr;
|
||||
|
||||
private final boolean momentary;
|
||||
|
||||
public IoTDataRequest(int seqNr, boolean momentary) {
|
||||
super(ELEMENT, NAMESPACE);
|
||||
this.seqNr = seqNr;
|
||||
this.momentary = momentary;
|
||||
}
|
||||
|
||||
public int getSequenceNr() {
|
||||
return seqNr;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) {
|
||||
xml.attribute("seqnr", seqNr);
|
||||
xml.optBooleanAttribute("momentary", momentary);
|
||||
xml.setEmptyElement();
|
||||
return xml;
|
||||
}
|
||||
|
||||
public boolean isMomentary() {
|
||||
return momentary;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.data.element;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.jivesoftware.smack.packet.ExtensionElement;
|
||||
import org.jivesoftware.smack.packet.Message;
|
||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||
import org.jivesoftware.smackx.iot.element.NodeInfo;
|
||||
|
||||
public class IoTFieldsExtension implements ExtensionElement {
|
||||
|
||||
public static final String ELEMENT = "fields";
|
||||
public static final String NAMESPACE = Constants.IOT_SENSORDATA_NAMESPACE;
|
||||
|
||||
private final int seqNr;
|
||||
private final boolean done;
|
||||
private final List<NodeElement> nodes;
|
||||
|
||||
public IoTFieldsExtension(int seqNr, boolean done, NodeElement node) {
|
||||
this(seqNr, done, Collections.singletonList(node));
|
||||
}
|
||||
|
||||
public IoTFieldsExtension(int seqNr, boolean done, List<NodeElement> nodes) {
|
||||
this.seqNr = seqNr;
|
||||
this.done = done;
|
||||
this.nodes = Collections.unmodifiableList(nodes);
|
||||
}
|
||||
|
||||
public int getSequenceNr() {
|
||||
return seqNr;
|
||||
}
|
||||
|
||||
public boolean isDone() {
|
||||
return done;
|
||||
}
|
||||
|
||||
public List<NodeElement> getNodes() {
|
||||
return nodes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getElementName() {
|
||||
return ELEMENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNamespace() {
|
||||
return NAMESPACE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XmlStringBuilder toXML() {
|
||||
XmlStringBuilder xml = new XmlStringBuilder(this);
|
||||
xml.attribute("seqnr", Integer.toString(seqNr));
|
||||
xml.attribute("done", done);
|
||||
xml.rightAngleBracket();
|
||||
|
||||
xml.append(nodes);
|
||||
|
||||
xml.closeElement(this);
|
||||
return xml;
|
||||
}
|
||||
|
||||
public static IoTFieldsExtension buildFor(int seqNr, boolean done, NodeInfo nodeInfo,
|
||||
List<? extends IoTDataField> data) {
|
||||
TimestampElement timestampElement = new TimestampElement(new Date(), data);
|
||||
NodeElement nodeElement = new NodeElement(nodeInfo, timestampElement);
|
||||
return new IoTFieldsExtension(seqNr, done, nodeElement);
|
||||
}
|
||||
|
||||
public static IoTFieldsExtension from(Message message) {
|
||||
return message.getExtension(ELEMENT, NAMESPACE);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.data.element;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.jivesoftware.smack.packet.NamedElement;
|
||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||
import org.jivesoftware.smackx.iot.element.NodeInfo;
|
||||
|
||||
public class NodeElement implements NamedElement {
|
||||
|
||||
public static final String ELEMENT = "node";
|
||||
|
||||
private final NodeInfo nodeInfo;
|
||||
private final List<TimestampElement> timestampElements;
|
||||
|
||||
public NodeElement(NodeInfo nodeInfo, TimestampElement timestampElement) {
|
||||
this(nodeInfo, Collections.singletonList(timestampElement));
|
||||
}
|
||||
|
||||
public NodeElement(NodeInfo nodeInfo, List<TimestampElement> timestampElements) {
|
||||
this.nodeInfo = nodeInfo;
|
||||
this.timestampElements = Collections.unmodifiableList(timestampElements);
|
||||
}
|
||||
|
||||
public List<TimestampElement> getTimestampElements() {
|
||||
return timestampElements;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getElementName() {
|
||||
return ELEMENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XmlStringBuilder toXML() {
|
||||
XmlStringBuilder xml = new XmlStringBuilder(this);
|
||||
nodeInfo.appendTo(xml);
|
||||
xml.rightAngleBracket();
|
||||
|
||||
xml.append(timestampElements);
|
||||
|
||||
xml.closeElement(this);
|
||||
return xml;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.data.element;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.jivesoftware.smack.packet.NamedElement;
|
||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||
|
||||
public class TimestampElement implements NamedElement {
|
||||
|
||||
public static final String ELEMENT = "timestamp";
|
||||
|
||||
private final Date date;
|
||||
private final List<? extends IoTDataField> fields;
|
||||
|
||||
public TimestampElement(Date date, List<? extends IoTDataField> fields) {
|
||||
this.date = date;
|
||||
this.fields = Collections.unmodifiableList(fields);
|
||||
}
|
||||
|
||||
public List<? extends IoTDataField> getDataFields() {
|
||||
return fields;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getElementName() {
|
||||
return ELEMENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XmlStringBuilder toXML() {
|
||||
XmlStringBuilder xml = new XmlStringBuilder(this);
|
||||
xml.attribute("value", date);
|
||||
xml.rightAngleBracket();
|
||||
|
||||
xml.append(fields);
|
||||
|
||||
xml.closeElement(this);
|
||||
return xml;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Smack's API for XMPP IoT.
|
||||
*/
|
||||
package org.jivesoftware.smackx.iot.data.element;
|
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.data.filter;
|
||||
|
||||
import org.jivesoftware.smack.filter.FlexibleStanzaTypeFilter;
|
||||
import org.jivesoftware.smack.packet.Message;
|
||||
import org.jivesoftware.smackx.iot.data.element.IoTFieldsExtension;
|
||||
|
||||
public class IoTFieldsExtensionFilter extends FlexibleStanzaTypeFilter<Message> {
|
||||
|
||||
private final int seqNr;
|
||||
private final boolean onlyDone;
|
||||
|
||||
public IoTFieldsExtensionFilter(int seqNr, boolean onlyDone) {
|
||||
this.seqNr = seqNr;
|
||||
this.onlyDone = onlyDone;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean acceptSpecific(Message message) {
|
||||
IoTFieldsExtension iotFieldsExtension = IoTFieldsExtension.from(message);
|
||||
if (iotFieldsExtension == null) {
|
||||
return false;
|
||||
}
|
||||
if (iotFieldsExtension.getSequenceNr() != seqNr) {
|
||||
return false;
|
||||
}
|
||||
if (onlyDone && !iotFieldsExtension.isDone()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Smack's API for XMPP IoT.
|
||||
*/
|
||||
package org.jivesoftware.smackx.iot.data.filter;
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Smack's API for XMPP IoT.
|
||||
*/
|
||||
package org.jivesoftware.smackx.iot.data;
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.data.provider;
|
||||
|
||||
import org.jivesoftware.smack.provider.IQProvider;
|
||||
import org.jivesoftware.smack.util.ParserUtils;
|
||||
import org.jivesoftware.smackx.iot.data.element.IoTDataReadOutAccepted;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
public class IoTDataReadOutAcceptedProvider extends IQProvider<IoTDataReadOutAccepted> {
|
||||
|
||||
@Override
|
||||
public IoTDataReadOutAccepted parse(XmlPullParser parser, int initialDepth) throws Exception {
|
||||
int seqNr = ParserUtils.getIntegerAttributeOrThrow(parser, "seqnr", "IoT data request <accepted/> without sequence number");
|
||||
boolean queued = ParserUtils.getBooleanAttribute(parser, "queued", false);
|
||||
return new IoTDataReadOutAccepted(seqNr, queued);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.data.provider;
|
||||
|
||||
import org.jivesoftware.smack.provider.IQProvider;
|
||||
import org.jivesoftware.smack.util.ParserUtils;
|
||||
import org.jivesoftware.smackx.iot.data.element.IoTDataRequest;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
public class IoTDataRequestProvider extends IQProvider<IoTDataRequest> {
|
||||
|
||||
@Override
|
||||
public IoTDataRequest parse(XmlPullParser parser, int initialDepth) throws Exception {
|
||||
int seqNr = ParserUtils.getIntegerAttributeOrThrow(parser, "seqnr", "IoT data request without sequence number");
|
||||
boolean momentary = ParserUtils.getBooleanAttribute(parser, "momentary", false);
|
||||
return new IoTDataRequest(seqNr, momentary);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.data.provider;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.jivesoftware.smack.provider.ExtensionElementProvider;
|
||||
import org.jivesoftware.smack.util.ParserUtils;
|
||||
import org.jivesoftware.smackx.iot.data.element.IoTDataField;
|
||||
import org.jivesoftware.smackx.iot.data.element.IoTFieldsExtension;
|
||||
import org.jivesoftware.smackx.iot.data.element.NodeElement;
|
||||
import org.jivesoftware.smackx.iot.data.element.TimestampElement;
|
||||
import org.jivesoftware.smackx.iot.element.NodeInfo;
|
||||
import org.jivesoftware.smackx.iot.parser.NodeInfoParser;
|
||||
import org.jxmpp.util.XmppDateTime;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
public class IoTFieldsExtensionProvider extends ExtensionElementProvider<IoTFieldsExtension> {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(IoTFieldsExtensionProvider.class.getName());
|
||||
|
||||
@Override
|
||||
public IoTFieldsExtension parse(XmlPullParser parser, int initialDepth) throws Exception {
|
||||
int seqNr = ParserUtils.getIntegerAttributeOrThrow(parser, "seqnr", "IoT data request <accepted/> without sequence number");
|
||||
boolean done = ParserUtils.getBooleanAttribute(parser, "done", false);
|
||||
List<NodeElement> nodes = new ArrayList<>();
|
||||
outerloop: while (true) {
|
||||
final int eventType = parser.next();
|
||||
final String name = parser.getName();
|
||||
switch (eventType) {
|
||||
case XmlPullParser.START_TAG:
|
||||
switch (name) {
|
||||
case NodeElement.ELEMENT:
|
||||
NodeElement node = parseNode(parser);
|
||||
nodes.add(node);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case XmlPullParser.END_TAG:
|
||||
if (parser.getDepth() == initialDepth) {
|
||||
break outerloop;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return new IoTFieldsExtension(seqNr, done, nodes);
|
||||
}
|
||||
|
||||
public NodeElement parseNode(XmlPullParser parser) throws XmlPullParserException, IOException, ParseException {
|
||||
final int initialDepth = parser.getDepth();
|
||||
final NodeInfo nodeInfo = NodeInfoParser.parse(parser);
|
||||
List<TimestampElement> timestampElements = new ArrayList<>();
|
||||
outerloop: while (true) {
|
||||
final int eventType = parser.next();
|
||||
final String name = parser.getName();
|
||||
switch (eventType) {
|
||||
case XmlPullParser.START_TAG:
|
||||
switch (name){
|
||||
case TimestampElement.ELEMENT:
|
||||
TimestampElement timestampElement = parseTimestampElement(parser);
|
||||
timestampElements.add(timestampElement);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case XmlPullParser.END_TAG:
|
||||
if (parser.getDepth() == initialDepth) {
|
||||
break outerloop;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return new NodeElement(nodeInfo, timestampElements);
|
||||
}
|
||||
|
||||
public TimestampElement parseTimestampElement(XmlPullParser parser) throws ParseException, XmlPullParserException, IOException {
|
||||
final int initialDepth = parser.getDepth();
|
||||
final String dateString = parser.getAttributeValue(null, "value");
|
||||
final Date date = XmppDateTime.parseDate(dateString);
|
||||
List<IoTDataField> fields = new ArrayList<>();
|
||||
outerloop: while (true) {
|
||||
final int eventType = parser.next();
|
||||
final String name = parser.getName();
|
||||
switch (eventType) {
|
||||
case XmlPullParser.START_TAG:
|
||||
IoTDataField field = null;
|
||||
final String fieldName = parser.getAttributeValue(null, "name");
|
||||
final String fieldValue = parser.getAttributeValue(null, "value");
|
||||
switch (name) {
|
||||
case "int": {
|
||||
int value = Integer.parseInt(fieldValue);
|
||||
field = new IoTDataField.IntField(fieldName, value);
|
||||
}
|
||||
break;
|
||||
case "boolean": {
|
||||
boolean value = Boolean.parseBoolean(fieldValue);
|
||||
field = new IoTDataField.BooleanField(fieldName, value);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOGGER.warning("IoT Data field type '" + name + "' not implement yet. Ignoring.");
|
||||
break;
|
||||
}
|
||||
if (field != null) {
|
||||
fields.add(field);
|
||||
}
|
||||
break;
|
||||
case XmlPullParser.END_TAG:
|
||||
if (parser.getDepth() == initialDepth) {
|
||||
break outerloop;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return new TimestampElement(date, fields);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Smack's API for XMPP IoT.
|
||||
*/
|
||||
package org.jivesoftware.smackx.iot.data.provider;
|
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.discovery;
|
||||
|
||||
import org.jxmpp.jid.BareJid;
|
||||
|
||||
public abstract class AbstractThingStateChangeListener implements ThingStateChangeListener {
|
||||
|
||||
@Override
|
||||
public void owned(BareJid owner) {
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.discovery;
|
||||
|
||||
import org.jivesoftware.smackx.iot.IoTException;
|
||||
import org.jivesoftware.smackx.iot.discovery.element.IoTClaimed;
|
||||
|
||||
public class IoTClaimedException extends IoTException {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final IoTClaimed iotClaimed;
|
||||
|
||||
public IoTClaimedException(IoTClaimed iotClaimed) {
|
||||
this.iotClaimed = iotClaimed;
|
||||
}
|
||||
|
||||
public IoTClaimed getIoTClaimed() {
|
||||
return iotClaimed;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,420 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.discovery;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.jivesoftware.smack.ConnectionCreationListener;
|
||||
import org.jivesoftware.smack.Manager;
|
||||
import org.jivesoftware.smack.SmackException.NoResponseException;
|
||||
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
import org.jivesoftware.smack.XMPPConnectionRegistry;
|
||||
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
|
||||
import org.jivesoftware.smack.iqrequest.AbstractIqRequestHandler;
|
||||
import org.jivesoftware.smack.iqrequest.IQRequestHandler.Mode;
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
|
||||
import org.jivesoftware.smackx.disco.packet.DiscoverInfo;
|
||||
import org.jivesoftware.smackx.iot.Thing;
|
||||
import org.jivesoftware.smackx.iot.control.IoTControlManager;
|
||||
import org.jivesoftware.smackx.iot.data.IoTDataManager;
|
||||
import org.jivesoftware.smackx.iot.discovery.element.Constants;
|
||||
import org.jivesoftware.smackx.iot.discovery.element.IoTClaimed;
|
||||
import org.jivesoftware.smackx.iot.discovery.element.IoTDisown;
|
||||
import org.jivesoftware.smackx.iot.discovery.element.IoTDisowned;
|
||||
import org.jivesoftware.smackx.iot.discovery.element.IoTMine;
|
||||
import org.jivesoftware.smackx.iot.discovery.element.IoTRegister;
|
||||
import org.jivesoftware.smackx.iot.discovery.element.IoTRemove;
|
||||
import org.jivesoftware.smackx.iot.discovery.element.IoTRemoved;
|
||||
import org.jivesoftware.smackx.iot.discovery.element.IoTUnregister;
|
||||
import org.jivesoftware.smackx.iot.discovery.element.Tag;
|
||||
import org.jivesoftware.smackx.iot.element.NodeInfo;
|
||||
import org.jivesoftware.smackx.iot.provisioning.IoTProvisioningManager;
|
||||
import org.jxmpp.jid.BareJid;
|
||||
import org.jxmpp.jid.Jid;
|
||||
|
||||
/**
|
||||
* A manager for XEP-0347: Internet of Things - Discovery. Used to register and discover things.
|
||||
*
|
||||
* @author Florian Schmaus {@literal <flo@geekplace.eu>}
|
||||
* @see <a href="http://xmpp.org/extensions/xep-0347.html">XEP-0347: Internet of Things - Discovery</a>
|
||||
*
|
||||
*/
|
||||
public final class IoTDiscoveryManager extends Manager {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(IoTDiscoveryManager.class.getName());
|
||||
|
||||
private static final Map<XMPPConnection, IoTDiscoveryManager> INSTANCES = new WeakHashMap<>();
|
||||
|
||||
// Ensure a IoTProvisioningManager exists for every connection.
|
||||
static {
|
||||
XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() {
|
||||
public void connectionCreated(XMPPConnection connection) {
|
||||
getInstanceFor(connection);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the manger instance responsible for the given connection.
|
||||
*
|
||||
* @param connection the XMPP connection.
|
||||
* @return a manager instance.
|
||||
*/
|
||||
public static synchronized IoTDiscoveryManager getInstanceFor(XMPPConnection connection) {
|
||||
IoTDiscoveryManager manager = INSTANCES.get(connection);
|
||||
if (manager == null) {
|
||||
manager = new IoTDiscoveryManager(connection);
|
||||
INSTANCES.put(connection, manager);
|
||||
}
|
||||
return manager;
|
||||
}
|
||||
|
||||
private Jid preconfiguredRegistry;
|
||||
|
||||
/**
|
||||
* A set of all registries we have interacted so far. {@link #isRegistry(BareJid)} uses this to
|
||||
* determine if the jid is a registry. Note that we currently do not record which thing
|
||||
* interacted with which registry. This allows any registry we have interacted so far with, to
|
||||
* send registry control stanzas about any other thing, and we would process them.
|
||||
*/
|
||||
private final Set<Jid> usedRegistries = new HashSet<>();
|
||||
|
||||
/**
|
||||
* Internal state of the things. Uses <code>null</code> for the single thing without node info attached.
|
||||
*/
|
||||
private final Map<NodeInfo, ThingState> things = new HashMap<>();
|
||||
|
||||
private IoTDiscoveryManager(XMPPConnection connection) {
|
||||
super(connection);
|
||||
|
||||
connection.registerIQRequestHandler(
|
||||
new AbstractIqRequestHandler(IoTClaimed.ELEMENT, IoTClaimed.NAMESPACE, IQ.Type.set, Mode.sync) {
|
||||
@Override
|
||||
public IQ handleIQRequest(IQ iqRequest) {
|
||||
if (!isRegistry(iqRequest.getFrom())) {
|
||||
LOGGER.log(Level.SEVERE, "Received control stanza from non-registry entity: " + iqRequest);
|
||||
return null;
|
||||
}
|
||||
|
||||
IoTClaimed iotClaimed = (IoTClaimed) iqRequest;
|
||||
Jid owner = iotClaimed.getJid();
|
||||
NodeInfo nodeInfo = iotClaimed.getNodeInfo();
|
||||
// Update the state.
|
||||
ThingState state = getStateFor(nodeInfo);
|
||||
state.setOwner(owner.asBareJid());
|
||||
LOGGER.info("Our thing got claimed by " + owner + ". " + iotClaimed);
|
||||
|
||||
IoTProvisioningManager iotProvisioningManager = IoTProvisioningManager.getInstanceFor(
|
||||
connection());
|
||||
try {
|
||||
iotProvisioningManager.sendFriendshipRequest(owner.asBareJid());
|
||||
}
|
||||
catch (NotConnectedException | InterruptedException e) {
|
||||
LOGGER.log(Level.WARNING, "Could not friendship owner", e);
|
||||
}
|
||||
|
||||
return IQ.createResultIQ(iqRequest);
|
||||
}
|
||||
});
|
||||
|
||||
connection.registerIQRequestHandler(new AbstractIqRequestHandler(IoTDisowned.ELEMENT, IoTDisowned.NAMESPACE,
|
||||
IQ.Type.set, Mode.sync) {
|
||||
@Override
|
||||
public IQ handleIQRequest(IQ iqRequest) {
|
||||
if (!isRegistry(iqRequest.getFrom())) {
|
||||
LOGGER.log(Level.SEVERE, "Received control stanza from non-registry entity: " + iqRequest);
|
||||
return null;
|
||||
}
|
||||
|
||||
IoTDisowned iotDisowned = (IoTDisowned) iqRequest;
|
||||
Jid from = iqRequest.getFrom();
|
||||
|
||||
NodeInfo nodeInfo = iotDisowned.getNodeInfo();
|
||||
ThingState state = getStateFor(nodeInfo);
|
||||
if (!from.equals(state.getRegistry())) {
|
||||
LOGGER.severe("Received <disowned/> for " + nodeInfo + " from " + from
|
||||
+ " but this is not the registry " + state.getRegistry() + " of the thing.");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (state.isOwned()) {
|
||||
state.setUnowned();
|
||||
} else {
|
||||
LOGGER.fine("Received <disowned/> for " + nodeInfo + " but thing was not owned.");
|
||||
}
|
||||
|
||||
return IQ.createResultIQ(iqRequest);
|
||||
}
|
||||
});
|
||||
|
||||
// XEP-0347 § 3.9 (ex28-29): <removed/>
|
||||
connection.registerIQRequestHandler(new AbstractIqRequestHandler(IoTRemoved.ELEMENT, IoTRemoved.NAMESPACE, IQ.Type.set, Mode.async) {
|
||||
@Override
|
||||
public IQ handleIQRequest(IQ iqRequest) {
|
||||
if (!isRegistry(iqRequest.getFrom())) {
|
||||
LOGGER.log(Level.SEVERE, "Received control stanza from non-registry entity: " + iqRequest);
|
||||
return null;
|
||||
}
|
||||
|
||||
IoTRemoved iotRemoved = (IoTRemoved) iqRequest;
|
||||
|
||||
ThingState state = getStateFor(iotRemoved.getNodeInfo());
|
||||
state.setRemoved();
|
||||
|
||||
// Unfriend registry. "It does this, so the Thing can remove the friendship and stop any
|
||||
// meta data updates to the Registry."
|
||||
try {
|
||||
IoTProvisioningManager.getInstanceFor(connection()).unfriend(iotRemoved.getFrom());
|
||||
}
|
||||
catch (NotConnectedException | InterruptedException e) {
|
||||
LOGGER.log(Level.SEVERE, "Could not unfriend registry after <removed/>", e);
|
||||
}
|
||||
|
||||
return IQ.createResultIQ(iqRequest);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to find an XMPP IoT registry.
|
||||
*
|
||||
* @return the JID of a Thing Registry if one could be found.
|
||||
* @throws InterruptedException
|
||||
* @throws NotConnectedException
|
||||
* @throws XMPPErrorException
|
||||
* @throws NoResponseException
|
||||
* @see <a href="http://xmpp.org/extensions/xep-0347.html#findingregistry">XEP-0347 § 3.5 Finding Thing Registry</a>
|
||||
*/
|
||||
public Jid findRegistry()
|
||||
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||
if (preconfiguredRegistry != null) {
|
||||
return preconfiguredRegistry;
|
||||
}
|
||||
|
||||
final XMPPConnection connection = connection();
|
||||
ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection);
|
||||
List<DiscoverInfo> discoverInfos = sdm.findServicesDiscoverInfo(Constants.IOT_DISCOVERY_NAMESPACE, true, true);
|
||||
if (!discoverInfos.isEmpty()) {
|
||||
return discoverInfos.get(0).getFrom();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Thing Registration - XEP-0347 § 3.6 - 3.8
|
||||
|
||||
public ThingState registerThing(Thing thing)
|
||||
throws NotConnectedException, InterruptedException, NoResponseException, XMPPErrorException, IoTClaimedException {
|
||||
Jid registry = findRegistry();
|
||||
return registerThing(registry, thing);
|
||||
}
|
||||
|
||||
public ThingState registerThing(Jid registry, Thing thing)
|
||||
throws NotConnectedException, InterruptedException, NoResponseException, XMPPErrorException, IoTClaimedException {
|
||||
final XMPPConnection connection = connection();
|
||||
IoTRegister iotRegister = new IoTRegister(thing.getMetaTags(), thing.getNodeInfo(), thing.isSelfOwened());
|
||||
iotRegister.setTo(registry);
|
||||
IQ result = connection.createPacketCollectorAndSend(iotRegister).nextResultOrThrow();
|
||||
if (result instanceof IoTClaimed) {
|
||||
IoTClaimed iotClaimedResult = (IoTClaimed) result;
|
||||
throw new IoTClaimedException(iotClaimedResult);
|
||||
}
|
||||
|
||||
ThingState state = getStateFor(thing.getNodeInfo());
|
||||
state.setRegistry(registry.asBareJid());
|
||||
|
||||
interactWithRegistry(registry);
|
||||
|
||||
IoTDataManager.getInstanceFor(connection).installThing(thing);
|
||||
IoTControlManager.getInstanceFor(connection).installThing(thing);
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
// Thing Claiming - XEP-0347 § 3.9
|
||||
|
||||
public IoTClaimed claimThing(Collection<Tag> metaTags) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||
return claimThing(metaTags, true);
|
||||
}
|
||||
|
||||
public IoTClaimed claimThing(Collection<Tag> metaTags, boolean publicThing) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||
Jid registry = findRegistry();
|
||||
return claimThing(registry, metaTags, publicThing);
|
||||
}
|
||||
|
||||
/**
|
||||
* Claim a thing by providing a collection of meta tags. If the claim was successful, then a {@link IoTClaimed}
|
||||
* instance will be returned, which contains the XMPP address of the thing. Use {@link IoTClaimed#getJid()} to
|
||||
* retrieve this address.
|
||||
*
|
||||
* @param registry the registry use to claim the thing.
|
||||
* @param metaTags a collection of meta tags used to identify the thing.
|
||||
* @param publicThing if this is a public thing.
|
||||
* @return a {@link IoTClaimed} if successful.
|
||||
* @throws NoResponseException
|
||||
* @throws XMPPErrorException
|
||||
* @throws NotConnectedException
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public IoTClaimed claimThing(Jid registry, Collection<Tag> metaTags, boolean publicThing) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||
interactWithRegistry(registry);
|
||||
|
||||
IoTMine iotMine = new IoTMine(metaTags, publicThing);
|
||||
iotMine.setTo(registry);
|
||||
IoTClaimed iotClaimed = connection().createPacketCollectorAndSend(iotMine).nextResultOrThrow();
|
||||
|
||||
// The 'jid' attribute of the <claimed/> response now represents the XMPP address of the thing we just successfully claimed.
|
||||
Jid thing = iotClaimed.getJid();
|
||||
|
||||
IoTProvisioningManager.getInstanceFor(connection()).sendFriendshipRequest(thing.asBareJid());
|
||||
|
||||
return iotClaimed;
|
||||
}
|
||||
|
||||
// Thing Removal - XEP-0347 § 3.10
|
||||
|
||||
public void removeThing(BareJid thing)
|
||||
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||
removeThing(thing, NodeInfo.EMPTY);
|
||||
}
|
||||
|
||||
public void removeThing(BareJid thing, NodeInfo nodeInfo)
|
||||
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||
Jid registry = findRegistry();
|
||||
removeThing(registry, thing, nodeInfo);
|
||||
}
|
||||
|
||||
public void removeThing(Jid registry, BareJid thing, NodeInfo nodeInfo)
|
||||
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||
interactWithRegistry(registry);
|
||||
|
||||
IoTRemove iotRemove = new IoTRemove(thing, nodeInfo);
|
||||
iotRemove.setTo(registry);
|
||||
connection().createPacketCollectorAndSend(iotRemove).nextResultOrThrow();
|
||||
|
||||
// We no not update the ThingState here, as this is done in the <removed/> IQ handler above.;
|
||||
}
|
||||
|
||||
// Thing Unregistering - XEP-0347 § 3.16
|
||||
|
||||
public void unregister()
|
||||
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||
unregister(NodeInfo.EMPTY);
|
||||
}
|
||||
|
||||
public void unregister(NodeInfo nodeInfo)
|
||||
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||
Jid registry = findRegistry();
|
||||
unregister(registry, nodeInfo);
|
||||
}
|
||||
|
||||
public void unregister(Jid registry, NodeInfo nodeInfo)
|
||||
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||
interactWithRegistry(registry);
|
||||
|
||||
IoTUnregister iotUnregister = new IoTUnregister(nodeInfo);
|
||||
iotUnregister.setTo(registry);
|
||||
connection().createPacketCollectorAndSend(iotUnregister).nextResultOrThrow();
|
||||
|
||||
ThingState state = getStateFor(nodeInfo);
|
||||
state.setUnregistered();
|
||||
|
||||
final XMPPConnection connection = connection();
|
||||
IoTDataManager.getInstanceFor(connection).uninstallThing(nodeInfo);
|
||||
IoTControlManager.getInstanceFor(connection).uninstallThing(nodeInfo);
|
||||
}
|
||||
|
||||
// Thing Disowning - XEP-0347 § 3.17
|
||||
|
||||
public void disownThing(Jid thing)
|
||||
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||
disownThing(thing, NodeInfo.EMPTY);
|
||||
}
|
||||
|
||||
public void disownThing(Jid thing, NodeInfo nodeInfo)
|
||||
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||
Jid registry = findRegistry();
|
||||
disownThing(registry, thing, nodeInfo);
|
||||
}
|
||||
|
||||
public void disownThing(Jid registry, Jid thing, NodeInfo nodeInfo)
|
||||
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||
interactWithRegistry(registry);
|
||||
|
||||
IoTDisown iotDisown = new IoTDisown(thing, nodeInfo);
|
||||
iotDisown.setTo(registry);
|
||||
connection().createPacketCollectorAndSend(iotDisown).nextResultOrThrow();
|
||||
}
|
||||
|
||||
// Registry utility methods
|
||||
|
||||
public boolean isRegistry(BareJid jid) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||
// At some point 'usedRegistries' will also contain the registry returned by findRegistry(), but since this is
|
||||
// not the case from the beginning, we perform findRegistry().equals(jid) too.
|
||||
if (findRegistry().equals(jid)) {
|
||||
return true;
|
||||
}
|
||||
if (usedRegistries.contains(jid)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isRegistry(Jid jid) {
|
||||
try {
|
||||
return isRegistry(jid.asBareJid());
|
||||
}
|
||||
catch (NoResponseException | XMPPErrorException | NotConnectedException
|
||||
| InterruptedException e) {
|
||||
LOGGER.log(Level.WARNING, "Could not determine if " + jid + " is a registry", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void interactWithRegistry(Jid registry) throws NotConnectedException, InterruptedException {
|
||||
boolean isNew = usedRegistries.add(registry);
|
||||
if (!isNew) {
|
||||
return;
|
||||
}
|
||||
IoTProvisioningManager iotProvisioningManager = IoTProvisioningManager.getInstanceFor(connection());
|
||||
iotProvisioningManager.sendFriendshipRequestIfRequired(registry.asBareJid());
|
||||
}
|
||||
|
||||
public ThingState getStateFor(Thing thing) {
|
||||
return things.get(thing.getNodeInfo());
|
||||
}
|
||||
|
||||
private ThingState getStateFor(NodeInfo nodeInfo) {
|
||||
ThingState state = things.get(nodeInfo);
|
||||
if (state == null) {
|
||||
state = new ThingState(nodeInfo);
|
||||
things.put(nodeInfo, state);
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.discovery;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import org.jivesoftware.smack.util.Async;
|
||||
import org.jivesoftware.smackx.iot.element.NodeInfo;
|
||||
import org.jxmpp.jid.BareJid;
|
||||
|
||||
public class ThingState {
|
||||
|
||||
private final NodeInfo nodeInfo;
|
||||
|
||||
private BareJid registry;
|
||||
private BareJid owner;
|
||||
private boolean removed;
|
||||
|
||||
private final List<ThingStateChangeListener> listeners = new CopyOnWriteArrayList<>();
|
||||
|
||||
ThingState(NodeInfo nodeInfo) {
|
||||
this.nodeInfo = nodeInfo;
|
||||
}
|
||||
|
||||
void setRegistry(BareJid registry) {
|
||||
this.registry = registry;
|
||||
}
|
||||
|
||||
void setUnregistered() {
|
||||
this.registry = null;
|
||||
}
|
||||
|
||||
void setOwner(final BareJid owner) {
|
||||
this.owner = owner;
|
||||
Async.go(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (ThingStateChangeListener thingStateChangeListener : listeners) {
|
||||
thingStateChangeListener.owned(owner);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void setUnowned() {
|
||||
this.owner = null;
|
||||
}
|
||||
|
||||
void setRemoved() {
|
||||
removed = true;
|
||||
}
|
||||
|
||||
public NodeInfo getNodeInfo() {
|
||||
return nodeInfo;
|
||||
}
|
||||
|
||||
public BareJid getRegistry() {
|
||||
return registry;
|
||||
}
|
||||
|
||||
public BareJid getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
public boolean isOwned() {
|
||||
return owner != null;
|
||||
}
|
||||
|
||||
public boolean isRemoved() {
|
||||
return removed;
|
||||
}
|
||||
|
||||
public boolean setThingStateChangeListener(ThingStateChangeListener thingStateChangeListener) {
|
||||
return listeners.add(thingStateChangeListener);
|
||||
}
|
||||
|
||||
public boolean removeThingStateChangeListener(ThingStateChangeListener thingStateChangeListener) {
|
||||
return listeners.remove(thingStateChangeListener);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.discovery;
|
||||
|
||||
import org.jxmpp.jid.BareJid;
|
||||
|
||||
public interface ThingStateChangeListener {
|
||||
|
||||
public void owned(BareJid owner);
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.discovery.element;
|
||||
|
||||
public class Constants {
|
||||
|
||||
public static final String IOT_DISCOVERY_NAMESPACE = "urn:xmpp:iot:discovery";
|
||||
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.discovery.element;
|
||||
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
import org.jivesoftware.smackx.iot.element.NodeInfo;
|
||||
import org.jxmpp.jid.Jid;
|
||||
|
||||
public class IoTClaimed extends IQ {
|
||||
|
||||
public static final String ELEMENT = "claimed";
|
||||
public static final String NAMESPACE = Constants.IOT_DISCOVERY_NAMESPACE;
|
||||
|
||||
private final Jid jid;
|
||||
|
||||
private final NodeInfo nodeInfo;
|
||||
|
||||
public IoTClaimed(Jid jid) {
|
||||
this(jid, NodeInfo.EMPTY);
|
||||
}
|
||||
|
||||
public IoTClaimed(Jid jid, NodeInfo nodeInfo) {
|
||||
super(ELEMENT, NAMESPACE);
|
||||
this.jid = jid;
|
||||
this.nodeInfo = nodeInfo;
|
||||
}
|
||||
|
||||
public Jid getJid() {
|
||||
return jid;
|
||||
}
|
||||
|
||||
public String getNodeId() {
|
||||
return nodeInfo.getNodeId();
|
||||
}
|
||||
|
||||
public String getSourceId() {
|
||||
return nodeInfo.getSourceId();
|
||||
}
|
||||
|
||||
public NodeInfo getNodeInfo() {
|
||||
return nodeInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) {
|
||||
xml.attribute("jid", jid);
|
||||
nodeInfo.appendTo(xml);
|
||||
xml.setEmptyElement();
|
||||
return xml;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.discovery.element;
|
||||
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
import org.jivesoftware.smackx.iot.element.NodeInfo;
|
||||
import org.jxmpp.jid.Jid;
|
||||
|
||||
public class IoTDisown extends IQ {
|
||||
|
||||
public static final String ELEMENT = "disown";
|
||||
public static final String NAMESPACE = Constants.IOT_DISCOVERY_NAMESPACE;
|
||||
|
||||
private final Jid jid;
|
||||
|
||||
private final NodeInfo nodeInfo;
|
||||
|
||||
public IoTDisown(Jid jid) {
|
||||
this(jid, NodeInfo.EMPTY);
|
||||
}
|
||||
|
||||
public IoTDisown(Jid jid, NodeInfo nodeInfo) {
|
||||
super(ELEMENT, NAMESPACE);
|
||||
this.jid = jid;
|
||||
this.nodeInfo = nodeInfo;
|
||||
}
|
||||
|
||||
public Jid getJid() {
|
||||
return jid;
|
||||
}
|
||||
|
||||
public String getNodeId() {
|
||||
return nodeInfo != null ? nodeInfo.getNodeId() : null;
|
||||
}
|
||||
|
||||
public String getSourceId() {
|
||||
return nodeInfo != null ? nodeInfo.getSourceId() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) {
|
||||
xml.attribute("jid", jid);
|
||||
nodeInfo.appendTo(xml);
|
||||
xml.rightAngleBracket();
|
||||
return xml;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.discovery.element;
|
||||
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
import org.jivesoftware.smackx.iot.element.NodeInfo;
|
||||
|
||||
public class IoTDisowned extends IQ {
|
||||
|
||||
public static final String ELEMENT = "disown";
|
||||
public static final String NAMESPACE = Constants.IOT_DISCOVERY_NAMESPACE;
|
||||
|
||||
private final NodeInfo nodeInfo;
|
||||
|
||||
public IoTDisowned(NodeInfo nodeInfo) {
|
||||
super(ELEMENT, NAMESPACE);
|
||||
this.nodeInfo = nodeInfo;
|
||||
}
|
||||
|
||||
public String getNodeId() {
|
||||
return nodeInfo.getNodeId();
|
||||
}
|
||||
|
||||
public String getSourceId() {
|
||||
return nodeInfo.getSourceId();
|
||||
}
|
||||
|
||||
public NodeInfo getNodeInfo() {
|
||||
return nodeInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) {
|
||||
nodeInfo.appendTo(xml);
|
||||
xml.setEmptyElement();
|
||||
return xml;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.discovery.element;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
|
||||
public class IoTMine extends IQ {
|
||||
|
||||
public static final String ELEMENT = "mine";
|
||||
public static final String NAMESPACE = Constants.IOT_DISCOVERY_NAMESPACE;
|
||||
|
||||
private final List<Tag> metaTags;
|
||||
private final boolean publicThing;
|
||||
|
||||
public IoTMine(Collection<Tag> metaTags, boolean publicThing) {
|
||||
this(new ArrayList<>(metaTags), publicThing);
|
||||
}
|
||||
|
||||
public IoTMine(List<Tag> metaTags, boolean publicThing) {
|
||||
super(ELEMENT, NAMESPACE);
|
||||
this.metaTags = metaTags;
|
||||
this.publicThing = publicThing;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) {
|
||||
xml.optBooleanAttributeDefaultTrue("public", publicThing);
|
||||
xml.rightAngleBracket();
|
||||
xml.append(metaTags);
|
||||
|
||||
return xml;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.discovery.element;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
import org.jivesoftware.smackx.iot.element.NodeInfo;
|
||||
|
||||
public class IoTRegister extends IQ {
|
||||
|
||||
public static final String ELEMENT = "register";
|
||||
public static final String NAMESPACE = Constants.IOT_DISCOVERY_NAMESPACE;
|
||||
|
||||
private final Collection<Tag> tags;
|
||||
private final NodeInfo nodeInfo;
|
||||
private final boolean selfOwned;
|
||||
|
||||
public IoTRegister(Collection<Tag> tags, NodeInfo nodeInfo, boolean selfOwned) {
|
||||
super(ELEMENT, NAMESPACE);
|
||||
if (tags.isEmpty()) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
this.tags = tags;
|
||||
this.nodeInfo = nodeInfo;
|
||||
this.selfOwned = selfOwned;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) {
|
||||
nodeInfo.appendTo(xml);
|
||||
xml.optBooleanAttribute("selfOwned", selfOwned);
|
||||
xml.rightAngleBracket();
|
||||
|
||||
xml.append(tags);
|
||||
|
||||
return xml;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.discovery.element;
|
||||
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
import org.jivesoftware.smackx.iot.element.NodeInfo;
|
||||
import org.jxmpp.jid.BareJid;
|
||||
import org.jxmpp.jid.Jid;
|
||||
|
||||
public class IoTRemove extends IQ {
|
||||
|
||||
public static final String ELEMENT = "remove";
|
||||
public static final String NAMESPACE = Constants.IOT_DISCOVERY_NAMESPACE;
|
||||
|
||||
/**
|
||||
* The XMPP address of the Thing to be removed from the registry. According to XEP-0347 § 3.10 the
|
||||
* "resource-less JID of the Thing" has to be used, therefore we use {@link BareJid} here.
|
||||
*/
|
||||
private final BareJid jid;
|
||||
|
||||
private final NodeInfo nodeInfo;
|
||||
|
||||
public IoTRemove(BareJid jid) {
|
||||
this(jid, NodeInfo.EMPTY);
|
||||
}
|
||||
|
||||
public IoTRemove(BareJid jid, NodeInfo nodeInfo) {
|
||||
super(ELEMENT, NAMESPACE);
|
||||
this.jid = jid;
|
||||
this.nodeInfo = nodeInfo;
|
||||
}
|
||||
|
||||
public Jid getJid() {
|
||||
return jid;
|
||||
}
|
||||
|
||||
public String getNodeId() {
|
||||
return nodeInfo != null ? nodeInfo.getNodeId() : null;
|
||||
}
|
||||
|
||||
public String getSourceId() {
|
||||
return nodeInfo != null ? nodeInfo.getSourceId() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) {
|
||||
xml.attribute("jid", jid);
|
||||
nodeInfo.appendTo(xml);
|
||||
xml.setEmptyElement();
|
||||
return xml;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.discovery.element;
|
||||
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
import org.jivesoftware.smackx.iot.element.NodeInfo;
|
||||
|
||||
public class IoTRemoved extends IQ {
|
||||
|
||||
public static final String ELEMENT = "removed";
|
||||
public static final String NAMESPACE = Constants.IOT_DISCOVERY_NAMESPACE;
|
||||
|
||||
private final NodeInfo nodeInfo;
|
||||
|
||||
public IoTRemoved() {
|
||||
this(NodeInfo.EMPTY);
|
||||
}
|
||||
|
||||
public IoTRemoved(NodeInfo nodeInfo) {
|
||||
super(ELEMENT, NAMESPACE);
|
||||
this.nodeInfo = nodeInfo;
|
||||
}
|
||||
|
||||
public String getNodeId() {
|
||||
return nodeInfo.getNodeId();
|
||||
}
|
||||
|
||||
public String getSourceId() {
|
||||
return nodeInfo.getSourceId();
|
||||
}
|
||||
|
||||
public NodeInfo getNodeInfo() {
|
||||
return nodeInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) {
|
||||
nodeInfo.appendTo(xml);
|
||||
xml.setEmptyElement();
|
||||
return xml;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.discovery.element;
|
||||
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
import org.jivesoftware.smackx.iot.element.NodeInfo;
|
||||
|
||||
public class IoTUnregister extends IQ {
|
||||
|
||||
public static final String ELEMENT = "unregister";
|
||||
public static final String NAMESPACE = Constants.IOT_DISCOVERY_NAMESPACE;
|
||||
|
||||
private final NodeInfo nodeInfo;
|
||||
|
||||
public IoTUnregister(NodeInfo nodeInfo) {
|
||||
super(ELEMENT, NAMESPACE);
|
||||
this.nodeInfo = nodeInfo;
|
||||
setType(Type.set);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) {
|
||||
nodeInfo.appendTo(xml);
|
||||
xml.rightAngleBracket();
|
||||
return xml;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.discovery.element;
|
||||
|
||||
import org.jivesoftware.smack.packet.NamedElement;
|
||||
import org.jivesoftware.smack.util.Objects;
|
||||
import org.jivesoftware.smack.util.StringUtils;
|
||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||
|
||||
public class Tag implements NamedElement {
|
||||
|
||||
public enum Type {
|
||||
str,
|
||||
num;
|
||||
}
|
||||
|
||||
private final String name;
|
||||
private final Type type;
|
||||
private final String value;
|
||||
|
||||
public Tag(String name, Type type, String value) {
|
||||
// TODO According to XEP-0347 § 5.2 names are case insensitive. Uppercase them all?
|
||||
this.name = StringUtils.requireNotNullOrEmpty(name, "name must not be null or empty");
|
||||
this.type = Objects.requireNonNull(type);
|
||||
this.value = StringUtils.requireNotNullOrEmpty(value, "value must not be null or empty");
|
||||
if (this.name.length() > 32) {
|
||||
throw new IllegalArgumentException("Meta Tag names must not be longer then 32 characters (XEP-0347 § 5.2");
|
||||
}
|
||||
if (this.type == Type.str && this.value.length() > 128) {
|
||||
throw new IllegalArgumentException("Meta Tag string values must not be longer then 128 characters (XEP-0347 § 5.2");
|
||||
}
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XmlStringBuilder toXML() {
|
||||
XmlStringBuilder xml = new XmlStringBuilder(this);
|
||||
xml.attribute("name", name);
|
||||
xml.attribute("value", value);
|
||||
xml.closeEmptyElement();
|
||||
return xml;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getElementName() {
|
||||
return getType().toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name + '(' + type + "):" + value;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Smack's API for XMPP IoT.
|
||||
*/
|
||||
package org.jivesoftware.smackx.iot.discovery.element;
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Smack's API for XMPP IoT XEP-0347 Discovery. See {@link org.jivesoftware.smackx.iot.discovery.IoTDiscoveryManager}.
|
||||
*/
|
||||
package org.jivesoftware.smackx.iot.discovery;
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.discovery.provider;
|
||||
|
||||
import org.jivesoftware.smack.provider.IQProvider;
|
||||
import org.jivesoftware.smack.util.ParserUtils;
|
||||
import org.jivesoftware.smackx.iot.discovery.element.IoTClaimed;
|
||||
import org.jivesoftware.smackx.iot.element.NodeInfo;
|
||||
import org.jivesoftware.smackx.iot.parser.NodeInfoParser;
|
||||
import org.jxmpp.jid.Jid;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
public class IoTClaimedProvider extends IQProvider<IoTClaimed> {
|
||||
|
||||
@Override
|
||||
public IoTClaimed parse(XmlPullParser parser, int initialDepth) throws Exception {
|
||||
Jid jid = ParserUtils.getJidAttribute(parser);
|
||||
NodeInfo nodeInfo = NodeInfoParser.parse(parser);
|
||||
return new IoTClaimed(jid, nodeInfo);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.discovery.provider;
|
||||
|
||||
import org.jivesoftware.smack.provider.IQProvider;
|
||||
import org.jivesoftware.smack.util.ParserUtils;
|
||||
import org.jivesoftware.smackx.iot.discovery.element.IoTDisown;
|
||||
import org.jivesoftware.smackx.iot.element.NodeInfo;
|
||||
import org.jivesoftware.smackx.iot.parser.NodeInfoParser;
|
||||
import org.jxmpp.jid.Jid;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
public class IoTDisownProvider extends IQProvider<IoTDisown> {
|
||||
|
||||
@Override
|
||||
public IoTDisown parse(XmlPullParser parser, int initialDepth) throws Exception {
|
||||
Jid jid = ParserUtils.getJidAttribute(parser);
|
||||
NodeInfo nodeInfo = NodeInfoParser.parse(parser);
|
||||
return new IoTDisown(jid, nodeInfo);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.discovery.provider;
|
||||
|
||||
import org.jivesoftware.smack.provider.IQProvider;
|
||||
import org.jivesoftware.smackx.iot.discovery.element.IoTDisowned;
|
||||
import org.jivesoftware.smackx.iot.element.NodeInfo;
|
||||
import org.jivesoftware.smackx.iot.parser.NodeInfoParser;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
public class IoTDisownedProvider extends IQProvider<IoTDisowned> {
|
||||
|
||||
@Override
|
||||
public IoTDisowned parse(XmlPullParser parser, int initialDepth) throws Exception {
|
||||
NodeInfo nodeInfo = NodeInfoParser.parse(parser);
|
||||
return new IoTDisowned(nodeInfo);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.discovery.provider;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.jivesoftware.smack.provider.IQProvider;
|
||||
import org.jivesoftware.smack.util.ParserUtils;
|
||||
import org.jivesoftware.smackx.iot.discovery.element.IoTRegister;
|
||||
import org.jivesoftware.smackx.iot.discovery.element.Tag;
|
||||
import org.jivesoftware.smackx.iot.element.NodeInfo;
|
||||
import org.jivesoftware.smackx.iot.parser.NodeInfoParser;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
public class IoTRegisterProvider extends IQProvider<IoTRegister> {
|
||||
|
||||
@Override
|
||||
public IoTRegister parse(XmlPullParser parser, int initialDepth) throws Exception {
|
||||
boolean selfOwned = ParserUtils.getBooleanAttribute(parser, "selfOwned", false);
|
||||
NodeInfo nodeInfo = NodeInfoParser.parse(parser);
|
||||
List<Tag> tags = new ArrayList<>();
|
||||
while (parser.getDepth() != initialDepth) {
|
||||
int event = parser.next();
|
||||
if (event != XmlPullParser.START_TAG) {
|
||||
continue;
|
||||
}
|
||||
final String element = parser.getName();
|
||||
Tag.Type type = null;
|
||||
switch (element) {
|
||||
case "str":
|
||||
type = Tag.Type.str;
|
||||
break;
|
||||
case "num":
|
||||
type = Tag.Type.num;
|
||||
break;
|
||||
}
|
||||
if (type == null) {
|
||||
continue;
|
||||
}
|
||||
String name = parser.getAttributeValue(null, "name");
|
||||
String value = parser.getAttributeValue(null, "value");
|
||||
tags.add(new Tag(name, type, value));
|
||||
}
|
||||
return new IoTRegister(tags, nodeInfo, selfOwned);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.discovery.provider;
|
||||
|
||||
import org.jivesoftware.smack.SmackException;
|
||||
import org.jivesoftware.smack.provider.IQProvider;
|
||||
import org.jivesoftware.smack.util.ParserUtils;
|
||||
import org.jivesoftware.smackx.iot.discovery.element.IoTRemove;
|
||||
import org.jivesoftware.smackx.iot.element.NodeInfo;
|
||||
import org.jivesoftware.smackx.iot.parser.NodeInfoParser;
|
||||
import org.jxmpp.jid.BareJid;
|
||||
import org.jxmpp.jid.Jid;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
public class IoTRemoveProvider extends IQProvider<IoTRemove> {
|
||||
|
||||
@Override
|
||||
public IoTRemove parse(XmlPullParser parser, int initialDepth) throws Exception {
|
||||
Jid jid = ParserUtils.getJidAttribute(parser);
|
||||
if (jid.hasResource()) {
|
||||
throw new SmackException("JID must be without resourcepart");
|
||||
}
|
||||
BareJid bareJid = jid.asBareJid();
|
||||
NodeInfo nodeInfo = NodeInfoParser.parse(parser);
|
||||
return new IoTRemove(bareJid, nodeInfo);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.discovery.provider;
|
||||
|
||||
import org.jivesoftware.smack.provider.IQProvider;
|
||||
import org.jivesoftware.smackx.iot.discovery.element.IoTRemoved;
|
||||
import org.jivesoftware.smackx.iot.element.NodeInfo;
|
||||
import org.jivesoftware.smackx.iot.parser.NodeInfoParser;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
public class IoTRemovedProvider extends IQProvider<IoTRemoved> {
|
||||
|
||||
@Override
|
||||
public IoTRemoved parse(XmlPullParser parser, int initialDepth) throws Exception {
|
||||
NodeInfo nodeInfo = NodeInfoParser.parse(parser);
|
||||
return new IoTRemoved(nodeInfo);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.discovery.provider;
|
||||
|
||||
import org.jivesoftware.smack.provider.IQProvider;
|
||||
import org.jivesoftware.smackx.iot.discovery.element.IoTUnregister;
|
||||
import org.jivesoftware.smackx.iot.element.NodeInfo;
|
||||
import org.jivesoftware.smackx.iot.parser.NodeInfoParser;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
public class IoTUnregisterProvider extends IQProvider<IoTUnregister> {
|
||||
|
||||
@Override
|
||||
public IoTUnregister parse(XmlPullParser parser, int initialDepth) throws Exception {
|
||||
NodeInfo nodeInfo = NodeInfoParser.parse(parser);
|
||||
return new IoTUnregister(nodeInfo);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Smack's API for XMPP IoT.
|
||||
*/
|
||||
package org.jivesoftware.smackx.iot.discovery.provider;
|
|
@ -0,0 +1,105 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.element;
|
||||
|
||||
import org.jivesoftware.smack.util.StringUtils;
|
||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||
|
||||
public final class NodeInfo {
|
||||
|
||||
public static final NodeInfo EMPTY = new NodeInfo();
|
||||
|
||||
private final String nodeId;
|
||||
private final String sourceId;
|
||||
private final String cacheType;
|
||||
|
||||
/**
|
||||
* The internal constructor for the {@link EMPTY} node info marker class.
|
||||
*/
|
||||
private NodeInfo() {
|
||||
this.nodeId = null;
|
||||
this.sourceId = null;
|
||||
this.cacheType = null;
|
||||
}
|
||||
|
||||
public NodeInfo(String nodeId, String sourceId, String cacheType) {
|
||||
this.nodeId = StringUtils.requireNotNullOrEmpty(nodeId, "Node ID must not be null or empty");
|
||||
this.sourceId = sourceId;
|
||||
this.cacheType = cacheType;
|
||||
}
|
||||
|
||||
public String getNodeId() {
|
||||
return nodeId;
|
||||
}
|
||||
|
||||
public String getSourceId() {
|
||||
return sourceId;
|
||||
}
|
||||
|
||||
public String getCacheType() {
|
||||
return cacheType;
|
||||
}
|
||||
|
||||
public void appendTo(XmlStringBuilder xml) {
|
||||
if (nodeId == null) {
|
||||
return;
|
||||
}
|
||||
xml.attribute("nodeId", nodeId).optAttribute("sourceId", sourceId).optAttribute("cacheType", cacheType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
if (this == EMPTY) {
|
||||
return 0;
|
||||
}
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + nodeId.hashCode();
|
||||
result = prime * result + ((sourceId == null) ? 0 : sourceId.hashCode());
|
||||
result = prime * result + ((cacheType == null) ? 0 : cacheType.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (other == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(other instanceof NodeInfo)) {
|
||||
return false;
|
||||
}
|
||||
NodeInfo otherNodeInfo = (NodeInfo) other;
|
||||
if (!nodeId.equals(otherNodeInfo.nodeId)) {
|
||||
return false;
|
||||
}
|
||||
if (StringUtils.nullSafeCharSequenceEquals(sourceId, otherNodeInfo.sourceId)
|
||||
&& StringUtils.nullSafeCharSequenceEquals(cacheType, otherNodeInfo.cacheType)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// public static void eventuallyAppend(NodeInfo nodeInfo, XmlStringBuilder xml) {
|
||||
// if (nodeInfo == null)
|
||||
// return;
|
||||
//
|
||||
// nodeInfo.appendTo(xml);
|
||||
// }
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Smack's API for XMPP IoT.
|
||||
*/
|
||||
package org.jivesoftware.smackx.iot.element;
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Smack's API for XMPP IoT.
|
||||
*/
|
||||
package org.jivesoftware.smackx.iot;
|
|
@ -0,0 +1,35 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.parser;
|
||||
|
||||
import org.jivesoftware.smackx.iot.element.NodeInfo;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
import static org.jivesoftware.smack.util.StringUtils.isNullOrEmpty;
|
||||
|
||||
public class NodeInfoParser {
|
||||
|
||||
public static NodeInfo parse(XmlPullParser parser) {
|
||||
String nodeId = parser.getAttributeValue(null, "nodeId");
|
||||
String sourceId = parser.getAttributeValue(null, "sourceId");
|
||||
String cacheType = parser.getAttributeValue(null, "cacheType");
|
||||
if (isNullOrEmpty(nodeId) && isNullOrEmpty(sourceId) && isNullOrEmpty(cacheType)) {
|
||||
return NodeInfo.EMPTY;
|
||||
}
|
||||
return new NodeInfo(nodeId, sourceId, cacheType);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Smack's API for XMPP IoT.
|
||||
*/
|
||||
package org.jivesoftware.smackx.iot.parser;
|
|
@ -0,0 +1,319 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.provisioning;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.jivesoftware.smack.ConnectionCreationListener;
|
||||
import org.jivesoftware.smack.Manager;
|
||||
import org.jivesoftware.smack.SmackException.NoResponseException;
|
||||
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
||||
import org.jivesoftware.smack.StanzaListener;
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
import org.jivesoftware.smack.XMPPConnectionRegistry;
|
||||
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
|
||||
import org.jivesoftware.smack.filter.AndFilter;
|
||||
import org.jivesoftware.smack.filter.StanzaExtensionFilter;
|
||||
import org.jivesoftware.smack.filter.StanzaFilter;
|
||||
import org.jivesoftware.smack.filter.StanzaTypeFilter;
|
||||
import org.jivesoftware.smack.iqrequest.AbstractIqRequestHandler;
|
||||
import org.jivesoftware.smack.iqrequest.IQRequestHandler.Mode;
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
import org.jivesoftware.smack.packet.IQ.Type;
|
||||
import org.jivesoftware.smack.packet.Message;
|
||||
import org.jivesoftware.smack.packet.Presence;
|
||||
import org.jivesoftware.smack.packet.Stanza;
|
||||
import org.jivesoftware.smack.roster.Roster;
|
||||
import org.jivesoftware.smack.roster.RosterEntry;
|
||||
import org.jivesoftware.smack.roster.SubscribeListener;
|
||||
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
|
||||
import org.jivesoftware.smackx.disco.packet.DiscoverInfo;
|
||||
import org.jivesoftware.smackx.iot.discovery.IoTDiscoveryManager;
|
||||
import org.jivesoftware.smackx.iot.provisioning.element.ClearCache;
|
||||
import org.jivesoftware.smackx.iot.provisioning.element.ClearCacheResponse;
|
||||
import org.jivesoftware.smackx.iot.provisioning.element.Constants;
|
||||
import org.jivesoftware.smackx.iot.provisioning.element.IoTIsFriend;
|
||||
import org.jivesoftware.smackx.iot.provisioning.element.IoTIsFriendResponse;
|
||||
import org.jivesoftware.smackx.iot.provisioning.element.Unfriend;
|
||||
import org.jxmpp.jid.BareJid;
|
||||
import org.jxmpp.jid.DomainBareJid;
|
||||
import org.jxmpp.jid.Jid;
|
||||
import org.jxmpp.util.cache.LruCache;
|
||||
|
||||
/**
|
||||
* A manager for XEP-0324: Internet of Things - Provisioning.
|
||||
*
|
||||
* @author Florian Schmaus {@literal <flo@geekplace.eu>}
|
||||
* @see <a href="http://xmpp.org/extensions/xep-0324.html">XEP-0324: Internet of Things - Provisioning</a>
|
||||
*/
|
||||
public final class IoTProvisioningManager extends Manager {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(IoTProvisioningManager.class.getName());
|
||||
|
||||
private static final StanzaFilter UNFRIEND_MESSAGE = new AndFilter(StanzaTypeFilter.MESSAGE,
|
||||
new StanzaExtensionFilter(Unfriend.ELEMENT, Unfriend.NAMESPACE));
|
||||
|
||||
private static final Map<XMPPConnection, IoTProvisioningManager> INSTANCES = new WeakHashMap<>();
|
||||
|
||||
// Ensure a IoTProvisioningManager exists for every connection.
|
||||
static {
|
||||
XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() {
|
||||
public void connectionCreated(XMPPConnection connection) {
|
||||
getInstanceFor(connection);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the manger instance responsible for the given connection.
|
||||
*
|
||||
* @param connection the XMPP connection.
|
||||
* @return a manager instance.
|
||||
*/
|
||||
public static synchronized IoTProvisioningManager getInstanceFor(XMPPConnection connection) {
|
||||
IoTProvisioningManager manager = INSTANCES.get(connection);
|
||||
if (manager == null) {
|
||||
manager = new IoTProvisioningManager(connection);
|
||||
INSTANCES.put(connection, manager);
|
||||
}
|
||||
return manager;
|
||||
}
|
||||
|
||||
private final Roster roster;
|
||||
private final LruCache<Jid, LruCache<BareJid, Void>> negativeFriendshipRequestCache = new LruCache<>(8);
|
||||
|
||||
private Jid configuredProvisioningServer;
|
||||
|
||||
private IoTProvisioningManager(XMPPConnection connection) {
|
||||
super(connection);
|
||||
|
||||
// Stanza listener for XEP-0324 § 3.2.3.
|
||||
connection.addAsyncStanzaListener(new StanzaListener() {
|
||||
@Override
|
||||
public void processPacket(Stanza stanza) throws NotConnectedException, InterruptedException {
|
||||
if (!isFromProvisioningService(stanza)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Message message = (Message) stanza;
|
||||
Unfriend unfriend = Unfriend.from(message);
|
||||
BareJid unfriendJid = unfriend.getJid();
|
||||
final XMPPConnection connection = connection();
|
||||
Roster roster = Roster.getInstanceFor(connection);
|
||||
if (!roster.isSubscribedToMyPresence(unfriendJid)) {
|
||||
LOGGER.warning("Ignoring <unfriend/> request '" + stanza + "' because " + unfriendJid
|
||||
+ " is already not subscribed to our presence.");
|
||||
return;
|
||||
}
|
||||
Presence unsubscribed = new Presence(Presence.Type.unsubscribed);
|
||||
unsubscribed.setTo(unfriendJid);
|
||||
connection.sendStanza(unsubscribed);
|
||||
}
|
||||
}, UNFRIEND_MESSAGE);
|
||||
|
||||
connection.registerIQRequestHandler(
|
||||
new AbstractIqRequestHandler(ClearCache.ELEMENT, ClearCache.NAMESPACE, Type.set, Mode.async) {
|
||||
@Override
|
||||
public IQ handleIQRequest(IQ iqRequest) {
|
||||
if (!isFromProvisioningService(iqRequest)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ClearCache clearCache = (ClearCache) iqRequest;
|
||||
|
||||
// Handle <clearCache/> request.
|
||||
Jid from = iqRequest.getFrom();
|
||||
LruCache<BareJid, Void> cache = negativeFriendshipRequestCache.get(from);
|
||||
if (cache != null) {
|
||||
cache.clear();
|
||||
}
|
||||
|
||||
return new ClearCacheResponse(clearCache);
|
||||
}
|
||||
});
|
||||
|
||||
roster = Roster.getInstanceFor(connection);
|
||||
roster.setSubscribeListener(new SubscribeListener() {
|
||||
@Override
|
||||
public SubscribeAnswer processSubscribe(Jid from, Presence subscribeRequest) {
|
||||
// First check if the subscription request comes from a known registry and accept the request if so.
|
||||
try {
|
||||
if (IoTDiscoveryManager.getInstanceFor(connection()).isRegistry(from.asBareJid())) {
|
||||
return SubscribeAnswer.Approve;
|
||||
}
|
||||
}
|
||||
catch (NoResponseException | XMPPErrorException | NotConnectedException | InterruptedException e) {
|
||||
LOGGER.log(Level.WARNING, "Could not determine if " + from + " is a registry", e);
|
||||
}
|
||||
|
||||
Jid provisioningServer = null;
|
||||
try {
|
||||
provisioningServer = getConfiguredProvisioningServer();
|
||||
}
|
||||
catch (NoResponseException | XMPPErrorException | NotConnectedException | InterruptedException e) {
|
||||
LOGGER.log(Level.WARNING,
|
||||
"Could not determine privisioning server. Ignoring friend request from " + from, e);
|
||||
}
|
||||
if (provisioningServer == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
boolean isFriend;
|
||||
try {
|
||||
isFriend = isFriend(provisioningServer, from.asBareJid());
|
||||
}
|
||||
catch (NoResponseException | XMPPErrorException | NotConnectedException | InterruptedException e) {
|
||||
LOGGER.log(Level.WARNING, "Could not determine if " + from + " is a friend.", e);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isFriend) {
|
||||
return SubscribeAnswer.Approve;
|
||||
}
|
||||
else {
|
||||
return SubscribeAnswer.Deny;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the configured provisioning server. Use <code>null</code> as provisioningServer to use
|
||||
* automatic discovery of the provisioning server (the default behavior).
|
||||
*
|
||||
* @param provisioningServer
|
||||
*/
|
||||
public void setConfiguredProvisioningServer(Jid provisioningServer) {
|
||||
this.configuredProvisioningServer = provisioningServer;
|
||||
}
|
||||
|
||||
public Jid getConfiguredProvisioningServer()
|
||||
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||
if (configuredProvisioningServer == null) {
|
||||
configuredProvisioningServer = findProvisioningServerComponent();
|
||||
}
|
||||
return configuredProvisioningServer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to find a provisioning server component.
|
||||
*
|
||||
* @return the XMPP address of the provisioning server component if one was found.
|
||||
* @throws NoResponseException
|
||||
* @throws XMPPErrorException
|
||||
* @throws NotConnectedException
|
||||
* @throws InterruptedException
|
||||
* @see <a href="http://xmpp.org/extensions/xep-0324.html#servercomponent">XEP-0324 § 3.1.2 Provisioning Server as a server component</a>
|
||||
*/
|
||||
public DomainBareJid findProvisioningServerComponent() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||
final XMPPConnection connection = connection();
|
||||
ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection);
|
||||
List<DiscoverInfo> discoverInfos = sdm.findServicesDiscoverInfo(Constants.IOT_PROVISIONING_NAMESPACE, true, true);
|
||||
if (discoverInfos.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
Jid jid = discoverInfos.get(0).getFrom();
|
||||
assert (jid.isDomainBareJid());
|
||||
return jid.asDomainBareJid();
|
||||
}
|
||||
|
||||
/**
|
||||
* As the given provisioning server is the given JID is a friend.
|
||||
*
|
||||
* @param provisioningServer the provisioning server to ask.
|
||||
* @param friendInQuestion the JID to ask about.
|
||||
* @return <code>true</code> if the JID is a friend, <code>false</code> otherwise.
|
||||
* @throws NoResponseException
|
||||
* @throws XMPPErrorException
|
||||
* @throws NotConnectedException
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public boolean isFriend(Jid provisioningServer, BareJid friendInQuestion) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
|
||||
LruCache<BareJid, Void> cache = negativeFriendshipRequestCache.get(provisioningServer);
|
||||
if (cache != null && cache.containsKey(friendInQuestion)) {
|
||||
// We hit a cached negative isFriend response for this provisioning server.
|
||||
return false;
|
||||
}
|
||||
|
||||
IoTIsFriend iotIsFriend = new IoTIsFriend(friendInQuestion);
|
||||
iotIsFriend.setTo(provisioningServer);
|
||||
IoTIsFriendResponse response = connection().createPacketCollectorAndSend(iotIsFriend).nextResultOrThrow();
|
||||
assert (response.getJid().equals(friendInQuestion));
|
||||
boolean isFriend = response.getIsFriendResult();
|
||||
if (!isFriend) {
|
||||
// Cache the negative is friend response.
|
||||
if (cache == null) {
|
||||
cache = new LruCache<>(1024);
|
||||
negativeFriendshipRequestCache.put(provisioningServer, cache);
|
||||
}
|
||||
cache.put(friendInQuestion, null);
|
||||
}
|
||||
return isFriend;
|
||||
}
|
||||
|
||||
public void sendFriendshipRequest(BareJid bareJid) throws NotConnectedException, InterruptedException {
|
||||
Presence presence = new Presence(Presence.Type.subscribe);
|
||||
presence.setTo(bareJid);
|
||||
connection().sendStanza(presence);
|
||||
}
|
||||
|
||||
public void sendFriendshipRequestIfRequired(BareJid jid) throws NotConnectedException, InterruptedException {
|
||||
RosterEntry entry = roster.getEntry(jid);
|
||||
if (entry != null && entry.canSeeHisPresence()) {
|
||||
return;
|
||||
}
|
||||
sendFriendshipRequest(jid);
|
||||
}
|
||||
|
||||
public boolean isBefriended(Jid friendInQuestion) {
|
||||
return roster.isSubscribedToMyPresence(friendInQuestion);
|
||||
}
|
||||
|
||||
public void unfriend(Jid friend) throws NotConnectedException, InterruptedException {
|
||||
if (isBefriended(friend)) {
|
||||
Presence presence = new Presence(Presence.Type.unsubscribed);
|
||||
presence.setTo(friend);
|
||||
connection().sendStanza(presence);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isFromProvisioningService(Stanza stanza) {
|
||||
Jid provisioningServer;
|
||||
try {
|
||||
provisioningServer = getConfiguredProvisioningServer();
|
||||
}
|
||||
catch (NotConnectedException | InterruptedException | NoResponseException | XMPPErrorException e) {
|
||||
LOGGER.log(Level.WARNING, "Could determine provisioning server", e);
|
||||
return false;
|
||||
}
|
||||
if (provisioningServer == null) {
|
||||
LOGGER.warning("Ignoring request '" + stanza
|
||||
+ "' because no provisioning server configured.");
|
||||
return false;
|
||||
}
|
||||
if (!provisioningServer.equals(stanza.getFrom())) {
|
||||
LOGGER.warning("Ignoring request '" + stanza + "' because not from provising server '"
|
||||
+ provisioningServer + "'.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.provisioning.element;
|
||||
|
||||
import org.jivesoftware.smack.packet.SimpleIQ;
|
||||
|
||||
public class ClearCache extends SimpleIQ {
|
||||
|
||||
public static final String ELEMENT = "clearCache";
|
||||
public static final String NAMESPACE = Constants.IOT_PROVISIONING_NAMESPACE;
|
||||
|
||||
public ClearCache() {
|
||||
super(ELEMENT, NAMESPACE);
|
||||
// <clearCache/> IQs are always of type 'get' (XEP-0324 § 3.5.1, see also the XEPs history remarks)
|
||||
setType(Type.get);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.provisioning.element;
|
||||
|
||||
import org.jivesoftware.smack.packet.SimpleIQ;
|
||||
|
||||
public class ClearCacheResponse extends SimpleIQ {
|
||||
|
||||
public static final String ELEMENT = "clearCacheResponse";
|
||||
public static final String NAMESPACE = Constants.IOT_PROVISIONING_NAMESPACE;
|
||||
|
||||
public ClearCacheResponse() {
|
||||
super(ELEMENT, NAMESPACE);
|
||||
// <clearCacheResponse/> IQs are always of type 'result' (XEP-0324 § 3.5.1, see also the XEPs history remarks)
|
||||
setType(Type.result);
|
||||
}
|
||||
|
||||
public ClearCacheResponse(ClearCache clearCacheRequest) {
|
||||
this();
|
||||
setStanzaId(clearCacheRequest.getStanzaId());
|
||||
setTo(clearCacheRequest.getFrom());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.provisioning.element;
|
||||
|
||||
public class Constants {
|
||||
|
||||
public static final String IOT_PROVISIONING_NAMESPACE = "urn:xmpp:iot:provisioning";
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.provisioning.element;
|
||||
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
import org.jxmpp.jid.Jid;
|
||||
|
||||
public class IoTIsFriend extends IQ {
|
||||
|
||||
public static final String ELEMENT = "isFriend";
|
||||
public static final String NAMESPACE = Constants.IOT_PROVISIONING_NAMESPACE;
|
||||
|
||||
private final Jid jid;
|
||||
|
||||
public IoTIsFriend(Jid jid) {
|
||||
super(ELEMENT, NAMESPACE);
|
||||
this.jid = jid;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) {
|
||||
xml.attribute("jid", jid);
|
||||
xml.setEmptyElement();
|
||||
return xml;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.provisioning.element;
|
||||
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
import org.jxmpp.jid.BareJid;
|
||||
|
||||
public class IoTIsFriendResponse extends IQ {
|
||||
|
||||
public static final String ELEMENT = "isFriend";
|
||||
public static final String NAMESPACE = Constants.IOT_PROVISIONING_NAMESPACE;
|
||||
|
||||
private final BareJid jid;
|
||||
|
||||
private final boolean result;
|
||||
|
||||
public IoTIsFriendResponse(BareJid jid, boolean result) {
|
||||
super(ELEMENT, NAMESPACE);
|
||||
this.jid = jid;
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
public BareJid getJid() {
|
||||
return jid;
|
||||
}
|
||||
|
||||
public boolean getIsFriendResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) {
|
||||
xml.attribute("jid", jid);
|
||||
xml.attribute("result", result);
|
||||
return xml;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.provisioning.element;
|
||||
|
||||
import org.jivesoftware.smack.packet.ExtensionElement;
|
||||
import org.jivesoftware.smack.packet.Message;
|
||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||
import org.jxmpp.jid.BareJid;
|
||||
|
||||
public class Unfriend implements ExtensionElement {
|
||||
public static final String ELEMENT = "UNFRIEND";
|
||||
public static final String NAMESPACE = Constants.IOT_PROVISIONING_NAMESPACE;
|
||||
|
||||
private final BareJid jid;
|
||||
|
||||
public Unfriend(BareJid jid) {
|
||||
this.jid = jid;
|
||||
}
|
||||
|
||||
public BareJid getJid() {
|
||||
return jid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getElementName() {
|
||||
return ELEMENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNamespace() {
|
||||
return NAMESPACE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XmlStringBuilder toXML() {
|
||||
XmlStringBuilder xml = new XmlStringBuilder(this);
|
||||
xml.attribute("jid", jid);
|
||||
xml.closeEmptyElement();
|
||||
return xml;
|
||||
}
|
||||
|
||||
public static Unfriend from(Message message) {
|
||||
return message.getExtension(ELEMENT, NAMESPACE);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Smack's API for XMPP IoT.
|
||||
*/
|
||||
package org.jivesoftware.smackx.iot.provisioning.element;
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Smack's API for XMPP IoT.
|
||||
*/
|
||||
package org.jivesoftware.smackx.iot.provisioning;
|
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.provisioning.provider;
|
||||
|
||||
import org.jivesoftware.smack.provider.IQProvider;
|
||||
|
||||
import org.jivesoftware.smackx.iot.provisioning.element.ClearCache;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
public class ClearCacheProvider extends IQProvider<ClearCache> {
|
||||
|
||||
@Override
|
||||
public ClearCache parse(XmlPullParser parser, int initialDepth) throws Exception {
|
||||
return new ClearCache();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.provisioning.provider;
|
||||
|
||||
import org.jivesoftware.smack.provider.IQProvider;
|
||||
|
||||
import org.jivesoftware.smackx.iot.provisioning.element.ClearCacheResponse;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
public class ClearCacheResponseProvider extends IQProvider<ClearCacheResponse> {
|
||||
|
||||
@Override
|
||||
public ClearCacheResponse parse(XmlPullParser parser, int initialDepth) throws Exception {
|
||||
return new ClearCacheResponse();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.provisioning.provider;
|
||||
|
||||
import org.jivesoftware.smack.provider.IQProvider;
|
||||
|
||||
import org.jivesoftware.smack.util.ParserUtils;
|
||||
import org.jivesoftware.smackx.iot.provisioning.element.IoTIsFriend;
|
||||
import org.jxmpp.jid.Jid;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
public class IoTIsFriendProvider extends IQProvider<IoTIsFriend> {
|
||||
|
||||
@Override
|
||||
public IoTIsFriend parse(XmlPullParser parser, int initialDepth) throws Exception {
|
||||
Jid jid = ParserUtils.getJidAttribute(parser);
|
||||
return new IoTIsFriend(jid);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.provisioning.provider;
|
||||
|
||||
import org.jivesoftware.smack.provider.IQProvider;
|
||||
import org.jivesoftware.smack.util.ParserUtils;
|
||||
import org.jivesoftware.smackx.iot.provisioning.element.IoTIsFriendResponse;
|
||||
import org.jxmpp.jid.BareJid;
|
||||
import org.jxmpp.jid.Jid;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
public class IoTIsFriendResponseProvider extends IQProvider<IoTIsFriendResponse> {
|
||||
|
||||
@Override
|
||||
public IoTIsFriendResponse parse(XmlPullParser parser, int initialDepth) throws Exception {
|
||||
Jid jid = ParserUtils.getJidAttribute(parser);
|
||||
BareJid bareJid = jid.asBareJid();
|
||||
boolean result = ParserUtils.getBooleanAttribute(parser, "result");
|
||||
|
||||
return new IoTIsFriendResponse(bareJid, result);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
*
|
||||
* 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.jivesoftware.smackx.iot.provisioning.provider;
|
||||
|
||||
import org.jivesoftware.smack.provider.ExtensionElementProvider;
|
||||
import org.jivesoftware.smack.util.ParserUtils;
|
||||
import org.jivesoftware.smackx.iot.provisioning.element.Unfriend;
|
||||
import org.jxmpp.jid.BareJid;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
public class UnfriendProvider extends ExtensionElementProvider<Unfriend> {
|
||||
|
||||
@Override
|
||||
public Unfriend parse(XmlPullParser parser, int initialDepth) throws Exception {
|
||||
BareJid jid = ParserUtils.getBareJidAttribute(parser);
|
||||
return new Unfriend(jid);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Smack's API for XMPP IoT.
|
||||
*/
|
||||
package org.jivesoftware.smackx.iot.provisioning.provider;
|
|
@ -52,4 +52,97 @@
|
|||
<className>org.jivesoftware.smackx.gcm.provider.GcmExtensionProvider</className>
|
||||
</extensionProvider>
|
||||
|
||||
<!-- XEP-0347: Internet of Things - Discovery -->
|
||||
<iqProvider>
|
||||
<elementName>register</elementName>
|
||||
<namespace>urn:xmpp:iot:discovery</namespace>
|
||||
<className>org.jivesoftware.smackx.iot.discovery.provider.IoTRegisterProvider</className>
|
||||
</iqProvider>
|
||||
<iqProvider>
|
||||
<elementName>claimed</elementName>
|
||||
<namespace>urn:xmpp:iot:discovery</namespace>
|
||||
<className>org.jivesoftware.smackx.iot.discovery.provider.IoTClaimedProvider</className>
|
||||
</iqProvider>
|
||||
<iqProvider>
|
||||
<elementName>disown</elementName>
|
||||
<namespace>urn:xmpp:iot:discovery</namespace>
|
||||
<className>org.jivesoftware.smackx.iot.discovery.provider.IoTDisownProvider</className>
|
||||
</iqProvider>
|
||||
<iqProvider>
|
||||
<elementName>disowned</elementName>
|
||||
<namespace>urn:xmpp:iot:discovery</namespace>
|
||||
<className>org.jivesoftware.smackx.iot.discovery.provider.IoTDisownedProvider</className>
|
||||
</iqProvider>
|
||||
<iqProvider>
|
||||
<elementName>remove</elementName>
|
||||
<namespace>urn:xmpp:iot:discovery</namespace>
|
||||
<className>org.jivesoftware.smackx.iot.discovery.provider.IoTRemoveProvider</className>
|
||||
</iqProvider>
|
||||
<iqProvider>
|
||||
<elementName>disown</elementName>
|
||||
<namespace>urn:xmpp:iot:discovery</namespace>
|
||||
<className>org.jivesoftware.smackx.iot.discovery.provider.IoTRemovedProvider</className>
|
||||
</iqProvider>
|
||||
<iqProvider>
|
||||
<elementName>unregister</elementName>
|
||||
<namespace>urn:xmpp:iot:discovery</namespace>
|
||||
<className>org.jivesoftware.smackx.iot.discovery.provider.IoTUnregisterProvider</className>
|
||||
</iqProvider>
|
||||
|
||||
<!-- XEP-0324: Internet of Things - Provisioning -->
|
||||
<iqProvider>
|
||||
<elementName>isFriend</elementName>
|
||||
<namespace>urn:xmpp:iot:provisioning</namespace>
|
||||
<className>org.jivesoftware.smackx.iot.provisioning.provider.IoTIsFriendProvider</className>
|
||||
</iqProvider>
|
||||
<iqProvider>
|
||||
<elementName>isFriendResponse</elementName>
|
||||
<namespace>urn:xmpp:iot:provisioning</namespace>
|
||||
<className>org.jivesoftware.smackx.iot.provisioning.provider.IoTIsFriendResponseProvider</className>
|
||||
</iqProvider>
|
||||
<iqProvider>
|
||||
<elementName>clearCache</elementName>
|
||||
<namespace>urn:xmpp:iot:provisioning</namespace>
|
||||
<className>org.jivesoftware.smackx.iot.provisioning.provider.ClearCacheProvider</className>
|
||||
</iqProvider>
|
||||
<iqProvider>
|
||||
<elementName>clearCacheResponse</elementName>
|
||||
<namespace>urn:xmpp:iot:provisioning</namespace>
|
||||
<className>org.jivesoftware.smackx.iot.provisioning.provider.ClearCacheResponseProvider</className>
|
||||
</iqProvider>
|
||||
<extensionProvider>
|
||||
<elementName>unfriend</elementName>
|
||||
<namespace>urn:xmpp:iot:provisioning</namespace>
|
||||
<className>org.jivesoftware.smackx.iot.provisioning.provider.UnfriendProvider</className>
|
||||
</extensionProvider>
|
||||
|
||||
<!-- XEP-0323: Internet of Things - Data -->
|
||||
<iqProvider>
|
||||
<elementName>req</elementName>
|
||||
<namespace>urn:xmpp:iot:data</namespace>
|
||||
<className>org.jivesoftware.smackx.iot.data.provider.IoTDataRequestProvider</className>
|
||||
</iqProvider>
|
||||
<iqProvider>
|
||||
<elementName>accepted</elementName>
|
||||
<namespace>urn:xmpp:iot:data</namespace>
|
||||
<className>org.jivesoftware.smackx.iot.data.provider.IoTDataReadOutAcceptedProvider</className>
|
||||
</iqProvider>
|
||||
<extensionProvider>
|
||||
<elementName>fields</elementName>
|
||||
<namespace>urn:xmpp:iot:data</namespace>
|
||||
<className>org.jivesoftware.smackx.iot.data.provider.IoTFieldsExtensionProvider</className>
|
||||
</extensionProvider>
|
||||
|
||||
<!-- XEP-0325: Internet of Things - Control -->
|
||||
<iqProvider>
|
||||
<elementName>set</elementName>
|
||||
<namespace>urn:xmpp:iot:control</namespace>
|
||||
<className>org.jivesoftware.smackx.iot.control.provider.IoTSetRequestProvider</className>
|
||||
</iqProvider>
|
||||
<iqProvider>
|
||||
<elementName>setResponse</elementName>
|
||||
<namespace>urn:xmpp:iot:control</namespace>
|
||||
<className>org.jivesoftware.smackx.iot.control.provider.IoTSetResponseProvider</className>
|
||||
</iqProvider>
|
||||
|
||||
</smackProviders>
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
<smack>
|
||||
<startupClasses>
|
||||
<className>org.jivesoftware.smackx.hoxt.HOXTManager</className>
|
||||
<className>org.jivesoftware.smackx.iot.data.IoTDataManager</className>
|
||||
<className>org.jivesoftware.smackx.iot.discovery.IoTDiscoveryManager</className>
|
||||
<className>org.jivesoftware.smackx.iot.provisioning.IoTProvisioningManager</className>
|
||||
</startupClasses>
|
||||
</smack>
|
||||
</smack>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue