mirror of
https://github.com/zyphlar/doorlock.git
synced 2024-04-03 21:36:03 +00:00
Changes to get working on tessel
This commit is contained in:
parent
b3eda3a674
commit
8c83229696
|
@ -1,6 +1,6 @@
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
|
|
||||||
require('dotenv').config({ path: path.join(__dirname, '..', '.env') })
|
require('dotenv').config({ path: path.join(__dirname, '.env') })
|
||||||
|
|
||||||
const ENV = process.env.NODE_ENV || 'development'
|
const ENV = process.env.NODE_ENV || 'development'
|
||||||
const USB_MOUNT_PATH = process.env.USB_MOUNT_PATH || '/mnt/sda1'
|
const USB_MOUNT_PATH = process.env.USB_MOUNT_PATH || '/mnt/sda1'
|
||||||
|
|
182
doorlock.js
182
doorlock.js
|
@ -1,27 +1,170 @@
|
||||||
const chalk = require('chalk')
|
'use strict'
|
||||||
const Cobot = require('./cobot')
|
|
||||||
|
// const axios = require('axios')
|
||||||
|
const https = require('https')
|
||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
const SerialPort = require('serialport')
|
const SerialPort = require('serialport')
|
||||||
const tessel = require('tessel')
|
const tessel = require('tessel')
|
||||||
const {
|
const {
|
||||||
CARD_UPDATE_INTERVAL,
|
CARD_UPDATE_INTERVAL,
|
||||||
CARDS_PATH,
|
CARDS_PATH,
|
||||||
|
COBOT_CARDS_API,
|
||||||
|
COBOT_CLIENT_ID,
|
||||||
|
COBOT_CLIENT_SECRET,
|
||||||
|
COBOT_SCOPE,
|
||||||
|
COBOT_USER_EMAIL,
|
||||||
|
COBOT_USER_PASSWORD,
|
||||||
DOOR_OPEN_DELAY,
|
DOOR_OPEN_DELAY,
|
||||||
|
ENV,
|
||||||
RFID_READER_SERIAL_NUMBER,
|
RFID_READER_SERIAL_NUMBER,
|
||||||
} = require('./constants')
|
} = require('./constants')
|
||||||
|
|
||||||
const TEST = process.env.NODE_ENV === 'test'
|
const TEST = ENV === 'test'
|
||||||
|
|
||||||
|
class Cobot {
|
||||||
|
constructor(token) {
|
||||||
|
this.token = token
|
||||||
|
}
|
||||||
|
|
||||||
|
cards() {
|
||||||
|
if (!COBOT_CARDS_API)
|
||||||
|
throw new Error('missing "COBOT_CARDS_API" env variable!')
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const req = https.request(
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${this.token}`,
|
||||||
|
},
|
||||||
|
hostname: 'chimera.cobot.me',
|
||||||
|
method: 'GET',
|
||||||
|
path: '/api/check_in_tokens',
|
||||||
|
},
|
||||||
|
res => {
|
||||||
|
const { statusCode, headers } = res
|
||||||
|
console.log('\n----------------------------------------------------')
|
||||||
|
console.log('COBOT CARDS RESPONSE:')
|
||||||
|
console.log(JSON.stringify({ statusCode, headers }, null, 2))
|
||||||
|
res.setEncoding('utf8')
|
||||||
|
|
||||||
|
let cards = ''
|
||||||
|
res.on('data', chunk => {
|
||||||
|
cards += chunk
|
||||||
|
})
|
||||||
|
|
||||||
|
res.on('end', () => {
|
||||||
|
cards = JSON.parse(cards)
|
||||||
|
console.log(JSON.stringify(cards, null, 2))
|
||||||
|
if (!cards || !cards.length) {
|
||||||
|
throw new Error('No cards received from API!')
|
||||||
|
}
|
||||||
|
resolve(
|
||||||
|
cards.map(card => ({
|
||||||
|
name: card.membership.name,
|
||||||
|
number: card.token,
|
||||||
|
}))
|
||||||
|
)
|
||||||
|
console.log(
|
||||||
|
'----------------------------------------------------\n'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
req.on('data', console.log)
|
||||||
|
req.on('error', e => {
|
||||||
|
console.error(e)
|
||||||
|
reject(e)
|
||||||
|
})
|
||||||
|
req.end()
|
||||||
|
})
|
||||||
|
// 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() {
|
||||||
|
console.log('Authorizing Cobot application...')
|
||||||
|
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=${encodeURI(COBOT_USER_PASSWORD)}`,
|
||||||
|
`client_id=${COBOT_CLIENT_ID}`,
|
||||||
|
`client_secret=${COBOT_CLIENT_SECRET}`,
|
||||||
|
].join('&')
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const req = https.request(
|
||||||
|
{
|
||||||
|
hostname: 'www.cobot.me',
|
||||||
|
method: 'POST',
|
||||||
|
path: `/oauth/access_token?${qs}`,
|
||||||
|
},
|
||||||
|
res => {
|
||||||
|
const { statusCode, headers } = res
|
||||||
|
console.log('\n----------------------------------------------------')
|
||||||
|
console.log('COBOT AUTHORIZATION RESPONSE:')
|
||||||
|
console.log(JSON.stringify({ statusCode, headers }, null, 2))
|
||||||
|
|
||||||
|
res.setEncoding('utf8')
|
||||||
|
|
||||||
|
let cobot
|
||||||
|
res.on('data', chunk => {
|
||||||
|
const body = JSON.parse(chunk)
|
||||||
|
console.log(JSON.stringify({ body }, null, 2))
|
||||||
|
const token = body.access_token
|
||||||
|
if (!token) {
|
||||||
|
console.error(`Expected access token, got: ${body}`)
|
||||||
|
throw new Error('Error getting access token')
|
||||||
|
}
|
||||||
|
cobot = new Cobot(token)
|
||||||
|
})
|
||||||
|
|
||||||
|
res.on('end', () => {
|
||||||
|
resolve(cobot)
|
||||||
|
console.log(
|
||||||
|
'----------------------------------------------------\n'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
req.on('error', e => reject(e))
|
||||||
|
req.end()
|
||||||
|
})
|
||||||
|
// return axios
|
||||||
|
// .post(`https://www.cobot.me/oauth/access_token?${qs}`)
|
||||||
|
// .then(resp => new Cobot(resp.data.access_token))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class DoorLock {
|
class DoorLock {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.log(chalk.gray('Initializing doorlock'))
|
this.log('Initializing doorlock')
|
||||||
|
|
||||||
if (!RFID_READER_SERIAL_NUMBER) {
|
if (!RFID_READER_SERIAL_NUMBER) {
|
||||||
throw new Error('No serial number set!')
|
throw new Error('No serial number set!')
|
||||||
}
|
}
|
||||||
|
|
||||||
this.cards = []
|
this.cards = []
|
||||||
// this.fetchCardListFromCobot()
|
this.fetchCardListFromCobot()
|
||||||
this.initializeRFIDReader()
|
this.initializeRFIDReader()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,8 +180,8 @@ class DoorLock {
|
||||||
|
|
||||||
getListOfSerialDevices() {
|
getListOfSerialDevices() {
|
||||||
return (SerialPort.list() || Promise.resolve([])).then(devices => {
|
return (SerialPort.list() || Promise.resolve([])).then(devices => {
|
||||||
this.log(chalk.green('Available serial devices:'))
|
this.log('Available serial devices:')
|
||||||
this.log(chalk.gray(JSON.stringify(devices.map(d => d.comName), null, 2)))
|
this.log(JSON.stringify(devices.map(d => d.comName), null, 2))
|
||||||
return devices
|
return devices
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -56,7 +199,7 @@ class DoorLock {
|
||||||
}
|
}
|
||||||
|
|
||||||
connectToRFIDReaderDevice(port) {
|
connectToRFIDReaderDevice(port) {
|
||||||
this.log(chalk.green('Connected to device:'), chalk.gray(port))
|
this.log('Connected to device:', port)
|
||||||
const device = new SerialPort(port, { baudRate: 9600 })
|
const device = new SerialPort(port, { baudRate: 9600 })
|
||||||
const Readline = SerialPort.parsers.Readline
|
const Readline = SerialPort.parsers.Readline
|
||||||
const parser = new Readline()
|
const parser = new Readline()
|
||||||
|
@ -76,24 +219,24 @@ class DoorLock {
|
||||||
16
|
16
|
||||||
)
|
)
|
||||||
|
|
||||||
this.log(chalk.green('Scanned card:'), chalk.gray(scanned))
|
this.log('Scanned card:', scanned)
|
||||||
|
|
||||||
return this.readCardsFromSDCard().then(cards => {
|
return this.readCardsFromSDCard().then(cards => {
|
||||||
const card = cards.find(c => parseInt(c.number) === scanned)
|
const card = cards.find(c => parseInt(c.number) === scanned)
|
||||||
|
|
||||||
if (card) {
|
if (card) {
|
||||||
const name = card.name.split(' ')[0]
|
const name = card.name.split(' ')[0]
|
||||||
this.log(chalk.green(`Welcome in ${name}!`), chalk.gray(scanned))
|
this.log(`Welcome in ${name}!`, scanned)
|
||||||
this.openDoor()
|
this.openDoor()
|
||||||
} else {
|
} else {
|
||||||
this.log(chalk.red('Card is invalid:'), chalk.gray(scanned))
|
this.log('Card is invalid:', scanned)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
openDoor() {
|
openDoor() {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
this.log(chalk.green('Opening door!'))
|
this.log('Opening door!')
|
||||||
|
|
||||||
// TODO: trigger door opening...
|
// TODO: trigger door opening...
|
||||||
if (tessel.led) tessel.led[3].on()
|
if (tessel.led) tessel.led[3].on()
|
||||||
|
@ -107,27 +250,25 @@ class DoorLock {
|
||||||
}
|
}
|
||||||
|
|
||||||
closeDoor() {
|
closeDoor() {
|
||||||
this.log(chalk.green('Closing door!'))
|
this.log('Closing door!')
|
||||||
if (tessel.led) tessel.led[3].off()
|
if (tessel.led) tessel.led[3].off()
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchCardListFromCobot() {
|
fetchCardListFromCobot() {
|
||||||
this.log(chalk.gray('Updating cards...'))
|
this.log('Updating cards...')
|
||||||
Cobot.authorize()
|
Cobot.authorize()
|
||||||
.then(cobot => cobot.cards())
|
.then(cobot => cobot.cards())
|
||||||
.then(cards => {
|
.then(cards => {
|
||||||
this.log(chalk.green('UPDATED CARDS:', cards.length, 'cards'))
|
this.log('UPDATED CARDS:', cards.length, 'cards')
|
||||||
this.writeCardsToSDCard(cards)
|
this.writeCardsToSDCard(cards)
|
||||||
this.cards = cards
|
this.cards = cards
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.log(
|
this.log(
|
||||||
chalk.gray(
|
|
||||||
'Updating card list in',
|
'Updating card list in',
|
||||||
CARD_UPDATE_INTERVAL / 1000,
|
CARD_UPDATE_INTERVAL / 1000,
|
||||||
'seconds...'
|
'seconds...'
|
||||||
)
|
)
|
||||||
)
|
|
||||||
setTimeout(this.fetchCardListFromCobot.bind(this), CARD_UPDATE_INTERVAL)
|
setTimeout(this.fetchCardListFromCobot.bind(this), CARD_UPDATE_INTERVAL)
|
||||||
})
|
})
|
||||||
.catch(this.logErrorMessage)
|
.catch(this.logErrorMessage)
|
||||||
|
@ -137,7 +278,6 @@ class DoorLock {
|
||||||
const sorted = cards.sort(
|
const sorted = cards.sort(
|
||||||
(a, b) => (a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1)
|
(a, b) => (a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1)
|
||||||
)
|
)
|
||||||
this.log(chalk.green('CARDS:'), sorted)
|
|
||||||
return sorted
|
return sorted
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,8 +285,6 @@ class DoorLock {
|
||||||
const json = JSON.stringify(this.sortCardsByName(cards))
|
const json = JSON.stringify(this.sortCardsByName(cards))
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
fs.writeFile(CARDS_PATH, json, err => {
|
fs.writeFile(CARDS_PATH, json, err => {
|
||||||
console.log(json)
|
|
||||||
console.log('JSON', json)
|
|
||||||
if (err) return reject(err)
|
if (err) return reject(err)
|
||||||
resolve()
|
resolve()
|
||||||
})
|
})
|
||||||
|
@ -164,8 +302,8 @@ class DoorLock {
|
||||||
|
|
||||||
logErrorMessage(error) {
|
logErrorMessage(error) {
|
||||||
if (TEST) return
|
if (TEST) return
|
||||||
console.error(chalk.red(error.message))
|
console.error(error.message)
|
||||||
console.error(chalk.gray(error.stack))
|
console.error(error.stack)
|
||||||
process.exit
|
process.exit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
{
|
{
|
||||||
"name": "doorlock",
|
"name": "doorlock",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"main": "src/boot.js",
|
"main": "doorlock.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"deploy": "t2 run src/boot.js",
|
"deploy": "t2 run doorlock.js",
|
||||||
"start": "node src/boot.js",
|
"start": "node doorlock.js",
|
||||||
"test": "jest",
|
"test": "jest",
|
||||||
"watch-test": "npm test -- --watch"
|
"watch-test": "npm test -- --watch"
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue
Block a user