From c70d626e473c8cbdbd87125a256ca221c0c3fa23 Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Mon, 12 Feb 2018 23:16:11 +0100 Subject: Add RFID support --- example.cfg | 3 +- sql/tables.sql | 1 + src/database/database.vala | 46 +++++++++++++++++++++++ src/database/db-interface.vala | 6 +++ src/input-device/main.vala | 13 +++++-- src/scanner-session/scannersession-interface.vala | 1 + src/scanner-session/scannersession.vala | 20 +++++++--- src/serial-device/main.vala | 6 +-- src/web/csv.vala | 10 +++++ src/web/web.vala | 1 + systemd/shopsystem-input-device-rfid.rules | 1 + templates/users/entry.html | 1 + 12 files changed, 97 insertions(+), 12 deletions(-) create mode 100644 systemd/shopsystem-input-device-rfid.rules diff --git a/example.cfg b/example.cfg index 65056d8..a56e074 100644 --- a/example.cfg +++ b/example.cfg @@ -6,7 +6,8 @@ spacename = Mainframe file = /path/to/shop.db [INPUT] # use ignore if you have no device (this skips the input feature) -device = /dev/input/by-id/path-to-barcode-scanner +barcodescanner = /dev/barcodescanner +rfidreader = /dev/rfidreader [MAIL] server = mail.server.example.com port = 587 diff --git a/sql/tables.sql b/sql/tables.sql index fbe4d0e..1518ef2 100644 --- a/sql/tables.sql +++ b/sql/tables.sql @@ -9,5 +9,6 @@ CREATE TABLE IF NOT EXISTS supplier(id INTEGER PRIMARY KEY AUTOINCREMENT, name T CREATE TABLE IF NOT EXISTS cashbox_diff(id INTEGER PRIMARY KEY AUTOINCREMENT, user INTEGER NOT NULL REFERENCES users, amount INTEGER NOT NULL, timestamp INTEGER NOT NULL DEFAULT 0); CREATE TABLE IF NOT EXISTS ean_aliases (id INTEGER PRIMARY KEY NOT NULL, real_ean INTEGER NOT NULL REFERENCES products); CREATE TABLE IF NOT EXISTS categories (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT); +CREATE TABLE IF NOT EXISTS rfid_users (rfid TEXT, user INTEGER NOT NULL REFERENCES users); CREATE INDEX IF NOT EXISTS invoiceindex ON sales (user ASC, timestamp DESC); COMMIT; diff --git a/src/database/database.vala b/src/database/database.vala index dc636b8..0ce3f87 100644 --- a/src/database/database.vala +++ b/src/database/database.vala @@ -138,6 +138,10 @@ public class DataBase : Object { queries["alias_ean_add"] = "INSERT OR IGNORE INTO ean_aliases (id, real_ean) VALUES (?, ?)"; queries["alias_ean_get"] = "SELECT real_ean FROM ean_aliases WHERE id = ?"; queries["alias_ean_list"] = "SELECT id, real_ean FROM ean_aliases ORDER BY id ASC"; + queries["userid_rfid"] = "SELECT user FROM rfid_users WHERE rfid = ?"; + queries["rfid_userid"] = "SELECT rfid FROM rfid_users WHERE user = ?"; + queries["rfid_insert"] = "INSERT OR REPLACE INTO rfid_users ('user','rfid') VALUES (?,?)"; + queries["rfid_delete_user"] = "DELETE FROM rfid_users WHERE user = ?"; /* compile queries into statements */ foreach(var entry in queries.entries) { @@ -632,6 +636,17 @@ public class DataBase : Object { throw new DatabaseError.INTERNAL_ERROR("internal error: %d", rc); } + statements["rfid_userid"].reset(); + statements["rfid_userid"].bind_int(1, user); + rc = statements["rfid_userid"].step(); + + string[] rfid = {}; + while(rc == Sqlite.ROW) { + rfid += statements["rfid_userid"].column_text(0); + rc = statements["rfid_userid"].step(); + } + result.rfid = rfid; + return result; } @@ -894,6 +909,21 @@ public class DataBase : Object { int rc = statements["user_replace"].step(); if(rc != Sqlite.DONE) throw new DatabaseError.INTERNAL_ERROR("internal error: %d", rc); + + statements["rfid_delete_user"].reset(); + statements["rfid_delete_user"].bind_int(1, u.id); + rc = statements["rfid_delete_user"].step(); + if(rc != Sqlite.DONE) + throw new DatabaseError.INTERNAL_ERROR("internal error: %d", rc); + + foreach (string rfid in u.rfid) { + statements["rfid_insert"].reset(); + statements["rfid_insert"].bind_int(1, u.id); + statements["rfid_insert"].bind_text(2, rfid); + rc = statements["rfid_insert"].step(); + if(rc != Sqlite.DONE) + throw new DatabaseError.INTERNAL_ERROR("internal error: %d", rc); + } } public bool user_is_disabled(int user) throws DatabaseError { @@ -1164,4 +1194,20 @@ public class DataBase : Object { return bbdlist.data; } + + public int get_userid_for_rfid(string rfid) throws IOError, DatabaseError { + statements["userid_rfid"].reset(); + statements["userid_rfid"].bind_text(1, rfid); + + int rc = statements["userid_rfid"].step(); + + switch(rc) { + case Sqlite.ROW: + return statements["userid_rfid"].column_int(0); + case Sqlite.DONE: + throw new DatabaseError.RFID_NOT_FOUND("unknown rfid: %s", rfid); + default: + throw new DatabaseError.INTERNAL_ERROR("internal error: %d", rc); + } + } } diff --git a/src/database/db-interface.vala b/src/database/db-interface.vala index de5bbc4..b6d1395 100644 --- a/src/database/db-interface.vala +++ b/src/database/db-interface.vala @@ -65,6 +65,9 @@ public interface Database : Object { public abstract uint64 ean_alias_get(uint64 ean) throws IOError; public abstract EanAlias[] ean_alias_list() throws IOError; public abstract BestBeforeEntry[] bestbeforelist() throws IOError; + public abstract int get_userid_for_rfid(string rfid) throws IOError, DatabaseError; + public abstract void addrfid(string rfid, int user) throws IOError, DatabaseError; + public abstract void delete_rfid_for_user(int user) throws IOError, DatabaseError; } public struct Category { @@ -126,6 +129,7 @@ public struct UserInfo { public bool disabled; public bool hidden; public string soundTheme; + public string[] rfid; public bool equals(UserInfo x) { if(id != x.id) return false; @@ -140,6 +144,7 @@ public struct UserInfo { if(joined_at != x.joined_at) return false; if(disabled != x.disabled) return false; if(hidden != x.hidden) return false; + if(rfid != x.rfid) return false; return true; } @@ -197,4 +202,5 @@ public errordomain DatabaseError { SESSION_NOT_FOUND, USER_NOT_FOUND, CONSTRAINT_FAILED, + RFID_NOT_FOUND, } diff --git a/src/input-device/main.vala b/src/input-device/main.vala index 8578033..30119b0 100644 --- a/src/input-device/main.vala +++ b/src/input-device/main.vala @@ -13,12 +13,14 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -Device dev; +Device devScanner; +Device devRfid; public static int main(string[] args) { try { Config cfg = Bus.get_proxy_sync(BusType.SYSTEM, "io.mainframe.shopsystem.Config", "/io/mainframe/shopsystem/config"); - dev = new Device(cfg.get_string("INPUT", "device")); + devScanner = new Device(cfg.get_string("INPUT", "barcodescanner")); + devRfid = new Device(cfg.get_string("INPUT", "rfidreader")); } catch(IOError e) { error("IOError: %s\n", e.message); } catch(KeyFileError e) { @@ -40,7 +42,12 @@ public static int main(string[] args) { void on_bus_aquired(DBusConnection con) { try { - con.register_object("/io/mainframe/shopsystem/device", dev); + con.register_object("/io/mainframe/shopsystem/device/scanner", devScanner); + } catch(IOError e) { + stderr.printf("Could not register service\n"); + } + try { + con.register_object("/io/mainframe/shopsystem/device/rfid", devRfid); } catch(IOError e) { stderr.printf("Could not register service\n"); } diff --git a/src/scanner-session/scannersession-interface.vala b/src/scanner-session/scannersession-interface.vala index ff2c2e9..c19a434 100644 --- a/src/scanner-session/scannersession-interface.vala +++ b/src/scanner-session/scannersession-interface.vala @@ -31,6 +31,7 @@ public enum ScannerSessionCodeType { UNDO, LOGOUT, EAN, + RFIDEM4100, UNKNOWN } diff --git a/src/scanner-session/scannersession.vala b/src/scanner-session/scannersession.vala index f19d94c..7cc9cc4 100644 --- a/src/scanner-session/scannersession.vala +++ b/src/scanner-session/scannersession.vala @@ -23,7 +23,8 @@ public class ScannerSessionImplementation { private Database db; private AudioPlayer audio; - private InputDevice dev; + private InputDevice devScanner; + private InputDevice devRfid; private Cli cli; private ScannerSessionState state = ScannerSessionState.READY; @@ -35,11 +36,13 @@ public class ScannerSessionImplementation { public ScannerSessionImplementation() { try { db = Bus.get_proxy_sync(BusType.SYSTEM, "io.mainframe.shopsystem.Database", "/io/mainframe/shopsystem/database"); - dev = Bus.get_proxy_sync(BusType.SYSTEM, "io.mainframe.shopsystem.InputDevice", "/io/mainframe/shopsystem/device"); + devScanner = Bus.get_proxy_sync(BusType.SYSTEM, "io.mainframe.shopsystem.InputDevice", "/io/mainframe/shopsystem/device/scanner"); + devRfid = Bus.get_proxy_sync(BusType.SYSTEM, "io.mainframe.shopsystem.InputDevice", "/io/mainframe/shopsystem/device/rfid"); cli = Bus.get_proxy_sync(BusType.SYSTEM, "io.mainframe.shopsystem.Cli", "/io/mainframe/shopsystem/cli"); audio = Bus.get_proxy_sync(BusType.SYSTEM, "io.mainframe.shopsystem.AudioPlayer", "/io/mainframe/shopsystem/audio"); - dev.received_barcode.connect(handle_barcode); + devScanner.received_barcode.connect(handle_barcode); + devRfid.received_barcode.connect(handle_barcode); cli.received_barcode.connect(handle_barcode); } catch(IOError e) { error("IOError: %s\n", e.message); @@ -85,6 +88,8 @@ public class ScannerSessionImplementation { return ScannerSessionCodeType.UNDO; } else if(scannerdata == "LOGOUT") { return ScannerSessionCodeType.LOGOUT; + } else if(scannerdata.length == 10) { + return ScannerSessionCodeType.RFIDEM4100; } else { //Handle EAN Code uint64 id = 0; @@ -184,6 +189,10 @@ public class ScannerSessionImplementation { scannerResult.audioType = AudioType.ERROR; state = ScannerSessionState.READY; return scannerResult; + case ScannerSessionCodeType.RFIDEM4100: + int user = db.get_userid_for_rfid(scannerdata); + scannerResult.nextScannerdata =@"USER $user"; + return scannerResult; default: state = ScannerSessionState.READY; return scannerResult; @@ -249,7 +258,8 @@ public class ScannerSessionImplementation { break; case ScannerSessionCodeType.USER: case ScannerSessionCodeType.GUEST: - //Logout alten User und akrtikel kaufen + case ScannerSessionCodeType.RFIDEM4100: + /* Logout old user session (and buy articles) */ scannerResult = logout(); scannerResult.nextScannerdata = scannerdata; break; @@ -284,7 +294,7 @@ public class ScannerSessionImplementation { try { stdout.printf("scannerdata: %s\n", scannerdata); if(interpret(scannerdata)) - dev.blink(1000); + devScanner.blink(1000); } catch(IOError e) { send_message(MessageType.ERROR, "IOError: %s", e.message); } catch(DatabaseError e) { diff --git a/src/serial-device/main.vala b/src/serial-device/main.vala index 0dea907..70d50e2 100644 --- a/src/serial-device/main.vala +++ b/src/serial-device/main.vala @@ -13,12 +13,12 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -Device dev; +Device scanner; public static int main(string[] args) { try { Config cfg = Bus.get_proxy_sync(BusType.SYSTEM, "io.mainframe.shopsystem.Config", "/io/mainframe/shopsystem/config"); - dev = new Device(cfg.get_string("INPUT", "device"), 9600, 8, 1); + scanner = new Device(cfg.get_string("INPUT", "barcodescanner"), 9600, 8, 1); } catch(IOError e) { error("IOError: %s\n", e.message); } catch(KeyFileError e) { @@ -40,7 +40,7 @@ public static int main(string[] args) { void on_bus_aquired(DBusConnection con) { try { - con.register_object("/io/mainframe/shopsystem/device", dev); + con.register_object("/io/mainframe/shopsystem/devicescanner", scanner); } catch(IOError e) { stderr.printf("Could not register service\n"); } diff --git a/src/web/csv.vala b/src/web/csv.vala index 299af8d..5d4daba 100644 --- a/src/web/csv.vala +++ b/src/web/csv.vala @@ -1,4 +1,5 @@ /* Copyright 2012, Sebastian Reichel + * Copyright 2017-2018, Johannes Rudolph * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -66,6 +67,15 @@ public class CSVMemberFile { m.pgp = csv_value(linedata[9]); m.hidden = int.parse(csv_value(linedata[10])) != 0; m.disabled = int.parse(csv_value(linedata[11])) != 0; + string[] rfid = {}; + if(csv_value(linedata[12]) != "") + rfid += csv_value(linedata[12]); + if(csv_value(linedata[13]) != "") + rfid += csv_value(linedata[13]); + if(csv_value(linedata[14]) != "") + rfid += csv_value(linedata[14]); + m.rfid = rfid; + m.soundTheme = ""; if(csv_value(linedata[0]) != "EXTERNEMITGLIEDSNUMMER") members += m; diff --git a/src/web/web.vala b/src/web/web.vala index 37e6edc..f4207ad 100644 --- a/src/web/web.vala +++ b/src/web/web.vala @@ -351,6 +351,7 @@ public class WebServer { t.replace("PGPKEYID", userinfo.pgp); t.replace("DISABLED", userinfo.disabled ? "true" : "false"); t.replace("HIDDEN", userinfo.hidden ? "true" : "false"); + t.replace("RFID", string.joinv("
",userinfo.rfid)); var userauth = db.get_user_auth(id); t.replace("ISSUPERUSER", userauth.superuser ? "true" : "false"); diff --git a/systemd/shopsystem-input-device-rfid.rules b/systemd/shopsystem-input-device-rfid.rules new file mode 100644 index 0000000..aebfbea --- /dev/null +++ b/systemd/shopsystem-input-device-rfid.rules @@ -0,0 +1 @@ +ACTION=="add", ATTRS{idVendor}=="ffff", ATTRS{idProduct}=="0035", MODE="0666", SYMLINK+="rfidreader" TAG+="systemd", ENV{SYSTEMD_WANTS}="shopsystem-input-device" diff --git a/templates/users/entry.html b/templates/users/entry.html index 065c4e7..b1477c7 100644 --- a/templates/users/entry.html +++ b/templates/users/entry.html @@ -22,6 +22,7 @@ Street{{{STREET}}} PLZ{{{POSTALCODE}}} City{{{CITY}}} + RFID{{{RFID}}} Settings Sound theme -- cgit v1.2.3