This is the source code of the NEEO SDK to interact with the NEEO Brain.
If you're looking for examples, take a look at the example repository at https://github.com/NEEOInc/neeo-sdk-examples
- You must have at least Node.js v6 installed, see http://nodejs.org
- If you use the SDK on Windows we suggest to install Apple iTunes (or the Bonjour SDK for Windows, available from the https://developer.apple.com/bonjour/ site). Windows versions < 10 seems to miss multicast DNS support (aka. Bonjour/Zeroconf). This means the Brain discovery find's a NEEO Brain but you cannot connect to the NEEO Brain (as the discovery fails). You can test if multicast DNS works on your machine when you try to
ping NEEO-xxxxxxxx.local
(replace xxxxxxxx with the unique hostname of your NEEO Brain).
The NEEO-CLI now lives in a dedicated repository: @neeo/cli
The neeo-sdk cli is deprecated and will be removed in a future version to make the neeo-sdk smaller. We recommend switching to the new CLI as soon as possible.
One goal of the CLI is to make it easy and simple to run SDK devices without writing any code for non developers. A NEEO-SDK user should be able to run multiple drivers easily without writing code (unlike development that focuses on a single driver at a time). That's where the CLI comes in:
# Example setup:
sdk-drivers/
node_modules/
# NEEO SDK drivers installed via npm:
neeo-driver-lifx/
neeo-driver-ps4/
neeo-driver-coffee/
# ... other modules as well
package.json
Running neeo-cli start
will find and load all 3 drivers (lifx, ps4, coffee). This means you don't have to worry about the folders, the ports or changing any code.
The neeo-sdk cli will be removed in a future version. We recommend using the @neeo/cli.
To use it for your own driver, either update the NPM script:
"scripts": {
[...]
"start": neeo-sdk start"
}
This allows you to start your driver with npm start
.
By default, the neeo-sdk cli will connect to the first discovered brain within the network. You can change this behaviour by creating a "neeoSdkOptions"
property in your project's package.json
, and set the "brainHost" property to the Brain IP address. Following parameters are available:
"neeoSdkOptions": {
"brainHost": "10.0.0.131", // If configured, connect to this IP. Else connect to the first NEEO Brain discovered
}
The Brain lookup uses a default timeout of 5000ms. To change this behaviour, change the environment variable NEEO_BRAIN_LOOKUP_DURATION_MS
See https://neeoinc.github.io/neeo-sdk/ for the functions documentation.
The NEEO CLI will look for drivers installed in the node_module folder (installed via npm) which export their devices using the following format:
- A single file exporting all devices for example
index.js
:module.exports = { devices: [ // Exports listed here will be detected, // these are the objects returned by neeo-sdk.buildDevice() exampleDriver, ], };
- Your
package.json
main property points to that file:... "main": "index.js", ...
- In your package.json use the
neeo-driver-
prefix for the name property.*
This allows you to place your export where you please as long as you document it in package.json
. The CLI will read the main
property of the package.json for drivers installed via npm.
This is the recommended setup for exporting devices:
- one device per driver module**
- Set the path to your main export in your
package.json
:main: "index.js"
* Previously we looked for the neeo-
and neeo_
prefixes, these are still detected but we recommend neeo-driver-
** In some cases like 2 devices of the same model but different series with slightly different features might share common code, they could then be part of the same module.
You can find an example driver: neeo-driver-example in the neeo-sdk-examples.
See SDK Driver Migration to 0.51.0 for migrating to the @neeo/cli
When developing a driver it is more convient to directly run a single driver rather than install or link the driver in another folder to use the regular CLI. This also allows attaching a debugger to the process more easiler.
One way to start a driver with the server is to create for example a devStart.js
file that looks like this:
"use strict";
const neeoapi = require("neeo-sdk");
const driver = require("./lib/DeviceController");
// IP of your NEEO Brain
const BRAIN_IP = '10.0.0.10';
neeoapi
.startServer({
brain: BRAIN_IP,
port: 6336,
name: 'debug-server',
devices: [
driver,
]
})
.then(() => console.log('Server Ready'))
.catch((error) => {
console.error('ERROR:', error);
process.exit(1);
});
You can then start your driver with node devStart.js
or by adding it to "start": "node devStart.js"
in your package.json
scripts npm start
.
To migrate a driver to the driver device export format, follow: Driver migration guide to 0.50.0. Note: We have updated the example code too, take a look there if something is unclear.
After 0.50.0 we've decided to move the CLI to a separate repository.
To migrate a driver to the new @neeo/cli, follow: Driver migration guide to @neeo/cli.
To tell the NEEO Brain about changes to your device's components you can simply change the driver version (.setDriverVersion
).
If you for example add new buttons to a device, you can increase the version and this will let the Brain know to fetch the new components.
You do not need to update the version if you do not change the components. When adding the version to a device that was previously not versioned, start with 1. The NEEO Brain will assume it was previously 0 and update. The check for updates happens as soon as the SDK driver is started and registers with the NEEO Brain
### NOTE
- the NEEO Brain will only add new components, updating or removing old components is not supported
- the
name
of a component is used as an identifier for that component, changing it will result in it being added as a "new" component instead of the old one being updated
A collection of hints if you create a device driver.
- If possible provide a device discovery to find a device to support (
.enableDiscovery
) - this is the most user friendly way for the user to add a device. - Make sure that your driver handles if the device reboots. It's possible that the device IP changed after the reboot.
- Make sure to handle the case when the user deleted the device from the NEEO Brain, so the driver won't send notifications anymore and shut down any running services (
registerDeviceSubscriptionHandler
). - Make sure your driver allocate resources only if needed - use the
registerInitialiseFunction
to initialise your driver. - List the minimal firmware version of the device you use - this might help if a driver does not work as expected (use
.enableDiscovery
to show information to the user). - The
.registerSubscriptionFunction
function is used to inject the notification function to your driver. So the driver can send updates to the NEEO Brain. - The
.registerDeviceSubscriptionHandler
function is used to inform your driver how many devices are in use on the NEEO Brain and when a device is added or removed from the NEEO Brain.
If you need to build different devices dynamically (for example to write an SDK driver for a controller that controls lights and switches) you can do that
thanks to the updated .enableDiscovery
function introduced in the v0.52 release.
It static defined device contains the information that it's able to build dynamic devices as soon the discovery function is called.
- you must set
enableDynamicDeviceBuilder
to true when you configure the.enableDiscovery
options - your discovery function needs to return the dynamically build devices as
.device
attribute (seedynamicDeviceBuilder
example) - Make sure the name (
neeoapi.buildDevice('THIS-IS-THE-NAME')
) of ALL SDK devices of your driver (the initial device and the dynamically build devices) are identical - else your device won't be found. - Don't forget to call the
.addCapability('dynamicDevice’)
to the dynamic build devices. - Use the
.registerDeviceSubscriptionHandler
function:- The initializeDeviceList can be used to build the dynamic devices in use as soon as the driver starts.
- This is important so the NEEO Brain won't miss a state update.
- Update the discovery function to handle the optional optionalDeviceId - this optionalDeviceId is set when your driver needs to rebuild the dynamic device (for example after a restart of your SDK driver)
There are some issues on the SDK we will address in the future. To avoid breaking changes we collect them and bulk fix them in a non breaking way in the future.
- If you added a sensor with the name "MYSENSOR" and want to update a sensor value, you cannot use the name "MYSENSOR" but you need to add the suffix "_SENSOR" (e.g. "MYSENSOR_SENSOR").
The view for a device in the recipe is generated automatically depending on the device capabilities.
See widget documentation for more details on the way default views are generated.
If your device supports Power control (power on device, power off device), add this capability - the generated recipe will power on and off your device automatically.
You need to add support for the following buttons (addButton({..
):
POWER ON
POWER OFF
or just use the shortcut function .addButtonGroup('POWER')
If your device supports Volume control (volume up and down, optional mute toggle), add this capability - the generated recipe will automatically use the volume capability of your device.
You need to add support for the following buttons (addButton({..
):
VOLUME UP
VOLUME DOWN
- optionally
MUTE TOGGLE
or just use the shortcut function .addButtonGroup('VOLUME')
If you want support for a custom Favorite view, you need to add support for the following buttons (addButton({..
):
DIGIT 0
DIGIT 1
DIGIT 2
DIGIT 3
DIGIT 4
DIGIT 5
DIGIT 6
DIGIT 7
DIGIT 8
DIGIT 9
or just use the helper function .addButtonGroup('Numpad')
. The device must be one of the following types:
TV
DVB
(aka Satellite box, digital receiver)TUNER
(audio tuner)
If you want to add a numpad widget to your view, make sure to implement all the DIGIT
buttons of the "Favorites View Capability". Supported for TV
and DVB
devices.
To create a Controlpad capability you need to implement the following buttons (addButton({..
):
CURSOR ENTER
CURSOR UP
CURSOR DOWN
CURSOR LEFT
CURSOR RIGHT
or just use the helper function .addButtonGroup('Controlpad')
. The devicetype must be TV
, DVB
, GAMECONSOLE
, MEDIAPLAYER
, VOD
, DVD
or PROJECTOR
.
To create a Controlpad capability you need to implement the following buttons (addButton({..
):
FUNCTION RED
FUNCTION GREEN
FUNCTION YELLOW
FUNCTION BLUE
or just use the helper function .addButtonGroup('Color Buttons')
. The devicetype must be TV
, DVB
, GAMECONSOLE
, MEDIAPLAYER
or PROJECTOR
.
To create a MENU (navigation) capability you need to implement the following buttons (addButton({..
):
MENU
BACK
or just use the helper function .addButtonGroup('Menu and Back')
. In most cases it make sense to include the Controlpad capability aswell.
To create a Channel Zapper capability (Channel Up/Down) you need to implement the following buttons (addButton({..
):
CHANNEL UP
CHANNEL DOWN
or just use the helper function .addButtonGroup('Channel Zapper')
.
If you want to support different transport features (like skip, forward, next) you can include the following buttons (addButton({..
):
PLAY
,PAUSE
,STOP
(helper function:.addButtonGroup('Transport')
)REVERSE
,FORWARD
(helper function:.addButtonGroup('Transport Search')
)PREVIOUS
,NEXT
(helper function:.addButtonGroup('Transport Scan')
)SKIP SECONDS BACKWARD
,SKIP SECONDS FORWARD
(helper function:.addButtonGroup('Transport Skip')
)
This works for the devices TV
, DVB
, GAMECONSOLE
, MEDIAPLAYER
, VOD
, DVD
or PROJECTOR
.
To create a Record capability you need to implement the following buttons (addButton({..
):
MY RECORDINGS
RECORD
LIVE
or just use the helper function .addButtonGroup('Record')
. The devicetype must be TV
, DVB
. Please note, if you don't have all 3 buttons you can implement only the buttons your device provides.
If you add support for a devicetype TV
, PROJECTOR
or AVRECIEVER
you should provide discrete input change commands depending of your devices features, for example:
INPUT HDMI 1
INPUT HDMI 2
INPUT VGA 1
INPUT SCART 1
Thanks to the contributors for porting the SDK to other platforms.
- C# implementation by Christian Riedl: https://github.com/ChristianRiedl/NeeoApi
- ESP8266 implementation by grumpyengineer: https://github.com/grumpyengineer/ESP8266NeeoSDK