Skip to content

Commit

Permalink
be more like a library, export some functions
Browse files Browse the repository at this point in the history
  • Loading branch information
chee committed Jul 10, 2017
1 parent 1da1c10 commit 3bfd12f
Showing 1 changed file with 80 additions and 90 deletions.
170 changes: 80 additions & 90 deletions index.js
@@ -1,18 +1,11 @@
const crypto = require('crypto')
const noble = global.noble = require('noble')
let mac = '00:21:4d:03:20:1b'
const name = 'Smart Light'
const password = '234'
let colors = [
0xff,
0xff,
0xff,
0xff
]
let packetCount = Math.random() * 0xffff | 0
packetCount = 1
let light = null
let ch = null
const noble = require('noble')

const nobleReady = new Promise(resolve =>
noble.on('stateChange', state => {
state === 'poweredOn' && resolve()
})
)

const range = to => Array(to).fill().map((_, i) => i)

Expand All @@ -37,20 +30,20 @@ function generateSk (name, password, data1, data2) {
return encrypt(key, data)
}

function keyEncrypt (name, password, data) {
function encryptKey (name, password, data) {
name = Buffer.from(name.padEnd(16, '\u0000'))
password = Buffer.from(password.padEnd(16, '\u0000'))
const key = []
;[].forEach.call(name, (byte, index) => {
key.forEach.call(name, (byte, index) => {
key.push(byte ^ password[index])
})
return encrypt(data, key)
}

// mutate me mor
function encryptPacket (sk, mac, packet) {
let tmp = [mac[0], mac[1], mac[2], mac[3], 0x01, packet[0], packet[1], packet[2], 15, 0, 0, 0, 0, 0, 0, 0]
let tmp = [...mac.slice(0, 4), 0x01, ...packet.slice(0, 3), 15, 0, 0, 0, 0, 0, 0, 0]
tmp = encrypt(sk, tmp)
let i = 0

range(15).forEach(i => {
tmp[i] = tmp[i] ^ packet[i + 5]
Expand All @@ -62,7 +55,7 @@ function encryptPacket (sk, mac, packet) {
packet[i + 3] = tmp[i]
})

tmp = [0, mac[0], mac[1], mac[2], mac[3], 0x01, packet[0], packet[1], packet[2], 0, 0, 0, 0, 0, 0, 0]
tmp = [0, ...mac.slice(0, 4), 0x01, ...packet.slice(0, 3), 0, 0, 0, 0, 0, 0, 0]

tmp2 = []

Expand All @@ -77,88 +70,85 @@ function encryptPacket (sk, mac, packet) {
return Buffer.from(packet)
}

const nobleReady = new Promise(resolve =>
noble.on('stateChange', state => {
state === 'poweredOn' && resolve()
})
)
function connect (light, callback) {
return light.connect(() => callback(light))
}

global.connect = async function connect () {
global.light = light = await new Promise(resolve => {
noble.on('discover', thing => {
console.log(thing.advertisement.localName, name)
if (thing.advertisement.localName === name) {
console.log('thinging')
mac = thing.address
resolve(thing)
function discover (options, callback) {
if (callback == null) {
callback = options || Function.prototype
options = null
}
options == null && (options = {})
const {name = 'Smart Light', password = '234', mac} = options
noble.on('discover', thing => {
if (thing.advertisement.localName === name) {
thing.password = password
if (mac) {
mac === thing.address && connect(thing, callback)
} else {
connect(thing, callback)
}
})
noble.startScanning()
}
})
.then(light => new Promise(resolve => light.connect(() => resolve(light))))
await new Promise(resolve => light.discoverAllServicesAndCharacteristics(() => resolve()))
ch = light.services[1].characteristics[1]
pairch = light.services[1].characteristics[3]
const pairHandle = 0x001b

// light now has .services each with .characteristics
const data = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0, 0, 0, 0, 0, 0, 0, 0]
const encryptedData = keyEncrypt(name, password, data)
const packet = [0x0c]
.concat(data.slice(0, 8))
.concat(Array.from(encryptedData).slice(0, 8))
await new Promise(resolve => pairch.write(new Buffer(packet), true, resolve))
const received = await new Promise((resolve, reject) => pairch.read((error, data) =>
error ? reject(error) : resolve(data)
))
light.sk = generateSk(name, password, data.slice(0, 8), received.slice(1, 9))
return light
noble.startScanning()
}

global.sendPacket = async function sendPacket (id, command, data) {
const packet = Array(20).fill(0)
packet[0] = packetCount & 0xff
packet[1] = packetCount >> 8 & 0xff
packet[5] = id & 0xff
packet[6] = id & 0xff | 0x80
packet[7] = command
packet[8] = 0x69
packet[9] = 0x69
packet[10] = data[0]
packet[11] = data[1]
packet[12] = data[2]
packet[13] = data[3]
const macArray = mac.split(':')
const macKey = Buffer.from([macArray[5], macArray[4], macArray[3], macArray[2], macArray[1], macArray[0]].map(n => parseInt(n, 16)))
const encryptedPacket = encryptPacket(light.sk, macKey, [...packet])
packetCount += 1
if (packetCount > 0xffff) packetCount = 1

return new Promise(resolve => ch.write(encryptedPacket, false, resolve))
function pair (light, callback = Function.prototype) {
let packetCount = Math.random() * 0xffff | 0
const name = light.advertisement.localName
const password = light.password
const mac = light.address
light.discoverAllServicesAndCharacteristics(() => {
const commandChar = light.services[1].characteristics[1]
const pairChar = light.services[1].characteristics[3]
const data = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0, 0, 0, 0, 0, 0, 0, 0]
const encryptedKey = encryptKey(name, password, data)
const packet = [0x0c]
.concat(data.slice(0, 8))
.concat([...encryptedKey].slice(0, 8))
pairChar.write(new Buffer(packet), true, () => {
pairChar.read((error, received) => {
const sk = generateSk(name, password, data.slice(0, 8), received.slice(1, 9))
callback(function dispatch ([id, command, data], callback = Function.prototype) {
const packet = Array(20).fill(0)
packet[0] = packetCount & 0xff
packet[1] = packetCount >> 8 & 0xff
packet[5] = id & 0xff
packet[6] = id & 0xff | 0x80
packet[7] = command
packet[8] = 0x69
packet[9] = 0x69
packet[10] = data[0]
packet[11] = data[1]
packet[12] = data[2]
packet[13] = data[3]
const macKey = Buffer.from(mac.split(':').slice(0, 6).reverse().map(n => parseInt(n, 16)))
const encryptedPacket = encryptPacket(sk, macKey, [...packet])
packetCount = packetCount > 0xffff ? 1 : packetCount + 1
commandChar.write(encryptedPacket, false, callback)
})
})
})
})
}

global.setState = function setState (red, green, blue, brightness) {
colors = [red, green, blue, brightness]
return sendPacket(0xffff, 0xc1, colors)
function sendCommand (command, ...args) {
return [0xffff, command, args]
}

function setDefaultState (...colors) {
return sendPacket(0xffff, 0xc4, colors)
// r, g, b, brightness
function setColors (...colors) {
return sendCommand(0xc1, ...colors)
}

/// brightness, speed, mode, loop
function setRainbow (...args) {
return sendPacket(0xffff, 0xca, args)
function setDefaultColors (...colors) {
return sendCommand(0xc4, ...colors)
}

function setMosquito (brightness) {
return sendPacket(0xffff, 0xcb, [brightness, 0, 0, 0])
module.exports = {
discover: (...args) => nobleReady.then(() => discover(...args)),
pair,
setColors,
setDefaultColors
}

const byte = () => Math.random() * 0xff | 0

nobleReady.then(global.connect).then(() => {
setInterval(() => {
setState(byte(), byte(), byte(), byte())
}, 300)
})

0 comments on commit 3bfd12f

Please sign in to comment.