mirror of
https://github.com/zyphlar/doorlock.git
synced 2024-04-03 21:36:03 +00:00
Simplify code, get scanning working
This commit is contained in:
@@ -1,3 +0,0 @@
|
||||
const DoorLock = require('./models/doorlock')
|
||||
|
||||
DoorLock.initialize()
|
||||
@@ -1,26 +0,0 @@
|
||||
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 = {
|
||||
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 || '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,
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
class AccessLog {
|
||||
static log(member) {
|
||||
console.log('LOGGING', member)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AccessLog
|
||||
@@ -1,25 +0,0 @@
|
||||
const axios = require('axios')
|
||||
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
|
||||
@@ -1,13 +0,0 @@
|
||||
const Cards = require('./cards')
|
||||
|
||||
describe('models/cards', () => {
|
||||
describe('.update', () => {
|
||||
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', () => {})
|
||||
})
|
||||
})
|
||||
@@ -1,57 +0,0 @@
|
||||
const axios = require('axios')
|
||||
const {
|
||||
COBOT_CARDS_API,
|
||||
COBOT_CLIENT_ID,
|
||||
COBOT_CLIENT_SECRET,
|
||||
COBOT_SCOPE,
|
||||
COBOT_USER_EMAIL,
|
||||
COBOT_USER_PASSWORD,
|
||||
} = require('../constants')
|
||||
|
||||
class Cobot {
|
||||
constructor(token) {
|
||||
this.token = token
|
||||
}
|
||||
|
||||
cards() {
|
||||
if (!COBOT_CARDS_API)
|
||||
throw new Error('missing "COBOT_CARDS_API" env variable!')
|
||||
return axios
|
||||
.get(COBOT_CARDS_API, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${this.token}`,
|
||||
},
|
||||
})
|
||||
.then(resp =>
|
||||
resp.data.map(card => ({
|
||||
name: card.membership.name,
|
||||
number: card.token,
|
||||
}))
|
||||
)
|
||||
}
|
||||
|
||||
static authorize() {
|
||||
if (!COBOT_SCOPE) throw new Error('missing "COBOT_SCOPE" env variable!')
|
||||
if (!COBOT_USER_EMAIL)
|
||||
throw new Error('missing "COBOT_USER_EMAIL" env variable!')
|
||||
if (!COBOT_USER_PASSWORD)
|
||||
throw new Error('missing "COBOT_USER_PASSWORD" env variable!')
|
||||
if (!COBOT_CLIENT_ID)
|
||||
throw new Error('missing "COBOT_CLIENT_ID" env variable!')
|
||||
if (!COBOT_CLIENT_SECRET)
|
||||
throw new Error('missing "COBOT_CLIENT_SECRET" env variable!')
|
||||
const qs = [
|
||||
`scope=${COBOT_SCOPE}`,
|
||||
`grant_type=password`,
|
||||
`username=${COBOT_USER_EMAIL}`,
|
||||
`password=${COBOT_USER_PASSWORD}`,
|
||||
`client_id=${COBOT_CLIENT_ID}`,
|
||||
`client_secret=${COBOT_CLIENT_SECRET}`,
|
||||
].join('&')
|
||||
return axios
|
||||
.post(`https://www.cobot.me/oauth/access_token?${qs}`)
|
||||
.then(resp => new Cobot(resp.data.access_token))
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Cobot
|
||||
@@ -1,41 +0,0 @@
|
||||
const axios = require('axios')
|
||||
const Cobot = require('./cobot')
|
||||
|
||||
jest.mock('axios')
|
||||
|
||||
describe('models/cobot', () => {
|
||||
describe('.authorize', () => {
|
||||
test('should fetch a new token', () => {
|
||||
const resp = { data: { access_token: 'meow' } }
|
||||
jest.spyOn(axios, 'post').mockResolvedValue(resp)
|
||||
return Cobot.authorize().then(cobot => {
|
||||
expect(axios.post).toBeCalled()
|
||||
expect(cobot).toBeInstanceOf(Cobot)
|
||||
expect(cobot.token).toBe('meow')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('.cards', () => {
|
||||
test('returns a structured list of cards', () => {
|
||||
const resp = {
|
||||
data: [
|
||||
{ membership: { id: 'foo', name: 'John' }, token: '001' },
|
||||
{ membership: { id: 'bar', name: 'Jane' }, token: '002' },
|
||||
],
|
||||
}
|
||||
const expected = [
|
||||
{ name: 'John', number: '001' },
|
||||
{ name: 'Jane', number: '002' },
|
||||
]
|
||||
jest.spyOn(axios, 'get').mockResolvedValue(resp)
|
||||
|
||||
// TODO: why doesnt this work? It should...
|
||||
// axios.get.mockResolvedValue(resp)
|
||||
|
||||
return new Cobot('fake-value')
|
||||
.cards()
|
||||
.then(actual => expect(actual).toEqual(expected))
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,11 +0,0 @@
|
||||
class Display {
|
||||
static successMessage(msg) {
|
||||
console.log('SUCCESS', msg)
|
||||
}
|
||||
|
||||
static failureMessage(msg) {
|
||||
console.log('FAILURE', msg)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Display
|
||||
@@ -1,27 +0,0 @@
|
||||
const { DOOR_OPEN_DELAY } = require('../constants')
|
||||
const logger = require('../utils/logger')
|
||||
const tessel = require('tessel')
|
||||
|
||||
class Door {
|
||||
static open() {
|
||||
logger.log('OPEN DOOR')
|
||||
|
||||
// TODO: trigger door opening...
|
||||
tessel.led[3].on()
|
||||
|
||||
return new Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
// TODO: trigger door closing
|
||||
Door.close()
|
||||
resolve()
|
||||
}, DOOR_OPEN_DELAY)
|
||||
})
|
||||
}
|
||||
|
||||
static close() {
|
||||
logger.log('CLOSE DOOR')
|
||||
tessel.led[3].off()
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Door
|
||||
@@ -1,23 +0,0 @@
|
||||
const Door = require('./door')
|
||||
const tessel = require('tessel')
|
||||
|
||||
jest.mock('tessel')
|
||||
|
||||
describe('models/door', () => {
|
||||
describe('.open', () => {
|
||||
test('opens door', () => {
|
||||
jest.spyOn(Door, 'close')
|
||||
return Door.open().then(() => {
|
||||
expect(tessel.led[3].on).toBeCalled()
|
||||
expect(Door.close).toBeCalled()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('.close', () => {
|
||||
test('closes door', () => {
|
||||
Door.close()
|
||||
expect(tessel.led[3].off).toBeCalled()
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,28 +0,0 @@
|
||||
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
|
||||
@@ -1,42 +0,0 @@
|
||||
const hid = require('node-hid')
|
||||
const { RFID_PRODUCT_NAME } = require('../constants')
|
||||
|
||||
class RFIDReader {
|
||||
static devices() {
|
||||
return hid.devices() || []
|
||||
}
|
||||
|
||||
static reader() {
|
||||
const device = this.devices().find(d => d.product === RFID_PRODUCT_NAME)
|
||||
|
||||
if (!device) {
|
||||
throw new Error(
|
||||
`no RFID device found with the "RFID_PRODUCT_NAME" matching "${RFID_PRODUCT_NAME}"`
|
||||
)
|
||||
}
|
||||
|
||||
return new hid.HID(device.path)
|
||||
}
|
||||
|
||||
static read() {
|
||||
const device = this.reader()
|
||||
device.read((err, data) => console.log(err, data))
|
||||
return device
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
@@ -1,47 +0,0 @@
|
||||
const hid = require('node-hid')
|
||||
const RFIDReader = require('./rfid-reader')
|
||||
|
||||
jest.mock('node-hid')
|
||||
|
||||
const rfidDevice = {
|
||||
interface: -1,
|
||||
manufacturer: 'Apple',
|
||||
path:
|
||||
'IOService:/IOResources/IOBluetoothHCIController/AppleBroadcomBluetoothHostController/IOBluetoothDevice/IOBluetoothL2CAPChannel/AppleHSBluetoothDevice/Keyboard / Boot@1/AppleHSBluetoothHIDDriver',
|
||||
product: 'KB800HM Kinesis Freestyle2 for Mac',
|
||||
productId: 615,
|
||||
release: 0,
|
||||
serialNumber: '04-69-f8-c6-d2-c2',
|
||||
usage: 6,
|
||||
usagePage: 1,
|
||||
vendorId: 76,
|
||||
}
|
||||
|
||||
describe('models/rfid-reader', () => {
|
||||
const devices = [rfidDevice]
|
||||
|
||||
beforeAll(() => {
|
||||
hid.devices.mockReturnValue(devices)
|
||||
})
|
||||
|
||||
describe('.devices', () => {
|
||||
test('lists devices', () => {
|
||||
const actual = RFIDReader.devices()
|
||||
expect(actual).toEqual(devices)
|
||||
})
|
||||
})
|
||||
|
||||
describe('.reader', () => {
|
||||
test('should connect to the RFID reader and return it', () => {
|
||||
const actual = RFIDReader.reader()
|
||||
expect(actual).toBeInstanceOf(hid.HID)
|
||||
})
|
||||
})
|
||||
|
||||
describe('.read', () => {
|
||||
test('it should listen for keyboard input', () => {
|
||||
const device = RFIDReader.read()
|
||||
expect(device.read).toBeCalled()
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,27 +0,0 @@
|
||||
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
|
||||
@@ -1,31 +0,0 @@
|
||||
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()
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,9 +0,0 @@
|
||||
const { ENV } = require('../constants')
|
||||
|
||||
class Logger {
|
||||
log() {
|
||||
ENV !== 'test' && console.log(...arguments)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new Logger()
|
||||
Reference in New Issue
Block a user