Start project with blootstrap (pre publishing)

This commit is contained in:
mmcwilliams 2017-08-21 21:11:07 -04:00
commit 3f9e2853b0
11 changed files with 430 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
node_modules

2
Readme.md Normal file
View File

@ -0,0 +1,2 @@
# intval3

45
index.js Normal file
View File

@ -0,0 +1,45 @@
'use strict'
const ble = require('./lib/blootstrap')
const express = require('express')
const app = express()
const gpio = require('gpio')
const gpio4 = gpio.export(4, {
direction: 'out',
interval: 100,
ready : () => {
}
})
const PORT = process.env.PORT || 6699
const APPNAME = 'my_project'
function blink (req, res, next) {
console.log('Blinking!')
gpio4.set(1)
setTimeout(() => {
gpio4.set(0)
res.send('<h1>You blinked!</h1>')
next()
}, 1000)
}
function index (req, res, next) {
res.send(
`<h1>Welcome to my app!</h1>
<form action="/blink" method="post">
<input type="submit" value="Blink!" />
</form>`)
next()
}
ble.on('data', (str) => {
console.log(str)
blink()
})
app.get('/', index)
app.all('/blink', blink)
app.listen(PORT, () => {
console.log(`${APPNAME} listening on port ${PORT}!`)
})

32
lib/blootstrap/index.js Normal file
View File

@ -0,0 +1,32 @@
'use strict'
const ipc = require('node-ipc')
function capitalize (s) {
return s[0].toUpperCase() + s.slice(1)
}
class Blootstrap {
constructor () {
this._onData = () => {}
ipc.connectTo('blootstrap_ble', () => {
ipc.of.blootstrap_ble.on('connect', () => {
ipc.log(`Connected to the blootstrap_ble service`)
})
ipc.of.blootstrap_ble.on('data', data => {
const str = data.toString()
ipc.log(str)
this._onData(str)
})
ipc.of.blootstrap_ble.on('disconnect', () => {
ipc.log(`Disconnected from the blootstrap_ble service`)
})
})
}
on (eventName, callback) {
this[`_on${capitalize(eventName)}`] = callback
}
}
module.exports = new Blootstrap()

90
lib/wifi/index.js Normal file
View File

@ -0,0 +1,90 @@
'use strict'
const networkPattern = /network[\s\S]*?=[\s\S]*?{([\s\S]*?)}/gi
const quoteRe = new RegExp('"', 'g')
const filePath = '/etc/wpa_supplicant/wpa_supplicant.conf'
const reconfigure = '/sbin/wpa_cli reconfigure'
const refresh = '/sbin/ifdown wlan0 && /sbin/ifup --force wlan0'
const iwlist = '/sbin/iwlist wlan0 scanning | grep "ESSID:"'
const iwgetid = '/sbin/iwgetid'
const exec = require('child_process').exec
const fs = require('fs')
class wifi {
constructor () {
this._callback = () => {}
this._entry = null
}
list (callback) {
exec(iwlist, (err, stdout, stderr) => {
if (err) {
console.error(err)
return callback(err)
}
const lines = stdout.split('\n')
const output = []
let line
for (let l of lines) {
line = l.replace('ESSID:', '').trim()
if (line != '""') {
line = line.replace(quoteRe, '')
output.push(line)
}
}
return callback(null, output)
})
}
_readConfigCb (err, data) {
if (err) {
console.error(err)
return this._callback(err)
}
if (data.search(networkPattern) === -1) {
data += `\n${this._entry}`
} else {
data = data.replace(networkPattern, entry)
}
fs.writeFile(filePath, data, 'utf8', this._writeConfigCb)
}
_writeConfigCb (err) {
if (err) {
console.error(err)
return this._callback(err)
}
exec(reconfigure, this._reconfigureCb)
}
_reconfigureCb (err, stdout, stderr) {
if (err) {
console.error(err)
return this._callback(err)
}
console.log('Wifi reconfigured')
exec(refresh, this._refreshCb)
}
_refreshCb (err, stdout, stderr) {
if (err) {
console.error(err)
return this._callback(err)
}
console.log('Wifi refreshed')
this._callback(null, { ssid : ssid, pwd : pwd.length })
this._callback = () => {}
}
setNetwork (ssid, pwd, callback) {
this._entry = `network={\n\tssid="${ssid}"\n\tpsk="${pwd}"\n}\n`
this._callback = callback
fs.readFile(filePath, 'utf8', this._readConfigCb)
}
getNetwork (callback) {
exec(iwgetid, (err, stdout, stderr) => {
if (err) {
return callback(err)
}
callback(null, stdout)
})
}
}
module.exports = new wifi()

47
nginx.conf Normal file
View File

@ -0,0 +1,47 @@
#blootstrap nginx conf
#uncomment and modify following files for ssl
#server {
#listen 80;
#server_name my_project;
#return 301 https://$server_name$request_uri;
#}
server {
listen 80;
#listen 443 ssl;
#ssl on;
#ssl_certificate {{SSL_CERT_PATH}};
#ssl_certificate_key {{SSL_KEY_PATH}};
#ssl_session_timeout 5m;
#ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
#ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
#ssl_prefer_server_ciphers on;
#server_name my_project;
location / {
proxy_pass http://127.0.0.1:6699/;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
gzip on;
gzip_comp_level 9;
gzip_types text/plain text/html text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript application/json;
}
#uncomment for static file servers
#location /static/ {
#uncomment to turn on caching
#expires modified 1y;
#access_log off;
#add_header Cache-Control "public";
#gzip on;
#gzip_comp_level 9;
#gzip_types text/plain text/html text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript application/json;
#alias /var/node/blootstrap/static/;
#}
}

32
package.json Normal file
View File

