-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
237 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
'use strict'; | ||
|
||
const debug = require('debug'); | ||
const BluePromise = require('bluebird'); | ||
const fs = require('fs') | ||
const readline = require('readline') | ||
const os = require('os'); | ||
const net = require('net'); | ||
const dgram = require('dgram'); | ||
|
||
const PORT_NUMBER = 9; | ||
const DEFAULT_IPADDRESS = '255.255.255.255'; | ||
|
||
let wolMap = "wol.map"; | ||
|
||
/** | ||
* Sets the path to the 'wol.map' file | ||
*/ | ||
module.exports.setMapPath = (mapPath) => { | ||
wolMap = mapPath; | ||
} | ||
|
||
/** | ||
* Handles button presses for WOL | ||
*/ | ||
module.exports.onButtonPressed = (deviceid, name) => { | ||
console.log(`WOL button pressed for ${name}`); | ||
|
||
const addr = parseAddr(name); | ||
const macAddr = getMacBuffer(addr.macAddress); | ||
|
||
if (macAddr) { | ||
let magic = Buffer.alloc(102, 0xff); | ||
for (let i = 6; i < magic.length; i+=6) { | ||
macAddr.copy(magic, i, 0); | ||
} | ||
|
||
debug("Sending WOL packet"); | ||
sendPacket(addr.ipAddress, magic) | ||
.catch((err) => { | ||
console.error("Error occurred writing WOL packet. ", err || err.message); | ||
}); | ||
|
||
} else { | ||
debug('MAC address was invalid and is ignored - %s', addr.macAddress); | ||
} | ||
} | ||
|
||
/** | ||
* Returns a promise to send the magic packet to the specified IP address | ||
* @param {any} ipAddress the ipaddress to send to | ||
* @param {any} magic the magic packet to send | ||
*/ | ||
function sendPacket(ipAddress, magic) { | ||
return new BluePromise((resolve, reject) => { | ||
const socket = dgram.createSocket(net.isIPv6(ipAddress) ? 'udp6' : 'udp4') | ||
.on('error', (err) => { | ||
socket.close(); | ||
reject(err); | ||
}) | ||
.once('listening', () => { | ||
socket.setBroadcast(true); | ||
}); | ||
|
||
socket.send(magic, 0, magic.length, PORT_NUMBER, ipAddress, (err, res) => { | ||
socket.close(); | ||
if (err) { | ||
reject(new Error("Exception writing the magic packet: " + err)); | ||
} else { | ||
resolve(true); | ||
} | ||
}); | ||
}); | ||
} | ||
|
||
/** | ||
* Discovers devices from the wolMap file. Please note that validation of the | ||
* address field is not | ||
*/ | ||
module.exports.discoverWolDevices = () => { | ||
debug('WOL discovery using %s', wolMap); | ||
|
||
return new BluePromise((resolve, reject) => { | ||
const devices = []; | ||
|
||
readline.createInterface({ input: fs.createReadStream(wolMap) }) | ||
.on('line', (line) => { | ||
const parsedLine = parseLine(line); | ||
if (parsedLine) { | ||
var parsedAddr = parseAddr(parsedLine.addr); | ||
const macAddr = getMacBuffer(parsedAddr.macAddress); | ||
if (macAddr) { | ||
debug('WOL discovery call - found %s at %s', parsedLine.name, parsedLine.addr); | ||
devices.push({ | ||
id: parsedLine.addr, | ||
name: parsedLine.name, | ||
reachable: true | ||
}); | ||
} else { | ||
debug("MAC address is invalid and will be ignored: %s", parsedAddr.macAddress); | ||
} | ||
} | ||
}) | ||
.on('error', (err) => { | ||
reject(err); | ||
}) | ||
.on('close', () => { | ||
resolve(devices); | ||
}); | ||
}); | ||
} | ||
|
||
/** | ||
* Parses a line from the map file and returns undefined (if the line can't be parsed | ||
* or an object containing a name and addr field. | ||
* @param {any} line the line to parse | ||
*/ | ||
function parseLine(line) { | ||
if (!line.startsWith("#")) { | ||
const idx = line.indexOf("="); | ||
if (idx >= 0) { | ||
return { | ||
name : line.substring(0, idx).trim(), | ||
addr : line.substring(idx + 1).trim().replace(/ /g, '/') | ||
} | ||
} | ||
} | ||
return undefined; | ||
} | ||
|
||
/** | ||
* Parses the string address (found in the wol.map file) to a macAddress/ipAddress | ||
* @param {any} addr the address field to parse | ||
*/ | ||
function parseAddr(addr) { | ||
const idx = addr.indexOf("/"); | ||
return { | ||
macAddress: (idx < 0 ? addr : addr.substring(0, idx)).trim(), | ||
ipAddress: (idx < 0 ? DEFAULT_IPADDRESS : addr.substring(idx + 1)).trim(), | ||
}; | ||
} | ||
|
||
/** | ||
* Parses the String (hex) MAC address to a byte array of integers | ||
* @param {any} macAddress the max address | ||
*/ | ||
function getMacBuffer(macAddress) { | ||
const hexArray = macAddress.split(/[-:]+/); | ||
if (hexArray.length === 6) { | ||
const buffer = Buffer.alloc(6); | ||
for (let i = 0; i < 6; i++) { | ||
buffer[i] = parseInt(hexArray[i], 16); | ||
} | ||
return buffer; | ||
} | ||
|
||
return undefined; | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
'use strict'; | ||
|
||
const neeoapi = require('neeo-sdk'); | ||
|
||
console.log('NEEO SDK Example "WakeOnLan"'); | ||
console.log('------------------------------------------'); | ||
|
||
const controller = require('./controller'); | ||
|
||
/** | ||
* Uncomment the following line to set the path to the wol map file | ||
*/ | ||
//controller.setMapPath("device/WakeOnLan/wol.map"); | ||
|
||
const wolDevice = neeoapi.buildDevice('WakeOnLan') | ||
.setManufacturer('NEEO') | ||
.addAdditionalSearchToken('WOL') | ||
.setType('ACCESSOIRE') | ||
.addButton({ name: 'wol', label: 'Wake Up' }) | ||
.addButtonHander(controller.onButtonPressed) | ||
.enableDiscovery({ | ||
headerText: 'WOL Instructions', | ||
description: 'Please make sure you add devices to wol.map' | ||
}, controller.discoverWolDevices); | ||
|
||
function startSdkExample(brain) { | ||
console.log('- Start server'); | ||
neeoapi.startServer({ | ||
brain, | ||
port: 6336, | ||
name: 'wake-on-lan', | ||
devices: [wolDevice] | ||
}) | ||
.then(() => { | ||
console.log('# READY, use the mobile app to search for "WakeOnLan"'); | ||
}) | ||
.catch((error) => { | ||
console.error('ERROR!', error.message); | ||
process.exit(1); | ||
}); | ||
} | ||
|
||
const brainIp = process.env.BRAINIP; | ||
//const brainIp = '192.168.1.29'; | ||
if (brainIp) { | ||
console.log('- use NEEO Brain IP from env variable', brainIp); | ||
startSdkExample(brainIp); | ||
} else { | ||
console.log('- discover one NEEO Brain...'); | ||
neeoapi.discoverOneBrain() | ||
.then((brain) => { | ||
console.log('- Brain discovered:', brain.name); | ||
startSdkExample(brain); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
##################################################################################### | ||
# This file will provide mappings between devices and their MAC address/IP addresses | ||
# | ||
# The format of the file is | ||
# Device Name=MACAddress[/IPAddress] | ||
# | ||
# 1) (Required) The device name will appear on the NEEO remote | ||
# 2) (Required) The MAC address to send the WOL packet to | ||
# 3) (Optional) Slash or space followed by the device IP address | ||
# | ||
# If IP Address is specified, the WOL packet is sent directly to it. If not | ||
# specified, the WOL packet will be broadcast to the network | ||
# | ||
# Please note that if the MACAddress appears twice (or MAC Address/IP Address combo), | ||
# the NEEO app will complain of a duplicate when trying to add a device. | ||
##################################################################################### | ||
|
||
Example=01:02:03:04:05:06 | ||
IP Example=01:02:03:04:05:06 192.168.1.111 | ||
IP Example2=01:02:03:04:05:06/192.168.1.112 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters