Giter Site home page Giter Site logo

react-hardware's Introduction

React Hardware

Build Status

React Hardware enables you to build firmata-based hardware applications using a consistent developer experience based on JavaScript and React. The focus of React Hardware is on developer efficiency across all the platforms you care about - learn once, write anywhere.

React Hardware is a IoT and Robotics programming framework developed by Dustan Kasten. Being based on firmata, it is capable of providing feature parity with alternative tools such as Johnny-Five.

Note that this is currently alpha software and hasn’t been tested or have many features implemented. It currently supports firmata’s digitalWrite and analogWrite methods. Full support for firmata is coming including an event system to receive feedback from the board and manipulate state as a result of that.

Hello World

The "Hello World" program of microcontrollers is to "blink an LED". The following code demonstrates how this is done naively with React Hardware and how React’s programming model brings composability to the hardware world.

import React from 'react';
import ReactHardware, {Led} from 'react-hardware';

const HIGH = 255;
const LOW = 0;

class Application extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: 0};
    this._timer = null;
  }

  componentDidMount() {
    this._timer = setInterval(_ => (
      this.setState(prevState => ({value: prevState.value === HIGH ? LOW : HIGH}))
    ), this.props.interval);
  }

  componentWillUnmount() {
    clearInterval(this._timer);
    this._timer = null;
  }

  render() {
    return (
      <Led pin={10} value={this.state.value} />
    );
  }
}

var PORT = '/dev/tty.usbmodem1411';
ReactHardware.render(<Application interval={1000} />, PORT);

While this is unquestionably more code than it’s Johnny-Five or Sketch equivalents, this now gives you the ability to extract the parts of your board into self-contained components and compose these together. In this application we introduced the concept of a flashing LED, hard-coded naively into the global state. Let’s now extract the idea of a flashing LED into something we can share with our team or even on npm.

import React from 'react';
import ReactHardware, {Board, Led} from 'react-hardware';

const HIGH = 255;
const LOW = 0;

class FlashingLed extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: 0};
    this._timer = null;
    this.defaultProps = {
      interval: 1000,
    };
  }

  componentDidMount() {
    this._timer = setInterval(_ => (
      this.setState(prevState => ({value: prevState.value === HIGH ? LOW : HIGH}))
    ), this.props.interval);
  }

  componentWillUnmount() {
    clearInterval(this._timer);
    this._timer = null;
  }

  render() {
    return (
      <Led {...this.props} value={this.state.value} />
    );
  }
}

class Application extends React.Component {
  render() {
    return (
      <Board>
        <FlashingLed pin={9} />
        <FlashingLed pin={10} />
        <FlashingLed pin={11} />
        <FlashingLed pin={12} />
      </Board>
    );
  }
}

var PORT = '/dev/tty.usbmodem1411';
ReactHardware.render(<Application />, PORT);

Community

There should be #react-hardware channels created on both https://reactiflux.com/ and IRC.

Contributing

The codebase is written in es6 with (sporadic) types and compiled with babel. Follow the existing style when creating changes. Eslint and the flow type checker will be set up shortly. While the project is under heavy active development it would be useful to make an issue discussing your change before making a PR to ensure we aren’t duplicating effort.

License

Copyright (c) 2015 Dustan Kasten | [email protected] Licensed under the MIT license.

react-hardware's People

Contributors

aunyks avatar aweary avatar dennisja avatar edvinerikson avatar iamdustan 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

react-hardware's Issues

Support all of firmata

Pin

  • pinMode(pin,mode)
  • digitalWrite(pin,value)
  • digitalRead(pin,callback)
  • analogWrite(pin,value)
  • analogRead(pin,callback)

Servo

See #18 and #17.

  • servoWrite(pin, degree)
  • servoConfig(pin, min, max)

I2C

  • i2cConfig(delay)
  • i2cConfig(options)
  • i2cWrite(address, [...bytes])
  • i2cWrite(address, register, [...bytes])
  • i2cWriteReg(address, register, byte)
  • i2cRead(address, numberOfBytesToRead, handler(data))
  • i2cRead(address, register, numberOfBytesToRead, handler(data))
  • i2cReadOnce(address, numberOfBytesToRead, handler(data))
  • i2cReadOnce(address, register, numberOfBytesToRead, handler(data))
  • sendI2CConfig(delay) Deprecated
  • sendI2CWriteRequest(slaveAddress, [bytes]) Deprecated
  • sendI2CReadRequest(slaveAddress, numBytes, function(data)) Deprecated