@ -0,0 +1,32 @@
{
"name": "intval3",
"version": "0.0.1",
"description": "Intervalometer for the Bolex",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/sixteenmillimeter/intval3.git"
},
"jshintConfig": {
"esversion": 6,
"strict": "global",
"node": true,
"asi": true
},
"author": "sixteenmillimeter",
"license": "MIT",
"bugs": {
"url": "https://github.com/sixteenmillimeter/intval3/issues"
},
"homepage": "https://github.com/sixteenmillimeter/intval3#readme",
"dependencies": {
"bleno": "^0.4.2",
"gpio": "^0.2.7",
"node-ipc": "^9.1.0",
"restify": "^5.2.0",
"uuid": "^3.1.0"
}
}

12
process.json Normal file
View File

@ -0,0 +1,12 @@
{
"apps" : [
{
"name" : "ble",
"script" : "./services/bluetooth/index.js",
"watch" : false,
"env" : {
"BLENO_DEVICE_NAME" : "intval3"
}
}
]
}

View File

@ -0,0 +1,17 @@
#!/bin/bash
echo "Running blootstrap install script"
apt-get update
apt-get install git ufw nginx -y
echo "Installing node.js dependencies.."
apt-get install nodejs npm -y
npm install -g n
n latest
npm install -g npm@latest
npm install -g pm2
echo "Installing bluetooth dependencies..."
apt-get install bluetooth bluez libbluetooth-dev libudev-dev -y
echo "Finished installing blootstrap dependencies"

View File

@ -0,0 +1,36 @@
#!/bin/bash
echo "Running blootstrap install script"
apt-get update
apt-get install git ufw nginx -y
echo "Installing node.js dependencies.."
apt-get install nodejs npm -y
npm install -g n
n latest
npm install -g npm@latest
npm install -g pm2
echo "Installing bluetooth dependencies..."
apt-get install bluetooth bluez libbluetooth-dev libudev-dev -y
echo "Configuring ufw (firewall)..."
ufw default deny incoming
ufw default allow outgoing
ufw allow ssh
ufw allow http
ufw allow https
ufw enable
echo "Installing blootstrap project..."
mkdir /var/node
cd /var/node
wget https://github.com/mattmcw/blootstrap/archive/master.zip
unzip master.zip -d blootstrap/
rm master.zip
cd blootstrap
npm install
pm2 start process.json
echo "Finished installing blootstrap"

116
services/bluetooth/index.js Normal file
View File

@ -0,0 +1,116 @@
'use strict'
const ipc = require('node-ipc')
const bleno = require('bleno')
const util = require('util')
const wifi = require('../../lib/wifi')
const BLENO_DEVICE_NAME = process.env.BLENO_DEVICE_NAME || 'my_project'
const DEVICE_ID = process.env.DEVICE_ID || 'my_project_id'
const SERVICE_ID = process.env.SERVICE_ID || 'blootstrap'
const CHAR_ID = process.env.CHAR_ID || 'blootstrapwifi'
const chars = []
ipc.config.id = 'blootstrap_ble'
ipc.config.retry = 1500
ipc.config.rawBuffer = true
ipc.config.encoding = 'hex'
function createChar(name, uuid, prop, write, read) {
function characteristic () {
bleno.Characteristic.call(this, {
uuid : uuid,
properties: prop
})
}
util.inherits(characteristic, bleno.Characteristic)
if (prop.indexOf('read')) {
//data, offset, withoutResponse, callback
characteristic.prototype.onReadRequest = read
}
if (prop.indexOf('write')) {
characteristic.prototype.onWriteRequest = write
}
char.push(new characteristic())
}
function onWifiWrite (data, offset, withoutResponse, callback) {
let result
let utf8
let obj
let ssid
let pwd
if (offset) {
console.warn(`Offset scenario`)
result = bleno.Characteristic.RESULT_ATTR_NOT_LONG
return callback(result)
}
utf8 = data.toString('utf8')
obj = JSON.parse(utf8)
ssid = obj.ssid
pwd = obj.pwd
console.log(`Connecting to AP: ${ssid}...`)
return wifi.setNetwork(ssid, pwd, (err, data) => {
if (err) {
console.error('Error configuring wifi', err)
result = bleno.Characteristic.RESULT_UNLIKELY_ERROR
return callback(result)
}
console.log(`Connected to ${ssid}`)
result = bleno.Characteristic.RESULT_SUCCESS
return callback(result)
})
}
function onWifiRead (offset, callback) {
const result = bleno.Characteristic.RESULT_SUCCESS
callback(result, data.slice(offset, data.length))
}
console.log('Starting bluetooth service')
bleno.on('stateChange', state => {
console.log('on -> stateChange: ' + state)
if (state === 'poweredOn') {
console.log('Started advertising blootstrap services')
bleno.startAdvertising(BLENO_DEVICE_NAME, [DEVICE_ID])
} else {
bleno.stopAdvertising()
}
})
bleno.on('advertisingStart', err => {
console.log('on -> advertisingStart: ' + (err ? 'error ' + err : 'success'))
if (!err) {
bleno.setServices([
new bleno.PrimaryService({
uuid : SERVICE_ID, //hardcoded across panels
characteristics : chars
})
])
}
})
bleno.on('accept', clientAddress => {
console.log(`${clientAddress} accepted`)
})
bleno.on('disconnect', clientAddress => {
console.log(`${clientAddress} disconnected`)
})
ipc.serve(() => {
ipc.server.on('connect', socket => {
ipc.log('Client connected to socket')
})
ipc.server.on('disconnect', () => {
ipc.log('Client disconnected from socket')
})
ipc.server.on('data', (data, socket) => {
ipc.server.emit(socket, JSON.stringify({}))
})
})
ipc.server.start()