[Skript] pirateweather.net

Sehr geil geworden! Hoffe ich kann es bald testen!
Cheers Seppm

Hi Heiko,

wollte mir das Ganze mit deiner Bibliothek und der Wetter Visu zu gemüte führen, aber muss sagen, dass ich keine klare „Anleitung“ in deinem Blog erkennen konnte wie ich die Bibliothek installiere. Ich vermute jetzt nur, dass ich alle Dateien aus der Bibliothek unter „Scripte“ ablegen muss. Ok, erledigt und Symcon mal sicherheitshalber neugestartet falls die Autoload erst dann ihren Zweck erfüllt.
Pirateweather API Secret hatte ich noch aus einem alten Script, welches auch noch funktioniert.

Wenn ich nun dein Weather Script ausführe kommt aber"Global function library not available!"
Also gehe ich davon aus, dass ich deine Bibliothek nicht vernünftig installiert habe. Eine „klare“ Anweisung was zu tun ist konnte ich hier nicht rauslesen. Has du einen Denkanstoß für mich ? :stuck_out_tongue:

Danke

1 „Gefällt mir“

Ich hatte es auch gestern versucht. Habe aber auch aufgegeben. :stuck_out_tongue_winking_eye:

Bin heute leider unterwegs, schreibe morgen mal ne kleine Anleitung!

1 „Gefällt mir“

Wie wär’s mit einem kleinen schicken Modul anstelle einer Anleitung. :crazy_face:

So, jetzt gibt es eine Anleitung :smiley:

Gruß Heiko

1 „Gefällt mir“

Moin,

habt ihr auch öfter die Mledung „Bad Gateway“?

