Development – Step by Step zum eigenen Module

Ausgangslage und Ziel

Am Beginn jeder Modul Entwicklung sollte man einmal kurz die Ausgangslage und die Ziele beschreiben.

Ziel

Ziel ist es ein Modul zu schreiben, das die täglichen Dämmerungszeiten berechnet und grafisch anzeigt.

  • Berechnung der täglichen Dämmerungszeiten
  • Berechnung der Zeiten mit einem oberen und unteren Limit
  • Grafische Visualisierung
  • Anlegen von Variablen tägliche Aktualisierung mit berechneten Zeiten
  • Generierung von Timern und Aufruf von Callback Methoden
  • Autom. Anlegen von WebFront und Mobile GUI

Voraussetzungen

Keine Voraussetzungen

Das Modul kann von Jedem installiert werden, es benötigt keinerlei Voraussetzungen

IPSTwillight_Unlimited

Installation

Auswahl des Modul Namens Pfades in der Library

Als erstes erfolgt die Auswahl des Pfades, wo das Modul zukünftig in der IPSLibrary zu finden ist. Da es sich hier um ein allgemeines Modul handelt und es in den Überbegriff Wetter fällt wurde folgende Location gewählt: IPSLibrary.app.module.weather.IPSTwilight

Benannt wird das Module mit: IPSTwilight 

Schritt 1: Anlegen der benötigten Scripte

Jedes Modul benötigt 3 Installations Scripte und 1 oder mehrere Applikations Scripte. Jedes dieser Files liegt in vordefinierten Ordnern, die sich durch den gewählten Modul Pfad ergeben.

Installations Scripte

Diese Scripts sind für die komplette Installation bzw. Deinstallation verantwortlich. Die Namen der Files sind fix vorgegeben und setzen sich aus den Modul Namen und dem jeweiligen Suffix zusammen.

  • …\IPSLibrary\install\DownloadListFiles\IPSTwilight_Filelist.ini
  • …\IPSLibrary\install\InstallationScripts\IPSTwilight_Installation.ips.php
  • …\IPSLibrary\install\InitializationFiles\default\IPSTwilight.ini

IPSTwilight_Filelist.ini enthält eine Liste aller Files, die für das Modul benötigt werden
IPSTwilight_Installation.ips.php enthält den Code, der die benötigten Objekte (Variablen, Instanzen, Timer) und die GUIs anlegt.
IPSTwilight.ini enthält diverse Initialisierungs Parameter, mit denen die Generierung des Webfronts gesteuert wird. Dieses File wird beim erstmaligen Laden des Modules in das „User“ Verzeichnis (…\IPSLibrary\install.InitializationFiles\) kopiert, Änderungen müssen vom Entwickler also immer in beiden Files vorgenommen werden.

Es ist auch zu bedenken, dass nachträgliche Änderungen an den „Default“ Files (nachdem das Modul bereits in die Library gestellt wurde), bei einem Update nicht automatisch auf bestehende Installationen ausgerollt wird, da diese Files nach dem erstmaligen Laden bereits kopiert werden und danach nicht mehr überschrieben werden. 

Modul Scripte

Der Name der eigentlichen Modul Scripts kann frei gewählt werden, der Modul Name als Prefix hat sich aber auch hier bewährt.

Folgende Files werden für das IPSTwilight Modul noch benötigt:

  • …\IPSLibrary\app\modules\weather\IPSTwilight\IPSTwilight.ips.php
  • …\IPSLibrary\config\modules\weather\IPSTwilight\default\IPSTwilight_Configuration.inc.php
  • …\IPSLibrary\config\modules\weather\IPSTwilight\default\IPSTwilight_Custom.inc.php

IPSTwilight.ips.php enthält die eigentliche Programm Logik, die die Dämmerungszeiten berechnet, Variablen aktualisiert, Grafiken generiert und die Timer neu erstellt.
IPSTwilight_Configuration.inc.php enthält einige Konfigurations Parameter, um die Berechnung der Zeiten auf den Wohnort anzupassen.
IPSTwilight_Custom.inc.php enhält Callback Methoden, diese werden von den generierten Timern aufgerufen und bieten dem User die Möglichkeit seinen eigenen Code zu platzieren.

