Uploaded door sensor #15
13
dist/pvv.sql
vendored
@ -38,15 +38,12 @@ CREATE TABLE "motd" (
|
||||
INSERT INTO motd (title, content)
|
||||
VALUES ("MOTD ./dev.sh", "du kan endre motd i admin panelet");
|
||||
|
||||
CREATE TABLE "doors" (
|
||||
"name" TEXT PRIMARY KEY,
|
||||
"open" BOOLEAN,
|
||||
"description" TEXT
|
||||
CREATE TABLE "door" (
|
||||
"time" INTEGER PRIMARY KEY,
|
||||
"open" BOOLEAN
|
||||
);
|
||||
INSERT INTO doors(name, open, description) VALUES
|
||||
("koserommet", FALSE, "Døra inn til koserommet på stripa"),
|
||||
("terminalrommet", FALSE, "Døra inn til terminalrommet på stripa");
|
||||
|
||||
INSERT INTO door (time, open)
|
||||
VALUES (0, FALSE);
|
||||
|
||||
|
||||
INSERT INTO users (uname, groups)
|
||||
|
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");
|
||||
*/
|
||||
|
||||
CREATE TABLE doors (
|
||||
`name` VARCHAR(20) PRIMARY KEY,
|
||||
`open` BOOLEAN,
|
||||
`description` TEXT
|
||||
CREATE TABLE door (
|
||||
`time` INTEGER PRIMARY KEY,
|
||||
`open` BOOLEAN
|
||||
);
|
||||
INSERT INTO doors(name, open, description) VALUES
|
||||
("koserommet", FALSE, "Døra inn til koserommet på stripa"),
|
||||
("terminalrommet", FALSE, "Døra inn til terminalrommet på stripa");
|
||||
INSERT INTO door(time, open) VALUES (0, FALSE);
|
1
dist/sql_config_example.php
vendored
@ -3,3 +3,4 @@ $dbDsn = 'sqlite:'.__DIR__.DIRECTORY_SEPARATOR.'pvv.sqlite';
|
||||
$dbUser = null;
|
||||
$dbPass = null;
|
||||
|
||||
$doorSensorSecret = "OGJiZTdjZDctMmFkNy00ZjZjLTk3OGItOTA3NzU3ZDM2Yjlm";
|
74
src/pvv/side/door.php
Normal file
@ -0,0 +1,74 @@
|
||||
|
||||
<?php
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
namespace pvv\side;
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
use \PDO;
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
class Door{
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
private $pdo;
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
public function __construct(PDO $pdo){
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
$this->pdo = $pdo;
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
}
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
public function getAll() {
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
$query = 'SELECT time, open FROM door ORDER BY time DESC';
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
$statement = $this->pdo->prepare($query);
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
$statement->execute();
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
$doorEvents = [];
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
foreach($statement->fetchAll() as $row){
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
$doorEvents[] = [
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
'time' => (int)$row['time'],
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
'open' => (bool)$row['open']
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
];
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
}
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
return $doorEvents;
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
}
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
public function getEntriesAfter($startTime) {
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
$query = 'SELECT time, open FROM door WHERE time > :startTime ORDER BY time DESC';
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
$statement = $this->pdo->prepare($query);
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
$statement->bindParam(':startTime', $startTime, PDO::PARAM_STR);
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
$statement->execute();
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
$doorEvents = [];
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
foreach($statement->fetchAll() as $row){
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
$doorEvents[] = [
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
'time' => (int)$row['time'],
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
'open' => (bool)$row['open']
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
];
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
}
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
return $doorEvents;
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
}
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
public function getCurrent() {
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
![]() What happens here if the table is empty? What happens here if the table is empty?
![]() Tested and checked, door.php exhbits the preferred behaviour even with an empty table; getCurrent() returns time=0 and open=false, and getEntriesAfter returns entries=[]. Tested and checked, door.php exhbits the preferred behaviour even with an empty table; getCurrent() returns time=0 and open=false, and getEntriesAfter returns entries=[].
![]() So i assume $row is an empty map, and accessing it returns null, which gets cast into 0 and False? So i assume $row is an empty map, and accessing it returns null, which gets cast into 0 and False?
![]() Correct, I check all types coming in, and extensively cast everything to the correct type before JSON encoding. Only ints(here cast to 0) and bools(here cast to false) can be returned as far as I can see. Correct, I check all types coming in, and extensively cast everything to the correct type before JSON encoding. Only ints(here cast to 0) and bools(here cast to false) can be returned as far as I can see.
|
||||
$query = 'SELECT time, open FROM door ORDER BY time DESC LIMIT 1';
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
$statement = $this->pdo->prepare($query);
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
$statement->execute();
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
$row = $statement->fetch();
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
return [
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
'time' => (int)$row['time'],
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
'open' => (bool)$row['open']
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
];
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
}
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
private function removeOld() {
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
![]() nice, relational databases don't scale well with a lot of timeseries data how often is it run? nice, relational databases don't scale well with a lot of timeseries data
how often is it run?
![]() The Raspberry Pi(Probaly ESP8266 later) posts the door state once every 15 minutes and immediately if the state changes. The Raspberry Pi(Probaly ESP8266 later) posts the door state once every 15 minutes and immediately if the state changes.
4 times an hour * 24 * 7 = 672, so the database currently stores approximately 700 elements. Can be greatly reduced by only storing actual changes...
![]() ah, it's called in createEvent ah, it's called in createEvent
|
||||
$firstValidTime = time() - 60*60*24*7; //One week before now
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
$query = 'DELETE FROM door WHERE time < :firstValid';
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
$statement = $this->pdo->prepare($query);
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
$statement->bindParam(':firstValid', $firstValidTime, PDO::PARAM_STR);
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
$statement->execute();
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
}
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
public function createEvent($time, $open) {
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
$query = 'INSERT INTO door(time, open) VALUES (:time, :open)';
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
$statement = $this->pdo->prepare($query);
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
$statement->bindParam(':time', $time, PDO::PARAM_STR);
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
$statement->bindParam(':open', $open, PDO::PARAM_STR);
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
$statement->execute();
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
$this->removeOld();
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
}
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
||||
}
|
||||
![]() Why no cast to int and bool here? Why no cast to int and bool here?
|
@ -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;
|
||||
}
|
||||
|
||||
#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){
|
||||
nav #menu, nav #menu li.active, nav #menu_toggle, nav #login {
|
||||
position: absolute;
|
||||
@ -226,6 +236,9 @@ nav #usermenu li:first-child:hover {
|
||||
margin-left: 1em !important;
|
||||
margin-right: 1em !important;
|
||||
}
|
||||
.doorStateMobileOnly {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
@ -346,3 +359,4 @@ article p {
|
||||
textarea.boxinput {
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
|
@ -1,49 +1,73 @@
|
||||
<?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');
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
|
||||
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);
|
||||
$door = new \pvv\side\Door($pdo);
|
||||
|
||||
$out = $doors->getByName($_POST["name"]);
|
||||
if (!$out) {
|
||||
echo '{"error": true, "reason": "not found"}';
|
||||
http_response_code(404);
|
||||
exit();
|
||||
if($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
if (isset($_SERVER["HTTP_AUTHORIZATION"])) {
|
||||
list($type, $data) = explode(" ", $_SERVER["HTTP_AUTHORIZATION"], 2);
|
||||
if (strcasecmp($type, "Bearer") == 0) {
|
||||
if (hash_equals($data, $doorSensorSecret)) {
|
||||
handleSetState();
|
||||
} else {
|
||||
echo '{"status": "error", "message": "Invalid authentication key"}';
|
||||
die();
|
||||
}
|
||||
} else {
|
||||
![]() i assume this will work in lighttpd i assume this will work in lighttpd
|
||||
echo '{"status": "error", "message": "Invalid authentication method"}';
|
||||
die();
|
||||
![]() should include the space after "Bearer" should include the space after "Bearer"
|
||||
}
|
||||
![]() Where is Where is `doorSensorSecret` set?
![]() In sql_config.php, appended a dummy in sql_config_example.php In sql_config.php, appended a dummy in sql_config_example.php
|
||||
} else {
|
||||
echo '{"status": "error", "message": "Missing authentication"}';
|
||||
die();
|
||||
}
|
||||
else {
|
||||
echo '{"error": true, "reason": "missing either \"name\" or \"open\" argument"}';
|
||||
http_response_code(404);
|
||||
exit();
|
||||
} elseif ($_SERVER['REQUEST_METHOD'] === 'GET') {
|
||||
|
||||
if (isset($_GET["period"])) {
|
||||
$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);
|
||||
$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>
|
||||
<html lang="no">
|
||||
@ -63,6 +69,10 @@ $motd = $motdfetcher->getMOTD();
|
||||
<a class="btn" href="om/"><li>Om PVV</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>
|
||||
<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>
|
||||
</div>
|
||||
</header>
|
||||
|
Why no cast to int and bool here?
Why no cast to int and bool here?