Merge pull request #15 from Programvareverkstedet/doorsensor
Uploaded door sensor
This commit is contained in:
commit
8fd03c9824
13
dist/pvv.sql
vendored
13
dist/pvv.sql
vendored
@ -38,15 +38,12 @@ CREATE TABLE "motd" (
|
|||||||
INSERT INTO motd (title, content)
|
INSERT INTO motd (title, content)
|
||||||
VALUES ("MOTD ./dev.sh", "du kan endre motd i admin panelet");
|
VALUES ("MOTD ./dev.sh", "du kan endre motd i admin panelet");
|
||||||
|
|
||||||
CREATE TABLE "doors" (
|
CREATE TABLE "door" (
|
||||||
"name" TEXT PRIMARY KEY,
|
"time" INTEGER PRIMARY KEY,
|
||||||
"open" BOOLEAN,
|
"open" BOOLEAN
|
||||||
"description" TEXT
|
|
||||||
);
|
);
|
||||||
INSERT INTO doors(name, open, description) VALUES
|
INSERT INTO door (time, open)
|
||||||
("koserommet", FALSE, "Døra inn til koserommet på stripa"),
|
VALUES (0, FALSE);
|
||||||
("terminalrommet", FALSE, "Døra inn til terminalrommet på stripa");
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
INSERT INTO users (uname, groups)
|
INSERT INTO users (uname, groups)
|
||||||
|
11
dist/pvv_mysql.sql
vendored
11
dist/pvv_mysql.sql
vendored
@ -40,11 +40,8 @@ INSERT INTO motd (title, content)
|
|||||||
VALUES ("MOTD ./dev.sh", "du kan endre motd i admin panelet");
|
VALUES ("MOTD ./dev.sh", "du kan endre motd i admin panelet");
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CREATE TABLE doors (
|
CREATE TABLE door (
|
||||||
`name` VARCHAR(20) PRIMARY KEY,
|
`time` INTEGER PRIMARY KEY,
|
||||||
`open` BOOLEAN,
|
`open` BOOLEAN
|
||||||
`description` TEXT
|
|
||||||
);
|
);
|
||||||
INSERT INTO doors(name, open, description) VALUES
|
INSERT INTO door(time, open) VALUES (0, FALSE);
|
||||||
("koserommet", FALSE, "Døra inn til koserommet på stripa"),
|
|
||||||
("terminalrommet", FALSE, "Døra inn til terminalrommet på stripa");
|
|
1
dist/sql_config_example.php
vendored
1
dist/sql_config_example.php
vendored
@ -3,3 +3,4 @@ $dbDsn = 'sqlite:'.__DIR__.DIRECTORY_SEPARATOR.'pvv.sqlite';
|
|||||||
$dbUser = null;
|
$dbUser = null;
|
||||||
$dbPass = null;
|
$dbPass = null;
|
||||||
|
|
||||||
|
$doorSensorSecret = "OGJiZTdjZDctMmFkNy00ZjZjLTk3OGItOTA3NzU3ZDM2Yjlm";
|
74
src/pvv/side/door.php
Normal file
74
src/pvv/side/door.php
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
<?php
|
||||||
|
namespace pvv\side;
|
||||||
|
|
||||||
|
use \PDO;
|
||||||
|
|
||||||
|
class Door{
|
||||||
|
private $pdo;
|
||||||
|
|
||||||
|
public function __construct(PDO $pdo){
|
||||||
|
$this->pdo = $pdo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAll() {
|
||||||
|
$query = 'SELECT time, open FROM door ORDER BY time DESC';
|
||||||
|
$statement = $this->pdo->prepare($query);
|
||||||
|
$statement->execute();
|
||||||
|
|
||||||
|
$doorEvents = [];
|
||||||
|
foreach($statement->fetchAll() as $row){
|
||||||
|
$doorEvents[] = [
|
||||||
|
'time' => (int)$row['time'],
|
||||||
|
'open' => (bool)$row['open']
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $doorEvents;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getEntriesAfter($startTime) {
|
||||||
|
$query = 'SELECT time, open FROM door WHERE time > :startTime ORDER BY time DESC';
|
||||||
|
$statement = $this->pdo->prepare($query);
|
||||||
|
$statement->bindParam(':startTime', $startTime, PDO::PARAM_STR);
|
||||||
|
$statement->execute();
|
||||||
|
|
||||||
|
$doorEvents = [];
|
||||||
|
foreach($statement->fetchAll() as $row){
|
||||||
|
$doorEvents[] = [
|
||||||
|
'time' => (int)$row['time'],
|
||||||
|
'open' => (bool)$row['open']
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $doorEvents;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCurrent() {
|
||||||
|
$query = 'SELECT time, open FROM door ORDER BY time DESC LIMIT 1';
|
||||||
|
$statement = $this->pdo->prepare($query);
|
||||||
|
$statement->execute();
|
||||||
|
$row = $statement->fetch();
|
||||||
|
return [
|
||||||
|
'time' => (int)$row['time'],
|
||||||
|
'open' => (bool)$row['open']
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function removeOld() {
|
||||||
|
$firstValidTime = time() - 60*60*24*7; //One week before now
|
||||||
|
$query = 'DELETE FROM door WHERE time < :firstValid';
|
||||||
|
$statement = $this->pdo->prepare($query);
|
||||||
|
$statement->bindParam(':firstValid', $firstValidTime, PDO::PARAM_STR);
|
||||||
|
$statement->execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createEvent($time, $open) {
|
||||||
|
$query = 'INSERT INTO door(time, open) VALUES (:time, :open)';
|
||||||
|
$statement = $this->pdo->prepare($query);
|
||||||
|
$statement->bindParam(':time', $time, PDO::PARAM_STR);
|
||||||
|
$statement->bindParam(':open', $open, PDO::PARAM_STR);
|
||||||
|
$statement->execute();
|
||||||
|
|
||||||
|
$this->removeOld();
|
||||||
|
}
|
||||||
|
}
|
@ -1,79 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace pvv\side;
|
|
||||||
|
|
||||||
use \PDO;
|
|
||||||
|
|
||||||
class Doors{
|
|
||||||
private $pdo;
|
|
||||||
|
|
||||||
public function __construct(PDO $pdo){
|
|
||||||
$this->pdo = $pdo;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getAll() {
|
|
||||||
$query = 'SELECT name, open, description FROM doors ORDER BY open DESC, name ASC';
|
|
||||||
$statement = $this->pdo->prepare($query);
|
|
||||||
$statement->execute();
|
|
||||||
|
|
||||||
$doors = [];
|
|
||||||
foreach($statement->fetchAll() as $row){
|
|
||||||
$doors[] = [
|
|
||||||
'name' => $row['name'],
|
|
||||||
'open' => (int)$row['open'],
|
|
||||||
'description' => $row['description'],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $doors;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getByName($name){
|
|
||||||
$query = 'SELECT name, open, description FROM doors WHERE name=:name';
|
|
||||||
$statement = $this->pdo->prepare($query);
|
|
||||||
$statement->bindParam(':name', $name, PDO::PARAM_STR);
|
|
||||||
$statement->execute();
|
|
||||||
|
|
||||||
$row = $statement->fetch();
|
|
||||||
if (!$row) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return [
|
|
||||||
'name' => $row['name'],
|
|
||||||
'open' => (int)$row['open'],
|
|
||||||
'description' => $row['description'],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setDoorState($name, $open) {
|
|
||||||
$query = 'UPDATE doors SET open=:open WHERE name=:name';
|
|
||||||
$statement = $this->pdo->prepare($query);
|
|
||||||
$statement->bindParam(':name', $name, PDO::PARAM_STR);
|
|
||||||
$statement->bindParam(':open', $open, PDO::PARAM_INT);
|
|
||||||
$statement->execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public function createDoor($name, $description) {
|
|
||||||
$query = 'INSERT INTO doors(name, open, description) VALUES (:name, TRUE, :desc)';
|
|
||||||
$statement = $this->pdo->prepare($query);
|
|
||||||
$statement->bindParam(':name', $name, PDO::PARAM_STR);
|
|
||||||
$statement->bindParam(':desc', $description, PDO::PARAM_STR);
|
|
||||||
$statement->execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function updateDoorDescription($name, $description) {
|
|
||||||
$query = 'UPDATE doors SET descriptin=:desc WHERE name=:name';
|
|
||||||
$statement = $this->pdo->prepare($query);
|
|
||||||
$statement->bindParam(':name', $name, PDO::PARAM_STR);
|
|
||||||
$statement->bindParam(':desc', $description, PDO::PARAM_STR);
|
|
||||||
$statement->execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function deleteDoor($name) {
|
|
||||||
$query = 'DELETE FROM doors WHERE name = :name;';
|
|
||||||
$statement = $this->pdo->prepare($query);
|
|
||||||
$statement->bindParam(':name', $name, PDO::PARAM_STR);
|
|
||||||
$statement->execute();
|
|
||||||
}
|
|
||||||
}
|
|
@ -153,6 +153,16 @@ nav #usermenu li:first-child:hover {
|
|||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#doorIndicator {
|
||||||
|
border-radius: 5px;
|
||||||
|
padding: 8px 8px;
|
||||||
|
margin: 4px 4px;
|
||||||
|
}
|
||||||
|
#doorIndicator > p > abbr[title] { text-decoration: none; border-bottom: none; cursor: inherit; }
|
||||||
|
.doorIndicator_OPEN { border: 2px solid green; }
|
||||||
|
.doorIndicator_CLOSED { border: 2px dotted red; }
|
||||||
|
.doorStateMobileOnly { display: none; }
|
||||||
|
|
||||||
@media(max-width: 800px){
|
@media(max-width: 800px){
|
||||||
nav #menu, nav #menu li.active, nav #menu_toggle, nav #login {
|
nav #menu, nav #menu li.active, nav #menu_toggle, nav #login {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@ -226,6 +236,9 @@ nav #usermenu li:first-child:hover {
|
|||||||
margin-left: 1em !important;
|
margin-left: 1em !important;
|
||||||
margin-right: 1em !important;
|
margin-right: 1em !important;
|
||||||
}
|
}
|
||||||
|
.doorStateMobileOnly {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
@ -346,3 +359,4 @@ article p {
|
|||||||
textarea.boxinput {
|
textarea.boxinput {
|
||||||
resize: vertical;
|
resize: vertical;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,49 +1,73 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
require_once dirname(dirname(__DIR__)) . implode(DIRECTORY_SEPARATOR, ['', 'inc', 'include.php']);
|
require_once dirname(dirname(__DIR__)) . implode(DIRECTORY_SEPARATOR, ['', 'inc', 'include.php']);
|
||||||
$doors = new \pvv\side\Doors($pdo);
|
|
||||||
|
|
||||||
$out = null;
|
|
||||||
header('Content-Type: application/json');
|
header('Content-Type: application/json');
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
|
$door = new \pvv\side\Door($pdo);
|
||||||
if (isset($_GET["name"])) {
|
|
||||||
$out = $doors->getByName($_GET["name"]);
|
|
||||||
if (!$out) {
|
|
||||||
echo '{"error": true, "reason": "not found"}';
|
|
||||||
http_response_code(404);
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$out = $doors->getAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
elseif ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
||||||
if (isset($_POST["name"]) and isset($_POST["open"]) ) {
|
|
||||||
$out = $doors->setDoorState($_POST["name"], (strtolower($_POST["open"])==="true")?1:0);
|
|
||||||
|
|
||||||
$out = $doors->getByName($_POST["name"]);
|
if($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
if (!$out) {
|
if (isset($_SERVER["HTTP_AUTHORIZATION"])) {
|
||||||
echo '{"error": true, "reason": "not found"}';
|
list($type, $data) = explode(" ", $_SERVER["HTTP_AUTHORIZATION"], 2);
|
||||||
http_response_code(404);
|
if (strcasecmp($type, "Bearer") == 0) {
|
||||||
exit();
|
if (hash_equals($data, $doorSensorSecret)) {
|
||||||
|
handleSetState();
|
||||||
|
} else {
|
||||||
|
echo '{"status": "error", "message": "Invalid authentication key"}';
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
echo '{"status": "error", "message": "Invalid authentication method"}';
|
||||||
|
die();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
echo '{"status": "error", "message": "Missing authentication"}';
|
||||||
|
die();
|
||||||
}
|
}
|
||||||
else {
|
} elseif ($_SERVER['REQUEST_METHOD'] === 'GET') {
|
||||||
echo '{"error": true, "reason": "missing either \"name\" or \"open\" argument"}';
|
|
||||||
http_response_code(404);
|
if (isset($_GET["period"])) {
|
||||||
exit();
|
$period = (string)htmlspecialchars($_GET["period"]);
|
||||||
|
if ($period == "day") {
|
||||||
|
$startTime = time() - (60*60*24);
|
||||||
|
} else if ($period == "week") {
|
||||||
|
$startTime = time() - (60*60*24*7);
|
||||||
|
} else {
|
||||||
|
echo '{"status": "error", "message": "Invalid period"}';
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
|
||||||
|
$lines = $door->getEntriesAfter($startTime);
|
||||||
|
echo json_encode([
|
||||||
|
'status' => "OK",
|
||||||
|
'entries' => $lines
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
//Only last entry
|
||||||
|
$line = (object)$door->getCurrent();
|
||||||
|
echo json_encode([
|
||||||
|
'status' => "OK",
|
||||||
|
'time' => $line->time,
|
||||||
|
'open' => $line->open
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function utf8ize($d) {
|
|
||||||
if (is_array($d)) {
|
|
||||||
foreach ($d as $k => $v) {
|
|
||||||
$d[$k] = utf8ize($v);
|
|
||||||
}
|
|
||||||
} else if (is_string ($d)) {
|
|
||||||
return utf8_encode($d);
|
|
||||||
}
|
|
||||||
return $d;
|
|
||||||
}
|
|
||||||
|
|
||||||
echo json_encode(utf8ize($out));
|
function handleSetState() {
|
||||||
|
global $door;
|
||||||
|
|
||||||
|
$jsonobj = file_get_contents('php://input');
|
||||||
|
$event = json_decode($jsonobj);
|
||||||
|
|
||||||
|
if ((!isset($event->time)) || (!is_numeric($event->time))) {
|
||||||
|
echo '{"status": "error", "message": "Invalid timestamp"}';
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
if ((!isset($event->isDoorOpen)) || (!is_bool($event->isDoorOpen))) {
|
||||||
|
echo '{"status": "error", "message": "Invalid door state"}';
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
|
||||||
|
$door->createEvent((int)($event->time), (bool)($event->isDoorOpen));
|
||||||
|
echo '{"status": "OK"}';
|
||||||
|
}
|
@ -7,6 +7,12 @@ $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
|||||||
|
|
||||||
$motdfetcher = new \pvv\side\MOTD($pdo);
|
$motdfetcher = new \pvv\side\MOTD($pdo);
|
||||||
$motd = $motdfetcher->getMOTD();
|
$motd = $motdfetcher->getMOTD();
|
||||||
|
|
||||||
|
$door = new \pvv\side\Door($pdo);
|
||||||
|
$doorEntry = (object)($door->getCurrent());
|
||||||
|
$isDoorOpen = $doorEntry->open;
|
||||||
|
if (date("Y-m-d") == date("Y-m-d", $doorEntry->time)) { $doorTime = date("H:i", $doorEntry->time);
|
||||||
|
} else { $doorTime = date("H:i d/m", $doorEntry->time);}
|
||||||
?>
|
?>
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="no">
|
<html lang="no">
|
||||||
@ -63,6 +69,10 @@ $motd = $motdfetcher->getMOTD();
|
|||||||
<a class="btn" href="om/"><li>Om PVV</li></a>
|
<a class="btn" href="om/"><li>Om PVV</li></a>
|
||||||
<a class="btn focus" href="paamelding/"><li>Bli medlem!</li></a>
|
<a class="btn focus" href="paamelding/"><li>Bli medlem!</li></a>
|
||||||
<a class="btn" href="https://use.mazemap.com/#config=ntnu&v=1&zlevel=2¢er=10.406281,63.417093&zoom=19.5&campuses=ntnu&campusid=1&sharepoitype=poi&sharepoi=38159&utm_medium=longurl">Veibeskrivelse</li></a>
|
<a class="btn" href="https://use.mazemap.com/#config=ntnu&v=1&zlevel=2¢er=10.406281,63.417093&zoom=19.5&campuses=ntnu&campusid=1&sharepoitype=poi&sharepoi=38159&utm_medium=longurl">Veibeskrivelse</li></a>
|
||||||
|
<div id="doorIndicator" class="<?php echo($isDoorOpen ? "doorIndicator_OPEN" : "doorIndicator_CLOSED"); ?>">
|
||||||
|
<p class="doorStateText"><abbr title="Oppdatert <?php echo($doorTime) ?>">Døren er <b><?php echo($isDoorOpen ? "" : "ikke") ?> åpen</b>.</abbr></p>
|
||||||
|
<p class="doorStateTime doorStateMobileOnly">(Oppdatert <?php echo($doorTime) ?>)</p>
|
||||||
|
</div>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
Loading…
Reference in New Issue
Block a user