Konfigurations und Custom File liegen im default Verzeichnis. Beim erstmaligen Laden des Modules werden die Files in den normalen User Ordner (…\IPSLibrary\config\modules\weather\IPSTwilight\) kopiert, wo sie der User ändern kann. Das heißt aber für den Entwickler, dass er Änderungen auch in den „Default“ Files nachziehen muss. 

Schritt 2: DownloadList File erstellen

Im 2. Schritt wird der Inhalt des IPSTwilight_Filelist.ini Files erstellt:

Version=2.50.1.Beta
ModuleNamespace=IPSLibrary::app::modules::Weather::IPSTwillight

[App]
DefaultFiles[]=
ScriptFiles[]=IPSTwillight.ips.php

[Config]
DefaultFiles[]=IPSTwillight_Configuration.inc.php
DefaultFiles[]=IPSTwillight_Custom.inc.php
ExampleFiles[]=

[Install]
InstallFiles[]=IPSTwillight_Installation.ips.php
DownloadFiles[]=IPSTwillight_FileList.ini
DefaultFiles[]=IPSTwillight.ini
ExampleFiles[]=

[WebFront]
ScriptFiles[]= 

Hier folgende Informationen abgelegt:

  • Namespace – „Namespace“ des Modules (Pfad in der IPSLibrary durch „::“ getrennt)
  • Version – Aktuelle Version des Modules
  • Liste der Files (Application, Config, WebFront und install)

Schritt 3: Erstmaliges Laden des Modules

Im nächsten Schritt können die Module bereits in IPS registriert werden, dazu werden sie in das lokale GIT Verzeichnis „deployed“ und von dort wieder geladen und dabei in IPS registriert.

  IPSUtils_Include ("IPSModuleManager.class.php", "IPSLibrary::install::IPSModuleManager");
  $moduleManager = new IPSModuleManager('<<MyNewModule>>', 'C:\IPS\GIT\IPSLibrary');
  $moduleManager->DeployModule();
  $moduleManager->LoadModule();

Die übrigen Files können bei diesem Vorgang auch noch leer sein, einzig im _ListFile.ini müssen alle Files korrekt registriert sein.

Der Vorgang kann auch später jederzeit wiederholt werden, falls es sich herausstellt, dass noch ein zusätzliches File benötigt wird. 

Schritt 4: Implementieren der Programmlogik

Die komplette Programm Logik ist in diesem Falle im File IPSTwilight.ips.php beinhaltet, der Code zur Berechnung der Dämmerungszeiten ist nicht Teil des WIKI Artikels und braucht an dieser Stelle nicht näher erörtert werden.

Die Entwicklung von Programm Logik und Installations Script kann aber durchaus iterativ erfolgen. Dh: Anlegen diverser Variablen und Profile mit dem Installer, Schreiben und Ausführung von Application Code zur Befüllung der Variablen, Anlegen zusätzlicher Variablen, Implementieren von WebFront und Mobile GUI… 

Schritt 5: Initialisierungs File

Im Initialisierungs File können prinzipiell beliebige Parameter zur Installation des Modules abgelegt werden. Mit ihnen ist normalerweise eine Feinjustierung der Installation möglich.

Damit die Deinstallation von Modulen aber Ordnungsgemäß funktioniert ist es nötig, dass man sich bei der Generierung von WebFront und Mobile Front an einige Naming Conventions hält:

  • Ablegen der WebFront Parameter in Gruppe „WFC10“
  • „Path“ spezifiziert den Pfad für die WebFront Objekte, dort müssen alle zugehörigen Objekte (Links, Dummy Module) abgelegt sein
  • Item Name des verwendeten TabPane muss im Parameter „TabPaneItem“ abgelegt sein
  • Parameter „TabPaneExclusive“ spezifiziert ob das TabPane dem Modul exklusive zur Verfügung steht (und so bei der Deinstallation auch komplett gelöscht werden kann)
  • Verwendete Tab’s sollten mit Hilfe der Parameter „TabItem“ bzw. „TabItem1“ bis „TabItem10“ angelegt werden
  • Ablegen der Mobile Parameter in Gruppe „Mobile“
  • „Path“ spezifiziert den Pfad für die Mobile Objekte, dort müssen alle zugehörigen Objekte (Links, Dummy Module) abgelegt sein
  • Parameter „PathExclusive“ spezifiziert ob der Ordner dem Modul exklusive zur Verfügung steht (und so bei der Deinstallation auch komplett gelöscht werden kann)
  • Verwendete Objekte (Links, Kategorien, Dummy Instanzen) unter diesem Pfad müssen mit Hilfe der Parameter „Name“ bzw. „Name1“ bis „Name10“ angelegt werden (außer der Pfad steht dem Module ohnehin exklusive zur Verfügung)
