# Basic Usage

This package uses gRPC messaging to interface with the device. The following sections cover basic usage patterns for sampling and system monitoring.

## uQRNG Sampling

uQRNG offers two types of sampling for users: `uqrng_direct.client.UqrngClient.GetEntropy()`, which allows users to sample uniform random bits, and `uqrng_direct.client.UqrngClient.GetNoise()`, which enables sampling from uniform random qudits with values ranging from 0 to 99,999. These qudits are used to generate the uniform random bits provided by `uqrng_direct.client.UqrngClient.GetEntropy()`. In order to sample from the device must fill in the IP address specific to your device in place of “YOUR DEVICE_IP_ADDRESS” in each of the below examples.

### Pulling random bits

The device streams random bits as bytes. Below is a basic pattern on how to get random bits from the uqrng device and convert it into a variety of formats:

    from uqrng_direct.client import UqrngClient
    # MUST FILL IN "YOUR DEVICE IP ADDRESS" based on your devices network location
    qrng_client = UqrngClient(ip_address="YOUR DEVICE IP ADDRESS")
    qrn_bytes = qrng_client.GetEntropy(bits_of_entropy = 32*2)
    print("As bytes:", qrn_bytes)
    print("As bitstring:", qrn_bytes.decode("utf-8"))
    # convert to four 32 bit integers
    print("As integer:", [int(qrn_bytes[i:i+32], 2) for i in range(0, 32*2, 32)])

Output:

    As bytes: b'1101000001101101010111100001011000101100001100100111111011110010'
    As bitstring: 1101000001101101010111100001011000101100001100100111111011110010
    As integer: [3496828438, 741506802]

### Reading Raw Data from the Device

Similarly, users can sample from the underlying uniform qudits (0-99,999) as follows:

    from uqrng_direct.client import UqrngClient

    ip_address = "YOUR_DEVICE_IP_ADDRESS"
    uqrng_client = UqrngClient(ip_address="YOUR DEVICE IP ADDRESS",
                               port="YOUR DEVICE PORT")
    qrn_raw = uqrng_client.GetNoise(number_of_samples_requested=10)
    print(qrn_raw)

Output:

    [75924, 96750, 31464, 66745, 97927, 95729, 44771, 43926, 20887, 80849],

### Additional Sampling Parameters

Since each request is processed on demand, if two users attempt to access the device to sample simultaneously, then the device will return a gRPC UNAVAILABLE error with the message “QRNG currently in use”. However, both of the above functions have parameters to allow users to wait either indefinitely or a specific time frame for their request to be processed:

- wait: bool - whether to wait for device to become available

- timeout: int - seconds to wait for QRNG device to become available. If is less than or equal to 0, then the request waits indefinitely.

## Health Tests and System Monitoring

There are several utility functions provided to support system monitoring and running health tests.

### Checking System Status

Below is an example of how to request the uQRNG device’s current system status:.

    qrng_client.SystemStatus()

Output:

    {'status_code': 1, 'status_desc': 'SAMPLING'}

For more information on possible device statuses see `uqrng_direct.utils.SysStatus`.

### Requesting System Information

System information includes several useful fields about the uQRNG device including the current server version and the delay in minutes between schedule health tests. For full details see `uqrng_direct.utils.SystemInfoDict`.

    qrng_client.SystemInfo()

Output:

    {'server_version': 'v1.0.0', 'device_type': 'uQRNG', 'test_interval_mins': 0}

### Running Health Tests On-Demand

The device also supports running NIST SP 800-22 STS version 2.1.2 which is a comprehensive suite developed by the National Institute of Standards and Technology (NIST) for testing the randomness of binary sequences. It is designed to evaluate the quality of random number generators (RNGs) and cryptographic sequences. For more information on the tests, see here. The device is configured to run all tests on 10 bitstreams of 1 million bits each. Each health test takes roughly 10 minutes to run. However, the device will be available during health testing because after samples are collected, the health tests will run in the background. There are two methods to initiate a health test: on demand and through the scheduling system. When a health test starts, it clears the results of the previous test to prevent users from retrieving outdated information. Below is example code to wait for an on-demand health test:

    health_res = qrng_client.HealthTest(wait=True)

### Scheduling Health Tests

As seen in the above `uqrng_direct.client.SystemInfo()` response there is a field which tells what is the current number of minutes between each set of consecutive health tests. The default for this interval is 0 which indicates that health tests will not be run going forward. Users can configure the interval on which health tests will be run by doing the following:

    sched_status = qrng_client.ScheduleHealthTest(test_interval_mins=120)
    print(qrng_client.SystemInfo())

Output:

    {'server_version': 'v1.0.0', 'device_type': 'uQRNG', 'test_interval_mins': 120}

Whenever the system is shut down, the health testing schedule reverts to its default settings. By default, a single health test runs at startup with no additional tests scheduled. Any desired ongoing test scheduling must be reconfigured after your device is powered on.

### Health Test Results

Health test results can be retrieved using the `uqrng_direct.client.UqrngClient.FetchHealthTest()` function or by employing the wait option for `uqrng_direct.client.UqrngClient.HealthTest()`. The `uqrng_direct.client.Uqrngclient.FetchHealthTest()`} function retrieves the most recent test result for the device.

    health_res = qrng_client.FetchHealthTest()
    print("Dict of Results:\n", health_res)
    print("Health result table:\n", health_res["summary_table"])

Output (truncated):

    Dict of Results:
     {'all_pass': True,
     'test_detail': {
        'elapsed_time_mins': 29.21890640258789,
        'test_name': [
            'Frequency',
            'BlockFrequency',
            ... # truncated
            , 'LinearComplexity'],
        'p_value': [0.5341460108757019,
            ... # truncated
            0.12232500314712524],
        'proportion_pass': [1.0,
            ... # truncated
            1.0],
        'passed': [True,

            True]},
        'summary_table':
            'STATISTICAL_TEST       | P-VALUE  | PROPORTION | PASS
        ... # truncated
            | True\nLinearComplexity       | 0.122325 | 1.0        | True\n'}

    Health result table:
     STATISTICAL_TEST       | P-VALUE  | PROPORTION | PASS
    -----------------------------------------------------
    Frequency              | 0.534146 | 1.0        | True
    BlockFrequency         | 0.350485 | 1.0        | True
    NonOverlappingTemplate | 0.0      | 1.0        | True
    ... # truncated
    Serial                 | 0.350485 | 0.9        | True
    LinearComplexity       | 0.122325 | 1.0        | True

A truncated example of health test output is shown above to see full description of the health test results object see `uqrng_direct.utils.ResultNIST`.

#### Understanding Health Test Results

In conducting randomness tests, it is not uncommon to observe occasional failures due to random chance. To mitigate this phenomenon, adjustments such as analyzing multiple tests and observing the distribution of p-values are often employed. If failures are repeatedly observed in the same test, this raises concerns about the underlying entropy. Additionally, the sample size used is crucial in determining the overall validity of a battery of tests. It is important to consider the number of tests being run and apply an appropriate multiple test correction to the resulting p-values. Since most entropy tests are statistical in nature, it is important to remember that even a true random number generator (tRNG) will occasionally fail a test when a sufficient number of tests are conducted, due to the inherent probabilities of false positives. For further guidance, QCi recommends reading Chapter 10 of the book Beautiful Testing, available as a free PDF. For further guidance on appropriate testing methodology and implementation for randomness testing, we also offer paid consulting services. Please contact our sales team by submitting the Contact Form on our website with subject “QRNG CONSULTING”.

## Troubleshooting and Support

If you encounter any issues with your uQRNG device or this package contact our customer support for assistance.