# This script includes windows specific config (MSVS/MSVC)
##
Import('env')
-import os.path
+import os
+import winreg
+import platform
+
+def OpenRegKey(env, key, sub_key, reg_view_64bit=False):
+ # Default access
+ reg_access_mask = winreg.KEY_READ
+ if reg_view_64bit:
+ # Access the 64bit Registry View
+ reg_access_mask |= winreg.KEY_WOW64_64KEY
+
+ try:
+ hkey = winreg.OpenKey(key,
+ sub_key,
+ 0, # Reserved
+ reg_access_mask)
+ except WindowsError, err:
+ if err.errno != os.errno.ENOENT:
+ # Couldn't open Registry Key
+ Exit('Error: Could not Open %s Registry Key. Err=%s' % (sub_key, err.errno))
+ else:
+ # Registry Key not found
+ hkey = None
+
+ return hkey
+
+def ReadRegistryStringValue(env, key, sub_key, value_name, reg_view_64bit=False):
+ hkey = env.OpenRegKey(key, sub_key, reg_view_64bit)
+ if hkey:
+ try:
+ (value, type) = winreg.QueryValueEx(hkey, value_name)
+ if type != winreg.REG_SZ:
+ Exit('Error: Registry Value \'%s\' is not a String' % value_name)
+ except WindowsError, err:
+ if err.errno != os.errno.ENOENT:
+ Exit('Error: Could not QueryValueEx for Registry Value \'%s\'. Err=%s' \
+ % (value_name, err.errno))
+ else:
+ # Registry Value not found
+ value = None
+
+ hkey.Close()
+ else:
+ value = None
+
+ return value
+
+def SetupMSBuildEnv(env):
+ # Add MSBuild path to path
+ msbuild_reg_path = 'SOFTWARE\\Microsoft\\MSBuild\\ToolsVersions\\' + env.get('MSVC_VERSION')
+ # MSBuild executable arch needs to be the same as the python/SCons environment Arch.
+ # Open the Registry key with the same registry view as the environment (handled by the
+ # winreg.OpenKey function)
+ msbuild_path = env.ReadRegistryStringValue(winreg.HKEY_LOCAL_MACHINE,
+ msbuild_reg_path,
+ 'MSBuildToolsPath')
+ if not msbuild_path:
+ Exit('Error: Could not Find the MSBuild Registry Key/Value')
+
+ env.AppendUnique(PATH = [msbuild_path])
+ # Need to update the 'ENV' dictionary PATH as that's what is used when executing
+ # commands
+ env['ENV']['PATH'] = env.get('PATH')
+
+def GetMSBuildArgs(env):
+ target_arch = env.get('TARGET_ARCH')
+ platform = target_arch
+ if target_arch in ['amd64']:
+ platform = 'x64'
+
+ # Set configuration value used by Visual Studio.
+ if env.get('RELEASE'):
+ configuration = 'Release'
+ else:
+ configuration = 'Debug /p:AppxPackageAllowDebugFrameworkReferencesInManifest=true'
+
+ # Get the MSBuildOutDir env variable for the output directory
+ # Note: This should only be set on a cloned Environment and not the global one
+ outdir = env.get('MSBuildOutDir')
+
+ return (configuration, platform, outdir)
+
+def MSBuildGenerator(source, target, env, for_signature):
+ env.SetupMSBuildEnv()
+ (configuration, platform, outdir) = env.GetMSBuildArgs()
+
+ msbuild_cmd = 'msbuild.exe %s /p:Configuration=%s /p:Platform=%s /p:OutDir="%s"' \
+ % (source[0], configuration, platform, outdir)
+ return msbuild_cmd
+
+def MSBuildClean(env, target, solutionfile):
+ env.SetupMSBuildEnv()
+ (configuration, platform, outdir) = env.GetMSBuildArgs()
+
+ msbuild_cmd = 'msbuild.exe %s /p:Configuration=%s /p:Platform=%s /p:OutDir="%s" /t:Clean' \
+ % (solutionfile, configuration, platform, outdir)
+ env.Execute(msbuild_cmd)
help_vars = Variables()
if env.get('BUILD_JAVA') == True:
help_vars.Update(env)
Help(help_vars.GenerateHelpText(env))
+if env.get('UWP_APP') == '1':
+ # Create an MSBuilder that uses a generator to generate the MSBuild actions
+ MSBuilder = Builder(generator = MSBuildGenerator)
+ # Add the builder to the env
+ env.Append(BUILDERS = {'MSBuild' : MSBuilder})
+ # Add MSBuildClean function to env
+ env.AddMethod(MSBuildClean)
+ # Add SetupMSBuildEnv function to env
+ env.AddMethod(SetupMSBuildEnv)
+ # Add GetMSBuildArgs function to env
+ env.AddMethod(GetMSBuildArgs)
+ # Add OpenRegKey function to env
+ env.AddMethod(OpenRegKey)
+ # Add ReadRegistryStringValue function to env
+ env.AddMethod(ReadRegistryStringValue)
+
# Set common flags
if env['CC'] == 'cl':
if env.get('UWP_APP') == '1':
--- /dev/null
+<Application\r
+ x:Class="ElevatorClientUWP.App"\r
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"\r
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"\r
+ xmlns:local="using:ElevatorClientUWP"\r
+ RequestedTheme="Light">\r
+\r
+</Application>\r
--- /dev/null
+/* *****************************************************************
+*
+* Copyright 2017 Microsoft
+*
+*
+* 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.
+*
+******************************************************************/\r
+\r
+//\r
+// App.xaml.cpp\r
+// Implementation of the App class.\r
+//\r
+\r
+#include "pch.h"\r
+#include "MainPage.xaml.h"\r
+\r
+using namespace ElevatorClientUWP;\r
+\r
+using namespace Platform;\r
+using namespace Windows::ApplicationModel;\r
+using namespace Windows::ApplicationModel::Activation;\r
+using namespace Windows::Foundation;\r
+using namespace Windows::Foundation::Collections;\r
+using namespace Windows::UI::Xaml;\r
+using namespace Windows::UI::Xaml::Controls;\r
+using namespace Windows::UI::Xaml::Controls::Primitives;\r
+using namespace Windows::UI::Xaml::Data;\r
+using namespace Windows::UI::Xaml::Input;\r
+using namespace Windows::UI::Xaml::Interop;\r
+using namespace Windows::UI::Xaml::Media;\r
+using namespace Windows::UI::Xaml::Navigation;\r
+\r
+/// <summary>\r
+/// Initializes the singleton application object. This is the first line of authored code\r
+/// executed, and as such is the logical equivalent of main() or WinMain().\r
+/// </summary>\r
+App::App()\r
+{\r
+ InitializeComponent();\r
+ Suspending += ref new SuspendingEventHandler(this, &App::OnSuspending);\r
+}\r
+\r
+/// <summary>\r
+/// Invoked when the application is launched normally by the end user. Other entry points\r
+/// will be used such as when the application is launched to open a specific file.\r
+/// </summary>\r
+/// <param name="e">Details about the launch request and process.</param>\r
+void App::OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEventArgs^ e)\r
+{\r
+#if _DEBUG\r
+ // Show graphics profiling information while debugging.\r
+ if (IsDebuggerPresent())\r
+ {\r
+ // Display the current frame rate counters\r
+ DebugSettings->EnableFrameRateCounter = true;\r
+ }\r
+#endif\r
+ auto rootFrame = dynamic_cast<Frame^>(Window::Current->Content);\r
+\r
+ // Do not repeat app initialization when the Window already has content,\r
+ // just ensure that the window is active\r
+ if (rootFrame == nullptr)\r
+ {\r
+ // Create a Frame to act as the navigation context and associate it with\r
+ // a SuspensionManager key\r
+ rootFrame = ref new Frame();\r
+\r
+ rootFrame->NavigationFailed += ref new Windows::UI::Xaml::Navigation::NavigationFailedEventHandler(this, &App::OnNavigationFailed);\r
+\r
+ if (e->PreviousExecutionState == ApplicationExecutionState::Terminated)\r
+ {\r
+ // TODO: Restore the saved session state only when appropriate, scheduling the\r
+ // final launch steps after the restore is complete\r
+\r
+ }\r
+\r
+ if (e->PrelaunchActivated == false)\r
+ {\r
+ if (rootFrame->Content == nullptr)\r
+ {\r
+ // When the navigation stack isn't restored navigate to the first page,\r
+ // configuring the new page by passing required information as a navigation\r
+ // parameter\r
+ rootFrame->Navigate(TypeName(MainPage::typeid), e->Arguments);\r
+ }\r
+ // Place the frame in the current Window\r
+ Window::Current->Content = rootFrame;\r
+ // Ensure the current window is active\r
+ Window::Current->Activate();\r
+ }\r
+ }\r
+ else\r
+ {\r
+ if (e->PrelaunchActivated == false)\r
+ {\r
+ if (rootFrame->Content == nullptr)\r
+ {\r
+ // When the navigation stack isn't restored navigate to the first page,\r
+ // configuring the new page by passing required information as a navigation\r
+ // parameter\r
+ rootFrame->Navigate(TypeName(MainPage::typeid), e->Arguments);\r
+ }\r
+ // Ensure the current window is active\r
+ Window::Current->Activate();\r
+ }\r
+ }\r
+}\r
+\r
+/// <summary>\r
+/// Invoked when application execution is being suspended. Application state is saved\r
+/// without knowing whether the application will be terminated or resumed with the contents\r
+/// of memory still intact.\r
+/// </summary>\r
+/// <param name="sender">The source of the suspend request.</param>\r
+/// <param name="e">Details about the suspend request.</param>\r
+void App::OnSuspending(Object^ sender, SuspendingEventArgs^ e)\r
+{\r
+ (void) sender; // Unused parameter\r
+ (void) e; // Unused parameter\r
+\r
+ //TODO: Save application state and stop any background activity\r
+}\r
+\r
+/// <summary>\r
+/// Invoked when Navigation to a certain page fails\r
+/// </summary>\r
+/// <param name="sender">The Frame which failed navigation</param>\r
+/// <param name="e">Details about the navigation failure</param>\r
+void App::OnNavigationFailed(Platform::Object ^sender, Windows::UI::Xaml::Navigation::NavigationFailedEventArgs ^e)\r
+{\r
+ throw ref new FailureException("Failed to load Page " + e->SourcePageType.Name);\r
+}
\ No newline at end of file
--- /dev/null
+/* *****************************************************************
+*
+* Copyright 2017 Microsoft
+*
+*
+* 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.
+*
+******************************************************************/\r
+\r
+//\r
+// App.xaml.h\r
+// Declaration of the App class.\r
+//\r
+\r
+#pragma once\r
+\r
+#include "App.g.h"\r
+\r
+namespace ElevatorClientUWP\r
+{\r
+ /// <summary>\r
+ /// Provides application-specific behavior to supplement the default Application class.\r
+ /// </summary>\r
+ ref class App sealed\r
+ {\r
+ protected:\r
+ virtual void OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEventArgs^ e) override;\r
+\r
+ internal:\r
+ App();\r
+\r
+ private:\r
+ void OnSuspending(Platform::Object^ sender, Windows::ApplicationModel::SuspendingEventArgs^ e);\r
+ void OnNavigationFailed(Platform::Object ^sender, Windows::UI::Xaml::Navigation::NavigationFailedEventArgs ^e);\r
+ };\r
+}\r
--- /dev/null
+/* *****************************************************************
+ *
+ * Copyright 2017 Microsoft
+ *
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+#include "pch.h"
+#include <string>
+#include <iostream>
+#include "ipca.h"
+#include "Elevator.h"
+#include "ElevatorViewModel.h"
+
+using namespace ElevatorClientUWP;\r
+\r
+using namespace std;\r
+using namespace Platform;\r
+using namespace Windows::ApplicationModel::Core;\r
+using namespace Windows::Foundation;\r
+using namespace Windows::Foundation::Collections;\r
+using namespace Windows::UI::Core;\r
+using namespace Windows::UI::Xaml;\r
+using namespace Windows::UI::Xaml::Controls;\r
+using namespace Windows::UI::Xaml::Controls::Primitives;\r
+using namespace Windows::UI::Xaml::Data;\r
+using namespace Windows::UI::Xaml::Input;\r
+using namespace Windows::UI::Xaml::Media;\r
+using namespace Windows::UI::Xaml::Navigation;
+
+// Callback from IPCAObserveResource().
+void IPCA_CALL ResourceChangeNotificationCallback(
+ IPCAStatus result,
+ void* context,
+ IPCAPropertyBagHandle propertyBagHandle)
+{
+ if (context)\r
+ {\r
+ Elevator^ dev = (reinterpret_cast<WeakReference*>(context))->Resolve<Elevator>();\r
+ if (dev)\r
+ {\r
+ dev->ResourceChangeNotificationCallback(result, propertyBagHandle);\r
+ }\r
+ }
+}
+
+void IPCA_CALL SetPropertiesCallback(
+ IPCAStatus result,
+ void* context,
+ IPCAPropertyBagHandle propertyBagHandle)
+{
+ if (context)\r
+ {\r
+ Elevator^ dev = (reinterpret_cast<WeakReference*>(context))->Resolve<Elevator>();\r
+ if (dev)\r
+ {\r
+ dev->SetPropertiesCallback(result, propertyBagHandle);\r
+ }\r
+ }
+}
+
+void IPCA_CALL AuthCompletionCallback(IPCAStatus completionStatus, void* context)
+{
+ if (context)\r
+ {\r
+ Elevator^ dev = (reinterpret_cast<WeakReference*>(context))->Resolve<Elevator>();\r
+ if (dev)\r
+ {\r
+ dev->AuthCompletionCallback(completionStatus);\r
+ }\r
+ }
+}
+
+Elevator::Elevator() :
+ m_initialized(false),
+ m_dispatcher(nullptr),
+ m_ipcaAppHandle(nullptr),
+ m_observeHandle(nullptr),
+ m_deviceName(nullptr),
+ m_deviceHandle(nullptr),
+ m_deviceInfo(nullptr),
+ m_platformInfo(nullptr),
+ m_requestedAccess(false),
+ m_requestAccessHandle(nullptr)
+{
+ m_thisWeakRef = new WeakReference(this);
+ m_dispatcher = CoreApplication::MainView->Dispatcher;
+}
+
+Elevator::~Elevator()
+{
+ StopObservation();
+
+ if (m_requestAccessHandle != nullptr)
+ {
+ IPCACloseHandle(m_requestAccessHandle, nullptr, nullptr);
+ m_requestAccessHandle = nullptr;
+ }
+
+ if (m_deviceHandle != nullptr)
+ {
+ IPCACloseDevice(m_deviceHandle);
+ m_deviceHandle = nullptr;
+ }
+
+ if (m_deviceInfo != nullptr)
+ {
+ IPCAFreeDeviceInfo(m_deviceInfo);
+ m_deviceInfo = nullptr;
+ }
+
+ if (m_platformInfo != nullptr)
+ {
+ IPCAFreePlatformInfo(m_platformInfo);
+ m_platformInfo = nullptr;
+ }
+}
+
+String^ Elevator::Name::get()
+{
+ String^ ret = m_deviceName;
+
+ if ((ret == nullptr) || ret->IsEmpty())\r
+ {\r
+ ret = Util::ConvertStrtoPlatformStr(m_deviceId.c_str());\r
+ }\r
+
+ return ret;
+}
+
+void Elevator::Name::set(String^ value)\r
+{\r
+ if (m_deviceName != value)\r
+ {\r
+ m_deviceName = value;\r
+ OnPropertyChanged("Name");\r
+ }\r
+}
+
+String^ Elevator::CurrentFloor::get()\r
+{\r
+ return m_curFloor;\r
+}\r
+\r
+void Elevator::CurrentFloor::set(String^ value)\r
+{\r
+ if (m_curFloor != value)\r
+ {\r
+ m_curFloor = value;\r
+ OnPropertyChanged("CurrentFloor");\r
+ }\r
+}
+
+void Elevator::OnPropertyChanged(String^ propertyName)\r
+{\r
+ m_dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler(\r
+ [this, propertyName]\r
+ {\r
+ PropertyChanged(this, ref new PropertyChangedEventArgs(propertyName));\r
+ }));\r
+}\r
+\r
+IPCAStatus Elevator::OpenDevice()
+{
+ if (m_deviceHandle != nullptr)
+ {
+ return IPCA_OK;
+ }
+ else
+ {
+ return IPCAOpenDevice(m_ipcaAppHandle, m_deviceId.c_str(), &m_deviceHandle);
+ }
+}\r
+\r
+void Elevator::UpdateDeviceInfo()\r
+{\r
+ IPCAStatus status;
+
+ if (!m_initialized)
+ {
+ return;
+ }
+
+ if (OpenDevice() != IPCA_OK)
+ {
+ return;
+ }
+
+ if (m_deviceInfo != nullptr)
+ {
+ IPCAFreeDeviceInfo(m_deviceInfo);
+ m_deviceInfo = nullptr;
+ }
+
+ status = IPCAGetDeviceInfo(m_deviceHandle, &m_deviceInfo);
+ if (IPCA_OK != status)
+ {
+ return;
+ }
+
+ Name = Util::ConvertStrtoPlatformStr(m_deviceInfo->deviceName);\r
+}\r
+\r
+void Elevator::UpdatePlatformInfo()\r
+{\r
+ IPCAStatus status;
+
+ if (!m_initialized)
+ {
+ return;
+ }
+
+ if (OpenDevice() != IPCA_OK)
+ {
+ return;
+ }
+
+ if (m_platformInfo != nullptr)
+ {
+ IPCAFreePlatformInfo(m_platformInfo);
+ m_platformInfo = nullptr;
+ }
+
+ status = IPCAGetPlatformInfo(m_deviceHandle, &m_platformInfo);
+ if (IPCA_OK != status)
+ {
+ return;
+ }\r
+}\r
+\r
+void Elevator::UpdateResourceInfo()\r
+{\r
+ IPCAStatus status;
+
+ ResourceList emptyResourceList;
+
+ if (!m_initialized)
+ {
+ return;
+ }
+
+ if (OpenDevice() != IPCA_OK)
+ {
+ return;
+ }
+
+ char** resourcePathList;
+ size_t resourceListCount;
+ status = IPCAGetResources(m_deviceHandle,
+ nullptr, nullptr, &resourcePathList, &resourceListCount);
+ if (IPCA_OK != status)
+ {
+ return;
+ }
+
+ m_resourceList.clear();
+ for (size_t i = 0; i < resourceListCount; i++)
+ {
+ char** resourceTypes;
+ size_t resourceTypeCount;
+ status = IPCAGetResourceTypes(m_deviceHandle,
+ resourcePathList[i], &resourceTypes, &resourceTypeCount);
+ if (IPCA_OK == status)
+ {
+ for (size_t j = 0; j < resourceTypeCount; j++)
+ {
+ m_resourceList[resourcePathList[i]].push_back(resourceTypes[j]);
+ }
+ IPCAFreeStringArray(resourceTypes, resourceTypeCount);
+ }
+ else
+ {
+ // Log failure
+ }
+ }
+
+ IPCAFreeStringArray(resourcePathList, resourceListCount);\r
+}
+
+bool Elevator::Init(IPCAAppHandle appHandle, Platform::String^ name, std::string id)\r
+{\r
+ if (!m_initialized)\r
+ {\r
+ m_ipcaAppHandle = appHandle;\r
+ m_deviceName = name;\r
+ m_deviceId = id;\r
+ m_initialized = true;\r
+ }\r
+\r
+ return m_initialized;\r
+}\r
+\r
+void Elevator::StartObservation()\r
+{\r
+ if (OpenDevice() != IPCA_OK)\r
+ {\r
+ throw ref new FailureException("Failed to open device");\r
+ }\r
+\r
+ StopObservation();
+
+ if (IPCAObserveResource(
+ m_deviceHandle,
+ &::ResourceChangeNotificationCallback,
+ m_thisWeakRef,
+ "/ipca/sample/elevator",
+ nullptr,
+ &m_observeHandle) != IPCA_OK)\r
+ {\r
+ throw ref new FailureException("IPCAObserveResource failed.");\r
+ }\r
+}\r
+\r
+void Elevator::StopObservation()\r
+{\r
+ if (m_observeHandle != nullptr)
+ {
+ IPCACloseHandle(m_observeHandle, nullptr, nullptr);
+ m_observeHandle = nullptr;
+ }\r
+}\r
+\r
+void Elevator::ResourceChangeNotificationCallback(IPCAStatus result,\r
+ IPCAPropertyBagHandle propertyBagHandle)\r
+{\r
+ int observedCurrentFloor = -1;
+
+ if (result == IPCA_ACCESS_DENIED)
+ {
+ std::lock_guard<std::mutex> lock(m_requestAccessMutex);
+ if (!m_requestedAccess)
+ {
+ if (m_requestAccessHandle != nullptr)
+ {
+ IPCACloseHandle(m_requestAccessHandle, nullptr, nullptr);
+ m_requestAccessHandle = nullptr;
+ }
+
+ IPCAStatus reqResult = IPCARequestAccess(
+ m_deviceHandle,
+ nullptr,
+ &::AuthCompletionCallback,
+ m_thisWeakRef,
+ &m_requestAccessHandle);
+ if (reqResult == IPCA_OK)
+ {
+ m_requestedAccess = true;
+ }
+ }
+ return;
+ }
+ else if ((result != IPCA_OK) && (result != IPCA_DEVICE_APPEAR_OFFLINE))
+ {
+ String^ err = "Failure in Resource Change Notification. result=" +
+ static_cast<int>(result).ToString();
+ Util::ShowErrorMsg(m_dispatcher, err);
+ return;
+ }
+
+ if (IPCAPropertyBagGetValueInt(propertyBagHandle, "x.org.iotivity.CurrentFloor",
+ &observedCurrentFloor) == IPCA_OK)
+ {
+ CurrentFloor = observedCurrentFloor.ToString();
+ }\r
+}\r
+\r
+void Elevator::AuthCompletionCallback(IPCAStatus completionStatus)\r
+{\r
+ if ((completionStatus != IPCA_SECURITY_UPDATE_REQUEST_FINISHED) &&
+ (completionStatus != IPCA_DEVICE_APPEAR_OFFLINE))
+ {
+ std::lock_guard<std::mutex> lock(m_requestAccessMutex);
+ // Reset requested access to enable request access again.
+ m_requestedAccess = false;
+
+ String^ err = "Failure in Auth Callback. result=" +
+ static_cast<int>(completionStatus).ToString();
+ Util::ShowErrorMsg(m_dispatcher, err);
+ OnAuthFailure();
+ return;
+ }\r
+\r
+ // Restart observation\r
+ StartObservation();\r
+}\r
+\r
+void Elevator::SetPropertiesCallback(IPCAStatus result, IPCAPropertyBagHandle propertyBagHandle)\r
+{\r
+ if ((result != IPCA_OK) && (result != IPCA_DEVICE_APPEAR_OFFLINE))
+ {
+ String^ err = "Failure trying to Set Properties. result=" +
+ static_cast<int>(result).ToString();
+ Util::ShowErrorMsg(m_dispatcher, err);
+ }\r
+}\r
+\r
+void Elevator::OnUpdatedInfo()\r
+{\r
+ std::lock_guard<std::mutex> lock(m_deviceMutex);\r
+ UpdateDeviceInfo();\r
+ UpdatePlatformInfo();\r
+ UpdateResourceInfo();\r
+}\r
+\r
+IPCADeviceInfo* Elevator::GetDeviceInfo()
+{
+ std::lock_guard<std::mutex> lock(m_deviceMutex);
+ if (!m_initialized)
+ {
+ return nullptr;
+ }
+
+ return m_deviceInfo;
+}
+
+IPCAPlatformInfo* Elevator::GetPlatformInfo()
+{
+ std::lock_guard<std::mutex> lock(m_deviceMutex);
+ if (!m_initialized)
+ {
+ return nullptr;
+ }
+
+ return m_platformInfo;
+}
+
+ResourceList Elevator::GetResourceInfo()
+{
+ std::lock_guard<std::mutex> lock(m_deviceMutex);
+ ResourceList emptyResourceList;
+
+ if (!m_initialized)
+ {
+ return emptyResourceList;
+ }
+
+ return m_resourceList;
+}\r
+\r
+bool Elevator::SetTargetFloor(int floor)\r
+{\r
+ if (OpenDevice() != IPCA_OK)
+ {
+ return false;
+ }\r
+\r
+ bool ret = false;\r
+ IPCAPropertyBagHandle propertyBagHandle;
+ IPCAStatus status = IPCAPropertyBagCreate(&propertyBagHandle);
+ if (IPCA_OK == status)
+ {
+ status = IPCAPropertyBagSetValueInt(propertyBagHandle,
+ "x.org.iotivity.TargetFloor", floor);
+
+ if (IPCA_OK == status)
+ {
+ status = IPCASetProperties(m_deviceHandle,
+ &::SetPropertiesCallback,
+ m_thisWeakRef,
+ "/ipca/sample/elevator",
+ "x.org.iotivity.sample.elevator",
+ nullptr,
+ propertyBagHandle,
+ nullptr);
+
+ if (IPCA_OK == status)
+ {
+ ret = true;
+ }
+ }
+ IPCAPropertyBagDestroy(propertyBagHandle);
+ }\r
+\r
+ return ret;\r
+}
--- /dev/null
+/* *****************************************************************
+ *
+ * Copyright 2017 Microsoft
+ *
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+#pragma once
+
+#include <mutex>
+#include <array>
+#include <string>
+#include <vector>
+#include <iostream>
+#include <map>
+#include <thread>
+#include <chrono>
+#include <memory>
+#include <functional>
+
+#include "ipca.h"
+
+namespace ElevatorClientUWP
+{
+ public delegate void AuthFailure();
+ // Key of map is resource path. Value is array of resource types.
+ typedef std::map<std::string, std::vector<std::string>> ResourceList;
+
+ /**
+ * Each Elevator object represents a device discovered by IPCA.
+ */
+ [Windows::UI::Xaml::Data::Bindable]
+ public ref class Elevator sealed : Windows::UI::Xaml::Data::INotifyPropertyChanged
+ {
+ public:
+ Elevator();
+ virtual ~Elevator();
+ internal:
+ bool Init(IPCAAppHandle appHandle, Platform::String^ name, std::string id);
+ void StartObservation();
+ void StopObservation();
+ void ResourceChangeNotificationCallback(IPCAStatus result, IPCAPropertyBagHandle propertyBagHandle);
+ void SetPropertiesCallback(IPCAStatus result, IPCAPropertyBagHandle propertyBagHandle);
+ void AuthCompletionCallback(IPCAStatus completionStatus);
+ void OnUpdatedInfo();
+
+ IPCADeviceInfo* GetDeviceInfo();
+ IPCAPlatformInfo* GetPlatformInfo();
+ ResourceList GetResourceInfo();
+
+ bool SetTargetFloor(int floor);
+
+ public:
+ virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler^ PropertyChanged;
+ event AuthFailure^ OnAuthFailure;
+
+ property Platform::String^ Name\r
+ {\r
+ Platform::String^ get();\r
+ void set(Platform::String^ value);\r
+ }
+
+ property Platform::String^ CurrentFloor\r
+ {\r
+ Platform::String^ get();\r
+ void set(Platform::String^ value);\r
+ }
+
+ private:
+ void OnPropertyChanged(Platform::String^ propertyName);
+ IPCAStatus OpenDevice();
+ void UpdateDeviceInfo();
+ void UpdatePlatformInfo();
+ void UpdateResourceInfo();
+
+ private:
+ Platform::WeakReference* m_thisWeakRef;
+ Windows::UI::Core::CoreDispatcher^ m_dispatcher;
+ bool m_initialized;
+ Platform::String^ m_deviceName;
+ Platform::String^ m_curFloor;
+ IPCAAppHandle m_ipcaAppHandle;
+ IPCAHandle m_observeHandle;
+ IPCAHandle m_requestAccessHandle;
+ std::string m_deviceId;
+ std::string m_hostAddress;
+ IPCADeviceHandle m_deviceHandle; // from IPCAOpenDevice();
+ IPCADeviceInfo* m_deviceInfo; // valid between IPCAOpenDevice() and IPCACloseDevice().
+ IPCAPlatformInfo* m_platformInfo; // valid between IPCAOpenDevice() and IPCACloseDevice().
+ ResourceList m_resourceList;
+ std::mutex m_deviceMutex;
+ bool m_requestedAccess;
+ std::mutex m_requestAccessMutex;
+ };
+}
--- /dev/null
+Microsoft Visual Studio Solution File, Format Version 12.00\r
+# Visual Studio 14\r
+VisualStudioVersion = 14.0.25420.1\r
+MinimumVisualStudioVersion = 10.0.40219.1\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ElevatorClientUWP", "ElevatorClientUWP.vcxproj", "{D30AE502-76EE-4061-87A3-C7142283D03E}"\r
+EndProject\r
+Global\r
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution\r
+ Debug|ARM = Debug|ARM\r
+ Debug|x64 = Debug|x64\r
+ Debug|x86 = Debug|x86\r
+ Release|ARM = Release|ARM\r
+ Release|x64 = Release|x64\r
+ Release|x86 = Release|x86\r
+ EndGlobalSection\r
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution\r
+ {D30AE502-76EE-4061-87A3-C7142283D03E}.Debug|ARM.ActiveCfg = Debug|ARM\r
+ {D30AE502-76EE-4061-87A3-C7142283D03E}.Debug|ARM.Build.0 = Debug|ARM\r
+ {D30AE502-76EE-4061-87A3-C7142283D03E}.Debug|ARM.Deploy.0 = Debug|ARM\r
+ {D30AE502-76EE-4061-87A3-C7142283D03E}.Debug|x64.ActiveCfg = Debug|x64\r
+ {D30AE502-76EE-4061-87A3-C7142283D03E}.Debug|x64.Build.0 = Debug|x64\r
+ {D30AE502-76EE-4061-87A3-C7142283D03E}.Debug|x64.Deploy.0 = Debug|x64\r
+ {D30AE502-76EE-4061-87A3-C7142283D03E}.Debug|x86.ActiveCfg = Debug|Win32\r
+ {D30AE502-76EE-4061-87A3-C7142283D03E}.Debug|x86.Build.0 = Debug|Win32\r
+ {D30AE502-76EE-4061-87A3-C7142283D03E}.Debug|x86.Deploy.0 = Debug|Win32\r
+ {D30AE502-76EE-4061-87A3-C7142283D03E}.Release|ARM.ActiveCfg = Release|ARM\r
+ {D30AE502-76EE-4061-87A3-C7142283D03E}.Release|ARM.Build.0 = Release|ARM\r
+ {D30AE502-76EE-4061-87A3-C7142283D03E}.Release|ARM.Deploy.0 = Release|ARM\r
+ {D30AE502-76EE-4061-87A3-C7142283D03E}.Release|x64.ActiveCfg = Release|x64\r
+ {D30AE502-76EE-4061-87A3-C7142283D03E}.Release|x64.Build.0 = Release|x64\r
+ {D30AE502-76EE-4061-87A3-C7142283D03E}.Release|x64.Deploy.0 = Release|x64\r
+ {D30AE502-76EE-4061-87A3-C7142283D03E}.Release|x86.ActiveCfg = Release|Win32\r
+ {D30AE502-76EE-4061-87A3-C7142283D03E}.Release|x86.Build.0 = Release|Win32\r
+ {D30AE502-76EE-4061-87A3-C7142283D03E}.Release|x86.Deploy.0 = Release|Win32\r
+ EndGlobalSection\r
+ GlobalSection(SolutionProperties) = preSolution\r
+ HideSolutionNode = FALSE\r
+ EndGlobalSection\r
+EndGlobal\r
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+ <PropertyGroup Label="Globals">\r
+ <ProjectGuid>{d30ae502-76ee-4061-87a3-c7142283d03e}</ProjectGuid>\r
+ <RootNamespace>ElevatorClientUWP</RootNamespace>\r
+ <DefaultLanguage>en-US</DefaultLanguage>\r
+ <MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>\r
+ <AppContainerApplication>true</AppContainerApplication>\r
+ <ApplicationType>Windows Store</ApplicationType>\r
+ <WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>\r
+ <WindowsTargetPlatformMinVersion>10.0.10586.0</WindowsTargetPlatformMinVersion>\r
+ <ApplicationTypeRevision>10.0</ApplicationTypeRevision>\r
+ <PackageCertificateThumbprint>1D05309EEC0622608A78ABCCA0E20C7528C4C79E</PackageCertificateThumbprint>\r
+ </PropertyGroup>\r
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
+ <ItemGroup Label="ProjectConfigurations">\r
+ <ProjectConfiguration Include="Debug|ARM">\r
+ <Configuration>Debug</Configuration>\r
+ <Platform>ARM</Platform>\r
+ </ProjectConfiguration>\r
+ <ProjectConfiguration Include="Debug|Win32">\r
+ <Configuration>Debug</Configuration>\r
+ <Platform>Win32</Platform>\r
+ </ProjectConfiguration>\r
+ <ProjectConfiguration Include="Debug|x64">\r
+ <Configuration>Debug</Configuration>\r
+ <Platform>x64</Platform>\r
+ </ProjectConfiguration>\r
+ <ProjectConfiguration Include="Release|ARM">\r
+ <Configuration>Release</Configuration>\r
+ <Platform>ARM</Platform>\r
+ </ProjectConfiguration>\r
+ <ProjectConfiguration Include="Release|Win32">\r
+ <Configuration>Release</Configuration>\r
+ <Platform>Win32</Platform>\r
+ </ProjectConfiguration>\r
+ <ProjectConfiguration Include="Release|x64">\r
+ <Configuration>Release</Configuration>\r
+ <Platform>x64</Platform>\r
+ </ProjectConfiguration>\r
+ </ItemGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">\r
+ <ConfigurationType>Application</ConfigurationType>\r
+ <UseDebugLibraries>true</UseDebugLibraries>\r
+ <PlatformToolset>v140</PlatformToolset>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">\r
+ <ConfigurationType>Application</ConfigurationType>\r
+ <UseDebugLibraries>true</UseDebugLibraries>\r
+ <PlatformToolset>v140</PlatformToolset>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">\r
+ <ConfigurationType>Application</ConfigurationType>\r
+ <UseDebugLibraries>true</UseDebugLibraries>\r
+ <PlatformToolset>v140</PlatformToolset>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">\r
+ <ConfigurationType>Application</ConfigurationType>\r
+ <UseDebugLibraries>false</UseDebugLibraries>\r
+ <WholeProgramOptimization>true</WholeProgramOptimization>\r
+ <PlatformToolset>v140</PlatformToolset>\r
+ <UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">\r
+ <ConfigurationType>Application</ConfigurationType>\r
+ <UseDebugLibraries>false</UseDebugLibraries>\r
+ <WholeProgramOptimization>true</WholeProgramOptimization>\r
+ <PlatformToolset>v140</PlatformToolset>\r
+ <UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">\r
+ <ConfigurationType>Application</ConfigurationType>\r
+ <UseDebugLibraries>false</UseDebugLibraries>\r
+ <WholeProgramOptimization>true</WholeProgramOptimization>\r
+ <PlatformToolset>v140</PlatformToolset>\r
+ <UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>\r
+ </PropertyGroup>\r
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
+ <ImportGroup Label="ExtensionSettings">\r
+ </ImportGroup>\r
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+ </ImportGroup>\r
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+ </ImportGroup>\r
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">\r
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+ </ImportGroup>\r
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">\r
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+ </ImportGroup>\r
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">\r
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+ </ImportGroup>\r
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">\r
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+ </ImportGroup>\r
+ <PropertyGroup Condition="'$(Platform)'=='x64'">\r
+ <PackageCertificateKeyFile>ElevatorClientUWP_TemporaryKey.pfx</PackageCertificateKeyFile>\r
+ <AppxAutoIncrementPackageRevision>False</AppxAutoIncrementPackageRevision>\r
+ <AppxBundle>Always</AppxBundle>\r
+ <AppxBundlePlatforms>x64</AppxBundlePlatforms>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Platform)'=='Win32'">\r
+ <PackageCertificateKeyFile>ElevatorClientUWP_TemporaryKey.pfx</PackageCertificateKeyFile>\r
+ <AppxAutoIncrementPackageRevision>False</AppxAutoIncrementPackageRevision>\r
+ <AppxBundle>Always</AppxBundle>\r
+ <AppxBundlePlatforms>x86</AppxBundlePlatforms>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Platform)'=='ARM'">\r
+ <PackageCertificateKeyFile>ElevatorClientUWP_TemporaryKey.pfx</PackageCertificateKeyFile>\r
+ <AppxAutoIncrementPackageRevision>False</AppxAutoIncrementPackageRevision>\r
+ <AppxBundle>Always</AppxBundle>\r
+ <AppxBundlePlatforms>arm</AppxBundlePlatforms>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
+ <IncludePath>$(ProjectDir)\..\..\inc;$(ProjectDir)\..\..\..\c_common;$(IncludePath)</IncludePath>\r
+ <OutDir>$(SolutionDir)Out\$(Configuration)\$(PlatformTarget)\$(MSBuildProjectName)\</OutDir>\r
+ <IntDir>$(PlatformTarget)\$(Configuration)\</IntDir>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
+ <IncludePath>$(ProjectDir)\..\..\inc;$(ProjectDir)\..\..\..\c_common;$(IncludePath)</IncludePath>\r
+ <OutDir>$(SolutionDir)Out\$(Configuration)\$(PlatformTarget)\$(MSBuildProjectName)\</OutDir>\r
+ <IntDir>$(PlatformTarget)\$(Configuration)\</IntDir>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">\r
+ <IncludePath>$(ProjectDir)\..\..\inc;$(ProjectDir)\..\..\..\c_common;$(IncludePath)</IncludePath>\r
+ <OutDir>$(SolutionDir)Out\$(Configuration)\$(PlatformTarget)\$(MSBuildProjectName)\</OutDir>\r
+ <IntDir>$(PlatformTarget)\$(Configuration)\</IntDir>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">\r
+ <IncludePath>$(ProjectDir)\..\..\inc;$(ProjectDir)\..\..\..\c_common;$(IncludePath)</IncludePath>\r
+ <OutDir>$(SolutionDir)Out\$(Configuration)\$(PlatformTarget)\$(MSBuildProjectName)\</OutDir>\r
+ <IntDir>$(PlatformTarget)\$(Configuration)\</IntDir>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">\r
+ <IncludePath>$(ProjectDir)\..\..\inc;$(ProjectDir)\..\..\..\c_common;$(IncludePath)</IncludePath>\r
+ <OutDir>$(SolutionDir)Out\$(Configuration)\$(PlatformTarget)\$(MSBuildProjectName)\</OutDir>\r
+ <IntDir>$(PlatformTarget)\$(Configuration)\</IntDir>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">\r
+ <IncludePath>$(ProjectDir)\..\..\inc;$(ProjectDir)\..\..\..\c_common;$(IncludePath)</IncludePath>\r
+ <OutDir>$(SolutionDir)Out\$(Configuration)\$(PlatformTarget)\$(MSBuildProjectName)\</OutDir>\r
+ <IntDir>$(PlatformTarget)\$(Configuration)\</IntDir>\r
+ </PropertyGroup>\r
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">\r
+ <ClCompile>\r
+ <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>\r
+ <DisableSpecificWarnings>4453;28204</DisableSpecificWarnings>\r
+ </ClCompile>\r
+ <Link>\r
+ <AdditionalDependencies>WindowsApp.lib;ipca.lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+ </Link>\r
+ </ItemDefinitionGroup>\r
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">\r
+ <ClCompile>\r
+ <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>\r
+ <DisableSpecificWarnings>4453;28204</DisableSpecificWarnings>\r
+ </ClCompile>\r
+ <Link>\r
+ <AdditionalDependencies>WindowsApp.lib;ipca.lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+ </Link>\r
+ </ItemDefinitionGroup>\r
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
+ <ClCompile>\r
+ <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>\r
+ <DisableSpecificWarnings>4453;28204</DisableSpecificWarnings>\r
+ </ClCompile>\r
+ <Link>\r
+ <AdditionalDependencies>WindowsApp.lib;ipca.lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+ </Link>\r
+ </ItemDefinitionGroup>\r
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
+ <ClCompile>\r
+ <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>\r
+ <DisableSpecificWarnings>4453;28204</DisableSpecificWarnings>\r
+ </ClCompile>\r
+ <Link>\r
+ <AdditionalDependencies>WindowsApp.lib;ipca.lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+ </Link>\r
+ </ItemDefinitionGroup>\r
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">\r
+ <ClCompile>\r
+ <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>\r
+ <DisableSpecificWarnings>4453;28204</DisableSpecificWarnings>\r
+ </ClCompile>\r
+ <Link>\r
+ <AdditionalDependencies>WindowsApp.lib;ipca.lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+ </Link>\r
+ </ItemDefinitionGroup>\r
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">\r
+ <ClCompile>\r
+ <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>\r
+ <DisableSpecificWarnings>4453;28204</DisableSpecificWarnings>\r
+ </ClCompile>\r
+ <Link>\r
+ <AdditionalDependencies>WindowsApp.lib;ipca.lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+ </Link>\r
+ </ItemDefinitionGroup>\r
+ <ItemGroup>\r
+ <ClInclude Include="ElevatorDiscovery.h" />\r
+ <ClInclude Include="ElevatorViewModel.h" />\r
+ <ClInclude Include="Elevator.h" />\r
+ <ClInclude Include="pch.h" />\r
+ <ClInclude Include="App.xaml.h">\r
+ <DependentUpon>App.xaml</DependentUpon>\r
+ </ClInclude>\r
+ <ClInclude Include="MainPage.xaml.h">\r
+ <DependentUpon>MainPage.xaml</DependentUpon>\r
+ </ClInclude>\r
+ <ClInclude Include="Util.h" />\r
+ </ItemGroup>\r
+ <ItemGroup>\r
+ <ApplicationDefinition Include="App.xaml">\r
+ <SubType>Designer</SubType>\r
+ </ApplicationDefinition>\r
+ <Page Include="MainPage.xaml">\r
+ <SubType>Designer</SubType>\r
+ </Page>\r
+ </ItemGroup>\r
+ <ItemGroup>\r
+ <AppxManifest Include="Package.appxmanifest">\r
+ <SubType>Designer</SubType>\r
+ </AppxManifest>\r
+ <None Include="ElevatorClientUWP_TemporaryKey.pfx" />\r
+ </ItemGroup>\r
+ <ItemGroup>\r
+ <Image Include="Assets\LockScreenLogo.scale-200.png" />\r
+ <Image Include="Assets\SplashScreen.scale-200.png" />\r
+ <Image Include="Assets\Square150x150Logo.scale-200.png" />\r
+ <Image Include="Assets\Square44x44Logo.scale-200.png" />\r
+ <Image Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png" />\r
+ <Image Include="Assets\StoreLogo.png" />\r
+ <Image Include="Assets\Wide310x150Logo.scale-200.png" />\r
+ </ItemGroup>\r
+ <ItemGroup>\r
+ <ClCompile Include="App.xaml.cpp">\r
+ <DependentUpon>App.xaml</DependentUpon>\r
+ </ClCompile>\r
+ <ClCompile Include="ElevatorDiscovery.cpp" />\r
+ <ClCompile Include="ElevatorViewModel.cpp" />\r
+ <ClCompile Include="MainPage.xaml.cpp">\r
+ <DependentUpon>MainPage.xaml</DependentUpon>\r
+ </ClCompile>\r
+ <ClCompile Include="Elevator.cpp" />\r
+ <ClCompile Include="pch.cpp">\r
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>\r
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>\r
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">Create</PrecompiledHeader>\r
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">Create</PrecompiledHeader>\r
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>\r
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>\r
+ </ClCompile>\r
+ <ClCompile Include="Util.cpp" />\r
+ </ItemGroup>\r
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
+ <ImportGroup Label="ExtensionTargets">\r
+ </ImportGroup>\r
+ <Import Project="$(ProjectDir)IPCALibs.targets" />\r
+</Project>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+ <ItemGroup>\r
+ <Filter Include="Common">\r
+ <UniqueIdentifier>d30ae502-76ee-4061-87a3-c7142283d03e</UniqueIdentifier>\r
+ </Filter>\r
+ <Filter Include="Assets">\r
+ <UniqueIdentifier>12bbc0a4-0b14-4fc7-bc95-3eef4bdbe84e</UniqueIdentifier>\r
+ <Extensions>bmp;fbx;gif;jpg;jpeg;tga;tiff;tif;png</Extensions>\r
+ </Filter>\r
+ </ItemGroup>\r
+ <ItemGroup>\r
+ <ApplicationDefinition Include="App.xaml" />\r
+ </ItemGroup>\r
+ <ItemGroup>\r
+ <ClCompile Include="App.xaml.cpp" />\r
+ <ClCompile Include="MainPage.xaml.cpp" />\r
+ <ClCompile Include="pch.cpp" />\r
+ <ClCompile Include="ElevatorViewModel.cpp" />\r
+ <ClCompile Include="ElevatorDiscovery.cpp" />\r
+ <ClCompile Include="Elevator.cpp" />\r
+ <ClCompile Include="Util.cpp" />\r
+ </ItemGroup>\r
+ <ItemGroup>\r
+ <ClInclude Include="pch.h" />\r
+ <ClInclude Include="App.xaml.h" />\r
+ <ClInclude Include="MainPage.xaml.h" />\r
+ <ClInclude Include="ElevatorViewModel.h" />\r
+ <ClInclude Include="ElevatorDiscovery.h" />\r
+ <ClInclude Include="Elevator.h" />\r
+ <ClInclude Include="Util.h" />\r
+ </ItemGroup>\r
+ <ItemGroup>\r
+ <Image Include="Assets\LockScreenLogo.scale-200.png">\r
+ <Filter>Assets</Filter>\r
+ </Image>\r
+ <Image Include="Assets\SplashScreen.scale-200.png">\r
+ <Filter>Assets</Filter>\r
+ </Image>\r
+ <Image Include="Assets\Square150x150Logo.scale-200.png">\r
+ <Filter>Assets</Filter>\r
+ </Image>\r
+ <Image Include="Assets\Square44x44Logo.scale-200.png">\r
+ <Filter>Assets</Filter>\r
+ </Image>\r
+ <Image Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png">\r
+ <Filter>Assets</Filter>\r
+ </Image>\r
+ <Image Include="Assets\StoreLogo.png">\r
+ <Filter>Assets</Filter>\r
+ </Image>\r
+ <Image Include="Assets\Wide310x150Logo.scale-200.png">\r
+ <Filter>Assets</Filter>\r
+ </Image>\r
+ </ItemGroup>\r
+ <ItemGroup>\r
+ <AppxManifest Include="Package.appxmanifest" />\r
+ </ItemGroup>\r
+ <ItemGroup>\r
+ <None Include="ElevatorClientUWP_TemporaryKey.pfx" />\r
+ <None Include="@(NativeLibs)" />\r
+ <None Include="@(NativeLibs)" />\r
+ <None Include="@(NativeLibs)" />\r
+ <None Include="@(NativeLibs)" />\r
+ <None Include="@(NativeLibs)" />\r
+ <None Include="@(NativeLibs)" />\r
+ <None Include="@(NativeLibs)" />\r
+ <None Include="@(NativeLibs)" />\r
+ <None Include="@(NativeLibs)" />\r
+ <None Include="@(NativeLibs)" />\r
+ </ItemGroup>\r
+ <ItemGroup>\r
+ <Page Include="MainPage.xaml" />\r
+ </ItemGroup>\r
+</Project>
\ No newline at end of file
--- /dev/null
+/* *****************************************************************
+*
+* Copyright 2017 Microsoft
+*
+*
+* 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.
+*
+******************************************************************/\r
+\r
+#include "pch.h"\r
+#include "ElevatorDiscovery.h"\r
+\r
+#include "iotivity_config.h"
+
+#include <mutex>
+#include <array>
+#include <string>
+#include <vector>
+#include <iostream>
+#include <map>
+#include <thread>
+#include <chrono>
+#include <condition_variable>
+#include <climits>
+#include <sstream>
+
+#include "ipca.h"
+#include "Elevator.h"\r
+#include "ElevatorViewModel.h"\r
+\r
+using namespace ElevatorClientUWP;\r
+\r
+using namespace concurrency;\r
+\r
+using namespace std;\r
+using namespace Platform;\r
+using namespace Platform::Collections;\r
+using namespace Windows::ApplicationModel::Core;\r
+using namespace Windows::Foundation;\r
+using namespace Windows::Foundation::Collections;\r
+using namespace Windows::UI::Core;\r
+using namespace Windows::UI::Xaml;\r
+using namespace Windows::UI::Xaml::Controls;\r
+using namespace Windows::UI::Xaml::Controls::Primitives;\r
+using namespace Windows::UI::Xaml::Data;\r
+using namespace Windows::UI::Xaml::Input;\r
+using namespace Windows::UI::Xaml::Media;\r
+using namespace Windows::UI::Xaml::Navigation;\r
+\r
+#define TIMEOUT_MS 3000\r
+\r
+String^ ElevatorDiscovery::guidStr = "{ab2593e4-2994-401e-a526-c92fd9b71414}";\r
+\r
+static void IPCA_CALL DiscoverDevicesCallback(
+ void* context,
+ IPCADeviceStatus deviceStatus,
+ const IPCADiscoveredDeviceInfo* deviceInfo)\r
+{\r
+ if (context)\r
+ {\r
+ ElevatorDiscovery^ elvDisc = \r
+ (reinterpret_cast<WeakReference*>(context))->Resolve<ElevatorDiscovery>();\r
+ if (elvDisc)\r
+ {\r
+ elvDisc->DiscoverDevicesCallback(deviceStatus, deviceInfo);\r
+ }\r
+ }\r
+}\r
+\r
+static IPCAStatus IPCA_CALL PwdInputCallback(
+ void* context,
+ const IPCADeviceInfo* deviceInformation,
+ const IPCAPlatformInfo* platformInformation,
+ IPCAOwnershipTransferType type,
+ char* passwordBuffer,
+ size_t passwordBufferSize)
+{
+ if (context)\r
+ {\r
+ ElevatorDiscovery^ elvDisc =\r
+ (reinterpret_cast<WeakReference*>(context))->Resolve<ElevatorDiscovery>();\r
+ if (elvDisc)\r
+ {\r
+ return elvDisc->PwdInputCallback(deviceInformation, platformInformation, type,\r
+ passwordBuffer, passwordBufferSize);\r
+ }\r
+ }
+
+ // If reached here means context is either null or wrong type
+ return IPCA_INVALID_ARGUMENT;
+}
+
+static IPCAStatus IPCA_CALL PwdDisplayCallback(
+ void* context,
+ const IPCADeviceInfo* deviceInformation,
+ const IPCAPlatformInfo* platformInformation,
+ IPCAOwnershipTransferType type,
+ const char* password)
+{
+ if (context)\r
+ {\r
+ ElevatorDiscovery^ elvDisc =\r
+ (reinterpret_cast<WeakReference*>(context))->Resolve<ElevatorDiscovery>();\r
+ if (elvDisc)\r
+ {\r
+ return elvDisc->PwdDisplayCallback(deviceInformation, platformInformation, type, password);\r
+ }\r
+ }
+
+ // If reached here means context is either null or wrong type
+ return IPCA_INVALID_ARGUMENT;
+}\r
+\r
+ElevatorDiscovery::ElevatorDiscovery() :\r
+ m_ipcaAppHandle(nullptr),\r
+ m_deviceHandle(nullptr),\r
+ m_discoverDeviceHandle(nullptr),\r
+ m_deviceDiscoveryHandle(nullptr),\r
+ m_targetElevatorDiscovered(false),\r
+ m_currentFloor(0)\r
+{\r
+ m_thisWeakRef = new WeakReference(this);\r
+ m_dispatcher = CoreApplication::MainView->Dispatcher;\r
+\r
+ GUID guid;\r
+ HRESULT hr = IIDFromString(guidStr->Data(), &guid);\r
+ if (FAILED(hr))\r
+ {\r
+ if (hr == E_INVALIDARG)\r
+ {\r
+ throw ref new InvalidArgumentException("IIDFromString invalid arg");\r
+ }\r
+ else if (hr == E_OUTOFMEMORY)\r
+ {\r
+ throw ref new OutOfMemoryException("IIDFromString out of memory");\r
+ }\r
+ else\r
+ {\r
+ throw ref new FailureException("IIDFromString failed");\r
+ }\r
+ }\r
+\r
+ IPCAUuid appId;
+ byte* guidBytes = reinterpret_cast<byte*>(&guid);\r
+ for (int i = 0; i < 16; i++)\r
+ {\r
+ appId.uuid[i] = guidBytes[i];\r
+ }
+
+ IPCAAppInfo ipcaAppInfo = { appId, "ElevatorClientUWP", "1.0.0", "Microsoft" };
+
+ IPCAStatus status = IPCAOpen(&ipcaAppInfo, IPCA_VERSION_1, &m_ipcaAppHandle);
+ if (status != IPCA_OK)
+ {
+ String^ err = "IPCAOpen() Failed. Status: " + static_cast<int>(status).ToString();
+ throw ref new FailureException(err);
+ }\r
+\r
+ status = IPCASetPasswordCallbacks(m_ipcaAppHandle, &::PwdInputCallback,
+ &::PwdDisplayCallback, m_thisWeakRef);
+ if (status != IPCA_OK)
+ {
+ String^ err = "IPCASetPasswordCallbacks() Failed. Status: " + static_cast<int>(status).ToString();
+ throw ref new FailureException(err);
+ }\r
+\r
+ m_ElevatorList = ref new Map<String^, Elevator^>();\r
+\r
+ // Generate Password Input Content Dialog\r
+ TextBlock^ tbPwdInput = ref new TextBlock();\r
+ tbPwdInput->Text = "Please enter Elevator Password:";\r
+ tbPwdInput->Margin = Thickness(0, 5, 0, 0);\r
+\r
+ m_pbPwdInput = ref new PasswordBox();\r
+ m_pbPwdInput->PasswordRevealMode = PasswordRevealMode::Peek;\r
+ m_pbPwdInput->Margin = Thickness(10);\r
+ m_pbPwdInput->MinWidth = 250;\r
+\r
+ StackPanel^ spPwdInput = ref new StackPanel();\r
+ spPwdInput->Orientation = Orientation::Vertical;\r
+ spPwdInput->Children->Append(tbPwdInput);\r
+ spPwdInput->Children->Append(m_pbPwdInput);\r
+\r
+ m_passInputDiag = ref new ContentDialog();\r
+ m_passInputDiag->Title = "Authentication Needed";\r
+ m_passInputDiag->Content = spPwdInput;\r
+ m_passInputDiag->PrimaryButtonText = "Authenticate";\r
+ m_passInputDiag->SecondaryButtonText = "Cancel";\r
+\r
+ // Generate Password Display Content Dialog\r
+ TextBlock^ tbPwdDisplay = ref new TextBlock();\r
+ tbPwdDisplay->Text = "Elevator Password is:";\r
+ tbPwdDisplay->Margin = Thickness(0, 5, 0, 0);\r
+\r
+ m_txtPwdDisplay = ref new TextBox();\r
+ m_txtPwdDisplay->IsReadOnly = true;\r
+ m_txtPwdDisplay->Margin = 10;\r
+ m_txtPwdDisplay->BorderThickness = 0;\r
+\r
+ StackPanel^ spPwdDisplay = ref new StackPanel();\r
+ spPwdDisplay->Orientation = Orientation::Vertical;\r
+ spPwdDisplay->Children->Append(tbPwdDisplay);\r
+ spPwdDisplay->Children->Append(m_txtPwdDisplay);\r
+\r
+ m_passDisplayDiag = ref new ContentDialog();\r
+ m_passDisplayDiag->Title = "Authentication Info";\r
+ m_passDisplayDiag->Content = spPwdDisplay;\r
+ m_passDisplayDiag->PrimaryButtonText = "OK";\r
+}\r
+\r
+ElevatorDiscovery::~ElevatorDiscovery()\r
+{\r
+ StopElevatorDiscovery();
+
+ std::lock_guard<std::recursive_mutex> lock(m_ElevatorListMutex);
+ m_ElevatorList->Clear();
+
+ if (m_ipcaAppHandle != nullptr)
+ {
+ IPCAClose(m_ipcaAppHandle);
+ }\r
+\r
+ delete m_thisWeakRef;\r
+}\r
+\r
+bool ElevatorDiscovery::StartElevatorDiscovery()\r
+{\r
+ std::unique_lock<std::mutex> lock(m_deviceDiscoveryMutex);
+
+ if (!m_deviceDiscoveryHandle)
+ {
+ // Start the discovery if not already started
+
+ const char* resourceTypes[] = {
+ "x.org.iotivity.sample.elevator",
+ "x.org.iotivity.sample.elevator2",
+ "x.org.iotivity.sample.elevator3",
+ "x.org.iotivity.sample.elevator4",
+ };
+
+ const int NUMBER_OF_RESOURCE_TYPES = sizeof(resourceTypes) / sizeof(char*);
+
+ IPCAStatus status = IPCADiscoverDevices(
+ m_ipcaAppHandle,
+ &::DiscoverDevicesCallback,
+ m_thisWeakRef,
+ resourceTypes,
+ NUMBER_OF_RESOURCE_TYPES,
+ &m_deviceDiscoveryHandle);
+
+ if (status != IPCA_OK)
+ {
+ return false;
+ }
+ }\r
+\r
+ return true;\r
+}\r
+\r
+void ElevatorDiscovery::StopElevatorDiscovery()\r
+{\r
+ std::unique_lock<std::mutex> lock(m_deviceDiscoveryMutex);
+ // Stop discovery.
+ if (m_deviceDiscoveryHandle)
+ {
+ IPCACloseHandle(m_deviceDiscoveryHandle, nullptr, nullptr);
+ m_deviceDiscoveryHandle = nullptr;
+ }\r
+}\r
+\r
+void ElevatorDiscovery::DiscoverDevicesCallback(IPCADeviceStatus deviceStatus,\r
+ const IPCADiscoveredDeviceInfo* deviceInfo)\r
+{\r
+ std::lock_guard<std::recursive_mutex> lock(m_ElevatorListMutex);
+
+ std::string deviceIdStr = deviceInfo->deviceId;
+ String^ deviceId = Util::ConvertStrtoPlatformStr(deviceInfo->deviceId);
+ String^ deviceName = Util::ConvertStrtoPlatformStr(deviceInfo->deviceName);
+ std::vector<std::string> deviceUris;
+ for (size_t i = 0; i < deviceInfo->deviceUriCount; i++)
+ {
+ deviceUris.push_back(deviceInfo->deviceUris[i]);
+ }
+
+ Elevator^ elevator = nullptr;
+
+ try
+ {
+ elevator = m_ElevatorList->Lookup(deviceId);
+ }
+ catch (OutOfBoundsException^ e)
+ {
+ if (deviceStatus != IPCA_DEVICE_DISCOVERED)
+ {
+ // Log Unexpected discovery status
+ }
+ // Device not in the Map
+ elevator = ref new Elevator();
+ elevator->Init(m_ipcaAppHandle, deviceName, deviceIdStr);
+ m_ElevatorList->Insert(deviceId, elevator);
+ }
+
+ switch (deviceStatus)
+ {
+ case IPCA_DEVICE_DISCOVERED:
+ OnElevatorDiscovered(elevator);
+ break;
+ case IPCA_DEVICE_UPDATED_INFO:
+ elevator->OnUpdatedInfo();
+ break;
+ case IPCA_DEVICE_STOPPED_RESPONDING:
+ OnElevatorDisconnected(elevator);
+ m_ElevatorList->Remove(deviceId);
+ break;
+ default:
+ break;
+ }\r
+}\r
+\r
+IPCAStatus ElevatorDiscovery::PwdInputCallback(\r
+ const IPCADeviceInfo* deviceInformation,\r
+ const IPCAPlatformInfo* platformInformation,\r
+ IPCAOwnershipTransferType type,\r
+ char* passwordBuffer,\r
+ size_t passwordBufferSize)\r
+{\r
+ IAsyncOperation<ContentDialogResult>^ showPwdDiagAsync;\r
+ create_task(m_dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler(\r
+ [this, &showPwdDiagAsync]\r
+ {\r
+ m_pbPwdInput->Password = nullptr;\r
+ showPwdDiagAsync = m_passInputDiag->ShowAsync();\r
+ }))\r
+ ).get();\r
+\r
+ ContentDialogResult result = create_task(showPwdDiagAsync).get();\r
+ // Get the password\r
+ if (result == ContentDialogResult::Primary)\r
+ {\r
+ String^ pwd = nullptr;\r
+ create_task(m_dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler(\r
+ [this, &pwd]\r
+ {\r
+ pwd = m_pbPwdInput->Password;\r
+ }))\r
+ ).get();\r
+\r
+ std::string pwdStr = Util::ConvertWStrtoStr(pwd->Data());\r
+ if (pwdStr.empty() || ((pwdStr.length() + 1) > passwordBufferSize)) // +1 for null char\r
+ {\r
+ return IPCA_INVALID_ARGUMENT;\r
+ }\r
+\r
+ strcpy_s(passwordBuffer, passwordBufferSize, pwdStr.c_str());\r
+ }\r
+ else\r
+ {\r
+ return IPCA_INVALID_ARGUMENT;\r
+ }\r
+\r
+ return IPCA_OK;\r
+}\r
+\r
+IPCAStatus ElevatorDiscovery::PwdDisplayCallback(\r
+ const IPCADeviceInfo* deviceInformation,\r
+ const IPCAPlatformInfo* platformInformation,\r
+ IPCAOwnershipTransferType type,\r
+ const char* password)\r
+{\r
+ String^ pwd = Util::ConvertStrtoPlatformStr(password);\r
+ if (pwd == nullptr)\r
+ {\r
+ return IPCA_INVALID_ARGUMENT;\r
+ }\r
+\r
+ m_dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler(\r
+ [this, pwd]\r
+ {\r
+ m_txtPwdDisplay->Text = pwd;\r
+ m_passDisplayDiag->ShowAsync();\r
+ }\r
+ ));\r
+\r
+ return IPCA_OK;\r
+}\r
--- /dev/null
+/* *****************************************************************
+*
+* Copyright 2017 Microsoft
+*
+*
+* 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.
+*
+******************************************************************/\r
+\r
+#pragma once\r
+\r
+#include "ipca.h"\r
+#include "Elevator.h"\r
+\r
+namespace ElevatorClientUWP\r
+{\r
+ public delegate void ElevatorEvent(Elevator^ elevator);\r
+\r
+ public ref class ElevatorDiscovery sealed\r
+ {\r
+ public:\r
+ ElevatorDiscovery();\r
+ virtual ~ElevatorDiscovery();\r
+\r
+ bool StartElevatorDiscovery();\r
+ void StopElevatorDiscovery();\r
+\r
+ public:\r
+ event ElevatorEvent^ OnElevatorDiscovered;\r
+ event ElevatorEvent^ OnElevatorDisconnected;\r
+\r
+ internal:\r
+ void DiscoverDevicesCallback(
+ IPCADeviceStatus deviceStatus,
+ const IPCADiscoveredDeviceInfo* deviceInfo);\r
+\r
+ IPCAStatus PwdInputCallback(
+ const IPCADeviceInfo* deviceInformation,
+ const IPCAPlatformInfo* platformInformation,
+ IPCAOwnershipTransferType type,
+ char* passwordBuffer,
+ size_t passwordBufferSize);\r
+\r
+ IPCAStatus PwdDisplayCallback(
+ const IPCADeviceInfo* deviceInformation,
+ const IPCAPlatformInfo* platformInformation,
+ IPCAOwnershipTransferType type,
+ const char* password);\r
+\r
+ private:\r
+ static Platform::String^ guidStr;\r
+ \r
+ Platform::WeakReference* m_thisWeakRef;\r
+ Windows::UI::Core::CoreDispatcher^ m_dispatcher;\r
+\r
+ std::string m_targetDeviceId;\r
+\r
+ IPCAAppHandle m_ipcaAppHandle;\r
+ IPCADeviceHandle m_deviceHandle;\r
+ IPCAHandle m_discoverDeviceHandle;\r
+ IPCAHandle m_deviceDiscoveryHandle;\r
+\r
+ bool m_targetElevatorDiscovered;\r
+\r
+ Windows::UI::Xaml::Controls::PasswordBox^ m_pbPwdInput;\r
+ Windows::UI::Xaml::Controls::TextBox^ m_txtPwdDisplay;\r
+ Windows::UI::Xaml::Controls::ContentDialog^ m_passInputDiag;\r
+ Windows::UI::Xaml::Controls::ContentDialog^ m_passDisplayDiag;\r
+\r
+ // Key is device id. Value is pointer to Elevator.
+ Windows::Foundation::Collections::IMap<Platform::String^, Elevator^>^ m_ElevatorList;
+
+ // Sync access to m_ElevatorList.
+ std::recursive_mutex m_ElevatorListMutex;
+ // Discovery mutex and cond var
+ std::mutex m_deviceDiscoveredCbMutex;
+ std::condition_variable m_deviceDiscoveredCV;\r
+ std::mutex m_deviceDiscoveryMutex;\r
+ std::condition_variable m_deviceDiscoveryCV;\r
+ // Device mutex\r
+ std::mutex m_deviceMutex;\r
+ // Get properties mutex and cond var\r
+ std::mutex m_getPropsMutex;\r
+ std::condition_variable m_getPropsCV;\r
+\r
+ int m_currentFloor;\r
+ };\r
+}
\ No newline at end of file
--- /dev/null
+/* *****************************************************************
+*
+* Copyright 2017 Microsoft
+*
+*
+* 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.
+*
+******************************************************************/\r
+\r
+#include "pch.h"\r
+#include "ElevatorViewModel.h"\r
+#include "ElevatorDiscovery.h"\r
+\r
+using namespace ElevatorClientUWP;\r
+\r
+using namespace concurrency;\r
+\r
+using namespace Platform;\r
+using namespace Platform::Collections;\r
+using namespace Windows::ApplicationModel::Core;\r
+using namespace Windows::Foundation;\r
+using namespace Windows::Foundation::Collections;\r
+using namespace Windows::UI::Core;\r
+using namespace Windows::UI::Xaml;\r
+using namespace Windows::UI::Xaml::Controls;\r
+using namespace Windows::UI::Xaml::Controls::Primitives;\r
+using namespace Windows::UI::Xaml::Data;\r
+using namespace Windows::UI::Xaml::Input;\r
+using namespace Windows::UI::Xaml::Media;\r
+using namespace Windows::UI::Xaml::Navigation;\r
+\r
+ElevatorViewModel::ElevatorViewModel() : m_dispatcher(nullptr), m_elevatorDisc(nullptr)\r
+{\r
+ m_dispatcher = CoreApplication::MainView->Dispatcher;\r
+\r
+ m_deviceList = ref new Vector<Elevator^>();\r
+\r
+ try\r
+ {\r
+ ElevatorDiscovery^ elvDisc = ref new ElevatorDiscovery();\r
+ elvDisc->OnElevatorDiscovered += ref new ElevatorEvent(this, &ElevatorViewModel::ElevatorDiscovered);\r
+ elvDisc->OnElevatorDisconnected += ref new ElevatorEvent(this, &ElevatorViewModel::ElevatorDisconnected);\r
+ m_elevatorDisc = elvDisc;\r
+ }\r
+ catch (Exception^ e)\r
+ {\r
+ Util::ShowErrorMsg(nullptr, e->Message);\r
+ }\r
+}\r
+\r
+ElevatorViewModel::~ElevatorViewModel()\r
+{\r
+ if (m_elevatorDisc)\r
+ {\r
+ m_elevatorDisc->StopElevatorDiscovery();\r
+ }\r
+}\r
+\r
+void ElevatorViewModel::DiscoverElevators()\r
+{\r
+ if (!m_elevatorDisc->StartElevatorDiscovery())\r
+ {\r
+ Util::ShowErrorMsg(nullptr, "Couldn't Start Elevator Discovery");\r
+ }\r
+}\r
+\r
+void ElevatorViewModel::ElevatorDiscovered(Elevator^ elevator)\r
+{\r
+ elevator->OnAuthFailure += ref new ElevatorClientUWP::AuthFailure(this,\r
+ &ElevatorViewModel::AuthFailure);\r
+\r
+ m_dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler(\r
+ [this, elevator]\r
+ {\r
+ unsigned int index;\r
+ if (!m_deviceList->IndexOf(elevator, &index))\r
+ {\r
+ m_deviceList->Append(elevator);\r
+ }\r
+ }\r
+ ));\r
+}\r
+\r
+void ElevatorViewModel::ElevatorDisconnected(Elevator^ elevator)\r
+{\r
+ m_dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler(\r
+ [this, elevator]\r
+ {\r
+ unsigned int index;\r
+ if (m_deviceList->IndexOf(elevator, &index))\r
+ {\r
+ m_deviceList->RemoveAt(index);\r
+ }\r
+ }\r
+ ));\r
+}\r
+\r
+void ElevatorViewModel::AuthFailure()\r
+{\r
+ m_dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler([this]\r
+ {\r
+ SelectedDevice = nullptr;\r
+ }));\r
+}\r
+\r
+void ElevatorViewModel::SetFloor(int floor)\r
+{\r
+ if (m_selectedDevice != nullptr)\r
+ {\r
+ if (!m_selectedDevice->SetTargetFloor(floor))\r
+ {\r
+ Util::ShowErrorMsg(nullptr, "Failed to set the target floor");\r
+ }\r
+ }\r
+}\r
+\r
+IVector<Elevator^>^ ElevatorViewModel::DeviceList::get()\r
+{\r
+ return m_deviceList;\r
+}\r
+\r
+Elevator^ ElevatorViewModel::SelectedDevice::get()\r
+{\r
+ return m_selectedDevice;\r
+}\r
+\r
+void ElevatorViewModel::SelectedDevice::set(Elevator^ value)\r
+{\r
+ if (m_selectedDevice != value)\r
+ {\r
+ // Stop Observation for the previously selected device\r
+ if (m_selectedDevice)\r
+ {\r
+ m_selectedDevice->StopObservation();\r
+ }\r
+\r
+ // Set the new device\r
+ m_selectedDevice = value;\r
+ OnPropertyChanged("SelectedDevice");\r
+\r
+ // Start Observation for the newly selected device\r
+ if (m_selectedDevice)\r
+ {\r
+ try\r
+ {\r
+ m_selectedDevice->StartObservation();\r
+ }\r
+ catch (Exception^ e)\r
+ {\r
+ Util::ShowErrorMsg(nullptr, e->Message);\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+void ElevatorViewModel::OnPropertyChanged(String^ propertyName)\r
+{\r
+ m_dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler([this, propertyName]\r
+ {\r
+ PropertyChanged(this, ref new PropertyChangedEventArgs(propertyName));\r
+ }));\r
+}\r
--- /dev/null
+/* *****************************************************************
+*
+* Copyright 2017 Microsoft
+*
+*
+* 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.
+*
+******************************************************************/\r
+\r
+#pragma once\r
+\r
+#include "Elevator.h"\r
+\r
+namespace ElevatorClientUWP\r
+{\r
+ ref class ElevatorDiscovery;\r
+\r
+ [Windows::UI::Xaml::Data::Bindable]\r
+ public ref class ElevatorViewModel sealed : Windows::UI::Xaml::Data::INotifyPropertyChanged\r
+ {\r
+ public:\r
+ ElevatorViewModel();\r
+ virtual ~ElevatorViewModel();\r
+ void DiscoverElevators();\r
+ void SetFloor(int floor);\r
+\r
+ public:\r
+ virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler^ PropertyChanged;\r
+\r
+ property Windows::Foundation::Collections::IVector<Elevator^>^ DeviceList\r
+ {\r
+ Windows::Foundation::Collections::IVector<Elevator^>^ get();\r
+ }\r
+\r
+ property Elevator^ SelectedDevice\r
+ {\r
+ Elevator^ get();\r
+ void set(Elevator^ value);\r
+ }\r
+\r
+ private:\r
+ void OnPropertyChanged(Platform::String^ propertyName);\r
+ void ElevatorDiscovered(Elevator^ elevator);\r
+ void ElevatorDisconnected(Elevator ^elevator);\r
+ void AuthFailure();\r
+\r
+ private:\r
+ Windows::UI::Core::CoreDispatcher^ m_dispatcher;\r
+ ElevatorDiscovery^ m_elevatorDisc;\r
+ Platform::String^ m_targetDeviceId;\r
+ Platform::Collections::Vector<Elevator^>^ m_deviceList;\r
+ Elevator^ m_selectedDevice;\r
+ };\r
+}\r
--- /dev/null
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+ <PropertyGroup Condition="'$(Platform)'=='x64'">\r
+ <IoTivityOutDir>$(ProjectDir)..\..\..\..\out\windows\uwp\amd64\$(Configuration)</IoTivityOutDir>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition="'$(Platform)'!='x64'">\r
+ <IoTivityOutDir>$(ProjectDir)..\..\..\..\out\windows\uwp\$(PlatformTarget)\$(Configuration)</IoTivityOutDir>\r
+ </PropertyGroup>\r
+ <ItemGroup>\r
+ <NativeLibs Include="$(IoTivityOutDir)\ipca.dll;$(IoTivityOutDir)\octbstack.dll" />\r
+ <None Include="@(NativeLibs)">\r
+ <Link>%(RecursiveDir)%(FileName)%(Extension)</Link>\r
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\r
+ </None>\r
+ <ReferenceCopyLocalPaths Include="@(NativeLibs)" />\r
+ </ItemGroup>\r
+ <ItemDefinitionGroup>\r
+ <Link>\r
+ <AdditionalLibraryDirectories>$(IoTivityOutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r
+ </Link>\r
+ </ItemDefinitionGroup>\r
+</Project>\r
--- /dev/null
+<Page\r
+ x:Class="ElevatorClientUWP.MainPage"\r
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"\r
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"\r
+ xmlns:local="using:ElevatorClientUWP"\r
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"\r
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"\r
+ mc:Ignorable="d">\r
+\r
+ <Page.Resources>\r
+ <Thickness x:Key="DefaultMargin">10</Thickness>\r
+ </Page.Resources>\r
+\r
+ <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">\r
+ <StackPanel Orientation="Vertical">\r
+ <StackPanel Orientation="Vertical" Margin="{StaticResource DefaultMargin}">\r
+ <TextBlock HorizontalAlignment="Left" Margin="10" TextWrapping="Wrap" Text="Elevators:" VerticalAlignment="Top"/>\r
+ <ComboBox Margin="10,0,10,10" MinWidth="320" ItemsSource="{Binding DeviceList}" SelectedItem="{Binding SelectedDevice, Mode=TwoWay}" DisplayMemberPath="Name"\r
+ SelectionChanged="Elevators_SelectionChanged" />\r
+ </StackPanel>\r
+ <StackPanel Orientation="Horizontal">\r
+ <TextBlock x:Name="curFloorTBlock" HorizontalAlignment="Left" TextWrapping="Wrap"\r
+ Text="Current Floor:" VerticalAlignment="Top" Margin="{StaticResource DefaultMargin}"/>\r
+ <TextBlock Text="{Binding SelectedDevice.CurrentFloor}" Margin="{StaticResource DefaultMargin}"\r
+ VerticalAlignment="Center"/>\r
+ </StackPanel>\r
+ <StackPanel Orientation="Horizontal">\r
+ <TextBlock x:Name="setFloorTBlock" HorizontalAlignment="Left" TextWrapping="Wrap"\r
+ Text="Set Floor:" VerticalAlignment="Top" Margin="{StaticResource DefaultMargin}"/>\r
+ <TextBox x:Name="setFloorText" HorizontalAlignment="Left" TextWrapping="Wrap"\r
+ VerticalAlignment="Top" Margin="{StaticResource DefaultMargin}"/>\r
+ <Button x:Name="setFloorBtn" Content="Set Floor" HorizontalAlignment="Left"\r
+ VerticalAlignment="Top" Margin="{StaticResource DefaultMargin}"\r
+ Click="setFloorBtn_Click"/>\r
+ </StackPanel>\r
+ </StackPanel>\r
+ </Grid>\r
+</Page>\r
--- /dev/null
+/* *****************************************************************
+*
+* Copyright 2017 Microsoft
+*
+*
+* 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.
+*
+******************************************************************/\r
+\r
+//\r
+// MainPage.xaml.cpp\r
+// Implementation of the MainPage class.\r
+//\r
+\r
+#include "pch.h"\r
+#include "MainPage.xaml.h"\r
+\r
+using namespace ElevatorClientUWP;\r
+using namespace concurrency;\r
+using namespace Platform;\r
+using namespace Windows::Foundation;\r
+using namespace Windows::Foundation::Collections;\r
+using namespace Windows::UI::Xaml;\r
+using namespace Windows::UI::Xaml::Controls;\r
+using namespace Windows::UI::Xaml::Controls::Primitives;\r
+using namespace Windows::UI::Xaml::Data;\r
+using namespace Windows::UI::Xaml::Input;\r
+using namespace Windows::UI::Xaml::Media;\r
+using namespace Windows::UI::Xaml::Navigation;\r
+using namespace Windows::UI::Core;\r
+\r
+MainPage::MainPage()\r
+{\r
+ InitializeComponent();\r
+ ViewModel = ref new ElevatorViewModel();\r
+ DataContext = ViewModel;\r
+ this->Loaded += ref new RoutedEventHandler(this, &MainPage::OnLoaded);\r
+}\r
+\r
+void MainPage::setFloorBtn_Click(Object^ sender, RoutedEventArgs^ e)\r
+{\r
+ int floor = 0;\r
+ try\r
+ {\r
+ floor = std::stoi(setFloorText->Text->Data());\r
+ }\r
+ catch (std::exception e)\r
+ {\r
+ Util::ShowErrorMsg(nullptr, "Invalid Floor Number");\r
+ }\r
+ ViewModel->SetFloor(floor);\r
+}\r
+\r
+void MainPage::Elevators_SelectionChanged(Object^ sender, SelectionChangedEventArgs^ e)\r
+{\r
+ setFloorText->Text = "";\r
+}\r
+\r
+void ElevatorClientUWP::MainPage::OnLoaded(Object ^sender, RoutedEventArgs ^e)\r
+{\r
+ ViewModel->DiscoverElevators();\r
+}\r
--- /dev/null
+/* *****************************************************************
+*
+* Copyright 2017 Microsoft
+*
+*
+* 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.
+*
+******************************************************************/\r
+\r
+//\r
+// MainPage.xaml.h\r
+// Declaration of the MainPage class.\r
+//\r
+\r
+#pragma once\r
+\r
+#include "MainPage.g.h"\r
+#include "ElevatorViewModel.h"\r
+\r
+namespace ElevatorClientUWP\r
+{\r
+ /// <summary>\r
+ /// An empty page that can be used on its own or navigated to within a Frame.\r
+ /// </summary>\r
+ public ref class MainPage sealed\r
+ {\r
+ public:\r
+ MainPage();\r
+\r
+ private:\r
+ void setFloorBtn_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);\r
+ void Elevators_SelectionChanged(Platform::Object^ sender,\r
+ Windows::UI::Xaml::Controls::SelectionChangedEventArgs^ e);\r
+ void OnLoaded(Platform::Object ^sender, Windows::UI::Xaml::RoutedEventArgs ^e);\r
+\r
+ ElevatorViewModel^ ViewModel;\r
+ };\r
+}\r
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>\r
+<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" IgnorableNamespaces="uap mp">\r
+ <Identity Name="ab2593e4-2994-401e-a526-c92fd9b71414" Publisher="CN=ElevatorClientUWP" Version="1.0.0.0" />\r
+ <mp:PhoneIdentity PhoneProductId="ab2593e4-2994-401e-a526-c92fd9b71414" PhonePublisherId="00000000-0000-0000-0000-000000000000" />\r
+ <Properties>\r
+ <DisplayName>ElevatorClientUWP</DisplayName>\r
+ <PublisherDisplayName>Microsoft</PublisherDisplayName>\r
+ <Logo>Assets\StoreLogo.png</Logo>\r
+ </Properties>\r
+ <Dependencies>\r
+ <TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />\r
+ </Dependencies>\r
+ <Resources>\r
+ <Resource Language="x-generate" />\r
+ </Resources>\r
+ <Applications>\r
+ <Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="ElevatorClientUWP.App">\r
+ <uap:VisualElements DisplayName="ElevatorClientUWP" Square150x150Logo="Assets\Square150x150Logo.png" Square44x44Logo="Assets\Square44x44Logo.png" Description="ElevatorClientUWP" BackgroundColor="transparent">\r
+ <uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png">\r
+ </uap:DefaultTile>\r
+ <uap:SplashScreen Image="Assets\SplashScreen.png" />\r
+ </uap:VisualElements>\r
+ </Application>\r
+ </Applications>\r
+ <Capabilities>\r
+ <Capability Name="internetClient" />\r
+ <Capability Name="privateNetworkClientServer" />\r
+ </Capabilities>\r
+</Package>
\ No newline at end of file
--- /dev/null
+#******************************************************************
+#
+# Copyright 2017 Microsoft
+#
+#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+#
+# 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.
+#
+#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+import os
+
+Import('ipca_env')
+target_arch = ipca_env.get('TARGET_ARCH')
+elevator_client_uwp_env = ipca_env.Clone()
+
+# Convert architecture to the platform value used by Visual Studio.
+platform_str = target_arch
+if platform_str == 'amd64':
+ platform_str = 'x64'
+elif platform_str == 'x86':
+ platform_str = 'Win32'
+
+app_package_folder_name = 'ElevatorClientUWP_1.0.0.0_Test'
+if not elevator_client_uwp_env.get('RELEASE'):
+ platform_str += '_Debug'
+ app_package_folder_name = 'ElevatorClientUWP_1.0.0.0_Debug_Test'
+
+solutiondir = 'resource\\IPCA\\samples\\ElevatorClientUWP'
+solutionfile = os.path.join(elevator_client_uwp_env.get('SRC_DIR'),
+ solutiondir,
+ 'ElevatorClientUWP.sln')
+
+# Construct output directory
+build_path = 'resource\\IPCA\\samples\\ElevatorClientUWP'
+build_outdir = os.path.normpath(elevator_client_uwp_env.get('BUILD_DIR') + build_path) + '\\'
+outdir = build_outdir + '\\'
+
+app_output_name = 'ElevatorClientUWP_1.0.0.0_' + platform_str
+appx_file = build_outdir + 'ElevatorClientUWP\\' + app_output_name + '.appx'
+
+# Set the MSBuildOutDir env variable so that the MSBuilder can use it
+# Note: This should only be set on a cloned Environment and not the global one
+elevator_client_uwp_env['MSBuildOutDir'] = outdir
+
+if elevator_client_uwp_env.GetOption('clean'):
+ elevator_client_uwp_env.MSBuildClean(appx_file, solutionfile)
+else:
+ elevator_client_uwp_build = elevator_client_uwp_env.MSBuild(appx_file, solutionfile)
+ elevator_client_uwp_env.AlwaysBuild('elevator_client_uwp_build')
+
+# Run the WACK test if we are building/running Release Tests
+if elevator_client_uwp_env.get('TEST') == '1' \
+ and elevator_client_uwp_env.get('RELEASE') \
+ and not elevator_client_uwp_env.GetOption('clean'):
+ cert_file = build_outdir + 'ElevatorClientUWP\\AppPackages\\' + app_package_folder_name + \
+ '\\' + app_output_name + '.cer'
+
+ from tools.scons.RunTest import *
+ run_uwp_wack_test(elevator_client_uwp_env, cert_file, appx_file, build_outdir)
--- /dev/null
+/* *****************************************************************
+*
+* Copyright 2017 Microsoft
+*
+*
+* 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.
+*
+******************************************************************/\r
+\r
+#include "pch.h"\r
+#include "Util.h"\r
+\r
+using namespace ElevatorClientUWP;\r
+using namespace Platform;\r
+using namespace Windows::UI::Core;\r
+using namespace Windows::UI::Popups;\r
+\r
+String^ Util::ConvertStrtoPlatformStr(PCSTR str)\r
+{\r
+ String^ wstrRet = nullptr;
+ PWSTR wstr = nullptr;
+
+ int wstrLength = MultiByteToWideChar(
+ CP_UTF8,
+ MB_ERR_INVALID_CHARS,
+ str,
+ -1,
+ nullptr,
+ 0);
+
+ if (wstrLength == 0)
+ {
+ goto exit;
+ }
+
+ // wstrLength includes null char
+ wstr = new WCHAR[wstrLength];
+ if (wstr == nullptr)
+ {
+ goto exit;
+ }
+
+ int retLen = MultiByteToWideChar(
+ CP_UTF8,
+ 0,
+ str,
+ -1,
+ wstr,
+ wstrLength);
+
+ if (retLen != wstrLength)
+ {
+ goto exit;
+ }
+
+ wstrRet = ref new String(wstr);
+
+exit:
+ if (wstr != nullptr)
+ {
+ delete[] wstr;
+ }
+ return wstrRet;\r
+}\r
+\r
+// This function converts a wide char string to a standard char string.
+std::string Util::ConvertWStrtoStr(PCWSTR wstr)
+{
+ std::string strRet;
+ char* str = nullptr;
+
+ int strLength = WideCharToMultiByte(
+ CP_UTF8,
+ WC_ERR_INVALID_CHARS,
+ wstr,
+ -1,
+ nullptr,
+ 0,
+ nullptr,
+ nullptr);
+
+ if (strLength == 0)
+ {
+ goto exit;
+ }
+
+ // strLength includes null char
+ str = new char[strLength];
+ if (str == nullptr)
+ {
+ goto exit;
+ }
+
+ int retLen = WideCharToMultiByte(
+ CP_UTF8,
+ 0,
+ wstr,
+ -1,
+ str,
+ strLength,
+ nullptr,
+ nullptr);
+
+ if (retLen != strLength)
+ {
+ goto exit;
+ }
+
+ strRet = str;
+
+exit:
+ if (str != nullptr)
+ {
+ delete[] str;
+ }
+ return strRet;
+}\r
+\r
+void Util::ShowErrorMsg(CoreDispatcher^ dispatcher, String^ msg)\r
+{\r
+ Platform::Agile<MessageDialog^> msgDlg(ref new MessageDialog(msg, "Error"));\r
+ if (dispatcher)\r
+ {\r
+ dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler([msgDlg]\r
+ {\r
+ msgDlg->ShowAsync();\r
+ }));\r
+ }\r
+ else\r
+ {\r
+ msgDlg->ShowAsync();\r
+ }\r
+}\r
--- /dev/null
+/* *****************************************************************
+*
+* Copyright 2017 Microsoft
+*
+*
+* 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.
+*
+******************************************************************/\r
+\r
+#pragma once\r
+\r
+#include "Windows.h"\r
+\r
+namespace ElevatorClientUWP\r
+{\r
+ public ref class Util sealed\r
+ {\r
+ internal:\r
+ static Platform::String^ ConvertStrtoPlatformStr(PCSTR str);\r
+ static std::string Util::ConvertWStrtoStr(PCWSTR wstr);\r
+ static void ShowErrorMsg(Windows::UI::Core::CoreDispatcher^ dispatcher,\r
+ Platform::String^ msg);\r
+ };\r
+}\r
--- /dev/null
+//\r
+// pch.cpp\r
+// Include the standard header and generate the precompiled header.\r
+//\r
+\r
+#include "pch.h"\r
--- /dev/null
+//\r
+// pch.h\r
+// Header for standard system include files.\r
+//\r
+\r
+#pragma once\r
+\r
+#include <collection.h>\r
+#include <ppltasks.h>\r
+\r
+#include "App.xaml.h"\r
+#include "Util.h"\r
SConscript('ipcaapp/SConscript', 'ipca_env')
SConscript('ElevatorServer/SConscript', 'ipca_env')
SConscript('ElevatorClient/SConscript', 'ipca_env')
+if ipca_env.get('UWP_APP') == '1':
+ SConscript('ElevatorClientUWP/SConscript', 'ipca_env')
# ------------------------------------------------------------------------
import os
+import platform
def run_test(env, xml_file, test, test_targets = ['test']):
"""
ut = env.Command('ut' + test, None, test_cmd)
env.Depends(ut, test_targets)
env.AlwaysBuild(ut)
+
+def run_uwp_wack_test(env, cert_file, appx_file, report_output_path):
+ if env.get('TARGET_OS') != 'windows' or env.get('UWP_APP') != '1':
+ return
+
+ import winreg
+
+ # Add WACK path to path
+ appcert_reg_path = 'SOFTWARE\\Microsoft\\Windows App Certification Kit'
+ # The WACK registry key is only in the default location, i.e. SOFTWARE\\Microsoft\...
+ # If the machine is 64bit, then we need to look into the 64bit Registry View for the key
+ reg_view_64bit = (platform.machine() == 'AMD64')
+ appcert_path = env.ReadRegistryStringValue(winreg.HKEY_LOCAL_MACHINE,
+ appcert_reg_path,
+ 'InstallLocation',
+ reg_view_64bit)
+ if not appcert_path:
+ Exit('Error: Could not Find the WACK Registry Key/Value')
+
+ env.AppendUnique(PATH = [appcert_path])
+ # Need to update the 'ENV' dictionary PATH as that's what is used when executing
+ # commands
+ env['ENV']['PATH'] = env.get('PATH')
+
+ # testid 38 is the "Supported APIs" test and verifies that all APIs used are available for
+ # store apps.
+ # Note that appcert.exe requires admin privileges and will prompt for elevation unless the
+ # build is run from an elevated command shell.
+ report_output_file = os.path.join(report_output_path, 'wack_output.xml')
+ command = 'certutil -addstore root %s' % (cert_file)
+ command += ' && appcert.exe reset'
+ command += ' && appcert.exe test -AppxPackagePath %s -reportoutputpath %s -testid [38]' \
+ % (appx_file, report_output_file)
+ command += ' && certutil %s | for /f "delims=: tokens=1*" %%i in (\'findstr "Serial Number:"\') do (certutil -delstore root %%j)' % (cert_file)
+ command += ' && findstr OVERALL_RESULT=.PASS %s' % (report_output_file)
+
+ print 'Running WACK Test'
+ wack_test = env.Command(report_output_file, appx_file, command)
+ env.AlwaysBuild(wack_test)
+