Merge branch '1.0-local' into 1.0
This commit is contained in:
commit
5b07a2926e
|
@ -1,3 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
/usr/bin/env php $(realpath $(dirname $0))/source/state.php $*;
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
/usr/bin/env php $(realpath $(dirname $0))/source/set.php $*;
|
|
@ -5,7 +5,7 @@
|
||||||
require_once __DIR__.'/../../include/php/const';
|
require_once __DIR__.'/../../include/php/const';
|
||||||
|
|
||||||
|
|
||||||
function chip_state($p_id_chip, $p_state){
|
function globalstate_set($p_id_chip, $p_state){
|
||||||
|
|
||||||
$g_pins = null;
|
$g_pins = null;
|
||||||
$g_state = null;
|
$g_state = null;
|
||||||
|
@ -50,8 +50,10 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (3) If chip not found -> abort */
|
/* (3) If chip not found -> abort */
|
||||||
if( is_null($g_pins) || is_null($g_state) )
|
if( is_null($g_pins) || is_null($g_state) ){
|
||||||
|
slog("Chip $p_id_chip not found", 'global-state:set');
|
||||||
return 127;
|
return 127;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -61,8 +63,10 @@
|
||||||
foreach($g_pins as $pinNumber)
|
foreach($g_pins as $pinNumber)
|
||||||
|
|
||||||
// if failed -> propagate error
|
// if failed -> propagate error
|
||||||
if( syscall(SOURCE_DIR."/lib/gpio/out {$pinNumber}") == false )
|
if( syscall(SOURCE_DIR."/lib/gpio/out {$pinNumber}") == false ){
|
||||||
|
slog("Chip $p_id_chip cannot be set to OUT mode", 'global-state:set');
|
||||||
return 127;
|
return 127;
|
||||||
|
}
|
||||||
|
|
||||||
/* (2) For each pin, set the associated value */
|
/* (2) For each pin, set the associated value */
|
||||||
foreach($g_state as $pinIndex=>$pinValue){
|
foreach($g_state as $pinIndex=>$pinValue){
|
||||||
|
@ -90,7 +94,7 @@
|
||||||
|
|
||||||
/* [2] Launch main script
|
/* [2] Launch main script
|
||||||
=========================================================*/
|
=========================================================*/
|
||||||
$exec = chip_state($argv[1], $argv[2]);
|
$exec = globalstate_set($argv[1], $argv[2]);
|
||||||
|
|
||||||
echo $exec;
|
echo $exec;
|
||||||
die($exec);
|
die($exec);
|
|
@ -0,0 +1,76 @@
|
||||||
|
#!/usr/bin/php
|
||||||
|
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once __DIR__.'/../../include/php/const';
|
||||||
|
|
||||||
|
|
||||||
|
function globalstate_update(){
|
||||||
|
|
||||||
|
|
||||||
|
/* [1] Fetch global state
|
||||||
|
=========================================================*/
|
||||||
|
/* (1) Fetch from file */
|
||||||
|
$f_gstate = @file_get_contents(STATE_CONF);
|
||||||
|
|
||||||
|
/* (2) Manage errors */
|
||||||
|
if( $f_gstate === false )
|
||||||
|
return 127;
|
||||||
|
|
||||||
|
/* (3) Remove surrounding spaces */
|
||||||
|
$f_gstate = preg_replace('@^\s+@', '', $f_gstate);
|
||||||
|
$f_gstate = preg_replace('@\s+$@', '', $f_gstate);
|
||||||
|
|
||||||
|
/* (4) Extract in array */
|
||||||
|
$gstate = explode('', $f_gstate);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* [2] Cache chips
|
||||||
|
=========================================================*/
|
||||||
|
/* (1) Get file handler */
|
||||||
|
$f_chips = new SplFileObject(CHIPS_CONF, 'r');
|
||||||
|
|
||||||
|
/* (2) Parse line by line */
|
||||||
|
while( !$f_chips->eof() ){
|
||||||
|
|
||||||
|
// {1} Try to parse current line //
|
||||||
|
$parsed = json_decode($f_chips->fgets(), true);
|
||||||
|
|
||||||
|
// {2} If cannot parse, go to next //
|
||||||
|
if( is_null($parsed) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// {3} Check if position available in GSTATE //
|
||||||
|
if( isset($gstate[$parsed[0]]) ){
|
||||||
|
|
||||||
|
/* (1) If according state does not exist -> go to next chip */
|
||||||
|
if( !isset($parsed[2][$gstate[$parsed[0]]) )
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* (2) Use more human-readable data */
|
||||||
|
$position = $parsed[0];
|
||||||
|
$state = $gstate[$parsed[0]];
|
||||||
|
|
||||||
|
/* (3) Set state */
|
||||||
|
$updated = syscall(SOURCE_DIR."/lib/global-state/set {$position} {$state}");
|
||||||
|
|
||||||
|
/* (4) If error */
|
||||||
|
if( $updated === false )
|
||||||
|
slog("Cannot set ${position} chip to state {$state}", 'global-state:update');
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* [3] Launch main script
|
||||||
|
=========================================================*/
|
||||||
|
$exec = globalstate_update();
|
||||||
|
|
||||||
|
echo $exec;
|
||||||
|
die($exec);
|
||||||
|
?>
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
/usr/bin/env php $(realpath $(dirname $0))/source/update.php;
|
Binary file not shown.
|
@ -4,28 +4,302 @@
|
||||||
|
|
||||||
require_once __DIR__.'/../../include/php/const';
|
require_once __DIR__.'/../../include/php/const';
|
||||||
|
|
||||||
$f_authlist;
|
$f_auth;
|
||||||
$f_accesslog;
|
$f_accesslog;
|
||||||
|
$f_states;
|
||||||
|
$f_actions;
|
||||||
|
|
||||||
|
$state = [];
|
||||||
|
|
||||||
|
$actions = [];
|
||||||
|
$states = [];
|
||||||
|
|
||||||
|
$last_user = null;
|
||||||
|
$timeout = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* RETURNS THE PERMISSIONS FOR A SPECIFIC CODE AND AN ACTION
|
||||||
|
*
|
||||||
|
* @code<string> Some RFID code
|
||||||
|
*
|
||||||
|
* @return user<array> User info if found ; else NULL
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
function auth($code){
|
||||||
|
|
||||||
|
global $f_auth;
|
||||||
|
|
||||||
|
|
||||||
|
/* (1) Goto first line */
|
||||||
|
$f_auth->seek(0);
|
||||||
|
|
||||||
|
/* (2) Parse each line */
|
||||||
|
while( $f_auth->eof() ){
|
||||||
|
|
||||||
|
/* (3) Try to parse line */
|
||||||
|
$parsed = json_decode($f_auth->fgets(), true);
|
||||||
|
|
||||||
|
/* (3) Ignore if parse error */
|
||||||
|
if( is_null($parsed) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* (4) If wrong code -> go to next */
|
||||||
|
if( $parsed[0] != $code )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* (5) return user info */
|
||||||
|
return [
|
||||||
|
'id' => $parsed[1],
|
||||||
|
'can' => $parsed[2]
|
||||||
|
];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (6) Return FALSE if not found */
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* PROCESS ACTIONS IF ACTION CAN BE PERFORMED BY USER (DEPENDING ON TIMEOUT/STATE)
|
||||||
|
*
|
||||||
|
* @user<array> Current user information
|
||||||
|
*
|
||||||
|
* @return success<bool> If success (action performed) | FALSE
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
function act($user){
|
||||||
|
|
||||||
|
/* [1] Export global caches + variables
|
||||||
|
=========================================================*/
|
||||||
|
/* (1) Variables */
|
||||||
|
global $timeout;
|
||||||
|
|
||||||
|
/* (2) Caches */
|
||||||
|
global $actions, $states, $state;
|
||||||
|
|
||||||
|
/* (3) Log history file descriptor */
|
||||||
|
global $f_accesslog;
|
||||||
|
|
||||||
|
|
||||||
|
/* [2] Manage timeout
|
||||||
|
=========================================================*/
|
||||||
|
/* (1) If no action for this @timeout -> reset to 0 */
|
||||||
|
if( !isset($actions[$timeout]) || !is_array($actions[$timeout]) )
|
||||||
|
$timeout = 0;
|
||||||
|
|
||||||
|
/* (2) fetch actions for the current @timeout */
|
||||||
|
$actionlist = $actions[$timeout];
|
||||||
|
|
||||||
|
|
||||||
|
/* [3] Manage permissions (action that can be performed)
|
||||||
|
=========================================================*/
|
||||||
|
/* (1) Will contain available @id_action-s granted for the user */
|
||||||
|
$grantedFor = [];
|
||||||
|
|
||||||
|
/* (2) Search an action the user can perform in the list */
|
||||||
|
foreach($actionlist as $id_action=>$acttion){
|
||||||
|
|
||||||
|
/* (3) If have permission -> add to list */
|
||||||
|
if( in_array($id_action, $user['can']) )
|
||||||
|
$grantedFor[] = $id_action;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (4) If no action found -> abort */
|
||||||
|
if( count($grantedFor) == 0 )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
|
||||||
|
/* [4] Manage action depending on the actual STATE
|
||||||
|
=========================================================*/
|
||||||
|
/* (1) Will contain the first available action depending on STATE */
|
||||||
|
$toPerform = null;
|
||||||
|
|
||||||
|
/* (2) For each granted action, check the STATE */
|
||||||
|
foreach($grantedFor as $id_action){
|
||||||
|
|
||||||
|
$failed = false;
|
||||||
|
|
||||||
|
/* (3) Fetch action data */
|
||||||
|
$action = $actionlist[$id_action];
|
||||||
|
|
||||||
|
/* (4) Check if the state allows the action to be performed */
|
||||||
|
for( $c = 0 ; $c < count($state) || $c < strlen($action['prev']) ; $c++ ){
|
||||||
|
// {1} 'X' = any state -> so ignore //
|
||||||
|
if( $action['prev'][$c] == 'X' )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// {2} Other state : if not equal -> set as FAILED //
|
||||||
|
else if( $action['prev'][$c] != $state[$c] ){
|
||||||
|
$failed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (5) If not failed -> save action in @toPerform */
|
||||||
|
if( !$failed ){
|
||||||
|
$toPerform = $id_action;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (6) If no action cant be performed -> abort */
|
||||||
|
if( is_null($toPerform) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* (7) Extract corresponding action */
|
||||||
|
$action = $grantedFor[$toPerform];
|
||||||
|
|
||||||
|
|
||||||
|
/* [5] Process the action on the STATE
|
||||||
|
=========================================================*/
|
||||||
|
/* (1) Update the state with the found action */
|
||||||
|
for( $c = 0 ; $c < count($state) || $c < strlen($action['next']) ; $c++ ){
|
||||||
|
|
||||||
|
// {1} If 'x' -> let the current state //
|
||||||
|
if( $action['next'][$c] == 'X' )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// {2} If other state -> update it //
|
||||||
|
else
|
||||||
|
$state[$c] = $action['next'][$c];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* (2) Update the state file */
|
||||||
|
$written = @file_put_contents(STATE_CONF, implode('', $state));
|
||||||
|
|
||||||
|
/* (3) Manage error */
|
||||||
|
if( $written === false )
|
||||||
|
slog('cannot update STATE file', 'mfrc522:loop');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* [6] Log action
|
||||||
|
=========================================================*/
|
||||||
|
/* (1) Log action to default log file */
|
||||||
|
$f_accesslog->fwrite( json_encode([
|
||||||
|
time(),
|
||||||
|
$user['id'],
|
||||||
|
$toPerform
|
||||||
|
]).PHP_EOL );
|
||||||
|
|
||||||
|
/* (2) Return status */
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$last_card;
|
|
||||||
$times;
|
|
||||||
|
|
||||||
|
|
||||||
function mfrc522_setup(){
|
function mfrc522_setup(){
|
||||||
|
|
||||||
|
/* [0] Initialize global variables
|
||||||
|
=========================================================*/
|
||||||
|
/* (1) File descriptiors */
|
||||||
|
global $f_auth, $f_accesslog;
|
||||||
|
|
||||||
|
/* (2) Caches */
|
||||||
|
global $actions, $states, $state;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* [1] Open file descriptors on useful files
|
/* [1] Open file descriptors on useful files
|
||||||
=========================================================*/
|
=========================================================*/
|
||||||
$f_authlist = new SplFileObject(AUTH_LIST, 'r');
|
/* (1) Read accesses */
|
||||||
|
$f_auth = new SplFileObject(AUTH_LIST, 'r');
|
||||||
|
$f_states = new SplFileObject(STATES_CONF, 'r');
|
||||||
|
$f_actions = new SplFileObject(ACTIONS_CONF, 'r');
|
||||||
|
$f_gstate = @file_get_contents(STATE_CONF);
|
||||||
|
|
||||||
|
/* (2) Append accesses (logs) */
|
||||||
$f_accesslog = new SplFileObject(ACCESS_LOG, 'a');
|
$f_accesslog = new SplFileObject(ACCESS_LOG, 'a');
|
||||||
|
|
||||||
/* [2] Parse @authlist to cache [action]=>[rfid1, rfid2, ..]
|
|
||||||
=========================================================*/
|
|
||||||
|
|
||||||
|
|
||||||
/* [3] Initialize global variables
|
/* [2] Parse ACTIONS and cache them
|
||||||
=========================================================*/
|
=========================================================*/
|
||||||
$last_card = null;
|
/* (1) Parse each line */
|
||||||
$times = 0;
|
while( $f_actions->eof() ){
|
||||||
|
|
||||||
|
/* (2) Try to parse line */
|
||||||
|
$parsed = json_decode($f_actions->fgets(), true);
|
||||||
|
|
||||||
|
/* (2) Ignore if parse error */
|
||||||
|
if( is_null($parsed) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* (3) Add key (timeout) to cache */
|
||||||
|
if( !isset($actions[$parsed[0]] )
|
||||||
|
$actions[$parsed[0]] = [];
|
||||||
|
|
||||||
|
/* (4) Add entry to cache */
|
||||||
|
$actions[$parsed[0]][$parsed[1]] = [
|
||||||
|
'prev' => $parsed[2],
|
||||||
|
'next' => $parsed[3]
|
||||||
|
];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (5) Free file descriptor */
|
||||||
|
$f_actions = null;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* [3] Parse STATES and cache them
|
||||||
|
=========================================================*/
|
||||||
|
/* (1) Parse each line */
|
||||||
|
while( $f_states->eof() ){
|
||||||
|
|
||||||
|
/* (2) Try to parse line */
|
||||||
|
$parsed = json_decode($f_states->fgets(), true);
|
||||||
|
|
||||||
|
/* (2) Ignore if parse error */
|
||||||
|
if( is_null($parsed) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* (3) Add entry to cache */
|
||||||
|
$states[] = $parsed;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (4) Free file descriptor */
|
||||||
|
$f_states = null;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* [4] Cache global state
|
||||||
|
=========================================================*/
|
||||||
|
/* (1) Check file */
|
||||||
|
if( $f_gstate === false )
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* (2) Remove surrounding spaces */
|
||||||
|
$f_gstate = preg_replace('@^\s+@', '', $f_gstate);
|
||||||
|
$f_gstate = preg_replace('@\s+$@', '', $f_gstate);
|
||||||
|
|
||||||
|
/* (3) For each character create an entry */
|
||||||
|
for( $c = 0 ; $c < strlen($f_gstate) ; $c++ )
|
||||||
|
$state[] = $c;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,38 +309,113 @@
|
||||||
|
|
||||||
function mfrc522_loop(){
|
function mfrc522_loop(){
|
||||||
|
|
||||||
|
/* [1] Load global variables
|
||||||
|
=========================================================*/
|
||||||
|
/* (1) Persistent variabes */
|
||||||
|
global $last_user;
|
||||||
|
global $timeout;
|
||||||
|
|
||||||
|
/* (2) Caches */
|
||||||
|
global $actions, $states, $state;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* [1] Wait for rfid card
|
/* [1] Wait for rfid card
|
||||||
=========================================================*/
|
=========================================================*/
|
||||||
while( ($code=syscall(SOURCE_DIR.'/lib/mfrc522/read')) === false );
|
/* (1) Read card */
|
||||||
|
$code = syscall(SOURCE_DIR.'/lib/mfrc522/read'));
|
||||||
|
|
||||||
|
/* (2) If no card read -> reset @last_user / @timeout + abort */
|
||||||
|
if( $code === false ){
|
||||||
|
|
||||||
|
$last_user = null;
|
||||||
|
$timeout = 0;
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* (3) If code -> format it */
|
||||||
$code = strtoupper($code);
|
$code = strtoupper($code);
|
||||||
|
|
||||||
slog("card '$code' read", 'mfrc522:read');
|
slog("card '$code' read", 'mfrc522:read');
|
||||||
|
|
||||||
$start_ts = microtime(true);
|
|
||||||
|
|
||||||
|
|
||||||
/* [2] Check for user in auth list
|
/* [2] Check for user in auth list
|
||||||
=========================================================*/
|
=========================================================*/
|
||||||
|
/* (1) Check user for this code */
|
||||||
|
$user = auth($code);
|
||||||
|
|
||||||
|
|
||||||
/* [3] Manage action (states)
|
/* (2) If not found -> reset @last_user / @timeout + abort */
|
||||||
=========================================================*/
|
if( is_null($user) ){
|
||||||
|
|
||||||
|
$last_user = null;
|
||||||
|
$timeout = 0;
|
||||||
|
return false;
|
||||||
|
|
||||||
/* [n] Wait for 0.5 s before reading again
|
|
||||||
=========================================================*/
|
|
||||||
while( microtime(true)-$start_ts < 0.5 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* [3] Manage @timeout incrementation + @last_user
|
||||||
|
=========================================================*/
|
||||||
|
/* (1) If same as last -> increment @timeout */
|
||||||
|
if( $last_user == $user['id'] )
|
||||||
|
$timeout++;
|
||||||
|
|
||||||
|
/* (2) If different -> reset @timeout to 0 */
|
||||||
|
else
|
||||||
|
$timeout = 0;
|
||||||
|
|
||||||
|
|
||||||
|
/* [4] Manage action
|
||||||
|
=========================================================*/
|
||||||
|
/* (1) Try to process action */
|
||||||
|
$performed = act($user);
|
||||||
|
|
||||||
|
/* (2) If performed -> update chip according to new state */
|
||||||
|
if( $performed ){
|
||||||
|
|
||||||
|
// {1} Try to update state //
|
||||||
|
$updateds = syscall(SOURCE_DIR.'/lib/global-state/update');
|
||||||
|
|
||||||
|
// {2} If not updated -> error //
|
||||||
|
if( !$updateds )
|
||||||
|
slog("Cannot update chips to '".implode('',$state)."'", 'mfrc522:loop');
|
||||||
|
// {3} If updated -> success //
|
||||||
|
else
|
||||||
|
slog("Chips updated to ".implode('',$state)."'", 'mfrc522:loop');
|
||||||
|
|
||||||
|
/* (3) If not performed -> log error */
|
||||||
|
}else
|
||||||
|
slog("Cannot perform action by '$code' at timeout $timeout", 'mfrc522:loop');
|
||||||
|
|
||||||
|
/* (4) Store user for next loop */
|
||||||
|
$last_user = $user['id'];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
slog('daemon started (loop)', 'mfrc522:loop');
|
slog('daemon started (loop)', 'mfrc522:loop');
|
||||||
|
|
||||||
while( true )
|
while( true ){
|
||||||
|
|
||||||
|
$start_ts = microtime(true);
|
||||||
|
|
||||||
mfrc522_loop();
|
mfrc522_loop();
|
||||||
|
|
||||||
|
while( microtime(true) - $start_ts < 0.5 );
|
||||||
|
|
||||||
|
}
|
||||||
?>
|
?>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue