jfr*_*d00 5 startup ntpd clock raspbian
我有一个运行 Raspbian(Debian 衍生产品)的 Raspberry Pi,它可以记录实时温度。作为其中的一部分,我需要一个精确到几秒钟的时钟。在服务器启动时的正常操作中,我知道 Raspberry Pi 会定期通过网络连接到 NTP 服务器,以确保其本地时钟合理地接近正确的时间。这种精度水平适合我的应用程序。Raspberry Pi 没有电池供电的时钟来在服务器关闭或断电时保持时间,因此当它第一次启动时,系统时间不正确,直到它建立互联网连接并通过 NTP 获取正确时间。
我发现一个问题是当停电并且 Raspberry Pi 在没有电源的情况下关闭一段时间,然后在某个时间后(比如 30 分钟)恢复供电。Pi 启动,我的应用程序启动并再次开始记录温度,但 Pi 上的时钟不正确,因此它以错误的时间戳记录温度。它似乎以某种方式保存了最后一个已知时间并从那里恢复(重新启动时它不会重置为纪元时间)。最终,当 Pi 所在的 LAN 恢复并重新获得互联网连接时,Pi 将更正其时间(通过 NTP),但在此之前,我记录了不准确的时间戳。
我想弄清楚解决这个问题的最佳行动方案是什么?
出于维护原因,我宁愿不添加电池支持的附加时钟(不希望任何人必须更换电池,因为这本质上是嵌入式设备,用户不易访问)。
我愿意让我的应用程序推迟记录温度,直到我知道从网络中准确检索了时间,但我什至不知道如何检测该状态。任何人都知道如何知道现在何时从 NTP 服务器更新时间并且现在是正确的?
我的应用程序是通过在启动时运行脚本来启动的。
关于如何解决这个问题的任何其他想法?
我决定在我的解决方案中需要一个函数,该函数将返回一个在系统时间准确时解决的承诺。然后,我可以在启动时调用该函数,并使用其反馈来了解何时再次开始记录温度。为此,我决定使用 ntpClient 自己获取准确的时间并将其与本地系统时间进行比较。当两者达到期望的精度时,我就可以解决承诺。如果不是,我设置一个计时器并重新检查时间,继续直到最终本地系统时间变得足够准确。到目前为止,在几次停电期间(这也是最初发现时间不准确问题的地方),该功能运行得很好。
这是我使用的代码:
const Promise = require('bluebird');
const ntpClient = Promise.promisifyAll(require('ntp-client'));
const log = require('./log');
function Decay(startT, maxT, decayAmount, decayTimes) {
// startT is initial delay (e.g. 5 seconds)
// maxT is the max delay this ever returns (e.g. 5 minutes)
// decayAmount is how much to decay when a threshold is crossed (e.g. increase by 0.5)
// decayTimes is how many invocations should trigger a decayAmount (e.g. every 5 times)
// example: var d = new Decay(5000, 5*60*1000, .5, 5);
// each 5 seconds, to a max of 5 minutes, getting 50% longer every 5 invocations
// make sure decayTimes is at least 1 and not negative
decayTimes = Math.max(decayTimes, 1);
var num = 0;
var currentDelay = startT;
var start = Date.now();
this.val = function() {
var elapsed = Date.now() - start;
// if evenly divisible by decayTimes, then bump the increment
if (num !== 0 && num % decayTimes === 0) {
currentDelay = Math.min(Math.round((1 + decayAmount) * currentDelay), maxT);
}
++num;
return currentDelay;
};
}
function checkSystemTime(precision) {
precision = precision || 5000;
return ntpClient.getNetworkTimeAsync("pool.ntp.org", 123).then(function(ntpTime) {
return Math.abs(ntpTime.getTime() - Date.now()) <= precision;
});
}
function waitForAccurateSystemTime(precision, howLong) {
var start = Date.now();
// retry starts every 5 seconds, repeats 5 times, then increases by 50%
// up until longest retry time of once every 15 minutes
var decay = new Decay(5000, 15*60*1000, .5, 5);
var errCntr = 0;
var inaccurateCntr = 0;
function logRetries() {
// only log anything if there were more than five consecutive errors
if (errCntr > 5 || inaccurateCntr > 0) {
log(7, "Time synchronization issue, errCntr = " + errCntr + ", inaccurateCntr = " + inaccurateCntr);
}
}
return new Promise(function(resolve, reject) {
function check() {
checkSystemTime(precision).then(function(accurate) {
if (accurate) {
resolve(true);
} else {
++inaccurateCntr;
again();
}
}, again);
}
function again() {
++errCntr;
if (errCntr == 10) {
// only log once here that we're in a retry loop on 10th retry
// final logging will be done later
log(7, "In retry loop waiting for system time to agree with ntp server time");
}
// if we're only supposed to go for a certain amount of time, then check to see
// if we exceeded that amount of time. If not, set timer for next decay() value.
if (!howLong || Date.now() - start <= howLong) {
setTimeout(check, decay.val());
} else {
var err = "timeout waiting for accurate system time";
log(7, err);
reject(err);
}
}
check();
}).then(function(result) {
logRetries();
return result;
}).catch(function(err) {
logRetries();
throw err;
});
}
module.exports = {
checkSystemTime: checkSystemTime,
waitForAccurateSystemTime: waitForAccurateSystemTime,
Decay: Decay
};
Run Code Online (Sandbox Code Playgroud)
而且,我这样使用它:
const validTime = require("./valid-time");
validTime.waitForAccurateSystemTime(2 * 60 * 1000, 0).then({
// start operation here that requires accurate system time
}).catch({
// abort process, no accurate system time could be found
});
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
6321 次 |
最近记录: |