Add Peripherals

Overview

Peripherals are the input and output devices that make a reader function as a complete door. A typical door configuration includes a Request-to-Exit (REX) input, a door contact sensor, and a door strike output. These components work together to provide secure, monitored access control.

Key Concepts

Component Type Purpose
REX (Request-to-Exit) Input Detects when someone pushes a button or motion sensor to exit
Door Contact Input Monitors whether the door is open or closed
Door Strike Output Unlocks the door when access is granted
Slave Reader Reader Secondary reader (exit side of door)
Auxiliary Input Input Additional monitoring (glass break, tamper, etc.)

Reader Peripheral Types (ReaderPeripheralTypes Enum)

Valid values for adding peripherals to a reader:

Value Description
Rex Request-to-Exit device (input)
Contact Door contact sensor (input)
Strike Door strike/lock (output)
Slave Slave/exit reader

Peripheral Behaviour Values

Value Description
0 Normally Closed (NC) - Circuit is closed when inactive
1 Normally Open (NO) - Circuit is open when inactive

Output Mode Values

Value Mode Description
0 Normal Standard momentary activation
1 Toggle Stays in current state until next activation
2 Timed Activates for specified duration

Prerequisites

Before adding peripherals, ensure you have:

  • ✅ A controller with downstream configured
  • ✅ A reader created on the downstream
  • ✅ Knowledge of physical I/O wiring and indices

C# Examples

Add Complete Door Configuration

This example adds REX, door contact, and strike to a reader for a complete door setup.

using Feenics.Keep.WebApi.Wrapper;
using Feenics.Keep.WebApi.Model;

// Assuming 'reader' is a MercuryReaderInfo object
var readerName = reader.CommonName;

// 1. Add REX (Request-to-Exit) Input
var rex = await client.AddPeripheralToReaderAsync(
    (MercuryReaderInfo)reader,
    ReaderPeripheralTypes.Rex,
    new MercuryInputInfo
    {
        CommonName = $"REX - {readerName}",
        Behaviour = 1,      // Normally Open (typical for motion sensors/push buttons)
        Debounce = 2,       // 200ms debounce to prevent false triggers
        SioNumber = 0,      // SIO board number
        SioIndex = 1        // Input index on the SIO (REX typically on index 1)
    });

Console.WriteLine($"Added REX: {rex.CommonName}");

// 2. Add Door Contact Input
var contact = await client.AddPeripheralToReaderAsync(
    (MercuryReaderInfo)reader,
    ReaderPeripheralTypes.Contact,
    new MercuryInputInfo
    {
        CommonName = $"Door Contact - {readerName}",
        Behaviour = 0,      // Normally Closed (door closed = circuit closed)
        Debounce = 4,       // 400ms debounce for door bounce
        SioNumber = 0,
        SioIndex = 0        // Contact typically on index 0
    });

Console.WriteLine($"Added Contact: {contact.CommonName}");

// 3. Add Door Strike Output
var strike = await client.AddPeripheralToReaderAsync(
    (MercuryReaderInfo)reader,
    ReaderPeripheralTypes.Strike,
    new MercuryOutputInfo
    {
        CommonName = $"Strike - {readerName}",
        Mode = 0,               // Normal mode
        ActivationTime = 6,     // Unlock for 6 seconds
        SioNumber = 0,
        SioIndex = 0            // Output index on the SIO
    });

Console.WriteLine($"Added Strike: {strike.CommonName}");

Add Standalone Inputs (Not Reader-Associated)

// Add a general purpose input (e.g., glass break sensor)
var glassBreak = await client.AddInputToControllerAsync(
    controller,
    new MercuryInputInfo
    {
        CommonName = "Glass Break - Lobby Window",
        Behaviour = 0,          // Normally Closed
        Debounce = 1,           // Quick response
        LatchMode = 1,          // Latch until acknowledged
        SioNumber = 1,          // On MR16-IN board
        SioIndex = 0
    });

Complete Door Setup Function

