From ba023cddca6c4d61c4081e3d0bd10fe5de913415 Mon Sep 17 00:00:00 2001 From: DaveNeudoerffer Date: Tue, 26 Nov 2024 17:40:32 -0500 Subject: [PATCH 1/3] eliminate warning from newer perls on GetOptions with duplicate templates --- bin/mh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bin/mh b/bin/mh index 3859f35fc..8ee182aa4 100755 --- a/bin/mh +++ b/bin/mh @@ -355,6 +355,8 @@ EOF for (@parms1) { push( @parms2, "$1=s" ) if /^([^\s\#\=]+)\s*=/; } + my %parmsh = map{ $_, 1} @parms2; + @parms2 = keys %parmsh; use Getopt::Long; if ( !&GetOptions( \%config_parms_startup, "h", "help", "run=s", "run_parms=s", @parms2 ) or ( $config_parms_startup{h} or $config_parms_startup{help} ) ) From 3a53af8f0a84398bc122d18061e8521e6b3e09e9 Mon Sep 17 00:00:00 2001 From: DaveNeudoerffer Date: Tue, 26 Nov 2024 17:41:52 -0500 Subject: [PATCH 2/3] Use nstore for AoG data so it is perl distro independent -- change is backward compatible --- lib/AoGSmartHome_Items.pm | 4 ++-- lib/http_server_aog.pl | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/AoGSmartHome_Items.pm b/lib/AoGSmartHome_Items.pm index 57680fcb1..7bb0625de 100644 --- a/lib/AoGSmartHome_Items.pm +++ b/lib/AoGSmartHome_Items.pm @@ -212,7 +212,7 @@ package AoGSmartHome_Items; @AoGSmartHome_Items::ISA = ('Generic_Item'); use Data::Dumper; -use Storable; +use Storable qw(nstore retrieve); #--------------Logging and debugging functions---------------------------------------- @@ -1441,7 +1441,7 @@ sub uuid { my $idmap->{'idmap'} = $self->{'idmap'}; my $file = $::config_parms{'data_dir'} . '/aogsmarthome_temp.saved_id'; - store $idmap, $file; + nstore $idmap, $file; return $highid; diff --git a/lib/http_server_aog.pl b/lib/http_server_aog.pl index 9d7389aa9..ed5b8966a 100644 --- a/lib/http_server_aog.pl +++ b/lib/http_server_aog.pl @@ -33,7 +33,7 @@ =head2 METHODS use Config; use MIME::Base64; use JSON qw(decode_json); -use Storable; +use Storable qw(nstore retrieve); use constant RANDBITS => $Config{randbits}; use constant RAND_MAX => 2**RANDBITS; @@ -271,7 +271,7 @@ sub process_http_aog { &aog_debug( 1, "token for user '$Authorized' did not exist; generated token '$token'" ); - store $oauth_tokens, $::config_parms{'aog_oauth_tokens_file'}; + nstore $oauth_tokens, $::config_parms{'aog_oauth_tokens_file'}; } return http_redirect("$HTTP_ARGV{'redirect_uri'}#access_token=$token&token_type=bearer&state=$HTTP_ARGV{'state'}"); From df3f37cfe3647d8c69b2b15412a2524b5bdb4455 Mon Sep 17 00:00:00 2001 From: DaveNeudoerffer Date: Tue, 26 Nov 2024 17:43:19 -0500 Subject: [PATCH 3/3] Added ability to add discovery parms to mqtt items --- lib/mqtt.pm | 25 +++++++++++++++++++++++++ lib/mqtt_discovery.pm | 4 ++-- lib/mqtt_items.pm | 40 +++++++++++++++++++++++++++++++--------- 3 files changed, 58 insertions(+), 11 deletions(-) diff --git a/lib/mqtt.pm b/lib/mqtt.pm index 9fb80aabe..6189342b7 100644 --- a/lib/mqtt.pm +++ b/lib/mqtt.pm @@ -492,6 +492,7 @@ sub new { # $self->set( 'on', $self ); &::Reload_post_add_hook( \&mqtt::generate_voice_commands, 1, $self ); + &::Reload_post_add_hook( \&mqtt::create_discovery_data, 1, $self ); return $self; } @@ -1175,6 +1176,7 @@ sub list_retained_topics { } foreach my $interface ( @interface_list ) { + $interface->log( "Listing retained topics for: $interface->{instance}" ); for my $topic ( keys %{$interface->{retained_topics}} ) { my $handled = $interface->{retained_topics}->{$topic}; $interface->log( "$$interface{instance} retained topic: ($handled) $topic" ); @@ -1222,6 +1224,29 @@ sub cleanup_discovery_topics { # ------------------------------------------------------------------------------ +=item C<(create_discovery_data())> + +Create discovery messages for each discoverable item. + +=cut + +sub create_discovery_data { + my ($self) = @_; + my $obj; + + if( !$self->isConnected ) { + $self->error( "Unable to publish discovery data -- $self->{instance} not connected" ); + return 0; + } + $self->log( "Creating and publishing discovery data for all discoverable objects" ); + for my $obj ( @{ $self->{objects} } ) { + if( $obj->can( 'create_discovery_message' ) ) { + $obj->create_discovery_message(); + } + } + return 1; +} + =item C<(publish_discovery_data())> Publish discovery messages for each discoverable item. diff --git a/lib/mqtt_discovery.pm b/lib/mqtt_discovery.pm index d0a7c7794..df4c747df 100644 --- a/lib/mqtt_discovery.pm +++ b/lib/mqtt_discovery.pm @@ -114,7 +114,7 @@ sub new { #### mqtt_DiscoveredItem } else { $mqtt_type = $disc_type; } - } elsif( grep( /^${disc_type}$/, ('light', 'switch', 'binary_sensor', 'sensor', 'scene', 'select') ) ) { + } elsif( grep( /^${disc_type}$/, ('light', 'switch', 'binary_sensor', 'sensor', 'scene', 'select', 'text', 'number') ) ) { $mqtt_type = $disc_type; } else { $disc_obj->debug( 1, "UNRECOGNIZED DISCOVERY TYPE: $disc_type" ); @@ -185,7 +185,7 @@ sub new { #### mqtt_DiscoveredItem } else { $obj_name .= $device_id; } - $obj_name =~ s/ /_/g; + $obj_name =~ s/[^\w]/_/g; $obj = ::get_object_by_name( $obj_name ); if( $obj ) { $disc_obj->error( "Trying to create object that already exists: $obj_name" ); diff --git a/lib/mqtt_items.pm b/lib/mqtt_items.pm index 49a5e83cc..ff90d6694 100644 --- a/lib/mqtt_items.pm +++ b/lib/mqtt_items.pm @@ -619,6 +619,8 @@ sub decode_mqtt_payload { $msg = $value; } elsif( $$self{mqtt_type} eq 'text' ) { $msg = $value; + } elsif( $$self{mqtt_type} eq 'number' ) { + $msg = $value; } elsif( $$self{mqtt_type} eq 'cover' ) { $msg = $value; } else { @@ -660,6 +662,7 @@ sub encode_mqtt_payload { if( $self->{mqtt_type} eq 'sensor' || $self->{mqtt_type} eq 'select' || $self->{mqtt_type} eq 'text' + || $self->{mqtt_type} eq 'number' || $self->{mqtt_type} eq 'cover' ) { $payload = $setval; @@ -984,6 +987,7 @@ package mqtt_LocalItem; use strict; use Data::Dumper; +use Hash::Merge; @mqtt_LocalItem::ISA = ( 'mqtt_BaseItem' ); @@ -1003,7 +1007,7 @@ sub new { ### mqtt_LocalItem $base_type = $local_object->{mqttlocalitem}->{base_type} if ((defined $local_object->{mqttlocalitem}->{base_type} ) and (!$type)); $device_class = $local_object->{mqttlocalitem}->{device_class} if ((defined $local_object->{mqttlocalitem}->{device_class} ) and (!$device_class)); - if( !grep( /^$base_type$/, ('light','switch','binary_sensor', 'sensor', 'scene', 'select', 'text', 'cover' ) ) ) { + if( !grep( /^$base_type$/, ('light','switch','binary_sensor', 'sensor', 'scene', 'select', 'text', 'number', 'cover' ) ) ) { $interface->error( "Invalid mqtt type '$type'" ); return; } @@ -1079,6 +1083,8 @@ sub new { ### mqtt_LocalItem } } elsif( $base_type eq 'text' ) { $self->{disc_info}->{command_topic} = "$topic_prefix/set"; + } elsif( $base_type eq 'number' ) { + $self->{disc_info}->{command_topic} = "$topic_prefix/set"; } $self->{is_local} = 1; @@ -1100,11 +1106,7 @@ sub new { ### mqtt_LocalItem $self->{disc_info}->{unique_id} =~ s/ /_/g; } - if( ref $self->{local_item}->{mqtt_device_info} ) { - $self->{disc_info}->{device} = $self->{local_item}->{mqtt_device_info}; - } - - $self->create_discovery_message(); + # $self->create_discovery_message(); # my $d = Data::Dumper->new( [$self] ); @@ -1116,6 +1118,26 @@ sub new { ### mqtt_LocalItem return $self; } +sub add_discovery_info { + my ($self,$extra_disc_info) = @_; + + my $merger = Hash::Merge->new( 'RIGHT_PRECEDENT' ); + $self->{disc_info} = $merger->merge( $self->{disc_info}, $extra_disc_info ); + +# foreach my $key (keys %{$extra_disc_info}) { +# if( exists $extra_disc_info && ref $extra_disc_info->{$key} eq 'HASH' ) { +# if( !exists $self->{disc_info}->{$key} ) { +# $self->{disc_info}->{$key} = {}; +# } +# for my $key2 (keys %{$extra_disc_info->{ +# +# if( exists $self->{disc_info}->{$key} ) { +# $self->log( "Overriding $key in discovery info for: $self->{object_name}" ); +# } +# $self->{disc_info}->{$key} = $extra_disc_info->{$key}; +# } +} + =item C Process received mqtt message =cut @@ -1138,7 +1160,7 @@ sub receive_mqtt_message { $obj_name = $self->get_object_name(); } if( $topic eq $self->{disc_info}->{state_topic} ) { - $self->debug( 1, "LocalItem $obj_name ignoring state topic message" ); + $self->debug( 2, "LocalItem $obj_name ignoring state topic message" ); } elsif( $topic eq $self->{disc_info}->{command_topic} ) { if( $retained ) { # command messages should never be retained, but just in case... @@ -1595,7 +1617,7 @@ sub new { ### mqtt_RemoteItem $self->{disc_info}->{unique_id} = 'tasmota_' . $self->{mqtt_name}; $self->{disc_info}->{unique_id} =~ s/ /_/g; - $self->create_discovery_message(); + # $self->create_discovery_message(); # We may need flags to deal with XML, JSON or Text return $self; @@ -1680,7 +1702,7 @@ sub new { ### mqtt_InstMqttItem $self->{disc_info}->{unique_id} = $self->{mqtt_name}; $self->{disc_info}->{unique_id} =~ s/ /_/g; - $self->create_discovery_message(); + # $self->create_discovery_message(); # $self->debug( 1, "InstMqttItem created: \n" . Dumper( $self ) );