GithubHelp home page GithubHelp logo

t2-cli's People

Contributors

alwasa0b avatar at-jdudley avatar codetriage-readme-bot avatar crvineeth97 avatar dbuentello avatar dependabot-preview[bot] avatar flaki avatar frijol avatar hipsterbrown avatar hoegertn avatar jiahuang avatar johnnyman727 avatar kwyn avatar linusu avatar majgis avatar mattsoftware avatar mrnice avatar nplus11 avatar rwaldron avatar ryanplusplus avatar samlandfried avatar scottgonzalez avatar snyk-bot avatar student007 avatar tcr avatar thojansen avatar tikurahul avatar tobbe avatar wprater avatar wyze 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

t2-cli's Issues

Occasional error about not being connected to remote Tessel

Every once in a while, I receive an error that a process is attempting to exec before the SSH process is opened:

INFO Connected over LAN. IP ADDRESS: 192.168.128.149
Unhandled rejection Error: Not connected
    at Client.exec (/Users/Jon/Work/technical/t2-cli/node_modules/ssh2/lib/client.js:544:11)
    at LANConnection.exec (/Users/Jon/Work/technical/t2-cli/lib/lan_connection.js:39:12)
    at stopRunningScript (/Users/Jon/Work/technical/t2-cli/lib/tessel/deploy.js:51:16)
    at Tessel.deployScript (/Users/Jon/Work/technical/t2-cli/lib/tessel/deploy.js:25:3)
    at /Users/Jon/Work/technical/t2-cli/lib/controller.js:173:14
    at tryCatcher (/Users/Jon/Work/technical/t2-cli/node_modules/bluebird/js/main/util.js:24:31)
    at Promise._settlePromiseFromHandler (/Users/Jon/Work/technical/t2-cli/node_modules/bluebird/js/main/promise.js:454:31)
    at Promise._settlePromiseAt (/Users/Jon/Work/technical/t2-cli/node_modules/bluebird/js/main/promise.js:530:18)
    at Promise._settlePromises (/Users/Jon/Work/technical/t2-cli/node_modules/bluebird/js/main/promise.js:646:14)
    at Async._drainQueue (/Users/Jon/Work/technical/t2-cli/node_modules/bluebird/js/main/async.js:79:16)
    at Async._drainQueues (/Users/Jon/Work/technical/t2-cli/node_modules/bluebird/js/main/async.js:89:10)
    at Async.drainQueues (/Users/Jon/Work/technical/t2-cli/node_modules/bluebird/js/main/async.js:14:14)
    at process._tickCallback (node.js:355:11)

Improve user experience of `tessel list`

Currently, the tessel list command waits an arbitrary number of seconds while searching for Tessels on the LAN. This should be changed so that USB Tessels are returned immediately and asynchronously from the LAN Tessels and the LAN Tessels should be returned faster than 2 seconds.

t2 rename

Current status: no such command

Spec: T2 CLI spec
tessel rename [-r | --reset]

Names the Tessel by changing the hostname of the device. Name restrictions found here: http://en.wikipedia.org/wiki/Hostname#Restrictions_on_valid_host_names

$ tessel rename
> Usage: tessel rename <name> [-r | --reset] [--help]
>  name:        the name to rename the currently selected tessel
>  -r | --reset:    reset the name of the device
$ 

$ tessel rename Jigglypuff
> Changed name of device Tessel-0123456789ab to Jigglypuff
$ 

$ tessel rename Snorlax
> Changed name of device Jigglypuff to Snorlax
$ 

$ tessel rename --reset
> Reset the name of device to Tessel-0123456789ab
$ 
  • rename
  • reset name to MAC address
  • make sure hostname is valid based on hostname restrictions

getTessel fails if there are no USB or no LAN Tessels

There are a couple of issues with getTessel (that, frankly, I should have caught in my last code review).

First, I believe the lan.findConnections and usb.findConnection functions in the Promise.join need to be invoked with parenthesis.

Second, Promise.join returns two arrays and those need to be consolidated.

Set up proper installation