[WFC10]
  Enabled=true
  Path=Visualization.WebFront.Weather.IPSTwilight
  TabPaneItem=TPWeather
  TabPaneParent=roottp
  TabPaneName=
  TabPaneOrder=10
  TabPaneIcon=Cloud
  TabPaneExclusive=false
  TabItem=Twillight 
  TabName=Dämmerung
  TabIcon=Sun
  TabOrder=20

[Mobile] 
  Enabled=true
  Path=Visualization.Mobile.Wetter
  PathExclusive=false
  PathOrder=10
  PathIcon=Cloud
  Name=Dämmerung
  Icon=Sun
  Order=20 

Schritt 6: Installations Script

IPSModuleManager instanzieren

  if (!isset($moduleManager)) {
    IPSUtils_Include ('IPSModuleManager.class.php', 'IPSLibrary::install::IPSModuleManager');

    echo 'ModuleManager Variable not set --> Create "default" ModuleManager'.PHP_EOL;
    $moduleManager = new IPSModuleManager('IPSTwilight');
  }

Dieser Teil ist optional, hat aber den Vorteil, dass man das Installations Script auch ohne IPSModulManager starten kann (speziell während der Entwicklung der Installation vorteilhaft). 

Versions Checks

  $moduleManager->VersionHandler()->CheckModuleVersion('IPS','2.50');
  $moduleManager->VersionHandler()->CheckModuleVersion('IPSModuleManager','2.50.1');
  $moduleManager->VersionHandler()->CheckModuleVersion('IPSLogger','2.50.1');

Hier werden alle benötigten Module überprüft, die zur Installation benötigt werden. Das spezifizierte Modul muss in einer Version größer oder gleich der angegebenen Version vorhanden sein. 

Includes

  IPSUtils_Include ("IPSInstaller.inc.php",              "IPSLibrary::install::IPSInstaller");
  IPSUtils_Include ("IPSTwilight_Configuration.inc.php", "IPSLibrary::config::modules::Weather::IPSTwilight");

Include der benötigten Files 

Einlesen der Initialisierungs Parameter

  $WFC10_Enabled        = $moduleManager->GetConfigValue('Enabled', 'WFC10');
  $WFC10_ConfigId       = $moduleManager->GetConfigValueIntDef('ID', 'WFC10', GetWFCIdDefault());
  $WFC10_Path           = $moduleManager->GetConfigValue('Path', 'WFC10');
  $WFC10_TabPaneItem    = $moduleManager->GetConfigValue('TabPaneItem', 'WFC10');
  $WFC10_TabPaneParent  = $moduleManager->GetConfigValue('TabPaneParent', 'WFC10');
  $WFC10_TabPaneName    = $moduleManager->GetConfigValue('TabPaneName', 'WFC10');
  $WFC10_TabPaneIcon    = $moduleManager->GetConfigValue('TabPaneIcon', 'WFC10');
  $WFC10_TabPaneOrder   = $moduleManager->GetConfigValueInt('TabPaneOrder', 'WFC10');
  $WFC10_TabItem        = $moduleManager->GetConfigValue('TabItem', 'WFC10');
  $WFC10_TabName        = $moduleManager->GetConfigValue('TabName', 'WFC10');
  $WFC10_TabIcon        = $moduleManager->GetConfigValue('TabIcon', 'WFC10');
  $WFC10_TabOrder       = $moduleManager->GetConfigValueInt('TabOrder', 'WFC10');

  $Mobile_Enabled       = $moduleManager->GetConfigValue('Enabled', 'Mobile');
  $Mobile_Path          = $moduleManager->GetConfigValue('Path', 'Mobile');
  $Mobile_PathOrder     = $moduleManager->GetConfigValueInt('PathOrder', 'Mobile');
  $Mobile_PathIcon      = $moduleManager->GetConfigValue('PathOrder', 'Mobile');
  $Mobile_Name          = $moduleManager->GetConfigValue('Name', 'Mobile');
  $Mobile_Order         = $moduleManager->GetConfigValueInt('Order', 'Mobile');
  $Mobile_Icon          = $moduleManager->GetConfigValue('Icon', 'Mobile');

