App-OpenHAP

 view release on metacpan or  search on metacpan

lib/Protocol/HAP/Server.pm  view on Meta::CPAN

	    if $self->{cancel} && defined $self->{event_flush_timer};
	$self->{event_flush_timer} = undef;

	return;
}

# Send an EVENT/1.0 notification to the subscribed sessions, through
# the output contract. Do not send it to the originating session when
# the caller gives one (HAP-HTTP.md §14).
sub send_event ( $self, $aid, $iid, $value, $originator = undef )
{
	my $key  = "$aid.$iid";
	my $subs = $self->{event_subscriptions}{$key} // {};

	my $event_body = $self->{json}->encode( {
			characteristics =>
			    [ { aid => $aid, iid => $iid, value => $value } ] }
	);
	my $event_msg = Protocol::HAP::HTTP::build_event($event_body);

	for my $session ( values %$subs ) {
		next unless $session && $session->is_encrypted;
		next if defined $originator && $session == $originator;

		$self->{output}->( $session, $session->encrypt($event_msg) );
	}

	return;
}

# --- identity and discovery -----------------------------------------------

sub is_paired ($self)
{
	my $pairings = $self->{store}->load_pairings;
	return scalar( keys %$pairings ) > 0;
}

sub add_accessory ( $self, $accessory )
{
	$self->{bridge}->add_bridged_accessory($accessory);

	return;
}

sub get_bridged_accessories ($self)
{
	return $self->{bridge}->get_bridged_accessories;
}

sub get_config_number ($self)
{
	return $self->{store}->get_config_number;
}

# $self->update_config_number:
#	Increment c# when the accessory database changed since the
#	last run (HAP-mDNS.md §3.1). The host calls this after
#	device loading. It compares a digest of the accessory
#	structure against the stored one.
sub update_config_number ($self)
{
	my @parts;
	for my $accessory ( $self->{bridge}->get_all_accessories ) {
		push @parts, "a$accessory->{aid}";
		for my $service ( $accessory->get_services ) {
			push @parts,
			    "s$service->{iid}:" . $service->to_json->{type};
			for my $char ( $service->get_characteristics ) {
				push @parts,
				      "c$char->{iid}:"
				    . $char->to_json->{type} . ':'
				    . $char->{format};
			}
		}
	}
	my $digest = unpack( 'H*', sha512( join( ';', @parts ) ) );

	my $stored = $self->{store}->get_config_digest;
	if ( !defined $stored ) {

		# On the first run, record the digest. c# stays at
		# its initial value of 1.
		$self->{store}->save_config_digest($digest);
	}
	elsif ( $stored ne $digest ) {
		$self->{store}->increment_config_number;
		$self->{store}->save_config_digest($digest);
		$self->{logger}
		    ->info( 'Accessory database changed, c# is now %d',
			$self->get_config_number );
	}

	return $self->get_config_number;
}

sub get_device_id ($self)
{
	return Protocol::HAP::device_id( $self->{accessory_ltpk} );
}

# $self->mdns_txt_records:
#	The TXT records of the advertisement, as a hash reference
#	[HAP-mDNS §3]. The host formats and publishes them; the wire
#	format belongs to the host's mDNS responder, not to HAP.
sub mdns_txt_records ($self)
{
	# Note: pv=1, not 1.1. mdnsd uses '.' as the TXT record
	# delimiter and does not support escaping. HomeKit accepts
	# pv=1.
	my $records = {
		'c#' => $self->get_config_number,
		'ff' => 0,
		'id' => $self->get_device_id,
		'md' => $self->{name},
		'pv' => '1',
		's#' => 1,
		'sf' => $self->is_paired ? 0 : 1,
		'ci' => $self->{category},
	};



( run in 3.164 seconds using v1.01-cache-2.11-cpan-364913b4093 )