由多个应用程序控制的UWP gpio

由多个应用程序控制的UWP gpio,uwp,gpio,windows-iot-core-10,Uwp,Gpio,Windows Iot Core 10,我的问题很简单。我有带win10的RPI和多个UWP应用程序。我想在任何应用程序出现问题(抛出异常或其他)时打开红色led,并在问题解决时将其关闭 我可以从应用程序上拉上/下引脚,但当一个应用程序持有GPIO引脚时,另一个应用程序将抛出异常。或者,当一个应用程序中的问题得到解决时,当其他应用程序仍有问题时,led将熄灭 有没有我可以使用的抽象概念,或者我可以创建自己的抽象概念 *抽象是指在后台工作的应用程序,我可以将其称为静态类。GPIO控制器不能跨多个应用程序域共享,一旦某个应用程序处理GPI

我的问题很简单。我有带win10的RPI和多个UWP应用程序。我想在任何应用程序出现问题(抛出异常或其他)时打开红色led,并在问题解决时将其关闭

我可以从应用程序上拉上/下引脚,但当一个应用程序持有GPIO引脚时,另一个应用程序将抛出异常。或者,当一个应用程序中的问题得到解决时,当其他应用程序仍有问题时,led将熄灭

有没有我可以使用的抽象概念,或者我可以创建自己的抽象概念


*抽象是指在后台工作的应用程序,我可以将其称为静态类。

GPIO控制器不能跨多个应用程序域共享,一旦某个应用程序处理GPIO控制器,它将被锁定到当前应用程序域。我认为解决这个问题的一个办法是,你可以创建一个作为设备上运行的网桥,应用程序服务控制GPIO,你的多个应用程序调用服务。您可以在应用程序服务中实现该逻辑

更新:

windows iot核心后台应用程序中没有托管应用程序服务

StartupTask.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Http;
using Windows.ApplicationModel.Background;
using Windows.ApplicationModel.AppService;
using Windows.Foundation.Collections;
using Windows.Devices.Gpio;
using System.Threading.Tasks;
using Windows.System.Threading;

// The Background Application template is documented at http://go.microsoft.com/fwlink/?LinkID=533884&clcid=0x409

namespace AppErrorCrossDomainMonitorService
{
    public sealed class AppErrorCrossDomainMonitorTask : IBackgroundTask
    {
        IBackgroundTaskInstance _taskInstance = null;
        private BackgroundTaskDeferral serviceDeferral;
        private AppServiceConnection connection;
        private GpioController gpioController;
        private static GpioPin ledPin = null;
        private GpioOpenStatus pinStatus = GpioOpenStatus.UnknownError;
        private const int LED_PIN = 4;

        public void Run(IBackgroundTaskInstance taskInstance)
        {
            // 
            // TODO: Insert code to perform background work
            //
            // If you start any asynchronous methods here, prevent the task
            // from closing prematurely by using BackgroundTaskDeferral as
            // described in http://aka.ms/backgroundtaskdeferral
            //
            //Take a service deferral so the service isn't terminated
            try
            {
                serviceDeferral = taskInstance.GetDeferral();

                taskInstance.Canceled += OnTaskCanceled;
                _taskInstance = taskInstance;

                pinStatus = GpioOpenStatus.UnknownError;
                gpioController = GpioController.GetDefault();

                var details = taskInstance.TriggerDetails as AppServiceTriggerDetails;
                if(details != null)
                {
                    connection = details.AppServiceConnection;

                    //Listen for incoming app service requests
                    connection.RequestReceived += OnRequestReceived;
                }
            }
            catch(Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message);
            }
        }

        private void OnTaskCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
        {
            if (serviceDeferral != null)
            {
                //Complete the service deferral
                serviceDeferral.Complete();
                serviceDeferral = null;
            }

            if (connection != null)
            {
                connection.Dispose();
                connection = null;
            }
        }

