diff --git a/fhem/contrib/betateilchen/debug/98_configdb.pm b/fhem/contrib/betateilchen/debug/98_configdb.pm new file mode 100644 index 000000000..2d1b2ba7c --- /dev/null +++ b/fhem/contrib/betateilchen/debug/98_configdb.pm @@ -0,0 +1,642 @@ +# $Id$ +# + +package main; +use strict; +use warnings; +use feature qw/say switch/; +use POSIX; +use configDB; + +no if $] >= 5.017011, warnings => 'experimental'; + +sub CommandConfigdb; +sub _cfgDB_readConfig(); + +my @pathname; + +sub configdb_Initialize { + my %hash = ( Fn => "CommandConfigdb", + Hlp => "help ,access additional functions from configDB" ); + $cmds{configdb} = \%hash; +} + +sub CommandConfigdb { + my ($cl, $param) = @_; + + my @a = split("[ \t][ \t]*", $param); + my ($cmd, $param1, $param2) = @a; + $cmd //= ""; + $param1 //= ""; + $param2 //= ""; + + my $configfile = $attr{global}{configfile}; + return "\n error: configDB not used!" unless($configfile eq 'configDB' || $cmd eq 'migrate'); + + my $ret; + + given ($cmd) { + + when ('attr') { + Log3('configdb', 4, "configdb: attr $param1 $param2 requested."); + if ($param1 eq '' && $param2 eq '') { + # list attributes + foreach my $c (sort keys %{$configDB{attr}}) { + my $val = $configDB{attr}{$c}; + $val =~ s/;/;;/g; + $val =~ s/\n/\\\n/g; + $ret .= "configdb attr $c $val\n"; + } + } elsif(lc($param1) eq '?' || lc($param1) eq 'help') { + # list all available attributes + my $l = 0; + foreach my $c (sort keys %{$configDB{knownAttr}}) { + $l = length($c) > $l ? length($c) : $l; + } + foreach my $c (sort keys %{$configDB{knownAttr}}) { + my $val = $configDB{knownAttr}{$c}; + $val =~ s/;/;;/g; + $val =~ s/\n/\\\n/g; + $ret .= sprintf("%-*s : ",$l,$c)."$val\n"; + } + } elsif($param2 eq '') { + # delete attribute + delete $configDB{attr}{$param1}; + $ret = " attribute $param1 deleted"; + addStructChange('configdb attr',undef,"$param1 (deleted)"); + + } else { + # set attribute + $configDB{attr}{$param1} = $param2; + $ret = " attribute $param1 set to value $param2"; + addStructChange('configdb attr',undef,"$param1 $param2 (set)"); + } + } + + when ('dump') { + return _cfgDB_dump($param1); + } + + + when ('diff') { + return "\n Syntax: configdb diff " if @a != 3; + return "Invalid paramaeter '$param2' for diff. Must be a number." + unless (looks_like_number($param2) || $param2 eq 'current'); + Log3('configdb', 4, "configdb: diff requested for device: $param1 in version $param2."); + $ret = _cfgDB_Diff($param1, $param2); + } + + when ('filedelete') { + return "\n Syntax: configdb filedelete " if @a != 2; + my $filename; + if($param1 =~ m,^[./],) { + $filename = $param1; + } else { + $filename = $attr{global}{modpath}; + $filename .= "/$param1"; + } + $ret = "File $filename "; + $ret .= defined(_cfgDB_Filedelete($filename)) ? "deleted from" : "not found in"; + $ret .= " database."; + } + + when ('fileexport') { + return "\n Syntax: configdb fileexport " if @a != 2; + if ($param1 ne 'all') { + my $filename; + if($param1 =~ m,^[./],) { + $filename = $param1; + } else { + $filename = $attr{global}{modpath}; + $filename .= "/$param1"; + } + $ret = _cfgDB_Fileexport $filename; + } else { # start export all + my $flist = _cfgDB_Filelist(1); + my @filelist = split(/\n/,$flist); + undef $flist; + foreach my $f (@filelist) { + Log3 (4,undef,"configDB: exporting $f"); + my ($path,$file) = $f =~ m|^(.*[/\\])([^/\\]+?)$|; + $path = "/tmp/$path"; + eval { qx(mkdir -p $path) } unless (-e "$path"); + $ret .= _cfgDB_Fileexport $f; + $ret .= "\n"; + } + } # end export all + } + + when ('fileimport') { + return "\n Syntax: configdb fileimport " if @a != 2; + my $filename; + if($param1 =~ m,^[./],) { + $filename = $param1; + } else { + $filename = $attr{global}{modpath}; + $filename .= "/$param1"; + } + if ( -r $filename ) { + my $filesize = -s $filename; + $ret = _cfgDB_binFileimport($filename,$filesize); + } elsif ( -e $filename) { + $ret = "\n Read error on file $filename"; + } else { + $ret = "\n File $filename not found."; + } + } + + when ('filelist') { + return _cfgDB_Filelist; + } + + when ('filemove') { + return "\n Syntax: configdb filemove " if @a != 2; + my $filename; + if($param1 =~ m,^[./],) { + $filename = $param1; + } else { + $filename = $attr{global}{modpath}; + $filename .= "/$param1"; + } + if ( -r $filename ) { + my $filesize = -s $filename; + $ret = _cfgDB_binFileimport ($filename,$filesize,1); + $ret .= "\nFile $filename deleted from local filesystem."; + } elsif ( -e $filename) { + $ret = "\n Read error on file $filename"; + } else { + $ret = "\n File $filename not found."; + } + } + + when ('fileshow') { + return "\n Syntax: configdb fileshow " if @a != 2; + my @rets = cfgDB_FileRead($param1); + my $r = (int(@rets)) ? join "\n",@rets : "File $param1 not found in database."; + return $r; + } + + when ('info') { + Log3('configdb', 4, "info requested."); + $ret = _cfgDB_Info('$Id$'); + } + + when ('list') { + $param1 = $param1 ? $param1 : '%'; + $param2 = looks_like_number($param2) ? $param2 : 0; + $ret = "list not allowed for configDB itself."; + break if($param1 =~ m/configdb/i); + Log3('configdb', 4, "configdb: list requested for device: $param1 in version $param2."); + $ret = _cfgDB_Search($param1,$param2,1); + } + + when ('migrate') { + return "\n Migration not possible. Already running with configDB!" if $configfile eq 'configDB'; + Log3('configdb', 4, "configdb: migration requested."); + $ret = _cfgDB_Migrate; + } + + when ('rawList'){ + $data{cfgDB_rawList} = 1; + my @out = cfgDB_SaveCfg(); + delete $data{cfgDB_rawList}; + return join("\n",@out); + } + + when ('recover') { + return "\n Syntax: configdb recover " if @a != 2; + return "Invalid paramaeter '$param1' for recover. Must be a number." + unless looks_like_number($param1); + Log3('configdb', 4, "configdb: recover for version $param1 requested."); + $ret = _cfgDB_Recover($param1); + } + + when ('reorg') { + $param1 = 3 unless $param1; + return "Invalid paramaeter '$param1' for reorg. Must be a number." + unless looks_like_number($param1); + Log3('configdb', 4, "configdb: reorg requested with keep: $param1."); + $ret = _cfgDB_Reorg($param1); + } + + when ('search') { + return "\n Syntax: configdb search [searchVersion]" if @a < 2; + $param1 = $param1 ? $param1 : '%'; + $param2 = looks_like_number($param2) ? $param2 : 0; + Log3('configdb', 4, "configdb: list requested for device: $param1 in version $param2."); + $ret = _cfgDB_Search($param1,$param2,0); + } + + when ('uuid') { + $param1 = createUniqueId(); + Log3('configdb', 4, "configdb: uuid requested: $param1"); + $ret = $param1; + } + + default { + $ret = "\n Syntax:\n". + " configdb attr [attribute] [value]\n". + " configdb diff \n". + " configdb dump\n". + " configDB filedelete \n". + " configDB fileimport \n". + " configDB fileexport \n". + " configDB filelist\n". + " configDB filemove \n". + " configDB fileshow \n". + " configdb info\n". + " configdb list [device] [version]\n". + " configdb migrate\n". + " configdb rawList\n". + " configdb recover \n". + " configdb reorg [keepVersions]\n". + " configdb search [version]\n". + " configdb uuid\n". + ""; + } + + } + + return $ret; + +} + +sub _cfgDB_readConfig() { + my ($conf,@config); + if(!open($conf, '<', 'configDB.conf')) { + Log3('configDB', 1, 'Cannot open database configuration file configDB.conf'); + return 0; + } + @config=<$conf>; + close($conf); + + use vars qw(%configDB); + + my %dbconfig; +## no critic + eval join("", @config) ; +## use critic + + my $cfgDB_dbconn = $dbconfig{connection}; + my $cfgDB_dbuser = $dbconfig{user}; + my $cfgDB_dbpass = $dbconfig{password}; + my $cfgDB_dbtype; + + %dbconfig = (); + @config = (); + + if($cfgDB_dbconn =~ m/pg:/i) { + $cfgDB_dbtype ="POSTGRESQL"; + } elsif ($cfgDB_dbconn =~ m/mysql:/i) { + $cfgDB_dbtype = "MYSQL"; + } elsif ($cfgDB_dbconn =~ m/sqlite:/i) { + $cfgDB_dbtype = "SQLITE"; + } else { + $cfgDB_dbtype = "unknown"; + } + + return($cfgDB_dbconn,$cfgDB_dbuser,$cfgDB_dbpass,$cfgDB_dbtype); +} + +1; + +=pod +=item command +=item summary frontend command for configDB configuration +=item summary_DE Befehl zur Konfiguration der configDB +=begin html + + +