Einlesen der benötigten Parameter aus dem Initialisierungs File. Sollte kein spezieller WebFront Konfigurator angegeben sein, so wird mit GetWFCIdDefault() der erst beste gefundene genommen. 

Module Kategorien Erstellen

  $categoryId_Data          = $moduleManager->GetModuleCategoryID('data');
  $categoryId_App           = $moduleManager->GetModuleCategoryID('app');

Ermitteln der benötigten IDs für app und data.

Der app Pfad (Program.IPSLibrary.app.modules.weather.IPSTwilight) ist bereits durch den Aufruf von ModuleLoad erzeugt worden und beinhaltet alle Scripte.

Der data Pfad (Program.IPSLibrary.data.modules.weather.IPSTwilight) wird durch den Aufruf den IPSModuleManager beim Aufruf der Funktion GetModuleCategoryID(‚data‘) angelegt. 

Installation der IPS Objekte

  $categoryId_DataGraphics  = CreateCategory('Graphics', $categoryId_Data, 10);
  $categoryId_DataValues    = CreateCategory('Values',   $categoryId_Data, 20);

  // Scripts
  $scriptId_Refresh  = IPS_GetScriptIDByName('IPSTwilight',  $categoryId_App);
  $timerId_Refresh   = CreateTimer_OnceADay ('Refresh', $scriptId_Refresh, 0, 15) ;

  // Graphics
  $YearMediaId          = CreateMedia ('IPSTwilight_Year',          $categoryId_DataGraphics, IPS_GetKernelDir().'media\\IPSTwilight_Year.gif',          false,1,'Sun');
  $YearLimitedMediaId   = CreateMedia ('IPSTwilight_YearLimited',   $categoryId_DataGraphics, IPS_GetKernelDir().'media\\IPSTwilight_YearLimited.gif',   false,1,'Sun');
  $YearUnlimitedMediaId = CreateMedia ('IPSTwilight_YearUnlimited', $categoryId_DataGraphics, IPS_GetKernelDir().'media\\IPSTwilight_YearUnlimited.gif', false,1,'Sun');
  $DayMediaId           = CreateMedia ('IPSTwilight_Day',           $categoryId_DataGraphics, IPS_GetKernelDir().'media\\IPSTwilight_Day.gif',           false,1,'Sun');
  $DayLimitedMediaId    = CreateMedia ('IPSTwilight_DayLimited',    $categoryId_DataGraphics, IPS_GetKernelDir().'media\\IPSTwilight_DayLimited.gif',    false,1,'Sun');
  $DayUnlimitedMediaId  = CreateMedia ('IPSTwilight_DayUnlimited',  $categoryId_DataGraphics, IPS_GetKernelDir().'media\\IPSTwilight_DayUnlimited.gif',  false,1,'Sun');

  //Data
  $DisplaySwitchId   = CreateVariable('Display' ,     0 /*Boolean*/, $categoryId_DataValues, 10, '~Switch',$scriptId_Refresh, false,   'Information');

  $SunriseBeg        = CreateVariable("SunriseBegin",           3 /*String*/,  $categoryId_DataValues,  110, '~String', $scriptId_Refresh, '');
  $SunriseEnd        = CreateVariable("SunriseEnd",             3 /*String*/,  $categoryId_DataValues,  120, '~String', $scriptId_Refresh, '');
  $SunriseBegLim     = CreateVariable("SunriseBeginLimited",    3 /*String*/,  $categoryId_DataValues,  130, '~String', $scriptId_Refresh, '');
  $SunriseEndLim     = CreateVariable("SunriseEndLimited",      3 /*String*/,  $categoryId_DataValues,  140, '~String', $scriptId_Refresh, '');
  $SunriseDisplay    = CreateVariable("SunriseDisplay",         3 /*String*/,  $categoryId_DataValues,  150, '~String', null,              '00:00 - 00:00');
  $SunriseLimits     = CreateVariable("SunriseLimits",          3 /*String*/,  $categoryId_DataValues,  160, '~String', $scriptId_Refresh, '05:30-07:30/18:30-20:30');

  $CivilBeg          = CreateVariable("CivilBegin",             3 /*String*/,  $categoryId_DataValues,  210, '~String', $scriptId_Refresh, '');
  $CivilEnd          = CreateVariable("CivilEnd",               3 /*String*/,  $categoryId_DataValues,  220, '~String', $scriptId_Refresh, '');
  $CivilBegLim       = CreateVariable("CivilBeginLimited",      3 /*String*/,  $categoryId_DataValues,  230, '~String', $scriptId_Refresh, '');
  $CivilEndLim       = CreateVariable("CivilEndLimited",        3 /*String*/,  $categoryId_DataValues,  240, '~String', $scriptId_Refresh, '');
  $CivilDisplay      = CreateVariable("CivilDisplay",           3 /*String*/,  $categoryId_DataValues,  250, '~String', null,              '00:00 - 00:00');
  $CivilLimits       = CreateVariable("CivilLimits",            3 /*String*/,  $categoryId_DataValues,  260, '~String', $scriptId_Refresh, '05:00-07:00/19:00-21:00');

  $NauticBeg         = CreateVariable("NauticBegin",            3 /*String*/,  $categoryId_DataValues,  310, '~String', $scriptId_Refresh, '');
  $NauticEnd         = CreateVariable("NauticEnd",              3 /*String*/,  $categoryId_DataValues,  320, '~String', $scriptId_Refresh, '');
  $NauticBegLim      = CreateVariable("NauticBeginLimited",     3 /*String*/,  $categoryId_DataValues,  330, '~String', $scriptId_Refresh, '');
  $NauticEndLim      = CreateVariable("NauticEndLimited",       3 /*String*/,  $categoryId_DataValues,  340, '~String', $scriptId_Refresh, '');
  $NauticDisplay     = CreateVariable("NauticDisplay",          3 /*String*/,  $categoryId_DataValues,  350, '~String', null,              '00:00 - 00:00');
  $NauticLimits      = CreateVariable("NauticLimits",           3 /*String*/,  $categoryId_DataValues,  360, '~String', $scriptId_Refresh, '04:30-06:30/19:30-21:30');

  $AstronomicBeg     = CreateVariable("AstronomicBegin",        3 /*String*/,  $categoryId_DataValues,  410, '~String', $scriptId_Refresh, '');
  $AstronomicEnd     = CreateVariable("AstronomicEnd",          3 /*String*/,  $categoryId_DataValues,  420, '~String', $scriptId_Refresh, '');
  $AstronomicBegLim  = CreateVariable("AstronomicBeginLimited", 3 /*String*/,  $categoryId_DataValues,  430, '~String', $scriptId_Refresh, '');
  $AstronomicEndLim  = CreateVariable("AstronomicEndLimited",   3 /*String*/,  $categoryId_DataValues,  440, '~String', $scriptId_Refresh, '');
  $AstronomicDisplay = CreateVariable("AstronomicDisplay",      3 /*String*/,  $categoryId_DataValues,  450, '~String', null,              '00:00 - 00:00');
  $AstronomicLimits  = CreateVariable("AstronomicLimits",       3 /*String*/,  $categoryId_DataValues,  460, '~String', $scriptId_Refresh, '04:00-06:00/20:00-22:00');

