mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-03-13 17:26:34 +00:00
70_DoorPi.pm: Neue Version
git-svn-id: https://svn.fhem.de/fhem/trunk@12377 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
d6bb6be67e
commit
aada47e4cb
@ -41,7 +41,7 @@ use vars qw{%attr %defs};
|
||||
sub Log($$);
|
||||
|
||||
#-- globals on start
|
||||
my $version = "1.2";
|
||||
my $version = "1.4";
|
||||
|
||||
#-- these we may get on request
|
||||
my %gets = (
|
||||
@ -73,7 +73,7 @@ sub DoorPi_Initialize ($) {
|
||||
$hash->{InitFn} = "DoorPi_Init";
|
||||
|
||||
$hash->{AttrList}= "verbose ".
|
||||
"language:de,en ".
|
||||
"language:de,en ringcmd ".
|
||||
"doorbutton dooropencmd doorlockcmd doorunlockcmd ".
|
||||
"lightbutton lightoncmd lighttimercmd lightoffcmd ".
|
||||
"snapshotbutton streambutton ".
|
||||
@ -83,7 +83,6 @@ sub DoorPi_Initialize ($) {
|
||||
|
||||
$hash->{FW_detailFn} = "DoorPi_makeTable";
|
||||
$hash->{FW_summaryFn} = "DoorPi_makeShort";
|
||||
$hash->{FW_atPageEnd} = 1;
|
||||
}
|
||||
|
||||
########################################################################################
|
||||
@ -274,8 +273,14 @@ sub DoorPi_Set ($@) {
|
||||
if ( !grep( /$key/, @{$hash->{HELPER}->{CMDS}} ) && ($key ne "call") && ($key ne "door") );
|
||||
|
||||
#-- hidden command "call" to be used by DoorPi for communicating with this module
|
||||
if( $key eq "call" ){
|
||||
if( $value =~ "start.*" ){
|
||||
if( $key eq "call" ){
|
||||
Log3 $name,1,"[DoorPi] call $value received";
|
||||
#-- call init
|
||||
if( $value eq "init" ){
|
||||
DoorPi_GetConfig($hash);
|
||||
InternalTimer(gettimeofday()+10, "DoorPi_GetHistory", $hash,0);
|
||||
#-- call start
|
||||
}elsif( $value =~ "start.*" ){
|
||||
readingsSingleUpdate($hash,"call","started",1);
|
||||
my ($sec, $min, $hour, $day,$month,$year,$wday) = (localtime())[0,1,2,3,4,5,6];
|
||||
$year += 1900;
|
||||
@ -285,31 +290,31 @@ sub DoorPi_Set ($@) {
|
||||
unshift(@{ $hash->{DATA}}, ["",$timestamp,AttrVal($name, "target$value","unknown"),"active","--","xx","yy"] );
|
||||
#-- update web interface immediately
|
||||
DoorPi_inform($hash);
|
||||
|
||||
}elsif( $value eq "end" ){
|
||||
readingsSingleUpdate($hash,"call","ended",1);
|
||||
#-- obtain last snapshot
|
||||
DoorPi_GetLastSnapshot($hash);
|
||||
#-- and finally execute FHEM command
|
||||
fhem(AttrVal($name, "ringcmd",undef))
|
||||
if(AttrVal($name, "ringcmd",undef));
|
||||
#-- call end
|
||||
}elsif( $value =~ "end.*" ){
|
||||
DoorPi_GetHistory($hash);
|
||||
#-- update web interface in 5 seconds
|
||||
InternalTimer(gettimeofday()+5, "DoorPi_inform", $hash,0);
|
||||
|
||||
readingsSingleUpdate($hash,"call","ended",1);
|
||||
readingsSingleUpdate($hash,"call_listed",int(@{ $hash->{DATA}}),1);
|
||||
#-- call rejected
|
||||
}elsif( $value eq "rejected" ){
|
||||
DoorPi_GetHistory($hash);
|
||||
InternalTimer(gettimeofday()+5, "DoorPi_inform", $hash,0);
|
||||
readingsSingleUpdate($hash,"call","rejected",1);
|
||||
DoorPi_GetHistory($hash);
|
||||
|
||||
#-- call dismissed
|
||||
}elsif( $value eq "dismissed" ){
|
||||
DoorPi_GetHistory($hash);
|
||||
InternalTimer(gettimeofday()+5, "DoorPi_inform", $hash,0);
|
||||
readingsSingleUpdate($hash,"call","dismissed",1);
|
||||
DoorPi_GetHistory($hash);
|
||||
|
||||
}elsif( $value eq "startup" ){
|
||||
DoorPi_GetConfig($hash);
|
||||
DoorPi_GetHistory($hash);
|
||||
|
||||
}elsif( $value eq "snapshot" ){
|
||||
# TODO
|
||||
}else{
|
||||
Log 1,"[DoorPi_Set] $value";
|
||||
}
|
||||
#-- call target
|
||||
Log 1,"[DoorPi] unknown command set ... call $value";
|
||||
}
|
||||
#-- target for the call
|
||||
}elsif( $key eq "target" ){
|
||||
if( $value =~ /[0123]/ ){
|
||||
if(AttrVal($name, "target$value",undef)){
|
||||
@ -324,7 +329,7 @@ sub DoorPi_Set ($@) {
|
||||
return;
|
||||
}
|
||||
|
||||
#-- Door opening - rather complicated
|
||||
#-- door commands
|
||||
}elsif( ($key eq "$door")||($key eq "door") ){
|
||||
my $lockstate = ReadingsVal($name,"lockstate",undef);
|
||||
|
||||
@ -394,7 +399,7 @@ sub DoorPi_Set ($@) {
|
||||
fhem(AttrVal($name, "doorunlockcmd",undef));
|
||||
Log 1,"[DoorPi_Set] sent doorunlocked command to DoorPi and executed FHEM doorunlock command";
|
||||
}else{
|
||||
Log 1,"[DoorPi_Set] sent doorunlocked command to DoorPi and NOT executed FHEM doorunlock command";
|
||||
#Log 1,"[DoorPi_Set] sent doorunlocked command to DoorPi and NOT executed FHEM doorunlock command";
|
||||
}
|
||||
readingsSingleUpdate($hash,"lockstate","unlocked",1);
|
||||
readingsSingleUpdate($hash,$door,"unlocked",1);
|
||||
@ -408,7 +413,7 @@ sub DoorPi_Set ($@) {
|
||||
fhem(AttrVal($name, "doorlockcmd",undef));
|
||||
Log 1,"[DoorPi_Set] sent doorlocked command to DoorPi and executed extra FHEM doorlock command";
|
||||
}else{
|
||||
Log 1,"[DoorPi_Set] sent doorlocked command to DoorPi and NOT executed extra FHEM doorlock command";
|
||||
#Log 1,"[DoorPi_Set] sent doorlocked command to DoorPi and NOT executed extra FHEM doorlock command";
|
||||
}
|
||||
readingsSingleUpdate($hash,"lockstate","locked",1);
|
||||
readingsSingleUpdate($hash,$door,"locked",1);
|
||||
@ -418,6 +423,7 @@ sub DoorPi_Set ($@) {
|
||||
#-- snapshot
|
||||
}elsif( $key eq "$snapshot" ){
|
||||
$v=DoorPi_Cmd($hash,"snapshot");
|
||||
InternalTimer(gettimeofday()+3, "DoorPi_GetLastSnapshot", $hash,0);
|
||||
#-- video stream
|
||||
}elsif( $key eq "$stream" ){
|
||||
if( $value eq "on" ){
|
||||
@ -673,8 +679,8 @@ sub DoorPi_GetLastSnapshot {
|
||||
#-- decode config
|
||||
my $DoorPi = $jhash0->{"config"}->{"DoorPi"};
|
||||
my $lastsnap = $jhash0->{"config"}->{"DoorPi"}->{"last_snapshot"};
|
||||
|
||||
#push(@{ $hash->{DATA}}, ["",$state,$timestamp,$number,"started","--",$snapshot,$record] );
|
||||
$url = "http://".$hash->{TCPIP}."/";
|
||||
$lastsnap =~ s/\/home\/doorpi\/records\//$url/;
|
||||
|
||||
Log 1,"[DoorPi_GetLastSnapshot] returns $lastsnap";
|
||||
|
||||
@ -1055,20 +1061,11 @@ sub DoorPi_makeShort($$$$){
|
||||
|
||||
my $ret = "";
|
||||
|
||||
if(AttrVal($name, "no-heading", "0") eq "0" and defined($FW_ME) and defined($FW_subdir))
|
||||
{
|
||||
#$ret .= '<tr><td>';
|
||||
$ret .= '<div class="col1"><a href="'.$FW_ME.$FW_subdir.'?detail='.$name.'">'.$alias.'</a>'.(IsDisabled($name) ? ' (disabled)' : '').'</div>';
|
||||
}
|
||||
|
||||
|
||||
if(AttrVal($name, "language", "en") eq "de"){
|
||||
$ret .= "</td><td>".int(@{ $hash->{DATA}})." Einträge";
|
||||
$ret .= "<div class=\"col2\">".int(@{$hash->{DATA}})."\ Einträge</div>";
|
||||
}else{
|
||||
$ret .= "</td><td>".int(@{ $hash->{DATA}})." calls";
|
||||
$ret .= "<div class=\"col2\">".int(@{$hash->{DATA}})."\ calls</div>";
|
||||
}
|
||||
|
||||
$ret .= "</td><td><a href=\"/fhem?cmd.$devname=set $devname door open\">open</a>";
|
||||
|
||||
setlocale(LC_ALL, $old_locale);
|
||||
|
||||
@ -1101,19 +1098,28 @@ sub DoorPi_makeTable($$$$){
|
||||
sub DoorPi_inform($){
|
||||
my ($hash) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
my $alias = AttrVal($hash->{NAME}, "alias", $hash->{NAME});
|
||||
|
||||
Log3 $name, 5, "[Doorpi_inform]- inform all FHEMWEB clients";
|
||||
Log3 $name, 1, "[Doorpi_inform]- inform all FHEMWEB clients";
|
||||
my $count = 0;
|
||||
|
||||
foreach my $line (DoorPi_list($hash,1)){
|
||||
#Log 1,"[Doorpi_Set] - informing $name with $line";
|
||||
#Log 1,"[Doorpi_Set] - informing $name";
|
||||
FW_directNotify($name, $line, 1);
|
||||
$count++;
|
||||
}
|
||||
|
||||
# send the current row count to ensure all other rows are deleted via JS
|
||||
# FW_directNotify($name,"max-lines,$count", 1);
|
||||
}
|
||||
|
||||
my $ret;
|
||||
if(AttrVal($name, "language", "en") eq "de"){
|
||||
$ret .= "</td><td><div class=\"col2\">".int(@{$hash->{DATA}})."\ Einträge</div>";
|
||||
}else{
|
||||
$ret .= "</td><td><div class=\"col2\">".int(@{$hash->{DATA}})."\ calls</div>";
|
||||
}
|
||||
|
||||
FW_directNotify($name,"",$ret);
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
||||
#######################################################################################
|
||||
#
|
||||
@ -1274,7 +1280,6 @@ sub DoorPi_list($;$){
|
||||
setlocale(LC_ALL, $old_locale);
|
||||
|
||||
return ($to_json ? @json_output : $ret);
|
||||
#return ($ret);
|
||||
}
|
||||
|
||||
|
||||
@ -1366,6 +1371,9 @@ sub DoorPi_list($;$){
|
||||
<li><a name="doorpi_target2"><code>attr <DoorPi-Device> target[0|1|2|3]
|
||||
<string></code></a>
|
||||
<br />Call target numbers for different redirections. If none is set, redirection will not be offered.</li>
|
||||
<li><a name="doorpi_ringcmd"><code>attr <DoorPi-Device> ringcmd
|
||||
<string></code></a>
|
||||
<br />FHEM command additionally executed for ringing action (no default)</li>
|
||||
<li><a name="doorpi_doorbutton"><code>attr <DoorPi-Device> doorbutton
|
||||
<string></code></a>
|
||||
<br />DoorPi name for door action (default: door)</li>
|
||||
|
@ -1,5 +1,35 @@
|
||||
# /bin/sh
|
||||
|
||||
#
|
||||
# FHEMHelper.sh
|
||||
#
|
||||
# Script file to perform various external tasks for DoorPi
|
||||
#
|
||||
# Prof. Dr. Peter A. Henning, 2016
|
||||
#
|
||||
# $Id: FHEMHelper 2016-05 - pahenning $
|
||||
#
|
||||
########################################################################################
|
||||
#
|
||||
# This programm 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.
|
||||
#
|
||||
# The GNU General Public License can be found at
|
||||
# http://www.gnu.org/copyleft/gpl.html.
|
||||
# A copy is found in the textfile GPL.txt and important notices to the license
|
||||
# from the author is found in LICENSE.txt distributed with these scripts.
|
||||
#
|
||||
# This script 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.
|
||||
#
|
||||
#########################################################################################
|
||||
# History
|
||||
# no_Legend 2016-09-28: Hinzufügen von verschiedenen Variablen, sowie bedingte Ausführung
|
||||
# der Textausgaben auf einem TTS_Device.
|
||||
#########################################################################################
|
||||
|
||||
checkstream() {
|
||||
streampid=`pidof mjpg_streamer`
|
||||
@ -10,41 +40,60 @@ checkstream() {
|
||||
fi
|
||||
}
|
||||
|
||||
FHEMDP="A.Door.Pi"
|
||||
FHEMIP="192.168.xxx"
|
||||
FHEM="http://192.168xx:8083/fhem?XHR=1&cmd.$FHEMDP"
|
||||
HOME="/home/doorpi"
|
||||
default_target="722xxxx"
|
||||
FHEMDP="A.Door.Pi" # FHEM Devicename for DoorPi
|
||||
FHEMIP="192.168.x.y" # IP address for DoorPi
|
||||
FHEMPORT="8083" # Port number for DoorPi
|
||||
FHEMHTTPS="false" # true for HTTPS, false without HTTPS
|
||||
curlprog="curl"
|
||||
curlargs="" # -k to disable HTTPS certificate check,
|
||||
# -u user:password for user and password
|
||||
HOME="/home/doorpi" # Doorpi Standard /usr/local/etc/DoorPi/
|
||||
default_target="yyyyy" # default telephone number to be called
|
||||
FHEMTTS="true" # true for TTS output, false without TTS
|
||||
FHEMTTSDEVICE="GalaxyTab" # FHEM Devicename for TTS device
|
||||
|
||||
### FHEM path ###
|
||||
if [ $FHEMHTTPS = "true" ]; then
|
||||
FHEM="https://$FHEMIP:$FHEMPORT/fhem?XHR=1&cmd.$FHEMDP"
|
||||
else
|
||||
FHEM="http://$FHEMIP:$FHEMPORT/fhem?XHR=1&cmd.$FHEMDP"
|
||||
fi
|
||||
|
||||
### execute commands ##
|
||||
case $1 in
|
||||
|
||||
init) target=`cat $HOME/calltarget`
|
||||
curl "$FHEM=setreading%20$FHEMDP%20call_target%20$target" &
|
||||
|
||||
init) #-- send current target to FHEM
|
||||
target=`cat $HOME/calltarget`
|
||||
$curlprog $curlargs "$FHEM=setreading%20$FHEMDP%20call_target%20$target" &
|
||||
#-- send state of mjpg_streamer to FHEM
|
||||
streampid=`pidof mjpg_streamer`
|
||||
if [ -z "$streampid" ]; then
|
||||
curl "$FHEM=setreading%20$FHEMDP%20stream%20off" &
|
||||
$curlprog $curlargs "$FHEM=setreading%20$FHEMDP%20stream%20off" &
|
||||
else
|
||||
curl "$FHEM=setreading%20$FHEMDP%20stream%20on" &
|
||||
$curlprog $curlargs "$FHEM=setreading%20$FHEMDP%20stream%20on" &
|
||||
fi
|
||||
;;
|
||||
|
||||
doorunlockandopen)
|
||||
curl "$FHEM=set%20GalaxyTab%20ttsSay%20Ein%20Bewohner%20betritt%20das%20Haus" &
|
||||
curl "$FHEM=set%20$FHEMDP%20door%20unlockandopen" &
|
||||
if [ $FHEMTTS = "true" ]; then
|
||||
$curlprog $curlargs "$FHEM=set%20$FHEMTTSDEVICE%20ttsSay%20Ein%20Bewohner%20betritt%20das%20Haus" &
|
||||
fi
|
||||
$curlprog $curlargs "$FHEM=set%20$FHEMDP%20door%20unlockandopen" &
|
||||
;;
|
||||
|
||||
wrongid)
|
||||
curl "$FHEM=set%20GalaxyTab%20ttsSay%20Unerlaubter%20Zutrittsversuch" &
|
||||
curl "$FHEM=set%20$FHEMDP%20door%20wrong_id" &
|
||||
if [ $FHEMTTS = "true" ]; then
|
||||
$curlprog $curlargs "$FHEM=set%20FHEMTTSDEVICE%20ttsSay%20Unerlaubter%20Zutrittsversuch" &
|
||||
fi
|
||||
$curlprog $curlargs "$FHEM=set%20$FHEMDP%20door%20wrong_id" &
|
||||
;;
|
||||
|
||||
softlock)
|
||||
curl "$FHEM=set%20$FHEMDP%20door%20softlock" &
|
||||
$curlprog $curlargs "$FHEM=set%20$FHEMDP%20door%20softlock" &
|
||||
;;
|
||||
|
||||
call)
|
||||
curl "$FHEM=set%20$FHEMDP%20call%20$2" &
|
||||
$curlprog $curlargs "$FHEM=set%20$FHEMDP%20call%20$2" &
|
||||
;;
|
||||
|
||||
gettarget)
|
||||
@ -56,11 +105,11 @@ case $1 in
|
||||
;;
|
||||
|
||||
movement)
|
||||
curl "$FHEM=set%20$FHEMDP%20door%20movement" &
|
||||
$curlprog $curlargs "$FHEM=set%20$FHEMDP%20door%20movement" &
|
||||
;;
|
||||
|
||||
sabotage)
|
||||
curl "$FHEM=set%20$FHEMDP%20door%20sabotage" &
|
||||
$curlprog $curlargs "$FHEM=set%20$FHEMDP%20door%20sabotage" &
|
||||
;;
|
||||
|
||||
esac
|
||||
|
@ -9,7 +9,7 @@ last_snapshot =
|
||||
[DoorPiWeb]
|
||||
indexfile = index.html
|
||||
loginfile = login.html
|
||||
online_fallback = http://motom001.github.io/DoorPiWeb
|
||||
#online_fallback = http://192.168.x.y:8083/fhem?detail=A.Door.Pi
|
||||
port = 80
|
||||
public = AREA_public
|
||||
www = /home/doorpi/records
|
||||
@ -49,7 +49,7 @@ administrators = dashboard,status,config
|
||||
guests = dashboard
|
||||
|
||||
[AdminNumbers]
|
||||
**621 = active
|
||||
**xxx = active
|
||||
|
||||
[DTMF]
|
||||
"#" = out:door,1,0,3
|
||||
@ -63,8 +63,8 @@ firewallpolicy = PolicyNoFirewall
|
||||
sipphonetyp = linphone
|
||||
sipserver_password = xxxxxxxxx
|
||||
sipserver_realm = fritz.box
|
||||
sipserver_server = xxxxxxx
|
||||
sipserver_username = xxxxxx
|
||||
sipserver_server = 192.168.x.y
|
||||
sipserver_username = yyy
|
||||
stun_server =
|
||||
#
|
||||
max_call_time = 300
|
||||
@ -77,7 +77,7 @@ audio_codecs = PCMA,PCMU
|
||||
record_while_dialing = False
|
||||
records = /home/doorpi/records/%Y-%m-%d_%H-%M-%S.wav
|
||||
#
|
||||
dialtone = /home/doorpi/sounds/ShortDialTone.wav
|
||||
dialtone = /home/doorpi/sounds/bigben_mono.wav
|
||||
dialtone_renew_every_start = False
|
||||
dialtone_volume = 35
|
||||
echo_cancellation_enabled = False
|
||||
@ -90,26 +90,35 @@ video_size = vga
|
||||
####################### Events #######################
|
||||
[EVENT_OnStartup]
|
||||
10 = sleep:1
|
||||
20 = os_execute:/home/doorpi/FHEMHelper.sh init
|
||||
20 = os_execute:/home/doorpi/FHEMHelper.sh call init
|
||||
#30 = out:audio,1
|
||||
|
||||
[EVENT_BeforeSipPhoneMakeCall]
|
||||
10 = out:irlight,1
|
||||
20 = os_execute:/home/doorpi/FHEMHelper.sh call startup
|
||||
30 = take_snapshot
|
||||
20 = take_snapshot
|
||||
30 = os_execute:/home/doorpi/FHEMHelper.sh call started
|
||||
40 = out:irlight,0
|
||||
#30 = mailto:haus271828@henning-weingarten.de,DoorPi,DoorPi initiating call
|
||||
|
||||
#[EVENT_OnCallStateConnect]
|
||||
#10 = out:audio,0
|
||||
|
||||
[EVENT_OnCallStateDisconnect]
|
||||
10 = os_execute:/home/doorpi/FHEMHelper.sh call end
|
||||
10 = os_execute:/home/doorpi/FHEMHelper.sh call ended
|
||||
#20 = out:audio,1
|
||||
|
||||
[EVENT_OnCallStateDismissed]
|
||||
10 = os_execute:/home/doorpi/FHEMHelper.sh call dismissed
|
||||
#20 = out:audio,1
|
||||
|
||||
[EVENT_OnCallStateReject]
|
||||
10 = os_execute:/home/doorpi/FHEMHelper.sh call rejected
|
||||
20 = out:audio,1
|
||||
|
||||
[EVENT_OnTimeMinuteEvery5]
|
||||
10=statuswatchdog:/tmp/doorpi.watchdog
|
||||
10 = statuswatchdog:/tmp/doorpi.watchdog
|
||||
#20 = out:audio,1
|
||||
|
||||
####################### Keyboards ##############################
|
||||
[keyboards]
|
||||
@ -183,21 +192,27 @@ pull_up_down = PUD_UP
|
||||
2 = dashlight
|
||||
3 = irlight
|
||||
4 = hardlock
|
||||
6 = audio
|
||||
7 = blinking_led
|
||||
|
||||
[onboardpins_InputPins]
|
||||
0 = file_call_value:/home/doorpi/calltarget
|
||||
0 = sleep:0
|
||||
1 = sleep:0
|
||||
4 = sleep:0
|
||||
5 = sleep:0
|
||||
6 = sleep:0
|
||||
7 = sleep:0
|
||||
|
||||
#-- DoorOpen pin from Arduino
|
||||
[EVENT_OnKeyPressed_onboardpins.1]
|
||||
10 = os_execute:/home/doorpi/FHEMHelper.sh doorunlockandopen
|
||||
20 = os_execute:aplay -D plughw:1,0 /home/doorpi/sounds/067_willkommen.wav
|
||||
#-- RING THE BELL
|
||||
[EVENT_OnKeyPressed_onboardpins.0]
|
||||
20 = file_call_value:/home/doorpi/calltarget
|
||||
|
||||
#-- DoorOpen pin from Arduino
|
||||
[EVENT_OnKeyPressed_onboardpins.1]
|
||||
#10 = out:audio,0
|
||||
20 = os_execute:/home/doorpi/FHEMHelper.sh doorunlockandopen
|
||||
30 = os_execute:aplay -D plughw:1,0 /home/doorpi/sounds/067_willkommen.wav
|
||||
#40 = out:audio,1
|
||||
|
||||
#-- WrongID pin from Arduino
|
||||
[EVENT_OnKeyPressed_onboardpins.4]
|
||||
@ -214,7 +229,6 @@ pull_up_down = PUD_UP
|
||||
[EVENT_OnKeyPressed_onboardpins.6]
|
||||
10 = out:dashlight,1,0,1
|
||||
20 = os_execute:/home/doorpi/FHEMHelper.sh movement
|
||||
30 = sleep:60
|
||||
|
||||
#-- Sabotage detection
|
||||
[EVENT_OnKeyPressed_onboardpins.7]
|
||||
|
Loading…
x
Reference in New Issue
Block a user