feat: mqtt app update #70
This commit is contained in:
+77
-19
@@ -198,7 +198,7 @@ const sessionDesktop = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks supported features based on global properties.
|
* Checks supported features based on hardware and software.
|
||||||
*
|
*
|
||||||
* @returns {Object} Returns support object with boolean values.
|
* @returns {Object} Returns support object with boolean values.
|
||||||
*/
|
*/
|
||||||
@@ -207,13 +207,16 @@ const checkSupport = () => {
|
|||||||
const status = HARDWARE.display.status;
|
const status = HARDWARE.display.status;
|
||||||
const brightness = HARDWARE.display.brightness;
|
const brightness = HARDWARE.display.brightness;
|
||||||
const keyboard = processRuns("squeekboard");
|
const keyboard = processRuns("squeekboard");
|
||||||
|
const service = serviceRuns(APP.name);
|
||||||
const sudo = sudoRights();
|
const sudo = sudoRights();
|
||||||
|
const deb = APP.build.maker === "deb";
|
||||||
return {
|
return {
|
||||||
batteryLevel: battery.path !== null,
|
batteryLevel: !!battery.path,
|
||||||
displayStatus: status.path !== null && status.command !== null,
|
displayStatus: !!status.path && !!status.command,
|
||||||
displayBrightness: sudo && brightness.path !== null && brightness.max !== null,
|
displayBrightness: sudo && !!brightness.path && !!brightness.max,
|
||||||
keyboardVisibility: keyboard,
|
keyboardVisibility: keyboard,
|
||||||
sudoRights: sudo,
|
sudoRights: sudo,
|
||||||
|
appUpdate: sudo && service && deb,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -689,6 +692,19 @@ const sudoRights = () => {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a service is running using `systemctl`.
|
||||||
|
*
|
||||||
|
* @param {string} name - The service name to check.
|
||||||
|
* @returns {bool} Returns true if the service runs.
|
||||||
|
*/
|
||||||
|
const serviceRuns = (name) => {
|
||||||
|
try {
|
||||||
|
return !!cpr.execSync(`systemctl --user is-active ${name}`, { encoding: "utf8" });
|
||||||
|
} catch {}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if a process is running using `pidof`.
|
* Checks if a process is running using `pidof`.
|
||||||
*
|
*
|
||||||
@@ -765,14 +781,61 @@ const execAsyncCommand = (cmd, args = [], callback = null) => {
|
|||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Execute Async:", error.message);
|
console.error("Execute Async:", error.message);
|
||||||
if (typeof callback === "function") {
|
if (typeof callback === "function") callback(null, error.message);
|
||||||
callback(null, error.message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return proc;
|
return proc;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes a script command asynchronously.
|
||||||
|
*
|
||||||
|
* @param {string} cmd - The script to execute.
|
||||||
|
* @param {Array<string>} args - The arguments for the command.
|
||||||
|
* @param {Function} callback - A callback function that receives the progress or error.
|
||||||
|
* @returns {Object} The spawned process object.
|
||||||
|
*/
|
||||||
|
const execScriptCommand = (cmd, args = [], callback = null) => {
|
||||||
|
let progress = 10;
|
||||||
|
let proc = cpr.spawn(cmd, args);
|
||||||
|
if (typeof callback === "function") callback(progress, null);
|
||||||
|
proc.stdout.on("data", (data) => {
|
||||||
|
if (data) {
|
||||||
|
const lines = data.toString().trim();
|
||||||
|
const output = lines.replace(/\n+/g, "\n").replace(/^\n+|\n+$|\0/g, "");
|
||||||
|
if (output) {
|
||||||
|
console.log(output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
proc.stderr.on("data", (data) => {
|
||||||
|
if (data) {
|
||||||
|
const lines = data.toString().trim();
|
||||||
|
const output = lines.replace(/\n+/g, "\n").replace(/^\n+|\n+$|\0/g, "");
|
||||||
|
if (output) {
|
||||||
|
const matches = output.match(/(\d{1,3})%/g);
|
||||||
|
if (matches) {
|
||||||
|
const match = Math.max(...matches.map((p) => parseInt(p)));
|
||||||
|
const percent = Math.floor(match / 10) * 10;
|
||||||
|
if (percent > 10 && percent > progress) {
|
||||||
|
progress = percent;
|
||||||
|
if (typeof callback === "function") callback(progress - 10, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
proc.on("close", (code) => {
|
||||||
|
if (code !== 0) {
|
||||||
|
console.log(`Script exited with error code ${code}.`);
|
||||||
|
if (typeof callback === "function") callback(null, code);
|
||||||
|
} else {
|
||||||
|
console.log("Script exited successfully.");
|
||||||
|
if (typeof callback === "function") callback(100, null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes a D-Bus method call synchronously using `dbus-send`.
|
* Executes a D-Bus method call synchronously using `dbus-send`.
|
||||||
*
|
*
|
||||||
@@ -788,14 +851,10 @@ const dbusCall = (path, method, values, callback = null) => {
|
|||||||
const args = ["--print-reply", "--type=method_call", `--dest=${dest}`];
|
const args = ["--print-reply", "--type=method_call", `--dest=${dest}`];
|
||||||
try {
|
try {
|
||||||
const output = cpr.execSync([cmd, ...args].join(" ").trim(), { encoding: "utf8" });
|
const output = cpr.execSync([cmd, ...args].join(" ").trim(), { encoding: "utf8" });
|
||||||
if (typeof callback === "function") {
|
if (typeof callback === "function") callback(output.trim().replace(/\0/g, ""), null);
|
||||||
callback(output.trim().replace(/\0/g, ""), null);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Call D-Bus:", error.message);
|
console.error("Call D-Bus:", error.message);
|
||||||
if (typeof callback === "function") {
|
if (typeof callback === "function") callback(null, error.message);
|
||||||
callback(null, error.message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -829,17 +888,13 @@ const dbusMonitor = (path, callback) => {
|
|||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Monitor D-Bus:", error.message);
|
console.error("Monitor D-Bus:", error.message);
|
||||||
if (typeof callback === "function") {
|
if (typeof callback === "function") callback(null, error.message);
|
||||||
callback(null, error.message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
proc.stderr.on("data", (data) => {
|
proc.stderr.on("data", (data) => {
|
||||||
if (data) {
|
if (data) {
|
||||||
console.error("Monitor D-Bus:", data.toString());
|
console.error("Monitor D-Bus:", data.toString());
|
||||||
if (typeof callback === "function") {
|
if (typeof callback === "function") callback(null, data.toString());
|
||||||
callback(null, data.toString());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return proc;
|
return proc;
|
||||||
@@ -889,4 +944,7 @@ module.exports = {
|
|||||||
checkPackageUpgrades,
|
checkPackageUpgrades,
|
||||||
shutdownSystem,
|
shutdownSystem,
|
||||||
rebootSystem,
|
rebootSystem,
|
||||||
|
execSyncCommand,
|
||||||
|
execAsyncCommand,
|
||||||
|
execScriptCommand,
|
||||||
};
|
};
|
||||||
|
|||||||
+80
-25
@@ -39,15 +39,15 @@ const init = async () => {
|
|||||||
// Init globals
|
// Init globals
|
||||||
INTEGRATION.discovery = discovery;
|
INTEGRATION.discovery = discovery;
|
||||||
INTEGRATION.node = `rpi_${deviceId}`;
|
INTEGRATION.node = `rpi_${deviceId}`;
|
||||||
INTEGRATION.root = `${app.getName()}/${INTEGRATION.node}`;
|
INTEGRATION.root = `${APP.name}/${INTEGRATION.node}`;
|
||||||
INTEGRATION.device = {
|
INTEGRATION.device = {
|
||||||
name: `TouchKio ${deviceName}`,
|
name: `${APP.title} ${deviceName}`,
|
||||||
model: model,
|
model: model,
|
||||||
manufacturer: vendor,
|
manufacturer: vendor,
|
||||||
serial_number: serialNumber,
|
serial_number: serialNumber,
|
||||||
identifiers: [INTEGRATION.node],
|
identifiers: [INTEGRATION.node],
|
||||||
sw_version: `${app.getName()}-v${app.getVersion()}`,
|
sw_version: `${APP.name}-v${APP.version}`,
|
||||||
configuration_url: "https://github.com/leukipp/touchkio",
|
configuration_url: APP.homepage,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Connection settings
|
// Connection settings
|
||||||
@@ -62,6 +62,7 @@ const init = async () => {
|
|||||||
console.log(`MQTT Connected: ${url.toString()}\n`);
|
console.log(`MQTT Connected: ${url.toString()}\n`);
|
||||||
|
|
||||||
// Init client controls
|
// Init client controls
|
||||||
|
initApp();
|
||||||
initShutdown();
|
initShutdown();
|
||||||
initReboot();
|
initReboot();
|
||||||
initRefresh();
|
initRefresh();
|
||||||
@@ -109,8 +110,9 @@ const init = async () => {
|
|||||||
update();
|
update();
|
||||||
}, 60 * 1000);
|
}, 60 * 1000);
|
||||||
|
|
||||||
// Update package sensors periodically (60min)
|
// Update upgrade sensors periodically (1h)
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
|
updateApp();
|
||||||
updatePackageUpgrades();
|
updatePackageUpgrades();
|
||||||
}, 3600 * 1000);
|
}, 3600 * 1000);
|
||||||
|
|
||||||
@@ -185,6 +187,57 @@ const publishState = (path, state) => {
|
|||||||
return INTEGRATION.client.publish(root, `${state}`, { qos: 1, retain: true });
|
return INTEGRATION.client.publish(root, `${state}`, { qos: 1, retain: true });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the app update entity and handles the execute logic.
|
||||||
|
*/
|
||||||
|
const initApp = () => {
|
||||||
|
if (!HARDWARE.support.appUpdate) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const root = `${INTEGRATION.root}/app`;
|
||||||
|
const config = {
|
||||||
|
name: "App",
|
||||||
|
unique_id: `${INTEGRATION.node}_app`,
|
||||||
|
command_topic: `${root}/install`,
|
||||||
|
state_topic: `${root}/version/state`,
|
||||||
|
payload_install: "update",
|
||||||
|
device: INTEGRATION.device,
|
||||||
|
};
|
||||||
|
publishConfig("update", config)
|
||||||
|
.on("message", (topic, message) => {
|
||||||
|
if (topic === config.command_topic) {
|
||||||
|
console.log("Update App...");
|
||||||
|
hardware.setDisplayStatus("ON");
|
||||||
|
const args = ["-c", `bash <(wget -qO- ${APP.scripts.install}) update`];
|
||||||
|
hardware.execScriptCommand("bash", args, (progress, error) => {
|
||||||
|
updateApp(progress);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.subscribe(config.command_topic);
|
||||||
|
updateApp();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the app update entity via the mqtt connection.
|
||||||
|
*/
|
||||||
|
const updateApp = async (progress = 0) => {
|
||||||
|
const latest = APP.releases.latest;
|
||||||
|
if (!latest) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const version = {
|
||||||
|
title: latest.title,
|
||||||
|
latest_version: latest.version,
|
||||||
|
installed_version: APP.version,
|
||||||
|
release_summary: latest.summary.slice(0, 250) + "...",
|
||||||
|
release_url: latest.url,
|
||||||
|
update_percentage: progress || null,
|
||||||
|
in_progress: progress && progress > 0 && progress < 100,
|
||||||
|
};
|
||||||
|
publishState("app/version", JSON.stringify(version));
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the shutdown button and handles the execute logic.
|
* Initializes the shutdown button and handles the execute logic.
|
||||||
*/
|
*/
|
||||||
@@ -314,7 +367,7 @@ const initKiosk = () => {
|
|||||||
/**
|
/**
|
||||||
* Updates the kiosk status via the mqtt connection.
|
* Updates the kiosk status via the mqtt connection.
|
||||||
*/
|
*/
|
||||||
const updateKiosk = () => {
|
const updateKiosk = async () => {
|
||||||
const kiosk = WEBVIEW.status;
|
const kiosk = WEBVIEW.status;
|
||||||
publishState("kiosk", kiosk);
|
publishState("kiosk", kiosk);
|
||||||
};
|
};
|
||||||
@@ -373,7 +426,7 @@ const initDisplay = () => {
|
|||||||
/**
|
/**
|
||||||
* Updates the display status, brightness via the mqtt connection.
|
* Updates the display status, brightness via the mqtt connection.
|
||||||
*/
|
*/
|
||||||
const updateDisplay = () => {
|
const updateDisplay = async () => {
|
||||||
const status = hardware.getDisplayStatus();
|
const status = hardware.getDisplayStatus();
|
||||||
const brightness = hardware.getDisplayBrightness();
|
const brightness = hardware.getDisplayBrightness();
|
||||||
publishState("display/power", status);
|
publishState("display/power", status);
|
||||||
@@ -423,7 +476,7 @@ const initKeyboard = () => {
|
|||||||
/**
|
/**
|
||||||
* Updates the keyboard visibility via the mqtt connection.
|
* Updates the keyboard visibility via the mqtt connection.
|
||||||
*/
|
*/
|
||||||
const updateKeyboard = () => {
|
const updateKeyboard = async () => {
|
||||||
const visibility = hardware.getKeyboardVisibility();
|
const visibility = hardware.getKeyboardVisibility();
|
||||||
publishState("keyboard", visibility);
|
publishState("keyboard", visibility);
|
||||||
};
|
};
|
||||||
@@ -432,7 +485,7 @@ const updateKeyboard = () => {
|
|||||||
* Initializes the page number and handles the execute logic.
|
* Initializes the page number and handles the execute logic.
|
||||||
*/
|
*/
|
||||||
const initPageNumber = () => {
|
const initPageNumber = () => {
|
||||||
if (WEBVIEW.viewUrls.length < 3) {
|
if (WEBVIEW.viewUrls.length <= 2) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const root = `${INTEGRATION.root}/page_number`;
|
const root = `${INTEGRATION.root}/page_number`;
|
||||||
@@ -465,7 +518,7 @@ const initPageNumber = () => {
|
|||||||
/**
|
/**
|
||||||
* Updates the page number via the mqtt connection.
|
* Updates the page number via the mqtt connection.
|
||||||
*/
|
*/
|
||||||
const updatePageNumber = () => {
|
const updatePageNumber = async () => {
|
||||||
const pageNumber = WEBVIEW.viewActive || 1;
|
const pageNumber = WEBVIEW.viewActive || 1;
|
||||||
publishState("page_number", pageNumber);
|
publishState("page_number", pageNumber);
|
||||||
};
|
};
|
||||||
@@ -504,7 +557,7 @@ const initPageZoom = () => {
|
|||||||
/**
|
/**
|
||||||
* Updates the page zoom via the mqtt connection.
|
* Updates the page zoom via the mqtt connection.
|
||||||
*/
|
*/
|
||||||
const updatePageZoom = () => {
|
const updatePageZoom = async () => {
|
||||||
const pageZoom = Math.round(WEBVIEW.views[WEBVIEW.viewActive || 1].webContents.getZoomFactor() * 100.0);
|
const pageZoom = Math.round(WEBVIEW.views[WEBVIEW.viewActive || 1].webContents.getZoomFactor() * 100.0);
|
||||||
publishState("page_zoom", pageZoom);
|
publishState("page_zoom", pageZoom);
|
||||||
};
|
};
|
||||||
@@ -539,7 +592,7 @@ const initPageUrl = () => {
|
|||||||
/**
|
/**
|
||||||
* Updates the page url via the mqtt connection.
|
* Updates the page url via the mqtt connection.
|
||||||
*/
|
*/
|
||||||
const updatePageUrl = () => {
|
const updatePageUrl = async () => {
|
||||||
const defaultUrl = WEBVIEW.viewUrls[WEBVIEW.viewActive || 1];
|
const defaultUrl = WEBVIEW.viewUrls[WEBVIEW.viewActive || 1];
|
||||||
const currentUrl = WEBVIEW.views[WEBVIEW.viewActive || 1].webContents.getURL();
|
const currentUrl = WEBVIEW.views[WEBVIEW.viewActive || 1].webContents.getURL();
|
||||||
const pageUrl = !currentUrl || currentUrl.startsWith("data:") ? defaultUrl : currentUrl;
|
const pageUrl = !currentUrl || currentUrl.startsWith("data:") ? defaultUrl : currentUrl;
|
||||||
@@ -555,6 +608,7 @@ const initModel = () => {
|
|||||||
name: "Model",
|
name: "Model",
|
||||||
unique_id: `${INTEGRATION.node}_model`,
|
unique_id: `${INTEGRATION.node}_model`,
|
||||||
state_topic: `${root}/state`,
|
state_topic: `${root}/state`,
|
||||||
|
json_attributes_topic: `${root}/attributes`,
|
||||||
value_template: "{{ value }}",
|
value_template: "{{ value }}",
|
||||||
icon: "mdi:raspberry-pi",
|
icon: "mdi:raspberry-pi",
|
||||||
device: INTEGRATION.device,
|
device: INTEGRATION.device,
|
||||||
@@ -566,9 +620,10 @@ const initModel = () => {
|
|||||||
/**
|
/**
|
||||||
* Updates the model sensor via the mqtt connection.
|
* Updates the model sensor via the mqtt connection.
|
||||||
*/
|
*/
|
||||||
const updateModel = () => {
|
const updateModel = async () => {
|
||||||
const model = hardware.getModel();
|
const model = hardware.getModel();
|
||||||
publishState("model", model);
|
publishState("model", model);
|
||||||
|
publishAttributes("model", HARDWARE.support);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -591,7 +646,7 @@ const initSerialNumber = () => {
|
|||||||
/**
|
/**
|
||||||
* Updates the serial number sensor via the mqtt connection.
|
* Updates the serial number sensor via the mqtt connection.
|
||||||
*/
|
*/
|
||||||
const updateSerialNumber = () => {
|
const updateSerialNumber = async () => {
|
||||||
const serialNumber = hardware.getSerialNumber();
|
const serialNumber = hardware.getSerialNumber();
|
||||||
publishState("serial_number", serialNumber);
|
publishState("serial_number", serialNumber);
|
||||||
};
|
};
|
||||||
@@ -617,7 +672,7 @@ const initNetworkAddress = () => {
|
|||||||
/**
|
/**
|
||||||
* Updates the network address sensor via the mqtt connection.
|
* Updates the network address sensor via the mqtt connection.
|
||||||
*/
|
*/
|
||||||
const updateNetworkAddress = () => {
|
const updateNetworkAddress = async () => {
|
||||||
const networkAddresses = hardware.getNetworkAddresses();
|
const networkAddresses = hardware.getNetworkAddresses();
|
||||||
const [name] = Object.keys(networkAddresses);
|
const [name] = Object.keys(networkAddresses);
|
||||||
const [family] = name ? Object.keys(networkAddresses[name]) : [];
|
const [family] = name ? Object.keys(networkAddresses[name]) : [];
|
||||||
@@ -646,7 +701,7 @@ const initHostName = () => {
|
|||||||
/**
|
/**
|
||||||
* Updates the host name sensor via the mqtt connection.
|
* Updates the host name sensor via the mqtt connection.
|
||||||
*/
|
*/
|
||||||
const updateHostName = () => {
|
const updateHostName = async () => {
|
||||||
const hostName = hardware.getHostName();
|
const hostName = hardware.getHostName();
|
||||||
publishState("host_name", hostName);
|
publishState("host_name", hostName);
|
||||||
};
|
};
|
||||||
@@ -672,7 +727,7 @@ const initUpTime = () => {
|
|||||||
/**
|
/**
|
||||||
* Updates the up time sensor via the mqtt connection.
|
* Updates the up time sensor via the mqtt connection.
|
||||||
*/
|
*/
|
||||||
const updateUpTime = () => {
|
const updateUpTime = async () => {
|
||||||
const upTime = hardware.getUpTime();
|
const upTime = hardware.getUpTime();
|
||||||
publishState("up_time", upTime);
|
publishState("up_time", upTime);
|
||||||
};
|
};
|
||||||
@@ -698,7 +753,7 @@ const initMemorySize = () => {
|
|||||||
/**
|
/**
|
||||||
* Updates the memory size sensor via the mqtt connection.
|
* Updates the memory size sensor via the mqtt connection.
|
||||||
*/
|
*/
|
||||||
const updateMemorySize = () => {
|
const updateMemorySize = async () => {
|
||||||
const memorySize = hardware.getMemorySize();
|
const memorySize = hardware.getMemorySize();
|
||||||
publishState("memory_size", memorySize);
|
publishState("memory_size", memorySize);
|
||||||
};
|
};
|
||||||
@@ -724,7 +779,7 @@ const initMemoryUsage = () => {
|
|||||||
/**
|
/**
|
||||||
* Updates the memory usage sensor via the mqtt connection.
|
* Updates the memory usage sensor via the mqtt connection.
|
||||||
*/
|
*/
|
||||||
const updateMemoryUsage = () => {
|
const updateMemoryUsage = async () => {
|
||||||
const memoryUsage = hardware.getMemoryUsage();
|
const memoryUsage = hardware.getMemoryUsage();
|
||||||
publishState("memory_usage", memoryUsage);
|
publishState("memory_usage", memoryUsage);
|
||||||
};
|
};
|
||||||
@@ -750,7 +805,7 @@ const initProcessorUsage = () => {
|
|||||||
/**
|
/**
|
||||||
* Updates the processor usage sensor via the mqtt connection.
|
* Updates the processor usage sensor via the mqtt connection.
|
||||||
*/
|
*/
|
||||||
const updateProcessorUsage = () => {
|
const updateProcessorUsage = async () => {
|
||||||
const processorUsage = hardware.getProcessorUsage();
|
const processorUsage = hardware.getProcessorUsage();
|
||||||
publishState("processor_usage", processorUsage);
|
publishState("processor_usage", processorUsage);
|
||||||
};
|
};
|
||||||
@@ -776,7 +831,7 @@ const initProcessorTemperature = () => {
|
|||||||
/**
|
/**
|
||||||
* Updates the processor temperature sensor via the mqtt connection.
|
* Updates the processor temperature sensor via the mqtt connection.
|
||||||
*/
|
*/
|
||||||
const updateProcessorTemperature = () => {
|
const updateProcessorTemperature = async () => {
|
||||||
const processorTemperature = hardware.getProcessorTemperature();
|
const processorTemperature = hardware.getProcessorTemperature();
|
||||||
publishState("processor_temperature", processorTemperature);
|
publishState("processor_temperature", processorTemperature);
|
||||||
};
|
};
|
||||||
@@ -805,7 +860,7 @@ const initBatteryLevel = () => {
|
|||||||
/**
|
/**
|
||||||
* Updates the battery level sensor via the mqtt connection.
|
* Updates the battery level sensor via the mqtt connection.
|
||||||
*/
|
*/
|
||||||
const updateBatteryLevel = () => {
|
const updateBatteryLevel = async () => {
|
||||||
const batteryLevel = hardware.getBatteryLevel();
|
const batteryLevel = hardware.getBatteryLevel();
|
||||||
publishState("battery_level", batteryLevel);
|
publishState("battery_level", batteryLevel);
|
||||||
};
|
};
|
||||||
@@ -831,7 +886,7 @@ const initPackageUpgrades = () => {
|
|||||||
/**
|
/**
|
||||||
* Updates the package upgrades sensor via the mqtt connection.
|
* Updates the package upgrades sensor via the mqtt connection.
|
||||||
*/
|
*/
|
||||||
const updatePackageUpgrades = () => {
|
const updatePackageUpgrades = async () => {
|
||||||
const packages = hardware.checkPackageUpgrades();
|
const packages = hardware.checkPackageUpgrades();
|
||||||
const attributes = {
|
const attributes = {
|
||||||
total: packages.length,
|
total: packages.length,
|
||||||
@@ -861,7 +916,7 @@ const initHeartbeat = () => {
|
|||||||
/**
|
/**
|
||||||
* Updates the heartbeat sensor via the mqtt connection.
|
* Updates the heartbeat sensor via the mqtt connection.
|
||||||
*/
|
*/
|
||||||
const updateHeartbeat = () => {
|
const updateHeartbeat = async () => {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const local = new Date(now.getTime() - now.getTimezoneOffset() * 60 * 1000);
|
const local = new Date(now.getTime() - now.getTimezoneOffset() * 60 * 1000);
|
||||||
const heartbeat = local.toISOString().replace(/\.\d{3}Z$/, "");
|
const heartbeat = local.toISOString().replace(/\.\d{3}Z$/, "");
|
||||||
@@ -889,7 +944,7 @@ const initLastActive = () => {
|
|||||||
/**
|
/**
|
||||||
* Updates the last active sensor via the mqtt connection.
|
* Updates the last active sensor via the mqtt connection.
|
||||||
*/
|
*/
|
||||||
const updateLastActive = () => {
|
const updateLastActive = async () => {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const then = WEBVIEW.pointer.time;
|
const then = WEBVIEW.pointer.time;
|
||||||
const lastActive = Math.abs(now - then) / (1000 * 60);
|
const lastActive = Math.abs(now - then) / (1000 * 60);
|
||||||
|
|||||||
+44
-17
@@ -54,8 +54,8 @@ const init = async () => {
|
|||||||
|
|
||||||
// Init global root window
|
// Init global root window
|
||||||
WEBVIEW.window = new BaseWindow({
|
WEBVIEW.window = new BaseWindow({
|
||||||
title: "TouchKio",
|
title: APP.title,
|
||||||
icon: path.join(__dirname, "..", "img", "icon.png"),
|
icon: path.join(APP.path, "img", "icon.png"),
|
||||||
});
|
});
|
||||||
WEBVIEW.window.setMenuBarVisibility(false);
|
WEBVIEW.window.setMenuBarVisibility(false);
|
||||||
WEBVIEW.window.setFullScreen(fullscreen);
|
WEBVIEW.window.setFullScreen(fullscreen);
|
||||||
@@ -91,7 +91,7 @@ const init = async () => {
|
|||||||
});
|
});
|
||||||
WEBVIEW.pager.setBackgroundColor("#00000000");
|
WEBVIEW.pager.setBackgroundColor("#00000000");
|
||||||
WEBVIEW.window.contentView.addChildView(WEBVIEW.pager);
|
WEBVIEW.window.contentView.addChildView(WEBVIEW.pager);
|
||||||
WEBVIEW.pager.webContents.loadFile(path.join(app.getAppPath(), "html", "pager.html"));
|
WEBVIEW.pager.webContents.loadFile(path.join(APP.path, "html", "pager.html"));
|
||||||
|
|
||||||
// Init global widget
|
// Init global widget
|
||||||
WEBVIEW.widget = new WebContentsView({
|
WEBVIEW.widget = new WebContentsView({
|
||||||
@@ -103,7 +103,7 @@ const init = async () => {
|
|||||||
});
|
});
|
||||||
WEBVIEW.widget.setBackgroundColor("#00000000");
|
WEBVIEW.widget.setBackgroundColor("#00000000");
|
||||||
WEBVIEW.window.contentView.addChildView(WEBVIEW.widget);
|
WEBVIEW.window.contentView.addChildView(WEBVIEW.widget);
|
||||||
WEBVIEW.widget.webContents.loadFile(path.join(app.getAppPath(), "html", "widget.html"));
|
WEBVIEW.widget.webContents.loadFile(path.join(APP.path, "html", "widget.html"));
|
||||||
|
|
||||||
// Init global navigation
|
// Init global navigation
|
||||||
WEBVIEW.navigation = new WebContentsView({
|
WEBVIEW.navigation = new WebContentsView({
|
||||||
@@ -115,14 +115,14 @@ const init = async () => {
|
|||||||
});
|
});
|
||||||
WEBVIEW.navigation.setBackgroundColor("#00000000");
|
WEBVIEW.navigation.setBackgroundColor("#00000000");
|
||||||
WEBVIEW.window.contentView.addChildView(WEBVIEW.navigation);
|
WEBVIEW.window.contentView.addChildView(WEBVIEW.navigation);
|
||||||
WEBVIEW.navigation.webContents.loadFile(path.join(app.getAppPath(), "html", "navigation.html"));
|
WEBVIEW.navigation.webContents.loadFile(path.join(APP.path, "html", "navigation.html"));
|
||||||
|
|
||||||
// Register events
|
// Register events
|
||||||
windowEvents();
|
await windowEvents();
|
||||||
widgetEvents();
|
await widgetEvents();
|
||||||
navigationEvents();
|
await navigationEvents();
|
||||||
viewEvents();
|
await viewEvents();
|
||||||
appEvents();
|
await appEvents();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
@@ -166,7 +166,7 @@ const updateView = () => {
|
|||||||
}
|
}
|
||||||
const url = WEBVIEW.views[WEBVIEW.viewActive].webContents.getURL();
|
const url = WEBVIEW.views[WEBVIEW.viewActive].webContents.getURL();
|
||||||
const host = url.startsWith("data:") ? "whoopsie" : new URL(url).host;
|
const host = url.startsWith("data:") ? "whoopsie" : new URL(url).host;
|
||||||
const title = `TouchKio - ${host} (${WEBVIEW.viewActive})`;
|
const title = `${APP.title} - ${host} (${WEBVIEW.viewActive})`;
|
||||||
|
|
||||||
// Update window title
|
// Update window title
|
||||||
console.log(`Update View: ${title}`);
|
console.log(`Update View: ${title}`);
|
||||||
@@ -427,7 +427,7 @@ const resizeView = () => {
|
|||||||
/**
|
/**
|
||||||
* Register window events and handler.
|
* Register window events and handler.
|
||||||
*/
|
*/
|
||||||
const windowEvents = () => {
|
const windowEvents = async () => {
|
||||||
// Handle window resize events
|
// Handle window resize events
|
||||||
WEBVIEW.window.on("ready-to-show", resizeView);
|
WEBVIEW.window.on("ready-to-show", resizeView);
|
||||||
WEBVIEW.window.on("resize", resizeView);
|
WEBVIEW.window.on("resize", resizeView);
|
||||||
@@ -476,7 +476,7 @@ const windowEvents = () => {
|
|||||||
historyForward();
|
historyForward();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Handle window touch events
|
// Check for window touch events (1s)
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const then = WEBVIEW.pointer.time;
|
const then = WEBVIEW.pointer.time;
|
||||||
@@ -495,7 +495,7 @@ const windowEvents = () => {
|
|||||||
/**
|
/**
|
||||||
* Register widget events and handler.
|
* Register widget events and handler.
|
||||||
*/
|
*/
|
||||||
const widgetEvents = () => {
|
const widgetEvents = async () => {
|
||||||
if (!WEBVIEW.widgetEnabled) {
|
if (!WEBVIEW.widgetEnabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -581,7 +581,7 @@ const widgetEvents = () => {
|
|||||||
/**
|
/**
|
||||||
* Register navigation events and handler.
|
* Register navigation events and handler.
|
||||||
*/
|
*/
|
||||||
const navigationEvents = () => {
|
const navigationEvents = async () => {
|
||||||
if (!WEBVIEW.navigationEnabled) {
|
if (!WEBVIEW.navigationEnabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -680,7 +680,7 @@ const navigationEvents = () => {
|
|||||||
/**
|
/**
|
||||||
* Register view events and handler.
|
* Register view events and handler.
|
||||||
*/
|
*/
|
||||||
const viewEvents = () => {
|
const viewEvents = async () => {
|
||||||
const ready = [];
|
const ready = [];
|
||||||
WEBVIEW.views.forEach((view, i) => {
|
WEBVIEW.views.forEach((view, i) => {
|
||||||
// Enable webview touch emulation
|
// Enable webview touch emulation
|
||||||
@@ -768,7 +768,7 @@ const viewEvents = () => {
|
|||||||
/**
|
/**
|
||||||
* Register app events and handler.
|
* Register app events and handler.
|
||||||
*/
|
*/
|
||||||
const appEvents = () => {
|
const appEvents = async () => {
|
||||||
// Handle signal and exit events
|
// Handle signal and exit events
|
||||||
process.on("SIGINT", app.quit);
|
process.on("SIGINT", app.quit);
|
||||||
app.on("before-quit", () => {
|
app.on("before-quit", () => {
|
||||||
@@ -784,10 +784,37 @@ const appEvents = () => {
|
|||||||
WEBVIEW.window.focus();
|
WEBVIEW.window.focus();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Check for latest release infos (2h)
|
||||||
|
setInterval(() => {
|
||||||
|
latestRelease();
|
||||||
|
}, 7200 * 1000);
|
||||||
|
await latestRelease();
|
||||||
|
|
||||||
// Webview initialized
|
// Webview initialized
|
||||||
WEBVIEW.initialized = true;
|
WEBVIEW.initialized = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches the latest app release infos from github.
|
||||||
|
*/
|
||||||
|
const latestRelease = async () => {
|
||||||
|
try {
|
||||||
|
const response = await axios.get(`${APP.releases.url}/latest`);
|
||||||
|
const data = response ? response.data : null;
|
||||||
|
if (!data || data.draft || data.prerelease) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
APP.releases.latest = {
|
||||||
|
title: APP.title,
|
||||||
|
version: (data.tag_name || data.name || "").replace(/^v/i, ""),
|
||||||
|
summary: data.body || "",
|
||||||
|
url: data.html_url || "",
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.warn("Github Error:", error.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks for network connectivity by requesting a known url.
|
* Checks for network connectivity by requesting a known url.
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user