2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-03-10 09:16:53 +00:00

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
This commit is contained in:
jensb 2020-12-20 19:47:51 +00:00
parent 8af8e98c5d
commit b7e37e6043
14 changed files with 1 additions and 3812 deletions

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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 ,

File diff suppressed because it is too large Load Diff

View File

@ -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;

File diff suppressed because it is too large Load Diff

View File

@ -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.

View File

@ -1 +0,0 @@
perl-firmata is distributed under the same terms as perl itself