2 * //******************************************************************
4 * // Copyright 2016 Samsung Electronics All Rights Reserved.
6 * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
8 * // Licensed under the Apache License, Version 2.0 (the "License");
9 * // you may not use this file except in compliance with the License.
10 * // You may obtain a copy of the License at
12 * // http://www.apache.org/licenses/LICENSE-2.0
14 * // Unless required by applicable law or agreed to in writing, software
15 * // distributed under the License is distributed on an "AS IS" BASIS,
16 * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * // See the License for the specific language governing permissions and
18 * // limitations under the License.
20 * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
22 package org.iotivity.cloud.rdserver.resources.presence;
24 import java.io.ByteArrayOutputStream;
25 import java.util.ArrayList;
26 import java.util.Arrays;
27 import java.util.HashMap;
28 import java.util.List;
30 import org.iotivity.cloud.base.device.Device;
31 import org.iotivity.cloud.base.exception.ServerException.InternalServerErrorException;
32 import org.iotivity.cloud.base.protocols.IRequest;
33 import org.iotivity.cloud.base.protocols.MessageBuilder;
34 import org.iotivity.cloud.base.protocols.enums.ContentFormat;
35 import org.iotivity.cloud.base.protocols.enums.ResponseStatus;
36 import org.iotivity.cloud.rdserver.Constants;
37 import org.iotivity.cloud.rdserver.db.DBManager;
38 import org.iotivity.cloud.util.Cbor;
39 import org.iotivity.cloud.util.Log;
41 import com.fasterxml.jackson.core.JsonEncoding;
42 import com.fasterxml.jackson.core.JsonGenerator;
43 import com.fasterxml.jackson.dataformat.cbor.CBORFactory;
44 import com.fasterxml.jackson.dataformat.cbor.CBORGenerator;
48 * This class provides a set of APIs handle requests about presence
51 public class PresenceManager {
52 private static PresenceManager mPresenceManager = new PresenceManager();
54 private Cbor<HashMap<String, Object>> mCbor = new Cbor<>();
56 private class PresenceSubscriber {
57 PresenceSubscriber(Device subscriber, IRequest request) {
58 mSubscriber = subscriber;
62 public Device mSubscriber;
63 public IRequest mRequest;
66 private class PresenceInfo {
69 mSubscriber = new HashMap<>();
70 mSubscribedDevices = new HashMap<>();
71 mSequenceNumber = new HashMap<>();
74 // di , token, Subscriber list
75 private HashMap<String, HashMap<String, PresenceSubscriber>> mSubscriber;
77 private HashMap<String, List<String>> mSubscribedDevices;
78 private HashMap<String, Long> mSequenceNumber;
81 private PresenceInfo mDevicePresence = null;
82 private PresenceInfo mResourcePresence = null;
84 private PresenceManager() {
85 mDevicePresence = new PresenceInfo();
86 mResourcePresence = new PresenceInfo();
90 * API to return PresenceManager object
92 * @return PresenceManager object
94 public static PresenceManager getInstance() {
95 return mPresenceManager;
102 * channel information
105 * @param deviceIdList
106 * subscribed device list
107 * @param presenceType
108 * device presence or resource presence
110 public void subscribePresence(Device srcDevice, IRequest request,
111 List<String> deviceIdList, String presenceType) {
113 PresenceInfo presenceInfo = getPresenceInfo(presenceType);
115 for (String deviceId : deviceIdList) {
116 HashMap<String, PresenceSubscriber> subscribers = presenceInfo.mSubscriber
119 if (subscribers == null) {
120 subscribers = new HashMap<>();
121 presenceInfo.mSubscriber.put(deviceId, subscribers);
124 subscribers.put(request.getRequestId(),
125 new PresenceSubscriber(srcDevice, request));
128 presenceInfo.mSubscribedDevices.put(request.getRequestId(),
130 presenceInfo.mSequenceNumber.put(request.getRequestId(), (long) 1);
134 * API to remove observer
138 * @param deviceIdList
139 * unsubscribed device list
140 * @param presenceType
141 * device presence or resource presence
143 public void unsubscribePresence(IRequest request, List<String> deviceIdList,
144 String presenceType) {
146 PresenceInfo presenceInfo = getPresenceInfo(presenceType);
148 for (String deviceId : deviceIdList) {
149 HashMap<String, PresenceSubscriber> subscribers = presenceInfo.mSubscriber
152 if (subscribers == null) {
156 subscribers.remove(request.getRequestId());
161 * API for notifying to observers about device presence
166 public void notifyToObservers(String deviceId) {
168 HashMap<String, PresenceSubscriber> tokenNSubscribers = mDevicePresence.mSubscriber
171 if (tokenNSubscribers != null) {
172 byte[] payload = makeResponsePayload(Arrays.asList(deviceId));
174 for (PresenceSubscriber subscriber : tokenNSubscribers.values()) {
176 subscriber.mSubscriber.sendResponse(
177 MessageBuilder.createResponse(subscriber.mRequest,
178 ResponseStatus.CONTENT,
179 ContentFormat.APPLICATION_CBOR, payload));
185 * API to make response payload about device presence
189 * @return payload data
191 public byte[] makeResponsePayload(List<String> deviceList) {
193 HashMap<String, Object> getPayload = new HashMap<>();
194 ArrayList<HashMap<String, Object>> prsList = new ArrayList<>();
196 for (String deviceId : deviceList) {
197 HashMap<String, Object> payloadSegment = new HashMap<>();
199 String deviceState = getDeviceState(deviceId);
200 if (deviceState != null) {
201 payloadSegment.put(Constants.DEVICE_ID, deviceId);
202 payloadSegment.put(Constants.PRESENCE_STATE, deviceState);
203 prsList.add(payloadSegment);
206 getPayload.put(Constants.PRESENCE_LIST, prsList);
207 Log.i("Device presence observe response : " + getPayload.toString());
209 return mCbor.encodingPayloadToCbor(getPayload);
213 private String getDeviceState(String deviceId) {
215 HashMap<String, Object> condition = new HashMap<>();
216 condition.put(Constants.DEVICE_ID, deviceId);
220 ArrayList<HashMap<String, Object>> readRecords = DBManager.getInstance()
221 .selectRecord(Constants.PRESENCE_TABLE, condition);
223 if (!readRecords.isEmpty()
224 && readRecords.get(0).get(Constants.PRESENCE_STATE) != null) {
225 state = readRecords.get(0).get(Constants.PRESENCE_STATE).toString();
231 private PresenceInfo getPresenceInfo(String presenceType) {
233 PresenceInfo presenceInfo = null;
234 switch (presenceType) {
235 case Constants.DEVICE_PRESENCE:
236 presenceInfo = mDevicePresence;
238 case Constants.RESOURCE_PRESENCE:
239 presenceInfo = mResourcePresence;
247 * API for notifying to observers about resource presence
249 * @param resourceInfo
250 * resource information
252 public void notifyToObservers(
253 ArrayList<HashMap<String, Object>> resourceInfo) {
255 if (resourceInfo.isEmpty()) {
259 Object obj = resourceInfo.get(0).get(Constants.DEVICE_ID);
265 String deviceId = obj.toString();
267 HashMap<String, PresenceSubscriber> tokenNSubscribers = mResourcePresence.mSubscriber
270 if (tokenNSubscribers != null) {
272 for (PresenceSubscriber subscriber : tokenNSubscribers.values()) {
274 for (HashMap<String, Object> resource : resourceInfo) {
275 subscriber.mSubscriber.sendResponse(
276 MessageBuilder.createResponse(subscriber.mRequest,
277 ResponseStatus.CONTENT,
278 ContentFormat.APPLICATION_CBOR,
280 subscriber.mRequest.getRequestId(),
287 private byte[] makeResponsePayload(String requestId,
288 HashMap<String, Object> resource) {
290 ByteArrayOutputStream out = new ByteArrayOutputStream();
291 CBORFactory f = new CBORFactory();
293 JsonGenerator gen = f.createGenerator(out, JsonEncoding.UTF8);
294 gen.writeStartObject();
295 long sequenceId = mResourcePresence.mSequenceNumber.get(requestId);
296 gen.writeNumberField(Constants.NON, sequenceId);
297 mResourcePresence.mSequenceNumber.put(requestId, sequenceId + 1);
298 gen.writeNumberField(Constants.RESOURCE_TTL, Long.parseLong(
299 checkPayload(resource, Constants.RESOURCE_TTL).toString()));
301 gen.writeFieldName(Constants.TRIGGER);
303 ((CBORGenerator) gen).writeRaw((byte) (224
304 + (byte) (checkPayload(resource, Constants.TRIGGER))));
306 gen.writeStringField(Constants.RESOURCE_TYPE,
307 checkPayload(resource, Constants.RESOURCE_TYPE).toString());
309 gen.writeStringField(Constants.HREF,
310 checkPayload(resource, Constants.HREF).toString());
311 gen.writeEndObject();
314 } catch (Exception e) {
315 throw new InternalServerErrorException(
316 "notification payload cbor encoding error");
319 return out.toByteArray();
322 private Object checkPayload(HashMap<String, Object> resource, String key) {
323 Object obj = resource.get(key);
326 throw new InternalServerErrorException(
327 "property (" + key + ") is null");
334 * API to update device state
337 * payload included device state
339 public void updateDevicePresence(HashMap<String, Object> payload) {
340 DBManager.getInstance().insertAndReplaceRecord(Constants.PRESENCE_TABLE,