2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 using System.Collections.Generic;
20 using System.Collections.ObjectModel;
21 using System.Runtime.InteropServices;
23 namespace Tizen.Network.IoTConnectivity
26 /// Abstract class respresenting a resource.
27 /// All resources need to inherit from this class.
29 public abstract class Resource : IDisposable
31 private IntPtr _resourceHandle = IntPtr.Zero;
32 private bool _disposed = false;
33 private ObservableCollection<Resource> _children = new ObservableCollection<Resource>();
34 private IntPtr _observerHandle = IntPtr.Zero;
40 /// @a uri format would be relative URI path like '/a/light'
41 /// and its length must be less than 128.
44 /// http://tizen.org/privilege/internet
46 /// <param name="uri">The URI path of the resource</param>
47 /// <param name="types">Resource types</param>
48 /// <param name="interfaces">Resource interfaces</param>
49 /// <param name="policy">The policies of the resoruce</param>
51 /// IoTConnectivityServerManager.Initialize() should be called to initialize
53 /// <seealso cref="ResourceTypes"/>
54 /// <seealso cref="ResourceInterfaces"/>
55 /// <seealso cref="ResourcePolicy"/>
56 /// <exception cref="NotSupportedException">Thrown when the iotcon is not supported</exception>
57 /// <exception cref="OutOfMemoryException">Thrown when there is not enough memory</exception>
58 /// <exception cref="ArgumentException">Thrown when there is an invalid parameter</exception>
60 /// // Create a class which inherits from Resource
61 /// public class DoorResource : Resource
63 /// public DoorResource(string uri, ResourceTypes types, ResourceInterfaces interfaces, ResourcePolicy policy)
64 /// : base(uri, types, interfaces, policy) {
66 /// protected override Response OnDelete(Request request) {
69 /// protected override Response OnGet(Request request) {
72 /// // Override other abstract methods of Resource class
75 /// // Use it like below
76 /// ResourceInterfaces ifaces = new ResourceInterfaces(new List<string>(){ ResourceInterfaces.DefaultInterface });
77 /// ResourceTypes types = new ResourceTypes(new List<string>(){ "oic.iot.door.new" });
78 /// Resource resource = new DoorResource("/door/uri1", types, ifaces, ResourcePolicy.Discoverable | ResourcePolicy.Observable);
80 protected Resource(string uri, ResourceTypes types, ResourceInterfaces interfaces, ResourcePolicy policy)
84 Interfaces = interfaces;
87 _children.CollectionChanged += ChildrenCollectionChanged;
89 int ret = Interop.IoTConnectivity.Server.Observers.Create(out _observerHandle);
90 if (ret != (int)IoTConnectivityError.None)
92 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to create obsever handle");
93 throw IoTConnectivityErrorFactory.GetException(ret);
98 /// Destructor of the Resource class.
106 /// Type details of the resource
108 public ResourceTypes Types { get; internal set; }
111 /// Interface details of the resource
113 public ResourceInterfaces Interfaces { get; internal set; }
116 /// The policies of the resource
118 public ResourcePolicy Policy { get; internal set; }
121 /// URI path of the resource
123 public string UriPath { get; internal set; }
126 /// List of Child resources
128 public ICollection<Resource> Children
136 internal IntPtr ResourceHandle
140 return _resourceHandle;
144 _resourceHandle = value;
149 /// Notify the specified representation and qos.
152 /// http://tizen.org/privilege/internet
154 /// <param name="representation">Representation.</param>
155 /// <param name="qos">The quality of service for message transfer.</param>
157 /// IoTConnectivityServerManager.Initialize() should be called to initialize
159 /// <seealso cref="Representation"/>
160 /// <seealso cref="QualityOfService"/>
161 /// <exception cref="NotSupportedException">Thrown when the iotcon is not supported</exception>
162 /// <exception cref="ArgumentException">Thrown when there is an invalid parameter</exception>
163 /// <exception cref="UnauthorizedAccessException">Thrown when app does not have privilege to access</exception>
164 /// <exception cref="InvalidOperationException">Thrown when the operation is invalid</exception>
166 /// ResourceInterfaces ifaces = new ResourceInterfaces(new List<string>(){ ResourceInterfaces.DefaultInterface });
167 /// ResourceTypes types = new ResourceTypes(new List<string>(){ "oic.iot.door.new.notify" });
168 /// Resource resource = new DoorResource("/door/uri/new/notify", types, ifaces, ResourcePolicy.Discoverable | ResourcePolicy.Observable);
169 /// IoTConnectivityServerManager.RegisterResource(resource);
171 /// Representation repr = new Representation();
172 /// repr.UriPath = "/door/uri/new/notify";
173 /// repr.Type = new ResourceTypes(new List<string>(){ "oic.iot.door.new.notify" });
174 /// repr.Attributes = new Attributes() {
177 /// resource.Notify(repr, QualityOfService.High);
179 public void Notify(Representation representation, QualityOfService qos)
181 int ret = (int)IoTConnectivityError.None;
182 ret = Interop.IoTConnectivity.Server.Resource.Notify(_resourceHandle, representation._representationHandle, _observerHandle, (int)qos);
183 if (ret != (int)IoTConnectivityError.None)
185 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to send notification");
186 throw IoTConnectivityErrorFactory.GetException(ret);
191 /// This is Called when the client performs get operation on this resource.
193 /// <param name="request">A request from client</param>
194 /// <returns>A response having the representation and the result</returns>
195 protected abstract Response OnGet(Request request);
198 /// This is Called when the client performs put operation on this resource.
200 /// <param name="request">A request from client</param>
201 /// <returns>A response</returns>
202 protected abstract Response OnPut(Request request);
205 /// This is Called when the client performs post operation on this resource.
207 /// <param name="request">A request from client</param>
208 /// <returns>A response having the representation and the result</returns>
209 protected abstract Response OnPost(Request request);
212 /// This is Called when the client performs delete operation on this resource.
214 /// <param name="request">A request from client</param>
215 /// <returns>A response</returns>
216 protected abstract Response OnDelete(Request request);
219 /// Called on the observing event.
221 /// <param name="request">A request from client</param>
222 /// <param name="type">Observer type</param>
223 /// <param name="observeId">Observe identifier.</param>
224 /// <returns>Returns true if it wants to be observed, else false.</returns>
225 protected abstract bool OnObserving(Request request, ObserveType type, int observeId);
228 /// Releases any unmanaged resources used by this object.
230 public void Dispose()
233 GC.SuppressFinalize(this);
237 /// Releases any unmanaged resources used by this object. Can also dispose any other disposable objects.
239 /// <param name="disposing">If true, disposes any disposable objects. If false, does not dispose disposable objects.</param>
240 protected virtual void Dispose(bool disposing)
248 Interfaces?.Dispose();
251 if (_resourceHandle != IntPtr.Zero)
252 Interop.IoTConnectivity.Server.Resource.Destroy(_resourceHandle);
253 if (_observerHandle != IntPtr.Zero)
254 Interop.IoTConnectivity.Server.Observers.Destroy(_observerHandle);
258 // This method is used as callback for Resource
259 internal void OnRequest(IntPtr resourceHandle, IntPtr requestHandle, IntPtr userData)
261 Request request = GetRequest(requestHandle);
262 Response response = null;
266 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get Request");
273 int ret = Interop.IoTConnectivity.Server.Request.GetObserveType(requestHandle, out observeType);
274 if (ret != (int)IoTConnectivityError.None)
276 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to Get observe type");
279 if ((ObserveType)observeType != ObserveType.NoType)
282 ret = Interop.IoTConnectivity.Server.Request.GetObserveId(requestHandle, out observeId);
283 if (ret != (int)IoTConnectivityError.None)
285 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to Get observe id");
288 switch ((ObserveType)observeType)
290 case ObserveType.Register:
292 if (OnObserving(request, ObserveType.Register, observeId))
294 ret = Interop.IoTConnectivity.Server.Observers.Add(_observerHandle, observeId);
295 if (ret != (int)IoTConnectivityError.None)
297 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to add observer id");
304 // If OnObserving for ObserveType.Register returns false, do not operate for Get operation after Observe operation.
308 case ObserveType.Deregister:
310 if (OnObserving(request, ObserveType.Deregister, observeId))
312 ret = Interop.IoTConnectivity.Server.Observers.Remove(_observerHandle, observeId);
313 if (ret != (int)IoTConnectivityError.None)
315 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to remove observer id");
322 // If OnObserving for ObserveType.Deregister returns false, do not operate for Get operation after Observe operation.
329 ret = Interop.IoTConnectivity.Server.Request.GetRequestType(requestHandle, out requestType);
330 if (ret != (int)IoTConnectivityError.None)
332 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to Get request type");
335 switch ((Interop.IoTConnectivity.Server.RequestType)requestType)
337 case Interop.IoTConnectivity.Server.RequestType.Put:
339 response = OnPut(request);
342 case Interop.IoTConnectivity.Server.RequestType.Get:
344 response = OnGet(request);
347 case Interop.IoTConnectivity.Server.RequestType.Post:
349 response = OnPost(request);
352 case Interop.IoTConnectivity.Server.RequestType.Delete:
354 response = OnDelete(request);
360 if (response == null)
362 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to send Response");
366 if (!response.Send(requestHandle))
368 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to send Response");
379 private Request GetRequest(IntPtr requestHandle)
381 IntPtr hostAddressPtr;
382 int ret = Interop.IoTConnectivity.Server.Request.GetHostAddress(requestHandle, out hostAddressPtr);
383 if (ret != (int)IoTConnectivityError.None)
385 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to Get host address");
389 IntPtr optionsHandle = IntPtr.Zero;
390 ret = Interop.IoTConnectivity.Server.Request.GetOptions(requestHandle, out optionsHandle);
391 if (ret != (int)IoTConnectivityError.None)
393 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to Get options");
397 IntPtr queryHandle = IntPtr.Zero;
398 ret = Interop.IoTConnectivity.Server.Request.GetQuery(requestHandle, out queryHandle);
399 if (ret != (int)IoTConnectivityError.None)
401 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to Get Query");
405 IntPtr representationHandle = IntPtr.Zero;
406 ret = Interop.IoTConnectivity.Server.Request.GetRepresentation(requestHandle, out representationHandle);
407 if (ret != (int)IoTConnectivityError.None)
409 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to Get representation");
413 ResourceOptions opts = null;
414 ResourceQuery query = null;
415 Representation representation = null;
418 opts = (optionsHandle == IntPtr.Zero) ? null : new ResourceOptions(optionsHandle);
420 catch (Exception exp)
422 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to new ResourceOptions: " + exp.Message);
428 query = (queryHandle == IntPtr.Zero) ? null : new ResourceQuery(queryHandle);
430 catch (Exception exp)
432 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to new ResourceQuery: " + exp.Message);
438 representation = (representationHandle == IntPtr.Zero) ? null : new Representation(representationHandle); ;
440 catch (Exception exp)
442 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to new Representation: " + exp.Message);
448 HostAddress = Marshal.PtrToStringAnsi(hostAddressPtr),
451 Representation = representation
455 private void ChildrenCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs eventArgs)
457 if (eventArgs.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
459 foreach (Resource r in eventArgs.NewItems)
461 int ret = Interop.IoTConnectivity.Server.Resource.BindChildResource(_resourceHandle, r._resourceHandle);
462 if (ret != (int)IoTConnectivityError.None)
464 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to bind resource ");
465 throw IoTConnectivityErrorFactory.GetException(ret);
469 else if (eventArgs.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
471 foreach (Resource r in eventArgs.NewItems)
473 int ret = Interop.IoTConnectivity.Server.Resource.UnbindChildResource(_resourceHandle, r._resourceHandle);
474 if (ret != (int)IoTConnectivityError.None)
476 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to unbind resource");
477 throw IoTConnectivityErrorFactory.GetException(ret);