############################################# package main; use strict; use warnings; use Device::Firmata; use Device::Firmata::Constants qw/ :all /; ##################################### my %sets = ( "alarm" => "", ); my %gets = ( "reading" => "", "state" => "", "count" => 0, "alarm" => "off" ); sub FRM_IN_Initialize($) { my ($hash) = @_; $hash->{SetFn} = "FRM_IN_Set"; $hash->{GetFn} = "FRM_IN_Get"; $hash->{DefFn} = "FRM_Client_Define"; $hash->{InitFn} = "FRM_IN_Init"; $hash->{UndefFn} = "FRM_IN_Undef"; $hash->{AttrList} = "IODev count-mode count-threshold loglevel:0,1,2,3,4,5 $main::readingFnAttributes"; } sub FRM_IN_Init($$) { my ($hash,$args) = @_; my $ret = FRM_Init_Pin_Client($hash,$args,PIN_INPUT); return $ret if (defined $ret); my $firmata = $hash->{IODev}->{FirmataDevice}; $firmata->observe_digital($hash->{PIN},\&FRM_IN_observer,$hash); if (! (defined AttrVal($hash->{NAME},"stateFormat",undef))) { $main::attr{$hash->{NAME}}{"stateFormat"} = "reading"; } main::readingsSingleUpdate($hash,"state","Initialized",1); return undef; } sub FRM_IN_observer { my ($pin,$old,$new,$hash) = @_; main::Log(6,"onDigitalMessage for pin ".$pin.", old: ".(defined $old ? $old : "--").", new: ".(defined $new ? $new : "--")); my $name = $hash->{NAME}; my $mode = AttrVal($name,"count-mode","rising"); my $count = ReadingsVal($name,"count",0); main::readingsBeginUpdate($hash); if ( ($old != $new) and (($mode eq "rising" and $old == PIN_LOW) or ($mode eq "falling" and $old == PIN_HIGH) or ($mode eq "both"))) { $count++; my $threshold = AttrVal($name,"count-threshold",0); if ( $count >= $threshold ) { main::readingsBulkUpdate($hash,"alarm","on",1); $count=0; } main::readingsBulkUpdate($hash,"count",$count,1); }; main::readingsBulkUpdate($hash,"reading",$new == PIN_HIGH ? "on" : "off", 1); main::readingsEndUpdate($hash,1); } sub FRM_IN_Set { my ($hash, @a) = @_; return "Need at least one parameters" if(@a < 2); return "Unknown argument $a[1], choose one of " . join(" ", sort keys %sets) if(!defined($sets{$a[1]})); my $command = $a[1]; my $value = $a[2]; COMMAND_HANDLER: { $command eq "alarm" and do { return undef if (!($value eq "off" or $value eq "on")); main::readingsSingleUpdate($hash,"alarm",$value,1); last; } } } sub FRM_IN_Get($) { my ($hash, @a) = @_; return "Need at least one parameters" if(@a < 2); return "Unknown argument $a[1], choose one of " . join(" ", sort keys %gets) if(!defined($gets{$a[1]})); my $name = shift @a; my $cmd = shift @a; ARGUMENT_HANDLER: { $cmd eq "reading" and do { my $iodev = $hash->{IODev}; return $name." no IODev assigned" if (!defined $iodev); return $name.", ".$iodev->{NAME}." is not connected" if (!(defined $iodev->{FirmataDevice} and defined $iodev->{FD})); return $iodev->{FirmataDevice}->digital_read($hash->{PIN}) == PIN_HIGH ? "on" : "off"; }; ( $cmd eq "count" or $cmd eq "alarm" or $cmd eq "state" ) and do { return main::ReadingsVal($name,"count",$gets{$cmd}); }; } return undef; } sub FRM_IN_Undef($$) { my ($hash, $name) = @_; } 1; =pod =begin html
define <name> FRM_IN <pin>