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 /// <since_tizen> 3 </since_tizen>
30 public abstract class Resource : IDisposable
32 private IntPtr _resourceHandle = IntPtr.Zero;
33 private bool _disposed = false;
34 private ObservableCollection<Resource> _children = new ObservableCollection<Resource>();
35 private IntPtr _observerHandle = IntPtr.Zero;
40 /// <since_tizen> 3 </since_tizen>
42 /// @a uri format would be relative URI path like '/a/light'
43 /// and its length must be less than 128.
46 /// http://tizen.org/privilege/internet
48 /// <privlevel>public</privlevel>
49 /// <param name="uri">The URI path of the resource.</param>
50 /// <param name="types">Resource types.</param>
51 /// <param name="interfaces">Resource interfaces.</param>
52 /// <param name="policy">The policies of the resoruce.</param>
53 /// <feature>http://tizen.org/feature/iot.ocf</feature>
55 /// IoTConnectivityServerManager.Initialize() should be called to initialize.
57 /// <seealso cref="ResourceTypes"/>
58 /// <seealso cref="ResourceInterfaces"/>
59 /// <seealso cref="ResourcePolicy"/>
60 /// <exception cref="NotSupportedException">Thrown when the iotcon is not supported.</exception>
61 /// <exception cref="OutOfMemoryException">Thrown when there is not enough memory.</exception>
63 /// // Create a class which inherits from Resource
64 /// public class DoorResource : Resource
66 /// public DoorResource(string uri, ResourceTypes types, ResourceInterfaces interfaces, ResourcePolicy policy)
67 /// : base(uri, types, interfaces, policy) {
69 /// protected override Response OnDelete(Request request) {
72 /// protected override Response OnGet(Request request) {
75 /// // Override other abstract methods of Resource class
78 /// // Use it like below
79 /// ResourceInterfaces ifaces = new ResourceInterfaces(new List<string>(){ ResourceInterfaces.DefaultInterface });
80 /// ResourceTypes types = new ResourceTypes(new List<string>(){ "oic.iot.door.new" });
81 /// Resource resource = new DoorResource("/door/uri1", types, ifaces, ResourcePolicy.Discoverable | ResourcePolicy.Observable);
83 protected Resource(string uri, ResourceTypes types, ResourceInterfaces interfaces, ResourcePolicy policy)
87 Interfaces = interfaces;
90 _children.CollectionChanged += ChildrenCollectionChanged;
92 int ret = Interop.IoTConnectivity.Server.Observers.Create(out _observerHandle);
93 if (ret != (int)IoTConnectivityError.None)
95 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to create obsever handle");
96 throw IoTConnectivityErrorFactory.GetException(ret);
101 /// Destructor of the Resource class.
109 /// Type details of the resource.
111 /// <since_tizen> 3 </since_tizen>
112 /// <value>Type details of the resource.</value>
113 public ResourceTypes Types { get; internal set; }
116 /// Interface details of the resource.
118 /// <since_tizen> 3 </since_tizen>
119 /// <value>Interface details of the resource.</value>
120 public ResourceInterfaces Interfaces { get; internal set; }
123 /// The policies of the resource.
125 /// <since_tizen> 3 </since_tizen>
126 /// <value>The policies of the resource.</value>
127 public ResourcePolicy Policy { get; internal set; }
130 /// URI path of the resource.
132 /// <since_tizen> 3 </since_tizen>
133 /// <value>URI path of the resource.</value>
134 public string UriPath { get; internal set; }
137 /// List of Child resources.
139 /// <since_tizen> 3 </since_tizen>
140 /// <value>List of Child resources.</value>
141 public ICollection<Resource> Children
149 internal IntPtr ResourceHandle
153 return _resourceHandle;
157 _resourceHandle = value;
162 /// Notify the specified representation and qos.
164 /// <since_tizen> 3 </since_tizen>
166 /// http://tizen.org/privilege/internet
168 /// <privlevel>public</privlevel>
169 /// <param name="representation">Representation.</param>
170 /// <param name="qos">The quality of service for message transfer.</param>
171 /// <feature>http://tizen.org/feature/iot.ocf</feature>
173 /// IoTConnectivityServerManager.Initialize() should be called to initialize.
175 /// <seealso cref="Representation"/>
176 /// <seealso cref="QualityOfService"/>
177 /// <exception cref="NotSupportedException">Thrown when the iotcon is not supported.</exception>
178 /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have privilege to access.</exception>
179 /// <exception cref="InvalidOperationException">Thrown when the operation is invalid.</exception>
181 /// ResourceInterfaces ifaces = new ResourceInterfaces(new List<string>(){ ResourceInterfaces.DefaultInterface });
182 /// ResourceTypes types = new ResourceTypes(new List<string>(){ "oic.iot.door.new.notify" });
183 /// Resource resource = new DoorResource("/door/uri/new/notify", types, ifaces, ResourcePolicy.Discoverable | ResourcePolicy.Observable);
184 /// IoTConnectivityServerManager.RegisterResource(resource);
186 /// Representation repr = new Representation();
187 /// repr.UriPath = "/door/uri/new/notify";
188 /// repr.Type = new ResourceTypes(new List<string>(){ "oic.iot.door.new.notify" });
189 /// repr.Attributes = new Attributes() {
192 /// resource.Notify(repr, QualityOfService.High);
194 public void Notify(Representation representation, QualityOfService qos)
196 int ret = (int)IoTConnectivityError.None;
197 ret = Interop.IoTConnectivity.Server.Resource.Notify(_resourceHandle, representation._representationHandle, _observerHandle, (int)qos);
198 if (ret != (int)IoTConnectivityError.None)
200 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to send notification");
201 throw IoTConnectivityErrorFactory.GetException(ret);
206 /// This is called when the client performs get operation on this resource.
208 /// <since_tizen> 3 </since_tizen>
209 /// <param name="request">A request from client.</param>
210 /// <returns>A response having the representation and the result.</returns>
211 protected abstract Response OnGet(Request request);
214 /// This is called when the client performs put operation on this resource.
216 /// <since_tizen> 3 </since_tizen>
217 /// <param name="request">A request from client.</param>
218 /// <returns>A response.</returns>
219 protected abstract Response OnPut(Request request);
222 /// This is called when the client performs post operation on this resource.
224 /// <since_tizen> 3 </since_tizen>
225 /// <param name="request">A request from client.</param>
226 /// <returns>A response having the representation and the result.</returns>
227 protected abstract Response OnPost(Request request);
230 /// This is called when the client performs delete operation on this resource.
232 /// <since_tizen> 3 </since_tizen>
233 /// <param name="request">A request from client.</param>
234 /// <returns>A response.</returns>
235 protected abstract Response OnDelete(Request request);
238 /// Called on the observing event.
240 /// <since_tizen> 3 </since_tizen>
241 /// <param name="request">A request from client.</param>
242 /// <param name="type">Observer type.</param>
243 /// <param name="observeId">Observe identifier.</param>
244 /// <returns>Returns true if it wants to be observed, else false.</returns>
245 protected abstract bool OnObserving(Request request, ObserveType type, int observeId);
248 /// Releases any unmanaged resources used by this object.
250 /// <since_tizen> 3 </since_tizen>
251 /// <feature>http://tizen.org/feature/iot.ocf</feature>
252 public void Dispose()
255 GC.SuppressFinalize(this);
259 /// Releases any unmanaged resources used by this object. Can also dispose any other disposable objects.
261 /// <since_tizen> 3 </since_tizen>
262 /// <param name="disposing">If true, disposes any disposable objects. If false, does not dispose disposable objects.</param>
263 /// <feature>http://tizen.org/feature/iot.ocf</feature>
264 protected virtual void Dispose(bool disposing)
272 Interfaces?.Dispose();
275 if (_resourceHandle != IntPtr.Zero)
276 Interop.IoTConnectivity.Server.Resource.Destroy(_resourceHandle);
277 if (_observerHandle != IntPtr.Zero)
278 Interop.IoTConnectivity.Server.Observers.Destroy(_observerHandle);
282 // This method is used as callback for Resource
283 internal void OnRequest(IntPtr resourceHandle, IntPtr requestHandle, IntPtr userData)
285 Request request = GetRequest(requestHandle);
286 Response response = null;
290 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get Request");
297 int ret = Interop.IoTConnectivity.Server.Request.GetObserveType(requestHandle, out observeType);
298 if (ret != (int)IoTConnectivityError.None)
300 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to Get observe type");
303 if ((ObserveType)observeType != ObserveType.NoType)
306 ret = Interop.IoTConnectivity.Server.Request.GetObserveId(requestHandle, out observeId);
307 if (ret != (int)IoTConnectivityError.None)
309 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to Get observe id");
312 switch ((ObserveType)observeType)
314 case ObserveType.Register:
316 if (OnObserving(request, ObserveType.Register, observeId))
318 ret = Interop.IoTConnectivity.Server.Observers.Add(_observerHandle, observeId);
319 if (ret != (int)IoTConnectivityError.None)
321 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to add observer id");
328 // If OnObserving for ObserveType.Register returns false, do not operate for Get operation after Observe operation.
332 case ObserveType.Deregister:
334 if (OnObserving(request, ObserveType.Deregister, observeId))
336 ret = Interop.IoTConnectivity.Server.Observers.Remove(_observerHandle, observeId);
337 if (ret != (int)IoTConnectivityError.None)
339 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to remove observer id");
346 // If OnObserving for ObserveType.Deregister returns false, do not operate for Get operation after Observe operation.
353 ret = Interop.IoTConnectivity.Server.Request.GetRequestType(requestHandle, out requestType);
354 if (ret != (int)IoTConnectivityError.None)
356 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to Get request type");
359 switch ((Interop.IoTConnectivity.Server.RequestType)requestType)
361 case Interop.IoTConnectivity.Server.RequestType.Put:
363 response = OnPut(request);
366 case Interop.IoTConnectivity.Server.RequestType.Get:
368 response = OnGet(request);
371 case Interop.IoTConnectivity.Server.RequestType.Post:
373 response = OnPost(request);
376 case Interop.IoTConnectivity.Server.RequestType.Delete:
378 response = OnDelete(request);
384 if (response == null)
386 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to send Response");
390 if (!response.Send(requestHandle))
392 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to send Response");
403 private Request GetRequest(IntPtr requestHandle)
405 IntPtr hostAddressPtr;
406 int ret = Interop.IoTConnectivity.Server.Request.GetHostAddress(requestHandle, out hostAddressPtr);
407 if (ret != (int)IoTConnectivityError.None)
409 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to Get host address");
413 IntPtr optionsHandle = IntPtr.Zero;
414 ret = Interop.IoTConnectivity.Server.Request.GetOptions(requestHandle, out optionsHandle);
415 if (ret != (int)IoTConnectivityError.None)
417 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to Get options");
421 IntPtr queryHandle = IntPtr.Zero;
422 ret = Interop.IoTConnectivity.Server.Request.GetQuery(requestHandle, out queryHandle);
423 if (ret != (int)IoTConnectivityError.None)
425 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to Get Query");
429 IntPtr representationHandle = IntPtr.Zero;
430 ret = Interop.IoTConnectivity.Server.Request.GetRepresentation(requestHandle, out representationHandle);
431 if (ret != (int)IoTConnectivityError.None)
433 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to Get representation");
437 ResourceOptions opts = null;
438 ResourceQuery query = null;
439 Representation representation = null;
442 opts = (optionsHandle == IntPtr.Zero) ? null : new ResourceOptions(optionsHandle);
444 catch (Exception exp)
446 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to new ResourceOptions: " + exp.Message);
452 query = (queryHandle == IntPtr.Zero) ? null : new ResourceQuery(queryHandle);
454 catch (Exception exp)
456 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to new ResourceQuery: " + exp.Message);
463 representation = (representationHandle == IntPtr.Zero) ? null : new Representation(representationHandle);
465 catch (Exception exp)
467 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to new Representation: " + exp.Message);
475 HostAddress = (hostAddressPtr != IntPtr.Zero) ? Marshal.PtrToStringAnsi(hostAddressPtr) : string.Empty,
478 Representation = representation
482 private void ChildrenCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs eventArgs)
484 if (eventArgs.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
486 foreach (Resource r in eventArgs.NewItems)
488 int ret = Interop.IoTConnectivity.Server.Resource.BindChildResource(_resourceHandle, r._resourceHandle);
489 if (ret != (int)IoTConnectivityError.None)
491 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to bind resource ");
492 throw IoTConnectivityErrorFactory.GetException(ret);
496 else if (eventArgs.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
498 foreach (Resource r in eventArgs.NewItems)
500 int ret = Interop.IoTConnectivity.Server.Resource.UnbindChildResource(_resourceHandle, r._resourceHandle);
501 if (ret != (int)IoTConnectivityError.None)
503 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to unbind resource");
504 throw IoTConnectivityErrorFactory.GetException(ret);