177 lines
5.7 KiB
JavaScript
177 lines
5.7 KiB
JavaScript
|
|
const { Client } = require('basic-ftp');
|
||
|
|
const { Readable } = require('stream');
|
||
|
|
|
||
|
|
module.exports = async (server) => {
|
||
|
|
|
||
|
|
const { api, env, util } = server;
|
||
|
|
const confdir = util.confdir();
|
||
|
|
|
||
|
|
let client, topic_report, topic_request, timer;
|
||
|
|
|
||
|
|
const mqtt = require("mqtt");
|
||
|
|
const mqtt_options = {
|
||
|
|
protocol: 'mqtts',
|
||
|
|
port: 8883,
|
||
|
|
username: 'bblp',
|
||
|
|
// ca: fs.readFileSync('ca.crt'),
|
||
|
|
// key: fs.readFileSync('client.key'),
|
||
|
|
// cert: fs.readFileSync('client.crt'),
|
||
|
|
rejectUnauthorized: false
|
||
|
|
};
|
||
|
|
|
||
|
|
const mqtt_fn = {
|
||
|
|
async send(msg) {
|
||
|
|
if (client) {
|
||
|
|
util.log('mqtt_send', msg);
|
||
|
|
client.publish(topic_request, JSON.stringify(msg));
|
||
|
|
clearTimeout(timer);
|
||
|
|
timer = setTimeout(() => { mqtt_fn.end() }, 30000);
|
||
|
|
return true;
|
||
|
|
} else {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
},
|
||
|
|
|
||
|
|
end() {
|
||
|
|
if (client) {
|
||
|
|
util.log('mqtt end');
|
||
|
|
client.end();
|
||
|
|
client = undefined;
|
||
|
|
}
|
||
|
|
topic_report = undefined;
|
||
|
|
topic_request = undefined;
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
function get_mqtt(serial) {
|
||
|
|
const fns = {};
|
||
|
|
const promise = new Promise((resolve, reject) => {
|
||
|
|
Object.assign(fns, { resolve, reject });
|
||
|
|
});
|
||
|
|
|
||
|
|
if (client) {
|
||
|
|
return mqtt_fn;
|
||
|
|
}
|
||
|
|
|
||
|
|
client = mqtt.connect(mqtt_options);
|
||
|
|
|
||
|
|
client.on("connect", () => {
|
||
|
|
topic_report = `device/${serial}/report`;
|
||
|
|
topic_request = `device/${serial}/request`;
|
||
|
|
util.log({ topic_report, topic_request });
|
||
|
|
client.subscribe(topic_report, (err) => {
|
||
|
|
util.log('mqtt_subscribed', err);
|
||
|
|
fns.resolve(mqtt_fn);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
client.on("message", (topic, message) => {
|
||
|
|
util.log('mqtt_recv', JSON.parse(message.toString()));
|
||
|
|
});
|
||
|
|
|
||
|
|
return promise;
|
||
|
|
}
|
||
|
|
|
||
|
|
async function ftp_send(args = {}) {
|
||
|
|
const client = new Client();
|
||
|
|
const port = parseInt(args.port || 990);
|
||
|
|
const host = args.host || "localhost";
|
||
|
|
const user = args.user || "bblp";
|
||
|
|
const password = args.password || '';
|
||
|
|
const filename = args.filename || "test.3mf";
|
||
|
|
const data = args.data || undefined;
|
||
|
|
// client.ftp.verbose = true;
|
||
|
|
try {
|
||
|
|
await client.access({
|
||
|
|
port,
|
||
|
|
host,
|
||
|
|
user,
|
||
|
|
password,
|
||
|
|
secure: "implicit",
|
||
|
|
secureOptions: { rejectUnauthorized: false }
|
||
|
|
});
|
||
|
|
const readableStream = new Readable();
|
||
|
|
readableStream._read = () => {};
|
||
|
|
readableStream.push(data);
|
||
|
|
readableStream.push(null);
|
||
|
|
await client.uploadFrom(readableStream, filename);
|
||
|
|
} finally {
|
||
|
|
client.close();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function decode_post(req, res, next) {
|
||
|
|
if (req.method === 'POST') {
|
||
|
|
let chunks = [];
|
||
|
|
req
|
||
|
|
.on('data', data => chunks.push(data) )
|
||
|
|
.on('end', () => {
|
||
|
|
req.app.post = Buffer.concat(chunks);
|
||
|
|
next();
|
||
|
|
});
|
||
|
|
} else {
|
||
|
|
next();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// insert script before all others in kiri client
|
||
|
|
server.inject("kiri", "bambu.js");
|
||
|
|
|
||
|
|
function o2s(obj) {
|
||
|
|
return JSON.stringify(obj);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!(env.debug || env.electron)) {
|
||
|
|
util.log('no valid context for bambu');
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
api.bambu_send = (req, res, next) => {
|
||
|
|
const { app, url, headers } = req;
|
||
|
|
const { host } = headers;
|
||
|
|
const { query } = app;
|
||
|
|
server.handler.addCORS(req, res);
|
||
|
|
decode_post(req, res, async () => {
|
||
|
|
res.setHeader("Content-Type", "application/octet-stream");
|
||
|
|
res.setHeader('Cache-Control', 'no-cache, no-store, private');
|
||
|
|
const data = req.app.post;
|
||
|
|
const { host, password, filename, serial, ams } = query;
|
||
|
|
const ams_mapping = ams ? ams.split(',').map(v => parseInt(v)) : undefined;
|
||
|
|
const mqtt_conn = serial ? get_mqtt(serial) : undefined;
|
||
|
|
ftp_send({ host, password, filename, data })
|
||
|
|
.then(() => {
|
||
|
|
if (serial) {
|
||
|
|
Object.assign(mqtt_options, { host, password });
|
||
|
|
const cmd = {
|
||
|
|
print: {
|
||
|
|
command: "project_file",
|
||
|
|
url: `file:///sdcard/${filename}`,
|
||
|
|
param: "Metadata/plate_1.gcode",
|
||
|
|
subtask_id: "0",
|
||
|
|
use_ams: ams_mapping ? true : false,
|
||
|
|
timelapse: false,
|
||
|
|
flow_cali: false,
|
||
|
|
bed_leveling: false,
|
||
|
|
layer_inspect: false,
|
||
|
|
vibration_cali: false
|
||
|
|
}
|
||
|
|
};
|
||
|
|
if (ams_mapping) {
|
||
|
|
cmd.print.ams_mapping = ams_mapping;
|
||
|
|
}
|
||
|
|
mqtt_conn
|
||
|
|
.then(mqtt => mqtt.send(cmd))
|
||
|
|
.catch(err => {
|
||
|
|
util.log({ mqtt_err: err });
|
||
|
|
});
|
||
|
|
}
|
||
|
|
res.end(o2s({ sent: true }));
|
||
|
|
})
|
||
|
|
.catch(error => {
|
||
|
|
util.log({ ftp_send_error: error });
|
||
|
|
res.end(o2s({ sent: false, error }));
|
||
|
|
});
|
||
|
|
});
|
||
|
|
};
|
||
|
|
|
||
|
|
};
|