Debug

  • sendString("a string")

One-Wire

  • sendOneWireConfig(pin, enableParasiticPower)
  • sendOneWireSearch(pin, callback)
  • sendOneWireAlarmsSearch(pin, callback)
  • sendOneWireRead(pin, device, numBytesToRead, callback)
  • sendOneWireReset()
  • sendOneWireWrite(pin, device, data)
  • sendOneWireDelay(pin, delay)
  • sendOneWireWriteAndRead(pin, device, data, numBytesToRead, callback)

Serial

  • board.SERIAL_PORT_IDs
  • board.serialConfig(options)
  • board.serialWrite(portId, inBytes)
  • board.serialRead(portId, callback)
  • board.serialRead(portId, maxBytesToRead, callback)
  • board.serialStop(portId)
  • board.serialClose(portId)
  • board.serialFlush(portId)
  • board.serialListen(portId)

Sysex

  • board.sysexResponse(commandByte, handler)
  • board.sysexCommand(message)

Encode/Decode

  • Board.encode(data)
  • Board.decode(data)

Update documentation

Currently there is a slightly mismatch between the API and the documentation.

Board and pin mapping support

There are a few interesting properties that Firmata supports and we have a few ways to support these.

I’m currently exploring the API tradeoffs (external and internal) with the following two options.

import React from '../';

const {
  ArduinoUno,
  Button,
  Led,
} = React;

class Application extends React.Component {
  render(): ReactElement {
    return (
      <ArduinoUno port="/dev/tty.usbmodem1411">
        <Button pin={2}
          onChange={this.toggle} onDown={this.log}
          onUp={this.log} onHold={this.log}
          />
        <Led pin={9} value={this.state.value} />
      </ArduinoUno>
    );
  }
}

React.render(<Application value={HIGH} />);
import React from '../';

const {
  Board,
  Button,
  Led,
} = React;

class Application extends React.Component {
  render(): ReactElement {
    return (
      <Board type="ArduinoUno" port="/dev/tty.usbmodem1411">
        <Button pin={2}
          onChange={this.toggle} onDown={this.log}
          onUp={this.log} onHold={this.log}
          />
        <Led pin={9} value={this.state.value} />
      </Board>
    );
  }
}

React.render(<Application value={HIGH} />);

Both intend to provide a friendly mapping from the boards visual port numbers to what is required to interface with node-firmata. E.g. on an Arduino Uno the analog pins [A0...A5] are pins 14-19 (maybe +1 to those) on the reported pin array.

By supporting this we can begin to provide developer warnings when attempting to set pins to values or modes that they do not support.

Thoughts?

$JSXIntrinsics

http://flowtype.org/blog/2016/02/02/Version-0.21.0.html#jsx-intrinsics

I’m fairly confident in the following, but haven’t had a chance to test it out at all yet.

/* @flow */
/* eslint-disable */

// JSXHelper is a type alias to make this example more concise.
// There's nothing special or magic here.
// JSXHelper<{name: string}> is a React component
// with the single string property "name", which has a default
// type JSXHelper<T> = Class<ReactComponent<T,T,mixed>>;

// $JSXIntrinsics is special and magic.
// This declares the types for `pin`
declare type $JSXIntrinsics = {
  pin: JSXHelper<{
    mode: 'INPUT'|'OUTPUT'|'ANALOG'|'PWM'| 'SERVO'|'SHIFT'|'I2C'|'ONEWIRE'|'STEPPER'|'IGNORE'|'UNKNOWN';
    pin: number|string;
    value: number;
    onRead: ?(...arg:any) => any;
  }>;

  container: JSXHelper<{}>;
};

Fails on Windows

Im unable to get the below example to work.
Pls Help, here are some details..

Steps tried ::

Node Version :: 10.0.0
OS : Windows 64 bit

What i've done so far is,

  1. Cloned the Repo of react-hardware via https://github.com/iamdustan/react-hardware/
  2. Did an npm install // All packages installed fine.
  3. npm run example -- basic

Throws the below error

