luci-mod-status: add WPS control for wifi info

Add a way to trigger and get the WPS Push Button status from the webui if supported.

Fixes: #1072

Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
This commit is contained in:
Ansuel Smith 2020-10-10 03:45:06 +02:00
parent 095309cf02
commit 6cf849bcf6
No known key found for this signature in database
GPG key ID: AC001D09ADBFEAD7
2 changed files with 164 additions and 92 deletions

View file

@ -2,16 +2,83 @@
'require baseclass'; 'require baseclass';
'require dom'; 'require dom';
'require network'; 'require network';
'require uci';
'require fs';
'require rpc'; 'require rpc';
var callSessionAccess = rpc.declare({ return baseclass.extend({
title: _('Wireless'),
WPSTranslateTbl: {
Disabled: _('Disabled'),
Active: _('Active'),
'Timed-out': _('Timed-out'),
Overlap: _('Overlap'),
Unknown: _('Unknown')
},
callSessionAccess: rpc.declare({
object: 'session', object: 'session',
method: 'access', method: 'access',
params: [ 'scope', 'object', 'function' ], params: [ 'scope', 'object', 'function' ],
expect: { 'access': false } expect: { 'access': false }
}); }),
function renderbox(radio, networks) { wifirate: function(rt) {
var s = '%.1f\xa0%s, %d\xa0%s'.format(rt.rate / 1000, _('Mbit/s'), rt.mhz, _('MHz')),
ht = rt.ht, vht = rt.vht,
mhz = rt.mhz, nss = rt.nss,
mcs = rt.mcs, sgi = rt.short_gi;
if (ht || vht) {
if (vht) s += ', VHT-MCS\xa0%d'.format(mcs);
if (nss) s += ', VHT-NSS\xa0%d'.format(nss);
if (ht) s += ', MCS\xa0%s'.format(mcs);
if (sgi) s += ', ' + _('Short GI').replace(/ /g, '\xa0');
}
return s;
},
handleDelClient: function(wifinet, mac, ev) {
dom.parent(ev.currentTarget, '.tr').style.opacity = 0.5;
ev.currentTarget.classList.add('spinning');
ev.currentTarget.disabled = true;
ev.currentTarget.blur();
wifinet.disconnectClient(mac, true, 5, 60000);
},
handleGetWPSStatus: function(wifinet) {
return rpc.declare({
object: 'hostapd.%s'.format(wifinet),
method: 'wps_status',
})()
},
handleCallWPS: function(wifinet, ev) {
ev.currentTarget.classList.add('spinning');
ev.currentTarget.disabled = true;
ev.currentTarget.blur();
return rpc.declare({
object: 'hostapd.%s'.format(wifinet),
method: 'wps_start',
})();
},
handleCancelWPS: function(wifinet, ev) {
ev.currentTarget.classList.add('spinning');
ev.currentTarget.disabled = true;
ev.currentTarget.blur();
return rpc.declare({
object: 'hostapd.%s'.format(wifinet),
method: 'wps_cancel',
})();
},
renderbox: function(radio, networks) {
var chan = null, var chan = null,
freq = null, freq = null,
rate = null, rate = null,
@ -36,6 +103,22 @@ function renderbox(radio, networks) {
else else
icon = L.resource('icons/signal-75-100.png'); icon = L.resource('icons/signal-75-100.png');
var WPS_button;
if (this.isWPSEnabled[net.sid]) {
if (net.wps_status == 'Active') {
WPS_button = E('button', {
'class' : 'cbi-button cbi-button-remove',
'click': L.bind(this.handleCancelWPS, this, net.getIfname()),
}, [ _('Stop WPS') ])
} else {
WPS_button = E('button', {
'class' : 'cbi-button cbi-button-apply',
'click': L.bind(this.handleCallWPS, this, net.getIfname()),
}, [ _('Start WPS') ])
}
}
var badge = renderBadge( var badge = renderBadge(
icon, icon,
'%s: %d dBm / %s: %d%%'.format(_('Signal'), net.getSignal(), _('Quality'), quality), '%s: %d dBm / %s: %d%%'.format(_('Signal'), net.getSignal(), _('Quality'), quality),
@ -44,7 +127,10 @@ function renderbox(radio, networks) {
_('BSSID'), is_assoc ? (net.getActiveBSSID() || '-') : null, _('BSSID'), is_assoc ? (net.getActiveBSSID() || '-') : null,
_('Encryption'), is_assoc ? net.getActiveEncryption() : null, _('Encryption'), is_assoc ? net.getActiveEncryption() : null,
_('Associations'), is_assoc ? (net.assoclist.length || '-') : null, _('Associations'), is_assoc ? (net.assoclist.length || '-') : null,
null, is_assoc ? null : E('em', net.isDisabled() ? _('Wireless is disabled') : _('Wireless is not associated'))); null, is_assoc ? null : E('em', net.isDisabled() ? _('Wireless is disabled') : _('Wireless is not associated')),
_('WPS status'), this.WPSTranslateTbl[net.wps_status],
'', WPS_button
);
badges.push(badge); badges.push(badge);
@ -60,60 +146,46 @@ function renderbox(radio, networks) {
L.itemlist(E('span'), [ L.itemlist(E('span'), [
_('Type'), radio.getI18n().replace(/^Generic | Wireless Controller .+$/g, ''), _('Type'), radio.getI18n().replace(/^Generic | Wireless Controller .+$/g, ''),
_('Channel'), chan ? '%d (%.3f %s)'.format(chan, freq, _('GHz')) : '-', _('Channel'), chan ? '%d (%.3f %s)'.format(chan, freq, _('GHz')) : '-',
_('Bitrate'), rate ? '%d %s'.format(rate, _('Mbit/s')) : '-' _('Bitrate'), rate ? '%d %s'.format(rate, _('Mbit/s')) : '-',
]), ]),
E('div', {}, badges) E('div', {}, badges)
]) ])
]); ]);
}
function wifirate(rt) {
var s = '%.1f\xa0%s, %d\xa0%s'.format(rt.rate / 1000, _('Mbit/s'), rt.mhz, _('MHz')),
ht = rt.ht, vht = rt.vht,
mhz = rt.mhz, nss = rt.nss,
mcs = rt.mcs, sgi = rt.short_gi;
if (ht || vht) {
if (vht) s += ', VHT-MCS\xa0%d'.format(mcs);
if (nss) s += ', VHT-NSS\xa0%d'.format(nss);
if (ht) s += ', MCS\xa0%s'.format(mcs);
if (sgi) s += ', ' + _('Short GI').replace(/ /g, '\xa0');
}
return s;
}
return baseclass.extend({
title: _('Wireless'),
handleDelClient: function(wifinet, mac, ev) {
dom.parent(ev.currentTarget, '.tr').style.opacity = 0.5;
ev.currentTarget.classList.add('spinning');
ev.currentTarget.disabled = true;
ev.currentTarget.blur();
wifinet.disconnectClient(mac, true, 5, 60000);
}, },
isWPSEnabled: {},
load: function() { load: function() {
return Promise.all([ return Promise.all([
network.getWifiDevices(), network.getWifiDevices(),
network.getWifiNetworks(), network.getWifiNetworks(),
network.getHostHints(), network.getHostHints(),
callSessionAccess('access-group', 'luci-mod-status-index-wifi', 'read'), this.callSessionAccess('access-group', 'luci-mod-status-index-wifi', 'read'),
callSessionAccess('access-group', 'luci-mod-status-index-wifi', 'write') this.callSessionAccess('access-group', 'luci-mod-status-index-wifi', 'write'),
]).then(function(radios_networks_hints) { uci.load('wireless')
var tasks = []; ]).then(L.bind(function(data) {
var tasks = [],
radios_networks_hints = data[1],
hasWPS = L.hasSystemFeature('hostapd', 'wps');
for (var i = 0; i < radios_networks_hints[1].length; i++) for (var i = 0; i < radios_networks_hints.length; i++) {
tasks.push(L.resolveDefault(radios_networks_hints[1][i].getAssocList(), []).then(L.bind(function(net, list) { tasks.push(L.resolveDefault(radios_networks_hints[i].getAssocList(), []).then(L.bind(function(net, list) {
net.assoclist = list.sort(function(a, b) { return a.mac > b.mac }); net.assoclist = list.sort(function(a, b) { return a.mac > b.mac });
}, this, radios_networks_hints[1][i]))); }, this, radios_networks_hints[i])));
if (hasWPS && uci.get('wireless', radios_networks_hints[i].sid, 'wps_pushbutton') == '1') {
this.isWPSEnabled[radios_networks_hints[i].sid] = true;
tasks.push(L.resolveDefault(this.handleGetWPSStatus(radios_networks_hints[i].getIfname()), null)
.then(L.bind(function(net, data) {
net.wps_status = data ? data.pbc_status : _('No Data');
}, this, radios_networks_hints[i])));
}
}
return Promise.all(tasks).then(function() { return Promise.all(tasks).then(function() {
return radios_networks_hints; return data;
});
}); });
}, this));
}, },
render: function(data) { render: function(data) {
@ -127,7 +199,7 @@ return baseclass.extend({
var table = E('div', { 'class': 'network-status-table' }); var table = E('div', { 'class': 'network-status-table' });
for (var i = 0; i < radios.sort(function(a, b) { a.getName() > b.getName() }).length; i++) for (var i = 0; i < radios.sort(function(a, b) { a.getName() > b.getName() }).length; i++)
table.appendChild(renderbox(radios[i], table.appendChild(this.renderbox(radios[i],
networks.filter(function(net) { return net.getWifiDeviceName() == radios[i].getName() }))); networks.filter(function(net) { return net.getWifiDeviceName() == radios[i].getName() })));
if (!table.lastElementChild) if (!table.lastElementChild)
@ -215,9 +287,9 @@ return baseclass.extend({
]) ])
]), ]),
E('span', {}, [ E('span', {}, [
E('span', wifirate(bss.rx)), E('span', this.wifirate(bss.rx)),
E('br'), E('br'),
E('span', wifirate(bss.tx)) E('span', this.wifirate(bss.tx))
]) ])
]; ];

View file

@ -125,7 +125,7 @@
}, },
"write": { "write": {
"ubus": { "ubus": {
"hostapd.*": [ "del_client" ] "hostapd.*": [ "del_client", "wps_start", "wps_cancel", "wps_status" ]
} }
} }
} }