Dieser Teil erstellt alle benötigten Objekte in IP-Symcon. Die verwendeten Funktionen befinden sich alle im Script IPSInstaller.inc.php und sind dort detailiert beschrieben. 

Erster Run der Applikation

  IPSUtils_Include ("IPSTwilight.ips.php", "IPSLibrary::app::modules::Weather::IPSTwilight");

Durch das inkludieren des Applikations Scriptes wird nun ein erster Run gemacht.

Im Falle von IPSTwilight werden nun alle Variablen berechnet, die Grafiken erzeugt und die erforderlichen Timer erzeugt. 

Create WebFront GUI

  if ($WFC10_Enabled) {
    $categoryId_WebFront         = CreateCategoryPath($WFC10_Path);
    $categoryId_WebFrontTopLeft  = CreateCategory(  'TopLeft',  $categoryId_WebFront, 10);
    $categoryId_WebFrontTopRight = CreateCategory(  'TopRight', $categoryId_WebFront, 20);
    $categoryId_WebFrontBottom   = CreateCategory(  'Bottom',   $categoryId_WebFront, 30);
    $categoryId_WebFrontRight    = CreateCategory(  'Right',    $categoryId_WebFront, 40);

    CreateLinkByDestination('Sonnen-Aufgang/Untergang', $SunriseDisplay,    $categoryId_WebFrontTopLeft,  10);
    CreateLinkByDestination('Limits',                   $SunriseLimits,     $categoryId_WebFrontTopRight, 10);
    CreateLinkByDestination('Zivile Dämmerung',         $CivilDisplay,      $categoryId_WebFrontTopLeft,  20);
    CreateLinkByDestination('Limits',                   $CivilLimits,       $categoryId_WebFrontTopRight, 20);
    CreateLinkByDestination('Nautische Dämmerung',      $NauticDisplay,     $categoryId_WebFrontTopLeft,  30);
    CreateLinkByDestination('Limits',                   $NauticLimits,      $categoryId_WebFrontTopRight, 30);
    CreateLinkByDestination('Astronomische Dämmerung',  $AstronomicDisplay, $categoryId_WebFrontTopLeft,  40);
    CreateLinkByDestination('Limits',                   $AstronomicLimits,  $categoryId_WebFrontTopRight, 40);

    CreateLinkByDestination("Tag- und Nachtstunden in ".IPSTWILIGHT_LOCATION,  $YearMediaId,      $categoryId_WebFrontBottom, 10);
    CreateLinkByDestination('Show Limited',                        $DisplaySwitchId,  $categoryId_WebFrontRight,  10);
    CreateLinkByDestination('Aktueller Tag',                       $DayMediaId,       $categoryId_WebFrontRight,  20);

    $tabItem = $WFC10_TabPaneItem.$WFC10_TabItem;
    DeleteWFCItems($WFC10_ConfigId, $tabItem);
    CreateWFCItemTabPane   ($WFC10_ConfigId, $WFC10_TabPaneItem, $WFC10_TabPaneParent,  $WFC10_TabPaneOrder, $WFC10_TabPaneName, $WFC10_TabPaneIcon);
    CreateWFCItemSplitPane ($WFC10_ConfigId, $tabItem,           $WFC10_TabPaneItem,    $WFC10_TabOrder,     $WFC10_TabName,     $WFC10_TabIcon, 1 /*Vertical*/, 300 /*Width*/, 1 /*Target=Pane2*/, 1/*UsePixel*/, 'true');
    CreateWFCItemSplitPane ($WFC10_ConfigId,   $tabItem.'_Left',        $tabItem,          10, '', '', 0 /*Horicontal*/, 205 /*Height*/, 0 /*Target=Pane1*/, 1 /*UsePixel*/, 'true');
    CreateWFCItemCategory  ($WFC10_ConfigId,   $tabItem.'_Right',        $tabItem,         20, '', '', $categoryId_WebFrontRight    /*BaseId*/, 'false' /*BarBottomVisible*/);
    CreateWFCItemSplitPane ($WFC10_ConfigId,     $tabItem.'_Top',        $tabItem.'_Left', 10, '', '', 1 /*Vertical*/, 50 /*Width*/, 0 /*Target=Pane1*/, 0 /*UsePercentage*/, 'true');
    CreateWFCItemCategory  ($WFC10_ConfigId,     $tabItem.'_Bottom',     $tabItem.'_Left', 20, '', '', $categoryId_WebFrontBottom   /*BaseId*/, 'false' /*BarBottomVisible*/);
    CreateWFCItemCategory  ($WFC10_ConfigId,       $tabItem.'_TopLeft',  $tabItem.'_Top',  10, '', '', $categoryId_WebFrontTopLeft  /*BaseId*/, 'false' /*BarBottomVisible*/);
    CreateWFCItemCategory  ($WFC10_ConfigId,       $tabItem.'_TopRight', $tabItem.'_Top',  20, '', '', $categoryId_WebFrontTopRight /*BaseId*/, 'false' /*BarBottomVisible*/);

    ReloadAllWebFronts();
  }

