obniz-cli
Version:
[日本語はこちら](./README-ja.md)
380 lines • 14 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const chalk_1 = __importDefault(require("chalk"));
const node_wifi_1 = __importDefault(require("node-wifi"));
const ora_1 = __importDefault(require("ora"));
const os_1 = require("os");
class WiFi {
constructor(obj) {
this.stdout = obj.stdout;
this.onerror = obj.onerror;
node_wifi_1.default.init({
iface: null,
});
}
async setNetwork(configs, duplicate = true) {
let spinner;
const successIds = [];
while (true) {
try {
spinner = ora_1.default(`Wi-Fi Scanning...`).start();
let networks;
while (true) {
networks = await this.scanObnizWiFi(30 * 1000);
if (networks.length === 0) {
continue;
}
break;
}
for (let i = 0; i < networks.length; i++) {
const network = networks[i];
if (!duplicate && successIds[network.ssid]) {
continue;
}
if (i !== 0) {
spinner = ora_1.default(``).start();
}
try {
// Connect access point
spinner.text = `Found ${chalk_1.default.green(network.ssid)}. Connecting...`;
try {
await node_wifi_1.default.connect({ ssid: network.ssid });
}
catch (e) {
throw new Error(`Connection to ${chalk_1.default.green(network.ssid)} failed`);
}
const destIP = guessObnizIP();
console.log(destIP);
spinner.text = `Connected ${chalk_1.default.green(network.ssid)}. IP=${destIP} Configuring...`;
if (destIP === "1.2.3.4" || destIP === "192.168.0.1") {
const succeed = await this.setForUnder350Devices(destIP, spinner, configs);
if (!succeed) {
continue;
}
spinner.succeed(`Configuration sent ${chalk_1.default.green(network.ssid)}`);
}
else {
const succeed = await this.setForEqualOrOver350Devices(destIP, spinner, configs);
if (!succeed) {
continue;
}
spinner.succeed(`Configuration Saved and Device Rebooted ${chalk_1.default.green(network.ssid)}`);
}
successIds[network.ssid] = true;
}
catch (e) {
spinner.fail(`${chalk_1.default.green(network.ssid)} Configuration failed reson=${e.toString()}`);
}
}
}
catch (e) {
spinner === null || spinner === void 0 ? void 0 : spinner.fail(`${e.toString()}`);
}
}
}
async setForUnder350Devices(targetIP, spinner, configs) {
// Configure network via wifi
const networks = configs.networks;
if (!networks) {
throw new Error(`please provide "networks". see more detail at example json file`);
}
if (!Array.isArray(networks)) {
throw new Error(`"networks" must be an array`);
}
if (networks.length !== 1) {
throw new Error(`"networks" must have single object in array.`);
}
const network = networks[0];
const type = network.type;
const setting = network.settings;
let getCount = 0;
let responseBody = "";
while (true) {
await new Promise((resolve) => {
setTimeout(resolve, 1000);
});
try {
const httpResponse = await new Promise((resolve, reject) => {
const timeout = 3000;
setTimeout(() => {
reject(new Error(`Timed out ${timeout}`));
}, timeout);
fetch(`http://${targetIP}/`)
.then((result) => {
resolve(result);
})
.catch((e) => {
reject(e);
});
});
if (httpResponse.ok) {
responseBody = await httpResponse.text();
break;
}
}
catch (e) {
// ignore fetching error
}
++getCount;
spinner.text = `${chalk_1.default.green(network.ssid)} Connecting HTTP Server... ${getCount}`;
if (getCount >= 4) {
throw new Error(`${chalk_1.default.green(network.ssid)} HTTP Communication Failed ${getCount} times. abort`);
}
}
if (this.isSettingMode(responseBody)) {
await this.sendReset(spinner, network.ssid);
spinner.succeed(`Network Reset done. ${chalk_1.default.green(network.ssid)}`);
return false;
}
// Send HTTP Request
let url = "http://192.168.0.1/";
if (type === "wifi") {
url = "http://192.168.0.1/";
}
else if (type === "cellular") {
url = "http://192.168.0.1/lte";
}
else if (type === "wifimesh") {
url = "http://192.168.0.1/mesh";
}
const options = this.createSettingData(type, setting);
const res = await fetch(url, options);
if (res.status !== 200) {
throw new Error(`Configuration failed ${chalk_1.default.green(network.ssid)}`);
}
return true;
}
/**
* setting configration for OS3.5.0 or older
* @param spinner Ora object
* @param configs json user set
* @returns
*/
async setForEqualOrOver350Devices(targetIP, spinner, configs) {
// Configure network via wifi
let getCount = 0;
const responseBody = "";
// Login Loop
spinner.text = `Logining...`;
while (true) {
await new Promise((resolve) => {
setTimeout(resolve, 1000);
});
try {
const res = await new Promise((resolve, reject) => {
const timeout = 3000;
setTimeout(() => {
reject(new Error(`Timed out ${timeout}`));
}, timeout);
fetch(`http://${targetIP}/api/login`, {
method: "POST",
headers: {
"Content-Type": "application/json;charset=utf-8",
},
body: JSON.stringify({ passkey: "obniz" }),
})
.then((result) => {
resolve(result);
})
.catch((e) => {
reject(e);
});
});
if (res.status === 404) {
// already logged in
break;
}
if (res.status !== 200) {
throw new Error(`Can't Logged In`);
}
break;
}
catch (e) {
// throw new Error(`Login Error`)
}
++getCount;
spinner.text = `Accessing and Logining... ${getCount}`;
if (getCount >= 4) {
throw new Error(`Login Failed ${getCount} times. abort`);
}
}
// after login
spinner.text = `Sending JSON`;
const setRes = await fetch(`http://${targetIP}/api/setting`, {
method: "POST",
headers: {
"Content-Type": "application/json;charset=utf-8",
},
body: JSON.stringify(configs),
});
if (setRes.status !== 201) {
throw new Error(`Configration Failed with status ${setRes.status}`);
}
const options = {
method: "POST",
};
spinner.text = `Rebooting`;
const params = new URLSearchParams();
params.append("mode", "reboot");
options.body = params;
// this will never done. because device will reboot
fetch(`http://${targetIP}/setting`, options).then();
return true;
}
isSettingMode(responseBody) {
return responseBody.indexOf(`Normal Launch`) >= 0;
}
async sendReset(spinner, identifier) {
// reset_all
const options = this.createResetData();
const res = await fetch("http://192.168.0.1/", options);
if (res.status !== 200) {
throw new Error(`Resetting Network failed ${chalk_1.default.green(identifier)}`);
}
}
/**
* リセットリクエストを送りWi-Fi設定モードに遷移させる
* @returns
*/
createResetData() {
const options = {
method: "POST",
};
const urlSetting = {
mode: "reset_all",
};
const params = new URLSearchParams();
Object.keys(urlSetting).forEach((key) => params.append(key, urlSetting[key]));
options.body = params;
return options;
}
/**
* ネットワーク設定を送る
* @param type
* @param setting
* @returns
*/
createSettingData(type, setting) {
const options = {
method: "POST",
};
if (type === "wifi") {
const urlSetting = {
ssid: "other",
input_ssid: setting.ssid,
pw: setting.password,
si: "",
nm: "",
gw: "",
ds: "",
proxy_ip: "",
proxy_port: "",
};
if (setting.dhcp === false) {
urlSetting.si = setting.static_ip;
urlSetting.nm = setting.subnetmask;
urlSetting.gw = setting.default_gateway;
urlSetting.ds = setting.dns;
}
if (setting.proxy) {
urlSetting.proxy_ip = setting.proxy_address;
urlSetting.proxy_port = setting.proxy_port;
}
const params = new URLSearchParams();
Object.keys(urlSetting).forEach((key) => params.append(key, urlSetting[key]));
options.body = params;
}
else if (type === "wifimesh") {
const urlSetting = {
ssid: "other",
input_ssid: setting.ssid,
pw: setting.password,
meshid: "",
si: "",
nm: "",
gw: "",
ds: "",
proxy_ip: "",
proxy_port: "",
};
if (setting.dhcp === false) {
urlSetting.si = setting.static_ip;
urlSetting.nm = setting.subnetmask;
urlSetting.gw = setting.default_gateway;
urlSetting.ds = setting.dns;
}
if (setting.proxy) {
urlSetting.proxy_ip = setting.proxy_address;
urlSetting.proxy_port = setting.proxy_port;
}
if (setting.meshid) {
urlSetting.meshid = setting.meshid;
}
const params = new URLSearchParams();
Object.keys(urlSetting).forEach((key) => params.append(key, urlSetting[key]));
options.body = params;
}
else if (type === "cellular") {
const urlSetting = setting;
const params = new URLSearchParams();
Object.keys(urlSetting).forEach((key) => params.append(key, urlSetting[key]));
options.body = params;
}
return options;
}
scanObnizWiFi(timeout) {
return new Promise(async (resolve, reject) => {
const timer = setTimeout(() => {
reject(new Error(`Timeout. Cannot find any connectable obniz.`));
}, timeout);
node_wifi_1.default.scan((error, networks) => {
if (error) {
clearTimeout(timer);
reject(error);
return;
}
const obnizwifis = [];
for (const network of networks) {
const re = /^obniz-[0-9]{8}/;
if (re.test(network.ssid)) {
obnizwifis.push(network);
}
}
clearTimeout(timer);
resolve(obnizwifis);
});
});
}
}
exports.default = WiFi;
function currentLocalIP() {
const nets = os_1.networkInterfaces();
for (const name of Object.keys(nets)) {
for (const net of nets[name]) {
// Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses
if (net.family === "IPv4" && !net.internal) {
if (net.address.startsWith("192.168") || net.address.startsWith("1.2.3.")) {
return net.address;
}
}
}
}
// obnizOS 3.5.0 standard
return "192.168.254.2";
}
function guessObnizIP() {
const ip = currentLocalIP();
if (ip === "1.2.3.5") {
return "1.2.3.4";
}
else if (ip === "192.168.0.2") {
return "192.168.0.1";
}
else {
return "192.168.254.1";
}
}
//# sourceMappingURL=index.js.map