mirror of
https://github.com/zyphlar/doorlock.git
synced 2024-04-03 21:36:03 +00:00
A happy beginning 🚪🔒
This commit is contained in:
@@ -0,0 +1,13 @@
|
|||||||
|
# http://editorconfig.org
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
charset = utf-8
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
indent_size = 4
|
||||||
|
trim_trailing_whitespace = false
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
dist
|
||||||
|
node_modules
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
---
|
||||||
|
parser: babel-eslint
|
||||||
|
parserOptions:
|
||||||
|
ecmaVersion: 6
|
||||||
|
sourceType: module
|
||||||
|
ecmaFeatures:
|
||||||
|
jsx: true
|
||||||
|
impliedStrict: true
|
||||||
|
experimentalObjectRestSpread: true
|
||||||
|
globals:
|
||||||
|
Promise: true
|
||||||
|
env:
|
||||||
|
browser: true
|
||||||
|
jest: true
|
||||||
|
node: true
|
||||||
|
commonjs: true
|
||||||
|
extends:
|
||||||
|
- eslint:recommended
|
||||||
|
- plugin:react/recommended
|
||||||
|
rules:
|
||||||
|
no-empty: warn
|
||||||
|
no-console: off
|
||||||
|
semi:
|
||||||
|
- error
|
||||||
|
- never
|
||||||
|
sort-vars: error
|
||||||
|
sort-imports:
|
||||||
|
- error
|
||||||
|
- ignoreCase: true
|
||||||
|
sort-keys: error
|
||||||
|
react/jsx-sort-prop: true
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
|
||||||
|
node_modules
|
||||||
|
.DS_Store
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
# This file is a special npm configuration file.
|
||||||
|
#
|
||||||
|
# From npm docs:
|
||||||
|
#
|
||||||
|
# The --global-style argument will cause
|
||||||
|
# npm to install the package into your
|
||||||
|
# local node_modules folder with the same
|
||||||
|
# layout it uses with the global node_modules
|
||||||
|
# folder. Only your direct dependencies
|
||||||
|
# will show in node_modules and everything
|
||||||
|
# they depend on will be flattened in their
|
||||||
|
# node_modules folders. This obviously will
|
||||||
|
# eliminate some deduping.
|
||||||
|
#
|
||||||
|
# t2-cli gives third party modules control over what
|
||||||
|
# files and dependencies get deployed to a Tessel 2
|
||||||
|
# by supporting .tesselignore and .tesselinclude files.
|
||||||
|
# Ever since npm 3, dependency flattening has taken that
|
||||||
|
# control away, since the rules in those files are
|
||||||
|
# resolved relative to the third party module itself.
|
||||||
|
# Forcing Tessel 2 project dependencies to install as
|
||||||
|
# described above restores that control, ideally
|
||||||
|
# producing smaller project bundles.
|
||||||
|
|
||||||
|
global-style = true
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
.vscode
|
||||||
|
dist
|
||||||
|
node_modules
|
||||||
|
package-lock.json
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"semi": false,
|
||||||
|
"singleQuote": true,
|
||||||
|
"trailingComma": "es5"
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
# This file should list any files or directories you want included with the
|
||||||
|
# T2 bundling and deployment process. This is handy for including
|
||||||
|
# non-JavaScript assets, like HTML, CSS, and images, for use within your project.
|
||||||
|
# .tesselinclude works the same as .npminclude
|
||||||
|
# You DO NOT need to list node_modules or package.json
|
||||||
|
# For more information, visit: https://tessel.io/docs/cli#usage
|
||||||
|
index.html
|
||||||
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"git.ignoreLimitWarning": true
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
function LED() {
|
||||||
|
return {
|
||||||
|
off: jest.fn(),
|
||||||
|
on: jest.fn(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const tessel = {
|
||||||
|
led: {
|
||||||
|
0: LED(), // red
|
||||||
|
1: LED(), // amber
|
||||||
|
2: LED(), // green
|
||||||
|
3: LED(), // blue
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = tessel
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
const ENV = process.env.NODE_ENV || 'development'
|
||||||
|
const DOOR_OPEN_DELAY = ENV === 'test' ? 1 : 6000 // in milliseconds
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
DOOR_OPEN_DELAY,
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
module.exports = {
|
||||||
|
moduleFileExtensions: ['ts', 'tsx', 'js'],
|
||||||
|
testEnvironment: 'node',
|
||||||
|
testMatch: ['**/*.test.(ts|tsx|js)'],
|
||||||
|
testPathIgnorePatterns: ['/node_modules/', '/config/'],
|
||||||
|
}
|
||||||
Generated
+5649
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"name": "doorlock",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"main": "src/boot.js",
|
||||||
|
"scripts": {
|
||||||
|
"start": "t2 run src/boot.js",
|
||||||
|
"test": "jest",
|
||||||
|
"watch-test": "jest --watch"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"axios": "0.17.1",
|
||||||
|
"chalk": "2.3.1",
|
||||||
|
"consolidate": "0.15.0",
|
||||||
|
"eslint": "4.17.0",
|
||||||
|
"express": "4.16.2",
|
||||||
|
"node-hid": "0.7.2",
|
||||||
|
"pug": "2.0.0-rc.4",
|
||||||
|
"serialport": "6.0.5",
|
||||||
|
"tessel": "0.3.25"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"babel-eslint": "8.2.2",
|
||||||
|
"eslint-plugin-react": "7.7.0",
|
||||||
|
"jest": "22.4.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
# Chimera Doorlock
|
||||||
|
|
||||||
|
Powered by a [Tessel][tessel]
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
Follow the [start guide][start] on [Tessel.io][tessel].
|
||||||
|
|
||||||
|
Install `t2-cli` globally:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install -g t2-cli
|
||||||
|
```
|
||||||
|
|
||||||
|
Now install the correct version of node using nvm:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nvm install
|
||||||
|
nvm use
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
Now you can deploy to your connected Tessel device:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm start
|
||||||
|
```
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
|
||||||
|
We use [Jest][jest] to do testing of the core code in the library. Make sure to write tests for new code or update tests on existing code as needed. Test files are next to their source file named with a `.test.js` extension.
|
||||||
|
|
||||||
|
Run tests once: `npm test`
|
||||||
|
|
||||||
|
Run tests watching for changes: `npm run watch-test`
|
||||||
|
|
||||||
|
### RFID Cards
|
||||||
|
|
||||||
|
Read cards from Cobot:
|
||||||
|
|
||||||
|
<https://www.cobot.me/api-docs/check-ins#list-check-in-tokens>
|
||||||
|
|
||||||
|
### Useful Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Connect to WiFi
|
||||||
|
t2 wifi -n network-name -p "some password"
|
||||||
|
|
||||||
|
# List devices
|
||||||
|
t2 list
|
||||||
|
|
||||||
|
# Update Tessel
|
||||||
|
t2 update
|
||||||
|
|
||||||
|
# Deploy code
|
||||||
|
t2 push index.js
|
||||||
|
|
||||||
|
# Clear code
|
||||||
|
t2 erase
|
||||||
|
|
||||||
|
# Create access point and server
|
||||||
|
t2 ap -n doorlock
|
||||||
|
```
|
||||||
|
|
||||||
|
### USB Storage
|
||||||
|
|
||||||
|
* Make sure to format USB to be FAT32!
|
||||||
|
|
||||||
|
[start]: http://tessel.github.io/t2-start
|
||||||
|
[tessel]: http://tessel.io
|
||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
const Door = require('./models/door')
|
||||||
|
|
||||||
|
Door.open()
|
||||||
|
|
||||||
|
// 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())
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
class AccessLog {
|
||||||
|
static log(member) {
|
||||||
|
console.log('LOGGING', member)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = AccessLog
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
class Display {
|
||||||
|
static successMessage(msg) {
|
||||||
|
console.log('SUCCESS', msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
static failureMessage(msg) {
|
||||||
|
console.log('FAILURE', msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Display
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
const tessel = require('tessel')
|
||||||
|
const constants = require('../../config/constants')
|
||||||
|
// 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() {
|
||||||
|
// TODO: trigger door opening...
|
||||||
|
tessel.led[2].on()
|
||||||
|
|
||||||
|
return new Promise(resolve => {
|
||||||
|
setTimeout(() => {
|
||||||
|
// TODO: trigger door closing
|
||||||
|
Door.close()
|
||||||
|
resolve()
|
||||||
|
}, constants.DOOR_OPEN_DELAY)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
static close() {
|
||||||
|
console.log('CLOSE DOOR')
|
||||||
|
tessel.led[2].off()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
const Door = require('./door')
|
||||||
|
const tessel = require('tessel')
|
||||||
|
|
||||||
|
jest.mock('tessel')
|
||||||
|
|
||||||
|
describe('models/door', () => {
|
||||||
|
describe('.open', () => {
|
||||||
|
test('opens door', () => {
|
||||||
|
jest.spyOn(Door, 'close')
|
||||||
|
// Door.close = jest.fn()
|
||||||
|
return Door.open().then(() => {
|
||||||
|
expect(tessel.led[2].on).toBeCalled()
|
||||||
|
expect(Door.close).toBeCalled()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('.close', () => {
|
||||||
|
test('closes door', () => {
|
||||||
|
Door.close()
|
||||||
|
expect(tessel.led[2].off).toBeCalled()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user