3 |
4 | based on https://forum.archive.openwrt.org/viewtopic.php?id=58715
5 | -%>
6 |
7 | <%+header%>
8 |
9 |
10 |
11 |
12 |
13 |
14 | <%+footer%>
15 |
--------------------------------------------------------------------------------
/luci-app-basicstation/files/usr/share/rpcd/acl.d/luci-app-basicstation.json:
--------------------------------------------------------------------------------
1 | {
2 | "luci-app-basicstation": {
3 | "description": "Grant UCI access for luci-app-basicstation",
4 | "read": {
5 | "uci": [ "station" ]
6 | },
7 | "write": {
8 | "uci": [ "station" ]
9 | }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/luci-app-pkg-fwd/Makefile:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (C) 2017 Xue Liu
3 | #
4 | # This is free software, licensed under the GNU General Public License v2.
5 |
6 | include $(TOPDIR)/rules.mk
7 |
8 | PKG_NAME:=luci-app-pkt-fwd
9 | PKG_VERSION:=1.0
10 | PKG_RELEASE:=1
11 |
12 | PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
13 |
14 | include $(INCLUDE_DIR)/package.mk
15 |
16 | define Package/luci-app-pkt-fwd
17 | SECTION:=luci
18 | CATEGORY:=LuCI
19 | SUBMENU:=3. Applications
20 | TITLE:=Semtech LoRa Packet Forward Configuration Interface
21 | PKGARCH:=all
22 | DEPENDS:=+lora-packet-forwarder +luci-compat
23 | endef
24 |
25 | define Build/Compile
26 | endef
27 |
28 | define Package/luci-app-pkt-fwd/install
29 | $(INSTALL_DIR) $(1)/
30 | $(CP) ./files/* $(1)/
31 | endef
32 |
33 | $(eval $(call BuildPackage,luci-app-pkt-fwd))
34 |
--------------------------------------------------------------------------------
/luci-app-pkg-fwd/files/usr/lib/lua/luci/controller/lora/lora.lua:
--------------------------------------------------------------------------------
1 |
2 | module("luci.controller.lora.lora",package.seeall)
3 |
4 | function index()
5 | entry({"admin","network","lora"}, cbi("lora/lora_gateway"),_("LoRa Gateway"),99).index=true
6 | end
7 |
--------------------------------------------------------------------------------
/luci-app-pkg-fwd/files/usr/lib/lua/luci/model/cbi/lora/lora_gateway.lua:
--------------------------------------------------------------------------------
1 |
2 | m=Map("lora-global",translate("LoRa Gateway"),translate("Here you can configure the LoRa gateway and pakcet forwarder"))
3 |
4 | --
5 | -- LoRa Gateway config for gateway_conf
6 | --
7 | gateway=m:section(TypedSection,"gateway","Gateway Parameters")
8 | gateway.addremove=false
9 | gateway.anonymous=true
10 |
11 | gateway:tab("general", translate("General Settings"))
12 | gateway:tab("lbt", translate("LBT Settings"))
13 | gateway:tab("forward", translate("Forward Rules"))
14 | gateway:tab("gps", translate("GPS Settings"))
15 | gateway:tab("beacon", translate("Beacon Settings"))
16 |
17 | gateway:taboption("general", Value,"gateway_ID",translate("Gateway ID"))
18 |
19 | local ttn_addr = gateway:taboption("general", Value,"server_address",translate("Server Address"))
20 | ttn_addr:value("router.eu.thethings.network", "ttn-router-eu")
21 | ttn_addr:value("router.us.thethings.network", "ttn-router-us-west")
22 | ttn_addr:value("router.cn.thethings.network", "ttn-router-cn")
23 | ttn_addr:value("router.as.thethings.network", "ttn-router-asia-se")
24 | ttn_addr:value("router.as1.thethings.network", "ttn-router-asia-se-1")
25 | ttn_addr:value("router.as2.thethings.network", "ttn-router-asia-se-2")
26 | ttn_addr:value("router.kr.thethings.network", "ttn-router-kr")
27 | ttn_addr:value("router.jp.thethings.network", "ttn-router-jp")
28 | ttn_addr:value("thethings.meshed.com.au", "ttn-router-asia-se")
29 | ttn_addr:value("as923.thethings.meshed.com.au", "meshed-router")
30 | ttn_addr:value("ttn.opennetworkinfrastructure.org", "switch-router")
31 |
32 | gateway:taboption("general", Value,"serv_port_up",translate("Server Port (Up)"))
33 | gateway:taboption("general", Value,"serv_port_down",translate("Server Port (Down)"))
34 | gateway:taboption("general", Value,"keepalive_interval",translate("Keep Alive Interval"))
35 | gateway:taboption("general", Value,"push_timeout_ms",translate("Push Timeout"))
36 |
37 | --
38 | -- forward_crc_valid
39 | --
40 | forward_crc_valid = gateway:taboption("forward", ListValue,"forward_crc_valid",translate("Forward When CRC Valid"))
41 | forward_crc_valid.optional = false
42 | forward_crc_valid.rmempty = false
43 | forward_crc_valid.default = true
44 | forward_crc_valid.datatype = "bool"
45 | forward_crc_valid:value(true, translate("True"))
46 | forward_crc_valid:value(false, translate("False"))
47 |
48 | --
49 | -- forward_crc_error
50 | --
51 | forward_crc_error = gateway:taboption("forward", ListValue,"forward_crc_error",translate("Forward When CRC Error"));
52 | forward_crc_error.optional = false;
53 | forward_crc_error.rmempty = false;
54 | forward_crc_error.default = false
55 | forward_crc_error.datatype = "bool"
56 | forward_crc_error:value(true, translate("True"))
57 | forward_crc_error:value(false, translate("False"))
58 |
59 | --
60 | -- forward_crc_disabled
61 | --
62 | forward_crc_disabled = gateway:taboption("forward", ListValue,"forward_crc_disabled",translate("Forward When CRC Disabled"))
63 | forward_crc_disabled.optional = false;
64 | forward_crc_disabled.rmempty = false;
65 | forward_crc_disabled.default = false
66 | forward_crc_disabled.datatype = "bool"
67 | forward_crc_disabled:value(true, translate("True"))
68 | forward_crc_disabled:value(false, translate("False"))
69 |
70 | --
71 | -- LBT Enable
72 | --
73 | lbt_enable = gateway:taboption("lbt", ListValue,"lbt_enable",translate("LBT Enable"))
74 | lbt_enable.optional = false;
75 | lbt_enable.rmempty = false;
76 | lbt_enable.default = false
77 | lbt_enable.datatype = "bool"
78 | lbt_enable:value(true, translate("True"))
79 | lbt_enable:value(false, translate("False"))
80 |
81 | --
82 | -- RSSI Target
83 | --
84 | lbt_rssi_target = gateway:taboption("lbt", Value,"rssi_target",translate("RSSI Target Value"))
85 | lbt_rssi_target.optional = true;
86 | lbt_rssi_target.rmempty = true;
87 | lbt_rssi_target.default = '-80'
88 | lbt_rssi_target.datatype = "float"
89 | lbt_rssi_target:depends("lbt_enable", "true")
90 |
91 | --
92 | -- sx127x RSSI Offset
93 | --
94 | sx127x_rssi_offset = gateway:taboption("lbt", Value,"sx127x_rssi_offset",translate("SX127x RSSI Offset"))
95 | sx127x_rssi_offset.optional = true;
96 | sx127x_rssi_offset.rmempty = true;
97 | sx127x_rssi_offset.default = '-4'
98 | sx127x_rssi_offset.datatype = "float"
99 | sx127x_rssi_offset:depends("lbt_enable", "true")
100 |
101 | --
102 | -- GPS Enable
103 | --
104 | gps_enable = gateway:taboption("gps", ListValue,"gps_enable",translate("GPS Enable"))
105 | gps_enable.optional = false;
106 | gps_enable.rmempty = false;
107 | gps_enable.default = false
108 | gps_enable.datatype = "bool"
109 | gps_enable:value(true, translate("True"))
110 | gps_enable:value(false, translate("False"))
111 |
112 | --
113 | -- TTY path for GPS
114 | --
115 | gps_tty_path = gateway:taboption("gps", Value,"gps_tty_path",translate("TTY path for GPS"))
116 | gps_tty_path.optional = true;
117 | gps_tty_path.rmempty = true;
118 | gps_tty_path.default = false
119 | gps_tty_path.datatype = "string"
120 | gps_tty_path:depends("gps_enable", "true")
121 |
122 | --
123 | -- GPS reference coordinates: latitude
124 | --
125 | gps_latitude = gateway:taboption("gps", Value,"ref_latitude",translate("GPS Reference Latitude"))
126 | gps_latitude.optional = true;
127 | gps_latitude.rmempty = true;
128 | gps_latitude.default = '1.0'
129 | gps_latitude.datatype = "float"
130 | gps_latitude:depends("gps_enable", "true")
131 |
132 | --
133 | -- GPS reference coordinates: longitude
134 | --
135 | gps_longitude = gateway:taboption("gps", Value,"ref_longitude",translate("GPS Reference Longitude"))
136 | gps_longitude.optional = true;
137 | gps_longitude.rmempty = true;
138 | gps_longitude.default = '1.0'
139 | gps_longitude.datatype = "float"
140 | gps_longitude:depends("gps_enable", "true")
141 |
142 | --
143 | -- GPS reference coordinates: altitude
144 | --
145 | gps_altitude = gateway:taboption("gps", Value,"ref_altitude",translate("GPS Reference Altitude"))
146 | gps_altitude.optional = true;
147 | gps_altitude.rmempty = true;
148 | gps_altitude.default = '1.0'
149 | gps_altitude.datatype = "float"
150 | gps_altitude:depends("gps_enable", "true")
151 |
152 | --
153 | -- Beacon enable
154 | --
155 | beacon_enable = gateway:taboption("beacon", ListValue,"beacon_enable",translate("Beacon Enable"))
156 | beacon_enable.optional = false;
157 | beacon_enable.rmempty = false;
158 | beacon_enable.default = false
159 | beacon_enable.datatype = "bool"
160 | beacon_enable:value(true, translate("True"))
161 | beacon_enable:value(false, translate("False"))
162 |
163 | --
164 | -- Beacon period
165 | --
166 | beacon_period = gateway:taboption("beacon", Value,"beacon_period",translate("Beacon Period"), "in second")
167 | beacon_period.optional = true;
168 | beacon_period.rmempty = true;
169 | beacon_period.default = '128'
170 | beacon_period.datatype = "uinteger"
171 | beacon_period:depends("beacon_enable", "true")
172 |
173 | --
174 | -- Beacon channel frequency
175 | --
176 | beacon_frequency = gateway:taboption("beacon", Value,"beacon_frequency",translate("Beacon Channel Frequency"), "in Hz")
177 | beacon_frequency.optional = true;
178 | beacon_frequency.rmempty = true;
179 | beacon_frequency.default = '869525000'
180 | beacon_frequency.datatype = "uinteger"
181 | beacon_frequency:depends("beacon_enable", "true")
182 |
183 | --
184 | -- Beacon channel datarate
185 | --
186 | beacon_datarate = gateway:taboption("beacon", Value,"beacon_datarate",translate("Beacon Channel Datarate"))
187 | beacon_datarate.optional = true;
188 | beacon_datarate.rmempty = true;
189 | beacon_datarate.default = '9'
190 | beacon_datarate.datatype = "uinteger"
191 | beacon_datarate:depends("beacon_enable", "true")
192 |
193 | --
194 | -- Beacon channel bandwidth
195 | --
196 | beacon_bandwidth = gateway:taboption("beacon", Value,"beacon_bandwidth",translate("Beacon Channel Bandwidth"), "in Hz")
197 | beacon_bandwidth.optional = true;
198 | beacon_bandwidth.rmempty = true;
199 | beacon_bandwidth.default = '125000'
200 | beacon_bandwidth.datatype = "uinteger"
201 | beacon_bandwidth:depends("beacon_enable", "true")
202 |
203 | --
204 | -- Beacon signal strength
205 | --
206 | beacon_power = gateway:taboption("beacon", Value,"beacon_power",translate("Beacon Signal Strength"), "in dBm")
207 | beacon_power.optional = true;
208 | beacon_power.rmempty = true;
209 | beacon_power.default = '14'
210 | beacon_power.datatype = "uinteger"
211 | beacon_power:depends("beacon_enable", "true")
212 |
213 | --
214 | -- Beacon info description
215 | --
216 | beacon_infodesc = gateway:taboption("beacon", Value,"beacon_infodesc",translate("Beacon Info Description"))
217 | beacon_infodesc.optional = true;
218 | beacon_infodesc.rmempty = true;
219 | beacon_infodesc.default = '0'
220 | beacon_infodesc.datatype = "uinteger"
221 | beacon_infodesc:depends("beacon_enable", "true")
222 |
223 | --
224 | -- SX1301 configuration for SX1301_conf
225 | --
226 | sx1301=m:section(TypedSection,"sx1301","SX1301 Parameters")
227 | sx1301.addremove=false
228 | sx1301.anonymous=true
229 |
230 | lorawan_pb = sx1301:option(ListValue,"lorawan_public",translate("LoRaWAN is public"))
231 | lorawan_pb.optional = false;
232 | lorawan_pb.rmempty = false;
233 | lorawan_pb.default = false
234 | lorawan_pb.datatype = "bool"
235 | lorawan_pb:value(true, translate("True"))
236 | lorawan_pb:value(false, translate("False"))
237 |
238 | clkscr = sx1301:option(ListValue,"clksrc",translate("Clock Source"), "radio_1 provides clock to concentrator for most devices except MultiTech. For MultiTech set to 0.")
239 | clkscr.optional = false;
240 | clkscr.rmempty = false;
241 | clkscr.datatype = "integer"
242 | clkscr:value(1, translate("From radio_1"))
243 | clkscr:value(0, translate("From radio_0"))
244 |
245 | antenna_gain = sx1301:option(Value,"antenna_gain",translate("Antenne Gain"), "Antenna Gain, in dBi")
246 | antenna_gain.optional = false;
247 | antenna_gain.rmempty = false;
248 |
249 | enable_reset_pin = sx1301:option(Flag,"enable_reset_pin",translate("Enable Reset Pin ?"), "Some SX1301 boards like iC880A require to reset every time after restart")
250 | enable_reset_pin.optional = false;
251 | enable_reset_pin.rmempty = false;
252 | enable_reset_pin.disabled = 0
253 | enable_reset_pin.enable = 1
254 |
255 | reset_pin = sx1301:option(Value,"reset_pin",translate("Reset Pin"), "Reset SX1301 board")
256 | reset_pin.optional = false;
257 | reset_pin.rmempty = true;
258 | reset_pin.default = 21
259 | reset_pin:depends("enable_reset_pin", "1")
260 |
261 | --
262 | -- Radio Parameters
263 | --
264 | radio=m:section(TypedSection,"radio","Radio Parameters")
265 | radio.addremove=false
266 | radio.anonymous=false
267 |
268 | --
269 | -- Radio enable
270 | --
271 | enable = radio:option(ListValue,"enable",translate("Enable"))
272 | enable.optional = false;
273 | enable.rmempty = false;
274 | enable.default = false
275 | enable.datatype = "bool"
276 | enable:value(true, translate("True"))
277 | enable:value(false, translate("False"))
278 |
279 | --
280 | -- Radio RF frontend
281 | --
282 | type = radio:option(ListValue,"type",translate("Type"))
283 | type.optional = false;
284 | type.rmempty = false;
285 | type.datatype = "string"
286 | type:value("SX1257", translate("SX1257"))
287 | type:value("SX1255", translate("SX1255"))
288 |
289 | --
290 | -- Radio Frequency
291 | --
292 | freq = radio:option(Value,"freq",translate("Frequency"), "Hz")
293 | freq.optional = false;
294 | freq.rmempty = false;
295 |
296 | --
297 | -- RSSI offset
298 | --
299 | rssi_offset = radio:option(Value,"rssi_offset",translate("RSSI Offset"), "dB")
300 | rssi_offset.optional = false;
301 | rssi_offset.rmempty = false;
302 |
303 | --
304 | -- Tx Enable
305 | --
306 | tx_enable = radio:option(ListValue,"tx_enable",translate("Tx Enable"))
307 | tx_enable.optional = false;
308 | tx_enable.rmempty = false;
309 | tx_enable.default = false
310 | tx_enable.datatype = "bool"
311 | tx_enable:value(true, translate("True"))
312 | tx_enable:value(false, translate("False"))
313 |
314 | tx_notch_freq= radio:option(Value,"tx_notch_freq",translate("Tx Notch Frequency"), "[126..250] KHz")
315 | tx_notch_freq.optional = false;
316 | tx_notch_freq.rmempty = true;
317 | tx_notch_freq:depends("tx_enable", "true")
318 |
319 | tx_freq_min= radio:option(Value,"tx_freq_min",translate("Minimum Tx Frequency"), "Hz")
320 | tx_freq_min.optional = false;
321 | tx_freq_min.rmempty = true;
322 | tx_freq_min:depends("tx_enable", "true")
323 |
324 | tx_freq_max= radio:option(Value,"tx_freq_max",translate("Maximum Tx Frequency"), "Hz")
325 | tx_freq_max.optional = false;
326 | tx_freq_max.rmempty = true;
327 | tx_freq_max:depends("tx_enable", "true")
328 |
329 | --
330 | -- chann
331 | --
332 | chan=m:section(TypedSection,"chan","Channel Parameters")
333 | chan.addremove=true
334 | chan.anonymous=false
335 |
336 | description = chan:option(Value ,"desc",translate("Description"))
337 | enable.optional = false;
338 | enable.rmempty = false;
339 |
340 | enable = chan:option(ListValue,"enable",translate("Enable"))
341 | enable.optional = false;
342 | enable.rmempty = false;
343 | enable.default = true
344 | enable.datatype = "bool"
345 | enable:value(true, translate("True"))
346 | enable:value(false, translate("False"))
347 |
348 | radio = chan:option(Value,"radio",translate("Radio"))
349 | radio.optional = false;
350 | radio.rmempty = false;
351 |
352 | interface = chan:option(Value,"if",translate("IF"), "Hz")
353 | interface.optional = false;
354 | interface.rmempty = false;
355 |
356 | bandwidth = chan:option(Value,"bandwidth",translate("Bandwidth"))
357 | bandwidth.optional = true;
358 | bandwidth.rmempty = false;
359 |
360 | spread_factor = chan:option(Value,"spread_factor",translate("Spread Factor"))
361 | spread_factor.optional = true;
362 | spread_factor.rmempty =false;
363 |
364 | datarate = chan:option(Value,"datarate",translate("Datarate"))
365 | datarate.optional = true;
366 | datarate.rmempty = false;
367 |
368 | --
369 | -- TX gain tables
370 | --
371 | lut=m:section(TypedSection,"lut","Tx LUT Parameters")
372 | lut.addremove=true
373 | lut.anonymous=false
374 |
375 | pa_gain = lut:option(Value,"pa_gain",translate("PA Gain"))
376 | pa_gain.optional = false;
377 | pa_gain.rmempty = false;
378 |
379 | mix_gain = lut:option(Value,"mix_gain",translate("Minimum Gain"))
380 | mix_gain.optional = false;
381 | mix_gain.rmempty = false;
382 |
383 | rf_power = lut:option(Value,"rf_power",translate("RF Power"))
384 | rf_power.optional = false;
385 | rf_power.rmempty = false;
386 |
387 | dig_gain = lut:option(Value,"dig_gain",translate("Dig Gain"))
388 | dig_gain.optional = false;
389 | dig_gain.rmempty = false;
390 |
391 | m.on_after_commit = function(self)
392 |
393 | io.popen("/etc/init.d/lora_pkt_fwd restart")
394 | end
395 |
396 | return m
397 |
398 |
--------------------------------------------------------------------------------
/luci-lora-gateway.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xueliu/lora-feed/7bf1be1efe717a1b9abf13886f4a98466a4137c2/luci-lora-gateway.png
--------------------------------------------------------------------------------