diff --git a/fhem/CHANGED b/fhem/CHANGED
index 39b14d491..710595b82 100644
--- a/fhem/CHANGED
+++ b/fhem/CHANGED
@@ -1,5 +1,25 @@
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
# Do not insert empty lines here, update check depends on it.
+ - featire: SD_ProtocolData.pm v1.1.7
+ new protocol 97 Momento remote control for wireless digital picture frame
+ new protocol 58 Weather F007-T
+ new protocol 27 for EuroChron EFTH-800
+ new protocol 26 - Remote control xavax 00111939
+ new protocol 20 - Remote control diesel heating
+ - feature: 00_SIGNALduino.pm version 3.4.2
+ automatic load cc1101 config after change value or restart
+ made multiple get commands more easy and robust to handle
+ extended cc1101 settings to ccconf reading
+- bugfix: 00_SIGNALduino.pm version 3.4.2
+ several retrys to initialize the SIGNALduino
+ flash via http: Fixed Filename extraction of URL
+ bug fixed set sduino cc1101_rAmpl 42
+ Allow lower case letters for hex values in set / get cc1101_reg
+- change:
+ filtered possible set/get commands per device type
+ added meta information to 00_SIGNALduino.pm
+ patable list values adapted to values allowed per frequency
+ ranges
- new: 70_HYDRAWISE: New module for controlling Hunter Hydrawise irrigation
- feature: 93_Log2Syslog: support time-secfrac of RFC 3339, minor fix
- feature: 93_Log2Syslog: new attribute 'timeSpec', send and parse messages
diff --git a/fhem/FHEM/00_SIGNALduino.pm b/fhem/FHEM/00_SIGNALduino.pm
index dde23c091..b19d8d82e 100644
--- a/fhem/FHEM/00_SIGNALduino.pm
+++ b/fhem/FHEM/00_SIGNALduino.pm
@@ -1,14 +1,15 @@
# $Id$
#
-# v3.4.1
+# v3.4.2 - https://github.com/RFD-FHEM/RFFHEM/tree/dev-r34
# The module is inspired by the FHEMduino project and modified in serval ways for processing the incoming messages
# see http://www.fhemwiki.de/wiki/SIGNALDuino
# It was modified also to provide support for raw message handling which can be send from the SIGNALduino
# The purpos is to use it as addition to the SIGNALduino which runs on an arduno nano or arduino uno.
# It routes Messages serval Modules which are already integrated in FHEM. But there are also modules which comes with it.
+#
# N. Butzek, S. Butzek, 2014-2015
# S.Butzek,Ralf9 2016-2019
-
+# S.Butzek, HomeAutoUser, elektron-bbs 2019-2020
package main;
my $missingModulSIGNALduino="";
@@ -31,7 +32,7 @@ use lib::SD_Protocols;
use constant {
- SDUINO_VERSION => "v3.4.1",
+ SDUINO_VERSION => "v3.4.2",
SDUINO_INIT_WAIT_XQ => 1.5, # wait disable device
SDUINO_INIT_WAIT => 2,
SDUINO_INIT_MAXRETRY => 3,
@@ -40,11 +41,12 @@ use constant {
SDUINO_KEEPALIVE_MAXRETRY => 3,
SDUINO_WRITEQUEUE_NEXT => 0.3,
SDUINO_WRITEQUEUE_TIMEOUT => 2,
-
+
SDUINO_DISPATCH_VERBOSE => 5, # default 5
SDUINO_MC_DISPATCH_VERBOSE => 5, # wenn kleiner 5, z.B. 3 dann wird vor dem dispatch mit loglevel 3 die ID und rmsg ausgegeben
SDUINO_MC_DISPATCH_LOG_ID => '12.1', # die o.g. Ausgabe erfolgt nur wenn der Wert mit der ID uebereinstimmt
- SDUINO_PARSE_DEFAULT_LENGHT_MIN => 8
+ SDUINO_PARSE_DEFAULT_LENGHT_MIN => 8,
+ SDUINO_GET_CONFIGQUERY_DELAY => 0.75 # delay for cmd to no overwrite a working cmd
};
@@ -65,88 +67,29 @@ sub SIGNALduino_Log3($$$);
our %modules;
our %defs;
-# Two options are possible to specify a get command
-# Option 1 will send a serial command to the uC and wait for response. For this an array needs to be specified
-# Option 2 will call a anonymous sub which does some things
-my %gets = ( # Name, Data to send to the SIGNALduino, Regexp for the answer
- "version" => ["V", 'V\s.*SIGNAL(duino|ESP).*'],
- "freeram" => ["R", '^[0-9]+'],
-# "raw" => ["", '.*'],
- "uptime" => ["t", '^[0-9]+' ],
- "cmds" => ["?", '.*Use one of[ 0-9A-Za-z]+[\r\n]*$' ],
-# "ITParms" => ["ip",'.*'],
- "ping" => ["P",'^OK$'],
- "config" => ["CG",'^MS.*MU.*MC.*'],
-# "protocolIDs" => ["none",'none'],
- "ccconf" => ["C0DnF", 'C0Dn11.*'],
- "ccreg" => ["C", '^C.* = .*'],
- "ccpatable" => ["C3E", '^C3E = .*'],
-# "ITClock" => ["ic", '\d+'],
-# "FAParms" => ["fp", '.*' ],
-# "TCParms" => ["dp", '.*' ],
-# "HXParms" => ["hp", '.*' ]
-# "availableFirmware" => ["none",'none'],
- "availableFirmware" => sub {
- my ($hash, @a) = @_;
-
- if ($missingModulSIGNALduino =~ m/JSON/ )
- {
- $hash->{logMethod}->($hash->{NAME}, 1, "$hash->{NAME}: get $a[1] failed. Pleas install Perl module JSON. Example: sudo apt-get install libjson-perl");
- return "$a[1]: \n\nFetching from github is not possible. Please install JSON. Example:
sudo apt-get install libjson-perl
";
- }
-
- my $channel=AttrVal($hash->{NAME},"updateChannelFW","stable");
- my $hardware=AttrVal($hash->{NAME},"hardware",undef);
-
- my ($validHw) = $modules{$hash->{TYPE}}{AttrList} =~ /.*hardware:(.*?)\s/;
- $hash->{logMethod}->($hash->{NAME}, 1, "$hash->{NAME}: found availableFirmware for $validHw");
-
- if (!defined($hardware) || $validHw !~ /$hardware(?:,|$)/ )
- {
- $hash->{logMethod}->($hash->{NAME}, 1, "$hash->{NAME}: get $a[1] failed. Please set attribute hardware first");
- return "$a[1]: \n\n$hash->{NAME}: get $a[1] failed. Please choose one of $validHw attribute hardware";
- }
- SIGNALduino_querygithubreleases($hash);
- return "$a[1]: \n\nFetching $channel firmware versions for $hardware from github\n";
- },
- "raw" => sub {
- my ($hash, @a) = @_;
- if ($a[2] =~ /^M[CcSU];.*/)
- {
- $a[2]="\002$a[2]\003"; ## Add start end end marker if not already there
- $hash->{logMethod}->($hash->{NAME}, 5, "$hash->{NAME}: msg adding start and endmarker to message");
- }
- if ($a[2] =~ /\002M.;.*;\003$/)
- {
- $hash->{logMethod}->( $hash->{NAME}, 4, "$hash->{NAME}: msg get raw: $a[2]");
- return SIGNALduino_Parse($hash, $hash, $hash->{NAME}, $a[2]);
- }
- },
-
+my %gets = ( # NameOFCommand => StyleMod for Fhemweb, SubToCall if get is executed, String to send to uC, sub called with response, regex to verify response,
+ "?" => ['', \&SIGNALduino_Get_FhemWebList ],
+ "version" => ['noArg', \&SIGNALduino_Get_Command, "V", \&SIGNALduino_CheckVersionResp, 'V\s.*SIGNAL(?:duino|ESP).*(?:\s\d\d:\d\d:\d\d)' ],
+ "freeram" => ['noArg', \&SIGNALduino_Get_Command, "R", \&SIGNALduino_GetResponseUpdateReading, '^[0-9]+' ] ,
+ "uptime" => ['noArg', \&SIGNALduino_Get_Command, "t", \&SIGNALduino_CheckUptimeResponse, '^[0-9]+' ],
+ "cmds" => ['noArg', \&SIGNALduino_Get_Command, "?", \&SIGNALduino_CheckCmdsResponse, '.*' ],
+ "ping" => ['noArg', \&SIGNALduino_Get_Command, "P", \&SIGNALduino_GetResponseUpdateReading, '^OK$' ],
+ "config" => ['noArg', \&SIGNALduino_Get_Command, "CG", \&SIGNALduino_GetResponseUpdateReading, '^MS.*MU.*MC.*' ],
+ "ccconf" => ['noArg', \&SIGNALduino_Get_Command, "C0DnF", \&SIGNALduino_CheckccConfResponse, 'C0Dn11=[A-F0-9a-f]+'],
+ "ccreg" => ['textFieldNL', \&SIGNALduino_Get_Command_CCReg,"C", \&SIGNALduino_CheckCcregResponse, '^(?:C[A-Fa-f0-9]{2}\s=\s[0-9A-Fa-f]+$|ccreg 00:)'],
+ "ccpatable" => ['noArg', \&SIGNALduino_Get_Command, "C3E", \&SIGNALduino_CheckccPatableResponse, '^C3E\s=\s.*'],
+ "raw" => ['textFieldNL', \&SIGNALduino_Get_Raw ],
+ "availableFirmware" => ['noArg', \&SIGNALduino_Get_availableFirmware ]
);
-my %sets = (
- "raw" => '',
- "flash" => '',
- "reset" => 'noArg',
- "close" => 'noArg',
- #"disablereceiver" => "",
- #"ITClock" => 'slider,100,20,700',
- "enableMessagetype" => 'syncedMS,unsyncedMU,manchesterMC',
- "disableMessagetype" => 'syncedMS,unsyncedMU,manchesterMC',
- "sendMsg" => "",
- "cc1101_freq" => '',
- "cc1101_bWidth" => '58,68,81,102,116,135,162,203,232,270,325,406,464,541,650,812',
- "cc1101_rAmpl" => '24,27,30,33,36,38,40,42',
- "cc1101_sens" => '4,8,12,16',
- "cc1101_patable_433" => '-10_dBm,-5_dBm,0_dBm,5_dBm,7_dBm,10_dBm',
- "cc1101_patable_868" => '-10_dBm,-5_dBm,0_dBm,5_dBm,7_dBm,10_dBm',
-);
-
+my %ProtocolListSIGNALduino;
my %patable = (
"433" =>
{
+ "-30_dBm" => '12',
+ "-20_dBm" => '0E',
+ "-15_dBm" => '1D',
"-10_dBm" => '34',
"-5_dBm" => '68',
"0_dBm" => '60',
@@ -156,6 +99,9 @@ my %patable = (
},
"868" =>
{
+ "-30_dBm" => '03',
+ "-20_dBm" => '0F',
+ "-15_dBm" => '1E',
"-10_dBm" => '27',
"-5_dBm" => '67',
"0_dBm" => '50',
@@ -164,9 +110,80 @@ my %patable = (
"10_dBm" => 'C2',
},
);
+my @ampllist = (24, 27, 30, 33, 36, 38, 40, 42); # rAmpl(dB)
+my %sets = (
+ #Command name [FhemWeb Argument type, code to run]
+ "?" => ['', \&SIGNALduino_Set_FhemWebList ],
+ "raw" => ['textFieldNL',\&SIGNALduino_Set_raw ],
+ "flash" => ['textFieldNL', \&SIGNALduino_Set_flash ],
+ "reset" => ['noArg', \&SIGNALduino_Set_reset ],
+ "close" => ['noArg', \&SIGNALduino_Set_close ],
+ "enableMessagetype" => ['syncedMS,unsyncedMU,manchesterMC', \&SIGNALduino_Set_MessageType ],
+ "disableMessagetype" => ['syncedMS,unsyncedMU,manchesterMC', \&SIGNALduino_Set_MessageType ],
+ "sendMsg" => ['textFieldNL',\&SIGNALduino_Set_sendMsg ],
+ "cc1101_freq" => ['textFieldNL', \&cc1101::SetFreq ],
+ "cc1101_bWidth" => ['58,68,81,102,116,135,162,203,232,270,325,406,464,541,650,812', \&SIGNALduino_Set_bWidth ],
+ "cc1101_rAmpl" => ['24,27,30,33,36,38,40,42', \&cc1101::setrAmpl ],
+ "cc1101_sens" => ['4,8,12,16', \&cc1101::SetSens ],
+ "cc1101_patable" => ['-30_dBm,-20_dBm,-15_dBm,-10_dBm,-5_dBm,0_dBm,5_dBm,7_dBm,10_dBm', \&cc1101::SetPatable ],
+ "cc1101_reg" => [ 'textFieldNL', \&cc1101::SetRegisters ],
+);
-my @ampllist = (24, 27, 30, 33, 36, 38, 40, 42); # rAmpl(dB)
+## Supported config CC1101 ##
+my @modformat = ("2-FSK","GFSK","-","ASK/OOK","4-FSK","-","-","MSK");
+my @syncmod = ("No preamble/sync","15/16 sync word bits detected","16/16 sync word bits detected","30/32 sync word bits detected",
+ "No preamble/sync, carrier-sense above threshold, carrier-sense above threshold", "15/16 + carrier-sense above threshold", "16/16 + carrier-sense above threshold", "30/32 + carrier-sense above threshold");
+
+my %cc1101_register = ( # for get ccreg 99 and set cc1101_reg
+ "00" => 'IOCFG2 ', # ! the values with spaces for output get ccreg 99 !
+ "01" => 'IOCFG1 ',
+ "02" => 'IOCFG0 ',
+ "03" => 'FIFOTHR ',
+ "04" => 'SYNC1 ',
+ "05" => 'SYNC0 ',
+ "06" => 'PKTLEN ',
+ "07" => 'PKTCTRL1',
+ "08" => 'PKTCTRL0',
+ "09" => 'ADDR ',
+ "0A" => 'CHANNR ',
+ "0B" => 'FSCTRL1 ',
+ "0C" => 'FSCTRL0 ',
+ "0D" => 'FREQ2 ',
+ "0E" => 'FREQ1 ',
+ "0F" => 'FREQ0 ',
+ "10" => 'MDMCFG4 ',
+ "11" => 'MDMCFG3 ',
+ "12" => 'MDMCFG2 ',
+ "13" => 'MDMCFG1 ',
+ "14" => 'MDMCFG0 ',
+ "15" => 'DEVIATN ',
+ "16" => 'MCSM2 ',
+ "17" => 'MCSM1 ',
+ "18" => 'MCSM0 ',
+ "19" => 'FOCCFG ',
+ "1A" => 'BSCFG ',
+ "1B" => 'AGCCTRL2',
+ "1C" => 'AGCCTRL1',
+ "1D" => 'AGCCTRL0',
+ "1E" => 'WOREVT1 ',
+ "1F" => 'WOREVT0 ',
+ "20" => 'WORCTRL ',
+ "21" => 'FREND1 ',
+ "22" => 'FREND0 ',
+ "23" => 'FSCAL3 ',
+ "24" => 'FSCAL2 ',
+ "25" => 'FSCAL1 ',
+ "26" => 'FSCAL0 ',
+ "27" => 'RCCTRL1 ',
+ "28" => 'RCCTRL0 ',
+ "29" => 'FSTEST ',
+ "2A" => 'PTEST ',
+ "2B" => 'AGCTEST ',
+ "2C" => 'TEST2 ',
+ "2D" => 'TEST1 ',
+ "2E" => 'TEST0 ',
+);
## Supported Clients per default
my $clientsSIGNALduino = ":IT:"
@@ -198,8 +215,9 @@ my $clientsSIGNALduino = ":IT:"
."CUL_EM:"
."Fernotron:"
."SD_Keeloq:"
+ ."SD_GT:"
."SIGNALduino_un:"
- ;
+ ;
## default regex match List for dispatching message to logical modules, can be updated during runtime because it is referenced
my %matchListSIGNALduino = (
@@ -218,24 +236,24 @@ my %matchListSIGNALduino = (
"14:Dooya" => '^P16#[A-Fa-f0-9]+',
"15:SOMFY" => '^Ys[0-9A-F]+',
"16:SD_WS_Maverick" => '^P47#[A-Fa-f0-9]+',
- "17:SD_UT" => '^P(?:14|29|30|34|46|68|69|76|81|83|86|90|91|91.1|92|93|95)#.*', # universal - more devices with different protocols
+ "17:SD_UT" => '^P(?:14|20|26|29|30|34|46|68|69|76|81|83|86|90|91|91.1|92|93|95|97)#.*', # universal - more devices with different protocols
"18:FLAMINGO" => '^P13\.?1?#[A-Fa-f0-9]+', # Flamingo Smoke
"19:CUL_WS" => '^K[A-Fa-f0-9]{5,}',
"20:Revolt" => '^r[A-Fa-f0-9]{22}',
"21:FS10" => '^P61#[A-F0-9]+',
"22:Siro" => '^P72#[A-Fa-f0-9]+',
"23:FHT" => "^81..(04|09|0d)..(0909a001|83098301|c409c401)..",
- "24:FS20" => "^81..(04|0c)..0101a001",
- "25:CUL_EM" => "^E0.................",
+ "24:FS20" => "^81..(04|0c)..0101a001",
+ "25:CUL_EM" => "^E0.................",
"26:Fernotron" => '^P82#.*',
"27:SD_BELL" => '^P(?:15|32|41|42|57|79|96)#.*',
"28:SD_Keeloq" => '^P(?:87|88)#.*',
+ "29:SD_GT" => '^P49#[A-Fa-f0-9]+',
"X:SIGNALduino_un" => '^[u]\d+#.*',
);
-my %ProtocolListSIGNALduino;
my %symbol_map = (one => 1 , zero =>0 ,sync => '', float=> 'F', 'start' => '');
@@ -262,7 +280,7 @@ sub SIGNALduino_Initialize($) {
$hash->{GetFn} = "SIGNALduino_Get";
$hash->{SetFn} = "SIGNALduino_Set";
$hash->{AttrFn} = "SIGNALduino_Attr";
- $hash->{AttrList} =
+ $hash->{AttrList} =
"Clients MatchList do_not_notify:1,0 dummy:1,0"
." hexFile"
." initCommands"
@@ -289,14 +307,14 @@ sub SIGNALduino_Initialize($) {
$hash->{ShutdownFn} = "SIGNALduino_Shutdown";
$hash->{FW_detailFn} = "SIGNALduino_FW_Detail";
$hash->{FW_deviceOverview} = 1;
-
+
$hash->{msIdList} = ();
$hash->{muIdList} = ();
$hash->{mcIdList} = ();
-
+
#our $attr;
-
+
%ProtocolListSIGNALduino = SIGNALduino_LoadProtocolHash("$attr{global}{modpath}/FHEM/lib/SD_ProtocolData.pm");
if (exists($ProtocolListSIGNALduino{error}) ) {
@@ -309,7 +327,7 @@ sub SIGNALduino_Initialize($) {
# Predeclare Variables from other modules may be loaded later from fhem
#
our $FW_wname;
-our $FW_ME;
+our $FW_ME;
#
# Predeclare Variables from other modules may be loaded later from fhem
@@ -322,8 +340,8 @@ our $FW_detail;
#
# returns a hash with protocols if loaded without error. Returns a hash with {eror} => errormessage if there was an error
-#####################################
-sub SIGNALduino_LoadProtocolHash($) {
+#####################################
+sub SIGNALduino_LoadProtocolHash($) {
my $ret= lib::SD_Protocols::LoadHash($_[0]);
return %$ret;
}
@@ -348,51 +366,51 @@ sub SIGNALduino_Define($$) {
Log3 undef, 2, $msg;
return $msg;
}
-
+
DevIo_CloseDev($hash);
my $name = $a[0];
-
+
if (!exists &round)
{
Log3 $name, 1, "$name: Define, Signalduino can't be activated (sub round not found). Please update Fhem via update command";
return undef;
}
-
+
my $dev = $a[2];
#Debug "dev: $dev" if ($debug);
#my $hardware=AttrVal($name,"hardware","nano");
#Debug "hardware: $hardware" if ($debug);
-
-
+
+
if($dev eq "none") {
Log3 $name, 1, "$name: Define, device is none, commands will be echoed only";
$attr{$name}{dummy} = 1;
#return undef;
}
-
+
if ($dev ne "none" && $dev =~ m/[a-zA-Z]/ && $dev !~ m/\@/) { # bei einer IP wird kein \@57600 angehaengt
$dev .= "\@57600";
- }
-
+ }
+
#$hash->{CMDS} = "";
$hash->{Clients} = $clientsSIGNALduino;
$hash->{MatchList} = \%matchListSIGNALduino;
$hash->{DeviceName} = $dev;
- $hash->{logMethod} = \&main::Log3;
-
+ $hash->{logMethod} = \&main::Log3;
+
my $ret=undef;
-
+
InternalTimer(gettimeofday(), 'SIGNALduino_IdList',"sduino_IdList:$name",0); # verzoegern bis alle Attribute eingelesen sind
-
+
if($dev ne "none") {
$ret = DevIo_OpenDev($hash, 0, "SIGNALduino_DoInit", 'SIGNALduino_Connect');
} else {
$hash->{DevState} = 'initialized';
readingsSingleUpdate($hash, "state", "opened", 1);
}
-
+
$hash->{DMSG}="nothing";
$hash->{LASTDMSG} = "nothing";
$hash->{LASTDMSGID} = "nothing";
@@ -402,7 +420,7 @@ sub SIGNALduino_Define($$) {
#notifyRegexpChanged($hash,"^$name$:^opened\$"); # Auf das Event opened der eigenen Definition reagieren
#notifyRegexpChanged($hash,"sduino:opened"); # Auf das Event opened der eigenen Definition reagieren
#$hash->{NOTIFYDEV}="$name";
- Log3 $name, 3, "$name: Define, Firmwareversion: ".$hash->{READINGS}{version}{VAL} if ($hash->{READINGS}{version}{VAL});
+ #Log3 $name, 3, "$name: Define, Firmwareversion: ".$hash->{READINGS}{version}{VAL} if ($hash->{READINGS}{version}{VAL});
return $ret;
}
@@ -422,7 +440,7 @@ sub SIGNALduino_Connect($$) {
sub SIGNALduino_Undef($$) {
my ($hash, $arg) = @_;
my $name = $hash->{NAME};
-
+
foreach my $d (sort keys %defs) {
if(defined($defs{$d}) &&
defined($defs{$d}{IODev}) &&
@@ -435,9 +453,9 @@ sub SIGNALduino_Undef($$) {
}
SIGNALduino_Shutdown($hash);
-
- DevIo_CloseDev($hash);
- RemoveInternalTimer($hash);
+
+ DevIo_CloseDev($hash);
+ RemoveInternalTimer($hash);
return undef;
}
@@ -450,16 +468,16 @@ sub SIGNALduino_Shutdown($) {
}
###############################
-sub SIGNALduino_flash($) {
+sub SIGNALduino_avrdude($) {
my $name = shift;
my $hash = $defs{$name};
-
+
if (defined($hash->{helper}{stty_pid}))
{
waitpid( $hash->{helper}{stty_pid}, 0 );
delete ( $hash->{helper}{stty_pid});
}
-
+
readingsSingleUpdate($hash,"state","FIRMWARE UPDATE running",1);
$hash->{helper}{avrdudelogs} .= "$name closed\n";
my $logFile = AttrVal("global", "logdir", "./log/") . "$hash->{TYPE}-Flash.log";
@@ -478,14 +496,14 @@ sub SIGNALduino_flash($) {
if ($? != 0 )
{
readingsSingleUpdate($hash,"state","FIRMWARE UPDATE with error",1); # processed in tests
- $hash->{logMethod}->($name ,3, "$name: flash, ERROR: avrdude exited with error $?");
+ $hash->{logMethod}->($name ,3, "$name: avrdude, ERROR: avrdude exited with error $?");
FW_directNotify("FILTER=$name", "#FHEMWEB:WEB", "FW_okDialog('ERROR: avrdude exited with error, for details see last flashlog.')", "");
$hash->{FLASH_RESULT}="ERROR: avrdude exited with error"; # processed in tests
} else {
- $hash->{logMethod}->($name ,3, "$name: flash, Firmware update was successfull");
+ $hash->{logMethod}->($name ,3, "$name: avrdude, Firmware update was successfull");
readingsSingleUpdate($hash,"state","FIRMWARE UPDATE successfull",1); # processed in tests
}
-
+
local $/=undef;
if (-e $logFile) {
open FILE, $logFile;
@@ -498,257 +516,212 @@ sub SIGNALduino_flash($) {
readingsSingleUpdate($hash,"state","FIRMWARE UPDATE with error",1);
$hash->{FLASH_RESULT}= "WARNING: avrdude created no log file"; # processed in tests
}
-
+
DevIo_OpenDev($hash, 0, "SIGNALduino_DoInit", 'SIGNALduino_Connect');
$hash->{helper}{avrdudelogs} .= "$name reopen started\n";
return $hash->{FLASH_RESULT};
}
+###############################
+sub SIGNALduino_PrepareFlash {
+ my ($hash,$hexFile) = @_;
+
+ my $name=$hash->{NAME};
+ my $hardware=AttrVal($name,"hardware","");
+ my ($port,undef) = split('@', $hash->{DeviceName});
+ my $baudrate= 57600;
+ my $log = "";
+ my $avrdudefound=0;
+ my $tool_name = "avrdude";
+ my $path_separator = ':';
+ if ($^O eq 'MSWin32') {
+ $tool_name .= ".exe";
+ $path_separator = ';';
+ }
+ for my $path ( split /$path_separator/, $ENV{PATH} ) {
+ if ( -f "$path/$tool_name" && -x _ ) {
+ $avrdudefound=1;
+ last;
+ }
+ }
+ $hash->{logMethod}->($name, 5, "$name: PrepareFlash, avrdude found = $avrdudefound");
+ return "avrdude is not installed. Please provide avrdude tool example: sudo apt-get install avrdude" if($avrdudefound == 0);
+
+ $log .= "flashing Arduino $name\n";
+ $log .= "hex file: $hexFile\n";
+ $log .= "port: $port\n";
+
+ # prepare default Flashcommand
+ my $defaultflashCommand = ($hardware eq "radinoCC1101" ? "avrdude -c avr109 -b [BAUDRATE] -P [PORT] -p atmega32u4 -vv -D -U flash:w:[HEXFILE] 2>[LOGFILE]" : "avrdude -c arduino -b [BAUDRATE] -P [PORT] -p atmega328p -vv -U flash:w:[HEXFILE] 2>[LOGFILE]");
+
+ # get User defined Flashcommand
+ my $flashCommand = AttrVal($name,"flashCommand",$defaultflashCommand);
+
+ if ($defaultflashCommand eq $flashCommand) {
+ $hash->{logMethod}->($name, 5, "$name: PrepareFlash, standard flashCommand is used to flash.");
+ } else {
+ $hash->{logMethod}->($name, 3, "$name: PrepareFlash, custom flashCommand is manual defined! $flashCommand");
+ }
+
+ DevIo_CloseDev($hash);
+ if ($hardware eq "radinoCC1101" && $^O eq 'linux') {
+ $hash->{logMethod}->($name, 3, "$name: PrepareFlash, forcing special reset for $hardware on $port");
+ # Mit dem Linux-Kommando 'stty' die Port-Einstellungen setzen
+ use IPC::Open3;
+
+ my($chld_out, $chld_in, $chld_err);
+ use Symbol 'gensym';
+ $chld_err = gensym;
+ my $pid;
+ eval {
+ $pid = open3($chld_in,$chld_out, $chld_err, "stty -F $port ospeed 1200 ispeed 1200");
+ close($chld_in); # give end of file to kid, or feed him
+ };
+ if ($@) {
+ $hash->{helper}{stty_output}=$@;
+ } else {
+ my @outlines = <$chld_out>; # read till EOF
+ my @errlines = <$chld_err>; # XXX: block potential if massive
+ $hash->{helper}{stty_pid}=$pid;
+ $hash->{helper}{stty_output} = join(" ",@outlines).join(" ",@errlines);
+ }
+ $port =~ s/usb-Unknown_radino/usb-In-Circuit_radino/g;
+ $hash->{logMethod}->($name ,3, "$name: PrepareFlash, changed usb port to \"$port\" for avrdude flashcommand compatible with radino");
+ }
+ $hash->{helper}{avrdudecmd} = $flashCommand;
+ $hash->{helper}{avrdudecmd}=~ s/\Q[PORT]\E/$port/g;
+ $hash->{helper}{avrdudecmd} =~ s/\Q[HEXFILE]\E/$hexFile/g;
+ if ($hardware =~ "^nano" && $^O eq 'linux') {
+ $hash->{logMethod}->($name ,5, "$name: PrepareFlash, try additional flash with baudrate 115200 for optiboot");
+ $hash->{helper}{avrdudecmd} = $hash->{helper}{avrdudecmd}." || ". $hash->{helper}{avrdudecmd};
+ $hash->{helper}{avrdudecmd} =~ s/\Q[BAUDRATE]\E/$baudrate/;
+ $baudrate=115200;
+ }
+ $hash->{helper}{avrdudecmd} =~ s/\Q[BAUDRATE]\E/$baudrate/;
+ $log .= "command: $hash->{helper}{avrdudecmd}\n\n";
+ InternalTimer(gettimeofday() + 1,"SIGNALduino_avrdude",$name);
+ $hash->{helper}{avrdudelogs} = $log;
+ return undef;
+}
#$hash,$name,"sendmsg","P17;R6#".substr($arg,2)
###############################
sub SIGNALduino_Set($$@) {
- my ($hash,$name, @a) = @_;
-
- return "\"set SIGNALduino\" needs at least one parameter" if(@a < 1);
+ my ($hash,$name, @a) = @_;
- #SIGNALduino_Log3 $hash, 3, "$name: Set, called with params @a";
+ return "\"set SIGNALduino\" needs at least one parameter" if(@a < 1);
+
+ if (!InternalVal($name,"cc1101_available",0) && $a[0] =~ /^cc1101/) {
+ return "This command is only available with a cc1101 receiver";
+ }
+ if (!exists($sets{$a[0]})) {
+ return "Unknown argument $a[0], choose one of supported commands";
+ }
+ my $rcode=undef;
+ if ( ( (exists($hash->{DevState}) && $hash->{DevState} eq "initialized") || $a[0] eq "?" || $a[0] eq 'reset'|| $a[0] eq 'flash') && ref @{$sets{$a[0]}}[1] eq "CODE") { #Todo uninitalized value
+ $rcode= @{$sets{$a[0]}}[1]->($hash,@a);
+ } elsif ($hash->{DevState} ne "initialized") {
+ $rcode= "$name is not active, may firmware is not supported, please flash or reset";
+ }
+
+ return $rcode; # We will exit here, and give an output only, $rcode has some value
+}
- my $CC1101Frequency;
- if (exists($hash->{hasCC1101}) && InternalVal($name,"hasCC1101",0)) {
- if (!defined($hash->{cc1101_frequency})) {
- $CC1101Frequency = "433";
- } else {
- $CC1101Frequency = $hash->{cc1101_frequency};
- }
- }
- my %my_sets = %sets;
- %my_sets = ( %my_sets, %{$hash->{additionalSets}} ) if ( defined($hash->{additionalSets}) );
-
- if (!defined($my_sets{$a[0]})) {
- my $arguments = ' ';
- foreach my $arg (sort keys %my_sets) {
- next if ($arg =~ m/cc1101/ && !InternalVal($name,"hasCC1101",0));
- if ($arg =~ m/patable/) {
- next if (substr($arg, -3) ne $CC1101Frequency);
- }
- $arguments.= $arg . ($my_sets{$arg} ? (':' . $my_sets{$arg}) : '') . ' ';
- }
- #SIGNALduino_Log3 $hash, 3, "$name: Set, arg = $arguments";
- return "Unknown argument $a[0], choose one of " . $arguments;
- }
+###############################
+sub SIGNALduino_Set_FhemWebList {
+ my ($hash, @a) = @_;
+ my @cList = sort map { "$_:@{$sets{$_}}[0]" } grep {
+ ($_ ne "?" &&
+ (
+ ( IsDummy($hash->{NAME}) && $_ =~ m/^(?:close|reset)/ ) ||
+ ( InternalVal($hash->{NAME},"cc1101_available",0) || (!InternalVal($hash->{NAME},"cc1101_available",0) && $_ !~ /^cc/)) &&
+ ( !IsDummy($hash->{NAME}) && (defined(DevIo_IsOpen($hash)) || $_ =~ m/^(?:flash|reset)/) )
+ )
+ )
+ } keys %sets;
+ map {
+ my $set_key=$_;
+ my ($index) = grep { $cList[$_] =~ /^$set_key:/ } (0 .. $#cList-1);
+ $cList[$index] = "$set_key:".$hash->{additionalSets}{$set_key} if (defined($index));
+ } keys %{$hash->{additionalSets}};
+ return "Unknown argument $a[0], choose one of " . join(" ", @cList);
+}
- my $cmd = shift @a;
- my $arg = join(" ", @a);
-
- if ($cmd =~ m/cc1101/ && !InternalVal($name,"hasCC1101",0)) {
- return "This command is only available with a cc1101 receiver";
- }
-
- return "$name is not active, may firmware is not suppoted, please flash or reset" if ($cmd ne 'reset' && $cmd ne 'flash' && exists($hash->{DevState}) && $hash->{DevState} ne 'initialized');
+sub SIGNALduino_Set_raw {
+ my ($hash, @a) = @_;
+ $hash->{logMethod}->($hash->{NAME}, 4, "$hash->{NAME}: Set_raw, ".join(" ",@a));
+ SIGNALduino_AddSendQueue($hash,$a[1]);
+ return undef;
+}
- if ($cmd =~ m/^cc1101_/) {
- $cmd = substr($cmd,7);
- }
-
- if($cmd eq "raw") {
- $hash->{logMethod}->($name, 4, "$name: Set, $cmd $arg");
- #SIGNALduino_SimpleWrite($hash, $arg);
- SIGNALduino_AddSendQueue($hash,$arg);
- } elsif( $cmd eq "flash" ) {
- my @args = split(' ', $arg);
- my $log = "";
- my $hexFile = "";
- my ($port,undef) = split('@', $hash->{DeviceName});
- my $hardware=AttrVal($name,"hardware","");
- my $baudrate= 57600;
- return "Please define your hardware! (attr $name hardware ) " if ($hardware eq "");
+###############################
+ sub SIGNALduino_Set_flash {
+ my ($hash, @a) = @_;
+ my $name = $hash->{NAME};
+ return "Please define your hardware! (attr $name hardware ) " if (AttrVal($name,"hardware","") eq "");
+
+ my @args = @a[1..$#a];
return "ERROR: argument failed! flash [hexFile|url]" if (!$args[0]);
-
- if( grep $args[0] eq $_ , split(",",$my_sets{flash}) )
+
+ my %http_param = (
+ timeout => 5,
+ hash => $hash, # Muss gesetzt werden, damit die Callback funktion wieder $hash hat
+ method => "GET", # Lesen von Inhalten
+ header => "User-Agent: perl_fhem\r\nAccept: application/json", # Den Header gemaess abzufragender Daten aendern
+ );
+
+ my $hexFile = "";
+ if( grep $args[0] eq $_ , split(",",$hash->{additionalSets}{flash}) )
{
- $hash->{logMethod}->($hash, 3, "$name: Set, flash $args[0] try to fetch github assets for tag $args[0]");
-
+ $hash->{logMethod}->($hash, 3, "$name: Set_flash, $args[0] try to fetch github assets for tag $args[0]");
my $ghurl = "https://api.github.com/repos/RFD-FHEM/SIGNALDuino/releases/tags/$args[0]";
+ $hash->{logMethod}->($hash, 3, "$name: Set_flash, $args[0] try to fetch release $ghurl");
- $hash->{logMethod}->($hash, 3, "$name: Set, flash $args[0] try to fetch release $ghurl");
-
- my $http_param = {
- url => $ghurl,
- timeout => 5,
- hash => $hash, # Muss gesetzt werden, damit die Callback funktion wieder $hash hat
- method => "GET", # Lesen von Inhalten
- header => "User-Agent: perl_fhem\r\nAccept: application/json", # Den Header gemaess abzufragender Daten aendern
- callback => \&SIGNALduino_githubParseHttpResponse, # Diese Funktion soll das Ergebnis dieser HTTP Anfrage bearbeiten
- command => "getReleaseByTag"
-
- };
- HttpUtils_NonblockingGet($http_param); # Starten der HTTP Abfrage. Es gibt keinen Return-Code.
+ $http_param{url} = $ghurl;
+ $http_param{callback} = \&SIGNALduino_githubParseHttpResponse; # Diese Funktion soll das Ergebnis dieser HTTP Anfrage bearbeiten
+ $http_param{command} = "getReleaseByTag";
+ HttpUtils_NonblockingGet(\%http_param); # Starten der HTTP Abfrage. Es gibt keinen Return-Code.
return;
- }
+ }
elsif ($args[0] =~ m/^https?:\/\// ) {
- my $http_param = {
- url => $args[0],
- timeout => 5,
- hash => $hash, # Muss gesetzt werden, damit die Callback funktion wieder $hash hat
- method => "GET", # Lesen von Inhalten
- callback => \&SIGNALduino_ParseHttpResponse, # Diese Funktion soll das Ergebnis dieser HTTP Anfrage bearbeiten
- command => 'flash',
- };
-
- HttpUtils_NonblockingGet($http_param);
- return;
+ $http_param{url} = $args[0];
+ $http_param{callback} = \&SIGNALduino_ParseHttpResponse; # Diese Funktion soll das Ergebnis dieser HTTP Anfrage bearbeiten
+ $http_param{command} = "flash";
+ HttpUtils_NonblockingGet(\%http_param);
+ return;
} else {
$hexFile = $args[0];
}
- $hash->{logMethod}->($name, 3, "$name: Set, filename $hexFile provided, trying to flash");
-
+ $hash->{logMethod}->($name, 3, "$name: Set_flash, filename $hexFile provided, trying to flash");
# Only for Arduino , not for ESP
- if ($hardware =~ m/(?:nano|mini|radino)/)
+ if (AttrVal($name,"hardware","") =~ m/(?:nano|mini|radino)/)
{
-
- my $avrdudefound=0;
- my $tool_name = "avrdude";
- my $path_separator = ':';
- if ($^O eq 'MSWin32') {
- $tool_name .= ".exe";
- $path_separator = ';';
- }
- for my $path ( split /$path_separator/, $ENV{PATH} ) {
- if ( -f "$path/$tool_name" && -x _ ) {
- $avrdudefound=1;
- last;
- }
- }
- $hash->{logMethod}->($name, 5, "$name: Set, avrdude found = $avrdudefound");
- return "avrdude is not installed. Please provide avrdude tool example: sudo apt-get install avrdude" if($avrdudefound == 0);
-
- $log .= "flashing Arduino $name\n";
- $log .= "hex file: $hexFile\n";
- $log .= "port: $port\n";
-
- # prepare default Flashcommand
- my $defaultflashCommand = ($hardware eq "radinoCC1101" ? "avrdude -c avr109 -b [BAUDRATE] -P [PORT] -p atmega32u4 -vv -D -U flash:w:[HEXFILE] 2>[LOGFILE]" : "avrdude -c arduino -b [BAUDRATE] -P [PORT] -p atmega328p -vv -U flash:w:[HEXFILE] 2>[LOGFILE]");
-
- # get User defined Flashcommand
- my $flashCommand = AttrVal($name,"flashCommand",$defaultflashCommand);
-
- if ($defaultflashCommand eq $flashCommand) {
- $hash->{logMethod}->($name, 5, "$name: Set, standard flashCommand is used to flash.");
- } else {
- $hash->{logMethod}->($name, 3, "$name: Set, custom flashCommand is manual defined! $flashCommand");
- }
-
- DevIo_CloseDev($hash);
- if ($hardware eq "radinoCC1101" && $^O eq 'linux') {
- $hash->{logMethod}->($name, 3, "$name: Set, forcing special reset for $hardware on $port");
- # Mit dem Linux-Kommando 'stty' die Port-Einstellungen setzen
- use IPC::Open3;
-
- my($chld_out, $chld_in, $chld_err);
- use Symbol 'gensym';
- $chld_err = gensym;
- my $pid;
- eval {
- $pid = open3($chld_in,$chld_out, $chld_err, "stty -F $port ospeed 1200 ispeed 1200");
- close($chld_in); # give end of file to kid, or feed him
- };
- if ($@) {
- $hash->{helper}{stty_output}=$@;
- } else {
- my @outlines = <$chld_out>; # read till EOF
- my @errlines = <$chld_err>; # XXX: block potential if massive
- $hash->{helper}{stty_pid}=$pid;
- $hash->{helper}{stty_output} = join(" ",@outlines).join(" ",@errlines);
- }
- $port =~ s/usb-Unknown_radino/usb-In-Circuit_radino/g;
- $hash->{logMethod}->($name ,3, "$name: Set, changed usb port to \"$port\" for avrdude flashcommand compatible with radino");
- }
- $hash->{helper}{avrdudecmd} = $flashCommand;
- $hash->{helper}{avrdudecmd}=~ s/\Q[PORT]\E/$port/g;
- $hash->{helper}{avrdudecmd} =~ s/\Q[HEXFILE]\E/$hexFile/g;
- if ($hardware =~ "^nano" && $^O eq 'linux') {
- $hash->{logMethod}->($name ,5, "$name: Set, try additional flash with baudrate 115200 for optiboot");
- $hash->{helper}{avrdudecmd} = $hash->{helper}{avrdudecmd}." || ". $hash->{helper}{avrdudecmd};
- $hash->{helper}{avrdudecmd} =~ s/\Q[BAUDRATE]\E/$baudrate/;
- $baudrate=115200;
- }
- $hash->{helper}{avrdudecmd} =~ s/\Q[BAUDRATE]\E/$baudrate/;
- $log .= "command: $hash->{helper}{avrdudecmd}\n\n";
- InternalTimer(gettimeofday() + 1,"SIGNALduino_flash",$name);
- $hash->{helper}{avrdudelogs} = $log;
- return undef;
+ SIGNALduino_PrepareFlash($hash,$hexFile);
} else {
FW_directNotify("FILTER=$name", "#FHEMWEB:WEB", "FW_okDialog('ERROR:
Sorry, flashing your ESP is currently not supported.
The file is only downloaded in /opt/fhem/FHEM/firmware.')", "");
return "Sorry, Flashing your ESP via Module is currently not supported."; # processed in tests
}
-
- } elsif ($cmd =~ m/reset/i) {
+}
+
+
+###############################
+sub SIGNALduino_Set_reset
+{
+ my $hash = shift;
delete($hash->{initResetFlag}) if defined($hash->{initResetFlag});
return SIGNALduino_ResetDevice($hash);
- } elsif( $cmd eq "close" ) {
- $hash->{DevState} = 'closed';
- return SIGNALduino_CloseDevice($hash);
- } elsif( $cmd eq "disableMessagetype" ) {
- my $argm = 'CD' . substr($arg,-1,1);
- #SIGNALduino_SimpleWrite($hash, $argm);
- SIGNALduino_AddSendQueue($hash,$argm);
- $hash->{logMethod}->($name, 4, "$name: Set, $cmd $arg $argm");
- } elsif( $cmd eq "enableMessagetype" ) {
- my $argm = 'CE' . substr($arg,-1,1);
- #SIGNALduino_SimpleWrite($hash, $argm);
- SIGNALduino_AddSendQueue($hash,$argm);
- $hash->{logMethod}->($name, 4, "$name: Set, $cmd $arg $argm");
- } elsif( $cmd eq "freq" ) {
- if ($arg eq "") {
- $arg = AttrVal($name,"cc1101_frequency", 433.92);
- }
- my $f = $arg/26*65536;
- my $f2 = sprintf("%02x", $f / 65536);
- my $f1 = sprintf("%02x", int($f % 65536) / 256);
- my $f0 = sprintf("%02x", $f % 256);
- $arg = sprintf("%.3f", (hex($f2)*65536+hex($f1)*256+hex($f0))/65536*26);
- $hash->{logMethod}->($name, 3, "$name: Set, Setting FREQ2..0 (0D,0E,0F) to $f2 $f1 $f0 = $arg MHz");
- SIGNALduino_AddSendQueue($hash,"W0F$f2");
- SIGNALduino_AddSendQueue($hash,"W10$f1");
- SIGNALduino_AddSendQueue($hash,"W11$f0");
- SIGNALduino_WriteInit($hash);
- } elsif( $cmd eq "bWidth" ) {
- SIGNALduino_AddSendQueue($hash,"C10");
- $hash->{getcmd}->{cmd} = "bWidth";
- $hash->{getcmd}->{arg} = $arg;
- } elsif( $cmd eq "rAmpl" ) {
- return "a numerical value between 24 and 42 is expected" if($arg !~ m/^\d+$/ || $arg < 24 || $arg > 42);
- my ($v, $w);
- for($v = 0; $v < @ampllist; $v++) {
- last if($ampllist[$v] > $arg);
- }
- $v = sprintf("%02d", $v-1);
- $w = $ampllist[$v];
- $hash->{logMethod}->($name, 3, "$name: Set, Setting AGCCTRL2 (1B) to $v / $w dB");
- SIGNALduino_AddSendQueue($hash,"W1D$v");
- SIGNALduino_WriteInit($hash);
- } elsif( $cmd eq "sens" ) {
- return "a numerical value between 4 and 16 is expected" if($arg !~ m/^\d+$/ || $arg < 4 || $arg > 16);
- my $w = int($arg/4)*4;
- my $v = sprintf("9%d",$arg/4-1);
- $hash->{logMethod}->($name, 3, "$name: Set, Setting AGCCTRL0 (1D) to $v / $w dB");
- SIGNALduino_AddSendQueue($hash,"W1F$v");
- SIGNALduino_WriteInit($hash);
- } elsif( substr($cmd,0,7) eq "patable" ) {
- my $paFreq = substr($cmd,8);
- my $pa = "x" . $patable{$paFreq}{$arg};
- $hash->{logMethod}->($name, 3, "$name: Set, Setting patable $paFreq $arg $pa");
- SIGNALduino_AddSendQueue($hash,$pa);
- SIGNALduino_WriteInit($hash);
- } elsif( $cmd eq "sendMsg" ) {
- $hash->{logMethod}->($name, 5, "$name: Set, sendmsg msg=$arg");
-
+}
+
+###############################
+sub SIGNALduino_Set_sendMsg {
+ my ($hash, @a) = @_;
+ $hash->{logMethod}->($hash->{NAME}, 5, "$hash->{NAME}: Set_sendMsg, msg=$a[1]");
+
# Split args in serval variables
my ($protocol,$data,$repeats,$clock,$frequency,$datalength,$dataishex);
my $n=0;
- foreach my $s (split "#", $arg) {
+ foreach my $s (split "#", $a[1]) {
my $c = substr($s,0,1);
if ($n == 0 ) { # protocol
$protocol = substr($s,1);
@@ -756,7 +729,7 @@ sub SIGNALduino_Set($$@) {
$data = $s;
if ( substr($s,0,2) eq "0x" ) { $dataishex=1; $data=substr($data,2); }
else { $dataishex=0; }
-
+
} else {
if ($c eq 'R') { $repeats = substr($s,1); }
elsif ($c eq 'C') { $clock = substr($s,1); }
@@ -765,42 +738,33 @@ sub SIGNALduino_Set($$@) {
}
$n++;
}
- return "$name: sendmsg, unknown protocol: $protocol" if (!exists($ProtocolListSIGNALduino{$protocol}));
+ return "$hash->{NAME}: sendmsg, unknown protocol: $protocol" if (!exists($ProtocolListSIGNALduino{$protocol}));
$repeats=1 if (!defined($repeats));
- if (exists($ProtocolListSIGNALduino{$protocol}{frequency}) && InternalVal($name,"hasCC1101",0) && !defined($frequency)) {
+ if (exists($ProtocolListSIGNALduino{$protocol}{frequency}) && InternalVal($hash->{NAME},"cc1101_available",0) && !defined($frequency)) {
$frequency = $ProtocolListSIGNALduino{$protocol}{frequency};
}
- if (defined($frequency) && InternalVal($name,"hasCC1101",0)) {
+ if (defined($frequency) && InternalVal($hash->{NAME},"cc1101_available",0)) {
$frequency="F=$frequency;";
} else {
$frequency="";
}
-
- #print ("data = $data \n");
- #print ("protocol = $protocol \n");
- #print ("repeats = $repeats \n");
-
+
my %signalHash;
my %patternHash;
my $pattern="";
my $cnt=0;
-
+
my $sendData;
if (exists($ProtocolListSIGNALduino{$protocol}{format}) && $ProtocolListSIGNALduino{$protocol}{format} eq 'manchester')
{
- #$clock = (map { $clock += $_ } @{$ProtocolListSIGNALduino{$protocol}{clockrange}}) / 2 if (!defined($clock));
-
$clock += $_ for(@{$ProtocolListSIGNALduino{$protocol}{clockrange}});
$clock = round($clock/2,0);
- if ($protocol == 43) {
- #$data =~ tr/0123456789ABCDEF/FEDCBA9876543210/;
- }
-
+
my $intro = "";
my $outro = "";
-
+
$intro = $ProtocolListSIGNALduino{$protocol}{msgIntro} if ($ProtocolListSIGNALduino{$protocol}{msgIntro});
$outro = $ProtocolListSIGNALduino{$protocol}{msgOutro}.";" if ($ProtocolListSIGNALduino{$protocol}{msgOutro});
@@ -811,7 +775,7 @@ sub SIGNALduino_Set($$@) {
}
$sendData = $intro . "SM;" . ($repeats > 0 ? "R=$repeats;" : "") . "C=$clock;D=$data;" . $outro . $frequency; # SM;R=2;C=400;D=AFAFAF;
- $hash->{logMethod}->($name, 5, "$name: Set, sendmsg Preparing manchester protocol=$protocol, repeats=$repeats, clock=$clock data=$data");
+ $hash->{logMethod}->($hash->{NAME}, 5, "$hash->{NAME}: Set_sendMsg, Preparing manchester protocol=$protocol, repeats=$repeats, clock=$clock data=$data");
} else {
if ($protocol == 3 || substr($data,0,2) eq "is") {
@@ -819,234 +783,445 @@ sub SIGNALduino_Set($$@) {
$data = substr($data,2); # is am Anfang entfernen
}
$data = SIGNALduino_ITV1_tristateToBit($data);
- $hash->{logMethod}->($name, 5, "$name: Set, sendmsg IT V1 convertet tristate to bits=$data");
+ $hash->{logMethod}->($hash->{NAME}, 5, "$hash->{NAME}: Set_sendMsg, IT V1 convertet tristate to bits=$data");
}
if (!defined($clock)) {
$hash->{ITClock} = 250 if (!defined($hash->{ITClock})); # Todo: Klaeren wo ITClock verwendet wird und ob wir diesen Teil nicht auf Protokoll 3,4 und 17 minimieren
$clock=$ProtocolListSIGNALduino{$protocol}{clockabs} > 1 ?$ProtocolListSIGNALduino{$protocol}{clockabs}:$hash->{ITClock};
}
-
- if ($dataishex == 1)
+
+ if ($dataishex == 1)
{
# convert hex to bits
my $hlen = length($data);
my $blen = $hlen * 4;
$data = unpack("B$blen", pack("H$hlen", $data));
}
+ $hash->{logMethod}->($hash->{NAME}, 5, "$hash->{NAME}: Set_sendMsg, Preparing rawsend command for protocol=$protocol, repeats=$repeats, clock=$clock bits=$data");
- $hash->{logMethod}->($name, 5, "$name: Set, sendmsg Preparing rawsend command for protocol=$protocol, repeats=$repeats, clock=$clock bits=$data");
-
foreach my $item (qw(preSync sync start one zero float pause end universal))
{
- #print ("item= $item \n");
next if (!exists($ProtocolListSIGNALduino{$protocol}{$item}));
-
+
foreach my $p (@{$ProtocolListSIGNALduino{$protocol}{$item}})
{
- #print (" p = $p \n");
-
if (!exists($patternHash{$p}))
{
$patternHash{$p}=$cnt;
- $pattern.="P".$patternHash{$p}."=".$p*$clock.";";
+ $pattern.="P".$patternHash{$p}."=". int($p*$clock) .";";
$cnt++;
}
$signalHash{$item}.=$patternHash{$p};
- #print (" signalHash{$item} = $signalHash{$item} \n");
}
}
my @bits = split("", $data);
-
+
my %bitconv = (1=>"one", 0=>"zero", 'D'=> "float", 'F'=> "float", 'P'=> "pause", 'U'=> "universal");
my $SignalData="D=";
-
+
$SignalData.=$signalHash{preSync} if (exists($signalHash{preSync}));
$SignalData.=$signalHash{sync} if (exists($signalHash{sync}));
$SignalData.=$signalHash{start} if (exists($signalHash{start}));
foreach my $bit (@bits)
{
next if (!exists($bitconv{$bit}));
- #SIGNALduino_Log3 $name, 5, "$name: Set, encoding $bit";
$SignalData.=$signalHash{$bitconv{$bit}}; ## Add the signal to our data string
}
$SignalData.=$signalHash{end} if (exists($signalHash{end}));
$sendData = "SR;R=$repeats;$pattern$SignalData;$frequency";
}
-
-
- #SIGNALduino_SimpleWrite($hash, $sendData);
SIGNALduino_AddSendQueue($hash,$sendData);
- $hash->{logMethod}->($name, 4, "$name: Set, sending via SendMsg: $sendData");
- } else {
- $hash->{logMethod}->($name, 5, "$name: Set, $cmd $arg");
- #SIGNALduino_SimpleWrite($hash, $arg);
- return "Unknown argument $cmd, choose one of ". ReadingsVal($name,'cmd',' help me');
- }
-
- return undef;
+ $hash->{logMethod}->($hash->{NAME}, 4, "$hash->{NAME}: Set_sendMsg, sending : $sendData");
}
+###############################
+sub SIGNALduino_Set_close {
+ my $hash = shift;
+ $hash->{DevState} = 'closed';
+ return SIGNALduino_CloseDevice($hash);
+}
+
+###############################
+sub SIGNALduino_Set_MessageType
+{
+ my ($hash, @a) = @_;
+ my $argm;
+ if ($a[0] =~ /^enable/) {
+ $argm = 'CE' . substr($a[1],-1,1);
+ } else {
+ $argm = 'CD' . substr($a[1],-1,1);
+ }
+ SIGNALduino_AddSendQueue($hash,$argm);
+ $hash->{logMethod}->($hash->{NAME}, 4, "$hash->{NAME}: Set_MessageType, $a[0] $a[1] $argm");
+}
+
+###############################
+sub SIGNALduino_Set_bWidth
+{
+ my ($hash, @a) = @_;
+
+ if (exists($hash->{ucCmd}->{cmd}) && $hash->{ucCmd}->{cmd} eq "set_bWidth" && $a[0] =~ /^C10\s=\s([A-Fa-f0-9]{2})$/ )
+ {
+ my ($ob,$bw) = cc1101::CalcbWidthReg($hash,$1,$hash->{ucCmd}->{arg});
+ $hash->{logMethod}->($hash->{NAME}, 3, "$hash->{NAME}: Set_bWidth, bWidth: Setting MDMCFG4 (10) to $ob = $bw KHz");
+ # Toddo setRegisters verwenden
+ main::SIGNALduino_AddSendQueue($hash,"W12$ob");
+ main::SIGNALduino_WriteInit($hash);
+ return ("Setting MDMCFG4 (10) to $ob = $bw KHz" ,undef);
+ } else {
+ $hash->{logMethod}->($hash->{NAME}, 3, "$hash->{NAME}: Set_bWidth, Request register 10");
+ # Get Register 10
+ cc1101::GetRegister($hash,10);
+
+ $hash->{ucCmd}->{cmd} = "set_bWidth";
+ $hash->{ucCmd}->{arg} = $a[1]; # Zielbandbreite
+ $hash->{ucCmd}->{responseSub} = \&SIGNALduino_Set_bWidth; # Callback auf sich selbst setzen
+ $hash->{ucCmd}->{asyncOut} = $hash->{CL} if (defined($hash->{CL}));
+ $hash->{ucCmd}->{timenow}=time();
+ #return "Register 10 requested";
+ return undef;
+ }
+}
+
+
###############################
sub SIGNALduino_Get($@) {
- my ($hash, @a) = @_;
- my $type = $hash->{TYPE};
- my $name = $hash->{NAME};
- return "$name is not active, may firmware is not suppoted, please flash or reset" if (exists($hash->{DevState}) && $hash->{DevState} ne 'initialized');
-
- $hash->{logMethod}->($name, 5, "$name: Get, $type\" needs at least one parameter") if(@a < 2);
- return "\"get $type\" needs at least one parameter" if(@a < 2);
- if(!defined($gets{$a[1]})) {
- Log3 ($name, 5, "Unknown argument $a[1] for $a[0]") if ($a[1] ne "?");
- my @cList = sort map { $_ =~ m/^(raw|ccreg)$/ ? $_ : "$_:noArg" } grep { (( InternalVal($a[0],"hasCC1101",0) || (!InternalVal($a[0],"hasCC1101",0) && $_ !~ /^cc/)) && (!IsDummy($a[0]) || IsDummy($a[0]) && $_ =~ m/^(availableFirmware|raw)/)) } keys %gets;
- return "Unknown argument $a[1], choose one of " . join(" ", @cList);
- }
- return "no command to send, get aborted." if (ref $gets{$a[1]} eq 'ARRAY' && length($gets{$a[1]}[0]) == 0 && length($a[2]) == 0);
-
- if (($a[1] eq "ccconf" || $a[1] eq "ccreg" || $a[1] eq "ccpatable") && !InternalVal($name,"hasCC1101",0)) {
+ my ($hash,$name, @a) = @_;
+ #my $type = $hash->{TYPE};
+
+ return "\"get SIGNALduino\" needs at least one parameter" if(@a < 1);
+
+ if (!InternalVal($name,"cc1101_available",0) && $a[0] =~ /^cc/) {
return "This command is only available with a cc1101 receiver";
}
-
- if (ref $gets{$a[1]} eq 'ARRAY') { # Option 1
- $hash->{logMethod}->($name, 5, "$name: Get, command for gets: " . $gets{$a[1]}[0] . " " . $a[2]);
- SIGNALduino_AddSendQueue($hash, $gets{$a[1]}[0] . $a[2]);
- $hash->{getcmd}->{cmd}=$a[1];
- $hash->{getcmd}->{asyncOut}=$hash->{CL};
- $hash->{getcmd}->{timenow}=time();
- } elsif ( ref $gets{$a[1]} eq 'CODE') { # Option 2
- return $gets{$a[1]}->($hash,@a);
+ if (!exists($gets{$a[0]})) {
+ return "Unknown argument $a[0], choose one of supported commands";
}
- return undef; # We will exit here, and give an output only, if any output is supported. If this is not supported, only the readings are updated
+ my $rcode=undef;
+ if (exists($hash->{ucCmd}) && $a[0] ne "?" ) {
+ SIGNALduino_Get_delayed("SIGNALduino_Get_delayed:$name:".join(":",@a));
+ }
+ elsif ( ($hash->{DevState} eq "initialized" || $a[0] eq "?" || $a[0] eq 'availableFirmware') && ref @{$gets{$a[0]}}[1] eq "CODE") { #
+ $rcode= @{$gets{$a[0]}}[1]->($hash,@a);
+ } elsif ($hash->{DevState} ne "initialized") {
+ $rcode= "$name is not active, may firmware is not supported, please flash or reset";
+ }
+
+ return $rcode; # We will exit here, and give an output only, $rcode has some value
+}
+
+
+
+###############################
+#SIGNALduino_Get_Callback($name, $callbackFn, @args);
+sub SIGNALduino_Get_Callback($$$) {
+ my ($name, $callbackFn, $arg) = @_;
+
+ my @a = split (" ",$arg);
+ return "\"get _Get_Callback\" needs at least two parameters" if(@a < 2);
+ return "\"$name\" is not a definition of type SIGNALduino" if (!IsDevice($name, "SIGNALduino"));
+
+ my $hash = $defs{$name};
+ my $rcode = SIGNALduino_Get($hash,$name,@a);
+
+ if (!defined($rcode))
+ {
+ $hash->{ucCmd}->{responseSub}=$callbackFn;
+ delete($hash->{ucCmd}->{asyncOut});
+ }
+
+ return $rcode; # We will exit here, and give an output only, $rcode has some value
+}
+
+
+###############################
+sub SIGNALduino_Get_FhemWebList {
+ my ($hash, @a) = @_;
+ my @cList = sort map { "$_:@{$gets{$_}}[0]" } grep {
+ ($_ ne "?" &&
+ (
+ (IsDummy($hash->{NAME}) && $_ =~ m/^(?:availableFirmware|raw)/) ||
+ ( InternalVal($hash->{NAME},"cc1101_available",0) || (!InternalVal($hash->{NAME},"cc1101_available",0) && $_ !~ /^cc/)) &&
+ ( !IsDummy($hash->{NAME}) && (defined(DevIo_IsOpen($hash)) || $_ =~ m/^(?:availableFirmware|raw)/ )) )
+ )
+ } keys %gets;
+ return "Unknown argument $a[0], choose one of " . join(" ", @cList);
+}
+
+
+###############################
+sub SIGNALduino_Get_availableFirmware {
+ my ($hash, @a) = @_;
+
+ if ($missingModulSIGNALduino =~ m/JSON/ )
+ {
+ $hash->{logMethod}->($hash->{NAME}, 1, "$hash->{NAME}: get $a[0] failed. Pleas install Perl module JSON. Example: sudo apt-get install libjson-perl");
+ return "$a[0]: \n\nFetching from github is not possible. Please install JSON. Example:
sudo apt-get install libjson-perl
";
+ }
+
+ my $channel=AttrVal($hash->{NAME},"updateChannelFW","stable");
+ my $hardware=AttrVal($hash->{NAME},"hardware",undef);
+
+ my ($validHw) = $modules{$hash->{TYPE}}{AttrList} =~ /.*hardware:(.*?)\s/;
+ $hash->{logMethod}->($hash->{NAME}, 1, "$hash->{NAME}: found availableFirmware for $validHw");
+
+ if (!defined($hardware) || $validHw !~ /$hardware(?:,|$)/ )
+ {
+ $hash->{logMethod}->($hash->{NAME}, 1, "$hash->{NAME}: get $a[0] failed. Please set attribute hardware first");
+ return "$a[0]: \n\n$hash->{NAME}: get $a[0] failed. Please choose one of $validHw attribute hardware";
+ }
+ SIGNALduino_querygithubreleases($hash);
+ return "$a[0]: \n\nFetching $channel firmware versions for $hardware from github\n";
}
###############################
-sub SIGNALduino_parseResponse($$$) {
- my $hash = shift;
- my $cmd = shift;
- my $msg = shift;
-
+sub SIGNALduino_Get_Command
+{
+ my ($hash, @a) = @_;
my $name=$hash->{NAME};
-
- $msg =~ s/[\r\n]//g;
-
- if($cmd eq "cmds")
- { # nice it up
- $msg =~ s/$name cmds =>//g;
- $msg =~ s/.*Use one of//g;
- }
- elsif($cmd eq "uptime")
- { # decode it
- #$msg = hex($msg); # /125; only for col or coc
- $msg = sprintf("%d %02d:%02d:%02d", $msg/86400, ($msg%86400)/3600, ($msg%3600)/60, $msg%60);
- }
- elsif($cmd eq "ccregAll")
- {
- $msg =~ s/ /\n/g;
- $msg = "\n\n" . $msg
- }
- elsif($cmd eq "ccconf")
- {
- my (undef,$str) = split('=', $msg);
- my $var;
- my %r = ( "0D"=>1,"0E"=>1,"0F"=>1,"10"=>1,"11"=>1,"1B"=>1,"1D"=>1 );
- $msg = "";
- foreach my $a (sort keys %r) {
- $var = substr($str,(hex($a)-13)*2, 2);
- $r{$a} = hex($var);
- }
- $msg = sprintf("freq:%.3fMHz bWidth:%dKHz rAmpl:%ddB sens:%ddB (DataRate:%.2fBaud)",
- 26*(($r{"0D"}*256+$r{"0E"})*256+$r{"0F"})/65536, #Freq
- 26000/(8 * (4+(($r{"10"}>>4)&3)) * (1 << (($r{"10"}>>6)&3))), #Bw
- $ampllist[$r{"1B"}&7], #rAmpl
- 4+4*($r{"1D"}&3), #Sens
- ((256+$r{"11"})*(2**($r{"10"} & 15 )))*26000000/(2**28) #DataRate
- );
- }
- elsif($cmd eq "bWidth") {
- my $val = hex(substr($msg,6));
- my $arg = $hash->{getcmd}->{arg};
- my $ob = $val & 0x0f;
-
- my ($bits, $bw) = (0,0);
- OUTERLOOP:
- for (my $e = 0; $e < 4; $e++) {
- for (my $m = 0; $m < 4; $m++) {
- $bits = ($e<<6)+($m<<4);
- $bw = int(26000/(8 * (4+$m) * (1 << $e))); # KHz
- last OUTERLOOP if($arg >= $bw);
- }
- }
-
- $ob = sprintf("%02x", $ob+$bits);
- $msg = "Setting MDMCFG4 (10) to $ob = $bw KHz";
- $hash->{logMethod}->($name, 3, "$name: parseResponse, bWidth: Setting MDMCFG4 (10) to $ob = $bw KHz");
- delete($hash->{getcmd});
- SIGNALduino_AddSendQueue($hash,"W12$ob");
- SIGNALduino_WriteInit($hash);
- }
- elsif($cmd eq "ccpatable") {
- my $CC1101Frequency = "433";
- if (defined($hash->{cc1101_frequency})) {
- $CC1101Frequency = $hash->{cc1101_frequency};
- }
- my $dBn = substr($msg,9,2);
- $hash->{logMethod}->($name, 3, "$name: parseResponse, patable: $dBn");
- foreach my $dB (keys %{ $patable{$CC1101Frequency} }) {
- if ($dBn eq $patable{$CC1101Frequency}{$dB}) {
- $hash->{logMethod}->($name, 5, "$name: parseResponse, patable: $dB");
- $msg .= " => $dB";
- last;
- }
- }
- # $msg .= "\n\n$CC1101Frequency MHz\n\n";
- # foreach my $dB (keys $patable{$CC1101Frequency})
- # {
- # $msg .= "$patable{$CC1101Frequency}{$dB} $dB\n";
- # }
- }
-
- return $msg;
+ return "Unsupported command for the microcontroller" if (!exists(${$gets{$a[0]}}[2]));
+ $hash->{logMethod}->($name, 5, "$name: Get $a[0] executed");
+ SIGNALduino_AddSendQueue($hash, @{$gets{$a[0]}}[2] . (exists($a[1]) ? "$a[1]" : ""));
+ $hash->{ucCmd}->{cmd}=$a[0];
+ $hash->{ucCmd}->{responseSub}=$gets{$a[0]}[3];
+ $hash->{ucCmd}->{asyncOut}=$hash->{CL} if (defined($hash->{CL}));
+ $hash->{ucCmd}->{timenow}=time();
+ return undef;
}
+###############################
+sub SIGNALduino_Get_Command_CCReg
+{
+ my ($hash, @a) = @_;
+ my $name=$hash->{NAME};
+ if (exists($cc1101_register{uc($_[2])}) || $_[2] =~ /^99$/ ) {
+ return SIGNALduino_Get_Command(@_);
+ } else {
+ return "unknown Register $_[2], please choose a valid cc1101 register";
+ }
+}
+
+
+###############################
+sub SIGNALduino_Get_Raw {
+ my ($hash, @a) = @_;
+ return "\"get raw\" needs at least a parameter" if (@a < 2);
+ if ($a[1] =~ /^M[CcSU];.*/)
+ {
+ $a[1]="\002$a[1]\003"; ## Add start end end marker if not already there
+ $hash->{logMethod}->($hash->{NAME}, 5, "$hash->{NAME}: msg adding start and endmarker to message");
+ }
+
+ if ($a[1] =~ /\002M.;.*;\003$/)
+ {
+ $hash->{logMethod}->( $hash->{NAME}, 4, "$hash->{NAME}: msg get raw: $a[1]");
+ return SIGNALduino_Parse($hash, $hash, $hash->{NAME}, $a[1]);
+ }
+}
+
+
+###############################
+sub SIGNALduino_GetResponseUpdateReading
+{
+ return ($_[1],1);
+}
+
+###############################
+sub SIGNALduino_Get_delayed($) {
+ my(undef,$name,@cmds) = split(':', shift);
+ my $hash = $defs{$name};
+
+ if ( exists($hash->{ucCmd}) && !exists($hash->{ucCmd}->{timenow}) ) {
+ $hash->{ucCmd}->{timenow}=time();
+ Log3 ($hash->{NAME}, 5, "$name: Get_delayed, timenow was missing, set ".$hash->{ucCmd}->{timenow});
+ }
+
+ if (exists($hash->{ucCmd}) && $hash->{ucCmd}->{timenow}+10 > time() ) {
+ $hash->{logMethod}->($hash->{NAME}, 5, "$name: Get_delayed, ".join(" ",@cmds)." delayed");
+ main::InternalTimer(main::gettimeofday() + main::SDUINO_GET_CONFIGQUERY_DELAY, "SIGNALduino_Get_delayed", "SIGNALduino_Get_delayed:$name:".join(" ",@cmds), 0);
+ } else {
+ delete($hash->{ucCmd});
+ $hash->{logMethod}->($hash->{NAME}, 5, "$name: Get_delayed, ".join(" ",@cmds)." executed");
+ RemoveInternalTimer("SIGNALduino_Get_delayed:$name:".join(" ",@cmds));
+ SIGNALduino_Get($hash,$name,$cmds[0]);
+ }
+}
+
+###############################
+sub SIGNALduino_CheckUptimeResponse
+{
+ my $msg = sprintf("%d %02d:%02d:%02d", $_[1]/86400, ($_[1]%86400)/3600, ($_[1]%3600)/60, $_[1]%60);
+ #readingsSingleUpdate($_[0], $_[0]->{ucCmd}->{cmd}, $msg, 0);
+ return ($msg,0);
+}
+
+###############################
+sub SIGNALduino_CheckCmdsResponse
+{
+ my $hash = shift;
+ my $msg = shift;
+ my $name=$hash->{NAME};
+
+ $msg =~ s/$name cmds =>//g;
+ $msg =~ s/.*Use one of//g;
+
+ return ($msg,0);
+}
+
+###############################
+sub SIGNALduino_CheckccConfResponse {
+ my (undef,$str) = split('=', $_[1]);
+ my $var;
+ my %r = ( "0D"=>1,"0E"=>1,"0F"=>1,"10"=>1,"11"=>1,"12"=>1,"1B"=>1,"1D"=>1, "15"=>1);
+ foreach my $a (sort keys %r) {
+ $var = substr($str,(hex($a)-13)*2, 2);
+ $r{$a} = hex($var);
+ }
+ my $msg = sprintf("Freq: %.3f MHz, Bandwidth: %d KHz, rAmpl: %d dB, sens: %d dB, DataRate: %.2f Baud",
+ 26*(($r{"0D"}*256+$r{"0E"})*256+$r{"0F"})/65536, #Freq | Register 0x0D,0x0E,0x0F
+ 26000/(8 * (4+(($r{"10"}>>4)&3)) * (1 << (($r{"10"}>>6)&3))), #Bw | Register 0x10
+ $ampllist[$r{"1B"}&7], #rAmpl | Register 0x1B
+ 4+4*($r{"1D"}&3), #Sens | Register 0x1D
+ ((256+$r{"11"})*(2**($r{"10"} & 15 )))*26000000/(2**28) #DataRate | Register 0x10,0x11
+ );
+
+ my $msg2 = sprintf("Modulation: %s, Syncmod: %s",
+ $modformat[$r{"12"}>>4], #Modulation | Register 0x12
+ $syncmod[($r{"12"})&7], #Syncmod | Register 0x12
+ );
+
+ readingsBeginUpdate($_[0]);
+ readingsBulkUpdate($_[0], "cc1101_config", $msg);
+ readingsBulkUpdate($_[0], "cc1101_config_ext", $msg2);
+ readingsEndUpdate($_[0], 1);
+
+ return ($msg.", ".$msg2,undef);
+}
+
+###############################
+sub SIGNALduino_CheckccPatableResponse {
+ my $hash = shift;
+ my $msg = shift;
+ my $name=$hash->{NAME};
+
+ my $CC1101Frequency=AttrVal($name,"cc1101_frequency",433);
+ $CC1101Frequency = 433 if ($CC1101Frequency >= 433 && $CC1101Frequency <= 435);
+ $CC1101Frequency = 868 if ($CC1101Frequency >= 863 && $CC1101Frequency <= 870);
+ my $dBn = substr($msg,9,2);
+ $hash->{logMethod}->($name, 3, "$name: CheckCcpatableResponse, patable: $dBn");
+ foreach my $dB (keys %{ $patable{$CC1101Frequency} }) {
+ if ($dBn eq $patable{$CC1101Frequency}{$dB}) {
+ $hash->{logMethod}->($name, 5, "$name: CheckCcpatableResponse, patable: $dB");
+ $msg .= " => $dB";
+ last;
+ }
+ }
+ readingsSingleUpdate($hash, "cc1101_patable", $msg,1);
+ return ($msg,undef);
+}
+
+###############################
+sub SIGNALduino_CheckCcregResponse
+{
+ my $hash = shift;
+ my $msg = shift;
+ my $name=$hash->{NAME};
+
+ if ($msg =~ /^ccreg/) {
+
+ $msg =~ s/\s\sccreg/\nccreg/g;
+ $msg =~ s/ccreg\s\d0:\s//g;
+
+ my @ccreg = split(/\s/,$msg);
+
+ $msg.= "\n\n";
+ $msg.= "Configuration Register Detail (address, name, value):\n";
+
+ my $reg_idx = 0;
+ foreach my $key (sort keys %cc1101_register) {
+ $msg.= "0x".$key." ".$cc1101_register{$key}. " - 0x".$ccreg[$reg_idx]."\n";
+ $reg_idx++;
+ }
+ } else {
+ $msg =~ /^C([A-Fa-f0-9]{2}) = ([A-Fa-f0-9]{2})$/;
+ my $reg = $1;
+ my $val = $2;
+ $msg = "Configuration Register Detail address (name) = value:\n";
+ $msg .= "0x$reg ( $cc1101_register{$reg}) = 0x$val\n";
+ }
+ return ("\n".$msg,undef);
+}
+
+
+
+###############################
+### Unused ###
+sub SIGNALduino_CheckSendRawResponse
+{
+ my $hash = shift;
+ my $msg = shift;
+
+ if ($msg =~ /^S[RCM];/ )
+ {
+ my $name=$hash->{NAME};
+
+ # zu testen der sendeQueue, kann wenn es funktioniert auf verbose 5
+ $hash->{logMethod}->($name, 4, "$name: CheckSendrawResponse, sendraw answer: $msg");
+ #RemoveInternalTimer("HandleWriteQueue:$name");
+ delete($hash->{ucCmd});
+ SIGNALduino_HandleWriteQueue("x:$name");
+ }
+ return (undef);
+}
+
###############################
sub SIGNALduino_ResetDevice($) {
my $hash = shift;
my $name = $hash->{NAME};
- if (!defined($hash->{helper}{resetInProgress}))
- {
+
+ if (!defined($hash->{helper}{resetInProgress})) {
my $hardware = AttrVal($name,"hardware","");
- $hash->{logMethod}->($name, 3, "$name: ResetDevice, $hardware");
+ $hash->{logMethod}->($name, 3, "$name: ResetDevice, $hardware");
+
+ if (IsDummy($name)) { # for dummy device
+ $hash->{DevState} = "initialized";
+ readingsSingleUpdate($hash, "state", "opened", 1);
+ return undef;
+ }
+
DevIo_CloseDev($hash);
if ($hardware eq "radinoCC1101" && $^O eq 'linux') {
# The reset is triggered when the Micro's virtual (CDC) serial / COM port is opened at 1200 baud and then closed.
# When this happens, the processor will reset, breaking the USB connection to the computer (meaning that the virtual serial / COM port will disappear).
# After the processor resets, the bootloader starts, remaining active for about 8 seconds.
# The bootloader can also be initiated by pressing the reset button on the Micro.
- # Note that when the board first powers up, it will jump straight to the user sketch, if present, rather than initiating the bootloader.
+ # Note that when the board first powers up, it will jump straight to the user sketch, if present, rather than initiating the bootloader.
my ($dev, $baudrate) = split("@", $hash->{DeviceName});
$hash->{logMethod}->($name, 3, "$name: ResetDevice, forcing special reset for $hardware on $dev");
# Mit dem Linux-Kommando 'stty' die Port-Einstellungen setzen
system("stty -F $dev ospeed 1200 ispeed 1200");
$hash->{helper}{resetInProgress}=1;
InternalTimer(gettimeofday()+10,"SIGNALduino_ResetDevice",$hash);
- $hash->{logMethod}->($name, 3, "$name: ResetDevice, reopen delayed for 10 second");
- return;
+ $hash->{logMethod}->($name, 3, "$name: ResetDevice, reopen delayed for 10 second");
+ return undef;
}
} else {
delete($hash->{helper}{resetInProgress});
}
DevIo_OpenDev($hash, 0, "SIGNALduino_DoInit", 'SIGNALduino_Connect');
+ return undef;
}
###############################
sub SIGNALduino_CloseDevice($) {
my ($hash) = @_;
- $hash->{logMethod}->($hash->{NAME}, 2, "$hash->{NAME}: CloseDevice, closed");
+ $hash->{logMethod}->($hash->{NAME}, 2, "$hash->{NAME}: CloseDevice, closed");
RemoveInternalTimer($hash);
DevIo_CloseDev($hash);
readingsSingleUpdate($hash, "state", "closed", 1);
-
+
return undef;
}
@@ -1059,29 +1234,27 @@ sub SIGNALduino_DoInit($) {
my ($ver, $try) = ("", 0);
#Dirty hack to allow initialisation of DirectIO Device for some debugging and tesing
- $hash->{logMethod}->($hash, 1, "$name: DoInit, ".$hash->{DEF});
-
+
delete($hash->{disConnFlag}) if defined($hash->{disConnFlag});
-
+
RemoveInternalTimer("HandleWriteQueue:$name");
@{$hash->{QUEUE}} = ();
$hash->{sendworking} = 0;
-
+
if (($hash->{DEF} !~ m/\@directio/) and ($hash->{DEF} !~ m/none/) )
{
$hash->{logMethod}->($hash, 1, "$name: DoInit, ".$hash->{DEF});
$hash->{initretry} = 0;
RemoveInternalTimer($hash);
-
+
#SIGNALduino_SimpleWrite($hash, "XQ"); # Disable receiver
InternalTimer(gettimeofday() + SDUINO_INIT_WAIT_XQ, "SIGNALduino_SimpleWrite_XQ", $hash, 0);
-
InternalTimer(gettimeofday() + SDUINO_INIT_WAIT, "SIGNALduino_StartInit", $hash, 0);
}
# Reset the counter
delete($hash->{XMIT_TIME});
delete($hash->{NR_CMD_LAST_H});
-
+
return;
return undef;
}
@@ -1092,7 +1265,7 @@ sub SIGNALduino_DoInit($) {
sub SIGNALduino_SimpleWrite_XQ($) {
my ($hash) = @_;
my $name = $hash->{NAME};
-
+
$hash->{logMethod}->($hash, 3, "$name: SimpleWrite_XQ, disable receiver (XQ)");
SIGNALduino_SimpleWrite($hash, "XQ");
#DevIo_SimpleWrite($hash, "XQ\n",2);
@@ -1103,7 +1276,7 @@ sub SIGNALduino_StartInit($) {
my ($hash) = @_;
my $name = $hash->{NAME};
$hash->{version} = undef;
-
+
$hash->{logMethod}->($name,3 , "$name: StartInit, get version, retry = " . $hash->{initretry});
if ($hash->{initretry} >= SDUINO_INIT_MAXRETRY) {
$hash->{DevState} = 'INACTIVE';
@@ -1119,22 +1292,84 @@ sub SIGNALduino_StartInit($) {
return;
}
else {
- $hash->{getcmd}->{cmd} = "version";
+ $hash->{ucCmd}->{cmd} = "version";
+ $hash->{ucCmd}->{responseSub} = \&SIGNALduino_CheckVersionResp;
+ $hash->{ucCmd}->{timenow} = time();
SIGNALduino_SimpleWrite($hash, "V");
#DevIo_SimpleWrite($hash, "V\n",2);
$hash->{DevState} = 'waitInit';
RemoveInternalTimer($hash);
- InternalTimer(gettimeofday() + SDUINO_CMD_TIMEOUT, "SIGNALduino_CheckCmdResp", $hash, 0);
+ InternalTimer(gettimeofday() + SDUINO_CMD_TIMEOUT, "SIGNALduino_CheckVersionResp", $hash, 0);
}
}
###############################
+sub SIGNALduino_CheckVersionResp
+{
+ my ($hash,$msg) = @_;
+ my $name = $hash->{NAME};
+
+
+ ### ToDo, manchmal kommen Mu Nachrichten in $msg und somit ist keine Version feststellbar !!!
+ if (defined($msg)) {
+ $hash->{logMethod}->($hash, 5, "$name: CheckVersionResp, called with $msg");
+ $msg =~ m/($gets{$hash->{ucCmd}->{cmd}}[4])/;
+ $hash->{version} = $1;
+ } else {
+ $hash->{logMethod}->($hash, 5, "$name: CheckVersionResp, called without msg");
+ # Aufruf durch Timeout!
+ $msg="undef";
+ delete($hash->{ucCmd});
+ }
+
+ if (!defined($hash->{version}) ) {
+ $msg = "$name: CheckVersionResp, Not an SIGNALduino device, got for V: $msg";
+ $hash->{logMethod}->($hash, 1, $msg);
+ readingsSingleUpdate($hash, "state", "no SIGNALduino found", 1); #uncoverable statement because state is overwritten by SIGNALduino_CloseDevice
+ $hash->{initretry} ++;
+ SIGNALduino_StartInit($hash);
+ } elsif($hash->{version} =~ m/^V 3\.1\./) {
+ $msg = "$name: CheckVersionResp, Version of your arduino is not compatible, please flash new firmware. (device closed) Got for V: $msg";
+ readingsSingleUpdate($hash, "state", "unsupported firmware found", 1); #uncoverable statement because state is overwritten by SIGNALduino_CloseDevice
+ $hash->{logMethod}->($hash, 1, $msg);
+ $hash->{DevState} = 'INACTIVE';
+ SIGNALduino_CloseDevice($hash);
+ } else {
+ if (exists($hash->{DevState}) && $hash->{DevState} eq 'waitInit') {
+ RemoveInternalTimer($hash);
+ }
+
+ readingsSingleUpdate($hash, "state", "opened", 1);
+ $hash->{logMethod}->($name, 2, "$name: CheckVersionResp, initialized " . SDUINO_VERSION);
+ delete($hash->{initResetFlag}) if defined($hash->{initResetFlag});
+ SIGNALduino_SimpleWrite($hash, "XE"); # Enable receiver
+ $hash->{logMethod}->($hash, 3, "$name: CheckVersionResp, enable receiver (XE) ");
+ delete($hash->{initretry});
+ # initialize keepalive
+ $hash->{keepalive}{ok} = 0;
+ $hash->{keepalive}{retry} = 0;
+ InternalTimer(gettimeofday() + SDUINO_KEEPALIVE_TIMEOUT, "SIGNALduino_KeepAlive", $hash, 0);
+ if ($hash->{version} =~ m/cc1101/) {
+ $hash->{cc1101_available} = 1;
+ $hash->{logMethod}->($name, 5, "$name: CheckVersionResp, cc1101 available");
+ SIGNALduino_Get($hash, $name,"ccconf");
+ SIGNALduino_Get($hash, $name,"ccpatable");
+ }
+ $hash->{DevState} = 'initialized';
+ $msg = $hash->{version};
+ }
+ return ($msg,undef);
+}
+
+
+###############################
+# Todo: SUB kann entfernt werden
sub SIGNALduino_CheckCmdResp($) {
my ($hash) = @_;
my $name = $hash->{NAME};
my $msg = undef;
my $ver;
-
+
if ($hash->{version}) {
$ver = $hash->{version};
if ($ver !~ m/SIGNAL(duino|ESP)/) {
@@ -1163,11 +1398,11 @@ sub SIGNALduino_CheckCmdResp($) {
$hash->{keepalive}{ok} = 0;
$hash->{keepalive}{retry} = 0;
InternalTimer(gettimeofday() + SDUINO_KEEPALIVE_TIMEOUT, "SIGNALduino_KeepAlive", $hash, 0);
- $hash->{hasCC1101} = 1 if ($ver =~ m/cc1101/);
+ $hash->{cc1101_available} = 1 if ($ver =~ m/cc1101/);
}
}
else {
- delete($hash->{getcmd});
+ delete($hash->{ucCmd});
$hash->{initretry} ++;
#InternalTimer(gettimeofday()+1, "SIGNALduino_StartInit", $hash, 0);
SIGNALduino_StartInit($hash);
@@ -1179,8 +1414,8 @@ sub SIGNALduino_CheckCmdResp($) {
# Check if the 1% limit is reached and trigger notifies
sub SIGNALduino_XmitLimitCheck($$) {
my ($hash,$fn) = @_;
-
- return if ($fn !~ m/^(is|SR).*/);
+
+ return if ($fn !~ m/^(is|S[RCM]).*/);
my $now = time();
@@ -1228,7 +1463,7 @@ sub SIGNALduino_Write($$$) {
$msg = SIGNALduino_PreparingSend_FS20_FHT(73, 12, $msg);
}
$hash->{logMethod}->($name, 5, "$name: Write, sending via Set $fn $msg");
-
+
SIGNALduino_Set($hash,$name,$fn,$msg);
}
@@ -1236,38 +1471,51 @@ sub SIGNALduino_Write($$$) {
sub SIGNALduino_AddSendQueue($$) {
my ($hash, $msg) = @_;
my $name = $hash->{NAME};
-
+
push(@{$hash->{QUEUE}}, $msg);
-
+
#SIGNALduino_Log3 $hash , 5, Dumper($hash->{QUEUE});
-
+
$hash->{logMethod}->($hash, 5,"$name: AddSendQueue, " . $hash->{NAME} . ": $msg (" . @{$hash->{QUEUE}} . ")");
- InternalTimer(gettimeofday() + 0.1, "SIGNALduino_HandleWriteQueue", "HandleWriteQueue:$name") if (@{$hash->{QUEUE}} == 1 && $hash->{sendworking} == 0);
+ InternalTimer(gettimeofday() + 0.1, "SIGNALduino_HandleWriteQueue", "HandleWriteQueue:$name") if (scalar @{$hash->{QUEUE}} == 1 && InternalVal($name,"sendworking",0) == 0);
}
###############################
sub SIGNALduino_SendFromQueue($$) {
my ($hash, $msg) = @_;
my $name = $hash->{NAME};
+
+ $hash->{logMethod}->($name, 4, "$name: SendFromQueue, called");
if($msg ne "") {
SIGNALduino_XmitLimitCheck($hash,$msg);
#DevIo_SimpleWrite($hash, $msg . "\n", 2);
$hash->{sendworking} = 1;
SIGNALduino_SimpleWrite($hash,$msg);
- if ($msg =~ m/^S(R|C|M);/) {
- $hash->{getcmd}->{cmd} = 'sendraw';
- $hash->{logMethod}->($name, 4, "$name: SendFromQueue, msg=$msg"); # zu testen der Queue, kann wenn es funktioniert auskommentiert werden
- }
- elsif ($msg eq "C99") {
- $hash->{getcmd}->{cmd} = 'ccregAll';
+ if ($msg =~ m/^S[RCM];/) {
+ $hash->{ucCmd}->{cmd} = 'sendraw';
+ $hash->{ucCmd}->{timenow} = time();
+ $hash->{ucCmd}->{responseSub} = \&SIGNALduino_CheckSendRawResponse;
+ $hash->{logMethod}->($name, 4, "$name: SendFromQueue, msg=$msg"); # zu testen der Queue, kann wenn es funktioniert auskommentiert werden
+ } elsif ($msg =~ "^e") { # Werkseinstellungen
+ SIGNALduino_Get($hash,$name,"ccconf");
+ SIGNALduino_Get($hash,$name,"ccpatable");
+ } elsif ($msg =~ "^W(?:0F|10|11|1D|12|1F)") { # SetFreq, setrAmpl, Set_bWidth, SetSens
+ SIGNALduino_Get($hash,$name,"ccconf");
+ } elsif ($msg =~ "^x") { # patable
+ SIGNALduino_Get($hash,$name,"ccpatable");
}
+# elsif ($msg eq "C99") {
+# $hash->{ucCmd}->{cmd} = 'ccregAll';
+# $hash->{ucCmd}->{responseSub} = \&SIGNALduino_CheckCcregResponse;
+#
+# }
}
##############
# Write the next buffer not earlier than 0.23 seconds
# else it will be sent too early by the SIGNALduino, resulting in a collision, or may the last command is not finished
-
- if (defined($hash->{getcmd}->{cmd}) && $hash->{getcmd}->{cmd} eq 'sendraw') {
+
+ if (defined($hash->{ucCmd}->{cmd}) && $hash->{ucCmd}->{cmd} eq 'sendraw') {
InternalTimer(gettimeofday() + SDUINO_WRITEQUEUE_TIMEOUT, "SIGNALduino_HandleWriteQueue", "HandleWriteQueue:$name");
} else {
InternalTimer(gettimeofday() + SDUINO_WRITEQUEUE_NEXT, "SIGNALduino_HandleWriteQueue", "HandleWriteQueue:$name");
@@ -1279,16 +1527,17 @@ sub SIGNALduino_HandleWriteQueue($) {
my($param) = @_;
my(undef,$name) = split(':', $param);
my $hash = $defs{$name};
-
+
#my @arr = @{$hash->{QUEUE}};
-
+
+ $hash->{logMethod}->($name, 4, "$name: HandleWriteQueue, called");
$hash->{sendworking} = 0; # es wurde gesendet
-
- if (defined($hash->{getcmd}->{cmd}) && $hash->{getcmd}->{cmd} eq 'sendraw') {
+
+ if (exists($hash->{ucCmd}) && exists($hash->{ucCmd}->{cmd}) && $hash->{ucCmd}->{cmd} eq 'sendraw') {
$hash->{logMethod}->($name, 4, "$name: HandleWriteQueue, sendraw no answer (timeout)");
- delete($hash->{getcmd});
+ delete($hash->{ucCmd});
}
-
+
if(exists($hash->{QUEUE}) && @{$hash->{QUEUE}}) {
my $msg= shift(@{$hash->{QUEUE}});
@@ -1321,7 +1570,7 @@ sub SIGNALduino_Read($) {
my $rmsg;
($rmsg,$SIGNALduinodata) = split("\n", $SIGNALduinodata, 2);
$rmsg =~ s/\r//;
-
+
if ($rmsg =~ m/^\002(M(s|u|o);.*;)\003/) {
$rmsg =~ s/^\002//; # \002 am Anfang entfernen
my @msg_parts = split(";",$rmsg);
@@ -1333,7 +1582,7 @@ sub SIGNALduino_Read($) {
my $part = "";
my $partD;
$hash->{logMethod}->($name, 5, "$name: Read, RAW rmsg: $rmsg");
-
+
foreach my $msgPart (@msg_parts) {
next if ($msgPart eq "");
$m0 = substr($msgPart,0,1);
@@ -1380,7 +1629,7 @@ sub SIGNALduino_Read($) {
elsif ($m0 eq "o" || $m0 eq "m") {
$part .= "$m0$m1;";
}
- elsif ($m1 =~ m/^[0-9A-Z]{1,2}$/) { # bei 1 oder 2 Hex Ziffern nach Dez wandeln
+ elsif ($m1 =~ m/^[0-9A-Z]{1,2}$/) { # bei 1 oder 2 Hex Ziffern nach Dez wandeln
$part .= "$m0=" . hex($m1) . ";";
}
elsif ($m0 =~m/[0-9a-zA-Z]/) {
@@ -1398,60 +1647,31 @@ sub SIGNALduino_Read($) {
$hash->{logMethod}->($name, 4, "$name: Read, msg: $rmsg");
}
- if ( $rmsg && !SIGNALduino_Parse($hash, $hash, $name, $rmsg) && defined($hash->{getcmd}) && defined($hash->{getcmd}->{cmd}))
+ if ( $rmsg && !SIGNALduino_Parse($hash, $hash, $name, $rmsg) && exists($hash->{ucCmd}) && defined($hash->{ucCmd}->{cmd}))
{
- my $regexp;
- if ($hash->{getcmd}->{cmd} eq 'sendraw') { # todo: pruefen wieso die regexp nicht im %gets hinterlegt ist. Das könnte in paar Zeilen code sparen
- $regexp = '^S(?:R|C|M);.';
- }
- elsif ($hash->{getcmd}->{cmd} eq 'ccregAll') {
- $regexp = '^ccreg 00:';
- }
- elsif ($hash->{getcmd}->{cmd} eq 'bWidth') {
- $regexp = '^C.* = .*';
- }
- else {
- $regexp = $gets{$hash->{getcmd}->{cmd}}[1];
- }
- if(!defined($regexp) || $rmsg =~ m/$regexp/) {
- if (defined($hash->{keepalive})) {
+ my $regexp = exists($gets{$hash->{ucCmd}->{cmd}}) && exists($gets{$hash->{ucCmd}->{cmd}}[4]) ? $gets{$hash->{ucCmd}->{cmd}}[4] : ".*";
+ if (exists($hash->{ucCmd}->{responseSub}) && ref $hash->{ucCmd}->{responseSub} eq "CODE") {
+ $hash->{logMethod}->($name, 5, "$name: Read, msg: regexp=$regexp cmd=$hash->{ucCmd}->{cmd} msg=$rmsg");
+ my $returnMessage ;
+ my $event;
+ if (!exists($gets{$hash->{ucCmd}->{cmd}}) || !exists($gets{$hash->{ucCmd}->{cmd}}[4]) || $rmsg =~ /$regexp/)
+ {
+ ($returnMessage,$event) = $hash->{ucCmd}->{responseSub}->($hash,$rmsg) ;
+ readingsSingleUpdate($hash, $hash->{ucCmd}->{cmd}, $returnMessage, $event) if (defined($returnMessage) && defined($event));
+ if (exists($hash->{ucCmd}->{asyncOut})) {
+ $hash->{logMethod}->($name, 5, "$name: Read, try asyncOutput of message $returnMessage");
+ my $ao = asyncOutput( $hash->{ucCmd}->{asyncOut}, $hash->{ucCmd}->{cmd}.": " . $returnMessage ) if (defined($returnMessage));
+ $hash->{logMethod}->($name, 5, "$name: Read, asyncOutput failed $ao") if ($ao);
+ }
+ delete($hash->{ucCmd});
+ }
+
+ if (exists($hash->{keepalive})) {
$hash->{keepalive}{ok} = 1;
$hash->{keepalive}{retry} = 0;
}
- $hash->{logMethod}->($name, 5, "$name: Read, msg: regexp=$regexp cmd=$hash->{getcmd}->{cmd} msg=$rmsg");
-
- if ($hash->{getcmd}->{cmd} eq 'version') { # todo prüfen ob der code nicht in die %gets tabelle verschoben werden kann
- my $msg_start = index($rmsg, 'V 3.');
- if ($msg_start > 0) {
- $rmsg = substr($rmsg, $msg_start);
- $hash->{logMethod}->($name, 4, "$name: Read, cut chars at begin. msgstart = $msg_start msg = $rmsg");
- }
- $hash->{version} = $rmsg;
- if (defined($hash->{DevState}) && $hash->{DevState} eq 'waitInit') {
- RemoveInternalTimer($hash);
- SIGNALduino_CheckCmdResp($hash);
- }
- }
- if ($hash->{getcmd}->{cmd} eq 'sendraw') {
- # zu testen der sendeQueue, kann wenn es funktioniert auf verbose 5
- $hash->{logMethod}->($name, 4, "$name: Read, sendraw answer: $rmsg");
- delete($hash->{getcmd});
- RemoveInternalTimer("HandleWriteQueue:$name");
- SIGNALduino_HandleWriteQueue("x:$name");
- }
- else {
- $rmsg = SIGNALduino_parseResponse($hash,$hash->{getcmd}->{cmd},$rmsg);
- if (defined($hash->{getcmd}) && $hash->{getcmd}->{cmd} ne 'ccregAll') {
- readingsSingleUpdate($hash, $hash->{getcmd}->{cmd}, $rmsg, 0);
- }
- if (defined($hash->{getcmd}->{asyncOut})) {
- #SIGNALduino_Log3 $name, 4, "$name: Read, msg: asyncOutput";
- my $ao = asyncOutput( $hash->{getcmd}->{asyncOut}, $hash->{getcmd}->{cmd}.": " . $rmsg );
- }
- delete($hash->{getcmd});
- }
} else {
- $hash->{logMethod}->($name, 4, "$name: Read, msg: Received answer ($rmsg) for ". $hash->{getcmd}->{cmd}." does not match $regexp");
+ $hash->{logMethod}->($name, 4, "$name: Read, msg: Received answer ($rmsg) for ". $hash->{ucCmd}->{cmd}." does not match $regexp / coderef");
}
}
}
@@ -1462,12 +1682,12 @@ sub SIGNALduino_Read($) {
sub SIGNALduino_KeepAlive($){
my ($hash) = @_;
my $name = $hash->{NAME};
-
+
return if ($hash->{DevState} eq 'disconnected');
-
+
#SIGNALduino_Log3 $name,4 , "$name: KeepAliveOk, " . $hash->{keepalive}{ok};
if (!$hash->{keepalive}{ok}) {
- delete($hash->{getcmd});
+ delete($hash->{ucCmd});
if ($hash->{keepalive}{retry} >= SDUINO_KEEPALIVE_MAXRETRY) {
$hash->{logMethod}->($name,3 , "$name: KeepAlive, not ok, retry count reached. Reset");
$hash->{DevState} = 'INACTIVE';
@@ -1481,16 +1701,17 @@ sub SIGNALduino_KeepAlive($){
$logLevel = 4;
}
$hash->{logMethod}->($name, $logLevel, "$name: KeepAlive, not ok, retry = " . $hash->{keepalive}{retry} . " -> get ping");
- $hash->{getcmd}->{cmd} = "ping";
+ $hash->{ucCmd}->{cmd} = "ping";
+ $hash->{ucCmd}->{timenow} = time();
+ $hash->{ucCmd}->{responseSub} = \&SIGNALduino_GetResponseUpdateReading;
SIGNALduino_AddSendQueue($hash, "P");
- #SIGNALduino_SimpleWrite($hash, "P");
}
}
else {
$hash->{logMethod}->($name,4 , "$name: KeepAlive, ok, retry = " . $hash->{keepalive}{retry});
}
$hash->{keepalive}{ok} = 0;
-
+
InternalTimer(gettimeofday() + SDUINO_KEEPALIVE_TIMEOUT, "SIGNALduino_KeepAlive", $hash);
}
@@ -1500,7 +1721,7 @@ sub SIGNALduino_KeepAlive($){
###############################
## Parses a HTTP Response for example for flash via http download
sub SIGNALduino_ParseHttpResponse {
-
+
my ($param, $err, $data) = @_;
my $hash = $param->{hash};
my $name = $hash->{NAME};
@@ -1511,29 +1732,29 @@ sub SIGNALduino_ParseHttpResponse {
}
elsif($param->{code} eq "200" && $data ne "") # wenn die Abfrage erfolgreich war ($data enthaelt die Ergebnisdaten des HTTP Aufrufes)
{
-
+
$hash->{logMethod}->($name, 3, "$name: ParseHttpResponse, url ".$param->{url}." returned: ".length($data)." bytes Data"); # Eintrag fuers Log
-
+
if ($param->{command} eq "flash")
{
my $filename;
-
+
if ($param->{httpheader} =~ /Content-Disposition: attachment;.?filename=\"?([-+.\w]+)?\"?/)
- {
+ {
$filename = $1;
} else { # Filename via path if not specifyied via Content-Disposition
- ($filename = $param->{path}) =~s/.*\///;
+ $param->{path} =~ /\/([-+.\w]+)$/; #(?:[^\/][\d\w\.]+)+$ \/([-+.\w]+)$
+ $filename = $1;
}
-
$hash->{logMethod}->($name, 3, "$name: ParseHttpResponse, Downloaded $filename firmware from ".$param->{host});
$hash->{logMethod}->($name, 5, "$name: ParseHttpResponse, Header = ".$param->{httpheader});
-
-
+
+
$filename = "FHEM/firmware/" . $filename;
open(my $file, ">", $filename) or die $!;
print $file $data;
close $file;
-
+
# Den Flash Befehl mit der soebene heruntergeladenen Datei ausfuehren
#SIGNALduino_Log3 $name, 3, "$name: ParseHttpResponse, calling set ".$param->{command}." $filename"; # Eintrag fuers Log
@@ -1541,7 +1762,7 @@ sub SIGNALduino_ParseHttpResponse {
if (defined($set_return))
{
$hash->{logMethod}->($name ,3, "$name: ParseHttpResponse, Error while flashing: $set_return");
- }
+ }
}
} else {
$hash->{logMethod}->($name, 3, "$name: ParseHttpResponse, undefined error while requesting ".$param->{url}." - $err - code=".$param->{code}); # Eintrag fuers Log
@@ -1553,7 +1774,7 @@ sub SIGNALduino_splitMsg {
my $txt = shift;
my $delim = shift;
my @msg_parts = split(/$delim/,$txt);
-
+
return @msg_parts;
}
@@ -1589,7 +1810,7 @@ sub SIGNALduino_FillPatternLookupTable {
###############################
#=item SIGNALduino_PatternExists()
# This functons, needs reference to $hash, @array of values to search and %patternList where to find the matches.
-#
+#
# Will return -1 if pattern is not found or a string, containing the indexes which are in tolerance and have the smallest gap to what we searched
# =cut
@@ -1598,44 +1819,44 @@ sub SIGNALduino_FillPatternLookupTable {
sub SIGNALduino_PatternExists {
my ($hash,$search,$patternList,$data) = @_;
#my %patternList=$arg3;
- #Debug "plist: ".Dumper($patternList) if($debug);
+ #Debug "plist: ".Dumper($patternList) if($debug);
#Debug "searchlist: ".Dumper($search) if($debug);
my $searchpattern;
- my $valid=1;
+ my $valid=1;
my @pstr;
my $debug = AttrVal($hash->{NAME},"debug",0);
-
+
my $i=0;
-
+
my $maxcol=0;
-
- foreach $searchpattern (@{$search}) # z.B. [1, -4]
+
+ foreach $searchpattern (@{$search}) # z.B. [1, -4]
{
#my $patt_id;
# Calculate tolernace for search
#my $tol=abs(abs($searchpattern)>=2 ?$searchpattern*0.3:$searchpattern*1.5);
my $tol=abs(abs($searchpattern)>3 ? abs($searchpattern)>16 ? $searchpattern*0.18 : $searchpattern*0.3 : 1); #tol is minimum 1 or higer, depending on our searched pulselengh
-
- Debug "tol: looking for ($searchpattern +- $tol)" if($debug);
-
+
+ Debug "tol: looking for ($searchpattern +- $tol)" if($debug);
+
my %pattern_gap ; #= {};
# Find and store the gap of every pattern, which is in tolerance
%pattern_gap = map { $_ => abs($patternList->{$_}-$searchpattern) } grep { abs($patternList->{$_}-$searchpattern) <= $tol} (keys %$patternList);
- if (scalar keys %pattern_gap > 0)
+ if (scalar keys %pattern_gap > 0)
{
Debug "index => gap in tol (+- $tol) of pulse ($searchpattern) : ".Dumper(\%pattern_gap) if($debug);
# Extract fist pattern, which is nearst to our searched value
my @closestidx = (sort {$pattern_gap{$a} <=> $pattern_gap{$b}} keys %pattern_gap);
-
+
my $idxstr="";
my $r=0;
-
- while (my ($item) = splice(@closestidx, 0, 1))
+
+ while (my ($item) = splice(@closestidx, 0, 1))
{
- $pstr[$i][$r]=$item;
+ $pstr[$i][$r]=$item;
$r++;
Debug "closest pattern has index: $item" if($debug);
}
@@ -1643,14 +1864,14 @@ sub SIGNALduino_PatternExists {
} else {
# search is not found, return -1
return -1;
- last;
+ last;
}
$i++;
#return ($valid ? $pstr : -1); # return $pstr if $valid or -1
-
+
#foreach $patt_id (keys %$patternList) {
- #Debug "$patt_id. chk ->intol $patternList->{$patt_id} $searchpattern $tol";
+ #Debug "$patt_id. chk ->intol $patternList->{$patt_id} $searchpattern $tol";
#$valid = SIGNALduino_inTol($patternList->{$patt_id}, $searchpattern, $tol);
#if ( $valid) #one pulse found in tolerance, search next one
#{
@@ -1663,21 +1884,21 @@ sub SIGNALduino_PatternExists {
#last if (!$valid); ## Exit loop if a complete iteration has not found anything
}
my @results = ('');
-
+
foreach my $subarray (@pstr)
{
@results = map {my $res = $_; map $res.$_, @$subarray } @results;
}
-
+
foreach my $search (@results)
{
Debug "looking for substr $search" if($debug);
-
+
return $search if (index( ${$data}, $search) >= 0);
}
-
+
return -1;
-
+
#return ($valid ? @results : -1); # return @pstr if $valid or -1
}
@@ -1686,20 +1907,20 @@ sub SIGNALduino_MatchSignalPattern($\@\%\@$){
my ( $hash, $signalpattern, $patternList, $data_array, $idx) = @_;
my $name = $hash->{NAME};
- #print Dumper($patternList);
- #print Dumper($idx);
- #Debug Dumper($signalpattern) if ($debug);
+ #print Dumper($patternList);
+ #print Dumper($idx);
+ #Debug Dumper($signalpattern) if ($debug);
my $tol="0.2"; # Tolerance factor
my $found=0;
my $debug = AttrVal($hash->{NAME},"debug",0);
-
+
foreach ( @{$signalpattern} )
{
- #Debug " $idx check: ".$patternList->{$data_array->[$idx]}." == ".$_;
- Debug "$name: idx: $idx check: abs(". $patternList->{$data_array->[$idx]}." - ".$_.") > ". ceil(abs($patternList->{$data_array->[$idx]}*$tol)) if ($debug);
-
+ #Debug " $idx check: ".$patternList->{$data_array->[$idx]}." == ".$_;
+ Debug "$name: idx: $idx check: abs(". $patternList->{$data_array->[$idx]}." - ".$_.") > ". ceil(abs($patternList->{$data_array->[$idx]}*$tol)) if ($debug);
+
#print "\n";;
- #if ($patternList->{$data_array->[$idx]} ne $_ )
+ #if ($patternList->{$data_array->[$idx]} ne $_ )
### Nachkommastelle von ceil!!!
if (!defined( $patternList->{$data_array->[$idx]})){
Debug "$name: Error index ($idx) does not exist!!" if ($debug);
@@ -1717,7 +1938,7 @@ sub SIGNALduino_MatchSignalPattern($\@\%\@$){
{
return $idx; ## Return new Index Position
}
-
+
}
###############################
@@ -1750,11 +1971,11 @@ sub SIGNALduino_Split_Message($$) {
my $clockabs;
my $mcbitnum;
my $rssi;
-
+
my @msg_parts = SIGNALduino_splitMsg($rmsg,';'); ## Split message parts by ";"
my %ret;
my $debug = AttrVal($name,"debug",0);
-
+
foreach (@msg_parts)
{
#Debug "$name: checking msg part:( $_ )" if ($debug);
@@ -1766,17 +1987,17 @@ sub SIGNALduino_Split_Message($$) {
}
elsif ($_ =~ m/^P\d=-?\d{2,}/ or $_ =~ m/^[SL][LH]=-?\d{2,}/) #### Extract Pattern List from array
{
- $_ =~ s/^P+//;
- $_ =~ s/^P\d//;
+ $_ =~ s/^P+//;
+ $_ =~ s/^P\d//;
my @pattern = split(/=/,$_);
-
+
$patternList{$pattern[0]} = $pattern[1];
Debug "$name: extracted pattern @pattern \n" if ($debug);
}
elsif($_ =~ m/D=\d+/ or $_ =~ m/^D=[A-F0-9]+/) #### Message from array
{
- $_ =~ s/D=//;
+ $_ =~ s/D=//;
$rawData = $_ ;
Debug "$name: extracted data $rawData\n" if ($debug);
$ret{rawData} = $rawData;
@@ -1803,10 +2024,10 @@ sub SIGNALduino_Split_Message($$) {
Debug "$name: extracted number of $mcbitnum bits\n" if ($debug);;
$ret{mcbitnum} = $mcbitnum;
}
-
+
elsif($_ =~ m/^C=\d+/) #### Message from array
{
- $_ =~ s/C=//;
+ $_ =~ s/C=//;
$clockabs = $_ ;
Debug "$name: extracted absolute clock $clockabs \n" if ($debug);
$ret{clockabs} = $clockabs;
@@ -1822,7 +2043,7 @@ sub SIGNALduino_Split_Message($$) {
}
#print "$_\n";
}
- $ret{pattern} = {%patternList};
+ $ret{pattern} = {%patternList};
return %ret;
}
@@ -1831,15 +2052,15 @@ sub SIGNALduino_Split_Message($$) {
sub SIGNALduno_Dispatch($$$$$) {
my ($hash, $rmsg, $dmsg, $rssi, $id) = @_;
my $name = $hash->{NAME};
-
+
if (!defined($dmsg))
{
$hash->{logMethod}->($name, 5, "$name: Dispatch, dmsg is undef. Skipping dispatch call");
return;
}
-
+
#SIGNALduino_Log3 $name, 5, "$name: Dispatch, DMSG: $dmsg";
-
+
my $DMSGgleich = 1;
if ($dmsg eq $hash->{LASTDMSG}) {
$hash->{logMethod}->($name, SDUINO_DISPATCH_VERBOSE, "$name: Dispatch, $dmsg, test gleich");
@@ -1857,7 +2078,7 @@ sub SIGNALduno_Dispatch($$$$$) {
if ($DMSGgleich) {
#Dispatch if dispatchequals is provided in protocol definition or only if $dmsg is different from last $dmsg, or if 2 seconds are between transmits
- if ( (SIGNALduino_getProtoProp($id,'dispatchequals',0) eq 'true') || ($hash->{DMSG} ne $dmsg) || ($hash->{TIME}+2 < time() ) ) {
+ if ( (SIGNALduino_getProtoProp($id,'dispatchequals',0) eq 'true') || ($hash->{DMSG} ne $dmsg) || ($hash->{TIME}+2 < time() ) ) {
$hash->{MSGCNT}++;
$hash->{TIME} = time();
$hash->{DMSG} = $dmsg;
@@ -1868,7 +2089,7 @@ sub SIGNALduno_Dispatch($$$$$) {
return if (substr($dmsg,0,1) eq 'U'); # Fuer $dmsg die mit U anfangen ist kein Dispatch notwendig, da es dafuer kein Modul gibt klein u wird dagegen dispatcht
}
#readingsSingleUpdate($hash, "state", $hash->{READINGS}{state}{VAL}, $event);
-
+
$hash->{RAWMSG} = $rmsg;
my %addvals = (
DMSG => $dmsg,
@@ -1887,8 +2108,8 @@ sub SIGNALduno_Dispatch($$$$$) {
}
$dmsg = lc($dmsg) if ($id eq '74' or $id eq '74.1'); # 10_FS20.pm accepted only lower case hex
$hash->{logMethod}->($name, SDUINO_DISPATCH_VERBOSE, "$name: Dispatch, $dmsg, $rssi dispatch");
- Dispatch($hash, $dmsg, \%addvals); ## Dispatch to other Modules
-
+ Dispatch($hash, $dmsg, \%addvals); ## Dispatch to other Modules
+
} else {
$hash->{logMethod}->($name, 4, "$name: Dispatch, $dmsg, Dropped due to short time or equal msg");
}
@@ -1896,12 +2117,12 @@ sub SIGNALduno_Dispatch($$$$$) {
}
###############################
-# param #1 is name of definition
+# param #1 is name of definition
# param #2 is protocol id
# param #3 is dispatched message to check against
#
# returns 1 if message matches modulematch + development attribute/whitelistIDs
-# returns 0 if message does not match modulematch
+# returns 0 if message does not match modulematch
# return -1 if message is not activated via whitelistIDs but has developID=m flag
sub SIGNALduino_moduleMatch {
my $name = shift;
@@ -1909,7 +2130,7 @@ sub SIGNALduino_moduleMatch {
my $dmsg = shift;
my $debug = AttrVal($name,"debug",0);
my $modMatchRegex=SIGNALduino_getProtoProp($id,"modulematch",undef);
-
+
if (!defined($modMatchRegex) || $dmsg =~ m/$modMatchRegex/) {
Debug "$name: modmatch passed for: $dmsg" if ($debug);
my $developID = SIGNALduino_getProtoProp($id,"developId","");
@@ -1919,7 +2140,7 @@ sub SIGNALduino_moduleMatch {
return -1;
}
- return 1; # return 1 da modulematch gefunden wurde
+ return 1; # return 1 da modulematch gefunden wurde
}
return 0;
}
@@ -1928,35 +2149,35 @@ sub SIGNALduino_moduleMatch {
sub SIGNALduino_Parse_MS($$$$%) {
my ($hash, $iohash, $name, $rmsg,%msg_parts) = @_;
- my $syncidx=$msg_parts{syncidx};
- my $clockidx=$msg_parts{clockidx};
+ my $syncidx=$msg_parts{syncidx};
+ my $clockidx=$msg_parts{clockidx};
my $rssi=$msg_parts{rssi};
my $rawData=$msg_parts{rawData};
my %patternList;
my $rssiStr= "";
-
+
if (defined($rssi)) {
$rssi = ($rssi>=128 ? (($rssi-256)/2-74) : ($rssi/2-74)); # todo: passt dies so? habe ich vom 00_cul.pm
$rssiStr= " RSSI = $rssi"
}
-
+
#Debug "Message splitted:";
#Debug Dumper(\@msg_parts);
my $debug = AttrVal($iohash->{NAME},"debug",0);
-
+
if (defined($clockidx) and defined($syncidx))
{
-
+
## Make a lookup table for our pattern index ids
#Debug "List of pattern:";
my $clockabs= $msg_parts{pattern}{$msg_parts{clockidx}};
- return undef if ($clockabs == 0);
+ return undef if ($clockabs == 0);
$patternList{$_} = round($msg_parts{pattern}{$_}/$clockabs,1) for keys %{$msg_parts{pattern}};
-
-
- #Debug Dumper(\%patternList);
+
+
+ #Debug Dumper(\%patternList);
#my $syncfact = $patternList{$syncidx}/$patternList{$clockidx};
#$syncfact=$patternList{$syncidx};
@@ -1968,16 +2189,16 @@ sub SIGNALduino_Parse_MS($$$$%) {
## Find matching protocols
my $id;
my $message_dispatched=0;
-
+
IDLOOP:
foreach $id (@{$hash->{msIdList}}) {
-
+
Debug "Testing against Protocol id $id -> $ProtocolListSIGNALduino{$id}{name}" if ($debug);
# Check Clock if is it in range
if ($ProtocolListSIGNALduino{$id}{clockabs} > 0) {
if (!SIGNALduino_inTol($ProtocolListSIGNALduino{$id}{clockabs},$clockabs,$clockabs*0.30)) {
- Debug "protocClock=$ProtocolListSIGNALduino{$id}{clockabs}, msgClock=$clockabs is not in tol=" . $clockabs*0.30 if ($debug);
+ Debug "protocClock=$ProtocolListSIGNALduino{$id}{clockabs}, msgClock=$clockabs is not in tol=" . $clockabs*0.30 if ($debug);
next;
} elsif ($debug) {
Debug "protocClock=$ProtocolListSIGNALduino{$id}{clockabs}, msgClock=$clockabs is in tol=" . $clockabs*0.30;
@@ -1985,7 +2206,7 @@ sub SIGNALduino_Parse_MS($$$$%) {
}
Debug "Searching in patternList: ".Dumper(\%patternList) if($debug);
-
+
my %patternLookupHash=();
my %endPatternLookupHash=();
my $signal_width= @{$ProtocolListSIGNALduino{$id}{one}};
@@ -1993,13 +2214,13 @@ sub SIGNALduino_Parse_MS($$$$%) {
my $message_start;
foreach my $key (qw(sync one zero float) ) {
next if (!exists($ProtocolListSIGNALduino{$id}{$key}));
-
+
if (!SIGNALduino_FillPatternLookupTable($hash,\@{$ProtocolListSIGNALduino{$id}{$key}},\$symbol_map{$key},\%patternList,\$rawData,\%patternLookupHash,\%endPatternLookupHash,\$return_text))
{
Debug sprintf("%s pattern not found",$key) if ($debug);
next IDLOOP if ($key ne "float") ;
}
-
+
if ($key eq "sync")
{
$message_start =index($rawData,$return_text)+length($return_text);
@@ -2014,7 +2235,7 @@ sub SIGNALduino_Parse_MS($$$$%) {
Debug sprintf("Found matched %s with indexes: (%s)",$key,$return_text) if ($debug);
}
next if (scalar keys %patternLookupHash == 0); # Keine Eingträge im patternLookupHash
-
+
$hash->{logMethod}->($name, 4, "$name: Parse_MS, Matched MS Protocol id $id -> $ProtocolListSIGNALduino{$id}{name}");
my @bit_msg; # array to store decoded signal bits
@@ -2043,10 +2264,10 @@ sub SIGNALduino_Parse_MS($$$$%) {
last;
}
}
-
-
+
+
Debug "$name: decoded message raw (@bit_msg), ".@bit_msg." bits\n" if ($debug);
-
+
#Check converted message against lengths
my ($rcode, $rtxt) = SIGNALduino_TestLength(undef,$id,scalar @bit_msg,undef);
if (!$rcode)
@@ -2055,7 +2276,7 @@ sub SIGNALduino_Parse_MS($$$$%) {
next;
}
my $padwith = lib::SD_Protocols::checkProperty($id,'paddingbits',4);
-
+
my $i=0;
while (scalar @bit_msg % $padwith > 0) ## will pad up full nibbles per default or full byte if specified in protocol
{
@@ -2063,43 +2284,43 @@ sub SIGNALduino_Parse_MS($$$$%) {
$i++;
}
Debug "$name padded $i bits to bit_msg array" if ($debug);
-
+
if ($i == 0) {
$hash->{logMethod}->($name, 5, "$name: Parse_MS, dispatching bits: @bit_msg");
} else {
$hash->{logMethod}->($name, 5, "$name: Parse_MS, dispatching bits: @bit_msg with $i Paddingbits 0");
}
-
+
my $evalcheck = (SIGNALduino_getProtoProp($id,"developId","") =~ 'p') ? 1 : undef;
($rcode,my @retvalue) = SIGNALduino_callsub('postDemodulation',$ProtocolListSIGNALduino{$id}{postDemodulation},$evalcheck,$name,@bit_msg);
next if ($rcode < 1 );
#SIGNALduino_Log3 $name, 5, "$name: Parse_MS, postdemodulation value @retvalue";
-
+
@bit_msg = @retvalue;
undef(@retvalue); undef($rcode);
-
+
my $dmsg = SIGNALduino_b2h(join "", @bit_msg);
my $postamble = $ProtocolListSIGNALduino{$id}{postamble};
$dmsg = "$dmsg".$postamble if (defined($postamble));
$dmsg = "$ProtocolListSIGNALduino{$id}{preamble}"."$dmsg" if (defined($ProtocolListSIGNALduino{$id}{preamble}));
-
-
+
+
#my ($rcode,@retvalue) = SIGNALduino_callsub('preDispatchfunc',$ProtocolListSIGNALduino{$id}{preDispatchfunc},$name,$dmsg);
#next if (!$rcode);
#$dmsg = @retvalue;
#undef(@retvalue); undef($rcode);
-
+
if ( SIGNALduino_moduleMatch($name,$id,$dmsg) == 1)
{
$message_dispatched++;
$hash->{logMethod}->($name, 4, "$name: Parse_MS, Decoded matched MS Protocol id $id dmsg $dmsg length " . scalar @bit_msg . " $rssiStr");
SIGNALduno_Dispatch($hash,$rmsg,$dmsg,$rssi,$id);
- }
-
+ }
+
}
-
+
return 0 if (!$message_dispatched);
-
+
return $message_dispatched;
}
@@ -2119,14 +2340,14 @@ sub SIGNALduino_padbits(\@$) {
###############################
#=item SIGNALduino_getProtoProp()
#This functons, will return a value from the Protocolist and check if the key exists and a value is defined optional you can specify a optional default value that will be reurned
-#
+#
# returns "" if the var is not defined
# =cut
# $id, $propertyname,
sub SIGNALduino_getProtoProp {
my ($id,$propNameLst,$default) = @_;
-
+
#my $id = shift;
#my $propNameLst = shift;
return $ProtocolListSIGNALduino{$id}{$propNameLst} if exists($ProtocolListSIGNALduino{$id}{$propNameLst}) && defined($ProtocolListSIGNALduino{$id}{$propNameLst});
@@ -2146,31 +2367,31 @@ sub SIGNALduino_Parse_MU($$$$@) {
my $message_dispatched=0;
my $debug = AttrVal($iohash->{NAME},"debug",0);
my $rssiStr= "";
-
+
if (defined($rssi)) {
$rssi = ($rssi>=128 ? (($rssi-256)/2-74) : ($rssi/2-74)); # todo: passt dies so? habe ich vom 00_cul.pm
$rssiStr= " RSSI = $rssi"
}
-
+
Debug "$name: processing unsynced message\n" if ($debug);
my $clockabs = 1; #Clock will be fetched from Protocol if possible
#$patternListRaw{$_} = floor($msg_parts{pattern}{$_}/$clockabs) for keys $msg_parts{pattern};
$patternListRaw{$_} = $msg_parts{pattern}{$_} for keys %{$msg_parts{pattern}};
-
+
if (defined($clockidx))
{
-
+
## Make a lookup table for our pattern index ids
- #Debug "List of pattern:"; #Debug Dumper(\%patternList);
+ #Debug "List of pattern:"; #Debug Dumper(\%patternList);
## Find matching protocols
my $id;
-
+
IDLOOP:
foreach $id (@{$hash->{muIdList}}) {
-
+
$clockabs= $ProtocolListSIGNALduino{$id}{clockabs};
my %patternList;
$rawData=$msg_parts{rawData};
@@ -2181,32 +2402,32 @@ sub SIGNALduino_Parse_MU($$$$@) {
{
$hash->{logMethod}->($name, 5, "$name: Parse_MU, Error: Unknown filtermethod=$method. Please define it in file $0");
next;
- } else {
+ } else {
$hash->{logMethod}->($name, 5, "$name: Parse_MU, for MU Protocol id $id, applying filterfunc $method");
no strict "refs";
- (my $count_changes,$rawData,my %patternListRaw_tmp) = $method->($name,$id,$rawData,%patternListRaw);
+ (my $count_changes,$rawData,my %patternListRaw_tmp) = $method->($name,$id,$rawData,%patternListRaw);
use strict "refs";
- %patternList = map { $_ => round($patternListRaw_tmp{$_}/$clockabs,1) } keys %patternListRaw_tmp;
+ %patternList = map { $_ => round($patternListRaw_tmp{$_}/$clockabs,1) } keys %patternListRaw_tmp;
}
} else {
- %patternList = map { $_ => round($patternListRaw{$_}/$clockabs,1) } keys %patternListRaw;
+ %patternList = map { $_ => round($patternListRaw{$_}/$clockabs,1) } keys %patternListRaw;
}
-
-
+
+
Debug "Testing against Protocol id $id -> $ProtocolListSIGNALduino{$id}{name}" if ($debug);
Debug "Searching in patternList: ".Dumper(\%patternList) if($debug);
my $startStr=""; # Default match if there is no start pattern available
my $message_start=0 ;
my $startLogStr="";
-
+
if (exists($ProtocolListSIGNALduino{$id}{start}) && defined($ProtocolListSIGNALduino{$id}{start}) && ref($ProtocolListSIGNALduino{$id}{start}) eq 'ARRAY') # wenn start definiert ist, dann startStr ermitteln und in rawData suchen und in der rawData alles bis zum startStr abschneiden
{
Debug "msgStartLst: ".Dumper(\@{$ProtocolListSIGNALduino{$id}{start}}) if ($debug);
-
-
+
+
if ( ($startStr=SIGNALduino_PatternExists($hash,\@{$ProtocolListSIGNALduino{$id}{start}},\%patternList,\$rawData)) eq -1)
{
$hash->{logMethod}->($name, 5, "$name: Parse_MU, start pattern for MU Protocol id $id -> $ProtocolListSIGNALduino{$id}{name} not found, aborting");
@@ -2214,7 +2435,7 @@ sub SIGNALduino_Parse_MU($$$$@) {
}
Debug "startStr is: $startStr" if ($debug);
$message_start = index($rawData, $startStr);
- if ( $message_start == -1)
+ if ( $message_start == -1)
{
Debug "startStr $startStr not found." if ($debug);
next;
@@ -2224,10 +2445,10 @@ sub SIGNALduino_Parse_MU($$$$@) {
Debug "rawData = $rawData" if ($debug);
Debug "startStr $startStr found. Message starts at $message_start" if ($debug);
#SIGNALduino_Log3 $name, 5, "$name: Parse_MU, substr: $rawData"; # todo: entfernen
- }
-
+ }
+
}
-
+
my %patternLookupHash=();
my %endPatternLookupHash=();
my $pstr="";
@@ -2236,7 +2457,7 @@ sub SIGNALduino_Parse_MU($$$$@) {
my $floatRegex ="";
my $return_text="";
my $signalRegex="(?:";
-
+
foreach my $key (qw(one zero float) ) {
next if (!exists($ProtocolListSIGNALduino{$id}{$key}));
if (!SIGNALduino_FillPatternLookupTable($hash,\@{$ProtocolListSIGNALduino{$id}{$key}},\$symbol_map{$key},\%patternList,\$rawData,\%patternLookupHash,\%endPatternLookupHash,\$return_text))
@@ -2256,16 +2477,16 @@ sub SIGNALduino_Parse_MU($$$$@) {
$signalRegex .= ")";
$hash->{logMethod}->($name, 4, "$name: Parse_MU, Fingerprint for MU Protocol id $id -> $ProtocolListSIGNALduino{$id}{name} matches, trying to demodulate");
-
+
my $signal_width= @{$ProtocolListSIGNALduino{$id}{one}};
my $length_min = $ProtocolListSIGNALduino{$id}{length_min};
my $length_max = "";
$length_max = $ProtocolListSIGNALduino{$id}{length_max} if (exists($ProtocolListSIGNALduino{$id}{length_max}));
-
+
$signalRegex .= "{$length_min,}";
-
+
if (exists($ProtocolListSIGNALduino{$id}{reconstructBit})) {
-
+
$signalRegex .= "(?:" . join("|",keys %endPatternLookupHash) . ")?";
}
Debug "signalRegex is $signalRegex " if ($debug);
@@ -2273,29 +2494,29 @@ sub SIGNALduino_Parse_MU($$$$@) {
my $nrRestart=0;
my $nrDispatch=0;
my $regex="(?:$startStr)($signalRegex)";
-
+
while ( $rawData =~ m/$regex/g) {
my $length_str="";
$nrRestart++;
- $hash->{logMethod}->($name, 5, "$name: Parse_MU, part is $1 starts at position $-[0] and ends at ". pos $rawData);
-
+ $hash->{logMethod}->($name, 5, "$name: Parse_MU, part is $1 starts at position $-[0] and ends at ". pos $rawData);
+
my @pairs = unpack "(a$signal_width)*", $1;
-
+
if (exists($ProtocolListSIGNALduino{$id}{length_max}) && scalar @pairs > $ProtocolListSIGNALduino{$id}{length_max}) # ist die Nachricht zu lang?
{
$hash->{logMethod}->($name, 5, "$name: Parse_MU, $nrRestart. skip demodulation (length ".scalar @pairs." is to long) at Pos $-[0] regex ($regex)");
next;
}
-
+
if ($nrRestart == 1) {
- $hash->{logMethod}->($name, 5, "$name: Parse_MU, Starting demodulation ($startLogStr " . "regex: $regex Pos $message_start) length_min_max (".$length_min."..".$length_max.") length=".scalar @pairs);
+ $hash->{logMethod}->($name, 5, "$name: Parse_MU, Starting demodulation ($startLogStr " . "regex: $regex Pos $message_start) length_min_max (".$length_min."..".$length_max.") length=".scalar @pairs);
} else {
$hash->{logMethod}->($name, 5, "$name: Parse_MU, $nrRestart. try demodulation$length_str at Pos $-[0]");
}
-
+
my @bit_msg=(); # array to store decoded signal bits
-
+
foreach my $sigStr (@pairs)
{
if (exists $patternLookupHash{$sigStr}) {
@@ -2307,37 +2528,37 @@ sub SIGNALduino_Parse_MU($$$$@) {
$hash->{logMethod}->($name, 4, "$name: Parse_MU, last part pair=$sigStr reconstructed, bit=$lastbit");
}
}
-
+
Debug "$name: demodulated message raw (@bit_msg), ".@bit_msg." bits\n" if ($debug);
my $evalcheck = (SIGNALduino_getProtoProp($id,"developId","") =~ 'p') ? 1 : undef;
my ($rcode,@retvalue) = SIGNALduino_callsub('postDemodulation',$ProtocolListSIGNALduino{$id}{postDemodulation},$evalcheck,$name,@bit_msg);
-
+
next if ($rcode < 1 );
@bit_msg = @retvalue;
undef(@retvalue); undef($rcode);
-
- my $dispmode="hex";
+
+ my $dispmode="hex";
$dispmode="bin" if (SIGNALduino_getProtoProp($id,"dispatchBin",0) == 1 );
-
+
my $padwith = lib::SD_Protocols::checkProperty($id,'paddingbits',4);
while (scalar @bit_msg % $padwith > 0) ## will pad up full nibbles per default or full byte if specified in protocol
{
push(@bit_msg,'0');
Debug "$name: padding 0 bit to bit_msg array" if ($debug);
- }
+ }
my $dmsg = join ("", @bit_msg);
my $bit_length=scalar @bit_msg;
@bit_msg=(); # clear bit_msg array
$dmsg = SIGNALduino_b2h($dmsg) if (SIGNALduino_getProtoProp($id,"dispatchBin",0) == 0 );
-
+
$dmsg =~ s/^0+// if ( SIGNALduino_getProtoProp($id,"remove_zero",0) );
-
+
$dmsg=sprintf("%s%s%s",SIGNALduino_getProtoProp($id,"preamble",""),$dmsg,SIGNALduino_getProtoProp($id,"postamble",""));
$hash->{logMethod}->($name, 5, "$name: Parse_MU, dispatching $dispmode: $dmsg");
-
+
if ( SIGNALduino_moduleMatch($name,$id,$dmsg) == 1)
{
$nrDispatch++;
@@ -2347,15 +2568,15 @@ sub SIGNALduino_Parse_MU($$$$@) {
{
last;
}
- }
+ }
}
$hash->{logMethod}->($name, 5, "$name: Parse_MU, $nrRestart. try, regex ($regex) did not match") if ($nrRestart == 0);
$message_dispatched=$message_dispatched+$nrDispatch;
}
- return $message_dispatched;
-
+ return $message_dispatched;
+
}
}
@@ -2375,13 +2596,13 @@ sub SIGNALduino_Parse_MC($$$$@) {
if (defined($rssi)) {
$rssi = ($rssi>=128 ? (($rssi-256)/2-74) : ($rssi/2-74)); # todo: passt dies so? habe ich vom 00_cul.pm
}
-
+
return undef if (!$clock);
#my $protocol=undef;
#my %patternListRaw = %msg_parts{patternList};
-
+
Debug "$name: processing manchester messag len:".length($rawData) if ($debug);
-
+
my $hlen = length($rawData);
my $blen;
#if (defined($mcbitnum)) {
@@ -2390,10 +2611,10 @@ sub SIGNALduino_Parse_MC($$$$@) {
$blen = $hlen * 4;
#}
my $id;
-
+
my $rawDataInverted;
($rawDataInverted = $rawData) =~ tr/0123456789ABCDEF/FEDCBA9876543210/; # Some Manchester Data is inverted
-
+
foreach $id (@{$hash->{mcIdList}}) {
#next if ($blen < $ProtocolListSIGNALduino{$id}{length_min} || $blen > $ProtocolListSIGNALduino{$id}{length_max});
@@ -2407,7 +2628,7 @@ sub SIGNALduino_Parse_MC($$$$@) {
} else {
$hash->{logMethod}->($name, 4, "$name: Parse_MC, Found manchester Protocol id $id clock $clock -> $ProtocolListSIGNALduino{$id}{name}");
}
-
+
my $polarityInvert = 0;
if (exists($ProtocolListSIGNALduino{$id}{polarity}) && ($ProtocolListSIGNALduino{$id}{polarity} eq 'invert'))
{
@@ -2419,14 +2640,14 @@ sub SIGNALduino_Parse_MC($$$$@) {
}
if ($polarityInvert == 1)
{
- $bitData= unpack("B$blen", pack("H$hlen", $rawDataInverted));
-
+ $bitData= unpack("B$blen", pack("H$hlen", $rawDataInverted));
+
} else {
- $bitData= unpack("B$blen", pack("H$hlen", $rawData));
+ $bitData= unpack("B$blen", pack("H$hlen", $rawData));
}
Debug "$name: extracted data $bitData (bin)\n" if ($debug); ## Convert Message from hex to bits
$hash->{logMethod}->($name, 5, "$name: Parse_MC, extracted data $bitData (bin)");
-
+
my $method = lib::SD_Protocols::getProperty($id,"method");
if (!exists &$method || !defined &{ $method })
{
@@ -2436,7 +2657,7 @@ sub SIGNALduino_Parse_MC($$$$@) {
my ($rcode,$res) = $method->($name,$bitData,$id,$mcbitnum);
if ($rcode != -1) {
$dmsg = $res;
- $dmsg=$ProtocolListSIGNALduino{$id}{preamble}.$dmsg if (defined($ProtocolListSIGNALduino{$id}{preamble}));
+ $dmsg=$ProtocolListSIGNALduino{$id}{preamble}.$dmsg if (defined($ProtocolListSIGNALduino{$id}{preamble}));
my $modulematch;
if (defined($ProtocolListSIGNALduino{$id}{modulematch})) {
$modulematch = $ProtocolListSIGNALduino{$id}{modulematch};
@@ -2464,12 +2685,12 @@ sub SIGNALduino_Parse_MC($$$$@) {
}
} else {
$res="undef" if (!defined($res));
- $hash->{logMethod}->($name, 5, "$name: Parse_MC, protocol does not match return from method: ($res)") ;
+ $hash->{logMethod}->($name, 5, "$name: Parse_MC, protocol does not match return from method: ($res)") ;
}
}
}
-
+
}
return 0 if (!$message_dispatched);
return 1;
@@ -2480,8 +2701,8 @@ sub SIGNALduino_Parse($$$$@) {
my ($hash, $iohash, $name, $rmsg, $initstr) = @_;
#print Dumper(\%ProtocolListSIGNALduino);
-
-
+
+
if (!($rmsg=~ s/^\002(M.;.*;)\003/$1/)) # Check if a Data Message arrived and if it's complete (start & end control char are received)
{ # cut off start end end character from message for further processing they are not needed
$hash->{logMethod}->($name, AttrVal($name,"noMsgVerbose",5), "$name: Parse, noMsg: $rmsg");
@@ -2492,24 +2713,24 @@ sub SIGNALduino_Parse($$$$@) {
$hash->{keepalive}{ok} = 1;
$hash->{keepalive}{retry} = 0;
}
-
+
my $debug = AttrVal($iohash->{NAME},"debug",0);
-
-
+
+
Debug "$name: incoming message: ($rmsg)\n" if ($debug);
-
+
if (AttrVal($name, "rawmsgEvent", 0)) {
DoTrigger($name, "RAWMSG " . $rmsg);
}
-
+
my %signal_parts=SIGNALduino_Split_Message($rmsg,$name); ## Split message and save anything in an hash %signal_parts
#Debug "raw data ". $signal_parts{rawData};
-
-
+
+
my $dispatched;
# Message Synced type -> M#
- if (@{$hash->{msIdList}} && $rmsg=~ m/^MS;(P\d=-?\d+;){3,8}D=\d+;CP=\d;SP=\d;/)
+ if (@{$hash->{msIdList}} && $rmsg=~ m/^MS;(P\d=-?\d+;){3,8}D=\d+;CP=\d;SP=\d;/)
{
$dispatched= SIGNALduino_Parse_MS($hash, $iohash, $name, $rmsg,%signal_parts);
}
@@ -2519,7 +2740,7 @@ sub SIGNALduino_Parse($$$$@) {
$dispatched= SIGNALduino_Parse_MU($hash, $iohash, $name, $rmsg,%signal_parts);
}
# Manchester encoded Data -> MC
- elsif (@{$hash->{mcIdList}} && $rmsg=~ m/^M[cC];.*;/)
+ elsif (@{$hash->{mcIdList}} && $rmsg=~ m/^M[cC];.*;/)
{
$dispatched= SIGNALduino_Parse_MC($hash, $iohash, $name, $rmsg,%signal_parts);
}
@@ -2527,14 +2748,14 @@ sub SIGNALduino_Parse($$$$@) {
Debug "$name: unknown Messageformat, aborting\n" if ($debug);
return undef;
}
-
+
if ( AttrVal($hash->{NAME},"verbose","0") > 4 && !$dispatched)
{
my $notdisplist;
my @lines;
if (defined($hash->{unknownmessages}))
{
- $notdisplist=$hash->{unknownmessages};
+ $notdisplist=$hash->{unknownmessages};
@lines = split ('#', $notdisplist); # or whatever
}
push(@lines,FmtDateTime(time())."-".$rmsg);
@@ -2546,7 +2767,7 @@ sub SIGNALduino_Parse($$$$@) {
#Todo compare Sync/Clock fact and length of D= if equal, then it's the same protocol!
}
return $dispatched;
-
+
}
@@ -2558,7 +2779,7 @@ sub SIGNALduino_Ready($) {
$hash->{DevState} = 'disconnected';
return DevIo_OpenDev($hash, 1, "SIGNALduino_DoInit", 'SIGNALduino_Connect')
}
-
+
# This is relevant for windows/USB only
my $po = $hash->{USBDev};
my ($BlockingFlags, $InBytes, $OutBytes, $ErrorFlags);
@@ -2571,9 +2792,9 @@ sub SIGNALduino_Ready($) {
###############################
sub SIGNALduino_WriteInit($) {
my ($hash) = @_;
-
+
# todo: ist dies so ausreichend, damit die Aenderungen uebernommen werden?
- SIGNALduino_AddSendQueue($hash,"WS36"); # SIDLE, Exit RX / TX, turn off frequency synthesizer
+ SIGNALduino_AddSendQueue($hash,"WS36"); # SIDLE, Exit RX / TX, turn off frequency synthesizer
SIGNALduino_AddSendQueue($hash,"WS34"); # SRX, Enable RX. Perform calibration first if coming from IDLE and MCSM0.FS_AUTOCAL=1.
}
@@ -2583,7 +2804,7 @@ sub SIGNALduino_SimpleWrite(@) {
return if(!$hash);
if($hash->{TYPE} eq "SIGNALduino_RFR") {
# Prefix $msg with RRBBU and return the corresponding SIGNALduino hash.
- ($hash, $msg) = SIGNALduino_RFR_AddPrefix($hash, $msg);
+ ($hash, $msg) = SIGNALduino_RFR_AddPrefix($hash, $msg);
}
my $name = $hash->{NAME};
@@ -2604,10 +2825,10 @@ sub SIGNALduino_Attr(@) {
my ($cmd,$name,$aName,$aVal) = @_;
my $hash = $defs{$name};
my $debug = AttrVal($name,"debug",0);
-
+
$aVal= "" if (!defined($aVal));
$hash->{logMethod}->($name, 4, "$name: Attr, Calling sub with args: $cmd $aName = $aVal");
-
+
if( $aName eq "Clients" ) { ## Change clientList
$hash->{Clients} = $aVal;
$hash->{Clients} = $clientsSIGNALduino if( !$hash->{Clients}) ; ## Set defaults
@@ -2620,7 +2841,7 @@ sub SIGNALduino_Attr(@) {
$hash->{logMethod}->($name, 2, $name .": Attr, $aVal: ". $@);
}
}
-
+
if( ref($match_list) eq 'HASH' ) {
$hash->{MatchList} = $match_list;
} else {
@@ -2632,7 +2853,7 @@ sub SIGNALduino_Attr(@) {
{
$hash->{logMethod}->($name, 3, "$name: Attr, setting Verbose to: " . $aVal);
$hash->{unknownmessages}="" if $aVal <4;
-
+
}
elsif ($aName eq "debug")
{
@@ -2678,17 +2899,18 @@ sub SIGNALduino_Attr(@) {
}
}
}
- elsif ($aName eq "cc1101_frequency")
- {
- if ($aVal eq "" || $aVal < 800) {
- $hash->{logMethod}->($name, 3, "$name: Attr, delete cc1101_frequency");
- delete ($hash->{cc1101_frequency}) if (defined($hash->{cc1101_frequency}));
- } else {
- $hash->{logMethod}->($name, 3, "$name: Attr, setting cc1101_frequency to 868");
- $hash->{cc1101_frequency} = 868;
- }
- }
-
+ ####### Beginn kann wahrscheinlich weg #######
+ # elsif ($aName eq "cc1101_frequency")
+ # {
+ # if ($aVal eq "" || $aVal < 800) {
+ # $hash->{logMethod}->($name, 3, "$name: Attr, delete cc1101_frequency");
+ # delete ($hash->{cc1101_frequency}) if (defined($hash->{cc1101_frequency}));
+ # } else {
+ # $hash->{logMethod}->($name, 3, "$name: Attr, setting cc1101_frequency to 868");
+ # $hash->{cc1101_frequency} = 868;
+ # }
+ # }
+ ####### Ende kann wahrscheinlich weg #######
elsif ($aName eq "hardware") # to set flashCommand if hardware def or change
{
# to delete flashCommand if hardware delete
@@ -2699,36 +2921,36 @@ sub SIGNALduino_Attr(@) {
elsif ($aName eq "eventlogging") # enable / disable eventlogging
{
if ($aVal == 1) {
- $hash->{logMethod} = \&::SIGNALduino_Log3;
+ $hash->{logMethod} = \&::SIGNALduino_Log3;
Log3 $name, 3, "$name: Attr, Enable eventlogging";
} else {
- $hash->{logMethod} = \&::Log3;
+ $hash->{logMethod} = \&::Log3;
Log3 $name, 3, "$name: Attr, Disable eventlogging";
}
}
-
+
return undef;
}
###############################
sub SIGNALduino_FW_Detail($@) {
my ($FW_wname, $name, $room, $pageHash) = @_;
-
+
my $hash = $defs{$name};
-
+
my @dspec=devspec2array("DEF=.*fakelog");
my $lfn = $dspec[0];
my $fn=$defs{$name}->{TYPE}."-Flash.log";
-
+
my $ret = "Information menu
-
+