(Refer: https://en.wikipedia.org/wiki/Wiegand_interface)
The PHPoC Blue is interfaced with a RFID card reader through the Wiegand interface. When a RFID card is tagged to the RFID card reader, it sends the card information to the PHPoC Blue through the Wiegand interface.
[Components]
1. PHPoC Blue with a USB WIFI dongle.
2. RFID reader (it is from http://www.dx.com - http://www.dx.com/p/k5-tamper-proof-id-door-access-machine-w-proximity-cards-2000-users-silver-229665#.Wi4fI99l-cl)
3. DC +12V Power Supplier
4. Jump wires
5. Smart device (Smart phone or Smart pad)
[Diagram]
[Source Codes]
wiegand.php
PHP Code:
<?php
function check_wiegand26_parity($str)
{
if(strlen($str) != 26) return false;
for($i = 1, $cnt = 0; $i < 13; $i++) if(substr($str, $i, 1) == "1") $cnt++;
if($cnt % 2 && (substr($str, 0, 1) == "0")) return false;
if(!($cnt % 2) && (substr($str, 0, 1) == "1")) return false;
for($i = 13, $cnt = 0; $i < 25; $i++) if(substr($str, $i, 1) == "1") $cnt++;
if($cnt % 2 && (substr($str, 25, 1) == "1")) return false;
if(!($cnt % 2) && (substr($str, 25, 1) == "0")) return false;
return true;
}
function binstr2int($binstr)
{
for($i = strlen($binstr) - 1, $pos = 0, $num = 0; $i >= 0; $i--, $pos++)
{
if(substr($binstr, $i, 1) == "1") $num |= (1 <<$pos);
}
return $num;
}
function get_wiegand26_id($str)
{
if(strlen($str) != 26) return false;
$str_id = substr($str, 9, 16);
$id = binstr2int($str_id);
return $id;
}
function get_wiegand26_fac_code($str)
{
if(strlen($str) != 26) return false;
$str_code = substr($str, 1, 8);
$code = binstr2int($str_code);
return $code;
}
function get_wiegand26_full_id($str)
{
if(strlen($str) != 26) return false;
$str_full_id = substr($str, 1, 24);
$full_id = binstr2int($str_full_id);
return $full_id;
}
function wiegand_scan()
{
$ht0 = pid_open("/mmap/ht0");
$ht1 = pid_open("/mmap/ht1");
/*
42: 1us
minimum pulse width: 20us
Maximum data duration: 520ms (maximum bit length: 20ms * 26 bits)
==> unit: 16us (672)
*/
$frame_len = 26;
$bad_format = "Bad Wiegand Format";
$unit = 672; // 42: 1 us
$bit_slot = 100;
pid_ioctl($ht0, "set div $unit");
pid_ioctl($ht1, "set div $unit");
pid_ioctl($ht0, "set mode capture fall");
pid_ioctl($ht1, "set mode capture rise");
pid_ioctl($ht0, "set repc $frame_len");
pid_ioctl($ht1, "set repc $frame_len");
pid_ioctl($ht0, "set trigger from pin fall");
pid_ioctl($ht1, "set trigger from pin fall");
pid_ioctl($ht0, "start");
pid_ioctl($ht1, "start");
while(1)
{
$st_ht0 = pid_ioctl($ht0, "get state");
$st_ht1 = pid_ioctl($ht1, "get state");
$ht0_cnt = $frame_len - pid_ioctl($ht0, "get repc");
$ht1_cnt = $frame_len - pid_ioctl($ht1, "get repc");
if(($ht0_cnt + $ht1_cnt) >= $frame_len) break;
if($st_ht0 == 0 && $st_ht1 == 0) break;
}
pid_ioctl($ht0, "stop");
pid_ioctl($ht1, "stop");
$ht0_str = "0";
$ht1_str = "1";
for($i = 1; $i < $ht0_cnt; $i++)
{
$cnt = pid_ioctl($ht0, "get count $i");
$tmp = (int)(round($cnt/$bit_slot));
for($j = 1; $j<$tmp; $j++) $ht0_str .= "1";
$ht0_str .= "0";
}
for($i = 1; $i < $ht1_cnt; $i++)
{
$cnt = pid_ioctl($ht1, "get count $i");
$tmp = (int)(round($cnt/$bit_slot));
for($j = 1; $j<$tmp; $j++) $ht1_str .= "0";
$ht1_str .= "1";
}
pid_close($ht0);
pid_close($ht1);
// merging signal 0 and signal 1
$strlen_ht0 = strlen($ht0_str);
$strlen_ht1 = strlen($ht1_str);
$rfid = "";
$len_intersection = $strlen_ht0 + $strlen_ht1 - $frame_len;
// when either frame size is equal to max frame size
if($strlen_ht0 >= $frame_len)
{
if(strpos($ht0_str, $ht1_str) !== false) $rfid = $ht0_str;
else $rfid = $bad_format;
}
else if($strlen_ht1 >= $frame_len)
{
if(strpos($ht1_str, $ht0_str) !== false) $rfid = $ht1_str;
else $rfid = $bad_format;
}
// when two frame size frame size is equal to max frame size
else if(($strlen_ht0 + $strlen_ht1) == $frame_len)
{
if(check_wiegand26_parity($ht0_str . $ht1_str) == true) $rfid = $ht0_str . $ht1_str;
else if(check_wiegand26_parity($ht1_str . $ht0_str) == true) $rfid = $ht1_str . $ht0_str;
else $rfid = $bad_format;
}
// the others
else
{
$tmp_str = substr($ht0_str, 0, $len_intersection);
$ident_pos0 = strpos($ht1_str, $tmp_str, $strlen_ht1-$len_intersection);
$tmp_str = substr($ht1_str, 0, $len_intersection);
$ident_pos1 = strpos($ht0_str, $tmp_str, $strlen_ht0-$len_intersection);
if($ident_pos0 !== false) $rfid = $ht1_str . substr($ht0_str, $len_intersection);
else if($ident_pos1 !== false) $rfid = $ht0_str . substr($ht1_str, $len_intersection);
else $rfid = $bad_format;
}
return $rfid;
}
?>
task0.php
PHP Code:
<?php
include_once "lib/sn_tcp_ws.php";
include_once "wiegand.php";
ws_setup(0, "rfid", "csv.phpoc");
$rwbuf = "";
$count = 1;
$state_old = 0;
while(1)
{
$rfid = wiegand_scan();
if(check_wiegand26_parity($rfid) == false) $full_id="error";
else
{
$id = get_wiegand26_id($rfid);
$fac_code = get_wiegand26_fac_code($rfid);
$full_id = get_wiegand26_full_id($rfid);
}
if(ws_state(0) == TCP_CONNECTED)
{
ws_write(0, "$full_id");
echo "full_id: $full_id, fac_code: $fac_code, id: $id\r\n";
}
}
?>
index.php
PHP Code:
<?php
$ws_host = _SERVER("HTTP_HOST");
?>
<!DOCTYPE html>
<html>
<head>
<title>PHPoC</title>
<script>
var ws;
var count = 1;
function ws_init()
{
ws = new WebSocket("ws://<?echo $ws_host?>/rfid", "csv.phpoc");
//ws.onopen = function(){ document.getElementById("ws_state").innerHTML = "connected" };
ws.onclose = function(){ document.getElementById("ws_state").innerHTML = "closed"};
ws.onerror = function(){ alert("websocket error " + this.url) };
ws.onopen = ws_onopen;
ws.onmessage = ws_onmessage;
}
function ws_onopen(e_msg)
{
e_msg = e_msg || window.event; // MessageEvent
document.getElementById("ws_state").innerHTML = "connected";
document.getElementById("ws_reply").innerHTML = e_msg.data;
}
function ws_onmessage(e_msg)
{
e_msg = e_msg || window.event; // MessageEvent
document.getElementById("ws_reply").innerHTML = e_msg.data;
}
window.onload = ws_init;
</script>
</head>
<body>
<img style="margin:0px auto;display:block" src="k5-dam.jpg">
<h1 style="text-align:center" id="ws_reply">-</h1>
</body>
</html>