Update car monitor asset reload and telemetry
This commit is contained in:
1 parent
6f965f8f3e
commit
5d75ad81bd
8 files changed
+4334
-4366
No files matched your search
@@ -44,37 +44,37 @@ if (($params['log'] ?? '') == '1') {
|
|||||||
$cmdRequested = $params['cmd'] ?? 'se';
|
$cmdRequested = $params['cmd'] ?? 'se';
|
||||||
$cmd = normalize_cmd($cmdRequested);
|
$cmd = normalize_cmd($cmdRequested);
|
||||||
|
|
||||||
if ($cmd === 'se') {
|
if ($cmd === 'se') {
|
||||||
$latest = db_latest($pdo);
|
$latest = db_latest($pdo);
|
||||||
|
|
||||||
if (!$latest) {
|
if (!$latest) {
|
||||||
json_exit([
|
json_exit([
|
||||||
'request_id' => $requestId,
|
'request_id' => $requestId,
|
||||||
'error' => 'no_latest_data'
|
'error' => 'no_latest_data'
|
||||||
], 500);
|
], 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
$ageSeconds = max(0, time() - strtotime((string)$latest['ts']));
|
$ageSeconds = max(0, time() - strtotime((string)$latest['ts']));
|
||||||
$latestUsage = db_latest_usage($pdo);
|
$latestUsage = db_latest_usage($pdo);
|
||||||
$staleReason = null;
|
$staleReason = null;
|
||||||
if ($ageSeconds > 30 && $latestUsage && (int)$latestUsage['tcp_ok'] === 0) {
|
if ($ageSeconds > 30 && $latestUsage && (int)$latestUsage['tcp_ok'] === 0) {
|
||||||
$staleReason = (string)($latestUsage['tcp_error'] ?? 'tcp_failed');
|
$staleReason = (string)($latestUsage['tcp_error'] ?? 'tcp_failed');
|
||||||
}
|
}
|
||||||
|
|
||||||
json_exit([
|
json_exit([
|
||||||
'request_id' => $requestId,
|
'request_id' => $requestId,
|
||||||
'cmd_requested' => 'se',
|
'cmd_requested' => 'se',
|
||||||
'cmd' => $latest['cmd'],
|
'cmd' => $latest['cmd'],
|
||||||
'ts' => $latest['ts'],
|
'ts' => $latest['ts'],
|
||||||
'meta' => [
|
'meta' => [
|
||||||
'age_seconds' => $ageSeconds,
|
'age_seconds' => $ageSeconds,
|
||||||
'stale' => $ageSeconds > 30,
|
'stale' => $ageSeconds > 30,
|
||||||
'stale_reason' => $staleReason,
|
'stale_reason' => $staleReason,
|
||||||
'latest_tcp' => $latestUsage,
|
'latest_tcp' => $latestUsage,
|
||||||
],
|
],
|
||||||
|
|
||||||
'raw_full' => $latest['raw_full'],
|
'raw_full' => $latest['raw_full'],
|
||||||
'raw_trim' => $latest['raw_trim'],
|
'raw_trim' => $latest['raw_trim'],
|
||||||
|
|
||||||
'data' => [
|
'data' => [
|
||||||
'boundary' => (int)$latest['boundary'],
|
'boundary' => (int)$latest['boundary'],
|
||||||
@@ -110,26 +110,26 @@ if ($requestMethod !== 'POST') {
|
|||||||
], 405);
|
], 405);
|
||||||
}
|
}
|
||||||
|
|
||||||
$tcpMs = 0;
|
$tcpMs = 0;
|
||||||
$connectMs = 0;
|
$connectMs = 0;
|
||||||
$readMs = 0;
|
$readMs = 0;
|
||||||
$tcpError = '';
|
$tcpError = '';
|
||||||
$trimError = '';
|
$trimError = '';
|
||||||
$sentBytes = 0;
|
$sentBytes = 0;
|
||||||
$receivedBytes = 0;
|
$receivedBytes = 0;
|
||||||
|
|
||||||
$rawFull = tcp_request(
|
$rawFull = tcp_request(
|
||||||
$cmd,
|
$cmd,
|
||||||
$tcpMs,
|
$tcpMs,
|
||||||
$connectMs,
|
$connectMs,
|
||||||
$readMs,
|
$readMs,
|
||||||
$tcpError,
|
$tcpError,
|
||||||
'api_control',
|
'api_control',
|
||||||
$requestId,
|
$requestId,
|
||||||
$sentBytes,
|
$sentBytes,
|
||||||
$receivedBytes
|
$receivedBytes
|
||||||
);
|
);
|
||||||
$execMs = (int)round((microtime(true) - $tsStart) * 1000);
|
$execMs = (int)round((microtime(true) - $tsStart) * 1000);
|
||||||
|
|
||||||
if ($rawFull === '') {
|
if ($rawFull === '') {
|
||||||
json_exit([
|
json_exit([
|
||||||
@@ -141,16 +141,16 @@ if ($rawFull === '') {
|
|||||||
'client_ip' => $clientIp,
|
'client_ip' => $clientIp,
|
||||||
'ua' => $userAgent,
|
'ua' => $userAgent,
|
||||||
'tcp_ok' => 0,
|
'tcp_ok' => 0,
|
||||||
'tcp_ms' => $tcpMs,
|
'tcp_ms' => $tcpMs,
|
||||||
'connect_ms' => $connectMs,
|
'connect_ms' => $connectMs,
|
||||||
'read_ms' => $readMs,
|
'read_ms' => $readMs,
|
||||||
'sent_bytes' => $sentBytes,
|
'sent_bytes' => $sentBytes,
|
||||||
'received_bytes' => $receivedBytes,
|
'received_bytes' => $receivedBytes,
|
||||||
'total_bytes' => $sentBytes + $receivedBytes,
|
'total_bytes' => $sentBytes + $receivedBytes,
|
||||||
'tcp_error' => ($tcpError !== '' ? $tcpError : 'timeout_or_empty'),
|
'tcp_error' => ($tcpError !== '' ? $tcpError : 'timeout_or_empty'),
|
||||||
'error' => 'CONTROL_CMD_SEND_FAILED'
|
'error' => 'CONTROL_CMD_SEND_FAILED'
|
||||||
], 502);
|
], 502);
|
||||||
}
|
}
|
||||||
|
|
||||||
$rawTrim = make_trim($rawFull, $trimError);
|
$rawTrim = make_trim($rawFull, $trimError);
|
||||||
$data = ($rawTrim !== '') ? parse_trim($rawTrim) : null;
|
$data = ($rawTrim !== '') ? parse_trim($rawTrim) : null;
|
||||||
@@ -174,16 +174,16 @@ json_exit([
|
|||||||
'client_ip' => $clientIp,
|
'client_ip' => $clientIp,
|
||||||
'ua' => $userAgent,
|
'ua' => $userAgent,
|
||||||
'tcp_ok' => 1,
|
'tcp_ok' => 1,
|
||||||
'tcp_ms' => $tcpMs,
|
'tcp_ms' => $tcpMs,
|
||||||
'connect_ms' => $connectMs,
|
'connect_ms' => $connectMs,
|
||||||
'read_ms' => $readMs,
|
'read_ms' => $readMs,
|
||||||
'sent_bytes' => $sentBytes,
|
'sent_bytes' => $sentBytes,
|
||||||
'received_bytes' => $receivedBytes,
|
'received_bytes' => $receivedBytes,
|
||||||
'total_bytes' => $sentBytes + $receivedBytes,
|
'total_bytes' => $sentBytes + $receivedBytes,
|
||||||
'tcp_error' => $tcpError,
|
'tcp_error' => $tcpError,
|
||||||
'accepted' => true,
|
'accepted' => true,
|
||||||
'ack_only' => ($rawTrim === ''),
|
'ack_only' => ($rawTrim === ''),
|
||||||
'raw_full' => $rawFull,
|
'raw_full' => $rawFull,
|
||||||
'raw_trim' => $rawTrim,
|
'raw_trim' => $rawTrim,
|
||||||
'data' => $data
|
'data' => $data
|
||||||
]);
|
]);
|
||||||
+2
-3
@@ -59,12 +59,11 @@ $assets = [];
|
|||||||
foreach (collect_asset_files($root, $scanRoots) as $fullPath) {
|
foreach (collect_asset_files($root, $scanRoots) as $fullPath) {
|
||||||
$relativePath = ltrim(str_replace($rootPath ?: $root, '', $fullPath), DIRECTORY_SEPARATOR);
|
$relativePath = ltrim(str_replace($rootPath ?: $root, '', $fullPath), DIRECTORY_SEPARATOR);
|
||||||
$fileHash = is_readable($fullPath) ? (hash_file('sha256', $fullPath) ?: 'hash-failed') : 'unreadable';
|
$fileHash = is_readable($fullPath) ? (hash_file('sha256', $fullPath) ?: 'hash-failed') : 'unreadable';
|
||||||
$fileVersion = (string)filemtime($fullPath) . '-' . substr($fileHash, 0, 10);
|
$fileVersion = substr($fileHash, 0, 16);
|
||||||
$publicPath = '/car/' . str_replace(DIRECTORY_SEPARATOR, '/', $relativePath);
|
$publicPath = '/custom/car/' . str_replace(DIRECTORY_SEPARATOR, '/', $relativePath);
|
||||||
$fingerprints[] = implode('|', [
|
$fingerprints[] = implode('|', [
|
||||||
ltrim($publicPath, '/'),
|
ltrim($publicPath, '/'),
|
||||||
(string)filesize($fullPath),
|
(string)filesize($fullPath),
|
||||||
(string)filemtime($fullPath),
|
|
||||||
$fileHash,
|
$fileHash,
|
||||||
]);
|
]);
|
||||||
$assets[$publicPath] = $fileVersion;
|
$assets[$publicPath] = $fileVersion;
|
||||||
|
|||||||
@@ -214,20 +214,23 @@
|
|||||||
}).then(function (data) {
|
}).then(function (data) {
|
||||||
if (!data || data.result !== 'ok' || !data.version) return;
|
if (!data || data.result !== 'ok' || !data.version) return;
|
||||||
|
|
||||||
var token = data.version.slice(0, 12);
|
|
||||||
var previous = storeGet(storageKey);
|
var previous = storeGet(storageKey);
|
||||||
var mismatch = loadedAssetMismatch(data.assets);
|
var versionChanged = previous && previous !== data.version;
|
||||||
var forceReload = bfcacheReturn;
|
var latestToken = String(data.version).slice(0, 12);
|
||||||
|
var hasLatestToken = assetTokenFromLocation() === latestToken;
|
||||||
|
var mismatch = !hasLatestToken && loadedAssetMismatch(data.assets);
|
||||||
|
var wasBfcacheReturn = bfcacheReturn;
|
||||||
bfcacheReturn = false;
|
bfcacheReturn = false;
|
||||||
storeSet(storageKey, data.version);
|
storeSet(storageKey, data.version);
|
||||||
|
|
||||||
if (assetTokenFromLocation() !== token || mismatch || forceReload) {
|
if ((mismatch || wasBfcacheReturn) && !hasLatestToken) {
|
||||||
reloadWith(data.version, mismatch || forceReload);
|
reloadWith(data.version, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (previous && previous !== data.version) {
|
if (versionChanged) {
|
||||||
reloadWith(data.version, false);
|
reloadWith(data.version, false);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}).then(function () {
|
}).then(function () {
|
||||||
running = false;
|
running = false;
|
||||||
|
|||||||
@@ -2,21 +2,21 @@
|
|||||||
"name": "Car Monitor",
|
"name": "Car Monitor",
|
||||||
"short_name": "Car Monitor",
|
"short_name": "Car Monitor",
|
||||||
"description": "Vehicle status monitor",
|
"description": "Vehicle status monitor",
|
||||||
"start_url": "/car/monitor.php?pwa=1",
|
"start_url": "/custom/car/monitor.php?pwa=1",
|
||||||
"scope": "/car/",
|
"scope": "/custom/car/",
|
||||||
"display": "standalone",
|
"display": "standalone",
|
||||||
"orientation": "portrait",
|
"orientation": "portrait",
|
||||||
"background_color": "#0f172a",
|
"background_color": "#0f172a",
|
||||||
"theme_color": "#0f172a",
|
"theme_color": "#0f172a",
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
"src": "/car/assets/icon-192.png",
|
"src": "/custom/car/assets/icon-192.png",
|
||||||
"sizes": "192x192",
|
"sizes": "192x192",
|
||||||
"type": "image/png",
|
"type": "image/png",
|
||||||
"purpose": "any maskable"
|
"purpose": "any maskable"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "/car/assets/icon-512.png",
|
"src": "/custom/car/assets/icon-512.png",
|
||||||
"sizes": "512x512",
|
"sizes": "512x512",
|
||||||
"type": "image/png",
|
"type": "image/png",
|
||||||
"purpose": "any maskable"
|
"purpose": "any maskable"
|
||||||
|
|||||||
+14
-14
@@ -62,19 +62,19 @@ function collect_once(): bool
|
|||||||
$tcpError = '';
|
$tcpError = '';
|
||||||
$trimError = '';
|
$trimError = '';
|
||||||
|
|
||||||
$sentBytes = 0;
|
$sentBytes = 0;
|
||||||
$receivedBytes = 0;
|
$receivedBytes = 0;
|
||||||
$rawFull = tcp_request(
|
$rawFull = tcp_request(
|
||||||
'se',
|
'se',
|
||||||
$tcpMs,
|
$tcpMs,
|
||||||
$connectMs,
|
$connectMs,
|
||||||
$readMs,
|
$readMs,
|
||||||
$tcpError,
|
$tcpError,
|
||||||
'collector_se',
|
'collector_se',
|
||||||
null,
|
null,
|
||||||
$sentBytes,
|
$sentBytes,
|
||||||
$receivedBytes
|
$receivedBytes
|
||||||
);
|
);
|
||||||
if ($rawFull === '') {
|
if ($rawFull === '') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -105,4 +105,4 @@ if (!is_fast_poll_state() && should_skip_non_driving()) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mark_attempt();
|
mark_attempt();
|
||||||
collect_once();
|
collect_once();
|
||||||
+750
-680
File diff suppressed because it is too large.
Load diff
+3452
-3556
File diff suppressed because it is too large.
Load diff
+37
-37
@@ -1,44 +1,44 @@
|
|||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
require __DIR__ . '/common.php';
|
require __DIR__ . '/common.php';
|
||||||
|
|
||||||
const WORKER_IDLE_SLEEP_USEC = 200000;
|
const WORKER_IDLE_SLEEP_USEC = 200000;
|
||||||
|
|
||||||
if (PHP_SAPI !== 'cli') {
|
if (PHP_SAPI !== 'cli') {
|
||||||
fwrite(STDERR, "tcp_worker.php must run from CLI\n");
|
fwrite(STDERR, "tcp_worker.php must run from CLI\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
$lockFp = fopen('/tmp/car_tcp_worker.lock', 'c');
|
$lockFp = fopen('/tmp/car_tcp_worker.lock', 'c');
|
||||||
if ($lockFp === false) {
|
if ($lockFp === false) {
|
||||||
fwrite(STDERR, "failed to open worker lock\n");
|
fwrite(STDERR, "failed to open worker lock\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!flock($lockFp, LOCK_EX | LOCK_NB)) {
|
if (!flock($lockFp, LOCK_EX | LOCK_NB)) {
|
||||||
fwrite(STDERR, "worker already running\n");
|
fwrite(STDERR, "worker already running\n");
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
register_shutdown_function(static function () use ($lockFp): void {
|
register_shutdown_function(static function () use ($lockFp): void {
|
||||||
@flock($lockFp, LOCK_UN);
|
@flock($lockFp, LOCK_UN);
|
||||||
@fclose($lockFp);
|
@fclose($lockFp);
|
||||||
});
|
});
|
||||||
|
|
||||||
db_ensure_tcp_queue_schema(db());
|
db_ensure_tcp_queue_schema(db(true));
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
$job = tcp_queue_claim_next(db());
|
$job = tcp_queue_claim_next(db(true));
|
||||||
if (!$job) {
|
if (!$job) {
|
||||||
usleep(WORKER_IDLE_SLEEP_USEC);
|
usleep(WORKER_IDLE_SLEEP_USEC);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
tcp_worker_process_job($job);
|
tcp_worker_process_job($job);
|
||||||
} catch (Throwable $e) {
|
} catch (Throwable $e) {
|
||||||
fwrite(STDERR, date('c') . ' ' . $e->getMessage() . "\n");
|
fwrite(STDERR, date('c') . ' ' . $e->getMessage() . "\n");
|
||||||
usleep(1000000);
|
usleep(1000000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user