Skip to content

Commit 0fa5603

Browse files
committed
Initial commit
1 parent d57fb6d commit 0fa5603

File tree

15 files changed

+1133
-0
lines changed

15 files changed

+1133
-0
lines changed

.babelrc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"presets": ["es2015"],
3+
"plugins": [
4+
["transform-runtime", {
5+
"helpers": false,
6+
"polyfill": false,
7+
"regenerator": true
8+
}],
9+
"add-module-exports",
10+
"transform-async-to-generator",
11+
"transform-class-properties",
12+
"transform-object-rest-spread"
13+
]
14+
}

.editorconfig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
root = true
2+
3+
[*]
4+
indent_style = space
5+
indent_size = 2
6+
end_of_line = LF
7+
charset = utf-8
8+
trim_trailing_whitespace = true
9+
insert_final_newline = true
10+
11+
[*.md]
12+
trim_trailing_whitespace = false

.eslintrc.js

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
module.exports = {
2+
"env": {
3+
"browser": true,
4+
"es6": true,
5+
"node": true
6+
},
7+
"globals": {
8+
"atom": true,
9+
"document": false,
10+
"escape": false,
11+
"navigator": false,
12+
"unescape": false,
13+
"window": false
14+
},
15+
"plugins": [
16+
"import"
17+
],
18+
"extends": [
19+
"eslint:recommended",
20+
"plugin:import/errors",
21+
"plugin:import/warnings"
22+
],
23+
"parser": "babel-eslint",
24+
"parserOptions": {
25+
"ecmaVersion": 6,
26+
"sourceType": "module"
27+
},
28+
"settings": {
29+
"import/resolver": {
30+
"webpack": {
31+
"config": {
32+
"resolve": {
33+
"extensions": [".js"]
34+
}
35+
}
36+
}
37+
}
38+
},
39+
"rules": {
40+
"curly": [
41+
"warn",
42+
"all"
43+
],
44+
"linebreak-style": [
45+
"error",
46+
"unix"
47+
],
48+
"no-console": [
49+
"error",
50+
{
51+
"allow": ["warn", "error", "info"]
52+
}
53+
],
54+
"prefer-const": "error",
55+
"quotes": [
56+
"error",
57+
"single",
58+
"avoid-escape"
59+
],
60+
"semi": [
61+
"error",
62+
"always"
63+
],
64+
"sort-imports": [
65+
"warn",
66+
{
67+
"ignoreCase": false,
68+
"ignoreMemberSort": false,
69+
"memberSyntaxSortOrder": ["none", "all", "multiple", "single"]
70+
}
71+
],
72+
"no-useless-escape": [
73+
"off"
74+
],
75+
"no-empty": [
76+
"warn",
77+
{
78+
"allowEmptyCatch": true
79+
}
80+
]
81+
},
82+
};

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
node_modules
2+
lib

.npmignore

