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.Concurrent;
22 using System.Runtime.InteropServices;
23 using System.Threading.Tasks;
25 namespace Tizen.Network.IoTConnectivity
28 /// This class represents a remote resource.
29 /// It provides APIs to manage remote resource.
31 /// <since_tizen> 3 </since_tizen>
32 public class RemoteResource : IDisposable
34 internal const int TimeOutMax = 3600;
35 internal IntPtr _remoteResourceHandle = IntPtr.Zero;
37 private bool _disposed = false;
38 private bool _cacheEnabled = false;
39 private ResourceOptions _options;
41 private static int _responseCallbackId = 1;
42 private static IDictionary<IntPtr, Interop.IoTConnectivity.Client.RemoteResource.ResponseCallback> _responseCallbacksMap = new ConcurrentDictionary<IntPtr, Interop.IoTConnectivity.Client.RemoteResource.ResponseCallback>();
44 private Interop.IoTConnectivity.Client.RemoteResource.CachedRepresentationChangedCallback _cacheUpdatedCallback;
45 private Interop.IoTConnectivity.Client.RemoteResource.StateChangedCallback _stateChangedCallback;
46 private Interop.IoTConnectivity.Client.RemoteResource.ObserveCallback _observeCallback;
48 private EventHandler<StateChangedEventArgs> _stateChangedEventHandler;
51 /// Creates a remote resource instance.
53 /// <since_tizen> 3 </since_tizen>
55 /// <para>To use this API, you should provide all the details required to correctly contact and
56 /// observe the object.</para>
57 /// <para>If not, you should discover the resource object manually.</para>
58 /// <para>The <paramref name="policy" /> can contain multiple policies like <c>ResourcePolicy.Discoverable | ResourcePolicy.Observable</c>.</para>
60 /// <param name="hostAddress">The host address of the resource.</param>
61 /// <param name="uriPath">The URI path of the resource.</param>
62 /// <param name="policy">The policies of the resource.</param>
63 /// <param name="resourceTypes">The resource types of the resource.</param>
64 /// <param name="resourceInterfaces">The resource interfaces of the resource.</param>
65 /// <feature>http://tizen.org/feature/iot.ocf</feature>
66 /// <exception cref="NotSupportedException">Thrown when the iotcon is not supported.</exception>
67 /// <exception cref="OutOfMemoryException">Thrown when there is not enough memory.</exception>
68 /// <exception cref="ArgumentException">Thrown when there is an invalid parameter.</exception>
69 public RemoteResource(string hostAddress, string uriPath, ResourcePolicy policy, ResourceTypes resourceTypes, ResourceInterfaces resourceInterfaces)
71 if (hostAddress == null || uriPath == null || resourceTypes == null || resourceInterfaces == null)
73 Log.Error(IoTConnectivityErrorFactory.LogTag, "Invalid parameters");
74 throw new ArgumentException("Invalid parameter");
77 HostAddress = hostAddress;
80 Types = new List<string>(resourceTypes);
81 Interfaces = new List<string>(resourceInterfaces);
84 CreateRemoteResource(resourceTypes._resourceTypeHandle, resourceInterfaces.ResourceInterfacesHandle);
87 internal RemoteResource(IntPtr handleToClone)
89 int ret = Interop.IoTConnectivity.Client.RemoteResource.Clone(handleToClone, out _remoteResourceHandle);
90 if (ret != (int)IoTConnectivityError.None)
92 Log.Error(IoTConnectivityErrorFactory.LogTag, "Faled to clone");
93 throw IoTConnectivityErrorFactory.GetException(ret);
99 /// Destructor of the RemoteResource class.
107 /// The event is invoked with cached resource attributes.
109 /// <since_tizen> 3 </since_tizen>
110 public event EventHandler<CacheUpdatedEventArgs> CacheUpdated;
113 /// Observe an event on the resource sent by the server.
115 /// <since_tizen> 3 </since_tizen>
116 public event EventHandler<ObserverNotifiedEventArgs> ObserverNotified;
119 /// The event is called when remote resource's state are changed.
121 /// <since_tizen> 3 </since_tizen>
122 public event EventHandler<StateChangedEventArgs> StateChanged
126 if (_stateChangedEventHandler == null)
128 RegisterStateChangedEvent();
130 _stateChangedEventHandler += value;
134 _stateChangedEventHandler -= value;
135 if (_stateChangedEventHandler == null)
137 UnregisterStateChangedEvent();
143 /// The host address of the resource.
145 /// <since_tizen> 3 </since_tizen>
146 /// <value>The host address of the resource.</value>
147 public string HostAddress { get; private set; }
150 /// The URI path of the resource.
152 /// <since_tizen> 3 </since_tizen>
153 /// <value>The URI path of the resource.</value>
154 public string UriPath { get; private set; }
157 /// The resource types of the remote resource.
159 /// <since_tizen> 3 </since_tizen>
160 /// <value>The resource types of the remote resource.</value>
161 public IEnumerable<string> Types { get; private set; }
164 /// The interfaces of the resource.
166 /// <since_tizen> 3 </since_tizen>
167 /// <value>The interfaces of the resource.</value>
168 public IEnumerable<string> Interfaces { get; private set; }
171 /// The policy of the resource.
173 /// <since_tizen> 3 </since_tizen>
174 /// <value>The policy of the resource.</value>
175 public ResourcePolicy Policy { get; private set; }
178 /// The header options of the resource.
180 /// <since_tizen> 3 </since_tizen>
181 /// <value>The header options of the resource.</value>
182 /// <exception cref="NotSupportedException">Thrown when the iotcon is not supported.</exception>
183 /// <exception cref="ArgumentException">Thrown when there is an invalid parameter.</exception>
184 public ResourceOptions Options
195 int ret = Interop.IoTConnectivity.Client.RemoteResource.SetOptions(_remoteResourceHandle, value._resourceOptionsHandle);
196 if (ret != (int)IoTConnectivityError.None)
198 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to set options");
199 throw IoTConnectivityErrorFactory.GetException(ret);
206 /// Indicates the CacheEnabled status of the remote resource.
208 /// <since_tizen> 3 </since_tizen>
210 /// Client can start caching only when this is set true. Set it to false to stop caching the resource attributes.
212 /// <exception cref="NotSupportedException">Thrown when the iotcon is not supported.</exception>
213 /// <exception cref="ArgumentException">Thrown when there is an invalid parameter.</exception>
214 /// <exception cref="InvalidOperationException">Thrown when the operation is invalid.</exception>
215 /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have privilege to access.</exception>
216 /// <exception cref="OutOfMemoryException">Thrown when there is not enough memory.</exception>
217 public bool CacheEnabled
221 return _cacheEnabled;
225 if (_cacheEnabled != value)
227 _cacheEnabled = value;
228 HandleCachePolicyChanged();
234 /// Time interval of monitoring and caching API.
236 /// <since_tizen> 3 </since_tizen>
238 /// Default time interval is 10 seconds.
239 /// Seconds for time interval (must be in range from 1 to 3600).
241 /// <exception cref="NotSupportedException">Thrown when the iotcon is not supported.</exception>
242 /// <exception cref="ArgumentException">Thrown when there is an invalid parameter.</exception>
243 public int TimeInterval
248 int ret = Interop.IoTConnectivity.Client.RemoteResource.GetTimeInterval(_remoteResourceHandle, out interval);
249 if (ret != (int)IoTConnectivityError.None)
251 Log.Warn(IoTConnectivityErrorFactory.LogTag, "Failed to get time interval");
258 int ret = (int)IoTConnectivityError.InvalidParameter;
259 if (value <= TimeOutMax && value > 0)
261 ret = Interop.IoTConnectivity.Client.RemoteResource.SetTimeInterval(_remoteResourceHandle, value);
263 if (ret != (int)IoTConnectivityError.None)
265 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to set time interval");
266 throw IoTConnectivityErrorFactory.GetException(ret);
272 /// The device ID of the resource.
274 /// <since_tizen> 3 </since_tizen>
275 /// <value>The device ID of the resource.</value>
276 public string DeviceId { get; private set; }
279 /// Gets cached representation from the remote resource.
281 /// <since_tizen> 3 </since_tizen>
282 /// <returns>cached representation from the remote resource.</returns>
283 /// <feature>http://tizen.org/feature/iot.ocf</feature>
284 public Representation CachedRepresentation()
287 int ret = Interop.IoTConnectivity.Client.RemoteResource.GetCachedRepresentation(_remoteResourceHandle, out handle);
288 if (ret != (int)IoTConnectivityError.None)
290 Log.Warn(IoTConnectivityErrorFactory.LogTag, "Failed to get CachedRepresentation");
294 Representation representation = new Representation(handle);
295 return representation;
299 /// Starts observing on the resource.
301 /// <since_tizen> 3 </since_tizen>
303 /// When server sends notification message, <see cref="ObserverNotified"/> will be called.
305 /// <privilege>http://tizen.org/privilege/internet</privilege>
306 /// <privlevel>public</privlevel>
307 /// <param name="policy">The type to specify how client wants to observe.</param>
308 /// <param name="query">The query to send to server.</param>
309 /// <feature>http://tizen.org/feature/iot.ocf</feature>
310 /// <exception cref="NotSupportedException">Thrown when the iotcon is not supported.</exception>
311 /// <exception cref="InvalidOperationException">Thrown when the operation is invalid.</exception>
312 /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have privilege to access.</exception>
313 /// <exception cref="OutOfMemoryException">Thrown when there is not enough memory.</exception>
314 public void StartObserving(ObservePolicy policy, ResourceQuery query = null)
316 _observeCallback = (IntPtr resource, int err, int sequenceNumber, IntPtr response, IntPtr userData) =>
319 IntPtr representationHandle;
320 int ret = Interop.IoTConnectivity.Server.Response.GetResult(response, out result);
321 if (ret != (int)IoTConnectivityError.None)
323 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get result");
327 ret = Interop.IoTConnectivity.Server.Response.GetRepresentation(response, out representationHandle);
328 if (ret != (int)IoTConnectivityError.None)
330 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get representation");
334 Representation repr = null;
337 repr = new Representation(representationHandle);
339 catch (Exception exp)
341 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to new representation: " + exp.Message);
345 ObserverNotifiedEventArgs e = new ObserverNotifiedEventArgs()
347 Representation = repr,
348 Result = (ResponseCode)result
350 ObserverNotified?.Invoke(this, e);
353 IntPtr queryHandle = IntPtr.Zero;
356 queryHandle = query._resourceQueryHandle;
359 int errCode = Interop.IoTConnectivity.Client.RemoteResource.RegisterObserve(_remoteResourceHandle, (int)policy, queryHandle, _observeCallback, IntPtr.Zero);
360 if (errCode != (int)IoTConnectivityError.None)
362 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to register observe callbacks");
363 throw IoTConnectivityErrorFactory.GetException(errCode);
368 /// Stops observing on the resource.
370 /// <since_tizen> 3 </since_tizen>
371 /// <privilege>http://tizen.org/privilege/internet</privilege>
372 /// <privlevel>public</privlevel>
373 /// <feature>http://tizen.org/feature/iot.ocf</feature>
374 /// <exception cref="NotSupportedException">Thrown when the iotcon is not supported.</exception>
375 /// <exception cref="InvalidOperationException">Thrown when the operation is invalid.</exception>
376 /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have privilege to access.</exception>
377 public void StopObserving()
379 int ret = Interop.IoTConnectivity.Client.RemoteResource.DeregisterObserve(_remoteResourceHandle);
380 if (ret != (int)IoTConnectivityError.None)
382 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to deregister observe callbacks");
383 throw IoTConnectivityErrorFactory.GetException(ret);
388 /// Gets the attributes of a resource asynchronously.
390 /// <since_tizen> 3 </since_tizen>
391 /// <privilege>http://tizen.org/privilege/internet</privilege>
392 /// <privlevel>public</privlevel>
393 /// <param name="query">The ResourceQuery to send to server.</param>
394 /// <returns>Remote response with result and representation.</returns>
395 /// <feature>http://tizen.org/feature/iot.ocf</feature>
396 public async Task<RemoteResponse> GetAsync(ResourceQuery query = null)
398 TaskCompletionSource<RemoteResponse> tcsRemoteResponse = new TaskCompletionSource<RemoteResponse>();
400 IntPtr id = IntPtr.Zero;
401 lock (_responseCallbacksMap)
403 id = (IntPtr)_responseCallbackId++;
405 _responseCallbacksMap[id] = (IntPtr resource, int err, int requestType, IntPtr responseHandle, IntPtr userData) =>
407 IntPtr responseCallbackId = userData;
409 _responseCallbacksMap.Remove(responseCallbackId);
411 if (responseHandle != IntPtr.Zero)
415 tcsRemoteResponse.TrySetResult(GetRemoteResponse(responseHandle));
419 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get RemoteResponse: ", exp.Message);
420 tcsRemoteResponse.TrySetException(exp);
425 tcsRemoteResponse.TrySetException(IoTConnectivityErrorFactory.GetException((int)IoTConnectivityError.System));
429 IntPtr queryHandle = (query == null) ? IntPtr.Zero : query._resourceQueryHandle;
430 int errCode = Interop.IoTConnectivity.Client.RemoteResource.Get(_remoteResourceHandle, queryHandle, _responseCallbacksMap[id], id);
431 if (errCode != (int)IoTConnectivityError.None)
433 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get resource attributes");
434 tcsRemoteResponse.TrySetException(IoTConnectivityErrorFactory.GetException(errCode));
436 return await tcsRemoteResponse.Task;
440 /// Puts the representation of a resource asynchronously.
442 /// <since_tizen> 3 </since_tizen>
443 /// <privilege>http://tizen.org/privilege/internet</privilege>
444 /// <privlevel>public</privlevel>
445 /// <param name="representation">Resource representation to put.</param>
446 /// <param name="query">The ResourceQuery to send to server.</param>
447 /// <returns>Remote response with result and representation.</returns>
448 /// <feature>http://tizen.org/feature/iot.ocf</feature>
449 public async Task<RemoteResponse> PutAsync(Representation representation, ResourceQuery query = null)
451 TaskCompletionSource<RemoteResponse> tcsRemoteResponse = new TaskCompletionSource<RemoteResponse>();
453 IntPtr id = IntPtr.Zero;
454 lock (_responseCallbacksMap)
456 id = (IntPtr)_responseCallbackId++;
458 _responseCallbacksMap[id] = (IntPtr resource, int err, int requestType, IntPtr responseHandle, IntPtr userData) =>
460 IntPtr responseCallbackId = userData;
462 _responseCallbacksMap.Remove(responseCallbackId);
464 if (err == (int)(IoTConnectivityError.Iotivity))
466 RemoteResponse response = new RemoteResponse();
467 response.Result = ResponseCode.Forbidden;
468 response.Representation = null;
469 tcsRemoteResponse.TrySetResult(response);
471 else if (responseHandle != IntPtr.Zero)
475 tcsRemoteResponse.TrySetResult(GetRemoteResponse(responseHandle));
477 catch (Exception exp)
479 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get RemoteResponse: ", exp.Message);
480 tcsRemoteResponse.TrySetException(exp);
485 tcsRemoteResponse.TrySetException(IoTConnectivityErrorFactory.GetException((int)IoTConnectivityError.System));
488 IntPtr queryHandle = (query == null) ? IntPtr.Zero : query._resourceQueryHandle;
489 int errCode = Interop.IoTConnectivity.Client.RemoteResource.Put(_remoteResourceHandle, representation._representationHandle, queryHandle, _responseCallbacksMap[id], id);
490 if (errCode != (int)IoTConnectivityError.None)
492 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to put resource representation");
493 tcsRemoteResponse.TrySetException(IoTConnectivityErrorFactory.GetException(errCode));
495 return await tcsRemoteResponse.Task;
499 /// Posts request on a resource asynchronously.
501 /// <since_tizen> 3 </since_tizen>
502 /// <privilege>http://tizen.org/privilege/internet</privilege>
503 /// <privlevel>public</privlevel>
504 /// <param name="representation">Resource representation of request.</param>
505 /// <param name="query">The ResourceQuery to send to server.</param>
506 /// <returns>Remote response with result and representation.</returns>
507 /// <feature>http://tizen.org/feature/iot.ocf</feature>
508 public async Task<RemoteResponse> PostAsync(Representation representation, ResourceQuery query = null)
510 TaskCompletionSource<RemoteResponse> tcsRemoteResponse = new TaskCompletionSource<RemoteResponse>();
512 IntPtr id = IntPtr.Zero;
513 lock (_responseCallbacksMap)
515 id = (IntPtr)_responseCallbackId++;
517 _responseCallbacksMap[id] = (IntPtr resource, int err, int requestType, IntPtr responseHandle, IntPtr userData) =>
519 IntPtr responseCallbackId = userData;
521 _responseCallbacksMap.Remove(responseCallbackId);
523 if (responseHandle != IntPtr.Zero)
527 tcsRemoteResponse.TrySetResult(GetRemoteResponse(responseHandle));
529 catch (Exception exp)
531 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get RemoteResponse: ", exp.Message);
532 tcsRemoteResponse.TrySetException(exp);
537 tcsRemoteResponse.TrySetException(IoTConnectivityErrorFactory.GetException((int)IoTConnectivityError.System));
540 IntPtr queryHandle = (query == null) ? IntPtr.Zero : query._resourceQueryHandle;
541 int errCode = Interop.IoTConnectivity.Client.RemoteResource.Post(_remoteResourceHandle, representation._representationHandle, queryHandle, _responseCallbacksMap[id], id);
542 if (errCode != (int)IoTConnectivityError.None)
544 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to post request");
545 tcsRemoteResponse.TrySetException(IoTConnectivityErrorFactory.GetException(errCode));
547 return await tcsRemoteResponse.Task;
551 /// Deletes the resource asynchronously.
553 /// <since_tizen> 3 </since_tizen>
554 /// <privilege>http://tizen.org/privilege/internet</privilege>
555 /// <privlevel>public</privlevel>
556 /// <returns>Remote response with result and representation.</returns>
557 /// <feature>http://tizen.org/feature/iot.ocf</feature>
558 public async Task<RemoteResponse> DeleteAsync()
560 TaskCompletionSource<RemoteResponse> tcsRemoteResponse = new TaskCompletionSource<RemoteResponse>();
562 IntPtr id = IntPtr.Zero;
563 lock (_responseCallbacksMap)
565 id = (IntPtr)_responseCallbackId++;
567 _responseCallbacksMap[id] = (IntPtr resource, int err, int requestType, IntPtr responseHandle, IntPtr userData) =>
569 IntPtr responseCallbackId = userData;
571 _responseCallbacksMap.Remove(responseCallbackId);
573 if (err == (int)(IoTConnectivityError.Iotivity))
575 RemoteResponse response = new RemoteResponse();
576 response.Result = ResponseCode.Forbidden;
577 response.Representation = null;
578 tcsRemoteResponse.TrySetResult(response);
580 else if (responseHandle != IntPtr.Zero)
584 tcsRemoteResponse.TrySetResult(GetRemoteResponse(responseHandle));
586 catch (Exception exp)
588 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get RemoteResponse: ", exp.Message);
589 tcsRemoteResponse.TrySetException(exp);
594 tcsRemoteResponse.TrySetException(IoTConnectivityErrorFactory.GetException((int)IoTConnectivityError.System));
598 int errCode = Interop.IoTConnectivity.Client.RemoteResource.Delete(_remoteResourceHandle, _responseCallbacksMap[id], id);
599 if (errCode != (int)IoTConnectivityError.None)
601 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to delete");
602 tcsRemoteResponse.TrySetException(IoTConnectivityErrorFactory.GetException(errCode));
604 return await tcsRemoteResponse.Task;
608 /// Releases any unmanaged resources used by this object.
610 /// <since_tizen> 3 </since_tizen>
611 /// <feature>http://tizen.org/feature/iot.ocf</feature>
612 public void Dispose()
615 GC.SuppressFinalize(this);
618 internal static Interop.IoTConnectivity.Client.RemoteResource.ConnectivityType GetConnectivityType(string hostAddress)
620 Interop.IoTConnectivity.Client.RemoteResource.ConnectivityType type = Interop.IoTConnectivity.Client.RemoteResource.ConnectivityType.None;
622 Log.Info(IoTConnectivityErrorFactory.LogTag, hostAddress);
624 if (hostAddress == IoTConnectivityClientManager.MulticastAddress)
626 type = Interop.IoTConnectivity.Client.RemoteResource.ConnectivityType.Ipv4;
631 string hostName = hostAddress;
632 if (hostAddress.Contains(":"))
634 string[] hostParts = hostAddress.Split(':');
635 if (hostParts.Length == 2)
637 hostName = hostParts[0];
640 if (hostAddress.Contains("%"))
642 string[] hostParts = hostAddress.Split('%');
643 if (hostParts.Length == 2)
645 hostName = hostParts[0];
648 if (hostName.Contains("["))
650 string[] hostParts = hostName.Split('[');
651 if (hostParts.Length == 2)
653 hostName = hostParts[1];
656 Log.Info(IoTConnectivityErrorFactory.LogTag, hostName);
657 if (IPAddress.TryParse(hostName, out address))
659 switch (address.AddressFamily)
661 case System.Net.Sockets.AddressFamily.InterNetwork:
662 type = Interop.IoTConnectivity.Client.RemoteResource.ConnectivityType.Ipv4;
664 case System.Net.Sockets.AddressFamily.InterNetworkV6:
665 type = Interop.IoTConnectivity.Client.RemoteResource.ConnectivityType.Ipv6;
668 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to parse for Ipv4 or Ipv6");
674 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to parse hostname " + hostName);
681 /// Releases any unmanaged resources used by this object. Can also dispose any other disposable objects.
683 /// <since_tizen> 3 </since_tizen>
684 /// <param name="disposing">If true, disposes any disposable objects. If false, does not dispose disposable objects.</param>
685 /// <feature>http://tizen.org/feature/iot.ocf</feature>
686 protected virtual void Dispose(bool disposing)
693 // Free managed objects
696 Interop.IoTConnectivity.Client.RemoteResource.Destroy(_remoteResourceHandle);
700 private void HandleCachePolicyChanged()
704 _cacheUpdatedCallback = (IntPtr resource, IntPtr representation, IntPtr userData) =>
708 Representation repr = null;
711 repr = new Representation(representation);
713 catch (Exception exp)
715 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to new Representation: " + exp.Message);
719 CacheUpdatedEventArgs e = new CacheUpdatedEventArgs()
721 Representation = repr
723 CacheUpdated?.Invoke(this, e);
727 int ret = Interop.IoTConnectivity.Client.RemoteResource.StartCaching(_remoteResourceHandle, _cacheUpdatedCallback, IntPtr.Zero);
728 if (ret != (int)IoTConnectivityError.None)
730 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to add cache updated event handler");
731 throw IoTConnectivityErrorFactory.GetException(ret);
736 int ret = Interop.IoTConnectivity.Client.RemoteResource.StopCaching(_remoteResourceHandle);
737 if (ret != (int)IoTConnectivityError.None)
739 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to remove cache updated event handler");
740 throw IoTConnectivityErrorFactory.GetException(ret);
745 private void RegisterStateChangedEvent()
747 _stateChangedCallback = (IntPtr resource, int state, IntPtr userData) =>
749 StateChangedEventArgs e = new StateChangedEventArgs()
751 State = (ResourceState)state
753 _stateChangedEventHandler?.Invoke(null, e);
756 int ret = Interop.IoTConnectivity.Client.RemoteResource.StartMonitoring(_remoteResourceHandle, _stateChangedCallback, IntPtr.Zero);
757 if (ret != (int)IoTConnectivityError.None)
759 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to add state changed event handler");
760 throw IoTConnectivityErrorFactory.GetException(ret);
764 private void UnregisterStateChangedEvent()
766 int ret = Interop.IoTConnectivity.Client.RemoteResource.StopMonitoring(_remoteResourceHandle);
767 if (ret != (int)IoTConnectivityError.None)
769 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to remove state changed event handler");
770 throw IoTConnectivityErrorFactory.GetException(ret);
774 private void CreateRemoteResource(IntPtr resourceTypeHandle, IntPtr resourceInterfaceHandle)
776 Interop.IoTConnectivity.Client.RemoteResource.ConnectivityType connectivityType = GetConnectivityType(HostAddress);
777 if (connectivityType == Interop.IoTConnectivity.Client.RemoteResource.ConnectivityType.None)
779 Log.Error(IoTConnectivityErrorFactory.LogTag, "Unable to parse host address");
780 throw new ArgumentException("Unable to parse host address");
782 int ret = Interop.IoTConnectivity.Client.RemoteResource.Create(HostAddress, (int)connectivityType, UriPath, (int)Policy, resourceTypeHandle, resourceInterfaceHandle, out _remoteResourceHandle);
783 if (ret != (int)IoTConnectivityError.None)
785 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get remote resource");
786 throw IoTConnectivityErrorFactory.GetException(ret);
790 private void SetRemoteResource()
792 IntPtr hostAddressPtr, uriPathPtr;
793 int ret = Interop.IoTConnectivity.Client.RemoteResource.GetHostAddress(_remoteResourceHandle, out hostAddressPtr);
794 if (ret != (int)IoTConnectivityError.None)
796 Log.Error(IoTConnectivityErrorFactory.LogTag, "Faled to get host address");
797 throw IoTConnectivityErrorFactory.GetException(ret);
800 ret = Interop.IoTConnectivity.Client.RemoteResource.GetUriPath(_remoteResourceHandle, out uriPathPtr);
801 if (ret != (int)IoTConnectivityError.None)
803 Log.Error(IoTConnectivityErrorFactory.LogTag, "Faled to get uri path");
804 throw IoTConnectivityErrorFactory.GetException(ret);
807 int policy = (int)ResourcePolicy.NoProperty;
808 ret = Interop.IoTConnectivity.Client.RemoteResource.GetPolicies(_remoteResourceHandle, out policy);
809 if (ret != (int)IoTConnectivityError.None)
811 Log.Error(IoTConnectivityErrorFactory.LogTag, "Faled to get uri path");
812 throw IoTConnectivityErrorFactory.GetException(ret);
815 IntPtr typesHandle, interfacesHandle;
816 ret = Interop.IoTConnectivity.Client.RemoteResource.GetTypes(_remoteResourceHandle, out typesHandle);
817 if (ret != (int)IoTConnectivityError.None)
819 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get resource types");
820 throw IoTConnectivityErrorFactory.GetException(ret);
823 ret = Interop.IoTConnectivity.Client.RemoteResource.GetInterfaces(_remoteResourceHandle, out interfacesHandle);
824 if (ret != (int)IoTConnectivityError.None)
826 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get resource interfaces");
827 throw IoTConnectivityErrorFactory.GetException(ret);
831 ret = Interop.IoTConnectivity.Client.RemoteResource.GetDeviceId(_remoteResourceHandle, out deviceIdPtr);
832 if (ret != (int)IoTConnectivityError.None)
834 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get device id");
835 throw IoTConnectivityErrorFactory.GetException(ret);
837 DeviceId = (deviceIdPtr != IntPtr.Zero) ? Marshal.PtrToStringAnsi(deviceIdPtr) : string.Empty;
838 HostAddress = (hostAddressPtr != IntPtr.Zero) ? Marshal.PtrToStringAnsi(hostAddressPtr) : string.Empty;
839 UriPath = (uriPathPtr != IntPtr.Zero) ? Marshal.PtrToStringAnsi(uriPathPtr) : string.Empty;
840 Types = new ResourceTypes(typesHandle);
841 Interfaces = new ResourceInterfaces(interfacesHandle);
842 Policy = (ResourcePolicy)policy;
845 private RemoteResponse GetRemoteResponse(IntPtr response)
848 IntPtr representationHandle, optionsHandle;
849 int ret = Interop.IoTConnectivity.Server.Response.GetResult(response, out result);
850 if (ret != (int)IoTConnectivityError.None)
852 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get result");
853 throw IoTConnectivityErrorFactory.GetException(ret);
856 ret = Interop.IoTConnectivity.Server.Response.GetRepresentation(response, out representationHandle);
857 if (ret != (int)IoTConnectivityError.None)
859 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get representation");
860 throw IoTConnectivityErrorFactory.GetException(ret);
863 ret = Interop.IoTConnectivity.Server.Response.GetOptions(response, out optionsHandle);
864 if (ret != (int)IoTConnectivityError.None)
866 Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to get options");
867 throw IoTConnectivityErrorFactory.GetException(ret);
869 return new RemoteResponse()
871 Result = (ResponseCode)result,
872 Representation = new Representation(representationHandle),
873 Options = (optionsHandle == IntPtr.Zero)? null : new ResourceOptions(optionsHandle)