+ Antworten
Ergebnis 1 bis 1 von 1
  1. #1
    Registriert seit
    Sep 2008
    Ort
    Hamburg
    Beiträge
    1,069

    Standard Mein Skript für BSB-LAN

    Ich habe ein Skript geschrieben, um eine Heizung (in meinem Fall: Öl) per BSB-LAN-Interface an IPS anzubinden.

    Es gab hier im Forum schon andere Codesnippets, aber ich wollte gern ein etwas universelleres Skript mit automatischem Setup.

    Das Skript erlaubt
    • das regelmäßige Auslesen aller per BSB-LAN verfügbaren Werte,
    • das Setzen von Parametern sowie das Absenden von INF-Nachrichten per RunScriptEx,
    • das Ändern von Parametern via WebFront.


    Es werden automatisch diverse Variablenprofile angelegt (erkennbar am BSB_LAN_-Präfix), um Enums und andere Datentypen halbwegs ansehnlich darzustellen. Diese können natürlich nach dem Setup beliebig geändert oder auch gelöscht werden.

    Gleiches gilt für die Benennung von Variablen und Kategorien. Auch ist es erlaubt, diese zu löschen wenn sie nicht benötigt werden oder keine sinnvollen Daten enthalten.

    Wie bei den meisten meiner Skripte muss der Code zum Setup in ein leeres Skript kopiert, einige Variablen oben verändert und das Skript dann manuell ausgeführt werden. Da in diesem Fall das Setup länger dauern kann als die maximale Skriptlaufzeit bitte ggf. mehrmals hintereinander ausführen. Das Ergebnis seht ihr jeweils in der Konsolenausgabe! Ein Setup, das noch nicht abgeschlossen wurde wird beim nächsten manuellen Ausführen automatisch fortgesetzt.

    Ich kann versuchen, bei Problemen zu helfen, habe allerdings gerade nicht all zu viel Zeit. Bitte um Verständnis wenn's länger dauert. Und bitte keine Fragen per PN, lieber im Thread, dann haben andere auch was davon.

    Weitere Informationen finden sich oben im Skript-Quellcode.

    PHP-Code:
    <?
    // BSB LAN Script for IP Symcon, written 2019 by sokkederheld
    // Please adjust the following settings before executing this script for setup.

    // IP address (or domain name) of the BSB-LAN interface
    $ip "192.168.188.30";

    // optional "pass key" to make 100% hack-proof - leave empty if no pass key is
    // being used. But seriously, this provides no security at all, so don't forget
    // to isolate the device from any open networks.
    $pass_key "";

    // Root id of the category under which the instances should be created and
    // maintained. Please do not move instances outside of that category. For
    // visualization purposes, please use links. Renaming of elements is okay.
    $root_id 54660 /*[Software-Instanzen\Stall\Heizung]*/;

    // Update interval in seconds - can not be less than 20, 30 should be good.
    $update_interval 30;

    // For setup mode, the "Setup Status" variable underneath this script must be
    // deleted if it exists!
    // Afterwards, execute this script manually to begin setup. Attention: You may
    // need to execute the script several times for setup to complete, because it
    // may not complete during one maximum run time. Check result status at the end
    // of the log!

    // To uninstall (delete all profiles beginning with the defined prefix, delete
    // all instances underneath the specified root id and all variables below that)
    // set the "Setup Status" variable underneath this script to -1 and execute it
    // manually.

    // This variable allows for forced updating (from the bsb-lan interface) of a
    // single category, by specifying its ID. This may be handy if you deleted some
    // or all parameters (or the entire instance) and wish to recreate it. The value
    // should normally be false, unless you wish to force an update of the specified
    // category id! If set to a valid category id, all parameter variables and enum
    // profiles of the category will be created if they don't exist.
    $force_update_cat false;

    // List of prameters you want writeable. Feel free to modify BEFORE setup.
    // Afterwards, you can set or unset this script as the corresponding variable's
    // action script in order to change a parameters' writeability.
    $writeable_parameters = array(
        
    700// heating operation mode
        
    701// presence button
        
    720721// kennlinie steilheit, verschiebung
        
    730// heizgrenze
        
    750// room influence
        
    641632633634635636637638639640641642643644645646647// holiday schedule
        
    648// holiday setting
        
    500501502503504505506// heating schedules
        
    1601// tww push
        
    2200// kessel betriebsart
        
    10000// room temperature INF!
    );

    $write_only_parameters = array(
        
    1601// tww push
    );

    $day_month_parameters = array(
        
    56// dst start end
        
    641632633634635636637638639640641642643644645646647// holiday schedule
    );

    $rel_temp_parameters = array(
        
    721// kennlinie verschiebung
        
    732// Tagesheizgrenze
        
    4721,
        
    4722,
        
    5020502450255026502750285029,
    );

    $sync_time true;

    // Outputting status messages during timer events is normally disabled in order
    // to avoid spamming the log file. Can be enabled for debug purposes.
    $timer_log_messages false;

    // Outputting status messages during variable actions is normally disabled in
    // order to avoid spamming the log file.
    $action_log_messages false;

    // To set parameters from a script:
    // $par = array("PARAMETER" => 1601, "VALUE" = 1, "ACTION" = "SET", "VARIABLE"
    //   => 12345);
    // IPS_RunScriptEx($id, $par);

    ////////////////////////////////////////////////////////////////////////////////
    // no changes required below this line

    // Some constants you should not fumble with.
    define("SETUP_INIT""0");
    define("SETUP_COMPLETED""100");
    define("SETUP_UNINSTALL""-1");
    define("SETUP_REQUEST_POSTPONE_UPDATE""101");
    define("MAX_EXECUTION_TIME""60"); // setting higher causes problems over Connect
    define("ENUM_PROFILE_PREFIX""BSB_LAN_ENUM_");
    define("UNIT_PROFILE_PREFIX""BSB_LAN_UNIT_");
    define("NO_VALUE""-100"); // used in profiles to denounce a lack of a value
    define("SEMAPHORE_NAME""BSB_LAN_SCRIPT");
    define("PARAM_ACTION_NONE""0");
    define("PARAM_ACTION_SET""1");
    define("PARAM_ACTION_INF""2");

    ini_set('max_execution_time'MAX_EXECUTION_TIME);

    // Buffer for enum data received by single category update requests - may spare
    // us from fiddling with the HTML based "get enum values" request later when
    // creating the parameter variables and, potentially, profiles.
    $enum_buffer = array();

    // measure time at beginning of this script
    $begin_ts time();

    // If we're doing something immediate, postpone updates in the background
    if(get_setup_status(true) == SETUP_COMPLETED && $_IPS['SENDER'] != 'TimerEvent') {
        
    set_setup_status(SETUP_REQUEST_POSTPONE_UPDATE);
    }

    if(!
    IPS_SemaphoreEnter(SEMAPHORE_NAME, (MAX_EXECUTION_TIME 15) * 1000)) {
        
    msg("Other script instance is running too long. Exiting.");
        return;
    }

    if(
    get_setup_status(true) == SETUP_REQUEST_POSTPONE_UPDATE) {
        
    set_setup_status(SETUP_COMPLETED);
    }

    if(
    get_elapsed_time() > 1) {
        
    msg("Needed to wait " get_elapsed_time() . " s for other script instance to finish.");
    }

    // Manual execution of this script is for maintenance tasks like setup, forced
    // category updates or uninstallation.
    if($_IPS['SENDER'] == 'Execute') {
        if(
    $force_update_cat !== false) { // forced category update
            
    msg("Forced updating mode for category #" $force_update_cat ".");
            
    update_categories($force_update_cat);
        } else if(
    get_setup_status() <= SETUP_UNINSTALL) { // uninstall
            
    msg("Uninstall mode.");
            
    IPS_SetScriptTimer($_IPS['SELF'], 0);
            
    set_setup_status(SETUP_INIT);
            
    $inst_ids IPS_GetChildrenIDs($root_id);
            foreach(
    $inst_ids as $inst_id) {
                
    msg("Clearing out instance \"" IPS_GetName($inst_id) . "\".");
                
    $var_ids IPS_GetChildrenIDs($inst_id);
                foreach(
    $var_ids as $var_id) {
                    
    msg("Removing variable \"" IPS_GetName($var_id) . "\".");
                    
    IPS_DeleteVariable($var_id);
                }
                
    msg("Removing instance \"" IPS_GetName($inst_id) . "\".");
                
    IPS_DeleteInstance($inst_id);
            }
            
    $prof_names IPS_GetVariableProfileListByType(1);
            foreach(
    $prof_names as $prof_name) {
                if(
    substr($prof_name0strlen(ENUM_PROFILE_PREFIX)) == ENUM_PROFILE_PREFIX) {
                    
    msg("Deleting ENUM profile \"" $prof_name "\".");
                    
    IPS_DeleteVariableProfile($prof_name);
                } else if(
    substr($prof_name0strlen(UNIT_PROFILE_PREFIX)) == UNIT_PROFILE_PREFIX) {
                    
    msg("Deleting unit profile \"" $prof_name "\".");
                    
    IPS_DeleteVariableProfile($prof_name);
                }
            }
            
    msg("Uninstall completed.");
        } else if(
    get_setup_status() < SETUP_COMPLETED) { // setup
            
    if(get_setup_status() == 0) {
                
    msg("Setup mode (beginning)! Attention, check end of log for setup status!");
            } else {
                
    msg("Setup mode (continued)! Attention, check end of log for setup status!");
            }
            if(
    update_categories()) {
                if(
    $update_interval 20$update_interval 20;
                
    IPS_SetScriptTimer($_IPS['SELF'], $update_interval);
                
    msg("Setup completed.");
                
    set_setup_status(SETUP_COMPLETED);
            }
        } else { 
    // nothing to do
            
    msg("Setup already completed. To uninstall, set \"Setup Status\" variable" .
                
    " to " SETUP_UNINSTALL " or lower and execute manually.");
            
    msg("To repeat setup (recreating potentially deleted elements), delete " .
                
    "\"Setup Status\" variable and execute manually.");
        }
    } else if(
    $_IPS['SENDER'] == 'TimerEvent') { // regular update of param values
        
    $force_update_cat false;
        if(
    get_setup_status() >= SETUP_COMPLETED) {
            do {
                
    msg("Attempting to find the most outdated category.");
                
    $inst_ids IPS_GetChildrenIDs($root_id);
                
    $oldest_inst_id false;
                
    $oldest_ts time();
                
    $cat_id false;
                foreach(
    $inst_ids as $inst_id) {
                    
    $inst_ident IPS_GetObject($inst_id)["ObjectIdent"];
                    if(
    substr($inst_ident04) == "Cat_") {
                        
    $var_ids IPS_GetChildrenIDs($inst_id);
                        
    $newest_ts_in_cat false;
                        foreach(
    $var_ids as $var_id) {
                            
    $this_update_ts IPS_GetVariable($var_id)["VariableUpdated"];
                            if(
    $newest_ts_in_cat === false$newest_ts_in_cat $this_update_ts;
                            if(
    $this_update_ts $newest_ts_in_cat) {
                                
    $newest_ts_in_cat $this_update_ts;
                            }
                        }
                        if(
    $newest_ts_in_cat !== false && $newest_ts_in_cat $oldest_ts) {
                            
    $cat_id substr($inst_ident4);
                            
    $oldest_ts $newest_ts_in_cat;
                            
    $oldest_inst_id $inst_id;
                        }
                    }
                } 
    // foreach
                
    $age time() - $oldest_ts;
                if(
    $cat_id !== false) {
                    
    msg("Updating category #" $cat_id " (\"" .
                        
    IPS_GetName($oldest_inst_id) .
                         
    "\", " $age " second(s) old).");//*/
                    
    update_categories($cat_id);
                }
                
    msg("Execution time elapsed: " get_elapsed_time() . "s.");
                if(
    get_setup_status() == SETUP_REQUEST_POSTPONE_UPDATE) {
                    
    msg("Further updating postponed by other script instance. Exiting " .
                        
    "from main loop.");
                    break;
                }
            } while (
    get_elapsed_time() < $update_interval 15);
        } else {
            
    msg("Setup not completed. Disabling update timer.");
            
    IPS_SetScriptTimer($_IPS['SELF'], 0);
        }
    } else {
        
    // webfront action script or execution from other script
        
    $force_update_cat false;
        
        
    $param_action PARAM_ACTION_SET;
        
        if(
    $_IPS['SENDER'] == 'WebFront') {
            
    $ident IPS_GetObject($_IPS['VARIABLE'])['ObjectIdent'];
            if(
    substr($ident04) == "Par_") { // if the variable is a parameter variable
                
    $p IPS_GetVariable($_IPS['VARIABLE'])["VariableCustomProfile"];
                
    $parent_id IPS_GetParent($_IPS['VARIABLE']);
                
                
    // extract the parameter index and, if present, the field index of the variable
                
    $index substr($ident4);
                
    $field_index false;
                
    $pos strpos($index"_");
                if(
    $pos) {
                    
    $field_index substr($index$pos 1);
                    
    $index substr($index0$pos);
                }
                
                
    // if a field index (for parameters that are presented as multiple fields,
                // like for example, heating schedules) is present, read all fields and
                // combine the values in order to form a proper set request
                
    if($field_index !== false) {
                    
    // determine the number of fields by looking for the highest field index
                    // which exists for this parameter index
                    
    $field_count $field_index 1;
                    while(@
    IPS_GetObjectIDByIdent("Par_" $index "_" $field_count$parent_id)) {
                        
    $field_count++;
                    }
                    
                    
                    
    $v "";
                    
                    
    // If we're setting a heating schedule, we must provide a valid start and
                    // end time at the same time, so if we're changing from an xx:xx value to
                    // something valid, we have to specify something valid for the end time as
                    // otherwise the receiver would just discard the change. So by default, we
                    // send an end time one hour past the start time. Otherwise it would be
                    // impossible to reenable a heating schedule after disabling it.
                    
    $force_value_index false;
                    if(
    $p == "~UnixTimestampTime") {
                        if(
    $_IPS['VALUE'] > && GetValue($_IPS['VARIABLE']) == 0) {
                            if(
    $field_index == 0) {
                                
    $force_value_index $field_index 1;
                                
    $force_value $_IPS['VALUE'] + 60 60 *
                                    (
    $field_index == 16 1);
                            }
                        }
                    }
                    
                    
    // Combine the set value out of all fields which belong to this param id.
                    
    for($fi 0$fi $field_count$fi++) {
                        if(
    $fi == $field_index) {
                            
    $v_raw $_IPS['VALUE'];
                        } else {
                            
    $var_id IPS_GetObjectIDByIdent("Par_" $index "_" $fi$parent_id);
                            
    $v_raw GetValue($var_id);
                            
                            if(
    $v_raw == && $force_value_index !== false && $force_value_index == $fi) {
                                
    $v_raw $force_value;
                            }
                        }
                        
                        
    // convert timestamp values to strings
                        
    if($p == "~UnixTimestampTime") {
                            if(
    $v_raw == 0) {
                                
    $v_field "xx:xx";
                            } else {
                                
    $v_field date("H:i"$v_raw);
                            }
                        } else {
                            
    $v_field $v_raw;
                        }
                        
                        
    // append to resulting set value string
                        
    $v .= $v_field;
                        
                        
    // include separators for schedule strings
                        
    if($p == "~UnixTimestampTime") {
                            if(
    $fi == && $fi $field_count 1) {
                                
    $v .= "-";
                            } else if(
    $fi == && $fi $field_count 1) {
                                
    $v .= "_";
                            }
                        } 
    // if
                    
    // for
                
    } else { // single field value (the vast majority)
                    
    $v_raw $_IPS['VALUE'];
                    if(
    $p == "~UnixTimestampTime") { // convert timestamp to string
                        
    $v date("H:i"$v_raw);
                    } else if(
    $p == "~UnixTimestampDate") { // convert timestamp to string
                        
    $v date("d.m"$v_raw);
                        
    IPS_SetVariableCustomProfile($_IPS['VARIABLE'], setup_day_month_profile($index$v_raw));
                    } else if(
    array_search($index$day_month_parameters) !== false) {
                        if(
    $v_raw == NO_VALUE) {
                            
    $v '';
                        } else if(
    $v_raw == GetValue($_IPS['VARIABLE'])) {
                            
    IPS_SetVariableCustomProfile($_IPS['VARIABLE'], "~UnixTimestampDate");
                            
    $param_action PARAM_ACTION_NONE;
                        } else {
                            
    $v date("d.m"$v_raw);
                        }
                    } else {
                        if(
    $v_raw == NO_VALUE) {
                            
    $v "";
                        } else {
                            
    $v $v_raw;
                        }
                    }
                }
            }
        }    else if(
    $_IPS['SENDER'] == 'RunScript') {
            
    $field_index false;
            if(!
    array_key_exists("PARAMETER"$_IPS)) {
                
    msg("Missing PARAMETER argument.");
                return;
            }
            if(!
    array_key_exists("VALUE"$_IPS)) {
                
    msg("Missing VALUE argument.");
                return;
            }
            
    $index $_IPS['PARAMETER'];
            
    $v $_IPS['VALUE'];
            if(
    array_key_exists("ACTION"$_IPS)) {
                if(
    $_IPS['ACTION'] == 'INF') {
                    
    $param_action PARAM_ACTION_INF;
                } else if(
    $_IPS['ACTION'] != 'SET') {
                    
    msg("Unsupported parameter action: \"" $_IPS['ACTION'] . "\".");
                    return;
                }
            }
        }
            
        if(
    $param_action == PARAM_ACTION_SET) {
            
    msg("Setting parameter #" $index " to \"" $v "\".");
            
            
    $result set_parameter($index$v);
            if(
    array_key_exists('VARIABLE'$_IPS)) {
                
    $parent_id IPS_GetParent($_IPS['VARIABLE']);
                if(
    $field_index === false && array_search($index$day_month_parameters) === false) {
                    
    SetValue($_IPS['VARIABLE'], $result);
                } else {
                    
    msg("Updating parameter.");
                    
    update_parameters($parent_id$index$index);
                }
            }
        } else if(
    $param_action == PARAM_ACTION_INF) {
            
    msg("Sending for parameter #" $index " INF message \"" $v "\".");
            
            
    set_parameter($index$vtrue);
        }
    // else

    IPS_SemaphoreLeave(SEMAPHORE_NAME);

    ////////////////////////////////////////////////////////////////////////////////
    // functions

    function sync_time() {
        
    msg("Syncing time...");
        
    set_parameter(0date("d.m.Y_H:i:s"), false);
    // sync_time

    // Returns the setup status level
    function get_setup_status($ignore_force_update_cat false) {
        global 
    $force_update_cat;
        
        
    $id = @IPS_GetObjectIDByIdent("SetupStatus"$_IPS['SELF']);
        if(
    $id === false) {
            
    $result SETUP_INIT;
        } else {
            
    $result GetValue($id);
        }
        if(
    $force_update_cat !== false && !$ignore_force_update_cat) {
            
    $result SETUP_INIT;
        }
        return 
    $result;
    // get_setup_status

    // Sets the setup status level
    function set_setup_status($status) {
        global 
    $force_update_cat;

        
    $id = @IPS_GetObjectIDByIdent("SetupStatus"$_IPS['SELF']);
        if(
    $status == SETUP_INIT && $id !== false) {
            
    IPS_DeleteVariable($id);
            return;
        } else if(
    $id === false) {
            
    $id IPS_CreateVariable(1);
            
    IPS_SetParent($id$_IPS['SELF']);
            
    IPS_SetIdent($id"SetupStatus");
            
    IPS_SetName($id"Setup Status");
        }
        
         if(
    $status != SETUP_REQUEST_POSTPONE_UPDATE && $status != SETUP_COMPLETED &&
            
    $force_update_cat !== false) {
            return;
        }
         
    SetValue($id$status);
    // set_setup_status

    // Update all values from the category with the specified id (all if omitted)
    // This function creates a dummy instance for the category if in setup mode or
    // doing a forced category update.
    function update_categories($cat_id "ALL") {
        global 
    $root_id$force_update_cat$enum_buffer;
        
    $dummy_guid "{485D0419-BE97-4548-AA9C-C083EB82E61E}";
        
        if(
    $cat_id == "ALL" || $force_update_cat !== false) { // update from bsb-lan
            
    $cats req("JK=" $cat_id);
            
            if(!
    $cats) {
                
    msg("Requesting categories failed.");
                return 
    false;
            }
                    
            if(
    strval($cat_id) != "ALL") {
                
    $min 9999;
                
    $max 0;
                foreach(
    $cats as $par_index => $par_info) {
                    if(
    $par_index $min$min $par_index;
                    if(
    $par_index $max$max $par_index;
                    
                    if(
    array_key_exists("possibleValues"$par_info) &&
                        
    count($par_info["possibleValues"]) > 0) {
                        
    $enum_buffer[$par_index] = $par_info["possibleValues"];
                    }
                }
                
                if(
    $min $max) {
                    if(
    $force_update_cat !== false) {
                        
    msg("Category is empty.");
                    }
                    return 
    true;
                }
                
                
    $inst_id = @IPS_GetObjectIDByIdent("Cat_" $cat_id$root_id);
                
                
    $cats = array(
                    
    $cat_id => array(
                        
    "min" => $min,
                        
    "max" => $max,
                        
    "name" => $inst_id IPS_GetName($inst_id) : ("Unbekannt (#" $cat_id ")")
                    )
                );
            }
        } else { 
    // regular refresh of existing category, no update from bsb-lan
            
    $inst_id = @IPS_GetObjectIDByIdent("Cat_" $cat_id$root_id);
            if(!
    $inst_id) return true;
            
            
    $min 9999;
            
    $max 0;
            
    $par_ids IPS_GetChildrenIDs($inst_id);
            foreach(
    $par_ids as $par_id) {
                
    $ident IPS_GetObject($par_id)["ObjectIdent"];
                if(
    substr($ident04) == "Par_") {
                    
    $par_index intval(substr($ident4));
                    if(
    $par_index $min$min $par_index;
                    if(
    $par_index $max$max $par_index;
                }
            }
            
            if(
    $min $max) return true;
            
            
    $cats = array(
                
    $cat_id => array(
                    
    "min" => $min,
                    
    "max" => $max,
                    
    "name" => $inst_id IPS_GetName($inst_id) : ("Unbekannt (#" $cat_id ")")
                )
            );
        }
        
        foreach(
    $cats as $i => $cat) {
            
    $ident 'Cat_' $i;
            
    $inst_id = @IPS_GetObjectIDByIdent($ident$root_id);
            if(
    get_setup_status() < SETUP_COMPLETED) {
                if(!
    $inst_id) {
                    
    msg("Creating dummy instance for category #" $i " (" .
                        
    $cat["name"] . "), spanning parameters #" $cat["min"] . " to #" .
                        
    $cat["max"] . ".");
                    
    $inst_id IPS_CreateInstance($dummy_guid);
                    
    IPS_SetParent($inst_id$root_id);
                    
    IPS_SetName($inst_id$cat["name"]);
                    
    IPS_SetIdent($inst_id$ident);
                }
            }
            if(
    $inst_id) {
                if(
    $i == $cat_id || $i >= get_setup_status()) {
                    if(
    get_setup_status() < SETUP_COMPLETED) {
                        
    msg("Processing parameters in category #" $i " (" .
                            
    $cat["name"] . "): #" $cat["min"] . " to #" .
                            
    $cat["max"] . ".");
                    }
                    if(
    update_parameters($inst_id$cat["min"], $cat["max"])) {
                        if(
    get_setup_status() <= $i) {
                            
    set_setup_status($i 1);
                            if(
    get_setup_status() < SETUP_COMPLETED) {
                                
    msg("Execution time elapsed: " get_elapsed_time() . "s.");
                            }
                        }
                    }
                }
            }
            
            if(
    get_elapsed_time() >= MAX_EXECUTION_TIME 15) {
                if(
    get_setup_status() < SETUP_COMPLETED) {
                    
    msg("Setup incomplete: Execution time limit near. Please execute again to continue!");
                }
                return 
    false;
            }
            if(
    get_setup_status() == SETUP_REQUEST_POSTPONE_UPDATE) {
                
    msg("Other script instance requested to postpone this update. Exiting " .
                    
    "from category update.");
                return 
    false;
            }
        } 
    // foreach
        
        
    return true;
    // update_categories

    function get_elapsed_time() {
        global 
    $begin_ts;
        return 
    time() - $begin_ts;
    }
    function 
    msg($msg) {
        global 
    $timer_log_messages$action_log_messages;
        if(
    $_IPS['SENDER'] == 'WebFront' && !$action_log_messages) return;
        if(
    $_IPS['SENDER'] == 'RunScript' && !$action_log_messages) return;
        if(
    $_IPS['SENDER'] == 'TimerEvent' && !$timer_log_messages) return;
        
    IPS_LogMessage(IPS_GetName($_IPS['SELF']), $msg);
        if(
    $_IPS['SENDER'] == 'Execute') echo $msg "\r";
    // msg

    // Query single parameter over html to get its value when json returns faulty
    // value for float number
    function get_num_html_value($par_index$html false) {
        if(
    $html === false$html req($par_index);
        
    $str_pre "id='value" $par_index "' VALUE='";
        
    $str_pre_offs 0;
        
    $str_post "'>";
        
    $str_post_offs 0;
        
    $html substr($htmlstrpos($html$str_pre) + strlen($str_pre) + $str_pre_offs);
        
    $value substr($html0strpos($html$str_post) + $str_post_offs);
        return 
    $value;
    // get_num_html_value

    // Query single parameter over html to get its value when json returns faulty
    // value for string or other
    function get_text_html_value($par_index$html false) {
        if(
    $html === false$html req($par_index);
        
    $str_pre1 "<table align=center width=80%>";
        
    $str_pre2 ": ";
        
    $str_post "\r";
        
    $str_post_offs 0;
        
    $html substr($htmlstrpos($html$str_pre1) + strlen($str_pre1));
        
    $html substr($htmlstrpos($html$str_pre2) + strlen($str_pre2));
        
    $value substr($html0strpos($html$str_post) + $str_post_offs);
        return 
    $value;
    // get_text_html_value

    // return result of bitmask flags as string. This is kinda lazy and obviously
    // not suited to be writeable.
    function get_bitmask_html_value($par_index) {
        
    $html req($par_index);
        
    $str_pre "<select multiple id='value" $par_index "'>";
        
    $str_pre_offs 2;
        
    $str_post "</select>";
        
    $str_post_offs = -2;
        
    $html substr($htmlstrpos($html$str_pre) + strlen($str_pre) + $str_pre_offs);
        
    $html substr($html0strpos($html$str_post) + $str_post_offs);
        
    $arr_raw explode("</option>\r\n"$html);
        
    $result "";
        foreach(
    $arr_raw as $entry) {
            if(
    strpos($entry" SELECTED>") !== false) {
                if(
    $result != ""$result .= ", ";
                
    $result .= substr($entrystrpos($entry">") + 1);
            }
        }
        return 
    $result;
    // get_bitmask_html_value

    // Update parameters with the specified indices (range) and place their variables
    // underneath the specified category's dummy instance.
    function update_parameters($cat_id$min_index$max_index) {
        global 
    $writeable_parameters$day_month_parameters$rel_temp_parameters$sync_time;
        
    $ips_dt_name = ["boolean""integer""float""string"];
        
    $bsb_lan_dt_name = ["number","enum","???","bitmask","hour.minute","day.month","string","timestamp"];
        
        if(!
    IPS_ObjectExists($cat_id)) return false;
        
        
    // construct request string
        
    $req_str "JQ=";
        
    $count 0;
        for(
    $i $min_index$i <= $max_index$i++) {
            
    $ident 'Par_' $i;
            
    $var_id = @IPS_GetObjectIDByIdent($ident$cat_id);
            
            if(
    $var_id === false) {
                
    $ident 'Par_' $i '_0';
                
    $var_id = @IPS_GetObjectIDByIdent($ident$cat_id);
            }
            
            if(
    get_setup_status() < SETUP_COMPLETED || $var_id) {
                
    $req_str .= $i ",";
                
    $count++;
            }
        }
        if(
    $count 0) {
            
    $req_str substr($req_str0strlen($req_str) - 1);
            
    $pars req($req_str);
        } else {
            return 
    true// nothing to update
        
    }
        
        if(!
    $pars) {
            
    msg("Requesting parameters #"$min_index " to #" $max_index .
                
    " has failed.");
            return 
    false;
        }
        
        
    // We use this variable to count the unused day.month parameters in this
        // category, so we can begin hiding some after a while to remove clutter.
        
    $count_empty_day_month_params 0;
        
        foreach(
    $pars as $i => $par) {
            
    // workaround to filter out unrequested (6705..6846 returned 675 for example)
            
    if($i $min_index || $i $max_index) {
                
    msg("Returned parameter index #" $i .
                    
    " is outside the requested range. Skipping.");
                continue;
            }
            if(
    get_setup_status() == SETUP_REQUEST_POSTPONE_UPDATE) {
                
    msg("Other script instance requested to postpone this update. Exiting " .
                    
    "from parameter update.");
                return 
    false;
            }
            
            
    $ident_prefix 'Par_' $i;
            
            
    msg("Raw value for parameter #" $i " (" $par["name"] . "): \"" .
                
    $par["value"] . "\" (data type " $par["dataType"] . ", unit \"" .
                
    $par["unit"] . "\").");
            
            
    $t 3;
            
    $p "";
            
    $v = [$par["value"]];
            
    $field_suffix = [""];
            
    $dt $par["dataType"];
            
    $u $par["unit"];
            
    $field_count 1;
            
    $writeable false;
            
            
    // writable fields
            
    if(array_search($i$writeable_parameters) !== false$writeable true;
            
            
    // relative temperatures should be visualized as Kelvin rather than °C
            
    if(array_search($i$rel_temp_parameters) !== false$unit "K";
            
            
    // Some parameters are sent as strings, but they're supposed to hold
            // dd.mm (day.month). According to documentation, data type 5 would be the
            // appropriate choice for them, so we override the data type with that
            // internally. Workaround..?
            
    if(array_search($i$day_month_parameters) !== false) {
                
    $dt 5;
                
    $v[0] = strval($v[0]);
            } else if(
    $dt == && strlen($v[0]) != 5) {
                
    // Special handling for data type 5, which is documented to return dd.mm,
                // but never actually returns that. Sometimes it returns the current
                // date/time, sometimes it is used for heating schedules. Workaround!
                
    $full_value get_text_html_value($i);
                
                if(
    strlen($full_value) == 50) { // heating schedule
                    
    $dt 4;
                    
    $field_count 6;
                    
    $v = array(
                        
    substr($full_value35),
                        
    substr($full_value115),
                        
    substr($full_value205),
                        
    substr($full_value285),
                        
    substr($full_value375),
                        
    substr($full_value455)
                    );
                    
    $field_suffix = array(
                        
    " Anfang 1",
                        
    " Ende 1",
                        
    " Anfang 2",
                        
    " Ende 2",
                        
    " Anfang 3",
                        
    " Ende 3",
                    );
                } else {
                    
    $dt 7;
                    
    $v = [$full_value];
                }
            }
            
            
    $idents = array();
            
    $var_ids = array();
            if(
    $field_count 1) {
                for(
    $fi 0$fi $field_count$fi++) {
                    
    $idents[$fi] = $ident_prefix "_" $fi;
                    
    $var_ids[$fi] = @IPS_GetObjectIDByIdent($idents[$fi], $cat_id);
                }
            } else {
                
    $idents[0] = $ident_prefix;
                
    $var_ids[0] = @IPS_GetObjectIDByIdent($ident_prefix$cat_id);
            }
            
            
    $hide_fields_after false;
            for(
    $fi 0$fi $field_count$fi++) {
                switch(
    $dt) {
                    case 
    0// number
                        
    if($v[$fi] == "" || $v[$fi] == "---") {
                            
    $v[$fi] = NO_VALUE;
                        }
                        if(
    $field_count == && substr($v[$fi], -1) == '.') {
                            
    // workaround! Faulty float result (decimal places missing after dot)
                            
    $v[$fi] = get_num_html_value($i);
                        }
                        
    $t 2;
                        
    $p setup_unit_profile($u$writeable);
                        break;
                        
                    case 
    1// enum
                        
    if($v[$fi] == "" || $v[$fi] == "---"$v[$fi] = NO_VALUE;
                        
    $p setup_enum_profile($i$writeable);
                        
    // if no enum profile could be created, do not create or update this
                        // variable.
                        
    if($p === false) continue 2;
                        
    $t 1;
                        
                        break;
                        
                    case 
    2// bit mask? as OBSERVED
                        
    $v[$fi] = get_bitmask_html_value($i);
                        break;
                        
                    case 
    4// time h:mm as OBSERVED!
                        
    $t 1;
                        
    $p "~UnixTimestampTime";
                        
    $v[$fi] = strtotime($v[$fi]);
                        if(
    $v[$fi] == && $hide_fields_after === false) {
                            
    $hide_fields_after $fi 1;
                        }
                        break;
                        
                    
    /*case 4: // full date time
                        if($v[$fi] == "" || $v[$fi] == "---") $v[$fi] = NO_VALUE;
                        $t = 1;
                        $p = "~UnixTimestamp";
                        $v[$fi] = strtotime(str_replace('.', '-', $v[$fi]));
                        break;*/
                        
                    
    case 5// date day.month
                        
    $t 1;
                        
    //$p = "~UnixTimestampDate";
                        
    if($v[$fi] == "" || $v[$fi] == "---") {
                            
    $v[$fi] = NO_VALUE;
                        } else {
                            
    $v[$fi] = substr($v[$fi], 05);
                            
    $v[$fi] = strtotime(str_replace('.''-'$v[$fi]) . "-" date("Y"));
                        }
                        
    $p setup_day_month_profile($i$v[$fi]);
                        if(
    $v[$fi] == NO_VALUE) {
                            
    $count_empty_day_month_params++;
                        } else {
                            
    $count_empty_day_month_params 0;
                        }
                        if(
    $count_empty_day_month_params 2$hide_fields_after 0;
                        break;
                        
                    case 
    6// string
                        
    break;
                        
                    case 
    7// full date time (internally used only)
                        
    if($v[$fi] == "" || $v[$fi] == "---"$v[$fi] = NO_VALUE;
                        
    $t 1;
                        
    $p "~UnixTimestamp";
                        
    $v[$fi] = strtotime(str_replace('.''-'$v[$fi]));
                        if(
    $i == 0) {
                            
    $diff $v[$fi] - time();
                            
    msg("Difference between heating / local time is " $diff " s.");
                            if(
    abs($diff) >= 15 && $sync_timesync_time();
                        }
                        break;
                } 
    // switch

                
    if(!$var_ids[$fi] && get_setup_status() < SETUP_COMPLETED) {
                    
    msg("Creating variable for parameter #" $i "." $fi " (" $par["name"] .
                        
    ") of data type " $bsb_lan_dt_name[$dt] . "(" $dt .  ") => " .
                        
    $ips_dt_name[$t] .
                        
    ", profile name \"" $p "\" with value \"" $v[$fi] . "\"."); 
                    
    $var_ids[$fi] = IPS_CreateVariable($t);
                    
    IPS_SetParent($var_ids[$fi], $cat_id);
                    
    IPS_SetName($var_ids[$fi], $par["name"] . $field_suffix[$fi]);
                    
    IPS_SetIdent($var_ids[$fi], $idents[$fi]);
                    
    IPS_SetPosition($var_ids[$fi], $i 10 $fi);
                    
    IPS_SetVariableCustomProfile($var_ids[$fi], $p);
                    if(
    $writeable) {
                        
    IPS_SetVariableCustomAction($var_ids[$fi], $_IPS['SELF']);
                    }
                }
                if(
    $var_ids[$fi]) {
                    
    IPS_SetHidden($var_ids[$fi],
                        
    $hide_fields_after !== false && $fi >= $hide_fields_after);
                    
    //if($v[$fi] == "---") msg($par["name"].": " . $dt);
                    
    SetValue($var_ids[$fi], $v[$fi]);
                }
            }
        } 
    // foreach
        
    return true;
    // update_parameters

    // Setup a variable specific profile for "day.month" type parameters. This is
    // a bit hacky, but it works better than the ~UnixTimestampDate profile, as
    // there is no year 1970 shown and it is possible to disable the parameter as
    // well.
    function setup_day_month_profile($par_index$par_value) {
        
    $profile_name ENUM_PROFILE_PREFIX $par_index;
        
    $c_selected 0xFFFFFF;
        
    $c_unselected 0x888888;
        if(!
    IPS_VariableProfileExists($profile_name)) {
            
    IPS_CreateVariableProfile($profile_name1);
            
    msg("Day.Month profile created for parameter #" $par_index ".");
        }
        
    $par_formatted date("d.m"$par_value);
        
    $associations IPS_GetVariableProfile($profile_name)["Associations"];
        foreach(
    $associations as $assoc) {
            
    $value $assoc["Value"];
            if(
    $value != $par_value && $value != NO_VALUE) {
                
    IPS_SetVariableProfileAssociation($profile_name$value"""", -1);
            }
        }
        
    IPS_SetVariableProfileAssociation(
            
    $profile_name,
            (
    $par_value == NO_VALUE) ? 1546297200 $par_value,
            (
    $par_value == NO_VALUE) ? "Ein" $par_formatted,
            
    "Calendar"// icon
            
    $par_value == $par_value $c_selected $c_unselected // color
        
    );
        
    IPS_SetVariableProfileAssociation(
            
    $profile_name,
            
    NO_VALUE,
            
    "Aus",
            
    "Cross"// icon
            
    $par_value == NO_VALUE $c_selected $c_unselected // color
        
    );
        
        return 
    $profile_name;
    // setup_day_month_profile

    // Retrieve possible values of an ENUM parameter and create a profile for it.
    // The request is done as an HTML call, since there is no json-based request
    // for it yet. May break if the HTML format changes.
    function setup_enum_profile($par_index$writeable) {
        global 
    $enum_buffer;
        
    $profile_name ENUM_PROFILE_PREFIX $par_index;
        if(!
    IPS_VariableProfileExists($profile_name)) {
            
    $arr_enum = array();
            
            if(
    array_key_exists($par_index$enum_buffer)) {
                
    $source_name " previous single category update request";
                foreach(
    $enum_buffer[$par_index] as $entry) {
                    
    $arr_enum[$entry["enumValue"]] = $entry["desc"];
                }
            } else if(
    get_setup_status() < SETUP_COMPLETED) {
                
    $source_name "HTML request of enum values";
                
    $html req("E" $par_index);
                
    $str_pre "<table align=center width=80%>";
                
    $str_pre_offs 10;
                
    $str_post "</td></tr></table>";
                
    $str_post_offs = -8;
                
    $str_sep "\r\n<br>\r\n";
                
    $html substr($htmlstrpos($html$str_pre) + strlen($str_pre) + $str_pre_offs);
                if(
    substr($html07) == "FEHLER:") {
                    
    $source_name "HTML request of current value (guessing boolean)";
                    
    $html_value get_text_html_value($par_index);
                    switch(
    $html_value) {
                        case 
    "0 - Nein":
                        case 
    "1 - Ja":
                            
    $arr_enum[0] = "Nein";
                            
    $arr_enum[1] = "Ja";
                            break;
                        case 
    "0 - Aus":
                        case 
    "1 - Ein":
                            
    $arr_enum[0] = "Aus";
                            
    $arr_enum[1] = "Ein";
                            break;
                        case 
    "0 - Aus":
                        case 
    "255 - Ein":
                            
    $arr_enum[0] = "Aus";
                            
    $arr_enum[255] = "Ein";
                            break;
                        default:
                            
    msg("Unable to create enum profile for parameter #" $par_index ": " .
                                
    "Error returned when requesting enum values and unable to " .
                                
    "deduce boolean values from current value \"" $html_value .
                                
    "\".");
                            return 
    false;
                    }
                } else {
                    
    $html substr($html0strpos($html$str_post) + $str_post_offs);
                    
    $arr_raw explode($str_sep$html);
                    foreach(
    $arr_raw as $entry) {
                        
    $index intval(substr($entry0strpos($entry" - ")));
                        
    $label substr($entrystrpos($entry" - ") + 3);
                        if(
    substr($label01) == '?'$label substr($label1);
                        
    $arr_enum[$index] = $label;
                    }
                }
            } else {
                return 
    false;
            }
            
            
    IPS_CreateVariableProfile($profile_name1);
            
    msg("Enum profile created for parameter #" $par_index " with " .
                
    count($arr_enum) . " entries from " $source_name ".");
            
            foreach(
    $arr_enum as $index => $label) {
                
    IPS_SetVariableProfileAssociation(
                    
    $profile_name,
                    
    $index,
                    
    $label,
                    
    ""// icon
                    
    -// color
                
    );
                
    // Workaround for "booleans" which are being described as enums with only
                // one possible value ("False")
                
    if(count($arr_enum) == && $label == "False") {
                    
    IPS_SetVariableProfileAssociation(
                        
    $profile_name,
                        
    1,
                        
    "True",
                        
    ""// icon
                        
    -// color
                    
    );
                }
            }
            if(!
    $writeable) {
                
    IPS_SetVariableProfileAssociation(
                    
    $profile_name,
                    
    NO_VALUE,
                    
    "Kein Wert",
                    
    "Cross"// icon
                    
    0x888888 // color
                
    );
            }
        }
        
        return 
    $profile_name;
    // setup_enum_profile

    function setup_unit_profile($unit$writeable) {
        
    // for writeable values we should use the builtin profiles
        
    if($writeable) {
            switch(
    $unit) {
                case 
    "&deg;C": return "~Temperature";
                case 
    "K": return "~Temperature.Difference";
                case 
    "%": return "~Humidity.F";
            }
        }
        
        switch(
    $unit) {
            case 
    " ": return ""// workaround, sometimes a space gets sent
            
    case "&deg;C"$unit "degrees"$digits 1$icon "Temperature"; break;
            case 
    "%"$unit "percent"$digits 0$icon "Intensity"; break;
            case 
    "K"$digits 0$icon "Temperature"; break;
            case 
    "h":
            case 
    "min":
            case 
    "s":
                
    $icon "Clock";
                
    $digits 0;
                break;
            default: 
    msg("Unknown unit: \"" $unit "\"."); return "";
        }
        
        
    $profile_name UNIT_PROFILE_PREFIX $unit;
        if(!
    IPS_VariableProfileExists($profile_name)) {
            
    IPS_CreateVariableProfile($profile_name2);
            
    msg("Unit profile created for unit \"" $unit "\".");
            if(
    $unit == "percent") {
                
    $unit "%%";
            } else if(
    $unit == "degrees") {
                
    $unit "°C";
            } else {
                
    $unit ' ' $unit;
            }
            
    IPS_SetVariableProfileDigits($profile_name$digits);
            
    IPS_SetVariableProfileAssociation(
                
    $profile_name,
                
    NO_VALUE 1,
                ((
    $digits == 0) ? "%d" : ("%." $digits "f")) . $unit,
                
    $icon// icon
                
    -// color
            
    );
            
    IPS_SetVariableProfileAssociation(
                
    $profile_name,
                
    NO_VALUE,
                
    "Kein Wert",
                
    "Cross"// icon
                
    0x888888 // color
            
    );
        }
        
        return 
    $profile_name;
    // setup_unit_profile

    function set_parameter($index$value$inf false) {
        
    $html req(($inf "I" "S") . $index "=" $value);
        
    $result_raw get_text_html_value($index$html);
        if(
    is_int($value)) {
            
    $result intval($result_raw);
        } else if(
    is_float($value)) {
            
    $result floatval($result_raw);
        } else {
            
    $result $result_raw;
        }
        
        
    msg("Parameter #" $index . ($inf " sent INF message \"" " set to \"") .
            
    $value "\", returned raw value" .
            
    " \"" $result_raw "\", interpreted as \""$result "\".");
        return 
    $result;
    // set_parameter
              
    function req($req) {
        global 
    $ip$pass_key;
        
        
    $expect_json = (substr($req01) == "J");
        if(
    $pass_key) {
            
    $req $pass_key "/" $req;
        }                        
        
    $result = @file_get_contents("http://" $ip "/" $req);
        
        if(
    $expect_json) {
            
    // workaround to filter out illegale characters from json response
            
    $result preg_replace('/[\x00-\x1F\x7F]/'''$result);
            
    $data = @json_decode($resulttrue);
            if(
    $data && count($data) > 0) {
                return 
    $data;
            }
        } else {
            return 
    $result;
        }
        return 
    false;
    // req
    ?>
    Name:  scsh.jpg
Hits: 93
Größe:  174.3 KB
    Geändert von sokkederheld (14.08.19 um 11:34 Uhr) Grund: Screenshot
    LCN | HM | FS20, HMS und FHT | Arduino | ESP usw.
    "Der RGB-Streifen ist das Arschgeweih der Home Automation. "

Ähnliche Themen

  1. Symcon das richtige für mein Projekt?
    Von power dodge im Forum Allgemeine Diskussion
    Antworten: 124
    Letzter Beitrag: 25.02.18, 14:03
  2. IPSLogger - mein kleiner feiner LogHandler für IPS
    Von Brownson im Forum IPSLibrary
    Antworten: 289
    Letzter Beitrag: 20.04.17, 09:55
  3. Antworten: 0
    Letzter Beitrag: 11.12.15, 20:28
  4. Antworten: 3
    Letzter Beitrag: 01.02.15, 04:18
  5. Antworten: 0
    Letzter Beitrag: 15.02.13, 10:22