Currently, you have to manage a config file in this repo to be able to connect to a Tessel 2 remotely. We should be able to get up and running with Tessel over USB (like sending SSH keys over to the device).

Generate an ssh key for a tessel user and store it in a tessel specific folder (like ~/.tessel on OSX). When a Prime is plugged in via USB, transfer that ssh key to the Tessel under a 'tessel' account.

Refactor all communication into abstract "Connection" object

We want to have a clean abstraction for communication between a host computer and Tessel 2. Because they can connect over USB or SSH (WiFi), it would be much simpler to provide a "Connection" object which handles the actual transfer of data.

t2 root

Current status: no such command

Spec: T2 CLI spec
tessel root [-i ]

Provides access to the underlying Linux system running on Tessel 2: exactly SSH (copies regular SSH keys to authorize and SSHes in as Linux computer)

$ tessel root --help
> Usage: tessel root [-i <path>] [--help]
>  -i <path>:   provide a path to the desired ssh key
$ 

$ tessel root
> Accessing root...
[email protected] # 

t2 help command

Current status: no such command

Spec: T2 CLI spec
tessel [--help | -h]
Prints out all the commands and what they do (usage)

$ tessel
> tessel <command> [--help]
>   help        prints usage. Add ‘--help’ after any command for more info
>   init        initialize the current directory as your working directory
>   list        list nearby tessel devices
>   select      choose which tessel you want to interact with
>   name        change the hostname of the selected tessel
>   erase       erase code pushed to flash
>   logs        display the console.logs from the currently running process
>   push        push a file to flash to be run anytime tessel is powered
>   root        provides access to the underlying linux system on board
>   run     run a file in RAM immediately
>   status      get the current status of the selected tessel
>   update      update the selected tessel to latest firmware build
>   wap     create a wireless access point on the selected tessel
>   wifi        configure wifi connection on the selected tessel
$

$ tessel --help
> tessel <command> [--help]
> ...
$ 

stdin.end can close the remote stdin before the write is complete

This is an issue on the jon-usb branch.

Currently, if a new process is created and then immediately writes and closes stdin, the bundle will not be written in its entirety.

tessel.connection.exec(someBashCommand, function(err, remoteProcess) {
  // Not all of someBundle will be written
  remoteProcess.stdin.end(someBundle);
});

That's because the USBDaemon on Tessel 2 may not have sent an acknowledgement that it can receive data on stdin yet. So when the _write function is called internally by the stdin Node stream, the data is placed in the backPressure Buffer and the callback is called right away. Once the callback is called, the finish event is fired and the CLI tells the daemon to close stdin. Meanwhile, that bundle is still sitting in the backPressure buffer.

Make help flags display .help from nomnom

Each command in tessel-2.js has a .help option, e.g.:

parser.command('push')
  .callback(function(opts) {
    // true: push=true
    controller.deployScript(opts, true)
      .catch(function (err) {
        if(err instanceof Error){
          throw err;
        }
        tessel.logs.warn(err);
        process.exit(1);
      });
  })
  .option('name', nameOption)
  .option('entryPoint', {
    position: 1,
    required: true,
    help: 'the entry point file to deploy to Tessel'
  })
  .option('verbose', {
    flag : true,
    abbr: 'v',
    help: 'choose to view more debugging information'
  })
  .help('Deploy a script to memory on Tessel and run it with Node whenever Tessel boots up.');

They're not really being used. When you call tessel push -h, it should print out Deploy a script to memory on Tessel and run it with Node whenever Tessel boots up.. But instead it just gives you the generic Usage: t2 <command>.

This should work on flags, too, e.g. tessel push -entryPoint -h should print the entry point file to deploy to Tessel.

t2 list

Current status:

  • prints out USB devices and LAN devices
  • takes a timeout flag
  • shows authorization status of tessels
  • doesn't show which tessel is selected

Spec: T2 CLI spec
tessel list

Lists all connected tessels. Shows which tessel is selected and authorization status of each tessel.

Find default per #93

# Help command example
$ tessel list --help
> Lists all connected tessels. Shows which tessel is selected and authorization status of each tessel.
$ 

