From 119c9a3885d7579fcd6be4ecd1d047eb3847edf3 Mon Sep 17 00:00:00 2001 From: jensb <> Date: Mon, 1 Jan 2018 10:42:43 +0000 Subject: [PATCH] lib/Device/Firmata: bump driver vesion to 0.63 (Forum #81815) git-svn-id: https://svn.fhem.de/fhem/trunk@15744 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/FHEM/lib/Device/Firmata.pm | 38 +++-- fhem/FHEM/lib/Device/Firmata/Changes | 59 ++++++++ fhem/FHEM/lib/Device/Firmata/Constants.pm | 10 +- fhem/FHEM/lib/Device/Firmata/Platform.pm | 74 ++++++++- fhem/FHEM/lib/Device/Firmata/Protocol.pm | 176 +++++++++++++++++++++- fhem/FHEM/lib/Device/Firmata/README | 47 ++++++ fhem/FHEM/lib/Device/Firmata/license.txt | 1 + fhem/MAINTAINER.txt | 2 +- 8 files changed, 376 insertions(+), 31 deletions(-) create mode 100644 fhem/FHEM/lib/Device/Firmata/Changes create mode 100644 fhem/FHEM/lib/Device/Firmata/README create mode 100644 fhem/FHEM/lib/Device/Firmata/license.txt diff --git a/fhem/FHEM/lib/Device/Firmata.pm b/fhem/FHEM/lib/Device/Firmata.pm index 5e866d65f..b3185daa9 100644 --- a/fhem/FHEM/lib/Device/Firmata.pm +++ b/fhem/FHEM/lib/Device/Firmata.pm @@ -8,18 +8,18 @@ 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.59 +Version 0.63 =cut -our $VERSION = '0.59'; +our $VERSION = '0.63'; our $DEBUG = 0; @@ -58,34 +58,32 @@ sub open { # -------------------------------------------------- # Establish a connection to Arduino via the serial port # - my ( $self, $serial_port, $opts ) = @_; + 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"; + 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; + $platform->probe; + return $platform; } sub listen { # -------------------------------------------------- # Listen on socket and wait for Arduino to establish a connection # - my ( $pkg, $ip, $port, $opts ) = @_; + my ( $pkg, $ip, $port, $opts ) = @_; - my $netio = "Device::Firmata::IO::NetIO"; - eval "require $netio"; - - return $netio->listen( $ip, $port, $opts ) or die "Could not bind to socket"; - + 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/Changes b/fhem/FHEM/lib/Device/Firmata/Changes new file mode 100644 index 000000000..71f834ac2 --- /dev/null +++ b/fhem/FHEM/lib/Device/Firmata/Changes @@ -0,0 +1,59 @@ +Revision history for Device-Firmata + +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 index 01ca350ed..f2e01082f 100644 --- a/fhem/FHEM/lib/Device/Firmata/Constants.pm +++ b/fhem/FHEM/lib/Device/Firmata/Constants.pm @@ -29,6 +29,7 @@ use constant ( PIN_ONEWIRE => 7, PIN_STEPPER => 8, PIN_ENCODER => 9, + PIN_SERIAL => 10, PIN_LOW => 0, PIN_HIGH => 1, } @@ -260,6 +261,8 @@ use constant ( # 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 @@ -291,6 +294,8 @@ use constant ( 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 + # Deprecated entries deprecated => [ qw( FIRMATA_STRING SYSEX_I2C_REQUEST SYSEX_I2C_REPLY SYSEX_SAMPLING_INTERVAL ) @@ -315,6 +320,7 @@ use constant ( # 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 @@ -348,14 +354,14 @@ use constant ( 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 # Deprecated entries deprecated => [ qw( FIRMATA_STRING SYSEX_I2C_REQUEST SYSEX_I2C_REPLY SYSEX_SAMPLING_INTERVAL ) ], - }, # /Constants for Version 2.6 + }, # /Constants for Version 2.6 } ); diff --git a/fhem/FHEM/lib/Device/Firmata/Platform.pm b/fhem/FHEM/lib/Device/Firmata/Platform.pm index 6a93d1208..2e205fb60 100644 --- a/fhem/FHEM/lib/Device/Firmata/Platform.pm +++ b/fhem/FHEM/lib/Device/Firmata/Platform.pm @@ -30,6 +30,7 @@ use Device::Firmata::Base servo_resolutions => {}, stepper_resolutions => {}, encoder_resolutions => {}, + serial_resolutions => {}, ports => [], input_ports => [], pins => {}, @@ -44,6 +45,7 @@ use Device::Firmata::Base onewire_observer => [], stepper_observer => [], encoder_observer => [], + serial_observer => [], scheduler_observer => undef, string_observer => undef, @@ -93,6 +95,7 @@ sub detach { $self->{onewire_observer} = []; $self->{stepper_observer} = []; $self->{encoder_observer} = []; + $self->{serial_observer} = []; $self->{scheduler_observer} = undef; $self->{tasks} = []; $self->{metadata} = {}; @@ -119,6 +122,7 @@ sub system_reset { $self->{onewire_observer} = []; $self->{stepper_observer} = []; $self->{encoder_observer} = []; + $self->{serial_observer} = []; $self->{scheduler_observer} = undef; $self->{tasks} = []; $self->{metadata} = {}; @@ -186,7 +190,7 @@ sub messages_handle { # Handle metadata information $command eq 'REPORT_VERSION' and do { - $self->{metadata}{firmware_version} = sprintf "V_%i_%02i", + $self->{metadata}{protocol_version} = sprintf "V_%i_%02i", @$data; last; }; @@ -251,6 +255,7 @@ sub sysex_handle { my @onewirepins; my @stepperpins; my @encoderpins; + my @serialpins; foreach my $pin (keys %$capabilities) { if (defined $capabilities->{$pin}) { @@ -289,6 +294,10 @@ sub sysex_handle { 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}; + } } } $self->{metadata}{input_pins} = \@inputpins; @@ -301,6 +310,7 @@ sub sysex_handle { $self->{metadata}{onewire_pins} = \@onewirepins; $self->{metadata}{stepper_pins} = \@stepperpins; $self->{metadata}{encoder_pins} = \@encoderpins; + $self->{metadata}{serial_pins} = \@serialpins; last; }; @@ -373,6 +383,15 @@ sub sysex_handle { }; 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; + }; } } @@ -392,14 +411,16 @@ 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 response - if ( $self->poll && $self->{metadata}{firmware} && $self->{metadata}{firmware_version} ) { - $self->{protocol}->{protocol_version} = $self->{metadata}{firmware_version}; + 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; @@ -409,8 +430,10 @@ sub probe { } else { $self->capability_query(); } - } else { - $self->firmware_version_query() unless $end_tics - 2 >= time; # version query on last 2 sec only + } elsif ($end_tics - 2 < time) { + # version query on last 2 sec only + $self->firmware_version_query(); + $self->protocol_version_query(); } } return; @@ -540,6 +563,12 @@ pmw_write is an alias for analog_write *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; @@ -831,6 +860,29 @@ sub encoder_detach { 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 @@ -921,6 +973,16 @@ sub observe_encoder { 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} = { diff --git a/fhem/FHEM/lib/Device/Firmata/Protocol.pm b/fhem/FHEM/lib/Device/Firmata/Protocol.pm index 0e4acd3f4..6ab4814ce 100644 --- a/fhem/FHEM/lib/Device/Firmata/Protocol.pm +++ b/fhem/FHEM/lib/Device/Firmata/Protocol.pm @@ -16,6 +16,7 @@ use constant { 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 /; @@ -24,7 +25,7 @@ use Device::Firmata::Base FIRMATA_ATTRIBS => { buffer => [], parse_status => MIDI_PARSE_NORMAL, - protocol_version => 'V_2_04', # We are starting with the highest protocol + protocol_version => MAX_PROTOCOL_VERSION, # We are starting with the highest protocol }; $MIDI_DATA_SIZES = { @@ -93,6 +94,14 @@ our $ENCODER_COMMANDS = { 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', @@ -104,6 +113,7 @@ our $MODENAMES = { 7 => 'ONEWIRE', 8 => 'STEPPER', 9 => 'ENCODER', + 10 => 'SERIAL', }; =head1 DESCRIPTION @@ -322,6 +332,11 @@ sub sysex_parse { 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; @@ -421,7 +436,11 @@ sub packet_query_version { } sub handle_query_version_response { - + my ( $self, $data ) = @_; + return { + major_version => shift @$data, + minor_version => shift @$data, + }; } sub handle_string_data { @@ -1012,6 +1031,138 @@ sub handle_encoder_response { 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; @@ -1133,4 +1284,25 @@ sub unpack_from_7bit { 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 new file mode 100644 index 000000000..20d529c91 --- /dev/null +++ b/fhem/FHEM/lib/Device/Firmata/README @@ -0,0 +1,47 @@ +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 new file mode 100644 index 000000000..b654cf035 --- /dev/null +++ b/fhem/FHEM/lib/Device/Firmata/license.txt @@ -0,0 +1 @@ +perl-firmata is distributed under the same terms as perl itself diff --git a/fhem/MAINTAINER.txt b/fhem/MAINTAINER.txt index 592eb5d5f..0c20ee71d 100644 --- a/fhem/MAINTAINER.txt +++ b/fhem/MAINTAINER.txt @@ -504,7 +504,7 @@ FHEM/TR064Utils.pm rudolfkoenig Automatisierung FHEM/UConv.pm loredo FHEM Development FHEM/Unit.pm loredo FHEM Development FHEM/YahooWeatherAPI.pm neubert Unterstuetzende Dienste/Wettermodule -FHEM/lib/Device/Firmata/* ntruchsess Sonstige Systeme +FHEM/lib/Device/Firmata/* jensb Sonstige Systeme FHEM/lib/Device/MySensors/* Hauswart Sonstige Systeme FHEM/lib/MP3/* Reinerlein Multimedia FHEM/lib/Net/MQTT.pod eisler MQTT