########################################################################################################################
# $Id: 49_SSCam.pm 17891 2018-12-03 21:52:16Z DS_Starter $
#########################################################################################################################
# 49_SSCam.pm
#
# (c) 2015-2018 by Heiko Maaz
# e-mail: Heiko dot Maaz at t-online dot de
#
# This Module can be used to operate Cameras defined in Synology Surveillance Station 7.0 or higher.
# It's based on and uses Synology Surveillance Station API.
#
# 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 .
#
#########################################################################################################################
#
# Definition: define SSCam [ServerPort] [Protocol]
#
# Example of defining a Cam-device: define CamCP1 SSCAM Carport 192.168.2.20 [5000] [HTTP(S)]
# Example of defining a SVS-device: define SDS1 SSCAM SVS 192.168.2.20 [5000] [HTTP(S)]
#
package main;
use strict;
use warnings;
eval "use JSON qw( decode_json );1;" or my $SScamMMDBI = "JSON"; # Debian: apt-get install libjson-perl
use Data::Dumper; # Perl Core module
use MIME::Base64;
use Time::HiRes;
use HttpUtils;
# no if $] >= 5.017011, warnings => 'experimental';
# Versions History intern
our %SSCam_vNotesIntern = (
"7.7.0" => "07.12.2018 SVS-Device: autocreateCams command added, some other fixes and improvements, minor code rewrite, ".
"save Stream \$streamHash->{HELPER}{STREAM} for popupStream in SSCamSTRM-Device ",
"7.6.0" => "02.12.2018 sub SSCam_ptzpanel completed by Preset and Patrol, minor fixes ",
"7.5.0" => "02.12.2018 sub SSCam_StreamDev and SSCam_composegallery changed to use popup window ",
"7.4.1" => "26.11.2018 sub composegallery deleted, SSCam_composegallery changed to get information for SSCam_refresh ",
"7.4.0" => "24.11.2018 new set command \"createReadingsGroup\", versionNotes can process lists like \"2,6\", changed compatibility check, use SnapId when get information after took snapshot and sscam state-event ",
"7.3.3" => "18.11.2018 change rights decsption in commandRef ",
"7.3.2" => "12.11.2018 fix Warning in line 4954, set COMPATIBILITY to 8.2.2 ",
"7.3.1" => "31.10.2018 fix connection lost failure if several SSCamSTRM devices are defined and updated by longpoll from same parent device ",
"7.3.0" => "28.10.2018 usage of attribute \"livestreamprefix\" changed, exec SSCam_getStmUrlPath on boot ",
"7.2.1" => "23.10.2018 new routine SSCam_versionCheck, COMPATIBILITY changed to 8.2.1 ",
"7.2.0" => "20.10.2018 direct help for attributes, new get versionNotes command, fix PERL WARNING: Use of uninitialized value \$small, get versionNotes ",
"7.1.1" => "18.10.2018 Message of \"Your current/simulated SVS-version...\" changed, commandref corrected ",
"7.1.0" => "02.09.2018 PIR Sensor enable/disable, SSCam_Set/SSCam_Get optimized ",
"7.0.1" => "27.08.2018 enable/disable issue (https://forum.fhem.de/index.php/topic,45671.msg830869.html#msg830869) ",
"7.0.0" => "27.07.2018 compatibility to API v2.8 ",
"6.0.1" => "04.07.2018 Reading CamFirmware ",
"6.0.0" => "03.07.2018 HTTPS Support, buttons for refresh SSCamSTRM-devices ",
"5.3.0" => "29.06.2018 changes regarding to \"createStreamDev ... generic\", refresh reading parentState of all, SSCamSTRM devices with PARENT=SSCam-device, control elements for runView within fhemweb, new CamLive.*-Readings, minor fixes ",
"5.2.7" => "26.06.2018 fix state turns to \"off\" even though cam is disabled ",
"5.2.6" => "20.06.2018 running stream as human readable entry for SSCamSTRM-Device, goAbsPTZ fix set-entry für non-PTZ ",
"5.2.5" => "18.06.2018 trigger lastsnap_fw to SSCamSTRM-Device only if snap was done by it. ",
"5.2.4" => "17.06.2018 SSCam_composegallery added and write warning if old composegallery-weblink device is used ",
"5.2.3" => "16.06.2018 no SSCamSTRM refresh when snapgetinfo was running without taken a snap by SSCamSTRM-Device ",
"5.2.2" => "16.06.2018 compatibility to SSCamSTRM V 1.1.0 ",
"5.2.1" => "14.06.2018 design change of SSCam_StreamDev, change in event generation for SSCam_StreamDev, fix global vars ",
"5.2.0" => "14.06.2018 support longpoll refresh of SSCamSTRM-Devices ",
"5.1.0" => "13.06.2018 more control elements (Start/Stop Recording, Take Snapshot) in func SSCam_StreamDev, control of detaillink is moved to SSCamSTRM-device ",
"5.0.1" => "12.06.2018 control of page refresh improved (for e.g. Floorplan,Dashboard) ",
"5.0.0" => "11.06.2018 HLS Streaming, Buttons for Streaming-Devices, use of module SSCamSTRM for Streaming-Devices, deletion of Streaming-devices if SSCam-device is deleted, some more improvements, minor bugfixes ",
"4.3.0" => "27.05.2018 HLS preparation changed ",
"4.2.0" => "22.05.2018 PTZ-Panel integrated to created StreamDevice ",
"4.1.0" => "05.05.2018 use SYNO.SurveillanceStation.VideoStream instead of SYNO.SurveillanceStation.VideoStreaming, preparation for hls ",
"4.0.0" => "01.05.2018 AudioStream possibility added ",
"3.10.0" => "24.04.2018 createStreamDev added, new features lastrec_fw_MJPEG, lastrec_fw_MPEG4/H.264 added to playback MPEG4/H.264 videos ",
"3.9.2" => "21.04.2018 minor fixes ",
"3.9.1" => "20.04.2018 Attribute ptzPanel_use, initial webcommands in DeviceOverview changed, minor fixes ptzPanel ",
"3.9.0" => "17.04.2018 control panel & PTZcontrol weblink device for PTZ cams ",
"3.8.4" => "06.04.2018 Internal MODEL changed to SVS or \"CamVendor - CamModel\" for Cams ",
"3.8.3" => "05.04.2018 bugfix V3.8.2, \$OpMode \"Start\" changed, composegallery changed ",
"3.8.2" => "04.04.2018 \$attr replaced by AttrVal, SSCam_wdpollcaminfo redesigned ",
"3.8.1" => "04.04.2018 some codereview like new sub SSCam_jboolmap ",
"3.8.0" => "03.04.2018 new reading PresetHome, setHome command, minor fixes ",
"3.7.0" => "26.03.2018 minor details of setPreset changed, new command delPreset ",
"3.6.0" => "25.03.2018 setPreset command, changed SSCam_wdpollcaminfo, SSCam_getcaminfoall ",
"3.5.0" => "22.03.2018 new get command listPresets ",
"3.4.0" => "21.03.2018 new commands startTracking, stopTracking ",
"3.3.1" => "20.03.2018 new readings CapPTZObjTracking, CapPTZPresetNumber ",
"3.3.0" => "25.02.2018 code review, API bug fix of runview lastrec, commandref revised (forum:#84953) ",
"1.0.0" => "12.12.2015 initial, changed completly to HttpUtils_NonblockingGet "
);
# Versions History extern
our %SSCam_vNotesExtern = (
"7.7.0" => "07.12.2018 autocreateCams command added in SVS device. BY this command all cameras installed in SVS can be defined automatically. ",
"7.6.0" => "02.12.2018 The PTZ panel is completed by \"Preset\" and \"Patrol\" (only for PTZ cameras) ",
"7.5.0" => "02.12.2018 A click on suitable content in a stream- or snapgallery device opens a popup window. ".
"The popup size can be adjusted by attribute \"popupWindowSize\". ",
"7.4.0" => "20.11.2018 new command \"createReadingsGroup\". By this command a ReadingsGroup with a name of your choice (or use the default name) can be created. ".
"Procedure changes of taking snapshots avoid inaccuracies if camera names in SVS very similar. ",
"7.3.2" => "12.11.2018 fix Warning if 'livestreamprefix' is set to DEF, COMPATIBILITY set to 8.2.2 ",
"7.3.0" => "28.10.2018 In attribute \"livestreamprefix\" can now \"DEF\" be specified to overwrite livestream address by specification from device definition ",
"7.2.1" => "23.10.2018 COMPATIBILITY changed to 8.2.1 ",
"7.2.0" => "20.10.2018 direct help for attributes, new get versionNotes command, please see commandref for details ",
"7.1.1" => "18.10.2018 Message of \"current/simulated SVS-version...\" changed, commandref corrected ",
"7.1.0" => "02.09.2018 PIR Sensor enable/disable, SSCam_Set/SSCam_Get optimized ",
"7.0.1" => "27.08.2018 enable/disable issue (https://forum.fhem.de/index.php/topic,45671.msg830869.html#msg830869) ",
"7.0.0" => "27.07.2018 compatibility to API v2.8 ",
"6.0.1" => "04.07.2018 Reading CamFirmware ",
"6.0.0" => "03.07.2018 HTTPS Support, buttons for refresh SSCamSTRM-devices ",
"5.2.7" => "26.06.2018 fix state turns to \"off\" even though cam is disabled ",
"5.2.5" => "18.06.2018 trigger lastsnap_fw to SSCamSTRM-Device only if snap was done by it. ",
"5.2.4" => "17.06.2018 SSCam_composegallery added and write warning if old composegallery-weblink device is used ",
"5.2.2" => "16.06.2018 compatibility to SSCamSTRM V 1.1.0 ",
"5.2.1" => "14.06.2018 design change of SSCam_StreamDev, change in event generation for SSCam_StreamDev, fix global vars ",
"5.2.0" => "14.06.2018 support longpoll refresh of SSCamSTRM-Devices ",
"5.1.0" => "13.06.2018 more control elements (Start/Stop Recording, Take Snapshot) in func SSCam_StreamDev, control of detaillink is moved to SSCamSTRM-device ",
"5.0.1" => "12.06.2018 control of page refresh improved (for e.g. Floorplan,Dashboard) ",
"4.2.0" => "22.05.2018 PTZ-Panel integrated to created StreamDevice ",
"4.0.0" => "01.05.2018 AudioStream possibility added ",
"3.10.0" => "24.04.2018 createStreamDev added, new features lastrec_fw_MJPEG, lastrec_fw_MPEG4/H.264 added to playback MPEG4/H.264 videos ",
"3.9.1" => "20.04.2018 Attribute ptzPanel_use, initial webcommands in DeviceOverview changed, minor fixes ptzPanel ",
"3.9.0" => "17.04.2018 control panel & PTZcontrol weblink device for PTZ cams ",
"3.8.4" => "06.04.2018 Internal MODEL changed to SVS or \"CamVendor - CamModel\" for Cams ",
"3.8.3" => "05.04.2018 bugfix V3.8.2, \$OpMode \"Start\" changed, composegallery changed ",
"3.6.0" => "25.03.2018 setPreset command ",
"3.5.0" => "22.03.2018 new get command listPresets ",
"3.4.0" => "21.03.2018 new commands startTracking, stopTracking ",
"3.3.1" => "20.03.2018 new readings CapPTZObjTracking, CapPTZPresetNumber ",
"3.3.0" => "25.02.2018 code review, API bug fix of runview lastrec, commandref revised (forum:#84953) ",
"3.2.4" => "18.11.2017 fix bug don't retrieve SSCam_getptzlistpreset if cam is disabled ",
"3.2.3" => "08.10.2017 set optimizeParams, get caminfo (simple), minor bugfix, commandref revised ",
"3.2.0" => "27.09.2017 new command get listLog, change to \$hash->{HELPER}{\".SNAPHASH\"} for avoid huge \"list\"-report ",
"3.1.0" => "26.09.2017 move extevent from CAM to SVS model, Reading PollState enhanced for CAM-Model, minor fixes ",
"3.0.0" => "23.09.2017 Internal MODEL SVS or CAM -> distinguish/support Cams and SVS in different devices new comand get storedCredentials, commandref revised ",
"2.9.0" => "20.09.2017 new function get homeModeState, minor fixes at simu_SVSversion, commandref revised ",
"2.6.0" => "06.08.2017 new command createSnapGallery ",
"2.5.4" => "05.08.2017 analyze \$hash->{CL} in SetFn bzw. GetFn, set snapGallery only if snapGalleryBoost=1 is set, some snapGallery improvements and fixes ",
"2.5.3" => "02.08.2017 implement snapGallery as set-command ",
"2.2.2" => "11.06.2017 bugfix SSCam_login, SSCam_login_return, Forum: https://forum.fhem.de/index.php/topic,45671.msg646701.html#msg646701 ",
"1.39.0" => "20.01.2017 compatibility to SVS 8.0.0, Version in Internals, execute SSCam_getsvsinfo after set credentials ",
"1.37.0" => "10.10.2016 bugfix Experimental keys on scalar is now forbidden (Perl >= 5.23) (Forum: #msg501709) ",
"1.34.0" => "15.09.2016 simu_SVSversion changed, added 407 errorcode message, external recording changed for SVS 7.2 ",
"1.33.0" => "21.08.2016 function get stmUrlPath added, fit to new commandref style, attribute showStmInfoFull added ",
"1.31.0" => "15.08.2016 Attr \"noQuotesForSID\" added, avoid possible 402 - permission denied problems in some SVS/DS-combinations ",
"1.28.0" => "30.06.2016 Attr \"showPassInLog\" added, per default no password will be shown in log ",
"1.27.0" => "29.06.2016 Attr \"simu_SVSversion\" added, sub login_nonbl changed, sub camret_nonbl changed (getlistptzpreset) due to 7.2 problem ",
"1.26.2" => "05.05.2016 change: get \"snapfileinfo\" will get back an Infomessage if Reading \"LastSnapId\" isn't available ",
"1.26.1" => "27.04.2016 bugfix module will not load due to Unknown warnings category 'experimental' when using an older perl version ",
"1.26.0" => "22.04.2016 Attribute \"disable\" to deactivate the module added ",
"1.25.0" => "18.04.2016 motion detection parameters can be entered if motion detection by camera or SVS is used ",
"1.24.0" => "16.04.2016 behavior of \"set ... on\" changed, Attr \"recextend\" added, bugfix: setstate-warning if FHEM will restarted and SVS is not reachable (Forum: #308) ",
"1.22.0" => "27.03.2016 bugfix \"link_open\" doesn't work after last update ",
"1.21.0" => "23.03.2016 added \"lastrec\", \"lastrec_open\" to playback last recording ",
"1.20.0" => "09.03.2016 command \"extevent\" added ",
"1.19.3" => "07.03.2016 bugfix \"uninitialized value \$lastrecstarttime\", \"uninitialized value \$lastrecstoptime\", new attribute \"videofolderMap\" ",
"1.19.2" => "06.03.2016 Reading \"CamLastRec\" added which contains Path/name of last recording ",
"1.19.1" => "28.02.2016 enhanced command runView by option \"link_open\" to open a streamlink immediately ",
"1.19.0" => "25.02.2016 functions for cam-livestream added ",
"1.18.1" => "21.02.2016 fixed a problem that the state is \"disable\" instead of \"disabled\" if a camera is disabled and FHEM will be restarted ",
"1.18.0" => "20.02.2016 function \"get ... eventlist\" added, Reading \"CamEventNum\" added which containes total number of camera events, change usage of reading \"LastUpdateTime\" ",
"1.17.0" => "19.02.2016 function \"runPatrol\" added that starts predefined patrols of PTZ-cameras, Reading \"CamDetMotSc\" added ",
"1.16.0" => "16.02.2016 set up of motion detection source now possible ",
"1.15.0" => "15.02.2016 control of exposure mode day, night & auto is possible now ",
"1.14.0" => "14.02.2016 The port in DEF-String is optional now, if not given, default port 5000 is used ",
"1.13.2" => "13.02.2016 fixed a problem that manual updates using \"getcaminfoall\" are leading to additional pollingloops if polling is used, attribute \"debugactivetoken\" added for debugging-use ",
"1.13.1" => "12.02.2016 fixed a problem that a usersession won't be destroyed if a function couldn't be executed successfully ",
"1.12.0" => "08.02.2016 added function \"move\" for continuous PTZ action ",
"1.11.0" => "05.02.2016 added function \"goPreset\" and \"goAbsPTZ\" to control the move of PTZ lense to absolute positions (http://forum.fhem.de/index.php/topic,45671.msg404275.html#msg404275), (http://forum.fhem.de/index.php/topic,45671.msg404892.html#msg404892) ",
"1.10.0" => "02.02.2016 added function \"svsinfo\" to get informations about installed SVS-package, if Availability = \"disconnected\" then \"state\"-value will be \"disconnected\" too, saved Credentials were deleted from file if a device will be deleted ",
"1.7.0" => "18.01.2016 Attribute \"httptimeout\" added ",
"1.6.0" => "16.01.2016 Change the define-string related to rectime. (http://forum.fhem.de/index.php/topic,45671.msg391664.html#msg391664) ",
"1.5.1" => "11.01.2016 Vars \"USERNAME\" and \"RECTIME\" removed from internals, Var (Internals) \"SERVERNAME\" changed to \"SERVERADDR\" ",
"1.5.0" => "04.01.2016 Function \"Get\" for creating Camera-Readings integrated, Attributs pollcaminfoall, pollnologging added, Function for Polling Cam-Infos added. ",
"1.4.0" => "23.12.2015 function \"enable\" and \"disable\" for SS-Cams added, changed timout of Http-calls to a higher value ",
"1.3.0" => "19.12.2015 function \"snap\" for taking snapshots added, fixed a bug that functions may impact each other ",
"1.0.0" => "12.12.2015 initial, changed completly to HttpUtils_NonblockingGet "
);
# Hint Hash en
our %SSCam_vHintsExt_en = (
"6" => "There are some Icons in directory www/images/sscam available for SSCam. Thereby the system can use the icons please do: ".
"- in FHEMWEB device attribute iconPath complete with \"sscam\", e.g.: attr WEB iconPath default:fhemSVG:openautomation:sscam ".
"After that execute \"rereadicons\" or restart FHEM. ",
"5" => "Find more Informations about manage users and the appropriate privilege profiles in ".
"Surveillance Station online help ",
"4" => "The message Meldung \"WARNING - The current/simulated SVS-version ... may be incompatible with SSCam version...\" means that ".
"the used SSCam version was currently not tested with the installed version of Synology Surveillance Station (Reading \"SVSversion\"). ".
"The compatible SVS-Version is printed out in the Internal COMPATIBILITY.\n".
"Actions: At first please update your SSCam version. If the message does appear furthermore, please inform the SSCam Maintainer. ".
"To ignore this message temporary, you may reduce the verbose level of your SSCam device. ",
"3" => "Link to SSCam english commandRef ",
"2" => "You can create own PTZ-control icons with a template available in SVN which can be downloaded here: contrib/sscam/black_btn_CAM_Template.pdn.\n".
"This template can be edited with Paint.Net for example. ",
"1" => "Some helpful FHEM-Wiki notes"
);
# Hint Hash de
our %SSCam_vHintsExt_de = (
"6" => "Für SSCam wird ein Satz Icons im Verzeichnis www/images/sscam zur Verfügung gestellt. Damit das System sie findet bitte setzen: ".
"- im FHEMWEB Device Attribut iconPath um \"sscam\" ergänzen, z.B.: attr WEB iconPath default:fhemSVG:openautomation:sscam ".
"Danach ein \"rereadicons\" bzw. einen FHEM restart ausführen. ",
"5" => "Informationen zum Management von Usern und entsprechenden Rechte-Profilen sind in der ".
"Surveillance Station Online-Hilfe zu finden.",
"4" => "Die Meldung \"WARNING - The current/simulated SVS-version ... may be incompatible with SSCam version...\" ist ein Hinweis darauf, dass ".
"die eingesetzte SSCam Version noch nicht mit der verwendeten Version von Synology Surveillance Station (Reading \"SVSversion\") getestet ".
"wurde. Die kompatible SVS-Version ist im Internal COMPATIBILITY ersichtlich.\n".
"Maßnahmen: Bitte SSCam zunächst updaten. Sollte die Meldung weiterhin auftreten, bitte den SSCam Maintainer informieren. Zur ".
"vorübergehenden Ignorierung kann der verbose Level des SSCam-Devices entsprechend reduziert werden. ",
"3" => "Link zur deutschen SSCam commandRef ",
"2" => "Zur Erstellung eigener PTZ-Steuericons gibt es eine Vorlage im SVN die hier contrib/sscam/black_btn_CAM_Template.pdn heruntergeladen werden kann.\n".
"Diese Vorlage kann zum Beispiel mit Paint.Net bearbeitet werden. ",
"1" => "Hilfreiche Hinweise zu SSCam im FHEM-Wiki"
);
# getestete SVS-Version
my $compstat = "8.2";
# Aufbau Errorcode-Hashes (siehe Surveillance Station Web API)
my %SSCam_errauthlist = (
100 => "Unknown error",
101 => "The account parameter is not specified",
102 => "API does not exist",
400 => "Invalid user or password",
401 => "Guest or disabled account",
402 => "Permission denied - DSM-Session: make sure user is member of Admin-group, SVS-Session: make sure SVS package is started, make sure FHEM-Server IP won't be blocked in DSM automated blocking list",
403 => "One time password not specified",
404 => "One time password authenticate failed",
405 => "method not allowd - maybe the password is too long",
406 => "OTP code enforced",
407 => "Max Tries (if auto blocking is set to true) - make sure FHEM-Server IP won't be blocked in DSM automated blocking list",
408 => "Password Expired Can not Change",
409 => "Password Expired",
410 => "Password must change (when first time use or after reset password by admin)",
411 => "Account Locked (when account max try exceed)",
);
my %SSCam_errlist = (
100 => "Unknown error",
101 => "Invalid parameters",
102 => "API does not exist",
103 => "Method does not exist",
104 => "This API version is not supported",
105 => "Insufficient user privilege",
106 => "Connection time out",
107 => "Multiple login detected",
117 => "need manager rights in SurveillanceStation for operation",
400 => "Execution failed",
401 => "Parameter invalid",
402 => "Camera disabled",
403 => "Insufficient license",
404 => "Codec activation failed",
405 => "CMS server connection failed",
407 => "CMS closed",
410 => "Service is not enabled",
412 => "Need to add license",
413 => "Reach the maximum of platform",
414 => "Some events not exist",
415 => "message connect failed",
417 => "Test Connection Error",
418 => "Object is not exist",
419 => "Visualstation name repetition",
439 => "Too many items selected",
502 => "Camera disconnected",
600 => "Presetname and PresetID not found in Hash",
);
# Standardvariablen
my $SSCam_slim = 3; # default Anzahl der abzurufenden Schnappschüsse mit snapGallery
my $SSCAM_snum = "1,2,3,4,5,6,7,8,9,10"; # mögliche Anzahl der abzurufenden Schnappschüsse mit snapGallery
use vars qw($FW_ME); # webname (default is fhem), used by 97_GROUP/weblink
use vars qw($FW_subdir); # Sub-path in URL, used by FLOORPLAN/weblink
use vars qw($FW_room); # currently selected room
use vars qw($FW_detail); # currently selected device for detail view
use vars qw($FW_wname); # Web instance
sub FW_pH(@); # add href
sub SSCam_Initialize($) {
my ($hash) = @_;
$hash->{DefFn} = "SSCam_Define";
$hash->{UndefFn} = "SSCam_Undef";
$hash->{DeleteFn} = "SSCam_Delete";
$hash->{SetFn} = "SSCam_Set";
$hash->{GetFn} = "SSCam_Get";
$hash->{AttrFn} = "SSCam_Attr";
# Aufrufe aus FHEMWEB
$hash->{FW_summaryFn} = "SSCam_FWsummaryFn";
$hash->{FW_detailFn} = "SSCam_FWdetailFn";
$hash->{FW_deviceOverview} = 1;
$hash->{AttrList} =
"disable:1,0 ".
"genericStrmHtmlTag ".
"httptimeout ".
"htmlattr ".
"livestreamprefix ".
"loginRetries:1,2,3,4,5,6,7,8,9,10 ".
"videofolderMap ".
"pollcaminfoall ".
"snapGalleryBoost:0,1 ".
"snapGallerySize:Icon,Full ".
"snapGalleryNumber:$SSCAM_snum ".
"snapGalleryColumns ".
"snapGalleryHtmlAttr ".
"pollnologging:1,0 ".
"debugactivetoken:1,0 ".
"rectime ".
"recextend:1,0 ".
"noQuotesForSID:1,0 ".
"session:SurveillanceStation,DSM ".
"showPassInLog:1,0 ".
"showStmInfoFull:1,0 ".
"simu_SVSversion:7.2-xxxx,7.1-xxxx,8.0.0-xxxx,8.1.5-xxxx,8.2.0-xxxx ".
"webCmd ".
$readingFnAttributes;
return undef;
}
################################################################
sub SSCam_Define($@) {
# Die Define-Funktion eines Moduls wird von Fhem aufgerufen wenn der Define-Befehl für ein Gerät ausgeführt wird
# Welche und wie viele Parameter akzeptiert werden ist Sache dieser Funktion. Die Werte werden nach dem übergebenen Hash in ein Array aufgeteilt
# define CamCP1 SSCAM Carport 192.168.2.20 [5000]
# ($hash) [1] [2] [3] [4]
#
my ($hash, $def) = @_;
my $name = $hash->{NAME};
return "Error: Perl module ".$SScamMMDBI." is missing. Install it on Debian with: sudo apt-get install libjson-perl" if($SScamMMDBI);
my @a = split("[ \t][ \t]*", $def);
if(int(@a) < 4) {
return "You need to specify more parameters.\n". "Format: define SSCAM [Port]";
}
my $camname = $a[2];
my $serveraddr = $a[3];
my $serverport = $a[4] ? $a[4] : 5000;
my $proto = $a[5] ? lc($a[5]) : "http";
$hash->{SERVERADDR} = $serveraddr;
$hash->{SERVERPORT} = $serverport;
$hash->{CAMNAME} = $camname;
$hash->{VERSION} = (reverse sort(keys %SSCam_vNotesIntern))[0];
$hash->{MODEL} = ($camname =~ m/^SVS$/i)?"SVS":"CAM"; # initial, CAM wird später ersetzt durch CamModel
$hash->{PROTOCOL} = $proto;
$hash->{COMPATIBILITY} = $compstat; # getestete SVS-version Kompatibilität
# benötigte API's in $hash einfügen
$hash->{HELPER}{APIINFO} = "SYNO.API.Info"; # Info-Seite für alle API's, einzige statische Seite !
$hash->{HELPER}{APIAUTH} = "SYNO.API.Auth"; # API used to perform session login and logout
$hash->{HELPER}{APISVSINFO} = "SYNO.SurveillanceStation.Info";
$hash->{HELPER}{APIEVENT} = "SYNO.SurveillanceStation.Event";
$hash->{HELPER}{APIEXTREC} = "SYNO.SurveillanceStation.ExternalRecording";
$hash->{HELPER}{APIEXTEVT} = "SYNO.SurveillanceStation.ExternalEvent";
$hash->{HELPER}{APICAM} = "SYNO.SurveillanceStation.Camera"; # stark geändert ab API v2.8
$hash->{HELPER}{APISNAPSHOT} = "SYNO.SurveillanceStation.SnapShot";
$hash->{HELPER}{APIPTZ} = "SYNO.SurveillanceStation.PTZ";
$hash->{HELPER}{APIPRESET} = "SYNO.SurveillanceStation.PTZ.Preset";
$hash->{HELPER}{APICAMEVENT} = "SYNO.SurveillanceStation.Camera.Event";
$hash->{HELPER}{APIVIDEOSTM} = "SYNO.SurveillanceStation.VideoStreaming"; # verwendet in Response von "SYNO.SurveillanceStation.Camera: GetLiveViewPath" -> StreamKey-Methode
# $hash->{HELPER}{APISTM} = "SYNO.SurveillanceStation.Streaming"; # provides methods to get Live View or Event video stream, removed in API v2.8
$hash->{HELPER}{APISTM} = "SYNO.SurveillanceStation.Stream"; # Beschreibung ist falsch und entspricht "SYNO.SurveillanceStation.Streaming" auch noch ab v2.8
$hash->{HELPER}{APIHM} = "SYNO.SurveillanceStation.HomeMode";
$hash->{HELPER}{APILOG} = "SYNO.SurveillanceStation.Log";
$hash->{HELPER}{APIAUDIOSTM} = "SYNO.SurveillanceStation.AudioStream"; # Audiostream mit SID, removed in API v2.8
$hash->{HELPER}{APIVIDEOSTMS} = "SYNO.SurveillanceStation.VideoStream"; # Videostream mit SID, removed in API v2.8
# Startwerte setzen
if(SSCam_IsModelCam($hash)) {
$attr{$name}{webCmd} = "on:off:snap:enable:disable:runView:stopView"; # initiale Webkommandos setzen
} else {
$attr{$name}{webCmd} = "homeMode";
$attr{$name}{webCmdLabel} = "HomeMode";
}
$hash->{HELPER}{ACTIVE} = "off"; # Funktionstoken "off", Funktionen können sofort starten
$hash->{HELPER}{OLDVALPOLLNOLOGGING} = "0"; # Loggingfunktion für Polling ist an
$hash->{HELPER}{OLDVALPOLL} = "0";
$hash->{HELPER}{RECTIME_DEF} = "15"; # Standard für rectime setzen, überschreibbar durch Attribut "rectime" bzw. beim "set .. on-for-time"
$hash->{HELPER}{OLDPTZHOME} = "";
$hash->{".ptzhtml"} = "";
$hash->{HELPER}{HLSSTREAM} = "inactive"; # Aktivitätsstatus HLS-Streaming
$hash->{HELPER}{SNAPLIMIT} = 0; # abgerufene Anzahl Snaps
$hash->{HELPER}{TOTALCNT} = 0; # totale Anzahl Snaps
readingsBeginUpdate($hash);
readingsBulkUpdate($hash,"PollState","Inactive"); # es ist keine Gerätepolling aktiv
if(SSCam_IsModelCam($hash)) {
readingsBulkUpdate($hash,"Availability", "???"); # Verfügbarkeit ist unbekannt
readingsBulkUpdate($hash,"state", "off"); # Init für "state" , Problemlösung für setstate, Forum #308
} else {
readingsBulkUpdate($hash,"state", "Initialized"); # Init für "state" wenn SVS
}
readingsEndUpdate($hash,1);
SSCam_getcredentials($hash,1); # Credentials lesen und in RAM laden ($boot=1)
# initiale Routinen nach Restart ausführen , verzögerter zufälliger Start
RemoveInternalTimer($hash, "SSCam_initonboot");
InternalTimer(gettimeofday()+int(rand(30)), "SSCam_initonboot", $hash, 0);
return undef;
}
################################################################
sub SSCam_Undef($$) {
my ($hash, $arg) = @_;
SSCam_logout($hash);
RemoveInternalTimer($hash);
return undef;
}
################################################################
sub SSCam_Delete($$) {
my ($hash, $arg) = @_;
my $index = $hash->{TYPE}."_".$hash->{NAME}."_credentials";
my $name = $hash->{NAME};
# gespeicherte Credentials löschen
setKeyValue($index, undef);
# löschen snapGallerie-Device falls vorhanden
my $sgdev = "SSCam.$hash->{NAME}.snapgallery";
CommandDelete($hash->{CL},"$sgdev");
# alle Streaming-Devices löschen falls vorhanden
CommandDelete($hash->{CL},"TYPE=SSCamSTRM:FILTER=PARENT=$name");
return undef;
}
################################################################
sub SSCam_Attr($$$$) {
my ($cmd,$name,$aName,$aVal) = @_;
my $hash = $defs{$name};
my ($do,$val);
# $cmd can be "del" or "set"
# $name is device name
# aName and aVal are Attribute name and value
# dynamisch PTZ-Attribute setzen (wichtig beim Start wenn Reading "DeviceType" nicht gesetzt ist)
if ($cmd eq "set" && ($aName =~ m/ptzPanel_.*/)) {
foreach my $n (0..9) {
$n = sprintf("%2.2d",$n);
addToDevAttrList($name, "ptzPanel_row$n");
}
addToDevAttrList($name, "ptzPanel_iconPrefix");
addToDevAttrList($name, "ptzPanel_iconPath");
}
if($aName =~ m/ptzPanel_row.*|ptzPanel_Home|ptzPanel_use/) {
InternalTimer(gettimeofday()+0.7, "SSCam_addptzattr", "$name", 0);
}
if ($aName eq "disable") {
if($cmd eq "set") {
$do = ($aVal) ? 1 : 0;
}
$do = 0 if($cmd eq "del");
if(SSCam_IsModelCam($hash)) {
$val = ($do == 1 ? "inactive" : "off");
} else {
$val = ($do == 1 ? "disabled" : "initialized");
}
readingsSingleUpdate($hash, "state", $val, 1);
readingsSingleUpdate($hash, "PollState", "Inactive", 1) if($do == 1);
readingsSingleUpdate($hash, "Availability", "???", 1) if($do == 1 && SSCam_IsModelCam($hash));
}
if ($aName eq "showStmInfoFull") {
if($cmd eq "set") {
$do = ($aVal) ? 1 : 0;
}
$do = 0 if($cmd eq "del");
if ($do == 0) {
delete($defs{$name}{READINGS}{StmKeymjpegHttp});
delete($defs{$name}{READINGS}{LiveStreamUrl});
delete($defs{$name}{READINGS}{StmKeyUnicst});
delete($defs{$name}{READINGS}{StmKeyUnicstOverHttp});
delete($defs{$name}{READINGS}{StmKeymxpegHttp});
}
}
if ($aName eq "snapGallerySize") {
if($cmd eq "set") {
$do = ($aVal eq "Icon")?1:2;
}
$do = 0 if($cmd eq "del");
if ($do == 0) {
delete($hash->{HELPER}{".SNAPHASH"}) if(AttrVal($name,"snapGalleryBoost",0)); # Snaphash nur löschen wenn Snaps gepollt werden
Log3($name, 4, "$name - Snapshot hash deleted");
} elsif (AttrVal($name,"snapGalleryBoost",0)) {
# snap-Infos abhängig ermitteln wenn gepollt werden soll
my ($slim,$ssize);
$hash->{HELPER}{GETSNAPGALLERY} = 1;
$slim = AttrVal($name,"snapGalleryNumber",$SSCam_slim); # Anzahl der abzurufenden Snaps
$ssize = $do;
RemoveInternalTimer("SSCam_getsnapinfo");
InternalTimer(gettimeofday()+0.7, "SSCam_getsnapinfo", "$name:$slim:$ssize", 0);
}
}
if ($aName eq "snapGalleryBoost") {
if($cmd eq "set") {
$do = ($aVal == 1)?1:0;
}
$do = 0 if($cmd eq "del");
if ($do == 0) {
delete($hash->{HELPER}{".SNAPHASH"}); # Snaphash löschen
Log3($name, 4, "$name - Snapshot hash deleted");
} else {
# snapgallery regelmäßig neu einlesen wenn Polling ein
return "When you want activate \"snapGalleryBoost\", you have to set the attribute \"pollcaminfoall\" first because the functionality depends on retrieving snapshots periodical."
if(!AttrVal($name,"pollcaminfoall",0));
my ($slim,$ssize);
$hash->{HELPER}{GETSNAPGALLERY} = 1;
$slim = AttrVal($name,"snapGalleryNumber",$SSCam_slim); # Anzahl der abzurufenden Snaps
my $sg = AttrVal($name,"snapGallerySize","Icon"); # Auflösung Image
$ssize = ($sg eq "Icon")?1:2;
RemoveInternalTimer("SSCam_getsnapinfo");
InternalTimer(gettimeofday()+0.7, "SSCam_getsnapinfo", "$name:$slim:$ssize", 0);
}
}
if ($aName eq "snapGalleryNumber" && AttrVal($name,"snapGalleryBoost",0)) {
my ($slim,$ssize);
if($cmd eq "set") {
$do = ($aVal != 0)?1:0;
}
$do = 0 if($cmd eq "del");
if ($do == 0) {
$slim = 3;
} else {
$slim = $aVal;
}
$hash->{HELPER}{GETSNAPGALLERY} = 1;
my $sg = AttrVal($name,"snapGallerySize","Icon"); # Auflösung Image
$ssize = ($sg eq "Icon")?1:2;
RemoveInternalTimer("SSCam_getsnapinfo");
InternalTimer(gettimeofday()+0.7, "SSCam_getsnapinfo", "$name:$slim:$ssize", 0);
}
if ($aName eq "simu_SVSversion") {
delete $hash->{HELPER}{APIPARSET};
delete $hash->{HELPER}{SID};
delete $hash->{CAMID};
RemoveInternalTimer($hash, "SSCam_getcaminfoall");
InternalTimer(gettimeofday()+0.5, "SSCam_getcaminfoall", $hash, 0);
}
if($aName =~ m/pollcaminfoall/ && $init_done == 1) {
RemoveInternalTimer($hash, "SSCam_getcaminfoall");
InternalTimer(gettimeofday()+1.0, "SSCam_getcaminfoall", $hash, 0);
RemoveInternalTimer($hash, "SSCam_wdpollcaminfo");
InternalTimer(gettimeofday()+1.5, "SSCam_wdpollcaminfo", $hash, 0);
}
if($aName =~ m/pollnologging/ && $init_done == 1) {
RemoveInternalTimer($hash, "SSCam_wdpollcaminfo");
InternalTimer(gettimeofday()+1.0, "SSCam_wdpollcaminfo", $hash, 0);
}
if ($cmd eq "set") {
if ($aName =~ m/httptimeout|snapGalleryColumns|rectime|pollcaminfoall/) {
unless ($aVal =~ /^\d+$/) { return " The Value for $aName is not valid. Use only figures 1-9 !";}
}
if($aName =~ m/pollcaminfoall/) {
return "The value of \"$aName\" has to be greater than 10 seconds." if($aVal <= 10);
}
}
if ($cmd eq "del") {
if ($aName =~ m/pollcaminfoall/ ) {
# Polling nicht ausschalten wenn snapGalleryBoost ein (regelmäßig neu einlesen)
return "Please switch off \"snapGalleryBoost\" first if you want to deactivate \"pollcaminfoall\" because the functionality of \"snapGalleryBoost\" depends on retrieving snapshots periodical."
if(AttrVal($name,"snapGalleryBoost",0));
}
}
return undef;
}
################################################################
sub SSCam_Set($@) {
my ($hash, @a) = @_;
return "\"set X\" needs at least an argument" if ( @a < 2 );
my $name = $a[0];
my $opt = $a[1];
my $prop = $a[2];
my $prop1 = $a[3];
my $prop2 = $a[4];
my $prop3 = $a[5];
my $camname = $hash->{CAMNAME};
my $success;
my $setlist;
my @prop;
return if(IsDisabled($name));
if(!$hash->{CREDENTIALS}) {
# initiale setlist für neue Devices
$setlist = "Unknown argument $opt, choose one of ".
"credentials "
;
} elsif(SSCam_IsModelCam($hash)) {
# selist für Cams
my $hlslfw = SSCam_IsHLSCap($hash)?",live_fw_hls,":",";
$setlist = "Unknown argument $opt, choose one of ".
"credentials ".
((ReadingsVal("$name", "CapPTZPan", "false") ne "false") ? "delPreset:".ReadingsVal("$name","Presets","")." " : "").
"expmode:auto,day,night ".
"on ".
"off:noArg ".
"motdetsc:disable,camera,SVS ".
"snap:noArg ".
(AttrVal($name, "snapGalleryBoost",0)?(AttrVal($name,"snapGalleryNumber",undef) || AttrVal($name,"snapGalleryBoost",0))?"snapGallery:noArg ":"snapGallery:$SSCAM_snum ":" ").
"createSnapGallery:noArg ".
"createStreamDev:generic,mjpeg,switched ".
((ReadingsVal("$name", "CapPTZPan", "false") ne "false") ? "createPTZcontrol:noArg ": "").
"enable:noArg ".
"disable:noArg ".
"optimizeParams ".
((ReadingsVal("$name", "CapPIR", "false") ne "false") ? "pirSensor:activate,deactivate ": "").
"createReadingsGroup ".
"runView:live_fw".$hlslfw."live_link,live_open,lastrec_fw,lastrec_fw_MJPEG,lastrec_fw_MPEG4/H.264,lastrec_open,lastsnap_fw ".
((ReadingsVal("$name", "CapPTZPan", "false") ne "false") ? "setPreset ": "").
((ReadingsVal("$name", "CapPTZPan", "false") ne "false") ? "setHome:---currentPosition---,".ReadingsVal("$name","Presets","")." " : "").
"stopView:noArg ".
((ReadingsVal("$name", "CapPTZObjTracking", "false") ne "false") ? "startTracking:noArg " : "").
((ReadingsVal("$name", "CapPTZObjTracking", "false") ne "false") ? "stopTracking:noArg " : "").
((ReadingsVal("$name", "CapPTZDirections", 0) > 0) ? "move"." " : "").
((ReadingsVal("$name", "CapPTZPan", "false") ne "false") ? "runPatrol:".ReadingsVal("$name", "Patrols", "")." " : "").
((ReadingsVal("$name", "CapPTZPan", "false") ne "false") ? "goPreset:".ReadingsVal("$name", "Presets", "")." " : "").
((ReadingsVal("$name", "CapPTZAbs", "false") ne "false") ? "goAbsPTZ"." " : "").
((ReadingsVal("$name", "CapPTZDirections", 0) > 0) ? "move"." " : "");
} else {
# setlist für SVS Devices
$setlist = "Unknown argument $opt, choose one of ".
"autocreateCams:noArg ".
"credentials ".
"createReadingsGroup ".
"extevent:1,2,3,4,5,6,7,8,9,10 ".
($hash->{HELPER}{APIHMMAXVER}?"homeMode:on,off ": "");
}
if ($opt eq "credentials") {
return "Credentials are incomplete, use username password" if (!$prop || !$prop1);
return "Password is too long. It is limited up to and including 20 characters." if (length $prop1 > 20);
delete $hash->{HELPER}{SID} if($hash->{HELPER}{SID});
($success) = SSCam_setcredentials($hash,$prop,$prop1);
$hash->{HELPER}{ACTIVE} = "off";
if($success) {
SSCam_getcaminfoall($hash,0);
RemoveInternalTimer($hash, "SSCam_getptzlistpreset");
InternalTimer(gettimeofday()+11, "SSCam_getptzlistpreset", $hash, 0);
RemoveInternalTimer($hash, "SSCam_getptzlistpatrol");
InternalTimer(gettimeofday()+12, "SSCam_getptzlistpatrol", $hash, 0);
SSCam_versionCheck($hash);
return "Username and Password saved successfully";
} else {
return "Error while saving Username / Password - see logfile for details";
}
}
if ($opt eq "on" && SSCam_IsModelCam($hash)) {
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
if (defined($prop)) {
unless ($prop =~ /^\d+$/) { return " The Value for \"$opt\" is not valid. Use only figures 0-9 without decimal places !";}
$hash->{HELPER}{RECTIME_TEMP} = $prop;
}
SSCam_camstartrec($hash);
} elsif ($opt eq "off" && SSCam_IsModelCam($hash)) {
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
SSCam_camstoprec($hash);
} elsif ($opt eq "snap" && SSCam_IsModelCam($hash)) {
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
$hash->{HELPER}{SNAPBYSTRMDEV} = 1 if ($prop); # $prop wird mitgegeben durch Snap by SSCamSTRM-Device
SSCam_camsnap($hash);
} elsif ($opt eq "startTracking" && SSCam_IsModelCam($hash)) {
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
if ($hash->{HELPER}{APIPTZMAXVER} < 5) {return "Function \"$opt\" needs a higher version of Surveillance Station";}
SSCam_starttrack($hash);
} elsif ($opt eq "stopTracking" && SSCam_IsModelCam($hash)) {
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
if ($hash->{HELPER}{APIPTZMAXVER} < 5) {return "Function \"$opt\" needs a higher version of Surveillance Station";}
SSCam_stoptrack($hash);
} elsif ($opt eq "snapGallery" && SSCam_IsModelCam($hash)) {
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
my $ret = SSCam_getclhash($hash);
return $ret if($ret);
if(!AttrVal($name, "snapGalleryBoost",0)) {
# Snaphash ist nicht vorhanden und wird neu abgerufen und ausgegeben
$hash->{HELPER}{GETSNAPGALLERY} = 1;
# snap-Infos für Gallerie abrufen
my ($sg,$slim,$ssize);
$slim = $prop?AttrVal($name,"snapGalleryNumber",$prop):AttrVal($name,"snapGalleryNumber",$SSCam_slim); # Anzahl der abzurufenden Snapshots
$ssize = (AttrVal($name,"snapGallerySize","Icon") eq "Icon")?1:2; # Image Size 1-Icon, 2-Full
SSCam_getsnapinfo("$name:$slim:$ssize");
} else {
# Snaphash ist vorhanden und wird zur Ausgabe aufbereitet (Polling ist aktiv)
my $htmlCode = SSCam_composegallery($name);
for (my $k=1; (defined($hash->{HELPER}{CL}{$k})); $k++ ) {
if ($hash->{HELPER}{CL}{$k}->{COMP}) {
# CL zusammengestellt (Auslösung durch Notify)
asyncOutput($hash->{HELPER}{CL}{$k}, "$htmlCode");
} else {
# Output wurde über FHEMWEB ausgelöst
return $htmlCode;
}
}
delete($hash->{HELPER}{CL});
}
} elsif ($opt eq "createSnapGallery" && SSCam_IsModelCam($hash)) {
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
my ($ret,$sgdev);
return "Before use \"$opt\" you have to set the attribute \"snapGalleryBoost\" first due to the technology of retrieving snapshots automatically is needed."
if(!AttrVal($name,"snapGalleryBoost",0));
$sgdev = "SSCamSTRM.$name.snapgallery";
$ret = CommandDefine($hash->{CL},"$sgdev SSCamSTRM {SSCam_composegallery('$name','$sgdev','snapgallery')}");
return $ret if($ret);
my $room = "SnapGallery";
$attr{$sgdev}{room} = $room;
return "Snapgallery device \"$sgdev\" created and assigned to room \"$room\".";
} elsif ($opt eq "createPTZcontrol" && SSCam_IsModelCam($hash)) {
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
my $ptzcdev = "SSCamSTRM.$name.PTZcontrol";
my $ret = CommandDefine($hash->{CL},"$ptzcdev SSCamSTRM {SSCam_ptzpanel('$name','$ptzcdev','ptzcontrol')}");
return $ret if($ret);
my $room = AttrVal($name,"room","PTZcontrol");
$attr{$ptzcdev}{room} = $room;
$attr{$ptzcdev}{group} = $name."_PTZcontrol";
return "PTZ control device \"$ptzcdev\" created and assigned to room \"$room\".";
} elsif ($opt eq "createStreamDev" && SSCam_IsModelCam($hash)) {
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
my ($livedev,$ret);
if($prop =~ /mjpeg/) {
$livedev = "SSCamSTRM.$name.mjpeg";
$ret = CommandDefine($hash->{CL},"$livedev SSCamSTRM {SSCam_StreamDev('$name','$livedev','mjpeg')}");
return $ret if($ret);
}
if($prop =~ /generic/) {
$livedev = "SSCamSTRM.$name.generic";
$ret = CommandDefine($hash->{CL},"$livedev SSCamSTRM {SSCam_StreamDev('$name','$livedev','generic')}");
return $ret if($ret);
}
if($prop =~ /switched/) {
$livedev = "SSCamSTRM.$name.switched";
$ret = CommandDefine($hash->{CL},"$livedev SSCamSTRM {SSCam_StreamDev('$name','$livedev','switched')}");
return $ret if($ret);
}
my $room = AttrVal($name,"room","Livestream");
$attr{$livedev}{room} = $room;
return "Livestream device \"$livedev\" created and assigned to room \"$room\".";
} elsif ($opt eq "createReadingsGroup") {
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
my $rgdev = $prop?$prop:"RG.SSCam";
my $rgdef = '<%it_camera>,On/Offline>,< >,,< >,erkennung>,< >,,< >,(MB)>,< >,,< >,Modul>,< >,'."\n".
'TYPE=SSCam:FILTER=MODEL!=SVS:Availability,< >,state,< >,!CamMotDetSc,< >,!CamLastRecTime,< >,!UsedSpaceMB,< >,!LastUpdateTime,< >,?!disable,< >,?!LSnap,?!LRec,?!Start,?!Stop'."\n".
'< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >'."\n".
'< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >'."\n".
'< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >'."\n".
'<%it_server>,On/Off>,< >,,< >, >,< >,< >,< >,< >, >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >'."\n".
'TYPE=SSCam:FILTER=MODEL=SVS:HomeModeState,< >,state,< >,< >,< >,< >,< >,< >, >,< >,< >,< >,?!disable,< >,< >,< >,< >,< >'."\n".
'';
my $ret = CommandDefine($hash->{CL},"$rgdev readingsGroup $rgdef");
return $ret if($ret);
my $room = AttrVal($name,"room","SSCam");
CommandAttr($hash->{CL},"$rgdev room $room");
CommandAttr($hash->{CL},"$rgdev alias Überblick Kameras");
my $cellStyle = '{'."\n".
' "c:0" => \'style="text-align:left;font-weight:normal"\','."\n".
' "c:1" => \'style="text-align:left;font-weight:normal"\','."\n".
' "c:4" => \'style="text-align:center;font-weight:bold"\','."\n".
' "c:5" => \'style="text-align:center;color:green;font-weight:normal"\','."\n".
' "c:9" => \'style="text-align:center;font-weight:normal"\''."\n".
'}';
CommandAttr($hash->{CL},"$rgdev cellStyle $cellStyle");
my $commands = '{'."\n".
' "Availability.enabled" => "set $DEVICE disable",'."\n".
' "Availability.disabled" => "set $DEVICE enable",'."\n".
' "HomeModeState.on" => "set $DEVICE homeMode off",'."\n".
' "HomeModeState.off" => "set $DEVICE homeMode on",'."\n".
' "'.$rgdev.'.Start" => "set %DEVICE runView live_fw",'."\n".
' "Start" => "set %DEVICE runView live_fw",'."\n".
' "LRec" => "set %DEVICE runView lastrec_fw",'."\n".
' "LSnap" => "set %DEVICE runView lastsnap_fw",'."\n".
' "Stop" => "set %DEVICE stopView",'."\n".
' "Record" => "runView:",'."\n".
' "disable" => "disable:"'."\n".
'}';
CommandAttr($hash->{CL},"$rgdev commands $commands");
my $nameStyle = 'style = "color:black;font-weight:bold;text-align:center"';
CommandAttr($hash->{CL},"$rgdev nameStyle $nameStyle");
my $valueColumns = '{'."\n".
' \'Wiedergabe\' => \'colspan="4"\''."\n".
'}';
CommandAttr($hash->{CL},"$rgdev valueColumns $valueColumns");
my $valueFormat = '{'."\n".
' ($READING eq "CamMotDetSc" && $VALUE eq "disabled") ? "external" : $VALUE'."\n".
'}';
CommandAttr($hash->{CL},"$rgdev valueFormat $valueFormat");
my $valueIcon = '{'."\n".
' "Availability.enabled" => "remotecontrol/black_btn_GREEN",'."\n".
' "Availability.disabled" => "remotecontrol/black_btn_RED",'."\n".
' "HomeModeState.on" => "status_available",'."\n".
' "HomeModeState.off" => "status_away_1\@orange",'."\n".
' "Start" => "black_btn_MJPEG",'."\n".
' "LRec" => "black_btn_LASTRECIFRAME",'."\n".
' "LSnap" => "black_btn_LSNAP",'."\n".
' "Stop" => "remotecontrol/black_btn_POWEROFF3",'."\n".
' "state.initialized" => "remotecontrol/black_btn_STOP",'."\n".
' "state" => "%devStateIcon"'."\n".
'}';
CommandAttr($hash->{CL},"$rgdev valueIcon $valueIcon");
my $valueStyle = '{'."\n".
' if($READING eq "Availability" && $VALUE eq "enabled"){ \' style="color:green" \' }'."\n".
' elsif( $READING eq "Availability" && $VALUE eq "disabled"){ \' style="color:red" \' }'."\n".
' elsif( $READING eq "CamMotDetSc" && $VALUE =~ /SVS.*/ ){ \' style="color:orange" \' }'."\n".
' elsif( $READING eq "CamMotDetSc" && $VALUE eq "disabled"){ \' style="color:LimeGreen" \' }'."\n".
' elsif( $READING eq "CamMotDetSc" && $VALUE =~ /Cam.*/ ){ \' style="color:SandyBrown" \' }'."\n".
'}';
CommandAttr($hash->{CL},"$rgdev valueStyle $valueStyle");
return "readingsGroup device \"$rgdev\" created and assigned to room \"$room\".";
} elsif ($opt eq "enable" && SSCam_IsModelCam($hash)) {
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
SSCam_camenable($hash);
} elsif ($opt eq "disable" && SSCam_IsModelCam($hash)) {
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
SSCam_camdisable($hash);
} elsif ($opt eq "motdetsc" && SSCam_IsModelCam($hash)) {
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
if (!$prop || $prop !~ /^(disable|camera|SVS)$/) { return " \"$opt\" needs one of those arguments: disable, camera, SVS !";}
$hash->{HELPER}{MOTDETSC} = $prop;
if ($prop1) {
# check ob Zahl zwischen 1 und 99
return "invalid value for sensitivity (SVS or camera) - use number between 1 - 99" if ($prop1 !~ /^([1-9]|[1-9][0-9])*$/);
$hash->{HELPER}{MOTDETSC_PROP1} = $prop1;
}
if ($prop2) {
# check ob Zahl zwischen 1 und 99
return "invalid value for threshold (SVS) / object size (camera) - use number between 1 - 99" if ($prop2 !~ /^([1-9]|[1-9][0-9])*$/);
$hash->{HELPER}{MOTDETSC_PROP2} = $prop2;
}
if ($prop3) {
# check ob Zahl zwischen 1 und 99
return "invalid value for threshold (SVS) / object size (camera) - use number between 1 - 99" if ($prop3 !~ /^([1-9]|[1-9][0-9])*$/);
$hash->{HELPER}{MOTDETSC_PROP3} = $prop3;
}
SSCam_cammotdetsc($hash);
} elsif ($opt eq "expmode" && SSCam_IsModelCam($hash)) {
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
unless ($prop) { return " \"$opt\" needs one of those arguments: auto, day, night !";}
$hash->{HELPER}{EXPMODE} = $prop;
SSCam_camexpmode($hash);
} elsif ($opt eq "homeMode" && !SSCam_IsModelCam($hash)) {
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
unless ($prop) { return " \"$opt\" needs one of those arguments: on, off !";}
$hash->{HELPER}{HOMEMODE} = $prop;
SSCam_sethomemode($hash);
} elsif ($opt eq "autocreateCams" && !SSCam_IsModelCam($hash)) {
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
SSCam_setAutocreate($hash);
} elsif ($opt eq "goPreset" && SSCam_IsModelCam($hash)) {
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
if (!$prop) {return "Function \"goPreset\" needs a \"Presetname\" as an argument";}
$hash->{HELPER}{GOPRESETNAME} = $prop;
$hash->{HELPER}{PTZACTION} = "gopreset";
SSCam_doptzaction($hash);
} elsif ($opt eq "optimizeParams" && SSCam_IsModelCam($hash)) {
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
my %cpcl = (ntp => 1, mirror => 2, flip => 4, rotate => 8);
SSCam_extoptpar($hash,$prop,\%cpcl) if($prop);
SSCam_extoptpar($hash,$prop1,\%cpcl) if($prop1);
SSCam_extoptpar($hash,$prop2,\%cpcl) if($prop2);
SSCam_setoptpar($hash);
} elsif ($opt eq "pirSensor" && SSCam_IsModelCam($hash)) {
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
if(ReadingsVal("$name", "CapPIR", "false") eq "false") {return "Function \"$opt\" not possible. Camera \"$name\" don't have a PIR sensor."}
if(!$prop) {return "Function \"$opt\" needs an argument";}
$hash->{HELPER}{PIRACT} = ($prop eq "activate")?0:($prop eq "deactivate")?-1:5;
if($hash->{HELPER}{PIRACT} == 5) {return " Illegal argument for \"$opt\" detected, use \"activate\" or \"activate\" !";}
SSCam_piract($hash);
} elsif ($opt eq "runPatrol" && SSCam_IsModelCam($hash)) {
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
if (!$prop) {return "Function \"$opt\" needs a \"Patrolname\" as an argument";}
$hash->{HELPER}{GOPATROLNAME} = $prop;
$hash->{HELPER}{PTZACTION} = "runpatrol";
SSCam_doptzaction($hash);
} elsif ($opt eq "goAbsPTZ" && SSCam_IsModelCam($hash)) {
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
if ($prop eq "up" || $prop eq "down" || $prop eq "left" || $prop eq "right") {
if ($prop eq "up") {$hash->{HELPER}{GOPTZPOSX} = 320; $hash->{HELPER}{GOPTZPOSY} = 480;}
if ($prop eq "down") {$hash->{HELPER}{GOPTZPOSX} = 320; $hash->{HELPER}{GOPTZPOSY} = 0;}
if ($prop eq "left") {$hash->{HELPER}{GOPTZPOSX} = 0; $hash->{HELPER}{GOPTZPOSY} = 240;}
if ($prop eq "right") {$hash->{HELPER}{GOPTZPOSX} = 640; $hash->{HELPER}{GOPTZPOSY} = 240;}
$hash->{HELPER}{PTZACTION} = "goabsptz";
SSCam_doptzaction($hash);
return undef;
} else {
if ($prop !~ /\d+/ || $prop1 !~ /\d+/ || abs($prop) > 640 || abs($prop1) > 480) {
return "Function \"goAbsPTZ\" needs two coordinates, posX=0-640 and posY=0-480, as arguments or use up, down, left, right instead";
}
$hash->{HELPER}{GOPTZPOSX} = abs($prop);
$hash->{HELPER}{GOPTZPOSY} = abs($prop1);
$hash->{HELPER}{PTZACTION} = "goabsptz";
SSCam_doptzaction($hash);
return undef;
}
return "Function \"goAbsPTZ\" needs two coordinates, posX=0-640 and posY=0-480, as arguments or use up, down, left, right instead";
} elsif ($opt eq "move" && SSCam_IsModelCam($hash)) {
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
return "PTZ version of Synology API isn't set. Use \"get $name scanVirgin\" first." if(!$hash->{HELPER}{APIPTZMAXVER});
if($hash->{HELPER}{APIPTZMAXVER} <= 4) {
if (!defined($prop) || ($prop !~ /^up$|^down$|^left$|^right$|^dir_\d$/)) {return "Function \"move\" needs an argument like up, down, left, right or dir_X (X = 0 to CapPTZDirections-1)";}
$hash->{HELPER}{GOMOVEDIR} = $prop;
} elsif ($hash->{HELPER}{APIPTZMAXVER} >= 5) {
if (!defined($prop) || ($prop !~ /^right$|^upright$|^up$|^upleft$|^left$|^downleft$|^down$|^downright$/)) {return "Function \"move\" needs an argument like right, upright, up, upleft, left, downleft, down, downright ";}
my %dirs = (
right => 0,
upright => 4,
up => 8,
upleft => 12,
left => 16,
downleft => 20,
down => 24,
downright => 28,
);
$hash->{HELPER}{GOMOVEDIR} = $dirs{$prop};
}
$hash->{HELPER}{GOMOVETIME} = defined($prop1) ? $prop1 : 1;
$hash->{HELPER}{PTZACTION} = "movestart";
SSCam_doptzaction($hash);
} elsif ($opt eq "runView" && SSCam_IsModelCam($hash)) {
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
if ($prop eq "live_open") {
if ($prop1) {$hash->{HELPER}{VIEWOPENROOM} = $prop1;} else {delete $hash->{HELPER}{VIEWOPENROOM};}
$hash->{HELPER}{OPENWINDOW} = 1;
$hash->{HELPER}{WLTYPE} = "link";
$hash->{HELPER}{ALIAS} = "LiveView";
$hash->{HELPER}{RUNVIEW} = "live_open";
$hash->{HELPER}{ACTSTRM} = ""; # sprechender Name des laufenden Streamtyps für SSCamSTRM
} elsif ($prop eq "live_link") {
$hash->{HELPER}{OPENWINDOW} = 0;
$hash->{HELPER}{WLTYPE} = "link";
$hash->{HELPER}{ALIAS} = "LiveView";
$hash->{HELPER}{RUNVIEW} = "live_link";
$hash->{HELPER}{ACTSTRM} = ""; # sprechender Name des laufenden Streamtyps für SSCamSTRM
} elsif ($prop eq "lastrec_open") {
if ($prop1) {$hash->{HELPER}{VIEWOPENROOM} = $prop1;} else {delete $hash->{HELPER}{VIEWOPENROOM};}
$hash->{HELPER}{OPENWINDOW} = 1;
$hash->{HELPER}{WLTYPE} = "link";
$hash->{HELPER}{ALIAS} = "LastRecording";
$hash->{HELPER}{RUNVIEW} = "lastrec_open";
$hash->{HELPER}{ACTSTRM} = ""; # sprechender Name des laufenden Streamtyps für SSCamSTRM
} elsif ($prop eq "lastrec_fw") { # Video in iFrame eingebettet
$hash->{HELPER}{OPENWINDOW} = 0;
$hash->{HELPER}{WLTYPE} = "iframe";
$hash->{HELPER}{ALIAS} = " ";
$hash->{HELPER}{RUNVIEW} = "lastrec";
$hash->{HELPER}{ACTSTRM} = "last Recording"; # sprechender Name des laufenden Streamtyps für SSCamSTRM
} elsif ($prop eq "lastrec_fw_MJPEG") { # “video/avi” – MJPEG format event
$hash->{HELPER}{OPENWINDOW} = 0;
$hash->{HELPER}{WLTYPE} = "image";
$hash->{HELPER}{ALIAS} = " ";
$hash->{HELPER}{RUNVIEW} = "lastrec";
$hash->{HELPER}{ACTSTRM} = "last Recording"; # sprechender Name des laufenden Streamtyps für SSCamSTRM
} elsif ($prop eq "lastrec_fw_MPEG4/H.264") { # “video/mp4” – MPEG4/H.264 format event
$hash->{HELPER}{OPENWINDOW} = 0;
$hash->{HELPER}{WLTYPE} = "video";
$hash->{HELPER}{ALIAS} = " ";
$hash->{HELPER}{RUNVIEW} = "lastrec";
$hash->{HELPER}{ACTSTRM} = "last Recording"; # sprechender Name des laufenden Streamtyps für SSCamSTRM
} elsif ($prop eq "live_fw") {
$hash->{HELPER}{OPENWINDOW} = 0;
$hash->{HELPER}{WLTYPE} = "image";
$hash->{HELPER}{ALIAS} = " ";
$hash->{HELPER}{RUNVIEW} = "live_fw";
$hash->{HELPER}{ACTSTRM} = "MJPEG Livestream"; # sprechender Name des laufenden Streamtyps für SSCamSTRM
} elsif ($prop eq "live_fw_hls") {
return "API \"SYNO.SurveillanceStation.VideoStream\" is not available or Reading \"CamStreamFormat\" is not \"HLS\". May be your API version is 2.8 or higher." if(!SSCam_IsHLSCap($hash));
$hash->{HELPER}{OPENWINDOW} = 0;
$hash->{HELPER}{WLTYPE} = "hls";
$hash->{HELPER}{ALIAS} = "View only on compatible browsers";
$hash->{HELPER}{RUNVIEW} = "live_fw_hls";
$hash->{HELPER}{ACTSTRM} = "HLS Livestream"; # sprechender Name des laufenden Streamtyps für SSCamSTRM
} elsif ($prop eq "lastsnap_fw") {
$hash->{HELPER}{LSNAPBYSTRMDEV} = 1 if($prop1); # Anzeige durch SSCamSTRM-Device ausgelöst
$hash->{HELPER}{LSNAPBYDEV} = 1 if(!$prop1); # Anzeige durch SSCam ausgelöst
$hash->{HELPER}{OPENWINDOW} = 0;
$hash->{HELPER}{WLTYPE} = "base64img";
$hash->{HELPER}{ALIAS} = " ";
$hash->{HELPER}{RUNVIEW} = "lastsnap_fw";
$hash->{HELPER}{ACTSTRM} = "last Snapshot"; # sprechender Name des laufenden Streamtyps für SSCamSTRM
} else {
return "$prop isn't a valid option of runview, use one of live_fw, live_link, live_open, lastrec_fw, lastrec_open, lastsnap_fw";
}
SSCam_runliveview($hash);
} elsif ($opt eq "hlsreactivate" && SSCam_IsModelCam($hash)) {
# ohne SET-Menüeintrag
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
SSCam_hlsreactivate($hash);
} elsif ($opt eq "hlsactivate" && SSCam_IsModelCam($hash)) {
# ohne SET-Menüeintrag
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
SSCam_hlsactivate($hash);
} elsif ($opt eq "refresh" && SSCam_IsModelCam($hash)) {
# ohne SET-Menüeintrag
if($prop =~ /STRM/) {
# Event in allen SSCamSTRM-Devices erzeugen um Contentwiedergabe aufzufrischen
SSCam_refresh($hash,0,0,1); # kein Room-Refresh, kein SSCam-state-Event, SSCamSTRM-Event
}
} elsif ($opt eq "extevent" && !SSCam_IsModelCam($hash)) {
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
$hash->{HELPER}{EVENTID} = $prop;
SSCam_extevent($hash);
} elsif ($opt eq "stopView" && SSCam_IsModelCam($hash)) {
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
SSCam_stopliveview($hash);
} elsif ($opt eq "setPreset" && SSCam_IsModelCam($hash)) {
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
if (!$prop) {return "Syntax of function \"$opt\" was wrong. Please use \"set $name setPreset []\" ";}
$hash->{HELPER}{PNUMBER} = $prop;
$hash->{HELPER}{PNAME} = $prop1?$prop1:$prop; # wenn keine Presetname angegeben -> Presetnummer als Name verwenden
$hash->{HELPER}{PSPEED} = $prop2 if($prop2);
SSCam_setPreset($hash);
} elsif ($opt eq "setHome" && SSCam_IsModelCam($hash)) {
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
if (!$prop) {return "Function \"$opt\" needs a \"Presetname\" as argument";}
$hash->{HELPER}{SETHOME} = $prop;
SSCam_setHome($hash);
} elsif ($opt eq "delPreset" && SSCam_IsModelCam($hash)) {
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
if (!$prop) {return "Function \"$opt\" needs a \"Presetname\" as argument";}
$hash->{HELPER}{DELPRESETNAME} = $prop;
SSCam_delPreset($hash);
} else {
return "$setlist";
}
return;
}
################################################################
sub SSCam_Get($@) {
my ($hash, @a) = @_;
return "\"get X\" needs at least an argument" if ( @a < 2 );
my $name = shift @a;
my $opt = shift @a;
my $arg = shift @a;
my $arg1 = shift @a;
my $arg2 = shift @a;
my $ret = "";
my $getlist;
if(!$hash->{CREDENTIALS}) {
return;
} elsif(SSCam_IsModelCam($hash)) {
# getlist für Cams
$getlist = "Unknown argument $opt, choose one of ".
"caminfoall:noArg ".
"caminfo:noArg ".
((AttrVal($name,"snapGalleryNumber",undef) || AttrVal($name,"snapGalleryBoost",0))
?"snapGallery:noArg ":"snapGallery:$SSCAM_snum ").
((ReadingsVal("$name", "CapPTZPresetNumber", 0) != 0) ? "listPresets:noArg " : "").
"snapinfo:noArg ".
"svsinfo:noArg ".
"snapfileinfo:noArg ".
"eventlist:noArg ".
"stmUrlPath:noArg ".
"storedCredentials:noArg ".
"scanVirgin:noArg ".
"versionNotes "
;
} else {
# getlist für SVS Devices
$getlist = "Unknown argument $opt, choose one of ".
"caminfoall:noArg ".
($hash->{HELPER}{APIHMMAXVER}?"homeModeState:noArg ": "").
"svsinfo:noArg ".
"listLog ".
"storedCredentials:noArg ".
"scanVirgin:noArg ".
"versionNotes "
;
}
return if(IsDisabled($name));
if ($opt eq "caminfo") {
# "1" ist Statusbit für manuelle Abfrage, kein Einstieg in Pollingroutine
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
SSCam_getcaminfo($hash);
} elsif ($opt eq "caminfoall") {
# "1" ist Statusbit für manuelle Abfrage, kein Einstieg in Pollingroutine
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
SSCam_getcaminfoall($hash,1);
} elsif ($opt eq "homeModeState" && !SSCam_IsModelCam($hash)) {
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
SSCam_gethomemodestate($hash);
} elsif ($opt eq "listLog" && !SSCam_IsModelCam($hash)) {
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
# übergebenen CL-Hash (FHEMWEB) in Helper eintragen
SSCam_getclhash($hash,1);
SSCam_extlogargs($hash,$arg) if($arg);
SSCam_extlogargs($hash,$arg1) if($arg1);
SSCam_extlogargs($hash,$arg2) if($arg2);
SSCam_getsvslog($hash);
} elsif ($opt eq "listPresets" && SSCam_IsModelCam($hash)) {
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
# übergebenen CL-Hash (FHEMWEB) in Helper eintragen
SSCam_getclhash($hash,1);
SSCam_getpresets($hash);
} elsif ($opt eq "svsinfo") {
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
SSCam_getsvsinfo($hash);
} elsif ($opt eq "storedCredentials") {
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
# Credentials abrufen
my ($success, $username, $password) = SSCam_getcredentials($hash,0);
unless ($success) {return "Credentials couldn't be retrieved successfully - see logfile"};
return "Stored Credentials for $name - Username: $username, Password: $password";
} elsif ($opt eq "snapGallery" && SSCam_IsModelCam($hash)) {
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
my $txt = SSCam_getclhash($hash);
return $txt if($txt);
if(!AttrVal($name, "snapGalleryBoost",0)) {
# Snaphash ist nicht vorhanden und wird abgerufen
$hash->{HELPER}{GETSNAPGALLERY} = 1;
# snap-Infos für Gallerie abrufen
my ($sg,$slim,$ssize);
$slim = $arg?AttrVal($name,"snapGalleryNumber",$arg):AttrVal($name,"snapGalleryNumber",$SSCam_slim); # Anzahl der abzurufenden Snapshots
$ssize = (AttrVal($name,"snapGallerySize","Icon") eq "Icon")?1:2; # Image Size 1-Icon, 2-Full
SSCam_getsnapinfo("$name:$slim:$ssize");
} else {
# Snaphash ist vorhanden und wird zur Ausgabe aufbereitet
my $htmlCode = SSCam_composegallery($name);
for (my $k=1; (defined($hash->{HELPER}{CL}{$k})); $k++ ) {
if ($hash->{HELPER}{CL}{$k}->{COMP}) {
# CL zusammengestellt (Auslösung durch Notify)
asyncOutput($hash->{HELPER}{CL}{$k}, "$htmlCode");
} else {
# Output wurde über FHEMWEB ausgelöst
return $htmlCode;
}
}
delete($hash->{HELPER}{CL});
}
} elsif ($opt eq "snapinfo" && SSCam_IsModelCam($hash)) {
# Schnappschußgalerie abrufen (snapGalleryBoost) oder nur Info des letzten Snaps
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
my ($slim,$ssize) = SSCam_snaplimsize($hash);
SSCam_getsnapinfo("$name:$slim:$ssize");
} elsif ($opt eq "snapfileinfo" && SSCam_IsModelCam($hash)) {
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
if (!ReadingsVal("$name", "LastSnapId", undef)) {return "Reading LastSnapId is empty - please take a snapshot before !"}
SSCam_getsnapfilename($hash);
} elsif ($opt eq "eventlist" && SSCam_IsModelCam($hash)) {
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
SSCam_geteventlist ($hash);
} elsif ($opt eq "stmUrlPath" && SSCam_IsModelCam($hash)) {
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
SSCam_getStmUrlPath ($hash);
} elsif ($opt eq "scanVirgin") {
if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
SSCam_sessionoff($hash);
delete $hash->{HELPER}{APIPARSET};
delete $hash->{CAMID};
# alte Readings außer state löschen
my @allrds = keys%{$defs{$name}{READINGS}};
foreach my $key(@allrds) {
# Log3 ($name, 1, "DbRep $name - Reading Schlüssel: $key");
delete($defs{$name}{READINGS}{$key}) if($key ne "state");
}
# "1" ist Statusbit für manuelle Abfrage, kein Einstieg in Pollingroutine
SSCam_getcaminfoall($hash,1);
} elsif ($opt =~ /versionNotes/) {
my $header = "Module release information ";
my $header1 = "Helpful hints ";
my %hs;
# Ausgabetabelle erstellen
my ($ret,$val0,$val1);
my $i = 0;
$ret = "";
# Hints
if(!$arg || $arg =~ /hints/ || $arg =~ /[\d]+/) {
$ret .= sprintf("