Dieser Teil erzeuft das komplette WebFront: Zuerst wird durch die Variable $WFC10_Enabled überprüft, ob die Generierung des WebFronts aktiviert ist.

Es folgt die Generierung des Visualisierungs Ordners mit „CreateCategoryPath($WFC10_Path)“. Wichtig auch hier, dass alle Objecte unter diesem Object angelegt werden, damit die Deinstallation funktioniert.

Danach werden für die diversen SplitPanes Kategorien angelegt und darin diverse Links

Nun folgt der komplizierteste Teil – das Anlegen der eigentlichen WebFront Elemente. Im Prinzip läuft es aber genauso ab, wie im WebFront Konfigurator. Es werden SplitPanes und WebFront Kategorien angelegt und mit Hilfe der ItemIDs ineinander verschachtelt.

Am Ende werden alle WebFronts mit dem Befehl ReloadAllWebFronts neu geladen, damit die Änderungen auch sichtbar werden.

DevStepByStep_WebFront

Create Mobile GUI

  if ($Mobile_Enabled) {
    $mobileId  = CreateCategoryPath($Mobile_Path, $Mobile_PathOrder, $Mobile_PathIcon);
    $mobileId  = CreateCategoryPath($Mobile_Path.'.'.$Mobile_Name, $Mobile_Order, $Mobile_Icon);
    
    $InstanceId    = CreateDummyInstance("Sonnen-Aufgang/Untergang",  $mobileId, 10);
    CreateLink('Begin/Ende',   $SunriseDisplay, $InstanceId, 10);
    CreateLink('Limits',       $SunriseLimits,  $InstanceId, 20);
    $InstanceId    = CreateDummyInstance("Zivile Dämmerung",  $mobileId, 20);
    CreateLink('Begin/Ende',   $CivilDisplay, $InstanceId, 10);
    CreateLink('Limits',       $CivilLimits,  $InstanceId, 20);
    $InstanceId    = CreateDummyInstance("Nautische Dämmerung",  $mobileId, 30);
    CreateLink('Begin/Ende',   $NauticDisplay, $InstanceId, 10);
    CreateLink('Limits',       $NauticLimits,  $InstanceId, 20);
    $InstanceId    = CreateDummyInstance("Astronomische Dämmerung",  $mobileId, 40);
    CreateLink('Begin/Ende',   $AstronomicDisplay, $InstanceId, 10);
    CreateLink('Limits',       $AstronomicLimits,  $InstanceId, 20);

    CreateLinkByDestination("Jahres Grafik",            $YearUnlimitedMediaId,   $mobileId, 100);
    CreateLinkByDestination('Tages Grafik',             $DayUnlimitedMediaId,    $mobileId, 110);
    CreateLinkByDestination("Jahres Grafik (limited)",  $YearLimitedMediaId,     $mobileId, 120);
    CreateLinkByDestination('Tages Grafik (limited)',   $DayLimitedMediaId,      $mobileId, 130);
  }