configdb

+
    + Link to FHEM forum

    + Starting with version 5079, fhem can be used with a configuration database instead of a plain text file (e.g. fhem.cfg).
    + This offers the possibility to completely waive all cfg-files, "include"-problems and so on.
    + Furthermore, configDB offers a versioning of several configuration together with the possibility to restore a former configuration.
    + Access to database is provided via perl's database interface DBI.
    +
    + + Interaction with other modules
    +

      + Currently the fhem modules
      +
      +
    • 02_RSS.pm
    • +
    • 55_InfoPanel.pm
    • +
    • 91_eventTypes
    • +
    • 93_DbLog.pm
    • +
    • 95_holiday.pm
    • +
    • 98_SVG.pm
    • +
    • 98_weekprofile.pm
    • +
      + will use configDB to read their configuration data from database
      + instead of formerly used configuration files inside the filesystem.
      +
      + This requires you to import your configuration files from filesystem into database.
      +
      + Examples:
      + configdb fileimport FHEM/nrw.holiday
      + configdb fileimport FHEM/myrss.layout
      + configdb fileimport www/gplot/xyz.gplot
      +
      + This does not affect the definitons of your holiday or RSS entities.
      +
      + During migration all external configfiles used in current configuration
      + will be imported aufmatically.

      +
      + Each fileimport into database will overwrite the file if it already exists in database.
      +
      +

    +
    + + Prerequisits / Installation
    +

      +
    • Please install perl package Text::Diff if not already installed on your system.

    • +
    • You must have access to a SQL database. Supported database types are SQLITE, MYSQL and POSTGRESQL.

    • +
    • The corresponding DBD module must be available in your perl environment,
      + e.g. sqlite3 running on a Debian systems requires package libdbd-sqlite3-perl

    • +
    • Create an empty database, e.g. with sqlite3:
      +
      +	mba:fhem udo$ sqlite3 configDB.db
      +
      +	SQLite version 3.7.13 2012-07-17 17:46:21
      +	Enter ".help" for instructions
      +	Enter SQL statements terminated with a ";"
      +	sqlite> pragma auto_vacuum=2;
      +	sqlite> .quit
      +
      +	mba:fhem udo$ 
      +			
    • +
    • The database tables will be created automatically.

    • +
    • Create a configuration file containing the connection string to access database.
      +
      + IMPORTANT: +

        +
      • This file must be named "configDB.conf"
      • +
      • This file must be located in the same directory containing fhem.pl and configDB.pm, e.g. /opt/fhem
      • +
      +
      +
      +## for MySQL
      +################################################################
      +#%dbconfig= (
      +#	connection => "mysql:database=configDB;host=db;port=3306",
      +#	user => "fhemuser",
      +#	password => "fhempassword",
      +#);
      +################################################################
      +#
      +## for PostgreSQL
      +################################################################
      +#%dbconfig= (
      +#        connection => "Pg:database=configDB;host=localhost",
      +#        user => "fhemuser",
      +#        password => "fhempassword"
      +#);
      +################################################################
      +#
      +## for SQLite (username and password stay empty for SQLite)
      +################################################################
      +#%dbconfig= (
      +#        connection => "SQLite:dbname=/opt/fhem/configDB.db",
      +#        user => "",
      +#        password => ""
      +#);
      +################################################################
      +			

    • +
    + + Start with a complete new "fresh" fhem Installation
    +

      + It's easy... simply start fhem by issuing following command:

      +
        perl fhem.pl configDB

      + + configDB is a keyword which is recognized by fhem to use database for configuration.
      +
      + That's all. Everything (save, rereadcfg etc) should work as usual. +
    + +
    + or:
    +
    + + Migrate your existing fhem configuration into the database
    +

      + It's easy, too...
      +
      +
    • start your fhem the last time with fhem.cfg

      +
        perl fhem.pl fhem.cfg

    • +
      +
    • transfer your existing configuration into the database

      +
        enter

        configdb migrate
        +
        + into frontend's command line


      + Be patient! Migration can take some time, especially on mini-systems like RaspberryPi or Beaglebone.
      + Completed migration will be indicated by showing database statistics.
      + Your original configfile will not be touched or modified by this step.

    • +
    • shutdown fhem

    • +
    • restart fhem with keyword configDB

      +
        perl fhem.pl configDB

    • + configDB is a keyword which is recognized by fhem to use database for configuration.
      +
      + That's all. Everything (save, rereadcfg etc) should work as usual. +
    +

    + + Additional functions provided
    +

      + A new command configdb is propagated to fhem.
      + This command can be used with different parameters.
      +
      + +
    • configdb attr [attribute] [value]

    • + Provides the possibility to pass attributes to backend and frontend.
      +
      + configdb attr private 1 - set the attribute named 'private' to value 1.
      +
      + configdb attr private - delete the attribute named 'private'
      +
      + configdb attr - show all defined attributes.
      +
      + configdb attr ?|help - show a list of available attributes.
      +
      + +
    • configdb diff <device> <version>

    • + Compare configuration dataset for device <device> + from current version 0 with version <version>
      + Example for valid request:
      +
      + configdb diff telnetPort 1
      +
      + will show a result like this: +
      +compare device: telnetPort in current version 0 (left) to version: 1 (right)
      ++--+--------------------------------------+--+--------------------------------------+
      +| 1|define telnetPort telnet 7072 global  | 1|define telnetPort telnet 7072 global  |
      +* 2|attr telnetPort room telnet           *  |                                      |
      ++--+--------------------------------------+--+--------------------------------------+
      + Special: configdb diff all current
      +
      + Will show a diff table containing all changes between saved version 0
      + and UNSAVED version from memory (currently running installation).
      +
      + +
    • configdb dump [unzipped]

    • + Create a gzipped dump file from from database.
      + If optional parameter 'unzipped' provided, dump file will be written unzipped.
      +
      +
      + +
    • configdb filedelete <Filename>

    • + Delete file from database.
      +
      +
      + +
    • configdb fileexport <targetFilename>|all

    • + Exports specified file (or all files) from database into filesystem.
      + Example:
      +
      + configdb fileexport FHEM/99_myUtils.pm
      +
      +
      + +
    • configdb fileimport <sourceFilename>

    • + Imports specified text file from from filesystem into database.
      + Example:
      +
      + configdb fileimport FHEM/99_myUtils.pm
      +
      +
      + +
    • configdb filelist

    • + Show a list with all filenames stored in database.
      +
      +
      + +
    • configdb filemove <sourceFilename>

    • + Imports specified fhem file from from filesystem into database and
      + deletes the file from local filesystem afterwards.
      + Example:
      +
      + configdb filemove FHEM/99_myUtils.pm
      +
      +
      + +
    • configdb fileshow <Filename>

    • + Show content of specified file stored in database.
      +
      +
      + +
    • configdb info

    • + Returns some database statistics
      +
      +--------------------------------------------------------------------------------
      + configDB Database Information
      +--------------------------------------------------------------------------------
      + dbconn: SQLite:dbname=/opt/fhem/configDB.db
      + dbuser: 
      + dbpass: 
      + dbtype: SQLITE
      +--------------------------------------------------------------------------------
      + fhemconfig: 7707 entries
      +
      + Ver 0 saved: Sat Mar  1 11:37:00 2014 def: 293 attr: 1248
      + Ver 1 saved: Fri Feb 28 23:55:13 2014 def: 293 attr: 1248
      + Ver 2 saved: Fri Feb 28 23:49:01 2014 def: 293 attr: 1248
      + Ver 3 saved: Fri Feb 28 22:24:40 2014 def: 293 attr: 1247
      + Ver 4 saved: Fri Feb 28 22:14:03 2014 def: 293 attr: 1246
      +--------------------------------------------------------------------------------
      + fhemstate: 1890 entries saved: Sat Mar  1 12:05:00 2014
      +--------------------------------------------------------------------------------
      +
      +Ver 0 always indicates the currently running configuration.
      +
      + +
    • configdb list [device] [version]

    • + Search for device named [device] in configuration version [version]
      + in database archive.
      + Default value for [device] = % to show all devices.
      + Default value for [version] = 0 to show devices from current version.
      + Examples for valid requests:
      +
      + get configDB list
      + get configDB list global
      + get configDB list '' 1
      + get configDB list global 1
      +
      + +
    • configdb rawList

    • + Lists the running configuration in the same order that
      + would be written to a configuration file.
      +
      + +
    • configdb recover <version>

    • + Restores an older version from database archive.
      + configdb recover 3 will copy version #3 from database + to version #0.
      + Original version #0 will be lost.

      + Important!
      + The restored version will NOT be activated automatically!
      + You must do a rereadcfg or - even better - shutdown restart yourself.
      +
      + +
    • configdb reorg [keep]

    • + Deletes all stored versions with version number higher than [keep].
      + Default value for optional parameter keep = 3.
      + This function can be used to create a nightly running job for
      + database reorganisation when called from an at-Definition.
      +
      + +
    • configdb search [searchVersion]

    • + Search for specified searchTerm in any given version (default=0)
      +
      +Example:
      +
      +configdb search %2286BC%
      +
      +Result:
      +
      +search result for: %2286BC% in version: 0 
      +-------------------------------------------------------------------------------- 
      +define az_RT CUL_HM 2286BC 
      +define az_RT_Clima CUL_HM 2286BC04 
      +define az_RT_Climate CUL_HM 2286BC02 
      +define az_RT_ClimaTeam CUL_HM 2286BC05 
      +define az_RT_remote CUL_HM 2286BC06 
      +define az_RT_Weather CUL_HM 2286BC01 
      +define az_RT_WindowRec CUL_HM 2286BC03 
      +attr Melder_FAl peerIDs 00000000,2286BC03, 
      +attr Melder_FAr peerIDs 00000000,2286BC03, 
      +
      +
      + +
    • configdb uuid

    • + Returns a uuid that can be used for own purposes.
      +
      + +
    +
    +
    + Author's notes
    +
    +
      +
    • You can find two template files for datebase and configfile (sqlite only!) for easy installation.
      + Just copy them to your fhem installation directory (/opt/fhem) and have fun.
    • +
      +
    • The frontend option "Edit files"->"config file" will be removed when running configDB.
    • +
      +
    • Please be patient when issuing a "save" command + (either manually or by clicking on "save config").
      + This will take some moments, due to writing version informations.
      + Finishing the save-process will be indicated by a corresponding message in frontend.
    • +
      +
    • There still will be some more (planned) development to this extension, + especially regarding some perfomance issues.
    • +
      +
    • Have fun!
    • +
    + +
+ +=end html + +=cut diff --git a/fhem/contrib/betateilchen/debug/configDB.pm b/fhem/contrib/betateilchen/debug/configDB.pm index 8cdc538f0..559a598cf 100644 --- a/fhem/contrib/betateilchen/debug/configDB.pm +++ b/fhem/contrib/betateilchen/debug/configDB.pm @@ -519,12 +519,14 @@ sub cfgDB_SaveCfg { ## prototype used in fhem.pl push @rowList, "attr $c $a $val"; } -# Insert @rowList into database table - my $fhem_dbh = _cfgDB_Connect; - my $uuid = _cfgDB_Rotate($fhem_dbh,$internal); $t = localtime; $out = "#created $t"; push @rowList, $out; + return @rowList if defined($data{cfgDB_rawList}); + +# Insert @rowList into database table + my $fhem_dbh = _cfgDB_Connect; + my $uuid = _cfgDB_Rotate($fhem_dbh,$internal); my $counter = 0; foreach (@rowList) { _cfgDB_InsertLine($fhem_dbh, $uuid, $_, $counter);