Add device menu

This commit is contained in:
Haitem 2020-08-31 21:23:23 +02:00
parent 0efbda0583
commit 6b0ab2d0ba
14 changed files with 4984 additions and 398 deletions

2044
adminer.php Normal file

File diff suppressed because one or more lines are too long

319
api.php Normal file
View File

@ -0,0 +1,319 @@
<?php
/** Includes **/
include_once('./config.php');
//Autoloader
$files = scandir('./app/class/');
$files = array_diff($files, array(
'.',
'..',
'app',
'ChartJS.php',
'ChartJS_Line.php',
'ChartManager.php',
'DashboardManager.php',
'Partial.php',
'Form.php',
'Route.php',
'Template.php',
'Ajax.php',
));
foreach($files as $file) {
include './app/class/'. $file;
}
//Allow acces only wia Curl, Ajax ETC
$restAcess = 'XMLHttpRequest' == ( $_SERVER['HTTP_X_REQUESTED_WITH'] ?? '' );
if (!$restAcess){
header('Location: ./');
}
//Log
$logManager = new LogManager();
$apiLogManager = new LogManager('./app/logs/api/'. date("Y-m-d").'.log');
//DB Conector
Db::connect (DBHOST, DBUSER, DBPASS, DBNAME);
//Read API data
$json = file_get_contents('php://input');
$obj = json_decode($json, true);
//Log RAW api request
if (API_DEBUGMOD == 1) {
$apiLogManager->write("[API] request body\n" . json_encode($obj, JSON_PRETTY_PRINT), LogRecordType::INFO);
}
//zabespecit proti Ddosu
if (isset($obj['user']) && $obj['user'] != ''){
//user at home
$user = UserManager::getUser($obj['user']);
$userAtHome = $user['at_home'];
if (!empty($user)) {
$userId = $user['user_id'];
$atHome = $obj['atHome'];
if($userAtHome != $atHome){
UserManager::atHome($userId, $atHome);
$logManager->write("[USER] user " . $userId . " changet his home state to " . $atHome , LogRecordType::INFO);
}
echo 'Saved: ' . $atHome;
header($_SERVER["SERVER_PROTOCOL"]." 200 OK");
die();
}
}
//Filtrování IP adress
if (DEBUGMOD != 1) {
if (!in_array($_SERVER['REMOTE_ADDR'], HOMEIP)) {
echo json_encode(array(
'state' => 'unsuccess',
'errorMSG' => "Using API from your IP insnt alowed!",
), JSON_PRETTY_PRINT);
header($_SERVER["SERVER_PROTOCOL"]." 401 Unauthorized");
$logManager->write("[API] acces denied from " . $_SERVER['REMOTE_ADDR'], LogRecordType::WARNING);
exit();
}
}
//automationExecution
try {
AutomationManager::executeAll();
$fallbackManager = new FallbackManager(RANGES);
$fallbackManager->check();
//LogKeeper::purge(LOGTIMOUT);
} catch (\Exception $e) {
$logManager->write("[Automation] Something happen during automation execution", LogRecordType::ERROR);
}
//Record Cleaning
try {
RecordManager::clean(RECORDTIMOUT);
} catch (\Exception $e) {
$logManager->write("[Record] cleaning record older that " . RECORDTIMOUT , LogRecordType::ERROR);
}
//Variables
$token = $obj['token'];
$values = null;
$settings = null;
$deviceLogs = null;
$command = "null";
if (isset($obj['values'])) {
$values = $obj['values'];
}
if (isset($obj['settings'])) {
$settings = $obj['settings'];
}
if (isset($obj['logs'])) {
$deviceLogs = $obj['logs'];
}
//Checks
if ($token == null || $token == "") {
echo json_encode(array(
'state' => 'unsuccess',
'errorMSG' => "Missing Value Token in JSON payload",
), JSON_PRETTY_PRINT);
header($_SERVER["SERVER_PROTOCOL"]." 401 Unauthorized");
die();
}
//Vstupní Checky
if (!DeviceManager::registeret($token)) {
//Notification data setup
$notificationMng = new NotificationManager;
$notificationData = [
'title' => 'Info',
'body' => 'New device Detected Found',
'icon' => BASEDIR . '/app/templates/images/icon-192x192.png',
];
//Subdevice Registration
$deviceId = DeviceManager::create($token, $token);
foreach ($values as $key => $value) {
if (!SubDeviceManager::getSubDeviceByMaster($deviceId, $key)) {
SubDeviceManager::create($deviceId, $key, UNITS[$key]);
}
}
//Notification for newly added Device
if ($notificationData != []) {
$subscribers = $notificationMng::getSubscription();
foreach ($subscribers as $key => $subscriber) {
$logManager->write("[NOTIFICATION] SENDING TO" . $subscriber['id'] . " ", LogRecordType::INFO);
$notificationMng::sendSimpleNotification(SERVERKEY, $subscriber['token'], $notificationData);
}
}
header($_SERVER["SERVER_PROTOCOL"]." 401 Unauthorized");
echo json_encode(array(
'state' => 'unsuccess',
'errorMSG' => "Device not registeret",
), JSON_PRETTY_PRINT);
$logManager->write("[API] Registering Device", LogRecordType::INFO);
exit();
}
if (!DeviceManager::approved($token)) {
header($_SERVER["SERVER_PROTOCOL"]." 401 Unauthorized");
echo json_encode(array(
'state' => 'unsuccess',
'errorMSG' => "Unaproved Device",
), JSON_PRETTY_PRINT);
exit();
}
// Diagnostic Data Write to DB
if ($settings != null && $settings != ""){
$data = ['mac' => $settings["network"]["mac"], 'ip_address' => $settings["network"]["ip"]];
if (array_key_exists("firmware_hash", $settings)) {
$data['firmware_hash'] = $settings["firmware_hash"];
}
DeviceManager::editByToken($token, $data);
$jsonAnswer = [
'state' => 'succes',
'command' => $command,
];
echo json_encode($jsonAnswer, JSON_PRETTY_PRINT);
header($_SERVER["SERVER_PROTOCOL"]." 200 OK");
die();
}
// Issuing command
if ($command == "null"){
$device = DeviceManager::getDeviceByToken($token);
$deviceId = $device['device_id'];
$deviceCommand = $device["command"];
if ($deviceCommand != '' && $deviceCommand != null && $deviceCommand != "null")
{
$command = $deviceCommand;
$data = [
'command'=>'null'
];
DeviceManager::editByToken($token, $data);
$logManager->write("[API] Device_ID " . $deviceId . " executing command " . $command, LogRecordType::INFO);
}
}
// Diagnostic Logs Write To log File
if ($deviceLogs != null && $deviceLogs != ""){
foreach ($deviceLogs as $log) {
$logManager->write("[Device Log Msg] Device_ID " . $deviceId . "->" . $log, LogRecordType::ERROR);
}
$jsonAnswer = [
'state' => 'succes',
'command' => $command,
];
echo json_encode($jsonAnswer, JSON_PRETTY_PRINT);
header($_SERVER["SERVER_PROTOCOL"]." 200 OK");
die();
}
// Subdevices first data!
if ($values != null && $values != "") {
//ZAPIS
$device = DeviceManager::getDeviceByToken($token);
$deviceId = $device['device_id'];
foreach ($values as $key => $value) {
if (!SubDeviceManager::getSubDeviceByMaster($deviceId, $key)) {
SubDeviceManager::create($deviceId, $key, UNITS[$key]);
}
RecordManager::create($deviceId, $key, round($value['value'],3));
$logManager->write("[API] Device_ID " . $deviceId . " writed value " . $key . ' ' . $value['value'], LogRecordType::INFO);
//notification
if ($key == 'door' || $key == 'water') {
$notificationMng = new NotificationManager;
$notificationData = [];
switch ($key) {
case 'door':
$notificationData = [
'title' => 'Info',
'body' => 'Someone just open up '.$device['name'],
'icon' => BASEDIR . '/app/templates/images/icon-192x192.png',
];
break;
case 'water':
$notificationData = [
'title' => 'Alert',
'body' => 'Wather leak detected by '.$device['name'],
'icon' => BASEDIR . '/app/templates/images/icon-192x192.png',
];
break;
}
if (DEBUGMOD) $notificationData['body'] .= ' value='.$value['value'];
if ($notificationData != []) {
$subscribers = $notificationMng::getSubscription();
foreach ($subscribers as $key => $subscriber) {
$logManager->write("[NOTIFICATION] SENDING TO" . $subscriber['id'] . " ", LogRecordType::INFO);
$notificationMng::sendSimpleNotification(SERVERKEY, $subscriber['token'], $notificationData);
}
}
}
}
$hostname = strtolower($device['name']);
$hostname = str_replace(' ', '_', $hostname);
//upravit format na setings-> netvork etc
$jsonAnswer = [
'device' => [
'hostname' => $hostname,
'ipAddress' => $device['ip_address'],
'subnet' => $device['subnet'],
'gateway' => $device['gateway'],
],
'state' => 'succes',
'command' => $command,
];
$subDevicesTypeList = SubDeviceManager::getSubDeviceSTypeForMater($deviceId);
if (!in_array($subDevicesTypeList, ['on/off', 'door', 'water'])) {
$jsonAnswer['device']['sleepTime'] = $device['sleep_time'];
}
echo json_encode($jsonAnswer, JSON_PRETTY_PRINT);
header($_SERVER["SERVER_PROTOCOL"]." 200 OK");
} else {
//Vypis
$device = DeviceManager::getDeviceByToken($token);
$deviceId = $device['device_id'];
if (count(SubDeviceManager::getAllSubDevices($deviceId)) == 0) {
SubDeviceManager::create($deviceId, 'on/off', UNITS[$key]);
//RecordManager::create($deviceId, 'on/off', 0);
}
$subDeviceId = SubDeviceManager::getAllSubDevices($deviceId)[0]['subdevice_id'];
$subDeviceLastReord = RecordManager::getLastRecord($subDeviceId);
$subDeviceLastReordValue = $subDeviceLastReord['value'];
if ($subDeviceLastReord['execuded'] == 0){
$logManager->write("[API] subDevice_ID ".$subDeviceId . " executed comand with value " .$subDeviceLastReordValue . " record id " . $subDeviceLastReord['record_id'] . " executed " . $subDeviceLastReord['execuded'], LogRecordType::INFO);
RecordManager::setExecuted($subDeviceLastReord['record_id']);
}
echo json_encode(array(
'device' => [
'hostname' => $device['name'],
'ipAddress' => $device['ip_address'],
'subnet' => $device['subnet'],
'gateway' => $device['gateway'],
],
'state' => 'succes',
'value' => $subDeviceLastReordValue,
'command' => $command,
), JSON_PRETTY_PRINT);
header($_SERVER["SERVER_PROTOCOL"]." 200 OK");
}
unset($logManager);
Db::disconect();
die();

