wiegand-control
Version:
Communicate with wiegand door access controller.
211 lines (185 loc) • 5.32 kB
text/typescript
import { Socket as UdpSocket } from "dgram";
import { Socket as TcpSocket } from "net";
import { isBuffer, isNumber } from "util";
import { buildBcdDate, ipToHex } from "./utils";
import funcNames from "./funcNames";
const { WGC_HIDE_LOG, WGC_ECHO_1, WGC_ECHO_2, WGC_ECHO_3 } = process.env;
const config = {
hideLog: !!WGC_HIDE_LOG,
echo1: WGC_ECHO_1 ? +WGC_ECHO_1 : 0,
echo2: WGC_ECHO_2 ? +WGC_ECHO_2 : 0,
echo3: WGC_ECHO_3 ? +WGC_ECHO_3 : 0
};
export default class WgCtl {
ip: string;
port: number;
serial?: number;
localSocket?: UdpSocket;
remoteSocket?: TcpSocket;
serverIp?: string;
serverPort?: number;
constructor(
socket: TcpSocket | UdpSocket,
serial?: number,
serverIp?: string,
serverPort?: number,
ip = "",
port = 60000
) {
this.ip = ip;
this.port = port;
this.serial = serial;
if (socket instanceof UdpSocket) {
this.localSocket = socket;
// server ip and port only available for local mode
this.serverIp = serverIp;
this.serverPort = serverPort;
} else {
this.remoteSocket = socket;
if (this.serverIp || this.serverPort) {
throw new Error("Server ip and port only available for local mode.");
}
}
}
protected packData(funcCode: number, payload?: string | number | Buffer) {
const data = Buffer.alloc(64);
data.writeUInt8(0x17, 0);
data.writeUInt8(funcCode, 1);
if (this.serial) {
data.writeUInt32LE(this.serial, 4);
}
if (payload) {
if (isBuffer(payload)) {
data.fill(payload, 8, 8 + payload.byteLength);
} else if (isNumber(payload)) {
data.writeUInt8(payload, 8);
} else {
data.write(payload.replace(/\s/g, ""), 8, "hex");
}
} else {
payload = Buffer.alloc(0);
}
const funcCodeStr = `0x${funcCode.toString(16).toUpperCase()}`;
if (!config.hideLog) {
console.log(
`[WGC] Func ${funcNames[funcCodeStr]}, controller ${this.serial ||
"all"}, payload to send:`,
payload
);
}
return data;
}
sendData(funcCode: number, payload?: string | number | Buffer) {
const data = this.packData(funcCode, payload);
if (this.remoteSocket) {
return this.remoteSendData(data);
} else {
return this.localSendData(data);
}
}
protected remoteSendData(data: Buffer) {
if (!this.remoteSocket) return;
this.remoteSocket.write(data, err => {
if (err) {
console.error(err);
}
});
}
protected localSendData(data: Buffer, isEcho = false) {
if (!this.localSocket) return;
if (!this.ip) {
this.localSocket.setBroadcast(true);
}
if (!WGC_HIDE_LOG) {
console.log(
`[WGC] Sending local data to ${this.ip || "255.255.255.255"}.`
);
}
this.localSocket.send(
data,
0,
data.byteLength,
this.port,
this.ip || "255.255.255.255",
(err, result) => {
if (err) {
console.error(err);
if (!this.ip && this.localSocket) {
this.localSocket.setBroadcast(false);
}
}
}
);
if (!isEcho && config.echo1) {
setTimeout(() => {
this.localSendData(data, true);
if (config.echo2) {
setTimeout(() => {
this.localSendData(data, true);
if (config.echo3) {
setTimeout(() => {
this.localSendData(data, true);
}, +config.echo3);
}
}, +config.echo2);
}
}, +config.echo1);
}
}
search() {
this.sendData(0x94);
}
openDoor(door: number) {
this.sendData(0x40, door);
}
getDate() {
this.sendData(0x32);
}
setDate(date?: Date) {
this.sendData(0x30, buildBcdDate(date || new Date()));
}
setAuth(cardNo: number, door?: number) {
const payload = Buffer.alloc(16);
payload.writeUInt32LE(cardNo, 0);
payload.write("20190101", 4, "hex");
payload.write("20291231", 8, "hex");
payload.writeUInt8(door && door !== 1 ? 0 : 1, 12);
payload.writeUInt8(door && door !== 2 ? 0 : 1, 13);
payload.writeUInt8(door && door !== 3 ? 0 : 1, 14);
payload.writeUInt8(door && door !== 4 ? 0 : 1, 15);
this.sendData(0x50, payload);
}
getAuth(cardNo: number) {
const payload = Buffer.alloc(4);
payload.writeUInt32LE(cardNo, 0);
this.sendData(0x5a, payload);
}
removeAuth(cardNo: number) {
const payload = Buffer.alloc(4);
payload.writeUInt32LE(cardNo, 0);
this.sendData(0x52, payload);
}
clearAuth() {
const payload = Buffer.from("55aaaa55", "hex");
this.sendData(0x54, payload);
}
setServerAddress(ip: string, port: number, interval = 0) {
const payload = Buffer.alloc(7);
payload.write(ipToHex(ip), "hex");
payload.writeUInt16LE(port, 4);
payload.writeUInt8(interval, 6);
this.sendData(0x90, payload);
}
setAddress(ip: string, subnet: string, gateway: string) {
const payload = Buffer.alloc(16);
payload.write(ipToHex(ip), "hex");
payload.write(ipToHex(subnet), 4, "hex");
payload.write(ipToHex(gateway), 8, "hex");
payload.write("55aaaa55", 12, "hex");
this.sendData(0x96, payload);
this.ip = "";
}
getServerAddress() {
this.sendData(0x92);
}
}