如何在Python中设置硬件时钟?

9
我该如何在嵌入式Linux系统上使用Python设置硬件时钟?
4个回答

13

可能没有比执行 os.system() 调用更简单的方法了。

import os
os.system('hwclock --set %s' % date_str)

或者使用 'date' 命令

import os
os.system('date -s %s' % date_str)

或者,如果你渴望进行一些C编程,可以使用SWIG来封装系统调用...但我认为这样做要比它的价值更高。


只要rtc或rtcN驱动程序存在,就可以通过ioctl,在fcntl中进行操作,参见http://docs.python.org/library/fcntl.html和rtc(4)(或内核的Documentation/rtc.txt)--但是,如果系统上有Python,则hwclock应该很容易适配。 - Arthur Shipkowski
Zdav,感谢你的帮助。只是想提醒一下:我正在使用busybox,首先需要使用“os.system('date -s %s' % date_str)”更改系统时钟,然后使用“os.system('hwclock -w')”从系统时钟设置硬件时钟。问候 - Diego Sueiro

4

Ubuntu 16.04的更新版本:

import subprocess
import shlex

subprocess.call(shlex.split("timedatectl set-ntp false"))  # May be necessary
subprocess.call(shlex.split("sudo date -s '2 OCT 2006 18:00:00'"))
subprocess.call(shlex.split("sudo hwclock -w"))

重要提示:您可能需要更改时间/日期设置以手动设置(set-ntp false),否则它将立即将其改回当前时间。

hwclock -w 根据当前系统时间(由 date 设置)设置硬件时钟。

同时,必须以 sudo 来运行 datehwclock


2

这里使用ioctl来按要求设置硬件时钟(但不是系统时钟)。它避免了多余的进程,但更加复杂。我正在使用pytzdateutil来处理本地/UTC转换。请随意使用该代码(三条款BSD许可证)。使用get_hwclock()获取时钟,使用set_hwclock()设置时钟...

from collections import namedtuple
from datetime import datetime
from fcntl import ioctl
import struct
from dateutil.tz import tzutc
from pytz import timezone


# From `uapi/asm-generic/ioctl.h`
_IOC_NRBITS = 8
_IOC_TYPEBITS = 8
_IOC_SIZEBITS = 14
_IOC_DIRBITS = 2

_IOC_NRMASK = (1 << _IOC_NRBITS) - 1
_IOC_TYPEMASK = (1 << _IOC_TYPEBITS) - 1
_IOC_SIZEMASK = (1 << _IOC_SIZEBITS) - 1
_IOC_DIRMASK = (1 << _IOC_DIRBITS) - 1

_IOC_NRSHIFT = 0
_IOC_TYPESHIFT = _IOC_NRSHIFT + _IOC_NRBITS
_IOC_SIZESHIFT = _IOC_TYPESHIFT + _IOC_TYPEBITS
_IOC_DIRSHIFT = _IOC_SIZESHIFT + _IOC_SIZEBITS

_IOC_NONE = 0
_IOC_WRITE = 1
_IOC_READ = 2


def _IOC(dir, type, nr, size):
    return ((dir << _IOC_DIRSHIFT) |
            (type << _IOC_TYPESHIFT) |
            (nr << _IOC_NRSHIFT) |
            (size << _IOC_SIZESHIFT))


def _IOC_TYPECHECK(t):
    return len(t)


def _IO(type, nr):
    return _IOC(_IOC_NONE, type, nr, 0)


def _IOR(type, nr, size):
    return _IOC(_IOC_READ, type, nr, _IOC_TYPECHECK(size))


def _IOW(type, nr, size):
    return _IOC(_IOC_WRITE, type, nr, _IOC_TYPECHECK(size))


def to_utc(dtobj):
    if dtobj.tzinfo is None:
        dtobj = timezone("UTC").localize(
            dtobj.replace(tzinfo=None) - tzlocal().utcoffset(dtobj))
    return dtobj.astimezone(timezone("UTC"))


class RtcTime(namedtuple(
    # man(4) rtc
    "RtcTime",
    "tm_sec tm_min tm_hour "
    "tm_mday tm_mon tm_year "
    "tm_wday tm_yday tm_isdst"  # Last row is unused.
)):

    _fmt = 9 * "i"

    def __new__(cls, tm_sec=0, tm_min=0, tm_hour=0,
                tm_mday=0, tm_mon=0, tm_year=0,
                tm_wday=0, tm_yday=0, tm_isdst=0):
        return super(RtcTime, cls).__new__(cls, tm_sec, tm_min, tm_hour,
                                            tm_mday, tm_mon, tm_year,
                                            tm_wday, tm_yday, tm_isdst)

    def __str__(self):
        return self.to_datetime().isoformat()

    @classmethod
    def from_datetime(cls, dtobj):
        dt = to_utc(dtobj)
        return cls(tm_sec=dt.second, tm_min=dt.minute, tm_hour=dt.hour,
                   tm_mday=dt.day, tm_mon=dt.month - 1, tm_year=dt.year - 1900)

    def to_datetime(self):
        # From `hwclock.c`.
        return datetime(
            year=self.tm_year + 1900, month=self.tm_mon + 1, day=self.tm_mday,
            hour=self.tm_hour, minute=self.tm_min, second=self.tm_sec,
            tzinfo=tzutc())

    def pack(self):
        return struct.pack(self._fmt, *self)

    @classmethod
    def unpack(cls, buffer):
        return cls._make(struct.unpack(cls._fmt, buffer))


# From `uapi/linux/rtc.h`
rtc_time = RtcTime().pack()
RTC_RD_TIME = _IOR(ord("p"), 0x09, rtc_time)   # 0x80247009
RTC_SET_TIME = _IOW(ord("p"), 0x0a, rtc_time)  # 0x4024700a
del rtc_time


def get_hwclock(devrtc="/dev/rtc"):
    with open(devrtc) as rtc:
        ret = ioctl(rtc, RTC_RD_TIME, RtcTime().pack())
    return RtcTime.unpack(ret).to_datetime()


def set_hwclock(dt, devrtc="/dev/rtc"):
    with open(devrtc) as rtc:
        ioctl(rtc, RTC_SET_TIME, RtcTime.from_datetime(dt).pack())

非常感谢。这个能否作为库使用呢?我被告知复制粘贴是一种不好的模式。 - guettli
@guettli:库:我不知道有没有。就我而言,我认为在代码库内复制和粘贴是一种不好的模式。但是复制第三方代码,将其保存到具有适当许可的文件中,并在生产代码中使用是完全不同的事情:它仍然像DRY一样... - Mathias Laurin

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接