ntp-shm


Namentp-shm JSON
Version 2.0.2 PyPI version JSON
download
home_page
SummaryPure Python NTP shared memory library.
upload_time2023-11-04 18:16:38
maintainer
docs_urlNone
author
requires_python>=3.7
license
keywords gps time chrony ntp serial shm ntpshm
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Overview
A pure Python interface to the NTP shared memory segment with no external
dependencies.

The only platform-dependent part of this library is the `SHM_CREAT` constant,
which seems to always be the octal value of 01000 (Linux and BSDs). Technically
the size of `time_t` is also platform-dependent, but it's 2021 and this should
be 64 bit everywhere.

# Prerequisites
Python: 3.7+

OSs: Posix-compliant with the System V shared memory interface.

This uses `ctypes` for direct access to memory and shared memory routines. This
will dynamically load the system's C library to access `shmget()` and `shmat()`
functions.

# Usage

## NTP Shared Memory
The `NtpShm` class wraps up access to the NTP shared memory segments. See the
[NTP documentation](https://docs.ntpsec.org/latest/driver_shm.html) for
information on the contents of this memory and how to safely access it.

Example use:
```python
from ntp_shm import NtpShm

seg = NtpShm(segment=0)

# Access copies of the memory segment (ShmTime) through read()/write()
shm_time = seg.read()
shm_time.count += 1
shm_time.clock_time_sec = 42
# ...
seg.write(shm_time)

# Dynamic, direct access (by ref) through .ref
shm_time = seg.ref  # Or just use seg.ref directly
shm_time.count += 1
shm_time.clock_time_sec = 42
# ...
```

The `ShmTime` object is a `ctypes` structure with a few extra properties for
convenience, and with fields renamed slightly to be more pythonic. The
convenience properties can be used to set or get the clock or receive times
using `datetime` objects or integer time in nanoseconds.

```python
>>> shm_time = seg.ref
>>> seg.ref.receive_dt
datetime.datetime(2021, 9, 6, 13, 45, 3, 495830, tzinfo=datetime.timezone.utc)
>>> seg.ref.receive_dt
datetime.datetime(2021, 9, 6, 13, 45, 4, 440210, tzinfo=datetime.timezone.utc)
>>> shm_time.clock_ns
1630935919000000000
```

Keep in mind that the `datetime` representation is only accurate to the
microsecond.

**Important**: Direct access to the shared memory segment suffers from race
conditions. Since the time values are split up across multiple fields, these
may be modified in between field reads leading to consumers reading corrupted
values.

The NTP documentation (above) specifies two different methods of updating and
reading from the shared memory segment to avoid this issue. Writing via mode 1
is implemented in the `ShmTime.update()` method. This can be used to update
the clock and receive times:

```python
from ntp_shm import util, NtpShm

seg = NtpShm()

clock_time_ns = some_function_that_gives_integer_nanoseconds()
receive_time_ns = util.datetime_to_ns(datetime.datetime.now())

seg.update(clock_time_ns, receive_time_ns)
```

Since Python lacks memory barriers or cache synchronization controls, its still
not 100% guaranteed that the `update()` method will be issue free.

## NTP Bridge
Included is a utility command: `ntp-shm bridge`. This acts as a very basic
NMEA0183 bridge to NTP shared memory. It reads lines from a file input, looking
for and parsing valid GPRMC NMEA sentences. Valid times, after a small holdoff
to allow for stabilization, are passed to the NTP shared memory segment.

The NMEA sentences must come from a file-like device, such as a character
device or pipe (stdin). For GPSs connected to a serial tty device, use `stty`
to configure the device for direct access. Alternatively, use one of many
applications to handle the serial interface and pipe the output to `ntp-shm
bridge`.

Example tty setup for raw access (on FreeBSD).
```shell
stty -f /dev/ttyu1.init raw 9600
```

Test the tty configuration using `cat /dev/ttyu1`. The output should be
smooth, without extra blank lines or non-printable characters.

To bridge the NMEA data on `ttyu1` to segment 0:
```shell
ntp-shm bridge -p /dev/ttyu1 -s 0
```

To create a persistent process, consider using `daemon` (FreeBSD) or
`daemonize` (Linux) and your system's service manager.

# Installation
From pypi:
```shell
pip install ntp-shm
```

From your local checkout:
```shell
pip install [--user] .
```

or

```shell
python setup.py install [--user]
```

            

Raw data

            {
    "_id": null,
    "home_page": "",
    "name": "ntp-shm",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.7",
    "maintainer_email": "",
    "keywords": "gps,time,chrony,ntp,serial,shm,ntpshm",
    "author": "",
    "author_email": "\"Stefan R. Filipek\" <srfilipek@gmail.com>",
    "download_url": "https://files.pythonhosted.org/packages/84/a4/2117cb5d4a17caea67cde98e2f1899eb2070716f4a6aa2ad1d470de94d5f/ntp-shm-2.0.2.tar.gz",
    "platform": null,
    "description": "# Overview\nA pure Python interface to the NTP shared memory segment with no external\ndependencies.\n\nThe only platform-dependent part of this library is the `SHM_CREAT` constant,\nwhich seems to always be the octal value of 01000 (Linux and BSDs). Technically\nthe size of `time_t` is also platform-dependent, but it's 2021 and this should\nbe 64 bit everywhere.\n\n# Prerequisites\nPython: 3.7+\n\nOSs: Posix-compliant with the System V shared memory interface.\n\nThis uses `ctypes` for direct access to memory and shared memory routines. This\nwill dynamically load the system's C library to access `shmget()` and `shmat()`\nfunctions.\n\n# Usage\n\n## NTP Shared Memory\nThe `NtpShm` class wraps up access to the NTP shared memory segments. See the\n[NTP documentation](https://docs.ntpsec.org/latest/driver_shm.html) for\ninformation on the contents of this memory and how to safely access it.\n\nExample use:\n```python\nfrom ntp_shm import NtpShm\n\nseg = NtpShm(segment=0)\n\n# Access copies of the memory segment (ShmTime) through read()/write()\nshm_time = seg.read()\nshm_time.count += 1\nshm_time.clock_time_sec = 42\n# ...\nseg.write(shm_time)\n\n# Dynamic, direct access (by ref) through .ref\nshm_time = seg.ref  # Or just use seg.ref directly\nshm_time.count += 1\nshm_time.clock_time_sec = 42\n# ...\n```\n\nThe `ShmTime` object is a `ctypes` structure with a few extra properties for\nconvenience, and with fields renamed slightly to be more pythonic. The\nconvenience properties can be used to set or get the clock or receive times\nusing `datetime` objects or integer time in nanoseconds.\n\n```python\n>>> shm_time = seg.ref\n>>> seg.ref.receive_dt\ndatetime.datetime(2021, 9, 6, 13, 45, 3, 495830, tzinfo=datetime.timezone.utc)\n>>> seg.ref.receive_dt\ndatetime.datetime(2021, 9, 6, 13, 45, 4, 440210, tzinfo=datetime.timezone.utc)\n>>> shm_time.clock_ns\n1630935919000000000\n```\n\nKeep in mind that the `datetime` representation is only accurate to the\nmicrosecond.\n\n**Important**: Direct access to the shared memory segment suffers from race\nconditions. Since the time values are split up across multiple fields, these\nmay be modified in between field reads leading to consumers reading corrupted\nvalues.\n\nThe NTP documentation (above) specifies two different methods of updating and\nreading from the shared memory segment to avoid this issue. Writing via mode 1\nis implemented in the `ShmTime.update()` method. This can be used to update\nthe clock and receive times:\n\n```python\nfrom ntp_shm import util, NtpShm\n\nseg = NtpShm()\n\nclock_time_ns = some_function_that_gives_integer_nanoseconds()\nreceive_time_ns = util.datetime_to_ns(datetime.datetime.now())\n\nseg.update(clock_time_ns, receive_time_ns)\n```\n\nSince Python lacks memory barriers or cache synchronization controls, its still\nnot 100% guaranteed that the `update()` method will be issue free.\n\n## NTP Bridge\nIncluded is a utility command: `ntp-shm bridge`. This acts as a very basic\nNMEA0183 bridge to NTP shared memory. It reads lines from a file input, looking\nfor and parsing valid GPRMC NMEA sentences. Valid times, after a small holdoff\nto allow for stabilization, are passed to the NTP shared memory segment.\n\nThe NMEA sentences must come from a file-like device, such as a character\ndevice or pipe (stdin). For GPSs connected to a serial tty device, use `stty`\nto configure the device for direct access. Alternatively, use one of many\napplications to handle the serial interface and pipe the output to `ntp-shm\nbridge`.\n\nExample tty setup for raw access (on FreeBSD).\n```shell\nstty -f /dev/ttyu1.init raw 9600\n```\n\nTest the tty configuration using `cat /dev/ttyu1`. The output should be\nsmooth, without extra blank lines or non-printable characters.\n\nTo bridge the NMEA data on `ttyu1` to segment 0:\n```shell\nntp-shm bridge -p /dev/ttyu1 -s 0\n```\n\nTo create a persistent process, consider using `daemon` (FreeBSD) or\n`daemonize` (Linux) and your system's service manager.\n\n# Installation\nFrom pypi:\n```shell\npip install ntp-shm\n```\n\nFrom your local checkout:\n```shell\npip install [--user] .\n```\n\nor\n\n```shell\npython setup.py install [--user]\n```\n",
    "bugtrack_url": null,
    "license": "",
    "summary": "Pure Python NTP shared memory library.",
    "version": "2.0.2",
    "project_urls": {
        "Bug Tracker": "https://gitlab.com/srfilipek/ntp-shm/-/issues",
        "Homepage": "https://gitlab.com/srfilipek/ntp-shm"
    },
    "split_keywords": [
        "gps",
        "time",
        "chrony",
        "ntp",
        "serial",
        "shm",
        "ntpshm"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "4225c86941823d3ce6b3222050f8b2d5a7aefee3dbfb67a67484ad6f6081cac4",
                "md5": "b3afeaeddf7f8727296011857118c296",
                "sha256": "b18657abf946f41d71527d5200af3c9d7c6ee2a3b4c18437041f2df2ca585b91"
            },
            "downloads": -1,
            "filename": "ntp_shm-2.0.2-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "b3afeaeddf7f8727296011857118c296",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.7",
            "size": 10995,
            "upload_time": "2023-11-04T18:16:37",
            "upload_time_iso_8601": "2023-11-04T18:16:37.562529Z",
            "url": "https://files.pythonhosted.org/packages/42/25/c86941823d3ce6b3222050f8b2d5a7aefee3dbfb67a67484ad6f6081cac4/ntp_shm-2.0.2-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "84a42117cb5d4a17caea67cde98e2f1899eb2070716f4a6aa2ad1d470de94d5f",
                "md5": "d83f0e9b7d21070a74497418b576f5c5",
                "sha256": "74c9344d058bfd36cedd5ae0fb8033c4926e0a8c55c722cf82491c08c19e6d75"
            },
            "downloads": -1,
            "filename": "ntp-shm-2.0.2.tar.gz",
            "has_sig": false,
            "md5_digest": "d83f0e9b7d21070a74497418b576f5c5",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.7",
            "size": 13655,
            "upload_time": "2023-11-04T18:16:38",
            "upload_time_iso_8601": "2023-11-04T18:16:38.835345Z",
            "url": "https://files.pythonhosted.org/packages/84/a4/2117cb5d4a17caea67cde98e2f1899eb2070716f4a6aa2ad1d470de94d5f/ntp-shm-2.0.2.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-11-04 18:16:38",
    "github": false,
    "gitlab": true,
    "bitbucket": false,
    "codeberg": false,
    "gitlab_user": "srfilipek",
    "gitlab_project": "ntp-shm",
    "lcname": "ntp-shm"
}
        
Elapsed time: 2.23495s