/// <summary>
/// Configures a complete door with all standard peripherals
/// </summary>
public async Task<(MercuryInputInfo rex, MercuryInputInfo contact, MercuryOutputInfo strike)> 
    SetupDoorPeripheralsAsync(MercuryReaderInfo reader, int sioNumber = 0)
{
    var doorName = reader.CommonName;
    
    // Determine indices based on reader position
    // Typically: Reader 1 uses inputs 0-1, Reader 2 uses inputs 2-3, etc.
    var readerIndex = reader.SioIndex ?? 0;
    var inputStartIndex = readerIndex * 2;
    var outputIndex = readerIndex;
    
    // Add REX
    var rex = await client.AddPeripheralToReaderAsync(
        reader,
        ReaderPeripheralTypes.Rex,
        new MercuryInputInfo
        {
            CommonName = $"REX - {doorName}",
            Behaviour = 1,          // NO
            Debounce = 2,
            SioNumber = sioNumber,
            SioIndex = inputStartIndex + 1
        }) as MercuryInputInfo;
    
    // Add Contact
    var contact = await client.AddPeripheralToReaderAsync(
        reader,
        ReaderPeripheralTypes.Contact,
        new MercuryInputInfo
        {
            CommonName = $"Contact - {doorName}",
            Behaviour = 0,          // NC
            Debounce = 4,
            SioNumber = sioNumber,
            SioIndex = inputStartIndex
        }) as MercuryInputInfo;
    
    // Add Strike
    var strike = await client.AddPeripheralToReaderAsync(
        reader,
        ReaderPeripheralTypes.Strike,
        new MercuryOutputInfo
        {
            CommonName = $"Strike - {doorName}",
            Mode = 0,
            ActivationTime = 6,
            SioNumber = sioNumber,
            SioIndex = outputIndex
        }) as MercuryOutputInfo;
    
    Console.WriteLine($"Configured door: {doorName}");
    Console.WriteLine($"  REX: Input {inputStartIndex + 1}");
    Console.WriteLine($"  Contact: Input {inputStartIndex}");
    Console.WriteLine($"  Strike: Output {outputIndex}");
    
    return (rex, contact, strike);
}

cURL Examples

Add REX Input

ACCESS_TOKEN="your-access-token"
INSTANCE_KEY="your-instance-key"
READER_KEY="your-reader-key"

# Add REX (Request-to-Exit) input
curl -X POST \
  "https://api.us.acresecurity.cloud/api/f/${INSTANCE_KEY}/peripherals/${READER_KEY}/Rex" \
  -H "Authorization: Bearer ${ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "$type": "Feenics.Keep.WebApi.Model.MercuryInputInfo, Feenics.Keep.WebApi.Model",
    "CommonName": "REX - Front Door",
    "Behaviour": 1,
    "Debounce": 2,
    "SioNumber": 0,
    "SioIndex": 1,
    "IsDisabled": false,
    "LatchMode": 0
  }'

Add Door Contact Input

# Add door contact sensor
curl -X POST \
  "https://api.us.acresecurity.cloud/api/f/${INSTANCE_KEY}/peripherals/${READER_KEY}/Contact" \
  -H "Authorization: Bearer ${ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "$type": "Feenics.Keep.WebApi.Model.MercuryInputInfo, Feenics.Keep.WebApi.Model",
    "CommonName": "Contact - Front Door",
    "Behaviour": 0,
    "Debounce": 4,
    "SioNumber": 0,
    "SioIndex": 0,
    "IsDisabled": false,
    "LatchMode": 0
  }'

Add Door Strike Output

# Add door strike relay
curl -X POST \
  "https://api.us.acresecurity.cloud/api/f/${INSTANCE_KEY}/peripherals/${READER_KEY}/Strike" \
  -H "Authorization: Bearer ${ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "$type": "Feenics.Keep.WebApi.Model.MercuryOutputInfo, Feenics.Keep.WebApi.Model",
    "CommonName": "Strike - Front Door",
    "Mode": 0,
    "ActivationTime": 6,
    "SioNumber": 0,
    "SioIndex": 0
  }'

Input Properties Reference

Property Type Description
CommonName string Descriptive name for the input
Behaviour int 0 = Normally Closed, 1 = Normally Open
Debounce int Debounce time in 100ms increments
LatchMode int 0 = No latch, 1 = Latch until acknowledged
SioNumber int SIO board number
SioIndex int Input point index on the SIO
IsDisabled bool Disable input processing
EntryDelay int? Delay before armed input triggers (seconds)
ExitDelay int? Delay after arming before input becomes active
HoldTime int? Time input must be active before triggering

Output Properties Reference

Property Type Description
CommonName string Descriptive name for the output
Mode int 0 = Normal, 1 = Toggle, 2 = Timed
ActivationTime int Time output stays active (seconds)
SioNumber int SIO board number
SioIndex int Output point index on the SIO

Best Practices

Practice Description
Use consistent naming Include door name and peripheral type in CommonName
Match physical wiring Ensure SioIndex matches actual wiring
Set appropriate debounce REX: 2 (200ms), Contact: 4 (400ms)
Test each peripheral Verify inputs/outputs work before going live
Document I/O mapping Keep a record of which index maps to which wire
Consider fail-safe vs fail-secure Strike mode affects door behavior during power loss

Troubleshooting

Issue Possible Cause Solution
Door won’t unlock Wrong strike output index Verify SioIndex matches physical wiring
Contact shows wrong state Behaviour mismatch Toggle between NC (0) and NO (1)
REX not triggering High debounce value Reduce debounce time
False alarms Low debounce value Increase debounce for noisy environments
Peripheral not found Wrong reader key Verify reader exists and is on correct downstream
Multiple peripherals same index Index conflict Each peripheral needs unique SioIndex