Code Monkey home page Code Monkey logo

node-dash-button's Introduction

Blank Dash

node-dash-button

Travis-CI Build Status Coverage Status gitter

Place it. Hack it. Press it. Get it.

This module was inspired by this fantastic article by Edward Bensen.

It is a simple library that will allow you to utilize a dash button to emit an event. I am using the same strategy of watching for dash generated ARP requests as the article above.

Contents


Installation Instructions

The following should work for ubuntu, the main thing for any os is getting the libpcap dependancy.

# dependancy on libpcap for reading packets
$ sudo apt-get install libpcap-dev
$ npm install node-dash-button

First Time Dash Setup

Follow Amazon's instructions to configure your button to send messages when you push them but not actually order anything. When you get a Dash button, Amazon gives you a list of setup instructions to get going. Just follow this list of instructions, but don’t complete the final step (#3 I think) Do not select a product, just exit the app.

Find a Dash

To find a dash on your network, run the following from the node-dash-button directory in node_modules:

# you may need to use sudo due to libpcap running in permiscuous mode
$ cd node_modules/node-dash-button
$ node bin/findbutton

It will watch for new arp and udp requests on your network. There may be several such requests, so press it a few times to make sure. Copy the hardware address as shown below, and make a note of the protocol used.

hw address

Note: If your computer has multiple active network interfaces, findbutton will use the first one listed. If you need to overwrite this setting, pass your preferred interface as the first argument, such as node bin/findbutton eth6.

Usage docs:

var dash_button = require('node-dash-button');
var dash = dash_button(mac_addresses, iface, timeout, protocol);
  • mac_addresses string or array of strings
  • iface the name of the interface on which to capture packets. If passed an empty string, libpcap will try to pick a "default" interface, which is often just the first one in some list and not what you want. (from the node_pcap README)
  • timeout timeout between presses in ms, default 5000 (5 seconds)
  • protocol either arp, udp, or all. default arp

Example Usage:

For a single dash

//warning this may trigger multiple times for one press
//...usually triggers twice based on testing for each press
var dash_button = require('node-dash-button');
var dash = dash_button("8f:3f:20:33:54:44", null, null, 'all'); //address from step above
dash.on("detected", function (){
	console.log("omg found");
});

For multiple dashes:

var dash_button = require('node-dash-button');
var dash = dash_button(["8f:3f:20:33:54:44","2e:3f:20:33:54:22"], null, null, 'all'); //address from step above
dash.on("detected", function (dash_id){
    if (dash_id === "8f:3f:20:33:54:44"){
        console.log("omg found");
    } else if (dash_id === "2e:3f:20:33:54:22"){
        console.log("found the other!");
    }
});

Binding To Specific Interface: By default, the dash button is bound to the first device with an address. To bind the button to a specific interface, such as eth6, pass the name of the interface as the 2nd argument to the invocation method.

var dash_button = require('node-dash-button');
var dash = dash_button("8f:3f:20:33:54:44", "eth6"); //address from step above
dash.on("detected", function (){
  console.log("omg found - on eth6!");
});

Adjusting the Timeout (if multiple presses are detected): By default the timeout between presses is 5 seconds. Depending on the network this may not be enough. Use the following syntax to specify a new timeout in miliseconds:

var dash_button = require('node-dash-button');
var dash = dash_button("8f:3f:20:33:54:44", null, 60000); //address from step above
dash.on("detected", function (){
  console.log("omg found - on eth6!");
});

ARP, UDP or both: By default the protocol monitored is ARP, which is what the earlier buttons tend to use. Newer buttons however, are using UDP to make thier request. By setting protocol to 'arp', 'udp', or 'all' (both), you can optimise the script to your setup.

Note: If your button was initially picked up using ARP, but is now not being picked up, it's possible that the button has switched to UDP.

var dash_button = require('node-dash-button');
var dash = dash_button("8f:3f:20:33:54:44", null, null, "all"); //address from step above
dash.on("detected", function (){
  console.log("omg found");
});

Running Tests:

Due to the use of pcap permiscuous monitoring this was difficult to test in CI environments, so I ended up making two testing suites. One uses the live pcap library and does actual packet capturing/arp injections. The other uses mockery to fake pcap packets. I will have an upcoming blog post on how I did this, because it was interesting.

To run a live test of the code (requiring root due to permiscuous access please run).

sudo npm run-script livetest

This will actually inject ARP packets to the network to run the tests to ensure detection.

I wanted to use various CI tools that would not allow the pcap functions to work, so I ended up mocking their functions. To run the mock tests use:

npm test

Example Projects:

I collected a few examples I found on github of how people are using this module, some projects are more mature than others

  • PizzaDash uses a node dash to order Domino's pizza. The Verge, Gizmodo and Grubstreet did short writeups on the PizzaDash project].
  • dashgong uses the node dash to send a message to slack
  • dash-listener performs various home automation tasks like adjusting lights and interacting with a music player
  • dasher lets you map a dash button press to an HTTP request.
  • Nest-Dash toggles the Nest setting from away to home via Amazon Dash Button
  • dash-hipchat-doorbell quick and dirty node app that intercepts traffic from an amazon dash button and creates a hipchat notification (think doorbell)
  • netflixandchill button to netflix and chill, dims the lights (no interface with netflix yet)
  • dash-rickroll title explains it all

To do

  • refactor

Contributions

Accepting pull requests!

License

The MIT License (MIT)

Copyright (c) 2016 Alex Hortin

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

node-dash-button's People

Contributors

a3qz avatar danthegoodman avatar dkordik avatar ecaron avatar hortinstein avatar kim3er avatar loisaidasam avatar maddox avatar ultrafez avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

node-dash-button's Issues

Merging continuous arp requests

Hi Guys,

first of all. Thank you very much for this awesome package. You make it easy to play around with the dash button. Nice job.

However, once I press the dash button, my app registers to two continuous request. I know that you mention this in the documentation. But, I was wondering if there is a way to merge the two requests which originate from one button press?

