From de1b18258670b9d731bc84768ecb13431d50721d Mon Sep 17 00:00:00 2001 From: Dana Woodman Date: Sun, 4 Mar 2018 16:09:09 -0800 Subject: [PATCH] Add DoorLock controller model Add more tests, cleanup --- .env.example | 7 +++--- src/boot.js | 38 ++------------------------------ src/constants.js | 15 +++++++++++-- src/models/cards.js | 17 ++++++++++++++- src/models/cards.test.js | 6 +++++- src/models/door.js | 44 -------------------------------------- src/models/doorlock.js | 28 ++++++++++++++++++++++++ src/models/rfid-reader.js | 14 ++++++++++++ src/models/sd-card.js | 27 +++++++++++++++++++++++ src/models/sd-card.test.js | 31 +++++++++++++++++++++++++++ 10 files changed, 139 insertions(+), 88 deletions(-) create mode 100644 src/models/doorlock.js create mode 100644 src/models/sd-card.js create mode 100644 src/models/sd-card.test.js diff --git a/.env.example b/.env.example index 19c7185..506af8d 100644 --- a/.env.example +++ b/.env.example @@ -1,10 +1,9 @@ +# COBOT_CARDS_API='https://chimera.cobot.me/api/check_in_tokens' COBOT_CLIENT_ID='...' COBOT_CLIENT_SECRET='...' COBOT_REDIRECT_URL='http://10.0.1.48:8080/success' -COBOT_AUTHORIZE_URL='https://www.cobot.me/oauth/authorize' -COBOT_TOKEN_URL='https://www.cobot.me/oauth/access_token' -COBOT_SCOPE='checkin_tokens' +# COBOT_SCOPE='checkin_tokens' COBOT_USER_EMAIL='...' COBOT_USER_PASSWORD='...' -COBOT_CARDS_API='https://chimera.cobot.me/api/check_in_tokens' RFID_PRODUCT_NAME='Name of USB device' +# USB_MOUNT_PATH='...' diff --git a/src/boot.js b/src/boot.js index 58c6ef9..9a04c2b 100644 --- a/src/boot.js +++ b/src/boot.js @@ -1,37 +1,3 @@ -const Cobot = require('./models/cobot') +const DoorLock = require('./models/doorlock') -Cobot.authorize().then(cobot => { - cobot.cards().then(resp => console.log('RESP:', resp)) -}) - -// const server = require('./server') - -// server() - -// const Cards = require('./models/cards') -// const Door = require('./models/door') - -// Door.open() - -// Cards.update() - -// const server = require('./server') - -// doorlock.updateCards() -// server() - -// const HID = require('node-hid') - -// choose driverType -// default is 'libusb' for Mac OSX & Windows -// default is 'hidraw', for Linux -// let type = null - -// if (process.argv[2]) { -// type = process.argv[2] -// } -// disabled until prebuild gets multi-target, see issue node-hid#242 -// console.log('driverType:', (type) ? type : 'default'); -// HID.setDriverType( type ); - -// console.log('devices:', HID.devices()) +DoorLock.initialize() diff --git a/src/constants.js b/src/constants.js index 02fee59..1f11f5b 100644 --- a/src/constants.js +++ b/src/constants.js @@ -1,15 +1,26 @@ require('dotenv').config() +const path = require('path') + const ENV = process.env.NODE_ENV || 'development' +const USB_MOUNT_PATH = process.env.USB_MOUNT_PATH || '/mnt/sda1' +const CARDS_PATH = path.join( + USB_MOUNT_PATH, + process.env.CARDS_PATH || 'cards.json' +) module.exports = { - COBOT_CARDS_API: process.env.COBOT_CARDS_API, + CARDS_PATH, + COBOT_CARDS_API: + process.env.COBOT_CARDS_API || + 'https://chimera.cobot.me/api/check_in_tokens', COBOT_CLIENT_ID: process.env.COBOT_CLIENT_ID, COBOT_CLIENT_SECRET: process.env.COBOT_CLIENT_SECRET, - COBOT_SCOPE: process.env.COBOT_SCOPE, + COBOT_SCOPE: process.env.COBOT_SCOPE || 'checkin_tokens', COBOT_USER_EMAIL: process.env.COBOT_USER_EMAIL, COBOT_USER_PASSWORD: process.env.COBOT_USER_PASSWORD, DOOR_OPEN_DELAY: ENV === 'test' ? 1 : 6000, ENV, RFID_PRODUCT_NAME: process.env.RFID_PRODUCT_NAME, + USB_MOUNT_PATH, } diff --git a/src/models/cards.js b/src/models/cards.js index 0e5ed59..93c50d4 100644 --- a/src/models/cards.js +++ b/src/models/cards.js @@ -1,10 +1,25 @@ const axios = require('axios') -const { COBOT_CARDS_API } = require('../constants') +const { CARDS_PATH, COBOT_CARDS_API } = require('../constants') +const SDCard = require('./sd-card') class Cards { static update() { return axios.get(COBOT_CARDS_API) } + + static read() { + return SDCard.read(CARDS_PATH) + } + + static write(cards) { + return SDCard.write(CARDS_PATH, cards) + } + + // static validate(number) { + // return this.read().then(cards => { + // return cards.find(c => c.number === number) + // }) + // } } module.exports = Cards diff --git a/src/models/cards.test.js b/src/models/cards.test.js index 51aa53a..1e5b4a1 100644 --- a/src/models/cards.test.js +++ b/src/models/cards.test.js @@ -2,8 +2,12 @@ const Cards = require('./cards') describe('models/cards', () => { describe('.update', () => { - test('should fetch list of RFID cards', () => { + test.skip('should fetch list of RFID cards', () => { return Cards.update().then(cards => expect(cards).toEqual()) }) }) + + describe('.validate', () => { + test.skip('should check card against list', () => {}) + }) }) diff --git a/src/models/door.js b/src/models/door.js index 536a03d..2d971ee 100644 --- a/src/models/door.js +++ b/src/models/door.js @@ -2,12 +2,6 @@ const { DOOR_OPEN_DELAY } = require('../constants') const logger = require('../utils/logger') const tessel = require('tessel') -// const fs = require('fs') -// const path = require('path') - -// const USB_MOUNT_PATH = '/mnt/sda1' -// const CARDS_PATH = path.join(USB_MOUNT_PATH, 'cards.json') - class Door { static open() { logger.log('OPEN DOOR') @@ -31,41 +25,3 @@ class Door { } module.exports = Door - -// const doorlock = {} - -// doorlock.updateCards = () => { -// console.log('fetch cards from API and update file') -// const cards = [{ card: '1234', name: 'John' }, { card: '5566', name: 'Jane' }] -// doorlock.writeCards(cards) -// } - -// doorlock.readCards = cb => { -// fs.readFile(CARDS_PATH, function(err, data) { -// if (err) throw err -// console.log('data:', data.toString()) -// cb(JSON.parse(data)) -// }) -// } - -// doorlock.writeCards = cards => { -// const text = JSON.stringify(cards) -// fs.writeFile(CARDS_PATH, text, err => { -// if (err) throw err -// console.log('wrote:', cards) -// }) -// } - -// doorlock.open = () => { -// console.log('open!') -// tessel.led[2].on() -// setTimeout(() => tessel.led[2].off(), 3000) -// } - -// doorlock.close = () => { -// console.log('close!') -// tessel.led[3].on() -// setTimeout(() => tessel.led[3].off(), 3000) -// } - -// module.exports = doorlock diff --git a/src/models/doorlock.js b/src/models/doorlock.js new file mode 100644 index 0000000..856dba0 --- /dev/null +++ b/src/models/doorlock.js @@ -0,0 +1,28 @@ +const Cobot = require('./cobot') +const Cards = require('./cards') +const logger = require('../utils/logger') + +class DoorLock { + static initializeRFIDReader() { + console.log('TODO: initialize RFID reader...') + Cards.read().then(cards => logger.log('EXISTING:', cards.length, 'cards')) + } + + static updateCards() { + logger.log('UPDATING CARDS!') + Cobot.authorize().then(cobot => { + cobot.cards().then(cards => { + logger.log('NEW:', cards.length, 'cards') + Cards.write(cards) + }) + }) + } + + static initialize() { + logger.log('INITIALIZING DOORLOCK!') + this.updateCards() + this.initializeRFIDReader() + } +} + +module.exports = DoorLock diff --git a/src/models/rfid-reader.js b/src/models/rfid-reader.js index 0505e8b..5e6e851 100644 --- a/src/models/rfid-reader.js +++ b/src/models/rfid-reader.js @@ -25,4 +25,18 @@ class RFIDReader { } } +// const RFIDReader = require('./models/rfid-reader') + +// console.log(RFIDReader.devices()) +// const reader = RFIDReader.reader() + +// reader.on('data', data => console.log(data)) +// reader.close() + +// new Promise(resolve => { +// setTimeout(() => resolve(), 10000) +// }) + +// console.log('READER:', reader) + module.exports = RFIDReader diff --git a/src/models/sd-card.js b/src/models/sd-card.js new file mode 100644 index 0000000..6aff43d --- /dev/null +++ b/src/models/sd-card.js @@ -0,0 +1,27 @@ +const fs = require('fs') +const logger = require('../utils/logger') + +class SDCard { + static read(filePath) { + return new Promise((resolve, reject) => { + fs.readFile(filePath, (err, data) => { + if (err) return reject(err) + // logger.log('READ:', data.toString()) + resolve(JSON.parse(data)) + }) + }) + } + + static write(filePath, json) { + const text = JSON.stringify(json) + return new Promise((resolve, reject) => { + fs.writeFile(filePath, text, err => { + if (err) return reject(err) + // logger.log('WROTE:', json) + resolve() + }) + }) + } +} + +module.exports = SDCard diff --git a/src/models/sd-card.test.js b/src/models/sd-card.test.js new file mode 100644 index 0000000..d6bbf00 --- /dev/null +++ b/src/models/sd-card.test.js @@ -0,0 +1,31 @@ +const fs = require('fs') +const SDCard = require('./sd-card') + +jest.mock('fs') + +describe('models/sd-card', () => { + const filePath = '/path/to/cards.json' + const expected = [{ name: 'John', number: '123' }] + + describe('.read', () => { + test('should read and convert file data to JSON', () => { + jest + .spyOn(fs, 'readFile') + .mockImplementationOnce((p, cb) => cb(null, JSON.stringify(expected))) + return SDCard.read(filePath).then(actual => { + expect(actual).toEqual(expected) + }) + }) + }) + + describe('.write', () => { + test('should write data to SD card', () => { + jest.spyOn(fs, 'writeFile').mockImplementationOnce((path, text, cb) => { + expect(path).toBe(filePath) + expect(text).toBe(JSON.stringify(expected)) + cb() + }) + return expect(SDCard.write(filePath, expected)).resolves.toBe() + }) + }) +})