Skip to content

Commit

Permalink
luci-app-basicstation: initial check-in
Browse files Browse the repository at this point in the history
LuCi support for Basicstation

Signed-off-by: Marcus Schref <mschref@web.de>
  • Loading branch information
mars642 committed Aug 18, 2022
1 parent f34839c commit 3d18c74
Show file tree
Hide file tree
Showing 6 changed files with 381 additions and 0 deletions.
22 changes: 22 additions & 0 deletions applications/luci-app-basicstation/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#
# Copyright (C) 2022 TDT AG <development@tdt.de>
#
# This is free software, licensed under the Apache License Version 2.0.
# See https://www.apache.org/licenses/LICENSE-2.0 for more information.
#

include $(TOPDIR)/rules.mk

PKG_NAME:=luci-app-basicstation
PKG_VERSION:=2.0.6
PKG_RELEASE:=1
PKG_LICENSE:=Apache-2.0
PKG_MAINTAINER:=Marcus Schref <mschref@tdt.de>

LUCI_TITLE:=LuCI Support for basicstation
LUCI_DEPENDS:=+basicstation
LUCI_PKGARCH:=all

include ../../luci.mk

# call BuildPackage - OpenWrt buildroot signature
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
'use strict';
'require form';
'require view';
'require uci';

return view.extend({
load: function() {
return Promise.all([
uci.load('basicstation')
]);
},

render: function(data) {
var m, s, o, options;

/* Advanced Settings */
m = new form.Map('basicstation', _('Advanced Settings'));

/* RF Configuration */
s = m.section(form.GridSection, 'rfconf', _('RF Configuration'));
s.addremove = true;
s.anonymous = false;
s.nodescriptions = true;

o = s.option(form.ListValue, 'type', _('Type'),
_('RF front end type'));
o.value('SX1250');
o.default = 'SX1250';

o = s.option(form.Flag, 'txEnable', _('Tx enable'),
_('Enable transmission capabilities'));
o.default = 'false';

o = s.option(form.Value, 'freq', _('Frequency'),
_('Frequency in Hz'));
o.datatype = 'uinteger';

o = s.option(form.Value, 'antennaGain', _('Antenna Gain'),
_('Antenna gain in dBi'));
o.datatype = 'uinteger';

o = s.option(form.Value, 'rssiOffset', _('RSSI Offset'),
_('RSSI offset in dBm'));
o.datatype = 'float';

o = s.option(form.ListValue, 'useRssiTcomp', _('RSSI Tcomp'),
_('RSSI Tcomp object to be used for this RF configuration'));
options = uci.sections('basicstation', 'rssitcomp')
for (var i = 0; i < options.length; i++) {
var value = options[i]['.name'];
o.value(value);
}
o.default = 'std';

/* RSSI Tcomp */
s = m.section(form.GridSection, 'rssitcomp', _('RSSI Tcomp'));
s.addremove = true;
s.anonymous = false;
s.nodescripitons = true;

o = s.option(form.Value, 'coeff_a', _('Coeff A'));
o.datatype = 'float';

o = s.option(form.Value, 'coeff_b', _('Coeff B'));
o.datatype = 'float';

o = s.option(form.Value, 'coeff_c', _('Coeff C'));
o.datatype = 'float';

o = s.option(form.Value, 'coeff_d', _('Coeff D'));
o.datatype = 'float';

o = s.option(form.Value, 'coeff_e', _('Coeff E'));
o.datatype = 'float';

/* TX Gain Lookup Table */
s = m.section(form.GridSection, 'txlut', _('TX Gain Lookup Table'));
s.addremove = true;
s.anonymous = true;
s.nodescriptions = true;

o = s.option(form.Value, 'rfPower', _('RF Power'),
_('RF output power target in dBm'));
o.datatype = 'uinteger';

o = s.option(form.Flag, 'paGain', _('PA Enable'),
_('Power amplifier enabled'));
o.default = false;

o = s.option(form.Value, 'pwrIdx', _('Power Index'),
_('Possible gain settings from 0 (min. gain) to 22 (max. gain)'));
o.datatype = 'range(0,22)';

o = s.option(form.DynamicList, 'usedBy', _('Used By'),
_('RF configurations that use this tx gain object'));
options = uci.sections('basicstation', 'rfconf');
for (var i = 0; i < options.length; i++) {
var value = options[i]['.name'];
o.value(value);
}

return m.render();
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
'use strict';
'require form';
'require view';
'require uci';
'require fs';
'require network';
'require tools.widgets as widgets';

return view.extend({
load: function() {
return Promise.all([
uci.load('basicstation')
]);
},

render: function(data) {
var m, s, o;

/* General Settings */
m = new form.Map('basicstation', _('General Settings'));

/* Station Identity */
s = m.section(form.NamedSection, 'station', 'station',
_('Station Identity'));

o = s.option(widgets.DeviceSelect, 'idGenIf',
_('Interface for station ID generation'),
_('Station ID is derived from the MAC address of the choosen interface'));
o.filter = function(section_id, value) {
var dev = this.devices.filter(function(dev) { return dev.getName() == value })[0];
return (dev && dev.getMAC() != null && dev.getMAC() != '00:00:00:00:00:00');
}
o.nobridges = true;
o.novirtual = true;
o.noaliases = true;
o.default = 'eth0';

o.write = function(sid, value) {
var path = "/sys/class/net/" + value + "/address";
uci.set('basicstation', sid, 'idGenIf', value);
uci.set('basicstation', sid, 'routerid', path);
}

o = s.option(form.Value, 'stationid', _('Station ID'),
_('Click save and apply to generate station ID'));
o.readonly = true;

/* Authentication */
s = m.section(form.NamedSection, 'auth', 'auth',
_('Authentication'));

o = s.option(form.ListValue, 'cred', _('Credentials'),
_('Credentials for LNS (TC) or CUPS (CUPS)'));
o.value('tc', _('TC'));
o.value('cups', _('CUPS'));
o.default = 'tc';

o = s.option(form.ListValue, 'mode', _('Authentication mode'),
_('Authentication mode for server connection'));
o.value('no', _('No Authentication'));
o.value('server', _('TLS Server Authentication'));
o.value('serverAndClient', _('TLS Server and Client Authentication'));
o.value('serverAndClientToken', _('TLS Server Authentication and Client Token'));
o.default = 'no';

o = s.option(form.Value, 'addr', _('Server address'));
o.optional = false;
o.rmempty = false;
o.placeholder = 'eu1.cloud.thethings.network';

o = s.option(form.Value, 'port', _('Port'));
o.optional = false;
o.rmempty = false;
o.datatype = 'uinteger';
o.placeholder = '8887';

o = s.option(form.Value, 'token', _('Authorization token'));
o.optional = false;
o.rmempty = false;
o.depends({ mode: 'serverAndClientToken' });

o = s.option(form.Value, 'key', _('Private station key'));
o.optional = false;
o.rmempty = false;
o.depends({ mode: 'serverAndClient' });

o = s.option(form.FileUpload, 'crt', _('Private station certificate'));
o.optional = false;
o.rmempty = false;
o.depends({ mode: "serverAndClient" });

o = s.option(form.FileUpload, 'trust', _('CA certificate'));
o.optional = false;
o.rmempty = false;
o.depends({ mode: "no", "!reverse": true });

/* Radio Configuration */
s = m.section(form.NamedSection, 'sx130x', 'sx130x',
_('Radio Configuration'));

o = s.option(form.ListValue, 'comif', _('Communication interface'),
_('Currently only USB devices are supported'));
o.value('usb', 'USB');
o.default = 'usb';

o = s.option(form.Value, 'devpath', _('Device path'),
_('Device path of the LoRaWAN concentrator card'));
o.optional = false;
o.rmempty = false;
o.placeholder = '/dev/ttyACM0';

o = s.option(form.Flag, 'pps', _('PPS'),
_('PPS (pulse per second) provided by GPS device or other source'));
o.default = false

o = s.option(form.Flag, 'public', _('Public network'),
_('Public or private LoRaWAN network'));
o.default = true;

o = s.option(form.ListValue, 'clksrc', _('Clock source'),
_('Radio to provide clock to Basicstation'));
o.value('0', 'Radio 0');
o.value('1', 'Radio 1');
o.default = '0';

var options = uci.sections('basicstation', 'rfconf');

o = s.option(form.ListValue, 'radio0', _('Radio 0'),
_('RF configuration for Radio 0'));
for (var i = 0; i < options.length; i++) {
var value = options[i]['.name'];
o.value(value);
}
o.default = 'rfconf0';

o = s.option(form.ListValue, 'radio1', _('Radio 1'),
_('RF configuration for Radio 1'));
for (var i = 0; i < options.length; i++) {
var value = options[i]['.name'];
o.value(value);
}
o.default = 'rfconf1';

/* Logging */
s = m.section(form.NamedSection, 'station','station',
_('Logging'));

o = s.option(form.ListValue, 'logLevel', _('Level'),
_('Level to which messages are to be logged'));
o.value('XDEBUG', 'xdebug');
o.value('DEBUG', 'debug');
o.value('VERBOSE', 'verbose');
o.value('INFO', 'info');
o.value('NOTICE', 'notice');
o.value('WARNING', 'warning');
o.value('ERROR', 'error');
o.value('CRITICAL', 'critical');
o.default = 'DEBUG';

o = s.option(form.Value, 'logSize', _('Size'),
_('Maximum size of log file in MB'));
o.value('1');
o.value('2');
o.value('3');
o.value('4');
o.default = '1';
o.datatype = 'range(1,10)';

o = s.option(form.Value, 'logRotate', _('Rotate'),
_('Number of old log files to be kept'));
o.value('1');
o.value('2');
o.value('3');
o.value('4');
o.default = '1';
o.datatype = 'range(1, 10)';

return m.render();
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
'use strict';
'require fs';
'require view';

return view.extend({
load: function() {
return L.resolveDefault(fs.read_direct('/tmp/basicstation/log'), '');
},

render: function(log) {
return E('div', { 'class': 'cbi-map', 'id': 'map' }, [
E('h2', _('Log Messages')),
E('div', { 'class': 'cbi-section' }, [
E('pre', [ log ])
]),
])
},

handleSaveApply: null,
handleSave: null,
handleReset: null
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"admin/network/basicstation": {
"title": "Basicstation",
"order": "600",
"action": {
"type": "firstchild"
},
"depends": {
"acl": [ "luci-app-basicstation" ]
}
},

"admin/network/basicstation/general": {
"title": "General Settings",
"order": 10,
"action": {
"type": "view",
"path": "basicstation/general"
}
},

"admin/network/basicstation/advanced": {
"title": "Advanced Settings",
"order": 20,
"action": {
"type": "view",
"path": "basicstation/advanced"
}
},

"admin/network/basicstation/log": {
"title": "Log Messages",
"order": 30,
"action": {
"type": "view",
"path": "basicstation/log"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"luci-app-basicstation": {
"description": "Grant UCI access for luci-app-basicstation",
"read": {
"file": {
"/tmp/basicstation/log": [ "read" ]
},
"uci": [ "basicstation" ]
},
"write": {
"uci": [ "basicstation" ]
}
}
}

0 comments on commit 3d18c74

Please sign in to comment.