Dieser Teil generiert die komplette Mobile GUI: Analog zum WebFront wird auch hier ein Ordner angelegt und darunter alle Elemente platziert.

Wichtig auch hier wieder, dass die ausgelesenen INI Parameter verwendet werden, damit auch eine Deinstallation wieder möglich ist. 

Dokumentation

Da die Dokumentation meistens zu kurz kommt, empfehle ich den Großteil der Dokumentation bereits während der Entwicklung des Modules zu machen.

Folgende Teile sollten dokumentiert sein:

  • Allgemeine Beschreibung des Modules – was kann es, was wird vorausgesetzt
  • Konfiguration – alle Konfigurations Parameter sollten detailiert beschrieben sein
  • Installation – kurze Beschreibung der Installation
  • API – falls vorhanden, sollte die API und deren Parameter beschrieben sein.
  • WebFront und Mobile GUI
  • Alle Files sollten einen Fileheader haben, der den Zweck beschreibt, den Filenamen und Author beinhaltet und auch eine Versionierung auflistet

Author, File und Version

Alle Dateien sollten einen kurzen Header haben, der den Author, den Filenamen und die Versions History beinhaltet:

*
* @file          IPSTwilight_Configuration.inc.php
* @author        Andreas Brauneis
* @version
*  Version 2.50.1, 13.02.2012<br/>
* 
 * Konfigurations File für IPSTwilight
