Commit 6a97978c authored by Oleg Dzhimiev's avatar Oleg Dzhimiev

initial

parent 4c112ecb
Pipeline #869 canceled with stages
const express = require('express');
const path = require('path');
const cookieParser = require('cookie-parser');
const logger = require('morgan');
const indexRouter = require('./routes/index');
const app = express();
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/node_modules',express.static(path.join(__dirname, 'node_modules')));
app.use('/', indexRouter);
module.exports = app;
#!/usr/bin/env node
/**
* Module dependencies.
*/
var app = require('../app');
var debug = require('debug')('p4:server');
var http = require('http');
/**
* Get port from environment and store in Express.
*/
var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);
/**
* Create HTTP server.
*/
var server = http.createServer(app);
/**
* Listen on provided port, on all network interfaces.
*/
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
/**
* Normalize a port into a number, string, or false.
*/
function normalizePort(val) {
var port = parseInt(val, 10);
if (isNaN(port)) {
// named pipe
return val;
}
if (port >= 0) {
// port number
return port;
}
return false;
}
/**
* Event listener for HTTP server "error" event.
*/
function onError(error) {
if (error.syscall !== 'listen') {
throw error;
}
var bind = typeof port === 'string'
? 'Pipe ' + port
: 'Port ' + port;
// handle specific listen errors with friendly messages
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges');
process.exit(1);
break;
case 'EADDRINUSE':
console.error(bind + ' is already in use');
process.exit(1);
break;
default:
throw error;
}
}
/**
* Event listener for HTTP server "listening" event.
*/
function onListening() {
var addr = server.address();
var bind = typeof addr === 'string'
? 'pipe ' + addr
: 'port ' + addr.port;
debug('Listening on ' + bind);
}
{
"name": "p4",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "node ./bin/www"
},
"dependencies": {
"cookie-parser": "~1.4.3",
"debug": "~2.6.9",
"express": "~4.16.0",
"jquery": "^3.3.1",
"morgan": "~1.9.0"
}
}
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>ROS2 Testing</title>
<link rel="stylesheet" href="/stylesheets/style.css">
<script type='text/javascript' src='node_modules/jquery/dist/jquery.js'></script>
<script type='text/javascript' src='javascripts/index.js'></script>
</head>
<body>
<div>
<table>
<tr>
<td>Master:</td>
<td id='masternode'></td>
</tr>
<tr valign='top'>
<td>Slaves:</td>
<td id='slavenodes'></td>
</tr>
</table>
</div>
<div>
<button id='testbutton'>List masters</button>
<!--<button id='testbutton1'>List slaves</button>-->
<button id='testbutton2'>Get states</button>
<!--<button id='testbutton3'>ifconfig</button>-->
</div>
<div id='nodelist'></div>
</body>
</html>
$(function(){
init();
});
let MasterNode = "-";
let appData = {
master: "-",
slaves: [],
slaves_selected: []
}
function init(){
// css
$("#nodelist").css({
padding:'10px 0px'
});
$("#masternode").css({
'font-weight': 'bold'
});
update_master_node();
// init button
$('#testbutton').on('click', function(e){
$.ajax({
url: '/api/nodelist',
success: function(response){
const l = response.trim().split('\n');
let ll = [];
$("#nodelist").empty();
l.forEach(function(entry) {
ll.push("<div class='master_nodes'>"+entry+"</div>");
});
$("#nodelist").empty().append(ll.join('\n'));
$(".master_nodes").on('click',function(e){
update_master_node($(this).html());
$("#nodelist").empty();
//send_command(appData.slaves,'list', parse_cmd_list_init);
// go straight with ifconfig
send_command(appData.slaves,'ifconfig', parse_cmd_ifconfig_init);
});
}
});
});
$('#testbutton1').on('click', function(e){
send_command(appData.slaves_selected,'list', parse_cmd_list);
});
$('#testbutton2').on('click', function(e){
send_command(appData.slaves_selected,'state', parse_cmd_state);
});
// need a post request
$('#testbutton3').on('click', function(e){
//let cmd = "wget -qO- -o /dev/null 'http://localhost/parsedit.php?immediate&amp;TRIG'";
//let cmd = "ifconfig";
//let cmd = "wget -qO- -o /dev/null 'http://localhost/diagnostics.php'";
const cmd = "ifconfig";
send_command(appData.slaves_selected, cmd, parse_cmd_ifconfig);
});
}
function parse_cmd_list_init(res){
$(res).find('target').each(function(){
const name = $(this).text();
update_slave_list(name);
});
$(".slave_checkbox").on("change",function(e){
let checked = $(this).prop("checked");
let name = $(this).parent().find("label").html();
console.log(checked+" "+name);
if (!checked) {
appData.slaves_selected = appData.slaves_selected.filter(item => item!==name);
}else{
appData.slaves_selected.push(name);
}
});
}
function parse_cmd_list(res){
let rtab = [
'<table class="slave_table">',
' <tr>',
' <th>Slave</th>',
' </tr>'
];
$(res).find('target').each(function(){
const name = $(this).text();
//update_slave_list(name);
rtab = rtab.concat([
'<tr>',
' <td class="name">'+name+'</td>',
'</tr>',
]);
});
rtab.push('</table>');
$("#nodelist").empty().append(rtab.join('\n'));
}
function parse_cmd_state(res){
let rtab = [
'<table class="slave_table">',
' <tr>',
' <th>Slave</th>',
' <th>State</th>',
' </tr>'
];
$(res).find('response').each(function(){
const name = $(this).find('node').text();
const state = $(this).find('state').text();
rtab = rtab.concat([
'<tr>',
' <td class="name">'+name+'</td>',
' <td class="state">'+state+'</td>',
'</tr>',
]);
});
rtab.push('</table>');
$("#nodelist").empty().append(rtab.join('\n'));
}
function parse_cmd_testing(res){
$(res).find('response').each(function(){
const name = $(this).find('node').text();
const state = $(this).find('state').text();
console.log(state);
});
}
function parse_cmd_ifconfig(res){
$(res).find('response').each(function(){
const name = $(this).find('node').text();
const state = $(this).find('state').text();
const ip = get_ipaddr_from_ifconfig(state);
console.log(ip);
$("."+name+" label").html(name+" ("+ip+")");
});
}
function send_command(targets, cmd, callback){
let targets_str = "";
if (Array.isArray(targets)){
targets_str = targets.join(',');
}else if (typeof targets === 'string' || targets instanceof String){
targets_str = targets;
}else{
targets_str = "";
}
$.ajax({
type: "POST",
url: '/api/cmd',
data: {
master: appData.master,
targets: targets_str,
cmd: cmd
},
dataType: "xml",
success: callback
});
}
function update_slave_list(name){
appData.slaves.push(name);
appData.slaves_selected.push(name);
let html = [
'<div class=\''+name+'\'>',
'<input class=\'slave_checkbox\' type=\'checkbox\' checked />',
'<label>'+name+'</label>',
'</div>'
].join('\n');
$("#slavenodes").append(html);
}
function update_master_node(newvalue){
if (newvalue!==undefined){
appData.master = newvalue;
appData.slaves = [];
}
$("#masternode").html(appData.master);
}
function get_ipaddr_from_ifconfig(str){
// for Elphel 10393
const iface_regex_10393 = /[^\ \n]+(?=\ +Link\ encap)/gi;
const ipaddr_regex_10393 = /(?<=inet\ addr\:)\d+\.\d+\.\d+\.\d+/gi;
// for PC
const iface_regex_pc = /[^\ \n]+(?=\:\ flags)/gi;
const ipaddr_regex_pc = /(?<=inet\ )\d+\.\d+\.\d+\.\d+/gi;
let res = "";
let ifaces = str.match(iface_regex_10393);
let ipaddrs = str.match(ipaddr_regex_10393);
if (ifaces===null || ipaddrs===null){
ifaces = str.match(iface_regex_pc);
ipaddrs = str.match(ipaddr_regex_pc);
}
for(var i=0;i<ipaddrs.length;i++){
if (ifaces[i]!=='lo') {
res = ipaddrs[i];
}
break;
}
return res;
}
body {
padding: 10px;
font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
}
a {
color: #00B7FF;
}
div.inline{
float: left;
padding: 2px 5px 2px 0px;
}
.master_nodes{
cursor: pointer;
}
.slave_table{
border-collapse: collapse;
}
.slave_table th,
.slave_table td
{
border: 1px solid gray;
padding: 3px 10px;
}
.slave_table .state{
text-align: center;
}
input[type=checkbox], input[type=radio] {
width: 18px;
height: 18px;
vertical-align: middle;
position: relative;
bottom: 1px;
}
// libs
const url = require('url');
const express = require('express');
const fs = require('fs');
const path = require('path');
// more libs
const router = express.Router();
const log = console.log;
const rclnodejs = require('rclnodejs');
let ros2node = {};
rclnodejs.init().then(() => {
const mac = get_my_mac();
ros2node = rclnodejs.createNode('_nodejs_client_'+mac);
rclnodejs.spin(ros2node);
log('rclnodejs initialized');
});
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index');
});
const { execSync } = require('child_process');
router.get('/api/nodelist', function(req, res, next) {
// shell command
const stdout = execSync('ros2 node list');
const uri = url.parse(req.url).pathname;
res.send(stdout);
});
router.post('/api/*', function(req, res, next) {
const master = req.body.master;
const targets = req.body.targets;
const cmd = req.body.cmd;
// handle errors
if ((master==='')||(master==='-')) {
res.send("Invalid master node name");
return;
}
const client = ros2node.createClient('elphel_interfaces/srv/StrReqStrRes', master+'/cmd');
const request = {
request: [
'<document>',
'<targets>'+targets+'</targets>',
'<cmd>'+cmd+'</cmd>',
'</document>'].join('')
};
console.log(`Sending: ${typeof request}`, request);
client.sendRequest(request, (response) => {
console.log(`Result: ${typeof response}`, response);
//rclnodejs.shutdown();
res.send(response.response);
});
//rclnodejs.spin(node);
});
module.exports = router;
function get_my_mac(last_three_octets=true){
let tmp_mac = "000000000000";
let dir = "/sys/class/net/";
fs.readdirSync(dir).forEach(file => {
//log(file);
let p = /^(eth|enp|wlp)/gi;
let a = p.test(file);
if(a){
tmp_mac = fs.readFileSync(path.join(dir,file,'address'),'utf-8').trim();
tmp_mac = tmp_mac.replace(/:/g,'');
}
//log(a);
});
if (last_three_octets) {
tmp_mac = tmp_mac.slice(-6);
}
return tmp_mac;
}
var express = require('express');
var router = express.Router();
/* GET users listing. */
router.get('/', function(req, res, next) {
res.send('respond with a resource');
});
module.exports = router;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment