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:
parent
8af8e98c5d
commit
b7e37e6043
@ -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
|
||||
|
@ -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;
|
@ -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;
|
@ -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
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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
@ -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
@ -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.
|
||||
|
@ -1 +0,0 @@
|
||||
perl-firmata is distributed under the same terms as perl itself
|
Loading…
x
Reference in New Issue
Block a user