From b7e37e60430cdc4bfe1285a59d52e724d3872d54 Mon Sep 17 00:00:00 2001 From: jensb <> Date: Sun, 20 Dec 2020 19:47:51 +0000 Subject: [PATCH] Device::Firmata: removed from FHEM, use CPAN version (forum #114552) git-svn-id: https://svn.fhem.de/fhem/trunk@23394 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/CHANGED | 1 + fhem/FHEM/lib/Device/Firmata.pm | 89 -- fhem/FHEM/lib/Device/Firmata/Base.pm | 386 ----- fhem/FHEM/lib/Device/Firmata/Changes | 62 - fhem/FHEM/lib/Device/Firmata/Constants.pm | 396 ----- fhem/FHEM/lib/Device/Firmata/Error.pm | 92 -- fhem/FHEM/lib/Device/Firmata/IO/NetIO.pm | 203 --- fhem/FHEM/lib/Device/Firmata/IO/SerialIO.pm | 77 - fhem/FHEM/lib/Device/Firmata/Language.pm | 106 -- fhem/FHEM/lib/Device/Firmata/Platform.pm | 1025 ------------- .../lib/Device/Firmata/Platform/Arduino.pm | 19 - fhem/FHEM/lib/Device/Firmata/Protocol.pm | 1309 ----------------- fhem/FHEM/lib/Device/Firmata/README | 47 - fhem/FHEM/lib/Device/Firmata/license.txt | 1 - 14 files changed, 1 insertion(+), 3812 deletions(-) delete mode 100644 fhem/FHEM/lib/Device/Firmata.pm delete mode 100644 fhem/FHEM/lib/Device/Firmata/Base.pm delete mode 100644 fhem/FHEM/lib/Device/Firmata/Changes delete mode 100644 fhem/FHEM/lib/Device/Firmata/Constants.pm delete mode 100644 fhem/FHEM/lib/Device/Firmata/Error.pm delete mode 100644 fhem/FHEM/lib/Device/Firmata/IO/NetIO.pm delete mode 100644 fhem/FHEM/lib/Device/Firmata/IO/SerialIO.pm delete mode 100644 fhem/FHEM/lib/Device/Firmata/Language.pm delete mode 100644 fhem/FHEM/lib/Device/Firmata/Platform.pm delete mode 100644 fhem/FHEM/lib/Device/Firmata/Platform/Arduino.pm delete mode 100644 fhem/FHEM/lib/Device/Firmata/Protocol.pm delete mode 100644 fhem/FHEM/lib/Device/Firmata/README delete mode 100644 fhem/FHEM/lib/Device/Firmata/license.txt diff --git a/fhem/CHANGED b/fhem/CHANGED index c0645ddc1..3338a040c 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -1,5 +1,6 @@ # Add changes at the top of the list. Keep it in ASCII, and 80-char wide. # Do not insert empty lines here, update check depends on it. + - change: Device::Firmata removed, use CPAN version (forum #114552) - bugfix: 10_FRM: Device::Firmata check (forum #114552 msg #1112141) - bugfix: 55_DWD_OpenData: forecast rotation (forum #83097 msg #1108423) - feature: 02_RSS: added readings to show filename and type of background diff --git a/fhem/FHEM/lib/Device/Firmata.pm b/fhem/FHEM/lib/Device/Firmata.pm deleted file mode 100644 index 5867ba89e..000000000 --- a/fhem/FHEM/lib/Device/Firmata.pm +++ /dev/null @@ -1,89 +0,0 @@ -package Device::Firmata; - -use strict; -use warnings; - -use Device::Firmata::Constants; -use Device::Firmata::Base - ISA => 'Device::Firmata::Base', - FIRMATA_ATTRIBS => { - }; - -=head1 NAME - -Device::Firmata - Perl interface to Firmata for the arduino platform. - -=head1 VERSION - -Version 0.64 - -=cut - -our $VERSION = '0.64'; -our $DEBUG = 0; - - -=head1 SYNOPSIS - - use strict; - use warnings; - - use Device::Firmata::Constants qw/ :all /; - use Device::Firmata; - - use Time::HiRes 'sleep'; - - $|++; - - my $led_pin = 13; - - my $device = Device::Firmata->open('/dev/ttyUSB0') or die "Could not connect to Firmata Server"; - $device->pin_mode($led_pin=>PIN_OUTPUT); - my $iteration = 0; - while (1) { - my $strobe_state = $iteration++%2; - $device->digital_write($led_pin=>$strobe_state); - sleep 0.5; - } - -=head1 SUBROUTINES/METHODS - -=head2 open - -establish serial connection with an Arduino micro-controller. Single argument is the name of the device file mapped to the arduino. Typically '/dev/ttyUSB0' or 'COM9' - -=cut - -sub open { -# -------------------------------------------------- -# Establish a connection to Arduino via the serial port -# - my ( $self, $serial_port, $opts ) = @_; - -# We're going to try and create the device connection first... - my $package = "Device::Firmata::Platform"; - eval "require $package"; - my $serialio = "Device::Firmata::IO::SerialIO"; - eval "require $serialio"; - - my $io = $serialio->open( $serial_port, $opts ); - my $platform = $package->attach( $io, $opts ) or die "Could not connect to Firmata Server"; - - # Figure out what platform we're running on - $platform->probe; - return $platform; -} - -sub listen { -# -------------------------------------------------- -# Listen on socket and wait for Arduino to establish a connection -# - my ( $pkg, $ip, $port, $opts ) = @_; - - my $netio = "Device::Firmata::IO::NetIO"; - eval "require $netio"; - - return $netio->listen( $ip, $port, $opts ) || die "Could not bind to socket"; -} - -1; diff --git a/fhem/FHEM/lib/Device/Firmata/Base.pm b/fhem/FHEM/lib/Device/Firmata/Base.pm deleted file mode 100644 index 51163df89..000000000 --- a/fhem/FHEM/lib/Device/Firmata/Base.pm +++ /dev/null @@ -1,386 +0,0 @@ -package Device::Firmata::Base; - -use strict 'vars', 'subs'; -use vars qw/ - $AUTOLOAD - $FIRMATA_DEBUG_LEVEL - $FIRMATA_ERROR_CLASS - $FIRMATA_ERROR - $FIRMATA_ATTRIBS - $FIRMATA_DEBUGGING - $FIRMATA_LOCALE - $FIRMATA_LOCALE_PATH - $FIRMATA_LOCALE_MESSAGES -/; - -=head1 NAME - -Device::Firmata::Base -- Abstract baseclass for Device::Firmata modules - -=cut - -$FIRMATA_DEBUGGING = 1; -$FIRMATA_ATTRIBS = {}; -$FIRMATA_LOCALE = 'en'; -$FIRMATA_LOCALE_PATH = '.'; -$FIRMATA_DEBUG_LEVEL = 0; -$FIRMATA_ERROR_CLASS = 'Device::Firmata::Error'; - -=head1 METHODS - -=head2 import - -Ease setting of configuration options - -=cut - -sub import { - my $self = shift; - my $pkg = caller; - my $config_opts = { - debugging => $FIRMATA_DEBUGGING, - }; - - if ( @_ ) { - my $opts = $self->parameters( @_ ); - if ( my $attrs = $opts->{FIRMATA_ATTRIBS} ) { - *{$pkg.'::FIRMATA_ATTRIBS'} = \$attrs; - } - - unless ( ref *{$pkg.'::ISA'} eq 'ARRAY' and @${$pkg.'::ISA'}) { - my @ISA = ref $opts->{ISA} ? @{$opts->{ISA}} : - $opts->{ISA} ? $opts->{ISA} : - __PACKAGE__; - *{$pkg.'::ISA'} = \@ISA; - } - use strict; - $self->SUPER::import( @_ ); - } -} - -=head2 new - -=cut - -sub new { - my $pkg = shift; - my $basis = copy_struct( $pkg->init_class_attribs ); - my $self = bless $basis, $pkg; - - @_ = $self->pre_init( @_ ) if $self->{_biofunc_pre_init}; - - if ( $self->{_biofunc_init} ) { - $self->init( @_ ); - } - else { - $self->init_instance_attribs( @_ ); - } - - return $self->post_init if $self->{_biofunc_post_init}; - return $self; -} - -=head2 create - -A soft new as some objects will override new and -we don't want to cause problems but still want -to invoice our creation code - -=cut - -sub create { - my $self = shift; - my $basis = copy_struct( $self->init_class_attribs ); - - @$self{ keys %$basis } = values %$basis; - - @_ = $self->pre_init( @_ ) if $self->{_biofunc_pre_init}; - - if ( $self->{_biofunc_init} ) { - $self->init( @_ ); - } - else { - $self->init_instance_attribs( @_ ); - } - - return $self->post_init if $self->{_biofunc_post_init}; - return $self; -} - -=head2 init_instance_attribs - -=cut - -sub init_instance_attribs { -# -------------------------------------------------- - my $self = shift; - my $opts = $self->parameters( @_ ); - - foreach my $k ( keys %$self ) { - next unless exists $opts->{$k}; - next if $k =~ /^_biofunc/; - $self->{$k} = $opts->{$k}; - } - - return $self; -} - -=head2 init_class_attribs - -=cut - -sub init_class_attribs { -# -------------------------------------------------- - my $class = ref $_[0] || shift; - my $track = { $class => 1, @_ ? %{$_[0]} : () }; - - return ${"${class}::ABSOLUTE_ATTRIBS"} if ${"${class}::ABSOLUTE_ATTRIBS"}; - - my $u = ${"${class}::FIRMATA_ATTRIBS"} || {}; - - for my $c ( @{"${class}::ISA"} ) { - next unless ${"${c}::FIRMATA_ATTRIBS"}; - - my $h; - if ( ${"${c}::ABSOLUTE_ATTRIBS"} ) { - $h = ${"${c}::ABSOLUTE_ATTRIBS"}; - } - else { - $c->fatal( "Cyclic dependancy!" ) if $track->{$c}; - $h = $c->init_class_attribs( $c, $track ); - } - - foreach my $k ( keys %$h ) { - next if exists $u->{$k}; - $u->{$k} = copy_struct( $h->{$k} ); - } - } - - foreach my $f ( qw( pre_init init post_init ) ) { - $u->{"_biofunc_" . $f} = $class->can( $f ) ? 1 : 0; - } - - ${"${class}::ABSOLUTE_ATTRIBS"} = $u; - - return $u; -} - -# logging/exception functions - - - -# Utilty functions - -=head2 parameters - -=cut - -sub parameters { -# -------------------------------------------------- - return {} unless @_ > 1; - - if ( @_ == 2 ) { - return $_[1] if ref $_[1]; - return; # something wierd happened - } - - @_ % 2 or $_[0]->warn( "Even number of elements were not passed to call.", join( " ", caller() ) ); - - shift; - - return {@_}; -} - -=head2 copy_struct - -=cut - -sub copy_struct { -# -------------------------------------------------- - my $s = shift; - - if ( ref $s ) { - if ( UNIVERSAL::isa( $s, 'HASH' ) ) { - return { - map { my $v = $s->{$_}; ( - $_ => ref $v ? copy_struct( $v ) : $v - )} keys %$s - }; - } - elsif ( UNIVERSAL::isa( $s, 'ARRAY' ) ) { - return [ - map { ref $_ ? copy_struct($_) : $_ } @$s - ]; - } - die "Cannot copy struct! : ".ref($s); - } - - return $s; -} - -=head2 locale - -=cut - -sub locale { -# -------------------------------------------------- - @_ >= 2 and shift; - $FIRMATA_LOCALE = shift; -} - -=head2 locale_path - -=cut - -sub locale_path { -# -------------------------------------------------- - @_ >= 2 and shift; - $FIRMATA_LOCALE_PATH = shift; -} - -=head2 language - -=cut - -sub language { -# -------------------------------------------------- - my $self = shift; - require Device::Firmata::Language; - return Device::Firmata::Language->language(@_); -} - -=head2 error - -=cut - -sub error { -# -------------------------------------------------- -# Handle any error messages -# - my $self = shift; - if ( @_ ) { - my $err_msg = $self->init_error->error(@_); - $self->{error} = $err_msg; - return; - } - - my $err_msg = $self->{error}; - $self->{error} = ''; - return $err_msg; -} - -=head2 init_error - -Creates the global error object that will collect -all error messages generated on the system. This -function can be called as many times as desired. - -=cut - -sub init_error { -# -------------------------------------------------- -# - $FIRMATA_ERROR and return $FIRMATA_ERROR; - - if ( $FIRMATA_ERROR_CLASS eq 'Device::Firmata::Error' ) { - require Device::Firmata::Error; - return $FIRMATA_ERROR = $FIRMATA_ERROR_CLASS; - } - -# Try and load the file. Use default if fails - eval "require $FIRMATA_ERROR_CLASS"; - $@ and return $FIRMATA_ERROR = $FIRMATA_ERROR_CLASS; - -# Try and init the error object. Use default if fails - eval { $FIRMATA_ERROR = $FIRMATA_ERROR_CLASS->new(); }; - $@ and return $FIRMATA_ERROR = $FIRMATA_ERROR_CLASS; - return $FIRMATA_ERROR; -} - -=head2 fatal - -Handle tragic and unrecoverable messages - -=cut - -sub fatal { -# -------------------------------------------------- -# - my $self = shift; - return $self->error( -1, @_ ); -} - -=head2 warn - -Handle tragic and unrecoverable messages - -=cut - -sub warn { -# -------------------------------------------------- -# - my $self = shift; - return $self->error( 0, @_ ); -} - -=head2 debug - -=cut - -sub debug { -# -------------------------------------------------- - my ( $self, $debug ) = @_; - $FIRMATA_DEBUG_LEVEL = $debug; -} - -=head2 DESTROY - -=cut - -sub DESTROY { -# -------------------------------------------------- - my $self = shift; -} - -=head2 AUTOLOAD - -=cut - -sub AUTOLOAD { -# -------------------------------------------------- - my $self = shift; - my ($attrib) = $AUTOLOAD =~ /::([^:]+)$/; - - if ( $self and UNIVERSAL::isa( $self, 'Device::Firmata::Base' ) ) { - $self->error( FIRMATA__unhandled => $attrib, join( " ", caller() ) ); - die $self->error; - } - else { - die "Tried to call function '$attrib' via object '$self' @ ", join( " ", caller(1) ), "\n"; - } - -} - -#################################################### -# Object instantiation code -#################################################### - -=head2 object_load - -Load the appropriate package and attempt to initialize -the object as well - -=cut - -sub object_load { -# -------------------------------------------------- - my $self = shift; - my $object_class = shift; - return unless $object_class =~ /^\w+(?:::\w+)*$/; # TODO ERROR MESSAGE - eval "require $object_class; 1" or die $@; - my $object = $object_class->new(@_); - return $object; -} - - -1; diff --git a/fhem/FHEM/lib/Device/Firmata/Changes b/fhem/FHEM/lib/Device/Firmata/Changes deleted file mode 100644 index ad310d6a2..000000000 --- a/fhem/FHEM/lib/Device/Firmata/Changes +++ /dev/null @@ -1,62 +0,0 @@ -Revision history for Device-Firmata - -0.64 2018.01.03 - Jens Beyer - support Firmata protocol version 2.5 feature PIN_PULLUP (Constants, Platform, Protocol) - -0.63 2016.03.19 - Jens Beyer - supported protocol version detection modified (Protocol) - -0.62 2016.02.22 - Jens Beyer - added software serial support (Platform, Protocol) - -0.61 2016.01.09 - Jens Beyer - added serial pin support (Platform, Protocol, Constants) - added protocol version query (Platform) - fixed messages_handle: REPORT_VERSION returns protocol version (Platform) - added method get_max_compatible_protocol_version (Protocol) - -0.60 2014.06.28 - Norbert Truchsess - Fixed formating of Firmata.pm as Windows line-endings break automatic install from CPAN - -0.59 2014.06.26 - Norbert Truchsess - Fix a bug in the parser incorrectly skipping single 0x30 bytes - -0.58 2014.06.26 - Yanick Champoux - cosmetic change to POD for CPAN - -0.57 2014.06.12 - Norbert Truchsess - Fixed building dist for cpan - -0.56 2014.06.04 - Norbert Truchsess - add generic method sysex_send to Platform.pl - -0.55 2014.04.17 - Norbert Truchsess - fix digital-input message interference with output pins on same port - -0.54 2014.03.04 - Norbert Truchsess - add stepper-motor protocol - -0.53 2014.03.03 - Norbert Truchsess - add rotary-encoder protocol - -0.52 2013.11.22 - Norbert Truchsess - add Firmata over Ethernet - -0.51 2013.09.10/23:00 - Brett Carroll - Changed IO.pm to use Win32::SerialPort instead of Win32::Serialport on Windows platforms - Norbert Truchsess: fix handle onewire in capability-response - -0.50 2012.12.13-2013.08.11 - Norbert Truchsess - adding all missing protocol-features (1-Wire, I2C, Servo ...) - adding observers for all suitable protocols - - Valdas Kondrotas: various bugfixes and enhancements. - - 2011.03.23 - Chris Fedde - reorganizing as CPAN ready module - - 2011.02.16 Aki Mimoto - implementig all protocol basics and releasing Device::Firmata on Github - - 2010.08.31 Aki Mimoto - start of development \ No newline at end of file diff --git a/fhem/FHEM/lib/Device/Firmata/Constants.pm b/fhem/FHEM/lib/Device/Firmata/Constants.pm deleted file mode 100644 index beabbfdab..000000000 --- a/fhem/FHEM/lib/Device/Firmata/Constants.pm +++ /dev/null @@ -1,396 +0,0 @@ -package Device::Firmata::Constants; - -=head1 NAME - -Device::Firmata::Constants - constants used in the Device::Firmata system - -=cut - -use strict; -use Exporter; -use vars qw/ - @ISA @EXPORT_OK %EXPORT_TAGS - $BASE - $COMMANDS $COMMAND_NAMES - $COMMAND_LOOKUP - /; -@ISA = 'Exporter'; - -# Basic commands and constants -use constant ( - $BASE = { - PIN_INPUT => 0, - PIN_OUTPUT => 1, - PIN_ANALOG => 2, - PIN_PWM => 3, - PIN_SERVO => 4, - PIN_SHIFT => 5, - PIN_I2C => 6, - PIN_ONEWIRE => 7, - PIN_STEPPER => 8, - PIN_ENCODER => 9, - PIN_SERIAL => 10, - PIN_PULLUP => 11, - PIN_LOW => 0, - PIN_HIGH => 1, - } -); - -# We need to apply all the available protocols -use constant ( - $COMMANDS = { - - V_2_01 => { - - MAX_DATA_BYTES => 32, # max number of data bytes in non-Sysex messages - - # message command bytes (128-255/0x80-0xFF) - DIGITAL_MESSAGE => 0x90, # send data for a digital pin - ANALOG_MESSAGE => 0xE0, # send data for an analog pin (or PWM) - REPORT_ANALOG => 0xC0, # enable analog input by pin # - REPORT_DIGITAL => 0xD0, # enable digital input by port pair - SET_PIN_MODE => 0xF4, # set a pin to INPUT/OUTPUT/PWM/etc - REPORT_VERSION => 0xF9, # report protocol version - SYSTEM_RESET => 0xFF, # reset from MIDI - START_SYSEX => 0xF0, # start a MIDI Sysex message - END_SYSEX => 0xF7, # end a MIDI Sysex message - - # extended command set using sysex (0-127/0x00-0x7F) - SERVO_CONFIG => 0x70, # set max angle, minPulse, maxPulse, freq - STRING_DATA => 0x71, # a string message with 14-bits per char - SHIFT_DATA => 0x75, # a bitstream to/from a shift register - I2C_REQUEST => 0x76, # send an I2C read/write request - I2C_REPLY => 0x77, # a reply to an I2C read request - I2C_CONFIG => 0x78, # config I2C settings such as delay times and power pins - REPORT_FIRMWARE => 0x79, # report name and version of the firmware - SAMPLING_INTERVAL => 0x7A, # set the poll rate of the main loop - SYSEX_NON_REALTIME => 0x7E, # MIDI Reserved for non-realtime messages - SYSEX_REALTIME => 0x7F, # MIDI Reserved for realtime messages - - # these are DEPRECATED to make the naming more consistent - FIRMATA_STRING => 0x71, # same as STRING_DATA - SYSEX_I2C_REQUEST => 0x76, # same as I2C_REQUEST - SYSEX_I2C_REPLY => 0x77, # same as I2C_REPLY - SYSEX_SAMPLING_INTERVAL => 0x7A, # same as SAMPLING_INTERVAL - - # pin modes - INPUT => 0x00, # digital pin in digitalOut mode - OUTPUT => 0x01, # digital pin in digitalInput mode - ANALOG => 0x02, # analog pin in analogInput mode - PWM => 0x03, # digital pin in PWM output mode - SERVO => 0x04, # digital pin in Servo output mode - SHIFT => 0x05, # shiftIn/shiftOut mode - I2C => 0x06, # pin included in I2C setup - - # Deprecated entries - deprecated => [ - qw( FIRMATA_STRING SYSEX_I2C_REQUEST SYSEX_I2C_REPLY SYSEX_SAMPLING_INTERVAL ) - ], - }, # /Constants for Version 2.1 - - V_2_02 => { - - MAX_DATA_BYTES => 32, # max number of data bytes in non-Sysex messages - - # message command bytes (128-255/0x80-0xFF) - DIGITAL_MESSAGE => 0x90, # send data for a digital pin - ANALOG_MESSAGE => 0xE0, # send data for an analog pin (or PWM) - REPORT_ANALOG => 0xC0, # enable analog input by pin # - REPORT_DIGITAL => 0xD0, # enable digital input by port pair - SET_PIN_MODE => 0xF4, # set a pin to INPUT/OUTPUT/PWM/etc - REPORT_VERSION => 0xF9, # report protocol version - SYSTEM_RESET => 0xFF, # reset from MIDI - START_SYSEX => 0xF0, # start a MIDI Sysex message - END_SYSEX => 0xF7, # end a MIDI Sysex message - - # extended command set using sysex (0-127/0x00-0x7F) - RESERVED_COMMAND => 0x00, # 2nd SysEx data byte is a chip-specific command (AVR, PIC, TI, etc). - ANALOG_MAPPING_QUERY => 0x69, # ask for mapping of analog to pin numbers - ANALOG_MAPPING_RESPONSE => 0x6A, # reply with mapping info - CAPABILITY_QUERY => 0x6B, # ask for supported modes and resolution of all pins - CAPABILITY_RESPONSE => 0x6C, # reply with supported modes and resolution - PIN_STATE_QUERY => 0x6D, # ask for a pin's current mode and value - PIN_STATE_RESPONSE => 0x6E, # reply with a pin's current mode and value - EXTENDED_ANALOG => 0x6F, # analog write (PWM, Servo, etc) to any pin - SERVO_CONFIG => 0x70, # set max angle, minPulse, maxPulse, freq - STRING_DATA => 0x71, # a string message with 14-bits per char - SHIFT_DATA => 0x75, # shiftOut config/data message (34 bits) - I2C_REQUEST => 0x76, # send an I2C read/write request - I2C_REPLY => 0x77, # a reply to an I2C read request - I2C_CONFIG => 0x78, # config I2C settings such as delay times and power pins - REPORT_FIRMWARE => 0x79, # report name and version of the firmware - SAMPLING_INTERVAL => 0x7A, # set the poll rate of the main loop - SYSEX_NON_REALTIME => 0x7E, # MIDI Reserved for non-realtime messages - SYSEX_REALTIME => 0x7F, # MIDI Reserved for realtime messages - - # pin modes - INPUT => 0x00, # digital pin in digitalOut mode - OUTPUT => 0x01, # digital pin in digitalInput mode - ANALOG => 0x02, # analog pin in analogInput mode - PWM => 0x03, # digital pin in PWM output mode - SERVO => 0x04, # digital pin in Servo output mode - SHIFT => 0x05, # shiftIn/shiftOut mode - I2C => 0x06, # pin included in I2C setup - - # Deprecated entries - deprecated => [ - qw( FIRMATA_STRING SYSEX_I2C_REQUEST SYSEX_I2C_REPLY SYSEX_SAMPLING_INTERVAL ) - ], - - }, # /Constants for Version 2.2 - - V_2_03 => { - - MAX_DATA_BYTES => 32, # max number of data bytes in non-Sysex messages - - # message command bytes (128-255/0x80-0xFF) - DIGITAL_MESSAGE => 0x90, # send data for a digital pin - ANALOG_MESSAGE => 0xE0, # send data for an analog pin (or PWM) - REPORT_ANALOG => 0xC0, # enable analog input by pin # - REPORT_DIGITAL => 0xD0, # enable digital input by port pair - SET_PIN_MODE => 0xF4, # set a pin to INPUT/OUTPUT/PWM/etc - REPORT_VERSION => 0xF9, # report protocol version - SYSTEM_RESET => 0xFF, # reset from MIDI - START_SYSEX => 0xF0, # start a MIDI Sysex message - END_SYSEX => 0xF7, # end a MIDI Sysex message - - # extended command set using sysex (0-127/0x00-0x7F) - RESERVED_COMMAND => 0x00, # 2nd SysEx data byte is a chip-specific command (AVR, PIC, TI, etc). - ANALOG_MAPPING_QUERY => 0x69, # ask for mapping of analog to pin numbers - ANALOG_MAPPING_RESPONSE => 0x6A, # reply with mapping info - CAPABILITY_QUERY => 0x6B, # ask for supported modes and resolution of all pins - CAPABILITY_RESPONSE => 0x6C, # reply with supported modes and resolution - PIN_STATE_QUERY => 0x6D, # ask for a pin's current mode and value - PIN_STATE_RESPONSE => 0x6E, # reply with a pin's current mode and value - EXTENDED_ANALOG => 0x6F, # analog write (PWM, Servo, etc) to any pin - SERVO_CONFIG => 0x70, # set max angle, minPulse, maxPulse, freq - STRING_DATA => 0x71, # a string message with 14-bits per char - SHIFT_DATA => 0x75, # shiftOut config/data message (34 bits) - I2C_REQUEST => 0x76, # send an I2C read/write request - I2C_REPLY => 0x77, # a reply to an I2C read request - I2C_CONFIG => 0x78, # config I2C settings such as delay times and power pins - REPORT_FIRMWARE => 0x79, # report name and version of the firmware - SAMPLING_INTERVAL => 0x7A, # set the poll rate of the main loop - SYSEX_NON_REALTIME => 0x7E, # MIDI Reserved for non-realtime messages - SYSEX_REALTIME => 0x7F, # MIDI Reserved for realtime messages - - # pin modes - INPUT => 0x00, # digital pin in digitalOut mode - OUTPUT => 0x01, # digital pin in digitalInput mode - ANALOG => 0x02, # analog pin in analogInput mode - PWM => 0x03, # digital pin in PWM output mode - SERVO => 0x04, # digital pin in Servo output mode - SHIFT => 0x05, # shiftIn/shiftOut mode - I2C => 0x06, # pin included in I2C setup - - # Deprecated entries - deprecated => [ - qw( FIRMATA_STRING SYSEX_I2C_REQUEST SYSEX_I2C_REPLY SYSEX_SAMPLING_INTERVAL ) - ], - - }, # /Constants for Version 2.3 (same as V_2_02) - - V_2_04 => { - - MAX_DATA_BYTES => 64, # max number of data bytes in non-Sysex messages - - # message command bytes (128-255/0x80-0xFF) - DIGITAL_MESSAGE => 0x90, # send data for a digital pin - ANALOG_MESSAGE => 0xE0, # send data for an analog pin (or PWM) - REPORT_ANALOG => 0xC0, # enable analog input by pin # - REPORT_DIGITAL => 0xD0, # enable digital input by port pair - SET_PIN_MODE => 0xF4, # set a pin to INPUT/OUTPUT/PWM/etc - REPORT_VERSION => 0xF9, # report protocol version - SYSTEM_RESET => 0xFF, # reset from MIDI - START_SYSEX => 0xF0, # start a MIDI Sysex message - END_SYSEX => 0xF7, # end a MIDI Sysex message - - # extended command set using sysex (0-127/0x00-0x7F) - RESERVED_COMMAND => 0x00, # 2nd SysEx data byte is a chip-specific command (AVR, PIC, TI, etc). - ANALOG_MAPPING_QUERY => 0x69, # ask for mapping of analog to pin numbers - ANALOG_MAPPING_RESPONSE => 0x6A, # reply with mapping info - CAPABILITY_QUERY => 0x6B, # ask for supported modes and resolution of all pins - CAPABILITY_RESPONSE => 0x6C, # reply with supported modes and resolution - PIN_STATE_QUERY => 0x6D, # ask for a pin's current mode and value - PIN_STATE_RESPONSE => 0x6E, # reply with a pin's current mode and value - EXTENDED_ANALOG => 0x6F, # analog write (PWM, Servo, etc) to any pin - SERVO_CONFIG => 0x70, # set max angle, minPulse, maxPulse, freq - STRING_DATA => 0x71, # a string message with 14-bits per char - STEPPER_DATA => 0x72, # control a stepper motor - ONEWIRE_DATA => 0x73, # OneWire read/write/reset/select/skip/search request + read/search reply - SHIFT_DATA => 0x75, # shiftOut config/data message (34 bits) - I2C_REQUEST => 0x76, # send an I2C read/write request - I2C_REPLY => 0x77, # a reply to an I2C read request - I2C_CONFIG => 0x78, # config I2C settings such as delay times and power pins - REPORT_FIRMWARE => 0x79, # report name and version of the firmware - SAMPLING_INTERVAL => 0x7A, # set the poll rate of the main loop - SCHEDULER_DATA => 0x7B, # createtask/deletetask/addtotask/schedule/querytasks/querytask request and querytasks/querytask reply - SYSEX_NON_REALTIME => 0x7E, # MIDI Reserved for non-realtime messages - SYSEX_REALTIME => 0x7F, # MIDI Reserved for realtime messages - - # pin modes - INPUT => 0x00, # digital pin in digitalOut mode - OUTPUT => 0x01, # digital pin in digitalInput mode - ANALOG => 0x02, # analog pin in analogInput mode - PWM => 0x03, # digital pin in PWM output mode - SERVO => 0x04, # digital pin in Servo output mode - SHIFT => 0x05, # shiftIn/shiftOut mode - I2C => 0x06, # pin included in I2C setup - ONEWIRE => 0x07, # pin configured for 1-Wire commuication - STEPPER => 0x08, # pin configured for stepper motor - - # Deprecated entries - deprecated => [ - qw( FIRMATA_STRING SYSEX_I2C_REQUEST SYSEX_I2C_REPLY SYSEX_SAMPLING_INTERVAL ) - ], - }, # /Constants for Version 2.4 - - V_2_05 => { - - MAX_DATA_BYTES => 64, # max number of data bytes in non-Sysex messages - - # message command bytes (128-255/0x80-0xFF) - DIGITAL_MESSAGE => 0x90, # send data for a digital pin - ANALOG_MESSAGE => 0xE0, # send data for an analog pin (or PWM) - REPORT_ANALOG => 0xC0, # enable analog input by pin # - REPORT_DIGITAL => 0xD0, # enable digital input by port pair - SET_PIN_MODE => 0xF4, # set a pin to INPUT/OUTPUT/PWM/etc - REPORT_VERSION => 0xF9, # report protocol version - SYSTEM_RESET => 0xFF, # reset from MIDI - START_SYSEX => 0xF0, # start a MIDI Sysex message - END_SYSEX => 0xF7, # end a MIDI Sysex message - - # extended command set using sysex (0-127/0x00-0x7F) - RESERVED_COMMAND => 0x00, # 2nd SysEx data byte is a chip-specific command (AVR, PIC, TI, etc). - SERIAL_DATA => 0x60, # serial port config/write/read/close/flush/listen request and read reply - ENCODER_DATA => 0x61, # receive rotary-encoders current positions - ANALOG_MAPPING_QUERY => 0x69, # ask for mapping of analog to pin numbers - ANALOG_MAPPING_RESPONSE => 0x6A, # reply with mapping info - CAPABILITY_QUERY => 0x6B, # ask for supported modes and resolution of all pins - CAPABILITY_RESPONSE => 0x6C, # reply with supported modes and resolution - PIN_STATE_QUERY => 0x6D, # ask for a pin's current mode and value - PIN_STATE_RESPONSE => 0x6E, # reply with a pin's current mode and value - EXTENDED_ANALOG => 0x6F, # analog write (PWM, Servo, etc) to any pin - SERVO_CONFIG => 0x70, # set max angle, minPulse, maxPulse, freq - STRING_DATA => 0x71, # a string message with 14-bits per char - STEPPER_DATA => 0x72, # control a stepper motor - ONEWIRE_DATA => 0x73, # OneWire read/write/reset/select/skip/search request + read/search reply - SHIFT_DATA => 0x75, # shiftOut config/data message (34 bits) - I2C_REQUEST => 0x76, # send an I2C read/write request - I2C_REPLY => 0x77, # a reply to an I2C read request - I2C_CONFIG => 0x78, # config I2C settings such as delay times and power pins - REPORT_FIRMWARE => 0x79, # report name and version of the firmware - SAMPLING_INTERVAL => 0x7A, # set the poll rate of the main loop - SCHEDULER_DATA => 0x7B, # createtask/deletetask/addtotask/schedule/querytasks/querytask request and querytasks/querytask reply - SYSEX_NON_REALTIME => 0x7E, # MIDI Reserved for non-realtime messages - SYSEX_REALTIME => 0x7F, # MIDI Reserved for realtime messages - - # pin modes - INPUT => 0x00, # digital pin in digitalOut mode - OUTPUT => 0x01, # digital pin in digitalInput mode - ANALOG => 0x02, # analog pin in analogInput mode - PWM => 0x03, # digital pin in PWM output mode - SERVO => 0x04, # digital pin in Servo output mode - SHIFT => 0x05, # shiftIn/shiftOut mode - I2C => 0x06, # pin included in I2C setup - ONEWIRE => 0x07, # pin configured for 1-Wire commuication - STEPPER => 0x08, # pin configured for stepper motor - SERIAL => 0x0A, # pin configured for serial port - PULLUP => 0x0B, # digital pin in digitalInput mode with pullup - - # Deprecated entries - deprecated => [ - qw( FIRMATA_STRING SYSEX_I2C_REQUEST SYSEX_I2C_REPLY SYSEX_SAMPLING_INTERVAL ) - ], - - }, # /Constants for Version 2.5 - - V_2_06 => { - - MAX_DATA_BYTES => 64, # max number of data bytes in non-Sysex messages - - # message command bytes (128-255/0x80-0xFF) - DIGITAL_MESSAGE => 0x90, # send data for a digital pin - ANALOG_MESSAGE => 0xE0, # send data for an analog pin (or PWM) - REPORT_ANALOG => 0xC0, # enable analog input by pin # - REPORT_DIGITAL => 0xD0, # enable digital input by port pair - SET_PIN_MODE => 0xF4, # set a pin to INPUT/OUTPUT/PWM/etc - REPORT_VERSION => 0xF9, # report protocol version - SYSTEM_RESET => 0xFF, # reset from MIDI - START_SYSEX => 0xF0, # start a MIDI Sysex message - END_SYSEX => 0xF7, # end a MIDI Sysex message - - # extended command set using sysex (0-127/0x00-0x7F) - RESERVED_COMMAND => 0x00, # 2nd SysEx data byte is a chip-specific command (AVR, PIC, TI, etc). - SERIAL_DATA => 0x60, # serial port config/write/read/close/flush/listen request and read reply - ENCODER_DATA => 0x61, # receive rotary-encoders current positions - ANALOG_MAPPING_QUERY => 0x69, # ask for mapping of analog to pin numbers - ANALOG_MAPPING_RESPONSE => 0x6A, # reply with mapping info - CAPABILITY_QUERY => 0x6B, # ask for supported modes and resolution of all pins - CAPABILITY_RESPONSE => 0x6C, # reply with supported modes and resolution - PIN_STATE_QUERY => 0x6D, # ask for a pin's current mode and value - PIN_STATE_RESPONSE => 0x6E, # reply with a pin's current mode and value - EXTENDED_ANALOG => 0x6F, # analog write (PWM, Servo, etc) to any pin - SERVO_CONFIG => 0x70, # set max angle, minPulse, maxPulse, freq - STRING_DATA => 0x71, # a string message with 14-bits per char - STEPPER_DATA => 0x72, # control a stepper motor - ONEWIRE_DATA => 0x73, # OneWire read/write/reset/select/skip/search request + read/search reply - SHIFT_DATA => 0x75, # shiftOut config/data message (34 bits) - I2C_REQUEST => 0x76, # send an I2C read/write request - I2C_REPLY => 0x77, # a reply to an I2C read request - I2C_CONFIG => 0x78, # config I2C settings such as delay times and power pins - REPORT_FIRMWARE => 0x79, # report name and version of the firmware - SAMPLING_INTERVAL => 0x7A, # set the poll rate of the main loop - SCHEDULER_DATA => 0x7B, # createtask/deletetask/addtotask/schedule/querytasks/querytask request and querytasks/querytask reply - SYSEX_NON_REALTIME => 0x7E, # MIDI Reserved for non-realtime messages - SYSEX_REALTIME => 0x7F, # MIDI Reserved for realtime messages - - # pin modes - INPUT => 0x00, # digital pin in digitalOut mode - OUTPUT => 0x01, # digital pin in digitalInput mode - ANALOG => 0x02, # analog pin in analogInput mode - PWM => 0x03, # digital pin in PWM output mode - SERVO => 0x04, # digital pin in Servo output mode - SHIFT => 0x05, # shiftIn/shiftOut mode - I2C => 0x06, # pin included in I2C setup - ONEWIRE => 0x07, # pin configured for 1-Wire commuication - STEPPER => 0x08, # pin configured for stepper motor - ENCODER => 0x09, # pin configured for rotary-encoders - SERIAL => 0x0A, # pin configured for serial port - PULLUP => 0x0B, # digital pin in digitalInput mode with pullup - - # Deprecated entries - deprecated => [ - qw( FIRMATA_STRING SYSEX_I2C_REQUEST SYSEX_I2C_REPLY SYSEX_SAMPLING_INTERVAL ) - ], - - }, # /Constants for Version 2.6 - } -); - -# Handle the reverse lookups of the protocol -$COMMAND_LOOKUP = {}; -while ( my ( $protocol_version, $protocol_commands ) = each %$COMMANDS ) { - my $protocol_lookup = $COMMAND_LOOKUP->{$protocol_version} = {}; - my $deprecated = $protocol_lookup->{deprecated} || []; - my $deprecated_lookup = { map { ( $_ => 1 ) } @$deprecated }; - while ( my ( $protocol_command, $command_value ) = each %$protocol_commands ) { - next if $protocol_command eq 'deprecated'; - next if $deprecated_lookup->{$protocol_command}; - $protocol_lookup->{$command_value} = $protocol_command; - } -} - -# Now we consolidate all the string keynames into a single master list. -use constant ( $COMMAND_NAMES = { map { map { ( $_ => $_ ) } keys %$_ } values %$COMMANDS } ); -use constant { COMMAND_NAMES => [ $COMMAND_NAMES = [ keys %$COMMAND_NAMES ] ] }; - -@EXPORT_OK = ( - @$COMMAND_NAMES, keys %$BASE, - keys %$COMMANDS, - qw( $COMMANDS $COMMAND_NAMES $COMMAND_LOOKUP ), - ); - -%EXPORT_TAGS = ( all => \@EXPORT_OK ); - -1; diff --git a/fhem/FHEM/lib/Device/Firmata/Error.pm b/fhem/FHEM/lib/Device/Firmata/Error.pm deleted file mode 100644 index d086f567b..000000000 --- a/fhem/FHEM/lib/Device/Firmata/Error.pm +++ /dev/null @@ -1,92 +0,0 @@ -package Device::Firmata::Error; -# ================================================================== - -=head1 NAME - -Device::Firmata::Error - Error handlers - -=cut - -use strict; -use Exporter; -use vars qw/ - @ISA - %ERRORS - @EXPORT - $FIRMATA_ERROR_DEFAULT - @ERROR_STACK - /; -use Device::Firmata::Base; - -@ISA = 'Exporter'; - -@EXPORT = qw(); - -$FIRMATA_ERROR_DEFAULT = -1; - - -=head2 error - -The base error reporting system. All errors will be -stored in this object until the error flush code is called. -This will allow the system to collect all errors that occur -in various parts of the system in one place. Very useful -for error reporting since it's a simple call to find -out the last error. - -Invocation of this function - - $err->error( [numerical error level], ErrorMessage, ... parameters ... ); - -ErrorMessage can be in the format "KEY" that will be referenced by -Device::Firmata::Base->language or "KEY:Message" where if ->language does -not map to anything, the error will default to Message - -=cut - -sub error { -# -------------------------------------------------- -# - my $self = shift; - my $error_level = $_[0] =~ /^\-?\d+$/ ? shift : $FIRMATA_ERROR_DEFAULT; - my $message = shift; - my $error_code; - if ( $message =~ /^([A-Z0-9_]+)\s*:\s*/ ) { - $error_code = $1; - } - else { - $error_code = $message; - }; - my $text = Device::Firmata::Base->language($message,@_); - push @ERROR_STACK, [ $text, $error_level, $text ]; - - if ( $error_level < 1 ) { - my $i = 1; - my ( $pkg, $fn, $line ); - -# Proceed up the call stack until we find out where the error likely occured (ie. Not in Device::Firmata::Base) - do { ( $pkg, $fn, $line ) = caller($i); $i++; } while ( $pkg eq 'Device::Firmata::Base' ); - - $error_level < 0 ? die "\@$fn:$pkg:$line". ' : ' . $text . "\n" - : warn "\@$fn:$pkg:$line". ' : ' . $text . "\n"; - }; - -# warn "Error called with args: @_ from " . join( " ", caller() ) . "\n"; -# require Carp; -# Carp::cluck(); - - return $text; -} - - -=head2 errors_flush - -=cut - -sub errors_flush { -# -------------------------------------------------- - @ERROR_STACK = (); -} - - -1; diff --git a/fhem/FHEM/lib/Device/Firmata/IO/NetIO.pm b/fhem/FHEM/lib/Device/Firmata/IO/NetIO.pm deleted file mode 100644 index b33c2f2be..000000000 --- a/fhem/FHEM/lib/Device/Firmata/IO/NetIO.pm +++ /dev/null @@ -1,203 +0,0 @@ -package Device::Firmata::IO::NetIO; - -use strict; -use warnings; -use IO::Socket::INET; -use IO::Select; - -use vars qw//; -use Device::Firmata::Base - ISA => 'Device::Firmata::Base', - FIRMATA_ATTRIBS => { - }; - -sub listen { -# -------------------------------------------------- - my ( $pkg, $ip, $port, $opts ) = @_; - - my $self = ref $pkg ? $pkg : $pkg->new($opts); - - # flush after every write - $| = 1; - - my $socket; - - # creating object interface of IO::Socket::INET modules which internally does - # socket creation, binding and listening at the specified port address. - $socket = new IO::Socket::INET ( - LocalHost => $ip, - LocalPort => $port, - Proto => 'tcp', - Listen => 5, - Reuse => 1 - ) or die "ERROR in Socket Creation : $!\n"; - - $self->{'socket'} = $socket; - return $self; -} - -sub accept { - - my ($self,$timeout) = @_; - # waiting for new client connection. - my $s = $self->{'select'}; - if (!($s)) { - $s = IO::Select->new(); - $s->add($self->{'socket'}); - $self->{'select'} = $s; - } - if(my @ready = $s->can_read($timeout)) { - my $socket = $self->{'socket'}; - foreach my $fh (@ready) { - if ($fh == $socket) { - if (my $client_socket = $socket->accept()) { - return $self->attach($client_socket); - } - } - } - } - return undef; -} - -sub close { - my $self = shift; - if ($self->{'select'} && $self->{'socket'}) { - $self->{'select'}->remove($self->{'socket'}); - delete $self->{'select'}; - } - if ($self->{'socket'}) { - $self->{'socket'}->close(); - delete $self->{'socket'}; - } - if ($self->{clients}) { - foreach my $client (@{$self->{clients}}) { - $client->close(); - } - delete $self->{clients}; - } -} - -sub attach { - my ( $pkg, $client_socket, $opts ) = @_; - - my $self = ref $pkg ? $pkg : $pkg->new($opts); - - my $clientpackage = "Device::Firmata::IO::NetIO::Client"; - eval "require $clientpackage"; - - my $clientio = $clientpackage->attach($client_socket); - - my $package = "Device::Firmata::Platform"; - eval "require $package"; - my $platform = $package->attach( $clientio, $opts ) or die "Could not connect to Firmata Server"; - - my $s = $self->{'select'}; - if (!($s)) { - $s = IO::Select->new(); - $self->{'select'} = $s; - } - $s->add($client_socket); - my $clients = $self->{clients}; - if (!($clients)) { - $clients = []; - $self->{clients} = $clients; - } - push $clients, $platform; - - # Figure out what platform we're running on - $platform->probe(); - - return $platform; -} - -sub poll { - my ($self,$timeout) = @_; - my $s = $self->{'select'}; - return unless $s; - if(my @ready = $s->can_read($timeout)) { - my $socket = $self->{'socket'}; - my $clients = $self->{clients}; - if (! defined($clients)) { - $clients = []; - $self->{clients} = $clients; - } - my @readyclients = (); - foreach my $fh (@ready) { - if ($fh != $socket) { - push @readyclients, grep { $fh == $_->{io}->{client}; } @$clients; - } - } - foreach my $readyclient (@readyclients) { - $readyclient->poll(); - } - } -} - -package Device::Firmata::IO::NetIO::Client; - -use strict; -use warnings; -use IO::Socket::INET; - -use vars qw//; -use Device::Firmata::Base - ISA => 'Device::Firmata::Base', - FIRMATA_ATTRIBS => { - }; - -sub attach { - my ( $pkg, $client_socket, $opts ) = @_; - - my $self = ref $pkg ? $pkg : $pkg->new($opts); - - $self->{client} = $client_socket; - - return $self; -} - -=head2 data_write - -Dump a bunch of data into the comm port - -=cut - -sub data_write { -# -------------------------------------------------- - my ( $self, $buf ) = @_; - $Device::Firmata::DEBUG and print ">".join(",",map{sprintf"%02x",ord$_}split//,$buf)."\n"; - return $self->{client}->write( $buf ); -} - - -=head2 data_read - -We fetch up to $bytes from the comm port -This function is non-blocking - -=cut - -sub data_read { -# -------------------------------------------------- - my ( $self, $bytes ) = @_; - my ($buf, $res); - $res = $self->{client}->sysread($buf, 512); - $buf = "" if(!defined($res)); - - if ( $Device::Firmata::DEBUG and $buf ) { - print "<".join(",",map{sprintf"%02x",ord$_}split//,$buf)."\n"; - } - return $buf; -} - -=head2 close - -close the underlying connection - -=cut - -sub close { - my $self = shift; - $self->{client}->close() if (($self->{client}) and $self->{client}->connected()); -} - -1; diff --git a/fhem/FHEM/lib/Device/Firmata/IO/SerialIO.pm b/fhem/FHEM/lib/Device/Firmata/IO/SerialIO.pm deleted file mode 100644 index e33c7e5f4..000000000 --- a/fhem/FHEM/lib/Device/Firmata/IO/SerialIO.pm +++ /dev/null @@ -1,77 +0,0 @@ -package Device::Firmata::IO::SerialIO; - -=head1 NAME - -Device::Firmata::IO::SerialIO - implement the low level serial IO - -=cut - -use strict; -use warnings; - -use vars qw/ $SERIAL_CLASS /; -use Device::Firmata::Base - ISA => 'Device::Firmata::Base', - FIRMATA_ATTRIBS => { - handle => undef, - baudrate => 57600, - }; - -$SERIAL_CLASS = $^O eq 'MSWin32' ? 'Win32::SerialPort' - : 'Device::SerialPort'; -eval "require $SERIAL_CLASS"; - - -=head2 open - -=cut - -sub open { -# -------------------------------------------------- - my ( $pkg, $serial_port, $opts ) = @_; - my $self = ref $pkg ? $pkg : $pkg->new($opts); - my $serial_obj = $SERIAL_CLASS->new( $serial_port, 1, 0 ) or return; - $self->attach($serial_obj,$opts); - $self->{handle}->baudrate($self->{baudrate}); - $self->{handle}->databits(8); - $self->{handle}->stopbits(1); - return $self; -} - -sub attach { - my ( $pkg, $serial_obj, $opts ) = @_; - my $self = ref $pkg ? $pkg : $pkg->new($opts); - $self->{handle} = $serial_obj; - return $self; -} - -=head2 data_write - -Dump a bunch of data into the comm port - -=cut - -sub data_write { -# -------------------------------------------------- - my ( $self, $buf ) = @_; - $Device::Firmata::DEBUG and print ">".join(",",map{sprintf"%02x",ord$_}split//,$buf)."\n"; - return $self->{handle}->write( $buf ); -} - - -=head2 data_read - -We fetch up to $bytes from the comm port -This function is non-blocking - -=cut - -sub data_read { -# -------------------------------------------------- - my ( $self, $bytes ) = @_; - my ( $count, $string ) = $self->{handle}->read($bytes); - print "<".join(",",map{sprintf"%02x",ord$_}split//,$string)."\n" if ( $Device::Firmata::DEBUG and $string ); - return $string; -} - -1; diff --git a/fhem/FHEM/lib/Device/Firmata/Language.pm b/fhem/FHEM/lib/Device/Firmata/Language.pm deleted file mode 100644 index 884897449..000000000 --- a/fhem/FHEM/lib/Device/Firmata/Language.pm +++ /dev/null @@ -1,106 +0,0 @@ -package Device::Firmata::Language; -# ================================================================== - -=head1 NAME - -Device::Firmata::Language - Localization - -=cut - -use strict; -use vars qw/ - $FIRMATA_LOCALE - $FIRMATA_LOCALE_PATH - $FIRMATA_LOCALE_MESSAGES - /; -use Device::Firmata::Base - ISA => 'Device::Firmata::Base', - FIRMATA_ATTRIBS => { - messages => {}, - }; - -$FIRMATA_LOCALE_MESSAGES = { -}; -$FIRMATA_LOCALE = 'en'; -$FIRMATA_LOCALE_PATH = '.'; - - -=head2 numbers - -=cut - -sub numbers { -# -------------------------------------------------- -} - - -=head2 date - -=cut - -sub date { -# -------------------------------------------------- -} - - -=head2 language - -=cut - -sub language { -# -------------------------------------------------- - my $self = shift; - - my $messages = $FIRMATA_LOCALE_MESSAGES->{$FIRMATA_LOCALE} ||= do { - my $target_fpath = "$FIRMATA_LOCALE_PATH/$FIRMATA_LOCALE.txt"; - - my $m; - require Symbol; - my $fh = Symbol::gensym(); - - if ( -f $target_fpath ) { - open $fh, "<$target_fpath" or die $!; - } - else { - $fh = \*DATA; - } - - while ( my $l = <$fh> ) { - next if $l =~ /^\s*$/; - $l =~ /([^\s]*)\s+(.*)/; - ( $m ||= {} )->{$1} = $2; - } - close $fh; - $m; - }; - -# This will parse messages coming through such that it will -# be possible to encode a language string with a code in the -# following formats: -# -# ->language( "CODE", $parametrs ... ) -# ->language( "CODE:Default Message %s", $parametrs ... ) -# - my $message = shift or return; - $message =~ s/^([\w_]+)\s*:?\s*//; - my $key = $1; - my $message_template; - -# Get the message template in the following order: -# 1. The local object if available -# 2. The global message object -# 3. The provided default message -# - ref $self and $message_template = $self->{messages}{$key}; - $message_template ||= $messages->{$key} || $message; - return sprintf( $message_template, @_ ); -} - -1; - -__DATA__ -FIRMATA__unhandled Unhandled attribute '%s' called -FIRMATA__unknown Unknown/Unhandled error encountered: %s - -FIRMATA__separator , - diff --git a/fhem/FHEM/lib/Device/Firmata/Platform.pm b/fhem/FHEM/lib/Device/Firmata/Platform.pm deleted file mode 100644 index 0ed53ffc9..000000000 --- a/fhem/FHEM/lib/Device/Firmata/Platform.pm +++ /dev/null @@ -1,1025 +0,0 @@ -package Device::Firmata::Platform; - -=head1 NAME - -Device::Firmata::Platform - Platform specifics - -=cut - -use strict; -use Time::HiRes qw/time/; -use Device::Firmata::Constants qw/ :all /; -use Device::Firmata::Protocol; -use Device::Firmata::Base - ISA => 'Device::Firmata::Base', - FIRMATA_ATTRIBS => { - - # Object handlers - io => undef, - protocol => undef, - - # Used for internal tracking of events/parameters - #protocol_version => undef, - #sysex_mode => undef, - sysex_data => [], - - # To track internal status - analog_pins => [], - analog_resolutions => {}, - pwm_resolutions => {}, - servo_resolutions => {}, - stepper_resolutions => {}, - encoder_resolutions => {}, - serial_resolutions => {}, - ports => [], - input_ports => [], - pins => {}, - pin_modes => {}, - encoders => [], - - # To notify on events - digital_observer => [], - analog_observer => [], - sysex_observer => undef, - i2c_observer => undef, - onewire_observer => [], - stepper_observer => [], - encoder_observer => [], - serial_observer => [], - scheduler_observer => undef, - string_observer => undef, - - # To track scheduled tasks - tasks => [], - - # For information about the device. eg: firmware version - metadata => {}, - - # latest STRING_DATA response: - stringresponse => {}, - }; - -=head2 open - -Connect to the IO port and do some basic operations -to find out how to connect to the device - -=cut - -sub attach { - # -------------------------------------------------- - # Attach to an open IO port and do some basic operations - # to find out how to connect to the device - # - my ( $pkg, $port, $opts ) = @_; - my $self = ref $pkg ? $pkg : $pkg->new($opts); - $self->{io} = $port or return; - $self->{protocol} = Device::Firmata::Protocol->new($opts) or return; - return $self; -} - -sub detach { - my $self = shift; - delete $self->{io} if ($self->{io}); - delete $self->{protocol} if ($self->{protocol}); - $self->{sysex_data} = []; - $self->{analog_pins} = []; - $self->{ports} = []; - $self->{input_ports} = []; - $self->{pins} = {}; - $self->{pin_modes} = {}; - $self->{digital_observer} = []; - $self->{analog_observer} = []; - $self->{sysex_observer} = undef; - $self->{i2c_observer} = undef; - $self->{onewire_observer} = []; - $self->{stepper_observer} = []; - $self->{encoder_observer} = []; - $self->{serial_observer} = []; - $self->{scheduler_observer} = undef; - $self->{tasks} = []; - $self->{metadata} = {}; -} - -sub close { - my $self = shift; - $self->{io}->close(); - $self->detach(); -} - -sub system_reset { - my $self = shift; - $self->{io}->data_write($self->{protocol}->message_prepare( SYSTEM_RESET => 0 )); - $self->{sysex_data} = []; - $self->{analog_pins} = []; - $self->{ports} = []; - $self->{pins} = {}; - $self->{pin_modes} = {}; - $self->{digital_observer} = []; - $self->{analog_observer} = []; - $self->{sysex_observer} = undef; - $self->{i2c_observer} = undef; - $self->{onewire_observer} = []; - $self->{stepper_observer} = []; - $self->{encoder_observer} = []; - $self->{serial_observer} = []; - $self->{scheduler_observer} = undef; - $self->{tasks} = []; - $self->{metadata} = {}; -} - -=head2 messages_handle - -Receive identified message packets and convert them -into their appropriate structures and parse -them as required - -=cut - -sub messages_handle { - # -------------------------------------------------- - my ( $self, $messages ) = @_; - return unless $messages; - return unless @$messages; - # Now, handle the messages - my $proto = $self->{protocol}; - for my $message (@$messages) { - my $command = $message->{command_str}; - my $data = $message->{data}; - COMMAND_HANDLE: { - #* digital I/O message 0x90 port LSB(bits 0-6) MSB(bits 7-13) - # Handle pin messages - $command eq 'DIGITAL_MESSAGE' and do { - my $port_number = $message->{command} & 0x0f; - my $port_state = $data->[0] | ( $data->[1] << 7 ); - my $old_state = $self->{input_ports}[$port_number] ||= 0; - my $observers = $self->{digital_observer}; - my $pinbase = $port_number << 3; - for ( my $i = 0 ; $i < 8 ; $i++ ) { - my $pin = $pinbase + $i; - my $observer = $observers->[$pin]; - if ($observer) { - my $pin_mask = 1 << $i; - $observer->{method}( - $pin, - ( $old_state & $pin_mask ) > 0 ? 1 : 0, - ( $port_state & $pin_mask ) > 0 ? 1 : 0, - $observer->{context} - ); - } - } - $self->{input_ports}[$port_number] = $port_state; - }; - - # Handle analog pin messages - $command eq 'ANALOG_MESSAGE' and do { - my $pin_number = $message->{command} & 0x0f; - my $pin_value = ( $data->[0] | ( $data->[1] << 7 ) ); - if (defined $self->{metadata}{analog_mappings}) { - $pin_number = $self->{metadata}{analog_mappings}{$pin_number}; - } - my $observer = $self->{analog_observer}[$pin_number]; - if ($observer) { - my $old_value = $self->{analog_pins}[$pin_number]; - if ( !defined $old_value or !($old_value eq $pin_value) ) { - $observer->{method}( $pin_number, $old_value, $pin_value, $observer->{context} ); - } - } - $self->{analog_pins}[$pin_number] = $pin_value; - }; - - # Handle metadata information - $command eq 'REPORT_VERSION' and do { - $self->{metadata}{protocol_version} = sprintf "V_%i_%02i", - @$data; - last; - }; - - # SYSEX handling - $command eq 'START_SYSEX' and do { last; }; - - $command eq 'DATA_SYSEX' and do { - my $sysex_data = $self->{sysex_data}; - push @$sysex_data, @$data; - last; - }; - - $command eq 'END_SYSEX' and do { - my $sysex_data = $self->{sysex_data}; - my $sysex_message = $proto->sysex_parse($sysex_data); - if ( defined $sysex_message ) { - my $observer = $self->{sysex_observer}; - if (defined $observer) { - $observer->{method} ($sysex_message, $observer->{context}); - } - $self->sysex_handle($sysex_message); - } - $self->{sysex_data} = []; - last; - }; - } - $Device::Firmata::DEBUG and print " < $command\n"; - } -} - -=head2 sysex_handle - -Receive identified sysex packets and convert them -into their appropriate structures and parse -them as required - -=cut - -sub sysex_handle { - # -------------------------------------------------- - my ( $self, $sysex_message ) = @_; - my $data = $sysex_message->{data}; - - COMMAND_HANDLER: { - $sysex_message->{command_str} eq 'REPORT_FIRMWARE' and do { - $self->{metadata}{firmware_version} = sprintf "V_%i_%02i", $data->{major_version}, $data->{minor_version}; - $self->{metadata}{firmware} = $data->{firmware}; - last; - }; - - $sysex_message->{command_str} eq 'CAPABILITY_RESPONSE' and do { - my $capabilities = $data->{capabilities}; - $self->{metadata}{capabilities} = $capabilities; - my @analogpins; - my @inputpins; - my @outputpins; - my @pwmpins; - my @servopins; - my @shiftpins; - my @i2cpins; - my @onewirepins; - my @stepperpins; - my @encoderpins; - my @serialpins; - my @pulluppins; - - foreach my $pin (keys %$capabilities) { - if (defined $capabilities->{$pin}) { - if ($capabilities->{$pin}->{PIN_INPUT+0}) { - push @inputpins, $pin; - } - if ($capabilities->{$pin}->{PIN_OUTPUT+0}) { - push @outputpins, $pin; - } - if ($capabilities->{$pin}->{PIN_ANALOG+0}) { - push @analogpins, $pin; - $self->{metadata}{analog_resolutions}{$pin} = $capabilities->{$pin}->{PIN_ANALOG+0}->{resolution}; - } - if ($capabilities->{$pin}->{PIN_PWM+0}) { - push @pwmpins, $pin; - $self->{metadata}{pwm_resolutions}{$pin} = $capabilities->{$pin}->{PIN_PWM+0}->{resolution}; - } - if ($capabilities->{$pin}->{PIN_SERVO+0}) { - push @servopins, $pin; - $self->{metadata}{servo_resolutions}{$pin} = $capabilities->{$pin}->{PIN_SERVO+0}->{resolution}; - } - if ($capabilities->{$pin}->{PIN_SHIFT+0}) { - push @shiftpins, $pin; - } - if ($capabilities->{$pin}->{PIN_I2C+0}) { - push @i2cpins, $pin; - } - if ($capabilities->{$pin}->{PIN_ONEWIRE+0}) { - push @onewirepins, $pin; - } - if ($capabilities->{$pin}->{PIN_STEPPER+0}) { - push @stepperpins, $pin; - $self->{metadata}{stepper_resolutions}{$pin} = $capabilities->{$pin}->{PIN_STEPPER+0}->{resolution}; - } - if ($capabilities->{$pin}->{PIN_ENCODER+0}) { - push @encoderpins, $pin; - $self->{metadata}{encoder_resolutions}{$pin} = $capabilities->{$pin}->{PIN_ENCODER+0}->{resolution}; - } - if ($capabilities->{$pin}->{PIN_SERIAL+0}) { - push @serialpins, $pin; - $self->{metadata}{serial_resolutions}{$pin} = $capabilities->{$pin}->{PIN_SERIAL+0}->{resolution}; - } - if ($capabilities->{$pin}->{PIN_PULLUP+0}) { - push @pulluppins, $pin; - } - } - } - $self->{metadata}{input_pins} = \@inputpins; - $self->{metadata}{output_pins} = \@outputpins; - $self->{metadata}{analog_pins} = \@analogpins; - $self->{metadata}{pwm_pins} = \@pwmpins; - $self->{metadata}{servo_pins} = \@servopins; - $self->{metadata}{shift_pins} = \@shiftpins; - $self->{metadata}{i2c_pins} = \@i2cpins; - $self->{metadata}{onewire_pins} = \@onewirepins; - $self->{metadata}{stepper_pins} = \@stepperpins; - $self->{metadata}{encoder_pins} = \@encoderpins; - $self->{metadata}{serial_pins} = \@serialpins; - $self->{metadata}{pullup_pins} = \@pulluppins; - last; - }; - - $sysex_message->{command_str} eq 'ANALOG_MAPPING_RESPONSE' and do { - $self->{metadata}{analog_mappings} = $data->{mappings}; - last; - }; - - $sysex_message->{command_str} eq 'PIN_STATE_RESPONSE' and do { - if (!defined $self->{metadata}{pinstates}) { - $self->{metadata}{pinstates} = {}; - }; - $self->{metadata}{pinstates}{ $data->{pin} } = { - mode => $data->{mode}, - state => $data->{state}, - }; - last; - }; - - $sysex_message->{command_str} eq 'I2C_REPLY' and do { - my $observer = $self->{i2c_observer}; - if (defined $observer) { - $observer->{method}( $data, $observer->{context} ); - } - last; - }; - - $sysex_message->{command_str} eq 'ONEWIRE_DATA' and do { - my $pin = $data->{pin}; - my $observer = $self->{onewire_observer}[$pin]; - if (defined $observer) { - $observer->{method}( $data, $observer->{context} ); - } - last; - }; - - $sysex_message->{command_str} eq 'SCHEDULER_DATA' and do { - my $observer = $self->{scheduler_observer}; - if (defined $observer) { - $observer->{method}( $data, $observer->{context} ); - } - last; - }; - - $sysex_message->{command_str} eq 'STRING_DATA' and do { - my $observer = $self->{string_observer}; - $self->{stringresponse} = $data->{string}; - if (defined $observer) { - $observer->{method}( $data->{string}, $observer->{context} ); - } - last; - }; - - $sysex_message->{command_str} eq 'STEPPER_DATA' and do { - my $stepperNum = $data->{stepperNum}; - my $observer = $self->{stepper_observer}[$stepperNum]; - if (defined $observer) { - $observer->{method}( $stepperNum, $observer->{context} ); - }; - last; - }; - - $sysex_message->{command_str} eq 'ENCODER_DATA' and do { - foreach my $encoder_data ( @$data ) { - my $encoderNum = $encoder_data->{encoderNum}; - my $observer = $self->{encoder_observer}[$encoderNum]; - if (defined $observer) { - $observer->{method}( $encoderNum, $encoder_data->{value}, $observer->{context} ); - } - }; - last; - }; - - $sysex_message->{command_str} eq 'SERIAL_DATA' and do { - my $serialPort = $data->{port}; - my $observer = $self->{serial_observer}[$serialPort]; - if (defined $observer) { - $observer->{method}( $data, $observer->{context} ); - } - last; - }; - } -} - -=head2 probe - -On device boot time we wait 3 seconds for firmware name -that the target device is using. -If not received the starting message, then we wait for -response another 2 seconds and fire requests for version. -If the response received, then we store protocol version -and analog mapping and capability. - -=cut - -sub probe { - # -------------------------------------------------- - my ($self) = @_; - $self->{metadata}{firmware} = ''; - $self->{metadata}{firmware_version} = ''; - $self->{metadata}{protocol_version} = ''; - - # Wait for 5 seconds only - my $end_tics = time + 5; - $self->firmware_version_query(); - $self->protocol_version_query(); - while ( $end_tics >= time ) { - select( undef, undef, undef, 0.2 ); # wait for responses - if ( $self->poll && $self->{metadata}{firmware} && $self->{metadata}{firmware_version} && $self->{metadata}{protocol_version} ) { - $self->{protocol}->{protocol_version} = $self->{protocol}->get_max_supported_protocol_version($self->{metadata}{protocol_version}); - if ( $self->{metadata}{capabilities} ) { - if ( $self->{metadata}{analog_mappings} ) { - return 1; - } else { - $self->analog_mapping_query(); - } - } else { - $self->capability_query(); - } - } elsif ($end_tics - 2 < time) { - # version query on last 2 sec only - $self->firmware_version_query(); - $self->protocol_version_query(); - } - } - return; -} - -=head2 pin_mode - -Similar to the pinMode function on the -arduino - -=cut - -sub pin_mode { - - # -------------------------------------------------- - my ( $self, $pin, $mode ) = @_; - - die "unsupported mode '".$mode."' for pin '".$pin."'" unless $self->is_supported_mode($pin,$mode); - - PIN_MODE_HANDLER: { - - ( $mode == PIN_INPUT or $mode == PIN_PULLUP ) and do { - my $port_number = $pin >> 3; - $self->{io}->data_write($self->{protocol}->message_prepare( SET_PIN_MODE => 0, $pin, $mode )); - $self->{io}->data_write($self->{protocol}->message_prepare( REPORT_DIGITAL => $port_number, 1 )); - last; - }; - - $mode == PIN_ANALOG and do { - $self->{io}->data_write($self->{protocol}->message_prepare( SET_PIN_MODE => 0, $pin, $mode )); - $self->{io}->data_write($self->{protocol}->message_prepare( REPORT_ANALOG => $pin, 1 )); - last; - }; - - $self->{io}->data_write($self->{protocol}->message_prepare( SET_PIN_MODE => 0, $pin, $mode )); - }; - $self->{pin_modes}->{$pin} = $mode; - return 1; -} - -=head2 digital_write - -Analogous to the digitalWrite function on the -arduino - -Deprecation Warning: -Writing to pin with mode "INPUT" is only supported for backward compatibility -to switch pullup on and off. Use sub pin_mode with $mode=PIN_PULLUP instead. - -=cut - -sub digital_write { - - # -------------------------------------------------- - my ( $self, $pin, $state ) = @_; - die "pin '".$pin."' is not configured for mode 'INPUT', 'PULLUP' or 'OUTPUT'" unless ($self->is_configured_mode($pin,PIN_OUTPUT) or $self->is_configured_mode($pin,PIN_INPUT) or $self->is_configured_mode($pin,PIN_PULLUP)); - my $port_number = $pin >> 3; - - my $pin_offset = $pin % 8; - my $pin_mask = 1 << $pin_offset; - - my $port_state = $self->{ports}[$port_number] ||= 0; - if ($state) { - $port_state |= $pin_mask; - } - else { - $port_state &= $pin_mask ^ 0xff; - } - $self->{ports}[$port_number] = $port_state; - $self->{io}->data_write($self->{protocol}->message_prepare( DIGITAL_MESSAGE => $port_number, $port_state & 0x7f, $port_state >> 7 )); - return 1; -} - -=head2 digital_read - -Analogous to the digitalRead function on the -arduino - -=cut - -sub digital_read { - - # -------------------------------------------------- - my ( $self, $pin ) = @_; - die "pin '".$pin."' is not configured for mode 'INPUT' or 'PULLUP'" unless ($self->is_configured_mode($pin,PIN_INPUT) or $self->is_configured_mode($pin,PIN_PULLUP)); - my $port_number = $pin >> 3; - my $pin_offset = $pin % 8; - my $pin_mask = 1 << $pin_offset; - my $port_state = $self->{input_ports}[$port_number] ||= 0; - return ( $port_state & $pin_mask ? 1 : 0 ); -} - -=head2 analog_read - -Fetches the analog value of a pin - -=cut - -sub analog_read { - - # -------------------------------------------------- - # - my ( $self, $pin ) = @_; - die "pin '".$pin."' is not configured for mode 'ANALOG'" unless $self->is_configured_mode($pin,PIN_ANALOG); - return $self->{analog_pins}[$pin]; -} - -=head2 analog_write - -=cut - -sub analog_write { - - # -------------------------------------------------- - # Sets the PWM value on an arduino - # - my ( $self, $pin, $value ) = @_; - die "pin '".$pin."' is not configured for mode 'PWM'" unless $self->is_configured_mode($pin,PIN_PWM); - - # FIXME: 8 -> 7 bit translation should be done in the protocol module - my $byte_0 = $value & 0x7f; - my $byte_1 = $value >> 7; - return $self->{io}->data_write($self->{protocol}->message_prepare( ANALOG_MESSAGE => $pin, $byte_0, $byte_1 )); -} - -=head2 pwm_write - -pmw_write is an alias for analog_write - -=cut - -*pwm_write = *analog_write; - -sub protocol_version_query { - my $self = shift; - my $protocol_version_query_packet = $self->{protocol}->packet_query_version; - return $self->{io}->data_write($protocol_version_query_packet); -} - -sub firmware_version_query { - my $self = shift; - my $firmware_version_query_packet = $self->{protocol}->packet_query_firmware; - return $self->{io}->data_write($firmware_version_query_packet); -} - -sub capability_query { - my $self = shift; - my $capability_query_packet = $self->{protocol}->packet_query_capability(); - return $self->{io}->data_write($capability_query_packet); -} - -sub analog_mapping_query { - my $self = shift; - my $analog_mapping_query_packet = $self->{protocol}->packet_query_analog_mapping(); - return $self->{io}->data_write($analog_mapping_query_packet); -} - -sub pin_state_query { - my ($self,$pin) = @_; - my $pin_state_query_packet = $self->{protocol}->packet_query_pin_state($pin); - return $self->{io}->data_write($pin_state_query_packet); -} - -sub sampling_interval { - my ( $self, $sampling_interval ) = @_; - my $sampling_interval_packet = $self->{protocol}->packet_sampling_interval($sampling_interval); - return $self->{io}->data_write($sampling_interval_packet); -} - -sub sysex_send { - my ( $self, @sysex_data ) = @_; - my $sysex_packet = $self->{protocol}->packet_sysex(@sysex_data); - return $self->{io}->data_write($sysex_packet); -} - -sub i2c_write { - my ($self,$address,@data) = @_; - return $self->{io}->data_write($self->{protocol}->packet_i2c_request($address,0x0,@data)); -} - -sub i2c_readonce { - my ($self,$address,$register,$numbytes) = @_; - my $packet = (defined $numbytes) - ? $self->{protocol}->packet_i2c_request($address,0x8,$register,$numbytes) - : $self->{protocol}->packet_i2c_request($address,0x8,$register); - return $self->{io}->data_write($packet); -} - -sub i2c_read { - my ($self,$address,$register,$numbytes) = @_; - return $self->{io}->data_write($self->{protocol}->packet_i2c_request($address,0x10,$register,$numbytes)); -} - -sub i2c_stopreading { - my ($self,$address) = @_; - return $self->{io}->data_write($self->{protocol}->packet_i2c_request($address,0x18)); -} - -sub i2c_config { - my ( $self, $delay, @data ) = @_; - return $self->{io}->data_write($self->{protocol}->packet_i2c_config($delay,@data)); -} - -sub servo_write { - - # -------------------------------------------------- - # Sets the SERVO value on an arduino - # - my ( $self, $pin, $value ) = @_; - die "pin '".$pin."' is not configured for mode 'SERVO'" unless $self->is_configured_mode($pin,PIN_SERVO); - - # FIXME: 8 -> 7 bit translation should be done in the protocol module - my $byte_0 = $value & 0x7f; - my $byte_1 = $value >> 7; - return $self->{io}->data_write($self->{protocol}->message_prepare( ANALOG_MESSAGE => $pin, $byte_0, $byte_1 )); -} - -sub servo_config { - my ( $self, $pin, $args ) = @_; - die "pin '".$pin."' is not configured for mode 'SERVO'" unless $self->is_configured_mode($pin,PIN_SERVO); - return $self->{io}->data_write($self->{protocol}->packet_servo_config_request($pin,$args)); -} - -sub scheduler_create_task { - my $self = shift; - my $id=-1; - my $tasks = $self->{tasks}; - for my $task (@$tasks) { - if ($id < $task->{id}) { - $id = $task->{id}; - } - } - $id++; - my $newtask = { - id => $id, - data => [], - time_ms => undef, - }; - push @$tasks,$newtask; - return $id; -} - -sub scheduler_delete_task { - my ($self,$id) = @_; - my $tasks = $self->{tasks}; - for my $task (@$tasks) { - if ($id == $task->{id}) { - if (defined $task->{time_ms}) { - my $packet = $self->{protocol}->packet_delete_task($id); - $self->{io}->data_write($packet); - } - delete $self->{tasks}[$id]; # delete $array[index]; (not delete @array[index];) - last; - } - } -} - -sub scheduler_add_to_task { - my ($self,$id,$packet) = @_; - my $tasks = $self->{tasks}; - for my $task (@$tasks) { - if ($id == $task->{id}) { - my $data = $task->{data}; - push @$data,unpack "C*", $packet; - last; - } - } -} - -sub scheduler_schedule_task { - my ($self,$id,$time_ms) = @_; - my $tasks = $self->{tasks}; - for my $task (@$tasks) { - if ($id == $task->{id}) { - if (!(defined $task->{time_ms})) { # TODO - a bit unclear why I put this test here in the first place. -> TODO: investigate and remove this check if not nessesary - my $data = $task->{data}; - my $len = @$data; - my $packet = $self->{protocol}->packet_create_task($id,$len); - $self->{io}->data_write($packet); - my $bytesPerPacket = 53; # (64-1)*7/8-2 (1 byte command, 1 byte for subcommand, 1 byte taskid) - my $j=0; - my @packetdata; - for (my $i=0;$i<$len;$i++) { - push @packetdata,@$data[$i]; - $j++; - if ($j==$bytesPerPacket) { - $j=0; - $packet = $self->{protocol}->packet_add_to_task($id,@packetdata); - $self->{io}->data_write($packet); - @packetdata = (); - } - } - if ($j>0) { - $packet = $self->{protocol}->packet_add_to_task($id,@packetdata); - $self->{io}->data_write($packet); - } - } - my $packet = $self->{protocol}->packet_schedule_task($id,$time_ms); - $self->{io}->data_write($packet); - last; - } - } -} - -sub scheduler_reset { - my $self = shift; - my $packet = $self->{protocol}->packet_reset_scheduler; - $self->{io}->data_write($packet); - $self->{tasks} = []; -} - -sub scheduler_query_all_tasks { - my $self = shift; - my $packet = $self->{protocol}->packet_query_all_tasks; - $self->{io}->data_write($packet); -} - -sub scheduler_query_task { - my ($self,$id) = @_; - my $packet = $self->{protocol}->packet_query_task($id); - $self->{io}->data_write($packet); -} - -# SEARCH_REQUEST, -# CONFIG_REQUEST, - -#$args = { -# reset => undef | 1, -# skip => undef | 1, -# select => undef | device, -# read => undef | short int, -# delay => undef | long int, -# write => undef | bytes[], -#} - -sub onewire_search { - my ( $self, $pin ) = @_; - die "pin '".$pin."' is not configured for mode 'ONEWIRE'" unless $self->is_configured_mode($pin,PIN_ONEWIRE); - return $self->{io}->data_write($self->{protocol}->packet_onewire_search_request( $pin )); -} - -sub onewire_search_alarms { - my ( $self, $pin ) = @_; - die "pin '".$pin."' is not configured for mode 'ONEWIRE'" unless $self->is_configured_mode($pin,PIN_ONEWIRE); - return $self->{io}->data_write($self->{protocol}->packet_onewire_search_alarms_request( $pin )); -} - -sub onewire_config { - my ( $self, $pin, $power ) = @_; - die "pin '".$pin."' is not configured for mode 'ONEWIRE'" unless $self->is_configured_mode($pin,PIN_ONEWIRE); - return $self->{io}->data_write($self->{protocol}->packet_onewire_config_request( $pin, $power )); -} - -sub onewire_reset { - my ( $self, $pin ) = @_; - return $self->onewire_command_series( $pin, {reset => 1} ); -} - -sub onewire_skip { - my ( $self, $pin ) = @_; - return $self->onewire_command_series( $pin, {skip => 1} ); -} - -sub onewire_select { - my ( $self, $pin, $device ) = @_; - return $self->onewire_command_series( $pin, {select => $device} ); -} - -sub onewire_read { - my ( $self, $pin, $numBytes ) = @_; - return $self->onewire_command_series( $pin, {read => $numBytes} ); -} - -sub onewire_write { - my ( $self, $pin, @data ) = @_; - return $self->onewire_command_series( $pin, {write => \@data} ); -} - -sub onewire_command_series { - my ( $self, $pin, $args ) = @_; - die "pin '".$pin."' is not configured for mode 'ONEWIRE'" unless $self->is_configured_mode($pin,PIN_ONEWIRE); - return $self->{io}->data_write($self->{protocol}->packet_onewire_request( $pin, $args )); -} - -sub stepper_config { - my ( $self, $stepperNum, $interface, $stepsPerRev, $directionPin, $stepPin, $motorPin3, $motorPin4 ) = @_; - die "unsupported mode 'STEPPER' for pin '".$directionPin."'" unless $self->is_supported_mode($directionPin,PIN_STEPPER); - die "unsupported mode 'STEPPER' for pin '".$stepPin."'" unless $self->is_supported_mode($stepPin,PIN_STEPPER); - die "unsupported mode 'STEPPER' for pin '".$motorPin3."'" unless (!(defined $motorPin3) or $self->is_supported_mode($motorPin3,PIN_STEPPER)); - die "unsupported mode 'STEPPER' for pin '".$motorPin4."'" unless (!(defined $motorPin4) or $self->is_supported_mode($motorPin4,PIN_STEPPER)); - return $self->{io}->data_write($self->{protocol}->packet_stepper_config( $stepperNum, $interface, $stepsPerRev, $directionPin, $stepPin, $motorPin3, $motorPin4 )); -} - -sub stepper_step { - my ( $self, $stepperNum, $direction, $numSteps, $stepSpeed, $accel, $decel ) = @_; - return $self->{io}->data_write($self->{protocol}->packet_stepper_step( $stepperNum, $direction, $numSteps, $stepSpeed, $accel, $decel )); -} - -sub encoder_attach { - my ( $self, $encoderNum, $pinA, $pinB ) = @_; - die "unsupported mode 'ENCODER' for pin '".$pinA."'" unless $self->is_supported_mode($pinA,PIN_ENCODER); - die "unsupported mode 'ENCODER' for pin '".$pinB."'" unless $self->is_supported_mode($pinB,PIN_ENCODER); - return $self->{io}->data_write($self->{protocol}->packet_encoder_attach( $encoderNum, $pinA, $pinB )); -} - -sub encoder_report_position { - my ( $self, $encoderNum ) = @_; - return $self->{io}->data_write($self->{protocol}->packet_encoder_report_position( $encoderNum )); -} - -sub encoder_report_positions { - my ( $self ) = @_; - return $self->{io}->data_write($self->{protocol}->packet_encoder_report_positions()); -} - -sub encoder_reset_position { - my ( $self, $encoderNum ) = @_; - return $self->{io}->data_write($self->{protocol}->packet_encoder_reset_position( $encoderNum )); -} - -sub encoder_report_auto { - my ( $self, $enable ) = @_; - return $self->{io}->data_write($self->{protocol}->packet_encoder_report_auto( $enable )); -} - -sub encoder_detach { - my ( $self, $encoderNum ) = @_; - return $self->{io}->data_write($self->{protocol}->packet_encoder_detach( $encoderNum )); -} - -sub serial_write { - my ( $self, $port, @data ) = @_; - return $self->{io}->data_write($self->{protocol}->packet_serial_write( $port, @data )); -} - -sub serial_read { - my ( $self, $port, $numbytes ) = @_; - if ($port >= 8) { - $self->{io}->data_write($self->{protocol}->packet_serial_listen( $port )); - } - return $self->{io}->data_write($self->{protocol}->packet_serial_read( $port, 0x00, $numbytes )); -} - -sub serial_stopreading { - my ( $self, $port) = @_; - return $self->{io}->data_write($self->{protocol}->packet_serial_read( $port, 0x01, 0 )); -} - -sub serial_config { - my ( $self, $port, $baud, $rxPin, $txPin ) = @_; - return $self->{io}->data_write($self->{protocol}->packet_serial_config( $port, $baud, $rxPin, $txPin )); -} - -=head2 poll - -Call this function every once in a while to -check up on the status of the comm port, receive -and process data from the arduino - -=cut - -sub poll { - - # -------------------------------------------------- - my $self = shift; - my $buf = $self->{io}->data_read(2048); - my $messages = $self->{protocol}->message_data_receive($buf) or return; - $self->messages_handle($messages); - return $messages; -} - -sub observe_digital { - my ( $self, $pin, $observer, $context ) = @_; - die "unsupported mode 'INPUT' for pin '".$pin."'" unless ($self->is_supported_mode($pin,PIN_INPUT)); - $self->{digital_observer}[$pin] = { - method => $observer, - context => $context, - }; - my $port_number = $pin >> 3; - $self->{io}->data_write($self->{protocol}->message_prepare( REPORT_DIGITAL => $port_number, 1 )); - return 1; -} - -sub observe_analog { - my ( $self, $pin, $observer, $context ) = @_; - die "unsupported mode 'ANALOG' for pin '".$pin."'" unless ($self->is_supported_mode($pin,PIN_ANALOG)); - $self->{analog_observer}[$pin] = { - method => $observer, - context => $context, - }; - $self->{io}->data_write($self->{protocol}->message_prepare( REPORT_ANALOG => $pin, 1 )); - return 1; -} - -sub observe_sysex { - my ( $self, $observer, $context ) = @_; - $self->{sysex_observer} = { - method => $observer, - context => $context, - }; - return 1; -} - -sub observe_i2c { - my ( $self, $observer, $context ) = @_; - return undef if (defined $self->{metadata}->{i2cpins} && @$self->{metadata}->{i2cpins} == 0 ); - $self->{i2c_observer} = { - method => $observer, - context => $context, - }; - return 1; -} - -sub observe_onewire { - my ( $self, $pin, $observer, $context ) = @_; - die "unsupported mode 'ONEWIRE' for pin '".$pin."'" unless ($self->is_supported_mode($pin,PIN_ONEWIRE)); - $self->{onewire_observer}[$pin] = { - method => $observer, - context => $context, - }; - return 1; -} - -sub observe_stepper { - my ( $self, $stepperNum, $observer, $context ) = @_; -#TODO validation? die "unsupported mode 'STEPPER' for pin '".$pin."'" unless ($self->is_supported_mode($pin,PIN_STEPPER)); - $self->{stepper_observer}[$stepperNum] = { - method => $observer, - context => $context, - }; - return 1; -} - -sub observe_encoder { - my ( $self, $encoderNum, $observer, $context ) = @_; -#TODO validation? die "unsupported mode 'ENCODER' for pin '".$pin."'" unless ($self->is_supported_mode($pin,PIN_ENCODER)); - $self->{encoder_observer}[$encoderNum] = { - method => $observer, - context => $context, - }; - return 1; -} - -sub observe_serial { - my ( $self, $port, $observer, $context ) = @_; - return undef if (defined $self->{metadata}->{serialpins} && @$self->{metadata}->{serialpins} == 0 ); - $self->{serial_observer}[$port] = { - method => $observer, - context => $context, - }; - return 1; -} - -sub observe_scheduler { - my ( $self, $observer, $context ) = @_; - $self->{scheduler_observer} = { - method => $observer, - context => $context, - }; - return 1; -} - -sub observe_string { - my ( $self, $observer, $context ) = @_; - $self->{string_observer} = { - method => $observer, - context => $context, - }; - return 1; -} - -sub is_supported_mode { - my ($self,$pin,$mode) = @_; - return undef if (defined $self->{metadata}->{capabilities} and (!(defined $self->{metadata}->{capabilities}->{$pin}) or !(defined $self->{metadata}->{capabilities}->{$pin}->{$mode}))); - return 1; -} - -sub is_configured_mode { - my ($self,$pin,$mode) = @_; - return undef if (!defined $self->{pin_modes}->{$pin} or $self->{pin_modes}->{$pin} != $mode); - return 1; -} - -1; diff --git a/fhem/FHEM/lib/Device/Firmata/Platform/Arduino.pm b/fhem/FHEM/lib/Device/Firmata/Platform/Arduino.pm deleted file mode 100644 index 2d0a3c6cd..000000000 --- a/fhem/FHEM/lib/Device/Firmata/Platform/Arduino.pm +++ /dev/null @@ -1,19 +0,0 @@ -package Device::Firmata::Platform::Arduino; - -=head1 NAME - -Device::Firmata::Platform::Arduino - subclass for the arduino itself - -=head1 DESCRIPTION - -No customization requried at this time so this is just a specification of the -Device::Firmata::Platform class - -=cut - -use strict; -use Device::Firmata::Platform; -use Device::Firmata::Base - ISA => 'Device::Firmata::Platform'; - -1; diff --git a/fhem/FHEM/lib/Device/Firmata/Protocol.pm b/fhem/FHEM/lib/Device/Firmata/Protocol.pm deleted file mode 100644 index 21803ead3..000000000 --- a/fhem/FHEM/lib/Device/Firmata/Protocol.pm +++ /dev/null @@ -1,1309 +0,0 @@ -package Device::Firmata::Protocol; - -=head1 NAME - -Device::Firmata::Protocol - details of the actual firmata protocol - -=cut - -use strict; -use warnings; -use vars qw/ $MIDI_DATA_SIZES /; - -use constant { - MIDI_COMMAND => 0x80, - MIDI_PARSE_NORMAL => 0, - MIDI_PARSE_SYSEX => 1, - MIDI_START_SYSEX => 0xf0, - MIDI_END_SYSEX => 0xf7, - MAX_PROTOCOL_VERSION => 'V_2_05', # highest Firmata protocol version currently implemented -}; - -use Device::Firmata::Constants qw/ :all /; -use Device::Firmata::Base - ISA => 'Device::Firmata::Base', - FIRMATA_ATTRIBS => { - buffer => [], - parse_status => MIDI_PARSE_NORMAL, - protocol_version => MAX_PROTOCOL_VERSION, # We are starting with the highest protocol - }; - -$MIDI_DATA_SIZES = { - 0x80 => 2, - 0x90 => 2, - 0xA0 => 2, - 0xB0 => 2, - 0xC0 => 1, - 0xD0 => 1, - 0xE0 => 2, - 0xF0 => 0, # note that this requires special handling - - # Special for version queries - 0xF4 => 2, - 0xF9 => 2, - 0x71 => 0, - 0xFF => 0, -}; - -our $ONE_WIRE_COMMANDS = { - SEARCH_REQUEST => 0x40, - CONFIG_REQUEST => 0x41, - SEARCH_REPLY => 0x42, - READ_REPLY => 0x43, - SEARCH_ALARMS_REQUEST => 0x44, - SEARCH_ALARMS_REPLY => 0x45, - RESET_REQUEST_BIT => 0x01, - SKIP_REQUEST_BIT => 0x02, - SELECT_REQUEST_BIT => 0x04, - READ_REQUEST_BIT => 0x08, - DELAY_REQUEST_BIT => 0x10, - WRITE_REQUEST_BIT => 0x20, -}; - -our $SCHEDULER_COMMANDS = { - CREATE_FIRMATA_TASK => 0, - DELETE_FIRMATA_TASK => 1, - ADD_TO_FIRMATA_TASK => 2, - DELAY_FIRMATA_TASK => 3, - SCHEDULE_FIRMATA_TASK => 4, - QUERY_ALL_FIRMATA_TASKS => 5, - QUERY_FIRMATA_TASK => 6, - RESET_FIRMATA_TASKS => 7, - ERROR_TASK_REPLY => 8, - QUERY_ALL_TASKS_REPLY => 9, - QUERY_TASK_REPLY => 10, -}; - -our $STEPPER_COMMANDS = { - STEPPER_CONFIG => 0, - STEPPER_STEP => 1, -}; - -our $STEPPER_INTERFACES = { - DRIVER => 1, - TWO_WIRE => 2, - FOUR_WIRE => 4, -}; - -our $ENCODER_COMMANDS = { - ENCODER_ATTACH => 0, - ENCODER_REPORT_POSITION => 1, - ENCODER_REPORT_POSITIONS => 2, - ENCODER_RESET_POSITION => 3, - ENCODER_REPORT_AUTO => 4, - ENCODER_DETACH => 5, -}; - -our $SERIAL_COMMANDS = { - SERIAL_CONFIG => 0x10, # config serial port stetting such as baud rate and pins - SERIAL_WRITE => 0x20, # write to serial port - SERIAL_READ => 0x30, # read request to serial port - SERIAL_REPLY => 0x40, # read reply from serial port - SERIAL_LISTEN => 0x70, # start listening on software serial port -}; - -our $MODENAMES = { - 0 => 'INPUT', - 1 => 'OUTPUT', - 2 => 'ANALOG', - 3 => 'PWM', - 4 => 'SERVO', - 5 => 'SHIFT', - 6 => 'I2C', - 7 => 'ONEWIRE', - 8 => 'STEPPER', - 9 => 'ENCODER', - 10 => 'SERIAL', - 11 => 'PULLUP', -}; - -=head1 DESCRIPTION - -Because we're dealing with a permutation of the -MIDI protocol, certain commands are one byte, -others 2 or even 3. We do this part to figure out -how many bytes we're actually looking at - -One of the first things to know is that while -MIDI is packet based, the bytes have specialized -construction (where the top-most bit has been -reserved to differentiate if it's a command or a -data bit) - -So any byte being transferred in a MIDI stream -will look like the following - - BIT# | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | - DATA | X | ? | ? | ? | ? | ? | ? | ? | - -If X is a "1" this byte is considered a command byte -If X is a "0" this byte is considered a data bte - -We figure out how many bytes a packet is by looking at the -command byte and of that byte, only the high nibble. -This nibble tells us the requisite information via a lookup -table... - -See: http://www.midi.org/techspecs/midimessages.php -And -http://www.ccarh.org/courses/253/handout/midiprotocol/ -For more information - -Basically, however: - -command -nibble bytes -8 2 -9 2 -A 2 -B 2 -C 1 -D 1 -E 2 -F 0 or variable - -=cut - -=head2 message_data_receive - -Receive a string of data. Normally, only one byte -is passed due to the code, but you can also pass as -many bytes in a string as you'd like. - -=cut - -sub message_data_receive { - - # -------------------------------------------------- - my ( $self, $data ) = @_; - - defined $data and length $data or return; - - my $protocol_version = $self->{protocol_version}; - my $protocol_commands = $COMMANDS->{$protocol_version}; - my $protocol_lookup = $COMMAND_LOOKUP->{$protocol_version}; - - # Add the new data to the buffer - my $buffer = $self->{buffer} ||= []; - push @$buffer, unpack "C*", $data; - - my @packets; - - # Loop until we're finished parsing all available packets - while (@$buffer) { - # Not in SYSEX mode, we can proceed normally - if ( $self->{parse_status} == MIDI_PARSE_NORMAL and $buffer->[0] == MIDI_START_SYSEX ) { - my $command = shift @$buffer; - push @packets, { - command => $command, - command_str => $protocol_lookup->{$command} || 'START_SYSEX', - }; - $self->{parse_status} = MIDI_PARSE_SYSEX; - next; - } - # If in sysex mode, we will check for the end of the sysex message here - elsif ( $self->{parse_status} == MIDI_PARSE_SYSEX and $buffer->[0] == MIDI_END_SYSEX ) { - $self->{parse_status} = MIDI_PARSE_NORMAL; - my $command = shift @$buffer; - push @packets, { - command => $command, - command_str => $protocol_lookup->{$command} || 'END_SYSEX', - }; - } - -# Regardless of the SYSEX mode we are in, we will allow commands to interrupt the flowthrough - elsif ( $buffer->[0] & MIDI_COMMAND ) { - my $command = $buffer->[0] & 0xf0; - my $bytes = ( $MIDI_DATA_SIZES->{$command} || $MIDI_DATA_SIZES->{ $buffer->[0] } ) + 1; - last if ( @$buffer < $bytes ); - my @data = splice @$buffer, 0, $bytes; - $command = shift @data; - push @packets, - { - command => $command, - command_str => $protocol_lookup->{$command} - || $protocol_lookup->{ $command & 0xf0 } - || 'UNKNOWN', - data => \@data - }; - } - -# We have a data byte, if we're in SYSEX mode, we'll just add that to the data stream -# packet - elsif ( $self->{parse_status} == MIDI_PARSE_SYSEX ) { - my $data = shift @$buffer; - if ( @packets and $packets[-1]{command_str} eq 'DATA_SYSEX' ) { - push @{ $packets[-1]{data} }, $data; - } - else { - push @packets, - { - command => 0x0, - command_str => 'DATA_SYSEX', - data => [$data] - }; - } - - } - - # No idea what to do with this one, eject it and skip to the next - else { - shift @$buffer; - last if ( not @$buffer ); - } - } - - return if not @packets; - return \@packets; -} - -=head2 sysex_parse - -Takes the sysex data buffer and parses it into -something useful - -=cut - -sub sysex_parse { - - # -------------------------------------------------- - my ( $self, $sysex_data ) = @_; - - my $protocol_version = $self->{protocol_version}; - my $protocol_commands = $COMMANDS->{$protocol_version}; - my $protocol_lookup = $COMMAND_LOOKUP->{$protocol_version}; - - my $command = shift @$sysex_data; - if ( defined $command ) { - my $command_str = $protocol_lookup->{$command}; - - if ($command_str) { - my $return_data; - - COMMAND_HANDLER: { - - $command == $protocol_commands->{STRING_DATA} and do { - $return_data = $self->handle_string_data($sysex_data); - last; - }; - - $command == $protocol_commands->{REPORT_FIRMWARE} and do { - $return_data = $self->handle_report_firmware($sysex_data); - last; - }; - - $command == $protocol_commands->{CAPABILITY_RESPONSE} and do { - $return_data = $self->handle_capability_response($sysex_data); - last; - }; - - $command == $protocol_commands->{ANALOG_MAPPING_RESPONSE} and do { - $return_data = - $self->handle_analog_mapping_response($sysex_data); - last; - }; - - $command == $protocol_commands->{PIN_STATE_RESPONSE} and do { - $return_data = $self->handle_pin_state_response($sysex_data); - last; - }; - - $command == $protocol_commands->{I2C_REPLY} and do { - $return_data = $self->handle_i2c_reply($sysex_data); - last; - }; - - $command == $protocol_commands->{ONEWIRE_DATA} and do { - $return_data = $self->handle_onewire_reply($sysex_data); - last; - }; - - $command == $protocol_commands->{SCHEDULER_DATA} and do { - $return_data = $self->handle_scheduler_response($sysex_data); - last; - }; - - $command == $protocol_commands->{STEPPER_DATA} and do { - $return_data = $self->handle_stepper_response($sysex_data); - last; - }; - - $command == $protocol_commands->{ENCODER_DATA} and do { - $return_data = $self->handle_encoder_response($sysex_data); - last; - }; - - $command == $protocol_commands->{SERIAL_DATA} and do { - $return_data = $self->handle_serial_reply($sysex_data); - last; - }; - - $command == $protocol_commands->{RESERVED_COMMAND} and do { - $return_data = $sysex_data; - last; - }; - } - - return { - command => $command, - command_str => $command_str, - data => $return_data - }; - } else { - return { - command => $command, - data => $sysex_data - } - } - } - return undef; -} - -=head2 message_prepare - -Using the midi protocol, create a binary packet -that can be transmitted to the serial output - -=cut - -sub message_prepare { - - # -------------------------------------------------- - my ( $self, $command_name, $channel, @data ) = @_; - - my $protocol_version = $self->{protocol_version}; - my $protocol_commands = $COMMANDS->{$protocol_version}; - my $command = $protocol_commands->{$command_name} or return; - - my $bytes = 1 + - ( $MIDI_DATA_SIZES->{ $command & 0xf0 } || $MIDI_DATA_SIZES->{$command} ); - my $packet = pack "C" x $bytes, $command | $channel, @data; - return $packet; -} - -=head2 packet_sysex - -create a binary packet containing a sysex-message - -=cut - -sub packet_sysex { - - my ( $self, @sysex_data ) = @_; - - my $protocol_version = $self->{protocol_version}; - my $protocol_commands = $COMMANDS->{$protocol_version}; - - my $bytes = @sysex_data + 2; - my $packet = pack "C" x $bytes, $protocol_commands->{START_SYSEX}, - @sysex_data, - $protocol_commands->{END_SYSEX}; - return $packet; -} - -=head2 packet_sysex_command - -create a binary packet containing a sysex-command - -=cut - -sub packet_sysex_command { - - my ( $self, $command_name, @data ) = @_; - - my $protocol_version = $self->{protocol_version}; - my $protocol_commands = $COMMANDS->{$protocol_version}; - my $command = $protocol_commands->{$command_name} or return; - -# my $bytes = 3+($MIDI_DATA_SIZES->{$command & 0xf0}||$MIDI_DATA_SIZES->{$command}); - my $bytes = @data + 3; - my $packet = pack "C" x $bytes, $protocol_commands->{START_SYSEX}, - $command, - @data, - $protocol_commands->{END_SYSEX}; - return $packet; -} - -=head2 packet_query_version - -Craft a firmware version query packet to be sent - -=cut - -sub packet_query_version { - my $self = shift; - return $self->message_prepare( REPORT_VERSION => 0 ); - -} - -sub handle_query_version_response { - my ( $self, $data ) = @_; - return { - major_version => shift @$data, - minor_version => shift @$data, - }; -} - -sub handle_string_data { - my ( $self, $sysex_data ) = @_; - return { string => double_7bit_to_string($sysex_data) }; -} - -=head2 packet_query_firmware - -Craft a firmware variant query packet to be sent - -=cut - -sub packet_query_firmware { - my $self = shift; - return $self->packet_sysex_command(REPORT_FIRMWARE); -} - -sub handle_report_firmware { - my ( $self, $sysex_data ) = @_; - return { - major_version => shift @$sysex_data, - minor_version => shift @$sysex_data, - firmware => double_7bit_to_string($sysex_data) - }; -} - -sub packet_query_capability { - my $self = shift; - return $self->packet_sysex_command(CAPABILITY_QUERY); -} - -#/* capabilities response -# * ------------------------------- -# * 0 START_SYSEX (0xF0) (MIDI System Exclusive) -# * 1 capabilities response (0x6C) -# * 2 1st mode supported of pin 0 -# * 3 1st mode's resolution of pin 0 -# * 4 2nd mode supported of pin 0 -# * 5 2nd mode's resolution of pin 0 -# ... additional modes/resolutions, followed by a single 127 to mark the -# end of the first pin's modes. Each pin follows with its mode and -# 127, until all pins implemented. -# * N END_SYSEX (0xF7) -# */ - -sub handle_capability_response { - my ( $self, $sysex_data ) = @_; - my %capabilities; - my $byte = shift @$sysex_data; - my $i=0; - while ( defined $byte ) { - my %pinmodes; - while ( defined $byte && $byte != 127 ) { - $pinmodes{$byte} = { - mode_str => $MODENAMES->{$byte}, - resolution => shift @$sysex_data # /secondbyte - }; - $byte = shift @$sysex_data; - } - $capabilities{$i}=\%pinmodes; - $i++; - $byte = shift @$sysex_data; - } - return { capabilities => \%capabilities }; -} - -sub packet_query_analog_mapping { - my $self = shift; - return $self->packet_sysex_command(ANALOG_MAPPING_QUERY); -} - -#/* analog mapping response -# * ------------------------------- -# * 0 START_SYSEX (0xF0) (MIDI System Exclusive) -# * 1 analog mapping response (0x6A) -# * 2 analog channel corresponding to pin 0, or 127 if pin 0 does not support analog -# * 3 analog channel corresponding to pin 1, or 127 if pin 1 does not support analog -# * 4 analog channel corresponding to pin 2, or 127 if pin 2 does not support analog -# ... etc, one byte for each pin -# * N END_SYSEX (0xF7) -# */ - -sub handle_analog_mapping_response { - my ( $self, $sysex_data ) = @_; - my %pins; - my $pin_mapping = shift @$sysex_data; - my $i=0; - - while ( defined $pin_mapping ) { - $pins{$pin_mapping}=$i if ($pin_mapping!=127); - $pin_mapping = shift @$sysex_data; - $i++; - } - return { mappings => \%pins }; -} - -#/* pin state query -# * ------------------------------- -# * 0 START_SYSEX (0xF0) (MIDI System Exclusive) -# * 1 pin state query (0x6D) -# * 2 pin (0 to 127) -# * 3 END_SYSEX (0xF7) (MIDI End of SysEx - EOX) -# */ - -sub packet_query_pin_state { - my ( $self, $pin ) = @_; - return $self->packet_sysex_command( PIN_STATE_QUERY, $pin ); -} - -#/* pin state response -# * ------------------------------- -# * 0 START_SYSEX (0xF0) (MIDI System Exclusive) -# * 1 pin state response (0x6E) -# * 2 pin (0 to 127) -# * 3 pin mode (the currently configured mode) -# * 4 pin state, bits 0-6 -# * 5 (optional) pin state, bits 7-13 -# * 6 (optional) pin state, bits 14-20 -# ... additional optional bytes, as many as needed -# * N END_SYSEX (0xF7) -# */ - -sub handle_pin_state_response { - my ( $self, $sysex_data ) = @_; - my $pin = shift @$sysex_data; - my $mode = shift @$sysex_data; - my $state = shift @$sysex_data & 0x7f; - my $nibble = shift @$sysex_data; - for ( my $i = 1 ; defined $nibble ; $nibble = shift @$sysex_data ) { - $state += ( $nibble & 0x7f ) << ( 7 * $i ); - } - - return { - pin => $pin, - mode => $mode, - moden_str => $MODENAMES->{$mode}, - state => $state - }; - -} - -sub packet_sampling_interval { - my ( $self, $interval ) = @_; - return $self->packet_sysex_command( SAMPLING_INTERVAL, - $interval & 0x7f, - $interval >> 7 - ); -} - -#/* I2C read/write request -# * ------------------------------- -# * 0 START_SYSEX (0xF0) (MIDI System Exclusive) -# * 1 I2C_REQUEST (0x76) -# * 2 slave address (LSB) -# * 3 slave address (MSB) + read/write and address mode bits -# {7: always 0} + {6: reserved} + {5: address mode, 1 means 10-bit mode} + -# {4-3: read/write, 00 => write, 01 => read once, 10 => read continuously, 11 => stop reading} + -# {2-0: slave address MSB in 10-bit mode, not used in 7-bit mode} -# * 4 data 0 (LSB) -# * 5 data 0 (MSB) -# * 6 data 1 (LSB) -# * 7 data 1 (MSB) -# * ... -# * n END_SYSEX (0xF7) -# */ - -sub packet_i2c_request { - my ( $self, $address, $command, @i2cdata ) = @_; - if (($address & 0x380) > 0) { - $command |= (0x20 | (($address >> 7) & 0x7)); - } - - if (scalar @i2cdata) { - my @data; - push_array_as_two_7bit(\@i2cdata,\@data); - return $self->packet_sysex_command( I2C_REQUEST, - $address & 0x7f, - $command, - @data, - ); - } else { - return $self->packet_sysex_command( I2C_REQUEST, - $address & 0x7f, - $command, - ); - } -} - -#/* I2C reply -# * ------------------------------- -# * 0 START_SYSEX (0xF0) (MIDI System Exclusive) -# * 1 I2C_REPLY (0x77) -# * 2 slave address (LSB) -# * 3 slave address (MSB) -# * 4 register (LSB) -# * 5 register (MSB) -# * 6 data 0 LSB -# * 7 data 0 MSB -# * ... -# * n END_SYSEX (0xF7) -# */ - -sub handle_i2c_reply { - my ( $self, $sysex_data ) = @_; - my $address = shift14bit($sysex_data); - my $register = shift14bit($sysex_data); - my @data = double_7bit_to_array($sysex_data); - return { - address => $address, - register => $register, - data => \@data, - }; -} - -#/* I2C config -# * ------------------------------- -# * 0 START_SYSEX (0xF0) (MIDI System Exclusive) -# * 1 I2C_CONFIG (0x78) -# * 2 Delay in microseconds (LSB) -# * 3 Delay in microseconds (MSB) -# * ... user defined for special cases, etc -# * n END_SYSEX (0xF7) -# */ - -sub packet_i2c_config { - my ( $self, $delay, @data ) = @_; - return $self->packet_sysex_command( I2C_CONFIG, - $delay & 0x7f, - $delay >> 7, @data - ); -} - -#/* servo config -# * -------------------- -# * 0 START_SYSEX (0xF0) -# * 1 SERVO_CONFIG (0x70) -# * 2 pin number (0-127) -# * 3 minPulse LSB (0-6) -# * 4 minPulse MSB (7-13) -# * 5 maxPulse LSB (0-6) -# * 6 maxPulse MSB (7-13) -# * 7 END_SYSEX (0xF7) -# */ - -sub packet_servo_config_request { - my ( $self, $pin, $data ) = @_; - my $min_pulse = $data->{min_pulse}; - my $max_pulse = $data->{max_pulse}; - - return $self->packet_sysex_command( SERVO_CONFIG, - $pin & 0x7f, - $min_pulse & 0x7f, - $min_pulse >> 7, - $max_pulse & 0x7f, - $max_pulse >> 7 - ); -} - -#This is just the standard SET_PIN_MODE message: - -#/* set digital pin mode -# * -------------------- -# * 1 set digital pin mode (0xF4) (MIDI Undefined) -# * 2 pin number (0-127) -# * 3 state (INPUT/OUTPUT/ANALOG/PWM/SERVO, 0/1/2/3/4) -# */ - -#Then the normal ANALOG_MESSAGE data format is used to send data. - -#/* write to servo, servo write is performed if the pins mode is SERVO -# * ------------------------------ -# * 0 ANALOG_MESSAGE (0xE0-0xEF) -# * 1 value lsb -# * 2 value msb -# */ - -sub packet_onewire_search_request { - my ( $self, $pin ) = @_; - return $self->packet_sysex_command( ONEWIRE_DATA,$ONE_WIRE_COMMANDS->{SEARCH_REQUEST},$pin); -}; - -sub packet_onewire_search_alarms_request { - my ( $self, $pin ) = @_; - return $self->packet_sysex_command( ONEWIRE_DATA,$ONE_WIRE_COMMANDS->{SEARCH_ALARMS_REQUEST},$pin); -}; - -sub packet_onewire_config_request { - my ( $self, $pin, $power ) = @_; - return $self->packet_sysex_command( ONEWIRE_DATA, $ONE_WIRE_COMMANDS->{CONFIG_REQUEST},$pin, - ( defined $power ) ? $power : 1 - ); -}; - -#$args = { -# reset => undef | 1, -# skip => undef | 1, -# select => undef | device, -# read => undef | short int, -# delay => undef | long int, -# write => undef | bytes[], -#} - -sub packet_onewire_request { - my ( $self, $pin, $args ) = @_; - my $subcommand = 0; - my @data; - if (defined $args->{reset}) { - $subcommand |= $ONE_WIRE_COMMANDS->{RESET_REQUEST_BIT}; - } - if (defined $args->{skip}) { - $subcommand |= $ONE_WIRE_COMMANDS->{SKIP_REQUEST_BIT}; - } - if (defined $args->{select}) { - $subcommand |= $ONE_WIRE_COMMANDS->{SELECT_REQUEST_BIT}; - push_onewire_device_to_byte_array($args->{select},\@data); - } - if (defined $args->{read}) { - $subcommand |= $ONE_WIRE_COMMANDS->{READ_REQUEST_BIT}; - push @data,$args->{read} & 0xFF; - push @data,($args->{read}>>8) & 0xFF; - if ($self->{protocol_version} ne 'V_2_04') { - my $id = (defined $args->{id}) ? $args->{id} : 0; - push @data,$id &0xFF; - push @data,($id>>8) & 0xFF; - } - } - if (defined $args->{delay}) { - $subcommand |= $ONE_WIRE_COMMANDS->{DELAY_REQUEST_BIT}; - push @data,$args->{delay} & 0xFF; - push @data,($args->{delay}>>8) & 0xFF; - push @data,($args->{delay}>>16) & 0xFF; - push @data,($args->{delay}>>24) & 0xFF; - } - if (defined $args->{write}) { - $subcommand |= $ONE_WIRE_COMMANDS->{WRITE_REQUEST_BIT}; - my $writeBytes=$args->{write}; - push @data,@$writeBytes; - } - return $self->packet_sysex_command( ONEWIRE_DATA, $subcommand, $pin, pack_as_7bit(@data)); -}; - -sub handle_onewire_reply { - my ( $self, $sysex_data ) = @_; - my $command = shift @$sysex_data; - my $pin = shift @$sysex_data; - - if ( defined $command ) { - COMMAND_HANDLER: { - $command == $ONE_WIRE_COMMANDS->{READ_REPLY} and do { #PIN,COMMAND,ADDRESS,DATA - my @data = unpack_from_7bit(@$sysex_data); - if ($self->{protocol_version} eq 'V_2_04') { - my $device = shift_onewire_device_from_byte_array(\@data); - return { - pin => $pin, - command => 'READ_REPLY', - device => $device, - data => \@data - }; - } else { - my $id = shift @data; - $id += (shift @data)<<8; - return { - pin => $pin, - command => 'READ_REPLY', - id => $id, - data => \@data - }; - }; - }; - - ($command == $ONE_WIRE_COMMANDS->{SEARCH_REPLY} or $command == $ONE_WIRE_COMMANDS->{SEARCH_ALARMS_REPLY}) and do { #PIN,COMMAND,ADDRESS... - my @devices; - my @data = unpack_from_7bit(@$sysex_data); - my $device = shift_onewire_device_from_byte_array(\@data); - while ( defined $device ) { - push @devices, $device; - $device = shift_onewire_device_from_byte_array(\@data); - } - return { - pin => $pin, - command => $command == $ONE_WIRE_COMMANDS->{SEARCH_REPLY} ? 'SEARCH_REPLY' : 'SEARCH_ALARMS_REPLY', - devices => \@devices, - }; - }; - } - } -} - -sub packet_create_task { - my ($self,$id,$len) = @_; - my $packet = $self->packet_sysex_command('SCHEDULER_DATA', $SCHEDULER_COMMANDS->{CREATE_FIRMATA_TASK}, $id, $len & 0x7F, $len>>7); - return $packet; -} - -sub packet_delete_task { - my ($self,$id) = @_; - return $self->packet_sysex_command('SCHEDULER_DATA', $SCHEDULER_COMMANDS->{DELETE_FIRMATA_TASK}, $id); -} - -sub packet_add_to_task { - my ($self,$id,@data) = @_; - my $packet = $self->packet_sysex_command('SCHEDULER_DATA', $SCHEDULER_COMMANDS->{ADD_TO_FIRMATA_TASK}, $id, pack_as_7bit(@data)); - return $packet; -} - -sub packet_delay_task { - my ($self,$time_ms) = @_; - my $packet = $self->packet_sysex_command('SCHEDULER_DATA', $SCHEDULER_COMMANDS->{DELAY_FIRMATA_TASK}, pack_as_7bit($time_ms & 0xFF, ($time_ms & 0xFF00)>>8, ($time_ms & 0xFF0000)>>16,($time_ms & 0xFF000000)>>24)); - return $packet; -} - -sub packet_schedule_task { - my ($self,$id,$time_ms) = @_; - my $packet = $self->packet_sysex_command('SCHEDULER_DATA', $SCHEDULER_COMMANDS->{SCHEDULE_FIRMATA_TASK}, $id, pack_as_7bit($time_ms & 0xFF, ($time_ms & 0xFF00)>>8, ($time_ms & 0xFF0000)>>16,($time_ms & 0xFF000000)>>24)); - return $packet; -} - -sub packet_query_all_tasks { - my $self = shift; - return $self->packet_sysex_command('SCHEDULER_DATA', $SCHEDULER_COMMANDS->{QUERY_ALL_FIRMATA_TASKS}); -} - -sub packet_query_task { - my ($self,$id) = @_; - return $self->packet_sysex_command('SCHEDULER_DATA', $SCHEDULER_COMMANDS->{QUERY_FIRMATA_TASK},$id); -} - -sub packet_reset_scheduler { - my $self = shift; - return $self->packet_sysex_command('SCHEDULER_DATA', $SCHEDULER_COMMANDS->{RESET_FIRMATA_TASKS}); -} - -sub handle_scheduler_response { - my ( $self, $sysex_data ) = @_; - my $command = shift @$sysex_data; - - if ( defined $command ) { - COMMAND_HANDLER: { - $command == $SCHEDULER_COMMANDS->{QUERY_ALL_TASKS_REPLY} and do { - return { - command => 'QUERY_ALL_TASKS_REPLY', - ids => $sysex_data, - } - }; - - ($command == $SCHEDULER_COMMANDS->{QUERY_TASK_REPLY} or $command == $SCHEDULER_COMMANDS->{ERROR_TASK_REPLY}) and do { - my $error = ($command == $SCHEDULER_COMMANDS->{ERROR_TASK_REPLY}); - if (scalar @$sysex_data == 1) { - return { - command => ($error ? 'ERROR_TASK_REPLY' : 'QUERY_TASK_REPLY'), - id => shift @$sysex_data, - } - } - if (scalar @$sysex_data >= 11) { - my $id = shift @$sysex_data; - my @data = unpack_from_7bit(@$sysex_data); - return { - command => ($error ? 'ERROR_TASK_REPLY' : 'QUERY_TASK_REPLY'), - id => $id, - time_ms => shift @data | (shift @data)<<8 | (shift @data)<<16 | (shift @data)<<24, - len => shift @data | (shift @data)<<8, - position => shift @data | (shift @data)<<8, - messages => \@data, - } - } - }; - } - } -} - -# stepper_data 0 -# stepper_config 1 -# devicenum 2 (0 < devicenum < 6) -# interface (DRIVER | TWO_WIRE | FOUR_WIRE) 3 -# stepsPerRev 4+5 (14bit) -# directionPin 6 -# stepPin 7 -# motorPin3 8 (interface FOUR_WIRE only) -# motorPin4 9 (interface FOUR_WIRE only) - -sub packet_stepper_config { - my ( $self, $stepperNum, $interface, $stepsPerRev, $directionPin, $stepPin, $motorPin3, $motorPin4 ) = @_; - - die "invalid stepper interface ".$interface unless defined ($STEPPER_INTERFACES->{$interface}); - my @configdata = ($stepperNum,$STEPPER_INTERFACES->{$interface}); - - push_value_as_two_7bit($stepsPerRev, \@configdata); - push @configdata, $directionPin; - push @configdata, $stepPin; - - if ($interface eq 'FOUR_WIRE') { - push @configdata, $motorPin3; - push @configdata, $motorPin4; - } - my $packet = $self->packet_sysex_command('STEPPER_DATA',$STEPPER_COMMANDS->{STEPPER_CONFIG},@configdata); - return $packet; -} - -# stepper_data 0 -# stepper_step 1 -# devicenum 2 -# stepDirection 3 0/>0 -# numSteps 4,5,6 (21bit) -# stepSpeed 7,8 (14bit) -# accel 9,10 (14bit, optional, aber nur zusammen mit decel) -# decel 11,12 (14bit, optional, aber nur zusammen mit accel) - -sub packet_stepper_step { - my ( $self, $stepperNum, $direction, $numSteps, $stepSpeed, $accel, $decel ) = @_; - my @stepdata = ($stepperNum, $direction); - push @stepdata, $numSteps & 0x7f; - push @stepdata, ($numSteps >> 7) & 0x7f; - push @stepdata, ($numSteps >> 14) & 0x7f; - push_value_as_two_7bit($stepSpeed, \@stepdata); - if (defined $accel and defined $decel) { - push_value_as_two_7bit($accel, \@stepdata); - push_value_as_two_7bit($decel, \@stepdata); - } - my $packet = $self->packet_sysex_command('STEPPER_DATA', $STEPPER_COMMANDS->{STEPPER_STEP},@stepdata); - return $packet; -} - -sub handle_stepper_response { - my ( $self, $sysex_data ) = @_; - - my $stepperNum = shift @$sysex_data; - return { - stepperNum => $stepperNum, - }; -} - - -sub packet_encoder_attach { - my ( $self,$encoderNum, $pinA, $pinB ) = @_; - my $packet = $self->packet_sysex_command('ENCODER_DATA', $ENCODER_COMMANDS->{ENCODER_ATTACH}, $encoderNum, $pinA, $pinB); - return $packet; -} - -sub packet_encoder_report_position { - my ( $self,$encoderNum ) = @_; - my $packet = $self->packet_sysex_command('ENCODER_DATA', $ENCODER_COMMANDS->{ENCODER_REPORT_POSITION}, $encoderNum); - return $packet; -} - -sub packet_encoder_report_positions { - my ( $self ) = @_; - my $packet = $self->packet_sysex_command('ENCODER_DATA', $ENCODER_COMMANDS->{ENCODER_REPORT_POSITIONS}); - return $packet; -} - -sub packet_encoder_reset_position { - my ( $self,$encoderNum ) = @_; - my $packet = $self->packet_sysex_command('ENCODER_DATA', $ENCODER_COMMANDS->{ENCODER_RESET_POSITION}, $encoderNum); - return $packet; -} - -sub packet_encoder_report_auto { - my ( $self,$arg ) = @_; - my $packet = $self->packet_sysex_command('ENCODER_DATA', $ENCODER_COMMANDS->{ENCODER_REPORT_AUTO}, $arg); - return $packet; -} - -sub packet_encoder_detach { - my ( $self,$encoderNum ) = @_; - my $packet = $self->packet_sysex_command('ENCODER_DATA', $ENCODER_COMMANDS->{ENCODER_DETACH}, $encoderNum); - return $packet; -} - -sub handle_encoder_response { - my ( $self, $sysex_data ) = @_; - - my @retval = (); - - while (@$sysex_data) { - - my $command = shift @$sysex_data; - my $direction = ($command & 0x40) >> 6; - my $encoderNum = $command & 0x3f; - my $value = shift14bit($sysex_data) + (shift14bit($sysex_data) << 14); - - push @retval,{ - encoderNum => $encoderNum, - value => $direction ? -1 * $value : $value, - }; - }; - - return \@retval; -} - -#/* serial config -# * ------------------------------- -# * 0 START_SYSEX (0xF0) -# * 1 SERIAL_DATA (0x60) // command byte -# * 2 SERIAL_CONFIG (0x10) // OR with port (0x11 = SERIAL_CONFIG | HW_SERIAL1) -# * 3 baud (bits 0 - 6) -# * 4 baud (bits 7 - 13) -# * 5 baud (bits 14 - 20) // need to send 3 bytes for baud even if value is < 14 bits -# * 6 rxPin (0-127) [optional] // only set if platform requires RX pin number -# * 7 txPin (0-127) [optional] // only set if platform requires TX pin number -# * 6|8 END_SYSEX (0xF7) -# */ - -sub packet_serial_config { - my ( $self, $port, $baud, $rxPin, $txPin ) = @_; - if (defined($rxPin) && defined($txPin)) { - return $self->packet_sysex_command( SERIAL_DATA, - $SERIAL_COMMANDS->{SERIAL_CONFIG} | $port, - $baud & 0x7f, - ($baud >> 7) & 0x7f, - ($baud >> 14) & 0x7f, - $rxPin & 0x7f, - $txPin & 0x7f - ); - } else { - return $self->packet_sysex_command( SERIAL_DATA, - $SERIAL_COMMANDS->{SERIAL_CONFIG} | $port, - $baud & 0x7f, - ($baud >> 7) & 0x7f, - ($baud >> 14) & 0x7f - ); - } -} - -#/* serial listen -# * ------------------------------- -# * 0 START_SYSEX (0xF0) -# * 1 SERIAL_DATA (0x60) // command byte -# * 2 SERIAL_LISTEN (0x70) // OR with port to switch to (0x79 = switch to SW_SERIAL1) -# * 3 END_SYSEX (0xF7) -# */ - -sub packet_serial_listen { - my ( $self, $port ) = @_; - return $self->packet_sysex_command( SERIAL_DATA, - $SERIAL_COMMANDS->{SERIAL_LISTEN} | $port - ); -} - -#/* serial write -# * ------------------------------- -# * 0 START_SYSEX (0xF0) -# * 1 SERIAL_DATA (0x60) -# * 2 SERIAL_WRITE (0x20) // OR with port (0x21 = SERIAL_WRITE | HW_SERIAL1) -# * 3 data 0 (LSB) -# * 4 data 0 (MSB) -# * 5 data 1 (LSB) -# * 6 data 1 (MSB) -# * ... // up to max buffer - 5 -# * n END_SYSEX (0xF7) -# */ - -sub packet_serial_write { - my ( $self, $port, @serialdata ) = @_; - - if (scalar @serialdata) { - my @data; - push_array_as_two_7bit(\@serialdata,\@data); - return $self->packet_sysex_command( SERIAL_DATA, - $SERIAL_COMMANDS->{SERIAL_WRITE} | $port, - @data - ); - } else { - return $self->packet_sysex_command( SERIAL_DATA, - $SERIAL_COMMANDS->{SERIAL_WRITE} | $port - ); - } -} - -#/* serial read -# * ------------------------------- -# * 0 START_SYSEX (0xF0) -# * 1 SERIAL_DATA (0x60) -# * 2 SERIAL_READ (0x30) // OR with port (0x31 = SERIAL_READ | HW_SERIAL1) -# * 3 SERIAL_READ_MODE (0x00) // 0x00 => read continuously, 0x01 => stop reading -# * 4 maxBytesToRead (lsb) // 0x00 for all bytes available [optional] -# * 5 maxBytesToRead (msb) // 0x00 for all bytes available [optional] -# * 4|6 END_SYSEX (0xF7) -# */ - -sub packet_serial_read { - my ( $self, $port, $command, $maxBytes ) = @_; - - if ($maxBytes > 0) { - return $self->packet_sysex_command( SERIAL_DATA, - $SERIAL_COMMANDS->{SERIAL_READ} | $port, - $command, - $maxBytes & 0x7f, - ($maxBytes >> 7) & 0x7f - ); - } else { - return $self->packet_sysex_command( SERIAL_DATA, - $SERIAL_COMMANDS->{SERIAL_READ} | $port, - $command - ); - } -} - -#/* serial reply -# * ------------------------------- -# * 0 START_SYSEX (0xF0) -# * 1 SERIAL_DATA (0x60) -# * 2 SERIAL_REPLY (0x40) // OR with port (0x41 = SERIAL_REPLY | HW_SERIAL1) -# * 3 data 0 (LSB) -# * 4 data 0 (MSB) -# * 3 data 1 (LSB) -# * 4 data 1 (MSB) -# * ... // up to max buffer - 5 -# * n END_SYSEX (0xF7) -# */ - -sub handle_serial_reply { - my ( $self, $sysex_data ) = @_; - - my $command = shift @$sysex_data; - my $port = $command & 0xF; - my @data = double_7bit_to_array($sysex_data); - return { - port => $port, - data => \@data, - }; -} - -sub shift14bit { - my $data = shift; - my $lsb = shift @$data; - my $msb = shift @$data; - return - defined $lsb - ? defined $msb - ? ( $msb << 7 ) + ( $lsb & 0x7f ) - : $lsb - : undef; -} - -sub double_7bit_to_string { - my ( $data, $numbytes ) = @_; - my $ret; - if ( defined $numbytes ) { - for ( my $i = 0 ; $i < $numbytes ; $i++ ) { - my $value = shift14bit($data); - $ret .= chr($value); - } - } - else { - while (@$data) { - my $value = shift14bit($data); - $ret .= chr($value); - } - } - return $ret; -} - -sub double_7bit_to_array { - my ( $data, $numbytes ) = @_; - my @ret; - if ( defined $numbytes ) { - for ( my $i = 0 ; $i < $numbytes ; $i++ ) { - push @ret, shift14bit($data); - } - } - else { - while (@$data) { - my $value = shift14bit($data); - push @ret, $value; - } - } - return @ret; -} - -sub shift_onewire_device_from_byte_array { - my $buffer = shift; - my $family = shift @$buffer; - if ( defined $family ) { - my @address; - for (my $i=0;$i<6;$i++) { push @address,shift @$buffer; } - my $crc = shift @$buffer; - return { - family => $family, - identity => \@address, - crc => $crc - }; - } - else { - return undef; - } -} - -sub push_value_as_two_7bit { - my ( $value, $buffer ) = @_; - push @$buffer, $value & 0x7f; #LSB - push @$buffer, ( $value >> 7 ) & 0x7f; #MSB -} - -sub push_onewire_device_to_byte_array { - my ( $device, $buffer ) = @_; - push @$buffer, $device->{family}; - for ( my $i = 0 ; $i < 6 ; $i++ ) { push @$buffer, $device->{identity}[$i]; } - push @$buffer, $device->{crc}; -} - -sub push_array_as_two_7bit { - my ( $data, $buffer ) = @_; - my $byte = shift @$data; - while ( defined $byte ) { - push_value_as_two_7bit( $byte, $buffer ); - $byte = shift @$data; - } -} - -sub pack_as_7bit { - my @data = @_; - my @outdata; - my $numBytes = @data; - my $messageSize = ( $numBytes << 3 ) / 7; - for ( my $i = 0 ; $i < $messageSize ; $i++ ) { - my $j = $i * 7; - my $pos = $j >> 3; - my $shift = $j & 7; - my $out = $data[$pos] >> $shift & 0x7F; - printf "%b, %b, %d\n",$data[$pos],$out,$shift if ($out >> 7 > 0); - $out |= ( $data[ $pos + 1 ] << ( 8 - $shift ) ) & 0x7F if ( $shift > 1 && $pos < $numBytes-1 ); - push( @outdata, $out ); - } - return @outdata; -} - -sub unpack_from_7bit { - my @data = @_; - my @outdata; - my $numBytes = @data; - my $outBytes = ( $numBytes * 7 ) >> 3; - for ( my $i = 0 ; $i < $outBytes ; $i++ ) { - my $j = $i << 3; - my $pos = $j / 7; - my $shift = $j % 7; - push( @outdata, - ( $data[$pos] >> $shift ) | - ( ( $data[ $pos + 1 ] << ( 7 - $shift ) ) & 0xFF ) ); - } - return @outdata; -} - -=head2 get_max_compatible_protocol_version - -Search list of implemented protocols for identical or next lower version. - -=cut - -sub get_max_supported_protocol_version { - my ( $self, $deviceProtcolVersion ) = @_; - return "V_2_01" unless (defined($deviceProtcolVersion)); # min. supported protocol version if undefined - return $deviceProtcolVersion if (defined($COMMANDS->{$deviceProtcolVersion})); # requested version if known - - my $maxSupportedProtocolVersion = undef; - foreach my $protocolVersion (sort keys %{$COMMANDS}) { - if ($protocolVersion lt $deviceProtcolVersion) { - $maxSupportedProtocolVersion = $protocolVersion; # nearest lower version if not known - } - } - - return $maxSupportedProtocolVersion; -} - -1; diff --git a/fhem/FHEM/lib/Device/Firmata/README b/fhem/FHEM/lib/Device/Firmata/README deleted file mode 100644 index 20d529c91..000000000 --- a/fhem/FHEM/lib/Device/Firmata/README +++ /dev/null @@ -1,47 +0,0 @@ -Device-Firmata - -Device::Firmata - Perl interface to the Firmata protocol for talking to the arduino microcontroler platform. See http://firmata.org/wiki/Main_Page for more details. - -INSTALLATION - -To install this module, run the following commands: - - perl Makefile.PL - make - make test - make install - -SUPPORT AND DOCUMENTATION - -After installing, you can find documentation for this module with the -perldoc command. - - perldoc Device::Firmata - -You can also look for information at: - - RT, CPAN's request tracker - http://rt.cpan.org/NoAuth/Bugs.html?Dist=Device-Firmata - - AnnoCPAN, Annotated CPAN documentation - http://annocpan.org/dist/Device-Firmata - - CPAN Ratings - http://cpanratings.perl.org/d/Device-Firmata - - Search CPAN - http://search.cpan.org/dist/Device-Firmata/ - - -LICENSE AND COPYRIGHT - -Copyright (C) 2011 amimato -Copyright (C) 2012 ntruchsess -Copyright (C) 2016 jnsbyr - -This program is free software; you can redistribute it and/or modify it -under the terms of either: the GNU General Public License as published -by the Free Software Foundation; or the Artistic License. - -See http://dev.perl.org/licenses/ for more information. - diff --git a/fhem/FHEM/lib/Device/Firmata/license.txt b/fhem/FHEM/lib/Device/Firmata/license.txt deleted file mode 100644 index b654cf035..000000000 --- a/fhem/FHEM/lib/Device/Firmata/license.txt +++ /dev/null @@ -1 +0,0 @@ -perl-firmata is distributed under the same terms as perl itself