View File

@ -18,6 +18,7 @@ $router->any('/login', 'Login');
$router->any('/logout', 'Logout');
$router->any('/automation', 'Automation');
$router->any('/setting', 'Setting');
$router->any('/device', 'Device');
$router->any('/ajax', 'Ajax');
$router->any('/oauth', 'Oauth');
@ -35,7 +36,7 @@ $router->get('/api/widgets/{widgetId}/detail', 'WidgetApi@detail');
//cron
$router->post('/cron/clean', 'CronApi@clean');
#$router->post('/cron/fetch', 'CronApi@fetch');
$router->post('/cron/fetch', 'CronApi@fetch');
//Google Home - API
$router->any('/api/HA/auth', 'Oauth');

View File

@ -9,12 +9,22 @@ class UpdatesApi {
readfile($path);
}
private function validateHeader($headers){
if (
isset($_SERVER['HTTP_X_ESP8266_STA_MAC']) &&
isset($_SERVER['HTTP_X_ESP8266_SKETCH_MD5'])
) {
return true;
}
return false;
}
public function default(){
header('Content-type: text/plain; charset=utf8', true);
$logManager = new LogManager('../logs/ota/'. date("Y-m-d").'.log');
$logManager->setLevel(LOGLEVEL);
$logManager->write("[Updater] Client Connected", LogRecordTypes::INFO);
header('Content-type: text/plain; charset=utf8', true);
//Filtrování IP adress
if (DEBUGMOD != 1) {

View File

@ -0,0 +1,21 @@
<?php
if (!empty ($_POST)){
if (!empty ($_FILES['deviceFirmware']) && !empty ($_FILES['deviceFirmware']['tmp_name']) && !empty ($_POST['deviceId'])) {
$deviceManager = new DeviceManager ();
$file = $_FILES['deviceFirmware'];
$deviceMac = $deviceManager->getDeviceById ($_POST['deviceId'])['mac'];
$fileName = (!empty ($deviceMac) ? str_replace (":", "", $deviceMac) . ".bin" : "");
if ($fileName != "" && file_exists ("../app/updater/" . $fileName)) {
unlink("../app/updater/" . $fileName);
}
if ($fileName != "") {
copy ($file['tmp_name'], "../app/updater/" . $fileName);
} else {
}
}
if (isset ($_POST['deviceCommand']) && !empty ($_POST['deviceId'])) {
$deviceManager = new DeviceManager ();
$deviceManager->edit ($_POST['deviceId'], array ('command' => $_POST['deviceCommand']));
}
}

42
app/views/Device.php Normal file
View File

@ -0,0 +1,42 @@
<?php
class Device extends Template
{
function __construct () {
$userManager = new UserManager ();
$deviceManager = new DeviceManager ();
$langMng = new LanguageManager ('en');
if (!$userManager->isLogin ()) {
header ('Location: ' . BASEURL . 'device');
}
$template = new Template ('device');
$template->prepare ('title', $langMng->get ("m_devices"));
$devices = $deviceManager->getAllDevices ();
foreach ($devices as $key => $device) {
$localBinary = "../updater/" . str_replace (':', '', $device['mac']) . ".bin";
if (file_exists ($localBinary)) {
$hash = md5_file ($localBinary);
if ($hash == $device['firmware_hash']) {
$devices[$key]['firmware_hash'] = "true";
} else {
$devices[$key]['firmware_hash'] = "need";
}
} else {
$devices[$key]['firmware_hash'] = "false";
}
}
$template->prepare ('baseDir', BASEDIR);
$template->prepare ('debugMod', DEBUGMOD);
$template->prepare ('logToLiveTime', LOGTIMOUT);
$template->prepare ('devices', $devices);
$template->prepare ('langMng', $langMng);
$template->render ();
}
}

View File

@ -0,0 +1,79 @@
<!DOCTYPE html>
<html lang="en">
<head>
<?php
$partial = new Partial('head');
$partial->prepare('baseDir', $BASEDIR);
$partial->render();
?>
<title><?php echo $TITLE ?></title>
</head>
<body class="no-transitions">
<div class="row no-gutters main">
<div class="col-md-3 d-sm-none"></div>
<div class="col-md-3 nav-container">
<?php
$partial = new Partial('menu');
$partial->prepare('item', 'device');
$partial->prepare('langMng',$LANGMNG);
$partial->prepare('debugMod',$DEBUGMOD);
$partial->render();
?>
</div>
<div class="col-md-9 main-body">
<table>
<thead>
<tr>
<th>Icon</th>
<th>Name</th>
<th>Firmware</th>
<th>Mac</th>
<th>IP Address</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<?php if (!empty ($DEVICES)): ?>
<?php foreach ($DEVICES as $device): ?>
<tr>
<td><i class="fa">&#x<?php echo (!empty ($device['icon']) ? $device['icon'] : ""); ?></i></td>
<td><?php echo (!empty ($device['name']) ? $device['name'] : ""); ?></td>
<td>
<?php if (!empty ($device['mac'])): ?>
<i
class="fa <?php echo (!empty ($device['firmware_hash']) ? ($device['firmware_hash'] != "need" ? "fa-check-circle" : "fa-circle") : "fa-times-circle"); ?>"
style="float: center; <?php echo (!empty ($device['firmware_hash']) ? ($device['firmware_hash'] != "need" ? "color: green;" : "color: yellow;") : "color: red;"); ?>"
></i>
<button class="fa custom-file-input" type="button" onclick="document.getElementById('deviceFirmware').click();" >&#xf0ee;</button>
<form style="display: none;" method="post" action="" enctype="multipart/form-data">
<input type="hidden" name="deviceId" value="<?php echo (!empty ($device['device_id']) ? $device['device_id'] : ""); ?>">
<input type="file" onchange="this.form.submit();" name="deviceFirmware" id="deviceFirmware" value="">
</form>
<?php endif; ?>
<div type="float: clear;"></div>
</td>
<td><?php echo (!empty ($device['mac']) ? $device['mac'] : ""); ?></td>
<td><?php echo (!empty ($device['ip_address']) ? $device['ip_address'] : ""); ?></td>
<td>
<form method="post" action="">
<input type="hidden" name="deviceId" value="<?php echo (!empty ($device['device_id']) ? $device['device_id'] : ""); ?>">
<button class="fa custom-file-input" type="submit" name="deviceCommand" value="reset" title="Reset">&#xf01e;</button>
<button class="fa custom-file-input" type="submit" name="deviceCommand" value="config" title="Config">&#xf013;</button>
<div style="float: clear;"></div>
</form>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
<tbody>
</table>
</div>
<?php
$partial = new Partial('footer');
$partial->prepare('baseDir', BASEDIR);
$partial->render();
//TODO js do main.js
?>
</body>
</html>

View File

@ -1,6 +1,11 @@
<div class="nav">
<?php
$menuItems = [
'fa-podcast' => [
'slug' => 'device',
'lngKey' => 'devices',
'path' => 'device',
],
'fa-wrench' => [
'slug' => 'setting',
'lngKey' => 'settings',

View File

@ -7,6 +7,7 @@ return $lang = [
'm_automatization' => 'Automatizace',
'm_scenes' => 'Scény',
'm_log' => 'Log',
'm_devices' => 'Zařízení',
//Buttons
'b_year' => 'Rok',

View File

@ -7,6 +7,7 @@ return $lang = [
'm_automatization' => 'Automatization',
'm_scenes' => 'Scenes',
'm_log' => 'Log',
'm_devices' => 'Devices',
//Buttons
'b_year' => 'Year',

View File

@ -7,6 +7,7 @@ return $lang = [
'm_automatization' => 'Automatisatie',
'm_scenes' => 'Scénes',
'm_log' => 'Log',
'm_devices' => 'Apparaat',
//Buttons
'b_year' => 'Jaar',

View File

@ -7,6 +7,7 @@ return $lang = [
'm_automatization' => 'Zaplanowane działania',
'm_scenes' => 'Scenariusze',
'm_log' => 'Logi',
'm_devices' => 'Urządzenie',
//Buttons
'b_year' => 'Rok',

2044
public/adminer.php Normal file

File diff suppressed because one or more lines are too long

View File

@ -2963,4 +2963,21 @@ html {
font-size: 4vw;
}
}
.custom-file-input {
float: center;
font-size: 20px;
font-weight: 400;
cursor: pointer;
border: 0;
background-color: inherit;
color: white;
}
.custom-file-input:hover {
color: #6495ED;
}
.custom-file-input:active {
color: gray;
}
/*# sourceMappingURL=main.css.map */