mirror of
https://github.com/zyphlar/doorlock.git
synced 2024-04-03 21:36:03 +00:00
Add start of doorlock server
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
const CARDS_PATH = path.join(process.cwd(), 'cards.json')
|
||||
|
||||
module.exports = class Cards {
|
||||
static all() {
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.readFile(CARDS_PATH, (err, data) => {
|
||||
if (err) return reject(err)
|
||||
resolve(JSON.parse(data))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
static write(cards) {
|
||||
const json = JSON.stringify(this.sortByName(cards))
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.writeFile(CARDS_PATH, json, err => {
|
||||
if (err) return reject(err)
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
static validate(number) {
|
||||
return this.all().then(cards => cards.find(c => c.number === number))
|
||||
// console.log(':', JSON.stringify(number.toString().trim()))
|
||||
// const scanned = parseInt(
|
||||
// number
|
||||
// .toString('hex')
|
||||
// .trim() // Remove any whiespace or newlines
|
||||
// .replace('\u0003', '') // Remove "end of text" character
|
||||
// .replace('\u0002', '') // Remove "start of text" character
|
||||
// .substring(3) // Strip off con
|
||||
// .slice(0, -2), // Strip off checksum
|
||||
// 16
|
||||
// )
|
||||
|
||||
// this.log('Scanned card:', scanned)
|
||||
|
||||
// return this.readCardsFromSDCard().then(cards => {
|
||||
// const card = cards.find(c => parseInt(c.number) === scanned)
|
||||
|
||||
// if (card) {
|
||||
// const name = card.name.split(' ')[0]
|
||||
// this.log(`Welcome in ${name}!`, scanned)
|
||||
// this.openDoor()
|
||||
// } else {
|
||||
// this.log('Card is invalid:', scanned)
|
||||
// }
|
||||
// })
|
||||
}
|
||||
|
||||
static sortByName(cards) {
|
||||
return cards.sort(
|
||||
(a, b) => (a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
const https = require('https')
|
||||
const {
|
||||
CARD_UPDATE_INTERVAL,
|
||||
COBOT_CARDS_API,
|
||||
COBOT_CLIENT_ID,
|
||||
COBOT_CLIENT_SECRET,
|
||||
COBOT_SCOPE,
|
||||
COBOT_USER_EMAIL,
|
||||
COBOT_USER_PASSWORD,
|
||||
} = require('./constants')
|
||||
|
||||
module.exports = 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) => {
|
||||
// TODO move to axios
|
||||
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))
|
||||
}
|
||||
|
||||
static getCards() {
|
||||
this.log('Updating cards...')
|
||||
this.authorize()
|
||||
.then(cobot => cobot.cards())
|
||||
.then(cards => {
|
||||
this.log('UPDATED CARDS:', cards.length, 'cards')
|
||||
this.writeCardsToSDCard(cards)
|
||||
this.cards = cards
|
||||
})
|
||||
.then(() => {
|
||||
this.log(
|
||||
'Updating card list in',
|
||||
CARD_UPDATE_INTERVAL / 1000,
|
||||
'seconds...'
|
||||
)
|
||||
setTimeout(this.fetchCardListFromCobot.bind(this), CARD_UPDATE_INTERVAL)
|
||||
})
|
||||
.catch(this.logErrorMessage)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
module.exports = class Door {
|
||||
static open() {
|
||||
console.log('OPEN')
|
||||
}
|
||||
|
||||
static close() {
|
||||
console.log('CLOSE')
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
module.exports = class Logs {
|
||||
static all() {
|
||||
return Promise.all([
|
||||
{
|
||||
timestamp: 1531256719431,
|
||||
card: { name: 'John Smith', number: '1234023423423' },
|
||||
},
|
||||
{
|
||||
timestamp: 1531256756227,
|
||||
card: { name: 'Jane Doe', number: '2394723984752983' },
|
||||
},
|
||||
])
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user