Whitespace-only changes.

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# platformio-node-helpers
2+
3+
Collection of Node.JS helpers for [PlatformIO](http://platformio.org).

package.json

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
{
2+
"name": "platformio-node-helpers",
3+
"version": "0.0.0",
4+
"description": "Collection of Node.JS helpers for PlatformIO",
5+
"main": "lib/index.js",
6+
"scripts": {
7+
"build": "webpack --env build",
8+
"dev": "webpack --progress --colors --watch --env dev",
9+
"lint": "eslint --ext js src || exit 0"
10+
},
11+
"repository": {
12+
"type": "git",
13+
"url": "https://github.com/platformio/platformio-node-helpers.git"
14+
},
15+
"keywords": [
16+
"PlatformIO",
17+
"IoT",
18+
"debug",
19+
"unittest",
20+
"embedded",
21+
"flash",
22+
"firmware",
23+
"arduino",
24+
"CMSIS",
25+
"ESP-IDF",
26+
"SPL",
27+
"mbed",
28+
"STM32Cube",
29+
"avr",
30+
"arm",
31+
"espressif",
32+
"esp8266",
33+
"esp32",
34+
"stm32",
35+
"pic32",
36+
"nRF51",
37+
"nRF52",
38+
"fpga",
39+
"verilog",
40+
"hardware",
41+
"serial",
42+
"monitor"
43+
],
44+
"license": "Apache-2.0",
45+
"bugs": {
46+
"url": "https://github.com/platformio/platformio-node-helpers/issues"
47+
},
48+
"homepage": "http://platformio.org",
49+
"dependencies": {
50+
"cross-spawn": "^5.1.0",
51+
"fs-plus": "^3.0.1",
52+
"jsonrpc-lite": "^1.2.4",
53+
"request": "^2.81.0",
54+
"semver": "^5.4.1",
55+
"sockjs-client": "^1.1.4",
56+
"tar": "^4.0.1",
57+
"tcp-port-used": "^0.1.2",
58+
"tmp": "0.0.33"
59+
},
60+
"devDependencies": {
61+
"babel-core": "^6.26.0",
62+
"babel-eslint": "^7.2.3",
63+
"babel-loader": "^7.1.2",
64+
"babel-plugin-add-module-exports": "^0.2.1",
65+
"babel-plugin-transform-async-to-generator": "^6.24.1",
66+
"babel-plugin-transform-class-properties": "^6.24.1",
67+
"babel-plugin-transform-object-rest-spread": "^6.26.0",
68+
"babel-plugin-transform-runtime": "^6.23.0",
69+
"babel-preset-es2015": "^6.24.1",
70+
"eslint": "^4.5.0",
71+
"eslint-import-resolver-webpack": "^0.8.3",
72+
"eslint-plugin-import": "^2.7.0",
73+
"webpack": "^3.5.5"
74+
}
75+
}

src/core.js

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/**
2+
* Copyright (c) 2017-present PlatformIO <contact@platformio.org>
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the license found in the LICENSE file in
6+
* the root directory of this source tree.
7+
*/
8+
9+
import fs from 'fs-plus';
10+
import path from 'path';
11+
import { runCommand } from './misc';
12+
13+
14+
const IS_WINDOWS = process.platform.startsWith('win');
15+
16+
export function getHomeDir() {
17+
const result = process.env.PLATFORMIO_HOME_DIR || path.join(fs.getHomeDirectory() || '~', '.platformio');
18+
if (IS_WINDOWS) {
19+
// Make sure that all path characters have valid ASCII codes.
20+
for (const char of result) {
21+
if (char.charCodeAt(0) > 127) {
22+
// If they don't, put the pio home directory into the root of the disk.
23+
const homeDirPathFormat = path.parse(result);
24+
return path.format({
25+
root: homeDirPathFormat.root,
26+
dir: homeDirPathFormat.root,
27+
base: '.platformio',
28+
name: '.platformio'
29+
});
30+
}
31+
}
32+
}
33+
return result;
34+
}
35+
36+
export function getEnvDir() {
37+
return path.join(getHomeDir(), 'penv');
38+
}
39+
40+
export function getEnvBinDir() {
41+
return path.join(getEnvDir(), IS_WINDOWS ? 'Scripts' : 'bin');
42+
}
43+
44+
export function getVersion() {
45+
return new Promise((resolve, reject) => {
46+
runCommand(
47+
'platformio',
48+
['--version'],
49+
(code, stdout, stderr) => {
50+
if (code === 0) {
51+
return resolve(stdout.trim().match(/[\d+\.]+.*$/)[0]);
52+
}
53+
return reject(stderr);
54+
}
55+
);
56+
});
57+
}
58+
59+
export function runPIOCommand(args, callback, options = {}) {
60+
runCommand(
61+
'platformio',
62+
['-f', ...args],
63+
callback,
64+
options
65+
);
66+
}

src/home.js

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
/**
2+
* Copyright (c) 2017-present PlatformIO <contact@platformio.org>
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the license found in the LICENSE file in
6+
* the root directory of this source tree.
7+
*/
8+
9+
import SockJS from 'sockjs-client';
10+
import jsonrpc from 'jsonrpc-lite';
11+
import request from 'request';
12+
import spawn from 'cross-spawn';
13+
import tcpPortUsed from 'tcp-port-used';
14+
15+
16+
const HTTP_HOST = '127.0.0.1';
17+
let HTTP_PORT = 0;
18+
19+
function listenIDECommands(callback) {
20+
const reconnect = {
21+
timer: null,
22+
delay: 500, // msec
23+
maxDelay: 10000, // msec
24+
retries: 0
25+
};
26+
27+
function newSocket(endpoint) {
28+
if (reconnect.timer) {
29+
clearTimeout(reconnect.timer);
30+
}
31+
const sock = new SockJS(endpoint);
32+
33+
sock.onopen = () => {
34+
reconnect.retries = 0;
35+
sock.send(jsonrpc.request(Math.random().toString(), 'ide.listen_commands').toString());
36+
};
37+
38+
sock.onclose = () => {
39+
// reconnect.retries++;
40+
// reconnect.interval = setTimeout(
41+
// () => newSocket(endpoint),
42+
// Math.min(reconnect.delay * reconnect.retries, reconnect.maxDelay)
43+
// );
44+
};
45+
46+
sock.onmessage = event => {
47+
try {
48+
const result = jsonrpc.parse(event.data);
49+
switch (result.type) {
50+
case 'success':
51+
callback(result.payload.result.method, result.payload.result.params);
52+
break;
53+
54+
case 'error':
55+
console.error('Errored result: ' + result.payload.toString());
56+
break;
57+
}
58+
} catch (err) {
59+
console.error('Invalid RPC message: ' + err.toString());
60+
}
61+
sock.send(jsonrpc.request(Math.random().toString(), 'ide.listen_commands').toString());
62+
};
63+
return sock;
64+
}
65+
66+
newSocket(`http://${HTTP_HOST}:${HTTP_PORT}/wsrpc`);
67+
}
68+
69+
async function findFreePort() {
70+
let port = 8010;
71+
let inUse = false;
72+
while (port < 9000) {
73+
inUse = await new Promise(resolve => {
74+
tcpPortUsed.check(port, HTTP_HOST)
75+
.then(inUse => {
76+
resolve(inUse);
77+
}, () => {
78+
return resolve(false);
79+
});
80+
});
81+
if (!inUse) {
82+
return port;
83+
}
84+
port++;
85+
}
86+
return 0;
87+
}
88+
89+
export function isServerStarted() {
90+
return new Promise(resolve => {
91+
tcpPortUsed.check(HTTP_PORT, HTTP_HOST)
92+
.then(inUse => {
93+
resolve(inUse);
94+
}, () => {
95+
return resolve(false);
96+
});
97+
});
98+
}
99+
100+
export async function ensureServerStarted(options) {
101+
if (HTTP_PORT === 0) {
102+
HTTP_PORT = await findFreePort();
103+
}
104+
const params = {
105+
host: HTTP_HOST,
106+
port: HTTP_PORT
107+
};
108+
if (await isServerStarted()) {
109+
return params;
110+
}
111+
spawn('platformio', ['home', '--port', HTTP_PORT, '--no-open']);
112+
await new Promise((resolve, reject) => {
113+
tcpPortUsed.waitUntilUsed(HTTP_PORT, 500, 10000)
114+
.then(() => {
115+
resolve(true);
116+
}, (err) => {
117+
reject('Could not start PIO Home server: ' + err.toString());
118+
});
119+
});
120+
if (options.onIDECommand) {
121+
listenIDECommands(options.onIDECommand);
122+
}
123+
return params;
124+
}
125+
126+
export function shutdownServer() {
127+
request.get(`http://${HTTP_HOST}:${HTTP_PORT}?__shutdown__=1`);
128+
}

0 commit comments

Comments
 (0)