        async void OnRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
        {
            //Get a deferral so we can use an awaitable API to respond to the message
            var messageDeferral = args.GetDeferral();

            try
            {
                var input = args.Request.Message;
                string appName = input["AppName"].ToString();
                string actionName = input["ActionName"].ToString();

                //Create the response
                var result = new ValueSet();

                if (gpioController != null)
                {
                    if(ledPin == null)
                    {
                        gpioController.TryOpenPin(LED_PIN, GpioSharingMode.Exclusive, out ledPin, out pinStatus);
                        if (ledPin != null)
                        {
                            ledPin.SetDriveMode(GpioPinDriveMode.Output);
                        }
                    }                    
                }

                if (actionName == "error")
                {
                    //Open LED
                    ledPin.Write(GpioPinValue.High);
                    result.Add("led-status", "ON");
                }

                if (actionName == "clear")
                {
                    //Close LED
                    ledPin.Write(GpioPinValue.Low);
                    result.Add("led-status", "OFF");
                }

                //Send the response
                await args.Request.SendResponseAsync(result);
            }
            catch(Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message);
            }
            finally
            {                
                //Complete the message deferral so the platform knows we're done responding
                messageDeferral.Complete();
            }
        }
    }
}
Package.appxmanifest

<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"
  xmlns:iot="http://schemas.microsoft.com/appx/manifest/iot/windows10"
  xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
  IgnorableNamespaces="uap mp iot uap3">

      ...

      <Extensions>
        <Extension Category="windows.backgroundTasks" EntryPoint="AppErrorCrossDomainMonitorService.AppErrorCrossDomainMonitorTask">
          <BackgroundTasks>
            <iot:Task Type="startup" />
          </BackgroundTasks>
        </Extension>
        <uap:Extension Category="windows.appService" EntryPoint="AppErrorCrossDomainMonitorService.AppErrorCrossDomainMonitorTask">
          <uap3:AppService Name="com.microsoft.errorcrossdomainmonitor" SupportsRemoteSystems="true"/>
        </uap:Extension>
      </Extensions>

      ...

  <Capabilities>
    <Capability Name="internetClient" />
    <DeviceCapability Name="lowLevel" />
  </Capabilities>
</Package>

...
...

您需要在程序包清单中添加应用程序服务的扩展引用。

无法在多个应用程序域中共享GPIO控制器,一旦某个应用程序处理GPIO控制器,它将针对当前应用程序域被锁定。我认为解决这个问题的一个办法是,你可以创建一个作为设备上运行的网桥,应用程序服务控制GPIO,你的多个应用程序调用服务。您可以在应用程序服务中实现该逻辑

更新:

windows iot核心后台应用程序中没有托管应用程序服务

StartupTask.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Http;
using Windows.ApplicationModel.Background;
using Windows.ApplicationModel.AppService;
using Windows.Foundation.Collections;
using Windows.Devices.Gpio;
using System.Threading.Tasks;
using Windows.System.Threading;

// The Background Application template is documented at http://go.microsoft.com/fwlink/?LinkID=533884&clcid=0x409

namespace AppErrorCrossDomainMonitorService
{
    public sealed class AppErrorCrossDomainMonitorTask : IBackgroundTask
    {
        IBackgroundTaskInstance _taskInstance = null;
        private BackgroundTaskDeferral serviceDeferral;
        private AppServiceConnection connection;
        private GpioController gpioController;
        private static GpioPin ledPin = null;
        private GpioOpenStatus pinStatus = GpioOpenStatus.UnknownError;
        private const int LED_PIN = 4;

        public void Run(IBackgroundTaskInstance taskInstance)
        {
            // 
            // TODO: Insert code to perform background work
            //
            // If you start any asynchronous methods here, prevent the task
            // from closing prematurely by using BackgroundTaskDeferral as
            // described in http://aka.ms/backgroundtaskdeferral
            //
            //Take a service deferral so the service isn't terminated
            try
            {
                serviceDeferral = taskInstance.GetDeferral();

                taskInstance.Canceled += OnTaskCanceled;
                _taskInstance = taskInstance;

                pinStatus = GpioOpenStatus.UnknownError;
                gpioController = GpioController.GetDefault();

                var details = taskInstance.TriggerDetails as AppServiceTriggerDetails;
                if(details != null)
                {
                    connection = details.AppServiceConnection;

                    //Listen for incoming app service requests
                    connection.RequestReceived += OnRequestReceived;
                }
            }
            catch(Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message);
            }
        }

