I also found over several weeks of using sonoffs with Domoticz that switching wasn't always reliable. I solved this by getting the on/off actions in Domoticz to kick off a perl job that will keep sending commands to the sonoff until it reports back (via JSON) that it's current state really is the state intended by Domoticz. Feel free to take ideas from it. The script on/off commands in Domoticz now look like:
script://exec.sh ipswitch swGuestroomLamp on
script://exec.sh ipswitch swGuestroomLamp off
where the perl code below is in a file named ipswitch.pl and the contents of exec.sh are
Code: Select all
#! /bin/sh
/usr/bin/perl /home/pi/domoticz/scripts/$1.pl $2 $3 > /dev/null 2>&1 &
Note that if you don't wrap calls to external scripts that cause significant delays in a shell script with an '&' at the end, Domoticz will wait for the external script to finish and you don't want that.
Here's the code that actually talks back and forth to the sonoff:
Code: Select all
#!/usr/bin/perl
use JSON::XS;
use LWP::UserAgent;
no warnings 'uninitialized';
# sets a Sonoff device on/off on behalf of Domoticz and then checks that it actually switched accordingly (in case of packet-loss)
($device, $action, $dbg)=@ARGV; # e.g. swGuestroomLamp, on / off
our $debug = ( $dbg == 1 ) || 0; $action=lc($action); $tries=0;
%sonoffs=(
swWardrobeLamp => { ip => '27', idx => '388' },
swAudioengines => { ip => '29', idx => '387' },
swBedroomLamp => { ip => '33', idx => '393' },
swGuestroomLamp => { ip => '34', idx => '394' },
);
$ua=LWP::UserAgent->new; $ua->timeout(1); $ua->env_proxy;
do {
# First send the command to the Sonoff
$url="http://192.168.178.".$sonoffs{$device}{ip}."/control?cmd=event,lamp_$action"; $c=0;
do { $c++;
$response=$ua->get($url);
} until ( ($response->is_success) || ($c==5) );
# Now check if it reacted
$url="http://192.168.178.".$sonoffs{$device}{ip}."/json"; $c=0;
do {
sleep 1; $c++;
$response=$ua->get($url);
} until ( ($response->is_success) || ($c==10) );
if ($response->is_success) {
$devices=$response->decoded_content; $data=decode_json $devices;
foreach $entry (@{$$data{Sensors}}) {
foreach $x (sort keys %{$entry}) { if ($$entry{$x} eq 'relay') { $state=$$entry{state} } };
}};
$ok=( ($action eq 'off') && ($state==0) ) || ( ($action eq 'on') && ($state==1) ); $tries++;
} until ( ($ok) || ($tries==5) );
print "$device: $action --> $state\n" if ($debug);