react-hardware\node_modules@babel\helper-plugin-utils\lib\index.js:72
throw Object.assign(err, {
^

Error: Requires Babel "^7.0.0-0", but was loaded with "6.26.3". If you are sure you have a compatible version of @babel/core, it is likely that something in your build process is loading the wrong version. Inspect the stack trace of this error to look for the first entry that doesn't mention "@babel/core" or "babel-core" to see what is calling Babel.
at throwVersionError (projectfolder\hwware\react-hardware\node_modules@babel\helper-plugin-utils\lib\index.js:65:11)
at Object.assertVersion (projectfolder\hwware\react-hardware\node_modules@babel\helper-plugin-utils\lib\index.js:13:11)
at _default (projectfolder\hwware\react-hardware\node_modules@babel\plugin-proposal-class-properties\lib\index.js:29:7)
at projectfolder\hwware\react-hardware\node_modules@babel\helper-plugin-utils\lib\index.js:19:12
at Function.memoisePluginContainer (C:\Users\user1\AppData\Roaming\npm\node_modules\babel-cli\node_modules\babel-core\lib\transformation\file\options\option-manager.js:113:13)
at Function.normalisePlugin (C:\Users\user1\AppData\Roaming\npm\node_modules\babel-cli\node_modules\babel-core\lib\transformation\file\options\option-manager.js:146:32)
at C:\Users\user1\AppData\Roaming\npm\node_modules\babel-cli\node_modules\babel-core\lib\transformation\file\options\option-manager.js:184:30
at Array.map ()
at Function.normalisePlugins (C:\Users\user1\AppData\Roaming\npm\node_modules\babel-cli\node_modules\babel-core\lib\transformation\file\options\option-manager.js:158:20)
at OptionManager.mergeOptions (C:\Users\user1\AppData\Roaming\npm\node_modules\babel-cli\node_modules\babel-core\lib\transformation\file\options\option-manager.js:234:36)
at OptionManager.init (C:\Users\user1\AppData\Roaming\npm\node_modules\babel-cli\node_modules\babel-core\lib\transformation\file\options\option-manager.js:368:12)
at compile (C:\Users\user1\AppData\Roaming\npm\node_modules\babel-cli\node_modules\babel-register\lib\node.js:103:45)
at loader (C:\Users\user1\AppData\Roaming\npm\node_modules\babel-cli\node_modules\babel-register\lib\node.js:144:14)
at Object.require.extensions.(anonymous function) [as .js] (C:\Users\user1\AppData\Roaming\npm\node_modules\babel-cli\node_modules\babel-register\lib\node.js:154:7)
at Module.load (internal/modules/cjs/loader.js:589:32)
at tryModuleLoad (internal/modules/cjs/loader.js:528:12)
at Function.Module._load (internal/modules/cjs/loader.js:520:3)
at Function.Module.runMain (internal/modules/cjs/loader.js:719:10)
at Object. (C:\Users\user1\AppData\Roaming\npm\node_modules\babel-cli\lib_babel-node.js:154:22)
at Module._compile (internal/modules/cjs/loader.js:678:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:689:10)
at Module.load (internal/modules/cjs/loader.js:589:32)
at tryModuleLoad (internal/modules/cjs/loader.js:528:12)
at Function.Module._load (internal/modules/cjs/loader.js:520:3)
at Function.Module.runMain (internal/modules/cjs/loader.js:719:10)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] example: babel-node ./scripts/examples "basic"
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] example 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! C:\Users\user1\AppData\Roaming\npm-cache_logs\2019-07-21T12_52_46_524Z-debug.log

DevTool hides children

DevTool does not display children of components that doesn't call setState.
Everything works as expected with the firmata mock. To reproduce this you will need to have the actual hardware.

Tested in React Native DevTools inside Nuclide.
RH version: master
Hardware: Arduino UNO
Firmata: 0.11.3

Expected behavior

<Led>
  <pin pin={9} value={1} />
</Led>

Actual behavior

<Led />

Example that hides children

import React, {Component} from 'react';
import {getPort} from '../port';
import ReactHardware from '../../src';

class Led extends Component {
  render() {
    return (
      <pin
        pin={9}
        value={1}
        mode={'OUTPUT'}
      />
    );
  }
}
ReactHardware.render(
  <Led />,
  getPort(),
  (inst) => {
    console.log('Rendered <%s />', Led.name);
  }
);

Example that shows children

import React, {Component} from 'react';
import {getPort} from '../port';
import ReactHardware from '../../src';

class Led extends Component {
  constructor() {
    super();
    this.state = {value: 1};
  }
  componentDidMount() {
    this.setState({value: 0});
  }
  render() {
    return (
      <pin
        pin={9}
        value={this.state.value}
        mode={'OUTPUT'}
      />
    );
  }
}
ReactHardware.render(
  <Led />,
  getPort(),
  (inst) => {
    console.log('Rendered <%s />', Led.name);
  }
);

Still maintained?

Is this repo still being maintained? There hasn't been an update for 6 Months.

How can use Serial Port

I want connect my react app to a serial port in the browser or electron app for communicate with a Caller ID.
please create a full documented example for working with a serial port.
tanx

Documentation things

  • sync examples to output
  • react devtools inline in the output for interactive experience
  • ...

POC: <board /> component

Or really support for any component that has an async mounting period before it can render it’s children. I have no idea how this will impact the codebase, but I imagine it will be slightly invasive.

React’s future incremental reconciler could be really interesting for this.

Strawman API that would be supported by this:

const App = (
  <container>
    <board port="/dev/cu.usbmodem1451" pinMapping={arduinoUnoPinMapping}>
      <Led pin={2} value={this.state.value}
    </board>
    <board port="/dev/cu.usbmodem1455" pinMapping={raspberryPiPinMapping}>{...}</board>
    <board port="/dev/rfcomm0">{someComponentsOnABluetoothConnectedDevice}</board>
  </container>
);

Use case is that full board configurations now become composable without needing an outside state management system other than setState.

Error in ReactHardwareMount.js file

Hi guys,

I'm trying to connect my Arduino UNO to use with this React renderer, but I have some errors.
This output comes when I connect my Arduino on the USB Port and them run the command: npm run example -- basic

[email protected] example /home/tiago/Documentos/react-hardware
babel-node ./scripts/examples "basic"

{ Error: Cannot find module 'react/lib/ReactInstanceHandles'
at Function.Module._resolveFilename (module.js:438:15)
at Function.Module._load (module.js:386:25)
at Module.require (module.js:466:17)
at require (internal/module.js:20:19)
at Object. (/home/tiago/Documentos/react-hardware/src/ReactHardwareMount.js:7:1)
at Module._compile (module.js:541:32)
at loader (/home/tiago/Documentos/react-hardware/node_modules/babel-register/lib/node.js:144:5)
at Object.require.extensions.(anonymous function) [as .js] (/home/tiago/Documentos/react-hardware/node_modules/babel-register/lib/node.js:154:7)
at Module.load (module.js:456:32)
at tryModuleLoad (module.js:415:12) code: 'MODULE_NOT_FOUND' }
Error: Cannot find module 'react/lib/ReactInstanceHandles'
at Function.Module._resolveFilename (module.js:438:15)
at Function.Module._load (module.js:386:25)
at Module.require (module.js:466:17)
at require (internal/module.js:20:19)
at Object. (/home/tiago/Documentos/react-hardware/src/ReactHardwareMount.js:7:1)
at Module._compile (module.js:541:32)
at loader (/home/tiago/Documentos/react-hardware/node_modules/babel-register/lib/node.js:144:5)
at Object.require.extensions.(anonymous function) [as .js] (/home/tiago/Documentos/react-hardware/node_modules/babel-register/lib/node.js:154:7)
at Module.load (module.js:456:32)
at tryModuleLoad (module.js:415:12)

Dont know what to do now, 'cause I only have one Led in the pin={13} that it's already setup in the index.js file.

Well, I really want to use and even contributing to this project in the future. When I get more knowledge about the React and other dependencies of this project. Thanks, I hope you help me.

Initial Release

To the few of you following along and anyone who stumbles across here:

I’m currently on paternity leave (part of why it’s been so quite for so long). That said, I’m starting to work on it again and am anticipating getting the real initial release out after React 0.14 comes out.

If you want to play, there is an alpha release that powered my tweets a couple months ago you can play with. npm install react-hardware and the wip branch here on github.

The things that need to be done yet:

  • upgrade to react 0.15
  • autodetect port #5
  • tests
  • Pin mapping from firmata (#4)
  • Analog pins (#4)
  • Manage children (e.g. swapping out things like a <FlashingLED />for <PulsatingLED />
  • Support multiple boards (BoardManager should be connection-aware)
  • Don’t bundle React, separate renderer for 0.14
  • webpack hot loader support don’t care
  • REACT_DEVTOOLS hook 😮
  • support events/reading from board
  • i2c read/write/config

C-lang error when trying with Particle Photon

This error stack comes up when I run my lib/app.js file:

#
# Fatal error in ../deps/v8/src/api.cc, line 1062
# Check failed: !value_obj->IsJSReceiver() || value_obj->IsTemplateInfo().
#

==== C stack trace ===============================

    0   node                                0x00000001008c5ecd v8::base::debug::StackTrace::StackTrace() + 19
    1   node                                0x00000001008c4be5 V8_Fatal + 233
    2   node                                0x0000000100146438 v8::Template::SetAccessorProperty(v8::Local<v8::Name>, v8::Local<v8::FunctionTem
plate>, v8::Local<v8::FunctionTemplate>, v8::PropertyAttribute, v8::AccessControl) + 0
    3   serialport.node                     0x00000001044ab098 SerialportPoller::Init(v8::Local<v8::Object>) + 248
    4   serialport.node                     0x00000001044a98ed init + 1201
    5   node                                0x00000001007c681a node::DLOpen(v8::FunctionCallbackInfo<v8::Value> const&) + 860
    6   node                                0x000000010016a808 v8::internal::FunctionCallbackArguments::Call(void (*)(v8::FunctionCallbackInfo<
v8::Value> const&)) + 340
    7   node                                0x00000001001b1fdf v8::internal::MaybeHandle<v8::internal::Object> v8::internal::(anonymous namespa
ce)::HandleApiCallHelper<false>(v8::internal::Isolate*, v8::internal::Handle<v8::internal::HeapObject>, v8::internal::Handle<v8::internal::Heap
Object>, v8::internal::Handle<v8::internal::FunctionTemplateInfo>, v8::internal::Handle<v8::internal::Object>, v8::internal::BuiltinArguments)
+ 915
    8   node                                0x00000001001b15b9 v8::internal::Builtin_Impl_HandleApiCall(v8::internal::BuiltinArguments, v8::int
ernal::Isolate*) + 281
    9   ???                                 0x00000a3cdd6043a7 0x0 + 11256528389031
    10  ???                                 0x00000a3cdd80a246 0x0 + 11256530510406
[1]    69327 illegal hardware instruction  node lib/app.js

Here is my src/app.js:

import React, {Component} from 'react';
import ReactHardware from 'react-hardware';

import five from 'johnny-five';
import Particle from 'particle-io';

class BlinkingLed extends Component {
  componentDidMount() {
    this.node = new five.Led(this.props.port);
    this.node.blink(this.props.period);
  }

  componentWillReceiveProps(nextProps) {
    if (this.props.period !== nextProps.period) {
      this.node.blink(nextProps.period);
    }
  }


  render() {
    return null;
  }
}

BlinkingLed.defaultProps = {
    port: 13,
    period: 500,
  };

ReactHardware.render(
  <BlinkingLed port={11} period={500} />,
  new five.Board({
        io: new Particle({
        token: process.env.PARTICLE_TOKEN,
        deviceId: process.env.PARTICLE_DEVICE_ID
    })
  }),
  (inst) => {
    console.log('Rendered <%s />', BlinkingLed.name);
  }
);

Here is my package.json:

{
  "name": "react-particle",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build": "babel src -d lib"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "johnny-five": "^0.10.7",
    "particle-io": "^0.14.0",
    "react": "15.0.0-rc.1",
    "react-hardware": "^0.5.0-alpha.2"
  },
  "devDependencies": {
    "babel-cli": "^6.24.1",
    "babel-preset-env": "^1.3.2",
    "babel-preset-react": "^6.24.1"
  }
}

Curious as to why the Firmata requirement?

Surely this ties the application to a host process? In something like the Espruino you would just call a lot of the code directly.

Is supporting something like the Espruino possible? Would love the advantage of using React and Components as a architecture for it...

import ergonomics

The following pattern should be supported. It is currently not due to how I’m exporting the components.

import {Pin} from 'react-hardware';

use jest

Jest looks to be decent as of v13.

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.