# Single Tessel found example
$ tessel list
> Searching for nearby Tessels...
>           Jigglypuff    USB
$ 

# Same Tessel with both USB and LAN connections
$ tessel list
> Searching for nearby Tessels...
>           Jigglypuff    USB
>           Jigglypuff    LAN
$ 

# Many Tessels available
$ tessel list
> Searching for nearby Tessels…
>            Rafael        LAN
>            Bulbasaur     USB       (run `tessel provision` to authorize)
>            Mewcat        LAN       (USB connect and run `tessel provision` to authorize)
>            Jigglypuff    USB
>            Jigglypuff    LAN
>
> Multiple Tessels found. Will default to Bulbasaur.
> Set default Tessel with environment variable (e.g. export TESSEL=Bulbasaur) or use the --name flag.
$ 

# No Tessels available
$ tessel list
> Searching for nearby tessels...
> ERR! No Tessels Found
$

Option: tessel list -t to set a timeout

To do:

  • Change functionality to display both authorized and unauthorized devices
  • Change printout style to match spec (layout, connection, authorization, hostname)
  • Remove timeout flag
  • Show which tessel is selected
  • Make help flag match spec

t2 run needs flags

Current status: t2 run <index.js> will push index.js to RAM and run it immediately.

Spec: T2 CLI spec
tessel run <index.js> [--lan | --usb]

Run the file in RAM immediately

$ tessel run --help
>
> Usage: /usr/local/bin/iojs t2 run <entryPoint> [options]
>
> entryPoint     The entry point file to deploy to Tessel
>
> Options:
>    --name NAME     The name of the tessel on which the command will be executed
>    --lan           Use LAN connection
>    --usb           Use USB connection
>    -v, --verbose   Choose to view more debugging information
>
> Deploy a script to Tessel and run it with Node

$ tessel run index.js
> Writing index.js to RAM on Mewcat (16kB)...
> Deployed.
> Running index.js...
> Hello world!
$ 

To do:

  • Create --help flag
  • Create --lan and --usb flags and make code push over the specified connection

Finish CLI design

CLI is under design. This needs to be finalized and codified into issues.

Design completeness of commands:

  • tessel provision: #64
  • tessel [-h | --help]: #65
  • tessel init: #76
  • tessel rename: #77
  • tessel erase: #78
  • tessel run: #79
  • tessel root: #80
  • tessel update: #81
  • tessel wifi: #82
  • tessel logs: #88
  • tessel select: #93
  • tessel push: #91
  • tessel ap: #87
  • tessel status: #95
  • tessel list: #86

Incomplete CLI spec

I don't think the CLI spec lists all the commands we're planning to provide. What is missing?

E.g. something like tessel wap --start turns tessel into a wireless access point