        private void OnTaskCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
        {
            if (serviceDeferral != null)
            {
                //Complete the service deferral
                serviceDeferral.Complete();
                serviceDeferral = null;
            }

            if (connection != null)
            {
                connection.Dispose();
                connection = null;
            }
        }

        async void OnRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
        {
            //Get a deferral so we can use an awaitable API to respond to the message
            var messageDeferral = args.GetDeferral();

            try
            {
                var input = args.Request.Message;
                string appName = input["AppName"].ToString();
                string actionName = input["ActionName"].ToString();

                //Create the response
                var result = new ValueSet();

                if (gpioController != null)
                {
                    if(ledPin == null)
                    {
                        gpioController.TryOpenPin(LED_PIN, GpioSharingMode.Exclusive, out ledPin, out pinStatus);
                        if (ledPin != null)
                        {
                            ledPin.SetDriveMode(GpioPinDriveMode.Output);
                        }
                    }                    
                }

                if (actionName == "error")
                {
                    //Open LED
                    ledPin.Write(GpioPinValue.High);
                    result.Add("led-status", "ON");
                }

                if (actionName == "clear")
                {
                    //Close LED
                    ledPin.Write(GpioPinValue.Low);
                    result.Add("led-status", "OFF");
                }

                //Send the response
                await args.Request.SendResponseAsync(result);
            }
            catch(Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message);
            }
            finally
            {                
                //Complete the message deferral so the platform knows we're done responding
                messageDeferral.Complete();
            }
        }
    }
}
Package.appxmanifest

<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"
  xmlns:iot="http://schemas.microsoft.com/appx/manifest/iot/windows10"
  xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
  IgnorableNamespaces="uap mp iot uap3">

      ...

      <Extensions>
        <Extension Category="windows.backgroundTasks" EntryPoint="AppErrorCrossDomainMonitorService.AppErrorCrossDomainMonitorTask">
          <BackgroundTasks>
            <iot:Task Type="startup" />
          </BackgroundTasks>
        </Extension>
        <uap:Extension Category="windows.appService" EntryPoint="AppErrorCrossDomainMonitorService.AppErrorCrossDomainMonitorTask">
          <uap3:AppService Name="com.microsoft.errorcrossdomainmonitor" SupportsRemoteSystems="true"/>
        </uap:Extension>
      </Extensions>

      ...

  <Capabilities>
    <Capability Name="internetClient" />
    <DeviceCapability Name="lowLevel" />
  </Capabilities>
</Package>

...
...

您需要在程序包清单中添加应用程序服务的扩展引用。

是否可以将一个应用程序服务附加到多个应用程序?不是一个服务的多个实例,每个应用一个吗?@110mat110,是的,可以将一个应用服务附加到多个应用。应用程序服务是一项后台任务,用于允许跨应用程序共享数据和功能。您还有其他示例吗?我尝试过microsoft示例,每个应用程序都会创建自己的应用程序服务。@110mat110,我更新了我的响应并提供了一个示例,您可以参考这个示例。omg,我喜欢您的答案。我不知道。我可以同时创建后台启动任务和appservice。微软的示例真的让人困惑。谢谢是否可以将一个应用程序服务附加到多个应用程序?不是一个服务的多个实例,每个应用一个吗?@110mat110,是的,可以将一个应用服务附加到多个应用。应用程序服务是一项后台任务,用于允许跨应用程序共享数据和功能。您还有其他示例吗?我尝试过microsoft示例,每个应用程序都会创建自己的应用程序服务。@110mat110,我更新了我的响应并提供了一个示例,您可以参考这个示例。omg,我喜欢您的答案。我不知道。我可以同时创建后台启动任务和appservice。微软的示例真的让人困惑。谢谢