From f698fe389abad60dcc14253761c9904004172712 Mon Sep 17 00:00:00 2001 From: xdrm-brackets Date: Tue, 21 Feb 2017 18:50:37 +0100 Subject: [PATCH 1/3] [Update] Loop -> implemented information cache (action/current state/states) + loop minimum" [Todo] Implement loop function using actions/states [Done] Implemented first auth verification (if in list but no action check) --- lib/mfrc522/source/.loop.php.swp | Bin 0 -> 12288 bytes lib/mfrc522/source/loop.php | 196 +++++++++++++++++++++++++++++-- 2 files changed, 184 insertions(+), 12 deletions(-) create mode 100644 lib/mfrc522/source/.loop.php.swp diff --git a/lib/mfrc522/source/.loop.php.swp b/lib/mfrc522/source/.loop.php.swp new file mode 100644 index 0000000000000000000000000000000000000000..8bdfea5420d19e8e32743dca7b3336f94237d986 GIT binary patch literal 12288 zcmeI2+iM(E9LG<^*iJ8AT10(NPuu9s#AG*@##Wn68@Ejxn>LzFR1E7dJ9Bn(n#s&M z=S(k_+Ja9CK4@=V@ZEx-4`N&KK_8?DQUvjD5Ctz4tRN_U&&=#5X_^Xc5KCvsC!3iw z=XZYR`}>{Cl2hq?W@tCvnA<>b-ATyr?1Sg-{YfWZ>VzC{!|9GnXggC(3RS+q6~E`% zbs5wbcq4iI@*IQtZA?s|O1{QrPLbd&l)!VtM6Io%Vz|E*YB&!{pR*m;`cXg`nuV1&8u30^PGb)kwIa450AX6YyAX6Yy zAX6YyAXDI`RY2C4kR#~*EvW)0($6KAeWthBN2WlgK&C*ZK&C*ZK&C*ZK&C*ZK&C*Z zK&C*ZzzwK??Go}ezU=qi3g_|v|Hk+Ki+2$6EBF!o0M39!kLGTD@11;eE?Sz~LK9~m2gMLr|ePA(vgnSClfwSNY zcmtHcMsOdv8(dmJ$QR&q@E&*tL_mUJpo3*#DfoUlAzy(H!3l5(L_mT%2*4ij7}x|h zf=9t!;9CtofOo)2upbn`6W~G60{&PAf4~KB8oUNx1sv=GUEm(@*HXL-E`i^`Meq&y z44eaJ!7(rnwt^h!0Byho2GGI7;32RAEC)Z|M#x8CFW_Jp>;eyf`@!EWXdC&!XlJgMsz$ZKwO(y`)Xulj3BOFAwYj9#AdJll zT4DH`(U93L_iNOy+1#h_Z!ucyDbwAyZ`T;L9m%1LfnG@_lw#VVw9s9q#YyH&#T|+S z3n{!;r>m&Pg;cG887&L+GMy0$EeYN_#|~Ypw>p8#^jMB{vjV5&i30~~>J3^zltURr z^*RfU_>l^0Gn~nzf;cD~+w+Xl$oOb+yR~g-G^fuw@|D;%DFREYwkMEHixcRsS%D6# z+@-2}aIhNrNhs!~^r2=(D!o)53aYLG?Nt7>dbW^OtWbgak>@RrlgN)DpG$6g{3S+f zUQn?;y3Y=|UGW%Bwr@^JccX;6x)NZfPFGUWn&h&WXxQp3mnX__ zZbDg9o^3Gcfa_A`%kUtT0i<^(S?U+Gyh43dJMooQ4Z4;K!K87;7tKZ^JxL=|>>xE% zyn;xY^BZ#lUvfWUu@1^M7nTyyNS!w^d!=4?n{=q=tGR$zX)F_EVb~N@OKZT@y&~`} zm#J}JG^5keU#;N?rD3+mvtpdau^O;DmgtZe^|&94fo9QkI{nQu!-A>-w+^9DiP>e+ zr&P=+gNhi{jmp&OtSoc zvM&wKb*Ep`&VQDFSi6$^8z_zqjqJHf0y<2n4TefVwx5>j-XP|@k;-1?NMoQ_++HeK z!y`MeT-j=kO2!R_-2fIR-wwmUzWH|Q9DvsM*}rGMMJqQj4-$lNV@gd~ByRJX9K+X(=82qgZ)ox)2ZE>mT}99Y>(e z@l<@9YZ?#2*z#iR$U6UR#htf5z)BQh&#N{F>Ba!vp4ktmO;0L^ifp`!HH1p<@j`PJ zRdpNddGdEtmGm}MOxX?DixCf*75EOLmfAg87WPlMociIu<3%pZ Some RFID code + * + * @return user 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; + + } + + + + + + + + + + + + + - $last_card; - $times; 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 =========================================================*/ - $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'); - /* [2] Parse @authlist to cache [action]=>[rfid1, rfid2, ..] - =========================================================*/ - - /* [3] Initialize global variables + + /* [2] Parse ACTIONS and cache them =========================================================*/ - $last_card = null; - $times = 0; + /* (1) Parse each line */ + 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]][] = [ + 'id' => $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 external 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,6 +180,11 @@ function mfrc522_loop(){ + /* [1] Load global variables + =========================================================*/ + global $last_user; + global $timeout; + /* [1] Wait for rfid card =========================================================*/ while( ($code=syscall(SOURCE_DIR.'/lib/mfrc522/read')) === false ); @@ -48,10 +198,32 @@ /* [2] Check for user in auth list =========================================================*/ + /* (0) CHECK FOR USER INFO IN AUTH LIST + ---------------------------------------------------------*/ + $user = auth($code); + + + /* (1) UNKNOWN USER -> reset count + ---------------------------------------------------------*/ + 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++; + + + + } - /* [3] Manage action (states) - =========================================================*/ /* [n] Wait for 0.5 s before reading again From 1500d616a97cb08f73b5423aa21bbce962875d7e Mon Sep 17 00:00:00 2001 From: xdrm-brackets Date: Wed, 22 Feb 2017 10:26:24 +0100 Subject: [PATCH 2/3] [Update] Implemented the whole mfrc522:loop script[Todo] Rename \lib\chip to \lib\global-state and create 'update' which updated the whole chips according to the STATE file --- lib/mfrc522/source/loop.php | 231 +++++++++++++++++++++++++++++++----- 1 file changed, 204 insertions(+), 27 deletions(-) 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 ); + + } ?> From 07b61d216743c9715303ed759d009619438da858 Mon Sep 17 00:00:00 2001 From: xdrm-brackets Date: Wed, 22 Feb 2017 10:40:43 +0100 Subject: [PATCH 3/3] [Update] Renames \lib\chip to \lib\global-state and implemented 'update' that updated all chips according to the STATE file and the CHIPS list --- lib/chip/state | 3 - lib/global-state/set | 3 + .../state.php => global-state/source/set.php} | 12 ++- lib/global-state/source/update.php | 76 +++++++++++++++++++ lib/global-state/update | 3 + lib/mfrc522/source/loop.php | 2 +- 6 files changed, 91 insertions(+), 8 deletions(-) delete mode 100755 lib/chip/state create mode 100755 lib/global-state/set rename lib/{chip/source/state.php => global-state/source/set.php} (86%) create mode 100755 lib/global-state/source/update.php create mode 100755 lib/global-state/update diff --git a/lib/chip/state b/lib/chip/state deleted file mode 100755 index 7457f40..0000000 --- a/lib/chip/state +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -/usr/bin/env php $(realpath $(dirname $0))/source/state.php $*; diff --git a/lib/global-state/set b/lib/global-state/set new file mode 100755 index 0000000..d27aec8 --- /dev/null +++ b/lib/global-state/set @@ -0,0 +1,3 @@ +#!/bin/sh + +/usr/bin/env php $(realpath $(dirname $0))/source/set.php $*; diff --git a/lib/chip/source/state.php b/lib/global-state/source/set.php similarity index 86% rename from lib/chip/source/state.php rename to lib/global-state/source/set.php index d8dc0ae..457c706 100755 --- a/lib/chip/source/state.php +++ b/lib/global-state/source/set.php @@ -5,7 +5,7 @@ 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_state = null; @@ -50,8 +50,10 @@ } /* (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; + } @@ -61,8 +63,10 @@ foreach($g_pins as $pinNumber) // 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; + } /* (2) For each pin, set the associated value */ foreach($g_state as $pinIndex=>$pinValue){ @@ -90,7 +94,7 @@ /* [2] Launch main script =========================================================*/ - $exec = chip_state($argv[1], $argv[2]); + $exec = globalstate_set($argv[1], $argv[2]); echo $exec; die($exec); diff --git a/lib/global-state/source/update.php b/lib/global-state/source/update.php new file mode 100755 index 0000000..fb588b4 --- /dev/null +++ b/lib/global-state/source/update.php @@ -0,0 +1,76 @@ +#!/usr/bin/php + +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); +?> + diff --git a/lib/global-state/update b/lib/global-state/update new file mode 100755 index 0000000..0cb51e3 --- /dev/null +++ b/lib/global-state/update @@ -0,0 +1,3 @@ +#!/bin/sh + +/usr/bin/env php $(realpath $(dirname $0))/source/update.php; diff --git a/lib/mfrc522/source/loop.php b/lib/mfrc522/source/loop.php index b97c467..03f4776 100755 --- a/lib/mfrc522/source/loop.php +++ b/lib/mfrc522/source/loop.php @@ -292,7 +292,7 @@ if( $f_gstate === false ) return; - /* (2) Remove external spaces */ + /* (2) Remove surrounding spaces */ $f_gstate = preg_replace('@^\s+@', '', $f_gstate); $f_gstate = preg_replace('@\s+$@', '', $f_gstate);