UWP gpio контролируется несколькими приложениями

моя проблема довольно проста. У меня есть RPI с win10 и несколькими приложениями UWP. Я хочу включить красный светодиод, когда у какого-либо приложения возникают проблемы (выдает исключение или что-то еще), и выключать его, когда проблема решена.

Я могу вытащить контакты вверх/вниз из приложения, но когда одно приложение удерживает контакт GPIO, другое выдает исключение. Или, когда проблема решена в одном приложении, светодиод выключится, в то время как в других приложениях все еще есть проблемы.

Есть ли какая-нибудь абстракция*, которую я могу использовать, или какой-нибудь способ, которым я могу создать свою собственную?

* Под абстракцией я подразумеваю приложение, которое работает в фоновом режиме, и я могу назвать его статическим классом.


person 110mat110    schedule 05.12.2018    source источник


Ответы (1)


Контроллер GPIO не может совместно использоваться несколькими доменами приложений. Как только приложение обрабатывает контроллер GPIO, оно будет заблокировано для текущего домена приложения. Я думаю, что обходной путь для этой проблемы заключается в том, что вы можете создать служба приложений в качестве моста, работающего на устройстве, служба приложений управляет GPIO, несколько приложений вызывают службу. Вы можете реализовать логику в службе приложений.

введите здесь описание изображения

Обновление:

Вот служба приложений, размещенная в фоновом приложении Windows iot core.

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();
            }
        }
    }
}

Пакет.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>

Вам необходимо добавить ссылку на расширение для службы приложений в манифест пакета.

person Michael Xu - MSFT    schedule 06.12.2018
comment
Можно ли подключить ОДНУ службу приложений к нескольким приложениям? Не будет ли это несколько экземпляров одного сервиса, по одному для каждого приложения? - person 110mat110; 07.12.2018
comment
@ 110mat110, да, одну службу приложений можно подключить к нескольким приложениям. Служба приложений — это фоновая задача, которая позволяет обмениваться данными и функциями между приложениями. - person Michael Xu - MSFT; 07.12.2018
comment
У вас есть другой пример? Я попробовал пример Microsoft, и каждое приложение создает свою собственную службу приложений. - person 110mat110; 08.12.2018
comment
@ 110mat110, я обновил свой ответ и предоставил образец, вы можете обратиться к этому образцу. - person Michael Xu - MSFT; 10.12.2018
comment
омг, мне нравится твой ответ. Я не знал. что я могу сделать фоновую задачу запуска и службу приложений одновременно. Образец Microsoft был действительно запутанным. Спасибо! - person 110mat110; 10.12.2018
comment
Добро пожаловать. Но вам нужно реализовать логику для вашего требования в методе OnRequestReceived. Важно еще одно: ledPin должен быть статичным. - person Michael Xu - MSFT; 10.12.2018
comment
У меня нет проблем с самим GPIO, он работает хорошо, и у меня есть (я думаю) хорошие функции для всего, что мне нужно. Но моя проблема заключалась в подключении нескольких приложений к статическим DLL. Теперь я могу реализовать свою библиотеку в одном приложении, и у меня все получится. - person 110mat110; 10.12.2018