Thanks for the help.

Gerardo

Detect double- or triple-press

Do you think it would be possible to detect a double press?

It'd be nice to configure a single button for multiple actions.

Cannot choose interface which to listen to ARP

On devices with multiple interfaces node_pcap uses a "default" interface which is not necessarily the one you want. It would be useful to be able to pass the desired interface using

var pcap = require('pcap'),
    pcap_session = pcap.createSession(interface, filter);

building issue

my maschine M8S TV Box with Armbian5.27 Ubuntu16.0.4 Xenial LTS kernel 3.10.99

follow error
install nodejs from apt-get
install ndm from apt-get

/bin/sh: 1: node: not found
gyp: Call to 'node -e "require('nan')"' returned exit status 127 while in binding.gyp. while trying to load binding.gyp
gyp ERR! configure error
gyp ERR! stack Error: gyp failed with exit code: 1
gyp ERR! stack at ChildProcess.onCpExit (/usr/share/node-gyp/lib/configure.js:354:16)
gyp ERR! stack at emitTwo (events.js:87:13)
gyp ERR! stack at ChildProcess.emit (events.js:172:7)
gyp ERR! stack at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
gyp ERR! System Linux 3.10.99
gyp ERR! command "/usr/bin/nodejs" "/usr/bin/node-gyp" "rebuild"
gyp ERR! cwd /root/node_modules/socketwatcher
gyp ERR! node -v v4.2.6
gyp ERR! node-gyp -v v3.0.3
gyp ERR! not ok
npm WARN enoent ENOENT: no such file or directory, open '/root/package.json'
npm WARN root No description
npm WARN root No repository field.
npm WARN root No README data
npm WARN root No license field.
npm ERR! Linux 3.10.99
npm ERR! argv "/usr/bin/nodejs" "/usr/bin/npm" "install" "node-dash-button"
npm ERR! node v4.2.6
npm ERR! npm v3.5.2
npm ERR! code ELIFECYCLE

npm ERR! [email protected] install: node-gyp rebuild
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] install script 'node-gyp rebuild'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the socketwatcher package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR! node-gyp rebuild
npm ERR! You can get information on how to open an issue for this project with:
npm ERR! npm bugs socketwatcher
npm ERR! Or if that isn't available, you can get their info via:
npm ERR! npm owner ls socketwatcher
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:
npm ERR! /root/npm-debug.log

any help ?

New Dash Button Version

I saw that the new model of the dash button behaves a bit differently than the old version; a fix is purportedly available here.

Does this same fix apply to this code?

Uncaught error crashes node app

My node app that uses this module occasionally halts with the following error and stack trace:

/Users/mark/bin/dash-dispatch/node_modules/pcap/decode/tcp.js:150
            throw new Error("Don't know how to process TCP option " + raw_packet[offset]);
            ^

Error: Don't know how to process TCP option 34
    at TCPOptions.decode (/Users/mark/bin/dash-dispatch/node_modules/pcap/decode/tcp.js:150:19)
    at TCP.decode (/Users/mark/bin/dash-dispatch/node_modules/pcap/decode/tcp.js:231:22)
    at IPv4.decode (/Users/mark/bin/dash-dispatch/node_modules/pcap/decode/ipv4.js:97:58)
    at EthernetPacket.decode (/Users/mark/bin/dash-dispatch/node_modules/pcap/decode/ethernet_packet.js:40:51)
    at PcapPacket.decode (/Users/mark/bin/dash-dispatch/node_modules/pcap/decode/pcap_packet.js:37:57)
    at Function.decode (/Users/mark/bin/dash-dispatch/node_modules/pcap/decode/index.js:11:36)
    at PcapSession.<anonymous> (/Users/mark/bin/dash-dispatch/node_modules/node-dash-button/index.js:66:34)
    at emitOne (events.js:77:13)
    at PcapSession.emit (events.js:169:7)
    at PcapSession.on_packet_ready (/Users/mark/bin/dash-dispatch/node_modules/pcap/pcap.js:99:10)
    at packet_ready (/Users/mark/bin/dash-dispatch/node_modules/pcap/pcap.js:44:14)

I'm running this on OS X 10.11. Could I detect this error in something like dash.on("error", function(err)...? Or does it go deeper out of my control?

Dash button "detected" event is called multiple times for a single press

Recently, I've noticed that my "detected" callback is being called multiple times for a single press. Our button is hooked up to a script to toggle the lights, so pressing the button to turn off the light inevitably has the light turn on after a minute or so. Has something change with the detection mechanism? Could the button be sending multiple ARP packets?

dash.on("detected", function (){
        toggleLight();
});

Amazon iOS app push notifications

This works great! Thanks so much for it. One thing I am seeing is every time I push the button, my Amazon iOS app shows a push notification:

Your Huggies Dash Button is almost ready for use. Finish the setup process to use your Dash Button

I know it may be out of scope for this project but I'm wondering if you anyone else gets these messages and if there is any way to suppress them?

doesn't actually watch for button presses

what it does is listen for arps. which detects when button wakes up and connects to wireless network.

aka multiple button presses will NOT result in multiple "actions" within the same wifi connectivity session.

something to do, maybe, is arp cache poison and fake https endpoint. but this will more than likely interfere w/ legitimate buttons.

--timball

Starts out working well but then sends multiple button presses.

I have the dash button press triggering a python script that blinks lights my Pimoroni Led strip. If i restart node-red it all behaves as expected (1 button press = 1 run of the script blinking lights in a night rider fashion) with 1 run shown in the debug log. After some time the debug shows 2 or 3 messages from 1 button press and the light patterns become erratic as if 2 or 3 threads of the script running. If i manually inject the trigger it all works as expected. Is there a way to debounce the button presses?

Still getting notifications on android phone

Hello, I just went through the setup process and made a quick test to make sure my dash button works with this library. (It does, and thank you!)

I'm just wondering if I'm supposed to be getting this notification on my android phone where I did the initial setup with the Amazon Shopping app every time I press the dash button with the node-dash-button server.

Your ______ Dash Button is almost ready for use. Finish the setup process to use your Dash Button.

Is there a way I can prevent the dash button from getting through to the phone?

About typescript

Hello.

I have a question about this project.
Does node-dash-button support typescript now or will?

If your answer is "no", can I progress "node-dash-button_typescript" project?

Add discovery mode to api

It would be great if one could also start the "discovery" mode currently implemented in bin/findbutton programmatically. It think this should be pretty easy to implement, because most of the register function is the same like in findbutton, except for the address filtering.

Find button detects but when in a script it does not

I had this working yesterday perfectly fine and I tried to bring the dash to another network and had annoying problems with that. Moving a dash to another network is kind of stupid. You cannot just connect to the config options and change the network, apparently. You have to deactivate it from your amazon account and add it on the other network.

I have the amazon successfully back on my network (I had issues getting it BACK on my network last night). The findbutton script successfully sees the arp packets and the dashes, but when I run my node app with sudo npm start it has many of those node_pcap: EthernetFrame() : Don't know how to decode ethertype messages when I press the button but it does not detect my buttons or any other ARP packets.

Are there any known issues about this?

error installing on raspberry pi

Hi,
Like I said in previous post a friend gave me raspberry pi ( first version), I m a noob in linux, but I succed booting up the pi, enabling ssh, installing npm and libpcap... But when I try to install your code : npm install node-dash-button , I have a this error, :

pi@raspberrypi:~ $ npm install node-dash-button
npm WARN addRemoteGit Error: not found: git
npm WARN addRemoteGit at F (/usr/local/lib/node_modules/npm/node_modules/which/which.js:72:28)
npm WARN addRemoteGit at E (/usr/local/lib/node_modules/npm/node_modules/which/which.js:75:29)
npm WARN addRemoteGit at /usr/local/lib/node_modules/npm/node_modules/which/which.js:83:16
npm WARN addRemoteGit at FSReqWrap.oncomplete (fs.js:95:15)
npm WARN addRemoteGit git+https://github.com/mranney/node_pcap.git resetting remote /home/pi/.npm/_git-remotes/https-github-com-mranney-node-pcap-git-72c55299 because of error: { [Error: not found: git] code: 'ENOGIT' }
npm ERR! git clone --template=/home/pi/.npm/_git-remotes/_templates --mirror https://github.com/mranney/node_pcap.git /home/pi/.npm/_git-remotes/https-github-com-mranney-node-pcap-git-72c55299: undefined
npm ERR! git clone --template=/home/pi/.npm/_git-remotes/_templates --mirror https://github.com/mranney/node_pcap.git /home/pi/.npm/_git-remotes/https-github-com-mranney-node-pcap-git-72c55299: undefined
npm ERR! Linux 4.4.34+
npm ERR! argv "/usr/local/bin/node" "/usr/local/bin/npm" "install" "node-dash-button"
npm ERR! node v0.12.6
npm ERR! npm v2.11.2
npm ERR! code ENOGIT

npm ERR! not found: git
npm ERR!
npm ERR! Failed using git.
npm ERR! This is most likely not a problem with npm itself.
npm ERR! Please check if you have git installed and in your PATH.

npm ERR! Please include the following file with any support request:
npm ERR! /home/pi/npm-debug.log

some help would be really appreciate, thanks

Can I change what the dash button does on press?

Is it possible to ping a custom url each time I press the dash button?

I would like to get my dash button connected to a zapier, but I do not want to have a server running on the same wifi nor do I want to set up a rasberry pi.

Is this possible?

Dach click detects only 1 time

I catch an interesting behaviour.

With findbutton I see a list of our office activity and after button click could detect Mac Address, but after 2nd button click I don't see it anymore.

Interesting that if I turn off WiFi on my computer and then turn it back, I can detect button click again. But only 1 time.

Anybody faced with such case already?

Thanks

Installing - Error 1

hello there,
i stumbled accross your node red plugin,
but i'm not able to install it.
(total noob here!)
i added the error message.
hope this helps?

THANK YOU in advance

npm ERR! code 1 npm ERR! path /config/node-red/node_modules/pcap npm ERR! command failed npm ERR! command sh -c node-gyp rebuild npm ERR! gyp info it worked if it ends with ok npm ERR! gyp info using [email protected] npm ERR! gyp info using [email protected] | linux | x64 npm ERR! gyp info find Python using Python version 3.9.7 found at "/usr/bin/python3" npm ERR! gyp info spawn /usr/bin/python3 npm ERR! gyp info spawn args [ npm ERR! gyp info spawn args '/usr/lib/node_modules/npm/node_modules/node-gyp/gyp/gyp_main.py', npm ERR! gyp info spawn args 'binding.gyp', npm ERR! gyp info spawn args '-f', npm ERR! gyp info spawn args 'make', npm ERR! gyp info spawn args '-I', npm ERR! gyp info spawn args '/config/node-red/node_modules/pcap/build/config.gypi', npm ERR! gyp info spawn args '-I', npm ERR! gyp info spawn args '/usr/lib/node_modules/npm/node_modules/node-gyp/addon.gypi', npm ERR! gyp info spawn args '-I', npm ERR! gyp info spawn args '/root/.cache/node-gyp/16.14.0/incl...

Node 4 / io.js install trouble

I have a Raspberry Pi running Raspbian Jessie, everything up to date on a fresh install. After installing libpcap and node, and making sure node/npm are up to date (tried all of these: 2.1.0, 4.0.0, 4.1.2), I get an error about the node-gyp rebuild command failing in relation to socketwatcher.

I've looked at the documentation and issues for the dependencies and tried pretty much everything I could find that fixed issues for others. This includes installing a local version of node-gyp instead of the global, using the --unsafe-perm flag, sudo vs. not, messing with nan, etc. All of those did not resolve the issue.

Here are my console output and npm-debug.log file.

Any ideas about what to look into next?

Install: Error Code 128

I'm trying to install node-dash-button on a RaspberryPi (stretch lite - debian 9.4) with this command:
sudo npm install node-dash-button

This is the reply:
npm ERR! code 128
npm ERR! Command failed: /usr/bin/git submodule update -q --init --recursive
npm ERR! fatal: Could not change back to '/root/.npm/_cacache/tmp/git-clone-c06219b0': Permission denied
npm ERR!

npm ERR! A complete log of this run can be found in:
npm ERR! /root/.npm/_logs/2018-09-19T06_57_31_180Z-debug.log

This is the content of /root/.npm/_logs/2018-09-19T06_57_31_180Z-debug.log:
0 info it worked if it ends with ok
1 verbose cli [ '/usr/bin/node', '/usr/bin/npm', 'install', 'node-dash-button' ]
2 info using [email protected]
3 info using [email protected]
4 verbose npm-session 5c2729c98d87554b
5 silly install loadCurrentTree
6 silly install readLocalPackageData
7 http fetch GET 304 https://registry.npmjs.org/node-dash-button 432ms (from cache)
8 silly pacote tag manifest for node-dash-button@latest fetched in 494ms
9 timing stage:loadCurrentTree Completed in 1353ms
10 silly install loadIdealTree
11 silly install cloneCurrentTreeToIdealTree
12 timing stage:loadIdealTree:cloneCurrentTree Completed in 2ms
13 silly install loadShrinkwrap
14 timing stage:loadIdealTree:loadShrinkwrap Completed in 62ms
15 silly install loadAllDepsIntoIdealTree
16 silly resolveWithNewModule [email protected] checking installable status
17 silly fetchPackageMetaData error for pcap@git+https://github.com/mranney/node_pcap.git Command failed: /usr/bin/git submodule update -q --init --recursive
17 silly fetchPackageMetaData fatal: Could not change back to '/root/.npm/_cacache/tmp/git-clone-c06219b0': Permission denied
18 timing stage:rollbackFailedOptional Completed in 3ms
19 timing stage:runTopLevelLifecycles Completed in 4953ms
20 silly saveTree pi
20 silly saveTree ├─┬ [email protected]
20 silly saveTree │ ├─┬ [email protected]
20 silly saveTree │ │ ├── [email protected]
20 silly saveTree │ │ └── [email protected]
20 silly saveTree │ └── [email protected]
20 silly saveTree ├── [email protected]
20 silly saveTree ├── [email protected]
20 silly saveTree ├── [email protected]
20 silly saveTree ├── [email protected]
20 silly saveTree └── [email protected]
21 verbose stack Error: Command failed: /usr/bin/git submodule update -q --init --recursive
21 verbose stack fatal: Could not change back to '/root/.npm/_cacache/tmp/git-clone-c06219b0': Permission denied
21 verbose stack
21 verbose stack at ChildProcess.exithandler (child_process.js:289:12)
21 verbose stack at ChildProcess.emit (events.js:182:13)
21 verbose stack at maybeClose (internal/child_process.js:962:16)
21 verbose stack at Socket.stream.socket.on (internal/child_process.js:381:11)
21 verbose stack at Socket.emit (events.js:182:13)
21 verbose stack at Pipe._handle.close (net.js:606:12)
22 verbose cwd /home/pi
23 verbose Linux 4.14.69-v7+
24 verbose argv "/usr/bin/node" "/usr/bin/npm" "install" "node-dash-button"
25 verbose node v10.10.0
26 verbose npm v6.4.1
27 error code 128
28 error Command failed: /usr/bin/git submodule update -q --init --recursive

I've tried with node v8.10.0 and v10.10.0
npm version is 6.4.1

sudo apt list --installed | grep libpcap:
libpcap-dev/stable,now 1.8.1-3 all [installed]
libpcap0.8/stable,now 1.8.1-3 armhf [installed]
libpcap0.8-dbg/stable,now 1.8.1-3 armhf [installed]
libpcap0.8-dev/stable,now 1.8.1-3 armhf [installed]
libpcapnav0/stable,now 0.8-3 armhf [installed]
libpcapnav0-dev/stable,now 0.8-3 armhf [installed]

I've also tried to start from scratch - no difference

Not detecting dash button press on OSX

I have followed the instructions to setup the button (it blinks white now, indicating it connects to the wifi network)

But the dash hardware access is not detected when running sudo node bin/findbutton - Other hardware is indeed detected on the network.

I'm trying this with a brand new dash button

Feature Request: Build Exclusion List

I've found it to be very frustrating to try to isolate the proper MAC address of my Dash button—there are so many appearing, and there seems to be enough of a delay between pressing the button and a MAC address appearing that I can't figure out which one belongs to the Dash button.

I think it could be made very easy if bin/findbutton would ask you to first refrain from pressing the button for the first (say) 2 minutes, so it could gather a list of MAC addresses that it knows it can ignore. Then, once it has this list, it could ask you to press the button, but first to hit a key just before you press the button, so it knows when to start accepting new MAC addresses.

By narrowing down the time when a correct MAC address may appear, and by first building a list of known bad MAC addresses, it should be possible to make it very easy to find the correct one.

Unknown manufactorer is actually Amazon

More of an FYI than an issue... just got a dash and running the findbutton program, the dash shows as:

Possible dash hardware address detected: 18:74:2e:5c:94:53 Manufacturer: unknown Protocol: udp

It took me a while to realise this was the dash button as I was expecting Amazon to appear in the manufacturer.

I confirmed via connecting from my machine to the 'Amazon Configure Me' access point (when the dash is in "setup" mode / after a 6 second press and blue flashing light).

screen shot 2017-11-18 at 19 28 29

PR #23 not in latest version

Hey,

Im currently working on expanding and improving the pizzadash project which uses this as a dependency. I just fixed a bug using the same solution as in error #14. Id like for the users to just use npm install but that does not yet include PR #23 so the error will still exist. Could you increment the version number and push to npm?

Dan

any idea what dependancy i am missing here?

root@norah:/home/stone# npm install node-dash-button
npm http GET https://registry.npmjs.org/node-dash-button
npm http 304 https://registry.npmjs.org/node-dash-button
npm http GET https://registry.npmjs.org/underscore
npm http 304 https://registry.npmjs.org/underscore
npm http GET https://registry.npmjs.org/socketwatcher
npm http GET https://registry.npmjs.org/nan
npm http 304 https://registry.npmjs.org/nan
npm http 304 https://registry.npmjs.org/socketwatcher
npm WARN engine [email protected]: wanted: {"node":">=4"} (current: {"node":"v0.10.25","npm":"1.3.10"})

[email protected] install /home/stone/node_modules/node-dash-button/node_modules/pcap/node_modules/socketwatcher
node-gyp rebuild

gyp: Call to 'node -e "require('nan')"' returned exit status 1. while trying to load binding.gyp
gyp ERR! configure error
gyp ERR! stack Error: gyp failed with exit code: 1
gyp ERR! stack at ChildProcess.onCpExit (/usr/share/node-gyp/lib/configure.js:431:16)
gyp ERR! stack at ChildProcess.EventEmitter.emit (events.js:98:17)
gyp ERR! stack at Process.ChildProcess._handle.onexit (child_process.js:797:12)
gyp ERR! System Linux 4.2.0-27-generic
gyp ERR! command "nodejs" "/usr/bin/node-gyp" "rebuild"
gyp ERR! cwd /home/stone/node_modules/node-dash-button/node_modules/pcap/node_modules/socketwatcher
gyp ERR! node -v v0.10.25
gyp ERR! node-gyp -v v0.10.10
gyp ERR! not ok
npm WARN This failure might be due to the use of legacy binary "node"
npm WARN For further explanations, please read
/usr/share/doc/nodejs/README.Debian

npm ERR! weird error 1
npm ERR! not ok code 0

Run without sudo on OSX

Not much of an issue, but more of a documentation change. It is POSSIBLE to run without using sudo.

On OSX, all applications using libpcap use the BPF (Berkeley Packet Filter) devices (/dev/bpf*). Normally, only root has rw- access to them. With a simple change, we can permit any user on the system to use them.

# sudo chmod +r /dev/bpf*

This is probably not the smartest idea on a multiuser system. You may wish to create a group (read_bpf, for example), add yourself to it, and give that group read-permission.

Linux:

# sudo groupadd read_bpf
# sudo gpasswd -a read_bpf username
# sudo chown root.read_bpf /dev/bpf*
# sudo chmod g+r /dev/bpf*

OSX can use dscl to create groups and add users to them.

[1] http://stackoverflow.com/questions/18049306/how-to-monitor-en0-network-interface-on-a-mac-without-having-to-use-sudo

Support for Node 5.4 or 4.0?

It seems to be running fine on OSX which is v0.10.32 but on my Raspberry Pi 2 and Zero which are running 5.4 and 4.0 respectively it doesn't seem to run.

Typing in node bin/findbutton shows nothing and running the app (using sudo) just exits with no error on Pi Zero running v5.4 and gives me "/node_modules/pcap/build/Release/pcap_binding.node: invalid ELF header" on my Pi 2 running v4.0

Too many false positives

For what it's worth I realize this library is only watching ARP requests and anything more is probably beyond the scope of this project.

I post this in hopes that someone has run across the same issue and can provide insight, maybe translating to some updates to the README for future readers.

I got an Amazon Dash button yesterday and went through the setup process described in the README. Basically I did all the steps with the exception of the "select a product" step and turned off notifications on the app. Then I found my button's mac address with node bin/findbutton and wrote the following:

var dash_button = require("node-dash-button");
var dash = dash_button(DASH_BTN_MAC, "en0", 60000);

dash.on("detected", function (dash_id) {
    console.log(new Date().toString() + "Dash button was clicked!");
});

That worked great. When I clicked the button the light flashed and registered the console message.

I made sure to specify a timeout to "debounce" (1min) the call and made sure to specify the network interface just to be explicit.

I left the app running for a couple of hours and saw this in the logs:

$ sudo node app.js 
Sat Jun 18 2016 17:21:29 GMT-0500 (CDT)Dash button was clicked!
Sat Jun 18 2016 17:26:30 GMT-0500 (CDT)Dash button was clicked!
Sat Jun 18 2016 17:36:30 GMT-0500 (CDT)Dash button was clicked!
Sat Jun 18 2016 17:41:30 GMT-0500 (CDT)Dash button was clicked!
Sat Jun 18 2016 17:46:30 GMT-0500 (CDT)Dash button was clicked!
Sat Jun 18 2016 17:51:30 GMT-0500 (CDT)Dash button was clicked!
Sat Jun 18 2016 17:56:30 GMT-0500 (CDT)Dash button was clicked!
Sat Jun 18 2016 18:01:30 GMT-0500 (CDT)Dash button was clicked!
Sat Jun 18 2016 18:06:30 GMT-0500 (CDT)Dash button was clicked!
Sat Jun 18 2016 18:16:30 GMT-0500 (CDT)Dash button was clicked!
Sat Jun 18 2016 18:21:30 GMT-0500 (CDT)Dash button was clicked!
Sat Jun 18 2016 18:22:23 GMT-0500 (CDT)Dash button was clicked!
Sat Jun 18 2016 18:26:30 GMT-0500 (CDT)Dash button was clicked!
Sat Jun 18 2016 18:36:30 GMT-0500 (CDT)Dash button was clicked!
Sat Jun 18 2016 18:41:30 GMT-0500 (CDT)Dash button was clicked!
Sat Jun 18 2016 18:46:30 GMT-0500 (CDT)Dash button was clicked!
Sat Jun 18 2016 18:56:30 GMT-0500 (CDT)Dash button was clicked!
Sat Jun 18 2016 19:01:30 GMT-0500 (CDT)Dash button was clicked!
Sat Jun 18 2016 19:06:30 GMT-0500 (CDT)Dash button was clicked!
Sat Jun 18 2016 19:16:30 GMT-0500 (CDT)Dash button was clicked!
Sat Jun 18 2016 19:21:30 GMT-0500 (CDT)Dash button was clicked!
Sat Jun 18 2016 19:26:30 GMT-0500 (CDT)Dash button was clicked!
Sat Jun 18 2016 19:36:30 GMT-0500 (CDT)Dash button was clicked!
Sat Jun 18 2016 19:46:30 GMT-0500 (CDT)Dash button was clicked!
Sat Jun 18 2016 19:51:30 GMT-0500 (CDT)Dash button was clicked!
Sat Jun 18 2016 20:01:30 GMT-0500 (CDT)Dash button was clicked!
Sat Jun 18 2016 20:05:40 GMT-0500 (CDT)Dash button was clicked!
Sat Jun 18 2016 20:06:30 GMT-0500 (CDT)Dash button was clicked!
Sat Jun 18 2016 20:11:30 GMT-0500 (CDT)Dash button was clicked!
Sat Jun 18 2016 20:11:54 GMT-0500 (CDT)Dash button was clicked!
Sat Jun 18 2016 20:16:30 GMT-0500 (CDT)Dash button was clicked!
Sat Jun 18 2016 20:20:47 GMT-0500 (CDT)Dash button was clicked!
Sat Jun 18 2016 20:21:30 GMT-0500 (CDT)Dash button was clicked!
Sat Jun 18 2016 20:26:30 GMT-0500 (CDT)Dash button was clicked!
Sat Jun 18 2016 20:27:48 GMT-0500 (CDT)Dash button was clicked!
Sat Jun 18 2016 20:31:30 GMT-0500 (CDT)Dash button was clicked!
Sat Jun 18 2016 20:41:30 GMT-0500 (CDT)Dash button was clicked!
Sat Jun 18 2016 20:46:30 GMT-0500 (CDT)Dash button was clicked!
Sat Jun 18 2016 20:51:30 GMT-0500 (CDT)Dash button was clicked!
Sat Jun 18 2016 20:54:34 GMT-0500 (CDT)Dash button was clicked!

None of those events were cause by manually clicking the button, it looks like it's trying to reach out to the server every 5 minutes (?).

I'm wondering if anyone has run into this or has any insight with regards to dealing with false positives?

I'm using node v6.2.1, npm 3.9.3 and node-dash-button 0.5.0 on a mac mini running OS X 10.11.5.

API Revision possibilities

looking to revise the API in 2 of the following possible ways. This way when watching for multiple dashes you only need one PCAP session.

dash_button = require('node-dash-button');
var dash = dash_button(["8f:3f:20:33:54:44","2e:3f:20:33:54:22"]); //address from step above
dash.on("8f:3f:20:33:54:44", function (){
    console.log("omg found");
});
dash.on("2e:3f:20:33:54:22", function (){
    console.log("omg found the other one!");
});

or

dash_button = require('node-dash-button');
var dash = dash_button(["8f:3f:20:33:54:44","2e:3f:20:33:54:22"]); //address from step above
dash.on("detected", function (dash_id){
    if (dash_id == "8f:3f:20:33:54:44"){
        console.log("omg found");
    } else if (dash_id == "2e:3f:20:33:54:22"){
        console.log("found the other!");
    }
});

I would also keep the dash.register method to add any additional

I would be open to feedback on which one would be better to use. I am thinking the first is better, but the second would allow me to keep the original API intact.

Dash button still contacts amazon

Hi, I followed a tutorial on using your library to make a shut down button for the raspberry pi. It works perfectly but after restarting the pi, it still contacts amazon and I get a popup from the amazon app on my phone telling me I need to set up my button. Is this intended or a bug? Thanks and great work on the library!

Spurious and delayed events with multiple buttons

I have registered for the event for 3 buttons by passing an array of mac addresses (code below).
I often see one or more of the following (often in combination)

  • an extra spurious event for the previous button
  • an event not firing until the next button is pressed
  • latency of 1 or more minutes (I've seen up to 5 minutes delay)

Example scenario from my real testing

  • Press Button 1 => I see the event for Button 1
  • Wait 1 minute
  • Press Button 2 => I see another event for Button 1 (but no event for Button 2)
  • Wait 1 minute
  • Press Button 3, I see an event to Button 2 (but no event for Button 3)
  • Wait 2 minutes
  • I see an event for Button 3

Another scenario from my real testing

  • Press Button 1 => I see the event for Button 1
  • Wait 1 minute
  • Press Button 2 => I see another event for Button 1 and an event for Button 2
  • Wait 1 minute
  • Press Button 3 => I see another event to Button 2 and and event for Button 3
  • Wait 1 minute
  • Press Button 1 => I do not see any event for Button 1
  • Wait 1 minute
  • Event for Button 1 appears (delayed by 1 minute)
  • Wait 1 minute
  • Press Button 2 => I see an event for Button 2 within 5 seconds
  • Wait 2 minutes
  • I see another event for Button 2 out of the blue

Any idea what's going on?
I am running inside an ubuntu 16.04 (xenial) chroot on an Asus Chromebook C302, with node version 8.3.0.

var b_wilkinson = 'b4:7c:9c:92:26:5b';
var b_attack = '34:d2:70:9d:60:31';
var b_genki = 'b4:7c:9c:31:e0:9d';

var dash = dash_button([b_wilkinson, b_attack, b_genki], 'wlan0', '3000', 'udp');

dash.on("detected", function (dash_id){
  if (dash_id === b_wilkinson) {
    console.log("*** WILKINSON ***");
  } else if (dash_id === b_attack) {
    console.log("*** ATTACK ***");
  } else if (dash_id === b_genki) {
    console.log("*** GENKI ***");
  }
  console.log("  detected at " + new Date().toLocaleString());
});`

Can't maintain a solidified connection

Here is output of running an app consistently for a handful of minutes. My first though is that the server looses connectivity to the network due to WiFi issues or something and then it can't gracefully recover, you have to reboot the app to get it working again.

master => ~/GitHub/pizzadash/ npm start

> [email protected] start /Users/brodyberson/GitHub/pizzadash
> sudo node app.js

node_pcap: EthernetFrame() - Don't know how to decode ethertype 34958
node_pcap: EthernetFrame() - Don't know how to decode ethertype 34958
node_pcap: EthernetFrame() - Don't know how to decode ethertype 34958
node_pcap: EthernetFrame() - Don't know how to decode ethertype 34958

Can't find the dash button using the libpcap library

I'm having trouble trying to capture my dash button using "findbutton", but I know it works since it discovers another random iot device in my house every minute. I ruled out the device being the issue since I was able to see it using wireshark from the same linux mint vm (packet: AmazonTe_27:9f:69 (f0:27:2d:27:9f:69)).

Just to make sure it wasn't the configuration that was the issue, I changed the mac address to the device I mentioned above and it successfully connected and printed a message when the device connected (using dash-rickroll).

npm install fails while compiling cpp sources

I have a archlinux installation, all packages up-to-date,
and I cannot install node-dash-button from npm repo or github source checkout.

Is there any dependency outdated?

please see attached compile log output:

$ LC_ALL=C npm install node-dash-button 2>&1 | tee install.log
> [email protected] install /home/feedc0de/dashbuttons/node_modules/socketwatcher
> node-gyp rebuild

make: Entering directory '/home/feedc0de/dashbuttons/node_modules/socketwatcher/build'
  CXX(target) Release/obj.target/socketwatcher/socket_watcher.o
In file included from ../socket_watcher.hpp:8,
                 from ../socket_watcher.cpp:5:
../../nan/nan.h: In function 'void Nan::AsyncQueueWorker(Nan::AsyncWorker*)':
../../nan/nan.h:2298:62: warning: cast between incompatible function types from 'void (*)(uv_work_t*)' {aka 'void (*)(uv_work_s*)'} to 'uv_after_work_cb' {aka 'void (*)(uv_work_s*, int)'} [-Wcast-function-type]
 2298 |     , reinterpret_cast<uv_after_work_cb>(AsyncExecuteComplete)
      |                                                              ^
../socket_watcher.cpp: In static member function 'static void SocketWatcher::Initialize(v8::Local<v8::Object>)':
../socket_watcher.cpp:29:36: error: no matching function for call to 'v8::FunctionTemplate::GetFunction()'
   29 |   constructor.Reset(t->GetFunction());
      |                                    ^
In file included from /home/feedc0de/.cache/node-gyp/12.12.0/include/node/node.h:63,
                 from ../../nan/nan.h:54,
                 from ../socket_watcher.hpp:8,
                 from ../socket_watcher.cpp:5:
/home/feedc0de/.cache/node-gyp/12.12.0/include/node/v8.h:5995:46: note: candidate: 'v8::MaybeLocal<v8::Function> v8::FunctionTemplate::GetFunction(v8::Local<v8::Context>)'
 5995 |   V8_WARN_UNUSED_RESULT MaybeLocal<Function> GetFunction(
      |                                              ^~~~~~~~~~~
/home/feedc0de/.cache/node-gyp/12.12.0/include/node/v8.h:5995:46: note:   candidate expects 1 argument, 0 provided
../socket_watcher.cpp:30:75: error: no matching function for call to 'v8::FunctionTemplate::GetFunction()'
   30 |   exports->Set(Nan::New("SocketWatcher").ToLocalChecked(), t->GetFunction());
      |                                                                           ^
In file included from /home/feedc0de/.cache/node-gyp/12.12.0/include/node/node.h:63,
                 from ../../nan/nan.h:54,
                 from ../socket_watcher.hpp:8,
                 from ../socket_watcher.cpp:5:
/home/feedc0de/.cache/node-gyp/12.12.0/include/node/v8.h:5995:46: note: candidate: 'v8::MaybeLocal<v8::Function> v8::FunctionTemplate::GetFunction(v8::Local<v8::Context>)'
 5995 |   V8_WARN_UNUSED_RESULT MaybeLocal<Function> GetFunction(
      |                                              ^~~~~~~~~~~
/home/feedc0de/.cache/node-gyp/12.12.0/include/node/v8.h:5995:46: note:   candidate expects 1 argument, 0 provided
../socket_watcher.cpp: In static member function 'static void SocketWatcher::Callback(uv_poll_t*, int, int)':
../socket_watcher.cpp:77:60: warning: 'v8::Local<v8::Value> Nan::MakeCallback(v8::Local<v8::Object>, v8::Local<v8::Function>, int, v8::Local<v8::Value>*)' is deprecated [-Wdeprecated-declarations]
   77 |   Nan::MakeCallback(watcher->handle(), callback, argc, argv);
      |                                                            ^
In file included from ../socket_watcher.hpp:8,
                 from ../socket_watcher.cpp:5:
../../nan/nan.h:1024:46: note: declared here
 1024 |   NAN_DEPRECATED inline v8::Local<v8::Value> MakeCallback(
      |                                              ^~~~~~~~~~~~
../socket_watcher.cpp:77:60: warning: 'v8::Local<v8::Value> Nan::MakeCallback(v8::Local<v8::Object>, v8::Local<v8::Function>, int, v8::Local<v8::Value>*)' is deprecated [-Wdeprecated-declarations]
   77 |   Nan::MakeCallback(watcher->handle(), callback, argc, argv);
      |                                                            ^
In file included from ../socket_watcher.hpp:8,
                 from ../socket_watcher.cpp:5:
../../nan/nan.h:1024:46: note: declared here
 1024 |   NAN_DEPRECATED inline v8::Local<v8::Value> MakeCallback(
      |                                              ^~~~~~~~~~~~
../socket_watcher.cpp: In static member function 'static void SocketWatcher::Set(const Nan::FunctionCallbackInfo<v8::Value>&)':
../socket_watcher.cpp:116:32: error: no matching function for call to 'v8::Value::Int32Value()'
  116 |   int fd = info[0]->Int32Value();
      |                                ^
In file included from /home/feedc0de/.cache/node-gyp/12.12.0/include/node/node.h:63,
                 from ../../nan/nan.h:54,
                 from ../socket_watcher.hpp:8,
                 from ../socket_watcher.cpp:5:
/home/feedc0de/.cache/node-gyp/12.12.0/include/node/v8.h:2613:40: note: candidate: 'v8::Maybe<int> v8::Value::Int32Value(v8::Local<v8::Context>) const'
 2613 |   V8_WARN_UNUSED_RESULT Maybe<int32_t> Int32Value(Local<Context> context) const;
      |                                        ^~~~~~~~~~
/home/feedc0de/.cache/node-gyp/12.12.0/include/node/v8.h:2613:40: note:   candidate expects 1 argument, 0 provided
In file included from ../../nan/nan.h:54,
                 from ../socket_watcher.hpp:8,
                 from ../socket_watcher.cpp:5:
../socket_watcher.cpp: At global scope:
/home/feedc0de/.cache/node-gyp/12.12.0/include/node/node.h:560:43: warning: cast between incompatible function types from 'void (*)(v8::Local<v8::Object>)' to 'node::addon_register_func' {aka 'void (*)(v8::Local<v8::Object>, v8::Local<v8::Value>, void*)'} [-Wcast-function-type]
  560 |       (node::addon_register_func) (regfunc),                          \
      |                                           ^
/home/feedc0de/.cache/node-gyp/12.12.0/include/node/node.h:594:3: note: in expansion of macro 'NODE_MODULE_X'
  594 |   NODE_MODULE_X(modname, regfunc, NULL, 0)  // NOLINT (readability/null_usage)
      |   ^~~~~~~~~~~~~
../socket_watcher.cpp:143:1: note: in expansion of macro 'NODE_MODULE'
  143 | NODE_MODULE(socketwatcher, Init)
      | ^~~~~~~~~~~
In file included from /home/feedc0de/.cache/node-gyp/12.12.0/include/node/node.h:63,
                 from ../../nan/nan.h:54,
                 from ../socket_watcher.hpp:8,
                 from ../socket_watcher.cpp:5:
/home/feedc0de/.cache/node-gyp/12.12.0/include/node/v8.h: In instantiation of 'void v8::PersistentBase<T>::SetWeak(P*, typename v8::WeakCallbackInfo<P>::Callback, v8::WeakCallbackType) [with P = node::ObjectWrap; T = v8::Object; typename v8::WeakCallbackInfo<P>::Callback = void (*)(const v8::WeakCallbackInfo<node::ObjectWrap>&)]':
/home/feedc0de/.cache/node-gyp/12.12.0/include/node/node_object_wrap.h:84:78:   required from here
/home/feedc0de/.cache/node-gyp/12.12.0/include/node/v8.h:10004:16: warning: cast between incompatible function types from 'v8::WeakCallbackInfo<node::ObjectWrap>::Callback' {aka 'void (*)(const v8::WeakCallbackInfo<node::ObjectWrap>&)'} to 'Callback' {aka 'void (*)(const v8::WeakCallbackInfo<void>&)'} [-Wcast-function-type]
10004 |                reinterpret_cast<Callback>(callback), type);
      |                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/feedc0de/.cache/node-gyp/12.12.0/include/node/v8.h: In instantiation of 'void v8::PersistentBase<T>::SetWeak(P*, typename v8::WeakCallbackInfo<P>::Callback, v8::WeakCallbackType) [with P = Nan::ObjectWrap; T = v8::Object; typename v8::WeakCallbackInfo<P>::Callback = void (*)(const v8::WeakCallbackInfo<Nan::ObjectWrap>&)]':
../../nan/nan_object_wrap.h:65:61:   required from here
/home/feedc0de/.cache/node-gyp/12.12.0/include/node/v8.h:10004:16: warning: cast between incompatible function types from 'v8::WeakCallbackInfo<Nan::ObjectWrap>::Callback' {aka 'void (*)(const v8::WeakCallbackInfo<Nan::ObjectWrap>&)'} to 'Callback' {aka 'void (*)(const v8::WeakCallbackInfo<void>&)'} [-Wcast-function-type]
make: *** [socketwatcher.target.mk:105: Release/obj.target/socketwatcher/socket_watcher.o] Error 1
make: Leaving directory '/home/feedc0de/dashbuttons/node_modules/socketwatcher/build'
gyp ERR! build error 
gyp ERR! stack Error: `make` failed with exit code: 2
gyp ERR! stack     at ChildProcess.onExit (/usr/lib/node_modules/node-gyp/lib/build.js:194:23)
gyp ERR! stack     at ChildProcess.emit (events.js:210:5)
gyp ERR! stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:272:12)
gyp ERR! System Linux 5.3.5-arch1-1-ARCH
gyp ERR! command "/usr/bin/node" "/usr/lib/node_modules/node-gyp/bin/node-gyp.js" "rebuild"
gyp ERR! cwd /home/feedc0de/dashbuttons/node_modules/socketwatcher
gyp ERR! node -v v12.12.0
gyp ERR! node-gyp -v v6.0.0
gyp ERR! not ok 
npm WARN enoent ENOENT: no such file or directory, open '/home/feedc0de/dashbuttons/package.json'
npm WARN dashbuttons No description
npm WARN dashbuttons No repository field.
npm WARN dashbuttons No README data
npm WARN dashbuttons No license field.

npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] install: `node-gyp rebuild`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the [email protected] install script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/feedc0de/.npm/_logs/2019-10-14T21_59_31_630Z-debug.log

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.