mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-04-20 19:36:02 +00:00
OWX_ASYNC: cleanup and refactor interface to busmaster-classes (do all nested protothreads)
Merge branch 'owx_protothreads' git-svn-id: https://svn.fhem.de/fhem/trunk@6259 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
1d098fe7c6
commit
fbf43ce944
@ -128,7 +128,7 @@ my %attrs = (
|
|||||||
);
|
);
|
||||||
|
|
||||||
#-- some globals needed for the 1-Wire module
|
#-- some globals needed for the 1-Wire module
|
||||||
$owx_async_version=5.4;
|
$owx_async_version=5.5;
|
||||||
#-- Debugging 0,1,2,3
|
#-- Debugging 0,1,2,3
|
||||||
$owx_async_debug=0;
|
$owx_async_debug=0;
|
||||||
|
|
||||||
@ -251,7 +251,7 @@ sub OWX_ASYNC_Attr(@) {
|
|||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub OWX_ASYNC_Notify {
|
sub OWX_ASYNC_Notify ($$) {
|
||||||
my ($hash,$dev) = @_;
|
my ($hash,$dev) = @_;
|
||||||
my $name = $hash->{NAME};
|
my $name = $hash->{NAME};
|
||||||
my $type = $hash->{TYPE};
|
my $type = $hash->{TYPE};
|
||||||
@ -276,12 +276,14 @@ sub OWX_ASYNC_Ready ($) {
|
|||||||
|
|
||||||
sub OWX_ASYNC_Read ($) {
|
sub OWX_ASYNC_Read ($) {
|
||||||
my $hash = shift;
|
my $hash = shift;
|
||||||
|
Log3 ($hash->{NAME},5,"OWX_ASYNC_Read") if ($owx_async_debug > 2);
|
||||||
OWX_ASYNC_Poll($hash);
|
OWX_ASYNC_Poll($hash);
|
||||||
OWX_ASYNC_RunTasks($hash);
|
OWX_ASYNC_RunTasks($hash);
|
||||||
};
|
};
|
||||||
|
|
||||||
sub OWX_ASYNC_Poll ($) {
|
sub OWX_ASYNC_Poll ($) {
|
||||||
my $hash = shift;
|
my $hash = shift;
|
||||||
|
Log3 ($hash->{NAME},5,"OWX_ASYNC_Poll") if ($owx_async_debug > 2);
|
||||||
if (defined $hash->{ASYNC}) {
|
if (defined $hash->{ASYNC}) {
|
||||||
$hash->{ASYNC}->poll($hash);
|
$hash->{ASYNC}->poll($hash);
|
||||||
};
|
};
|
||||||
@ -326,56 +328,35 @@ sub OWX_ASYNC_Disconnected($) {
|
|||||||
#TODO fix OWX_ASYNC_Alarms return value on failure
|
#TODO fix OWX_ASYNC_Alarms return value on failure
|
||||||
########################################################################################
|
########################################################################################
|
||||||
|
|
||||||
sub OWX_ASYNC_Alarms ($) {
|
sub OWX_ASYNC_PT_Alarms ($) {
|
||||||
my ($hash) = @_;
|
my ($hash) = @_;
|
||||||
|
|
||||||
#-- get the interface
|
#-- get the interface
|
||||||
my $name = $hash->{NAME};
|
|
||||||
my $async = $hash->{ASYNC};
|
my $async = $hash->{ASYNC};
|
||||||
my $res;
|
|
||||||
|
|
||||||
|
#-- Discover all devices on the 1-Wire bus, they will be found in $hash->{DEVS}
|
||||||
if (defined $async) {
|
if (defined $async) {
|
||||||
delete $hash->{ALARMDEVS};
|
return PT_THREAD(sub {
|
||||||
return $async->alarms($hash);
|
my ($thread) = @_;
|
||||||
|
PT_BEGIN($thread);
|
||||||
|
$thread->{pt_alarms} = $async->get_pt_alarms();
|
||||||
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
|
PT_WAIT_THREAD($thread->{pt_alarms});
|
||||||
|
delete $thread->{TimeoutTime};
|
||||||
|
die $thread->{pt_alarms}->PT_CAUSE() if ($thread->{pt_alarms}->PT_STATE() == PT_ERROR);
|
||||||
|
if (defined (my $alarmed_devs = $thread->{pt_alarms}->PT_RETVAL())) {
|
||||||
|
OWX_ASYNC_AfterAlarms($hash,$alarmed_devs);
|
||||||
|
};
|
||||||
|
PT_END;
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
#-- interface error
|
|
||||||
my $owx_interface = $hash->{INTERFACE};
|
my $owx_interface = $hash->{INTERFACE};
|
||||||
if( !(defined($owx_interface))){
|
if( !defined($owx_interface) ) {
|
||||||
return undef;
|
die "OWX: Alarms called with undefined interface on bus $hash->{NAME}";
|
||||||
} else {
|
} else {
|
||||||
return "OWX: Alarms called with unknown interface $owx_interface on bus $name";
|
die "OWX: Alarms called with unknown interface $owx_interface on bus $hash->{NAME}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
#######################################################################################
|
|
||||||
#
|
|
||||||
# OWX_ASYNC_AwaitAlarmsResponse - Wait for the result of a call to OWX_ASYNC_Alarms
|
|
||||||
#
|
|
||||||
# Parameter hash = hash of bus master
|
|
||||||
#
|
|
||||||
# Return: Reference to Array of alarmed 1-Wire-addresses found on 1-Wire bus.
|
|
||||||
# undef if timeout occours
|
|
||||||
#
|
|
||||||
########################################################################################
|
|
||||||
|
|
||||||
sub OWX_ASYNC_AwaitAlarmsResponse($) {
|
|
||||||
my ($hash) = @_;
|
|
||||||
|
|
||||||
#-- get the interface
|
|
||||||
my $async = $hash->{ASYNC};
|
|
||||||
if (defined $async) {
|
|
||||||
my $times = AttrVal($hash->{NAME},"timeout",5000) / 50; #timeout in ms, defaults to 1 sec #TODO add attribute timeout?
|
|
||||||
for (my $i=0;$i<$times;$i++) {
|
|
||||||
if(! defined $hash->{ALARMDEVS} ) {
|
|
||||||
select (undef,undef,undef,0.05);
|
|
||||||
$async->poll($hash);
|
|
||||||
} else {
|
|
||||||
return $hash->{ALARMDEVS};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
return undef;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
########################################################################################
|
########################################################################################
|
||||||
@ -395,63 +376,22 @@ sub OWX_ASYNC_AwaitAlarmsResponse($) {
|
|||||||
|
|
||||||
sub OWX_ASYNC_AfterAlarms($$) {
|
sub OWX_ASYNC_AfterAlarms($$) {
|
||||||
my ($hash,$alarmed_devs) = @_;
|
my ($hash,$alarmed_devs) = @_;
|
||||||
$hash->{ALARMDEVS} = $alarmed_devs;
|
my @alarmed_devnames = ();
|
||||||
GP_ForallClients($hash,sub {
|
GP_ForallClients($hash,sub {
|
||||||
my ($hash,$devs) = @_;
|
my ($client) = @_;
|
||||||
my $romid = $hash->{ROM_ID};
|
my $romid = $client->{ROM_ID};
|
||||||
if (grep {/$romid/} @$devs) {
|
Log3 ($client->{IODev}->{NAME},5,"OWX_ASYNC_AfterAlarms client NAME: $client->{NAME}, ROM_ID: $romid, ALARM: $client->{ALARM}, alarmed_devs: [".join(",",@$alarmed_devs)."]") if ($owx_async_debug>2);
|
||||||
readingsSingleUpdate($hash,"alarm",1,!$hash->{ALARM});
|
if (grep {$romid eq $_} @$alarmed_devs) {
|
||||||
$hash->{ALARM}=1;
|
readingsSingleUpdate($client,"alarm",1,!$client->{ALARM});
|
||||||
|
$client->{ALARM}=1;
|
||||||
|
push (@alarmed_devnames,$client->{NAME});
|
||||||
} else {
|
} else {
|
||||||
readingsSingleUpdate($hash,"alarm",0, $hash->{ALARM});
|
readingsSingleUpdate($client,"alarm",0, $client->{ALARM});
|
||||||
$hash->{ALARM}=0;
|
$client->{ALARM}=0;
|
||||||
}
|
|
||||||
},$alarmed_devs);
|
|
||||||
};
|
|
||||||
|
|
||||||
########################################################################################
|
|
||||||
#
|
|
||||||
# OWX_ASYNC_DiscoverAlarms - Search for devices on the 1-Wire bus which have the alarm flag set
|
|
||||||
#
|
|
||||||
# Parameter hash = hash of bus master
|
|
||||||
#
|
|
||||||
# Return: Message or list of alarmed devices
|
|
||||||
#
|
|
||||||
########################################################################################
|
|
||||||
|
|
||||||
sub OWX_ASYNC_DiscoverAlarms($) {
|
|
||||||
my ($hash) = @_;
|
|
||||||
if (OWX_ASYNC_Alarms($hash)) {
|
|
||||||
if (my $alarmed_devs = OWX_ASYNC_AwaitAlarmsResponse($hash)) {
|
|
||||||
my @owx_alarm_names=();
|
|
||||||
my $name = $hash->{NAME};
|
|
||||||
|
|
||||||
if( $alarmed_devs == 0){
|
|
||||||
return "OWX: No alarmed 1-Wire devices found on bus $name";
|
|
||||||
}
|
|
||||||
#-- walk through all the devices to get their proper fhem names
|
|
||||||
foreach my $fhem_dev (sort keys %main::defs) {
|
|
||||||
#-- skip if busmaster
|
|
||||||
next if( $name eq $main::defs{$fhem_dev}{NAME} );
|
|
||||||
#-- all OW types start with OW
|
|
||||||
next if( substr($main::defs{$fhem_dev}{TYPE},0,2) ne "OW");
|
|
||||||
foreach my $owx_dev (@{$alarmed_devs}) {
|
|
||||||
#-- two pieces of the ROM ID found on the bus
|
|
||||||
my $owx_rnf = substr($owx_dev,3,12);
|
|
||||||
my $owx_f = substr($owx_dev,0,2);
|
|
||||||
my $id_owx = $owx_f.".".$owx_rnf;
|
|
||||||
|
|
||||||
#-- skip if not in alarm list
|
|
||||||
if( $owx_dev eq $main::defs{$fhem_dev}{ROM_ID} ){
|
|
||||||
$main::defs{$fhem_dev}{STATE} = "Alarmed";
|
|
||||||
push(@owx_alarm_names,$main::defs{$fhem_dev}{NAME});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#-- so far, so good - what do we want to do with this ?
|
|
||||||
return "OWX: ".scalar(@owx_alarm_names)." alarmed 1-Wire devices found on bus $name (".join(",",@owx_alarm_names).")";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
$hash->{ALARMDEVS} = \@alarmed_devnames;
|
||||||
|
Log3 ($hash->{NAME},5,"OWX_ASYNC_AfterAlarms: ALARMDEVS = [".join(",",@alarmed_devnames)."]") if ($owx_async_debug>2);
|
||||||
};
|
};
|
||||||
|
|
||||||
########################################################################################
|
########################################################################################
|
||||||
@ -465,14 +405,34 @@ sub OWX_ASYNC_DiscoverAlarms($) {
|
|||||||
#
|
#
|
||||||
########################################################################################
|
########################################################################################
|
||||||
|
|
||||||
sub OWX_ASYNC_Discover ($) {
|
sub OWX_ASYNC_PT_Discover ($) {
|
||||||
my ($hash) = @_;
|
my ($hash) = @_;
|
||||||
if (OWX_ASYNC_Search($hash)) {
|
|
||||||
if (my $owx_devices = OWX_ASYNC_AwaitSearchResponse($hash)) {
|
#-- get the interface
|
||||||
return OWX_ASYNC_AutoCreate($hash,$owx_devices);
|
my $async = $hash->{ASYNC};
|
||||||
|
|
||||||
|
#-- Discover all devices on the 1-Wire bus, they will be found in $hash->{DEVS}
|
||||||
|
if (defined $async) {
|
||||||
|
return PT_THREAD(sub {
|
||||||
|
my ($thread) = @_;
|
||||||
|
PT_BEGIN($thread);
|
||||||
|
$thread->{pt_discover} = $async->get_pt_discover();
|
||||||
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
|
PT_WAIT_THREAD($thread->{pt_discover});
|
||||||
|
delete $thread->{TimeoutTime};
|
||||||
|
die $thread->{pt_discover}->PT_CAUSE() if ($thread->{pt_discover}->PT_STATE() == PT_ERROR);
|
||||||
|
if (my $owx_devices = $thread->{pt_discover}->PT_RETVAL()) {
|
||||||
|
PT_EXIT(OWX_ASYNC_AutoCreate($hash,$owx_devices));
|
||||||
};
|
};
|
||||||
|
PT_END;
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
return undef;
|
my $owx_interface = $hash->{INTERFACE};
|
||||||
|
if( !defined($owx_interface) ) {
|
||||||
|
die "OWX: Discover called with undefined interface on bus $hash->{NAME}";
|
||||||
|
} else {
|
||||||
|
die "OWX: Discover called with unknown interface $owx_interface on bus $hash->{NAME}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -486,61 +446,37 @@ sub OWX_ASYNC_Discover ($) {
|
|||||||
#
|
#
|
||||||
########################################################################################
|
########################################################################################
|
||||||
|
|
||||||
sub OWX_ASYNC_Search($) {
|
sub OWX_ASYNC_PT_Search($) {
|
||||||
my ($hash) = @_;
|
my ($hash) = @_;
|
||||||
|
|
||||||
my $res;
|
|
||||||
my $ow_dev;
|
|
||||||
|
|
||||||
#-- get the interface
|
#-- get the interface
|
||||||
my $async = $hash->{ASYNC};
|
my $async = $hash->{ASYNC};
|
||||||
|
|
||||||
#-- Discover all devices on the 1-Wire bus, they will be found in $hash->{DEVS}
|
#-- Discover all devices on the 1-Wire bus, they will be found in $hash->{DEVS}
|
||||||
if (defined $async) {
|
if (defined $async) {
|
||||||
delete $hash->{DEVS};
|
return PT_THREAD(sub {
|
||||||
return $async->discover($hash);
|
my ($thread) = @_;
|
||||||
|
PT_BEGIN($thread);
|
||||||
|
$thread->{pt_discover} = $async->get_pt_discover();
|
||||||
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
|
PT_WAIT_THREAD($thread->{pt_discover});
|
||||||
|
delete $thread->{TimeoutTime};
|
||||||
|
die $thread->{pt_discover}->PT_CAUSE() if ($thread->{pt_discover}->PT_STATE() == PT_ERROR);
|
||||||
|
if (defined (my $owx_devs = $thread->{pt_discover}->PT_RETVAL())) {
|
||||||
|
OWX_ASYNC_AfterSearch($hash,$owx_devs);
|
||||||
|
}
|
||||||
|
PT_END;
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
my $owx_interface = $hash->{INTERFACE};
|
my $owx_interface = $hash->{INTERFACE};
|
||||||
if( !defined($owx_interface) ) {
|
if( !defined($owx_interface) ) {
|
||||||
return undef;
|
die "OWX: Search called with undefined interface on bus $hash->{NAME}";
|
||||||
} else {
|
} else {
|
||||||
Log3 ($hash->{NAME},3,"OWX: Search called with unknown interface $owx_interface");
|
die "OWX: Search called with unknown interface $owx_interface on bus $hash->{NAME}";
|
||||||
return undef;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#######################################################################################
|
|
||||||
#
|
|
||||||
# OWX_ASYNC_AwaitSearchResponse - Wait for the result of a call to OWX_ASYNC_Search
|
|
||||||
#
|
|
||||||
# Parameter hash = hash of bus master
|
|
||||||
#
|
|
||||||
# Return: Reference to Array of 1-Wire-addresses found on 1-Wire bus.
|
|
||||||
# undef if timeout occours
|
|
||||||
#
|
|
||||||
########################################################################################
|
|
||||||
|
|
||||||
sub OWX_ASYNC_AwaitSearchResponse($) {
|
|
||||||
my ($hash) = @_;
|
|
||||||
#-- get the interface
|
|
||||||
my $async = $hash->{ASYNC};
|
|
||||||
|
|
||||||
#-- Discover all devices on the 1-Wire bus, they will be found in $hash->{DEVS}
|
|
||||||
if (defined $async) {
|
|
||||||
my $times = AttrVal($hash->{NAME},"timeout",5000) / 50; #timeout in ms, defaults to 1 sec #TODO add attribute timeout?
|
|
||||||
for (my $i=0;$i<$times;$i++) {
|
|
||||||
if(! defined $hash->{DEVS} ) {
|
|
||||||
select (undef,undef,undef,0.05);
|
|
||||||
$async->poll($hash);
|
|
||||||
} else {
|
|
||||||
return $hash->{DEVS};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
return undef;
|
|
||||||
};
|
|
||||||
|
|
||||||
########################################################################################
|
########################################################################################
|
||||||
#
|
#
|
||||||
# OWX_ASYNC_AfterSearch - is called when the search initiated by OWX_ASYNC_Search successfully returns
|
# OWX_ASYNC_AfterSearch - is called when the search initiated by OWX_ASYNC_Search successfully returns
|
||||||
@ -558,20 +494,24 @@ sub OWX_ASYNC_AwaitSearchResponse($) {
|
|||||||
|
|
||||||
sub OWX_ASYNC_AfterSearch($$) {
|
sub OWX_ASYNC_AfterSearch($$) {
|
||||||
my ($hash,$owx_devs) = @_;
|
my ($hash,$owx_devs) = @_;
|
||||||
if (defined $owx_devs and (ref($owx_devs) eq "ARRAY")) {
|
# if (defined $owx_devs and (ref($owx_devs) eq "ARRAY")) {
|
||||||
$hash->{DEVS} = $owx_devs;
|
my @devnames = ();
|
||||||
GP_ForallClients($hash,sub {
|
GP_ForallClients($hash,sub {
|
||||||
my ($hash,$devs) = @_;
|
my ($client) = @_;
|
||||||
my $romid = $hash->{ROM_ID};
|
my $romid = $client->{ROM_ID};
|
||||||
if (grep {/$romid/} @$devs) {
|
Log3 ($client->{IODev}->{NAME},5,"OWX_ASYNC_AfterSearch client NAME: $client->{NAME}, ROM_ID: $romid, PRESENT: $client->{PRESENT}, devs: [".join(",",@$owx_devs)."]") if ($owx_async_debug>2);
|
||||||
readingsSingleUpdate($hash,"present",1,!$hash->{PRESENT});
|
if (grep {$romid eq $_} @$owx_devs) {
|
||||||
$hash->{PRESENT} = 1;
|
readingsSingleUpdate($client,"present",1,!$client->{PRESENT});
|
||||||
|
$client->{PRESENT} = 1;
|
||||||
|
push (@devnames,$client->{NAME});
|
||||||
} else {
|
} else {
|
||||||
readingsSingleUpdate($hash,"present",0,$hash->{PRESENT});
|
readingsSingleUpdate($client,"present",0,$client->{PRESENT});
|
||||||
$hash->{PRESENT} = 0;
|
$client->{PRESENT} = 0;
|
||||||
}
|
|
||||||
},$owx_devs);
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
$hash->{DEVS} = \@devnames;
|
||||||
|
Log3 ($hash->{NAME},5,"OWX_ASYNC_AfterSearch: DEVS = [".join(",",@devnames)."]") if ($owx_async_debug>2);
|
||||||
|
# }
|
||||||
}
|
}
|
||||||
|
|
||||||
########################################################################################
|
########################################################################################
|
||||||
@ -633,6 +573,7 @@ sub OWX_ASYNC_AutoCreate($$) {
|
|||||||
push(@owx_names,$exname);
|
push(@owx_names,$exname);
|
||||||
#-- replace the ROM ID by the proper value including CRC
|
#-- replace the ROM ID by the proper value including CRC
|
||||||
$main::defs{$fhem_dev}{ROM_ID}=$owx_dev;
|
$main::defs{$fhem_dev}{ROM_ID}=$owx_dev;
|
||||||
|
readingsSingleUpdate($main::defs{$fhem_dev},"present",1,!$main::defs{$fhem_dev}->{PRESENT});
|
||||||
$main::defs{$fhem_dev}{PRESENT}=1;
|
$main::defs{$fhem_dev}{PRESENT}=1;
|
||||||
$match = 1;
|
$match = 1;
|
||||||
last;
|
last;
|
||||||
@ -668,6 +609,7 @@ sub OWX_ASYNC_AutoCreate($$) {
|
|||||||
} else{
|
} else{
|
||||||
select(undef,undef,undef,0.1);
|
select(undef,undef,undef,0.1);
|
||||||
push(@owx_names,$acname);
|
push(@owx_names,$acname);
|
||||||
|
readingsSingleUpdate($main::defs{$acname},"present",1,!$main::defs{$acname}->{PRESENT});
|
||||||
$main::defs{$acname}{PRESENT}=1;
|
$main::defs{$acname}{PRESENT}=1;
|
||||||
#-- THIS IODev, default room (model is set in the device module)
|
#-- THIS IODev, default room (model is set in the device module)
|
||||||
CommandAttr (undef,"$acname IODev $hash->{NAME}");
|
CommandAttr (undef,"$acname IODev $hash->{NAME}");
|
||||||
@ -727,16 +669,28 @@ sub OWX_ASYNC_Get($@) {
|
|||||||
my $name = $hash->{NAME};
|
my $name = $hash->{NAME};
|
||||||
my $owx_dev = $hash->{ROM_ID};
|
my $owx_dev = $hash->{ROM_ID};
|
||||||
|
|
||||||
|
my ($task,$task_state);
|
||||||
|
|
||||||
if( $a[1] eq "alarms") {
|
if( $a[1] eq "alarms") {
|
||||||
my $res = OWX_ASYNC_DiscoverAlarms($hash);
|
eval {
|
||||||
#-- process result
|
$task = OWX_ASYNC_PT_Alarms($hash);
|
||||||
return $res
|
OWX_ASYNC_ScheduleMaster($hash,$task);
|
||||||
|
$task_state = OWX_ASYNC_RunToCompletion($hash,$task);
|
||||||
|
};
|
||||||
|
return $@ if $@;
|
||||||
|
return $task->PT_CAUSE() if ($task_state == PT_ERROR or $task_state == PT_CANCELED);
|
||||||
|
unless ( defined $hash->{ALARMDEVS} and @{$hash->{ALARMDEVS}}) {
|
||||||
|
return "OWX: No alarmed 1-Wire devices found on bus $name";
|
||||||
|
}
|
||||||
|
return "OWX: ".scalar(@{$hash->{ALARMDEVS}})." alarmed 1-Wire devices found on bus $name (".join(",",@{$hash->{ALARMDEVS}}).")";
|
||||||
} elsif( $a[1] eq "devices") {
|
} elsif( $a[1] eq "devices") {
|
||||||
my $res = OWX_ASYNC_Discover($hash);
|
eval {
|
||||||
#-- process result
|
$task = OWX_ASYNC_PT_Discover($hash);
|
||||||
return $res
|
OWX_ASYNC_ScheduleMaster($hash,$task);
|
||||||
|
$task_state = OWX_ASYNC_RunToCompletion($hash,$task);
|
||||||
|
};
|
||||||
|
return $@ if $@;
|
||||||
|
return ($task_state == PT_ERROR or $task_state == PT_CANCELED) ? $task->PT_CAUSE() : $task->PT_RETVAL();
|
||||||
} elsif( $a[1] eq "version") {
|
} elsif( $a[1] eq "version") {
|
||||||
return $owx_async_version;
|
return $owx_async_version;
|
||||||
|
|
||||||
@ -781,14 +735,22 @@ sub OWX_ASYNC_Init ($) {
|
|||||||
return "OWX_ASYNC_Init failed: $err";
|
return "OWX_ASYNC_Init failed: $err";
|
||||||
};
|
};
|
||||||
$hash->{ASYNC} = $ret;
|
$hash->{ASYNC} = $ret;
|
||||||
|
$hash->{ASYNC}->{debug} = $owx_async_debug;
|
||||||
$hash->{INTERFACE} = $owx->{interface};
|
$hash->{INTERFACE} = $owx->{interface};
|
||||||
} else {
|
} else {
|
||||||
return "OWX: Init called with undefined interface";
|
return "OWX: Init called with undefined interface";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$hash->{STATE} = "Active";
|
||||||
|
|
||||||
#-- Fourth step: discovering devices on the bus
|
#-- Fourth step: discovering devices on the bus
|
||||||
# in 10 seconds discover all devices on the 1-Wire bus
|
# in 10 seconds discover all devices on the 1-Wire bus
|
||||||
InternalTimer(gettimeofday()+10, "OWX_ASYNC_Discover", $hash,0);
|
my $pt_discover = OWX_ASYNC_PT_Discover($hash);
|
||||||
|
$pt_discover->{ExecuteTime} = gettimeofday()+10;
|
||||||
|
eval {
|
||||||
|
OWX_ASYNC_ScheduleMaster($hash,$pt_discover);
|
||||||
|
};
|
||||||
|
return GP_Catch($@) if $@;
|
||||||
|
|
||||||
#-- Default settings
|
#-- Default settings
|
||||||
$hash->{interval} = AttrVal($hash->{NAME},"interval",300); # kick every 5 minutes
|
$hash->{interval} = AttrVal($hash->{NAME},"interval",300); # kick every 5 minutes
|
||||||
@ -800,7 +762,6 @@ sub OWX_ASYNC_Init ($) {
|
|||||||
#readingsSingleUpdate($hash,"state","defined",1);
|
#readingsSingleUpdate($hash,"state","defined",1);
|
||||||
#-- Intiate first alarm detection and eventually conversion in a minute or so
|
#-- Intiate first alarm detection and eventually conversion in a minute or so
|
||||||
InternalTimer(gettimeofday() + $hash->{interval}, "OWX_ASYNC_Kick", $hash,0);
|
InternalTimer(gettimeofday() + $hash->{interval}, "OWX_ASYNC_Kick", $hash,0);
|
||||||
$hash->{STATE} = "Active";
|
|
||||||
GP_ForallClients($hash,\&OWX_ASYNC_InitClient,undef);
|
GP_ForallClients($hash,\&OWX_ASYNC_InitClient,undef);
|
||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
@ -833,28 +794,26 @@ sub OWX_ASYNC_Kick($) {
|
|||||||
#-- Call us in n seconds again.
|
#-- Call us in n seconds again.
|
||||||
InternalTimer(gettimeofday()+ $hash->{interval}, "OWX_ASYNC_Kick", $hash,0);
|
InternalTimer(gettimeofday()+ $hash->{interval}, "OWX_ASYNC_Kick", $hash,0);
|
||||||
|
|
||||||
|
unless ($hash->{".kickrunning"}) {
|
||||||
|
$hash->{".kickrunning"} = 1;
|
||||||
eval {
|
eval {
|
||||||
OWX_ASYNC_ScheduleMaster( $hash, PT_THREAD(\&OWX_ASYNC_PT_Kick), $hash );
|
OWX_ASYNC_ScheduleMaster( $hash, PT_THREAD(sub {
|
||||||
};
|
my ($thread) = @_;
|
||||||
Log3 $hash->{NAME},3,"OWX_ASYNC_Kick: ".GP_Catch($@) if $@;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub OWX_ASYNC_PT_Kick($) {
|
|
||||||
my ($thread,$hash) = @_;
|
|
||||||
|
|
||||||
PT_BEGIN($thread);
|
PT_BEGIN($thread);
|
||||||
#-- Only if we have the dokick attribute set to 1
|
#-- Only if we have the dokick attribute set to 1
|
||||||
if (main::AttrVal($hash->{NAME},"dokick",0)) {
|
if (main::AttrVal($hash->{NAME},"dokick",0)) {
|
||||||
Log3 $hash->{NAME},5,"OWX_ASYNC_PT_Kick: kicking DS14B20 temperature conversion";
|
Log3 $hash->{NAME},5,"OWX_ASYNC_PT_Kick: kicking DS14B20 temperature conversion";
|
||||||
#-- issue the skip ROM command \xCC followed by start conversion command \x44
|
#-- issue the skip ROM command \xCC followed by start conversion command \x44
|
||||||
unless (OWX_ASYNC_Execute($hash,$thread,1,undef,"\x44",0)) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($hash,1,undef,"\x44",0);
|
||||||
PT_EXIT("OWX_ASYNC: Failure in temperature conversion");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
|
delete $thread->{TimeoutTime};
|
||||||
|
if ($thread->{pt_execute}->PT_STATE() == PT_ERROR) {
|
||||||
|
Log3 ($hash->{NAME},4,"OWX_ASYNC_PT_Kick: Failure in temperature conversion: ".$thread->{pt_execute}->PT_CAUSE());
|
||||||
|
} else {
|
||||||
$thread->{ExecuteTime} = gettimeofday()+1;
|
$thread->{ExecuteTime} = gettimeofday()+1;
|
||||||
PT_YIELD_UNTIL(defined $thread->{ExecuteResponse} and (gettimeofday() >= $thread->{ExecuteTime}));
|
PT_YIELD_UNTIL(gettimeofday() >= $thread->{ExecuteTime});
|
||||||
|
delete $thread->{ExecuteTime};
|
||||||
GP_ForallClients($hash,sub {
|
GP_ForallClients($hash,sub {
|
||||||
my ($client) = @_;
|
my ($client) = @_;
|
||||||
if ($client->{TYPE} eq "OWTHERM" and AttrVal($client->{NAME},"tempConv","") eq "onkick" ) {
|
if ($client->{TYPE} eq "OWTHERM" and AttrVal($client->{NAME},"tempConv","") eq "onkick" ) {
|
||||||
@ -863,13 +822,30 @@ sub OWX_ASYNC_PT_Kick($) {
|
|||||||
}
|
}
|
||||||
},undef);
|
},undef);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#TODO OWX_ASYNC_Search allways returns 1 when busmaster is active
|
$thread->{pt_search} = OWX_ASYNC_PT_Search($hash);
|
||||||
if (OWX_ASYNC_Search($hash)) {
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
OWX_ASYNC_Alarms($hash);
|
PT_WAIT_THREAD($thread->{pt_search});
|
||||||
|
delete $thread->{Timeouttime};
|
||||||
|
if ($thread->{pt_search}->PT_STATE() == PT_ERROR) {
|
||||||
|
Log3 ($hash->{NAME},4,"OWX_ASYNC_PT_Kick: Failure in search: ".$thread->{pt_search}->PT_CAUSE());
|
||||||
|
} else {
|
||||||
|
$thread->{pt_alarms} = OWX_ASYNC_PT_Alarms($hash);
|
||||||
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
|
PT_WAIT_THREAD($thread->{pt_alarms});
|
||||||
|
delete $thread->{TimeoutTime};
|
||||||
|
if ($thread->{pt_alarms}->PT_STATE() == PT_ERROR) {
|
||||||
|
Log3 ($hash->{NAME},4,"OWX_ASYNC_PT_Kick: Failure in alarm-search: ".$thread->{pt_alarms}->PT_CAUSE());
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
delete $hash->{".kickrunning"};
|
||||||
PT_END;
|
PT_END;
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
Log3 ($hash->{NAME},4,"OWX_ASYNC_PT_Kick".GP_Catch($@)) if ($@);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
########################################################################################
|
########################################################################################
|
||||||
@ -950,17 +926,42 @@ sub OWX_ASYNC_Undef ($$) {
|
|||||||
#
|
#
|
||||||
########################################################################################
|
########################################################################################
|
||||||
|
|
||||||
sub OWX_ASYNC_Verify ($$) {
|
sub OWX_ASYNC_PT_Verify($) {
|
||||||
my ($hash,$dev) = @_;
|
my ($hash) = @_;
|
||||||
my $address = substr($dev,0,15);
|
|
||||||
if (OWX_ASYNC_Search($hash)) {
|
#-- get the interface
|
||||||
if (my $owx_devices = OWX_ASYNC_AwaitSearchResponse($hash)) {
|
my $async = $hash->{IODev}->{ASYNC};
|
||||||
if (grep {/$address/} @{$owx_devices}) {
|
my $romid = $hash->{ROM_ID};
|
||||||
return 1;
|
|
||||||
};
|
#-- Verify a devices is present on the 1-Wire bus
|
||||||
};
|
if (defined $async) {
|
||||||
|
return PT_THREAD(sub {
|
||||||
|
my ($thread) = @_;
|
||||||
|
PT_BEGIN($thread);
|
||||||
|
$thread->{pt_verify} = $async->get_pt_verify($romid);
|
||||||
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
|
PT_WAIT_THREAD($thread->{pt_verify});
|
||||||
|
delete $thread->{TimeoutTime};
|
||||||
|
die $thread->{pt_verify}->PT_CAUSE() if ($thread->{pt_verify}->PT_STATE() == PT_ERROR);
|
||||||
|
|
||||||
|
my $value = $thread->{pt_verify}->PT_RETVAL();
|
||||||
|
|
||||||
|
if( $value == 0 ){
|
||||||
|
readingsSingleUpdate($hash,"present",0,$hash->{PRESENT});
|
||||||
|
} else {
|
||||||
|
readingsSingleUpdate($hash,"present",1,!$hash->{PRESENT});
|
||||||
|
}
|
||||||
|
$hash->{PRESENT} = $value;
|
||||||
|
PT_END;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
my $owx_interface = $hash->{IODev}->{INTERFACE};
|
||||||
|
if( !defined($owx_interface) ) {
|
||||||
|
die "OWX: Verify called with undefined interface on bus $hash->{IODev}->{NAME}";
|
||||||
|
} else {
|
||||||
|
die "OWX: Verify called with unknown interface $owx_interface on bus $hash->{IODev}->{NAME}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
########################################################################################
|
########################################################################################
|
||||||
@ -983,209 +984,171 @@ sub OWX_ASYNC_Verify ($$) {
|
|||||||
#
|
#
|
||||||
########################################################################################
|
########################################################################################
|
||||||
|
|
||||||
sub OWX_ASYNC_Execute($$$$$$) {
|
sub OWX_ASYNC_PT_Execute($$$$$) {
|
||||||
my ( $hash, $context, $reset, $owx_dev, $data, $numread ) = @_;
|
my ( $hash, $reset, $owx_dev, $data, $numread ) = @_;
|
||||||
if (my $executor = $hash->{ASYNC}) {
|
if (my $executor = $hash->{ASYNC}) {
|
||||||
delete $context->{ExecuteResponse};
|
return $executor->get_pt_execute($reset,$owx_dev,$data,$numread);
|
||||||
my $now = gettimeofday();
|
|
||||||
#TODO implement propper timeout based on timeout-attribute
|
|
||||||
#my $timeoutms = AttrVal($hash->{NAME},"timeout",1000);
|
|
||||||
$context->{TimeoutTime} = $now+2;
|
|
||||||
Log3 ($hash->{NAME},5,sprintf("OWX_ASYNC_Execute: set TimeoutTime: %.6f, now: %.6f",$context->{TimeoutTime},$now)) if ($owx_async_debug);
|
|
||||||
return $executor->execute( $hash, $context, $reset, $owx_dev, $data, $numread );
|
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
die "OWX_ASYNC_PT_Execute: no async device assigned";
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
########################################################################################
|
|
||||||
#
|
|
||||||
# OWX_ASYNC_AfterExecute - is called when a query initiated by OWX_Execute successfully returns
|
|
||||||
#
|
|
||||||
# calls 'AfterExecuteFn' on the devices module (if such is defined)
|
|
||||||
# stores data read in $hash->{replies}{$owx_dev}{$context} after calling 'AfterExecuteFn'
|
|
||||||
#
|
|
||||||
# Attention: this function is not intendet to be called directly!
|
|
||||||
#
|
|
||||||
# Parameter hash = hash of bus master
|
|
||||||
# context = context parameter of call to OWX_Execute. Allows to correlate request and response
|
|
||||||
# success = indicates whether an error did occur
|
|
||||||
# reset = indicates whether a reset was carried out
|
|
||||||
# owx_dev = 1-wire device-address
|
|
||||||
# data = data written to the 1-wire device before read was executed
|
|
||||||
# numread = number of bytes requested from 1-wire device
|
|
||||||
# readdata = bytes read from 1-wire device
|
|
||||||
#
|
|
||||||
# Returns: nothing
|
|
||||||
#
|
|
||||||
########################################################################################
|
|
||||||
|
|
||||||
sub OWX_ASYNC_AfterExecute($$$$$$$$) {
|
|
||||||
my ( $master, $context, $success, $reset, $owx_dev, $writedata, $numread, $readdata ) = @_;
|
|
||||||
|
|
||||||
Log3 ($master->{NAME},5,"AfterExecute:".
|
|
||||||
" context: ".(defined $context ? $context : "undef").
|
|
||||||
", success: ".(defined $success ? $success : "undef").
|
|
||||||
", reset: ".(defined $reset ? $reset : "undef").
|
|
||||||
", owx_dev: ".(defined $owx_dev ? $owx_dev : "undef").
|
|
||||||
", writedata: ".(defined $writedata ? unpack ("H*",$writedata) : "undef").
|
|
||||||
", numread: ".(defined $numread ? $numread : "undef").
|
|
||||||
", readdata: ".(defined $readdata ? unpack ("H*",$readdata) : "undef"));
|
|
||||||
|
|
||||||
if ( defined $context and ref $context eq "ProtoThreads" ) {
|
|
||||||
$context->{ExecuteResponse} = {
|
|
||||||
success => $success,
|
|
||||||
'reset' => $reset,
|
|
||||||
writedata => $writedata,
|
|
||||||
readdata => $readdata,
|
|
||||||
numread => $numread,
|
|
||||||
};
|
|
||||||
delete $context->{TimeoutTime};
|
|
||||||
} else {
|
|
||||||
die "OWX_ASYNC_AfterExecute: $context is not a ProtoThread";
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
sub OWX_ASYNC_Schedule($$@) {
|
sub OWX_ASYNC_Schedule($$@) {
|
||||||
my ( $hash, $task, @args ) = @_;
|
my ( $hash, $task, @args ) = @_;
|
||||||
my $master = $hash->{IODev};
|
my $master = $hash->{IODev};
|
||||||
die "OWX_ASYNC_Schedule: Master not Active" unless $master->{STATE} eq "Active";
|
die "OWX_ASYNC_Schedule: Master not Active" unless $master->{STATE} eq "Active";
|
||||||
my $owx_dev = $hash->{ROM_ID};
|
my $name = $hash->{NAME};
|
||||||
$task->{ExecuteArgs} = \@args;
|
$task->{ExecuteArgs} = \@args;
|
||||||
my $now = gettimeofday();
|
$task->{ExecuteTime} = gettimeofday() unless (defined $task->{ExecuteTime});
|
||||||
$task->{ExecuteTime} = $now;
|
if (defined $master->{tasks}->{$name}) {
|
||||||
if (defined $master->{tasks}->{$owx_dev}) {
|
push @{$master->{tasks}->{$name}}, $task;
|
||||||
push @{$master->{tasks}->{$owx_dev}}, $task;
|
$hash->{NUMTASKS} = @{$master->{tasks}->{$name}};
|
||||||
} else {
|
} else {
|
||||||
$master->{tasks}->{$owx_dev} = [$task];
|
$master->{tasks}->{$name} = [$task];
|
||||||
|
$hash->{NUMTASKS} = 1;
|
||||||
}
|
}
|
||||||
main::InternalTimer($now, "OWX_ASYNC_RunTasks", $master,0);
|
#TODO make use of $master->{".nexttasktime"}
|
||||||
|
InternalTimer($task->{ExecuteTime}, "OWX_ASYNC_RunTasks", $master,0);
|
||||||
};
|
};
|
||||||
|
|
||||||
sub OWX_ASYNC_ScheduleMaster($$@) {
|
sub OWX_ASYNC_ScheduleMaster($$@) {
|
||||||
my ( $master, $task, @args ) = @_;
|
my ( $master, $task, @args ) = @_;
|
||||||
die "OWX_ASYNC_Schedule: Master not Active" unless $master->{STATE} eq "Active";
|
die "OWX_ASYNC_Schedule: Master not Active" unless $master->{STATE} eq "Active";
|
||||||
|
my $name = $master->{NAME};
|
||||||
$task->{ExecuteArgs} = \@args;
|
$task->{ExecuteArgs} = \@args;
|
||||||
my $now = gettimeofday();
|
$task->{ExecuteTime} = gettimeofday() unless (defined $task->{ExecuteTime});
|
||||||
$task->{ExecuteTime} = $now;
|
if (defined $master->{tasks}->{$name}) {
|
||||||
if (defined $master->{tasks}->{master}) {
|
push @{$master->{tasks}->{$name}}, $task;
|
||||||
push @{$master->{tasks}->{master}}, $task;
|
$master->{NUMTASKS} = @{$master->{tasks}->{$name}};
|
||||||
} else {
|
} else {
|
||||||
$master->{tasks}->{master} = [$task];
|
$master->{tasks}->{$name} = [$task];
|
||||||
|
$master->{NUMTASKS} = 1;
|
||||||
}
|
}
|
||||||
main::InternalTimer($now, "OWX_ASYNC_RunTasks", $master,0);
|
#TODO make use of $master->{".nexttasktime"}
|
||||||
|
InternalTimer($task->{ExecuteTime}, "OWX_ASYNC_RunTasks", $master,0);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
sub OWX_ASYNC_RunToCompletion($$) {
|
||||||
|
my ($master,$task) = @_;
|
||||||
|
my $task_state;
|
||||||
|
do {
|
||||||
|
OWX_ASYNC_Poll($master);
|
||||||
|
OWX_ASYNC_RunTasks($master);
|
||||||
|
$task_state = $task->PT_STATE();
|
||||||
|
} while ($task_state == PT_INITIAL or $task_state == PT_WAITING or $task_state == PT_YIELDED);
|
||||||
|
return $task_state;
|
||||||
|
}
|
||||||
|
|
||||||
sub OWX_ASYNC_RunTasks($) {
|
sub OWX_ASYNC_RunTasks($) {
|
||||||
my ( $master ) = @_;
|
my ( $master ) = @_;
|
||||||
if ($master->{STATE} eq "Active") {
|
if ($master->{STATE} eq "Active") {
|
||||||
Log3 ($master->{NAME},5,"OWX_ASYNC_RunTasks: ".((defined $master->{".currenttaskdevice"}) ? $master->{".currenttaskdevice"} : "-undefined-")." called") if ($owx_async_debug);
|
Log3 ($master->{NAME},5,"OWX_ASYNC_RunTasks: called") if ($owx_async_debug>2);
|
||||||
my $now = gettimeofday();
|
my $now = gettimeofday();
|
||||||
my $currentqueue;
|
while(1) {
|
||||||
my $currentdevice = $master->{".currenttaskdevice"};
|
my @queue_waiting = ();
|
||||||
$currentqueue = $master->{tasks}->{$currentdevice} if (defined $currentdevice);
|
my @queue_ready = ();
|
||||||
do {
|
my @queue_sleeping = ();
|
||||||
unless (defined $currentqueue and @$currentqueue) {
|
my @queue_initial = ();
|
||||||
foreach my $owx_dev (keys %{$master->{tasks}}) {
|
foreach my $name (keys %{$master->{tasks}}) {
|
||||||
my $queue = $master->{tasks}->{$owx_dev};
|
my $queue = $master->{tasks}->{$name};
|
||||||
if (@$queue) {
|
while (@$queue) {
|
||||||
# if task is eligible to run now:
|
my $state = $queue->[0]->PT_STATE();
|
||||||
if (defined ($queue->[0]->{ExecuteTime}) and ($now >= $queue->[0]->{ExecuteTime})) {
|
if ($state == PT_WAITING) {
|
||||||
$currentqueue = $queue;
|
push @queue_waiting,{ device => $name, queue => $queue};
|
||||||
$currentdevice = $owx_dev;
|
|
||||||
Log3 ($master->{NAME},5,"OWX_ASYNC_RunTasks: $owx_dev identified") if ($owx_async_debug);
|
|
||||||
last;
|
last;
|
||||||
}
|
} elsif ($state == PT_YIELDED) {
|
||||||
|
if ($now >= $queue->[0]->{ExecuteTime}) {
|
||||||
|
push @queue_ready, { device => $name, queue => $queue};
|
||||||
} else {
|
} else {
|
||||||
delete $master->{tasks}->{$owx_dev};
|
push @queue_sleeping, { device => $name, queue => $queue};
|
||||||
}
|
}
|
||||||
|
last;
|
||||||
|
} elsif ($state == PT_INITIAL) {
|
||||||
|
push @queue_initial, { device => $name, queue => $queue};
|
||||||
|
last;
|
||||||
|
} else {
|
||||||
|
shift @$queue;
|
||||||
|
$main::defs{$name}->{NUMTASKS} = @$queue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (defined $currentqueue and @$currentqueue) {
|
|
||||||
my $task = $currentqueue->[0];
|
|
||||||
my $timeout = $task->{TimeoutTime};
|
|
||||||
my $ret;
|
|
||||||
eval {
|
|
||||||
$ret = $task->PT_SCHEDULE(@{$task->{ExecuteArgs}});
|
|
||||||
};
|
};
|
||||||
# finished running or error:
|
delete $master->{tasks}->{$name} unless (@$queue);
|
||||||
if (!$ret or $@) {
|
|
||||||
shift @$currentqueue;
|
|
||||||
undef $currentqueue;
|
|
||||||
my $msg = ($@) ? GP_Catch($@) : $task->PT_RETVAL();
|
|
||||||
if (defined $msg) {
|
|
||||||
Log3 ($master->{NAME},3,"OWX_ASYNC_RunTasks: $currentdevice Error running task: $msg");
|
|
||||||
} else {
|
|
||||||
Log3 ($master->{NAME},5,"OWX_ASYNC_RunTasks: $currentdevice finished task");
|
|
||||||
}
|
}
|
||||||
|
if (defined (my $current = @queue_waiting ? shift @queue_waiting : @queue_ready ? shift @queue_ready : @queue_initial ? shift @queue_initial : undef)) {
|
||||||
|
my $task = $current->{queue}->[0];
|
||||||
|
my $timeout = $task->{TimeoutTime};
|
||||||
|
if ($task->PT_SCHEDULE(@{$task->{ExecuteArgs}})) {
|
||||||
|
my $state = $task->PT_STATE();
|
||||||
# waiting for ExecuteResponse:
|
# waiting for ExecuteResponse:
|
||||||
} elsif (defined $task->{TimeoutTime}) {
|
if ($state == PT_WAITING) {
|
||||||
|
die "$current->{device} unexpected thread state PT_WAITING without TimeoutTime" unless (defined $task->{TimeoutTime});
|
||||||
#task timed out:
|
#task timed out:
|
||||||
if ($now >= $task->{TimeoutTime}) {
|
if ($now >= $task->{TimeoutTime}) {
|
||||||
shift @$currentqueue;
|
Log3 ($master->{NAME},4,"OWX_ASYNC_RunTasks: $current->{device} task timed out");
|
||||||
undef $currentqueue;
|
Log3 ($master->{NAME},5,sprintf("OWX_ASYNC_RunTasks: $current->{device} TimeoutTime: %.6f, now: %.6f",$task->{TimeoutTime},$now)) if ($owx_async_debug>1);
|
||||||
Log3 ($master->{NAME},3,"OWX_ASYNC_RunTasks: $currentdevice task timed out");
|
$task->PT_CANCEL("Timeout");
|
||||||
Log3 ($master->{NAME},5,sprintf("OWX_ASYNC_RunTasks: $currentdevice TimeoutTime: %.6f, now: %.6f",$task->{TimeoutTime},$now));
|
shift @{$current->{queue}};
|
||||||
|
$main::defs{$current->{device}}->{NUMTASKS} = @{$current->{queue}};
|
||||||
|
next;
|
||||||
} else {
|
} else {
|
||||||
Log3 $master->{NAME},5,"OWX_ASYNC_RunTasks: $currentdevice waiting for data or timeout" if ($owx_async_debug);
|
Log3 $master->{NAME},5,"OWX_ASYNC_RunTasks: $current->{device} waiting for data or timeout" if ($owx_async_debug>2);
|
||||||
#new timeout or timeout did change:
|
#new timeout or timeout did change:
|
||||||
if (!defined $timeout or $timeout != $task->{TimeoutTime}) {
|
if (!defined $timeout or $timeout != $task->{TimeoutTime}) {
|
||||||
Log3 $master->{NAME},5,sprintf("OWX_ASYNC_RunTasks: $currentdevice schedule for timeout at %.6f",$task->{TimeoutTime});
|
Log3 $master->{NAME},5,sprintf("OWX_ASYNC_RunTasks: $current->{device} schedule for timeout at %.6f",$task->{TimeoutTime});
|
||||||
main::InternalTimer($task->{TimeoutTime}, "OWX_ASYNC_RunTasks", $master,0);
|
InternalTimer($task->{TimeoutTime}, "OWX_ASYNC_RunTasks", $master,0);
|
||||||
}
|
}
|
||||||
|
last;
|
||||||
}
|
}
|
||||||
# or not finished running, no error but scheduled for future:
|
# sleeping:
|
||||||
} elsif (defined $task->{ExecuteTime} and $now < $task->{ExecuteTime}) {
|
} elsif ($state == PT_YIELDED) {
|
||||||
undef $currentqueue;
|
next;
|
||||||
Log3 ($master->{NAME},5,"OWX_ASYNC_RunTasks: $currentdevice task not finished, next executetime: $task->{ExecuteTime}");
|
} else {
|
||||||
} elsif ($owx_async_debug) {
|
die "$current->{device} unexpected thread state while running: $state";
|
||||||
Log3 $master->{NAME},5,"OWX_ASYNC_RunTasks: $currentdevice no action";
|
|
||||||
}
|
}
|
||||||
if (defined $currentqueue and @$currentqueue) {
|
} else {
|
||||||
Log3 $master->{NAME},5,"OWX_ASYNC_RunTasks: $currentdevice exit loop" if ($owx_async_debug);
|
my $state = $task->PT_STATE();
|
||||||
$master->{".currenttaskdevice"} = $currentdevice;
|
if ($state == PT_ENDED) {
|
||||||
OWX_ASYNC_Poll($master);
|
Log3 ($master->{NAME},5,"OWX_ASYNC_RunTasks: $current->{device} finished task");
|
||||||
return;
|
} elsif ($state == PT_EXITED) {
|
||||||
} elsif ($owx_async_debug) {
|
Log3 ($master->{NAME},4,"OWX_ASYNC_RunTasks: $current->{device} exited task: ".(defined $task->PT_RETVAL() ? $task->PT_RETVAL : "- no retval -"));
|
||||||
Log3 $master->{NAME},5,sprintf("OWX_ASYNC_RunTasks: -undefined- continue loop");
|
} elsif ($state == PT_ERROR) {
|
||||||
|
Log3 ($master->{NAME},4,"OWX_ASYNC_RunTasks: $current->{device} Error task: ".$task->PT_CAUSE());
|
||||||
|
$main::defs{$current->{device}}->{PRESENT} = 0;
|
||||||
|
} else {
|
||||||
|
die "$current->{device} unexpected thread state after termination: $state";
|
||||||
|
}
|
||||||
|
shift @{$current->{queue}};
|
||||||
|
$main::defs{$current->{device}}->{NUMTASKS} = @{$current->{queue}};
|
||||||
|
next;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
my $nexttime;
|
my $nexttime;
|
||||||
foreach my $owx_dev (keys %{$master->{tasks}}) {
|
my $nextdevice;
|
||||||
my $queue = $master->{tasks}->{$owx_dev};
|
foreach my $current (@queue_sleeping) {
|
||||||
if (@$queue) {
|
|
||||||
my $nexttask = $queue->[0];
|
|
||||||
# if task is scheduled for future:
|
# if task is scheduled for future:
|
||||||
if (defined $nexttask->{ExecuteTime}) {
|
if (!defined $nexttime or ($nexttime > $current->{queue}->[0]->{ExecuteTime})) {
|
||||||
$nexttime = $nexttask->{ExecuteTime} if (!defined $nexttime or ($nexttime > $nexttask->{ExecuteTime}));
|
$nexttime = $current->{queue}->[0]->{ExecuteTime};
|
||||||
$currentdevice = $owx_dev;
|
$nextdevice = $current->{device};
|
||||||
}
|
|
||||||
} else {
|
|
||||||
delete $master->{tasks}->{$owx_dev};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (defined $nexttime) {
|
if (defined $nexttime) {
|
||||||
if ($nexttime > $now) {
|
if ($nexttime > $now) {
|
||||||
if (!defined $master->{".nexttasktime"} or $nexttime < $master->{".nexttasktime"} or $now >= $master->{".nexttasktime"}) {
|
if (!defined $master->{".nexttasktime"} or $nexttime < $master->{".nexttasktime"} or $now >= $master->{".nexttasktime"}) {
|
||||||
Log3 $master->{NAME},5,sprintf("OWX_ASYNC_RunTasks: $currentdevice schedule next at %.6f",$nexttime);
|
Log3 $master->{NAME},5,sprintf("OWX_ASYNC_RunTasks: $nextdevice schedule next at %.6f",$nexttime) if ($owx_async_debug);
|
||||||
main::InternalTimer($nexttime, "OWX_ASYNC_RunTasks", $master,0);
|
main::InternalTimer($nexttime, "OWX_ASYNC_RunTasks", $master,0);
|
||||||
$master->{".nexttasktime"} = $nexttime;
|
$master->{".nexttasktime"} = $nexttime;
|
||||||
} else {
|
} else {
|
||||||
Log3 $master->{NAME},5,sprintf("OWX_ASYNC_RunTasks: $currentdevice skip %.6f, allready scheduled at %.6f",$nexttime,$master->{".nexttasktime"}) if ($owx_async_debug);
|
Log3 $master->{NAME},5,sprintf("OWX_ASYNC_RunTasks: $nextdevice skip %.6f, allready scheduled at %.6f",$nexttime,$master->{".nexttasktime"}) if ($owx_async_debug>2);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
delete $master->{".nexttasktime"};
|
Log3 $master->{NAME},5,sprintf("OWX_ASYNC_RunTasks: $nextdevice nexttime at %.6f allready passed",$nexttime) if ($owx_async_debug>2);
|
||||||
Log3 $master->{NAME},5,sprintf("OWX_ASYNC_RunTasks: $currentdevice nexttime at %.6f allready passed",$nexttime) if ($owx_async_debug);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log3 $master->{NAME},5,sprintf("OWX_ASYNC_RunTasks: -undefined- no nexttime") if ($owx_async_debug);
|
Log3 $master->{NAME},5,sprintf("OWX_ASYNC_RunTasks: -undefined- no nexttime") if ($owx_async_debug>2);
|
||||||
}
|
}
|
||||||
delete $master->{".currenttaskdevice"};
|
Log3 $master->{NAME},5,sprintf("OWX_ASYNC_RunTasks: -undefined- exit loop") if ($owx_async_debug>2);
|
||||||
Log3 $master->{NAME},5,sprintf("OWX_ASYNC_RunTasks: -undefined- exit loop") if ($owx_async_debug);
|
last;
|
||||||
OWX_ASYNC_Poll($master);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
} while (1);
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ use vars qw{%attr %defs %modules $readingFnAttributes $init_done};
|
|||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
use GPUtils qw(:all);
|
use GPUtils qw(:all);
|
||||||
use Time::HiRes qw( gettimeofday tv_interval usleep );
|
use Time::HiRes qw( gettimeofday );
|
||||||
|
|
||||||
#add FHEM/lib to @INC if it's not allready included. Should rather be in fhem.pl than here though...
|
#add FHEM/lib to @INC if it's not allready included. Should rather be in fhem.pl than here though...
|
||||||
BEGIN {
|
BEGIN {
|
||||||
@ -90,7 +90,7 @@ use ProtoThreads;
|
|||||||
no warnings 'deprecated';
|
no warnings 'deprecated';
|
||||||
sub Log($$);
|
sub Log($$);
|
||||||
|
|
||||||
my $owx_version="5.15";
|
my $owx_version="5.16";
|
||||||
#-- fixed raw channel name, flexible channel name
|
#-- fixed raw channel name, flexible channel name
|
||||||
my @owg_fixed = ("A","B","C","D");
|
my @owg_fixed = ("A","B","C","D");
|
||||||
my @owg_channel = ("A","B","C","D");
|
my @owg_channel = ("A","B","C","D");
|
||||||
@ -157,6 +157,8 @@ sub OWAD_Initialize ($) {
|
|||||||
$hash->{UndefFn} = "OWAD_Undef";
|
$hash->{UndefFn} = "OWAD_Undef";
|
||||||
$hash->{GetFn} = "OWAD_Get";
|
$hash->{GetFn} = "OWAD_Get";
|
||||||
$hash->{SetFn} = "OWAD_Set";
|
$hash->{SetFn} = "OWAD_Set";
|
||||||
|
$hash->{NotifyFn}= "OWAD_Notify";
|
||||||
|
$hash->{InitFn} = "OWAD_Init";
|
||||||
$hash->{AttrFn} = "OWAD_Attr";
|
$hash->{AttrFn} = "OWAD_Attr";
|
||||||
|
|
||||||
my $attlist = "IODev do_not_notify:0,1 showtime:0,1 model:DS2450 loglevel:0,1,2,3,4,5 ".
|
my $attlist = "IODev do_not_notify:0,1 showtime:0,1 model:DS2450 loglevel:0,1,2,3,4,5 ".
|
||||||
@ -276,12 +278,27 @@ sub OWAD_Define ($$) {
|
|||||||
readingsSingleUpdate($hash,"state","defined",1);
|
readingsSingleUpdate($hash,"state","defined",1);
|
||||||
Log 3, "OWAD: Device $name defined.";
|
Log 3, "OWAD: Device $name defined.";
|
||||||
|
|
||||||
#-- Initialization reading according to interface type
|
$hash->{NOTIFYDEV} = "global";
|
||||||
my $interface= $hash->{IODev}->{TYPE};
|
|
||||||
|
|
||||||
|
if ($init_done) {
|
||||||
|
OWAD_Init($hash);
|
||||||
|
}
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub OWAD_Notify ($$) {
|
||||||
|
my ($hash,$dev) = @_;
|
||||||
|
if( grep(m/^(INITIALIZED|REREADCFG)$/, @{$dev->{CHANGED}}) ) {
|
||||||
|
OWAD_Init($hash);
|
||||||
|
} elsif( grep(m/^SAVE$/, @{$dev->{CHANGED}}) ) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub OWAD_Init ($) {
|
||||||
|
my ($hash)=@_;
|
||||||
#-- Start timer for updates
|
#-- Start timer for updates
|
||||||
InternalTimer(time()+60, "OWAD_GetValues", $hash, 0);
|
RemoveInternalTimer($hash);
|
||||||
|
InternalTimer(gettimeofday()+10, "OWAD_InitializeDevice", $hash, 0);
|
||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -326,6 +343,9 @@ sub OWAD_Attr(@) {
|
|||||||
AssignIoPort($hash,$value);
|
AssignIoPort($hash,$value);
|
||||||
if( defined($hash->{IODev}) ) {
|
if( defined($hash->{IODev}) ) {
|
||||||
$hash->{ASYNC} = $hash->{IODev}->{TYPE} eq "OWX_ASYNC" ? 1 : 0;
|
$hash->{ASYNC} = $hash->{IODev}->{TYPE} eq "OWX_ASYNC" ? 1 : 0;
|
||||||
|
if ($init_done) {
|
||||||
|
OWAD_Init($hash);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
last;
|
last;
|
||||||
};
|
};
|
||||||
@ -565,11 +585,17 @@ sub OWAD_Get($@) {
|
|||||||
|
|
||||||
#-- get present
|
#-- get present
|
||||||
if($a[1] eq "present") {
|
if($a[1] eq "present") {
|
||||||
#-- hash of the busmaster
|
|
||||||
my $master = $hash->{IODev};
|
|
||||||
#-- asynchronous mode
|
#-- asynchronous mode
|
||||||
if( $hash->{ASYNC} ){
|
if( $hash->{ASYNC} ){
|
||||||
$value = OWX_ASYNC_Verify($master,$hash->{ROM_ID});
|
my ($task,$task_state);
|
||||||
|
eval {
|
||||||
|
$task = OWX_ASYNC_PT_Verify($hash);
|
||||||
|
OWX_ASYNC_Schedule($hash,$task);
|
||||||
|
$task_state = OWX_ASYNC_RunToCompletion($master,$task);
|
||||||
|
};
|
||||||
|
return GP_Catch($@) if $@;
|
||||||
|
return $task->PT_CAUSE() if ($task_state == PT_ERROR or $task_state == PT_CANCELED);
|
||||||
|
return "$name.present => ".ReadingsVal($name,"present","unknown");
|
||||||
} else {
|
} else {
|
||||||
$value = OWX_Verify($master,$hash->{ROM_ID});
|
$value = OWX_Verify($master,$hash->{ROM_ID});
|
||||||
}
|
}
|
||||||
@ -595,12 +621,13 @@ sub OWAD_Get($@) {
|
|||||||
if( $interface eq "OWX" ){
|
if( $interface eq "OWX" ){
|
||||||
$ret = OWXAD_GetPage($hash,"reading",1);
|
$ret = OWXAD_GetPage($hash,"reading",1);
|
||||||
}elsif( $interface eq "OWX_ASYNC" ){
|
}elsif( $interface eq "OWX_ASYNC" ){
|
||||||
#TODO use OWX_ASYNC_Schedule instead
|
my ($task,$task_state);
|
||||||
my $task = PT_THREAD(\&OWXAD_PT_GetPage);
|
|
||||||
eval {
|
eval {
|
||||||
while ($task->PT_SCHEDULE($hash,"reading",1)) { OWX_ASYNC_Poll($hash->{IODev}); };
|
$task = OWXAD_PT_GetPage($hash,"reading",1);
|
||||||
|
OWX_ASYNC_Schedule($hash,$task);
|
||||||
|
$task_state = OWX_ASYNC_RunToCompletion($master,$task);
|
||||||
};
|
};
|
||||||
$ret = ($@) ? GP_Catch($@) : $task->PT_RETVAL();
|
$ret = ($@) ? GP_Catch($@) : ($task_state == PT_ERROR or $task_state == PT_CANCELED) ? $task->PT_CAUSE() : $task->PT_RETVAL();
|
||||||
#-- OWFS interface
|
#-- OWFS interface
|
||||||
}elsif( $interface eq "OWServer" ){
|
}elsif( $interface eq "OWServer" ){
|
||||||
$ret = OWFSAD_GetPage($hash,"reading",1);
|
$ret = OWFSAD_GetPage($hash,"reading",1);
|
||||||
@ -626,12 +653,13 @@ sub OWAD_Get($@) {
|
|||||||
if( $interface eq "OWX" ){
|
if( $interface eq "OWX" ){
|
||||||
$ret = OWXAD_GetPage($hash,"alarm",1);
|
$ret = OWXAD_GetPage($hash,"alarm",1);
|
||||||
}elsif( $interface eq "OWX_ASYNC" ){
|
}elsif( $interface eq "OWX_ASYNC" ){
|
||||||
#TODO use OWX_ASYNC_Schedule instead
|
my ($task,$task_state);
|
||||||
my $task = PT_THREAD(\&OWXAD_PT_GetPage);
|
|
||||||
eval {
|
eval {
|
||||||
while ($task->PT_SCHEDULE($hash,"alarm",1)) { OWX_ASYNC_Poll($hash->{IODev}); };
|
$task = OWXAD_PT_GetPage($hash,"alarm",1);
|
||||||
|
OWX_ASYNC_Schedule($hash,$task);
|
||||||
|
$task_state = OWX_ASYNC_RunToCompletion($master,$task);
|
||||||
};
|
};
|
||||||
$ret = ($@) ? GP_Catch($@) : $task->PT_RETVAL();
|
$ret = ($@) ? GP_Catch($@) : ($task_state == PT_ERROR or $task_state == PT_CANCELED) ? $task->PT_CAUSE() : $task->PT_RETVAL();
|
||||||
#-- OWFS interface
|
#-- OWFS interface
|
||||||
}elsif( $interface eq "OWServer" ){
|
}elsif( $interface eq "OWServer" ){
|
||||||
$ret = OWFSAD_GetPage($hash,"alarm",1);
|
$ret = OWFSAD_GetPage($hash,"alarm",1);
|
||||||
@ -665,12 +693,13 @@ sub OWAD_Get($@) {
|
|||||||
if( $interface eq "OWX" ){
|
if( $interface eq "OWX" ){
|
||||||
$ret = OWXAD_GetPage($hash,"status",1);
|
$ret = OWXAD_GetPage($hash,"status",1);
|
||||||
}elsif( $interface eq "OWX_ASYNC" ){
|
}elsif( $interface eq "OWX_ASYNC" ){
|
||||||
#TODO use OWX_ASYNC_Schedule instead
|
my ($task,$task_state);
|
||||||
my $task = PT_THREAD(\&OWXAD_PT_GetPage);
|
|
||||||
eval {
|
eval {
|
||||||
while ($task->PT_SCHEDULE($hash,"status",1)) { OWX_ASYNC_Poll($hash->{IODev}); };
|
$task = OWXAD_PT_GetPage($hash,"status",1);
|
||||||
|
OWX_ASYNC_Schedule($hash,$task);
|
||||||
|
$task_state = OWX_ASYNC_RunToCompletion($master,$task);
|
||||||
};
|
};
|
||||||
$ret = ($@) ? GP_Catch($@) : $task->PT_RETVAL();
|
$ret = ($@) ? GP_Catch($@) : ($task_state == PT_ERROR or $task_state == PT_CANCELED) ? $task->PT_CAUSE() : $task->PT_RETVAL();
|
||||||
#-- OWFS interface
|
#-- OWFS interface
|
||||||
}elsif( $interface eq "OWServer" ){
|
}elsif( $interface eq "OWServer" ){
|
||||||
$ret = OWFSAD_GetPage($hash,"status",1);
|
$ret = OWFSAD_GetPage($hash,"status",1);
|
||||||
@ -741,10 +770,6 @@ sub OWAD_GetValues($) {
|
|||||||
my $ret = "";
|
my $ret = "";
|
||||||
my ($ret1,$ret2,$ret3);
|
my ($ret1,$ret2,$ret3);
|
||||||
|
|
||||||
#-- check if device needs to be initialized
|
|
||||||
OWAD_InitializeDevice($hash)
|
|
||||||
if( $hash->{READINGS}{"state"}{VAL} eq "defined");
|
|
||||||
|
|
||||||
#-- define warnings
|
#-- define warnings
|
||||||
my $warn = "none";
|
my $warn = "none";
|
||||||
$hash->{ALARM} = "0";
|
$hash->{ALARM} = "0";
|
||||||
@ -763,9 +788,9 @@ sub OWAD_GetValues($) {
|
|||||||
#}
|
#}
|
||||||
}elsif( $interface eq "OWX_ASYNC" ){
|
}elsif( $interface eq "OWX_ASYNC" ){
|
||||||
eval {
|
eval {
|
||||||
OWX_ASYNC_Schedule( $hash, PT_THREAD(\&OWXAD_PT_GetPage),$hash,"reading",0 );
|
OWX_ASYNC_Schedule( $hash, OWXAD_PT_GetPage($hash,"reading",0));
|
||||||
OWX_ASYNC_Schedule( $hash, PT_THREAD(\&OWXAD_PT_GetPage),$hash,"alarm",0 );
|
OWX_ASYNC_Schedule( $hash, OWXAD_PT_GetPage($hash,"alarm",0));
|
||||||
OWX_ASYNC_Schedule( $hash, PT_THREAD(\&OWXAD_PT_GetPage),$hash,"status",1 );
|
OWX_ASYNC_Schedule( $hash, OWXAD_PT_GetPage($hash,"status",1));
|
||||||
};
|
};
|
||||||
$ret .= GP_Catch($@) if $@;
|
$ret .= GP_Catch($@) if $@;
|
||||||
}elsif( $interface eq "OWServer" ){
|
}elsif( $interface eq "OWServer" ){
|
||||||
@ -859,8 +884,8 @@ sub OWAD_InitializeDevice($) {
|
|||||||
$ret2 = OWXAD_SetPage($hash,"alarm");
|
$ret2 = OWXAD_SetPage($hash,"alarm");
|
||||||
}elsif( $interface eq "OWX_ASYNC" ){
|
}elsif( $interface eq "OWX_ASYNC" ){
|
||||||
eval {
|
eval {
|
||||||
OWX_ASYNC_Schedule( $hash, PT_THREAD(\&OWXAD_PT_SetPage),$hash,"status" );
|
OWX_ASYNC_Schedule( $hash, OWXAD_PT_SetPage($hash,"status"));
|
||||||
OWX_ASYNC_Schedule( $hash, PT_THREAD(\&OWXAD_PT_SetPage),$hash,"alarm" );
|
OWX_ASYNC_Schedule( $hash, OWXAD_PT_SetPage($hash,"alarm"));
|
||||||
};
|
};
|
||||||
$ret .= GP_Catch($@) if $@;
|
$ret .= GP_Catch($@) if $@;
|
||||||
#-- OWFS interface
|
#-- OWFS interface
|
||||||
@ -880,7 +905,7 @@ sub OWAD_InitializeDevice($) {
|
|||||||
#-- Set state to initialized
|
#-- Set state to initialized
|
||||||
readingsSingleUpdate($hash,"state","initialized",1);
|
readingsSingleUpdate($hash,"state","initialized",1);
|
||||||
|
|
||||||
return undef;
|
return OWAD_GetValues($hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
#######################################################################################
|
#######################################################################################
|
||||||
@ -982,7 +1007,7 @@ sub OWAD_Set($@) {
|
|||||||
$ret = OWXAD_SetPage($hash,"status");
|
$ret = OWXAD_SetPage($hash,"status");
|
||||||
}elsif( $interface eq "OWX_ASYNC" ){
|
}elsif( $interface eq "OWX_ASYNC" ){
|
||||||
eval {
|
eval {
|
||||||
OWX_ASYNC_Schedule( $hash, PT_THREAD(\&OWXAD_PT_SetPage),$hash,"status" );
|
OWX_ASYNC_Schedule( $hash, OWXAD_PT_SetPage($hash,"status"));
|
||||||
};
|
};
|
||||||
$ret = GP_Catch($@) if $@;
|
$ret = GP_Catch($@) if $@;
|
||||||
#-- OWFS interface
|
#-- OWFS interface
|
||||||
@ -1033,7 +1058,7 @@ sub OWAD_Set($@) {
|
|||||||
$ret = OWXAD_SetPage($hash,"alarm");
|
$ret = OWXAD_SetPage($hash,"alarm");
|
||||||
}elsif( $interface eq "OWX_ASYNC" ){
|
}elsif( $interface eq "OWX_ASYNC" ){
|
||||||
eval {
|
eval {
|
||||||
OWX_ASYNC_Schedule( $hash, PT_THREAD(\&OWXAD_PT_SetPage),$hash,"status" );
|
OWX_ASYNC_Schedule( $hash, OWXAD_PT_SetPage($hash,"status"));
|
||||||
};
|
};
|
||||||
$ret = GP_Catch($@) if $@;
|
$ret = GP_Catch($@) if $@;
|
||||||
#-- OWFS interface
|
#-- OWFS interface
|
||||||
@ -1537,9 +1562,13 @@ sub OWXAD_SetPage($$) {
|
|||||||
|
|
||||||
sub OWXAD_PT_GetPage($$$) {
|
sub OWXAD_PT_GetPage($$$) {
|
||||||
|
|
||||||
my ($thread,$hash,$page,$final) = @_;
|
my ($hash,$page,$final) = @_;
|
||||||
|
|
||||||
my ($select, $res, $res2, $res3, @data, $an, $vn);
|
return PT_THREAD(sub {
|
||||||
|
|
||||||
|
my ($thread) = @_;
|
||||||
|
|
||||||
|
my ($res, $res2, $res3, @data, $an, $vn);
|
||||||
|
|
||||||
#-- ID of the device, hash of the busmaster
|
#-- ID of the device, hash of the busmaster
|
||||||
my $owx_dev = $hash->{ROM_ID};
|
my $owx_dev = $hash->{ROM_ID};
|
||||||
@ -1549,50 +1578,51 @@ sub OWXAD_PT_GetPage($$$) {
|
|||||||
|
|
||||||
PT_BEGIN($thread);
|
PT_BEGIN($thread);
|
||||||
|
|
||||||
#-- reset presence
|
|
||||||
$hash->{PRESENT} = 0;
|
|
||||||
|
|
||||||
#=============== get the voltage reading ===============================
|
#=============== get the voltage reading ===============================
|
||||||
if( $page eq "reading") {
|
if( $page eq "reading") {
|
||||||
#-- issue the match ROM command \x55 and the start conversion command
|
#-- issue the match ROM command \x55 and the start conversion command
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, "\x3C\x0F\x00\xFF\xFF", 0 )) {
|
|
||||||
PT_EXIT("$owx_dev not accessible for conversion");
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev, "\x3C\x0F\x00\xFF\xFF", 0 );
|
||||||
}
|
$thread->{ExecuteTime} = gettimeofday() + 0.05; # was 0.02
|
||||||
PT_WAIT_UNTIL(defined $thread->{ExecuteResponse});
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
#TODO async 20ms delay
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
select(undef,undef,undef,0.02);
|
delete $thread->{TimeoutTime};
|
||||||
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
|
|
||||||
|
PT_YIELD_UNTIL(gettimeofday() >= $thread->{ExecuteTime});
|
||||||
|
delete $thread->{ExecuteTime};
|
||||||
|
|
||||||
#-- issue the match ROM command \x55 and the read conversion page command
|
#-- issue the match ROM command \x55 and the read conversion page command
|
||||||
# \xAA\x00\x00
|
# \xAA\x00\x00
|
||||||
$select="\xAA\x00\x00";
|
$thread->{'select'}="\xAA\x00\x00";
|
||||||
#=============== get the alarm reading ===============================
|
#=============== get the alarm reading ===============================
|
||||||
} elsif ( $page eq "alarm" ) {
|
} elsif ( $page eq "alarm" ) {
|
||||||
#-- issue the match ROM command \x55 and the read alarm page command
|
#-- issue the match ROM command \x55 and the read alarm page command
|
||||||
# \xAA\x10\x00
|
# \xAA\x10\x00
|
||||||
$select="\xAA\x10\x00";
|
$thread->{'select'}="\xAA\x10\x00";
|
||||||
#=============== get the status reading ===============================
|
#=============== get the status reading ===============================
|
||||||
} elsif ( $page eq "status" ) {
|
} elsif ( $page eq "status" ) {
|
||||||
#-- issue the match ROM command \x55 and the read status memory page command
|
#-- issue the match ROM command \x55 and the read status memory page command
|
||||||
# \xAA\x08\x00 r
|
# \xAA\x08\x00 r
|
||||||
$select="\xAA\x08\x00";
|
$thread->{'select'}="\xAA\x08\x00";
|
||||||
#=============== wrong value requested ===============================
|
#=============== wrong value requested ===============================
|
||||||
} else {
|
} else {
|
||||||
return "wrong memory page requested from $owx_dev";
|
die "wrong memory page requested from $owx_dev";
|
||||||
}
|
}
|
||||||
#-- reading 9 + 3 + 8 data bytes and 2 CRC bytes = 22 bytes
|
#-- reading 9 + 3 + 8 data bytes and 2 CRC bytes = 22 bytes
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, $select, 10 )) {
|
|
||||||
PT_EXIT("$owx_dev not accessible in reading $page page");
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev, $thread->{'select'}, 10 );
|
||||||
}
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
PT_WAIT_UNTIL(defined $thread->{ExecuteResponse});
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
my $response = $thread->{ExecuteResponse};
|
delete $thread->{TimeoutTime};
|
||||||
unless ($response->{success}) {
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
PT_EXIT("$owx_dev read not successful");
|
my $response = $thread->{pt_execute}->PT_RETVAL();
|
||||||
}
|
my $res = OWXAD_BinValues($hash,"ds2450.get".$page.($final ? ".final" : ""),1,1,$owx_dev,$thread->{'select'},10,$response);
|
||||||
my $res = OWXAD_BinValues($hash,"ds2450.get".$page.($final ? ".final" : ""),1,1,$owx_dev,$response->{writedata},$response->{numread},$response->{readdata});
|
|
||||||
if ($res) {
|
if ($res) {
|
||||||
PT_EXIT($res);
|
die $res;
|
||||||
}
|
}
|
||||||
PT_END;
|
PT_END;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
########################################################################################
|
########################################################################################
|
||||||
@ -1606,8 +1636,11 @@ sub OWXAD_PT_GetPage($$$) {
|
|||||||
|
|
||||||
sub OWXAD_PT_SetPage($$) {
|
sub OWXAD_PT_SetPage($$) {
|
||||||
|
|
||||||
my ($thread,$hash,$page) = @_;
|
my ($hash,$page) = @_;
|
||||||
|
|
||||||
|
return PT_THREAD(sub {
|
||||||
|
|
||||||
|
my ($thread) = @_;
|
||||||
my ($select, $res, $res2, $res3, @data);
|
my ($select, $res, $res2, $res3, @data);
|
||||||
|
|
||||||
#-- ID of the device, hash of the busmaster
|
#-- ID of the device, hash of the busmaster
|
||||||
@ -1663,15 +1696,13 @@ sub OWXAD_PT_SetPage($$) {
|
|||||||
PT_EXIT("wrong memory page write attempt");
|
PT_EXIT("wrong memory page write attempt");
|
||||||
}
|
}
|
||||||
#"setpage"
|
#"setpage"
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, $select, 0 )) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev, $select, 0 );
|
||||||
PT_EXIT("device $owx_dev not accessible for writing");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL(defined $thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
my $response = $thread->{ExecuteResponse};
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
unless ($response->{success}) {
|
|
||||||
PT_EXIT("$owx_dev write not successful");
|
|
||||||
}
|
|
||||||
PT_END;
|
PT_END;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
@ -99,7 +99,7 @@ no warnings 'deprecated';
|
|||||||
|
|
||||||
sub Log3($$$);
|
sub Log3($$$);
|
||||||
|
|
||||||
my $owx_version="5.22";
|
my $owx_version="5.23";
|
||||||
#-- fixed raw channel name, flexible channel name
|
#-- fixed raw channel name, flexible channel name
|
||||||
my @owg_fixed = ("A","B");
|
my @owg_fixed = ("A","B");
|
||||||
my @owg_channel = ("A","B");
|
my @owg_channel = ("A","B");
|
||||||
@ -151,6 +151,8 @@ sub OWCOUNT_Initialize ($) {
|
|||||||
$hash->{UndefFn} = "OWCOUNT_Undef";
|
$hash->{UndefFn} = "OWCOUNT_Undef";
|
||||||
$hash->{GetFn} = "OWCOUNT_Get";
|
$hash->{GetFn} = "OWCOUNT_Get";
|
||||||
$hash->{SetFn} = "OWCOUNT_Set";
|
$hash->{SetFn} = "OWCOUNT_Set";
|
||||||
|
$hash->{NotifyFn}= "OWCOUNT_Notify";
|
||||||
|
$hash->{InitFn} = "OWCOUNT_Init";
|
||||||
$hash->{AttrFn} = "OWCOUNT_Attr";
|
$hash->{AttrFn} = "OWCOUNT_Attr";
|
||||||
#-- see header for attributes
|
#-- see header for attributes
|
||||||
my $attlist = "IODev do_not_notify:0,1 showtime:0,1 model:DS2423,DS2423enew,DS2423eold LogM LogY ".
|
my $attlist = "IODev do_not_notify:0,1 showtime:0,1 model:DS2423,DS2423enew,DS2423eold LogM LogY ".
|
||||||
@ -264,9 +266,29 @@ sub OWCOUNT_Define ($$) {
|
|||||||
readingsSingleUpdate($hash,"state","defined",1);
|
readingsSingleUpdate($hash,"state","defined",1);
|
||||||
Log3 $name, 3, "OWCOUNT: Device $name defined.";
|
Log3 $name, 3, "OWCOUNT: Device $name defined.";
|
||||||
|
|
||||||
#-- Start timer for updates
|
$hash->{NOTIFYDEV} = "global";
|
||||||
InternalTimer(time()+10, "OWCOUNT_GetValues", $hash, 0);
|
|
||||||
|
|
||||||
|
if ($init_done) {
|
||||||
|
OWCOUNT_Init($hash);
|
||||||
|
}
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub OWCOUNT_Notify ($$) {
|
||||||
|
my ($hash,$dev) = @_;
|
||||||
|
if( grep(m/^(INITIALIZED|REREADCFG)$/, @{$dev->{CHANGED}}) ) {
|
||||||
|
OWCOUNT_Init($hash);
|
||||||
|
} elsif( grep(m/^SAVE$/, @{$dev->{CHANGED}}) ) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub OWCOUNT_Init ($) {
|
||||||
|
my ($hash)=@_;
|
||||||
|
#-- Start timer for updates
|
||||||
|
RemoveInternalTimer($hash);
|
||||||
|
InternalTimer(gettimeofday()+10, "OWCOUNT_GetValues", $hash, 0);
|
||||||
|
#--
|
||||||
|
readingsSingleUpdate($hash,"state","Initialized",1);
|
||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,6 +325,9 @@ sub OWCOUNT_Attr(@) {
|
|||||||
AssignIoPort($hash,$value);
|
AssignIoPort($hash,$value);
|
||||||
if( defined($hash->{IODev}) ) {
|
if( defined($hash->{IODev}) ) {
|
||||||
$hash->{ASYNC} = $hash->{IODev}->{TYPE} eq "OWX_ASYNC" ? 1 : 0;
|
$hash->{ASYNC} = $hash->{IODev}->{TYPE} eq "OWX_ASYNC" ? 1 : 0;
|
||||||
|
if ($init_done) {
|
||||||
|
OWCOUNT_Init($hash);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
last;
|
last;
|
||||||
};
|
};
|
||||||
@ -626,7 +651,15 @@ sub OWCOUNT_Get($@) {
|
|||||||
my $master = $hash->{IODev};
|
my $master = $hash->{IODev};
|
||||||
#-- asynchronous mode
|
#-- asynchronous mode
|
||||||
if( $hash->{ASYNC} ){
|
if( $hash->{ASYNC} ){
|
||||||
$value = OWX_ASYNC_Verify($master,$hash->{ROM_ID});
|
my ($task,$task_state);
|
||||||
|
eval {
|
||||||
|
$task = OWX_ASYNC_PT_Verify($hash);
|
||||||
|
OWX_ASYNC_Schedule($hash,$task);
|
||||||
|
$task_state = OWX_ASYNC_RunToCompletion($master,$task);
|
||||||
|
};
|
||||||
|
return GP_Catch($@) if $@;
|
||||||
|
return $task->PT_CAUSE() if ($task_state == PT_ERROR or $task_state == PT_CANCELED);
|
||||||
|
return "$name.present => ".ReadingsVal($name,"present","unknown");
|
||||||
} else {
|
} else {
|
||||||
$value = OWX_Verify($master,$hash->{ROM_ID});
|
$value = OWX_Verify($master,$hash->{ROM_ID});
|
||||||
}
|
}
|
||||||
@ -800,6 +833,7 @@ sub OWCOUNT_GetPage ($$$@) {
|
|||||||
my ($hash, $page,$final,$sync) = @_;
|
my ($hash, $page,$final,$sync) = @_;
|
||||||
|
|
||||||
#-- get memory page/counter according to interface type
|
#-- get memory page/counter according to interface type
|
||||||
|
my $master= $hash->{IODev};
|
||||||
my $interface= $hash->{IODev}->{TYPE};
|
my $interface= $hash->{IODev}->{TYPE};
|
||||||
my $name = $hash->{NAME};
|
my $name = $hash->{NAME};
|
||||||
my $ret;
|
my $ret;
|
||||||
@ -815,15 +849,16 @@ sub OWCOUNT_GetPage ($$$@) {
|
|||||||
$ret = OWXCOUNT_GetPage($hash,$page,$final);
|
$ret = OWXCOUNT_GetPage($hash,$page,$final);
|
||||||
}elsif( $interface eq "OWX_ASYNC" ){
|
}elsif( $interface eq "OWX_ASYNC" ){
|
||||||
if ($sync) {
|
if ($sync) {
|
||||||
#TODO use OWX_ASYNC_Schedule instead
|
my ($task,$task_state);
|
||||||
my $task = PT_THREAD(\&OWXCOUNT_PT_GetPage);
|
|
||||||
eval {
|
eval {
|
||||||
while ($task->PT_SCHEDULE($hash,$page,$final)) { OWX_ASYNC_Poll($hash->{IODev}); };
|
$task = OWXCOUNT_PT_GetPage($hash,$page,$final);
|
||||||
|
OWX_ASYNC_Schedule($hash,$task);
|
||||||
|
$task_state = OWX_ASYNC_RunToCompletion($master,$task);
|
||||||
};
|
};
|
||||||
$ret = ($@) ? GP_Catch($@) : $task->PT_RETVAL();
|
$ret = ($@) ? GP_Catch($@) : ($task_state == PT_ERROR or $task_state == PT_CANCELED) ? $task->PT_CAUSE() : $task->PT_RETVAL();
|
||||||
} else {
|
} else {
|
||||||
eval {
|
eval {
|
||||||
OWX_ASYNC_Schedule( $hash, PT_THREAD(\&OWXCOUNT_PT_GetPage),$hash,$page,$final );
|
OWX_ASYNC_Schedule( $hash, OWXCOUNT_PT_GetPage($hash,$page,$final) );
|
||||||
};
|
};
|
||||||
$ret = GP_Catch($@) if $@;
|
$ret = GP_Catch($@) if $@;
|
||||||
}
|
}
|
||||||
@ -1097,6 +1132,7 @@ sub OWCOUNT_InitializeDevice($) {
|
|||||||
|
|
||||||
my $name = $hash->{NAME};
|
my $name = $hash->{NAME};
|
||||||
#-- get memory page/counter according to interface type
|
#-- get memory page/counter according to interface type
|
||||||
|
my $master= $hash->{IODev};
|
||||||
my $interface= $hash->{IODev}->{TYPE};
|
my $interface= $hash->{IODev}->{TYPE};
|
||||||
|
|
||||||
my $olddata = "";
|
my $olddata = "";
|
||||||
@ -1123,12 +1159,13 @@ sub OWCOUNT_InitializeDevice($) {
|
|||||||
$ret = OWXCOUNT_GetPage($hash,14,0);
|
$ret = OWXCOUNT_GetPage($hash,14,0);
|
||||||
$ret = OWXCOUNT_SetPage($hash,14,$olddata);
|
$ret = OWXCOUNT_SetPage($hash,14,$olddata);
|
||||||
}elsif( $interface eq "OWX_ASYNC" ){
|
}elsif( $interface eq "OWX_ASYNC" ){
|
||||||
#TODO use OWX_ASYNC_Schedule instead
|
my ($task,$task_state);
|
||||||
my $task = PT_THREAD(\&OWXCOUNT_PT_InitializeDevicePage);
|
|
||||||
eval {
|
eval {
|
||||||
while ($task->PT_SCHEDULE($hash,14,$newdata)) { OWX_ASYNC_Poll($hash->{IODev}); };
|
$task = OWXCOUNT_PT_InitializeDevicePage($hash,14,$newdata);
|
||||||
|
OWX_ASYNC_Schedule($hash,$task);
|
||||||
|
$task_state = OWX_ASYNC_RunToCompletion($master,$task);
|
||||||
};
|
};
|
||||||
$ret = ($@) ? GP_Catch($@) : $task->PT_RETVAL();
|
$ret = ($@) ? GP_Catch($@) : ($task_state == PT_ERROR or $task_state == PT_CANCELED) ? $task->PT_CAUSE() : $task->PT_RETVAL();
|
||||||
#-- OWFS interface
|
#-- OWFS interface
|
||||||
}elsif( $interface eq "OWServer" ){
|
}elsif( $interface eq "OWServer" ){
|
||||||
$ret = OWFSCOUNT_GetPage($hash,14,0);
|
$ret = OWFSCOUNT_GetPage($hash,14,0);
|
||||||
@ -1150,12 +1187,13 @@ sub OWCOUNT_InitializeDevice($) {
|
|||||||
$ret = OWXCOUNT_GetPage($hash,0,0);
|
$ret = OWXCOUNT_GetPage($hash,0,0);
|
||||||
$ret = OWXCOUNT_SetPage($hash,0,$olddata);
|
$ret = OWXCOUNT_SetPage($hash,0,$olddata);
|
||||||
}elsif( $interface eq "OWX_ASYNC" ){
|
}elsif( $interface eq "OWX_ASYNC" ){
|
||||||
#TODO use OWX_ASYNC_Schedule instead
|
my ($task,$task_state);
|
||||||
my $task = PT_THREAD(\&OWXCOUNT_PT_InitializeDevicePage);
|
|
||||||
eval {
|
eval {
|
||||||
while ($task->PT_SCHEDULE($hash,0,$newdata)) { OWX_ASYNC_Poll($hash->{IODev}); };
|
$task = OWXCOUNT_PT_InitializeDevicePage($hash,0,$newdata);
|
||||||
|
OWX_ASYNC_Schedule($hash,$task);
|
||||||
|
$task_state = OWX_ASYNC_RunToCompletion($master,$task);
|
||||||
};
|
};
|
||||||
$ret = ($@) ? GP_Catch($@) : $task->PT_RETVAL();
|
$ret = ($@) ? GP_Catch($@) : ($task_state == PT_ERROR or $task_state == PT_CANCELED) ? $task->PT_CAUSE() : $task->PT_RETVAL();
|
||||||
#-- OWFS interface
|
#-- OWFS interface
|
||||||
}elsif( $interface eq "OWServer" ){
|
}elsif( $interface eq "OWServer" ){
|
||||||
$ret = OWFSCOUNT_GetPage($hash,0,0);
|
$ret = OWFSCOUNT_GetPage($hash,0,0);
|
||||||
@ -1372,7 +1410,7 @@ sub OWCOUNT_SetPage ($$$) {
|
|||||||
$ret = OWXCOUNT_SetPage($hash,$page,$data);
|
$ret = OWXCOUNT_SetPage($hash,$page,$data);
|
||||||
}elsif( $interface eq "OWX_ASYNC" ){
|
}elsif( $interface eq "OWX_ASYNC" ){
|
||||||
eval {
|
eval {
|
||||||
OWX_ASYNC_Schedule( $hash, PT_THREAD(\&OWXCOUNT_PT_SetPage),$hash,$page,$data );
|
OWX_ASYNC_Schedule( $hash, OWXCOUNT_PT_SetPage($hash,$page,$data) );
|
||||||
};
|
};
|
||||||
$ret = GP_Catch($@) if $@;
|
$ret = GP_Catch($@) if $@;
|
||||||
#-- OWFS interface
|
#-- OWFS interface
|
||||||
@ -1578,12 +1616,12 @@ sub OWFSCOUNT_SetPage($$$) {
|
|||||||
#
|
#
|
||||||
########################################################################################
|
########################################################################################
|
||||||
|
|
||||||
sub OWXCOUNT_BinValues($$$$$$$$) {
|
sub OWXCOUNT_BinValues($$$$$) {
|
||||||
my ($hash, $context, $success, $reset, $owx_dev, $select, $numread, $res) = @_;
|
my ($hash, $context, $owx_dev, $select, $res) = @_;
|
||||||
|
|
||||||
#-- unused are success, reset, data
|
#-- unused are success, reset, data
|
||||||
|
|
||||||
return undef unless ($success and defined $context and $context =~ /^(get|set)page\.([\d]+)(\.final|)$/);
|
return undef unless (defined $context and $context =~ /^(get|set)page\.([\d]+)(\.final|)$/);
|
||||||
|
|
||||||
my $cmd = $1;
|
my $cmd = $1;
|
||||||
my $page = $2;
|
my $page = $2;
|
||||||
@ -1711,7 +1749,7 @@ sub OWXCOUNT_GetPage($$$) {
|
|||||||
if( $res eq 0 );
|
if( $res eq 0 );
|
||||||
return "$owx_dev has returned invalid data"
|
return "$owx_dev has returned invalid data"
|
||||||
if( length($res)!=54);
|
if( length($res)!=54);
|
||||||
return OWXCOUNT_BinValues($hash,$context,1,1,$owx_dev,$select,42,substr($res,12));
|
return OWXCOUNT_BinValues($hash,$context,$owx_dev,$select,substr($res,12));
|
||||||
}
|
}
|
||||||
|
|
||||||
########################################################################################
|
########################################################################################
|
||||||
@ -1822,9 +1860,11 @@ sub OWXCOUNT_SetPage($$$) {
|
|||||||
########################################################################################
|
########################################################################################
|
||||||
|
|
||||||
sub OWXCOUNT_PT_GetPage($$$) {
|
sub OWXCOUNT_PT_GetPage($$$) {
|
||||||
my ($thread,$hash,$page,$final) = @_;
|
|
||||||
|
|
||||||
my ($select, $res, $response);
|
my ($hash,$page,$final) = @_;
|
||||||
|
|
||||||
|
return PT_THREAD(sub {
|
||||||
|
my ($thread) = @_;
|
||||||
|
|
||||||
#-- ID of the device, hash of the busmaster
|
#-- ID of the device, hash of the busmaster
|
||||||
my $owx_dev = $hash->{ROM_ID};
|
my $owx_dev = $hash->{ROM_ID};
|
||||||
@ -1832,44 +1872,38 @@ sub OWXCOUNT_PT_GetPage($$$) {
|
|||||||
|
|
||||||
PT_BEGIN($thread);
|
PT_BEGIN($thread);
|
||||||
|
|
||||||
#-- reset presence
|
|
||||||
$hash->{PRESENT} = 0;
|
|
||||||
|
|
||||||
#=============== wrong value requested ===============================
|
#=============== wrong value requested ===============================
|
||||||
if( ($page<0) || ($page>15) ){
|
if( ($page<0) || ($page>15) ){
|
||||||
PT_EXIT("wrong memory page requested");
|
die("wrong memory page requested");
|
||||||
}
|
}
|
||||||
#=============== get memory + counter ===============================
|
#=============== get memory + counter ===============================
|
||||||
#-- issue the match ROM command \x55 and the read memory + counter command
|
#-- issue the match ROM command \x55 and the read memory + counter command
|
||||||
# \xA5 TA1 TA2 reading 40 data bytes and 2 CRC bytes
|
# \xA5 TA1 TA2 reading 40 data bytes and 2 CRC bytes
|
||||||
my $ta2 = ($page*32) >> 8;
|
my $ta2 = ($page*32) >> 8;
|
||||||
my $ta1 = ($page*32) & 255;
|
my $ta1 = ($page*32) & 255;
|
||||||
$select=sprintf("\xA5%c%c",$ta1,$ta2);
|
$thread->{'select'}=sprintf("\xA5%c%c",$ta1,$ta2);
|
||||||
|
|
||||||
#-- reading 9 + 3 + 40 data bytes (32 byte memory, 4 byte counter + 4 byte zeroes) and 2 CRC bytes = 54 bytes
|
#-- reading 9 + 3 + 40 data bytes (32 byte memory, 4 byte counter + 4 byte zeroes) and 2 CRC bytes = 54 bytes
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, $select, 42 )) {
|
|
||||||
PT_EXIT("device $owx_dev not accessible for reading page $page");
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev, $thread->{'select'}, 42 );
|
||||||
}
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
PT_WAIT_UNTIL($thread->{ExecuteResponse});
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
$response = $thread->{ExecuteResponse};
|
delete $thread->{TimeoutTime};
|
||||||
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
|
$thread->{response} = $thread->{pt_execute}->PT_RETVAL();
|
||||||
|
|
||||||
#-- reset the bus (needed to stop receiving data ?)
|
#-- reset the bus (needed to stop receiving data ?)
|
||||||
OWX_ASYNC_Execute( $master, $thread, 1, undef, undef, undef );
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,undef,undef,undef);
|
||||||
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
|
delete $thread->{TimeoutTime};
|
||||||
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
|
|
||||||
unless ($response->{success}) {
|
if (my $ret = OWXCOUNT_BinValues($hash,"getpage.".$page.($final ? ".final" : ""),$owx_dev,$thread->{'select'},$thread->{response})) {
|
||||||
PT_EXIT("device $owx_dev error reading page $page");
|
die $ret;
|
||||||
}
|
|
||||||
$res = $response->{readdata};
|
|
||||||
|
|
||||||
#TODO validate whether testing '0' is appropriate with async interface
|
|
||||||
if( $res eq 0 ) {
|
|
||||||
PT_EXIT("device $owx_dev error reading page $page");
|
|
||||||
}
|
|
||||||
$res = OWXCOUNT_BinValues($hash,"getpage.".$page.($final ? ".final" : ""),1,1,$owx_dev,$response->{writedata},$response->{numread},$res);
|
|
||||||
if ($res) {
|
|
||||||
PT_EXIT($res);
|
|
||||||
}
|
}
|
||||||
PT_END;
|
PT_END;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
########################################################################################
|
########################################################################################
|
||||||
@ -1883,9 +1917,12 @@ sub OWXCOUNT_PT_GetPage($$$) {
|
|||||||
|
|
||||||
sub OWXCOUNT_PT_SetPage($$$) {
|
sub OWXCOUNT_PT_SetPage($$$) {
|
||||||
|
|
||||||
my ($thread,$hash,$page,$data) = @_;
|
my ($hash,$page,$data) = @_;
|
||||||
|
|
||||||
my ($select, $res, $response);
|
return PT_THREAD(sub {
|
||||||
|
my ($thread) = @_;
|
||||||
|
|
||||||
|
my ($res, $response);
|
||||||
|
|
||||||
#-- ID of the device, hash of the busmaster
|
#-- ID of the device, hash of the busmaster
|
||||||
my $owx_dev = $hash->{ROM_ID};
|
my $owx_dev = $hash->{ROM_ID};
|
||||||
@ -1906,93 +1943,64 @@ sub OWXCOUNT_PT_SetPage($$$) {
|
|||||||
my $ta2 = ($page*32) >> 8;
|
my $ta2 = ($page*32) >> 8;
|
||||||
my $ta1 = ($page*32) & 255;
|
my $ta1 = ($page*32) & 255;
|
||||||
#Log 1, "OWXCOUNT: setting page Nr. $ta2 $ta1 $data";
|
#Log 1, "OWXCOUNT: setting page Nr. $ta2 $ta1 $data";
|
||||||
$select=sprintf("\x0F%c%c",$ta1,$ta2).$data;
|
$thread->{'select'}=sprintf("\x0F%c%c",$ta1,$ta2).$data;
|
||||||
|
|
||||||
#-- first command, next 2 are address, then data
|
|
||||||
#$res2 = "OWCOUNT SET PAGE 1 device $owx_dev ";
|
|
||||||
#for($i=0;$i<10;$i++){
|
|
||||||
# $j=int(ord(substr($select,$i,1))/16);
|
|
||||||
# $k=ord(substr($select,$i,1))%16;
|
|
||||||
# $res2.=sprintf "0x%1x%1x ",$j,$k;
|
|
||||||
#}
|
|
||||||
#main::Log(1, $res2);
|
|
||||||
|
|
||||||
#"setpage.1"
|
#"setpage.1"
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, $select, 0)) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev, $thread->{'select'}, 0 );
|
||||||
PT_EXIT("device $owx_dev not accessible in writing scratchpad");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL($thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
unless ($thread->{ExecuteResponse}->{success}) {
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
PT_EXIT("device $owx_dev error writing scratchpad");
|
|
||||||
}
|
|
||||||
|
|
||||||
#-- issue the match ROM command \x55 and the read scratchpad command
|
#-- issue the match ROM command \x55 and the read scratchpad command
|
||||||
# \xAA, receiving 2 address bytes, 1 status byte and scratchpad content
|
# \xAA, receiving 2 address bytes, 1 status byte and scratchpad content
|
||||||
$select = "\xAA";
|
$thread->{'select'} = "\xAA";
|
||||||
#-- reading 9 + 3 + up to 32 bytes
|
#-- reading 9 + 3 + up to 32 bytes
|
||||||
# TODO: sometimes much less than 28
|
# TODO: sometimes much less than 28
|
||||||
#"setpage.2"
|
#"setpage.2"
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, $select, 28)) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev, $thread->{'select'}, 28 );
|
||||||
PT_EXIT("device $owx_dev not accessible in writing scratchpad");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL($thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
$response = $thread->{ExecuteResponse};
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
unless ($response->{success}) {
|
$res = $thread->{pt_execute}->PT_RETVAL();
|
||||||
PT_EXIT("device $owx_dev error writing scratchpad");
|
|
||||||
}
|
|
||||||
$res = $response->{readdata};
|
|
||||||
if( length($res) < 13 ){
|
if( length($res) < 13 ){
|
||||||
PT_EXIT("device $owx_dev not accessible in reading scratchpad");
|
PT_EXIT("device $owx_dev not accessible in reading scratchpad");
|
||||||
}
|
}
|
||||||
|
|
||||||
#-- first 1 command, next 2 are address, then data
|
|
||||||
#$res3 = substr($res,9,10);
|
|
||||||
#$res2 = "OWCOUNT SET PAGE 2 device $owx_dev ";
|
|
||||||
#for($i=0;$i<10;$i++){
|
|
||||||
# $j=int(ord(substr($res3,$i,1))/16);
|
|
||||||
# $k=ord(substr($res3,$i,1))%16;
|
|
||||||
# $res2.=sprintf "0x%1x%1x ",$j,$k;
|
|
||||||
#}
|
|
||||||
#main::Log(1, $res2);
|
|
||||||
#-- issue the match ROM command \x55 and the copy scratchpad command
|
#-- issue the match ROM command \x55 and the copy scratchpad command
|
||||||
# \x5A followed by 3 byte authentication code obtained in previous read
|
# \x5A followed by 3 byte authentication code obtained in previous read
|
||||||
$select="\x5A".substr($res,0,3);
|
$thread->{'select'}="\x5A".substr($res,0,3);
|
||||||
#-- first command, next 2 are address, then data
|
#-- first command, next 2 are address, then data
|
||||||
#$res2 = "OWCOUNT SET PAGE 3 device $owx_dev ";
|
|
||||||
#for($i=0;$i<10;$i++){
|
|
||||||
# $j=int(ord(substr($select,$i,1))/16);
|
|
||||||
# $k=ord(substr($select,$i,1))%16;
|
|
||||||
# $res2.=sprintf "0x%1x%1x ",$j,$k;
|
|
||||||
#}
|
|
||||||
#main::Log(1, $res2);
|
|
||||||
|
|
||||||
#"setpage.3"
|
#"setpage.3"
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, $select, 6)) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev, $thread->{'select'}, 6 );
|
||||||
PT_EXIT("device $owx_dev not accessible for copying scratchpad");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL($thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
$response = $thread->{ExecuteResponse};
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
unless ($response->{success}) {
|
$res = $thread->{pt_execute}->PT_RETVAL();
|
||||||
PT_EXIT("device $owx_dev error copying scratchpad");
|
|
||||||
}
|
|
||||||
$res = $response->{readdata};
|
|
||||||
#TODO validate whether testing '0' is appropriate with async interface
|
#TODO validate whether testing '0' is appropriate with async interface
|
||||||
#-- process results
|
#-- process results
|
||||||
if( $res eq 0 ){
|
if( $res eq 0 ){
|
||||||
PT_EXIT("device $owx_dev error copying scratchpad");
|
PT_EXIT("device $owx_dev error copying scratchpad");
|
||||||
}
|
}
|
||||||
PT_END;
|
PT_END;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
sub OWXCOUNT_PT_InitializeDevicePage($$$) {
|
sub OWXCOUNT_PT_InitializeDevicePage($$$) {
|
||||||
my ($thread,$hash,$page,$newdata) = @_;
|
my ($hash,$page,$newdata) = @_;
|
||||||
|
|
||||||
|
return PT_THREAD(sub {
|
||||||
|
my ($thread) = @_;
|
||||||
|
|
||||||
my $ret;
|
my $ret;
|
||||||
|
|
||||||
PT_BEGIN($thread);
|
PT_BEGIN($thread);
|
||||||
|
|
||||||
$thread->{task} = PT_THREAD(\&OWXCOUNT_PT_GetPage);
|
$thread->{task} = OWXCOUNT_PT_GetPage($hash,$page,0);
|
||||||
PT_WAIT_THREAD($thread->{task},$hash,$page,0);
|
PT_WAIT_THREAD($thread->{task});
|
||||||
$ret = $thread->{task}->PT_RETVAL();
|
$ret = $thread->{task}->PT_RETVAL();
|
||||||
if ($ret) {
|
if ($ret) {
|
||||||
PT_EXIT($ret);
|
PT_EXIT($ret);
|
||||||
@ -2000,27 +2008,28 @@ sub OWXCOUNT_PT_InitializeDevicePage($$$) {
|
|||||||
|
|
||||||
$thread->{olddata} = $hash->{owg_str}->[14];
|
$thread->{olddata} = $hash->{owg_str}->[14];
|
||||||
|
|
||||||
$thread->{task} = PT_THREAD(\&OWXCOUNT_PT_SetPage);
|
$thread->{task} = OWXCOUNT_PT_SetPage($hash,$page,$newdata);
|
||||||
PT_WAIT_THREAD($thread->{task},$hash,$page,$newdata);
|
PT_WAIT_THREAD($thread->{task});
|
||||||
$ret = $thread->{task}->PT_RETVAL();
|
$ret = $thread->{task}->PT_RETVAL();
|
||||||
if ($ret) {
|
if ($ret) {
|
||||||
PT_EXIT($ret);
|
PT_EXIT($ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
$thread->{task} = PT_THREAD(\&OWXCOUNT_PT_GetPage);
|
$thread->{task} = OWXCOUNT_PT_GetPage($hash,$page,0);
|
||||||
PT_WAIT_THREAD($thread->{task},$hash,$page,0);
|
PT_WAIT_THREAD($thread->{task});
|
||||||
$ret = $thread->{task}->PT_RETVAL();
|
$ret = $thread->{task}->PT_RETVAL();
|
||||||
if ($ret) {
|
if ($ret) {
|
||||||
PT_EXIT($ret);
|
PT_EXIT($ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
$thread->{task} = PT_THREAD(\&OWXCOUNT_PT_SetPage);
|
$thread->{task} = OWXCOUNT_PT_SetPage($hash,$page,$thread->{olddata});
|
||||||
PT_WAIT_THREAD($thread->{task},$hash,$page,$thread->{olddata});
|
PT_WAIT_THREAD($thread->{task});
|
||||||
$ret = $thread->{task}->PT_RETVAL();
|
$ret = $thread->{task}->PT_RETVAL();
|
||||||
if ($ret) {
|
if ($ret) {
|
||||||
PT_EXIT($ret);
|
PT_EXIT($ret);
|
||||||
}
|
}
|
||||||
PT_END;
|
PT_END;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
@ -49,13 +49,26 @@
|
|||||||
package main;
|
package main;
|
||||||
|
|
||||||
use vars qw{%attr %defs %modules $readingFnAttributes $init_done};
|
use vars qw{%attr %defs %modules $readingFnAttributes $init_done};
|
||||||
use Time::HiRes qw(usleep ualarm gettimeofday tv_interval);
|
use Time::HiRes qw(gettimeofday);
|
||||||
|
|
||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
|
|
||||||
|
#add FHEM/lib to @INC if it's not allready included. Should rather be in fhem.pl than here though...
|
||||||
|
BEGIN {
|
||||||
|
if (!grep(/FHEM\/lib$/,@INC)) {
|
||||||
|
foreach my $inc (grep(/FHEM$/,@INC)) {
|
||||||
|
push @INC,$inc."/lib";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
use GPUtils qw(:all);
|
||||||
|
use ProtoThreads;
|
||||||
|
no warnings 'deprecated';
|
||||||
sub Log($$);
|
sub Log($$);
|
||||||
|
|
||||||
my $owx_version="5.12";
|
my $owx_version="5.13";
|
||||||
#-- declare variables
|
#-- declare variables
|
||||||
my %gets = (
|
my %gets = (
|
||||||
"present" => "",
|
"present" => "",
|
||||||
@ -92,6 +105,8 @@ sub OWID_Initialize ($) {
|
|||||||
$hash->{GetFn} = "OWID_Get";
|
$hash->{GetFn} = "OWID_Get";
|
||||||
$hash->{SetFn} = "OWID_Set";
|
$hash->{SetFn} = "OWID_Set";
|
||||||
$hash->{AttrFn} = "OWID_Attr";
|
$hash->{AttrFn} = "OWID_Attr";
|
||||||
|
$hash->{NotifyFn} = "OWID_Notify";
|
||||||
|
$hash->{InitFn} = "OWID_Init";
|
||||||
$hash->{AttrList} = "IODev do_not_notify:0,1 showtime:0,1 model loglevel:0,1,2,3,4,5 ".
|
$hash->{AttrList} = "IODev do_not_notify:0,1 showtime:0,1 model loglevel:0,1,2,3,4,5 ".
|
||||||
"interval ".
|
"interval ".
|
||||||
$readingFnAttributes;
|
$readingFnAttributes;
|
||||||
@ -199,12 +214,27 @@ sub OWID_Define ($$) {
|
|||||||
readingsSingleUpdate($hash,"state","Defined",1);
|
readingsSingleUpdate($hash,"state","Defined",1);
|
||||||
Log 3, "OWID: Device $name defined.";
|
Log 3, "OWID: Device $name defined.";
|
||||||
|
|
||||||
#-- Initialization reading according to interface type
|
$hash->{NOTIFYDEV} = "global";
|
||||||
my $interface= $hash->{IODev}->{TYPE};
|
|
||||||
|
|
||||||
|
if ($init_done) {
|
||||||
|
return OWID_Init($hash);
|
||||||
|
}
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub OWID_Notify ($$) {
|
||||||
|
my ($hash,$dev) = @_;
|
||||||
|
if( grep(m/^(INITIALIZED|REREADCFG)$/, @{$dev->{CHANGED}}) ) {
|
||||||
|
OWID_Init($hash);
|
||||||
|
} elsif( grep(m/^SAVE$/, @{$dev->{CHANGED}}) ) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub OWID_Init ($) {
|
||||||
|
my ($hash)=@_;
|
||||||
#-- Start timer for updates
|
#-- Start timer for updates
|
||||||
InternalTimer(time()+5+$hash->{INTERVAL}, "OWID_GetValues", $hash, 0);
|
RemoveInternalTimer($hash);
|
||||||
|
InternalTimer(gettimeofday()+10, "OWID_GetValues", $hash, 0);
|
||||||
#--
|
#--
|
||||||
readingsSingleUpdate($hash,"state","Initialized",1);
|
readingsSingleUpdate($hash,"state","Initialized",1);
|
||||||
|
|
||||||
@ -248,6 +278,9 @@ sub OWID_Attr(@) {
|
|||||||
AssignIoPort($hash,$value);
|
AssignIoPort($hash,$value);
|
||||||
if( defined($hash->{IODev}) ) {
|
if( defined($hash->{IODev}) ) {
|
||||||
$hash->{ASYNC} = $hash->{IODev}->{TYPE} eq "OWX_ASYNC" ? 1 : 0;
|
$hash->{ASYNC} = $hash->{IODev}->{TYPE} eq "OWX_ASYNC" ? 1 : 0;
|
||||||
|
if ($init_done) {
|
||||||
|
OWID_Init($hash);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
last;
|
last;
|
||||||
};
|
};
|
||||||
@ -301,7 +334,15 @@ sub OWID_Get($@) {
|
|||||||
my $master = $hash->{IODev};
|
my $master = $hash->{IODev};
|
||||||
#-- asynchronous mode
|
#-- asynchronous mode
|
||||||
if( $hash->{ASYNC} ){
|
if( $hash->{ASYNC} ){
|
||||||
$value = OWX_ASYNC_Verify($master,$hash->{ROM_ID});
|
my ($task,$task_state);
|
||||||
|
eval {
|
||||||
|
$task = OWX_ASYNC_PT_Verify($hash);
|
||||||
|
OWX_ASYNC_Schedule($hash,$task);
|
||||||
|
$task_state = OWX_ASYNC_RunToCompletion($master,$task);
|
||||||
|
};
|
||||||
|
return GP_Catch($@) if $@;
|
||||||
|
return $task->PT_CAUSE() if ($task_state == PT_ERROR or $task_state == PT_CANCELED);
|
||||||
|
return "$name.present => ".ReadingsVal($name,"present","unknown");
|
||||||
} else {
|
} else {
|
||||||
$value = OWX_Verify($master,$hash->{ROM_ID});
|
$value = OWX_Verify($master,$hash->{ROM_ID});
|
||||||
}
|
}
|
||||||
@ -344,22 +385,18 @@ sub OWID_GetValues($) {
|
|||||||
#-- hash of the busmaster
|
#-- hash of the busmaster
|
||||||
my $master = $hash->{IODev};
|
my $master = $hash->{IODev};
|
||||||
|
|
||||||
#-- measure elapsed time
|
|
||||||
my $t0 = [gettimeofday];
|
|
||||||
|
|
||||||
if( $hash->{ASYNC} ){
|
if( $hash->{ASYNC} ){
|
||||||
$value = OWX_ASYNC_Verify($master,$hash->{ROM_ID});
|
#TODO use OWX_ASYNC_Schedule instead
|
||||||
|
my $task = OWX_ASYNC_PT_Verify($hash);
|
||||||
|
eval {
|
||||||
|
OWX_ASYNC_Schedule($hash,$task);
|
||||||
|
};
|
||||||
|
return GP_Catch($@) if $@;
|
||||||
|
return undef;
|
||||||
} else {
|
} else {
|
||||||
$value = OWX_Verify($master,$hash->{ROM_ID});
|
$value = OWX_Verify($master,$hash->{ROM_ID});
|
||||||
}
|
}
|
||||||
|
|
||||||
#my $thr = threads->create('OWX_Verify', $master, $hash->{ROM_ID});
|
|
||||||
#$thr->detach();
|
|
||||||
|
|
||||||
my $t1 = [gettimeofday];
|
|
||||||
my $t0_t1 = tv_interval $t0, $t1;
|
|
||||||
#Log 1,"====> Time for verify = $t0_t1";
|
|
||||||
|
|
||||||
#-- generate an event only if presence has changed
|
#-- generate an event only if presence has changed
|
||||||
if( $value == 0 ){
|
if( $value == 0 ){
|
||||||
readingsSingleUpdate($hash,"present",0,$hash->{PRESENT});
|
readingsSingleUpdate($hash,"present",0,$hash->{PRESENT});
|
||||||
|
@ -58,6 +58,7 @@
|
|||||||
package main;
|
package main;
|
||||||
|
|
||||||
use vars qw{%attr %defs %modules $readingFnAttributes $init_done};
|
use vars qw{%attr %defs %modules $readingFnAttributes $init_done};
|
||||||
|
use Time::HiRes qw(gettimeofday);
|
||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
|
|
||||||
@ -76,7 +77,7 @@ no warnings 'deprecated';
|
|||||||
|
|
||||||
sub Log3($$$);
|
sub Log3($$$);
|
||||||
|
|
||||||
my $owx_version="3.37";
|
my $owx_version="3.38";
|
||||||
#-- controller may be HD44780 or KS0073
|
#-- controller may be HD44780 or KS0073
|
||||||
# these values have to be changed for different display
|
# these values have to be changed for different display
|
||||||
# geometries or memory maps
|
# geometries or memory maps
|
||||||
@ -132,6 +133,7 @@ sub OWLCD_Initialize ($) {
|
|||||||
$hash->{UndefFn} = "OWLCD_Undef";
|
$hash->{UndefFn} = "OWLCD_Undef";
|
||||||
$hash->{GetFn} = "OWLCD_Get";
|
$hash->{GetFn} = "OWLCD_Get";
|
||||||
$hash->{SetFn} = "OWLCD_Set";
|
$hash->{SetFn} = "OWLCD_Set";
|
||||||
|
$hash->{NotifyFn} = "OWLCD_Notify";
|
||||||
$hash->{InitFn} = "OWLCD_Init";
|
$hash->{InitFn} = "OWLCD_Init";
|
||||||
$hash->{AttrFn} = "OWLCD_Attr";
|
$hash->{AttrFn} = "OWLCD_Attr";
|
||||||
my $attlist = "IODev do_not_notify:0,1 showtime:0,1 ".
|
my $attlist = "IODev do_not_notify:0,1 showtime:0,1 ".
|
||||||
@ -198,12 +200,22 @@ sub OWLCD_Define ($$) {
|
|||||||
$hash->{STATE} = "Defined";
|
$hash->{STATE} = "Defined";
|
||||||
Log3 $name,3, "OWLCD: Device $name defined.";
|
Log3 $name,3, "OWLCD: Device $name defined.";
|
||||||
|
|
||||||
if (($hash->{IODev}->{TYPE} eq "OWX") or $main::init_done) {
|
$hash->{NOTIFYDEV} = "global";
|
||||||
|
|
||||||
|
if ($main::init_done) {
|
||||||
return OWLCD_Init($hash);
|
return OWLCD_Init($hash);
|
||||||
}
|
}
|
||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub OWLCD_Notify ($$) {
|
||||||
|
my ($hash,$dev) = @_;
|
||||||
|
if( grep(m/^(INITIALIZED|REREADCFG)$/, @{$dev->{CHANGED}}) ) {
|
||||||
|
OWLCD_Init($hash);
|
||||||
|
} elsif( grep(m/^SAVE$/, @{$dev->{CHANGED}}) ) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sub OWLCD_Init($) {
|
sub OWLCD_Init($) {
|
||||||
my ($hash) = @_;
|
my ($hash) = @_;
|
||||||
#-- Initialization reading according to interface type
|
#-- Initialization reading according to interface type
|
||||||
@ -221,11 +233,11 @@ sub OWLCD_Init($) {
|
|||||||
eval {
|
eval {
|
||||||
OWXLCD_InitializeDevice($hash);
|
OWXLCD_InitializeDevice($hash);
|
||||||
#-- set backlight on
|
#-- set backlight on
|
||||||
OWX_ASYNC_Schedule($hash,PT_THREAD(\&OWXLCD_PT_SetFunction),$hash,"bklon",0);
|
OWX_ASYNC_Schedule($hash,OWXLCD_PT_SetFunction($hash,"bklon",0));
|
||||||
#-- erase all icons
|
#-- erase all icons
|
||||||
OWX_ASYNC_Schedule($hash,PT_THREAD(\&OWXLCD_PT_SetIcon),$hash,0,0);
|
OWX_ASYNC_Schedule($hash,OWXLCD_PT_SetIcon($hash,0,0));
|
||||||
#-- erase alarm state
|
#-- erase alarm state
|
||||||
OWX_ASYNC_Schedule($hash,PT_THREAD(\&OWXLCD_PT_SetFunction),$hash,"gpio",15);
|
OWX_ASYNC_Schedule($hash,OWXLCD_PT_SetFunction($hash,"gpio",15));
|
||||||
};
|
};
|
||||||
return GP_Catch($@) if $@;
|
return GP_Catch($@) if $@;
|
||||||
#-- Unknown interface
|
#-- Unknown interface
|
||||||
@ -257,6 +269,9 @@ sub OWLCD_Attr(@) {
|
|||||||
AssignIoPort($hash,$value);
|
AssignIoPort($hash,$value);
|
||||||
if( defined($hash->{IODev}) ) {
|
if( defined($hash->{IODev}) ) {
|
||||||
$hash->{ASYNC} = $hash->{IODev}->{TYPE} eq "OWX_ASYNC" ? 1 : 0;
|
$hash->{ASYNC} = $hash->{IODev}->{TYPE} eq "OWX_ASYNC" ? 1 : 0;
|
||||||
|
if ($main::init_done) {
|
||||||
|
return OWLCD_Init($hash);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
last;
|
last;
|
||||||
};
|
};
|
||||||
@ -302,13 +317,22 @@ sub OWLCD_Get($@) {
|
|||||||
return "$name.id => $value";
|
return "$name.id => $value";
|
||||||
}
|
}
|
||||||
|
|
||||||
#-- get present
|
|
||||||
if($a[1] eq "present") {
|
|
||||||
#-- hash of the busmaster
|
#-- hash of the busmaster
|
||||||
my $master = $hash->{IODev};
|
my $master = $hash->{IODev};
|
||||||
|
|
||||||
|
#-- get present
|
||||||
|
if($a[1] eq "present") {
|
||||||
#-- asynchronous mode
|
#-- asynchronous mode
|
||||||
if( $hash->{ASYNC} ){
|
if( $hash->{ASYNC} ){
|
||||||
$value = OWX_ASYNC_Verify($master,$hash->{ROM_ID});
|
my ($task,$task_state);
|
||||||
|
eval {
|
||||||
|
$task = OWX_ASYNC_PT_Verify($hash);
|
||||||
|
OWX_ASYNC_Schedule($hash,$task);
|
||||||
|
$task_state = OWX_ASYNC_RunToCompletion($master,$task);
|
||||||
|
};
|
||||||
|
return GP_Catch($@) if $@;
|
||||||
|
return $task->PT_CAUSE() if ($task_state == PT_ERROR or $task_state == PT_CANCELED);
|
||||||
|
return "$name.present => ".ReadingsVal($name,"present","unknown");
|
||||||
} else {
|
} else {
|
||||||
$value = OWX_Verify($master,$hash->{ROM_ID});
|
$value = OWX_Verify($master,$hash->{ROM_ID});
|
||||||
}
|
}
|
||||||
@ -319,11 +343,13 @@ sub OWLCD_Get($@) {
|
|||||||
#-- get gpio states
|
#-- get gpio states
|
||||||
if($a[1] eq "gpio") {
|
if($a[1] eq "gpio") {
|
||||||
if ($hash->{ASYNC}) {
|
if ($hash->{ASYNC}) {
|
||||||
my $task = PT_THREAD(\&OWXLCD_PT_Get);
|
my ($task,$task_state);
|
||||||
eval {
|
eval {
|
||||||
while ($task->PT_SCHEDULE($hash,"gpio")) { OWX_ASYNC_Poll($hash->{IODev}); };
|
$task = OWXLCD_PT_Get($hash,"gpio");
|
||||||
|
OWX_ASYNC_Schedule($hash,$task);
|
||||||
|
$task_state = OWX_ASYNC_RunToCompletion($master,$task);
|
||||||
};
|
};
|
||||||
$ret = ($@) ? GP_Catch($@) : $task->PT_RETVAL();
|
$ret = ($@) ? GP_Catch($@) : ($task_state == PT_ERROR or $task_state == PT_CANCELED) ? $task->PT_CAUSE() : $task->PT_RETVAL();
|
||||||
return $ret if $ret;
|
return $ret if $ret;
|
||||||
return "$name.gpio => ".main::ReadingsVal($hash->{NAME},"gpio","");
|
return "$name.gpio => ".main::ReadingsVal($hash->{NAME},"gpio","");
|
||||||
} else {
|
} else {
|
||||||
@ -335,11 +361,13 @@ sub OWLCD_Get($@) {
|
|||||||
#-- get gpio counters
|
#-- get gpio counters
|
||||||
if($a[1] eq "counter") {
|
if($a[1] eq "counter") {
|
||||||
if ($hash->{ASYNC}) {
|
if ($hash->{ASYNC}) {
|
||||||
my $task = PT_THREAD(\&OWXLCD_PT_Get);
|
my ($task,$task_state);
|
||||||
eval {
|
eval {
|
||||||
while ($task->PT_SCHEDULE($hash,"counter")) { OWX_ASYNC_Poll($hash->{IODev}); };
|
$task = OWXLCD_PT_Get($hash,"counter");
|
||||||
|
OWX_ASYNC_Schedule($hash,$task);
|
||||||
|
$task_state = OWX_ASYNC_RunToCompletion($master,$task);
|
||||||
};
|
};
|
||||||
$ret = ($@) ? GP_Catch($@) : $task->PT_RETVAL();
|
$ret = ($@) ? GP_Catch($@) : ($task_state == PT_ERROR or $task_state == PT_CANCELED) ? $task->PT_CAUSE() : $task->PT_RETVAL();
|
||||||
return $ret if $ret;
|
return $ret if $ret;
|
||||||
return "$name.counter => ".main::ReadingsVal($hash->{NAME},"counter","");
|
return "$name.counter => ".main::ReadingsVal($hash->{NAME},"counter","");
|
||||||
} else {
|
} else {
|
||||||
@ -351,11 +379,13 @@ sub OWLCD_Get($@) {
|
|||||||
#-- get version
|
#-- get version
|
||||||
if($a[1] eq "version") {
|
if($a[1] eq "version") {
|
||||||
if ($hash->{ASYNC}) {
|
if ($hash->{ASYNC}) {
|
||||||
my $task = PT_THREAD(\&OWXLCD_PT_Get);
|
my ($task,$task_state);
|
||||||
eval {
|
eval {
|
||||||
while ($task->PT_SCHEDULE($hash,"version")) { OWX_ASYNC_Poll($hash->{IODev}); };
|
$task = OWXLCD_PT_Get($hash,"version");
|
||||||
|
OWX_ASYNC_Schedule($hash,$task);
|
||||||
|
$task_state = OWX_ASYNC_RunToCompletion($master,$task);
|
||||||
};
|
};
|
||||||
$ret = ($@) ? GP_Catch($@) : $task->PT_RETVAL();
|
$ret = ($@) ? GP_Catch($@) : ($task_state == PT_ERROR or $task_state == PT_CANCELED) ? $task->PT_CAUSE() : $task->PT_RETVAL();
|
||||||
return $ret if $ret;
|
return $ret if $ret;
|
||||||
return "$name.gpio => ".main::ReadingsVal($hash->{NAME},"version","");
|
return "$name.gpio => ".main::ReadingsVal($hash->{NAME},"version","");
|
||||||
} else {
|
} else {
|
||||||
@ -369,11 +399,13 @@ sub OWLCD_Get($@) {
|
|||||||
my $page = (defined $a[2] and $a[2] =~ m/\d/) ? int($a[2]) : 0;
|
my $page = (defined $a[2] and $a[2] =~ m/\d/) ? int($a[2]) : 0;
|
||||||
Log3 $name,1,"Calling GetMemory with page $page";
|
Log3 $name,1,"Calling GetMemory with page $page";
|
||||||
if ($hash->{ASYNC}) {
|
if ($hash->{ASYNC}) {
|
||||||
my $task = PT_THREAD(\&OWXLCD_PT_GetMemory);
|
my ($task,$task_state);
|
||||||
eval {
|
eval {
|
||||||
while ($task->PT_SCHEDULE($hash,$page)) { OWX_ASYNC_Poll($hash->{IODev}); };
|
$task = OWXLCD_PT_GetMemory($hash,$page);
|
||||||
|
OWX_ASYNC_Schedule($hash,$task);
|
||||||
|
$task_state = OWX_ASYNC_RunToCompletion($master,$task);
|
||||||
};
|
};
|
||||||
$ret = ($@) ? GP_Catch($@) : $task->PT_RETVAL();
|
$ret = ($@) ? GP_Catch($@) : ($task_state == PT_ERROR or $task_state == PT_CANCELED) ? $task->PT_CAUSE() : $task->PT_RETVAL();
|
||||||
return $ret if $ret;
|
return $ret if $ret;
|
||||||
return "$name $reading $page => ".main::ReadingsVal($hash->{NAME},"memory$page","");
|
return "$name $reading $page => ".main::ReadingsVal($hash->{NAME},"memory$page","");
|
||||||
} else {
|
} else {
|
||||||
@ -468,7 +500,7 @@ sub OWLCD_Set($@) {
|
|||||||
if( ! ((int($value) >= 0) && (int($value) <= 7)) );
|
if( ! ((int($value) >= 0) && (int($value) <= 7)) );
|
||||||
if ($hash->{ASYNC}) {
|
if ($hash->{ASYNC}) {
|
||||||
eval {
|
eval {
|
||||||
OWX_ASYNC_Schedule( $hash, PT_THREAD(\&OWXLCD_PT_SetFunction), $hash, "gpio", int($value) );
|
OWX_ASYNC_Schedule( $hash, OWXLCD_PT_SetFunction($hash, "gpio", int($value)) );
|
||||||
};
|
};
|
||||||
return GP_Catch($@) if $@;
|
return GP_Catch($@) if $@;
|
||||||
} else {
|
} else {
|
||||||
@ -483,7 +515,7 @@ sub OWLCD_Set($@) {
|
|||||||
if( uc($value) eq "ON"){
|
if( uc($value) eq "ON"){
|
||||||
if ($hash->{ASYNC}) {
|
if ($hash->{ASYNC}) {
|
||||||
eval {
|
eval {
|
||||||
OWX_ASYNC_Schedule( $hash, PT_THREAD(\&OWXLCD_PT_SetFunction), $hash, "lcdon", 0 );
|
OWX_ASYNC_Schedule( $hash, OWXLCD_PT_SetFunction($hash, "lcdon", 0) );
|
||||||
};
|
};
|
||||||
return GP_Catch($@) if $@;
|
return GP_Catch($@) if $@;
|
||||||
} else {
|
} else {
|
||||||
@ -492,7 +524,7 @@ sub OWLCD_Set($@) {
|
|||||||
}elsif( uc($value) eq "OFF" ){
|
}elsif( uc($value) eq "OFF" ){
|
||||||
if ($hash->{ASYNC}) {
|
if ($hash->{ASYNC}) {
|
||||||
eval {
|
eval {
|
||||||
OWX_ASYNC_Schedule( $hash, PT_THREAD(\&OWXLCD_PT_SetFunction), $hash, "lcdoff", 0 );
|
OWX_ASYNC_Schedule( $hash, OWXLCD_PT_SetFunction($hash, "lcdoff", 0) );
|
||||||
};
|
};
|
||||||
return GP_Catch($@) if $@;
|
return GP_Catch($@) if $@;
|
||||||
} else {
|
} else {
|
||||||
@ -510,7 +542,7 @@ sub OWLCD_Set($@) {
|
|||||||
if( uc($value) eq "ON"){
|
if( uc($value) eq "ON"){
|
||||||
if ($hash->{ASYNC}) {
|
if ($hash->{ASYNC}) {
|
||||||
eval {
|
eval {
|
||||||
OWX_ASYNC_Schedule( $hash, PT_THREAD(\&OWXLCD_PT_SetFunction), $hash, "blkon", 0 );
|
OWX_ASYNC_Schedule( $hash, OWXLCD_PT_SetFunction($hash, "blkon", 0) );
|
||||||
};
|
};
|
||||||
return GP_Catch($@) if $@;
|
return GP_Catch($@) if $@;
|
||||||
} else {
|
} else {
|
||||||
@ -519,7 +551,7 @@ sub OWLCD_Set($@) {
|
|||||||
}elsif( uc($value) eq "OFF" ){
|
}elsif( uc($value) eq "OFF" ){
|
||||||
if ($hash->{ASYNC}) {
|
if ($hash->{ASYNC}) {
|
||||||
eval {
|
eval {
|
||||||
OWX_ASYNC_Schedule( $hash, PT_THREAD(\&OWXLCD_PT_SetFunction), $hash, "blkoff", 0 );
|
OWX_ASYNC_Schedule( $hash, OWXLCD_PT_SetFunction($hash, "blkoff", 0) );
|
||||||
};
|
};
|
||||||
return GP_Catch($@) if $@;
|
return GP_Catch($@) if $@;
|
||||||
} else {
|
} else {
|
||||||
@ -535,9 +567,9 @@ sub OWLCD_Set($@) {
|
|||||||
if($key eq "reset") {
|
if($key eq "reset") {
|
||||||
if ($hash->{ASYNC}) {
|
if ($hash->{ASYNC}) {
|
||||||
eval {
|
eval {
|
||||||
OWX_ASYNC_Schedule( $hash, PT_THREAD(\&OWXLCD_PT_SetFunction), $hash, "reset", 0 );
|
OWX_ASYNC_Schedule( $hash, OWXLCD_PT_SetFunction($hash, "reset", 0) );
|
||||||
OWX_ASYNC_Schedule( $hash, PT_THREAD(\&OWXLCD_PT_SetIcon), $hash, 0, 0 );
|
OWX_ASYNC_Schedule( $hash, OWXLCD_PT_SetIcon($hash, 0, 0) );
|
||||||
OWX_ASYNC_Schedule( $hash, PT_THREAD(\&OWXLCD_PT_SetFunction), $hash, "gpio", 15 );
|
OWX_ASYNC_Schedule( $hash, OWXLCD_PT_SetFunction($hash, "gpio", 15) );
|
||||||
};
|
};
|
||||||
return GP_Catch($@) if $@;
|
return GP_Catch($@) if $@;
|
||||||
} else {
|
} else {
|
||||||
@ -557,7 +589,7 @@ sub OWLCD_Set($@) {
|
|||||||
if( uc($value) eq "OFF" ){
|
if( uc($value) eq "OFF" ){
|
||||||
if ($hash->{ASYNC}) {
|
if ($hash->{ASYNC}) {
|
||||||
eval {
|
eval {
|
||||||
OWX_ASYNC_Schedule( $hash, PT_THREAD(\&OWXLCD_PT_SetIcon), $hash, 16, 0 );
|
OWX_ASYNC_Schedule( $hash, OWXLCD_PT_SetIcon($hash, 16, 0) );
|
||||||
};
|
};
|
||||||
return GP_Catch($@) if $@;
|
return GP_Catch($@) if $@;
|
||||||
} else {
|
} else {
|
||||||
@ -566,7 +598,7 @@ sub OWLCD_Set($@) {
|
|||||||
}elsif( uc($value) eq "BLINK" ){
|
}elsif( uc($value) eq "BLINK" ){
|
||||||
if ($hash->{ASYNC}) {
|
if ($hash->{ASYNC}) {
|
||||||
eval {
|
eval {
|
||||||
OWX_ASYNC_Schedule( $hash, PT_THREAD(\&OWXLCD_PT_SetIcon), $hash, 16, 6 );
|
OWX_ASYNC_Schedule( $hash, OWXLCD_PT_SetIcon($hash, 16, 6) );
|
||||||
};
|
};
|
||||||
return GP_Catch($@) if $@;
|
return GP_Catch($@) if $@;
|
||||||
} else {
|
} else {
|
||||||
@ -575,7 +607,7 @@ sub OWLCD_Set($@) {
|
|||||||
}elsif( ((int($value) > 0) && (int($value) < 6)) ){
|
}elsif( ((int($value) > 0) && (int($value) < 6)) ){
|
||||||
if ($hash->{ASYNC}) {
|
if ($hash->{ASYNC}) {
|
||||||
eval {
|
eval {
|
||||||
OWX_ASYNC_Schedule( $hash, PT_THREAD(\&OWXLCD_PT_SetIcon), $hash, 16, int($value) );
|
OWX_ASYNC_Schedule( $hash, OWXLCD_PT_SetIcon($hash, 16, int($value)) );
|
||||||
};
|
};
|
||||||
return GP_Catch($@) if $@;
|
return GP_Catch($@) if $@;
|
||||||
} else {
|
} else {
|
||||||
@ -588,7 +620,7 @@ sub OWLCD_Set($@) {
|
|||||||
if( uc($value) eq "OFF"){
|
if( uc($value) eq "OFF"){
|
||||||
if ($hash->{ASYNC}) {
|
if ($hash->{ASYNC}) {
|
||||||
eval {
|
eval {
|
||||||
OWX_ASYNC_Schedule( $hash, PT_THREAD(\&OWXLCD_PT_SetIcon), $hash, $icon, 0 );
|
OWX_ASYNC_Schedule( $hash, OWXLCD_PT_SetIcon($hash, $icon, 0) );
|
||||||
};
|
};
|
||||||
return GP_Catch($@) if $@;
|
return GP_Catch($@) if $@;
|
||||||
} else {
|
} else {
|
||||||
@ -597,7 +629,7 @@ sub OWLCD_Set($@) {
|
|||||||
}elsif( uc($value) eq "ON" ){
|
}elsif( uc($value) eq "ON" ){
|
||||||
if ($hash->{ASYNC}) {
|
if ($hash->{ASYNC}) {
|
||||||
eval {
|
eval {
|
||||||
OWX_ASYNC_Schedule( $hash, PT_THREAD(\&OWXLCD_PT_SetIcon), $hash, $icon, 1 );
|
OWX_ASYNC_Schedule( $hash, OWXLCD_PT_SetIcon($hash, $icon, 1) );
|
||||||
};
|
};
|
||||||
return GP_Catch($@) if $@;
|
return GP_Catch($@) if $@;
|
||||||
} else {
|
} else {
|
||||||
@ -606,7 +638,7 @@ sub OWLCD_Set($@) {
|
|||||||
}elsif( uc($value) eq "BLINK" ){
|
}elsif( uc($value) eq "BLINK" ){
|
||||||
if ($hash->{ASYNC}) {
|
if ($hash->{ASYNC}) {
|
||||||
eval {
|
eval {
|
||||||
OWX_ASYNC_Schedule( $hash, PT_THREAD(\&OWXLCD_PT_SetIcon), $hash, $icon, 2 );
|
OWX_ASYNC_Schedule( $hash, &OWXLCD_PT_SetIcon($hash, $icon, 2) );
|
||||||
};
|
};
|
||||||
return GP_Catch($@) if $@;
|
return GP_Catch($@) if $@;
|
||||||
} else {
|
} else {
|
||||||
@ -629,7 +661,7 @@ sub OWLCD_Set($@) {
|
|||||||
#-- check value and write to device
|
#-- check value and write to device
|
||||||
if ($hash->{ASYNC}) {
|
if ($hash->{ASYNC}) {
|
||||||
eval {
|
eval {
|
||||||
OWX_ASYNC_Schedule( $hash, PT_THREAD(\&OWXLCD_PT_SetLine), $hash, $line, $value );
|
OWX_ASYNC_Schedule( $hash, OWXLCD_PT_SetLine($hash, $line, $value) );
|
||||||
};
|
};
|
||||||
return GP_Catch($@) if $@;
|
return GP_Catch($@) if $@;
|
||||||
} else {
|
} else {
|
||||||
@ -648,7 +680,7 @@ sub OWLCD_Set($@) {
|
|||||||
Log3 $name,1,"Calling SetMemory with page $line";
|
Log3 $name,1,"Calling SetMemory with page $line";
|
||||||
if ($hash->{ASYNC}) {
|
if ($hash->{ASYNC}) {
|
||||||
eval {
|
eval {
|
||||||
OWX_ASYNC_Schedule( $hash, PT_THREAD(\&OWXLCD_PT_SetMemory), $hash, $line, $value );
|
OWX_ASYNC_Schedule( $hash, OWXLCD_PT_SetMemory($hash, $line, $value) );
|
||||||
};
|
};
|
||||||
return GP_Catch($@) if $@;
|
return GP_Catch($@) if $@;
|
||||||
} else {
|
} else {
|
||||||
@ -662,7 +694,7 @@ sub OWLCD_Set($@) {
|
|||||||
if(lc($value) eq "beep") {
|
if(lc($value) eq "beep") {
|
||||||
if ($hash->{ASYNC}) {
|
if ($hash->{ASYNC}) {
|
||||||
eval {
|
eval {
|
||||||
OWX_ASYNC_Schedule( $hash, PT_THREAD(\&OWXLCD_PT_SetFunction), $hash, "gpio", 14 );
|
OWX_ASYNC_Schedule( $hash, OWXLCD_PT_SetFunction($hash, "gpio", 14) );
|
||||||
};
|
};
|
||||||
return GP_Catch($@) if $@;
|
return GP_Catch($@) if $@;
|
||||||
} else {
|
} else {
|
||||||
@ -672,7 +704,7 @@ sub OWLCD_Set($@) {
|
|||||||
}elsif(lc($value) eq "red") {
|
}elsif(lc($value) eq "red") {
|
||||||
if ($hash->{ASYNC}) {
|
if ($hash->{ASYNC}) {
|
||||||
eval {
|
eval {
|
||||||
OWX_ASYNC_Schedule( $hash, PT_THREAD(\&OWXLCD_PT_SetFunction), $hash, "gpio", 13 );
|
OWX_ASYNC_Schedule( $hash, OWXLCD_PT_SetFunction($hash, "gpio", 13) );
|
||||||
};
|
};
|
||||||
return GP_Catch($@) if $@;
|
return GP_Catch($@) if $@;
|
||||||
} else {
|
} else {
|
||||||
@ -682,7 +714,7 @@ sub OWLCD_Set($@) {
|
|||||||
}elsif(lc($value) eq "yellow") {
|
}elsif(lc($value) eq "yellow") {
|
||||||
if ($hash->{ASYNC}) {
|
if ($hash->{ASYNC}) {
|
||||||
eval {
|
eval {
|
||||||
OWX_ASYNC_Schedule( $hash, PT_THREAD(\&OWXLCD_PT_SetFunction), $hash, "gpio", 11 );
|
OWX_ASYNC_Schedule( $hash, OWXLCD_PT_SetFunction($hash, "gpio", 11) );
|
||||||
};
|
};
|
||||||
return GP_Catch($@) if $@;
|
return GP_Catch($@) if $@;
|
||||||
} else {
|
} else {
|
||||||
@ -692,7 +724,7 @@ sub OWLCD_Set($@) {
|
|||||||
}elsif( (lc($value) eq "off") || (lc($value) eq "none") ) {
|
}elsif( (lc($value) eq "off") || (lc($value) eq "none") ) {
|
||||||
if ($hash->{ASYNC}) {
|
if ($hash->{ASYNC}) {
|
||||||
eval {
|
eval {
|
||||||
OWX_ASYNC_Schedule( $hash, PT_THREAD(\&OWXLCD_PT_SetFunction), $hash, "gpio", 15 );
|
OWX_ASYNC_Schedule( $hash, OWXLCD_PT_SetFunction($hash, "gpio", 15) );
|
||||||
};
|
};
|
||||||
return GP_Catch($@) if $@;
|
return GP_Catch($@) if $@;
|
||||||
} else {
|
} else {
|
||||||
@ -708,10 +740,10 @@ sub OWLCD_Set($@) {
|
|||||||
if($key eq "test") {
|
if($key eq "test") {
|
||||||
if ($hash->{ASYNC}) {
|
if ($hash->{ASYNC}) {
|
||||||
eval {
|
eval {
|
||||||
OWX_ASYNC_Schedule( $hash, PT_THREAD(\&OWXLCD_PT_SetLine), $hash,0,"Hallo Welt");
|
OWX_ASYNC_Schedule( $hash, OWXLCD_PT_SetLine($hash,0,"Hallo Welt"));
|
||||||
OWX_ASYNC_Schedule( $hash, PT_THREAD(\&OWXLCD_PT_SetLine), $hash,1,"Mary had a big lamb");
|
OWX_ASYNC_Schedule( $hash, OWXLCD_PT_SetLine($hash,1,"Mary had a big lamb"));
|
||||||
OWX_ASYNC_Schedule( $hash, PT_THREAD(\&OWXLCD_PT_SetLine), $hash,2,"Solar 4.322 kW ");
|
OWX_ASYNC_Schedule( $hash, OWXLCD_PT_SetLine($hash,2,"Solar 4.322 kW "));
|
||||||
OWX_ASYNC_Schedule( $hash, PT_THREAD(\&OWXLCD_PT_SetLine), $hash,3,"\x5B\x5C\x5E\x7B\x7C\x7E\xBE");
|
OWX_ASYNC_Schedule( $hash, OWXLCD_PT_SetLine($hash,3,"\x5B\x5C\x5E\x7B\x7C\x7E\xBE"));
|
||||||
};
|
};
|
||||||
return GP_Catch($@) if $@;
|
return GP_Catch($@) if $@;
|
||||||
} else {
|
} else {
|
||||||
@ -801,16 +833,15 @@ sub OWXLCD_Byte($$$) {
|
|||||||
|
|
||||||
sub OWXLCD_PT_Byte($$$) {
|
sub OWXLCD_PT_Byte($$$) {
|
||||||
|
|
||||||
my ($thread,$hash,$cmd,$byte) = @_;
|
my ($hash,$cmd,$byte) = @_;
|
||||||
|
|
||||||
|
return PT_THREAD(sub {
|
||||||
|
my ($thread) = @_;
|
||||||
my ($select);
|
my ($select);
|
||||||
|
|
||||||
#-- ID of the device
|
#-- ID of the device
|
||||||
my $owx_dev = $hash->{ROM_ID};
|
my $owx_dev = $hash->{ROM_ID};
|
||||||
|
|
||||||
#-- hash of the busmaster
|
#-- hash of the busmaster
|
||||||
my $master = $hash->{IODev};
|
my $master = $hash->{IODev};
|
||||||
|
|
||||||
my ($i,$j,$k);
|
my ($i,$j,$k);
|
||||||
|
|
||||||
PT_BEGIN($thread);
|
PT_BEGIN($thread);
|
||||||
@ -825,18 +856,17 @@ sub OWXLCD_PT_Byte($$$) {
|
|||||||
$select = sprintf("\x12%c",$byte);
|
$select = sprintf("\x12%c",$byte);
|
||||||
#=============== wrong value requested ===============================
|
#=============== wrong value requested ===============================
|
||||||
} else {
|
} else {
|
||||||
return "OWXLCD: Wrong byte write attempt";
|
die "OWXLCD: Wrong byte write attempt";
|
||||||
}
|
}
|
||||||
|
|
||||||
#"byte"
|
#"byte"
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, $select, 0 )) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,$select,0);
|
||||||
PT_EXIT("OWLCD: Device $owx_dev not accessible for writing a byte");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL($thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
unless ($thread->{ExecuteResponse}->{success}) {
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
PT_EXIT("OWLCD: Device $owx_dev error writing a byte");
|
|
||||||
}
|
|
||||||
PT_END;
|
PT_END;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
########################################################################################
|
########################################################################################
|
||||||
@ -913,8 +943,11 @@ sub OWXLCD_Get($$) {
|
|||||||
|
|
||||||
sub OWXLCD_PT_Get($$) {
|
sub OWXLCD_PT_Get($$) {
|
||||||
|
|
||||||
my ($thread,$hash,$cmd) = @_;
|
my ($hash,$cmd) = @_;
|
||||||
|
|
||||||
|
return PT_THREAD(sub {
|
||||||
|
|
||||||
|
my ($thread) = @_;
|
||||||
my ($select);
|
my ($select);
|
||||||
|
|
||||||
#-- ID of the device
|
#-- ID of the device
|
||||||
@ -942,29 +975,26 @@ sub OWXLCD_PT_Get($$) {
|
|||||||
$select = "\x41";
|
$select = "\x41";
|
||||||
$thread->{len} = 16;
|
$thread->{len} = 16;
|
||||||
} else {
|
} else {
|
||||||
PT_EXIT("OWXLCD: Wrong get attempt");
|
die("OWXLCD: Wrong get attempt");
|
||||||
}
|
}
|
||||||
#"get.prepare"
|
#"get.prepare"
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, $select, 0 )) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,$select,0);
|
||||||
PT_EXIT("OWLCD: Device $owx_dev not accessible for reading");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL($thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
unless ($thread->{ExecuteResponse}->{success}) {
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
PT_EXIT("OWLCD: Device $owx_dev error writing a byte");
|
|
||||||
}
|
|
||||||
|
|
||||||
#-- issue the read scratchpad command \xBE
|
#-- issue the read scratchpad command \xBE
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, "\xBE", $thread->{len} )) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,"\xBE", $thread->{len});
|
||||||
PT_EXIT("OWLCD: Device $owx_dev not accessible for reading in 2nd step");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL($thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
my $response = $thread->{ExecuteResponse};
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
unless ($response->{success}) {
|
|
||||||
PT_EXIT("OWLCD: Device $owx_dev error writing a byte");
|
OWXLCD_BinValues($hash, "get.".$cmd, 1, 1, $owx_dev, "\xBE", $thread->{len}, $thread->{pt_execute}->PT_RETVAL());
|
||||||
}
|
|
||||||
OWXLCD_BinValues($hash, "get.".$cmd, 1, 1, $owx_dev, $response->{writedata}, $response->{numread}, $response->{readdata});
|
|
||||||
|
|
||||||
PT_END;
|
PT_END;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
########################################################################################
|
########################################################################################
|
||||||
@ -1033,8 +1063,11 @@ sub OWXLCD_GetMemory($$) {
|
|||||||
|
|
||||||
sub OWXLCD_PT_GetMemory($$) {
|
sub OWXLCD_PT_GetMemory($$) {
|
||||||
|
|
||||||
my ($thread,$hash,$page) = @_;
|
my ($hash,$page) = @_;
|
||||||
|
|
||||||
|
return PT_THREAD(sub {
|
||||||
|
|
||||||
|
my ($thread) = @_;
|
||||||
my ($select);
|
my ($select);
|
||||||
|
|
||||||
#-- ID of the device
|
#-- ID of the device
|
||||||
@ -1048,34 +1081,32 @@ sub OWXLCD_PT_GetMemory($$) {
|
|||||||
#Log 1," page read is ".$page;
|
#Log 1," page read is ".$page;
|
||||||
$select = sprintf("\4E%c\x10\x37",$page);
|
$select = sprintf("\4E%c\x10\x37",$page);
|
||||||
#"prepare"
|
#"prepare"
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, $select, 0 )) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,$select,0);
|
||||||
PT_EXIT("OWLCD: Device $owx_dev not accessible for reading memory");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL($thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
unless ($thread->{ExecuteResponse}->{success}) {
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
PT_EXIT("OWLCD: Device $owx_dev error reading memory");
|
|
||||||
}
|
|
||||||
|
|
||||||
#-- sleeping for some time
|
#-- sleeping for some time
|
||||||
#select(undef,undef,undef,0.5);
|
$thread->{ExecuteTime} = gettimeofday()+0.5;
|
||||||
|
PT_YIELD_UNTIL(gettimeofday() >= $thread->{ExecuteTime});
|
||||||
|
delete $thread->{ExecuteTime};
|
||||||
|
|
||||||
#-- issue the match ROM command \x55 and the read scratchpad command \xBE
|
#-- issue the match ROM command \x55 and the read scratchpad command \xBE
|
||||||
$select = "\xBE";
|
$thread->{'select'} = "\xBE";
|
||||||
#"get.memory.$page"
|
#"get.memory.$page"
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, $select,16 )) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,$thread->{'select'},16);
|
||||||
PT_EXIT("OWLCD: Device $owx_dev not accessible for reading in 2nd step");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL($thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
my $response = $thread->{ExecuteResponse};
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
unless ($response->{success}) {
|
|
||||||
PT_EXIT("OWLCD: Device $owx_dev error reading memory in 2nd step");
|
|
||||||
}
|
|
||||||
|
|
||||||
OWXLCD_BinValues($hash, "get.memory.$page", 1, 1, $owx_dev, $response->{writedata}, $response->{numread}, $response->{readdata});
|
OWXLCD_BinValues($hash, "get.memory.$page", 1, 1, $owx_dev, $thread->{'select'}, 16, $thread->{pt_execute}->PT_RETVAL());
|
||||||
#-- process results (10 bytes or more have been sent)
|
#-- process results (10 bytes or more have been sent)
|
||||||
#$res2 = substr($res,11,16);
|
#$res2 = substr($res,11,16);
|
||||||
#return $res2;
|
#return $res2;
|
||||||
PT_END;
|
PT_END;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
########################################################################################
|
########################################################################################
|
||||||
@ -1111,11 +1142,11 @@ sub OWXLCD_InitializeDevice($) {
|
|||||||
|
|
||||||
if ($hash->{ASYNC}) {
|
if ($hash->{ASYNC}) {
|
||||||
eval {
|
eval {
|
||||||
OWX_ASYNC_Schedule($hash,PT_THREAD(\&OWXLCD_PT_Byte),$hash,"register",38);
|
OWX_ASYNC_Schedule($hash,OWXLCD_PT_Byte($hash,"register",38));
|
||||||
OWX_ASYNC_Schedule($hash,PT_THREAD(\&OWXLCD_PT_Byte),$hash,"register", 9);
|
OWX_ASYNC_Schedule($hash,OWXLCD_PT_Byte($hash,"register", 9));
|
||||||
OWX_ASYNC_Schedule($hash,PT_THREAD(\&OWXLCD_PT_Byte),$hash,"register",32);
|
OWX_ASYNC_Schedule($hash,OWXLCD_PT_Byte($hash,"register",32));
|
||||||
OWX_ASYNC_Schedule($hash,PT_THREAD(\&OWXLCD_PT_Byte),$hash,"register",12);
|
OWX_ASYNC_Schedule($hash,OWXLCD_PT_Byte($hash,"register",12));
|
||||||
OWX_ASYNC_Schedule($hash,PT_THREAD(\&OWXLCD_PT_Byte),$hash,"register", 1);
|
OWX_ASYNC_Schedule($hash,OWXLCD_PT_Byte($hash,"register", 1));
|
||||||
};
|
};
|
||||||
return GP_Catch($@) if $@;
|
return GP_Catch($@) if $@;
|
||||||
} else {
|
} else {
|
||||||
@ -1217,8 +1248,11 @@ sub OWXLCD_SetFunction($$$) {
|
|||||||
|
|
||||||
sub OWXLCD_PT_SetFunction($$$) {
|
sub OWXLCD_PT_SetFunction($$$) {
|
||||||
|
|
||||||
my ($thread,$hash,$cmd,$value) = @_;
|
my ($hash,$cmd,$value) = @_;
|
||||||
|
|
||||||
|
return PT_THREAD(sub {
|
||||||
|
|
||||||
|
my ($thread) = @_;
|
||||||
my ($select);
|
my ($select);
|
||||||
|
|
||||||
#-- ID of the device, hash of the busmaster
|
#-- ID of the device, hash of the busmaster
|
||||||
@ -1259,15 +1293,14 @@ sub OWXLCD_PT_SetFunction($$$) {
|
|||||||
return "OWXLCD: Wrong function selected";
|
return "OWXLCD: Wrong function selected";
|
||||||
}
|
}
|
||||||
#"set.function"
|
#"set.function"
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, $select, 0 )) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,$select,0);
|
||||||
PT_EXIT("OWLCD: Device $owx_dev not accessible for writing");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL($thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
unless ($thread->{ExecuteResponse}->{success}) {
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
PT_EXIT("OWLCD: Device $owx_dev error writing");
|
|
||||||
}
|
|
||||||
|
|
||||||
PT_END;
|
PT_END;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
########################################################################################
|
########################################################################################
|
||||||
@ -1380,8 +1413,11 @@ sub OWXLCD_SetIcon($$$) {
|
|||||||
########################################################################################
|
########################################################################################
|
||||||
|
|
||||||
sub OWXLCD_PT_SetIcon($$$) {
|
sub OWXLCD_PT_SetIcon($$$) {
|
||||||
my ($thread,$hash,$icon,$value) = @_;
|
my ($hash,$icon,$value) = @_;
|
||||||
|
|
||||||
|
return PT_THREAD(sub {
|
||||||
|
|
||||||
|
my ($thread) = @_;
|
||||||
my ($i,$data,$select, $res);
|
my ($i,$data,$select, $res);
|
||||||
|
|
||||||
#-- ID of the device, hash of the busmaster
|
#-- ID of the device, hash of the busmaster
|
||||||
@ -1398,37 +1434,31 @@ sub OWXLCD_PT_SetIcon($$$) {
|
|||||||
#-- 4 bit data size, RE => 1, blink Enable = \x26
|
#-- 4 bit data size, RE => 1, blink Enable = \x26
|
||||||
$select = "\x10\x26";
|
$select = "\x10\x26";
|
||||||
#"set.icon.1"
|
#"set.icon.1"
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, $select, 0 )) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,$select,0);
|
||||||
PT_EXIT("Device $owx_dev not accessible for writing");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL($thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
unless ($thread->{ExecuteResponse}->{success}) {
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
PT_EXIT("OWLCD: Device $owx_dev error writing");
|
|
||||||
}
|
|
||||||
|
|
||||||
#-- SEGRAM addres to 0 = \x40,
|
#-- SEGRAM addres to 0 = \x40,
|
||||||
$select = "\x10\x40";
|
$select = "\x10\x40";
|
||||||
#-- write 16 zeros to scratchpad
|
#-- write 16 zeros to scratchpad
|
||||||
$select .= "\x4E\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
|
$select .= "\x4E\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
|
||||||
#"set.icon.2"
|
#"set.icon.2"
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, $select, 0 )) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,$select,0);
|
||||||
PT_EXIT("Device $owx_dev not accessible for writing");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL($thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
unless ($thread->{ExecuteResponse}->{success}) {
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
PT_EXIT("OWLCD: Device $owx_dev error writing");
|
|
||||||
}
|
|
||||||
|
|
||||||
#-- issue the copy scratchpad to LCD command \x48
|
#-- issue the copy scratchpad to LCD command \x48
|
||||||
$select="\x48";
|
$select="\x48";
|
||||||
#"set.icon.3"
|
#"set.icon.3"
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, $select, 0 )) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,$select,0);
|
||||||
PT_EXIT("Device $owx_dev not accessible for writing");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL($thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
unless ($thread->{ExecuteResponse}->{success}) {
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
PT_EXIT("OWLCD: Device $owx_dev error writing");
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
#-- determine data value
|
#-- determine data value
|
||||||
if( int($icon) != 16 ){
|
if( int($icon) != 16 ){
|
||||||
@ -1439,7 +1469,7 @@ sub OWXLCD_PT_SetIcon($$$) {
|
|||||||
} elsif ( $value == 2) {
|
} elsif ( $value == 2) {
|
||||||
$data = 80;
|
$data = 80;
|
||||||
} else {
|
} else {
|
||||||
PT_EXIT("OWXLCD: Wrong data value $value for icon $icon");
|
die("OWXLCD: Wrong data value $value for icon $icon");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if( $value == 0 ){
|
if( $value == 0 ){
|
||||||
@ -1457,58 +1487,51 @@ sub OWXLCD_PT_SetIcon($$$) {
|
|||||||
} elsif ( $value == 6) {
|
} elsif ( $value == 6) {
|
||||||
$data = 80;
|
$data = 80;
|
||||||
} else {
|
} else {
|
||||||
PT_EXIT("OWXLCD: Wrong data value $value for icon $icon");
|
die("OWXLCD: Wrong data value $value for icon $icon");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#-- 4 bit data size, RE => 1, blink Enable = \x26
|
#-- 4 bit data size, RE => 1, blink Enable = \x26
|
||||||
$select = "\x10\x26";
|
$select = "\x10\x26";
|
||||||
#"set.icon.4"
|
#"set.icon.4"
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, $select, 0 )) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,$select,0);
|
||||||
PT_EXIT("Device $owx_dev not accessible for writing");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL($thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
unless ($thread->{ExecuteResponse}->{success}) {
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
PT_EXIT("OWLCD: Device $owx_dev error writing");
|
|
||||||
}
|
|
||||||
|
|
||||||
#-- SEGRAM addres to 0 = \x40 + icon address
|
#-- SEGRAM addres to 0 = \x40 + icon address
|
||||||
$select = sprintf("\x10%c",63+$icon);
|
$select = sprintf("\x10%c",63+$icon);
|
||||||
#"set.icon.5"
|
#"set.icon.5"
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, $select, 0 )) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,$select,0);
|
||||||
PT_EXIT("Device $owx_dev not accessible for writing");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL($thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
unless ($thread->{ExecuteResponse}->{success}) {
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
PT_EXIT("OWLCD: Device $owx_dev error writing");
|
|
||||||
}
|
|
||||||
|
|
||||||
#-- data
|
#-- data
|
||||||
$select = sprintf("\x12%c",$data);
|
$select = sprintf("\x12%c",$data);
|
||||||
#"set.icon.6"
|
#"set.icon.6"
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, $select, 0 )) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,$select,0);
|
||||||
PT_EXIT("Device $owx_dev not accessible for writing");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL($thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
unless ($thread->{ExecuteResponse}->{success}) {
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
PT_EXIT("OWLCD: Device $owx_dev error writing");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#-- return to normal state
|
#-- return to normal state
|
||||||
$select = "\x10\x20";
|
$select = "\x10\x20";
|
||||||
#"set.icon.7"
|
#"set.icon.7"
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, $select, 0 )) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,$select,0);
|
||||||
PT_EXIT("Device $owx_dev not accessible for writing");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL($thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
unless ($thread->{ExecuteResponse}->{success}) {
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
PT_EXIT("OWLCD: Device $owx_dev error writing");
|
|
||||||
}
|
|
||||||
#-- or else
|
#-- or else
|
||||||
} else {
|
} else {
|
||||||
PT_EXIT("OWXLCD: Wrong LCD controller type");
|
die("OWXLCD: Wrong LCD controller type");
|
||||||
}
|
}
|
||||||
PT_END;
|
PT_END;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
########################################################################################
|
########################################################################################
|
||||||
@ -1609,8 +1632,11 @@ sub OWXLCD_SetLine($$$) {
|
|||||||
|
|
||||||
sub OWXLCD_PT_SetLine($$$) {
|
sub OWXLCD_PT_SetLine($$$) {
|
||||||
|
|
||||||
my ($thread,$hash,$line,$msg) = @_;
|
my ($hash,$line,$msg) = @_;
|
||||||
|
|
||||||
|
return PT_THREAD(sub {
|
||||||
|
|
||||||
|
my ($thread) = @_;
|
||||||
my ($select, $i, $msgA, $msgB);
|
my ($select, $i, $msgA, $msgB);
|
||||||
|
|
||||||
#-- ID of the device, hash of the busmaster
|
#-- ID of the device, hash of the busmaster
|
||||||
@ -1655,24 +1681,20 @@ sub OWXLCD_PT_SetLine($$$) {
|
|||||||
# followed by LCD page address and the text
|
# followed by LCD page address and the text
|
||||||
$select=sprintf("\x4E%c",$lcdpage[$line]).$msgA;
|
$select=sprintf("\x4E%c",$lcdpage[$line]).$msgA;
|
||||||
#"set.line.1"
|
#"set.line.1"
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, $select, 0 )) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,$select,0);
|
||||||
PT_EXIT("Device $owx_dev not accessible for writing");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL($thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
unless ($thread->{ExecuteResponse}->{success}) {
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
PT_EXIT("OWLCD: Device $owx_dev error writing");
|
|
||||||
}
|
|
||||||
|
|
||||||
#-- issue the copy scratchpad to LCD command \x48
|
#-- issue the copy scratchpad to LCD command \x48
|
||||||
$select="\x48";
|
$select="\x48";
|
||||||
#"set.line.2"
|
#"set.line.2"
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, $select, 0 )) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,$select,0);
|
||||||
PT_EXIT("Device $owx_dev not accessible for writing");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL($thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
unless ($thread->{ExecuteResponse}->{success}) {
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
PT_EXIT("OWLCD: Device $owx_dev error writing");
|
|
||||||
}
|
|
||||||
|
|
||||||
#-- if second string available:
|
#-- if second string available:
|
||||||
if( defined($thread->{msgB}) ) {
|
if( defined($thread->{msgB}) ) {
|
||||||
@ -1681,26 +1703,23 @@ sub OWXLCD_PT_SetLine($$$) {
|
|||||||
# followed by LCD page address and the text
|
# followed by LCD page address and the text
|
||||||
$select=sprintf("\x4E%c",$lcdpage[$line]+16).$thread->{msgB};
|
$select=sprintf("\x4E%c",$lcdpage[$line]+16).$thread->{msgB};
|
||||||
#"set.line.3"
|
#"set.line.3"
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, $select, 0 )) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,$select,0);
|
||||||
PT_EXIT("Device $owx_dev not accessible for writing");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL($thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
unless ($thread->{ExecuteResponse}->{success}) {
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
PT_EXIT("OWLCD: Device $owx_dev error writing");
|
|
||||||
}
|
|
||||||
|
|
||||||
#-- issue the copy scratchpad to LCD command \x48
|
#-- issue the copy scratchpad to LCD command \x48
|
||||||
$select="\x48";
|
$select="\x48";
|
||||||
#"set.line.4"
|
#"set.line.4"
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, $select, 0 )) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,$select,0);
|
||||||
PT_EXIT("Device $owx_dev not accessible for writing");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL($thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
unless ($thread->{ExecuteResponse}->{success}) {
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
PT_EXIT("OWLCD: Device $owx_dev error writing");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
PT_END;
|
PT_END;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
########################################################################################
|
########################################################################################
|
||||||
@ -1794,8 +1813,11 @@ sub OWXLCD_SetMemory($$$) {
|
|||||||
|
|
||||||
sub OWXLCD_PT_SetMemory($$$) {
|
sub OWXLCD_PT_SetMemory($$$) {
|
||||||
|
|
||||||
my ($thread,$hash,$page,$msg) = @_;
|
my ($hash,$page,$msg) = @_;
|
||||||
|
|
||||||
|
return PT_THREAD(sub {
|
||||||
|
|
||||||
|
my ($thread,$hash,$page,$msg) = @_;
|
||||||
my ($select, $i, $msgA);
|
my ($select, $i, $msgA);
|
||||||
|
|
||||||
#-- ID of the device, hash of the busmaster
|
#-- ID of the device, hash of the busmaster
|
||||||
@ -1818,25 +1840,22 @@ sub OWXLCD_PT_SetMemory($$$) {
|
|||||||
#Log 1," page written is ".$page;
|
#Log 1," page written is ".$page;
|
||||||
$select=sprintf("\x4E\%c",$page).$msgA;
|
$select=sprintf("\x4E\%c",$page).$msgA;
|
||||||
#"set.memory.page"
|
#"set.memory.page"
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, $select, 0 )) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,$select,0);
|
||||||
PT_EXIT("Device $owx_dev not accessible for writing");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL($thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
unless ($thread->{ExecuteResponse}->{success}) {
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
PT_EXIT("OWLCD: Device $owx_dev error writing");
|
|
||||||
}
|
|
||||||
|
|
||||||
#-- issue the copy scratchpad to EEPROM command \x39
|
#-- issue the copy scratchpad to EEPROM command \x39
|
||||||
$select = "\x39";
|
$select = "\x39";
|
||||||
#"set.memory.copy"
|
#"set.memory.copy"
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, $select, 0 )) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,$select,0);
|
||||||
PT_EXIT("Device $owx_dev not accessible for writing");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL($thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
unless ($thread->{ExecuteResponse}->{success}) {
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
PT_EXIT("OWLCD: Device $owx_dev error writing");
|
|
||||||
}
|
|
||||||
PT_END;
|
PT_END;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
sub OWXLCD_BinValues($$$$$$$$) {
|
sub OWXLCD_BinValues($$$$$$$$) {
|
||||||
|
@ -82,7 +82,7 @@ no warnings 'deprecated';
|
|||||||
|
|
||||||
sub Log($$);
|
sub Log($$);
|
||||||
|
|
||||||
my $owx_version="5.15";
|
my $owx_version="5.16";
|
||||||
#-- flexible channel name
|
#-- flexible channel name
|
||||||
my $owg_channel;
|
my $owg_channel;
|
||||||
|
|
||||||
@ -130,6 +130,8 @@ sub OWMULTI_Initialize ($) {
|
|||||||
$hash->{UndefFn} = "OWMULTI_Undef";
|
$hash->{UndefFn} = "OWMULTI_Undef";
|
||||||
$hash->{GetFn} = "OWMULTI_Get";
|
$hash->{GetFn} = "OWMULTI_Get";
|
||||||
$hash->{SetFn} = "OWMULTI_Set";
|
$hash->{SetFn} = "OWMULTI_Set";
|
||||||
|
$hash->{NotifyFn}= "OWMULTI_Notify";
|
||||||
|
$hash->{InitFn} = "OWMULTI_Init";
|
||||||
$hash->{AttrFn} = "OWMULTI_Attr";
|
$hash->{AttrFn} = "OWMULTI_Attr";
|
||||||
|
|
||||||
#tempOffset = a temperature offset added to the temperature reading for correction
|
#tempOffset = a temperature offset added to the temperature reading for correction
|
||||||
@ -182,6 +184,9 @@ sub OWMULTI_Attr(@) {
|
|||||||
AssignIoPort($hash,$value);
|
AssignIoPort($hash,$value);
|
||||||
if( defined($hash->{IODev}) ) {
|
if( defined($hash->{IODev}) ) {
|
||||||
$hash->{ASYNC} = $hash->{IODev}->{TYPE} eq "OWX_ASYNC" ? 1 : 0;
|
$hash->{ASYNC} = $hash->{IODev}->{TYPE} eq "OWX_ASYNC" ? 1 : 0;
|
||||||
|
if ($init_done) {
|
||||||
|
OWMULTI_Init($hash);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
last;
|
last;
|
||||||
};
|
};
|
||||||
@ -277,9 +282,29 @@ sub OWMULTI_Define ($$) {
|
|||||||
readingsSingleUpdate($hash,"state","defined",1);
|
readingsSingleUpdate($hash,"state","defined",1);
|
||||||
Log 3, "OWMULTI: Device $name defined.";
|
Log 3, "OWMULTI: Device $name defined.";
|
||||||
|
|
||||||
#-- Start timer for updates
|
$hash->{NOTIFYDEV} = "global";
|
||||||
InternalTimer(time()+10, "OWMULTI_GetValues", $hash, 0);
|
|
||||||
|
|
||||||
|
if ($init_done) {
|
||||||
|
OWMULTI_Init($hash);
|
||||||
|
}
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub OWMULTI_Notify ($$) {
|
||||||
|
my ($hash,$dev) = @_;
|
||||||
|
if( grep(m/^(INITIALIZED|REREADCFG)$/, @{$dev->{CHANGED}}) ) {
|
||||||
|
OWMULTI_Init($hash);
|
||||||
|
} elsif( grep(m/^SAVE$/, @{$dev->{CHANGED}}) ) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub OWMULTI_Init ($) {
|
||||||
|
my ($hash)=@_;
|
||||||
|
#-- Start timer for updates
|
||||||
|
RemoveInternalTimer($hash);
|
||||||
|
InternalTimer(gettimeofday()+10, "OWMULTI_GetValues", $hash, 0);
|
||||||
|
#--
|
||||||
|
readingsSingleUpdate($hash,"state","Initialized",1);
|
||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -445,6 +470,8 @@ sub OWMULTI_Get($@) {
|
|||||||
return "$name.id => $value";
|
return "$name.id => $value";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#-- hash of the busmaster
|
||||||
|
my $master = $hash->{IODev};
|
||||||
#-- Get other values according to interface type
|
#-- Get other values according to interface type
|
||||||
my $interface= $hash->{IODev}->{TYPE};
|
my $interface= $hash->{IODev}->{TYPE};
|
||||||
|
|
||||||
@ -452,11 +479,17 @@ sub OWMULTI_Get($@) {
|
|||||||
if($a[1] eq "present" ) {
|
if($a[1] eq "present" ) {
|
||||||
#-- OWX interface
|
#-- OWX interface
|
||||||
if( $interface =~ /^OWX/ ){
|
if( $interface =~ /^OWX/ ){
|
||||||
#-- hash of the busmaster
|
|
||||||
my $master = $hash->{IODev};
|
|
||||||
#-- asynchronous mode
|
#-- asynchronous mode
|
||||||
if( $hash->{ASYNC} ){
|
if( $hash->{ASYNC} ){
|
||||||
$value = OWX_ASYNC_Verify($master,$hash->{ROM_ID});
|
my ($task,$task_state);
|
||||||
|
eval {
|
||||||
|
$task = OWX_ASYNC_PT_Verify($hash);
|
||||||
|
OWX_ASYNC_Schedule($hash,$task);
|
||||||
|
$task_state = OWX_ASYNC_RunToCompletion($master,$task);
|
||||||
|
};
|
||||||
|
return GP_Catch($@) if $@;
|
||||||
|
return $task->PT_CAUSE() if ($task_state == PT_ERROR or $task_state == PT_CANCELED);
|
||||||
|
return "$name.present => ".ReadingsVal($name,"present","unknown");
|
||||||
} else {
|
} else {
|
||||||
$value = OWX_Verify($master,$hash->{ROM_ID});
|
$value = OWX_Verify($master,$hash->{ROM_ID});
|
||||||
}
|
}
|
||||||
@ -484,12 +517,13 @@ sub OWMULTI_Get($@) {
|
|||||||
#-- not different from getting all values ..
|
#-- not different from getting all values ..
|
||||||
$ret = OWXMULTI_GetValues($hash);
|
$ret = OWXMULTI_GetValues($hash);
|
||||||
}elsif( $interface eq "OWX_ASYNC"){
|
}elsif( $interface eq "OWX_ASYNC"){
|
||||||
#TODO use OWX_ASYNC_Schedule instead
|
my ($task,$task_state);
|
||||||
my $task = PT_THREAD(\&OWXMULTI_PT_GetValues);
|
|
||||||
eval {
|
eval {
|
||||||
while ($task->PT_SCHEDULE($hash)) { OWX_ASYNC_Poll($hash->{IODev}); };
|
$task = OWXMULTI_PT_GetValues($hash);
|
||||||
|
OWX_ASYNC_Schedule($hash,$task);
|
||||||
|
$task_state = OWX_ASYNC_RunToCompletion($master,$task);
|
||||||
};
|
};
|
||||||
$ret = ($@) ? GP_Catch($@) : $task->PT_RETVAL();
|
$ret = ($@) ? GP_Catch($@) : ($task_state == PT_ERROR or $task_state == PT_CANCELED) ? $task->PT_CAUSE() : $task->PT_RETVAL();
|
||||||
#-- OWFS interface not yet implemented
|
#-- OWFS interface not yet implemented
|
||||||
}elsif( $interface eq "OWServer" ){
|
}elsif( $interface eq "OWServer" ){
|
||||||
$ret = OWFSMULTI_GetValues($hash);
|
$ret = OWFSMULTI_GetValues($hash);
|
||||||
@ -558,7 +592,7 @@ sub OWMULTI_GetValues($) {
|
|||||||
}
|
}
|
||||||
}elsif( $interface eq "OWX_ASYNC" ){
|
}elsif( $interface eq "OWX_ASYNC" ){
|
||||||
eval {
|
eval {
|
||||||
OWX_ASYNC_Schedule( $hash, PT_THREAD(\&OWXMULTI_PT_GetValues),$hash );
|
OWX_ASYNC_Schedule( $hash, OWXMULTI_PT_GetValues($hash) );
|
||||||
};
|
};
|
||||||
$ret = GP_Catch($@) if $@;
|
$ret = GP_Catch($@) if $@;
|
||||||
}elsif( $interface eq "OWServer" ){
|
}elsif( $interface eq "OWServer" ){
|
||||||
@ -656,7 +690,7 @@ sub OWMULTI_Set($@) {
|
|||||||
$ret = OWXMULTI_SetValues($hash,@a);
|
$ret = OWXMULTI_SetValues($hash,@a);
|
||||||
}elsif( $interface eq "OWX_ASYNC" ){
|
}elsif( $interface eq "OWX_ASYNC" ){
|
||||||
eval {
|
eval {
|
||||||
OWX_ASYNC_Schedule( $hash, PT_THREAD(\&OWXMULTI_PT_SetValues),$hash,@a );
|
OWX_ASYNC_Schedule( $hash, OWXMULTI_PT_SetValues($hash,@a) );
|
||||||
};
|
};
|
||||||
$ret = GP_Catch($@) if $@;
|
$ret = GP_Catch($@) if $@;
|
||||||
#-- OWFS interface
|
#-- OWFS interface
|
||||||
@ -1013,7 +1047,11 @@ sub OWXMULTI_SetValues($@) {
|
|||||||
|
|
||||||
sub OWXMULTI_PT_GetValues($) {
|
sub OWXMULTI_PT_GetValues($) {
|
||||||
|
|
||||||
my ($thread,$hash) = @_;
|
my ($hash) = @_;
|
||||||
|
|
||||||
|
return PT_THREAD(sub {
|
||||||
|
|
||||||
|
my ($thread) = @_;
|
||||||
|
|
||||||
my ($i,$j,$k,$res,$ret,$response);
|
my ($i,$j,$k,$res,$ret,$response);
|
||||||
|
|
||||||
@ -1023,163 +1061,152 @@ sub OWXMULTI_PT_GetValues($) {
|
|||||||
my $master = $hash->{IODev};
|
my $master = $hash->{IODev};
|
||||||
|
|
||||||
PT_BEGIN($thread);
|
PT_BEGIN($thread);
|
||||||
#-- reset presence
|
|
||||||
$hash->{PRESENT} = 0;
|
|
||||||
#------------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------------
|
||||||
#-- switch the device to current measurement off, VDD only
|
#-- switch the device to current measurement off, VDD only
|
||||||
#-- issue the match ROM command \x55 and the write scratchpad command
|
#-- issue the match ROM command \x55 and the write scratchpad command
|
||||||
#"ds2438.writestatusvdd"
|
#"ds2438.writestatusvdd"
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, "\x4E\x00\x08", 0)) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,"\x4E\x00\x08",0);
|
||||||
PT_EXIT("$owx_dev not accessible for writing status");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL($thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
unless ($thread->{ExecuteResponse}->{success}) {
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
PT_EXIT("$owx_dev write status failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
#-- copy scratchpad to register
|
#-- copy scratchpad to register
|
||||||
#-- issue the match ROM command \x55 and the copy scratchpad command
|
#-- issue the match ROM command \x55 and the copy scratchpad command
|
||||||
#"ds2438.copyscratchpadvdd"
|
#"ds2438.copyscratchpadvdd"
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, "\x48\x00", 0)) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,"\x48\x00",0);
|
||||||
PT_EXIT("$owx_dev not accessible to copy scratchpad");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL($thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
unless ($thread->{ExecuteResponse}->{success}) {
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
PT_EXIT("$owx_dev copy scratchpad failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
#-- initiate temperature conversion
|
#-- initiate temperature conversion
|
||||||
#-- conversion needs some 12 ms !
|
#-- conversion needs some 12 ms !
|
||||||
#-- issue the match ROM command \x55 and the start conversion command
|
#-- issue the match ROM command \x55 and the start conversion command
|
||||||
#"ds2438.temperaturconversionvdd"
|
#"ds2438.temperaturconversionvdd"
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, "\x44", 0)) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,"\x44",0);
|
||||||
PT_EXIT("$owx_dev not accessible for temperature conversion");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL($thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
unless ($thread->{ExecuteResponse}->{success}) {
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
PT_EXIT("$owx_dev temperature conversion failed");
|
|
||||||
}
|
$thread->{ExecuteTime} = gettimeofday() + 0.012;
|
||||||
#TODO implement async wait
|
PT_YIELD_UNTIL(gettimeofday() >= $thread->{ExecuteTime});
|
||||||
select(undef,undef,undef,0.012);
|
delete $thread->{ExecuteTime};
|
||||||
|
|
||||||
#-- initiate voltage conversion
|
#-- initiate voltage conversion
|
||||||
#-- conversion needs some 6 ms !
|
#-- conversion needs some 6 ms !
|
||||||
#-- issue the match ROM command \x55 and the start conversion command
|
#-- issue the match ROM command \x55 and the start conversion command
|
||||||
#"ds2438.voltageconversionvdd"
|
#"ds2438.voltageconversionvdd"
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, "\xB4", 0)) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,"\xB4",0);
|
||||||
PT_EXIT("$owx_dev not accessible for voltage conversion");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL($thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
unless ($thread->{ExecuteResponse}->{success}) {
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
PT_EXIT("$owx_dev voltage conversion failed");
|
|
||||||
}
|
$thread->{ExecuteTime} = gettimeofday() + 0.006;
|
||||||
#TODO implement async wait
|
PT_YIELD_UNTIL(gettimeofday() >= $thread->{ExecuteTime});
|
||||||
select(undef,undef,undef,0.006);
|
delete $thread->{ExecuteTime};
|
||||||
|
|
||||||
#-- from memory to scratchpad
|
#-- from memory to scratchpad
|
||||||
#-- copy needs some 12 ms !
|
#-- copy needs some 12 ms !
|
||||||
#-- issue the match ROM command \x55 and the recall memory command
|
#-- issue the match ROM command \x55 and the recall memory command
|
||||||
#"ds2438.recallmemoryvdd"
|
#"ds2438.recallmemoryvdd"
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, "\xB8\x00", 0)) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,"\xB8\x00",0);
|
||||||
PT_EXIT("$owx_dev not accessible for recall memory");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL($thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
unless ($thread->{ExecuteResponse}->{success}) {
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
PT_EXIT("$owx_dev recall memory failed");
|
|
||||||
}
|
$thread->{ExecuteTime} = gettimeofday() + 0.012;
|
||||||
#TODO implement async wait
|
PT_YIELD_UNTIL(gettimeofday() >= $thread->{ExecuteTime});
|
||||||
select(undef,undef,undef,0.012);
|
delete $thread->{ExecuteTime};
|
||||||
|
|
||||||
#-- NOW ask the specific device
|
#-- NOW ask the specific device
|
||||||
#-- issue the match ROM command \x55 and the read scratchpad command \xBE
|
#-- issue the match ROM command \x55 and the read scratchpad command \xBE
|
||||||
#-- reading 9 + 2 + 9 data bytes = 20 bytes
|
#-- reading 9 + 2 + 9 data bytes = 20 bytes
|
||||||
#"ds2438.getvdd"
|
#"ds2438.getvdd"
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, "\xBE\x00", 9)) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,"\xBE\x00",9);
|
||||||
PT_EXIT("$owx_dev not accessible in 2nd step");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL($thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
$response = $thread->{ExecuteResponse};
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
unless ($response->{success}) {
|
$res = $thread->{pt_execute}->PT_RETVAL();
|
||||||
PT_EXIT("$owx_dev not accessible in 2nd step");
|
|
||||||
}
|
|
||||||
$res = $response->{readdata};
|
|
||||||
unless (defined $res and length($res)==9) {
|
unless (defined $res and length($res)==9) {
|
||||||
PT_EXIT("$owx_dev has returned invalid data");
|
PT_EXIT("$owx_dev has returned invalid data");
|
||||||
}
|
}
|
||||||
$ret = OWXMULTI_BinValues($hash,"ds2438.getvdd",1,undef,$owx_dev,undef,undef,$res);
|
$ret = OWXMULTI_BinValues($hash,"ds2438.getvdd",1,undef,$owx_dev,undef,undef,$res);
|
||||||
if (defined $ret) {
|
if ($ret) {
|
||||||
PT_EXIT($ret);
|
die $ret;
|
||||||
}
|
}
|
||||||
#------------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------------
|
||||||
#-- switch the device to current measurement off, V external only
|
#-- switch the device to current measurement off, V external only
|
||||||
#-- issue the match ROM command \x55 and the write scratchpad command
|
#-- issue the match ROM command \x55 and the write scratchpad command
|
||||||
#"ds2438.writestatusvad"
|
#"ds2438.writestatusvad"
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, "\x4E\x00\x00", 0)) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,"\x4E\x00\x00",0);
|
||||||
PT_EXIT("$owx_dev not accessible to write status");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL($thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
unless ($thread->{ExecuteResponse}->{success}) {
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
PT_EXIT("$owx_dev write status failed");
|
|
||||||
}
|
|
||||||
#-- copy scratchpad to register
|
#-- copy scratchpad to register
|
||||||
#-- issue the match ROM command \x55 and the copy scratchpad command
|
#-- issue the match ROM command \x55 and the copy scratchpad command
|
||||||
#"ds2438.copyscratchpadvad"
|
#"ds2438.copyscratchpadvad"
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, "\x48\x00", 0)) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,"\x48\x00",0);
|
||||||
PT_EXIT("$owx_dev not accessible to copy scratchpad");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL($thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
unless ($thread->{ExecuteResponse}->{success}) {
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
PT_EXIT("$owx_dev copy scratchpad failed");
|
|
||||||
}
|
|
||||||
#-- initiate voltage conversion
|
#-- initiate voltage conversion
|
||||||
#-- conversion needs some 6 ms !
|
#-- conversion needs some 6 ms !
|
||||||
#-- issue the match ROM command \x55 and the start conversion command
|
#-- issue the match ROM command \x55 and the start conversion command
|
||||||
#"ds2438.voltageconversionvad"
|
#"ds2438.voltageconversionvad"
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, "\xB4", 0)) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,"\xB4",0);
|
||||||
PT_EXIT("$owx_dev not accessible for voltage conversion");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL($thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
unless ($thread->{ExecuteResponse}->{success}) {
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
PT_EXIT("$owx_dev voltage conversion failed");
|
|
||||||
}
|
$thread->{ExecuteTime} = gettimeofday() + 0.006;
|
||||||
#TODO implement async wait
|
PT_YIELD_UNTIL(gettimeofday() >= $thread->{ExecuteTime});
|
||||||
select(undef,undef,undef,0.006);
|
delete $thread->{ExecuteTime};
|
||||||
|
|
||||||
#-- from memory to scratchpad
|
#-- from memory to scratchpad
|
||||||
#-- copy needs some 12 ms !
|
#-- copy needs some 12 ms !
|
||||||
#-- issue the match ROM command \x55 and the recall memory command
|
#-- issue the match ROM command \x55 and the recall memory command
|
||||||
#"ds2438.recallmemoryvad"
|
#"ds2438.recallmemoryvad"
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, "\xB8\x00", 0)) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,"\xB8\x00",0);
|
||||||
PT_EXIT("$owx_dev not accessible to recall memory");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL($thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
unless ($thread->{ExecuteResponse}->{success}) {
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
PT_EXIT("$owx_dev recall memory failed");
|
|
||||||
}
|
$thread->{ExecuteTime} = gettimeofday() + 0.012;
|
||||||
#TODO implement async wait
|
PT_YIELD_UNTIL(gettimeofday() >= $thread->{ExecuteTime});
|
||||||
select(undef,undef,undef,0.012);
|
delete $thread->{ExecuteTime};
|
||||||
|
|
||||||
#-- NOW ask the specific device
|
#-- NOW ask the specific device
|
||||||
#-- issue the match ROM command \x55 and the read scratchpad command \xBE
|
#-- issue the match ROM command \x55 and the read scratchpad command \xBE
|
||||||
#-- reading 9 + 2 + 9 data bytes = 20 bytes
|
#-- reading 9 + 2 + 9 data bytes = 20 bytes
|
||||||
#"ds2438.getvad"
|
#"ds2438.getvad"
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, "\xBE\x00", 9)) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,"\xBE\x00", 9);
|
||||||
PT_EXIT("$owx_dev not accessible in 2nd step");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL($thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
$response = $thread->{ExecuteResponse};
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
unless ($response->{success}) {
|
|
||||||
PT_EXIT("$owx_dev not accessible in 2nd step");
|
|
||||||
}
|
|
||||||
#-- process results
|
#-- process results
|
||||||
$res = $response->{readdata};
|
$res = $thread->{pt_execute}->PT_RETVAL();
|
||||||
unless (defined $res and length($res)==9) {
|
unless (defined $res and length($res)==9) {
|
||||||
PT_EXIT("$owx_dev has returned invalid data");
|
PT_EXIT("$owx_dev has returned invalid data");
|
||||||
}
|
}
|
||||||
$ret = OWXMULTI_BinValues($hash,"ds2438.getvad",1,undef,$owx_dev,undef,undef,$res);
|
$ret = OWXMULTI_BinValues($hash,"ds2438.getvad",1,undef,$owx_dev,undef,undef,$res);
|
||||||
if (defined $ret) {
|
if ($ret) {
|
||||||
PT_EXIT($ret);
|
die $ret;
|
||||||
}
|
}
|
||||||
PT_END;
|
PT_END;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#######################################################################################
|
#######################################################################################
|
||||||
@ -1192,7 +1219,11 @@ sub OWXMULTI_PT_GetValues($) {
|
|||||||
########################################################################################
|
########################################################################################
|
||||||
|
|
||||||
sub OWXMULTI_PT_SetValues($@) {
|
sub OWXMULTI_PT_SetValues($@) {
|
||||||
my ($thread,$hash, @a) = @_;
|
my ($hash, @a) = @_;
|
||||||
|
|
||||||
|
return PT_THREAD(sub {
|
||||||
|
|
||||||
|
my ($thread) = @_;
|
||||||
|
|
||||||
my ($i,$j,$k);
|
my ($i,$j,$k);
|
||||||
|
|
||||||
@ -1217,15 +1248,14 @@ sub OWXMULTI_PT_SetValues($@) {
|
|||||||
|
|
||||||
my $select=sprintf("\x4E%c%c\x48",0,0);
|
my $select=sprintf("\x4E%c%c\x48",0,0);
|
||||||
#"setvalues"
|
#"setvalues"
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, $select, 0)) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,$select, 0);
|
||||||
PT_EXIT("OWXMULTI: Device $owx_dev not accessible");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL($thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
unless ($thread->{ExecuteResponse}->{success}) {
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
PT_EXIT("OWXMULTI: error setting values in $owx_dev");
|
|
||||||
}
|
|
||||||
|
|
||||||
PT_END;
|
PT_END;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
@ -89,7 +89,7 @@ no warnings 'deprecated';
|
|||||||
|
|
||||||
sub Log($$);
|
sub Log($$);
|
||||||
|
|
||||||
my $owx_version="5.16";
|
my $owx_version="5.17";
|
||||||
#-- fixed raw channel name, flexible channel name
|
#-- fixed raw channel name, flexible channel name
|
||||||
my @owg_fixed = ("A","B","C","D","E","F","G","H");
|
my @owg_fixed = ("A","B","C","D","E","F","G","H");
|
||||||
my @owg_channel = ("A","B","C","D","E","F","G","H");
|
my @owg_channel = ("A","B","C","D","E","F","G","H");
|
||||||
@ -144,6 +144,8 @@ sub OWSWITCH_Initialize ($) {
|
|||||||
$hash->{UndefFn} = "OWSWITCH_Undef";
|
$hash->{UndefFn} = "OWSWITCH_Undef";
|
||||||
$hash->{GetFn} = "OWSWITCH_Get";
|
$hash->{GetFn} = "OWSWITCH_Get";
|
||||||
$hash->{SetFn} = "OWSWITCH_Set";
|
$hash->{SetFn} = "OWSWITCH_Set";
|
||||||
|
$hash->{NotifyFn}= "OWSWITCH_Notify";
|
||||||
|
$hash->{InitFn} = "OWSWITCH_Init";
|
||||||
$hash->{AttrFn} = "OWSWITCH_Attr";
|
$hash->{AttrFn} = "OWSWITCH_Attr";
|
||||||
|
|
||||||
my $attlist = "IODev do_not_notify:0,1 showtime:0,1 model:DS2413,DS2406,DS2408 loglevel:0,1,2,3,4,5 ".
|
my $attlist = "IODev do_not_notify:0,1 showtime:0,1 model:DS2413,DS2406,DS2408 loglevel:0,1,2,3,4,5 ".
|
||||||
@ -266,9 +268,29 @@ sub OWSWITCH_Define ($$) {
|
|||||||
readingsSingleUpdate($hash,"state","defined",1);
|
readingsSingleUpdate($hash,"state","defined",1);
|
||||||
Log 3, "OWSWITCH: Device $name defined.";
|
Log 3, "OWSWITCH: Device $name defined.";
|
||||||
|
|
||||||
#-- Start timer for updates
|
$hash->{NOTIFYDEV} = "global";
|
||||||
InternalTimer(time()+10, "OWSWITCH_GetValues", $hash, 0);
|
|
||||||
|
|
||||||
|
if ($init_done) {
|
||||||
|
OWSWITCH_Init($hash);
|
||||||
|
}
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub OWSWITCH_Notify ($$) {
|
||||||
|
my ($hash,$dev) = @_;
|
||||||
|
if( grep(m/^(INITIALIZED|REREADCFG)$/, @{$dev->{CHANGED}}) ) {
|
||||||
|
OWSWITCH_Init($hash);
|
||||||
|
} elsif( grep(m/^SAVE$/, @{$dev->{CHANGED}}) ) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub OWSWITCH_Init ($) {
|
||||||
|
my ($hash)=@_;
|
||||||
|
#-- Start timer for updates
|
||||||
|
RemoveInternalTimer($hash);
|
||||||
|
InternalTimer(gettimeofday()+10, "OWSWITCH_GetValues", $hash, 0);
|
||||||
|
#--
|
||||||
|
readingsSingleUpdate($hash,"state","Initialized",1);
|
||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -307,6 +329,9 @@ sub OWSWITCH_Attr(@) {
|
|||||||
AssignIoPort($hash,$value);
|
AssignIoPort($hash,$value);
|
||||||
if( defined($hash->{IODev}) ) {
|
if( defined($hash->{IODev}) ) {
|
||||||
$hash->{ASYNC} = $hash->{IODev}->{TYPE} eq "OWX_ASYNC" ? 1 : 0;
|
$hash->{ASYNC} = $hash->{IODev}->{TYPE} eq "OWX_ASYNC" ? 1 : 0;
|
||||||
|
if ($init_done) {
|
||||||
|
OWSWITCH_Init($hash);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
last;
|
last;
|
||||||
};
|
};
|
||||||
@ -457,13 +482,22 @@ sub OWSWITCH_Get($@) {
|
|||||||
return "$name.id => $value";
|
return "$name.id => $value";
|
||||||
}
|
}
|
||||||
|
|
||||||
#-- get present
|
|
||||||
if($a[1] eq "present") {
|
|
||||||
#-- hash of the busmaster
|
#-- hash of the busmaster
|
||||||
my $master = $hash->{IODev};
|
my $master = $hash->{IODev};
|
||||||
|
|
||||||
|
#-- get present
|
||||||
|
if($a[1] eq "present") {
|
||||||
#-- asynchronous mode
|
#-- asynchronous mode
|
||||||
if( $hash->{ASYNC} ){
|
if( $hash->{ASYNC} ){
|
||||||
$value = OWX_ASYNC_Verify($master,$hash->{ROM_ID});
|
my ($task,$task_state);
|
||||||
|
eval {
|
||||||
|
$task = OWX_ASYNC_PT_Verify($hash);
|
||||||
|
OWX_ASYNC_Schedule($hash,$task);
|
||||||
|
$task_state = OWX_ASYNC_RunToCompletion($master,$task);
|
||||||
|
};
|
||||||
|
return GP_Catch($@) if $@;
|
||||||
|
return $task->PT_CAUSE() if ($task_state == PT_ERROR or $task_state == PT_CANCELED);
|
||||||
|
return "$name.present => ".ReadingsVal($name,"present","unknown");
|
||||||
} else {
|
} else {
|
||||||
$value = OWX_Verify($master,$hash->{ROM_ID});
|
$value = OWX_Verify($master,$hash->{ROM_ID});
|
||||||
}
|
}
|
||||||
@ -506,12 +540,13 @@ sub OWSWITCH_Get($@) {
|
|||||||
if( $interface eq "OWX" ){
|
if( $interface eq "OWX" ){
|
||||||
$ret = OWXSWITCH_GetState($hash);
|
$ret = OWXSWITCH_GetState($hash);
|
||||||
}elsif( $interface eq "OWX_ASYNC") {
|
}elsif( $interface eq "OWX_ASYNC") {
|
||||||
#TODO use OWX_ASYNC_Schedule instead
|
my ($task,$task_state);
|
||||||
my $task = PT_THREAD(\&OWXSWITCH_PT_GetState);
|
|
||||||
eval {
|
eval {
|
||||||
while ($task->PT_SCHEDULE($hash)) { OWX_ASYNC_Poll($hash->{IODev}); };
|
$task = OWXSWITCH_PT_GetState($hash);
|
||||||
|
OWX_ASYNC_Schedule($hash,$task);
|
||||||
|
$task_state = OWX_ASYNC_RunToCompletion($master,$task);
|
||||||
};
|
};
|
||||||
$ret = ($@) ? GP_Catch($@) : $task->PT_RETVAL();
|
$ret = ($@) ? GP_Catch($@) : ($task_state == PT_ERROR or $task_state == PT_CANCELED) ? $task->PT_CAUSE() : $task->PT_RETVAL();
|
||||||
#-- OWFS interface
|
#-- OWFS interface
|
||||||
}elsif( $interface eq "OWFS" ){
|
}elsif( $interface eq "OWFS" ){
|
||||||
$ret = OWFSSWITCH_GetState($hash);
|
$ret = OWFSSWITCH_GetState($hash);
|
||||||
@ -530,12 +565,13 @@ sub OWSWITCH_Get($@) {
|
|||||||
if( $interface eq "OWX" ){
|
if( $interface eq "OWX" ){
|
||||||
$ret = OWXSWITCH_GetState($hash);
|
$ret = OWXSWITCH_GetState($hash);
|
||||||
}elsif( $interface eq "OWX_ASYNC" ){
|
}elsif( $interface eq "OWX_ASYNC" ){
|
||||||
#TODO use OWX_ASYNC_Schedule instead
|
my ($task,$task_state);
|
||||||
my $task = PT_THREAD(\&OWXSWITCH_PT_GetState);
|
|
||||||
eval {
|
eval {
|
||||||
while ($task->PT_SCHEDULE($hash)) { OWX_ASYNC_Poll($hash->{IODev}); };
|
$task = OWXSWITCH_PT_GetState($hash);
|
||||||
|
OWX_ASYNC_Schedule($hash,$task);
|
||||||
|
$task_state = OWX_ASYNC_RunToCompletion($master,$task);
|
||||||
};
|
};
|
||||||
$ret = ($@) ? GP_Catch($@) : $task->PT_RETVAL();
|
$ret = ($@) ? GP_Catch($@) : ($task_state == PT_ERROR or $task_state == PT_CANCELED) ? $task->PT_CAUSE() : $task->PT_RETVAL();
|
||||||
}elsif( $interface eq "OWServer" ){
|
}elsif( $interface eq "OWServer" ){
|
||||||
$ret = OWFSSWITCH_GetState($hash);
|
$ret = OWFSSWITCH_GetState($hash);
|
||||||
}else{
|
}else{
|
||||||
@ -583,7 +619,7 @@ sub OWSWITCH_GetValues($) {
|
|||||||
}
|
}
|
||||||
}elsif( $interface eq "OWX_ASYNC" ){
|
}elsif( $interface eq "OWX_ASYNC" ){
|
||||||
eval {
|
eval {
|
||||||
OWX_ASYNC_Schedule( $hash, PT_THREAD(\&OWXSWITCH_PT_GetState),$hash );
|
OWX_ASYNC_Schedule( $hash, OWXSWITCH_PT_GetState($hash) );
|
||||||
};
|
};
|
||||||
return unless $@;
|
return unless $@;
|
||||||
$ret = GP_Catch($@);
|
$ret = GP_Catch($@);
|
||||||
@ -753,7 +789,7 @@ sub OWSWITCH_Set($@) {
|
|||||||
$ret2 = OWXSWITCH_SetState($hash,$value);
|
$ret2 = OWXSWITCH_SetState($hash,$value);
|
||||||
}elsif( $interface eq "OWX_ASYNC"){
|
}elsif( $interface eq "OWX_ASYNC"){
|
||||||
eval {
|
eval {
|
||||||
OWX_ASYNC_Schedule( $hash, PT_THREAD(\&OWXSWITCH_PT_SetOutput),$hash,$fnd,$nval );
|
OWX_ASYNC_Schedule( $hash, OWXSWITCH_PT_SetOutput($hash,$fnd,$nval) );
|
||||||
};
|
};
|
||||||
$ret2 = GP_Catch($@) if $@;
|
$ret2 = GP_Catch($@) if $@;
|
||||||
#-- OWFS interface
|
#-- OWFS interface
|
||||||
@ -791,7 +827,7 @@ sub OWSWITCH_Set($@) {
|
|||||||
$ret = OWXSWITCH_SetState($hash,int($value));
|
$ret = OWXSWITCH_SetState($hash,int($value));
|
||||||
}elsif( $interface eq "OWX_ASYNC" ){
|
}elsif( $interface eq "OWX_ASYNC" ){
|
||||||
eval {
|
eval {
|
||||||
OWX_ASYNC_Schedule( $hash, PT_THREAD(\&OWXSWITCH_PT_SetState),$hash,int($value) );
|
OWX_ASYNC_Schedule( $hash, OWXSWITCH_PT_SetState($hash,int($value)) );
|
||||||
};
|
};
|
||||||
$ret = GP_Catch($@) if $@;
|
$ret = GP_Catch($@) if $@;
|
||||||
}elsif( $interface eq "OWServer" ){
|
}elsif( $interface eq "OWServer" ){
|
||||||
@ -1245,8 +1281,12 @@ sub OWXSWITCH_SetState($$) {
|
|||||||
########################################################################################
|
########################################################################################
|
||||||
|
|
||||||
sub OWXSWITCH_PT_GetState($) {
|
sub OWXSWITCH_PT_GetState($) {
|
||||||
my ($thread,$hash) = @_;
|
|
||||||
|
|
||||||
|
my ($hash) = @_;
|
||||||
|
|
||||||
|
return PT_THREAD( sub {
|
||||||
|
|
||||||
|
my ($thread) = @_;
|
||||||
my ($select, $ret, @data, $response);
|
my ($select, $ret, @data, $response);
|
||||||
|
|
||||||
#-- ID of the device
|
#-- ID of the device
|
||||||
@ -1257,9 +1297,6 @@ sub OWXSWITCH_PT_GetState($) {
|
|||||||
|
|
||||||
PT_BEGIN($thread);
|
PT_BEGIN($thread);
|
||||||
|
|
||||||
#-- reset presence
|
|
||||||
$hash->{PRESENT} = 0;
|
|
||||||
|
|
||||||
my ($i,$j,$k);
|
my ($i,$j,$k);
|
||||||
|
|
||||||
#-- family = 12 => DS2406
|
#-- family = 12 => DS2406
|
||||||
@ -1268,19 +1305,17 @@ sub OWXSWITCH_PT_GetState($) {
|
|||||||
#-- issue the match ROM command \x55 and the access channel command
|
#-- issue the match ROM command \x55 and the access channel command
|
||||||
# \xF5 plus the two byte channel control and the value
|
# \xF5 plus the two byte channel control and the value
|
||||||
#-- reading 9 + 3 + 2 data bytes + 2 CRC bytes = 16 bytes
|
#-- reading 9 + 3 + 2 data bytes + 2 CRC bytes = 16 bytes
|
||||||
$select=sprintf("\xF5\xDD\xFF");
|
$thread->{'select'}=sprintf("\xF5\xDD\xFF");
|
||||||
unless(OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, $select, 4)) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,$thread->{'select'},4);
|
||||||
PT_EXIT("device $owx_dev not accessible in reading");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL(defined $thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
$response = $thread->{ExecuteResponse};
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
unless ($response->{success}) {
|
$response = $thread->{pt_execute}->PT_RETVAL();
|
||||||
|
unless (length($response) == 4) {
|
||||||
PT_EXIT("$owx_dev has returned invalid data");
|
PT_EXIT("$owx_dev has returned invalid data");
|
||||||
}
|
}
|
||||||
unless (length($response->{readdata}) == 4) {
|
$ret = OWXSWITCH_BinValues($hash,"ds2406.getstate",1,1,$owx_dev,$thread->{'select'},4,$response);
|
||||||
PT_EXIT("$owx_dev has returned invalid data");
|
|
||||||
}
|
|
||||||
$ret = OWXSWITCH_BinValues($hash,"ds2406.getstate",1,1,$owx_dev,$response->{writedata},4,$response->{readdata});
|
|
||||||
if (defined $ret) {
|
if (defined $ret) {
|
||||||
PT_EXIT($ret);
|
PT_EXIT($ret);
|
||||||
}
|
}
|
||||||
@ -1290,19 +1325,17 @@ sub OWXSWITCH_PT_GetState($) {
|
|||||||
#-- issue the match ROM command \x55 and the read PIO rtegisters command
|
#-- issue the match ROM command \x55 and the read PIO rtegisters command
|
||||||
# \xF5 plus the two byte channel target address
|
# \xF5 plus the two byte channel target address
|
||||||
#-- reading 9 + 3 + 8 data bytes + 2 CRC bytes = 22 bytes
|
#-- reading 9 + 3 + 8 data bytes + 2 CRC bytes = 22 bytes
|
||||||
$select=sprintf("\xF0\x88\x00");
|
$thread->{'select'}=sprintf("\xF0\x88\x00");
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, $select, 10)) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,$thread->{'select'},10);
|
||||||
PT_EXIT("device $owx_dev not accessible in reading");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL($thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
$response = $thread->{ExecuteResponse};
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
unless ($response->{success}) {
|
$response = $thread->{pt_execute}->PT_RETVAL();
|
||||||
PT_EXIT("$owx_dev has returned invalid data");
|
unless (length($response) == 10) {
|
||||||
}
|
|
||||||
unless (length($response->{readdata}) == 10) {
|
|
||||||
PT_EXIT("$owx_dev has returned invalid data")
|
PT_EXIT("$owx_dev has returned invalid data")
|
||||||
};
|
};
|
||||||
$ret = OWXSWITCH_BinValues($hash,"ds2408.getstate",1,1,$owx_dev,$response->{writedata},10,$response->{readdata});
|
$ret = OWXSWITCH_BinValues($hash,"ds2408.getstate",1,1,$owx_dev,$thread->{'select'},10,$response);
|
||||||
if (defined $ret) {
|
if (defined $ret) {
|
||||||
PT_EXIT($ret);
|
PT_EXIT($ret);
|
||||||
}
|
}
|
||||||
@ -1312,19 +1345,17 @@ sub OWXSWITCH_PT_GetState($) {
|
|||||||
#-- issue the match ROM command \x55 and the read gpio command
|
#-- issue the match ROM command \x55 and the read gpio command
|
||||||
# \xF5 plus 2 empty bytes
|
# \xF5 plus 2 empty bytes
|
||||||
#-- reading 9 + 1 + 2 data bytes = 12 bytes
|
#-- reading 9 + 1 + 2 data bytes = 12 bytes
|
||||||
$select = "\xF5";
|
$thread->{'select'}="\xF5";
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, $select, 2)) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,$thread->{'select'},2);
|
||||||
PT_EXIT("device $owx_dev not accessible in reading");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL($thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
$response = $thread->{ExecuteResponse};
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
unless ($response->{success}) {
|
$response = $thread->{pt_execute}->PT_RETVAL();
|
||||||
|
unless (length($response) == 2) {
|
||||||
PT_EXIT("$owx_dev has returned invalid data");
|
PT_EXIT("$owx_dev has returned invalid data");
|
||||||
}
|
}
|
||||||
unless (length($response->{readdata}) == 2) {
|
$ret = OWXSWITCH_BinValues($hash,"ds2413.getstate",1,1,$owx_dev,$thread->{'select'},2,$response);
|
||||||
PT_EXIT("$owx_dev has returned invalid data");
|
|
||||||
}
|
|
||||||
$ret = OWXSWITCH_BinValues($hash,"ds2413.getstate",1,1,$owx_dev,$response->{writedata},2,$response->{readdata});
|
|
||||||
if (defined $ret) {
|
if (defined $ret) {
|
||||||
PT_EXIT($ret);
|
PT_EXIT($ret);
|
||||||
}
|
}
|
||||||
@ -1332,6 +1363,7 @@ sub OWXSWITCH_PT_GetState($) {
|
|||||||
PT_EXIT("unknown device family $hash->{OW_FAMILY}\n");
|
PT_EXIT("unknown device family $hash->{OW_FAMILY}\n");
|
||||||
}
|
}
|
||||||
PT_END;
|
PT_END;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
########################################################################################
|
########################################################################################
|
||||||
@ -1345,8 +1377,11 @@ sub OWXSWITCH_PT_GetState($) {
|
|||||||
|
|
||||||
sub OWXSWITCH_PT_SetState($$) {
|
sub OWXSWITCH_PT_SetState($$) {
|
||||||
|
|
||||||
my ($thread,$hash,$value) = @_;
|
my ($hash,$value) = @_;
|
||||||
|
|
||||||
|
return PT_THREAD( sub {
|
||||||
|
|
||||||
|
my ($thread) = @_;
|
||||||
my ($select,$res,@data);
|
my ($select,$res,@data);
|
||||||
|
|
||||||
#-- ID of the device
|
#-- ID of the device
|
||||||
@ -1366,14 +1401,12 @@ sub OWXSWITCH_PT_SetState($$) {
|
|||||||
# \xAA at address TA1 = \x07 TA2 = \x00
|
# \xAA at address TA1 = \x07 TA2 = \x00
|
||||||
#-- reading 9 + 3 + 1 data bytes + 2 CRC bytes = 15 bytes
|
#-- reading 9 + 3 + 1 data bytes + 2 CRC bytes = 15 bytes
|
||||||
|
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, "\xAA\x07\x00", 3)) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,"\xAA\x07\x00", 3);
|
||||||
PT_EXIT("device $owx_dev not accessible in writing");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL($thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
unless ($thread->{ExecuteResponse}->{success}) {
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
PT_EXIT("state could not be set for device $owx_dev");
|
$res = $thread->{pt_execute}->PT_RETVAL();
|
||||||
}
|
|
||||||
$res = $thread->{ExecuteResponse}->{readdata};
|
|
||||||
|
|
||||||
#-- first step
|
#-- first step
|
||||||
my $stat = ord(substr($res,0,1));
|
my $stat = ord(substr($res,0,1));
|
||||||
@ -1382,17 +1415,16 @@ sub OWXSWITCH_PT_SetState($$) {
|
|||||||
#-- issue the match ROM command \x55 and the write status command
|
#-- issue the match ROM command \x55 and the write status command
|
||||||
# \x55 at address TA1 = \x07 TA2 = \x00
|
# \x55 at address TA1 = \x07 TA2 = \x00
|
||||||
#-- reading 9 + 4 + 2 data bytes = 15 bytes
|
#-- reading 9 + 4 + 2 data bytes = 15 bytes
|
||||||
$select=sprintf("\x55\x07\x00%c",$statneu);
|
$thread->{'select'}=sprintf("\x55\x07\x00%c",$statneu);
|
||||||
|
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, $select, 2)) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,$thread->{'select'}, 2);
|
||||||
PT_EXIT("device $owx_dev not accessible in writing");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL($thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
unless ($thread->{ExecuteResponse}->{success}) {
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
PT_EXIT("state could not be set for device $owx_dev");
|
$res = $thread->{pt_execute}->PT_RETVAL();
|
||||||
}
|
|
||||||
$res = $thread->{ExecuteResponse}->{readdata};
|
my $command = $thread->{'select'};
|
||||||
my $command = $thread->{ExecuteResponse}->{writedata};
|
|
||||||
|
|
||||||
#-- second step from above
|
#-- second step from above
|
||||||
@data=split(//,$res);
|
@data=split(//,$res);
|
||||||
@ -1416,14 +1448,12 @@ sub OWXSWITCH_PT_SetState($$) {
|
|||||||
# \x5A plus the value byte and its complement
|
# \x5A plus the value byte and its complement
|
||||||
$select=sprintf("\x5A%c%c",$value,255-$value);
|
$select=sprintf("\x5A%c%c",$value,255-$value);
|
||||||
|
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, $select, 1)) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,$select, 1);
|
||||||
PT_EXIT("device $owx_dev not accessible in writing");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL($thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
unless ($thread->{ExecuteResponse}->{success}) {
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
PT_EXIT("state could not be set for device $owx_dev");
|
$res = $thread->{pt_execute}->PT_RETVAL();
|
||||||
}
|
|
||||||
$res = $thread->{ExecuteResponse}->{readdata};
|
|
||||||
|
|
||||||
@data=split(//,$res);
|
@data=split(//,$res);
|
||||||
if (@data != 1) {
|
if (@data != 1) {
|
||||||
@ -1439,14 +1469,12 @@ sub OWXSWITCH_PT_SetState($$) {
|
|||||||
#-- issue the match ROM command \x55 and the write gpio command
|
#-- issue the match ROM command \x55 and the write gpio command
|
||||||
# \x5A plus the value byte and its complement
|
# \x5A plus the value byte and its complement
|
||||||
$select=sprintf("\x5A%c%c",252+$value,3-$value);
|
$select=sprintf("\x5A%c%c",252+$value,3-$value);
|
||||||
unless (OWX_ASYNC_Execute( $master, $thread, 1, $owx_dev, $select, 1)) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,$select, 1);
|
||||||
PT_EXIT("device $owx_dev not accessible in writing");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL($thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
unless ($thread->{ExecuteResponse}->{success}) {
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
PT_EXIT("state could not be set for device $owx_dev");
|
$res = $thread->{pt_execute}->PT_RETVAL();
|
||||||
}
|
|
||||||
$res = $thread->{ExecuteResponse}->{readdata};
|
|
||||||
|
|
||||||
@data=split(//,$res);
|
@data=split(//,$res);
|
||||||
if (@data != 1) {
|
if (@data != 1) {
|
||||||
@ -1459,18 +1487,22 @@ sub OWXSWITCH_PT_SetState($$) {
|
|||||||
PT_EXIT("unknown device family $hash->{OW_FAMILY}\n");
|
PT_EXIT("unknown device family $hash->{OW_FAMILY}\n");
|
||||||
}
|
}
|
||||||
PT_END;
|
PT_END;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
sub OWXSWITCH_PT_SetOutput($$$) {
|
sub OWXSWITCH_PT_SetOutput($$$) {
|
||||||
|
|
||||||
my ($thread,$hash,$fnd,$nval) = @_;
|
my ($hash,$fnd,$nval) = @_;
|
||||||
|
|
||||||
|
return PT_THREAD(sub {
|
||||||
|
|
||||||
|
my ($thread) = @_;
|
||||||
my ($ret,$value);
|
my ($ret,$value);
|
||||||
|
|
||||||
PT_BEGIN($thread);
|
PT_BEGIN($thread);
|
||||||
|
|
||||||
$thread->{task} = PT_THREAD(\&OWXSWITCH_PT_GetState);
|
$thread->{task} = OWXSWITCH_PT_GetState($hash);
|
||||||
PT_WAIT_THREAD($thread->{task},$hash);
|
PT_WAIT_THREAD($thread->{task});
|
||||||
$ret = $thread->{task}->PT_RETVAL();
|
$ret = $thread->{task}->PT_RETVAL();
|
||||||
if ($ret) {
|
if ($ret) {
|
||||||
PT_EXIT($ret);
|
PT_EXIT($ret);
|
||||||
@ -1484,13 +1516,14 @@ sub OWXSWITCH_PT_SetOutput($$$) {
|
|||||||
if( $i == $fnd );
|
if( $i == $fnd );
|
||||||
}
|
}
|
||||||
$thread->{value} = $value;
|
$thread->{value} = $value;
|
||||||
$thread->{task} = PT_THREAD(\&OWXSWITCH_PT_SetState);
|
$thread->{task} = OWXSWITCH_PT_SetState($hash,$thread->{value});
|
||||||
PT_WAIT_THREAD($thread->{task},$hash,$thread->{value});
|
PT_WAIT_THREAD($thread->{task});
|
||||||
$ret = $thread->{task}->PT_RETVAL();
|
$ret = $thread->{task}->PT_RETVAL();
|
||||||
if ($ret) {
|
if ($ret) {
|
||||||
PT_EXIT($ret);
|
PT_EXIT($ret);
|
||||||
}
|
}
|
||||||
PT_END;
|
PT_END;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
150
fhem/FHEM/21_OWTHERM.pm
Executable file → Normal file
150
fhem/FHEM/21_OWTHERM.pm
Executable file → Normal file
@ -70,7 +70,7 @@ package main;
|
|||||||
use vars qw{%attr %defs %modules $readingFnAttributes $init_done};
|
use vars qw{%attr %defs %modules $readingFnAttributes $init_done};
|
||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
use Time::HiRes qw( gettimeofday tv_interval usleep );
|
use Time::HiRes qw( gettimeofday );
|
||||||
|
|
||||||
#add FHEM/lib to @INC if it's not allready included. Should rather be in fhem.pl than here though...
|
#add FHEM/lib to @INC if it's not allready included. Should rather be in fhem.pl than here though...
|
||||||
BEGIN {
|
BEGIN {
|
||||||
@ -86,7 +86,7 @@ no warnings 'deprecated';
|
|||||||
sub Log3($$$);
|
sub Log3($$$);
|
||||||
sub AttrVal($$$);
|
sub AttrVal($$$);
|
||||||
|
|
||||||
my $owx_version="5.20";
|
my $owx_version="5.21";
|
||||||
|
|
||||||
my %gets = (
|
my %gets = (
|
||||||
"id" => "",
|
"id" => "",
|
||||||
@ -138,6 +138,8 @@ sub OWTHERM_Initialize ($) {
|
|||||||
$hash->{UndefFn} = "OWTHERM_Undef";
|
$hash->{UndefFn} = "OWTHERM_Undef";
|
||||||
$hash->{GetFn} = "OWTHERM_Get";
|
$hash->{GetFn} = "OWTHERM_Get";
|
||||||
$hash->{SetFn} = "OWTHERM_Set";
|
$hash->{SetFn} = "OWTHERM_Set";
|
||||||
|
$hash->{NotifyFn}= "OWTHERM_Notify";
|
||||||
|
$hash->{InitFn} = "OWTHERM_Init";
|
||||||
$hash->{AttrFn} = "OWTHERM_Attr";
|
$hash->{AttrFn} = "OWTHERM_Attr";
|
||||||
$hash->{AttrList}= "IODev model:DS1820,DS18B20,DS1822 loglevel:0,1,2,3,4,5 ".
|
$hash->{AttrList}= "IODev model:DS1820,DS18B20,DS1822 loglevel:0,1,2,3,4,5 ".
|
||||||
"stateAL stateAH ".
|
"stateAL stateAH ".
|
||||||
@ -254,9 +256,29 @@ sub OWTHERM_Define ($$) {
|
|||||||
readingsSingleUpdate($hash,"state","defined",1);
|
readingsSingleUpdate($hash,"state","defined",1);
|
||||||
Log3 $name, 3, "OWTHERM: Device $name defined.";
|
Log3 $name, 3, "OWTHERM: Device $name defined.";
|
||||||
|
|
||||||
#-- Start timer for updates
|
$hash->{NOTIFYDEV} = "global";
|
||||||
InternalTimer(time()+10, "OWTHERM_GetValues", $hash, 0);
|
|
||||||
|
|
||||||
|
if ($init_done) {
|
||||||
|
OWTHERM_Init($hash);
|
||||||
|
}
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub OWTHERM_Notify ($$) {
|
||||||
|
my ($hash,$dev) = @_;
|
||||||
|
if( grep(m/^(INITIALIZED|REREADCFG)$/, @{$dev->{CHANGED}}) ) {
|
||||||
|
OWTHERM_Init($hash);
|
||||||
|
} elsif( grep(m/^SAVE$/, @{$dev->{CHANGED}}) ) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub OWTHERM_Init ($) {
|
||||||
|
my ($hash)=@_;
|
||||||
|
#-- Start timer for updates
|
||||||
|
RemoveInternalTimer($hash);
|
||||||
|
InternalTimer(gettimeofday()+10, "OWTHERM_GetValues", $hash, 0);
|
||||||
|
#--
|
||||||
|
readingsSingleUpdate($hash,"state","Initialized",1);
|
||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -307,6 +329,9 @@ sub OWTHERM_Attr(@) {
|
|||||||
AssignIoPort($hash,$value);
|
AssignIoPort($hash,$value);
|
||||||
if( defined($hash->{IODev}) ) {
|
if( defined($hash->{IODev}) ) {
|
||||||
$hash->{ASYNC} = $hash->{IODev}->{TYPE} eq "OWX_ASYNC" ? 1 : 0;
|
$hash->{ASYNC} = $hash->{IODev}->{TYPE} eq "OWX_ASYNC" ? 1 : 0;
|
||||||
|
if ($init_done) {
|
||||||
|
OWTHERM_Init($hash);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
last;
|
last;
|
||||||
};
|
};
|
||||||
@ -425,6 +450,8 @@ sub OWTHERM_Get($@) {
|
|||||||
return "$name.id => $value";
|
return "$name.id => $value";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#-- hash of the busmaster
|
||||||
|
my $master = $hash->{IODev};
|
||||||
#-- Get other values according to interface type
|
#-- Get other values according to interface type
|
||||||
my $interface= $hash->{IODev}->{TYPE};
|
my $interface= $hash->{IODev}->{TYPE};
|
||||||
|
|
||||||
@ -432,11 +459,17 @@ sub OWTHERM_Get($@) {
|
|||||||
if($a[1] eq "present" ) {
|
if($a[1] eq "present" ) {
|
||||||
#-- OWX interface
|
#-- OWX interface
|
||||||
if( $interface =~ /^OWX/ ){
|
if( $interface =~ /^OWX/ ){
|
||||||
#-- hash of the busmaster
|
|
||||||
my $master = $hash->{IODev};
|
|
||||||
#-- asynchronous mode
|
#-- asynchronous mode
|
||||||
if( $hash->{ASYNC} ){
|
if( $hash->{ASYNC} ){
|
||||||
$value = OWX_ASYNC_Verify($master,$hash->{ROM_ID});
|
my ($task,$task_state);
|
||||||
|
eval {
|
||||||
|
$task = OWX_ASYNC_PT_Verify($hash);
|
||||||
|
OWX_ASYNC_Schedule($hash,$task);
|
||||||
|
$task_state = OWX_ASYNC_RunToCompletion($master,$task);
|
||||||
|
};
|
||||||
|
return GP_Catch($@) if $@;
|
||||||
|
return $task->PT_CAUSE() if ($task_state == PT_ERROR or $task_state == PT_CANCELED);
|
||||||
|
return "$name.present => ".ReadingsVal($name,"present","unknown");
|
||||||
} else {
|
} else {
|
||||||
$value = OWX_Verify($master,$hash->{ROM_ID});
|
$value = OWX_Verify($master,$hash->{ROM_ID});
|
||||||
}
|
}
|
||||||
@ -463,12 +496,13 @@ sub OWTHERM_Get($@) {
|
|||||||
#-- not different from getting all values ..
|
#-- not different from getting all values ..
|
||||||
$ret = OWXTHERM_GetValues($hash);
|
$ret = OWXTHERM_GetValues($hash);
|
||||||
}elsif( $interface eq "OWX_ASYNC" ){
|
}elsif( $interface eq "OWX_ASYNC" ){
|
||||||
#TODO use OWX_ASYNC_Schedule instead
|
my ($task,$task_state);
|
||||||
my $task = PT_THREAD(\&OWXTHERM_PT_GetValues);
|
|
||||||
eval {
|
eval {
|
||||||
while ($task->PT_SCHEDULE($hash)) { OWX_ASYNC_Poll($hash->{IODev}); };
|
$task = OWXTHERM_PT_GetValues($hash);
|
||||||
|
OWX_ASYNC_Schedule($hash,$task);
|
||||||
|
$task_state = OWX_ASYNC_RunToCompletion($master,$task);
|
||||||
};
|
};
|
||||||
$ret = ($@) ? GP_Catch($@) : $task->PT_RETVAL();
|
$ret = ($@) ? GP_Catch($@) : ($task_state == PT_ERROR or $task_state == PT_CANCELED) ? $task->PT_CAUSE() : $task->PT_RETVAL();
|
||||||
#-- OWFS interface
|
#-- OWFS interface
|
||||||
}elsif( $interface eq "OWServer" ){
|
}elsif( $interface eq "OWServer" ){
|
||||||
$ret = OWFSTHERM_GetValues($hash);
|
$ret = OWFSTHERM_GetValues($hash);
|
||||||
@ -531,7 +565,7 @@ sub OWTHERM_GetValues($@) {
|
|||||||
#-- skip, if the conversion is driven by master
|
#-- skip, if the conversion is driven by master
|
||||||
unless ( defined($attr{$name}{tempConv}) && ( $attr{$name}{tempConv} eq "onkick") ){
|
unless ( defined($attr{$name}{tempConv}) && ( $attr{$name}{tempConv} eq "onkick") ){
|
||||||
eval {
|
eval {
|
||||||
OWX_ASYNC_Schedule( $hash, PT_THREAD(\&OWXTHERM_PT_GetValues),$hash );
|
OWX_ASYNC_Schedule( $hash, OWXTHERM_PT_GetValues($hash) );
|
||||||
};
|
};
|
||||||
$ret = GP_Catch($@) if $@;
|
$ret = GP_Catch($@) if $@;
|
||||||
}
|
}
|
||||||
@ -566,7 +600,8 @@ sub OWTHERM_InitializeDevice($) {
|
|||||||
my ($hash) = @_;
|
my ($hash) = @_;
|
||||||
|
|
||||||
my $name = $hash->{NAME};
|
my $name = $hash->{NAME};
|
||||||
my $interface = $hash->{IODev}->{TYPE};
|
my $master = $hash->{IODev};
|
||||||
|
my $interface = $master->{TYPE};
|
||||||
my @a = ($name,"",0);
|
my @a = ($name,"",0);
|
||||||
my ($unit,$offset,$factor,$abbr,$value,$ret);
|
my ($unit,$offset,$factor,$abbr,$value,$ret);
|
||||||
|
|
||||||
@ -633,12 +668,13 @@ sub OWTHERM_InitializeDevice($) {
|
|||||||
if( $interface eq "OWX" ){
|
if( $interface eq "OWX" ){
|
||||||
$ret = OWXTHERM_SetValues($hash,$args);
|
$ret = OWXTHERM_SetValues($hash,$args);
|
||||||
}elsif( $interface eq "OWX_ASYNC" ){
|
}elsif( $interface eq "OWX_ASYNC" ){
|
||||||
#TODO use OWX_ASYNC_Schedule instead
|
my ($task,$task_state);
|
||||||
my $task = PT_THREAD(\&OWXTHERM_PT_SetValues);
|
|
||||||
eval {
|
eval {
|
||||||
while ($task->PT_SCHEDULE($hash,$args)) { OWX_ASYNC_Poll($hash->{IODev}); };
|
$task = OWXTHERM_PT_SetValues($hash,$args);
|
||||||
|
OWX_ASYNC_Schedule($hash,$task);
|
||||||
|
$task_state = OWX_ASYNC_RunToCompletion($master,$task);
|
||||||
};
|
};
|
||||||
$ret = ($@) ? GP_Catch($@) : $task->PT_RETVAL();
|
$ret = ($@) ? GP_Catch($@) : ($task_state == PT_ERROR or $task_state == PT_CANCELED) ? $task->PT_CAUSE() : $task->PT_RETVAL();
|
||||||
#-- OWFS interface
|
#-- OWFS interface
|
||||||
}elsif( $interface eq "OWServer" ){
|
}elsif( $interface eq "OWServer" ){
|
||||||
$ret = OWFSTHERM_SetValues($hash,$args);
|
$ret = OWFSTHERM_SetValues($hash,$args);
|
||||||
@ -732,7 +768,7 @@ sub OWTHERM_Set($@) {
|
|||||||
}elsif( $interface eq "OWX_ASYNC" ){
|
}elsif( $interface eq "OWX_ASYNC" ){
|
||||||
$args->{format} = 1;
|
$args->{format} = 1;
|
||||||
eval {
|
eval {
|
||||||
OWX_ASYNC_Schedule( $hash, PT_THREAD(\&OWXTHERM_PT_SetValues),$hash,$args );
|
OWX_ASYNC_Schedule( $hash, OWXTHERM_PT_SetValues($hash,$args) );
|
||||||
};
|
};
|
||||||
$ret = GP_Catch($@) if $@;
|
$ret = GP_Catch($@) if $@;
|
||||||
#-- OWFS interface
|
#-- OWFS interface
|
||||||
@ -876,11 +912,8 @@ sub OWFSTHERM_SetValues($$) {
|
|||||||
#
|
#
|
||||||
########################################################################################
|
########################################################################################
|
||||||
|
|
||||||
sub OWXTHERM_BinValues($$$$$$$$) {
|
sub OWXTHERM_BinValues($$$$$$) {
|
||||||
my ($hash, $context, $success, $reset, $owx_dev, $command, $numread, $res) = @_;
|
my ($hash, $reset, $owx_dev, $command, $numread, $res) = @_;
|
||||||
|
|
||||||
#-- always check for success, unused are reset, numread
|
|
||||||
return unless ($success and ($context =~ /.*reading.*/));
|
|
||||||
|
|
||||||
#Log3 $name, 1,"OWXTHERM_BinValues context = $context";
|
#Log3 $name, 1,"OWXTHERM_BinValues context = $context";
|
||||||
|
|
||||||
@ -889,17 +922,15 @@ sub OWXTHERM_BinValues($$$$$$$$) {
|
|||||||
|
|
||||||
#Log3 $name, 1,"OWXTHERM: data length from reading device is ".length($res)." bytes";
|
#Log3 $name, 1,"OWXTHERM: data length from reading device is ".length($res)." bytes";
|
||||||
#-- process results
|
#-- process results
|
||||||
if( $res eq 0 ){
|
die "$owx_dev not accessible in 2nd step" unless ( defined $res and $res ne 0 );
|
||||||
return "$owx_dev not accessible in 2nd step";
|
|
||||||
}
|
|
||||||
|
|
||||||
#-- process results
|
#-- process results
|
||||||
@data=split(//,$res);
|
@data=split(//,$res);
|
||||||
return "invalid data length, ".int(@data)." instead of 9 bytes"
|
die "invalid data length, ".int(@data)." instead of 9 bytes"
|
||||||
if (@data != 9);
|
if (@data != 9);
|
||||||
return "invalid data"
|
die "invalid data"
|
||||||
if (ord($data[7])<=0);
|
if (ord($data[7])<=0);
|
||||||
return "invalid CRC"
|
die "invalid CRC"
|
||||||
if (OWX_CRC8(substr($res,0,8),$data[8])==0);
|
if (OWX_CRC8(substr($res,0,8),$data[8])==0);
|
||||||
|
|
||||||
#-- this must be different for the different device types
|
#-- this must be different for the different device types
|
||||||
@ -948,7 +979,7 @@ sub OWXTHERM_BinValues($$$$$$$$) {
|
|||||||
$ow_tln = ord($data[3]) > 127 ? 128-ord($data[3]) : ord($data[3]);
|
$ow_tln = ord($data[3]) > 127 ? 128-ord($data[3]) : ord($data[3]);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return "OWXTHERM: Unknown device family $hash->{OW_FAMILY}\n";
|
die "OWXTHERM: Unknown device family $hash->{OW_FAMILY}\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
#-- process alarm settings
|
#-- process alarm settings
|
||||||
@ -984,9 +1015,6 @@ sub OWXTHERM_GetValues($) {
|
|||||||
my $master = $hash->{IODev};
|
my $master = $hash->{IODev};
|
||||||
my $name = $hash->{NAME};
|
my $name = $hash->{NAME};
|
||||||
|
|
||||||
#-- reset presence
|
|
||||||
$hash->{PRESENT} = 0;
|
|
||||||
|
|
||||||
#-- check, if the conversion has been called before for all sensors
|
#-- check, if the conversion has been called before for all sensors
|
||||||
if( defined($attr{$name}{tempConv}) && ( $attr{$name}{tempConv} eq "onkick") ){
|
if( defined($attr{$name}{tempConv}) && ( $attr{$name}{tempConv} eq "onkick") ){
|
||||||
$con=0;
|
$con=0;
|
||||||
@ -1011,7 +1039,10 @@ sub OWXTHERM_GetValues($) {
|
|||||||
if( $res eq 0 );
|
if( $res eq 0 );
|
||||||
return "$owx_dev has returned invalid data"
|
return "$owx_dev has returned invalid data"
|
||||||
if( length($res)!=19);
|
if( length($res)!=19);
|
||||||
return OWXTHERM_BinValues($hash,"ds182x.reading",1,undef,$owx_dev,undef,undef,substr($res,10,9));
|
eval {
|
||||||
|
OWXTHERM_BinValues($hash,undef,$owx_dev,undef,undef,substr($res,10,9));
|
||||||
|
};
|
||||||
|
return $@;
|
||||||
}
|
}
|
||||||
|
|
||||||
#######################################################################################
|
#######################################################################################
|
||||||
@ -1079,8 +1110,10 @@ sub OWXTHERM_SetValues($$) {
|
|||||||
|
|
||||||
sub OWXTHERM_PT_GetValues($@) {
|
sub OWXTHERM_PT_GetValues($@) {
|
||||||
|
|
||||||
my ($thread,$hash) = @_;
|
my ($hash) = @_;
|
||||||
|
|
||||||
|
return PT_THREAD(sub {
|
||||||
|
my ($thread) = @_;
|
||||||
#-- For default, perform the conversion now
|
#-- For default, perform the conversion now
|
||||||
my $con=1;
|
my $con=1;
|
||||||
|
|
||||||
@ -1093,9 +1126,6 @@ sub OWXTHERM_PT_GetValues($@) {
|
|||||||
|
|
||||||
PT_BEGIN($thread);
|
PT_BEGIN($thread);
|
||||||
|
|
||||||
#-- reset presence
|
|
||||||
$hash->{PRESENT} = 0;
|
|
||||||
|
|
||||||
#-- check, if the conversion has been called before for all sensors
|
#-- check, if the conversion has been called before for all sensors
|
||||||
if( defined($attr{$name}{tempConv}) && ( $attr{$name}{tempConv} eq "onkick") ){
|
if( defined($attr{$name}{tempConv}) && ( $attr{$name}{tempConv} eq "onkick") ){
|
||||||
$con=0;
|
$con=0;
|
||||||
@ -1104,30 +1134,28 @@ sub OWXTHERM_PT_GetValues($@) {
|
|||||||
#-- if the conversion has not been called before
|
#-- if the conversion has not been called before
|
||||||
if( $con==1 ){
|
if( $con==1 ){
|
||||||
#-- issue the match ROM command \x55 and the start conversion command \x44
|
#-- issue the match ROM command \x55 and the start conversion command \x44
|
||||||
unless (OWX_ASYNC_Execute($master,$thread,1,$owx_dev,"\x44",0)) {
|
|
||||||
PT_EXIT("$owx_dev not accessible for convert");
|
|
||||||
}
|
|
||||||
my $now = gettimeofday();
|
my $now = gettimeofday();
|
||||||
my $delay = $convtimes{AttrVal($name,"resolution",12)};
|
my $delay = $convtimes{AttrVal($name,"resolution",12)};
|
||||||
$thread->{ExecuteTime} = $now + $delay*0.001;
|
$thread->{ExecuteTime} = $now + $delay*0.001;
|
||||||
PT_YIELD_UNTIL(defined $thread->{ExecuteResponse} and (gettimeofday() >= $thread->{ExecuteTime}));
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,"\x44",0);
|
||||||
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
|
delete $thread->{TimeoutTime};
|
||||||
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
|
PT_YIELD_UNTIL(gettimeofday() >= $thread->{ExecuteTime});
|
||||||
|
delete $thread->{ExecuteTime};
|
||||||
}
|
}
|
||||||
#-- NOW ask the specific device
|
#-- NOW ask the specific device
|
||||||
#-- issue the match ROM command \x55 and the read scratchpad command \xBE
|
#-- issue the match ROM command \x55 and the read scratchpad command \xBE
|
||||||
#-- reading 9 + 1 + 8 data bytes and 1 CRC byte = 19 bytes
|
#-- reading 9 + 1 + 8 data bytes and 1 CRC byte = 19 bytes
|
||||||
unless (OWX_ASYNC_Execute($master,$thread,1,$owx_dev,"\xBE",9)) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,"\xBE",9);
|
||||||
PT_EXIT("$owx_dev not accessible in reading");
|
$thread->{TimeoutTime} = gettimeofday()+2; #TODO: implement attribute-based timeout
|
||||||
}
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
PT_WAIT_UNTIL(defined $thread->{ExecuteResponse});
|
delete $thread->{TimeoutTime};
|
||||||
my $response = $thread->{ExecuteResponse};
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
unless ($response->{success}) {
|
OWXTHERM_BinValues($hash,1,$owx_dev,undef,9,$thread->{pt_execute}->PT_RETVAL());
|
||||||
PT_EXIT("$owx_dev read not successful");
|
|
||||||
}
|
|
||||||
my $res = OWXTHERM_BinValues($hash,"ds182x.reading",1,1,$owx_dev,undef,$response->{numread},$response->{readdata});
|
|
||||||
if ($res) {
|
|
||||||
PT_EXIT($res);
|
|
||||||
}
|
|
||||||
PT_END;
|
PT_END;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#######################################################################################
|
#######################################################################################
|
||||||
@ -1140,7 +1168,11 @@ sub OWXTHERM_PT_GetValues($@) {
|
|||||||
########################################################################################
|
########################################################################################
|
||||||
|
|
||||||
sub OWXTHERM_PT_SetValues($$) {
|
sub OWXTHERM_PT_SetValues($$) {
|
||||||
my ($thread, $hash, $args) = @_;
|
|
||||||
|
my ($hash,$args) = @_;
|
||||||
|
|
||||||
|
return PT_THREAD( sub {
|
||||||
|
my ($thread) = @_;
|
||||||
|
|
||||||
my ($i,$j,$k);
|
my ($i,$j,$k);
|
||||||
|
|
||||||
@ -1180,10 +1212,9 @@ sub OWXTHERM_PT_SetValues($$) {
|
|||||||
# 3. \x48 sent by WriteBytePower after match ROM => command ok, no effect on EEPROM
|
# 3. \x48 sent by WriteBytePower after match ROM => command ok, no effect on EEPROM
|
||||||
|
|
||||||
my $select=sprintf("\x4E%c%c%c",$thp,$tlp,$cfg);
|
my $select=sprintf("\x4E%c%c%c",$thp,$tlp,$cfg);
|
||||||
unless (OWX_ASYNC_Execute($master,$thread,1,$owx_dev,$select,3)) {
|
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,$select,3);
|
||||||
PT_EXIT("OWXTHERM: Device $owx_dev not accessible");
|
PT_WAIT_THREAD($thread->{pt_execute});
|
||||||
}
|
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
|
||||||
PT_WAIT_UNTIL(defined $thread->{ExecuteResponse});
|
|
||||||
|
|
||||||
#-- process results
|
#-- process results
|
||||||
$hash->{PRESENT} = 1;
|
$hash->{PRESENT} = 1;
|
||||||
@ -1191,6 +1222,7 @@ sub OWXTHERM_PT_SetValues($$) {
|
|||||||
OWTHERM_FormatValues($hash);
|
OWTHERM_FormatValues($hash);
|
||||||
}
|
}
|
||||||
PT_END;
|
PT_END;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
@ -32,14 +32,14 @@ sub GP_Catch($) {
|
|||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub GP_ForallClients($$$)
|
sub GP_ForallClients($$@)
|
||||||
{
|
{
|
||||||
my ($hash,$fn,$args) = @_;
|
my ($hash,$fn,@args) = @_;
|
||||||
foreach my $d ( sort keys %main::defs ) {
|
foreach my $d ( sort keys %main::defs ) {
|
||||||
if ( defined( $main::defs{$d} )
|
if ( defined( $main::defs{$d} )
|
||||||
&& defined( $main::defs{$d}{IODev} )
|
&& defined( $main::defs{$d}{IODev} )
|
||||||
&& $main::defs{$d}{IODev} == $hash ) {
|
&& $main::defs{$d}{IODev} == $hash ) {
|
||||||
&$fn($main::defs{$d},$args);
|
&$fn($main::defs{$d},@args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return undef;
|
return undef;
|
||||||
|
@ -1,186 +0,0 @@
|
|||||||
##############################################
|
|
||||||
# $Id$
|
|
||||||
##############################################
|
|
||||||
package OWX_Executor;
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
use warnings;
|
|
||||||
|
|
||||||
use constant {
|
|
||||||
DISCOVER => 1,
|
|
||||||
ALARMS => 2,
|
|
||||||
VERIFY => 3,
|
|
||||||
EXECUTE => 4,
|
|
||||||
EXIT => 5,
|
|
||||||
LOG => 6
|
|
||||||
};
|
|
||||||
|
|
||||||
sub new() {
|
|
||||||
my $class = shift;
|
|
||||||
my $self = {};
|
|
||||||
$self->{worker} = OWX_Worker->new($self);
|
|
||||||
return bless $self,$class;
|
|
||||||
};
|
|
||||||
|
|
||||||
sub discover($) {
|
|
||||||
my ($self,$hash) = @_;
|
|
||||||
if($self->{worker}->submit( { command => DISCOVER }, $hash )) {
|
|
||||||
$self->poll($hash);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub alarms($) {
|
|
||||||
my ($self,$hash) = @_;
|
|
||||||
if($self->{worker}->submit( { command => ALARMS }, $hash )) {
|
|
||||||
$self->poll($hash);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub verify($$) {
|
|
||||||
my ($self,$hash,$device) = @_;
|
|
||||||
if($self->{worker}->submit( { command => VERIFY, address => $device }, $hash )) {
|
|
||||||
$self->poll($hash);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub execute($$$$$$$) {
|
|
||||||
my ( $self, $hash, $context, $reset, $owx_dev, $data, $numread ) = @_;
|
|
||||||
if($self->{worker}->submit( {
|
|
||||||
command => EXECUTE,
|
|
||||||
context => $context,
|
|
||||||
reset => $reset,
|
|
||||||
address => $owx_dev,
|
|
||||||
writedata => $data,
|
|
||||||
numread => $numread
|
|
||||||
}, $hash )) {
|
|
||||||
$self->poll($hash);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return undef;
|
|
||||||
};
|
|
||||||
|
|
||||||
sub exit($) {
|
|
||||||
my ( $self,$hash ) = @_;
|
|
||||||
if($self->{worker}->submit( { command => EXIT }, $hash )) {
|
|
||||||
$self->poll($hash);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub poll($) {
|
|
||||||
my ( $self,$hash ) = @_;
|
|
||||||
$self->read();
|
|
||||||
$self->{worker}->PT_SCHEDULE($hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
# start of worker code
|
|
||||||
|
|
||||||
package OWX_Worker;
|
|
||||||
|
|
||||||
use Time::HiRes qw( gettimeofday tv_interval usleep );
|
|
||||||
use ProtoThreads;
|
|
||||||
no warnings 'deprecated';
|
|
||||||
|
|
||||||
use vars qw/@ISA/;
|
|
||||||
@ISA='ProtoThreads';
|
|
||||||
|
|
||||||
sub new($) {
|
|
||||||
my ($class,$owx) = @_;
|
|
||||||
|
|
||||||
my $worker = PT_THREAD(\&pt_main);
|
|
||||||
|
|
||||||
$worker->{commands} = [];
|
|
||||||
$worker->{delayed} = {};
|
|
||||||
$worker->{owx} = $owx;
|
|
||||||
|
|
||||||
return bless $worker,$class;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub submit($$) {
|
|
||||||
my ($self,$command,$hash) = @_;
|
|
||||||
push @{$self->{commands}}, $command;
|
|
||||||
$self->PT_SCHEDULE($hash);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub pt_main($) {
|
|
||||||
my ( $self, $hash ) = @_;
|
|
||||||
my $item = $self->{item};
|
|
||||||
PT_BEGIN($self);
|
|
||||||
PT_WAIT_UNTIL($item = $self->nextItem($hash));
|
|
||||||
$self->{item} = $item;
|
|
||||||
|
|
||||||
REQUEST_HANDLER: {
|
|
||||||
my $command = $item->{command};
|
|
||||||
|
|
||||||
$command eq OWX_Executor::DISCOVER and do {
|
|
||||||
PT_WAIT_THREAD($self->{owx}->{pt_discover},$self->{owx});
|
|
||||||
my $devices = $self->{owx}->{pt_discover}->PT_RETVAL();
|
|
||||||
if (defined $devices) {
|
|
||||||
main::OWX_ASYNC_AfterSearch($hash,$devices);
|
|
||||||
}
|
|
||||||
PT_EXIT;
|
|
||||||
};
|
|
||||||
|
|
||||||
$command eq OWX_Executor::ALARMS and do {
|
|
||||||
PT_WAIT_THREAD($self->{owx}->{pt_alarms},$self->{owx});
|
|
||||||
my $devices = $self->{owx}->{pt_alarms}->PT_RETVAL();
|
|
||||||
if (defined $devices) {
|
|
||||||
main::OWX_ASYNC_AfterAlarms($hash,$devices);
|
|
||||||
}
|
|
||||||
PT_EXIT;
|
|
||||||
};
|
|
||||||
|
|
||||||
$command eq OWX_Executor::VERIFY and do {
|
|
||||||
PT_WAIT_THREAD($self->{owx}->{pt_verify},$self->{owx},$item->{address});
|
|
||||||
my $devices = $self->{owx}->{pt_verify}->PT_RETVAL();
|
|
||||||
if (defined $devices) {
|
|
||||||
main::OWX_ASYNC_AfterVerify($hash,$devices);
|
|
||||||
}
|
|
||||||
PT_EXIT;
|
|
||||||
};
|
|
||||||
|
|
||||||
$command eq OWX_Executor::EXECUTE and do {
|
|
||||||
PT_WAIT_THREAD($self->{owx}->{pt_execute},$self->{owx},$hash,$item->{context},$item->{reset},$item->{address},$item->{writedata},$item->{numread});
|
|
||||||
my $res = $self->{owx}->{pt_execute}->PT_RETVAL();
|
|
||||||
unless (defined $res) {
|
|
||||||
main::OWX_ASYNC_AfterExecute($hash,$item->{context},undef,$item->{reset},$item->{address},$item->{writedata},$item->{numread},undef);
|
|
||||||
PT_EXIT;
|
|
||||||
}
|
|
||||||
my $writelen = defined $item->{writedata} ? split (//,$item->{writedata}) : 0;
|
|
||||||
my @result = split (//, $res);
|
|
||||||
my $readdata = 9+$writelen < @result ? substr($res,9+$writelen) : "";
|
|
||||||
main::OWX_ASYNC_AfterExecute($hash,$item->{context},1,$item->{reset},$item->{address},$item->{writedata},$item->{numread},$readdata);
|
|
||||||
PT_EXIT;
|
|
||||||
};
|
|
||||||
|
|
||||||
$command eq OWX_Executor::EXIT and do {
|
|
||||||
main::OWX_ASYNC_Disconnected($hash);
|
|
||||||
PT_EXIT;
|
|
||||||
};
|
|
||||||
main::Log3($hash->{NAME},3,"OWX_Executor: unexpected command: "+$command);
|
|
||||||
};
|
|
||||||
PT_END;
|
|
||||||
};
|
|
||||||
|
|
||||||
sub nextItem($) {
|
|
||||||
my ( $self,$hash ) = @_;
|
|
||||||
my $item = shift @{$self->{commands}};
|
|
||||||
if ($item) {
|
|
||||||
if($item->{context}) {
|
|
||||||
main::Log3 $hash->{NAME},5,"OWX_Executor: item $item->{context} for ".(defined $item->{address} ? $item->{address} : "---")." eligible to run";
|
|
||||||
} else {
|
|
||||||
main::Log3 $hash->{NAME},5,"OWX_Executor: command $item->{command} eligible to run";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $item;
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
@ -36,7 +36,9 @@ BEGIN {
|
|||||||
};
|
};
|
||||||
|
|
||||||
use Device::Firmata::Constants qw/ :all /;
|
use Device::Firmata::Constants qw/ :all /;
|
||||||
use Time::HiRes qw(gettimeofday tv_interval);
|
use Time::HiRes qw( gettimeofday );
|
||||||
|
use ProtoThreads;
|
||||||
|
no warnings 'deprecated';
|
||||||
|
|
||||||
sub new() {
|
sub new() {
|
||||||
my ($class) = @_;
|
my ($class) = @_;
|
||||||
@ -103,40 +105,26 @@ sub FRM_OWX_observer
|
|||||||
my $command = $data->{command};
|
my $command = $data->{command};
|
||||||
COMMAND_HANDLER: {
|
COMMAND_HANDLER: {
|
||||||
$command eq "READ_REPLY" and do {
|
$command eq "READ_REPLY" and do {
|
||||||
my $id = $data->{id};
|
$self->{responses}->{$data->{id}} = $data->{data}; # // $data->{device} // "defaultid"}
|
||||||
my $request = ( defined $id ) ? $self->{requests}->{$id} : undef;
|
main::Log3 ($self->{name},5,"FRM_OWX_observer: READ_REPLY $data->{id}: ".join " ",map sprintf("%02X",$_),@{$data->{data}}) if $self->{debug};
|
||||||
unless ( defined $request ) {
|
|
||||||
last unless ( defined $data->{device} );
|
|
||||||
my $owx_device = FRM_OWX_firmata_to_device( $data->{device} );
|
|
||||||
my %requests = %{ $self->{requests} };
|
|
||||||
foreach my $key ( keys %requests ) {
|
|
||||||
if ( $requests{$key}->{device} eq $owx_device ) {
|
|
||||||
$request = $requests{$key};
|
|
||||||
$id = $key;
|
|
||||||
last;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
last unless ( defined $request );
|
|
||||||
my $owx_data = pack "C*", @{ $data->{data} };
|
|
||||||
my $owx_device = $request->{device};
|
|
||||||
my $context = $request->{context};
|
|
||||||
my $reqcommand = $request->{command};
|
|
||||||
my $writedata = pack "C*", @{ $reqcommand->{'write'} } if ( defined $reqcommand->{'write'} );
|
|
||||||
main::OWX_ASYNC_AfterExecute( $self->{hash}, $context, 1, $reqcommand->{'reset'}, $owx_device, $writedata, $reqcommand->{'read'}, $owx_data);
|
|
||||||
delete $self->{requests}->{$id};
|
|
||||||
last;
|
last;
|
||||||
};
|
};
|
||||||
( $command eq "SEARCH_REPLY" or $command eq "SEARCH_ALARMS_REPLY" ) and do {
|
( $command eq "SEARCH_REPLY" or $command eq "SEARCH_ALARMS_REPLY" ) and do {
|
||||||
my @owx_devices = ();
|
my @owx_devices = ();
|
||||||
foreach my $device ( @{ $data->{devices} } ) {
|
foreach my $device ( @{ $data->{devices} } ) {
|
||||||
push @owx_devices, FRM_OWX_firmata_to_device($device);
|
push @owx_devices, firmata_to_device($device);
|
||||||
};
|
};
|
||||||
if ( $command eq "SEARCH_REPLY" ) {
|
if ( $command eq "SEARCH_REPLY" ) {
|
||||||
$self->{devs} = \@owx_devices;
|
$self->{devs} = \@owx_devices;
|
||||||
|
main::Log3 ($self->{name},5,"FRM_OWX_observer: SEARCH_REPLY: ".join ",",@owx_devices) if $self->{debug};
|
||||||
|
$self->{devs_timestamp} = gettimeofday();
|
||||||
|
#TODO avoid OWX_ASYNC_AfterSearch to be called twice
|
||||||
main::OWX_ASYNC_AfterSearch($self->{hash},\@owx_devices);
|
main::OWX_ASYNC_AfterSearch($self->{hash},\@owx_devices);
|
||||||
} else {
|
} else {
|
||||||
$self->{alarmdevs} = \@owx_devices;
|
$self->{alarmdevs} = \@owx_devices;
|
||||||
|
main::Log3 ($self->{name},5,"FRM_OWX_observer: SEARCH_ALARMS_REPLY: ".join ",",@owx_devices) if $self->{debug};
|
||||||
|
$self->{alarmdevs_timestamp} = gettimeofday();
|
||||||
|
#TODO avoid OWX_ASYNC_AfterAlarms to be called twice
|
||||||
main::OWX_ASYNC_AfterAlarms($self->{hash},\@owx_devices);
|
main::OWX_ASYNC_AfterAlarms($self->{hash},\@owx_devices);
|
||||||
};
|
};
|
||||||
last;
|
last;
|
||||||
@ -147,7 +135,7 @@ COMMAND_HANDLER: {
|
|||||||
|
|
||||||
########### functions implementing interface to OWX ##########
|
########### functions implementing interface to OWX ##########
|
||||||
|
|
||||||
sub FRM_OWX_device_to_firmata
|
sub device_to_firmata
|
||||||
{
|
{
|
||||||
my @device;
|
my @device;
|
||||||
foreach my $hbyte ( unpack "A2xA2A2A2A2A2A2xA2", shift ) {
|
foreach my $hbyte ( unpack "A2xA2A2A2A2A2A2xA2", shift ) {
|
||||||
@ -160,7 +148,7 @@ sub FRM_OWX_device_to_firmata
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub FRM_OWX_firmata_to_device
|
sub firmata_to_device
|
||||||
{
|
{
|
||||||
my $device = shift;
|
my $device = shift;
|
||||||
return sprintf( "%02X.%02X%02X%02X%02X%02X%02X.%02X", $device->{family}, @{ $device->{identity} }, $device->{crc} );
|
return sprintf( "%02X.%02X%02X%02X%02X%02X%02X.%02X", $device->{family}, @{ $device->{identity} }, $device->{crc} );
|
||||||
@ -168,82 +156,114 @@ sub FRM_OWX_firmata_to_device
|
|||||||
|
|
||||||
########################################################################################
|
########################################################################################
|
||||||
#
|
#
|
||||||
# asynchronous methods search, alarms and execute
|
# factory methods for protothreads running discover, search, alarms and execute
|
||||||
#
|
#
|
||||||
########################################################################################
|
########################################################################################
|
||||||
|
|
||||||
sub discover($) {
|
########################################################################################
|
||||||
my ( $self, $hash ) = @_;
|
#
|
||||||
my $success = undef;
|
# Discover - Find devices on the 1-Wire bus
|
||||||
eval {
|
#
|
||||||
if ( my $firmata = main::FRM_Client_FirmataDevice($hash) and my $pin = $self->{pin} ) {
|
# Parameter hash = hash of bus master
|
||||||
$firmata->onewire_search($pin);
|
#
|
||||||
$success = 1;
|
# Return 1, if alarmed devices found, 0 otherwise.
|
||||||
};
|
#
|
||||||
};
|
########################################################################################
|
||||||
if ($@) {
|
|
||||||
main::Log( 5, $@ );
|
|
||||||
$self->exit($hash);
|
|
||||||
};
|
|
||||||
return $success;
|
|
||||||
};
|
|
||||||
|
|
||||||
sub alarms($) {
|
sub get_pt_discover() {
|
||||||
my ( $self, $hash ) = @_;
|
my ($self) = @_;
|
||||||
my $success = undef;
|
return PT_THREAD(sub {
|
||||||
eval {
|
my ($thread) = @_;
|
||||||
if ( my $firmata = main::FRM_Client_FirmataDevice($hash) and my $pin = $self->{pin} ) {
|
PT_BEGIN($thread);
|
||||||
$firmata->onewire_search_alarms($pin);
|
delete $self->{devs};
|
||||||
$success = 1;
|
main::FRM_Client_FirmataDevice($self->{hash})->onewire_search($self->{pin});
|
||||||
};
|
PT_WAIT_UNTIL(defined $self->{devs});
|
||||||
};
|
PT_EXIT($self->{devs});
|
||||||
if ($@) {
|
PT_END;
|
||||||
$self->exit($hash);
|
});
|
||||||
};
|
}
|
||||||
return $success;
|
|
||||||
};
|
|
||||||
|
|
||||||
sub execute($$$$$$) {
|
########################################################################################
|
||||||
my ( $self, $hash, $context, $reset, $owx_dev, $data, $numread ) = @_;
|
#
|
||||||
|
# Alarms - Find devices on the 1-Wire bus, which have the alarm flag set
|
||||||
|
#
|
||||||
|
# Return number of alarmed devices
|
||||||
|
#
|
||||||
|
########################################################################################
|
||||||
|
|
||||||
my $success = undef;
|
sub get_pt_alarms() {
|
||||||
|
my ($self) = @_;
|
||||||
|
return PT_THREAD(sub {
|
||||||
|
my ($thread) = @_;
|
||||||
|
PT_BEGIN($thread);
|
||||||
|
delete $self->{alarmdevs};
|
||||||
|
main::FRM_Client_FirmataDevice($self->{hash})->onewire_search_alarms($self->{pin});
|
||||||
|
PT_WAIT_UNTIL(defined $self->{alarmdevs});
|
||||||
|
PT_EXIT($self->{alarmdevs});
|
||||||
|
PT_END;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
eval {
|
sub get_pt_verify($) {
|
||||||
if ( my $firmata = main::FRM_Client_FirmataDevice($hash) and my $pin = $self->{pin} ) {
|
my ($self,$dev) = @_;
|
||||||
my @data = unpack "C*", $data if defined $data;
|
return PT_THREAD(sub {
|
||||||
my $id = $self->{id} if ($numread);
|
my ($thread) = @_;
|
||||||
|
PT_BEGIN($thread);
|
||||||
|
delete $self->{devs};
|
||||||
|
main::FRM_Client_FirmataDevice($self->{hash})->onewire_search($self->{pin});
|
||||||
|
PT_WAIT_UNTIL(defined $self->{devs});
|
||||||
|
PT_EXIT(scalar(grep {$dev eq $_} @{$self->{devs}}));
|
||||||
|
PT_END;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
########################################################################################
|
||||||
|
#
|
||||||
|
# Complex - Send match ROM, data block and receive bytes as response
|
||||||
|
#
|
||||||
|
# Parameter hash = hash of bus master,
|
||||||
|
# owx_dev = ROM ID of device
|
||||||
|
# data = string to send
|
||||||
|
# numread = number of bytes to receive
|
||||||
|
#
|
||||||
|
# Return response, if OK
|
||||||
|
# 0 if not OK
|
||||||
|
#
|
||||||
|
########################################################################################
|
||||||
|
|
||||||
|
sub get_pt_execute($$$$) {
|
||||||
|
my ($self, $reset, $owx_dev, $writedata, $numread) = @_;
|
||||||
|
return PT_THREAD(sub {
|
||||||
|
my ($thread) = @_;
|
||||||
|
|
||||||
|
PT_BEGIN($thread);
|
||||||
|
|
||||||
|
if ( my $firmata = main::FRM_Client_FirmataDevice($self->{hash}) and my $pin = $self->{pin} ) {
|
||||||
|
my @data = unpack "C*", $writedata if defined $writedata;
|
||||||
|
my $id = $self->{id};
|
||||||
my $ow_command = {
|
my $ow_command = {
|
||||||
'reset' => $reset,
|
'reset' => $reset,
|
||||||
'skip' => defined($owx_dev) ? undef : 1,
|
'skip' => defined($owx_dev) ? undef : 1,
|
||||||
'select' => defined($owx_dev) ? FRM_OWX_device_to_firmata($owx_dev) : undef,
|
'select' => defined($owx_dev) ? device_to_firmata($owx_dev) : undef,
|
||||||
'read' => $numread,
|
'read' => $numread,
|
||||||
'write' => @data ? \@data : undef,
|
'write' => @data ? \@data : undef,
|
||||||
'delay' => undef,
|
'delay' => undef,
|
||||||
'id' => $numread ? $id : undef
|
'id' => $numread ? $id : undef
|
||||||
};
|
};
|
||||||
if ($numread) {
|
main::Log3 ($self->{name},5,"FRM_OWX_Execute: $id: $owx_dev [".join(" ",(map sprintf("%02X",$_),@data))."] numread: ".(defined $numread ? $numread : 0)) if $self->{debug};
|
||||||
$owx_dev = '00.000000000000.00' unless defined $owx_dev;
|
|
||||||
$self->{requests}->{$id} = {
|
|
||||||
context => $context,
|
|
||||||
command => $ow_command,
|
|
||||||
device => $owx_dev
|
|
||||||
};
|
|
||||||
$self->{id} = ( ( $id + 1 ) & 0xFFFF );
|
|
||||||
};
|
|
||||||
$firmata->onewire_command_series( $pin, $ow_command );
|
$firmata->onewire_command_series( $pin, $ow_command );
|
||||||
$success = 1;
|
if ($numread) {
|
||||||
|
$thread->{id} = $id;
|
||||||
|
$self->{id} = ( $id + 1 ) & 0xFFFF;
|
||||||
|
delete $self->{responses}->{$id};
|
||||||
|
PT_WAIT_UNTIL(defined $self->{responses}->{$thread->{id}});
|
||||||
|
my $ret = pack "C*", @{$self->{responses}->{$thread->{id}}};
|
||||||
|
delete $self->{responses}->{$thread->{id}};
|
||||||
|
PT_EXIT($ret);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
if ($@) {
|
PT_END;
|
||||||
main::Log3 $hash->{NAME},1,"OWX_FRM: $@";
|
});
|
||||||
#$self->exit($hash);
|
|
||||||
};
|
|
||||||
|
|
||||||
unless ($numread) {
|
|
||||||
main::OWX_ASYNC_AfterExecute( $hash, $context, $success, $reset, $owx_dev, $data, $numread, "" );
|
|
||||||
main::InternalTimer(gettimeofday(), "OWX_ASYNC_RunTasks", $hash,0);
|
|
||||||
}
|
|
||||||
return $success;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
sub exit($) {
|
sub exit($) {
|
||||||
@ -258,22 +278,4 @@ sub poll($) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#sub printqueues($$) {
|
|
||||||
# my ($self,$hash,$calledfrom) = @_;
|
|
||||||
# my $name = $hash->{NAME};
|
|
||||||
# main::Log3 $name,5,"OWX_ASYNC all queues, called from :".$calledfrom;
|
|
||||||
# my $delayed = $self->{delayed};
|
|
||||||
#
|
|
||||||
# foreach my $address ( keys %$delayed ) {
|
|
||||||
# my $msg = $address.": until: ";
|
|
||||||
# $msg .= $delayed->{$address}->{'until'} ? $delayed->{$address}->{'until'}->[0].",".$delayed->{$address}->{'until'}->[1] : "---";
|
|
||||||
# $msg .= " items: [";
|
|
||||||
# foreach my $item (@{$delayed->{$address}->{'items'}}) {
|
|
||||||
# $msg .= $item->{context}.",";
|
|
||||||
# }
|
|
||||||
# $msg .= "]";
|
|
||||||
# main::Log3 $name,5,$msg;
|
|
||||||
# }
|
|
||||||
#}
|
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
@ -29,8 +29,8 @@ use strict;
|
|||||||
use warnings;
|
use warnings;
|
||||||
|
|
||||||
use vars qw/@ISA/;
|
use vars qw/@ISA/;
|
||||||
@ISA='OWX_Executor';
|
|
||||||
|
|
||||||
|
use Time::HiRes qw( gettimeofday );
|
||||||
use ProtoThreads;
|
use ProtoThreads;
|
||||||
no warnings 'deprecated';
|
no warnings 'deprecated';
|
||||||
|
|
||||||
@ -42,35 +42,31 @@ no warnings 'deprecated';
|
|||||||
|
|
||||||
sub new() {
|
sub new() {
|
||||||
my $class = shift;
|
my $class = shift;
|
||||||
|
my $self = {
|
||||||
require "$main::attr{global}{modpath}/FHEM/OWX_Executor.pm";
|
interface => "serial",
|
||||||
|
|
||||||
my $self = OWX_Executor->new();
|
|
||||||
|
|
||||||
$self->{interface} = "serial";
|
|
||||||
#-- baud rate serial interface
|
#-- baud rate serial interface
|
||||||
$self->{baud} = 9600;
|
baud => 9600,
|
||||||
#-- 16 byte search string
|
#-- 16 byte search string
|
||||||
$self->{search} = [0,0,0,0 ,0,0,0,0, 0,0,0,0, 0,0,0,0];
|
search => [0,0,0,0 ,0,0,0,0, 0,0,0,0, 0,0,0,0],
|
||||||
$self->{ROM_ID} = [0,0,0,0 ,0,0,0,0];
|
ROM_ID => [0,0,0,0 ,0,0,0,0],
|
||||||
#-- search state for 1-Wire bus search
|
#-- search state for 1-Wire bus search
|
||||||
$self->{LastDiscrepancy} = 0;
|
LastDiscrepancy => 0,
|
||||||
$self->{LastFamilyDiscrepancy} = 0;
|
LastFamilyDiscrepancy => 0,
|
||||||
$self->{LastDeviceFlag} = 0;
|
LastDeviceFlag => 0,
|
||||||
#-- module version
|
#-- module version
|
||||||
$self->{version} = 4.1;
|
version => 4.1,
|
||||||
$self->{alarmdevs} = [];
|
alarmdevs => [],
|
||||||
$self->{devs} = [];
|
devs => [],
|
||||||
$self->{pt_alarms} = PT_THREAD(\&pt_alarms);
|
timeout => 1.0, #default timeout 1 sec.
|
||||||
$self->{pt_discover} = PT_THREAD(\&pt_discover);
|
};
|
||||||
$self->{pt_verify} = PT_THREAD(\&pt_verify);
|
|
||||||
$self->{pt_execute} = PT_THREAD(\&pt_execute);
|
|
||||||
|
|
||||||
$self->{timeout} = 1.0; #default timeout 1 sec.
|
|
||||||
|
|
||||||
return bless $self,$class;
|
return bless $self,$class;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub poll($) {
|
||||||
|
my ( $self ) = @_;
|
||||||
|
$self->read();
|
||||||
|
}
|
||||||
|
|
||||||
########################################################################################
|
########################################################################################
|
||||||
#
|
#
|
||||||
# Public methods
|
# Public methods
|
||||||
@ -116,9 +112,10 @@ sub Define ($$) {
|
|||||||
#
|
#
|
||||||
########################################################################################
|
########################################################################################
|
||||||
|
|
||||||
sub pt_alarms () {
|
sub get_pt_alarms() {
|
||||||
my ($thread,$self) = @_;
|
my ($self) = @_;
|
||||||
|
return PT_THREAD(sub {
|
||||||
|
my ($thread) = @_;
|
||||||
PT_BEGIN($thread);
|
PT_BEGIN($thread);
|
||||||
$self->{alarmdevs} = [];
|
$self->{alarmdevs} = [];
|
||||||
#-- Discover all alarmed devices on the 1-Wire bus
|
#-- Discover all alarmed devices on the 1-Wire bus
|
||||||
@ -131,6 +128,7 @@ sub pt_alarms () {
|
|||||||
main::Log3($self->{name},5, " Alarms = ".join(' ',@{$self->{alarmdevs}}));
|
main::Log3($self->{name},5, " Alarms = ".join(' ',@{$self->{alarmdevs}}));
|
||||||
PT_EXIT($self->{alarmdevs});
|
PT_EXIT($self->{alarmdevs});
|
||||||
PT_END;
|
PT_END;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
########################################################################################
|
########################################################################################
|
||||||
@ -147,16 +145,20 @@ sub pt_alarms () {
|
|||||||
#
|
#
|
||||||
########################################################################################
|
########################################################################################
|
||||||
|
|
||||||
sub pt_execute($$$$$$$) {
|
sub get_pt_execute($$$$) {
|
||||||
my ($thread, $self, $hash, $context, $reset, $dev, $writedata, $numread) = @_;
|
my ($self, $reset, $dev, $writedata, $numread) = @_;
|
||||||
|
return PT_THREAD(sub {
|
||||||
|
my ($thread) = @_;
|
||||||
|
|
||||||
PT_BEGIN($thread);
|
PT_BEGIN($thread);
|
||||||
|
$thread->{writedata} = $writedata;
|
||||||
|
|
||||||
#-- get the interface
|
#-- get the interface
|
||||||
my $interface = $self->{interface};
|
my $interface = $self->{interface};
|
||||||
my $hwdevice = $self->{hwdevice};
|
my $hwdevice = $self->{hwdevice};
|
||||||
|
unless (defined $hwdevice) {
|
||||||
PT_EXIT unless (defined $hwdevice);
|
PT_EXIT;
|
||||||
|
}
|
||||||
|
|
||||||
$self->reset() if ($reset);
|
$self->reset() if ($reset);
|
||||||
|
|
||||||
@ -203,7 +205,9 @@ sub pt_execute($$$$$$$) {
|
|||||||
|
|
||||||
PT_WAIT_UNTIL($self->response_ready());
|
PT_WAIT_UNTIL($self->response_ready());
|
||||||
|
|
||||||
PT_EXIT if ($reset and !$self->reset_response());
|
if ($reset and !$self->reset_response()) {
|
||||||
|
PT_EXIT
|
||||||
|
}
|
||||||
|
|
||||||
my $res = $self->{string_in};
|
my $res = $self->{string_in};
|
||||||
#-- for debugging
|
#-- for debugging
|
||||||
@ -211,8 +215,14 @@ sub pt_execute($$$$$$$) {
|
|||||||
main::Log3($self->{name},5,"OWX_SER::Execute: Receiving ".unpack ("H*",$res));
|
main::Log3($self->{name},5,"OWX_SER::Execute: Receiving ".unpack ("H*",$res));
|
||||||
}
|
}
|
||||||
|
|
||||||
PT_EXIT($res);
|
if (defined $res) {
|
||||||
|
my $writelen = defined $thread->{writedata} ? split (//,$thread->{writedata}) : 0;
|
||||||
|
my @result = split (//, $res);
|
||||||
|
my $readdata = 9+$writelen < @result ? substr($res,9+$writelen) : "";
|
||||||
|
PT_EXIT($readdata);
|
||||||
|
}
|
||||||
PT_END;
|
PT_END;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
########################################################################################
|
########################################################################################
|
||||||
@ -225,8 +235,10 @@ sub pt_execute($$$$$$$) {
|
|||||||
#
|
#
|
||||||
########################################################################################
|
########################################################################################
|
||||||
|
|
||||||
sub pt_discover($) {
|
sub get_pt_discover() {
|
||||||
my ($thread,$self) = @_;
|
my ($self) = @_;
|
||||||
|
return PT_THREAD(sub {
|
||||||
|
my ($thread) = @_;
|
||||||
PT_BEGIN($thread);
|
PT_BEGIN($thread);
|
||||||
#-- Discover all alarmed devices on the 1-Wire bus
|
#-- Discover all alarmed devices on the 1-Wire bus
|
||||||
$self->first("discover");
|
$self->first("discover");
|
||||||
@ -237,6 +249,7 @@ sub pt_discover($) {
|
|||||||
} while( $self->{LastDeviceFlag}==0 );
|
} while( $self->{LastDeviceFlag}==0 );
|
||||||
PT_EXIT($self->{devs});
|
PT_EXIT($self->{devs});
|
||||||
PT_END;
|
PT_END;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
########################################################################################
|
########################################################################################
|
||||||
@ -382,8 +395,10 @@ sub Disconnect($) {
|
|||||||
#
|
#
|
||||||
########################################################################################
|
########################################################################################
|
||||||
|
|
||||||
sub pt_verify ($) {
|
sub get_pt_verify($) {
|
||||||
my ($thread,$self,$dev) = @_;
|
my ($self,$dev) = @_;
|
||||||
|
return PT_THREAD(sub {
|
||||||
|
my ($thread) = @_;
|
||||||
my $i;
|
my $i;
|
||||||
PT_BEGIN($thread);
|
PT_BEGIN($thread);
|
||||||
#-- from search string to byte id
|
#-- from search string to byte id
|
||||||
@ -410,10 +425,11 @@ sub pt_verify ($) {
|
|||||||
if ($dev eq $dev2){
|
if ($dev eq $dev2){
|
||||||
PT_EXIT(1);
|
PT_EXIT(1);
|
||||||
}else{
|
}else{
|
||||||
PT_EXIT;
|
PT_EXIT(0);
|
||||||
}
|
}
|
||||||
PT_END;
|
PT_END;
|
||||||
}
|
});
|
||||||
|
};
|
||||||
|
|
||||||
#######################################################################################
|
#######################################################################################
|
||||||
#
|
#
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# Perl Protothreads Version 1.01
|
# Perl Protothreads Version 1.04
|
||||||
#
|
#
|
||||||
# a lightwight pseudo-threading framework for perl that is
|
# a lightwight pseudo-threading framework for perl that is
|
||||||
# heavily inspired by Adam Dunkels protothreads for the c-language
|
# heavily inspired by Adam Dunkels protothreads for the c-language
|
||||||
@ -58,16 +58,19 @@
|
|||||||
package ProtoThreads;
|
package ProtoThreads;
|
||||||
|
|
||||||
use constant {
|
use constant {
|
||||||
PT_WAITING => 0,
|
PT_INITIAL => 0,
|
||||||
PT_EXITED => 1,
|
PT_WAITING => 1,
|
||||||
PT_ENDED => 2,
|
PT_YIELDED => 2,
|
||||||
PT_YIELDED => 3,
|
PT_EXITED => 3,
|
||||||
|
PT_ENDED => 4,
|
||||||
|
PT_ERROR => 5,
|
||||||
|
PT_CANCELED => 6,
|
||||||
};
|
};
|
||||||
|
|
||||||
my $DEBUG=0;
|
my $DEBUG=0;
|
||||||
|
|
||||||
use Exporter 'import';
|
use Exporter 'import';
|
||||||
@EXPORT = qw(PT_THREAD PT_WAITING PT_EXITED PT_ENDED PT_YIELDED PT_INIT PT_SCHEDULE);
|
@EXPORT = qw(PT_THREAD PT_INITIAL PT_WAITING PT_YIELDED PT_EXITED PT_ENDED PT_ERROR PT_CANCELED PT_INIT PT_SCHEDULE);
|
||||||
@EXPORT_OK = qw();
|
@EXPORT_OK = qw();
|
||||||
|
|
||||||
use Text::Balanced qw (
|
use Text::Balanced qw (
|
||||||
@ -77,14 +80,17 @@ use Text::Balanced qw (
|
|||||||
sub PT_THREAD($) {
|
sub PT_THREAD($) {
|
||||||
my $method = shift;
|
my $method = shift;
|
||||||
return bless({
|
return bless({
|
||||||
PT_THREAD_STATE => 0,
|
PT_THREAD_STATE => PT_INITIAL,
|
||||||
|
PT_THREAD_POSITION => 0,
|
||||||
PT_THREAD_METHOD => $method
|
PT_THREAD_METHOD => $method
|
||||||
}, "ProtoThreads");
|
}, "ProtoThreads");
|
||||||
}
|
}
|
||||||
|
|
||||||
sub PT_INIT($) {
|
sub PT_INIT($) {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
$self->{PT_THREAD_STATE} = 0;
|
$self->{PT_THREAD_POSITION} = 0;
|
||||||
|
$self->{PT_THREAD_STATE} = PT_INITIAL;
|
||||||
|
delete $self->{PT_THREAD_ERROR};
|
||||||
}
|
}
|
||||||
|
|
||||||
sub PT_SCHEDULE(@) {
|
sub PT_SCHEDULE(@) {
|
||||||
@ -93,11 +99,28 @@ sub PT_SCHEDULE(@) {
|
|||||||
return ($state == PT_WAITING or $state == PT_YIELDED);
|
return ($state == PT_WAITING or $state == PT_YIELDED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub PT_CANCEL($) {
|
||||||
|
my ($self,$cause) = @_;
|
||||||
|
$self->{PT_THREAD_POSITION} = 0;
|
||||||
|
$self->{PT_THREAD_ERROR} = $cause;
|
||||||
|
$self->{PT_THREAD_STATE} = PT_CANCELED;
|
||||||
|
}
|
||||||
|
|
||||||
sub PT_RETVAL() {
|
sub PT_RETVAL() {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
return $self->{PT_THREAD_RETURN};
|
return $self->{PT_THREAD_RETURN};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub PT_STATE() {
|
||||||
|
my $self = shift;
|
||||||
|
return $self->{PT_THREAD_STATE};
|
||||||
|
}
|
||||||
|
|
||||||
|
sub PT_CAUSE() {
|
||||||
|
my $self = shift;
|
||||||
|
return $self->{PT_THREAD_ERROR};
|
||||||
|
}
|
||||||
|
|
||||||
sub PT_NEXTCOMMAND($$) {
|
sub PT_NEXTCOMMAND($$) {
|
||||||
my ($code,$command) = @_;
|
my ($code,$command) = @_;
|
||||||
if ($code =~ /$command\s*(?=\()/s) {
|
if ($code =~ /$command\s*(?=\()/s) {
|
||||||
@ -121,66 +144,68 @@ FILTER_ONLY
|
|||||||
|
|
||||||
my $code = $_;
|
my $code = $_;
|
||||||
my $counter = 1;
|
my $counter = 1;
|
||||||
my ($success,$before,$arg,$after);
|
my ($success,$before,$arg,$after,$beforeblock);
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
my $thread = " - no PT_BEGIN before use of thread - ";
|
($success,$beforeblock,$arg,$after) = PT_NEXTCOMMAND($code,"PT_BEGIN");
|
||||||
($success,$before,$arg,$after) = PT_NEXTCOMMAND($code,"PT_BEGIN");
|
|
||||||
if ($success) {
|
if ($success) {
|
||||||
$thread = $arg;
|
if ($after =~ /PT_END\s*;/s) {
|
||||||
$code=$before."my \$PT_THREAD_STATE = eval { my \$PT_YIELD_FLAG = 1; goto ".$thread."->{PT_THREAD_STATE} if ".$thread."->{PT_THREAD_STATE};".$after;
|
my $thread = $arg;
|
||||||
|
my $block = $thread."->{PT_THREAD_STATE} = eval { my \$PT_YIELD_FLAG = 1; goto ".$thread."->{PT_THREAD_POSITION} if ".$thread."->{PT_THREAD_POSITION};".$`.$thread."->{PT_THREAD_POSITION} = 0; delete ".$thread."->{PT_THREAD_RETURN}; return PT_ENDED; }; if (\$\@) {".$thread."->{PT_THREAD_STATE} = PT_ERROR; ".$thread."->{PT_THREAD_ERROR} = \$\@; }; return ".$thread."->{PT_THREAD_STATE};";
|
||||||
|
my $afterblock = $';
|
||||||
while (1) {
|
while (1) {
|
||||||
($success,$before,$arg,$after) = PT_NEXTCOMMAND($code,"PT_YIELD_UNTIL");
|
($success,$before,$arg,$after) = PT_NEXTCOMMAND($block,"PT_YIELD_UNTIL");
|
||||||
if ($success) {
|
if ($success) {
|
||||||
$code=$before."\$PT_YIELD_FLAG = 0; ".$thread."->{PT_THREAD_STATE} = 'PT_LABEL_$counter'; PT_LABEL_$counter: return PT_YIELDED unless (\$PT_YIELD_FLAG and ($arg));".$after;
|
$block=$before."\$PT_YIELD_FLAG = 0; ".$thread."->{PT_THREAD_POSITION} = 'PT_LABEL_$counter'; PT_LABEL_$counter: return PT_YIELDED unless (\$PT_YIELD_FLAG and ($arg));".$after;
|
||||||
$counter++;
|
$counter++;
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
if ($code =~ /PT_YIELD\s*;/s) {
|
if ($block =~ /PT_YIELD\s*;/s) {
|
||||||
$code = $`."\$PT_YIELD_FLAG = 0; ".$thread."->{PT_THREAD_STATE} = 'PT_LABEL_$counter'; PT_LABEL_$counter: return PT_YIELDED unless \$PT_YIELD_FLAG;".$';
|
$block = $`."\$PT_YIELD_FLAG = 0; ".$thread."->{PT_THREAD_POSITION} = 'PT_LABEL_$counter'; PT_LABEL_$counter: return PT_YIELDED unless \$PT_YIELD_FLAG;".$';
|
||||||
$counter++;
|
$counter++;
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
($success,$before,$arg,$after) = PT_NEXTCOMMAND($code,"PT_WAIT_UNTIL");
|
($success,$before,$arg,$after) = PT_NEXTCOMMAND($block,"PT_WAIT_UNTIL");
|
||||||
if ($success) {
|
if ($success) {
|
||||||
$code=$before.$thread."->{PT_THREAD_STATE} = 'PT_LABEL_$counter'; PT_LABEL_$counter: return PT_WAITING unless ($arg);".$after;
|
$block=$before.$thread."->{PT_THREAD_POSITION} = 'PT_LABEL_$counter'; PT_LABEL_$counter: return PT_WAITING unless ($arg);".$after;
|
||||||
$counter++;
|
$counter++;
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
($success,$before,$arg,$after) = PT_NEXTCOMMAND($code,"PT_WAIT_WHILE");
|
($success,$before,$arg,$after) = PT_NEXTCOMMAND($block,"PT_WAIT_WHILE");
|
||||||
if ($success) {
|
if ($success) {
|
||||||
$code=$before.$thread."->{PT_THREAD_STATE} = 'PT_LABEL_$counter'; PT_LABEL_$counter: return PT_WAITING if ($arg);".$after;
|
$block=$before.$thread."->{PT_THREAD_POSITION} = 'PT_LABEL_$counter'; PT_LABEL_$counter: return PT_WAITING if ($arg);".$after;
|
||||||
$counter++;
|
$counter++;
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
($success,$before,$arg,$after) = PT_NEXTCOMMAND($code,"PT_WAIT_THREAD");
|
($success,$before,$arg,$after) = PT_NEXTCOMMAND($block,"PT_WAIT_THREAD");
|
||||||
if ($success) {
|
if ($success) {
|
||||||
$code=$before."PT_WAIT_WHILE(PT_SCHEDULE(".$arg."));".$after;
|
$block=$before."PT_WAIT_WHILE(PT_SCHEDULE(".$arg."));".$after;
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
($success,$before,$arg,$after) = PT_NEXTCOMMAND($code,"PT_SPAWN");
|
($success,$before,$arg,$after) = PT_NEXTCOMMAND($block,"PT_SPAWN");
|
||||||
if ($success) {
|
if ($success) {
|
||||||
$code=$before.$arg."->{PT_THREAD_STATE} = 0; PT_WAIT_THREAD($arg);".$after;
|
$block=$before.$arg."->{PT_THREAD_POSITION} = 0; PT_WAIT_THREAD($arg);".$after;
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
($success,$before,$arg,$after) = PT_NEXTCOMMAND($code,"PT_EXIT");
|
($success,$before,$arg,$after) = PT_NEXTCOMMAND($block,"PT_EXIT");
|
||||||
if ($success) {
|
if ($success) {
|
||||||
$code=$before.$thread."->{PT_THREAD_STATE} = 0; ".$thread."->{PT_THREAD_RETURN} = $arg; return PT_EXITED;".$after;
|
$block=$before.$thread."->{PT_THREAD_POSITION} = 0; ".$thread."->{PT_THREAD_RETURN} = $arg; return PT_EXITED;".$after;
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
if ($code =~ /PT_EXIT(\s*;|\s+)/s) {
|
if ($block =~ /PT_EXIT(\s*;|\s+)/s) {
|
||||||
$code = $`.$thread."->{PT_THREAD_STATE} = 0; delete ".$thread."->{PT_THREAD_RETURN}; return PT_EXITED".$1.$';
|
$block = $`.$thread."->{PT_THREAD_POSITION} = 0; delete ".$thread."->{PT_THREAD_RETURN}; return PT_EXITED".$1.$';
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
if ($code =~ /PT_RESTART(\s*;|\s)/s) {
|
if ($block =~ /PT_RESTART(\s*;|\s)/s) {
|
||||||
$code = $`.$thread."->{PT_THREAD_STATE} = 0; return PT_WAITING;".$1.$';
|
$block = $`.$thread."->{PT_THREAD_POSITION} = 0; return PT_WAITING;".$1.$';
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
if ($code =~ /PT_END\s*;/s) {
|
|
||||||
$code = $`.$thread."->{PT_THREAD_STATE} = 0; delete ".$thread."->{PT_THREAD_RETURN}; return PT_ENDED; }; die \$\@ if \$\@; return \$PT_THREAD_STATE;".$';
|
|
||||||
}
|
|
||||||
last;
|
last;
|
||||||
}
|
}
|
||||||
|
$code = $beforeblock.$block.$afterblock;
|
||||||
|
} else {
|
||||||
|
die "PT_END expected"
|
||||||
|
}
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
last;
|
last;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user