(Moved here from #5)

Unit Test Suite

We really need a test bench with the CLI that will test all available commands over USB and over SSH. Currently, we've been just running all commands we can think of manually and it's not good. This is critical for making a CLI that will scale.

I think the first task is to break up all of the commands into a parsable JSON file so they can be gobbled up by the test runner.

  • Listing Available Tessels
  • Listing Available WiFi Networks
  • Connecting to a WiFi Network
  • Running Code
  • Pushing Code
  • Erasing Pushed Code
  • Renaming
  • Provision

t2 wifi needs filling out

Current status:

  • tessel wifi -l lists networks
  • tessel wifi -n -p copies the wifi network into the configuration file, but doesn't check to see if the network/password are valid or if we connect

Spec: T2 CLI spec
tessel wifi

$ tessel wifi -h
> Usage: tessel wifi [-l] [-n <ssid>] [-p <pass>] [-s <security>] [--off] [-t]
>  -l:          list available networks
>  -n <ssid>:   name of the network to connect with
>  -p <pass>:   password to access network
>  -s <security>:   security protocol to connect with (i.e. WEP, WPA, PSK)
>  -t:          attempt to connect for the provided number of seconds
>  --off:       disconnect from a wifi connection
$ 

$ tessel wifi
> Connected to "technicallyWifi"
> IP Address: 192.168.128.149
> Signal Strength: 27/70
> Bitrate: 145mbps up / 24 mbps down

$ tessel wifi
> Not Connected (run 'tessel wifi -l' to see available networks)

$ tessel wifi -l
> INFO Requesting wifi status...
> Currently visible networks (10):
>   Gaumenkitzel (47/127)
>   XFBSECA7HE6H (30/127)
>   HP-Print-8f-LaserJet 200 color (49/127)
>   technicallyWifi (40/127)
>   tessel (38/127)
>   KeetsaBerkeley (37/127)
>   ATT219_EXT (38/127)
>   xfinitywifi (38/127)
>   CableWiFi (32/127)
>   Max4 (30/127)

$ tessel wifi -n test-network
> Connecting to network “test-network”...
> Connected to network “test-network”
$ 

$ tessel wifi -n test-network -p super-secret
> Connecting to network “test-network”...
> Failed to connect to “test-network” (ssid or password incorrect)
$ tessel wifi -n test-network -p secret
> Connecting to network “test-network”...
> Connected to network “test-network”
$ 

$ tessel wifi -n test-network -p secret -s WPA
> Connecting to network “test-network”...
> Connected to network “test-network”
$ 

$ tessel wifi -n test-network -t 1
> Connecting to network “test-network”...
> Failed to connect to “test-network” (timeout)
$

$ tessel wifi --list
> Currently connected to “test-network”
> Scanning for wifi connections...
>  technicallyWifi (67/75)
>  test-network (65/75) [connected]
>  Gaumenkitzel (33/75)
$

To do:

  • tessel wifi
  • tessel wifi --help
  • -s flag
  • -t flag
  • --off flag
  • check whether network/password authenticate and whether the Tessel connects
  • Show connection status, IP address, signal strength, bitrate

Merge changes from jon-export-v2 branch of original cli and release new module

Currently, the V2 CLI has a dependency on a branch of the V1 CLI. That needs to be surfaced into an npm release.

For now the workaround is to:

// Clone the CLI if you haven't already, outside the v2-cli repo
git clone [email protected]:tessel/cli.git
// Checkout the relevant branch
git checkout jon-export-v2
// Make this repo linkable
npm link --local

// Within the v2-cli repo, install all deps
npm install
// Delete the tessel cli module downloaded from npm
rm -rf node_modules/tessel
// Link it to the checked out branch
npm link tessel

t2 erase console.logs edit

Current status: erases everything in /app folder

Spec: T2 CLI spec
tessel erase

Erases files pushed to Flash using the tessel push command.

$ tessel erase --help
> Erases files pushed to Flash using the tessel push command.
$ 

$ tessel erase
> Erasing files from flash...
> Files erased
$ 

To do:

  • console.log edit to match spec
  • --help flag

t2 ap

Current status: no such command

Spec: T2 CLI spec
tessel ap [-n ] [-p ] [-s ] [on | off]

Creates a wireless access point.

$ tessel ap
> Usage: tessel ap [-n <ssid>] [-p <pass>] [-s <security>] [on | off]
>  -n <ssid>:      name of the network
>  -p <pass>:      password to access network
>  -s <security>:  encryption to use on network (i.e. WEP, WPA, PSK)
>  on:             bring up an access point that’s turned off
>  off:            turn off the access point
$

$ tessel ap -n test-network
> Created access point “test-network”
$ 

$ tessel ap off
> Turned off access point “test-network”
$ 

$ tessel ap -n test-network -p secret
> Created password protected access point “test-network”
$ 

$ tessel ap -n test-network -p secret -s WPA
> Created password protected access point “test-network” secured with WPA
$ 

$ tessel ap off
> Turned off access point “test-network”
$ tessel ap on
> Turned on access point “test-network”
$ 

t2 init needs console.logs

Current status: t2 init creates a package.json and index.js containing Hello World example.

T2 CLI spec
To match spec, it needs:

  • --help command
  • console.logs when running
$ tessel init --help
> Usage: tessel init [dir] [--help]
>  dir: initialize in the provided directory
$ 


$ tessel init
> Initializing tessel repository...
> Created package.json.
> Wrote “Hello World” to index.js.
$ 

t2 provision

command t2 provision T2 CLI spec: A silent command (not exposed in CLI): [ONLY WORKS OVER USB] creates a .tessel folder with ssh keys in your home directory and uses those ssh keys to authorize you to push code to the USB-connected Tessel

Current status:

  • t2 setup is a callable command
  • creates a .tessel folder in computer's home directory containing an ssh keypair
  • copies public key from ~/.tessel into tessel's /etc/dropbear/authorized_keys, thus authorizing the given computer to program that tessel over SSH
  • Change name to 'provision' #101

Remaining issues:

  • Needs to work on Windows as well (see #147)
  • Needs error message if you try to call it over SSH: "Connect via USB to use tessel provision" #111

`tessel status` spec

Do we have a format planned for all of the information this is supposed to provide, or any -tags to make this interaction cleaner?

(Moved here from #5)

`tessel wifi` missing commands.

Is there a reason these are missing?

[-p PASS] connects with the given PASS
[-t TIMEOUT] connects with the given TIMEOUT
[-s SECURITY] connects using the provided SECURITY protocol

(moved here from #5)

t2 update

Current status: no such command

Spec: T2 CLI spec
tessel update [-l | --list] [-b | --build] [-f | --force]

Updates tessel to most recent build if it’s not already on that build, displays info including when tessel was last updated, when build was published

$ tessel update --help
> Usage: tessel update [-l | --list] [-b | --build]
>  -l | --list: show the last five builds and current build
>  -b | --build:    update to a specific build
>  -f | --force:    force tessel to update to the specified version
$ 

$ tessel update
> New firmware version found...
> Updating Bulbasaur to latest build...
> Updated Bulbasaur from v0.3.12 to v0.3.14
$ tessel update
> Bulbasaur is already on the latest firmware build. You can force an update with “tessel update --force”
$ 

$ tessel update -b
> Usage: tessel update -b <build_number>
> Example: “tessel update -b 0.3.12”
> tessel update -b 0.3.12
> Updating Bulbasaur to v0.3.12...
> Updated Bulbasaur to v0.3.12
$ 

$ tessel update -l
> Latest builds:
>  v0.3.14 Published 04/1/2015 03:35:57
>  v0.3.13
>  v0.3.12 Bulbasaur last updated 03/31/2015 08:22:03
>  v0.3.11
>  v0.3.10
>  v0.3.09
$ tessel update
> New firmware version found...
> Updating Bulbasaur to latest build...
> Updated Bulbasaur from v0.3.12 to v0.3.14
$ tessel update -l
> Latest builds:
>  v0.3.14 Bulbasaur last updated 03/31/2015 08:22:03 to latest firmware
>  v0.3.13
>  v0.3.12 
>  v0.3.11
>  v0.3.10
>  v0.3.09
$ 
  • update to latest build
  • list builds
  • update to specific build

tessel list can show two of the same Tessel using mDNS

Currently, I am picking up two instances of the same Tessel when running tessel list. The objects returned by the mdns-js library look like this (where the only difference is the networkInterface and interfaceIndex fields:

update { addresses: [ '172.20.10.16' ],
  query: [ '_tessel._tcp.local' ],
  type:
   [ { name: 'tessel',
       protocol: 'tcp',
       subtypes: [],
       description: undefined } ],
  port: 22,
  fullname: 't2._tessel._tcp.local',
  txt: [ '' ],
  host: 't2.local',
  interfaceIndex: 0,
  networkInterface: 'en0' }


update { addresses: [ '172.20.10.16' ],
  query: [ '_tessel._tcp.local' ],
  type:
   [ { name: 'tessel',
       protocol: 'tcp',
       subtypes: [],
       description: undefined } ],
  port: 22,
  fullname: 't2._tessel._tcp.local',
  txt: [ '' ],
  host: 't2.local',
  interfaceIndex: 1,
  networkInterface: 'en4' }

I'm not sure exactly what those fields indicate and whether or not this is an issue with the mdns implementation on the T2 or should just be accounted for in the CLI.

Implement `tessel push`

This should work essentially the same as tessel run except the file needs to be placed in a folder that won't be overwritten on power cycle and we need to add an "init.d" script to run node on the folder on startup.

tessel logs

Current status: no such command

Spec: T2 CLI spec
tessel logs [-n ] [-t | --tail] [stdout | stderr]

Lists the recent activity and console.logs (100 lines default) from the running program

$ tessel logs --help
> Usage: tessel logs [-n <lines>] [-t | --tail] [--help]
>  -n:          the number of lines of log to display
>  -m|--monitor:    continuously display the logs as they are updated
>  stdout|stderr:   display the logs from the specified output stream
$ 

$ tessel logs -n 2
> Bulbasaur is running index.js
> #[03/31/2015 18:10:28] This is my logggggg
> #[03/31/2015 18:10:29] Look at it!
$ 

$ tessel logs --tail
> Bulbasaur is running index.js
> #[03/31/2015 18:10:28] This is my logggggg
> #[03/31/2015 18:10:29] Look at it!
> #[03/31/2015 18:11:29] Look at it!
> #[03/31/2015 18:12:29] Look at it!
> #[03/31/2015 18:13:29] Look at it!
> #[03/31/2015 18:14:29] Look at it!
> #[03/31/2015 18:15:29] Look at it!
> #[03/31/2015 18:16:29] Look at it!
> #[03/31/2015 18:17:29] Look at it!
> #[03/31/2015 18:18:29] Look at it!
$ 

$ tessel logs -t stderr
> Bulbasaur is running index.js
> #[03/31/2015 18:10:28] Error: index.js:146 - index out of bounds yo
$ 

Can't run a script from outside the project repo.

Test Cast from within this repo:

prime run test/test-deploy-script.js

Error:

Error: ENOENT, no such file or directory '/Users/Jon/Work/technical/prime-cli/test/index.js'
    at Error (native)
    at Object.fs.lstatSync (fs.js:796:18)
    at Object.root (/Users/Jon/Work/technical/cli/node_modules/hardware-resolve/index.js:160:6)
    at Object.analyzeScript (/Users/Jon/Work/technical/cli/src/script.js:37:19)
    at /Users/Jon/Work/technical/prime-cli/lib/deploy.js:24:24
    at /Users/Jon/Work/technical/prime-cli/node_modules/ssh2/lib/client.js:1165:5
    at SSH2Stream.<anonymous> (/Users/Jon/Work/technical/prime-cli/node_modules/ssh2/lib/Channel.js:179:24)
    at SSH2Stream.emit (events.js:104:17)
    at parsePacket (/Users/Jon/Work/technical/prime-cli/node_modules/ssh2/node_modules/ssh2-streams/lib/ssh.js:3137:10)

Create the remote-deploy folder if it is missing or was deleted.

Currently, if the /tmp/remote-script folder is non-existant, the CLI will throw an error:

INFO Deploying code of size 23468 bytes ...
events.js:85
      throw er; // Unhandled 'error' event
            ^
Error: write after end
    at writeAfterEnd (_stream_writable.js:167:12)
    at Channel.Writable.write (_stream_writable.js:214:5)
    at Channel.Writable.end (_stream_writable.js:449:10)
    at /Users/Jon/Work/technical/prime-cli/lib/deploy.js:34:16
    at Parse.<anonymous> (/Users/Jon/Work/technical/cli/src/bundle.js:179:7)
    at Parse.emit (events.js:104:17)
    at Parse._streamEnd (/Users/Jon/Work/technical/cli/node_modules/tar/lib/parse.js:65:6)
    at BlockStream.<anonymous> (/Users/Jon/Work/technical/cli/node_modules/tar/lib/parse.js:51:8)
    at BlockStream.emit (events.js:104:17)
    at BlockStream._emitChunk (/Users/Jon/Work/technical/cli/node_modules/tar/node_modules/block-stream/block-stream.js:203:10)

tessel init command

We need a way for people to define the root of their project. What better way than a tessel init command? It should essentially call npm init with all of the defaults and add a few relevant tags to the package.json ("hardware", "tessel", etc.)

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.