11.03.2024, 11:00:16 | WEATHER              | Array
(
    [type] => 2
    [message] => file_get_contents(https://api.pirateweather.net/forecast/xxxxxx/xx.7xx7,xx.0xx5?exclude=minutely&lang=de&units=ca): Failed to open stream: HTTP request failed! HTTP/1.1 502 Bad Gateway

    [file] => /var/lib/symcon/scripts/24528.ips.php
    [line] => 195
)

@pitti
Kann man die Icons gegen Lizenzgebühr beim Anbieter beziehen bzw. woher sind diese?

Huhu. Ich hab mir mal zum Test die Scripte zusammenkopiert, und in der Zeile 476 meinen Key reingesetzt. Funktioniert auch wunderbar, nur sieht es so aus auf dem iPhone:


und wenn ich nach unten eins weiterziehe:

Hier der Test-Code:

<?php

declare(strict_types=1);

############################################################################################################################################ Functions
define('WWX_FUNCTIONS', true);

function ExtractGuid($name)
{
    // Modules
    $guids = IPS_GetModuleList();
    $result = false;
    foreach ($guids as $guid) {
        $module = IPS_GetModule($guid);
        if ($module['ModuleName'] == $name) {
            return $guid;
        }
    }
    // Actions/Automations
    $actions = json_decode(IPS_GetActions(), true);
    $matching = [];
    foreach ($actions as $action) {
        if ($action['caption'] == $name && count($action['form']) == 0) {
            $matching[] = $action;
        }
    }
    if (count($matching) == 1) {
        return $matching[0]['id'];
    }
    throw new Exception('GUID does not exist for ' . $name);
}

function CreateIdent($name, $lower = false)
{
    $umlaute = ['/ä/', '/ö/', '/ü/', '/Ä/', '/Ö/', '/Ü/', '/ß/'];
    $replace = ['ae', 'oe', 'ue', 'Ae', 'Oe', 'Ue', 'ss'];
    $ident = preg_replace($umlaute, $replace, $name);
    // idents immer klein?!?
    if ($lower) {
        $ident = strtolower($ident);
    }
    return preg_replace('/[^a-z0-9_]+/i', '', $ident);
}

function GetObjectByIdent($id, $ident, $internal = true)
{
    if($internal) {
        $ident = CreateIdent($ident);
    }
    return @IPS_GetObjectIDByIdent($ident, $id);
}

function GetObjectByName($id, $name)
{
    return @IPS_GetObjectIDByName($name, $id);
}

function CreateCategoryByName($id, $name, $pos = 0, $icon = '')
{
    $cid = GetCategoryByName($id, $name);
    if ($cid === false) {
        $cid = IPS_CreateCategory();
        IPS_SetName($cid, $name);
        IPS_SetParent($cid, $id);
        IPS_SetPosition($cid, $pos);
        IPS_SetIcon($cid, $icon);
    }
    return $cid;
}

function GetCategoryByName($id, $name)
{
    return @IPS_GetCategoryIDByName($name, $id);
}

function CreateDummyByName($id, $name, $pos = 0, $icon = '')
{
    return CreateDummyByIdent($id, $name, $name, $pos, $icon);
}

function GetDummyByName($id, $name)
{
    return GetObjectByName($id, $name);
}

function CreateDummyByIdent($id, $ident, $name, $pos = 0, $icon = '')
{
    $ident = CreateIdent($ident);
    $did = GetObjectByIdent($id, $ident);
    if ($did === false) {
        $did = IPS_CreateInstance(ExtractGuid('Dummy Module'));
        IPS_SetName($did, $name);
        IPS_SetIdent($did, $ident);
        IPS_SetParent($did, $id);
        IPS_SetPosition($did, $pos);
        IPS_SetIcon($did, $icon);
    }
    return $did;
}

function GetDummyByIdent($id, $ident)
{
    return GetObjectByIdent($id, $ident);
}

function CreatePopupByName($id, $name, $pos = 0, $icon = '')
{
    return CreatePopupByName($id, $name, $name, $pos, $icon);
}

function GetPopupByName($id, $name)
{
    return GetObjectByName($id, $name);
}

function CreatePopupByIdent($id, $ident, $name, $pos = 0, $icon = '')
{
    $ident = CreateIdent($ident);
    $pid = GetObjectByIdent($id, $ident);
    if ($pid === false) {
        $pid = IPS_CreateInstance(ExtractGuid('Popup Module'));
        IPS_SetName($pid, $name);
        IPS_SetIdent($pid, $ident);
        IPS_SetParent($pid, $id);
        IPS_SetPosition($pid, $pos);
        IPS_SetIcon($pid, $icon);
    }
    return $pid;
}

function GetPopupByIdent($id, $ident)
{
    return GetObjectByIdent($id, $ident);
}

function CreateVariableByName($id, $name, $type, $pos = 0, $icon = '', $profile = '', $action = null)
{
    $vid = GetVariableByName($id, $name);
    if ($vid === false) {
        $vid = IPS_CreateVariable($type);
        IPS_SetParent($vid, $id);
        IPS_SetName($vid, $name);
        IPS_SetPosition($vid, $pos);
        IPS_SetIcon($vid, $icon);
        if ($profile !== '') {
            IPS_SetVariableCustomProfile($vid, $profile);
        }
        if ($action != null) {
            IPS_SetVariableCustomAction($vid, $action);
        }
    }
    return $vid;
}

function GetVariableByName($id, $name)
{
    return @IPS_GetVariableIDByName($name, $id);
}

function CreateVariableByIdent($id, $ident, $name, $type, $pos = 0, $icon = '', $profile = '', $action = null)
{
    $ident = CreateIdent($ident);
    $vid = GetObjectByIdent($id, $ident);
    if ($vid === false) {
        $vid = IPS_CreateVariable($type);
        IPS_SetParent($vid, $id);
        IPS_SetName($vid, $name);
        IPS_SetIdent($vid, $ident);
        IPS_SetPosition($vid, $pos);
        IPS_SetIcon($vid, $icon);
        if ($profile !== '') {
            IPS_SetVariableCustomProfile($vid, $profile);
        }
        if ($action != null) {
            IPS_SetVariableCustomAction($vid, $action);
        }
    }
    return $vid;
}

function GetVariableByIdent($id, $ident)
{
    return GetObjectByIdent($id, $ident);
}

function CreateEventByName($id, $name, $time = 0)
{
    $eid = GetEventByName($id, $name);
    if (($eid === false) && ($time > 0)) {
        // Eventtyp = Zyklisch (1)
        $eid = IPS_CreateEvent(1);
        IPS_SetParent($eid, $id);
        IPS_SetName($eid, $name);
        IPS_SetPosition($eid, -2);
        IPS_SetHidden($eid, true);
    }
    if ($time > 0) {
        // Datumstyp = Tägliche (2), Datumsintervall = keins (1), Datumstage = keine (0), Datumstagesintervall = keine (0), Zeittyp = Einmalig (0), Zeitintervall = keine (0)
        IPS_SetEventCyclic($eid, 2, 1, 0, 0, 0, 0);
        IPS_SetEventCyclicDateFrom($eid, (int) date('j', $time), (int) date('n', $time), (int) date('Y', $time));
        IPS_SetEventCyclicDateTo($eid, 0, 0, 0);
        IPS_SetEventCyclicTimeFrom($eid, (int) date('H', $time), (int) date('i', $time), (int) date('s', $time));
        IPS_SetEventCyclicTimeTo($eid, 0, 0, 0);
        IPS_SetEventActive($eid, true);
        if (function_exists('IPS_SetEventAction')) {
            IPS_SetEventAction($eid, ExtractGuid('Run Automation'), []);
        }
    }
    return $eid;
}

function CreateEventByNameFromTo($id, $name, $type, $interval, $from, $to)
{
    $eid = GetEventByName($id, $name);
    if (($eid === false) && ($type > 0) && ($interval > 0)) {
        // Eventtyp = Zyklisch (1)
        $eid = IPS_CreateEvent(1);
        IPS_SetParent($eid, $id);
        IPS_SetName($eid, $name);
        IPS_SetPosition($eid, -2);
        IPS_SetHidden($eid, true);
    }
    if ($from > 0 && $to > 0) {
        // Datumstyp = Tägliche (2), Datumsintervall = keins (1), Datumstage = keine (0), Datumstagesintervall = keine (0), Zeittyp = Einmalig (0), Zeitintervall = keine (0)
        IPS_SetEventCyclic($eid, 2, 1, 0, 0, $type, $interval);
        IPS_SetEventCyclicTimeFrom($eid, (int) date('H', $from), (int) date('i', $from), (int) date('s', $from));
        IPS_SetEventCyclicTimeTo($eid, (int) date('H', $to), (int) date('i', $to), (int) date('s', $to));
        IPS_SetEventActive($eid, true);
        if (function_exists('IPS_SetEventAction')) {
            IPS_SetEventAction($eid, ExtractGuid('Run Automation'), []);
        }
    }
    return $eid;
}

function CreateTimerByName($id, $name, $time = 0, $repeat = true)
{
    $eid = GetEventByName($id, $name);
    if (($eid === false) && ($time > 0)) {
        // Eventtyp = Zyklisch (1)
        $eid = IPS_CreateEvent(1);
        IPS_SetParent($eid, $id);
        IPS_SetName($eid, $name);
        IPS_SetPosition($eid, -1);
        IPS_SetHidden($eid, true);
        if ($repeat == true) {
            // 0 = Tägliche Ausführung
            IPS_SetEventCyclic($eid, 0, 1, 0, 0, 2, $time);
            $now = time();
            IPS_SetEventCyclicDateFrom($eid, (int) date('j', $now), (int) date('n', $now), (int) date('Y', $now));
        } else {
            // Einmalige Ausführung
            IPS_SetEventCyclic($eid, 1, 0, 0, 0, 0, 0);
            IPS_SetEventCyclicDateFrom($eid, (int) date('j', $time), (int) date('n', $time), (int) date('Y', $time));
            IPS_SetEventCyclicDateTo($eid, (int) date('j', $time), (int) date('n', $time), (int) date('Y', $time));
            IPS_SetEventCyclicTimeFrom($eid, (int) date('H', $time), (int) date('i', $time), (int) date('s', $time));
            IPS_SetEventCyclicTimeTo($eid, (int) date('H', $time), (int) date('i', $time), (int) date('s', $time));
        }
        IPS_SetEventActive($eid, true);
        if (function_exists('IPS_SetEventAction')) {
            IPS_SetEventAction($eid, ExtractGuid('Run Automation'), []);
        }
    }
    return $eid;
}

function GetEventByName($id, $name)
{
    return @IPS_GetEventIDByName($name, $id);
}

function CreateScriptByName($id, $name)
{
    $sid = GetScriptByName($id, $name);
    if ($sid === false) {
        $sid = IPS_CreateScript(0);
        IPS_SetName($sid, $name);
        IPS_SetParent($sid, $id);
    }
    return $sid;
}

function GetScriptByName($id, $name)
{
    return @IPS_GetScriptIDByName($name, $id);
}

function RegisterHook($webhook, $id)
{
    $ids = IPS_GetInstanceListByModuleID(ExtractGuid('WebHook Control'));
    if (count($ids) > 0) {
        $hooks = json_decode(IPS_GetProperty($ids[0], 'Hooks'), true);
        $found = false;
        foreach ($hooks as $index => $hook) {
            if ($hook['Hook'] == $webhook) {
                if ($hook['TargetID'] == $id) {
                    return;
                }
                $hooks[$index]['TargetID'] = $id;
                $found = true;
            }
        }
        if (!$found) {
            $hooks[] = ['Hook' => $webhook, 'TargetID' => $id];
        }
        IPS_SetProperty($ids[0], 'Hooks', json_encode($hooks));
        IPS_ApplyChanges($ids[0]);
    }
}

function UnregisterHook($hook)
{
    $ids = IPS_GetInstanceListByModuleID(ExtractGuid('WebHook Control'));
    if (count($ids) > 0) {
        $hooks = json_decode(IPS_GetProperty($ids[0], 'Hooks'), true);
        $found = false;
        foreach ($hooks as $key => $value) {
            if ($value['Hook'] == $hook) {
                $found = true;
                $this->SendDebug('UnregisterHook', $hook . $this->InstanceID);
                break;
            }
        }
        // Unregister
        if ($found == true) {
            array_splice($hooks, $key, 1);
            IPS_SetProperty($ids[0], 'Hooks', json_encode($hooks));
            IPS_ApplyChanges($ids[0]);
        }
    }
}

function RegisterArchive($id, $default = true, $zero = false)
{
    $ids = IPS_GetInstanceListByModuleID(ExtractGuid('Archive Control'));
    if (count($ids) > 0) {
        AC_SetLoggingStatus($ids[0], $id, true);
        AC_SetAggregationType($ids[0], $id, ($default ? 0 : 1));
        if ($zero) {
            AC_SetCounterIgnoreZeros($ids[0], $id, true);
        }
    }
}

function UnregisterArchive($id)
{
    $ids = IPS_GetInstanceListByModuleID(ExtractGuid('Archive Control'));
    if (count($ids) > 0) {
        AC_SetLoggingStatus($ids[0], $id, false);
    }
}

function CreateProfile($name, $type)
{
    if (!IPS_VariableProfileExists($name)) {
        IPS_CreateVariableProfile($name, $type);
    } else {
        $profile = IPS_GetVariableProfile($name);
        if ($profile['ProfileType'] != $type) {
            throw new Exception('Variable profile type does not match for profile ' . $name);
        }
    }
}

function CreateProfileBoolean($name, $icon, $prefix, $suffix, $asso)
{
    CreateProfile($name, 0);
    IPS_SetVariableProfileIcon($name, $icon);
    IPS_SetVariableProfileText($name, $prefix, $suffix);

    if (($asso !== null) && (count($asso) !== 0)) {
        foreach ($asso as $ass) {
            IPS_SetVariableProfileAssociation($name, $ass[0], $ass[1], $ass[2], $ass[3]);
        }
    }
}

function CreateProfileInteger($name, $icon, $prefix, $suffix, $minvalue, $maxvalue, $step, $asso = null)
{
    CreateProfile($name, 1);
    IPS_SetVariableProfileIcon($name, $icon);
    IPS_SetVariableProfileText($name, $prefix, $suffix);
    IPS_SetVariableProfileValues($name, $minvalue, $maxvalue, $step);

    if (($asso !== null) && (count($asso) !== 0)) {
        foreach ($asso as $ass) {
            IPS_SetVariableProfileAssociation($name, $ass[0], $ass[1], $ass[2], $ass[3]);
        }
    }
}

function CreateProfileFloat($name, $icon, $prefix, $suffix, $minvalue, $maxvalue, $step, $digits, $asso = null)
{
    CreateProfile($name, 2);
    IPS_SetVariableProfileIcon($name, $icon);
    IPS_SetVariableProfileText($name, $prefix, $suffix);
    IPS_SetVariableProfileDigits($name, $digits);
    /*
        if(($asso == null) && (count($asso) == 0)){
            $minvalue = 0;
            $maxvalue = 0;
        }
     */
    IPS_SetVariableProfileValues($name, $minvalue, $maxvalue, $step);
    if (($asso !== null) && (count($asso) !== 0)) {
        foreach ($asso as $ass) {
            IPS_SetVariableProfileAssociation($name, $ass[0], $ass[1], $ass[2], $ass[3]);
        }
    }
}

function CreateProfileString($name, $icon, $prefix, $suffix, $asso)
{
    CreateProfile($name, 3);
    IPS_SetVariableProfileIcon($name, $icon);
    IPS_SetVariableProfileText($name, $prefix, $suffix);

    if (($asso !== null) && (count($asso) !== 0)) {
        foreach ($asso as $ass) {
            IPS_SetVariableProfileAssociation($name, $ass[0], $ass[1], $ass[2], $ass[3]);
        }
    }
}

function UnregisterProfile($name)
{
    if (!IPS_VariableProfileExists($name)) {
        return false;
    }
    foreach (IPS_GetVariableList() as $vid) {
        if (IPS_GetVariable($vid)['VariableCustomProfile'] == $name) {
            return false;
        }
        if (IPS_GetVariable($vid)['VariableProfile'] == $name) {
            return false;
        }
    }
    return IPS_DeleteVariableProfile($name);
}

function EchoDebug($msg, $data, $pre = null)
{
    // Safty Check for use!
    if (!isset($GLOBALS['DEBUG'])) {
        echo "!!! For Debug Output define global variable 'DEBUG' (true|false) !!!";
        return;
    }
    // only if Debug enabled
    if ($GLOBALS['DEBUG']) {
        if (is_object($data)) {
            foreach ($data as $key => $value) {
                EchoDebug($msg, $value, $key);
            }
        } elseif (is_array($data)) {
            if ($pre !== null) {
                echo $msg . ': ' . $pre . '(array) =>' . PHP_EOL;
            }
            foreach ($data as $key => $value) {
                EchoDebug($msg, $value, $key);
            }
        } elseif (is_bool($data)) {
            echo $msg . ': ' . ($pre !== null ? $pre . ' => ' : '') . ($data ? 'TRUE' : 'FALSE') . PHP_EOL;
        } else {
            echo $msg . ': ' . ($pre !== null ? $pre . ' => ' : '') . $data . PHP_EOL;
        }
    }
}

############################################################################################################################################ LOCALs

// Globale Private Definition (API-Keys, API-Tockens usw.)
// Benennung des Arrays und der Schlüssel kann jeder selber definieren!

define('__WWX', [
    'MY_APIKEY' => 'xyz-xyz-xyz',
    'PWN_TOKEN' => 'dasIstMeinPrivaterKey',
    // ....
]);
############################################################################################################################################ CFG
# Global Debug Output Flag
$DEBUG = false;
#
# Globale Variable __WWX als Array via define() in __autoload definiert!!!
$API = __WWX['PWN_TOKEN'];   // # API-Token (Key)
#
# Location Control ID (wenn 0 => müssen $LAT & $LON korrekt gesetzt werden)
$LCID = 0;
# Latitude/Längengrad
$LAT = 52.5208;
# Longitude/Breitengrad
$LON = 13.4094;
#
# Ortsinfos setzen
if ($LCID != 0) {
    $location = json_decode(IPS_GetProperty($LCID, 'Location'), true);
    $LAT = $location['latitude'];
    $LON = $location['longitude'];
}
#
# Settings für HTML-Boxen;
$HTML = [
    'temp'      => 0,       // ID eigenen Temperaturvariable, z.B. von Wetterstation
    'chance'    => 0,       // ID eigener Niederschlagswahrscheinlichkeit, z.B. von Wetterstation
    'wind'      => 0,       // ID eigener Windgeschwindigkeit, z.B. von Wetterstation
    'direction' => 0,       // ID eigener Windrichtung, z.B. von Wetterstation
    'humidity'  => 0,       // ID eigener Luftfeutigkeit (Aussen), z.B. von Wetterstation
    'rain'      => 0,       // ID eigener Niederschlagsmenge, z.B. von Wetterstation
    'sunrise'   => date_sunrise(time(), SUNFUNCS_RET_STRING, $LAT, $LON, 90, 1),  // Uhrzeit 'hh:mm' für Sonnenaufgang, oder via GetValue() vom Location Modul Variable => date('H:i', Getvalue(12345));
    'sunset'    => date_sunset(time(), SUNFUNCS_RET_STRING, $LAT, $LON, 90, 1),   // Uhrzeit 'hh:mm' für Sonnenuntergang, oder via GetValue() vom Location Modul Variable => date('H:i', Getvalue(12345));
    'webfront'  => true,    // true = Support für WebFront ('3-Tage-Wetter' & '24-Stunden--Wetter'), IPS <= v6.4
    'tilevisu'  => true,    // true = Support für Tile Visu ('Aktuelles-Wetter'). IPS >= v7.0
    'icon01'    => false,   // true = Nutzung eigener Icons für aktuelle Wetterlage (siehe Array $ICONS) oder nachfolgende URL hinterlegen
    'icon03'    => false,   // true = Nutzung eigener Icons für 3 Tage Vorhersage (siehe Array $ICONS) oder nachfolgende URL hinterlegen
    'icon07'    => false,   // true = Nutzung eigener Icons für 7 Tage Vorhersage (siehe Array $ICONS) oder nachfolgende URL hinterlegen
    'icon24'    => false,   // true = Nutzung eigener Icons für 24 Stunden Vorhersage (siehe Array $ICONS) oder nachfolgende URL hinterlegen
    'ibase'     => 'https://basmilius.github.io/weather-icons/production/line/all/', // URL Base für Online-Icons (.../fill/all/ or .../line/all/)
    'iext'      => '.svg',  // Image Type Extension (.png, .svg, .jpg, ...)
    'theme'     => 'hell',  // 'hell' oder 'dunkel'
];
#
# Globale Übersetzungstabelle
$TRANS = [
    'Monday'    => 'Montag',
    'Tuesday'   => 'Dienstag',
    'Wednesday' => 'Mittwoch',
    'Thursday'  => 'Donnerstag',
    'Friday'    => 'Freitag',
    'Saturday'  => 'Samstag',
    'Sunday'    => 'Sonntag',
    'Mon'       => 'Mo',
    'Tue'       => 'Di',
    'Wed'       => 'Mi',
    'Thu'       => 'Do',
    'Fri'       => 'Fr',
    'Sat'       => 'Sa',
    'Sun'       => 'So',
    'January'   => 'Januar',
    'February'  => 'Februar',
    'March'     => 'März',
    'May'       => 'Mai',
    'June'      => 'Juni',
    'July'      => 'Juli',
    'October'   => 'Oktober',
    'December'  => 'Dezember',
    // Summary texts
    'Clear'         => 'Klar',
    'Cloudy'        => 'Bewölkt',
    'Partly Cloudy' => 'Teilweise bewölkt',
    'Rain'          => 'Regen',
];
#
# Icon Mapping Array - freies Mapping auf eigene lokale Icons
# Pirate Weather kennt folgende Namen für Icons:
#  clear-day, clear-night,
#  rain, snow, sleet, wind, fog, cloudy,
#  partly-cloudy-day, partly-cloudy-night
$ICONS = [
    // -------------------------------- day ------------------------------------
    'day' => [
        'clear'  => '/user/weather/img/day/day_sunny.png',
        'rain'   => '/user/weather/img/day/day_heavy_rain.png',
        'snow'   => '/user/weather/img/day/day_heavy_snow.png',
        'sleet'  => '/user/weather/img/day/day_sleet.png',
        'wind'   => '/user/weather/img/day/day_overcast.png',
        'fog'    => '/user/weather/img/day/day_fog.png',
        'cloudy' => '/user/weather/img/day/day_clouded.png',
        'partly' => '/user/weather/img/day/day_cloudy.png',
    ],
    // ------------------------------- night -----------------------------------
    'night' => [
        'clear'  => '/user/weather/img/night/night_sunny.png',
        'rain'   => '/user/weather/img/night/night_heavy_rain.png',
        'snow'   => '/user/weather/img/night/night_heavy_snow.png',
        'sleet'  => '/user/weather/img/night/night_sleet.png',
        'wind'   => '/user/weather/img/night/night_overcast.png',
        'fog'    => '/user/weather/img/night/night_fog.png',
        'cloudy' => '/user/weather/img/night/night_clouded.png',
        'partly' => '/user/weather/img/night/night_cloudy.png',
    ],
    // -------------------------------- unknown --------------------------------
    'unknown' => [
        'icon' => '/user/weather/img/night/night_thunderstorm.png',
    ],
];
#
################################################################################
defined('WWX_FUNCTIONS') || die('Global function library not available!');

// INSTALLATION
if ($_IPS['SENDER'] == 'Execute') {
    $pos = 1; // 0 für Forecast
    // Variablen
    $vid = CreateVariableByName($_IPS['SELF'], 'Temperatur', 2, $pos++, '', '~Temperature');
    $vid = CreateVariableByName($_IPS['SELF'], 'Gefühlte Temperatur', 2, $pos++, '', '~Temperature');
    $vid = CreateVariableByName($_IPS['SELF'], 'Taupunkt', 2, $pos++, '', '~Temperature');
    $vid = CreateVariableByName($_IPS['SELF'], 'Bewölkung', 2, $pos++, 'Cloudy', '~Intensity.1');
    $vid = CreateVariableByName($_IPS['SELF'], 'Luftfeuchtigkeit', 2, $pos++, 'Drops', '~Intensity.1');
    $vid = CreateVariableByName($_IPS['SELF'], 'Luftdruck', 2, $pos++, '', '~AirPressure.F');
    $vid = CreateVariableByName($_IPS['SELF'], 'Niederschlag', 3, $pos++, 'Rainfall');
    $vid = CreateVariableByName($_IPS['SELF'], 'Niederschlag/h', 2, $pos++, '~Rainfall');
    $vid = CreateVariableByName($_IPS['SELF'], 'Niederschlagswahrscheinlichkeit', 2, $pos++, 'Rainfall', '~Intensity.1');
    $vid = CreateVariableByName($_IPS['SELF'], 'Windgeschwindigkeit', 2, $pos++, '', '~WindSpeed.kmh');
    $vid = CreateVariableByName($_IPS['SELF'], 'Windrichtung', 2, $pos++, '', '~WindDirection.Text');
    $vid = CreateVariableByName($_IPS['SELF'], 'Windböe', 2, $pos++, '', '~WindSpeed.kmh');
    $vid = CreateVariableByName($_IPS['SELF'], 'Sichtweite', 2, $pos++);
    $vid = CreateVariableByName($_IPS['SELF'], 'UV Strahlung', 1, $pos++);
    $vid = CreateVariableByName($_IPS['SELF'], 'Ozonwert', 2, $pos++);
    $vid = CreateVariableByName($_IPS['SELF'], 'Zusammenfassung', 3, $pos++, 'Talk');
    $vid = CreateVariableByName($_IPS['SELF'], 'Icon', 3, $pos++);
    $vid = CreateVariableByName($_IPS['SELF'], 'Uhrzeit', 1, $pos++, '~UnixTimestamp');
    // Weateher & Forecast HTML Boxes
    $vid = CreateVariableByName($_IPS['SELF'], 'Aktuelles-Wetter', 3, $pos++, '', '~HTMLBox');
    $vid = CreateVariableByName($_IPS['SELF'], '3-Tage-Wetter', 3, $pos++, '', '~HTMLBox');
    $vid = CreateVariableByName($_IPS['SELF'], '24-Stunden-Wetter', 3, $pos++, '', '~HTMLBox');
    // Service Update Timer (aller 10 Minuten)
    $eid = CreateTimerByName($_IPS['SELF'], 'ServiceUpdate', 10);
    IPS_SetHidden($eid, true);
    IPS_SetPosition($eid, -1);
}
// TIMER EVENT
elseif($_IPS['SENDER'] == 'TimerEvent') {
    //  Daten abholen
    $url = "https://api.pirateweather.net/forecast/$API/$LAT,$LON?exclude=minutely&lang=de&units=ca";
    if($DEBUG) EchoDebug('WEATHER', $url);
    $json = @file_get_contents($url);
    if($DEBUG) EchoDebug('WEATHER', $json);
    // Handle the error
    if ($json === false) {
        $error = error_get_last();
        IPS_LogMessage('WEATHER', print_r($error, true));
        exit();
    }
    $data = json_decode($json);
    // Aktuelle Daten
    SetCurrentWeather($data->{'currently'});
    // Tägliche Daten holen
    SetDailyWeather($data->{'daily'}->{'data'});
    // 24h Daten holen
    SetHourlyWeather($data->{'hourly'}->{'data'});
}

// Extrahiert die aktuellen Wetterdaten
function SetCurrentWeather($current)
{
    $vid = CreateVariableByName($_IPS['SELF'], 'Uhrzeit', 1);
    SetValue($vid, $current->time);
    $vid = CreateVariableByName($_IPS['SELF'], 'Zusammenfassung', 3);
    SetValue($vid, $current->summary);
    $vid = CreateVariableByName($_IPS['SELF'], 'Icon', 3);
    SetValue($vid, $current->icon);
    $vid = CreateVariableByName($_IPS['SELF'], 'Niederschlag', 3);
    @$niederschlag = $current->precipType;
    $niederschlag = GetPrecipitation($niederschlag);
    SetValue($vid, GetPrecipitation($niederschlag));
    $vid = CreateVariableByName($_IPS['SELF'], 'Niederschlag/h', 2);
    SetValue($vid, $current->precipIntensity);
    $vid = CreateVariableByName($_IPS['SELF'], 'Niederschlagswahrscheinlichkeit', 2);
    SetValue($vid, $current->precipProbability);
    $vid = CreateVariableByName($_IPS['SELF'], 'Temperatur', 2);
    SetValue($vid, $current->temperature);
    $vid = CreateVariableByName($_IPS['SELF'], 'Gefühlte Temperatur', 2);
    SetValue($vid, $current->apparentTemperature);
    $vid = CreateVariableByName($_IPS['SELF'], 'Taupunkt', 2);
    SetValue($vid, $current->dewPoint);
    $vid = CreateVariableByName($_IPS['SELF'], 'Luftfeuchtigkeit', 2);
    SetValue($vid, $current->humidity);
    $vid = CreateVariableByName($_IPS['SELF'], 'Luftdruck', 2);
    SetValue($vid, $current->pressure);
    $vid = CreateVariableByName($_IPS['SELF'], 'Windgeschwindigkeit', 2);
    SetValue($vid, $current->windSpeed);
    $vid = CreateVariableByName($_IPS['SELF'], 'Windböe', 2);
    SetValue($vid, $current->windGust);
    $vid = CreateVariableByName($_IPS['SELF'], 'Windrichtung', 2);
    SetValue($vid, $current->windBearing);
    $vid = CreateVariableByName($_IPS['SELF'], 'Bewölkung', 2);
    SetValue($vid, $current->cloudCover);
    $vid = CreateVariableByName($_IPS['SELF'], 'UV Strahlung', 1);
    SetValue($vid, $current->uvIndex);
    $vid = CreateVariableByName($_IPS['SELF'], 'Sichtweite', 2);
    SetValue($vid, $current->visibility);
    $vid = CreateVariableByName($_IPS['SELF'], 'Ozonwert', 1);
    SetValue($vid, $current->ozone);
}

// Extrahiere die Tageswerte und baue HTML Box zusammen
function SetDailyWeather($days)
{
    global $TRANS, $HTML;
    // Json Daten speichern
    $vid = CreateVariableByName($_IPS['SELF'], 'Forecast', 3);
    SetValue($vid, json_encode($days));
    // Icon holen
    $vid = CreateVariableByName($_IPS['SELF'], 'Icon', 3);
    $ico = GetValue($vid);
    $url = GetIcon($ico, 'icon01');
    // Text holen
    $vid = CreateVariableByName($_IPS['SELF'], 'Zusammenfassung', 3);
    $txt = strtr(GetValue($vid), $TRANS);
    // Temperatur
    $vid = CreateVariableByName($_IPS['SELF'], 'Temperatur', 2);
    if ($HTML['temp'] != 0) {
        $vid = $HTML['temp'];
    }
    $tmp = GetValue($vid);
    // Sun
    $snr = $HTML['sunrise'];
    $sns = $HTML['sunset'];
    // Niederschlagswahrscheinlichkeit
    $fall = '<span class="txt fall">{{fall}} Regen</span>';
    $vid = CreateVariableByName($_IPS['SELF'], 'Niederschlagswahrscheinlichkeit', 2);
    if($HTML['chance'] != 0) {
        $vid = $HTML['chance'];
    }
    $value = GetValueFormatted($vid);
    $fall = str_replace('{{fall}}', $value, $fall);
    // Wind
    $wind = '<span class="txt wind">{{wind}}</span>';
    $vid = CreateVariableByName($_IPS['SELF'], 'Windgeschwindigkeit', 2);
    if($HTML['wind'] != 0) {
        $vid = $HTML['wind'];
    }
    $value = GetValueFormatted($vid);
    $vid = CreateVariableByName($_IPS['SELF'], 'Windrichtung', 2);
    if($HTML['direction'] != 0) {
        $vid = $HTML['direction'];
    }
    $value = $value . ' ' . GetValueFormatted($vid);
    $wind = str_replace('{{wind}}', $value, $wind);
    // Luftfeuchtigkeit
    $humi = '<span class="txt humi">{{humi}} Luftfeuchte</span>';
    $vid = CreateVariableByName($_IPS['SELF'], 'Luftfeuchtigkeit', 2);
    if($HTML['humidity'] != 0) {
        $vid = $HTML['humidity'];
    }
    $value = GetValueFormatted($vid);
    $humi = str_replace('{{humi}}', $value, $humi);
    // Niederschlag/h
    $rain = '<span class="txt rain">{{rain}}/h</span>';
    $vid = CreateVariableByName($_IPS['SELF'], 'Niederschlag/h', 2);
    if($HTML['rain'] != 0) {
        $vid = $HTML['rain'];
    }
    $value = GetValueFormatted($vid);
    $rain = str_replace('{{rain}}', $value, $rain);
    // HTML WebFront
    if ($HTML['webfront']) {
        $htmlWF = '';
        $htmlWF .= '<style type="text/css">';
        $htmlWF .= '.wdiv { height:220px; display:flex;}';
        $htmlWF .= '.wbox { display:inline-block; position:relative; border:1px solid rgba(255, 255, 255, 0.1); height:220px; margin: 0px 10px 0px 0px; color: rgb(255, 255, 255); background-image: linear-gradient(top,rgba(0,0,0,0) 0,rgba(0,0,0,0.3) 50%,rgba(0,0,0,0.3) 100%); background-image: -o-linear-gradient(top,rgba(0,0,0,0) 0,rgba(0,0,0,0.3) 50%,rgba(0,0,0,0.3) 100%); background-image: -moz-linear-gradient(top,rgba(0,0,0,0) 0,rgba(0,0,0,0.3) 50%,rgba(0,0,0,0.3) 100%); background-image: -webkit-linear-gradient(top,rgba(0,0,0,0) 0,rgba(0,0,0,0.3) 50%,rgba(0,0,0,0.3) 100%); background-image: -ms-linear-gradient(top,rgba(0,0,0,0) 0,rgba(0,0,0,0.3) 50%,rgba(0,0,0,0.3) 100%);}';
        $htmlWF .= '.wday { position:absolute; top:10px; left:10px; font-size:20px; font-weight:bold; color:rgba(255, 255, 255, 0.5); overflow:hidden;}';
        $htmlWF .= '.wdeb { position:absolute; top:0px; right:5px; font-size:72px; font-weight:bold; overflow:hidden;}';
        $htmlWF .= '.wdes { position:absolute; top:35px; left:10px; right: 100px; font-size:12px;  color:rgba(255, 255, 255, 0.5); overflow:hidden;}';
        $htmlWF .= '.wicb { position:absolute; bottom:0px; overflow:hidden;}';
        $htmlWF .= '.wics { position:absolute; width:115px; top:45px; text-align:center; overflow:hidden;}';
        $htmlWF .= '.wdec { position:absolute; width:115px; bottom:35px; text-align:center; font-size:48px; font-weight:bold; overflow:hidden;}';
        $htmlWF .= '.wtec { position:absolute; width:110px; bottom:5px; text-align:center; text-overflow: ellipsis; font-size:10px;  color:rgba(255, 255, 255, 0.5); overflow:hidden;}';
        $htmlWF .= '.wder { position:absolute; bottom:42px; right:5px; text-align:right; font-size:16px; color:rgba(255, 255, 255, 0.5); overflow:hidden;}';
        $htmlWF .= '.wsgl { position:absolute; bottom:5px; left:10px; text-align:left; font-size:12px; color:rgba(255, 255, 255, 0.5); overflow:hidden;}';
        $htmlWF .= '.wssr { position:absolute; bottom:5px; right:10px; text-align:right; font-size:12px; color:rgba(255, 255, 255, 0.5); overflow:hidden;}';
        $htmlWF .= '.warw { position:absolute; width:25px; left:10px; bottom:70px; text-align:center; font-size:48px; font-weight:bold; overflow:hidden; background-repeat:no-repeat; background-image: url(data:image/svg+xml;utf8;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pgo8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMTYuMC4wLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogNi4wMCBCdWlsZCAwKSAgLS0+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiBpZD0iQ2FwYV8xIiB4PSIwcHgiIHk9IjBweCIgd2lkdGg9IjMycHgiIGhlaWdodD0iMzJweCIgdmlld0JveD0iMCAwIDQ2LjAyIDQ2LjAyIiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCA0Ni4wMiA0Ni4wMjsiIHhtbDpzcGFjZT0icHJlc2VydmUiPgo8Zz4KCTxnPgoJCTxwYXRoIGQ9Ik0xNC43NTcsNDYuMDJjLTEuNDEyLDAtMi44MjUtMC41MjEtMy45MjktMS41NjljLTIuMjgyLTIuMTctMi4zNzMtNS43OC0wLjIwNC04LjA2M2wxMi43NTgtMTMuNDE4TDEwLjYzNyw5LjY0NSAgICBDOC40Niw3LjM3LDguNTQsMy43NiwxMC44MTYsMS41ODJjMi4yNzctMi4xNzgsNS44ODYtMi4wOTcsOC4wNjMsMC4xNzlsMTYuNTA1LDE3LjI1M2MyLjEwNCwyLjIsMi4xMDgsNS42NjUsMC4wMTMsNy44NzIgICAgTDE4Ljg5Myw0NC4yNDdDMTcuNzcsNDUuNDI0LDE2LjI2Nyw0Ni4wMiwxNC43NTcsNDYuMDJ6IiBmaWxsPSIjRkZGRkZGIi8+Cgk8L2c+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPC9zdmc+Cg==)}';
        $htmlWF .= '.wtew { position:absolute; width:50px; bottom:5px; text-align:center; text-overflow: ellipsis; font-size:12px;  color:rgba(255, 255, 255, 0.5); overflow:hidden;}';
        $htmlWF .= '</style>';
        // Aktueller Daten
        $htmlWF .= '<div class="wdiv">';
        $htmlWF .= '<div class="wbox" style="width:225px;">';
        $htmlWF .= '<div class="wday">Aktuell</div>';
        $htmlWF .= '<div class="wdeb">' . (round($tmp, 0) + 0) . '°</div>';
        $htmlWF .= '<div class="wdes">' . $txt . '</div>';
        $htmlWF .= '<div class="wicb"><img style="width:220px; height:140px;" src="' . $url . '" /></div>';
        $htmlWF .= '<div class="wsgl">&uarr;&nbsp;' . $snr . '</div>';
        $htmlWF .= '<div class="wssr">' . $sns . '&nbsp;&darr;</div>';
        $htmlWF .= '</div>';
        // Forcast (next 3 Days)
        for($i = 1; $i < 4; $i++) {
            $day = $days[$i]->time;
            $sum = strtr($days[$i]->summary, $TRANS);
            $thi = $days[$i]->temperatureHigh;
            $tlo = $days[$i]->temperatureLow;
            $wdy = date('D', intval($day));
            $wdy = strtr($wdy, $TRANS);
            $ico = GetIcon($days[$i]->icon, 'icon03');
            $htmlWF .= '<div class="wbox" style="width:115px;">';
            $htmlWF .= '<div class="wday">' . $wdy . '</div>';
            $htmlWF .= '<div class="wics"><img style="width:125px; height:74px;" src="' . $ico . '" /></div>';
            $htmlWF .= '<div class="wdec">' . (round($thi, 0) + 0) . '°</div>';
            $htmlWF .= '<div class="wder">' . (round($tlo, 0) + 0) . '°</div>';
            $htmlWF .= '<div class="wtec">' . $txt . '</div>';
            $htmlWF .= '</div>';
        }
        // Box ready
        $htmlWF .= '</div>';
        // Days speichern
        $vid = CreateVariableByName($_IPS['SELF'], '3-Tage-Wetter', 3);
        SetValue($vid, $htmlWF);
    }
    // HTML Tile Visu
    if ($HTML['tilevisu']) {
        $bgc = ($HTML['theme'] == 'hell') ? '#00CDAB' : '#24625B';
        $iif = ($HTML['theme'] == 'hell') ? ' filter: invert(0.6);' : '';
        $htmlTV = '<meta name="viewport" content="width=device-width, initial-scale=1">';
        $htmlTV .= '<style type="text/css">';
        $htmlTV .= 'body {margin:0px;}';
        $htmlTV .= '::-webkit-scrollbar{width:8px;}';
        $htmlTV .= '::-webkit-scrollbar-track{background:transparent;}';
        $htmlTV .= '::-webkit-scrollbar-thumb{background:transparent; border-radius:20px;}';
        $htmlTV .= '::-webkit-scrollbar-thumb:hover{background:#555;}';
        $htmlTV .= '.cardS {display:block;}';
        $htmlTV .= '.cardM {display:none;}';
        $htmlTV .= '.cardL {display:none;}';
        $htmlTV .= '#grid {width:100%; height:100%; display:grid; justify-items:center;}';
        $htmlTV .= '#grid > div {justify-content:center; align-items:center; display:flex; width:100%;}';
        $htmlTV .= '.wdes {position:absolute; top:0px; left:0px; font-size:7vw; width:50%; overflow:hidden;}';
        $htmlTV .= '.wdeg {position:absolute; top:0px; right:0px; font-size:25vw; line-height:1em; overflow:hidden;}';
        $htmlTV .= '.wico {width:100%; height:80vw; position:absolute; bottom:0px; background-image:url(' . $url . '); background-size:contain; background-repeat:no-repeat; background-position-x:center; background-position-y:bottom;}';
        $htmlTV .= '.wsgl {position:absolute; bottom:0px; left:0px; font-size:6vw; opacity: 75%;}';
        $htmlTV .= '.wssr {position:absolute; bottom:0px; right:0px; font-size:6vw; opacity: 75%;}';
        $htmlTV .= '.wfgd {position: absolute; bottom: 0; width: 100%; padding-top: 5px; display: grid; border-top: solid 2px ' . $bgc . '; grid-template-rows: auto; grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr; margin: 0 auto; justify-content: center; text-align: center;}';
        $htmlTV .= '.wfgd > .day {font-size: 6vh;}';
        $htmlTV .= '.wfgd > .img {width: 48px; height: 48px; margin: auto; display: block; }';
        $htmlTV .= '.wfgd > .txt {color: white; background: ' . $bgc . '; border-radius:5px; margin: 0 4px}';
        $htmlTV .= '.wifo {position: absolute; top: 0; right: 0; display: grid; grid-template-rows: 1fr 1fr 1fr 1fr ; grid-template-columns: auto; margin: 0 auto; justify-content: center;}';
        $htmlTV .= '.wifo > .txt {font-size: 7vh; opacity: 75%;}';
        $htmlTV .= '.fall:before {content: ""; background: url("/preview/assets/icons/Umbrella.svg") no-repeat; background-size: cover; width: 4vw; height: 100%; float: left; margin: 0 6px 0 0;' . $iif . '}';
        $htmlTV .= '.humi:before {content: ""; background: url("/preview/assets/icons/Drops.svg") no-repeat; background-size: cover; width: 4vw; height: 100%; float: left; margin: 0 6px 0 0;' . $iif . '}';
        $htmlTV .= '.wind:before {content: ""; background: url("/preview/assets/icons/WindSpeed.svg") no-repeat; background-size: cover; width: 4vw; height: 100%; float: left; margin: 0 6px 0 0;' . $iif . '}';
        $htmlTV .= '.rain:before {content: ""; background: url("/preview/assets/icons/Rainfall.svg") no-repeat; background-size: cover; width: 4vw; height: 100%; float: left; margin: 0 6px 0 0;' . $iif . '}';
        $htmlTV .= '.hidden {display:none;}';
        $htmlTV .= '@media (aspect-ratio >1.5) {';
        $htmlTV .= '  .cardS {display:none;}';
        $htmlTV .= '  .cardM {display:block;}';
        $htmlTV .= '  .cardL {display:none;}';
        $htmlTV .= '  .wdes {font-size:3vw; width:25vw;}';
        $htmlTV .= '  .wdeg {font-size:12vw; right: 40vw;}';
        $htmlTV .= '  .wsgl, .wssr { font-size: 2.5vw; bottom: 57vh;}';
        $htmlTV .= '  .wssr {right: 40vw;}';
        $htmlTV .= '  .wico {top: 0px; height: 45vh; width: 60vw}';
        $htmlTV .= '}';
        $htmlTV .= '@media screen and (min-width:768px){';
        $htmlTV .= '  .cardS {display:block;}';
        $htmlTV .= '  .cardM {display:none;}';
        $htmlTV .= '  .cardL {display:none;}';
        $htmlTV .= '}';
        $htmlTV .= '</style>';
        // Aktueller Daten
        $htmlTV .= '<!-- Small Cards -->';
        $htmlTV .= '<div class="cardS">';
        $htmlTV .= '    <div class="wbox">';
        $htmlTV .= '        <div class="wdes">' . $txt . '</div>';
        $htmlTV .= '        <div class="wdeg">' . (round($tmp, 0) + 0) . '°</div>';
        $htmlTV .= '        <div class="wico"></div>';
        $htmlTV .= '        <div class="wsgl">☀️&nbsp;' . $snr . '</div>';
        $htmlTV .= '        <div class="wssr">' . $sns . '&nbsp;🌓</div>';
        $htmlTV .= '    </div>';
        $htmlTV .= '</div>';
        $htmlTV .= '<!-- Medium Cards -->';
        $htmlTV .= '<div class="cardM">';
        $htmlTV .= '    <div class="wbox">';
        $htmlTV .= '        <div class="wdes">' . $txt . '</div>';
        $htmlTV .= '        <div class="wico"></div>';
        $htmlTV .= '        <div class="wdeg">' . (round($tmp, 0) + 0) . '°</div>';
        $htmlTV .= '        <div class="wsgl">☀️&nbsp;' . $snr . '</div>';
        $htmlTV .= '        <div class="wssr">' . $sns . '&nbsp;🌓</div>';
        $htmlTV .= '        <div class="wifo">';
        $htmlTV .= $fall;
        $htmlTV .= $humi;
        $htmlTV .= $wind;
        $htmlTV .= $rain;
        $htmlTV .= '        </div>';
        $htmlTV .= '        <div class="wfgd">';
        // 7 days forecast
        for($i = 1; $i < 8; $i++) {
            $day = $days[$i]->temperatureHighTime;
            $wd = date('D', intval($day));
            $wd = strtr($wd, $TRANS);
            $htmlTV .= '        <span class="day">' . strtoupper($wd) . '</span>';
        }
        // Icons
        for($i = 1; $i < 8; $i++) {
            $ico = $days[$i]->icon;
            $htmlTV .= '        <img class="img" src="' . GetIcon($ico, 'icon07') . '" />';
        }
        // Temp
        for($i = 1; $i < 8; $i++) {
            $th = $days[$i]->temperatureHigh;
            $htmlTV .= '        <span class="txt">' . (round($th, 0) + 0) . '°</span>';
        }
        $htmlTV .= '        </div>';
        $htmlTV .= '    </div>';
        $htmlTV .= '</div>';
        $htmlTV .= '<!-- Large Cards -->';
        $htmlTV .= '<div class="cardL">';
        $htmlTV .= '</div>';
        // Day speichern
        $vid = CreateVariableByName($_IPS['SELF'], 'Aktuelles-Wetter', 3);
        SetValue($vid, $htmlTV);
    }
}

// Extrahiere die Stundenwerte und baue HTML Box zusammen
function SetHourlyWeather($hourly)
{
    global $TRANS, $HTML;
    // HTML WebFront
    if ($HTML['webfront']) {
        // General CSS
        $htmlWF = '';
        $htmlWF .= '<style type="text/css">';
        $htmlWF .= '.wdiv { height:180px;}';
        $htmlWF .= '.wbox { display:inline-block; position:relative; border:1px solid rgba(255, 255, 255, 0.1); height:180px; margin: 0px 10px 0px 0px; color: rgb(255, 255, 255); background-image: linear-gradient(top,rgba(0,0,0,0) 0,rgba(0,0,0,0.3) 50%,rgba(0,0,0,0.3) 100%); background-image: -o-linear-gradient(top,rgba(0,0,0,0) 0,rgba(0,0,0,0.3) 50%,rgba(0,0,0,0.3) 100%); background-image: -moz-linear-gradient(top,rgba(0,0,0,0) 0,rgba(0,0,0,0.3) 50%,rgba(0,0,0,0.3) 100%); background-image: -webkit-linear-gradient(top,rgba(0,0,0,0) 0,rgba(0,0,0,0.3) 50%,rgba(0,0,0,0.3) 100%); background-image: -ms-linear-gradient(top,rgba(0,0,0,0) 0,rgba(0,0,0,0.3) 50%,rgba(0,0,0,0.3) 100%);}';
        $htmlWF .= '.wday { position:absolute; top:10px; left:10px; font-size:18px; font-weight:bold; color:rgba(255, 255, 255, 0.5); overflow:hidden;}';
        $htmlWF .= '.wics { position:absolute; width:109px; top:35px; text-align:center; overflow:hidden;}';
        $htmlWF .= '.wdec { position:absolute; width:100px; bottom:35px; text-align:center; font-size:36px; font-weight:bold; overflow:hidden;}';
        $htmlWF .= '.wtec { position:absolute; width:109px; bottom:5px; text-align:center; text-overflow: ellipsis; font-size:10px;  color:rgba(255, 255, 255, 0.5); overflow:hidden;}';
        $htmlWF .= '.wder { position:absolute; bottom:42px; right:5px; text-align:right; font-size:14px; color:rgba(255, 255, 255, 0.5); overflow:hidden;}';
        $htmlWF .= '</style>';
        $htmlWF .= '<div class="wdiv">';
        // nächsten 24h reichen!
        for($i = 0; $i < 24; $i++) {
            $time = $hourly[$i]->time;
            $text = strtr($hourly[$i]->summary, $TRANS);
            $temp = $hourly[$i]->temperature;
            $rain = $hourly[$i]->precipProbability;
            $hour = date('H:i', intval($time));
            $icon = GetIcon($hourly[$i]->icon, 'icon24');
            if ((($i + 1) % 8) == 0) {
                $htmlWF .= '<div class="wbox" style="width:109px; margin-right:0px; margin-bottom:5px;">';
            }
            else {
                $htmlWF .= '<div class="wbox" style="width:109px; float:left; margin-bottom:5px; ">';
            }
            $htmlWF .= '<div class="wday">' . $hour . '</div>';
            $htmlWF .= '<div class="wics"><img style="width:75px;" src="' . $icon . '"></img></div>';
            $htmlWF .= '<div class="wdec">' . (round($temp, 0) + 0) . '°</div>';
            $htmlWF .= '<div class="wder">' . number_format($rain * 100) . '%</div>';
            $htmlWF .= '<div class="wtec">' . $text . '</div>';
            $htmlWF .= '</div>';
        }
        $htmlWF .= '</div>';
        // Hours speichern
        $vid = CreateVariableByName($_IPS['SELF'], '24-Stunden-Wetter', 3);
        SetValue($vid, $htmlWF);
    }
}

// Gibt für den übergebenen (engl.) Type die deutsche Niederschlagsart zurück.
function GetPrecipitation($type = null)
{
    if ($type == 'rain') return 'Regen';
    if ($type == 'snow') return 'Schnee';
    if ($type == 'sleet') return 'Schneeregen';
    return 'keiner';
}

// Erstellt aus dem Icon-String eine Image-URL
function GetIcon($ico, $type)
{
    global $ICONS, $HTML;

    // Ist es Tag oder Nacht?
    $now = date('H:i', time());
    $snr = $HTML['sunrise'];
    $sns = $HTML['sunset'];
    $day = (($now > $snr) && ($now < $sns)) ? true : false;
    // Tag oder Nacht Icon
    $time = 'night';
    if ($day) $time = 'day';
    // Basis Name ermitteln
    $icon = explode('-', $ico);
    // Woher Bilder nehmen?
    if($HTML[$type]) {
        // Url ermitteln
        $found = false;
        foreach ($ICONS[$time] as $name => $url) {
            if ($icon[0] == $name) {
                $found = true;
                return $url;
            }
        }
        if($found == false) {
            IPS_LogMessage('WEATHER', 'Forecast Icon: ' . $ico);
        }
        return $ICONS['unknown']['icon'];
    }
    else {
        return $HTML['ibase'] . $ico . $HTML['iext'];
    }
}

############################################################################################################################################

EDIT: Grid in der Symcon App steht auf 12.

Die sind von BMW Connect gewesen!

Ja, kommt bei mir in letzter Zeit 2-3 mal pro Tag vor!

Ich nutze ein 24er GRID und habe noch was angepasst fürs Handy - muss ich nochmal schauen - ist noch nicht online!

Huhu. Vorab schonmal. Mit dem 24er wird es besser. Bekomme aber immer noch Überschneidungen. :v:t3:

Habe ein Update hochgeladen auf github.

Weiteren großen Support wird es leider nicht geben, da jedes Endgerät sehr wählerisch mit der Darstellung ist. Das ist auch der Grund warum ich in absehbarer Zeit keine Module mit ViSu-Support rausbringen werde.

Gruß Heiko

Hat bei mir leider nichts bewirkt… :thinking: …könnte man noch einen Schalter einbauen, ob man die automatische Umschaltung möchte zwischen „länglich“ und „quadratisch“ …dann könnte ich es nach unten weiter ziehen.

Also auf meinem iPhone sieht es so aus!

1 „Gefällt mir“

Hi. Hatte das Script auf der Arbeit noch flott reinkopiert und einmal ausgeführt. Da ging es noch nicht. Als ich zuhause ankam, war alles paletti. :v:t3::smiley:

Img:

Huhu - der Ich mal wieder… :sweat_smile: …auf dem iPhone passt alles. Auf meinem iPad mit der App, sowohl die aktuelle aus dem Store sowie die aktuelle aus dem Testflight, schaltet er nicht um zwischen der Quadart und Breit Kachel. Ist bei mir am PC aber identisch. Profil ist Tabelet und Gitter ist 24. Meinst du das du dich aber nochmal motivieren kannst, da rein zuschauen? …Moppi sagt auch bitte bitte. :yum:

img:

Was meinst Du mit automatisch umschalten - meinst wegen der Größe!? Mach es mal etwas schmaler dann sollte es passen.

1 „Gefällt mir“

Im Browser geht das wirklich. Aber auf meinem iPad kann ich es schieben und ziehen wie ich will. Die Wettervorhersage unten bekomme ich nicht. :face_with_spiral_eyes:

edit: