Skip to content
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,34 @@ daemon.downloading.subscribe(download => {

```

## Version 2

Version 2 of the arduino-create-agent aims to provide a cleaner api based on promises.
It will remain confined to a v2 property on the daemon object until it will be stable.
At the moment it only supports tool management.

```js
daemon.agentV2Found.subscribe(daemonV2 => {
if (!daemonV2) {
// Your Agent doesn't support v2
}
// Your Agent supports v2
});

daemon.v2.installedTools()
.then(tools => console.debug(tools)) // [{"name":"avrdude","version":"6.3.0-arduino9","packager":"arduino"}]

let payload = {
name: 'avrdude',
version: '6.3.0-arduino9',
packager: 'arduino',
url: 'http://downloads.arduino.cc/tools/avrdude-6.3.0-arduino9-i686-w64-mingw32.zip',
checksum: 'SHA-256:f3c5cfa8d0b3b0caee81c5b35fb6acff89c342ef609bf4266734c6266a256d4f',
signature: '7628b488c7ffd21ae1ca657245751a4043c419fbab5c256a020fb53f17eb88686439f54f18e78a80b40fc2de742f79b78ed4338c959216dc8ae8279e482d2d4117eeaf34a281ce2369d1dc4356f782c0940d82610f1c892e913b637391c39e95d4d4dfe82d8dbc5350b833186a70a62c7952917481bad798a9c8b4905df91bd914fbdfd6e98ef75c8f7fb06284278da449ce05b27741d6eda156bbdb906d519ff7d7d5042379fdfc55962b3777fb9240b368552182758c297e39c72943d75d177f2dbb584b2210301250796dbe8af11f0cf06d762fe4f912294f4cdc8aff26715354cfb33010a81342fbbc438912eb424a39fc0c52a9b2bf722051a6f3b024bd'
}
daemon.v2.installTool(payload) // Will install the tool in the system
```

## Development and test features
Just run `npm run dev` and open your browser on http://localhost:8000

Expand Down
43 changes: 23 additions & 20 deletions demo/app.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import React from 'react';
import Daemon from '../src';

import { HEX } from './serial_mirror';
import V2 from './v2/v2.jsx';

const chromeExtensionID = 'hfejhkbipnickajaidoppbadcomekkde';

Expand Down Expand Up @@ -173,11 +174,11 @@ class App extends React.Component {
{device.Name} - IsOpen: <span className={device.IsOpen ? 'open' : 'closed'}>
{device.IsOpen ? 'true' : 'false'}
</span> - <a href="#" onClick={(e) => this.handleOpen(e, device.Name)}>
open
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@matteosuppo pleeease, don't modify the formatting 😄

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry vscode decided it was better that way. I didn't even notice. Should I put it the way it was?

Copy link
Contributor

@AlbyIanna AlbyIanna Apr 5, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know, vscode has its own will sometimes. Yes please 👍

open
</a> - <a href="#" onClick={(e) => this.handleClose(e, device.Name)}>
close
close
</a> - <a href="#" onClick={(e) => handleBootloaderMode(e, device.Name)}>
bootloader mode
bootloader mode
</a>
</li>);

Expand All @@ -186,7 +187,7 @@ class App extends React.Component {
</li>);

const supportedBoards = this.state.supportedBoards.map((board, i) => <li key={i}>
{ board }
{board}
</li>);

let uploadClass;
Expand All @@ -213,24 +214,26 @@ class App extends React.Component {

return (
<div>
<V2 daemon={daemon}></V2>

<h1>Arduino Create Plugin Client Demo</h1>

<div className="section">
<h2>Plugin info</h2>

<p>
Agent status: <span className={ this.state.agentStatus ? 'found' : 'not-found' }>
{ this.state.agentStatus ? 'Found' : 'Not found' }
Agent status: <span className={this.state.agentStatus ? 'found' : 'not-found'}>
{this.state.agentStatus ? 'Found' : 'Not found'}
</span>
</p>
<p>
Channel status: <span className={ this.state.channelStatus ? 'found' : 'not-found' }>
{ this.state.channelStatus ? 'Connected' : 'Not connected' }
Channel status: <span className={this.state.channelStatus ? 'found' : 'not-found'}>
{this.state.channelStatus ? 'Connected' : 'Not connected'}
</span>
</p>

<pre>
{ this.state.agentInfo }
{this.state.agentInfo}
</pre>
</div>

Expand All @@ -239,12 +242,12 @@ class App extends React.Component {

<strong>serial:</strong>
<ul>
{ listSerialDevices }
{listSerialDevices}
</ul>

<strong>network:</strong>
<ul>
{ listNetworkDevices }
{listNetworkDevices}
</ul>

<p id="error"></p>
Expand All @@ -266,20 +269,20 @@ class App extends React.Component {
<h2>Serial Monitor</h2>

<form onSubmit={this.handleSend}>
<input id="serial-input" value={this.state.serialInput} onChange={this.handleChangeSerial}/>
<input id="serial-input" value={this.state.serialInput} onChange={this.handleChangeSerial} />
<input type="submit" value="Send" />
</form>

<textarea id="serial-textarea" value={ this.state.serialMonitorContent } readOnly/>
<textarea id="serial-textarea" value={this.state.serialMonitorContent} readOnly />
</div>

<div className="section">
<h2>Upload a sample sketch on a MKR1000 at /dev/ttyACM0</h2>
<button onClick={ handleUpload } disabled={ this.state.uploadStatus === daemon.UPLOAD_IN_PROGRESS }>Upload Sketch</button><br/>
<div>Upload status: <span className={ uploadClass }> { this.state.uploadStatus }</span> <span>{ this.state.uploadError }</span></div>
<button onClick={handleUpload} disabled={this.state.uploadStatus === daemon.UPLOAD_IN_PROGRESS}>Upload Sketch</button><br />
<div>Upload status: <span className={uploadClass}> {this.state.uploadStatus}</span> <span>{this.state.uploadError}</span></div>
</div>

{ daemon.downloading ? <div className="section">
{daemon.downloading ? <div className="section">
<h2>Download tool (not supported on Chrome OS)</h2>

<div>
Expand All @@ -300,19 +303,19 @@ class App extends React.Component {
</div>

<form onSubmit={handleDownloadTool}>
<div><input id="toolname" placeholder="Tool Name"/></div>
<div><input id="toolname" placeholder="Tool Name" /></div>
<div><input id="toolversion" placeholder="Tool Version" /></div>
<div><input id="package" placeholder="Package" /></div>
<div><input id="replacement" placeholder="Replacement strategy"/></div>
<div><input id="replacement" placeholder="Replacement strategy" /></div>

<input type="submit" value="Download" />
<div>Download status: <span className={ downloadClass }> { this.state.downloadStatus }</span></div>
<div>Download status: <span className={downloadClass}> {this.state.downloadStatus}</span></div>
</form>
</div> : null}

<div className="section">
<h2>Errors</h2>
<div className="error">{ this.state.error }</div>
<div className="error">{this.state.error}</div>
</div>
</div>
);
Expand Down
37 changes: 33 additions & 4 deletions demo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
-->

<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
Expand All @@ -26,15 +27,20 @@
<style>
body {
color: #2c353a;
font-family: Lucida Grande,Lucida,Verdana,sans-serif;
font-family: Lucida Grande, Lucida, Verdana, sans-serif;
padding: 15px;
}

#error, .not-found, .closed, .error {
#error,
.not-found,
.closed,
.error {
color: red
}

.found, .open, .success {
.found,
.open,
.success {
color: green;
}

Expand All @@ -53,9 +59,32 @@
.section {
margin: 20px;
}
.install-tool-container .tool-input {
display: flex;
margin: 10px 0;
}

.install-tool-container .tool-input label {
flex: 0 1 200px;
}

.install-tool-container .tool-input input {
flex: 0 1 500px;
}

table {
border-collapse: collapse;
}

table td {
border: 1px solid black;
padding: 3px;
}
</style>
</head>

<body>
<div id="root"></div>
</body>
</html>

</html>
107 changes: 107 additions & 0 deletions demo/v2/install_tool.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import React from 'react';
import { flatMap } from 'rxjs/operators';

export class V2InstallTool extends React.Component {
constructor() {
super();
this.state = {
name: 'avrdude',
version: '6.3.0-arduino9',
packager: 'arduino',
url: 'http://downloads.arduino.cc/tools/avrdude-6.3.0-arduino9-i686-w64-mingw32.zip',
checksum: 'SHA-256:f3c5cfa8d0b3b0caee81c5b35fb6acff89c342ef609bf4266734c6266a256d4f',
signature: '7628b488c7ffd21ae1ca657245751a4043c419fbab5c256a020fb53f17eb88686439f54f18e78a80b40fc2de742f79b78ed4338c959216dc8ae8279e482d2d4117eeaf34a281ce2369d1dc4356f782c0940d82610f1c892e913b637391c39e95d4d4dfe82d8dbc5350b833186a70a62c7952917481bad798a9c8b4905df91bd914fbdfd6e98ef75c8f7fb06284278da449ce05b27741d6eda156bbdb906d519ff7d7d5042379fdfc55962b3777fb9240b368552182758c297e39c72943d75d177f2dbb584b2210301250796dbe8af11f0cf06d762fe4f912294f4cdc8aff26715354cfb33010a81342fbbc438912eb424a39fc0c52a9b2bf722051a6f3b024bd',
res: ''
};

this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}

componentDidMount() {
this.daemon = this.props.daemon;

this.daemon.agentV2Found.subscribe(daemonV2 => {
if (!daemonV2) {
return;
}
this.daemonV2 = daemonV2;
});
}

handleChange(event) {
this.setState({ [event.target.name]: event.target.value });
}

handleSubmit(event) {
event.preventDefault();

this.daemonV2.installTool({
name: this.state.name,
version: this.state.version,
packager: this.state.packager,
checksum: this.state.checksum,
signature: this.state.signature,
url: this.state.url,

})
.then(res => {
this.setState({
res: JSON.stringify(res, null, 2)
});
})
.catch(err => {
this.setState({
res: JSON.stringify(err, null, 2)
});
});
}

render() {
return (
<section className="install-tool-container">
<h2>Install a new tool</h2>
<form onSubmit={this.handleSubmit}>
<div className="tool-input">
<label for="name">
Name:
</label>
<input type="text" name="name" value={this.state.name} onChange={this.handleChange} />
</div>
<div className="tool-input">
<label for="version">
Version:
</label>
<input type="text" name="version" value={this.state.version} onChange={this.handleChange} />
</div>
<div className="tool-input">
<label for="packager">
Packager:
</label>
<input type="text" name="packager" value={this.state.packager} onChange={this.handleChange} />
</div>
<div className="tool-input">
<label for="url">
Url:
</label>
<input type="text" name="url" value={this.state.url} onChange={this.handleChange} />
</div>
<div className="tool-input">
<label for="checksum">
Checksum:
</label>
<input type="text" name="checksum" value={this.state.checksum} onChange={this.handleChange} />
</div>
<div className="tool-input">
<label for="signature">
Signature:
</label>
<input type="text" name="signature" value={this.state.signature} onChange={this.handleChange} />
</div>
<input type="submit" value="Submit" />
</form>
<textarea cols="100" rows="10" value={this.state.res} readOnly></textarea>
</section>
);
}
}
60 changes: 60 additions & 0 deletions demo/v2/v2.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import React from 'react';
import { V2InstallTool } from './install_tool.jsx';

class V2 extends React.Component {
constructor() {
super();
this.state = {
tools: []
};
}

componentDidMount() {
this.daemon = this.props.daemon;

this.daemon.agentV2Found.subscribe(daemonV2 => {
if (!daemonV2) {
return;
}
this.daemonV2 = daemonV2;
this.daemonV2.installedTools().then(res => {
this.setState({
tools: res
});
});
});
}

render() {
const tools = this.state.tools.map((tool, i) => <tr key={i}>
<td>{tool.packager}</td>
<td>{tool.name}</td>
<td>{tool.version}</td>
</tr>);

return (
<section>
<h2>V2</h2>
<section>
<h3>Installed tools</h3>
<form onSubmit={this.handleInstallTool}>
<table>
<thead>
<tr>
<th>Packager</th>
<th>Name</th>
<th>Version</th>
</tr>
</thead>
<tbody>{tools}</tbody>
</table>
</form>

<V2InstallTool daemon={this.props.daemon}></V2InstallTool>
</section>
</section >
);
}
}

export default V2;
Loading