* 

Allgemeine Beschreibung

*
* IPSTwilight ist ein IPS Modul, um die täglichen Dämmerungszeiten zu berechnen und grafisch darzustellen.
* Ein Timer berechnet jeden Tag automatisch die aktuellen Dämmerungszeiten.
*
* Es gibt die Möglichkeit durch Angabe einer Minimal bzw. Maximal Range die jeweilige Dämmerungszeit zu begrenzen.
*
* So ist es z.B. möglich mit einer Beschattungssteuerung das Schließen der Jalousien an die Dämmerungszeit zu binden, aber gleichzeitig 
 * zu definieren, dass das Schließen frühestens um 18:00 aber spätestens um 20:00 zu geschehen hat.
*
* Es werden folgende Dämmerungszeiten berechnet:
* - Sonnenaufgang/Sonnenuntergang
* - bürgerliche (zivile/ civil) Dämmerung - ist der Zeitpunkt, an dem die Sonne 6 Grad unter dem Horizont ist.
* - nautische Dämmerung - ist der Zeitpunkt, an dem die Sonne 12 Grad unter dem Horizont ist.
* - astronomische Dämmerung - ist der Zeitpunkt, an dem die Sonne 18 Grad unter dem Horizont ist.
*

Beschreibung der Konfigurations Parameter

Jeder Konfigurations Parameter sollte eine kurz Beschreibung haben, die seinen Zweck beschreibt und den Impact einer Änderung.

/**
* Angabe des Längengrades zur Berechnung der Dämmerung, eine Aktuallisierung der Werte erfolgt bei der nächsten Berechnung
* der Dämmerungswerte (Mitternacht). Ein Ausführen der Installation ist bei Änderung des Parameters nicht erforderlich.
*/
define ("IPSTWILIGHT_LONGITUDE", 16.37);

WebFront und Mobile GUI

Mit “defgroup”, “ingroup” und “addtogroup” kann man in Doxygen eine Gruppierung erzeugen. Diese kann auch dazu benützt werden Abschnitt Visualisierung zu gestalten, in dem sich einige Screenshot befinden um dem User eine bessere Vorstellung vom Modul zu ermöglichen.

Screenshots sollten immer als Prefix den Modul Namen haben und sind im Ordner IPSLibrary.Docu.Screenshots zu platzieren.

  /**@defgroup ipstwilight_visualization IPSTwilight Visualisierung
   * @ingroup ipstwilight
   * @{
   *
   * Visualisierungen von IPSTwilight
   *
   * IPSTwilight WebFront Visualisierung:
   *
   *  @image html IPSTwilight_WebFront.png
   *
   * IPSTwilight Mobile Visualisierung:
   *
   *  @image html IPSTwilight_Mobile.png
   *
   *@}*/ 

File Header

Alle Files sollten einen kurzen Header haben, der auf die GPL License hinweist:

  /*
   * This file is part of the IPSLibrary.
   *
   * The IPSLibrary is free software: you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published
   * by the Free Software Foundation, either version 3 of the License, or
   * (at your option) any later version.
   *
   * The IPSLibrary is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with the IPSLibrary. If not, see http://www.gnu.org/licenses/gpl.txt.
   */