noant / Lazurite

Home automation software
https://noant.github.io/Lazurite/
Apache License 2.0
55 stars 4 forks source link

Стратегический список TODO #3

Open noant opened 5 years ago

noant commented 5 years ago

Есть определенные идеи по поводу развития Lazurite, список по приоритету: 1) MQTT; 2) Кросс-платформенный бакэнд; 3) ZigBee; 4) Клиент на iOS; 5) Интеграция с Siri и Google Assistant. 6) Создание сценариев на телефоне;

Далее в комментах опишу примерный путь для решения этих задач, также прошу присоединиться желающих к обсуждению. Все аспекты и разъяснения по архитектуре Lazurite объясню по требованию, не нужно стесняться.

noant commented 5 years ago

Кросс-платформенный бакэнд и создание сценариев на телефоне пересекаются. Текущая архитектура плагинов достаточно гибкая, но имеет один фатальный минус для того, чтобы (относительно) быстро реализовать этот функционал. Дело в том, что сейчас интерфейс плагина выглядит так:

    public interface IAction
    {
        string GetValue(ExecutionContext context);
        void SetValue(ExecutionContext context, string value);
        string Caption { get; set; }
        ValueTypeBase ValueType { get; set; }
        void Initialize();
        bool UserInitializeWith(ValueTypeBase valueType, bool inheritsSupportedValues);
        event ValueChangedEventHandler ValueChanged;
        bool IsSupportsEvent { get; }
        bool IsSupportsModification { get; }
    }

Это основа, но доступны еще некоторые возможности из плагина, о них можно узнать здесь.

Основные методы здесь это GetValue, SetValue и UserInitializeWith.

Про сеттер и геттер понятно и так, а вот метод UserInitializeWith является очень узким местом. Дело в том, что есть настраиваемые плагины и не настраиваемые. Настраиваемые плагины это те плагины, которые пользователь может настроить. Допустим, в плагине ZWave пользователь может выбрать нужный узел, т.е. нужное устройство, а также добавить новый узел или удалить и др. Таким образом получается так, что сейчас необходимо иметь собственный UI в почти каждом плагине. На самом деле для этого предоставлен список UI контролов, которые можно использовать из плагина, но это не отменяет того факта, что: 1) каждый плагин привязан к платформе; 2) плагин не настроить через телефон и сейчас нет возможности написать такой клиент, который бы мог создавать сценарии, т.к. плагин не настроишь по сети.

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

noant commented 5 years ago

Далее объясняется только одна из возможностей реализации, скорее всего не являющаяся лучшей, поэтому все, что здесь написано, нужно оспаривать и критиковать.

Для реализации следует "прокинуть" функционал передачи UI через все слои. Напрашивается идея о реализации подобия Wizard'а, где каждая ступень "далее" это отдельное состояние диалога. Попробую описать идею в виде базовых классов:

// Видимый параметр на странице Wizard'a
interface IParameter {
    ushort VisibleIndex { get; }
    object Value { get; }
    object DefaultValue { get; }
}

// Страничка параметров
interface IWizardState{
   IEnumerable<IParameter> Parameters { get; }
   uint StateId { get; }
}

// Целиком визард
interface IWizard {
   IWizardState CurrentState {get;}
   void MoveNext();
   void MovePrevious();
}

// Как это может использоваться в ServiceContract для передачи по сети
interface IService
{
    **** другие методы сервиса
    IWizardState GetWizardState(string scenarioId, string operationId, bool? moveBack, IWizardState previousWizardState);
    **** другие методы сервиса
}

IParameter может быть строкой, списком, числом, картой с выбранной геолокацией, тут только фантазия ограничивает, главное чтобы была одинаковая их реализация на клиентах. Свойства Value и DefaultValue заданы для примера, в реализации лучше их опустить и добавить только в классах-потомках.

IWizardState - страничка с такими параметрами IParameter, где их можно задавать, изменять и т.д., также эту страничку можно перелистнуть, т.е. нажать "Далее", что вызовет метод GetWizardState в сервисе и выдаст следующую страничку визарда в зависимости от того, как мы заполнили параметры на предыдущей страничке. Т.е. каждая отдельная страничка (IWizardState) визарда (IWizard) будет зависеть от предыдущей, а как конкретно будет определять уже сам плагин.

Каждый плагин, который хочет чтобы его настраивали должен реализовать такой IWizard и уже с ним будет работать сервис. Таким образом интерфейс плагина будет выглядеть так:

    public interface IAction
    {
        string GetValue(ExecutionContext context);
        void SetValue(ExecutionContext context, string value);
        string Caption { get; set; }
        ValueTypeBase ValueType { get; set; }
        void Initialize();
        IWizard GetSettingsWizard(); // ------------- Этот метод будет вместо UserInitializeWith
        event ValueChangedEventHandler ValueChanged;
        bool IsSupportsEvent { get; }
        bool IsSupportsModification { get; }
    }

Идея примерно такова.

heX16 commented 5 years ago

GUI Визард это замечательно! Но как будет обстоять дело с непосредственным редактированием конфигурации?

User case: Есть дом, в нем ~180 сигналов. Перечень сигналов в процессе монтажа и ПНР измениться еще 20 раз (по другому не бывает). Разумеется вручную добавлять ~180 сигналов и каждый настраивать руками, а потом переделывать почти каждый сигнал по 2-5 раз просто невозможно. Поэтому используется скрипт который формирует необходимые конфиги. Здесь это возможно?

noant commented 5 years ago

Здесь разумно будет предоставлять api к редактированию сценариев. Сейчас нет такого функционала.

Hedin9000 commented 5 years ago

А как вам вариант внести концепцию устройств? Как я понимаю, сейчас плагин добавляет IAction, который представляет из себя возможное действие/параметр, не привязанное к конкретному экземпляру устройства. И уже при его выполнении из настроек IAction можно получить "координаты" устройства и что-то с ним сделать. А что если плагин будет добавлять непосредственно поддержку устройства (например, какой-нибудь IThing) и описывать возможный набор IAction у этого устройства? Похожая система реализована в Web Thing API от Mozilla и на ней и выполняется генерация UI (правда, только для WEB-интерфейса).

noant commented 5 years ago

Нужно пожить с этой идеей. По сути сейчас задача состоит в следующем: нужно декомпозировать работу со сценарием и плагином таким образом, чтобы работа с устройствами была более формализована, но без потери гибкости создания плагина. Нужно выделить всю возможную логику плагинов и "разложить" ее по интерфейсам, но сделать это так, чтобы в плагине можно было бы реализовать то, что реализовано сейчас (работа с геолокацией, голосовые команды и т.д.). Если смотреть совсем абстрактно, то почти все плагины в Lazurite работают следующим образом: пользователь создаёт сценарий, добавляет строчку, выбирает нужное действие из плагина, в действии плагина он обычно выбирает абстрактный параметр из дерева чего-либо, например в Zwave это выбор контроллер_zwave->устройство_сети_zwave->параметр_устройства. Или в плагине геолокаций пользователь выбирает место->пользователь->телефон_пользователя, т.е. плагин выдает пользователю на выбор некое дерево параметров, каждый из элементов которого можно формализовать типом данных, например строка, число, геолокация и т.д. Ещё в плагине должны быть статические настройки (не в терминах C#, а в терминах Lazurite уже), т.е. в том-же плагине геолокаций пользователь может сам создать место, в плагине zwave пользователь может добавлять контроллер или устройство в сеть, удалять его. Думаю, эти статические настройки тоже можно декомпозировать как и настройку действия. Вообще, нужно абстрагироваться от устройств, т.к. умный дом это не только реле и диммеры.