OpenHAP::Test::Controller(3p) Perl Library Manual OpenHAP::Test::Controller(3p)

OpenHAP::Test::Controller - minimal HomeKit controller for tests

    use OpenHAP::Test::Controller;
    my $c = OpenHAP::Test::Controller->new(
        host => '127.0.0.1',
        port => 51827,
        pin  => '031-45-154',
    );
    $c->pair_setup  or die 'pair-setup failed: ' . $c->last_error;
    $c->pair_verify or die 'pair-verify failed: ' . $c->last_error;
    my $res = $c->request('GET', '/accessories');
    my $put = $c->request('PUT', '/characteristics',
        '{"characteristics":[{"aid":2,"iid":11,"value":true}]}',
        { 'Content-Type' => 'application/hap+json' });
    my $event = $c->next_event;
    $c->remove_pairing;    # cleanup for test teardown

A minimal HomeKit controller used by conformance and integration tests. It completes SRP-6a pair-setup (M1-M6), X25519 pair-verify, and speaks the ChaCha20-Poly1305 session framing, either over TCP against a live accessory or in-process through an injected transport.

The controller follows the repository error convention: methods return undef (bare return) on protocol or transport errors, recording the TLV error code (or a message string) in "last_error"; they die only on programming errors.

Create a controller. Arguments: "host" (default 127.0.0.1), "port" (default 51827), "pin" (setup code, default 031-45-154), "controller_id" (pairing identifier, default openhap-test-ctrl), "timeout" (socket timeout in seconds, default 5), and "transport".

"transport", when given, is a code ref "($request_bytes) -" $response_bytes> replacing the TCP socket; this enables in-process use against an OpenHAP::HAP instance without sockets. Request and response bytes are pre-encryption/post-encryption wire bytes.

An Ed25519 controller identity is generated once per controller.

pair_setup()

Complete pair-setup M1-M6 with the configured PIN. On success the accessory LTPK and pairing identifier are stored on the controller and true is returned.

pair_verify()

Complete pair-verify M1-M4 and switch the connection to encrypted session framing. When the accessory LTPK is known from a prior "pair_setup", the accessory signature in M2 is verified against it.

Perform one HTTP request over the session, encrypted once pair-verify has completed. Returns a hash ref with "status", "headers" (lower cased names) and "body".

Wait for an EVENT/1.0 message, decrypt and parse it. Returns a hash ref with "status", "headers" and "body", or undef on timeout. Without an explicit $timeout the wait is bounded by the session timeout, which honors OPENHAP_TEST_TIMEOUT - pass a literal only for short negative probes ("no event arrives"). Event frames split across socket reads are reassembled without desynchronizing the session nonce counter. Requires a socket connection.

Add a pairing over POST /pairings (method AddPairing).

Remove a pairing (default: this controller's own).

list_pairings()

Return an array ref of hashes with "identifier", "ltpk" and "permissions".

last_error()

The TLV error code (numeric) or message string of the last failure.

is_encrypted()

True once pair-verify has switched the session to encrypted framing.

close()

Close the socket connection and reset session state.

Test-only namespace: not part of the production daemon and never a dependency of production modules. Ships to the integration VM together with the integration tests.

OpenHAP::Test::Controller::SRP, OpenHAP::Test::Integration, spec/HAP-Pairing.md, spec/HAP-Encryption.md

2026-07-27 OpenBSD