diff --git a/lib/mfrc522/source/loop.php b/lib/mfrc522/source/loop.php index 4e5320f..b97c467 100755 --- a/lib/mfrc522/source/loop.php +++ b/lib/mfrc522/source/loop.php @@ -15,7 +15,7 @@ $states = []; $last_user = null; - $timeout = 1; + $timeout = 0; @@ -67,6 +67,136 @@ + /* PROCESS ACTIONS IF ACTION CAN BE PERFORMED BY USER (DEPENDING ON TIMEOUT/STATE) + * + * @user Current user information + * + * @return success 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; + + } @@ -122,10 +252,9 @@ $actions[$parsed[0]] = []; /* (4) Add entry to cache */ - $actions[$parsed[0]][] = [ - 'id' => $parsed[1], + $actions[$parsed[0]][$parsed[1]] = [ 'prev' => $parsed[2], - 'next' => $parsed[3], + 'next' => $parsed[3] ]; } @@ -182,53 +311,89 @@ /* [1] Load global variables =========================================================*/ + /* (1) Persistent variabes */ global $last_user; global $timeout; + /* (2) Caches */ + global $actions, $states, $state; + + + /* [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); slog("card '$code' read", 'mfrc522:read'); - $start_ts = microtime(true); /* [2] Check for user in auth list =========================================================*/ - /* (0) CHECK FOR USER INFO IN AUTH LIST - ---------------------------------------------------------*/ + /* (1) Check user for this code */ $user = auth($code); - /* (1) UNKNOWN USER -> reset count - ---------------------------------------------------------*/ + /* (2) If not found -> reset @last_user / @timeout + abort */ if( is_null($user) ){ $last_user = null; - $timeout = 1; - - - /* (2) KNOWN USER -> Manage timeout - ---------------------------------------------------------*/ - }else{ - - /* (1) If same as last -> increment @timeout */ - if( $last_user == $user['id'] ) - $timeout++; - - + $timeout = 0; + return false; } - - - /* [n] Wait for 0.5 s before reading again + /* [3] Manage @timeout incrementation + @last_user =========================================================*/ - while( microtime(true)-$start_ts < 0.5 ); + /* (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']; + } @@ -236,9 +401,21 @@ + + + + + slog('daemon started (loop)', 'mfrc522:loop'); - while( true ) + while( true ){ + + $start_ts = microtime(true); + mfrc522_loop(); + + while( microtime(true) - $start_ts < 0.5 ); + + } ?>