diff --git a/fhem/MAINTAINER.txt b/fhem/MAINTAINER.txt
index 802119ad5..944d046bc 100644
--- a/fhem/MAINTAINER.txt
+++ b/fhem/MAINTAINER.txt
@@ -602,6 +602,7 @@ FHEM/lib/UPnP/* Reinerlein Multimedia
lib/FHEM/Core/Timer/Helper.pm sidey79 FHEM Development
lib/FHEM/SynoModules/API.pm DS_Starter Sonstiges
+lib/FHEM/SynoModules/SMUtils.pm DS_Starter Sonstiges
contrib/sacha_gloor/* rudolfkoenig Sonstiges
contrib/70_ONKYO_AVR_PULL.pm loredo (deprecated)
diff --git a/fhem/lib/FHEM/SynoModules/SMUtils.pm b/fhem/lib/FHEM/SynoModules/SMUtils.pm
new file mode 100644
index 000000000..eab78c8c0
--- /dev/null
+++ b/fhem/lib/FHEM/SynoModules/SMUtils.pm
@@ -0,0 +1,180 @@
+########################################################################################################################
+# $Id$
+#########################################################################################################################
+# SMUtils.pm
+#
+# (c) 2020 by Heiko Maaz
+# e-mail: Heiko dot Maaz at t-online dot de
+#
+# This Module provides routines for FHEM modules developed for Synology use cases.
+#
+# This script is part of fhem.
+#
+# Fhem is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# Fhem is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with fhem. If not, see .
+#
+#########################################################################################################################
+
+package FHEM::SynoModules::SMUtils;
+
+use strict;
+use warnings;
+use utf8;
+
+# use lib qw(/opt/fhem/FHEM); # für Syntaxcheck mit: perl -c /opt/fhem/lib/FHEM/SynoModules/SMUtils.pm
+use GPUtils qw( GP_Import GP_Export );
+use Carp qw(croak carp);
+
+use version; our $VERSION = qv('1.0.0');
+
+use Exporter ('import');
+our @EXPORT_OK = qw(
+ getClHash
+ trim
+ sortVersion
+ setVersionInfo
+ );
+
+our %EXPORT_TAGS = (all => [@EXPORT_OK]);
+
+# Run before module compilation
+BEGIN {
+ # Import from main::
+ GP_Import(
+ qw(
+ Log3
+ defs
+ modules
+ devspec2array
+ )
+ );
+};
+
+###############################################################################
+# Clienthash übernehmen oder zusammenstellen
+# Identifikation ob über FHEMWEB ausgelöst oder nicht -> erstellen $hash->CL
+###############################################################################
+sub getClHash {
+ my $hash = shift // carp "got no hash value !" && return;
+ my $nobgd = shift;
+ my $name = $hash->{NAME};
+ my $ret;
+
+ if($nobgd) { # nur übergebenen CL-Hash speichern, keine Hintergrundverarbeitung bzw. synthetische Erstellung CL-Hash
+ $hash->{HELPER}{CL}{1} = $hash->{CL};
+ return;
+ }
+
+ if (!defined($hash->{CL})) { # Clienthash wurde nicht übergeben und wird erstellt (FHEMWEB Instanzen mit canAsyncOutput=1 analysiert)
+ my $outdev;
+ my @webdvs = devspec2array("TYPE=FHEMWEB:FILTER=canAsyncOutput=1:FILTER=STATE=Connected");
+ my $i = 1;
+ for (@webdvs) {
+ $outdev = $_;
+ next if(!$defs{$outdev});
+ $hash->{HELPER}{CL}{$i}->{NAME} = $defs{$outdev}{NAME};
+ $hash->{HELPER}{CL}{$i}->{NR} = $defs{$outdev}{NR};
+ $hash->{HELPER}{CL}{$i}->{COMP} = 1;
+ $i++;
+ }
+
+ } else { # übergebenen CL-Hash in Helper eintragen
+ $hash->{HELPER}{CL}{1} = $hash->{CL};
+ }
+
+ if (defined($hash->{HELPER}{CL}{1})) { # Clienthash auflösen zur Fehlersuche (aufrufende FHEMWEB Instanz)
+ for (my $k=1; (defined($hash->{HELPER}{CL}{$k})); $k++ ) {
+ Log3 ($name, 4, "$name - Clienthash number: $k");
+ while (my ($key,$val) = each(%{$hash->{HELPER}{CL}{$k}})) {
+ $val = $val // " ";
+ Log3 ($name, 4, "$name - Clienthash: $key -> $val");
+ }
+ }
+
+ } else {
+ Log3 ($name, 2, "$name - Clienthash was neither delivered nor created !");
+ $ret = "Clienthash was neither delivered nor created. Can't use asynchronous output for function.";
+ }
+
+return $ret;
+}
+
+###############################################################################
+# Leerzeichen am Anfang / Ende eines strings entfernen
+###############################################################################
+sub trim {
+ my $str = shift;
+ $str =~ s/^\s+|\s+$//gx;
+
+return $str;
+}
+
+################################################################
+# sortiert eine Liste von Versionsnummern x.x.x
+# Schwartzian Transform and the GRT transform
+# Übergabe: "asc | desc",
+################################################################
+sub sortVersion {
+ my ($sseq,@versions) = @_;
+
+ my @sorted = map {$_->[0]}
+ sort {$a->[1] cmp $b->[1]}
+ map {[$_, pack "C*", split /\./x]} @versions;
+
+ @sorted = map {join ".", unpack "C*", $_}
+ sort
+ map {pack "C*", split /\./x} @versions;
+
+ if($sseq eq "desc") {
+ @sorted = reverse @sorted;
+ }
+
+return @sorted;
+}
+
+#############################################################################################
+# Versionierungen des Moduls setzen
+# Die Verwendung von Meta.pm und Packages wird berücksichtigt
+#############################################################################################
+sub setVersionInfo {
+ my $hash = shift // carp "got no hash value !" && return;
+ my $notes = shift // carp "got no vNotesIntern value !" && return;
+ my $name = $hash->{NAME};
+
+ my $v = (sortVersion("desc",keys %{$notes}))[0];
+ my $type = $hash->{TYPE};
+ $hash->{HELPER}{PACKAGE} = __PACKAGE__;
+ $hash->{HELPER}{VERSION} = $v;
+
+ if($modules{$type}{META}{x_prereqs_src} && !$hash->{HELPER}{MODMETAABSENT}) { # META-Daten sind vorhanden
+ $modules{$type}{META}{version} = "v".$v; # Version aus META.json überschreiben, Anzeige mit {Dumper $modules{}{META}}
+
+ if($modules{$type}{META}{x_version}) { # {x_version} ( nur gesetzt wenn $Id$ im Kopf komplett! vorhanden )
+ $modules{$type}{META}{x_version} =~ s/1\.1\.1/$v/gx;
+ } else {
+ $modules{$type}{META}{x_version} = $v;
+ }
+ return $@ unless (FHEM::Meta::SetInternals($hash)); # FVERSION wird gesetzt ( nur gesetzt wenn $Id$ im Kopf komplett! vorhanden )
+
+ if(__PACKAGE__ eq "FHEM::$type" || __PACKAGE__ eq $type) { # es wird mit Packages gearbeitet -> mit {->VERSION()} im FHEMWEB kann Modulversion abgefragt werden
+ use version; our $VERSION = FHEM::Meta::Get( $hash, 'version' ); ## no critic 'VERSION Reused'
+ }
+
+ } else { # herkömmliche Modulstruktur
+ $hash->{VERSION} = $v;
+ }
+
+return;
+}
+
+1;
\ No newline at end of file